static void compare_mpc_pow (mpfr_prec_t pmax, int iter, unsigned long nbits) /* copied from tpow_ui.c and replaced unsigned by signed */ { mpfr_prec_t p; mpc_t x, y, z, t; long n; int i, inex_pow, inex_pow_si; mpc_rnd_t rnd; mpc_init3 (y, sizeof (unsigned long) * CHAR_BIT, MPFR_PREC_MIN); for (p = MPFR_PREC_MIN; p <= pmax; p++) for (i = 0; i < iter; i++) { mpc_init2 (x, p); mpc_init2 (z, p); mpc_init2 (t, p); mpc_urandom (x, rands); n = (signed long) gmp_urandomb_ui (rands, nbits); mpc_set_si (y, n, MPC_RNDNN); for (rnd = 0; rnd < 16; rnd ++) { inex_pow = mpc_pow (z, x, y, rnd); inex_pow_si = mpc_pow_si (t, x, n, rnd); if (mpc_cmp (z, t) != 0) { printf ("mpc_pow and mpc_pow_si differ for x="); mpc_out_str (stdout, 10, 0, x, MPC_RNDNN); printf (" n=%li\n", n); printf ("mpc_pow gives "); mpc_out_str (stdout, 10, 0, z, MPC_RNDNN); printf ("\nmpc_pow_si gives "); mpc_out_str (stdout, 10, 0, t, MPC_RNDNN); printf ("\n"); exit (1); } if (inex_pow != inex_pow_si) { printf ("mpc_pow and mpc_pow_si give different flags for x="); mpc_out_str (stdout, 10, 0, x, MPC_RNDNN); printf (" n=%li\n", n); printf ("mpc_pow gives %d\n", inex_pow); printf ("mpc_pow_si gives %d\n", inex_pow_si); exit (1); } } mpc_clear (x); mpc_clear (z); mpc_clear (t); } mpc_clear (y); }
/* tests intermediate underflow; WONTFIX */ static int test_underflow (void) { mpc_t z; mpfr_exp_t emin = mpfr_get_emin (); mpfr_set_emin (-10); mpc_init2 (z, 21); mpfr_set_si (mpc_realref(z), -1, GMP_RNDZ); mpfr_set_ui_2exp (mpc_imagref(z), 1, 20, GMP_RNDZ); mpfr_add_ui (mpc_imagref(z), mpc_imagref(z), 1, GMP_RNDZ); mpfr_div_2exp (mpc_imagref(z), mpc_imagref(z), 20, GMP_RNDZ); mpc_atan (z, z, MPC_RNDNN); if (mpfr_cmp_si_2exp (mpc_realref(z), -1066635, 20) != 0 || mpfr_cmp_si_2exp (mpc_imagref(z), 1687619, 22)) { printf ("Error in test_coverage\n"); printf ("expected (-1066635/2^20 1687619/2^22)\n"); printf ("got "); mpc_out_str (stdout, 10, 20, z, MPC_RNDNN); printf ("\n"); exit (1); } mpc_clear (z); mpfr_set_emin (emin); }
static void test_reuse (void) { mpc_t z; mpfr_t y; int inex; mpfr_init2 (y, 2); mpc_init2 (z, 2); mpc_set_si_si (z, 0, -1, MPC_RNDNN); mpfr_neg (mpc_realref (z), mpc_realref (z), MPFR_RNDN); mpc_div_2ui (z, z, 4, MPC_RNDNN); mpfr_set_ui (y, 512, MPFR_RNDN); inex = mpc_pow_fr (z, z, y, MPC_RNDNN); if (MPC_INEX_RE(inex) != 0 || MPC_INEX_IM(inex) != 0 || mpfr_cmp_ui_2exp (mpc_realref(z), 1, -2048) != 0 || mpfr_cmp_ui (mpc_imagref(z), 0) != 0 || mpfr_signbit (mpc_imagref(z)) == 0) { printf ("Error in test_reuse, wrong ternary value or output\n"); printf ("inex=(%d %d)\n", MPC_INEX_RE(inex), MPC_INEX_IM(inex)); printf ("z="); mpc_out_str (stdout, 2, 0, z, MPC_RNDNN); printf ("\n"); exit (1); } mpfr_clear (y); mpc_clear (z); }
void print(Sequence seq, size_t N) { size_t n = 0; while (n++ < N) { mpc_out_str(stdout, 10, 16, seq, RND); //cout << *seq++ << endl; seq++; putchar('\n'); } }
int main() { mpc_t z; int inex; mpc_init2(z, 128); mpc_set_ui_ui(z, 0, 1, MPC_RNDNN); inex = mpc_sqrt(z, z, MPC_RNDNN); mpc_out_str(stdout, 10, 3, z, MPC_RNDNN); printf("\n%i %i\n", MPC_INEX_RE(inex), MPC_INEX_IM(inex)); mpc_clear(z); }
/* test out_str with stream=NULL */ static void check_stdout (mpc_ptr read_number, mpc_ptr expected) { char tmp_file[] = "mpc_test"; int fd; size_t sz; fflush(stdout); fd = dup(fileno(stdout)); if (freopen(tmp_file, "w", stdout) == NULL) { printf ("mpc_inp_str cannot redirect stdout\n"); exit (1); } mpc_out_str (NULL, 2, 0, expected, MPC_RNDNN); fflush(stdout); dup2(fd, fileno(stdout)); close(fd); clearerr(stdout); fflush(stdin); fd = dup(fileno(stdin)); if (freopen(tmp_file, "r", stdin) == NULL) { printf ("mpc_inp_str cannot redirect stdout\n"); exit (1); } if (mpc_inp_str (read_number, NULL, &sz, 2, MPC_RNDNN) == -1) { printf ("mpc_inp_str cannot correctly re-read number " "in file %s\n", tmp_file); exit (1); } mpfr_clear_flags (); /* mpc_cmp set erange flag when an operand is a NaN */ if (mpc_cmp (read_number, expected) != 0 || mpfr_erangeflag_p()) { printf ("mpc_inp_str did not read the number which was written by " "mpc_out_str\n"); OUT (read_number); OUT (expected); exit (1); } fflush(stdin); dup2(fd, fileno(stdin)); close(fd); clearerr(stdin); }
static void check_io_str (mpc_ptr read_number, mpc_ptr expected) { char tmp_file[] = "mpc_test"; FILE *fp; size_t sz; if (!(fp = fopen (tmp_file, "w"))) { printf ("Error: Could not open file %s\n", tmp_file); exit (1); } mpc_out_str (fp, 10, 0, expected, MPC_RNDNN); fclose (fp); if (!(fp = fopen (tmp_file, "r"))) { printf ("Error: Could not open file %s\n", tmp_file); exit (1); }; if (mpc_inp_str (read_number, fp, &sz, 10, MPC_RNDNN) == -1) { printf ("Error: mpc_inp_str cannot correctly re-read number " "in file %s\n", tmp_file); exit (1); } fclose (fp); /* mpc_cmp set erange flag when an operand is a NaN */ mpfr_clear_flags (); if (mpc_cmp (read_number, expected) != 0 || mpfr_erangeflag_p()) { printf ("Error: inp_str o out_str <> Id\n"); OUT (read_number); OUT (expected); exit (1); } }
static void foo (int f(mpc_ptr, mpc_srcptr, mpc_rnd_t), char *s) { mpc_t z, t; int rnd_re, rnd_im, rnd; #define N 5 mpfr_exp_t exy[N][2] = {{200, 800}, {800, 200}, {-50, 50}, {-10, 1000}, {0, 1000}}; int n, inex, inex_re, inex_im, sgn; mpc_init2 (z, MPFR_PREC_MIN); mpc_init2 (t, MPFR_PREC_MIN); for (n = 0; n < N; n++) for (sgn = 0; sgn < 4; sgn++) { if (exy[n][0]) mpfr_set_ui_2exp (mpc_realref (z), 1, exy[n][0], MPFR_RNDN); else mpfr_set_ui (mpc_realref (z), 0, MPFR_RNDN); if (sgn & 1) mpfr_neg (mpc_realref (z), mpc_realref (z), MPFR_RNDN); if (exy[n][1]) mpfr_set_ui_2exp (mpc_imagref (z), 1, exy[n][1], MPFR_RNDN); else mpfr_set_ui (mpc_imagref (z), 0, MPFR_RNDN); if (sgn & 2) mpfr_neg (mpc_imagref (z), mpc_imagref (z), MPFR_RNDN); inex = f (t, z, MPC_RNDZZ); inex_re = MPC_INEX_RE(inex); inex_im = MPC_INEX_IM(inex); if (inex_re != 0 && mpfr_inf_p (mpc_realref (t))) { fprintf (stderr, "Error, wrong real part with rounding towards zero\n"); fprintf (stderr, "f = %s\n", s); fprintf (stderr, "z="); mpc_out_str (stderr, 2, 0, z, MPC_RNDNN); fprintf (stderr, "\nt="); mpc_out_str (stderr, 2, 0, t, MPC_RNDNN); fprintf (stderr, "\n"); exit (1); } if (inex_im != 0 && mpfr_inf_p (mpc_imagref (t))) { fprintf (stderr, "Error, wrong imag part with rounding towards zero\n"); fprintf (stderr, "f = %s\n", s); fprintf (stderr, "z="); mpc_out_str (stderr, 2, 0, z, MPC_RNDNN); fprintf (stderr, "\nt="); mpc_out_str (stderr, 2, 0, t, MPC_RNDNN); fprintf (stderr, "\n"); exit (1); } rnd_re = mpfr_signbit (mpc_realref (t)) == 0 ? MPFR_RNDU : MPFR_RNDD; rnd_im = mpfr_signbit (mpc_imagref (t)) == 0 ? MPFR_RNDU : MPFR_RNDD; rnd = MPC_RND(rnd_re,rnd_im); /* round away */ inex = f (t, z, rnd); inex_re = MPC_INEX_RE(inex); inex_im = MPC_INEX_IM(inex); if (inex_re != 0 && mpfr_zero_p (mpc_realref (t))) { fprintf (stderr, "Error, wrong real part with rounding away from zero\n"); fprintf (stderr, "f = %s\n", s); fprintf (stderr, "z="); mpc_out_str (stderr, 2, 0, z, MPC_RNDNN); fprintf (stderr, "\nt="); mpc_out_str (stderr, 2, 0, t, MPC_RNDNN); fprintf (stderr, "\n"); fprintf (stderr, "rnd=%s\n", mpfr_print_rnd_mode (rnd_re)); exit (1); } if (inex_im != 0 && mpfr_zero_p (mpc_imagref (t))) { fprintf (stderr, "Error, wrong imag part with rounding away from zero\n"); fprintf (stderr, "f = %s\n", s); fprintf (stderr, "z="); mpc_out_str (stderr, 2, 0, z, MPC_RNDNN); fprintf (stderr, "\nt="); mpc_out_str (stderr, 2, 0, t, MPC_RNDNN); fprintf (stderr, "\n"); fprintf (stderr, "rnd=%s\n", mpfr_print_rnd_mode (rnd_im)); exit (1); } } mpc_clear (z); mpc_clear (t); }
static void cmpsqr (mpc_srcptr x, mpc_rnd_t rnd) /* computes the square of x with the specific function or by simple */ /* multiplication using the rounding mode rnd and compares the results */ /* and return values. */ /* In our current test suite, the real and imaginary parts of x have */ /* the same precision, and we use this precision also for the result. */ /* Furthermore, we check whether computing the square in the same */ /* place yields the same result. */ /* We also compute the result with four times the precision and check */ /* whether the rounding is correct. Error reports in this part of the */ /* algorithm might still be wrong, though, since there are two */ /* consecutive roundings. */ { mpc_t z, t, u; int inexact_z, inexact_t; mpc_init2 (z, MPC_MAX_PREC (x)); mpc_init2 (t, MPC_MAX_PREC (x)); mpc_init2 (u, 4 * MPC_MAX_PREC (x)); inexact_z = mpc_sqr (z, x, rnd); inexact_t = mpc_mul (t, x, x, rnd); if (mpc_cmp (z, t)) { fprintf (stderr, "sqr and mul differ for rnd=(%s,%s) \nx=", mpfr_print_rnd_mode(MPC_RND_RE(rnd)), mpfr_print_rnd_mode(MPC_RND_IM(rnd))); mpc_out_str (stderr, 2, 0, x, MPC_RNDNN); fprintf (stderr, "\nmpc_sqr gives "); mpc_out_str (stderr, 2, 0, z, MPC_RNDNN); fprintf (stderr, "\nmpc_mul gives "); mpc_out_str (stderr, 2, 0, t, MPC_RNDNN); fprintf (stderr, "\n"); exit (1); } if (inexact_z != inexact_t) { fprintf (stderr, "The return values of sqr and mul differ for rnd=(%s,%s) \nx= ", mpfr_print_rnd_mode(MPC_RND_RE(rnd)), mpfr_print_rnd_mode(MPC_RND_IM(rnd))); mpc_out_str (stderr, 2, 0, x, MPC_RNDNN); fprintf (stderr, "\nx^2="); mpc_out_str (stderr, 2, 0, z, MPC_RNDNN); fprintf (stderr, "\nmpc_sqr gives %i", inexact_z); fprintf (stderr, "\nmpc_mul gives %i", inexact_t); fprintf (stderr, "\n"); exit (1); } mpc_set (t, x, MPC_RNDNN); inexact_t = mpc_sqr (t, t, rnd); if (mpc_cmp (z, t)) { fprintf (stderr, "sqr and sqr in place differ for rnd=(%s,%s) \nx=", mpfr_print_rnd_mode(MPC_RND_RE(rnd)), mpfr_print_rnd_mode(MPC_RND_IM(rnd))); mpc_out_str (stderr, 2, 0, x, MPC_RNDNN); fprintf (stderr, "\nmpc_sqr gives "); mpc_out_str (stderr, 2, 0, z, MPC_RNDNN); fprintf (stderr, "\nmpc_sqr in place gives "); mpc_out_str (stderr, 2, 0, t, MPC_RNDNN); fprintf (stderr, "\n"); exit (1); } if (inexact_z != inexact_t) { fprintf (stderr, "The return values of sqr and sqr in place differ for rnd=(%s,%s) \nx= ", mpfr_print_rnd_mode(MPC_RND_RE(rnd)), mpfr_print_rnd_mode(MPC_RND_IM(rnd))); mpc_out_str (stderr, 2, 0, x, MPC_RNDNN); fprintf (stderr, "\nx^2="); mpc_out_str (stderr, 2, 0, z, MPC_RNDNN); fprintf (stderr, "\nmpc_sqr gives %i", inexact_z); fprintf (stderr, "\nmpc_sqr in place gives %i", inexact_t); fprintf (stderr, "\n"); exit (1); } mpc_sqr (u, x, rnd); mpc_set (t, u, rnd); if (mpc_cmp (z, t)) { fprintf (stderr, "rounding in sqr might be incorrect for rnd=(%s,%s) \nx=", mpfr_print_rnd_mode(MPC_RND_RE(rnd)), mpfr_print_rnd_mode(MPC_RND_IM(rnd))); mpc_out_str (stderr, 2, 0, x, MPC_RNDNN); fprintf (stderr, "\nmpc_sqr gives "); mpc_out_str (stderr, 2, 0, z, MPC_RNDNN); fprintf (stderr, "\nmpc_sqr quadruple precision gives "); mpc_out_str (stderr, 2, 0, u, MPC_RNDNN); fprintf (stderr, "\nand is rounded to "); mpc_out_str (stderr, 2, 0, t, MPC_RNDNN); fprintf (stderr, "\n"); exit (1); } mpc_clear (z); mpc_clear (t); mpc_clear (u); }
// See Cohen; my D is -D in his notation. size_t pbc_hilbert(mpz_t **arr, int D) { int a, b; int t; int B = (int)floor(sqrt((double) D / 3.0)); mpc_t alpha; mpc_t j; mpf_t sqrtD; mpf_t f0; darray_t Pz; mpc_t z0, z1, z2; double d = 1.0; int h = 1; int jcount = 1; // Compute required precision. b = D % 2; for (;;) { t = (b*b + D) / 4; a = b; if (a <= 1) { a = 1; goto step535_4; } step535_3: if (!(t % a)) { jcount++; if ((a == b) || (a*a == t) || !b) { d += 1.0 / ((double) a); h++; } else { d += 2.0 / ((double) a); h+=2; } } step535_4: a++; if (a * a <= t) { goto step535_3; } else { b += 2; if (b > B) break; } } //printf("modulus: %f\n", exp(3.14159265358979 * sqrt(D)) * d * 0.5); d *= sqrt(D) * 3.14159265358979 / log(2); precision_init((int)(d + 34)); pbc_info("class number %d, %d bit precision", h, (int) d + 34); darray_init(Pz); mpc_init(alpha); mpc_init(j); mpc_init(z0); mpc_init(z1); mpc_init(z2); mpf_init(sqrtD); mpf_init(f0); mpf_sqrt_ui(sqrtD, D); b = D % 2; h = 0; for (;;) { t = (b*b + D) / 4; if (b > 1) { a = b; } else { a = 1; } step3: if (t % a) { step4: a++; if (a * a <= t) goto step3; } else { // a, b, t/a are coeffs of an appropriate primitive reduced positive // definite form. // Compute j((-b + sqrt{-D})/(2a)). h++; pbc_info("[%d/%d] a b c = %d %d %d", h, jcount, a, b, t/a); mpf_set_ui(f0, 1); mpf_div_ui(f0, f0, 2 * a); mpf_mul(mpc_im(alpha), sqrtD, f0); mpf_mul_ui(f0, f0, b); mpf_neg(mpc_re(alpha), f0); compute_j(j, alpha); if (0) { int i; for (i=Pz->count - 1; i>=0; i--) { printf("P %d = ", i); mpc_out_str(stdout, 10, 4, Pz->item[i]); printf("\n"); } } if (a == b || a * a == t || !b) { // P *= X - j int i, n; mpc_ptr p0; p0 = (mpc_ptr) pbc_malloc(sizeof(mpc_t)); mpc_init(p0); mpc_neg(p0, j); n = Pz->count; if (n) { mpc_set(z1, Pz->item[0]); mpc_add(Pz->item[0], z1, p0); for (i=1; i<n; i++) { mpc_mul(z0, z1, p0); mpc_set(z1, Pz->item[i]); mpc_add(Pz->item[i], z1, z0); } mpc_mul(p0, p0, z1); } darray_append(Pz, p0); } else { // P *= X^2 - 2 Re(j) X + |j|^2 int i, n; mpc_ptr p0, p1; p0 = (mpc_ptr) pbc_malloc(sizeof(mpc_t)); p1 = (mpc_ptr) pbc_malloc(sizeof(mpc_t)); mpc_init(p0); mpc_init(p1); // p1 = - 2 Re(j) mpf_mul_ui(f0, mpc_re(j), 2); mpf_neg(f0, f0); mpf_set(mpc_re(p1), f0); // p0 = |j|^2 mpf_mul(f0, mpc_re(j), mpc_re(j)); mpf_mul(mpc_re(p0), mpc_im(j), mpc_im(j)); mpf_add(mpc_re(p0), mpc_re(p0), f0); n = Pz->count; if (!n) { } else if (n == 1) { mpc_set(z1, Pz->item[0]); mpc_add(Pz->item[0], z1, p1); mpc_mul(p1, z1, p1); mpc_add(p1, p1, p0); mpc_mul(p0, p0, z1); } else { mpc_set(z2, Pz->item[0]); mpc_set(z1, Pz->item[1]); mpc_add(Pz->item[0], z2, p1); mpc_mul(z0, z2, p1); mpc_add(Pz->item[1], z1, z0); mpc_add(Pz->item[1], Pz->item[1], p0); for (i=2; i<n; i++) { mpc_mul(z0, z1, p1); mpc_mul(alpha, z2, p0); mpc_set(z2, z1); mpc_set(z1, Pz->item[i]); mpc_add(alpha, alpha, z0); mpc_add(Pz->item[i], z1, alpha); } mpc_mul(z0, z2, p0); mpc_mul(p1, p1, z1); mpc_add(p1, p1, z0); mpc_mul(p0, p0, z1); } darray_append(Pz, p1); darray_append(Pz, p0); } goto step4; } b+=2; if (b > B) break; } // Round polynomial and assign. int k = 0; { *arr = pbc_malloc(sizeof(mpz_t) * (Pz->count + 1)); int i; for (i=Pz->count - 1; i>=0; i--) { if (mpf_sgn(mpc_re(Pz->item[i])) < 0) { mpf_set_d(f0, -0.5); } else { mpf_set_d(f0, 0.5); } mpf_add(f0, f0, mpc_re(Pz->item[i])); mpz_init((*arr)[k]); mpz_set_f((*arr)[k], f0); k++; mpc_clear(Pz->item[i]); pbc_free(Pz->item[i]); } mpz_init((*arr)[k]); mpz_set_ui((*arr)[k], 1); k++; } darray_clear(Pz); mpc_clear(z0); mpc_clear(z1); mpc_clear(z2); mpf_clear(f0); mpf_clear(sqrtD); mpc_clear(alpha); mpc_clear(j); precision_clear(); return k; }