Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions arbi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ rand = { version = "0.8.5", optional = true }

[dev-dependencies]
rand = { version = "0.8.5", features = ["std_rng"] }
alloy-primitives = { version = "0.5" }

[package.metadata.docs.rs]
# RUSTDOCFLAGS="--html-in-header ./arbi/doc/header.html --cfg docsrs" cargo +nightly doc --no-deps --all-features
Expand Down
75 changes: 57 additions & 18 deletions arbi/src/add.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright 2024 Owain Davies
Copyright 2024-2025 Owain Davies
SPDX-License-Identifier: Apache-2.0 OR MIT
*/

Expand Down Expand Up @@ -460,7 +460,14 @@ mod tests {
let c = Arbi::from(DDigit::MAX);
let d = c.clone();

#[cfg(not(target_pointer_width = "64"))]
assert_eq!(d + c, 36893488147419103230_u128);
#[cfg(target_pointer_width = "64")]
assert_eq!(
d + c,
Arbi::from_str_radix("680564733841876926926749214863536422910", 10)
.unwrap()
);
}

#[test]
Expand Down Expand Up @@ -927,8 +934,10 @@ impl_arbi_add_for_primitive![
#[cfg(test)]
mod test_add_with_integral {
use super::*;
#[cfg(not(target_pointer_width = "64"))]
use crate::util::test::{get_seedable_rng, get_uniform_die, Distribution};
use crate::{SDDigit, SDigit, SQDigit};
#[cfg(not(target_pointer_width = "64"))]
use crate::{SDDigit, SDigit};

#[test]
fn test_add_zero() {
Expand Down Expand Up @@ -973,6 +982,7 @@ mod test_add_with_integral {
assert_eq!(rhs + a, expected);
}

#[cfg(not(target_pointer_width = "64"))]
#[test]
fn smoke() {
let (mut rng, _) = get_seedable_rng();
Expand Down Expand Up @@ -1011,6 +1021,7 @@ mod test_add_with_integral {
}

#[test]
#[cfg(not(target_pointer_width = "64"))]
fn smoke_3_to_4_digits() {
let (mut rng, _) = get_seedable_rng();
let die_sqdigit = get_uniform_die(SQDigit::MIN, SQDigit::MAX);
Expand Down Expand Up @@ -1108,33 +1119,58 @@ mod test_sub_with_integral {
let lhs = die_sddigit.sample(&mut rng);
let lhs_arbi = Arbi::from(lhs);
let rhs = die_sddigit.sample(&mut rng);
assert_eq!(&lhs_arbi - rhs, lhs as SQDigit - rhs as SQDigit);
assert_eq!(
&lhs_arbi - rhs,
SQDigit::try_from(lhs).unwrap()
- SQDigit::try_from(rhs).unwrap()
);
let rhs = die_sdigit.sample(&mut rng);
assert_eq!(lhs_arbi - rhs, lhs as SQDigit - rhs as SQDigit);
assert_eq!(
lhs_arbi - rhs,
SQDigit::try_from(lhs).unwrap()
- SQDigit::try_from(rhs).unwrap()
);

let lhs = die_sdigit.sample(&mut rng);
let lhs_arbi = Arbi::from(lhs);
let rhs = die_sdigit.sample(&mut rng);
assert_eq!(&lhs_arbi - rhs, lhs as SDDigit - rhs as SDDigit);
let rhs = die_sddigit.sample(&mut rng);
assert_eq!(lhs_arbi - rhs, lhs as SQDigit - rhs as SQDigit);
assert_eq!(
lhs_arbi - rhs,
SQDigit::try_from(lhs).unwrap()
- SQDigit::try_from(rhs).unwrap()
);

let lhs = die_sddigit.sample(&mut rng);
let lhs_arbi = Arbi::from(lhs);
let rhs = die_sddigit.sample(&mut rng);
assert_eq!(rhs - &lhs_arbi, rhs as SQDigit - lhs as SQDigit);
assert_eq!(
rhs - &lhs_arbi,
SQDigit::try_from(rhs).unwrap()
- SQDigit::try_from(lhs).unwrap()
);
let rhs = die_sdigit.sample(&mut rng);
assert_eq!(rhs - lhs_arbi, rhs as SQDigit - lhs as SQDigit);
assert_eq!(
rhs - lhs_arbi,
SQDigit::try_from(rhs).unwrap()
- SQDigit::try_from(lhs).unwrap()
);

let lhs = die_sdigit.sample(&mut rng);
let lhs_arbi = Arbi::from(lhs);
let rhs = die_sdigit.sample(&mut rng);
assert_eq!(rhs - &lhs_arbi, rhs as SDDigit - lhs as SDDigit);
let rhs = die_sddigit.sample(&mut rng);
assert_eq!(rhs - lhs_arbi, rhs as SQDigit - lhs as SQDigit);
assert_eq!(
rhs - lhs_arbi,
SQDigit::try_from(rhs).unwrap()
- SQDigit::try_from(lhs).unwrap()
);
}
}

#[cfg(not(target_pointer_width = "64"))]
#[test]
fn smoke_3_to_4_digits() {
let (mut rng, _) = get_seedable_rng();
Expand Down Expand Up @@ -1249,7 +1285,7 @@ impl Arbi {
let (digit, borrow_p) =
self.vec[i].overflowing_sub(sum as Digit + borrow);
self.vec[i] = digit;
borrow = u32::from(borrow_p);
borrow = Digit::from(borrow_p);
}
self.trim();
self.neg = false;
Expand All @@ -1268,7 +1304,7 @@ mod test_add3_abs_assign {
let b = 11334117686971261073_u64;
let c = 9795558189060012567_u64;
s.add3_abs_assign(&Arbi::from(a), &Arbi::from(b), &Arbi::from(c));
assert_eq!(s, (a as QDigit) + (b as QDigit) + (c as QDigit));
assert_eq!(s, QDigit::from(a) + QDigit::from(b) + QDigit::from(c));
}

#[test]
Expand All @@ -1278,7 +1314,7 @@ mod test_add3_abs_assign {
let b = 13975311186207392826_u64;
let c = 12301324174353418444_u64;
s.add3_abs_assign(&Arbi::from(a), &Arbi::from(b), &Arbi::from(c));
assert_eq!(s, (a as QDigit) + (b as QDigit) + (c as QDigit));
assert_eq!(s, QDigit::from(a) + QDigit::from(b) + QDigit::from(c));
}

#[test]
Expand All @@ -1288,7 +1324,7 @@ mod test_add3_abs_assign {
let b = 1619148075948679532_u64;
let c = 2567961127114686782_u64;
s.add3_abs_assign(&Arbi::from(a), &Arbi::from(b), &Arbi::from(c));
assert_eq!(s, (a as QDigit) + (b as QDigit) + (c as QDigit));
assert_eq!(s, QDigit::from(a) + QDigit::from(b) + QDigit::from(c));
}

#[test]
Expand All @@ -1301,7 +1337,7 @@ mod test_add3_abs_assign {
let b = die.sample(&mut rng);
let c = die.sample(&mut rng);
s.add3_abs_assign(&Arbi::from(a), &Arbi::from(b), &Arbi::from(c));
assert_eq!(s, (a as QDigit) + (b as QDigit) + (c as QDigit));
assert_eq!(s, QDigit::from(a) + QDigit::from(b) + QDigit::from(c));
}
}
}
Expand All @@ -1318,7 +1354,7 @@ mod test_sub_sum_of_abs_gt {
let b = 1986771123253152281_u64;
let mut slf = Arbi::from(s);
slf.sub_sum_of_abs_gt(&Arbi::from(a), &Arbi::from(b));
assert_eq!(slf, (s as QDigit) - (a as QDigit + b as QDigit));
assert_eq!(slf, QDigit::from(s) - (QDigit::from(a) + QDigit::from(b)));
}

#[test]
Expand All @@ -1328,7 +1364,7 @@ mod test_sub_sum_of_abs_gt {
let b = 3480730557869871236_u64;
let mut slf = Arbi::from(s);
slf.sub_sum_of_abs_gt(&Arbi::from(a), &Arbi::from(b));
assert_eq!(slf, (s as QDigit) - (a as QDigit + b as QDigit));
assert_eq!(slf, QDigit::from(s) - (QDigit::from(a) + QDigit::from(b)));
}

#[test]
Expand All @@ -1338,7 +1374,7 @@ mod test_sub_sum_of_abs_gt {
let b = 1329917829030286033_u64;
let mut slf = Arbi::from(s);
slf.sub_sum_of_abs_gt(&Arbi::from(a), &Arbi::from(b));
assert_eq!(slf, (s as QDigit) - (a as QDigit + b as QDigit));
assert_eq!(slf, QDigit::from(s) - (QDigit::from(a) + QDigit::from(b)));
}

#[test]
Expand All @@ -1349,12 +1385,15 @@ mod test_sub_sum_of_abs_gt {
let s = die.sample(&mut rng);
let a = die.sample(&mut rng);
let b = die.sample(&mut rng);
if (s as QDigit) < (a as QDigit + b as QDigit) {
if QDigit::from(s) < QDigit::from(a) + QDigit::from(b) {
continue;
}
let mut slf = Arbi::from(s);
slf.sub_sum_of_abs_gt(&Arbi::from(a), &Arbi::from(b));
assert_eq!(slf, (s as QDigit) - (a as QDigit + b as QDigit));
assert_eq!(
slf,
QDigit::from(s) - (QDigit::from(a) + QDigit::from(b))
);
}
}
}
13 changes: 10 additions & 3 deletions arbi/src/assign_integral.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,10 @@ impl_assign_from_primitive!(
#[cfg(test)]
mod tests {
use super::*;
use crate::{DDigit, QDigit};
use crate::DDigit;

#[cfg(not(target_pointer_width = "64"))]
use crate::QDigit;

#[test]
fn test_assign_from_primitive() {
Expand Down Expand Up @@ -164,8 +167,12 @@ mod tests {
assert_eq!(arbi, DDigit::MAX - 1);
arbi.assign(DDigit::MAX);
assert_eq!(arbi, DDigit::MAX);
arbi.assign(DDigit::MAX as QDigit + 1);
assert_eq!(arbi, DDigit::MAX as QDigit + 1);

#[cfg(not(target_pointer_width = "64"))]
{
arbi.assign(DDigit::MAX as QDigit + 1);
assert_eq!(arbi, DDigit::MAX as QDigit + 1);
}
}
}

Expand Down
4 changes: 2 additions & 2 deletions arbi/src/assign_string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ impl Arbi {
while pos < end {
match (base_digits[pos] as char).to_digit(base) {
Some(base_digit) => {
batch = base_digit + batch * base;
batch = base_digit as Digit + batch * base as Digit;
pos += 1;
}
None => return Err(ParseError::InvalidDigit),
Expand All @@ -246,7 +246,7 @@ impl Arbi {
while pos < end {
match (base_digits[pos] as char).to_digit(base) {
Some(base_digit) => {
batch = base_digit + batch * base;
batch = base_digit as Digit + batch * base as Digit;
pos += 1;
}
None => return Err(ParseError::InvalidDigit),
Expand Down
17 changes: 13 additions & 4 deletions arbi/src/bits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,10 @@ impl Arbi {
mod tests {
use crate::util::test::{get_seedable_rng, get_uniform_die, Distribution};
use crate::Arbi;
use crate::{BitCount, DDigit, Digit, QDigit, SDDigit, SDigit, SQDigit};
use crate::{BitCount, DDigit, Digit, SDDigit, SDigit};

#[cfg(not(target_pointer_width = "64"))]
use crate::{QDigit, SQDigit};

fn test_i128_bit(v: i128, i: u32) -> bool {
assert!(i < 128);
Expand Down Expand Up @@ -426,18 +429,24 @@ mod tests {
let die_digit = get_uniform_die(0, Digit::MAX);
let die_ddigit =
get_uniform_die(Digit::MAX as DDigit + 1, DDigit::MAX);
let die_qdigit =
get_uniform_die(DDigit::MAX as QDigit + 1, QDigit::MAX);
let die_sdigit = get_uniform_die(SDigit::MIN, SDigit::MAX);
let die_sddigit = get_uniform_die(SDDigit::MIN, SDDigit::MAX);

#[cfg(not(target_pointer_width = "64"))]
let die_qdigit =
get_uniform_die(DDigit::MAX as QDigit + 1, QDigit::MAX);
#[cfg(not(target_pointer_width = "64"))]
let die_sqdigit = get_uniform_die(SQDigit::MIN, SQDigit::MAX);

for _ in 0..i16::MAX {
test_bit_ops_for_type!(rng, die_digit);
test_bit_ops_for_type!(rng, die_ddigit);
test_bit_ops_for_type!(rng, die_qdigit);
test_bit_ops_for_type!(rng, die_sdigit);
test_bit_ops_for_type!(rng, die_sddigit);

#[cfg(not(target_pointer_width = "64"))]
test_bit_ops_for_type!(rng, die_qdigit);
#[cfg(not(target_pointer_width = "64"))]
test_bit_ops_for_type!(rng, die_sqdigit);
}
}
Expand Down
46 changes: 39 additions & 7 deletions arbi/src/builtin_int_methods/count_ones.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,23 @@ mod tests {
use crate::{Arbi, Assign};
use crate::{BitCount, DDigit, Digit, QDigit, SDDigit, SDigit, SQDigit};

macro_rules! assert_count_ones_big {
($value:expr, $T:ty) => {
#[allow(unused_comparisons)] // for unsigned types
{
let value = $value;
assert_eq!(
Arbi::from(value).count_ones(),
if value >= <$T>::try_from(0).unwrap() {
Some(BitCount::from(value.count_ones() as u32))
} else {
None
}
);
}
};
}

macro_rules! assert_count_ones {
($value:expr) => {
#[allow(unused_comparisons)] // for unsigned types
Expand All @@ -55,7 +72,7 @@ mod tests {
assert_eq!(
Arbi::from(value).count_ones(),
if value >= 0 {
Some(BitCount::from(value.count_ones()))
Some(BitCount::from(value.count_ones() as u32))
} else {
None
}
Expand All @@ -69,18 +86,32 @@ mod tests {
let (mut rng, _) = get_seedable_rng();
let die_d = get_uniform_die(Digit::MIN, Digit::MAX);
let die_dd = get_uniform_die(Digit::MAX as DDigit + 1, DDigit::MAX);
let die_qd = get_uniform_die(DDigit::MAX as QDigit + 1, QDigit::MAX);
let die_qd = crate::util::qdigit::get_uniform_qdigit_die(
QDigit::from(DDigit::MAX) + QDigit::from(1u8),
QDigit::MAX,
);
let die_sd = get_uniform_die(SDigit::MIN, SDigit::MAX);
let die_sdd = get_uniform_die(SDDigit::MIN, SDDigit::MAX);
let die_sqd = get_uniform_die(SQDigit::MIN, SQDigit::MAX);
let die_sqd = crate::util::qdigit::get_uniform_sqdigit_die(
SQDigit::MIN,
SQDigit::MAX,
);

for _ in 0..i16::MAX {
assert_count_ones!(die_d.sample(&mut rng));
assert_count_ones!(die_dd.sample(&mut rng));
assert_count_ones!(die_qd.sample(&mut rng));
assert_count_ones!(die_sd.sample(&mut rng));
assert_count_ones!(die_sdd.sample(&mut rng));
assert_count_ones!(die_sqd.sample(&mut rng));
#[cfg(not(target_pointer_width = "64"))]
{
assert_count_ones!(die_qd.sample(&mut rng));
assert_count_ones!(die_sqd.sample(&mut rng));
}
#[cfg(target_pointer_width = "64")]
{
assert_count_ones_big!(die_qd.sample(&mut rng), QDigit);
assert_count_ones_big!(die_sqd.sample(&mut rng), SQDigit);
}
}
}

Expand Down Expand Up @@ -119,10 +150,11 @@ mod tests {
Some(BitCount::from(DDigit::MAX.count_ones()))
);

a.assign(DDigit::MAX as QDigit + 1);
a = Arbi::from(QDigit::from(DDigit::MAX) + QDigit::from(1));
assert_eq!(
a.count_ones(),
Some(BitCount::from((DDigit::MAX as QDigit + 1).count_ones()))
Some((QDigit::from(DDigit::MAX) + QDigit::from(1)).count_ones()
as BitCount)
);
}
}
Loading
Loading