mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2024-12-26 16:11:07 +00:00
158 lines
4.5 KiB
Rust
158 lines
4.5 KiB
Rust
use num_bigint::BigInt;
|
|
use num_bigint::Sign::Plus;
|
|
use num_traits::{One, Signed, ToPrimitive, Zero};
|
|
|
|
use std::ops::Neg;
|
|
use std::panic::catch_unwind;
|
|
|
|
mod consts;
|
|
use crate::consts::*;
|
|
|
|
#[macro_use]
|
|
mod macros;
|
|
|
|
#[test]
|
|
fn test_scalar_add() {
|
|
fn check(x: &BigInt, y: &BigInt, z: &BigInt) {
|
|
let (x, y, z) = (x.clone(), y.clone(), z.clone());
|
|
assert_signed_scalar_op!(x + y == z);
|
|
assert_signed_scalar_assign_op!(x += y == z);
|
|
}
|
|
|
|
for elm in SUM_TRIPLES.iter() {
|
|
let (a_vec, b_vec, c_vec) = *elm;
|
|
let a = BigInt::from_slice(Plus, a_vec);
|
|
let b = BigInt::from_slice(Plus, b_vec);
|
|
let c = BigInt::from_slice(Plus, c_vec);
|
|
let (na, nb, nc) = (-&a, -&b, -&c);
|
|
|
|
check(&a, &b, &c);
|
|
check(&b, &a, &c);
|
|
check(&c, &na, &b);
|
|
check(&c, &nb, &a);
|
|
check(&a, &nc, &nb);
|
|
check(&b, &nc, &na);
|
|
check(&na, &nb, &nc);
|
|
check(&a, &na, &Zero::zero());
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_scalar_sub() {
|
|
fn check(x: &BigInt, y: &BigInt, z: &BigInt) {
|
|
let (x, y, z) = (x.clone(), y.clone(), z.clone());
|
|
assert_signed_scalar_op!(x - y == z);
|
|
assert_signed_scalar_assign_op!(x -= y == z);
|
|
}
|
|
|
|
for elm in SUM_TRIPLES.iter() {
|
|
let (a_vec, b_vec, c_vec) = *elm;
|
|
let a = BigInt::from_slice(Plus, a_vec);
|
|
let b = BigInt::from_slice(Plus, b_vec);
|
|
let c = BigInt::from_slice(Plus, c_vec);
|
|
let (na, nb, nc) = (-&a, -&b, -&c);
|
|
|
|
check(&c, &a, &b);
|
|
check(&c, &b, &a);
|
|
check(&nb, &a, &nc);
|
|
check(&na, &b, &nc);
|
|
check(&b, &na, &c);
|
|
check(&a, &nb, &c);
|
|
check(&nc, &na, &nb);
|
|
check(&a, &a, &Zero::zero());
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_scalar_mul() {
|
|
fn check(x: &BigInt, y: &BigInt, z: &BigInt) {
|
|
let (x, y, z) = (x.clone(), y.clone(), z.clone());
|
|
assert_signed_scalar_op!(x * y == z);
|
|
assert_signed_scalar_assign_op!(x *= y == z);
|
|
}
|
|
|
|
for elm in MUL_TRIPLES.iter() {
|
|
let (a_vec, b_vec, c_vec) = *elm;
|
|
let a = BigInt::from_slice(Plus, a_vec);
|
|
let b = BigInt::from_slice(Plus, b_vec);
|
|
let c = BigInt::from_slice(Plus, c_vec);
|
|
let (na, nb, nc) = (-&a, -&b, -&c);
|
|
|
|
check(&a, &b, &c);
|
|
check(&b, &a, &c);
|
|
check(&na, &nb, &c);
|
|
|
|
check(&na, &b, &nc);
|
|
check(&nb, &a, &nc);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_scalar_div_rem() {
|
|
fn check_sub(a: &BigInt, b: u32, ans_q: &BigInt, ans_r: &BigInt) {
|
|
let (q, r) = (a / b, a % b);
|
|
if !r.is_zero() {
|
|
assert_eq!(r.sign(), a.sign());
|
|
}
|
|
assert!(r.abs() <= BigInt::from(b));
|
|
assert!(*a == b * &q + &r);
|
|
assert!(q == *ans_q);
|
|
assert!(r == *ans_r);
|
|
|
|
let b = BigInt::from(b);
|
|
let (a, ans_q, ans_r) = (a.clone(), ans_q.clone(), ans_r.clone());
|
|
assert_signed_scalar_op!(a / b == ans_q);
|
|
assert_signed_scalar_op!(a % b == ans_r);
|
|
assert_signed_scalar_assign_op!(a /= b == ans_q);
|
|
assert_signed_scalar_assign_op!(a %= b == ans_r);
|
|
|
|
let nb = -b;
|
|
assert_signed_scalar_op!(a / nb == -ans_q.clone());
|
|
assert_signed_scalar_op!(a % nb == ans_r);
|
|
assert_signed_scalar_assign_op!(a /= nb == -ans_q.clone());
|
|
assert_signed_scalar_assign_op!(a %= nb == ans_r);
|
|
}
|
|
|
|
fn check(a: &BigInt, b: u32, q: &BigInt, r: &BigInt) {
|
|
check_sub(a, b, q, r);
|
|
check_sub(&a.neg(), b, &q.neg(), &r.neg());
|
|
}
|
|
|
|
for elm in MUL_TRIPLES.iter() {
|
|
let (a_vec, b_vec, c_vec) = *elm;
|
|
let a = BigInt::from_slice(Plus, a_vec);
|
|
let b = BigInt::from_slice(Plus, b_vec);
|
|
let c = BigInt::from_slice(Plus, c_vec);
|
|
|
|
if a_vec.len() == 1 && a_vec[0] != 0 {
|
|
let a = a_vec[0];
|
|
check(&c, a, &b, &Zero::zero());
|
|
}
|
|
|
|
if b_vec.len() == 1 && b_vec[0] != 0 {
|
|
let b = b_vec[0];
|
|
check(&c, b, &a, &Zero::zero());
|
|
}
|
|
}
|
|
|
|
for elm in DIV_REM_QUADRUPLES.iter() {
|
|
let (a_vec, b_vec, c_vec, d_vec) = *elm;
|
|
let a = BigInt::from_slice(Plus, a_vec);
|
|
let c = BigInt::from_slice(Plus, c_vec);
|
|
let d = BigInt::from_slice(Plus, d_vec);
|
|
|
|
if b_vec.len() == 1 && b_vec[0] != 0 {
|
|
let b = b_vec[0];
|
|
check(&a, b, &c, &d);
|
|
}
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_scalar_div_rem_zero() {
|
|
catch_unwind(|| BigInt::zero() / 0u32).unwrap_err();
|
|
catch_unwind(|| BigInt::zero() % 0u32).unwrap_err();
|
|
catch_unwind(|| BigInt::one() / 0u32).unwrap_err();
|
|
catch_unwind(|| BigInt::one() % 0u32).unwrap_err();
|
|
}
|