MathsCustomFunctions.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "MathsCustomFunctions.hpp"
00030
00031 #include <cmath>
00032 #include <iostream>
00033
00034 double SmallPow(double x, unsigned exponent)
00035 {
00036 switch (exponent)
00037 {
00038 case 0:
00039 {
00040 return 1.0;
00041 }
00042 case 1:
00043 {
00044 return x;
00045 }
00046 case 2:
00047 {
00048 return x*x;
00049 }
00050 case 3:
00051 {
00052 return x*x*x;
00053 }
00054 default:
00055 {
00056 if (exponent % 2 == 0)
00057 {
00058
00059 double partial_answer = SmallPow(x, exponent/2);
00060 return partial_answer*partial_answer;
00061 }
00062 else
00063 {
00064
00065 return SmallPow(x, exponent-1)*x;
00066 }
00067 }
00068 }
00069 }
00070
00071 bool Divides(double smallerNumber, double largerNumber)
00072 {
00073 double remainder = fmod(largerNumber, smallerNumber);
00074
00075
00076
00077
00078 if (remainder < DBL_EPSILON*largerNumber)
00079 {
00080 return true;
00081 }
00082
00083
00084
00085
00086 if (fabs(remainder-smallerNumber) < DBL_EPSILON*largerNumber)
00087 {
00088 return true;
00089 }
00090
00091 return false;
00092 }
00093
00094 bool CompareDoubles::IsNearZero(double number, double tolerance)
00095 {
00096 return fabs(number) <= fabs(tolerance);
00097 }
00098
00104 double SafeDivide(double number, double divisor)
00105 {
00106
00107 if (divisor < 1.0 && number > divisor*DBL_MAX)
00108 {
00109 return DBL_MAX;
00110 }
00111
00112
00113 if (number == 0.0 || (divisor > 1.0 && number < divisor*DBL_MIN))
00114 {
00115 return 0.0;
00116 }
00117
00118 return number/divisor;
00119
00120 }
00121
00122 bool CompareDoubles::WithinRelativeTolerance(double number1, double number2, double tolerance)
00123 {
00124 double diff = fabs(number1 - number2);
00125 double d1 = SafeDivide(diff, fabs(number1));
00126 double d2 = SafeDivide(diff, fabs(number2));
00127
00128 return d1 <= tolerance && d2 <= tolerance;
00129 }
00130
00131 bool CompareDoubles::WithinAbsoluteTolerance(double number1, double number2, double tolerance)
00132 {
00133 return fabs(number1 - number2) <= tolerance;
00134 }
00135
00136 bool CompareDoubles::WithinAnyTolerance(double number1, double number2, double relTol, double absTol, bool printError)
00137 {
00138 bool ok = WithinAbsoluteTolerance(number1, number2, absTol) || WithinRelativeTolerance(number1, number2, relTol);
00139 if (printError && !ok)
00140 {
00141 std::cout << "CompareDoubles::WithinAnyTolerance: " << number1 << " and " << number2
00142 << " differ by more than relative tolerance of " << relTol
00143 << " and absolute tolerance of " << absTol << std::endl;
00144 }
00145 return ok;
00146 }
00147
00148 bool CompareDoubles::WithinTolerance(double number1, double number2, double tolerance, bool toleranceIsAbsolute)
00149 {
00150 bool ok;
00151 if (toleranceIsAbsolute)
00152 {
00153 ok = WithinAbsoluteTolerance(number1, number2, tolerance);
00154 }
00155 else
00156 {
00157 ok = WithinRelativeTolerance(number1, number2, tolerance);
00158 }
00159 if (!ok)
00160 {
00161 std::cout << "CompareDoubles::WithinTolerance: " << number1 << " and " << number2
00162 << " differ by more than " << (toleranceIsAbsolute ? "absolute" : "relative")
00163 << " tolerance of " << tolerance << std::endl;
00164 }
00165 return ok;
00166 }
00167
00168 double CompareDoubles::Difference(double number1, double number2, bool toleranceIsAbsolute)
00169 {
00170 if (toleranceIsAbsolute)
00171 {
00172 return fabs(number1 - number2);
00173 }
00174 else
00175 {
00176 double diff = fabs(number1 - number2);
00177 double d1 = SafeDivide(diff, fabs(number1));
00178 double d2 = SafeDivide(diff, fabs(number2));
00179 return d1 > d2 ? d1 : d2;
00180 }
00181 }