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 * ====================================================
51 #include "wine/debug.h"
53 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt
);
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
;
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
);
78 sse2_enabled
= sse2_supported
;
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
)
90 static inline double fp_barrier(double x
)
92 volatile double y
= x
;
96 static inline double CDECL
ret_nan( BOOL update_sw
)
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" \
111 "andw $~" #MASK ", %ax\n\t" \
112 "movw %ax, 2(%esp)\n\t" \
113 "fldcw 2(%esp)\n\t" \
116 #define RESET_X87_CW \
117 "movw (%esp), %ax\n\t" \
118 "cmpw %ax, 2(%esp)\n\t" \
120 "fstpl 8(%esp)\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
)
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
;
149 /* don't set errno */
159 /* don't set errno */
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
;
188 /*********************************************************************
189 * _get_FMA3_enable (UCRTBASE.@)
191 int CDECL
_get_FMA3_enable(void)
199 /*********************************************************************
200 * _set_FMA3_enable (MSVCR120.@)
202 int CDECL
_set_FMA3_enable(int flag
)
204 FIXME("(%x) stub\n", flag
);
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
};
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
};
231 ux
.i
|= uy
.i
& 0x80000000;
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
))
249 if (_fpclassf(y
) & (_FPCLASS_ND
| _FPCLASS_PD
| _FPCLASS_NZ
| _FPCLASS_PZ
))
253 ax
= ix
& 0x7fffffff;
254 ay
= iy
& 0x7fffffff;
258 ix
= (iy
& 0x80000000) | 1;
259 } else if (ax
> ay
|| ((ix
^ iy
) & 0x80000000))
264 /* raise overflow if ix is infinite and x is finite */
265 if (e
== 0x7f800000) {
269 /* raise underflow if ix is subnormal or zero */
272 fp_barrierf(x
* x
+ y
* 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;
287 if (u
.i
== 0) return FP_ILOGB0
;
289 for (e
= -0x7f; u
.i
>> 31 == 0; e
--, u
.i
<<= 1);
292 if (e
== 0xff) return u
.i
<< 9 ? FP_ILOGBNAN
: INT_MAX
;
296 /*********************************************************************
299 * Copied from musl: src/math/logbf.c
301 float CDECL
_logbf(float x
)
314 /* Copied from musl: src/math/scalbn.c */
315 static double __scalbn(double x
, int n
)
317 union {double f
; UINT64 i
;} u
;
329 } else if (n
< -1022) {
330 /* make sure final n < -53 to avoid double
331 rounding in the subnormal range */
332 y
*= 0x1p
-1022 * 0x1p
53;
335 y
*= 0x1p
-1022 * 0x1p
53;
341 u
.i
= (UINT64
)(0x3ff + n
) << 52;
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];
381 /* determine jx,jv,q0, note that 3>q0 */
385 q0
= e0
- 24 * (jv
+ 1);
387 /* set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+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
];
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
- 0x1p
24 * fw
);
410 z
= __scalbn(z
, q0
); /* actual value of z */
411 z
-= 8.0 * floor(z
* 0.125); /* trim off integer >= 8 */
415 if (q0
> 0) { /* need iq[jz-1] to determine n */
416 i
= iq
[jz
- 1] >> (24 - q0
);
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 */
427 for (i
= 0; i
< jz
; i
++) { /* compute 1-q */
432 iq
[i
] = 0x1000000 - j
;
435 iq
[i
] = 0xffffff - j
;
437 if (q0
> 0) { /* rare case: chance is 1 in 12 */
440 iq
[jz
- 1] &= 0x7fffff;
443 iq
[jz
- 1] &= 0x3fffff;
450 z
-= __scalbn(1.0, q0
);
454 /* check if recomputation is needed */
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
];
472 /* chop off zero terms */
476 while (iq
[jz
] == 0) {
480 } else { /* break z into 24-bit if necessary */
481 z
= __scalbn(z
, -q0
);
483 fw
= (double)(INT32
)(0x1p
-24 * z
);
484 iq
[jz
] = (INT32
)(z
- 0x1p
24 * fw
);
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
];
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
];
506 /* compress fq[] into y[] */
510 for (i
= jz
; i
>= 0; i
--)
512 y
[0] = ih
== 0 ? fw
: -fw
;
517 for (i
= jz
; i
>= 0; i
--)
520 y
[0] = ih
==0 ? fw
: -fw
;
522 for (i
= 1; i
<= jz
; i
++)
524 y
[1] = ih
== 0 ? fw
: -fw
;
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
;
532 for (i
= jz
; i
> 1; i
--) {
533 fw
= fq
[i
- 1] + fq
[i
];
534 fq
[i
] += fq
[i
- 1] - fw
;
537 for (fw
= 0.0, i
= jz
; i
>= 2; i
--)
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
;
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 */
590 k
= invln2
* x
+ (sign
? -0.5f
: 0.5f
);
592 hi
= x
- t
* ln2_hi
; /* t*ln2_hi is exact here */
597 } else if (hx
< 0x33000000) { /* when |x|<2**-25, return x */
604 /* x is now in primary range */
607 r1
= 1.0f
+ hxs
* (Q1
+ hxs
* Q2
);
609 e
= hxs
* ((r1
- t
) / (6.0f
- x
* t
));
610 if (k
== 0) /* c is 0 */
611 return x
- (x
* e
- hxs
);
614 /* exp(x) ~ 2^k (x_reduced - e + 1) */
616 return 0.5f
* (x
- e
) - 0.5f
;
619 return -2.0f
* (e
- (x
+ 0.5f
));
620 return 1.0f
+ 2.0f
* (x
- e
);
622 u
.i
= (0x7f + k
) << 23; /* 2^k */
624 if (k
< 0 || k
> 56) { /* suffice to return exp(x)-1 */
627 y
= y
* 2.0f
* 0x1p
127f
;
632 u
.i
= (0x7f-k
) << 23; /* 2^-k */
634 y
= (x
- e
+ (1 - u
.f
)) * twopk
;
636 y
= (x
- (e
+ u
.f
) + 1) * twopk
;
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;
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;
669 return ((1.0 + z
* C0
) + w
* C1
) + (w
* z
) * r
;
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;
687 if (u
.i
<< 1) return s
? _FPCLASS_ND
: _FPCLASS_PD
;
688 return s
? _FPCLASS_NZ
: _FPCLASS_PZ
;
690 if (u
.i
<< 9) return ((u
.i
>> 22) & 1) ? _FPCLASS_QNAN
: _FPCLASS_SNAN
;
691 return s
? _FPCLASS_NINF
: _FPCLASS_PINF
;
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 /*********************************************************************
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;
725 p
= z
* (p1
+ z
* (p2
+ z
* (p3
+ z
* p4
)));
730 /*********************************************************************
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
;
742 hx
= *(unsigned int*)&x
;
743 ix
= hx
& 0x7fffffff;
744 /* |x| >= 1 or nan */
745 if (ix
>= 0x3f800000) {
746 if (ix
== 0x3f800000) {
751 if (isnan(x
)) return x
;
752 return math_error(_DOMAIN
, "acosf", x
, 0, 0 / (x
- x
));
755 if (ix
< 0x3f000000) {
756 if (ix
<= 0x32800000) /* |x| < 2**-26 */
758 return M_PI_2
- (x
- (pio2_lo
- x
* asinf_R(x
* x
)));
764 return M_PI
- 2 * (s
+ ((double)s
* asinf_R(z
)));
769 hx
= *(unsigned int*)&s
& 0xffff0000;
771 c
= (z
- df
* df
) / (s
+ df
);
772 w
= asinf_R(z
) * s
+ c
;
776 /*********************************************************************
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;
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)
802 return x
+ x
* asinf_R(x
* x
);
805 z
= (1 - fabsf(x
)) * 0.5f
;
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
));
816 /*********************************************************************
819 * Copied from musl: src/math/atanf.c
821 float CDECL
atanf( float x
)
823 static const float atanhi
[] = {
829 static const float atanlo
[] = {
835 static const float aT
[] = {
844 unsigned int ix
, sign
;
848 if (isnan(x
)) return math_error(_DOMAIN
, "atanf", x
, 0, x
);
851 ix
= *(unsigned int*)&x
;
854 if (ix
>= 0x4c800000) { /* if |x| >= 2**26 */
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 */
863 /* raise underflow for subnormal x */
870 if (ix
< 0x3f980000) { /* |x| < 1.1875 */
871 if (ix
< 0x3f300000) { /* 7/16 <= |x| < 11/16 */
873 x
= (2.0f
* x
- 1.0f
) / (2.0f
+ x
);
874 } else { /* 11/16 <= |x| < 19/16 */
876 x
= (x
- 1.0f
) / (x
+ 1.0f
);
879 if (ix
< 0x401c0000) { /* |x| < 2.4375 */
881 x
= (x
- 1.5f
) / (1.0f
+ 1.5f
* x
);
882 } else { /* 2.4375 <= |x| < 2**26 */
888 /* end of argument reduction */
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]);
895 return x
- x
* (s1
+ s2
);
896 z
= atanhi
[id
] - ((x
* (s1
+ s2
) - atanlo
[id
]) - x
);
897 return sign
? -z
: z
;
900 /*********************************************************************
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;
911 unsigned int m
, ix
, iy
;
913 if (isnan(x
) || isnan(y
))
915 ix
= *(unsigned int*)&x
;
916 iy
= *(unsigned int*)&y
;
917 if (ix
== 0x3f800000) /* x=1.0 */
919 m
= ((iy
>> 31) & 1) | ((ix
>> 30) & 2); /* 2*sign(x)+sign(y) */
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 */
934 return m
& 1 ? -pi
/ 2 : pi
/ 2;
936 if (ix
== 0x7f800000) {
937 if (iy
== 0x7f800000) {
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)*/
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) */
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 */
961 z
= atanf(fabsf(y
/ x
));
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
;
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
;
991 *y
= x
- fn
* pio2_1
- fn
* pio2_1t
;
992 /* Matters with directed rounding. */
996 *y
= x
- fn
* pio2_1
- fn
* pio2_1t
;
997 } else if (*y
> pio4
) {
1000 *y
= x
- fn
* pio2_1
- fn
* pio2_1t
;
1004 if(ix
>= 0x7f800000) { /* x is inf or NaN */
1008 /* scale x into [2^23, 2^24-1] */
1010 e0
= (ix
>> 23) - (0x7f + 23); /* e0 = ilogb(|x|)-23, positive */
1011 u
.i
= ix
- (e0
<< 23);
1013 n
= __rem_pio2_large(tx
, ty
, e0
, 1, 0);
1022 /*********************************************************************
1025 * Copied from musl: src/math/cosf.c
1027 float CDECL
cosf( float x
)
1029 static const double c1pio2
= 1*M_PI_2
,
1042 if (ix
<= 0x3f490fda) { /* |x| ~<= pi/4 */
1043 if (ix
< 0x39800000) { /* |x| < 2**-12 */
1044 /* raise inexact if x != 0 */
1045 fp_barrierf(x
+ 0x1p
120f
);
1050 if (ix
<= 0x407b53d1) { /* |x| ~<= 5*pi/4 */
1051 if (ix
> 0x4016cbe3) /* |x| ~> 3*pi/4 */
1052 return -__cosdf(sign
? x
+ c2pio2
: x
- c2pio2
);
1055 return __sindf(x
+ c1pio2
);
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
);
1065 return __sindf(-x
- c3pio2
);
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)
1076 /* general argument reduction needed */
1077 n
= __rem_pio2f(x
, &y
);
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
;
1093 *(UINT32
*)&scale
= (UINT32
)(0x7f + k
/2) << 23;
1094 return expf(x
- kln2
) * (sign
* scale
) * scale
;
1097 /*********************************************************************
1100 * Copied from musl: src/math/coshf.c
1102 float CDECL
coshf( float x
)
1104 UINT32 ui
= *(UINT32
*)&x
;
1112 if (ui
< 0x3f317217) {
1113 if (ui
< 0x3f800000 - (12 << 23)) {
1114 fp_barrierf(x
+ 0x1p
120f
);
1118 return 1 + t
* t
/ (2 * (1 + t
));
1121 /* |x| < log(FLT_MAX) */
1122 if (ui
< 0x42b17217) {
1124 return 0.5f
* (t
+ 1 / t
);
1127 /* |x| > log(FLT_MAX) or nan */
1128 t
= __expo2f(x
, 1.0f
);
1132 /*********************************************************************
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
);
1144 /*********************************************************************
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;
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)
1167 /* normalize x and y */
1169 for (i
= xi
<< 9; i
>> 31 == 0; ex
--, i
<<= 1);
1176 for (i
= yi
<< 9; i
>> 31 == 0; ey
--, i
<<= 1);
1184 for (; ex
> ey
; ex
--) {
1199 for (; xi
>>23 == 0; xi
<<= 1, ex
--);
1201 /* scale result up */
1204 xi
|= (UINT32
)ex
<< 23;
1209 return *(float*)&xi
;
1212 /*********************************************************************
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 {
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 },
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
;
1251 /* Fix sign of zero with downward rounding when x==1. */
1252 if (ix
== 0x3f800000)
1254 if (ix
- 0x00800000 >= 0x7f800000 - 0x00800000) {
1255 /* x < 0x1p-126 or inf or nan. */
1257 return math_error(_SING
, "logf", x
, 0, (ix
& 0x80000000 ? 1.0 : -1.0) / x
);
1258 if (ix
== 0x7f800000) /* log(inf) == inf. */
1260 if (ix
* 2 > 0xff000000)
1262 if (ix
& 0x80000000)
1263 return math_error(_DOMAIN
, "logf", x
, 0, (x
- x
) / (x
- x
));
1264 /* x is subnormal, normalize it. */
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));
1281 /* log(x) = log1p(z/c-1) + log(c) + k*Ln2 */
1283 y0
= logc
+ (double)k
* Ln2
;
1285 /* Pipelined polynomial evaluation to approximate log1p(r). */
1287 y
= A
[1] * r
+ A
[2];
1289 y
= y
* r2
+ (y0
+ r
);
1293 /*********************************************************************
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
;
1314 if (ix
< 0x00800000 || ix
>> 31) { /* x < 2**-126 */
1316 return math_error(_SING
, "log10f", x
, 0, -1 / (x
* x
));
1317 if ((ix
& ~(1u << 31)) > 0x7f800000)
1320 return math_error(_DOMAIN
, "log10f", x
, 0, (x
- x
) / (x
- x
));
1321 /* subnormal number, scale up x */
1326 } else if (ix
>= 0x7f800000) {
1328 } else if (ix
== 0x3f800000)
1331 /* reduce x into [sqrt(2)/2, sqrt(2)] */
1332 ix
+= 0x3f800000 - 0x3f3504f3;
1333 k
+= (int)(ix
>> 23) - 0x7f;
1334 ix
= (ix
& 0x007fffff) + 0x3f3504f3;
1342 t1
= w
* (Lg2
+ w
* Lg4
);
1343 t2
= z
* (Lg1
+ w
* Lg3
);
1345 hfsq
= 0.5f
* f
* f
;
1351 lo
= f
- hi
- hfsq
+ s
* (hfsq
+ R
);
1353 return dk
* log10_2lo
+ (lo
+ hi
) * ivln10lo
+ lo
* ivln10hi
+ hi
* ivln10hi
+ dk
* log10_2hi
;
1356 /*********************************************************************
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
);
1369 /*********************************************************************
1372 * Copied from musl: src/math/sinf.c
1374 float CDECL
sinf( float x
)
1376 static const double s1pio2
= 1*M_PI_2
,
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
/ 0x1p
120f
: x
+ 0x1p
120f
);
1397 if (ix
<= 0x407b53d1) { /* |x| ~<= 5*pi/4 */
1398 if (ix
<= 0x4016cbe3) { /* |x| ~<= 3pi/4 */
1400 return -__cosdf(x
+ s1pio2
);
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 */
1409 return __cosdf(x
+ s3pio2
);
1411 return -__cosdf(x
- s3pio2
);
1413 return __sindf(sign
? x
+ s4pio2
: x
- s4pio2
);
1416 /* sin(Inf or NaN) is NaN */
1418 return math_error(_DOMAIN
, "sinf", x
, 0, x
- x
);
1419 if (ix
>= 0x7f800000)
1422 /* general argument reduction needed */
1423 n
= __rem_pio2f(x
, &y
);
1425 case 0: return __sindf(y
);
1426 case 1: return __cosdf(y
);
1427 case 2: return __sindf(-y
);
1428 default: return -__cosdf(y
);
1432 /*********************************************************************
1435 float CDECL
sinhf( float x
)
1437 UINT32 ui
= *(UINT32
*)&x
;
1445 absx
= *(float*)&ui
;
1447 /* |x| < log(FLT_MAX) */
1448 if (ui
< 0x42b17217) {
1450 if (ui
< 0x3f800000) {
1451 if (ui
< 0x3f800000 - (12 << 23))
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
);
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
;
1471 *x
= math_error(_DOMAIN
, "sqrtf", *x
, 0, ret_nan(TRUE
));
1474 if (c
== FP_INFINITE
) return FALSE
;
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"
1485 /*********************************************************************
1488 * Copied from musl: src/math/sqrtf.c
1490 float CDECL
sqrtf( float x
)
1493 if (!sqrtf_validate(&x
))
1496 return sse2_sqrtf(x
);
1498 static const float tiny
= 1.0e-30;
1506 if (!sqrtf_validate(&x
))
1511 if (m
== 0) { /* subnormal x */
1512 for (i
= 0; (ix
& 0x00800000) == 0; i
++)
1516 m
-= 127; /* unbias exponent */
1517 ix
= (ix
& 0x007fffff) | 0x00800000;
1518 if (m
& 1) /* odd m, double x to make it even */
1520 m
>>= 1; /* m = [m/2] */
1522 /* generate sqrt(x) bit by bit */
1524 q
= s
= 0; /* q = sqrt(x) */
1525 r
= 0x01000000; /* r = moving bit from right to left */
1538 /* use floating add to find out rounding direction */
1540 z
= 1.0f
- tiny
; /* raise inexact flag */
1549 ix
= (q
>> 1) + 0x3f000000;
1550 r
= ix
+ ((unsigned int)m
<< 23);
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
;
1571 r
= T
[4] + z
* T
[5];
1572 t
= T
[2] + z
* T
[3];
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 /*********************************************************************
1583 * Copied from musl: src/math/tanf.c
1585 float CDECL
tanf( float x
)
1587 static const double t1pio2
= 1*M_PI_2
,
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
/ 0x1p
120f
: x
+ 0x1p
120f
);
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);
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);
1618 return __tandf((sign
? x
+ t4pio2
: x
- t4pio2
), 0);
1621 /* tan(Inf or NaN) is NaN */
1623 return math_error(_DOMAIN
, "tanf", x
, 0, x
- x
);
1624 if (ix
>= 0x7f800000)
1627 /* argument reduction */
1628 n
= __rem_pio2f(x
, &y
);
1629 return __tandf(y
, n
& 1);
1632 /*********************************************************************
1635 float CDECL
tanhf( float x
)
1637 UINT32 ui
= *(UINT32
*)&x
;
1646 if (ui
> 0x3f0c9f54) {
1647 /* |x| > log(3)/2 ~= 0.5493 or nan */
1648 if (ui
> 0x41200000) {
1649 #if _MSVCR_VER < 140
1651 return math_error(_DOMAIN
, "tanhf", x
, 0, x
);
1654 fp_barrierf(x
+ 0x1p
120f
);
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
);
1664 } else if (ui
>= 0x00800000) {
1665 /* |x| >= 0x1p-126 */
1666 t
= __expm1f(-2 * x
);
1669 /* |x| is subnormal */
1673 return sign
? -t
: t
;
1676 /*********************************************************************
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;
1690 m
= 0x007fffff >> e
;
1705 /*********************************************************************
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;
1719 m
= 0x007fffff >> e
;
1734 /*********************************************************************
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;
1746 x
= frexpf(x
* 0x1p
64, e
);
1750 } else if (ee
== 0xff) {
1757 return *(float*)&ux
;
1760 /*********************************************************************
1763 * Copied from musl: src/math/modff.c
1765 float CDECL
modff( float x
, float *iptr
)
1767 union {float f
; UINT32 i
;} u
= {x
};
1769 int e
= (u
.i
>> 23 & 0xff) - 0x7f;
1771 /* no fractional part */
1774 if (e
== 0x80 && u
.i
<< 9 != 0) { /* nan */
1780 /* no integral part */
1787 mask
= 0x007fffff >> e
;
1788 if ((u
.i
& mask
) == 0) {
1800 #if !defined(__i386__) && !defined(__x86_64__) && (_MSVCR_VER == 0 || _MSVCR_VER >= 110)
1802 /*********************************************************************
1805 * Copied from musl: src/math/fabsf.c
1807 float CDECL
fabsf( float x
)
1809 union { float f
; UINT32 i
; } u
= { x
};
1816 /*********************************************************************
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;
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
)));
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
;
1849 hx
= *(ULONGLONG
*)&x
>> 32;
1850 ix
= hx
& 0x7fffffff;
1851 /* |x| >= 1 or nan */
1852 if (ix
>= 0x3ff00000) {
1855 lx
= *(ULONGLONG
*)&x
;
1856 if (((ix
- 0x3ff00000) | lx
) == 0) {
1857 /* acos(1)=0, acos(-1)=pi */
1859 return 2 * pio2_hi
+ 7.5231638452626401e-37;
1862 if (isnan(x
)) return x
;
1863 return math_error(_DOMAIN
, "acos", x
, 0, 0 / (x
- x
));
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
)));
1873 z
= (1.0 + x
) * 0.5;
1875 w
= acos_R(z
) * s
- pio2_lo
;
1876 return 2 * (pio2_hi
- (s
+ w
));
1879 z
= (1.0 - x
) * 0.5;
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 /*********************************************************************
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;
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
)));
1915 double CDECL
x87_asin(double);
1916 __ASM_GLOBAL_FUNC( x87_asin
,
1931 double CDECL
asin( double x
)
1933 static const double pio2_hi
= 1.57079632679489655800e+00,
1934 pio2_lo
= 6.12323399573676603587e-17;
1937 unsigned int hx
, ix
;
1940 unsigned int x87_cw
, sse2_cw
;
1943 hx
= *(ULONGLONG
*)&x
>> 32;
1944 ix
= hx
& 0x7fffffff;
1945 /* |x| >= 1 or nan */
1946 if (ix
>= 0x3ff00000) {
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;
1955 return math_error(_DOMAIN
, "asin", x
, 0, x
);
1960 return math_error(_DOMAIN
, "asin", x
, 0, 0 / (x
- x
));
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
)
1971 if (ix
< 0x3fe00000) {
1972 /* if 0x1p-1022 <= |x| < 0x1p-26, avoid raising underflow */
1973 if (ix
< 0x3e500000 && ix
>= 0x00100000)
1975 return x
+ x
* asin_R(x
* x
);
1977 /* 1 > |x| >= 0.5 */
1978 z
= (1 - fabs(x
)) * 0.5;
1981 if (ix
>= 0x3fef3333) { /* if |x| > 0.975 */
1982 x
= pio2_hi
- (2 * (s
+ s
* r
) - pio2_lo
);
1987 llx
= (*(ULONGLONG
*)&f
>> 32) << 32;
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
));
1997 /*********************************************************************
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
;
2035 if (isnan(x
)) return math_error(_DOMAIN
, "atan", x
, 0, x
);
2038 ix
= *(ULONGLONG
*)&x
>> 32;
2041 if (ix
>= 0x44100000) { /* if |x| >= 2^66 */
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
);
2057 if (ix
< 0x3ff30000) { /* |x| < 1.1875 */
2058 if (ix
< 0x3fe60000) { /* 7/16 <= |x| < 11/16 */
2060 x
= (2.0 * x
- 1.0) / (2.0 + x
);
2061 } else { /* 11/16 <= |x| < 19/16 */
2063 x
= (x
- 1.0) / (x
+ 1.0);
2066 if (ix
< 0x40038000) { /* |x| < 2.4375 */
2068 x
= (x
- 1.5) / (1.0 + 1.5 * x
);
2069 } else { /* 2.4375 <= |x| < 2^66 */
2075 /* end of argument reduction */
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]))));
2082 return x
- x
* (s1
+ s2
);
2083 z
= atanhi
[id
] - (x
* (s1
+ s2
) - atanlo
[id
] - x
);
2084 return sign
? -z
: z
;
2087 /*********************************************************************
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;
2098 unsigned int m
, lx
, ly
, ix
, iy
;
2100 if (isnan(x
) || isnan(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 */
2108 m
= ((iy
>> 31) & 1) | ((ix
>> 30) & 2); /* 2*sign(x)+sign(y) */
2109 ix
= ix
& 0x7fffffff;
2110 iy
= iy
& 0x7fffffff;
2113 if ((iy
| ly
) == 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 */
2123 return m
& 1 ? -pi
/ 2 : pi
/ 2;
2125 if (ix
== 0x7ff00000) {
2126 if (iy
== 0x7ff00000) {
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) */
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 */
2150 z
= atan(fabs(y
/ x
));
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;
2173 cw
= _controlfp(0, 0);
2174 if ((cw
& _MCW_PC
) != _PC_53
)
2175 _controlfp(_PC_53
, _MCW_PC
);
2177 y
= fp_barrier(x
- toint
) + toint
;
2179 y
= fp_barrier(x
+ toint
) - toint
;
2180 if ((cw
& _MCW_PC
) != _PC_53
)
2181 _controlfp(cw
, _MCW_PC
);
2183 return s
? -0.0 : 0;
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];
2202 int sign
, n
, ex
, ey
, i
;
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 */
2211 z
= x
- pio2_1
; /* one round good to 85 bits */
2213 y
[1] = (z
- y
[0]) - pio2_1t
;
2218 y
[1] = (z
- y
[0]) + pio2_1t
;
2224 y
[0] = z
- 2 * pio2_1t
;
2225 y
[1] = (z
- y
[0]) - 2 * pio2_1t
;
2229 y
[0] = z
+ 2 * pio2_1t
;
2230 y
[1] = (z
- y
[0]) + 2 * pio2_1t
;
2235 if (ix
<= 0x401c463b) { /* |x| ~<= 9pi/4 */
2236 if (ix
<= 0x4015fdbc) { /* |x| ~<= 7pi/4 */
2237 if (ix
== 0x4012d97c) /* |x| ~= 3pi/2 */
2241 y
[0] = z
- 3 * pio2_1t
;
2242 y
[1] = (z
- y
[0]) - 3 * pio2_1t
;
2246 y
[0] = z
+ 3 * pio2_1t
;
2247 y
[1] = (z
- y
[0]) + 3 * pio2_1t
;
2251 if (ix
== 0x401921fb) /* |x| ~= 4pi/2 */
2255 y
[0] = z
- 4 * pio2_1t
;
2256 y
[1] = (z
- y
[0]) - 4 * pio2_1t
;
2260 y
[0] = z
+ 4 * pio2_1t
;
2261 y
[1] = (z
- y
[0]) + 4 * pio2_1t
;
2266 if (ix
< 0x413921fb) { /* |x| ~< 2^20*(pi/2), medium size */
2268 fn
= __rint(x
* invpio2
);
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
) {
2276 r
= x
- fn
* pio2_1
;
2278 } else if (r
- w
> pio4
) {
2281 r
= x
- fn
* pio2_1
;
2286 ey
= u
.i
>> 52 & 0x7ff;
2288 if (ex
- ey
> 16) { /* 2nd round, good to 118 bits */
2292 w
= fn
* pio2_2t
- ((t
- r
) - w
);
2295 ey
= u
.i
>> 52 & 0x7ff;
2296 if (ex
- ey
> 49) { /* 3rd round, good to 151 bits, covers all cases */
2300 w
= fn
* pio2_3t
- ((t
- r
) - w
);
2304 y
[1] = (r
- y
[0]) - w
;
2308 * all other (large) arguments
2310 if (ix
>= 0x7ff00000) { /* x is inf or NaN */
2311 y
[0] = y
[1] = x
- x
;
2314 /* set z = scalbn(|x|,-ilogb(x)+23) */
2316 u
.i
&= (UINT64
)-1 >> 12;
2317 u
.i
|= (UINT64
)(0x3ff + 23) << 52;
2319 for (i
= 0; i
< 2; i
++) {
2320 tx
[i
] = (double)(INT32
)z
;
2321 z
= (z
- tx
[i
]) * 0x1p
24;
2324 /* skip zero terms, first term is non-zero */
2325 while (tx
[i
] == 0.0)
2327 n
= __rem_pio2_large(tx
, ty
, (int)(ix
>> 20) - (0x3ff + 23), i
+ 1, 1);
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;
2352 r
= S2
+ z
* (S3
+ z
* S4
) + z
* w
* (S5
+ z
* S6
);
2355 return x
+ v
* (S1
+ z
* r
);
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;
2373 r
= z
* (C1
+ z
* (C2
+ z
* C3
)) + w
* w
* (C4
+ z
* (C5
+ z
* C6
));
2376 return w
+ (((1.0 - w
) - hz
) + (z
* r
- x
* y
));
2379 /*********************************************************************
2382 * Copied from musl: src/math/cos.c
2384 double CDECL
cos( double x
)
2390 ix
= *(ULONGLONG
*)&x
>> 32;
2394 if (ix
<= 0x3fe921fb) {
2395 if (ix
< 0x3e46a09e) { /* |x| < 2**-27 * sqrt(2) */
2396 /* raise inexact if x!=0 */
2397 fp_barrier(x
+ 0x1p
120f
);
2403 /* cos(Inf or NaN) is NaN */
2404 if (isinf(x
)) return math_error(_DOMAIN
, "cos", x
, 0, x
- x
);
2405 if (ix
>= 0x7ff00000)
2408 /* argument reduction */
2409 n
= __rem_pio2(x
, y
);
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 */
2441 return sign
? -1 : x
;
2443 return math_error(_UNDERFLOW
, "exp", x
, 0, -1);
2444 if (x
> o_threshold
)
2445 return math_error(_OVERFLOW
, "exp", x
, 0, x
* 0x1p
1023);
2448 /* argument reduction */
2449 if (hx
> 0x3fd62e42) { /* if |x| > 0.5 ln2 */
2450 if (hx
< 0x3FF0A2B2) { /* and |x| < 1.5 ln2 */
2461 k
= invln2
* x
+ (sign
? -0.5 : 0.5);
2463 hi
= x
- t
* ln2_hi
; /* t*ln2_hi is exact here */
2468 } else if (hx
< 0x3c900000) { /* |x| < 2**-54, return x */
2469 fp_barrier(x
+ 0x1p
120f
);
2470 if (hx
< 0x00100000)
2471 fp_barrier((float)x
);
2476 /* x is now in primary range */
2479 r1
= 1.0 + hxs
* (Q1
+ hxs
* (Q2
+ hxs
* (Q3
+ hxs
* (Q4
+ hxs
* Q5
))));
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
;
2486 /* exp(x) ~ 2^k (x_reduced - e + 1) */
2488 return 0.5 * (x
- e
) - 0.5;
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 */
2496 if (k
< 0 || k
> 56) { /* suffice to return exp(x)-1 */
2499 y
= y
* 2.0 * 0x1p
1023;
2504 u
.i
= (UINT64
)(0x3ff - k
) << 52; /* 2^-k */
2506 y
= (x
- e
+ (1 - u
.f
)) * twopk
;
2508 y
= (x
- (e
+ u
.f
) + 1) * twopk
;
2512 static double __expo2(double x
, double sign
)
2514 static const int k
= 2043;
2515 static const double kln2
= 0x1.62066151add8bp
+10;
2518 *(UINT64
*)&scale
= (UINT64
)(0x3ff + k
/ 2) << 52;
2519 return exp(x
- kln2
) * (sign
* scale
) * scale
;
2522 /*********************************************************************
2525 * Copied from musl: src/math/cosh.c
2527 double CDECL
cosh( double x
)
2529 UINT64 ux
= *(UINT64
*)&x
;
2534 ux
&= (uint64_t)-1 / 2;
2539 if (w
< 0x3fe62e42) {
2540 if (w
< 0x3ff00000 - (26 << 20)) {
2541 fp_barrier(x
+ 0x1p
120f
);
2545 return 1 + t
* t
/ (2 * (1 + t
));
2548 /* |x| < log(DBL_MAX) */
2549 if (w
< 0x40862e42) {
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);
2561 /*********************************************************************
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
);
2573 /*********************************************************************
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;
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)
2596 /* normalize x and y */
2598 for (i
= xi
<< 12; i
>> 63 == 0; ex
--, i
<<= 1);
2605 for (i
= yi
<< 12; i
>> 63 == 0; ey
--, i
<<= 1);
2613 for (; ex
> ey
; ex
--) {
2628 for (; xi
>> 52 == 0; xi
<<= 1, ex
--);
2633 xi
|= (UINT64
)ex
<< 52;
2637 xi
|= (UINT64
)sx
<< 63;
2638 return *(double*)&xi
;
2641 /*********************************************************************
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
[] = {
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 {
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 {
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
;
2942 if (ix
- 0x3fee000000000000ULL
< 0x3090000000000ULL
) {
2945 /* Handle close to 1.0 inputs separately. */
2946 /* Fix sign of zero with downward rounding when x==1. */
2947 if (ix
== 0x3ff0000000000000ULL
)
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. */
2958 w
= rhi
* rhi
* B
[0]; /* B[0] == -0.5. */
2961 lo
+= B
[0] * rlo
* (rhi
+ r
);
2966 if (top
- 0x0010 >= 0x7ff0 - 0x0010) {
2967 /* x < 0x1p-1022 or inf or nan. */
2969 return math_error(_SING
, "log", x
, 0, (top
& 0x8000 ? 1.0 : -1.0) / x
);
2970 if (ix
== 0x7ff0000000000000ULL
) /* log(inf) == inf. */
2972 if ((top
& 0x7ff0) == 0x7ff0 && (ix
& 0xfffffffffffffULL
))
2975 return math_error(_DOMAIN
, "log", x
, 0, (x
- x
) / (x
- x
));
2976 /* x is subnormal, normalize it. */
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);
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
;
2998 /* hi + lo = r + log(c) + k*Ln2. */
2999 w
= kd
* Ln2hi
+ logc
;
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
;
3014 /*********************************************************************
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
;
3038 if (hx
< 0x00100000 || hx
>> 31) {
3040 return math_error(_SING
, "log10", x
, 0, -1 / (x
* x
));
3041 if ((u
.i
& ~(1ULL << 63)) > 0x7ff0000000000000ULL
)
3044 return math_error(_DOMAIN
, "log10", x
, 0, (x
- x
) / (x
- x
));
3045 /* subnormal number, scale x up */
3050 } else if (hx
>= 0x7ff00000) {
3052 } else if (hx
== 0x3ff00000 && u
.i
<<32 == 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);
3067 t1
= w
* (Lg2
+ w
* (Lg4
+ w
* Lg6
));
3068 t2
= z
* (Lg1
+ w
* (Lg3
+ w
* (Lg5
+ w
* Lg7
)));
3071 /* hi+lo = f - hfsq + s*(hfsq+R) ~ log(1+f) */
3074 u
.i
&= (UINT64
)-1 << 32;
3076 lo
= f
- hi
- hfsq
+ s
* (hfsq
+ R
);
3078 /* val_hi+val_lo ~ log10(1+f) + k*log10(2) */
3079 val_hi
= hi
* ivln10hi
;
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.
3091 val_lo
+= (y
- w
) + val_hi
;
3094 return val_lo
+ val_hi
;
3097 /*********************************************************************
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
);
3114 /*********************************************************************
3117 * Copied from musl: src/math/sin.c
3119 double CDECL
sin( double x
)
3125 ix
= *(ULONGLONG
*)&x
>> 32;
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
/0x1p
120f
: x
+0x1p
120f
);
3135 return __sin(x
, 0.0, 0);
3138 /* sin(Inf or NaN) is NaN */
3140 return math_error(_DOMAIN
, "sin", x
, 0, x
- x
);
3141 if (ix
>= 0x7ff00000)
3144 /* argument reduction needed */
3145 n
= __rem_pio2(x
, y
);
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 /*********************************************************************
3157 double CDECL
sinh( double x
)
3159 UINT64 ux
= *(UINT64
*)&x
;
3167 ux
&= (UINT64
)-1 / 2;
3168 absx
= *(double*)&ux
;
3171 /* |x| < log(DBL_MAX) */
3172 if (w
< 0x40862e42) {
3174 if (w
< 0x3ff00000) {
3175 if (w
< 0x3ff00000 - (26 << 20))
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
);
3188 static BOOL
sqrt_validate( double *x
, BOOL update_sw
)
3190 short c
= _dclass(*x
);
3192 if (c
== FP_ZERO
) return FALSE
;
3197 *x
= math_error(_DOMAIN
, "sqrt", *x
, 0, *x
);
3199 /* set signaling bit */
3200 *(ULONGLONG
*)x
|= 0x8000000000000ULL
;
3206 *x
= math_error(_DOMAIN
, "sqrt", *x
, 0, ret_nan(update_sw
));
3209 if (c
== FP_INFINITE
) return FALSE
;
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"
3221 double CDECL
x87_sqrt(double);
3222 __ASM_GLOBAL_FUNC( x87_sqrt
,
3230 /*********************************************************************
3233 * Copied from musl: src/math/sqrt.c
3235 double CDECL
sqrt( double x
)
3238 if (!sqrt_validate(&x
, TRUE
))
3241 return sse2_sqrt(x
);
3242 #elif defined( __i386__ )
3243 if (!sqrt_validate(&x
, TRUE
))
3248 static const double tiny
= 1.0e-300;
3251 int sign
= 0x80000000;
3253 unsigned int r
,t1
,s1
,ix1
,q1
;
3256 if (!sqrt_validate(&x
, TRUE
))
3259 ix
= *(ULONGLONG
*)&x
;
3265 if (m
== 0) { /* subnormal x */
3271 for (i
=0; (ix0
& 0x00100000) == 0; i
++)
3274 ix0
|= ix1
>> (32 - 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);
3283 m
>>= 1; /* m = [m/2] */
3285 /* generate sqrt(x) bit by bit */
3286 ix0
+= ix0
+ ((ix1
& sign
) >> 31);
3288 q
= q1
= s0
= s1
= 0; /* [q,q1] = sqrt(x) */
3289 r
= 0x00200000; /* r = moving bit from right to left */
3298 ix0
+= ix0
+ ((ix1
& sign
) >> 31);
3307 if (t
< ix0
|| (t
== ix0
&& t1
<= ix1
)) {
3309 if ((t1
&sign
) == sign
&& (s1
& sign
) == 0)
3317 ix0
+= ix0
+ ((ix1
& sign
) >> 31);
3322 /* use floating add to find out rounding direction */
3323 if ((ix0
| ix1
) != 0) {
3324 z
= 1.0 - tiny
; /* raise inexact flag */
3327 if (q1
== (unsigned int)0xffffffff) {
3330 } else if (z
> 1.0) {
3331 if (q1
== (unsigned int)0xfffffffe)
3338 ix0
= (q
>> 1) + 0x3fe00000;
3342 ix
= ix0
+ ((unsigned int)m
<< 20);
3345 return *(double*)&ix
;
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
;
3374 hx
= *(ULONGLONG
*)&x
>> 32;
3375 big
= (hx
& 0x7fffffff) >= 0x3FE59428; /* |x| >= 0.6744 */
3382 x
= (pio4
- x
) + (pio4lo
- y
);
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])))));
3390 r
= y
+ z
* (s
* (r
+ v
) + y
) + s
* T
[0];
3394 v
= s
- 2.0 * (x
+ (r
- w
* w
/ (w
+ s
)));
3395 return sign
? -v
: v
;
3399 /* -1.0/(x+r) has up to 2ulp error, so compute it accurately */
3401 *(LONGLONG
*)&w0
= *(LONGLONG
*)&w0
& 0xffffffff00000000ULL
;
3402 v
= r
- (w0
- x
); /* w0+v = r+x */
3404 *(LONGLONG
*)&a0
= *(LONGLONG
*)&a0
& 0xffffffff00000000ULL
;
3405 return a0
+ a
* (1.0 + a0
* w0
+ a0
* v
);
3408 /*********************************************************************
3411 * Copied from musl: src/math/tan.c
3413 double CDECL
tan( double x
)
3419 ix
= *(ULONGLONG
*)&x
>> 32;
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
/ 0x1p
120f
: x
+ 0x1p
120f
);
3428 return __tan(x
, 0.0, 0);
3432 return math_error(_DOMAIN
, "tan", x
, 0, x
- x
);
3433 if (ix
>= 0x7ff00000)
3436 n
= __rem_pio2(x
, y
);
3437 return __tan(y
[0], y
[1], n
& 1);
3440 /*********************************************************************
3443 double CDECL
tanh( double x
)
3445 UINT64 ui
= *(UINT64
*)&x
;
3452 ui
&= (UINT64
)-1 / 2;
3456 if (w
> 0x3fe193ea) {
3457 /* |x| > log(3)/2 ~= 0.5493 or nan */
3458 if (w
> 0x40340000) {
3459 #if _MSVCR_VER < 140
3461 return math_error(_DOMAIN
, "tanh", x
, 0, x
);
3463 /* |x| > 20 or nan */
3464 /* note: this branch avoids raising overflow */
3465 fp_barrier(x
+ 0x1p
120f
);
3469 t
= 1 - 2 / (t
+ 2);
3471 } else if (w
> 0x3fd058ae) {
3472 /* |x| > log(5/3)/2 ~= 0.2554 */
3475 } else if (w
>= 0x00100000) {
3476 /* |x| >= 0x1p-1022, up to 2ulp error in [0.1,0.2554] */
3477 t
= __expm1(-2 * x
);
3480 /* |x| is subnormal */
3481 /* note: the branch above would not raise underflow in [0x1p-1023,0x1p-1022) */
3482 fp_barrier((float)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, \
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 */ \
3501 "movl $1, %ecx\n\t" /* empty FPU stack */ \
3505 "and $0x4500, %ax\n\t" \
3506 "cmp $0x4100, %ax\n\t" \
3508 "fstpl (%esp,%ecx,8)\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 */ \
3519 "fldl (%esp,%ecx,8)\n\t" \
3520 "cmpl $0, %ecx\n\t" \
3523 __ASM_CFI(".cfi_def_cfa %esp,4\n\t") \
3524 __ASM_CFI(".cfi_same_value %ebp\n\t") \
3527 #define CREATE_FPU_FUNC2(name, call) \
3528 __ASM_GLOBAL_FUNC(name, \
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 */ \
3537 "fstpl (%esp)\n\t" \
3539 "movl $2, %ecx\n\t" /* empty FPU stack */ \
3543 "and $0x4500, %ax\n\t" \
3544 "cmp $0x4100, %ax\n\t" \
3546 "fstpl (%esp,%ecx,8)\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 */ \
3557 "fldl (%esp,%ecx,8)\n\t" \
3558 "cmpl $1, %ecx\n\t" \
3561 __ASM_CFI(".cfi_def_cfa %esp,4\n\t") \
3562 __ASM_CFI(".cfi_same_value %ebp\n\t") \
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
,
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) */
3590 "mov (%esp), %ax\n\t"
3591 "or $0xc00, %ax\n\t"
3592 "mov %ax, 2(%esp)\n\t"
3594 "fistpq 4(%esp)\n\t"
3596 "movl 4(%esp), %eax\n\t"
3597 "movl 8(%esp), %edx\n\t"
3599 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
3600 __ASM_CFI(".cfi_same_value %ebp\n\t")
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;
3617 if (u
.i
<< 1) return s
? _FPCLASS_ND
: _FPCLASS_PD
;
3618 return s
? _FPCLASS_NZ
: _FPCLASS_PZ
;
3620 if (u
.i
<< 12) return ((u
.i
>> 51) & 1) ? _FPCLASS_QNAN
: _FPCLASS_SNAN
;
3621 return s
? _FPCLASS_NINF
: _FPCLASS_PINF
;
3623 return s
? _FPCLASS_NN
: _FPCLASS_PN
;
3627 /*********************************************************************
3630 unsigned int CDECL
MSVCRT__rotl(unsigned int num
, int shift
)
3633 return (num
<< shift
) | (num
>> (32-shift
));
3636 /*********************************************************************
3639 __msvcrt_ulong CDECL
MSVCRT__lrotl(__msvcrt_ulong num
, int shift
)
3642 return (num
<< shift
) | (num
>> (32-shift
));
3645 /*********************************************************************
3648 __msvcrt_ulong CDECL
MSVCRT__lrotr(__msvcrt_ulong num
, int shift
)
3651 return (num
>> shift
) | (num
<< (32-shift
));
3654 /*********************************************************************
3657 unsigned int CDECL
MSVCRT__rotr(unsigned int num
, int shift
)
3660 return (num
>> shift
) | (num
<< (32-shift
));
3663 /*********************************************************************
3664 * _rotl64 (MSVCRT.@)
3666 unsigned __int64 CDECL
MSVCRT__rotl64(unsigned __int64 num
, int shift
)
3669 return (num
<< shift
) | (num
>> (64-shift
));
3672 /*********************************************************************
3673 * _rotr64 (MSVCRT.@)
3675 unsigned __int64 CDECL
MSVCRT__rotr64(unsigned __int64 num
, int shift
)
3678 return (num
>> shift
) | (num
<< (64-shift
));
3681 /*********************************************************************
3684 int CDECL
abs( int n
)
3686 return n
>= 0 ? n
: -n
;
3689 /*********************************************************************
3692 __msvcrt_long CDECL
labs( __msvcrt_long n
)
3694 return n
>= 0 ? n
: -n
;
3698 /*********************************************************************
3699 * llabs (MSVCR100.@)
3701 __int64 CDECL
llabs( __int64 n
)
3703 return n
>= 0 ? n
: -n
;
3708 /*********************************************************************
3709 * imaxabs (MSVCR120.@)
3711 intmax_t CDECL
imaxabs( intmax_t n
)
3713 return n
>= 0 ? n
: -n
;
3717 /*********************************************************************
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;
3734 if (u
.i
== 0) return FP_ILOGB0
;
3736 for (e
= -0x3ff; u
.i
>> 63 == 0; e
--, u
.i
<<= 1);
3739 if (e
== 0x7ff) return u
.i
<< 12 ? FP_ILOGBNAN
: INT_MAX
;
3743 /*********************************************************************
3746 * Copied from musl: src/math/logb.c
3748 double CDECL
_logb(double x
)
3753 return math_error(_SING
, "_logb", x
, 0, -1 / (x
* x
));
3757 static void sq(double *hi
, double *lo
, double x
)
3761 xc
= x
* (0x1p
27 + 1);
3765 *lo
= xh
* xh
- *hi
+ 2 * xh
* xl
+ xl
* xl
;
3768 /*********************************************************************
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
;
3779 /* arrange |x| >= |y| */
3793 /* note: hypot(inf,nan) == inf */
3796 if (ex
== 0x7ff || uy
== 0)
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 */
3803 /* precise sqrt argument in nearest rounding mode without overflow */
3804 /* xh*xh must not overflow and xl*xl must not underflow in sq */
3806 if (ex
> 0x3ff + 510) {
3810 } else if (ey
< 0x3ff - 450) {
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
;
3840 if (uy
== 0xff << 23)
3842 if (ux
>= 0xff << 23 || uy
== 0 || ux
- uy
>= 25 << 23)
3846 if (ux
>= (0x7f + 60) << 23) {
3850 } else if (uy
< (0x7f - 60) << 23) {
3855 return z
* sqrtf((double)x
* x
+ (double)y
* y
);
3858 /*********************************************************************
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;
3872 m
= 0x000fffffffffffffULL
>> e
;
3887 /*********************************************************************
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;
3901 m
= 0x000fffffffffffffULL
>> e
;
3916 /*********************************************************************
3919 * Copied from musl: src/math/fma.c
3928 static struct fma_num
normalize(double x
)
3930 UINT64 ix
= *(UINT64
*)&x
;
3932 int sign
= e
& 0x800;
3939 e
= ix
>> 52 & 0x7ff;
3940 e
= e
? e
- 63 : 0x800;
3942 ix
&= (1ull << 52) - 1;
3945 e
-= 0x3ff + 52 + 1;
3953 static void mul(UINT64
*hi
, UINT64
*lo
, UINT64 x
, UINT64 y
)
3956 UINT64 xlo
= (UINT32
)x
, xhi
= x
>> 32;
3957 UINT64 ylo
= (UINT32
)y
, yhi
= y
>> 32;
3960 t2
= xlo
* yhi
+ xhi
* ylo
;
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
;
3974 /* normalize so top 10bits and last bit are 0 */
3979 if (nx
.e
>= 0x7ff - 0x3ff - 52 - 1 || ny
.e
>= 0x7ff - 0x3ff - 52 - 1) {
3981 if (!isnan(x
) && !isnan(y
) && !isnan(z
) && isnan(r
)) *_errno() = EDOM
;
3984 if (nz
.e
>= 0x7ff - 0x3ff - 52 - 1) {
3985 if (nz
.e
> 0x7ff - 0x3ff - 52 - 1) {/* z==0 */
3987 if (!isnan(x
) && !isnan(y
) && isnan(r
)) *_errno() = EDOM
;
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 */
4000 /* shift bits z<<=kz, r>>=kr, so kz+kr == d, set e = e+kr (== ez-kz) */
4004 zhi
= nz
.m
>> (64 - d
);
4011 rlo
= rhi
<< (64 - d
) | rlo
>> d
| !!(rlo
<< (64 - d
));
4023 } else if (d
< 64) {
4024 zlo
= nz
.m
>> d
| !!(nz
.m
<< (64 - d
));
4031 sign
= nx
.sign
^ ny
.sign
;
4032 samesign
= !(sign
^ nz
.sign
);
4037 rhi
+= zhi
+ (rlo
< zlo
);
4042 rhi
= rhi
- zhi
- (t
< rlo
);
4051 /* set rhi to top 63bit of the result (last bit is sticky) */
4055 BitScanReverse((DWORD
*)&d
, rhi
>> 32);
4058 BitScanReverse((DWORD
*)&d
, rhi
);
4062 rhi
= rhi
<< d
| rlo
>> (64 - d
) | !!(rlo
<< d
);
4065 BitScanReverse((DWORD
*)&d
, rlo
>> 32);
4068 BitScanReverse((DWORD
*)&d
, rlo
);
4072 rhi
= rlo
>> 1 | (rlo
& 1);
4081 /* convert to double */
4082 i
= rhi
; /* i is in [1<<62,(1<<63)-1] */
4085 r
= i
; /* |r| is in [0x1p62,0x1p63] */
4087 if (e
< -1022 - 62) {
4088 /* result is subnormal before rounding */
4089 if (e
== -1022 - 63) {
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 */
4105 i
= rhi
>> 1 | (rhi
& 1) | 1ull << 62;
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
);
4117 /* only round once when scaled */
4119 i
= (rhi
>> d
| !!(rhi
<< (64 - d
))) << d
;
4125 return __scalbn(r
, e
);
4128 /*********************************************************************
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
;
4140 /*********************************************************************
4143 * Copied from musl: src/math/fabsf.c
4145 double CDECL
fabs( double x
)
4147 union { double f
; UINT64 i
; } u
= { x
};
4152 /*********************************************************************
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;
4164 x
= frexp(x
* 0x1p
64, e
);
4168 } else if (ee
== 0x7ff) {
4173 ux
&= 0x800fffffffffffffull
;
4174 ux
|= 0x3fe0000000000000ull
;
4175 return *(double*)&ux
;
4178 /*********************************************************************
4181 * Copied from musl: src/math/modf.c
4183 double CDECL
modf( double x
, double *iptr
)
4185 union {double f
; UINT64 i
;} u
= {x
};
4187 int e
= (u
.i
>> 52 & 0x7ff) - 0x3ff;
4189 /* no fractional part */
4192 if (e
== 0x400 && u
.i
<< 12 != 0) /* nan */
4198 /* no integral part*/
4205 mask
= -1ULL >> 12 >> e
;
4206 if ((u
.i
& mask
) == 0) {
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__)
4226 unsigned long fpword
;
4230 __asm__
__volatile__( "fstsw %0" : "=m" (fpword
) );
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
;
4241 if (!sse2_sw
) return;
4245 __asm__
__volatile__( "stmxcsr %0" : "=m" (fpword
) );
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
;
4257 FIXME( "not implemented\n" );
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__)
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
;
4285 FIXME( "not implemented\n" );
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
;
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
;
4317 __asm__
__volatile__( "ldmxcsr %0" : : "m" (fpword
) );
4319 #elif defined(__aarch64__)
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
;
4330 __asm__
__volatile__( "msr fpsr, %0" :: "r" (fpsr
) );
4332 FIXME( "not implemented\n" );
4337 /*********************************************************************
4338 * __fpecode (MSVCRT.@)
4340 int * CDECL
__fpecode(void)
4342 return &msvcrt_get_thread_data()->fpecode
;
4345 /*********************************************************************
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
);
4359 /*********************************************************************
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
};
4377 /*********************************************************************
4378 * __control87_2 (MSVCR80.@)
4380 * Not exported by native msvcrt, added in msvcr80.
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
;
4389 unsigned int old_flags
;
4393 __asm__
__volatile__( "fstcw %0" : "=m" (fpword
) );
4395 /* Convert into mask constants */
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
);
4420 flags
= (flags
& ~mask
) | (newval
& mask
);
4422 /* Convert (masked) value back to fp word */
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
) );
4449 if (!sse2_cw
) return 1;
4453 __asm__
__volatile__( "stmxcsr %0" : "=m" (fpword
) );
4455 /* Convert into mask constants */
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
);
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 */
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
) );
4514 FIXME( "not implemented\n" );
4520 /*********************************************************************
4521 * _control87 (MSVCRT.@)
4523 unsigned int CDECL
_control87(unsigned int newval
, unsigned int mask
)
4525 unsigned int flags
= 0;
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
;
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;
4557 mask
&= _MCW_EM
| _MCW_RC
| _MCW_DN
;
4558 flags
= (flags
& ~mask
) | (newval
& mask
);
4559 if (flags
!= old_flags
)
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__)
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
) );
4614 FIXME( "not implemented\n" );
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
|
4644 if (!MSVCRT_CHECK_PMT( !(newval
& mask
& ~all_flags
) ))
4646 if (cur
) *cur
= _controlfp( 0, 0 ); /* retrieve it anyway */
4649 val
= _controlfp( newval
, mask
);
4650 if (cur
) *cur
= val
;
4654 #if _MSVCR_VER >= 140
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
);
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
)
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
);
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());
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();
4775 /*********************************************************************
4776 * feupdateenv (MSVCR120.@)
4778 int CDECL
feupdateenv(const fenv_t
*env
)
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
)
4802 excepts
&= FE_ALL_EXCEPT
;
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
);
4814 env
._Fe_stat
&= ~excepts
;
4815 env
._Fe_stat
|= *status
& excepts
;
4817 return fesetenv(&env
);
4820 /*********************************************************************
4821 * feraiseexcept (MSVCR120.@)
4823 int CDECL
feraiseexcept(int flags
)
4827 flags
&= FE_ALL_EXCEPT
;
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
);
4834 env
._Fe_stat
|= flags
;
4836 return fesetenv(&env
);
4839 /*********************************************************************
4840 * feclearexcept (MSVCR120.@)
4842 int CDECL
feclearexcept(int flags
)
4847 flags
&= FE_ALL_EXCEPT
;
4849 env
._Fe_stat
&= ~fenv_encode(flags
, flags
);
4851 env
._Fe_stat
&= ~flags
;
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
);
4868 *status
= _statusfp() & excepts
;
4875 /*********************************************************************
4876 * __fpe_flt_rounds (UCRTBASE.@)
4878 int CDECL
__fpe_flt_rounds(void)
4880 unsigned int fpc
= _controlfp(0, 0) & _RC_CHOP
;
4885 case _RC_CHOP
: return 0;
4886 case _RC_NEAR
: return 1;
4887 case _RC_UP
: return 2;
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
))
4910 _controlfp(round_mode
, _RC_CHOP
);
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
};
4925 ux
.i
|= uy
.i
& 1ull << 63;
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
) );
4948 const unsigned long sse2_cw
= 0x1f80;
4949 __asm__
__volatile__( "ldmxcsr %0" : : "m" (sse2_cw
) );
4952 FIXME( "not implemented\n" );
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
;
4971 DWORD instruction_pointer
;
4979 TRACE( "(%p)\n", env
);
4981 if (!env
->_Fe_ctl
&& !env
->_Fe_stat
) {
4987 if (!fenv_decode(env
->_Fe_ctl
, &x87_cw
, &sse_cw
))
4989 if (!fenv_decode(env
->_Fe_stat
, &x87_stat
, &sse_stat
))
4992 x87_cw
= sse_cw
= env
->_Fe_ctl
;
4993 x87_stat
= sse_stat
= env
->_Fe_stat
;
4996 __asm__
__volatile__( "fnstenv %0" : "=m" (fenv
) );
4998 fenv
.control_word
&= ~0xc3d;
5000 fenv
.control_word
&= ~0x1302;
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;
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;
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)" );
5038 __asm__
__volatile__( "stmxcsr %0" : "=m" (fpword
) );
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;
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;
5069 __asm__
__volatile__( "ldmxcsr %0" : : "m" (fpword
) );
5074 FIXME( "not implemented\n" );
5080 /*********************************************************************
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,
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,
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,
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,
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
;
5149 ix
= *(ULONGLONG
*)&x
>> 32;
5151 if (ix
>= 0x40200000) {
5154 } else if (ix
>= 0x40122E8B) {
5157 } else if (ix
>= 0x4006DB6D) {
5160 } else /*ix >= 0x40000000*/ {
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]))));
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,
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,
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,
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,
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
;
5235 ix
= *(ULONGLONG
*)&x
>> 32;
5237 if (ix
>= 0x40200000) {
5240 } else if (ix
>= 0x40122E8B) {
5243 } else if (ix
>= 0x4006DB6D) {
5246 } else /*ix >= 0x40000000*/ {
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
;
5268 /* avoid overflow in 2*x, big ulp error when x>=0x1p1023 */
5269 if (ix
< 0x7fe00000) {
5272 if (s
* c
< 0) cc
= z
/ ss
;
5274 if (ix
< 0x48000000) {
5276 cc
= pzero(x
) * cc
- qzero(x
) * ss
;
5279 return invsqrtpi
* cc
/ sqrt(x
);
5282 /*********************************************************************
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;
5301 ix
= *(ULONGLONG
*)&x
>> 32;
5304 /* j0(+-inf)=0, j0(nan)=nan */
5305 if (ix
>= 0x7ff00000)
5306 return math_error(_DOMAIN
, "_j0", x
, 0, 1 / (x
* 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 */
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
);
5323 /* prevent underflow */
5324 /* inexact should be raised when x!=0, this is not done correctly */
5325 if (ix
>= 0x38000000) /* |x| >= 2**-127 */
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,
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,
5353 5.92805987221131331921e+01,
5354 9.91401418733614377743e+02,
5355 5.35326695291487976647e+03,
5356 7.84469031749551231769e+03,
5357 1.50404688810361062679e+03,
5359 3.02503916137373618024e-09,
5360 1.17186865567253592491e-01,
5361 3.93297750033315640650e+00,
5362 3.51194035591636932736e+01,
5363 9.10550110750781271918e+01,
5364 4.85590685197364919645e+01,
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,
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
;
5390 ix
= *(ULONGLONG
*)&x
>> 32;
5392 if (ix
>= 0x40200000) {
5395 } else if (ix
>= 0x40122E8B) {
5398 } else if (ix
>= 0x4006DB6D) {
5401 } else /*ix >= 0x40000000*/ {
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]))));
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,
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,
5435 8.12765501384335777857e+01,
5436 1.99179873460485964642e+03,
5437 1.74684851924908907677e+04,
5438 4.98514270910352279316e+04,
5439 2.79480751638918118260e+04,
5440 -4.71918354795128470869e+03,
5442 -5.07831226461766561369e-09,
5443 -1.02537829820837089745e-01,
5444 -4.61011581139473403113e+00,
5445 -5.78472216562783643212e+01,
5446 -2.28244540737631695038e+02,
5447 -2.19210128478909325622e+02,
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,
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
;
5475 ix
= *(ULONGLONG
*)&x
>> 32;
5477 if (ix
>= 0x40200000) {
5480 } else if (ix
>= 0x40122E8B) {
5483 } else if (ix
>= 0x4006DB6D) {
5486 } else /*ix >= 0x40000000*/ {
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
;
5506 if (ix
< 0x7fe00000) {
5509 if (s
* c
> 0) cc
= z
/ ss
;
5511 if (ix
< 0x48000000) {
5514 cc
= pone(x
) * cc
- qone(x
) * ss
;
5519 return invsqrtpi
* cc
/ sqrt(x
);
5522 /*********************************************************************
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;
5543 ix
= *(ULONGLONG
*)&x
>> 32;
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 */
5552 r
= z
* (r00
+ z
* (r01
+ z
* (r02
+ z
* r03
)));
5553 s
= 1 + z
* (s01
+ z
* (s02
+ z
* (s03
+ z
* (s04
+ z
* s05
))));
5556 /* avoid underflow, raise inexact if x!=0 */
5559 return (0.5 + z
) * x
;
5562 /*********************************************************************
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
;
5575 ix
= *(ULONGLONG
*)&x
>> 32;
5576 lx
= *(ULONGLONG
*)&x
;
5580 if ((ix
| (lx
| -lx
) >> 31) > 0x7ff00000) /* nan */
5595 sign
&= n
; /* even n: 0, odd n: signbit(x) */
5597 if ((ix
| lx
) == 0 || ix
== 0x7ff00000) /* if x is 0 or inf */
5600 if (ix
>= 0x52d00000) { /* x > 2**302 */
5603 temp
= -cos(x
) + sin(x
);
5606 temp
= -cos(x
) - sin(x
);
5609 temp
= cos(x
) - sin(x
);
5612 temp
= cos(x
) + sin(x
);
5615 b
= invsqrtpi
* temp
/ sqrt(x
);
5619 for (i
= 0; i
< nm1
; ) {
5622 b
= b
* (2.0 * i
/ x
) - a
; /* avoid underflow */
5627 if (ix
< 0x3e100000) { /* x < 2**-29 */
5628 if (nm1
> 32) /* underflow */
5634 for (i
= 2; i
<= nm1
+ 1; i
++) {
5635 a
*= (double)i
; /* a = n! */
5636 b
*= temp
; /* b = (x/2)^n */
5641 double t
, q0
, q1
, w
, h
, z
, tmp
, nf
;
5651 while (q1
< 1.0e9
) {
5658 for (t
= 0.0, i
= k
; i
>= 0; i
--)
5659 t
= 1 / (2 * (i
+ nf
) / x
- t
);
5662 tmp
= nf
* log(fabs(w
));
5663 if (tmp
< 7.09782712893383973096e+02) {
5664 for (i
= nm1
; i
> 0; i
--) {
5666 b
= b
* (2.0 * i
) / x
- a
;
5670 for (i
= nm1
; i
> 0; i
--) {
5672 b
= b
* (2.0 * i
) / x
- a
;
5674 /* scale b to avoid spurious overflow */
5684 if (fabs(z
) >= fabs(w
))
5690 return sign
? -b
: b
;
5693 /*********************************************************************
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;
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
);
5723 return math_error(_DOMAIN
, "_y0", x
, 0, 0 / (x
- x
));
5724 if (ix
>= 0x7ff00000)
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 */
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 /*********************************************************************
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;
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
);
5771 return math_error(_DOMAIN
, "_y1", x
, 0, 0 / (x
- x
));
5772 if (ix
>= 0x7ff00000)
5775 if (ix
>= 0x40000000) /* x >= 2 */
5776 return j1_y1_approx(ix
, x
, TRUE
, 0);
5777 if (ix
< 0x3c900000) /* x < 2**-54 */
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 /*********************************************************************
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
;
5798 ix
= *(ULONGLONG
*)&x
>> 32;
5799 lx
= *(ULONGLONG
*)&x
;
5803 if ((ix
| (lx
| -lx
) >> 31) > 0x7ff00000) /* nan */
5805 if (sign
&& (ix
| lx
) != 0) /* x < 0 */
5806 return math_error(_DOMAIN
, "_y1", x
, 0, 0 / (x
- x
));
5807 if (ix
== 0x7ff00000)
5820 return sign
? -y1(x
) : y1(x
);
5822 if (ix
>= 0x52d00000) { /* x > 2**302 */
5825 temp
= -sin(x
) - cos(x
);
5828 temp
= -sin(x
) + cos(x
);
5831 temp
= sin(x
) + cos(x
);
5834 temp
= sin(x
) - cos(x
);
5837 b
= invsqrtpi
* temp
/ sqrt(x
);
5841 /* quit if b is -inf */
5842 ib
= *(ULONGLONG
*)&b
>> 32;
5843 for (i
= 0; i
< nm1
&& ib
!= 0xfff00000;) {
5846 b
= (2.0 * i
/ x
) * b
- a
;
5847 ib
= *(ULONGLONG
*)&b
>> 32;
5851 return sign
? -b
: b
;
5856 /*********************************************************************
5857 * _nearbyint (MSVCR120.@)
5859 * Based on musl: src/math/nearbyteint.c
5861 double CDECL
nearbyint(double x
)
5866 _control87(_MCW_EM
, _MCW_EM
);
5868 feclearexcept(FE_INEXACT
);
5873 /*********************************************************************
5874 * _nearbyintf (MSVCR120.@)
5876 * Based on musl: src/math/nearbyteintf.c
5878 float CDECL
nearbyintf(float x
)
5883 _control87(_MCW_EM
, _MCW_EM
);
5885 feclearexcept(FE_INEXACT
);
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
;
5909 if (isnan(x
) || isnan(y
))
5928 e
= ix
& 0x7f800000;
5929 /* raise overflow if ix is infinite and x is finite */
5930 if (e
== 0x7f800000) {
5935 /* raise underflow if ret is subnormal or zero */
5937 fp_barrierf(x
* x
+ ret
* 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
;
5957 if (isnan(x
) || isnan(y
))
5960 if (_fpclass(y
) & (_FPCLASS_ND
| _FPCLASS_PD
| _FPCLASS_NZ
| _FPCLASS_PZ
))
5964 ax
= llx
& -1ULL / 2;
5965 ay
= lly
& -1ULL / 2;
5969 llx
= (lly
& 1ULL << 63) | 1;
5970 } else if (ax
> ay
|| ((llx
^ lly
) & 1ULL << 63))
5974 e
= llx
>> 52 & 0x7ff;
5975 /* raise overflow if llx is infinite and x is finite */
5980 /* raise underflow if llx is subnormal or zero */
5983 fp_barrier(x
* x
+ y
* y
);
5989 /*********************************************************************
5992 char * CDECL
_ecvt( double number
, int ndigits
, int *decpt
, int *sign
)
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 */
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
-- );
6013 /* take the decimal "point away */
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
);
6021 /* adjust for some border cases */
6022 if( data
->efcvt_buffer
[0] == '0')/* value is zero */
6024 /* handle cases with zero ndigits or less */
6026 if( data
->efcvt_buffer
[ 0] >= '5')
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
)
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 */
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
-- );
6059 /* take the decimal "point away */
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
);
6067 /* adjust for some border cases */
6068 if( result
[0] == '0')/* value is zero */
6070 /* handle cases with zero ndigits or less */
6072 if( result
[ 0] >= '5')
6076 memcpy( buffer
, result
, max(ndigits
+ 1, 1) );
6081 /***********************************************************************
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
);
6097 ptr2
= data
->efcvt_buffer
;
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 */
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
) {
6134 while (*ptr1
== '0') { /* Process leading zeroes */
6139 while (*ptr1
!= '\0') {
6140 if (!first
) first
= ptr2
;
6147 /* We never found a non-zero digit, then our number is either
6148 * smaller than the requested precision, or 0.0 */
6153 first
= data
->efcvt_buffer
;
6158 *decpt
= dec2
? dec2
: dec1
;
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)
6178 stop
= _snprintf(buf
, 80, "%.*f", ndigits
< 0 ? 0 : ndigits
, number
);
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 */
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
) {
6220 while (*ptr1
== '0') { /* Process leading zeroes */
6221 if (number
== 0.0 && size
> 1) {
6229 while (*ptr1
!= '\0') {
6230 if (!first
) first
= ptr2
;
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))
6245 *decpt
= dec2
? dec2
: dec1
;
6249 /***********************************************************************
6252 char * CDECL
_gcvt( double number
, int ndigit
, char *buff
)
6264 sprintf(buff
, "%.*g", ndigit
, number
);
6268 /***********************************************************************
6269 * _gcvt_s (MSVCRT.@)
6271 int CDECL
_gcvt_s(char *buff
, size_t size
, double number
, int digits
)
6280 if( digits
<0 || digits
>=size
) {
6288 len
= _scprintf("%.*g", digits
, number
);
6295 sprintf(buff
, "%.*g", digits
, number
);
6299 #include <stdlib.h> /* div_t, ldiv_t */
6301 /*********************************************************************
6304 * [i386] Windows binary compatible - returns the struct in eax/edx.
6307 unsigned __int64 CDECL
div(int num
, int denom
)
6311 unsigned __int64 uint64
;
6314 ret
.div
.quot
= num
/ denom
;
6315 ret
.div
.rem
= num
% denom
;
6319 /*********************************************************************
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
)
6328 ret
.quot
= num
/ denom
;
6329 ret
.rem
= num
% denom
;
6332 #endif /* ifdef __i386__ */
6335 /*********************************************************************
6338 * [i386] Windows binary compatible - returns the struct in eax/edx.
6341 unsigned __int64 CDECL
ldiv(__msvcrt_long num
, __msvcrt_long denom
)
6345 unsigned __int64 uint64
;
6348 ret
.ldiv
.quot
= num
/ denom
;
6349 ret
.ldiv
.rem
= num
% denom
;
6353 /*********************************************************************
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
)
6362 ret
.quot
= num
/ denom
;
6363 ret
.rem
= num
% denom
;
6366 #endif /* ifdef __i386__ */
6369 /*********************************************************************
6370 * lldiv (MSVCR100.@)
6372 lldiv_t CDECL
lldiv(__int64 num
, __int64 denom
)
6376 ret
.quot
= num
/ denom
;
6377 ret
.rem
= num
% denom
;
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.@)
6395 * I _think_ this function is intended to work around the Pentium
6398 void __stdcall
_adj_fdiv_m16i( short arg
)
6400 TRACE("(): stub\n");
6403 /***********************************************************************
6404 * _adj_fdiv_m32 (MSVCRT.@)
6407 * I _think_ this function is intended to work around the Pentium
6410 void __stdcall
_adj_fdiv_m32( unsigned int arg
)
6412 TRACE("(): stub\n");
6415 /***********************************************************************
6416 * _adj_fdiv_m32i (MSVCRT.@)
6419 * I _think_ this function is intended to work around the Pentium
6422 void __stdcall
_adj_fdiv_m32i( int arg
)
6424 TRACE("(): stub\n");
6427 /***********************************************************************
6428 * _adj_fdiv_m64 (MSVCRT.@)
6431 * I _think_ this function is intended to work around the Pentium
6434 void __stdcall
_adj_fdiv_m64( unsigned __int64 arg
)
6436 TRACE("(): stub\n");
6439 /***********************************************************************
6440 * _adj_fdiv_r (MSVCRT.@)
6442 * This function is likely to have the wrong number of arguments.
6445 * I _think_ this function is intended to work around the Pentium
6448 void _adj_fdiv_r(void)
6450 TRACE("(): stub\n");
6453 /***********************************************************************
6454 * _adj_fdivr_m16i (MSVCRT.@)
6457 * I _think_ this function is intended to work around the Pentium
6460 void __stdcall
_adj_fdivr_m16i( short arg
)
6462 TRACE("(): stub\n");
6465 /***********************************************************************
6466 * _adj_fdivr_m32 (MSVCRT.@)
6469 * I _think_ this function is intended to work around the Pentium
6472 void __stdcall
_adj_fdivr_m32( unsigned int arg
)
6474 TRACE("(): stub\n");
6477 /***********************************************************************
6478 * _adj_fdivr_m32i (MSVCRT.@)
6481 * I _think_ this function is intended to work around the Pentium
6484 void __stdcall
_adj_fdivr_m32i( int arg
)
6486 TRACE("(): stub\n");
6489 /***********************************************************************
6490 * _adj_fdivr_m64 (MSVCRT.@)
6493 * I _think_ this function is intended to work around the Pentium
6496 void __stdcall
_adj_fdivr_m64( unsigned __int64 arg
)
6498 TRACE("(): stub\n");
6501 /***********************************************************************
6502 * _adj_fpatan (MSVCRT.@)
6504 * This function is likely to have the wrong number of arguments.
6507 * I _think_ this function is intended to work around the Pentium
6510 void _adj_fpatan(void)
6512 TRACE("(): stub\n");
6515 /***********************************************************************
6516 * _adj_fprem (MSVCRT.@)
6518 * This function is likely to have the wrong number of arguments.
6521 * I _think_ this function is intended to work around the Pentium
6524 void _adj_fprem(void)
6526 TRACE("(): stub\n");
6529 /***********************************************************************
6530 * _adj_fprem1 (MSVCRT.@)
6532 * This function is likely to have the wrong number of arguments.
6535 * I _think_ this function is intended to work around the Pentium
6538 void _adj_fprem1(void)
6540 TRACE("(): stub\n");
6543 /***********************************************************************
6544 * _adj_fptan (MSVCRT.@)
6546 * This function is likely to have the wrong number of arguments.
6549 * I _think_ this function is intended to work around the Pentium
6552 void _adj_fptan(void)
6554 TRACE("(): stub\n");
6557 /***********************************************************************
6558 * _safe_fdiv (MSVCRT.@)
6560 * This function is likely to have the wrong number of arguments.
6563 * I _think_ this function is intended to work around the Pentium
6566 void _safe_fdiv(void)
6568 TRACE("(): stub\n");
6571 /***********************************************************************
6572 * _safe_fdivr (MSVCRT.@)
6574 * This function is likely to have the wrong number of arguments.
6577 * I _think_ this function is intended to work around the Pentium
6580 void _safe_fdivr(void)
6582 TRACE("(): stub\n");
6585 /***********************************************************************
6586 * _safe_fprem (MSVCRT.@)
6588 * This function is likely to have the wrong number of arguments.
6591 * I _think_ this function is intended to work around the Pentium
6594 void _safe_fprem(void)
6596 TRACE("(): stub\n");
6599 /***********************************************************************
6600 * _safe_fprem1 (MSVCRT.@)
6603 * This function is likely to have the wrong number of arguments.
6606 * I _think_ this function is intended to work around the Pentium
6609 void _safe_fprem1(void)
6611 TRACE("(): stub\n");
6614 /***********************************************************************
6615 * __libm_sse2_acos (MSVCRT.@)
6617 void __cdecl
__libm_sse2_acos(void)
6620 __asm__
__volatile__( "movq %%xmm0,%0" : "=m" (d
) );
6622 __asm__
__volatile__( "movq %0,%%xmm0" : : "m" (d
) );
6625 /***********************************************************************
6626 * __libm_sse2_acosf (MSVCRT.@)
6628 void __cdecl
__libm_sse2_acosf(void)
6631 __asm__
__volatile__( "movd %%xmm0,%0" : "=g" (f
) );
6633 __asm__
__volatile__( "movd %0,%%xmm0" : : "g" (f
) );
6636 /***********************************************************************
6637 * __libm_sse2_asin (MSVCRT.@)
6639 void __cdecl
__libm_sse2_asin(void)
6642 __asm__
__volatile__( "movq %%xmm0,%0" : "=m" (d
) );
6644 __asm__
__volatile__( "movq %0,%%xmm0" : : "m" (d
) );
6647 /***********************************************************************
6648 * __libm_sse2_asinf (MSVCRT.@)
6650 void __cdecl
__libm_sse2_asinf(void)
6653 __asm__
__volatile__( "movd %%xmm0,%0" : "=g" (f
) );
6655 __asm__
__volatile__( "movd %0,%%xmm0" : : "g" (f
) );
6658 /***********************************************************************
6659 * __libm_sse2_atan (MSVCRT.@)
6661 void __cdecl
__libm_sse2_atan(void)
6664 __asm__
__volatile__( "movq %%xmm0,%0" : "=m" (d
) );
6666 __asm__
__volatile__( "movq %0,%%xmm0" : : "m" (d
) );
6669 /***********************************************************************
6670 * __libm_sse2_atan2 (MSVCRT.@)
6672 void __cdecl
__libm_sse2_atan2(void)
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)
6686 __asm__
__volatile__( "movd %%xmm0,%0" : "=g" (f
) );
6688 __asm__
__volatile__( "movd %0,%%xmm0" : : "g" (f
) );
6691 /***********************************************************************
6692 * __libm_sse2_cos (MSVCRT.@)
6694 void __cdecl
__libm_sse2_cos(void)
6697 __asm__
__volatile__( "movq %%xmm0,%0" : "=m" (d
) );
6699 __asm__
__volatile__( "movq %0,%%xmm0" : : "m" (d
) );
6702 /***********************************************************************
6703 * __libm_sse2_cosf (MSVCRT.@)
6705 void __cdecl
__libm_sse2_cosf(void)
6708 __asm__
__volatile__( "movd %%xmm0,%0" : "=g" (f
) );
6710 __asm__
__volatile__( "movd %0,%%xmm0" : : "g" (f
) );
6713 /***********************************************************************
6714 * __libm_sse2_exp (MSVCRT.@)
6716 void __cdecl
__libm_sse2_exp(void)
6719 __asm__
__volatile__( "movq %%xmm0,%0" : "=m" (d
) );
6721 __asm__
__volatile__( "movq %0,%%xmm0" : : "m" (d
) );
6724 /***********************************************************************
6725 * __libm_sse2_expf (MSVCRT.@)
6727 void __cdecl
__libm_sse2_expf(void)
6730 __asm__
__volatile__( "movd %%xmm0,%0" : "=g" (f
) );
6732 __asm__
__volatile__( "movd %0,%%xmm0" : : "g" (f
) );
6735 /***********************************************************************
6736 * __libm_sse2_log (MSVCRT.@)
6738 void __cdecl
__libm_sse2_log(void)
6741 __asm__
__volatile__( "movq %%xmm0,%0" : "=m" (d
) );
6743 __asm__
__volatile__( "movq %0,%%xmm0" : : "m" (d
) );
6746 /***********************************************************************
6747 * __libm_sse2_log10 (MSVCRT.@)
6749 void __cdecl
__libm_sse2_log10(void)
6752 __asm__
__volatile__( "movq %%xmm0,%0" : "=m" (d
) );
6754 __asm__
__volatile__( "movq %0,%%xmm0" : : "m" (d
) );
6757 /***********************************************************************
6758 * __libm_sse2_log10f (MSVCRT.@)
6760 void __cdecl
__libm_sse2_log10f(void)
6763 __asm__
__volatile__( "movd %%xmm0,%0" : "=g" (f
) );
6765 __asm__
__volatile__( "movd %0,%%xmm0" : : "g" (f
) );
6768 /***********************************************************************
6769 * __libm_sse2_logf (MSVCRT.@)
6771 void __cdecl
__libm_sse2_logf(void)
6774 __asm__
__volatile__( "movd %%xmm0,%0" : "=g" (f
) );
6776 __asm__
__volatile__( "movd %0,%%xmm0" : : "g" (f
) );
6779 /***********************************************************************
6780 * __libm_sse2_pow (MSVCRT.@)
6782 void __cdecl
__libm_sse2_pow(void)
6785 __asm__
__volatile__( "movq %%xmm0,%0; movq %%xmm1,%1 " : "=m" (d1
), "=m" (d2
) );
6787 __asm__
__volatile__( "movq %0,%%xmm0" : : "m" (d1
) );
6790 /***********************************************************************
6791 * __libm_sse2_powf (MSVCRT.@)
6793 void __cdecl
__libm_sse2_powf(void)
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)
6807 __asm__
__volatile__( "movq %%xmm0,%0" : "=m" (d
) );
6809 __asm__
__volatile__( "movq %0,%%xmm0" : : "m" (d
) );
6812 /***********************************************************************
6813 * __libm_sse2_sinf (MSVCRT.@)
6815 void __cdecl
__libm_sse2_sinf(void)
6818 __asm__
__volatile__( "movd %%xmm0,%0" : "=g" (f
) );
6820 __asm__
__volatile__( "movd %0,%%xmm0" : : "g" (f
) );
6823 /***********************************************************************
6824 * __libm_sse2_tan (MSVCRT.@)
6826 void __cdecl
__libm_sse2_tan(void)
6829 __asm__
__volatile__( "movq %%xmm0,%0" : "=m" (d
) );
6831 __asm__
__volatile__( "movq %0,%%xmm0" : : "m" (d
) );
6834 /***********************************************************************
6835 * __libm_sse2_tanf (MSVCRT.@)
6837 void __cdecl
__libm_sse2_tanf(void)
6840 __asm__
__volatile__( "movd %%xmm0,%0" : "=g" (f
) );
6842 __asm__
__volatile__( "movd %0,%%xmm0" : : "g" (f
) );
6845 /***********************************************************************
6846 * __libm_sse2_sqrt_precise (MSVCR110.@)
6848 void __cdecl
__libm_sse2_sqrt_precise(void)
6853 __asm__
__volatile__( "movq %%xmm0,%0" : "=m" (d
) );
6854 __control87_2(0, 0, NULL
, &cw
);
6858 __asm__
__volatile__( "movq %0,%%xmm0" : : "m" (d
) );
6862 if (!sqrt_validate(&d
, FALSE
))
6864 __asm__
__volatile__( "movq %0,%%xmm0" : : "m" (d
) );
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
;
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
;
6903 /*********************************************************************
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
};
6919 UINT32 hx
= u
.i
>> 32 & 0x7fffffff;
6921 if (hx
>= 0x7ff00000) /* cbrt(NaN,INF) is itself */
6924 if (hx
< 0x00100000) { /* zero or subnormal? */
6926 hx
= u
.i
>>32 & 0x7fffffff;
6933 u
.i
|= (UINT64
)hx
<< 32;
6936 r
= (t
* t
) * (t
/ x
);
6937 t
= t
* ((P0
+ r
* (P1
+ r
* P2
)) + ((r
* r
) * r
) * (P3
+ r
* P4
));
6940 u
.i
= (u
.i
+ 0x80000000) & 0xffffffffc0000000ULL
;
6946 r
= (r
- t
) / (w
+ r
);
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;
6961 union {float f
; UINT32 i
;} u
= {x
};
6962 UINT32 hx
= u
.i
& 0x7fffffff;
6964 if (hx
>= 0x7f800000)
6967 if (hx
< 0x00800000) { /* zero or subnormal? */
6971 hx
= u
.i
& 0x7fffffff;
6980 T
= T
* (x
+ x
+ r
) / (x
+ r
+ r
);
6983 T
= T
* (x
+ x
+ r
) / (x
+ r
+ r
);
6987 /*********************************************************************
6990 double CDECL
exp2(double x
)
6992 double ret
= unix_funcs
->exp2( x
);
6993 if (isfinite(x
) && !isfinite(ret
)) *_errno() = ERANGE
;
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
;
7007 /*********************************************************************
7008 * expm1 (MSVCR120.@)
7010 double CDECL
expm1(double x
)
7015 /*********************************************************************
7016 * expm1f (MSVCR120.@)
7018 float CDECL
expm1f(float 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
;
7047 if (hx
< 0x3fda827a || hx
>> 31) { /* 1+x < sqrt(2)+ */
7048 if (hx
>= 0xbff00000) { /* x <= -1.0 */
7051 return x
/ 0.0; /* og1p(-1) = -inf */
7054 return (x
-x
) / 0.0; /* log1p(x<-1) = NaN */
7056 if (hx
<< 1 < 0x3ca00000 << 1) { /* |x| < 2**-53 */
7057 fp_barrier(x
+ 0x1p
120f
);
7058 /* underflow if subnormal */
7059 if ((hx
& 0x7ff00000) == 0)
7063 if (hx
<= 0xbfd2bec4) { /* sqrt(2)/2- <= 1+x < sqrt(2)+ */
7068 } else if (hx
>= 0x7ff00000)
7073 hu
+= 0x3ff00000 - 0x3fe6a09e;
7074 k
= (int)(hu
>> 20) - 0x3ff;
7075 /* correction term ~ log(1+x)-log(u), avoid underflow in c/u */
7077 c
= k
>= 2 ? 1 - (u
.f
- x
) : x
- (u
.f
- 1);
7081 /* reduce u into [sqrt(2)/2, sqrt(2)] */
7082 hu
= (hu
& 0x000fffff) + 0x3fe6a09e;
7083 u
.i
= (UINT64
)hu
<< 32 | (u
.i
& 0xffffffff);
7090 t1
= w
* (Lg2
+ w
* (Lg4
+ w
* Lg6
));
7091 t2
= z
* (Lg1
+ w
* (Lg3
+ w
* (Lg5
+ w
* Lg7
)));
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
;
7118 if (ix
< 0x3ed413d0 || ix
>> 31) { /* 1+x < sqrt(2)+ */
7119 if (ix
>= 0xbf800000) { /* x <= -1.0 */
7122 return x
/ 0.0f
; /* log1p(-1)=+inf */
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)
7133 if (ix
<= 0xbe95f619) { /* sqrt(2)/2- <= 1+x < sqrt(2)+ */
7138 } else if (ix
>= 0x7f800000)
7143 iu
+= 0x3f800000 - 0x3f3504f3;
7144 k
= (int)(iu
>> 23) - 0x7f;
7145 /* correction term ~ log(1+x)-log(u), avoid underflow in c/u */
7147 c
= k
>= 2 ? 1 - (u
.f
- x
) : x
- (u
.f
- 1);
7151 /* reduce u into [sqrt(2)/2, sqrt(2)] */
7152 iu
= (iu
& 0x007fffff) + 0x3f3504f3;
7159 t1
= w
* (Lg2
+ w
* Lg4
);
7160 t2
= z
* (Lg1
+ w
* Lg3
);
7162 hfsq
= 0.5f
* f
* f
;
7164 return s
* (hfsq
+ R
) + (dk
* ln2_lo
+ c
) - hfsq
+ f
+ dk
* ln2_hi
;
7167 /*********************************************************************
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 {
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 {
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
;
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
)
7346 *(UINT64
*)&rhi
= *(UINT64
*)&r
& -1ULL << 32;
7348 hi
= rhi
* invln2hi
;
7349 lo
= rlo
* invln2hi
+ r
* invln2lo
;
7350 r2
= r
* r
; /* rounding error: 0x1p-62. */
7352 /* Worst-case error is less than 0.54 ULP (0.55 ULP without fma). */
7353 p
= r2
* (B
[0] + r
* B
[1]);
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])));
7361 if (top
- 0x0010 >= 0x7ff0 - 0x0010) {
7362 /* x < 0x1p-1022 or inf or nan. */
7367 if (ix
== 0x7ff0000000000000ULL
) /* log(inf) == inf. */
7369 if ((top
& 0x7ff0) == 0x7ff0 && (ix
& 0xfffffffffffffULL
))
7373 return (x
- x
) / (x
- x
);
7375 /* x is subnormal, normalize it. */
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);
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;
7399 t1
= rhi
* invln2hi
;
7400 t2
= rlo
* invln2hi
+ r
* invln2lo
;
7402 /* hi + lo = r/ln2 + log2(c) + k. */
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. */
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
;
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,
7431 static const struct {
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 },
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
;
7457 /* Fix sign of zero with downward rounding when x==1. */
7458 if (ix
== 0x3f800000)
7460 if (ix
- 0x00800000 >= 0x7f800000 - 0x00800000) {
7461 /* x < 0x1p-126 or inf or nan. */
7466 if (ix
== 0x7f800000) /* log2(inf) == inf. */
7468 if (ix
* 2 > 0xff000000)
7470 if (ix
& 0x80000000) {
7472 return (x
- x
) / (x
- x
);
7474 /* x is subnormal, normalize it. */
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;
7487 k
= (INT32
)tmp
>> 23; /* arithmetic shift */
7492 /* log2(x) = log1p(z/c-1)/ln2 + log2(c) + k */
7494 y0
= logc
+ (double)k
;
7496 /* Pipelined polynomial evaluation to approximate log1p(r)/ln2. */
7498 y
= A
[1] * r
+ A
[2];
7505 /*********************************************************************
7508 double CDECL
rint(double 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;
7530 y
= fp_barrierf(x
- toint
) + toint
;
7532 y
= fp_barrierf(x
+ toint
) - toint
;
7534 return s
? -0.0f
: 0.0f
;
7538 /*********************************************************************
7539 * lrint (MSVCR120.@)
7541 __msvcrt_long CDECL
lrint(double x
)
7546 if ((d
< 0 && d
!= (double)(__msvcrt_long
)d
)
7547 || (d
>= 0 && d
!= (double)(__msvcrt_ulong
)d
)) {
7554 /*********************************************************************
7555 * lrintf (MSVCR120.@)
7557 __msvcrt_long CDECL
lrintf(float x
)
7562 if ((f
< 0 && f
!= (float)(__msvcrt_long
)f
)
7563 || (f
>= 0 && f
!= (float)(__msvcrt_ulong
)f
)) {
7570 /*********************************************************************
7571 * llrint (MSVCR120.@)
7573 __int64 CDECL
llrint(double x
)
7578 if ((d
< 0 && d
!= (double)(__int64
)d
)
7579 || (d
>= 0 && d
!= (double)(unsigned __int64
)d
)) {
7586 /*********************************************************************
7587 * llrintf (MSVCR120.@)
7589 __int64 CDECL
llrintf(float x
)
7594 if ((f
< 0 && f
!= (float)(__int64
)f
)
7595 || (f
>= 0 && f
!= (float)(unsigned __int64
)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;
7617 return signbit(x
) ? -1 : 1;
7619 tmp
= 0x000fffffffffffffULL
>> e
;
7622 llx
+= 0x0008000000000000ULL
>> e
;
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;
7645 return 0 * *(float*)&ix
;
7646 y
= fp_barrierf(x
+ toint
) - toint
- x
;
7649 else if (y
<= -0.5f
)
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
) {
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
) {
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
) {
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
) {
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;
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;
7762 /*********************************************************************
7763 * _dtest (MSVCR120.@)
7765 short CDECL
_dtest(double *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;
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;
7839 if (ix
< 0x3ff40000) /* |x| < 1.25 */
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
))))));
7856 iz
= *(ULONGLONG
*)&z
;
7857 iz
&= 0xffffffff00000000ULL
;
7859 return exp(-z
* z
- 0.5625) * exp((z
- x
) * (z
+ x
) + R
/ S
) / x
;
7862 /*********************************************************************
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;
7883 ix
= *(UINT64
*)&x
>> 32;
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
);
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
))));
7901 if (ix
< 0x40180000) /* 0.84375 <= |x| < 6 */
7902 y
= 1 - erfc2(ix
, x
);
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;
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;
7968 if (ix
< 0x3fa00000) /* |x| < 1.25 */
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;
7986 return expf(-z
* z
- 0.5625f
) * expf((z
- x
) * (z
+ x
) + R
/ S
) / x
;
7989 /*********************************************************************
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;
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
);
8025 r
= pp0
+ z
* (pp1
+ z
* (pp2
+ z
* (pp3
+ z
* pp4
)));
8026 s
= 1 + z
* (qq1
+ z
* (qq2
+ z
* (qq3
+ z
* (qq4
+ z
* qq5
))));
8030 if (ix
< 0x40c00000) /* |x| < 6 */
8031 y
= 1 - erfc2f(ix
, x
);
8034 return sign
? -y
: y
;
8037 /*********************************************************************
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;
8059 ix
= *(ULONGLONG
*)&x
>> 32;
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 */
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
))));
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
);
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;
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 */
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
))));
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
);
8134 return FLT_MIN
* FLT_MIN
;
8137 /*********************************************************************
8138 * fmaxf (MSVCR120.@)
8140 float CDECL
fmaxf(float x
, float y
)
8147 return signbit(x
) ? y
: x
;
8151 /*********************************************************************
8154 double CDECL
fmax(double x
, double y
)
8161 return signbit(x
) ? y
: x
;
8165 /*********************************************************************
8166 * fdimf (MSVCR120.@)
8168 float CDECL
fdimf(float x
, float y
)
8174 return x
>y
? x
-y
: 0;
8177 /*********************************************************************
8180 double CDECL
fdim(double x
, double 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
))
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
)
8238 return signbit(x
) ? x
: y
;
8242 /*********************************************************************
8245 double CDECL
fmin(double x
, double y
)
8252 return signbit(x
) ? 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;
8268 ux
&= (UINT64
)-1 / 2;
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
+ 0x1p
120f
);
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;
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
+ 0x1p
120f
);
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;
8319 feraiseexcept(FE_INVALID
);
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;
8343 feraiseexcept(FE_INVALID
);
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;
8367 ux
&= (UINT64
)-1 / 2;
8372 feraiseexcept(FE_INVALID
);
8376 if (e
< 0x3ff - 1) {
8377 if (e
< 0x3ff - 32) {
8378 fp_barrier(x
+ 0x1p
120f
);
8379 if (e
== 0) /* handle underflow */
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
;
8391 /*********************************************************************
8392 * atanhf (MSVCR120.@)
8394 * Copied from musl: src/math/atanhf.c
8396 float CDECL
atanhf(float x
)
8398 UINT32 ux
= *(UINT32
*)&x
;
8407 feraiseexcept(FE_INVALID
);
8411 if (ux
< 0x3f800000 - (1 << 23)) {
8412 if (ux
< 0x3f800000 - (32 << 23)) {
8413 fp_barrierf(x
+ 0x1p
120f
);
8414 if (ux
< (1 << 23)) /* handle underflow */
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
;
8426 #endif /* _MSVCR_VER>=120 */
8428 /*********************************************************************
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
);
8450 /*********************************************************************
8451 * remainder (MSVCR120.@)
8453 * Copied from musl: src/math/remainder.c
8455 double CDECL
remainder(double x
, double y
)
8458 #if _MSVCR_VER == 120 && defined(__x86_64__)
8459 if (isnan(x
) || isnan(y
)) *_errno() = EDOM
;
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
)
8472 #if _MSVCR_VER == 120 && defined(__x86_64__)
8473 if (isnan(x
) || isnan(y
)) *_errno() = EDOM
;
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;
8495 if (y
== 0 || isinf(x
)) *_errno() = EDOM
;
8496 if (uyi
<< 1 == 0 || isnan(y
) || ex
== 0x7ff)
8497 return (x
* y
) / (x
* y
);
8501 /* normalize x and y */
8503 for (i
= uxi
<< 12; i
>> 63 == 0; ex
--, i
<<= 1);
8510 for (i
= uyi
<< 12; i
>> 63 == 0; ey
--, i
<<= 1);
8525 for (; ex
> ey
; ex
--) {
8542 for (; uxi
>> 52 == 0; uxi
<<= 1, ex
--);
8544 /* scale result and decide between |x| and |x|-|y| */
8547 uxi
|= (UINT64
)ex
<< 52;
8554 if (ex
== ey
|| (ex
+ 1 == ey
&& (2 * x
> y
|| (2 * x
== y
&& q
% 2)))) {
8559 *quo
= sx
^ sy
? -(int)q
: (int)q
;
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;
8579 if (y
== 0 || isinf(x
)) *_errno() = EDOM
;
8580 if (uyi
<< 1 == 0 || isnan(y
) || ex
== 0xff)
8581 return (x
* y
) / (x
* y
);
8585 /* normalize x and y */
8587 for (i
= uxi
<< 9; i
>> 31 == 0; ex
--, i
<<= 1);
8594 for (i
= uyi
<< 9; i
>> 31 == 0; ey
--, i
<<= 1);
8609 for (; ex
> ey
; ex
--) {
8626 for (; uxi
>> 23 == 0; uxi
<<= 1, ex
--);
8628 /* scale result and decide between |x| and |x|-|y| */
8631 uxi
|= (UINT32
)ex
<< 23;
8638 if (ex
== ey
|| (ex
+ 1 == ey
&& (2 * x
> y
|| (2 * x
== y
&& q
% 2)))) {
8643 *quo
= sx
^ sy
? -(int)q
: (int)q
;
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;
8653 /* spurious inexact if odd int */
8654 x
= 2.0 * (x
* 0.5 - floor(x
* 0.5)); /* x mod 2.0 */
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
;
8745 /* purge off +-inf, NaN, +-0, tiny and negative arguments */
8747 ix
= u
.i
>> 32 & 0x7fffffff;
8748 if (ix
>= 0x7ff00000)
8750 if (ix
< (0x3ff - 70) << 20) { /* |x|<2**-70, return -log(|x|) */
8758 if (t
== 0.0) { /* -integer */
8760 return 1.0 / (x
- x
);
8764 nadj
= log(pi
/ (t
* x
));
8767 /* purge off 1 and 2 */
8768 if ((ix
== 0x3ff00000 || ix
== 0x40000000) && (UINT32
)u
.i
== 0)
8771 else if (ix
< 0x40000000) {
8772 if (ix
<= 0x3feccccc) { /* lgamma(x) = lgamma(x+1)-log(x) */
8774 if (ix
>= 0x3FE76944) {
8777 } else if (ix
>= 0x3FCDA661) {
8786 if (ix
>= 0x3FFBB4C3) { /* [1.7316,2] */
8789 } else if(ix
>= 0x3FF3B4C4) { /* [1.23,1.73] */
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
)))));
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
));
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 */
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) */
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 */
8836 } else if (ix
< 0x43900000) { /* 8.0 <= x < 2**58 */
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);
8849 /* sin(pi*x) assuming x > 2^-100, if sin(pi*x)==0 the sign is arbitrary */
8850 static float sinf_pi(float x
)
8855 /* spurious inexact if odd int */
8856 x
= 2 * (x
* 0.5f
- floorf(x
* 0.5f
)); /* x mod 2.0 */
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
;
8946 /* purge off +-inf, NaN, +-0, tiny and negative arguments */
8948 ix
= u
.i
& 0x7fffffff;
8949 if (ix
>= 0x7f800000)
8951 if (ix
< 0x35000000) { /* |x| < 2**-21, return -log(|x|) */
8959 if (t
== 0.0f
) { /* -integer */
8961 return 1.0f
/ (x
- x
);
8965 nadj
= logf(pi
/ (t
* x
));
8968 /* purge off 1 and 2 */
8969 if (ix
== 0x3f800000 || ix
== 0x40000000)
8972 else if (ix
< 0x40000000) {
8973 if (ix
<= 0x3f666666) { /* lgamma(x) = lgamma(x+1)-log(x) */
8975 if (ix
>= 0x3f3b4a20) {
8978 } else if (ix
>= 0x3e6d3308) {
8979 y
= x
- (tc
- 1.0f
);
8987 if (ix
>= 0x3fdda618) { /* [1.7316,2] */
8990 } else if (ix
>= 0x3F9da620) { /* [1.23,1.73] */
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
)))));
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
));
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 */
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) */
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 */
9037 } else if (ix
< 0x5c800000) { /* 8.0 <= x < 2**58 */
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
);
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 /*********************************************************************
9069 double CDECL
nan(const char *tagp
)
9071 /* Windows ignores input (MSDN) */
9075 /*********************************************************************
9078 float CDECL
nanf(const char *tagp
)
9083 /*********************************************************************
9084 * _except1 (MSVCR120.@)
9086 * - find meaning of ignored cw and operation bits
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;
9097 TRACE("(%x %x %lf %lf %x %p)\n", fpe
, op
, arg
, res
, cw
, unk
);
9100 cw
= ((cw
>> 7) & 0x3f) | ((cw
>> 3) & 0xc00);
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
;
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;
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
;
9127 exception
= EXCEPTION_FLT_DIVIDE_BY_ZERO
;
9129 } else if (fpe
& 0x8) { /* invalid */
9130 if (fpe
== 0x8 && (cw
& 0x1)) {
9131 raise
|= FE_INVALID
;
9133 exception
= EXCEPTION_FLT_INVALID_OPERATION
;
9135 } else if (fpe
& 0x10) { /* inexact */
9136 if (fpe
== 0x10 && (cw
& 0x20)) {
9137 raise
|= FE_INEXACT
;
9139 exception
= EXCEPTION_FLT_INEXACT_RESULT
;
9145 feraiseexcept(raise
);
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
;
9157 case 0xc00: fpword
|= _RC_UP
|_RC_DOWN
; break;
9158 case 0x800: fpword
|= _RC_UP
; break;
9159 case 0x400: fpword
|= _RC_DOWN
; break;
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);
9173 _Dcomplex
* CDECL
_Cbuild(_Dcomplex
*ret
, double r
, double i
)
9180 double CDECL
MSVCR120_creal(_Dcomplex z
)
9185 /*********************************************************************
9186 * ilogb (MSVCR120.@)
9188 int CDECL
ilogb(double x
)
9193 /*********************************************************************
9194 * ilogbf (MSVCR120.@)
9196 int CDECL
ilogbf(float x
)
9200 #endif /* _MSVCR_VER>=120 */