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