use unsigned::add::unsafe_addition; pub fn subtract(res: &mut [u64], spare: &mut [u64], other: &mut [u64]) { for i in 0..res.len() { other[i] = !other[i]; } spare[0] = 1; unsafe_addition(other, &spare, true); unsafe_addition(res, &other, true); } macro_rules! subtraction_impls { ($name: ident, $size: expr) => { impl SubAssign for $name { fn sub_assign(&mut self, rhs: $name) { let mut temp = [0; $size]; subtract(&mut self.value, &mut temp, &mut rhs.value.clone()); } } impl<'a> SubAssign<&'a $name> for $name { fn sub_assign(&mut self, rhs: &$name) { let mut temp = [0; $size]; subtract(&mut self.value, &mut temp, &mut rhs.value.clone()); } } impl Sub for $name { type Output = $name; fn sub(self, rhs: $name) -> $name { let mut res = self.clone(); let mut temp = [0; $size]; subtract(&mut res.value, &mut temp, &mut rhs.value.clone()); res } } impl<'a> Sub<$name> for &'a $name { type Output = $name; fn sub(self, rhs: $name) -> $name { let mut res = self.clone(); let mut temp = [0; $size]; subtract(&mut res.value, &mut temp, &mut rhs.value.clone()); res } } impl<'a> Sub<&'a $name> for $name { type Output = $name; fn sub(self, rhs: &$name) -> $name { let mut res = self.clone(); let mut temp = [0; $size]; subtract(&mut res.value, &mut temp, &mut rhs.value.clone()); res } } impl<'a,'b> Sub<&'a $name> for &'b $name { type Output = $name; fn sub(self, rhs: &$name) -> $name { let mut res = self.clone(); let mut temp = [0; $size]; subtract(&mut res.value, &mut temp, &mut rhs.value.clone()); res } } } } #[cfg(test)] macro_rules! generate_sub_tests { ($name: ident, $lname: ident) => { #[test] fn $lname() { generate_sub_tests!(body $name, $lname); } }; (ignore $name: ident, $lname: ident) => { #[test] #[ignore] fn $lname() { generate_sub_tests!(body $name, $lname); } }; (body $name: ident, $lname: ident) => { let fname = build_test_path("sub", stringify!($name)); run_test(fname.to_string(), 3, |case| { let (neg0, abytes) = case.get("a").unwrap(); let (neg1, bbytes) = case.get("b").unwrap(); let (neg2, cbytes) = case.get("c").unwrap(); assert!(!neg0 && !neg1 && !neg2); let mut a = $name::from_bytes(abytes); let b = $name::from_bytes(bbytes); let c = $name::from_bytes(cbytes); assert_eq!(c, &a - &b); a -= b; assert_eq!(c, a); }); }; }