Coverage Report

Created: 2025-10-14 06:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/pxfm-0.1.25/src/logs/log2.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::{f_fmla, min_normal_f64};
30
use crate::double_double::DoubleDouble;
31
use crate::logs::log2dd::log2_dd;
32
use crate::logs::log2td::log2_td;
33
use crate::polyeval::f_polyeval6;
34
35
pub(crate) static LOG_RANGE_REDUCTION: [u64; 128] = [
36
    0x3ff0000000000000,
37
    0x3fefc00000000000,
38
    0x3fef800000000000,
39
    0x3fef400000000000,
40
    0x3fef000000000000,
41
    0x3feec00000000000,
42
    0x3fee800000000000,
43
    0x3fee400000000000,
44
    0x3fee000000000000,
45
    0x3fede00000000000,
46
    0x3feda00000000000,
47
    0x3fed600000000000,
48
    0x3fed400000000000,
49
    0x3fed000000000000,
50
    0x3fecc00000000000,
51
    0x3feca00000000000,
52
    0x3fec600000000000,
53
    0x3fec400000000000,
54
    0x3fec000000000000,
55
    0x3febe00000000000,
56
    0x3feba00000000000,
57
    0x3feb800000000000,
58
    0x3feb400000000000,
59
    0x3feb200000000000,
60
    0x3feae00000000000,
61
    0x3feac00000000000,
62
    0x3fea800000000000,
63
    0x3fea600000000000,
64
    0x3fea400000000000,
65
    0x3fea000000000000,
66
    0x3fe9e00000000000,
67
    0x3fe9c00000000000,
68
    0x3fe9800000000000,
69
    0x3fe9600000000000,
70
    0x3fe9400000000000,
71
    0x3fe9200000000000,
72
    0x3fe9000000000000,
73
    0x3fe8c00000000000,
74
    0x3fe8a00000000000,
75
    0x3fe8800000000000,
76
    0x3fe8600000000000,
77
    0x3fe8400000000000,
78
    0x3fe8000000000000,
79
    0x3fe7e00000000000,
80
    0x3fe7c00000000000,
81
    0x3fe7a00000000000,
82
    0x3fe7800000000000,
83
    0x3fe7600000000000,
84
    0x3fe7400000000000,
85
    0x3fe7200000000000,
86
    0x3fe7000000000000,
87
    0x3fe6e00000000000,
88
    0x3fe6c00000000000,
89
    0x3fe6a00000000000,
90
    0x3fe6800000000000,
91
    0x3fe6600000000000,
92
    0x3fe6400000000000,
93
    0x3fe6200000000000,
94
    0x3fe6000000000000,
95
    0x3fe5e00000000000,
96
    0x3fe5c00000000000,
97
    0x3fe5a00000000000,
98
    0x3fe5800000000000,
99
    0x3fe5600000000000,
100
    0x3fe5400000000000,
101
    0x3fe5400000000000,
102
    0x3fe5200000000000,
103
    0x3fe5000000000000,
104
    0x3fe4e00000000000,
105
    0x3fe4c00000000000,
106
    0x3fe4a00000000000,
107
    0x3fe4a00000000000,
108
    0x3fe4800000000000,
109
    0x3fe4600000000000,
110
    0x3fe4400000000000,
111
    0x3fe4200000000000,
112
    0x3fe4000000000000,
113
    0x3fe4000000000000,
114
    0x3fe3e00000000000,
115
    0x3fe3c00000000000,
116
    0x3fe3a00000000000,
117
    0x3fe3a00000000000,
118
    0x3fe3800000000000,
119
    0x3fe3600000000000,
120
    0x3fe3400000000000,
121
    0x3fe3400000000000,
122
    0x3fe3200000000000,
123
    0x3fe3000000000000,
124
    0x3fe3000000000000,
125
    0x3fe2e00000000000,
126
    0x3fe2c00000000000,
127
    0x3fe2c00000000000,
128
    0x3fe2a00000000000,
129
    0x3fe2800000000000,
130
    0x3fe2800000000000,
131
    0x3fe2600000000000,
132
    0x3fe2400000000000,
133
    0x3fe2400000000000,
134
    0x3fe2200000000000,
135
    0x3fe2000000000000,
136
    0x3fe2000000000000,
137
    0x3fe1e00000000000,
138
    0x3fe1c00000000000,
139
    0x3fe1c00000000000,
140
    0x3fe1a00000000000,
141
    0x3fe1a00000000000,
142
    0x3fe1800000000000,
143
    0x3fe1600000000000,
144
    0x3fe1600000000000,
145
    0x3fe1400000000000,
146
    0x3fe1400000000000,
147
    0x3fe1200000000000,
148
    0x3fe1000000000000,
149
    0x3fe1000000000000,
150
    0x3fe0e00000000000,
151
    0x3fe0e00000000000,
152
    0x3fe0c00000000000,
153
    0x3fe0c00000000000,
154
    0x3fe0a00000000000,
155
    0x3fe0a00000000000,
156
    0x3fe0800000000000,
157
    0x3fe0800000000000,
158
    0x3fe0600000000000,
159
    0x3fe0600000000000,
160
    0x3fe0400000000000,
161
    0x3fe0400000000000,
162
    0x3fe0200000000000,
163
    0x3fe0000000000000,
164
];
165
166
/**
167
Generated by SageMath:
168
```python
169
values = LOG_RANGE_REDUCTION
170
171
R = RealField(150)
172
173
def hex_to_float(h):
174
    return struct.unpack('>d', struct.pack('>Q', h))[0]
175
176
real_array = [R(hex_to_float(h)) for h in values]
177
178
for r in real_array:
179
    print_double_double("", -RealField(180)(r).log2())
180
```
181
**/
182
static LOG2_DD: [(u64, u64); 128] = [
183
    (0x0, 0x0),
184
    (0x3c26d746128b1857, 0x3f872c7ba20f7327),
185
    (0x3c2b2a41b08fbe06, 0x3f9743ee861f3556),
186
    (0x3c3491f06c085bc2, 0x3fa184b8e4c56af8),
187
    (0x3c477970e03f821c, 0x3fa77394c9d958d5),
188
    (0x3c0155660710eb2a, 0x3fad6ebd1f1febfe),
189
    (0x3c298c5452bbce74, 0x3fb1bb32a600549d),
190
    (0x3c2c141e66faaaad, 0x3fb4c560fe68af88),
191
    (0x3c59ced1447e30ad, 0x3fb7d60496cfbb4c),
192
    (0xbc321ba488a62577, 0x3fb960caf9abb7ca),
193
    (0xbc17936311889913, 0x3fbc7b528b70f1c5),
194
    (0xbc36cd4d2ae3a2f6, 0x3fbf9c95dc1d1165),
195
    (0x3c55d243efd93259, 0x3fc097e38ce60649),
196
    (0xbc5696e2866c718e, 0x3fc22dadc2ab3497),
197
    (0xbc67a6ed4e1b0936, 0x3fc3c6fb650cde51),
198
    (0xbc61562d61af73f8, 0x3fc494f863b8df35),
199
    (0x3c354fae008fbb59, 0x3fc633a8bf437ce1),
200
    (0xbc60798d1aa21694, 0x3fc7046031c79f85),
201
    (0x3c699aa6df8b7d83, 0x3fc8a8980abfbd32),
202
    (0xbc6e95734abd2fcc, 0x3fc97c1cb13c7ec1),
203
    (0xbc6cc865b3dd0dbb, 0x3fcb2602497d5346),
204
    (0x3c2bc0af7b82e7d7, 0x3fcbfc67a7fff4cc),
205
    (0xbc0ba8b1f646ab12, 0x3fcdac22d3e441d3),
206
    (0xbc6086fce864a1f6, 0x3fce857d3d361368),
207
    (0x3c7768994400ca0a, 0x3fd01d9bbcfa61d4),
208
    (0xbc53d56efe4338fe, 0x3fd08bce0d95fa38),
209
    (0x3c7c8d43e017579b, 0x3fd169c05363f158),
210
    (0x3c6ae9804237ec8e, 0x3fd1d982c9d52708),
211
    (0x3c734107c0e54aed, 0x3fd249cd2b13cd6c),
212
    (0x3c7968925e378d68, 0x3fd32bfee370ee68),
213
    (0x3c7fcad2f4710e00, 0x3fd39de8e1559f6f),
214
    (0xbc7c658d602e66b0, 0x3fd4106017c3eca3),
215
    (0x3c7e393a16b94b52, 0x3fd4f6fbb2cec598),
216
    (0xbc78d86531d55da2, 0x3fd56b22e6b578e5),
217
    (0x3c710b5b643a6ecb, 0x3fd5dfdcf1eeae0e),
218
    (0x3c7ac9080333c605, 0x3fd6552b49986277),
219
    (0x3c2b6d40900b2502, 0x3fd6cb0f6865c8ea),
220
    (0x3c68f89e2eb553b2, 0x3fd7b89f02cf2aad),
221
    (0x3c651d58525aad39, 0x3fd8304d90c11fd3),
222
    (0x3c799aa6df8b7d83, 0x3fd8a8980abfbd32),
223
    (0x3c7fdc46af571993, 0x3fd921800924dd3b),
224
    (0x3c7bca36fd02def0, 0x3fd99b072a96c6b2),
225
    (0x3c5817fd3b7d7e5d, 0x3fda8ff971810a5e),
226
    (0xbc45e13b838eba7d, 0x3fdb0b67f4f46810),
227
    (0xbc501d98c3531027, 0x3fdb877c57b1b070),
228
    (0x3c7edf515c63dd87, 0x3fdc043859e2fdb3),
229
    (0x3c6c4aec56233279, 0x3fdc819dc2d45fe4),
230
    (0x3c78a38b4175d665, 0x3fdcffae611ad12b),
231
    (0xbc6e15a52a31604a, 0x3fdd7e6c0abc3579),
232
    (0x3c438c8946414c6a, 0x3fddfdd89d586e2b),
233
    (0x3c73bed456b24ed1, 0x3fde7df5fe538ab3),
234
    (0x3c76d261f1753e0b, 0x3fdefec61b011f85),
235
    (0xbc79ca1a3202b3d7, 0x3fdf804ae8d0cd02),
236
    (0xbc87398fe685f171, 0x3fe0014332be0033),
237
    (0xbc89c32630008a1f, 0x3fe042bd4b9a7c99),
238
    (0xbc7f47806a0e4105, 0x3fe08494c66b8ef0),
239
    (0xbc48a33c25e8e226, 0x3fe0c6caaf0c5597),
240
    (0xbc73aec658457c41, 0x3fe1096015dee4da),
241
    (0xbc8fc7d7c3320aab, 0x3fe14c560fe68af9),
242
    (0xbc892ba145dcf40b, 0x3fe18fadb6e2d3c2),
243
    (0xbc7f9fb952bbbccc, 0x3fe1d368296b5255),
244
    (0xbc8568859c64022e, 0x3fe217868b0c37e8),
245
    (0xbc84828ddf1fb145, 0x3fe25c0a0463beb0),
246
    (0xbc8c348e4aab18b8, 0x3fe2a0f3c340705c),
247
    (0xbc83af881af2f3d9, 0x3fe2e644fac04fd8),
248
    (0xbc83af881af2f3d9, 0x3fe2e644fac04fd8),
249
    (0x3c8968925e378d68, 0x3fe32bfee370ee68),
250
    (0xbc869656a0ad70d4, 0x3fe37222bb70747c),
251
    (0x3c76d266d6cdc959, 0x3fe3b8b1c68fa6ed),
252
    (0xbc69575b04fa6fbd, 0x3fe3ffad4e74f1d6),
253
    (0x3c5b90132aeddb58, 0x3fe44716a2c08262),
254
    (0x3c5b90132aeddb58, 0x3fe44716a2c08262),
255
    (0xbc75e35482d13dc1, 0x3fe48eef19317991),
256
    (0xbc8ca44f1db913d3, 0x3fe4d7380dcc422d),
257
    (0x3c7817fd3b7d7e5d, 0x3fe51ff2e30214bc),
258
    (0x3c804613e33c06c9, 0x3fe5692101d9b4a6),
259
    (0xbc8fc9257edfe9b6, 0x3fe5b2c3da19723b),
260
    (0xbc8fc9257edfe9b6, 0x3fe5b2c3da19723b),
261
    (0x3c8149a1977b5b99, 0x3fe5fcdce2727ddb),
262
    (0xbc8b32266d92c0fe, 0x3fe6476d98ad990a),
263
    (0x3c821d90b84e7218, 0x3fe6927781d932a8),
264
    (0x3c821d90b84e7218, 0x3fe6927781d932a8),
265
    (0x3c7f6e91ad16ecff, 0x3fe6ddfc2a78fc63),
266
    (0xbc74a31ce1b7e328, 0x3fe729fd26b707c8),
267
    (0x3c6a7b47d2c352d9, 0x3fe7767c12967a45),
268
    (0x3c6a7b47d2c352d9, 0x3fe7767c12967a45),
269
    (0x3c821f9cb2cc5575, 0x3fe7c37a9227e7fb),
270
    (0x3c8dc572667587b1, 0x3fe810fa51bf65fd),
271
    (0x3c8dc572667587b1, 0x3fe810fa51bf65fd),
272
    (0xbc78f93e7aa3bdf8, 0x3fe85efd062c656d),
273
    (0x3c5b85a54d7ee2fd, 0x3fe8ad846cf369a4),
274
    (0x3c5b85a54d7ee2fd, 0x3fe8ad846cf369a4),
275
    (0x3c8bf1d926766301, 0x3fe8fc924c89ac84),
276
    (0x3c401ee1343fe7ca, 0x3fe94c287492c4db),
277
    (0x3c401ee1343fe7ca, 0x3fe94c287492c4db),
278
    (0x3c7fa0a62e6add1b, 0x3fe99c48be2063c8),
279
    (0x3c8022ddb71189c5, 0x3fe9ecf50bf43f13),
280
    (0x3c8022ddb71189c5, 0x3fe9ecf50bf43f13),
281
    (0x3c7ac7fc60a51031, 0x3fea3e2f4ac43f60),
282
    (0x3c6817fd3b7d7e5d, 0x3fea8ff971810a5e),
283
    (0x3c6817fd3b7d7e5d, 0x3fea8ff971810a5e),
284
    (0xbc83138e941643f7, 0x3feae255819f022d),
285
    (0x3c8e0ae0d3f8a58b, 0x3feb35458761d479),
286
    (0x3c8e0ae0d3f8a58b, 0x3feb35458761d479),
287
    (0x3c742b7579f0f8d4, 0x3feb88cb9a2ab521),
288
    (0x3c742b7579f0f8d4, 0x3feb88cb9a2ab521),
289
    (0x3c6a7610e40bd6ab, 0x3febdce9dcc96187),
290
    (0xbc80e5edaecee150, 0x3fec31a27dd00b4a),
291
    (0xbc80e5edaecee150, 0x3fec31a27dd00b4a),
292
    (0xbc831d962d3728cc, 0x3fec86f7b7ea4a89),
293
    (0xbc831d962d3728cc, 0x3fec86f7b7ea4a89),
294
    (0xbc857391924a6d9d, 0x3fecdcebd2373995),
295
    (0x3c78333ac7d9ebbb, 0x3fed338120a6dd9d),
296
    (0x3c78333ac7d9ebbb, 0x3fed338120a6dd9d),
297
    (0xbc86c0268890da53, 0x3fed8aba045b01c8),
298
    (0xbc86c0268890da53, 0x3fed8aba045b01c8),
299
    (0xbc859e7ba5d5ccc9, 0x3fede298ec0bac0d),
300
    (0xbc859e7ba5d5ccc9, 0x3fede298ec0bac0d),
301
    (0x3c60b07079619c47, 0x3fee3b20546f554a),
302
    (0x3c60b07079619c47, 0x3fee3b20546f554a),
303
    (0xbc8cc4d81bc25adf, 0x3fee9452c8a71028),
304
    (0xbc8cc4d81bc25adf, 0x3fee9452c8a71028),
305
    (0xbc776c0a2827d49a, 0x3feeee32e2aeccbf),
306
    (0xbc776c0a2827d49a, 0x3feeee32e2aeccbf),
307
    (0xbc8314dc4fc42302, 0x3fef48c34bd1e96f),
308
    (0xbc8314dc4fc42302, 0x3fef48c34bd1e96f),
309
    (0xbc817f8e37b00179, 0x3fefa406bd2443df),
310
    (0x0, 0x0),
311
];
312
313
#[cfg(not(any(
314
    all(
315
        any(target_arch = "x86", target_arch = "x86_64"),
316
        target_feature = "fma"
317
    ),
318
    target_arch = "aarch64"
319
)))]
320
pub(crate) static LOG_CD: [u64; 128] = [
321
    0x0000000000000000,
322
    0xbf10000000000000,
323
    0xbf30000000000000,
324
    0xbf42000000000000,
325
    0xbf50000000000000,
326
    0xbf59000000000000,
327
    0xbf62000000000000,
328
    0xbf68800000000000,
329
    0xbf70000000000000,
330
    0xbf49000000000000,
331
    0xbf5f000000000000,
332
    0xbf69c00000000000,
333
    0xbf30000000000000,
334
    0xbf5c000000000000,
335
    0xbf6b000000000000,
336
    0xbf45000000000000,
337
    0xbf64000000000000,
338
    0x3f10000000000000,
339
    0xbf60000000000000,
340
    0x3f3a000000000000,
341
    0xbf5e000000000000,
342
    0x3f38000000000000,
343
    0xbf61000000000000,
344
    0xbf00000000000000,
345
    0xbf66000000000000,
346
    0xbf4a000000000000,
347
    0xbf6e000000000000,
348
    0xbf5f800000000000,
349
    0xbf30000000000000,
350
    0xbf6c000000000000,
351
    0xbf5f000000000000,
352
    0xbf3c000000000000,
353
    0xbf70000000000000,
354
    0xbf65400000000000,
355
    0xbf56000000000000,
356
    0xbf24000000000000,
357
    0x3f50000000000000,
358
    0xbf68800000000000,
359
    0xbf60800000000000,
360
    0xbf52000000000000,
361
    0xbf30000000000000,
362
    0x3f42000000000000,
363
    0xbf70000000000000,
364
    0xbf6ac00000000000,
365
    0xbf66000000000000,
366
    0xbf61c00000000000,
367
    0xbf5c000000000000,
368
    0xbf55800000000000,
369
    0xbf50000000000000,
370
    0xbf47000000000000,
371
    0xbf40000000000000,
372
    0xbf36000000000000,
373
    0xbf30000000000000,
374
    0xbf2c000000000000,
375
    0xbf30000000000000,
376
    0xbf36000000000000,
377
    0xbf40000000000000,
378
    0xbf47000000000000,
379
    0xbf50000000000000,
380
    0xbf55800000000000,
381
    0xbf5c000000000000,
382
    0xbf61c00000000000,
383
    0xbf66000000000000,
384
    0xbf6ac00000000000,
385
    0xbf70000000000000,
386
    0x3f55000000000000,
387
    0x3f42000000000000,
388
    0xbf30000000000000,
389
    0xbf52000000000000,
390
    0xbf60800000000000,
391
    0xbf68800000000000,
392
    0x3f60c00000000000,
393
    0x3f50000000000000,
394
    0xbf24000000000000,
395
    0xbf56000000000000,
396
    0xbf65400000000000,
397
    0xbf70000000000000,
398
    0x3f50000000000000,
399
    0xbf3c000000000000,
400
    0xbf5f000000000000,
401
    0xbf6c000000000000,
402
    0x3f56800000000000,
403
    0xbf30000000000000,
404
    0xbf5f800000000000,
405
    0xbf6e000000000000,
406
    0x3f51000000000000,
407
    0xbf4a000000000000,
408
    0xbf66000000000000,
409
    0x3f60000000000000,
410
    0xbf00000000000000,
411
    0xbf61000000000000,
412
    0x3f64800000000000,
413
    0x3f38000000000000,
414
    0xbf5e000000000000,
415
    0x3f66000000000000,
416
    0x3f3a000000000000,
417
    0xbf60000000000000,
418
    0x3f64800000000000,
419
    0x3f10000000000000,
420
    0xbf64000000000000,
421
    0x3f60000000000000,
422
    0xbf45000000000000,
423
    0xbf6b000000000000,
424
    0x3f51000000000000,
425
    0xbf5c000000000000,
426
    0x3f65400000000000,
427
    0xbf30000000000000,
428
    0xbf69c00000000000,
429
    0x3f52000000000000,
430
    0xbf5f000000000000,
431
    0x3f63000000000000,
432
    0xbf49000000000000,
433
    0xbf70000000000000,
434
    0x3f30000000000000,
435
    0xbf68800000000000,
436
    0x3f52800000000000,
437
    0xbf62000000000000,
438
    0x3f5f000000000000,
439
    0xbf59000000000000,
440
    0x3f64c00000000000,
441
    0xbf50000000000000,
442
    0x3f69000000000000,
443
    0xbf42000000000000,
444
    0x3f6c400000000000,
445
    0xbf30000000000000,
446
    0x3f6e800000000000,
447
    0xbf10000000000000,
448
    0xbf70000000000000,
449
];
450
451
pub(crate) const LOG_COEFFS: [u64; 6] = [
452
    0xbfdfffffffffffff,
453
    0x3fd5555555554a9b,
454
    0xbfd0000000094567,
455
    0x3fc99999dcc9823c,
456
    0xbfc55550ac2e537a,
457
    0x3fc21a02c4e624d7,
458
];
459
460
/// Log2(x)
461
///
462
/// Max found ULP 0.5
463
0
pub fn f_log2(x: f64) -> f64 {
464
0
    let mut x_u = x.to_bits();
465
466
    const E_BIAS: u64 = (1u64 << (11 - 1u64)) - 1u64;
467
468
0
    let mut x_e: i64 = -(E_BIAS as i64);
469
470
    const MAX_NORMAL: u64 = f64::to_bits(f64::MAX);
471
472
0
    if x_u == 1f64.to_bits() {
473
        // log2(1.0) = +0.0
474
0
        return 0.0;
475
0
    }
476
0
    if x_u < min_normal_f64().to_bits() || x_u > MAX_NORMAL {
477
0
        if x == 0.0 {
478
0
            return f64::NEG_INFINITY;
479
0
        }
480
0
        if x < 0. || x.is_nan() {
481
0
            return f64::NAN;
482
0
        }
483
0
        if x.is_infinite() || x.is_nan() {
484
0
            return x + x;
485
0
        }
486
        // Normalize denormal inputs.
487
0
        x_u = (x * f64::from_bits(0x4330000000000000)).to_bits();
488
0
        x_e -= 52;
489
0
    }
490
491
    // log2(x) = log2(2^x_e * x_m)
492
    //         = x_e + log2(x_m)
493
    // Range reduction for log2(x_m):
494
    // For each x_m, we would like to find r such that:
495
    //   -2^-8 <= r * x_m - 1 < 2^-7
496
0
    let shifted = (x_u >> 45) as i64;
497
0
    let index = shifted & 0x7F;
498
499
    // Add unbiased exponent. Add an extra 1 if the 8 leading fractional bits are
500
    // all 1's.
501
0
    x_e = x_e.wrapping_add(x_u.wrapping_add(1u64 << 45).wrapping_shr(52) as i64);
502
0
    let e_x = x_e as f64;
503
504
    // Set m = 1.mantissa.
505
0
    let x_m = (x_u & 0x000F_FFFF_FFFF_FFFFu64) | 0x3FF0_0000_0000_0000u64;
506
0
    let m = f64::from_bits(x_m);
507
508
    let u;
509
510
0
    let r = f64::from_bits(LOG_RANGE_REDUCTION[index as usize]);
511
512
    #[cfg(any(
513
        all(
514
            any(target_arch = "x86", target_arch = "x86_64"),
515
            target_feature = "fma"
516
        ),
517
        target_arch = "aarch64"
518
    ))]
519
    {
520
        u = f_fmla(r, m, -1.0); // exact   
521
    }
522
    #[cfg(not(any(
523
        all(
524
            any(target_arch = "x86", target_arch = "x86_64"),
525
            target_feature = "fma"
526
        ),
527
        target_arch = "aarch64"
528
    )))]
529
0
    {
530
0
        let c_m = x_m & 0x3FFF_E000_0000_0000u64;
531
0
        let c = f64::from_bits(c_m);
532
0
        u = f_fmla(r, m - c, f64::from_bits(LOG_CD[index as usize])); // exact
533
0
    }
534
535
    // Exact sum:
536
0
    let log_vals = DoubleDouble::from_bit_pair(LOG2_DD[index as usize]);
537
538
    /*
539
       Poly generated in Sollya;
540
       d = [-2^-8, 2^-7];
541
       f = (log2(1 + x))/x;
542
       pf = fpminimax(f, 5, [|D...|], [-2^-8, 2^-7]);
543
544
       See ./notes/log2.sollya
545
    */
546
    const C: [u64; 6] = [
547
        0x3ff71547652b82fe,
548
        0xbfe71547652b7a07,
549
        0x3fdec709dc458db1,
550
        0xbfd715479c2266c9,
551
        0x3fd2776ae1ddf8f0,
552
        0xbfce7b2178870157,
553
    ];
554
555
    // Degree-7 minimax polynomial
556
0
    let p = f_fmla(
557
0
        f_polyeval6(
558
0
            u,
559
0
            f64::from_bits(C[0]),
560
0
            f64::from_bits(C[1]),
561
0
            f64::from_bits(C[2]),
562
0
            f64::from_bits(C[3]),
563
0
            f64::from_bits(C[4]),
564
0
            f64::from_bits(C[5]),
565
        ),
566
0
        u,
567
0
        log_vals.lo,
568
    );
569
570
    // log2(x) = e + log2(r) + log2(index)
571
572
0
    let rr = DoubleDouble::from_full_exact_add(log_vals.hi, e_x);
573
0
    let r3 = DoubleDouble::add_f64(rr, p);
574
575
0
    let err = f_fmla(
576
0
        r3.hi,
577
0
        f64::from_bits(0x3bf0000000000000), // 2^-64
578
0
        f64::from_bits(0x3c60000000000000), // 2^-57
579
    );
580
581
    // Lower bound from the result
582
0
    let left = r3.hi + (r3.lo - err);
583
    // Upper bound from the result
584
0
    let right = r3.hi + (r3.lo + err);
585
586
    // Ziv's test if fast pass is accurate enough.
587
0
    if left == right {
588
0
        return left;
589
0
    }
590
591
0
    log2_hard(x)
592
0
}
593
594
#[cold]
595
#[inline(never)]
596
0
fn log2_hard(x: f64) -> f64 {
597
0
    let r = log2_dd(x);
598
0
    let err = f_fmla(
599
0
        r.hi,
600
0
        f64::from_bits(0x3b50000000000000), // 2^-74
601
0
        f64::from_bits(0x3990000000000000), // 2^-102
602
    );
603
0
    let ub = r.hi + (r.lo + err);
604
0
    let lb = r.hi + (r.lo - err);
605
0
    if ub == lb {
606
0
        return r.to_f64();
607
0
    }
608
0
    log2_hard_slow(x)
609
0
}
610
611
#[cold]
612
#[inline(never)]
613
0
fn log2_hard_slow(x: f64) -> f64 {
614
0
    log2_td(x).to_f64()
615
0
}
616
617
#[cfg(test)]
618
mod tests {
619
    use super::*;
620
621
    #[test]
622
    fn test_log2d() {
623
        assert_eq!(f_log2(0.7500000000000461), -0.4150374992787552);
624
        assert_eq!(f_log2(1.99999999779061), 0.999999998406262);
625
        assert_eq!(f_log2(0.7812499981882864), -0.35614381357087554);
626
        assert_eq!(f_log2(0.5937499997089616), -0.7520724872635803);
627
        assert_eq!(f_log2(0.9983015060407214), -0.0024524921736992287);
628
        assert_eq!(f_log2(0.2284926469437778), -2.129780355811612);
629
        assert_eq!(f_log2(24.), 4.584962500721156181453738943);
630
        assert!((f_log2(0.35) - 0.35f64.log2()).abs() < 1e-8);
631
        assert!((f_log2(0.9) - 0.9f64.log2()).abs() < 1e-8);
632
        assert_eq!(f_log2(0.), f64::NEG_INFINITY);
633
        assert!(f_log2(-1.).is_nan());
634
        assert!(f_log2(f64::NAN).is_nan());
635
        assert!(f_log2(f64::NEG_INFINITY).is_nan());
636
        assert_eq!(f_log2(f64::INFINITY), f64::INFINITY);
637
    }
638
639
    #[test]
640
    fn test_log2_control_values() {
641
        assert_eq!(
642
            f_log2(f64::from_bits(0x3ff1406d79e1b574)),
643
            0.10866415915666149
644
        );
645
        assert_eq!(
646
            f_log2(f64::from_bits(0x3ffb4ebe40c95a01)),
647
            0.7712301192941611
648
        );
649
        assert_eq!(
650
            f_log2(f64::from_bits(0x3ff0b541b6746bd1)),
651
            0.062470074690080965
652
        );
653
        assert_eq!(
654
            f_log2(f64::from_bits(0x3ff68d778f076021)),
655
            0.4952222169409832
656
        );
657
        assert_eq!(
658
            f_log2(f64::from_bits(0x3ff67eaf07ce24d1)),
659
            0.4915233709893074
660
        );
661
        assert_eq!(
662
            f_log2(f64::from_bits(0x3ff0b53197bd66c8)),
663
            0.062448835548542664
664
        );
665
        assert_eq!(
666
            f_log2(f64::from_bits(0x3fe6b015f8d9a784)),
667
            -0.496152942566177
668
        );
669
        assert_eq!(
670
            f_log2(f64::from_bits(0x3ff160732376ad7f)),
671
            0.11908694357502585
672
        );
673
        assert_eq!(
674
            f_log2(f64::from_bits(0x3ff0b53f741fb8c4)),
675
            0.062467098188572705
676
        );
677
    }
678
}