gcd.rs 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. use ibig::{
  2. ibig,
  3. ops::{Abs, UnsignedAbs},
  4. ubig, IBig, UBig,
  5. };
  6. #[test]
  7. fn test_gcd_ubig() {
  8. // test cases (x, y, gcd(x,y))
  9. let test_cases = [
  10. // trivial cases
  11. (ubig!(0), ubig!(123), ubig!(123)),
  12. (ubig!(123), ubig!(0), ubig!(123)),
  13. (ubig!(1), ubig!(123), ubig!(1)),
  14. (ubig!(123), ubig!(1), ubig!(1)),
  15. (ubig!(123), ubig!(123), ubig!(123)),
  16. (
  17. ubig!(0),
  18. ubig!(_0x123456789123456789123456789123456789),
  19. ubig!(_0x123456789123456789123456789123456789),
  20. ),
  21. (
  22. ubig!(1),
  23. ubig!(_0x123456789123456789123456789123456789),
  24. ubig!(1),
  25. ),
  26. (
  27. ubig!(_0x123456789123456789123456789123456789),
  28. ubig!(_0x123456789123456789123456789123456789),
  29. ubig!(_0x123456789123456789123456789123456789),
  30. ),
  31. // small cases
  32. (ubig!(3), ubig!(7), ubig!(1)),
  33. (ubig!(8), ubig!(9), ubig!(1)),
  34. (ubig!(9), ubig!(8), ubig!(1)),
  35. (ubig!(42), ubig!(56), ubig!(14)),
  36. (ubig!(7966496), ubig!(314080416), ubig!(32)),
  37. // big cases
  38. (
  39. ubig!(0xffffffffffffffffffffffff1), // largest prime under 2^100
  40. ubig!(0x7ffffffffffffffffffffff8d), // largest prime under 2^99
  41. ubig!(1),
  42. ),
  43. (
  44. ubig!(0xffffffffffffffffffffffffffffff61), // largest prime under 2^128
  45. ubig!(0xffffffffffffffffffffffffffffff53), // second largest prime under 2^128
  46. ubig!(1),
  47. ),
  48. (
  49. ubig!(_0x3ffffffffffffffffffffffffffffffffffffd), // largest prime under 2^150
  50. ubig!(_0x1fffffffffffffffffffffffffffffffffffe1), // largest prime under 2^149
  51. ubig!(1),
  52. ),
  53. (
  54. ubig!(_0x123456789123456789123456789123456789),
  55. ubig!(_0x987654321),
  56. ubig!(_0x2d),
  57. ),
  58. (
  59. ubig!(_0x123456789123456789123456789123456789),
  60. ubig!(_0x987654321987654321987654321987654321),
  61. ubig!(_0x2d00000002d00000002d00000002d),
  62. ),
  63. (
  64. ubig!(_0x5a4653ca673768565b41f775d6947d55cf3813d1), // 3^100
  65. ubig!(_0x1000000000000000000000000000000000000000),
  66. ubig!(1),
  67. ),
  68. ];
  69. for (a, b, c) in &test_cases {
  70. for (a, b) in [(a, b), (b, a)] {
  71. assert_eq!(a.gcd(b), *c);
  72. let (g, x, y) = a.extended_gcd(b);
  73. assert_eq!(g, *c);
  74. assert_eq!(&x * IBig::from(a) + &y * IBig::from(b), IBig::from(g));
  75. assert!(x.unsigned_abs() <= *b.max(&ubig!(1)));
  76. assert!(y.unsigned_abs() <= *a.max(&ubig!(1)));
  77. }
  78. }
  79. for a in 0u8..=20 {
  80. for b in 0u8..=20 {
  81. if a == 0 && b == 0 {
  82. continue;
  83. }
  84. let a = UBig::from(a);
  85. let b = UBig::from(b);
  86. let (g, x, y) = a.extended_gcd(&b);
  87. assert_eq!(g, a.gcd(&b));
  88. assert_eq!(&x * IBig::from(&a) + &y * IBig::from(&b), IBig::from(g));
  89. assert!(x.unsigned_abs() <= b.max(ubig!(1)));
  90. assert!(y.unsigned_abs() <= a.max(ubig!(1)));
  91. }
  92. }
  93. }
  94. #[test]
  95. #[should_panic]
  96. fn test_gcd_ubig_0_0() {
  97. let _ = ubig!(0).gcd(&ubig!(0));
  98. }
  99. #[test]
  100. #[should_panic]
  101. fn test_extended_gcd_ubig_0_0() {
  102. let _ = ubig!(0).extended_gcd(&ubig!(0));
  103. }
  104. #[test]
  105. fn test_gcd_ibig() {
  106. assert_eq!(ibig!(12).gcd(&ibig!(18)), ibig!(6));
  107. assert_eq!(ibig!(12).gcd(&ibig!(-18)), ibig!(6));
  108. assert_eq!(ibig!(-12).gcd(&ibig!(18)), ibig!(6));
  109. assert_eq!(ibig!(-12).gcd(&ibig!(-18)), ibig!(6));
  110. for a in -20i8..=20 {
  111. for b in -20i8..=20 {
  112. if a == 0 && b == 0 {
  113. continue;
  114. }
  115. let a = IBig::from(a);
  116. let b = IBig::from(b);
  117. let (g, x, y) = a.extended_gcd(&b);
  118. assert_eq!(g, a.gcd(&b));
  119. assert_eq!(&x * &a + &y * &b, g);
  120. assert!(x.abs() <= b.abs().max(ibig!(1)));
  121. assert!(y.abs() <= a.abs().max(ibig!(1)));
  122. }
  123. }
  124. }
  125. #[test]
  126. #[should_panic]
  127. fn test_gcd_ibig_0_0() {
  128. let _ = ibig!(0).gcd(&ibig!(0));
  129. }
  130. #[test]
  131. #[should_panic]
  132. fn test_extended_gcd_ibig_0_0() {
  133. let _ = ibig!(0).extended_gcd(&ibig!(0));
  134. }