Annotation of OpenXM_contrib/gmp/mpfr/tests/tmul.c, Revision 1.1
1.1 ! ohara 1: /* Test file for mpfr_mul.
! 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 <stdlib.h>
! 24: #include <time.h>
! 25: #include "gmp.h"
! 26: #include "gmp-impl.h"
! 27: #include "mpfr.h"
! 28: #include "mpfr-impl.h"
! 29: #include "mpfr-test.h"
! 30:
! 31: void check53 _PROTO((double, double, mp_rnd_t, double));
! 32: void check24 _PROTO((float, float, mp_rnd_t, float));
! 33: void check_float _PROTO((void));
! 34: void check_sign _PROTO((void));
! 35: void check_exact _PROTO((void));
! 36: void check_max _PROTO((void));
! 37: void check_min _PROTO((void));
! 38:
! 39:
! 40: /* Workaround for sparc gcc 2.95.x bug, see notes in tadd.c. */
! 41: #define check(x,y,rnd_mode,px,py,pz,res) _check(x,y,res,rnd_mode,px,py,pz)
! 42:
! 43: /* checks that x*y gives the same results in double
! 44: and with mpfr with 53 bits of precision */
! 45: void
! 46: _check (double x, double y, double res, mp_rnd_t rnd_mode, unsigned int px,
! 47: unsigned int py, unsigned int pz)
! 48: {
! 49: double z1, z2; mpfr_t xx, yy, zz;
! 50:
! 51: mpfr_init2 (xx, px);
! 52: mpfr_init2 (yy, py);
! 53: mpfr_init2 (zz, pz);
! 54: mpfr_set_d(xx, x, rnd_mode);
! 55: mpfr_set_d(yy, y, rnd_mode);
! 56: mpfr_mul(zz, xx, yy, rnd_mode);
! 57: #ifdef MPFR_HAVE_FESETROUND
! 58: mpfr_set_machine_rnd_mode(rnd_mode);
! 59: #endif
! 60: z1 = (res==0.0) ? x*y : res;
! 61: z2 = mpfr_get_d1 (zz);
! 62: if (z1!=z2 && (z1>=MINNORM || z1<=-MINNORM)) {
! 63: printf("mpfr_mul ");
! 64: if (res==0.0) printf("differs from libm.a"); else printf("failed");
! 65: printf(" for x=%1.20e y=%1.20e with rnd_mode=%s\n", x, y,
! 66: mpfr_print_rnd_mode(rnd_mode));
! 67: printf("libm.a gives %1.20e, mpfr_mul gives %1.20e\n", z1, z2);
! 68: if (res!=0.0) exit(1);
! 69: }
! 70: mpfr_clear(xx); mpfr_clear(yy); mpfr_clear(zz);
! 71: }
! 72:
! 73: void
! 74: check53 (double x, double y, mp_rnd_t rnd_mode, double z1)
! 75: {
! 76: double z2; mpfr_t xx, yy, zz;
! 77:
! 78: mpfr_init2 (xx, 53);
! 79: mpfr_init2 (yy, 53);
! 80: mpfr_init2 (zz, 53);
! 81: mpfr_set_d (xx, x, rnd_mode);
! 82: mpfr_set_d (yy, y, rnd_mode);
! 83: mpfr_mul (zz, xx, yy, rnd_mode);
! 84: z2 = mpfr_get_d1 (zz);
! 85: if (z1!=z2 && (!isnan(z1) || !isnan(z2))) {
! 86: printf("mpfr_mul failed for x=%1.20e y=%1.20e with rnd_mode=%s\n",
! 87: x, y, mpfr_print_rnd_mode(rnd_mode));
! 88: printf("libm.a gives %1.20e, mpfr_mul gives %1.20e\n", z1, z2);
! 89: exit(1);
! 90: }
! 91: mpfr_clear(xx); mpfr_clear(yy); mpfr_clear(zz);
! 92: }
! 93:
! 94: /* checks that x*y gives the same results in double
! 95: and with mpfr with 24 bits of precision */
! 96: void
! 97: check24 (float x, float y, mp_rnd_t rnd_mode, float z1)
! 98: {
! 99: float z2;
! 100: mpfr_t xx, yy, zz;
! 101:
! 102: mpfr_init2 (xx, 24);
! 103: mpfr_init2 (yy, 24);
! 104: mpfr_init2 (zz, 24);
! 105: mpfr_set_d (xx, x, rnd_mode);
! 106: mpfr_set_d (yy, y, rnd_mode);
! 107: mpfr_mul (zz, xx, yy, rnd_mode);
! 108: z2 = (float) mpfr_get_d1 (zz);
! 109: if (z1 != z2)
! 110: {
! 111: fprintf (stderr, "mpfr_mul failed for x=%1.0f y=%1.0f with prec=24 and"
! 112: "rnd=%s\n", x, y, mpfr_print_rnd_mode(rnd_mode));
! 113: fprintf (stderr, "libm.a gives %.10e, mpfr_mul gives %.10e\n", z1, z2);
! 114: exit (1);
! 115: }
! 116: mpfr_clear(xx);
! 117: mpfr_clear(yy);
! 118: mpfr_clear(zz);
! 119: }
! 120:
! 121: /* the following examples come from the paper "Number-theoretic Test
! 122: Generation for Directed Rounding" from Michael Parks, Table 1 */
! 123: void
! 124: check_float (void)
! 125: {
! 126: float z;
! 127:
! 128: check24(8388609.0, 8388609.0, GMP_RNDN, 70368760954880.0);
! 129: check24(16777213.0, 8388609.0, GMP_RNDN, 140737479966720.0);
! 130: check24(8388611.0, 8388609.0, GMP_RNDN, 70368777732096.0);
! 131: check24(12582911.0, 8388610.0, GMP_RNDN, 105553133043712.0);
! 132: check24(12582914.0, 8388610.0, GMP_RNDN, 105553158209536.0);
! 133: check24(13981013.0, 8388611.0, GMP_RNDN, 117281279442944.0);
! 134: check24(11184811.0, 8388611.0, GMP_RNDN, 93825028587520.0);
! 135: check24(11184810.0, 8388611.0, GMP_RNDN, 93825020198912.0);
! 136: check24(13981014.0, 8388611.0, GMP_RNDN, 117281287831552.0);
! 137:
! 138: check24(8388609.0, 8388609.0, GMP_RNDZ, 70368760954880.0);
! 139: check24(16777213.0, 8388609.0, GMP_RNDZ, 140737471578112.0);
! 140: z = 70368777732096.0;
! 141: check24(8388611.0, 8388609.0, GMP_RNDZ, z);
! 142: check24(12582911.0, 8388610.0, GMP_RNDZ, 105553124655104.0);
! 143: check24(12582914.0, 8388610.0, GMP_RNDZ, 105553158209536.0);
! 144: check24(13981013.0, 8388611.0, GMP_RNDZ, 117281271054336.0);
! 145: check24(11184811.0, 8388611.0, GMP_RNDZ, 93825028587520.0);
! 146: check24(11184810.0, 8388611.0, GMP_RNDZ, 93825011810304.0);
! 147: check24(13981014.0, 8388611.0, GMP_RNDZ, 117281287831552.0);
! 148:
! 149: check24(8388609.0, 8388609.0, GMP_RNDU, 70368769343488.0);
! 150: check24(16777213.0, 8388609.0, GMP_RNDU, 140737479966720.0);
! 151: check24(8388611.0, 8388609.0, GMP_RNDU, 70368786120704.0);
! 152: check24(12582911.0, 8388610.0, GMP_RNDU, 105553133043712.0);
! 153: check24(12582914.0, 8388610.0, GMP_RNDU, 105553166598144.0);
! 154: check24(13981013.0, 8388611.0, GMP_RNDU, 117281279442944.0);
! 155: check24(11184811.0, 8388611.0, GMP_RNDU, 93825036976128.0);
! 156: check24(11184810.0, 8388611.0, GMP_RNDU, 93825020198912.0);
! 157: check24(13981014.0, 8388611.0, GMP_RNDU, 117281296220160.0);
! 158:
! 159: check24(8388609.0, 8388609.0, GMP_RNDD, 70368760954880.0);
! 160: check24(16777213.0, 8388609.0, GMP_RNDD, 140737471578112.0);
! 161: check24(8388611.0, 8388609.0, GMP_RNDD, 70368777732096.0);
! 162: check24(12582911.0, 8388610.0, GMP_RNDD, 105553124655104.0);
! 163: check24(12582914.0, 8388610.0, GMP_RNDD, 105553158209536.0);
! 164: check24(13981013.0, 8388611.0, GMP_RNDD, 117281271054336.0);
! 165: check24(11184811.0, 8388611.0, GMP_RNDD, 93825028587520.0);
! 166: check24(11184810.0, 8388611.0, GMP_RNDD, 93825011810304.0);
! 167: check24(13981014.0, 8388611.0, GMP_RNDD, 117281287831552.0);
! 168: }
! 169:
! 170: /* check sign of result */
! 171: void
! 172: check_sign (void)
! 173: {
! 174: mpfr_t a, b;
! 175:
! 176: mpfr_init2 (a, 53);
! 177: mpfr_init2 (b, 53);
! 178: mpfr_set_d(a, -1.0, GMP_RNDN);
! 179: mpfr_set_d(b, 2.0, GMP_RNDN);
! 180: mpfr_mul(a, b, b, GMP_RNDN);
! 181: if (mpfr_get_d1 (a) != 4.0) {
! 182: fprintf(stderr,"2.0*2.0 gives %1.20e\n", mpfr_get_d1 (a)); exit(1);
! 183: }
! 184: mpfr_clear(a); mpfr_clear(b);
! 185: }
! 186:
! 187: /* checks that the inexact return value is correct */
! 188: void
! 189: check_exact (void)
! 190: {
! 191: mpfr_t a, b, c, d;
! 192: mp_prec_t prec;
! 193: int i, inexact;
! 194: mp_rnd_t rnd;
! 195:
! 196: mpfr_init (a);
! 197: mpfr_init (b);
! 198: mpfr_init (c);
! 199: mpfr_init (d);
! 200:
! 201: mpfr_set_prec (a, 17);
! 202: mpfr_set_prec (b, 17);
! 203: mpfr_set_prec (c, 32);
! 204: mpfr_set_str_raw (a, "1.1000111011000100e-1");
! 205: mpfr_set_str_raw (b, "1.0010001111100111e-1");
! 206: if (mpfr_mul (c, a, b, GMP_RNDZ))
! 207: {
! 208: fprintf (stderr, "wrong return value (1)\n");
! 209: exit (1);
! 210: }
! 211:
! 212: for (prec = 2; prec < 100; prec++)
! 213: {
! 214: mpfr_set_prec (a, prec);
! 215: mpfr_set_prec (b, prec);
! 216: mpfr_set_prec (c, 2 * prec - 2);
! 217: mpfr_set_prec (d, 2 * prec);
! 218: for (i = 0; i < 1000; i++)
! 219: {
! 220: mpfr_random (a);
! 221: mpfr_random (b);
! 222: rnd = LONG_RAND() % 4;
! 223: inexact = mpfr_mul (c, a, b, rnd);
! 224: if (mpfr_mul (d, a, b, rnd)) /* should be always exact */
! 225: {
! 226: fprintf (stderr, "unexpected inexact return value\n");
! 227: exit (1);
! 228: }
! 229: if ((inexact == 0) && mpfr_cmp (c, d))
! 230: {
! 231: fprintf (stderr, "inexact=0 but results differ\n");
! 232: exit (1);
! 233: }
! 234: else if (inexact && (mpfr_cmp (c, d) == 0))
! 235: {
! 236: fprintf (stderr, "inexact!=0 but results agree\n");
! 237: fprintf (stderr, "prec=%u rnd=%s a=", (unsigned int) prec,
! 238: mpfr_print_rnd_mode (rnd));
! 239: mpfr_out_str (stderr, 2, 0, a, rnd);
! 240: fprintf (stderr, "\nb=");
! 241: mpfr_out_str (stderr, 2, 0, b, rnd);
! 242: fprintf (stderr, "\nc=");
! 243: mpfr_out_str (stderr, 2, 0, c, rnd);
! 244: fprintf (stderr, "\nd=");
! 245: mpfr_out_str (stderr, 2, 0, d, rnd);
! 246: fprintf (stderr, "\n");
! 247: exit (1);
! 248: }
! 249: }
! 250: }
! 251:
! 252: mpfr_clear (a);
! 253: mpfr_clear (b);
! 254: mpfr_clear (c);
! 255: mpfr_clear (d);
! 256: }
! 257:
! 258: void
! 259: check_max(void)
! 260: {
! 261: mpfr_t xx, yy, zz;
! 262:
! 263: mpfr_init2(xx, 4);
! 264: mpfr_init2(yy, 4);
! 265: mpfr_init2(zz, 4);
! 266: mpfr_set_d(xx, 11.0/16, GMP_RNDN);
! 267: mpfr_mul_2si(xx, xx, MPFR_EMAX_DEFAULT/2, GMP_RNDN);
! 268: mpfr_set_d(yy, 11.0/16, GMP_RNDN);
! 269: mpfr_mul_2si(yy, yy, MPFR_EMAX_DEFAULT - MPFR_EMAX_DEFAULT/2 + 1, GMP_RNDN);
! 270: mpfr_clear_flags();
! 271: mpfr_mul(zz, xx, yy, GMP_RNDU);
! 272: if (!(mpfr_overflow_p() && MPFR_IS_INF(zz)))
! 273: {
! 274: printf("check_max failed (should be an overflow)\n");
! 275: exit(1);
! 276: }
! 277:
! 278: mpfr_clear_flags();
! 279: mpfr_mul(zz, xx, yy, GMP_RNDD);
! 280: if (mpfr_overflow_p() || MPFR_IS_INF(zz))
! 281: {
! 282: printf("check_max failed (should NOT be an overflow)\n");
! 283: exit(1);
! 284: }
! 285: mpfr_set_d(xx, 15.0/16, GMP_RNDN);
! 286: mpfr_mul_2si(xx, xx, MPFR_EMAX_DEFAULT, GMP_RNDN);
! 287: if (!(MPFR_IS_FP(xx) && MPFR_IS_FP(zz)))
! 288: {
! 289: printf("check_max failed (internal error)\n");
! 290: exit(1);
! 291: }
! 292: if (mpfr_cmp(xx, zz) != 0)
! 293: {
! 294: printf("check_max failed: got ");
! 295: mpfr_out_str(stdout, 2, 0, zz, GMP_RNDZ);
! 296: printf(" instead of ");
! 297: mpfr_out_str(stdout, 2, 0, xx, GMP_RNDZ);
! 298: printf("\n");
! 299: exit(1);
! 300: }
! 301:
! 302: mpfr_clear(xx);
! 303: mpfr_clear(yy);
! 304: mpfr_clear(zz);
! 305: }
! 306:
! 307: void
! 308: check_min(void)
! 309: {
! 310: mpfr_t xx, yy, zz;
! 311:
! 312: mpfr_init2(xx, 4);
! 313: mpfr_init2(yy, 4);
! 314: mpfr_init2(zz, 3);
! 315: mpfr_set_d(xx, 15.0/16, GMP_RNDN);
! 316: mpfr_mul_2si(xx, xx, MPFR_EMIN_DEFAULT/2, GMP_RNDN);
! 317: mpfr_set_d(yy, 15.0/16, GMP_RNDN);
! 318: mpfr_mul_2si(yy, yy, MPFR_EMIN_DEFAULT - MPFR_EMIN_DEFAULT/2 - 1, GMP_RNDN);
! 319: mpfr_mul(zz, xx, yy, GMP_RNDD);
! 320: if (mpfr_sgn(zz) != 0)
! 321: {
! 322: printf("check_min failed: got ");
! 323: mpfr_out_str(stdout, 2, 0, zz, GMP_RNDZ);
! 324: printf(" instead of 0\n");
! 325: exit(1);
! 326: }
! 327:
! 328: mpfr_mul(zz, xx, yy, GMP_RNDU);
! 329: mpfr_set_d(xx, 0.5, GMP_RNDN);
! 330: mpfr_mul_2si(xx, xx, MPFR_EMIN_DEFAULT, GMP_RNDN);
! 331: if (mpfr_sgn(xx) <= 0)
! 332: {
! 333: printf("check_min failed (internal error)\n");
! 334: exit(1);
! 335: }
! 336: if (mpfr_cmp(xx, zz) != 0)
! 337: {
! 338: printf("check_min failed: got ");
! 339: mpfr_out_str(stdout, 2, 0, zz, GMP_RNDZ);
! 340: printf(" instead of ");
! 341: mpfr_out_str(stdout, 2, 0, xx, GMP_RNDZ);
! 342: printf("\n");
! 343: exit(1);
! 344: }
! 345:
! 346: mpfr_clear(xx);
! 347: mpfr_clear(yy);
! 348: mpfr_clear(zz);
! 349: }
! 350:
! 351: int
! 352: main (int argc, char *argv[])
! 353: {
! 354: #ifdef MPFR_HAVE_FESETROUND
! 355: double x, y, z;
! 356: int i, prec, rnd_mode;
! 357:
! 358: mpfr_test_init ();
! 359: #endif
! 360:
! 361: check_exact ();
! 362: check_float ();
! 363: #ifdef HAVE_INFS
! 364: check53 (0.0, DBL_POS_INF, GMP_RNDN, DBL_NAN);
! 365: check53(1.0, DBL_POS_INF, GMP_RNDN, DBL_POS_INF);
! 366: check53(-1.0, DBL_POS_INF, GMP_RNDN, DBL_NEG_INF);
! 367: check53(DBL_NAN, 0.0, GMP_RNDN, DBL_NAN);
! 368: check53(1.0, DBL_NAN, GMP_RNDN, DBL_NAN);
! 369: #endif
! 370: check53(6.9314718055994530941514e-1, 0.0, GMP_RNDZ, 0.0);
! 371: check53(0.0, 6.9314718055994530941514e-1, GMP_RNDZ, 0.0);
! 372: check_sign();
! 373: check53(-4.165000000e4, -0.00004801920768307322868063274915, GMP_RNDN, 2.0);
! 374: check53(2.71331408349172961467e-08, -6.72658901114033715233e-165, GMP_RNDZ,
! 375: -1.8251348697787782844e-172);
! 376: check53(0.31869277231188065, 0.88642843322303122, GMP_RNDZ,
! 377: 2.8249833483992453642e-1);
! 378: check(8.47622108205396074254e-01, 3.24039313247872939883e-01, GMP_RNDU,
! 379: 28, 45, 2, 0.375);
! 380: check(2.63978122803639081440e-01, 6.8378615379333496093e-1, GMP_RNDN,
! 381: 34, 23, 31, 0.180504585267044603);
! 382: check(1.0, 0.11835170935876249132, GMP_RNDU, 6, 41, 36, 0.1183517093595583);
! 383: check53(67108865.0, 134217729.0, GMP_RNDN, 9.007199456067584e15);
! 384: check(1.37399642157394197284e-01, 2.28877275604219221350e-01, GMP_RNDN,
! 385: 49, 15, 32, 0.0314472340833162888);
! 386: check(4.03160720978664954828e-01, 5.85483042917246621073e-01, GMP_RNDZ,
! 387: 51, 22, 32, 0.2360436821472831);
! 388: check(3.90798504668055102229e-14, 9.85394674650308388664e-04, GMP_RNDN,
! 389: 46, 22, 12, 0.385027296503914762e-16);
! 390: check(4.58687081072827851358e-01, 2.20543551472118792844e-01, GMP_RNDN,
! 391: 49, 3, 2, 0.09375);
! 392: check_max();
! 393: check_min();
! 394: #ifdef MPFR_HAVE_FESETROUND
! 395: SEED_RAND (time(NULL));
! 396: prec = (argc<2) ? 53 : atoi(argv[1]);
! 397: rnd_mode = (argc<3) ? -1 : atoi(argv[2]);
! 398: for (i=0;i<1000000;) {
! 399: x = drand();
! 400: y = drand();
! 401: z = x*y; if (z<0) z=-z;
! 402: if (z<1e+308 && z>1e-308) /* don't test overflow/underflow for now */
! 403: { i++;
! 404: check(x, y, (rnd_mode==-1) ? LONG_RAND()%4 : rnd_mode,
! 405: prec, prec, prec, 0.0);
! 406: }
! 407: }
! 408: #endif
! 409:
! 410: return 0;
! 411: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>