00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "fixed.h"
00024 #include <math.h>
00025 #include <stdlib.h>
00026 #include <string.h>
00027 #include <limits.h>
00028 #include <common/DefinesAssert.h>
00029 #include <common/DefinesString.h>
00030 #include <common/Logger.h>
00031
00032 #define _XPI 31415 // 3.1415926535897932384626433832795
00033 fixed fixed::XPI = fixed(true,_XPI);
00034 #define _X2PI 62831 // 6.283185307179586476925286766559
00035 fixed fixed::X2PI = fixed(true,_X2PI);
00036 #define _XPIO2 15707 // 1.5707963267948966192313216916398
00037 fixed fixed::XPIO2 = fixed(true,_XPIO2);
00038 #define _XPIO4 7853 // 0.78539816339744830961566084581988
00039 #define XPIO4 fixed(true, _XPIO4)
00040 #define _XLN_E 27182 // 2.71828182845904523536
00041 #define XLN_E fixed(true,_XLN_E)
00042 #define _XLN_10 23025 // 2.30258509299404568402
00043 #define XLN_10 fixed(true,_XLN_10)
00044
00045 fixed fixed::MAX_FIXED(true, INT_MAX);
00046
00047 inline int fixed_internal_mult(int a, int b)
00048 {
00049 int c = 0;
00050 if (sizeof(long) == 8)
00051 {
00052 c = (int)((((long)a)*((long)b))/FIXED_RESOLUTION);
00053 }
00054 else if (sizeof(long long) == 8)
00055 {
00056 c = (int)((((long long)a)*((long long)b))/FIXED_RESOLUTION);
00057 }
00058 return c;
00059 }
00060
00061 inline int fixed_internal_div(int a, int b)
00062 {
00063 if(b == 0) return 0xFFFFFFF;
00064
00065 int c = 0;
00066 if (sizeof(long) == 8)
00067 {
00068 c = (int)((((long)a)*((long)FIXED_RESOLUTION))/b);
00069 }
00070 else if (sizeof(long long) == 8)
00071 {
00072 c = (int)((((long long)a)*((long long)FIXED_RESOLUTION))/b);
00073 }
00074 return c;
00075 }
00076
00077 fixed::fixed(const char *nVal)
00078 {
00079 if (strlen(nVal) > 12)
00080 {
00081 Logger::log(S3D::formatStringBuffer("Warning: Ignoring fixed string conversion of %s", nVal));
00082
00083 m_nVal = 0;
00084 return;
00085 }
00086
00087 char i[15];
00088 char f[15];
00089
00090 int ip = 0;
00091 int fp = 0;
00092 bool fract = false;
00093 bool neg = false;
00094 for (const char *c=nVal; *c; c++)
00095 {
00096 if (*c == '.') fract = true;
00097 else if (*c == '-') neg = true;
00098 else
00099 {
00100 if (fract) f[fp++] = *c;
00101 else i[ip++] = *c;
00102 }
00103 }
00104
00105 for (; fp<4; fp++)
00106 {
00107 f[fp] = '0';
00108 }
00109 i[ip] = '\0';
00110 f[fp] = '\0';
00111 DIALOG_ASSERT(ip < 15 && fp < 15);
00112
00113 int ipa = atoi(i);
00114 int fpa = atoi(f);
00115
00116 m_nVal = ipa * FIXED_RESOLUTION + fpa;
00117 if (neg) m_nVal =- m_nVal;
00118 }
00119
00120 const char *fixed::asString()
00121 {
00122 static char result[15];
00123 int r = 0;
00124
00125 char buffer[15];
00126 if (m_nVal < 0)
00127 {
00128 snprintf(buffer, 15, "%i", -m_nVal);
00129 result[r++] = '-';
00130 }
00131 else
00132 {
00133 snprintf(buffer, 15, "%i", m_nVal);
00134 }
00135 int len = strlen(buffer);
00136
00137 if (len <= 4)
00138 {
00139 result[r++] = '0';
00140 result[r++] = '.';
00141 for (int i=len; i<4; i++)
00142 {
00143 result[r++] = '0';
00144 }
00145 for (int i=0; i<len; i++)
00146 {
00147 result[r++] = buffer[i];
00148 }
00149 }
00150 else
00151 {
00152 for (int i=0; i<len-4; i++)
00153 {
00154 result[r++] = buffer[i];
00155 }
00156 result[r++] = '.';
00157 for (int i=len-4; i<len; i++)
00158 {
00159 result[r++] = buffer[i];
00160 }
00161 }
00162
00163 result[r++] = '\0';
00164 DIALOG_ASSERT(r < 15);
00165
00166 return result;
00167 }
00168
00169 fixed fixed::operator*(fixed b)
00170 {
00171 return fixed(true, fixed_internal_mult(m_nVal, b.m_nVal));
00172 }
00173
00174 fixed fixed::operator/(fixed b)
00175 {
00176 return fixed(true, fixed_internal_div(m_nVal, b.m_nVal));
00177 }
00178
00179 fixed fixed::operator*=(fixed b)
00180 {
00181 m_nVal = fixed_internal_mult(m_nVal, b.m_nVal);
00182 return *this;
00183 }
00184
00185 fixed fixed::operator/=(fixed b)
00186 {
00187 m_nVal = fixed_internal_div(m_nVal, b.m_nVal);
00188 return *this;
00189 }
00190
00191 #define sqrt_step(shift) \
00192 if((0x40000000l >> shift) + root <= value) \
00193 { \
00194 value -= (0x40000000l >> shift) + root; \
00195 root = (root >> 1) | (0x40000000l >> shift); \
00196 } \
00197 else \
00198 { \
00199 root = root >> 1; \
00200 }
00201
00202 static int iSqrt(int value)
00203 {
00204 int root = 0;
00205
00206 sqrt_step( 0);
00207 sqrt_step( 2);
00208 sqrt_step( 4);
00209 sqrt_step( 6);
00210 sqrt_step( 8);
00211 sqrt_step(10);
00212 sqrt_step(12);
00213 sqrt_step(14);
00214 sqrt_step(16);
00215 sqrt_step(18);
00216 sqrt_step(20);
00217 sqrt_step(22);
00218 sqrt_step(24);
00219 sqrt_step(26);
00220 sqrt_step(28);
00221 sqrt_step(30);
00222
00223
00224
00225 if(root < value)
00226 {
00227 ++root;
00228 }
00229
00230 return root;
00231 }
00232
00233 fixed absx( fixed p_Base )
00234 {
00235 if( p_Base < fixed(0) ) return -p_Base;
00236 return p_Base;
00237 }
00238
00239
00240
00241
00242
00243
00244
00245 static fixed iLog2( fixed p_Base )
00246 {
00247 fixed w = 0;
00248 fixed y = 0;
00249 fixed z = 0;
00250 fixed num = 1;
00251 fixed dec = 0;
00252
00253 if( p_Base == fixed(1) )
00254 return 0;
00255
00256 for( dec=fixed(0) ; absx( p_Base ) >= fixed(2) ; ++dec )
00257 p_Base /= XLN_E;
00258
00259 p_Base -= fixed(1);
00260 z = p_Base;
00261 y = p_Base;
00262 w = 1;
00263
00264 while( y != y + w )
00265 y += ( w = ( z = fixed(0) - ( z * p_Base ) ) / ( fixed(num) += fixed(1) ) );
00266
00267 return y + fixed(dec);
00268 }
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279 static fixed iExp2(fixed p_Base)
00280 {
00281 fixed w;
00282 fixed y;
00283 fixed num;
00284
00285 for( w=fixed(1), y=fixed(1), num=fixed(1) ; y != y+w ; ++num )
00286 y += ( w *= p_Base / fixed(num) );
00287
00288 return y;
00289 }
00290
00291 static fixed ipow( fixed p_Base, fixed p_Power )
00292 {
00293 if( p_Base < fixed(0) && p_Power%2 != fixed(0) )
00294 return - iExp2( (p_Power * iLog2( -p_Base )) );
00295 else
00296 return iExp2( (p_Power * iLog2(absx( p_Base ))) );
00297 }
00298
00299 static fixed ilog10( fixed p_Base )
00300 {
00301 return iLog2( p_Base ) / XLN_10;
00302 }
00303
00304 fixed fixed::sqrt()
00305 {
00306 int val = iSqrt(m_nVal);
00307 val *= 100;
00308 return fixed(true, val);
00309 }
00310
00311 fixed sqrtx(fixed fixedVal)
00312 {
00313 return fixedVal.sqrt();
00314 }
00315
00316 fixed fixed::pow(fixed fixedPower)
00317 {
00318 return ipow(*this, fixedPower);
00319 }
00320
00321 fixed powx(fixed fixedVal, fixed fixedPower)
00322 {
00323 return fixedVal.pow(fixedPower);
00324 }
00325
00326 fixed fixed::exp()
00327 {
00328 return iExp2(*this);
00329 }
00330
00331 fixed expx(fixed fixedVal)
00332 {
00333 return fixedVal.exp();
00334 }
00335
00336 fixed fixed::log10()
00337 {
00338 return ilog10(*this);
00339 }
00340
00341 fixed log10x(fixed fixedVal)
00342 {
00343 return fixedVal.log10();
00344 }
00345
00346 fixed fixed::log()
00347 {
00348 return iLog2(*this);
00349
00350
00351
00352
00353
00354
00355 }
00356
00357 fixed logx(fixed fixedVal)
00358 {
00359 return fixedVal.log();
00360 }
00361
00362 fixed floorx(fixed fixedVal)
00363 {
00364 return fixedVal.floor();
00365 }
00366
00367 fixed ceilx(fixed fixedVal)
00368 {
00369 return fixedVal.ceil();
00370 }
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380 static fixed _sinx(fixed x)
00381 {
00382 fixed xpwr;
00383 int xftl;
00384 fixed xresult;
00385 bool positive;
00386
00387 xresult = 0;
00388 xpwr = x;
00389 xftl = 1;
00390 positive = true;
00391
00392
00393 for(int i = 1; i < 7; i+=2)
00394 {
00395 if( positive )
00396 xresult += (xpwr/fixed(xftl));
00397 else
00398 xresult -= (xpwr/fixed(xftl));
00399
00400 xpwr *= x;
00401 xpwr *= x;
00402 xftl *= i+1;
00403 xftl *= i+2;
00404 positive = !positive;
00405 }
00406
00407 return xresult;
00408 }
00409
00410 fixed fixed::sin()
00411 {
00412 fixed xresult;
00413 bool bBottom = false;
00414 static fixed xPI = XPI;
00415 static fixed x2PI = X2PI;
00416 static fixed xPIO2 = XPIO2;
00417
00418 fixed x(true, m_nVal%_X2PI);
00419 if( x < fixed(0) )
00420 x += x2PI;
00421
00422 if( x > xPI )
00423 {
00424 bBottom = true;
00425 x -= xPI;
00426 }
00427
00428 if( x <= xPIO2 )
00429 xresult = _sinx(x);
00430 else
00431 xresult = _sinx(xPIO2-(x-xPIO2));
00432
00433 if( bBottom )
00434 return -xresult;
00435
00436 return xresult;
00437 }
00438
00439 fixed sinx(fixed x)
00440 {
00441 return x.sin();
00442 }
00443
00444 fixed fixed::acos()
00445 {
00446 return fixed(0);
00447 }
00448
00449 fixed fixed::cos()
00450 {
00451 fixed xresult;
00452 bool bBottom = false;
00453 static fixed xPI = XPI;
00454 static fixed x2PI = X2PI;
00455 static fixed xPIO2 = XPIO2;
00456
00457 fixed x(true, (m_nVal+_XPIO2)%_X2PI);
00458 if( x < fixed(0) )
00459 x += x2PI;
00460
00461 if( x > xPI )
00462 {
00463 bBottom = true;
00464 x -= xPI;
00465 }
00466
00467 if( x <= xPIO2 )
00468 xresult = _sinx(x);
00469 else
00470 xresult = _sinx(xPIO2-(x-xPIO2));
00471
00472 if( bBottom )
00473 return -xresult;
00474
00475 return xresult;
00476 }
00477
00478 fixed cosx(fixed x)
00479 {
00480 return x.cos();
00481 }
00482
00483 fixed fixed::tan()
00484 {
00485 return sin()/cos();
00486 }
00487
00488 fixed tanx(fixed x)
00489 {
00490 return x.tan();
00491 }
00492
00493 fixed fixed::fromFloat(float flt)
00494 {
00495 fixed result;
00496 result.m_nVal = int(flt * FIXED_RESOLUTION_FLOAT);
00497 return result;
00498 }
00499
00500 static fixed CON1(true, 2679);
00501 static fixed ROOT_3M1(true, 7321);
00502 static fixed ROOT_3(true, 17321);
00503
00504 static fixed p0 = fixed(true, -136887);
00505 static fixed p1 = fixed(true, -205058);
00506 static fixed p2 = fixed(true, -84946);
00507 static fixed p3 = fixed(true, -8375);
00508 static fixed q0 = fixed(true, 410663);
00509 static fixed q1 = fixed(true, 861573);
00510 static fixed q2 = fixed(true, 595784);
00511 static fixed q3 = fixed(true, 150240);
00512
00513 static fixed at[] =
00514 {
00515 0,
00516 fixed(true, 5235),
00517 fixed::XPIO2,
00518 fixed(true, 10472)
00519 };
00520
00521 static fixed _atanx(fixed f, int n)
00522 {
00523 fixed g, q, r;
00524
00525 if (f > CON1)
00526 {
00527 f = (((ROOT_3M1 * f - fixed(true, 5000)) - fixed(true, 5000)) + f) / (ROOT_3 + f);
00528 n++;
00529 }
00530 {
00531 g = f * f;
00532 q = (((g + q3)*g + q2)*g + q1)*g + q0;
00533 r = (((p3*g + p2)*g + p1)*g + p0)*g / q;
00534 f = f + f * r;
00535 }
00536
00537 if (n > 1) f = -f;
00538 return(f + at[n]);
00539 }
00540
00541 fixed atanx(fixed x)
00542 {
00543 fixed f = x < 0 ? -x : x;
00544 if (f > 1) f = _atanx(fixed(1) / f, 2);
00545 else f = _atanx(f, 0);
00546
00547 return(x < fixed(0) ? -f : f);
00548 }
00549
00550 fixed atan2x(fixed v, fixed u)
00551 {
00552 fixed f;
00553 fixed av = v < 0 ? -v : v;
00554 fixed au = u < 0 ? -u : u;
00555
00556 if (u != 0)
00557 {
00558 if (av > au)
00559 {
00560 if ((f = au / av) == 0) f = fixed::XPIO2;
00561 else f = _atanx(f, 2);
00562 }
00563 else
00564 {
00565 if ((f = av / au) == 0) f = 0;
00566 else f = _atanx(f, 0);
00567 }
00568 }
00569 else
00570 {
00571 if (v != 0) f = fixed::XPIO2;
00572 else
00573 {
00574
00575 f = 0;
00576 }
00577 }
00578 if (u < 0) f = fixed::XPI - f;
00579
00580 return(v < 0 ? -f : f);
00581 }