Skip to content

Commit

Permalink
v0.4.6
Browse files Browse the repository at this point in the history
  • Loading branch information
akubera committed Oct 28, 2024
2 parents 369dfae + 2f2a072 commit 148b4cf
Show file tree
Hide file tree
Showing 18 changed files with 1,339 additions and 682 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "bigdecimal"
version = "0.4.5"
version = "0.4.6"
authors = ["Andrew Kubera"]
description = "Arbitrary precision decimal numbers"
documentation = "https://docs.rs/bigdecimal"
Expand Down Expand Up @@ -53,3 +53,6 @@ std = ["num-bigint/std", "num-integer/std", "num-traits/std"]
# BENCH: [[bench]]
# BENCH: name = "arithmetic"
# BENCH: harness = false

[lints.rust]
unexpected_cfgs = { level = "allow", check-cfg = ['cfg(no_track_caller)'] }
23 changes: 13 additions & 10 deletions benches/arithmetic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -331,14 +331,17 @@ pub fn criterion_benchmark(c: &mut Criterion) {
},
criterion::BatchSize::SmallInput));

c.bench_function(
"sqrt",
|b| b.iter_batched(
|| {
random_decimal.next()
},
|a| {
black_box(a.sqrt());
},
criterion::BatchSize::SmallInput));
let mut sqrt_group = c.benchmark_group("sqrt");
for prec in [10, 100, 1000, 10000] {
sqrt_group.bench_function(
format!("sqrt_prec_{prec}"),
|b| b.iter_batched(
|| {
(bigdecimal::Context::default().with_precision(std::num::NonZeroU64::new(prec).unwrap()), random_decimal.next())
},
|(ctx, a)| {
black_box(a.sqrt_with_context(&ctx));
},
criterion::BatchSize::SmallInput));
}
}
3 changes: 3 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ fn main() {
let ac = autocfg::new();
ac.emit_rustc_version(1, 70);

// slice::fill
ac.emit_rustc_version(1, 50);

// Option::zip
ac.emit_rustc_version(1, 46);

Expand Down
71 changes: 57 additions & 14 deletions src/arithmetic/addition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,12 @@ pub(crate) fn add_bigdecimals(
mut b: BigDecimal,
) -> BigDecimal {
if b.is_zero() {
if a.scale < b.scale {
a.int_val *= ten_to_the((b.scale - a.scale) as u64);
a.scale = b.scale;
}
a.extend_scale_to(b.scale);
return a;
}

if a.is_zero() {
if b.scale < a.scale {
b.int_val *= ten_to_the((a.scale - b.scale) as u64);
b.scale = a.scale;
}
b.extend_scale_to(a.scale);
return b;
}

Expand Down Expand Up @@ -51,23 +45,35 @@ fn add_aligned_bigdecimals(
pub(crate) fn add_bigdecimal_refs<'a, 'b, Lhs, Rhs>(
lhs: Lhs,
rhs: Rhs,
ctx: Option<&Context>,
) -> BigDecimal
where
Rhs: Into<BigDecimalRef<'a>>,
Lhs: Into<BigDecimalRef<'b>>,
{
use stdlib::cmp::Ordering::*;

let lhs = lhs.into();
let rhs = rhs.into();
if rhs.is_zero() {
return lhs.to_owned();
let scale_diff = rhs.scale.saturating_sub(lhs.scale).max(0).min(15);
return lhs.to_owned_with_scale(lhs.scale + scale_diff);
}
if lhs.is_zero() {
return rhs.to_owned();
let scale_diff = lhs.scale.saturating_sub(rhs.scale).max(0).min(15);
return rhs.to_owned_with_scale(rhs.scale + scale_diff);
}
if lhs.scale >= rhs.scale {
lhs.to_owned() + rhs
} else {
rhs.to_owned() + lhs

match lhs.scale.cmp(&rhs.scale) {
Equal => {
add_aligned_bigdecimal_ref_ref(lhs, rhs)
}
Greater => {
add_unaligned_bigdecimal_ref_ref(lhs, rhs, ctx)
}
Less => {
add_unaligned_bigdecimal_ref_ref(rhs, lhs, ctx)
}
}
}

Expand Down Expand Up @@ -108,3 +114,40 @@ pub(crate) fn addassign_bigdecimal_ref<'a, T: Into<BigDecimalRef<'a>>>(
}
}
}

/// Add BigDecimal references which have the same scale (integer addition)
fn add_aligned_bigdecimal_ref_ref(
lhs: BigDecimalRef, rhs: BigDecimalRef
) -> BigDecimal {
debug_assert!(!lhs.is_zero() && !rhs.is_zero());
debug_assert_eq!(lhs.scale, rhs.scale);

if lhs.digits.bits() >= rhs.digits.bits() {
lhs.to_owned() + rhs
} else {
rhs.to_owned() + lhs
}
}

fn add_unaligned_bigdecimal_ref_ref(
lhs: BigDecimalRef, rhs: BigDecimalRef, _ctx: Option<&Context>,
) -> BigDecimal {
debug_assert!(!lhs.is_zero() && !rhs.is_zero());
debug_assert!(lhs.scale >= rhs.scale);

let scale_diff = (lhs.scale - rhs.scale) as u64;

let shifted_rhs_digits = rhs.digits * ten_to_the_uint(scale_diff);
let shifted_rhs_int = BigInt::from_biguint(rhs.sign, shifted_rhs_digits);
let shifted_rhs = BigDecimal::new(shifted_rhs_int, lhs.scale);

shifted_rhs + lhs
}


#[cfg(test)]
mod test {
use super::*;

include!("addition.tests.rs");
}
52 changes: 52 additions & 0 deletions src/arithmetic/addition.tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
mod add_bigdecimals {
use super::*;
use paste::paste;

macro_rules! impl_case {
( $name:ident: $a:literal + $b:literal = $c:literal ) => {

#[test]
fn $name() {
let lhs: BigDecimal = $a.parse().unwrap();
let rhs: BigDecimal = $b.parse().unwrap();

let l_plus_r = add_bigdecimals(lhs.clone(), rhs.clone());
let r_plus_l = add_bigdecimals(rhs, lhs);

let expected: BigDecimal = $c.parse().unwrap();
assert_eq!(expected.int_val, l_plus_r.int_val);
assert_eq!(expected.scale, l_plus_r.scale);

assert_eq!(expected.int_val, r_plus_l.int_val);
assert_eq!(expected.scale, r_plus_l.scale);
}

paste! {
#[test]
fn [< $name _refs >]() {
let lhs: BigDecimal = $a.parse().unwrap();
let rhs: BigDecimal = $b.parse().unwrap();

let l_plus_r = add_bigdecimal_refs(&lhs, &rhs, None);
let r_plus_l = add_bigdecimal_refs(&rhs, &lhs, None);

let expected: BigDecimal = $c.parse().unwrap();
assert_eq!(expected.int_val, l_plus_r.int_val);
assert_eq!(expected.scale, l_plus_r.scale);

assert_eq!(expected.int_val, r_plus_l.int_val);
assert_eq!(expected.scale, r_plus_l.scale);
}
}
};
}

impl_case!(case_1d2345_123d45: "1.2345" + "123.45" = "124.6845");
impl_case!(case_123d43e5_1d2345: "123.43e5" + "1.2345" = "12343001.2345");

impl_case!(case_0_0: "0" + "0" = "0");
impl_case!(case_0_0d00: "0" + "0.00" = "0.00");
impl_case!(case_10_0d00: "10" + "0.00" = "10.00");
impl_case!(case_22132e2_0d0000: "22132e2" + "0.0000" = "2213200.0000");
impl_case!(case_n316d79_0en6: "-316.79" + "0e-6" = "-316.790000");
}
Loading

0 comments on commit 148b4cf

Please sign in to comment.