#![doc(hidden)]
#[cfg(feature = "compact")]
use crate::bellerophon::bellerophon;
use crate::extended_float::{extended_to_float, ExtendedFloat};
#[cfg(not(feature = "compact"))]
use crate::lemire::lemire;
use crate::num::Float;
use crate::number::Number;
use crate::slow::slow;
#[inline]
fn parse_number_fast<'a, Iter1, Iter2>(
integer: Iter1,
fraction: Iter2,
exponent: i32,
) -> Option<Number>
where
Iter1: Iterator<Item = &'a u8>,
Iter2: Iterator<Item = &'a u8>,
{
let mut num = Number::default();
let mut integer_count: usize = 0;
let mut fraction_count: usize = 0;
for &c in integer {
integer_count += 1;
let digit = c - b'0';
num.mantissa = num.mantissa.wrapping_mul(10).wrapping_add(digit as u64);
}
for &c in fraction {
fraction_count += 1;
let digit = c - b'0';
num.mantissa = num.mantissa.wrapping_mul(10).wrapping_add(digit as u64);
}
if integer_count + fraction_count <= 19 {
num.exponent = exponent.saturating_sub(fraction_count as i32);
Some(num)
} else {
None
}
}
#[inline]
fn parse_number<'a, Iter1, Iter2>(mut integer: Iter1, mut fraction: Iter2, exponent: i32) -> Number
where
Iter1: Iterator<Item = &'a u8> + Clone,
Iter2: Iterator<Item = &'a u8> + Clone,
{
if let Some(num) = parse_number_fast(integer.clone(), fraction.clone(), exponent) {
return num;
}
let mut num = Number::default();
let mut count = 0;
while let Some(&c) = integer.next() {
count += 1;
if count == 20 {
num.many_digits = true;
num.exponent = exponent.saturating_add(into_i32(1 + integer.count()));
return num;
} else {
let digit = c - b'0';
num.mantissa = num.mantissa * 10 + digit as u64;
}
}
let mut fraction_count: usize = 0;
if count == 0 {
for &c in &mut fraction {
fraction_count += 1;
if c != b'0' {
count += 1;
let digit = c - b'0';
num.mantissa = num.mantissa * 10 + digit as u64;
break;
}
}
}
for c in fraction {
fraction_count += 1;
count += 1;
if count == 20 {
num.many_digits = true;
num.exponent = exponent.saturating_sub(fraction_count as i32 - 1);
return num;
} else {
let digit = c - b'0';
num.mantissa = num.mantissa * 10 + digit as u64;
}
}
num.exponent = exponent.saturating_sub(fraction_count as i32);
num
}
pub fn parse_float<'a, F, Iter1, Iter2>(integer: Iter1, fraction: Iter2, exponent: i32) -> F
where
F: Float,
Iter1: Iterator<Item = &'a u8> + Clone,
Iter2: Iterator<Item = &'a u8> + Clone,
{
let num = parse_number(integer.clone(), fraction.clone(), exponent);
if let Some(value) = num.try_fast_path() {
return value;
}
let mut fp = moderate_path::<F>(&num);
if fp.exp < 0 {
fp.exp -= F::INVALID_FP;
fp = slow::<F, _, _>(num, fp, integer, fraction);
}
extended_to_float::<F>(fp)
}
#[inline]
pub fn moderate_path<F: Float>(num: &Number) -> ExtendedFloat {
#[cfg(not(feature = "compact"))]
return lemire::<F>(num);
#[cfg(feature = "compact")]
return bellerophon::<F>(num);
}
#[inline]
fn into_i32(value: usize) -> i32 {
if value > i32::max_value() as usize {
i32::max_value()
} else {
value as i32
}
}
#[inline]
pub fn add_digit(value: u64, digit: u8) -> Option<u64> {
value.checked_mul(10)?.checked_add(digit as u64)
}