#[cfg(test)]
use fixed_bigint::FixedUInt as Bn;
use num_traits::{FromPrimitive, ToPrimitive};
use std::ops::{Div, Mul};
#[test]
fn test_mul() {
let a: Bn<u8, 1> = 2u8.into();
let b: Bn<u8, 1> = 3u8.into();
assert_eq!(a * b, 6u8.into());
assert_eq!(a.mul(b), 6u8.into());
let a = Bn::<u8, 2>::from_u64(3).unwrap();
let b = Bn::<u8, 2>::from_u64(4).unwrap();
let r = a * b;
assert_eq!(r.to_u16().unwrap(), 12);
let a = Bn::<u8, 2>::from_u64(300).unwrap();
let b = Bn::<u8, 2>::from_u64(4).unwrap();
let r = a * b;
assert_eq!(r.to_u64().unwrap(), 1200);
let tests = [
(0x010203u64, 0x1020u64, 0x10407060u64),
(42, 0, 0),
(42, 1, 42),
(42, 2, 84),
(42, 10, 420),
(42, 100, 4200),
(420, 1000, 420000),
(200, 8, 1600),
(2, 256, 512),
(500, 2, 1000),
(500000, 2, 1000000),
(500, 500, 250000),
(1000000000, 2, 2000000000),
(2, 1000000000, 2000000000),
(1000000000, 4, 4000000000),
];
for (a, b, res) in &tests {
let b_a = Bn::<u8, 8>::from_u64(*a).unwrap();
let b_b = Bn::<u8, 8>::from_u64(*b).unwrap();
let b_res = b_a * b_b;
assert_eq!(b_res.to_u64().unwrap(), *res);
}
for (a, b, res) in &tests {
let b_a = Bn::<u32, 2>::from_u64(*a).unwrap();
let b_b = Bn::<u32, 2>::from_u64(*b).unwrap();
let b_res = b_a * b_b;
assert_eq!(b_res.to_u64().unwrap(), *res);
}
}
#[test]
fn test_div() {
let a: Bn<u8, 1> = 6u8.into();
let b: Bn<u8, 1> = 3u8.into();
assert_eq!(a / b, 2u8.into());
assert_eq!(a.div(b), 2u8.into());
fn test_div_1<BN: num_traits::PrimInt + num_traits::NumAssign + num_traits::NumAssignRef>()
where
BN::FromStrRadixErr: core::fmt::Debug,
{
let tests = [
("0", "00000002", 0),
("00000010", "00000002", 0x8),
("0000001b", "00000003", 0x9),
("0000012C", "00000064", 3),
("00015F90", "0000012C", 0x12C),
];
for (a, b, res) in &tests {
let f = BN::from_str_radix(a, 16).unwrap();
let g = BN::from_str_radix(b, 16).unwrap();
let e = f / g;
assert_eq!(e.to_u64().unwrap(), *res);
let e = f.div(g);
assert_eq!(e.to_u64().unwrap(), *res);
let mut x = f;
x /= g;
assert_eq!(x.to_u64().unwrap(), *res);
let mut x = f;
let gref = &g;
x /= gref;
assert_eq!(x.to_u64().unwrap(), *res);
}
}
test_div_1::<Bn<u8, 8>>();
test_div_1::<Bn<u16, 4>>();
test_div_1::<Bn<u32, 2>>();
}
#[test]
fn test_rem() {
fn test_rem_1<BN: num_traits::PrimInt + num_traits::FromPrimitive>() {
let tests = [
(10u64, 3u64, 1u64),
(256, 256, 0),
(256, 1, 0),
(256, 255, 1),
(255, 256, 255),
(4_294_967_295, 65536, 65535),
];
for (a, b, res) in &tests {
let cmp = a % b;
assert_eq!(*res, cmp);
let f = BN::from_u64(*a).unwrap();
let g = BN::from_u64(*b).unwrap();
let e = f % g;
assert_eq!(*res, e.to_u64().unwrap());
}
}
test_rem_1::<Bn<u8, 8>>();
test_rem_1::<Bn<u16, 4>>();
test_rem_1::<Bn<u32, 2>>();
}
#[test]
fn test_overflowing_mul() {
fn test_8_bit<
INT: num_traits::PrimInt
+ num_traits::ops::overflowing::OverflowingMul
+ core::fmt::Debug
+ core::convert::From<u8>,
>() {
let a: INT = 2.into();
let b: INT = 3.into();
let c: INT = 130.into();
assert_eq!(a.overflowing_mul(&b), (6.into(), false));
assert_eq!(a.overflowing_mul(&c), (4.into(), true));
assert_eq!(Into::<INT>::into(128).overflowing_mul(&a), (0.into(), true));
assert_eq!(
Into::<INT>::into(127).overflowing_mul(&a),
(254.into(), false)
);
}
test_8_bit::<u8>();
test_8_bit::<Bn<u8, 1>>();
fn test_16_bit<
INT: num_traits::PrimInt
+ num_traits::ops::overflowing::OverflowingMul
+ num_traits::WrappingMul
+ num_traits::SaturatingMul
+ core::fmt::Debug
+ core::convert::From<u16>,
>() {
let a: INT = 2.into();
let b: INT = 3.into();
let c: INT = 32770.into();
assert_eq!(a.overflowing_mul(&b), (6.into(), false));
assert_eq!(a.overflowing_mul(&c), (4.into(), true));
assert_eq!(c.overflowing_mul(&a), (4.into(), true));
assert_eq!(
Into::<INT>::into(32768).overflowing_mul(&a),
(0.into(), true)
);
assert_eq!(
Into::<INT>::into(32767).overflowing_mul(&a),
(65534.into(), false)
);
let tests = [
(0u16, 0u16, 0u16, false),
(2, 3, 6, false),
(2, 32767, 65534, false),
(2, 32768, 0, true),
(2, 32770, 4, true),
(255, 255, 65025, false),
(255, 256, 65280, false),
(256, 256, 0, true),
(256, 257, 256, true),
(257, 257, 513, true),
];
for (a, b, res, overflow) in &tests {
let ac: INT = (*a).into();
let bc: INT = (*b).into();
assert_eq!(ac.overflowing_mul(&bc), ((*res).into(), *overflow));
assert_eq!(bc.overflowing_mul(&ac), ((*res).into(), *overflow));
assert_eq!(ac.wrapping_mul(&bc), (*res).into());
let checked = ac.checked_mul(&bc);
let saturating = ac.saturating_mul(&bc);
if *overflow {
assert_eq!(checked, None);
assert_eq!(saturating, INT::max_value());
} else {
assert_eq!(checked, Some((*res).into()));
assert_eq!(saturating, (*res).into())
}
}
}
test_16_bit::<u16>();
test_16_bit::<Bn<u8, 2>>();
test_16_bit::<Bn<u16, 1>>();
fn test_32_bit<
INT: num_traits::PrimInt
+ num_traits::ops::overflowing::OverflowingMul
+ num_traits::WrappingMul
+ num_traits::SaturatingMul
+ core::fmt::Debug
+ core::convert::From<u32>,
>() {
let a: INT = 2.into();
let b: INT = 3.into();
let c: INT = 2147483650.into();
assert_eq!(a.overflowing_mul(&b), (6.into(), false));
assert_eq!(a.overflowing_mul(&c), (4.into(), true));
assert_eq!(c.overflowing_mul(&a), (4.into(), true));
let tests = [
(0u32, 0u32, 0u32, false),
(2, 3, 6, false),
(2, 2_147_483_647, 4_294_967_294, false),
(2, 2_147_483_648, 0, true),
(2, 2_147_483_650, 4, true),
(65535, 65535, 4_294_836_225, false),
(65535, 65536, 4_294_901_760, false),
(65536, 65536, 0, true),
(65536, 65537, 65536, true),
(65537, 65537, 131073, true),
];
for (a, b, res, overflow) in &tests {
let ac: INT = (*a).into();
let bc: INT = (*b).into();
assert_eq!(ac.overflowing_mul(&bc), ((*res).into(), *overflow));
assert_eq!(ac.wrapping_mul(&bc), (*res).into());
let checked = ac.checked_mul(&bc);
let saturating = ac.saturating_mul(&bc);
if *overflow {
assert_eq!(checked, None);
assert_eq!(saturating, INT::max_value());
} else {
assert_eq!(checked, Some((*res).into()));
assert_eq!(saturating, (*res).into())
}
}
}
test_32_bit::<u32>();
test_32_bit::<Bn<u16, 2>>();
test_32_bit::<Bn<u8, 4>>();
}
#[test]
fn test_key_range_mul() {
fn test_key_values<
REF: num_traits::PrimInt + num_traits::ops::overflowing::OverflowingMul + core::fmt::Debug,
INT: num_traits::PrimInt + num_traits::ops::overflowing::OverflowingMul + core::fmt::Debug,
>()
where
INT: core::convert::From<REF>,
{
let mut test_values = Vec::new();
test_values.push(REF::zero());
test_values.push(REF::one());
let mut power_of_2 = REF::one();
for _ in 0..4 {
if power_of_2 < REF::max_value() / (REF::one() + REF::one()) {
test_values.push(power_of_2);
test_values.push(power_of_2 + REF::one());
if power_of_2 > REF::zero() {
test_values.push(power_of_2 - REF::one());
}
power_of_2 = power_of_2 + power_of_2; }
}
let max_val = REF::max_value();
test_values.push(max_val / (REF::one() + REF::one()));
test_values.push(max_val);
test_values.sort();
test_values.dedup();
for &i in &test_values {
for &j in &test_values {
let ref_val = i.overflowing_mul(&j);
let lhs: INT = i.into();
let rhs: INT = j.into();
let int_val = lhs.overflowing_mul(&rhs);
assert_eq!(
int_val,
(ref_val.0.into(), ref_val.1),
"Failed for {:?} * {:?}",
i,
j
);
}
}
}
test_key_values::<u8, Bn<u8, 1>>();
test_key_values::<u16, Bn<u16, 1>>();
test_key_values::<u16, Bn<u8, 2>>();
test_key_values::<u32, Bn<u32, 1>>();
test_key_values::<u32, Bn<u16, 2>>();
test_key_values::<u32, Bn<u8, 4>>();
}
#[test]
fn test_checked_div() {
fn test<
INT: num_traits::PrimInt
+ core::fmt::Debug
+ num_traits::CheckedDiv
+ num_traits::CheckedRem
+ core::convert::From<u8>,
>() {
let a: INT = 2.into();
let b: INT = 0.into();
assert_eq!(Into::<INT>::into(128).checked_div(&a), Some(64.into()));
assert_eq!(Into::<INT>::into(128).checked_div(&b), None);
assert_eq!(Into::<INT>::into(0).checked_div(&b), None);
assert_eq!(Into::<INT>::into(0).checked_div(&a), Some(0.into()));
assert_eq!(Into::<INT>::into(127).checked_rem(&a), Some(1.into()));
assert_eq!(Into::<INT>::into(127).checked_rem(&b), None);
assert_eq!(Into::<INT>::into(0).checked_rem(&b), None);
assert_eq!(Into::<INT>::into(0).checked_rem(&a), Some(0.into()));
}
test::<u8>();
test::<Bn<u8, 1>>();
test::<u16>();
test::<Bn<u16, 1>>();
test::<Bn<u8, 2>>();
test::<u32>();
test::<Bn<u32, 1>>();
test::<Bn<u16, 2>>();
test::<Bn<u8, 4>>();
}