nanvm_lib/vm/bigint/
sub.rs1use core::ops::Sub;
2
3use crate::vm::{Any, BigInt, IVm};
4
5impl<A: IVm> Sub for BigInt<A> {
8 type Output = Result<Self, Any<A>>;
9 fn sub(self, rhs: Self) -> Self::Output {
10 let rhs_sign = rhs.sign().flip();
11 self.add_signed(rhs, rhs_sign).within_limit()
12 }
13}
14
15#[cfg(test)]
16mod tests {
17 use crate::vm::{
18 bigint::test_util::{T, int, pos, pow2},
19 error,
20 };
21
22 #[test]
23 fn same_signs_rhs_magnitude_greater() {
24 assert_eq!(int(3) - int(5), Ok(int(-2)));
25 assert_eq!(int(-3) - int(-5), Ok(int(2)));
26 }
27
28 #[test]
29 fn same_signs_lhs_magnitude_greater() {
30 assert_eq!(int(5) - int(3), Ok(int(2)));
31 assert_eq!(int(-5) - int(-3), Ok(int(-2)));
32 }
33
34 #[test]
35 fn cancellation_to_zero() {
36 assert_eq!(int(7) - int(7), Ok(T::default()));
37 assert_eq!(int(-7) - int(-7), Ok(T::default()));
38 }
39
40 #[test]
41 fn different_signs() {
42 assert_eq!(int(3) - int(-5), Ok(int(8)));
43 assert_eq!(int(-3) - int(5), Ok(int(-8)));
44 }
45
46 #[test]
47 fn multi_word_borrow() {
48 let a = pos([0, 1]);
50 let b: T = 1u64.into();
51 let expected: T = u64::MAX.into();
52 assert_eq!(a - b, Ok(expected));
53 }
54
55 #[test]
57 fn difference_at_and_past_the_limit() {
58 assert_eq!(pow2(1_048_575) - int(0), Ok(pow2(1_048_575)));
59 assert_eq!(
60 pow2(1_048_575) - -pow2(1_048_575),
61 Err(error::bigint_too_large())
62 );
63 assert_eq!(
64 -pow2(1_048_575) - pow2(1_048_575),
65 Err(error::bigint_too_large())
66 );
67 }
68}