//! Integration tests. //! //! Tests for linear and quadratic equations. //! use modular_equations::{LinEq, LinEqSigned, QuadEq, QuadEqSigned}; #[test] fn linear_equation() { let lin_eq = LinEq:: { a: 81, b: 9, c: 77, modu: 79, }; let sol = lin_eq.solve(); assert!(sol.is_some()); // correct solution is 34 assert_eq!(sol.unwrap()[0], 34); } #[test] fn quadratic_equation() { let quad_eq = QuadEq:: { a: 111, b: 1, c: 250, d: 1, modu: 255, }; match quad_eq.solve() { Some(sols) if sols.len() == 2 => { assert_eq!(sols, vec![42, 177]); } _ => assert!(false), } } #[test] fn signed_linear_equation() { let lin_eq = LinEqSigned:: { a: -1, b: -1000, c: 17, modu: 7, }; match lin_eq.solve() { None => assert!(false), Some(sol) => { assert_eq!(sol.len(), 1); // correct solution is 5 assert_eq!(sol[0], 5); } } } #[test] fn signed_quadratic_equation() { let quad_eq = QuadEqSigned:: { a: -11, b: 99, c: 0, d: -110, modu: 20_871_587_710_370_244_961, }; match quad_eq.solve() { Some(sols) if sols.len() == 4 => { assert_eq!( sols, vec![ 10, 7_399_711_637_570_012_490, 13_471_876_072_800_232_480, 20_871_587_710_370_244_960 ] ); } _ => assert!(false), } } #[test] fn linear_equation_multiple_solutions() { let lin_eq = LinEq:: { a: 15, b: 3, c: 33, modu: 55, }; match lin_eq.solve() { None => assert!(false), Some(sols) => { // solution should be a vector of length five assert_eq!(sols.len(), 5); assert_eq!(sols, vec![2, 13, 24, 35, 46]); } } } #[test] fn linear_equation_one_hundred_solutions() { let lin_eq = LinEqSigned:: { a: 100, b: -1, c: 199, modu: 500, }; match lin_eq.solve() { None => assert!(false), Some(sols) => { // there should be 100 solutions assert_eq!(sols.len(), 100); // test first and last, solutions should be ordered assert_eq!(sols[0], 2); assert_eq!(sols[99], 497); } } } #[test] fn linear_equation_no_solution() { let mut lin_eq = LinEq:: { a: 5, b: 0, c: 1, modu: 5, }; // a % modu == 0 assert_eq!(lin_eq.solve(), None); lin_eq.modu = 10; // gcd(a, modu) does not divide c assert_eq!(lin_eq.solve(), None); } #[test] fn linear_equation_large_modulo() { let lin_eq = LinEq:: { a: 7, b: u128::MAX - 4, c: 0, modu: u128::MAX, }; match lin_eq.solve() { None => assert!(false), Some(sols) => { assert_eq!(sols.len(), 1); assert_eq!(sols[0], 48_611_766_702_991_209_066_196_372_490_252_601_637); } } } #[test] fn quadratic_equation_large_modulo() { let quad_eq = QuadEq:: { a: 1, b: 1, c: 0, d: 1, modu: 416_997_623_116_370_028_124_580_469_121, }; match quad_eq.solve() { Some(sols) if sols.len() == 2 => { assert_eq!( sols, vec![ 137_307_780_239_429_241_193_741_330_788, 279_689_842_876_940_786_930_839_138_332 ] ); } _ => assert!(false), } } #[test] fn quadratic_equation_large_power_of_two_modulo() { let quad_eq = QuadEq:: { a: 1, b: 3, c: 4, d: 0, modu: 2u128.pow(120), }; match quad_eq.solve() { Some(sols) => { assert_eq!(sols.len(), 2); assert_eq!(sols[0], 150_432_075_026_641_822_261_322_309_717_221_465); assert_eq!(sols[1], 1_178_795_920_758_274_050_642_484_750_563_123_108); } _ => assert!(false), } } #[test] fn quadratic_equation_semiprime_modulo() { let quad_eq = QuadEq:: { a: 1, b: 0, c: 0, d: 110, modu: 90_124_258_835_295_998_242_413_094_252_351, }; match quad_eq.solve() { Some(sols) if sols.len() == 4 => { assert_eq!( sols, vec![ 29_129_589_224_271_400_202_982_829_638_184, 43_668_906_256_281_904_644_985_325_179_904, 46_455_352_579_014_093_597_427_769_072_447, 60_994_669_611_024_598_039_430_264_614_167, ] ); } _ => assert!(false), } } #[test] fn quadratic_equation_max_modulo() { let quad_eq = QuadEqSigned:: { a: -1, b: -3, c: 0, d: 0, modu: u128::MAX, }; match quad_eq.solve() { Some(sols) => { assert_eq!(sols.len(), 256); // Check that smallest and largest solutions are correct assert_eq!(sols[0], 0); assert_eq!(sols[1], 6_582_685_413_135_159_043_597_262_296_651_990_362); assert_eq!(sols[2], 8_509_006_254_635_304_544_360_869_534_143_792_742); // Larger solutions have at least 38 digits assert_eq!( sols[sols.len() - 1], 340_282_366_920_938_463_463_374_607_431_768_211_452 ); } _ => assert!(false), } } #[test] fn linear_equation_failure() { let lin_eq = LinEqSigned:: { a: i64::MIN, // No absolute value in 2's complement b: 1, c: -1, modu: 5, }; assert_eq!(lin_eq.solve(), None); } #[test] fn quadratic_equation_failure() { let quad_eq = QuadEqSigned:: { a: i32::MIN, // No absolute value in 2's complement b: 1, c: -1, d: -1, modu: 15, }; assert_eq!(quad_eq.solve(), None); } #[test] fn linear_equation_readme() { let lin_eq = LinEq:: { a: 17, b: 0, c: 1, modu: u8::MAX, }; assert_eq!(lin_eq.solve(), None); } #[test] fn quadratic_equation_readme_old() { let quad_eq = QuadEq:: { a: 1, b: 3, c: 2, d: 0, modu: 2u32.pow(30), }; if let Some(x) = quad_eq.solve() { assert_eq!(x, vec![1_073_741_822, 1_073_741_823]); } else { assert!(false); } } #[test] fn quadratic_equation_readme() { let quad_eq = QuadEq:: { a: 1, b: 3, c: 4, d: 0, modu: 2u64.pow(60), }; if let Some(x) = quad_eq.solve() { assert_eq!(x, vec![226_765_812_977_082_276, 926_155_691_629_764_697]); } else { assert!(false); } } #[test] fn quadratic_signed_equation_readme() { let quad_eq = QuadEqSigned:: { a: -1, b: 2, c: -1, d: 0, modu: 2_082_064_493_491_567_088_228_629_031_592_644_077, }; if let Some(x) = quad_eq.solve() { // Residue class [1] is the only solution assert_eq!(x, vec![1]); } else { assert!(false); } }