3 #if defined(__MINGW32__) && A_PREREQ_GNUC(3, 0)
4 #pragma GCC diagnostic ignored "-Wfloat-conversion"
5 #endif /* __MINGW32__ */
6 #if A_PREREQ_GNUC(3, 0) || __has_warning("-Wfloat-equal")
7 #pragma GCC diagnostic ignored "-Wfloat-equal"
8 #endif /* -Wfloat-equal */
9 #if A_PREREQ_MSVC(19, 30)
10 #pragma warning(disable : 5250)
11 #endif /* msvc 17.0+ */
13 static A_INLINE a_float
polevl(a_float
const *p
, a_size n
, a_float x
)
22 a_f32
a_f32_rsqrt(a_f32 x
)
25 return 1 / a_f32_sqrt(x
);
35 a_f32 xh
= A_F32_C(0.5) * x
;
36 u
.u
= A_U32_C(0x5F375A86) - (u
.u
>> 1);
37 u
.x
*= A_F32_C(1.5) - u
.x
* u
.x
* xh
;
38 u
.x
*= A_F32_C(1.5) - u
.x
* u
.x
* xh
;
52 a_f64
a_f64_rsqrt(a_f64 x
)
55 return 1 / a_f64_sqrt(x
);
65 a_f64 xh
= A_F64_C(0.5) * x
;
66 u
.u
= A_U64_C(0x5FE6EC85E7DE30DA) - (u
.u
>> 1);
67 u
.x
*= A_F64_C(1.5) - u
.x
* u
.x
* xh
;
68 u
.x
*= A_F64_C(1.5) - u
.x
* u
.x
* xh
;
82 #if (__has_builtin(__builtin_clz) || A_PREREQ_GNUC(3, 4)) && (ULONG_MAX == A_U32_MAX)
83 #define A_U32_BSR(x) (31 - __builtin_clzl(x))
84 #elif __has_builtin(__builtin_clz) || A_PREREQ_GNUC(3, 4)
85 #define A_U32_BSR(x) (31 - __builtin_clz(x))
86 #elif defined(_MSC_VER)
87 #pragma intrinsic(_BitScanReverse)
88 #define A_U32_BSR(x) BitScanReverse(x)
89 static A_INLINE
int A_U32_BSR(a_u32 x
)
92 _BitScanReverse(&i
, x
);
95 #endif /* A_U32_BSR */
97 a_u16
a_u32_sqrt(a_u32 x
)
99 #if defined(A_U32_BSR) /* Newton's method */
101 if (x
<= 1) { return (a_u16
)x
; }
102 x1
<<= (A_U32_BSR(x
) + 1) >> 1;
105 x1
= (x0
+ x
/ x0
) >> 1;
108 #else /* Digit-by-digit */
109 a_u32 a
, b
= 1, y
= 0;
110 for (b
<<= sizeof(b
) * 8 - 2; b
> x
; b
>>= 2) {}
125 #if (__has_builtin(__builtin_clz) || A_PREREQ_GNUC(3, 4)) && (ULONG_MAX == A_U32_MAX)
126 #define A_U64_BSR(x) (63 - __builtin_clzll(x))
127 #elif __has_builtin(__builtin_clz) || A_PREREQ_GNUC(3, 4)
128 #define A_U64_BSR(x) (63 - __builtin_clzl(x))
129 #elif defined(_MSC_VER) && defined(_WIN64)
130 #pragma intrinsic(_BitScanReverse64)
131 #define A_U64_BSR(x) BitScanReverse64(x)
132 static A_INLINE
int A_U64_BSR(a_u64 x
)
135 _BitScanReverse64(&i
, x
);
138 #elif defined(_MSC_VER)
139 #define A_U64_BSR(x) BitScanReverse64(x)
140 static A_INLINE
int A_U64_BSR(a_u64 x
)
142 unsigned long i
= 0, hi
;
143 if (_BitScanReverse(&hi
, x
>> 32))
147 _BitScanReverse(&i
, (a_u32
)x
);
150 #endif /* A_U64_BSR */
152 a_u32
a_u64_sqrt(a_u64 x
)
154 #if defined(A_U64_BSR) /* Newton's method */
156 if (x
<= 1) { return (a_u32
)x
; }
157 x1
<<= (A_U64_BSR(x
) + 1) >> 1;
160 x1
= (x0
+ x
/ x0
) >> 1;
163 #else /* Digit-by-digit */
164 a_u64 a
, b
= 1, y
= 0;
165 for (b
<<= sizeof(b
) * 8 - 2; b
> x
; b
>>= 2) {}
181 a_float
a_float_log1p(a_float x
)
183 a_float
volatile a
= x
+ 1;
184 a_float y
= a_float_log(a
);
185 if (x
< A_FLOAT_EPSILON
&& a
> 0)
187 a_float
volatile b
= a
- 1;
194 a_float
a_float_expm1(a_float x
)
196 static a_float
const P
[] = {
197 A_FLOAT_C(1.2617719307481059087798E-4),
198 A_FLOAT_C(3.0299440770744196129956E-2),
199 A_FLOAT_C(9.9999999999999999991025E-1),
201 static a_float
const Q
[] = {
202 A_FLOAT_C(3.0019850513866445504159E-6),
203 A_FLOAT_C(2.5244834034968410419224E-3),
204 A_FLOAT_C(2.2726554820815502876593E-1),
205 A_FLOAT_C(2.0000000000000000000897E-0),
210 if (isnan(x
) || x
> 0) { return x
; }
213 if (x
< -A_FLOAT_C(0.5) || x
> A_FLOAT_C(0.5))
215 return a_float_exp(x
) - 1;
218 y
= polevl(P
, A_LEN(P
) - 1, xx
) * x
;
219 y
/= polevl(Q
, A_LEN(Q
) - 1, xx
) - y
;
224 a_float
a_float_atan2(a_float x
, a_float y
)
226 if (x
> 0) { return a_float_atan(y
/ x
); }
229 if (y
>= 0) { return a_float_atan(y
/ x
) + A_FLOAT_PI
; }
230 return a_float_atan(y
/ x
) - A_FLOAT_PI
;
232 if (y
> 0) { return +A_FLOAT_PI
; }
233 if (y
< 0) { return -A_FLOAT_PI
; }
238 a_float
a_float_hypot(a_float x
, a_float y
)
240 a_float
const a
= a_float_abs(x
);
241 a_float
const b
= a_float_abs(y
);
242 if (isinf(x
) || isinf(y
))
257 return a_float_sqrt(x
* x
+ 1) * y
;
260 a_float
a_float_hypot3(a_float x
, a_float y
, a_float z
)
262 a_float
const a
= a_float_abs(x
);
263 a_float
const b
= a_float_abs(y
);
264 a_float
const c
= a_float_abs(z
);
266 if (isinf(x
) || isinf(y
) || isinf(z
))
270 if (w
< b
) { w
= b
; }
271 if (w
< c
) { w
= c
; }
272 if (w
== 0) { return 0; }
276 return a_float_sqrt(x
* x
+ y
* y
+ z
* z
) * w
;