Skip to content

Commit cbb41d1

Browse files
committed
Add safefloat tests for div and mul_div
1 parent f616e11 commit cbb41d1

File tree

1 file changed

+100
-9
lines changed
  • primitives/share-pool/src

1 file changed

+100
-9
lines changed

primitives/share-pool/src/lib.rs

Lines changed: 100 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -75,13 +75,13 @@ impl SafeFloat {
7575

7676
let mut safe_float = SafeFloat { mantissa, exponent };
7777

78-
safe_float.adjust_precision();
78+
safe_float.normalize();
7979
Some(safe_float)
8080
}
8181

8282
/// Adjusts mantissa and exponent of this floating point number so that
8383
/// SAFE_FLOAT_MAX <= mantissa < 10 * SAFE_FLOAT_MAX
84-
pub(crate) fn adjust_precision(&mut self) {
84+
pub(crate) fn normalize(&mut self) {
8585
let max_value = SafeInt::from(SAFE_FLOAT_MAX);
8686
let max_value_div10 = SafeInt::from(SAFE_FLOAT_MAX.checked_div(10).unwrap_or_default());
8787
let mantissa_abs = self.mantissa.clone().abs();
@@ -129,7 +129,7 @@ impl SafeFloat {
129129
.saturating_sub(a.exponent)
130130
.saturating_sub(redundant_exponent),
131131
};
132-
safe_float.adjust_precision();
132+
safe_float.normalize();
133133
Some(safe_float)
134134
} else {
135135
None
@@ -148,7 +148,7 @@ impl SafeFloat {
148148
mantissa: unnormalized_mantissa,
149149
exponent: exponent_offset.neg(),
150150
};
151-
safe_float.adjust_precision();
151+
safe_float.normalize();
152152
safe_float
153153
}
154154

@@ -725,7 +725,7 @@ mod tests {
725725
}
726726

727727
#[test]
728-
fn test_safefloat_adjust_precision() {
728+
fn test_safefloat_normalize() {
729729
// Test case: mantissa, exponent, expected mantissa, expected exponent
730730
[
731731
(1_u128, 0, 100_000_000_000_000_000_000_u128, -20_i64),
@@ -933,15 +933,106 @@ mod tests {
933933
});
934934
}
935935

936+
#[test]
937+
fn test_safefloat_div_by_zero_is_none() {
938+
let a = SafeFloat::new(SafeInt::from(1), 0).unwrap();
939+
assert!(a.div(&SafeFloat::zero()).is_none());
940+
}
941+
936942
#[test]
937943
fn test_safefloat_div() {
938-
todo!()
939-
// Test with f64
944+
// Test case: man_a, exp_a, man_b, exp_b
945+
[
946+
(1_u128, 0_i64, 100_000_000_000_000_000_000_u128, -20_i64),
947+
(1_u128, 0, 1_u128, 0),
948+
(1_u128, 1, 1_u128, 0),
949+
(1_u128, 7, 1_u128, 0),
950+
(1_u128, 50, 1_u128, 0),
951+
(1_u128, 100, 1_u128, 0),
952+
(1_u128, 0, 7_u128, 0),
953+
(1_u128, 1, 7_u128, 0),
954+
(1_u128, 7, 7_u128, 0),
955+
(1_u128, 50, 7_u128, 0),
956+
(1_u128, 100, 7_u128, 0),
957+
(1_u128, 0, 3_u128, 0),
958+
(1_u128, 1, 3_u128, 0),
959+
(1_u128, 7, 3_u128, 0),
960+
(1_u128, 50, 3_u128, 0),
961+
(1_u128, 100, 3_u128, 0),
962+
(2_u128, 0, 3_u128, 0),
963+
(2_u128, 1, 3_u128, 0),
964+
(2_u128, 7, 3_u128, 0),
965+
(2_u128, 50, 3_u128, 0),
966+
(2_u128, 100, 3_u128, 0),
967+
(5_u128, 0, 3_u128, 0),
968+
(5_u128, 1, 3_u128, 0),
969+
(5_u128, 7, 3_u128, 0),
970+
(5_u128, 50, 3_u128, 0),
971+
(5_u128, 100, 3_u128, 0),
972+
(10_u128, 0, 100_000_000_000_000_000_000_u128, -19),
973+
(1_000_u128, 0, 100_000_000_000_000_000_000_u128, -17),
974+
(
975+
100_000_000_000_000_000_000_u128,
976+
0,
977+
1_000_000_000_000_000_000_000_u128,
978+
-1,
979+
),
980+
(SAFE_FLOAT_MAX, 0, SAFE_FLOAT_MAX, 0),
981+
(SAFE_FLOAT_MAX, 100, SAFE_FLOAT_MAX, -100),
982+
(SAFE_FLOAT_MAX, 100, SAFE_FLOAT_MAX-1, -100),
983+
(SAFE_FLOAT_MAX-1, 100, SAFE_FLOAT_MAX, -100),
984+
(SAFE_FLOAT_MAX-2, 100, SAFE_FLOAT_MAX, -100),
985+
(SAFE_FLOAT_MAX, 100, SAFE_FLOAT_MAX/2 - 1, -100),
986+
(SAFE_FLOAT_MAX, 100, SAFE_FLOAT_MAX/2 - 1, 100),
987+
(1_u128, 0, 100_000_000_000_000_000_000_u128, -20_i64),
988+
(123_456_789_123_456_789_123_u128, 20_i64, 87_654_321_987_654_321_987_u128, -20_i64),
989+
(123_456_789_123_456_789_123_u128, 100_i64, 87_654_321_987_654_321_987_u128, -100_i64),
990+
(123_456_789_123_456_789_123_u128, -100_i64, 87_654_321_987_654_321_987_u128, 100_i64),
991+
(123_456_789_123_456_789_123_u128, -99_i64, 87_654_321_987_654_321_987_u128, 99_i64),
992+
(123_456_789_123_456_789_123_u128, 123_i64, 87_654_321_987_654_321_987_u128, -32_i64),
993+
(123_456_789_123_456_789_123_u128, -123_i64, 87_654_321_987_654_321_987_u128, 32_i64),
994+
]
995+
.into_iter()
996+
.for_each(|(ma, ea, mb, eb)| {
997+
let a = SafeFloat::new(SafeInt::from(ma), ea).unwrap();
998+
let b = SafeFloat::new(SafeInt::from(mb), eb).unwrap();
999+
1000+
let actual: f64 = a.div(&b).unwrap().into();
1001+
let expected = ma as f64 * (10_f64).powi(ea as i32) / (mb as f64 * (10_f64).powi(eb as i32));
1002+
1003+
assert_abs_diff_eq!(
1004+
actual,
1005+
expected,
1006+
epsilon = actual / 100_000_000_000_000_f64
1007+
);
1008+
});
9401009
}
9411010

9421011
#[test]
9431012
fn test_safefloat_mul_div() {
944-
todo!()
945-
// Test with f64
1013+
// result = a * b / c
1014+
// should not lose precision gained in a * b
1015+
// Test case: man_a, exp_a, man_b, exp_b, man_c, exp_c
1016+
[
1017+
(1_u128, -20_i64, 1_u128, -20_i64, 1_u128, -20_i64),
1018+
(123_u128, 20_i64, 123_u128, -20_i64, 321_u128, 0_i64),
1019+
(123_123_123_123_123_123_u128, 20_i64, 321_321_321_321_321_321_u128, -20_i64, 777_777_777_777_777_777_u128, 0_i64),
1020+
(11_111_111_111_111_111_111_u128, 20_i64, 99_321_321_321_321_321_321_u128, -20_i64, 77_777_777_777_777_777_777_u128, 0_i64),
1021+
]
1022+
.into_iter()
1023+
.for_each(|(ma, ea, mb, eb, mc, ec)| {
1024+
let a = SafeFloat::new(SafeInt::from(ma), ea).unwrap();
1025+
let b = SafeFloat::new(SafeInt::from(mb), eb).unwrap();
1026+
let c = SafeFloat::new(SafeInt::from(mc), ec).unwrap();
1027+
1028+
let actual: f64 = a.mul_div(&b, &c).unwrap().into();
1029+
let expected = (ma as f64 * (10_f64).powi(ea as i32)) * (mb as f64 * (10_f64).powi(eb as i32)) / (mc as f64 * (10_f64).powi(ec as i32));
1030+
1031+
assert_abs_diff_eq!(
1032+
actual,
1033+
expected,
1034+
epsilon = actual / 100_000_000_000_000_f64
1035+
);
1036+
});
9461037
}
9471038
}

0 commit comments

Comments
 (0)