/rust/registry/src/index.crates.io-1949cf8c6b5b557f/lexical-parse-float-1.0.6/src/float.rs
Line | Count | Source |
1 | | //! Extended helper trait for generic float types. |
2 | | //! |
3 | | //! This adapted from the Rust implementation, based on the fast-float-rust |
4 | | //! implementation, and is similarly subject to an Apache2.0/MIT license. |
5 | | |
6 | | #![doc(hidden)] |
7 | | |
8 | | #[cfg(feature = "f16")] |
9 | | use lexical_util::bf16::bf16; |
10 | | use lexical_util::extended_float::ExtendedFloat; |
11 | | #[cfg(feature = "f16")] |
12 | | use lexical_util::f16::f16; |
13 | | use lexical_util::num::{AsCast, Float}; |
14 | | |
15 | | #[cfg(all(not(feature = "std"), feature = "compact"))] |
16 | | use crate::libm::{powd, powf}; |
17 | | use crate::limits::{ExactFloat, MaxDigits}; |
18 | | #[cfg(not(feature = "compact"))] |
19 | | use crate::table::{get_small_f32_power, get_small_f64_power, get_small_int_power}; |
20 | | |
21 | | /// Alias with ~80 bits of precision, 64 for the mantissa and 16 for exponent. |
22 | | /// This exponent is biased, and if the exponent is negative, it represents |
23 | | /// a value with a bias of `i32::MIN + F::EXPONENT_BIAS`. |
24 | | pub type ExtendedFloat80 = ExtendedFloat<u64>; |
25 | | |
26 | | /// Helper trait to add more float characteristics for parsing floats. |
27 | | pub trait RawFloat: Float + ExactFloat + MaxDigits { |
28 | | // Maximum mantissa for the fast-path (`1 << 53` for f64). |
29 | | const MAX_MANTISSA_FAST_PATH: u64 = 2_u64 << Self::MANTISSA_SIZE; |
30 | | |
31 | | // Largest exponent value `(1 << EXP_BITS) - 1`. |
32 | | const INFINITE_POWER: i32 = Self::MAX_EXPONENT + Self::EXPONENT_BIAS; |
33 | | |
34 | | /// Minimum exponent that for a fast path case, or |
35 | | /// `-⌊(MANTISSA_SIZE+1)/log2(r)⌋` where `r` is the radix with |
36 | | /// powers-of-two removed. |
37 | | #[must_use] |
38 | | #[inline(always)] |
39 | 941 | fn min_exponent_fast_path(radix: u32) -> i64 { |
40 | 941 | Self::exponent_limit(radix).0 |
41 | 941 | } <f64 as lexical_parse_float::float::RawFloat>::min_exponent_fast_path Line | Count | Source | 39 | 941 | fn min_exponent_fast_path(radix: u32) -> i64 { | 40 | 941 | Self::exponent_limit(radix).0 | 41 | 941 | } |
Unexecuted instantiation: <_ as lexical_parse_float::float::RawFloat>::min_exponent_fast_path |
42 | | |
43 | | /// Maximum exponent that for a fast path case, or |
44 | | /// `⌊(MANTISSA_SIZE+1)/log2(r)⌋` where `r` is the radix with |
45 | | /// powers-of-two removed. |
46 | | #[must_use] |
47 | | #[inline(always)] |
48 | 1.44k | fn max_exponent_fast_path(radix: u32) -> i64 { |
49 | 1.44k | Self::exponent_limit(radix).1 |
50 | 1.44k | } <f64 as lexical_parse_float::float::RawFloat>::max_exponent_fast_path Line | Count | Source | 48 | 1.44k | fn max_exponent_fast_path(radix: u32) -> i64 { | 49 | 1.44k | Self::exponent_limit(radix).1 | 50 | 1.44k | } |
Unexecuted instantiation: <_ as lexical_parse_float::float::RawFloat>::max_exponent_fast_path |
51 | | |
52 | | // Maximum exponent that can be represented for a disguised-fast path case. |
53 | | // This is `max_exponent_fast_path(radix) + ⌊(MANTISSA_SIZE+1)/log2(radix)⌋` |
54 | | #[must_use] |
55 | | #[inline(always)] |
56 | 910 | fn max_exponent_disguised_fast_path(radix: u32) -> i64 { |
57 | 910 | Self::max_exponent_fast_path(radix) + Self::mantissa_limit(radix) |
58 | 910 | } <f64 as lexical_parse_float::float::RawFloat>::max_exponent_disguised_fast_path Line | Count | Source | 56 | 910 | fn max_exponent_disguised_fast_path(radix: u32) -> i64 { | 57 | 910 | Self::max_exponent_fast_path(radix) + Self::mantissa_limit(radix) | 58 | 910 | } |
Unexecuted instantiation: <_ as lexical_parse_float::float::RawFloat>::max_exponent_disguised_fast_path |
59 | | |
60 | | /// Get a small power-of-radix for fast-path multiplication. |
61 | | fn pow_fast_path(exponent: usize, radix: u32) -> Self; |
62 | | |
63 | | /// Get a small, integral power-of-radix for fast-path multiplication. |
64 | | #[must_use] |
65 | | #[inline(always)] |
66 | 68 | fn int_pow_fast_path(exponent: usize, radix: u32) -> u64 { |
67 | | #[cfg(not(feature = "compact"))] |
68 | 68 | return get_small_int_power(exponent, radix); |
69 | | |
70 | | #[cfg(feature = "compact")] |
71 | | return (radix as u64).wrapping_pow(exponent as u32); |
72 | 68 | } <f64 as lexical_parse_float::float::RawFloat>::int_pow_fast_path Line | Count | Source | 66 | 68 | fn int_pow_fast_path(exponent: usize, radix: u32) -> u64 { | 67 | | #[cfg(not(feature = "compact"))] | 68 | 68 | return get_small_int_power(exponent, radix); | 69 | | | 70 | | #[cfg(feature = "compact")] | 71 | | return (radix as u64).wrapping_pow(exponent as u32); | 72 | 68 | } |
Unexecuted instantiation: <_ as lexical_parse_float::float::RawFloat>::int_pow_fast_path |
73 | | } |
74 | | |
75 | | impl RawFloat for f32 { |
76 | | #[inline(always)] |
77 | 0 | fn pow_fast_path(exponent: usize, radix: u32) -> Self { |
78 | | #[cfg(not(feature = "compact"))] |
79 | 0 | return get_small_f32_power(exponent, radix); |
80 | | |
81 | | #[cfg(feature = "compact")] |
82 | | return powf(radix as f32, exponent as f32); |
83 | 0 | } |
84 | | } |
85 | | |
86 | | impl RawFloat for f64 { |
87 | | #[inline(always)] |
88 | 531 | fn pow_fast_path(exponent: usize, radix: u32) -> Self { |
89 | | #[cfg(not(feature = "compact"))] |
90 | 531 | return get_small_f64_power(exponent, radix); |
91 | | |
92 | | #[cfg(feature = "compact")] |
93 | | return powd(radix as f64, exponent as f64); |
94 | 531 | } |
95 | | } |
96 | | |
97 | | #[cfg(feature = "f16")] |
98 | | impl RawFloat for f16 { |
99 | | #[inline(always)] |
100 | | fn pow_fast_path(_: usize, _: u32) -> Self { |
101 | | unimplemented!() |
102 | | } |
103 | | } |
104 | | |
105 | | #[cfg(feature = "f16")] |
106 | | impl RawFloat for bf16 { |
107 | | #[inline(always)] |
108 | | fn pow_fast_path(_: usize, _: u32) -> Self { |
109 | | unimplemented!() |
110 | | } |
111 | | } |
112 | | |
113 | | /// Helper trait to add more float characteristics for the Eisel-Lemire |
114 | | /// algorithm. |
115 | | pub trait LemireFloat: RawFloat { |
116 | | // Round-to-even only happens for negative values of q |
117 | | // when `q ≥ −4` in the 64-bit case and when `q ≥ −17` in |
118 | | // the 32-bitcase. |
119 | | // |
120 | | // When `q ≥ 0`,we have that `5^q ≤ 2m+1`. In the 64-bit case,we |
121 | | // have `5^q ≤ 2m+1 ≤ 2^54` or `q ≤ 23`. In the 32-bit case,we have |
122 | | // `5^q ≤ 2m+1 ≤ 2^25` or `q ≤ 10`. |
123 | | // |
124 | | // When q < 0, we have `w ≥ (2m+1)×5^−q`. We must have that `w < 2^64` |
125 | | // so `(2m+1)×5^−q < 2^64`. We have that `2m+1 > 2^53` (64-bit case) |
126 | | // or `2m+1 > 2^24` (32-bit case). Hence,we must have `2^53×5^−q < 2^64` |
127 | | // (64-bit) and `2^24×5^−q < 2^64` (32-bit). Hence we have `5^−q < 2^11` |
128 | | // or `q ≥ −4` (64-bit case) and `5^−q < 2^40` or `q ≥ −17` (32-bitcase). |
129 | | // |
130 | | // Thus we have that we only need to round ties to even when |
131 | | // we have that `q ∈ [−4,23]` (in the 64-bit case) or `q∈[−17,10]` |
132 | | // (in the 32-bit case). In both cases,the power of five (`5^|q|`) |
133 | | // fits in a 64-bit word. |
134 | | const MIN_EXPONENT_ROUND_TO_EVEN: i32; |
135 | | const MAX_EXPONENT_ROUND_TO_EVEN: i32; |
136 | | |
137 | | /// Minimum normal exponent value `-(1 << (EXPONENT_SIZE - 1)) + 1`. |
138 | | const MINIMUM_EXPONENT: i32; |
139 | | |
140 | | /// Smallest decimal exponent for a non-zero value. |
141 | | const SMALLEST_POWER_OF_TEN: i32; |
142 | | |
143 | | /// Largest decimal exponent for a non-infinite value. |
144 | | const LARGEST_POWER_OF_TEN: i32; |
145 | | } |
146 | | |
147 | | impl LemireFloat for f32 { |
148 | | const MIN_EXPONENT_ROUND_TO_EVEN: i32 = -17; |
149 | | const MAX_EXPONENT_ROUND_TO_EVEN: i32 = 10; |
150 | | const MINIMUM_EXPONENT: i32 = -127; |
151 | | const SMALLEST_POWER_OF_TEN: i32 = -65; |
152 | | const LARGEST_POWER_OF_TEN: i32 = 38; |
153 | | } |
154 | | |
155 | | impl LemireFloat for f64 { |
156 | | const MIN_EXPONENT_ROUND_TO_EVEN: i32 = -4; |
157 | | const MAX_EXPONENT_ROUND_TO_EVEN: i32 = 23; |
158 | | const MINIMUM_EXPONENT: i32 = -1023; |
159 | | const SMALLEST_POWER_OF_TEN: i32 = -342; |
160 | | const LARGEST_POWER_OF_TEN: i32 = 308; |
161 | | } |
162 | | |
163 | | #[cfg(feature = "f16")] |
164 | | impl LemireFloat for f16 { |
165 | | const MIN_EXPONENT_ROUND_TO_EVEN: i32 = 0; |
166 | | const MAX_EXPONENT_ROUND_TO_EVEN: i32 = 0; |
167 | | const MINIMUM_EXPONENT: i32 = 0; |
168 | | const SMALLEST_POWER_OF_TEN: i32 = 0; |
169 | | const LARGEST_POWER_OF_TEN: i32 = 0; |
170 | | } |
171 | | |
172 | | #[cfg(feature = "f16")] |
173 | | impl LemireFloat for bf16 { |
174 | | const MIN_EXPONENT_ROUND_TO_EVEN: i32 = 0; |
175 | | const MAX_EXPONENT_ROUND_TO_EVEN: i32 = 0; |
176 | | const MINIMUM_EXPONENT: i32 = 0; |
177 | | const SMALLEST_POWER_OF_TEN: i32 = 0; |
178 | | const LARGEST_POWER_OF_TEN: i32 = 0; |
179 | | } |
180 | | |
181 | | #[inline(always)] |
182 | | #[cfg(all(feature = "std", feature = "compact"))] |
183 | | pub fn powf(x: f32, y: f32) -> f32 { |
184 | | x.powf(y) |
185 | | } |
186 | | |
187 | | #[inline(always)] |
188 | | #[cfg(all(feature = "std", feature = "compact"))] |
189 | | pub fn powd(x: f64, y: f64) -> f64 { |
190 | | x.powf(y) |
191 | | } |
192 | | |
193 | | /// Converts an `ExtendedFloat` to the closest machine float type. |
194 | | #[must_use] |
195 | | #[inline(always)] |
196 | 443 | pub fn extended_to_float<F: Float>(x: ExtendedFloat80) -> F { |
197 | 443 | let mut word = x.mant; |
198 | 443 | word |= (x.exp as u64) << F::MANTISSA_SIZE; |
199 | 443 | F::from_bits(F::Unsigned::as_cast(word)) |
200 | 443 | } lexical_parse_float::float::extended_to_float::<f64> Line | Count | Source | 196 | 443 | pub fn extended_to_float<F: Float>(x: ExtendedFloat80) -> F { | 197 | 443 | let mut word = x.mant; | 198 | 443 | word |= (x.exp as u64) << F::MANTISSA_SIZE; | 199 | 443 | F::from_bits(F::Unsigned::as_cast(word)) | 200 | 443 | } |
Unexecuted instantiation: lexical_parse_float::float::extended_to_float::<_> |