Coverage Report

Created: 2026-05-16 07:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/pxfm-0.1.29/src/hyperbolic/acosh.rs
Line
Count
Source
1
/*
2
 * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved.
3
 * //
4
 * // Redistribution and use in source and binary forms, with or without modification,
5
 * // are permitted provided that the following conditions are met:
6
 * //
7
 * // 1.  Redistributions of source code must retain the above copyright notice, this
8
 * // list of conditions and the following disclaimer.
9
 * //
10
 * // 2.  Redistributions in binary form must reproduce the above copyright notice,
11
 * // this list of conditions and the following disclaimer in the documentation
12
 * // and/or other materials provided with the distribution.
13
 * //
14
 * // 3.  Neither the name of the copyright holder nor the names of its
15
 * // contributors may be used to endorse or promote products derived from
16
 * // this software without specific prior written permission.
17
 * //
18
 * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
 * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
 * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
 * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22
 * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
 * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24
 * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25
 * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26
 * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27
 * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
 */
29
use crate::common::{dd_fmla, f_fmla};
30
use crate::double_double::DoubleDouble;
31
32
pub(crate) static ACOSH_ASINH_LL: [[(u64, u64, u64); 17]; 4] = [
33
    [
34
        (0x0000000000000000, 0x0000000000000000, 0x0000000000000000),
35
        (0x3f962e432b240000, 0xbd5745af34bb54b8, 0xb9e17e3ec05cde70),
36
        (0x3fa62e42e4a80000, 0x3d3111a4eadf3120, 0x3a2cff3027abb119),
37
        (0x3fb0a2b233f10000, 0xbd588ac4ec78af80, 0x3a24fa087ca75dfd),
38
        (0x3fb62e43056c0000, 0x3d16bd65e8b0b700, 0xba0b18e160362c24),
39
        (0x3fbbb9d3cbd60000, 0x3d5de14aa55ec2b0, 0xba1c6ac3f1862a6b),
40
        (0x3fc0a2b244da0000, 0x3d594def487fea70, 0xba1dead1a4581acf),
41
        (0x3fc3687aa9b78000, 0x3d49cec9a50db220, 0x3a234a70684f8e0e),
42
        (0x3fc62e42faba0000, 0xbd3d69047a3aeb00, 0xba04e061f79144e2),
43
        (0x3fc8f40b56d28000, 0x3d5de7d755fd2e20, 0x3a1bdc7ecf001489),
44
        (0x3fcbb9d3b61f0000, 0x3d1c14f1445b1200, 0x3a2a1d78cbdc5b58),
45
        (0x3fce7f9c11f08000, 0xbd46e3e0000dae70, 0x3a16a4559fadde98),
46
        (0x3fd0a2b242ec4000, 0x3d5bb7cf852a5fe8, 0x3a2a6aef11ee43bd),
47
        (0x3fd205966c764000, 0x3d2ad3a5f2142940, 0x3a25cc344fa10652),
48
        (0x3fd3687a98aac000, 0x3d21623671842f00, 0xba10b428fe1f9e43),
49
        (0x3fd4cb5ec93f4000, 0x3d53d50980ea5130, 0x3a267f0ea083b1c4),
50
        (0x3fd62e42fefa4000, 0xbd38432a1b0e2640, 0x3a2803f2f6af40f3),
51
    ],
52
    [
53
        (0x0000000000000000, 0x0000000000000000, 0x0000000000000000),
54
        (0x3f562e462b400000, 0x3d5061d003b97318, 0x3a2d7faee66a2e1e),
55
        (0x3f662e44c9200000, 0x3d595a7bff5e2390, 0xba0f7e788a871350),
56
        (0x3f70a2b1e3300000, 0x3d42a3a1a65aa3a0, 0xba254599c9605442),
57
        (0x3f762e4367c00000, 0xbd24a995b6d9ddc0, 0xb9b56bb79b254f33),
58
        (0x3f7bb9d449a00000, 0x3d58a119c42e9bc0, 0xba28ecf7d8d661f1),
59
        (0x3f80a2b1f1900000, 0x3d58863771bd10a8, 0x3a1e9731de7f0155),
60
        (0x3f83687ad1100000, 0x3d5e026a347ca1c8, 0x39efadc62522444d),
61
        (0x3f862e436f280000, 0x3d525b84f71b70b8, 0xb9ffcb3f98612d27),
62
        (0x3f88f40b7b380000, 0xbd462a0a4fd47580, 0x3a23cb3c35d9f6a1),
63
        (0x3f8bb9d3abb00000, 0xbd50ec48f94d7860, 0xba26b47d410e4cc7),
64
        (0x3f8e7f9bb2300000, 0x3d4e4415cbc97a00, 0xba23729fdb677231),
65
        (0x3f90a2b224780000, 0xbd5cb73f4505b030, 0xba21b3b3a3bc370a),
66
        (0x3f92059691e80000, 0xbd4abcc3412f2640, 0xba0fe6e998e48673),
67
        (0x3f93687a76800000, 0xbd543901e5c97a90, 0x39fb54cdd52a5d88),
68
        (0x3f94cb5eb5d80000, 0xbd58f106f00f13b8, 0xba28f793f5fce148),
69
        (0x3f962e432b240000, 0xbd5745af34bb54b8, 0xb9e17e3ec05cde70),
70
    ],
71
    [
72
        (0x0000000000000000, 0x0000000000000000, 0x0000000000000000),
73
        (0x3f162e7b00000000, 0xbd3868625640a680, 0xba234bf0db910f65),
74
        (0x3f262e35f6000000, 0xbd42ee3d96b696a0, 0x3a1a2948cd558655),
75
        (0x3f30a2b4b2000000, 0x3d053edbcf116500, 0xb9ecfc26ccf6d0e4),
76
        (0x3f362e4be1000000, 0x3cb783e334614000, 0xba204b96da30e63a),
77
        (0x3f3bb9e085000000, 0xbd460785f20acb20, 0xb9ff33369bf7dff1),
78
        (0x3f40a2b94d000000, 0x3d5fd4b3a2733530, 0xb9f685a35575eff1),
79
        (0x3f4368810f800000, 0x3d07ded26dc81300, 0xb9f4c4d1abca79bf),
80
        (0x3f462e4787800000, 0x3d57d2bee9a1f630, 0x3a2860233b7ad130),
81
        (0x3f48f40cb4800000, 0xbd5af034eaf471c0, 0x3a1ae748822d57b7),
82
        (0x3f4bb9d094000000, 0xbd57a223013a20f0, 0xba21e499087075b6),
83
        (0x3f4e7fa32c800000, 0xbd4b2e67b1b59bd0, 0xba254a41eda30fa6),
84
        (0x3f50a2b237000000, 0xbd37ad97ff4ac7a0, 0x3a2f932da91371dd),
85
        (0x3f52059a33800000, 0xbd396422d90df400, 0xba190800fbbf2ed3),
86
        (0x3f53687982400000, 0x3d30f90540018120, 0x3a29567e01e48f9a),
87
        (0x3f54cb602c000000, 0xbd40d709a5ec0b50, 0x3a1253dfd44635d2),
88
        (0x3f562e462b400000, 0x3d5061d003b97318, 0x3a2d7faee66a2e1e),
89
    ],
90
    [
91
        (0x0000000000000000, 0x0000000000000000, 0x0000000000000000),
92
        (0x3ed63007c0000000, 0xbd4db0e38e5aaaa0, 0x3a2259a7b94815b9),
93
        (0x3ee6300f60000000, 0x3d32b1c755804380, 0x3a278cabba01e3e4),
94
        (0x3ef0a21150000000, 0xbd55ff2237307590, 0x3a08074feacfe49d),
95
        (0x3ef62e1ec0000000, 0xbd285d6f6487ce40, 0x3a205485074b9276),
96
        (0x3efbba3010000000, 0xbd4af5d58a7c9210, 0xba230a8c0fd2ff5f),
97
        (0x3f00a32298000000, 0x3d4590faa0883bd0, 0x3a295e9bda999947),
98
        (0x3f03682f10000000, 0x3d5f0224376efaf8, 0xba25843c0db50d10),
99
        (0x3f062e3d80000000, 0xbd4142c13daed4a0, 0x3a2c68a61183ce87),
100
        (0x3f08f44dd8000000, 0xbd4aa489f3999310, 0x3a111c5c376854ea),
101
        (0x3f0bb96010000000, 0x3d59904d8b6a3638, 0x3a28c89554493c8f),
102
        (0x3f0e7f7440000000, 0x3d55785ddbe7cba8, 0x3a1e7ff3cde7d70c),
103
        (0x3f10a2c530000000, 0xbd46d9e8780d0d50, 0x3a1ad9c178106693),
104
        (0x3f1205d134000000, 0xbd4214a2e893fcc0, 0x3a2548a9500c9822),
105
        (0x3f13685e28000000, 0x3d4e235886461030, 0x3a12a97b26da2d88),
106
        (0x3f14cb6c18000000, 0x3d52b7cfcea9e0d8, 0xba25095048a6b824),
107
        (0x3f162e7b00000000, 0xbd3868625640a680, 0xba234bf0db910f65),
108
    ],
109
];
110
111
pub(crate) static ACOSH_SINH_REFINE_T1: [u64; 17] = [
112
    0x3ff0000000000000,
113
    0x3feea4afa0000000,
114
    0x3fed5818e0000000,
115
    0x3fec199be0000000,
116
    0x3feae89f98000000,
117
    0x3fe9c49180000000,
118
    0x3fe8ace540000000,
119
    0x3fe7a11470000000,
120
    0x3fe6a09e68000000,
121
    0x3fe5ab07e0000000,
122
    0x3fe4bfdad8000000,
123
    0x3fe3dea650000000,
124
    0x3fe306fe08000000,
125
    0x3fe2387a70000000,
126
    0x3fe172b840000000,
127
    0x3fe0b55870000000,
128
    0x3fe0000000000000,
129
];
130
131
pub(crate) static ACOSH_ASINH_REFINE_T2: [u64; 16] = [
132
    0x3ff0000000000000,
133
    0x3fefe9d968000000,
134
    0x3fefd3c228000000,
135
    0x3fefbdba38000000,
136
    0x3fefa7c180000000,
137
    0x3fef91d800000000,
138
    0x3fef7bfdb0000000,
139
    0x3fef663278000000,
140
    0x3fef507658000000,
141
    0x3fef3ac948000000,
142
    0x3fef252b38000000,
143
    0x3fef0f9c20000000,
144
    0x3feefa1bf0000000,
145
    0x3feee4aaa0000000,
146
    0x3feecf4830000000,
147
    0x3feeb9f488000000,
148
];
149
150
pub(crate) static ACOSH_SINH_REFINE_T3: [u64; 16] = [
151
    0x3ff0000000000000,
152
    0x3feffe9d20000000,
153
    0x3feffd3a58000000,
154
    0x3feffbd798000000,
155
    0x3feffa74e8000000,
156
    0x3feff91248000000,
157
    0x3feff7afb8000000,
158
    0x3feff64d38000000,
159
    0x3feff4eac8000000,
160
    0x3feff38868000000,
161
    0x3feff22618000000,
162
    0x3feff0c3d0000000,
163
    0x3fefef61a0000000,
164
    0x3fefedff78000000,
165
    0x3fefec9d68000000,
166
    0x3fefeb3b60000000,
167
];
168
169
pub(crate) static ACOSH_ASINH_REFINE_T4: [u64; 16] = [
170
    0x3ff0000000000000,
171
    0x3fefffe9d0000000,
172
    0x3fefffd3a0000000,
173
    0x3fefffbd78000000,
174
    0x3fefffa748000000,
175
    0x3fefff9118000000,
176
    0x3fefff7ae8000000,
177
    0x3fefff64c0000000,
178
    0x3fefff4e90000000,
179
    0x3fefff3860000000,
180
    0x3fefff2238000000,
181
    0x3fefff0c08000000,
182
    0x3feffef5d8000000,
183
    0x3feffedfa8000000,
184
    0x3feffec980000000,
185
    0x3feffeb350000000,
186
];
187
188
#[cold]
189
0
fn acosh_refine(x: f64, a: f64) -> f64 {
190
0
    let ix = x.to_bits();
191
192
0
    let z: DoubleDouble = if ix < 0x4190000000000000u64 {
193
0
        let dx2 = DoubleDouble::from_exact_mult(x, x);
194
0
        let w = DoubleDouble::from_exact_add(dx2.hi - 1., dx2.lo);
195
0
        let sh = w.hi.sqrt();
196
0
        let ish = 0.5 / w.hi;
197
0
        let sl = (ish * sh) * (w.lo - dd_fmla(sh, sh, -w.hi));
198
0
        let mut p = DoubleDouble::from_exact_add(x, sh);
199
0
        p.lo += sl;
200
0
        DoubleDouble::from_exact_add(p.hi, p.lo)
201
0
    } else if ix < 0x4330000000000000 {
202
0
        DoubleDouble::new(-0.5 / x, 2. * x)
203
    } else {
204
0
        DoubleDouble::new(0., x)
205
    };
206
207
0
    let mut t = z.hi.to_bits();
208
0
    let ex: i32 = (t >> 52) as i32;
209
0
    let e = ex.wrapping_sub(0x3ff) + if z.lo == 0.0 { 1i32 } else { 0i32 };
210
0
    t &= 0x000fffffffffffff;
211
0
    t |= 0x3ffu64 << 52;
212
0
    let ed = e as f64;
213
0
    let v = (a - ed + f64::from_bits(0x3ff0000800000000)).to_bits();
214
0
    let i = (v.wrapping_sub(0x3ffu64 << 52)) >> (52 - 16);
215
0
    let i1 = (i >> 12) & 0x1f;
216
0
    let i2 = (i >> 8) & 0xf;
217
0
    let i3 = (i >> 4) & 0xf;
218
0
    let i4 = i & 0xf;
219
    const L20: f64 = f64::from_bits(0x3fd62e42fefa3800);
220
    const L21: f64 = f64::from_bits(0x3d1ef35793c76800);
221
    const L22: f64 = f64::from_bits(0xba49ff0342542fc3);
222
0
    let el2 = L22 * ed;
223
0
    let el1 = L21 * ed;
224
0
    let el0 = L20 * ed;
225
    let mut dl0: f64;
226
227
0
    let ll0i1 = ACOSH_ASINH_LL[0][i1 as usize];
228
0
    let ll1i2 = ACOSH_ASINH_LL[1][i2 as usize];
229
0
    let ll2i3 = ACOSH_ASINH_LL[2][i3 as usize];
230
0
    let ll3i4 = ACOSH_ASINH_LL[3][i4 as usize];
231
232
0
    dl0 = f64::from_bits(ll0i1.0)
233
0
        + f64::from_bits(ll1i2.0)
234
0
        + (f64::from_bits(ll2i3.0) + f64::from_bits(ll3i4.0));
235
0
    let dl1 = f64::from_bits(ll0i1.1)
236
0
        + f64::from_bits(ll1i2.1)
237
0
        + (f64::from_bits(ll2i3.1) + f64::from_bits(ll3i4.1));
238
0
    let dl2 = f64::from_bits(ll0i1.2)
239
0
        + f64::from_bits(ll1i2.2)
240
0
        + (f64::from_bits(ll2i3.2) + f64::from_bits(ll3i4.2));
241
0
    dl0 += el0;
242
0
    let t12 = f64::from_bits(ACOSH_SINH_REFINE_T1[i1 as usize])
243
0
        * f64::from_bits(ACOSH_ASINH_REFINE_T2[i2 as usize]);
244
0
    let t34 = f64::from_bits(ACOSH_SINH_REFINE_T3[i3 as usize])
245
0
        * f64::from_bits(ACOSH_ASINH_REFINE_T4[i4 as usize]);
246
0
    let th = t12 * t34;
247
0
    let tl = dd_fmla(t12, t34, -th);
248
0
    let dh = th * f64::from_bits(t);
249
0
    let dl = dd_fmla(th, f64::from_bits(t), -dh);
250
0
    let sh = tl * f64::from_bits(t);
251
0
    let sl = dd_fmla(tl, f64::from_bits(t), -sh);
252
253
0
    let mut dx = DoubleDouble::from_exact_add(dh - 1., dl);
254
0
    if z.lo != 0.0 {
255
0
        t = z.lo.to_bits();
256
0
        t = t.wrapping_sub((e as i64).wrapping_shl(52) as u64);
257
0
        dx.lo += th * f64::from_bits(t);
258
0
    }
259
0
    dx = DoubleDouble::add(dx, DoubleDouble::new(sl, sh));
260
    const CL: [u64; 3] = [0xbfc0000000000000, 0x3fb9999999a0754f, 0xbfb55555555c3157];
261
0
    let sl = dx.hi
262
0
        * (f64::from_bits(CL[0]) + dx.hi * (f64::from_bits(CL[1]) + dx.hi * f64::from_bits(CL[2])));
263
    const CH: [(u64, u64); 3] = [
264
        (0x39024b67ee516e3b, 0x3fe0000000000000),
265
        (0xb91932ce43199a8d, 0xbfd0000000000000),
266
        (0x3c655540c15cf91f, 0x3fc5555555555555),
267
    ];
268
0
    let mut s = lpoly_xd_generic(dx, CH, sl);
269
0
    s = DoubleDouble::quick_mult(dx, s);
270
0
    s = DoubleDouble::add(s, DoubleDouble::new(el2, el1));
271
0
    s = DoubleDouble::add(s, DoubleDouble::new(dl2, dl1));
272
0
    let mut v02 = DoubleDouble::from_exact_add(dl0, s.hi);
273
0
    let mut v12 = DoubleDouble::from_exact_add(v02.lo, s.lo);
274
0
    v02.hi *= 2.;
275
0
    v12.hi *= 2.;
276
0
    v12.lo *= 2.;
277
0
    t = v12.hi.to_bits();
278
0
    if (t & 0x000fffffffffffff) == 0 {
279
0
        let w = v12.lo.to_bits();
280
0
        if ((w ^ t) >> 63) != 0 {
281
0
            t = t.wrapping_sub(1);
282
0
        } else {
283
0
            t = t.wrapping_add(1);
284
0
        }
285
0
        v12.hi = f64::from_bits(t);
286
0
    }
287
0
    v02.hi + v12.hi
288
0
}
289
290
pub(crate) static ACOSH_ASINH_B: [[i32; 2]; 32] = [
291
    [301, 27565],
292
    [7189, 24786],
293
    [13383, 22167],
294
    [18923, 19696],
295
    [23845, 17361],
296
    [28184, 15150],
297
    [31969, 13054],
298
    [35231, 11064],
299
    [37996, 9173],
300
    [40288, 7372],
301
    [42129, 5657],
302
    [43542, 4020],
303
    [44546, 2457],
304
    [45160, 962],
305
    [45399, -468],
306
    [45281, -1838],
307
    [44821, -3151],
308
    [44032, -4412],
309
    [42929, -5622],
310
    [41522, -6786],
311
    [39825, -7905],
312
    [37848, -8982],
313
    [35602, -10020],
314
    [33097, -11020],
315
    [30341, -11985],
316
    [27345, -12916],
317
    [24115, -13816],
318
    [20661, -14685],
319
    [16989, -15526],
320
    [13107, -16339],
321
    [9022, -17126],
322
    [4740, -17889],
323
];
324
325
pub(crate) static ACOSH_ASINH_R1: [u64; 33] = [
326
    0x3ff0000000000000,
327
    0x3fef507600000000,
328
    0x3feea4b000000000,
329
    0x3fedfc9800000000,
330
    0x3fed581800000000,
331
    0x3fecb72000000000,
332
    0x3fec199c00000000,
333
    0x3feb7f7600000000,
334
    0x3feae8a000000000,
335
    0x3fea550400000000,
336
    0x3fe9c49200000000,
337
    0x3fe9373800000000,
338
    0x3fe8ace600000000,
339
    0x3fe8258a00000000,
340
    0x3fe7a11400000000,
341
    0x3fe71f7600000000,
342
    0x3fe6a09e00000000,
343
    0x3fe6247e00000000,
344
    0x3fe5ab0800000000,
345
    0x3fe5342c00000000,
346
    0x3fe4bfda00000000,
347
    0x3fe44e0800000000,
348
    0x3fe3dea600000000,
349
    0x3fe371a800000000,
350
    0x3fe306fe00000000,
351
    0x3fe29e9e00000000,
352
    0x3fe2387a00000000,
353
    0x3fe1d48800000000,
354
    0x3fe172b800000000,
355
    0x3fe1130200000000,
356
    0x3fe0b55800000000,
357
    0x3fe059b000000000,
358
    0x3fe0000000000000,
359
];
360
361
pub(crate) static ACOSH_ASINH_R2: [u64; 33] = [
362
    0x3ff0000000000000,
363
    0x3feffa7400000000,
364
    0x3feff4ea00000000,
365
    0x3fefef6200000000,
366
    0x3fefe9da00000000,
367
    0x3fefe45200000000,
368
    0x3fefdecc00000000,
369
    0x3fefd94600000000,
370
    0x3fefd3c200000000,
371
    0x3fefce3e00000000,
372
    0x3fefc8bc00000000,
373
    0x3fefc33a00000000,
374
    0x3fefbdba00000000,
375
    0x3fefb83a00000000,
376
    0x3fefb2bc00000000,
377
    0x3fefad3e00000000,
378
    0x3fefa7c200000000,
379
    0x3fefa24600000000,
380
    0x3fef9cca00000000,
381
    0x3fef975000000000,
382
    0x3fef91d800000000,
383
    0x3fef8c6000000000,
384
    0x3fef86e800000000,
385
    0x3fef817200000000,
386
    0x3fef7bfe00000000,
387
    0x3fef768a00000000,
388
    0x3fef711600000000,
389
    0x3fef6ba400000000,
390
    0x3fef663200000000,
391
    0x3fef60c200000000,
392
    0x3fef5b5200000000,
393
    0x3fef55e400000000,
394
    0x3fef507600000000,
395
];
396
397
pub(crate) static ACOSH_ASINH_L1: [(u64, u64); 33] = [
398
    (0x0000000000000000, 0x0000000000000000),
399
    (0xbd1269e2038315b3, 0x3f962e4eacd40000),
400
    (0xbd23f2558bddfc47, 0x3fa62e3ce7218000),
401
    (0x3d207ea13c34efb5, 0x3fb0a2ab6d3ec000),
402
    (0x3d38f3e77084d3ba, 0x3fb62e4a86d8c000),
403
    (0xbd18d92a005f1a7e, 0x3fbbb9db7062c000),
404
    (0x3d358239e799bfe5, 0x3fc0a2b1a22cc000),
405
    (0xbd3a93fcf5f593b7, 0x3fc3687f0a298000),
406
    (0xbd1db4cac32fd2b5, 0x3fc62e4116b64000),
407
    (0xbd10e65a92ee0f3b, 0x3fc8f409e4df6000),
408
    (0xbd38261383d475f1, 0x3fcbb9d15001c000),
409
    (0xbd3359886207513b, 0x3fce7f9a8c940000),
410
    (0x3d3811f87496ceb7, 0x3fd0a2b052ddb000),
411
    (0x3d34991ec6cb435c, 0x3fd205955ef73000),
412
    (0xbd34581abfeb8927, 0x3fd3687bd9121000),
413
    (0x3d3cab48f6942703, 0x3fd4cb5e8f2b5000),
414
    (0xbd0df2c452fde132, 0x3fd62e4420e20000),
415
    (0x3d26109f4fdb74bd, 0x3fd791292c46a000),
416
    (0xbd36b95fbdac7696, 0x3fd8f40af84e7000),
417
    (0x3d17394fa880cbda, 0x3fda56ed8f865000),
418
    (0xbd150b06a94eccab, 0x3fdbb9d6505b4000),
419
    (0xbd3be2abf0b38989, 0x3fdd1cb91e728000),
420
    (0xbd37d6bf1e34da04, 0x3fde7f9d139e2000),
421
    (0xbd3423c1e14de6ed, 0x3fdfe27db9b0e000),
422
    (0x3d3c46f1a0efbbc2, 0x3fe0a2b25060a800),
423
    (0x3d2834fe4e3e6018, 0x3fe154244482a000),
424
    (0x3d16a03d0f02b650, 0x3fe2059731298800),
425
    (0x3d3d437056526f30, 0x3fe2b707145de000),
426
    (0xbd2a0233728405c5, 0x3fe3687b0e0b2800),
427
    (0xbd24dbdda10d2bf1, 0x3fe419ec5d3f6800),
428
    (0x3d3f7d0a25d154f2, 0x3fe4cb5f9fc02000),
429
    (0x3d315ede4d803b18, 0x3fe57cd28421a800),
430
    (0x3d2ef35793c76730, 0x3fe62e42fefa3800),
431
];
432
433
pub(crate) static ACOSH_ASINH_L2: [(u64, u64); 33] = [
434
    (0x0000000000000000, 0x0000000000000000),
435
    (0x3d35abdac3638e99, 0x3f4631ec81e00000),
436
    (0xbd216b8be9bbe239, 0x3f562fd812700000),
437
    (0xbd3364c6315542eb, 0x3f60a25205080000),
438
    (0x3d2734abe459c900, 0x3f662dadc1d00000),
439
    (0x3d30cf8a761431bf, 0x3f6bb9ff94d00000),
440
    (0x3d2da2718eb78708, 0x3f70a2a2def80000),
441
    (0x3d334ada62c59b93, 0x3f7368c0fae40000),
442
    (0x3d3d09ab376682d4, 0x3f762e58e4f80000),
443
    (0xbd23cb7b94329211, 0x3f78f46bd28c0000),
444
    (0xbd2eec5c297c41d0, 0x3f7bb9f831200000),
445
    (0xbd36411b9395d150, 0x3f7e7fff8f300000),
446
    (0xbd31c0e59a43053c, 0x3f80a2c0006e0000),
447
    (0x3d16506596e077b6, 0x3f8205bdb6f00000),
448
    (0x3d3e256bce6faa27, 0x3f836877c86e0000),
449
    (0x3ccbd42467b0c8d1, 0x3f84cb6f55780000),
450
    (0xbd3c4f92132ff0f0, 0x3f862e230e8c0000),
451
    (0xbd380be08bfab390, 0x3f87911440f60000),
452
    (0xbd3f0b1319ceb1f7, 0x3f88f443020a0000),
453
    (0x3d2a65fcfb8de99b, 0x3f8a572dbef40000),
454
    (0x3d14233885d3779c, 0x3f8bb9d449a60000),
455
    (0x3d3f46a59e646edb, 0x3f8d1cb8491c0000),
456
    (0xbd3c3d2f11c11446, 0x3f8e7fd9d2aa0000),
457
    (0x3d27763f78a1e0cc, 0x3f8fe2b6f9780000),
458
    (0x3d3b4c37fc60c043, 0x3f90a2a7c7a50000),
459
    (0xbd15b8a822859be3, 0x3f915412ca860000),
460
    (0xbd3f2d8c9fc06400, 0x3f92059c90050000),
461
    (0xbd3e80e79c20378d, 0x3f92b703f49b0000),
462
    (0x3d368256e4329bdb, 0x3f93688a1a8d0000),
463
    (0x3d37e9741da248c3, 0x3f9419edc7ba0000),
464
    (0x3d2e330dccce602b, 0x3f94cb7034fa0000),
465
    (0x3ce2f32b5d18eefb, 0x3f957cd011870000),
466
    (0xbd1269e2038315b3, 0x3f962e4eacd40000),
467
];
468
469
#[inline]
470
0
pub(crate) fn lpoly_xd_generic<const N: usize>(
471
0
    x: DoubleDouble,
472
0
    poly: [(u64, u64); N],
473
0
    l: f64,
474
0
) -> DoubleDouble {
475
0
    let zch = poly.last().unwrap();
476
477
0
    let tch = f64::from_bits(zch.1) + l;
478
479
0
    let mut ch = DoubleDouble::new(
480
0
        ((f64::from_bits(zch.1) - tch) + l) + f64::from_bits(zch.0),
481
0
        tch,
482
    );
483
484
0
    for zch in poly.iter().rev().skip(1) {
485
0
        ch = DoubleDouble::mult(ch, x);
486
0
        let th = ch.hi + f64::from_bits(zch.1);
487
0
        let tl = (f64::from_bits(zch.1) - th) + ch.hi;
488
0
        ch.hi = th;
489
0
        ch.lo += tl + f64::from_bits(zch.0);
490
0
    }
491
492
0
    ch
493
0
}
Unexecuted instantiation: pxfm::hyperbolic::acosh::lpoly_xd_generic::<3>
Unexecuted instantiation: pxfm::hyperbolic::acosh::lpoly_xd_generic::<4>
Unexecuted instantiation: pxfm::hyperbolic::acosh::lpoly_xd_generic::<5>
Unexecuted instantiation: pxfm::hyperbolic::acosh::lpoly_xd_generic::<10>
Unexecuted instantiation: pxfm::hyperbolic::acosh::lpoly_xd_generic::<12>
Unexecuted instantiation: pxfm::hyperbolic::acosh::lpoly_xd_generic::<13>
494
495
#[cold]
496
0
fn as_acosh_one(x: f64, sh: f64, sl: f64) -> f64 {
497
    static CH: [(u64, u64); 10] = [
498
        (0xbc55555555554af1, 0xbfb5555555555555),
499
        (0x3c29999998933f0e, 0x3f93333333333333),
500
        (0x3c024929b16ec6b7, 0xbf76db6db6db6db7),
501
        (0x3bdc56d45e265e2c, 0x3f5f1c71c71c71c7),
502
        (0x3be6d50ce7188d3d, 0xbf46e8ba2e8ba2e9),
503
        (0x3bdc6791d1cf399a, 0x3f31c4ec4ec4ec43),
504
        (0x3bbee0d9408a2e2a, 0xbf1c99999999914f),
505
        (0xbba1cea281e08012, 0x3f07a878787648e2),
506
        (0x3b70335101403d9d, 0xbef3fde50d0cb4b9),
507
        (0x3aff9c6b51787043, 0x3ee12ef3bf8a0a74),
508
    ];
509
510
    const CL: [u64; 6] = [
511
        0xbecdf3b9d1296ea9,
512
        0x3eba681d7d2298eb,
513
        0xbea77ead7b1ca449,
514
        0x3e94edd2ddb3721f,
515
        0xbe81bf173531ee23,
516
        0x3e6613229230e255,
517
    ];
518
519
0
    let yw0 = f_fmla(x, f64::from_bits(CL[5]), f64::from_bits(CL[4]));
520
0
    let yw1 = f_fmla(x, yw0, f64::from_bits(CL[3]));
521
0
    let yw2 = f_fmla(x, yw1, f64::from_bits(CL[2]));
522
0
    let yw3 = f_fmla(x, yw2, f64::from_bits(CL[1]));
523
524
0
    let y2 = x * f_fmla(x, yw3, f64::from_bits(CL[0]));
525
0
    let mut y1 = lpoly_xd_generic(DoubleDouble::new(0., x), CH, y2);
526
0
    y1 = DoubleDouble::mult_f64(y1, x);
527
0
    let y0 = DoubleDouble::from_exact_add(1., y1.hi);
528
0
    let yl = y0.lo + y1.lo;
529
0
    let p = DoubleDouble::quick_mult(DoubleDouble::new(yl, y0.hi), DoubleDouble::new(sl, sh));
530
0
    p.to_f64()
531
0
}
532
533
/// Huperbolic acos
534
///
535
/// Max ULP 0.5
536
0
pub fn f_acosh(x: f64) -> f64 {
537
0
    let ix = x.to_bits();
538
0
    if ix >= 0x7ff0000000000000u64 {
539
0
        let aix = ix.wrapping_shl(1);
540
0
        if ix == 0x7ff0000000000000u64 || aix > (0x7ffu64 << 53) {
541
0
            return x + x;
542
0
        } // +inf or nan
543
544
0
        return f64::NAN;
545
0
    }
546
547
0
    if ix <= 0x3ff0000000000000u64 {
548
0
        if ix == 0x3ff0000000000000u64 {
549
0
            return 0.;
550
0
        }
551
0
        return f64::NAN;
552
0
    }
553
0
    let mut off: i32 = 0x3fe;
554
0
    let mut t = ix;
555
0
    let g = if ix < 0x3ff1e83e425aee63u64 {
556
0
        let z = x - 1.;
557
0
        let iz = (-0.25) / z;
558
0
        let zt = 2. * z;
559
0
        let sh = zt.sqrt();
560
0
        let sl = dd_fmla(sh, sh, -zt) * (sh * iz);
561
        const CL: [u64; 9] = [
562
            0xbfb5555555555555,
563
            0x3f93333333332f95,
564
            0xbf76db6db6d5534c,
565
            0x3f5f1c71c1e04356,
566
            0xbf46e8b8e3e40d58,
567
            0x3f31c4ba825ac4fe,
568
            0xbf1c9045534e6d9e,
569
            0x3f071fedae26a76b,
570
            0xbeef1f4f8cc65342,
571
        ];
572
0
        let z2 = z * z;
573
0
        let z4 = z2 * z2;
574
575
0
        let ds0 = f_fmla(z, f64::from_bits(CL[8]), f64::from_bits(CL[7]));
576
0
        let ds1 = f_fmla(z, f64::from_bits(CL[6]), f64::from_bits(CL[5]));
577
0
        let ds2 = f_fmla(z, f64::from_bits(CL[4]), f64::from_bits(CL[3]));
578
0
        let ds3 = f_fmla(z, f64::from_bits(CL[2]), f64::from_bits(CL[1]));
579
580
0
        let dsw0 = f_fmla(z2, ds0, ds1);
581
0
        let dsw1 = f_fmla(z2, ds2, ds3);
582
0
        let dsw2 = f_fmla(z4, dsw0, dsw1);
583
584
0
        let mut ds = (sh * z) * f_fmla(z, dsw2, f64::from_bits(CL[0]));
585
586
0
        let eps = ds * f64::from_bits(0x3ccfc00000000000) - f64::from_bits(0x3970000000000000) * sh;
587
0
        ds += sl;
588
0
        let lb = sh + (ds - eps);
589
0
        let ub = sh + (ds + eps);
590
0
        if lb == ub {
591
0
            return lb;
592
0
        }
593
0
        return as_acosh_one(z, sh, sl);
594
0
    } else if ix < 0x405bf00000000000u64 {
595
0
        off = 0x3ff;
596
0
        let x2h = x * x;
597
0
        let wh = x2h - 1.;
598
0
        let wl = dd_fmla(x, x, -x2h);
599
0
        let sh = wh.sqrt();
600
0
        let ish = 0.5 / wh;
601
0
        let sl = (wl - dd_fmla(sh, sh, -wh)) * (sh * ish);
602
0
        let mut pt = DoubleDouble::from_exact_add(x, sh);
603
0
        pt.lo += sl;
604
0
        t = pt.hi.to_bits();
605
0
        pt.lo / pt.hi
606
0
    } else if ix < 0x4087100000000000u64 {
607
        const CL: [u64; 4] = [
608
            0x3bd5c4b6148816e2,
609
            0xbfd000000000005c,
610
            0xbfb7fffffebf3e6c,
611
            0xbfaaab6691f2bae7,
612
        ];
613
0
        let z = 1. / (x * x);
614
0
        let zw0 = f_fmla(z, f64::from_bits(CL[3]), f64::from_bits(CL[2]));
615
0
        let zw1 = f_fmla(z, zw0, f64::from_bits(CL[1]));
616
0
        f_fmla(z, zw1, f64::from_bits(CL[0]))
617
0
    } else if ix < 0x40e0100000000000u64 {
618
        const CL: [u64; 3] = [0xbbc7f77c8429c6c6, 0xbfcffffffffff214, 0xbfb8000268641bfe];
619
0
        let z = 1. / (x * x);
620
0
        let zw0 = f_fmla(z, f64::from_bits(CL[2]), f64::from_bits(CL[1]));
621
0
        f_fmla(z, zw0, f64::from_bits(CL[0]))
622
0
    } else if ix < 0x41ea000000000000u64 {
623
        const CL: [u64; 2] = [0x3bc7a0ed2effdd10, 0xbfd000000017d048];
624
0
        let z = 1. / (x * x);
625
0
        f_fmla(z, f64::from_bits(CL[1]), f64::from_bits(CL[0]))
626
    } else {
627
0
        0.
628
    };
629
0
    let ex: i32 = (t >> 52) as i32;
630
0
    let e = ex - off;
631
0
    t &= 0x000fffffffffffff;
632
0
    let ed = e;
633
0
    let i: u64 = t >> (52 - 5);
634
0
    let d: i64 = (t & 0x00007fffffffffff) as i64;
635
0
    let b_i = ACOSH_ASINH_B[i as usize];
636
0
    let j: u64 = t
637
0
        .wrapping_add((b_i[0] as u64).wrapping_shl(33))
638
0
        .wrapping_add((b_i[1] as i64).wrapping_mul(d >> 16) as u64)
639
0
        >> (52 - 10);
640
0
    t |= 0x3ffu64 << 52;
641
0
    let i1: i32 = (j >> 5) as i32;
642
0
    let i2 = j & 0x1f;
643
0
    let r =
644
0
        f64::from_bits(ACOSH_ASINH_R1[i1 as usize]) * f64::from_bits(ACOSH_ASINH_R2[i2 as usize]);
645
0
    let dx = dd_fmla(r, f64::from_bits(t), -1.);
646
0
    let dx2 = dx * dx;
647
648
    const C: [u64; 5] = [
649
        0xbfe0000000000000,
650
        0x3fd5555555555530,
651
        0xbfcfffffffffffa0,
652
        0x3fc99999e33a6366,
653
        0xbfc555559ef9525f,
654
    ];
655
656
0
    let fw0 = f_fmla(dx, f64::from_bits(C[3]), f64::from_bits(C[2]));
657
0
    let fw1 = f_fmla(dx, f64::from_bits(C[1]), f64::from_bits(C[0]));
658
0
    let fw2 = f_fmla(dx2, f64::from_bits(C[4]), fw0);
659
660
0
    let f = dx2 * f_fmla(dx2, fw2, fw1);
661
    const L2H: f64 = f64::from_bits(0x3fe62e42fefa3800);
662
    const L2L: f64 = f64::from_bits(0x3d2ef35793c76730);
663
0
    let l1r = ACOSH_ASINH_L1[i1 as usize];
664
0
    let l2r = ACOSH_ASINH_L2[i2 as usize];
665
0
    let lh = f_fmla(
666
        L2H,
667
0
        ed as f64,
668
0
        f64::from_bits(l1r.1) + f64::from_bits(l2r.1),
669
    );
670
0
    let mut ll = f_fmla(L2L, ed as f64, dx);
671
0
    ll += g;
672
0
    ll += f64::from_bits(l1r.0) + f64::from_bits(l2r.0);
673
0
    ll += f;
674
0
    let eps = 2.8e-19;
675
0
    let lb = lh + (ll - eps);
676
0
    let ub = lh + (ll + eps);
677
0
    if lb == ub {
678
0
        return lb;
679
0
    }
680
0
    acosh_refine(x, f64::from_bits(0x3ff71547652b82fe) * lb)
681
0
}
682
683
#[cfg(test)]
684
mod tests {
685
    use super::*;
686
687
    #[test]
688
    fn test() {
689
        assert_eq!(f_acosh(1.52), 0.9801016289951905);
690
        assert_eq!(f_acosh(1.86), 1.2320677765479648);
691
        assert_eq!(f_acosh(4.52), 2.189191592518765);
692
    }
693
}