Beispiel #1
0
mps_boolean
mps_quadratic_poly_meval (mps_context * ctx, mps_polynomial * p, mpc_t x, mpc_t value, rdpe_t error)
{
  int i;
  int m = (int) (log (p->degree + 1.0) / LOG2);
  rdpe_t ax, rtmp;
  mpc_t tmp;
  long int wp = mpc_get_prec (x);

  /* Correct the working precision in case of a limited 
     precision polynomial (quite unlikely
   * in the quadratic case, but still. */
  if (p->prec > 0 && p->prec < wp)
    wp = p->prec;

  if ((1 << m) <= p->degree)
    m++;

  mpc_init2 (tmp, wp);

  mpc_rmod (ax, x);
  mpc_set_ui (value, 1U, 0U);
  mpc_rmod (error, value);

  for (i = 1; i <= m; i++)
    {
      mpc_sqr (tmp, value);
      mpc_mul (value, x, tmp);
      mpc_add_eq_ui (value, 1U, 0U);

      rdpe_mul_eq (error, ax);
      mpc_rmod (rtmp, value);
      rdpe_add_eq (error, rtmp);
    }

  rdpe_set_2dl (rtmp, 1.0, -wp);
  rdpe_mul_eq (error, rtmp);

  mpc_clear (tmp);

  return true;
}
Beispiel #2
0
static void
reuse_bug (void)
{
  mpc_t z1;

  /* reuse bug found by Paul Zimmermann 20081021 */
  mpc_init2 (z1, 2);
  /* RE (z1^2) overflows, IM(z^2) = -0 */
  mpfr_set_str (mpc_realref (z1), "0.11", 2, MPFR_RNDN);
  mpfr_mul_2si (mpc_realref (z1), mpc_realref (z1), mpfr_get_emax (), MPFR_RNDN);
  mpfr_set_ui (mpc_imagref (z1), 0, MPFR_RNDN);
  mpc_conj (z1, z1, MPC_RNDNN);
  mpc_sqr (z1, z1, MPC_RNDNN);
  if (!mpfr_inf_p (mpc_realref (z1)) || mpfr_signbit (mpc_realref (z1))
      ||!mpfr_zero_p (mpc_imagref (z1)) || !mpfr_signbit (mpc_imagref (z1)))
    {
      printf ("Error: Regression, bug 20081021 reproduced\n");
      MPC_OUT (z1);
      exit (1);
    }

  mpc_clear (z1);
}
Beispiel #3
0
int
mpc_asin (mpc_ptr rop, mpc_srcptr op, mpc_rnd_t rnd)
{
  mpfr_prec_t p, p_re, p_im, incr_p = 0;
  mpfr_rnd_t rnd_re, rnd_im;
  mpc_t z1;
  int inex;

  /* special values */
  if (mpfr_nan_p (mpc_realref (op)) || mpfr_nan_p (mpc_imagref (op)))
    {
      if (mpfr_inf_p (mpc_realref (op)) || mpfr_inf_p (mpc_imagref (op)))
        {
          mpfr_set_nan (mpc_realref (rop));
          mpfr_set_inf (mpc_imagref (rop), mpfr_signbit (mpc_imagref (op)) ? -1 : +1);
        }
      else if (mpfr_zero_p (mpc_realref (op)))
        {
          mpfr_set (mpc_realref (rop), mpc_realref (op), GMP_RNDN);
          mpfr_set_nan (mpc_imagref (rop));
        }
      else
        {
          mpfr_set_nan (mpc_realref (rop));
          mpfr_set_nan (mpc_imagref (rop));
        }

      return 0;
    }

  if (mpfr_inf_p (mpc_realref (op)) || mpfr_inf_p (mpc_imagref (op)))
    {
      int inex_re;
      if (mpfr_inf_p (mpc_realref (op)))
        {
          int inf_im = mpfr_inf_p (mpc_imagref (op));

          inex_re = set_pi_over_2 (mpc_realref (rop),
             (mpfr_signbit (mpc_realref (op)) ? -1 : 1), MPC_RND_RE (rnd));
          mpfr_set_inf (mpc_imagref (rop), (mpfr_signbit (mpc_imagref (op)) ? -1 : 1));

          if (inf_im)
            mpfr_div_2ui (mpc_realref (rop), mpc_realref (rop), 1, GMP_RNDN);
        }
      else
        {
          mpfr_set_zero (mpc_realref (rop), (mpfr_signbit (mpc_realref (op)) ? -1 : 1));
          inex_re = 0;
          mpfr_set_inf (mpc_imagref (rop), (mpfr_signbit (mpc_imagref (op)) ? -1 : 1));
        }

      return MPC_INEX (inex_re, 0);
    }

  /* pure real argument */
  if (mpfr_zero_p (mpc_imagref (op)))
    {
      int inex_re;
      int inex_im;
      int s_im;
      s_im = mpfr_signbit (mpc_imagref (op));

      if (mpfr_cmp_ui (mpc_realref (op), 1) > 0)
        {
          if (s_im)
            inex_im = -mpfr_acosh (mpc_imagref (rop), mpc_realref (op),
                                   INV_RND (MPC_RND_IM (rnd)));
          else
            inex_im = mpfr_acosh (mpc_imagref (rop), mpc_realref (op),
                                  MPC_RND_IM (rnd));
          inex_re = set_pi_over_2 (mpc_realref (rop),
             (mpfr_signbit (mpc_realref (op)) ? -1 : 1), MPC_RND_RE (rnd));
          if (s_im)
            mpc_conj (rop, rop, MPC_RNDNN);
        }
      else if (mpfr_cmp_si (mpc_realref (op), -1) < 0)
        {
          mpfr_t minus_op_re;
          minus_op_re[0] = mpc_realref (op)[0];
          MPFR_CHANGE_SIGN (minus_op_re);

          if (s_im)
            inex_im = -mpfr_acosh (mpc_imagref (rop), minus_op_re,
                                   INV_RND (MPC_RND_IM (rnd)));
          else
            inex_im = mpfr_acosh (mpc_imagref (rop), minus_op_re,
                                  MPC_RND_IM (rnd));
          inex_re = set_pi_over_2 (mpc_realref (rop),
             (mpfr_signbit (mpc_realref (op)) ? -1 : 1), MPC_RND_RE (rnd));
          if (s_im)
            mpc_conj (rop, rop, MPC_RNDNN);
        }
      else
        {
          inex_im = mpfr_set_ui (mpc_imagref (rop), 0, MPC_RND_IM (rnd));
          if (s_im)
            mpfr_neg (mpc_imagref (rop), mpc_imagref (rop), GMP_RNDN);
          inex_re = mpfr_asin (mpc_realref (rop), mpc_realref (op), MPC_RND_RE (rnd));
        }

      return MPC_INEX (inex_re, inex_im);
    }

  /* pure imaginary argument */
  if (mpfr_zero_p (mpc_realref (op)))
    {
      int inex_im;
      int s;
      s = mpfr_signbit (mpc_realref (op));
      mpfr_set_ui (mpc_realref (rop), 0, GMP_RNDN);
      if (s)
        mpfr_neg (mpc_realref (rop), mpc_realref (rop), GMP_RNDN);
      inex_im = mpfr_asinh (mpc_imagref (rop), mpc_imagref (op), MPC_RND_IM (rnd));

      return MPC_INEX (0, inex_im);
    }

  /* regular complex: asin(z) = -i*log(i*z+sqrt(1-z^2)) */
  p_re = mpfr_get_prec (mpc_realref(rop));
  p_im = mpfr_get_prec (mpc_imagref(rop));
  rnd_re = MPC_RND_RE(rnd);
  rnd_im = MPC_RND_IM(rnd);
  p = p_re >= p_im ? p_re : p_im;
  mpc_init2 (z1, p);
  while (1)
  {
    mpfr_exp_t ex, ey, err;

    p += mpc_ceil_log2 (p) + 3 + incr_p; /* incr_p is zero initially */
    incr_p = p / 2;
    mpfr_set_prec (mpc_realref(z1), p);
    mpfr_set_prec (mpc_imagref(z1), p);

    /* z1 <- z^2 */
    mpc_sqr (z1, op, MPC_RNDNN);
    /* err(x) <= 1/2 ulp(x), err(y) <= 1/2 ulp(y) */
    /* z1 <- 1-z1 */
    ex = mpfr_get_exp (mpc_realref(z1));
    mpfr_ui_sub (mpc_realref(z1), 1, mpc_realref(z1), GMP_RNDN);
    mpfr_neg (mpc_imagref(z1), mpc_imagref(z1), GMP_RNDN);
    ex = ex - mpfr_get_exp (mpc_realref(z1));
    ex = (ex <= 0) ? 0 : ex;
    /* err(x) <= 2^ex * ulp(x) */
    ex = ex + mpfr_get_exp (mpc_realref(z1)) - p;
    /* err(x) <= 2^ex */
    ey = mpfr_get_exp (mpc_imagref(z1)) - p - 1;
    /* err(y) <= 2^ey */
    ex = (ex >= ey) ? ex : ey; /* err(x), err(y) <= 2^ex, i.e., the norm
                                  of the error is bounded by |h|<=2^(ex+1/2) */
    /* z1 <- sqrt(z1): if z1 = z + h, then sqrt(z1) = sqrt(z) + h/2/sqrt(t) */
    ey = mpfr_get_exp (mpc_realref(z1)) >= mpfr_get_exp (mpc_imagref(z1))
      ? mpfr_get_exp (mpc_realref(z1)) : mpfr_get_exp (mpc_imagref(z1));
    /* we have |z1| >= 2^(ey-1) thus 1/|z1| <= 2^(1-ey) */
    mpc_sqrt (z1, z1, MPC_RNDNN);
    ex = (2 * ex + 1) - 2 - (ey - 1); /* |h^2/4/|t| <= 2^ex */
    ex = (ex + 1) / 2; /* ceil(ex/2) */
    /* express ex in terms of ulp(z1) */
    ey = mpfr_get_exp (mpc_realref(z1)) <= mpfr_get_exp (mpc_imagref(z1))
      ? mpfr_get_exp (mpc_realref(z1)) : mpfr_get_exp (mpc_imagref(z1));
    ex = ex - ey + p;
    /* take into account the rounding error in the mpc_sqrt call */
    err = (ex <= 0) ? 1 : ex + 1;
    /* err(x) <= 2^err * ulp(x), err(y) <= 2^err * ulp(y) */
    /* z1 <- i*z + z1 */
    ex = mpfr_get_exp (mpc_realref(z1));
    ey = mpfr_get_exp (mpc_imagref(z1));
    mpfr_sub (mpc_realref(z1), mpc_realref(z1), mpc_imagref(op), GMP_RNDN);
    mpfr_add (mpc_imagref(z1), mpc_imagref(z1), mpc_realref(op), GMP_RNDN);
    if (mpfr_cmp_ui (mpc_realref(z1), 0) == 0 || mpfr_cmp_ui (mpc_imagref(z1), 0) == 0)
      continue;
    ex -= mpfr_get_exp (mpc_realref(z1)); /* cancellation in x */
    ey -= mpfr_get_exp (mpc_imagref(z1)); /* cancellation in y */
    ex = (ex >= ey) ? ex : ey; /* maximum cancellation */
    err += ex;
    err = (err <= 0) ? 1 : err + 1; /* rounding error in sub/add */
    /* z1 <- log(z1): if z1 = z + h, then log(z1) = log(z) + h/t with
       |t| >= min(|z1|,|z|) */
    ex = mpfr_get_exp (mpc_realref(z1));
    ey = mpfr_get_exp (mpc_imagref(z1));
    ex = (ex >= ey) ? ex : ey;
    err += ex - p; /* revert to absolute error <= 2^err */
    mpc_log (z1, z1, GMP_RNDN);
    err -= ex - 1; /* 1/|t| <= 1/|z| <= 2^(1-ex) */
    /* express err in terms of ulp(z1) */
    ey = mpfr_get_exp (mpc_realref(z1)) <= mpfr_get_exp (mpc_imagref(z1))
      ? mpfr_get_exp (mpc_realref(z1)) : mpfr_get_exp (mpc_imagref(z1));
    err = err - ey + p;
    /* take into account the rounding error in the mpc_log call */
    err = (err <= 0) ? 1 : err + 1;
    /* z1 <- -i*z1 */
    mpfr_swap (mpc_realref(z1), mpc_imagref(z1));
    mpfr_neg (mpc_imagref(z1), mpc_imagref(z1), GMP_RNDN);
    if (mpfr_can_round (mpc_realref(z1), p - err, GMP_RNDN, GMP_RNDZ,
                        p_re + (rnd_re == GMP_RNDN)) &&
        mpfr_can_round (mpc_imagref(z1), p - err, GMP_RNDN, GMP_RNDZ,
                        p_im + (rnd_im == GMP_RNDN)))
      break;
  }

  inex = mpc_set (rop, z1, rnd);
  mpc_clear (z1);

  return inex;
}
Beispiel #4
0
/******************************************************
*              SUBROUTINE MNEWTON_USR                 *   
******************************************************* 
 multiprecision computation
******************************************************/
void
mnewton_usr (mpc_t x, rdpe_t rad, mpc_t corr, mps_boolean * again)
{
  int i, m;
  rdpe_t ap, ax, eps, temp, apeps, atmp;
  cdpe_t ctmp;
  tmpc_t p, pp, pt, tmp;

  tmpc_init2 (p, mpwp);
  tmpc_init2 (pp, mpwp);
  tmpc_init2 (pt, mpwp);
  tmpc_init2 (tmp, mpwp);

  m = (int) (log (n + 1.0) / LOG2);
  if ((1 << m) <= n)
    m++;
  rdpe_set (eps, mp_epsilon);
  rdpe_mul_eq_d (eps, (double) 4 * n);
  mpc_get_cdpe (ctmp, x);
  cdpe_mod (ax, ctmp);

  mpc_set_ui (p, 1, 0);
  mpc_set_ui (pp, 0, 0);
  rdpe_set (ap, rdpe_one);
  for (i = 1; i <= m; i++)
    {
      mpc_sqr (tmp, p);
      mpc_mul (pt, x, tmp);
      mpc_add_eq_ui (pt, 1, 0);
      mpc_mul_eq (pp, x);
      mpc_mul_eq (pp, p);
      mpc_mul_eq_ui (pp, 2);
      mpc_add_eq (pp, tmp);
      mpc_set (p, pt);
      rdpe_mul_eq (ap, ax);
      mpc_get_cdpe (ctmp, p);
      cdpe_mod (atmp, ctmp);
      rdpe_add_eq (ap, atmp);
    }
  rdpe_mul_eq (ap, ax);
  mpc_div (corr, p, pp);

  mpc_get_cdpe (ctmp, p);
  cdpe_mod (temp, ctmp);
  rdpe_mul (apeps, ap, eps);
  rdpe_mul_eq_d (apeps, 3.0);
  *again = rdpe_gt (temp, apeps);

  rdpe_add (rad, temp, apeps);
  rdpe_mul_eq_d (rad, (double) n);
  mpc_get_cdpe (ctmp, pp);
  cdpe_mod (temp, ctmp);
  rdpe_div_eq (rad, temp);
  if (rdpe_eq (rad, rdpe_zero))
    rdpe_mul (rad, ax, eps);

  tmpc_clear (tmp);
  tmpc_clear (pt);
  tmpc_clear (pp);
  tmpc_clear (p);
}
Beispiel #5
0
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);
}
Beispiel #6
0
/**
 * @brief User-defined program for the computation of \f$p\f$, \f$p'\f$. 
 *
 * @param s The current mps_context
 * @param poly The mps_polynomial being solved. 
 * @param root The approximation whose Newton correction shall be computed. 
 * @param corr The output value where the newton correction will be stored. 
 *
 * This sample computes the 'Quadratic polynomial by  
 * means of the relation: p=1+x*p**2, starting with p=1
 */
void 
mps_quadratic_poly_mnewton (mps_context * ctx, mps_polynomial * poly, 
			     mps_approximation * root, mpc_t corr, long int wp)
{
  int i, m, n = poly->degree;
  rdpe_t ap, ax, eps, temp, apeps, atmp, epsilon, drad;
  cdpe_t ctmp;
  mpc_t p, pp, pt, tmp, x;
  mps_boolean again;

  mpc_init2 (p, wp);
  mpc_init2 (pp, wp);
  mpc_init2 (pt, wp);
  mpc_init2 (tmp, wp);

  mpc_init2 (x, wp);
  mps_approximation_get_mvalue (ctx, root, x);
  mps_approximation_get_drad (ctx, root, drad);
  again = mps_approximation_get_again (ctx, root);
  
  rdpe_set_2dl (epsilon, 1.0, 2 - wp);

  m = (int) (log (n + 1.0) / LOG2);
  if ((1 << m) <= n)
    m++;
  rdpe_set (eps, epsilon);
  rdpe_mul_eq_d (eps, (double) 4 * n);
  mpc_get_cdpe (ctmp, x);
  cdpe_mod (ax, ctmp);

  mpc_set_ui (p, 1, 0);
  mpc_set_ui (pp, 0, 0);
  rdpe_set (ap, rdpe_one);
  for (i = 1; i <= m; i++)
    {
      mpc_sqr (tmp, p);
      mpc_mul (pt, x, tmp);
      mpc_add_eq_ui (pt, 1, 0);
      mpc_mul_eq (pp, x);
      mpc_mul_eq (pp, p);
      mpc_mul_eq_ui (pp, 2);
      mpc_add_eq (pp, tmp);
      mpc_set (p, pt);
      rdpe_mul_eq (ap, ax);
      mpc_get_cdpe (ctmp, p);
      cdpe_mod (atmp, ctmp);
      rdpe_add_eq (ap, atmp);
    }
  rdpe_mul_eq (ap, ax);
  mpc_div (corr, p, pp);

  mpc_get_cdpe (ctmp, p);
  cdpe_mod (temp, ctmp);
  rdpe_mul (apeps, ap, eps);
  rdpe_mul_eq_d (apeps, 3.0);
  mps_approximation_set_again (ctx, root, rdpe_gt (temp, apeps));

  rdpe_add (drad, temp, apeps);
  rdpe_mul_eq_d (drad, (double) n);
  mpc_get_cdpe (ctmp, pp);
  cdpe_mod (temp, ctmp);
  rdpe_div_eq (drad, temp);
  if (rdpe_eq (drad, rdpe_zero))
    rdpe_mul (drad, ax, eps);

  mps_approximation_set_drad (ctx, root, drad);
  mps_approximation_set_again (ctx, root, again);

  mpc_clear (tmp);
  mpc_clear (pt);
  mpc_clear (pp);
  mpc_clear (p);
  mpc_clear (x);
}
Beispiel #7
0
void mpcomplex::sqr3() {
    mpc_sqr(mpc_val, mpc_val, default_rnd);
}