solve_pell_equation_generalized.pl 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. #!/usr/bin/perl
  2. # Daniel "Trizen" Șuteu
  3. # Date: 29 May 2018
  4. # https://github.com/trizen
  5. # Find the smallest solution in positive integers to the generalized Pell equation:
  6. #
  7. # x^2 - d*y^2 = n
  8. #
  9. # where `d` and `n` are given.
  10. # See also:
  11. # https://en.wikipedia.org/wiki/Pell%27s_equation
  12. use 5.020;
  13. use strict;
  14. use warnings;
  15. use experimental qw(signatures);
  16. use Math::AnyNum qw(idiv isqrt is_square irand);
  17. sub solve_pell ($n, $u = 1) {
  18. return () if is_square($n);
  19. my $x = isqrt($n);
  20. my $y = $x;
  21. my $z = 1;
  22. my $r = $x + $x;
  23. my ($f1, $f2) = (1, $x);
  24. for (1 .. 4 * $x * log($x) + 10) {
  25. $y = $r * $z - $y;
  26. $z = idiv($n - $y * $y, $z) || return;
  27. $r = idiv($x + $y, $z);
  28. ($f1, $f2) = ($f2, $r * $f2 + $f1);
  29. my $p = ($n * ($f1 * $f1 - $u)) << 2;
  30. if (is_square($p)) {
  31. my $t = isqrt($p) >> 1;
  32. $t % $n == 0 || next;
  33. return ($f1, idiv($t, $n));
  34. }
  35. }
  36. return ();
  37. }
  38. foreach my $d (1 .. 99) {
  39. my ($x, $y) = solve_pell($d, irand(1, 9) * (irand(0, 1) ? 1 : -1));
  40. if (defined($x)) {
  41. printf("x^2 - %2dy^2 = %2d minimum solution: x=%15s and y=%15s\n", $d, $x**2 - $d * $y**2, $x, $y);
  42. }
  43. }
  44. __END__
  45. x^2 - 2y^2 = 9 minimum solution: x= 3 and y= 0
  46. x^2 - 5y^2 = 4 minimum solution: x= 2 and y= 0
  47. x^2 - 14y^2 = -5 minimum solution: x= 3 and y= 1
  48. x^2 - 15y^2 = 9 minimum solution: x= 3 and y= 0
  49. x^2 - 21y^2 = -3 minimum solution: x= 9 and y= 2
  50. x^2 - 28y^2 = 1 minimum solution: x= 127 and y= 24
  51. x^2 - 29y^2 = -4 minimum solution: x= 5 and y= 1
  52. x^2 - 31y^2 = -6 minimum solution: x= 5 and y= 1
  53. x^2 - 47y^2 = 2 minimum solution: x= 7 and y= 1
  54. x^2 - 53y^2 = -4 minimum solution: x= 7 and y= 1
  55. x^2 - 58y^2 = -6 minimum solution: x= 38 and y= 5
  56. x^2 - 61y^2 = 1 minimum solution: x= 1766319049 and y= 226153980
  57. x^2 - 67y^2 = 9 minimum solution: x= 131 and y= 16
  58. x^2 - 68y^2 = 1 minimum solution: x= 33 and y= 4
  59. x^2 - 69y^2 = -5 minimum solution: x= 8 and y= 1
  60. x^2 - 71y^2 = 1 minimum solution: x= 3480 and y= 413
  61. x^2 - 89y^2 = -8 minimum solution: x= 9 and y= 1
  62. x^2 - 92y^2 = 4 minimum solution: x= 48 and y= 5
  63. x^2 - 93y^2 = 4 minimum solution: x= 29 and y= 3
  64. x^2 - 95y^2 = 1 minimum solution: x= 39 and y= 4
  65. x^2 - 97y^2 = 1 minimum solution: x= 62809633 and y= 6377352
  66. x^2 - 98y^2 = 1 minimum solution: x= 99 and y= 10