quadratic_form_representations.sf 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. #!/usr/bin/ruby
  2. # Represent an odd prime number p as x^2 + d*y^2 using the Cornacchia–Smith method.
  3. # Given an odd prime p and a positive integer d not divisible by p, this algorithm
  4. # either reports that p = x^2 + d*y^2 has no integral solution, or returns a solution.
  5. # Implementation of "Algorithm 2.3.12" from the book "Prime Numbers - A Computational Perspective".
  6. # Algorithm extended to any composite number n, returning multiple positive solutions. (it may not return ALL solutions)
  7. func quadratic_form_representations(d, n) {
  8. if ((kronecker(-d, n) == -1) && n.is_prime) {
  9. return []
  10. }
  11. var solutions = []
  12. for x in (sqrtmod_all(-d, n)) {
  13. if (2*x < n) {
  14. x = (n - x)
  15. }
  16. var (a, b, c) = (n, x, n.isqrt)
  17. while (b > c) {
  18. (a,b) = (b, a % b)
  19. }
  20. var t = (n - b**2)
  21. d.divides(t) || next
  22. idiv(t,d).is_square || next
  23. solutions << [b, isqrt(idiv(t,d))]
  24. }
  25. solutions.uniq!
  26. solutions.map_2d {|x,y| x**2 + d*y**2 }.each {|v| assert_eq(v, n) }
  27. return solutions
  28. }
  29. say quadratic_form_representations(12, 97) #=> [[7, 2]]
  30. say quadratic_form_representations(14, 3*5*7) #=> [[7, 2]]
  31. say quadratic_form_representations(18, 43*97) #=> [[61, 5], [11, 15]]
  32. say quadratic_form_representations( 5, 3*5*7) #=> [[10, 1], [5, 4]]
  33. say quadratic_form_representations(1234, 1810585219) #=> [[41087, 315]]
  34. say quadratic_form_representations(14, 2**127 - 1) #=> [[10229855171020855649, 2162856025860368397]]
  35. say quadratic_form_representations( 1, 99025) #=> [[256, 183], [297, 104], [312, 41], [311, 48]]