Ejemplo n.º 1
0
void coords_pixel_to_coord(coords* c, mpfr_t x, mpfr_t y)
{
    mpfr_t tmp;
    mpfr_t tmp2;

    mpfr_init2(tmp,  mpfr_get_prec(x));
    mpfr_init2(tmp2, mpfr_get_prec(x));

    if (y != NULL)
    {
        mpfr_div_si(tmp2,   c->width,   c->img_width,   GMP_RNDN);
        mpfr_mul(   tmp,    tmp2,       y,              GMP_RNDN);
        mpfr_sub(   y,      c->ymax,    tmp,            GMP_RNDN);
    }

    if (x != NULL)
    {
        mpfr_div_si(tmp2,   x,          c->img_width,   GMP_RNDN);
        mpfr_mul(   tmp,    tmp2,       c->width,       GMP_RNDN);
        mpfr_add(   x,      tmp,        c->xmin,        GMP_RNDN);
    }

    mpfr_clear(tmp2);
    mpfr_clear(tmp);
}
Ejemplo n.º 2
0
/** Binomial Coefficient --
 * all initialization and cleanup is called in the caller
 * @result R = choose(X, n)
 */
int my_mpfr_choose (mpfr_t R, long n, mpfr_t X, mpfr_rnd_t RND)
{
    int ans;
    long i;
    mpfr_t r, x;
    mpfr_prec_t p_X = mpfr_get_prec(X);

    mpfr_init2(x, p_X); mpfr_set(x, X, RND);
    mpfr_init2(r, p_X);
    if(n > 0) {
	mpfr_set(r, X, RND);
	for(i=1; i < n; ) {
	    mpfr_sub_si(x, x, 1L, RND); // x = X - i
	    mpfr_mul   (r, r, x, RND); // r := r * x = X(X-1)..(X-i)
	    mpfr_div_si(r, r, ++i, RND);
	    // r := r / (i+1) =  X(X-1)..(X-i) / (1*2..*(i+1))
#ifdef DEBUG_Rmpfr
	    Rprintf("my_mpfr_choose(): X (= X_0 - %d)= ", i); R_PRT(x);
	    Rprintf("\n --> r ="); R_PRT(r); Rprintf("\n");
#endif
	}
    }
    else // n = 0
	mpfr_set_si(r, (long) 1, RND);
    ans = mpfr_set(R, r, RND);
    mpfr_clear (x);
    mpfr_clear (r);
    return ans;
}
Ejemplo n.º 3
0
int coords_calculate_precision(coords* c)
{
    int l, p;
    mpfr_t tmp;
    mpfr_t bail;
    mpfr_t px_size;
    mpfr_t precision;

    mpfr_init2(tmp,         c->precision);
    mpfr_init2(bail,        c->precision);
    mpfr_init2(px_size,     c->precision);
    mpfr_init2(precision,   c->precision);

    mpfr_set_d( bail,       4.0,        GMP_RNDN);
    mpfr_div_si(px_size,    c->width,   c->img_width,   GMP_RNDN);
    mpfr_div(   tmp,        bail,       px_size,        GMP_RNDN);

    l = mpfr_log2(  precision,          tmp,            GMP_RNDN);
    p = (int)mpfr_get_si(   precision,                  GMP_RNDN);

    if (l < 0) /* precision was rounded down */
        ++p;

    c->recommend = p;

    mpfr_clear(tmp);
    mpfr_clear(bail);
    mpfr_clear(px_size);
    mpfr_clear(precision);

    mpfr_free_cache(); /* <-- keep valgrind happy over mpfr_log2 */

    return c->recommend;
}
Ejemplo n.º 4
0
static int synge_sum(synge_t to, synge_t number, mpfr_rnd_t round) {
	/* round input */
	mpfr_floor(number, number);

	/* (x * (x + 1)) / 2 */
	mpfr_set(to, number, round);
	mpfr_add_si(number, number, 1, round);
	mpfr_mul(to, to, number, round);
	mpfr_div_si(to, to, 2, round);
	return 0;
} /* synge_sum() */
Ejemplo n.º 5
0
static int synge_phi(synge_t num, mpfr_rnd_t round) {
	/* get sqrt(5) */
	synge_t root_five;
	mpfr_init2(root_five, SYNGE_PRECISION);
	mpfr_sqrt_ui(root_five, 5, round);

	/* (1 + sqrt(5)) / 2 */
	mpfr_add_si(num, root_five, 1, round);
	mpfr_div_si(num, num, 2, round);

	mpfr_clears(root_five, NULL);
	return 0;
} /* synge_phi() */
Ejemplo n.º 6
0
/// @brief d->r keyword implementation
///
void program::rpn_d2r(void) {
    MIN_ARGUMENTS(1);
    ARG_MUST_BE_OF_TYPE(0, cmd_number);

    // add pi on stack
    rpn_pi();

    floating_t* pi = &((number*)_stack->pop_back())->_value;
    floating_t* left = &((number*)_stack->get_obj(0))->_value;

    CHECK_MPFR(mpfr_mul(left->mpfr, left->mpfr, pi->mpfr, floating_t::s_mpfr_rnd));
    CHECK_MPFR(mpfr_div_si(left->mpfr, left->mpfr, 180, floating_t::s_mpfr_rnd));
}
Ejemplo n.º 7
0
int
main (int argc, char *argv[])
{
  mpfr_t x, z;
  int y;
  int i;

  tests_start_mpfr ();
  mpfr_inits2 (53, x, z, (mpfr_ptr) 0);
  for(i = 0 ; i < numberof (tab) ; i++)
    {
      mpfr_set_str (x, tab[i].op1, 16, MPFR_RNDN);
      y = tab[i].op2;
      mpfr_add_si (z, x, y, MPFR_RNDZ);
      if (mpfr_cmp_str (z, tab[i].res_add, 16, MPFR_RNDN))
        ERROR1("add_si", i, z, tab[i].res_add);
      mpfr_sub_si (z, x, y, MPFR_RNDZ);
      if (mpfr_cmp_str (z, tab[i].res_sub, 16, MPFR_RNDN))
        ERROR1("sub_si", i, z, tab[i].res_sub);
      mpfr_si_sub (z, y, x, MPFR_RNDZ);
      mpfr_neg (z, z, MPFR_RNDZ);
      if (mpfr_cmp_str (z, tab[i].res_sub, 16, MPFR_RNDN))
        ERROR1("si_sub", i, z, tab[i].res_sub);
      mpfr_mul_si (z, x, y, MPFR_RNDZ);
      if (mpfr_cmp_str (z, tab[i].res_mul, 16, MPFR_RNDN))
        ERROR1("mul_si", i, z, tab[i].res_mul);
      mpfr_div_si (z, x, y, MPFR_RNDZ);
      if (mpfr_cmp_str (z, tab[i].res_div, 16, MPFR_RNDN))
        ERROR1("div_si", i, z, tab[i].res_div);
    }
  mpfr_set_str1 (x, "1");
  mpfr_si_div (z, 1024, x, MPFR_RNDN);
  if (mpfr_cmp_str1 (z, "1024"))
    ERROR1("si_div", i, z, "1024");
  mpfr_si_div (z, -1024, x, MPFR_RNDN);
  if (mpfr_cmp_str1 (z, "-1024"))
    ERROR1("si_div", i, z, "-1024");

  mpfr_clears (x, z, (mpfr_ptr) 0);

  check_invert ();

  test_generic_add_si (2, 200, 17);
  test_generic_sub_si (2, 200, 17);
  test_generic_mul_si (2, 200, 17);
  test_generic_div_si (2, 200, 17);

  tests_end_mpfr ();
  return 0;
}
Ejemplo n.º 8
0
static int
mpfr_all_div (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t r)
{
  mpfr_t a2;
  unsigned int oldflags, newflags;
  int inex, inex2;

  oldflags = __gmpfr_flags;
  inex = mpfr_div (a, b, c, r);

  if (a == b || a == c)
    return inex;

  newflags = __gmpfr_flags;

  mpfr_init2 (a2, MPFR_PREC (a));

  if (mpfr_integer_p (b) && ! (MPFR_IS_ZERO (b) && MPFR_IS_NEG (b)))
    {
      /* b is an integer, but not -0 (-0 is rejected as
         it becomes +0 when converted to an integer). */
      if (mpfr_fits_ulong_p (b, MPFR_RNDA))
        {
          __gmpfr_flags = oldflags;
          inex2 = mpfr_ui_div (a2, mpfr_get_ui (b, MPFR_RNDN), c, r);
          MPFR_ASSERTN (SAME_SIGN (inex2, inex));
          MPFR_ASSERTN (__gmpfr_flags == newflags);
          check_equal (a, a2, "mpfr_ui_div", b, c, r);
        }
      if (mpfr_fits_slong_p (b, MPFR_RNDA))
        {
          __gmpfr_flags = oldflags;
          inex2 = mpfr_si_div (a2, mpfr_get_si (b, MPFR_RNDN), c, r);
          MPFR_ASSERTN (SAME_SIGN (inex2, inex));
          MPFR_ASSERTN (__gmpfr_flags == newflags);
          check_equal (a, a2, "mpfr_si_div", b, c, r);
        }
    }

  if (mpfr_integer_p (c) && ! (MPFR_IS_ZERO (c) && MPFR_IS_NEG (c)))
    {
      /* c is an integer, but not -0 (-0 is rejected as
         it becomes +0 when converted to an integer). */
      if (mpfr_fits_ulong_p (c, MPFR_RNDA))
        {
          __gmpfr_flags = oldflags;
          inex2 = mpfr_div_ui (a2, b, mpfr_get_ui (c, MPFR_RNDN), r);
          MPFR_ASSERTN (SAME_SIGN (inex2, inex));
          MPFR_ASSERTN (__gmpfr_flags == newflags);
          check_equal (a, a2, "mpfr_div_ui", b, c, r);
        }
      if (mpfr_fits_slong_p (c, MPFR_RNDA))
        {
          __gmpfr_flags = oldflags;
          inex2 = mpfr_div_si (a2, b, mpfr_get_si (c, MPFR_RNDN), r);
          MPFR_ASSERTN (SAME_SIGN (inex2, inex));
          MPFR_ASSERTN (__gmpfr_flags == newflags);
          check_equal (a, a2, "mpfr_div_si", b, c, r);
        }
    }

  mpfr_clear (a2);

  return inex;
}
Ejemplo n.º 9
0
int timefunc(int *timing, void **args) {
  unsigned short oldcw, cw;
#if defined(D_TO_D)
  double x;
  double resh;
#elif defined(D_TO_DD)
  double x;
  double resh, resm;
#elif defined(D_TO_TD)
  double x;
  double resh, resm, resl;
#elif defined(DD_TO_DD)
  double xh, xm;
  double resh, resm;
#elif defined(DD_TO_TD)
  double xh, xm;
  double resh, resm, resl;
#elif defined (TD_TO_TD)
  double xh, xm, xl;
  double resh, resm, resl;
#endif
  mpfr_t xMpfr;
  mpfr_t a, b;
  mpfr_t h;
  int steps, iterations;
  int i;
  struct timeval start, end;
  int usecs;
  double overalltime;

  mpfr_init2(xMpfr, 161);
  mpfr_init2(a, mpfr_get_prec(*((mpfr_t *) (args[0]))));
  mpfr_init2(b, mpfr_get_prec(*((mpfr_t *) (args[1]))));
  mpfr_set(a, *((mpfr_t *) (args[0])), GMP_RNDN);
  mpfr_set(b, *((mpfr_t *) (args[1])), GMP_RNDN);
  mpfr_init2(h, 161);

  mpfr_set(xMpfr, a, GMP_RNDU);

  steps = *((int *) (args[2]));
  iterations = *((int *) (args[3]));

  mpfr_sub(h, b, a, GMP_RNDU);
  mpfr_div_si(h, h, steps, GMP_RNDU);
  
  overalltime = 0;

  while (mpfr_cmp(xMpfr,b) <= 0) {

    _FPU_GETCW(oldcw);
    cw = (_FPU_DEFAULT & ~_FPU_EXTENDED)|_FPU_DOUBLE;
    _FPU_SETCW(cw);

#if defined(D_TO_D)
    mpfr_to_double(&x, xMpfr);     
    gettimeofday(&start,NULL);
    for (i=0;i<iterations;i++) POLYNOMIALNAME(&resh, x);
    gettimeofday(&end,NULL);
#elif defined(D_TO_DD)
    mpfr_to_double(&x, xMpfr);
    gettimeofday(&start,NULL);
    for (i=0;i<iterations;i++) POLYNOMIALNAME(&resh, &resm, x);
    gettimeofday(&end,NULL);
#elif defined(D_TO_TD)
    mpfr_to_double(&x, xMpfr);
    gettimeofday(&start,NULL);
    for (i=0;i<iterations;i++) POLYNOMIALNAME(&resh, &resm, &resl, x);
    gettimeofday(&end,NULL);
#elif defined(DD_TO_DD)
    mpfr_to_doubledouble(&xh, &xm, xMpfr);
    gettimeofday(&start,NULL);
    for (i=0;i<iterations;i++) POLYNOMIALNAME(&resh, &resm, xh, xm);
    gettimeofday(&end,NULL);
#elif defined(DD_TO_TD)
    mpfr_to_doubledouble(&xh, &xm, xMpfr);
    gettimeofday(&start,NULL);
    for (i=0;i<iterations;i++) POLYNOMIALNAME(&resh, &resm, &resl, xh, xm);
    gettimeofday(&end,NULL);
#elif defined(TD_TO_TD)
    mpfr_to_tripledouble(&xh, &xm, &xl, xMpfr);
    gettimeofday(&start,NULL);
    for (i=0;i<iterations;i++) POLYNOMIALNAME(&resh, &resm, &resl, xh, xm, xl);
    gettimeofday(&end,NULL);
#else
#warning You must define one of the macros for the argument and result formats
#endif

    _FPU_SETCW(oldcw);

    mpfr_add(xMpfr, xMpfr, h, GMP_RNDU);

    usecs = ((end.tv_sec - start.tv_sec) * 1000000) + (end.tv_usec - start.tv_usec);

    overalltime += usecs;
  }

  overalltime /= steps;

  mpfr_clear(b);
  mpfr_clear(a);
  mpfr_clear(xMpfr);
  mpfr_clear(h);

  *timing = overalltime;

  return 1;
}
Ejemplo n.º 10
0
static PyObject *
GMPy_Real_FloorDiv(PyObject *x, PyObject *y, CTXT_Object *context)
{
    MPFR_Object *result;

    CHECK_CONTEXT(context);

    if (!(result = GMPy_MPFR_New(0, context))) {
        /* LCOV_EXCL_START */
        return NULL;
        /* LCOV_EXCL_STOP */
    }

    if (MPFR_Check(x)) {
        if (MPFR_Check(y)) {
            mpfr_clear_flags();

            result->rc = mpfr_div(result->f, MPFR(x), MPFR(y), GET_MPFR_ROUND(context));
            result->rc = mpfr_floor(result->f, result->f);
            goto done;
        }

        if (PyIntOrLong_Check(y)) {
            int error;
            long tempi = GMPy_Integer_AsLongAndError(y, &error);

            if (!error) {
                mpfr_clear_flags();

                result->rc = mpfr_div_si(result->f, MPFR(x), tempi, GET_MPFR_ROUND(context));
                result->rc = mpfr_floor(result->f, result->f);
                goto done;
            }
            else {
                mpz_set_PyIntOrLong(global.tempz, y);
                mpfr_clear_flags();

                result->rc = mpfr_div_z(result->f, MPFR(x), global.tempz, GET_MPFR_ROUND(context));
                result->rc = mpfr_floor(result->f, result->f);
                goto done;
            }
        }

        if (CHECK_MPZANY(y)) {
            mpfr_clear_flags();

            result->rc = mpfr_div_z(result->f, MPFR(x), MPZ(y), GET_MPFR_ROUND(context));
            result->rc = mpfr_floor(result->f, result->f);
            goto done;
        }

        if (IS_RATIONAL(y)) {
            MPQ_Object *tempy;

            if (!(tempy = GMPy_MPQ_From_Number(y, context))) {
                Py_DECREF((PyObject*)result);
                return NULL;
            }
            mpfr_clear_flags();

            result->rc = mpfr_div_q(result->f, MPFR(x), tempy->q, GET_MPFR_ROUND(context));
            result->rc = mpfr_floor(result->f, result->f);
            Py_DECREF((PyObject*)tempy);
            goto done;
        }

        if (PyFloat_Check(y)) {
            mpfr_clear_flags();

            result->rc = mpfr_div_d(result->f, MPFR(x), PyFloat_AS_DOUBLE(y), GET_MPFR_ROUND(context));
            result->rc = mpfr_floor(result->f, result->f);
            goto done;
        }
    }

    if (MPFR_Check(y)) {
        if (PyIntOrLong_Check(x)) {
            int error;
            long tempi = GMPy_Integer_AsLongAndError(x, &error);
            if (!error) {
                mpfr_clear_flags();

                result->rc = mpfr_si_div(result->f, tempi, MPFR(y), GET_MPFR_ROUND(context));
                result->rc = mpfr_floor(result->f, result->f);
                goto done;
            }
        }

        /* Since mpfr_z_div does not exist, this combination is handled at the
         * end by converting x to an mpfr. Ditto for rational.*/

        if (PyFloat_Check(x)) {
            mpfr_clear_flags();

            result->rc = mpfr_d_div(result->f, PyFloat_AS_DOUBLE(x), MPFR(y), GET_MPFR_ROUND(context));
            result->rc = mpfr_floor(result->f, result->f);
            goto done;
        }
    }

    /* Handle the remaining cases.
     * Note: verify that MPZ if converted at full precision! */

    if (IS_REAL(x) && IS_REAL(y)) {
        MPFR_Object *tempx, *tempy;

        tempx = GMPy_MPFR_From_Real(x, 1, context);
        tempy = GMPy_MPFR_From_Real(y, 1, context);
        if (!tempx || !tempy) {
            Py_XDECREF((PyObject*)tempx);
            Py_XDECREF((PyObject*)tempy);
            Py_DECREF((PyObject*)result);
            return NULL;
        }
        mpfr_clear_flags();

        result->rc = mpfr_div(result->f, MPFR(tempx), MPFR(tempy), GET_MPFR_ROUND(context));
        result->rc = mpfr_floor(result->f, result->f);
        Py_DECREF((PyObject*)tempx);
        Py_DECREF((PyObject*)tempy);
        goto done;
    }

    Py_DECREF((PyObject*)result);
    Py_RETURN_NOTIMPLEMENTED;

  done:
    _GMPy_MPFR_Cleanup(&result, context);
    return (PyObject*)result;
}
Ejemplo n.º 11
0
/* Returns >= zero iff successful */
static int find_triple_64(int i, int min_leeway, int perfect_leeway, mpfr_fn
                          sin_fn, mpfr_fn cos_fn)
{
        /*
           Using mpfr is not entirely overkill for this; [Lut95]
           includes PASCAL fragments that use almost entirely integer
           arithmetic... but the error term in that only handles
           up to 13 extra bits of zeroes or so. We proudly boast
           at least 16 bits of extra zeroes in all cases.
         */
        mpfr_t xi;
        mpfr_t xip1;
        mpfr_t cos;
        mpfr_t sin;
        double xip1_d;
        double t;
        uint64_t sin_u;
        uint64_t cos_u;
        int e1;
        int e2;
        uint64_t xip1_u;
        double xi_initial;
        uint64_t xi_initial_u;
        double xi_current;
        uint64_t xi_current_u;
        long int r = 0;
        long int best_r = 0;
        int sgn = 1;
        int ml = min_leeway;
        int best_l = 0;
        uint64_t best_xi_u;
        uint64_t best_sin_u;
        uint64_t best_cos_u;
        time_t start;
        time_t end;

        start = time(0);
        mpfr_init2(xi, 100);
        mpfr_init2(xip1, 100);
        mpfr_init2(cos, 100);
        mpfr_init2(sin, 100);

        /* start out at xi = πi/(4N) */
        mpfr_const_pi(xi, MPFR_RNDN);
        mpfr_mul_si(xip1, xi, (long int) (i + 1), MPFR_RNDN);
        mpfr_mul_si(xi, xi, (long int) i, MPFR_RNDN);
        mpfr_div_si(xi, xi, (long int) 4 * N, MPFR_RNDN);
        mpfr_div_si(xip1, xip1, (long int) 4 * N, MPFR_RNDN);
        xip1_d = mpfr_get_d(xip1, MPFR_RNDN);
        xip1_u = FLT64_TO_UINT64(xip1_d);
        xi_initial = mpfr_get_d(xi, MPFR_RNDN);
        xi_initial_u = FLT64_TO_UINT64(xi_initial);

        while (1) {
                xi_current_u = xi_initial_u + (sgn * r);
                xi_current = UINT64_TO_FLT64(xi_current_u);
                mpfr_set_d(xi, xi_current, MPFR_RNDN);

                /* Test if cos(xi) has enough zeroes */
                cos_fn(cos, xi, MPFR_RNDN);
                t = mpfr_get_d(cos, MPFR_RNDN);
                cos_u = FLT64_TO_UINT64(t);
                e1 = EXP_OF_FLT64(t);
                mpfr_sub_d(cos, cos, t, MPFR_RNDN);
                t = mpfr_get_d(cos, MPFR_RNDN);
                e2 = EXP_OF_FLT64(t);

                if (e2 == -1024) {

                        /* Damn; this is too close to a subnormal. i = 0 or N? */
                        return -1;
                }

                if (e1 - e2 < (52 + min_leeway)) {
                        goto inc;
                }

                ml = xmax(min_leeway, e1 - e2 - 52);

                /* Test if sin(xi) has enough zeroes */
                sin_fn(sin, xi, MPFR_RNDN);
                t = mpfr_get_d(sin, MPFR_RNDN);
                sin_u = FLT64_TO_UINT64(t);
                e1 = EXP_OF_FLT64(t);
                mpfr_sub_d(sin, sin, t, MPFR_RNDN);
                t = mpfr_get_d(sin, MPFR_RNDN);
                e2 = EXP_OF_FLT64(t);

                if (e2 == -1024) {

                        /* Damn; this is too close to a subnormal. i = 0 or N? */
                        return -1;
                }

                if (e1 - e2 < (52 + min_leeway)) {
                        goto inc;
                }

                ml = xmin(ml, e1 - e2 - 52);

                /* Hurrah, this is valid */
                if (ml > best_l) {
                        best_l = ml;
                        best_xi_u = xi_current_u;
                        best_cos_u = cos_u;
                        best_sin_u = sin_u;
                        best_r = sgn * r;

                        /* If this is super-good, don't bother finding more */
                        if (best_l >= perfect_leeway) {
                                break;
                        }
                }

inc:

                /* Increment */
                sgn *= -1;

                if (sgn < 0) {
                        r++;
                } else if (r > (1 << 29) ||
                           xi_current_u > xip1_u) {
                        /*
                           This is taking too long, give up looking
                           for perfection and take the best we've
                           got. A sweep of 1 << 28 finishes in ~60
                           hrs on my personal machine as I write
                           this.
                         */
                        break;
                }
        }

        end = time(0);

        if (best_l > min_leeway) {
                printf(
                        "(%#018lx, %#018lx, %#018lx), /* i = %03d, l = %02d, r = %010ld, t = %ld */ \n",
                        best_xi_u, best_cos_u, best_sin_u, i, best_l, best_r,
                        end -
                        start);

                return 0;
        } else {
                return -1;
        }
}
Ejemplo n.º 12
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;
}