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 void msvcrt_init_math( void *module
)
72 sse2_supported
= IsProcessorFeaturePresent( PF_XMMI64_INSTRUCTIONS_AVAILABLE
);
76 sse2_enabled
= sse2_supported
;
80 /* Copied from musl: src/internal/libm.h */
81 static inline float fp_barrierf(float x
)
87 static inline double fp_barrier(double x
)
89 volatile double y
= x
;
93 static inline double ret_nan( BOOL update_sw
)
96 if (!update_sw
) return -NAN
;
97 return (x
- x
) / (x
- x
);
100 #define SET_X87_CW(MASK) \
101 "subl $4, %esp\n\t" \
102 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") \
103 "fnstcw (%esp)\n\t" \
104 "movw (%esp), %ax\n\t" \
105 "movw %ax, 2(%esp)\n\t" \
106 "testw $" #MASK ", %ax\n\t" \
108 "andw $~" #MASK ", %ax\n\t" \
109 "movw %ax, 2(%esp)\n\t" \
110 "fldcw 2(%esp)\n\t" \
113 #define RESET_X87_CW \
114 "movw (%esp), %ax\n\t" \
115 "cmpw %ax, 2(%esp)\n\t" \
117 "fstpl 8(%esp)\n\t" \
122 "addl $4, %esp\n\t" \
123 __ASM_CFI(".cfi_adjust_cfa_offset -4\n\t")
125 /*********************************************************************
126 * _matherr (CRTDLL.@)
128 int CDECL
_matherr(struct _exception
*e
)
134 static double math_error(int type
, const char *name
, double arg1
, double arg2
, double retval
)
136 struct _exception exception
= {type
, (char *)name
, arg1
, arg2
, retval
};
138 TRACE("(%d, %s, %g, %g, %g)\n", type
, debugstr_a(name
), arg1
, arg2
, retval
);
140 if (MSVCRT_default_matherr_func
&& MSVCRT_default_matherr_func(&exception
))
141 return exception
.retval
;
146 /* don't set errno */
156 /* don't set errno */
159 ERR("Unhandled math error!\n");
162 return exception
.retval
;
165 /*********************************************************************
166 * __setusermatherr (MSVCRT.@)
168 void CDECL
__setusermatherr(MSVCRT_matherr_func func
)
170 MSVCRT_default_matherr_func
= func
;
171 TRACE("new matherr handler %p\n", func
);
174 /*********************************************************************
175 * _set_SSE2_enable (MSVCRT.@)
177 int CDECL
_set_SSE2_enable(int flag
)
179 sse2_enabled
= flag
&& sse2_supported
;
185 /*********************************************************************
186 * _get_FMA3_enable (UCRTBASE.@)
188 int CDECL
_get_FMA3_enable(void)
196 /*********************************************************************
197 * _set_FMA3_enable (MSVCR120.@)
199 int CDECL
_set_FMA3_enable(int flag
)
201 FIXME("(%x) stub\n", flag
);
207 #if !defined(__i386__) || _MSVCR_VER>=120
209 /*********************************************************************
210 * _chgsignf (MSVCRT.@)
212 float CDECL
_chgsignf( float num
)
214 union { float f
; UINT32 i
; } u
= { num
};
219 /*********************************************************************
220 * _copysignf (MSVCRT.@)
222 * Copied from musl: src/math/copysignf.c
224 float CDECL
_copysignf( float x
, float y
)
226 union { float f
; UINT32 i
; } ux
= { x
}, uy
= { y
};
228 ux
.i
|= uy
.i
& 0x80000000;
232 /*********************************************************************
233 * _nextafterf (MSVCRT.@)
235 * Copied from musl: src/math/nextafterf.c
237 float CDECL
_nextafterf( float x
, float y
)
239 unsigned int ix
= *(unsigned int*)&x
;
240 unsigned int iy
= *(unsigned int*)&y
;
241 unsigned int ax
, ay
, e
;
243 if (isnan(x
) || isnan(y
))
246 if (_fpclassf(y
) & (_FPCLASS_ND
| _FPCLASS_PD
| _FPCLASS_NZ
| _FPCLASS_PZ
))
250 ax
= ix
& 0x7fffffff;
251 ay
= iy
& 0x7fffffff;
255 ix
= (iy
& 0x80000000) | 1;
256 } else if (ax
> ay
|| ((ix
^ iy
) & 0x80000000))
261 /* raise overflow if ix is infinite and x is finite */
262 if (e
== 0x7f800000) {
266 /* raise underflow if ix is subnormal or zero */
269 fp_barrierf(x
* x
+ y
* y
);
275 /* Copied from musl: src/math/ilogbf.c */
276 static int __ilogbf(float x
)
278 union { float f
; UINT32 i
; } u
= { x
};
279 int e
= u
.i
>> 23 & 0xff;
284 if (u
.i
== 0) return FP_ILOGB0
;
286 for (e
= -0x7f; u
.i
>> 31 == 0; e
--, u
.i
<<= 1);
289 if (e
== 0xff) return u
.i
<< 9 ? FP_ILOGBNAN
: INT_MAX
;
293 /*********************************************************************
296 * Copied from musl: src/math/logbf.c
298 float CDECL
_logbf(float x
)
311 /* Copied from musl: src/math/scalbn.c */
312 static double __scalbn(double x
, int n
)
314 union {double f
; UINT64 i
;} u
;
326 } else if (n
< -1022) {
327 /* make sure final n < -53 to avoid double
328 rounding in the subnormal range */
329 y
*= 0x1p
-1022 * 0x1p
53;
332 y
*= 0x1p
-1022 * 0x1p
53;
338 u
.i
= (UINT64
)(0x3ff + n
) << 52;
343 /* Copied from musl: src/math/__rem_pio2_large.c */
344 static int __rem_pio2_large(double *x
, double *y
, int e0
, int nx
, int prec
)
346 static const int init_jk
[] = {3, 4};
347 static const INT32 ipio2
[] = {
348 0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62,
349 0x95993C, 0x439041, 0xFE5163, 0xABDEBB, 0xC561B7, 0x246E3A,
350 0x424DD2, 0xE00649, 0x2EEA09, 0xD1921C, 0xFE1DEB, 0x1CB129,
351 0xA73EE8, 0x8235F5, 0x2EBB44, 0x84E99C, 0x7026B4, 0x5F7E41,
352 0x3991D6, 0x398353, 0x39F49C, 0x845F8B, 0xBDF928, 0x3B1FF8,
353 0x97FFDE, 0x05980F, 0xEF2F11, 0x8B5A0A, 0x6D1F6D, 0x367ECF,
354 0x27CB09, 0xB74F46, 0x3F669E, 0x5FEA2D, 0x7527BA, 0xC7EBE5,
355 0xF17B3D, 0x0739F7, 0x8A5292, 0xEA6BFB, 0x5FB11F, 0x8D5D08,
356 0x560330, 0x46FC7B, 0x6BABF0, 0xCFBC20, 0x9AF436, 0x1DA9E3,
357 0x91615E, 0xE61B08, 0x659985, 0x5F14A0, 0x68408D, 0xFFD880,
358 0x4D7327, 0x310606, 0x1556CA, 0x73A8C9, 0x60E27B, 0xC08C6B,
360 static const double PIo2
[] = {
361 1.57079625129699707031e+00,
362 7.54978941586159635335e-08,
363 5.39030252995776476554e-15,
364 3.28200341580791294123e-22,
365 1.27065575308067607349e-29,
366 1.22933308981111328932e-36,
367 2.73370053816464559624e-44,
368 2.16741683877804819444e-51,
371 INT32 jz
, jx
, jv
, jp
, jk
, carry
, n
, iq
[20], i
, j
, k
, m
, q0
, ih
;
372 double z
, fw
, f
[20], fq
[20] = {0}, q
[20];
378 /* determine jx,jv,q0, note that 3>q0 */
382 q0
= e0
- 24 * (jv
+ 1);
384 /* set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk] */
387 for (i
= 0; i
<= m
; i
++, j
++)
388 f
[i
] = j
< 0 ? 0.0 : (double)ipio2
[j
];
390 /* compute q[0],q[1],...q[jk] */
391 for (i
= 0; i
<= jk
; i
++) {
392 for (j
= 0, fw
= 0.0; j
<= jx
; j
++)
393 fw
+= x
[j
] * f
[jx
+ i
- j
];
399 /* distill q[] into iq[] reversingly */
400 for (i
= 0, j
= jz
, z
= q
[jz
]; j
> 0; i
++, j
--) {
401 fw
= (double)(INT32
)(0x1p
-24 * z
);
402 iq
[i
] = (INT32
)(z
- 0x1p
24 * fw
);
407 z
= __scalbn(z
, q0
); /* actual value of z */
408 z
-= 8.0 * floor(z
* 0.125); /* trim off integer >= 8 */
412 if (q0
> 0) { /* need iq[jz-1] to determine n */
413 i
= iq
[jz
- 1] >> (24 - q0
);
415 iq
[jz
- 1] -= i
<< (24 - q0
);
416 ih
= iq
[jz
- 1] >> (23 - q0
);
418 else if (q0
== 0) ih
= iq
[jz
- 1] >> 23;
419 else if (z
>= 0.5) ih
= 2;
421 if (ih
> 0) { /* q > 0.5 */
424 for (i
= 0; i
< jz
; i
++) { /* compute 1-q */
429 iq
[i
] = 0x1000000 - j
;
432 iq
[i
] = 0xffffff - j
;
434 if (q0
> 0) { /* rare case: chance is 1 in 12 */
437 iq
[jz
- 1] &= 0x7fffff;
440 iq
[jz
- 1] &= 0x3fffff;
447 z
-= __scalbn(1.0, q0
);
451 /* check if recomputation is needed */
454 for (i
= jz
- 1; i
>= jk
; i
--) j
|= iq
[i
];
455 if (j
== 0) { /* need recomputation */
456 for (k
= 1; iq
[jk
- k
] == 0; k
++); /* k = no. of terms needed */
458 for (i
= jz
+ 1; i
<= jz
+ k
; i
++) { /* add q[jz+1] to q[jz+k] */
459 f
[jx
+ i
] = (double)ipio2
[jv
+ i
];
460 for (j
= 0, fw
= 0.0; j
<= jx
; j
++)
461 fw
+= x
[j
] * f
[jx
+ i
- j
];
469 /* chop off zero terms */
473 while (iq
[jz
] == 0) {
477 } else { /* break z into 24-bit if necessary */
478 z
= __scalbn(z
, -q0
);
480 fw
= (double)(INT32
)(0x1p
-24 * z
);
481 iq
[jz
] = (INT32
)(z
- 0x1p
24 * fw
);
489 /* convert integer "bit" chunk to floating-point value */
490 fw
= __scalbn(1.0, q0
);
491 for (i
= jz
; i
>= 0; i
--) {
492 q
[i
] = fw
* (double)iq
[i
];
496 /* compute PIo2[0,...,jp]*q[jz,...,0] */
497 for(i
= jz
; i
>= 0; i
--) {
498 for (fw
= 0.0, k
= 0; k
<= jp
&& k
<= jz
- i
; k
++)
499 fw
+= PIo2
[k
] * q
[i
+ k
];
503 /* compress fq[] into y[] */
507 for (i
= jz
; i
>= 0; i
--)
509 y
[0] = ih
== 0 ? fw
: -fw
;
514 for (i
= jz
; i
>= 0; i
--)
517 y
[0] = ih
==0 ? fw
: -fw
;
519 for (i
= 1; i
<= jz
; i
++)
521 y
[1] = ih
== 0 ? fw
: -fw
;
523 case 3: /* painful */
524 for (i
= jz
; i
> 0; i
--) {
525 fw
= fq
[i
- 1] + fq
[i
];
526 fq
[i
] += fq
[i
- 1] - fw
;
529 for (i
= jz
; i
> 1; i
--) {
530 fw
= fq
[i
- 1] + fq
[i
];
531 fq
[i
] += fq
[i
- 1] - fw
;
534 for (fw
= 0.0, i
= jz
; i
>= 2; i
--)
549 /* Based on musl implementation: src/math/round.c */
550 static double __round(double x
)
552 ULONGLONG llx
= *(ULONGLONG
*)&x
, tmp
;
553 int e
= (llx
>> 52 & 0x7ff) - 0x3ff;
560 return signbit(x
) ? -1 : 1;
562 tmp
= 0x000fffffffffffffULL
>> e
;
565 llx
+= 0x0008000000000000ULL
>> e
;
567 return *(double*)&llx
;
570 #if !defined(__i386__) || _MSVCR_VER >= 120
571 /* Copied from musl: src/math/expm1f.c */
572 static float __expm1f(float x
)
574 static const float ln2_hi
= 6.9313812256e-01,
575 ln2_lo
= 9.0580006145e-06,
576 invln2
= 1.4426950216e+00,
577 Q1
= -3.3333212137e-2,
578 Q2
= 1.5807170421e-3;
580 float y
, hi
, lo
, c
, t
, e
, hxs
, hfx
, r1
, twopk
;
581 union {float f
; UINT32 i
;} u
= {x
};
582 UINT32 hx
= u
.i
& 0x7fffffff;
583 int k
, sign
= u
.i
>> 31;
585 /* filter out huge and non-finite argument */
586 if (hx
>= 0x4195b844) { /* if |x|>=27*ln2 */
587 if (hx
>= 0x7f800000) /* NaN */
588 return u
.i
== 0xff800000 ? -1 : x
;
590 return math_error(_UNDERFLOW
, "exp", x
, 0, -1);
591 if (hx
> 0x42b17217) /* x > log(FLT_MAX) */
592 return math_error(_OVERFLOW
, "exp", x
, 0, fp_barrierf(x
* FLT_MAX
));
595 /* argument reduction */
596 if (hx
> 0x3eb17218) { /* if |x| > 0.5 ln2 */
597 if (hx
< 0x3F851592) { /* and |x| < 1.5 ln2 */
608 k
= invln2
* x
+ (sign
? -0.5f
: 0.5f
);
610 hi
= x
- t
* ln2_hi
; /* t*ln2_hi is exact here */
615 } else if (hx
< 0x33000000) { /* when |x|<2**-25, return x */
622 /* x is now in primary range */
625 r1
= 1.0f
+ hxs
* (Q1
+ hxs
* Q2
);
627 e
= hxs
* ((r1
- t
) / (6.0f
- x
* t
));
628 if (k
== 0) /* c is 0 */
629 return x
- (x
* e
- hxs
);
632 /* exp(x) ~ 2^k (x_reduced - e + 1) */
634 return 0.5f
* (x
- e
) - 0.5f
;
637 return -2.0f
* (e
- (x
+ 0.5f
));
638 return 1.0f
+ 2.0f
* (x
- e
);
640 u
.i
= (0x7f + k
) << 23; /* 2^k */
642 if (k
< 0 || k
> 56) { /* suffice to return exp(x)-1 */
645 y
= y
* 2.0f
* 0x1p
127f
;
650 u
.i
= (0x7f-k
) << 23; /* 2^-k */
652 y
= (x
- e
+ (1 - u
.f
)) * twopk
;
654 y
= (x
- (e
+ u
.f
) + 1) * twopk
;
658 /* Copied from musl: src/math/__sindf.c */
659 static float __sindf(double x
)
661 static const double S1
= -0x1.5555555555555p
-3,
662 S2
= 0x1.1111111111111p
-7,
663 S3
= -0x1.a01a01a01a01ap
-13,
664 S4
= 0x1.71de3a556c734p
-19;
669 if (x
> -7.8175831586122513e-03 && x
< 7.8175831586122513e-03)
670 return x
* (1 + S1
* z
);
675 return (x
+ s
* (S1
+ z
* S2
)) + s
* w
* r
;
678 /* Copied from musl: src/math/__cosdf.c */
679 static float __cosdf(double x
)
681 static const double C0
= -0x1.0000000000000p
-1,
682 C1
= 0x1.5555555555555p
-5,
683 C2
= -0x1.6c16c16c16c17p
-10,
684 C3
= 0x1.a01a01a01a01ap
-16,
685 C4
= -0x1.27e4fb7789f5cp
-22;
689 if (x
> -7.8163146972656250e-03 && x
< 7.8163146972656250e-03)
691 return 1.0 + z
* (C0
+ z
* (C1
+ z
* (C2
+ z
* (C3
+ z
* C4
))));
694 static const UINT64 exp2f_T
[] = {
695 0x3ff0000000000000ULL
, 0x3fefd9b0d3158574ULL
, 0x3fefb5586cf9890fULL
, 0x3fef9301d0125b51ULL
,
696 0x3fef72b83c7d517bULL
, 0x3fef54873168b9aaULL
, 0x3fef387a6e756238ULL
, 0x3fef1e9df51fdee1ULL
,
697 0x3fef06fe0a31b715ULL
, 0x3feef1a7373aa9cbULL
, 0x3feedea64c123422ULL
, 0x3feece086061892dULL
,
698 0x3feebfdad5362a27ULL
, 0x3feeb42b569d4f82ULL
, 0x3feeab07dd485429ULL
, 0x3feea47eb03a5585ULL
,
699 0x3feea09e667f3bcdULL
, 0x3fee9f75e8ec5f74ULL
, 0x3feea11473eb0187ULL
, 0x3feea589994cce13ULL
,
700 0x3feeace5422aa0dbULL
, 0x3feeb737b0cdc5e5ULL
, 0x3feec49182a3f090ULL
, 0x3feed503b23e255dULL
,
701 0x3feee89f995ad3adULL
, 0x3feeff76f2fb5e47ULL
, 0x3fef199bdd85529cULL
, 0x3fef3720dcef9069ULL
,
702 0x3fef5818dcfba487ULL
, 0x3fef7c97337b9b5fULL
, 0x3fefa4afa2a490daULL
, 0x3fefd0765b6e4540ULL
706 /*********************************************************************
707 * _fdclass (MSVCR120.@)
709 * Copied from musl: src/math/__fpclassifyf.c
711 short CDECL
_fdclass(float x
)
713 union { float f
; UINT32 i
; } u
= { x
};
714 int e
= u
.i
>> 23 & 0xff;
716 if (!e
) return u
.i
<< 1 ? FP_SUBNORMAL
: FP_ZERO
;
717 if (e
== 0xff) return u
.i
<< 9 ? FP_NAN
: FP_INFINITE
;
721 /*********************************************************************
722 * _dclass (MSVCR120.@)
724 * Copied from musl: src/math/__fpclassify.c
726 short CDECL
_dclass(double x
)
728 union { double f
; UINT64 i
; } u
= { x
};
729 int e
= u
.i
>> 52 & 0x7ff;
731 if (!e
) return u
.i
<< 1 ? FP_SUBNORMAL
: FP_ZERO
;
732 if (e
== 0x7ff) return (u
.i
<< 12) ? FP_NAN
: FP_INFINITE
;
738 /*********************************************************************
739 * _fpclassf (MSVCRT.@)
741 int CDECL
_fpclassf( float num
)
743 union { float f
; UINT32 i
; } u
= { num
};
744 int e
= u
.i
>> 23 & 0xff;
750 if (u
.i
<< 1) return s
? _FPCLASS_ND
: _FPCLASS_PD
;
751 return s
? _FPCLASS_NZ
: _FPCLASS_PZ
;
753 if (u
.i
<< 9) return ((u
.i
>> 22) & 1) ? _FPCLASS_QNAN
: _FPCLASS_SNAN
;
754 return s
? _FPCLASS_NINF
: _FPCLASS_PINF
;
756 return s
? _FPCLASS_NN
: _FPCLASS_PN
;
760 /*********************************************************************
761 * _finitef (MSVCRT.@)
763 int CDECL
_finitef( float num
)
765 union { float f
; UINT32 i
; } u
= { num
};
766 return (u
.i
& 0x7fffffff) < 0x7f800000;
769 /*********************************************************************
772 int CDECL
_isnanf( float num
)
774 union { float f
; UINT32 i
; } u
= { num
};
775 return (u
.i
& 0x7fffffff) > 0x7f800000;
778 static float asinf_R(float z
)
780 /* coefficients for R(x^2) */
781 static const float p1
= 1.66666672e-01,
782 p2
= -5.11644611e-02,
783 p3
= -1.21124933e-02,
784 p4
= -3.58742251e-03,
785 q1
= -7.56982703e-01;
788 p
= z
* (p1
+ z
* (p2
+ z
* (p3
+ z
* p4
)));
793 /*********************************************************************
796 * Copied from musl: src/math/acosf.c
798 float CDECL
acosf( float x
)
800 static const double pio2_lo
= 6.12323399573676603587e-17;
801 static const double pio2_hi
= 1.57079632679489655800e+00;
803 float z
, w
, s
, c
, df
;
806 hx
= *(unsigned int*)&x
;
807 ix
= hx
& 0x7fffffff;
808 /* |x| >= 1 or nan */
809 if (ix
>= 0x3f800000) {
810 if (ix
== 0x3f800000) {
815 if (isnan(x
)) return x
;
816 return math_error(_DOMAIN
, "acosf", x
, 0, 0 / (x
- x
));
819 if (ix
< 0x3f000000) {
820 if (ix
<= 0x32800000) /* |x| < 2**-26 */
822 return pio2_hi
- (x
- (pio2_lo
- x
* asinf_R(x
* x
)));
828 return 2*(pio2_hi
- (s
+ (asinf_R(z
) * s
- pio2_lo
)));
833 hx
= *(unsigned int*)&s
& 0xffff0000;
835 c
= (z
- df
* df
) / (s
+ df
);
836 w
= asinf_R(z
) * s
+ c
;
840 /*********************************************************************
843 * Copied from musl: src/math/asinf.c
845 float CDECL
asinf( float x
)
847 static const double pio2
= 1.570796326794896558e+00;
848 static const float pio4_hi
= 0.785398125648;
849 static const float pio2_lo
= 7.54978941586e-08;
854 hx
= *(unsigned int*)&x
;
855 ix
= hx
& 0x7fffffff;
856 if (ix
>= 0x3f800000) { /* |x| >= 1 */
857 if (ix
== 0x3f800000) /* |x| == 1 */
858 return x
* pio2
+ 7.5231638453e-37; /* asin(+-1) = +-pi/2 with inexact */
859 if (isnan(x
)) return x
;
860 return math_error(_DOMAIN
, "asinf", x
, 0, 0 / (x
- x
));
862 if (ix
< 0x3f000000) { /* |x| < 0.5 */
863 /* if 0x1p-126 <= |x| < 0x1p-12, avoid raising underflow */
864 if (ix
< 0x39800000 && ix
>= 0x00800000)
866 return x
+ x
* asinf_R(x
* x
);
869 z
= (1 - fabsf(x
)) * 0.5f
;
872 *(unsigned int*)&f
= *(unsigned int*)&s
& 0xffff0000;
873 c
= (z
- f
* f
) / (s
+ f
);
874 x
= pio4_hi
- (2 * s
* asinf_R(z
) - (pio2_lo
- 2 * c
) - (pio4_hi
- 2 * f
));
880 /*********************************************************************
883 * Copied from musl: src/math/atanf.c
885 float CDECL
atanf( float x
)
887 static const float atanhi
[] = {
893 static const float atanlo
[] = {
899 static const float aT
[] = {
908 unsigned int ix
, sign
;
912 if (isnan(x
)) return math_error(_DOMAIN
, "atanf", x
, 0, x
);
915 ix
= *(unsigned int*)&x
;
918 if (ix
>= 0x4c800000) { /* if |x| >= 2**26 */
921 z
= atanhi
[3] + 7.5231638453e-37;
922 return sign
? -z
: z
;
924 if (ix
< 0x3ee00000) { /* |x| < 0.4375 */
925 if (ix
< 0x39800000) { /* |x| < 2**-12 */
927 /* raise underflow for subnormal x */
934 if (ix
< 0x3f980000) { /* |x| < 1.1875 */
935 if (ix
< 0x3f300000) { /* 7/16 <= |x| < 11/16 */
937 x
= (2.0f
* x
- 1.0f
) / (2.0f
+ x
);
938 } else { /* 11/16 <= |x| < 19/16 */
940 x
= (x
- 1.0f
) / (x
+ 1.0f
);
943 if (ix
< 0x401c0000) { /* |x| < 2.4375 */
945 x
= (x
- 1.5f
) / (1.0f
+ 1.5f
* x
);
946 } else { /* 2.4375 <= |x| < 2**26 */
952 /* end of argument reduction */
955 /* break sum from i=0 to 10 aT[i]z**(i+1) into odd and even poly */
956 s1
= z
* (aT
[0] + w
* (aT
[2] + w
* aT
[4]));
957 s2
= w
* (aT
[1] + w
* aT
[3]);
959 return x
- x
* (s1
+ s2
);
960 z
= atanhi
[id
] - ((x
* (s1
+ s2
) - atanlo
[id
]) - x
);
961 return sign
? -z
: z
;
964 /*********************************************************************
967 * Copied from musl: src/math/atan2f.c
969 float CDECL
atan2f( float y
, float x
)
971 static const float pi
= 3.1415927410e+00,
972 pi_lo
= -8.7422776573e-08;
975 unsigned int m
, ix
, iy
;
977 if (isnan(x
) || isnan(y
))
979 ix
= *(unsigned int*)&x
;
980 iy
= *(unsigned int*)&y
;
981 if (ix
== 0x3f800000) /* x=1.0 */
983 m
= ((iy
>> 31) & 1) | ((ix
>> 30) & 2); /* 2*sign(x)+sign(y) */
991 case 1: return y
; /* atan(+-0,+anything)=+-0 */
992 case 2: return pi
; /* atan(+0,-anything) = pi */
993 case 3: return -pi
; /* atan(-0,-anything) =-pi */
998 return m
& 1 ? -pi
/ 2 : pi
/ 2;
1000 if (ix
== 0x7f800000) {
1001 if (iy
== 0x7f800000) {
1003 case 0: return pi
/ 4; /* atan(+INF,+INF) */
1004 case 1: return -pi
/ 4; /* atan(-INF,+INF) */
1005 case 2: return 3 * pi
/ 4; /*atan(+INF,-INF)*/
1006 case 3: return -3 * pi
/ 4; /*atan(-INF,-INF)*/
1010 case 0: return 0.0f
; /* atan(+...,+INF) */
1011 case 1: return -0.0f
; /* atan(-...,+INF) */
1012 case 2: return pi
; /* atan(+...,-INF) */
1013 case 3: return -pi
; /* atan(-...,-INF) */
1017 /* |y/x| > 0x1p26 */
1018 if (ix
+ (26 << 23) < iy
|| iy
== 0x7f800000)
1019 return m
& 1 ? -pi
/ 2 : pi
/ 2;
1021 /* z = atan(|y/x|) with correct underflow */
1022 if ((m
& 2) && iy
+ (26 << 23) < ix
) /*|y/x| < 0x1p-26, x < 0 */
1025 z
= atanf(fabsf(y
/ x
));
1027 case 0: return z
; /* atan(+,+) */
1028 case 1: return -z
; /* atan(-,+) */
1029 case 2: return pi
- (z
- pi_lo
); /* atan(+,-) */
1030 default: /* case 3 */
1031 return (z
- pi_lo
) - pi
; /* atan(-,-) */
1035 /* Copied from musl: src/math/__rem_pio2f.c */
1036 static int __rem_pio2f(float x
, double *y
)
1038 static const double toint
= 1.5 / DBL_EPSILON
,
1039 pio4
= 0x1.921fb6p
-1,
1040 invpio2
= 6.36619772367581382433e-01,
1041 pio2_1
= 1.57079631090164184570e+00,
1042 pio2_1t
= 1.58932547735281966916e-08;
1044 union {float f
; uint32_t i
;} u
= {x
};
1045 double tx
[1], ty
[1], fn
;
1049 ix
= u
.i
& 0x7fffffff;
1050 /* 25+53 bit pi is good enough for medium size */
1051 if (ix
< 0x4dc90fdb) { /* |x| ~< 2^28*(pi/2), medium size */
1052 /* Use a specialized rint() to get fn. */
1053 fn
= fp_barrier(x
* invpio2
+ toint
) - toint
;
1055 *y
= x
- fn
* pio2_1
- fn
* pio2_1t
;
1056 /* Matters with directed rounding. */
1060 *y
= x
- fn
* pio2_1
- fn
* pio2_1t
;
1061 } else if (*y
> pio4
) {
1064 *y
= x
- fn
* pio2_1
- fn
* pio2_1t
;
1068 if(ix
>= 0x7f800000) { /* x is inf or NaN */
1072 /* scale x into [2^23, 2^24-1] */
1074 e0
= (ix
>> 23) - (0x7f + 23); /* e0 = ilogb(|x|)-23, positive */
1075 u
.i
= ix
- (e0
<< 23);
1077 n
= __rem_pio2_large(tx
, ty
, e0
, 1, 0);
1086 /*********************************************************************
1089 * Copied from musl: src/math/cosf.c
1091 float CDECL
cosf( float x
)
1093 static const double c1pio2
= 1*M_PI_2
,
1106 if (ix
<= 0x3f490fda) { /* |x| ~<= pi/4 */
1107 if (ix
< 0x39800000) { /* |x| < 2**-12 */
1108 /* raise inexact if x != 0 */
1109 fp_barrierf(x
+ 0x1p
120f
);
1114 if (ix
<= 0x407b53d1) { /* |x| ~<= 5*pi/4 */
1115 if (ix
> 0x4016cbe3) /* |x| ~> 3*pi/4 */
1116 return -__cosdf(sign
? x
+ c2pio2
: x
- c2pio2
);
1119 return __sindf(x
+ c1pio2
);
1121 return __sindf(c1pio2
- x
);
1124 if (ix
<= 0x40e231d5) { /* |x| ~<= 9*pi/4 */
1125 if (ix
> 0x40afeddf) /* |x| ~> 7*pi/4 */
1126 return __cosdf(sign
? x
+ c4pio2
: x
- c4pio2
);
1129 return __sindf(-x
- c3pio2
);
1131 return __sindf(x
- c3pio2
);
1135 /* cos(Inf or NaN) is NaN */
1136 if (isinf(x
)) return math_error(_DOMAIN
, "cosf", x
, 0, x
- x
);
1137 if (ix
>= 0x7f800000)
1140 /* general argument reduction needed */
1141 n
= __rem_pio2f(x
, &y
);
1143 case 0: return __cosdf(y
);
1144 case 1: return __sindf(-y
);
1145 case 2: return -__cosdf(y
);
1146 default: return __sindf(y
);
1150 /* Copied from musl: src/math/__expo2f.c */
1151 static float __expo2f(float x
, float sign
)
1153 static const int k
= 235;
1154 static const float kln2
= 0x1.45c778p
+7f
;
1157 *(UINT32
*)&scale
= (UINT32
)(0x7f + k
/2) << 23;
1158 return expf(x
- kln2
) * (sign
* scale
) * scale
;
1161 /*********************************************************************
1164 * Copied from musl: src/math/coshf.c
1166 float CDECL
coshf( float x
)
1168 UINT32 ui
= *(UINT32
*)&x
;
1169 UINT32 sign
= ui
& 0x80000000;
1177 if (ui
< 0x3f317217) {
1178 if (ui
< 0x3f800000 - (12 << 23)) {
1179 fp_barrierf(x
+ 0x1p
120f
);
1183 return 1 + t
* t
/ (2 * (1 + t
));
1186 /* |x| < log(FLT_MAX) */
1187 if (ui
< 0x42b17217) {
1189 return 0.5f
* (t
+ 1 / t
);
1192 /* |x| > log(FLT_MAX) or nan */
1193 if (ui
> 0x7f800000)
1194 *(UINT32
*)&t
= ui
| sign
| 0x400000;
1196 t
= __expo2f(x
, 1.0f
);
1200 /*********************************************************************
1203 float CDECL
expf( float x
)
1205 static const double C
[] = {
1206 0x1.c6af84b912394p
-5 / (1 << 5) / (1 << 5) / (1 << 5),
1207 0x1.ebfce50fac4f3p
-3 / (1 << 5) / (1 << 5),
1208 0x1.62e42ff0c52d6p
-1 / (1 << 5)
1210 static const double invln2n
= 0x1.71547652b82fep
+0 * (1 << 5);
1212 double kd
, z
, r
, r2
, y
, s
;
1216 abstop
= (*(UINT32
*)&x
>> 20) & 0x7ff;
1217 if (abstop
>= 0x42b) {
1218 /* |x| >= 88 or x is nan. */
1219 if (*(UINT32
*)&x
== 0xff800000)
1221 if (abstop
>= 0x7f8)
1223 if (x
> 0x1.62e42ep6f
) /* x > log(0x1p128) ~= 88.72 */
1224 return math_error(_OVERFLOW
, "expf", x
, 0, x
* FLT_MAX
);
1225 if (x
< -0x1.9fe368p6f
) /* x < log(0x1p-150) ~= -103.97 */
1226 return math_error(_UNDERFLOW
, "expf", x
, 0, fp_barrierf(FLT_MIN
) * FLT_MIN
);
1229 /* x*N/Ln2 = k + r with r in [-1/2, 1/2] and int k. */
1232 /* Round and convert z to int, the result is in [-150*N, 128*N] and
1233 ideally ties-to-even rule is used, otherwise the magnitude of r
1234 can be bigger which gives larger approximation error. */
1239 /* exp(x) = 2^(k/N) * 2^(r/N) ~= s * (C0*r^3 + C1*r^2 + C2*r + 1) */
1240 t
= exp2f_T
[ki
% (1 << 5)];
1241 t
+= ki
<< (52 - 5);
1243 z
= C
[0] * r
+ C
[1];
1251 /*********************************************************************
1254 * Copied from musl: src/math/fmodf.c
1256 float CDECL
fmodf( float x
, float y
)
1258 UINT32 xi
= *(UINT32
*)&x
;
1259 UINT32 yi
= *(UINT32
*)&y
;
1260 int ex
= xi
>>23 & 0xff;
1261 int ey
= yi
>>23 & 0xff;
1262 UINT32 sx
= xi
& 0x80000000;
1265 if (isinf(x
)) return math_error(_DOMAIN
, "fmodf", x
, y
, (x
* y
) / (x
* y
));
1266 if (yi
<< 1 == 0 || isnan(y
) || ex
== 0xff)
1267 return (x
* y
) / (x
* y
);
1268 if (xi
<< 1 <= yi
<< 1) {
1269 if (xi
<< 1 == yi
<< 1)
1274 /* normalize x and y */
1276 for (i
= xi
<< 9; i
>> 31 == 0; ex
--, i
<<= 1);
1283 for (i
= yi
<< 9; i
>> 31 == 0; ey
--, i
<<= 1);
1291 for (; ex
> ey
; ex
--) {
1306 for (; xi
>>23 == 0; xi
<<= 1, ex
--);
1308 /* scale result up */
1311 xi
|= (UINT32
)ex
<< 23;
1316 return *(float*)&xi
;
1319 /*********************************************************************
1322 * Copied from musl: src/math/logf.c src/math/logf_data.c
1324 float CDECL
logf( float x
)
1326 static const double Ln2
= 0x1.62e42fefa39efp
-1;
1327 static const double A
[] = {
1328 -0x1.00ea348b88334p
-2,
1329 0x1.5575b0be00b6ap
-2,
1330 -0x1.ffffef20a4123p
-2
1332 static const struct {
1335 { 0x1.661ec79f8f3bep
+0, -0x1.57bf7808caadep
-2 },
1336 { 0x1.571ed4aaf883dp
+0, -0x1.2bef0a7c06ddbp
-2 },
1337 { 0x1.49539f0f010bp
+0, -0x1.01eae7f513a67p
-2 },
1338 { 0x1.3c995b0b80385p
+0, -0x1.b31d8a68224e9p
-3 },
1339 { 0x1.30d190c8864a5p
+0, -0x1.6574f0ac07758p
-3 },
1340 { 0x1.25e227b0b8eap
+0, -0x1.1aa2bc79c81p
-3 },
1341 { 0x1.1bb4a4a1a343fp
+0, -0x1.a4e76ce8c0e5ep
-4 },
1342 { 0x1.12358f08ae5bap
+0, -0x1.1973c5a611cccp
-4 },
1343 { 0x1.0953f419900a7p
+0, -0x1.252f438e10c1ep
-5 },
1345 { 0x1.e608cfd9a47acp
-1, 0x1.aa5aa5df25984p
-5 },
1346 { 0x1.ca4b31f026aap
-1, 0x1.c5e53aa362eb4p
-4 },
1347 { 0x1.b2036576afce6p
-1, 0x1.526e57720db08p
-3 },
1348 { 0x1.9c2d163a1aa2dp
-1, 0x1.bc2860d22477p
-3 },
1349 { 0x1.886e6037841edp
-1, 0x1.1058bc8a07ee1p
-2 },
1350 { 0x1.767dcf5534862p
-1, 0x1.4043057b6ee09p
-2 }
1353 double z
, r
, r2
, y
, y0
, invc
, logc
;
1358 /* Fix sign of zero with downward rounding when x==1. */
1359 if (ix
== 0x3f800000)
1361 if (ix
- 0x00800000 >= 0x7f800000 - 0x00800000) {
1362 /* x < 0x1p-126 or inf or nan. */
1364 return math_error(_SING
, "logf", x
, 0, (ix
& 0x80000000 ? 1.0 : -1.0) / x
);
1365 if (ix
== 0x7f800000) /* log(inf) == inf. */
1367 if (ix
* 2 > 0xff000000)
1369 if (ix
& 0x80000000)
1370 return math_error(_DOMAIN
, "logf", x
, 0, (x
- x
) / (x
- x
));
1371 /* x is subnormal, normalize it. */
1377 /* x = 2^k z; where z is in range [OFF,2*OFF] and exact.
1378 The range is split into N subintervals.
1379 The ith subinterval contains z and c is near its center. */
1380 tmp
= ix
- 0x3f330000;
1381 i
= (tmp
>> (23 - 4)) % (1 << 4);
1382 k
= (INT32
)tmp
>> 23; /* arithmetic shift */
1383 iz
= ix
- (tmp
& (0x1ffu
<< 23));
1388 /* log(x) = log1p(z/c-1) + log(c) + k*Ln2 */
1390 y0
= logc
+ (double)k
* Ln2
;
1392 /* Pipelined polynomial evaluation to approximate log1p(r). */
1394 y
= A
[1] * r
+ A
[2];
1396 y
= y
* r2
+ (y0
+ r
);
1400 /*********************************************************************
1403 float CDECL
log10f( float x
)
1405 static const float ivln10hi
= 4.3432617188e-01,
1406 ivln10lo
= -3.1689971365e-05,
1407 log10_2hi
= 3.0102920532e-01,
1408 log10_2lo
= 7.9034151668e-07,
1409 Lg1
= 0xaaaaaa.0p
-24,
1410 Lg2
= 0xccce13.0p
-25,
1411 Lg3
= 0x91e9ee.0p
-25,
1412 Lg4
= 0xf89e26.0p
-26;
1414 union {float f
; UINT32 i
;} u
= {x
};
1415 float hfsq
, f
, s
, z
, R
, w
, t1
, t2
, dk
, hi
, lo
;
1421 if (ix
< 0x00800000 || ix
>> 31) { /* x < 2**-126 */
1423 return math_error(_SING
, "log10f", x
, 0, -1 / (x
* x
));
1424 if ((ix
& ~(1u << 31)) > 0x7f800000)
1427 return math_error(_DOMAIN
, "log10f", x
, 0, (x
- x
) / (x
- x
));
1428 /* subnormal number, scale up x */
1433 } else if (ix
>= 0x7f800000) {
1435 } else if (ix
== 0x3f800000)
1438 /* reduce x into [sqrt(2)/2, sqrt(2)] */
1439 ix
+= 0x3f800000 - 0x3f3504f3;
1440 k
+= (int)(ix
>> 23) - 0x7f;
1441 ix
= (ix
& 0x007fffff) + 0x3f3504f3;
1449 t1
= w
* (Lg2
+ w
* Lg4
);
1450 t2
= z
* (Lg1
+ w
* Lg3
);
1452 hfsq
= 0.5f
* f
* f
;
1458 lo
= f
- hi
- hfsq
+ s
* (hfsq
+ R
);
1460 return dk
* log10_2lo
+ (lo
+ hi
) * ivln10lo
+ lo
* ivln10hi
+ hi
* ivln10hi
+ dk
* log10_2hi
;
1463 /* Subnormal input is normalized so ix has negative biased exponent.
1464 Output is multiplied by POWF_SCALE (where 1 << 5). */
1465 static double powf_log2(UINT32 ix
)
1467 static const struct {
1470 { 0x1.661ec79f8f3bep
+0, -0x1.efec65b963019p
-2 * (1 << 5) },
1471 { 0x1.571ed4aaf883dp
+0, -0x1.b0b6832d4fca4p
-2 * (1 << 5) },
1472 { 0x1.49539f0f010bp
+0, -0x1.7418b0a1fb77bp
-2 * (1 << 5) },
1473 { 0x1.3c995b0b80385p
+0, -0x1.39de91a6dcf7bp
-2 * (1 << 5) },
1474 { 0x1.30d190c8864a5p
+0, -0x1.01d9bf3f2b631p
-2 * (1 << 5) },
1475 { 0x1.25e227b0b8eap
+0, -0x1.97c1d1b3b7afp
-3 * (1 << 5) },
1476 { 0x1.1bb4a4a1a343fp
+0, -0x1.2f9e393af3c9fp
-3 * (1 << 5) },
1477 { 0x1.12358f08ae5bap
+0, -0x1.960cbbf788d5cp
-4 * (1 << 5) },
1478 { 0x1.0953f419900a7p
+0, -0x1.a6f9db6475fcep
-5 * (1 << 5) },
1479 { 0x1p
+0, 0x0p
+0 * (1 << 4) },
1480 { 0x1.e608cfd9a47acp
-1, 0x1.338ca9f24f53dp
-4 * (1 << 5) },
1481 { 0x1.ca4b31f026aap
-1, 0x1.476a9543891bap
-3 * (1 << 5) },
1482 { 0x1.b2036576afce6p
-1, 0x1.e840b4ac4e4d2p
-3 * (1 << 5) },
1483 { 0x1.9c2d163a1aa2dp
-1, 0x1.40645f0c6651cp
-2 * (1 << 5) },
1484 { 0x1.886e6037841edp
-1, 0x1.88e9c2c1b9ff8p
-2 * (1 << 5) },
1485 { 0x1.767dcf5534862p
-1, 0x1.ce0a44eb17bccp
-2 * (1 << 5) }
1487 static const double A
[] = {
1488 0x1.27616c9496e0bp
-2 * (1 << 5), -0x1.71969a075c67ap
-2 * (1 << 5),
1489 0x1.ec70a6ca7baddp
-2 * (1 << 5), -0x1.7154748bef6c8p
-1 * (1 << 5),
1490 0x1.71547652ab82bp0
* (1 << 5)
1493 double z
, r
, r2
, r4
, p
, q
, y
, y0
, invc
, logc
;
1494 UINT32 iz
, top
, tmp
;
1497 /* x = 2^k z; where z is in range [OFF,2*OFF] and exact.
1498 The range is split into N subintervals.
1499 The ith subinterval contains z and c is near its center. */
1500 tmp
= ix
- 0x3f330000;
1501 i
= (tmp
>> (23 - 4)) % (1 << 4);
1502 top
= tmp
& 0xff800000;
1504 k
= (INT32
)top
>> (23 - 5); /* arithmetic shift */
1509 /* log2(x) = log1p(z/c-1)/ln2 + log2(c) + k */
1511 y0
= logc
+ (double)k
;
1513 /* Pipelined polynomial evaluation to approximate log1p(r)/ln2. */
1515 y
= A
[0] * r
+ A
[1];
1516 p
= A
[2] * r
+ A
[3];
1524 /* The output of log2 and thus the input of exp2 is either scaled by N
1525 (in case of fast toint intrinsics) or not. The unscaled xd must be
1526 in [-1021,1023], sign_bias sets the sign of the result. */
1527 static float powf_exp2(double xd
, UINT32 sign_bias
)
1529 static const double C
[] = {
1530 0x1.c6af84b912394p
-5 / (1 << 5) / (1 << 5) / (1 << 5),
1531 0x1.ebfce50fac4f3p
-3 / (1 << 5) / (1 << 5),
1532 0x1.62e42ff0c52d6p
-1 / (1 << 5)
1536 double kd
, z
, r
, r2
, y
, s
;
1538 /* N*x = k + r with r in [-1/2, 1/2] */
1539 kd
= __round(xd
); /* k */
1543 /* exp2(x) = 2^(k/N) * 2^r ~= s * (C0*r^3 + C1*r^2 + C2*r + 1) */
1544 t
= exp2f_T
[ki
% (1 << 5)];
1545 ski
= ki
+ sign_bias
;
1546 t
+= ski
<< (52 - 5);
1548 z
= C
[0] * r
+ C
[1];
1556 /* Returns 0 if not int, 1 if odd int, 2 if even int. The argument is
1557 the bit representation of a non-zero finite floating-point value. */
1558 static int powf_checkint(UINT32 iy
)
1560 int e
= iy
>> 23 & 0xff;
1565 if (iy
& ((1 << (0x7f + 23 - e
)) - 1))
1567 if (iy
& (1 << (0x7f + 23 - e
)))
1572 /*********************************************************************
1575 * Copied from musl: src/math/powf.c src/math/powf_data.c
1577 float CDECL
powf( float x
, float y
)
1579 UINT32 sign_bias
= 0;
1585 if (ix
- 0x00800000 >= 0x7f800000 - 0x00800000 ||
1586 2 * iy
- 1 >= 2u * 0x7f800000 - 1) {
1587 /* Either (x < 0x1p-126 or inf or nan) or (y is 0 or inf or nan). */
1588 if (2 * iy
- 1 >= 2u * 0x7f800000 - 1) {
1591 if (ix
== 0x3f800000)
1593 if (2 * ix
> 2u * 0x7f800000 || 2 * iy
> 2u * 0x7f800000)
1595 if (2 * ix
== 2 * 0x3f800000)
1597 if ((2 * ix
< 2 * 0x3f800000) == !(iy
& 0x80000000))
1598 return 0.0f
; /* |x|<1 && y==inf or |x|>1 && y==-inf. */
1601 if (2 * ix
- 1 >= 2u * 0x7f800000 - 1) {
1603 if (ix
& 0x80000000 && powf_checkint(iy
) == 1)
1605 if (iy
& 0x80000000 && x2
== 0.0)
1606 return math_error(_SING
, "powf", x
, y
, 1 / x2
);
1607 /* Without the barrier some versions of clang hoist the 1/x2 and
1608 thus division by zero exception can be signaled spuriously. */
1609 return iy
& 0x80000000 ? fp_barrierf(1 / x2
) : x2
;
1611 /* x and y are non-zero finite. */
1612 if (ix
& 0x80000000) {
1614 int yint
= powf_checkint(iy
);
1616 return math_error(_DOMAIN
, "powf", x
, y
, 0 / (x
- x
));
1618 sign_bias
= 1 << (5 + 11);
1621 if (ix
< 0x00800000) {
1622 /* Normalize subnormal x so exponent becomes negative. */
1629 logx
= powf_log2(ix
);
1630 ylogx
= y
* logx
; /* cannot overflow, y is single prec. */
1631 if ((*(UINT64
*)&ylogx
>> 47 & 0xffff) >= 0x40af800000000000llu
>> 47) {
1632 /* |y*log(x)| >= 126. */
1633 if (ylogx
> 0x1.fffffffd1d571p
+6 * (1 << 5))
1634 return math_error(_OVERFLOW
, "powf", x
, y
, (sign_bias
? -1.0 : 1.0) * 0x1p
1023);
1635 if (ylogx
<= -150.0 * (1 << 5))
1636 return math_error(_UNDERFLOW
, "powf", x
, y
, (sign_bias
? -1.0 : 1.0) / 0x1p
1023);
1638 return powf_exp2(ylogx
, sign_bias
);
1641 /*********************************************************************
1644 * Copied from musl: src/math/sinf.c
1646 float CDECL
sinf( float x
)
1648 static const double s1pio2
= 1*M_PI_2
,
1661 if (ix
<= 0x3f490fda) { /* |x| ~<= pi/4 */
1662 if (ix
< 0x39800000) { /* |x| < 2**-12 */
1663 /* raise inexact if x!=0 and underflow if subnormal */
1664 fp_barrierf(ix
< 0x00800000 ? x
/ 0x1p
120f
: x
+ 0x1p
120f
);
1669 if (ix
<= 0x407b53d1) { /* |x| ~<= 5*pi/4 */
1670 if (ix
<= 0x4016cbe3) { /* |x| ~<= 3pi/4 */
1672 return -__cosdf(x
+ s1pio2
);
1674 return __cosdf(x
- s1pio2
);
1676 return __sindf(sign
? -(x
+ s2pio2
) : -(x
- s2pio2
));
1678 if (ix
<= 0x40e231d5) { /* |x| ~<= 9*pi/4 */
1679 if (ix
<= 0x40afeddf) { /* |x| ~<= 7*pi/4 */
1681 return __cosdf(x
+ s3pio2
);
1683 return -__cosdf(x
- s3pio2
);
1685 return __sindf(sign
? x
+ s4pio2
: x
- s4pio2
);
1688 /* sin(Inf or NaN) is NaN */
1690 return math_error(_DOMAIN
, "sinf", x
, 0, x
- x
);
1691 if (ix
>= 0x7f800000)
1694 /* general argument reduction needed */
1695 n
= __rem_pio2f(x
, &y
);
1697 case 0: return __sindf(y
);
1698 case 1: return __cosdf(y
);
1699 case 2: return __sindf(-y
);
1700 default: return -__cosdf(y
);
1704 /*********************************************************************
1707 float CDECL
sinhf( float x
)
1709 UINT32 ui
= *(UINT32
*)&x
;
1717 absx
= *(float*)&ui
;
1719 /* |x| < log(FLT_MAX) */
1720 if (ui
< 0x42b17217) {
1722 if (ui
< 0x3f800000) {
1723 if (ui
< 0x3f800000 - (12 << 23))
1725 return h
* (2 * t
- t
* t
/ (t
+ 1));
1727 return h
* (t
+ t
/ (t
+ 1));
1730 /* |x| > logf(FLT_MAX) or nan */
1731 if (ui
> 0x7f800000)
1732 *(DWORD
*)&t
= *(DWORD
*)&x
| 0x400000;
1734 t
= __expo2f(absx
, 2 * h
);
1738 static BOOL
sqrtf_validate( float *x
)
1740 short c
= _fdclass(*x
);
1742 if (c
== FP_ZERO
) return FALSE
;
1743 if (c
== FP_NAN
) return FALSE
;
1746 *x
= math_error(_DOMAIN
, "sqrtf", *x
, 0, ret_nan(TRUE
));
1749 if (c
== FP_INFINITE
) return FALSE
;
1753 #if defined(__x86_64__) || defined(__i386__)
1754 float CDECL
sse2_sqrtf(float);
1755 __ASM_GLOBAL_FUNC( sse2_sqrtf
,
1756 "sqrtss %xmm0, %xmm0\n\t"
1760 /*********************************************************************
1763 * Copied from musl: src/math/sqrtf.c
1765 float CDECL
sqrtf( float x
)
1768 if (!sqrtf_validate(&x
))
1771 return sse2_sqrtf(x
);
1773 static const float tiny
= 1.0e-30;
1781 if (!sqrtf_validate(&x
))
1786 if (m
== 0) { /* subnormal x */
1787 for (i
= 0; (ix
& 0x00800000) == 0; i
++)
1791 m
-= 127; /* unbias exponent */
1792 ix
= (ix
& 0x007fffff) | 0x00800000;
1793 if (m
& 1) /* odd m, double x to make it even */
1795 m
>>= 1; /* m = [m/2] */
1797 /* generate sqrt(x) bit by bit */
1799 q
= s
= 0; /* q = sqrt(x) */
1800 r
= 0x01000000; /* r = moving bit from right to left */
1813 /* use floating add to find out rounding direction */
1815 z
= 1.0f
- tiny
; /* raise inexact flag */
1824 ix
= (q
>> 1) + 0x3f000000;
1825 r
= ix
+ ((unsigned int)m
<< 23);
1831 /* Copied from musl: src/math/__tandf.c */
1832 static float __tandf(double x
, int odd
)
1834 static const double T
[] = {
1835 0x15554d3418c99f.0p
-54,
1836 0x1112fd38999f72.0p
-55,
1837 0x1b54c91d865afe.0p
-57,
1838 0x191df3908c33ce.0p
-58,
1839 0x185dadfcecf44e.0p
-61,
1840 0x1362b9bf971bcd.0p
-59,
1843 double z
, r
, w
, s
, t
, u
;
1846 r
= T
[4] + z
* T
[5];
1847 t
= T
[2] + z
* T
[3];
1850 u
= T
[0] + z
* T
[1];
1851 r
= (x
+ s
* u
) + (s
* w
) * (t
+ w
* r
);
1852 return odd
? -1.0 / r
: r
;
1855 /*********************************************************************
1858 * Copied from musl: src/math/tanf.c
1860 float CDECL
tanf( float x
)
1862 static const double t1pio2
= 1*M_PI_2
,
1875 if (ix
<= 0x3f490fda) { /* |x| ~<= pi/4 */
1876 if (ix
< 0x39800000) { /* |x| < 2**-12 */
1877 /* raise inexact if x!=0 and underflow if subnormal */
1878 fp_barrierf(ix
< 0x00800000 ? x
/ 0x1p
120f
: x
+ 0x1p
120f
);
1881 return __tandf(x
, 0);
1883 if (ix
<= 0x407b53d1) { /* |x| ~<= 5*pi/4 */
1884 if (ix
<= 0x4016cbe3) /* |x| ~<= 3pi/4 */
1885 return __tandf((sign
? x
+ t1pio2
: x
- t1pio2
), 1);
1887 return __tandf((sign
? x
+ t2pio2
: x
- t2pio2
), 0);
1889 if (ix
<= 0x40e231d5) { /* |x| ~<= 9*pi/4 */
1890 if (ix
<= 0x40afeddf) /* |x| ~<= 7*pi/4 */
1891 return __tandf((sign
? x
+ t3pio2
: x
- t3pio2
), 1);
1893 return __tandf((sign
? x
+ t4pio2
: x
- t4pio2
), 0);
1896 /* tan(Inf or NaN) is NaN */
1898 return math_error(_DOMAIN
, "tanf", x
, 0, x
- x
);
1899 if (ix
>= 0x7f800000)
1902 /* argument reduction */
1903 n
= __rem_pio2f(x
, &y
);
1904 return __tandf(y
, n
& 1);
1907 /*********************************************************************
1910 float CDECL
tanhf( float x
)
1912 UINT32 ui
= *(UINT32
*)&x
;
1913 UINT32 sign
= ui
& 0x80000000;
1920 if (ui
> 0x3f0c9f54) {
1921 /* |x| > log(3)/2 ~= 0.5493 or nan */
1922 if (ui
> 0x41200000) {
1923 if (ui
> 0x7f800000) {
1924 *(UINT32
*)&x
= ui
| sign
| 0x400000;
1925 #if _MSVCR_VER < 140
1926 return math_error(_DOMAIN
, "tanhf", x
, 0, x
);
1932 fp_barrierf(x
+ 0x1p
120f
);
1935 t
= __expm1f(2 * x
);
1936 t
= 1 - 2 / (t
+ 2);
1938 } else if (ui
> 0x3e82c578) {
1939 /* |x| > log(5/3)/2 ~= 0.2554 */
1940 t
= __expm1f(2 * x
);
1942 } else if (ui
>= 0x00800000) {
1943 /* |x| >= 0x1p-126 */
1944 t
= __expm1f(-2 * x
);
1947 /* |x| is subnormal */
1951 return sign
? -t
: t
;
1954 /*********************************************************************
1957 * Copied from musl: src/math/ceilf.c
1959 float CDECL
ceilf( float x
)
1961 union {float f
; UINT32 i
;} u
= {x
};
1962 int e
= (int)(u
.i
>> 23 & 0xff) - 0x7f;
1968 m
= 0x007fffff >> e
;
1983 /*********************************************************************
1986 * Copied from musl: src/math/floorf.c
1988 float CDECL
floorf( float x
)
1990 union {float f
; UINT32 i
;} u
= {x
};
1991 int e
= (int)(u
.i
>> 23 & 0xff) - 0x7f;
1997 m
= 0x007fffff >> e
;
2012 /*********************************************************************
2015 * Copied from musl: src/math/frexpf.c
2017 float CDECL
frexpf( float x
, int *e
)
2019 UINT32 ux
= *(UINT32
*)&x
;
2020 int ee
= ux
>> 23 & 0xff;
2024 x
= frexpf(x
* 0x1p
64, e
);
2028 } else if (ee
== 0xff) {
2035 return *(float*)&ux
;
2038 /*********************************************************************
2041 * Copied from musl: src/math/modff.c
2043 float CDECL
modff( float x
, float *iptr
)
2045 union {float f
; UINT32 i
;} u
= {x
};
2047 int e
= (u
.i
>> 23 & 0xff) - 0x7f;
2049 /* no fractional part */
2052 if (e
== 0x80 && u
.i
<< 9 != 0) { /* nan */
2058 /* no integral part */
2065 mask
= 0x007fffff >> e
;
2066 if ((u
.i
& mask
) == 0) {
2078 #if !defined(__i386__) && !defined(__x86_64__) && (_MSVCR_VER == 0 || _MSVCR_VER >= 110)
2080 /*********************************************************************
2083 * Copied from musl: src/math/fabsf.c
2085 float CDECL
fabsf( float x
)
2087 union { float f
; UINT32 i
; } u
= { x
};
2094 /*********************************************************************
2097 * Copied from musl: src/math/acos.c
2099 static double acos_R(double z
)
2101 static const double pS0
= 1.66666666666666657415e-01,
2102 pS1
= -3.25565818622400915405e-01,
2103 pS2
= 2.01212532134862925881e-01,
2104 pS3
= -4.00555345006794114027e-02,
2105 pS4
= 7.91534994289814532176e-04,
2106 pS5
= 3.47933107596021167570e-05,
2107 qS1
= -2.40339491173441421878e+00,
2108 qS2
= 2.02094576023350569471e+00,
2109 qS3
= -6.88283971605453293030e-01,
2110 qS4
= 7.70381505559019352791e-02;
2113 p
= z
* (pS0
+ z
* (pS1
+ z
* (pS2
+ z
* (pS3
+ z
* (pS4
+ z
* pS5
)))));
2114 q
= 1.0 + z
* (qS1
+ z
* (qS2
+ z
* (qS3
+ z
* qS4
)));
2118 double CDECL
acos( double x
)
2120 static const double pio2_hi
= 1.57079632679489655800e+00,
2121 pio2_lo
= 6.12323399573676603587e-17;
2123 double z
, w
, s
, c
, df
;
2124 unsigned int hx
, ix
;
2127 hx
= *(ULONGLONG
*)&x
>> 32;
2128 ix
= hx
& 0x7fffffff;
2129 /* |x| >= 1 or nan */
2130 if (ix
>= 0x3ff00000) {
2133 lx
= *(ULONGLONG
*)&x
;
2134 if (((ix
- 0x3ff00000) | lx
) == 0) {
2135 /* acos(1)=0, acos(-1)=pi */
2137 return 2 * pio2_hi
+ 7.5231638452626401e-37;
2140 if (isnan(x
)) return x
;
2141 return math_error(_DOMAIN
, "acos", x
, 0, 0 / (x
- x
));
2144 if (ix
< 0x3fe00000) {
2145 if (ix
<= 0x3c600000) /* |x| < 2**-57 */
2146 return pio2_hi
+ 7.5231638452626401e-37;
2147 return pio2_hi
- (x
- (pio2_lo
- x
* acos_R(x
* x
)));
2151 z
= (1.0 + x
) * 0.5;
2153 w
= acos_R(z
) * s
- pio2_lo
;
2154 return 2 * (pio2_hi
- (s
+ w
));
2157 z
= (1.0 - x
) * 0.5;
2160 llx
= (*(ULONGLONG
*)&df
>> 32) << 32;
2161 df
= *(double*)&llx
;
2162 c
= (z
- df
* df
) / (s
+ df
);
2163 w
= acos_R(z
) * s
+ c
;
2164 return 2 * (df
+ w
);
2167 /*********************************************************************
2170 * Copied from musl: src/math/asin.c
2172 static double asin_R(double z
)
2174 /* coefficients for R(x^2) */
2175 static const double pS0
= 1.66666666666666657415e-01,
2176 pS1
= -3.25565818622400915405e-01,
2177 pS2
= 2.01212532134862925881e-01,
2178 pS3
= -4.00555345006794114027e-02,
2179 pS4
= 7.91534994289814532176e-04,
2180 pS5
= 3.47933107596021167570e-05,
2181 qS1
= -2.40339491173441421878e+00,
2182 qS2
= 2.02094576023350569471e+00,
2183 qS3
= -6.88283971605453293030e-01,
2184 qS4
= 7.70381505559019352791e-02;
2187 p
= z
* (pS0
+ z
* (pS1
+ z
* (pS2
+ z
* (pS3
+ z
* (pS4
+ z
* pS5
)))));
2188 q
= 1.0 + z
* (qS1
+ z
* (qS2
+ z
* (qS3
+ z
* qS4
)));
2193 double CDECL
x87_asin(double);
2194 __ASM_GLOBAL_FUNC( x87_asin
,
2209 double CDECL
asin( double x
)
2211 static const double pio2_hi
= 1.57079632679489655800e+00,
2212 pio2_lo
= 6.12323399573676603587e-17;
2215 unsigned int hx
, ix
;
2218 unsigned int x87_cw
, sse2_cw
;
2221 hx
= *(ULONGLONG
*)&x
>> 32;
2222 ix
= hx
& 0x7fffffff;
2223 /* |x| >= 1 or nan */
2224 if (ix
>= 0x3ff00000) {
2226 lx
= *(ULONGLONG
*)&x
;
2227 if (((ix
- 0x3ff00000) | lx
) == 0)
2228 /* asin(1) = +-pi/2 with inexact */
2229 return x
* pio2_hi
+ 7.5231638452626401e-37;
2233 return math_error(_DOMAIN
, "asin", x
, 0, x
);
2238 return math_error(_DOMAIN
, "asin", x
, 0, 0 / (x
- x
));
2242 __control87_2(0, 0, &x87_cw
, &sse2_cw
);
2243 if (!sse2_enabled
|| (x87_cw
& _MCW_EM
) != _MCW_EM
2244 || (sse2_cw
& (_MCW_EM
| _MCW_RC
)) != _MCW_EM
)
2249 if (ix
< 0x3fe00000) {
2250 /* if 0x1p-1022 <= |x| < 0x1p-26, avoid raising underflow */
2251 if (ix
< 0x3e500000 && ix
>= 0x00100000)
2253 return x
+ x
* asin_R(x
* x
);
2255 /* 1 > |x| >= 0.5 */
2256 z
= (1 - fabs(x
)) * 0.5;
2259 if (ix
>= 0x3fef3333) { /* if |x| > 0.975 */
2260 x
= pio2_hi
- (2 * (s
+ s
* r
) - pio2_lo
);
2265 llx
= (*(ULONGLONG
*)&f
>> 32) << 32;
2267 c
= (z
- f
* f
) / (s
+ f
);
2268 x
= 0.5 * pio2_hi
- (2 * s
* r
- (pio2_lo
- 2 * c
) - (0.5 * pio2_hi
- 2 * f
));
2275 /*********************************************************************
2278 * Copied from musl: src/math/atan.c
2280 double CDECL
atan( double x
)
2282 static const double atanhi
[] = {
2283 4.63647609000806093515e-01,
2284 7.85398163397448278999e-01,
2285 9.82793723247329054082e-01,
2286 1.57079632679489655800e+00,
2288 static const double atanlo
[] = {
2289 2.26987774529616870924e-17,
2290 3.06161699786838301793e-17,
2291 1.39033110312309984516e-17,
2292 6.12323399573676603587e-17,
2294 static const double aT
[] = {
2295 3.33333333333329318027e-01,
2296 -1.99999999998764832476e-01,
2297 1.42857142725034663711e-01,
2298 -1.11111104054623557880e-01,
2299 9.09088713343650656196e-02,
2300 -7.69187620504482999495e-02,
2301 6.66107313738753120669e-02,
2302 -5.83357013379057348645e-02,
2303 4.97687799461593236017e-02,
2304 -3.65315727442169155270e-02,
2305 1.62858201153657823623e-02,
2308 double w
, s1
, s2
, z
;
2309 unsigned int ix
, sign
;
2313 if (isnan(x
)) return math_error(_DOMAIN
, "atan", x
, 0, x
);
2316 ix
= *(ULONGLONG
*)&x
>> 32;
2319 if (ix
>= 0x44100000) { /* if |x| >= 2^66 */
2322 z
= atanhi
[3] + 7.5231638452626401e-37;
2323 return sign
? -z
: z
;
2325 if (ix
< 0x3fdc0000) { /* |x| < 0.4375 */
2326 if (ix
< 0x3e400000) { /* |x| < 2^-27 */
2327 if (ix
< 0x00100000)
2328 /* raise underflow for subnormal x */
2329 fp_barrierf((float)x
);
2335 if (ix
< 0x3ff30000) { /* |x| < 1.1875 */
2336 if (ix
< 0x3fe60000) { /* 7/16 <= |x| < 11/16 */
2338 x
= (2.0 * x
- 1.0) / (2.0 + x
);
2339 } else { /* 11/16 <= |x| < 19/16 */
2341 x
= (x
- 1.0) / (x
+ 1.0);
2344 if (ix
< 0x40038000) { /* |x| < 2.4375 */
2346 x
= (x
- 1.5) / (1.0 + 1.5 * x
);
2347 } else { /* 2.4375 <= |x| < 2^66 */
2353 /* end of argument reduction */
2356 /* break sum from i=0 to 10 aT[i]z**(i+1) into odd and even poly */
2357 s1
= z
* (aT
[0] + w
* (aT
[2] + w
* (aT
[4] + w
* (aT
[6] + w
* (aT
[8] + w
* aT
[10])))));
2358 s2
= w
* (aT
[1] + w
* (aT
[3] + w
* (aT
[5] + w
* (aT
[7] + w
* aT
[9]))));
2360 return x
- x
* (s1
+ s2
);
2361 z
= atanhi
[id
] - (x
* (s1
+ s2
) - atanlo
[id
] - x
);
2362 return sign
? -z
: z
;
2365 /*********************************************************************
2368 * Copied from musl: src/math/atan2.c
2370 double CDECL
atan2( double y
, double x
)
2372 static const double pi
= 3.1415926535897931160E+00,
2373 pi_lo
= 1.2246467991473531772E-16;
2376 unsigned int m
, lx
, ly
, ix
, iy
;
2378 if (isnan(x
) || isnan(y
))
2380 ix
= *(ULONGLONG
*)&x
>> 32;
2381 lx
= *(ULONGLONG
*)&x
;
2382 iy
= *(ULONGLONG
*)&y
>> 32;
2383 ly
= *(ULONGLONG
*)&y
;
2384 if (((ix
- 0x3ff00000) | lx
) == 0) /* x = 1.0 */
2386 m
= ((iy
>> 31) & 1) | ((ix
>> 30) & 2); /* 2*sign(x)+sign(y) */
2387 ix
= ix
& 0x7fffffff;
2388 iy
= iy
& 0x7fffffff;
2391 if ((iy
| ly
) == 0) {
2394 case 1: return y
; /* atan(+-0,+anything)=+-0 */
2395 case 2: return pi
; /* atan(+0,-anything) = pi */
2396 case 3: return -pi
; /* atan(-0,-anything) =-pi */
2401 return m
& 1 ? -pi
/ 2 : pi
/ 2;
2403 if (ix
== 0x7ff00000) {
2404 if (iy
== 0x7ff00000) {
2406 case 0: return pi
/ 4; /* atan(+INF,+INF) */
2407 case 1: return -pi
/ 4; /* atan(-INF,+INF) */
2408 case 2: return 3 * pi
/ 4; /* atan(+INF,-INF) */
2409 case 3: return -3 * pi
/ 4; /* atan(-INF,-INF) */
2413 case 0: return 0.0; /* atan(+...,+INF) */
2414 case 1: return -0.0; /* atan(-...,+INF) */
2415 case 2: return pi
; /* atan(+...,-INF) */
2416 case 3: return -pi
; /* atan(-...,-INF) */
2420 /* |y/x| > 0x1p64 */
2421 if (ix
+ (64 << 20) < iy
|| iy
== 0x7ff00000)
2422 return m
& 1 ? -pi
/ 2 : pi
/ 2;
2424 /* z = atan(|y/x|) without spurious underflow */
2425 if ((m
& 2) && iy
+ (64 << 20) < ix
) /* |y/x| < 0x1p-64, x<0 */
2428 z
= atan(fabs(y
/ x
));
2430 case 0: return z
; /* atan(+,+) */
2431 case 1: return -z
; /* atan(-,+) */
2432 case 2: return pi
- (z
- pi_lo
); /* atan(+,-) */
2433 default: /* case 3 */
2434 return (z
- pi_lo
) - pi
; /* atan(-,-) */
2438 /* Copied from musl: src/math/rint.c */
2439 static double __rint(double x
)
2441 static const double toint
= 1 / DBL_EPSILON
;
2443 ULONGLONG llx
= *(ULONGLONG
*)&x
;
2444 int e
= llx
>> 52 & 0x7ff;
2451 cw
= _controlfp(0, 0);
2452 if ((cw
& _MCW_PC
) != _PC_53
)
2453 _controlfp(_PC_53
, _MCW_PC
);
2455 y
= fp_barrier(x
- toint
) + toint
;
2457 y
= fp_barrier(x
+ toint
) - toint
;
2458 if ((cw
& _MCW_PC
) != _PC_53
)
2459 _controlfp(cw
, _MCW_PC
);
2461 return s
? -0.0 : 0;
2465 /* Copied from musl: src/math/__rem_pio2.c */
2466 static int __rem_pio2(double x
, double *y
)
2468 static const double pio4
= 0x1.921fb54442d18p
-1,
2469 invpio2
= 6.36619772367581382433e-01,
2470 pio2_1
= 1.57079632673412561417e+00,
2471 pio2_1t
= 6.07710050650619224932e-11,
2472 pio2_2
= 6.07710050630396597660e-11,
2473 pio2_2t
= 2.02226624879595063154e-21,
2474 pio2_3
= 2.02226624871116645580e-21,
2475 pio2_3t
= 8.47842766036889956997e-32;
2477 union {double f
; UINT64 i
;} u
= {x
};
2478 double z
, w
, t
, r
, fn
, tx
[3], ty
[2];
2480 int sign
, n
, ex
, ey
, i
;
2483 ix
= u
.i
>> 32 & 0x7fffffff;
2484 if (ix
<= 0x400f6a7a) { /* |x| ~<= 5pi/4 */
2485 if ((ix
& 0xfffff) == 0x921fb) /* |x| ~= pi/2 or 2pi/2 */
2486 goto medium
; /* cancellation -- use medium case */
2487 if (ix
<= 0x4002d97c) { /* |x| ~<= 3pi/4 */
2489 z
= x
- pio2_1
; /* one round good to 85 bits */
2491 y
[1] = (z
- y
[0]) - pio2_1t
;
2496 y
[1] = (z
- y
[0]) + pio2_1t
;
2502 y
[0] = z
- 2 * pio2_1t
;
2503 y
[1] = (z
- y
[0]) - 2 * pio2_1t
;
2507 y
[0] = z
+ 2 * pio2_1t
;
2508 y
[1] = (z
- y
[0]) + 2 * pio2_1t
;
2513 if (ix
<= 0x401c463b) { /* |x| ~<= 9pi/4 */
2514 if (ix
<= 0x4015fdbc) { /* |x| ~<= 7pi/4 */
2515 if (ix
== 0x4012d97c) /* |x| ~= 3pi/2 */
2519 y
[0] = z
- 3 * pio2_1t
;
2520 y
[1] = (z
- y
[0]) - 3 * pio2_1t
;
2524 y
[0] = z
+ 3 * pio2_1t
;
2525 y
[1] = (z
- y
[0]) + 3 * pio2_1t
;
2529 if (ix
== 0x401921fb) /* |x| ~= 4pi/2 */
2533 y
[0] = z
- 4 * pio2_1t
;
2534 y
[1] = (z
- y
[0]) - 4 * pio2_1t
;
2538 y
[0] = z
+ 4 * pio2_1t
;
2539 y
[1] = (z
- y
[0]) + 4 * pio2_1t
;
2544 if (ix
< 0x413921fb) { /* |x| ~< 2^20*(pi/2), medium size */
2546 fn
= __rint(x
* invpio2
);
2548 r
= x
- fn
* pio2_1
;
2549 w
= fn
* pio2_1t
; /* 1st round, good to 85 bits */
2550 /* Matters with directed rounding. */
2551 if (r
- w
< -pio4
) {
2554 r
= x
- fn
* pio2_1
;
2556 } else if (r
- w
> pio4
) {
2559 r
= x
- fn
* pio2_1
;
2564 ey
= u
.i
>> 52 & 0x7ff;
2566 if (ex
- ey
> 16) { /* 2nd round, good to 118 bits */
2570 w
= fn
* pio2_2t
- ((t
- r
) - w
);
2573 ey
= u
.i
>> 52 & 0x7ff;
2574 if (ex
- ey
> 49) { /* 3rd round, good to 151 bits, covers all cases */
2578 w
= fn
* pio2_3t
- ((t
- r
) - w
);
2582 y
[1] = (r
- y
[0]) - w
;
2586 * all other (large) arguments
2588 if (ix
>= 0x7ff00000) { /* x is inf or NaN */
2589 y
[0] = y
[1] = x
- x
;
2592 /* set z = scalbn(|x|,-ilogb(x)+23) */
2594 u
.i
&= (UINT64
)-1 >> 12;
2595 u
.i
|= (UINT64
)(0x3ff + 23) << 52;
2597 for (i
= 0; i
< 2; i
++) {
2598 tx
[i
] = (double)(INT32
)z
;
2599 z
= (z
- tx
[i
]) * 0x1p
24;
2602 /* skip zero terms, first term is non-zero */
2603 while (tx
[i
] == 0.0)
2605 n
= __rem_pio2_large(tx
, ty
, (int)(ix
>> 20) - (0x3ff + 23), i
+ 1, 1);
2616 /* Copied from musl: src/math/__sin.c */
2617 static double __sin(double x
, double y
, int iy
)
2619 static const double S1
= -1.66666666666666324348e-01,
2620 S2
= 8.33333333332248946124e-03,
2621 S3
= -1.98412698298579493134e-04,
2622 S4
= 2.75573137070700676789e-06,
2623 S5
= -2.50507602534068634195e-08,
2624 S6
= 1.58969099521155010221e-10;
2630 r
= S2
+ z
* (S3
+ z
* S4
) + z
* w
* (S5
+ z
* S6
);
2633 return x
+ v
* (S1
+ z
* r
);
2635 return x
- ((z
* (0.5 * y
- v
* r
) - y
) - v
* S1
);
2638 /* Copied from musl: src/math/__cos.c */
2639 static double __cos(double x
, double y
)
2641 static const double C1
= 4.16666666666666019037e-02,
2642 C2
= -1.38888888888741095749e-03,
2643 C3
= 2.48015872894767294178e-05,
2644 C4
= -2.75573143513906633035e-07,
2645 C5
= 2.08757232129817482790e-09,
2646 C6
= -1.13596475577881948265e-11;
2651 r
= z
* (C1
+ z
* (C2
+ z
* C3
)) + w
* w
* (C4
+ z
* (C5
+ z
* C6
));
2654 return w
+ (((1.0 - w
) - hz
) + (z
* r
- x
* y
));
2657 /*********************************************************************
2660 * Copied from musl: src/math/cos.c
2662 double CDECL
cos( double x
)
2668 ix
= *(ULONGLONG
*)&x
>> 32;
2672 if (ix
<= 0x3fe921fb) {
2673 if (ix
< 0x3e46a09e) { /* |x| < 2**-27 * sqrt(2) */
2674 /* raise inexact if x!=0 */
2675 fp_barrier(x
+ 0x1p
120f
);
2681 /* cos(Inf or NaN) is NaN */
2682 if (isinf(x
)) return math_error(_DOMAIN
, "cos", x
, 0, x
- x
);
2683 if (ix
>= 0x7ff00000)
2686 /* argument reduction */
2687 n
= __rem_pio2(x
, y
);
2689 case 0: return __cos(y
[0], y
[1]);
2690 case 1: return -__sin(y
[0], y
[1], 1);
2691 case 2: return -__cos(y
[0], y
[1]);
2692 default: return __sin(y
[0], y
[1], 1);
2696 /* Copied from musl: src/math/expm1.c */
2697 static double __expm1(double x
)
2699 static const double o_threshold
= 7.09782712893383973096e+02,
2700 ln2_hi
= 6.93147180369123816490e-01,
2701 ln2_lo
= 1.90821492927058770002e-10,
2702 invln2
= 1.44269504088896338700e+00,
2703 Q1
= -3.33333333333331316428e-02,
2704 Q2
= 1.58730158725481460165e-03,
2705 Q3
= -7.93650757867487942473e-05,
2706 Q4
= 4.00821782732936239552e-06,
2707 Q5
= -2.01099218183624371326e-07;
2709 double y
, hi
, lo
, c
, t
, e
, hxs
, hfx
, r1
, twopk
;
2710 union {double f
; UINT64 i
;} u
= {x
};
2711 UINT32 hx
= u
.i
>> 32 & 0x7fffffff;
2712 int k
, sign
= u
.i
>> 63;
2714 /* filter out huge and non-finite argument */
2715 if (hx
>= 0x4043687A) { /* if |x|>=56*ln2 */
2719 return sign
? -1 : x
;
2721 return math_error(_UNDERFLOW
, "exp", x
, 0, -1);
2722 if (x
> o_threshold
)
2723 return math_error(_OVERFLOW
, "exp", x
, 0, x
* 0x1p
1023);
2726 /* argument reduction */
2727 if (hx
> 0x3fd62e42) { /* if |x| > 0.5 ln2 */
2728 if (hx
< 0x3FF0A2B2) { /* and |x| < 1.5 ln2 */
2739 k
= invln2
* x
+ (sign
? -0.5 : 0.5);
2741 hi
= x
- t
* ln2_hi
; /* t*ln2_hi is exact here */
2746 } else if (hx
< 0x3c900000) { /* |x| < 2**-54, return x */
2747 fp_barrier(x
+ 0x1p
120f
);
2748 if (hx
< 0x00100000)
2749 fp_barrier((float)x
);
2754 /* x is now in primary range */
2757 r1
= 1.0 + hxs
* (Q1
+ hxs
* (Q2
+ hxs
* (Q3
+ hxs
* (Q4
+ hxs
* Q5
))));
2759 e
= hxs
* ((r1
- t
) / (6.0 - x
* t
));
2760 if (k
== 0) /* c is 0 */
2761 return x
- (x
* e
- hxs
);
2762 e
= x
* (e
- c
) - c
;
2764 /* exp(x) ~ 2^k (x_reduced - e + 1) */
2766 return 0.5 * (x
- e
) - 0.5;
2769 return -2.0 * (e
- (x
+ 0.5));
2770 return 1.0 + 2.0 * (x
- e
);
2772 u
.i
= (UINT64
)(0x3ff + k
) << 52; /* 2^k */
2774 if (k
< 0 || k
> 56) { /* suffice to return exp(x)-1 */
2777 y
= y
* 2.0 * 0x1p
1023;
2782 u
.i
= (UINT64
)(0x3ff - k
) << 52; /* 2^-k */
2784 y
= (x
- e
+ (1 - u
.f
)) * twopk
;
2786 y
= (x
- (e
+ u
.f
) + 1) * twopk
;
2790 static double __expo2(double x
, double sign
)
2792 static const int k
= 2043;
2793 static const double kln2
= 0x1.62066151add8bp
+10;
2796 *(UINT64
*)&scale
= (UINT64
)(0x3ff + k
/ 2) << 52;
2797 return exp(x
- kln2
) * (sign
* scale
) * scale
;
2800 /*********************************************************************
2803 * Copied from musl: src/math/cosh.c
2805 double CDECL
cosh( double x
)
2807 UINT64 ux
= *(UINT64
*)&x
;
2808 UINT64 sign
= ux
& 0x8000000000000000ULL
;
2813 ux
&= (uint64_t)-1 / 2;
2818 if (w
< 0x3fe62e42) {
2819 if (w
< 0x3ff00000 - (26 << 20)) {
2820 fp_barrier(x
+ 0x1p
120f
);
2824 return 1 + t
* t
/ (2 * (1 + t
));
2827 /* |x| < log(DBL_MAX) */
2828 if (w
< 0x40862e42) {
2830 /* note: if x>log(0x1p26) then the 1/t is not needed */
2831 return 0.5 * (t
+ 1 / t
);
2834 /* |x| > log(DBL_MAX) or nan */
2835 /* note: the result is stored to handle overflow */
2836 if (ux
> 0x7ff0000000000000ULL
)
2837 *(UINT64
*)&t
= ux
| sign
| 0x0008000000000000ULL
;
2839 t
= __expo2(x
, 1.0);
2843 /* Copied from musl: src/math/exp_data.c */
2844 static const UINT64 exp_T
[] = {
2845 0x0ULL
, 0x3ff0000000000000ULL
,
2846 0x3c9b3b4f1a88bf6eULL
, 0x3feff63da9fb3335ULL
,
2847 0xbc7160139cd8dc5dULL
, 0x3fefec9a3e778061ULL
,
2848 0xbc905e7a108766d1ULL
, 0x3fefe315e86e7f85ULL
,
2849 0x3c8cd2523567f613ULL
, 0x3fefd9b0d3158574ULL
,
2850 0xbc8bce8023f98efaULL
, 0x3fefd06b29ddf6deULL
,
2851 0x3c60f74e61e6c861ULL
, 0x3fefc74518759bc8ULL
,
2852 0x3c90a3e45b33d399ULL
, 0x3fefbe3ecac6f383ULL
,
2853 0x3c979aa65d837b6dULL
, 0x3fefb5586cf9890fULL
,
2854 0x3c8eb51a92fdeffcULL
, 0x3fefac922b7247f7ULL
,
2855 0x3c3ebe3d702f9cd1ULL
, 0x3fefa3ec32d3d1a2ULL
,
2856 0xbc6a033489906e0bULL
, 0x3fef9b66affed31bULL
,
2857 0xbc9556522a2fbd0eULL
, 0x3fef9301d0125b51ULL
,
2858 0xbc5080ef8c4eea55ULL
, 0x3fef8abdc06c31ccULL
,
2859 0xbc91c923b9d5f416ULL
, 0x3fef829aaea92de0ULL
,
2860 0x3c80d3e3e95c55afULL
, 0x3fef7a98c8a58e51ULL
,
2861 0xbc801b15eaa59348ULL
, 0x3fef72b83c7d517bULL
,
2862 0xbc8f1ff055de323dULL
, 0x3fef6af9388c8deaULL
,
2863 0x3c8b898c3f1353bfULL
, 0x3fef635beb6fcb75ULL
,
2864 0xbc96d99c7611eb26ULL
, 0x3fef5be084045cd4ULL
,
2865 0x3c9aecf73e3a2f60ULL
, 0x3fef54873168b9aaULL
,
2866 0xbc8fe782cb86389dULL
, 0x3fef4d5022fcd91dULL
,
2867 0x3c8a6f4144a6c38dULL
, 0x3fef463b88628cd6ULL
,
2868 0x3c807a05b0e4047dULL
, 0x3fef3f49917ddc96ULL
,
2869 0x3c968efde3a8a894ULL
, 0x3fef387a6e756238ULL
,
2870 0x3c875e18f274487dULL
, 0x3fef31ce4fb2a63fULL
,
2871 0x3c80472b981fe7f2ULL
, 0x3fef2b4565e27cddULL
,
2872 0xbc96b87b3f71085eULL
, 0x3fef24dfe1f56381ULL
,
2873 0x3c82f7e16d09ab31ULL
, 0x3fef1e9df51fdee1ULL
,
2874 0xbc3d219b1a6fbffaULL
, 0x3fef187fd0dad990ULL
,
2875 0x3c8b3782720c0ab4ULL
, 0x3fef1285a6e4030bULL
,
2876 0x3c6e149289cecb8fULL
, 0x3fef0cafa93e2f56ULL
,
2877 0x3c834d754db0abb6ULL
, 0x3fef06fe0a31b715ULL
,
2878 0x3c864201e2ac744cULL
, 0x3fef0170fc4cd831ULL
,
2879 0x3c8fdd395dd3f84aULL
, 0x3feefc08b26416ffULL
,
2880 0xbc86a3803b8e5b04ULL
, 0x3feef6c55f929ff1ULL
,
2881 0xbc924aedcc4b5068ULL
, 0x3feef1a7373aa9cbULL
,
2882 0xbc9907f81b512d8eULL
, 0x3feeecae6d05d866ULL
,
2883 0xbc71d1e83e9436d2ULL
, 0x3feee7db34e59ff7ULL
,
2884 0xbc991919b3ce1b15ULL
, 0x3feee32dc313a8e5ULL
,
2885 0x3c859f48a72a4c6dULL
, 0x3feedea64c123422ULL
,
2886 0xbc9312607a28698aULL
, 0x3feeda4504ac801cULL
,
2887 0xbc58a78f4817895bULL
, 0x3feed60a21f72e2aULL
,
2888 0xbc7c2c9b67499a1bULL
, 0x3feed1f5d950a897ULL
,
2889 0x3c4363ed60c2ac11ULL
, 0x3feece086061892dULL
,
2890 0x3c9666093b0664efULL
, 0x3feeca41ed1d0057ULL
,
2891 0x3c6ecce1daa10379ULL
, 0x3feec6a2b5c13cd0ULL
,
2892 0x3c93ff8e3f0f1230ULL
, 0x3feec32af0d7d3deULL
,
2893 0x3c7690cebb7aafb0ULL
, 0x3feebfdad5362a27ULL
,
2894 0x3c931dbdeb54e077ULL
, 0x3feebcb299fddd0dULL
,
2895 0xbc8f94340071a38eULL
, 0x3feeb9b2769d2ca7ULL
,
2896 0xbc87deccdc93a349ULL
, 0x3feeb6daa2cf6642ULL
,
2897 0xbc78dec6bd0f385fULL
, 0x3feeb42b569d4f82ULL
,
2898 0xbc861246ec7b5cf6ULL
, 0x3feeb1a4ca5d920fULL
,
2899 0x3c93350518fdd78eULL
, 0x3feeaf4736b527daULL
,
2900 0x3c7b98b72f8a9b05ULL
, 0x3feead12d497c7fdULL
,
2901 0x3c9063e1e21c5409ULL
, 0x3feeab07dd485429ULL
,
2902 0x3c34c7855019c6eaULL
, 0x3feea9268a5946b7ULL
,
2903 0x3c9432e62b64c035ULL
, 0x3feea76f15ad2148ULL
,
2904 0xbc8ce44a6199769fULL
, 0x3feea5e1b976dc09ULL
,
2905 0xbc8c33c53bef4da8ULL
, 0x3feea47eb03a5585ULL
,
2906 0xbc845378892be9aeULL
, 0x3feea34634ccc320ULL
,
2907 0xbc93cedd78565858ULL
, 0x3feea23882552225ULL
,
2908 0x3c5710aa807e1964ULL
, 0x3feea155d44ca973ULL
,
2909 0xbc93b3efbf5e2228ULL
, 0x3feea09e667f3bcdULL
,
2910 0xbc6a12ad8734b982ULL
, 0x3feea012750bdabfULL
,
2911 0xbc6367efb86da9eeULL
, 0x3fee9fb23c651a2fULL
,
2912 0xbc80dc3d54e08851ULL
, 0x3fee9f7df9519484ULL
,
2913 0xbc781f647e5a3ecfULL
, 0x3fee9f75e8ec5f74ULL
,
2914 0xbc86ee4ac08b7db0ULL
, 0x3fee9f9a48a58174ULL
,
2915 0xbc8619321e55e68aULL
, 0x3fee9feb564267c9ULL
,
2916 0x3c909ccb5e09d4d3ULL
, 0x3feea0694fde5d3fULL
,
2917 0xbc7b32dcb94da51dULL
, 0x3feea11473eb0187ULL
,
2918 0x3c94ecfd5467c06bULL
, 0x3feea1ed0130c132ULL
,
2919 0x3c65ebe1abd66c55ULL
, 0x3feea2f336cf4e62ULL
,
2920 0xbc88a1c52fb3cf42ULL
, 0x3feea427543e1a12ULL
,
2921 0xbc9369b6f13b3734ULL
, 0x3feea589994cce13ULL
,
2922 0xbc805e843a19ff1eULL
, 0x3feea71a4623c7adULL
,
2923 0xbc94d450d872576eULL
, 0x3feea8d99b4492edULL
,
2924 0x3c90ad675b0e8a00ULL
, 0x3feeaac7d98a6699ULL
,
2925 0x3c8db72fc1f0eab4ULL
, 0x3feeace5422aa0dbULL
,
2926 0xbc65b6609cc5e7ffULL
, 0x3feeaf3216b5448cULL
,
2927 0x3c7bf68359f35f44ULL
, 0x3feeb1ae99157736ULL
,
2928 0xbc93091fa71e3d83ULL
, 0x3feeb45b0b91ffc6ULL
,
2929 0xbc5da9b88b6c1e29ULL
, 0x3feeb737b0cdc5e5ULL
,
2930 0xbc6c23f97c90b959ULL
, 0x3feeba44cbc8520fULL
,
2931 0xbc92434322f4f9aaULL
, 0x3feebd829fde4e50ULL
,
2932 0xbc85ca6cd7668e4bULL
, 0x3feec0f170ca07baULL
,
2933 0x3c71affc2b91ce27ULL
, 0x3feec49182a3f090ULL
,
2934 0x3c6dd235e10a73bbULL
, 0x3feec86319e32323ULL
,
2935 0xbc87c50422622263ULL
, 0x3feecc667b5de565ULL
,
2936 0x3c8b1c86e3e231d5ULL
, 0x3feed09bec4a2d33ULL
,
2937 0xbc91bbd1d3bcbb15ULL
, 0x3feed503b23e255dULL
,
2938 0x3c90cc319cee31d2ULL
, 0x3feed99e1330b358ULL
,
2939 0x3c8469846e735ab3ULL
, 0x3feede6b5579fdbfULL
,
2940 0xbc82dfcd978e9db4ULL
, 0x3feee36bbfd3f37aULL
,
2941 0x3c8c1a7792cb3387ULL
, 0x3feee89f995ad3adULL
,
2942 0xbc907b8f4ad1d9faULL
, 0x3feeee07298db666ULL
,
2943 0xbc55c3d956dcaebaULL
, 0x3feef3a2b84f15fbULL
,
2944 0xbc90a40e3da6f640ULL
, 0x3feef9728de5593aULL
,
2945 0xbc68d6f438ad9334ULL
, 0x3feeff76f2fb5e47ULL
,
2946 0xbc91eee26b588a35ULL
, 0x3fef05b030a1064aULL
,
2947 0x3c74ffd70a5fddcdULL
, 0x3fef0c1e904bc1d2ULL
,
2948 0xbc91bdfbfa9298acULL
, 0x3fef12c25bd71e09ULL
,
2949 0x3c736eae30af0cb3ULL
, 0x3fef199bdd85529cULL
,
2950 0x3c8ee3325c9ffd94ULL
, 0x3fef20ab5fffd07aULL
,
2951 0x3c84e08fd10959acULL
, 0x3fef27f12e57d14bULL
,
2952 0x3c63cdaf384e1a67ULL
, 0x3fef2f6d9406e7b5ULL
,
2953 0x3c676b2c6c921968ULL
, 0x3fef3720dcef9069ULL
,
2954 0xbc808a1883ccb5d2ULL
, 0x3fef3f0b555dc3faULL
,
2955 0xbc8fad5d3ffffa6fULL
, 0x3fef472d4a07897cULL
,
2956 0xbc900dae3875a949ULL
, 0x3fef4f87080d89f2ULL
,
2957 0x3c74a385a63d07a7ULL
, 0x3fef5818dcfba487ULL
,
2958 0xbc82919e2040220fULL
, 0x3fef60e316c98398ULL
,
2959 0x3c8e5a50d5c192acULL
, 0x3fef69e603db3285ULL
,
2960 0x3c843a59ac016b4bULL
, 0x3fef7321f301b460ULL
,
2961 0xbc82d52107b43e1fULL
, 0x3fef7c97337b9b5fULL
,
2962 0xbc892ab93b470dc9ULL
, 0x3fef864614f5a129ULL
,
2963 0x3c74b604603a88d3ULL
, 0x3fef902ee78b3ff6ULL
,
2964 0x3c83c5ec519d7271ULL
, 0x3fef9a51fbc74c83ULL
,
2965 0xbc8ff7128fd391f0ULL
, 0x3fefa4afa2a490daULL
,
2966 0xbc8dae98e223747dULL
, 0x3fefaf482d8e67f1ULL
,
2967 0x3c8ec3bc41aa2008ULL
, 0x3fefba1bee615a27ULL
,
2968 0x3c842b94c3a9eb32ULL
, 0x3fefc52b376bba97ULL
,
2969 0x3c8a64a931d185eeULL
, 0x3fefd0765b6e4540ULL
,
2970 0xbc8e37bae43be3edULL
, 0x3fefdbfdad9cbe14ULL
,
2971 0x3c77893b4d91cd9dULL
, 0x3fefe7c1819e90d8ULL
,
2972 0x3c5305c14160cc89ULL
, 0x3feff3c22b8f71f1ULL
2975 /*********************************************************************
2978 * Copied from musl: src/math/exp.c
2980 double CDECL
exp( double x
)
2982 static const double C
[] = {
2983 0x1.ffffffffffdbdp
-2,
2984 0x1.555555555543cp
-3,
2985 0x1.55555cf172b91p
-5,
2986 0x1.1111167a4d017p
-7
2988 static const double invln2N
= 0x1.71547652b82fep0
* (1 << 7),
2989 negln2hiN
= -0x1.62e42fefa0000p
-8,
2990 negln2loN
= -0x1.cf79abc9e3b3ap
-47;
2993 UINT64 ki
, idx
, top
, sbits
;
2994 double kd
, z
, r
, r2
, scale
, tail
, tmp
;
2996 abstop
= (*(UINT64
*)&x
>> 52) & 0x7ff;
2997 if (abstop
- 0x3c9 >= 0x408 - 0x3c9) {
2998 if (abstop
- 0x3c9 >= 0x80000000)
2999 /* Avoid spurious underflow for tiny x. */
3000 /* Note: 0 is common input. */
3002 if (abstop
>= 0x409) {
3003 if (*(UINT64
*)&x
== 0xfff0000000000000ULL
)
3006 if (*(UINT64
*)&x
> 0x7ff0000000000000ULL
)
3007 return math_error(_DOMAIN
, "exp", x
, 0, 1.0 + x
);
3009 if (abstop
>= 0x7ff)
3011 if (*(UINT64
*)&x
>> 63)
3012 return math_error(_UNDERFLOW
, "exp", x
, 0, fp_barrier(DBL_MIN
) * DBL_MIN
);
3014 return math_error(_OVERFLOW
, "exp", x
, 0, fp_barrier(DBL_MAX
) * DBL_MAX
);
3016 /* Large x is special cased below. */
3020 /* exp(x) = 2^(k/N) * exp(r), with exp(r) in [2^(-1/2N),2^(1/2N)]. */
3021 /* x = ln2/N*k + r, with int k and r in [-ln2/2N, ln2/2N]. */
3026 r
= x
+ kd
* negln2hiN
+ kd
* negln2loN
;
3027 /* 2^(k/N) ~= scale * (1 + tail). */
3028 idx
= 2 * (ki
% (1 << 7));
3029 top
= ki
<< (52 - 7);
3030 tail
= *(double*)&exp_T
[idx
];
3031 /* This is only a valid scale when -1023*N < k < 1024*N. */
3032 sbits
= exp_T
[idx
+ 1] + top
;
3033 /* exp(x) = 2^(k/N) * exp(r) ~= scale + scale * (tail + exp(r) - 1). */
3034 /* Evaluation is optimized assuming superscalar pipelined execution. */
3036 /* Without fma the worst case error is 0.25/N ulp larger. */
3037 /* Worst case error is less than 0.5+1.11/N+(abs poly error * 2^53) ulp. */
3038 tmp
= tail
+ r
+ r2
* (C
[0] + r
* C
[1]) + r2
* r2
* (C
[2] + r
* C
[3]);
3040 /* Handle cases that may overflow or underflow when computing the result that
3041 is scale*(1+TMP) without intermediate rounding. The bit representation of
3042 scale is in SBITS, however it has a computed exponent that may have
3043 overflown into the sign bit so that needs to be adjusted before using it as
3044 a double. (int32_t)KI is the k used in the argument reduction and exponent
3045 adjustment of scale, positive k here means the result may overflow and
3046 negative k means the result may underflow. */
3049 if ((ki
& 0x80000000) == 0) {
3050 /* k > 0, the exponent of scale might have overflowed by <= 460. */
3051 sbits
-= 1009ull << 52;
3052 scale
= *(double*)&sbits
;
3053 y
= 0x1p
1009 * (scale
+ scale
* tmp
);
3055 return math_error(_OVERFLOW
, "exp", x
, 0, y
);
3058 /* k < 0, need special care in the subnormal range. */
3059 sbits
+= 1022ull << 52;
3060 scale
= *(double*)&sbits
;
3061 y
= scale
+ scale
* tmp
;
3063 /* Round y to the right precision before scaling it into the subnormal
3064 range to avoid double rounding that can cause 0.5+E/2 ulp error where
3065 E is the worst-case ulp error outside the subnormal range. So this
3066 is only useful if the goal is better than 1 ulp worst-case error. */
3068 lo
= scale
- y
+ scale
* tmp
;
3070 lo
= 1.0 - hi
+ y
+ lo
;
3072 /* Avoid -0.0 with downward rounding. */
3075 /* The underflow exception needs to be signaled explicitly. */
3076 fp_barrier(fp_barrier(0x1p
-1022) * 0x1p
-1022);
3078 return math_error(_UNDERFLOW
, "exp", x
, 0, y
);
3083 scale
= *(double*)&sbits
;
3084 /* Note: tmp == 0 or |tmp| > 2^-200 and scale > 2^-739, so there
3085 is no spurious underflow here even without fma. */
3086 return scale
+ scale
* tmp
;
3089 /*********************************************************************
3092 * Copied from musl: src/math/fmod.c
3094 double CDECL
fmod( double x
, double y
)
3096 UINT64 xi
= *(UINT64
*)&x
;
3097 UINT64 yi
= *(UINT64
*)&y
;
3098 int ex
= xi
>> 52 & 0x7ff;
3099 int ey
= yi
>> 52 & 0x7ff;
3103 if (isinf(x
)) return math_error(_DOMAIN
, "fmod", x
, y
, (x
* y
) / (x
* y
));
3104 if (yi
<< 1 == 0 || isnan(y
) || ex
== 0x7ff)
3105 return (x
* y
) / (x
* y
);
3106 if (xi
<< 1 <= yi
<< 1) {
3107 if (xi
<< 1 == yi
<< 1)
3112 /* normalize x and y */
3114 for (i
= xi
<< 12; i
>> 63 == 0; ex
--, i
<<= 1);
3121 for (i
= yi
<< 12; i
>> 63 == 0; ey
--, i
<<= 1);
3129 for (; ex
> ey
; ex
--) {
3144 for (; xi
>> 52 == 0; xi
<<= 1, ex
--);
3149 xi
|= (UINT64
)ex
<< 52;
3153 xi
|= (UINT64
)sx
<< 63;
3154 return *(double*)&xi
;
3157 /*********************************************************************
3160 * Copied from musl: src/math/log.c src/math/log_data.c
3162 double CDECL
log( double x
)
3164 static const double Ln2hi
= 0x1.62e42fefa3800p
-1,
3165 Ln2lo
= 0x1.ef35793c76730p
-45;
3166 static const double A
[] = {
3167 -0x1.0000000000001p
-1,
3168 0x1.555555551305bp
-2,
3169 -0x1.fffffffeb459p
-3,
3170 0x1.999b324f10111p
-3,
3171 -0x1.55575e506c89fp
-3
3173 static const double B
[] = {
3175 0x1.5555555555577p
-2,
3176 -0x1.ffffffffffdcbp
-3,
3177 0x1.999999995dd0cp
-3,
3178 -0x1.55555556745a7p
-3,
3179 0x1.24924a344de3p
-3,
3180 -0x1.fffffa4423d65p
-4,
3181 0x1.c7184282ad6cap
-4,
3182 -0x1.999eb43b068ffp
-4,
3183 0x1.78182f7afd085p
-4,
3184 -0x1.5521375d145cdp
-4
3186 static const struct {
3189 {0x1.734f0c3e0de9fp
+0, -0x1.7cc7f79e69000p
-2},
3190 {0x1.713786a2ce91fp
+0, -0x1.76feec20d0000p
-2},
3191 {0x1.6f26008fab5a0p
+0, -0x1.713e31351e000p
-2},
3192 {0x1.6d1a61f138c7dp
+0, -0x1.6b85b38287800p
-2},
3193 {0x1.6b1490bc5b4d1p
+0, -0x1.65d5590807800p
-2},
3194 {0x1.69147332f0cbap
+0, -0x1.602d076180000p
-2},
3195 {0x1.6719f18224223p
+0, -0x1.5a8ca86909000p
-2},
3196 {0x1.6524f99a51ed9p
+0, -0x1.54f4356035000p
-2},
3197 {0x1.63356aa8f24c4p
+0, -0x1.4f637c36b4000p
-2},
3198 {0x1.614b36b9ddc14p
+0, -0x1.49da7fda85000p
-2},
3199 {0x1.5f66452c65c4cp
+0, -0x1.445923989a800p
-2},
3200 {0x1.5d867b5912c4fp
+0, -0x1.3edf439b0b800p
-2},
3201 {0x1.5babccb5b90dep
+0, -0x1.396ce448f7000p
-2},
3202 {0x1.59d61f2d91a78p
+0, -0x1.3401e17bda000p
-2},
3203 {0x1.5805612465687p
+0, -0x1.2e9e2ef468000p
-2},
3204 {0x1.56397cee76bd3p
+0, -0x1.2941b3830e000p
-2},
3205 {0x1.54725e2a77f93p
+0, -0x1.23ec58cda8800p
-2},
3206 {0x1.52aff42064583p
+0, -0x1.1e9e129279000p
-2},
3207 {0x1.50f22dbb2bddfp
+0, -0x1.1956d2b48f800p
-2},
3208 {0x1.4f38f4734ded7p
+0, -0x1.141679ab9f800p
-2},
3209 {0x1.4d843cfde2840p
+0, -0x1.0edd094ef9800p
-2},
3210 {0x1.4bd3ec078a3c8p
+0, -0x1.09aa518db1000p
-2},
3211 {0x1.4a27fc3e0258ap
+0, -0x1.047e65263b800p
-2},
3212 {0x1.4880524d48434p
+0, -0x1.feb224586f000p
-3},
3213 {0x1.46dce1b192d0bp
+0, -0x1.f474a7517b000p
-3},
3214 {0x1.453d9d3391854p
+0, -0x1.ea4443d103000p
-3},
3215 {0x1.43a2744b4845ap
+0, -0x1.e020d44e9b000p
-3},
3216 {0x1.420b54115f8fbp
+0, -0x1.d60a22977f000p
-3},
3217 {0x1.40782da3ef4b1p
+0, -0x1.cc00104959000p
-3},
3218 {0x1.3ee8f5d57fe8fp
+0, -0x1.c202956891000p
-3},
3219 {0x1.3d5d9a00b4ce9p
+0, -0x1.b81178d811000p
-3},
3220 {0x1.3bd60c010c12bp
+0, -0x1.ae2c9ccd3d000p
-3},
3221 {0x1.3a5242b75dab8p
+0, -0x1.a45402e129000p
-3},
3222 {0x1.38d22cd9fd002p
+0, -0x1.9a877681df000p
-3},
3223 {0x1.3755bc5847a1cp
+0, -0x1.90c6d69483000p
-3},
3224 {0x1.35dce49ad36e2p
+0, -0x1.87120a645c000p
-3},
3225 {0x1.34679984dd440p
+0, -0x1.7d68fb4143000p
-3},
3226 {0x1.32f5cceffcb24p
+0, -0x1.73cb83c627000p
-3},
3227 {0x1.3187775a10d49p
+0, -0x1.6a39a9b376000p
-3},
3228 {0x1.301c8373e3990p
+0, -0x1.60b3154b7a000p
-3},
3229 {0x1.2eb4ebb95f841p
+0, -0x1.5737d76243000p
-3},
3230 {0x1.2d50a0219a9d1p
+0, -0x1.4dc7b8fc23000p
-3},
3231 {0x1.2bef9a8b7fd2ap
+0, -0x1.4462c51d20000p
-3},
3232 {0x1.2a91c7a0c1babp
+0, -0x1.3b08abc830000p
-3},
3233 {0x1.293726014b530p
+0, -0x1.31b996b490000p
-3},
3234 {0x1.27dfa5757a1f5p
+0, -0x1.2875490a44000p
-3},
3235 {0x1.268b39b1d3bbfp
+0, -0x1.1f3b9f879a000p
-3},
3236 {0x1.2539d838ff5bdp
+0, -0x1.160c8252ca000p
-3},
3237 {0x1.23eb7aac9083bp
+0, -0x1.0ce7f57f72000p
-3},
3238 {0x1.22a012ba940b6p
+0, -0x1.03cdc49fea000p
-3},
3239 {0x1.2157996cc4132p
+0, -0x1.f57bdbc4b8000p
-4},
3240 {0x1.201201dd2fc9bp
+0, -0x1.e370896404000p
-4},
3241 {0x1.1ecf4494d480bp
+0, -0x1.d17983ef94000p
-4},
3242 {0x1.1d8f5528f6569p
+0, -0x1.bf9674ed8a000p
-4},
3243 {0x1.1c52311577e7cp
+0, -0x1.adc79202f6000p
-4},
3244 {0x1.1b17c74cb26e9p
+0, -0x1.9c0c3e7288000p
-4},
3245 {0x1.19e010c2c1ab6p
+0, -0x1.8a646b372c000p
-4},
3246 {0x1.18ab07bb670bdp
+0, -0x1.78d01b3ac0000p
-4},
3247 {0x1.1778a25efbcb6p
+0, -0x1.674f145380000p
-4},
3248 {0x1.1648d354c31dap
+0, -0x1.55e0e6d878000p
-4},
3249 {0x1.151b990275fddp
+0, -0x1.4485cdea1e000p
-4},
3250 {0x1.13f0ea432d24cp
+0, -0x1.333d94d6aa000p
-4},
3251 {0x1.12c8b7210f9dap
+0, -0x1.22079f8c56000p
-4},
3252 {0x1.11a3028ecb531p
+0, -0x1.10e4698622000p
-4},
3253 {0x1.107fbda8434afp
+0, -0x1.ffa6c6ad20000p
-5},
3254 {0x1.0f5ee0f4e6bb3p
+0, -0x1.dda8d4a774000p
-5},
3255 {0x1.0e4065d2a9fcep
+0, -0x1.bbcece4850000p
-5},
3256 {0x1.0d244632ca521p
+0, -0x1.9a1894012c000p
-5},
3257 {0x1.0c0a77ce2981ap
+0, -0x1.788583302c000p
-5},
3258 {0x1.0af2f83c636d1p
+0, -0x1.5715e67d68000p
-5},
3259 {0x1.09ddb98a01339p
+0, -0x1.35c8a49658000p
-5},
3260 {0x1.08cabaf52e7dfp
+0, -0x1.149e364154000p
-5},
3261 {0x1.07b9f2f4e28fbp
+0, -0x1.e72c082eb8000p
-6},
3262 {0x1.06ab58c358f19p
+0, -0x1.a55f152528000p
-6},
3263 {0x1.059eea5ecf92cp
+0, -0x1.63d62cf818000p
-6},
3264 {0x1.04949cdd12c90p
+0, -0x1.228fb8caa0000p
-6},
3265 {0x1.038c6c6f0ada9p
+0, -0x1.c317b20f90000p
-7},
3266 {0x1.02865137932a9p
+0, -0x1.419355daa0000p
-7},
3267 {0x1.0182427ea7348p
+0, -0x1.81203c2ec0000p
-8},
3268 {0x1.008040614b195p
+0, -0x1.0040979240000p
-9},
3269 {0x1.fe01ff726fa1ap
-1, 0x1.feff384900000p
-9},
3270 {0x1.fa11cc261ea74p
-1, 0x1.7dc41353d0000p
-7},
3271 {0x1.f6310b081992ep
-1, 0x1.3cea3c4c28000p
-6},
3272 {0x1.f25f63ceeadcdp
-1, 0x1.b9fc114890000p
-6},
3273 {0x1.ee9c8039113e7p
-1, 0x1.1b0d8ce110000p
-5},
3274 {0x1.eae8078cbb1abp
-1, 0x1.58a5bd001c000p
-5},
3275 {0x1.e741aa29d0c9bp
-1, 0x1.95c8340d88000p
-5},
3276 {0x1.e3a91830a99b5p
-1, 0x1.d276aef578000p
-5},
3277 {0x1.e01e009609a56p
-1, 0x1.07598e598c000p
-4},
3278 {0x1.dca01e577bb98p
-1, 0x1.253f5e30d2000p
-4},
3279 {0x1.d92f20b7c9103p
-1, 0x1.42edd8b380000p
-4},
3280 {0x1.d5cac66fb5ccep
-1, 0x1.606598757c000p
-4},
3281 {0x1.d272caa5ede9dp
-1, 0x1.7da76356a0000p
-4},
3282 {0x1.cf26e3e6b2ccdp
-1, 0x1.9ab434e1c6000p
-4},
3283 {0x1.cbe6da2a77902p
-1, 0x1.b78c7bb0d6000p
-4},
3284 {0x1.c8b266d37086dp
-1, 0x1.d431332e72000p
-4},
3285 {0x1.c5894bd5d5804p
-1, 0x1.f0a3171de6000p
-4},
3286 {0x1.c26b533bb9f8cp
-1, 0x1.067152b914000p
-3},
3287 {0x1.bf583eeece73fp
-1, 0x1.147858292b000p
-3},
3288 {0x1.bc4fd75db96c1p
-1, 0x1.2266ecdca3000p
-3},
3289 {0x1.b951e0c864a28p
-1, 0x1.303d7a6c55000p
-3},
3290 {0x1.b65e2c5ef3e2cp
-1, 0x1.3dfc33c331000p
-3},
3291 {0x1.b374867c9888bp
-1, 0x1.4ba366b7a8000p
-3},
3292 {0x1.b094b211d304ap
-1, 0x1.5933928d1f000p
-3},
3293 {0x1.adbe885f2ef7ep
-1, 0x1.66acd2418f000p
-3},
3294 {0x1.aaf1d31603da2p
-1, 0x1.740f8ec669000p
-3},
3295 {0x1.a82e63fd358a7p
-1, 0x1.815c0f51af000p
-3},
3296 {0x1.a5740ef09738bp
-1, 0x1.8e92954f68000p
-3},
3297 {0x1.a2c2a90ab4b27p
-1, 0x1.9bb3602f84000p
-3},
3298 {0x1.a01a01393f2d1p
-1, 0x1.a8bed1c2c0000p
-3},
3299 {0x1.9d79f24db3c1bp
-1, 0x1.b5b515c01d000p
-3},
3300 {0x1.9ae2505c7b190p
-1, 0x1.c2967ccbcc000p
-3},
3301 {0x1.9852ef297ce2fp
-1, 0x1.cf635d5486000p
-3},
3302 {0x1.95cbaeea44b75p
-1, 0x1.dc1bd3446c000p
-3},
3303 {0x1.934c69de74838p
-1, 0x1.e8c01b8cfe000p
-3},
3304 {0x1.90d4f2f6752e6p
-1, 0x1.f5509c0179000p
-3},
3305 {0x1.8e6528effd79dp
-1, 0x1.00e6c121fb800p
-2},
3306 {0x1.8bfce9fcc007cp
-1, 0x1.071b80e93d000p
-2},
3307 {0x1.899c0dabec30ep
-1, 0x1.0d46b9e867000p
-2},
3308 {0x1.87427aa2317fbp
-1, 0x1.13687334bd000p
-2},
3309 {0x1.84f00acb39a08p
-1, 0x1.1980d67234800p
-2},
3310 {0x1.82a49e8653e55p
-1, 0x1.1f8ffe0cc8000p
-2},
3311 {0x1.8060195f40260p
-1, 0x1.2595fd7636800p
-2},
3312 {0x1.7e22563e0a329p
-1, 0x1.2b9300914a800p
-2},
3313 {0x1.7beb377dcb5adp
-1, 0x1.3187210436000p
-2},
3314 {0x1.79baa679725c2p
-1, 0x1.377266dec1800p
-2},
3315 {0x1.77907f2170657p
-1, 0x1.3d54ffbaf3000p
-2},
3316 {0x1.756cadbd6130cp
-1, 0x1.432eee32fe000p
-2}
3318 static const struct {
3321 {0x1.61000014fb66bp
-1, 0x1.e026c91425b3cp
-56},
3322 {0x1.63000034db495p
-1, 0x1.dbfea48005d41p
-55},
3323 {0x1.650000d94d478p
-1, 0x1.e7fa786d6a5b7p
-55},
3324 {0x1.67000074e6fadp
-1, 0x1.1fcea6b54254cp
-57},
3325 {0x1.68ffffedf0faep
-1, -0x1.c7e274c590efdp
-56},
3326 {0x1.6b0000763c5bcp
-1, -0x1.ac16848dcda01p
-55},
3327 {0x1.6d0001e5cc1f6p
-1, 0x1.33f1c9d499311p
-55},
3328 {0x1.6efffeb05f63ep
-1, -0x1.e80041ae22d53p
-56},
3329 {0x1.710000e86978p
-1, 0x1.bff6671097952p
-56},
3330 {0x1.72ffffc67e912p
-1, 0x1.c00e226bd8724p
-55},
3331 {0x1.74fffdf81116ap
-1, -0x1.e02916ef101d2p
-57},
3332 {0x1.770000f679c9p
-1, -0x1.7fc71cd549c74p
-57},
3333 {0x1.78ffffa7ec835p
-1, 0x1.1bec19ef50483p
-55},
3334 {0x1.7affffe20c2e6p
-1, -0x1.07e1729cc6465p
-56},
3335 {0x1.7cfffed3fc9p
-1, -0x1.08072087b8b1cp
-55},
3336 {0x1.7efffe9261a76p
-1, 0x1.dc0286d9df9aep
-55},
3337 {0x1.81000049ca3e8p
-1, 0x1.97fd251e54c33p
-55},
3338 {0x1.8300017932c8fp
-1, -0x1.afee9b630f381p
-55},
3339 {0x1.850000633739cp
-1, 0x1.9bfbf6b6535bcp
-55},
3340 {0x1.87000204289c6p
-1, -0x1.bbf65f3117b75p
-55},
3341 {0x1.88fffebf57904p
-1, -0x1.9006ea23dcb57p
-55},
3342 {0x1.8b00022bc04dfp
-1, -0x1.d00df38e04b0ap
-56},
3343 {0x1.8cfffe50c1b8ap
-1, -0x1.8007146ff9f05p
-55},
3344 {0x1.8effffc918e43p
-1, 0x1.3817bd07a7038p
-55},
3345 {0x1.910001efa5fc7p
-1, 0x1.93e9176dfb403p
-55},
3346 {0x1.9300013467bb9p
-1, 0x1.f804e4b980276p
-56},
3347 {0x1.94fffe6ee076fp
-1, -0x1.f7ef0d9ff622ep
-55},
3348 {0x1.96fffde3c12d1p
-1, -0x1.082aa962638bap
-56},
3349 {0x1.98ffff4458a0dp
-1, -0x1.7801b9164a8efp
-55},
3350 {0x1.9afffdd982e3ep
-1, -0x1.740e08a5a9337p
-55},
3351 {0x1.9cfffed49fb66p
-1, 0x1.fce08c19bep
-60},
3352 {0x1.9f00020f19c51p
-1, -0x1.a3faa27885b0ap
-55},
3353 {0x1.a10001145b006p
-1, 0x1.4ff489958da56p
-56},
3354 {0x1.a300007bbf6fap
-1, 0x1.cbeab8a2b6d18p
-55},
3355 {0x1.a500010971d79p
-1, 0x1.8fecadd78793p
-55},
3356 {0x1.a70001df52e48p
-1, -0x1.f41763dd8abdbp
-55},
3357 {0x1.a90001c593352p
-1, -0x1.ebf0284c27612p
-55},
3358 {0x1.ab0002a4f3e4bp
-1, -0x1.9fd043cff3f5fp
-57},
3359 {0x1.acfffd7ae1ed1p
-1, -0x1.23ee7129070b4p
-55},
3360 {0x1.aefffee510478p
-1, 0x1.a063ee00edea3p
-57},
3361 {0x1.b0fffdb650d5bp
-1, 0x1.a06c8381f0ab9p
-58},
3362 {0x1.b2ffffeaaca57p
-1, -0x1.9011e74233c1dp
-56},
3363 {0x1.b4fffd995badcp
-1, -0x1.9ff1068862a9fp
-56},
3364 {0x1.b7000249e659cp
-1, 0x1.aff45d0864f3ep
-55},
3365 {0x1.b8ffff987164p
-1, 0x1.cfe7796c2c3f9p
-56},
3366 {0x1.bafffd204cb4fp
-1, -0x1.3ff27eef22bc4p
-57},
3367 {0x1.bcfffd2415c45p
-1, -0x1.cffb7ee3bea21p
-57},
3368 {0x1.beffff86309dfp
-1, -0x1.14103972e0b5cp
-55},
3369 {0x1.c0fffe1b57653p
-1, 0x1.bc16494b76a19p
-55},
3370 {0x1.c2ffff1fa57e3p
-1, -0x1.4feef8d30c6edp
-57},
3371 {0x1.c4fffdcbfe424p
-1, -0x1.43f68bcec4775p
-55},
3372 {0x1.c6fffed54b9f7p
-1, 0x1.47ea3f053e0ecp
-55},
3373 {0x1.c8fffeb998fd5p
-1, 0x1.383068df992f1p
-56},
3374 {0x1.cb0002125219ap
-1, -0x1.8fd8e64180e04p
-57},
3375 {0x1.ccfffdd94469cp
-1, 0x1.e7ebe1cc7ea72p
-55},
3376 {0x1.cefffeafdc476p
-1, 0x1.ebe39ad9f88fep
-55},
3377 {0x1.d1000169af82bp
-1, 0x1.57d91a8b95a71p
-56},
3378 {0x1.d30000d0ff71dp
-1, 0x1.9c1906970c7dap
-55},
3379 {0x1.d4fffea790fc4p
-1, -0x1.80e37c558fe0cp
-58},
3380 {0x1.d70002edc87e5p
-1, -0x1.f80d64dc10f44p
-56},
3381 {0x1.d900021dc82aap
-1, -0x1.47c8f94fd5c5cp
-56},
3382 {0x1.dafffd86b0283p
-1, 0x1.c7f1dc521617ep
-55},
3383 {0x1.dd000296c4739p
-1, 0x1.8019eb2ffb153p
-55},
3384 {0x1.defffe54490f5p
-1, 0x1.e00d2c652cc89p
-57},
3385 {0x1.e0fffcdabf694p
-1, -0x1.f8340202d69d2p
-56},
3386 {0x1.e2fffdb52c8ddp
-1, 0x1.b00c1ca1b0864p
-56},
3387 {0x1.e4ffff24216efp
-1, 0x1.2ffa8b094ab51p
-56},
3388 {0x1.e6fffe88a5e11p
-1, -0x1.7f673b1efbe59p
-58},
3389 {0x1.e9000119eff0dp
-1, -0x1.4808d5e0bc801p
-55},
3390 {0x1.eafffdfa51744p
-1, 0x1.80006d54320b5p
-56},
3391 {0x1.ed0001a127fa1p
-1, -0x1.002f860565c92p
-58},
3392 {0x1.ef00007babcc4p
-1, -0x1.540445d35e611p
-55},
3393 {0x1.f0ffff57a8d02p
-1, -0x1.ffb3139ef9105p
-59},
3394 {0x1.f30001ee58ac7p
-1, 0x1.a81acf2731155p
-55},
3395 {0x1.f4ffff5823494p
-1, 0x1.a3f41d4d7c743p
-55},
3396 {0x1.f6ffffca94c6bp
-1, -0x1.202f41c987875p
-57},
3397 {0x1.f8fffe1f9c441p
-1, 0x1.77dd1f477e74bp
-56},
3398 {0x1.fafffd2e0e37ep
-1, -0x1.f01199a7ca331p
-57},
3399 {0x1.fd0001c77e49ep
-1, 0x1.181ee4bceacb1p
-56},
3400 {0x1.feffff7e0c331p
-1, -0x1.e05370170875ap
-57},
3401 {0x1.00ffff465606ep
+0, -0x1.a7ead491c0adap
-55},
3402 {0x1.02ffff3867a58p
+0, -0x1.77f69c3fcb2ep
-54},
3403 {0x1.04ffffdfc0d17p
+0, 0x1.7bffe34cb945bp
-54},
3404 {0x1.0700003cd4d82p
+0, 0x1.20083c0e456cbp
-55},
3405 {0x1.08ffff9f2cbe8p
+0, -0x1.dffdfbe37751ap
-57},
3406 {0x1.0b000010cda65p
+0, -0x1.13f7faee626ebp
-54},
3407 {0x1.0d00001a4d338p
+0, 0x1.07dfa79489ff7p
-55},
3408 {0x1.0effffadafdfdp
+0, -0x1.7040570d66bcp
-56},
3409 {0x1.110000bbafd96p
+0, 0x1.e80d4846d0b62p
-55},
3410 {0x1.12ffffae5f45dp
+0, 0x1.dbffa64fd36efp
-54},
3411 {0x1.150000dd59ad9p
+0, 0x1.a0077701250aep
-54},
3412 {0x1.170000f21559ap
+0, 0x1.dfdf9e2e3deeep
-55},
3413 {0x1.18ffffc275426p
+0, 0x1.10030dc3b7273p
-54},
3414 {0x1.1b000123d3c59p
+0, 0x1.97f7980030188p
-54},
3415 {0x1.1cffff8299eb7p
+0, -0x1.5f932ab9f8c67p
-57},
3416 {0x1.1effff48ad4p
+0, 0x1.37fbf9da75bebp
-54},
3417 {0x1.210000c8b86a4p
+0, 0x1.f806b91fd5b22p
-54},
3418 {0x1.2300003854303p
+0, 0x1.3ffc2eb9fbf33p
-54},
3419 {0x1.24fffffbcf684p
+0, 0x1.601e77e2e2e72p
-56},
3420 {0x1.26ffff52921d9p
+0, 0x1.ffcbb767f0c61p
-56},
3421 {0x1.2900014933a3cp
+0, -0x1.202ca3c02412bp
-56},
3422 {0x1.2b00014556313p
+0, -0x1.2808233f21f02p
-54},
3423 {0x1.2cfffebfe523bp
+0, -0x1.8ff7e384fdcf2p
-55},
3424 {0x1.2f0000bb8ad96p
+0, -0x1.5ff51503041c5p
-55},
3425 {0x1.30ffffb7ae2afp
+0, -0x1.10071885e289dp
-55},
3426 {0x1.32ffffeac5f7fp
+0, -0x1.1ff5d3fb7b715p
-54},
3427 {0x1.350000ca66756p
+0, 0x1.57f82228b82bdp
-54},
3428 {0x1.3700011fbf721p
+0, 0x1.000bac40dd5ccp
-55},
3429 {0x1.38ffff9592fb9p
+0, -0x1.43f9d2db2a751p
-54},
3430 {0x1.3b00004ddd242p
+0, 0x1.57f6b707638e1p
-55},
3431 {0x1.3cffff5b2c957p
+0, 0x1.a023a10bf1231p
-56},
3432 {0x1.3efffeab0b418p
+0, 0x1.87f6d66b152bp
-54},
3433 {0x1.410001532aff4p
+0, 0x1.7f8375f198524p
-57},
3434 {0x1.4300017478b29p
+0, 0x1.301e672dc5143p
-55},
3435 {0x1.44fffe795b463p
+0, 0x1.9ff69b8b2895ap
-55},
3436 {0x1.46fffe80475ep
+0, -0x1.5c0b19bc2f254p
-54},
3437 {0x1.48fffef6fc1e7p
+0, 0x1.b4009f23a2a72p
-54},
3438 {0x1.4afffe5bea704p
+0, -0x1.4ffb7bf0d7d45p
-54},
3439 {0x1.4d000171027dep
+0, -0x1.9c06471dc6a3dp
-54},
3440 {0x1.4f0000ff03ee2p
+0, 0x1.77f890b85531cp
-54},
3441 {0x1.5100012dc4bd1p
+0, 0x1.004657166a436p
-57},
3442 {0x1.530001605277ap
+0, -0x1.6bfcece233209p
-54},
3443 {0x1.54fffecdb704cp
+0, -0x1.902720505a1d7p
-55},
3444 {0x1.56fffef5f54a9p
+0, 0x1.bbfe60ec96412p
-54},
3445 {0x1.5900017e61012p
+0, 0x1.87ec581afef9p
-55},
3446 {0x1.5b00003c93e92p
+0, -0x1.f41080abf0ccp
-54},
3447 {0x1.5d0001d4919bcp
+0, -0x1.8812afb254729p
-54},
3448 {0x1.5efffe7b87a89p
+0, -0x1.47eb780ed6904p
-54}
3451 double w
, z
, r
, r2
, r3
, y
, invc
, logc
, kd
, hi
, lo
;
3458 if (ix
- 0x3fee000000000000ULL
< 0x3090000000000ULL
) {
3461 /* Handle close to 1.0 inputs separately. */
3462 /* Fix sign of zero with downward rounding when x==1. */
3463 if (ix
== 0x3ff0000000000000ULL
)
3468 y
= r3
* (B
[1] + r
* B
[2] + r2
* B
[3] + r3
* (B
[4] + r
* B
[5] + r2
* B
[6] +
3469 r3
* (B
[7] + r
* B
[8] + r2
* B
[9] + r3
* B
[10])));
3470 /* Worst-case error is around 0.507 ULP. */
3474 w
= rhi
* rhi
* B
[0]; /* B[0] == -0.5. */
3477 lo
+= B
[0] * rlo
* (rhi
+ r
);
3482 if (top
- 0x0010 >= 0x7ff0 - 0x0010) {
3483 /* x < 0x1p-1022 or inf or nan. */
3485 return math_error(_SING
, "log", x
, 0, (top
& 0x8000 ? 1.0 : -1.0) / x
);
3486 if (ix
== 0x7ff0000000000000ULL
) /* log(inf) == inf. */
3488 if ((top
& 0x7ff0) == 0x7ff0 && (ix
& 0xfffffffffffffULL
))
3491 return math_error(_DOMAIN
, "log", x
, 0, (x
- x
) / (x
- x
));
3492 /* x is subnormal, normalize it. */
3498 /* x = 2^k z; where z is in range [OFF,2*OFF) and exact.
3499 The range is split into N subintervals.
3500 The ith subinterval contains z and c is near its center. */
3501 tmp
= ix
- 0x3fe6000000000000ULL
;
3502 i
= (tmp
>> (52 - 7)) % (1 << 7);
3503 k
= (INT64
)tmp
>> 52; /* arithmetic shift */
3504 iz
= ix
- (tmp
& 0xfffULL
<< 52);
3509 /* log(x) = log1p(z/c-1) + log(c) + k*Ln2. */
3510 /* r ~= z/c - 1, |r| < 1/(2*N). */
3511 r
= (z
- T2
[i
].chi
- T2
[i
].clo
) * invc
;
3514 /* hi + lo = r + log(c) + k*Ln2. */
3515 w
= kd
* Ln2hi
+ logc
;
3517 lo
= w
- hi
+ r
+ kd
* Ln2lo
;
3519 /* log(x) = lo + (log1p(r) - r) + hi. */
3520 r2
= r
* r
; /* rounding error: 0x1p-54/N^2. */
3521 /* Worst case error if |y| > 0x1p-5:
3522 0.5 + 4.13/N + abs-poly-error*2^57 ULP (+ 0.002 ULP without fma)
3523 Worst case error if |y| > 0x1p-4:
3524 0.5 + 2.06/N + abs-poly-error*2^56 ULP (+ 0.001 ULP without fma). */
3525 y
= lo
+ r2
* A
[0] +
3526 r
* r2
* (A
[1] + r
* A
[2] + r2
* (A
[3] + r
* A
[4])) + hi
;
3530 /*********************************************************************
3533 double CDECL
log10( double x
)
3535 static const double ivln10hi
= 4.34294481878168880939e-01,
3536 ivln10lo
= 2.50829467116452752298e-11,
3537 log10_2hi
= 3.01029995663611771306e-01,
3538 log10_2lo
= 3.69423907715893078616e-13,
3539 Lg1
= 6.666666666666735130e-01,
3540 Lg2
= 3.999999999940941908e-01,
3541 Lg3
= 2.857142874366239149e-01,
3542 Lg4
= 2.222219843214978396e-01,
3543 Lg5
= 1.818357216161805012e-01,
3544 Lg6
= 1.531383769920937332e-01,
3545 Lg7
= 1.479819860511658591e-01;
3547 union {double f
; UINT64 i
;} u
= {x
};
3548 double hfsq
, f
, s
, z
, R
, w
, t1
, t2
, dk
, y
, hi
, lo
, val_hi
, val_lo
;
3554 if (hx
< 0x00100000 || hx
>> 31) {
3556 return math_error(_SING
, "log10", x
, 0, -1 / (x
* x
));
3557 if ((u
.i
& ~(1ULL << 63)) > 0x7ff0000000000000ULL
)
3560 return math_error(_DOMAIN
, "log10", x
, 0, (x
- x
) / (x
- x
));
3561 /* subnormal number, scale x up */
3566 } else if (hx
>= 0x7ff00000) {
3568 } else if (hx
== 0x3ff00000 && u
.i
<<32 == 0)
3571 /* reduce x into [sqrt(2)/2, sqrt(2)] */
3572 hx
+= 0x3ff00000 - 0x3fe6a09e;
3573 k
+= (int)(hx
>> 20) - 0x3ff;
3574 hx
= (hx
& 0x000fffff) + 0x3fe6a09e;
3575 u
.i
= (UINT64
)hx
<< 32 | (u
.i
& 0xffffffff);
3583 t1
= w
* (Lg2
+ w
* (Lg4
+ w
* Lg6
));
3584 t2
= z
* (Lg1
+ w
* (Lg3
+ w
* (Lg5
+ w
* Lg7
)));
3587 /* hi+lo = f - hfsq + s*(hfsq+R) ~ log(1+f) */
3590 u
.i
&= (UINT64
)-1 << 32;
3592 lo
= f
- hi
- hfsq
+ s
* (hfsq
+ R
);
3594 /* val_hi+val_lo ~ log10(1+f) + k*log10(2) */
3595 val_hi
= hi
* ivln10hi
;
3598 val_lo
= dk
* log10_2lo
+ (lo
+ hi
) * ivln10lo
+ lo
* ivln10hi
;
3601 * Extra precision in for adding y is not strictly needed
3602 * since there is no very large cancellation near x = sqrt(2) or
3603 * x = 1/sqrt(2), but we do it anyway since it costs little on CPUs
3604 * with some parallelism and it reduces the error for many args.
3607 val_lo
+= (y
- w
) + val_hi
;
3610 return val_lo
+ val_hi
;
3613 /* Compute y+TAIL = log(x) where the rounded result is y and TAIL has about
3614 additional 15 bits precision. IX is the bit representation of x, but
3615 normalized in the subnormal range using the sign bit for the exponent. */
3616 static double pow_log(UINT64 ix
, double *tail
)
3618 static const struct {
3619 double invc
, logc
, logctail
;
3621 {0x1.6a00000000000p
+0, -0x1.62c82f2b9c800p
-2, 0x1.ab42428375680p
-48},
3622 {0x1.6800000000000p
+0, -0x1.5d1bdbf580800p
-2, -0x1.ca508d8e0f720p
-46},
3623 {0x1.6600000000000p
+0, -0x1.5767717455800p
-2, -0x1.362a4d5b6506dp
-45},
3624 {0x1.6400000000000p
+0, -0x1.51aad872df800p
-2, -0x1.684e49eb067d5p
-49},
3625 {0x1.6200000000000p
+0, -0x1.4be5f95777800p
-2, -0x1.41b6993293ee0p
-47},
3626 {0x1.6000000000000p
+0, -0x1.4618bc21c6000p
-2, 0x1.3d82f484c84ccp
-46},
3627 {0x1.5e00000000000p
+0, -0x1.404308686a800p
-2, 0x1.c42f3ed820b3ap
-50},
3628 {0x1.5c00000000000p
+0, -0x1.3a64c55694800p
-2, 0x1.0b1c686519460p
-45},
3629 {0x1.5a00000000000p
+0, -0x1.347dd9a988000p
-2, 0x1.5594dd4c58092p
-45},
3630 {0x1.5800000000000p
+0, -0x1.2e8e2bae12000p
-2, 0x1.67b1e99b72bd8p
-45},
3631 {0x1.5600000000000p
+0, -0x1.2895a13de8800p
-2, 0x1.5ca14b6cfb03fp
-46},
3632 {0x1.5600000000000p
+0, -0x1.2895a13de8800p
-2, 0x1.5ca14b6cfb03fp
-46},
3633 {0x1.5400000000000p
+0, -0x1.22941fbcf7800p
-2, -0x1.65a242853da76p
-46},
3634 {0x1.5200000000000p
+0, -0x1.1c898c1699800p
-2, -0x1.fafbc68e75404p
-46},
3635 {0x1.5000000000000p
+0, -0x1.1675cababa800p
-2, 0x1.f1fc63382a8f0p
-46},
3636 {0x1.4e00000000000p
+0, -0x1.1058bf9ae4800p
-2, -0x1.6a8c4fd055a66p
-45},
3637 {0x1.4c00000000000p
+0, -0x1.0a324e2739000p
-2, -0x1.c6bee7ef4030ep
-47},
3638 {0x1.4a00000000000p
+0, -0x1.0402594b4d000p
-2, -0x1.036b89ef42d7fp
-48},
3639 {0x1.4a00000000000p
+0, -0x1.0402594b4d000p
-2, -0x1.036b89ef42d7fp
-48},
3640 {0x1.4800000000000p
+0, -0x1.fb9186d5e4000p
-3, 0x1.d572aab993c87p
-47},
3641 {0x1.4600000000000p
+0, -0x1.ef0adcbdc6000p
-3, 0x1.b26b79c86af24p
-45},
3642 {0x1.4400000000000p
+0, -0x1.e27076e2af000p
-3, -0x1.72f4f543fff10p
-46},
3643 {0x1.4200000000000p
+0, -0x1.d5c216b4fc000p
-3, 0x1.1ba91bbca681bp
-45},
3644 {0x1.4000000000000p
+0, -0x1.c8ff7c79aa000p
-3, 0x1.7794f689f8434p
-45},
3645 {0x1.4000000000000p
+0, -0x1.c8ff7c79aa000p
-3, 0x1.7794f689f8434p
-45},
3646 {0x1.3e00000000000p
+0, -0x1.bc286742d9000p
-3, 0x1.94eb0318bb78fp
-46},
3647 {0x1.3c00000000000p
+0, -0x1.af3c94e80c000p
-3, 0x1.a4e633fcd9066p
-52},
3648 {0x1.3a00000000000p
+0, -0x1.a23bc1fe2b000p
-3, -0x1.58c64dc46c1eap
-45},
3649 {0x1.3a00000000000p
+0, -0x1.a23bc1fe2b000p
-3, -0x1.58c64dc46c1eap
-45},
3650 {0x1.3800000000000p
+0, -0x1.9525a9cf45000p
-3, -0x1.ad1d904c1d4e3p
-45},
3651 {0x1.3600000000000p
+0, -0x1.87fa06520d000p
-3, 0x1.bbdbf7fdbfa09p
-45},
3652 {0x1.3400000000000p
+0, -0x1.7ab890210e000p
-3, 0x1.bdb9072534a58p
-45},
3653 {0x1.3400000000000p
+0, -0x1.7ab890210e000p
-3, 0x1.bdb9072534a58p
-45},
3654 {0x1.3200000000000p
+0, -0x1.6d60fe719d000p
-3, -0x1.0e46aa3b2e266p
-46},
3655 {0x1.3000000000000p
+0, -0x1.5ff3070a79000p
-3, -0x1.e9e439f105039p
-46},
3656 {0x1.3000000000000p
+0, -0x1.5ff3070a79000p
-3, -0x1.e9e439f105039p
-46},
3657 {0x1.2e00000000000p
+0, -0x1.526e5e3a1b000p
-3, -0x1.0de8b90075b8fp
-45},
3658 {0x1.2c00000000000p
+0, -0x1.44d2b6ccb8000p
-3, 0x1.70cc16135783cp
-46},
3659 {0x1.2c00000000000p
+0, -0x1.44d2b6ccb8000p
-3, 0x1.70cc16135783cp
-46},
3660 {0x1.2a00000000000p
+0, -0x1.371fc201e9000p
-3, 0x1.178864d27543ap
-48},
3661 {0x1.2800000000000p
+0, -0x1.29552f81ff000p
-3, -0x1.48d301771c408p
-45},
3662 {0x1.2600000000000p
+0, -0x1.1b72ad52f6000p
-3, -0x1.e80a41811a396p
-45},
3663 {0x1.2600000000000p
+0, -0x1.1b72ad52f6000p
-3, -0x1.e80a41811a396p
-45},
3664 {0x1.2400000000000p
+0, -0x1.0d77e7cd09000p
-3, 0x1.a699688e85bf4p
-47},
3665 {0x1.2400000000000p
+0, -0x1.0d77e7cd09000p
-3, 0x1.a699688e85bf4p
-47},
3666 {0x1.2200000000000p
+0, -0x1.fec9131dbe000p
-4, -0x1.575545ca333f2p
-45},
3667 {0x1.2000000000000p
+0, -0x1.e27076e2b0000p
-4, 0x1.a342c2af0003cp
-45},
3668 {0x1.2000000000000p
+0, -0x1.e27076e2b0000p
-4, 0x1.a342c2af0003cp
-45},
3669 {0x1.1e00000000000p
+0, -0x1.c5e548f5bc000p
-4, -0x1.d0c57585fbe06p
-46},
3670 {0x1.1c00000000000p
+0, -0x1.a926d3a4ae000p
-4, 0x1.53935e85baac8p
-45},
3671 {0x1.1c00000000000p
+0, -0x1.a926d3a4ae000p
-4, 0x1.53935e85baac8p
-45},
3672 {0x1.1a00000000000p
+0, -0x1.8c345d631a000p
-4, 0x1.37c294d2f5668p
-46},
3673 {0x1.1a00000000000p
+0, -0x1.8c345d631a000p
-4, 0x1.37c294d2f5668p
-46},
3674 {0x1.1800000000000p
+0, -0x1.6f0d28ae56000p
-4, -0x1.69737c93373dap
-45},
3675 {0x1.1600000000000p
+0, -0x1.51b073f062000p
-4, 0x1.f025b61c65e57p
-46},
3676 {0x1.1600000000000p
+0, -0x1.51b073f062000p
-4, 0x1.f025b61c65e57p
-46},
3677 {0x1.1400000000000p
+0, -0x1.341d7961be000p
-4, 0x1.c5edaccf913dfp
-45},
3678 {0x1.1400000000000p
+0, -0x1.341d7961be000p
-4, 0x1.c5edaccf913dfp
-45},
3679 {0x1.1200000000000p
+0, -0x1.16536eea38000p
-4, 0x1.47c5e768fa309p
-46},
3680 {0x1.1000000000000p
+0, -0x1.f0a30c0118000p
-5, 0x1.d599e83368e91p
-45},
3681 {0x1.1000000000000p
+0, -0x1.f0a30c0118000p
-5, 0x1.d599e83368e91p
-45},
3682 {0x1.0e00000000000p
+0, -0x1.b42dd71198000p
-5, 0x1.c827ae5d6704cp
-46},
3683 {0x1.0e00000000000p
+0, -0x1.b42dd71198000p
-5, 0x1.c827ae5d6704cp
-46},
3684 {0x1.0c00000000000p
+0, -0x1.77458f632c000p
-5, -0x1.cfc4634f2a1eep
-45},
3685 {0x1.0c00000000000p
+0, -0x1.77458f632c000p
-5, -0x1.cfc4634f2a1eep
-45},
3686 {0x1.0a00000000000p
+0, -0x1.39e87b9fec000p
-5, 0x1.502b7f526feaap
-48},
3687 {0x1.0a00000000000p
+0, -0x1.39e87b9fec000p
-5, 0x1.502b7f526feaap
-48},
3688 {0x1.0800000000000p
+0, -0x1.f829b0e780000p
-6, -0x1.980267c7e09e4p
-45},
3689 {0x1.0800000000000p
+0, -0x1.f829b0e780000p
-6, -0x1.980267c7e09e4p
-45},
3690 {0x1.0600000000000p
+0, -0x1.7b91b07d58000p
-6, -0x1.88d5493faa639p
-45},
3691 {0x1.0400000000000p
+0, -0x1.fc0a8b0fc0000p
-7, -0x1.f1e7cf6d3a69cp
-50},
3692 {0x1.0400000000000p
+0, -0x1.fc0a8b0fc0000p
-7, -0x1.f1e7cf6d3a69cp
-50},
3693 {0x1.0200000000000p
+0, -0x1.fe02a6b100000p
-8, -0x1.9e23f0dda40e4p
-46},
3694 {0x1.0200000000000p
+0, -0x1.fe02a6b100000p
-8, -0x1.9e23f0dda40e4p
-46},
3695 {0x1.0000000000000p
+0, 0x0.0000000000000p
+0, 0x0.0000000000000p
+0},
3696 {0x1.0000000000000p
+0, 0x0.0000000000000p
+0, 0x0.0000000000000p
+0},
3697 {0x1.fc00000000000p
-1, 0x1.0101575890000p
-7, -0x1.0c76b999d2be8p
-46},
3698 {0x1.f800000000000p
-1, 0x1.0205658938000p
-6, -0x1.3dc5b06e2f7d2p
-45},
3699 {0x1.f400000000000p
-1, 0x1.8492528c90000p
-6, -0x1.aa0ba325a0c34p
-45},
3700 {0x1.f000000000000p
-1, 0x1.0415d89e74000p
-5, 0x1.111c05cf1d753p
-47},
3701 {0x1.ec00000000000p
-1, 0x1.466aed42e0000p
-5, -0x1.c167375bdfd28p
-45},
3702 {0x1.e800000000000p
-1, 0x1.894aa149fc000p
-5, -0x1.97995d05a267dp
-46},
3703 {0x1.e400000000000p
-1, 0x1.ccb73cdddc000p
-5, -0x1.a68f247d82807p
-46},
3704 {0x1.e200000000000p
-1, 0x1.eea31c006c000p
-5, -0x1.e113e4fc93b7bp
-47},
3705 {0x1.de00000000000p
-1, 0x1.1973bd1466000p
-4, -0x1.5325d560d9e9bp
-45},
3706 {0x1.da00000000000p
-1, 0x1.3bdf5a7d1e000p
-4, 0x1.cc85ea5db4ed7p
-45},
3707 {0x1.d600000000000p
-1, 0x1.5e95a4d97a000p
-4, -0x1.c69063c5d1d1ep
-45},
3708 {0x1.d400000000000p
-1, 0x1.700d30aeac000p
-4, 0x1.c1e8da99ded32p
-49},
3709 {0x1.d000000000000p
-1, 0x1.9335e5d594000p
-4, 0x1.3115c3abd47dap
-45},
3710 {0x1.cc00000000000p
-1, 0x1.b6ac88dad6000p
-4, -0x1.390802bf768e5p
-46},
3711 {0x1.ca00000000000p
-1, 0x1.c885801bc4000p
-4, 0x1.646d1c65aacd3p
-45},
3712 {0x1.c600000000000p
-1, 0x1.ec739830a2000p
-4, -0x1.dc068afe645e0p
-45},
3713 {0x1.c400000000000p
-1, 0x1.fe89139dbe000p
-4, -0x1.534d64fa10afdp
-45},
3714 {0x1.c000000000000p
-1, 0x1.1178e8227e000p
-3, 0x1.1ef78ce2d07f2p
-45},
3715 {0x1.be00000000000p
-1, 0x1.1aa2b7e23f000p
-3, 0x1.ca78e44389934p
-45},
3716 {0x1.ba00000000000p
-1, 0x1.2d1610c868000p
-3, 0x1.39d6ccb81b4a1p
-47},
3717 {0x1.b800000000000p
-1, 0x1.365fcb0159000p
-3, 0x1.62fa8234b7289p
-51},
3718 {0x1.b400000000000p
-1, 0x1.4913d8333b000p
-3, 0x1.5837954fdb678p
-45},
3719 {0x1.b200000000000p
-1, 0x1.527e5e4a1b000p
-3, 0x1.633e8e5697dc7p
-45},
3720 {0x1.ae00000000000p
-1, 0x1.6574ebe8c1000p
-3, 0x1.9cf8b2c3c2e78p
-46},
3721 {0x1.ac00000000000p
-1, 0x1.6f0128b757000p
-3, -0x1.5118de59c21e1p
-45},
3722 {0x1.aa00000000000p
-1, 0x1.7898d85445000p
-3, -0x1.c661070914305p
-46},
3723 {0x1.a600000000000p
-1, 0x1.8beafeb390000p
-3, -0x1.73d54aae92cd1p
-47},
3724 {0x1.a400000000000p
-1, 0x1.95a5adcf70000p
-3, 0x1.7f22858a0ff6fp
-47},
3725 {0x1.a000000000000p
-1, 0x1.a93ed3c8ae000p
-3, -0x1.8724350562169p
-45},
3726 {0x1.9e00000000000p
-1, 0x1.b31d8575bd000p
-3, -0x1.c358d4eace1aap
-47},
3727 {0x1.9c00000000000p
-1, 0x1.bd087383be000p
-3, -0x1.d4bc4595412b6p
-45},
3728 {0x1.9a00000000000p
-1, 0x1.c6ffbc6f01000p
-3, -0x1.1ec72c5962bd2p
-48},
3729 {0x1.9600000000000p
-1, 0x1.db13db0d49000p
-3, -0x1.aff2af715b035p
-45},
3730 {0x1.9400000000000p
-1, 0x1.e530effe71000p
-3, 0x1.212276041f430p
-51},
3731 {0x1.9200000000000p
-1, 0x1.ef5ade4dd0000p
-3, -0x1.a211565bb8e11p
-51},
3732 {0x1.9000000000000p
-1, 0x1.f991c6cb3b000p
-3, 0x1.bcbecca0cdf30p
-46},
3733 {0x1.8c00000000000p
-1, 0x1.07138604d5800p
-2, 0x1.89cdb16ed4e91p
-48},
3734 {0x1.8a00000000000p
-1, 0x1.0c42d67616000p
-2, 0x1.7188b163ceae9p
-45},
3735 {0x1.8800000000000p
-1, 0x1.1178e8227e800p
-2, -0x1.c210e63a5f01cp
-45},
3736 {0x1.8600000000000p
-1, 0x1.16b5ccbacf800p
-2, 0x1.b9acdf7a51681p
-45},
3737 {0x1.8400000000000p
-1, 0x1.1bf99635a6800p
-2, 0x1.ca6ed5147bdb7p
-45},
3738 {0x1.8200000000000p
-1, 0x1.214456d0eb800p
-2, 0x1.a87deba46baeap
-47},
3739 {0x1.7e00000000000p
-1, 0x1.2bef07cdc9000p
-2, 0x1.a9cfa4a5004f4p
-45},
3740 {0x1.7c00000000000p
-1, 0x1.314f1e1d36000p
-2, -0x1.8e27ad3213cb8p
-45},
3741 {0x1.7a00000000000p
-1, 0x1.36b6776be1000p
-2, 0x1.16ecdb0f177c8p
-46},
3742 {0x1.7800000000000p
-1, 0x1.3c25277333000p
-2, 0x1.83b54b606bd5cp
-46},
3743 {0x1.7600000000000p
-1, 0x1.419b423d5e800p
-2, 0x1.8e436ec90e09dp
-47},
3744 {0x1.7400000000000p
-1, 0x1.4718dc271c800p
-2, -0x1.f27ce0967d675p
-45},
3745 {0x1.7200000000000p
-1, 0x1.4c9e09e173000p
-2, -0x1.e20891b0ad8a4p
-45},
3746 {0x1.7000000000000p
-1, 0x1.522ae0738a000p
-2, 0x1.ebe708164c759p
-45},
3747 {0x1.6e00000000000p
-1, 0x1.57bf753c8d000p
-2, 0x1.fadedee5d40efp
-46},
3748 {0x1.6c00000000000p
-1, 0x1.5d5bddf596000p
-2, -0x1.a0b2a08a465dcp
-47},
3750 static const double A
[] = {
3752 0x1.555555555556p
-2 * -2,
3753 -0x1.0000000000006p
-2 * -2,
3754 0x1.999999959554ep
-3 * 4,
3755 -0x1.555555529a47ap
-3 * 4,
3756 0x1.2495b9b4845e9p
-3 * -8,
3757 -0x1.0002b8b263fc3p
-3 * -8
3759 static const double ln2hi
= 0x1.62e42fefa3800p
-1,
3760 ln2lo
= 0x1.ef35793c76730p
-45;
3762 double z
, r
, y
, invc
, logc
, logctail
, kd
, hi
, t1
, t2
, lo
, lo1
, lo2
, p
;
3763 double zhi
, zlo
, rhi
, rlo
, ar
, ar2
, ar3
, lo3
, lo4
, arhi
, arhi2
;
3767 /* x = 2^k z; where z is in range [OFF,2*OFF) and exact.
3768 The range is split into N subintervals.
3769 The ith subinterval contains z and c is near its center. */
3770 tmp
= ix
- 0x3fe6955500000000ULL
;
3771 i
= (tmp
>> (52 - 7)) % (1 << 7);
3772 k
= (INT64
)tmp
>> 52; /* arithmetic shift */
3773 iz
= ix
- (tmp
& 0xfffULL
<< 52);
3777 /* log(x) = k*Ln2 + log(c) + log1p(z/c-1). */
3780 logctail
= T
[i
].logctail
;
3782 /* Note: 1/c is j/N or j/N/2 where j is an integer in [N,2N) and
3783 |z/c - 1| < 1/N, so r = z/c - 1 is exactly representible. */
3784 /* Split z such that rhi, rlo and rhi*rhi are exact and |rlo| <= |r|. */
3785 iz
= (iz
+ (1ULL << 31)) & (-1ULL << 32);
3786 zhi
= *(double*)&iz
;
3788 rhi
= zhi
* invc
- 1.0;
3792 /* k*Ln2 + log(c) + r. */
3793 t1
= kd
* ln2hi
+ logc
;
3795 lo1
= kd
* ln2lo
+ logctail
;
3798 /* Evaluation is optimized assuming superscalar pipelined execution. */
3799 ar
= A
[0] * r
; /* A[0] = -0.5. */
3802 /* k*Ln2 + log(c) + r + A[0]*r*r. */
3806 lo3
= rlo
* (ar
+ arhi
);
3807 lo4
= t2
- hi
+ arhi2
;
3808 /* p = log1p(r) - r - A[0]*r*r. */
3809 p
= (ar3
* (A
[1] + r
* A
[2] + ar2
* (A
[3] + r
* A
[4] + ar2
* (A
[5] + r
* A
[6]))));
3810 lo
= lo1
+ lo2
+ lo3
+ lo4
+ p
;
3812 *tail
= hi
- y
+ lo
;
3816 /* Computes sign*exp(x+xtail) where |xtail| < 2^-8/N and |xtail| <= |x|.
3817 The sign_bias argument is SIGN_BIAS or 0 and sets the sign to -1 or 1. */
3818 static double pow_exp(double argx
, double argy
, double x
, double xtail
, UINT32 sign_bias
)
3820 static const double C
[] = {
3821 0x1.ffffffffffdbdp
-2,
3822 0x1.555555555543cp
-3,
3823 0x1.55555cf172b91p
-5,
3824 0x1.1111167a4d017p
-7
3826 static const double invln2N
= 0x1.71547652b82fep0
* (1 << 7),
3827 negln2hiN
= -0x1.62e42fefa0000p
-8,
3828 negln2loN
= -0x1.cf79abc9e3b3ap
-47;
3831 UINT64 ki
, idx
, top
, sbits
;
3832 double kd
, z
, r
, r2
, scale
, tail
, tmp
;
3834 abstop
= (*(UINT64
*)&x
>> 52) & 0x7ff;
3835 if (abstop
- 0x3c9 >= 0x408 - 0x3c9) {
3836 if (abstop
- 0x3c9 >= 0x80000000) {
3837 /* Avoid spurious underflow for tiny x. */
3838 /* Note: 0 is common input. */
3839 double one
= 1.0 + x
;
3840 return sign_bias
? -one
: one
;
3842 if (abstop
>= 0x409) {
3843 /* Note: inf and nan are already handled. */
3844 if (*(UINT64
*)&x
>> 63)
3845 return math_error(_UNDERFLOW
, "pow", argx
, argy
, (sign_bias
? -DBL_MIN
: DBL_MIN
) * DBL_MIN
);
3846 return math_error(_OVERFLOW
, "pow", argx
, argy
, (sign_bias
? -DBL_MAX
: DBL_MAX
) * DBL_MAX
);
3848 /* Large x is special cased below. */
3852 /* exp(x) = 2^(k/N) * exp(r), with exp(r) in [2^(-1/2N),2^(1/2N)]. */
3853 /* x = ln2/N*k + r, with int k and r in [-ln2/2N, ln2/2N]. */
3857 r
= x
+ kd
* negln2hiN
+ kd
* negln2loN
;
3858 /* The code assumes 2^-200 < |xtail| < 2^-8/N. */
3860 /* 2^(k/N) ~= scale * (1 + tail). */
3861 idx
= 2 * (ki
% (1 << 7));
3862 top
= (ki
+ sign_bias
) << (52 - 7);
3863 tail
= *(double*)&exp_T
[idx
];
3864 /* This is only a valid scale when -1023*N < k < 1024*N. */
3865 sbits
= exp_T
[idx
+ 1] + top
;
3866 /* exp(x) = 2^(k/N) * exp(r) ~= scale + scale * (tail + exp(r) - 1). */
3867 /* Evaluation is optimized assuming superscalar pipelined execution. */
3869 /* Without fma the worst case error is 0.25/N ulp larger. */
3870 /* Worst case error is less than 0.5+1.11/N+(abs poly error * 2^53) ulp. */
3871 tmp
= tail
+ r
+ r2
* (C
[0] + r
* C
[1]) + r2
* r2
* (C
[2] + r
* C
[3]);
3873 /* Handle cases that may overflow or underflow when computing the result that
3874 is scale*(1+TMP) without intermediate rounding. The bit representation of
3875 scale is in SBITS, however it has a computed exponent that may have
3876 overflown into the sign bit so that needs to be adjusted before using it as
3877 a double. (int32_t)KI is the k used in the argument reduction and exponent
3878 adjustment of scale, positive k here means the result may overflow and
3879 negative k means the result may underflow. */
3882 if ((ki
& 0x80000000) == 0) {
3883 /* k > 0, the exponent of scale might have overflowed by <= 460. */
3884 sbits
-= 1009ull << 52;
3885 scale
= *(double*)&sbits
;
3886 y
= 0x1p
1009 * (scale
+ scale
* tmp
);
3888 return math_error(_OVERFLOW
, "pow", argx
, argy
, y
);
3891 /* k < 0, need special care in the subnormal range. */
3892 sbits
+= 1022ull << 52;
3893 /* Note: sbits is signed scale. */
3894 scale
= *(double*)&sbits
;
3895 y
= scale
+ scale
* tmp
;
3896 if (fabs(y
) < 1.0) {
3897 /* Round y to the right precision before scaling it into the subnormal
3898 range to avoid double rounding that can cause 0.5+E/2 ulp error where
3899 E is the worst-case ulp error outside the subnormal range. So this
3900 is only useful if the goal is better than 1 ulp worst-case error. */
3901 double hi
, lo
, one
= 1.0;
3904 lo
= scale
- y
+ scale
* tmp
;
3906 lo
= one
- hi
+ y
+ lo
;
3908 /* Fix the sign of 0. */
3910 sbits
&= 0x8000000000000000ULL
;
3911 y
= *(double*)&sbits
;
3913 /* The underflow exception needs to be signaled explicitly. */
3914 fp_barrier(fp_barrier(0x1p
-1022) * 0x1p
-1022);
3916 return math_error(_UNDERFLOW
, "pow", argx
, argy
, y
);
3921 scale
= *(double*)&sbits
;
3922 /* Note: tmp == 0 or |tmp| > 2^-200 and scale > 2^-739, so there
3923 is no spurious underflow here even without fma. */
3924 return scale
+ scale
* tmp
;
3927 /* Returns 0 if not int, 1 if odd int, 2 if even int. The argument is
3928 the bit representation of a non-zero finite floating-point value. */
3929 static inline int pow_checkint(UINT64 iy
)
3931 int e
= iy
>> 52 & 0x7ff;
3936 if (iy
& ((1ULL << (0x3ff + 52 - e
)) - 1))
3938 if (iy
& (1ULL << (0x3ff + 52 - e
)))
3943 /*********************************************************************
3946 * Copied from musl: src/math/pow.c
3948 double CDECL
pow( double x
, double y
)
3950 UINT32 sign_bias
= 0;
3953 double lo
, hi
, ehi
, elo
, yhi
, ylo
, lhi
, llo
;
3959 if (topx
- 0x001 >= 0x7ff - 0x001 ||
3960 (topy
& 0x7ff) - 0x3be >= 0x43e - 0x3be) {
3961 /* Note: if |y| > 1075 * ln2 * 2^53 ~= 0x1.749p62 then pow(x,y) = inf/0
3962 and if |y| < 2^-54 / 1075 ~= 0x1.e7b6p-65 then pow(x,y) = +-1. */
3963 /* Special cases: (x < 0x1p-126 or inf or nan) or
3964 (|y| < 0x1p-65 or |y| >= 0x1p63 or nan). */
3965 if (2 * iy
- 1 >= 2 * 0x7ff0000000000000ULL
- 1) {
3968 if (ix
== 0x3ff0000000000000ULL
)
3970 if (2 * ix
> 2 * 0x7ff0000000000000ULL
||
3971 2 * iy
> 2 * 0x7ff0000000000000ULL
)
3973 if (2 * ix
== 2 * 0x3ff0000000000000ULL
)
3975 if ((2 * ix
< 2 * 0x3ff0000000000000ULL
) == !(iy
>> 63))
3976 return 0.0; /* |x|<1 && y==inf or |x|>1 && y==-inf. */
3979 if (2 * ix
- 1 >= 2 * 0x7ff0000000000000ULL
- 1) {
3981 if (ix
>> 63 && pow_checkint(iy
) == 1)
3983 if (iy
& 0x8000000000000000ULL
&& x2
== 0.0)
3984 return math_error(_SING
, "pow", x
, y
, 1 / x2
);
3985 /* Without the barrier some versions of clang hoist the 1/x2 and
3986 thus division by zero exception can be signaled spuriously. */
3987 return iy
>> 63 ? fp_barrier(1 / x2
) : x2
;
3989 /* Here x and y are non-zero finite. */
3992 int yint
= pow_checkint(iy
);
3994 return math_error(_DOMAIN
, "pow", x
, y
, 0 / (x
- x
));
3996 sign_bias
= 0x800 << 7;
3997 ix
&= 0x7fffffffffffffff;
4000 if ((topy
& 0x7ff) - 0x3be >= 0x43e - 0x3be) {
4001 /* Note: sign_bias == 0 here because y is not odd. */
4002 if (ix
== 0x3ff0000000000000ULL
)
4004 if ((topy
& 0x7ff) < 0x3be) {
4005 /* |y| < 2^-65, x^y ~= 1 + y*log(x). */
4006 return ix
> 0x3ff0000000000000ULL
? 1.0 + y
: 1.0 - y
;
4008 if ((ix
> 0x3ff0000000000000ULL
) == (topy
< 0x800))
4009 return math_error(_OVERFLOW
, "pow", x
, y
, fp_barrier(DBL_MAX
) * DBL_MAX
);
4010 return math_error(_UNDERFLOW
, "pow", x
, y
, fp_barrier(DBL_MIN
) * DBL_MIN
);
4013 /* Normalize subnormal x so exponent becomes negative. */
4016 ix
&= 0x7fffffffffffffff;
4021 hi
= pow_log(ix
, &lo
);
4023 yhi
= *(double*)&iy
;
4025 *(UINT64
*)&lhi
= *(UINT64
*)&hi
& -1ULL << 27;
4026 llo
= fp_barrier(hi
- lhi
+ lo
);
4028 elo
= ylo
* lhi
+ y
* llo
; /* |elo| < |ehi| * 2^-25. */
4029 return pow_exp(x
, y
, ehi
, elo
, sign_bias
);
4032 /*********************************************************************
4035 * Copied from musl: src/math/sin.c
4037 double CDECL
sin( double x
)
4043 ix
= *(ULONGLONG
*)&x
>> 32;
4047 if (ix
<= 0x3fe921fb) {
4048 if (ix
< 0x3e500000) { /* |x| < 2**-26 */
4049 /* raise inexact if x != 0 and underflow if subnormal*/
4050 fp_barrier(ix
< 0x00100000 ? x
/0x1p
120f
: x
+0x1p
120f
);
4053 return __sin(x
, 0.0, 0);
4056 /* sin(Inf or NaN) is NaN */
4058 return math_error(_DOMAIN
, "sin", x
, 0, x
- x
);
4059 if (ix
>= 0x7ff00000)
4062 /* argument reduction needed */
4063 n
= __rem_pio2(x
, y
);
4065 case 0: return __sin(y
[0], y
[1], 1);
4066 case 1: return __cos(y
[0], y
[1]);
4067 case 2: return -__sin(y
[0], y
[1], 1);
4068 default: return -__cos(y
[0], y
[1]);
4072 /*********************************************************************
4075 double CDECL
sinh( double x
)
4077 UINT64 ux
= *(UINT64
*)&x
;
4078 UINT64 sign
= ux
& 0x8000000000000000ULL
;
4086 ux
&= (UINT64
)-1 / 2;
4087 absx
= *(double*)&ux
;
4090 /* |x| < log(DBL_MAX) */
4091 if (w
< 0x40862e42) {
4093 if (w
< 0x3ff00000) {
4094 if (w
< 0x3ff00000 - (26 << 20))
4096 return h
* (2 * t
- t
* t
/ (t
+ 1));
4098 return h
* (t
+ t
/ (t
+ 1));
4101 /* |x| > log(DBL_MAX) or nan */
4102 /* note: the result is stored to handle overflow */
4103 if (ux
> 0x7ff0000000000000ULL
)
4104 *(UINT64
*)&t
= ux
| sign
| 0x0008000000000000ULL
;
4106 t
= __expo2(absx
, 2 * h
);
4110 static BOOL
sqrt_validate( double *x
, BOOL update_sw
)
4112 short c
= _dclass(*x
);
4114 if (c
== FP_ZERO
) return FALSE
;
4119 *x
= math_error(_DOMAIN
, "sqrt", *x
, 0, *x
);
4121 /* set signaling bit */
4122 *(ULONGLONG
*)x
|= 0x8000000000000ULL
;
4128 *x
= math_error(_DOMAIN
, "sqrt", *x
, 0, ret_nan(update_sw
));
4131 if (c
== FP_INFINITE
) return FALSE
;
4135 #if defined(__x86_64__) || defined(__i386__)
4136 double CDECL
sse2_sqrt(double);
4137 __ASM_GLOBAL_FUNC( sse2_sqrt
,
4138 "sqrtsd %xmm0, %xmm0\n\t"
4143 double CDECL
x87_sqrt(double);
4144 __ASM_GLOBAL_FUNC( x87_sqrt
,
4152 /*********************************************************************
4155 * Copied from musl: src/math/sqrt.c
4157 double CDECL
sqrt( double x
)
4160 if (!sqrt_validate(&x
, TRUE
))
4163 return sse2_sqrt(x
);
4164 #elif defined( __i386__ )
4165 if (!sqrt_validate(&x
, TRUE
))
4170 static const double tiny
= 1.0e-300;
4173 int sign
= 0x80000000;
4175 unsigned int r
,t1
,s1
,ix1
,q1
;
4178 if (!sqrt_validate(&x
, TRUE
))
4181 ix
= *(ULONGLONG
*)&x
;
4187 if (m
== 0) { /* subnormal x */
4193 for (i
=0; (ix0
& 0x00100000) == 0; i
++)
4196 ix0
|= ix1
>> (32 - i
);
4199 m
-= 1023; /* unbias exponent */
4200 ix0
= (ix0
& 0x000fffff) | 0x00100000;
4201 if (m
& 1) { /* odd m, double x to make it even */
4202 ix0
+= ix0
+ ((ix1
& sign
) >> 31);
4205 m
>>= 1; /* m = [m/2] */
4207 /* generate sqrt(x) bit by bit */
4208 ix0
+= ix0
+ ((ix1
& sign
) >> 31);
4210 q
= q1
= s0
= s1
= 0; /* [q,q1] = sqrt(x) */
4211 r
= 0x00200000; /* r = moving bit from right to left */
4220 ix0
+= ix0
+ ((ix1
& sign
) >> 31);
4229 if (t
< ix0
|| (t
== ix0
&& t1
<= ix1
)) {
4231 if ((t1
&sign
) == sign
&& (s1
& sign
) == 0)
4239 ix0
+= ix0
+ ((ix1
& sign
) >> 31);
4244 /* use floating add to find out rounding direction */
4245 if ((ix0
| ix1
) != 0) {
4246 z
= 1.0 - tiny
; /* raise inexact flag */
4249 if (q1
== (unsigned int)0xffffffff) {
4252 } else if (z
> 1.0) {
4253 if (q1
== (unsigned int)0xfffffffe)
4260 ix0
= (q
>> 1) + 0x3fe00000;
4264 ix
= ix0
+ ((unsigned int)m
<< 20);
4267 return *(double*)&ix
;
4271 /* Copied from musl: src/math/__tan.c */
4272 static double __tan(double x
, double y
, int odd
)
4274 static const double T
[] = {
4275 3.33333333333334091986e-01,
4276 1.33333333333201242699e-01,
4277 5.39682539762260521377e-02,
4278 2.18694882948595424599e-02,
4279 8.86323982359930005737e-03,
4280 3.59207910759131235356e-03,
4281 1.45620945432529025516e-03,
4282 5.88041240820264096874e-04,
4283 2.46463134818469906812e-04,
4284 7.81794442939557092300e-05,
4285 7.14072491382608190305e-05,
4286 -1.85586374855275456654e-05,
4287 2.59073051863633712884e-05,
4289 static const double pio4
= 7.85398163397448278999e-01;
4290 static const double pio4lo
= 3.06161699786838301793e-17;
4292 double z
, r
, v
, w
, s
, a
, w0
, a0
;
4296 hx
= *(ULONGLONG
*)&x
>> 32;
4297 big
= (hx
& 0x7fffffff) >= 0x3FE59428; /* |x| >= 0.6744 */
4304 x
= (pio4
- x
) + (pio4lo
- y
);
4309 r
= T
[1] + w
* (T
[3] + w
* (T
[5] + w
* (T
[7] + w
* (T
[9] + w
* T
[11]))));
4310 v
= z
* (T
[2] + w
* (T
[4] + w
* (T
[6] + w
* (T
[8] + w
* (T
[10] + w
* T
[12])))));
4312 r
= y
+ z
* (s
* (r
+ v
) + y
) + s
* T
[0];
4316 v
= s
- 2.0 * (x
+ (r
- w
* w
/ (w
+ s
)));
4317 return sign
? -v
: v
;
4321 /* -1.0/(x+r) has up to 2ulp error, so compute it accurately */
4323 *(LONGLONG
*)&w0
= *(LONGLONG
*)&w0
& 0xffffffff00000000ULL
;
4324 v
= r
- (w0
- x
); /* w0+v = r+x */
4326 *(LONGLONG
*)&a0
= *(LONGLONG
*)&a0
& 0xffffffff00000000ULL
;
4327 return a0
+ a
* (1.0 + a0
* w0
+ a0
* v
);
4330 /*********************************************************************
4333 * Copied from musl: src/math/tan.c
4335 double CDECL
tan( double x
)
4341 ix
= *(ULONGLONG
*)&x
>> 32;
4344 if (ix
<= 0x3fe921fb) { /* |x| ~< pi/4 */
4345 if (ix
< 0x3e400000) { /* |x| < 2**-27 */
4346 /* raise inexact if x!=0 and underflow if subnormal */
4347 fp_barrier(ix
< 0x00100000 ? x
/ 0x1p
120f
: x
+ 0x1p
120f
);
4350 return __tan(x
, 0.0, 0);
4354 return math_error(_DOMAIN
, "tan", x
, 0, x
- x
);
4355 if (ix
>= 0x7ff00000)
4358 n
= __rem_pio2(x
, y
);
4359 return __tan(y
[0], y
[1], n
& 1);
4362 /*********************************************************************
4365 double CDECL
tanh( double x
)
4367 UINT64 ui
= *(UINT64
*)&x
;
4368 UINT64 sign
= ui
& 0x8000000000000000ULL
;
4373 ui
&= (UINT64
)-1 / 2;
4377 if (w
> 0x3fe193ea) {
4378 /* |x| > log(3)/2 ~= 0.5493 or nan */
4379 if (w
> 0x40340000) {
4380 if (ui
> 0x7ff0000000000000ULL
) {
4381 *(UINT64
*)&x
= ui
| sign
| 0x0008000000000000ULL
;
4382 #if _MSVCR_VER < 140
4383 return math_error(_DOMAIN
, "tanh", x
, 0, x
);
4389 /* note: this branch avoids raising overflow */
4390 fp_barrier(x
+ 0x1p
120f
);
4394 t
= 1 - 2 / (t
+ 2);
4396 } else if (w
> 0x3fd058ae) {
4397 /* |x| > log(5/3)/2 ~= 0.2554 */
4400 } else if (w
>= 0x00100000) {
4401 /* |x| >= 0x1p-1022, up to 2ulp error in [0.1,0.2554] */
4402 t
= __expm1(-2 * x
);
4405 /* |x| is subnormal */
4406 /* note: the branch above would not raise underflow in [0x1p-1023,0x1p-1022) */
4407 fp_barrier((float)x
);
4410 return sign
? -t
: t
;
4414 #if (defined(__GNUC__) || defined(__clang__)) && defined(__i386__)
4416 #define CREATE_FPU_FUNC1(name, call) \
4417 __ASM_GLOBAL_FUNC(name, \
4419 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") \
4420 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t") \
4421 "movl %esp, %ebp\n\t" \
4422 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t") \
4423 "subl $68, %esp\n\t" /* sizeof(double)*8 + sizeof(int) */ \
4424 "fstpl (%esp)\n\t" /* store function argument */ \
4426 "movl $1, %ecx\n\t" /* empty FPU stack */ \
4430 "and $0x4500, %ax\n\t" \
4431 "cmp $0x4100, %ax\n\t" \
4433 "fstpl (%esp,%ecx,8)\n\t" \
4438 "movl %ecx, -4(%ebp)\n\t" \
4439 "call " __ASM_NAME( #call ) "\n\t" \
4440 "movl -4(%ebp), %ecx\n\t" \
4441 "fstpl (%esp)\n\t" /* save result */ \
4442 "3:\n\t" /* restore FPU stack */ \
4444 "fldl (%esp,%ecx,8)\n\t" \
4445 "cmpl $0, %ecx\n\t" \
4448 __ASM_CFI(".cfi_def_cfa %esp,4\n\t") \
4449 __ASM_CFI(".cfi_same_value %ebp\n\t") \
4452 #define CREATE_FPU_FUNC2(name, call) \
4453 __ASM_GLOBAL_FUNC(name, \
4455 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") \
4456 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t") \
4457 "movl %esp, %ebp\n\t" \
4458 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t") \
4459 "subl $68, %esp\n\t" /* sizeof(double)*8 + sizeof(int) */ \
4460 "fstpl 8(%esp)\n\t" /* store function argument */ \
4462 "fstpl (%esp)\n\t" \
4464 "movl $2, %ecx\n\t" /* empty FPU stack */ \
4468 "and $0x4500, %ax\n\t" \
4469 "cmp $0x4100, %ax\n\t" \
4471 "fstpl (%esp,%ecx,8)\n\t" \
4476 "movl %ecx, -4(%ebp)\n\t" \
4477 "call " __ASM_NAME( #call ) "\n\t" \
4478 "movl -4(%ebp), %ecx\n\t" \
4479 "fstpl 8(%esp)\n\t" /* save result */ \
4480 "3:\n\t" /* restore FPU stack */ \
4482 "fldl (%esp,%ecx,8)\n\t" \
4483 "cmpl $1, %ecx\n\t" \
4486 __ASM_CFI(".cfi_def_cfa %esp,4\n\t") \
4487 __ASM_CFI(".cfi_same_value %ebp\n\t") \
4490 CREATE_FPU_FUNC1(_CIacos
, acos
)
4491 CREATE_FPU_FUNC1(_CIasin
, asin
)
4492 CREATE_FPU_FUNC1(_CIatan
, atan
)
4493 CREATE_FPU_FUNC2(_CIatan2
, atan2
)
4494 CREATE_FPU_FUNC1(_CIcos
, cos
)
4495 CREATE_FPU_FUNC1(_CIcosh
, cosh
)
4496 CREATE_FPU_FUNC1(_CIexp
, exp
)
4497 CREATE_FPU_FUNC2(_CIfmod
, fmod
)
4498 CREATE_FPU_FUNC1(_CIlog
, log
)
4499 CREATE_FPU_FUNC1(_CIlog10
, log10
)
4500 CREATE_FPU_FUNC2(_CIpow
, pow
)
4501 CREATE_FPU_FUNC1(_CIsin
, sin
)
4502 CREATE_FPU_FUNC1(_CIsinh
, sinh
)
4503 CREATE_FPU_FUNC1(_CIsqrt
, sqrt
)
4504 CREATE_FPU_FUNC1(_CItan
, tan
)
4505 CREATE_FPU_FUNC1(_CItanh
, tanh
)
4507 __ASM_GLOBAL_FUNC(_ftol
,
4509 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
4510 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
4511 "movl %esp, %ebp\n\t"
4512 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
4513 "subl $12, %esp\n\t" /* sizeof(LONGLONG) + 2*sizeof(WORD) */
4515 "mov (%esp), %ax\n\t"
4516 "or $0xc00, %ax\n\t"
4517 "mov %ax, 2(%esp)\n\t"
4519 "fistpq 4(%esp)\n\t"
4521 "movl 4(%esp), %eax\n\t"
4522 "movl 8(%esp), %edx\n\t"
4524 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
4525 __ASM_CFI(".cfi_same_value %ebp\n\t")
4528 #endif /* (defined(__GNUC__) || defined(__clang__)) && defined(__i386__) */
4530 /*********************************************************************
4531 * _fpclass (MSVCRT.@)
4533 int CDECL
_fpclass(double num
)
4535 union { double f
; UINT64 i
; } u
= { num
};
4536 int e
= u
.i
>> 52 & 0x7ff;
4542 if (u
.i
<< 1) return s
? _FPCLASS_ND
: _FPCLASS_PD
;
4543 return s
? _FPCLASS_NZ
: _FPCLASS_PZ
;
4545 if (u
.i
<< 12) return ((u
.i
>> 51) & 1) ? _FPCLASS_QNAN
: _FPCLASS_SNAN
;
4546 return s
? _FPCLASS_NINF
: _FPCLASS_PINF
;
4548 return s
? _FPCLASS_NN
: _FPCLASS_PN
;
4552 /*********************************************************************
4555 unsigned int CDECL
MSVCRT__rotl(unsigned int num
, int shift
)
4558 return (num
<< shift
) | (num
>> (32-shift
));
4561 /*********************************************************************
4564 __msvcrt_ulong CDECL
MSVCRT__lrotl(__msvcrt_ulong num
, int shift
)
4567 return (num
<< shift
) | (num
>> (32-shift
));
4570 /*********************************************************************
4573 __msvcrt_ulong CDECL
MSVCRT__lrotr(__msvcrt_ulong num
, int shift
)
4576 return (num
>> shift
) | (num
<< (32-shift
));
4579 /*********************************************************************
4582 unsigned int CDECL
MSVCRT__rotr(unsigned int num
, int shift
)
4585 return (num
>> shift
) | (num
<< (32-shift
));
4588 /*********************************************************************
4589 * _rotl64 (MSVCRT.@)
4591 unsigned __int64 CDECL
MSVCRT__rotl64(unsigned __int64 num
, int shift
)
4594 return (num
<< shift
) | (num
>> (64-shift
));
4597 /*********************************************************************
4598 * _rotr64 (MSVCRT.@)
4600 unsigned __int64 CDECL
MSVCRT__rotr64(unsigned __int64 num
, int shift
)
4603 return (num
>> shift
) | (num
<< (64-shift
));
4606 /*********************************************************************
4609 int CDECL
abs( int n
)
4611 return n
>= 0 ? n
: -n
;
4614 /*********************************************************************
4617 __msvcrt_long CDECL
labs( __msvcrt_long n
)
4619 return n
>= 0 ? n
: -n
;
4623 /*********************************************************************
4624 * llabs (MSVCR100.@)
4626 __int64 CDECL
llabs( __int64 n
)
4628 return n
>= 0 ? n
: -n
;
4633 /*********************************************************************
4634 * imaxabs (MSVCR120.@)
4636 intmax_t CDECL
imaxabs( intmax_t n
)
4638 return n
>= 0 ? n
: -n
;
4642 /*********************************************************************
4645 __int64 CDECL
_abs64( __int64 n
)
4647 return n
>= 0 ? n
: -n
;
4650 /* Copied from musl: src/math/ilogb.c */
4651 static int __ilogb(double x
)
4653 union { double f
; UINT64 i
; } u
= { x
};
4654 int e
= u
.i
>> 52 & 0x7ff;
4659 if (u
.i
== 0) return FP_ILOGB0
;
4661 for (e
= -0x3ff; u
.i
>> 63 == 0; e
--, u
.i
<<= 1);
4664 if (e
== 0x7ff) return u
.i
<< 12 ? FP_ILOGBNAN
: INT_MAX
;
4668 /*********************************************************************
4671 * Copied from musl: src/math/logb.c
4673 double CDECL
_logb(double x
)
4678 return math_error(_SING
, "_logb", x
, 0, -1 / (x
* x
));
4682 static void sq(double *hi
, double *lo
, double x
)
4686 xc
= x
* (0x1p
27 + 1);
4690 *lo
= xh
* xh
- *hi
+ 2 * xh
* xl
+ xl
* xl
;
4693 /*********************************************************************
4696 * Copied from musl: src/math/hypot.c
4698 double CDECL
_hypot(double x
, double y
)
4700 UINT64 ux
= *(UINT64
*)&x
, uy
= *(UINT64
*)&y
, ut
;
4701 double hx
, lx
, hy
, ly
, z
;
4704 /* arrange |x| >= |y| */
4718 /* note: hypot(inf,nan) == inf */
4721 if (ex
== 0x7ff || uy
== 0)
4723 /* note: hypot(x,y) ~= x + y*y/x/2 with inexact for small y/x */
4724 /* 64 difference is enough for ld80 double_t */
4728 /* precise sqrt argument in nearest rounding mode without overflow */
4729 /* xh*xh must not overflow and xl*xl must not underflow in sq */
4731 if (ex
> 0x3ff + 510) {
4735 } else if (ey
< 0x3ff - 450) {
4742 return z
* sqrt(ly
+ lx
+ hy
+ hx
);
4745 /*********************************************************************
4746 * _hypotf (MSVCRT.@)
4748 * Copied from musl: src/math/hypotf.c
4750 float CDECL
_hypotf(float x
, float y
)
4752 UINT32 ux
= *(UINT32
*)&x
, uy
= *(UINT32
*)&y
, ut
;
4765 if (uy
== 0xff << 23)
4767 if (ux
>= 0xff << 23 || uy
== 0 || ux
- uy
>= 25 << 23)
4771 if (ux
>= (0x7f + 60) << 23) {
4775 } else if (uy
< (0x7f - 60) << 23) {
4780 return z
* sqrtf((double)x
* x
+ (double)y
* y
);
4783 /*********************************************************************
4786 * Based on musl: src/math/ceilf.c
4788 double CDECL
ceil( double x
)
4790 union {double f
; UINT64 i
;} u
= {x
};
4791 int e
= (u
.i
>> 52 & 0x7ff) - 0x3ff;
4797 m
= 0x000fffffffffffffULL
>> e
;
4812 /*********************************************************************
4815 * Based on musl: src/math/floorf.c
4817 double CDECL
floor( double x
)
4819 union {double f
; UINT64 i
;} u
= {x
};
4820 int e
= (int)(u
.i
>> 52 & 0x7ff) - 0x3ff;
4826 m
= 0x000fffffffffffffULL
>> e
;
4841 /*********************************************************************
4844 * Copied from musl: src/math/fma.c
4853 static struct fma_num
normalize(double x
)
4855 UINT64 ix
= *(UINT64
*)&x
;
4857 int sign
= e
& 0x800;
4864 e
= ix
>> 52 & 0x7ff;
4865 e
= e
? e
- 63 : 0x800;
4867 ix
&= (1ull << 52) - 1;
4870 e
-= 0x3ff + 52 + 1;
4878 static void mul(UINT64
*hi
, UINT64
*lo
, UINT64 x
, UINT64 y
)
4881 UINT64 xlo
= (UINT32
)x
, xhi
= x
>> 32;
4882 UINT64 ylo
= (UINT32
)y
, yhi
= y
>> 32;
4885 t2
= xlo
* yhi
+ xhi
* ylo
;
4887 *lo
= t1
+ (t2
<< 32);
4888 *hi
= t3
+ (t2
>> 32) + (t1
> *lo
);
4891 double CDECL
fma( double x
, double y
, double z
)
4893 int e
, d
, sign
, samesign
, nonzero
;
4894 UINT64 rhi
, rlo
, zhi
, zlo
;
4895 struct fma_num nx
, ny
, nz
;
4899 /* normalize so top 10bits and last bit are 0 */
4904 if (nx
.e
>= 0x7ff - 0x3ff - 52 - 1 || ny
.e
>= 0x7ff - 0x3ff - 52 - 1) {
4906 if (!isnan(x
) && !isnan(y
) && !isnan(z
) && isnan(r
)) *_errno() = EDOM
;
4909 if (nz
.e
>= 0x7ff - 0x3ff - 52 - 1) {
4910 if (nz
.e
> 0x7ff - 0x3ff - 52 - 1) {/* z==0 */
4912 if (!isnan(x
) && !isnan(y
) && isnan(r
)) *_errno() = EDOM
;
4919 mul(&rhi
, &rlo
, nx
.m
, ny
.m
);
4920 /* either top 20 or 21 bits of rhi and last 2 bits of rlo are 0 */
4922 /* align exponents */
4925 /* shift bits z<<=kz, r>>=kr, so kz+kr == d, set e = e+kr (== ez-kz) */
4929 zhi
= nz
.m
>> (64 - d
);
4936 rlo
= rhi
<< (64 - d
) | rlo
>> d
| !!(rlo
<< (64 - d
));
4948 } else if (d
< 64) {
4949 zlo
= nz
.m
>> d
| !!(nz
.m
<< (64 - d
));
4956 sign
= nx
.sign
^ ny
.sign
;
4957 samesign
= !(sign
^ nz
.sign
);
4962 rhi
+= zhi
+ (rlo
< zlo
);
4967 rhi
= rhi
- zhi
- (t
< rlo
);
4976 /* set rhi to top 63bit of the result (last bit is sticky) */
4980 BitScanReverse((DWORD
*)&d
, rhi
>> 32);
4983 BitScanReverse((DWORD
*)&d
, rhi
);
4987 rhi
= rhi
<< d
| rlo
>> (64 - d
) | !!(rlo
<< d
);
4990 BitScanReverse((DWORD
*)&d
, rlo
>> 32);
4993 BitScanReverse((DWORD
*)&d
, rlo
);
4997 rhi
= rlo
>> 1 | (rlo
& 1);
5006 /* convert to double */
5007 i
= rhi
; /* i is in [1<<62,(1<<63)-1] */
5010 r
= i
; /* |r| is in [0x1p62,0x1p63] */
5012 if (e
< -1022 - 62) {
5013 /* result is subnormal before rounding */
5014 if (e
== -1022 - 63) {
5019 /* min normal after rounding, underflow depends
5020 on arch behaviour which can be imitated by
5021 a double to float conversion */
5022 float fltmin
= 0x0.ffffff8p
-63 * FLT_MIN
* r
;
5023 return DBL_MIN
/ FLT_MIN
* fltmin
;
5025 /* one bit is lost when scaled, add another top bit to
5026 only round once at conversion if it is inexact */
5030 i
= rhi
>> 1 | (rhi
& 1) | 1ull << 62;
5034 r
= 2 * r
- c
; /* remove top bit */
5036 /* raise underflow portably, such that it
5037 cannot be optimized away */
5038 tiny
= DBL_MIN
/ FLT_MIN
* r
;
5039 r
+= (double)(tiny
* tiny
) * (r
- r
);
5042 /* only round once when scaled */
5044 i
= (rhi
>> d
| !!(rhi
<< (64 - d
))) << d
;
5050 return __scalbn(r
, e
);
5053 /*********************************************************************
5056 * Copied from musl: src/math/fmaf.c
5058 float CDECL
fmaf( float x
, float y
, float z
)
5060 union { double f
; UINT64 i
; } u
;
5066 e
= u
.i
>>52 & 0x7ff;
5067 /* Common case: The double precision result is fine. */
5068 if ((u
.i
& 0x1fffffff) != 0x10000000 || /* not a halfway case */
5069 e
== 0x7ff || /* NaN */
5070 (u
.f
- xy
== z
&& u
.f
- z
== xy
) || /* exact */
5071 (_controlfp(0, 0) & _MCW_RC
) != _RC_NEAR
) /* not round-to-nearest */
5073 if (!isnan(x
) && !isnan(y
) && !isnan(z
) && isnan(u
.f
)) *_errno() = EDOM
;
5075 /* underflow may not be raised correctly, example:
5076 fmaf(0x1p-120f, 0x1p-120f, 0x1p-149f) */
5077 if (e
< 0x3ff-126 && e
>= 0x3ff-149 && _statusfp() & _SW_INEXACT
)
5078 fp_barrierf((float)u
.f
* (float)u
.f
);
5083 * If result is inexact, and exactly halfway between two float values,
5084 * we need to adjust the low-order bit in the direction of the error.
5087 if (neg
== (z
> xy
))
5091 if (neg
== (err
< 0))
5098 /*********************************************************************
5101 * Copied from musl: src/math/fabsf.c
5103 double CDECL
fabs( double x
)
5105 union { double f
; UINT64 i
; } u
= { x
};
5110 /*********************************************************************
5113 * Copied from musl: src/math/frexp.c
5115 double CDECL
frexp( double x
, int *e
)
5117 UINT64 ux
= *(UINT64
*)&x
;
5118 int ee
= ux
>> 52 & 0x7ff;
5122 x
= frexp(x
* 0x1p
64, e
);
5126 } else if (ee
== 0x7ff) {
5131 ux
&= 0x800fffffffffffffull
;
5132 ux
|= 0x3fe0000000000000ull
;
5133 return *(double*)&ux
;
5136 /*********************************************************************
5139 * Copied from musl: src/math/modf.c
5141 double CDECL
modf( double x
, double *iptr
)
5143 union {double f
; UINT64 i
;} u
= {x
};
5145 int e
= (u
.i
>> 52 & 0x7ff) - 0x3ff;
5147 /* no fractional part */
5150 if (e
== 0x400 && u
.i
<< 12 != 0) /* nan */
5156 /* no integral part*/
5163 mask
= -1ULL >> 12 >> e
;
5164 if ((u
.i
& mask
) == 0) {
5174 #if defined(__i386__) || defined(__x86_64__)
5175 static void _setfp_sse( unsigned int *cw
, unsigned int cw_mask
,
5176 unsigned int *sw
, unsigned int sw_mask
)
5178 #if defined(__GNUC__) || defined(__clang__)
5179 unsigned long old_fpword
, fpword
;
5182 __asm__
__volatile__( "stmxcsr %0" : "=m" (fpword
) );
5183 old_fpword
= fpword
;
5185 cw_mask
&= _MCW_EM
| _MCW_RC
| _MCW_DN
;
5191 if (fpword
& 0x1) flags
|= _SW_INVALID
;
5192 if (fpword
& 0x2) flags
|= _SW_DENORMAL
;
5193 if (fpword
& 0x4) flags
|= _SW_ZERODIVIDE
;
5194 if (fpword
& 0x8) flags
|= _SW_OVERFLOW
;
5195 if (fpword
& 0x10) flags
|= _SW_UNDERFLOW
;
5196 if (fpword
& 0x20) flags
|= _SW_INEXACT
;
5198 *sw
= (flags
& ~sw_mask
) | (*sw
& sw_mask
);
5199 TRACE("sse2 update sw %08x to %08x\n", flags
, *sw
);
5201 if (*sw
& _SW_INVALID
) fpword
|= 0x1;
5202 if (*sw
& _SW_DENORMAL
) fpword
|= 0x2;
5203 if (*sw
& _SW_ZERODIVIDE
) fpword
|= 0x4;
5204 if (*sw
& _SW_OVERFLOW
) fpword
|= 0x8;
5205 if (*sw
& _SW_UNDERFLOW
) fpword
|= 0x10;
5206 if (*sw
& _SW_INEXACT
) fpword
|= 0x20;
5213 if (fpword
& 0x80) flags
|= _EM_INVALID
;
5214 if (fpword
& 0x100) flags
|= _EM_DENORMAL
;
5215 if (fpword
& 0x200) flags
|= _EM_ZERODIVIDE
;
5216 if (fpword
& 0x400) flags
|= _EM_OVERFLOW
;
5217 if (fpword
& 0x800) flags
|= _EM_UNDERFLOW
;
5218 if (fpword
& 0x1000) flags
|= _EM_INEXACT
;
5219 switch (fpword
& 0x6000)
5221 case 0x6000: flags
|= _RC_UP
|_RC_DOWN
; break;
5222 case 0x4000: flags
|= _RC_UP
; break;
5223 case 0x2000: flags
|= _RC_DOWN
; break;
5225 switch (fpword
& 0x8040)
5227 case 0x0040: flags
|= _DN_FLUSH_OPERANDS_SAVE_RESULTS
; break;
5228 case 0x8000: flags
|= _DN_SAVE_OPERANDS_FLUSH_RESULTS
; break;
5229 case 0x8040: flags
|= _DN_FLUSH
; break;
5232 *cw
= (flags
& ~cw_mask
) | (*cw
& cw_mask
);
5233 TRACE("sse2 update cw %08x to %08x\n", flags
, *cw
);
5235 if (*cw
& _EM_INVALID
) fpword
|= 0x80;
5236 if (*cw
& _EM_DENORMAL
) fpword
|= 0x100;
5237 if (*cw
& _EM_ZERODIVIDE
) fpword
|= 0x200;
5238 if (*cw
& _EM_OVERFLOW
) fpword
|= 0x400;
5239 if (*cw
& _EM_UNDERFLOW
) fpword
|= 0x800;
5240 if (*cw
& _EM_INEXACT
) fpword
|= 0x1000;
5241 switch (*cw
& _MCW_RC
)
5243 case _RC_UP
|_RC_DOWN
: fpword
|= 0x6000; break;
5244 case _RC_UP
: fpword
|= 0x4000; break;
5245 case _RC_DOWN
: fpword
|= 0x2000; break;
5247 switch (*cw
& _MCW_DN
)
5249 case _DN_FLUSH_OPERANDS_SAVE_RESULTS
: fpword
|= 0x0040; break;
5250 case _DN_SAVE_OPERANDS_FLUSH_RESULTS
: fpword
|= 0x8000; break;
5251 case _DN_FLUSH
: fpword
|= 0x8040; break;
5254 /* clear status word if anything changes */
5255 if (fpword
!= old_fpword
&& !sw
)
5257 TRACE("sse2 clear status word\n");
5262 if (fpword
!= old_fpword
)
5263 __asm__
__volatile__( "ldmxcsr %0" : : "m" (fpword
) );
5265 FIXME("not implemented\n");
5272 static void _setfp( unsigned int *cw
, unsigned int cw_mask
,
5273 unsigned int *sw
, unsigned int sw_mask
)
5275 #if (defined(__GNUC__) || defined(__clang__)) && defined(__i386__)
5276 unsigned long oldcw
= 0, newcw
= 0;
5277 unsigned long oldsw
= 0, newsw
= 0;
5280 cw_mask
&= _MCW_EM
| _MCW_IC
| _MCW_RC
| _MCW_PC
;
5285 __asm__
__volatile__( "fstsw %0" : "=m" (newsw
) );
5289 if (newsw
& 0x1) flags
|= _SW_INVALID
;
5290 if (newsw
& 0x2) flags
|= _SW_DENORMAL
;
5291 if (newsw
& 0x4) flags
|= _SW_ZERODIVIDE
;
5292 if (newsw
& 0x8) flags
|= _SW_OVERFLOW
;
5293 if (newsw
& 0x10) flags
|= _SW_UNDERFLOW
;
5294 if (newsw
& 0x20) flags
|= _SW_INEXACT
;
5296 *sw
= (flags
& ~sw_mask
) | (*sw
& sw_mask
);
5297 TRACE("x86 update sw %08x to %08x\n", flags
, *sw
);
5299 if (*sw
& _SW_INVALID
) newsw
|= 0x1;
5300 if (*sw
& _SW_DENORMAL
) newsw
|= 0x2;
5301 if (*sw
& _SW_ZERODIVIDE
) newsw
|= 0x4;
5302 if (*sw
& _SW_OVERFLOW
) newsw
|= 0x8;
5303 if (*sw
& _SW_UNDERFLOW
) newsw
|= 0x10;
5304 if (*sw
& _SW_INEXACT
) newsw
|= 0x20;
5310 __asm__
__volatile__( "fstcw %0" : "=m" (newcw
) );
5314 if (newcw
& 0x1) flags
|= _EM_INVALID
;
5315 if (newcw
& 0x2) flags
|= _EM_DENORMAL
;
5316 if (newcw
& 0x4) flags
|= _EM_ZERODIVIDE
;
5317 if (newcw
& 0x8) flags
|= _EM_OVERFLOW
;
5318 if (newcw
& 0x10) flags
|= _EM_UNDERFLOW
;
5319 if (newcw
& 0x20) flags
|= _EM_INEXACT
;
5320 switch (newcw
& 0xc00)
5322 case 0xc00: flags
|= _RC_UP
|_RC_DOWN
; break;
5323 case 0x800: flags
|= _RC_UP
; break;
5324 case 0x400: flags
|= _RC_DOWN
; break;
5326 switch (newcw
& 0x300)
5328 case 0x0: flags
|= _PC_24
; break;
5329 case 0x200: flags
|= _PC_53
; break;
5330 case 0x300: flags
|= _PC_64
; break;
5332 if (newcw
& 0x1000) flags
|= _IC_AFFINE
;
5334 *cw
= (flags
& ~cw_mask
) | (*cw
& cw_mask
);
5335 TRACE("x86 update cw %08x to %08x\n", flags
, *cw
);
5337 if (*cw
& _EM_INVALID
) newcw
|= 0x1;
5338 if (*cw
& _EM_DENORMAL
) newcw
|= 0x2;
5339 if (*cw
& _EM_ZERODIVIDE
) newcw
|= 0x4;
5340 if (*cw
& _EM_OVERFLOW
) newcw
|= 0x8;
5341 if (*cw
& _EM_UNDERFLOW
) newcw
|= 0x10;
5342 if (*cw
& _EM_INEXACT
) newcw
|= 0x20;
5343 switch (*cw
& _MCW_RC
)
5345 case _RC_UP
|_RC_DOWN
: newcw
|= 0xc00; break;
5346 case _RC_UP
: newcw
|= 0x800; break;
5347 case _RC_DOWN
: newcw
|= 0x400; break;
5349 switch (*cw
& _MCW_PC
)
5351 case _PC_64
: newcw
|= 0x300; break;
5352 case _PC_53
: newcw
|= 0x200; break;
5353 case _PC_24
: newcw
|= 0x0; break;
5355 if (*cw
& _IC_AFFINE
) newcw
|= 0x1000;
5358 if (oldsw
!= newsw
&& (newsw
& 0x3f))
5367 DWORD instruction_pointer
;
5377 __asm__
__volatile__( "fnstenv %0" : "=m" (fenv
) );
5378 fenv
.control_word
= newcw
;
5379 fenv
.status_word
= newsw
;
5380 __asm__
__volatile__( "fldenv %0" : : "m" (fenv
) : "st", "st(1)",
5381 "st(2)", "st(3)", "st(4)", "st(5)", "st(6)", "st(7)" );
5386 __asm__
__volatile__( "fnclex" );
5388 __asm__
__volatile__( "fldcw %0" : : "m" (newcw
) );
5389 #elif defined(__x86_64__)
5390 _setfp_sse(cw
, cw_mask
, sw
, sw_mask
);
5391 #elif defined(__aarch64__)
5392 ULONG_PTR old_fpsr
= 0, fpsr
= 0, old_fpcr
= 0, fpcr
= 0;
5395 cw_mask
&= _MCW_EM
| _MCW_RC
;
5400 __asm__
__volatile__( "mrs %0, fpsr" : "=r" (fpsr
) );
5404 if (fpsr
& 0x1) flags
|= _SW_INVALID
;
5405 if (fpsr
& 0x2) flags
|= _SW_ZERODIVIDE
;
5406 if (fpsr
& 0x4) flags
|= _SW_OVERFLOW
;
5407 if (fpsr
& 0x8) flags
|= _SW_UNDERFLOW
;
5408 if (fpsr
& 0x10) flags
|= _SW_INEXACT
;
5409 if (fpsr
& 0x80) flags
|= _SW_DENORMAL
;
5411 *sw
= (flags
& ~sw_mask
) | (*sw
& sw_mask
);
5412 TRACE("aarch64 update sw %08x to %08x\n", flags
, *sw
);
5414 if (*sw
& _SW_INVALID
) fpsr
|= 0x1;
5415 if (*sw
& _SW_ZERODIVIDE
) fpsr
|= 0x2;
5416 if (*sw
& _SW_OVERFLOW
) fpsr
|= 0x4;
5417 if (*sw
& _SW_UNDERFLOW
) fpsr
|= 0x8;
5418 if (*sw
& _SW_INEXACT
) fpsr
|= 0x10;
5419 if (*sw
& _SW_DENORMAL
) fpsr
|= 0x80;
5425 __asm__
__volatile__( "mrs %0, fpcr" : "=r" (fpcr
) );
5429 if (!(fpcr
& 0x100)) flags
|= _EM_INVALID
;
5430 if (!(fpcr
& 0x200)) flags
|= _EM_ZERODIVIDE
;
5431 if (!(fpcr
& 0x400)) flags
|= _EM_OVERFLOW
;
5432 if (!(fpcr
& 0x800)) flags
|= _EM_UNDERFLOW
;
5433 if (!(fpcr
& 0x1000)) flags
|= _EM_INEXACT
;
5434 if (!(fpcr
& 0x8000)) flags
|= _EM_DENORMAL
;
5435 switch (fpcr
& 0xc00000)
5437 case 0x400000: flags
|= _RC_UP
; break;
5438 case 0x800000: flags
|= _RC_DOWN
; break;
5439 case 0xc00000: flags
|= _RC_CHOP
; break;
5442 *cw
= (flags
& ~cw_mask
) | (*cw
& cw_mask
);
5443 TRACE("aarch64 update cw %08x to %08x\n", flags
, *cw
);
5444 fpcr
&= ~0xc09f00ul
;
5445 if (!(*cw
& _EM_INVALID
)) fpcr
|= 0x100;
5446 if (!(*cw
& _EM_ZERODIVIDE
)) fpcr
|= 0x200;
5447 if (!(*cw
& _EM_OVERFLOW
)) fpcr
|= 0x400;
5448 if (!(*cw
& _EM_UNDERFLOW
)) fpcr
|= 0x800;
5449 if (!(*cw
& _EM_INEXACT
)) fpcr
|= 0x1000;
5450 if (!(*cw
& _EM_DENORMAL
)) fpcr
|= 0x8000;
5451 switch (*cw
& _MCW_RC
)
5453 case _RC_CHOP
: fpcr
|= 0xc00000; break;
5454 case _RC_UP
: fpcr
|= 0x400000; break;
5455 case _RC_DOWN
: fpcr
|= 0x800000; break;
5459 /* mask exceptions if needed */
5460 if (old_fpcr
!= fpcr
&& ~(old_fpcr
>> 8) & fpsr
& 0x9f != fpsr
& 0x9f)
5462 ULONG_PTR mask
= fpcr
& ~0x9f00;
5463 __asm__
__volatile__( "msr fpcr, %0" :: "r" (mask
) );
5466 if (old_fpsr
!= fpsr
)
5467 __asm__
__volatile__( "msr fpsr, %0" :: "r" (fpsr
) );
5468 if (old_fpcr
!= fpcr
)
5469 __asm__
__volatile__( "msr fpcr, %0" :: "r" (fpcr
) );
5470 #elif defined(__arm__) && !defined(__SOFTFP__)
5471 DWORD old_fpscr
, fpscr
;
5474 __asm__
__volatile__( "vmrs %0, fpscr" : "=r" (fpscr
) );
5477 cw_mask
&= _MCW_EM
| _MCW_RC
;
5483 if (fpscr
& 0x1) flags
|= _SW_INVALID
;
5484 if (fpscr
& 0x2) flags
|= _SW_ZERODIVIDE
;
5485 if (fpscr
& 0x4) flags
|= _SW_OVERFLOW
;
5486 if (fpscr
& 0x8) flags
|= _SW_UNDERFLOW
;
5487 if (fpscr
& 0x10) flags
|= _SW_INEXACT
;
5488 if (fpscr
& 0x80) flags
|= _SW_DENORMAL
;
5490 *sw
= (flags
& ~sw_mask
) | (*sw
& sw_mask
);
5491 TRACE("arm update sw %08x to %08x\n", flags
, *sw
);
5493 if (*sw
& _SW_INVALID
) fpscr
|= 0x1;
5494 if (*sw
& _SW_ZERODIVIDE
) fpscr
|= 0x2;
5495 if (*sw
& _SW_OVERFLOW
) fpscr
|= 0x4;
5496 if (*sw
& _SW_UNDERFLOW
) fpscr
|= 0x8;
5497 if (*sw
& _SW_INEXACT
) fpscr
|= 0x10;
5498 if (*sw
& _SW_DENORMAL
) fpscr
|= 0x80;
5505 if (!(fpscr
& 0x100)) flags
|= _EM_INVALID
;
5506 if (!(fpscr
& 0x200)) flags
|= _EM_ZERODIVIDE
;
5507 if (!(fpscr
& 0x400)) flags
|= _EM_OVERFLOW
;
5508 if (!(fpscr
& 0x800)) flags
|= _EM_UNDERFLOW
;
5509 if (!(fpscr
& 0x1000)) flags
|= _EM_INEXACT
;
5510 if (!(fpscr
& 0x8000)) flags
|= _EM_DENORMAL
;
5511 switch (fpscr
& 0xc00000)
5513 case 0x400000: flags
|= _RC_UP
; break;
5514 case 0x800000: flags
|= _RC_DOWN
; break;
5515 case 0xc00000: flags
|= _RC_CHOP
; break;
5518 *cw
= (flags
& ~cw_mask
) | (*cw
& cw_mask
);
5519 TRACE("arm update cw %08x to %08x\n", flags
, *cw
);
5520 fpscr
&= ~0xc09f00ul
;
5521 if (!(*cw
& _EM_INVALID
)) fpscr
|= 0x100;
5522 if (!(*cw
& _EM_ZERODIVIDE
)) fpscr
|= 0x200;
5523 if (!(*cw
& _EM_OVERFLOW
)) fpscr
|= 0x400;
5524 if (!(*cw
& _EM_UNDERFLOW
)) fpscr
|= 0x800;
5525 if (!(*cw
& _EM_INEXACT
)) fpscr
|= 0x1000;
5526 if (!(*cw
& _EM_DENORMAL
)) fpscr
|= 0x8000;
5527 switch (*cw
& _MCW_RC
)
5529 case _RC_CHOP
: fpscr
|= 0xc00000; break;
5530 case _RC_UP
: fpscr
|= 0x400000; break;
5531 case _RC_DOWN
: fpscr
|= 0x800000; break;
5535 if (old_fpscr
!= fpscr
)
5536 __asm__
__volatile__( "vmsr fpscr, %0" :: "r" (fpscr
) );
5538 FIXME("not implemented\n");
5544 /**********************************************************************
5545 * _statusfp2 (MSVCR80.@)
5547 #if defined(__i386__)
5548 void CDECL
_statusfp2( unsigned int *x86_sw
, unsigned int *sse2_sw
)
5551 _setfp(NULL
, 0, x86_sw
, 0);
5552 if (!sse2_sw
) return;
5554 _setfp_sse(NULL
, 0, sse2_sw
, 0);
5559 /**********************************************************************
5560 * _statusfp (MSVCRT.@)
5562 unsigned int CDECL
_statusfp(void)
5564 unsigned int flags
= 0;
5565 #if defined(__i386__)
5566 unsigned int x86_sw
, sse2_sw
;
5568 _statusfp2( &x86_sw
, &sse2_sw
);
5569 /* FIXME: there's no definition for ambiguous status, just return all status bits for now */
5570 flags
= x86_sw
| sse2_sw
;
5572 _setfp(NULL
, 0, &flags
, 0);
5577 /*********************************************************************
5578 * _clearfp (MSVCRT.@)
5580 unsigned int CDECL
_clearfp(void)
5582 unsigned int flags
= 0;
5584 _setfp(NULL
, 0, &flags
, _MCW_EM
);
5587 unsigned int sse_sw
= 0;
5589 _setfp_sse(NULL
, 0, &sse_sw
, _MCW_EM
);
5593 _setfp(NULL
, 0, &flags
, _MCW_EM
);
5598 /*********************************************************************
5599 * __fpecode (MSVCRT.@)
5601 int * CDECL
__fpecode(void)
5603 return &msvcrt_get_thread_data()->fpecode
;
5606 /*********************************************************************
5609 double CDECL
ldexp(double num
, int exp
)
5611 double z
= __scalbn(num
, exp
);
5613 if (isfinite(num
) && !isfinite(z
))
5614 return math_error(_OVERFLOW
, "ldexp", num
, exp
, z
);
5615 if (num
&& isfinite(num
) && !z
)
5616 return math_error(_UNDERFLOW
, "ldexp", num
, exp
, z
);
5620 /*********************************************************************
5623 double CDECL
_cabs(struct _complex num
)
5625 return sqrt(num
.x
* num
.x
+ num
.y
* num
.y
);
5628 /*********************************************************************
5629 * _chgsign (MSVCRT.@)
5631 double CDECL
_chgsign(double num
)
5633 union { double f
; UINT64 i
; } u
= { num
};
5638 /*********************************************************************
5639 * __control87_2 (MSVCR80.@)
5641 * Not exported by native msvcrt, added in msvcr80.
5644 int CDECL
__control87_2( unsigned int newval
, unsigned int mask
,
5645 unsigned int *x86_cw
, unsigned int *sse2_cw
)
5650 _setfp(x86_cw
, mask
, NULL
, 0);
5653 if (!sse2_cw
) return 1;
5658 _setfp_sse(sse2_cw
, mask
, NULL
, 0);
5666 /*********************************************************************
5667 * _control87 (MSVCRT.@)
5669 unsigned int CDECL
_control87(unsigned int newval
, unsigned int mask
)
5671 unsigned int flags
= 0;
5673 unsigned int sse2_cw
;
5675 __control87_2( newval
, mask
, &flags
, &sse2_cw
);
5679 if ((flags
^ sse2_cw
) & (_MCW_EM
| _MCW_RC
)) flags
|= _EM_AMBIGUOUS
;
5684 _setfp(&flags
, mask
, NULL
, 0);
5689 /*********************************************************************
5690 * _controlfp (MSVCRT.@)
5692 unsigned int CDECL
_controlfp(unsigned int newval
, unsigned int mask
)
5694 return _control87( newval
, mask
& ~_EM_DENORMAL
);
5697 /*********************************************************************
5698 * _set_controlfp (MSVCRT.@)
5700 void CDECL
_set_controlfp( unsigned int newval
, unsigned int mask
)
5702 _controlfp( newval
, mask
);
5705 /*********************************************************************
5706 * _controlfp_s (MSVCRT.@)
5708 int CDECL
_controlfp_s(unsigned int *cur
, unsigned int newval
, unsigned int mask
)
5710 static const unsigned int all_flags
= (_MCW_EM
| _MCW_IC
| _MCW_RC
|
5714 if (!MSVCRT_CHECK_PMT( !(newval
& mask
& ~all_flags
) ))
5716 if (cur
) *cur
= _controlfp( 0, 0 ); /* retrieve it anyway */
5719 val
= _controlfp( newval
, mask
);
5720 if (cur
) *cur
= val
;
5724 #if _MSVCR_VER >= 140 && (defined(__i386__) || defined(__x86_64__))
5727 FENV_X_INVALID
= 0x00100010,
5728 FENV_X_DENORMAL
= 0x00200020,
5729 FENV_X_ZERODIVIDE
= 0x00080008,
5730 FENV_X_OVERFLOW
= 0x00040004,
5731 FENV_X_UNDERFLOW
= 0x00020002,
5732 FENV_X_INEXACT
= 0x00010001,
5733 FENV_X_AFFINE
= 0x00004000,
5734 FENV_X_UP
= 0x00800200,
5735 FENV_X_DOWN
= 0x00400100,
5736 FENV_X_24
= 0x00002000,
5737 FENV_X_53
= 0x00001000,
5738 FENV_Y_INVALID
= 0x10000010,
5739 FENV_Y_DENORMAL
= 0x20000020,
5740 FENV_Y_ZERODIVIDE
= 0x08000008,
5741 FENV_Y_OVERFLOW
= 0x04000004,
5742 FENV_Y_UNDERFLOW
= 0x02000002,
5743 FENV_Y_INEXACT
= 0x01000001,
5744 FENV_Y_UP
= 0x80000200,
5745 FENV_Y_DOWN
= 0x40000100,
5746 FENV_Y_FLUSH
= 0x00000400,
5747 FENV_Y_FLUSH_SAVE
= 0x00000800
5750 /* encodes x87/sse control/status word in ulong */
5751 static __msvcrt_ulong
fenv_encode(unsigned int x
, unsigned int y
)
5753 __msvcrt_ulong ret
= 0;
5756 if (x
& _EM_INVALID
) ret
|= FENV_X_INVALID
;
5757 if (x
& _EM_DENORMAL
) ret
|= FENV_X_DENORMAL
;
5758 if (x
& _EM_ZERODIVIDE
) ret
|= FENV_X_ZERODIVIDE
;
5759 if (x
& _EM_OVERFLOW
) ret
|= FENV_X_OVERFLOW
;
5760 if (x
& _EM_UNDERFLOW
) ret
|= FENV_X_UNDERFLOW
;
5761 if (x
& _EM_INEXACT
) ret
|= FENV_X_INEXACT
;
5762 if (x
& _IC_AFFINE
) ret
|= FENV_X_AFFINE
;
5763 if (x
& _RC_UP
) ret
|= FENV_X_UP
;
5764 if (x
& _RC_DOWN
) ret
|= FENV_X_DOWN
;
5765 if (x
& _PC_24
) ret
|= FENV_X_24
;
5766 if (x
& _PC_53
) ret
|= FENV_X_53
;
5768 x
&= ~(_MCW_EM
| _MCW_IC
| _MCW_RC
| _MCW_PC
);
5770 if (y
& _EM_INVALID
) ret
|= FENV_Y_INVALID
;
5771 if (y
& _EM_DENORMAL
) ret
|= FENV_Y_DENORMAL
;
5772 if (y
& _EM_ZERODIVIDE
) ret
|= FENV_Y_ZERODIVIDE
;
5773 if (y
& _EM_OVERFLOW
) ret
|= FENV_Y_OVERFLOW
;
5774 if (y
& _EM_UNDERFLOW
) ret
|= FENV_Y_UNDERFLOW
;
5775 if (y
& _EM_INEXACT
) ret
|= FENV_Y_INEXACT
;
5776 if (y
& _RC_UP
) ret
|= FENV_Y_UP
;
5777 if (y
& _RC_DOWN
) ret
|= FENV_Y_DOWN
;
5778 if (y
& _DN_FLUSH
) ret
|= FENV_Y_FLUSH
;
5779 if (y
& _DN_FLUSH_OPERANDS_SAVE_RESULTS
) ret
|= FENV_Y_FLUSH_SAVE
;
5780 y
&= ~(_MCW_EM
| _MCW_IC
| _MCW_RC
| _MCW_DN
);
5782 if(x
|| y
) FIXME("unsupported flags: %x, %x\n", x
, y
);
5786 /* decodes x87/sse control/status word, returns FALSE on error */
5787 static BOOL
fenv_decode(__msvcrt_ulong enc
, unsigned int *x
, unsigned int *y
)
5790 if ((enc
& FENV_X_INVALID
) == FENV_X_INVALID
) *x
|= _EM_INVALID
;
5791 if ((enc
& FENV_X_DENORMAL
) == FENV_X_DENORMAL
) *x
|= _EM_DENORMAL
;
5792 if ((enc
& FENV_X_ZERODIVIDE
) == FENV_X_ZERODIVIDE
) *x
|= _EM_ZERODIVIDE
;
5793 if ((enc
& FENV_X_OVERFLOW
) == FENV_X_OVERFLOW
) *x
|= _EM_OVERFLOW
;
5794 if ((enc
& FENV_X_UNDERFLOW
) == FENV_X_UNDERFLOW
) *x
|= _EM_UNDERFLOW
;
5795 if ((enc
& FENV_X_INEXACT
) == FENV_X_INEXACT
) *x
|= _EM_INEXACT
;
5796 if ((enc
& FENV_X_AFFINE
) == FENV_X_AFFINE
) *x
|= _IC_AFFINE
;
5797 if ((enc
& FENV_X_UP
) == FENV_X_UP
) *x
|= _RC_UP
;
5798 if ((enc
& FENV_X_DOWN
) == FENV_X_DOWN
) *x
|= _RC_DOWN
;
5799 if ((enc
& FENV_X_24
) == FENV_X_24
) *x
|= _PC_24
;
5800 if ((enc
& FENV_X_53
) == FENV_X_53
) *x
|= _PC_53
;
5802 if ((enc
& FENV_Y_INVALID
) == FENV_Y_INVALID
) *y
|= _EM_INVALID
;
5803 if ((enc
& FENV_Y_DENORMAL
) == FENV_Y_DENORMAL
) *y
|= _EM_DENORMAL
;
5804 if ((enc
& FENV_Y_ZERODIVIDE
) == FENV_Y_ZERODIVIDE
) *y
|= _EM_ZERODIVIDE
;
5805 if ((enc
& FENV_Y_OVERFLOW
) == FENV_Y_OVERFLOW
) *y
|= _EM_OVERFLOW
;
5806 if ((enc
& FENV_Y_UNDERFLOW
) == FENV_Y_UNDERFLOW
) *y
|= _EM_UNDERFLOW
;
5807 if ((enc
& FENV_Y_INEXACT
) == FENV_Y_INEXACT
) *y
|= _EM_INEXACT
;
5808 if ((enc
& FENV_Y_UP
) == FENV_Y_UP
) *y
|= _RC_UP
;
5809 if ((enc
& FENV_Y_DOWN
) == FENV_Y_DOWN
) *y
|= _RC_DOWN
;
5810 if ((enc
& FENV_Y_FLUSH
) == FENV_Y_FLUSH
) *y
|= _DN_FLUSH
;
5811 if ((enc
& FENV_Y_FLUSH_SAVE
) == FENV_Y_FLUSH_SAVE
) *y
|= _DN_FLUSH_OPERANDS_SAVE_RESULTS
;
5813 if (fenv_encode(*x
, *y
) != enc
)
5815 WARN("can't decode: %lx\n", enc
);
5820 #elif _MSVCR_VER >= 120
5821 static __msvcrt_ulong
fenv_encode(unsigned int x
, unsigned int y
)
5823 if (y
& _EM_DENORMAL
)
5824 y
= (y
& ~_EM_DENORMAL
) | 0x20;
5829 static BOOL
fenv_decode(__msvcrt_ulong enc
, unsigned int *x
, unsigned int *y
)
5832 enc
= (enc
& ~0x20) | _EM_DENORMAL
;
5840 /*********************************************************************
5841 * fegetenv (MSVCR120.@)
5843 int CDECL
fegetenv(fenv_t
*env
)
5845 #if _MSVCR_VER>=140 && defined(__i386__)
5846 unsigned int x87
, sse
;
5847 __control87_2(0, 0, &x87
, &sse
);
5848 env
->_Fe_ctl
= fenv_encode(x87
, sse
);
5849 _statusfp2(&x87
, &sse
);
5850 env
->_Fe_stat
= fenv_encode(x87
, sse
);
5851 #elif _MSVCR_VER>=140
5852 env
->_Fe_ctl
= fenv_encode(0, _control87(0, 0));
5853 env
->_Fe_stat
= fenv_encode(0, _statusfp());
5855 env
->_Fe_ctl
= _controlfp(0, 0) & (_EM_INEXACT
| _EM_UNDERFLOW
|
5856 _EM_OVERFLOW
| _EM_ZERODIVIDE
| _EM_INVALID
| _MCW_RC
);
5857 env
->_Fe_stat
= _statusfp();
5862 /*********************************************************************
5863 * feupdateenv (MSVCR120.@)
5865 int CDECL
feupdateenv(const fenv_t
*env
)
5869 set
._Fe_ctl
= env
->_Fe_ctl
;
5870 set
._Fe_stat
|= env
->_Fe_stat
;
5871 return fesetenv(&set
);
5874 /*********************************************************************
5875 * fetestexcept (MSVCR120.@)
5877 int CDECL
fetestexcept(int flags
)
5879 return _statusfp() & flags
;
5882 /*********************************************************************
5883 * fesetexceptflag (MSVCR120.@)
5885 int CDECL
fesetexceptflag(const fexcept_t
*status
, int excepts
)
5889 excepts
&= FE_ALL_EXCEPT
;
5894 env
._Fe_stat
&= ~fenv_encode(excepts
, excepts
);
5895 env
._Fe_stat
|= *status
& fenv_encode(excepts
, excepts
);
5896 return fesetenv(&env
);
5899 /*********************************************************************
5900 * feraiseexcept (MSVCR120.@)
5902 int CDECL
feraiseexcept(int flags
)
5906 flags
&= FE_ALL_EXCEPT
;
5908 env
._Fe_stat
|= fenv_encode(flags
, flags
);
5909 return fesetenv(&env
);
5912 /*********************************************************************
5913 * feclearexcept (MSVCR120.@)
5915 int CDECL
feclearexcept(int flags
)
5920 flags
&= FE_ALL_EXCEPT
;
5921 env
._Fe_stat
&= ~fenv_encode(flags
, flags
);
5922 return fesetenv(&env
);
5925 /*********************************************************************
5926 * fegetexceptflag (MSVCR120.@)
5928 int CDECL
fegetexceptflag(fexcept_t
*status
, int excepts
)
5930 #if _MSVCR_VER>=140 && defined(__i386__)
5931 unsigned int x87
, sse
;
5932 _statusfp2(&x87
, &sse
);
5933 *status
= fenv_encode(x87
& excepts
, sse
& excepts
);
5935 *status
= fenv_encode(0, _statusfp() & excepts
);
5942 /*********************************************************************
5943 * __fpe_flt_rounds (UCRTBASE.@)
5945 int CDECL
__fpe_flt_rounds(void)
5947 unsigned int fpc
= _controlfp(0, 0) & _RC_CHOP
;
5952 case _RC_CHOP
: return 0;
5953 case _RC_NEAR
: return 1;
5954 case _RC_UP
: return 2;
5962 /*********************************************************************
5963 * fegetround (MSVCR120.@)
5965 int CDECL
fegetround(void)
5967 return _controlfp(0, 0) & _MCW_RC
;
5970 /*********************************************************************
5971 * fesetround (MSVCR120.@)
5973 int CDECL
fesetround(int round_mode
)
5975 if (round_mode
& (~_MCW_RC
))
5977 _controlfp(round_mode
, _MCW_RC
);
5981 #endif /* _MSVCR_VER>=120 */
5983 /*********************************************************************
5984 * _copysign (MSVCRT.@)
5986 * Copied from musl: src/math/copysign.c
5988 double CDECL
_copysign( double x
, double y
)
5990 union { double f
; UINT64 i
; } ux
= { x
}, uy
= { y
};
5992 ux
.i
|= uy
.i
& 1ull << 63;
5996 /*********************************************************************
5997 * _finite (MSVCRT.@)
5999 int CDECL
_finite(double num
)
6001 union { double f
; UINT64 i
; } u
= { num
};
6002 return (u
.i
& ~0ull >> 1) < 0x7ffull
<< 52;
6005 /*********************************************************************
6006 * _fpreset (MSVCRT.@)
6008 void CDECL
_fpreset(void)
6010 #if (defined(__GNUC__) || defined(__clang__)) && defined(__i386__)
6011 const unsigned int x86_cw
= 0x27f;
6012 __asm__
__volatile__( "fninit; fldcw %0" : : "m" (x86_cw
) );
6015 unsigned int cw
= _MCW_EM
, sw
= 0;
6016 _setfp_sse(&cw
, ~0, &sw
, ~0);
6019 unsigned int cw
= _MCW_EM
, sw
= 0;
6020 _setfp(&cw
, ~0, &sw
, ~0);
6025 /*********************************************************************
6026 * fesetenv (MSVCR120.@)
6028 int CDECL
fesetenv(const fenv_t
*env
)
6030 unsigned int x87_cw
, cw
, x87_stat
, stat
;
6033 TRACE( "(%p)\n", env
);
6035 if (!env
->_Fe_ctl
&& !env
->_Fe_stat
) {
6040 if (!fenv_decode(env
->_Fe_ctl
, &x87_cw
, &cw
))
6042 if (!fenv_decode(env
->_Fe_stat
, &x87_stat
, &stat
))
6045 #if _MSVCR_VER >= 140
6048 mask
= _EM_INEXACT
| _EM_UNDERFLOW
| _EM_OVERFLOW
6049 | _EM_ZERODIVIDE
| _EM_INVALID
| _MCW_RC
;
6053 _setfp(&x87_cw
, mask
, &x87_stat
, ~0);
6055 _setfp_sse(&cw
, mask
, &stat
, ~0);
6058 _setfp(&cw
, mask
, &stat
, ~0);
6064 /*********************************************************************
6067 int CDECL
_isnan(double num
)
6069 union { double f
; UINT64 i
; } u
= { num
};
6070 return (u
.i
& ~0ull >> 1) > 0x7ffull
<< 52;
6073 static double pzero(double x
)
6075 static const double pR8
[6] = { /* for x in [inf, 8]=1/[0,0.125] */
6076 0.00000000000000000000e+00,
6077 -7.03124999999900357484e-02,
6078 -8.08167041275349795626e+00,
6079 -2.57063105679704847262e+02,
6080 -2.48521641009428822144e+03,
6081 -5.25304380490729545272e+03,
6083 1.16534364619668181717e+02,
6084 3.83374475364121826715e+03,
6085 4.05978572648472545552e+04,
6086 1.16752972564375915681e+05,
6087 4.76277284146730962675e+04,
6088 }, pR5
[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
6089 -1.14125464691894502584e-11,
6090 -7.03124940873599280078e-02,
6091 -4.15961064470587782438e+00,
6092 -6.76747652265167261021e+01,
6093 -3.31231299649172967747e+02,
6094 -3.46433388365604912451e+02,
6096 6.07539382692300335975e+01,
6097 1.05125230595704579173e+03,
6098 5.97897094333855784498e+03,
6099 9.62544514357774460223e+03,
6100 2.40605815922939109441e+03,
6101 }, pR3
[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */
6102 -2.54704601771951915620e-09,
6103 -7.03119616381481654654e-02,
6104 -2.40903221549529611423e+00,
6105 -2.19659774734883086467e+01,
6106 -5.80791704701737572236e+01,
6107 -3.14479470594888503854e+01,
6109 3.58560338055209726349e+01,
6110 3.61513983050303863820e+02,
6111 1.19360783792111533330e+03,
6112 1.12799679856907414432e+03,
6113 1.73580930813335754692e+02,
6114 }, pR2
[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
6115 -8.87534333032526411254e-08,
6116 -7.03030995483624743247e-02,
6117 -1.45073846780952986357e+00,
6118 -7.63569613823527770791e+00,
6119 -1.11931668860356747786e+01,
6120 -3.23364579351335335033e+00,
6122 2.22202997532088808441e+01,
6123 1.36206794218215208048e+02,
6124 2.70470278658083486789e+02,
6125 1.53875394208320329881e+02,
6126 1.46576176948256193810e+01,
6129 const double *p
, *q
;
6133 ix
= *(ULONGLONG
*)&x
>> 32;
6135 if (ix
>= 0x40200000) {
6138 } else if (ix
>= 0x40122E8B) {
6141 } else if (ix
>= 0x4006DB6D) {
6144 } else /*ix >= 0x40000000*/ {
6150 r
= p
[0] + z
* (p
[1] + z
* (p
[2] + z
* (p
[3] + z
* (p
[4] + z
* p
[5]))));
6151 s
= 1.0 + z
* (q
[0] + z
* (q
[1] + z
* (q
[2] + z
* (q
[3] + z
* q
[4]))));
6155 static double qzero(double x
)
6157 static const double qR8
[6] = { /* for x in [inf, 8]=1/[0,0.125] */
6158 0.00000000000000000000e+00,
6159 7.32421874999935051953e-02,
6160 1.17682064682252693899e+01,
6161 5.57673380256401856059e+02,
6162 8.85919720756468632317e+03,
6163 3.70146267776887834771e+04,
6165 1.63776026895689824414e+02,
6166 8.09834494656449805916e+03,
6167 1.42538291419120476348e+05,
6168 8.03309257119514397345e+05,
6169 8.40501579819060512818e+05,
6170 -3.43899293537866615225e+05,
6171 }, qR5
[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
6172 1.84085963594515531381e-11,
6173 7.32421766612684765896e-02,
6174 5.83563508962056953777e+00,
6175 1.35111577286449829671e+02,
6176 1.02724376596164097464e+03,
6177 1.98997785864605384631e+03,
6179 8.27766102236537761883e+01,
6180 2.07781416421392987104e+03,
6181 1.88472887785718085070e+04,
6182 5.67511122894947329769e+04,
6183 3.59767538425114471465e+04,
6184 -5.35434275601944773371e+03,
6185 }, qR3
[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */
6186 4.37741014089738620906e-09,
6187 7.32411180042911447163e-02,
6188 3.34423137516170720929e+00,
6189 4.26218440745412650017e+01,
6190 1.70808091340565596283e+02,
6191 1.66733948696651168575e+02,
6193 4.87588729724587182091e+01,
6194 7.09689221056606015736e+02,
6195 3.70414822620111362994e+03,
6196 6.46042516752568917582e+03,
6197 2.51633368920368957333e+03,
6198 -1.49247451836156386662e+02,
6199 }, qR2
[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
6200 1.50444444886983272379e-07,
6201 7.32234265963079278272e-02,
6202 1.99819174093815998816e+00,
6203 1.44956029347885735348e+01,
6204 3.16662317504781540833e+01,
6205 1.62527075710929267416e+01,
6207 3.03655848355219184498e+01,
6208 2.69348118608049844624e+02,
6209 8.44783757595320139444e+02,
6210 8.82935845112488550512e+02,
6211 2.12666388511798828631e+02,
6212 -5.31095493882666946917e+00,
6215 const double *p
, *q
;
6219 ix
= *(ULONGLONG
*)&x
>> 32;
6221 if (ix
>= 0x40200000) {
6224 } else if (ix
>= 0x40122E8B) {
6227 } else if (ix
>= 0x4006DB6D) {
6230 } else /*ix >= 0x40000000*/ {
6236 r
= p
[0] + z
* (p
[1] + z
* (p
[2] + z
* (p
[3] + z
* (p
[4] + z
* p
[5]))));
6237 s
= 1.0 + z
* (q
[0] + z
* (q
[1] + z
* (q
[2] + z
* (q
[3] + z
* (q
[4] + z
* q
[5])))));
6238 return (-0.125 + r
/ s
) / x
;
6241 /* j0 and y0 approximation for |x|>=2 */
6242 static double j0_y0_approx(unsigned int ix
, double x
, BOOL y0
)
6244 static const double invsqrtpi
= 5.64189583547756279280e-01;
6246 double s
, c
, ss
, cc
, z
;
6252 /* avoid overflow in 2*x, big ulp error when x>=0x1p1023 */
6253 if (ix
< 0x7fe00000) {
6256 if (s
* c
< 0) cc
= z
/ ss
;
6258 if (ix
< 0x48000000) {
6260 cc
= pzero(x
) * cc
- qzero(x
) * ss
;
6263 return invsqrtpi
* cc
/ sqrt(x
);
6266 /*********************************************************************
6269 * Copied from musl: src/math/j0.c
6271 double CDECL
_j0(double x
)
6273 static const double R02
= 1.56249999999999947958e-02,
6274 R03
= -1.89979294238854721751e-04,
6275 R04
= 1.82954049532700665670e-06,
6276 R05
= -4.61832688532103189199e-09,
6277 S01
= 1.56191029464890010492e-02,
6278 S02
= 1.16926784663337450260e-04,
6279 S03
= 5.13546550207318111446e-07,
6280 S04
= 1.16614003333790000205e-09;
6285 ix
= *(ULONGLONG
*)&x
>> 32;
6288 /* j0(+-inf)=0, j0(nan)=nan */
6289 if (ix
>= 0x7ff00000)
6290 return math_error(_DOMAIN
, "_j0", x
, 0, 1 / (x
* x
));
6293 if (ix
>= 0x40000000) { /* |x| >= 2 */
6294 /* large ulp error near zeros: 2.4, 5.52, 8.6537,.. */
6295 return j0_y0_approx(ix
, x
, FALSE
);
6298 if (ix
>= 0x3f200000) { /* |x| >= 2**-13 */
6299 /* up to 4ulp error close to 2 */
6301 r
= z
* (R02
+ z
* (R03
+ z
* (R04
+ z
* R05
)));
6302 s
= 1 + z
* (S01
+ z
* (S02
+ z
* (S03
+ z
* S04
)));
6303 return (1 + x
/ 2) * (1 - x
/ 2) + z
* (r
/ s
);
6307 /* prevent underflow */
6308 /* inexact should be raised when x!=0, this is not done correctly */
6309 if (ix
>= 0x38000000) /* |x| >= 2**-127 */
6314 static double pone(double x
)
6316 static const double pr8
[6] = { /* for x in [inf, 8]=1/[0,0.125] */
6317 0.00000000000000000000e+00,
6318 1.17187499999988647970e-01,
6319 1.32394806593073575129e+01,
6320 4.12051854307378562225e+02,
6321 3.87474538913960532227e+03,
6322 7.91447954031891731574e+03,
6324 1.14207370375678408436e+02,
6325 3.65093083420853463394e+03,
6326 3.69562060269033463555e+04,
6327 9.76027935934950801311e+04,
6328 3.08042720627888811578e+04,
6329 }, pr5
[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
6330 1.31990519556243522749e-11,
6331 1.17187493190614097638e-01,
6332 6.80275127868432871736e+00,
6333 1.08308182990189109773e+02,
6334 5.17636139533199752805e+02,
6335 5.28715201363337541807e+02,
6337 5.92805987221131331921e+01,
6338 9.91401418733614377743e+02,
6339 5.35326695291487976647e+03,
6340 7.84469031749551231769e+03,
6341 1.50404688810361062679e+03,
6343 3.02503916137373618024e-09,
6344 1.17186865567253592491e-01,
6345 3.93297750033315640650e+00,
6346 3.51194035591636932736e+01,
6347 9.10550110750781271918e+01,
6348 4.85590685197364919645e+01,
6350 3.47913095001251519989e+01,
6351 3.36762458747825746741e+02,
6352 1.04687139975775130551e+03,
6353 8.90811346398256432622e+02,
6354 1.03787932439639277504e+02,
6355 }, pr2
[6] = { /* for x in [2.8570,2]=1/[0.3499,0.5] */
6356 1.07710830106873743082e-07,
6357 1.17176219462683348094e-01,
6358 2.36851496667608785174e+00,
6359 1.22426109148261232917e+01,
6360 1.76939711271687727390e+01,
6361 5.07352312588818499250e+00,
6363 2.14364859363821409488e+01,
6364 1.25290227168402751090e+02,
6365 2.32276469057162813669e+02,
6366 1.17679373287147100768e+02,
6367 8.36463893371618283368e+00,
6370 const double *p
, *q
;
6374 ix
= *(ULONGLONG
*)&x
>> 32;
6376 if (ix
>= 0x40200000) {
6379 } else if (ix
>= 0x40122E8B) {
6382 } else if (ix
>= 0x4006DB6D) {
6385 } else /*ix >= 0x40000000*/ {
6390 r
= p
[0] + z
* (p
[1] + z
* (p
[2] + z
* (p
[3] + z
* (p
[4] + z
* p
[5]))));
6391 s
= 1.0 + z
* (q
[0] + z
* (q
[1] + z
* (q
[2] + z
* (q
[3] + z
* q
[4]))));
6395 static double qone(double x
)
6397 static const double qr8
[6] = { /* for x in [inf, 8]=1/[0,0.125] */
6398 0.00000000000000000000e+00,
6399 -1.02539062499992714161e-01,
6400 -1.62717534544589987888e+01,
6401 -7.59601722513950107896e+02,
6402 -1.18498066702429587167e+04,
6403 -4.84385124285750353010e+04,
6405 1.61395369700722909556e+02,
6406 7.82538599923348465381e+03,
6407 1.33875336287249578163e+05,
6408 7.19657723683240939863e+05,
6409 6.66601232617776375264e+05,
6410 -2.94490264303834643215e+05,
6411 }, qr5
[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
6412 -2.08979931141764104297e-11,
6413 -1.02539050241375426231e-01,
6414 -8.05644828123936029840e+00,
6415 -1.83669607474888380239e+02,
6416 -1.37319376065508163265e+03,
6417 -2.61244440453215656817e+03,
6419 8.12765501384335777857e+01,
6420 1.99179873460485964642e+03,
6421 1.74684851924908907677e+04,
6422 4.98514270910352279316e+04,
6423 2.79480751638918118260e+04,
6424 -4.71918354795128470869e+03,
6426 -5.07831226461766561369e-09,
6427 -1.02537829820837089745e-01,
6428 -4.61011581139473403113e+00,
6429 -5.78472216562783643212e+01,
6430 -2.28244540737631695038e+02,
6431 -2.19210128478909325622e+02,
6433 4.76651550323729509273e+01,
6434 6.73865112676699709482e+02,
6435 3.38015286679526343505e+03,
6436 5.54772909720722782367e+03,
6437 1.90311919338810798763e+03,
6438 -1.35201191444307340817e+02,
6439 }, qr2
[6] = { /* for x in [2.8570,2]=1/[0.3499,0.5] */
6440 -1.78381727510958865572e-07,
6441 -1.02517042607985553460e-01,
6442 -2.75220568278187460720e+00,
6443 -1.96636162643703720221e+01,
6444 -4.23253133372830490089e+01,
6445 -2.13719211703704061733e+01,
6447 2.95333629060523854548e+01,
6448 2.52981549982190529136e+02,
6449 7.57502834868645436472e+02,
6450 7.39393205320467245656e+02,
6451 1.55949003336666123687e+02,
6452 -4.95949898822628210127e+00,
6455 const double *p
, *q
;
6459 ix
= *(ULONGLONG
*)&x
>> 32;
6461 if (ix
>= 0x40200000) {
6464 } else if (ix
>= 0x40122E8B) {
6467 } else if (ix
>= 0x4006DB6D) {
6470 } else /*ix >= 0x40000000*/ {
6475 r
= p
[0] + z
* (p
[1] + z
* (p
[2] + z
* (p
[3] + z
* (p
[4] + z
* p
[5]))));
6476 s
= 1.0 + z
* (q
[0] + z
* (q
[1] + z
* (q
[2] + z
* (q
[3] + z
* (q
[4] + z
* q
[5])))));
6477 return (0.375 + r
/ s
) / x
;
6480 static double j1_y1_approx(unsigned int ix
, double x
, BOOL y1
, int sign
)
6482 static const double invsqrtpi
= 5.64189583547756279280e-01;
6484 double z
, s
, c
, ss
, cc
;
6490 if (ix
< 0x7fe00000) {
6493 if (s
* c
> 0) cc
= z
/ ss
;
6495 if (ix
< 0x48000000) {
6498 cc
= pone(x
) * cc
- qone(x
) * ss
;
6503 return invsqrtpi
* cc
/ sqrt(x
);
6506 /*********************************************************************
6509 * Copied from musl: src/math/j1.c
6511 double CDECL
_j1(double x
)
6513 static const double r00
= -6.25000000000000000000e-02,
6514 r01
= 1.40705666955189706048e-03,
6515 r02
= -1.59955631084035597520e-05,
6516 r03
= 4.96727999609584448412e-08,
6517 s01
= 1.91537599538363460805e-02,
6518 s02
= 1.85946785588630915560e-04,
6519 s03
= 1.17718464042623683263e-06,
6520 s04
= 5.04636257076217042715e-09,
6521 s05
= 1.23542274426137913908e-11;
6527 ix
= *(ULONGLONG
*)&x
>> 32;
6530 if (ix
>= 0x7ff00000)
6531 return math_error(isnan(x
) ? 0 : _DOMAIN
, "_j1", x
, 0, 1 / (x
* x
));
6532 if (ix
>= 0x40000000) /* |x| >= 2 */
6533 return j1_y1_approx(ix
, fabs(x
), FALSE
, sign
);
6534 if (ix
>= 0x38000000) { /* |x| >= 2**-127 */
6536 r
= z
* (r00
+ z
* (r01
+ z
* (r02
+ z
* r03
)));
6537 s
= 1 + z
* (s01
+ z
* (s02
+ z
* (s03
+ z
* (s04
+ z
* s05
))));
6540 /* avoid underflow, raise inexact if x!=0 */
6543 return (0.5 + z
) * x
;
6546 /*********************************************************************
6549 * Copied from musl: src/math/jn.c
6551 double CDECL
_jn(int n
, double x
)
6553 static const double invsqrtpi
= 5.64189583547756279280e-01;
6555 unsigned int ix
, lx
;
6559 ix
= *(ULONGLONG
*)&x
>> 32;
6560 lx
= *(ULONGLONG
*)&x
;
6564 if ((ix
| (lx
| -lx
) >> 31) > 0x7ff00000) /* nan */
6579 sign
&= n
; /* even n: 0, odd n: signbit(x) */
6581 if ((ix
| lx
) == 0 || ix
== 0x7ff00000) /* if x is 0 or inf */
6584 if (ix
>= 0x52d00000) { /* x > 2**302 */
6587 temp
= -cos(x
) + sin(x
);
6590 temp
= -cos(x
) - sin(x
);
6593 temp
= cos(x
) - sin(x
);
6596 temp
= cos(x
) + sin(x
);
6599 b
= invsqrtpi
* temp
/ sqrt(x
);
6603 for (i
= 0; i
< nm1
; ) {
6606 b
= b
* (2.0 * i
/ x
) - a
; /* avoid underflow */
6611 if (ix
< 0x3e100000) { /* x < 2**-29 */
6612 if (nm1
> 32) /* underflow */
6618 for (i
= 2; i
<= nm1
+ 1; i
++) {
6619 a
*= (double)i
; /* a = n! */
6620 b
*= temp
; /* b = (x/2)^n */
6625 double t
, q0
, q1
, w
, h
, z
, tmp
, nf
;
6635 while (q1
< 1.0e9
) {
6642 for (t
= 0.0, i
= k
; i
>= 0; i
--)
6643 t
= 1 / (2 * (i
+ nf
) / x
- t
);
6646 tmp
= nf
* log(fabs(w
));
6647 if (tmp
< 7.09782712893383973096e+02) {
6648 for (i
= nm1
; i
> 0; i
--) {
6650 b
= b
* (2.0 * i
) / x
- a
;
6654 for (i
= nm1
; i
> 0; i
--) {
6656 b
= b
* (2.0 * i
) / x
- a
;
6658 /* scale b to avoid spurious overflow */
6668 if (fabs(z
) >= fabs(w
))
6674 return sign
? -b
: b
;
6677 /*********************************************************************
6680 double CDECL
_y0(double x
)
6682 static const double tpi
= 6.36619772367581382433e-01,
6683 u00
= -7.38042951086872317523e-02,
6684 u01
= 1.76666452509181115538e-01,
6685 u02
= -1.38185671945596898896e-02,
6686 u03
= 3.47453432093683650238e-04,
6687 u04
= -3.81407053724364161125e-06,
6688 u05
= 1.95590137035022920206e-08,
6689 u06
= -3.98205194132103398453e-11,
6690 v01
= 1.27304834834123699328e-02,
6691 v02
= 7.60068627350353253702e-05,
6692 v03
= 2.59150851840457805467e-07,
6693 v04
= 4.41110311332675467403e-10;
6696 unsigned int ix
, lx
;
6698 ix
= *(ULONGLONG
*)&x
>> 32;
6699 lx
= *(ULONGLONG
*)&x
;
6701 /* y0(nan)=nan, y0(<0)=nan, y0(0)=-inf, y0(inf)=0 */
6702 if ((ix
<< 1 | lx
) == 0)
6703 return math_error(_OVERFLOW
, "_y0", x
, 0, -INFINITY
);
6707 return math_error(_DOMAIN
, "_y0", x
, 0, 0 / (x
- x
));
6708 if (ix
>= 0x7ff00000)
6711 if (ix
>= 0x40000000) { /* x >= 2 */
6712 /* large ulp errors near zeros: 3.958, 7.086,.. */
6713 return j0_y0_approx(ix
, x
, TRUE
);
6716 if (ix
>= 0x3e400000) { /* x >= 2**-27 */
6717 /* large ulp error near the first zero, x ~= 0.89 */
6719 u
= u00
+ z
* (u01
+ z
* (u02
+ z
* (u03
+ z
* (u04
+ z
* (u05
+ z
* u06
)))));
6720 v
= 1.0 + z
* (v01
+ z
* (v02
+ z
* (v03
+ z
* v04
)));
6721 return u
/ v
+ tpi
* (j0(x
) * log(x
));
6723 return u00
+ tpi
* log(x
);
6726 /*********************************************************************
6729 double CDECL
_y1(double x
)
6731 static const double tpi
= 6.36619772367581382433e-01,
6732 u00
= -1.96057090646238940668e-01,
6733 u01
= 5.04438716639811282616e-02,
6734 u02
= -1.91256895875763547298e-03,
6735 u03
= 2.35252600561610495928e-05,
6736 u04
= -9.19099158039878874504e-08,
6737 v00
= 1.99167318236649903973e-02,
6738 v01
= 2.02552581025135171496e-04,
6739 v02
= 1.35608801097516229404e-06,
6740 v03
= 6.22741452364621501295e-09,
6741 v04
= 1.66559246207992079114e-11;
6744 unsigned int ix
, lx
;
6746 ix
= *(ULONGLONG
*)&x
>> 32;
6747 lx
= *(ULONGLONG
*)&x
;
6749 /* y1(nan)=nan, y1(<0)=nan, y1(0)=-inf, y1(inf)=0 */
6750 if ((ix
<< 1 | lx
) == 0)
6751 return math_error(_OVERFLOW
, "_y1", x
, 0, -INFINITY
);
6755 return math_error(_DOMAIN
, "_y1", x
, 0, 0 / (x
- x
));
6756 if (ix
>= 0x7ff00000)
6759 if (ix
>= 0x40000000) /* x >= 2 */
6760 return j1_y1_approx(ix
, x
, TRUE
, 0);
6761 if (ix
< 0x3c900000) /* x < 2**-54 */
6764 u
= u00
+ z
* (u01
+ z
* (u02
+ z
* (u03
+ z
* u04
)));
6765 v
= 1 + z
* (v00
+ z
* (v01
+ z
* (v02
+ z
* (v03
+ z
* v04
))));
6766 return x
* (u
/ v
) + tpi
* (j1(x
) * log(x
) - 1 / x
);
6769 /*********************************************************************
6772 * Copied from musl: src/math/jn.c
6774 double CDECL
_yn(int n
, double x
)
6776 static const double invsqrtpi
= 5.64189583547756279280e-01;
6778 unsigned int ix
, lx
, ib
;
6782 ix
= *(ULONGLONG
*)&x
>> 32;
6783 lx
= *(ULONGLONG
*)&x
;
6787 if ((ix
| (lx
| -lx
) >> 31) > 0x7ff00000) /* nan */
6789 if (sign
&& (ix
| lx
) != 0) /* x < 0 */
6790 return math_error(_DOMAIN
, "_y1", x
, 0, 0 / (x
- x
));
6791 if (ix
== 0x7ff00000)
6804 return sign
? -y1(x
) : y1(x
);
6806 if (ix
>= 0x52d00000) { /* x > 2**302 */
6809 temp
= -sin(x
) - cos(x
);
6812 temp
= -sin(x
) + cos(x
);
6815 temp
= sin(x
) + cos(x
);
6818 temp
= sin(x
) - cos(x
);
6821 b
= invsqrtpi
* temp
/ sqrt(x
);
6825 /* quit if b is -inf */
6826 ib
= *(ULONGLONG
*)&b
>> 32;
6827 for (i
= 0; i
< nm1
&& ib
!= 0xfff00000;) {
6830 b
= (2.0 * i
/ x
) * b
- a
;
6831 ib
= *(ULONGLONG
*)&b
>> 32;
6835 return sign
? -b
: b
;
6840 /*********************************************************************
6841 * _nearbyint (MSVCR120.@)
6843 * Based on musl: src/math/nearbyteint.c
6845 double CDECL
nearbyint(double x
)
6847 BOOL update_cw
, update_sw
;
6848 unsigned int cw
, sw
;
6850 _setfp(&cw
, 0, &sw
, 0);
6851 update_cw
= !(cw
& _EM_INEXACT
);
6852 update_sw
= !(sw
& _SW_INEXACT
);
6856 _setfp(&cw
, _EM_INEXACT
, NULL
, 0);
6859 if (update_cw
|| update_sw
)
6863 _setfp(update_cw
? &cw
: NULL
, _EM_INEXACT
,
6864 update_sw
? &sw
: NULL
, _SW_INEXACT
);
6869 /*********************************************************************
6870 * _nearbyintf (MSVCR120.@)
6872 * Based on musl: src/math/nearbyteintf.c
6874 float CDECL
nearbyintf(float x
)
6876 BOOL update_cw
, update_sw
;
6877 unsigned int cw
, sw
;
6879 _setfp(&cw
, 0, &sw
, 0);
6880 update_cw
= !(cw
& _EM_INEXACT
);
6881 update_sw
= !(sw
& _SW_INEXACT
);
6885 _setfp(&cw
, _EM_INEXACT
, NULL
, 0);
6888 if (update_cw
|| update_sw
)
6892 _setfp(update_cw
? &cw
: NULL
, _EM_INEXACT
,
6893 update_sw
? &sw
: NULL
, _SW_INEXACT
);
6898 /*********************************************************************
6899 * nexttoward (MSVCR120.@)
6901 double CDECL
MSVCRT_nexttoward(double num
, double next
)
6903 return _nextafter(num
, next
);
6906 /*********************************************************************
6907 * nexttowardf (MSVCR120.@)
6909 * Copied from musl: src/math/nexttowardf.c
6911 float CDECL
MSVCRT_nexttowardf(float x
, double y
)
6913 unsigned int ix
= *(unsigned int*)&x
;
6917 if (isnan(x
) || isnan(y
))
6936 e
= ix
& 0x7f800000;
6937 /* raise overflow if ix is infinite and x is finite */
6938 if (e
== 0x7f800000) {
6943 /* raise underflow if ret is subnormal or zero */
6945 fp_barrierf(x
* x
+ ret
* ret
);
6951 #endif /* _MSVCR_VER>=120 */
6953 /*********************************************************************
6954 * _nextafter (MSVCRT.@)
6956 * Copied from musl: src/math/nextafter.c
6958 double CDECL
_nextafter(double x
, double y
)
6960 ULONGLONG llx
= *(ULONGLONG
*)&x
;
6961 ULONGLONG lly
= *(ULONGLONG
*)&y
;
6965 if (isnan(x
) || isnan(y
))
6968 if (_fpclass(y
) & (_FPCLASS_ND
| _FPCLASS_PD
| _FPCLASS_NZ
| _FPCLASS_PZ
))
6972 ax
= llx
& -1ULL / 2;
6973 ay
= lly
& -1ULL / 2;
6977 llx
= (lly
& 1ULL << 63) | 1;
6978 } else if (ax
> ay
|| ((llx
^ lly
) & 1ULL << 63))
6982 e
= llx
>> 52 & 0x7ff;
6983 /* raise overflow if llx is infinite and x is finite */
6988 /* raise underflow if llx is subnormal or zero */
6991 fp_barrier(x
* x
+ y
* y
);
6997 /*********************************************************************
7000 char * CDECL
_ecvt( double number
, int ndigits
, int *decpt
, int *sign
)
7003 thread_data_t
*data
= msvcrt_get_thread_data();
7004 /* FIXME: check better for overflow (native supports over 300 chars) */
7005 ndigits
= min( ndigits
, 80 - 8); /* 8 : space for sign, dec point, "e",
7006 * 4 for exponent and one for
7007 * terminating '\0' */
7008 if (!data
->efcvt_buffer
)
7009 data
->efcvt_buffer
= malloc( 80 ); /* ought to be enough */
7011 /* handle cases with zero ndigits or less */
7013 if( prec
< 1) prec
= 2;
7014 len
= _snprintf(data
->efcvt_buffer
, 80, "%.*le", prec
- 1, number
);
7016 if (data
->efcvt_buffer
[0] == '-') {
7017 memmove( data
->efcvt_buffer
, data
->efcvt_buffer
+ 1, len
-- );
7021 /* take the decimal "point away */
7023 memmove( data
->efcvt_buffer
+ 1, data
->efcvt_buffer
+ 2, len
- 1 );
7024 /* take the exponential "e" out */
7025 data
->efcvt_buffer
[ prec
] = '\0';
7026 /* read the exponent */
7027 sscanf( data
->efcvt_buffer
+ prec
+ 1, "%d", decpt
);
7029 /* adjust for some border cases */
7030 if( data
->efcvt_buffer
[0] == '0')/* value is zero */
7032 /* handle cases with zero ndigits or less */
7034 if( data
->efcvt_buffer
[ 0] >= '5')
7036 data
->efcvt_buffer
[ 0] = '\0';
7038 TRACE("out=\"%s\"\n",data
->efcvt_buffer
);
7039 return data
->efcvt_buffer
;
7042 /*********************************************************************
7043 * _ecvt_s (MSVCRT.@)
7045 int CDECL
_ecvt_s( char *buffer
, size_t length
, double number
, int ndigits
, int *decpt
, int *sign
)
7050 if (!MSVCRT_CHECK_PMT(buffer
!= NULL
)) return EINVAL
;
7051 if (!MSVCRT_CHECK_PMT(decpt
!= NULL
)) return EINVAL
;
7052 if (!MSVCRT_CHECK_PMT(sign
!= NULL
)) return EINVAL
;
7053 if (!MSVCRT_CHECK_PMT_ERR( length
> 2, ERANGE
)) return ERANGE
;
7054 if (!MSVCRT_CHECK_PMT_ERR(ndigits
< (int)length
- 1, ERANGE
)) return ERANGE
;
7056 /* handle cases with zero ndigits or less */
7058 if( prec
< 1) prec
= 2;
7059 result
= malloc(prec
+ 8);
7061 len
= _snprintf(result
, prec
+ 8, "%.*le", prec
- 1, number
);
7062 if (result
[0] == '-') {
7063 memmove( result
, result
+ 1, len
-- );
7067 /* take the decimal "point away */
7069 memmove( result
+ 1, result
+ 2, len
- 1 );
7070 /* take the exponential "e" out */
7071 result
[ prec
] = '\0';
7072 /* read the exponent */
7073 sscanf( result
+ prec
+ 1, "%d", decpt
);
7075 /* adjust for some border cases */
7076 if( result
[0] == '0')/* value is zero */
7078 /* handle cases with zero ndigits or less */
7080 if( result
[ 0] >= '5')
7084 memcpy( buffer
, result
, max(ndigits
+ 1, 1) );
7089 /***********************************************************************
7092 char * CDECL
_fcvt( double number
, int ndigits
, int *decpt
, int *sign
)
7094 thread_data_t
*data
= msvcrt_get_thread_data();
7095 int stop
, dec1
, dec2
;
7096 char *ptr1
, *ptr2
, *first
;
7097 char buf
[80]; /* ought to be enough */
7098 char decimal_separator
= get_locinfo()->lconv
->decimal_point
[0];
7100 if (!data
->efcvt_buffer
)
7101 data
->efcvt_buffer
= malloc( 80 ); /* ought to be enough */
7103 stop
= _snprintf(buf
, 80, "%.*f", ndigits
< 0 ? 0 : ndigits
, number
);
7105 ptr2
= data
->efcvt_buffer
;
7115 /* For numbers below the requested resolution, work out where
7116 the decimal point will be rather than finding it in the string */
7117 if (number
< 1.0 && number
> 0.0) {
7118 dec2
= log10(number
+ 1e-10);
7119 if (-dec2
<= ndigits
) dec2
= 0;
7122 /* If requested digits is zero or less, we will need to truncate
7123 * the returned string */
7128 while (*ptr1
== '0') ptr1
++; /* Skip leading zeroes */
7129 while (*ptr1
!= '\0' && *ptr1
!= decimal_separator
) {
7130 if (!first
) first
= ptr2
;
7131 if ((ptr1
- buf
) < stop
) {
7142 while (*ptr1
== '0') { /* Process leading zeroes */
7147 while (*ptr1
!= '\0') {
7148 if (!first
) first
= ptr2
;
7155 /* We never found a non-zero digit, then our number is either
7156 * smaller than the requested precision, or 0.0 */
7161 first
= data
->efcvt_buffer
;
7166 *decpt
= dec2
? dec2
: dec1
;
7170 /***********************************************************************
7171 * _fcvt_s (MSVCRT.@)
7173 int CDECL
_fcvt_s(char* outbuffer
, size_t size
, double number
, int ndigits
, int *decpt
, int *sign
)
7175 int stop
, dec1
, dec2
;
7176 char *ptr1
, *ptr2
, *first
;
7177 char buf
[80]; /* ought to be enough */
7178 char decimal_separator
= get_locinfo()->lconv
->decimal_point
[0];
7180 if (!outbuffer
|| !decpt
|| !sign
|| size
== 0)
7186 stop
= _snprintf(buf
, 80, "%.*f", ndigits
< 0 ? 0 : ndigits
, number
);
7198 /* For numbers below the requested resolution, work out where
7199 the decimal point will be rather than finding it in the string */
7200 if (number
< 1.0 && number
> 0.0) {
7201 dec2
= log10(number
+ 1e-10);
7202 if (-dec2
<= ndigits
) dec2
= 0;
7205 /* If requested digits is zero or less, we will need to truncate
7206 * the returned string */
7211 while (*ptr1
== '0') ptr1
++; /* Skip leading zeroes */
7212 while (*ptr1
!= '\0' && *ptr1
!= decimal_separator
) {
7213 if (!first
) first
= ptr2
;
7214 if ((ptr1
- buf
) < stop
) {
7228 while (*ptr1
== '0') { /* Process leading zeroes */
7229 if (number
== 0.0 && size
> 1) {
7237 while (*ptr1
!= '\0') {
7238 if (!first
) first
= ptr2
;
7248 /* We never found a non-zero digit, then our number is either
7249 * smaller than the requested precision, or 0.0 */
7250 if (!first
&& (number
<= 0.0))
7253 *decpt
= dec2
? dec2
: dec1
;
7257 /***********************************************************************
7260 char * CDECL
_gcvt( double number
, int ndigit
, char *buff
)
7272 sprintf(buff
, "%.*g", ndigit
, number
);
7276 /***********************************************************************
7277 * _gcvt_s (MSVCRT.@)
7279 int CDECL
_gcvt_s(char *buff
, size_t size
, double number
, int digits
)
7288 if( digits
<0 || digits
>=size
) {
7296 len
= _scprintf("%.*g", digits
, number
);
7303 sprintf(buff
, "%.*g", digits
, number
);
7307 #include <stdlib.h> /* div_t, ldiv_t */
7309 /*********************************************************************
7312 * [i386] Windows binary compatible - returns the struct in eax/edx.
7315 unsigned __int64 CDECL
div(int num
, int denom
)
7319 unsigned __int64 uint64
;
7322 ret
.div
.quot
= num
/ denom
;
7323 ret
.div
.rem
= num
% denom
;
7327 /*********************************************************************
7330 * [!i386] Non-x86 can't run win32 apps so we don't need binary compatibility
7332 div_t CDECL
div(int num
, int denom
)
7336 ret
.quot
= num
/ denom
;
7337 ret
.rem
= num
% denom
;
7340 #endif /* ifdef __i386__ */
7343 /*********************************************************************
7346 * [i386] Windows binary compatible - returns the struct in eax/edx.
7349 unsigned __int64 CDECL
ldiv(__msvcrt_long num
, __msvcrt_long denom
)
7353 unsigned __int64 uint64
;
7356 ret
.ldiv
.quot
= num
/ denom
;
7357 ret
.ldiv
.rem
= num
% denom
;
7361 /*********************************************************************
7364 * [!i386] Non-x86 can't run win32 apps so we don't need binary compatibility
7366 ldiv_t CDECL
ldiv(__msvcrt_long num
, __msvcrt_long denom
)
7370 ret
.quot
= num
/ denom
;
7371 ret
.rem
= num
% denom
;
7374 #endif /* ifdef __i386__ */
7377 /*********************************************************************
7378 * lldiv (MSVCR100.@)
7380 lldiv_t CDECL
lldiv(__int64 num
, __int64 denom
)
7384 ret
.quot
= num
/ denom
;
7385 ret
.rem
= num
% denom
;
7393 /*********************************************************************
7394 * _adjust_fdiv (MSVCRT.@)
7395 * Used by the MSVC compiler to work around the Pentium FDIV bug.
7397 int MSVCRT__adjust_fdiv
= 0;
7399 /***********************************************************************
7400 * _adj_fdiv_m16i (MSVCRT.@)
7403 * I _think_ this function is intended to work around the Pentium
7406 void __stdcall
_adj_fdiv_m16i( short arg
)
7408 TRACE("(): stub\n");
7411 /***********************************************************************
7412 * _adj_fdiv_m32 (MSVCRT.@)
7415 * I _think_ this function is intended to work around the Pentium
7418 void __stdcall
_adj_fdiv_m32( unsigned int arg
)
7420 TRACE("(): stub\n");
7423 /***********************************************************************
7424 * _adj_fdiv_m32i (MSVCRT.@)
7427 * I _think_ this function is intended to work around the Pentium
7430 void __stdcall
_adj_fdiv_m32i( int arg
)
7432 TRACE("(): stub\n");
7435 /***********************************************************************
7436 * _adj_fdiv_m64 (MSVCRT.@)
7439 * I _think_ this function is intended to work around the Pentium
7442 void __stdcall
_adj_fdiv_m64( unsigned __int64 arg
)
7444 TRACE("(): stub\n");
7447 /***********************************************************************
7448 * _adj_fdiv_r (MSVCRT.@)
7450 * This function is likely to have the wrong number of arguments.
7453 * I _think_ this function is intended to work around the Pentium
7456 void _adj_fdiv_r(void)
7458 TRACE("(): stub\n");
7461 /***********************************************************************
7462 * _adj_fdivr_m16i (MSVCRT.@)
7465 * I _think_ this function is intended to work around the Pentium
7468 void __stdcall
_adj_fdivr_m16i( short arg
)
7470 TRACE("(): stub\n");
7473 /***********************************************************************
7474 * _adj_fdivr_m32 (MSVCRT.@)
7477 * I _think_ this function is intended to work around the Pentium
7480 void __stdcall
_adj_fdivr_m32( unsigned int arg
)
7482 TRACE("(): stub\n");
7485 /***********************************************************************
7486 * _adj_fdivr_m32i (MSVCRT.@)
7489 * I _think_ this function is intended to work around the Pentium
7492 void __stdcall
_adj_fdivr_m32i( int arg
)
7494 TRACE("(): stub\n");
7497 /***********************************************************************
7498 * _adj_fdivr_m64 (MSVCRT.@)
7501 * I _think_ this function is intended to work around the Pentium
7504 void __stdcall
_adj_fdivr_m64( unsigned __int64 arg
)
7506 TRACE("(): stub\n");
7509 /***********************************************************************
7510 * _adj_fpatan (MSVCRT.@)
7512 * This function is likely to have the wrong number of arguments.
7515 * I _think_ this function is intended to work around the Pentium
7518 void _adj_fpatan(void)
7520 TRACE("(): stub\n");
7523 /***********************************************************************
7524 * _adj_fprem (MSVCRT.@)
7526 * This function is likely to have the wrong number of arguments.
7529 * I _think_ this function is intended to work around the Pentium
7532 void _adj_fprem(void)
7534 TRACE("(): stub\n");
7537 /***********************************************************************
7538 * _adj_fprem1 (MSVCRT.@)
7540 * This function is likely to have the wrong number of arguments.
7543 * I _think_ this function is intended to work around the Pentium
7546 void _adj_fprem1(void)
7548 TRACE("(): stub\n");
7551 /***********************************************************************
7552 * _adj_fptan (MSVCRT.@)
7554 * This function is likely to have the wrong number of arguments.
7557 * I _think_ this function is intended to work around the Pentium
7560 void _adj_fptan(void)
7562 TRACE("(): stub\n");
7565 /***********************************************************************
7566 * _safe_fdiv (MSVCRT.@)
7568 * This function is likely to have the wrong number of arguments.
7571 * I _think_ this function is intended to work around the Pentium
7574 void _safe_fdiv(void)
7576 TRACE("(): stub\n");
7579 /***********************************************************************
7580 * _safe_fdivr (MSVCRT.@)
7582 * This function is likely to have the wrong number of arguments.
7585 * I _think_ this function is intended to work around the Pentium
7588 void _safe_fdivr(void)
7590 TRACE("(): stub\n");
7593 /***********************************************************************
7594 * _safe_fprem (MSVCRT.@)
7596 * This function is likely to have the wrong number of arguments.
7599 * I _think_ this function is intended to work around the Pentium
7602 void _safe_fprem(void)
7604 TRACE("(): stub\n");
7607 /***********************************************************************
7608 * _safe_fprem1 (MSVCRT.@)
7611 * This function is likely to have the wrong number of arguments.
7614 * I _think_ this function is intended to work around the Pentium
7617 void _safe_fprem1(void)
7619 TRACE("(): stub\n");
7622 /***********************************************************************
7623 * __libm_sse2_acos (MSVCRT.@)
7625 void __cdecl
__libm_sse2_acos(void)
7628 __asm__
__volatile__( "movq %%xmm0,%0" : "=m" (d
) );
7630 __asm__
__volatile__( "movq %0,%%xmm0" : : "m" (d
) );
7633 /***********************************************************************
7634 * __libm_sse2_acosf (MSVCRT.@)
7636 void __cdecl
__libm_sse2_acosf(void)
7639 __asm__
__volatile__( "movd %%xmm0,%0" : "=g" (f
) );
7641 __asm__
__volatile__( "movd %0,%%xmm0" : : "g" (f
) );
7644 /***********************************************************************
7645 * __libm_sse2_asin (MSVCRT.@)
7647 void __cdecl
__libm_sse2_asin(void)
7650 __asm__
__volatile__( "movq %%xmm0,%0" : "=m" (d
) );
7652 __asm__
__volatile__( "movq %0,%%xmm0" : : "m" (d
) );
7655 /***********************************************************************
7656 * __libm_sse2_asinf (MSVCRT.@)
7658 void __cdecl
__libm_sse2_asinf(void)
7661 __asm__
__volatile__( "movd %%xmm0,%0" : "=g" (f
) );
7663 __asm__
__volatile__( "movd %0,%%xmm0" : : "g" (f
) );
7666 /***********************************************************************
7667 * __libm_sse2_atan (MSVCRT.@)
7669 void __cdecl
__libm_sse2_atan(void)
7672 __asm__
__volatile__( "movq %%xmm0,%0" : "=m" (d
) );
7674 __asm__
__volatile__( "movq %0,%%xmm0" : : "m" (d
) );
7677 /***********************************************************************
7678 * __libm_sse2_atan2 (MSVCRT.@)
7680 void __cdecl
__libm_sse2_atan2(void)
7683 __asm__
__volatile__( "movq %%xmm0,%0; movq %%xmm1,%1 " : "=m" (d1
), "=m" (d2
) );
7684 d1
= atan2( d1
, d2
);
7685 __asm__
__volatile__( "movq %0,%%xmm0" : : "m" (d1
) );
7688 /***********************************************************************
7689 * __libm_sse2_atanf (MSVCRT.@)
7691 void __cdecl
__libm_sse2_atanf(void)
7694 __asm__
__volatile__( "movd %%xmm0,%0" : "=g" (f
) );
7696 __asm__
__volatile__( "movd %0,%%xmm0" : : "g" (f
) );
7699 /***********************************************************************
7700 * __libm_sse2_cos (MSVCRT.@)
7702 void __cdecl
__libm_sse2_cos(void)
7705 __asm__
__volatile__( "movq %%xmm0,%0" : "=m" (d
) );
7707 __asm__
__volatile__( "movq %0,%%xmm0" : : "m" (d
) );
7710 /***********************************************************************
7711 * __libm_sse2_cosf (MSVCRT.@)
7713 void __cdecl
__libm_sse2_cosf(void)
7716 __asm__
__volatile__( "movd %%xmm0,%0" : "=g" (f
) );
7718 __asm__
__volatile__( "movd %0,%%xmm0" : : "g" (f
) );
7721 /***********************************************************************
7722 * __libm_sse2_exp (MSVCRT.@)
7724 void __cdecl
__libm_sse2_exp(void)
7727 __asm__
__volatile__( "movq %%xmm0,%0" : "=m" (d
) );
7729 __asm__
__volatile__( "movq %0,%%xmm0" : : "m" (d
) );
7732 /***********************************************************************
7733 * __libm_sse2_expf (MSVCRT.@)
7735 void __cdecl
__libm_sse2_expf(void)
7738 __asm__
__volatile__( "movd %%xmm0,%0" : "=g" (f
) );
7740 __asm__
__volatile__( "movd %0,%%xmm0" : : "g" (f
) );
7743 /***********************************************************************
7744 * __libm_sse2_log (MSVCRT.@)
7746 void __cdecl
__libm_sse2_log(void)
7749 __asm__
__volatile__( "movq %%xmm0,%0" : "=m" (d
) );
7751 __asm__
__volatile__( "movq %0,%%xmm0" : : "m" (d
) );
7754 /***********************************************************************
7755 * __libm_sse2_log10 (MSVCRT.@)
7757 void __cdecl
__libm_sse2_log10(void)
7760 __asm__
__volatile__( "movq %%xmm0,%0" : "=m" (d
) );
7762 __asm__
__volatile__( "movq %0,%%xmm0" : : "m" (d
) );
7765 /***********************************************************************
7766 * __libm_sse2_log10f (MSVCRT.@)
7768 void __cdecl
__libm_sse2_log10f(void)
7771 __asm__
__volatile__( "movd %%xmm0,%0" : "=g" (f
) );
7773 __asm__
__volatile__( "movd %0,%%xmm0" : : "g" (f
) );
7776 /***********************************************************************
7777 * __libm_sse2_logf (MSVCRT.@)
7779 void __cdecl
__libm_sse2_logf(void)
7782 __asm__
__volatile__( "movd %%xmm0,%0" : "=g" (f
) );
7784 __asm__
__volatile__( "movd %0,%%xmm0" : : "g" (f
) );
7787 /***********************************************************************
7788 * __libm_sse2_pow (MSVCRT.@)
7790 void __cdecl
__libm_sse2_pow(void)
7793 __asm__
__volatile__( "movq %%xmm0,%0; movq %%xmm1,%1 " : "=m" (d1
), "=m" (d2
) );
7795 __asm__
__volatile__( "movq %0,%%xmm0" : : "m" (d1
) );
7798 /***********************************************************************
7799 * __libm_sse2_powf (MSVCRT.@)
7801 void __cdecl
__libm_sse2_powf(void)
7804 __asm__
__volatile__( "movd %%xmm0,%0; movd %%xmm1,%1" : "=g" (f1
), "=g" (f2
) );
7805 f1
= powf( f1
, f2
);
7806 __asm__
__volatile__( "movd %0,%%xmm0" : : "g" (f1
) );
7809 /***********************************************************************
7810 * __libm_sse2_sin (MSVCRT.@)
7812 void __cdecl
__libm_sse2_sin(void)
7815 __asm__
__volatile__( "movq %%xmm0,%0" : "=m" (d
) );
7817 __asm__
__volatile__( "movq %0,%%xmm0" : : "m" (d
) );
7820 /***********************************************************************
7821 * __libm_sse2_sinf (MSVCRT.@)
7823 void __cdecl
__libm_sse2_sinf(void)
7826 __asm__
__volatile__( "movd %%xmm0,%0" : "=g" (f
) );
7828 __asm__
__volatile__( "movd %0,%%xmm0" : : "g" (f
) );
7831 /***********************************************************************
7832 * __libm_sse2_tan (MSVCRT.@)
7834 void __cdecl
__libm_sse2_tan(void)
7837 __asm__
__volatile__( "movq %%xmm0,%0" : "=m" (d
) );
7839 __asm__
__volatile__( "movq %0,%%xmm0" : : "m" (d
) );
7842 /***********************************************************************
7843 * __libm_sse2_tanf (MSVCRT.@)
7845 void __cdecl
__libm_sse2_tanf(void)
7848 __asm__
__volatile__( "movd %%xmm0,%0" : "=g" (f
) );
7850 __asm__
__volatile__( "movd %0,%%xmm0" : : "g" (f
) );
7853 /***********************************************************************
7854 * __libm_sse2_sqrt_precise (MSVCR110.@)
7856 void __cdecl
__libm_sse2_sqrt_precise(void)
7861 __asm__
__volatile__( "movq %%xmm0,%0" : "=m" (d
) );
7862 __control87_2(0, 0, NULL
, &cw
);
7866 __asm__
__volatile__( "movq %0,%%xmm0" : : "m" (d
) );
7870 if (!sqrt_validate(&d
, FALSE
))
7872 __asm__
__volatile__( "movq %0,%%xmm0" : : "m" (d
) );
7875 __asm__
__volatile__( "call " __ASM_NAME( "sse2_sqrt" ) );
7877 #endif /* __i386__ */
7881 /*********************************************************************
7884 * Copied from musl: src/math/cbrt.c
7886 double CDECL
cbrt(double x
)
7888 static const UINT32 B1
= 715094163, B2
= 696219795;
7889 static const double P0
= 1.87595182427177009643,
7890 P1
= -1.88497979543377169875,
7891 P2
= 1.621429720105354466140,
7892 P3
= -0.758397934778766047437,
7893 P4
= 0.145996192886612446982;
7895 union {double f
; UINT64 i
;} u
= {x
};
7897 UINT32 hx
= u
.i
>> 32 & 0x7fffffff;
7899 if (hx
>= 0x7ff00000) /* cbrt(NaN,INF) is itself */
7902 if (hx
< 0x00100000) { /* zero or subnormal? */
7904 hx
= u
.i
>>32 & 0x7fffffff;
7911 u
.i
|= (UINT64
)hx
<< 32;
7914 r
= (t
* t
) * (t
/ x
);
7915 t
= t
* ((P0
+ r
* (P1
+ r
* P2
)) + ((r
* r
) * r
) * (P3
+ r
* P4
));
7918 u
.i
= (u
.i
+ 0x80000000) & 0xffffffffc0000000ULL
;
7924 r
= (r
- t
) / (w
+ r
);
7929 /*********************************************************************
7930 * cbrtf (MSVCR120.@)
7932 * Copied from musl: src/math/cbrtf.c
7934 float CDECL
cbrtf(float x
)
7936 static const unsigned B1
= 709958130, B2
= 642849266;
7939 union {float f
; UINT32 i
;} u
= {x
};
7940 UINT32 hx
= u
.i
& 0x7fffffff;
7942 if (hx
>= 0x7f800000)
7945 if (hx
< 0x00800000) { /* zero or subnormal? */
7949 hx
= u
.i
& 0x7fffffff;
7958 T
= T
* (x
+ x
+ r
) / (x
+ r
+ r
);
7961 T
= T
* (x
+ x
+ r
) / (x
+ r
+ r
);
7965 /*********************************************************************
7968 * Copied from musl: src/math/exp2.c
7970 double CDECL
exp2(double x
)
7972 static const double C
[] = {
7973 0x1.62e42fefa39efp
-1,
7974 0x1.ebfbdff82c424p
-3,
7975 0x1.c6b08d70cf4b5p
-5,
7976 0x1.3b2abd24650ccp
-7,
7977 0x1.5d7e09b4e3a84p
-10
7981 UINT64 ki
, idx
, top
, sbits
;
7982 double kd
, r
, r2
, scale
, tail
, tmp
;
7984 abstop
= (*(UINT64
*)&x
>> 52) & 0x7ff;
7985 if (abstop
- 0x3c9 >= 0x408 - 0x3c9) {
7986 if (abstop
- 0x3c9 >= 0x80000000) {
7987 /* Avoid spurious underflow for tiny x. */
7988 /* Note: 0 is common input. */
7991 if (abstop
>= 409) {
7992 if (*(UINT64
*)&x
== 0xfff0000000000000ull
)
7994 if (abstop
>= 0x7ff)
7996 if (!(*(UINT64
*)&x
>> 63)) {
7998 return fp_barrier(DBL_MAX
) * DBL_MAX
;
8000 else if (x
<= -2147483648.0) {
8001 fp_barrier(x
+ 0x1p
120f
);
8004 else if (*(UINT64
*)&x
>= 0xc090cc0000000000ull
) {
8006 fp_barrier(x
+ 0x1p
120f
);
8010 if (2 * *(UINT64
*)&x
> 2 * 0x408d000000000000ull
)
8011 /* Large x is special cased below. */
8015 /* exp2(x) = 2^(k/N) * 2^r, with 2^r in [2^(-1/2N),2^(1/2N)]. */
8016 /* x = k/N + r, with int k and r in [-1/2N, 1/2N]. */
8017 kd
= fp_barrier(x
+ 0x1.8p52
/ (1 << 7));
8018 ki
= *(UINT64
*)&kd
; /* k. */
8019 kd
-= 0x1.8p52
/ (1 << 7); /* k/N for int k. */
8021 /* 2^(k/N) ~= scale * (1 + tail). */
8022 idx
= 2 * (ki
% (1 << 7));
8023 top
= ki
<< (52 - 7);
8024 tail
= *(double*)&exp_T
[idx
];
8025 /* This is only a valid scale when -1023*N < k < 1024*N. */
8026 sbits
= exp_T
[idx
+ 1] + top
;
8027 /* exp2(x) = 2^(k/N) * 2^r ~= scale + scale * (tail + 2^r - 1). */
8028 /* Evaluation is optimized assuming superscalar pipelined execution. */
8030 /* Without fma the worst case error is 0.5/N ulp larger. */
8031 /* Worst case error is less than 0.5+0.86/N+(abs poly error * 2^53) ulp. */
8032 tmp
= tail
+ r
* C
[0] + r2
* (C
[1] + r
* C
[2]) + r2
* r2
* (C
[3] + r
* C
[4]);
8035 /* Handle cases that may overflow or underflow when computing the result that
8036 is scale*(1+TMP) without intermediate rounding. The bit representation of
8037 scale is in SBITS, however it has a computed exponent that may have
8038 overflown into the sign bit so that needs to be adjusted before using it as
8039 a double. (int32_t)KI is the k used in the argument reduction and exponent
8040 adjustment of scale, positive k here means the result may overflow and
8041 negative k means the result may underflow. */
8044 if ((ki
& 0x80000000) == 0) {
8045 /* k > 0, the exponent of scale might have overflowed by 1. */
8046 sbits
-= 1ull << 52;
8047 scale
= *(double*)&sbits
;
8048 y
= 2 * (scale
+ scale
* tmp
);
8051 /* k < 0, need special care in the subnormal range. */
8052 sbits
+= 1022ull << 52;
8053 scale
= *(double*)&sbits
;
8054 y
= scale
+ scale
* tmp
;
8056 /* Round y to the right precision before scaling it into the subnormal
8057 range to avoid double rounding that can cause 0.5+E/2 ulp error where
8058 E is the worst-case ulp error outside the subnormal range. So this
8059 is only useful if the goal is better than 1 ulp worst-case error. */
8061 lo
= scale
- y
+ scale
* tmp
;
8063 lo
= 1.0 - hi
+ y
+ lo
;
8065 /* Avoid -0.0 with downward rounding. */
8068 /* The underflow exception needs to be signaled explicitly. */
8069 fp_barrier(fp_barrier(0x1p
-1022) * 0x1p
-1022);
8074 scale
= *(double*)&sbits
;
8075 /* Note: tmp == 0 or |tmp| > 2^-65 and scale > 2^-928, so there
8076 is no spurious underflow here even without fma. */
8077 return scale
+ scale
* tmp
;
8080 /*********************************************************************
8081 * exp2f (MSVCR120.@)
8083 * Copied from musl: src/math/exp2f.c
8085 float CDECL
exp2f(float x
)
8087 static const double C
[] = {
8088 0x1.c6af84b912394p
-5, 0x1.ebfce50fac4f3p
-3, 0x1.62e42ff0c52d6p
-1
8090 static const double shift
= 0x1.8p
+52 / (1 << 5);
8092 double kd
, xd
, z
, r
, r2
, y
, s
;
8097 abstop
= (*(UINT32
*)&x
>> 20) & 0x7ff;
8098 if (abstop
>= 0x430) {
8099 /* |x| >= 128 or x is nan. */
8100 if (*(UINT32
*)&x
== 0xff800000)
8102 if (abstop
>= 0x7f8)
8106 return fp_barrierf(x
* FLT_MAX
);
8109 fp_barrierf(x
- 0x1p
120);
8114 /* x = k/N + r with r in [-1/(2N), 1/(2N)] and int k, N = 1 << 5. */
8117 kd
-= shift
; /* k/(1<<5) for int k. */
8120 /* exp2(x) = 2^(k/N) * 2^r ~= s * (C0*r^3 + C1*r^2 + C2*r + 1) */
8121 t
= exp2f_T
[ki
% (1 << 5)];
8122 t
+= ki
<< (52 - 5);
8124 z
= C
[0] * r
+ C
[1];
8132 /*********************************************************************
8133 * expm1 (MSVCR120.@)
8135 double CDECL
expm1(double x
)
8140 /*********************************************************************
8141 * expm1f (MSVCR120.@)
8143 float CDECL
expm1f(float x
)
8148 /*********************************************************************
8149 * log1p (MSVCR120.@)
8151 * Copied from musl: src/math/log1p.c
8153 double CDECL
log1p(double x
)
8155 static const double ln2_hi
= 6.93147180369123816490e-01,
8156 ln2_lo
= 1.90821492927058770002e-10,
8157 Lg1
= 6.666666666666735130e-01,
8158 Lg2
= 3.999999999940941908e-01,
8159 Lg3
= 2.857142874366239149e-01,
8160 Lg4
= 2.222219843214978396e-01,
8161 Lg5
= 1.818357216161805012e-01,
8162 Lg6
= 1.531383769920937332e-01,
8163 Lg7
= 1.479819860511658591e-01;
8165 union {double f
; UINT64 i
;} u
= {x
};
8166 double hfsq
, f
, c
, s
, z
, R
, w
, t1
, t2
, dk
;
8172 if (hx
< 0x3fda827a || hx
>> 31) { /* 1+x < sqrt(2)+ */
8173 if (hx
>= 0xbff00000) { /* x <= -1.0 */
8176 return x
/ 0.0; /* og1p(-1) = -inf */
8179 return (x
-x
) / 0.0; /* log1p(x<-1) = NaN */
8181 if (hx
<< 1 < 0x3ca00000 << 1) { /* |x| < 2**-53 */
8182 fp_barrier(x
+ 0x1p
120f
);
8183 /* underflow if subnormal */
8184 if ((hx
& 0x7ff00000) == 0)
8188 if (hx
<= 0xbfd2bec4) { /* sqrt(2)/2- <= 1+x < sqrt(2)+ */
8193 } else if (hx
>= 0x7ff00000)
8198 hu
+= 0x3ff00000 - 0x3fe6a09e;
8199 k
= (int)(hu
>> 20) - 0x3ff;
8200 /* correction term ~ log(1+x)-log(u), avoid underflow in c/u */
8202 c
= k
>= 2 ? 1 - (u
.f
- x
) : x
- (u
.f
- 1);
8206 /* reduce u into [sqrt(2)/2, sqrt(2)] */
8207 hu
= (hu
& 0x000fffff) + 0x3fe6a09e;
8208 u
.i
= (UINT64
)hu
<< 32 | (u
.i
& 0xffffffff);
8215 t1
= w
* (Lg2
+ w
* (Lg4
+ w
* Lg6
));
8216 t2
= z
* (Lg1
+ w
* (Lg3
+ w
* (Lg5
+ w
* Lg7
)));
8219 return s
* (hfsq
+ R
) + (dk
* ln2_lo
+ c
) - hfsq
+ f
+ dk
* ln2_hi
;
8222 /*********************************************************************
8223 * log1pf (MSVCR120.@)
8225 * Copied from musl: src/math/log1pf.c
8227 float CDECL
log1pf(float x
)
8229 static const float ln2_hi
= 6.9313812256e-01,
8230 ln2_lo
= 9.0580006145e-06,
8231 Lg1
= 0xaaaaaa.0p
-24,
8232 Lg2
= 0xccce13.0p
-25,
8233 Lg3
= 0x91e9ee.0p
-25,
8234 Lg4
= 0xf89e26.0p
-26;
8236 union {float f
; UINT32 i
;} u
= {x
};
8237 float hfsq
, f
, c
, s
, z
, R
, w
, t1
, t2
, dk
;
8243 if (ix
< 0x3ed413d0 || ix
>> 31) { /* 1+x < sqrt(2)+ */
8244 if (ix
>= 0xbf800000) { /* x <= -1.0 */
8247 return x
/ 0.0f
; /* log1p(-1)=+inf */
8250 return (x
- x
) / 0.0f
; /* log1p(x<-1)=NaN */
8252 if (ix
<<1 < 0x33800000<<1) { /* |x| < 2**-24 */
8253 /* underflow if subnormal */
8254 if ((ix
& 0x7f800000) == 0)
8258 if (ix
<= 0xbe95f619) { /* sqrt(2)/2- <= 1+x < sqrt(2)+ */
8263 } else if (ix
>= 0x7f800000)
8268 iu
+= 0x3f800000 - 0x3f3504f3;
8269 k
= (int)(iu
>> 23) - 0x7f;
8270 /* correction term ~ log(1+x)-log(u), avoid underflow in c/u */
8272 c
= k
>= 2 ? 1 - (u
.f
- x
) : x
- (u
.f
- 1);
8276 /* reduce u into [sqrt(2)/2, sqrt(2)] */
8277 iu
= (iu
& 0x007fffff) + 0x3f3504f3;
8284 t1
= w
* (Lg2
+ w
* Lg4
);
8285 t2
= z
* (Lg1
+ w
* Lg3
);
8287 hfsq
= 0.5f
* f
* f
;
8289 return s
* (hfsq
+ R
) + (dk
* ln2_lo
+ c
) - hfsq
+ f
+ dk
* ln2_hi
;
8292 /*********************************************************************
8295 * Copied from musl: src/math/log2.c
8297 double CDECL
log2(double x
)
8299 static const double invln2hi
= 0x1.7154765200000p
+0,
8300 invln2lo
= 0x1.705fc2eefa200p
-33;
8301 static const double A
[] = {
8302 -0x1.71547652b8339p
-1,
8303 0x1.ec709dc3a04bep
-2,
8304 -0x1.7154764702ffbp
-2,
8305 0x1.2776c50034c48p
-2,
8306 -0x1.ec7b328ea92bcp
-3,
8307 0x1.a6225e117f92ep
-3
8309 static const double B
[] = {
8310 -0x1.71547652b82fep
-1,
8311 0x1.ec709dc3a03f7p
-2,
8312 -0x1.71547652b7c3fp
-2,
8313 0x1.2776c50f05be4p
-2,
8314 -0x1.ec709dd768fe5p
-3,
8315 0x1.a61761ec4e736p
-3,
8316 -0x1.7153fbc64a79bp
-3,
8317 0x1.484d154f01b4ap
-3,
8318 -0x1.289e4a72c383cp
-3,
8319 0x1.0b32f285aee66p
-3
8321 static const struct {
8324 {0x1.724286bb1acf8p
+0, -0x1.1095feecdb000p
-1},
8325 {0x1.6e1f766d2cca1p
+0, -0x1.08494bd76d000p
-1},
8326 {0x1.6a13d0e30d48ap
+0, -0x1.00143aee8f800p
-1},
8327 {0x1.661ec32d06c85p
+0, -0x1.efec5360b4000p
-2},
8328 {0x1.623fa951198f8p
+0, -0x1.dfdd91ab7e000p
-2},
8329 {0x1.5e75ba4cf026cp
+0, -0x1.cffae0cc79000p
-2},
8330 {0x1.5ac055a214fb8p
+0, -0x1.c043811fda000p
-2},
8331 {0x1.571ed0f166e1ep
+0, -0x1.b0b67323ae000p
-2},
8332 {0x1.53909590bf835p
+0, -0x1.a152f5a2db000p
-2},
8333 {0x1.5014fed61adddp
+0, -0x1.9217f5af86000p
-2},
8334 {0x1.4cab88e487bd0p
+0, -0x1.8304db0719000p
-2},
8335 {0x1.49539b4334feep
+0, -0x1.74189f9a9e000p
-2},
8336 {0x1.460cbdfafd569p
+0, -0x1.6552bb5199000p
-2},
8337 {0x1.42d664ee4b953p
+0, -0x1.56b23a29b1000p
-2},
8338 {0x1.3fb01111dd8a6p
+0, -0x1.483650f5fa000p
-2},
8339 {0x1.3c995b70c5836p
+0, -0x1.39de937f6a000p
-2},
8340 {0x1.3991c4ab6fd4ap
+0, -0x1.2baa1538d6000p
-2},
8341 {0x1.3698e0ce099b5p
+0, -0x1.1d98340ca4000p
-2},
8342 {0x1.33ae48213e7b2p
+0, -0x1.0fa853a40e000p
-2},
8343 {0x1.30d191985bdb1p
+0, -0x1.01d9c32e73000p
-2},
8344 {0x1.2e025cab271d7p
+0, -0x1.e857da2fa6000p
-3},
8345 {0x1.2b404cf13cd82p
+0, -0x1.cd3c8633d8000p
-3},
8346 {0x1.288b02c7ccb50p
+0, -0x1.b26034c14a000p
-3},
8347 {0x1.25e2263944de5p
+0, -0x1.97c1c2f4fe000p
-3},
8348 {0x1.234563d8615b1p
+0, -0x1.7d6023f800000p
-3},
8349 {0x1.20b46e33eaf38p
+0, -0x1.633a71a05e000p
-3},
8350 {0x1.1e2eefdcda3ddp
+0, -0x1.494f5e9570000p
-3},
8351 {0x1.1bb4a580b3930p
+0, -0x1.2f9e424e0a000p
-3},
8352 {0x1.19453847f2200p
+0, -0x1.162595afdc000p
-3},
8353 {0x1.16e06c0d5d73cp
+0, -0x1.f9c9a75bd8000p
-4},
8354 {0x1.1485f47b7e4c2p
+0, -0x1.c7b575bf9c000p
-4},
8355 {0x1.12358ad0085d1p
+0, -0x1.960c60ff48000p
-4},
8356 {0x1.0fef00f532227p
+0, -0x1.64ce247b60000p
-4},
8357 {0x1.0db2077d03a8fp
+0, -0x1.33f78b2014000p
-4},
8358 {0x1.0b7e6d65980d9p
+0, -0x1.0387d1a42c000p
-4},
8359 {0x1.0953efe7b408dp
+0, -0x1.a6f9208b50000p
-5},
8360 {0x1.07325cac53b83p
+0, -0x1.47a954f770000p
-5},
8361 {0x1.05197e40d1b5cp
+0, -0x1.d23a8c50c0000p
-6},
8362 {0x1.03091c1208ea2p
+0, -0x1.16a2629780000p
-6},
8363 {0x1.0101025b37e21p
+0, -0x1.720f8d8e80000p
-8},
8364 {0x1.fc07ef9caa76bp
-1, 0x1.6fe53b1500000p
-7},
8365 {0x1.f4465d3f6f184p
-1, 0x1.11ccce10f8000p
-5},
8366 {0x1.ecc079f84107fp
-1, 0x1.c4dfc8c8b8000p
-5},
8367 {0x1.e573a99975ae8p
-1, 0x1.3aa321e574000p
-4},
8368 {0x1.de5d6f0bd3de6p
-1, 0x1.918a0d08b8000p
-4},
8369 {0x1.d77b681ff38b3p
-1, 0x1.e72e9da044000p
-4},
8370 {0x1.d0cb5724de943p
-1, 0x1.1dcd2507f6000p
-3},
8371 {0x1.ca4b2dc0e7563p
-1, 0x1.476ab03dea000p
-3},
8372 {0x1.c3f8ee8d6cb51p
-1, 0x1.7074377e22000p
-3},
8373 {0x1.bdd2b4f020c4cp
-1, 0x1.98ede8ba94000p
-3},
8374 {0x1.b7d6c006015cap
-1, 0x1.c0db86ad2e000p
-3},
8375 {0x1.b20366e2e338fp
-1, 0x1.e840aafcee000p
-3},
8376 {0x1.ac57026295039p
-1, 0x1.0790ab4678000p
-2},
8377 {0x1.a6d01bc2731ddp
-1, 0x1.1ac056801c000p
-2},
8378 {0x1.a16d3bc3ff18bp
-1, 0x1.2db11d4fee000p
-2},
8379 {0x1.9c2d14967feadp
-1, 0x1.406464ec58000p
-2},
8380 {0x1.970e4f47c9902p
-1, 0x1.52dbe093af000p
-2},
8381 {0x1.920fb3982bcf2p
-1, 0x1.651902050d000p
-2},
8382 {0x1.8d30187f759f1p
-1, 0x1.771d2cdeaf000p
-2},
8383 {0x1.886e5ebb9f66dp
-1, 0x1.88e9c857d9000p
-2},
8384 {0x1.83c97b658b994p
-1, 0x1.9a80155e16000p
-2},
8385 {0x1.7f405ffc61022p
-1, 0x1.abe186ed3d000p
-2},
8386 {0x1.7ad22181415cap
-1, 0x1.bd0f2aea0e000p
-2},
8387 {0x1.767dcf99eff8cp
-1, 0x1.ce0a43dbf4000p
-2}
8389 static const struct {
8392 {0x1.6200012b90a8ep
-1, 0x1.904ab0644b605p
-55},
8393 {0x1.66000045734a6p
-1, 0x1.1ff9bea62f7a9p
-57},
8394 {0x1.69fffc325f2c5p
-1, 0x1.27ecfcb3c90bap
-55},
8395 {0x1.6e00038b95a04p
-1, 0x1.8ff8856739326p
-55},
8396 {0x1.71fffe09994e3p
-1, 0x1.afd40275f82b1p
-55},
8397 {0x1.7600015590e1p
-1, -0x1.2fd75b4238341p
-56},
8398 {0x1.7a00012655bd5p
-1, 0x1.808e67c242b76p
-56},
8399 {0x1.7e0003259e9a6p
-1, -0x1.208e426f622b7p
-57},
8400 {0x1.81fffedb4b2d2p
-1, -0x1.402461ea5c92fp
-55},
8401 {0x1.860002dfafcc3p
-1, 0x1.df7f4a2f29a1fp
-57},
8402 {0x1.89ffff78c6b5p
-1, -0x1.e0453094995fdp
-55},
8403 {0x1.8e00039671566p
-1, -0x1.a04f3bec77b45p
-55},
8404 {0x1.91fffe2bf1745p
-1, -0x1.7fa34400e203cp
-56},
8405 {0x1.95fffcc5c9fd1p
-1, -0x1.6ff8005a0695dp
-56},
8406 {0x1.9a0003bba4767p
-1, 0x1.0f8c4c4ec7e03p
-56},
8407 {0x1.9dfffe7b92da5p
-1, 0x1.e7fd9478c4602p
-55},
8408 {0x1.a1fffd72efdafp
-1, -0x1.a0c554dcdae7ep
-57},
8409 {0x1.a5fffde04ff95p
-1, 0x1.67da98ce9b26bp
-55},
8410 {0x1.a9fffca5e8d2bp
-1, -0x1.284c9b54c13dep
-55},
8411 {0x1.adfffddad03eap
-1, 0x1.812c8ea602e3cp
-58},
8412 {0x1.b1ffff10d3d4dp
-1, -0x1.efaddad27789cp
-55},
8413 {0x1.b5fffce21165ap
-1, 0x1.3cb1719c61237p
-58},
8414 {0x1.b9fffd950e674p
-1, 0x1.3f7d94194cep
-56},
8415 {0x1.be000139ca8afp
-1, 0x1.50ac4215d9bcp
-56},
8416 {0x1.c20005b46df99p
-1, 0x1.beea653e9c1c9p
-57},
8417 {0x1.c600040b9f7aep
-1, -0x1.c079f274a70d6p
-56},
8418 {0x1.ca0006255fd8ap
-1, -0x1.a0b4076e84c1fp
-56},
8419 {0x1.cdfffd94c095dp
-1, 0x1.8f933f99ab5d7p
-55},
8420 {0x1.d1ffff975d6cfp
-1, -0x1.82c08665fe1bep
-58},
8421 {0x1.d5fffa2561c93p
-1, -0x1.b04289bd295f3p
-56},
8422 {0x1.d9fff9d228b0cp
-1, 0x1.70251340fa236p
-55},
8423 {0x1.de00065bc7e16p
-1, -0x1.5011e16a4d80cp
-56},
8424 {0x1.e200002f64791p
-1, 0x1.9802f09ef62ep
-55},
8425 {0x1.e600057d7a6d8p
-1, -0x1.e0b75580cf7fap
-56},
8426 {0x1.ea00027edc00cp
-1, -0x1.c848309459811p
-55},
8427 {0x1.ee0006cf5cb7cp
-1, -0x1.f8027951576f4p
-55},
8428 {0x1.f2000782b7dccp
-1, -0x1.f81d97274538fp
-55},
8429 {0x1.f6000260c450ap
-1, -0x1.071002727ffdcp
-59},
8430 {0x1.f9fffe88cd533p
-1, -0x1.81bdce1fda8bp
-58},
8431 {0x1.fdfffd50f8689p
-1, 0x1.7f91acb918e6ep
-55},
8432 {0x1.0200004292367p
+0, 0x1.b7ff365324681p
-54},
8433 {0x1.05fffe3e3d668p
+0, 0x1.6fa08ddae957bp
-55},
8434 {0x1.0a0000a85a757p
+0, -0x1.7e2de80d3fb91p
-58},
8435 {0x1.0e0001a5f3fccp
+0, -0x1.1823305c5f014p
-54},
8436 {0x1.11ffff8afbaf5p
+0, -0x1.bfabb6680bac2p
-55},
8437 {0x1.15fffe54d91adp
+0, -0x1.d7f121737e7efp
-54},
8438 {0x1.1a00011ac36e1p
+0, 0x1.c000a0516f5ffp
-54},
8439 {0x1.1e00019c84248p
+0, -0x1.082fbe4da5dap
-54},
8440 {0x1.220000ffe5e6ep
+0, -0x1.8fdd04c9cfb43p
-55},
8441 {0x1.26000269fd891p
+0, 0x1.cfe2a7994d182p
-55},
8442 {0x1.2a00029a6e6dap
+0, -0x1.00273715e8bc5p
-56},
8443 {0x1.2dfffe0293e39p
+0, 0x1.b7c39dab2a6f9p
-54},
8444 {0x1.31ffff7dcf082p
+0, 0x1.df1336edc5254p
-56},
8445 {0x1.35ffff05a8b6p
+0, -0x1.e03564ccd31ebp
-54},
8446 {0x1.3a0002e0eaeccp
+0, 0x1.5f0e74bd3a477p
-56},
8447 {0x1.3e000043bb236p
+0, 0x1.c7dcb149d8833p
-54},
8448 {0x1.4200002d187ffp
+0, 0x1.e08afcf2d3d28p
-56},
8449 {0x1.460000d387cb1p
+0, 0x1.20837856599a6p
-55},
8450 {0x1.4a00004569f89p
+0, -0x1.9fa5c904fbcd2p
-55},
8451 {0x1.4e000043543f3p
+0, -0x1.81125ed175329p
-56},
8452 {0x1.51fffcc027f0fp
+0, 0x1.883d8847754dcp
-54},
8453 {0x1.55ffffd87b36fp
+0, -0x1.709e731d02807p
-55},
8454 {0x1.59ffff21df7bap
+0, 0x1.7f79f68727b02p
-55},
8455 {0x1.5dfffebfc3481p
+0, -0x1.180902e30e93ep
-54}
8458 double z
, r
, r2
, r4
, y
, invc
, logc
, kd
, hi
, lo
, t1
, t2
, t3
, p
, rhi
, rlo
;
8465 if (ix
- 0x3feea4af00000000ULL
< 0x210aa00000000ULL
) {
8466 /* Handle close to 1.0 inputs separately. */
8467 /* Fix sign of zero with downward rounding when x==1. */
8468 if (ix
== 0x3ff0000000000000ULL
)
8471 *(UINT64
*)&rhi
= *(UINT64
*)&r
& -1ULL << 32;
8473 hi
= rhi
* invln2hi
;
8474 lo
= rlo
* invln2hi
+ r
* invln2lo
;
8475 r2
= r
* r
; /* rounding error: 0x1p-62. */
8477 /* Worst-case error is less than 0.54 ULP (0.55 ULP without fma). */
8478 p
= r2
* (B
[0] + r
* B
[1]);
8481 lo
+= r4
* (B
[2] + r
* B
[3] + r2
* (B
[4] + r
* B
[5]) +
8482 r4
* (B
[6] + r
* B
[7] + r2
* (B
[8] + r
* B
[9])));
8486 if (top
- 0x0010 >= 0x7ff0 - 0x0010) {
8487 /* x < 0x1p-1022 or inf or nan. */
8492 if (ix
== 0x7ff0000000000000ULL
) /* log(inf) == inf. */
8494 if ((top
& 0x7ff0) == 0x7ff0 && (ix
& 0xfffffffffffffULL
))
8498 return (x
- x
) / (x
- x
);
8500 /* x is subnormal, normalize it. */
8506 /* x = 2^k z; where z is in range [OFF,2*OFF) and exact.
8507 The range is split into N subintervals.
8508 The ith subinterval contains z and c is near its center. */
8509 tmp
= ix
- 0x3fe6000000000000ULL
;
8510 i
= (tmp
>> (52 - 6)) % (1 << 6);
8511 k
= (INT64
)tmp
>> 52; /* arithmetic shift */
8512 iz
= ix
- (tmp
& 0xfffULL
<< 52);
8518 /* log2(x) = log2(z/c) + log2(c) + k. */
8519 /* r ~= z/c - 1, |r| < 1/(2*N). */
8520 /* rounding error: 0x1p-55/N + 0x1p-65. */
8521 r
= (z
- T2
[i
].chi
- T2
[i
].clo
) * invc
;
8522 *(UINT64
*)&rhi
= *(UINT64
*)&r
& -1ULL << 32;
8524 t1
= rhi
* invln2hi
;
8525 t2
= rlo
* invln2hi
+ r
* invln2lo
;
8527 /* hi + lo = r/ln2 + log2(c) + k. */
8530 lo
= t3
- hi
+ t1
+ t2
;
8532 /* log2(r+1) = r/ln2 + r^2*poly(r). */
8533 /* Evaluation is optimized assuming superscalar pipelined execution. */
8534 r2
= r
* r
; /* rounding error: 0x1p-54/N^2. */
8536 /* Worst-case error if |y| > 0x1p-4: 0.547 ULP (0.550 ULP without fma).
8537 ~ 0.5 + 2/N/ln2 + abs-poly-error*0x1p56 ULP (+ 0.003 ULP without fma). */
8538 p
= A
[0] + r
* A
[1] + r2
* (A
[2] + r
* A
[3]) + r4
* (A
[4] + r
* A
[5]);
8539 y
= lo
+ r2
* p
+ hi
;
8543 /*********************************************************************
8544 * log2f (MSVCR120.@)
8546 * Copied from musl: src/math/log2f.c
8548 float CDECL
log2f(float x
)
8550 static const double A
[] = {
8551 -0x1.712b6f70a7e4dp
-2,
8552 0x1.ecabf496832ep
-2,
8553 -0x1.715479ffae3dep
-1,
8556 static const struct {
8559 { 0x1.661ec79f8f3bep
+0, -0x1.efec65b963019p
-2 },
8560 { 0x1.571ed4aaf883dp
+0, -0x1.b0b6832d4fca4p
-2 },
8561 { 0x1.49539f0f010bp
+0, -0x1.7418b0a1fb77bp
-2 },
8562 { 0x1.3c995b0b80385p
+0, -0x1.39de91a6dcf7bp
-2 },
8563 { 0x1.30d190c8864a5p
+0, -0x1.01d9bf3f2b631p
-2 },
8564 { 0x1.25e227b0b8eap
+0, -0x1.97c1d1b3b7afp
-3 },
8565 { 0x1.1bb4a4a1a343fp
+0, -0x1.2f9e393af3c9fp
-3 },
8566 { 0x1.12358f08ae5bap
+0, -0x1.960cbbf788d5cp
-4 },
8567 { 0x1.0953f419900a7p
+0, -0x1.a6f9db6475fcep
-5 },
8569 { 0x1.e608cfd9a47acp
-1, 0x1.338ca9f24f53dp
-4 },
8570 { 0x1.ca4b31f026aap
-1, 0x1.476a9543891bap
-3 },
8571 { 0x1.b2036576afce6p
-1, 0x1.e840b4ac4e4d2p
-3 },
8572 { 0x1.9c2d163a1aa2dp
-1, 0x1.40645f0c6651cp
-2 },
8573 { 0x1.886e6037841edp
-1, 0x1.88e9c2c1b9ff8p
-2 },
8574 { 0x1.767dcf5534862p
-1, 0x1.ce0a44eb17bccp
-2 }
8577 double z
, r
, r2
, p
, y
, y0
, invc
, logc
;
8578 UINT32 ix
, iz
, top
, tmp
;
8582 /* Fix sign of zero with downward rounding when x==1. */
8583 if (ix
== 0x3f800000)
8585 if (ix
- 0x00800000 >= 0x7f800000 - 0x00800000) {
8586 /* x < 0x1p-126 or inf or nan. */
8591 if (ix
== 0x7f800000) /* log2(inf) == inf. */
8593 if (ix
* 2 > 0xff000000)
8595 if (ix
& 0x80000000) {
8597 return (x
- x
) / (x
- x
);
8599 /* x is subnormal, normalize it. */
8605 /* x = 2^k z; where z is in range [OFF,2*OFF] and exact.
8606 The range is split into N subintervals.
8607 The ith subinterval contains z and c is near its center. */
8608 tmp
= ix
- 0x3f330000;
8609 i
= (tmp
>> (23 - 4)) % (1 << 4);
8610 top
= tmp
& 0xff800000;
8612 k
= (INT32
)tmp
>> 23; /* arithmetic shift */
8617 /* log2(x) = log1p(z/c-1)/ln2 + log2(c) + k */
8619 y0
= logc
+ (double)k
;
8621 /* Pipelined polynomial evaluation to approximate log1p(r)/ln2. */
8623 y
= A
[1] * r
+ A
[2];
8630 /*********************************************************************
8633 double CDECL
rint(double x
)
8638 /*********************************************************************
8639 * rintf (MSVCR120.@)
8641 * Copied from musl: src/math/rintf.c
8643 float CDECL
rintf(float x
)
8645 static const float toint
= 1 / FLT_EPSILON
;
8647 unsigned int ix
= *(unsigned int*)&x
;
8648 int e
= ix
>> 23 & 0xff;
8655 y
= fp_barrierf(x
- toint
) + toint
;
8657 y
= fp_barrierf(x
+ toint
) - toint
;
8659 return s
? -0.0f
: 0.0f
;
8663 /*********************************************************************
8664 * lrint (MSVCR120.@)
8666 __msvcrt_long CDECL
lrint(double x
)
8671 if ((d
< 0 && d
!= (double)(__msvcrt_long
)d
)
8672 || (d
>= 0 && d
!= (double)(__msvcrt_ulong
)d
)) {
8679 /*********************************************************************
8680 * lrintf (MSVCR120.@)
8682 __msvcrt_long CDECL
lrintf(float x
)
8687 if ((f
< 0 && f
!= (float)(__msvcrt_long
)f
)
8688 || (f
>= 0 && f
!= (float)(__msvcrt_ulong
)f
)) {
8695 /*********************************************************************
8696 * llrint (MSVCR120.@)
8698 __int64 CDECL
llrint(double x
)
8703 if ((d
< 0 && d
!= (double)(__int64
)d
)
8704 || (d
>= 0 && d
!= (double)(unsigned __int64
)d
)) {
8711 /*********************************************************************
8712 * llrintf (MSVCR120.@)
8714 __int64 CDECL
llrintf(float x
)
8719 if ((f
< 0 && f
!= (float)(__int64
)f
)
8720 || (f
>= 0 && f
!= (float)(unsigned __int64
)f
)) {
8727 /*********************************************************************
8728 * round (MSVCR120.@)
8730 double CDECL
round(double x
)
8735 /*********************************************************************
8736 * roundf (MSVCR120.@)
8738 * Copied from musl: src/math/roundf.c
8740 float CDECL
roundf(float x
)
8742 static const float toint
= 1 / FLT_EPSILON
;
8744 unsigned int ix
= *(unsigned int*)&x
;
8745 int e
= ix
>> 23 & 0xff;
8753 return 0 * *(float*)&ix
;
8754 y
= fp_barrierf(x
+ toint
) - toint
- x
;
8757 else if (y
<= -0.5f
)
8766 /*********************************************************************
8767 * lround (MSVCR120.@)
8769 * Copied from musl: src/math/lround.c
8771 __msvcrt_long CDECL
lround(double x
)
8773 double d
= round(x
);
8774 if (d
!= (double)(__msvcrt_long
)d
) {
8781 /*********************************************************************
8782 * lroundf (MSVCR120.@)
8784 * Copied from musl: src/math/lroundf.c
8786 __msvcrt_long CDECL
lroundf(float x
)
8788 float f
= roundf(x
);
8789 if (f
!= (float)(__msvcrt_long
)f
) {
8796 /*********************************************************************
8797 * llround (MSVCR120.@)
8799 * Copied from musl: src/math/llround.c
8801 __int64 CDECL
llround(double x
)
8803 double d
= round(x
);
8804 if (d
!= (double)(__int64
)d
) {
8811 /*********************************************************************
8812 * llroundf (MSVCR120.@)
8814 * Copied from musl: src/math/llroundf.c
8816 __int64 CDECL
llroundf(float x
)
8818 float f
= roundf(x
);
8819 if (f
!= (float)(__int64
)f
) {
8826 /*********************************************************************
8827 * trunc (MSVCR120.@)
8829 * Copied from musl: src/math/trunc.c
8831 double CDECL
trunc(double x
)
8833 union {double f
; UINT64 i
;} u
= {x
};
8834 int e
= (u
.i
>> 52 & 0x7ff) - 0x3ff + 12;
8848 /*********************************************************************
8849 * truncf (MSVCR120.@)
8851 * Copied from musl: src/math/truncf.c
8853 float CDECL
truncf(float x
)
8855 union {float f
; UINT32 i
;} u
= {x
};
8856 int e
= (u
.i
>> 23 & 0xff) - 0x7f + 9;
8870 /*********************************************************************
8871 * _dtest (MSVCR120.@)
8873 short CDECL
_dtest(double *x
)
8878 /*********************************************************************
8879 * _fdtest (MSVCR120.@)
8881 short CDECL
_fdtest(float *x
)
8883 return _fdclass(*x
);
8886 static double erfc1(double x
)
8888 static const double erx
= 8.45062911510467529297e-01,
8889 pa0
= -2.36211856075265944077e-03,
8890 pa1
= 4.14856118683748331666e-01,
8891 pa2
= -3.72207876035701323847e-01,
8892 pa3
= 3.18346619901161753674e-01,
8893 pa4
= -1.10894694282396677476e-01,
8894 pa5
= 3.54783043256182359371e-02,
8895 pa6
= -2.16637559486879084300e-03,
8896 qa1
= 1.06420880400844228286e-01,
8897 qa2
= 5.40397917702171048937e-01,
8898 qa3
= 7.18286544141962662868e-02,
8899 qa4
= 1.26171219808761642112e-01,
8900 qa5
= 1.36370839120290507362e-02,
8901 qa6
= 1.19844998467991074170e-02;
8906 P
= pa0
+ s
* (pa1
+ s
* (pa2
+ s
* (pa3
+ s
* (pa4
+ s
* (pa5
+ s
* pa6
)))));
8907 Q
= 1 + s
* (qa1
+ s
* (qa2
+ s
* (qa3
+ s
* (qa4
+ s
* (qa5
+ s
* qa6
)))));
8908 return 1 - erx
- P
/ Q
;
8911 static double erfc2(UINT32 ix
, double x
)
8913 static const double ra0
= -9.86494403484714822705e-03,
8914 ra1
= -6.93858572707181764372e-01,
8915 ra2
= -1.05586262253232909814e+01,
8916 ra3
= -6.23753324503260060396e+01,
8917 ra4
= -1.62396669462573470355e+02,
8918 ra5
= -1.84605092906711035994e+02,
8919 ra6
= -8.12874355063065934246e+01,
8920 ra7
= -9.81432934416914548592e+00,
8921 sa1
= 1.96512716674392571292e+01,
8922 sa2
= 1.37657754143519042600e+02,
8923 sa3
= 4.34565877475229228821e+02,
8924 sa4
= 6.45387271733267880336e+02,
8925 sa5
= 4.29008140027567833386e+02,
8926 sa6
= 1.08635005541779435134e+02,
8927 sa7
= 6.57024977031928170135e+00,
8928 sa8
= -6.04244152148580987438e-02,
8929 rb0
= -9.86494292470009928597e-03,
8930 rb1
= -7.99283237680523006574e-01,
8931 rb2
= -1.77579549177547519889e+01,
8932 rb3
= -1.60636384855821916062e+02,
8933 rb4
= -6.37566443368389627722e+02,
8934 rb5
= -1.02509513161107724954e+03,
8935 rb6
= -4.83519191608651397019e+02,
8936 sb1
= 3.03380607434824582924e+01,
8937 sb2
= 3.25792512996573918826e+02,
8938 sb3
= 1.53672958608443695994e+03,
8939 sb4
= 3.19985821950859553908e+03,
8940 sb5
= 2.55305040643316442583e+03,
8941 sb6
= 4.74528541206955367215e+02,
8942 sb7
= -2.24409524465858183362e+01;
8947 if (ix
< 0x3ff40000) /* |x| < 1.25 */
8952 if (ix
< 0x4006db6d) { /* |x| < 1/.35 ~ 2.85714 */
8953 R
= ra0
+ s
* (ra1
+ s
* (ra2
+ s
* (ra3
+ s
* (ra4
+ s
*
8954 (ra5
+ s
* (ra6
+ s
* ra7
))))));
8955 S
= 1.0 + s
* (sa1
+ s
* (sa2
+ s
* (sa3
+ s
* (sa4
+ s
*
8956 (sa5
+ s
* (sa6
+ s
* (sa7
+ s
* sa8
)))))));
8957 } else { /* |x| > 1/.35 */
8958 R
= rb0
+ s
* (rb1
+ s
* (rb2
+ s
* (rb3
+ s
* (rb4
+ s
*
8959 (rb5
+ s
* rb6
)))));
8960 S
= 1.0 + s
* (sb1
+ s
* (sb2
+ s
* (sb3
+ s
* (sb4
+ s
*
8961 (sb5
+ s
* (sb6
+ s
* sb7
))))));
8964 iz
= *(ULONGLONG
*)&z
;
8965 iz
&= 0xffffffff00000000ULL
;
8967 return exp(-z
* z
- 0.5625) * exp((z
- x
) * (z
+ x
) + R
/ S
) / x
;
8970 /*********************************************************************
8973 double CDECL
erf(double x
)
8975 static const double efx8
= 1.02703333676410069053e+00,
8976 pp0
= 1.28379167095512558561e-01,
8977 pp1
= -3.25042107247001499370e-01,
8978 pp2
= -2.84817495755985104766e-02,
8979 pp3
= -5.77027029648944159157e-03,
8980 pp4
= -2.37630166566501626084e-05,
8981 qq1
= 3.97917223959155352819e-01,
8982 qq2
= 6.50222499887672944485e-02,
8983 qq3
= 5.08130628187576562776e-03,
8984 qq4
= 1.32494738004321644526e-04,
8985 qq5
= -3.96022827877536812320e-06;
8991 ix
= *(UINT64
*)&x
>> 32;
8994 if (ix
>= 0x7ff00000) {
8995 /* erf(nan)=nan, erf(+-inf)=+-1 */
8996 return 1 - 2 * sign
+ 1 / x
;
8998 if (ix
< 0x3feb0000) { /* |x| < 0.84375 */
8999 if (ix
< 0x3e300000) { /* |x| < 2**-28 */
9000 /* avoid underflow */
9001 return 0.125 * (8 * x
+ efx8
* x
);
9004 r
= pp0
+ z
* (pp1
+ z
* (pp2
+ z
* (pp3
+ z
* pp4
)));
9005 s
= 1.0 + z
* (qq1
+ z
* (qq2
+ z
* (qq3
+ z
* (qq4
+ z
* qq5
))));
9009 if (ix
< 0x40180000) /* 0.84375 <= |x| < 6 */
9010 y
= 1 - erfc2(ix
, x
);
9013 return sign
? -y
: y
;
9016 static float erfc1f(float x
)
9018 static const float erx
= 8.4506291151e-01,
9019 pa0
= -2.3621185683e-03,
9020 pa1
= 4.1485610604e-01,
9021 pa2
= -3.7220788002e-01,
9022 pa3
= 3.1834661961e-01,
9023 pa4
= -1.1089469492e-01,
9024 pa5
= 3.5478305072e-02,
9025 pa6
= -2.1663755178e-03,
9026 qa1
= 1.0642088205e-01,
9027 qa2
= 5.4039794207e-01,
9028 qa3
= 7.1828655899e-02,
9029 qa4
= 1.2617121637e-01,
9030 qa5
= 1.3637083583e-02,
9031 qa6
= 1.1984500103e-02;
9036 P
= pa0
+ s
* (pa1
+ s
* (pa2
+ s
* (pa3
+ s
* (pa4
+ s
* (pa5
+ s
* pa6
)))));
9037 Q
= 1 + s
* (qa1
+ s
* (qa2
+ s
* (qa3
+ s
* (qa4
+ s
* (qa5
+ s
* qa6
)))));
9038 return 1 - erx
- P
/ Q
;
9041 static float erfc2f(UINT32 ix
, float x
)
9043 static const float ra0
= -9.8649440333e-03,
9044 ra1
= -6.9385856390e-01,
9045 ra2
= -1.0558626175e+01,
9046 ra3
= -6.2375331879e+01,
9047 ra4
= -1.6239666748e+02,
9048 ra5
= -1.8460508728e+02,
9049 ra6
= -8.1287437439e+01,
9050 ra7
= -9.8143291473e+00,
9051 sa1
= 1.9651271820e+01,
9052 sa2
= 1.3765776062e+02,
9053 sa3
= 4.3456588745e+02,
9054 sa4
= 6.4538726807e+02,
9055 sa5
= 4.2900814819e+02,
9056 sa6
= 1.0863500214e+02,
9057 sa7
= 6.5702495575e+00,
9058 sa8
= -6.0424413532e-02,
9059 rb0
= -9.8649431020e-03,
9060 rb1
= -7.9928326607e-01,
9061 rb2
= -1.7757955551e+01,
9062 rb3
= -1.6063638306e+02,
9063 rb4
= -6.3756646729e+02,
9064 rb5
= -1.0250950928e+03,
9065 rb6
= -4.8351919556e+02,
9066 sb1
= 3.0338060379e+01,
9067 sb2
= 3.2579251099e+02,
9068 sb3
= 1.5367296143e+03,
9069 sb4
= 3.1998581543e+03,
9070 sb5
= 2.5530502930e+03,
9071 sb6
= 4.7452853394e+02,
9072 sb7
= -2.2440952301e+01;
9076 if (ix
< 0x3fa00000) /* |x| < 1.25 */
9081 if (ix
< 0x4036db6d) { /* |x| < 1/0.35 */
9082 R
= ra0
+ s
* (ra1
+ s
* (ra2
+ s
* (ra3
+ s
* (ra4
+ s
*
9083 (ra5
+ s
* (ra6
+ s
* ra7
))))));
9084 S
= 1.0f
+ s
* (sa1
+ s
* (sa2
+ s
* (sa3
+ s
* (sa4
+ s
*
9085 (sa5
+ s
* (sa6
+ s
* (sa7
+ s
* sa8
)))))));
9086 } else { /* |x| >= 1/0.35 */
9087 R
= rb0
+ s
* (rb1
+ s
* (rb2
+ s
* (rb3
+ s
* (rb4
+ s
* (rb5
+ s
* rb6
)))));
9088 S
= 1.0f
+ s
* (sb1
+ s
* (sb2
+ s
* (sb3
+ s
* (sb4
+ s
*
9089 (sb5
+ s
* (sb6
+ s
* sb7
))))));
9092 ix
= *(UINT32
*)&x
& 0xffffe000;
9094 return expf(-z
* z
- 0.5625f
) * expf((z
- x
) * (z
+ x
) + R
/ S
) / x
;
9097 /*********************************************************************
9100 * Copied from musl: src/math/erff.c
9102 float CDECL
erff(float x
)
9104 static const float efx8
= 1.0270333290e+00,
9105 pp0
= 1.2837916613e-01,
9106 pp1
= -3.2504209876e-01,
9107 pp2
= -2.8481749818e-02,
9108 pp3
= -5.7702702470e-03,
9109 pp4
= -2.3763017452e-05,
9110 qq1
= 3.9791721106e-01,
9111 qq2
= 6.5022252500e-02,
9112 qq3
= 5.0813062117e-03,
9113 qq4
= 1.3249473704e-04,
9114 qq5
= -3.9602282413e-06;
9123 if (ix
>= 0x7f800000) {
9124 /* erf(nan)=nan, erf(+-inf)=+-1 */
9125 return 1 - 2 * sign
+ 1 / x
;
9127 if (ix
< 0x3f580000) { /* |x| < 0.84375 */
9128 if (ix
< 0x31800000) { /* |x| < 2**-28 */
9129 /*avoid underflow */
9130 return 0.125f
* (8 * x
+ efx8
* x
);
9133 r
= pp0
+ z
* (pp1
+ z
* (pp2
+ z
* (pp3
+ z
* pp4
)));
9134 s
= 1 + z
* (qq1
+ z
* (qq2
+ z
* (qq3
+ z
* (qq4
+ z
* qq5
))));
9138 if (ix
< 0x40c00000) /* |x| < 6 */
9139 y
= 1 - erfc2f(ix
, x
);
9142 return sign
? -y
: y
;
9145 /*********************************************************************
9148 * Copied from musl: src/math/erf.c
9150 double CDECL
erfc(double x
)
9152 static const double pp0
= 1.28379167095512558561e-01,
9153 pp1
= -3.25042107247001499370e-01,
9154 pp2
= -2.84817495755985104766e-02,
9155 pp3
= -5.77027029648944159157e-03,
9156 pp4
= -2.37630166566501626084e-05,
9157 qq1
= 3.97917223959155352819e-01,
9158 qq2
= 6.50222499887672944485e-02,
9159 qq3
= 5.08130628187576562776e-03,
9160 qq4
= 1.32494738004321644526e-04,
9161 qq5
= -3.96022827877536812320e-06;
9167 ix
= *(ULONGLONG
*)&x
>> 32;
9170 if (ix
>= 0x7ff00000) {
9171 /* erfc(nan)=nan, erfc(+-inf)=0,2 */
9172 return 2 * sign
+ 1 / x
;
9174 if (ix
< 0x3feb0000) { /* |x| < 0.84375 */
9175 if (ix
< 0x3c700000) /* |x| < 2**-56 */
9178 r
= pp0
+ z
* (pp1
+ z
* (pp2
+ z
* (pp3
+ z
* pp4
)));
9179 s
= 1.0 + z
* (qq1
+ z
* (qq2
+ z
* (qq3
+ z
* (qq4
+ z
* qq5
))));
9181 if (sign
|| ix
< 0x3fd00000) { /* x < 1/4 */
9182 return 1.0 - (x
+ x
* y
);
9184 return 0.5 - (x
- 0.5 + x
* y
);
9186 if (ix
< 0x403c0000) { /* 0.84375 <= |x| < 28 */
9187 return sign
? 2 - erfc2(ix
, x
) : erfc2(ix
, x
);
9192 return fp_barrier(DBL_MIN
) * DBL_MIN
;
9195 /*********************************************************************
9196 * erfcf (MSVCR120.@)
9198 * Copied from musl: src/math/erff.c
9200 float CDECL
erfcf(float x
)
9202 static const float pp0
= 1.2837916613e-01,
9203 pp1
= -3.2504209876e-01,
9204 pp2
= -2.8481749818e-02,
9205 pp3
= -5.7702702470e-03,
9206 pp4
= -2.3763017452e-05,
9207 qq1
= 3.9791721106e-01,
9208 qq2
= 6.5022252500e-02,
9209 qq3
= 5.0813062117e-03,
9210 qq4
= 1.3249473704e-04,
9211 qq5
= -3.9602282413e-06;
9220 if (ix
>= 0x7f800000) {
9221 /* erfc(nan)=nan, erfc(+-inf)=0,2 */
9222 return 2 * sign
+ 1 / x
;
9225 if (ix
< 0x3f580000) { /* |x| < 0.84375 */
9226 if (ix
< 0x23800000) /* |x| < 2**-56 */
9229 r
= pp0
+ z
* (pp1
+ z
* (pp2
+ z
* (pp3
+ z
* pp4
)));
9230 s
= 1.0f
+ z
* (qq1
+ z
* (qq2
+ z
* (qq3
+ z
* (qq4
+ z
* qq5
))));
9232 if (sign
|| ix
< 0x3e800000) /* x < 1/4 */
9233 return 1.0f
- (x
+ x
* y
);
9234 return 0.5f
- (x
- 0.5f
+ x
* y
);
9236 if (ix
< 0x41e00000) { /* |x| < 28 */
9237 return sign
? 2 - erfc2f(ix
, x
) : erfc2f(ix
, x
);
9242 return FLT_MIN
* FLT_MIN
;
9245 /*********************************************************************
9246 * fmaxf (MSVCR120.@)
9248 float CDECL
fmaxf(float x
, float y
)
9255 return signbit(x
) ? y
: x
;
9259 /*********************************************************************
9262 double CDECL
fmax(double x
, double y
)
9269 return signbit(x
) ? y
: x
;
9273 /*********************************************************************
9274 * fdimf (MSVCR120.@)
9276 float CDECL
fdimf(float x
, float y
)
9282 return x
>y
? x
-y
: 0;
9285 /*********************************************************************
9288 double CDECL
fdim(double x
, double y
)
9294 return x
>y
? x
-y
: 0;
9297 /*********************************************************************
9298 * _fdsign (MSVCR120.@)
9300 int CDECL
_fdsign(float x
)
9302 union { float f
; UINT32 i
; } u
= { x
};
9303 return (u
.i
>> 16) & 0x8000;
9306 /*********************************************************************
9307 * _dsign (MSVCR120.@)
9309 int CDECL
_dsign(double x
)
9311 union { double f
; UINT64 i
; } u
= { x
};
9312 return (u
.i
>> 48) & 0x8000;
9316 /*********************************************************************
9317 * _dpcomp (MSVCR120.@)
9319 int CDECL
_dpcomp(double x
, double y
)
9321 if(isnan(x
) || isnan(y
))
9324 if(x
== y
) return 2;
9325 return x
< y
? 1 : 4;
9328 /*********************************************************************
9329 * _fdpcomp (MSVCR120.@)
9331 int CDECL
_fdpcomp(float x
, float y
)
9333 return _dpcomp(x
, y
);
9336 /*********************************************************************
9337 * fminf (MSVCR120.@)
9339 float CDECL
fminf(float x
, float y
)
9346 return signbit(x
) ? x
: y
;
9350 /*********************************************************************
9353 double CDECL
fmin(double x
, double y
)
9360 return signbit(x
) ? x
: y
;
9364 /*********************************************************************
9365 * asinh (MSVCR120.@)
9367 * Copied from musl: src/math/asinh.c
9369 double CDECL
asinh(double x
)
9371 UINT64 ux
= *(UINT64
*)&x
;
9372 int e
= ux
>> 52 & 0x7ff;
9376 ux
&= (UINT64
)-1 / 2;
9379 if (e
>= 0x3ff + 26) /* |x| >= 0x1p26 or inf or nan */
9380 x
= log(x
) + 0.693147180559945309417232121458176568;
9381 else if (e
>= 0x3ff + 1) /* |x| >= 2 */
9382 x
= log(2 * x
+ 1 / (sqrt(x
* x
+ 1) + x
));
9383 else if (e
>= 0x3ff - 26) /* |x| >= 0x1p-26 */
9384 x
= log1p(x
+ x
* x
/ (sqrt(x
* x
+ 1) + 1));
9385 else /* |x| < 0x1p-26, raise inexact if x != 0 */
9386 fp_barrier(x
+ 0x1p
120f
);
9390 /*********************************************************************
9391 * asinhf (MSVCR120.@)
9393 * Copied from musl: src/math/asinhf.c
9395 float CDECL
asinhf(float x
)
9397 UINT32 ux
= *(UINT32
*)&x
;
9398 UINT32 i
= ux
& 0x7fffffff;
9404 if (i
>= 0x3f800000 + (12 << 23))/* |x| >= 0x1p12 or inf or nan */
9405 x
= logf(x
) + 0.693147180559945309417232121458176568f
;
9406 else if (i
>= 0x3f800000 + (1 << 23)) /* |x| >= 2 */
9407 x
= logf(2 * x
+ 1 / (sqrtf(x
* x
+ 1) + x
));
9408 else if (i
>= 0x3f800000 - (12 << 23)) /* |x| >= 0x1p-12 */
9409 x
= log1pf(x
+ x
* x
/ (sqrtf(x
* x
+ 1) + 1));
9410 else /* |x| < 0x1p-12, raise inexact if x!=0 */
9411 fp_barrierf(x
+ 0x1p
120f
);
9415 /*********************************************************************
9416 * acosh (MSVCR120.@)
9418 * Copied from musl: src/math/acosh.c
9420 double CDECL
acosh(double x
)
9422 int e
= *(UINT64
*)&x
>> 52 & 0x7ff;
9427 feraiseexcept(FE_INVALID
);
9431 if (e
< 0x3ff + 1) /* |x| < 2, up to 2ulp error in [1,1.125] */
9432 return log1p(x
- 1 + sqrt((x
- 1) * (x
- 1) + 2 * (x
- 1)));
9433 if (e
< 0x3ff + 26) /* |x| < 0x1p26 */
9434 return log(2 * x
- 1 / (x
+ sqrt(x
* x
- 1)));
9435 /* |x| >= 0x1p26 or nan */
9436 return log(x
) + 0.693147180559945309417232121458176568;
9439 /*********************************************************************
9440 * acoshf (MSVCR120.@)
9442 * Copied from musl: src/math/acoshf.c
9444 float CDECL
acoshf(float x
)
9446 UINT32 a
= *(UINT32
*)&x
& 0x7fffffff;
9451 feraiseexcept(FE_INVALID
);
9455 if (a
< 0x3f800000 + (1 << 23)) /* |x| < 2, up to 2ulp error in [1,1.125] */
9456 return log1pf(x
- 1 + sqrtf((x
- 1) * (x
- 1) + 2 * (x
- 1)));
9457 if (*(UINT32
*)&x
< 0x3f800000 + (12 << 23)) /* 2 <= x < 0x1p12 */
9458 return logf(2 * x
- 1 / (x
+ sqrtf(x
* x
- 1)));
9459 /* x >= 0x1p12 or x <= -2 or nan */
9460 return logf(x
) + 0.693147180559945309417232121458176568f
;
9463 /*********************************************************************
9464 * atanh (MSVCR120.@)
9466 * Copied from musl: src/math/atanh.c
9468 double CDECL
atanh(double x
)
9470 UINT64 ux
= *(UINT64
*)&x
;
9471 int e
= ux
>> 52 & 0x7ff;
9475 ux
&= (UINT64
)-1 / 2;
9480 feraiseexcept(FE_INVALID
);
9484 if (e
< 0x3ff - 1) {
9485 if (e
< 0x3ff - 32) {
9486 fp_barrier(x
+ 0x1p
120f
);
9487 if (e
== 0) /* handle underflow */
9489 } else { /* |x| < 0.5, up to 1.7ulp error */
9490 x
= 0.5 * log1p(2 * x
+ 2 * x
* x
/ (1 - x
));
9492 } else { /* avoid overflow */
9493 x
= 0.5 * log1p(2 * (x
/ (1 - x
)));
9494 if (isinf(x
)) *_errno() = ERANGE
;
9499 /*********************************************************************
9500 * atanhf (MSVCR120.@)
9502 * Copied from musl: src/math/atanhf.c
9504 float CDECL
atanhf(float x
)
9506 UINT32 ux
= *(UINT32
*)&x
;
9515 feraiseexcept(FE_INVALID
);
9519 if (ux
< 0x3f800000 - (1 << 23)) {
9520 if (ux
< 0x3f800000 - (32 << 23)) {
9521 fp_barrierf(x
+ 0x1p
120f
);
9522 if (ux
< (1 << 23)) /* handle underflow */
9524 } else { /* |x| < 0.5, up to 1.7ulp error */
9525 x
= 0.5f
* log1pf(2 * x
+ 2 * x
* x
/ (1 - x
));
9527 } else { /* avoid overflow */
9528 x
= 0.5f
* log1pf(2 * (x
/ (1 - x
)));
9529 if (isinf(x
)) *_errno() = ERANGE
;
9534 #endif /* _MSVCR_VER>=120 */
9536 /*********************************************************************
9538 * scalbn (MSVCR120.@)
9539 * scalbln (MSVCR120.@)
9541 double CDECL
_scalb(double num
, __msvcrt_long power
)
9543 return ldexp(num
, power
);
9546 /*********************************************************************
9547 * _scalbf (MSVCRT.@)
9548 * scalbnf (MSVCR120.@)
9549 * scalblnf (MSVCR120.@)
9551 float CDECL
_scalbf(float num
, __msvcrt_long power
)
9553 return ldexp(num
, power
);
9558 /*********************************************************************
9559 * remainder (MSVCR120.@)
9561 * Copied from musl: src/math/remainder.c
9563 double CDECL
remainder(double x
, double y
)
9566 #if _MSVCR_VER == 120 && defined(__x86_64__)
9567 if (isnan(x
) || isnan(y
)) *_errno() = EDOM
;
9569 return remquo(x
, y
, &q
);
9572 /*********************************************************************
9573 * remainderf (MSVCR120.@)
9575 * Copied from musl: src/math/remainderf.c
9577 float CDECL
remainderf(float x
, float y
)
9580 #if _MSVCR_VER == 120 && defined(__x86_64__)
9581 if (isnan(x
) || isnan(y
)) *_errno() = EDOM
;
9583 return remquof(x
, y
, &q
);
9586 /*********************************************************************
9587 * remquo (MSVCR120.@)
9589 * Copied from musl: src/math/remquo.c
9591 double CDECL
remquo(double x
, double y
, int *quo
)
9593 UINT64 uxi
= *(UINT64
*)&x
;
9594 UINT64 uyi
= *(UINT64
*)&y
;
9595 int ex
= uxi
>> 52 & 0x7ff;
9596 int ey
= uyi
>> 52 & 0x7ff;
9603 if (y
== 0 || isinf(x
)) *_errno() = EDOM
;
9604 if (uyi
<< 1 == 0 || isnan(y
) || ex
== 0x7ff)
9605 return (x
* y
) / (x
* y
);
9609 /* normalize x and y */
9611 for (i
= uxi
<< 12; i
>> 63 == 0; ex
--, i
<<= 1);
9618 for (i
= uyi
<< 12; i
>> 63 == 0; ey
--, i
<<= 1);
9633 for (; ex
> ey
; ex
--) {
9650 for (; uxi
>> 52 == 0; uxi
<<= 1, ex
--);
9652 /* scale result and decide between |x| and |x|-|y| */
9655 uxi
|= (UINT64
)ex
<< 52;
9662 if (ex
== ey
|| (ex
+ 1 == ey
&& (2 * x
> y
|| (2 * x
== y
&& q
% 2)))) {
9667 *quo
= sx
^ sy
? -(int)q
: (int)q
;
9671 /*********************************************************************
9672 * remquof (MSVCR120.@)
9674 * Copied from musl: src/math/remquof.c
9676 float CDECL
remquof(float x
, float y
, int *quo
)
9678 UINT32 uxi
= *(UINT32
*)&x
;
9679 UINT32 uyi
= *(UINT32
*)&y
;
9680 int ex
= uxi
>> 23 & 0xff;
9681 int ey
= uyi
>> 23 & 0xff;
9687 if (y
== 0 || isinf(x
)) *_errno() = EDOM
;
9688 if (uyi
<< 1 == 0 || isnan(y
) || ex
== 0xff)
9689 return (x
* y
) / (x
* y
);
9693 /* normalize x and y */
9695 for (i
= uxi
<< 9; i
>> 31 == 0; ex
--, i
<<= 1);
9702 for (i
= uyi
<< 9; i
>> 31 == 0; ey
--, i
<<= 1);
9717 for (; ex
> ey
; ex
--) {
9734 for (; uxi
>> 23 == 0; uxi
<<= 1, ex
--);
9736 /* scale result and decide between |x| and |x|-|y| */
9739 uxi
|= (UINT32
)ex
<< 23;
9746 if (ex
== ey
|| (ex
+ 1 == ey
&& (2 * x
> y
|| (2 * x
== y
&& q
% 2)))) {
9751 *quo
= sx
^ sy
? -(int)q
: (int)q
;
9755 /* sin(pi*x) assuming x > 2^-100, if sin(pi*x)==0 the sign is arbitrary */
9756 static double sin_pi(double x
)
9760 /* spurious inexact if odd int */
9761 x
= 2.0 * (x
* 0.5 - floor(x
* 0.5)); /* x mod 2.0 */
9769 default: /* case 4: */
9770 case 0: return __sin(x
, 0.0, 0);
9771 case 1: return __cos(x
, 0.0);
9772 case 2: return __sin(-x
, 0.0, 0);
9773 case 3: return -__cos(x
, 0.0);
9777 /*********************************************************************
9778 * lgamma (MSVCR120.@)
9780 * Copied from musl: src/math/lgamma_r.c
9782 double CDECL
lgamma(double x
)
9784 static const double pi
= 3.14159265358979311600e+00,
9785 a0
= 7.72156649015328655494e-02,
9786 a1
= 3.22467033424113591611e-01,
9787 a2
= 6.73523010531292681824e-02,
9788 a3
= 2.05808084325167332806e-02,
9789 a4
= 7.38555086081402883957e-03,
9790 a5
= 2.89051383673415629091e-03,
9791 a6
= 1.19270763183362067845e-03,
9792 a7
= 5.10069792153511336608e-04,
9793 a8
= 2.20862790713908385557e-04,
9794 a9
= 1.08011567247583939954e-04,
9795 a10
= 2.52144565451257326939e-05,
9796 a11
= 4.48640949618915160150e-05,
9797 tc
= 1.46163214496836224576e+00,
9798 tf
= -1.21486290535849611461e-01,
9799 tt
= -3.63867699703950536541e-18,
9800 t0
= 4.83836122723810047042e-01,
9801 t1
= -1.47587722994593911752e-01,
9802 t2
= 6.46249402391333854778e-02,
9803 t3
= -3.27885410759859649565e-02,
9804 t4
= 1.79706750811820387126e-02,
9805 t5
= -1.03142241298341437450e-02,
9806 t6
= 6.10053870246291332635e-03,
9807 t7
= -3.68452016781138256760e-03,
9808 t8
= 2.25964780900612472250e-03,
9809 t9
= -1.40346469989232843813e-03,
9810 t10
= 8.81081882437654011382e-04,
9811 t11
= -5.38595305356740546715e-04,
9812 t12
= 3.15632070903625950361e-04,
9813 t13
= -3.12754168375120860518e-04,
9814 t14
= 3.35529192635519073543e-04,
9815 u0
= -7.72156649015328655494e-02,
9816 u1
= 6.32827064025093366517e-01,
9817 u2
= 1.45492250137234768737e+00,
9818 u3
= 9.77717527963372745603e-01,
9819 u4
= 2.28963728064692451092e-01,
9820 u5
= 1.33810918536787660377e-02,
9821 v1
= 2.45597793713041134822e+00,
9822 v2
= 2.12848976379893395361e+00,
9823 v3
= 7.69285150456672783825e-01,
9824 v4
= 1.04222645593369134254e-01,
9825 v5
= 3.21709242282423911810e-03,
9826 s0
= -7.72156649015328655494e-02,
9827 s1
= 2.14982415960608852501e-01,
9828 s2
= 3.25778796408930981787e-01,
9829 s3
= 1.46350472652464452805e-01,
9830 s4
= 2.66422703033638609560e-02,
9831 s5
= 1.84028451407337715652e-03,
9832 s6
= 3.19475326584100867617e-05,
9833 r1
= 1.39200533467621045958e+00,
9834 r2
= 7.21935547567138069525e-01,
9835 r3
= 1.71933865632803078993e-01,
9836 r4
= 1.86459191715652901344e-02,
9837 r5
= 7.77942496381893596434e-04,
9838 r6
= 7.32668430744625636189e-06,
9839 w0
= 4.18938533204672725052e-01,
9840 w1
= 8.33333333333329678849e-02,
9841 w2
= -2.77777777728775536470e-03,
9842 w3
= 7.93650558643019558500e-04,
9843 w4
= -5.95187557450339963135e-04,
9844 w5
= 8.36339918996282139126e-04,
9845 w6
= -1.63092934096575273989e-03;
9847 union {double f
; UINT64 i
;} u
= {x
};
9848 double t
, y
, z
, nadj
, p
, p1
, p2
, p3
, q
, r
, w
;
9852 /* purge off +-inf, NaN, +-0, tiny and negative arguments */
9854 ix
= u
.i
>> 32 & 0x7fffffff;
9855 if (ix
>= 0x7ff00000)
9857 if (ix
< (0x3ff - 70) << 20) { /* |x|<2**-70, return -log(|x|) */
9865 if (t
== 0.0) { /* -integer */
9867 return 1.0 / (x
- x
);
9871 nadj
= log(pi
/ (t
* x
));
9874 /* purge off 1 and 2 */
9875 if ((ix
== 0x3ff00000 || ix
== 0x40000000) && (UINT32
)u
.i
== 0)
9878 else if (ix
< 0x40000000) {
9879 if (ix
<= 0x3feccccc) { /* lgamma(x) = lgamma(x+1)-log(x) */
9881 if (ix
>= 0x3FE76944) {
9884 } else if (ix
>= 0x3FCDA661) {
9893 if (ix
>= 0x3FFBB4C3) { /* [1.7316,2] */
9896 } else if(ix
>= 0x3FF3B4C4) { /* [1.23,1.73] */
9907 p1
= a0
+ z
* (a2
+ z
* (a4
+ z
* (a6
+ z
* (a8
+ z
* a10
))));
9908 p2
= z
* (a1
+ z
* (a3
+ z
* (a5
+ z
* (a7
+ z
* (a9
+ z
* a11
)))));
9915 p1
= t0
+ w
* (t3
+ w
* (t6
+ w
* (t9
+ w
* t12
))); /* parallel comp */
9916 p2
= t1
+ w
* (t4
+ w
* (t7
+ w
* (t10
+ w
* t13
)));
9917 p3
= t2
+ w
* (t5
+ w
* (t8
+ w
* (t11
+ w
* t14
)));
9918 p
= z
* p1
- (tt
- w
* (p2
+ y
* p3
));
9922 p1
= y
* (u0
+ y
* (u1
+ y
* (u2
+ y
* (u3
+ y
* (u4
+ y
* u5
)))));
9923 p2
= 1.0 + y
* (v1
+ y
* (v2
+ y
* (v3
+ y
* (v4
+ y
* v5
))));
9924 r
+= -0.5 * y
+ p1
/ p2
;
9926 } else if (ix
< 0x40200000) { /* x < 8.0 */
9929 p
= y
* (s0
+ y
* (s1
+ y
* (s2
+ y
* (s3
+ y
* (s4
+ y
* (s5
+ y
* s6
))))));
9930 q
= 1.0 + y
* (r1
+ y
* (r2
+ y
* (r3
+ y
* (r4
+ y
* (r5
+ y
* r6
)))));
9931 r
= 0.5 * y
+ p
/ q
;
9932 z
= 1.0; /* lgamma(1+s) = log(s) + lgamma(s) */
9934 case 7: z
*= y
+ 6.0; /* fall through */
9935 case 6: z
*= y
+ 5.0; /* fall through */
9936 case 5: z
*= y
+ 4.0; /* fall through */
9937 case 4: z
*= y
+ 3.0; /* fall through */
9943 } else if (ix
< 0x43900000) { /* 8.0 <= x < 2**58 */
9947 w
= w0
+ z
* (w1
+ y
* (w2
+ y
* (w3
+ y
* (w4
+ y
* (w5
+ y
* w6
)))));
9948 r
= (x
- 0.5) * (t
- 1.0) + w
;
9949 } else /* 2**58 <= x <= inf */
9950 r
= x
* (log(x
) - 1.0);
9956 /* sin(pi*x) assuming x > 2^-100, if sin(pi*x)==0 the sign is arbitrary */
9957 static float sinf_pi(float x
)
9962 /* spurious inexact if odd int */
9963 x
= 2 * (x
* 0.5f
- floorf(x
* 0.5f
)); /* x mod 2.0 */
9970 default: /* case 4: */
9971 case 0: return __sindf(y
);
9972 case 1: return __cosdf(y
);
9973 case 2: return __sindf(-y
);
9974 case 3: return -__cosdf(y
);
9978 /*********************************************************************
9979 * lgammaf (MSVCR120.@)
9981 * Copied from musl: src/math/lgammaf_r.c
9983 float CDECL
lgammaf(float x
)
9985 static const float pi
= 3.1415927410e+00,
9986 a0
= 7.7215664089e-02,
9987 a1
= 3.2246702909e-01,
9988 a2
= 6.7352302372e-02,
9989 a3
= 2.0580807701e-02,
9990 a4
= 7.3855509982e-03,
9991 a5
= 2.8905137442e-03,
9992 a6
= 1.1927076848e-03,
9993 a7
= 5.1006977446e-04,
9994 a8
= 2.2086278477e-04,
9995 a9
= 1.0801156895e-04,
9996 a10
= 2.5214456400e-05,
9997 a11
= 4.4864096708e-05,
9998 tc
= 1.4616321325e+00,
9999 tf
= -1.2148628384e-01,
10000 tt
= 6.6971006518e-09,
10001 t0
= 4.8383611441e-01,
10002 t1
= -1.4758771658e-01,
10003 t2
= 6.4624942839e-02,
10004 t3
= -3.2788541168e-02,
10005 t4
= 1.7970675603e-02,
10006 t5
= -1.0314224288e-02,
10007 t6
= 6.1005386524e-03,
10008 t7
= -3.6845202558e-03,
10009 t8
= 2.2596477065e-03,
10010 t9
= -1.4034647029e-03,
10011 t10
= 8.8108185446e-04,
10012 t11
= -5.3859531181e-04,
10013 t12
= 3.1563205994e-04,
10014 t13
= -3.1275415677e-04,
10015 t14
= 3.3552918467e-04,
10016 u0
= -7.7215664089e-02,
10017 u1
= 6.3282704353e-01,
10018 u2
= 1.4549225569e+00,
10019 u3
= 9.7771751881e-01,
10020 u4
= 2.2896373272e-01,
10021 u5
= 1.3381091878e-02,
10022 v1
= 2.4559779167e+00,
10023 v2
= 2.1284897327e+00,
10024 v3
= 7.6928514242e-01,
10025 v4
= 1.0422264785e-01,
10026 v5
= 3.2170924824e-03,
10027 s0
= -7.7215664089e-02,
10028 s1
= 2.1498242021e-01,
10029 s2
= 3.2577878237e-01,
10030 s3
= 1.4635047317e-01,
10031 s4
= 2.6642270386e-02,
10032 s5
= 1.8402845599e-03,
10033 s6
= 3.1947532989e-05,
10034 r1
= 1.3920053244e+00,
10035 r2
= 7.2193557024e-01,
10036 r3
= 1.7193385959e-01,
10037 r4
= 1.8645919859e-02,
10038 r5
= 7.7794247773e-04,
10039 r6
= 7.3266842264e-06,
10040 w0
= 4.1893854737e-01,
10041 w1
= 8.3333335817e-02,
10042 w2
= -2.7777778450e-03,
10043 w3
= 7.9365057172e-04,
10044 w4
= -5.9518753551e-04,
10045 w5
= 8.3633989561e-04,
10046 w6
= -1.6309292987e-03;
10048 union {float f
; UINT32 i
;} u
= {x
};
10049 float t
, y
, z
, nadj
, p
, p1
, p2
, p3
, q
, r
, w
;
10053 /* purge off +-inf, NaN, +-0, tiny and negative arguments */
10055 ix
= u
.i
& 0x7fffffff;
10056 if (ix
>= 0x7f800000)
10058 if (ix
< 0x35000000) { /* |x| < 2**-21, return -log(|x|) */
10066 if (t
== 0.0f
) { /* -integer */
10067 *_errno() = ERANGE
;
10068 return 1.0f
/ (x
- x
);
10072 nadj
= logf(pi
/ (t
* x
));
10075 /* purge off 1 and 2 */
10076 if (ix
== 0x3f800000 || ix
== 0x40000000)
10079 else if (ix
< 0x40000000) {
10080 if (ix
<= 0x3f666666) { /* lgamma(x) = lgamma(x+1)-log(x) */
10082 if (ix
>= 0x3f3b4a20) {
10085 } else if (ix
>= 0x3e6d3308) {
10086 y
= x
- (tc
- 1.0f
);
10094 if (ix
>= 0x3fdda618) { /* [1.7316,2] */
10097 } else if (ix
>= 0x3F9da620) { /* [1.23,1.73] */
10108 p1
= a0
+ z
* (a2
+ z
* (a4
+ z
* (a6
+ z
* (a8
+ z
* a10
))));
10109 p2
= z
* (a1
+ z
* (a3
+ z
* (a5
+ z
* (a7
+ z
* (a9
+ z
* a11
)))));
10116 p1
= t0
+ w
* (t3
+ w
* (t6
+ w
* (t9
+ w
* t12
))); /* parallel comp */
10117 p2
= t1
+ w
* (t4
+ w
* (t7
+ w
* (t10
+ w
* t13
)));
10118 p3
= t2
+ w
* (t5
+ w
* (t8
+ w
* (t11
+ w
* t14
)));
10119 p
= z
* p1
- (tt
- w
* (p2
+ y
* p3
));
10123 p1
= y
* (u0
+ y
* (u1
+ y
* (u2
+ y
* (u3
+ y
* (u4
+ y
* u5
)))));
10124 p2
= 1.0f
+ y
* (v1
+ y
* (v2
+ y
* (v3
+ y
* (v4
+ y
* v5
))));
10125 r
+= -0.5f
* y
+ p1
/ p2
;
10127 } else if (ix
< 0x41000000) { /* x < 8.0 */
10130 p
= y
* (s0
+ y
* (s1
+ y
* (s2
+ y
* (s3
+ y
* (s4
+ y
* (s5
+ y
* s6
))))));
10131 q
= 1.0f
+ y
* (r1
+ y
* (r2
+ y
* (r3
+ y
* (r4
+ y
* (r5
+ y
* r6
)))));
10132 r
= 0.5f
* y
+ p
/ q
;
10133 z
= 1.0f
; /* lgamma(1+s) = log(s) + lgamma(s) */
10135 case 7: z
*= y
+ 6.0f
; /* fall through */
10136 case 6: z
*= y
+ 5.0f
; /* fall through */
10137 case 5: z
*= y
+ 4.0f
; /* fall through */
10138 case 4: z
*= y
+ 3.0f
; /* fall through */
10144 } else if (ix
< 0x5c800000) { /* 8.0 <= x < 2**58 */
10148 w
= w0
+ z
* (w1
+ y
* (w2
+ y
* (w3
+ y
* (w4
+ y
* (w5
+ y
* w6
)))));
10149 r
= (x
- 0.5f
) * (t
- 1.0f
) + w
;
10150 } else /* 2**58 <= x <= inf */
10151 r
= x
* (logf(x
) - 1.0f
);
10157 static double tgamma_S(double x
)
10159 static const double Snum
[] = {
10160 23531376880.410759688572007674451636754734846804940,
10161 42919803642.649098768957899047001988850926355848959,
10162 35711959237.355668049440185451547166705960488635843,
10163 17921034426.037209699919755754458931112671403265390,
10164 6039542586.3520280050642916443072979210699388420708,
10165 1439720407.3117216736632230727949123939715485786772,
10166 248874557.86205415651146038641322942321632125127801,
10167 31426415.585400194380614231628318205362874684987640,
10168 2876370.6289353724412254090516208496135991145378768,
10169 186056.26539522349504029498971604569928220784236328,
10170 8071.6720023658162106380029022722506138218516325024,
10171 210.82427775157934587250973392071336271166969580291,
10172 2.5066282746310002701649081771338373386264310793408,
10174 static const double Sden
[] = {
10175 0, 39916800, 120543840, 150917976, 105258076, 45995730, 13339535,
10176 2637558, 357423, 32670, 1925, 66, 1,
10179 double num
= 0, den
= 0;
10182 /* to avoid overflow handle large x differently */
10184 for (i
= ARRAY_SIZE(Snum
) - 1; i
>= 0; i
--) {
10185 num
= num
* x
+ Snum
[i
];
10186 den
= den
* x
+ Sden
[i
];
10189 for (i
= 0; i
< ARRAY_SIZE(Snum
); i
++) {
10190 num
= num
/ x
+ Snum
[i
];
10191 den
= den
/ x
+ Sden
[i
];
10196 /*********************************************************************
10197 * tgamma (MSVCR120.@)
10199 * Copied from musl: src/math/tgamma.c
10201 double CDECL
tgamma(double x
)
10203 static const double gmhalf
= 5.524680040776729583740234375;
10204 static const double fact
[] = {
10205 1, 1, 2, 6, 24, 120, 720, 5040.0, 40320.0, 362880.0, 3628800.0, 39916800.0,
10206 479001600.0, 6227020800.0, 87178291200.0, 1307674368000.0, 20922789888000.0,
10207 355687428096000.0, 6402373705728000.0, 121645100408832000.0,
10208 2432902008176640000.0, 51090942171709440000.0, 1124000727777607680000.0,
10211 union {double f
; UINT64 i
;} u
= {x
};
10212 double absx
, y
, dy
, z
, r
;
10213 UINT32 ix
= u
.i
>> 32 & 0x7fffffff;
10214 int sign
= u
.i
>> 63;
10216 /* special cases */
10217 if (ix
>= 0x7ff00000) {
10218 /* tgamma(nan)=nan, tgamma(inf)=inf, tgamma(-inf)=nan with invalid */
10219 if (u
.i
== 0xfff0000000000000ULL
)
10221 return x
+ INFINITY
;
10223 if (ix
< (0x3ff - 54) << 20) {
10224 /* |x| < 2^-54: tgamma(x) ~ 1/x, +-0 raises div-by-zero */
10226 *_errno() = ERANGE
;
10230 /* integer arguments */
10231 /* raise inexact when non-integer */
10232 if (x
== floor(x
)) {
10235 return 0 / (x
- x
);
10237 if (x
<= ARRAY_SIZE(fact
))
10238 return fact
[(int)x
- 1];
10241 /* x >= 172: tgamma(x)=inf with overflow */
10242 /* x =< -184: tgamma(x)=+-0 with underflow */
10243 if (ix
>= 0x40670000) { /* |x| >= 184 */
10244 *_errno() = ERANGE
;
10246 fp_barrierf(0x1p
-126 / x
);
10253 absx
= sign
? -x
: x
;
10255 /* handle the error of x + g - 0.5 */
10257 if (absx
> gmhalf
) {
10266 r
= tgamma_S(absx
) * exp(-y
);
10268 /* reflection formula for negative x */
10269 /* sinpi(absx) is not 0, integers are already handled */
10270 r
= -M_PI
/ (sin_pi(absx
) * absx
* r
);
10274 r
+= dy
* (gmhalf
+ 0.5) * r
/ y
;
10275 z
= pow(y
, 0.5 * z
);
10280 /*********************************************************************
10281 * tgammaf (MSVCR120.@)
10283 * Copied from musl: src/math/tgammaf.c
10285 float CDECL
tgammaf(float x
)
10290 /*********************************************************************
10293 double CDECL
nan(const char *tagp
)
10295 /* Windows ignores input (MSDN) */
10299 /*********************************************************************
10300 * nanf (MSVCR120.@)
10302 float CDECL
nanf(const char *tagp
)
10307 /*********************************************************************
10308 * _except1 (MSVCR120.@)
10310 * - find meaning of ignored cw and operation bits
10313 double CDECL
_except1(DWORD fpe
, _FP_OPERATION_CODE op
, double arg
, double res
, DWORD cw
, void *unk
)
10315 ULONG_PTR exception_arg
;
10316 DWORD exception
= 0;
10317 unsigned int fpword
= 0;
10321 TRACE("(%lx %x %lf %lf %lx %p)\n", fpe
, op
, arg
, res
, cw
, unk
);
10324 cw
= ((cw
>> 7) & 0x3f) | ((cw
>> 3) & 0xc00);
10326 operation
= op
<< 5;
10327 exception_arg
= (ULONG_PTR
)&operation
;
10329 if (fpe
& 0x1) { /* overflow */
10330 if ((fpe
== 0x1 && (cw
& 0x8)) || (fpe
==0x11 && (cw
& 0x28))) {
10331 /* 32-bit version also sets SW_INEXACT here */
10332 raise
|= FE_OVERFLOW
;
10333 if (fpe
& 0x10) raise
|= FE_INEXACT
;
10334 res
= signbit(res
) ? -INFINITY
: INFINITY
;
10336 exception
= EXCEPTION_FLT_OVERFLOW
;
10338 } else if (fpe
& 0x2) { /* underflow */
10339 if ((fpe
== 0x2 && (cw
& 0x10)) || (fpe
==0x12 && (cw
& 0x30))) {
10340 raise
|= FE_UNDERFLOW
;
10341 if (fpe
& 0x10) raise
|= FE_INEXACT
;
10342 res
= signbit(res
) ? -0.0 : 0.0;
10344 exception
= EXCEPTION_FLT_UNDERFLOW
;
10346 } else if (fpe
& 0x4) { /* zerodivide */
10347 if ((fpe
== 0x4 && (cw
& 0x4)) || (fpe
==0x14 && (cw
& 0x24))) {
10348 raise
|= FE_DIVBYZERO
;
10349 if (fpe
& 0x10) raise
|= FE_INEXACT
;
10351 exception
= EXCEPTION_FLT_DIVIDE_BY_ZERO
;
10353 } else if (fpe
& 0x8) { /* invalid */
10354 if (fpe
== 0x8 && (cw
& 0x1)) {
10355 raise
|= FE_INVALID
;
10357 exception
= EXCEPTION_FLT_INVALID_OPERATION
;
10359 } else if (fpe
& 0x10) { /* inexact */
10360 if (fpe
== 0x10 && (cw
& 0x20)) {
10361 raise
|= FE_INEXACT
;
10363 exception
= EXCEPTION_FLT_INEXACT_RESULT
;
10369 feraiseexcept(raise
);
10371 RaiseException(exception
, 0, 1, &exception_arg
);
10373 if (cw
& 0x1) fpword
|= _EM_INVALID
;
10374 if (cw
& 0x2) fpword
|= _EM_DENORMAL
;
10375 if (cw
& 0x4) fpword
|= _EM_ZERODIVIDE
;
10376 if (cw
& 0x8) fpword
|= _EM_OVERFLOW
;
10377 if (cw
& 0x10) fpword
|= _EM_UNDERFLOW
;
10378 if (cw
& 0x20) fpword
|= _EM_INEXACT
;
10379 switch (cw
& 0xc00)
10381 case 0xc00: fpword
|= _RC_UP
|_RC_DOWN
; break;
10382 case 0x800: fpword
|= _RC_UP
; break;
10383 case 0x400: fpword
|= _RC_DOWN
; break;
10385 switch (cw
& 0x300)
10387 case 0x0: fpword
|= _PC_24
; break;
10388 case 0x200: fpword
|= _PC_53
; break;
10389 case 0x300: fpword
|= _PC_64
; break;
10391 if (cw
& 0x1000) fpword
|= _IC_AFFINE
;
10392 _setfp(&fpword
, _MCW_EM
| _MCW_RC
| _MCW_PC
| _MCW_IC
, NULL
, 0);
10397 _Dcomplex
* CDECL
_Cbuild(_Dcomplex
*ret
, double r
, double i
)
10404 double CDECL
MSVCR120_creal(_Dcomplex z
)
10409 /*********************************************************************
10410 * ilogb (MSVCR120.@)
10412 int CDECL
ilogb(double x
)
10417 /*********************************************************************
10418 * ilogbf (MSVCR120.@)
10420 int CDECL
ilogbf(float x
)
10422 return __ilogbf(x
);
10424 #endif /* _MSVCR_VER>=120 */