[BACK]Return to const_pi.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / gmp / mpfr

Annotation of OpenXM_contrib/gmp/mpfr/const_pi.c, Revision 1.1.1.1

1.1       ohara       1: /* mpfr_const_pi -- compute Pi
                      2:
                      3: Copyright 1999, 2000, 2001 Free Software Foundation.
                      4:
                      5: This file is part of the MPFR Library.
                      6:
                      7: The MPFR Library is free software; you can redistribute it and/or modify
                      8: it under the terms of the GNU Lesser General Public License as published by
                      9: the Free Software Foundation; either version 2.1 of the License, or (at your
                     10: option) any later version.
                     11:
                     12: The MPFR Library is distributed in the hope that it will be useful, but
                     13: WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     14: or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
                     15: License for more details.
                     16:
                     17: You should have received a copy of the GNU Lesser General Public License
                     18: along with the MPFR Library; see the file COPYING.LIB.  If not, write to
                     19: the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
                     20: MA 02111-1307, USA. */
                     21:
                     22: #include <stdio.h>
                     23: #include <stdlib.h>
                     24: #include "gmp.h"
                     25: #include "gmp-impl.h"
                     26: #include "longlong.h"
                     27: #include "mpfr.h"
                     28: #include "mpfr-impl.h"
                     29:
                     30: static int mpfr_aux_pi _PROTO ((mpfr_ptr, mpz_srcptr, int, int));
                     31: static int mpfr_pi_machin3 _PROTO ((mpfr_ptr, mp_rnd_t));
                     32:
                     33: #define A
                     34: #define A1 1
                     35: #define A2 2
                     36: #undef B
                     37: #define C
                     38: #define C1 3
                     39: #define C2 2
                     40: #define GENERIC mpfr_aux_pi
                     41: #define R_IS_RATIONAL
                     42: #define NO_FACTORIAL
                     43: #include "generic.c"
                     44:
                     45:
                     46: static int
                     47: mpfr_pi_machin3 (mpfr_ptr mylog, mp_rnd_t rnd_mode)
                     48: {
                     49:   int prec, logn, prec_x;
                     50:   int prec_i_want=MPFR_PREC(mylog);
                     51:   int good = 0;
                     52:   mpfr_t tmp1, tmp2, result,tmp3,tmp4,tmp5,tmp6;
                     53:   mpz_t cst;
                     54:
                     55:   MPFR_CLEAR_FLAGS(mylog);
                     56:   logn =  _mpfr_ceil_log2 ((double) MPFR_PREC(mylog));
                     57:   prec_x = prec_i_want + logn + 5;
                     58:   mpz_init(cst);
                     59:   while (!good){
                     60:   prec = _mpfr_ceil_log2 ((double) prec_x);
                     61:
                     62:   mpfr_init2(tmp1, prec_x);
                     63:   mpfr_init2(tmp2, prec_x);
                     64:   mpfr_init2(tmp3, prec_x);
                     65:   mpfr_init2(tmp4, prec_x);
                     66:   mpfr_init2(tmp5, prec_x);
                     67:   mpfr_init2(tmp6, prec_x);
                     68:   mpfr_init2(result, prec_x);
                     69:   mpz_set_si(cst, -1);
                     70:
                     71:   mpfr_aux_pi(tmp1, cst, 268*268, prec - 4);
                     72:   mpfr_div_ui(tmp1, tmp1, 268, GMP_RNDD);
                     73:   mpfr_mul_ui(tmp1, tmp1, 61, GMP_RNDD);
                     74:
                     75:   mpfr_aux_pi(tmp2, cst, 343*343, prec - 4);
                     76:   mpfr_div_ui(tmp2, tmp2, 343, GMP_RNDD);
                     77:   mpfr_mul_ui(tmp2, tmp2, 122, GMP_RNDD);
                     78:
                     79:   mpfr_aux_pi(tmp3, cst, 557*557, prec - 4);
                     80:   mpfr_div_ui(tmp3, tmp3, 557, GMP_RNDD);
                     81:   mpfr_mul_ui(tmp3, tmp3, 115, GMP_RNDD);
                     82:
                     83:   mpfr_aux_pi(tmp4, cst, 1068*1068, prec - 4);
                     84:   mpfr_div_ui(tmp4, tmp4, 1068, GMP_RNDD);
                     85:   mpfr_mul_ui(tmp4, tmp4, 32, GMP_RNDD);
                     86:
                     87:   mpfr_aux_pi(tmp5, cst, 3458*3458, prec - 4);
                     88:   mpfr_div_ui(tmp5, tmp5, 3458, GMP_RNDD);
                     89:   mpfr_mul_ui(tmp5, tmp5, 83, GMP_RNDD);
                     90:
                     91:   mpfr_aux_pi(tmp6, cst, 27493*27493, prec - 4);
                     92:   mpfr_div_ui(tmp6, tmp6, 27493, GMP_RNDD);
                     93:   mpfr_mul_ui(tmp6, tmp6, 44, GMP_RNDD);
                     94:
                     95:   mpfr_add(result, tmp1, tmp2, GMP_RNDD);
                     96:   mpfr_add(result, result, tmp3, GMP_RNDD);
                     97:   mpfr_sub(result, result, tmp4, GMP_RNDD);
                     98:   mpfr_add(result, result, tmp5, GMP_RNDD);
                     99:   mpfr_add(result, result, tmp6, GMP_RNDD);
                    100:   mpfr_mul_2ui(result, result, 2, GMP_RNDD);
                    101:   mpfr_clear(tmp1);
                    102:   mpfr_clear(tmp2);
                    103:   mpfr_clear(tmp3);
                    104:   mpfr_clear(tmp4);
                    105:   mpfr_clear(tmp5);
                    106:   mpfr_clear(tmp6);
                    107:   if (mpfr_can_round(result, prec_x - 5, GMP_RNDD, rnd_mode, prec_i_want)){
                    108:     mpfr_set(mylog, result, rnd_mode);
                    109:     mpfr_clear(result);
                    110:     good = 1;
                    111:   } else
                    112:     {
                    113:       mpfr_clear(result);
                    114:       prec_x += logn;
                    115:       }
                    116:   }
                    117:   mpz_clear(cst);
                    118:   return 0;
                    119: }
                    120:
                    121: /*
                    122: Set x to the value of Pi to precision MPFR_PREC(x) rounded to direction rnd_mode.
                    123: Use the formula giving the binary representation of Pi found by Simon Plouffe
                    124: and the Borwein's brothers:
                    125:
                    126:                    infinity    4         2         1         1
                    127:                     -----   ------- - ------- - ------- - -------
                    128:                      \      8 n + 1   8 n + 4   8 n + 5   8 n + 6
                    129:               Pi =    )     -------------------------------------
                    130:                      /                         n
                    131:                     -----                    16
                    132:                     n = 0
                    133:
                    134: i.e. Pi*16^N = S(N) + R(N) where
                    135: S(N) = sum(16^(N-n)*(4/(8*n+1)-2/(8*n+4)-1/(8*n+5)-1/(8*n+6)), n=0..N-1)
                    136: R(N) = sum((4/(8*n+1)-2/(8*n+4)-1/(8*n+5)-1/(8*n+6))/16^(n-N), n=N..infinity)
                    137:
                    138: Let f(n) = 4/(8*n+1)-2/(8*n+4)-1/(8*n+5)-1/(8*n+6), we can show easily that
                    139: f(n) < 15/(64*n^2), so R(N) < sum(15/(64*n^2)/16^(n-N), n=N..infinity)
                    140:                             < 15/64/N^2*sum(1/16^(n-N), n=N..infinity)
                    141:                            = 1/4/N^2
                    142:
                    143: Now let S'(N) = sum(floor(16^(N-n)*(120*n^2+151*n+47),
                    144:   (512*n^4+1024*n^3+712*n^2+194*n+15)), n=0..N-1)
                    145:
                    146: S(N)-S'(N) <= sum(1, n=0..N-1) = N
                    147:
                    148: so Pi*16^N-S'(N) <= N+1 (as 1/4/N^2 < 1)
                    149: */
                    150:
                    151: mpfr_t __mpfr_const_pi; /* stored value of Pi */
                    152: int __mpfr_const_pi_prec=0; /* precision of stored value */
                    153: mp_rnd_t __mpfr_const_pi_rnd; /* rounding mode of stored value */
                    154:
                    155: void
                    156: mpfr_const_pi (mpfr_ptr x, mp_rnd_t rnd_mode)
                    157: {
                    158:   int N, oldN, n, prec; mpz_t pi, num, den, d3, d2, tmp; mpfr_t y;
                    159:
                    160:   prec=MPFR_PREC(x);
                    161:
                    162:   /* has stored value enough precision ? */
                    163:   if ((prec==__mpfr_const_pi_prec && rnd_mode==__mpfr_const_pi_rnd) ||
                    164:       (prec<=__mpfr_const_pi_prec &&
                    165:       mpfr_can_round(__mpfr_const_pi, __mpfr_const_pi_prec,
                    166:                     __mpfr_const_pi_rnd, rnd_mode, prec)))
                    167:     {
                    168:       mpfr_set(x, __mpfr_const_pi, rnd_mode); return;
                    169:     }
                    170:
                    171:   if (prec < 20000){
                    172:     /* need to recompute */
                    173:     N=1;
                    174:     do {
                    175:       oldN = N;
                    176:       N = (prec+3)/4 + _mpfr_ceil_log2((double) N + 1.0);
                    177:     } while (N != oldN);
                    178:     mpz_init(pi); mpz_init(num); mpz_init(den); mpz_init(d3); mpz_init(d2);
                    179:     mpz_init(tmp);
                    180:     mpz_set_ui(pi, 0);
                    181:     mpz_set_ui(num, 16); /* num(-1) */
                    182:     mpz_set_ui(den, 21); /* den(-1) */
                    183:     mpz_set_si(d3, -2454);
                    184:     mpz_set_ui(d2, 14736);
                    185:   /* invariants: num=120*n^2+151*n+47, den=512*n^4+1024*n^3+712*n^2+194*n+15
                    186:      d3 = 2048*n^3+400*n-6, d2 = 6144*n^2-6144*n+2448
                    187:    */
                    188:     for (n=0; n<N; n++) {
                    189:       /* num(n)-num(n-1) = 240*n+31 */
                    190:       mpz_add_ui(num, num, 240*n+31); /* no overflow up to MPFR_PREC=71M */
                    191:       /* d2(n) - d2(n-1) = 12288*(n-1) */
                    192:       if (n>0) mpz_add_ui(d2, d2, 12288*(n-1));
                    193:       else mpz_sub_ui(d2, d2, 12288);
                    194:       /* d3(n) - d3(n-1) = d2 */
                    195:       mpz_add(d3, d3, d2);
                    196:       /* den(n)-den(n-1) = 2048*n^3 + 400n - 6 = d3 */
                    197:       mpz_add(den, den, d3);
                    198:       mpz_mul_2exp(tmp, num, 4*(N-n));
                    199:       mpz_fdiv_q(tmp, tmp, den);
                    200:       mpz_add(pi, pi, tmp);
                    201:     }
                    202:     mpfr_set_z(x, pi, rnd_mode);
                    203:     mpfr_init2(y, mpfr_get_prec(x));
                    204:     mpz_add_ui(pi, pi, N+1);
                    205:     mpfr_set_z(y, pi, rnd_mode);
                    206:     if (mpfr_cmp(x, y) != 0) {
                    207:       fprintf(stderr, "does not converge\n"); exit(1);
                    208:     }
                    209:     MPFR_EXP(x) -= 4*N;
                    210:     mpz_clear(pi); mpz_clear(num); mpz_clear(den); mpz_clear(d3); mpz_clear(d2);
                    211:     mpz_clear(tmp); mpfr_clear(y);
                    212:   } else
                    213:      mpfr_pi_machin3(x, rnd_mode);
                    214:   /* store computed value */
                    215:   if (__mpfr_const_pi_prec==0) mpfr_init2(__mpfr_const_pi, prec);
                    216:   else mpfr_set_prec(__mpfr_const_pi, prec);
                    217:   mpfr_set(__mpfr_const_pi, x, rnd_mode);
                    218:   __mpfr_const_pi_prec=prec;
                    219:   __mpfr_const_pi_rnd=rnd_mode;
                    220: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>