• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use crate::common::*;
2 use crate::f2s;
3 use crate::f2s_intrinsics::*;
4 use crate::parse::Error;
5 #[cfg(feature = "no-panic")]
6 use no_panic::no_panic;
7 
8 const FLOAT_EXPONENT_BIAS: usize = 127;
9 
floor_log2(value: u32) -> u3210 fn floor_log2(value: u32) -> u32 {
11     31_u32.wrapping_sub(value.leading_zeros())
12 }
13 
14 #[cfg_attr(feature = "no-panic", no_panic)]
s2f(buffer: &[u8]) -> Result<f32, Error>15 pub fn s2f(buffer: &[u8]) -> Result<f32, Error> {
16     let len = buffer.len();
17     if len == 0 {
18         return Err(Error::InputTooShort);
19     }
20 
21     let mut m10digits = 0;
22     let mut e10digits = 0;
23     let mut dot_index = len;
24     let mut e_index = len;
25     let mut m10 = 0u32;
26     let mut e10 = 0i32;
27     let mut signed_m = false;
28     let mut signed_e = false;
29 
30     let mut i = 0;
31     if unsafe { *buffer.get_unchecked(0) } == b'-' {
32         signed_m = true;
33         i += 1;
34     }
35 
36     while let Some(c) = buffer.get(i).copied() {
37         if c == b'.' {
38             if dot_index != len {
39                 return Err(Error::MalformedInput);
40             }
41             dot_index = i;
42             i += 1;
43             continue;
44         }
45         if c < b'0' || c > b'9' {
46             break;
47         }
48         if m10digits >= 9 {
49             return Err(Error::InputTooLong);
50         }
51         m10 = 10 * m10 + (c - b'0') as u32;
52         if m10 != 0 {
53             m10digits += 1;
54         }
55         i += 1;
56     }
57 
58     if let Some(b'e') | Some(b'E') = buffer.get(i) {
59         e_index = i;
60         i += 1;
61         match buffer.get(i) {
62             Some(b'-') => {
63                 signed_e = true;
64                 i += 1;
65             }
66             Some(b'+') => i += 1,
67             _ => {}
68         }
69         while let Some(c) = buffer.get(i).copied() {
70             if c < b'0' || c > b'9' {
71                 return Err(Error::MalformedInput);
72             }
73             if e10digits > 3 {
74                 // TODO: Be more lenient. Return +/-Infinity or +/-0 instead.
75                 return Err(Error::InputTooLong);
76             }
77             e10 = 10 * e10 + (c - b'0') as i32;
78             if e10 != 0 {
79                 e10digits += 1;
80             }
81             i += 1;
82         }
83     }
84 
85     if i < len {
86         return Err(Error::MalformedInput);
87     }
88     if signed_e {
89         e10 = -e10;
90     }
91     e10 -= if dot_index < e_index {
92         (e_index - dot_index - 1) as i32
93     } else {
94         0
95     };
96     if m10 == 0 {
97         return Ok(if signed_m { -0.0 } else { 0.0 });
98     }
99 
100     if m10digits + e10 <= -46 || m10 == 0 {
101         // Number is less than 1e-46, which should be rounded down to 0; return
102         // +/-0.0.
103         let ieee = (signed_m as u32) << (f2s::FLOAT_EXPONENT_BITS + f2s::FLOAT_MANTISSA_BITS);
104         return Ok(f32::from_bits(ieee));
105     }
106     if m10digits + e10 >= 40 {
107         // Number is larger than 1e+39, which should be rounded to +/-Infinity.
108         let ieee = ((signed_m as u32) << (f2s::FLOAT_EXPONENT_BITS + f2s::FLOAT_MANTISSA_BITS))
109             | (0xff_u32 << f2s::FLOAT_MANTISSA_BITS);
110         return Ok(f32::from_bits(ieee));
111     }
112 
113     // Convert to binary float m2 * 2^e2, while retaining information about
114     // whether the conversion was exact (trailing_zeros).
115     let e2: i32;
116     let m2: u32;
117     let mut trailing_zeros: bool;
118     if e10 >= 0 {
119         // The length of m * 10^e in bits is:
120         //   log2(m10 * 10^e10) = log2(m10) + e10 log2(10) = log2(m10) + e10 + e10 * log2(5)
121         //
122         // We want to compute the FLOAT_MANTISSA_BITS + 1 top-most bits (+1 for
123         // the implicit leading one in IEEE format). We therefore choose a
124         // binary output exponent of
125         //   log2(m10 * 10^e10) - (FLOAT_MANTISSA_BITS + 1).
126         //
127         // We use floor(log2(5^e10)) so that we get at least this many bits; better to
128         // have an additional bit than to not have enough bits.
129         e2 = floor_log2(m10)
130             .wrapping_add(e10 as u32)
131             .wrapping_add(log2_pow5(e10) as u32)
132             .wrapping_sub(f2s::FLOAT_MANTISSA_BITS + 1) as i32;
133 
134         // We now compute [m10 * 10^e10 / 2^e2] = [m10 * 5^e10 / 2^(e2-e10)].
135         // To that end, we use the FLOAT_POW5_SPLIT table.
136         let j = e2
137             .wrapping_sub(e10)
138             .wrapping_sub(ceil_log2_pow5(e10))
139             .wrapping_add(f2s::FLOAT_POW5_BITCOUNT);
140         debug_assert!(j >= 0);
141         m2 = mul_pow5_div_pow2(m10, e10 as u32, j);
142 
143         // We also compute if the result is exact, i.e.,
144         //   [m10 * 10^e10 / 2^e2] == m10 * 10^e10 / 2^e2.
145         // This can only be the case if 2^e2 divides m10 * 10^e10, which in turn
146         // requires that the largest power of 2 that divides m10 + e10 is
147         // greater than e2. If e2 is less than e10, then the result must be
148         // exact. Otherwise we use the existing multiple_of_power_of_2 function.
149         trailing_zeros =
150             e2 < e10 || e2 - e10 < 32 && multiple_of_power_of_2_32(m10, (e2 - e10) as u32);
151     } else {
152         e2 = floor_log2(m10)
153             .wrapping_add(e10 as u32)
154             .wrapping_sub(ceil_log2_pow5(-e10) as u32)
155             .wrapping_sub(f2s::FLOAT_MANTISSA_BITS + 1) as i32;
156         let j = e2
157             .wrapping_sub(e10)
158             .wrapping_add(ceil_log2_pow5(-e10))
159             .wrapping_sub(1)
160             .wrapping_add(f2s::FLOAT_POW5_INV_BITCOUNT);
161         m2 = mul_pow5_inv_div_pow2(m10, -e10 as u32, j);
162         trailing_zeros = multiple_of_power_of_5_32(m10, -e10 as u32);
163     }
164 
165     // Compute the final IEEE exponent.
166     let mut ieee_e2 = i32::max(0, e2 + FLOAT_EXPONENT_BIAS as i32 + floor_log2(m2) as i32) as u32;
167 
168     if ieee_e2 > 0xfe {
169         // Final IEEE exponent is larger than the maximum representable; return
170         // +/-Infinity.
171         let ieee = ((signed_m as u32) << (f2s::FLOAT_EXPONENT_BITS + f2s::FLOAT_MANTISSA_BITS))
172             | (0xff_u32 << f2s::FLOAT_MANTISSA_BITS);
173         return Ok(f32::from_bits(ieee));
174     }
175 
176     // We need to figure out how much we need to shift m2. The tricky part is
177     // that we need to take the final IEEE exponent into account, so we need to
178     // reverse the bias and also special-case the value 0.
179     let shift = if ieee_e2 == 0 { 1 } else { ieee_e2 as i32 }
180         .wrapping_sub(e2)
181         .wrapping_sub(FLOAT_EXPONENT_BIAS as i32)
182         .wrapping_sub(f2s::FLOAT_MANTISSA_BITS as i32);
183     debug_assert!(shift >= 0);
184 
185     // We need to round up if the exact value is more than 0.5 above the value
186     // we computed. That's equivalent to checking if the last removed bit was 1
187     // and either the value was not just trailing zeros or the result would
188     // otherwise be odd.
189     //
190     // We need to update trailing_zeros given that we have the exact output
191     // exponent ieee_e2 now.
192     trailing_zeros &= (m2 & ((1_u32 << (shift - 1)) - 1)) == 0;
193     let last_removed_bit = (m2 >> (shift - 1)) & 1;
194     let round_up = last_removed_bit != 0 && (!trailing_zeros || ((m2 >> shift) & 1) != 0);
195 
196     let mut ieee_m2 = (m2 >> shift).wrapping_add(round_up as u32);
197     if ieee_m2 == (1_u32 << (f2s::FLOAT_MANTISSA_BITS + 1)) {
198         // Due to how the IEEE represents +/-Infinity, we don't need to check
199         // for overflow here.
200         ieee_e2 += 1;
201     }
202     ieee_m2 &= (1_u32 << f2s::FLOAT_MANTISSA_BITS) - 1;
203     let ieee = ((((signed_m as u32) << f2s::FLOAT_EXPONENT_BITS) | ieee_e2 as u32)
204         << f2s::FLOAT_MANTISSA_BITS)
205         | ieee_m2;
206     Ok(f32::from_bits(ieee))
207 }
208