double _Complex __muldc3(double fa, double fb, double fc, double fd) { union ud ua, ub, uc, ud, ux, uy, uac, ubd, uad, ubc; ua.f = fa; ub.f = fb; uc.f = fc; ud.f = fd; uac.f = ua.f * uc.f; ubd.f = ub.f * ud.f; uad.f = ua.f * ud.f; ubc.f = ub.f * uc.f; ux.f=uac.f-ubd.f; uy.f=uad.f+ubc.f; if (DOUBLE_ISNAN(ux) && DOUBLE_ISNAN(uy)) { /* Recover infinities that computed as NaN+iNaN ... */ int recalc = 0; if (DOUBLE_ISINF(ua) || DOUBLE_ISINF(ub) ) { // z is infinite /* "Box" the infinity and change NaNs in the other factor to 0 */ ua.f = pcc_copysign(DOUBLE_ISINF(ua) ? 1.0 : 0.0, ua.f); ub.f = pcc_copysign(DOUBLE_ISINF(ub) ? 1.0 : 0.0, ub.f); if (DOUBLE_ISNAN(uc)) uc.f = pcc_copysign(0.0, uc.f); if (DOUBLE_ISNAN(ud)) ud.f = pcc_copysign(0.0, ud.f); recalc = 1; } if (DOUBLE_ISINF(uc) || DOUBLE_ISINF(ud) ) { // w is infinite /* "Box" the infinity and change NaNs in the other factor to 0 */ uc.f = pcc_copysign(DOUBLE_ISINF(uc) ? 1.0 : 0.0, uc.f); ud.f = pcc_copysign(DOUBLE_ISINF(ud) ? 1.0 : 0.0, ud.f); if (DOUBLE_ISNAN(ua)) ua.f = pcc_copysign(0.0, ua.f); if (DOUBLE_ISNAN(ub)) ub.f = pcc_copysign(0.0, ub.f); recalc = 1; } if (!recalc && (DOUBLE_ISINF(uac) || DOUBLE_ISINF(ubd) || DOUBLE_ISINF(uad) || DOUBLE_ISINF(ubc))) { /* Recover infinities from overflow by changing NaNs to 0 ... */ if (DOUBLE_ISNAN(ua)) ua.f = pcc_copysign(0.0, ua.f); if (DOUBLE_ISNAN(ub)) ub.f = pcc_copysign(0.0, ub.f); if (DOUBLE_ISNAN(uc)) uc.f = pcc_copysign(0.0, uc.f); if (DOUBLE_ISNAN(ud)) ud.f = pcc_copysign(0.0, ud.f); recalc = 1; } if (recalc) { ux.f = __builtin_inf() * ( ua.f * uc.f - ub.f * ud.f ); uy.f = __builtin_inf() * ( ua.f * ud.f + ub.f * uc.f ); } } return ux.f + 1.0iF * uy.f; }
static void check_inf_nan (void) { /* only if nans and infs are available */ #if _GMP_IEEE_FLOATS mpfr_t x; double d; long exp; mpfr_init2 (x, 123); mpfr_set_inf (x, 1); d = mpfr_get_d_2exp (&exp, x, MPFR_RNDZ); ASSERT_ALWAYS (d > 0); ASSERT_ALWAYS (DOUBLE_ISINF (d)); mpfr_set_inf (x, -1); d = mpfr_get_d_2exp (&exp, x, MPFR_RNDZ); ASSERT_ALWAYS (d < 0); ASSERT_ALWAYS (DOUBLE_ISINF (d)); mpfr_set_nan (x); d = mpfr_get_d_2exp (&exp, x, MPFR_RNDZ); ASSERT_ALWAYS (DOUBLE_ISNAN (d)); mpfr_clear (x); #endif }
static void check_inf_nan (void) { /* only if nans and infs are available */ #if _GMP_IEEE_FLOATS && !defined(MPFR_ERRDIVZERO) mpfr_t x; double d; mpfr_init2 (x, 123); mpfr_set_inf (x, 1); d = mpfr_get_d (x, MPFR_RNDZ); ASSERT_ALWAYS (d > 0); ASSERT_ALWAYS (DOUBLE_ISINF (d)); mpfr_set_inf (x, -1); d = mpfr_get_d (x, MPFR_RNDZ); ASSERT_ALWAYS (d < 0); ASSERT_ALWAYS (DOUBLE_ISINF (d)); mpfr_set_nan (x); d = mpfr_get_d (x, MPFR_RNDZ); ASSERT_ALWAYS (DOUBLE_ISNAN (d)); mpfr_clear (x); #endif }
static void check_inf_nan (void) { #if !defined(MPFR_ERRDIVZERO) mpfr_t x; double d; long exp; mpfr_init2 (x, 123); mpfr_set_inf (x, 1); d = (double) mpfr_get_ld_2exp (&exp, x, MPFR_RNDZ); MPFR_ASSERTN (d > 0); MPFR_ASSERTN (DOUBLE_ISINF (d)); mpfr_set_inf (x, -1); d = (double) mpfr_get_ld_2exp (&exp, x, MPFR_RNDZ); MPFR_ASSERTN (d < 0); MPFR_ASSERTN (DOUBLE_ISINF (d)); mpfr_set_nan (x); d = (double) mpfr_get_ld_2exp (&exp, x, MPFR_RNDZ); MPFR_ASSERTN (DOUBLE_ISNAN (d)); mpfr_clear (x); #endif }
static double pcc_scalbn(double x, int exp) { union ud x1, z1, z2; x1.f = x; if (DOUBLE_ISINF(x1) || DOUBLE_ISNAN(x1)) return x; exp += 1023; z1.dil = z2.dil = 0; if (exp <= 0) { z2.dih = (1023 - 110) << 20; x *= z2.f; exp += 110; if (exp < 0) exp = 0; } else if (exp > 2046) { z2.dih = (1024 + 55) << 20; x *= z2.f; exp -= 55; if (exp > 2046) exp = 2046; } z1.dih = exp << 20; x *= z1.f; return x; }
static void check_get_d_2exp_inf_nan (void) { double var_d; long exp; mpfr_t var; mpfr_init2 (var, MPFR_PREC_MIN); mpfr_set_nan (var); var_d = mpfr_get_d_2exp (&exp, var, MPFR_RNDN); if (!DOUBLE_ISNAN (var_d)) { printf ("mpfr_get_d_2exp with a NAN mpfr value returned a wrong value :\n" " waiting for %g got %g\n", MPFR_DBL_NAN, var_d); exit (1); } mpfr_set_zero (var, 1); var_d = mpfr_get_d_2exp (&exp, var, MPFR_RNDN); if ((exp != 0) || (var_d != 0.0)) { printf ("mpfr_get_d_2exp with a +0.0 mpfr value returned a wrong value :\n" " double waiting for 0.0 got %g\n exp waiting for 0 got %ld\n", var_d, exp); exit (1); } mpfr_set_zero (var, -1); var_d = mpfr_get_d_2exp (&exp, var, MPFR_RNDN); if ((exp != 0) || (var_d != DBL_NEG_ZERO)) { printf ("mpfr_get_d_2exp with a +0.0 mpfr value returned a wrong value :\n" " double waiting for %g got %g\n exp waiting for 0 got %ld\n", DBL_NEG_ZERO, var_d, exp); exit (1); } mpfr_set_inf (var, 1); var_d = mpfr_get_d_2exp (&exp, var, MPFR_RNDN); if (var_d != MPFR_DBL_INFP) { printf ("mpfr_get_d_2exp with a +Inf mpfr value returned a wrong value :\n" " waiting for %g got %g\n", MPFR_DBL_INFP, var_d); exit (1); } mpfr_set_inf (var, -1); var_d = mpfr_get_d_2exp (&exp, var, MPFR_RNDN); if (var_d != MPFR_DBL_INFM) { printf ("mpfr_get_d_2exp with a -Inf mpfr value returned a wrong value :\n" " waiting for %g got %g\n", MPFR_DBL_INFM, var_d); exit (1); } mpfr_clear (var); }
int main (int argc, char *argv[]) { mpfr_t x, y, z; unsigned long k, n; volatile double d; double dd; tests_start_mpfr (); mpfr_test_init (); #ifndef MPFR_DOUBLE_SPEC printf ("Warning! The MPFR_DOUBLE_SPEC macro is not defined. This means\n" "that you do not have a conforming C implementation and problems\n" "may occur with conversions between MPFR numbers and standard\n" "floating-point types. Please contact the MPFR team.\n"); #elif MPFR_DOUBLE_SPEC == 0 /* printf ("The type 'double' of your C implementation does not seem to\n" "correspond to the IEEE-754 double precision. Though code has\n" "been written to support such implementations, tests have been\n" "done only on IEEE-754 double-precision implementations and\n" "conversions between MPFR numbers and standard floating-point\n" "types may be inaccurate. You may wish to contact the MPFR team\n" "for further testing.\n"); */ printf ("The type 'double' of your C implementation does not seem to\n" "correspond to the IEEE-754 double precision. Such particular\n" "implementations are not supported yet, and conversions between\n" "MPFR numbers and standard floating-point types may be very\n" "inaccurate.\n"); printf ("FLT_RADIX = %ld\n", (long) FLT_RADIX); printf ("DBL_MANT_DIG = %ld\n", (long) DBL_MANT_DIG); printf ("DBL_MIN_EXP = %ld\n", (long) DBL_MIN_EXP); printf ("DBL_MAX_EXP = %ld\n", (long) DBL_MAX_EXP); #endif mpfr_init (x); mpfr_set_nan (x); d = mpfr_get_d (x, MPFR_RNDN); if (! DOUBLE_ISNAN (d)) { printf ("ERROR for NAN (1)\n"); #ifdef MPFR_NANISNAN printf ("The reason is that NAN == NAN. Please look at the configure " "output\nand Section \"In case of problem\" of the INSTALL " "file.\n"); #endif exit (1); } mpfr_set_ui (x, 0, MPFR_RNDN); mpfr_set_d (x, d, MPFR_RNDN); if (! mpfr_nan_p (x)) { printf ("ERROR for NAN (2)\n"); #ifdef MPFR_NANISNAN printf ("The reason is that NAN == NAN. Please look at the configure " "output\nand Section \"In case of problem\" of the INSTALL " "file.\n"); #endif exit (1); } d = 0.0; mpfr_set_d (x, d, MPFR_RNDN); MPFR_ASSERTN(mpfr_cmp_ui (x, 0) == 0 && MPFR_IS_POS(x)); d = -d; mpfr_set_d (x, d, MPFR_RNDN); if (mpfr_cmp_ui (x, 0) != 0 || MPFR_IS_POS(x)) { printf ("Error in mpfr_set_d on -0\n"); exit (1); } mpfr_set_inf (x, 1); d = mpfr_get_d (x, MPFR_RNDN); mpfr_set_ui (x, 0, MPFR_RNDN); mpfr_set_d (x, d, MPFR_RNDN); MPFR_ASSERTN(mpfr_inf_p (x) && mpfr_sgn (x) > 0); mpfr_set_inf (x, -1); d = mpfr_get_d (x, MPFR_RNDN); mpfr_set_ui (x, 0, MPFR_RNDN); mpfr_set_d (x, d, MPFR_RNDN); MPFR_ASSERTN(mpfr_inf_p (x) && mpfr_sgn (x) < 0); mpfr_set_prec (x, 2); /* checks that denormalized are not flushed to zero */ d = DBL_MIN; /* 2^(-1022) */ for (n=0; n<52; n++, d /= 2.0) if (d != 0.0) /* should be 2^(-1022-n) */ { mpfr_set_d (x, d, MPFR_RNDN); if (mpfr_cmp_ui_2exp (x, 1, -1022-n)) { printf ("Wrong result for d=2^(%ld), ", -1022-n); printf ("got "); mpfr_out_str (stdout, 10, 10, x, MPFR_RNDN); printf ("\n"); mpfr_print_binary (x); puts (""); exit (1); } } /* checks that rounds to nearest sets the last bit to zero in case of equal distance */ mpfr_set_d (x, 5.0, MPFR_RNDN); if (mpfr_cmp_ui (x, 4)) { printf ("Error in tset_d: expected 4.0, got "); mpfr_print_binary (x); putchar('\n'); exit (1); } mpfr_set_d (x, -5.0, MPFR_RNDN); if (mpfr_cmp_si (x, -4)) { printf ("Error in tset_d: expected -4.0, got "); mpfr_print_binary (x); putchar('\n'); exit (1); } mpfr_set_d (x, 9.84891017624509146344e-01, MPFR_RNDU); if (mpfr_cmp_ui (x, 1)) { printf ("Error in tset_d: expected 1.0, got "); mpfr_print_binary (x); putchar('\n'); exit (1); } mpfr_init2 (z, 32); mpfr_set_d (z, 1.0, (mpfr_rnd_t) 0); if (mpfr_cmp_ui (z, 1)) { mpfr_print_binary (z); puts (""); printf ("Error: 1.0 != 1.0\n"); exit (1); } mpfr_set_prec (x, 53); mpfr_init2 (y, 53); mpfr_set_d (x, d=-1.08007920352320089721e+150, (mpfr_rnd_t) 0); if (mpfr_get_d1 (x) != d) { mpfr_print_binary (x); puts (""); printf ("Error: get_d o set_d <> identity for d = %1.20e %1.20e\n", d, mpfr_get_d1 (x)); exit (1); } mpfr_set_d (x, 8.06294740693074521573e-310, (mpfr_rnd_t) 0); d = -6.72658901114033715233e-165; mpfr_set_d (x, d, (mpfr_rnd_t) 0); if (d != mpfr_get_d1 (x)) { mpfr_print_binary (x); puts (""); printf ("Error: get_d o set_d <> identity for d = %1.20e %1.20e\n", d, mpfr_get_d1 (x)); exit (1); } n = (argc==1) ? 500000 : atoi(argv[1]); for (k = 1; k <= n; k++) { do { d = DBL_RAND (); } #ifdef HAVE_DENORMS while (0); #else while (ABS(d) < DBL_MIN); #endif mpfr_set_d (x, d, (mpfr_rnd_t) 0); dd = mpfr_get_d1 (x); if (d != dd && !(Isnan(d) && Isnan(dd))) { printf ("Mismatch on : %1.18g != %1.18g\n", d, mpfr_get_d1 (x)); mpfr_print_binary (x); puts (""); exit (1); } } mpfr_clear (x); mpfr_clear (y); mpfr_clear (z); tests_end_mpfr (); return 0; }
double _Complex __divdc3(double ax, double bx, double cx, double dx) { double denom; union ud ua, ub, uc, ud, ur, ulogbw, ux, uy; int uci, udi, res, ilogbw = 0; ua.f = ax; ub.f = bx; uc.f = cx; ud.f = dx; /* fabsf; clear sign */ uci = uc.dih & DOUBLE_MANTEXP; udi = ud.dih & DOUBLE_MANTEXP; /* fmaxf; ordinary integer compare */ if ((uci > udi) || (uci == udi && uc.dil > ud.dil)) { ur.dih = uci; ur.dil = uc.dil; } else { ur.dih = udi; ur.dil = ud.dil; } /* logbf */ res = ur.dih >> 20; if (ur.dih == 0 && ur.dil == 0) ulogbw.f = (double)-1.0/ur.f; else if (res == 2047) ulogbw.f = ur.f * ur.f; else if (res == 0) ulogbw.f = -1022.0; else ulogbw.f = (res-1023); /* isfinite */ if (DOUBLE_ISFIN(ulogbw)) { ilogbw = (int)ulogbw.f; uc.f = pcc_scalbn(uc.f, -ilogbw); ud.f = pcc_scalbn(ud.f, -ilogbw); } denom = uc.f * uc.f + ud.f * ud.f; ux.f = pcc_scalbn((ua.f * uc.f + ub.f * ud.f) / denom, -ilogbw); uy.f = pcc_scalbn((ub.f * uc.f - ua.f * ud.f) / denom, -ilogbw); if (DOUBLE_ISNAN(ux) && DOUBLE_ISNAN(uy)) { if ((denom == 0.0) && (!DOUBLE_ISNAN(ua) || !DOUBLE_ISNAN(ub))) { ux.f = pcc_copysign(__builtin_inff(), uc.f) * ua.f; uy.f = pcc_copysign(__builtin_inff(), uc.f) * ub.f; } else if ((DOUBLE_ISINF(ua) || DOUBLE_ISINF(ub)) && DOUBLE_ISFIN(uc) && DOUBLE_ISFIN(ud)) { ua.f = pcc_copysign(DOUBLE_ISINF(ua) ? 1.0 : 0.0, ua.f); ub.f = pcc_copysign(DOUBLE_ISINF(ub) ? 1.0 : 0.0, ub.f); ux.f = __builtin_inf() * ( ua.f * uc.f + ub.f * ud.f ); uy.f = __builtin_inf() * ( ub.f * uc.f - ua.f * ud.f ); } else if (DOUBLE_ISINF(ulogbw) && DOUBLE_ISFIN(ua) && DOUBLE_ISFIN(ub)) { uc.f = pcc_copysign(DOUBLE_ISINF(uc) ? 1.0 : 0.0, uc.f); ud.f = pcc_copysign(DOUBLE_ISINF(ud) ? 1.0 : 0.0, ud.f); ux.f = 0.0 * ( ua.f * uc.f + ub.f * ud.f ); uy.f = 0.0 * ( ub.f * uc.f - ua.f * ud.f ); } } return ux.f + 1.0iF * uy.f; }
static void check_special (void) { __float128 f; mpfr_t x; mpfr_init2 (x, 113); #if !defined(MPFR_ERRDIVZERO) /* check NaN */ f = 0.0 / 0.0; mpfr_set_float128 (x, f, MPFR_RNDN); if (! mpfr_nan_p (x)) { printf ("Error in mpfr_set_float128(x, NaN)\n"); exit (1); } f = mpfr_get_float128 (x, MPFR_RNDN); if (! DOUBLE_ISNAN (f)) { printf ("Error in mpfr_get_float128(NaN)\n"); printf ("got %f\n", (double) f); exit (1); } /* check +Inf */ f = 1.0 / 0.0; mpfr_set_float128 (x, f, MPFR_RNDN); if (! mpfr_inf_p (x) || MPFR_IS_NEG (x)) { printf ("Error in mpfr_set_float128(x, +Inf)\n"); exit (1); } f = mpfr_get_float128 (x, MPFR_RNDN); if (f != (1.0 / 0.0)) { printf ("Error in mpfr_get_float128(+Inf)\n"); exit (1); } /* check -Inf */ f = -1.0 / 0.0; mpfr_set_float128 (x, f, MPFR_RNDN); if (! mpfr_inf_p (x) || MPFR_IS_POS (x)) { printf ("Error in mpfr_set_float128(x, -Inf)\n"); exit (1); } f = mpfr_get_float128 (x, MPFR_RNDN); if (f != (-1.0 / 0.0)) { printf ("Error in mpfr_get_float128(-Inf)\n"); exit (1); } #endif /* check +0 */ f = 0.0; mpfr_set_float128 (x, f, MPFR_RNDN); if (! mpfr_zero_p (x) || MPFR_IS_NEG (x)) { printf ("Error in mpfr_set_float128(x, +0)\n"); exit (1); } f = mpfr_get_float128 (x, MPFR_RNDN); if (f != 0.0) /* the sign is not checked */ { printf ("Error in mpfr_get_float128(+0.0)\n"); exit (1); } #if !defined(MPFR_ERRDIVZERO) && defined(HAVE_SIGNEDZ) if (1 / f != 1 / 0.0) /* check the sign */ { printf ("Error in mpfr_get_float128(+0.0)\n"); exit (1); } #endif /* check -0 */ f = -0.0; mpfr_set_float128 (x, f, MPFR_RNDN); if (! mpfr_zero_p (x)) { printf ("Error in mpfr_set_float128(x, -0)\n"); exit (1); } #if defined(HAVE_SIGNEDZ) if (MPFR_IS_POS (x)) { printf ("Error in mpfr_set_float128(x, -0)\n"); exit (1); } #endif f = mpfr_get_float128 (x, MPFR_RNDN); if (f != -0.0) /* the sign is not checked */ { printf ("Error in mpfr_get_float128(-0.0)\n"); exit (1); } #if !defined(MPFR_ERRDIVZERO) && defined(HAVE_SIGNEDZ) if (1 / f != 1 / -0.0) /* check the sign */ { printf ("Error in mpfr_get_float128(-0.0)\n"); exit (1); } #endif mpfr_clear (x); }