msvcrt: Fix logf implementation.
[wine.git] / dlls / msvcrt / math.c
bloba471f07f046d2983b2837f4ff36e3380cb6288ba
1 /*
2 * msvcrt.dll math functions
4 * Copyright 2000 Jon Griffiths
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 * For functions copied from musl libc (http://musl.libc.org/):
22 * ====================================================
23 * Copyright 2005-2020 Rich Felker, et al.
25 * Permission is hereby granted, free of charge, to any person obtaining
26 * a copy of this software and associated documentation files (the
27 * "Software"), to deal in the Software without restriction, including
28 * without limitation the rights to use, copy, modify, merge, publish,
29 * distribute, sublicense, and/or sell copies of the Software, and to
30 * permit persons to whom the Software is furnished to do so, subject to
31 * the following conditions:
33 * The above copyright notice and this permission notice shall be
34 * included in all copies or substantial portions of the Software.
35 * ====================================================
38 #include <complex.h>
39 #include <stdio.h>
40 #include <fenv.h>
41 #include <fpieee.h>
42 #include <limits.h>
43 #include <locale.h>
44 #include <math.h>
46 #include "msvcrt.h"
47 #include "winternl.h"
48 #include "unixlib.h"
50 #include "wine/asm.h"
51 #include "wine/debug.h"
53 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
55 #undef div
56 #undef ldiv
58 #define _DOMAIN 1 /* domain error in argument */
59 #define _SING 2 /* singularity */
60 #define _OVERFLOW 3 /* range overflow */
61 #define _UNDERFLOW 4 /* range underflow */
63 typedef int (CDECL *MSVCRT_matherr_func)(struct _exception *);
65 static MSVCRT_matherr_func MSVCRT_default_matherr_func = NULL;
67 BOOL sse2_supported;
68 static BOOL sse2_enabled;
70 static const struct unix_funcs *unix_funcs;
72 void msvcrt_init_math( void *module )
74 sse2_supported = IsProcessorFeaturePresent( PF_XMMI64_INSTRUCTIONS_AVAILABLE );
75 #if _MSVCR_VER <=71
76 sse2_enabled = FALSE;
77 #else
78 sse2_enabled = sse2_supported;
79 #endif
80 __wine_init_unix_lib( module, DLL_PROCESS_ATTACH, NULL, &unix_funcs );
83 /* Copied from musl: src/internal/libm.h */
84 static inline float fp_barrierf(float x)
86 volatile float y = x;
87 return y;
90 static inline double fp_barrier(double x)
92 volatile double y = x;
93 return y;
96 static inline double CDECL ret_nan( BOOL update_sw )
98 double x = 1.0;
99 if (!update_sw) return -NAN;
100 return (x - x) / (x - x);
103 #define SET_X87_CW(MASK) \
104 "subl $4, %esp\n\t" \
105 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") \
106 "fnstcw (%esp)\n\t" \
107 "movw (%esp), %ax\n\t" \
108 "movw %ax, 2(%esp)\n\t" \
109 "testw $" #MASK ", %ax\n\t" \
110 "jz 1f\n\t" \
111 "andw $~" #MASK ", %ax\n\t" \
112 "movw %ax, 2(%esp)\n\t" \
113 "fldcw 2(%esp)\n\t" \
114 "1:\n\t"
116 #define RESET_X87_CW \
117 "movw (%esp), %ax\n\t" \
118 "cmpw %ax, 2(%esp)\n\t" \
119 "je 1f\n\t" \
120 "fstpl 8(%esp)\n\t" \
121 "fldcw (%esp)\n\t" \
122 "fldl 8(%esp)\n\t" \
123 "fwait\n\t" \
124 "1:\n\t" \
125 "addl $4, %esp\n\t" \
126 __ASM_CFI(".cfi_adjust_cfa_offset -4\n\t")
128 /*********************************************************************
129 * _matherr (CRTDLL.@)
131 int CDECL _matherr(struct _exception *e)
133 return 0;
137 static double math_error(int type, const char *name, double arg1, double arg2, double retval)
139 struct _exception exception = {type, (char *)name, arg1, arg2, retval};
141 TRACE("(%d, %s, %g, %g, %g)\n", type, debugstr_a(name), arg1, arg2, retval);
143 if (MSVCRT_default_matherr_func && MSVCRT_default_matherr_func(&exception))
144 return exception.retval;
146 switch (type)
148 case 0:
149 /* don't set errno */
150 break;
151 case _DOMAIN:
152 *_errno() = EDOM;
153 break;
154 case _SING:
155 case _OVERFLOW:
156 *_errno() = ERANGE;
157 break;
158 case _UNDERFLOW:
159 /* don't set errno */
160 break;
161 default:
162 ERR("Unhandled math error!\n");
165 return exception.retval;
168 /*********************************************************************
169 * __setusermatherr (MSVCRT.@)
171 void CDECL __setusermatherr(MSVCRT_matherr_func func)
173 MSVCRT_default_matherr_func = func;
174 TRACE("new matherr handler %p\n", func);
177 /*********************************************************************
178 * _set_SSE2_enable (MSVCRT.@)
180 int CDECL _set_SSE2_enable(int flag)
182 sse2_enabled = flag && sse2_supported;
183 return sse2_enabled;
186 #if defined(_WIN64)
187 # if _MSVCR_VER>=140
188 /*********************************************************************
189 * _get_FMA3_enable (UCRTBASE.@)
191 int CDECL _get_FMA3_enable(void)
193 FIXME("() stub\n");
194 return 0;
196 # endif
198 # if _MSVCR_VER>=120
199 /*********************************************************************
200 * _set_FMA3_enable (MSVCR120.@)
202 int CDECL _set_FMA3_enable(int flag)
204 FIXME("(%x) stub\n", flag);
205 return 0;
207 # endif
208 #endif
210 #if !defined(__i386__) || _MSVCR_VER>=120
212 /*********************************************************************
213 * _chgsignf (MSVCRT.@)
215 float CDECL _chgsignf( float num )
217 union { float f; UINT32 i; } u = { num };
218 u.i ^= 0x80000000;
219 return u.f;
222 /*********************************************************************
223 * _copysignf (MSVCRT.@)
225 * Copied from musl: src/math/copysignf.c
227 float CDECL _copysignf( float x, float y )
229 union { float f; UINT32 i; } ux = { x }, uy = { y };
230 ux.i &= 0x7fffffff;
231 ux.i |= uy.i & 0x80000000;
232 return ux.f;
235 /*********************************************************************
236 * _nextafterf (MSVCRT.@)
238 * Copied from musl: src/math/nextafterf.c
240 float CDECL _nextafterf( float x, float y )
242 unsigned int ix = *(unsigned int*)&x;
243 unsigned int iy = *(unsigned int*)&y;
244 unsigned int ax, ay, e;
246 if (isnan(x) || isnan(y))
247 return x + y;
248 if (x == y) {
249 if (_fpclassf(y) & (_FPCLASS_ND | _FPCLASS_PD | _FPCLASS_NZ | _FPCLASS_PZ ))
250 *_errno() = ERANGE;
251 return y;
253 ax = ix & 0x7fffffff;
254 ay = iy & 0x7fffffff;
255 if (ax == 0) {
256 if (ay == 0)
257 return y;
258 ix = (iy & 0x80000000) | 1;
259 } else if (ax > ay || ((ix ^ iy) & 0x80000000))
260 ix--;
261 else
262 ix++;
263 e = ix & 0x7f800000;
264 /* raise overflow if ix is infinite and x is finite */
265 if (e == 0x7f800000) {
266 fp_barrierf(x + x);
267 *_errno() = ERANGE;
269 /* raise underflow if ix is subnormal or zero */
270 y = *(float*)&ix;
271 if (e == 0) {
272 fp_barrierf(x * x + y * y);
273 *_errno() = ERANGE;
275 return y;
278 /* Copied from musl: src/math/ilogbf.c */
279 static int __ilogbf(float x)
281 union { float f; UINT32 i; } u = { x };
282 int e = u.i >> 23 & 0xff;
284 if (!e)
286 u.i <<= 9;
287 if (u.i == 0) return FP_ILOGB0;
288 /* subnormal x */
289 for (e = -0x7f; u.i >> 31 == 0; e--, u.i <<= 1);
290 return e;
292 if (e == 0xff) return u.i << 9 ? FP_ILOGBNAN : INT_MAX;
293 return e - 0x7f;
296 /*********************************************************************
297 * _logbf (MSVCRT.@)
299 * Copied from musl: src/math/logbf.c
301 float CDECL _logbf(float x)
303 if (!isfinite(x))
304 return x * x;
305 if (x == 0) {
306 *_errno() = ERANGE;
307 return -1 / (x * x);
309 return __ilogbf(x);
312 #endif
314 /* Copied from musl: src/math/scalbn.c */
315 static double __scalbn(double x, int n)
317 union {double f; UINT64 i;} u;
318 double y = x;
320 if (n > 1023) {
321 y *= 0x1p1023;
322 n -= 1023;
323 if (n > 1023) {
324 y *= 0x1p1023;
325 n -= 1023;
326 if (n > 1023)
327 n = 1023;
329 } else if (n < -1022) {
330 /* make sure final n < -53 to avoid double
331 rounding in the subnormal range */
332 y *= 0x1p-1022 * 0x1p53;
333 n += 1022 - 53;
334 if (n < -1022) {
335 y *= 0x1p-1022 * 0x1p53;
336 n += 1022 - 53;
337 if (n < -1022)
338 n = -1022;
341 u.i = (UINT64)(0x3ff + n) << 52;
342 x = y * u.f;
343 return x;
346 /* Copied from musl: src/math/__rem_pio2_large.c */
347 static int __rem_pio2_large(double *x, double *y, int e0, int nx, int prec)
349 static const int init_jk[] = {3, 4};
350 static const INT32 ipio2[] = {
351 0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62,
352 0x95993C, 0x439041, 0xFE5163, 0xABDEBB, 0xC561B7, 0x246E3A,
353 0x424DD2, 0xE00649, 0x2EEA09, 0xD1921C, 0xFE1DEB, 0x1CB129,
354 0xA73EE8, 0x8235F5, 0x2EBB44, 0x84E99C, 0x7026B4, 0x5F7E41,
355 0x3991D6, 0x398353, 0x39F49C, 0x845F8B, 0xBDF928, 0x3B1FF8,
356 0x97FFDE, 0x05980F, 0xEF2F11, 0x8B5A0A, 0x6D1F6D, 0x367ECF,
357 0x27CB09, 0xB74F46, 0x3F669E, 0x5FEA2D, 0x7527BA, 0xC7EBE5,
358 0xF17B3D, 0x0739F7, 0x8A5292, 0xEA6BFB, 0x5FB11F, 0x8D5D08,
359 0x560330, 0x46FC7B, 0x6BABF0, 0xCFBC20, 0x9AF436, 0x1DA9E3,
360 0x91615E, 0xE61B08, 0x659985, 0x5F14A0, 0x68408D, 0xFFD880,
361 0x4D7327, 0x310606, 0x1556CA, 0x73A8C9, 0x60E27B, 0xC08C6B,
363 static const double PIo2[] = {
364 1.57079625129699707031e+00,
365 7.54978941586159635335e-08,
366 5.39030252995776476554e-15,
367 3.28200341580791294123e-22,
368 1.27065575308067607349e-29,
369 1.22933308981111328932e-36,
370 2.73370053816464559624e-44,
371 2.16741683877804819444e-51,
374 INT32 jz, jx, jv, jp, jk, carry, n, iq[20], i, j, k, m, q0, ih;
375 double z, fw, f[20], fq[20] = {0}, q[20];
377 /* initialize jk*/
378 jk = init_jk[prec];
379 jp = jk;
381 /* determine jx,jv,q0, note that 3>q0 */
382 jx = nx - 1;
383 jv = (e0 - 3) / 24;
384 if(jv < 0) jv = 0;
385 q0 = e0 - 24 * (jv + 1);
387 /* set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk] */
388 j = jv - jx;
389 m = jx + jk;
390 for (i = 0; i <= m; i++, j++)
391 f[i] = j < 0 ? 0.0 : (double)ipio2[j];
393 /* compute q[0],q[1],...q[jk] */
394 for (i = 0; i <= jk; i++) {
395 for (j = 0, fw = 0.0; j <= jx; j++)
396 fw += x[j] * f[jx + i - j];
397 q[i] = fw;
400 jz = jk;
401 recompute:
402 /* distill q[] into iq[] reversingly */
403 for (i = 0, j = jz, z = q[jz]; j > 0; i++, j--) {
404 fw = (double)(INT32)(0x1p-24 * z);
405 iq[i] = (INT32)(z - 0x1p24 * fw);
406 z = q[j - 1] + fw;
409 /* compute n */
410 z = __scalbn(z, q0); /* actual value of z */
411 z -= 8.0 * floor(z * 0.125); /* trim off integer >= 8 */
412 n = (INT32)z;
413 z -= (double)n;
414 ih = 0;
415 if (q0 > 0) { /* need iq[jz-1] to determine n */
416 i = iq[jz - 1] >> (24 - q0);
417 n += i;
418 iq[jz - 1] -= i << (24 - q0);
419 ih = iq[jz - 1] >> (23 - q0);
421 else if (q0 == 0) ih = iq[jz - 1] >> 23;
422 else if (z >= 0.5) ih = 2;
424 if (ih > 0) { /* q > 0.5 */
425 n += 1;
426 carry = 0;
427 for (i = 0; i < jz; i++) { /* compute 1-q */
428 j = iq[i];
429 if (carry == 0) {
430 if (j != 0) {
431 carry = 1;
432 iq[i] = 0x1000000 - j;
434 } else
435 iq[i] = 0xffffff - j;
437 if (q0 > 0) { /* rare case: chance is 1 in 12 */
438 switch(q0) {
439 case 1:
440 iq[jz - 1] &= 0x7fffff;
441 break;
442 case 2:
443 iq[jz - 1] &= 0x3fffff;
444 break;
447 if (ih == 2) {
448 z = 1.0 - z;
449 if (carry != 0)
450 z -= __scalbn(1.0, q0);
454 /* check if recomputation is needed */
455 if (z == 0.0) {
456 j = 0;
457 for (i = jz - 1; i >= jk; i--) j |= iq[i];
458 if (j == 0) { /* need recomputation */
459 for (k = 1; iq[jk - k] == 0; k++); /* k = no. of terms needed */
461 for (i = jz + 1; i <= jz + k; i++) { /* add q[jz+1] to q[jz+k] */
462 f[jx + i] = (double)ipio2[jv + i];
463 for (j = 0, fw = 0.0; j <= jx; j++)
464 fw += x[j] * f[jx + i - j];
465 q[i] = fw;
467 jz += k;
468 goto recompute;
472 /* chop off zero terms */
473 if (z == 0.0) {
474 jz -= 1;
475 q0 -= 24;
476 while (iq[jz] == 0) {
477 jz--;
478 q0 -= 24;
480 } else { /* break z into 24-bit if necessary */
481 z = __scalbn(z, -q0);
482 if (z >= 0x1p24) {
483 fw = (double)(INT32)(0x1p-24 * z);
484 iq[jz] = (INT32)(z - 0x1p24 * fw);
485 jz += 1;
486 q0 += 24;
487 iq[jz] = (INT32)fw;
488 } else
489 iq[jz] = (INT32)z;
492 /* convert integer "bit" chunk to floating-point value */
493 fw = __scalbn(1.0, q0);
494 for (i = jz; i >= 0; i--) {
495 q[i] = fw * (double)iq[i];
496 fw *= 0x1p-24;
499 /* compute PIo2[0,...,jp]*q[jz,...,0] */
500 for(i = jz; i >= 0; i--) {
501 for (fw = 0.0, k = 0; k <= jp && k <= jz - i; k++)
502 fw += PIo2[k] * q[i + k];
503 fq[jz - i] = fw;
506 /* compress fq[] into y[] */
507 switch(prec) {
508 case 0:
509 fw = 0.0;
510 for (i = jz; i >= 0; i--)
511 fw += fq[i];
512 y[0] = ih == 0 ? fw : -fw;
513 break;
514 case 1:
515 case 2:
516 fw = 0.0;
517 for (i = jz; i >= 0; i--)
518 fw += fq[i];
519 fw = (double)fw;
520 y[0] = ih==0 ? fw : -fw;
521 fw = fq[0] - fw;
522 for (i = 1; i <= jz; i++)
523 fw += fq[i];
524 y[1] = ih == 0 ? fw : -fw;
525 break;
526 case 3: /* painful */
527 for (i = jz; i > 0; i--) {
528 fw = fq[i - 1] + fq[i];
529 fq[i] += fq[i - 1] - fw;
530 fq[i - 1] = fw;
532 for (i = jz; i > 1; i--) {
533 fw = fq[i - 1] + fq[i];
534 fq[i] += fq[i - 1] - fw;
535 fq[i - 1] = fw;
537 for (fw = 0.0, i = jz; i >= 2; i--)
538 fw += fq[i];
539 if (ih == 0) {
540 y[0] = fq[0];
541 y[1] = fq[1];
542 y[2] = fw;
543 } else {
544 y[0] = -fq[0];
545 y[1] = -fq[1];
546 y[2] = -fw;
549 return n & 7;
552 #if !defined(__i386__) || _MSVCR_VER >= 120
553 /* Copied from musl: src/math/expm1f.c */
554 static float __expm1f(float x)
556 static const float ln2_hi = 6.9313812256e-01,
557 ln2_lo = 9.0580006145e-06,
558 invln2 = 1.4426950216e+00,
559 Q1 = -3.3333212137e-2,
560 Q2 = 1.5807170421e-3;
562 float y, hi, lo, c, t, e, hxs, hfx, r1, twopk;
563 union {float f; UINT32 i;} u = {x};
564 UINT32 hx = u.i & 0x7fffffff;
565 int k, sign = u.i >> 31;
567 /* filter out huge and non-finite argument */
568 if (hx >= 0x4195b844) { /* if |x|>=27*ln2 */
569 if (hx >= 0x7f800000) /* NaN */
570 return u.i == 0xff800000 ? -1 : x;
571 if (sign)
572 return math_error(_UNDERFLOW, "exp", x, 0, -1);
573 if (hx > 0x42b17217) /* x > log(FLT_MAX) */
574 return math_error(_OVERFLOW, "exp", x, 0, fp_barrierf(x * FLT_MAX));
577 /* argument reduction */
578 if (hx > 0x3eb17218) { /* if |x| > 0.5 ln2 */
579 if (hx < 0x3F851592) { /* and |x| < 1.5 ln2 */
580 if (!sign) {
581 hi = x - ln2_hi;
582 lo = ln2_lo;
583 k = 1;
584 } else {
585 hi = x + ln2_hi;
586 lo = -ln2_lo;
587 k = -1;
589 } else {
590 k = invln2 * x + (sign ? -0.5f : 0.5f);
591 t = k;
592 hi = x - t * ln2_hi; /* t*ln2_hi is exact here */
593 lo = t * ln2_lo;
595 x = hi - lo;
596 c = (hi - x) - lo;
597 } else if (hx < 0x33000000) { /* when |x|<2**-25, return x */
598 if (hx < 0x00800000)
599 fp_barrierf(x * x);
600 return x;
601 } else
602 k = 0;
604 /* x is now in primary range */
605 hfx = 0.5f * x;
606 hxs = x * hfx;
607 r1 = 1.0f + hxs * (Q1 + hxs * Q2);
608 t = 3.0f - r1 * hfx;
609 e = hxs * ((r1 - t) / (6.0f - x * t));
610 if (k == 0) /* c is 0 */
611 return x - (x * e - hxs);
612 e = x * (e - c) - c;
613 e -= hxs;
614 /* exp(x) ~ 2^k (x_reduced - e + 1) */
615 if (k == -1)
616 return 0.5f * (x - e) - 0.5f;
617 if (k == 1) {
618 if (x < -0.25f)
619 return -2.0f * (e - (x + 0.5f));
620 return 1.0f + 2.0f * (x - e);
622 u.i = (0x7f + k) << 23; /* 2^k */
623 twopk = u.f;
624 if (k < 0 || k > 56) { /* suffice to return exp(x)-1 */
625 y = x - e + 1.0f;
626 if (k == 128)
627 y = y * 2.0f * 0x1p127f;
628 else
629 y = y * twopk;
630 return y - 1.0f;
632 u.i = (0x7f-k) << 23; /* 2^-k */
633 if (k < 23)
634 y = (x - e + (1 - u.f)) * twopk;
635 else
636 y = (x - (e + u.f) + 1) * twopk;
637 return y;
640 /* Copied from musl: src/math/__sindf.c */
641 static float __sindf(double x)
643 static const double S1 = -0x15555554cbac77.0p-55,
644 S2 = 0x111110896efbb2.0p-59,
645 S3 = -0x1a00f9e2cae774.0p-65,
646 S4 = 0x16cd878c3b46a7.0p-71;
648 double r, s, w, z;
650 z = x * x;
651 w = z * z;
652 r = S3 + z * S4;
653 s = z * x;
654 return (x + s * (S1 + z * S2)) + s * w * r;
657 /* Copied from musl: src/math/__cosdf.c */
658 static float __cosdf(double x)
660 static const double C0 = -0x1ffffffd0c5e81.0p-54,
661 C1 = 0x155553e1053a42.0p-57,
662 C2 = -0x16c087e80f1e27.0p-62,
663 C3 = 0x199342e0ee5069.0p-68;
664 double r, w, z;
666 z = x * x;
667 w = z * z;
668 r = C2 + z * C3;
669 return ((1.0 + z * C0) + w * C1) + (w * z) * r;
671 #endif
673 #ifndef __i386__
675 /*********************************************************************
676 * _fpclassf (MSVCRT.@)
678 int CDECL _fpclassf( float num )
680 union { float f; UINT32 i; } u = { num };
681 int e = u.i >> 23 & 0xff;
682 int s = u.i >> 31;
684 switch (e)
686 case 0:
687 if (u.i << 1) return s ? _FPCLASS_ND : _FPCLASS_PD;
688 return s ? _FPCLASS_NZ : _FPCLASS_PZ;
689 case 0xff:
690 if (u.i << 9) return ((u.i >> 22) & 1) ? _FPCLASS_QNAN : _FPCLASS_SNAN;
691 return s ? _FPCLASS_NINF : _FPCLASS_PINF;
692 default:
693 return s ? _FPCLASS_NN : _FPCLASS_PN;
697 /*********************************************************************
698 * _finitef (MSVCRT.@)
700 int CDECL _finitef( float num )
702 union { float f; UINT32 i; } u = { num };
703 return (u.i & 0x7fffffff) < 0x7f800000;
706 /*********************************************************************
707 * _isnanf (MSVCRT.@)
709 int CDECL _isnanf( float num )
711 union { float f; UINT32 i; } u = { num };
712 return (u.i & 0x7fffffff) > 0x7f800000;
715 static float asinf_R(float z)
717 /* coefficients for R(x^2) */
718 static const float p1 = 1.66666672e-01,
719 p2 = -5.11644611e-02,
720 p3 = -1.21124933e-02,
721 p4 = -3.58742251e-03,
722 q1 = -7.56982703e-01;
724 float p, q;
725 p = z * (p1 + z * (p2 + z * (p3 + z * p4)));
726 q = 1.0f + z * q1;
727 return p / q;
730 /*********************************************************************
731 * acosf (MSVCRT.@)
733 * Copied from musl: src/math/acosf.c
735 float CDECL acosf( float x )
737 static const double pio2_lo = 6.12323399573676603587e-17;
739 float z, w, s, c, df;
740 unsigned int hx, ix;
742 hx = *(unsigned int*)&x;
743 ix = hx & 0x7fffffff;
744 /* |x| >= 1 or nan */
745 if (ix >= 0x3f800000) {
746 if (ix == 0x3f800000) {
747 if (hx >> 31)
748 return M_PI;
749 return 0;
751 if (isnan(x)) return x;
752 return math_error(_DOMAIN, "acosf", x, 0, 0 / (x - x));
754 /* |x| < 0.5 */
755 if (ix < 0x3f000000) {
756 if (ix <= 0x32800000) /* |x| < 2**-26 */
757 return M_PI_2;
758 return M_PI_2 - (x - (pio2_lo - x * asinf_R(x * x)));
760 /* x < -0.5 */
761 if (hx >> 31) {
762 z = (1 + x) * 0.5f;
763 s = sqrtf(z);
764 return M_PI - 2 * (s + ((double)s * asinf_R(z)));
766 /* x > 0.5 */
767 z = (1 - x) * 0.5f;
768 s = sqrtf(z);
769 hx = *(unsigned int*)&s & 0xffff0000;
770 df = *(float*)&hx;
771 c = (z - df * df) / (s + df);
772 w = asinf_R(z) * s + c;
773 return 2 * (df + w);
776 /*********************************************************************
777 * asinf (MSVCRT.@)
779 * Copied from musl: src/math/asinf.c
781 float CDECL asinf( float x )
783 static const double pio2 = 1.570796326794896558e+00;
784 static const float pio4_hi = 0.785398125648;
785 static const float pio2_lo = 7.54978941586e-08;
787 float s, z, f, c;
788 unsigned int hx, ix;
790 hx = *(unsigned int*)&x;
791 ix = hx & 0x7fffffff;
792 if (ix >= 0x3f800000) { /* |x| >= 1 */
793 if (ix == 0x3f800000) /* |x| == 1 */
794 return x * pio2 + 7.5231638453e-37; /* asin(+-1) = +-pi/2 with inexact */
795 if (isnan(x)) return x;
796 return math_error(_DOMAIN, "asinf", x, 0, 0 / (x - x));
798 if (ix < 0x3f000000) { /* |x| < 0.5 */
799 /* if 0x1p-126 <= |x| < 0x1p-12, avoid raising underflow */
800 if (ix < 0x39800000 && ix >= 0x00800000)
801 return x;
802 return x + x * asinf_R(x * x);
804 /* 1 > |x| >= 0.5 */
805 z = (1 - fabsf(x)) * 0.5f;
806 s = sqrtf(z);
807 /* f+c = sqrt(z) */
808 *(unsigned int*)&f = *(unsigned int*)&s & 0xffff0000;
809 c = (z - f * f) / (s + f);
810 x = pio4_hi - (2 * s * asinf_R(z) - (pio2_lo - 2 * c) - (pio4_hi - 2 * f));
811 if (hx >> 31)
812 return -x;
813 return x;
816 /*********************************************************************
817 * atanf (MSVCRT.@)
819 * Copied from musl: src/math/atanf.c
821 float CDECL atanf( float x )
823 static const float atanhi[] = {
824 4.6364760399e-01,
825 7.8539812565e-01,
826 9.8279368877e-01,
827 1.5707962513e+00,
829 static const float atanlo[] = {
830 5.0121582440e-09,
831 3.7748947079e-08,
832 3.4473217170e-08,
833 7.5497894159e-08,
835 static const float aT[] = {
836 3.3333328366e-01,
837 -1.9999158382e-01,
838 1.4253635705e-01,
839 -1.0648017377e-01,
840 6.1687607318e-02,
843 float w, s1, s2, z;
844 unsigned int ix, sign;
845 int id;
847 #if _MSVCR_VER == 0
848 if (isnan(x)) return math_error(_DOMAIN, "atanf", x, 0, x);
849 #endif
851 ix = *(unsigned int*)&x;
852 sign = ix >> 31;
853 ix &= 0x7fffffff;
854 if (ix >= 0x4c800000) { /* if |x| >= 2**26 */
855 if (isnan(x))
856 return x;
857 z = atanhi[3] + 7.5231638453e-37;
858 return sign ? -z : z;
860 if (ix < 0x3ee00000) { /* |x| < 0.4375 */
861 if (ix < 0x39800000) { /* |x| < 2**-12 */
862 if (ix < 0x00800000)
863 /* raise underflow for subnormal x */
864 fp_barrierf(x*x);
865 return x;
867 id = -1;
868 } else {
869 x = fabsf(x);
870 if (ix < 0x3f980000) { /* |x| < 1.1875 */
871 if (ix < 0x3f300000) { /* 7/16 <= |x| < 11/16 */
872 id = 0;
873 x = (2.0f * x - 1.0f) / (2.0f + x);
874 } else { /* 11/16 <= |x| < 19/16 */
875 id = 1;
876 x = (x - 1.0f) / (x + 1.0f);
878 } else {
879 if (ix < 0x401c0000) { /* |x| < 2.4375 */
880 id = 2;
881 x = (x - 1.5f) / (1.0f + 1.5f * x);
882 } else { /* 2.4375 <= |x| < 2**26 */
883 id = 3;
884 x = -1.0f / x;
888 /* end of argument reduction */
889 z = x * x;
890 w = z * z;
891 /* break sum from i=0 to 10 aT[i]z**(i+1) into odd and even poly */
892 s1 = z * (aT[0] + w * (aT[2] + w * aT[4]));
893 s2 = w * (aT[1] + w * aT[3]);
894 if (id < 0)
895 return x - x * (s1 + s2);
896 z = atanhi[id] - ((x * (s1 + s2) - atanlo[id]) - x);
897 return sign ? -z : z;
900 /*********************************************************************
901 * atan2f (MSVCRT.@)
903 * Copied from musl: src/math/atan2f.c
905 float CDECL atan2f( float y, float x )
907 static const float pi = 3.1415927410e+00,
908 pi_lo = -8.7422776573e-08;
910 float z;
911 unsigned int m, ix, iy;
913 if (isnan(x) || isnan(y))
914 return x + y;
915 ix = *(unsigned int*)&x;
916 iy = *(unsigned int*)&y;
917 if (ix == 0x3f800000) /* x=1.0 */
918 return atanf(y);
919 m = ((iy >> 31) & 1) | ((ix >> 30) & 2); /* 2*sign(x)+sign(y) */
920 ix &= 0x7fffffff;
921 iy &= 0x7fffffff;
923 /* when y = 0 */
924 if (iy == 0) {
925 switch (m) {
926 case 0:
927 case 1: return y; /* atan(+-0,+anything)=+-0 */
928 case 2: return pi; /* atan(+0,-anything) = pi */
929 case 3: return -pi; /* atan(-0,-anything) =-pi */
932 /* when x = 0 */
933 if (ix == 0)
934 return m & 1 ? -pi / 2 : pi / 2;
935 /* when x is INF */
936 if (ix == 0x7f800000) {
937 if (iy == 0x7f800000) {
938 switch (m) {
939 case 0: return pi / 4; /* atan(+INF,+INF) */
940 case 1: return -pi / 4; /* atan(-INF,+INF) */
941 case 2: return 3 * pi / 4; /*atan(+INF,-INF)*/
942 case 3: return -3 * pi / 4; /*atan(-INF,-INF)*/
944 } else {
945 switch (m) {
946 case 0: return 0.0f; /* atan(+...,+INF) */
947 case 1: return -0.0f; /* atan(-...,+INF) */
948 case 2: return pi; /* atan(+...,-INF) */
949 case 3: return -pi; /* atan(-...,-INF) */
953 /* |y/x| > 0x1p26 */
954 if (ix + (26 << 23) < iy || iy == 0x7f800000)
955 return m & 1 ? -pi / 2 : pi / 2;
957 /* z = atan(|y/x|) with correct underflow */
958 if ((m & 2) && iy + (26 << 23) < ix) /*|y/x| < 0x1p-26, x < 0 */
959 z = 0.0;
960 else
961 z = atanf(fabsf(y / x));
962 switch (m) {
963 case 0: return z; /* atan(+,+) */
964 case 1: return -z; /* atan(-,+) */
965 case 2: return pi - (z - pi_lo); /* atan(+,-) */
966 default: /* case 3 */
967 return (z - pi_lo) - pi; /* atan(-,-) */
971 /* Copied from musl: src/math/__rem_pio2f.c */
972 static int __rem_pio2f(float x, double *y)
974 static const double toint = 1.5 / DBL_EPSILON,
975 pio4 = 0x1.921fb6p-1,
976 invpio2 = 6.36619772367581382433e-01,
977 pio2_1 = 1.57079631090164184570e+00,
978 pio2_1t = 1.58932547735281966916e-08;
980 union {float f; uint32_t i;} u = {x};
981 double tx[1], ty[1], fn;
982 UINT32 ix;
983 int n, sign, e0;
985 ix = u.i & 0x7fffffff;
986 /* 25+53 bit pi is good enough for medium size */
987 if (ix < 0x4dc90fdb) { /* |x| ~< 2^28*(pi/2), medium size */
988 /* Use a specialized rint() to get fn. */
989 fn = fp_barrier(x * invpio2 + toint) - toint;
990 n = (int)fn;
991 *y = x - fn * pio2_1 - fn * pio2_1t;
992 /* Matters with directed rounding. */
993 if (*y < -pio4) {
994 n--;
995 fn--;
996 *y = x - fn * pio2_1 - fn * pio2_1t;
997 } else if (*y > pio4) {
998 n++;
999 fn++;
1000 *y = x - fn * pio2_1 - fn * pio2_1t;
1002 return n;
1004 if(ix >= 0x7f800000) { /* x is inf or NaN */
1005 *y = x - x;
1006 return 0;
1008 /* scale x into [2^23, 2^24-1] */
1009 sign = u.i >> 31;
1010 e0 = (ix >> 23) - (0x7f + 23); /* e0 = ilogb(|x|)-23, positive */
1011 u.i = ix - (e0 << 23);
1012 tx[0] = u.f;
1013 n = __rem_pio2_large(tx, ty, e0, 1, 0);
1014 if (sign) {
1015 *y = -ty[0];
1016 return -n;
1018 *y = ty[0];
1019 return n;
1022 /*********************************************************************
1023 * cosf (MSVCRT.@)
1025 * Copied from musl: src/math/cosf.c
1027 float CDECL cosf( float x )
1029 static const double c1pio2 = 1*M_PI_2,
1030 c2pio2 = 2*M_PI_2,
1031 c3pio2 = 3*M_PI_2,
1032 c4pio2 = 4*M_PI_2;
1034 double y;
1035 UINT32 ix;
1036 unsigned n, sign;
1038 ix = *(UINT32*)&x;
1039 sign = ix >> 31;
1040 ix &= 0x7fffffff;
1042 if (ix <= 0x3f490fda) { /* |x| ~<= pi/4 */
1043 if (ix < 0x39800000) { /* |x| < 2**-12 */
1044 /* raise inexact if x != 0 */
1045 fp_barrierf(x + 0x1p120f);
1046 return 1.0f;
1048 return __cosdf(x);
1050 if (ix <= 0x407b53d1) { /* |x| ~<= 5*pi/4 */
1051 if (ix > 0x4016cbe3) /* |x| ~> 3*pi/4 */
1052 return -__cosdf(sign ? x + c2pio2 : x - c2pio2);
1053 else {
1054 if (sign)
1055 return __sindf(x + c1pio2);
1056 else
1057 return __sindf(c1pio2 - x);
1060 if (ix <= 0x40e231d5) { /* |x| ~<= 9*pi/4 */
1061 if (ix > 0x40afeddf) /* |x| ~> 7*pi/4 */
1062 return __cosdf(sign ? x + c4pio2 : x - c4pio2);
1063 else {
1064 if (sign)
1065 return __sindf(-x - c3pio2);
1066 else
1067 return __sindf(x - c3pio2);
1071 /* cos(Inf or NaN) is NaN */
1072 if (isinf(x)) return math_error(_DOMAIN, "cosf", x, 0, x - x);
1073 if (ix >= 0x7f800000)
1074 return x - x;
1076 /* general argument reduction needed */
1077 n = __rem_pio2f(x, &y);
1078 switch (n & 3) {
1079 case 0: return __cosdf(y);
1080 case 1: return __sindf(-y);
1081 case 2: return -__cosdf(y);
1082 default: return __sindf(y);
1086 /* Copied from musl: src/math/__expo2f.c */
1087 static float __expo2f(float x, float sign)
1089 static const int k = 235;
1090 static const float kln2 = 0x1.45c778p+7f;
1091 float scale;
1093 *(UINT32*)&scale = (UINT32)(0x7f + k/2) << 23;
1094 return expf(x - kln2) * (sign * scale) * scale;
1097 /*********************************************************************
1098 * coshf (MSVCRT.@)
1100 * Copied from musl: src/math/coshf.c
1102 float CDECL coshf( float x )
1104 UINT32 ui = *(UINT32*)&x;
1105 float t;
1107 /* |x| */
1108 ui &= 0x7fffffff;
1109 x = *(float*)&ui;
1111 /* |x| < log(2) */
1112 if (ui < 0x3f317217) {
1113 if (ui < 0x3f800000 - (12 << 23)) {
1114 fp_barrierf(x + 0x1p120f);
1115 return 1;
1117 t = __expm1f(x);
1118 return 1 + t * t / (2 * (1 + t));
1121 /* |x| < log(FLT_MAX) */
1122 if (ui < 0x42b17217) {
1123 t = expf(x);
1124 return 0.5f * (t + 1 / t);
1127 /* |x| > log(FLT_MAX) or nan */
1128 t = __expo2f(x, 1.0f);
1129 return t;
1132 /*********************************************************************
1133 * expf (MSVCRT.@)
1135 float CDECL expf( float x )
1137 float ret = unix_funcs->expf( x );
1138 if (isnan(x)) return math_error(_DOMAIN, "expf", x, 0, ret);
1139 if (isfinite(x) && !ret) return math_error(_UNDERFLOW, "expf", x, 0, ret);
1140 if (isfinite(x) && !isfinite(ret)) return math_error(_OVERFLOW, "expf", x, 0, ret);
1141 return ret;
1144 /*********************************************************************
1145 * fmodf (MSVCRT.@)
1147 * Copied from musl: src/math/fmodf.c
1149 float CDECL fmodf( float x, float y )
1151 UINT32 xi = *(UINT32*)&x;
1152 UINT32 yi = *(UINT32*)&y;
1153 int ex = xi>>23 & 0xff;
1154 int ey = yi>>23 & 0xff;
1155 UINT32 sx = xi & 0x80000000;
1156 UINT32 i;
1158 if (isinf(x)) return math_error(_DOMAIN, "fmodf", x, y, (x * y) / (x * y));
1159 if (yi << 1 == 0 || isnan(y) || ex == 0xff)
1160 return (x * y) / (x * y);
1161 if (xi << 1 <= yi << 1) {
1162 if (xi << 1 == yi << 1)
1163 return 0 * x;
1164 return x;
1167 /* normalize x and y */
1168 if (!ex) {
1169 for (i = xi << 9; i >> 31 == 0; ex--, i <<= 1);
1170 xi <<= -ex + 1;
1171 } else {
1172 xi &= -1U >> 9;
1173 xi |= 1U << 23;
1175 if (!ey) {
1176 for (i = yi << 9; i >> 31 == 0; ey--, i <<= 1);
1177 yi <<= -ey + 1;
1178 } else {
1179 yi &= -1U >> 9;
1180 yi |= 1U << 23;
1183 /* x mod y */
1184 for (; ex > ey; ex--) {
1185 i = xi - yi;
1186 if (i >> 31 == 0) {
1187 if (i == 0)
1188 return 0 * x;
1189 xi = i;
1191 xi <<= 1;
1193 i = xi - yi;
1194 if (i >> 31 == 0) {
1195 if (i == 0)
1196 return 0 * x;
1197 xi = i;
1199 for (; xi>>23 == 0; xi <<= 1, ex--);
1201 /* scale result up */
1202 if (ex > 0) {
1203 xi -= 1U << 23;
1204 xi |= (UINT32)ex << 23;
1205 } else {
1206 xi >>= -ex + 1;
1208 xi |= sx;
1209 return *(float*)&xi;
1212 /*********************************************************************
1213 * logf (MSVCRT.@)
1215 * Copied from musl: src/math/logf.c src/math/logf_data.c
1217 float CDECL logf( float x )
1219 static const double Ln2 = 0x1.62e42fefa39efp-1;
1220 static const double A[] = {
1221 -0x1.00ea348b88334p-2,
1222 0x1.5575b0be00b6ap-2,
1223 -0x1.ffffef20a4123p-2
1225 static const struct {
1226 double invc, logc;
1227 } T[] = {
1228 { 0x1.661ec79f8f3bep+0, -0x1.57bf7808caadep-2 },
1229 { 0x1.571ed4aaf883dp+0, -0x1.2bef0a7c06ddbp-2 },
1230 { 0x1.49539f0f010bp+0, -0x1.01eae7f513a67p-2 },
1231 { 0x1.3c995b0b80385p+0, -0x1.b31d8a68224e9p-3 },
1232 { 0x1.30d190c8864a5p+0, -0x1.6574f0ac07758p-3 },
1233 { 0x1.25e227b0b8eap+0, -0x1.1aa2bc79c81p-3 },
1234 { 0x1.1bb4a4a1a343fp+0, -0x1.a4e76ce8c0e5ep-4 },
1235 { 0x1.12358f08ae5bap+0, -0x1.1973c5a611cccp-4 },
1236 { 0x1.0953f419900a7p+0, -0x1.252f438e10c1ep-5 },
1237 { 0x1p+0, 0x0p+0 },
1238 { 0x1.e608cfd9a47acp-1, 0x1.aa5aa5df25984p-5 },
1239 { 0x1.ca4b31f026aap-1, 0x1.c5e53aa362eb4p-4 },
1240 { 0x1.b2036576afce6p-1, 0x1.526e57720db08p-3 },
1241 { 0x1.9c2d163a1aa2dp-1, 0x1.bc2860d22477p-3 },
1242 { 0x1.886e6037841edp-1, 0x1.1058bc8a07ee1p-2 },
1243 { 0x1.767dcf5534862p-1, 0x1.4043057b6ee09p-2 }
1246 double z, r, r2, y, y0, invc, logc;
1247 UINT32 ix, iz, tmp;
1248 int k, i;
1250 ix = *(UINT32*)&x;
1251 /* Fix sign of zero with downward rounding when x==1. */
1252 if (ix == 0x3f800000)
1253 return 0;
1254 if (ix - 0x00800000 >= 0x7f800000 - 0x00800000) {
1255 /* x < 0x1p-126 or inf or nan. */
1256 if (ix * 2 == 0)
1257 return math_error(_SING, "logf", x, 0, (ix & 0x80000000 ? 1.0 : -1.0) / x);
1258 if (ix == 0x7f800000) /* log(inf) == inf. */
1259 return x;
1260 if (ix * 2 > 0xff000000)
1261 return x;
1262 if (ix & 0x80000000)
1263 return math_error(_DOMAIN, "logf", x, 0, (x - x) / (x - x));
1264 /* x is subnormal, normalize it. */
1265 x *= 0x1p23f;
1266 ix = *(UINT32*)&x;
1267 ix -= 23 << 23;
1270 /* x = 2^k z; where z is in range [OFF,2*OFF] and exact.
1271 The range is split into N subintervals.
1272 The ith subinterval contains z and c is near its center. */
1273 tmp = ix - 0x3f330000;
1274 i = (tmp >> (23 - 4)) % (1 << 4);
1275 k = (INT32)tmp >> 23; /* arithmetic shift */
1276 iz = ix - (tmp & (0x1ffu << 23));
1277 invc = T[i].invc;
1278 logc = T[i].logc;
1279 z = *(float*)&iz;
1281 /* log(x) = log1p(z/c-1) + log(c) + k*Ln2 */
1282 r = z * invc - 1;
1283 y0 = logc + (double)k * Ln2;
1285 /* Pipelined polynomial evaluation to approximate log1p(r). */
1286 r2 = r * r;
1287 y = A[1] * r + A[2];
1288 y = A[0] * r2 + y;
1289 y = y * r2 + (y0 + r);
1290 return y;
1293 /*********************************************************************
1294 * log10f (MSVCRT.@)
1296 float CDECL log10f( float x )
1298 static const float ivln10hi = 4.3432617188e-01,
1299 ivln10lo = -3.1689971365e-05,
1300 log10_2hi = 3.0102920532e-01,
1301 log10_2lo = 7.9034151668e-07,
1302 Lg1 = 0xaaaaaa.0p-24,
1303 Lg2 = 0xccce13.0p-25,
1304 Lg3 = 0x91e9ee.0p-25,
1305 Lg4 = 0xf89e26.0p-26;
1307 union {float f; UINT32 i;} u = {x};
1308 float hfsq, f, s, z, R, w, t1, t2, dk, hi, lo;
1309 UINT32 ix;
1310 int k;
1312 ix = u.i;
1313 k = 0;
1314 if (ix < 0x00800000 || ix >> 31) { /* x < 2**-126 */
1315 if (ix << 1 == 0)
1316 return math_error(_SING, "log10f", x, 0, -1 / (x * x));
1317 if ((ix & ~(1u << 31)) > 0x7f800000)
1318 return x;
1319 if (ix >> 31)
1320 return math_error(_DOMAIN, "log10f", x, 0, (x - x) / (x - x));
1321 /* subnormal number, scale up x */
1322 k -= 25;
1323 x *= 0x1p25f;
1324 u.f = x;
1325 ix = u.i;
1326 } else if (ix >= 0x7f800000) {
1327 return x;
1328 } else if (ix == 0x3f800000)
1329 return 0;
1331 /* reduce x into [sqrt(2)/2, sqrt(2)] */
1332 ix += 0x3f800000 - 0x3f3504f3;
1333 k += (int)(ix >> 23) - 0x7f;
1334 ix = (ix & 0x007fffff) + 0x3f3504f3;
1335 u.i = ix;
1336 x = u.f;
1338 f = x - 1.0f;
1339 s = f / (2.0f + f);
1340 z = s * s;
1341 w = z * z;
1342 t1= w * (Lg2 + w * Lg4);
1343 t2= z * (Lg1 + w * Lg3);
1344 R = t2 + t1;
1345 hfsq = 0.5f * f * f;
1347 hi = f - hfsq;
1348 u.f = hi;
1349 u.i &= 0xfffff000;
1350 hi = u.f;
1351 lo = f - hi - hfsq + s * (hfsq + R);
1352 dk = k;
1353 return dk * log10_2lo + (lo + hi) * ivln10lo + lo * ivln10hi + hi * ivln10hi + dk * log10_2hi;
1356 /*********************************************************************
1357 * powf (MSVCRT.@)
1359 float CDECL powf( float x, float y )
1361 float z = unix_funcs->powf(x,y);
1362 if (x < 0 && y != floorf(y)) return math_error(_DOMAIN, "powf", x, y, z);
1363 if (!x && isfinite(y) && y < 0) return math_error(_SING, "powf", x, y, z);
1364 if (isfinite(x) && isfinite(y) && !isfinite(z)) return math_error(_OVERFLOW, "powf", x, y, z);
1365 if (x && isfinite(x) && isfinite(y) && !z) return math_error(_UNDERFLOW, "powf", x, y, z);
1366 return z;
1369 /*********************************************************************
1370 * sinf (MSVCRT.@)
1372 * Copied from musl: src/math/sinf.c
1374 float CDECL sinf( float x )
1376 static const double s1pio2 = 1*M_PI_2,
1377 s2pio2 = 2*M_PI_2,
1378 s3pio2 = 3*M_PI_2,
1379 s4pio2 = 4*M_PI_2;
1381 double y;
1382 UINT32 ix;
1383 int n, sign;
1385 ix = *(UINT32*)&x;
1386 sign = ix >> 31;
1387 ix &= 0x7fffffff;
1389 if (ix <= 0x3f490fda) { /* |x| ~<= pi/4 */
1390 if (ix < 0x39800000) { /* |x| < 2**-12 */
1391 /* raise inexact if x!=0 and underflow if subnormal */
1392 fp_barrierf(ix < 0x00800000 ? x / 0x1p120f : x + 0x1p120f);
1393 return x;
1395 return __sindf(x);
1397 if (ix <= 0x407b53d1) { /* |x| ~<= 5*pi/4 */
1398 if (ix <= 0x4016cbe3) { /* |x| ~<= 3pi/4 */
1399 if (sign)
1400 return -__cosdf(x + s1pio2);
1401 else
1402 return __cosdf(x - s1pio2);
1404 return __sindf(sign ? -(x + s2pio2) : -(x - s2pio2));
1406 if (ix <= 0x40e231d5) { /* |x| ~<= 9*pi/4 */
1407 if (ix <= 0x40afeddf) { /* |x| ~<= 7*pi/4 */
1408 if (sign)
1409 return __cosdf(x + s3pio2);
1410 else
1411 return -__cosdf(x - s3pio2);
1413 return __sindf(sign ? x + s4pio2 : x - s4pio2);
1416 /* sin(Inf or NaN) is NaN */
1417 if (isinf(x))
1418 return math_error(_DOMAIN, "sinf", x, 0, x - x);
1419 if (ix >= 0x7f800000)
1420 return x - x;
1422 /* general argument reduction needed */
1423 n = __rem_pio2f(x, &y);
1424 switch (n&3) {
1425 case 0: return __sindf(y);
1426 case 1: return __cosdf(y);
1427 case 2: return __sindf(-y);
1428 default: return -__cosdf(y);
1432 /*********************************************************************
1433 * sinhf (MSVCRT.@)
1435 float CDECL sinhf( float x )
1437 UINT32 ui = *(UINT32*)&x;
1438 float t, h, absx;
1440 h = 0.5;
1441 if (ui >> 31)
1442 h = -h;
1443 /* |x| */
1444 ui &= 0x7fffffff;
1445 absx = *(float*)&ui;
1447 /* |x| < log(FLT_MAX) */
1448 if (ui < 0x42b17217) {
1449 t = __expm1f(absx);
1450 if (ui < 0x3f800000) {
1451 if (ui < 0x3f800000 - (12 << 23))
1452 return x;
1453 return h * (2 * t - t * t / (t + 1));
1455 return h * (t + t / (t + 1));
1458 /* |x| > logf(FLT_MAX) or nan */
1459 t = __expo2f(absx, 2 * h);
1460 return t;
1463 static BOOL sqrtf_validate( float *x )
1465 short c = _fdclass(*x);
1467 if (c == FP_ZERO) return FALSE;
1468 if (c == FP_NAN) return FALSE;
1469 if (signbit(*x))
1471 *x = math_error(_DOMAIN, "sqrtf", *x, 0, ret_nan(TRUE));
1472 return FALSE;
1474 if (c == FP_INFINITE) return FALSE;
1475 return TRUE;
1478 #if defined(__x86_64__) || defined(__i386__)
1479 float CDECL sse2_sqrtf(float);
1480 __ASM_GLOBAL_FUNC( sse2_sqrtf,
1481 "sqrtss %xmm0, %xmm0\n\t"
1482 "ret" )
1483 #endif
1485 /*********************************************************************
1486 * sqrtf (MSVCRT.@)
1488 * Copied from musl: src/math/sqrtf.c
1490 float CDECL sqrtf( float x )
1492 #ifdef __x86_64__
1493 if (!sqrtf_validate(&x))
1494 return x;
1496 return sse2_sqrtf(x);
1497 #else
1498 static const float tiny = 1.0e-30;
1500 float z;
1501 int ix,s,q,m,t,i;
1502 unsigned int r;
1504 ix = *(int*)&x;
1506 if (!sqrtf_validate(&x))
1507 return x;
1509 /* normalize x */
1510 m = ix >> 23;
1511 if (m == 0) { /* subnormal x */
1512 for (i = 0; (ix & 0x00800000) == 0; i++)
1513 ix <<= 1;
1514 m -= i - 1;
1516 m -= 127; /* unbias exponent */
1517 ix = (ix & 0x007fffff) | 0x00800000;
1518 if (m & 1) /* odd m, double x to make it even */
1519 ix += ix;
1520 m >>= 1; /* m = [m/2] */
1522 /* generate sqrt(x) bit by bit */
1523 ix += ix;
1524 q = s = 0; /* q = sqrt(x) */
1525 r = 0x01000000; /* r = moving bit from right to left */
1527 while (r != 0) {
1528 t = s + r;
1529 if (t <= ix) {
1530 s = t + r;
1531 ix -= t;
1532 q += r;
1534 ix += ix;
1535 r >>= 1;
1538 /* use floating add to find out rounding direction */
1539 if (ix != 0) {
1540 z = 1.0f - tiny; /* raise inexact flag */
1541 if (z >= 1.0f) {
1542 z = 1.0f + tiny;
1543 if (z > 1.0f)
1544 q += 2;
1545 else
1546 q += q & 1;
1549 ix = (q >> 1) + 0x3f000000;
1550 r = ix + ((unsigned int)m << 23);
1551 z = *(float*)&r;
1552 return z;
1553 #endif
1556 /* Copied from musl: src/math/__tandf.c */
1557 static float __tandf(double x, int odd)
1559 static const double T[] = {
1560 0x15554d3418c99f.0p-54,
1561 0x1112fd38999f72.0p-55,
1562 0x1b54c91d865afe.0p-57,
1563 0x191df3908c33ce.0p-58,
1564 0x185dadfcecf44e.0p-61,
1565 0x1362b9bf971bcd.0p-59,
1568 double z, r, w, s, t, u;
1570 z = x * x;
1571 r = T[4] + z * T[5];
1572 t = T[2] + z * T[3];
1573 w = z * z;
1574 s = z * x;
1575 u = T[0] + z * T[1];
1576 r = (x + s * u) + (s * w) * (t + w * r);
1577 return odd ? -1.0 / r : r;
1580 /*********************************************************************
1581 * tanf (MSVCRT.@)
1583 * Copied from musl: src/math/tanf.c
1585 float CDECL tanf( float x )
1587 static const double t1pio2 = 1*M_PI_2,
1588 t2pio2 = 2*M_PI_2,
1589 t3pio2 = 3*M_PI_2,
1590 t4pio2 = 4*M_PI_2;
1592 double y;
1593 UINT32 ix;
1594 unsigned n, sign;
1596 ix = *(UINT32*)&x;
1597 sign = ix >> 31;
1598 ix &= 0x7fffffff;
1600 if (ix <= 0x3f490fda) { /* |x| ~<= pi/4 */
1601 if (ix < 0x39800000) { /* |x| < 2**-12 */
1602 /* raise inexact if x!=0 and underflow if subnormal */
1603 fp_barrierf(ix < 0x00800000 ? x / 0x1p120f : x + 0x1p120f);
1604 return x;
1606 return __tandf(x, 0);
1608 if (ix <= 0x407b53d1) { /* |x| ~<= 5*pi/4 */
1609 if (ix <= 0x4016cbe3) /* |x| ~<= 3pi/4 */
1610 return __tandf((sign ? x + t1pio2 : x - t1pio2), 1);
1611 else
1612 return __tandf((sign ? x + t2pio2 : x - t2pio2), 0);
1614 if (ix <= 0x40e231d5) { /* |x| ~<= 9*pi/4 */
1615 if (ix <= 0x40afeddf) /* |x| ~<= 7*pi/4 */
1616 return __tandf((sign ? x + t3pio2 : x - t3pio2), 1);
1617 else
1618 return __tandf((sign ? x + t4pio2 : x - t4pio2), 0);
1621 /* tan(Inf or NaN) is NaN */
1622 if (isinf(x))
1623 return math_error(_DOMAIN, "tanf", x, 0, x - x);
1624 if (ix >= 0x7f800000)
1625 return x - x;
1627 /* argument reduction */
1628 n = __rem_pio2f(x, &y);
1629 return __tandf(y, n & 1);
1632 /*********************************************************************
1633 * tanhf (MSVCRT.@)
1635 float CDECL tanhf( float x )
1637 UINT32 ui = *(UINT32*)&x;
1638 int sign;
1639 float t;
1641 /* x = |x| */
1642 sign = ui >> 31;
1643 ui &= 0x7fffffff;
1644 x = *(float*)&ui;
1646 if (ui > 0x3f0c9f54) {
1647 /* |x| > log(3)/2 ~= 0.5493 or nan */
1648 if (ui > 0x41200000) {
1649 #if _MSVCR_VER < 140
1650 if (isnan(x))
1651 return math_error(_DOMAIN, "tanhf", x, 0, x);
1652 #endif
1653 /* |x| > 10 */
1654 fp_barrierf(x + 0x1p120f);
1655 t = 1 + 0 / x;
1656 } else {
1657 t = __expm1f(2 * x);
1658 t = 1 - 2 / (t + 2);
1660 } else if (ui > 0x3e82c578) {
1661 /* |x| > log(5/3)/2 ~= 0.2554 */
1662 t = __expm1f(2 * x);
1663 t = t / (t + 2);
1664 } else if (ui >= 0x00800000) {
1665 /* |x| >= 0x1p-126 */
1666 t = __expm1f(-2 * x);
1667 t = -t / (t + 2);
1668 } else {
1669 /* |x| is subnormal */
1670 fp_barrierf(x * x);
1671 t = x;
1673 return sign ? -t : t;
1676 /*********************************************************************
1677 * ceilf (MSVCRT.@)
1679 * Copied from musl: src/math/ceilf.c
1681 float CDECL ceilf( float x )
1683 union {float f; UINT32 i;} u = {x};
1684 int e = (int)(u.i >> 23 & 0xff) - 0x7f;
1685 UINT32 m;
1687 if (e >= 23)
1688 return x;
1689 if (e >= 0) {
1690 m = 0x007fffff >> e;
1691 if ((u.i & m) == 0)
1692 return x;
1693 if (u.i >> 31 == 0)
1694 u.i += m;
1695 u.i &= ~m;
1696 } else {
1697 if (u.i >> 31)
1698 return -0.0;
1699 else if (u.i << 1)
1700 return 1.0;
1702 return u.f;
1705 /*********************************************************************
1706 * floorf (MSVCRT.@)
1708 * Copied from musl: src/math/floorf.c
1710 float CDECL floorf( float x )
1712 union {float f; UINT32 i;} u = {x};
1713 int e = (int)(u.i >> 23 & 0xff) - 0x7f;
1714 UINT32 m;
1716 if (e >= 23)
1717 return x;
1718 if (e >= 0) {
1719 m = 0x007fffff >> e;
1720 if ((u.i & m) == 0)
1721 return x;
1722 if (u.i >> 31)
1723 u.i += m;
1724 u.i &= ~m;
1725 } else {
1726 if (u.i >> 31 == 0)
1727 return 0;
1728 else if (u.i << 1)
1729 return -1;
1731 return u.f;
1734 /*********************************************************************
1735 * frexpf (MSVCRT.@)
1737 * Copied from musl: src/math/frexpf.c
1739 float CDECL frexpf( float x, int *e )
1741 UINT32 ux = *(UINT32*)&x;
1742 int ee = ux >> 23 & 0xff;
1744 if (!ee) {
1745 if (x) {
1746 x = frexpf(x * 0x1p64, e);
1747 *e -= 64;
1748 } else *e = 0;
1749 return x;
1750 } else if (ee == 0xff) {
1751 return x;
1754 *e = ee - 0x7e;
1755 ux &= 0x807ffffful;
1756 ux |= 0x3f000000ul;
1757 return *(float*)&ux;
1760 /*********************************************************************
1761 * modff (MSVCRT.@)
1763 * Copied from musl: src/math/modff.c
1765 float CDECL modff( float x, float *iptr )
1767 union {float f; UINT32 i;} u = {x};
1768 UINT32 mask;
1769 int e = (u.i >> 23 & 0xff) - 0x7f;
1771 /* no fractional part */
1772 if (e >= 23) {
1773 *iptr = x;
1774 if (e == 0x80 && u.i << 9 != 0) { /* nan */
1775 return x;
1777 u.i &= 0x80000000;
1778 return u.f;
1780 /* no integral part */
1781 if (e < 0) {
1782 u.i &= 0x80000000;
1783 *iptr = u.f;
1784 return x;
1787 mask = 0x007fffff >> e;
1788 if ((u.i & mask) == 0) {
1789 *iptr = x;
1790 u.i &= 0x80000000;
1791 return u.f;
1793 u.i &= ~mask;
1794 *iptr = u.f;
1795 return x - u.f;
1798 #endif
1800 #if !defined(__i386__) && !defined(__x86_64__) && (_MSVCR_VER == 0 || _MSVCR_VER >= 110)
1802 /*********************************************************************
1803 * fabsf (MSVCRT.@)
1805 * Copied from musl: src/math/fabsf.c
1807 float CDECL fabsf( float x )
1809 union { float f; UINT32 i; } u = { x };
1810 u.i &= 0x7fffffff;
1811 return u.f;
1814 #endif
1816 /*********************************************************************
1817 * acos (MSVCRT.@)
1819 * Copied from musl: src/math/acos.c
1821 static double acos_R(double z)
1823 static const double pS0 = 1.66666666666666657415e-01,
1824 pS1 = -3.25565818622400915405e-01,
1825 pS2 = 2.01212532134862925881e-01,
1826 pS3 = -4.00555345006794114027e-02,
1827 pS4 = 7.91534994289814532176e-04,
1828 pS5 = 3.47933107596021167570e-05,
1829 qS1 = -2.40339491173441421878e+00,
1830 qS2 = 2.02094576023350569471e+00,
1831 qS3 = -6.88283971605453293030e-01,
1832 qS4 = 7.70381505559019352791e-02;
1834 double p, q;
1835 p = z * (pS0 + z * (pS1 + z * (pS2 + z * (pS3 + z * (pS4 + z * pS5)))));
1836 q = 1.0 + z * (qS1 + z * (qS2 + z * (qS3 + z * qS4)));
1837 return p/q;
1840 double CDECL acos( double x )
1842 static const double pio2_hi = 1.57079632679489655800e+00,
1843 pio2_lo = 6.12323399573676603587e-17;
1845 double z, w, s, c, df;
1846 unsigned int hx, ix;
1847 ULONGLONG llx;
1849 hx = *(ULONGLONG*)&x >> 32;
1850 ix = hx & 0x7fffffff;
1851 /* |x| >= 1 or nan */
1852 if (ix >= 0x3ff00000) {
1853 unsigned int lx;
1855 lx = *(ULONGLONG*)&x;
1856 if (((ix - 0x3ff00000) | lx) == 0) {
1857 /* acos(1)=0, acos(-1)=pi */
1858 if (hx >> 31)
1859 return 2 * pio2_hi + 7.5231638452626401e-37;
1860 return 0;
1862 if (isnan(x)) return x;
1863 return math_error(_DOMAIN, "acos", x, 0, 0 / (x - x));
1865 /* |x| < 0.5 */
1866 if (ix < 0x3fe00000) {
1867 if (ix <= 0x3c600000) /* |x| < 2**-57 */
1868 return pio2_hi + 7.5231638452626401e-37;
1869 return pio2_hi - (x - (pio2_lo - x * acos_R(x * x)));
1871 /* x < -0.5 */
1872 if (hx >> 31) {
1873 z = (1.0 + x) * 0.5;
1874 s = sqrt(z);
1875 w = acos_R(z) * s - pio2_lo;
1876 return 2 * (pio2_hi - (s + w));
1878 /* x > 0.5 */
1879 z = (1.0 - x) * 0.5;
1880 s = sqrt(z);
1881 df = s;
1882 llx = (*(ULONGLONG*)&df >> 32) << 32;
1883 df = *(double*)&llx;
1884 c = (z - df * df) / (s + df);
1885 w = acos_R(z) * s + c;
1886 return 2 * (df + w);
1889 /*********************************************************************
1890 * asin (MSVCRT.@)
1892 * Copied from musl: src/math/asin.c
1894 static double asin_R(double z)
1896 /* coefficients for R(x^2) */
1897 static const double pS0 = 1.66666666666666657415e-01,
1898 pS1 = -3.25565818622400915405e-01,
1899 pS2 = 2.01212532134862925881e-01,
1900 pS3 = -4.00555345006794114027e-02,
1901 pS4 = 7.91534994289814532176e-04,
1902 pS5 = 3.47933107596021167570e-05,
1903 qS1 = -2.40339491173441421878e+00,
1904 qS2 = 2.02094576023350569471e+00,
1905 qS3 = -6.88283971605453293030e-01,
1906 qS4 = 7.70381505559019352791e-02;
1908 double p, q;
1909 p = z * (pS0 + z * (pS1 + z * (pS2 + z * (pS3 + z * (pS4 + z * pS5)))));
1910 q = 1.0 + z * (qS1 + z * (qS2 + z * (qS3 + z * qS4)));
1911 return p / q;
1914 #ifdef __i386__
1915 double CDECL x87_asin(double);
1916 __ASM_GLOBAL_FUNC( x87_asin,
1917 "fldl 4(%esp)\n\t"
1918 SET_X87_CW(~0x37f)
1919 "fld %st\n\t"
1920 "fld1\n\t"
1921 "fsubp\n\t"
1922 "fld1\n\t"
1923 "fadd %st(2)\n\t"
1924 "fmulp\n\t"
1925 "fsqrt\n\t"
1926 "fpatan\n\t"
1927 RESET_X87_CW
1928 "ret" )
1929 #endif
1931 double CDECL asin( double x )
1933 static const double pio2_hi = 1.57079632679489655800e+00,
1934 pio2_lo = 6.12323399573676603587e-17;
1936 double z, r, s;
1937 unsigned int hx, ix;
1938 ULONGLONG llx;
1939 #ifdef __i386__
1940 unsigned int x87_cw, sse2_cw;
1941 #endif
1943 hx = *(ULONGLONG*)&x >> 32;
1944 ix = hx & 0x7fffffff;
1945 /* |x| >= 1 or nan */
1946 if (ix >= 0x3ff00000) {
1947 unsigned int lx;
1948 lx = *(ULONGLONG*)&x;
1949 if (((ix - 0x3ff00000) | lx) == 0)
1950 /* asin(1) = +-pi/2 with inexact */
1951 return x * pio2_hi + 7.5231638452626401e-37;
1952 if (isnan(x))
1954 #ifdef __i386__
1955 return math_error(_DOMAIN, "asin", x, 0, x);
1956 #else
1957 return x;
1958 #endif
1960 return math_error(_DOMAIN, "asin", x, 0, 0 / (x - x));
1963 #ifdef __i386__
1964 __control87_2(0, 0, &x87_cw, &sse2_cw);
1965 if (!sse2_enabled || (x87_cw & _MCW_EM) != _MCW_EM
1966 || (sse2_cw & (_MCW_EM | _MCW_RC)) != _MCW_EM)
1967 return x87_asin(x);
1968 #endif
1970 /* |x| < 0.5 */
1971 if (ix < 0x3fe00000) {
1972 /* if 0x1p-1022 <= |x| < 0x1p-26, avoid raising underflow */
1973 if (ix < 0x3e500000 && ix >= 0x00100000)
1974 return x;
1975 return x + x * asin_R(x * x);
1977 /* 1 > |x| >= 0.5 */
1978 z = (1 - fabs(x)) * 0.5;
1979 s = sqrt(z);
1980 r = asin_R(z);
1981 if (ix >= 0x3fef3333) { /* if |x| > 0.975 */
1982 x = pio2_hi - (2 * (s + s * r) - pio2_lo);
1983 } else {
1984 double f, c;
1985 /* f+c = sqrt(z) */
1986 f = s;
1987 llx = (*(ULONGLONG*)&f >> 32) << 32;
1988 f = *(double*)&llx;
1989 c = (z - f * f) / (s + f);
1990 x = 0.5 * pio2_hi - (2 * s * r - (pio2_lo - 2 * c) - (0.5 * pio2_hi - 2 * f));
1992 if (hx >> 31)
1993 return -x;
1994 return x;
1997 /*********************************************************************
1998 * atan (MSVCRT.@)
2000 * Copied from musl: src/math/atan.c
2002 double CDECL atan( double x )
2004 static const double atanhi[] = {
2005 4.63647609000806093515e-01,
2006 7.85398163397448278999e-01,
2007 9.82793723247329054082e-01,
2008 1.57079632679489655800e+00,
2010 static const double atanlo[] = {
2011 2.26987774529616870924e-17,
2012 3.06161699786838301793e-17,
2013 1.39033110312309984516e-17,
2014 6.12323399573676603587e-17,
2016 static const double aT[] = {
2017 3.33333333333329318027e-01,
2018 -1.99999999998764832476e-01,
2019 1.42857142725034663711e-01,
2020 -1.11111104054623557880e-01,
2021 9.09088713343650656196e-02,
2022 -7.69187620504482999495e-02,
2023 6.66107313738753120669e-02,
2024 -5.83357013379057348645e-02,
2025 4.97687799461593236017e-02,
2026 -3.65315727442169155270e-02,
2027 1.62858201153657823623e-02,
2030 double w, s1, s2, z;
2031 unsigned int ix, sign;
2032 int id;
2034 #if _MSVCR_VER == 0
2035 if (isnan(x)) return math_error(_DOMAIN, "atan", x, 0, x);
2036 #endif
2038 ix = *(ULONGLONG*)&x >> 32;
2039 sign = ix >> 31;
2040 ix &= 0x7fffffff;
2041 if (ix >= 0x44100000) { /* if |x| >= 2^66 */
2042 if (isnan(x))
2043 return x;
2044 z = atanhi[3] + 7.5231638452626401e-37;
2045 return sign ? -z : z;
2047 if (ix < 0x3fdc0000) { /* |x| < 0.4375 */
2048 if (ix < 0x3e400000) { /* |x| < 2^-27 */
2049 if (ix < 0x00100000)
2050 /* raise underflow for subnormal x */
2051 fp_barrierf((float)x);
2052 return x;
2054 id = -1;
2055 } else {
2056 x = fabs(x);
2057 if (ix < 0x3ff30000) { /* |x| < 1.1875 */
2058 if (ix < 0x3fe60000) { /* 7/16 <= |x| < 11/16 */
2059 id = 0;
2060 x = (2.0 * x - 1.0) / (2.0 + x);
2061 } else { /* 11/16 <= |x| < 19/16 */
2062 id = 1;
2063 x = (x - 1.0) / (x + 1.0);
2065 } else {
2066 if (ix < 0x40038000) { /* |x| < 2.4375 */
2067 id = 2;
2068 x = (x - 1.5) / (1.0 + 1.5 * x);
2069 } else { /* 2.4375 <= |x| < 2^66 */
2070 id = 3;
2071 x = -1.0 / x;
2075 /* end of argument reduction */
2076 z = x * x;
2077 w = z * z;
2078 /* break sum from i=0 to 10 aT[i]z**(i+1) into odd and even poly */
2079 s1 = z * (aT[0] + w * (aT[2] + w * (aT[4] + w * (aT[6] + w * (aT[8] + w * aT[10])))));
2080 s2 = w * (aT[1] + w * (aT[3] + w * (aT[5] + w * (aT[7] + w * aT[9]))));
2081 if (id < 0)
2082 return x - x * (s1 + s2);
2083 z = atanhi[id] - (x * (s1 + s2) - atanlo[id] - x);
2084 return sign ? -z : z;
2087 /*********************************************************************
2088 * atan2 (MSVCRT.@)
2090 * Copied from musl: src/math/atan2.c
2092 double CDECL atan2( double y, double x )
2094 static const double pi = 3.1415926535897931160E+00,
2095 pi_lo = 1.2246467991473531772E-16;
2097 double z;
2098 unsigned int m, lx, ly, ix, iy;
2100 if (isnan(x) || isnan(y))
2101 return x+y;
2102 ix = *(ULONGLONG*)&x >> 32;
2103 lx = *(ULONGLONG*)&x;
2104 iy = *(ULONGLONG*)&y >> 32;
2105 ly = *(ULONGLONG*)&y;
2106 if (((ix - 0x3ff00000) | lx) == 0) /* x = 1.0 */
2107 return atan(y);
2108 m = ((iy >> 31) & 1) | ((ix >> 30) & 2); /* 2*sign(x)+sign(y) */
2109 ix = ix & 0x7fffffff;
2110 iy = iy & 0x7fffffff;
2112 /* when y = 0 */
2113 if ((iy | ly) == 0) {
2114 switch(m) {
2115 case 0:
2116 case 1: return y; /* atan(+-0,+anything)=+-0 */
2117 case 2: return pi; /* atan(+0,-anything) = pi */
2118 case 3: return -pi; /* atan(-0,-anything) =-pi */
2121 /* when x = 0 */
2122 if ((ix | lx) == 0)
2123 return m & 1 ? -pi / 2 : pi / 2;
2124 /* when x is INF */
2125 if (ix == 0x7ff00000) {
2126 if (iy == 0x7ff00000) {
2127 switch(m) {
2128 case 0: return pi / 4; /* atan(+INF,+INF) */
2129 case 1: return -pi / 4; /* atan(-INF,+INF) */
2130 case 2: return 3 * pi / 4; /* atan(+INF,-INF) */
2131 case 3: return -3 * pi / 4; /* atan(-INF,-INF) */
2133 } else {
2134 switch(m) {
2135 case 0: return 0.0; /* atan(+...,+INF) */
2136 case 1: return -0.0; /* atan(-...,+INF) */
2137 case 2: return pi; /* atan(+...,-INF) */
2138 case 3: return -pi; /* atan(-...,-INF) */
2142 /* |y/x| > 0x1p64 */
2143 if (ix + (64 << 20) < iy || iy == 0x7ff00000)
2144 return m & 1 ? -pi / 2 : pi / 2;
2146 /* z = atan(|y/x|) without spurious underflow */
2147 if ((m & 2) && iy + (64 << 20) < ix) /* |y/x| < 0x1p-64, x<0 */
2148 z = 0;
2149 else
2150 z = atan(fabs(y / x));
2151 switch (m) {
2152 case 0: return z; /* atan(+,+) */
2153 case 1: return -z; /* atan(-,+) */
2154 case 2: return pi - (z - pi_lo); /* atan(+,-) */
2155 default: /* case 3 */
2156 return (z - pi_lo) - pi; /* atan(-,-) */
2160 /* Copied from musl: src/math/rint.c */
2161 static double __rint(double x)
2163 static const double toint = 1 / DBL_EPSILON;
2165 ULONGLONG llx = *(ULONGLONG*)&x;
2166 int e = llx >> 52 & 0x7ff;
2167 int s = llx >> 63;
2168 unsigned cw;
2169 double y;
2171 if (e >= 0x3ff+52)
2172 return x;
2173 cw = _controlfp(0, 0);
2174 if ((cw & _MCW_PC) != _PC_53)
2175 _controlfp(_PC_53, _MCW_PC);
2176 if (s)
2177 y = fp_barrier(x - toint) + toint;
2178 else
2179 y = fp_barrier(x + toint) - toint;
2180 if ((cw & _MCW_PC) != _PC_53)
2181 _controlfp(cw, _MCW_PC);
2182 if (y == 0)
2183 return s ? -0.0 : 0;
2184 return y;
2187 /* Copied from musl: src/math/__rem_pio2.c */
2188 static int __rem_pio2(double x, double *y)
2190 static const double pio4 = 0x1.921fb54442d18p-1,
2191 invpio2 = 6.36619772367581382433e-01,
2192 pio2_1 = 1.57079632673412561417e+00,
2193 pio2_1t = 6.07710050650619224932e-11,
2194 pio2_2 = 6.07710050630396597660e-11,
2195 pio2_2t = 2.02226624879595063154e-21,
2196 pio2_3 = 2.02226624871116645580e-21,
2197 pio2_3t = 8.47842766036889956997e-32;
2199 union {double f; UINT64 i;} u = {x};
2200 double z, w, t, r, fn, tx[3], ty[2];
2201 UINT32 ix;
2202 int sign, n, ex, ey, i;
2204 sign = u.i >> 63;
2205 ix = u.i >> 32 & 0x7fffffff;
2206 if (ix <= 0x400f6a7a) { /* |x| ~<= 5pi/4 */
2207 if ((ix & 0xfffff) == 0x921fb) /* |x| ~= pi/2 or 2pi/2 */
2208 goto medium; /* cancellation -- use medium case */
2209 if (ix <= 0x4002d97c) { /* |x| ~<= 3pi/4 */
2210 if (!sign) {
2211 z = x - pio2_1; /* one round good to 85 bits */
2212 y[0] = z - pio2_1t;
2213 y[1] = (z - y[0]) - pio2_1t;
2214 return 1;
2215 } else {
2216 z = x + pio2_1;
2217 y[0] = z + pio2_1t;
2218 y[1] = (z - y[0]) + pio2_1t;
2219 return -1;
2221 } else {
2222 if (!sign) {
2223 z = x - 2 * pio2_1;
2224 y[0] = z - 2 * pio2_1t;
2225 y[1] = (z - y[0]) - 2 * pio2_1t;
2226 return 2;
2227 } else {
2228 z = x + 2 * pio2_1;
2229 y[0] = z + 2 * pio2_1t;
2230 y[1] = (z - y[0]) + 2 * pio2_1t;
2231 return -2;
2235 if (ix <= 0x401c463b) { /* |x| ~<= 9pi/4 */
2236 if (ix <= 0x4015fdbc) { /* |x| ~<= 7pi/4 */
2237 if (ix == 0x4012d97c) /* |x| ~= 3pi/2 */
2238 goto medium;
2239 if (!sign) {
2240 z = x - 3 * pio2_1;
2241 y[0] = z - 3 * pio2_1t;
2242 y[1] = (z - y[0]) - 3 * pio2_1t;
2243 return 3;
2244 } else {
2245 z = x + 3 * pio2_1;
2246 y[0] = z + 3 * pio2_1t;
2247 y[1] = (z - y[0]) + 3 * pio2_1t;
2248 return -3;
2250 } else {
2251 if (ix == 0x401921fb) /* |x| ~= 4pi/2 */
2252 goto medium;
2253 if (!sign) {
2254 z = x - 4 * pio2_1;
2255 y[0] = z - 4 * pio2_1t;
2256 y[1] = (z - y[0]) - 4 * pio2_1t;
2257 return 4;
2258 } else {
2259 z = x + 4 * pio2_1;
2260 y[0] = z + 4 * pio2_1t;
2261 y[1] = (z - y[0]) + 4 * pio2_1t;
2262 return -4;
2266 if (ix < 0x413921fb) { /* |x| ~< 2^20*(pi/2), medium size */
2267 medium:
2268 fn = __rint(x * invpio2);
2269 n = (INT32)fn;
2270 r = x - fn * pio2_1;
2271 w = fn * pio2_1t; /* 1st round, good to 85 bits */
2272 /* Matters with directed rounding. */
2273 if (r - w < -pio4) {
2274 n--;
2275 fn--;
2276 r = x - fn * pio2_1;
2277 w = fn * pio2_1t;
2278 } else if (r - w > pio4) {
2279 n++;
2280 fn++;
2281 r = x - fn * pio2_1;
2282 w = fn * pio2_1t;
2284 y[0] = r - w;
2285 u.f = y[0];
2286 ey = u.i >> 52 & 0x7ff;
2287 ex = ix >> 20;
2288 if (ex - ey > 16) { /* 2nd round, good to 118 bits */
2289 t = r;
2290 w = fn * pio2_2;
2291 r = t - w;
2292 w = fn * pio2_2t - ((t - r) - w);
2293 y[0] = r - w;
2294 u.f = y[0];
2295 ey = u.i >> 52 & 0x7ff;
2296 if (ex - ey > 49) { /* 3rd round, good to 151 bits, covers all cases */
2297 t = r;
2298 w = fn * pio2_3;
2299 r = t - w;
2300 w = fn * pio2_3t - ((t - r) - w);
2301 y[0] = r - w;
2304 y[1] = (r - y[0]) - w;
2305 return n;
2308 * all other (large) arguments
2310 if (ix >= 0x7ff00000) { /* x is inf or NaN */
2311 y[0] = y[1] = x - x;
2312 return 0;
2314 /* set z = scalbn(|x|,-ilogb(x)+23) */
2315 u.f = x;
2316 u.i &= (UINT64)-1 >> 12;
2317 u.i |= (UINT64)(0x3ff + 23) << 52;
2318 z = u.f;
2319 for (i = 0; i < 2; i++) {
2320 tx[i] = (double)(INT32)z;
2321 z = (z - tx[i]) * 0x1p24;
2323 tx[i] = z;
2324 /* skip zero terms, first term is non-zero */
2325 while (tx[i] == 0.0)
2326 i--;
2327 n = __rem_pio2_large(tx, ty, (int)(ix >> 20) - (0x3ff + 23), i + 1, 1);
2328 if (sign) {
2329 y[0] = -ty[0];
2330 y[1] = -ty[1];
2331 return -n;
2333 y[0] = ty[0];
2334 y[1] = ty[1];
2335 return n;
2338 /* Copied from musl: src/math/__sin.c */
2339 static double __sin(double x, double y, int iy)
2341 static const double S1 = -1.66666666666666324348e-01,
2342 S2 = 8.33333333332248946124e-03,
2343 S3 = -1.98412698298579493134e-04,
2344 S4 = 2.75573137070700676789e-06,
2345 S5 = -2.50507602534068634195e-08,
2346 S6 = 1.58969099521155010221e-10;
2348 double z, r, v, w;
2350 z = x * x;
2351 w = z * z;
2352 r = S2 + z * (S3 + z * S4) + z * w * (S5 + z * S6);
2353 v = z * x;
2354 if (iy == 0)
2355 return x + v * (S1 + z * r);
2356 else
2357 return x - ((z * (0.5 * y - v * r) - y) - v * S1);
2360 /* Copied from musl: src/math/__cos.c */
2361 static double __cos(double x, double y)
2363 static const double C1 = 4.16666666666666019037e-02,
2364 C2 = -1.38888888888741095749e-03,
2365 C3 = 2.48015872894767294178e-05,
2366 C4 = -2.75573143513906633035e-07,
2367 C5 = 2.08757232129817482790e-09,
2368 C6 = -1.13596475577881948265e-11;
2369 double hz, z, r, w;
2371 z = x * x;
2372 w = z * z;
2373 r = z * (C1 + z * (C2 + z * C3)) + w * w * (C4 + z * (C5 + z * C6));
2374 hz = 0.5 * z;
2375 w = 1.0 - hz;
2376 return w + (((1.0 - w) - hz) + (z * r - x * y));
2379 /*********************************************************************
2380 * cos (MSVCRT.@)
2382 * Copied from musl: src/math/cos.c
2384 double CDECL cos( double x )
2386 double y[2];
2387 UINT32 ix;
2388 unsigned n;
2390 ix = *(ULONGLONG*)&x >> 32;
2391 ix &= 0x7fffffff;
2393 /* |x| ~< pi/4 */
2394 if (ix <= 0x3fe921fb) {
2395 if (ix < 0x3e46a09e) { /* |x| < 2**-27 * sqrt(2) */
2396 /* raise inexact if x!=0 */
2397 fp_barrier(x + 0x1p120f);
2398 return 1.0;
2400 return __cos(x, 0);
2403 /* cos(Inf or NaN) is NaN */
2404 if (isinf(x)) return math_error(_DOMAIN, "cos", x, 0, x - x);
2405 if (ix >= 0x7ff00000)
2406 return x - x;
2408 /* argument reduction */
2409 n = __rem_pio2(x, y);
2410 switch (n & 3) {
2411 case 0: return __cos(y[0], y[1]);
2412 case 1: return -__sin(y[0], y[1], 1);
2413 case 2: return -__cos(y[0], y[1]);
2414 default: return __sin(y[0], y[1], 1);
2418 /* Copied from musl: src/math/expm1.c */
2419 static double CDECL __expm1(double x)
2421 static const double o_threshold = 7.09782712893383973096e+02,
2422 ln2_hi = 6.93147180369123816490e-01,
2423 ln2_lo = 1.90821492927058770002e-10,
2424 invln2 = 1.44269504088896338700e+00,
2425 Q1 = -3.33333333333331316428e-02,
2426 Q2 = 1.58730158725481460165e-03,
2427 Q3 = -7.93650757867487942473e-05,
2428 Q4 = 4.00821782732936239552e-06,
2429 Q5 = -2.01099218183624371326e-07;
2431 double y, hi, lo, c, t, e, hxs, hfx, r1, twopk;
2432 union {double f; UINT64 i;} u = {x};
2433 UINT32 hx = u.i >> 32 & 0x7fffffff;
2434 int k, sign = u.i >> 63;
2436 /* filter out huge and non-finite argument */
2437 if (hx >= 0x4043687A) { /* if |x|>=56*ln2 */
2438 if (isnan(x))
2439 return x;
2440 if (isinf(x))
2441 return sign ? -1 : x;
2442 if (sign)
2443 return math_error(_UNDERFLOW, "exp", x, 0, -1);
2444 if (x > o_threshold)
2445 return math_error(_OVERFLOW, "exp", x, 0, x * 0x1p1023);
2448 /* argument reduction */
2449 if (hx > 0x3fd62e42) { /* if |x| > 0.5 ln2 */
2450 if (hx < 0x3FF0A2B2) { /* and |x| < 1.5 ln2 */
2451 if (!sign) {
2452 hi = x - ln2_hi;
2453 lo = ln2_lo;
2454 k = 1;
2455 } else {
2456 hi = x + ln2_hi;
2457 lo = -ln2_lo;
2458 k = -1;
2460 } else {
2461 k = invln2 * x + (sign ? -0.5 : 0.5);
2462 t = k;
2463 hi = x - t * ln2_hi; /* t*ln2_hi is exact here */
2464 lo = t * ln2_lo;
2466 x = hi - lo;
2467 c = (hi - x) - lo;
2468 } else if (hx < 0x3c900000) { /* |x| < 2**-54, return x */
2469 fp_barrier(x + 0x1p120f);
2470 if (hx < 0x00100000)
2471 fp_barrier((float)x);
2472 return x;
2473 } else
2474 k = 0;
2476 /* x is now in primary range */
2477 hfx = 0.5 * x;
2478 hxs = x * hfx;
2479 r1 = 1.0 + hxs * (Q1 + hxs * (Q2 + hxs * (Q3 + hxs * (Q4 + hxs * Q5))));
2480 t = 3.0 - r1 * hfx;
2481 e = hxs * ((r1 - t) / (6.0 - x * t));
2482 if (k == 0) /* c is 0 */
2483 return x - (x * e - hxs);
2484 e = x * (e - c) - c;
2485 e -= hxs;
2486 /* exp(x) ~ 2^k (x_reduced - e + 1) */
2487 if (k == -1)
2488 return 0.5 * (x - e) - 0.5;
2489 if (k == 1) {
2490 if (x < -0.25)
2491 return -2.0 * (e - (x + 0.5));
2492 return 1.0 + 2.0 * (x - e);
2494 u.i = (UINT64)(0x3ff + k) << 52; /* 2^k */
2495 twopk = u.f;
2496 if (k < 0 || k > 56) { /* suffice to return exp(x)-1 */
2497 y = x - e + 1.0;
2498 if (k == 1024)
2499 y = y * 2.0 * 0x1p1023;
2500 else
2501 y = y * twopk;
2502 return y - 1.0;
2504 u.i = (UINT64)(0x3ff - k) << 52; /* 2^-k */
2505 if (k < 20)
2506 y = (x - e + (1 - u.f)) * twopk;
2507 else
2508 y = (x - (e + u.f) + 1) * twopk;
2509 return y;
2512 static double __expo2(double x, double sign)
2514 static const int k = 2043;
2515 static const double kln2 = 0x1.62066151add8bp+10;
2516 double scale;
2518 *(UINT64*)&scale = (UINT64)(0x3ff + k / 2) << 52;
2519 return exp(x - kln2) * (sign * scale) * scale;
2522 /*********************************************************************
2523 * cosh (MSVCRT.@)
2525 * Copied from musl: src/math/cosh.c
2527 double CDECL cosh( double x )
2529 UINT64 ux = *(UINT64*)&x;
2530 UINT32 w;
2531 double t;
2533 /* |x| */
2534 ux &= (uint64_t)-1 / 2;
2535 x = *(double*)&ux;
2536 w = ux >> 32;
2538 /* |x| < log(2) */
2539 if (w < 0x3fe62e42) {
2540 if (w < 0x3ff00000 - (26 << 20)) {
2541 fp_barrier(x + 0x1p120f);
2542 return 1;
2544 t = __expm1(x);
2545 return 1 + t * t / (2 * (1 + t));
2548 /* |x| < log(DBL_MAX) */
2549 if (w < 0x40862e42) {
2550 t = exp(x);
2551 /* note: if x>log(0x1p26) then the 1/t is not needed */
2552 return 0.5 * (t + 1 / t);
2555 /* |x| > log(DBL_MAX) or nan */
2556 /* note: the result is stored to handle overflow */
2557 t = __expo2(x, 1.0);
2558 return t;
2561 /*********************************************************************
2562 * exp (MSVCRT.@)
2564 double CDECL exp( double x )
2566 double ret = unix_funcs->exp( x );
2567 if (isnan(x)) return math_error(_DOMAIN, "exp", x, 0, ret);
2568 if (isfinite(x) && !ret) return math_error(_UNDERFLOW, "exp", x, 0, ret);
2569 if (isfinite(x) && !isfinite(ret)) return math_error(_OVERFLOW, "exp", x, 0, ret);
2570 return ret;
2573 /*********************************************************************
2574 * fmod (MSVCRT.@)
2576 * Copied from musl: src/math/fmod.c
2578 double CDECL fmod( double x, double y )
2580 UINT64 xi = *(UINT64*)&x;
2581 UINT64 yi = *(UINT64*)&y;
2582 int ex = xi >> 52 & 0x7ff;
2583 int ey = yi >> 52 & 0x7ff;
2584 int sx = xi >> 63;
2585 UINT64 i;
2587 if (isinf(x)) return math_error(_DOMAIN, "fmod", x, y, (x * y) / (x * y));
2588 if (yi << 1 == 0 || isnan(y) || ex == 0x7ff)
2589 return (x * y) / (x * y);
2590 if (xi << 1 <= yi << 1) {
2591 if (xi << 1 == yi << 1)
2592 return 0 * x;
2593 return x;
2596 /* normalize x and y */
2597 if (!ex) {
2598 for (i = xi << 12; i >> 63 == 0; ex--, i <<= 1);
2599 xi <<= -ex + 1;
2600 } else {
2601 xi &= -1ULL >> 12;
2602 xi |= 1ULL << 52;
2604 if (!ey) {
2605 for (i = yi << 12; i >> 63 == 0; ey--, i <<= 1);
2606 yi <<= -ey + 1;
2607 } else {
2608 yi &= -1ULL >> 12;
2609 yi |= 1ULL << 52;
2612 /* x mod y */
2613 for (; ex > ey; ex--) {
2614 i = xi - yi;
2615 if (i >> 63 == 0) {
2616 if (i == 0)
2617 return 0 * x;
2618 xi = i;
2620 xi <<= 1;
2622 i = xi - yi;
2623 if (i >> 63 == 0) {
2624 if (i == 0)
2625 return 0 * x;
2626 xi = i;
2628 for (; xi >> 52 == 0; xi <<= 1, ex--);
2630 /* scale result */
2631 if (ex > 0) {
2632 xi -= 1ULL << 52;
2633 xi |= (UINT64)ex << 52;
2634 } else {
2635 xi >>= -ex + 1;
2637 xi |= (UINT64)sx << 63;
2638 return *(double*)&xi;
2641 /*********************************************************************
2642 * log (MSVCRT.@)
2644 * Copied from musl: src/math/log.c src/math/log_data.c
2646 double CDECL log( double x )
2648 static const double Ln2hi = 0x1.62e42fefa3800p-1,
2649 Ln2lo = 0x1.ef35793c76730p-45;
2650 static const double A[] = {
2651 -0x1.0000000000001p-1,
2652 0x1.555555551305bp-2,
2653 -0x1.fffffffeb459p-3,
2654 0x1.999b324f10111p-3,
2655 -0x1.55575e506c89fp-3
2657 static const double B[] = {
2658 -0x1p-1,
2659 0x1.5555555555577p-2,
2660 -0x1.ffffffffffdcbp-3,
2661 0x1.999999995dd0cp-3,
2662 -0x1.55555556745a7p-3,
2663 0x1.24924a344de3p-3,
2664 -0x1.fffffa4423d65p-4,
2665 0x1.c7184282ad6cap-4,
2666 -0x1.999eb43b068ffp-4,
2667 0x1.78182f7afd085p-4,
2668 -0x1.5521375d145cdp-4
2670 static const struct {
2671 double invc, logc;
2672 } T[] = {
2673 {0x1.734f0c3e0de9fp+0, -0x1.7cc7f79e69000p-2},
2674 {0x1.713786a2ce91fp+0, -0x1.76feec20d0000p-2},
2675 {0x1.6f26008fab5a0p+0, -0x1.713e31351e000p-2},
2676 {0x1.6d1a61f138c7dp+0, -0x1.6b85b38287800p-2},
2677 {0x1.6b1490bc5b4d1p+0, -0x1.65d5590807800p-2},
2678 {0x1.69147332f0cbap+0, -0x1.602d076180000p-2},
2679 {0x1.6719f18224223p+0, -0x1.5a8ca86909000p-2},
2680 {0x1.6524f99a51ed9p+0, -0x1.54f4356035000p-2},
2681 {0x1.63356aa8f24c4p+0, -0x1.4f637c36b4000p-2},
2682 {0x1.614b36b9ddc14p+0, -0x1.49da7fda85000p-2},
2683 {0x1.5f66452c65c4cp+0, -0x1.445923989a800p-2},
2684 {0x1.5d867b5912c4fp+0, -0x1.3edf439b0b800p-2},
2685 {0x1.5babccb5b90dep+0, -0x1.396ce448f7000p-2},
2686 {0x1.59d61f2d91a78p+0, -0x1.3401e17bda000p-2},
2687 {0x1.5805612465687p+0, -0x1.2e9e2ef468000p-2},
2688 {0x1.56397cee76bd3p+0, -0x1.2941b3830e000p-2},
2689 {0x1.54725e2a77f93p+0, -0x1.23ec58cda8800p-2},
2690 {0x1.52aff42064583p+0, -0x1.1e9e129279000p-2},
2691 {0x1.50f22dbb2bddfp+0, -0x1.1956d2b48f800p-2},
2692 {0x1.4f38f4734ded7p+0, -0x1.141679ab9f800p-2},
2693 {0x1.4d843cfde2840p+0, -0x1.0edd094ef9800p-2},
2694 {0x1.4bd3ec078a3c8p+0, -0x1.09aa518db1000p-2},
2695 {0x1.4a27fc3e0258ap+0, -0x1.047e65263b800p-2},
2696 {0x1.4880524d48434p+0, -0x1.feb224586f000p-3},
2697 {0x1.46dce1b192d0bp+0, -0x1.f474a7517b000p-3},
2698 {0x1.453d9d3391854p+0, -0x1.ea4443d103000p-3},
2699 {0x1.43a2744b4845ap+0, -0x1.e020d44e9b000p-3},
2700 {0x1.420b54115f8fbp+0, -0x1.d60a22977f000p-3},
2701 {0x1.40782da3ef4b1p+0, -0x1.cc00104959000p-3},
2702 {0x1.3ee8f5d57fe8fp+0, -0x1.c202956891000p-3},
2703 {0x1.3d5d9a00b4ce9p+0, -0x1.b81178d811000p-3},
2704 {0x1.3bd60c010c12bp+0, -0x1.ae2c9ccd3d000p-3},
2705 {0x1.3a5242b75dab8p+0, -0x1.a45402e129000p-3},
2706 {0x1.38d22cd9fd002p+0, -0x1.9a877681df000p-3},
2707 {0x1.3755bc5847a1cp+0, -0x1.90c6d69483000p-3},
2708 {0x1.35dce49ad36e2p+0, -0x1.87120a645c000p-3},
2709 {0x1.34679984dd440p+0, -0x1.7d68fb4143000p-3},
2710 {0x1.32f5cceffcb24p+0, -0x1.73cb83c627000p-3},
2711 {0x1.3187775a10d49p+0, -0x1.6a39a9b376000p-3},
2712 {0x1.301c8373e3990p+0, -0x1.60b3154b7a000p-3},
2713 {0x1.2eb4ebb95f841p+0, -0x1.5737d76243000p-3},
2714 {0x1.2d50a0219a9d1p+0, -0x1.4dc7b8fc23000p-3},
2715 {0x1.2bef9a8b7fd2ap+0, -0x1.4462c51d20000p-3},
2716 {0x1.2a91c7a0c1babp+0, -0x1.3b08abc830000p-3},
2717 {0x1.293726014b530p+0, -0x1.31b996b490000p-3},
2718 {0x1.27dfa5757a1f5p+0, -0x1.2875490a44000p-3},
2719 {0x1.268b39b1d3bbfp+0, -0x1.1f3b9f879a000p-3},
2720 {0x1.2539d838ff5bdp+0, -0x1.160c8252ca000p-3},
2721 {0x1.23eb7aac9083bp+0, -0x1.0ce7f57f72000p-3},
2722 {0x1.22a012ba940b6p+0, -0x1.03cdc49fea000p-3},
2723 {0x1.2157996cc4132p+0, -0x1.f57bdbc4b8000p-4},
2724 {0x1.201201dd2fc9bp+0, -0x1.e370896404000p-4},
2725 {0x1.1ecf4494d480bp+0, -0x1.d17983ef94000p-4},
2726 {0x1.1d8f5528f6569p+0, -0x1.bf9674ed8a000p-4},
2727 {0x1.1c52311577e7cp+0, -0x1.adc79202f6000p-4},
2728 {0x1.1b17c74cb26e9p+0, -0x1.9c0c3e7288000p-4},
2729 {0x1.19e010c2c1ab6p+0, -0x1.8a646b372c000p-4},
2730 {0x1.18ab07bb670bdp+0, -0x1.78d01b3ac0000p-4},
2731 {0x1.1778a25efbcb6p+0, -0x1.674f145380000p-4},
2732 {0x1.1648d354c31dap+0, -0x1.55e0e6d878000p-4},
2733 {0x1.151b990275fddp+0, -0x1.4485cdea1e000p-4},
2734 {0x1.13f0ea432d24cp+0, -0x1.333d94d6aa000p-4},
2735 {0x1.12c8b7210f9dap+0, -0x1.22079f8c56000p-4},
2736 {0x1.11a3028ecb531p+0, -0x1.10e4698622000p-4},
2737 {0x1.107fbda8434afp+0, -0x1.ffa6c6ad20000p-5},
2738 {0x1.0f5ee0f4e6bb3p+0, -0x1.dda8d4a774000p-5},
2739 {0x1.0e4065d2a9fcep+0, -0x1.bbcece4850000p-5},
2740 {0x1.0d244632ca521p+0, -0x1.9a1894012c000p-5},
2741 {0x1.0c0a77ce2981ap+0, -0x1.788583302c000p-5},
2742 {0x1.0af2f83c636d1p+0, -0x1.5715e67d68000p-5},
2743 {0x1.09ddb98a01339p+0, -0x1.35c8a49658000p-5},
2744 {0x1.08cabaf52e7dfp+0, -0x1.149e364154000p-5},
2745 {0x1.07b9f2f4e28fbp+0, -0x1.e72c082eb8000p-6},
2746 {0x1.06ab58c358f19p+0, -0x1.a55f152528000p-6},
2747 {0x1.059eea5ecf92cp+0, -0x1.63d62cf818000p-6},
2748 {0x1.04949cdd12c90p+0, -0x1.228fb8caa0000p-6},
2749 {0x1.038c6c6f0ada9p+0, -0x1.c317b20f90000p-7},
2750 {0x1.02865137932a9p+0, -0x1.419355daa0000p-7},
2751 {0x1.0182427ea7348p+0, -0x1.81203c2ec0000p-8},
2752 {0x1.008040614b195p+0, -0x1.0040979240000p-9},
2753 {0x1.fe01ff726fa1ap-1, 0x1.feff384900000p-9},
2754 {0x1.fa11cc261ea74p-1, 0x1.7dc41353d0000p-7},
2755 {0x1.f6310b081992ep-1, 0x1.3cea3c4c28000p-6},
2756 {0x1.f25f63ceeadcdp-1, 0x1.b9fc114890000p-6},
2757 {0x1.ee9c8039113e7p-1, 0x1.1b0d8ce110000p-5},
2758 {0x1.eae8078cbb1abp-1, 0x1.58a5bd001c000p-5},
2759 {0x1.e741aa29d0c9bp-1, 0x1.95c8340d88000p-5},
2760 {0x1.e3a91830a99b5p-1, 0x1.d276aef578000p-5},
2761 {0x1.e01e009609a56p-1, 0x1.07598e598c000p-4},
2762 {0x1.dca01e577bb98p-1, 0x1.253f5e30d2000p-4},
2763 {0x1.d92f20b7c9103p-1, 0x1.42edd8b380000p-4},
2764 {0x1.d5cac66fb5ccep-1, 0x1.606598757c000p-4},
2765 {0x1.d272caa5ede9dp-1, 0x1.7da76356a0000p-4},
2766 {0x1.cf26e3e6b2ccdp-1, 0x1.9ab434e1c6000p-4},
2767 {0x1.cbe6da2a77902p-1, 0x1.b78c7bb0d6000p-4},
2768 {0x1.c8b266d37086dp-1, 0x1.d431332e72000p-4},
2769 {0x1.c5894bd5d5804p-1, 0x1.f0a3171de6000p-4},
2770 {0x1.c26b533bb9f8cp-1, 0x1.067152b914000p-3},
2771 {0x1.bf583eeece73fp-1, 0x1.147858292b000p-3},
2772 {0x1.bc4fd75db96c1p-1, 0x1.2266ecdca3000p-3},
2773 {0x1.b951e0c864a28p-1, 0x1.303d7a6c55000p-3},
2774 {0x1.b65e2c5ef3e2cp-1, 0x1.3dfc33c331000p-3},
2775 {0x1.b374867c9888bp-1, 0x1.4ba366b7a8000p-3},
2776 {0x1.b094b211d304ap-1, 0x1.5933928d1f000p-3},
2777 {0x1.adbe885f2ef7ep-1, 0x1.66acd2418f000p-3},
2778 {0x1.aaf1d31603da2p-1, 0x1.740f8ec669000p-3},
2779 {0x1.a82e63fd358a7p-1, 0x1.815c0f51af000p-3},
2780 {0x1.a5740ef09738bp-1, 0x1.8e92954f68000p-3},
2781 {0x1.a2c2a90ab4b27p-1, 0x1.9bb3602f84000p-3},
2782 {0x1.a01a01393f2d1p-1, 0x1.a8bed1c2c0000p-3},
2783 {0x1.9d79f24db3c1bp-1, 0x1.b5b515c01d000p-3},
2784 {0x1.9ae2505c7b190p-1, 0x1.c2967ccbcc000p-3},
2785 {0x1.9852ef297ce2fp-1, 0x1.cf635d5486000p-3},
2786 {0x1.95cbaeea44b75p-1, 0x1.dc1bd3446c000p-3},
2787 {0x1.934c69de74838p-1, 0x1.e8c01b8cfe000p-3},
2788 {0x1.90d4f2f6752e6p-1, 0x1.f5509c0179000p-3},
2789 {0x1.8e6528effd79dp-1, 0x1.00e6c121fb800p-2},
2790 {0x1.8bfce9fcc007cp-1, 0x1.071b80e93d000p-2},
2791 {0x1.899c0dabec30ep-1, 0x1.0d46b9e867000p-2},
2792 {0x1.87427aa2317fbp-1, 0x1.13687334bd000p-2},
2793 {0x1.84f00acb39a08p-1, 0x1.1980d67234800p-2},
2794 {0x1.82a49e8653e55p-1, 0x1.1f8ffe0cc8000p-2},
2795 {0x1.8060195f40260p-1, 0x1.2595fd7636800p-2},
2796 {0x1.7e22563e0a329p-1, 0x1.2b9300914a800p-2},
2797 {0x1.7beb377dcb5adp-1, 0x1.3187210436000p-2},
2798 {0x1.79baa679725c2p-1, 0x1.377266dec1800p-2},
2799 {0x1.77907f2170657p-1, 0x1.3d54ffbaf3000p-2},
2800 {0x1.756cadbd6130cp-1, 0x1.432eee32fe000p-2}
2802 static const struct {
2803 double chi, clo;
2804 } T2[] = {
2805 {0x1.61000014fb66bp-1, 0x1.e026c91425b3cp-56},
2806 {0x1.63000034db495p-1, 0x1.dbfea48005d41p-55},
2807 {0x1.650000d94d478p-1, 0x1.e7fa786d6a5b7p-55},
2808 {0x1.67000074e6fadp-1, 0x1.1fcea6b54254cp-57},
2809 {0x1.68ffffedf0faep-1, -0x1.c7e274c590efdp-56},
2810 {0x1.6b0000763c5bcp-1, -0x1.ac16848dcda01p-55},
2811 {0x1.6d0001e5cc1f6p-1, 0x1.33f1c9d499311p-55},
2812 {0x1.6efffeb05f63ep-1, -0x1.e80041ae22d53p-56},
2813 {0x1.710000e86978p-1, 0x1.bff6671097952p-56},
2814 {0x1.72ffffc67e912p-1, 0x1.c00e226bd8724p-55},
2815 {0x1.74fffdf81116ap-1, -0x1.e02916ef101d2p-57},
2816 {0x1.770000f679c9p-1, -0x1.7fc71cd549c74p-57},
2817 {0x1.78ffffa7ec835p-1, 0x1.1bec19ef50483p-55},
2818 {0x1.7affffe20c2e6p-1, -0x1.07e1729cc6465p-56},
2819 {0x1.7cfffed3fc9p-1, -0x1.08072087b8b1cp-55},
2820 {0x1.7efffe9261a76p-1, 0x1.dc0286d9df9aep-55},
2821 {0x1.81000049ca3e8p-1, 0x1.97fd251e54c33p-55},
2822 {0x1.8300017932c8fp-1, -0x1.afee9b630f381p-55},
2823 {0x1.850000633739cp-1, 0x1.9bfbf6b6535bcp-55},
2824 {0x1.87000204289c6p-1, -0x1.bbf65f3117b75p-55},
2825 {0x1.88fffebf57904p-1, -0x1.9006ea23dcb57p-55},
2826 {0x1.8b00022bc04dfp-1, -0x1.d00df38e04b0ap-56},
2827 {0x1.8cfffe50c1b8ap-1, -0x1.8007146ff9f05p-55},
2828 {0x1.8effffc918e43p-1, 0x1.3817bd07a7038p-55},
2829 {0x1.910001efa5fc7p-1, 0x1.93e9176dfb403p-55},
2830 {0x1.9300013467bb9p-1, 0x1.f804e4b980276p-56},
2831 {0x1.94fffe6ee076fp-1, -0x1.f7ef0d9ff622ep-55},
2832 {0x1.96fffde3c12d1p-1, -0x1.082aa962638bap-56},
2833 {0x1.98ffff4458a0dp-1, -0x1.7801b9164a8efp-55},
2834 {0x1.9afffdd982e3ep-1, -0x1.740e08a5a9337p-55},
2835 {0x1.9cfffed49fb66p-1, 0x1.fce08c19bep-60},
2836 {0x1.9f00020f19c51p-1, -0x1.a3faa27885b0ap-55},
2837 {0x1.a10001145b006p-1, 0x1.4ff489958da56p-56},
2838 {0x1.a300007bbf6fap-1, 0x1.cbeab8a2b6d18p-55},
2839 {0x1.a500010971d79p-1, 0x1.8fecadd78793p-55},
2840 {0x1.a70001df52e48p-1, -0x1.f41763dd8abdbp-55},
2841 {0x1.a90001c593352p-1, -0x1.ebf0284c27612p-55},
2842 {0x1.ab0002a4f3e4bp-1, -0x1.9fd043cff3f5fp-57},
2843 {0x1.acfffd7ae1ed1p-1, -0x1.23ee7129070b4p-55},
2844 {0x1.aefffee510478p-1, 0x1.a063ee00edea3p-57},
2845 {0x1.b0fffdb650d5bp-1, 0x1.a06c8381f0ab9p-58},
2846 {0x1.b2ffffeaaca57p-1, -0x1.9011e74233c1dp-56},
2847 {0x1.b4fffd995badcp-1, -0x1.9ff1068862a9fp-56},
2848 {0x1.b7000249e659cp-1, 0x1.aff45d0864f3ep-55},
2849 {0x1.b8ffff987164p-1, 0x1.cfe7796c2c3f9p-56},
2850 {0x1.bafffd204cb4fp-1, -0x1.3ff27eef22bc4p-57},
2851 {0x1.bcfffd2415c45p-1, -0x1.cffb7ee3bea21p-57},
2852 {0x1.beffff86309dfp-1, -0x1.14103972e0b5cp-55},
2853 {0x1.c0fffe1b57653p-1, 0x1.bc16494b76a19p-55},
2854 {0x1.c2ffff1fa57e3p-1, -0x1.4feef8d30c6edp-57},
2855 {0x1.c4fffdcbfe424p-1, -0x1.43f68bcec4775p-55},
2856 {0x1.c6fffed54b9f7p-1, 0x1.47ea3f053e0ecp-55},
2857 {0x1.c8fffeb998fd5p-1, 0x1.383068df992f1p-56},
2858 {0x1.cb0002125219ap-1, -0x1.8fd8e64180e04p-57},
2859 {0x1.ccfffdd94469cp-1, 0x1.e7ebe1cc7ea72p-55},
2860 {0x1.cefffeafdc476p-1, 0x1.ebe39ad9f88fep-55},
2861 {0x1.d1000169af82bp-1, 0x1.57d91a8b95a71p-56},
2862 {0x1.d30000d0ff71dp-1, 0x1.9c1906970c7dap-55},
2863 {0x1.d4fffea790fc4p-1, -0x1.80e37c558fe0cp-58},
2864 {0x1.d70002edc87e5p-1, -0x1.f80d64dc10f44p-56},
2865 {0x1.d900021dc82aap-1, -0x1.47c8f94fd5c5cp-56},
2866 {0x1.dafffd86b0283p-1, 0x1.c7f1dc521617ep-55},
2867 {0x1.dd000296c4739p-1, 0x1.8019eb2ffb153p-55},
2868 {0x1.defffe54490f5p-1, 0x1.e00d2c652cc89p-57},
2869 {0x1.e0fffcdabf694p-1, -0x1.f8340202d69d2p-56},
2870 {0x1.e2fffdb52c8ddp-1, 0x1.b00c1ca1b0864p-56},
2871 {0x1.e4ffff24216efp-1, 0x1.2ffa8b094ab51p-56},
2872 {0x1.e6fffe88a5e11p-1, -0x1.7f673b1efbe59p-58},
2873 {0x1.e9000119eff0dp-1, -0x1.4808d5e0bc801p-55},
2874 {0x1.eafffdfa51744p-1, 0x1.80006d54320b5p-56},
2875 {0x1.ed0001a127fa1p-1, -0x1.002f860565c92p-58},
2876 {0x1.ef00007babcc4p-1, -0x1.540445d35e611p-55},
2877 {0x1.f0ffff57a8d02p-1, -0x1.ffb3139ef9105p-59},
2878 {0x1.f30001ee58ac7p-1, 0x1.a81acf2731155p-55},
2879 {0x1.f4ffff5823494p-1, 0x1.a3f41d4d7c743p-55},
2880 {0x1.f6ffffca94c6bp-1, -0x1.202f41c987875p-57},
2881 {0x1.f8fffe1f9c441p-1, 0x1.77dd1f477e74bp-56},
2882 {0x1.fafffd2e0e37ep-1, -0x1.f01199a7ca331p-57},
2883 {0x1.fd0001c77e49ep-1, 0x1.181ee4bceacb1p-56},
2884 {0x1.feffff7e0c331p-1, -0x1.e05370170875ap-57},
2885 {0x1.00ffff465606ep+0, -0x1.a7ead491c0adap-55},
2886 {0x1.02ffff3867a58p+0, -0x1.77f69c3fcb2ep-54},
2887 {0x1.04ffffdfc0d17p+0, 0x1.7bffe34cb945bp-54},
2888 {0x1.0700003cd4d82p+0, 0x1.20083c0e456cbp-55},
2889 {0x1.08ffff9f2cbe8p+0, -0x1.dffdfbe37751ap-57},
2890 {0x1.0b000010cda65p+0, -0x1.13f7faee626ebp-54},
2891 {0x1.0d00001a4d338p+0, 0x1.07dfa79489ff7p-55},
2892 {0x1.0effffadafdfdp+0, -0x1.7040570d66bcp-56},
2893 {0x1.110000bbafd96p+0, 0x1.e80d4846d0b62p-55},
2894 {0x1.12ffffae5f45dp+0, 0x1.dbffa64fd36efp-54},
2895 {0x1.150000dd59ad9p+0, 0x1.a0077701250aep-54},
2896 {0x1.170000f21559ap+0, 0x1.dfdf9e2e3deeep-55},
2897 {0x1.18ffffc275426p+0, 0x1.10030dc3b7273p-54},
2898 {0x1.1b000123d3c59p+0, 0x1.97f7980030188p-54},
2899 {0x1.1cffff8299eb7p+0, -0x1.5f932ab9f8c67p-57},
2900 {0x1.1effff48ad4p+0, 0x1.37fbf9da75bebp-54},
2901 {0x1.210000c8b86a4p+0, 0x1.f806b91fd5b22p-54},
2902 {0x1.2300003854303p+0, 0x1.3ffc2eb9fbf33p-54},
2903 {0x1.24fffffbcf684p+0, 0x1.601e77e2e2e72p-56},
2904 {0x1.26ffff52921d9p+0, 0x1.ffcbb767f0c61p-56},
2905 {0x1.2900014933a3cp+0, -0x1.202ca3c02412bp-56},
2906 {0x1.2b00014556313p+0, -0x1.2808233f21f02p-54},
2907 {0x1.2cfffebfe523bp+0, -0x1.8ff7e384fdcf2p-55},
2908 {0x1.2f0000bb8ad96p+0, -0x1.5ff51503041c5p-55},
2909 {0x1.30ffffb7ae2afp+0, -0x1.10071885e289dp-55},
2910 {0x1.32ffffeac5f7fp+0, -0x1.1ff5d3fb7b715p-54},
2911 {0x1.350000ca66756p+0, 0x1.57f82228b82bdp-54},
2912 {0x1.3700011fbf721p+0, 0x1.000bac40dd5ccp-55},
2913 {0x1.38ffff9592fb9p+0, -0x1.43f9d2db2a751p-54},
2914 {0x1.3b00004ddd242p+0, 0x1.57f6b707638e1p-55},
2915 {0x1.3cffff5b2c957p+0, 0x1.a023a10bf1231p-56},
2916 {0x1.3efffeab0b418p+0, 0x1.87f6d66b152bp-54},
2917 {0x1.410001532aff4p+0, 0x1.7f8375f198524p-57},
2918 {0x1.4300017478b29p+0, 0x1.301e672dc5143p-55},
2919 {0x1.44fffe795b463p+0, 0x1.9ff69b8b2895ap-55},
2920 {0x1.46fffe80475ep+0, -0x1.5c0b19bc2f254p-54},
2921 {0x1.48fffef6fc1e7p+0, 0x1.b4009f23a2a72p-54},
2922 {0x1.4afffe5bea704p+0, -0x1.4ffb7bf0d7d45p-54},
2923 {0x1.4d000171027dep+0, -0x1.9c06471dc6a3dp-54},
2924 {0x1.4f0000ff03ee2p+0, 0x1.77f890b85531cp-54},
2925 {0x1.5100012dc4bd1p+0, 0x1.004657166a436p-57},
2926 {0x1.530001605277ap+0, -0x1.6bfcece233209p-54},
2927 {0x1.54fffecdb704cp+0, -0x1.902720505a1d7p-55},
2928 {0x1.56fffef5f54a9p+0, 0x1.bbfe60ec96412p-54},
2929 {0x1.5900017e61012p+0, 0x1.87ec581afef9p-55},
2930 {0x1.5b00003c93e92p+0, -0x1.f41080abf0ccp-54},
2931 {0x1.5d0001d4919bcp+0, -0x1.8812afb254729p-54},
2932 {0x1.5efffe7b87a89p+0, -0x1.47eb780ed6904p-54}
2935 double w, z, r, r2, r3, y, invc, logc, kd, hi, lo;
2936 UINT64 ix, iz, tmp;
2937 UINT32 top;
2938 int k, i;
2940 ix = *(UINT64*)&x;
2941 top = ix >> 48;
2942 if (ix - 0x3fee000000000000ULL < 0x3090000000000ULL) {
2943 double rhi, rlo;
2945 /* Handle close to 1.0 inputs separately. */
2946 /* Fix sign of zero with downward rounding when x==1. */
2947 if (ix == 0x3ff0000000000000ULL)
2948 return 0;
2949 r = x - 1.0;
2950 r2 = r * r;
2951 r3 = r * r2;
2952 y = r3 * (B[1] + r * B[2] + r2 * B[3] + r3 * (B[4] + r * B[5] + r2 * B[6] +
2953 r3 * (B[7] + r * B[8] + r2 * B[9] + r3 * B[10])));
2954 /* Worst-case error is around 0.507 ULP. */
2955 w = r * 0x1p27;
2956 rhi = r + w - w;
2957 rlo = r - rhi;
2958 w = rhi * rhi * B[0]; /* B[0] == -0.5. */
2959 hi = r + w;
2960 lo = r - hi + w;
2961 lo += B[0] * rlo * (rhi + r);
2962 y += lo;
2963 y += hi;
2964 return y;
2966 if (top - 0x0010 >= 0x7ff0 - 0x0010) {
2967 /* x < 0x1p-1022 or inf or nan. */
2968 if (ix * 2 == 0)
2969 return math_error(_SING, "log", x, 0, (top & 0x8000 ? 1.0 : -1.0) / x);
2970 if (ix == 0x7ff0000000000000ULL) /* log(inf) == inf. */
2971 return x;
2972 if ((top & 0x7ff0) == 0x7ff0 && (ix & 0xfffffffffffffULL))
2973 return x;
2974 if (top & 0x8000)
2975 return math_error(_DOMAIN, "log", x, 0, (x - x) / (x - x));
2976 /* x is subnormal, normalize it. */
2977 x *= 0x1p52;
2978 ix = *(UINT64*)&x;
2979 ix -= 52ULL << 52;
2982 /* x = 2^k z; where z is in range [OFF,2*OFF) and exact.
2983 The range is split into N subintervals.
2984 The ith subinterval contains z and c is near its center. */
2985 tmp = ix - 0x3fe6000000000000ULL;
2986 i = (tmp >> (52 - 7)) % (1 << 7);
2987 k = (INT64)tmp >> 52; /* arithmetic shift */
2988 iz = ix - (tmp & 0xfffULL << 52);
2989 invc = T[i].invc;
2990 logc = T[i].logc;
2991 z = *(double*)&iz;
2993 /* log(x) = log1p(z/c-1) + log(c) + k*Ln2. */
2994 /* r ~= z/c - 1, |r| < 1/(2*N). */
2995 r = (z - T2[i].chi - T2[i].clo) * invc;
2996 kd = (double)k;
2998 /* hi + lo = r + log(c) + k*Ln2. */
2999 w = kd * Ln2hi + logc;
3000 hi = w + r;
3001 lo = w - hi + r + kd * Ln2lo;
3003 /* log(x) = lo + (log1p(r) - r) + hi. */
3004 r2 = r * r; /* rounding error: 0x1p-54/N^2. */
3005 /* Worst case error if |y| > 0x1p-5:
3006 0.5 + 4.13/N + abs-poly-error*2^57 ULP (+ 0.002 ULP without fma)
3007 Worst case error if |y| > 0x1p-4:
3008 0.5 + 2.06/N + abs-poly-error*2^56 ULP (+ 0.001 ULP without fma). */
3009 y = lo + r2 * A[0] +
3010 r * r2 * (A[1] + r * A[2] + r2 * (A[3] + r * A[4])) + hi;
3011 return y;
3014 /*********************************************************************
3015 * log10 (MSVCRT.@)
3017 double CDECL log10( double x )
3019 static const double ivln10hi = 4.34294481878168880939e-01,
3020 ivln10lo = 2.50829467116452752298e-11,
3021 log10_2hi = 3.01029995663611771306e-01,
3022 log10_2lo = 3.69423907715893078616e-13,
3023 Lg1 = 6.666666666666735130e-01,
3024 Lg2 = 3.999999999940941908e-01,
3025 Lg3 = 2.857142874366239149e-01,
3026 Lg4 = 2.222219843214978396e-01,
3027 Lg5 = 1.818357216161805012e-01,
3028 Lg6 = 1.531383769920937332e-01,
3029 Lg7 = 1.479819860511658591e-01;
3031 union {double f; UINT64 i;} u = {x};
3032 double hfsq, f, s, z, R, w, t1, t2, dk, y, hi, lo, val_hi, val_lo;
3033 UINT32 hx;
3034 int k;
3036 hx = u.i >> 32;
3037 k = 0;
3038 if (hx < 0x00100000 || hx >> 31) {
3039 if (u.i << 1 == 0)
3040 return math_error(_SING, "log10", x, 0, -1 / (x * x));
3041 if ((u.i & ~(1ULL << 63)) > 0x7ff0000000000000ULL)
3042 return x;
3043 if (hx >> 31)
3044 return math_error(_DOMAIN, "log10", x, 0, (x - x) / (x - x));
3045 /* subnormal number, scale x up */
3046 k -= 54;
3047 x *= 0x1p54;
3048 u.f = x;
3049 hx = u.i >> 32;
3050 } else if (hx >= 0x7ff00000) {
3051 return x;
3052 } else if (hx == 0x3ff00000 && u.i<<32 == 0)
3053 return 0;
3055 /* reduce x into [sqrt(2)/2, sqrt(2)] */
3056 hx += 0x3ff00000 - 0x3fe6a09e;
3057 k += (int)(hx >> 20) - 0x3ff;
3058 hx = (hx & 0x000fffff) + 0x3fe6a09e;
3059 u.i = (UINT64)hx << 32 | (u.i & 0xffffffff);
3060 x = u.f;
3062 f = x - 1.0;
3063 hfsq = 0.5 * f * f;
3064 s = f / (2.0 + f);
3065 z = s * s;
3066 w = z * z;
3067 t1 = w * (Lg2 + w * (Lg4 + w * Lg6));
3068 t2 = z * (Lg1 + w * (Lg3 + w * (Lg5 + w * Lg7)));
3069 R = t2 + t1;
3071 /* hi+lo = f - hfsq + s*(hfsq+R) ~ log(1+f) */
3072 hi = f - hfsq;
3073 u.f = hi;
3074 u.i &= (UINT64)-1 << 32;
3075 hi = u.f;
3076 lo = f - hi - hfsq + s * (hfsq + R);
3078 /* val_hi+val_lo ~ log10(1+f) + k*log10(2) */
3079 val_hi = hi * ivln10hi;
3080 dk = k;
3081 y = dk * log10_2hi;
3082 val_lo = dk * log10_2lo + (lo + hi) * ivln10lo + lo * ivln10hi;
3085 * Extra precision in for adding y is not strictly needed
3086 * since there is no very large cancellation near x = sqrt(2) or
3087 * x = 1/sqrt(2), but we do it anyway since it costs little on CPUs
3088 * with some parallelism and it reduces the error for many args.
3090 w = y + val_hi;
3091 val_lo += (y - w) + val_hi;
3092 val_hi = w;
3094 return val_lo + val_hi;
3097 /*********************************************************************
3098 * pow (MSVCRT.@)
3100 double CDECL pow( double x, double y )
3102 double z = unix_funcs->pow(x,y);
3103 if (x < 0 && y != floor(y))
3104 return math_error(_DOMAIN, "pow", x, y, z);
3105 if (!x && isfinite(y) && y < 0)
3106 return math_error(_SING, "pow", x, y, z);
3107 if (isfinite(x) && isfinite(y) && !isfinite(z))
3108 return math_error(_OVERFLOW, "pow", x, y, z);
3109 if (x && isfinite(x) && isfinite(y) && !z)
3110 return math_error(_UNDERFLOW, "pow", x, y, z);
3111 return z;
3114 /*********************************************************************
3115 * sin (MSVCRT.@)
3117 * Copied from musl: src/math/sin.c
3119 double CDECL sin( double x )
3121 double y[2];
3122 UINT32 ix;
3123 unsigned n;
3125 ix = *(ULONGLONG*)&x >> 32;
3126 ix &= 0x7fffffff;
3128 /* |x| ~< pi/4 */
3129 if (ix <= 0x3fe921fb) {
3130 if (ix < 0x3e500000) { /* |x| < 2**-26 */
3131 /* raise inexact if x != 0 and underflow if subnormal*/
3132 fp_barrier(ix < 0x00100000 ? x/0x1p120f : x+0x1p120f);
3133 return x;
3135 return __sin(x, 0.0, 0);
3138 /* sin(Inf or NaN) is NaN */
3139 if (isinf(x))
3140 return math_error(_DOMAIN, "sin", x, 0, x - x);
3141 if (ix >= 0x7ff00000)
3142 return x - x;
3144 /* argument reduction needed */
3145 n = __rem_pio2(x, y);
3146 switch (n&3) {
3147 case 0: return __sin(y[0], y[1], 1);
3148 case 1: return __cos(y[0], y[1]);
3149 case 2: return -__sin(y[0], y[1], 1);
3150 default: return -__cos(y[0], y[1]);
3154 /*********************************************************************
3155 * sinh (MSVCRT.@)
3157 double CDECL sinh( double x )
3159 UINT64 ux = *(UINT64*)&x;
3160 UINT32 w;
3161 double t, h, absx;
3163 h = 0.5;
3164 if (ux >> 63)
3165 h = -h;
3166 /* |x| */
3167 ux &= (UINT64)-1 / 2;
3168 absx = *(double*)&ux;
3169 w = ux >> 32;
3171 /* |x| < log(DBL_MAX) */
3172 if (w < 0x40862e42) {
3173 t = __expm1(absx);
3174 if (w < 0x3ff00000) {
3175 if (w < 0x3ff00000 - (26 << 20))
3176 return x;
3177 return h * (2 * t - t * t / (t + 1));
3179 return h * (t + t / (t + 1));
3182 /* |x| > log(DBL_MAX) or nan */
3183 /* note: the result is stored to handle overflow */
3184 t = __expo2(absx, 2 * h);
3185 return t;
3188 static BOOL sqrt_validate( double *x, BOOL update_sw )
3190 short c = _dclass(*x);
3192 if (c == FP_ZERO) return FALSE;
3193 if (c == FP_NAN)
3195 #ifdef __i386__
3196 if (update_sw)
3197 *x = math_error(_DOMAIN, "sqrt", *x, 0, *x);
3198 #else
3199 /* set signaling bit */
3200 *(ULONGLONG*)x |= 0x8000000000000ULL;
3201 #endif
3202 return FALSE;
3204 if (signbit(*x))
3206 *x = math_error(_DOMAIN, "sqrt", *x, 0, ret_nan(update_sw));
3207 return FALSE;
3209 if (c == FP_INFINITE) return FALSE;
3210 return TRUE;
3213 #if defined(__x86_64__) || defined(__i386__)
3214 double CDECL sse2_sqrt(double);
3215 __ASM_GLOBAL_FUNC( sse2_sqrt,
3216 "sqrtsd %xmm0, %xmm0\n\t"
3217 "ret" )
3218 #endif
3220 #ifdef __i386__
3221 double CDECL x87_sqrt(double);
3222 __ASM_GLOBAL_FUNC( x87_sqrt,
3223 "fldl 4(%esp)\n\t"
3224 SET_X87_CW(0xc00)
3225 "fsqrt\n\t"
3226 RESET_X87_CW
3227 "ret" )
3228 #endif
3230 /*********************************************************************
3231 * sqrt (MSVCRT.@)
3233 * Copied from musl: src/math/sqrt.c
3235 double CDECL sqrt( double x )
3237 #ifdef __x86_64__
3238 if (!sqrt_validate(&x, TRUE))
3239 return x;
3241 return sse2_sqrt(x);
3242 #elif defined( __i386__ )
3243 if (!sqrt_validate(&x, TRUE))
3244 return x;
3246 return x87_sqrt(x);
3247 #else
3248 static const double tiny = 1.0e-300;
3250 double z;
3251 int sign = 0x80000000;
3252 int ix0,s0,q,m,t,i;
3253 unsigned int r,t1,s1,ix1,q1;
3254 ULONGLONG ix;
3256 if (!sqrt_validate(&x, TRUE))
3257 return x;
3259 ix = *(ULONGLONG*)&x;
3260 ix0 = ix >> 32;
3261 ix1 = ix;
3263 /* normalize x */
3264 m = ix0 >> 20;
3265 if (m == 0) { /* subnormal x */
3266 while (ix0 == 0) {
3267 m -= 21;
3268 ix0 |= (ix1 >> 11);
3269 ix1 <<= 21;
3271 for (i=0; (ix0 & 0x00100000) == 0; i++)
3272 ix0 <<= 1;
3273 m -= i - 1;
3274 ix0 |= ix1 >> (32 - i);
3275 ix1 <<= i;
3277 m -= 1023; /* unbias exponent */
3278 ix0 = (ix0 & 0x000fffff) | 0x00100000;
3279 if (m & 1) { /* odd m, double x to make it even */
3280 ix0 += ix0 + ((ix1 & sign) >> 31);
3281 ix1 += ix1;
3283 m >>= 1; /* m = [m/2] */
3285 /* generate sqrt(x) bit by bit */
3286 ix0 += ix0 + ((ix1 & sign) >> 31);
3287 ix1 += ix1;
3288 q = q1 = s0 = s1 = 0; /* [q,q1] = sqrt(x) */
3289 r = 0x00200000; /* r = moving bit from right to left */
3291 while (r != 0) {
3292 t = s0 + r;
3293 if (t <= ix0) {
3294 s0 = t + r;
3295 ix0 -= t;
3296 q += r;
3298 ix0 += ix0 + ((ix1 & sign) >> 31);
3299 ix1 += ix1;
3300 r >>= 1;
3303 r = sign;
3304 while (r != 0) {
3305 t1 = s1 + r;
3306 t = s0;
3307 if (t < ix0 || (t == ix0 && t1 <= ix1)) {
3308 s1 = t1 + r;
3309 if ((t1&sign) == sign && (s1 & sign) == 0)
3310 s0++;
3311 ix0 -= t;
3312 if (ix1 < t1)
3313 ix0--;
3314 ix1 -= t1;
3315 q1 += r;
3317 ix0 += ix0 + ((ix1 & sign) >> 31);
3318 ix1 += ix1;
3319 r >>= 1;
3322 /* use floating add to find out rounding direction */
3323 if ((ix0 | ix1) != 0) {
3324 z = 1.0 - tiny; /* raise inexact flag */
3325 if (z >= 1.0) {
3326 z = 1.0 + tiny;
3327 if (q1 == (unsigned int)0xffffffff) {
3328 q1 = 0;
3329 q++;
3330 } else if (z > 1.0) {
3331 if (q1 == (unsigned int)0xfffffffe)
3332 q++;
3333 q1 += 2;
3334 } else
3335 q1 += q1 & 1;
3338 ix0 = (q >> 1) + 0x3fe00000;
3339 ix1 = q1 >> 1;
3340 if (q & 1)
3341 ix1 |= sign;
3342 ix = ix0 + ((unsigned int)m << 20);
3343 ix <<= 32;
3344 ix |= ix1;
3345 return *(double*)&ix;
3346 #endif
3349 /* Copied from musl: src/math/__tan.c */
3350 static double __tan(double x, double y, int odd)
3352 static const double T[] = {
3353 3.33333333333334091986e-01,
3354 1.33333333333201242699e-01,
3355 5.39682539762260521377e-02,
3356 2.18694882948595424599e-02,
3357 8.86323982359930005737e-03,
3358 3.59207910759131235356e-03,
3359 1.45620945432529025516e-03,
3360 5.88041240820264096874e-04,
3361 2.46463134818469906812e-04,
3362 7.81794442939557092300e-05,
3363 7.14072491382608190305e-05,
3364 -1.85586374855275456654e-05,
3365 2.59073051863633712884e-05,
3367 static const double pio4 = 7.85398163397448278999e-01;
3368 static const double pio4lo = 3.06161699786838301793e-17;
3370 double z, r, v, w, s, a, w0, a0;
3371 UINT32 hx;
3372 int big, sign;
3374 hx = *(ULONGLONG*)&x >> 32;
3375 big = (hx & 0x7fffffff) >= 0x3FE59428; /* |x| >= 0.6744 */
3376 if (big) {
3377 sign = hx >> 31;
3378 if (sign) {
3379 x = -x;
3380 y = -y;
3382 x = (pio4 - x) + (pio4lo - y);
3383 y = 0.0;
3385 z = x * x;
3386 w = z * z;
3387 r = T[1] + w * (T[3] + w * (T[5] + w * (T[7] + w * (T[9] + w * T[11]))));
3388 v = z * (T[2] + w * (T[4] + w * (T[6] + w * (T[8] + w * (T[10] + w * T[12])))));
3389 s = z * x;
3390 r = y + z * (s * (r + v) + y) + s * T[0];
3391 w = x + r;
3392 if (big) {
3393 s = 1 - 2 * odd;
3394 v = s - 2.0 * (x + (r - w * w / (w + s)));
3395 return sign ? -v : v;
3397 if (!odd)
3398 return w;
3399 /* -1.0/(x+r) has up to 2ulp error, so compute it accurately */
3400 w0 = w;
3401 *(LONGLONG*)&w0 = *(LONGLONG*)&w0 & 0xffffffff00000000ULL;
3402 v = r - (w0 - x); /* w0+v = r+x */
3403 a0 = a = -1.0 / w;
3404 *(LONGLONG*)&a0 = *(LONGLONG*)&a0 & 0xffffffff00000000ULL;
3405 return a0 + a * (1.0 + a0 * w0 + a0 * v);
3408 /*********************************************************************
3409 * tan (MSVCRT.@)
3411 * Copied from musl: src/math/tan.c
3413 double CDECL tan( double x )
3415 double y[2];
3416 UINT32 ix;
3417 unsigned n;
3419 ix = *(ULONGLONG*)&x >> 32;
3420 ix &= 0x7fffffff;
3422 if (ix <= 0x3fe921fb) { /* |x| ~< pi/4 */
3423 if (ix < 0x3e400000) { /* |x| < 2**-27 */
3424 /* raise inexact if x!=0 and underflow if subnormal */
3425 fp_barrier(ix < 0x00100000 ? x / 0x1p120f : x + 0x1p120f);
3426 return x;
3428 return __tan(x, 0.0, 0);
3431 if (isinf(x))
3432 return math_error(_DOMAIN, "tan", x, 0, x - x);
3433 if (ix >= 0x7ff00000)
3434 return x - x;
3436 n = __rem_pio2(x, y);
3437 return __tan(y[0], y[1], n & 1);
3440 /*********************************************************************
3441 * tanh (MSVCRT.@)
3443 double CDECL tanh( double x )
3445 UINT64 ui = *(UINT64*)&x;
3446 UINT32 w;
3447 int sign;
3448 double t;
3450 /* x = |x| */
3451 sign = ui >> 63;
3452 ui &= (UINT64)-1 / 2;
3453 x = *(double*)&ui;
3454 w = ui >> 32;
3456 if (w > 0x3fe193ea) {
3457 /* |x| > log(3)/2 ~= 0.5493 or nan */
3458 if (w > 0x40340000) {
3459 #if _MSVCR_VER < 140
3460 if (isnan(x))
3461 return math_error(_DOMAIN, "tanh", x, 0, x);
3462 #endif
3463 /* |x| > 20 or nan */
3464 /* note: this branch avoids raising overflow */
3465 fp_barrier(x + 0x1p120f);
3466 t = 1 - 0 / x;
3467 } else {
3468 t = __expm1(2 * x);
3469 t = 1 - 2 / (t + 2);
3471 } else if (w > 0x3fd058ae) {
3472 /* |x| > log(5/3)/2 ~= 0.2554 */
3473 t = __expm1(2 * x);
3474 t = t / (t + 2);
3475 } else if (w >= 0x00100000) {
3476 /* |x| >= 0x1p-1022, up to 2ulp error in [0.1,0.2554] */
3477 t = __expm1(-2 * x);
3478 t = -t / (t + 2);
3479 } else {
3480 /* |x| is subnormal */
3481 /* note: the branch above would not raise underflow in [0x1p-1023,0x1p-1022) */
3482 fp_barrier((float)x);
3483 t = x;
3485 return sign ? -t : t;
3489 #if (defined(__GNUC__) || defined(__clang__)) && defined(__i386__)
3491 #define CREATE_FPU_FUNC1(name, call) \
3492 __ASM_GLOBAL_FUNC(name, \
3493 "pushl %ebp\n\t" \
3494 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") \
3495 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t") \
3496 "movl %esp, %ebp\n\t" \
3497 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t") \
3498 "subl $68, %esp\n\t" /* sizeof(double)*8 + sizeof(int) */ \
3499 "fstpl (%esp)\n\t" /* store function argument */ \
3500 "fwait\n\t" \
3501 "movl $1, %ecx\n\t" /* empty FPU stack */ \
3502 "1:\n\t" \
3503 "fxam\n\t" \
3504 "fstsw %ax\n\t" \
3505 "and $0x4500, %ax\n\t" \
3506 "cmp $0x4100, %ax\n\t" \
3507 "je 2f\n\t" \
3508 "fstpl (%esp,%ecx,8)\n\t" \
3509 "fwait\n\t" \
3510 "incl %ecx\n\t" \
3511 "jmp 1b\n\t" \
3512 "2:\n\t" \
3513 "movl %ecx, -4(%ebp)\n\t" \
3514 "call " __ASM_NAME( #call ) "\n\t" \
3515 "movl -4(%ebp), %ecx\n\t" \
3516 "fstpl (%esp)\n\t" /* save result */ \
3517 "3:\n\t" /* restore FPU stack */ \
3518 "decl %ecx\n\t" \
3519 "fldl (%esp,%ecx,8)\n\t" \
3520 "cmpl $0, %ecx\n\t" \
3521 "jne 3b\n\t" \
3522 "leave\n\t" \
3523 __ASM_CFI(".cfi_def_cfa %esp,4\n\t") \
3524 __ASM_CFI(".cfi_same_value %ebp\n\t") \
3525 "ret")
3527 #define CREATE_FPU_FUNC2(name, call) \
3528 __ASM_GLOBAL_FUNC(name, \
3529 "pushl %ebp\n\t" \
3530 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") \
3531 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t") \
3532 "movl %esp, %ebp\n\t" \
3533 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t") \
3534 "subl $68, %esp\n\t" /* sizeof(double)*8 + sizeof(int) */ \
3535 "fstpl 8(%esp)\n\t" /* store function argument */ \
3536 "fwait\n\t" \
3537 "fstpl (%esp)\n\t" \
3538 "fwait\n\t" \
3539 "movl $2, %ecx\n\t" /* empty FPU stack */ \
3540 "1:\n\t" \
3541 "fxam\n\t" \
3542 "fstsw %ax\n\t" \
3543 "and $0x4500, %ax\n\t" \
3544 "cmp $0x4100, %ax\n\t" \
3545 "je 2f\n\t" \
3546 "fstpl (%esp,%ecx,8)\n\t" \
3547 "fwait\n\t" \
3548 "incl %ecx\n\t" \
3549 "jmp 1b\n\t" \
3550 "2:\n\t" \
3551 "movl %ecx, -4(%ebp)\n\t" \
3552 "call " __ASM_NAME( #call ) "\n\t" \
3553 "movl -4(%ebp), %ecx\n\t" \
3554 "fstpl 8(%esp)\n\t" /* save result */ \
3555 "3:\n\t" /* restore FPU stack */ \
3556 "decl %ecx\n\t" \
3557 "fldl (%esp,%ecx,8)\n\t" \
3558 "cmpl $1, %ecx\n\t" \
3559 "jne 3b\n\t" \
3560 "leave\n\t" \
3561 __ASM_CFI(".cfi_def_cfa %esp,4\n\t") \
3562 __ASM_CFI(".cfi_same_value %ebp\n\t") \
3563 "ret")
3565 CREATE_FPU_FUNC1(_CIacos, acos)
3566 CREATE_FPU_FUNC1(_CIasin, asin)
3567 CREATE_FPU_FUNC1(_CIatan, atan)
3568 CREATE_FPU_FUNC2(_CIatan2, atan2)
3569 CREATE_FPU_FUNC1(_CIcos, cos)
3570 CREATE_FPU_FUNC1(_CIcosh, cosh)
3571 CREATE_FPU_FUNC1(_CIexp, exp)
3572 CREATE_FPU_FUNC2(_CIfmod, fmod)
3573 CREATE_FPU_FUNC1(_CIlog, log)
3574 CREATE_FPU_FUNC1(_CIlog10, log10)
3575 CREATE_FPU_FUNC2(_CIpow, pow)
3576 CREATE_FPU_FUNC1(_CIsin, sin)
3577 CREATE_FPU_FUNC1(_CIsinh, sinh)
3578 CREATE_FPU_FUNC1(_CIsqrt, sqrt)
3579 CREATE_FPU_FUNC1(_CItan, tan)
3580 CREATE_FPU_FUNC1(_CItanh, tanh)
3582 __ASM_GLOBAL_FUNC(_ftol,
3583 "pushl %ebp\n\t"
3584 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
3585 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
3586 "movl %esp, %ebp\n\t"
3587 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
3588 "subl $12, %esp\n\t" /* sizeof(LONGLONG) + 2*sizeof(WORD) */
3589 "fnstcw (%esp)\n\t"
3590 "mov (%esp), %ax\n\t"
3591 "or $0xc00, %ax\n\t"
3592 "mov %ax, 2(%esp)\n\t"
3593 "fldcw 2(%esp)\n\t"
3594 "fistpq 4(%esp)\n\t"
3595 "fldcw (%esp)\n\t"
3596 "movl 4(%esp), %eax\n\t"
3597 "movl 8(%esp), %edx\n\t"
3598 "leave\n\t"
3599 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
3600 __ASM_CFI(".cfi_same_value %ebp\n\t")
3601 "ret")
3603 #endif /* (defined(__GNUC__) || defined(__clang__)) && defined(__i386__) */
3605 /*********************************************************************
3606 * _fpclass (MSVCRT.@)
3608 int CDECL _fpclass(double num)
3610 union { double f; UINT64 i; } u = { num };
3611 int e = u.i >> 52 & 0x7ff;
3612 int s = u.i >> 63;
3614 switch (e)
3616 case 0:
3617 if (u.i << 1) return s ? _FPCLASS_ND : _FPCLASS_PD;
3618 return s ? _FPCLASS_NZ : _FPCLASS_PZ;
3619 case 0x7ff:
3620 if (u.i << 12) return ((u.i >> 51) & 1) ? _FPCLASS_QNAN : _FPCLASS_SNAN;
3621 return s ? _FPCLASS_NINF : _FPCLASS_PINF;
3622 default:
3623 return s ? _FPCLASS_NN : _FPCLASS_PN;
3627 /*********************************************************************
3628 * _rotl (MSVCRT.@)
3630 unsigned int CDECL MSVCRT__rotl(unsigned int num, int shift)
3632 shift &= 31;
3633 return (num << shift) | (num >> (32-shift));
3636 /*********************************************************************
3637 * _lrotl (MSVCRT.@)
3639 __msvcrt_ulong CDECL MSVCRT__lrotl(__msvcrt_ulong num, int shift)
3641 shift &= 0x1f;
3642 return (num << shift) | (num >> (32-shift));
3645 /*********************************************************************
3646 * _lrotr (MSVCRT.@)
3648 __msvcrt_ulong CDECL MSVCRT__lrotr(__msvcrt_ulong num, int shift)
3650 shift &= 0x1f;
3651 return (num >> shift) | (num << (32-shift));
3654 /*********************************************************************
3655 * _rotr (MSVCRT.@)
3657 unsigned int CDECL MSVCRT__rotr(unsigned int num, int shift)
3659 shift &= 0x1f;
3660 return (num >> shift) | (num << (32-shift));
3663 /*********************************************************************
3664 * _rotl64 (MSVCRT.@)
3666 unsigned __int64 CDECL MSVCRT__rotl64(unsigned __int64 num, int shift)
3668 shift &= 63;
3669 return (num << shift) | (num >> (64-shift));
3672 /*********************************************************************
3673 * _rotr64 (MSVCRT.@)
3675 unsigned __int64 CDECL MSVCRT__rotr64(unsigned __int64 num, int shift)
3677 shift &= 63;
3678 return (num >> shift) | (num << (64-shift));
3681 /*********************************************************************
3682 * abs (MSVCRT.@)
3684 int CDECL abs( int n )
3686 return n >= 0 ? n : -n;
3689 /*********************************************************************
3690 * labs (MSVCRT.@)
3692 __msvcrt_long CDECL labs( __msvcrt_long n )
3694 return n >= 0 ? n : -n;
3697 #if _MSVCR_VER>=100
3698 /*********************************************************************
3699 * llabs (MSVCR100.@)
3701 __int64 CDECL llabs( __int64 n )
3703 return n >= 0 ? n : -n;
3705 #endif
3707 #if _MSVCR_VER>=120
3708 /*********************************************************************
3709 * imaxabs (MSVCR120.@)
3711 intmax_t CDECL imaxabs( intmax_t n )
3713 return n >= 0 ? n : -n;
3715 #endif
3717 /*********************************************************************
3718 * _abs64 (MSVCRT.@)
3720 __int64 CDECL _abs64( __int64 n )
3722 return n >= 0 ? n : -n;
3725 /* Copied from musl: src/math/ilogb.c */
3726 static int __ilogb(double x)
3728 union { double f; UINT64 i; } u = { x };
3729 int e = u.i >> 52 & 0x7ff;
3731 if (!e)
3733 u.i <<= 12;
3734 if (u.i == 0) return FP_ILOGB0;
3735 /* subnormal x */
3736 for (e = -0x3ff; u.i >> 63 == 0; e--, u.i <<= 1);
3737 return e;
3739 if (e == 0x7ff) return u.i << 12 ? FP_ILOGBNAN : INT_MAX;
3740 return e - 0x3ff;
3743 /*********************************************************************
3744 * _logb (MSVCRT.@)
3746 * Copied from musl: src/math/logb.c
3748 double CDECL _logb(double x)
3750 if (!isfinite(x))
3751 return x * x;
3752 if (x == 0)
3753 return math_error(_SING, "_logb", x, 0, -1 / (x * x));
3754 return __ilogb(x);
3757 static void sq(double *hi, double *lo, double x)
3759 double xh, xl, xc;
3761 xc = x * (0x1p27 + 1);
3762 xh = x - xc + xc;
3763 xl = x - xh;
3764 *hi = x * x;
3765 *lo = xh * xh - *hi + 2 * xh * xl + xl * xl;
3768 /*********************************************************************
3769 * _hypot (MSVCRT.@)
3771 * Copied from musl: src/math/hypot.c
3773 double CDECL _hypot(double x, double y)
3775 UINT64 ux = *(UINT64*)&x, uy = *(UINT64*)&y, ut;
3776 double hx, lx, hy, ly, z;
3777 int ex, ey;
3779 /* arrange |x| >= |y| */
3780 ux &= -1ULL >> 1;
3781 uy &= -1ULL >> 1;
3782 if (ux < uy) {
3783 ut = ux;
3784 ux = uy;
3785 uy = ut;
3788 /* special cases */
3789 ex = ux >> 52;
3790 ey = uy >> 52;
3791 x = *(double*)&ux;
3792 y = *(double*)&uy;
3793 /* note: hypot(inf,nan) == inf */
3794 if (ey == 0x7ff)
3795 return y;
3796 if (ex == 0x7ff || uy == 0)
3797 return x;
3798 /* note: hypot(x,y) ~= x + y*y/x/2 with inexact for small y/x */
3799 /* 64 difference is enough for ld80 double_t */
3800 if (ex - ey > 64)
3801 return x + y;
3803 /* precise sqrt argument in nearest rounding mode without overflow */
3804 /* xh*xh must not overflow and xl*xl must not underflow in sq */
3805 z = 1;
3806 if (ex > 0x3ff + 510) {
3807 z = 0x1p700;
3808 x *= 0x1p-700;
3809 y *= 0x1p-700;
3810 } else if (ey < 0x3ff - 450) {
3811 z = 0x1p-700;
3812 x *= 0x1p700;
3813 y *= 0x1p700;
3815 sq(&hx, &lx, x);
3816 sq(&hy, &ly, y);
3817 return z * sqrt(ly + lx + hy + hx);
3820 /*********************************************************************
3821 * _hypotf (MSVCRT.@)
3823 * Copied from musl: src/math/hypotf.c
3825 float CDECL _hypotf(float x, float y)
3827 UINT32 ux = *(UINT32*)&x, uy = *(UINT32*)&y, ut;
3828 float z;
3830 ux &= -1U >> 1;
3831 uy &= -1U >> 1;
3832 if (ux < uy) {
3833 ut = ux;
3834 ux = uy;
3835 uy = ut;
3838 x = *(float*)&ux;
3839 y = *(float*)&uy;
3840 if (uy == 0xff << 23)
3841 return y;
3842 if (ux >= 0xff << 23 || uy == 0 || ux - uy >= 25 << 23)
3843 return x + y;
3845 z = 1;
3846 if (ux >= (0x7f + 60) << 23) {
3847 z = 0x1p90f;
3848 x *= 0x1p-90f;
3849 y *= 0x1p-90f;
3850 } else if (uy < (0x7f - 60) << 23) {
3851 z = 0x1p-90f;
3852 x *= 0x1p90f;
3853 y *= 0x1p90f;
3855 return z * sqrtf((double)x * x + (double)y * y);
3858 /*********************************************************************
3859 * ceil (MSVCRT.@)
3861 * Based on musl: src/math/ceilf.c
3863 double CDECL ceil( double x )
3865 union {double f; UINT64 i;} u = {x};
3866 int e = (u.i >> 52 & 0x7ff) - 0x3ff;
3867 UINT64 m;
3869 if (e >= 52)
3870 return x;
3871 if (e >= 0) {
3872 m = 0x000fffffffffffffULL >> e;
3873 if ((u.i & m) == 0)
3874 return x;
3875 if (u.i >> 63 == 0)
3876 u.i += m;
3877 u.i &= ~m;
3878 } else {
3879 if (u.i >> 63)
3880 return -0.0;
3881 else if (u.i << 1)
3882 return 1.0;
3884 return u.f;
3887 /*********************************************************************
3888 * floor (MSVCRT.@)
3890 * Based on musl: src/math/floorf.c
3892 double CDECL floor( double x )
3894 union {double f; UINT64 i;} u = {x};
3895 int e = (int)(u.i >> 52 & 0x7ff) - 0x3ff;
3896 UINT64 m;
3898 if (e >= 52)
3899 return x;
3900 if (e >= 0) {
3901 m = 0x000fffffffffffffULL >> e;
3902 if ((u.i & m) == 0)
3903 return x;
3904 if (u.i >> 63)
3905 u.i += m;
3906 u.i &= ~m;
3907 } else {
3908 if (u.i >> 63 == 0)
3909 return 0;
3910 else if (u.i << 1)
3911 return -1;
3913 return u.f;
3916 /*********************************************************************
3917 * fma (MSVCRT.@)
3919 * Copied from musl: src/math/fma.c
3921 struct fma_num
3923 UINT64 m;
3924 int e;
3925 int sign;
3928 static struct fma_num normalize(double x)
3930 UINT64 ix = *(UINT64*)&x;
3931 int e = ix >> 52;
3932 int sign = e & 0x800;
3933 struct fma_num ret;
3935 e &= 0x7ff;
3936 if (!e) {
3937 x *= 0x1p63;
3938 ix = *(UINT64*)&x;
3939 e = ix >> 52 & 0x7ff;
3940 e = e ? e - 63 : 0x800;
3942 ix &= (1ull << 52) - 1;
3943 ix |= 1ull << 52;
3944 ix <<= 1;
3945 e -= 0x3ff + 52 + 1;
3947 ret.m = ix;
3948 ret.e = e;
3949 ret.sign = sign;
3950 return ret;
3953 static void mul(UINT64 *hi, UINT64 *lo, UINT64 x, UINT64 y)
3955 UINT64 t1, t2, t3;
3956 UINT64 xlo = (UINT32)x, xhi = x >> 32;
3957 UINT64 ylo = (UINT32)y, yhi = y >> 32;
3959 t1 = xlo * ylo;
3960 t2 = xlo * yhi + xhi * ylo;
3961 t3 = xhi * yhi;
3962 *lo = t1 + (t2 << 32);
3963 *hi = t3 + (t2 >> 32) + (t1 > *lo);
3966 double CDECL fma( double x, double y, double z )
3968 int e, d, sign, samesign, nonzero;
3969 UINT64 rhi, rlo, zhi, zlo;
3970 struct fma_num nx, ny, nz;
3971 double r;
3972 INT64 i;
3974 /* normalize so top 10bits and last bit are 0 */
3975 nx = normalize(x);
3976 ny = normalize(y);
3977 nz = normalize(z);
3979 if (nx.e >= 0x7ff - 0x3ff - 52 - 1 || ny.e >= 0x7ff - 0x3ff - 52 - 1) {
3980 r = x * y + z;
3981 if (!isnan(x) && !isnan(y) && !isnan(z) && isnan(r)) *_errno() = EDOM;
3982 return r;
3984 if (nz.e >= 0x7ff - 0x3ff - 52 - 1) {
3985 if (nz.e > 0x7ff - 0x3ff - 52 - 1) {/* z==0 */
3986 r = x * y + z;
3987 if (!isnan(x) && !isnan(y) && isnan(r)) *_errno() = EDOM;
3988 return r;
3990 return z;
3993 /* mul: r = x*y */
3994 mul(&rhi, &rlo, nx.m, ny.m);
3995 /* either top 20 or 21 bits of rhi and last 2 bits of rlo are 0 */
3997 /* align exponents */
3998 e = nx.e + ny.e;
3999 d = nz.e - e;
4000 /* shift bits z<<=kz, r>>=kr, so kz+kr == d, set e = e+kr (== ez-kz) */
4001 if (d > 0) {
4002 if (d < 64) {
4003 zlo = nz.m << d;
4004 zhi = nz.m >> (64 - d);
4005 } else {
4006 zlo = 0;
4007 zhi = nz.m;
4008 e = nz.e - 64;
4009 d -= 64;
4010 if (d < 64 && d) {
4011 rlo = rhi << (64 - d) | rlo >> d | !!(rlo << (64 - d));
4012 rhi = rhi >> d;
4013 } else if (d) {
4014 rlo = 1;
4015 rhi = 0;
4018 } else {
4019 zhi = 0;
4020 d = -d;
4021 if (d == 0) {
4022 zlo = nz.m;
4023 } else if (d < 64) {
4024 zlo = nz.m >> d | !!(nz.m << (64 - d));
4025 } else {
4026 zlo = 1;
4030 /* add */
4031 sign = nx.sign ^ ny.sign;
4032 samesign = !(sign ^ nz.sign);
4033 nonzero = 1;
4034 if (samesign) {
4035 /* r += z */
4036 rlo += zlo;
4037 rhi += zhi + (rlo < zlo);
4038 } else {
4039 /* r -= z */
4040 UINT64 t = rlo;
4041 rlo -= zlo;
4042 rhi = rhi - zhi - (t < rlo);
4043 if (rhi >> 63) {
4044 rlo = -rlo;
4045 rhi = -rhi - !!rlo;
4046 sign = !sign;
4048 nonzero = !!rhi;
4051 /* set rhi to top 63bit of the result (last bit is sticky) */
4052 if (nonzero) {
4053 e += 64;
4054 if (rhi >> 32) {
4055 BitScanReverse((DWORD*)&d, rhi >> 32);
4056 d = 31 - d - 1;
4057 } else {
4058 BitScanReverse((DWORD*)&d, rhi);
4059 d = 63 - d - 1;
4061 /* note: d > 0 */
4062 rhi = rhi << d | rlo >> (64 - d) | !!(rlo << d);
4063 } else if (rlo) {
4064 if (rlo >> 32) {
4065 BitScanReverse((DWORD*)&d, rlo >> 32);
4066 d = 31 - d - 1;
4067 } else {
4068 BitScanReverse((DWORD*)&d, rlo);
4069 d = 63 - d - 1;
4071 if (d < 0)
4072 rhi = rlo >> 1 | (rlo & 1);
4073 else
4074 rhi = rlo << d;
4075 } else {
4076 /* exact +-0 */
4077 return x * y + z;
4079 e -= d;
4081 /* convert to double */
4082 i = rhi; /* i is in [1<<62,(1<<63)-1] */
4083 if (sign)
4084 i = -i;
4085 r = i; /* |r| is in [0x1p62,0x1p63] */
4087 if (e < -1022 - 62) {
4088 /* result is subnormal before rounding */
4089 if (e == -1022 - 63) {
4090 double c = 0x1p63;
4091 if (sign)
4092 c = -c;
4093 if (r == c) {
4094 /* min normal after rounding, underflow depends
4095 on arch behaviour which can be imitated by
4096 a double to float conversion */
4097 float fltmin = 0x0.ffffff8p-63 * FLT_MIN * r;
4098 return DBL_MIN / FLT_MIN * fltmin;
4100 /* one bit is lost when scaled, add another top bit to
4101 only round once at conversion if it is inexact */
4102 if (rhi << 53) {
4103 double tiny;
4105 i = rhi >> 1 | (rhi & 1) | 1ull << 62;
4106 if (sign)
4107 i = -i;
4108 r = i;
4109 r = 2 * r - c; /* remove top bit */
4111 /* raise underflow portably, such that it
4112 cannot be optimized away */
4113 tiny = DBL_MIN / FLT_MIN * r;
4114 r += (double)(tiny * tiny) * (r - r);
4116 } else {
4117 /* only round once when scaled */
4118 d = 10;
4119 i = (rhi >> d | !!(rhi << (64 - d))) << d;
4120 if (sign)
4121 i = -i;
4122 r = i;
4125 return __scalbn(r, e);
4128 /*********************************************************************
4129 * fmaf (MSVCRT.@)
4131 float CDECL fmaf( float x, float y, float z )
4133 float w = unix_funcs->fmaf(x, y, z);
4134 if ((isinf(x) && y == 0) || (x == 0 && isinf(y))) *_errno() = EDOM;
4135 else if (isinf(x) && isinf(z) && x != z) *_errno() = EDOM;
4136 else if (isinf(y) && isinf(z) && y != z) *_errno() = EDOM;
4137 return w;
4140 /*********************************************************************
4141 * fabs (MSVCRT.@)
4143 * Copied from musl: src/math/fabsf.c
4145 double CDECL fabs( double x )
4147 union { double f; UINT64 i; } u = { x };
4148 u.i &= ~0ull >> 1;
4149 return u.f;
4152 /*********************************************************************
4153 * frexp (MSVCRT.@)
4155 * Copied from musl: src/math/frexp.c
4157 double CDECL frexp( double x, int *e )
4159 UINT64 ux = *(UINT64*)&x;
4160 int ee = ux >> 52 & 0x7ff;
4162 if (!ee) {
4163 if (x) {
4164 x = frexp(x * 0x1p64, e);
4165 *e -= 64;
4166 } else *e = 0;
4167 return x;
4168 } else if (ee == 0x7ff) {
4169 return x;
4172 *e = ee - 0x3fe;
4173 ux &= 0x800fffffffffffffull;
4174 ux |= 0x3fe0000000000000ull;
4175 return *(double*)&ux;
4178 /*********************************************************************
4179 * modf (MSVCRT.@)
4181 * Copied from musl: src/math/modf.c
4183 double CDECL modf( double x, double *iptr )
4185 union {double f; UINT64 i;} u = {x};
4186 UINT64 mask;
4187 int e = (u.i >> 52 & 0x7ff) - 0x3ff;
4189 /* no fractional part */
4190 if (e >= 52) {
4191 *iptr = x;
4192 if (e == 0x400 && u.i << 12 != 0) /* nan */
4193 return x;
4194 u.i &= 1ULL << 63;
4195 return u.f;
4198 /* no integral part*/
4199 if (e < 0) {
4200 u.i &= 1ULL << 63;
4201 *iptr = u.f;
4202 return x;
4205 mask = -1ULL >> 12 >> e;
4206 if ((u.i & mask) == 0) {
4207 *iptr = x;
4208 u.i &= 1ULL << 63;
4209 return u.f;
4211 u.i &= ~mask;
4212 *iptr = u.f;
4213 return x - u.f;
4216 /**********************************************************************
4217 * _statusfp2 (MSVCRT.@)
4219 * Not exported by native msvcrt, added in msvcr80.
4221 #if defined(__i386__) || defined(__x86_64__)
4222 void CDECL _statusfp2( unsigned int *x86_sw, unsigned int *sse2_sw )
4224 #if defined(__GNUC__) || defined(__clang__)
4225 unsigned int flags;
4226 unsigned long fpword;
4228 if (x86_sw)
4230 __asm__ __volatile__( "fstsw %0" : "=m" (fpword) );
4231 flags = 0;
4232 if (fpword & 0x1) flags |= _SW_INVALID;
4233 if (fpword & 0x2) flags |= _SW_DENORMAL;
4234 if (fpword & 0x4) flags |= _SW_ZERODIVIDE;
4235 if (fpword & 0x8) flags |= _SW_OVERFLOW;
4236 if (fpword & 0x10) flags |= _SW_UNDERFLOW;
4237 if (fpword & 0x20) flags |= _SW_INEXACT;
4238 *x86_sw = flags;
4241 if (!sse2_sw) return;
4243 if (sse2_supported)
4245 __asm__ __volatile__( "stmxcsr %0" : "=m" (fpword) );
4246 flags = 0;
4247 if (fpword & 0x1) flags |= _SW_INVALID;
4248 if (fpword & 0x2) flags |= _SW_DENORMAL;
4249 if (fpword & 0x4) flags |= _SW_ZERODIVIDE;
4250 if (fpword & 0x8) flags |= _SW_OVERFLOW;
4251 if (fpword & 0x10) flags |= _SW_UNDERFLOW;
4252 if (fpword & 0x20) flags |= _SW_INEXACT;
4253 *sse2_sw = flags;
4255 else *sse2_sw = 0;
4256 #else
4257 FIXME( "not implemented\n" );
4258 #endif
4260 #endif
4262 /**********************************************************************
4263 * _statusfp (MSVCRT.@)
4265 unsigned int CDECL _statusfp(void)
4267 unsigned int flags = 0;
4268 #if defined(__i386__) || defined(__x86_64__)
4269 unsigned int x86_sw, sse2_sw;
4271 _statusfp2( &x86_sw, &sse2_sw );
4272 /* FIXME: there's no definition for ambiguous status, just return all status bits for now */
4273 flags = x86_sw | sse2_sw;
4274 #elif defined(__aarch64__)
4275 ULONG_PTR fpsr;
4277 __asm__ __volatile__( "mrs %0, fpsr" : "=r" (fpsr) );
4278 if (fpsr & 0x1) flags |= _SW_INVALID;
4279 if (fpsr & 0x2) flags |= _SW_ZERODIVIDE;
4280 if (fpsr & 0x4) flags |= _SW_OVERFLOW;
4281 if (fpsr & 0x8) flags |= _SW_UNDERFLOW;
4282 if (fpsr & 0x10) flags |= _SW_INEXACT;
4283 if (fpsr & 0x80) flags |= _SW_DENORMAL;
4284 #else
4285 FIXME( "not implemented\n" );
4286 #endif
4287 return flags;
4290 /*********************************************************************
4291 * _clearfp (MSVCRT.@)
4293 unsigned int CDECL _clearfp(void)
4295 unsigned int flags = 0;
4296 #if (defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__))
4297 unsigned long fpword;
4299 __asm__ __volatile__( "fnstsw %0; fnclex" : "=m" (fpword) );
4300 if (fpword & 0x1) flags |= _SW_INVALID;
4301 if (fpword & 0x2) flags |= _SW_DENORMAL;
4302 if (fpword & 0x4) flags |= _SW_ZERODIVIDE;
4303 if (fpword & 0x8) flags |= _SW_OVERFLOW;
4304 if (fpword & 0x10) flags |= _SW_UNDERFLOW;
4305 if (fpword & 0x20) flags |= _SW_INEXACT;
4307 if (sse2_supported)
4309 __asm__ __volatile__( "stmxcsr %0" : "=m" (fpword) );
4310 if (fpword & 0x1) flags |= _SW_INVALID;
4311 if (fpword & 0x2) flags |= _SW_DENORMAL;
4312 if (fpword & 0x4) flags |= _SW_ZERODIVIDE;
4313 if (fpword & 0x8) flags |= _SW_OVERFLOW;
4314 if (fpword & 0x10) flags |= _SW_UNDERFLOW;
4315 if (fpword & 0x20) flags |= _SW_INEXACT;
4316 fpword &= ~0x3f;
4317 __asm__ __volatile__( "ldmxcsr %0" : : "m" (fpword) );
4319 #elif defined(__aarch64__)
4320 ULONG_PTR fpsr;
4322 __asm__ __volatile__( "mrs %0, fpsr" : "=r" (fpsr) );
4323 if (fpsr & 0x1) flags |= _SW_INVALID;
4324 if (fpsr & 0x2) flags |= _SW_ZERODIVIDE;
4325 if (fpsr & 0x4) flags |= _SW_OVERFLOW;
4326 if (fpsr & 0x8) flags |= _SW_UNDERFLOW;
4327 if (fpsr & 0x10) flags |= _SW_INEXACT;
4328 if (fpsr & 0x80) flags |= _SW_DENORMAL;
4329 fpsr &= ~0x9f;
4330 __asm__ __volatile__( "msr fpsr, %0" :: "r" (fpsr) );
4331 #else
4332 FIXME( "not implemented\n" );
4333 #endif
4334 return flags;
4337 /*********************************************************************
4338 * __fpecode (MSVCRT.@)
4340 int * CDECL __fpecode(void)
4342 return &msvcrt_get_thread_data()->fpecode;
4345 /*********************************************************************
4346 * ldexp (MSVCRT.@)
4348 double CDECL ldexp(double num, int exp)
4350 double z = __scalbn(num, exp);
4352 if (isfinite(num) && !isfinite(z))
4353 return math_error(_OVERFLOW, "ldexp", num, exp, z);
4354 if (num && isfinite(num) && !z)
4355 return math_error(_UNDERFLOW, "ldexp", num, exp, z);
4356 return z;
4359 /*********************************************************************
4360 * _cabs (MSVCRT.@)
4362 double CDECL _cabs(struct _complex num)
4364 return sqrt(num.x * num.x + num.y * num.y);
4367 /*********************************************************************
4368 * _chgsign (MSVCRT.@)
4370 double CDECL _chgsign(double num)
4372 union { double f; UINT64 i; } u = { num };
4373 u.i ^= 1ull << 63;
4374 return u.f;
4377 /*********************************************************************
4378 * __control87_2 (MSVCR80.@)
4380 * Not exported by native msvcrt, added in msvcr80.
4382 #ifdef __i386__
4383 int CDECL __control87_2( unsigned int newval, unsigned int mask,
4384 unsigned int *x86_cw, unsigned int *sse2_cw )
4386 #if defined(__GNUC__) || defined(__clang__)
4387 unsigned long fpword;
4388 unsigned int flags;
4389 unsigned int old_flags;
4391 if (x86_cw)
4393 __asm__ __volatile__( "fstcw %0" : "=m" (fpword) );
4395 /* Convert into mask constants */
4396 flags = 0;
4397 if (fpword & 0x1) flags |= _EM_INVALID;
4398 if (fpword & 0x2) flags |= _EM_DENORMAL;
4399 if (fpword & 0x4) flags |= _EM_ZERODIVIDE;
4400 if (fpword & 0x8) flags |= _EM_OVERFLOW;
4401 if (fpword & 0x10) flags |= _EM_UNDERFLOW;
4402 if (fpword & 0x20) flags |= _EM_INEXACT;
4403 switch (fpword & 0xc00)
4405 case 0xc00: flags |= _RC_UP|_RC_DOWN; break;
4406 case 0x800: flags |= _RC_UP; break;
4407 case 0x400: flags |= _RC_DOWN; break;
4409 switch (fpword & 0x300)
4411 case 0x0: flags |= _PC_24; break;
4412 case 0x200: flags |= _PC_53; break;
4413 case 0x300: flags |= _PC_64; break;
4415 if (fpword & 0x1000) flags |= _IC_AFFINE;
4417 TRACE( "x86 flags=%08x newval=%08x mask=%08x\n", flags, newval, mask );
4418 if (mask)
4420 flags = (flags & ~mask) | (newval & mask);
4422 /* Convert (masked) value back to fp word */
4423 fpword = 0;
4424 if (flags & _EM_INVALID) fpword |= 0x1;
4425 if (flags & _EM_DENORMAL) fpword |= 0x2;
4426 if (flags & _EM_ZERODIVIDE) fpword |= 0x4;
4427 if (flags & _EM_OVERFLOW) fpword |= 0x8;
4428 if (flags & _EM_UNDERFLOW) fpword |= 0x10;
4429 if (flags & _EM_INEXACT) fpword |= 0x20;
4430 switch (flags & _MCW_RC)
4432 case _RC_UP|_RC_DOWN: fpword |= 0xc00; break;
4433 case _RC_UP: fpword |= 0x800; break;
4434 case _RC_DOWN: fpword |= 0x400; break;
4436 switch (flags & _MCW_PC)
4438 case _PC_64: fpword |= 0x300; break;
4439 case _PC_53: fpword |= 0x200; break;
4440 case _PC_24: fpword |= 0x0; break;
4442 if (flags & _IC_AFFINE) fpword |= 0x1000;
4444 __asm__ __volatile__( "fldcw %0" : : "m" (fpword) );
4446 *x86_cw = flags;
4449 if (!sse2_cw) return 1;
4451 if (sse2_supported)
4453 __asm__ __volatile__( "stmxcsr %0" : "=m" (fpword) );
4455 /* Convert into mask constants */
4456 flags = 0;
4457 if (fpword & 0x80) flags |= _EM_INVALID;
4458 if (fpword & 0x100) flags |= _EM_DENORMAL;
4459 if (fpword & 0x200) flags |= _EM_ZERODIVIDE;
4460 if (fpword & 0x400) flags |= _EM_OVERFLOW;
4461 if (fpword & 0x800) flags |= _EM_UNDERFLOW;
4462 if (fpword & 0x1000) flags |= _EM_INEXACT;
4463 switch (fpword & 0x6000)
4465 case 0x6000: flags |= _RC_UP|_RC_DOWN; break;
4466 case 0x4000: flags |= _RC_UP; break;
4467 case 0x2000: flags |= _RC_DOWN; break;
4469 switch (fpword & 0x8040)
4471 case 0x0040: flags |= _DN_FLUSH_OPERANDS_SAVE_RESULTS; break;
4472 case 0x8000: flags |= _DN_SAVE_OPERANDS_FLUSH_RESULTS; break;
4473 case 0x8040: flags |= _DN_FLUSH; break;
4476 TRACE( "sse2 flags=%08x newval=%08x mask=%08x\n", flags, newval, mask );
4477 if (mask)
4479 old_flags = flags;
4480 mask &= _MCW_EM | _MCW_RC | _MCW_DN;
4481 flags = (flags & ~mask) | (newval & mask);
4483 if (flags != old_flags)
4485 /* Convert (masked) value back to fp word */
4486 fpword = 0;
4487 if (flags & _EM_INVALID) fpword |= 0x80;
4488 if (flags & _EM_DENORMAL) fpword |= 0x100;
4489 if (flags & _EM_ZERODIVIDE) fpword |= 0x200;
4490 if (flags & _EM_OVERFLOW) fpword |= 0x400;
4491 if (flags & _EM_UNDERFLOW) fpword |= 0x800;
4492 if (flags & _EM_INEXACT) fpword |= 0x1000;
4493 switch (flags & _MCW_RC)
4495 case _RC_UP|_RC_DOWN: fpword |= 0x6000; break;
4496 case _RC_UP: fpword |= 0x4000; break;
4497 case _RC_DOWN: fpword |= 0x2000; break;
4499 switch (flags & _MCW_DN)
4501 case _DN_FLUSH_OPERANDS_SAVE_RESULTS: fpword |= 0x0040; break;
4502 case _DN_SAVE_OPERANDS_FLUSH_RESULTS: fpword |= 0x8000; break;
4503 case _DN_FLUSH: fpword |= 0x8040; break;
4505 __asm__ __volatile__( "ldmxcsr %0" : : "m" (fpword) );
4508 *sse2_cw = flags;
4510 else *sse2_cw = 0;
4512 return 1;
4513 #else
4514 FIXME( "not implemented\n" );
4515 return 0;
4516 #endif
4518 #endif
4520 /*********************************************************************
4521 * _control87 (MSVCRT.@)
4523 unsigned int CDECL _control87(unsigned int newval, unsigned int mask)
4525 unsigned int flags = 0;
4526 #ifdef __i386__
4527 unsigned int sse2_cw;
4529 __control87_2( newval, mask, &flags, &sse2_cw );
4531 if ((flags ^ sse2_cw) & (_MCW_EM | _MCW_RC)) flags |= _EM_AMBIGUOUS;
4532 flags |= sse2_cw;
4533 #elif defined(__x86_64__)
4534 unsigned long fpword;
4535 unsigned int old_flags;
4537 __asm__ __volatile__( "stmxcsr %0" : "=m" (fpword) );
4538 if (fpword & 0x80) flags |= _EM_INVALID;
4539 if (fpword & 0x100) flags |= _EM_DENORMAL;
4540 if (fpword & 0x200) flags |= _EM_ZERODIVIDE;
4541 if (fpword & 0x400) flags |= _EM_OVERFLOW;
4542 if (fpword & 0x800) flags |= _EM_UNDERFLOW;
4543 if (fpword & 0x1000) flags |= _EM_INEXACT;
4544 switch (fpword & 0x6000)
4546 case 0x6000: flags |= _RC_CHOP; break;
4547 case 0x4000: flags |= _RC_UP; break;
4548 case 0x2000: flags |= _RC_DOWN; break;
4550 switch (fpword & 0x8040)
4552 case 0x0040: flags |= _DN_FLUSH_OPERANDS_SAVE_RESULTS; break;
4553 case 0x8000: flags |= _DN_SAVE_OPERANDS_FLUSH_RESULTS; break;
4554 case 0x8040: flags |= _DN_FLUSH; break;
4556 old_flags = flags;
4557 mask &= _MCW_EM | _MCW_RC | _MCW_DN;
4558 flags = (flags & ~mask) | (newval & mask);
4559 if (flags != old_flags)
4561 fpword = 0;
4562 if (flags & _EM_INVALID) fpword |= 0x80;
4563 if (flags & _EM_DENORMAL) fpword |= 0x100;
4564 if (flags & _EM_ZERODIVIDE) fpword |= 0x200;
4565 if (flags & _EM_OVERFLOW) fpword |= 0x400;
4566 if (flags & _EM_UNDERFLOW) fpword |= 0x800;
4567 if (flags & _EM_INEXACT) fpword |= 0x1000;
4568 switch (flags & _MCW_RC)
4570 case _RC_CHOP: fpword |= 0x6000; break;
4571 case _RC_UP: fpword |= 0x4000; break;
4572 case _RC_DOWN: fpword |= 0x2000; break;
4574 switch (flags & _MCW_DN)
4576 case _DN_FLUSH_OPERANDS_SAVE_RESULTS: fpword |= 0x0040; break;
4577 case _DN_SAVE_OPERANDS_FLUSH_RESULTS: fpword |= 0x8000; break;
4578 case _DN_FLUSH: fpword |= 0x8040; break;
4580 __asm__ __volatile__( "ldmxcsr %0" :: "m" (fpword) );
4582 #elif defined(__aarch64__)
4583 ULONG_PTR fpcr;
4585 __asm__ __volatile__( "mrs %0, fpcr" : "=r" (fpcr) );
4586 if (!(fpcr & 0x100)) flags |= _EM_INVALID;
4587 if (!(fpcr & 0x200)) flags |= _EM_ZERODIVIDE;
4588 if (!(fpcr & 0x400)) flags |= _EM_OVERFLOW;
4589 if (!(fpcr & 0x800)) flags |= _EM_UNDERFLOW;
4590 if (!(fpcr & 0x1000)) flags |= _EM_INEXACT;
4591 if (!(fpcr & 0x8000)) flags |= _EM_DENORMAL;
4592 switch (fpcr & 0xc00000)
4594 case 0x400000: flags |= _RC_UP; break;
4595 case 0x800000: flags |= _RC_DOWN; break;
4596 case 0xc00000: flags |= _RC_CHOP; break;
4598 flags = (flags & ~mask) | (newval & mask);
4599 fpcr &= ~0xc09f00ul;
4600 if (!(flags & _EM_INVALID)) fpcr |= 0x100;
4601 if (!(flags & _EM_ZERODIVIDE)) fpcr |= 0x200;
4602 if (!(flags & _EM_OVERFLOW)) fpcr |= 0x400;
4603 if (!(flags & _EM_UNDERFLOW)) fpcr |= 0x800;
4604 if (!(flags & _EM_INEXACT)) fpcr |= 0x1000;
4605 if (!(flags & _EM_DENORMAL)) fpcr |= 0x8000;
4606 switch (flags & _MCW_RC)
4608 case _RC_CHOP: fpcr |= 0xc00000; break;
4609 case _RC_UP: fpcr |= 0x400000; break;
4610 case _RC_DOWN: fpcr |= 0x800000; break;
4612 __asm__ __volatile__( "msr fpcr, %0" :: "r" (fpcr) );
4613 #else
4614 FIXME( "not implemented\n" );
4615 #endif
4616 return flags;
4619 /*********************************************************************
4620 * _controlfp (MSVCRT.@)
4622 unsigned int CDECL _controlfp(unsigned int newval, unsigned int mask)
4624 return _control87( newval, mask & ~_EM_DENORMAL );
4627 /*********************************************************************
4628 * _set_controlfp (MSVCRT.@)
4630 void CDECL _set_controlfp( unsigned int newval, unsigned int mask )
4632 _controlfp( newval, mask );
4635 /*********************************************************************
4636 * _controlfp_s (MSVCRT.@)
4638 int CDECL _controlfp_s(unsigned int *cur, unsigned int newval, unsigned int mask)
4640 static const unsigned int all_flags = (_MCW_EM | _MCW_IC | _MCW_RC |
4641 _MCW_PC | _MCW_DN);
4642 unsigned int val;
4644 if (!MSVCRT_CHECK_PMT( !(newval & mask & ~all_flags) ))
4646 if (cur) *cur = _controlfp( 0, 0 ); /* retrieve it anyway */
4647 return EINVAL;
4649 val = _controlfp( newval, mask );
4650 if (cur) *cur = val;
4651 return 0;
4654 #if _MSVCR_VER >= 140
4655 enum fenv_masks
4657 FENV_X_INVALID = 0x00100010,
4658 FENV_X_DENORMAL = 0x00200020,
4659 FENV_X_ZERODIVIDE = 0x00080008,
4660 FENV_X_OVERFLOW = 0x00040004,
4661 FENV_X_UNDERFLOW = 0x00020002,
4662 FENV_X_INEXACT = 0x00010001,
4663 FENV_X_AFFINE = 0x00004000,
4664 FENV_X_UP = 0x00800200,
4665 FENV_X_DOWN = 0x00400100,
4666 FENV_X_24 = 0x00002000,
4667 FENV_X_53 = 0x00001000,
4668 FENV_Y_INVALID = 0x10000010,
4669 FENV_Y_DENORMAL = 0x20000020,
4670 FENV_Y_ZERODIVIDE = 0x08000008,
4671 FENV_Y_OVERFLOW = 0x04000004,
4672 FENV_Y_UNDERFLOW = 0x02000002,
4673 FENV_Y_INEXACT = 0x01000001,
4674 FENV_Y_UP = 0x80000200,
4675 FENV_Y_DOWN = 0x40000100,
4676 FENV_Y_FLUSH = 0x00000400,
4677 FENV_Y_FLUSH_SAVE = 0x00000800
4680 /* encodes x87/sse control/status word in ulong */
4681 static __msvcrt_ulong fenv_encode(unsigned int x, unsigned int y)
4683 __msvcrt_ulong ret = 0;
4685 if (x & _EM_INVALID) ret |= FENV_X_INVALID;
4686 if (x & _EM_DENORMAL) ret |= FENV_X_DENORMAL;
4687 if (x & _EM_ZERODIVIDE) ret |= FENV_X_ZERODIVIDE;
4688 if (x & _EM_OVERFLOW) ret |= FENV_X_OVERFLOW;
4689 if (x & _EM_UNDERFLOW) ret |= FENV_X_UNDERFLOW;
4690 if (x & _EM_INEXACT) ret |= FENV_X_INEXACT;
4691 if (x & _IC_AFFINE) ret |= FENV_X_AFFINE;
4692 if (x & _RC_UP) ret |= FENV_X_UP;
4693 if (x & _RC_DOWN) ret |= FENV_X_DOWN;
4694 if (x & _PC_24) ret |= FENV_X_24;
4695 if (x & _PC_53) ret |= FENV_X_53;
4696 x &= ~(_MCW_EM | _MCW_IC | _MCW_RC | _MCW_PC);
4698 if (y & _EM_INVALID) ret |= FENV_Y_INVALID;
4699 if (y & _EM_DENORMAL) ret |= FENV_Y_DENORMAL;
4700 if (y & _EM_ZERODIVIDE) ret |= FENV_Y_ZERODIVIDE;
4701 if (y & _EM_OVERFLOW) ret |= FENV_Y_OVERFLOW;
4702 if (y & _EM_UNDERFLOW) ret |= FENV_Y_UNDERFLOW;
4703 if (y & _EM_INEXACT) ret |= FENV_Y_INEXACT;
4704 if (y & _RC_UP) ret |= FENV_Y_UP;
4705 if (y & _RC_DOWN) ret |= FENV_Y_DOWN;
4706 if (y & _DN_FLUSH) ret |= FENV_Y_FLUSH;
4707 if (y & _DN_FLUSH_OPERANDS_SAVE_RESULTS) ret |= FENV_Y_FLUSH_SAVE;
4708 y &= ~(_MCW_EM | _MCW_IC | _MCW_RC | _MCW_DN);
4710 if(x || y) FIXME("unsupported flags: %x, %x\n", x, y);
4711 return ret;
4714 /* decodes x87/sse control/status word, returns FALSE on error */
4715 #if (defined(__i386__) || defined(__x86_64__))
4716 static BOOL fenv_decode(__msvcrt_ulong enc, unsigned int *x, unsigned int *y)
4718 *x = *y = 0;
4719 if ((enc & FENV_X_INVALID) == FENV_X_INVALID) *x |= _EM_INVALID;
4720 if ((enc & FENV_X_DENORMAL) == FENV_X_DENORMAL) *x |= _EM_DENORMAL;
4721 if ((enc & FENV_X_ZERODIVIDE) == FENV_X_ZERODIVIDE) *x |= _EM_ZERODIVIDE;
4722 if ((enc & FENV_X_OVERFLOW) == FENV_X_OVERFLOW) *x |= _EM_OVERFLOW;
4723 if ((enc & FENV_X_UNDERFLOW) == FENV_X_UNDERFLOW) *x |= _EM_UNDERFLOW;
4724 if ((enc & FENV_X_INEXACT) == FENV_X_INEXACT) *x |= _EM_INEXACT;
4725 if ((enc & FENV_X_AFFINE) == FENV_X_AFFINE) *x |= _IC_AFFINE;
4726 if ((enc & FENV_X_UP) == FENV_X_UP) *x |= _RC_UP;
4727 if ((enc & FENV_X_DOWN) == FENV_X_DOWN) *x |= _RC_DOWN;
4728 if ((enc & FENV_X_24) == FENV_X_24) *x |= _PC_24;
4729 if ((enc & FENV_X_53) == FENV_X_53) *x |= _PC_53;
4731 if ((enc & FENV_Y_INVALID) == FENV_Y_INVALID) *y |= _EM_INVALID;
4732 if ((enc & FENV_Y_DENORMAL) == FENV_Y_DENORMAL) *y |= _EM_DENORMAL;
4733 if ((enc & FENV_Y_ZERODIVIDE) == FENV_Y_ZERODIVIDE) *y |= _EM_ZERODIVIDE;
4734 if ((enc & FENV_Y_OVERFLOW) == FENV_Y_OVERFLOW) *y |= _EM_OVERFLOW;
4735 if ((enc & FENV_Y_UNDERFLOW) == FENV_Y_UNDERFLOW) *y |= _EM_UNDERFLOW;
4736 if ((enc & FENV_Y_INEXACT) == FENV_Y_INEXACT) *y |= _EM_INEXACT;
4737 if ((enc & FENV_Y_UP) == FENV_Y_UP) *y |= _RC_UP;
4738 if ((enc & FENV_Y_DOWN) == FENV_Y_DOWN) *y |= _RC_DOWN;
4739 if ((enc & FENV_Y_FLUSH) == FENV_Y_FLUSH) *y |= _DN_FLUSH;
4740 if ((enc & FENV_Y_FLUSH_SAVE) == FENV_Y_FLUSH_SAVE) *y |= _DN_FLUSH_OPERANDS_SAVE_RESULTS;
4742 if (fenv_encode(*x, *y) != enc)
4744 WARN("can't decode: %lx\n", enc);
4745 return FALSE;
4747 return TRUE;
4749 #endif
4750 #endif
4752 #if _MSVCR_VER>=120
4753 /*********************************************************************
4754 * fegetenv (MSVCR120.@)
4756 int CDECL fegetenv(fenv_t *env)
4758 #if _MSVCR_VER>=140 && defined(__i386__)
4759 unsigned int x87, sse;
4760 __control87_2(0, 0, &x87, &sse);
4761 env->_Fe_ctl = fenv_encode(x87, sse);
4762 _statusfp2(&x87, &sse);
4763 env->_Fe_stat = fenv_encode(x87, sse);
4764 #elif _MSVCR_VER>=140
4765 env->_Fe_ctl = fenv_encode(0, _control87(0, 0));
4766 env->_Fe_stat = fenv_encode(0, _statusfp());
4767 #else
4768 env->_Fe_ctl = _controlfp(0, 0) & (_EM_INEXACT | _EM_UNDERFLOW |
4769 _EM_OVERFLOW | _EM_ZERODIVIDE | _EM_INVALID | _RC_CHOP);
4770 env->_Fe_stat = _statusfp();
4771 #endif
4772 return 0;
4775 /*********************************************************************
4776 * feupdateenv (MSVCR120.@)
4778 int CDECL feupdateenv(const fenv_t *env)
4780 fenv_t set;
4781 fegetenv(&set);
4782 set._Fe_ctl = env->_Fe_ctl;
4783 set._Fe_stat |= env->_Fe_stat;
4784 return fesetenv(&set);
4787 /*********************************************************************
4788 * fetestexcept (MSVCR120.@)
4790 int CDECL fetestexcept(int flags)
4792 return _statusfp() & flags;
4795 /*********************************************************************
4796 * fesetexceptflag (MSVCR120.@)
4798 int CDECL fesetexceptflag(const fexcept_t *status, int excepts)
4800 fenv_t env;
4802 excepts &= FE_ALL_EXCEPT;
4803 if(!excepts)
4804 return 0;
4806 fegetenv(&env);
4807 #if _MSVCR_VER>=140 && (defined(__i386__) || defined(__x86_64__))
4808 env._Fe_stat &= ~fenv_encode(excepts, excepts);
4809 env._Fe_stat |= *status & fenv_encode(excepts, excepts);
4810 #elif _MSVCR_VER>=140
4811 env._Fe_stat &= ~fenv_encode(0, excepts);
4812 env._Fe_stat |= *status & fenv_encode(0, excepts);
4813 #else
4814 env._Fe_stat &= ~excepts;
4815 env._Fe_stat |= *status & excepts;
4816 #endif
4817 return fesetenv(&env);
4820 /*********************************************************************
4821 * feraiseexcept (MSVCR120.@)
4823 int CDECL feraiseexcept(int flags)
4825 fenv_t env;
4827 flags &= FE_ALL_EXCEPT;
4828 fegetenv(&env);
4829 #if _MSVCR_VER>=140 && defined(__i386__)
4830 env._Fe_stat |= fenv_encode(flags, flags);
4831 #elif _MSVCR_VER>=140
4832 env._Fe_stat |= fenv_encode(0, flags);
4833 #else
4834 env._Fe_stat |= flags;
4835 #endif
4836 return fesetenv(&env);
4839 /*********************************************************************
4840 * feclearexcept (MSVCR120.@)
4842 int CDECL feclearexcept(int flags)
4844 fenv_t env;
4846 fegetenv(&env);
4847 flags &= FE_ALL_EXCEPT;
4848 #if _MSVCR_VER>=140
4849 env._Fe_stat &= ~fenv_encode(flags, flags);
4850 #else
4851 env._Fe_stat &= ~flags;
4852 #endif
4853 return fesetenv(&env);
4856 /*********************************************************************
4857 * fegetexceptflag (MSVCR120.@)
4859 int CDECL fegetexceptflag(fexcept_t *status, int excepts)
4861 #if _MSVCR_VER>=140 && defined(__i386__)
4862 unsigned int x87, sse;
4863 _statusfp2(&x87, &sse);
4864 *status = fenv_encode(x87 & excepts, sse & excepts);
4865 #elif _MSVCR_VER>=140
4866 *status = fenv_encode(0, _statusfp() & excepts);
4867 #else
4868 *status = _statusfp() & excepts;
4869 #endif
4870 return 0;
4872 #endif
4874 #if _MSVCR_VER>=140
4875 /*********************************************************************
4876 * __fpe_flt_rounds (UCRTBASE.@)
4878 int CDECL __fpe_flt_rounds(void)
4880 unsigned int fpc = _controlfp(0, 0) & _RC_CHOP;
4882 TRACE("()\n");
4884 switch(fpc) {
4885 case _RC_CHOP: return 0;
4886 case _RC_NEAR: return 1;
4887 case _RC_UP: return 2;
4888 default: return 3;
4891 #endif
4893 #if _MSVCR_VER>=120
4895 /*********************************************************************
4896 * fegetround (MSVCR120.@)
4898 int CDECL fegetround(void)
4900 return _controlfp(0, 0) & _RC_CHOP;
4903 /*********************************************************************
4904 * fesetround (MSVCR120.@)
4906 int CDECL fesetround(int round_mode)
4908 if (round_mode & (~_RC_CHOP))
4909 return 1;
4910 _controlfp(round_mode, _RC_CHOP);
4911 return 0;
4914 #endif /* _MSVCR_VER>=120 */
4916 /*********************************************************************
4917 * _copysign (MSVCRT.@)
4919 * Copied from musl: src/math/copysign.c
4921 double CDECL _copysign( double x, double y )
4923 union { double f; UINT64 i; } ux = { x }, uy = { y };
4924 ux.i &= ~0ull >> 1;
4925 ux.i |= uy.i & 1ull << 63;
4926 return ux.f;
4929 /*********************************************************************
4930 * _finite (MSVCRT.@)
4932 int CDECL _finite(double num)
4934 union { double f; UINT64 i; } u = { num };
4935 return (u.i & ~0ull >> 1) < 0x7ffull << 52;
4938 /*********************************************************************
4939 * _fpreset (MSVCRT.@)
4941 void CDECL _fpreset(void)
4943 #if (defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__))
4944 const unsigned int x86_cw = 0x27f;
4945 __asm__ __volatile__( "fninit; fldcw %0" : : "m" (x86_cw) );
4946 if (sse2_supported)
4948 const unsigned long sse2_cw = 0x1f80;
4949 __asm__ __volatile__( "ldmxcsr %0" : : "m" (sse2_cw) );
4951 #else
4952 FIXME( "not implemented\n" );
4953 #endif
4956 #if _MSVCR_VER>=120
4957 /*********************************************************************
4958 * fesetenv (MSVCR120.@)
4960 int CDECL fesetenv(const fenv_t *env)
4962 #if (defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__))
4963 unsigned int x87_cw, sse_cw, x87_stat, sse_stat;
4964 struct {
4965 WORD control_word;
4966 WORD unused1;
4967 WORD status_word;
4968 WORD unused2;
4969 WORD tag_word;
4970 WORD unused3;
4971 DWORD instruction_pointer;
4972 WORD code_segment;
4973 WORD unused4;
4974 DWORD operand_addr;
4975 WORD data_segment;
4976 WORD unused5;
4977 } fenv;
4979 TRACE( "(%p)\n", env );
4981 if (!env->_Fe_ctl && !env->_Fe_stat) {
4982 _fpreset();
4983 return 0;
4986 #if _MSVCR_VER>=140
4987 if (!fenv_decode(env->_Fe_ctl, &x87_cw, &sse_cw))
4988 return 1;
4989 if (!fenv_decode(env->_Fe_stat, &x87_stat, &sse_stat))
4990 return 1;
4991 #else
4992 x87_cw = sse_cw = env->_Fe_ctl;
4993 x87_stat = sse_stat = env->_Fe_stat;
4994 #endif
4996 __asm__ __volatile__( "fnstenv %0" : "=m" (fenv) );
4998 fenv.control_word &= ~0xc3d;
4999 #if _MSVCR_VER>=140
5000 fenv.control_word &= ~0x1302;
5001 #endif
5002 if (x87_cw & _EM_INVALID) fenv.control_word |= 0x1;
5003 if (x87_cw & _EM_ZERODIVIDE) fenv.control_word |= 0x4;
5004 if (x87_cw & _EM_OVERFLOW) fenv.control_word |= 0x8;
5005 if (x87_cw & _EM_UNDERFLOW) fenv.control_word |= 0x10;
5006 if (x87_cw & _EM_INEXACT) fenv.control_word |= 0x20;
5007 switch (x87_cw & _MCW_RC)
5009 case _RC_UP|_RC_DOWN: fenv.control_word |= 0xc00; break;
5010 case _RC_UP: fenv.control_word |= 0x800; break;
5011 case _RC_DOWN: fenv.control_word |= 0x400; break;
5013 #if _MSVCR_VER>=140
5014 if (x87_cw & _EM_DENORMAL) fenv.control_word |= 0x2;
5015 switch (x87_cw & _MCW_PC)
5017 case _PC_64: fenv.control_word |= 0x300; break;
5018 case _PC_53: fenv.control_word |= 0x200; break;
5019 case _PC_24: fenv.control_word |= 0x0; break;
5021 if (x87_cw & _IC_AFFINE) fenv.control_word |= 0x1000;
5022 #endif
5024 fenv.status_word &= ~0x3f;
5025 if (x87_stat & _SW_INVALID) fenv.status_word |= 0x1;
5026 if (x87_stat & _SW_DENORMAL) fenv.status_word |= 0x2;
5027 if (x87_stat & _SW_ZERODIVIDE) fenv.status_word |= 0x4;
5028 if (x87_stat & _SW_OVERFLOW) fenv.status_word |= 0x8;
5029 if (x87_stat & _SW_UNDERFLOW) fenv.status_word |= 0x10;
5030 if (x87_stat & _SW_INEXACT) fenv.status_word |= 0x20;
5032 __asm__ __volatile__( "fldenv %0" : : "m" (fenv) : "st", "st(1)",
5033 "st(2)", "st(3)", "st(4)", "st(5)", "st(6)", "st(7)" );
5035 if (sse2_supported)
5037 DWORD fpword;
5038 __asm__ __volatile__( "stmxcsr %0" : "=m" (fpword) );
5039 fpword &= ~0x7ebf;
5040 #if _MSVCR_VER>=140
5041 fpword &= ~0x8140;
5042 #endif
5043 if (sse_cw & _EM_INVALID) fpword |= 0x80;
5044 if (sse_cw & _EM_ZERODIVIDE) fpword |= 0x200;
5045 if (sse_cw & _EM_OVERFLOW) fpword |= 0x400;
5046 if (sse_cw & _EM_UNDERFLOW) fpword |= 0x800;
5047 if (sse_cw & _EM_INEXACT) fpword |= 0x1000;
5048 switch (sse_cw & _MCW_RC)
5050 case _RC_CHOP: fpword |= 0x6000; break;
5051 case _RC_UP: fpword |= 0x4000; break;
5052 case _RC_DOWN: fpword |= 0x2000; break;
5054 if (sse_stat & _SW_INVALID) fpword |= 0x1;
5055 if (sse_stat & _SW_DENORMAL) fpword |= 0x2;
5056 if (sse_stat & _SW_ZERODIVIDE) fpword |= 0x4;
5057 if (sse_stat & _SW_OVERFLOW) fpword |= 0x8;
5058 if (sse_stat & _SW_UNDERFLOW) fpword |= 0x10;
5059 if (sse_stat & _SW_INEXACT) fpword |= 0x20;
5060 #if _MSVCR_VER>=140
5061 if (sse_cw & _EM_DENORMAL) fpword |= 0x100;
5062 switch (sse_cw & _MCW_DN)
5064 case _DN_FLUSH_OPERANDS_SAVE_RESULTS: fpword |= 0x0040; break;
5065 case _DN_SAVE_OPERANDS_FLUSH_RESULTS: fpword |= 0x8000; break;
5066 case _DN_FLUSH: fpword |= 0x8040; break;
5068 #endif
5069 __asm__ __volatile__( "ldmxcsr %0" : : "m" (fpword) );
5072 return 0;
5073 #else
5074 FIXME( "not implemented\n" );
5075 #endif
5076 return 1;
5078 #endif
5080 /*********************************************************************
5081 * _isnan (MSVCRT.@)
5083 int CDECL _isnan(double num)
5085 union { double f; UINT64 i; } u = { num };
5086 return (u.i & ~0ull >> 1) > 0x7ffull << 52;
5089 static double pzero(double x)
5091 static const double pR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
5092 0.00000000000000000000e+00,
5093 -7.03124999999900357484e-02,
5094 -8.08167041275349795626e+00,
5095 -2.57063105679704847262e+02,
5096 -2.48521641009428822144e+03,
5097 -5.25304380490729545272e+03,
5098 }, pS8[5] = {
5099 1.16534364619668181717e+02,
5100 3.83374475364121826715e+03,
5101 4.05978572648472545552e+04,
5102 1.16752972564375915681e+05,
5103 4.76277284146730962675e+04,
5104 }, pR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
5105 -1.14125464691894502584e-11,
5106 -7.03124940873599280078e-02,
5107 -4.15961064470587782438e+00,
5108 -6.76747652265167261021e+01,
5109 -3.31231299649172967747e+02,
5110 -3.46433388365604912451e+02,
5111 }, pS5[5] = {
5112 6.07539382692300335975e+01,
5113 1.05125230595704579173e+03,
5114 5.97897094333855784498e+03,
5115 9.62544514357774460223e+03,
5116 2.40605815922939109441e+03,
5117 }, pR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */
5118 -2.54704601771951915620e-09,
5119 -7.03119616381481654654e-02,
5120 -2.40903221549529611423e+00,
5121 -2.19659774734883086467e+01,
5122 -5.80791704701737572236e+01,
5123 -3.14479470594888503854e+01,
5124 }, pS3[5] = {
5125 3.58560338055209726349e+01,
5126 3.61513983050303863820e+02,
5127 1.19360783792111533330e+03,
5128 1.12799679856907414432e+03,
5129 1.73580930813335754692e+02,
5130 }, pR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
5131 -8.87534333032526411254e-08,
5132 -7.03030995483624743247e-02,
5133 -1.45073846780952986357e+00,
5134 -7.63569613823527770791e+00,
5135 -1.11931668860356747786e+01,
5136 -3.23364579351335335033e+00,
5137 }, pS2[5] = {
5138 2.22202997532088808441e+01,
5139 1.36206794218215208048e+02,
5140 2.70470278658083486789e+02,
5141 1.53875394208320329881e+02,
5142 1.46576176948256193810e+01,
5145 const double *p, *q;
5146 double z, r, s;
5147 UINT32 ix;
5149 ix = *(ULONGLONG*)&x >> 32;
5150 ix &= 0x7fffffff;
5151 if (ix >= 0x40200000) {
5152 p = pR8;
5153 q = pS8;
5154 } else if (ix >= 0x40122E8B) {
5155 p = pR5;
5156 q = pS5;
5157 } else if (ix >= 0x4006DB6D) {
5158 p = pR3;
5159 q = pS3;
5160 } else /*ix >= 0x40000000*/ {
5161 p = pR2;
5162 q = pS2;
5165 z = 1.0 / (x * x);
5166 r = p[0] + z * (p[1] + z * (p[2] + z * (p[3] + z * (p[4] + z * p[5]))));
5167 s = 1.0 + z * (q[0] + z * (q[1] + z * (q[2] + z * (q[3] + z * q[4]))));
5168 return 1.0 + r / s;
5171 static double qzero(double x)
5173 static const double qR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
5174 0.00000000000000000000e+00,
5175 7.32421874999935051953e-02,
5176 1.17682064682252693899e+01,
5177 5.57673380256401856059e+02,
5178 8.85919720756468632317e+03,
5179 3.70146267776887834771e+04,
5180 }, qS8[6] = {
5181 1.63776026895689824414e+02,
5182 8.09834494656449805916e+03,
5183 1.42538291419120476348e+05,
5184 8.03309257119514397345e+05,
5185 8.40501579819060512818e+05,
5186 -3.43899293537866615225e+05,
5187 }, qR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
5188 1.84085963594515531381e-11,
5189 7.32421766612684765896e-02,
5190 5.83563508962056953777e+00,
5191 1.35111577286449829671e+02,
5192 1.02724376596164097464e+03,
5193 1.98997785864605384631e+03,
5194 }, qS5[6] = {
5195 8.27766102236537761883e+01,
5196 2.07781416421392987104e+03,
5197 1.88472887785718085070e+04,
5198 5.67511122894947329769e+04,
5199 3.59767538425114471465e+04,
5200 -5.35434275601944773371e+03,
5201 }, qR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */
5202 4.37741014089738620906e-09,
5203 7.32411180042911447163e-02,
5204 3.34423137516170720929e+00,
5205 4.26218440745412650017e+01,
5206 1.70808091340565596283e+02,
5207 1.66733948696651168575e+02,
5208 }, qS3[6] = {
5209 4.87588729724587182091e+01,
5210 7.09689221056606015736e+02,
5211 3.70414822620111362994e+03,
5212 6.46042516752568917582e+03,
5213 2.51633368920368957333e+03,
5214 -1.49247451836156386662e+02,
5215 }, qR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
5216 1.50444444886983272379e-07,
5217 7.32234265963079278272e-02,
5218 1.99819174093815998816e+00,
5219 1.44956029347885735348e+01,
5220 3.16662317504781540833e+01,
5221 1.62527075710929267416e+01,
5222 }, qS2[6] = {
5223 3.03655848355219184498e+01,
5224 2.69348118608049844624e+02,
5225 8.44783757595320139444e+02,
5226 8.82935845112488550512e+02,
5227 2.12666388511798828631e+02,
5228 -5.31095493882666946917e+00,
5231 const double *p, *q;
5232 double s, r, z;
5233 unsigned int ix;
5235 ix = *(ULONGLONG*)&x >> 32;
5236 ix &= 0x7fffffff;
5237 if (ix >= 0x40200000) {
5238 p = qR8;
5239 q = qS8;
5240 } else if (ix >= 0x40122E8B) {
5241 p = qR5;
5242 q = qS5;
5243 } else if (ix >= 0x4006DB6D) {
5244 p = qR3;
5245 q = qS3;
5246 } else /*ix >= 0x40000000*/ {
5247 p = qR2;
5248 q = qS2;
5251 z = 1.0 / (x * x);
5252 r = p[0] + z * (p[1] + z * (p[2] + z * (p[3] + z * (p[4] + z * p[5]))));
5253 s = 1.0 + z * (q[0] + z * (q[1] + z * (q[2] + z * (q[3] + z * (q[4] + z * q[5])))));
5254 return (-0.125 + r / s) / x;
5257 /* j0 and y0 approximation for |x|>=2 */
5258 static double j0_y0_approx(unsigned int ix, double x, BOOL y0)
5260 static const double invsqrtpi = 5.64189583547756279280e-01;
5262 double s, c, ss, cc, z;
5264 s = sin(x);
5265 c = cos(x);
5266 if (y0) c = -c;
5267 cc = s + c;
5268 /* avoid overflow in 2*x, big ulp error when x>=0x1p1023 */
5269 if (ix < 0x7fe00000) {
5270 ss = s - c;
5271 z = -cos(2 * x);
5272 if (s * c < 0) cc = z / ss;
5273 else ss = z / cc;
5274 if (ix < 0x48000000) {
5275 if (y0) ss = -ss;
5276 cc = pzero(x) * cc - qzero(x) * ss;
5279 return invsqrtpi * cc / sqrt(x);
5282 /*********************************************************************
5283 * _j0 (MSVCRT.@)
5285 * Copied from musl: src/math/j0.c
5287 double CDECL _j0(double x)
5289 static const double R02 = 1.56249999999999947958e-02,
5290 R03 = -1.89979294238854721751e-04,
5291 R04 = 1.82954049532700665670e-06,
5292 R05 = -4.61832688532103189199e-09,
5293 S01 = 1.56191029464890010492e-02,
5294 S02 = 1.16926784663337450260e-04,
5295 S03 = 5.13546550207318111446e-07,
5296 S04 = 1.16614003333790000205e-09;
5298 double z, r, s;
5299 unsigned int ix;
5301 ix = *(ULONGLONG*)&x >> 32;
5302 ix &= 0x7fffffff;
5304 /* j0(+-inf)=0, j0(nan)=nan */
5305 if (ix >= 0x7ff00000)
5306 return math_error(_DOMAIN, "_j0", x, 0, 1 / (x * x));
5307 x = fabs(x);
5309 if (ix >= 0x40000000) { /* |x| >= 2 */
5310 /* large ulp error near zeros: 2.4, 5.52, 8.6537,.. */
5311 return j0_y0_approx(ix, x, FALSE);
5314 if (ix >= 0x3f200000) { /* |x| >= 2**-13 */
5315 /* up to 4ulp error close to 2 */
5316 z = x * x;
5317 r = z * (R02 + z * (R03 + z * (R04 + z * R05)));
5318 s = 1 + z * (S01 + z * (S02 + z * (S03 + z * S04)));
5319 return (1 + x / 2) * (1 - x / 2) + z * (r / s);
5322 /* 1 - x*x/4 */
5323 /* prevent underflow */
5324 /* inexact should be raised when x!=0, this is not done correctly */
5325 if (ix >= 0x38000000) /* |x| >= 2**-127 */
5326 x = 0.25 * x * x;
5327 return 1 - x;
5330 static double pone(double x)
5332 static const double pr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
5333 0.00000000000000000000e+00,
5334 1.17187499999988647970e-01,
5335 1.32394806593073575129e+01,
5336 4.12051854307378562225e+02,
5337 3.87474538913960532227e+03,
5338 7.91447954031891731574e+03,
5339 }, ps8[5] = {
5340 1.14207370375678408436e+02,
5341 3.65093083420853463394e+03,
5342 3.69562060269033463555e+04,
5343 9.76027935934950801311e+04,
5344 3.08042720627888811578e+04,
5345 }, pr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
5346 1.31990519556243522749e-11,
5347 1.17187493190614097638e-01,
5348 6.80275127868432871736e+00,
5349 1.08308182990189109773e+02,
5350 5.17636139533199752805e+02,
5351 5.28715201363337541807e+02,
5352 }, ps5[5] = {
5353 5.92805987221131331921e+01,
5354 9.91401418733614377743e+02,
5355 5.35326695291487976647e+03,
5356 7.84469031749551231769e+03,
5357 1.50404688810361062679e+03,
5358 }, pr3[6] = {
5359 3.02503916137373618024e-09,
5360 1.17186865567253592491e-01,
5361 3.93297750033315640650e+00,
5362 3.51194035591636932736e+01,
5363 9.10550110750781271918e+01,
5364 4.85590685197364919645e+01,
5365 }, ps3[5] = {
5366 3.47913095001251519989e+01,
5367 3.36762458747825746741e+02,
5368 1.04687139975775130551e+03,
5369 8.90811346398256432622e+02,
5370 1.03787932439639277504e+02,
5371 }, pr2[6] = { /* for x in [2.8570,2]=1/[0.3499,0.5] */
5372 1.07710830106873743082e-07,
5373 1.17176219462683348094e-01,
5374 2.36851496667608785174e+00,
5375 1.22426109148261232917e+01,
5376 1.76939711271687727390e+01,
5377 5.07352312588818499250e+00,
5378 }, ps2[5] = {
5379 2.14364859363821409488e+01,
5380 1.25290227168402751090e+02,
5381 2.32276469057162813669e+02,
5382 1.17679373287147100768e+02,
5383 8.36463893371618283368e+00,
5386 const double *p, *q;
5387 double z, r, s;
5388 unsigned int ix;
5390 ix = *(ULONGLONG*)&x >> 32;
5391 ix &= 0x7fffffff;
5392 if (ix >= 0x40200000) {
5393 p = pr8;
5394 q = ps8;
5395 } else if (ix >= 0x40122E8B) {
5396 p = pr5;
5397 q = ps5;
5398 } else if (ix >= 0x4006DB6D) {
5399 p = pr3;
5400 q = ps3;
5401 } else /*ix >= 0x40000000*/ {
5402 p = pr2;
5403 q = ps2;
5405 z = 1.0 / (x * x);
5406 r = p[0] + z * (p[1] + z * (p[2] + z * (p[3] + z * (p[4] + z * p[5]))));
5407 s = 1.0 + z * (q[0] + z * (q[1] + z * (q[2] + z * (q[3] + z * q[4]))));
5408 return 1.0 + r / s;
5411 static double qone(double x)
5413 static const double qr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
5414 0.00000000000000000000e+00,
5415 -1.02539062499992714161e-01,
5416 -1.62717534544589987888e+01,
5417 -7.59601722513950107896e+02,
5418 -1.18498066702429587167e+04,
5419 -4.84385124285750353010e+04,
5420 }, qs8[6] = {
5421 1.61395369700722909556e+02,
5422 7.82538599923348465381e+03,
5423 1.33875336287249578163e+05,
5424 7.19657723683240939863e+05,
5425 6.66601232617776375264e+05,
5426 -2.94490264303834643215e+05,
5427 }, qr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
5428 -2.08979931141764104297e-11,
5429 -1.02539050241375426231e-01,
5430 -8.05644828123936029840e+00,
5431 -1.83669607474888380239e+02,
5432 -1.37319376065508163265e+03,
5433 -2.61244440453215656817e+03,
5434 }, qs5[6] = {
5435 8.12765501384335777857e+01,
5436 1.99179873460485964642e+03,
5437 1.74684851924908907677e+04,
5438 4.98514270910352279316e+04,
5439 2.79480751638918118260e+04,
5440 -4.71918354795128470869e+03,
5441 }, qr3[6] = {
5442 -5.07831226461766561369e-09,
5443 -1.02537829820837089745e-01,
5444 -4.61011581139473403113e+00,
5445 -5.78472216562783643212e+01,
5446 -2.28244540737631695038e+02,
5447 -2.19210128478909325622e+02,
5448 }, qs3[6] = {
5449 4.76651550323729509273e+01,
5450 6.73865112676699709482e+02,
5451 3.38015286679526343505e+03,
5452 5.54772909720722782367e+03,
5453 1.90311919338810798763e+03,
5454 -1.35201191444307340817e+02,
5455 }, qr2[6] = { /* for x in [2.8570,2]=1/[0.3499,0.5] */
5456 -1.78381727510958865572e-07,
5457 -1.02517042607985553460e-01,
5458 -2.75220568278187460720e+00,
5459 -1.96636162643703720221e+01,
5460 -4.23253133372830490089e+01,
5461 -2.13719211703704061733e+01,
5462 }, qs2[6] = {
5463 2.95333629060523854548e+01,
5464 2.52981549982190529136e+02,
5465 7.57502834868645436472e+02,
5466 7.39393205320467245656e+02,
5467 1.55949003336666123687e+02,
5468 -4.95949898822628210127e+00,
5471 const double *p, *q;
5472 double s, r, z;
5473 unsigned int ix;
5475 ix = *(ULONGLONG*)&x >> 32;
5476 ix &= 0x7fffffff;
5477 if (ix >= 0x40200000) {
5478 p = qr8;
5479 q = qs8;
5480 } else if (ix >= 0x40122E8B) {
5481 p = qr5;
5482 q = qs5;
5483 } else if (ix >= 0x4006DB6D) {
5484 p = qr3;
5485 q = qs3;
5486 } else /*ix >= 0x40000000*/ {
5487 p = qr2;
5488 q = qs2;
5490 z = 1.0 / (x * x);
5491 r = p[0] + z * (p[1] + z * (p[2] + z * (p[3] + z * (p[4] + z * p[5]))));
5492 s = 1.0 + z * (q[0] + z * (q[1] + z * (q[2] + z * (q[3] + z * (q[4] + z * q[5])))));
5493 return (0.375 + r / s) / x;
5496 static double j1_y1_approx(unsigned int ix, double x, BOOL y1, int sign)
5498 static const double invsqrtpi = 5.64189583547756279280e-01;
5500 double z, s, c, ss, cc;
5502 s = sin(x);
5503 if (y1) s = -s;
5504 c = cos(x);
5505 cc = s - c;
5506 if (ix < 0x7fe00000) {
5507 ss = -s - c;
5508 z = cos(2 * x);
5509 if (s * c > 0) cc = z / ss;
5510 else ss = z / cc;
5511 if (ix < 0x48000000) {
5512 if (y1)
5513 ss = -ss;
5514 cc = pone(x) * cc - qone(x) * ss;
5517 if (sign)
5518 cc = -cc;
5519 return invsqrtpi * cc / sqrt(x);
5522 /*********************************************************************
5523 * _j1 (MSVCRT.@)
5525 * Copied from musl: src/math/j1.c
5527 double CDECL _j1(double x)
5529 static const double r00 = -6.25000000000000000000e-02,
5530 r01 = 1.40705666955189706048e-03,
5531 r02 = -1.59955631084035597520e-05,
5532 r03 = 4.96727999609584448412e-08,
5533 s01 = 1.91537599538363460805e-02,
5534 s02 = 1.85946785588630915560e-04,
5535 s03 = 1.17718464042623683263e-06,
5536 s04 = 5.04636257076217042715e-09,
5537 s05 = 1.23542274426137913908e-11;
5539 double z, r, s;
5540 unsigned int ix;
5541 int sign;
5543 ix = *(ULONGLONG*)&x >> 32;
5544 sign = ix >> 31;
5545 ix &= 0x7fffffff;
5546 if (ix >= 0x7ff00000)
5547 return math_error(isnan(x) ? 0 : _DOMAIN, "_j1", x, 0, 1 / (x * x));
5548 if (ix >= 0x40000000) /* |x| >= 2 */
5549 return j1_y1_approx(ix, fabs(x), FALSE, sign);
5550 if (ix >= 0x38000000) { /* |x| >= 2**-127 */
5551 z = x * x;
5552 r = z * (r00 + z * (r01 + z * (r02 + z * r03)));
5553 s = 1 + z * (s01 + z * (s02 + z * (s03 + z * (s04 + z * s05))));
5554 z = r / s;
5555 } else {
5556 /* avoid underflow, raise inexact if x!=0 */
5557 z = x;
5559 return (0.5 + z) * x;
5562 /*********************************************************************
5563 * _jn (MSVCRT.@)
5565 * Copied from musl: src/math/jn.c
5567 double CDECL _jn(int n, double x)
5569 static const double invsqrtpi = 5.64189583547756279280e-01;
5571 unsigned int ix, lx;
5572 int nm1, i, sign;
5573 double a, b, temp;
5575 ix = *(ULONGLONG*)&x >> 32;
5576 lx = *(ULONGLONG*)&x;
5577 sign = ix >> 31;
5578 ix &= 0x7fffffff;
5580 if ((ix | (lx | -lx) >> 31) > 0x7ff00000) /* nan */
5581 return x;
5583 if (n == 0)
5584 return _j0(x);
5585 if (n < 0) {
5586 nm1 = -(n + 1);
5587 x = -x;
5588 sign ^= 1;
5589 } else {
5590 nm1 = n-1;
5592 if (nm1 == 0)
5593 return j1(x);
5595 sign &= n; /* even n: 0, odd n: signbit(x) */
5596 x = fabs(x);
5597 if ((ix | lx) == 0 || ix == 0x7ff00000) /* if x is 0 or inf */
5598 b = 0.0;
5599 else if (nm1 < x) {
5600 if (ix >= 0x52d00000) { /* x > 2**302 */
5601 switch(nm1 & 3) {
5602 case 0:
5603 temp = -cos(x) + sin(x);
5604 break;
5605 case 1:
5606 temp = -cos(x) - sin(x);
5607 break;
5608 case 2:
5609 temp = cos(x) - sin(x);
5610 break;
5611 default:
5612 temp = cos(x) + sin(x);
5613 break;
5615 b = invsqrtpi * temp / sqrt(x);
5616 } else {
5617 a = _j0(x);
5618 b = _j1(x);
5619 for (i = 0; i < nm1; ) {
5620 i++;
5621 temp = b;
5622 b = b * (2.0 * i / x) - a; /* avoid underflow */
5623 a = temp;
5626 } else {
5627 if (ix < 0x3e100000) { /* x < 2**-29 */
5628 if (nm1 > 32) /* underflow */
5629 b = 0.0;
5630 else {
5631 temp = x * 0.5;
5632 b = temp;
5633 a = 1.0;
5634 for (i = 2; i <= nm1 + 1; i++) {
5635 a *= (double)i; /* a = n! */
5636 b *= temp; /* b = (x/2)^n */
5638 b = b / a;
5640 } else {
5641 double t, q0, q1, w, h, z, tmp, nf;
5642 int k;
5644 nf = nm1 + 1.0;
5645 w = 2 * nf / x;
5646 h = 2 / x;
5647 z = w + h;
5648 q0 = w;
5649 q1 = w * z - 1.0;
5650 k = 1;
5651 while (q1 < 1.0e9) {
5652 k += 1;
5653 z += h;
5654 tmp = z * q1 - q0;
5655 q0 = q1;
5656 q1 = tmp;
5658 for (t = 0.0, i = k; i >= 0; i--)
5659 t = 1 / (2 * (i + nf) / x - t);
5660 a = t;
5661 b = 1.0;
5662 tmp = nf * log(fabs(w));
5663 if (tmp < 7.09782712893383973096e+02) {
5664 for (i = nm1; i > 0; i--) {
5665 temp = b;
5666 b = b * (2.0 * i) / x - a;
5667 a = temp;
5669 } else {
5670 for (i = nm1; i > 0; i--) {
5671 temp = b;
5672 b = b * (2.0 * i) / x - a;
5673 a = temp;
5674 /* scale b to avoid spurious overflow */
5675 if (b > 0x1p500) {
5676 a /= b;
5677 t /= b;
5678 b = 1.0;
5682 z = j0(x);
5683 w = j1(x);
5684 if (fabs(z) >= fabs(w))
5685 b = t * z / b;
5686 else
5687 b = t * w / a;
5690 return sign ? -b : b;
5693 /*********************************************************************
5694 * _y0 (MSVCRT.@)
5696 double CDECL _y0(double x)
5698 static const double tpi = 6.36619772367581382433e-01,
5699 u00 = -7.38042951086872317523e-02,
5700 u01 = 1.76666452509181115538e-01,
5701 u02 = -1.38185671945596898896e-02,
5702 u03 = 3.47453432093683650238e-04,
5703 u04 = -3.81407053724364161125e-06,
5704 u05 = 1.95590137035022920206e-08,
5705 u06 = -3.98205194132103398453e-11,
5706 v01 = 1.27304834834123699328e-02,
5707 v02 = 7.60068627350353253702e-05,
5708 v03 = 2.59150851840457805467e-07,
5709 v04 = 4.41110311332675467403e-10;
5711 double z, u, v;
5712 unsigned int ix, lx;
5714 ix = *(ULONGLONG*)&x >> 32;
5715 lx = *(ULONGLONG*)&x;
5717 /* y0(nan)=nan, y0(<0)=nan, y0(0)=-inf, y0(inf)=0 */
5718 if ((ix << 1 | lx) == 0)
5719 return math_error(_OVERFLOW, "_y0", x, 0, -INFINITY);
5720 if (isnan(x))
5721 return x;
5722 if (ix >> 31)
5723 return math_error(_DOMAIN, "_y0", x, 0, 0 / (x - x));
5724 if (ix >= 0x7ff00000)
5725 return 1 / x;
5727 if (ix >= 0x40000000) { /* x >= 2 */
5728 /* large ulp errors near zeros: 3.958, 7.086,.. */
5729 return j0_y0_approx(ix, x, TRUE);
5732 if (ix >= 0x3e400000) { /* x >= 2**-27 */
5733 /* large ulp error near the first zero, x ~= 0.89 */
5734 z = x * x;
5735 u = u00 + z * (u01 + z * (u02 + z * (u03 + z * (u04 + z * (u05 + z * u06)))));
5736 v = 1.0 + z * (v01 + z * (v02 + z * (v03 + z * v04)));
5737 return u / v + tpi * (j0(x) * log(x));
5739 return u00 + tpi * log(x);
5742 /*********************************************************************
5743 * _y1 (MSVCRT.@)
5745 double CDECL _y1(double x)
5747 static const double tpi = 6.36619772367581382433e-01,
5748 u00 = -1.96057090646238940668e-01,
5749 u01 = 5.04438716639811282616e-02,
5750 u02 = -1.91256895875763547298e-03,
5751 u03 = 2.35252600561610495928e-05,
5752 u04 = -9.19099158039878874504e-08,
5753 v00 = 1.99167318236649903973e-02,
5754 v01 = 2.02552581025135171496e-04,
5755 v02 = 1.35608801097516229404e-06,
5756 v03 = 6.22741452364621501295e-09,
5757 v04 = 1.66559246207992079114e-11;
5759 double z, u, v;
5760 unsigned int ix, lx;
5762 ix = *(ULONGLONG*)&x >> 32;
5763 lx = *(ULONGLONG*)&x;
5765 /* y1(nan)=nan, y1(<0)=nan, y1(0)=-inf, y1(inf)=0 */
5766 if ((ix << 1 | lx) == 0)
5767 return math_error(_OVERFLOW, "_y1", x, 0, -INFINITY);
5768 if (isnan(x))
5769 return x;
5770 if (ix >> 31)
5771 return math_error(_DOMAIN, "_y1", x, 0, 0 / (x - x));
5772 if (ix >= 0x7ff00000)
5773 return 1 / x;
5775 if (ix >= 0x40000000) /* x >= 2 */
5776 return j1_y1_approx(ix, x, TRUE, 0);
5777 if (ix < 0x3c900000) /* x < 2**-54 */
5778 return -tpi / x;
5779 z = x * x;
5780 u = u00 + z * (u01 + z * (u02 + z * (u03 + z * u04)));
5781 v = 1 + z * (v00 + z * (v01 + z * (v02 + z * (v03 + z * v04))));
5782 return x * (u / v) + tpi * (j1(x) * log(x) - 1 / x);
5785 /*********************************************************************
5786 * _yn (MSVCRT.@)
5788 * Copied from musl: src/math/jn.c
5790 double CDECL _yn(int n, double x)
5792 static const double invsqrtpi = 5.64189583547756279280e-01;
5794 unsigned int ix, lx, ib;
5795 int nm1, sign, i;
5796 double a, b, temp;
5798 ix = *(ULONGLONG*)&x >> 32;
5799 lx = *(ULONGLONG*)&x;
5800 sign = ix >> 31;
5801 ix &= 0x7fffffff;
5803 if ((ix | (lx | -lx) >> 31) > 0x7ff00000) /* nan */
5804 return x;
5805 if (sign && (ix | lx) != 0) /* x < 0 */
5806 return math_error(_DOMAIN, "_y1", x, 0, 0 / (x - x));
5807 if (ix == 0x7ff00000)
5808 return 0.0;
5810 if (n == 0)
5811 return y0(x);
5812 if (n < 0) {
5813 nm1 = -(n + 1);
5814 sign = n & 1;
5815 } else {
5816 nm1 = n - 1;
5817 sign = 0;
5819 if (nm1 == 0)
5820 return sign ? -y1(x) : y1(x);
5822 if (ix >= 0x52d00000) { /* x > 2**302 */
5823 switch(nm1 & 3) {
5824 case 0:
5825 temp = -sin(x) - cos(x);
5826 break;
5827 case 1:
5828 temp = -sin(x) + cos(x);
5829 break;
5830 case 2:
5831 temp = sin(x) + cos(x);
5832 break;
5833 default:
5834 temp = sin(x) - cos(x);
5835 break;
5837 b = invsqrtpi * temp / sqrt(x);
5838 } else {
5839 a = y0(x);
5840 b = y1(x);
5841 /* quit if b is -inf */
5842 ib = *(ULONGLONG*)&b >> 32;
5843 for (i = 0; i < nm1 && ib != 0xfff00000;) {
5844 i++;
5845 temp = b;
5846 b = (2.0 * i / x) * b - a;
5847 ib = *(ULONGLONG*)&b >> 32;
5848 a = temp;
5851 return sign ? -b : b;
5854 #if _MSVCR_VER>=120
5856 /*********************************************************************
5857 * _nearbyint (MSVCR120.@)
5859 * Based on musl: src/math/nearbyteint.c
5861 double CDECL nearbyint(double x)
5863 fenv_t env;
5865 fegetenv(&env);
5866 _control87(_MCW_EM, _MCW_EM);
5867 x = rint(x);
5868 feclearexcept(FE_INEXACT);
5869 feupdateenv(&env);
5870 return x;
5873 /*********************************************************************
5874 * _nearbyintf (MSVCR120.@)
5876 * Based on musl: src/math/nearbyteintf.c
5878 float CDECL nearbyintf(float x)
5880 fenv_t env;
5882 fegetenv(&env);
5883 _control87(_MCW_EM, _MCW_EM);
5884 x = rintf(x);
5885 feclearexcept(FE_INEXACT);
5886 feupdateenv(&env);
5887 return x;
5890 /*********************************************************************
5891 * nexttoward (MSVCR120.@)
5893 double CDECL MSVCRT_nexttoward(double num, double next)
5895 return _nextafter(num, next);
5898 /*********************************************************************
5899 * nexttowardf (MSVCR120.@)
5901 * Copied from musl: src/math/nexttowardf.c
5903 float CDECL MSVCRT_nexttowardf(float x, double y)
5905 unsigned int ix = *(unsigned int*)&x;
5906 unsigned int e;
5907 float ret;
5909 if (isnan(x) || isnan(y))
5910 return x + y;
5911 if (x == y)
5912 return y;
5913 if (x == 0) {
5914 ix = 1;
5915 if (signbit(y))
5916 ix |= 0x80000000;
5917 } else if (x < y) {
5918 if (signbit(x))
5919 ix--;
5920 else
5921 ix++;
5922 } else {
5923 if (signbit(x))
5924 ix++;
5925 else
5926 ix--;
5928 e = ix & 0x7f800000;
5929 /* raise overflow if ix is infinite and x is finite */
5930 if (e == 0x7f800000) {
5931 fp_barrierf(x + x);
5932 *_errno() = ERANGE;
5934 ret = *(float*)&ix;
5935 /* raise underflow if ret is subnormal or zero */
5936 if (e == 0) {
5937 fp_barrierf(x * x + ret * ret);
5938 *_errno() = ERANGE;
5940 return ret;
5943 #endif /* _MSVCR_VER>=120 */
5945 /*********************************************************************
5946 * _nextafter (MSVCRT.@)
5948 * Copied from musl: src/math/nextafter.c
5950 double CDECL _nextafter(double x, double y)
5952 ULONGLONG llx = *(ULONGLONG*)&x;
5953 ULONGLONG lly = *(ULONGLONG*)&y;
5954 ULONGLONG ax, ay;
5955 int e;
5957 if (isnan(x) || isnan(y))
5958 return x + y;
5959 if (llx == lly) {
5960 if (_fpclass(y) & (_FPCLASS_ND | _FPCLASS_PD | _FPCLASS_NZ | _FPCLASS_PZ ))
5961 *_errno() = ERANGE;
5962 return y;
5964 ax = llx & -1ULL / 2;
5965 ay = lly & -1ULL / 2;
5966 if (ax == 0) {
5967 if (ay == 0)
5968 return y;
5969 llx = (lly & 1ULL << 63) | 1;
5970 } else if (ax > ay || ((llx ^ lly) & 1ULL << 63))
5971 llx--;
5972 else
5973 llx++;
5974 e = llx >> 52 & 0x7ff;
5975 /* raise overflow if llx is infinite and x is finite */
5976 if (e == 0x7ff) {
5977 fp_barrier(x + x);
5978 *_errno() = ERANGE;
5980 /* raise underflow if llx is subnormal or zero */
5981 y = *(double*)&llx;
5982 if (e == 0) {
5983 fp_barrier(x * x + y * y);
5984 *_errno() = ERANGE;
5986 return y;
5989 /*********************************************************************
5990 * _ecvt (MSVCRT.@)
5992 char * CDECL _ecvt( double number, int ndigits, int *decpt, int *sign )
5994 int prec, len;
5995 thread_data_t *data = msvcrt_get_thread_data();
5996 /* FIXME: check better for overflow (native supports over 300 chars) */
5997 ndigits = min( ndigits, 80 - 8); /* 8 : space for sign, dec point, "e",
5998 * 4 for exponent and one for
5999 * terminating '\0' */
6000 if (!data->efcvt_buffer)
6001 data->efcvt_buffer = malloc( 80 ); /* ought to be enough */
6003 /* handle cases with zero ndigits or less */
6004 prec = ndigits;
6005 if( prec < 1) prec = 2;
6006 len = _snprintf(data->efcvt_buffer, 80, "%.*le", prec - 1, number);
6008 if (data->efcvt_buffer[0] == '-') {
6009 memmove( data->efcvt_buffer, data->efcvt_buffer + 1, len-- );
6010 *sign = 1;
6011 } else *sign = 0;
6013 /* take the decimal "point away */
6014 if( prec != 1)
6015 memmove( data->efcvt_buffer + 1, data->efcvt_buffer + 2, len - 1 );
6016 /* take the exponential "e" out */
6017 data->efcvt_buffer[ prec] = '\0';
6018 /* read the exponent */
6019 sscanf( data->efcvt_buffer + prec + 1, "%d", decpt);
6020 (*decpt)++;
6021 /* adjust for some border cases */
6022 if( data->efcvt_buffer[0] == '0')/* value is zero */
6023 *decpt = 0;
6024 /* handle cases with zero ndigits or less */
6025 if( ndigits < 1){
6026 if( data->efcvt_buffer[ 0] >= '5')
6027 (*decpt)++;
6028 data->efcvt_buffer[ 0] = '\0';
6030 TRACE("out=\"%s\"\n",data->efcvt_buffer);
6031 return data->efcvt_buffer;
6034 /*********************************************************************
6035 * _ecvt_s (MSVCRT.@)
6037 int CDECL _ecvt_s( char *buffer, size_t length, double number, int ndigits, int *decpt, int *sign )
6039 int prec, len;
6040 char *result;
6042 if (!MSVCRT_CHECK_PMT(buffer != NULL)) return EINVAL;
6043 if (!MSVCRT_CHECK_PMT(decpt != NULL)) return EINVAL;
6044 if (!MSVCRT_CHECK_PMT(sign != NULL)) return EINVAL;
6045 if (!MSVCRT_CHECK_PMT_ERR( length > 2, ERANGE )) return ERANGE;
6046 if (!MSVCRT_CHECK_PMT_ERR(ndigits < (int)length - 1, ERANGE )) return ERANGE;
6048 /* handle cases with zero ndigits or less */
6049 prec = ndigits;
6050 if( prec < 1) prec = 2;
6051 result = malloc(prec + 8);
6053 len = _snprintf(result, prec + 8, "%.*le", prec - 1, number);
6054 if (result[0] == '-') {
6055 memmove( result, result + 1, len-- );
6056 *sign = 1;
6057 } else *sign = 0;
6059 /* take the decimal "point away */
6060 if( prec != 1)
6061 memmove( result + 1, result + 2, len - 1 );
6062 /* take the exponential "e" out */
6063 result[ prec] = '\0';
6064 /* read the exponent */
6065 sscanf( result + prec + 1, "%d", decpt);
6066 (*decpt)++;
6067 /* adjust for some border cases */
6068 if( result[0] == '0')/* value is zero */
6069 *decpt = 0;
6070 /* handle cases with zero ndigits or less */
6071 if( ndigits < 1){
6072 if( result[ 0] >= '5')
6073 (*decpt)++;
6074 result[ 0] = '\0';
6076 memcpy( buffer, result, max(ndigits + 1, 1) );
6077 free( result );
6078 return 0;
6081 /***********************************************************************
6082 * _fcvt (MSVCRT.@)
6084 char * CDECL _fcvt( double number, int ndigits, int *decpt, int *sign )
6086 thread_data_t *data = msvcrt_get_thread_data();
6087 int stop, dec1, dec2;
6088 char *ptr1, *ptr2, *first;
6089 char buf[80]; /* ought to be enough */
6090 char decimal_separator = get_locinfo()->lconv->decimal_point[0];
6092 if (!data->efcvt_buffer)
6093 data->efcvt_buffer = malloc( 80 ); /* ought to be enough */
6095 stop = _snprintf(buf, 80, "%.*f", ndigits < 0 ? 0 : ndigits, number);
6096 ptr1 = buf;
6097 ptr2 = data->efcvt_buffer;
6098 first = NULL;
6099 dec1 = 0;
6100 dec2 = 0;
6102 if (*ptr1 == '-') {
6103 *sign = 1;
6104 ptr1++;
6105 } else *sign = 0;
6107 /* For numbers below the requested resolution, work out where
6108 the decimal point will be rather than finding it in the string */
6109 if (number < 1.0 && number > 0.0) {
6110 dec2 = log10(number + 1e-10);
6111 if (-dec2 <= ndigits) dec2 = 0;
6114 /* If requested digits is zero or less, we will need to truncate
6115 * the returned string */
6116 if (ndigits < 1) {
6117 stop += ndigits;
6120 while (*ptr1 == '0') ptr1++; /* Skip leading zeroes */
6121 while (*ptr1 != '\0' && *ptr1 != decimal_separator) {
6122 if (!first) first = ptr2;
6123 if ((ptr1 - buf) < stop) {
6124 *ptr2++ = *ptr1++;
6125 } else {
6126 ptr1++;
6128 dec1++;
6131 if (ndigits > 0) {
6132 ptr1++;
6133 if (!first) {
6134 while (*ptr1 == '0') { /* Process leading zeroes */
6135 *ptr2++ = *ptr1++;
6136 dec1--;
6139 while (*ptr1 != '\0') {
6140 if (!first) first = ptr2;
6141 *ptr2++ = *ptr1++;
6145 *ptr2 = '\0';
6147 /* We never found a non-zero digit, then our number is either
6148 * smaller than the requested precision, or 0.0 */
6149 if (!first) {
6150 if (number > 0.0) {
6151 first = ptr2;
6152 } else {
6153 first = data->efcvt_buffer;
6154 dec1 = 0;
6158 *decpt = dec2 ? dec2 : dec1;
6159 return first;
6162 /***********************************************************************
6163 * _fcvt_s (MSVCRT.@)
6165 int CDECL _fcvt_s(char* outbuffer, size_t size, double number, int ndigits, int *decpt, int *sign)
6167 int stop, dec1, dec2;
6168 char *ptr1, *ptr2, *first;
6169 char buf[80]; /* ought to be enough */
6170 char decimal_separator = get_locinfo()->lconv->decimal_point[0];
6172 if (!outbuffer || !decpt || !sign || size == 0)
6174 *_errno() = EINVAL;
6175 return EINVAL;
6178 stop = _snprintf(buf, 80, "%.*f", ndigits < 0 ? 0 : ndigits, number);
6179 ptr1 = buf;
6180 ptr2 = outbuffer;
6181 first = NULL;
6182 dec1 = 0;
6183 dec2 = 0;
6185 if (*ptr1 == '-') {
6186 *sign = 1;
6187 ptr1++;
6188 } else *sign = 0;
6190 /* For numbers below the requested resolution, work out where
6191 the decimal point will be rather than finding it in the string */
6192 if (number < 1.0 && number > 0.0) {
6193 dec2 = log10(number + 1e-10);
6194 if (-dec2 <= ndigits) dec2 = 0;
6197 /* If requested digits is zero or less, we will need to truncate
6198 * the returned string */
6199 if (ndigits < 1) {
6200 stop += ndigits;
6203 while (*ptr1 == '0') ptr1++; /* Skip leading zeroes */
6204 while (*ptr1 != '\0' && *ptr1 != decimal_separator) {
6205 if (!first) first = ptr2;
6206 if ((ptr1 - buf) < stop) {
6207 if (size > 1) {
6208 *ptr2++ = *ptr1++;
6209 size--;
6211 } else {
6212 ptr1++;
6214 dec1++;
6217 if (ndigits > 0) {
6218 ptr1++;
6219 if (!first) {
6220 while (*ptr1 == '0') { /* Process leading zeroes */
6221 if (number == 0.0 && size > 1) {
6222 *ptr2++ = '0';
6223 size--;
6225 ptr1++;
6226 dec1--;
6229 while (*ptr1 != '\0') {
6230 if (!first) first = ptr2;
6231 if (size > 1) {
6232 *ptr2++ = *ptr1++;
6233 size--;
6238 *ptr2 = '\0';
6240 /* We never found a non-zero digit, then our number is either
6241 * smaller than the requested precision, or 0.0 */
6242 if (!first && (number <= 0.0))
6243 dec1 = 0;
6245 *decpt = dec2 ? dec2 : dec1;
6246 return 0;
6249 /***********************************************************************
6250 * _gcvt (MSVCRT.@)
6252 char * CDECL _gcvt( double number, int ndigit, char *buff )
6254 if(!buff) {
6255 *_errno() = EINVAL;
6256 return NULL;
6259 if(ndigit < 0) {
6260 *_errno() = ERANGE;
6261 return NULL;
6264 sprintf(buff, "%.*g", ndigit, number);
6265 return buff;
6268 /***********************************************************************
6269 * _gcvt_s (MSVCRT.@)
6271 int CDECL _gcvt_s(char *buff, size_t size, double number, int digits)
6273 int len;
6275 if(!buff) {
6276 *_errno() = EINVAL;
6277 return EINVAL;
6280 if( digits<0 || digits>=size) {
6281 if(size)
6282 buff[0] = '\0';
6284 *_errno() = ERANGE;
6285 return ERANGE;
6288 len = _scprintf("%.*g", digits, number);
6289 if(len > size) {
6290 buff[0] = '\0';
6291 *_errno() = ERANGE;
6292 return ERANGE;
6295 sprintf(buff, "%.*g", digits, number);
6296 return 0;
6299 #include <stdlib.h> /* div_t, ldiv_t */
6301 /*********************************************************************
6302 * div (MSVCRT.@)
6303 * VERSION
6304 * [i386] Windows binary compatible - returns the struct in eax/edx.
6306 #ifdef __i386__
6307 unsigned __int64 CDECL div(int num, int denom)
6309 union {
6310 div_t div;
6311 unsigned __int64 uint64;
6312 } ret;
6314 ret.div.quot = num / denom;
6315 ret.div.rem = num % denom;
6316 return ret.uint64;
6318 #else
6319 /*********************************************************************
6320 * div (MSVCRT.@)
6321 * VERSION
6322 * [!i386] Non-x86 can't run win32 apps so we don't need binary compatibility
6324 div_t CDECL div(int num, int denom)
6326 div_t ret;
6328 ret.quot = num / denom;
6329 ret.rem = num % denom;
6330 return ret;
6332 #endif /* ifdef __i386__ */
6335 /*********************************************************************
6336 * ldiv (MSVCRT.@)
6337 * VERSION
6338 * [i386] Windows binary compatible - returns the struct in eax/edx.
6340 #ifdef __i386__
6341 unsigned __int64 CDECL ldiv(__msvcrt_long num, __msvcrt_long denom)
6343 union {
6344 ldiv_t ldiv;
6345 unsigned __int64 uint64;
6346 } ret;
6348 ret.ldiv.quot = num / denom;
6349 ret.ldiv.rem = num % denom;
6350 return ret.uint64;
6352 #else
6353 /*********************************************************************
6354 * ldiv (MSVCRT.@)
6355 * VERSION
6356 * [!i386] Non-x86 can't run win32 apps so we don't need binary compatibility
6358 ldiv_t CDECL ldiv(__msvcrt_long num, __msvcrt_long denom)
6360 ldiv_t ret;
6362 ret.quot = num / denom;
6363 ret.rem = num % denom;
6364 return ret;
6366 #endif /* ifdef __i386__ */
6368 #if _MSVCR_VER>=100
6369 /*********************************************************************
6370 * lldiv (MSVCR100.@)
6372 lldiv_t CDECL lldiv(__int64 num, __int64 denom)
6374 lldiv_t ret;
6376 ret.quot = num / denom;
6377 ret.rem = num % denom;
6379 return ret;
6381 #endif
6383 #ifdef __i386__
6385 /*********************************************************************
6386 * _adjust_fdiv (MSVCRT.@)
6387 * Used by the MSVC compiler to work around the Pentium FDIV bug.
6389 int MSVCRT__adjust_fdiv = 0;
6391 /***********************************************************************
6392 * _adj_fdiv_m16i (MSVCRT.@)
6394 * NOTE
6395 * I _think_ this function is intended to work around the Pentium
6396 * fdiv bug.
6398 void __stdcall _adj_fdiv_m16i( short arg )
6400 TRACE("(): stub\n");
6403 /***********************************************************************
6404 * _adj_fdiv_m32 (MSVCRT.@)
6406 * NOTE
6407 * I _think_ this function is intended to work around the Pentium
6408 * fdiv bug.
6410 void __stdcall _adj_fdiv_m32( unsigned int arg )
6412 TRACE("(): stub\n");
6415 /***********************************************************************
6416 * _adj_fdiv_m32i (MSVCRT.@)
6418 * NOTE
6419 * I _think_ this function is intended to work around the Pentium
6420 * fdiv bug.
6422 void __stdcall _adj_fdiv_m32i( int arg )
6424 TRACE("(): stub\n");
6427 /***********************************************************************
6428 * _adj_fdiv_m64 (MSVCRT.@)
6430 * NOTE
6431 * I _think_ this function is intended to work around the Pentium
6432 * fdiv bug.
6434 void __stdcall _adj_fdiv_m64( unsigned __int64 arg )
6436 TRACE("(): stub\n");
6439 /***********************************************************************
6440 * _adj_fdiv_r (MSVCRT.@)
6441 * FIXME
6442 * This function is likely to have the wrong number of arguments.
6444 * NOTE
6445 * I _think_ this function is intended to work around the Pentium
6446 * fdiv bug.
6448 void _adj_fdiv_r(void)
6450 TRACE("(): stub\n");
6453 /***********************************************************************
6454 * _adj_fdivr_m16i (MSVCRT.@)
6456 * NOTE
6457 * I _think_ this function is intended to work around the Pentium
6458 * fdiv bug.
6460 void __stdcall _adj_fdivr_m16i( short arg )
6462 TRACE("(): stub\n");
6465 /***********************************************************************
6466 * _adj_fdivr_m32 (MSVCRT.@)
6468 * NOTE
6469 * I _think_ this function is intended to work around the Pentium
6470 * fdiv bug.
6472 void __stdcall _adj_fdivr_m32( unsigned int arg )
6474 TRACE("(): stub\n");
6477 /***********************************************************************
6478 * _adj_fdivr_m32i (MSVCRT.@)
6480 * NOTE
6481 * I _think_ this function is intended to work around the Pentium
6482 * fdiv bug.
6484 void __stdcall _adj_fdivr_m32i( int arg )
6486 TRACE("(): stub\n");
6489 /***********************************************************************
6490 * _adj_fdivr_m64 (MSVCRT.@)
6492 * NOTE
6493 * I _think_ this function is intended to work around the Pentium
6494 * fdiv bug.
6496 void __stdcall _adj_fdivr_m64( unsigned __int64 arg )
6498 TRACE("(): stub\n");
6501 /***********************************************************************
6502 * _adj_fpatan (MSVCRT.@)
6503 * FIXME
6504 * This function is likely to have the wrong number of arguments.
6506 * NOTE
6507 * I _think_ this function is intended to work around the Pentium
6508 * fdiv bug.
6510 void _adj_fpatan(void)
6512 TRACE("(): stub\n");
6515 /***********************************************************************
6516 * _adj_fprem (MSVCRT.@)
6517 * FIXME
6518 * This function is likely to have the wrong number of arguments.
6520 * NOTE
6521 * I _think_ this function is intended to work around the Pentium
6522 * fdiv bug.
6524 void _adj_fprem(void)
6526 TRACE("(): stub\n");
6529 /***********************************************************************
6530 * _adj_fprem1 (MSVCRT.@)
6531 * FIXME
6532 * This function is likely to have the wrong number of arguments.
6534 * NOTE
6535 * I _think_ this function is intended to work around the Pentium
6536 * fdiv bug.
6538 void _adj_fprem1(void)
6540 TRACE("(): stub\n");
6543 /***********************************************************************
6544 * _adj_fptan (MSVCRT.@)
6545 * FIXME
6546 * This function is likely to have the wrong number of arguments.
6548 * NOTE
6549 * I _think_ this function is intended to work around the Pentium
6550 * fdiv bug.
6552 void _adj_fptan(void)
6554 TRACE("(): stub\n");
6557 /***********************************************************************
6558 * _safe_fdiv (MSVCRT.@)
6559 * FIXME
6560 * This function is likely to have the wrong number of arguments.
6562 * NOTE
6563 * I _think_ this function is intended to work around the Pentium
6564 * fdiv bug.
6566 void _safe_fdiv(void)
6568 TRACE("(): stub\n");
6571 /***********************************************************************
6572 * _safe_fdivr (MSVCRT.@)
6573 * FIXME
6574 * This function is likely to have the wrong number of arguments.
6576 * NOTE
6577 * I _think_ this function is intended to work around the Pentium
6578 * fdiv bug.
6580 void _safe_fdivr(void)
6582 TRACE("(): stub\n");
6585 /***********************************************************************
6586 * _safe_fprem (MSVCRT.@)
6587 * FIXME
6588 * This function is likely to have the wrong number of arguments.
6590 * NOTE
6591 * I _think_ this function is intended to work around the Pentium
6592 * fdiv bug.
6594 void _safe_fprem(void)
6596 TRACE("(): stub\n");
6599 /***********************************************************************
6600 * _safe_fprem1 (MSVCRT.@)
6602 * FIXME
6603 * This function is likely to have the wrong number of arguments.
6605 * NOTE
6606 * I _think_ this function is intended to work around the Pentium
6607 * fdiv bug.
6609 void _safe_fprem1(void)
6611 TRACE("(): stub\n");
6614 /***********************************************************************
6615 * __libm_sse2_acos (MSVCRT.@)
6617 void __cdecl __libm_sse2_acos(void)
6619 double d;
6620 __asm__ __volatile__( "movq %%xmm0,%0" : "=m" (d) );
6621 d = acos( d );
6622 __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d) );
6625 /***********************************************************************
6626 * __libm_sse2_acosf (MSVCRT.@)
6628 void __cdecl __libm_sse2_acosf(void)
6630 float f;
6631 __asm__ __volatile__( "movd %%xmm0,%0" : "=g" (f) );
6632 f = acosf( f );
6633 __asm__ __volatile__( "movd %0,%%xmm0" : : "g" (f) );
6636 /***********************************************************************
6637 * __libm_sse2_asin (MSVCRT.@)
6639 void __cdecl __libm_sse2_asin(void)
6641 double d;
6642 __asm__ __volatile__( "movq %%xmm0,%0" : "=m" (d) );
6643 d = asin( d );
6644 __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d) );
6647 /***********************************************************************
6648 * __libm_sse2_asinf (MSVCRT.@)
6650 void __cdecl __libm_sse2_asinf(void)
6652 float f;
6653 __asm__ __volatile__( "movd %%xmm0,%0" : "=g" (f) );
6654 f = asinf( f );
6655 __asm__ __volatile__( "movd %0,%%xmm0" : : "g" (f) );
6658 /***********************************************************************
6659 * __libm_sse2_atan (MSVCRT.@)
6661 void __cdecl __libm_sse2_atan(void)
6663 double d;
6664 __asm__ __volatile__( "movq %%xmm0,%0" : "=m" (d) );
6665 d = atan( d );
6666 __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d) );
6669 /***********************************************************************
6670 * __libm_sse2_atan2 (MSVCRT.@)
6672 void __cdecl __libm_sse2_atan2(void)
6674 double d1, d2;
6675 __asm__ __volatile__( "movq %%xmm0,%0; movq %%xmm1,%1 " : "=m" (d1), "=m" (d2) );
6676 d1 = atan2( d1, d2 );
6677 __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d1) );
6680 /***********************************************************************
6681 * __libm_sse2_atanf (MSVCRT.@)
6683 void __cdecl __libm_sse2_atanf(void)
6685 float f;
6686 __asm__ __volatile__( "movd %%xmm0,%0" : "=g" (f) );
6687 f = atanf( f );
6688 __asm__ __volatile__( "movd %0,%%xmm0" : : "g" (f) );
6691 /***********************************************************************
6692 * __libm_sse2_cos (MSVCRT.@)
6694 void __cdecl __libm_sse2_cos(void)
6696 double d;
6697 __asm__ __volatile__( "movq %%xmm0,%0" : "=m" (d) );
6698 d = cos( d );
6699 __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d) );
6702 /***********************************************************************
6703 * __libm_sse2_cosf (MSVCRT.@)
6705 void __cdecl __libm_sse2_cosf(void)
6707 float f;
6708 __asm__ __volatile__( "movd %%xmm0,%0" : "=g" (f) );
6709 f = cosf( f );
6710 __asm__ __volatile__( "movd %0,%%xmm0" : : "g" (f) );
6713 /***********************************************************************
6714 * __libm_sse2_exp (MSVCRT.@)
6716 void __cdecl __libm_sse2_exp(void)
6718 double d;
6719 __asm__ __volatile__( "movq %%xmm0,%0" : "=m" (d) );
6720 d = exp( d );
6721 __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d) );
6724 /***********************************************************************
6725 * __libm_sse2_expf (MSVCRT.@)
6727 void __cdecl __libm_sse2_expf(void)
6729 float f;
6730 __asm__ __volatile__( "movd %%xmm0,%0" : "=g" (f) );
6731 f = expf( f );
6732 __asm__ __volatile__( "movd %0,%%xmm0" : : "g" (f) );
6735 /***********************************************************************
6736 * __libm_sse2_log (MSVCRT.@)
6738 void __cdecl __libm_sse2_log(void)
6740 double d;
6741 __asm__ __volatile__( "movq %%xmm0,%0" : "=m" (d) );
6742 d = log( d );
6743 __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d) );
6746 /***********************************************************************
6747 * __libm_sse2_log10 (MSVCRT.@)
6749 void __cdecl __libm_sse2_log10(void)
6751 double d;
6752 __asm__ __volatile__( "movq %%xmm0,%0" : "=m" (d) );
6753 d = log10( d );
6754 __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d) );
6757 /***********************************************************************
6758 * __libm_sse2_log10f (MSVCRT.@)
6760 void __cdecl __libm_sse2_log10f(void)
6762 float f;
6763 __asm__ __volatile__( "movd %%xmm0,%0" : "=g" (f) );
6764 f = log10f( f );
6765 __asm__ __volatile__( "movd %0,%%xmm0" : : "g" (f) );
6768 /***********************************************************************
6769 * __libm_sse2_logf (MSVCRT.@)
6771 void __cdecl __libm_sse2_logf(void)
6773 float f;
6774 __asm__ __volatile__( "movd %%xmm0,%0" : "=g" (f) );
6775 f = logf( f );
6776 __asm__ __volatile__( "movd %0,%%xmm0" : : "g" (f) );
6779 /***********************************************************************
6780 * __libm_sse2_pow (MSVCRT.@)
6782 void __cdecl __libm_sse2_pow(void)
6784 double d1, d2;
6785 __asm__ __volatile__( "movq %%xmm0,%0; movq %%xmm1,%1 " : "=m" (d1), "=m" (d2) );
6786 d1 = pow( d1, d2 );
6787 __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d1) );
6790 /***********************************************************************
6791 * __libm_sse2_powf (MSVCRT.@)
6793 void __cdecl __libm_sse2_powf(void)
6795 float f1, f2;
6796 __asm__ __volatile__( "movd %%xmm0,%0; movd %%xmm1,%1" : "=g" (f1), "=g" (f2) );
6797 f1 = powf( f1, f2 );
6798 __asm__ __volatile__( "movd %0,%%xmm0" : : "g" (f1) );
6801 /***********************************************************************
6802 * __libm_sse2_sin (MSVCRT.@)
6804 void __cdecl __libm_sse2_sin(void)
6806 double d;
6807 __asm__ __volatile__( "movq %%xmm0,%0" : "=m" (d) );
6808 d = sin( d );
6809 __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d) );
6812 /***********************************************************************
6813 * __libm_sse2_sinf (MSVCRT.@)
6815 void __cdecl __libm_sse2_sinf(void)
6817 float f;
6818 __asm__ __volatile__( "movd %%xmm0,%0" : "=g" (f) );
6819 f = sinf( f );
6820 __asm__ __volatile__( "movd %0,%%xmm0" : : "g" (f) );
6823 /***********************************************************************
6824 * __libm_sse2_tan (MSVCRT.@)
6826 void __cdecl __libm_sse2_tan(void)
6828 double d;
6829 __asm__ __volatile__( "movq %%xmm0,%0" : "=m" (d) );
6830 d = tan( d );
6831 __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d) );
6834 /***********************************************************************
6835 * __libm_sse2_tanf (MSVCRT.@)
6837 void __cdecl __libm_sse2_tanf(void)
6839 float f;
6840 __asm__ __volatile__( "movd %%xmm0,%0" : "=g" (f) );
6841 f = tanf( f );
6842 __asm__ __volatile__( "movd %0,%%xmm0" : : "g" (f) );
6845 /***********************************************************************
6846 * __libm_sse2_sqrt_precise (MSVCR110.@)
6848 void __cdecl __libm_sse2_sqrt_precise(void)
6850 unsigned int cw;
6851 double d;
6853 __asm__ __volatile__( "movq %%xmm0,%0" : "=m" (d) );
6854 __control87_2(0, 0, NULL, &cw);
6855 if (cw & _MCW_RC)
6857 d = sqrt(d);
6858 __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d) );
6859 return;
6862 if (!sqrt_validate(&d, FALSE))
6864 __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d) );
6865 return;
6867 __asm__ __volatile__( "call " __ASM_NAME( "sse2_sqrt" ) );
6869 #endif /* __i386__ */
6871 /*********************************************************************
6872 * _fdclass (MSVCR120.@)
6874 * Copied from musl: src/math/__fpclassifyf.c
6876 short CDECL _fdclass(float x)
6878 union { float f; UINT32 i; } u = { x };
6879 int e = u.i >> 23 & 0xff;
6881 if (!e) return u.i << 1 ? FP_SUBNORMAL : FP_ZERO;
6882 if (e == 0xff) return u.i << 9 ? FP_NAN : FP_INFINITE;
6883 return FP_NORMAL;
6886 /*********************************************************************
6887 * _dclass (MSVCR120.@)
6889 * Copied from musl: src/math/__fpclassify.c
6891 short CDECL _dclass(double x)
6893 union { double f; UINT64 i; } u = { x };
6894 int e = u.i >> 52 & 0x7ff;
6896 if (!e) return u.i << 1 ? FP_SUBNORMAL : FP_ZERO;
6897 if (e == 0x7ff) return (u.i << 12) ? FP_NAN : FP_INFINITE;
6898 return FP_NORMAL;
6901 #if _MSVCR_VER>=120
6903 /*********************************************************************
6904 * cbrt (MSVCR120.@)
6906 * Copied from musl: src/math/cbrt.c
6908 double CDECL cbrt(double x)
6910 static const UINT32 B1 = 715094163, B2 = 696219795;
6911 static const double P0 = 1.87595182427177009643,
6912 P1 = -1.88497979543377169875,
6913 P2 = 1.621429720105354466140,
6914 P3 = -0.758397934778766047437,
6915 P4 = 0.145996192886612446982;
6917 union {double f; UINT64 i;} u = {x};
6918 double r,s,t,w;
6919 UINT32 hx = u.i >> 32 & 0x7fffffff;
6921 if (hx >= 0x7ff00000) /* cbrt(NaN,INF) is itself */
6922 return x + x;
6924 if (hx < 0x00100000) { /* zero or subnormal? */
6925 u.f = x * 0x1p54;
6926 hx = u.i>>32 & 0x7fffffff;
6927 if (hx == 0)
6928 return x;
6929 hx = hx / 3 + B2;
6930 } else
6931 hx = hx / 3 + B1;
6932 u.i &= 1ULL << 63;
6933 u.i |= (UINT64)hx << 32;
6934 t = u.f;
6936 r = (t * t) * (t / x);
6937 t = t * ((P0 + r * (P1 + r * P2)) + ((r * r) * r) * (P3 + r * P4));
6939 u.f = t;
6940 u.i = (u.i + 0x80000000) & 0xffffffffc0000000ULL;
6941 t = u.f;
6943 s = t * t;
6944 r = x / s;
6945 w = t + t;
6946 r = (r - t) / (w + r);
6947 t = t + t * r;
6948 return t;
6951 /*********************************************************************
6952 * cbrtf (MSVCR120.@)
6954 * Copied from musl: src/math/cbrtf.c
6956 float CDECL cbrtf(float x)
6958 static const unsigned B1 = 709958130, B2 = 642849266;
6960 double r,T;
6961 union {float f; UINT32 i;} u = {x};
6962 UINT32 hx = u.i & 0x7fffffff;
6964 if (hx >= 0x7f800000)
6965 return x + x;
6967 if (hx < 0x00800000) { /* zero or subnormal? */
6968 if (hx == 0)
6969 return x;
6970 u.f = x * 0x1p24f;
6971 hx = u.i & 0x7fffffff;
6972 hx = hx / 3 + B2;
6973 } else
6974 hx = hx / 3 + B1;
6975 u.i &= 0x80000000;
6976 u.i |= hx;
6978 T = u.f;
6979 r = T * T * T;
6980 T = T * (x + x + r) / (x + r + r);
6982 r = T * T * T;
6983 T = T * (x + x + r) / (x + r + r);
6984 return T;
6987 /*********************************************************************
6988 * exp2 (MSVCR120.@)
6990 double CDECL exp2(double x)
6992 double ret = unix_funcs->exp2( x );
6993 if (isfinite(x) && !isfinite(ret)) *_errno() = ERANGE;
6994 return ret;
6997 /*********************************************************************
6998 * exp2f (MSVCR120.@)
7000 float CDECL exp2f(float x)
7002 float ret = unix_funcs->exp2f( x );
7003 if (isfinite(x) && !isfinite(ret)) *_errno() = ERANGE;
7004 return ret;
7007 /*********************************************************************
7008 * expm1 (MSVCR120.@)
7010 double CDECL expm1(double x)
7012 return __expm1(x);
7015 /*********************************************************************
7016 * expm1f (MSVCR120.@)
7018 float CDECL expm1f(float x)
7020 return __expm1f(x);
7023 /*********************************************************************
7024 * log1p (MSVCR120.@)
7026 * Copied from musl: src/math/log1p.c
7028 double CDECL log1p(double x)
7030 static const double ln2_hi = 6.93147180369123816490e-01,
7031 ln2_lo = 1.90821492927058770002e-10,
7032 Lg1 = 6.666666666666735130e-01,
7033 Lg2 = 3.999999999940941908e-01,
7034 Lg3 = 2.857142874366239149e-01,
7035 Lg4 = 2.222219843214978396e-01,
7036 Lg5 = 1.818357216161805012e-01,
7037 Lg6 = 1.531383769920937332e-01,
7038 Lg7 = 1.479819860511658591e-01;
7040 union {double f; UINT64 i;} u = {x};
7041 double hfsq, f, c, s, z, R, w, t1, t2, dk;
7042 UINT32 hx, hu;
7043 int k;
7045 hx = u.i >> 32;
7046 k = 1;
7047 if (hx < 0x3fda827a || hx >> 31) { /* 1+x < sqrt(2)+ */
7048 if (hx >= 0xbff00000) { /* x <= -1.0 */
7049 if (x == -1) {
7050 *_errno() = ERANGE;
7051 return x / 0.0; /* og1p(-1) = -inf */
7053 *_errno() = EDOM;
7054 return (x-x) / 0.0; /* log1p(x<-1) = NaN */
7056 if (hx << 1 < 0x3ca00000 << 1) { /* |x| < 2**-53 */
7057 fp_barrier(x + 0x1p120f);
7058 /* underflow if subnormal */
7059 if ((hx & 0x7ff00000) == 0)
7060 fp_barrierf(x);
7061 return x;
7063 if (hx <= 0xbfd2bec4) { /* sqrt(2)/2- <= 1+x < sqrt(2)+ */
7064 k = 0;
7065 c = 0;
7066 f = x;
7068 } else if (hx >= 0x7ff00000)
7069 return x;
7070 if (k) {
7071 u.f = 1 + x;
7072 hu = u.i >> 32;
7073 hu += 0x3ff00000 - 0x3fe6a09e;
7074 k = (int)(hu >> 20) - 0x3ff;
7075 /* correction term ~ log(1+x)-log(u), avoid underflow in c/u */
7076 if (k < 54) {
7077 c = k >= 2 ? 1 - (u.f - x) : x - (u.f - 1);
7078 c /= u.f;
7079 } else
7080 c = 0;
7081 /* reduce u into [sqrt(2)/2, sqrt(2)] */
7082 hu = (hu & 0x000fffff) + 0x3fe6a09e;
7083 u.i = (UINT64)hu << 32 | (u.i & 0xffffffff);
7084 f = u.f - 1;
7086 hfsq = 0.5 * f * f;
7087 s = f / (2.0 + f);
7088 z = s * s;
7089 w = z * z;
7090 t1 = w * (Lg2 + w * (Lg4 + w * Lg6));
7091 t2 = z * (Lg1 + w * (Lg3 + w * (Lg5 + w * Lg7)));
7092 R = t2 + t1;
7093 dk = k;
7094 return s * (hfsq + R) + (dk * ln2_lo + c) - hfsq + f + dk * ln2_hi;
7097 /*********************************************************************
7098 * log1pf (MSVCR120.@)
7100 * Copied from musl: src/math/log1pf.c
7102 float CDECL log1pf(float x)
7104 static const float ln2_hi = 6.9313812256e-01,
7105 ln2_lo = 9.0580006145e-06,
7106 Lg1 = 0xaaaaaa.0p-24,
7107 Lg2 = 0xccce13.0p-25,
7108 Lg3 = 0x91e9ee.0p-25,
7109 Lg4 = 0xf89e26.0p-26;
7111 union {float f; UINT32 i;} u = {x};
7112 float hfsq, f, c, s, z, R, w, t1, t2, dk;
7113 UINT32 ix, iu;
7114 int k;
7116 ix = u.i;
7117 k = 1;
7118 if (ix < 0x3ed413d0 || ix >> 31) { /* 1+x < sqrt(2)+ */
7119 if (ix >= 0xbf800000) { /* x <= -1.0 */
7120 if (x == -1) {
7121 *_errno() = ERANGE;
7122 return x / 0.0f; /* log1p(-1)=+inf */
7124 *_errno() = EDOM;
7125 return (x - x) / 0.0f; /* log1p(x<-1)=NaN */
7127 if (ix<<1 < 0x33800000<<1) { /* |x| < 2**-24 */
7128 /* underflow if subnormal */
7129 if ((ix & 0x7f800000) == 0)
7130 fp_barrierf(x * x);
7131 return x;
7133 if (ix <= 0xbe95f619) { /* sqrt(2)/2- <= 1+x < sqrt(2)+ */
7134 k = 0;
7135 c = 0;
7136 f = x;
7138 } else if (ix >= 0x7f800000)
7139 return x;
7140 if (k) {
7141 u.f = 1 + x;
7142 iu = u.i;
7143 iu += 0x3f800000 - 0x3f3504f3;
7144 k = (int)(iu >> 23) - 0x7f;
7145 /* correction term ~ log(1+x)-log(u), avoid underflow in c/u */
7146 if (k < 25) {
7147 c = k >= 2 ? 1 - (u.f - x) : x - (u.f - 1);
7148 c /= u.f;
7149 } else
7150 c = 0;
7151 /* reduce u into [sqrt(2)/2, sqrt(2)] */
7152 iu = (iu & 0x007fffff) + 0x3f3504f3;
7153 u.i = iu;
7154 f = u.f - 1;
7156 s = f / (2.0f + f);
7157 z = s * s;
7158 w = z * z;
7159 t1= w * (Lg2 + w * Lg4);
7160 t2= z * (Lg1 + w * Lg3);
7161 R = t2 + t1;
7162 hfsq = 0.5f * f * f;
7163 dk = k;
7164 return s * (hfsq + R) + (dk * ln2_lo + c) - hfsq + f + dk * ln2_hi;
7167 /*********************************************************************
7168 * log2 (MSVCR120.@)
7170 * Copied from musl: src/math/log2.c
7172 double CDECL log2(double x)
7174 static const double invln2hi = 0x1.7154765200000p+0,
7175 invln2lo = 0x1.705fc2eefa200p-33;
7176 static const double A[] = {
7177 -0x1.71547652b8339p-1,
7178 0x1.ec709dc3a04bep-2,
7179 -0x1.7154764702ffbp-2,
7180 0x1.2776c50034c48p-2,
7181 -0x1.ec7b328ea92bcp-3,
7182 0x1.a6225e117f92ep-3
7184 static const double B[] = {
7185 -0x1.71547652b82fep-1,
7186 0x1.ec709dc3a03f7p-2,
7187 -0x1.71547652b7c3fp-2,
7188 0x1.2776c50f05be4p-2,
7189 -0x1.ec709dd768fe5p-3,
7190 0x1.a61761ec4e736p-3,
7191 -0x1.7153fbc64a79bp-3,
7192 0x1.484d154f01b4ap-3,
7193 -0x1.289e4a72c383cp-3,
7194 0x1.0b32f285aee66p-3
7196 static const struct {
7197 double invc, logc;
7198 } T[] = {
7199 {0x1.724286bb1acf8p+0, -0x1.1095feecdb000p-1},
7200 {0x1.6e1f766d2cca1p+0, -0x1.08494bd76d000p-1},
7201 {0x1.6a13d0e30d48ap+0, -0x1.00143aee8f800p-1},
7202 {0x1.661ec32d06c85p+0, -0x1.efec5360b4000p-2},
7203 {0x1.623fa951198f8p+0, -0x1.dfdd91ab7e000p-2},
7204 {0x1.5e75ba4cf026cp+0, -0x1.cffae0cc79000p-2},
7205 {0x1.5ac055a214fb8p+0, -0x1.c043811fda000p-2},
7206 {0x1.571ed0f166e1ep+0, -0x1.b0b67323ae000p-2},
7207 {0x1.53909590bf835p+0, -0x1.a152f5a2db000p-2},
7208 {0x1.5014fed61adddp+0, -0x1.9217f5af86000p-2},
7209 {0x1.4cab88e487bd0p+0, -0x1.8304db0719000p-2},
7210 {0x1.49539b4334feep+0, -0x1.74189f9a9e000p-2},
7211 {0x1.460cbdfafd569p+0, -0x1.6552bb5199000p-2},
7212 {0x1.42d664ee4b953p+0, -0x1.56b23a29b1000p-2},
7213 {0x1.3fb01111dd8a6p+0, -0x1.483650f5fa000p-2},
7214 {0x1.3c995b70c5836p+0, -0x1.39de937f6a000p-2},
7215 {0x1.3991c4ab6fd4ap+0, -0x1.2baa1538d6000p-2},
7216 {0x1.3698e0ce099b5p+0, -0x1.1d98340ca4000p-2},
7217 {0x1.33ae48213e7b2p+0, -0x1.0fa853a40e000p-2},
7218 {0x1.30d191985bdb1p+0, -0x1.01d9c32e73000p-2},
7219 {0x1.2e025cab271d7p+0, -0x1.e857da2fa6000p-3},
7220 {0x1.2b404cf13cd82p+0, -0x1.cd3c8633d8000p-3},
7221 {0x1.288b02c7ccb50p+0, -0x1.b26034c14a000p-3},
7222 {0x1.25e2263944de5p+0, -0x1.97c1c2f4fe000p-3},
7223 {0x1.234563d8615b1p+0, -0x1.7d6023f800000p-3},
7224 {0x1.20b46e33eaf38p+0, -0x1.633a71a05e000p-3},
7225 {0x1.1e2eefdcda3ddp+0, -0x1.494f5e9570000p-3},
7226 {0x1.1bb4a580b3930p+0, -0x1.2f9e424e0a000p-3},
7227 {0x1.19453847f2200p+0, -0x1.162595afdc000p-3},
7228 {0x1.16e06c0d5d73cp+0, -0x1.f9c9a75bd8000p-4},
7229 {0x1.1485f47b7e4c2p+0, -0x1.c7b575bf9c000p-4},
7230 {0x1.12358ad0085d1p+0, -0x1.960c60ff48000p-4},
7231 {0x1.0fef00f532227p+0, -0x1.64ce247b60000p-4},
7232 {0x1.0db2077d03a8fp+0, -0x1.33f78b2014000p-4},
7233 {0x1.0b7e6d65980d9p+0, -0x1.0387d1a42c000p-4},
7234 {0x1.0953efe7b408dp+0, -0x1.a6f9208b50000p-5},
7235 {0x1.07325cac53b83p+0, -0x1.47a954f770000p-5},
7236 {0x1.05197e40d1b5cp+0, -0x1.d23a8c50c0000p-6},
7237 {0x1.03091c1208ea2p+0, -0x1.16a2629780000p-6},
7238 {0x1.0101025b37e21p+0, -0x1.720f8d8e80000p-8},
7239 {0x1.fc07ef9caa76bp-1, 0x1.6fe53b1500000p-7},
7240 {0x1.f4465d3f6f184p-1, 0x1.11ccce10f8000p-5},
7241 {0x1.ecc079f84107fp-1, 0x1.c4dfc8c8b8000p-5},
7242 {0x1.e573a99975ae8p-1, 0x1.3aa321e574000p-4},
7243 {0x1.de5d6f0bd3de6p-1, 0x1.918a0d08b8000p-4},
7244 {0x1.d77b681ff38b3p-1, 0x1.e72e9da044000p-4},
7245 {0x1.d0cb5724de943p-1, 0x1.1dcd2507f6000p-3},
7246 {0x1.ca4b2dc0e7563p-1, 0x1.476ab03dea000p-3},
7247 {0x1.c3f8ee8d6cb51p-1, 0x1.7074377e22000p-3},
7248 {0x1.bdd2b4f020c4cp-1, 0x1.98ede8ba94000p-3},
7249 {0x1.b7d6c006015cap-1, 0x1.c0db86ad2e000p-3},
7250 {0x1.b20366e2e338fp-1, 0x1.e840aafcee000p-3},
7251 {0x1.ac57026295039p-1, 0x1.0790ab4678000p-2},
7252 {0x1.a6d01bc2731ddp-1, 0x1.1ac056801c000p-2},
7253 {0x1.a16d3bc3ff18bp-1, 0x1.2db11d4fee000p-2},
7254 {0x1.9c2d14967feadp-1, 0x1.406464ec58000p-2},
7255 {0x1.970e4f47c9902p-1, 0x1.52dbe093af000p-2},
7256 {0x1.920fb3982bcf2p-1, 0x1.651902050d000p-2},
7257 {0x1.8d30187f759f1p-1, 0x1.771d2cdeaf000p-2},
7258 {0x1.886e5ebb9f66dp-1, 0x1.88e9c857d9000p-2},
7259 {0x1.83c97b658b994p-1, 0x1.9a80155e16000p-2},
7260 {0x1.7f405ffc61022p-1, 0x1.abe186ed3d000p-2},
7261 {0x1.7ad22181415cap-1, 0x1.bd0f2aea0e000p-2},
7262 {0x1.767dcf99eff8cp-1, 0x1.ce0a43dbf4000p-2}
7264 static const struct {
7265 double chi, clo;
7266 } T2[] = {
7267 {0x1.6200012b90a8ep-1, 0x1.904ab0644b605p-55},
7268 {0x1.66000045734a6p-1, 0x1.1ff9bea62f7a9p-57},
7269 {0x1.69fffc325f2c5p-1, 0x1.27ecfcb3c90bap-55},
7270 {0x1.6e00038b95a04p-1, 0x1.8ff8856739326p-55},
7271 {0x1.71fffe09994e3p-1, 0x1.afd40275f82b1p-55},
7272 {0x1.7600015590e1p-1, -0x1.2fd75b4238341p-56},
7273 {0x1.7a00012655bd5p-1, 0x1.808e67c242b76p-56},
7274 {0x1.7e0003259e9a6p-1, -0x1.208e426f622b7p-57},
7275 {0x1.81fffedb4b2d2p-1, -0x1.402461ea5c92fp-55},
7276 {0x1.860002dfafcc3p-1, 0x1.df7f4a2f29a1fp-57},
7277 {0x1.89ffff78c6b5p-1, -0x1.e0453094995fdp-55},
7278 {0x1.8e00039671566p-1, -0x1.a04f3bec77b45p-55},
7279 {0x1.91fffe2bf1745p-1, -0x1.7fa34400e203cp-56},
7280 {0x1.95fffcc5c9fd1p-1, -0x1.6ff8005a0695dp-56},
7281 {0x1.9a0003bba4767p-1, 0x1.0f8c4c4ec7e03p-56},
7282 {0x1.9dfffe7b92da5p-1, 0x1.e7fd9478c4602p-55},
7283 {0x1.a1fffd72efdafp-1, -0x1.a0c554dcdae7ep-57},
7284 {0x1.a5fffde04ff95p-1, 0x1.67da98ce9b26bp-55},
7285 {0x1.a9fffca5e8d2bp-1, -0x1.284c9b54c13dep-55},
7286 {0x1.adfffddad03eap-1, 0x1.812c8ea602e3cp-58},
7287 {0x1.b1ffff10d3d4dp-1, -0x1.efaddad27789cp-55},
7288 {0x1.b5fffce21165ap-1, 0x1.3cb1719c61237p-58},
7289 {0x1.b9fffd950e674p-1, 0x1.3f7d94194cep-56},
7290 {0x1.be000139ca8afp-1, 0x1.50ac4215d9bcp-56},
7291 {0x1.c20005b46df99p-1, 0x1.beea653e9c1c9p-57},
7292 {0x1.c600040b9f7aep-1, -0x1.c079f274a70d6p-56},
7293 {0x1.ca0006255fd8ap-1, -0x1.a0b4076e84c1fp-56},
7294 {0x1.cdfffd94c095dp-1, 0x1.8f933f99ab5d7p-55},
7295 {0x1.d1ffff975d6cfp-1, -0x1.82c08665fe1bep-58},
7296 {0x1.d5fffa2561c93p-1, -0x1.b04289bd295f3p-56},
7297 {0x1.d9fff9d228b0cp-1, 0x1.70251340fa236p-55},
7298 {0x1.de00065bc7e16p-1, -0x1.5011e16a4d80cp-56},
7299 {0x1.e200002f64791p-1, 0x1.9802f09ef62ep-55},
7300 {0x1.e600057d7a6d8p-1, -0x1.e0b75580cf7fap-56},
7301 {0x1.ea00027edc00cp-1, -0x1.c848309459811p-55},
7302 {0x1.ee0006cf5cb7cp-1, -0x1.f8027951576f4p-55},
7303 {0x1.f2000782b7dccp-1, -0x1.f81d97274538fp-55},
7304 {0x1.f6000260c450ap-1, -0x1.071002727ffdcp-59},
7305 {0x1.f9fffe88cd533p-1, -0x1.81bdce1fda8bp-58},
7306 {0x1.fdfffd50f8689p-1, 0x1.7f91acb918e6ep-55},
7307 {0x1.0200004292367p+0, 0x1.b7ff365324681p-54},
7308 {0x1.05fffe3e3d668p+0, 0x1.6fa08ddae957bp-55},
7309 {0x1.0a0000a85a757p+0, -0x1.7e2de80d3fb91p-58},
7310 {0x1.0e0001a5f3fccp+0, -0x1.1823305c5f014p-54},
7311 {0x1.11ffff8afbaf5p+0, -0x1.bfabb6680bac2p-55},
7312 {0x1.15fffe54d91adp+0, -0x1.d7f121737e7efp-54},
7313 {0x1.1a00011ac36e1p+0, 0x1.c000a0516f5ffp-54},
7314 {0x1.1e00019c84248p+0, -0x1.082fbe4da5dap-54},
7315 {0x1.220000ffe5e6ep+0, -0x1.8fdd04c9cfb43p-55},
7316 {0x1.26000269fd891p+0, 0x1.cfe2a7994d182p-55},
7317 {0x1.2a00029a6e6dap+0, -0x1.00273715e8bc5p-56},
7318 {0x1.2dfffe0293e39p+0, 0x1.b7c39dab2a6f9p-54},
7319 {0x1.31ffff7dcf082p+0, 0x1.df1336edc5254p-56},
7320 {0x1.35ffff05a8b6p+0, -0x1.e03564ccd31ebp-54},
7321 {0x1.3a0002e0eaeccp+0, 0x1.5f0e74bd3a477p-56},
7322 {0x1.3e000043bb236p+0, 0x1.c7dcb149d8833p-54},
7323 {0x1.4200002d187ffp+0, 0x1.e08afcf2d3d28p-56},
7324 {0x1.460000d387cb1p+0, 0x1.20837856599a6p-55},
7325 {0x1.4a00004569f89p+0, -0x1.9fa5c904fbcd2p-55},
7326 {0x1.4e000043543f3p+0, -0x1.81125ed175329p-56},
7327 {0x1.51fffcc027f0fp+0, 0x1.883d8847754dcp-54},
7328 {0x1.55ffffd87b36fp+0, -0x1.709e731d02807p-55},
7329 {0x1.59ffff21df7bap+0, 0x1.7f79f68727b02p-55},
7330 {0x1.5dfffebfc3481p+0, -0x1.180902e30e93ep-54}
7333 double z, r, r2, r4, y, invc, logc, kd, hi, lo, t1, t2, t3, p, rhi, rlo;
7334 UINT64 ix, iz, tmp;
7335 UINT32 top;
7336 int k, i;
7338 ix = *(UINT64*)&x;
7339 top = ix >> 48;
7340 if (ix - 0x3feea4af00000000ULL < 0x210aa00000000ULL) {
7341 /* Handle close to 1.0 inputs separately. */
7342 /* Fix sign of zero with downward rounding when x==1. */
7343 if (ix == 0x3ff0000000000000ULL)
7344 return 0;
7345 r = x - 1.0;
7346 *(UINT64*)&rhi = *(UINT64*)&r & -1ULL << 32;
7347 rlo = r - rhi;
7348 hi = rhi * invln2hi;
7349 lo = rlo * invln2hi + r * invln2lo;
7350 r2 = r * r; /* rounding error: 0x1p-62. */
7351 r4 = r2 * r2;
7352 /* Worst-case error is less than 0.54 ULP (0.55 ULP without fma). */
7353 p = r2 * (B[0] + r * B[1]);
7354 y = hi + p;
7355 lo += hi - y + p;
7356 lo += r4 * (B[2] + r * B[3] + r2 * (B[4] + r * B[5]) +
7357 r4 * (B[6] + r * B[7] + r2 * (B[8] + r * B[9])));
7358 y += lo;
7359 return y;
7361 if (top - 0x0010 >= 0x7ff0 - 0x0010) {
7362 /* x < 0x1p-1022 or inf or nan. */
7363 if (ix * 2 == 0) {
7364 *_errno() = ERANGE;
7365 return -1.0 / x;
7367 if (ix == 0x7ff0000000000000ULL) /* log(inf) == inf. */
7368 return x;
7369 if ((top & 0x7ff0) == 0x7ff0 && (ix & 0xfffffffffffffULL))
7370 return x;
7371 if (top & 0x8000) {
7372 *_errno() = EDOM;
7373 return (x - x) / (x - x);
7375 /* x is subnormal, normalize it. */
7376 x *= 0x1p52;
7377 ix = *(UINT64*)&x;
7378 ix -= 52ULL << 52;
7381 /* x = 2^k z; where z is in range [OFF,2*OFF) and exact.
7382 The range is split into N subintervals.
7383 The ith subinterval contains z and c is near its center. */
7384 tmp = ix - 0x3fe6000000000000ULL;
7385 i = (tmp >> (52 - 6)) % (1 << 6);
7386 k = (INT64)tmp >> 52; /* arithmetic shift */
7387 iz = ix - (tmp & 0xfffULL << 52);
7388 invc = T[i].invc;
7389 logc = T[i].logc;
7390 z = *(double*)&iz;
7391 kd = k;
7393 /* log2(x) = log2(z/c) + log2(c) + k. */
7394 /* r ~= z/c - 1, |r| < 1/(2*N). */
7395 /* rounding error: 0x1p-55/N + 0x1p-65. */
7396 r = (z - T2[i].chi - T2[i].clo) * invc;
7397 *(UINT64*)&rhi = *(UINT64*)&r & -1ULL << 32;
7398 rlo = r - rhi;
7399 t1 = rhi * invln2hi;
7400 t2 = rlo * invln2hi + r * invln2lo;
7402 /* hi + lo = r/ln2 + log2(c) + k. */
7403 t3 = kd + logc;
7404 hi = t3 + t1;
7405 lo = t3 - hi + t1 + t2;
7407 /* log2(r+1) = r/ln2 + r^2*poly(r). */
7408 /* Evaluation is optimized assuming superscalar pipelined execution. */
7409 r2 = r * r; /* rounding error: 0x1p-54/N^2. */
7410 r4 = r2 * r2;
7411 /* Worst-case error if |y| > 0x1p-4: 0.547 ULP (0.550 ULP without fma).
7412 ~ 0.5 + 2/N/ln2 + abs-poly-error*0x1p56 ULP (+ 0.003 ULP without fma). */
7413 p = A[0] + r * A[1] + r2 * (A[2] + r * A[3]) + r4 * (A[4] + r * A[5]);
7414 y = lo + r2 * p + hi;
7415 return y;
7418 /*********************************************************************
7419 * log2f (MSVCR120.@)
7421 * Copied from musl: src/math/log2f.c
7423 float CDECL log2f(float x)
7425 static const double A[] = {
7426 -0x1.712b6f70a7e4dp-2,
7427 0x1.ecabf496832ep-2,
7428 -0x1.715479ffae3dep-1,
7429 0x1.715475f35c8b8p0
7431 static const struct {
7432 double invc, logc;
7433 } T[] = {
7434 { 0x1.661ec79f8f3bep+0, -0x1.efec65b963019p-2 },
7435 { 0x1.571ed4aaf883dp+0, -0x1.b0b6832d4fca4p-2 },
7436 { 0x1.49539f0f010bp+0, -0x1.7418b0a1fb77bp-2 },
7437 { 0x1.3c995b0b80385p+0, -0x1.39de91a6dcf7bp-2 },
7438 { 0x1.30d190c8864a5p+0, -0x1.01d9bf3f2b631p-2 },
7439 { 0x1.25e227b0b8eap+0, -0x1.97c1d1b3b7afp-3 },
7440 { 0x1.1bb4a4a1a343fp+0, -0x1.2f9e393af3c9fp-3 },
7441 { 0x1.12358f08ae5bap+0, -0x1.960cbbf788d5cp-4 },
7442 { 0x1.0953f419900a7p+0, -0x1.a6f9db6475fcep-5 },
7443 { 0x1p+0, 0x0p+0 },
7444 { 0x1.e608cfd9a47acp-1, 0x1.338ca9f24f53dp-4 },
7445 { 0x1.ca4b31f026aap-1, 0x1.476a9543891bap-3 },
7446 { 0x1.b2036576afce6p-1, 0x1.e840b4ac4e4d2p-3 },
7447 { 0x1.9c2d163a1aa2dp-1, 0x1.40645f0c6651cp-2 },
7448 { 0x1.886e6037841edp-1, 0x1.88e9c2c1b9ff8p-2 },
7449 { 0x1.767dcf5534862p-1, 0x1.ce0a44eb17bccp-2 }
7452 double z, r, r2, p, y, y0, invc, logc;
7453 UINT32 ix, iz, top, tmp;
7454 int k, i;
7456 ix = *(UINT32*)&x;
7457 /* Fix sign of zero with downward rounding when x==1. */
7458 if (ix == 0x3f800000)
7459 return 0;
7460 if (ix - 0x00800000 >= 0x7f800000 - 0x00800000) {
7461 /* x < 0x1p-126 or inf or nan. */
7462 if (ix * 2 == 0) {
7463 *_errno() = ERANGE;
7464 return -1.0f / x;
7466 if (ix == 0x7f800000) /* log2(inf) == inf. */
7467 return x;
7468 if (ix * 2 > 0xff000000)
7469 return x;
7470 if (ix & 0x80000000) {
7471 *_errno() = EDOM;
7472 return (x - x) / (x - x);
7474 /* x is subnormal, normalize it. */
7475 x *= 0x1p23f;
7476 ix = *(UINT32*)&x;
7477 ix -= 23 << 23;
7480 /* x = 2^k z; where z is in range [OFF,2*OFF] and exact.
7481 The range is split into N subintervals.
7482 The ith subinterval contains z and c is near its center. */
7483 tmp = ix - 0x3f330000;
7484 i = (tmp >> (23 - 4)) % (1 << 4);
7485 top = tmp & 0xff800000;
7486 iz = ix - top;
7487 k = (INT32)tmp >> 23; /* arithmetic shift */
7488 invc = T[i].invc;
7489 logc = T[i].logc;
7490 z = *(float*)&iz;
7492 /* log2(x) = log1p(z/c-1)/ln2 + log2(c) + k */
7493 r = z * invc - 1;
7494 y0 = logc + (double)k;
7496 /* Pipelined polynomial evaluation to approximate log1p(r)/ln2. */
7497 r2 = r * r;
7498 y = A[1] * r + A[2];
7499 y = A[0] * r2 + y;
7500 p = A[3] * r + y0;
7501 y = y * r2 + p;
7502 return y;
7505 /*********************************************************************
7506 * rint (MSVCR120.@)
7508 double CDECL rint(double x)
7510 return __rint(x);
7513 /*********************************************************************
7514 * rintf (MSVCR120.@)
7516 * Copied from musl: src/math/rintf.c
7518 float CDECL rintf(float x)
7520 static const float toint = 1 / FLT_EPSILON;
7522 unsigned int ix = *(unsigned int*)&x;
7523 int e = ix >> 23 & 0xff;
7524 int s = ix >> 31;
7525 float y;
7527 if (e >= 0x7f + 23)
7528 return x;
7529 if (s)
7530 y = fp_barrierf(x - toint) + toint;
7531 else
7532 y = fp_barrierf(x + toint) - toint;
7533 if (y == 0)
7534 return s ? -0.0f : 0.0f;
7535 return y;
7538 /*********************************************************************
7539 * lrint (MSVCR120.@)
7541 __msvcrt_long CDECL lrint(double x)
7543 double d;
7545 d = rint(x);
7546 if ((d < 0 && d != (double)(__msvcrt_long)d)
7547 || (d >= 0 && d != (double)(__msvcrt_ulong)d)) {
7548 *_errno() = EDOM;
7549 return 0;
7551 return d;
7554 /*********************************************************************
7555 * lrintf (MSVCR120.@)
7557 __msvcrt_long CDECL lrintf(float x)
7559 float f;
7561 f = rintf(x);
7562 if ((f < 0 && f != (float)(__msvcrt_long)f)
7563 || (f >= 0 && f != (float)(__msvcrt_ulong)f)) {
7564 *_errno() = EDOM;
7565 return 0;
7567 return f;
7570 /*********************************************************************
7571 * llrint (MSVCR120.@)
7573 __int64 CDECL llrint(double x)
7575 double d;
7577 d = rint(x);
7578 if ((d < 0 && d != (double)(__int64)d)
7579 || (d >= 0 && d != (double)(unsigned __int64)d)) {
7580 *_errno() = EDOM;
7581 return 0;
7583 return d;
7586 /*********************************************************************
7587 * llrintf (MSVCR120.@)
7589 __int64 CDECL llrintf(float x)
7591 float f;
7593 f = rintf(x);
7594 if ((f < 0 && f != (float)(__int64)f)
7595 || (f >= 0 && f != (float)(unsigned __int64)f)) {
7596 *_errno() = EDOM;
7597 return 0;
7599 return f;
7602 /*********************************************************************
7603 * round (MSVCR120.@)
7605 * Based on musl implementation: src/math/round.c
7607 double CDECL round(double x)
7609 ULONGLONG llx = *(ULONGLONG*)&x, tmp;
7610 int e = (llx >> 52 & 0x7ff) - 0x3ff;
7612 if (e >= 52)
7613 return x;
7614 if (e < -1)
7615 return 0 * x;
7616 else if (e == -1)
7617 return signbit(x) ? -1 : 1;
7619 tmp = 0x000fffffffffffffULL >> e;
7620 if (!(llx & tmp))
7621 return x;
7622 llx += 0x0008000000000000ULL >> e;
7623 llx &= ~tmp;
7624 return *(double*)&llx;
7627 /*********************************************************************
7628 * roundf (MSVCR120.@)
7630 * Copied from musl: src/math/roundf.c
7632 float CDECL roundf(float x)
7634 static const float toint = 1 / FLT_EPSILON;
7636 unsigned int ix = *(unsigned int*)&x;
7637 int e = ix >> 23 & 0xff;
7638 float y;
7640 if (e >= 0x7f + 23)
7641 return x;
7642 if (ix >> 31)
7643 x = -x;
7644 if (e < 0x7f - 1)
7645 return 0 * *(float*)&ix;
7646 y = fp_barrierf(x + toint) - toint - x;
7647 if (y > 0.5f)
7648 y = y + x - 1;
7649 else if (y <= -0.5f)
7650 y = y + x + 1;
7651 else
7652 y = y + x;
7653 if (ix >> 31)
7654 y = -y;
7655 return y;
7658 /*********************************************************************
7659 * lround (MSVCR120.@)
7661 * Copied from musl: src/math/lround.c
7663 __msvcrt_long CDECL lround(double x)
7665 double d = round(x);
7666 if (d != (double)(__msvcrt_long)d) {
7667 *_errno() = EDOM;
7668 return 0;
7670 return d;
7673 /*********************************************************************
7674 * lroundf (MSVCR120.@)
7676 * Copied from musl: src/math/lroundf.c
7678 __msvcrt_long CDECL lroundf(float x)
7680 float f = roundf(x);
7681 if (f != (float)(__msvcrt_long)f) {
7682 *_errno() = EDOM;
7683 return 0;
7685 return f;
7688 /*********************************************************************
7689 * llround (MSVCR120.@)
7691 * Copied from musl: src/math/llround.c
7693 __int64 CDECL llround(double x)
7695 double d = round(x);
7696 if (d != (double)(__int64)d) {
7697 *_errno() = EDOM;
7698 return 0;
7700 return d;
7703 /*********************************************************************
7704 * llroundf (MSVCR120.@)
7706 * Copied from musl: src/math/llroundf.c
7708 __int64 CDECL llroundf(float x)
7710 float f = roundf(x);
7711 if (f != (float)(__int64)f) {
7712 *_errno() = EDOM;
7713 return 0;
7715 return f;
7718 /*********************************************************************
7719 * trunc (MSVCR120.@)
7721 * Copied from musl: src/math/trunc.c
7723 double CDECL trunc(double x)
7725 union {double f; UINT64 i;} u = {x};
7726 int e = (u.i >> 52 & 0x7ff) - 0x3ff + 12;
7727 UINT64 m;
7729 if (e >= 52 + 12)
7730 return x;
7731 if (e < 12)
7732 e = 1;
7733 m = -1ULL >> e;
7734 if ((u.i & m) == 0)
7735 return x;
7736 u.i &= ~m;
7737 return u.f;
7740 /*********************************************************************
7741 * truncf (MSVCR120.@)
7743 * Copied from musl: src/math/truncf.c
7745 float CDECL truncf(float x)
7747 union {float f; UINT32 i;} u = {x};
7748 int e = (u.i >> 23 & 0xff) - 0x7f + 9;
7749 UINT32 m;
7751 if (e >= 23 + 9)
7752 return x;
7753 if (e < 9)
7754 e = 1;
7755 m = -1U >> e;
7756 if ((u.i & m) == 0)
7757 return x;
7758 u.i &= ~m;
7759 return u.f;
7762 /*********************************************************************
7763 * _dtest (MSVCR120.@)
7765 short CDECL _dtest(double *x)
7767 return _dclass(*x);
7770 /*********************************************************************
7771 * _fdtest (MSVCR120.@)
7773 short CDECL _fdtest(float *x)
7775 return _fdclass(*x);
7778 static double erfc1(double x)
7780 static const double erx = 8.45062911510467529297e-01,
7781 pa0 = -2.36211856075265944077e-03,
7782 pa1 = 4.14856118683748331666e-01,
7783 pa2 = -3.72207876035701323847e-01,
7784 pa3 = 3.18346619901161753674e-01,
7785 pa4 = -1.10894694282396677476e-01,
7786 pa5 = 3.54783043256182359371e-02,
7787 pa6 = -2.16637559486879084300e-03,
7788 qa1 = 1.06420880400844228286e-01,
7789 qa2 = 5.40397917702171048937e-01,
7790 qa3 = 7.18286544141962662868e-02,
7791 qa4 = 1.26171219808761642112e-01,
7792 qa5 = 1.36370839120290507362e-02,
7793 qa6 = 1.19844998467991074170e-02;
7795 double s, P, Q;
7797 s = fabs(x) - 1;
7798 P = pa0 + s * (pa1 + s * (pa2 + s * (pa3 + s * (pa4 + s * (pa5 + s * pa6)))));
7799 Q = 1 + s * (qa1 + s * (qa2 + s * (qa3 + s * (qa4 + s * (qa5 + s * qa6)))));
7800 return 1 - erx - P / Q;
7803 static double erfc2(UINT32 ix, double x)
7805 static const double ra0 = -9.86494403484714822705e-03,
7806 ra1 = -6.93858572707181764372e-01,
7807 ra2 = -1.05586262253232909814e+01,
7808 ra3 = -6.23753324503260060396e+01,
7809 ra4 = -1.62396669462573470355e+02,
7810 ra5 = -1.84605092906711035994e+02,
7811 ra6 = -8.12874355063065934246e+01,
7812 ra7 = -9.81432934416914548592e+00,
7813 sa1 = 1.96512716674392571292e+01,
7814 sa2 = 1.37657754143519042600e+02,
7815 sa3 = 4.34565877475229228821e+02,
7816 sa4 = 6.45387271733267880336e+02,
7817 sa5 = 4.29008140027567833386e+02,
7818 sa6 = 1.08635005541779435134e+02,
7819 sa7 = 6.57024977031928170135e+00,
7820 sa8 = -6.04244152148580987438e-02,
7821 rb0 = -9.86494292470009928597e-03,
7822 rb1 = -7.99283237680523006574e-01,
7823 rb2 = -1.77579549177547519889e+01,
7824 rb3 = -1.60636384855821916062e+02,
7825 rb4 = -6.37566443368389627722e+02,
7826 rb5 = -1.02509513161107724954e+03,
7827 rb6 = -4.83519191608651397019e+02,
7828 sb1 = 3.03380607434824582924e+01,
7829 sb2 = 3.25792512996573918826e+02,
7830 sb3 = 1.53672958608443695994e+03,
7831 sb4 = 3.19985821950859553908e+03,
7832 sb5 = 2.55305040643316442583e+03,
7833 sb6 = 4.74528541206955367215e+02,
7834 sb7 = -2.24409524465858183362e+01;
7836 double s, R, S, z;
7837 UINT64 iz;
7839 if (ix < 0x3ff40000) /* |x| < 1.25 */
7840 return erfc1(x);
7842 x = fabs(x);
7843 s = 1 / (x * x);
7844 if (ix < 0x4006db6d) { /* |x| < 1/.35 ~ 2.85714 */
7845 R = ra0 + s * (ra1 + s * (ra2 + s * (ra3 + s * (ra4 + s *
7846 (ra5 + s * (ra6 + s * ra7))))));
7847 S = 1.0 + s * (sa1 + s * (sa2 + s * (sa3 + s * (sa4 + s *
7848 (sa5 + s * (sa6 + s * (sa7 + s * sa8)))))));
7849 } else { /* |x| > 1/.35 */
7850 R = rb0 + s * (rb1 + s * (rb2 + s * (rb3 + s * (rb4 + s *
7851 (rb5 + s * rb6)))));
7852 S = 1.0 + s * (sb1 + s * (sb2 + s * (sb3 + s * (sb4 + s *
7853 (sb5 + s * (sb6 + s * sb7))))));
7855 z = x;
7856 iz = *(ULONGLONG*)&z;
7857 iz &= 0xffffffff00000000ULL;
7858 z = *(double*)&iz;
7859 return exp(-z * z - 0.5625) * exp((z - x) * (z + x) + R / S) / x;
7862 /*********************************************************************
7863 * erf (MSVCR120.@)
7865 double CDECL erf(double x)
7867 static const double efx8 = 1.02703333676410069053e+00,
7868 pp0 = 1.28379167095512558561e-01,
7869 pp1 = -3.25042107247001499370e-01,
7870 pp2 = -2.84817495755985104766e-02,
7871 pp3 = -5.77027029648944159157e-03,
7872 pp4 = -2.37630166566501626084e-05,
7873 qq1 = 3.97917223959155352819e-01,
7874 qq2 = 6.50222499887672944485e-02,
7875 qq3 = 5.08130628187576562776e-03,
7876 qq4 = 1.32494738004321644526e-04,
7877 qq5 = -3.96022827877536812320e-06;
7879 double r, s, z, y;
7880 UINT32 ix;
7881 int sign;
7883 ix = *(UINT64*)&x >> 32;
7884 sign = ix >> 31;
7885 ix &= 0x7fffffff;
7886 if (ix >= 0x7ff00000) {
7887 /* erf(nan)=nan, erf(+-inf)=+-1 */
7888 return 1 - 2 * sign + 1 / x;
7890 if (ix < 0x3feb0000) { /* |x| < 0.84375 */
7891 if (ix < 0x3e300000) { /* |x| < 2**-28 */
7892 /* avoid underflow */
7893 return 0.125 * (8 * x + efx8 * x);
7895 z = x * x;
7896 r = pp0 + z * (pp1 + z * (pp2 + z * (pp3 + z * pp4)));
7897 s = 1.0 + z * (qq1 + z * (qq2 + z * (qq3 + z * (qq4 + z * qq5))));
7898 y = r / s;
7899 return x + x * y;
7901 if (ix < 0x40180000) /* 0.84375 <= |x| < 6 */
7902 y = 1 - erfc2(ix, x);
7903 else
7904 y = 1 - DBL_MIN;
7905 return sign ? -y : y;
7908 static float erfc1f(float x)
7910 static const float erx = 8.4506291151e-01,
7911 pa0 = -2.3621185683e-03,
7912 pa1 = 4.1485610604e-01,
7913 pa2 = -3.7220788002e-01,
7914 pa3 = 3.1834661961e-01,
7915 pa4 = -1.1089469492e-01,
7916 pa5 = 3.5478305072e-02,
7917 pa6 = -2.1663755178e-03,
7918 qa1 = 1.0642088205e-01,
7919 qa2 = 5.4039794207e-01,
7920 qa3 = 7.1828655899e-02,
7921 qa4 = 1.2617121637e-01,
7922 qa5 = 1.3637083583e-02,
7923 qa6 = 1.1984500103e-02;
7925 float s, P, Q;
7927 s = fabsf(x) - 1;
7928 P = pa0 + s * (pa1 + s * (pa2 + s * (pa3 + s * (pa4 + s * (pa5 + s * pa6)))));
7929 Q = 1 + s * (qa1 + s * (qa2 + s * (qa3 + s * (qa4 + s * (qa5 + s * qa6)))));
7930 return 1 - erx - P / Q;
7933 static float erfc2f(UINT32 ix, float x)
7935 static const float ra0 = -9.8649440333e-03,
7936 ra1 = -6.9385856390e-01,
7937 ra2 = -1.0558626175e+01,
7938 ra3 = -6.2375331879e+01,
7939 ra4 = -1.6239666748e+02,
7940 ra5 = -1.8460508728e+02,
7941 ra6 = -8.1287437439e+01,
7942 ra7 = -9.8143291473e+00,
7943 sa1 = 1.9651271820e+01,
7944 sa2 = 1.3765776062e+02,
7945 sa3 = 4.3456588745e+02,
7946 sa4 = 6.4538726807e+02,
7947 sa5 = 4.2900814819e+02,
7948 sa6 = 1.0863500214e+02,
7949 sa7 = 6.5702495575e+00,
7950 sa8 = -6.0424413532e-02,
7951 rb0 = -9.8649431020e-03,
7952 rb1 = -7.9928326607e-01,
7953 rb2 = -1.7757955551e+01,
7954 rb3 = -1.6063638306e+02,
7955 rb4 = -6.3756646729e+02,
7956 rb5 = -1.0250950928e+03,
7957 rb6 = -4.8351919556e+02,
7958 sb1 = 3.0338060379e+01,
7959 sb2 = 3.2579251099e+02,
7960 sb3 = 1.5367296143e+03,
7961 sb4 = 3.1998581543e+03,
7962 sb5 = 2.5530502930e+03,
7963 sb6 = 4.7452853394e+02,
7964 sb7 = -2.2440952301e+01;
7966 float s, R, S, z;
7968 if (ix < 0x3fa00000) /* |x| < 1.25 */
7969 return erfc1f(x);
7971 x = fabsf(x);
7972 s = 1 / (x * x);
7973 if (ix < 0x4036db6d) { /* |x| < 1/0.35 */
7974 R = ra0 + s * (ra1 + s * (ra2 + s * (ra3 + s * (ra4 + s *
7975 (ra5 + s * (ra6 + s * ra7))))));
7976 S = 1.0f + s * (sa1 + s * (sa2 + s * (sa3 + s * (sa4 + s *
7977 (sa5 + s * (sa6 + s * (sa7 + s * sa8)))))));
7978 } else { /* |x| >= 1/0.35 */
7979 R = rb0 + s * (rb1 + s * (rb2 + s * (rb3 + s * (rb4 + s * (rb5 + s * rb6)))));
7980 S = 1.0f + s * (sb1 + s * (sb2 + s * (sb3 + s * (sb4 + s *
7981 (sb5 + s * (sb6 + s * sb7))))));
7984 ix = *(UINT32*)&x & 0xffffe000;
7985 z = *(float*)&ix;
7986 return expf(-z * z - 0.5625f) * expf((z - x) * (z + x) + R / S) / x;
7989 /*********************************************************************
7990 * erff (MSVCR120.@)
7992 * Copied from musl: src/math/erff.c
7994 float CDECL erff(float x)
7996 static const float efx8 = 1.0270333290e+00,
7997 pp0 = 1.2837916613e-01,
7998 pp1 = -3.2504209876e-01,
7999 pp2 = -2.8481749818e-02,
8000 pp3 = -5.7702702470e-03,
8001 pp4 = -2.3763017452e-05,
8002 qq1 = 3.9791721106e-01,
8003 qq2 = 6.5022252500e-02,
8004 qq3 = 5.0813062117e-03,
8005 qq4 = 1.3249473704e-04,
8006 qq5 = -3.9602282413e-06;
8008 float r, s, z, y;
8009 UINT32 ix;
8010 int sign;
8012 ix = *(UINT32*)&x;
8013 sign = ix >> 31;
8014 ix &= 0x7fffffff;
8015 if (ix >= 0x7f800000) {
8016 /* erf(nan)=nan, erf(+-inf)=+-1 */
8017 return 1 - 2 * sign + 1 / x;
8019 if (ix < 0x3f580000) { /* |x| < 0.84375 */
8020 if (ix < 0x31800000) { /* |x| < 2**-28 */
8021 /*avoid underflow */
8022 return 0.125f * (8 * x + efx8 * x);
8024 z = x * x;
8025 r = pp0 + z * (pp1 + z * (pp2 + z * (pp3 + z * pp4)));
8026 s = 1 + z * (qq1 + z * (qq2 + z * (qq3 + z * (qq4 + z * qq5))));
8027 y = r / s;
8028 return x + x * y;
8030 if (ix < 0x40c00000) /* |x| < 6 */
8031 y = 1 - erfc2f(ix, x);
8032 else
8033 y = 1 - FLT_MIN;
8034 return sign ? -y : y;
8037 /*********************************************************************
8038 * erfc (MSVCR120.@)
8040 * Copied from musl: src/math/erf.c
8042 double CDECL erfc(double x)
8044 static const double pp0 = 1.28379167095512558561e-01,
8045 pp1 = -3.25042107247001499370e-01,
8046 pp2 = -2.84817495755985104766e-02,
8047 pp3 = -5.77027029648944159157e-03,
8048 pp4 = -2.37630166566501626084e-05,
8049 qq1 = 3.97917223959155352819e-01,
8050 qq2 = 6.50222499887672944485e-02,
8051 qq3 = 5.08130628187576562776e-03,
8052 qq4 = 1.32494738004321644526e-04,
8053 qq5 = -3.96022827877536812320e-06;
8055 double r, s, z, y;
8056 UINT32 ix;
8057 int sign;
8059 ix = *(ULONGLONG*)&x >> 32;
8060 sign = ix >> 31;
8061 ix &= 0x7fffffff;
8062 if (ix >= 0x7ff00000) {
8063 /* erfc(nan)=nan, erfc(+-inf)=0,2 */
8064 return 2 * sign + 1 / x;
8066 if (ix < 0x3feb0000) { /* |x| < 0.84375 */
8067 if (ix < 0x3c700000) /* |x| < 2**-56 */
8068 return 1.0 - x;
8069 z = x * x;
8070 r = pp0 + z * (pp1 + z * (pp2 + z * (pp3 + z * pp4)));
8071 s = 1.0 + z * (qq1 + z * (qq2 + z * (qq3 + z * (qq4 + z * qq5))));
8072 y = r / s;
8073 if (sign || ix < 0x3fd00000) { /* x < 1/4 */
8074 return 1.0 - (x + x * y);
8076 return 0.5 - (x - 0.5 + x * y);
8078 if (ix < 0x403c0000) { /* 0.84375 <= |x| < 28 */
8079 return sign ? 2 - erfc2(ix, x) : erfc2(ix, x);
8081 if (sign)
8082 return 2 - DBL_MIN;
8083 *_errno() = ERANGE;
8084 return fp_barrier(DBL_MIN) * DBL_MIN;
8087 /*********************************************************************
8088 * erfcf (MSVCR120.@)
8090 * Copied from musl: src/math/erff.c
8092 float CDECL erfcf(float x)
8094 static const float pp0 = 1.2837916613e-01,
8095 pp1 = -3.2504209876e-01,
8096 pp2 = -2.8481749818e-02,
8097 pp3 = -5.7702702470e-03,
8098 pp4 = -2.3763017452e-05,
8099 qq1 = 3.9791721106e-01,
8100 qq2 = 6.5022252500e-02,
8101 qq3 = 5.0813062117e-03,
8102 qq4 = 1.3249473704e-04,
8103 qq5 = -3.9602282413e-06;
8105 float r, s, z, y;
8106 UINT32 ix;
8107 int sign;
8109 ix = *(UINT32*)&x;
8110 sign = ix >> 31;
8111 ix &= 0x7fffffff;
8112 if (ix >= 0x7f800000) {
8113 /* erfc(nan)=nan, erfc(+-inf)=0,2 */
8114 return 2 * sign + 1 / x;
8117 if (ix < 0x3f580000) { /* |x| < 0.84375 */
8118 if (ix < 0x23800000) /* |x| < 2**-56 */
8119 return 1.0f - x;
8120 z = x * x;
8121 r = pp0 + z * (pp1 + z * (pp2 + z * (pp3 + z * pp4)));
8122 s = 1.0f + z * (qq1 + z * (qq2 + z * (qq3 + z * (qq4 + z * qq5))));
8123 y = r / s;
8124 if (sign || ix < 0x3e800000) /* x < 1/4 */
8125 return 1.0f - (x + x * y);
8126 return 0.5f - (x - 0.5f + x * y);
8128 if (ix < 0x41e00000) { /* |x| < 28 */
8129 return sign ? 2 - erfc2f(ix, x) : erfc2f(ix, x);
8131 if (sign)
8132 return 2 - FLT_MIN;
8133 *_errno() = ERANGE;
8134 return FLT_MIN * FLT_MIN;
8137 /*********************************************************************
8138 * fmaxf (MSVCR120.@)
8140 float CDECL fmaxf(float x, float y)
8142 if(isnan(x))
8143 return y;
8144 if(isnan(y))
8145 return x;
8146 if(x==0 && y==0)
8147 return signbit(x) ? y : x;
8148 return x<y ? y : x;
8151 /*********************************************************************
8152 * fmax (MSVCR120.@)
8154 double CDECL fmax(double x, double y)
8156 if(isnan(x))
8157 return y;
8158 if(isnan(y))
8159 return x;
8160 if(x==0 && y==0)
8161 return signbit(x) ? y : x;
8162 return x<y ? y : x;
8165 /*********************************************************************
8166 * fdimf (MSVCR120.@)
8168 float CDECL fdimf(float x, float y)
8170 if(isnan(x))
8171 return x;
8172 if(isnan(y))
8173 return y;
8174 return x>y ? x-y : 0;
8177 /*********************************************************************
8178 * fdim (MSVCR120.@)
8180 double CDECL fdim(double x, double y)
8182 if(isnan(x))
8183 return x;
8184 if(isnan(y))
8185 return y;
8186 return x>y ? x-y : 0;
8189 /*********************************************************************
8190 * _fdsign (MSVCR120.@)
8192 int CDECL _fdsign(float x)
8194 union { float f; UINT32 i; } u = { x };
8195 return (u.i >> 16) & 0x8000;
8198 /*********************************************************************
8199 * _dsign (MSVCR120.@)
8201 int CDECL _dsign(double x)
8203 union { double f; UINT64 i; } u = { x };
8204 return (u.i >> 48) & 0x8000;
8208 /*********************************************************************
8209 * _dpcomp (MSVCR120.@)
8211 int CDECL _dpcomp(double x, double y)
8213 if(isnan(x) || isnan(y))
8214 return 0;
8216 if(x == y) return 2;
8217 return x < y ? 1 : 4;
8220 /*********************************************************************
8221 * _fdpcomp (MSVCR120.@)
8223 int CDECL _fdpcomp(float x, float y)
8225 return _dpcomp(x, y);
8228 /*********************************************************************
8229 * fminf (MSVCR120.@)
8231 float CDECL fminf(float x, float y)
8233 if(isnan(x))
8234 return y;
8235 if(isnan(y))
8236 return x;
8237 if(x==0 && y==0)
8238 return signbit(x) ? x : y;
8239 return x<y ? x : y;
8242 /*********************************************************************
8243 * fmin (MSVCR120.@)
8245 double CDECL fmin(double x, double y)
8247 if(isnan(x))
8248 return y;
8249 if(isnan(y))
8250 return x;
8251 if(x==0 && y==0)
8252 return signbit(x) ? x : y;
8253 return x<y ? x : y;
8256 /*********************************************************************
8257 * asinh (MSVCR120.@)
8259 * Copied from musl: src/math/asinh.c
8261 double CDECL asinh(double x)
8263 UINT64 ux = *(UINT64*)&x;
8264 int e = ux >> 52 & 0x7ff;
8265 int s = ux >> 63;
8267 /* |x| */
8268 ux &= (UINT64)-1 / 2;
8269 x = *(double*)&ux;
8271 if (e >= 0x3ff + 26) /* |x| >= 0x1p26 or inf or nan */
8272 x = log(x) + 0.693147180559945309417232121458176568;
8273 else if (e >= 0x3ff + 1) /* |x| >= 2 */
8274 x = log(2 * x + 1 / (sqrt(x * x + 1) + x));
8275 else if (e >= 0x3ff - 26) /* |x| >= 0x1p-26 */
8276 x = log1p(x + x * x / (sqrt(x * x + 1) + 1));
8277 else /* |x| < 0x1p-26, raise inexact if x != 0 */
8278 fp_barrier(x + 0x1p120f);
8279 return s ? -x : x;
8282 /*********************************************************************
8283 * asinhf (MSVCR120.@)
8285 * Copied from musl: src/math/asinhf.c
8287 float CDECL asinhf(float x)
8289 UINT32 ux = *(UINT32*)&x;
8290 UINT32 i = ux & 0x7fffffff;
8291 int s = ux >> 31;
8293 /* |x| */
8294 x = *(float*)&i;
8296 if (i >= 0x3f800000 + (12 << 23))/* |x| >= 0x1p12 or inf or nan */
8297 x = logf(x) + 0.693147180559945309417232121458176568f;
8298 else if (i >= 0x3f800000 + (1 << 23)) /* |x| >= 2 */
8299 x = logf(2 * x + 1 / (sqrtf(x * x + 1) + x));
8300 else if (i >= 0x3f800000 - (12 << 23)) /* |x| >= 0x1p-12 */
8301 x = log1pf(x + x * x / (sqrtf(x * x + 1) + 1));
8302 else /* |x| < 0x1p-12, raise inexact if x!=0 */
8303 fp_barrierf(x + 0x1p120f);
8304 return s ? -x : x;
8307 /*********************************************************************
8308 * acosh (MSVCR120.@)
8310 * Copied from musl: src/math/acosh.c
8312 double CDECL acosh(double x)
8314 int e = *(UINT64*)&x >> 52 & 0x7ff;
8316 if (x < 1)
8318 *_errno() = EDOM;
8319 feraiseexcept(FE_INVALID);
8320 return NAN;
8323 if (e < 0x3ff + 1) /* |x| < 2, up to 2ulp error in [1,1.125] */
8324 return log1p(x - 1 + sqrt((x - 1) * (x - 1) + 2 * (x - 1)));
8325 if (e < 0x3ff + 26) /* |x| < 0x1p26 */
8326 return log(2 * x - 1 / (x + sqrt(x * x - 1)));
8327 /* |x| >= 0x1p26 or nan */
8328 return log(x) + 0.693147180559945309417232121458176568;
8331 /*********************************************************************
8332 * acoshf (MSVCR120.@)
8334 * Copied from musl: src/math/acoshf.c
8336 float CDECL acoshf(float x)
8338 UINT32 a = *(UINT32*)&x & 0x7fffffff;
8340 if (x < 1)
8342 *_errno() = EDOM;
8343 feraiseexcept(FE_INVALID);
8344 return NAN;
8347 if (a < 0x3f800000 + (1 << 23)) /* |x| < 2, up to 2ulp error in [1,1.125] */
8348 return log1pf(x - 1 + sqrtf((x - 1) * (x - 1) + 2 * (x - 1)));
8349 if (*(UINT32*)&x < 0x3f800000 + (12 << 23)) /* 2 <= x < 0x1p12 */
8350 return logf(2 * x - 1 / (x + sqrtf(x * x - 1)));
8351 /* x >= 0x1p12 or x <= -2 or nan */
8352 return logf(x) + 0.693147180559945309417232121458176568f;
8355 /*********************************************************************
8356 * atanh (MSVCR120.@)
8358 * Copied from musl: src/math/atanh.c
8360 double CDECL atanh(double x)
8362 UINT64 ux = *(UINT64*)&x;
8363 int e = ux >> 52 & 0x7ff;
8364 int s = ux >> 63;
8366 /* |x| */
8367 ux &= (UINT64)-1 / 2;
8368 x = *(double*)&ux;
8370 if (x > 1) {
8371 *_errno() = EDOM;
8372 feraiseexcept(FE_INVALID);
8373 return NAN;
8376 if (e < 0x3ff - 1) {
8377 if (e < 0x3ff - 32) {
8378 fp_barrier(x + 0x1p120f);
8379 if (e == 0) /* handle underflow */
8380 fp_barrier(x * x);
8381 } else { /* |x| < 0.5, up to 1.7ulp error */
8382 x = 0.5 * log1p(2 * x + 2 * x * x / (1 - x));
8384 } else { /* avoid overflow */
8385 x = 0.5 * log1p(2 * (x / (1 - x)));
8386 if (isinf(x)) *_errno() = ERANGE;
8388 return s ? -x : x;
8391 /*********************************************************************
8392 * atanhf (MSVCR120.@)
8394 * Copied from musl: src/math/atanhf.c
8396 float CDECL atanhf(float x)
8398 UINT32 ux = *(UINT32*)&x;
8399 int s = ux >> 31;
8401 /* |x| */
8402 ux &= 0x7fffffff;
8403 x = *(float*)&ux;
8405 if (x > 1) {
8406 *_errno() = EDOM;
8407 feraiseexcept(FE_INVALID);
8408 return NAN;
8411 if (ux < 0x3f800000 - (1 << 23)) {
8412 if (ux < 0x3f800000 - (32 << 23)) {
8413 fp_barrierf(x + 0x1p120f);
8414 if (ux < (1 << 23)) /* handle underflow */
8415 fp_barrierf(x * x);
8416 } else { /* |x| < 0.5, up to 1.7ulp error */
8417 x = 0.5f * log1pf(2 * x + 2 * x * x / (1 - x));
8419 } else { /* avoid overflow */
8420 x = 0.5f * log1pf(2 * (x / (1 - x)));
8421 if (isinf(x)) *_errno() = ERANGE;
8423 return s ? -x : x;
8426 #endif /* _MSVCR_VER>=120 */
8428 /*********************************************************************
8429 * _scalb (MSVCRT.@)
8430 * scalbn (MSVCR120.@)
8431 * scalbln (MSVCR120.@)
8433 double CDECL _scalb(double num, __msvcrt_long power)
8435 return ldexp(num, power);
8438 /*********************************************************************
8439 * _scalbf (MSVCRT.@)
8440 * scalbnf (MSVCR120.@)
8441 * scalblnf (MSVCR120.@)
8443 float CDECL _scalbf(float num, __msvcrt_long power)
8445 return ldexp(num, power);
8448 #if _MSVCR_VER>=120
8450 /*********************************************************************
8451 * remainder (MSVCR120.@)
8453 * Copied from musl: src/math/remainder.c
8455 double CDECL remainder(double x, double y)
8457 int q;
8458 #if _MSVCR_VER == 120 && defined(__x86_64__)
8459 if (isnan(x) || isnan(y)) *_errno() = EDOM;
8460 #endif
8461 return remquo(x, y, &q);
8464 /*********************************************************************
8465 * remainderf (MSVCR120.@)
8467 * Copied from musl: src/math/remainderf.c
8469 float CDECL remainderf(float x, float y)
8471 int q;
8472 #if _MSVCR_VER == 120 && defined(__x86_64__)
8473 if (isnan(x) || isnan(y)) *_errno() = EDOM;
8474 #endif
8475 return remquof(x, y, &q);
8478 /*********************************************************************
8479 * remquo (MSVCR120.@)
8481 * Copied from musl: src/math/remquo.c
8483 double CDECL remquo(double x, double y, int *quo)
8485 UINT64 uxi = *(UINT64*)&x;
8486 UINT64 uyi = *(UINT64*)&y;
8487 int ex = uxi >> 52 & 0x7ff;
8488 int ey = uyi >> 52 & 0x7ff;
8489 int sx = uxi >> 63;
8490 int sy = uyi >> 63;
8491 UINT32 q;
8492 UINT64 i;
8494 *quo = 0;
8495 if (y == 0 || isinf(x)) *_errno() = EDOM;
8496 if (uyi << 1 == 0 || isnan(y) || ex == 0x7ff)
8497 return (x * y) / (x * y);
8498 if (uxi << 1 == 0)
8499 return x;
8501 /* normalize x and y */
8502 if (!ex) {
8503 for (i = uxi << 12; i >> 63 == 0; ex--, i <<= 1);
8504 uxi <<= -ex + 1;
8505 } else {
8506 uxi &= -1ULL >> 12;
8507 uxi |= 1ULL << 52;
8509 if (!ey) {
8510 for (i = uyi << 12; i >> 63 == 0; ey--, i <<= 1);
8511 uyi <<= -ey + 1;
8512 } else {
8513 uyi &= -1ULL >> 12;
8514 uyi |= 1ULL << 52;
8517 q = 0;
8518 if (ex < ey) {
8519 if (ex+1 == ey)
8520 goto end;
8521 return x;
8524 /* x mod y */
8525 for (; ex > ey; ex--) {
8526 i = uxi - uyi;
8527 if (i >> 63 == 0) {
8528 uxi = i;
8529 q++;
8531 uxi <<= 1;
8532 q <<= 1;
8534 i = uxi - uyi;
8535 if (i >> 63 == 0) {
8536 uxi = i;
8537 q++;
8539 if (uxi == 0)
8540 ex = -60;
8541 else
8542 for (; uxi >> 52 == 0; uxi <<= 1, ex--);
8543 end:
8544 /* scale result and decide between |x| and |x|-|y| */
8545 if (ex > 0) {
8546 uxi -= 1ULL << 52;
8547 uxi |= (UINT64)ex << 52;
8548 } else {
8549 uxi >>= -ex + 1;
8551 x = *(double*)&uxi;
8552 if (sy)
8553 y = -y;
8554 if (ex == ey || (ex + 1 == ey && (2 * x > y || (2 * x == y && q % 2)))) {
8555 x -= y;
8556 q++;
8558 q &= 0x7fffffff;
8559 *quo = sx ^ sy ? -(int)q : (int)q;
8560 return sx ? -x : x;
8563 /*********************************************************************
8564 * remquof (MSVCR120.@)
8566 * Copied from musl: src/math/remquof.c
8568 float CDECL remquof(float x, float y, int *quo)
8570 UINT32 uxi = *(UINT32*)&x;
8571 UINT32 uyi = *(UINT32*)&y;
8572 int ex = uxi >> 23 & 0xff;
8573 int ey = uyi >> 23 & 0xff;
8574 int sx = uxi >> 31;
8575 int sy = uyi>> 31;
8576 UINT32 q, i;
8578 *quo = 0;
8579 if (y == 0 || isinf(x)) *_errno() = EDOM;
8580 if (uyi << 1 == 0 || isnan(y) || ex == 0xff)
8581 return (x * y) / (x * y);
8582 if (uxi << 1 == 0)
8583 return x;
8585 /* normalize x and y */
8586 if (!ex) {
8587 for (i = uxi << 9; i >> 31 == 0; ex--, i <<= 1);
8588 uxi <<= -ex + 1;
8589 } else {
8590 uxi &= -1U >> 9;
8591 uxi |= 1U << 23;
8593 if (!ey) {
8594 for (i = uyi << 9; i >> 31 == 0; ey--, i <<= 1);
8595 uyi <<= -ey + 1;
8596 } else {
8597 uyi &= -1U >> 9;
8598 uyi |= 1U << 23;
8601 q = 0;
8602 if (ex < ey) {
8603 if (ex + 1 == ey)
8604 goto end;
8605 return x;
8608 /* x mod y */
8609 for (; ex > ey; ex--) {
8610 i = uxi - uyi;
8611 if (i >> 31 == 0) {
8612 uxi = i;
8613 q++;
8615 uxi <<= 1;
8616 q <<= 1;
8618 i = uxi - uyi;
8619 if (i >> 31 == 0) {
8620 uxi = i;
8621 q++;
8623 if (uxi == 0)
8624 ex = -30;
8625 else
8626 for (; uxi >> 23 == 0; uxi <<= 1, ex--);
8627 end:
8628 /* scale result and decide between |x| and |x|-|y| */
8629 if (ex > 0) {
8630 uxi -= 1U << 23;
8631 uxi |= (UINT32)ex << 23;
8632 } else {
8633 uxi >>= -ex + 1;
8635 x = *(float*)&uxi;
8636 if (sy)
8637 y = -y;
8638 if (ex == ey || (ex + 1 == ey && (2 * x > y || (2 * x == y && q % 2)))) {
8639 x -= y;
8640 q++;
8642 q &= 0x7fffffff;
8643 *quo = sx ^ sy ? -(int)q : (int)q;
8644 return sx ? -x : x;
8647 /* sin(pi*x) assuming x > 2^-100, if sin(pi*x)==0 the sign is arbitrary */
8648 static double sin_pi(double x)
8650 static const double pi = 3.14159265358979311600e+00;
8651 int n;
8653 /* spurious inexact if odd int */
8654 x = 2.0 * (x * 0.5 - floor(x * 0.5)); /* x mod 2.0 */
8656 n = (int)(x * 4.0);
8657 n = (n + 1) / 2;
8658 x -= n * 0.5f;
8659 x *= pi;
8661 switch (n) {
8662 default: /* case 4: */
8663 case 0: return __sin(x, 0.0, 0);
8664 case 1: return __cos(x, 0.0);
8665 case 2: return __sin(-x, 0.0, 0);
8666 case 3: return -__cos(x, 0.0);
8670 /*********************************************************************
8671 * lgamma (MSVCR120.@)
8673 * Copied from musl: src/math/lgamma_r.c
8675 double CDECL lgamma(double x)
8677 static const double pi = 3.14159265358979311600e+00,
8678 a0 = 7.72156649015328655494e-02,
8679 a1 = 3.22467033424113591611e-01,
8680 a2 = 6.73523010531292681824e-02,
8681 a3 = 2.05808084325167332806e-02,
8682 a4 = 7.38555086081402883957e-03,
8683 a5 = 2.89051383673415629091e-03,
8684 a6 = 1.19270763183362067845e-03,
8685 a7 = 5.10069792153511336608e-04,
8686 a8 = 2.20862790713908385557e-04,
8687 a9 = 1.08011567247583939954e-04,
8688 a10 = 2.52144565451257326939e-05,
8689 a11 = 4.48640949618915160150e-05,
8690 tc = 1.46163214496836224576e+00,
8691 tf = -1.21486290535849611461e-01,
8692 tt = -3.63867699703950536541e-18,
8693 t0 = 4.83836122723810047042e-01,
8694 t1 = -1.47587722994593911752e-01,
8695 t2 = 6.46249402391333854778e-02,
8696 t3 = -3.27885410759859649565e-02,
8697 t4 = 1.79706750811820387126e-02,
8698 t5 = -1.03142241298341437450e-02,
8699 t6 = 6.10053870246291332635e-03,
8700 t7 = -3.68452016781138256760e-03,
8701 t8 = 2.25964780900612472250e-03,
8702 t9 = -1.40346469989232843813e-03,
8703 t10 = 8.81081882437654011382e-04,
8704 t11 = -5.38595305356740546715e-04,
8705 t12 = 3.15632070903625950361e-04,
8706 t13 = -3.12754168375120860518e-04,
8707 t14 = 3.35529192635519073543e-04,
8708 u0 = -7.72156649015328655494e-02,
8709 u1 = 6.32827064025093366517e-01,
8710 u2 = 1.45492250137234768737e+00,
8711 u3 = 9.77717527963372745603e-01,
8712 u4 = 2.28963728064692451092e-01,
8713 u5 = 1.33810918536787660377e-02,
8714 v1 = 2.45597793713041134822e+00,
8715 v2 = 2.12848976379893395361e+00,
8716 v3 = 7.69285150456672783825e-01,
8717 v4 = 1.04222645593369134254e-01,
8718 v5 = 3.21709242282423911810e-03,
8719 s0 = -7.72156649015328655494e-02,
8720 s1 = 2.14982415960608852501e-01,
8721 s2 = 3.25778796408930981787e-01,
8722 s3 = 1.46350472652464452805e-01,
8723 s4 = 2.66422703033638609560e-02,
8724 s5 = 1.84028451407337715652e-03,
8725 s6 = 3.19475326584100867617e-05,
8726 r1 = 1.39200533467621045958e+00,
8727 r2 = 7.21935547567138069525e-01,
8728 r3 = 1.71933865632803078993e-01,
8729 r4 = 1.86459191715652901344e-02,
8730 r5 = 7.77942496381893596434e-04,
8731 r6 = 7.32668430744625636189e-06,
8732 w0 = 4.18938533204672725052e-01,
8733 w1 = 8.33333333333329678849e-02,
8734 w2 = -2.77777777728775536470e-03,
8735 w3 = 7.93650558643019558500e-04,
8736 w4 = -5.95187557450339963135e-04,
8737 w5 = 8.36339918996282139126e-04,
8738 w6 = -1.63092934096575273989e-03;
8740 union {double f; UINT64 i;} u = {x};
8741 double t, y, z, nadj, p, p1, p2, p3, q, r, w;
8742 UINT32 ix;
8743 int sign,i;
8745 /* purge off +-inf, NaN, +-0, tiny and negative arguments */
8746 sign = u.i >> 63;
8747 ix = u.i >> 32 & 0x7fffffff;
8748 if (ix >= 0x7ff00000)
8749 return x * x;
8750 if (ix < (0x3ff - 70) << 20) { /* |x|<2**-70, return -log(|x|) */
8751 if(sign)
8752 x = -x;
8753 return -log(x);
8755 if (sign) {
8756 x = -x;
8757 t = sin_pi(x);
8758 if (t == 0.0) { /* -integer */
8759 *_errno() = ERANGE;
8760 return 1.0 / (x - x);
8762 if (t <= 0.0)
8763 t = -t;
8764 nadj = log(pi / (t * x));
8767 /* purge off 1 and 2 */
8768 if ((ix == 0x3ff00000 || ix == 0x40000000) && (UINT32)u.i == 0)
8769 r = 0;
8770 /* for x < 2.0 */
8771 else if (ix < 0x40000000) {
8772 if (ix <= 0x3feccccc) { /* lgamma(x) = lgamma(x+1)-log(x) */
8773 r = -log(x);
8774 if (ix >= 0x3FE76944) {
8775 y = 1.0 - x;
8776 i = 0;
8777 } else if (ix >= 0x3FCDA661) {
8778 y = x - (tc - 1.0);
8779 i = 1;
8780 } else {
8781 y = x;
8782 i = 2;
8784 } else {
8785 r = 0.0;
8786 if (ix >= 0x3FFBB4C3) { /* [1.7316,2] */
8787 y = 2.0 - x;
8788 i = 0;
8789 } else if(ix >= 0x3FF3B4C4) { /* [1.23,1.73] */
8790 y = x - tc;
8791 i = 1;
8792 } else {
8793 y = x - 1.0;
8794 i = 2;
8797 switch (i) {
8798 case 0:
8799 z = y * y;
8800 p1 = a0 + z * (a2 + z * (a4 + z * (a6 + z * (a8 + z * a10))));
8801 p2 = z * (a1 + z * (a3 + z * (a5 + z * (a7 + z * (a9 + z * a11)))));
8802 p = y * p1 + p2;
8803 r += (p - 0.5 * y);
8804 break;
8805 case 1:
8806 z = y * y;
8807 w = z * y;
8808 p1 = t0 + w * (t3 + w * (t6 + w * (t9 + w * t12))); /* parallel comp */
8809 p2 = t1 + w * (t4 + w * (t7 + w * (t10 + w * t13)));
8810 p3 = t2 + w * (t5 + w * (t8 + w * (t11 + w * t14)));
8811 p = z * p1 - (tt - w * (p2 + y * p3));
8812 r += tf + p;
8813 break;
8814 case 2:
8815 p1 = y * (u0 + y * (u1 + y * (u2 + y * (u3 + y * (u4 + y * u5)))));
8816 p2 = 1.0 + y * (v1 + y * (v2 + y * (v3 + y * (v4 + y * v5))));
8817 r += -0.5 * y + p1 / p2;
8819 } else if (ix < 0x40200000) { /* x < 8.0 */
8820 i = (int)x;
8821 y = x - (double)i;
8822 p = y * (s0 + y * (s1 + y * (s2 + y * (s3 + y * (s4 + y * (s5 + y * s6))))));
8823 q = 1.0 + y * (r1 + y * (r2 + y * (r3 + y * (r4 + y * (r5 + y * r6)))));
8824 r = 0.5 * y + p / q;
8825 z = 1.0; /* lgamma(1+s) = log(s) + lgamma(s) */
8826 switch (i) {
8827 case 7: z *= y + 6.0; /* fall through */
8828 case 6: z *= y + 5.0; /* fall through */
8829 case 5: z *= y + 4.0; /* fall through */
8830 case 4: z *= y + 3.0; /* fall through */
8831 case 3:
8832 z *= y + 2.0;
8833 r += log(z);
8834 break;
8836 } else if (ix < 0x43900000) { /* 8.0 <= x < 2**58 */
8837 t = log(x);
8838 z = 1.0 / x;
8839 y = z * z;
8840 w = w0 + z * (w1 + y * (w2 + y * (w3 + y * (w4 + y * (w5 + y * w6)))));
8841 r = (x - 0.5) * (t - 1.0) + w;
8842 } else /* 2**58 <= x <= inf */
8843 r = x * (log(x) - 1.0);
8844 if (sign)
8845 r = nadj - r;
8846 return r;
8849 /* sin(pi*x) assuming x > 2^-100, if sin(pi*x)==0 the sign is arbitrary */
8850 static float sinf_pi(float x)
8852 double y;
8853 int n;
8855 /* spurious inexact if odd int */
8856 x = 2 * (x * 0.5f - floorf(x * 0.5f)); /* x mod 2.0 */
8858 n = (int)(x * 4);
8859 n = (n + 1) / 2;
8860 y = x - n * 0.5f;
8861 y *= M_PI;
8862 switch (n) {
8863 default: /* case 4: */
8864 case 0: return __sindf(y);
8865 case 1: return __cosdf(y);
8866 case 2: return __sindf(-y);
8867 case 3: return -__cosdf(y);
8871 /*********************************************************************
8872 * lgammaf (MSVCR120.@)
8874 * Copied from musl: src/math/lgammaf_r.c
8876 float CDECL lgammaf(float x)
8878 static const float pi = 3.1415927410e+00,
8879 a0 = 7.7215664089e-02,
8880 a1 = 3.2246702909e-01,
8881 a2 = 6.7352302372e-02,
8882 a3 = 2.0580807701e-02,
8883 a4 = 7.3855509982e-03,
8884 a5 = 2.8905137442e-03,
8885 a6 = 1.1927076848e-03,
8886 a7 = 5.1006977446e-04,
8887 a8 = 2.2086278477e-04,
8888 a9 = 1.0801156895e-04,
8889 a10 = 2.5214456400e-05,
8890 a11 = 4.4864096708e-05,
8891 tc = 1.4616321325e+00,
8892 tf = -1.2148628384e-01,
8893 tt = 6.6971006518e-09,
8894 t0 = 4.8383611441e-01,
8895 t1 = -1.4758771658e-01,
8896 t2 = 6.4624942839e-02,
8897 t3 = -3.2788541168e-02,
8898 t4 = 1.7970675603e-02,
8899 t5 = -1.0314224288e-02,
8900 t6 = 6.1005386524e-03,
8901 t7 = -3.6845202558e-03,
8902 t8 = 2.2596477065e-03,
8903 t9 = -1.4034647029e-03,
8904 t10 = 8.8108185446e-04,
8905 t11 = -5.3859531181e-04,
8906 t12 = 3.1563205994e-04,
8907 t13 = -3.1275415677e-04,
8908 t14 = 3.3552918467e-04,
8909 u0 = -7.7215664089e-02,
8910 u1 = 6.3282704353e-01,
8911 u2 = 1.4549225569e+00,
8912 u3 = 9.7771751881e-01,
8913 u4 = 2.2896373272e-01,
8914 u5 = 1.3381091878e-02,
8915 v1 = 2.4559779167e+00,
8916 v2 = 2.1284897327e+00,
8917 v3 = 7.6928514242e-01,
8918 v4 = 1.0422264785e-01,
8919 v5 = 3.2170924824e-03,
8920 s0 = -7.7215664089e-02,
8921 s1 = 2.1498242021e-01,
8922 s2 = 3.2577878237e-01,
8923 s3 = 1.4635047317e-01,
8924 s4 = 2.6642270386e-02,
8925 s5 = 1.8402845599e-03,
8926 s6 = 3.1947532989e-05,
8927 r1 = 1.3920053244e+00,
8928 r2 = 7.2193557024e-01,
8929 r3 = 1.7193385959e-01,
8930 r4 = 1.8645919859e-02,
8931 r5 = 7.7794247773e-04,
8932 r6 = 7.3266842264e-06,
8933 w0 = 4.1893854737e-01,
8934 w1 = 8.3333335817e-02,
8935 w2 = -2.7777778450e-03,
8936 w3 = 7.9365057172e-04,
8937 w4 = -5.9518753551e-04,
8938 w5 = 8.3633989561e-04,
8939 w6 = -1.6309292987e-03;
8941 union {float f; UINT32 i;} u = {x};
8942 float t, y, z, nadj, p, p1, p2, p3, q, r, w;
8943 UINT32 ix;
8944 int i, sign;
8946 /* purge off +-inf, NaN, +-0, tiny and negative arguments */
8947 sign = u.i >> 31;
8948 ix = u.i & 0x7fffffff;
8949 if (ix >= 0x7f800000)
8950 return x * x;
8951 if (ix < 0x35000000) { /* |x| < 2**-21, return -log(|x|) */
8952 if (sign)
8953 x = -x;
8954 return -logf(x);
8956 if (sign) {
8957 x = -x;
8958 t = sinf_pi(x);
8959 if (t == 0.0f) { /* -integer */
8960 *_errno() = ERANGE;
8961 return 1.0f / (x - x);
8963 if (t <= 0.0f)
8964 t = -t;
8965 nadj = logf(pi / (t * x));
8968 /* purge off 1 and 2 */
8969 if (ix == 0x3f800000 || ix == 0x40000000)
8970 r = 0;
8971 /* for x < 2.0 */
8972 else if (ix < 0x40000000) {
8973 if (ix <= 0x3f666666) { /* lgamma(x) = lgamma(x+1)-log(x) */
8974 r = -logf(x);
8975 if (ix >= 0x3f3b4a20) {
8976 y = 1.0f - x;
8977 i = 0;
8978 } else if (ix >= 0x3e6d3308) {
8979 y = x - (tc - 1.0f);
8980 i = 1;
8981 } else {
8982 y = x;
8983 i = 2;
8985 } else {
8986 r = 0.0f;
8987 if (ix >= 0x3fdda618) { /* [1.7316,2] */
8988 y = 2.0f - x;
8989 i = 0;
8990 } else if (ix >= 0x3F9da620) { /* [1.23,1.73] */
8991 y = x - tc;
8992 i = 1;
8993 } else {
8994 y = x - 1.0f;
8995 i = 2;
8998 switch(i) {
8999 case 0:
9000 z = y * y;
9001 p1 = a0 + z * (a2 + z * (a4 + z * (a6 + z * (a8 + z * a10))));
9002 p2 = z * (a1 + z * (a3 + z * (a5 + z * (a7 + z * (a9 + z * a11)))));
9003 p = y * p1 + p2;
9004 r += p - 0.5f * y;
9005 break;
9006 case 1:
9007 z = y * y;
9008 w = z * y;
9009 p1 = t0 + w * (t3 + w * (t6 + w * (t9 + w * t12))); /* parallel comp */
9010 p2 = t1 + w * (t4 + w * (t7 + w * (t10 + w * t13)));
9011 p3 = t2 + w * (t5 + w * (t8 + w * (t11 + w * t14)));
9012 p = z * p1 - (tt - w * (p2 + y * p3));
9013 r += (tf + p);
9014 break;
9015 case 2:
9016 p1 = y * (u0 + y * (u1 + y * (u2 + y * (u3 + y * (u4 + y * u5)))));
9017 p2 = 1.0f + y * (v1 + y * (v2 + y * (v3 + y * (v4 + y * v5))));
9018 r += -0.5f * y + p1 / p2;
9020 } else if (ix < 0x41000000) { /* x < 8.0 */
9021 i = (int)x;
9022 y = x - (float)i;
9023 p = y * (s0 + y * (s1 + y * (s2 + y * (s3 + y * (s4 + y * (s5 + y * s6))))));
9024 q = 1.0f + y * (r1 + y * (r2 + y * (r3 + y * (r4 + y * (r5 + y * r6)))));
9025 r = 0.5f * y + p / q;
9026 z = 1.0f; /* lgamma(1+s) = log(s) + lgamma(s) */
9027 switch (i) {
9028 case 7: z *= y + 6.0f; /* fall through */
9029 case 6: z *= y + 5.0f; /* fall through */
9030 case 5: z *= y + 4.0f; /* fall through */
9031 case 4: z *= y + 3.0f; /* fall through */
9032 case 3:
9033 z *= y + 2.0f;
9034 r += logf(z);
9035 break;
9037 } else if (ix < 0x5c800000) { /* 8.0 <= x < 2**58 */
9038 t = logf(x);
9039 z = 1.0f / x;
9040 y = z * z;
9041 w = w0 + z * (w1 + y * (w2 + y * (w3 + y * (w4 + y * (w5 + y * w6)))));
9042 r = (x - 0.5f) * (t - 1.0f) + w;
9043 } else /* 2**58 <= x <= inf */
9044 r = x * (logf(x) - 1.0f);
9045 if (sign)
9046 r = nadj - r;
9047 return r;
9050 /*********************************************************************
9051 * tgamma (MSVCR120.@)
9053 double CDECL tgamma(double x)
9055 return unix_funcs->tgamma( x );
9058 /*********************************************************************
9059 * tgammaf (MSVCR120.@)
9061 float CDECL tgammaf(float x)
9063 return unix_funcs->tgammaf( x );
9066 /*********************************************************************
9067 * nan (MSVCR120.@)
9069 double CDECL nan(const char *tagp)
9071 /* Windows ignores input (MSDN) */
9072 return NAN;
9075 /*********************************************************************
9076 * nanf (MSVCR120.@)
9078 float CDECL nanf(const char *tagp)
9080 return NAN;
9083 /*********************************************************************
9084 * _except1 (MSVCR120.@)
9085 * TODO:
9086 * - find meaning of ignored cw and operation bits
9087 * - unk parameter
9089 double CDECL _except1(DWORD fpe, _FP_OPERATION_CODE op, double arg, double res, DWORD cw, void *unk)
9091 ULONG_PTR exception_arg;
9092 DWORD exception = 0;
9093 DWORD fpword = 0;
9094 WORD operation;
9095 int raise = 0;
9097 TRACE("(%x %x %lf %lf %x %p)\n", fpe, op, arg, res, cw, unk);
9099 #ifdef _WIN64
9100 cw = ((cw >> 7) & 0x3f) | ((cw >> 3) & 0xc00);
9101 #endif
9102 operation = op << 5;
9103 exception_arg = (ULONG_PTR)&operation;
9105 if (fpe & 0x1) { /* overflow */
9106 if ((fpe == 0x1 && (cw & 0x8)) || (fpe==0x11 && (cw & 0x28))) {
9107 /* 32-bit version also sets SW_INEXACT here */
9108 raise |= FE_OVERFLOW;
9109 if (fpe & 0x10) raise |= FE_INEXACT;
9110 res = signbit(res) ? -INFINITY : INFINITY;
9111 } else {
9112 exception = EXCEPTION_FLT_OVERFLOW;
9114 } else if (fpe & 0x2) { /* underflow */
9115 if ((fpe == 0x2 && (cw & 0x10)) || (fpe==0x12 && (cw & 0x30))) {
9116 raise |= FE_UNDERFLOW;
9117 if (fpe & 0x10) raise |= FE_INEXACT;
9118 res = signbit(res) ? -0.0 : 0.0;
9119 } else {
9120 exception = EXCEPTION_FLT_UNDERFLOW;
9122 } else if (fpe & 0x4) { /* zerodivide */
9123 if ((fpe == 0x4 && (cw & 0x4)) || (fpe==0x14 && (cw & 0x24))) {
9124 raise |= FE_DIVBYZERO;
9125 if (fpe & 0x10) raise |= FE_INEXACT;
9126 } else {
9127 exception = EXCEPTION_FLT_DIVIDE_BY_ZERO;
9129 } else if (fpe & 0x8) { /* invalid */
9130 if (fpe == 0x8 && (cw & 0x1)) {
9131 raise |= FE_INVALID;
9132 } else {
9133 exception = EXCEPTION_FLT_INVALID_OPERATION;
9135 } else if (fpe & 0x10) { /* inexact */
9136 if (fpe == 0x10 && (cw & 0x20)) {
9137 raise |= FE_INEXACT;
9138 } else {
9139 exception = EXCEPTION_FLT_INEXACT_RESULT;
9143 if (exception)
9144 raise = 0;
9145 feraiseexcept(raise);
9146 if (exception)
9147 RaiseException(exception, 0, 1, &exception_arg);
9149 if (cw & 0x1) fpword |= _EM_INVALID;
9150 if (cw & 0x2) fpword |= _EM_DENORMAL;
9151 if (cw & 0x4) fpword |= _EM_ZERODIVIDE;
9152 if (cw & 0x8) fpword |= _EM_OVERFLOW;
9153 if (cw & 0x10) fpword |= _EM_UNDERFLOW;
9154 if (cw & 0x20) fpword |= _EM_INEXACT;
9155 switch (cw & 0xc00)
9157 case 0xc00: fpword |= _RC_UP|_RC_DOWN; break;
9158 case 0x800: fpword |= _RC_UP; break;
9159 case 0x400: fpword |= _RC_DOWN; break;
9161 switch (cw & 0x300)
9163 case 0x0: fpword |= _PC_24; break;
9164 case 0x200: fpword |= _PC_53; break;
9165 case 0x300: fpword |= _PC_64; break;
9167 if (cw & 0x1000) fpword |= _IC_AFFINE;
9168 _control87(fpword, 0xffffffff);
9170 return res;
9173 _Dcomplex* CDECL _Cbuild(_Dcomplex *ret, double r, double i)
9175 ret->_Val[0] = r;
9176 ret->_Val[1] = i;
9177 return ret;
9180 double CDECL MSVCR120_creal(_Dcomplex z)
9182 return z._Val[0];
9185 /*********************************************************************
9186 * ilogb (MSVCR120.@)
9188 int CDECL ilogb(double x)
9190 return __ilogb(x);
9193 /*********************************************************************
9194 * ilogbf (MSVCR120.@)
9196 int CDECL ilogbf(float x)
9198 return __ilogbf(x);
9200 #endif /* _MSVCR_VER>=120 */