Task: Pell's equation





Java: import java.math.BigInteger;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;

public class PellsEquation {

    public static void main(String[] args) {
        NumberFormat format = NumberFormat.getInstance();
        for ( int n : new int[] {61, 109, 181, 277, 8941} ) {
            BigInteger[] pell = pellsEquation(n);
            System.out.printf("x^2 - %3d * y^2 = 1 for:%n    x = %s%n    y = %s%n%n", n,  format.format(pell[0]),  format.format(pell[1]));
        }
    }

    private static final BigInteger[] pellsEquation(int n) {
        int a0 = (int) Math.sqrt(n);
        if ( a0*a0 == n ) {
            throw new IllegalArgumentException("ERROR 102:  Invalid n = " + n);
        }
        List<Integer> continuedFrac = continuedFraction(n);
        int count = 0;
        BigInteger ajm2 = BigInteger.ONE;
        BigInteger ajm1 = new BigInteger(a0 + "");
        BigInteger bjm2 = BigInteger.ZERO;
        BigInteger bjm1 = BigInteger.ONE;
        boolean stop = (continuedFrac.size() % 2 == 1);
        if ( continuedFrac.size() == 2 ) {
            stop = true;
        }
        while ( true ) {
            count++;
            BigInteger bn = new BigInteger(continuedFrac.get(count) + "");
            BigInteger aj = bn.multiply(ajm1).add(ajm2);
            BigInteger bj = bn.multiply(bjm1).add(bjm2);
            if ( stop && (count == continuedFrac.size()-2 || continuedFrac.size() == 2) ) {
                return new BigInteger[] {aj, bj};
            }
            else if (continuedFrac.size() % 2 == 0 && count == continuedFrac.size()-2 ) {
                stop = true;
            }
            if ( count == continuedFrac.size()-1 ) {
                count = 0;
            }
            ajm2 = ajm1;
            ajm1 = aj;
            bjm2 = bjm1;
            bjm1 = bj;
        }
    }

    private static final List<Integer> continuedFraction(int n) {
        List<Integer> answer = new ArrayList<Integer>();
        int a0 = (int) Math.sqrt(n);
        answer.add(a0);
        int a = -a0;
        int aStart = a;
        int b = 1;
        int bStart = b;

        while ( true ) {
            
            int[] values = iterateFrac(n, a, b);
            answer.add(values[0]);
            a = values[1];
            b = values[2];
            if (a == aStart && b == bStart) break;
        }
        return answer;
    }
    
    
    
    
    private static final int[] iterateFrac(int n, int a, int b) {
        int x = (int) Math.floor((b * Math.sqrt(n) - b * a)/(n - a * a));
        int[] answer = new int[3];
        answer[0] = x;
        answer[1] = -(b * a + x *(n - a * a)) / b;
        answer[2] = (n - a * a) / b;
        return answer;
    }


}







Ada: with Ada.Text_Io;
with Ada.Numerics.Elementary_Functions;
with Ada.Numerics.Big_Numbers.Big_Integers;

procedure Pells_Equation is
   use Ada.Numerics.Big_Numbers.Big_Integers;

   type Pair is
      record
         V1, V2 : Big_Integer;
      end record;

   procedure Solve_Pell (N : Natural; X, Y : out Big_Integer) is
      use Ada.Numerics.Elementary_Functions;
      Big_N : constant Big_Integer := To_Big_Integer (N);
      XX    : constant Big_Integer := To_Big_Integer (Natural (Float'Floor (Sqrt (Float (N)))));
   begin
      if XX**2 = Big_N then
         X := 1; Y := 0;
         return;
      end if;

      declare
         YY   : Big_Integer := XX;
         Z    : Big_Integer := 1;
         R    : Big_Integer := 2 * XX;
         E    : Pair        := Pair'(V1 => 1, V2 => 0);
         F    : Pair        := Pair'(V1 => 0, V2 => 1);
      begin
         loop
            YY := R * Z - YY;
            Z  := (Big_N - YY**2) / Z;
            R  := (XX + YY) / Z;
            E  := Pair'(V1 => E.V2, V2 => R * E.V2 + E.V1);
            F  := Pair'(V1 => F.V2, V2 => R * F.V2 + F.V1);
            X  := E.V2 + XX * F.V2;
            Y  := F.V2;
            exit when X**2 - Big_N * Y**2 = 1;
         end loop;
      end;
   end Solve_Pell;

   procedure Test (N : Natural) is

      package Natural_Io is new Ada.Text_Io.Integer_Io (Natural);
      use Ada.Text_Io, Natural_Io;

      X, Y : Big_Integer;
   begin
      Solve_Pell (N, X => X, Y => Y);
      Put ("X**2 - ");
      Put (N, Width => 3);
      Put (" * Y**2 = 1 for X = ");
      Put (To_String (X, Width => 22));
      Put (" and Y = ");
      Put (To_String (Y, Width => 20));
      New_Line;
   end Test;

begin
   Test (61);
   Test (109);
   Test (181);
   Test (277);
end Pells_Equation;