Skip to content

Commit

Permalink
Delay splitting into words
Browse files Browse the repository at this point in the history
  • Loading branch information
paupino committed Feb 2, 2024
1 parent 38de762 commit e125131
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 31 deletions.
9 changes: 6 additions & 3 deletions macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,11 @@ pub fn dec(input: TokenStream) -> TokenStream {
Err(e) => panic!("{}", e),
}
};
if decimal.mid == 0 && decimal.hi == 0 {
match (decimal.lo, decimal.scale, decimal.negative) {
let lo = decimal.lo();
let mid = decimal.mid();
let hi = decimal.hi();
if mid == 0 && hi == 0 {
match (lo, decimal.scale, decimal.negative) {
(0, 0, _) => return constant(Constant::Zero),
(1, 0, false) => return constant(Constant::One),
(1, 0, true) => return constant(Constant::NegativeOne),
Expand All @@ -86,7 +89,7 @@ pub fn dec(input: TokenStream) -> TokenStream {
}
}

expand(decimal.lo, decimal.mid, decimal.hi, decimal.negative, decimal.scale)
expand(lo, mid, hi, decimal.negative, decimal.scale)
}

#[derive(Debug)]
Expand Down
34 changes: 19 additions & 15 deletions parser/src/base_10.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ fn parse_str_radix_10_dispatch<const BIG: bool, const ROUND: bool>(
) -> Result<DecimalComponents, ParserError> {
match bytes {
[b, rest @ ..] => byte_dispatch_u64::<false, false, false, BIG, true, ROUND>(rest, 0, 0, *b),
[] => Err(ParserError::EmptyInput),
[] => tail_error(ParserError::EmptyInput),
}
}

Expand Down Expand Up @@ -160,16 +160,6 @@ fn handle_separator<const POINT: bool, const NEG: bool, const BIG: bool, const R
dispatch_next::<POINT, NEG, true, BIG, ROUND>(bytes, data64, scale)
}

#[inline(never)]
#[cold]
fn tail_invalid_digit(digit: u8) -> Result<DecimalComponents, ParserError> {
match digit {
b'.' => Err(ParserError::MultipleDecimalPoints),
b'_' => Err(ParserError::InvalidPlaceholderPosition),
_ => Err(ParserError::InvalidCharacter),
}
}

#[inline(never)]
#[cold]
fn handle_full_128<const POINT: bool, const NEG: bool, const ROUND: bool>(
Expand Down Expand Up @@ -267,7 +257,7 @@ fn maybe_round(
// next least significant digit and discard precision
if overflow_128(data) {
if scale == 0 {
return Err(ParserError::OverflowAfterRound);
return tail_error(ParserError::OverflowAfterRound);
}
data += 4;
data /= 10;
Expand All @@ -283,6 +273,22 @@ fn maybe_round(
}

#[inline(never)]
#[cold]
fn tail_invalid_digit(digit: u8) -> Result<DecimalComponents, ParserError> {
match digit {
b'.' => tail_error(ParserError::MultipleDecimalPoints),
b'_' => tail_error(ParserError::InvalidPlaceholderPosition),
_ => tail_error(ParserError::InvalidCharacter),
}
}

#[cold]
fn tail_error(e: ParserError) -> Result<DecimalComponents, ParserError> {
Err(e)
}

#[inline(never)]
#[cold]
fn tail_no_has() -> Result<DecimalComponents, ParserError> {
return Err(ParserError::NoDigits);
}
Expand All @@ -294,9 +300,7 @@ fn handle_data<const NEG: bool, const HAS: bool>(data: u128, scale: u8) -> Resul
tail_no_has()
} else {
Ok(DecimalComponents {
lo: data as u32,
mid: (data >> 32) as u32,
hi: (data >> 64) as u32,
mantissa: data,
negative: NEG,
scale: scale as u32,
})
Expand Down
21 changes: 18 additions & 3 deletions parser/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,24 @@ impl core::fmt::Display for ParserError {

#[derive(Debug)]
pub struct DecimalComponents {
pub lo: u32,
pub mid: u32,
pub hi: u32,
pub mantissa: u128,
pub negative: bool,
pub scale: u32,
}

impl DecimalComponents {
#[inline(always)]
pub fn lo(&self) -> u32 {
self.mantissa as u32
}

#[inline(always)]
pub fn mid(&self) -> u32 {
(self.mantissa >> 32) as u32
}

#[inline(always)]
pub fn hi(&self) -> u32 {
(self.mantissa >> 64) as u32
}
}
12 changes: 4 additions & 8 deletions parser/src/scientific.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ pub fn parse_scientific(input: &str) -> Result<DecimalComponents, ParserError> {
let exp = split.next().ok_or_else(|| ParserError::UnableToExtractExponent)?;

let mut decimal = parse_radix_10_exact(base)?;
let mut mantissa = (decimal.lo as u128) | ((decimal.mid as u128) << 32) | ((decimal.hi as u128) << 64);

if let Some(stripped) = exp.strip_prefix('-') {
let exp: u32 = stripped.parse().map_err(|_| ParserError::UnableToParseExponent)?;
Expand All @@ -37,28 +36,25 @@ pub fn parse_scientific(input: &str) -> Result<DecimalComponents, ParserError> {
assert_scale(exp)?;

let pow = 10_u128.pow(exp);
mantissa = match mantissa.checked_mul(pow) {
decimal.mantissa = match decimal.mantissa.checked_mul(pow) {
Some(m) => m,
None => return Err(ParserError::ExceedsMaximumPossibleValue),
};
if mantissa >= OVERFLOW_U96 {
if decimal.mantissa >= OVERFLOW_U96 {
return Err(ParserError::ExceedsMaximumPossibleValue);
}
}
}

// Lastly, remove any trailing zeros. This is unique to scientific parsing.
while decimal.scale > 0 {
let remainder = mantissa.rem(10);
let remainder = decimal.mantissa.rem(10);
if remainder != 0 {
break;
}
mantissa /= 10;
decimal.mantissa /= 10;
decimal.scale -= 1;
}

decimal.lo = mantissa as u32;
decimal.mid = (mantissa >> 32) as u32;
decimal.hi = (mantissa >> 64) as u32;
Ok(decimal)
}
4 changes: 2 additions & 2 deletions src/str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ pub(crate) fn fmt_scientific_notation(
impl From<DecimalComponents> for Decimal {
#[inline]
fn from(value: DecimalComponents) -> Self {
Decimal::from_parts(value.lo, value.mid, value.hi, value.negative, value.scale)
Decimal::from_parts(value.lo(), value.mid(), value.hi(), value.negative, value.scale)
}
}

Expand Down Expand Up @@ -193,7 +193,7 @@ pub(crate) fn parse_str_radix_10_exact(str: &str) -> Result<Decimal, Error> {
#[inline]
pub(crate) fn parse_str_scientific(str: &str) -> Result<Decimal, Error> {
decimal_parser::parse_scientific(str)
.map(|d| Decimal::from(d).normalize())
.map(Decimal::from)
.map_err(Error::from)
}

Expand Down

0 comments on commit e125131

Please sign in to comment.