rvm  1.11
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
rmath.h
Go to the documentation of this file.
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>
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>
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>
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>
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>
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>
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>
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>
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>
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 */
286  {
287  clear();
288  }
289 
290  /** C'tor */
291  safe_num(const T a_num)
292  {
293  clear();
294  m_num = a_num;
295  }
296 
297  /** C'tor */
298  safe_num(const safe_num& a_class)
299  {
300  clear();
301  m_num = a_class.value();
302  }
303 
304  /** Clear the value */
305  void clear(void)
306  {
307  m_num = static_cast<T>(0);
308  }
309 
310  /** Return the value */
311  const T value(void) const
312  {
313  return(m_num);
314  }
315 
316  /** Assign a value */
317  void assign(const T& a_arg)
318  {
319  m_num = a_arg;
320  }
321 
322  /** Add a value */
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 */
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 */
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 */
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 */
502  void assign(const safe_num<T>& a_class)
503  {
504  assign(a_class.value());
505  }
506 
507  /** Add a safe_num */
508  void add(const safe_num<T>& a_class)
509  {
510  add(a_class.value());
511  }
512 
513  /** Subtract a safe_num */
514  void subtract(const safe_num<T>& a_class)
515  {
516  subtract(a_class.value());
517  }
518 
519  /** Multiply by a safe_num */
520  void multiply(const safe_num<T>& a_class)
521  {
522  multiply(a_class.value());
523  }
524 
525  /** Divide by a safe_num */
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 */
653  {
654  add(a_class);
655 
656  return(*this);
657  }
658 
659  /** Arithmetic operator */
661  {
662  subtract(a_class);
663 
664  return(*this);
665  }
666 
667  /** Arithmetic operator */
669  {
670  multiply(a_class);
671 
672  return(*this);
673  }
674 
675  /** Arithmetic operator */
677  {
678  divide(a_class);
679 
680  return(*this);
681  }
682 
683  /** Arithmetic operator */
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>
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>
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>
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>
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>
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>
757 {
758  a_class.add(static_cast<T>(1));
759 
760  return(a_class);
761 }
762 
763 /** Arithmetic operator */
764 template<typename T>
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>
778 {
779  a_class.subtract(static_cast<T>(1));
780 
781  return(a_class);
782 }
783 
784 /** Arithmetic operator */
785 template<typename T>
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
void add(const T &a_arg)
Add a value.
Definition: rmath.h:323
T absolute(const T &a_num)
Return the absolute value of a numeric type.
Definition: rmath.h:240
Safely manipulate numbers without worryiung about over/underflow error.
Definition: rmath.h:281
Basic types definitions and templates.
static const T lowest_value(void)
Return 0 for unsigned types, or the maximum negative value that the type may hold.
Definition: rmath.h:206
An extended string class.
Definition: estring.h:52
#define ASSERT(code)
Definition: asserts.h:9
void divide(const safe_num< T > &a_class)
Divide by a safe_num.
Definition: rmath.h:526
const bool operator==(const safe_num< T > &a_class) const
Boolean operator.
Definition: rmath.h:542
safe_num< T > & operator+=(safe_num< T > a_class)
Arithmetic operator.
Definition: rmath.h:652
void add(const safe_num< T > &a_class)
Add a safe_num.
Definition: rmath.h:508
void subtract(const safe_num< T > &a_class)
Subtract a safe_num.
Definition: rmath.h:514
T m_num
Definition: rmath.h:692
const T value(void) const
Return the value.
Definition: rmath.h:311
void assign(const safe_num< T > &a_class)
Assign a safe_num.
Definition: rmath.h:502
safe_num< T > operator/(safe_num< T > a_class1, safe_num< T > a_class2)
Arithmetic operator.
Definition: rmath.h:733
static const T max_limit()
A small set of numeric limits routines, since gcc prior to 3.x doesn't have numeric_limits.
Definition: rmath.h:20
const float max_limit< float >()
Return the largest possible number that a float may hold.
Definition: rmath.h:86
safe_num< T > operator+(safe_num< T > a_class1, safe_num< T > a_class2)
Arithmetic operator.
Definition: rmath.h:697
safe_num< T > & operator++(safe_num< T > &a_class)
Arithmetic operator.
Definition: rmath.h:756
safe_num< T > & operator-=(safe_num< T > a_class)
Arithmetic operator.
Definition: rmath.h:660
void assign(const T &a_arg)
Assign a value.
Definition: rmath.h:317
safe_num< T > operator*(safe_num< T > a_class1, safe_num< T > a_class2)
Arithmetic operator.
Definition: rmath.h:721
const bool operator>(const T &a_arg) const
Boolean operator.
Definition: rmath.h:592
void multiply(const T &a_arg)
Multiply by a value.
Definition: rmath.h:395
safe_num< T > & operator--(safe_num< T > &a_class)
Arithmetic operator.
Definition: rmath.h:777
#define TRY_nomem(code)
Definition: error.h:144
safe_num< T > & operator*=(safe_num< T > a_class)
Arithmetic operator.
Definition: rmath.h:668
void divide(const T &a_arg)
Divide by a value.
Definition: rmath.h:454
const bool operator!=(const T &a_arg) const
Boolean operator.
Definition: rmath.h:552
safe_num(const safe_num &a_class)
C'tor.
Definition: rmath.h:298
const bool operator<=(const T &a_arg) const
Boolean operator.
Definition: rmath.h:612
safe_num< T > operator%(safe_num< T > a_class1, safe_num< T > a_class2)
Arithmetic operator.
Definition: rmath.h:745
#define INTERNAL_ERROR(e, s)
Definition: error.h:123
const bool operator>=(const T &a_arg) const
Boolean operator.
Definition: rmath.h:632
std::istream & operator>>(std::istream &a_in, safe_num< T > &a_class)
Arithmetic operator.
Definition: rmath.h:807
const double min_limit< double >()
Return the smallest positive number that a double may hold.
Definition: rmath.h:134
static const T highest_value(void)
Return the maximum possible value a type may hold.
Definition: rmath.h:182
static bool is_char(const T &a_arg)
Return true for any variable that is either a signed or unsigned char.
Definition: types.h:120
const float min_limit< float >()
Return the smallest positive number that a float may hold.
Definition: rmath.h:104
safe_num< T > operator-(safe_num< T > a_class1, safe_num< T > a_class2)
Arithmetic operator.
Definition: rmath.h:709
safe_num(const T a_num)
C'tor.
Definition: rmath.h:291
safe_num()
C'tor.
Definition: rmath.h:285
safe_num< T > & operator%=(safe_num< T > a_class)
Arithmetic operator.
Definition: rmath.h:684
#define ERROR(e, s)
Definition: error.h:120
void clear(void)
Clear the value.
Definition: rmath.h:305
void multiply(const safe_num< T > &a_class)
Multiply by a safe_num.
Definition: rmath.h:520
const double max_limit< double >()
Return the largest possible number that a double may hold.
Definition: rmath.h:116
const bool operator>(const safe_num< T > &a_class) const
Boolean operator.
Definition: rmath.h:602
const bool operator<(const T &a_arg) const
Boolean operator.
Definition: rmath.h:572
const bool operator>=(const safe_num< T > &a_class) const
Boolean operator.
Definition: rmath.h:642
void subtract(const T &a_arg)
Subtract a value.
Definition: rmath.h:356
const bool operator==(const T &a_arg) const
Boolean operator.
Definition: rmath.h:532
safe_num< T > & operator/=(safe_num< T > a_class)
Arithmetic operator.
Definition: rmath.h:676
const bool operator!=(const safe_num< T > &a_class) const
Boolean operator.
Definition: rmath.h:562
static const T min_limit()
Find the maximum limit for a type, equivalent to std::numeric_limits<T>.min() for systems that don't ha...
Definition: rmath.h:48