1 // Adapted from https://github.com/Alexhuszagh/rust-lexical.
2 
3 //! Compare the mantissa to the halfway representation of the float.
4 //!
5 //! Compares the actual significant digits of the mantissa to the
6 //! theoretical digits from `b+h`, scaled into the proper range.
7 
8 use super::bignum::*;
9 use super::digit::*;
10 use super::exponent::*;
11 use super::float::*;
12 use super::math::*;
13 use super::num::*;
14 use super::rounding::*;
15 use crate::lib::{cmp, mem};
16 
17 // MANTISSA
18 
19 /// Parse the full mantissa into a big integer.
20 ///
21 /// Max digits is the maximum number of digits plus one.
parse_mantissa<F>(integer: &[u8], fraction: &[u8]) -> Bigint where F: Float,22 fn parse_mantissa<F>(integer: &[u8], fraction: &[u8]) -> Bigint
23 where
24     F: Float,
25 {
26     // Main loop
27     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     // Iteratively process all the data in the mantissa.
36     for &digit in integer.iter().chain(fraction) {
37         // We've parsed the max digits using small values, add to bignum
38         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     // We will always have a remainder, as long as we entered the loop
56     // once, or counter % step is 0.
57     if counter != 0 {
58         result.imul_small(small_powers[counter]);
59         result.iadd_small(value);
60     }
61 
62     // If we have any remaining digits after the last value, we need
63     // to add a 1 after the rest of the array, it doesn't matter where,
64     // just move it up. This is good for the worst-possible float
65     // representation. We also need to return an index.
66     // Since we already trimmed trailing zeros, we know there has
67     // to be a non-zero digit if there are any left.
68     if i < integer.len() + fraction.len() {
69         result.imul_small(10);
70         result.iadd_small(1);
71     }
72 
73     result
74 }
75 
76 // FLOAT OPS
77 
78 /// Calculate `b` from a a representation of `b` as a float.
79 #[inline]
b_extended<F: Float>(f: F) -> ExtendedFloat80 pub(super) fn b_extended<F: Float>(f: F) -> ExtendedFloat {
81     ExtendedFloat::from_float(f)
82 }
83 
84 /// Calculate `b+h` from a a representation of `b` as a float.
85 #[inline]
bh_extended<F: Float>(f: F) -> ExtendedFloat86 pub(super) fn bh_extended<F: Float>(f: F) -> ExtendedFloat {
87     // None of these can overflow.
88     let b = b_extended(f);
89     ExtendedFloat {
90         mant: (b.mant << 1) + 1,
91         exp: b.exp - 1,
92     }
93 }
94 
95 // ROUNDING
96 
97 /// Custom round-nearest, tie-event algorithm for bhcomp.
98 #[inline]
round_nearest_tie_even(fp: &mut ExtendedFloat, shift: i32, is_truncated: bool)99 fn 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 
108 // BHCOMP
109 
110 /// Calculate the mantissa for a big integer with a positive exponent.
large_atof<F>(mantissa: Bigint, exponent: i32) -> F where F: Float,111 fn large_atof<F>(mantissa: Bigint, exponent: i32) -> F
112 where
113     F: Float,
114 {
115     let bits = mem::size_of::<u64>() * 8;
116 
117     // Simple, we just need to multiply by the power of the radix.
118     // Now, we can calculate the mantissa and the exponent from this.
119     // The binary exponent is the binary exponent for the mantissa
120     // shifted to the hidden bit.
121     let mut bigmant = mantissa;
122     bigmant.imul_pow10(exponent as u32);
123 
124     // Get the exact representation of the float from the big integer.
125     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 
132 /// Calculate the mantissa for a big integer with a negative exponent.
133 ///
134 /// This invokes the comparison with `b+h`.
small_atof<F>(mantissa: Bigint, exponent: i32, f: F) -> F where F: Float,135 fn small_atof<F>(mantissa: Bigint, exponent: i32, f: F) -> F
136 where
137     F: Float,
138 {
139     // Get the significant digits and radix exponent for the real digits.
140     let mut real_digits = mantissa;
141     let real_exp = exponent;
142     debug_assert!(real_exp < 0);
143 
144     // Get the significant digits and the binary exponent for `b+h`.
145     let theor = bh_extended(f);
146     let mut theor_digits = Bigint::from_u64(theor.mant);
147     let theor_exp = theor.exp;
148 
149     // We need to scale the real digits and `b+h` digits to be the same
150     // order. We currently have `real_exp`, in `radix`, that needs to be
151     // shifted to `theor_digits` (since it is negative), and `theor_exp`
152     // to either `theor_digits` or `real_digits` as a power of 2 (since it
153     // may be positive or negative). Try to remove as many powers of 2
154     // as possible. All values are relative to `theor_digits`, that is,
155     // reflect the power you need to multiply `theor_digits` by.
156 
157     // Can remove a power-of-two, since the radix is 10.
158     // Both are on opposite-sides of equation, can factor out a
159     // power of two.
160     //
161     // Example: 10^-10, 2^-10   -> ( 0, 10, 0)
162     // Example: 10^-10, 2^-15   -> (-5, 10, 0)
163     // Example: 10^-10, 2^-5    -> ( 5, 10, 0)
164     // Example: 10^-10, 2^5 -> (15, 10, 0)
165     let binary_exp = theor_exp - real_exp;
166     let halfradix_exp = -real_exp;
167     let radix_exp = 0;
168 
169     // Carry out our multiplication.
170     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     // Compare real digits to theoretical digits and round the float.
183     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 
190 /// Calculate the exact value of the float.
191 ///
192 /// Note: fraction must not have trailing zeros.
bhcomp<F>(b: F, integer: &[u8], mut fraction: &[u8], exponent: i32) -> F where F: Float,193 pub(crate) fn bhcomp<F>(b: F, integer: &[u8], mut fraction: &[u8], exponent: i32) -> F
194 where
195     F: Float,
196 {
197     // Calculate the number of integer digits and use that to determine
198     // where the significant digits start in the fraction.
199     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 }
219