solve_modular_quadratic_equation.sf 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. #!/usr/bin/ruby
  2. # Author: Trizen
  3. # Date: 27 April 2022
  4. # Edit: 26 October 2023
  5. # https://github.com/trizen
  6. # Solve modular quadratic equations of the form:
  7. # a*x^2 + b*x + c == 0 (mod m)
  8. # Solving method:
  9. # D = b^2 - 4*a*c
  10. # t^2 == D (mod 4*a*m)
  11. # By finding all the solutions to `t`, using `sqrtmod(D, 4*a*m)`, the candidate values for `x` are given by:
  12. # x_1 = (-b + t)/(2*a)
  13. # x_2 = (-b - t)/(2*a)
  14. func modular_quadratic_equation (a,b,c,m) {
  15. a %= m
  16. b %= m
  17. c %= m
  18. var D = (b**2 - 4*a*c).mod(4*a*m)
  19. var S = []
  20. for t in (sqrtmod_all(D, 4*a*m)) {
  21. for u,v in ([[-b + t, 2*a]]) {
  22. var x = (u/v)%m
  23. assert_eq((a*x*x + b*x + c)%m, 0)
  24. S << x
  25. }
  26. }
  27. return S.uniq.sort
  28. }
  29. say modular_quadratic_equation(1,1,-1e10 + 8,1e10)
  30. say modular_quadratic_equation(4,6,10 - 1e10, 1e10)
  31. say modular_quadratic_equation(1,1,-1e10 - 10, 1e10)
  32. assert_eq(modular_quadratic_equation(3,4,5, 124), %n[47, 55, 109, 117])
  33. assert_eq(modular_quadratic_equation(3/5,4,5,124), %n[19, 57, 81, 119])
  34. assert_eq(modular_quadratic_equation(3/13, 112, 13, 124), %n[9, 43, 71, 105])
  35. assert_eq(modular_quadratic_equation(3/13, 4, 13*5, 124), %n[33, 53, 95, 115])
  36. assert_eq(modular_quadratic_equation(3/13, 4, 5, 124), %n[3, 21, 65, 83])
  37. assert_eq(modular_quadratic_equation(3/13, 4/7, 5, 124), %n[5, 25, 67, 87])
  38. assert_eq(modular_quadratic_equation(400, 85, 125, 1600), [1983/80, 2035/16, 963/5, 295, 27583/80, 7155/16, 2563/5, 615, 53183/80, 12275/16, 4163/5, 935, 78783/80, 17395/16, 5763/5, 1255, 104383/80, 22515/16, 7363/5, 1575])
  39. __END__
  40. [1810486343, 2632873031, 7367126968, 8189513656]
  41. [905243171, 1316436515, 7367126967/2, 8189513655/2, 5905243171, 6316436515, 17367126967/2, 18189513655/2]
  42. [263226214, 1620648089, 8379351910, 9736773785]