/* Test file for mpfr_log. Copyright 1999, 2001, 2002 Free Software Foundation, Inc. This file is part of the MPFR Library. The MPFR Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The MPFR Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. 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 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include "gmp.h" #include "mpfr.h" #include "mpfr-test.h" double drand_log _PROTO((void)); int check1 _PROTO((double, mp_rnd_t, double, int, int)); void check3 _PROTO((double, unsigned long, mp_rnd_t)); void check4 _PROTO((int)); void slave _PROTO((int, int)); void check_worst_cases _PROTO((void)); void special _PROTO((void)); #if (BITS_PER_LONGINT == 32) #define INT32 long int #else #define INT32 int #endif double drand_log (void) { double d; INT32 *i; i = (INT32*) &d; do { i[0] = LONG_RAND(); i[1] = LONG_RAND(); } while ((d<1e-153) || (d>1e153)); /* to avoid underflow or overflow in double calculus in sqrt(u*v) */ return d; } #define check2(a,rnd,res) check1(a,rnd,res,1,0) #define check(a,r) check2(a,r,0.0) int check1 (double a, mp_rnd_t rnd_mode, double res1, int ck, int max_ulp) { mpfr_t ta, tres; double res2; int diff=0; /* ck=1 iff res1 is certified correct */ #ifdef MPFR_HAVE_FESETROUND mpfr_set_machine_rnd_mode(rnd_mode); #endif if (ck==0 && res1==0.0) res1=log(a); mpfr_init2(ta, 53); mpfr_init2(tres, 53); mpfr_set_d(ta, a, GMP_RNDN); mpfr_log(tres, ta, rnd_mode); res2=mpfr_get_d1 (tres); mpfr_clear(ta); mpfr_clear(tres); if (res1!=res2 && (!isnan(res1) || !isnan(res2))) { diff = ulp(res1,res2); if (ck) { printf("mpfr_log failed for a=%1.20e, rnd_mode=%s\n", a, mpfr_print_rnd_mode(rnd_mode)); printf("correct result is %1.20e\n mpfr_log gives %1.20e (%d ulp)\n",res1,res2,ulp(res1,res2)); exit(1); } else if (diff>max_ulp) { printf("mpfr_log differs from libm.a for a=%1.20e, rnd_mode=%s\n", a, mpfr_print_rnd_mode(rnd_mode)); printf(" double calculus gives %1.20e\n mpfr_log gives %1.20e (%d ulp)\n",res1,res2,ulp(res1,res2)); } } if (!isnan(res1) || !isnan(res2)) return diff; else return 0; } void check3 (double d, unsigned long prec, mp_rnd_t rnd) { mpfr_t x, y; mpfr_init2(x, prec); mpfr_init2(y, prec); mpfr_set_d(x, d, rnd); mpfr_log(y, x, rnd); mpfr_out_str(stdout, 10, 0, y, rnd); putchar('\n'); mpfr_print_binary(y); putchar('\n'); mpfr_clear(x); mpfr_clear(y); } void check4 (int N) { int i, max=0, sum=0, cur; double d; mp_rnd_t rnd; for(i=0;i max) max=cur; sum+=cur; } d=(double)sum / (double)N; fprintf(stderr, "max error : %i \t mean error : %f (in ulps)\n",max,d); } void slave (int N, int p) { int i; double d; mpfr_t ta, tres; mpfr_init2(ta, 53); mpfr_init2(tres, p); for(i=0;i