Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

450 lines
6.1 KiB

  1. // Copyright (c) 1996-1999 Microsoft Corporation
  2. #ifdef DMSYNTH_MINIPORT
  3. #include "common.h"
  4. #else
  5. #include "simple.h"
  6. #include "float.h"
  7. #endif
  8. #ifdef _ALPHA_
  9. #include <math.h>
  10. #endif // _ALPHA_
  11. #ifndef _ALPHA_
  12. #ifndef DBG
  13. extern "C" int _fltused = 1;
  14. #endif
  15. // asm_fsave(rgbState)
  16. //
  17. // Store the floating point state into <rgbState> and reinitialize the FPU.
  18. //
  19. void __cdecl asm_fsave(char *rgbState)
  20. {
  21. _asm
  22. {
  23. mov eax, dword ptr rgbState
  24. fsave [eax]
  25. }
  26. }
  27. // asm_frestore(rgbState)
  28. //
  29. // Restore a previously saved floating point state <rgbState>.
  30. //
  31. void __cdecl asm_frestore(const char *rgbState)
  32. {
  33. _asm
  34. {
  35. fwait
  36. mov eax, dword ptr rgbState
  37. frstor [eax]
  38. }
  39. }
  40. // FLOATSAFE
  41. //
  42. // Saves floating point state on construction and restores on destruction.
  43. //
  44. struct FLOATSAFE
  45. {
  46. char m_rgbState[105];
  47. FLOATSAFE::FLOATSAFE(void)
  48. {
  49. asm_fsave(m_rgbState);
  50. }
  51. FLOATSAFE::~FLOATSAFE(void)
  52. {
  53. asm_frestore(m_rgbState);
  54. }
  55. };
  56. // asm_fdiv()
  57. //
  58. float __cdecl asm_fdiv(float flNum, float flDenom)
  59. {
  60. float flResult = (float) 0.0;
  61. if (flDenom != (float) 0.0)
  62. {
  63. _asm
  64. {
  65. fld flNum
  66. fdiv flDenom
  67. fstp flResult
  68. fnclex ; clear the status word of exceptions
  69. }
  70. }
  71. return(flResult);
  72. }
  73. // asm__fsin()
  74. //
  75. float __cdecl asm_fsin(float flRad)
  76. {
  77. float flSine;
  78. _asm
  79. {
  80. fld flRad
  81. fsin
  82. fstp flSine
  83. fnclex ; clear the status word of exceptions
  84. }
  85. return(flSine);
  86. }
  87. // asm__fcos()
  88. //
  89. float __cdecl asm_fcos(float flRad)
  90. {
  91. float flCosine;
  92. _asm
  93. {
  94. fld flRad
  95. fcos
  96. fstp flCosine
  97. fnclex ; clear the status word of exceptions
  98. }
  99. return(flCosine);
  100. }
  101. // asm_flog2()
  102. //
  103. float __cdecl asm_flog2(float flX)
  104. {
  105. float flLog;
  106. _asm
  107. {
  108. fld1
  109. fld flX
  110. fyl2X
  111. fstp flLog;
  112. fnclex ; clear the status word of exceptions
  113. }
  114. return flLog;
  115. }
  116. // asm_ftol()
  117. //
  118. long __cdecl asm_ftol(float flX)
  119. {
  120. long lResult;
  121. WORD wCW;
  122. WORD wNewCW;
  123. _asm
  124. {
  125. fld flX // Push the float onto the stack
  126. wait
  127. fnstcw wCW // Store the control word
  128. wait
  129. mov ax,wCW // Setup our rounding
  130. or ah,0x0c
  131. mov wNewCW,ax
  132. fldcw wNewCW // Set Control word to our new value
  133. fistp lResult // Round off top of stack into result
  134. fldcw wCW // Restore control word
  135. fnclex // clear the status word of exceptions
  136. }
  137. return(lResult);
  138. }
  139. // asm_fpow()
  140. //
  141. float __cdecl asm_fpow(float flX, float flY)
  142. {
  143. float flHalf = (float) 0.5;
  144. float flOne = (float) 1.0;
  145. float flResult = (float) 0.0;
  146. if (flX == (float) 0.0 && flY > (float) 0.0)
  147. {
  148. flResult = (float) 0.0;
  149. }
  150. else if (flX == (float) 0.0 && flY <= (float) 0.0)
  151. {
  152. flResult = (float) 1.0;
  153. }
  154. else if (flY == (float) 0.0)
  155. {
  156. flResult = (float) 1.0;
  157. }
  158. else
  159. {
  160. BOOL fNeg = FALSE;
  161. // Ok, if X is negative the sign is positive if the Y is even
  162. // and negative if Y is odd. Fractions can't be done.
  163. if (flX < (float) 0.0)
  164. {
  165. long lY = asm_ftol(flY);
  166. if ((float) lY == flY) // Only fix it if we have a integer poer
  167. {
  168. flX = -flX;
  169. if (lY % 2)
  170. {
  171. fNeg = TRUE;
  172. }
  173. }
  174. }
  175. flX = flY * asm_flog2(flX);
  176. if (max(-flX,flX) < flOne)
  177. // Is the power is in the range which F2XM1 can handle?
  178. {
  179. _asm
  180. {
  181. fld flX // Put flX in ST[0]
  182. f2xm1 // ST := 2^ST - 1
  183. fadd flOne // ST := 2^mantissa
  184. fstp flResult // Store result
  185. fnclex // clear the status word of exceptions
  186. }
  187. }
  188. else // Nope, we've got to scale first
  189. {
  190. _asm
  191. {
  192. fld flX // Put flX in ST[0]
  193. fld ST // Duplicate ST
  194. frndint // Integral value in ST
  195. fsub ST(1),ST // Fractional value in ST(1)
  196. fxch // Factional value in ST
  197. f2xm1 // ST := 2^ST - 1
  198. fadd flOne // ST := 2^frac
  199. fscale // ST := 2^frac * 2^integral
  200. fstp flResult // Store result
  201. fnclex // clear the status word of exceptions
  202. }
  203. }
  204. if (fNeg)
  205. {
  206. flResult = -flResult;
  207. }
  208. }
  209. return flResult;
  210. }
  211. #endif // _ALPHA_
  212. // fp_ftol()
  213. //
  214. STDAPI_(long) fp_ftol(float flX)
  215. {
  216. #ifdef _ALPHA_
  217. return (long)flX;
  218. #else
  219. FLOATSAFE fs;
  220. return(asm_ftol(flX));
  221. #endif
  222. }
  223. // fp_ltof()
  224. //
  225. STDAPI_(float) fp_ltof(long lx)
  226. {
  227. #ifndef _ALPHA_
  228. FLOATSAFE fs;
  229. #endif
  230. return(float(lx));
  231. }
  232. // fp_fadd()
  233. //
  234. STDAPI_(float) fp_fadd(float flX, float flY)
  235. {
  236. #ifndef _ALPHA_
  237. FLOATSAFE fs;
  238. #endif
  239. return(flX + flY);
  240. }
  241. // fp_fsub()
  242. //
  243. STDAPI_(float) fp_fsub(float flX, float flY)
  244. {
  245. #ifndef _ALPHA_
  246. FLOATSAFE fs;
  247. #endif
  248. return(flX - flY);
  249. }
  250. // fp_fmul()
  251. //
  252. STDAPI_(float) fp_fmul(float flX, float flY)
  253. {
  254. #ifndef _ALPHA_
  255. FLOATSAFE fs;
  256. #endif
  257. return(flX * flY);
  258. }
  259. // fp_fdiv()
  260. //
  261. STDAPI_(float) fp_fdiv(float flNum, float flDenom)
  262. {
  263. #ifdef _ALPHA_
  264. return flNum/flDenom;
  265. #else
  266. FLOATSAFE fs;
  267. return(asm_fdiv(flNum,flDenom));
  268. #endif
  269. }
  270. // fp_fabs()
  271. //
  272. STDAPI_(float) fp_fabs(float flX)
  273. {
  274. #ifndef _ALPHA_
  275. FLOATSAFE fs;
  276. #endif
  277. return max(-flX,flX);
  278. }
  279. // fp_fsin()
  280. //
  281. STDAPI_(float) fp_fsin(float flRad)
  282. {
  283. #ifdef _ALPHA_
  284. return sin(flRad);
  285. #else
  286. FLOATSAFE fs;
  287. return(asm_fsin(flRad));
  288. #endif
  289. }
  290. // fp_fcos()
  291. //
  292. STDAPI_(float) fp_fcos(float flRad)
  293. {
  294. #ifdef _ALPHA_
  295. return cos(flRad);
  296. #else
  297. FLOATSAFE fs;
  298. return(asm_fcos(flRad));
  299. #endif
  300. }
  301. // fp_fpow()
  302. //
  303. STDAPI_(float) fp_fpow(float flX, float flY)
  304. {
  305. #ifdef _ALPHA_
  306. return pow(flX, flY);
  307. #else
  308. FLOATSAFE fs;
  309. return(asm_fpow(flX,flY));
  310. #endif
  311. }
  312. // fp_flog2()
  313. //
  314. STDAPI_(float) fp_flog2(float flX)
  315. {
  316. #ifdef _ALPHA_
  317. return log(flX);
  318. #else
  319. FLOATSAFE fs;
  320. return(asm_flog2(flX));
  321. #endif
  322. }
  323. // fp_flog10()
  324. //
  325. STDAPI_(float) fp_flog10(float flX)
  326. {
  327. #ifdef _ALPHA_
  328. return log10(flX);
  329. #else
  330. FLOATSAFE fs;
  331. #define LOG2OF10 float(3.321928094887)
  332. return(asm_fdiv(asm_flog2(flX),LOG2OF10));
  333. #endif
  334. }
  335. // fp_fchs()
  336. //
  337. STDAPI_(float) fp_fchs(float flX)
  338. {
  339. #ifndef _ALPHA_
  340. FLOATSAFE fs;
  341. #endif
  342. return(-flX);
  343. }
  344. // fp_fcmp()
  345. //
  346. STDAPI_(int) fp_fcmp(float flA, float flB)
  347. {
  348. #ifndef _ALPHA_
  349. FLOATSAFE fs;
  350. #endif
  351. if (flA > flB)
  352. return(1);
  353. if (flA < flB)
  354. return(-1);
  355. return(0);
  356. }
  357. // fp_fmin()
  358. //
  359. STDAPI_(float) fp_fmin(float flA, float flB)
  360. {
  361. #ifndef _ALPHA_
  362. FLOATSAFE fs;
  363. #endif
  364. return(min(flA,flB));
  365. }
  366. // fp_fmax()
  367. //
  368. STDAPI_(float) fp_fmax(float flA, float flB)
  369. {
  370. #ifndef _ALPHA_
  371. FLOATSAFE fs;
  372. #endif
  373. return(max(flA,flB));
  374. }