1*71db0c75SAndroid Build Coastguard Worker //===-- Single-precision general exp/log functions ------------------------===//
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 #ifndef LLVM_LIBC_SRC_MATH_GENERIC_EXPLOGXF_H
10*71db0c75SAndroid Build Coastguard Worker #define LLVM_LIBC_SRC_MATH_GENERIC_EXPLOGXF_H
11*71db0c75SAndroid Build Coastguard Worker
12*71db0c75SAndroid Build Coastguard Worker #include "common_constants.h"
13*71db0c75SAndroid Build Coastguard Worker #include "src/__support/CPP/bit.h"
14*71db0c75SAndroid Build Coastguard Worker #include "src/__support/CPP/optional.h"
15*71db0c75SAndroid Build Coastguard Worker #include "src/__support/FPUtil/FEnvImpl.h"
16*71db0c75SAndroid Build Coastguard Worker #include "src/__support/FPUtil/FPBits.h"
17*71db0c75SAndroid Build Coastguard Worker #include "src/__support/FPUtil/PolyEval.h"
18*71db0c75SAndroid Build Coastguard Worker #include "src/__support/FPUtil/nearest_integer.h"
19*71db0c75SAndroid Build Coastguard Worker #include "src/__support/common.h"
20*71db0c75SAndroid Build Coastguard Worker #include "src/__support/macros/config.h"
21*71db0c75SAndroid Build Coastguard Worker #include "src/__support/macros/properties/cpu_features.h"
22*71db0c75SAndroid Build Coastguard Worker
23*71db0c75SAndroid Build Coastguard Worker namespace LIBC_NAMESPACE_DECL {
24*71db0c75SAndroid Build Coastguard Worker
25*71db0c75SAndroid Build Coastguard Worker struct ExpBase {
26*71db0c75SAndroid Build Coastguard Worker // Base = e
27*71db0c75SAndroid Build Coastguard Worker static constexpr int MID_BITS = 5;
28*71db0c75SAndroid Build Coastguard Worker static constexpr int MID_MASK = (1 << MID_BITS) - 1;
29*71db0c75SAndroid Build Coastguard Worker // log2(e) * 2^5
30*71db0c75SAndroid Build Coastguard Worker static constexpr double LOG2_B = 0x1.71547652b82fep+0 * (1 << MID_BITS);
31*71db0c75SAndroid Build Coastguard Worker // High and low parts of -log(2) * 2^(-5)
32*71db0c75SAndroid Build Coastguard Worker static constexpr double M_LOGB_2_HI = -0x1.62e42fefa0000p-1 / (1 << MID_BITS);
33*71db0c75SAndroid Build Coastguard Worker static constexpr double M_LOGB_2_LO =
34*71db0c75SAndroid Build Coastguard Worker -0x1.cf79abc9e3b3ap-40 / (1 << MID_BITS);
35*71db0c75SAndroid Build Coastguard Worker // Look up table for bit fields of 2^(i/32) for i = 0..31, generated by Sollya
36*71db0c75SAndroid Build Coastguard Worker // with:
37*71db0c75SAndroid Build Coastguard Worker // > for i from 0 to 31 do printdouble(round(2^(i/32), D, RN));
38*71db0c75SAndroid Build Coastguard Worker static constexpr int64_t EXP_2_MID[1 << MID_BITS] = {
39*71db0c75SAndroid Build Coastguard Worker 0x3ff0000000000000, 0x3ff059b0d3158574, 0x3ff0b5586cf9890f,
40*71db0c75SAndroid Build Coastguard Worker 0x3ff11301d0125b51, 0x3ff172b83c7d517b, 0x3ff1d4873168b9aa,
41*71db0c75SAndroid Build Coastguard Worker 0x3ff2387a6e756238, 0x3ff29e9df51fdee1, 0x3ff306fe0a31b715,
42*71db0c75SAndroid Build Coastguard Worker 0x3ff371a7373aa9cb, 0x3ff3dea64c123422, 0x3ff44e086061892d,
43*71db0c75SAndroid Build Coastguard Worker 0x3ff4bfdad5362a27, 0x3ff5342b569d4f82, 0x3ff5ab07dd485429,
44*71db0c75SAndroid Build Coastguard Worker 0x3ff6247eb03a5585, 0x3ff6a09e667f3bcd, 0x3ff71f75e8ec5f74,
45*71db0c75SAndroid Build Coastguard Worker 0x3ff7a11473eb0187, 0x3ff82589994cce13, 0x3ff8ace5422aa0db,
46*71db0c75SAndroid Build Coastguard Worker 0x3ff93737b0cdc5e5, 0x3ff9c49182a3f090, 0x3ffa5503b23e255d,
47*71db0c75SAndroid Build Coastguard Worker 0x3ffae89f995ad3ad, 0x3ffb7f76f2fb5e47, 0x3ffc199bdd85529c,
48*71db0c75SAndroid Build Coastguard Worker 0x3ffcb720dcef9069, 0x3ffd5818dcfba487, 0x3ffdfc97337b9b5f,
49*71db0c75SAndroid Build Coastguard Worker 0x3ffea4afa2a490da, 0x3fff50765b6e4540,
50*71db0c75SAndroid Build Coastguard Worker };
51*71db0c75SAndroid Build Coastguard Worker
52*71db0c75SAndroid Build Coastguard Worker // Approximating e^dx with degree-5 minimax polynomial generated by Sollya:
53*71db0c75SAndroid Build Coastguard Worker // > Q = fpminimax(expm1(x)/x, 4, [|1, D...|], [-log(2)/64, log(2)/64]);
54*71db0c75SAndroid Build Coastguard Worker // Then:
55*71db0c75SAndroid Build Coastguard Worker // e^dx ~ P(dx) = 1 + dx + COEFFS[0] * dx^2 + ... + COEFFS[3] * dx^5.
56*71db0c75SAndroid Build Coastguard Worker static constexpr double COEFFS[4] = {
57*71db0c75SAndroid Build Coastguard Worker 0x1.ffffffffe5bc8p-2, 0x1.555555555cd67p-3, 0x1.5555c2a9b48b4p-5,
58*71db0c75SAndroid Build Coastguard Worker 0x1.11112a0e34bdbp-7};
59*71db0c75SAndroid Build Coastguard Worker
powb_loExpBase60*71db0c75SAndroid Build Coastguard Worker LIBC_INLINE static double powb_lo(double dx) {
61*71db0c75SAndroid Build Coastguard Worker using fputil::multiply_add;
62*71db0c75SAndroid Build Coastguard Worker double dx2 = dx * dx;
63*71db0c75SAndroid Build Coastguard Worker double c0 = 1.0 + dx;
64*71db0c75SAndroid Build Coastguard Worker // c1 = COEFFS[0] + COEFFS[1] * dx
65*71db0c75SAndroid Build Coastguard Worker double c1 = multiply_add(dx, ExpBase::COEFFS[1], ExpBase::COEFFS[0]);
66*71db0c75SAndroid Build Coastguard Worker // c2 = COEFFS[2] + COEFFS[3] * dx
67*71db0c75SAndroid Build Coastguard Worker double c2 = multiply_add(dx, ExpBase::COEFFS[3], ExpBase::COEFFS[2]);
68*71db0c75SAndroid Build Coastguard Worker // r = c4 + c5 * dx^4
69*71db0c75SAndroid Build Coastguard Worker // = 1 + dx + COEFFS[0] * dx^2 + ... + COEFFS[5] * dx^7
70*71db0c75SAndroid Build Coastguard Worker return fputil::polyeval(dx2, c0, c1, c2);
71*71db0c75SAndroid Build Coastguard Worker }
72*71db0c75SAndroid Build Coastguard Worker };
73*71db0c75SAndroid Build Coastguard Worker
74*71db0c75SAndroid Build Coastguard Worker struct Exp10Base : public ExpBase {
75*71db0c75SAndroid Build Coastguard Worker // log2(10) * 2^5
76*71db0c75SAndroid Build Coastguard Worker static constexpr double LOG2_B = 0x1.a934f0979a371p1 * (1 << MID_BITS);
77*71db0c75SAndroid Build Coastguard Worker // High and low parts of -log10(2) * 2^(-5).
78*71db0c75SAndroid Build Coastguard Worker // Notice that since |x * log2(10)| < 150:
79*71db0c75SAndroid Build Coastguard Worker // |k| = |round(x * log2(10) * 2^5)| < 2^8 * 2^5 = 2^13
80*71db0c75SAndroid Build Coastguard Worker // So when the FMA instructions are not available, in order for the product
81*71db0c75SAndroid Build Coastguard Worker // k * M_LOGB_2_HI
82*71db0c75SAndroid Build Coastguard Worker // to be exact, we only store the high part of log10(2) up to 38 bits
83*71db0c75SAndroid Build Coastguard Worker // (= 53 - 15) of precision.
84*71db0c75SAndroid Build Coastguard Worker // It is generated by Sollya with:
85*71db0c75SAndroid Build Coastguard Worker // > round(log10(2), 44, RN);
86*71db0c75SAndroid Build Coastguard Worker static constexpr double M_LOGB_2_HI = -0x1.34413509f8p-2 / (1 << MID_BITS);
87*71db0c75SAndroid Build Coastguard Worker // > round(log10(2) - 0x1.34413509f8p-2, D, RN);
88*71db0c75SAndroid Build Coastguard Worker static constexpr double M_LOGB_2_LO = 0x1.80433b83b532ap-44 / (1 << MID_BITS);
89*71db0c75SAndroid Build Coastguard Worker
90*71db0c75SAndroid Build Coastguard Worker // Approximating 10^dx with degree-5 minimax polynomial generated by Sollya:
91*71db0c75SAndroid Build Coastguard Worker // > Q = fpminimax((10^x - 1)/x, 4, [|D...|], [-log10(2)/2^6, log10(2)/2^6]);
92*71db0c75SAndroid Build Coastguard Worker // Then:
93*71db0c75SAndroid Build Coastguard Worker // 10^dx ~ P(dx) = 1 + COEFFS[0] * dx + ... + COEFFS[4] * dx^5.
94*71db0c75SAndroid Build Coastguard Worker static constexpr double COEFFS[5] = {0x1.26bb1bbb55515p1, 0x1.53524c73bd3eap1,
95*71db0c75SAndroid Build Coastguard Worker 0x1.0470591dff149p1, 0x1.2bd7c0a9fbc4dp0,
96*71db0c75SAndroid Build Coastguard Worker 0x1.1429e74a98f43p-1};
97*71db0c75SAndroid Build Coastguard Worker
powb_loExp10Base98*71db0c75SAndroid Build Coastguard Worker static double powb_lo(double dx) {
99*71db0c75SAndroid Build Coastguard Worker using fputil::multiply_add;
100*71db0c75SAndroid Build Coastguard Worker double dx2 = dx * dx;
101*71db0c75SAndroid Build Coastguard Worker // c0 = 1 + COEFFS[0] * dx
102*71db0c75SAndroid Build Coastguard Worker double c0 = multiply_add(dx, Exp10Base::COEFFS[0], 1.0);
103*71db0c75SAndroid Build Coastguard Worker // c1 = COEFFS[1] + COEFFS[2] * dx
104*71db0c75SAndroid Build Coastguard Worker double c1 = multiply_add(dx, Exp10Base::COEFFS[2], Exp10Base::COEFFS[1]);
105*71db0c75SAndroid Build Coastguard Worker // c2 = COEFFS[3] + COEFFS[4] * dx
106*71db0c75SAndroid Build Coastguard Worker double c2 = multiply_add(dx, Exp10Base::COEFFS[4], Exp10Base::COEFFS[3]);
107*71db0c75SAndroid Build Coastguard Worker // r = c0 + dx^2 * (c1 + c2 * dx^2)
108*71db0c75SAndroid Build Coastguard Worker // = c0 + c1 * dx^2 + c2 * dx^4
109*71db0c75SAndroid Build Coastguard Worker // = 1 + COEFFS[0] * dx + ... + COEFFS[4] * dx^5.
110*71db0c75SAndroid Build Coastguard Worker return fputil::polyeval(dx2, c0, c1, c2);
111*71db0c75SAndroid Build Coastguard Worker }
112*71db0c75SAndroid Build Coastguard Worker };
113*71db0c75SAndroid Build Coastguard Worker
114*71db0c75SAndroid Build Coastguard Worker constexpr int LOG_P1_BITS = 6;
115*71db0c75SAndroid Build Coastguard Worker constexpr int LOG_P1_SIZE = 1 << LOG_P1_BITS;
116*71db0c75SAndroid Build Coastguard Worker
117*71db0c75SAndroid Build Coastguard Worker // N[Table[Log[2, 1 + x], {x, 0/64, 63/64, 1/64}], 40]
118*71db0c75SAndroid Build Coastguard Worker extern const double LOG_P1_LOG2[LOG_P1_SIZE];
119*71db0c75SAndroid Build Coastguard Worker
120*71db0c75SAndroid Build Coastguard Worker // N[Table[1/(1 + x), {x, 0/64, 63/64, 1/64}], 40]
121*71db0c75SAndroid Build Coastguard Worker extern const double LOG_P1_1_OVER[LOG_P1_SIZE];
122*71db0c75SAndroid Build Coastguard Worker
123*71db0c75SAndroid Build Coastguard Worker // Taylor series expansion for Log[2, 1 + x] splitted to EVEN AND ODD numbers
124*71db0c75SAndroid Build Coastguard Worker // K_LOG2_ODD starts from x^3
125*71db0c75SAndroid Build Coastguard Worker extern const double K_LOG2_ODD[4];
126*71db0c75SAndroid Build Coastguard Worker extern const double K_LOG2_EVEN[4];
127*71db0c75SAndroid Build Coastguard Worker
128*71db0c75SAndroid Build Coastguard Worker // Output of range reduction for exp_b: (2^(mid + hi), lo)
129*71db0c75SAndroid Build Coastguard Worker // where:
130*71db0c75SAndroid Build Coastguard Worker // b^x = 2^(mid + hi) * b^lo
131*71db0c75SAndroid Build Coastguard Worker struct exp_b_reduc_t {
132*71db0c75SAndroid Build Coastguard Worker double mh; // 2^(mid + hi)
133*71db0c75SAndroid Build Coastguard Worker double lo;
134*71db0c75SAndroid Build Coastguard Worker };
135*71db0c75SAndroid Build Coastguard Worker
136*71db0c75SAndroid Build Coastguard Worker // The function correctly calculates b^x value with at least float precision
137*71db0c75SAndroid Build Coastguard Worker // in a limited range.
138*71db0c75SAndroid Build Coastguard Worker // Range reduction:
139*71db0c75SAndroid Build Coastguard Worker // b^x = 2^(hi + mid) * b^lo
140*71db0c75SAndroid Build Coastguard Worker // where:
141*71db0c75SAndroid Build Coastguard Worker // x = (hi + mid) * log_b(2) + lo
142*71db0c75SAndroid Build Coastguard Worker // hi is an integer,
143*71db0c75SAndroid Build Coastguard Worker // 0 <= mid * 2^MID_BITS < 2^MID_BITS is an integer
144*71db0c75SAndroid Build Coastguard Worker // -2^(-MID_BITS - 1) <= lo * log2(b) <= 2^(-MID_BITS - 1)
145*71db0c75SAndroid Build Coastguard Worker // Base class needs to provide the following constants:
146*71db0c75SAndroid Build Coastguard Worker // - MID_BITS : number of bits after decimal points used for mid
147*71db0c75SAndroid Build Coastguard Worker // - MID_MASK : 2^MID_BITS - 1, mask to extract mid bits
148*71db0c75SAndroid Build Coastguard Worker // - LOG2_B : log2(b) * 2^MID_BITS for scaling
149*71db0c75SAndroid Build Coastguard Worker // - M_LOGB_2_HI : high part of -log_b(2) * 2^(-MID_BITS)
150*71db0c75SAndroid Build Coastguard Worker // - M_LOGB_2_LO : low part of -log_b(2) * 2^(-MID_BITS)
151*71db0c75SAndroid Build Coastguard Worker // - EXP_2_MID : look up table for bit fields of 2^mid
152*71db0c75SAndroid Build Coastguard Worker // Return:
153*71db0c75SAndroid Build Coastguard Worker // { 2^(hi + mid), lo }
exp_b_range_reduc(float x)154*71db0c75SAndroid Build Coastguard Worker template <class Base> LIBC_INLINE exp_b_reduc_t exp_b_range_reduc(float x) {
155*71db0c75SAndroid Build Coastguard Worker double xd = static_cast<double>(x);
156*71db0c75SAndroid Build Coastguard Worker // kd = round((hi + mid) * log2(b) * 2^MID_BITS)
157*71db0c75SAndroid Build Coastguard Worker double kd = fputil::nearest_integer(Base::LOG2_B * xd);
158*71db0c75SAndroid Build Coastguard Worker // k = round((hi + mid) * log2(b) * 2^MID_BITS)
159*71db0c75SAndroid Build Coastguard Worker int k = static_cast<int>(kd);
160*71db0c75SAndroid Build Coastguard Worker // hi = floor(kd * 2^(-MID_BITS))
161*71db0c75SAndroid Build Coastguard Worker // exp_hi = shift hi to the exponent field of double precision.
162*71db0c75SAndroid Build Coastguard Worker uint64_t exp_hi = static_cast<uint64_t>(k >> Base::MID_BITS)
163*71db0c75SAndroid Build Coastguard Worker << fputil::FPBits<double>::FRACTION_LEN;
164*71db0c75SAndroid Build Coastguard Worker // mh = 2^hi * 2^mid
165*71db0c75SAndroid Build Coastguard Worker // mh_bits = bit field of mh
166*71db0c75SAndroid Build Coastguard Worker uint64_t mh_bits = Base::EXP_2_MID[k & Base::MID_MASK] + exp_hi;
167*71db0c75SAndroid Build Coastguard Worker double mh = fputil::FPBits<double>(mh_bits).get_val();
168*71db0c75SAndroid Build Coastguard Worker // dx = lo = x - (hi + mid) * log(2)
169*71db0c75SAndroid Build Coastguard Worker double dx = fputil::multiply_add(
170*71db0c75SAndroid Build Coastguard Worker kd, Base::M_LOGB_2_LO, fputil::multiply_add(kd, Base::M_LOGB_2_HI, xd));
171*71db0c75SAndroid Build Coastguard Worker return {mh, dx};
172*71db0c75SAndroid Build Coastguard Worker }
173*71db0c75SAndroid Build Coastguard Worker
174*71db0c75SAndroid Build Coastguard Worker // The function correctly calculates sinh(x) and cosh(x) by calculating exp(x)
175*71db0c75SAndroid Build Coastguard Worker // and exp(-x) simultaneously.
176*71db0c75SAndroid Build Coastguard Worker // To compute e^x, we perform the following range
177*71db0c75SAndroid Build Coastguard Worker // reduction: find hi, mid, lo such that:
178*71db0c75SAndroid Build Coastguard Worker // x = (hi + mid) * log(2) + lo, in which
179*71db0c75SAndroid Build Coastguard Worker // hi is an integer,
180*71db0c75SAndroid Build Coastguard Worker // 0 <= mid * 2^5 < 32 is an integer
181*71db0c75SAndroid Build Coastguard Worker // -2^(-6) <= lo * log2(e) <= 2^-6.
182*71db0c75SAndroid Build Coastguard Worker // In particular,
183*71db0c75SAndroid Build Coastguard Worker // hi + mid = round(x * log2(e) * 2^5) * 2^(-5).
184*71db0c75SAndroid Build Coastguard Worker // Then,
185*71db0c75SAndroid Build Coastguard Worker // e^x = 2^(hi + mid) * e^lo = 2^hi * 2^mid * e^lo.
186*71db0c75SAndroid Build Coastguard Worker // 2^mid is stored in the lookup table of 32 elements.
187*71db0c75SAndroid Build Coastguard Worker // e^lo is computed using a degree-5 minimax polynomial
188*71db0c75SAndroid Build Coastguard Worker // generated by Sollya:
189*71db0c75SAndroid Build Coastguard Worker // e^lo ~ P(lo) = 1 + lo + c2 * lo^2 + ... + c5 * lo^5
190*71db0c75SAndroid Build Coastguard Worker // = (1 + c2*lo^2 + c4*lo^4) + lo * (1 + c3*lo^2 + c5*lo^4)
191*71db0c75SAndroid Build Coastguard Worker // = P_even + lo * P_odd
192*71db0c75SAndroid Build Coastguard Worker // We perform 2^hi * 2^mid by simply add hi to the exponent field
193*71db0c75SAndroid Build Coastguard Worker // of 2^mid.
194*71db0c75SAndroid Build Coastguard Worker // To compute e^(-x), notice that:
195*71db0c75SAndroid Build Coastguard Worker // e^(-x) = 2^(-(hi + mid)) * e^(-lo)
196*71db0c75SAndroid Build Coastguard Worker // ~ 2^(-(hi + mid)) * P(-lo)
197*71db0c75SAndroid Build Coastguard Worker // = 2^(-(hi + mid)) * (P_even - lo * P_odd)
198*71db0c75SAndroid Build Coastguard Worker // So:
199*71db0c75SAndroid Build Coastguard Worker // sinh(x) = (e^x - e^(-x)) / 2
200*71db0c75SAndroid Build Coastguard Worker // ~ 0.5 * (2^(hi + mid) * (P_even + lo * P_odd) -
201*71db0c75SAndroid Build Coastguard Worker // 2^(-(hi + mid)) * (P_even - lo * P_odd))
202*71db0c75SAndroid Build Coastguard Worker // = 0.5 * (P_even * (2^(hi + mid) - 2^(-(hi + mid))) +
203*71db0c75SAndroid Build Coastguard Worker // lo * P_odd * (2^(hi + mid) + 2^(-(hi + mid))))
204*71db0c75SAndroid Build Coastguard Worker // And similarly:
205*71db0c75SAndroid Build Coastguard Worker // cosh(x) = (e^x + e^(-x)) / 2
206*71db0c75SAndroid Build Coastguard Worker // ~ 0.5 * (P_even * (2^(hi + mid) + 2^(-(hi + mid))) +
207*71db0c75SAndroid Build Coastguard Worker // lo * P_odd * (2^(hi + mid) - 2^(-(hi + mid))))
208*71db0c75SAndroid Build Coastguard Worker // The main point of these formulas is that the expensive part of calculating
209*71db0c75SAndroid Build Coastguard Worker // the polynomials approximating lower parts of e^(x) and e^(-x) are shared
210*71db0c75SAndroid Build Coastguard Worker // and only done once.
exp_pm_eval(float x)211*71db0c75SAndroid Build Coastguard Worker template <bool is_sinh> LIBC_INLINE double exp_pm_eval(float x) {
212*71db0c75SAndroid Build Coastguard Worker double xd = static_cast<double>(x);
213*71db0c75SAndroid Build Coastguard Worker
214*71db0c75SAndroid Build Coastguard Worker // kd = round(x * log2(e) * 2^5)
215*71db0c75SAndroid Build Coastguard Worker // k_p = round(x * log2(e) * 2^5)
216*71db0c75SAndroid Build Coastguard Worker // k_m = round(-x * log2(e) * 2^5)
217*71db0c75SAndroid Build Coastguard Worker double kd;
218*71db0c75SAndroid Build Coastguard Worker int k_p, k_m;
219*71db0c75SAndroid Build Coastguard Worker
220*71db0c75SAndroid Build Coastguard Worker #ifdef LIBC_TARGET_CPU_HAS_NEAREST_INT
221*71db0c75SAndroid Build Coastguard Worker kd = fputil::nearest_integer(ExpBase::LOG2_B * xd);
222*71db0c75SAndroid Build Coastguard Worker k_p = static_cast<int>(kd);
223*71db0c75SAndroid Build Coastguard Worker k_m = -k_p;
224*71db0c75SAndroid Build Coastguard Worker #else
225*71db0c75SAndroid Build Coastguard Worker constexpr double HALF_WAY[2] = {0.5, -0.5};
226*71db0c75SAndroid Build Coastguard Worker
227*71db0c75SAndroid Build Coastguard Worker k_p = static_cast<int>(
228*71db0c75SAndroid Build Coastguard Worker fputil::multiply_add(xd, ExpBase::LOG2_B, HALF_WAY[x < 0.0f]));
229*71db0c75SAndroid Build Coastguard Worker k_m = -k_p;
230*71db0c75SAndroid Build Coastguard Worker kd = static_cast<double>(k_p);
231*71db0c75SAndroid Build Coastguard Worker #endif // LIBC_TARGET_CPU_HAS_NEAREST_INT
232*71db0c75SAndroid Build Coastguard Worker
233*71db0c75SAndroid Build Coastguard Worker // hi = floor(kf * 2^(-5))
234*71db0c75SAndroid Build Coastguard Worker // exp_hi = shift hi to the exponent field of double precision.
235*71db0c75SAndroid Build Coastguard Worker int64_t exp_hi_p = static_cast<int64_t>((k_p >> ExpBase::MID_BITS))
236*71db0c75SAndroid Build Coastguard Worker << fputil::FPBits<double>::FRACTION_LEN;
237*71db0c75SAndroid Build Coastguard Worker int64_t exp_hi_m = static_cast<int64_t>((k_m >> ExpBase::MID_BITS))
238*71db0c75SAndroid Build Coastguard Worker << fputil::FPBits<double>::FRACTION_LEN;
239*71db0c75SAndroid Build Coastguard Worker // mh_p = 2^(hi + mid)
240*71db0c75SAndroid Build Coastguard Worker // mh_m = 2^(-(hi + mid))
241*71db0c75SAndroid Build Coastguard Worker // mh_bits_* = bit field of mh_*
242*71db0c75SAndroid Build Coastguard Worker int64_t mh_bits_p = ExpBase::EXP_2_MID[k_p & ExpBase::MID_MASK] + exp_hi_p;
243*71db0c75SAndroid Build Coastguard Worker int64_t mh_bits_m = ExpBase::EXP_2_MID[k_m & ExpBase::MID_MASK] + exp_hi_m;
244*71db0c75SAndroid Build Coastguard Worker double mh_p = fputil::FPBits<double>(uint64_t(mh_bits_p)).get_val();
245*71db0c75SAndroid Build Coastguard Worker double mh_m = fputil::FPBits<double>(uint64_t(mh_bits_m)).get_val();
246*71db0c75SAndroid Build Coastguard Worker // mh_sum = 2^(hi + mid) + 2^(-(hi + mid))
247*71db0c75SAndroid Build Coastguard Worker double mh_sum = mh_p + mh_m;
248*71db0c75SAndroid Build Coastguard Worker // mh_diff = 2^(hi + mid) - 2^(-(hi + mid))
249*71db0c75SAndroid Build Coastguard Worker double mh_diff = mh_p - mh_m;
250*71db0c75SAndroid Build Coastguard Worker
251*71db0c75SAndroid Build Coastguard Worker // dx = lo = x - (hi + mid) * log(2)
252*71db0c75SAndroid Build Coastguard Worker double dx =
253*71db0c75SAndroid Build Coastguard Worker fputil::multiply_add(kd, ExpBase::M_LOGB_2_LO,
254*71db0c75SAndroid Build Coastguard Worker fputil::multiply_add(kd, ExpBase::M_LOGB_2_HI, xd));
255*71db0c75SAndroid Build Coastguard Worker double dx2 = dx * dx;
256*71db0c75SAndroid Build Coastguard Worker
257*71db0c75SAndroid Build Coastguard Worker // c0 = 1 + COEFFS[0] * lo^2
258*71db0c75SAndroid Build Coastguard Worker // P_even = (1 + COEFFS[0] * lo^2 + COEFFS[2] * lo^4) / 2
259*71db0c75SAndroid Build Coastguard Worker double p_even = fputil::polyeval(dx2, 0.5, ExpBase::COEFFS[0] * 0.5,
260*71db0c75SAndroid Build Coastguard Worker ExpBase::COEFFS[2] * 0.5);
261*71db0c75SAndroid Build Coastguard Worker // P_odd = (1 + COEFFS[1] * lo^2 + COEFFS[3] * lo^4) / 2
262*71db0c75SAndroid Build Coastguard Worker double p_odd = fputil::polyeval(dx2, 0.5, ExpBase::COEFFS[1] * 0.5,
263*71db0c75SAndroid Build Coastguard Worker ExpBase::COEFFS[3] * 0.5);
264*71db0c75SAndroid Build Coastguard Worker
265*71db0c75SAndroid Build Coastguard Worker double r;
266*71db0c75SAndroid Build Coastguard Worker if constexpr (is_sinh)
267*71db0c75SAndroid Build Coastguard Worker r = fputil::multiply_add(dx * mh_sum, p_odd, p_even * mh_diff);
268*71db0c75SAndroid Build Coastguard Worker else
269*71db0c75SAndroid Build Coastguard Worker r = fputil::multiply_add(dx * mh_diff, p_odd, p_even * mh_sum);
270*71db0c75SAndroid Build Coastguard Worker return r;
271*71db0c75SAndroid Build Coastguard Worker }
272*71db0c75SAndroid Build Coastguard Worker
273*71db0c75SAndroid Build Coastguard Worker // x should be positive, normal finite value
log2_eval(double x)274*71db0c75SAndroid Build Coastguard Worker LIBC_INLINE static double log2_eval(double x) {
275*71db0c75SAndroid Build Coastguard Worker using FPB = fputil::FPBits<double>;
276*71db0c75SAndroid Build Coastguard Worker FPB bs(x);
277*71db0c75SAndroid Build Coastguard Worker
278*71db0c75SAndroid Build Coastguard Worker double result = 0;
279*71db0c75SAndroid Build Coastguard Worker result += bs.get_exponent();
280*71db0c75SAndroid Build Coastguard Worker
281*71db0c75SAndroid Build Coastguard Worker int p1 = (bs.get_mantissa() >> (FPB::FRACTION_LEN - LOG_P1_BITS)) &
282*71db0c75SAndroid Build Coastguard Worker (LOG_P1_SIZE - 1);
283*71db0c75SAndroid Build Coastguard Worker
284*71db0c75SAndroid Build Coastguard Worker bs.set_uintval(bs.uintval() & (FPB::FRACTION_MASK >> LOG_P1_BITS));
285*71db0c75SAndroid Build Coastguard Worker bs.set_biased_exponent(FPB::EXP_BIAS);
286*71db0c75SAndroid Build Coastguard Worker double dx = (bs.get_val() - 1.0) * LOG_P1_1_OVER[p1];
287*71db0c75SAndroid Build Coastguard Worker
288*71db0c75SAndroid Build Coastguard Worker // Taylor series for log(2,1+x)
289*71db0c75SAndroid Build Coastguard Worker double c1 = fputil::multiply_add(dx, K_LOG2_ODD[0], K_LOG2_EVEN[0]);
290*71db0c75SAndroid Build Coastguard Worker double c2 = fputil::multiply_add(dx, K_LOG2_ODD[1], K_LOG2_EVEN[1]);
291*71db0c75SAndroid Build Coastguard Worker double c3 = fputil::multiply_add(dx, K_LOG2_ODD[2], K_LOG2_EVEN[2]);
292*71db0c75SAndroid Build Coastguard Worker double c4 = fputil::multiply_add(dx, K_LOG2_ODD[3], K_LOG2_EVEN[3]);
293*71db0c75SAndroid Build Coastguard Worker
294*71db0c75SAndroid Build Coastguard Worker // c0 = dx * (1.0 / ln(2)) + LOG_P1_LOG2[p1]
295*71db0c75SAndroid Build Coastguard Worker double c0 = fputil::multiply_add(dx, 0x1.71547652b82fep+0, LOG_P1_LOG2[p1]);
296*71db0c75SAndroid Build Coastguard Worker result += LIBC_NAMESPACE::fputil::polyeval(dx * dx, c0, c1, c2, c3, c4);
297*71db0c75SAndroid Build Coastguard Worker return result;
298*71db0c75SAndroid Build Coastguard Worker }
299*71db0c75SAndroid Build Coastguard Worker
300*71db0c75SAndroid Build Coastguard Worker // x should be positive, normal finite value
log_eval(double x)301*71db0c75SAndroid Build Coastguard Worker LIBC_INLINE static double log_eval(double x) {
302*71db0c75SAndroid Build Coastguard Worker // For x = 2^ex * (1 + mx)
303*71db0c75SAndroid Build Coastguard Worker // log(x) = ex * log(2) + log(1 + mx)
304*71db0c75SAndroid Build Coastguard Worker using FPB = fputil::FPBits<double>;
305*71db0c75SAndroid Build Coastguard Worker FPB bs(x);
306*71db0c75SAndroid Build Coastguard Worker
307*71db0c75SAndroid Build Coastguard Worker double ex = static_cast<double>(bs.get_exponent());
308*71db0c75SAndroid Build Coastguard Worker
309*71db0c75SAndroid Build Coastguard Worker // p1 is the leading 7 bits of mx, i.e.
310*71db0c75SAndroid Build Coastguard Worker // p1 * 2^(-7) <= m_x < (p1 + 1) * 2^(-7).
311*71db0c75SAndroid Build Coastguard Worker int p1 = static_cast<int>(bs.get_mantissa() >> (FPB::FRACTION_LEN - 7));
312*71db0c75SAndroid Build Coastguard Worker
313*71db0c75SAndroid Build Coastguard Worker // Set bs to (1 + (mx - p1*2^(-7))
314*71db0c75SAndroid Build Coastguard Worker bs.set_uintval(bs.uintval() & (FPB::FRACTION_MASK >> 7));
315*71db0c75SAndroid Build Coastguard Worker bs.set_biased_exponent(FPB::EXP_BIAS);
316*71db0c75SAndroid Build Coastguard Worker // dx = (mx - p1*2^(-7)) / (1 + p1*2^(-7)).
317*71db0c75SAndroid Build Coastguard Worker double dx = (bs.get_val() - 1.0) * ONE_OVER_F[p1];
318*71db0c75SAndroid Build Coastguard Worker
319*71db0c75SAndroid Build Coastguard Worker // Minimax polynomial of log(1 + dx) generated by Sollya with:
320*71db0c75SAndroid Build Coastguard Worker // > P = fpminimax(log(1 + x)/x, 6, [|D...|], [0, 2^-7]);
321*71db0c75SAndroid Build Coastguard Worker const double COEFFS[6] = {-0x1.ffffffffffffcp-2, 0x1.5555555552ddep-2,
322*71db0c75SAndroid Build Coastguard Worker -0x1.ffffffefe562dp-3, 0x1.9999817d3a50fp-3,
323*71db0c75SAndroid Build Coastguard Worker -0x1.554317b3f67a5p-3, 0x1.1dc5c45e09c18p-3};
324*71db0c75SAndroid Build Coastguard Worker double dx2 = dx * dx;
325*71db0c75SAndroid Build Coastguard Worker double c1 = fputil::multiply_add(dx, COEFFS[1], COEFFS[0]);
326*71db0c75SAndroid Build Coastguard Worker double c2 = fputil::multiply_add(dx, COEFFS[3], COEFFS[2]);
327*71db0c75SAndroid Build Coastguard Worker double c3 = fputil::multiply_add(dx, COEFFS[5], COEFFS[4]);
328*71db0c75SAndroid Build Coastguard Worker
329*71db0c75SAndroid Build Coastguard Worker double p = fputil::polyeval(dx2, dx, c1, c2, c3);
330*71db0c75SAndroid Build Coastguard Worker double result =
331*71db0c75SAndroid Build Coastguard Worker fputil::multiply_add(ex, /*log(2)*/ 0x1.62e42fefa39efp-1, LOG_F[p1] + p);
332*71db0c75SAndroid Build Coastguard Worker return result;
333*71db0c75SAndroid Build Coastguard Worker }
334*71db0c75SAndroid Build Coastguard Worker
335*71db0c75SAndroid Build Coastguard Worker // Rounding tests for 2^hi * (mid + lo) when the output might be denormal. We
336*71db0c75SAndroid Build Coastguard Worker // assume further that 1 <= mid < 2, mid + lo < 2, and |lo| << mid.
337*71db0c75SAndroid Build Coastguard Worker // Notice that, if 0 < x < 2^-1022,
338*71db0c75SAndroid Build Coastguard Worker // double(2^-1022 + x) - 2^-1022 = double(x).
339*71db0c75SAndroid Build Coastguard Worker // So if we scale x up by 2^1022, we can use
340*71db0c75SAndroid Build Coastguard Worker // double(1.0 + 2^1022 * x) - 1.0 to test how x is rounded in denormal range.
ziv_test_denorm(int hi,double mid,double lo,double err)341*71db0c75SAndroid Build Coastguard Worker LIBC_INLINE cpp::optional<double> ziv_test_denorm(int hi, double mid, double lo,
342*71db0c75SAndroid Build Coastguard Worker double err) {
343*71db0c75SAndroid Build Coastguard Worker using FPBits = typename fputil::FPBits<double>;
344*71db0c75SAndroid Build Coastguard Worker
345*71db0c75SAndroid Build Coastguard Worker // Scaling factor = 1/(min normal number) = 2^1022
346*71db0c75SAndroid Build Coastguard Worker int64_t exp_hi = static_cast<int64_t>(hi + 1022) << FPBits::FRACTION_LEN;
347*71db0c75SAndroid Build Coastguard Worker double mid_hi = cpp::bit_cast<double>(exp_hi + cpp::bit_cast<int64_t>(mid));
348*71db0c75SAndroid Build Coastguard Worker double lo_scaled =
349*71db0c75SAndroid Build Coastguard Worker (lo != 0.0) ? cpp::bit_cast<double>(exp_hi + cpp::bit_cast<int64_t>(lo))
350*71db0c75SAndroid Build Coastguard Worker : 0.0;
351*71db0c75SAndroid Build Coastguard Worker
352*71db0c75SAndroid Build Coastguard Worker double extra_factor = 0.0;
353*71db0c75SAndroid Build Coastguard Worker uint64_t scale_down = 0x3FE0'0000'0000'0000; // 1022 in the exponent field.
354*71db0c75SAndroid Build Coastguard Worker
355*71db0c75SAndroid Build Coastguard Worker // Result is denormal if (mid_hi + lo_scale < 1.0).
356*71db0c75SAndroid Build Coastguard Worker if ((1.0 - mid_hi) > lo_scaled) {
357*71db0c75SAndroid Build Coastguard Worker // Extra rounding step is needed, which adds more rounding errors.
358*71db0c75SAndroid Build Coastguard Worker err += 0x1.0p-52;
359*71db0c75SAndroid Build Coastguard Worker extra_factor = 1.0;
360*71db0c75SAndroid Build Coastguard Worker scale_down = 0x3FF0'0000'0000'0000; // 1023 in the exponent field.
361*71db0c75SAndroid Build Coastguard Worker }
362*71db0c75SAndroid Build Coastguard Worker
363*71db0c75SAndroid Build Coastguard Worker double err_scaled =
364*71db0c75SAndroid Build Coastguard Worker cpp::bit_cast<double>(exp_hi + cpp::bit_cast<int64_t>(err));
365*71db0c75SAndroid Build Coastguard Worker
366*71db0c75SAndroid Build Coastguard Worker double lo_u = lo_scaled + err_scaled;
367*71db0c75SAndroid Build Coastguard Worker double lo_l = lo_scaled - err_scaled;
368*71db0c75SAndroid Build Coastguard Worker
369*71db0c75SAndroid Build Coastguard Worker // By adding 1.0, the results will have similar rounding points as denormal
370*71db0c75SAndroid Build Coastguard Worker // outputs.
371*71db0c75SAndroid Build Coastguard Worker double upper = extra_factor + (mid_hi + lo_u);
372*71db0c75SAndroid Build Coastguard Worker double lower = extra_factor + (mid_hi + lo_l);
373*71db0c75SAndroid Build Coastguard Worker
374*71db0c75SAndroid Build Coastguard Worker if (LIBC_LIKELY(upper == lower)) {
375*71db0c75SAndroid Build Coastguard Worker return cpp::bit_cast<double>(cpp::bit_cast<uint64_t>(upper) - scale_down);
376*71db0c75SAndroid Build Coastguard Worker }
377*71db0c75SAndroid Build Coastguard Worker
378*71db0c75SAndroid Build Coastguard Worker return cpp::nullopt;
379*71db0c75SAndroid Build Coastguard Worker }
380*71db0c75SAndroid Build Coastguard Worker
381*71db0c75SAndroid Build Coastguard Worker } // namespace LIBC_NAMESPACE_DECL
382*71db0c75SAndroid Build Coastguard Worker
383*71db0c75SAndroid Build Coastguard Worker #endif // LLVM_LIBC_SRC_MATH_GENERIC_EXPLOGXF_H
384