| version 1.1, 2000/09/09 14:12:19 |
version 1.1.1.2, 2003/08/25 16:06:06 |
|
|
| /* mpfr_agm -- arithmetic-geometric mean of two floating-point numbers |
/* mpfr_agm -- arithmetic-geometric mean of two floating-point numbers |
| |
|
| Copyright (C) 1999 PolKA project, Inria Lorraine and Loria |
Copyright 1999, 2000, 2001, 2002 Free Software Foundation. |
| |
|
| This file is part of the MPFR Library. |
This file is part of the MPFR Library. |
| |
|
| The MPFR Library is free software; you can redistribute it and/or modify |
The MPFR Library is free software; you can redistribute it and/or modify |
| it under the terms of the GNU Library General Public License as published by |
it under the terms of the GNU Lesser General Public License as published by |
| the Free Software Foundation; either version 2 of the License, or (at your |
the Free Software Foundation; either version 2.1 of the License, or (at your |
| option) any later version. |
option) any later version. |
| |
|
| The MPFR Library is distributed in the hope that it will be useful, but |
The MPFR Library is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
| or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public |
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public |
| License for more details. |
License for more details. |
| |
|
| You should have received a copy of the GNU Library General Public License |
You should have received a copy of the GNU Lesser General Public License |
| along with the MPFR Library; see the file COPYING.LIB. If not, write to |
along with the MPFR Library; see the file COPYING.LIB. If not, write to |
| the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, |
the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, |
| MA 02111-1307, USA. */ |
MA 02111-1307, USA. */ |
| |
|
| #include <stdio.h> |
|
| #include <math.h> |
|
| #include "gmp.h" |
#include "gmp.h" |
| #include "gmp-impl.h" |
#include "gmp-impl.h" |
| #include "mpfr.h" |
#include "mpfr.h" |
| |
#include "mpfr-impl.h" |
| |
|
| |
|
| /*Memory gestion */ |
|
| #define MON_INIT(xp, x, p, s) xp = (mp_ptr) TMP_ALLOC(s*BYTES_PER_MP_LIMB); x -> _mp_prec = p; x -> _mp_d = xp; x -> _mp_size = s; x -> _mp_exp = 0; |
|
| |
|
| |
|
| |
|
| |
|
| void |
void |
| #ifdef __STDC__ |
mpfr_agm (mpfr_ptr r, mpfr_srcptr op2, mpfr_srcptr op1, mp_rnd_t rnd_mode) |
| mpfr_agm(mpfr_ptr r, mpfr_srcptr op2, mpfr_srcptr op1, unsigned char rnd_mode) |
|
| #else |
|
| mpfr_agm(r, a, b, rnd_mode) |
|
| mpfr_ptr r; |
|
| mpfr_srcptr a; |
|
| mpfr_srcptr b; |
|
| unsigned char rnd_mode; |
|
| #endif |
|
| { |
{ |
| int s, p, q, go_on; |
int s, go_on, compare; |
| |
mp_prec_t p, q; |
| double uo, vo; |
double uo, vo; |
| mp_limb_t *up, *vp, *tmpp, *tmpup, *tmpvp, *ap, *bp; |
mp_limb_t *up, *vp, *tmpp, *tmpup, *tmpvp, *ap, *bp; |
| mpfr_t u, v, tmp, tmpu, tmpv, a, b; |
mpfr_t u, v, tmp, tmpu, tmpv, a, b; |
| TMP_DECL(marker1); |
TMP_DECL(marker); |
| TMP_DECL(marker2); |
|
| |
|
| |
|
| /* If a or b is NaN, the result is NaN */ |
/* If a or b is NaN, the result is NaN */ |
| if (FLAG_NAN(op1) || FLAG_NAN(op2)) |
if (MPFR_IS_NAN(op1) || MPFR_IS_NAN(op2)) |
| { SET_NAN(r); return; } |
{ |
| |
MPFR_SET_NAN(r); |
| |
__mpfr_flags |= MPFR_FLAGS_NAN; |
| |
return; |
| |
} |
| |
|
| |
/* If a or b is negative (including -Infinity), the result is NaN */ |
| |
if ((MPFR_SIGN(op1) < 0) || (MPFR_SIGN(op2) < 0)) |
| |
{ |
| |
MPFR_SET_NAN(r); |
| |
__mpfr_flags |= MPFR_FLAGS_NAN; |
| |
return; |
| |
} |
| |
|
| /* If a or b is negative, the result is NaN */ |
MPFR_CLEAR_NAN(r); |
| if ((SIGN(op1)<0)||(SIGN(op2)<0)) |
|
| { SET_NAN(r); return; } |
|
| |
|
| |
/* If a or b is +Infinity, the result is +Infinity */ |
| |
if (MPFR_IS_INF(op1) || MPFR_IS_INF(op2)) |
| |
{ |
| |
MPFR_SET_INF(r); |
| |
MPFR_SET_SAME_SIGN(r, op1); |
| |
return; |
| |
} |
| |
|
| |
MPFR_CLEAR_INF(r); |
| |
|
| /* If a or b is 0, the result is 0 */ |
/* If a or b is 0, the result is 0 */ |
| if ((SIGN(op1)==0)||(SIGN(op2)==0)) |
if ((MPFR_NOTZERO(op1) && MPFR_NOTZERO(op2)) == 0) |
| { SET_ZERO(r); |
{ |
| return; |
MPFR_SET_ZERO(r); |
| |
return; |
| } |
} |
| |
|
| /* precision of the following calculus */ |
/* precision of the following calculus */ |
| q = PREC(r); |
q = MPFR_PREC(r); |
| p = q + 15; |
p = q + 15; |
| |
|
| |
|
| /* Initialisations */ |
/* Initialisations */ |
| go_on=1; |
go_on=1; |
| |
|
| TMP_MARK(marker1); |
TMP_MARK(marker); |
| s=(p-1)/BITS_PER_MP_LIMB+1; |
s=(p-1)/BITS_PER_MP_LIMB+1; |
| MON_INIT(ap, a, p, s); |
MPFR_INIT(ap, a, p, s); |
| MON_INIT(bp, b, p, s); |
MPFR_INIT(bp, b, p, s); |
| TMP_MARK(marker2); |
MPFR_INIT(up, u, p, s); |
| MON_INIT(up, u, p, s); |
MPFR_INIT(vp, v, p, s); |
| MON_INIT(vp, v, p, s); |
MPFR_INIT(tmpup, tmpu, p, s); |
| MON_INIT(tmpup, tmpu, p, s); |
MPFR_INIT(tmpvp, tmpv, p, s); |
| MON_INIT(tmpvp, tmpv, p, s); |
MPFR_INIT(tmpp, tmp, p, s); |
| MON_INIT(tmpp, tmp, p, s); |
|
| |
|
| |
|
| |
|
| /* b and a will be the 2 operands but I want b>= a */ |
/* b and a are the 2 operands but we want b >= a */ |
| if (mpfr_cmp(op1,op2) > 0) { |
if ((compare = mpfr_cmp (op1,op2)) > 0) |
| mpfr_set(b,op1,GMP_RNDN); mpfr_set(a,op2,GMP_RNDN); |
{ |
| } |
mpfr_set (b,op1,GMP_RNDN); |
| else { |
mpfr_set (a,op2,GMP_RNDN); |
| mpfr_set(b,op2,GMP_RNDN); mpfr_set(a,op1,GMP_RNDN); |
} |
| } |
else if (compare == 0) |
| |
{ |
| |
mpfr_set (r, op1, rnd_mode); |
| |
TMP_FREE(marker); |
| |
return; |
| |
} |
| |
else |
| |
{ |
| |
mpfr_set (b,op2,GMP_RNDN); |
| |
mpfr_set (a,op1,GMP_RNDN); |
| |
} |
| |
|
| vo=mpfr_get_d(b); |
vo = mpfr_get_d1 (b); |
| uo=mpfr_get_d(a); |
uo = mpfr_get_d1 (a); |
| |
|
| mpfr_set(u,a,GMP_RNDN); |
mpfr_set(u,a,GMP_RNDN); |
| mpfr_set(v,b,GMP_RNDN); |
mpfr_set(v,b,GMP_RNDN); |
| |
|
| |
|
| /* Main loop */ |
/* Main loop */ |
| |
|
| while (go_on) { |
while (go_on) { |
| int err, eq, can_round; |
int err, can_round; |
| |
mp_prec_t eq; |
| |
|
| eq=0; |
err=1 + (int) ((3.0/2.0*(double)_mpfr_ceil_log2((double)p)+1.0)*_mpfr_ceil_exp2(-(double)p) |
| |
+3.0*_mpfr_ceil_exp2(-2.0*(double)p*uo/(vo-uo))); |
| err=ceil((3.0/2.0*log((double)p)/log(2.0)+1.0)*exp(-(double)p*log(2.0))+3.0*exp(-2.0*(double)p*uo*log(2.0)/(vo-uo))); |
|
| if(p-err-3<=q) { |
if(p-err-3<=q) { |
| p=q+err+4; |
p=q+err+4; |
| err=ceil((3.0/2.0*log((double)p)/log(2.0)+1.0)*exp(-(double)p*log(2.0))+3.0*exp(-2.0*(double)p*uo*log(2.0)/(vo-uo))); |
err= 1 + |
| |
(int) ((3.0/2.0*_mpfr_ceil_log2((double)p)+1.0)*_mpfr_ceil_exp2(-(double)p) |
| |
+3.0*_mpfr_ceil_exp2(-2.0*(double)p*uo/(vo-uo))); |
| } |
} |
| |
|
| /* Calculus of un and vn */ |
/* Calculus of un and vn */ |
| while (eq<=p-2) { |
do |
| mpfr_mul(tmp,u,v,GMP_RNDN); |
{ |
| mpfr_sqrt(tmpu,tmp,GMP_RNDN); |
mpfr_mul(tmp, u, v, GMP_RNDN); |
| mpfr_add(tmp,u,v,GMP_RNDN); |
mpfr_sqrt (tmpu, tmp, GMP_RNDN); |
| mpfr_div_2exp(tmpv,tmp,1,GMP_RNDN); |
mpfr_add(tmp, u, v, GMP_RNDN); |
| mpfr_set(u,tmpu,GMP_RNDN); |
mpfr_div_2ui(tmpv, tmp, 1, GMP_RNDN); |
| mpfr_set(v,tmpv,GMP_RNDN); |
mpfr_set(u, tmpu, GMP_RNDN); |
| if (mpfr_cmp(v,u)>=0) |
mpfr_set(v, tmpv, GMP_RNDN); |
| eq=mpfr_cmp2(v,u); |
} |
| else |
while (mpfr_cmp2(u, v, &eq) != 0 && eq <= p - 2); |
| eq=mpfr_cmp2(u,v); |
|
| } |
|
| |
|
| /* printf("avant can_round %i bits faux\n v : ",err+3); |
|
| mpfr_print_raw(v); printf("\n u : "); |
|
| mpfr_print_raw(u);printf("\n");*/ |
|
| |
|
| |
|
| /* Roundability of the result */ |
/* Roundability of the result */ |
| can_round=mpfr_can_round(v,p-err-3,GMP_RNDN,rnd_mode,q); |
can_round=mpfr_can_round(v,p-err-3,GMP_RNDN,rnd_mode,q); |
| |
|
| Line 145 mpfr_agm(r, a, b, rnd_mode) |
|
| Line 148 mpfr_agm(r, a, b, rnd_mode) |
|
| else { |
else { |
| go_on=1; |
go_on=1; |
| p+=5; |
p+=5; |
| TMP_FREE(marker2); |
|
| TMP_MARK(marker2); |
|
| s=(p-1)/BITS_PER_MP_LIMB+1; |
s=(p-1)/BITS_PER_MP_LIMB+1; |
| MON_INIT(up, u, p, s); |
MPFR_INIT(up, u, p, s); |
| MON_INIT(vp, v, p, s); |
MPFR_INIT(vp, v, p, s); |
| MON_INIT(tmpup, tmpu, p, s); |
MPFR_INIT(tmpup, tmpu, p, s); |
| MON_INIT(tmpvp, tmpv, p, s); |
MPFR_INIT(tmpvp, tmpv, p, s); |
| MON_INIT(tmpp, tmp, p, s); |
MPFR_INIT(tmpp, tmp, p, s); |
| mpfr_set(u,a,GMP_RNDN); |
mpfr_set(u,a,GMP_RNDN); |
| mpfr_set(v,b,GMP_RNDN); |
mpfr_set(v,b,GMP_RNDN); |
| } |
} |
| Line 161 mpfr_agm(r, a, b, rnd_mode) |
|
| Line 162 mpfr_agm(r, a, b, rnd_mode) |
|
| |
|
| /* Setting of the result */ |
/* Setting of the result */ |
| |
|
| mpfr_set(r,v,rnd_mode); |
mpfr_set(r,v,rnd_mode); |
| |
|
| |
|
| /* Let's clean */ |
/* Let's clean */ |
| TMP_FREE(marker1); |
TMP_FREE(marker); |
| |
|
| return ; |
return ; |
| } |
} |
| |
|