Ejemplo n.º 1
0
/* Check mpfr_ui_sub with u = 0 (unsigned). */
static void check_neg (void)
{
  mpfr_t x, yneg, ysub;
  int i, s;
  int r;

  mpfr_init2 (x, 64);
  mpfr_init2 (yneg, 32);
  mpfr_init2 (ysub, 32);

  for (i = 0; i <= 25; i++)
    {
      mpfr_sqrt_ui (x, i, MPFR_RNDN);
      for (s = 0; s <= 1; s++)
        {
          RND_LOOP (r)
            {
              int tneg, tsub;

              tneg = mpfr_neg (yneg, x, (mpfr_rnd_t) r);
              tsub = mpfr_ui_sub (ysub, 0, x, (mpfr_rnd_t) r);
              MPFR_ASSERTN (mpfr_equal_p (yneg, ysub));
              MPFR_ASSERTN (!(MPFR_IS_POS (yneg) ^ MPFR_IS_POS (ysub)));
              MPFR_ASSERTN (tneg == tsub);
            }
          mpfr_neg (x, x, MPFR_RNDN);
        }
    }

  mpfr_clear (x);
  mpfr_clear (yneg);
  mpfr_clear (ysub);
}
Ejemplo n.º 2
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.º 3
0
static void
check (unsigned long a, mp_rnd_t rnd_mode, const char *qs)
{
  mpfr_t q;

  mpfr_init2 (q, 53);
  mpfr_sqrt_ui (q, a, rnd_mode);
  if (mpfr_cmp_str1 (q, qs))
    {
      printf ("mpfr_sqrt_ui failed for a=%lu, rnd_mode=%s\n",
              a, mpfr_print_rnd_mode (rnd_mode));
      printf ("sqrt gives %s, mpfr_sqrt_ui gives ", qs);
      mpfr_out_str(stdout, 10, 0, q, GMP_RNDN);
      exit (1);
    }
  mpfr_clear (q);
}
Ejemplo n.º 4
0
/* put in rop the value of exp(2*i*pi*k/n) rounded according to rnd */
int
mpc_rootofunity (mpc_ptr rop, unsigned long n, unsigned long k, mpc_rnd_t rnd)
{
   unsigned long g;
   mpq_t kn;
   mpfr_t t, s, c;
   mpfr_prec_t prec;
   int inex_re, inex_im;
   mpfr_rnd_t rnd_re, rnd_im;

   if (n == 0) {
      /* Compute exp (0 + i*inf). */
      mpfr_set_nan (mpc_realref (rop));
      mpfr_set_nan (mpc_imagref (rop));
      return MPC_INEX (0, 0);
   }

   /* Eliminate common denominator. */
   k %= n;
   g = gcd (k, n);
   k /= g;
   n /= g;

   /* Now 0 <= k < n and gcd(k,n)=1. */

   /* We assume that only n=1, 2, 3, 4, 6 and 12 may yield exact results
      and treat them separately; n=8 is also treated here for efficiency
      reasons. */
   if (n == 1)
     {
       /* necessarily k=0 thus we want exp(0)=1 */
       MPC_ASSERT (k == 0);
       return mpc_set_ui_ui (rop, 1, 0, rnd);
     }
   else if (n == 2)
     {
       /* since gcd(k,n)=1, necessarily k=1, thus we want exp(i*pi)=-1 */
       MPC_ASSERT (k == 1);
       return mpc_set_si_si (rop, -1, 0, rnd);
     }
   else if (n == 4)
     {
       /* since gcd(k,n)=1, necessarily k=1 or k=3, thus we want
          exp(2*i*pi/4)=i or exp(2*i*pi*3/4)=-i */
       MPC_ASSERT (k == 1 || k == 3);
       if (k == 1)
         return mpc_set_ui_ui (rop, 0, 1, rnd);
       else
         return mpc_set_si_si (rop, 0, -1, rnd);
     }
   else if (n == 3 || n == 6)
     {
       MPC_ASSERT ((n == 3 && (k == 1 || k == 2)) ||
                   (n == 6 && (k == 1 || k == 5)));
       /* for n=3, necessarily k=1 or k=2: -1/2+/-1/2*sqrt(3)*i;
          for n=6, necessarily k=1 or k=5: 1/2+/-1/2*sqrt(3)*i */
       inex_re = mpfr_set_si (mpc_realref (rop), (n == 3 ? -1 : 1),
                              MPC_RND_RE (rnd));
       /* inverse the rounding mode for -sqrt(3)/2 for zeta_3^2 and zeta_6^5 */
       rnd_im = MPC_RND_IM (rnd);
       if (k != 1)
         rnd_im = INV_RND (rnd_im);
       inex_im = mpfr_sqrt_ui (mpc_imagref (rop), 3, rnd_im);
       mpc_div_2ui (rop, rop, 1, MPC_RNDNN);
       if (k != 1)
         {
           mpfr_neg (mpc_imagref (rop), mpc_imagref (rop), MPFR_RNDN);
           inex_im = -inex_im;
         }
       return MPC_INEX (inex_re, inex_im);
     }
   else if (n == 12)
     {
       /* necessarily k=1, 5, 7, 11:
          k=1: 1/2*sqrt(3) + 1/2*I
          k=5: -1/2*sqrt(3) + 1/2*I
          k=7: -1/2*sqrt(3) - 1/2*I
          k=11: 1/2*sqrt(3) - 1/2*I */
       MPC_ASSERT (k == 1 || k == 5 || k == 7 || k == 11);
       /* inverse the rounding mode for -sqrt(3)/2 for zeta_12^5 and zeta_12^7 */
       rnd_re = MPC_RND_RE (rnd);
       if (k == 5 || k == 7)
         rnd_re = INV_RND (rnd_re);
       inex_re = mpfr_sqrt_ui (mpc_realref (rop), 3, rnd_re);
       inex_im = mpfr_set_si (mpc_imagref (rop), k < 6 ? 1 : -1,
                              MPC_RND_IM (rnd));
       mpc_div_2ui (rop, rop, 1, MPC_RNDNN);
       if (k == 5 || k == 7)
         {
           mpfr_neg (mpc_realref (rop), mpc_realref (rop), MPFR_RNDN);
           inex_re = -inex_re;
         }
       return MPC_INEX (inex_re, inex_im);
     }
   else if (n == 8)
     {
       /* k=1, 3, 5 or 7:
          k=1: (1/2*I + 1/2)*sqrt(2)
          k=3: (1/2*I - 1/2)*sqrt(2)
          k=5: -(1/2*I + 1/2)*sqrt(2)
          k=7: -(1/2*I - 1/2)*sqrt(2) */
       MPC_ASSERT (k == 1 || k == 3 || k == 5 || k == 7);
       rnd_re = MPC_RND_RE (rnd);
       if (k == 3 || k == 5)
         rnd_re = INV_RND (rnd_re);
       rnd_im = MPC_RND_IM (rnd);
       if (k > 4)
         rnd_im = INV_RND (rnd_im);
       inex_re = mpfr_sqrt_ui (mpc_realref (rop), 2, rnd_re);
       inex_im = mpfr_sqrt_ui (mpc_imagref (rop), 2, rnd_im);
       mpc_div_2ui (rop, rop, 1, MPC_RNDNN);
       if (k == 3 || k == 5)
         {
           mpfr_neg (mpc_realref (rop), mpc_realref (rop), MPFR_RNDN);
           inex_re = -inex_re;
         }
       if (k > 4)
         {
           mpfr_neg (mpc_imagref (rop), mpc_imagref (rop), MPFR_RNDN);
           inex_im = -inex_im;
         }
       return MPC_INEX (inex_re, inex_im);
     }

   prec = MPC_MAX_PREC(rop);

   /* For the error analysis justifying the following algorithm,
      see algorithms.tex. */
   mpfr_init2 (t, 67);
   mpfr_init2 (s, 67);
   mpfr_init2 (c, 67);
   mpq_init (kn);
   mpq_set_ui (kn, k, n);
   mpq_mul_2exp (kn, kn, 1); /* kn=2*k/n < 2 */

   do {
      prec += mpc_ceil_log2 (prec) + 5; /* prec >= 6 */

      mpfr_set_prec (t, prec);
      mpfr_set_prec (s, prec);
      mpfr_set_prec (c, prec);

      mpfr_const_pi (t, MPFR_RNDN);
      mpfr_mul_q (t, t, kn, MPFR_RNDN);
      mpfr_sin_cos (s, c, t, MPFR_RNDN);
   }
   while (   !mpfr_can_round (c, prec - (4 - mpfr_get_exp (c)),
                 MPFR_RNDN, MPFR_RNDZ,
                 MPC_PREC_RE(rop) + (MPC_RND_RE(rnd) == MPFR_RNDN))
          || !mpfr_can_round (s, prec - (4 - mpfr_get_exp (s)),
                 MPFR_RNDN, MPFR_RNDZ,
                 MPC_PREC_IM(rop) + (MPC_RND_IM(rnd) == MPFR_RNDN)));

   inex_re = mpfr_set (mpc_realref(rop), c, MPC_RND_RE(rnd));
   inex_im = mpfr_set (mpc_imagref(rop), s, MPC_RND_IM(rnd));

   mpfr_clear (t);
   mpfr_clear (s);
   mpfr_clear (c);
   mpq_clear (kn);

   return MPC_INEX(inex_re, inex_im);
}
Ejemplo n.º 5
0
int main(int argc, char **argv) {
    mpfr_t tmp1;
    mpfr_t tmp2;
    mpfr_t tmp3;
    mpfr_t s1;
    mpfr_t s2;
    mpfr_t r;
    mpfr_t a1;
    mpfr_t a2;

    time_t start_time;
    time_t end_time;

    // Parse command line opts
    int hide_pi = 0;
    if(argc == 2) {
        if(strcmp(argv[1], "--hide-pi") == 0) {
            hide_pi = 1;
        } else if((precision = atoi(argv[1])) == 0) {
            fprintf(stderr, "Invalid precision specified. Aborting.\n");
            return 1;
        }
    } else if(argc == 3) {
        if(strcmp(argv[1], "--hide-pi") == 0) {
            hide_pi = 1;
        }

        if((precision = atoi(argv[2])) == 0) {
            fprintf(stderr, "Invalid precision specified. Aborting.\n");
            return 1;
        }
    }

    // If the precision was not specified, default it
    if(precision == 0) {
        precision = DEFAULT_PRECISION;
    }


    // Actual number of correct digits is roughly 3.35 times the requested precision
    precision *= 3.35;

    mpfr_set_default_prec(precision);

    mpfr_inits(tmp1, tmp2, tmp3, s1, s2, r, a1, a2, NULL);

    start_time = time(NULL);

    // a0 = 1/3
    mpfr_set_ui(a1, 1, MPFR_RNDN);
    mpfr_div_ui(a1, a1, 3, MPFR_RNDN);

    // s0 = (3^.5 - 1) / 2
    mpfr_sqrt_ui(s1, 3, MPFR_RNDN);
    mpfr_sub_ui(s1, s1, 1, MPFR_RNDN);
    mpfr_div_ui(s1, s1, 2, MPFR_RNDN);

    unsigned long i = 0;
    while(i < MAX_ITERS) {
        // r = 3 / (1 + 2(1-s^3)^(1/3))
        mpfr_pow_ui(tmp1, s1, 3, MPFR_RNDN);
        mpfr_ui_sub(r, 1, tmp1, MPFR_RNDN);
        mpfr_root(r, r, 3, MPFR_RNDN);
        mpfr_mul_ui(r, r, 2, MPFR_RNDN);
        mpfr_add_ui(r, r, 1, MPFR_RNDN);
        mpfr_ui_div(r, 3, r, MPFR_RNDN);

        // s = (r - 1) / 2
        mpfr_sub_ui(s2, r, 1, MPFR_RNDN);
        mpfr_div_ui(s2, s2, 2, MPFR_RNDN);

        // a = r^2 * a - 3^i(r^2-1)
        mpfr_pow_ui(tmp1, r, 2, MPFR_RNDN);
        mpfr_mul(a2, tmp1, a1, MPFR_RNDN);
        mpfr_sub_ui(tmp1, tmp1, 1, MPFR_RNDN);
        mpfr_ui_pow_ui(tmp2, 3UL, i, MPFR_RNDN);
        mpfr_mul(tmp1, tmp1, tmp2, MPFR_RNDN);        
        mpfr_sub(a2, a2, tmp1, MPFR_RNDN);
        
        // s1 = s2
        mpfr_set(s1, s2, MPFR_RNDN);
        // a1 = a2
        mpfr_set(a1, a2, MPFR_RNDN);

        i++;
    }

    // pi = 1/a
    mpfr_ui_div(a2, 1, a2, MPFR_RNDN);

    end_time = time(NULL);

    mpfr_clears(tmp1, tmp2, tmp3, s1, s2, r, a1, NULL);

    // Write the digits to a string for accuracy comparison
    char *pi = malloc(precision + 100);
    if(pi == NULL) {
        fprintf(stderr, "Failed to allocated memory for output string.\n");
        return 1;
    }

    mpfr_sprintf(pi, "%.*R*f", precision, MPFR_RNDN, a2);

    // Check out accurate we are
    unsigned long accuracy = check_digits(pi);

    // Print the results (only print the digits that are accurate)
    if(!hide_pi) {
        // Plus two for the "3." at the beginning
        for(unsigned long i=0; i<(unsigned long)(precision/3.35)+2; i++) {
            printf("%c", pi[i]);
        }
        printf("\n");
    }    // Send the time and accuracy to stderr so pi can be redirected to a file if necessary
    fprintf(stderr, "Time: %d seconds\nAccuracy: %lu digits\n", (int)(end_time - start_time), accuracy);

    mpfr_clear(a2);
    free(pi);
    pi = NULL;

    return 0;
}
/* Don't need to save/restore exponent range: the cache does it.
   Catalan's constant is G = sum((-1)^k/(2*k+1)^2, k=0..infinity).
   We compute it using formula (31) of Victor Adamchik's page
   "33 representations for Catalan's constant"
   http://www-2.cs.cmu.edu/~adamchik/articles/catalan/catalan.htm

   G = Pi/8*log(2+sqrt(3)) + 3/8*sum(k!^2/(2k)!/(2k+1)^2,k=0..infinity)
*/
int
mpfr_const_catalan_internal (mpfr_ptr g, mpfr_rnd_t rnd_mode)
{
  mpfr_t x, y, z;
  mpz_t T, P, Q;
  mpfr_prec_t pg, p;
  int inex;
  MPFR_ZIV_DECL (loop);
  MPFR_GROUP_DECL (group);

  MPFR_LOG_FUNC (("rnd_mode=%d", rnd_mode), ("g[%#R]=%R inex=%d", g, g, inex));

  /* Here are the WC (max prec = 100.000.000)
     Once we have found a chain of 11, we only look for bigger chain.
     Found 3 '1' at 0
     Found 5 '1' at 9
     Found 6 '0' at 34
     Found 9 '1' at 176
     Found 11 '1' at 705
     Found 12 '0' at 913
     Found 14 '1' at 12762
     Found 15 '1' at 152561
     Found 16 '0' at 171725
     Found 18 '0' at 525355
     Found 20 '0' at 529245
     Found 21 '1' at 6390133
     Found 22 '0' at 7806417
     Found 25 '1' at 11936239
     Found 27 '1' at 51752950
  */
  pg = MPFR_PREC (g);
  p = pg + MPFR_INT_CEIL_LOG2 (pg) + 7;

  MPFR_GROUP_INIT_3 (group, p, x, y, z);
  mpz_init (T);
  mpz_init (P);
  mpz_init (Q);

  MPFR_ZIV_INIT (loop, p);
  for (;;) {
    mpfr_sqrt_ui (x, 3, MPFR_RNDU);
    mpfr_add_ui (x, x, 2, MPFR_RNDU);
    mpfr_log (x, x, MPFR_RNDU);
    mpfr_const_pi (y, MPFR_RNDU);
    mpfr_mul (x, x, y, MPFR_RNDN);
    S (T, P, Q, 0, (p - 1) / 2);
    mpz_mul_ui (T, T, 3);
    mpfr_set_z (y, T, MPFR_RNDU);
    mpfr_set_z (z, Q, MPFR_RNDD);
    mpfr_div (y, y, z, MPFR_RNDN);
    mpfr_add (x, x, y, MPFR_RNDN);
    mpfr_div_2ui (x, x, 3, MPFR_RNDN);

    if (MPFR_LIKELY (MPFR_CAN_ROUND (x, p - 5, pg, rnd_mode)))
      break;

    MPFR_ZIV_NEXT (loop, p);
    MPFR_GROUP_REPREC_3 (group, p, x, y, z);
  }
  MPFR_ZIV_FREE (loop);
  inex = mpfr_set (g, x, rnd_mode);

  MPFR_GROUP_CLEAR (group);
  mpz_clear (T);
  mpz_clear (P);
  mpz_clear (Q);

  return inex;
}