rvm  1.11
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
rmath.cc
Go to the documentation of this file.
1 #include "config.h"
2 
3 #include "error.h"
4 #include "rmath.h"
5 
6 /** A small set of numeric limits routines, since gcc prior to 3.x doesn't
7  * have numeric_limits */
8 
9 // ---------------------------------------------------------------------------
10 
11 /** Find the maximum limit for a type, equivalent to
12  * std::numeric_limits<T>.max() for systems that don't have the limits c++
13  * header file. */
14 // template<typename T>
15 // static const T max_limit()
16 // {
17 // T tmp = 0;
18 // static T max = 0;
19 // static bool found = false;
20 //
21 // if (found) {
22 // return(max);
23 // }
24 //
25 // tmp = 1;
26 // max = 0;
27 // while (tmp > max) {
28 // max = tmp;
29 // try {
30 // tmp = (tmp * T(2)) + T(1);
31 // }
32 // catch(...) { }
33 // }
34 // found = true;
35 // return(max);
36 // }
37 
38 /** Find the maximum limit for a type, equivalent to
39  * std::numeric_limits<T>.min() for systems that don't have the limits c++
40  * header file.
41  */
42 // template<typename T>
43 // static const T min_limit()
44 // {
45 // T tmp = 0;
46 // static T min = 0;
47 // static bool found = false;
48 //
49 // if (found) {
50 // return(min);
51 // }
52 //
53 // tmp = -1;
54 // min = 0;
55 // while (tmp < min) {
56 // min = tmp;
57 // try {
58 // tmp = (tmp * T(2)) - T(1);
59 // }
60 // catch(...) { }
61 // }
62 //
63 // try {
64 // tmp = - max_limit<T>() - T(1);
65 // }
66 // catch(...) { }
67 // if (tmp < min) {
68 // min = tmp;
69 // }
70 //
71 // found = true;
72 // return(min);
73 // }
74 
75 /** Return the largest possible number that a float may hold. */
76 #ifdef OSX_WORKAROUND
77 template<>
78 const float max_limit<float>()
79 {
80  return(FLT_MAX);
81 }
82 #endif
83 
84 /** Return the smallest positive number that a float may hold.
85  *
86  * Caveat: This is in contrast to other types, where min_limit<T>() will return
87  * either 0 or the largest possible negative number that the type may hold. If
88  * you are looking for the largest possible negative number for any given type,
89  * use lowest_value<T>() instead.
90  */
91 #ifdef OSX_WORKAROUND
92 template<>
93 const float min_limit<float>()
94 {
95  return(FLT_MIN);
96 }
97 #endif
98 
99 /** Return the largest possible number that a double may hold. */
100 #ifdef OSX_WORKAROUND
101 template<>
102 const double max_limit<double>()
103 {
104  return(DBL_MAX);
105 }
106 #endif
107 
108 /** Return the smallest positive number that a double may hold.
109  *
110  * Caveat: This is in contrast to other types, where min_limit<T>() will return
111  * either 0 or the largest possible negative number that the type may hold. If
112  * you are looking for the largest possible negative number for any given type,
113  * use lowest_value<T>() instead.
114  */
115 #ifdef OSX_WORKAROUND
116 template<>
117 const double min_limit<double>()
118 {
119  return(DBL_MIN);
120 }
121 #endif
122 
123 // ---------------------------------------------------------------------------
124 
125 /** Return the max_limit of a variable.
126  *
127  * This is handy to have because it means
128  * that the author may change the type of a variable without having to track
129  * down all uses of max_limit or min_limit to change the type they measure.
130  */
131 // template<typename T>
132 // static const T max_limit(const T& a_arg)
133 // {
134 // T value;
135 //
136 // value = max_limit<T>();
137 //
138 // return(value);
139 // }
140 
141 /** Return the min_limit of a variable.
142  *
143  * This is handy to have because it means
144  * that the author may change the type of a variable without having to track
145  * down all uses of max_limit or min_limit to change the type they measure.
146  */
147 // template<typename T>
148 // static const T min_limit(const T& a_arg)
149 // {
150 // T value;
151 //
152 // value = min_limit<T>();
153 //
154 // return(value);
155 // }
156 
157 // ---------------------------------------------------------------------------
158 
159 /** Return the maximum possible value a type may hold.
160  *
161  * This is just a convenience function to match lowest_value<T>(). All it does
162  * is return the value of max_limit<T>().
163  */
164 // template<typename T>
165 // static const T highest_value(void)
166 // {
167 // T value;
168 //
169 // value = max_limit<T>();
170 //
171 // return(value);
172 // }
173 
174 /** Return the maximum possible value of a variable. */
175 // template<typename T>
176 // static const T highest_value(const T& a_arg)
177 // {
178 // T value;
179 //
180 // value = highest_value<T>();
181 //
182 // return(value);
183 // }
184 
185 /** Return 0 for unsigned types, or the maximum negative value that the type
186  * may hold.
187  */
188 // template<typename T>
189 // static const T lowest_value(void)
190 // {
191 // T value;
192 //
193 // value = -max_limit<T>();
194 // if (value > min_limit<T>())
195 // value = min_limit<T>();
196 //
197 // return(value);
198 // }
199 
200 /** Return 0 for unsigned types, or the maximum negative value that a variable
201  * may hold.
202  */
203 // template<typename T>
204 // static const T lowest_value(const T& a_arg)
205 // {
206 // T value;
207 //
208 // value = lowest_value<T>();
209 //
210 // return(value);
211 // }
212 
213 // ---------------------------------------------------------------------------
214 
215 /** Return the absolute value of a numeric type
216  *
217  * Caveat: For some types, the maximum negative value is one larger than the
218  * maximum positive value: specifically char. Depending on the type and value,
219  * it may be impossible to return the absolute value. For such types under
220  * such circumstances an exception is thrown.
221  */
222 // template<typename T>
223 // T absolute(const T& a_num)
224 // {
225 // T num;
226 // std::string es;
227 //
228 // // std::cerr << "absolute(" << static_cast<long long>(a_num) << ") : BEGIN" << std::endl;
229 // num = a_num;
230 // if ((num < 0) && (num == min_limit<T>())) {
231 // TRY_nomem(es = "Absolute value is not containable by this type: ");
232 // if (is_char(num)) {
233 // TRY_nomem(es += estring(static_cast<int>(num)));
234 // }
235 // else {
236 // TRY_nomem(es += estring(num));
237 // }
238 // throw(ERROR(0,es));
239 // }
240 // if (num < 0) {
241 // num = -num;
242 // if (num < 0) {
243 // TRY_nomem(es = "Absolute value is still negative: ");
244 // if (is_char(num)) {
245 // TRY_nomem(es += estring(static_cast<int>(num)));
246 // }
247 // else {
248 // TRY_nomem(es += estring(num));
249 // }
250 // throw(INTERNAL_ERROR(0,es));
251 // }
252 // // else std::cerr << "absolute(" << static_cast<long long>(a_num) << ") >= 0" << std::endl;
253 // }
254 //
255 // // std::cerr << "absolute(" << static_cast<long long>(a_num) << ") = " << static_cast<long long>(num) << std::endl;
256 // // std::cerr << "absolute(" << static_cast<long long>(a_num) << ") : END" << std::endl;
257 // return(num);
258 // }
259 
260 // ---------------------------------------------------------------------------
261 
262 /** Safely manipulate numbers without worryiung about over/underflow error */
263 // template<typename T>
264 // class safe_num
265 // {
266 // public:
267 // /** C'tor */
268 // safe_num()
269 // {
270 // clear();
271 // }
272 //
273 // /** C'tor */
274 // safe_num(const T a_num)
275 // {
276 // clear();
277 // m_num = a_num;
278 // }
279 //
280 // /** C'tor */
281 // safe_num(const safe_num& a_class)
282 // {
283 // clear();
284 // m_num = a_class.value();
285 // }
286 //
287 // /** Clear the value */
288 // void clear(void)
289 // {
290 // m_num = static_cast<T>(0);
291 // }
292 //
293 // /** Return the value */
294 // const T value(void) const
295 // {
296 // return(m_num);
297 // }
298 //
299 // /** Assign a value */
300 // void assign(const T& a_arg)
301 // {
302 // m_num = a_arg;
303 // }
304 //
305 // /** Add a value */
306 // void add(const T& a_arg)
307 // {
308 // bool overflow = false;
309 // T num;
310 //
311 // if (a_arg < static_cast<T>(0)) {
312 // num = absolute(a_arg);
313 // subtract(num);
314 // return;
315 // }
316 //
317 // if (highest_value<T>() - a_arg < m_num)
318 // overflow = true;
319 //
320 // if (overflow) {
321 // estring es;
322 //
323 // es = "Addition overflow error detected: ";
324 // if (is_char(m_num))
325 // es += estring(static_cast<int>(m_num));
326 // else
327 // es += estring(m_num);
328 // es += " + ";
329 // if (is_char(a_arg))
330 // es += estring(static_cast<int>(a_arg));
331 // else
332 // es += estring(a_arg);
333 // throw(INTERNAL_ERROR(0,es));
334 // }
335 // m_num += a_arg;
336 // }
337 //
338 // /** Subtract a value */
339 // void subtract(const T& a_arg)
340 // {
341 // bool underflow = false;
342 // T num;
343 //
344 // if (a_arg < static_cast<T>(0)) {
345 // num = absolute(a_arg);
346 // add(num);
347 // return;
348 // }
349 //
350 // if (lowest_value<T>() < 0) {
351 // if (m_num < lowest_value<T>() + a_arg)
352 // underflow = true;
353 // }
354 // else {
355 // if (m_num - lowest_value<T>() < a_arg)
356 // underflow = true;
357 // }
358 //
359 // if (underflow) {
360 // estring es;
361 //
362 // es = "Subtraction underflow error detected: ";
363 // if (is_char(m_num))
364 // es += estring(static_cast<int>(m_num));
365 // else
366 // es += estring(m_num);
367 // es += " - ";
368 // if (is_char(a_arg))
369 // es += estring(static_cast<int>(a_arg));
370 // else
371 // es += estring(a_arg);
372 // throw(INTERNAL_ERROR(0,es));
373 // }
374 // m_num -= a_arg;
375 // }
376 //
377 // /** Multiply by a value */
378 // void multiply(const T& a_arg)
379 // {
380 // bool overflow = false;
381 //
382 // if ((a_arg == 0) || (m_num == 0) || (a_arg == 1) || (m_num == 1)) {
383 // m_num *= a_arg;
384 // return;
385 // }
386 //
387 // if ((lowest_value<T>() < 0) && (m_num < 0) && (a_arg < 0)) {
388 // if (-highest_value<T>() > a_arg)
389 // overflow = true;
390 // if (-(highest_value<T>() / a_arg) < -m_num)
391 // overflow = true;
392 // }
393 // else
394 // if ((lowest_value<T>() < 0) && (m_num < 0) && (a_arg >= 0)) {
395 // if (lowest_value<T>() / a_arg > m_num)
396 // overflow = true;
397 // }
398 // else
399 // if ((lowest_value<T>() < 0) && (m_num >= 0) && (a_arg < 0)) {
400 // if (lowest_value<T>() / m_num > a_arg)
401 // overflow = true;
402 // }
403 // else
404 // if ((lowest_value<T>() < 0) && (m_num >= 0) && (a_arg >= 0)) {
405 // if (highest_value<T>() / a_arg < m_num)
406 // overflow = true;
407 // }
408 // else
409 // if ((lowest_value<T>() >= 0) && (m_num >= 0) && (a_arg >= 0)) {
410 // if (highest_value<T>() / a_arg < m_num)
411 // overflow = true;
412 // }
413 // else {
414 // // This should never happen
415 // ASSERT(0);
416 // }
417 //
418 // if (overflow) {
419 // estring es;
420 //
421 // es = "Multiplication overflow error detected: ";
422 // if (is_char(m_num))
423 // es += estring(static_cast<int>(m_num));
424 // else
425 // es += estring(m_num);
426 // es += " * ";
427 // if (is_char(a_arg))
428 // es += estring(static_cast<int>(a_arg));
429 // else
430 // es += estring(a_arg);
431 // throw(INTERNAL_ERROR(0,es));
432 // }
433 // m_num *= a_arg;
434 // }
435 //
436 // /** Divide by a value */
437 // void divide(const T& a_arg)
438 // {
439 // T num;
440 //
441 // if (a_arg == static_cast<T>(0)) {
442 // estring es;
443 //
444 // es = "Division by zero error detected: ";
445 // if (is_char(m_num))
446 // es += estring(static_cast<int>(m_num));
447 // else
448 // es += estring(m_num);
449 // es += " / ";
450 // if (is_char(a_arg))
451 // es += estring(static_cast<int>(a_arg));
452 // else
453 // es += estring(a_arg);
454 // throw(INTERNAL_ERROR(0,es));
455 // }
456 //
457 // num = m_num;
458 // num /= a_arg;
459 // if ((m_num < 0) && (a_arg < 0) && (num < 0)) {
460 // estring es;
461 //
462 // es = "Division result has incorrect sign: ";
463 // if (is_char(m_num))
464 // es += estring(static_cast<int>(m_num));
465 // else
466 // es += estring(m_num);
467 // es += " / ";
468 // if (is_char(a_arg))
469 // es += estring(static_cast<int>(a_arg));
470 // else
471 // es += estring(a_arg);
472 // es += " != ";
473 // if (is_char(num))
474 // es += estring(static_cast<int>(num));
475 // else
476 // es += estring(num);
477 // throw(INTERNAL_ERROR(0,es));
478 // }
479 //
480 // m_num = num;
481 // return;
482 // }
483 //
484 // /** Assign a safe_num */
485 // void assign(const safe_num<T>& a_class)
486 // {
487 // assign(a_class.value());
488 // }
489 //
490 // /** Add a safe_num */
491 // void add(const safe_num<T>& a_class)
492 // {
493 // add(a_class.value());
494 // }
495 //
496 // /** Subtract a safe_num */
497 // void subtract(const safe_num<T>& a_class)
498 // {
499 // subtract(a_class.value());
500 // }
501 //
502 // /** Multiply by a safe_num */
503 // void multiply(const safe_num<T>& a_class)
504 // {
505 // multiply(a_class.value());
506 // }
507 //
508 // /** Divide by a safe_num */
509 // void divide(const safe_num<T>& a_class)
510 // {
511 // divide(a_class.value());
512 // }
513 //
514 // /** Boolean operator */
515 // const bool operator==(const T& a_arg) const
516 // {
517 // bool value;
518 //
519 // value = (m_num == a_arg);
520 //
521 // return(value);
522 // }
523 //
524 // /** Boolean operator */
525 // const bool operator==(const safe_num<T>& a_class) const
526 // {
527 // bool value;
528 //
529 // value = (m_num == a_class.value());
530 //
531 // return(value);
532 // }
533 //
534 // /** Boolean operator */
535 // const bool operator!=(const T& a_arg) const
536 // {
537 // bool value;
538 //
539 // value = (m_num != a_arg);
540 //
541 // return(value);
542 // }
543 //
544 // /** Boolean operator */
545 // const bool operator!=(const safe_num<T>& a_class) const
546 // {
547 // bool value;
548 //
549 // value = (m_num != a_class.value());
550 //
551 // return(value);
552 // }
553 //
554 // /** Boolean operator */
555 // const bool operator<(const T& a_arg) const
556 // {
557 // bool value;
558 //
559 // value = (m_num < a_arg);
560 //
561 // return(value);
562 // }
563 //
564 // /** Boolean operator */
565 // const bool operator<(const safe_num<T>& a_class) const
566 // {
567 // bool value;
568 //
569 // value = (m_num < a_class.value());
570 //
571 // return(value);
572 // }
573 //
574 // /** Boolean operator */
575 // const bool operator>(const T& a_arg) const
576 // {
577 // bool value;
578 //
579 // value = (m_num > a_arg);
580 //
581 // return(value);
582 // }
583 //
584 // /** Boolean operator */
585 // const bool operator>(const safe_num<T>& a_class) const
586 // {
587 // bool value;
588 //
589 // value = (m_num > a_class.value());
590 //
591 // return(value);
592 // }
593 //
594 // /** Boolean operator */
595 // const bool operator<=(const T& a_arg) const
596 // {
597 // bool value;
598 //
599 // value = (m_num <= a_arg);
600 //
601 // return(value);
602 // }
603 //
604 // /** Boolean operator */
605 // const bool operator<=(const safe_num<T>& a_class) const
606 // {
607 // bool value;
608 //
609 // value = (m_num <= a_class.value());
610 //
611 // return(value);
612 // }
613 //
614 // /** Boolean operator */
615 // const bool operator>=(const T& a_arg) const
616 // {
617 // bool value;
618 //
619 // value = (m_num >= a_arg);
620 //
621 // return(value);
622 // }
623 //
624 // /** Boolean operator */
625 // const bool operator>=(const safe_num<T>& a_class) const
626 // {
627 // bool value;
628 //
629 // value = (m_num >= a_class.value());
630 //
631 // return(value);
632 // }
633 //
634 // /** Arithmetic operator */
635 // safe_num<T>& operator+=(safe_num<T> a_class)
636 // {
637 // add(a_class);
638 //
639 // return(*this);
640 // }
641 //
642 // /** Arithmetic operator */
643 // safe_num<T>& operator-=(safe_num<T> a_class)
644 // {
645 // subtract(a_class);
646 //
647 // return(*this);
648 // }
649 //
650 // /** Arithmetic operator */
651 // safe_num<T>& operator*=(safe_num<T> a_class)
652 // {
653 // multiply(a_class);
654 //
655 // return(*this);
656 // }
657 //
658 // /** Arithmetic operator */
659 // safe_num<T>& operator/=(safe_num<T> a_class)
660 // {
661 // divide(a_class);
662 //
663 // return(*this);
664 // }
665 //
666 // /** Arithmetic operator */
667 // safe_num<T>& operator%=(safe_num<T> a_class)
668 // {
669 // m_num %= a_class.value();
670 //
671 // return(*this);
672 // }
673 //
674 // private:
675 // T m_num;
676 // };
677 
678 /** Arithmetic operator */
679 // template<typename T>
680 // safe_num<T> operator+(safe_num<T> a_class1, safe_num<T> a_class2)
681 // {
682 // safe_num<T> result;
683 //
684 // result.assign(a_class1);
685 // result.add(a_class2);
686 //
687 // return(result);
688 // }
689 
690 /** Arithmetic operator */
691 // template<typename T>
692 // safe_num<T> operator-(safe_num<T> a_class1, safe_num<T> a_class2)
693 // {
694 // safe_num<T> result;
695 //
696 // result.assign(a_class1);
697 // result.subtract(a_class2);
698 //
699 // return(result);
700 // }
701 
702 /** Arithmetic operator */
703 // template<typename T>
704 // safe_num<T> operator*(safe_num<T> a_class1, safe_num<T> a_class2)
705 // {
706 // safe_num<T> result;
707 //
708 // result.assign(a_class1);
709 // result.multiply(a_class2);
710 //
711 // return(result);
712 // }
713 
714 /** Arithmetic operator */
715 // template<typename T>
716 // safe_num<T> operator/(safe_num<T> a_class1, safe_num<T> a_class2)
717 // {
718 // safe_num<T> result;
719 //
720 // result.assign(a_class1);
721 // result.divide(a_class2);
722 //
723 // return(result);
724 // }
725 
726 /** Arithmetic operator */
727 // template<typename T>
728 // safe_num<T> operator%(safe_num<T> a_class1, safe_num<T> a_class2)
729 // {
730 // safe_num<T> result;
731 //
732 // result.assign(a_class1.value() % a_class2.value());
733 //
734 // return(result);
735 // }
736 
737 /** Arithmetic operator */
738 // template<typename T>
739 // safe_num<T>& operator++(safe_num<T>& a_class)
740 // {
741 // a_class.add(static_cast<T>(1));
742 //
743 // return(a_class);
744 // }
745 
746 /** Arithmetic operator */
747 // template<typename T>
748 // safe_num<T> operator++(safe_num<T>& a_class, int)
749 // {
750 // safe_num<T> result;
751 //
752 // result.assign(a_class);
753 // a_class.add(static_cast<T>(1));
754 //
755 // return(result);
756 // }
757 
758 /** Arithmetic operator */
759 // template<typename T>
760 // safe_num<T>& operator--(safe_num<T>& a_class)
761 // {
762 // a_class.subtract(static_cast<T>(1));
763 //
764 // return(a_class);
765 // }
766 
767 /** Arithmetic operator */
768 // template<typename T>
769 // safe_num<T> operator--(safe_num<T>& a_class, int)
770 // {
771 // safe_num<T> result;
772 //
773 // result.assign(a_class);
774 // a_class.subtract(static_cast<T>(1));
775 //
776 // return(result);
777 // }
778 
779 /** Arithmetic operator */
780 // template<typename T>
781 // std::ostream& operator<<(std::ostream& a_out, safe_num<T> a_class)
782 // {
783 // a_out << a_class.value();
784 //
785 // return(a_out);
786 // }
787 
788 /** Arithmetic operator */
789 // template<typename T>
790 // std::istream& operator>>(std::istream& a_in, safe_num<T>& a_class)
791 // {
792 // T num;
793 //
794 // a_in >> num;
795 // a_class = num;
796 //
797 // return(a_in);
798 // }
799 
800 // ---------------------------------------------------------------------------
801 
const float max_limit< float >()
Return the largest possible number that a float may hold.
Definition: rmath.h:86
const double min_limit< double >()
Return the smallest positive number that a double may hold.
Definition: rmath.h:134
const float min_limit< float >()
Return the smallest positive number that a float may hold.
Definition: rmath.h:104
const double max_limit< double >()
Return the largest possible number that a double may hold.
Definition: rmath.h:116