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.
56#![doc(hidden)]
78#[cfg(feature = "f16")]
9use lexical_util::bf16::bf16;
10use lexical_util::extended_float::ExtendedFloat;
11#[cfg(feature = "f16")]
12use lexical_util::f16::f16;
13use lexical_util::num::{AsCast, Float};
1415#[cfg(all(not(feature = "std"), feature = "compact"))]
16use crate::libm::{powd, powf};
17use crate::limits::{ExactFloat, MaxDigits};
18#[cfg(not(feature = "compact"))]
19use crate::table::{get_small_f32_power, get_small_f64_power, get_small_int_power};
2021/// 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`.
24pub type ExtendedFloat80 = ExtendedFloat<u64>;
2526/// Helper trait to add more float characteristics for parsing floats.
27pub trait RawFloat: Float + ExactFloat + MaxDigits {
28// Maximum mantissa for the fast-path (`1 << 53` for f64).
29const MAX_MANTISSA_FAST_PATH: u64 = 2_u64 << Self::MANTISSA_SIZE;
3031// Largest exponent value `(1 << EXP_BITS) - 1`.
32const INFINITE_POWER: i32 = Self::MAX_EXPONENT + Self::EXPONENT_BIAS;
3334/// 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)]
39fn min_exponent_fast_path(radix: u32) -> i64 {
40Self::exponent_limit(radix).0
41}
4243/// 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)]
48fn max_exponent_fast_path(radix: u32) -> i64 {
49Self::exponent_limit(radix).1
50}
5152// 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)]
56fn max_exponent_disguised_fast_path(radix: u32) -> i64 {
57Self::max_exponent_fast_path(radix) + Self::mantissa_limit(radix)
58 }
5960/// Get a small power-of-radix for fast-path multiplication.
61fn pow_fast_path(exponent: usize, radix: u32) -> Self;
6263/// Get a small, integral power-of-radix for fast-path multiplication.
64#[must_use]
65 #[inline(always)]
66fn int_pow_fast_path(exponent: usize, radix: u32) -> u64 {
67// SAFETY: safe as long as the exponent is smaller than the radix table.
68#[cfg(not(feature = "compact"))]
69return get_small_int_power(exponent, radix);
7071#[cfg(feature = "compact")]
72return (radix as u64).wrapping_pow(exponent as u32);
73 }
74}
7576impl RawFloat for f32 {
77#[inline(always)]
78fn pow_fast_path(exponent: usize, radix: u32) -> Self {
79// SAFETY: safe as long as the exponent is smaller than the radix table.
80#[cfg(not(feature = "compact"))]
81return get_small_f32_power(exponent, radix);
8283#[cfg(feature = "compact")]
84return powf(radix as f32, exponent as f32);
85 }
86}
8788impl RawFloat for f64 {
89#[inline(always)]
90fn pow_fast_path(exponent: usize, radix: u32) -> Self {
91// SAFETY: safe as long as the exponent is smaller than the radix table.
92#[cfg(not(feature = "compact"))]
93return get_small_f64_power(exponent, radix);
9495#[cfg(feature = "compact")]
96return powd(radix as f64, exponent as f64);
97 }
98}
99100#[cfg(feature = "f16")]
101impl RawFloat for f16 {
102#[inline(always)]
103fn pow_fast_path(_: usize, _: u32) -> Self {
104unimplemented!()
105 }
106}
107108#[cfg(feature = "f16")]
109impl RawFloat for bf16 {
110#[inline(always)]
111fn pow_fast_path(_: usize, _: u32) -> Self {
112unimplemented!()
113 }
114}
115116/// Helper trait to add more float characteristics for the Eisel-Lemire
117/// algorithm.
118pub trait LemireFloat: RawFloat {
119// Round-to-even only happens for negative values of q
120 // when `q ≥ −4` in the 64-bit case and when `q ≥ −17` in
121 // the 32-bitcase.
122 //
123 // When `q ≥ 0`,we have that `5^q ≤ 2m+1`. In the 64-bit case,we
124 // have `5^q ≤ 2m+1 ≤ 2^54` or `q ≤ 23`. In the 32-bit case,we have
125 // `5^q ≤ 2m+1 ≤ 2^25` or `q ≤ 10`.
126 //
127 // When q < 0, we have `w ≥ (2m+1)×5^−q`. We must have that `w < 2^64`
128 // so `(2m+1)×5^−q < 2^64`. We have that `2m+1 > 2^53` (64-bit case)
129 // or `2m+1 > 2^24` (32-bit case). Hence,we must have `2^53×5^−q < 2^64`
130 // (64-bit) and `2^24×5^−q < 2^64` (32-bit). Hence we have `5^−q < 2^11`
131 // or `q ≥ −4` (64-bit case) and `5^−q < 2^40` or `q ≥ −17` (32-bitcase).
132 //
133 // Thus we have that we only need to round ties to even when
134 // we have that `q ∈ [−4,23]` (in the 64-bit case) or `q∈[−17,10]`
135 // (in the 32-bit case). In both cases,the power of five (`5^|q|`)
136 // fits in a 64-bit word.
137const MIN_EXPONENT_ROUND_TO_EVEN: i32;
138const MAX_EXPONENT_ROUND_TO_EVEN: i32;
139140/// Minimum normal exponent value `-(1 << (EXPONENT_SIZE - 1)) + 1`.
141const MINIMUM_EXPONENT: i32;
142143/// Smallest decimal exponent for a non-zero value.
144const SMALLEST_POWER_OF_TEN: i32;
145146/// Largest decimal exponent for a non-infinite value.
147const LARGEST_POWER_OF_TEN: i32;
148}
149150impl LemireFloat for f32 {
151const MIN_EXPONENT_ROUND_TO_EVEN: i32 = -17;
152const MAX_EXPONENT_ROUND_TO_EVEN: i32 = 10;
153const MINIMUM_EXPONENT: i32 = -127;
154const SMALLEST_POWER_OF_TEN: i32 = -65;
155const LARGEST_POWER_OF_TEN: i32 = 38;
156}
157158impl LemireFloat for f64 {
159const MIN_EXPONENT_ROUND_TO_EVEN: i32 = -4;
160const MAX_EXPONENT_ROUND_TO_EVEN: i32 = 23;
161const MINIMUM_EXPONENT: i32 = -1023;
162const SMALLEST_POWER_OF_TEN: i32 = -342;
163const LARGEST_POWER_OF_TEN: i32 = 308;
164}
165166#[cfg(feature = "f16")]
167impl LemireFloat for f16 {
168const MIN_EXPONENT_ROUND_TO_EVEN: i32 = 0;
169const MAX_EXPONENT_ROUND_TO_EVEN: i32 = 0;
170const MINIMUM_EXPONENT: i32 = 0;
171const SMALLEST_POWER_OF_TEN: i32 = 0;
172const LARGEST_POWER_OF_TEN: i32 = 0;
173}
174175#[cfg(feature = "f16")]
176impl LemireFloat for bf16 {
177const MIN_EXPONENT_ROUND_TO_EVEN: i32 = 0;
178const MAX_EXPONENT_ROUND_TO_EVEN: i32 = 0;
179const MINIMUM_EXPONENT: i32 = 0;
180const SMALLEST_POWER_OF_TEN: i32 = 0;
181const LARGEST_POWER_OF_TEN: i32 = 0;
182}
183184#[inline(always)]
185#[cfg(all(feature = "std", feature = "compact"))]
186pub fn powf(x: f32, y: f32) -> f32 {
187 x.powf(y)
188}
189190#[inline(always)]
191#[cfg(all(feature = "std", feature = "compact"))]
192pub fn powd(x: f64, y: f64) -> f64 {
193 x.powf(y)
194}
195196/// Converts an `ExtendedFloat` to the closest machine float type.
197#[must_use]
198#[inline(always)]
199pub fn extended_to_float<F: Float>(x: ExtendedFloat80) -> F {
200let mut word = x.mant;
201 word |= (x.exp as u64) << F::MANTISSA_SIZE;
202 F::from_bits(F::Unsigned::as_cast(word))
203}