1*71db0c75SAndroid Build Coastguard Worker //===-- Single-precision x^y function -------------------------------------===//
2*71db0c75SAndroid Build Coastguard Worker //
3*71db0c75SAndroid Build Coastguard Worker // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*71db0c75SAndroid Build Coastguard Worker // See https://llvm.org/LICENSE.txt for license information.
5*71db0c75SAndroid Build Coastguard Worker // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*71db0c75SAndroid Build Coastguard Worker //
7*71db0c75SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
8*71db0c75SAndroid Build Coastguard Worker
9*71db0c75SAndroid Build Coastguard Worker #include "src/math/powf.h"
10*71db0c75SAndroid Build Coastguard Worker #include "common_constants.h" // Lookup tables EXP_M1 and EXP_M2.
11*71db0c75SAndroid Build Coastguard Worker #include "src/__support/CPP/bit.h"
12*71db0c75SAndroid Build Coastguard Worker #include "src/__support/CPP/optional.h"
13*71db0c75SAndroid Build Coastguard Worker #include "src/__support/FPUtil/FPBits.h"
14*71db0c75SAndroid Build Coastguard Worker #include "src/__support/FPUtil/PolyEval.h"
15*71db0c75SAndroid Build Coastguard Worker #include "src/__support/FPUtil/double_double.h"
16*71db0c75SAndroid Build Coastguard Worker #include "src/__support/FPUtil/except_value_utils.h"
17*71db0c75SAndroid Build Coastguard Worker #include "src/__support/FPUtil/multiply_add.h"
18*71db0c75SAndroid Build Coastguard Worker #include "src/__support/FPUtil/nearest_integer.h"
19*71db0c75SAndroid Build Coastguard Worker #include "src/__support/FPUtil/rounding_mode.h"
20*71db0c75SAndroid Build Coastguard Worker #include "src/__support/FPUtil/sqrt.h" // Speedup for powf(x, 1/2) = sqrtf(x)
21*71db0c75SAndroid Build Coastguard Worker #include "src/__support/common.h"
22*71db0c75SAndroid Build Coastguard Worker #include "src/__support/macros/config.h"
23*71db0c75SAndroid Build Coastguard Worker #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
24*71db0c75SAndroid Build Coastguard Worker
25*71db0c75SAndroid Build Coastguard Worker #include "exp10f_impl.h" // Speedup for powf(10, y) = exp10f(y)
26*71db0c75SAndroid Build Coastguard Worker #include "exp2f_impl.h" // Speedup for powf(2, y) = exp2f(y)
27*71db0c75SAndroid Build Coastguard Worker
28*71db0c75SAndroid Build Coastguard Worker namespace LIBC_NAMESPACE_DECL {
29*71db0c75SAndroid Build Coastguard Worker
30*71db0c75SAndroid Build Coastguard Worker using fputil::DoubleDouble;
31*71db0c75SAndroid Build Coastguard Worker using fputil::TripleDouble;
32*71db0c75SAndroid Build Coastguard Worker
33*71db0c75SAndroid Build Coastguard Worker namespace {
34*71db0c75SAndroid Build Coastguard Worker
35*71db0c75SAndroid Build Coastguard Worker #ifdef LIBC_TARGET_CPU_HAS_FMA
36*71db0c75SAndroid Build Coastguard Worker constexpr uint64_t ERR = 64;
37*71db0c75SAndroid Build Coastguard Worker #else
38*71db0c75SAndroid Build Coastguard Worker constexpr uint64_t ERR = 128;
39*71db0c75SAndroid Build Coastguard Worker #endif // LIBC_TARGET_CPU_HAS_FMA
40*71db0c75SAndroid Build Coastguard Worker
41*71db0c75SAndroid Build Coastguard Worker // We choose the precision of the high part to be 53 - 24 - 8, so that when
42*71db0c75SAndroid Build Coastguard Worker // y * (e_x + LOG2_R_DD[i].hi) is exact.
43*71db0c75SAndroid Build Coastguard Worker // Generated by Sollya with:
44*71db0c75SAndroid Build Coastguard Worker // > for i from 0 to 127 do {
45*71db0c75SAndroid Build Coastguard Worker // r = 2^-8 * ceil(2^8 * (1 - 2^-8) / (1 + i * 2^-7) );
46*71db0c75SAndroid Build Coastguard Worker // a = -log2(r);
47*71db0c75SAndroid Build Coastguard Worker // b = round(1 + a, 53 - 24 - 8, RN) - 1;
48*71db0c75SAndroid Build Coastguard Worker // c = round(a - b, D, RN);
49*71db0c75SAndroid Build Coastguard Worker // d = round(a - b - c, D, RN);
50*71db0c75SAndroid Build Coastguard Worker // print("{", d, ",", c, ", ", b, "},");
51*71db0c75SAndroid Build Coastguard Worker // };
52*71db0c75SAndroid Build Coastguard Worker static constexpr TripleDouble LOG2_R_TD[128] = {
53*71db0c75SAndroid Build Coastguard Worker {0.0, 0.0, 0.0},
54*71db0c75SAndroid Build Coastguard Worker {0x1.84a2c615b70adp-79, -0x1.177c23362928cp-25, 0x1.72c8p-7},
55*71db0c75SAndroid Build Coastguard Worker {-0x1.f27b820fd03eap-76, -0x1.179e0caa9c9abp-22, 0x1.744p-6},
56*71db0c75SAndroid Build Coastguard Worker {-0x1.f27ef487c8f34p-77, -0x1.c6cea541f5b7p-23, 0x1.184cp-5},
57*71db0c75SAndroid Build Coastguard Worker {-0x1.e3f80fbc71454p-76, -0x1.66c4d4e554434p-22, 0x1.773ap-5},
58*71db0c75SAndroid Build Coastguard Worker {-0x1.9f8ef14d5f6eep-79, -0x1.70700a00fdd55p-24, 0x1.d6ecp-5},
59*71db0c75SAndroid Build Coastguard Worker {0x1.452bbce7398c1p-77, 0x1.53002a4e86631p-23, 0x1.1bb3p-4},
60*71db0c75SAndroid Build Coastguard Worker {-0x1.990555535afdp-81, 0x1.fcd15f101c142p-25, 0x1.4c56p-4},
61*71db0c75SAndroid Build Coastguard Worker {0x1.447e30ad393eep-78, 0x1.25b3eed319cedp-22, 0x1.7d6p-4},
62*71db0c75SAndroid Build Coastguard Worker {0x1.b7759da88a2dap-76, -0x1.4195120d8486fp-22, 0x1.960dp-4},
63*71db0c75SAndroid Build Coastguard Worker {0x1.cee7766ece702p-78, 0x1.45b878e27d0d9p-23, 0x1.c7b5p-4},
64*71db0c75SAndroid Build Coastguard Worker {-0x1.a55c745ecdc2fp-77, 0x1.770744593a4cbp-22, 0x1.f9c9p-4},
65*71db0c75SAndroid Build Coastguard Worker {0x1.f7ec992caa67fp-77, 0x1.c673032495d24p-22, 0x1.097ep-3},
66*71db0c75SAndroid Build Coastguard Worker {-0x1.433638c6ece3ep-77, -0x1.1eaa65b49696ep-22, 0x1.22dbp-3},
67*71db0c75SAndroid Build Coastguard Worker {0x1.58f27b6518824p-76, 0x1.b2866f2850b22p-22, 0x1.3c6f8p-3},
68*71db0c75SAndroid Build Coastguard Worker {-0x1.86bdcfdfd4a4cp-79, 0x1.8ee37cd2ea9d3p-25, 0x1.494f8p-3},
69*71db0c75SAndroid Build Coastguard Worker {-0x1.ff7044a68a7fap-80, 0x1.7e86f9c2154fbp-24, 0x1.633a8p-3},
70*71db0c75SAndroid Build Coastguard Worker {-0x1.aa21694561327p-81, 0x1.8e3cfc25f0ce6p-26, 0x1.7046p-3},
71*71db0c75SAndroid Build Coastguard Worker {-0x1.d209f2d4239c6p-87, 0x1.57f7a64ccd537p-28, 0x1.8a898p-3},
72*71db0c75SAndroid Build Coastguard Worker {-0x1.a55e97e60e632p-76, -0x1.a761c09fbd2aep-22, 0x1.97c2p-3},
73*71db0c75SAndroid Build Coastguard Worker {0x1.261179225541ep-76, 0x1.24bea9a2c66f3p-22, 0x1.b26p-3},
74*71db0c75SAndroid Build Coastguard Worker {-0x1.08fa30510fca9p-82, -0x1.60002ccfe43f5p-25, 0x1.bfc68p-3},
75*71db0c75SAndroid Build Coastguard Worker {-0x1.63ec8d56242f9p-76, 0x1.69f220e97f22cp-22, 0x1.dac2p-3},
76*71db0c75SAndroid Build Coastguard Worker {0x1.8bcdaf0534365p-76, -0x1.6164f64c210ep-22, 0x1.e858p-3},
77*71db0c75SAndroid Build Coastguard Worker {0x1.1003282896056p-78, -0x1.0c1678ae89767p-24, 0x1.01d9cp-2},
78*71db0c75SAndroid Build Coastguard Worker {0x1.01bcc7025fa92p-78, -0x1.f26a05c813d57p-22, 0x1.08bdp-2},
79*71db0c75SAndroid Build Coastguard Worker {-0x1.fe8a8648e9ebcp-80, 0x1.4d8fc561c8d44p-24, 0x1.169cp-2},
80*71db0c75SAndroid Build Coastguard Worker {0x1.08dfb23650c75p-79, -0x1.362ad8f7ca2dp-22, 0x1.1d984p-2},
81*71db0c75SAndroid Build Coastguard Worker {-0x1.f8d5a89861a5ep-79, 0x1.2b13cd6c4d042p-22, 0x1.249ccp-2},
82*71db0c75SAndroid Build Coastguard Worker {-0x1.a1c872983511ep-76, -0x1.1c8f11979a5dbp-22, 0x1.32cp-2},
83*71db0c75SAndroid Build Coastguard Worker {0x1.e8e21bff3336bp-77, 0x1.c2ab3edefe569p-23, 0x1.39de8p-2},
84*71db0c75SAndroid Build Coastguard Worker {0x1.fd1994fb2c4a1p-80, 0x1.7c3eca28e69cap-26, 0x1.4106p-2},
85*71db0c75SAndroid Build Coastguard Worker {0x1.6b94b51cf76b1p-80, -0x1.34c4e99e1c6c6p-24, 0x1.4f6fcp-2},
86*71db0c75SAndroid Build Coastguard Worker {-0x1.31d55da1d0f66p-76, -0x1.194a871b63619p-22, 0x1.56b24p-2},
87*71db0c75SAndroid Build Coastguard Worker {-0x1.378b22691e28bp-77, 0x1.e3dd5c1c885aep-23, 0x1.5dfdcp-2},
88*71db0c75SAndroid Build Coastguard Worker {0x1.99e302970e411p-83, -0x1.6ccf3b1129b7cp-23, 0x1.6552cp-2},
89*71db0c75SAndroid Build Coastguard Worker {0x1.20164a049664dp-82, -0x1.2f346e2bf924bp-23, 0x1.6cb1p-2},
90*71db0c75SAndroid Build Coastguard Worker {-0x1.d14aac4d864c3p-77, -0x1.fa61aaa59c1d8p-23, 0x1.7b8ap-2},
91*71db0c75SAndroid Build Coastguard Worker {0x1.496ab4e4b293fp-79, 0x1.90c11fd32a3abp-22, 0x1.8304cp-2},
92*71db0c75SAndroid Build Coastguard Worker {-0x1.d209f2d4239c6p-86, 0x1.57f7a64ccd537p-27, 0x1.8a898p-2},
93*71db0c75SAndroid Build Coastguard Worker {0x1.eae3326327babp-81, 0x1.249ba76fee235p-27, 0x1.9218p-2},
94*71db0c75SAndroid Build Coastguard Worker {0x1.fa05bddfded8cp-77, -0x1.aad2729b21ae5p-23, 0x1.99b08p-2},
95*71db0c75SAndroid Build Coastguard Worker {-0x1.624140d175ba2p-77, 0x1.71810a5e1818p-22, 0x1.a8ff8p-2},
96*71db0c75SAndroid Build Coastguard Worker {0x1.f1c5160c515c1p-81, -0x1.6172fe015e13cp-27, 0x1.b0b68p-2},
97*71db0c75SAndroid Build Coastguard Worker {-0x1.86a6204eec8cp-79, 0x1.5ec6c1bfbf89ap-24, 0x1.b877cp-2},
98*71db0c75SAndroid Build Coastguard Worker {0x1.718f761dd3915p-78, 0x1.678bf6cdedf51p-24, 0x1.c0438p-2},
99*71db0c75SAndroid Build Coastguard Worker {-0x1.d4ee66c3700e4p-76, 0x1.c2d45fe43895ep-22, 0x1.c819cp-2},
100*71db0c75SAndroid Build Coastguard Worker {-0x1.7d14533586306p-77, -0x1.9ee52ed49d71dp-22, 0x1.cffbp-2},
101*71db0c75SAndroid Build Coastguard Worker {0x1.5ce9fb5a7bb5bp-81, 0x1.5786af187a96bp-27, 0x1.d7e6cp-2},
102*71db0c75SAndroid Build Coastguard Worker {-0x1.ae6face57ad3bp-77, 0x1.3ab0dc56138c9p-23, 0x1.dfdd8p-2},
103*71db0c75SAndroid Build Coastguard Worker {0x1.5ac93b443d55fp-78, 0x1.fe538ab34efb5p-22, 0x1.e7df4p-2},
104*71db0c75SAndroid Build Coastguard Worker {0x1.f1753e0ae1e8fp-76, -0x1.e4fee07aa4b68p-22, 0x1.efec8p-2},
105*71db0c75SAndroid Build Coastguard Worker {0x1.cdfd4c297069bp-76, -0x1.172f32fe67287p-22, 0x1.f804cp-2},
106*71db0c75SAndroid Build Coastguard Worker {0x1.97a0e8f3ba742p-79, -0x1.9a83ff9ab9cc8p-22, 0x1.00144p-1},
107*71db0c75SAndroid Build Coastguard Worker {-0x1.800450f5b2357p-78, -0x1.68cb06cece193p-22, 0x1.042bep-1},
108*71db0c75SAndroid Build Coastguard Worker {-0x1.a839041241fe7p-78, 0x1.8cd71ddf82e2p-22, 0x1.08494p-1},
109*71db0c75SAndroid Build Coastguard Worker {0x1.ed0b8eeccca86p-78, 0x1.5e18ab2df3ae6p-22, 0x1.0c6cap-1},
110*71db0c75SAndroid Build Coastguard Worker {0x1.3dd41df9689b3p-79, 0x1.5dee4d9d8a273p-25, 0x1.1096p-1},
111*71db0c75SAndroid Build Coastguard Worker {-0x1.990555535afdp-82, 0x1.fcd15f101c142p-26, 0x1.14c56p-1},
112*71db0c75SAndroid Build Coastguard Worker {-0x1.1773d02c9055cp-77, -0x1.2474b0f992ba1p-23, 0x1.18faep-1},
113*71db0c75SAndroid Build Coastguard Worker {-0x1.4aeef330c53c1p-78, 0x1.4b5a92a606047p-24, 0x1.1d368p-1},
114*71db0c75SAndroid Build Coastguard Worker {0x1.8e6ff749ebacbp-77, 0x1.16186fcf54bbdp-22, 0x1.21786p-1},
115*71db0c75SAndroid Build Coastguard Worker {0x1.c09d761c548ebp-84, 0x1.18efabeb7d722p-27, 0x1.25c0ap-1},
116*71db0c75SAndroid Build Coastguard Worker {0x1.aaa73a428e1e4p-78, -0x1.e5fc7d238691dp-24, 0x1.2a0f4p-1},
117*71db0c75SAndroid Build Coastguard Worker {-0x1.af2f3d8b63fbap-79, 0x1.f5809faf6283cp-22, 0x1.2e644p-1},
118*71db0c75SAndroid Build Coastguard Worker {-0x1.af2f3d8b63fbap-79, 0x1.f5809faf6283cp-22, 0x1.2e644p-1},
119*71db0c75SAndroid Build Coastguard Worker {0x1.78de359f2bb88p-77, 0x1.c6e1dcd0cb449p-22, 0x1.32bfep-1},
120*71db0c75SAndroid Build Coastguard Worker {-0x1.415ae1a715618p-76, 0x1.76e0e8f74b4d5p-22, 0x1.37222p-1},
121*71db0c75SAndroid Build Coastguard Worker {-0x1.4991b5375621fp-79, -0x1.cb82c89692d99p-24, 0x1.3b8b2p-1},
122*71db0c75SAndroid Build Coastguard Worker {-0x1.827d37deb2236p-76, -0x1.63161c5432aebp-22, 0x1.3ffaep-1},
123*71db0c75SAndroid Build Coastguard Worker {0x1.9576edac01c78p-77, 0x1.458104c41b901p-22, 0x1.44716p-1},
124*71db0c75SAndroid Build Coastguard Worker {0x1.9576edac01c78p-77, 0x1.458104c41b901p-22, 0x1.44716p-1},
125*71db0c75SAndroid Build Coastguard Worker {-0x1.05a27b81e2219p-77, -0x1.cd9d0cde578d5p-22, 0x1.48efp-1},
126*71db0c75SAndroid Build Coastguard Worker {0x1.237616778b4bap-82, 0x1.b9884591add87p-26, 0x1.4d738p-1},
127*71db0c75SAndroid Build Coastguard Worker {0x1.3b7d7e5d148bbp-76, 0x1.c6042978605ffp-22, 0x1.51ff2p-1},
128*71db0c75SAndroid Build Coastguard Worker {-0x1.cc3f936a5977cp-79, -0x1.fc4c96b37dcf6p-22, 0x1.56922p-1},
129*71db0c75SAndroid Build Coastguard Worker {0x1.20164a049664dp-83, -0x1.2f346e2bf924bp-24, 0x1.5b2c4p-1},
130*71db0c75SAndroid Build Coastguard Worker {0x1.20164a049664dp-83, -0x1.2f346e2bf924bp-24, 0x1.5b2c4p-1},
131*71db0c75SAndroid Build Coastguard Worker {-0x1.a212919a92f7ap-77, 0x1.c4e4fbb68a4d1p-22, 0x1.5fcdcp-1},
132*71db0c75SAndroid Build Coastguard Worker {-0x1.b64b03f7230ddp-77, -0x1.9d499bd9b3226p-23, 0x1.6476ep-1},
133*71db0c75SAndroid Build Coastguard Worker {-0x1.1ec6379e6e3b9p-77, -0x1.f89b355ede26fp-23, 0x1.69278p-1},
134*71db0c75SAndroid Build Coastguard Worker {-0x1.1ec6379e6e3b9p-77, -0x1.f89b355ede26fp-23, 0x1.69278p-1},
135*71db0c75SAndroid Build Coastguard Worker {-0x1.4ba44c03bfbbdp-78, 0x1.53c7e319f6e92p-24, 0x1.6ddfcp-1},
136*71db0c75SAndroid Build Coastguard Worker {-0x1.c36fc650d030fp-77, -0x1.b291f070528c7p-22, 0x1.729fep-1},
137*71db0c75SAndroid Build Coastguard Worker {-0x1.69e5693a7f067p-80, 0x1.2967a451a7b48p-25, 0x1.7767cp-1},
138*71db0c75SAndroid Build Coastguard Worker {-0x1.69e5693a7f067p-80, 0x1.2967a451a7b48p-25, 0x1.7767cp-1},
139*71db0c75SAndroid Build Coastguard Worker {0x1.6598aae91499ap-76, 0x1.244fcff690fcep-22, 0x1.7c37ap-1},
140*71db0c75SAndroid Build Coastguard Worker {0x1.99d61ec432837p-77, 0x1.46fd97f5dc572p-23, 0x1.810fap-1},
141*71db0c75SAndroid Build Coastguard Worker {0x1.99d61ec432837p-77, 0x1.46fd97f5dc572p-23, 0x1.810fap-1},
142*71db0c75SAndroid Build Coastguard Worker {0x1.855c42078f81bp-76, -0x1.f3a7352663e5p-22, 0x1.85efep-1},
143*71db0c75SAndroid Build Coastguard Worker {-0x1.59408e815107p-77, 0x1.b3cda690370b5p-23, 0x1.8ad84p-1},
144*71db0c75SAndroid Build Coastguard Worker {-0x1.59408e815107p-77, 0x1.b3cda690370b5p-23, 0x1.8ad84p-1},
145*71db0c75SAndroid Build Coastguard Worker {0x1.33b318085e50ap-78, 0x1.3226b211bf1d9p-23, 0x1.8fc92p-1},
146*71db0c75SAndroid Build Coastguard Worker {0x1.343fe7c9cb4aep-79, 0x1.d24b136c101eep-23, 0x1.94c28p-1},
147*71db0c75SAndroid Build Coastguard Worker {0x1.343fe7c9cb4aep-79, 0x1.d24b136c101eep-23, 0x1.94c28p-1},
148*71db0c75SAndroid Build Coastguard Worker {-0x1.d19522e56fe6p-76, 0x1.7c40c7907e82ap-22, 0x1.99c48p-1},
149*71db0c75SAndroid Build Coastguard Worker {-0x1.23b9d8ea55c3ep-77, -0x1.e81781d97ee91p-22, 0x1.9ecf6p-1},
150*71db0c75SAndroid Build Coastguard Worker {-0x1.23b9d8ea55c3ep-77, -0x1.e81781d97ee91p-22, 0x1.9ecf6p-1},
151*71db0c75SAndroid Build Coastguard Worker {0x1.829440c24aeb6p-78, -0x1.6a77813f94e01p-22, 0x1.a3e3p-1},
152*71db0c75SAndroid Build Coastguard Worker {-0x1.624140d175ba2p-76, -0x1.1cfdeb43cfdp-22, 0x1.a8ffap-1},
153*71db0c75SAndroid Build Coastguard Worker {-0x1.624140d175ba2p-76, -0x1.1cfdeb43cfdp-22, 0x1.a8ffap-1},
154*71db0c75SAndroid Build Coastguard Worker {0x1.afa6f024fb045p-77, -0x1.f983f74d3138fp-23, 0x1.ae256p-1},
155*71db0c75SAndroid Build Coastguard Worker {-0x1.603ad3a5d326dp-78, -0x1.e278ae1a1f51fp-23, 0x1.b3546p-1},
156*71db0c75SAndroid Build Coastguard Worker {-0x1.603ad3a5d326dp-78, -0x1.e278ae1a1f51fp-23, 0x1.b3546p-1},
157*71db0c75SAndroid Build Coastguard Worker {-0x1.0c1e0e5855d6ap-77, -0x1.97552b7b5ea45p-23, 0x1.b88ccp-1},
158*71db0c75SAndroid Build Coastguard Worker {-0x1.0c1e0e5855d6ap-77, -0x1.97552b7b5ea45p-23, 0x1.b88ccp-1},
159*71db0c75SAndroid Build Coastguard Worker {0x1.c817ad56baa16p-78, -0x1.19b4f3c72c4f8p-24, 0x1.bdceap-1},
160*71db0c75SAndroid Build Coastguard Worker {0x1.44c47ac1bf62bp-77, 0x1.f7402d26f1a12p-23, 0x1.c31a2p-1},
161*71db0c75SAndroid Build Coastguard Worker {0x1.44c47ac1bf62bp-77, 0x1.f7402d26f1a12p-23, 0x1.c31a2p-1},
162*71db0c75SAndroid Build Coastguard Worker {-0x1.69b9465eae1e6p-78, -0x1.2056d5dd31d96p-23, 0x1.c86f8p-1},
163*71db0c75SAndroid Build Coastguard Worker {-0x1.69b9465eae1e6p-78, -0x1.2056d5dd31d96p-23, 0x1.c86f8p-1},
164*71db0c75SAndroid Build Coastguard Worker {-0x1.24a6d9d1d1904p-79, -0x1.6e46335aae723p-24, 0x1.cdcecp-1},
165*71db0c75SAndroid Build Coastguard Worker {-0x1.3826144575ac4p-76, -0x1.beb244c59f331p-22, 0x1.d3382p-1},
166*71db0c75SAndroid Build Coastguard Worker {-0x1.3826144575ac4p-76, -0x1.beb244c59f331p-22, 0x1.d3382p-1},
167*71db0c75SAndroid Build Coastguard Worker {0x1.dbc96b3b12b25p-81, 0x1.16c071e93fd97p-27, 0x1.d8abap-1},
168*71db0c75SAndroid Build Coastguard Worker {0x1.dbc96b3b12b25p-81, 0x1.16c071e93fd97p-27, 0x1.d8abap-1},
169*71db0c75SAndroid Build Coastguard Worker {0x1.68a8ccdbd1f33p-77, 0x1.d8175819530c2p-22, 0x1.de298p-1},
170*71db0c75SAndroid Build Coastguard Worker {0x1.68a8ccdbd1f33p-77, 0x1.d8175819530c2p-22, 0x1.de298p-1},
171*71db0c75SAndroid Build Coastguard Worker {0x1.e586711df5ea1p-79, 0x1.51bd552842c1cp-23, 0x1.e3b2p-1},
172*71db0c75SAndroid Build Coastguard Worker {0x1.e586711df5ea1p-79, 0x1.51bd552842c1cp-23, 0x1.e3b2p-1},
173*71db0c75SAndroid Build Coastguard Worker {-0x1.bc25adf042483p-79, 0x1.914e204f19d94p-22, 0x1.e9452p-1},
174*71db0c75SAndroid Build Coastguard Worker {-0x1.bc25adf042483p-79, 0x1.914e204f19d94p-22, 0x1.e9452p-1},
175*71db0c75SAndroid Build Coastguard Worker {0x1.d7d82b65c5686p-76, 0x1.c55d997da24fdp-22, 0x1.eee32p-1},
176*71db0c75SAndroid Build Coastguard Worker {0x1.d7d82b65c5686p-76, 0x1.c55d997da24fdp-22, 0x1.eee32p-1},
177*71db0c75SAndroid Build Coastguard Worker {-0x1.3f108c0857ca3p-77, -0x1.685c2d2298a6ep-22, 0x1.f48c4p-1},
178*71db0c75SAndroid Build Coastguard Worker {-0x1.3f108c0857ca3p-77, -0x1.685c2d2298a6ep-22, 0x1.f48c4p-1},
179*71db0c75SAndroid Build Coastguard Worker {-0x1.bd800bca7a221p-78, 0x1.7a4887bd74039p-22, 0x1.fa406p-1},
180*71db0c75SAndroid Build Coastguard Worker {0.0, 0.0, 1.0},
181*71db0c75SAndroid Build Coastguard Worker };
182*71db0c75SAndroid Build Coastguard Worker
183*71db0c75SAndroid Build Coastguard Worker // Look up table for the second range reduction step:
184*71db0c75SAndroid Build Coastguard Worker // Generated by Sollya with:
185*71db0c75SAndroid Build Coastguard Worker // > for i from -64 to 128 do {
186*71db0c75SAndroid Build Coastguard Worker // r = 2^-16 * nearestint(2^16 / (1 + i * 2^-14) );
187*71db0c75SAndroid Build Coastguard Worker // a = -log2(r);
188*71db0c75SAndroid Build Coastguard Worker // b = round(a, D, RN);
189*71db0c75SAndroid Build Coastguard Worker // c = round(a - b, D, RN);
190*71db0c75SAndroid Build Coastguard Worker // print("{", c, ", ", b, "},");
191*71db0c75SAndroid Build Coastguard Worker // };
192*71db0c75SAndroid Build Coastguard Worker static constexpr DoubleDouble LOG2_R2_DD[] = {
193*71db0c75SAndroid Build Coastguard Worker {0x1.ff25180953e64p-62, -0x1.720c2ab2312a9p-8},
194*71db0c75SAndroid Build Coastguard Worker {-0x1.15ffd79560d8fp-62, -0x1.6c4c92b1478ffp-8},
195*71db0c75SAndroid Build Coastguard Worker {0x1.b8d6d6f2e3579p-62, -0x1.668ce3c873549p-8},
196*71db0c75SAndroid Build Coastguard Worker {-0x1.5bfc3f0d5ef71p-62, -0x1.60cd1df6fde91p-8},
197*71db0c75SAndroid Build Coastguard Worker {-0x1.d1f7a8777984ap-64, -0x1.5b0d413c30b5ep-8},
198*71db0c75SAndroid Build Coastguard Worker {0x1.8e858515b8343p-66, -0x1.554d4d97551abp-8},
199*71db0c75SAndroid Build Coastguard Worker {0x1.e165c4014c1f2p-62, -0x1.4f8d4307b46ecp-8},
200*71db0c75SAndroid Build Coastguard Worker {0x1.0f84b2cc14c7ep-63, -0x1.49cd218c9800bp-8},
201*71db0c75SAndroid Build Coastguard Worker {0x1.de618ed0db9a6p-62, -0x1.440ce9254916cp-8},
202*71db0c75SAndroid Build Coastguard Worker {-0x1.f6b8587e64f22p-62, -0x1.3e4c99d110ee7p-8},
203*71db0c75SAndroid Build Coastguard Worker {-0x1.7f793c84cfa63p-64, -0x1.388c338f38bdp-8},
204*71db0c75SAndroid Build Coastguard Worker {-0x1.7d7ecf6258c9ap-65, -0x1.32cbb65f09aeep-8},
205*71db0c75SAndroid Build Coastguard Worker {-0x1.810bc5ac188f5p-62, -0x1.2d0b223fcce81p-8},
206*71db0c75SAndroid Build Coastguard Worker {-0x1.950035fc5b67cp-62, -0x1.274a7730cb841p-8},
207*71db0c75SAndroid Build Coastguard Worker {0x1.4f47f3048cdadp-62, -0x1.2189b5314e95dp-8},
208*71db0c75SAndroid Build Coastguard Worker {0x1.269519861e298p-68, -0x1.1bc8dc409f279p-8},
209*71db0c75SAndroid Build Coastguard Worker {-0x1.5c2b0a46a7e2fp-62, -0x1.1607ec5e063b3p-8},
210*71db0c75SAndroid Build Coastguard Worker {0x1.5001ac8f0bda8p-63, -0x1.1046e588cccap-8},
211*71db0c75SAndroid Build Coastguard Worker {0x1.106f246af5d41p-62, -0x1.0a85c7c03bc4ap-8},
212*71db0c75SAndroid Build Coastguard Worker {0x1.82a00583b34bap-66, -0x1.0354423e3c666p-8},
213*71db0c75SAndroid Build Coastguard Worker {0x1.b6f37deb3137p-65, -0x1.fb25e19f11aecp-9},
214*71db0c75SAndroid Build Coastguard Worker {-0x1.44a2140444811p-63, -0x1.efa310d6550ecp-9},
215*71db0c75SAndroid Build Coastguard Worker {0x1.f5e68a763133fp-63, -0x1.e4201220d4858p-9},
216*71db0c75SAndroid Build Coastguard Worker {0x1.692083115f0b9p-63, -0x1.d89ce57d219a6p-9},
217*71db0c75SAndroid Build Coastguard Worker {0x1.144bb17b9ac9cp-63, -0x1.cd198ae9cdc3dp-9},
218*71db0c75SAndroid Build Coastguard Worker {0x1.ee7f086d32c05p-63, -0x1.c19602656a671p-9},
219*71db0c75SAndroid Build Coastguard Worker {-0x1.d4f1167538dbep-63, -0x1.b6124bee88d82p-9},
220*71db0c75SAndroid Build Coastguard Worker {0x1.7df8d226c67ep-63, -0x1.aa8e6783ba5a2p-9},
221*71db0c75SAndroid Build Coastguard Worker {0x1.60545d61b9512p-63, -0x1.9f0a5523901ebp-9},
222*71db0c75SAndroid Build Coastguard Worker {0x1.54c99c291702p-63, -0x1.938614cc9b468p-9},
223*71db0c75SAndroid Build Coastguard Worker {-0x1.a7e678d7280dep-64, -0x1.8801a67d6ce1p-9},
224*71db0c75SAndroid Build Coastguard Worker {-0x1.6d419bbeb223ap-64, -0x1.7c7d0a3495ec9p-9},
225*71db0c75SAndroid Build Coastguard Worker {0x1.ce2b9892e27e9p-64, -0x1.70f83ff0a7565p-9},
226*71db0c75SAndroid Build Coastguard Worker {-0x1.a4db4eff7bd61p-63, -0x1.657347b031fa2p-9},
227*71db0c75SAndroid Build Coastguard Worker {0x1.5bb04682fab82p-63, -0x1.59ee2171c6a2fp-9},
228*71db0c75SAndroid Build Coastguard Worker {-0x1.78b8bfe6a3adep-64, -0x1.4e68cd33f60a3p-9},
229*71db0c75SAndroid Build Coastguard Worker {0x1.574c3ce9b89b1p-63, -0x1.42e34af550d87p-9},
230*71db0c75SAndroid Build Coastguard Worker {0x1.08fb216647b7bp-63, -0x1.375d9ab467a4dp-9},
231*71db0c75SAndroid Build Coastguard Worker {0x1.ed5a50e7b919cp-66, -0x1.2bd7bc6fcaf56p-9},
232*71db0c75SAndroid Build Coastguard Worker {0x1.91ad7a23f86fep-63, -0x1.2051b0260b3fp-9},
233*71db0c75SAndroid Build Coastguard Worker {0x1.3ab2c932b8b0ap-64, -0x1.14cb75d5b8e54p-9},
234*71db0c75SAndroid Build Coastguard Worker {-0x1.c63bcdf120f7ap-63, -0x1.09450d7d643a9p-9},
235*71db0c75SAndroid Build Coastguard Worker {0x1.8af8c4ab4e82dp-64, -0x1.fb7cee373b008p-10},
236*71db0c75SAndroid Build Coastguard Worker {0x1.a52c2ca9d8b9bp-65, -0x1.e46f655de9cc6p-10},
237*71db0c75SAndroid Build Coastguard Worker {-0x1.460b177a58742p-64, -0x1.cd61806bf5166p-10},
238*71db0c75SAndroid Build Coastguard Worker {0x1.611089de8d12ap-66, -0x1.b6533f5e7cf9bp-10},
239*71db0c75SAndroid Build Coastguard Worker {-0x1.4209853cee70cp-69, -0x1.9f44a232a16eep-10},
240*71db0c75SAndroid Build Coastguard Worker {0x1.964e032541a28p-64, -0x1.8835a8e5824c3p-10},
241*71db0c75SAndroid Build Coastguard Worker {-0x1.fa9f94392637bp-66, -0x1.712653743f454p-10},
242*71db0c75SAndroid Build Coastguard Worker {-0x1.3293693721a53p-64, -0x1.5a16a1dbf7eb6p-10},
243*71db0c75SAndroid Build Coastguard Worker {-0x1.6e2af03c83c6ep-68, -0x1.43069419cbad5p-10},
244*71db0c75SAndroid Build Coastguard Worker {-0x1.b5f05b9d5bd29p-65, -0x1.2bf62a2ad9d74p-10},
245*71db0c75SAndroid Build Coastguard Worker {0x1.3db883c072f72p-64, -0x1.14e5640c4193p-10},
246*71db0c75SAndroid Build Coastguard Worker {-0x1.a675a1c045304p-68, -0x1.fba8837643cf6p-11},
247*71db0c75SAndroid Build Coastguard Worker {0x1.3b9c2aeb00068p-66, -0x1.cd85866933743p-11},
248*71db0c75SAndroid Build Coastguard Worker {-0x1.2911a381901ebp-66, -0x1.9f61d0eb8f98bp-11},
249*71db0c75SAndroid Build Coastguard Worker {-0x1.5ea75a74def03p-68, -0x1.713d62f7957c3p-11},
250*71db0c75SAndroid Build Coastguard Worker {-0x1.305b92f93ffep-67, -0x1.43183c878218dp-11},
251*71db0c75SAndroid Build Coastguard Worker {0x1.b7c8c8dd40d35p-68, -0x1.14f25d959223ap-11},
252*71db0c75SAndroid Build Coastguard Worker {0x1.dc915d58a62f6p-66, -0x1.cd978c3804191p-12},
253*71db0c75SAndroid Build Coastguard Worker {0x1.c7bc3fe53cd94p-66, -0x1.7148ec2a1bfc9p-12},
254*71db0c75SAndroid Build Coastguard Worker {-0x1.427ce595cc53cp-67, -0x1.14f8daf5e3bcfp-12},
255*71db0c75SAndroid Build Coastguard Worker {-0x1.d523885ac824cp-67, -0x1.714eb11fa5363p-13},
256*71db0c75SAndroid Build Coastguard Worker {-0x1.945957f63330ap-69, -0x1.715193b17d35dp-14},
257*71db0c75SAndroid Build Coastguard Worker {0, 0},
258*71db0c75SAndroid Build Coastguard Worker {-0x1.88fb2ea8bf9eap-70, 0x1.7157590356aeep-14},
259*71db0c75SAndroid Build Coastguard Worker {-0x1.5aeaee345d04ep-68, 0x1.715a3bc3593d5p-13},
260*71db0c75SAndroid Build Coastguard Worker {-0x1.7fce430230132p-66, 0x1.1505d6ee104c5p-12},
261*71db0c75SAndroid Build Coastguard Worker {-0x1.9a480f204ff09p-70, 0x1.716001718cb2bp-12},
262*71db0c75SAndroid Build Coastguard Worker {-0x1.00e7233f2d8bdp-68, 0x1.cdbb9d77ae5a8p-12},
263*71db0c75SAndroid Build Coastguard Worker {0x1.09d379fa18c5dp-67, 0x1.150c5586012b8p-11},
264*71db0c75SAndroid Build Coastguard Worker {0x1.b6b9d90a104d3p-65, 0x1.433b951d0b231p-11},
265*71db0c75SAndroid Build Coastguard Worker {0x1.4d9a3ea651885p-65, 0x1.716b8d86bc285p-11},
266*71db0c75SAndroid Build Coastguard Worker {-0x1.7590b3a76f0f9p-67, 0x1.9f9c3ec8db94fp-11},
267*71db0c75SAndroid Build Coastguard Worker {0x1.f183ca5b21bfep-65, 0x1.cdcda8e93107fp-11},
268*71db0c75SAndroid Build Coastguard Worker {-0x1.a7e3465ba127p-66, 0x1.fbffcbed8465fp-11},
269*71db0c75SAndroid Build Coastguard Worker {-0x1.7821f738d1221p-64, 0x1.151953edceec6p-10},
270*71db0c75SAndroid Build Coastguard Worker {0x1.3bb4c0fb95359p-65, 0x1.2c331e5ca2e7dp-10},
271*71db0c75SAndroid Build Coastguard Worker {0x1.236028e962f8p-64, 0x1.434d4546227fcp-10},
272*71db0c75SAndroid Build Coastguard Worker {0x1.aaaa64d30f184p-66, 0x1.5a67c8ad32315p-10},
273*71db0c75SAndroid Build Coastguard Worker {-0x1.a821b7cc57a7ap-64, 0x1.7182a894b69c6p-10},
274*71db0c75SAndroid Build Coastguard Worker {-0x1.13d9d78aace21p-64, 0x1.889de4ff94838p-10},
275*71db0c75SAndroid Build Coastguard Worker {-0x1.2f249a6b923ap-64, 0x1.9fb97df0b0cc2p-10},
276*71db0c75SAndroid Build Coastguard Worker {-0x1.d47dc3664be7ap-68, 0x1.b6d5736af07e6p-10},
277*71db0c75SAndroid Build Coastguard Worker {0x1.bd1522c6418fbp-64, 0x1.cdf1c57138c53p-10},
278*71db0c75SAndroid Build Coastguard Worker {-0x1.bacdbb22d2163p-64, 0x1.e50e74066eee6p-10},
279*71db0c75SAndroid Build Coastguard Worker {-0x1.ca7604812d77bp-64, 0x1.fc2b7f2d786a5p-10},
280*71db0c75SAndroid Build Coastguard Worker {-0x1.2b6832f8830bfp-63, 0x1.09a473749d663p-9},
281*71db0c75SAndroid Build Coastguard Worker {0x1.4e712033d0457p-65, 0x1.1533559e4de55p-9},
282*71db0c75SAndroid Build Coastguard Worker {-0x1.473dd044017b5p-66, 0x1.20c26615409f1p-9},
283*71db0c75SAndroid Build Coastguard Worker {-0x1.e033bcac726d3p-63, 0x1.2c51a4dae8915p-9},
284*71db0c75SAndroid Build Coastguard Worker {-0x1.4a47a2b18a0fap-63, 0x1.37e111f0b8cb5p-9},
285*71db0c75SAndroid Build Coastguard Worker {0x1.6f3615771c17bp-66, 0x1.4370ad58246ddp-9},
286*71db0c75SAndroid Build Coastguard Worker {0x1.c0ee6c32d6236p-65, 0x1.4f0077129eabp-9},
287*71db0c75SAndroid Build Coastguard Worker {0x1.fa94c99761b8fp-64, 0x1.5a906f219ac67p-9},
288*71db0c75SAndroid Build Coastguard Worker {-0x1.979e6b473fbf8p-64, 0x1.662095868c153p-9},
289*71db0c75SAndroid Build Coastguard Worker {0x1.30edde8d24c7bp-64, 0x1.71b0ea42e5fdap-9},
290*71db0c75SAndroid Build Coastguard Worker {-0x1.d01594fe1421cp-64, 0x1.7d416d581bf7cp-9},
291*71db0c75SAndroid Build Coastguard Worker {0x1.50bf7b995b49ap-63, 0x1.88d21ec7a18cdp-9},
292*71db0c75SAndroid Build Coastguard Worker {-0x1.28ea2bcec5018p-63, 0x1.9462fe92ea57cp-9},
293*71db0c75SAndroid Build Coastguard Worker {0x1.ed6add489c30bp-65, 0x1.9ff40cbb6a04bp-9},
294*71db0c75SAndroid Build Coastguard Worker {0x1.201d5c3bbeb69p-64, 0x1.ab85494294517p-9},
295*71db0c75SAndroid Build Coastguard Worker {-0x1.a05d0d4461ea9p-64, 0x1.b716b429dd0d3p-9},
296*71db0c75SAndroid Build Coastguard Worker {-0x1.7c974c8a392fdp-63, 0x1.c2a84d72b8189p-9},
297*71db0c75SAndroid Build Coastguard Worker {-0x1.f068238451bdep-64, 0x1.ce3a151e9965bp-9},
298*71db0c75SAndroid Build Coastguard Worker {-0x1.5e4d95c6259c3p-66, 0x1.d9cc0b2ef4f83p-9},
299*71db0c75SAndroid Build Coastguard Worker {-0x1.1fc262efaad6cp-63, 0x1.e55e2fa53ee53p-9},
300*71db0c75SAndroid Build Coastguard Worker {0x1.49eee7abc7716p-63, 0x1.f0f08282eb533p-9},
301*71db0c75SAndroid Build Coastguard Worker {-0x1.903de284d2782p-65, 0x1.fc8303c96e7a6p-9},
302*71db0c75SAndroid Build Coastguard Worker {-0x1.ec564845134cbp-63, 0x1.040ad9bd1e522p-8},
303*71db0c75SAndroid Build Coastguard Worker {-0x1.7692b7791cf1fp-66, 0x1.0861eadabc3dcp-8},
304*71db0c75SAndroid Build Coastguard Worker {-0x1.37829afb11c1p-62, 0x1.0e2b6b51e4f7ep-8},
305*71db0c75SAndroid Build Coastguard Worker {0x1.6706b91c3b0bap-62, 0x1.13f5030033459p-8},
306*71db0c75SAndroid Build Coastguard Worker {-0x1.7558ccd710756p-62, 0x1.19beb1e6616c9p-8},
307*71db0c75SAndroid Build Coastguard Worker {0x1.79f72a5bbe9dep-62, 0x1.1f88780529bb1p-8},
308*71db0c75SAndroid Build Coastguard Worker {-0x1.e1297c110b25p-62, 0x1.2552555d46886p-8},
309*71db0c75SAndroid Build Coastguard Worker {0x1.29930d567ca26p-62, 0x1.2b1c49ef72343p-8},
310*71db0c75SAndroid Build Coastguard Worker {0x1.a08cbd7592a17p-65, 0x1.30e655bc67275p-8},
311*71db0c75SAndroid Build Coastguard Worker {0x1.e4f9d4ac5db83p-62, 0x1.36b078c4dfd31p-8},
312*71db0c75SAndroid Build Coastguard Worker {-0x1.ed1b0aafd30c2p-62, 0x1.3c7ab30996b1cp-8},
313*71db0c75SAndroid Build Coastguard Worker {0x1.e78f0aa014b32p-62, 0x1.4245048b46462p-8},
314*71db0c75SAndroid Build Coastguard Worker {0x1.8594548038a0fp-69, 0x1.480f6d4aa91c2p-8},
315*71db0c75SAndroid Build Coastguard Worker {0x1.3df498168a333p-63, 0x1.4dd9ed4879c82p-8},
316*71db0c75SAndroid Build Coastguard Worker {0x1.b1c502544f82ap-62, 0x1.53a4848572e77p-8},
317*71db0c75SAndroid Build Coastguard Worker {-0x1.dc50552fe0da9p-63, 0x1.596f33024f203p-8},
318*71db0c75SAndroid Build Coastguard Worker {-0x1.671d85c357d5ep-62, 0x1.5f39f8bfc9212p-8},
319*71db0c75SAndroid Build Coastguard Worker {0x1.1c670cabccefap-64, 0x1.6504d5be9ba1ep-8},
320*71db0c75SAndroid Build Coastguard Worker {-0x1.9983a9e98f318p-62, 0x1.6acfc9ff8162fp-8},
321*71db0c75SAndroid Build Coastguard Worker {0x1.ae1a26af3eebep-62, 0x1.709ad583352d6p-8},
322*71db0c75SAndroid Build Coastguard Worker {0x1.655eb510bfda3p-62, 0x1.7665f84a71d35p-8},
323*71db0c75SAndroid Build Coastguard Worker {-0x1.e287bc0192e15p-64, 0x1.7c313255f22f8p-8},
324*71db0c75SAndroid Build Coastguard Worker {0x1.cc4944139ccbfp-63, 0x1.81fc83a671257p-8},
325*71db0c75SAndroid Build Coastguard Worker {0x1.4e09b4cb8645bp-62, 0x1.87c7ec3ca9a19p-8},
326*71db0c75SAndroid Build Coastguard Worker {-0x1.5becc991e3a5fp-64, 0x1.8d936c1956991p-8},
327*71db0c75SAndroid Build Coastguard Worker {-0x1.ddfa3f1e15ba8p-62, 0x1.935f033d3309ep-8},
328*71db0c75SAndroid Build Coastguard Worker {-0x1.b7b06ea3fb362p-62, 0x1.992ab1a8f9facp-8},
329*71db0c75SAndroid Build Coastguard Worker {0x1.32d614904e46cp-62, 0x1.9ef6775d667b4p-8},
330*71db0c75SAndroid Build Coastguard Worker {-0x1.7186892b5bfaep-64, 0x1.a4c2545b33a3ep-8},
331*71db0c75SAndroid Build Coastguard Worker {-0x1.d4de10b28dfd8p-62, 0x1.aa8e48a31c95cp-8},
332*71db0c75SAndroid Build Coastguard Worker {0x1.4bb4b3bdc8175p-62, 0x1.b05a5435dc7adp-8},
333*71db0c75SAndroid Build Coastguard Worker {0x1.9cedbd1d7fba5p-62, 0x1.b62677142e86p-8},
334*71db0c75SAndroid Build Coastguard Worker {-0x1.0ed3379beaffdp-66, 0x1.bbf2b13ecdf2fp-8},
335*71db0c75SAndroid Build Coastguard Worker {0x1.6e86a125567a6p-62, 0x1.c1bf02b67606p-8},
336*71db0c75SAndroid Build Coastguard Worker {-0x1.35038e0c0a52cp-62, 0x1.c6184f1b326d9p-8},
337*71db0c75SAndroid Build Coastguard Worker {0x1.05ef8bf5adf5ep-67, 0x1.cbe4c95b6c5abp-8},
338*71db0c75SAndroid Build Coastguard Worker {-0x1.b7338b99a6b26p-65, 0x1.d1b15aeab217cp-8},
339*71db0c75SAndroid Build Coastguard Worker {0x1.9e901c30c427ep-63, 0x1.d77e03c9bf0a4p-8},
340*71db0c75SAndroid Build Coastguard Worker {-0x1.1f28a9c0b3d47p-62, 0x1.dd4ac3f94ea0ap-8},
341*71db0c75SAndroid Build Coastguard Worker {-0x1.140ef760d3b63p-62, 0x1.e3179b7a1c52p-8},
342*71db0c75SAndroid Build Coastguard Worker {-0x1.ab65b1037f517p-63, 0x1.e8e48a4ce39e7p-8},
343*71db0c75SAndroid Build Coastguard Worker {-0x1.76940c457ce6dp-63, 0x1.eeb19072600edp-8},
344*71db0c75SAndroid Build Coastguard Worker {0x1.da3ae65a605cfp-64, 0x1.f47eadeb4d34dp-8},
345*71db0c75SAndroid Build Coastguard Worker {0x1.b15d0bce2ede6p-62, 0x1.fa4be2b866abp-8},
346*71db0c75SAndroid Build Coastguard Worker {0x1.e02aa1fa9dc57p-61, 0x1.000c976d340a6p-7},
347*71db0c75SAndroid Build Coastguard Worker {0x1.6be971a5565b9p-62, 0x1.02f34929068f3p-7},
348*71db0c75SAndroid Build Coastguard Worker {-0x1.8a9319a6ed164p-64, 0x1.05da069008be7p-7},
349*71db0c75SAndroid Build Coastguard Worker {0x1.825079f1e0ec5p-62, 0x1.08c0cfa298771p-7},
350*71db0c75SAndroid Build Coastguard Worker {0x1.60d5749321466p-63, 0x1.0ba7a461139c8p-7},
351*71db0c75SAndroid Build Coastguard Worker {-0x1.5b8f4c479e2ep-61, 0x1.0e8e84cbd8169p-7},
352*71db0c75SAndroid Build Coastguard Worker {-0x1.e3e1248004e29p-62, 0x1.117570e343d17p-7},
353*71db0c75SAndroid Build Coastguard Worker {0x1.9ac06487c375p-63, 0x1.145c68a7b4bddp-7},
354*71db0c75SAndroid Build Coastguard Worker {0x1.f657ea5c03ea4p-62, 0x1.17436c1988d0dp-7},
355*71db0c75SAndroid Build Coastguard Worker {-0x1.5a965659a05e2p-61, 0x1.1a2a7b391e04p-7},
356*71db0c75SAndroid Build Coastguard Worker {-0x1.21ce9b9bfc512p-61, 0x1.1d119606d2554p-7},
357*71db0c75SAndroid Build Coastguard Worker {-0x1.30fda247ad0e1p-61, 0x1.1ff8bc8303c7p-7},
358*71db0c75SAndroid Build Coastguard Worker {-0x1.382c78a45cdeap-62, 0x1.22dfeeae10601p-7},
359*71db0c75SAndroid Build Coastguard Worker {0x1.46ae4a64073d4p-61, 0x1.250d5bf952374p-7},
360*71db0c75SAndroid Build Coastguard Worker {-0x1.dcad2cec3b84bp-62, 0x1.27f4a29740a2fp-7},
361*71db0c75SAndroid Build Coastguard Worker {-0x1.413fbeb0b0635p-61, 0x1.2adbf4e50cdf9p-7},
362*71db0c75SAndroid Build Coastguard Worker {0x1.f28e6a48bcb9p-61, 0x1.2dc352e315049p-7},
363*71db0c75SAndroid Build Coastguard Worker {-0x1.96f286e1eb086p-61, 0x1.30aabc91b72ep-7},
364*71db0c75SAndroid Build Coastguard Worker {-0x1.f88c04206dfa1p-61, 0x1.339231f1517c1p-7},
365*71db0c75SAndroid Build Coastguard Worker {-0x1.11ea20e195841p-61, 0x1.3679b30242139p-7},
366*71db0c75SAndroid Build Coastguard Worker {-0x1.d6e71452b674ap-63, 0x1.39613fc4e71dcp-7},
367*71db0c75SAndroid Build Coastguard Worker {-0x1.57c578233b1b3p-61, 0x1.3c48d8399ec85p-7},
368*71db0c75SAndroid Build Coastguard Worker {-0x1.ec430f03b76ep-63, 0x1.3f307c60c7455p-7},
369*71db0c75SAndroid Build Coastguard Worker {0x1.e00dd1902ffb9p-61, 0x1.42182c3abecb5p-7},
370*71db0c75SAndroid Build Coastguard Worker {-0x1.f22bcd96afe38p-61, 0x1.44ffe7c7e3957p-7},
371*71db0c75SAndroid Build Coastguard Worker {0x1.08fd90f841d3p-61, 0x1.47e7af0893e2fp-7},
372*71db0c75SAndroid Build Coastguard Worker {0x1.09594c5552bccp-62, 0x1.4acf81fd2df7ep-7},
373*71db0c75SAndroid Build Coastguard Worker {-0x1.01a8a652e5602p-61, 0x1.4db760a6101c9p-7},
374*71db0c75SAndroid Build Coastguard Worker {-0x1.826168febb3dp-64, 0x1.509f4b03989dcp-7},
375*71db0c75SAndroid Build Coastguard Worker {-0x1.7eb21a35021e3p-62, 0x1.5387411625cccp-7},
376*71db0c75SAndroid Build Coastguard Worker {-0x1.66cbc818e175p-61, 0x1.566f42de15ff4p-7},
377*71db0c75SAndroid Build Coastguard Worker {0x1.9b784dd6cebdap-64, 0x1.5957505bc78f6p-7},
378*71db0c75SAndroid Build Coastguard Worker {0x1.2b121ab482456p-61, 0x1.5b8562298c65bp-7},
379*71db0c75SAndroid Build Coastguard Worker {-0x1.5d29869dd8233p-62, 0x1.5e6d842633702p-7},
380*71db0c75SAndroid Build Coastguard Worker {-0x1.572a1b6cd63cfp-61, 0x1.6155b1d99f672p-7},
381*71db0c75SAndroid Build Coastguard Worker {-0x1.a1f355360e877p-62, 0x1.643deb442eb59p-7},
382*71db0c75SAndroid Build Coastguard Worker {-0x1.b6f1cd2e1c03fp-61, 0x1.672630663fcadp-7},
383*71db0c75SAndroid Build Coastguard Worker {-0x1.2aaa11ccddcaep-61, 0x1.6a0e8140311aap-7},
384*71db0c75SAndroid Build Coastguard Worker {0x1.3d979ddf4746cp-61, 0x1.6cf6ddd2611d4p-7},
385*71db0c75SAndroid Build Coastguard Worker {-0x1.dc930484501f8p-63, 0x1.6fdf461d2e4f8p-7},
386*71db0c75SAndroid Build Coastguard Worker };
387*71db0c75SAndroid Build Coastguard Worker
is_odd_integer(float x)388*71db0c75SAndroid Build Coastguard Worker LIBC_INLINE bool is_odd_integer(float x) {
389*71db0c75SAndroid Build Coastguard Worker using FPBits = typename fputil::FPBits<float>;
390*71db0c75SAndroid Build Coastguard Worker uint32_t x_u = cpp::bit_cast<uint32_t>(x);
391*71db0c75SAndroid Build Coastguard Worker int32_t x_e =
392*71db0c75SAndroid Build Coastguard Worker static_cast<int32_t>((x_u & FPBits::EXP_MASK) >> FPBits::FRACTION_LEN);
393*71db0c75SAndroid Build Coastguard Worker int32_t lsb = cpp::countr_zero(x_u | FPBits::EXP_MASK);
394*71db0c75SAndroid Build Coastguard Worker constexpr int32_t UNIT_EXPONENT =
395*71db0c75SAndroid Build Coastguard Worker FPBits::EXP_BIAS + static_cast<int32_t>(FPBits::FRACTION_LEN);
396*71db0c75SAndroid Build Coastguard Worker return (x_e + lsb == UNIT_EXPONENT);
397*71db0c75SAndroid Build Coastguard Worker }
398*71db0c75SAndroid Build Coastguard Worker
is_integer(float x)399*71db0c75SAndroid Build Coastguard Worker LIBC_INLINE bool is_integer(float x) {
400*71db0c75SAndroid Build Coastguard Worker using FPBits = typename fputil::FPBits<float>;
401*71db0c75SAndroid Build Coastguard Worker uint32_t x_u = cpp::bit_cast<uint32_t>(x);
402*71db0c75SAndroid Build Coastguard Worker int32_t x_e =
403*71db0c75SAndroid Build Coastguard Worker static_cast<int32_t>((x_u & FPBits::EXP_MASK) >> FPBits::FRACTION_LEN);
404*71db0c75SAndroid Build Coastguard Worker int32_t lsb = cpp::countr_zero(x_u | FPBits::EXP_MASK);
405*71db0c75SAndroid Build Coastguard Worker constexpr int32_t UNIT_EXPONENT =
406*71db0c75SAndroid Build Coastguard Worker FPBits::EXP_BIAS + static_cast<int32_t>(FPBits::FRACTION_LEN);
407*71db0c75SAndroid Build Coastguard Worker return (x_e + lsb >= UNIT_EXPONENT);
408*71db0c75SAndroid Build Coastguard Worker }
409*71db0c75SAndroid Build Coastguard Worker
larger_exponent(double a,double b)410*71db0c75SAndroid Build Coastguard Worker LIBC_INLINE bool larger_exponent(double a, double b) {
411*71db0c75SAndroid Build Coastguard Worker using DoubleBits = typename fputil::FPBits<double>;
412*71db0c75SAndroid Build Coastguard Worker return DoubleBits(a).get_biased_exponent() >=
413*71db0c75SAndroid Build Coastguard Worker DoubleBits(b).get_biased_exponent();
414*71db0c75SAndroid Build Coastguard Worker }
415*71db0c75SAndroid Build Coastguard Worker
416*71db0c75SAndroid Build Coastguard Worker // Calculate 2^(y * log2(x)) in double-double precision.
417*71db0c75SAndroid Build Coastguard Worker // At this point we can reuse the following values:
418*71db0c75SAndroid Build Coastguard Worker // idx_x: index for extra precision of log2 for the middle part of log2(x).
419*71db0c75SAndroid Build Coastguard Worker // dx: the reduced argument for log2(x)
420*71db0c75SAndroid Build Coastguard Worker // y6: 2^6 * y.
421*71db0c75SAndroid Build Coastguard Worker // lo6_hi: the high part of 2^6 * (y - (hi + mid))
422*71db0c75SAndroid Build Coastguard Worker // exp2_hi_mid: high part of 2^(hi + mid)
powf_double_double(int idx_x,double dx,double y6,double lo6_hi,const DoubleDouble & exp2_hi_mid)423*71db0c75SAndroid Build Coastguard Worker double powf_double_double(int idx_x, double dx, double y6, double lo6_hi,
424*71db0c75SAndroid Build Coastguard Worker const DoubleDouble &exp2_hi_mid) {
425*71db0c75SAndroid Build Coastguard Worker using DoubleBits = typename fputil::FPBits<double>;
426*71db0c75SAndroid Build Coastguard Worker
427*71db0c75SAndroid Build Coastguard Worker // Perform a second range reduction step:
428*71db0c75SAndroid Build Coastguard Worker // idx2 = round(2^14 * (dx + 2^-8)) = round ( dx * 2^14 + 2^6)
429*71db0c75SAndroid Build Coastguard Worker // dx2 = (1 + dx) * r2 - 1
430*71db0c75SAndroid Build Coastguard Worker // Output range:
431*71db0c75SAndroid Build Coastguard Worker // -0x1.3ffcp-15 <= dx2 <= 0x1.3e3dp-15
432*71db0c75SAndroid Build Coastguard Worker int idx2 = static_cast<int>(
433*71db0c75SAndroid Build Coastguard Worker fputil::nearest_integer(fputil::multiply_add(dx, 0x1.0p14, 0x1.0p6)));
434*71db0c75SAndroid Build Coastguard Worker double dx2 = fputil::multiply_add(1.0 + dx, R2[idx2], -1.0); // Exact
435*71db0c75SAndroid Build Coastguard Worker
436*71db0c75SAndroid Build Coastguard Worker // Degree-5 polynomial approximation of log2(1 + x)/x in double-double
437*71db0c75SAndroid Build Coastguard Worker // precision. Generate by Solya with:
438*71db0c75SAndroid Build Coastguard Worker // > P = fpminimax(log2(1 + x)/x, 5, [|DD...|],
439*71db0c75SAndroid Build Coastguard Worker // [-0x1.3ffcp-15, 0x1.3e3dp-15]);
440*71db0c75SAndroid Build Coastguard Worker // > dirtyinfnorm(log2(1 + x)/x - P, [-0x1.3ffcp-15, 0x1.3e3dp-15]);
441*71db0c75SAndroid Build Coastguard Worker // 0x1.8be5...p-96.
442*71db0c75SAndroid Build Coastguard Worker constexpr DoubleDouble COEFFS[] = {
443*71db0c75SAndroid Build Coastguard Worker {0x1.777d0ffda25ep-56, 0x1.71547652b82fep0},
444*71db0c75SAndroid Build Coastguard Worker {-0x1.777d101cf0a84p-57, -0x1.71547652b82fep-1},
445*71db0c75SAndroid Build Coastguard Worker {0x1.ce04b5140d867p-56, 0x1.ec709dc3a03fdp-2},
446*71db0c75SAndroid Build Coastguard Worker {0x1.137b47e635be5p-56, -0x1.71547652b82fbp-2},
447*71db0c75SAndroid Build Coastguard Worker {-0x1.b5a30b3bdb318p-58, 0x1.2776c516a92a2p-2},
448*71db0c75SAndroid Build Coastguard Worker {0x1.2d2fbd081e657p-57, -0x1.ec70af1929ca6p-3},
449*71db0c75SAndroid Build Coastguard Worker };
450*71db0c75SAndroid Build Coastguard Worker
451*71db0c75SAndroid Build Coastguard Worker DoubleDouble dx_dd({0.0, dx2});
452*71db0c75SAndroid Build Coastguard Worker DoubleDouble p = fputil::polyeval(dx_dd, COEFFS[0], COEFFS[1], COEFFS[2],
453*71db0c75SAndroid Build Coastguard Worker COEFFS[3], COEFFS[4], COEFFS[5]);
454*71db0c75SAndroid Build Coastguard Worker // log2(1 + dx2) ~ dx2 * P(dx2)
455*71db0c75SAndroid Build Coastguard Worker DoubleDouble log2_x_lo = fputil::quick_mult(dx2, p);
456*71db0c75SAndroid Build Coastguard Worker // Lower parts of (e_x - log2(r1)) of the first range reduction constant
457*71db0c75SAndroid Build Coastguard Worker DoubleDouble log2_x_mid({LOG2_R_TD[idx_x].lo, LOG2_R_TD[idx_x].mid});
458*71db0c75SAndroid Build Coastguard Worker // -log2(r2) + lower part of (e_x - log2(r1))
459*71db0c75SAndroid Build Coastguard Worker DoubleDouble log2_x_m = fputil::add(LOG2_R2_DD[idx2], log2_x_mid);
460*71db0c75SAndroid Build Coastguard Worker // log2(1 + dx2) - log2(r2) + lower part of (e_x - log2(r1))
461*71db0c75SAndroid Build Coastguard Worker // Since we don't know which one has larger exponent to apply Fast2Sum
462*71db0c75SAndroid Build Coastguard Worker // algorithm, we need to check them before calling double-double addition.
463*71db0c75SAndroid Build Coastguard Worker DoubleDouble log2_x = larger_exponent(log2_x_m.hi, log2_x_lo.hi)
464*71db0c75SAndroid Build Coastguard Worker ? fputil::add(log2_x_m, log2_x_lo)
465*71db0c75SAndroid Build Coastguard Worker : fputil::add(log2_x_lo, log2_x_m);
466*71db0c75SAndroid Build Coastguard Worker DoubleDouble lo6_hi_dd({0.0, lo6_hi});
467*71db0c75SAndroid Build Coastguard Worker // 2^6 * y * (log2(1 + dx2) - log2(r2) + lower part of (e_x - log2(r1)))
468*71db0c75SAndroid Build Coastguard Worker DoubleDouble prod = fputil::quick_mult(y6, log2_x);
469*71db0c75SAndroid Build Coastguard Worker // 2^6 * (y * log2(x) - (hi + mid)) = 2^6 * lo
470*71db0c75SAndroid Build Coastguard Worker DoubleDouble lo6 = larger_exponent(prod.hi, lo6_hi)
471*71db0c75SAndroid Build Coastguard Worker ? fputil::add(prod, lo6_hi_dd)
472*71db0c75SAndroid Build Coastguard Worker : fputil::add(lo6_hi_dd, prod);
473*71db0c75SAndroid Build Coastguard Worker
474*71db0c75SAndroid Build Coastguard Worker constexpr DoubleDouble EXP2_COEFFS[] = {
475*71db0c75SAndroid Build Coastguard Worker {0, 0x1p0},
476*71db0c75SAndroid Build Coastguard Worker {0x1.abc9e3b398024p-62, 0x1.62e42fefa39efp-7},
477*71db0c75SAndroid Build Coastguard Worker {-0x1.5e43a5429bddbp-69, 0x1.ebfbdff82c58fp-15},
478*71db0c75SAndroid Build Coastguard Worker {-0x1.d33162491268fp-77, 0x1.c6b08d704a0cp-23},
479*71db0c75SAndroid Build Coastguard Worker {0x1.4fb32d240a14ep-86, 0x1.3b2ab6fba4e77p-31},
480*71db0c75SAndroid Build Coastguard Worker {0x1.e84e916be83ep-97, 0x1.5d87fe78a6731p-40},
481*71db0c75SAndroid Build Coastguard Worker {-0x1.9a447bfddc5e6p-103, 0x1.430912f86bfb8p-49},
482*71db0c75SAndroid Build Coastguard Worker {-0x1.31a55719de47fp-113, 0x1.ffcbfc588ded9p-59},
483*71db0c75SAndroid Build Coastguard Worker {-0x1.0ba57164eb36bp-122, 0x1.62c034beb8339p-68},
484*71db0c75SAndroid Build Coastguard Worker {-0x1.8483eabd9642dp-132, 0x1.b5251ff97bee1p-78},
485*71db0c75SAndroid Build Coastguard Worker };
486*71db0c75SAndroid Build Coastguard Worker
487*71db0c75SAndroid Build Coastguard Worker DoubleDouble pp = fputil::polyeval(
488*71db0c75SAndroid Build Coastguard Worker lo6, EXP2_COEFFS[0], EXP2_COEFFS[1], EXP2_COEFFS[2], EXP2_COEFFS[3],
489*71db0c75SAndroid Build Coastguard Worker EXP2_COEFFS[4], EXP2_COEFFS[5], EXP2_COEFFS[6], EXP2_COEFFS[7],
490*71db0c75SAndroid Build Coastguard Worker EXP2_COEFFS[8], EXP2_COEFFS[9]);
491*71db0c75SAndroid Build Coastguard Worker DoubleDouble rr = fputil::quick_mult(exp2_hi_mid, pp);
492*71db0c75SAndroid Build Coastguard Worker
493*71db0c75SAndroid Build Coastguard Worker // Make sure the sum is normalized:
494*71db0c75SAndroid Build Coastguard Worker DoubleDouble r = fputil::exact_add(rr.hi, rr.lo);
495*71db0c75SAndroid Build Coastguard Worker // Round to odd.
496*71db0c75SAndroid Build Coastguard Worker uint64_t r_bits = cpp::bit_cast<uint64_t>(r.hi);
497*71db0c75SAndroid Build Coastguard Worker if (LIBC_UNLIKELY(((r_bits & 0xfff'ffff) == 0) && (r.lo != 0.0))) {
498*71db0c75SAndroid Build Coastguard Worker Sign hi_sign = DoubleBits(r.hi).sign();
499*71db0c75SAndroid Build Coastguard Worker Sign lo_sign = DoubleBits(r.lo).sign();
500*71db0c75SAndroid Build Coastguard Worker if (hi_sign == lo_sign) {
501*71db0c75SAndroid Build Coastguard Worker ++r_bits;
502*71db0c75SAndroid Build Coastguard Worker } else if ((r_bits & DoubleBits::FRACTION_MASK) > 0) {
503*71db0c75SAndroid Build Coastguard Worker --r_bits;
504*71db0c75SAndroid Build Coastguard Worker }
505*71db0c75SAndroid Build Coastguard Worker }
506*71db0c75SAndroid Build Coastguard Worker
507*71db0c75SAndroid Build Coastguard Worker return cpp::bit_cast<double>(r_bits);
508*71db0c75SAndroid Build Coastguard Worker }
509*71db0c75SAndroid Build Coastguard Worker
510*71db0c75SAndroid Build Coastguard Worker } // namespace
511*71db0c75SAndroid Build Coastguard Worker
512*71db0c75SAndroid Build Coastguard Worker LLVM_LIBC_FUNCTION(float, powf, (float x, float y)) {
513*71db0c75SAndroid Build Coastguard Worker using FloatBits = typename fputil::FPBits<float>;
514*71db0c75SAndroid Build Coastguard Worker using DoubleBits = typename fputil::FPBits<double>;
515*71db0c75SAndroid Build Coastguard Worker
516*71db0c75SAndroid Build Coastguard Worker FloatBits xbits(x), ybits(y);
517*71db0c75SAndroid Build Coastguard Worker
518*71db0c75SAndroid Build Coastguard Worker uint32_t x_u = xbits.uintval();
519*71db0c75SAndroid Build Coastguard Worker uint32_t x_abs = xbits.abs().uintval();
520*71db0c75SAndroid Build Coastguard Worker uint32_t y_u = ybits.uintval();
521*71db0c75SAndroid Build Coastguard Worker uint32_t y_abs = ybits.abs().uintval();
522*71db0c75SAndroid Build Coastguard Worker
523*71db0c75SAndroid Build Coastguard Worker ///////// BEGIN - Check exceptional cases ////////////////////////////////////
524*71db0c75SAndroid Build Coastguard Worker
525*71db0c75SAndroid Build Coastguard Worker // The single precision number that is closest to 1 is (1 - 2^-24), which has
526*71db0c75SAndroid Build Coastguard Worker // log2(1 - 2^-24) ~ -1.715...p-24.
527*71db0c75SAndroid Build Coastguard Worker // So if |y| > 151 * 2^24, and x is finite:
528*71db0c75SAndroid Build Coastguard Worker // |y * log2(x)| = 0 or > 151.
529*71db0c75SAndroid Build Coastguard Worker // Hence x^y will either overflow or underflow if x is not zero.
530*71db0c75SAndroid Build Coastguard Worker if (LIBC_UNLIKELY((y_abs & 0x0007'ffff) == 0) || (y_abs > 0x4f170000)) {
531*71db0c75SAndroid Build Coastguard Worker // Exceptional exponents.
532*71db0c75SAndroid Build Coastguard Worker if (y == 0.0f)
533*71db0c75SAndroid Build Coastguard Worker return 1.0f;
534*71db0c75SAndroid Build Coastguard Worker
535*71db0c75SAndroid Build Coastguard Worker switch (y_abs) {
536*71db0c75SAndroid Build Coastguard Worker case 0x7f80'0000: { // y = +-Inf
537*71db0c75SAndroid Build Coastguard Worker if (x_abs > 0x7f80'0000) {
538*71db0c75SAndroid Build Coastguard Worker // pow(NaN, +-Inf) = NaN
539*71db0c75SAndroid Build Coastguard Worker return x;
540*71db0c75SAndroid Build Coastguard Worker }
541*71db0c75SAndroid Build Coastguard Worker if (x_abs == 0x3f80'0000) {
542*71db0c75SAndroid Build Coastguard Worker // pow(+-1, +-Inf) = 1.0f
543*71db0c75SAndroid Build Coastguard Worker return 1.0f;
544*71db0c75SAndroid Build Coastguard Worker }
545*71db0c75SAndroid Build Coastguard Worker if (x == 0.0f && y_u == 0xff80'0000) {
546*71db0c75SAndroid Build Coastguard Worker // pow(+-0, -Inf) = +inf and raise FE_DIVBYZERO
547*71db0c75SAndroid Build Coastguard Worker fputil::set_errno_if_required(EDOM);
548*71db0c75SAndroid Build Coastguard Worker fputil::raise_except_if_required(FE_DIVBYZERO);
549*71db0c75SAndroid Build Coastguard Worker return FloatBits::inf().get_val();
550*71db0c75SAndroid Build Coastguard Worker }
551*71db0c75SAndroid Build Coastguard Worker // pow (|x| < 1, -inf) = +inf
552*71db0c75SAndroid Build Coastguard Worker // pow (|x| < 1, +inf) = 0.0f
553*71db0c75SAndroid Build Coastguard Worker // pow (|x| > 1, -inf) = 0.0f
554*71db0c75SAndroid Build Coastguard Worker // pow (|x| > 1, +inf) = +inf
555*71db0c75SAndroid Build Coastguard Worker return ((x_abs < 0x3f80'0000) == (y_u == 0xff80'0000))
556*71db0c75SAndroid Build Coastguard Worker ? FloatBits::inf().get_val()
557*71db0c75SAndroid Build Coastguard Worker : 0.0f;
558*71db0c75SAndroid Build Coastguard Worker }
559*71db0c75SAndroid Build Coastguard Worker default:
560*71db0c75SAndroid Build Coastguard Worker // Speed up for common exponents
561*71db0c75SAndroid Build Coastguard Worker switch (y_u) {
562*71db0c75SAndroid Build Coastguard Worker case 0x3f00'0000: // y = 0.5f
563*71db0c75SAndroid Build Coastguard Worker // pow(x, 1/2) = sqrt(x)
564*71db0c75SAndroid Build Coastguard Worker if (LIBC_UNLIKELY(x == 0.0f || x_u == 0xff80'0000)) {
565*71db0c75SAndroid Build Coastguard Worker // pow(-0, 1/2) = +0
566*71db0c75SAndroid Build Coastguard Worker // pow(-inf, 1/2) = +inf
567*71db0c75SAndroid Build Coastguard Worker // Make sure it is correct for FTZ/DAZ.
568*71db0c75SAndroid Build Coastguard Worker return x * x;
569*71db0c75SAndroid Build Coastguard Worker }
570*71db0c75SAndroid Build Coastguard Worker float r;
571*71db0c75SAndroid Build Coastguard Worker r = fputil::sqrt<float>(x);
572*71db0c75SAndroid Build Coastguard Worker return (FloatBits(r).uintval() != 0x8000'0000) ? r : 0.0f;
573*71db0c75SAndroid Build Coastguard Worker case 0x3f80'0000: // y = 1.0f
574*71db0c75SAndroid Build Coastguard Worker return x;
575*71db0c75SAndroid Build Coastguard Worker case 0x4000'0000: // y = 2.0f
576*71db0c75SAndroid Build Coastguard Worker // pow(x, 2) = x^2
577*71db0c75SAndroid Build Coastguard Worker return x * x;
578*71db0c75SAndroid Build Coastguard Worker // TODO: Enable special case speed-up for x^(-1/2) when rsqrt is ready.
579*71db0c75SAndroid Build Coastguard Worker // case 0xbf00'0000: // pow(x, -1/2) = rsqrt(x)
580*71db0c75SAndroid Build Coastguard Worker // return rsqrt(x);
581*71db0c75SAndroid Build Coastguard Worker }
582*71db0c75SAndroid Build Coastguard Worker if (is_integer(y) && (y_u > 0x4000'0000) && (y_u <= 0x41c0'0000)) {
583*71db0c75SAndroid Build Coastguard Worker // Check for exact cases when 2 < y < 25 and y is an integer.
584*71db0c75SAndroid Build Coastguard Worker int msb =
585*71db0c75SAndroid Build Coastguard Worker (x_abs == 0) ? (FloatBits::TOTAL_LEN - 2) : cpp::countl_zero(x_abs);
586*71db0c75SAndroid Build Coastguard Worker msb = (msb > FloatBits::EXP_LEN) ? msb : FloatBits::EXP_LEN;
587*71db0c75SAndroid Build Coastguard Worker int lsb = (x_abs == 0) ? 0 : cpp::countr_zero(x_abs);
588*71db0c75SAndroid Build Coastguard Worker lsb = (lsb > FloatBits::FRACTION_LEN) ? FloatBits::FRACTION_LEN : lsb;
589*71db0c75SAndroid Build Coastguard Worker int extra_bits = FloatBits::TOTAL_LEN - 2 - lsb - msb;
590*71db0c75SAndroid Build Coastguard Worker int iter = static_cast<int>(y);
591*71db0c75SAndroid Build Coastguard Worker
592*71db0c75SAndroid Build Coastguard Worker if (extra_bits * iter <= FloatBits::FRACTION_LEN + 2) {
593*71db0c75SAndroid Build Coastguard Worker // The result is either exact or exactly half-way.
594*71db0c75SAndroid Build Coastguard Worker // But it is exactly representable in double precision.
595*71db0c75SAndroid Build Coastguard Worker double x_d = static_cast<double>(x);
596*71db0c75SAndroid Build Coastguard Worker double result = x_d;
597*71db0c75SAndroid Build Coastguard Worker for (int i = 1; i < iter; ++i)
598*71db0c75SAndroid Build Coastguard Worker result *= x_d;
599*71db0c75SAndroid Build Coastguard Worker return static_cast<float>(result);
600*71db0c75SAndroid Build Coastguard Worker }
601*71db0c75SAndroid Build Coastguard Worker }
602*71db0c75SAndroid Build Coastguard Worker if (y_abs > 0x4f17'0000) {
603*71db0c75SAndroid Build Coastguard Worker if (y_abs > 0x7f80'0000) {
604*71db0c75SAndroid Build Coastguard Worker // y is NaN
605*71db0c75SAndroid Build Coastguard Worker if (x_u == 0x3f80'0000) { // x = 1.0f
606*71db0c75SAndroid Build Coastguard Worker // pow(1, NaN) = 1
607*71db0c75SAndroid Build Coastguard Worker return 1.0f;
608*71db0c75SAndroid Build Coastguard Worker }
609*71db0c75SAndroid Build Coastguard Worker // pow(x, NaN) = NaN
610*71db0c75SAndroid Build Coastguard Worker return y;
611*71db0c75SAndroid Build Coastguard Worker }
612*71db0c75SAndroid Build Coastguard Worker // x^y will be overflow / underflow in single precision. Set y to a
613*71db0c75SAndroid Build Coastguard Worker // large enough exponent but not too large, so that the computations
614*71db0c75SAndroid Build Coastguard Worker // won't be overflow in double precision.
615*71db0c75SAndroid Build Coastguard Worker y = cpp::bit_cast<float>((y_u & FloatBits::SIGN_MASK) + 0x4f800000U);
616*71db0c75SAndroid Build Coastguard Worker }
617*71db0c75SAndroid Build Coastguard Worker }
618*71db0c75SAndroid Build Coastguard Worker }
619*71db0c75SAndroid Build Coastguard Worker
620*71db0c75SAndroid Build Coastguard Worker int ex = -FloatBits::EXP_BIAS;
621*71db0c75SAndroid Build Coastguard Worker uint64_t sign = 0;
622*71db0c75SAndroid Build Coastguard Worker
623*71db0c75SAndroid Build Coastguard Worker // y is finite and non-zero.
624*71db0c75SAndroid Build Coastguard Worker if (LIBC_UNLIKELY(((x_u & 0x801f'ffffU) == 0) || x_u >= 0x7f80'0000U ||
625*71db0c75SAndroid Build Coastguard Worker x_u < 0x0080'0000U)) {
626*71db0c75SAndroid Build Coastguard Worker switch (x_u) {
627*71db0c75SAndroid Build Coastguard Worker case 0x3f80'0000: // x = 1.0f
628*71db0c75SAndroid Build Coastguard Worker return 1.0f;
629*71db0c75SAndroid Build Coastguard Worker // TODO: Put these 2 entrypoint dependency under control flag.
630*71db0c75SAndroid Build Coastguard Worker case 0x4000'0000: // x = 2.0f
631*71db0c75SAndroid Build Coastguard Worker // pow(2, y) = exp2(y)
632*71db0c75SAndroid Build Coastguard Worker return generic::exp2f(y);
633*71db0c75SAndroid Build Coastguard Worker case 0x4120'0000: // x = 10.0f
634*71db0c75SAndroid Build Coastguard Worker // pow(10, y) = exp10(y)
635*71db0c75SAndroid Build Coastguard Worker return generic::exp10f(y);
636*71db0c75SAndroid Build Coastguard Worker }
637*71db0c75SAndroid Build Coastguard Worker
638*71db0c75SAndroid Build Coastguard Worker const bool x_is_neg = x_u >= FloatBits::SIGN_MASK;
639*71db0c75SAndroid Build Coastguard Worker
640*71db0c75SAndroid Build Coastguard Worker if (x == 0.0f) {
641*71db0c75SAndroid Build Coastguard Worker const bool out_is_neg =
642*71db0c75SAndroid Build Coastguard Worker x_is_neg && is_odd_integer(FloatBits(y_u).get_val());
643*71db0c75SAndroid Build Coastguard Worker if (y_u > 0x8000'0000U) {
644*71db0c75SAndroid Build Coastguard Worker // pow(0, negative number) = inf
645*71db0c75SAndroid Build Coastguard Worker fputil::set_errno_if_required(EDOM);
646*71db0c75SAndroid Build Coastguard Worker fputil::raise_except_if_required(FE_DIVBYZERO);
647*71db0c75SAndroid Build Coastguard Worker return FloatBits::inf(out_is_neg ? Sign::NEG : Sign::POS).get_val();
648*71db0c75SAndroid Build Coastguard Worker }
649*71db0c75SAndroid Build Coastguard Worker // pow(0, positive number) = 0
650*71db0c75SAndroid Build Coastguard Worker return out_is_neg ? -0.0f : 0.0f;
651*71db0c75SAndroid Build Coastguard Worker }
652*71db0c75SAndroid Build Coastguard Worker
653*71db0c75SAndroid Build Coastguard Worker if (x_abs == 0x7f80'0000) {
654*71db0c75SAndroid Build Coastguard Worker // x = +-Inf
655*71db0c75SAndroid Build Coastguard Worker const bool out_is_neg =
656*71db0c75SAndroid Build Coastguard Worker x_is_neg && is_odd_integer(FloatBits(y_u).get_val());
657*71db0c75SAndroid Build Coastguard Worker if (y_u >= FloatBits::SIGN_MASK) {
658*71db0c75SAndroid Build Coastguard Worker return out_is_neg ? -0.0f : 0.0f;
659*71db0c75SAndroid Build Coastguard Worker }
660*71db0c75SAndroid Build Coastguard Worker return FloatBits::inf(out_is_neg ? Sign::NEG : Sign::POS).get_val();
661*71db0c75SAndroid Build Coastguard Worker }
662*71db0c75SAndroid Build Coastguard Worker
663*71db0c75SAndroid Build Coastguard Worker if (x_abs > 0x7f80'0000) {
664*71db0c75SAndroid Build Coastguard Worker // x is NaN.
665*71db0c75SAndroid Build Coastguard Worker // pow (aNaN, 0) is already taken care above.
666*71db0c75SAndroid Build Coastguard Worker return x;
667*71db0c75SAndroid Build Coastguard Worker }
668*71db0c75SAndroid Build Coastguard Worker
669*71db0c75SAndroid Build Coastguard Worker // Normalize denormal inputs.
670*71db0c75SAndroid Build Coastguard Worker if (x_abs < 0x0080'0000U) {
671*71db0c75SAndroid Build Coastguard Worker ex -= 64;
672*71db0c75SAndroid Build Coastguard Worker x *= 0x1.0p64f;
673*71db0c75SAndroid Build Coastguard Worker }
674*71db0c75SAndroid Build Coastguard Worker
675*71db0c75SAndroid Build Coastguard Worker // x is finite and negative, and y is a finite integer.
676*71db0c75SAndroid Build Coastguard Worker if (x_is_neg) {
677*71db0c75SAndroid Build Coastguard Worker if (is_integer(y)) {
678*71db0c75SAndroid Build Coastguard Worker x = -x;
679*71db0c75SAndroid Build Coastguard Worker if (is_odd_integer(y)) {
680*71db0c75SAndroid Build Coastguard Worker // sign = -1.0;
681*71db0c75SAndroid Build Coastguard Worker sign = 0x8000'0000'0000'0000ULL;
682*71db0c75SAndroid Build Coastguard Worker }
683*71db0c75SAndroid Build Coastguard Worker } else {
684*71db0c75SAndroid Build Coastguard Worker // pow( negative, non-integer ) = NaN
685*71db0c75SAndroid Build Coastguard Worker fputil::set_errno_if_required(EDOM);
686*71db0c75SAndroid Build Coastguard Worker fputil::raise_except_if_required(FE_INVALID);
687*71db0c75SAndroid Build Coastguard Worker return FloatBits::quiet_nan().get_val();
688*71db0c75SAndroid Build Coastguard Worker }
689*71db0c75SAndroid Build Coastguard Worker }
690*71db0c75SAndroid Build Coastguard Worker }
691*71db0c75SAndroid Build Coastguard Worker
692*71db0c75SAndroid Build Coastguard Worker ///////// END - Check exceptional cases //////////////////////////////////////
693*71db0c75SAndroid Build Coastguard Worker
694*71db0c75SAndroid Build Coastguard Worker // x^y = 2^( y * log2(x) )
695*71db0c75SAndroid Build Coastguard Worker // = 2^( y * ( e_x + log2(m_x) ) )
696*71db0c75SAndroid Build Coastguard Worker // First we compute log2(x) = e_x + log2(m_x)
697*71db0c75SAndroid Build Coastguard Worker x_u = FloatBits(x).uintval();
698*71db0c75SAndroid Build Coastguard Worker
699*71db0c75SAndroid Build Coastguard Worker // Extract exponent field of x.
700*71db0c75SAndroid Build Coastguard Worker ex += (x_u >> FloatBits::FRACTION_LEN);
701*71db0c75SAndroid Build Coastguard Worker double e_x = static_cast<double>(ex);
702*71db0c75SAndroid Build Coastguard Worker // Use the highest 7 fractional bits of m_x as the index for look up tables.
703*71db0c75SAndroid Build Coastguard Worker uint32_t x_mant = x_u & FloatBits::FRACTION_MASK;
704*71db0c75SAndroid Build Coastguard Worker int idx_x = static_cast<int>(x_mant >> (FloatBits::FRACTION_LEN - 7));
705*71db0c75SAndroid Build Coastguard Worker // Add the hidden bit to the mantissa.
706*71db0c75SAndroid Build Coastguard Worker // 1 <= m_x < 2
707*71db0c75SAndroid Build Coastguard Worker float m_x = cpp::bit_cast<float>(x_mant | 0x3f800000);
708*71db0c75SAndroid Build Coastguard Worker
709*71db0c75SAndroid Build Coastguard Worker // Reduced argument for log2(m_x):
710*71db0c75SAndroid Build Coastguard Worker // dx = r * m_x - 1.
711*71db0c75SAndroid Build Coastguard Worker // The computation is exact, and -2^-8 <= dx < 2^-7.
712*71db0c75SAndroid Build Coastguard Worker // Then m_x = (1 + dx) / r, and
713*71db0c75SAndroid Build Coastguard Worker // log2(m_x) = log2( (1 + dx) / r )
714*71db0c75SAndroid Build Coastguard Worker // = log2(1 + dx) - log2(r).
715*71db0c75SAndroid Build Coastguard Worker double dx;
716*71db0c75SAndroid Build Coastguard Worker #ifdef LIBC_TARGET_CPU_HAS_FMA
717*71db0c75SAndroid Build Coastguard Worker dx = static_cast<double>(fputil::multiply_add(m_x, R[idx_x], -1.0f)); // Exact
718*71db0c75SAndroid Build Coastguard Worker #else
719*71db0c75SAndroid Build Coastguard Worker dx = fputil::multiply_add(static_cast<double>(m_x), RD[idx_x], -1.0); // Exact
720*71db0c75SAndroid Build Coastguard Worker #endif // LIBC_TARGET_CPU_HAS_FMA
721*71db0c75SAndroid Build Coastguard Worker
722*71db0c75SAndroid Build Coastguard Worker // Degree-5 polynomial approximation:
723*71db0c75SAndroid Build Coastguard Worker // dx * P(dx) ~ log2(1 + dx)
724*71db0c75SAndroid Build Coastguard Worker // Generated by Sollya with:
725*71db0c75SAndroid Build Coastguard Worker // > P = fpminimax(log2(1 + x)/x, 5, [|D...|], [-2^-8, 2^-7]);
726*71db0c75SAndroid Build Coastguard Worker // > dirtyinfnorm(log2(1 + x)/x - P, [-2^-8, 2^-7]);
727*71db0c75SAndroid Build Coastguard Worker // 0x1.653...p-52
728*71db0c75SAndroid Build Coastguard Worker constexpr double COEFFS[] = {0x1.71547652b82fep0, -0x1.71547652b7a07p-1,
729*71db0c75SAndroid Build Coastguard Worker 0x1.ec709dc458db1p-2, -0x1.715479c2266c9p-2,
730*71db0c75SAndroid Build Coastguard Worker 0x1.2776ae1ddf8fp-2, -0x1.e7b2178870157p-3};
731*71db0c75SAndroid Build Coastguard Worker
732*71db0c75SAndroid Build Coastguard Worker double dx2 = dx * dx; // Exact
733*71db0c75SAndroid Build Coastguard Worker double c0 = fputil::multiply_add(dx, COEFFS[1], COEFFS[0]);
734*71db0c75SAndroid Build Coastguard Worker double c1 = fputil::multiply_add(dx, COEFFS[3], COEFFS[2]);
735*71db0c75SAndroid Build Coastguard Worker double c2 = fputil::multiply_add(dx, COEFFS[5], COEFFS[4]);
736*71db0c75SAndroid Build Coastguard Worker
737*71db0c75SAndroid Build Coastguard Worker double p = fputil::polyeval(dx2, c0, c1, c2);
738*71db0c75SAndroid Build Coastguard Worker
739*71db0c75SAndroid Build Coastguard Worker //////////////////////////////////////////////////////////////////////////////
740*71db0c75SAndroid Build Coastguard Worker // NOTE: For some reason, this is significantly less efficient than above!
741*71db0c75SAndroid Build Coastguard Worker //
742*71db0c75SAndroid Build Coastguard Worker // > P = fpminimax(log2(1 + x)/x, 4, [|D...|], [-2^-8, 2^-7]);
743*71db0c75SAndroid Build Coastguard Worker // > dirtyinfnorm(log2(1 + x)/x - P, [-2^-8, 2^-7]);
744*71db0c75SAndroid Build Coastguard Worker // 0x1.d04...p-44
745*71db0c75SAndroid Build Coastguard Worker // constexpr double COEFFS[] = {0x1.71547652b8133p0, -0x1.71547652d1e33p-1,
746*71db0c75SAndroid Build Coastguard Worker // 0x1.ec70a098473dep-2, -0x1.7154c5ccdf121p-2,
747*71db0c75SAndroid Build Coastguard Worker // 0x1.2514fd90a130ap-2};
748*71db0c75SAndroid Build Coastguard Worker //
749*71db0c75SAndroid Build Coastguard Worker // double dx2 = dx * dx;
750*71db0c75SAndroid Build Coastguard Worker // double c0 = fputil::multiply_add(dx, COEFFS[1], COEFFS[0]);
751*71db0c75SAndroid Build Coastguard Worker // double c1 = fputil::multiply_add(dx, COEFFS[3], COEFFS[2]);
752*71db0c75SAndroid Build Coastguard Worker // double p = fputil::polyeval(dx2, c0, c1, COEFFS[4]);
753*71db0c75SAndroid Build Coastguard Worker //////////////////////////////////////////////////////////////////////////////
754*71db0c75SAndroid Build Coastguard Worker
755*71db0c75SAndroid Build Coastguard Worker // s = e_x - log2(r) + dx * P(dx)
756*71db0c75SAndroid Build Coastguard Worker // Approximation errors:
757*71db0c75SAndroid Build Coastguard Worker // |log2(x) - s| < ulp(e_x) + (bounds on dx) * (error bounds of P(dx))
758*71db0c75SAndroid Build Coastguard Worker // = ulp(e_x) + 2^-7 * 2^-51
759*71db0c75SAndroid Build Coastguard Worker // < 2^8 * 2^-52 + 2^-7 * 2^-43
760*71db0c75SAndroid Build Coastguard Worker // ~ 2^-44 + 2^-50
761*71db0c75SAndroid Build Coastguard Worker double s = fputil::multiply_add(dx, p, LOG2_R[idx_x] + e_x);
762*71db0c75SAndroid Build Coastguard Worker
763*71db0c75SAndroid Build Coastguard Worker // To compute 2^(y * log2(x)), we break the exponent into 3 parts:
764*71db0c75SAndroid Build Coastguard Worker // y * log(2) = hi + mid + lo, where
765*71db0c75SAndroid Build Coastguard Worker // hi is an integer
766*71db0c75SAndroid Build Coastguard Worker // mid * 2^6 is an integer
767*71db0c75SAndroid Build Coastguard Worker // |lo| <= 2^-7
768*71db0c75SAndroid Build Coastguard Worker // Then:
769*71db0c75SAndroid Build Coastguard Worker // x^y = 2^(y * log2(x)) = 2^hi * 2^mid * 2^lo,
770*71db0c75SAndroid Build Coastguard Worker // In which 2^mid is obtained from a look-up table of size 2^6 = 64 elements,
771*71db0c75SAndroid Build Coastguard Worker // and 2^lo ~ 1 + lo * P(lo).
772*71db0c75SAndroid Build Coastguard Worker // Thus, we have:
773*71db0c75SAndroid Build Coastguard Worker // hi + mid = 2^-6 * round( 2^6 * y * log2(x) )
774*71db0c75SAndroid Build Coastguard Worker // If we restrict the output such that |hi| < 150, (hi + mid) uses (8 + 6)
775*71db0c75SAndroid Build Coastguard Worker // bits, hence, if we use double precision to perform
776*71db0c75SAndroid Build Coastguard Worker // round( 2^6 * y * log2(x))
777*71db0c75SAndroid Build Coastguard Worker // the lo part is bounded by 2^-7 + 2^(-(52 - 14)) = 2^-7 + 2^-38
778*71db0c75SAndroid Build Coastguard Worker
779*71db0c75SAndroid Build Coastguard Worker // In the following computations:
780*71db0c75SAndroid Build Coastguard Worker // y6 = 2^6 * y
781*71db0c75SAndroid Build Coastguard Worker // hm = 2^6 * (hi + mid) = round(2^6 * y * log2(x)) ~ round(y6 * s)
782*71db0c75SAndroid Build Coastguard Worker // lo6 = 2^6 * lo = 2^6 * (y - (hi + mid)) = y6 * log2(x) - hm.
783*71db0c75SAndroid Build Coastguard Worker double y6 = static_cast<double>(y * 0x1.0p6f); // Exact.
784*71db0c75SAndroid Build Coastguard Worker double hm = fputil::nearest_integer(s * y6);
785*71db0c75SAndroid Build Coastguard Worker // lo6 = 2^6 * lo.
786*71db0c75SAndroid Build Coastguard Worker double lo6_hi =
787*71db0c75SAndroid Build Coastguard Worker fputil::multiply_add(y6, e_x + LOG2_R_TD[idx_x].hi, -hm); // Exact
788*71db0c75SAndroid Build Coastguard Worker // Error bounds:
789*71db0c75SAndroid Build Coastguard Worker // | (y*log2(x) - hm * 2^-6 - lo) / y| < err(dx * p) + err(LOG2_R_DD.lo)
790*71db0c75SAndroid Build Coastguard Worker // < 2^-51 + 2^-75
791*71db0c75SAndroid Build Coastguard Worker double lo6 = fputil::multiply_add(
792*71db0c75SAndroid Build Coastguard Worker y6, fputil::multiply_add(dx, p, LOG2_R_TD[idx_x].mid), lo6_hi);
793*71db0c75SAndroid Build Coastguard Worker
794*71db0c75SAndroid Build Coastguard Worker // |2^(hi + mid) - exp2_hi_mid| <= ulp(exp2_hi_mid) / 2
795*71db0c75SAndroid Build Coastguard Worker // Clamp the exponent part into smaller range that fits double precision.
796*71db0c75SAndroid Build Coastguard Worker // For those exponents that are out of range, the final conversion will round
797*71db0c75SAndroid Build Coastguard Worker // them correctly to inf/max float or 0/min float accordingly.
798*71db0c75SAndroid Build Coastguard Worker int64_t hm_i = static_cast<int64_t>(hm);
799*71db0c75SAndroid Build Coastguard Worker hm_i = (hm_i > (1 << 15)) ? (1 << 15)
800*71db0c75SAndroid Build Coastguard Worker : (hm_i < (-(1 << 15)) ? -(1 << 15) : hm_i);
801*71db0c75SAndroid Build Coastguard Worker
802*71db0c75SAndroid Build Coastguard Worker int idx_y = hm_i & 0x3f;
803*71db0c75SAndroid Build Coastguard Worker
804*71db0c75SAndroid Build Coastguard Worker // 2^hi
805*71db0c75SAndroid Build Coastguard Worker int64_t exp_hi_i = (hm_i >> 6) << DoubleBits::FRACTION_LEN;
806*71db0c75SAndroid Build Coastguard Worker // 2^mid
807*71db0c75SAndroid Build Coastguard Worker int64_t exp_mid_i = cpp::bit_cast<uint64_t>(EXP2_MID1[idx_y].hi);
808*71db0c75SAndroid Build Coastguard Worker // (-1)^sign * 2^hi * 2^mid
809*71db0c75SAndroid Build Coastguard Worker // Error <= 2^hi * 2^-53
810*71db0c75SAndroid Build Coastguard Worker uint64_t exp2_hi_mid_i = static_cast<uint64_t>(exp_hi_i + exp_mid_i) + sign;
811*71db0c75SAndroid Build Coastguard Worker double exp2_hi_mid = cpp::bit_cast<double>(exp2_hi_mid_i);
812*71db0c75SAndroid Build Coastguard Worker
813*71db0c75SAndroid Build Coastguard Worker // Degree-5 polynomial approximation P(lo6) ~ 2^(lo6 / 2^6) = 2^(lo).
814*71db0c75SAndroid Build Coastguard Worker // Generated by Sollya with:
815*71db0c75SAndroid Build Coastguard Worker // > P = fpminimax(2^(x/64), 5, [|1, D...|], [-2^-1, 2^-1]);
816*71db0c75SAndroid Build Coastguard Worker // > dirtyinfnorm(2^(x/64) - P, [-0.5, 0.5]);
817*71db0c75SAndroid Build Coastguard Worker // 0x1.a2b77e618f5c4c176fd11b7659016cde5de83cb72p-60
818*71db0c75SAndroid Build Coastguard Worker constexpr double EXP2_COEFFS[] = {0x1p0,
819*71db0c75SAndroid Build Coastguard Worker 0x1.62e42fefa39efp-7,
820*71db0c75SAndroid Build Coastguard Worker 0x1.ebfbdff82a23ap-15,
821*71db0c75SAndroid Build Coastguard Worker 0x1.c6b08d7076268p-23,
822*71db0c75SAndroid Build Coastguard Worker 0x1.3b2ad33f8b48bp-31,
823*71db0c75SAndroid Build Coastguard Worker 0x1.5d870c4d84445p-40};
824*71db0c75SAndroid Build Coastguard Worker
825*71db0c75SAndroid Build Coastguard Worker double lo6_sqr = lo6 * lo6;
826*71db0c75SAndroid Build Coastguard Worker double d0 = fputil::multiply_add(lo6, EXP2_COEFFS[1], EXP2_COEFFS[0]);
827*71db0c75SAndroid Build Coastguard Worker double d1 = fputil::multiply_add(lo6, EXP2_COEFFS[3], EXP2_COEFFS[2]);
828*71db0c75SAndroid Build Coastguard Worker double d2 = fputil::multiply_add(lo6, EXP2_COEFFS[5], EXP2_COEFFS[4]);
829*71db0c75SAndroid Build Coastguard Worker double pp = fputil::polyeval(lo6_sqr, d0, d1, d2);
830*71db0c75SAndroid Build Coastguard Worker
831*71db0c75SAndroid Build Coastguard Worker double r = pp * exp2_hi_mid;
832*71db0c75SAndroid Build Coastguard Worker
833*71db0c75SAndroid Build Coastguard Worker // Ziv accuracy test.
834*71db0c75SAndroid Build Coastguard Worker uint64_t r_u = cpp::bit_cast<uint64_t>(r);
835*71db0c75SAndroid Build Coastguard Worker float r_upper = static_cast<float>(cpp::bit_cast<double>(r_u + ERR));
836*71db0c75SAndroid Build Coastguard Worker float r_lower = static_cast<float>(cpp::bit_cast<double>(r_u - ERR));
837*71db0c75SAndroid Build Coastguard Worker
838*71db0c75SAndroid Build Coastguard Worker if (LIBC_LIKELY(r_upper == r_lower)) {
839*71db0c75SAndroid Build Coastguard Worker // Check for overflow or underflow.
840*71db0c75SAndroid Build Coastguard Worker if (LIBC_UNLIKELY(FloatBits(r_upper).get_mantissa() == 0)) {
841*71db0c75SAndroid Build Coastguard Worker if (FloatBits(r_upper).is_inf()) {
842*71db0c75SAndroid Build Coastguard Worker fputil::set_errno_if_required(ERANGE);
843*71db0c75SAndroid Build Coastguard Worker fputil::raise_except_if_required(FE_OVERFLOW);
844*71db0c75SAndroid Build Coastguard Worker } else if (r_upper == 0.0f) {
845*71db0c75SAndroid Build Coastguard Worker fputil::set_errno_if_required(ERANGE);
846*71db0c75SAndroid Build Coastguard Worker fputil::raise_except_if_required(FE_UNDERFLOW);
847*71db0c75SAndroid Build Coastguard Worker }
848*71db0c75SAndroid Build Coastguard Worker }
849*71db0c75SAndroid Build Coastguard Worker return r_upper;
850*71db0c75SAndroid Build Coastguard Worker }
851*71db0c75SAndroid Build Coastguard Worker
852*71db0c75SAndroid Build Coastguard Worker // Scale lower part of 2^(hi + mid)
853*71db0c75SAndroid Build Coastguard Worker DoubleDouble exp2_hi_mid_dd;
854*71db0c75SAndroid Build Coastguard Worker exp2_hi_mid_dd.lo =
855*71db0c75SAndroid Build Coastguard Worker (idx_y != 0)
856*71db0c75SAndroid Build Coastguard Worker ? cpp::bit_cast<double>(exp_hi_i +
857*71db0c75SAndroid Build Coastguard Worker cpp::bit_cast<int64_t>(EXP2_MID1[idx_y].mid))
858*71db0c75SAndroid Build Coastguard Worker : 0.0;
859*71db0c75SAndroid Build Coastguard Worker exp2_hi_mid_dd.hi = exp2_hi_mid;
860*71db0c75SAndroid Build Coastguard Worker
861*71db0c75SAndroid Build Coastguard Worker double r_dd = powf_double_double(idx_x, dx, y6, lo6_hi, exp2_hi_mid_dd);
862*71db0c75SAndroid Build Coastguard Worker
863*71db0c75SAndroid Build Coastguard Worker return static_cast<float>(r_dd);
864*71db0c75SAndroid Build Coastguard Worker }
865*71db0c75SAndroid Build Coastguard Worker
866*71db0c75SAndroid Build Coastguard Worker } // namespace LIBC_NAMESPACE_DECL
867