13 inline constexpr auto nan_mix(
auto x,
auto y)
noexcept {
return ((x + 0.0L) + (y + 0)); }
15 template <
typename A,
typename B>
16 constexpr void extract_words(A& high, B& low,
double d)
noexcept
18 low = std::bit_cast<uint64_t>(d) & 0xFFFFFFFF;
19 high = (std::bit_cast<uint64_t>(d) >> 32LL) & 0xFFFFFFFF;
23 constexpr void get_high_word(A& high,
double d)
noexcept
25 high = (std::bit_cast<uint64_t>(d) >> 32LL) & 0xFFFFFFFF;
29 constexpr void get_low_word(A& low,
double d)
noexcept
31 low = std::bit_cast<uint64_t>(d) & 0xFFFFFFFF;
34 template <
typename A,
typename B>
35 constexpr void insert_words(
double& d, A high, B low)
noexcept
37 const auto bits =
static_cast<uint64_t
>(std::bit_cast<uint32_t>(low)) | (
static_cast<uint64_t
>(std::bit_cast<uint32_t>(high)) << 32ULL);
38 d = std::bit_cast<double>(bits);
42 constexpr void set_high_word(
double& d, A i)
noexcept
44 uint32_t low = 0, high = 0;
45 ::ghassanpl::cem::detail::extract_words(high, low, d);
46 ::ghassanpl::cem::detail::insert_words(d, i, low);
50 constexpr void set_low_word(
double& d, A i)
noexcept
52 uint32_t low = 0, high = 0;
53 ::ghassanpl::cem::detail::extract_words(high, low, d);
54 ::ghassanpl::cem::detail::insert_words(d, high, i);
57 static constexpr double bp[] = { 1.0, 1.5 };
58 static constexpr double dp_h[] = { 0.0, 5.84962487220764160156e-01 };
59 static constexpr double dp_l[] = { 0.0, 1.35003920212974897128e-08 };
60 static constexpr double zero = 0.0;
61 static constexpr double half = 0.5;
62 static constexpr double qrtr = 0.25;
63 static constexpr double thrd = 3.3333333333333331e-01;
64 static constexpr double one = 1.0;
65 static constexpr double two = 2.0;
66 static constexpr double two53 = 9007199254740992.0;
67 static constexpr double huge = 1.0e300;
68 static constexpr double tiny = 1.0e-300;
69 static constexpr double L1 = 5.99999999999994648725e-01;
70 static constexpr double L2 = 4.28571428578550184252e-01;
71 static constexpr double L3 = 3.33333329818377432918e-01;
72 static constexpr double L4 = 2.72728123808534006489e-01;
73 static constexpr double L5 = 2.30660745775561754067e-01;
74 static constexpr double L6 = 2.06975017800338417784e-01;
75 static constexpr double P1 = 1.66666666666666019037e-01;
76 static constexpr double P2 = -2.77777777770155933842e-03;
77 static constexpr double P3 = 6.61375632143793436117e-05;
78 static constexpr double P4 = -1.65339022054652515390e-06;
79 static constexpr double P5 = 4.13813679705723846039e-08;
80 static constexpr double lg2 = 6.93147180559945286227e-01;
81 static constexpr double lg2_h = 6.93147182464599609375e-01;
82 static constexpr double lg2_l = -1.90465429995776804525e-09;
83 static constexpr double ovt = 8.0085662595372944372e-0017;
84 static constexpr double cp = 9.61796693925975554329e-01;
85 static constexpr double cp_h = 9.61796700954437255859e-01;
86 static constexpr double cp_l = -7.02846165095275826516e-09;
87 static constexpr double ivln2 = 1.44269504088896338700e+00;
88 static constexpr double ivln2_h = 1.44269502162933349609e+00;
89 static constexpr double ivln2_l = 1.92596299112661746887e-08;
94 int32_t sign = (int)0x80000000;
95 int32_t ix0, s0, q, m, t, i;
96 uint32_t r, t1, s1, ix1, q1;
98 extract_words(ix0, ix1, x);
101 if ((ix0 & 0x7ff00000) == 0x7ff00000)
109 if (((ix0 & (~sign)) | ix1) == 0)
112 return std::numeric_limits<double>::quiet_NaN();
124 for (i = 0; (ix0 & 0x00100000) == 0; i++)
127 ix0 |= (ix1 >> (32 - i));
131 ix0 = (ix0 & 0x000fffff) | 0x00100000;
134 ix0 += ix0 + ((ix1 & sign) >> 31);
140 ix0 += ix0 + ((ix1 & sign) >> 31);
142 q = q1 = s0 = s1 = 0;
154 ix0 += ix0 + ((ix1 & sign) >> 31);
164 if ((t < ix0) || ((t == ix0) && (t1 <= ix1)))
167 if (((t1 & sign) == sign) && (s1 & sign) == 0)
175 ix0 += ix0 + ((ix1 & sign) >> 31);
181 if ((ix0 | ix1) != 0)
187 if (q1 == (uint32_t)0xffffffff)
194 if (q1 == (uint32_t)0xfffffffe)
202 ix0 = (q >> 1) + 0x3fe00000;
207 insert_words(z, ix0, ix1);
211 constexpr double scalbn(
double x,
int n)
noexcept
231 y *= 0x1p-1022 * 0x1p53;
235 y *= 0x1p-1022 * 0x1p53;
241 x = y * std::bit_cast<double>((uint64_t)(0x3ff + n) << 52);
245 constexpr double pow_impl(
double x,
double y)
noexcept
247 double z, ax, z_h, z_l, p_h, p_l;
248 double y1, t1, t2, r, s, t, u, v, w;
249 int32_t i, j, k, yisint, n;
250 int32_t hx, hy, ix, iy;
253 extract_words(hx, lx, x);
254 extract_words(hy, ly, y);
255 ix = hx & 0x7fffffff;
256 iy = hy & 0x7fffffff;
263 if (hx == 0x3ff00000 && lx == 0)
267 if (ix > 0x7ff00000 || ((ix == 0x7ff00000) && (lx != 0)) ||
268 iy > 0x7ff00000 || ((iy == 0x7ff00000) && (ly != 0)))
269 return nan_mix(x, y);
279 if (iy >= 0x43400000)
281 else if (iy >= 0x3ff00000)
283 k = (iy >> 20) - 0x3ff;
287 if (((uint32_t)j << (52 - k)) == ly)
288 yisint = 2 - (j & 1);
293 if ((j << (20 - k)) == iy)
294 yisint = 2 - (j & 1);
302 if (iy == 0x7ff00000)
304 if (((ix - 0x3ff00000) | lx) == 0)
306 else if (ix >= 0x3ff00000)
307 return (hy >= 0) ? y :
zero;
309 return (hy < 0) ? -y :
zero;
311 if (iy == 0x3ff00000)
318 if (hy == 0x40000000)
320 if (hy == 0x3fe00000)
331 if (ix == 0x7ff00000 || ix == 0 || ix == 0x3ff00000)
338 if (((ix - 0x3ff00000) | yisint) == 0)
340 z = (z - z) / (z - z);
342 else if (yisint == 1)
353 n = ((uint32_t)hx >> 31) - 1;
356 if ((n | yisint) == 0)
357 return std::numeric_limits<double>::quiet_NaN();
360 if ((n | (yisint - 1)) == 0)
368 if (ix <= 0x3fefffff)
369 return (hy < 0) ?
huge *
huge : tiny * tiny;
370 if (ix >= 0x3ff00000)
371 return (hy > 0) ?
huge *
huge : tiny * tiny;
375 return (hy < 0) ? s *
huge *
huge : s * tiny * tiny;
377 return (hy > 0) ? s *
huge *
huge : s * tiny * tiny;
381 w = (t * t) * (half - t * (thrd - t * qrtr));
390 double ss, s2, s_h, s_l, t_h, t_l;
397 get_high_word(ix, ax);
399 n += ((ix) >> 20) - 0x3ff;
405 else if (j < 0xBB67A)
413 set_high_word(ax, ix);
417 v =
one / (ax + bp[k]);
420 set_low_word(s_h, 0);
423 set_high_word(t_h, ((ix >> 1) | 0x20000000) + 0x00080000 + (k << 18));
424 t_l = ax - (t_h - bp[k]);
425 s_l = v * ((u - s_h * t_h) - s_h * t_l);
428 r = s2 * s2 * (L1 + s2 * (
L2 + s2 * (
L3 + s2 * (
L4 + s2 * (
L5 + s2 *
L6)))));
429 r += s_l * (s_h + ss);
432 set_low_word(t_h, 0);
433 t_l = r - ((t_h - 3) - s2);
436 v = s_l * t_h + t_l * ss;
439 set_low_word(p_h, 0);
445 t1 = (((z_h + z_l) + dp_h[k]) + t);
447 t2 = z_l - (((t1 - t) - dp_h[k]) - z_h);
453 p_l = (y - y1) * t1 + y * t2;
456 extract_words(j, i, z);
459 if (((j - 0x40900000) | i) != 0)
463 if (p_l +
ovt > z - p_h)
467 else if ((j & 0x7fffffff) >= 0x4090cc00)
469 if (((j - 0xc090cc00) | i) != 0)
470 return s * tiny * tiny;
474 return s * tiny * tiny;
481 k = (i >> 20) - 0x3ff;
485 n = j + (0x00100000 >> (k + 1));
486 k = ((n & 0x7fffffff) >> 20) - 0x3ff;
488 set_high_word(t, n & ~(0x000fffff >> k));
489 n = ((n & 0x000fffff) | 0x00100000) >> (20 - k);
497 v = (p_l - (t - p_h)) *
lg2 + t *
lg2_l;
501 t1 = z - t * (
P1 + t * (
P2 + t * (
P3 + t * (
P4 + t *
P5))));
502 r = (z * t1) / (t1 - two) - (w + z * w);
The below code is based on Sun's libm library code, which is licensed under the following license:
static constexpr double P5
0xBEBBBD41; 0xC5D26BF1
static constexpr double one
0x3fd55555, 0x55555555
static constexpr double lg2
0x3E663769; 0x72BEA4D0
static constexpr double cp_l
0x3FEEC709; 0xE0000000 =(float)cp
static constexpr double lg2_l
0x3FE62E43; 0x00000000
constexpr double sqrt_impl(double x) noexcept
0x3E54AE0B; 0xF85DDF44 =1/ln2 tail
static constexpr double cp
-(1024-log2(ovfl+.5ulp))
static constexpr double lg2_h
0x3FE62E42; 0xFEFA39EF
static constexpr double ovt
0xBE205C61; 0x0CA86C39
static constexpr double P2
0x3FC55555; 0x5555553E
static constexpr double ivln2
0xBE3E2FE0; 0x145B01F5 =tail of cp_h
static constexpr double huge
0x43400000; 0x00000000
static constexpr double L3
0x3FDB6DB6; 0xDB6FABFF
static constexpr double zero
0x3E4CFDEB; 0x43CFD006
static constexpr double L4
0x3FD55555; 0x518F264D
static constexpr double P4
0x3F11566A; 0xAF25DE2C
static constexpr double dp_l[]
0x3FE2B803; 0x40000000
static constexpr double cp_h
0x3FEEC709; 0xDC3A03FD =2/(3ln2)
static constexpr double L2
0x3FE33333; 0x33333303
static constexpr double L5
0x3FD17460; 0xA91D4101
static constexpr double ivln2_h
0x3FF71547; 0x652B82FE =1/ln2
static constexpr double P1
0x3FCA7E28; 0x4A454EEF
static constexpr double P3
0xBF66C16C; 0x16BEBD93
static constexpr double L6
0x3FCD864A; 0x93C9DB65
static constexpr double ivln2_l
0x3FF71547; 0x60000000 =24b 1/ln2
constexpr auto abs(T num)
TODO: round.