serde_json/lexical/
bhcomp.rs1use super::bignum::*;
9use super::digit::*;
10use super::exponent::*;
11use super::float::*;
12use super::math::*;
13use super::num::*;
14use super::rounding::*;
15use core::{cmp, mem};
16
17fn parse_mantissa<F>(integer: &[u8], fraction: &[u8]) -> Bigint
23where
24 F: Float,
25{
26 let small_powers = POW10_LIMB;
28 let step = small_powers.len() - 2;
29 let max_digits = F::MAX_DIGITS - 1;
30 let mut counter = 0;
31 let mut value: Limb = 0;
32 let mut i: usize = 0;
33 let mut result = Bigint::default();
34
35 for &digit in integer.iter().chain(fraction) {
37 if counter == step {
39 result.imul_small(small_powers[counter]);
40 result.iadd_small(value);
41 counter = 0;
42 value = 0;
43 }
44
45 value *= 10;
46 value += as_limb(to_digit(digit).unwrap());
47
48 i += 1;
49 counter += 1;
50 if i == max_digits {
51 break;
52 }
53 }
54
55 if counter != 0 {
58 result.imul_small(small_powers[counter]);
59 result.iadd_small(value);
60 }
61
62 if i < integer.len() + fraction.len() {
69 result.imul_small(10);
70 result.iadd_small(1);
71 }
72
73 result
74}
75
76#[inline]
80pub(super) fn b_extended<F: Float>(f: F) -> ExtendedFloat {
81 ExtendedFloat::from_float(f)
82}
83
84#[inline]
86pub(super) fn bh_extended<F: Float>(f: F) -> ExtendedFloat {
87 let b = b_extended(f);
89 ExtendedFloat {
90 mant: (b.mant << 1) + 1,
91 exp: b.exp - 1,
92 }
93}
94
95#[inline]
99fn round_nearest_tie_even(fp: &mut ExtendedFloat, shift: i32, is_truncated: bool) {
100 let (mut is_above, mut is_halfway) = round_nearest(fp, shift);
101 if is_halfway && is_truncated {
102 is_above = true;
103 is_halfway = false;
104 }
105 tie_even(fp, is_above, is_halfway);
106}
107
108fn large_atof<F>(mantissa: Bigint, exponent: i32) -> F
112where
113 F: Float,
114{
115 let bits = mem::size_of::<u64>() * 8;
116
117 let mut bigmant = mantissa;
122 bigmant.imul_pow10(exponent as u32);
123
124 let (mant, is_truncated) = bigmant.hi64();
126 let exp = bigmant.bit_length() as i32 - bits as i32;
127 let mut fp = ExtendedFloat { mant, exp };
128 fp.round_to_native::<F, _>(|fp, shift| round_nearest_tie_even(fp, shift, is_truncated));
129 into_float(fp)
130}
131
132fn small_atof<F>(mantissa: Bigint, exponent: i32, f: F) -> F
136where
137 F: Float,
138{
139 let mut real_digits = mantissa;
141 let real_exp = exponent;
142 if true {
if !(real_exp < 0) {
::core::panicking::panic("assertion failed: real_exp < 0")
};
};debug_assert!(real_exp < 0);
143
144 let theor = bh_extended(f);
146 let mut theor_digits = Bigint::from_u64(theor.mant);
147 let theor_exp = theor.exp;
148
149 let binary_exp = theor_exp - real_exp;
166 let halfradix_exp = -real_exp;
167 let radix_exp = 0;
168
169 if halfradix_exp != 0 {
171 theor_digits.imul_pow5(halfradix_exp as u32);
172 }
173 if radix_exp != 0 {
174 theor_digits.imul_pow10(radix_exp as u32);
175 }
176 if binary_exp > 0 {
177 theor_digits.imul_pow2(binary_exp as u32);
178 } else if binary_exp < 0 {
179 real_digits.imul_pow2(-binary_exp as u32);
180 }
181
182 match real_digits.compare(&theor_digits) {
184 cmp::Ordering::Greater => f.next_positive(),
185 cmp::Ordering::Less => f,
186 cmp::Ordering::Equal => f.round_positive_even(),
187 }
188}
189
190pub(crate) fn bhcomp<F>(b: F, integer: &[u8], mut fraction: &[u8], exponent: i32) -> F
194where
195 F: Float,
196{
197 let integer_digits = integer.len();
200 let fraction_digits = fraction.len();
201 let digits_start = if integer_digits == 0 {
202 let start = fraction.iter().take_while(|&x| *x == b'0').count();
203 fraction = &fraction[start..];
204 start
205 } else {
206 0
207 };
208 let sci_exp = scientific_exponent(exponent, integer_digits, digits_start);
209 let count = F::MAX_DIGITS.min(integer_digits + fraction_digits - digits_start);
210 let scaled_exponent = sci_exp + 1 - count as i32;
211
212 let mantissa = parse_mantissa::<F>(integer, fraction);
213 if scaled_exponent >= 0 {
214 large_atof(mantissa, scaled_exponent)
215 } else {
216 small_atof(mantissa, scaled_exponent, b)
217 }
218}