Wiselib
wiselib.testing/util/standalone_math.h
Go to the documentation of this file.
00001 // vim: set noexpandtab ts=4 sw=4:
00002 
00003 #ifndef STANDALONE_MATH_H
00004 #define STANDALONE_MATH_H
00005 
00006 #include <stdint.h>
00007 
00008 namespace wiselib {
00009 
00010 template<typename OsModel_P>
00011 class StandaloneMath {
00012    public:
00013       typedef OsModel_P OsModel;
00014       typedef double real_t;
00015       typedef int32_t integer_t;
00016       
00017       static const real_t PI, PI_2, PI_3, PI_4, PI_6;
00018       
00019       static real_t sqrt(real_t);
00020       
00021       // ---- Trigonometry
00022       
00023       static real_t radians_to_degrees(real_t);
00024       static real_t degrees_to_radians(real_t);
00025       
00026       static real_t sin(real_t);
00027       static real_t cos(real_t);
00028       static real_t tan(real_t);
00029       
00030       static real_t asin(real_t);
00031       static real_t acos(real_t);
00032       
00033       // ---- Rounding & signs
00034       
00035       static real_t fabs(real_t);
00036       
00037       template<typename T>
00038       static T sgn(T x) {
00039          if(x > 0) { return 1; }
00040          else if(x < 0) { return -1; }
00041          return 0;
00042       }
00043       
00045       static integer_t trunc(real_t);
00047       static integer_t floor(real_t);
00049       static integer_t ceil(real_t);
00051       static integer_t round(real_t);
00052       
00053    private:
00054       static real_t sin_degrees(integer_t);
00055       static real_t cos_degrees(integer_t);
00056       static integer_t asin_degrees(real_t);
00057       
00058       static real_t sqrt_eps(real_t, real_t);
00059       
00060       static const real_t sin_table_[91];
00061 };
00062 
00063 template<typename OsModel_P>
00064 const typename StandaloneMath<OsModel_P>::real_t StandaloneMath<OsModel_P>::PI = 3.14159265358979323846; /* pi */
00065 
00066 template<typename OsModel_P>
00067 const typename StandaloneMath<OsModel_P>::real_t StandaloneMath<OsModel_P>::PI_2 = 1.57079632679489661923; /* pi/2 */
00068 
00069 template<typename OsModel_P>
00070 const typename StandaloneMath<OsModel_P>::real_t StandaloneMath<OsModel_P>::PI_3 = 1.04719755119659763132; /* pi/3 */
00071 
00072 template<typename OsModel_P>
00073 const typename StandaloneMath<OsModel_P>::real_t StandaloneMath<OsModel_P>::PI_4 = 0.78539816339744830962; /* pi/4 */
00074 
00075 template<typename OsModel_P>
00076 const typename StandaloneMath<OsModel_P>::real_t StandaloneMath<OsModel_P>::PI_6 = 0.52359877559829881566; /* pi/6 */
00077 
00078 template<typename OsModel_P>
00079 const typename StandaloneMath<OsModel_P>::real_t StandaloneMath<OsModel_P>::sin_table_[91] = {
00080    0.000000000000000000000000000000,
00081    0.017452406437283511653202339176,
00082    0.034899496702500969191884649945,
00083    0.052335956242943834637593170100,
00084    0.069756473744125302438590097154,
00085    0.087155742747658165869850677154,
00086    0.104528463267653470847307062286,
00087    0.121869343405147476100403025612,
00088    0.139173100960065437847745783984,
00089    0.156434465040230868959625354364,
00090    0.173648177666930331186634361984,
00091    0.190808995376544804356555573577,
00092    0.207911690817759342575499204031,
00093    0.224951054343865003426472526371,
00094    0.241921895599667730047954705697,
00095    0.258819045102520739476403832668,
00096    0.275637355816999163327096766807,
00097    0.292371704722736769355151409400,
00098    0.309016994374947395751718204338,
00099    0.325568154457156699876918537484,
00100    0.342020143325668712908083080038,
00101    0.358367949545300268354708350671,
00102    0.374606593415912014766178117497,
00103    0.390731128489273771275946955939,
00104    0.406736643075800208269043878317,
00105    0.422618261740699441286750470681,
00106    0.438371146789077403838064128649,
00107    0.453990499739546748969587497413,
00108    0.469471562785890805802324621254,
00109    0.484809620246337058535601727272,
00110    0.499999999999999944488848768742,
00111    0.515038074910054155530758634995,
00112    0.529919264233204900804707904172,
00113    0.544639035015027084263294909761,
00114    0.559192903470746904837085367035,
00115    0.573576436351046048400803556433,
00116    0.587785252292473137103456792829,
00117    0.601815023152048267363056766044,
00118    0.615661475325658291701813595864,
00119    0.629320391049837390973209494405,
00120    0.642787609686539251896419955301,
00121    0.656059028990507275835852851742,
00122    0.669130606358858237570075289113,
00123    0.681998360062498476530379321048,
00124    0.694658370458997254104360763449,
00125    0.707106781186547461715008466854,
00126    0.719339800338651080835461470997,
00127    0.731353701619170459835572728480,
00128    0.743144825477394244117590460519,
00129    0.754709580222772014046483946004,
00130    0.766044443118978013451680908474,
00131    0.777145961456970901792828954058,
00132    0.788010753606722014197316639184,
00133    0.798635510047292829227671973058,
00134    0.809016994374947451262869435595,
00135    0.819152044288991798559607104835,
00136    0.829037572555041735178349426860,
00137    0.838670567945424050293468098971,
00138    0.848048096156425956770874563517,
00139    0.857167300702112333610216410307,
00140    0.866025403784438596588302061718,
00141    0.874619707139395741180010190874,
00142    0.882947592858926877390501886111,
00143    0.891006524188367787786546614370,
00144    0.898794046299167037616939524014,
00145    0.906307787036649936673882166360,
00146    0.913545457642600866599025266623,
00147    0.920504853452440374717014037742,
00148    0.927183854566787424289486807538,
00149    0.933580426497201742996878692793,
00150    0.939692620785908316882739654829,
00151    0.945518575599316735136312672694,
00152    0.951056516295153531181938433292,
00153    0.956304755963035435506469639222,
00154    0.961261695938318894150143023580,
00155    0.965925826289068312213714762038,
00156    0.970295726275996472942608761514,
00157    0.974370064785235245885530730447,
00158    0.978147600733805577810642262193,
00159    0.981627183447663975712771389226,
00160    0.984807753012208020315654266597,
00161    0.987688340595137770350220307591,
00162    0.990268068741570361979142944620,
00163    0.992546151641321983127852490725,
00164    0.994521895368273289861349439889,
00165    0.996194698091745545198705258372,
00166    0.997564050259824197652847033169,
00167    0.998629534754573833232882407174,
00168    0.999390827019095762118183756684,
00169    1.000000000000000000000000000000
00170 };
00171 
00172 template<typename OsModel_P>
00173 typename StandaloneMath<OsModel_P>::real_t
00174 StandaloneMath<OsModel_P>::
00175 fabs(typename StandaloneMath<OsModel_P>::real_t x) {
00176    if(x < 0) { return -x; }
00177    return x;
00178 }
00179 
00180 template<typename OsModel_P>
00181 typename StandaloneMath<OsModel_P>::real_t
00182 StandaloneMath<OsModel_P>::
00183 sqrt_eps(typename StandaloneMath<OsModel_P>::real_t x, typename StandaloneMath<OsModel_P>::real_t epsilon) {
00184    //static const integer_t max_iterations = 1000;
00185    typename StandaloneMath<OsModel_P>::integer_t iterations = 0;
00186    
00187    if(x < 0) { // || x <= (2.0*epsilon*epsilon)) {
00188       return -1.0;
00189    }
00190    
00191    typename StandaloneMath<OsModel_P>::real_t y = x;
00192    while(fabs((y*y) - x) > epsilon /*&& iterations < max_iterations*/) {
00193       y = (y + (x / y)) / 2.0;
00194       iterations++;
00195    }
00196    return y;
00197 }
00198 
00199 template<typename OsModel_P>
00200 typename StandaloneMath<OsModel_P>::real_t
00201 StandaloneMath<OsModel_P>::
00202 sqrt(typename StandaloneMath<OsModel_P>::real_t x) {
00203    return sqrt_eps(x, 0.00000001);
00204 }
00205 
00206 // Degrees <-> Radians conversion
00207 template<typename OsModel_P>
00208 typename StandaloneMath<OsModel_P>::real_t
00209 StandaloneMath<OsModel_P>::
00210 radians_to_degrees(typename StandaloneMath<OsModel_P>::real_t x) { return 180.0 * x / PI; }
00211 
00212 template<typename OsModel_P>
00213 typename StandaloneMath<OsModel_P>::real_t
00214 StandaloneMath<OsModel_P>::
00215 degrees_to_radians(typename StandaloneMath<OsModel_P>::real_t x) { return PI * x / 180.0; }
00216 
00217 // Basic trigonometric functions
00218 template<typename OsModel_P>
00219 typename StandaloneMath<OsModel_P>::real_t
00220 StandaloneMath<OsModel_P>::
00221 sin(typename StandaloneMath<OsModel_P>::real_t x) {
00222    return sin_degrees(round(radians_to_degrees(x)));
00223 }
00224 
00225 template<typename OsModel_P>
00226 typename StandaloneMath<OsModel_P>::real_t
00227 StandaloneMath<OsModel_P>::
00228 cos(typename StandaloneMath<OsModel_P>::real_t x) {
00229    return sin(x + PI_2);
00230 }
00231 
00232 template<typename OsModel_P>
00233 typename StandaloneMath<OsModel_P>::real_t
00234 StandaloneMath<OsModel_P>::
00235 tan(typename StandaloneMath<OsModel_P>::real_t x) {
00236    return sin(x) / cos(x);
00237 }
00238 
00239 template<typename OsModel_P>
00240 typename StandaloneMath<OsModel_P>::real_t
00241 StandaloneMath<OsModel_P>::
00242 sin_degrees(typename StandaloneMath<OsModel_P>::integer_t x) {
00243    int y = x % 360;
00244    if(y < 0) { y += 360; }
00245    
00246    if(y < 90) { return sin_table_[y]; }
00247    else if(y < 180) { return sin_table_[180 - y]; }
00248    else if(y < 270) { return -sin_table_[y - 180]; }
00249    else { return -sin_table_[360 - y]; }
00250 }
00251 
00252 template<typename OsModel_P>
00253 typename StandaloneMath<OsModel_P>::real_t
00254 StandaloneMath<OsModel_P>::
00255 cos_degrees(typename StandaloneMath<OsModel_P>::integer_t x) {
00256    return sin_degrees(x + 90);
00257 }
00258 
00259 template<typename OsModel_P>
00260 typename StandaloneMath<OsModel_P>::real_t
00261 StandaloneMath<OsModel_P>::
00262 asin(typename StandaloneMath<OsModel_P>::real_t x) {
00263    return degrees_to_radians(asin_degrees(x));
00264 }
00265 
00266 template<typename OsModel_P>
00267 typename StandaloneMath<OsModel_P>::real_t
00268 StandaloneMath<OsModel_P>::
00269 acos(typename StandaloneMath<OsModel_P>::real_t x) {
00270    return degrees_to_radians(180 + asin_degrees(-x));
00271 }
00272 
00273 template<typename OsModel_P>
00274 typename StandaloneMath<OsModel_P>::integer_t
00275 StandaloneMath<OsModel_P>::
00276 asin_degrees(typename StandaloneMath<OsModel_P>::real_t x) {
00277    if(x < 0) {
00278       return -asin_degrees(-x);
00279    }
00280    
00281    // sin_table_ is monotone, conduct a binary search
00282    integer_t top = 90, bottom = 0, idx = 0;
00283    while(top - bottom > 1) {
00284       idx = (top + bottom) / 2;
00285       if(sin_table_[idx] > x) {
00286          top = idx;
00287       }
00288       else {
00289          bottom = idx;
00290       }
00291    }
00292    
00293    idx = bottom;
00294    if(
00295       fabs(sin_table_[top] - x) <
00296       fabs(sin_table_[bottom] - x)
00297    ) {
00298       idx = top;
00299    }
00300    return idx;
00301 }
00302 
00303 
00304 // Rounding
00305 template<typename OsModel_P>
00306 typename StandaloneMath<OsModel_P>::integer_t
00307 StandaloneMath<OsModel_P>::
00308 trunc(typename StandaloneMath<OsModel_P>::real_t x) {
00309    return static_cast<integer_t>(x);
00310 }
00311 
00312 template<typename OsModel_P>
00313 typename StandaloneMath<OsModel_P>::integer_t
00314 StandaloneMath<OsModel_P>::
00315 floor(typename StandaloneMath<OsModel_P>::real_t x) {
00316    if(x > 0) { return trunc(x); }
00317    else {
00318       //   floor(-12.3456) = -13
00319       //   trunc(-12.3456) = -12
00320       if(static_cast<real_t>(trunc(x)) != x) {
00321          return trunc(x) - 1;
00322       }
00323       else {
00324          return trunc(x);
00325       }
00326    }
00327 }
00328 
00329 template<typename OsModel_P>
00330 typename StandaloneMath<OsModel_P>::integer_t
00331 StandaloneMath<OsModel_P>::
00332 ceil(typename StandaloneMath<OsModel_P>::real_t x) {
00333    return -floor(-x);
00334 }
00335 
00336 template<typename OsModel_P>
00337 typename StandaloneMath<OsModel_P>::integer_t
00338 StandaloneMath<OsModel_P>::
00339 round(typename StandaloneMath<OsModel_P>::real_t x) {
00340    return floor(x + 0.5);
00341 }
00342 
00343 } // namespace wiselib
00344 
00345 #endif // STANDALONE_MATH_H
00346 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines