/rust/registry/src/index.crates.io-6f17d22bba15001f/ryu-1.0.19/src/f2s_intrinsics.rs
Line | Count | Source (jump to first uncovered line) |
1 | | // Translated from C to Rust. The original C code can be found at |
2 | | // https://github.com/ulfjack/ryu and carries the following license: |
3 | | // |
4 | | // Copyright 2018 Ulf Adams |
5 | | // |
6 | | // The contents of this file may be used under the terms of the Apache License, |
7 | | // Version 2.0. |
8 | | // |
9 | | // (See accompanying file LICENSE-Apache or copy at |
10 | | // http://www.apache.org/licenses/LICENSE-2.0) |
11 | | // |
12 | | // Alternatively, the contents of this file may be used under the terms of |
13 | | // the Boost Software License, Version 1.0. |
14 | | // (See accompanying file LICENSE-Boost or copy at |
15 | | // https://www.boost.org/LICENSE_1_0.txt) |
16 | | // |
17 | | // Unless required by applicable law or agreed to in writing, this software |
18 | | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
19 | | // KIND, either express or implied. |
20 | | |
21 | | use crate::d2s; |
22 | | |
23 | | pub const FLOAT_POW5_INV_BITCOUNT: i32 = d2s::DOUBLE_POW5_INV_BITCOUNT - 64; |
24 | | pub const FLOAT_POW5_BITCOUNT: i32 = d2s::DOUBLE_POW5_BITCOUNT - 64; |
25 | | |
26 | | #[cfg_attr(feature = "no-panic", inline)] |
27 | 0 | fn pow5factor_32(mut value: u32) -> u32 { |
28 | 0 | let mut count = 0u32; |
29 | | loop { |
30 | 0 | debug_assert!(value != 0); |
31 | 0 | let q = value / 5; |
32 | 0 | let r = value % 5; |
33 | 0 | if r != 0 { |
34 | 0 | break; |
35 | 0 | } |
36 | 0 | value = q; |
37 | 0 | count += 1; |
38 | | } |
39 | 0 | count |
40 | 0 | } |
41 | | |
42 | | // Returns true if value is divisible by 5^p. |
43 | | #[cfg_attr(feature = "no-panic", inline)] |
44 | 0 | pub fn multiple_of_power_of_5_32(value: u32, p: u32) -> bool { |
45 | 0 | pow5factor_32(value) >= p |
46 | 0 | } |
47 | | |
48 | | // Returns true if value is divisible by 2^p. |
49 | | #[cfg_attr(feature = "no-panic", inline)] |
50 | 0 | pub fn multiple_of_power_of_2_32(value: u32, p: u32) -> bool { |
51 | 0 | // __builtin_ctz doesn't appear to be faster here. |
52 | 0 | (value & ((1u32 << p) - 1)) == 0 |
53 | 0 | } |
54 | | |
55 | | // It seems to be slightly faster to avoid uint128_t here, although the |
56 | | // generated code for uint128_t looks slightly nicer. |
57 | | #[cfg_attr(feature = "no-panic", inline)] |
58 | 0 | fn mul_shift_32(m: u32, factor: u64, shift: i32) -> u32 { |
59 | 0 | debug_assert!(shift > 32); |
60 | | |
61 | | // The casts here help MSVC to avoid calls to the __allmul library |
62 | | // function. |
63 | 0 | let factor_lo = factor as u32; |
64 | 0 | let factor_hi = (factor >> 32) as u32; |
65 | 0 | let bits0 = m as u64 * factor_lo as u64; |
66 | 0 | let bits1 = m as u64 * factor_hi as u64; |
67 | 0 |
|
68 | 0 | let sum = (bits0 >> 32) + bits1; |
69 | 0 | let shifted_sum = sum >> (shift - 32); |
70 | 0 | debug_assert!(shifted_sum <= u32::max_value() as u64); |
71 | 0 | shifted_sum as u32 |
72 | 0 | } |
73 | | |
74 | | #[cfg_attr(feature = "no-panic", inline)] |
75 | 0 | pub fn mul_pow5_inv_div_pow2(m: u32, q: u32, j: i32) -> u32 { |
76 | 0 | #[cfg(feature = "small")] |
77 | 0 | { |
78 | 0 | // The inverse multipliers are defined as [2^x / 5^y] + 1; the upper 64 |
79 | 0 | // bits from the double lookup table are the correct bits for [2^x / |
80 | 0 | // 5^y], so we have to add 1 here. Note that we rely on the fact that |
81 | 0 | // the added 1 that's already stored in the table never overflows into |
82 | 0 | // the upper 64 bits. |
83 | 0 | let pow5 = unsafe { d2s::compute_inv_pow5(q) }; |
84 | 0 | mul_shift_32(m, pow5.1 + 1, j) |
85 | 0 | } |
86 | 0 |
|
87 | 0 | #[cfg(not(feature = "small"))] |
88 | 0 | { |
89 | 0 | debug_assert!(q < d2s::DOUBLE_POW5_INV_SPLIT.len() as u32); |
90 | | unsafe { |
91 | 0 | mul_shift_32( |
92 | 0 | m, |
93 | 0 | d2s::DOUBLE_POW5_INV_SPLIT.get_unchecked(q as usize).1 + 1, |
94 | 0 | j, |
95 | 0 | ) |
96 | 0 | } |
97 | 0 | } |
98 | 0 | } |
99 | | |
100 | | #[cfg_attr(feature = "no-panic", inline)] |
101 | 0 | pub fn mul_pow5_div_pow2(m: u32, i: u32, j: i32) -> u32 { |
102 | 0 | #[cfg(feature = "small")] |
103 | 0 | { |
104 | 0 | let pow5 = unsafe { d2s::compute_pow5(i) }; |
105 | 0 | mul_shift_32(m, pow5.1, j) |
106 | 0 | } |
107 | 0 |
|
108 | 0 | #[cfg(not(feature = "small"))] |
109 | 0 | { |
110 | 0 | debug_assert!(i < d2s::DOUBLE_POW5_SPLIT.len() as u32); |
111 | 0 | unsafe { mul_shift_32(m, d2s::DOUBLE_POW5_SPLIT.get_unchecked(i as usize).1, j) } |
112 | 0 | } |
113 | 0 | } |