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
00030
00031
00032
00033
00034
00035
00036 #include "MathsCustomFunctions.hpp"
00037
00038 #include <cmath>
00039 #include <iostream>
00040
00041 double SmallPow(double x, unsigned exponent)
00042 {
00043 switch (exponent)
00044 {
00045 case 0:
00046 {
00047 return 1.0;
00048 }
00049 case 1:
00050 {
00051 return x;
00052 }
00053 case 2:
00054 {
00055 return x*x;
00056 }
00057 case 3:
00058 {
00059 return x*x*x;
00060 }
00061 default:
00062 {
00063 if (exponent % 2 == 0)
00064 {
00065
00066 double partial_answer = SmallPow(x, exponent/2);
00067 return partial_answer*partial_answer;
00068 }
00069 else
00070 {
00071
00072 return SmallPow(x, exponent-1)*x;
00073 }
00074 }
00075 }
00076 }
00077 unsigned SmallPow(unsigned x, unsigned exponent)
00078 {
00079 switch (exponent)
00080 {
00081 case 0:
00082 {
00083 return 1u;
00084 }
00085 case 1:
00086 {
00087 return x;
00088 }
00089 case 2:
00090 {
00091 return x*x;
00092 }
00093 case 3:
00094 {
00095 return x*x*x;
00096 }
00097 default:
00098 {
00099 if (exponent % 2 == 0)
00100 {
00101
00102 unsigned partial_answer = SmallPow(x, exponent/2);
00103 return partial_answer*partial_answer;
00104 }
00105 else
00106 {
00107
00108 return SmallPow(x, exponent-1)*x;
00109 }
00110 }
00111 }
00112 }
00113
00114 bool Divides(double smallerNumber, double largerNumber)
00115 {
00116 double remainder = fmod(largerNumber, smallerNumber);
00117
00118
00119
00120
00121 if (remainder < DBL_EPSILON*largerNumber)
00122 {
00123 return true;
00124 }
00125
00126
00127
00128
00129 if (fabs(remainder-smallerNumber) < DBL_EPSILON*largerNumber)
00130 {
00131 return true;
00132 }
00133
00134 return false;
00135 }
00136
00137 unsigned CeilDivide(unsigned numerator, unsigned denominator)
00138 {
00139 if( numerator==0u )
00140 {
00141 return 0u;
00142 }
00143 else
00144 {
00145
00146 return ((numerator - 1u) / denominator) + 1u;
00147 }
00148 }
00149
00150 double Signum(double value)
00151 {
00152 return (0.0 < value) - (value < 0.0);
00153 }
00154
00155 bool CompareDoubles::IsNearZero(double number, double tolerance)
00156 {
00157 return fabs(number) <= fabs(tolerance);
00158 }
00159
00165 double SafeDivide(double numerator, double divisor);
00166
00167 double SafeDivide(double numerator, double divisor)
00168 {
00169
00170 if (divisor < 1.0 && numerator > divisor*DBL_MAX)
00171 {
00172 return DBL_MAX;
00173 }
00174
00175
00176 if (numerator == 0.0 || (divisor > 1.0 && numerator < divisor*DBL_MIN))
00177 {
00178 return 0.0;
00179 }
00180
00181 return numerator/divisor;
00182
00183 }
00184
00185 bool CompareDoubles::WithinRelativeTolerance(double number1, double number2, double tolerance)
00186 {
00187 double difference = fabs(number1 - number2);
00188 double d1 = SafeDivide(difference, fabs(number1));
00189 double d2 = SafeDivide(difference, fabs(number2));
00190
00191 return d1 <= tolerance && d2 <= tolerance;
00192 }
00193
00194 bool CompareDoubles::WithinAbsoluteTolerance(double number1, double number2, double tolerance)
00195 {
00196 return fabs(number1 - number2) <= tolerance;
00197 }
00198
00199 bool CompareDoubles::WithinAnyTolerance(double number1, double number2, double relTol, double absTol, bool printError)
00200 {
00201 bool ok = WithinAbsoluteTolerance(number1, number2, absTol) || WithinRelativeTolerance(number1, number2, relTol);
00202 if (printError && !ok)
00203 {
00204 std::cout << "CompareDoubles::WithinAnyTolerance: " << number1 << " and " << number2
00205 << " differ by more than relative tolerance of " << relTol
00206 << " and absolute tolerance of " << absTol << std::endl;
00207 }
00208 return ok;
00209 }
00210
00211 bool CompareDoubles::WithinTolerance(double number1, double number2, double tolerance, bool toleranceIsAbsolute)
00212 {
00213 bool ok;
00214 if (toleranceIsAbsolute)
00215 {
00216 ok = WithinAbsoluteTolerance(number1, number2, tolerance);
00217 }
00218 else
00219 {
00220 ok = WithinRelativeTolerance(number1, number2, tolerance);
00221 }
00222 if (!ok)
00223 {
00224 std::cout << "CompareDoubles::WithinTolerance: " << number1 << " and " << number2
00225 << " differ by more than " << (toleranceIsAbsolute ? "absolute" : "relative")
00226 << " tolerance of " << tolerance << std::endl;
00227 }
00228 return ok;
00229 }
00230
00231 double CompareDoubles::Difference(double number1, double number2, bool toleranceIsAbsolute)
00232 {
00233 if (toleranceIsAbsolute)
00234 {
00235 return fabs(number1 - number2);
00236 }
00237 else
00238 {
00239 double difference = fabs(number1 - number2);
00240 double d1 = SafeDivide(difference, fabs(number1));
00241 double d2 = SafeDivide(difference, fabs(number2));
00242 return d1 > d2 ? d1 : d2;
00243 }
00244 }