/* * http://en.wikipedia.org/wiki/Pell's_equation * * We find the continued fraction expansion of sqrt(d), and * expand out the convergents as h/k. At some point, the * solution x=h, y=k will satisfy the equation and this is * guaranteed to be minimal in x. * * To find the continued fraction expansion of sqrt(d): * http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Continued_fraction_expansion * * To find the convergents: * http://www.proofwiki.org/wiki/Definition:Continued_Fraction/Numerators_and_Denominators * (our h, k are their p, q) */ static void minx(int d, mpz_t x) { int a0 = sqrt(d); int mn = 0, dn = 1, an = a0; int m1, d1, a1; mpz_t h, k; // h_n, k_n mpz_t h1, k1; // h_{n-1}, k_{n-1} mpz_t h2, k2; // h_{n-2}, k_{n-2} mpz_t hsq, ksq; // h^2, k^2 mpz_init(h); mpz_init(k); mpz_init(h1); mpz_init(k1); mpz_init(h2); mpz_init(k2); mpz_init(hsq); mpz_init(ksq); mpz_set_ui(h1, 1); mpz_set_ui(k1, 0); mpz_set_ui(h, a0); mpz_set_ui(k, 1); do { // Get the next a_n in the continued fraction m1 = dn * an - mn; d1 = (d - m1*m1) / dn; a1 = (a0 + m1) / d1; mn = m1; dn = d1; an = a1; // Get the next convergent mpz_set(h2, h1); mpz_set(k2, k1); mpz_set(h1, h); mpz_set(k1, k); mpz_mul_ui(h, h1, an); mpz_add(h, h, h2); // h_n = a_n*h_{n-1} + h_{n-2} mpz_mul_ui(k, k1, an); mpz_add(k, k, k2); // k_n = a_n*k_{n-1} + k_{n-2} // Check if h, k is a solution mpz_mul(hsq, h, h); mpz_mul(ksq, k, k); mpz_submul_ui(hsq, ksq, d); } while (mpz_cmp_ui(hsq, 1) != 0); mpz_set(x, h); mpz_clear(h); mpz_clear(k); mpz_clear(h1); mpz_clear(k1); mpz_clear(h2); mpz_clear(k2); mpz_clear(hsq); mpz_clear(ksq); }
void testmain (int argc, char **argv) { unsigned i; mpz_t a, b, res, ref; mpz_init (a); mpz_init (b); mpz_init_set_ui (res, 5); mpz_init (ref); for (i = 0; i < COUNT; i++) { mini_random_op3 (OP_MUL, MAXBITS, a, b, ref); if (i & 1) { mpz_add (ref, ref, res); if (mpz_fits_ulong_p (b)) mpz_addmul_ui (res, a, mpz_get_ui (b)); else mpz_addmul (res, a, b); } else { mpz_sub (ref, res, ref); if (mpz_fits_ulong_p (b)) mpz_submul_ui (res, a, mpz_get_ui (b)); else mpz_submul (res, a, b); } if (mpz_cmp (res, ref)) { if (i & 1) fprintf (stderr, "mpz_addmul failed:\n"); else fprintf (stderr, "mpz_submul failed:\n"); dump ("a", a); dump ("b", b); dump ("r", res); dump ("ref", ref); abort (); } } mpz_clear (a); mpz_clear (b); mpz_clear (res); mpz_clear (ref); }
void check_one_ui (mpz_ptr w, mpz_ptr x, unsigned long y) { mpz_t want, got; mpz_init (want); mpz_init (got); mpz_mul_ui (want, x, (unsigned long) y); mpz_add (want, w, want); mpz_set (got, w); mpz_addmul_ui (got, x, (unsigned long) y); MPZ_CHECK_FORMAT (got); if (mpz_cmp (want, got) != 0) { printf ("mpz_addmul_ui fail\n"); fail: mpz_trace ("w", w); mpz_trace ("x", x); printf ("y=0x%lX %lu\n", y, y); mpz_trace ("want", want); mpz_trace ("got ", got); abort (); } mpz_mul_ui (want, x, y); mpz_sub (want, w, want); mpz_set (got, w); mpz_submul_ui (got, x, y); MPZ_CHECK_FORMAT (got); if (mpz_cmp (want, got) != 0) { printf ("mpz_submul_ui fail\n"); goto fail; } mpz_clear (want); mpz_clear (got); }
static void eliminate_digit(unsigned int d) { mpz_submul_ui(accum, denom, d); mpz_mul_ui(accum, accum, 10); mpz_mul_ui(numer, numer, 10); }
void eliminate_digit(ui d) { mpz_submul_ui(acc, den, d); mpz_mul_ui(acc, acc, 10); mpz_mul_ui(num, num, 10); }
Integer& Integer::maxpyin(Integer& res, const Integer& a, const uint64_t x) { if (isZero(a) || isZero(x)) return res; mpz_submul_ui( (mpz_ptr)&res.gmp_rep, (mpz_srcptr)&a.gmp_rep, x); return res; }