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