╭ exp_f128.zig ─────────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭ find file ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╮ ╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╮ │ │ │http│ ssh │ │ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╯ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╯
.. aarch64_outline_atomics.zig absv.zig absvdi2.zig absvdi2_test.zig absvsi2.zig absvsi2_test.zig absvti2.zig absvti2_test.zig addf3.zig addf3_test.zig addvdi3.zig addvsi3.zig arm.zig atomics.zig aulldiv.zig aullrem.zig bitreverse.zig bitreversedi2_test.zig bitreversesi2_test.zig bitreverseti2_test.zig bswap.zig bswapdi2_test.zig bswapsi2_test.zig bswapti2_test.zig clear_cache.zig clzdi2_test.zig clzsi2_test.zig clzti2_test.zig cmp.zig cmpdi2_test.zig cmpsi2_test.zig cmpti2_test.zig comparedf2_test.zig comparef.zig comparesf2_test.zig cos.zig count0bits.zig ctzdi2_test.zig ctzsi2_test.zig ctzti2_test.zig divc3.zig divc3_test.zig divdf3.zig divdf3_test.zig divmodei4.zig divsf3.zig divsf3_test.zig divtf3.zig divtf3_test.zig divti3_test.zig divxf3.zig divxf3_test.zig emutls.zig exp.zig exp2.zig ╭─────────────────────────────────╮ │exp_f128.zig │ ╰─────────────────────────────────╯ extendf.zig extendf_test.zig fabs.zig ffsdi2_test.zig ffssi2_test.zig ffsti2_test.zig float_from_int.zig float_from_int_test.zig floor_ceil.zig fma.zig fmax.zig fmin.zig fmod.zig fmodq_test.zig fmodx_test.zig hexagon.zig int.zig int_from_float.zig int_from_float_test.zig limb64.zig log.zig log10.zig log2.zig log_f128.zig memcpy.zig memmove.zig modti3_test.zig mulXi3.zig mulXi3_test.zig mulc3.zig mulc3_test.zig mulf3.zig mulf3_test.zig mulo.zig mulodi4_test.zig mulosi4_test.zig muloti4_test.zig mulvsi3.zig negdi2_test.zig negsi2_test.zig negti2_test.zig negv.zig negvdi2_test.zig negvsi2_test.zig negvti2_test.zig os_version_check.zig parity.zig paritydi2_test.zig paritysi2_test.zig parityti2_test.zig popcount.zig popcountdi2_test.zig popcountsi2_test.zig popcountti2_test.zig powiXf2.zig powiXf2_test.zig rem_pio2.zig rem_pio2_large.zig rem_pio2f.zig rem_pio2l.zig round.zig shift.zig shift_test.zig sin.zig sincos.zig sqrt.zig ssp.zig stack_probe.zig subvdi3.zig subvsi3.zig tan.zig trig.zig trunc.zig truncf.zig truncf_test.zig ucmpdi2_test.zig ucmpsi2_test.zig ucmpti2_test.zig udivmod.zig udivmoddi4_test.zig udivmodei4.zig udivmodsi4_test.zig udivmodti4_test.zig
1 /// Implementation of f128 exp and exp2 based on: 2 /// 3 /// * "Table-Driven Implementation of the Exponential Function in IEEE Floating-Point Arithmetic" 4 /// ACM Transactions on Mathematical Software (TOMS), Volume 15, Issue 2 pp. 144-157 5 /// 6 /// and 7 /// 8 /// * "Table-driven implementation of the Expm1 function in IEEE floating-point arithmetic" 9 /// ACM Transactions on Mathematical Software (TOMS), Volume 18, Issue 2 pp. 211-222 10 /// 11 /// Both by Ping Tak Peter Tang. 12 /// 13 /// Adapted by Christophe Delage to work with 128 bit floats and with base 2 and 10. 14 /// 15 /// Accuracy tested on 100 million uniformly distributed random values: 16 /// 17 /// exp: 18 /// when result is normal: <= 0.5 ulp: 99.83%, worst case: 0.512 19 /// when result is subnormal: <= 0.5 ulp: 99.80%, worst case: 0.628 20 /// exp2: 21 /// when result is normal: <= 0.5 ulp: 99.82%, worst case: 0.514 22 /// when result is subnormal: <= 0.5 ulp: 99.56%, worst case: 0.752 23 /// 24 const exp_f128 = @This(); 25 26 const std = @import("std"); 27 const math = std.math; 28 29 pub fn exp(x: f128) f128 { 30 if (!math.isFinite(x)) { 31 if (math.isNan(x)) { 32 if (math.isSignalNan(x)) math.raiseInvalid(); 33 return math.nan(f128); 34 } 35 return if (math.signbit(x)) 0 else x; 36 } 37 if (@abs(x) > 12000) { 38 if (math.signbit(x)) { 39 math.raiseUnderflow(); 40 return 0; 41 } else { 42 math.raiseOverflow(); 43 return math.inf(f128); 44 } 45 } 46 47 if (@abs(x) < 0x1p-114) 48 return 1 + x; 49 50 return proc1(cfg_e, x); 51 } 52 53 const cfg_e: Config = .{ 54 .inv_log_size = 92.33248261689365807103517958412109, 55 .log_size_hi = 1.0830424696249145459644251897780967e-2, 56 .neg_log_size_lo = -3.0422579568449217993561868333332404e-33, 57 .poly = expPoly, 58 .finalize = expFinalize, 59 }; 60 61 /// Approximates e^(r_hi + r_lo) - 1. 62 fn expPoly(r_hi: f128, r_lo: f128) f128 { 63 const a2: f128 = 0.5000000000000000000000000000000001; 64 const a3: f128 = 0.16666666666666666666666666666666673; 65 const a4: f128 = 4.16666666666666666666666665159063e-2; 66 const a5: f128 = 8.333333333333333333333333293907277e-3; 67 const a6: f128 = 1.3888888888888888889300177029864553e-3; 68 const a7: f128 = 1.984126984126984127049928848046117e-4; 69 const a8: f64 = 2.4801587301583374475925191558926944e-5; 70 const a9: f64 = 2.7557319223981316410138550193306495e-6; 71 const a10: f64 = 2.75573345290144319034653394989056e-7; 72 const a11: f64 = 2.5052122512857680160207187885276378e-8; 73 74 const r = r_hi + r_lo; 75 const s: f64 = @floatCast(r); 76 const rr = r * r; 77 const ss = s * s; 78 79 // Do the upper degree computation in f64 and try to get better ILP 80 // by deviating from Horner's method. This does not measurably hurt 81 // accuracy. 82 const a10_11 = a10 + s * a11; 83 const a8_9 = a8 + s * a9; 84 const a8_11 = a8_9 + ss * a10_11; 85 const a6_7 = a6 + r * a7; 86 const a4_5 = a4 + r * a5; 87 const a2_3 = a2 + r * a3; 88 const a2_11 = a2_3 + rr * (a4_5 + rr * (a6_7 + rr * a8_11)); 89 90 return r_hi + (r_lo + rr * a2_11); 91 } 92 93 /// Computes 2^x 94 pub fn exp2(x: f128) f128 { 95 if (!math.isFinite(x)) { 96 if (math.isNan(x)) { 97 if (math.isSignalNan(x)) math.raiseInvalid(); 98 return math.nan(f128); 99 } 100 return if (math.signbit(x)) 0 else x; 101 } 102 if (@abs(x) > 17000) { 103 if (math.signbit(x)) { 104 math.raiseUnderflow(); 105 return 0; 106 } else { 107 math.raiseOverflow(); 108 return math.inf(f128); 109 } 110 } 111 if (@abs(x) < 0x1p-114 * math.log2e) 112 return 1 + x; 113 114 return proc1(cfg_2, x); 115 } 116 117 /// Compute a^`x` or a^`x` - 1, depending on `cfg`. 118 fn proc1(comptime cfg: Config, x: f128) f128 { 119 // Argument reduction: x = r * 2^(j / size + m) 120 // with r in [-log_a(2) / 2 / size, log_a(2) / 2 / size]. 121 // 122 // r computed as r_hi + r_lo to simulate higher precision. 123 const n = @round(x * cfg.inv_log_size); 124 const ni: i32 = @intFromFloat(n); 125 const n2 = @mod(ni, size); 126 const n1 = ni - n2; 127 const m = @divExact(n1, size); 128 const j: usize = @intCast(n2); 129 130 const r_hi = x - n * cfg.log_size_hi; 131 const r_lo = n * cfg.neg_log_size_lo; 132 133 const pr = cfg.poly(r_hi, r_lo); 134 135 return cfg.finalize(pr, j, m); 136 } 137 138 const cfg_2: Config = .{ 139 .inv_log_size = 64, 140 .log_size_hi = 1.5625e-2, 141 .neg_log_size_lo = 0, 142 .poly = exp2Poly, 143 .finalize = expFinalize, 144 }; 145 146 /// Approximates 2^(r_hi + r_lo) - 1. 147 fn exp2Poly(r_hi: f128, r_lo: f128) f128 { 148 const a1: f128 = 0.6931471805599453094172321214581766; 149 const a2: f128 = 0.24022650695910071233355126316333273; 150 const a3: f128 = 5.5504108664821579953142263768621824e-2; 151 const a4: f128 = 9.618129107628477161979071497097137e-3; 152 const a5: f128 = 1.3333558146428443423412221872998745e-3; 153 const a6: f128 = 1.5403530393381609955139554247429082e-4; 154 const a7: f128 = 1.5252733804059840280740292411812167e-5; 155 const a8: f64 = 1.321548679014167884759296382063556e-6; 156 const a9: f64 = 1.0178086009237659848870888288504849e-7; 157 const a10: f64 = 7.0549159308426003613013130647805315e-9; 158 const a11: f64 = 4.445540987582123304209680731453203e-10; 159 160 const r = r_hi + r_lo; 161 const s: f64 = @floatCast(r); 162 const rr = r * r; 163 const ss = s * s; 164 165 // Do the upper degree computation in f64 and try to get better ILP 166 // by deviating from Horner's method. This does not measurably hurt 167 // accuracy. 168 const a10_11 = a10 + s * a11; 169 const a8_9 = a8 + s * a9; 170 const a8_11 = a8_9 + ss * a10_11; 171 const a6_7 = a6 + r * a7; 172 const a4_5 = a4 + r * a5; 173 const a2_3 = a2 + r * a3; 174 const a2_11 = a2_3 + rr * (a4_5 + rr * (a6_7 + rr * a8_11)); 175 176 return r * (a1 + r * a2_11); 177 } 178 179 /// Configuration for computing a^x, a in {e, 2, 10}, or e^x - 1. 180 const Config = struct { 181 /// size / log(a) 182 inv_log_size: f128, 183 184 // High bits of log(a) / size, with the 12 last bits set to 0 185 log_size_hi: f128, 186 // Low bits of log(a) / size, negated 187 neg_log_size_lo: f128, 188 189 /// Approximates a^(r_hi + r_lo) - 1. 190 poly: fn (f128, f128) f128, 191 192 /// Compute the final value, a^x or e^x - 1. 193 finalize: fn (pr: f128, j: usize, m: i32) f128, 194 }; 195 196 /// computes (1 + pr) * 2^(j / 32) * 2^m. 197 fn expFinalize(pr: f128, j: usize, m: i32) f128 { 198 const sj_hi = exp2_tab[j].hi; 199 const sj_lo = exp2_tab[j].lo; 200 const sj = sj_hi + sj_lo; 201 202 const x = sj_hi + (sj_lo + sj * pr); 203 204 return math.ldexp(x, m); 205 } 206 207 const expect = std.testing.expect; 208 const expectEqual = std.testing.expectEqual; 209 210 test "expq() special" { 211 try expectEqual(exp(0.0), 1.0); 212 try expectEqual(exp(-0.0), 1.0); 213 try expectEqual(exp(1.0), math.e); 214 try expectEqual(exp(math.ln2), 2.0); 215 try expect(math.isPositiveInf(exp(math.inf(f128)))); 216 try expect(math.isPositiveZero(exp(-math.inf(f128)))); 217 try expect(math.isNan(exp(math.nan(f128)))); 218 try expect(math.isNan(exp(math.snan(f128)))); 219 } 220 221 test "expq() sanity" { 222 try expectEqual(exp(0x1.161ba065182111ea1cf73db026b2p12), 0x1.83a48fa990038d5b6aebb7cac716p6419); 223 try expectEqual(exp(-0x1.49ce1b7b0e51027f6db3fe83bff7p9), 0x1.4dfac2418bdadddd6cf1fa1fefddp-952); 224 try expectEqual(exp(0x1.35395ecd9c471cb5a122e54421ap8), 0x1.1572fcd2d80a52183b1bc955dcb7p446); 225 try expectEqual(exp(0x1.2dfaba39016894e707847c6440b4p13), 0x1.314a408dab5852acfb4370713cdbp13941); 226 try expectEqual(exp(0x1.101337475539dd36e833c7d40d91p11), 0x1.2029e18fbabc334f851f14221089p3140); 227 try expectEqual(exp(0x1.2df2675a752767aa05874af1118cp13), 0x1.af6cbcf21a569f825eaa6879d87dp13939); 228 try expectEqual(exp(-0x1.c9900887871caf097d99f8398542p12), 0x1.04c39baa5c766f3de6233e8f07dp-10562); 229 try expectEqual(exp(0x1.9bc48fe7bfa2ac7128ebbd4939e9p12), 0x1.d931cb3d966a597631fde3c69694p9504); 230 try expectEqual(exp(-0x1.8868d9a1dd219debf76c9f0fb392p12), 0x1.f2dfb4906d3071c2df3e80934569p-9059); 231 try expectEqual(exp(0x1.5f41cc1bcb930c61a05f067fc442p13), 0x1.296ca19217f05a510f9811aa0e9cp16216); 232 try expectEqual(exp(0x1.35e8dfcc0cde6a334b9038fa98e6p13), 0x1.498de58f228e3c83d7e47400d686p14307); 233 try expectEqual(exp(0x1.ffea26d2e6e91cd9f621e730bbd2p12), 0x1.80bdb34340cb9136969a18505dd6p11816); 234 try expectEqual(exp(0x1.afc460feee0dc9db39bf49d3c112p11), 0x1.33d9f1d36aa9a75ecb5223a08282p4983); 235 try expectEqual(exp(-0x1.15511240004039de7beb770b122p13), 0x1.42058fe87c73fe2eed08e91eb0ccp-12803); 236 try expectEqual(exp(-0x1.a5e28048748f388fefc535e90fafp6), 0x1.c95ffed3eae71936b30ebdc29bfp-153); 237 try expectEqual(exp(0x1.3110993e3603ad8aea31e268ee83p12), 0x1.ccf37b60dd3e26bb7fb6b5d9f8cdp7041); 238 try expectEqual(exp(-0x1.a11e9d8a913df7ab8dcdef2179c4p12), 0x1.7e3089dc5ff6b84df2d1e042564cp-9629); 239 try expectEqual(exp(-0x1.4bcbe608a6526310c7fc13922e9p13), 0x1.26d226f1f40ab0e96bf9a717535p-15318); 240 try expectEqual(exp(0x1.410cb56d92bc5ae8986384c4299p13), 0x1.93300e94463e8e934eaff7563284p14821); 241 try expectEqual(exp(-0x1.f78f1935bf343246826d6769415fp11), 0x1.1ace810ef509fd05b4870388788ap-5812); 242 } 243 244 test "expq() boundary" { 245 // largest value before the result is infinite 246 try expectEqual(exp(0x1.62e42fefa39ef35793c7673007e5p13), 0x1.ffffffffffffffffffffffffc4a8p16383); 247 // first value that gives inf 248 try expect(math.isPositiveInf(exp(0x1.62e42fefa39ef35793c7673007e6p13))); 249 try expect(math.isPositiveInf(exp(math.floatMax(f128)))); 250 try expectEqual(exp(0x1p-16494), 1.0); 251 try expectEqual(exp(-0x1p-16494), 1.0); 252 try expectEqual(exp(0x1p-16382), 1.0); 253 try expectEqual(exp(-0x1p-16382), 1.0); 254 try expectEqual(exp(-0x1.654bb3b2c73ebb059fabb506ff33p13), 0x1p-16494); 255 try expectEqual(exp(-0x1.654bb3b2c73ebb059fabb506ff34p13), 0); 256 try expectEqual(exp(-0x1.62d918ce2421d65ff90ac8f4ce65p13), 0x1.00000000000000000000000015c6p-16382); 257 try expectEqual(exp(-0x1.62d918ce2421d65ff90ac8f4ce66p13), 0x1.ffffffffffffffffffffffffeb8cp-16383); 258 } 259 260 test "exp2q() special" { 261 try expectEqual(exp2(0.0), 1.0); 262 try expectEqual(exp2(-0.0), 1.0); 263 try expectEqual(exp2(1.0), 2.0); 264 try expectEqual(exp2(-1.0), 0.5); 265 try expectEqual(exp2(math.inf(f128)), math.inf(f128)); 266 try expect(math.isPositiveZero(exp2(-math.inf(f128)))); 267 try expect(math.isNan(exp2(math.nan(f128)))); 268 try expect(math.isNan(exp2(math.snan(f128)))); 269 } 270 271 test "exp2q() boundary" { 272 try expectEqual(exp2(0x1.ffffffffffffffffffffffffffffp13), 0x1.ffffffffffffffffffffffffd3a3p16383); 273 try expect(math.isPositiveInf(exp2(0x1p14))); 274 try expect(math.isPositiveInf(exp2(math.floatMax(f128)))); 275 try expectEqual(exp2(-0x1.01bcp14), 0); 276 try expectEqual(exp2(-0x1.01bbffffffffffffffffffffffffp14), 0x1p-16494); 277 try expectEqual(exp2(-0x1.fff0000000000000000000000001p13), 0x1.ffffffffffffffffffffffffd3a4p-16383); 278 try expectEqual(exp2(-0x1.fffp13), 0x1p-16382); 279 try expectEqual(exp2(0x1p-16494), 1.0); 280 try expectEqual(exp2(-0x1p-16494), 1.0); 281 try expectEqual(exp2(0x1p-16382), 1.0); 282 try expectEqual(exp2(-0x1p-16382), 1.0); 283 } 284 285 test "exp2q() sanity" { 286 try expectEqual(exp2(0x1.89e197c1a4509481147ae147ae16p12), 0x1.1249d5e676aa9feec3a5953b7c02p6302); 287 try expectEqual(exp2(-0x1.b411f0cfad25fc1b5c28f5c28f57p9), 0x1.d09909ac25bf2b1e11958781a70ap-873); 288 try expectEqual(exp2(0x1.e83de574e1a8b96e147ae147ae2p8), 0x1.2eb5386c57c57bc388716eaccd12p488); 289 try expectEqual(exp2(0x1.a9b613bed67b5f363d70a3d70a3ep13), 0x1.b16d037cd2c9626236091147b746p13622); 290 try expectEqual(exp2(0x1.84c9c52432be7a8a28f5c28f5c2bp11), 0x1.3c5614f7f1ddbadb57dc669669e2p3110); 291 try expectEqual(exp2(0x1.a9aa63b33e07e2bd23d70a3d70a5p13), 0x1.3ae2967925b501adb329d3bdc999p13621); 292 try expectEqual(exp2(-0x1.3f8d7f1b5b5ad15a028f5c28f5c2p13), 0x1.3e02ffbf66c581bd049af0ba1014p-10226); 293 try expectEqual(exp2(0x1.22c788348289d077a3d70a3d70a4p13), 0x1.eba8052f961ea5fb455eb7fd72c5p9304); 294 try expectEqual(exp2(-0x1.11cf846583d5645a628f5c28f5c2p13), 0x1.0aefc431a531a66384b8682fd26p-8762); 295 try expectEqual(exp2(0x1.eee7707f597161b90a3d70a3d70bp13), 0x1.e7ba24db2ff207c89727d80fca5dp15836); 296 try expectEqual(exp2(0x1.b4d8b18ce858fe773d70a3d70a3ep13), 0x1.0fdaed7d8d2bd78a08575b84b9edp13979); 297 try expectEqual(exp2(0x1.6916f408801b3f7ebd70a3d70a3ep13), 0x1.d39bbbe66e1288441ef91fb6c4f8p11554); 298 try expectEqual(exp2(0x1.32826286d5689c66147ae147ae15p12), 0x1.1bdd18f576fffb40d7a7c4600473p4904); 299 try expectEqual(exp2(-0x1.83b40cdd8603c81b65c28f5c28f6p13), 0x1.687736e6ce5610f434444b20f2a5p-12407); 300 try expectEqual(exp2(-0x1.7832ea6506b0b2f47ae147ae144dp6), 0x1.eea794ee31522277606ff7a2c8ep-95); 301 try expectEqual(exp2(0x1.afbb8b6830cac8c2e147ae147ae2p12), 0x1.a620a1f8a46335e10818a504693cp6907); 302 try expectEqual(exp2(-0x1.2328a820e1db0e1b028f5c28f5c2p13), 0x1.e3add1a5b805ac7fa39b1ecf7a2ap-9318); 303 try expectEqual(exp2(-0x1.d03363f43eb86051c5c28f5c28f6p13), 0x1.7dac5a9d06f845523a229370d6fbp-14855); 304 try expectEqual(exp2(0x1.c47d13ba4001d5d6a3d70a3d70a5p13), 0x1.8d7369b8ad7bd5aace25ccb030dbp14479); 305 try expectEqual(exp2(-0x1.5e280f18074b0b38d1eb851eb851p12), 0x1.691d77d02a99bab87b9bd0aeb82ep-5603); 306 } 307 308 const size = 64; 309 310 /// exp2_tab[j].hi + exp2_tab[j].lo ~= 2^(j / size) 311 /// where exp2_tab[j].hi has its 30 trailing bits set to 0 312 const exp2_tab = [size]struct { hi: f128, lo: f128 }{ 313 .{ .hi = 1, .lo = 0 }, 314 .{ .hi = 1.0108892860517004600204097572469746, .lo = 3.331488596564031210563288051982794e-26 }, 315 .{ .hi = 1.0218971486541166782344800872427626, .lo = 4.754053684121973789288755464722138e-26 }, 316 .{ .hi = 1.0330248790212284225001081883964135, .lo = 9.557404741840277960546616586298063e-26 }, 317 .{ .hi = 1.044273782427413840321966300719135, .lo = 1.7802079401409229639033486606835582e-25 }, 318 .{ .hi = 1.0556451783605571588083412749313592, .lo = 5.022157947196508429749069389839003e-26 }, 319 .{ .hi = 1.0671404006768236181695209696174248, .lo = 1.5137538440721428405259778473587436e-25 }, 320 .{ .hi = 1.0787607977571197937406800254939246, .lo = 1.1944558390181437089024030105545753e-26 }, 321 .{ .hi = 1.0905077326652576592070106394193907, .lo = 1.6341317298466358429137337862221883e-26 }, 322 .{ .hi = 1.1023825833078409435564140763781162, .lo = 1.3304753063524778951752027959085558e-25 }, 323 .{ .hi = 1.1143867425958925363088128257407598, .lo = 1.3117884324019192923687629273175252e-25 }, 324 .{ .hi = 1.1265216186082418997947985102919192, .lo = 1.3349511554260129942233288245148925e-25 }, 325 .{ .hi = 1.1387886347566916537038301230733987, .lo = 1.6076811251744575806878211946090158e-25 }, 326 .{ .hi = 1.1511892299529827058177595055860644, .lo = 1.296159181480888798344830542672908e-25 }, 327 .{ .hi = 1.1637248587775775138135734257915416, .lo = 1.7330064367522746277589854745025186e-25 }, 328 .{ .hi = 1.1763969916502812762846455513693297, .lo = 1.771145189358715817500494171124228e-25 }, 329 .{ .hi = 1.1892071150027210667174999505630234, .lo = 1.9997452525989289056308227410382985e-26 }, 330 .{ .hi = 1.2021567314527031420963969135940365, .lo = 4.39037293484801126250674148724549e-26 }, 331 .{ .hi = 1.2152473599804688781165200985991755, .lo = 1.527396229646477709981006835952422e-25 }, 332 .{ .hi = 1.228480536106870005694008874178169, .lo = 8.361461276961479852265822764365295e-26 }, 333 .{ .hi = 1.2418578120734840485936772681433546, .lo = 2.0058324097379166931165857504486515e-25 }, 334 .{ .hi = 1.2553807570246910895793906081957795, .lo = 4.924652165836275746251690393601314e-26 }, 335 .{ .hi = 1.2690509571917332225544190491370338, .lo = 3.189530418840927873154659237729416e-26 }, 336 .{ .hi = 1.2828700160787782807266696484653204, .lo = 1.3255619363013763369194141036415331e-25 }, 337 .{ .hi = 1.2968395546510096659337539149835045, .lo = 2.02808946708216061939618255479545e-25 }, 338 .{ .hi = 1.310961211524764341922991651706552, .lo = 1.346242038813654021913487031222685e-25 }, 339 .{ .hi = 1.3252366431597412946295370636866045, .lo = 3.1812117152957157712136370198427476e-26 }, 340 .{ .hi = 1.3396675240533030053600306458323573, .lo = 2.3891995273689563530726030193400994e-26 }, 341 .{ .hi = 1.3542555469368927282980146833689865, .lo = 5.67717163322109547382357648078323e-26 }, 342 .{ .hi = 1.3690024229745906119296010288577105, .lo = 1.0412448235463674573152224239700108e-25 }, 343 .{ .hi = 1.3839098819638319548726593727386685, .lo = 1.5452652430918943949928858324045516e-25 }, 344 .{ .hi = 1.3989796725383111402095280019026587, .lo = 1.3481253628381644220060758348040214e-25 }, 345 .{ .hi = 1.4142135623730950488016886615184001, .lo = 6.269129796655816816448098260436884e-26 }, 346 .{ .hi = 1.4296133383919700112350655775923445, .lo = 2.0068279541703738029999633782788845e-25 }, 347 .{ .hi = 1.445180806977046620037006089799907, .lo = 1.5167176381672076760972768074093684e-25 }, 348 .{ .hi = 1.4609177941806469886513027234439021, .lo = 1.6686671941792611979901360149296145e-25 }, 349 .{ .hi = 1.4768261459394993113869072754361651, .lo = 2.0493788478634531656455008519536741e-25 }, 350 .{ .hi = 1.49290772829126484920064342375234, .lo = 1.0773433350993147906480285567163657e-25 }, 351 .{ .hi = 1.5091644275934227397660193613621397, .lo = 1.8967105384997666454575618820074827e-25 }, 352 .{ .hi = 1.5255981507445383068512536547525588, .lo = 3.4764382194065807351168306319041174e-26 }, 353 .{ .hi = 1.5422108254079408236122917536092588, .lo = 1.0848147603849114107703141658063051e-25 }, 354 .{ .hi = 1.5590044002378369670337279975513864, .lo = 9.192347150259542397065645937482374e-26 }, 355 .{ .hi = 1.5759808451078864864552699975624628, .lo = 1.6261944219083569434254919427993836e-25 }, 356 .{ .hi = 1.5931421513422668979372484585565874, .lo = 1.8456248131371918402429861736678934e-25 }, 357 .{ .hi = 1.6104903319492543081795206443457414, .lo = 2.3011659157684786972918492411493627e-26 }, 358 .{ .hi = 1.6280274218573477668482183385098177, .lo = 1.835041970102208063150895447921664e-25 }, 359 .{ .hi = 1.64575547815396484451875663203744, .lo = 9.268838235051047071258544486384168e-26 }, 360 .{ .hi = 1.6636765803267364350463362566524458, .lo = 2.0032394462130729047106824908094624e-25 }, 361 .{ .hi = 1.6817928305074290860622508766963224, .lo = 7.577010737594502271619933404428869e-26 }, 362 .{ .hi = 1.7001063537185234695013623801157575, .lo = 1.933817448612744754580708784271012e-25 }, 363 .{ .hi = 1.718619298122477915629344290158266, .lo = 8.62980464213340198403279699525989e-26 }, 364 .{ .hi = 1.7373338352737062489942020634467155, .lo = 1.8425451283271326141972376758637252e-26 }, 365 .{ .hi = 1.7562521603732994831121604835510348, .lo = 1.3582427846847187375106521297188138e-25 }, 366 .{ .hi = 1.7753764925265212525505591418467304, .lo = 5.835259276799184480900795848675494e-26 }, 367 .{ .hi = 1.7947090750031071864277031433167551, .lo = 9.881102667288512774484945809680091e-26 }, 368 .{ .hi = 1.8142521755003987562498344916971016, .lo = 1.0866523870529919822788296235287719e-25 }, 369 .{ .hi = 1.8340080864093424634870830493492878, .lo = 1.4023900106308197217404351420134241e-25 }, 370 .{ .hi = 1.8539791250833855683924529817164416, .lo = 8.862125500492644219109133612513259e-26 }, 371 .{ .hi = 1.874167634110299901329998762784126, .lo = 1.8717032055831336786703352406163195e-25 }, 372 .{ .hi = 1.89457598158696564134021858484563, .lo = 6.858129468658742940783256569996436e-26 }, 373 .{ .hi = 1.915206561397147293872611189644507, .lo = 8.065132397713481068247895691781549e-26 }, 374 .{ .hi = 1.9360617934922944505980557715120804, .lo = 1.3305461113869976975105134936816773e-25 }, 375 .{ .hi = 1.9571441241754002690183220766337223, .lo = 1.749931492273774722940602643722382e-25 }, 376 .{ .hi = 1.9784560263879509682582497478585111, .lo = 1.702726561957295469933280686411065e-25 }, 377 }; 378