示例#1
0
 private Diophantine Chakravala(Diophantine d, long N)
 {
     // see aforementioned wikipedia page for how this works. Essentially if you have two solutions to a more general
     // a^2 - N*b^2 = k, you can compose the two solutions to find yet another. Eventually k == 1 and you have
     // the solution we are looking for.
     while (d.k != 1)
     {
         BigInteger m, a, b, k;
         if (d.k == -1)
         {
             //special case, compose d with itself
             a = (d.a * d.a + N * d.b * d.b);
             b = (2 * d.a * d.b);
             k = 1;
         }
         else
         {
             m = ChooseM(d, N);
             a = (d.a * m + N * d.b) / BigInteger.Abs(d.k);
             b = (d.a + d.b * m) / BigInteger.Abs(d.k);
             k = (m * m - N) / d.k;
         }
         d.a = a;
         d.b = b;
         d.k = k;
     }
     return(d);
 }
示例#2
0
        private BigInteger ChooseM(Diophantine d, long N)
        {
            // we need m such that k | (a + bm) that minimizes (m^2 - N)
            // first find possible m
            // a + bm = 0 mod k
            // => m = -a(b^-1) mod k
            var sqrtN = (int)Math.Sqrt(N);
            var k     = BigInteger.Abs(d.k);
            var invB  = Modular.ModularMultiplicativeInverse(d.b, k); // apparently gcd(b, k) = 1 always, so this is legit ¯\_(ツ)_/¯
            var m     = (-d.a) * invB;
            var m0    = m + ((sqrtN - m) / k) * k;
            var m1    = m + ((sqrtN - m) / k + 1) * k;

            return(new[] { m0, m1 }.OrderBy(x => BigInteger.Abs(x * x - N)).First());
        }
    public static void diophantine_solution_minimize_test()

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    DIOPHANTINE_SOLUTION_MINIMIZE_TEST tests DIOPHANTINE_SOLUTION_MINIMIZE.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    02 December 2006
    //
    //  Author:
    //
    //    John Burkardt
    //
    {
        const int a = 4096;
        const int b = -15625;
        const int c = 46116;

        Console.WriteLine("");
        Console.WriteLine("DIOPHANTINE_SOLUTION_MINIMIZE_TEST");
        Console.WriteLine("  DIOPHANTINE_SOLUTION_MINIMIZE computes a minimal");
        Console.WriteLine("  Euclidean norm solution of a Diophantine equation:");
        Console.WriteLine("    A * X + B * Y = C");

        int x = 665499996;
        int y = 174456828;

        int r = a * x + b * y - c;

        Console.WriteLine("");
        Console.WriteLine("  Coefficients:");
        Console.WriteLine("    A = " + a.ToString().PadLeft(12) + "");
        Console.WriteLine("    B = " + b.ToString().PadLeft(12) + "");
        Console.WriteLine("    C = " + c.ToString().PadLeft(12) + "");
        Console.WriteLine("  Solution:");
        Console.WriteLine("    X = " + x.ToString().PadLeft(12) + "");
        Console.WriteLine("    Y = " + y.ToString().PadLeft(12) + "");
        Console.WriteLine("  Residual R = A * X + B * Y - C:");
        Console.WriteLine("    R = " + r.ToString().PadLeft(12) + "");

        Diophantine.diophantine_solution_minimize(a, b, ref x, ref y);

        r = a * x + b * y - c;

        Console.WriteLine("");
        Console.WriteLine("  DIOPHANTINE_SOLUTION_MINIMIZE returns");
        Console.WriteLine("  the minimized solution:");
        Console.WriteLine("    X = " + x.ToString().PadLeft(12) + "");
        Console.WriteLine("    Y = " + y.ToString().PadLeft(12) + "");
        Console.WriteLine("  Residual R = A * X + B * Y - C:");
        Console.WriteLine("    R = " + r.ToString().PadLeft(12) + "");

        x = 15621;
        y = 4092;

        r = a * x + b * y - c;

        Console.WriteLine("");
        Console.WriteLine("  Here is the minimal positive solution:");
        Console.WriteLine("    X = " + x.ToString().PadLeft(12) + "");
        Console.WriteLine("    Y = " + y.ToString().PadLeft(12) + "");
        Console.WriteLine("  Residual R = A * X + B * Y - C:");
        Console.WriteLine("    R = " + r.ToString().PadLeft(12) + "");
    }
    public static void diophantine_test()

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    DIOPHANTINE_TEST tests DIOPHANTINE.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    02 December 2006
    //
    //  Author:
    //
    //    John Burkardt
    //
    {
        const int TEST_NUM = 20;

        int[] a_test =
        {
            1027,   1027,  1027, 1027, -1027,
            -1027, -1027, -1027,    6,     0,
            0,         0,     1,    1,     1,
            1024,      0,     0,    5, 2
        };
        int[] b_test =
        {
            712,     712, -712, -712, 712,
            712,    -712, -712,    8,   0,
            1,         1,    0,    0,   1,
            -15625,    0,    3,    0, 4
        };
        int[] c_test =
        {
            7,     -7,  7, -7, 7,
            -7,     7, -7, 50, 0,
            0,      1,  0,  1, 0,
            11529,  1, 11, 19, 7
        };

        bool error = false;
        int  test_i;
        int  x = 0;
        int  y = 0;

        Console.WriteLine("");
        Console.WriteLine("DIOPHANTINE_TEST");
        Console.WriteLine("  DIOPHANTINE solves a Diophantine equation:");
        Console.WriteLine("    A * X + B * Y = C");
        Console.WriteLine("");
        Console.WriteLine("        A         B         C         X     Y     Residual");
        Console.WriteLine("");

        for (test_i = 0; test_i < TEST_NUM; test_i++)
        {
            int a = a_test[test_i];
            int b = b_test[test_i];
            int c = c_test[test_i];

            Diophantine.diophantine(a, b, c, ref error, ref x, ref y);

            switch (error)
            {
            case true:
                Console.WriteLine(a.ToString().PadLeft(10) + "  "
                                  + b.ToString().PadLeft(10) + "  "
                                  + c.ToString().PadLeft(10) + "  "
                                  + "(Error occurred!)" + "");
                break;

            default:
                int r = a * x + b * y - c;
                Console.WriteLine(a.ToString().PadLeft(10) + "  "
                                  + b.ToString().PadLeft(10) + "  "
                                  + c.ToString().PadLeft(10) + "  "
                                  + x.ToString().PadLeft(10) + "  "
                                  + y.ToString().PadLeft(10) + "  "
                                  + r.ToString().PadLeft(10) + "");
                break;
            }
        }
    }