mesh_loader/utils/float/
mod.rs
1#![allow(
19 clippy::cast_possible_truncation,
20 clippy::cast_possible_wrap,
21 clippy::cast_precision_loss,
22 clippy::cast_sign_loss,
23 clippy::items_after_statements,
24 clippy::module_inception,
25 clippy::redundant_else
26)]
27
28pub(crate) mod common;
29mod decimal;
30mod float;
31mod lemire;
32mod number;
33pub(crate) mod parse;
34mod slow;
35mod table;
36
37use self::{
38 common::{BiasedFp, ByteSlice},
39 float::RawFloat,
40 lemire::compute_float,
41 parse::{parse_inf_nan, parse_partial_number},
42 slow::parse_long_mantissa,
43};
44
45#[inline]
46pub fn parse<T: Float>(bytes: &[u8]) -> Option<T> {
47 T::parse(bytes)
48}
49
50#[inline]
51pub fn parse_partial<T: Float>(bytes: &[u8]) -> Option<(T, usize)> {
52 T::parse_partial(bytes)
53}
54
55pub trait Float: float::RawFloat {
56 #[inline]
57 fn parse(bytes: &[u8]) -> Option<Self> {
58 match Self::parse_partial(bytes) {
59 Some((v, n)) if n == bytes.len() => Some(v),
60 _ => None,
61 }
62 }
63
64 #[inline]
65 fn parse_partial(bytes: &[u8]) -> Option<(Self, usize)> {
66 dec2flt(bytes)
67 }
68}
69
70impl Float for f32 {}
71impl Float for f64 {}
72
73fn biased_fp_to_float<T: RawFloat>(x: BiasedFp) -> T {
75 let mut word = x.f;
76 word |= (x.e as u64) << T::MANTISSA_EXPLICIT_BITS;
77 T::from_u64_bits(word)
78}
79
80#[inline]
82pub(crate) fn dec2flt<F: RawFloat>(mut s: &[u8]) -> Option<(F, usize)> {
83 let start = s;
84 let c = if let Some(&c) = s.first() {
85 c
86 } else {
87 return None;
88 };
89 let negative = c == b'-';
90 if negative || c == b'+' {
91 s = &s[1..];
92 if s.is_empty() {
93 return None;
94 }
95 }
96
97 let (mut num, len) = match parse_partial_number(s, start) {
98 Some(r) => r,
99 None => match parse_inf_nan(s, negative) {
100 Some((value, len)) => return Some((value, len + s.offset_from(start) as usize)),
101 None => return None,
102 },
103 };
104 num.negative = negative;
105 if let Some(value) = num.try_fast_path::<F>() {
106 return Some((value, len));
107 }
108
109 let mut fp = compute_float::<F>(num.exponent, num.mantissa);
114 if num.many_digits && fp.e >= 0 && fp != compute_float::<F>(num.exponent, num.mantissa + 1) {
115 fp.e = -1;
116 }
117 if fp.e < 0 {
120 fp = parse_long_mantissa::<F>(s);
121 }
122
123 let mut float = biased_fp_to_float::<F>(fp);
124 if num.negative {
125 float = -float;
126 }
127 Some((float, len))
128}
129
130#[cfg(test)]
131#[path = "../tests/float.rs"]
132mod tests;