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

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

1.1       ohara       1: /* mpfr_exp -- exponential of a floating-point number
                      2:
                      3: Copyright 1999, 2001, 2002 Free Software Foundation, Inc.
                      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 "gmp.h"
                     24: #include "gmp-impl.h"
                     25: #include "mpfr.h"
                     26: #include "mpfr-impl.h"
                     27:
                     28: static int mpfr_exp_rational _PROTO ((mpfr_ptr, mpz_srcptr, int, int));
                     29:
                     30: static int
                     31: mpfr_exp_rational (mpfr_ptr y, mpz_srcptr p, int r, int m)
                     32: {
                     33:   int n,i,k,j,l;
                     34:   mpz_t* P,*S;
                     35:   mpz_t* ptoj;
                     36:   int diff,expo;
                     37:   int precy = MPFR_PREC(y);
                     38:   int * mult;
                     39:   int prec_i_have;
                     40:   int *nb_terms;
                     41:   int accu;
                     42:   TMP_DECL (marker);
                     43:
                     44:   TMP_MARK (marker);
                     45:   n = 1 << m;
                     46:   P = (mpz_t*) TMP_ALLOC((m+1) * sizeof(mpz_t));
                     47:   S = (mpz_t*) TMP_ALLOC((m+1) * sizeof(mpz_t));
                     48:   ptoj = (mpz_t*) TMP_ALLOC((m+1) * sizeof(mpz_t)); /* ptoj[i] = mantissa^(2^i) */
                     49:   mult = (int*) TMP_ALLOC((m+1) * sizeof(int));
                     50:   nb_terms = (int*) TMP_ALLOC((m+1) * sizeof(int));
                     51:   mult[0] = 0;
                     52:   for (i=0;i<=m;i++) { mpz_init(P[i]); mpz_init(S[i]); mpz_init(ptoj[i]); }
                     53:   mpz_set(ptoj[0], p);
                     54:   for (i=1;i<m;i++) mpz_mul(ptoj[i], ptoj[i-1], ptoj[i-1]);
                     55:   mpz_set_ui(P[0], 1);
                     56:   mpz_set_ui(S[0], 1);
                     57:   k = 0;
                     58:   nb_terms[0] = 1;
                     59:    prec_i_have = 0;
                     60:    for (i=1;(prec_i_have < precy) && (i < n) ;i++) {
                     61:     k++;
                     62:     nb_terms[k] = 1;
                     63:     mpz_set_ui(P[k], i+1);
                     64:     mpz_set(S[k], P[k]);;
                     65:     j=i+1; l=0; while ((j & 1) == 0) {
                     66:       mpz_mul(S[k], S[k], ptoj[l]);
                     67:       mpz_mul(S[k-1], S[k-1], P[k]);
                     68:       mpz_mul_2exp(S[k-1], S[k-1], r*(1<<l));
                     69:       mpz_add(S[k-1], S[k-1], S[k]);
                     70:       mpz_mul(P[k-1], P[k-1], P[k]);
                     71:       nb_terms[k-1] = nb_terms[k-1]+ nb_terms[k];
                     72:       mult[k] = mult[k-1] + (1 << l)*(r >> 2) + mpz_sizeinbase(P[k],2) - 1;
                     73:       prec_i_have = mult[k];
                     74:       l++; j>>=1; k--;
                     75:     }
                     76:   }
                     77:    l = 0;
                     78:    accu = 0;
                     79:    while (k > 0){
                     80:      mpz_mul(S[k], S[k], ptoj[_mpfr_ceil_log2((double) nb_terms[k])]);
                     81:      mpz_mul(S[k-1], S[k-1], P[k]);
                     82:      accu += nb_terms[k];
                     83:      mpz_mul_2exp(S[k-1], S[k-1], r* accu);
                     84:      mpz_add(S[k-1], S[k-1], S[k]);
                     85:      mpz_mul(P[k-1], P[k-1], P[k]);
                     86:      l++; k--;
                     87:    }
                     88:
                     89:   diff = mpz_sizeinbase(S[0],2) - 2*precy;
                     90:   expo = diff;
                     91:   if (diff >=0)
                     92:     {
                     93:       mpz_div_2exp(S[0],S[0],diff);
                     94:     } else
                     95:       {
                     96:        mpz_mul_2exp(S[0],S[0],-diff);
                     97:       }
                     98:   diff = mpz_sizeinbase(P[0],2) - precy;
                     99:   expo -= diff;
                    100:   if (diff >=0)
                    101:     {
                    102:       mpz_div_2exp(P[0],P[0],diff);
                    103:     } else
                    104:       {
                    105:        mpz_mul_2exp(P[0],P[0],-diff);
                    106:        }
                    107:
                    108:   mpz_tdiv_q(S[0], S[0], P[0]);
                    109:   mpfr_set_z(y,S[0], GMP_RNDD);
                    110:   MPFR_EXP(y) += expo;
                    111:
                    112:   mpfr_div_2ui(y, y, r*(i-1),GMP_RNDN);
                    113:   for (i=0;i<=m;i++) { mpz_clear(P[i]); mpz_clear(S[i]); mpz_clear(ptoj[i]); }
                    114:   TMP_FREE (marker);
                    115:   return 0;
                    116: }
                    117:
                    118: #define shift (BITS_PER_MP_LIMB/2)
                    119:
                    120: int
                    121: mpfr_exp3 (mpfr_ptr y, mpfr_srcptr x, mp_rnd_t rnd_mode)
                    122: {
                    123:   mpfr_t t;
                    124:   mpfr_t x_copy;
                    125:   int i,k;
                    126:   mpz_t uk;
                    127:   mpfr_t tmp;
                    128:   int ttt;
                    129:   int twopoweri;
                    130:   int Prec;
                    131:   int loop;
                    132:   int prec_x;
                    133:   int shift_x = 0;
                    134:   int good = 0;
                    135:   int realprec = 0;
                    136:   int iter;
                    137:   int logn, inexact = 0;
                    138:
                    139:   /* decompose x */
                    140:   /* we first write x = 1.xxxxxxxxxxxxx
                    141:      ----- k bits -- */
                    142:   prec_x = _mpfr_ceil_log2 ((double) (MPFR_PREC(x)) / BITS_PER_MP_LIMB);
                    143:   if (prec_x < 0) prec_x = 0;
                    144:   logn =  _mpfr_ceil_log2 ((double) prec_x + MPFR_PREC(y));
                    145:   if (logn < 2) logn = 2;
                    146:   ttt = MPFR_EXP(x);
                    147:   mpfr_init2(x_copy,MPFR_PREC(x));
                    148:   mpfr_set(x_copy,x,GMP_RNDD);
                    149:   /* we shift to get a number less than 1 */
                    150:   if (ttt > 0)
                    151:     {
                    152:       shift_x = ttt;
                    153:       mpfr_div_2ui(x_copy, x, ttt, GMP_RNDN);
                    154:       ttt = MPFR_EXP(x_copy);
                    155:     }
                    156:   realprec = MPFR_PREC(y)+logn;
                    157:   mpz_init (uk);
                    158:   while (!good){
                    159:     Prec = realprec+shift+2+shift_x;
                    160:     k = _mpfr_ceil_log2 ((double) Prec / BITS_PER_MP_LIMB);
                    161:
                    162:     /* now we have to extract */
                    163:     mpfr_init2 (t, Prec);
                    164:     mpfr_init2 (tmp, Prec);
                    165:     mpfr_set_ui(tmp,1,GMP_RNDN);
                    166:     twopoweri = BITS_PER_MP_LIMB;
                    167:     if (k <= prec_x) iter = k; else iter= prec_x;
                    168:     for(i = 0; i <= iter; i++){
                    169:       mpfr_extract (uk, x_copy, i);
                    170:        if (i)
                    171:            mpfr_exp_rational (t, uk, twopoweri - ttt, k  - i + 1);
                    172:        else
                    173:          {
                    174:            /* particular case: we have to compute with x/2^., then
                    175:                do squarings (this is faster) */
                    176:              mpfr_exp_rational (t, uk, shift + twopoweri - ttt, k+1);
                    177:            for (loop= 0 ; loop < shift; loop++)
                    178:              mpfr_mul(t,t,t,GMP_RNDD);
                    179:
                    180:          }
                    181:        mpfr_mul(tmp,tmp,t,GMP_RNDD);
                    182:        twopoweri <<= 1;
                    183:     }
                    184:       mpfr_clear (t);
                    185:       for (loop= 0 ; loop < shift_x; loop++)
                    186:        mpfr_mul (tmp, tmp, tmp, GMP_RNDD);
                    187:       if (mpfr_can_round (tmp, realprec, GMP_RNDD, rnd_mode, MPFR_PREC(y)))
                    188:        {
                    189:          inexact = mpfr_set (y, tmp, rnd_mode);
                    190:          good = 1;
                    191:        }
                    192:       else
                    193:        realprec += 3*logn;
                    194:       mpfr_clear (tmp);
                    195:   }
                    196:   mpz_clear (uk);
                    197:   mpfr_clear(x_copy);
                    198:   return inexact;
                    199: }

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