wwmath.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658
  1. /*
  2. ** Command & Conquer Generals Zero Hour(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : WWMath *
  23. * *
  24. * $Archive:: /Commando/Code/wwmath/wwmath.h $*
  25. * *
  26. * Author:: Greg Hjelstrom *
  27. * *
  28. * $Modtime:: 8/26/01 2:22p $*
  29. * *
  30. * $Revision:: 64 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #if defined(_MSC_VER)
  36. #pragma once
  37. #endif
  38. #ifndef WWMATH_H
  39. #define WWMATH_H
  40. #include "always.h"
  41. #include <math.h>
  42. #include <float.h>
  43. #include <assert.h>
  44. #include <float.h>
  45. /*
  46. ** Some global constants.
  47. */
  48. #define WWMATH_EPSILON 0.0001f
  49. #define WWMATH_EPSILON2 WWMATH_EPSILON * WWMATH_EPSILON
  50. #define WWMATH_PI 3.141592654f
  51. #define WWMATH_FLOAT_MAX (FLT_MAX)
  52. #define WWMATH_FLOAT_MIN (FLT_MIN)
  53. #define WWMATH_SQRT2 1.414213562f
  54. #define WWMATH_SQRT3 1.732050808f
  55. #define WWMATH_OOSQRT2 0.707106781f
  56. #define WWMATH_OOSQRT3 0.577350269f
  57. // (DRM 05/07/01) Temporarily eliminated _fastcall
  58. // on non-Microsoft compatible compilers. Jani
  59. // should be replacing this soon.
  60. #ifndef _MSC_VER
  61. #define __fastcall
  62. #endif // _MSC_VER
  63. /*
  64. ** Macros to convert between degrees and radians
  65. */
  66. #ifndef RAD_TO_DEG
  67. #define RAD_TO_DEG(x) (((double)x)*180.0/WWMATH_PI)
  68. #endif
  69. #ifndef DEG_TO_RAD
  70. #define DEG_TO_RAD(x) (((double)x)*WWMATH_PI/180.0)
  71. #endif
  72. #ifndef RAD_TO_DEGF
  73. #define RAD_TO_DEGF(x) (((float)x)*180.0f/WWMATH_PI)
  74. #endif
  75. #ifndef DEG_TO_RADF
  76. #define DEG_TO_RADF(x) (((float)x)*WWMATH_PI/180.0f)
  77. #endif
  78. const int ARC_TABLE_SIZE=1024;
  79. const int SIN_TABLE_SIZE=1024;
  80. extern float _FastAcosTable[ARC_TABLE_SIZE];
  81. extern float _FastAsinTable[ARC_TABLE_SIZE];
  82. extern float _FastSinTable[SIN_TABLE_SIZE];
  83. extern float _FastInvSinTable[SIN_TABLE_SIZE];
  84. /*
  85. ** Some simple math functions which work on the built-in types.
  86. ** Include the various other header files in the WWMATH library
  87. ** in order to get matrices, quaternions, etc.
  88. */
  89. class WWMath
  90. {
  91. public:
  92. // Initialization and Shutdown. Other math sub-systems which require initialization and
  93. // shutdown processing will be handled in these functions
  94. static void Init(void);
  95. static void Shutdown(void);
  96. // These are meant to be a collection of small math utility functions to be optimized at some point.
  97. static WWINLINE float Fabs(float val)
  98. {
  99. int value=*(int*)&val;
  100. value&=0x7fffffff;
  101. return *(float*)&value;
  102. }
  103. static WWINLINE int Float_To_Int_Chop(const float& f);
  104. static WWINLINE int Float_To_Int_Floor(const float& f);
  105. #if defined(_MSC_VER) && defined(_M_IX86)
  106. static WWINLINE float Cos(float val);
  107. static WWINLINE float Sin(float val);
  108. static WWINLINE float Sqrt(float val);
  109. static float __fastcall Inv_Sqrt(float a); // Some 30% faster inverse square root than regular C++ compiled, from Intel's math library
  110. static WWINLINE long Float_To_Long(float f);
  111. #else
  112. static float Cos(float val);
  113. static float Sin(float val);
  114. static float Sqrt(float val);
  115. static float Inv_Sqrt(float a);
  116. static long Float_To_Long(float f);
  117. #endif
  118. static WWINLINE float Fast_Sin(float val);
  119. static WWINLINE float Fast_Inv_Sin(float val);
  120. static WWINLINE float Fast_Cos(float val);
  121. static WWINLINE float Fast_Inv_Cos(float val);
  122. static WWINLINE float Fast_Acos(float val);
  123. static WWINLINE float Acos(float val);
  124. static WWINLINE float Fast_Asin(float val);
  125. static WWINLINE float Asin(float val);
  126. static float Atan(float x) { return static_cast<float>(atan(x)); }
  127. static float Atan2(float y,float x) { return static_cast<float>(atan2(y,x)); }
  128. static float Sign(float val);
  129. static float Ceil(float val) { return ceilf(val); }
  130. static float Floor(float val) { return floorf(val); }
  131. static bool Fast_Is_Float_Positive(const float & val);
  132. static bool Is_Power_Of_2(const unsigned int val);
  133. static float Random_Float(void);
  134. static float Random_Float(float min,float max);
  135. static float Clamp(float val, float min = 0.0f, float max = 1.0f);
  136. static double Clamp(double val, double min = 0.0f, double max = 1.0f);
  137. static int Clamp_Int(int val, int min_val, int max_val);
  138. static float Wrap(float val, float min = 0.0f, float max = 1.0f);
  139. static double Wrap(double val, double min = 0.0f, double max = 1.0f);
  140. static float Min(float a, float b);
  141. static float Max(float a, float b);
  142. static int Float_As_Int(const float f) { return *((int*)&f); }
  143. static float Lerp(float a, float b, float lerp );
  144. static double Lerp(double a, double b, float lerp );
  145. static long Float_To_Long(double f);
  146. static unsigned char Unit_Float_To_Byte(float f) { return (unsigned char)(f*255.0f); }
  147. static float Byte_To_Unit_Float(unsigned char byte) { return ((float)byte) / 255.0f; }
  148. static bool Is_Valid_Float(float x);
  149. static bool Is_Valid_Double(double x);
  150. };
  151. WWINLINE float WWMath::Sign(float val)
  152. {
  153. if (val > 0.0f) {
  154. return +1.0f;
  155. }
  156. if (val < 0.0f) {
  157. return -1.0f;
  158. }
  159. return 0.0f;
  160. }
  161. WWINLINE bool WWMath::Fast_Is_Float_Positive(const float & val)
  162. {
  163. return !((*(int *)(&val)) & 0x80000000);
  164. }
  165. WWINLINE bool WWMath::Is_Power_Of_2(const unsigned int val)
  166. {
  167. return !((val)&val-1);
  168. }
  169. WWINLINE float WWMath::Random_Float(float min,float max)
  170. {
  171. return Random_Float() * (max-min) + min;
  172. }
  173. WWINLINE float WWMath::Clamp(float val, float min /*= 0.0f*/, float max /*= 1.0f*/)
  174. {
  175. if(val < min) return min;
  176. if(val > max) return max;
  177. return val;
  178. }
  179. WWINLINE double WWMath::Clamp(double val, double min /*= 0.0f*/, double max /*= 1.0f*/)
  180. {
  181. if(val < min) return min;
  182. if(val > max) return max;
  183. return val;
  184. }
  185. WWINLINE int WWMath::Clamp_Int(int val, int min_val, int max_val)
  186. {
  187. if(val < min_val) return min_val;
  188. if(val > max_val) return max_val;
  189. return val;
  190. }
  191. WWINLINE float WWMath::Wrap(float val, float min /*= 0.0f*/, float max /*= 1.0f*/)
  192. {
  193. // Implemented as an if rather than a while, to long loops
  194. if ( val >= max ) val -= (max-min);
  195. if ( val < min ) val += (max-min);
  196. if ( val < min ) {
  197. val = min;
  198. }
  199. if ( val > max ) {
  200. val = max;
  201. }
  202. return val;
  203. }
  204. WWINLINE double WWMath::Wrap(double val, double min /*= 0.0f*/, double max /*= 1.0f*/)
  205. {
  206. // Implemented as an if rather than a while, to long loops
  207. if ( val >= max ) val -= (max-min);
  208. if ( val < min ) val += (max-min);
  209. if ( val < min ) {
  210. val = min;
  211. }
  212. if ( val > max ) {
  213. val = max;
  214. }
  215. return val;
  216. }
  217. WWINLINE float WWMath::Min(float a, float b)
  218. {
  219. if (a<b) return a;
  220. return b;
  221. }
  222. WWINLINE float WWMath::Max(float a, float b)
  223. {
  224. if (a>b) return a;
  225. return b;
  226. }
  227. WWINLINE float WWMath::Lerp(float a, float b, float lerp )
  228. {
  229. return (a + (b - a)*lerp);
  230. }
  231. WWINLINE double WWMath::Lerp(double a, double b, float lerp )
  232. {
  233. return (a + (b - a)*lerp);
  234. }
  235. WWINLINE bool WWMath::Is_Valid_Float(float x)
  236. {
  237. unsigned long * plong = (unsigned long *)(&x);
  238. unsigned long exponent = ((*plong) & 0x7F800000) >> (32-9);
  239. // if exponent is 0xFF, this is a NAN
  240. if (exponent == 0xFF) {
  241. return false;
  242. }
  243. return true;
  244. }
  245. WWINLINE bool WWMath::Is_Valid_Double(double x)
  246. {
  247. unsigned long * plong = (unsigned long *)(&x) + 1;
  248. unsigned long exponent = ((*plong) & 0x7FF00000) >> (32-12);
  249. // if exponent is 0x7FF, this is a NAN
  250. if (exponent == 0x7FF) {
  251. return false;
  252. }
  253. return true;
  254. }
  255. // ----------------------------------------------------------------------------
  256. // Float to long
  257. // ----------------------------------------------------------------------------
  258. #if defined(_MSC_VER) && defined(_M_IX86)
  259. WWINLINE long WWMath::Float_To_Long(float f)
  260. {
  261. long i;
  262. __asm {
  263. fld [f]
  264. fistp [i]
  265. }
  266. return i;
  267. }
  268. #else
  269. WWINLINE long WWMath::Float_To_Long(float f)
  270. {
  271. return (long) f;
  272. }
  273. #endif
  274. WWINLINE long WWMath::Float_To_Long(double f)
  275. {
  276. #if defined(_MSC_VER) && defined(_M_IX86)
  277. long retval;
  278. __asm fld qword ptr [f]
  279. __asm fistp dword ptr [retval]
  280. return retval;
  281. #else
  282. return (long) f;
  283. #endif
  284. }
  285. // ----------------------------------------------------------------------------
  286. // Cos
  287. // ----------------------------------------------------------------------------
  288. #if defined(_MSC_VER) && defined(_M_IX86)
  289. WWINLINE float WWMath::Cos(float val)
  290. {
  291. float retval;
  292. __asm {
  293. fld [val]
  294. fcos
  295. fstp [retval]
  296. }
  297. return retval;
  298. }
  299. #else
  300. WWINLINE float WWMath::Cos(float val)
  301. {
  302. return cosf(val);
  303. }
  304. #endif
  305. // ----------------------------------------------------------------------------
  306. // Sin
  307. // ----------------------------------------------------------------------------
  308. #if defined(_MSC_VER) && defined(_M_IX86)
  309. WWINLINE float WWMath::Sin(float val)
  310. {
  311. float retval;
  312. __asm {
  313. fld [val]
  314. fsin
  315. fstp [retval]
  316. }
  317. return retval;
  318. }
  319. #else
  320. WWINLINE float WWMath::Sin(float val)
  321. {
  322. return sinf(val);
  323. }
  324. #endif
  325. // ----------------------------------------------------------------------------
  326. // Fast, table based sin
  327. // ----------------------------------------------------------------------------
  328. WWINLINE float WWMath::Fast_Sin(float val)
  329. {
  330. val*=float(SIN_TABLE_SIZE) / (2.0f * WWMATH_PI);
  331. int idx0=Float_To_Int_Floor(val);
  332. int idx1=idx0+1;
  333. float frac=val-(float)idx0;
  334. idx0 = ((unsigned)idx0) & (SIN_TABLE_SIZE-1);
  335. idx1 = ((unsigned)idx1) & (SIN_TABLE_SIZE-1);
  336. return (1.0f - frac) * _FastSinTable[idx0] + frac * _FastSinTable[idx1];
  337. }
  338. // ----------------------------------------------------------------------------
  339. // Fast, table based 1.0f/sin
  340. // ----------------------------------------------------------------------------
  341. WWINLINE float WWMath::Fast_Inv_Sin(float val)
  342. {
  343. #if 0 // TODO: more testing, not reliable!
  344. float index = val * float(SIN_TABLE_SIZE) / (2.0f * WWMATH_PI);
  345. int idx0=Float_To_Int_Floor(index);
  346. int idx1=idx0+1;
  347. float frac=val-(float)idx0;
  348. idx0 = ((unsigned)idx0) & (SIN_TABLE_SIZE-1);
  349. idx1 = ((unsigned)idx1) & (SIN_TABLE_SIZE-1);
  350. // The table becomes inaccurate near 0 and 2pi so fall back to doing a divide.
  351. const int BUFFER = 16;
  352. if ((idx0 <= BUFFER) || (idx0 >= SIN_TABLE_SIZE-BUFFER-1)) {
  353. return 1.0f / WWMath::Fast_Sin(val);
  354. } else {
  355. return (1.0f - frac) * _FastInvSinTable[idx0] + frac * _FastInvSinTable[idx1];
  356. }
  357. #else
  358. return 1.0f / WWMath::Fast_Sin(val);
  359. #endif
  360. }
  361. // ----------------------------------------------------------------------------
  362. // Fast, table based cos
  363. // ----------------------------------------------------------------------------
  364. WWINLINE float WWMath::Fast_Cos(float val)
  365. {
  366. val+=(WWMATH_PI * 0.5f);
  367. val*=float(SIN_TABLE_SIZE) / (2.0f * WWMATH_PI);
  368. int idx0=Float_To_Int_Floor(val);
  369. int idx1=idx0+1;
  370. float frac=val-(float)idx0;
  371. idx0 = ((unsigned)idx0) & (SIN_TABLE_SIZE-1);
  372. idx1 = ((unsigned)idx1) & (SIN_TABLE_SIZE-1);
  373. return (1.0f - frac) * _FastSinTable[idx0] + frac * _FastSinTable[idx1];
  374. }
  375. // ----------------------------------------------------------------------------
  376. // Fast, table based 1.0f/cos
  377. // ----------------------------------------------------------------------------
  378. WWINLINE float WWMath::Fast_Inv_Cos(float val)
  379. {
  380. #if 0 // TODO: more testing, not reliable!
  381. float index = val + (WWMATH_PI * 0.5f);
  382. index *= float(SIN_TABLE_SIZE) / (2.0f * WWMATH_PI);
  383. int idx0=Float_To_Int_Chop(index);
  384. int idx1=idx0+1;
  385. float frac=val-(float)idx0;
  386. idx0 = ((unsigned)idx0) & (SIN_TABLE_SIZE-1);
  387. idx1 = ((unsigned)idx1) & (SIN_TABLE_SIZE-1);
  388. // The table becomes inaccurate near 0 and 2pi so fall back to doing a divide.
  389. if ((idx0 <= 2) || (idx0 >= SIN_TABLE_SIZE-3)) {
  390. return 1.0f / WWMath::Fast_Cos(val);
  391. } else {
  392. return (1.0f - frac) * _FastInvSinTable[idx0] + frac * _FastInvSinTable[idx1];
  393. }
  394. #else
  395. return 1.0f / WWMath::Fast_Cos(val);
  396. #endif
  397. }
  398. // ----------------------------------------------------------------------------
  399. // Fast, table based arc cos
  400. // ----------------------------------------------------------------------------
  401. WWINLINE float WWMath::Fast_Acos(float val)
  402. {
  403. // Near -1 and +1, the table becomes too inaccurate
  404. if (WWMath::Fabs(val) > 0.975f) {
  405. return WWMath::Acos(val);
  406. }
  407. val*=float(ARC_TABLE_SIZE/2);
  408. int idx0=Float_To_Int_Floor(val);
  409. int idx1=idx0+1;
  410. float frac=val-(float)idx0;
  411. idx0+=ARC_TABLE_SIZE/2;
  412. idx1+=ARC_TABLE_SIZE/2;
  413. // we dont even get close to the edge of the table...
  414. assert((idx0 >= 0) && (idx0 < ARC_TABLE_SIZE));
  415. assert((idx1 >= 0) && (idx1 < ARC_TABLE_SIZE));
  416. // compute and return the interpolated value
  417. return (1.0f - frac) * _FastAcosTable[idx0] + frac * _FastAcosTable[idx1];
  418. }
  419. // ----------------------------------------------------------------------------
  420. // Arc cos
  421. // ----------------------------------------------------------------------------
  422. WWINLINE float WWMath::Acos(float val)
  423. {
  424. return (float)acos(val);
  425. }
  426. // ----------------------------------------------------------------------------
  427. // Fast, table based arc sin
  428. // ----------------------------------------------------------------------------
  429. WWINLINE float WWMath::Fast_Asin(float val)
  430. {
  431. // Near -1 and +1, the table becomes too inaccurate
  432. if (WWMath::Fabs(val) > 0.975f) {
  433. return WWMath::Asin(val);
  434. }
  435. val*=float(ARC_TABLE_SIZE/2);
  436. int idx0=Float_To_Int_Floor(val);
  437. int idx1=idx0+1;
  438. float frac=val-(float)idx0;
  439. idx0+=ARC_TABLE_SIZE/2;
  440. idx1+=ARC_TABLE_SIZE/2;
  441. // we dont even get close to the edge of the table...
  442. assert((idx0 >= 0) && (idx0 < ARC_TABLE_SIZE));
  443. assert((idx1 >= 0) && (idx1 < ARC_TABLE_SIZE));
  444. // compute and return the interpolated value
  445. return (1.0f - frac) * _FastAsinTable[idx0] + frac * _FastAsinTable[idx1];
  446. }
  447. // ----------------------------------------------------------------------------
  448. // Arc sin
  449. // ----------------------------------------------------------------------------
  450. WWINLINE float WWMath::Asin(float val)
  451. {
  452. return (float)asin(val);
  453. }
  454. // ----------------------------------------------------------------------------
  455. // Sqrt
  456. // ----------------------------------------------------------------------------
  457. #if defined(_MSC_VER) && defined(_M_IX86)
  458. WWINLINE float WWMath::Sqrt(float val)
  459. {
  460. float retval;
  461. __asm {
  462. fld [val]
  463. fsqrt
  464. fstp [retval]
  465. }
  466. return retval;
  467. }
  468. #else
  469. WWINLINE float WWMath::Sqrt(float val)
  470. {
  471. return (float)sqrt(val);
  472. }
  473. #endif
  474. WWINLINE int WWMath::Float_To_Int_Chop(const float& f)
  475. {
  476. int a = *reinterpret_cast<const int*>(&f); // take bit pattern of float into a register
  477. int sign = (a>>31); // sign = 0xFFFFFFFF if original value is negative, 0 if positive
  478. int mantissa = (a&((1<<23)-1))|(1<<23); // extract mantissa and add the hidden bit
  479. int exponent = ((a&0x7fffffff)>>23)-127; // extract the exponent
  480. int r = ((unsigned int)(mantissa)<<8)>>(31-exponent); // ((1<<exponent)*mantissa)>>24 -- (we know that mantissa > (1<<24))
  481. return ((r ^ (sign)) - sign ) &~ (exponent>>31); // add original sign. If exponent was negative, make return value 0.
  482. }
  483. WWINLINE int WWMath::Float_To_Int_Floor (const float& f)
  484. {
  485. int a = *reinterpret_cast<const int*>(&f); // take bit pattern of float into a register
  486. int sign = (a>>31); // sign = 0xFFFFFFFF if original value is negative, 0 if positive
  487. a&=0x7fffffff; // we don't need the sign any more
  488. int exponent = (a>>23)-127; // extract the exponent
  489. int expsign = ~(exponent>>31); // 0xFFFFFFFF if exponent is positive, 0 otherwise
  490. int imask = ( (1<<(31-(exponent))))-1; // mask for true integer values
  491. int mantissa = (a&((1<<23)-1)); // extract mantissa (without the hidden bit)
  492. int r = ((unsigned int)(mantissa|(1<<23))<<8)>>(31-exponent); // ((1<<exponent)*(mantissa|hidden bit))>>24 -- (we know that mantissa > (1<<24))
  493. r = ((r & expsign) ^ (sign)) + ((!((mantissa<<8)&imask)&(expsign^((a-1)>>31)))&sign); // if (fabs(value)<1.0) value = 0; copy sign; if (value < 0 && value==(int)(value)) value++;
  494. return r;
  495. }
  496. // ----------------------------------------------------------------------------
  497. // Inverse square root
  498. // ----------------------------------------------------------------------------
  499. #if defined(_MSC_VER) && defined(_M_IX86)
  500. WWINLINE __declspec(naked) float __fastcall WWMath::Inv_Sqrt(float a)
  501. {
  502. __asm {
  503. mov eax, 0be6eb508h
  504. mov DWORD PTR [esp-12],03fc00000h ; 1.5 on the stack
  505. sub eax, DWORD PTR [esp+4]; a
  506. sub DWORD PTR [esp+4], 800000h ; a/2 a=Y0
  507. shr eax, 1 ; firs approx in eax=R0
  508. mov DWORD PTR [esp-8], eax
  509. fld DWORD PTR [esp-8] ;r
  510. fmul st, st ;r*r
  511. fld DWORD PTR [esp-8] ;r
  512. fxch st(1)
  513. fmul DWORD PTR [esp+4];a ;r*r*y0
  514. fld DWORD PTR [esp-12];load 1.5
  515. fld st(0)
  516. fsub st,st(2) ;r1 = 1.5 - y1
  517. ;x1 = st(3)
  518. ;y1 = st(2)
  519. ;1.5 = st(1)
  520. ;r1 = st(0)
  521. fld st(1)
  522. fxch st(1)
  523. fmul st(3),st ; y2=y1*r1*...
  524. fmul st(3),st ; y2=y1*r1*r1
  525. fmulp st(4),st ; x2=x1*r1
  526. fsub st,st(2) ; r2=1.5-y2
  527. ;x2=st(3)
  528. ;y2=st(2)
  529. ;1.5=st(1)
  530. ;r2 = st(0)
  531. fmul st(2),st ;y3=y2*r2*...
  532. fmul st(3),st ;x3=x2*r2
  533. fmulp st(2),st ;y3=y2*r2*r2
  534. fxch st(1)
  535. fsubp st(1),st ;r3= 1.5 - y3
  536. ;x3 = st(1)
  537. ;r3 = st(0)
  538. fmulp st(1), st
  539. ret 4
  540. }
  541. }
  542. #else
  543. WWINLINE float WWMath::Inv_Sqrt(float val)
  544. {
  545. return 1.0f / (float)sqrt(val);
  546. }
  547. #endif
  548. #endif