Annotation of OpenXM_contrib/gmp/mpfr/tests/tsqrt.c, Revision 1.1
1.1 ! ohara 1: /* Test file for mpfr_sqrt.
! 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 <math.h>
! 23: #include <stdio.h>
! 24: #include <stdlib.h>
! 25: #include <time.h>
! 26: #include "gmp.h"
! 27: #include "gmp-impl.h"
! 28: #include "mpfr.h"
! 29: #include "mpfr-impl.h"
! 30: #include "mpfr-test.h"
! 31:
! 32: #define check(a,r) check3(a,r,-1.0)
! 33:
! 34: int maxulp=0;
! 35:
! 36: void check3 _PROTO((double, mp_rnd_t, double));
! 37: void check4 _PROTO((double, mp_rnd_t, char *));
! 38: void check24 _PROTO((float, mp_rnd_t, float));
! 39: void check_float _PROTO((void));
! 40: void special _PROTO((void));
! 41: void check_inexact _PROTO((mp_prec_t));
! 42: void check_nan _PROTO((void));
! 43:
! 44: void
! 45: check3 (double a, mp_rnd_t rnd_mode, double Q)
! 46: {
! 47: mpfr_t q; double Q2; int ck,u;
! 48:
! 49: ck = (Q!=-1.0); /* if ck=1, then Q is certified correct */
! 50: mpfr_init2(q, 53);
! 51: mpfr_set_d(q, a, rnd_mode);
! 52: #ifdef MPFR_HAVE_FESETROUND
! 53: mpfr_set_machine_rnd_mode(rnd_mode);
! 54: #endif
! 55: mpfr_sqrt(q, q, rnd_mode);
! 56: if (ck==0) Q = sqrt(a);
! 57: else {
! 58: if (Q != sqrt(a) && (!isnan(Q) || !isnan(sqrt(a)))) {
! 59: fprintf(stderr, "you've found a bug in your machine's sqrt for x=%1.20e\n", a);
! 60: mpfr_clear(q);
! 61: exit(1);
! 62:
! 63: }
! 64: }
! 65: Q2 = mpfr_get_d1 (q);
! 66: if (Q!=Q2 && (!isnan(Q) || !isnan(Q2))) {
! 67: u = ulp(Q2,Q);
! 68: if (ck) {
! 69: printf("mpfr_sqrt failed for a=%1.20e, rnd_mode=%s\n",
! 70: a, mpfr_print_rnd_mode(rnd_mode));
! 71: printf("expected sqrt is %1.20e, got %1.20e (%d ulp)\n",Q,Q2,u);
! 72: mpfr_clear(q);
! 73: exit(1);
! 74: }
! 75: else if (u>maxulp || u<-maxulp) {
! 76: maxulp = (u>maxulp) ? u : -u;
! 77: printf("libm.a differs from mpfr_sqrt for a=%1.20e, rnd_mode=%s\n",
! 78: a, mpfr_print_rnd_mode(rnd_mode));
! 79: printf("libm.a gives %1.20e, mpfr_sqrt gives %1.20e (%d ulp)\n",Q,Q2,u);
! 80: }
! 81: }
! 82: mpfr_clear(q);
! 83: }
! 84:
! 85: void
! 86: check4 (double a, mp_rnd_t rnd_mode, char *Q)
! 87: {
! 88: mpfr_t q, res;
! 89:
! 90: mpfr_init2(q, 53); mpfr_init2(res, 53);
! 91: mpfr_set_d(q, a, rnd_mode);
! 92: mpfr_sqrt(q, q, rnd_mode);
! 93: mpfr_set_str(res, Q, 16, GMP_RNDN);
! 94: if (mpfr_cmp(q, res)) {
! 95: printf("mpfr_sqrt failed for a=%1.20e, rnd_mode=%s\n",
! 96: a, mpfr_print_rnd_mode(rnd_mode));
! 97: printf("expected "); mpfr_print_binary(res); putchar('\n');
! 98: printf("got "); mpfr_print_binary(q); putchar('\n');
! 99: mpfr_clear(q); mpfr_clear(res);
! 100: exit(1);
! 101: }
! 102: mpfr_clear(res);
! 103: mpfr_clear(q);
! 104: }
! 105:
! 106: void
! 107: check24 (float a, mp_rnd_t rnd_mode, float Q)
! 108: {
! 109: mpfr_t q; float Q2;
! 110:
! 111: mpfr_init2(q, 24);
! 112: mpfr_set_d(q, a, rnd_mode);
! 113: mpfr_sqrt(q, q, rnd_mode);
! 114: Q2 = mpfr_get_d1 (q);
! 115: if (Q!=Q2) {
! 116: printf("mpfr_sqrt failed for a=%1.10e, prec=24, rnd_mode=%s\n",
! 117: a, mpfr_print_rnd_mode(rnd_mode));
! 118: printf("expected sqrt is %1.10e, got %1.10e\n",Q,Q2);
! 119: exit(1);
! 120: }
! 121: mpfr_clear(q);
! 122: }
! 123:
! 124: /* the following examples come from the paper "Number-theoretic Test
! 125: Generation for Directed Rounding" from Michael Parks, Table 3 */
! 126: void
! 127: check_float (void)
! 128: {
! 129: float b = 8388608.0; /* 2^23 */
! 130:
! 131: check24(b*8388610.0, GMP_RNDN, 8.388609e6);
! 132: check24(b*2.0*16777214.0, GMP_RNDN, 1.6777215e7);
! 133: check24(b*8388612.0, GMP_RNDN, 8.388610e6);
! 134: check24(b*2.0*16777212.0, GMP_RNDN, 1.6777214e7);
! 135: check24(b*11946704.0, GMP_RNDN, 1.0010805e7);
! 136: check24(b*14321479.0, GMP_RNDN, 1.0960715e7);
! 137: check24(b*2.0*13689673.0, GMP_RNDN, 1.5155019e7);
! 138: check24(b*8388614.0, GMP_RNDN, 8.388611e6);
! 139: check24(b*2.0*16777210.0, GMP_RNDN, 1.6777213e7);
! 140: check24(b*10873622.0, GMP_RNDN, 9.550631e6);
! 141:
! 142: check24(b*8388610.0, GMP_RNDZ, 8.388608e6);
! 143: check24(b*2.0*16777214.0, GMP_RNDZ, 1.6777214e7);
! 144: check24(b*8388612.0, GMP_RNDZ, 8.388609e6);
! 145: check24(b*2.0*16777212.0, GMP_RNDZ, 1.6777213e7);
! 146: check24(b*11946704.0, GMP_RNDZ, 1.0010805e7);
! 147: check24(b*14321479.0, GMP_RNDZ, 1.0960715e7);
! 148: check24(b*2.0*13689673.0, GMP_RNDZ, 1.5155019e7);
! 149: check24(b*8388614.0, GMP_RNDZ, 8.38861e6);
! 150: check24(b*2.0*16777210.0, GMP_RNDZ, 1.6777212e7);
! 151: check24(b*10873622.0, GMP_RNDZ, 9.550631e6);
! 152:
! 153: check24(b*8388610.0, GMP_RNDU, 8.388609e6);
! 154: check24(b*2.0*16777214.0, GMP_RNDU, 1.6777215e7);
! 155: check24(b*8388612.0, GMP_RNDU, 8.388610e6);
! 156: check24(b*2.0*16777212.0, GMP_RNDU, 1.6777214e7);
! 157: check24(b*11946704.0, GMP_RNDU, 1.0010806e7);
! 158: check24(b*14321479.0, GMP_RNDU, 1.0960716e7);
! 159: check24(b*2.0*13689673.0, GMP_RNDU, 1.515502e7);
! 160: check24(b*8388614.0, GMP_RNDU, 8.388611e6);
! 161: check24(b*2.0*16777210.0, GMP_RNDU, 1.6777213e7);
! 162: check24(b*10873622.0, GMP_RNDU, 9.550632e6);
! 163:
! 164: check24(b*8388610.0, GMP_RNDD, 8.388608e6);
! 165: check24(b*2.0*16777214.0, GMP_RNDD, 1.6777214e7);
! 166: check24(b*8388612.0, GMP_RNDD, 8.388609e6);
! 167: check24(b*2.0*16777212.0, GMP_RNDD, 1.6777213e7);
! 168: check24(b*11946704.0, GMP_RNDD, 1.0010805e7);
! 169: check24(b*14321479.0, GMP_RNDD, 1.0960715e7);
! 170: check24(b*2.0*13689673.0, GMP_RNDD, 1.5155019e7);
! 171: check24(b*8388614.0, GMP_RNDD, 8.38861e6);
! 172: check24(b*2.0*16777210.0, GMP_RNDD, 1.6777212e7);
! 173: check24(b*10873622.0, GMP_RNDD, 9.550631e6);
! 174: }
! 175:
! 176: void
! 177: special (void)
! 178: {
! 179: mpfr_t x, z;
! 180: int inexact;
! 181: mp_prec_t p;
! 182:
! 183: mpfr_init (x);
! 184: mpfr_init (z);
! 185:
! 186: mpfr_set_prec (x, 27);
! 187: mpfr_set_str_raw (x, "0.110100111010101000010001011");
! 188: if ((inexact = mpfr_sqrt (x, x, GMP_RNDZ)) >= 0)
! 189: {
! 190: fprintf (stderr, "Wrong inexact flag: expected -1, got %d\n", inexact);
! 191: exit (1);
! 192: }
! 193:
! 194: mpfr_set_prec (x, 2);
! 195: for (p=2; p<1000; p++)
! 196: {
! 197: mpfr_set_prec (z, p);
! 198: mpfr_set_ui (z, 1, GMP_RNDN);
! 199: mpfr_add_one_ulp (z, GMP_RNDN);
! 200: mpfr_sqrt (x, z, GMP_RNDU);
! 201: if (mpfr_get_d1 (x) != 1.5)
! 202: {
! 203: fprintf (stderr, "Error: sqrt(1+ulp(1), up) should give 1.5 (prec=%u)\n", (unsigned) p);
! 204: printf ("got "); mpfr_print_binary (x); putchar ('\n');
! 205: exit (1);
! 206: }
! 207: }
! 208:
! 209: /* check inexact flag */
! 210: mpfr_set_prec (x, 5);
! 211: mpfr_set_str_raw (x, "1.1001E-2");
! 212: if ((inexact = mpfr_sqrt (x, x, GMP_RNDN)))
! 213: {
! 214: fprintf (stderr, "Wrong inexact flag: expected 0, got %d\n", inexact);
! 215: exit (1);
! 216: }
! 217:
! 218: mpfr_set_prec (x, 2);
! 219: mpfr_set_prec (z, 2);
! 220:
! 221: /* checks the sign is correctly set */
! 222: mpfr_set_d (x, 1.0, GMP_RNDN);
! 223: mpfr_set_d (z, -1.0, GMP_RNDN);
! 224: mpfr_sqrt (z, x, GMP_RNDN);
! 225: if (mpfr_cmp_ui (z, 0) < 0) {
! 226: fprintf (stderr, "Error: square root of %e gives %e\n",
! 227: mpfr_get_d1 (x), mpfr_get_d1 (z));
! 228: exit (1);
! 229: }
! 230:
! 231: mpfr_set_prec (x, 192);
! 232: mpfr_set_prec (z, 160);
! 233: mpfr_set_str_raw (z, "0.1011010100000100100100100110011001011100100100000011000111011001011101101101110000110100001000100001100001011000E1");
! 234: mpfr_set_prec (x, 160);
! 235: mpfr_sqrt(x, z, GMP_RNDN);
! 236: mpfr_sqrt(z, x, GMP_RNDN);
! 237:
! 238: mpfr_clear (x);
! 239: mpfr_clear (z);
! 240: }
! 241:
! 242: void
! 243: check_inexact (mp_prec_t p)
! 244: {
! 245: mpfr_t x, y, z;
! 246: mp_rnd_t rnd;
! 247: int inexact, sign;
! 248:
! 249: mpfr_init2 (x, p);
! 250: mpfr_init2 (y, p);
! 251: mpfr_init2 (z, 2*p);
! 252: mpfr_random (x);
! 253: rnd = LONG_RAND() % 4;
! 254: inexact = mpfr_sqrt (y, x, rnd);
! 255: if (mpfr_mul (z, y, y, rnd)) /* exact since prec(z) = 2*prec(y) */
! 256: {
! 257: fprintf (stderr, "Error: multiplication should be exact\n");
! 258: exit (1);
! 259: }
! 260: mpfr_sub (z, z, x, rnd); /* exact also */
! 261: sign = mpfr_cmp_ui (z, 0);
! 262: if (((inexact == 0) && (sign)) ||
! 263: ((inexact > 0) && (sign <= 0)) ||
! 264: ((inexact < 0) && (sign >= 0)))
! 265: {
! 266: fprintf (stderr, "Error: wrong inexact flag, expected %d, got %d\n",
! 267: sign, inexact);
! 268: printf ("x=");
! 269: mpfr_print_binary (x);
! 270: printf (" rnd=%s\n", mpfr_print_rnd_mode (rnd));
! 271: printf ("y="); mpfr_print_binary (y); putchar ('\n');
! 272: exit (1);
! 273: }
! 274: mpfr_clear (x);
! 275: mpfr_clear (y);
! 276: mpfr_clear (z);
! 277: }
! 278:
! 279: void
! 280: check_nan (void)
! 281: {
! 282: mpfr_t x, got;
! 283:
! 284: mpfr_init2 (x, 100L);
! 285: mpfr_init2 (got, 100L);
! 286:
! 287: /* sqrt(NaN) == NaN */
! 288: MPFR_CLEAR_FLAGS (x);
! 289: MPFR_SET_NAN (x);
! 290: ASSERT_ALWAYS (mpfr_sqrt (got, x, GMP_RNDZ) == 0); /* exact */
! 291: ASSERT_ALWAYS (mpfr_nan_p (got));
! 292:
! 293: /* sqrt(-1) == NaN */
! 294: mpfr_set_si (x, -1L, GMP_RNDZ);
! 295: ASSERT_ALWAYS (mpfr_sqrt (got, x, GMP_RNDZ) == 0); /* exact */
! 296: ASSERT_ALWAYS (mpfr_nan_p (got));
! 297:
! 298: /* sqrt(+inf) == +inf */
! 299: MPFR_CLEAR_FLAGS (x);
! 300: MPFR_SET_INF (x);
! 301: MPFR_SET_POS (x);
! 302: ASSERT_ALWAYS (mpfr_sqrt (got, x, GMP_RNDZ) == 0); /* exact */
! 303: ASSERT_ALWAYS (mpfr_inf_p (got));
! 304:
! 305: /* sqrt(-inf) == NaN */
! 306: MPFR_CLEAR_FLAGS (x);
! 307: MPFR_SET_INF (x);
! 308: MPFR_SET_NEG (x);
! 309: ASSERT_ALWAYS (mpfr_sqrt (got, x, GMP_RNDZ) == 0); /* exact */
! 310: ASSERT_ALWAYS (mpfr_nan_p (got));
! 311:
! 312: /* sqrt(-0) == 0 */
! 313: mpfr_set_si (x, 0L, GMP_RNDZ);
! 314: MPFR_SET_NEG (x);
! 315: ASSERT_ALWAYS (mpfr_sqrt (got, x, GMP_RNDZ) == 0); /* exact */
! 316: ASSERT_ALWAYS (mpfr_number_p (got));
! 317: ASSERT_ALWAYS (mpfr_cmp_ui (got, 0L) == 0);
! 318:
! 319: mpfr_clear (x);
! 320: mpfr_clear (got);
! 321: }
! 322:
! 323: double five = 5.0;
! 324:
! 325: int
! 326: main (void)
! 327: {
! 328: double a;
! 329: mp_prec_t p;
! 330: int k;
! 331: #ifdef MPFR_HAVE_FESETROUND
! 332: int i;
! 333:
! 334: mpfr_test_init ();
! 335:
! 336: /* On Debian potato glibc 2.1.3-18, sqrt() doesn't seem to respect
! 337: fesetround. */
! 338: {
! 339: double a, b;
! 340: mpfr_set_machine_rnd_mode (GMP_RNDU);
! 341: a = sqrt (five);
! 342: mpfr_set_machine_rnd_mode (GMP_RNDD);
! 343: b = sqrt (five);
! 344: if (a == b)
! 345: {
! 346: printf ("Tests suppressed, mpfr_set_machine_rnd_mode doesn't affect sqrt()\n");
! 347: goto nogood;
! 348: }
! 349: }
! 350:
! 351: SEED_RAND (time(NULL));
! 352: for (i=0;i<100000;i++)
! 353: {
! 354: a = drand();
! 355: if (a < 0.0) a = -a; /* ensures a is positive */
! 356: check (a, LONG_RAND() % 4);
! 357: }
! 358: nogood:
! 359: #endif
! 360:
! 361: check_nan ();
! 362:
! 363: for (p=2; p<200; p++)
! 364: for (k=0; k<200; k++)
! 365: check_inexact (p);
! 366: special ();
! 367: check_float();
! 368: #ifdef HAVE_INFS
! 369: check3 (DBL_NAN, GMP_RNDN, DBL_NAN);
! 370: check3 (-1.0, GMP_RNDN, DBL_NAN);
! 371: check3 (DBL_POS_INF, GMP_RNDN, DBL_POS_INF);
! 372: check3 (DBL_NEG_INF, GMP_RNDN, DBL_NAN);
! 373: #endif
! 374: check3(-0.0, GMP_RNDN, 0.0);
! 375: check4(6.37983013646045901440e+32, GMP_RNDN, "5.9bc5036d09e0c@13");
! 376: check4(1.0, GMP_RNDN, "1");
! 377: check4(1.0, GMP_RNDZ, "1");
! 378: check4(3.725290298461914062500000e-9, GMP_RNDN, "4@-4");
! 379: check4(3.725290298461914062500000e-9, GMP_RNDZ, "4@-4");
! 380: a=1190456976439861.0;
! 381: check4(a, GMP_RNDZ, "2.0e7957873529a@6");
! 382: check4(1024.0*a, GMP_RNDZ, "4.1cf2af0e6a534@7");
! 383: /* the following examples are bugs in Cygnus compiler/system, found by
! 384: Fabrice Rouillier while porting mpfr to Windows */
! 385: check4(9.89438396044940256501e-134, GMP_RNDU, "8.7af7bf0ebbee@-56");
! 386: check4(7.86528588050363751914e+31, GMP_RNDZ, "1.f81fc40f32062@13");
! 387: check4(0.99999999999999988897, GMP_RNDN, "f.ffffffffffff8@-1");
! 388: check4(1.00000000000000022204, GMP_RNDN, "1");
! 389: /* the following examples come from the paper "Number-theoretic Test
! 390: Generation for Directed Rounding" from Michael Parks, Table 4 */
! 391: a = 4503599627370496.0; /* 2^52 */
! 392:
! 393: check4(a*2.0*8732221479794286.0, GMP_RNDN, "1.f81fc40f32063@13");
! 394: check4(a*8550954388695124.0, GMP_RNDN, "1.60c012a92fc65@13");
! 395: check4(a*7842344481681754.0, GMP_RNDN, "1.51d17526c7161@13");
! 396: check4(a*5935035262218600.0, GMP_RNDN, "1.25e19302f7e51@13");
! 397: check4(a*5039650445085418.0, GMP_RNDN, "1.0ecea7dd2ec3d@13");
! 398: check4(a*5039721545366078.0, GMP_RNDN, "1.0ecf250e8e921@13");
! 399: check4(a*8005963117781324.0, GMP_RNDN, "1.5552f3eedcf33@13");
! 400: check4(a*6703494707970582.0, GMP_RNDN, "1.3853ee10c9c99@13");
! 401: check4(a*8010323124937260.0, GMP_RNDN, "1.556abe212b56f@13");
! 402: check4(a*2.0*8010776873384260.0, GMP_RNDN, "1.e2d9a51977e6e@13");
! 403:
! 404: check4(a*2.0*8732221479794286.0, GMP_RNDZ, "1.f81fc40f32062@13");
! 405: check4(a*8550954388695124.0, GMP_RNDZ, "1.60c012a92fc64@13");
! 406: check4(a*7842344481681754.0, GMP_RNDZ, "1.51d17526c716@13");
! 407: check4(a*5935035262218600.0, GMP_RNDZ, "1.25e19302f7e5@13");
! 408: check4(a*5039650445085418.0, GMP_RNDZ, "1.0ecea7dd2ec3c@13");
! 409: check4(a*5039721545366078.0, GMP_RNDZ, "1.0ecf250e8e92@13");
! 410: check4(a*8005963117781324.0, GMP_RNDZ, "1.5552f3eedcf32@13");
! 411: check4(a*6703494707970582.0, GMP_RNDZ, "1.3853ee10c9c98@13");
! 412: check4(a*8010323124937260.0, GMP_RNDZ, "1.556abe212b56e@13");
! 413: check4(a*2.0*8010776873384260.0, GMP_RNDZ, "1.e2d9a51977e6d@13");
! 414:
! 415: check4(a*2.0*8732221479794286.0, GMP_RNDU, "1.f81fc40f32063@13");
! 416: check4(a*8550954388695124.0, GMP_RNDU, "1.60c012a92fc65@13");
! 417: check4(a*7842344481681754.0, GMP_RNDU, "1.51d17526c7161@13");
! 418: check4(a*5935035262218600.0, GMP_RNDU, "1.25e19302f7e51@13");
! 419: check4(a*5039650445085418.0, GMP_RNDU, "1.0ecea7dd2ec3d@13");
! 420: check4(a*5039721545366078.0, GMP_RNDU, "1.0ecf250e8e921@13");
! 421: check4(a*8005963117781324.0, GMP_RNDU, "1.5552f3eedcf33@13");
! 422: check4(a*6703494707970582.0, GMP_RNDU, "1.3853ee10c9c99@13");
! 423: check4(a*8010323124937260.0, GMP_RNDU, "1.556abe212b56f@13");
! 424: check4(a*2.0*8010776873384260.0, GMP_RNDU, "1.e2d9a51977e6e@13");
! 425:
! 426: check4(a*2.0*8732221479794286.0, GMP_RNDD, "1.f81fc40f32062@13");
! 427: check4(a*8550954388695124.0, GMP_RNDD, "1.60c012a92fc64@13");
! 428: check4(a*7842344481681754.0, GMP_RNDD, "1.51d17526c716@13");
! 429: check4(a*5935035262218600.0, GMP_RNDD, "1.25e19302f7e5@13");
! 430: check4(a*5039650445085418.0, GMP_RNDD, "1.0ecea7dd2ec3c@13");
! 431: check4(a*5039721545366078.0, GMP_RNDD, "1.0ecf250e8e92@13");
! 432: check4(a*8005963117781324.0, GMP_RNDD, "1.5552f3eedcf32@13");
! 433: check4(a*6703494707970582.0, GMP_RNDD, "1.3853ee10c9c98@13");
! 434: check4(a*8010323124937260.0, GMP_RNDD, "1.556abe212b56e@13");
! 435: check4(a*2.0*8010776873384260.0, GMP_RNDD, "1.e2d9a51977e6d@13");
! 436:
! 437: return 0;
! 438: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>