Exemplo n.º 1
0
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);
}
Exemplo n.º 2
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);
}
Exemplo n.º 3
0
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;
}