static void _fmpq_poly_oz_sqrt_approx_scale(fmpq_poly_t y, fmpq_poly_t z, const long n, const mpfr_prec_t prec) { /* We scale by about |det(y) · det(z)|^(-1/(2n)) to make it converge faster */ mpfr_t gamma; mpfr_init2(gamma, prec); mpfr_t tmp; mpfr_init2(tmp, prec); fmpq_t gamma_q; fmpq_init(gamma_q); /* det(y) */ fmpq_poly_oz_ideal_norm(gamma_q, y, n, 1); fmpq_get_mpfr(gamma, gamma_q, MPFR_RNDN); /* det(y) · det(z) */ fmpq_poly_oz_ideal_norm(gamma_q, z, n, 1); fmpq_get_mpfr(tmp, gamma_q, MPFR_RNDN); mpfr_mul(gamma, gamma, tmp, MPFR_RNDN); /* (det(y) · det(z))^(-1/(2n)) */ mpfr_root(gamma, gamma, 2*n, MPFR_RNDN); mpfr_ui_div(gamma, 1, gamma, MPFR_RNDN); mpfr_abs(gamma, gamma, MPFR_RNDN); fmpq_set_mpfr(gamma_q, gamma, MPFR_RNDN); fmpq_poly_scalar_mul_fmpq(y, y, gamma_q); fmpq_poly_scalar_mul_fmpq(z, z, gamma_q); fmpq_clear(gamma_q); mpfr_clear(gamma); mpfr_clear(tmp); }
int main(void) { int i, result; flint_rand_t state; printf("content...."); fflush(stdout); flint_randinit(state); /* Check that content(a f) = abs(a) content(f) */ for (i = 0; i < 10000; i++) { fmpq_poly_t f, g; fmpq_t a, b, c; fmpq_poly_init(f); fmpq_poly_init(g); fmpq_init(a); fmpq_init(b); fmpq_init(c); fmpq_poly_randtest_not_zero(f, state, n_randint(state, 100) + 1, 100); fmpq_randtest_not_zero(a, state, 100); fmpq_poly_scalar_mul_fmpq(g, f, a); fmpq_poly_content(b, g); fmpq_poly_content(c, f); fmpq_mul(c, a, c); fmpq_abs(c, c); result = (fmpq_equal(b, c)); if (!result) { printf("FAIL:\n"); fmpq_poly_print(f), printf("\n\n"); fmpq_poly_print(g), printf("\n\n"); fmpq_print(a), printf("\n\n"); fmpq_print(b), printf("\n\n"); fmpq_print(c), printf("\n\n"); abort(); } fmpq_poly_clear(f); fmpq_poly_clear(g); fmpq_clear(a); fmpq_clear(b); fmpq_clear(c); } flint_randclear(state); _fmpz_cleanup(); printf("PASS\n"); return 0; }
void _dgsl_rot_mp_sqrt_sigma_2(fmpq_poly_t rop, const fmpz_poly_t g, const mpfr_t sigma, const int r, const long n, const mpfr_prec_t prec, const oz_flag_t flags) { fmpq_poly_zero(rop); fmpq_t r_q2; fmpq_init(r_q2); fmpq_set_si(r_q2, r, 1); fmpq_mul(r_q2, r_q2, r_q2); fmpq_neg(r_q2, r_q2); fmpq_poly_set_coeff_fmpq(rop, 0, r_q2); fmpq_clear(r_q2); fmpq_poly_t g_q; fmpq_poly_init(g_q); fmpq_poly_set_fmpz_poly(g_q, g); fmpq_poly_t ng; fmpq_poly_init(ng); fmpq_poly_oz_invert_approx(ng, g_q, n, prec, flags); fmpq_poly_t ngt; fmpq_poly_init(ngt); fmpq_poly_oz_conjugate(ngt, ng, n); fmpq_poly_t nggt; fmpq_poly_init(nggt); fmpq_poly_oz_mul(nggt, ng, ngt, n); /** We compute sqrt(g^-T · g^-1) to use it as the starting point for convergence on sqrt(σ^2 · g^-T · g^-1 - r^2) below. We can compute the former with less precision than the latter */ mpfr_t norm; mpfr_init2(norm, prec); fmpz_poly_eucl_norm_mpfr(norm, g, MPFR_RNDN); double p = mpfr_get_d(norm, MPFR_RNDN); /** |g^-1| ~= 1/|g| |g^-T| ~= |g^-1| |g^-1·g^-T| ~= sqrt(n)·|g^-T|·|g^-1| */ fmpq_poly_t sqrt_start; fmpq_poly_init(sqrt_start); p = log2(n) + 4*log2(p); int fail = -1; while (fail) { p = 2*p; if (fail<0) fail = fmpq_poly_oz_sqrt_approx_db(sqrt_start, nggt, n, p, prec/2, flags, NULL); else fail = fmpq_poly_oz_sqrt_approx_db(sqrt_start, nggt, n, p, prec/2, flags, sqrt_start); if(fail) fprintf(stderr, "FAILED for precision %7.1f with code (%d), doubling precision.\n", p, fail); } fmpq_t sigma2; fmpq_init(sigma2); fmpq_set_mpfr(sigma2, sigma, MPFR_RNDN); fmpq_poly_scalar_mul_fmpq(sqrt_start, sqrt_start, sigma2); fmpq_mul(sigma2, sigma2, sigma2); fmpq_poly_scalar_mul_fmpq(nggt, nggt, sigma2); fmpq_clear(sigma2); fmpq_poly_add(rop, rop, nggt); p = p + 2*log2(mpfr_get_d(sigma, MPFR_RNDN)); fmpq_poly_oz_sqrt_approx_babylonian(rop, rop, n, p, prec, flags, sqrt_start); mpfr_clear(norm); fmpq_poly_clear(g_q); fmpq_poly_clear(ng); fmpq_poly_clear(ngt); fmpq_poly_clear(nggt); fmpq_poly_clear(sqrt_start); }
int fmpq_poly_oz_sqrt_approx_pade(fmpq_poly_t f_sqrt, const fmpq_poly_t f, const long n, const int p, const mpfr_prec_t prec, const mpfr_prec_t bound, oz_flag_t flags, const fmpq_poly_t init) { fmpq_poly_t y; fmpq_poly_init(y); fmpq_poly_t y_next; fmpq_poly_init(y_next); fmpq_poly_t z; fmpq_poly_init(z); fmpq_poly_t z_next; fmpq_poly_init(z_next); mpfr_t norm; mpfr_init2(norm, prec); mpfr_t prev_norm; mpfr_init2(prev_norm, prec); mpfr_t log_f; mpfr_init2(log_f, prec); if (init) { // z = y/x fmpq_poly_set(y, init); _fmpq_poly_oz_invert_approx(z, f, n, prec); fmpq_poly_oz_mul(z, z, y, n); } else { fmpq_poly_set(y, f); fmpq_poly_set_coeff_si(z, 0, 1); } fmpq_t *xi = (fmpq_t*)calloc(p, sizeof(fmpq_t)); fmpq_t *a2 = (fmpq_t*)calloc(p, sizeof(fmpq_t)); fmpq_t *c = (fmpq_t*)calloc(p, sizeof(fmpq_t)); fmpq_poly_t *t_ = (fmpq_poly_t*)calloc(p, sizeof(fmpq_poly_t)); fmpq_poly_t *s_ = (fmpq_poly_t*)calloc(p, sizeof(fmpq_poly_t)); mpfr_t pi; mpfr_init2(pi, 4*prec); mpfr_const_pi(pi, MPFR_RNDN); #pragma omp parallel for for(int i=0; i<p; i++) { mpfr_t xi_r; mpfr_init2(xi_r, 4*prec); mpfr_t a2_r; mpfr_init2(a2_r, 4*prec); /* ζ_i = 1/2 * (1 + cos( (2·i -1)·π/(2·p) )) */ mpfr_set_si(xi_r, 2*i+1, MPFR_RNDN); mpfr_mul(xi_r, xi_r, pi, MPFR_RNDN); mpfr_div_si(xi_r, xi_r, 2*p, MPFR_RNDN); mpfr_cos(xi_r, xi_r, MPFR_RNDN); mpfr_add_si(xi_r, xi_r, 1, MPFR_RNDN); mpfr_div_si(xi_r, xi_r, 2, MPFR_RNDN); /* α_i^2 = 1/ζ_i -1 */ mpfr_set_si(a2_r, 1, MPFR_RNDN); mpfr_div(a2_r, a2_r, xi_r, MPFR_RNDN); mpfr_sub_si(a2_r, a2_r, 1, MPFR_RNDN); fmpq_init(xi[i]); fmpq_init(a2[i]); fmpq_set_mpfr(xi[i], xi_r, MPFR_RNDN); fmpq_set_mpfr(a2[i], a2_r, MPFR_RNDN); fmpq_init(c[i]); fmpq_poly_init(t_[i]); fmpq_poly_init(s_[i]); mpfr_clear(xi_r); mpfr_clear(a2_r); } mpfr_clear(pi); uint64_t t = oz_walltime(0); int r = 0; int cont = 1; for(long k=0; cont; k++) { if (k == 0 || mpfr_cmp_ui(prev_norm, 1) > 0) _fmpq_poly_oz_sqrt_approx_scale(y, z, n, prec); /* T = sum([1/xi[i] * ~(Z*Y + a2[i]) for i in range(p)]) */ #pragma omp parallel for for(int i=0; i<p; i++) { fmpq_poly_oz_mul(t_[i], z, y, n); fmpq_poly_get_coeff_fmpq(c[i], t_[i], 0); fmpq_add(c[i], c[i], a2[i]); fmpq_poly_set_coeff_fmpq(t_[i], 0, c[i]); fmpq_poly_scalar_mul_fmpq(t_[i], t_[i], xi[i]); _fmpq_poly_oz_invert_approx(s_[i], t_[i], n, prec); } for(int i=1; i<p; i++) fmpq_poly_add(s_[0], s_[0], s_[i]); #pragma omp parallel sections { #pragma omp section { fmpq_poly_oz_mul(y_next, y, s_[0], n); fmpq_poly_scalar_div_si(y_next, y_next, p); fmpq_poly_set(y, y_next); } #pragma omp section { fmpq_poly_oz_mul(z_next, z, s_[0], n); fmpq_poly_scalar_div_si(z_next, z_next, p); fmpq_poly_set(z, z_next); } } cont = !_fmpq_poly_oz_sqrt_approx_break(norm, y, f, n, bound, prec); if(flags & OZ_VERBOSE) { mpfr_log2(log_f, norm, MPFR_RNDN); mpfr_fprintf(stderr, "Computing sqrt(Σ):: k: %4d, Δ=|sqrt(Σ)^2-Σ|: %7.2Rf", k, log_f); fprintf(stderr, " <? %4ld, ", -bound); fprintf(stderr, "t: %8.2fs\n", oz_seconds(oz_walltime(t))); fflush(0); } if (cont) { if (k>0 && mpfr_cmp_ui_2exp(norm, 1, bound) >= 0) { /* something went really wrong */ r = -1; break; } if (k>0 && mpfr_cmp(norm, prev_norm) >= 0) { /* we don't converge any more */ r = 1; break; } mpfr_set(prev_norm, norm, MPFR_RNDN); } } for(int i=0; i<p; i++) { fmpq_clear(xi[i]); fmpq_clear(a2[i]); fmpq_clear(c[i]); fmpq_poly_clear(t_[i]); fmpq_poly_clear(s_[i]); } free(xi); free(a2); free(c); free(t_); free(s_); mpfr_clear(log_f); fmpq_poly_set(f_sqrt, y); mpfr_clear(norm); mpfr_clear(prev_norm); fmpq_poly_clear(y_next); fmpq_poly_clear(y); fmpq_poly_clear(z_next); fmpq_poly_clear(z); return r; }
int main(void) { int i, result; ulong cflags = UWORD(0); FLINT_TEST_INIT(state); flint_printf("scalar_mul_fmpq...."); fflush(stdout); /* Check aliasing of a and b */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b; fmpq_t z; fmpq_init(z); fmpq_randtest(z, state, 100); fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_randtest(a, state, n_randint(state, 100), 200); fmpq_poly_scalar_mul_fmpq(b, a, z); fmpq_poly_scalar_mul_fmpq(a, a, z); cflags |= fmpq_poly_is_canonical(a) ? 0 : 1; cflags |= fmpq_poly_is_canonical(b) ? 0 : 2; result = (fmpq_poly_equal(a, b) && !cflags); if (!result) { flint_printf("FAIL (aliasing):\n\n"); flint_printf("a = "), fmpq_poly_debug(a), flint_printf("\n\n"); flint_printf("b = "), fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("z = "), fmpq_print(z), flint_printf("\n\n"); gmp_printf("z = %Qd\n\n", z); flint_printf("cflags = %wu\n\n", cflags); abort(); } fmpq_clear(z); fmpq_poly_clear(a); fmpq_poly_clear(b); } /* Check that (a * n1) * n2 == a * (n1 * n2) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, lhs, rhs; fmpq_t z1, z2, z; fmpq_init(z1); fmpq_init(z2); fmpq_init(z); fmpq_randtest(z1, state, 100); fmpq_randtest(z2, state, 100); fmpq_mul(z, z1, z2); fmpq_poly_init(a); fmpq_poly_init(lhs); fmpq_poly_init(rhs); fmpq_poly_randtest(a, state, n_randint(state, 100), 200); fmpq_poly_scalar_mul_fmpq(lhs, a, z1); fmpq_poly_scalar_mul_fmpq(lhs, lhs, z2); fmpq_poly_scalar_mul_fmpq(rhs, a, z); cflags |= fmpq_poly_is_canonical(lhs) ? 0 : 1; cflags |= fmpq_poly_is_canonical(rhs) ? 0 : 2; result = (fmpq_poly_equal(lhs, rhs) && !cflags); if (!result) { flint_printf("FAIL (a * n1 * n2):\n"); fmpq_poly_debug(a), flint_printf("\n\n"); flint_printf("z1 = "), fmpq_print(z1), flint_printf("\n\n"); flint_printf("z2 = "), fmpq_print(z2), flint_printf("\n\n"); flint_printf("z = "), fmpq_print(z), flint_printf("\n\n"); fmpq_poly_debug(lhs), flint_printf("\n\n"); fmpq_poly_debug(rhs), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); abort(); } fmpq_clear(z1); fmpq_clear(z2); fmpq_clear(z); fmpq_poly_clear(a); fmpq_poly_clear(lhs); fmpq_poly_clear(rhs); } /* Check that (a + b) * n == a*n + b*n */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_poly_t a, b, lhs, rhs; fmpq_t z; fmpq_init(z); fmpq_randtest(z, state, 100); fmpq_poly_init(a); fmpq_poly_init(b); fmpq_poly_init(lhs); fmpq_poly_init(rhs); fmpq_poly_randtest(a, state, n_randint(state, 100), 200); fmpq_poly_randtest(b, state, n_randint(state, 100), 200); fmpq_poly_scalar_mul_fmpq(lhs, a, z); fmpq_poly_scalar_mul_fmpq(rhs, b, z); fmpq_poly_add(rhs, lhs, rhs); fmpq_poly_add(lhs, a, b); fmpq_poly_scalar_mul_fmpq(lhs, lhs, z); cflags |= fmpq_poly_is_canonical(lhs) ? 0 : 1; cflags |= fmpq_poly_is_canonical(rhs) ? 0 : 2; result = (fmpq_poly_equal(lhs, rhs) && !cflags); if (!result) { flint_printf("FAIL ((a + b) / n):\n"); fmpq_poly_debug(a), flint_printf("\n\n"); fmpq_poly_debug(b), flint_printf("\n\n"); flint_printf("z = "), fmpq_print(z), flint_printf("\n\n"); fmpq_poly_debug(lhs), flint_printf("\n\n"); fmpq_poly_debug(rhs), flint_printf("\n\n"); flint_printf("cflags = %wu\n\n", cflags); abort(); } fmpq_clear(z); fmpq_poly_clear(a); fmpq_poly_clear(b); fmpq_poly_clear(lhs); fmpq_poly_clear(rhs); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; }