use dashu_int::fast_div::ConstDivisor; use num_modular::Reducer; mod helper_macros; #[test] fn test_reducer_add() { let reducer = ConstDivisor::new(ubig!(1234)); let small_cases = [ (ubig!(0), ubig!(0), ubig!(0)), (ubig!(0), ubig!(1), ubig!(1)), (ubig!(1), ubig!(2), ubig!(3)), (ubig!(1000), ubig!(2000), ubig!(3000)), ]; for (a, b, c) in small_cases { assert_eq!(reducer.add(&reducer.transform(a), &reducer.transform(b)), reducer.transform(c)); } let reducer = ConstDivisor::new(ubig!(0x1234567890123456789012345678901234567890)); let large_cases = [ (ubig!(0), ubig!(0), ubig!(0)), (ubig!(0), ubig!(1), ubig!(1)), (ubig!(1), ubig!(2), ubig!(3)), (ubig!(0x1000), ubig!(0x2000), ubig!(0x3000)), ( ubig!(0x100000000000000000000000), ubig!(0x200000000000000000000000), ubig!(0x300000000000000000000000), ), ]; for (a, b, c) in large_cases { assert_eq!(reducer.add(&reducer.transform(a), &reducer.transform(b)), reducer.transform(c)); } } #[test] fn test_reducer_dbl() { let reducer = ConstDivisor::new(ubig!(1234)); let small_cases = [ (ubig!(0), ubig!(0)), (ubig!(1), ubig!(2)), (ubig!(2), ubig!(4)), (ubig!(1000), ubig!(2000)), ]; for (a, b) in small_cases { assert_eq!(reducer.dbl(reducer.transform(a)), reducer.transform(b)); } let reducer = ConstDivisor::new(ubig!(0x1234567890123456789012345678901234567890)); let large_cases = [ (ubig!(0), ubig!(0)), (ubig!(1), ubig!(2)), (ubig!(2), ubig!(4)), (ubig!(0x1000), ubig!(0x2000)), (ubig!(0x100000000000000000000000), ubig!(0x200000000000000000000000)), ]; for (a, b) in large_cases { assert_eq!(reducer.dbl(reducer.transform(a)), reducer.transform(b)); } } #[test] fn test_reducer_sub() { let reducer = ConstDivisor::new(ubig!(1234)); let small_cases = [ (ubig!(0), ubig!(0), ubig!(0)), (ubig!(0), ubig!(1), ubig!(1233)), (ubig!(1), ubig!(0), ubig!(1)), (ubig!(1000), ubig!(2000), ubig!(234)), (ubig!(2000), ubig!(1000), ubig!(1000)), ]; for (a, b, c) in small_cases { assert_eq!(reducer.sub(&reducer.transform(a), &reducer.transform(b)), reducer.transform(c)); } let m = ubig!(0x1234567890123456789012345678901234567890); let reducer = ConstDivisor::new(m.clone()); let large_cases = [ (ubig!(0), ubig!(0), ubig!(0)), (ubig!(0), ubig!(1), &m - ubig!(1)), (ubig!(1), ubig!(0), ubig!(1)), (ubig!(0x1000), ubig!(0x2000), &m - ubig!(0x1000)), (ubig!(0x2000), ubig!(0x1000), ubig!(0x1000)), ( ubig!(0x100000000000000000000000), ubig!(0x200000000000000000000000), &m - ubig!(0x100000000000000000000000), ), ( ubig!(0x200000000000000000000000), ubig!(0x100000000000000000000000), ubig!(0x100000000000000000000000), ), ]; for (a, b, c) in large_cases { assert_eq!(reducer.sub(&reducer.transform(a), &reducer.transform(b)), reducer.transform(c)); } } #[test] fn test_reducer_neg() { let reducer = ConstDivisor::new(ubig!(1234)); let small_cases = [ (ubig!(0), ubig!(0)), (ubig!(1), ubig!(1233)), (ubig!(2), ubig!(1232)), (ubig!(1000), ubig!(234)), ]; for (a, b) in small_cases { assert_eq!(reducer.neg(reducer.transform(a)), reducer.transform(b)); } let m = ubig!(0x1234567890123456789012345678901234567890); let reducer = ConstDivisor::new(m.clone()); let large_cases = [ (ubig!(0), ubig!(0)), (ubig!(1), &m - ubig!(1)), (ubig!(2), &m - ubig!(2)), (ubig!(0x1000), &m - ubig!(0x1000)), (ubig!(0x100000000000000000000000), &m - ubig!(0x100000000000000000000000)), ]; for (a, b) in large_cases { assert_eq!(reducer.neg(reducer.transform(a)), reducer.transform(b)); } } #[test] fn test_reducer_mul() { let reducer = ConstDivisor::new(ubig!(1234)); let small_cases = [ (ubig!(0), ubig!(0), ubig!(0)), (ubig!(0), ubig!(1), ubig!(0)), (ubig!(1), ubig!(1), ubig!(1)), (ubig!(1000), ubig!(2000), ubig!(920)), (ubig!(2000), ubig!(1000), ubig!(920)), ]; for (a, b, c) in small_cases { assert_eq!(reducer.mul(&reducer.transform(a), &reducer.transform(b)), reducer.transform(c)); } let m = ubig!(0x1234567890123456789012345678901234567890); let reducer = ConstDivisor::new(m.clone()); let large_cases = [ (ubig!(0), ubig!(0), ubig!(0)), (ubig!(0), ubig!(1), ubig!(0)), (ubig!(1), ubig!(1), ubig!(1)), (ubig!(0x1000), ubig!(0x2000), ubig!(0x2000000)), (ubig!(0x2000), ubig!(0x1000), ubig!(0x2000000)), ( ubig!(0x100000000000000000000000), ubig!(0x200000000000000000000000), ubig!(0x12c000000012c000000012c000000012e000000), ), ( ubig!(0x200000000000000000000000), ubig!(0x100000000000000000000000), ubig!(0x12c000000012c000000012c000000012e000000), ), ]; for (a, b, c) in large_cases { assert_eq!(reducer.mul(&reducer.transform(a), &reducer.transform(b)), reducer.transform(c)); } } #[test] fn test_reducer_sqr() { let reducer = ConstDivisor::new(ubig!(1234)); let small_cases = [ (ubig!(0), ubig!(0)), (ubig!(1), ubig!(1)), (ubig!(2), ubig!(4)), (ubig!(1000), ubig!(460)), ]; for (a, b) in small_cases { assert_eq!(reducer.sqr(reducer.transform(a)), reducer.transform(b)); } let m = ubig!(0x1234567890123456789012345678901234567890); let reducer = ConstDivisor::new(m.clone()); let large_cases = [ (ubig!(0), ubig!(0)), (ubig!(1), ubig!(1)), (ubig!(2), ubig!(4)), (ubig!(0x1000), ubig!(0x1000000)), ( ubig!(0x100000000000000000000000), ubig!(0x96000000009600000000960000000097000000), ), ]; for (a, b) in large_cases { assert_eq!(reducer.sqr(reducer.transform(a)), reducer.transform(b)); } } #[test] fn test_reducer_inv() { let reducer = ConstDivisor::new(ubig!(1234)); let small_cases = [ (ubig!(0), None), (ubig!(1), Some(ubig!(1))), (ubig!(2), None), (ubig!(1001), Some(ubig!(1091))), ]; for (a, b) in small_cases { assert_eq!(reducer.inv(reducer.transform(a)), b.map(|v| reducer.transform(v))); } let m = ubig!(0x1234567890123456789012345678901234567890); let reducer = ConstDivisor::new(m.clone()); let large_cases = [ (ubig!(0), None), (ubig!(1), Some(ubig!(1))), (ubig!(2), None), (ubig!(0x1001), Some(ubig!(94593912811883961533498385659457234825064814993))), ( ubig!(0x100000000000000000000001), Some(ubig!(49597318474237639809488304913303841829624579953)), ), ]; for (a, b) in large_cases { assert_eq!(reducer.inv(reducer.transform(a)), b.map(|v| reducer.transform(v))); } } #[test] fn test_reducer_pow() { let reducer = ConstDivisor::new(ubig!(1234)); let small_cases = [ (ubig!(0), ubig!(0), ubig!(1)), (ubig!(0), ubig!(1), ubig!(0)), (ubig!(1), ubig!(1), ubig!(1)), (ubig!(1000), ubig!(2000), ubig!(968)), (ubig!(2000), ubig!(1000), ubig!(446)), ]; for (a, b, c) in small_cases { assert_eq!(reducer.pow(reducer.transform(a), &b), reducer.transform(c)); } let m = ubig!(0x1234567890123456789012345678901234567890); let reducer = ConstDivisor::new(m.clone()); let large_cases = [ (ubig!(0), ubig!(0), ubig!(1)), (ubig!(0), ubig!(1), ubig!(0)), (ubig!(1), ubig!(1), ubig!(1)), ( ubig!(0x1000), ubig!(0x2000), ubig!(6836336448053429355926867185433977698732821296), ), ( ubig!(0x2000), ubig!(0x1000), ubig!(40493613063087797729807140685333106341989572736), ), ( ubig!(0x100000000000000000000000), ubig!(0x200000000000000000000000), ubig!(3353173600746198511020157785071195910194367376), ), ( ubig!(0x100000000000000000000001), ubig!(0x200000000000000000000001), ubig!(5183365446386658625038933891731846219325326897), ), ]; for (a, b, c) in large_cases { assert_eq!(reducer.pow(reducer.transform(a), &b), reducer.transform(c)); } }