/* Test file for mpfr_pow, mpfr_pow_ui and mpfr_pow_si. Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. Contributed by the Arenaire and Cacao projects, INRIA. 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include "mpfr-test.h" #ifdef CHECK_EXTERNAL static int test_pow (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mp_rnd_t rnd_mode) { int res; int ok = rnd_mode == GMP_RNDN && mpfr_number_p (b) && mpfr_number_p (c) && mpfr_get_prec (a) >= 53; if (ok) { mpfr_print_raw (b); printf (" "); mpfr_print_raw (c); } res = mpfr_pow (a, b, c, rnd_mode); if (ok) { printf (" "); mpfr_print_raw (a); printf ("\n"); } return res; } #else #define test_pow mpfr_pow #endif #define TEST_FUNCTION test_pow #define TWO_ARGS #include "tgeneric.c" #define TEST_FUNCTION mpfr_pow_ui #define INTEGER_TYPE unsigned long #define RAND_FUNCTION(x) mpfr_random2(x, MPFR_LIMB_SIZE (x), 1) #include "tgeneric_ui.c" #define TEST_FUNCTION mpfr_pow_si #define INTEGER_TYPE long #define RAND_FUNCTION(x) mpfr_random2(x, MPFR_LIMB_SIZE (x), 1) #define test_generic_ui test_generic_si #include "tgeneric_ui.c" static void check_pow_ui (void) { mpfr_t a, b; int res; mpfr_init2 (a, 53); mpfr_init2 (b, 53); /* check in-place operations */ mpfr_set_str (b, "0.6926773", 10, GMP_RNDN); mpfr_pow_ui (a, b, 10, GMP_RNDN); mpfr_pow_ui (b, b, 10, GMP_RNDN); if (mpfr_cmp (a, b)) { printf ("Error for mpfr_pow_ui (b, b, ...)\n"); exit (1); } /* check large exponents */ mpfr_set_ui (b, 1, GMP_RNDN); mpfr_pow_ui (a, b, 4294967295UL, GMP_RNDN); mpfr_set_inf (a, -1); mpfr_pow_ui (a, a, 4049053855UL, GMP_RNDN); if (!mpfr_inf_p (a) || (mpfr_sgn (a) >= 0)) { printf ("Error for (-Inf)^4049053855\n"); exit (1); } mpfr_set_inf (a, -1); mpfr_pow_ui (a, a, (unsigned long) 30002752, GMP_RNDN); if (!mpfr_inf_p (a) || (mpfr_sgn (a) <= 0)) { printf ("Error for (-Inf)^30002752\n"); exit (1); } /* Check underflow */ mpfr_set_str_binary (a, "1E-1"); res = mpfr_pow_ui (a, a, -mpfr_get_emin (), GMP_RNDN); if (MPFR_GET_EXP (a) != mpfr_get_emin () + 1) { printf ("Error for (1e-1)^MPFR_EMAX_MAX\n"); mpfr_dump (a); exit (1); } mpfr_set_str_binary (a, "1E-10"); res = mpfr_pow_ui (a, a, -mpfr_get_emin (), GMP_RNDZ); if (!MPFR_IS_ZERO (a)) { printf ("Error for (1e-10)^MPFR_EMAX_MAX\n"); mpfr_dump (a); exit (1); } /* Check overflow */ mpfr_set_str_binary (a, "1E10"); res = mpfr_pow_ui (a, a, ULONG_MAX, GMP_RNDN); if (!MPFR_IS_INF (a) || MPFR_SIGN (a) < 0) { printf ("Error for (1e10)^ULONG_MAX\n"); exit (1); } /* Check 0 */ MPFR_SET_ZERO (a); MPFR_SET_POS (a); mpfr_set_si (b, -1, GMP_RNDN); res = mpfr_pow_ui (b, a, 1, GMP_RNDN); if (res != 0 || MPFR_IS_NEG (b)) { printf ("Error for (0+)^1\n"); exit (1); } MPFR_SET_ZERO (a); MPFR_SET_NEG (a); mpfr_set_ui (b, 1, GMP_RNDN); res = mpfr_pow_ui (b, a, 5, GMP_RNDN); if (res != 0 || MPFR_IS_POS (b)) { printf ("Error for (0-)^5\n"); exit (1); } MPFR_SET_ZERO (a); MPFR_SET_NEG (a); mpfr_set_si (b, -1, GMP_RNDN); res = mpfr_pow_ui (b, a, 6, GMP_RNDN); if (res != 0 || MPFR_IS_NEG (b)) { printf ("Error for (0-)^6\n"); exit (1); } mpfr_set_prec (a, 122); mpfr_set_prec (b, 122); mpfr_set_str_binary (a, "0.10000010010000111101001110100101101010011110011100001111000001001101000110011001001001001011001011010110110110101000111011E1"); mpfr_set_str_binary (b, "0.11111111100101001001000001000001100011100000001110111111100011111000111011100111111111110100011000111011000100100011001011E51290375"); mpfr_pow_ui (a, a, 2026876995UL, GMP_RNDU); if (mpfr_cmp (a, b) != 0) { printf ("Error for x^2026876995\n"); exit (1); } mpfr_set_prec (a, 29); mpfr_set_prec (b, 29); mpfr_set_str_binary (a, "1.0000000000000000000000001111"); mpfr_set_str_binary (b, "1.1001101111001100111001010111e165"); mpfr_pow_ui (a, a, 2055225053, GMP_RNDZ); if (mpfr_cmp (a, b) != 0) { printf ("Error for x^2055225053\n"); printf ("Expected "); mpfr_out_str (stdout, 2, 0, b, GMP_RNDN); printf ("\nGot "); mpfr_out_str (stdout, 2, 0, a, GMP_RNDN); printf ("\n"); exit (1); } /* worst case found by Vincent Lefevre, 25 Nov 2006 */ mpfr_set_prec (a, 53); mpfr_set_prec (b, 53); mpfr_set_str_binary (a, "1.0000010110000100001000101101101001011101101011010111"); mpfr_set_str_binary (b, "1.0000110111101111011010110100001100010000001010110100E1"); mpfr_pow_ui (a, a, 35, GMP_RNDN); if (mpfr_cmp (a, b) != 0) { printf ("Error in mpfr_pow_ui for worst case (1)\n"); printf ("Expected "); mpfr_out_str (stdout, 2, 0, b, GMP_RNDN); printf ("\nGot "); mpfr_out_str (stdout, 2, 0, a, GMP_RNDN); printf ("\n"); exit (1); } /* worst cases found on 2006-11-26 */ mpfr_set_str_binary (a, "1.0110100111010001101001010111001110010100111111000011"); mpfr_set_str_binary (b, "1.1111010011101110001111010110000101110000110110101100E17"); mpfr_pow_ui (a, a, 36, GMP_RNDD); if (mpfr_cmp (a, b) != 0) { printf ("Error in mpfr_pow_ui for worst case (2)\n"); printf ("Expected "); mpfr_out_str (stdout, 2, 0, b, GMP_RNDN); printf ("\nGot "); mpfr_out_str (stdout, 2, 0, a, GMP_RNDN); printf ("\n"); exit (1); } mpfr_set_str_binary (a, "1.1001010100001110000110111111100011011101110011000100"); mpfr_set_str_binary (b, "1.1100011101101101100010110001000001110001111110010001E23"); mpfr_pow_ui (a, a, 36, GMP_RNDU); if (mpfr_cmp (a, b) != 0) { printf ("Error in mpfr_pow_ui for worst case (3)\n"); printf ("Expected "); mpfr_out_str (stdout, 2, 0, b, GMP_RNDN); printf ("\nGot "); mpfr_out_str (stdout, 2, 0, a, GMP_RNDN); printf ("\n"); exit (1); } mpfr_clear (a); mpfr_clear (b); } static void check_pow_si (void) { mpfr_t x; mpfr_init (x); mpfr_set_nan (x); mpfr_pow_si (x, x, -1, GMP_RNDN); MPFR_ASSERTN(mpfr_nan_p (x)); mpfr_set_inf (x, 1); mpfr_pow_si (x, x, -1, GMP_RNDN); MPFR_ASSERTN(mpfr_cmp_ui (x, 0) == 0 && MPFR_IS_POS(x)); mpfr_set_inf (x, -1); mpfr_pow_si (x, x, -1, GMP_RNDN); MPFR_ASSERTN(mpfr_cmp_ui (x, 0) == 0 && MPFR_IS_NEG(x)); mpfr_set_inf (x, -1); mpfr_pow_si (x, x, -2, GMP_RNDN); MPFR_ASSERTN(mpfr_cmp_ui (x, 0) == 0 && MPFR_IS_POS(x)); mpfr_set_ui (x, 0, GMP_RNDN); mpfr_pow_si (x, x, -1, GMP_RNDN); MPFR_ASSERTN(mpfr_inf_p (x) && mpfr_sgn (x) > 0); mpfr_set_ui (x, 0, GMP_RNDN); mpfr_neg (x, x, GMP_RNDN); mpfr_pow_si (x, x, -1, GMP_RNDN); MPFR_ASSERTN(mpfr_inf_p (x) && mpfr_sgn (x) < 0); mpfr_set_ui (x, 0, GMP_RNDN); mpfr_neg (x, x, GMP_RNDN); mpfr_pow_si (x, x, -2, GMP_RNDN); MPFR_ASSERTN(mpfr_inf_p (x) && mpfr_sgn (x) > 0); mpfr_set_si (x, 2, GMP_RNDN); mpfr_pow_si (x, x, LONG_MAX, GMP_RNDN); /* 2^LONG_MAX */ if (LONG_MAX > mpfr_get_emax () - 1) /* LONG_MAX + 1 > emax */ { MPFR_ASSERTN (mpfr_inf_p (x)); } else { MPFR_ASSERTN (mpfr_cmp_si_2exp (x, 1, LONG_MAX)); } mpfr_set_si (x, 2, GMP_RNDN); mpfr_pow_si (x, x, LONG_MIN, GMP_RNDN); /* 2^LONG_MIN */ if (LONG_MIN + 1 < mpfr_get_emin ()) { MPFR_ASSERTN (mpfr_zero_p (x)); } else { MPFR_ASSERTN (mpfr_cmp_si_2exp (x, 1, LONG_MIN)); } mpfr_set_si (x, 2, GMP_RNDN); mpfr_pow_si (x, x, LONG_MIN + 1, GMP_RNDN); /* 2^(LONG_MIN+1) */ if (mpfr_nan_p (x)) { printf ("Error in pow_si(2, LONG_MIN+1): got NaN\n"); exit (1); } if (LONG_MIN + 2 < mpfr_get_emin ()) { MPFR_ASSERTN (mpfr_zero_p (x)); } else { MPFR_ASSERTN (mpfr_cmp_si_2exp (x, 1, LONG_MIN + 1)); } mpfr_set_si_2exp (x, 1, -1, GMP_RNDN); /* 0.5 */ mpfr_pow_si (x, x, LONG_MIN, GMP_RNDN); /* 2^(-LONG_MIN) */ if (LONG_MIN < 1 - mpfr_get_emax ()) /* 1 - LONG_MIN > emax */ { MPFR_ASSERTN (mpfr_inf_p (x)); } else { MPFR_ASSERTN (mpfr_cmp_si_2exp (x, 2, - (LONG_MIN + 1))); } mpfr_clear (x); } static void check_special_pow_si () { mpfr_t a, b; mp_exp_t emin; mpfr_init (a); mpfr_init (b); mpfr_set_str (a, "2E100000000", 10, GMP_RNDN); mpfr_set_si (b, -10, GMP_RNDN); test_pow (b, a, b, GMP_RNDN); if (!MPFR_IS_ZERO(b)) { printf("Pow(2E10000000, -10) failed\n"); mpfr_dump (a); mpfr_dump (b); exit(1); } emin = mpfr_get_emin (); mpfr_set_emin (-10); mpfr_set_si (a, -2, GMP_RNDN); mpfr_pow_si (b, a, -10000, GMP_RNDN); if (!MPFR_IS_ZERO (b)) { printf ("Pow_so (1, -10000) doesn't underflow if emin=-10.\n"); mpfr_dump (a); mpfr_dump (b); exit (1); } mpfr_set_emin (emin); mpfr_clear (a); mpfr_clear (b); } static void pow_si_long_min (void) { mpfr_t x, y, z; int inex; mpfr_inits2 (sizeof(long) * CHAR_BIT + 32, x, y, z, (void *) 0); mpfr_set_si_2exp (x, 3, -1, GMP_RNDN); /* 1.5 */ inex = mpfr_set_si (y, LONG_MIN, GMP_RNDN); MPFR_ASSERTN (inex == 0); mpfr_nextbelow (y); mpfr_pow (y, x, y, GMP_RNDD); inex = mpfr_set_si (z, LONG_MIN, GMP_RNDN); MPFR_ASSERTN (inex == 0); mpfr_nextabove (z); mpfr_pow (z, x, z, GMP_RNDU); mpfr_pow_si (x, x, LONG_MIN, GMP_RNDN); /* 1.5^LONG_MIN */ if (mpfr_cmp (x, y) < 0 || mpfr_cmp (x, z) > 0) { printf ("Error in pow_si_long_min\n"); exit (1); } mpfr_clears (x, y, z, (void *) 0); } static void check_inexact (mp_prec_t p) { mpfr_t x, y, z, t; unsigned long u; mp_prec_t q; int inexact, cmp; int rnd; mpfr_init2 (x, p); mpfr_init (y); mpfr_init (z); mpfr_init (t); mpfr_random (x); u = randlimb () % 2; for (q = 2; q <= p; q++) for (rnd = 0; rnd < GMP_RND_MAX; rnd++) { mpfr_set_prec (y, q); mpfr_set_prec (z, q + 10); mpfr_set_prec (t, q); inexact = mpfr_pow_ui (y, x, u, (mp_rnd_t) rnd); cmp = mpfr_pow_ui (z, x, u, (mp_rnd_t) rnd); if (mpfr_can_round (z, q + 10, (mp_rnd_t) rnd, (mp_rnd_t) rnd, q)) { cmp = mpfr_set (t, z, (mp_rnd_t) rnd) || cmp; if (mpfr_cmp (y, t)) { printf ("results differ for u=%lu rnd=%s\n", u, mpfr_print_rnd_mode ((mp_rnd_t) rnd)); printf ("x="); mpfr_print_binary (x); puts (""); printf ("y="); mpfr_print_binary (y); puts (""); printf ("t="); mpfr_print_binary (t); puts (""); printf ("z="); mpfr_print_binary (z); puts (""); exit (1); } if (((inexact == 0) && (cmp != 0)) || ((inexact != 0) && (cmp == 0))) { printf ("Wrong inexact flag for p=%u, q=%u, rnd=%s\n", (unsigned int) p, (unsigned int) q, mpfr_print_rnd_mode ((mp_rnd_t) rnd)); printf ("expected %d, got %d\n", cmp, inexact); printf ("u=%lu x=", u); mpfr_print_binary (x); puts (""); printf ("y="); mpfr_print_binary (y); puts (""); exit (1); } } } /* check exact power */ mpfr_set_prec (x, p); mpfr_set_prec (y, p); mpfr_set_prec (z, p); mpfr_set_ui (x, 4, GMP_RNDN); mpfr_set_str (y, "0.5", 10, GMP_RNDN); test_pow (z, x, y, GMP_RNDZ); mpfr_clear (x); mpfr_clear (y); mpfr_clear (z); mpfr_clear (t); } static void special () { mpfr_t x, y, z, t; mpfr_init2 (x, 53); mpfr_init2 (y, 53); mpfr_init2 (z, 53); mpfr_init2 (t, 2); mpfr_set_ui (x, 2, GMP_RNDN); mpfr_pow_si (x, x, -2, GMP_RNDN); if (mpfr_cmp_ui_2exp (x, 1, -2)) { printf ("Error in pow_si(x,x,-2) for x=2\n"); exit (1); } mpfr_set_ui (x, 2, GMP_RNDN); mpfr_set_si (y, -2, GMP_RNDN); test_pow (x, x, y, GMP_RNDN); if (mpfr_cmp_ui_2exp (x, 1, -2)) { printf ("Error in pow(x,x,y) for x=2, y=-2\n"); exit (1); } mpfr_set_prec (x, 2); mpfr_set_str_binary (x, "1.0e-1"); mpfr_set_prec (y, 53); mpfr_set_str_binary (y, "0.11010110011100101010110011001010100111000001000101110E-1"); mpfr_set_prec (z, 2); test_pow (z, x, y, GMP_RNDZ); mpfr_set_str_binary (x, "1.0e-1"); if (mpfr_cmp (x, z)) { printf ("Error in mpfr_pow (1)\n"); exit (1); } mpfr_set_prec (x, 64); mpfr_set_prec (y, 64); mpfr_set_prec (z, 64); mpfr_set_prec (t, 64); mpfr_set_str_binary (x, "0.111011000111100000111010000101010100110011010000011"); mpfr_set_str_binary (y, "0.111110010100110000011101100011010111000010000100101"); mpfr_set_str_binary (t, "0.1110110011110110001000110100100001001111010011111000010000011001"); test_pow (z, x, y, GMP_RNDN); if (mpfr_cmp (z, t)) { printf ("Error in mpfr_pow for prec=64, rnd=GMP_RNDN\n"); exit (1); } mpfr_set_prec (x, 53); mpfr_set_prec (y, 53); mpfr_set_prec (z, 53); mpfr_set_str (x, "5.68824667828621954868e-01", 10, GMP_RNDN); mpfr_set_str (y, "9.03327850535952658895e-01", 10, GMP_RNDN); test_pow (z, x, y, GMP_RNDZ); if (mpfr_cmp_str1 (z, "0.60071044650456473235")) { printf ("Error in mpfr_pow for prec=53, rnd=GMP_RNDZ\n"); exit (1); } mpfr_set_prec (t, 2); mpfr_set_prec (x, 30); mpfr_set_prec (y, 30); mpfr_set_prec (z, 30); mpfr_set_str (x, "1.00000000001010111110001111011e1", 2, GMP_RNDN); mpfr_set_str (t, "-0.5", 10, GMP_RNDN); test_pow (z, x, t, GMP_RNDN); mpfr_set_str (y, "1.01101001111010101110000101111e-1", 2, GMP_RNDN); if (mpfr_cmp (z, y)) { printf ("Error in mpfr_pow for prec=30, rnd=GMP_RNDN\n"); exit (1); } mpfr_set_prec (x, 21); mpfr_set_prec (y, 21); mpfr_set_prec (z, 21); mpfr_set_str (x, "1.11111100100001100101", 2, GMP_RNDN); test_pow (z, x, t, GMP_RNDZ); mpfr_set_str (y, "1.01101011010001100000e-1", 2, GMP_RNDN); if (mpfr_cmp (z, y)) { printf ("Error in mpfr_pow for prec=21, rnd=GMP_RNDZ\n"); printf ("Expected "); mpfr_out_str (stdout, 2, 0, y, GMP_RNDN); printf ("\nGot "); mpfr_out_str (stdout, 2, 0, z, GMP_RNDN); printf ("\n"); exit (1); } /* From http://www.terra.es/personal9/ismaeljc/hall.htm */ mpfr_set_prec (x, 113); mpfr_set_prec (y, 2); mpfr_set_prec (z, 169); mpfr_set_str1 (x, "6078673043126084065007902175846955"); mpfr_set_ui_2exp (y, 3, -1, GMP_RNDN); test_pow (z, x, y, GMP_RNDZ); if (mpfr_cmp_str1 (z, "473928882491000966028828671876527456070714790264144")) { printf ("Error in mpfr_pow for 6078673043126084065007902175846955"); printf ("^(3/2), GMP_RNDZ\nExpected "); printf ("4.73928882491000966028828671876527456070714790264144e50"); printf ("\nGot "); mpfr_out_str (stdout, 10, 0, z, GMP_RNDN); printf ("\n"); exit (1); } test_pow (z, x, y, GMP_RNDU); if (mpfr_cmp_str1 (z, "473928882491000966028828671876527456070714790264145")) { printf ("Error in mpfr_pow for 6078673043126084065007902175846955"); printf ("^(3/2), GMP_RNDU\nExpected "); printf ("4.73928882491000966028828671876527456070714790264145e50"); printf ("\nGot "); mpfr_out_str (stdout, 10, 0, z, GMP_RNDN); printf ("\n"); exit (1); } mpfr_set_inf (x, 1); mpfr_set_prec (y, 2); mpfr_set_str_binary (y, "1E10"); test_pow (z, x, y, GMP_RNDN); MPFR_ASSERTN(mpfr_inf_p (z) && MPFR_IS_POS(z)); mpfr_set_inf (x, -1); test_pow (z, x, y, GMP_RNDN); MPFR_ASSERTN(mpfr_inf_p (z) && MPFR_IS_POS(z)); mpfr_set_prec (y, 10); mpfr_set_str_binary (y, "1.000000001E9"); test_pow (z, x, y, GMP_RNDN); MPFR_ASSERTN(mpfr_inf_p (z) && MPFR_IS_NEG(z)); mpfr_set_str_binary (y, "1.000000001E8"); test_pow (z, x, y, GMP_RNDN); MPFR_ASSERTN(mpfr_inf_p (z) && MPFR_IS_POS(z)); mpfr_set_inf (x, -1); mpfr_set_prec (y, 2 * mp_bits_per_limb); mpfr_set_ui (y, 1, GMP_RNDN); mpfr_mul_2exp (y, y, mp_bits_per_limb - 1, GMP_RNDN); /* y = 2^(mp_bits_per_limb - 1) */ test_pow (z, x, y, GMP_RNDN); MPFR_ASSERTN(mpfr_inf_p (z) && MPFR_IS_POS(z)); mpfr_nextabove (y); test_pow (z, x, y, GMP_RNDN); /* y = 2^(mp_bits_per_limb - 1) + epsilon */ MPFR_ASSERTN(mpfr_inf_p (z) && MPFR_IS_POS(z)); mpfr_nextbelow (y); mpfr_div_2exp (y, y, 1, GMP_RNDN); mpfr_nextabove (y); test_pow (z, x, y, GMP_RNDN); /* y = 2^(mp_bits_per_limb - 2) + epsilon */ MPFR_ASSERTN(mpfr_inf_p (z) && MPFR_IS_POS(z)); mpfr_set_si (x, -1, GMP_RNDN); mpfr_set_prec (y, 2); mpfr_set_str_binary (y, "1E10"); test_pow (z, x, y, GMP_RNDN); MPFR_ASSERTN(mpfr_cmp_ui (z, 1) == 0); /* Check (-0)^(17.0001) */ mpfr_set_prec (x, 6); mpfr_set_prec (y, 640); MPFR_SET_ZERO (x); MPFR_SET_NEG (x); mpfr_set_ui (y, 17, GMP_RNDN); mpfr_nextabove (y); test_pow (z, x, y, GMP_RNDN); MPFR_ASSERTN (MPFR_IS_ZERO (z) && MPFR_IS_POS (z)); mpfr_clear (x); mpfr_clear (y); mpfr_clear (z); mpfr_clear (t); } static void particular_cases (void) { mpfr_t t[11], r; static const char *name[11] = { "NaN", "+inf", "-inf", "+0", "-0", "+1", "-1", "+2", "-2", "+0.5", "-0.5"}; int i, j; int error = 0; for (i = 0; i < 11; i++) mpfr_init2 (t[i], 2); mpfr_init2 (r, 6); mpfr_set_nan (t[0]); mpfr_set_inf (t[1], 1); mpfr_set_ui (t[3], 0, GMP_RNDN); mpfr_set_ui (t[5], 1, GMP_RNDN); mpfr_set_ui (t[7], 2, GMP_RNDN); mpfr_div_2ui (t[9], t[5], 1, GMP_RNDN); for (i = 1; i < 11; i += 2) mpfr_neg (t[i+1], t[i], GMP_RNDN); for (i = 0; i < 11; i++) for (j = 0; j < 11; j++) { double d; int p; static int q[11][11] = { /* NaN +inf -inf +0 -0 +1 -1 +2 -2 +0.5 -0.5 */ /* NaN */ { 0, 0, 0, 128, 128, 0, 0, 0, 0, 0, 0 }, /* +inf */ { 0, 1, 2, 128, 128, 1, 2, 1, 2, 1, 2 }, /* -inf */ { 0, 1, 2, 128, 128, -1, -2, 1, 2, 1, 2 }, /* +0 */ { 0, 2, 1, 128, 128, 2, 1, 2, 1, 2, 1 }, /* -0 */ { 0, 2, 1, 128, 128, -2, -1, 2, 1, 2, 1 }, /* +1 */ {128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }, /* -1 */ { 0, 128, 128, 128, 128,-128,-128, 128, 128, 0, 0 }, /* +2 */ { 0, 1, 2, 128, 128, 256, 64, 512, 32, 180, 90 }, /* -2 */ { 0, 1, 2, 128, 128,-256, -64, 512, 32, 0, 0 }, /* +0.5 */ { 0, 2, 1, 128, 128, 64, 256, 32, 512, 90, 180 }, /* -0.5 */ { 0, 2, 1, 128, 128, -64,-256, 32, 512, 0, 0 } }; test_pow (r, t[i], t[j], GMP_RNDN); p = mpfr_nan_p (r) ? 0 : mpfr_inf_p (r) ? 1 : mpfr_cmp_ui (r, 0) == 0 ? 2 : (d = mpfr_get_d (r, GMP_RNDN), (int) (ABS(d) * 128.0)); if (p != 0 && MPFR_SIGN(r) < 0) p = -p; if (p != q[i][j]) { printf ("Error in mpfr_pow for particular case (%s)^(%s) (%d,%d):\n" "got %d instead of %d\n", name[i], name[j], i,j,p, q[i][j]); mpfr_dump (r); error = 1; } } for (i = 0; i < 11; i++) mpfr_clear (t[i]); mpfr_clear (r); if (error) exit (1); } static void underflows (void) { mpfr_t x, y, z; int err = 0; int inexact; int i; mp_exp_t emin; mpfr_init2 (x, 64); mpfr_init2 (y, 64); mpfr_set_ui (x, 1, GMP_RNDN); mpfr_set_exp (x, mpfr_get_emin()); for (i = 3; i < 10; i++) { mpfr_set_ui (y, i, GMP_RNDN); mpfr_div_2ui (y, y, 1, GMP_RNDN); test_pow (y, x, y, GMP_RNDN); if (!MPFR_IS_FP(y) || mpfr_cmp_ui (y, 0)) { printf ("Error in mpfr_pow for "); mpfr_out_str (stdout, 2, 0, x, GMP_RNDN); printf (" ^ (%d/2)\nGot ", i); mpfr_out_str (stdout, 2, 0, y, GMP_RNDN); printf (" instead of 0.\n"); exit (1); } } mpfr_init2 (z, 55); mpfr_set_str (x, "0.110011010011101001110001110100010000110111101E0", 2, GMP_RNDN); mpfr_set_str (y, "0.101110010011111001011010100011011100111110011E40", 2, GMP_RNDN); mpfr_clear_flags (); inexact = mpfr_pow (z, x, y, GMP_RNDU); if (!mpfr_underflow_p ()) { printf ("Underflow flag is not set for special underflow test.\n"); err = 1; } if (inexact <= 0) { printf ("Ternary value is wrong for special underflow test.\n"); err = 1; } mpfr_set_ui (x, 0, GMP_RNDN); mpfr_nextabove (x); if (mpfr_cmp (x, z) != 0) { printf ("Wrong value for special underflow test.\nGot "); mpfr_out_str (stdout, 2, 0, z, GMP_RNDN); printf ("\ninstead of "); mpfr_out_str (stdout, 2, 2, x, GMP_RNDN); printf ("\n"); err = 1; } if (err) exit (1); /* MPFR currently (2006-08-19) segfaults on the following code (and possibly makes other programs crash due to the lack of memory), because y is converted into an mpz_t, and the required precision is too high. */ mpfr_set_prec (x, 2); mpfr_set_prec (y, 2); mpfr_set_prec (z, 12); mpfr_set_ui_2exp (x, 3, -2, GMP_RNDN); mpfr_set_ui_2exp (y, 1, mpfr_get_emax () - 1, GMP_RNDN); mpfr_clear_flags (); mpfr_pow (z, x, y, GMP_RNDN); if (!mpfr_underflow_p () || MPFR_NOTZERO (z)) { printf ("Underflow test with large y fails.\n"); exit (1); } emin = mpfr_get_emin (); mpfr_set_emin (-256); mpfr_set_prec (x, 2); mpfr_set_prec (y, 2); mpfr_set_prec (z, 12); mpfr_set_ui_2exp (x, 3, -2, GMP_RNDN); mpfr_set_ui_2exp (y, 1, 38, GMP_RNDN); mpfr_clear_flags (); inexact = mpfr_pow (z, x, y, GMP_RNDN); if (!mpfr_underflow_p () || MPFR_NOTZERO (z) || inexact >= 0) { printf ("Bad underflow detection for 0.75^(2^38). Obtained:\n" "Underflow flag... %-3s (should be 'yes')\n" "Zero result...... %-3s (should be 'yes')\n" "Inexact value.... %-3d (should be negative)\n", mpfr_underflow_p () ? "yes" : "no", MPFR_IS_ZERO (z) ? "yes" : "no", inexact); exit (1); } mpfr_set_emin (emin); emin = mpfr_get_emin (); mpfr_set_emin (-256); mpfr_set_prec (x, 2); mpfr_set_prec (y, 40); mpfr_set_prec (z, 12); mpfr_set_ui_2exp (x, 3, -1, GMP_RNDN); mpfr_set_si_2exp (y, -1, 38, GMP_RNDN); for (i = 0; i < 4; i++) { if (i == 2) mpfr_neg (x, x, GMP_RNDN); mpfr_clear_flags (); inexact = mpfr_pow (z, x, y, GMP_RNDN); if (!mpfr_underflow_p () || MPFR_NOTZERO (z) || (i == 3 ? (inexact <= 0) : (inexact >= 0))) { printf ("Bad underflow detection for ("); mpfr_out_str (stdout, 10, 0, x, GMP_RNDN); printf (")^(-2^38-%d). Obtained:\n" "Overflow flag.... %-3s (should be 'no')\n" "Underflow flag... %-3s (should be 'yes')\n" "Zero result...... %-3s (should be 'yes')\n" "Inexact value.... %-3d (should be %s)\n", i, mpfr_overflow_p () ? "yes" : "no", mpfr_underflow_p () ? "yes" : "no", MPFR_IS_ZERO (z) ? "yes" : "no", inexact, i == 3 ? "positive" : "negative"); exit (1); } inexact = mpfr_sub_ui (y, y, 1, GMP_RNDN); MPFR_ASSERTN (inexact == 0); } mpfr_set_emin (emin); mpfr_clears (x, y, z, (void *) 0); } static void overflows (void) { mpfr_t a, b; /* bug found by Ming J. Tsai , 4 Oct 2003 */ mpfr_init_set_str (a, "5.1e32", 10, GMP_RNDN); mpfr_init (b); test_pow (b, a, a, GMP_RNDN); if (!(mpfr_inf_p (b) && mpfr_sgn (b) > 0)) { printf ("Error for a^a for a=5.1e32\n"); printf ("Expected +Inf, got "); mpfr_out_str (stdout, 10, 0, b, GMP_RNDN); printf ("\n"); exit (1); } mpfr_clear(a); mpfr_clear(b); } static void x_near_one (void) { mpfr_t x, y, z; int inex; mpfr_init2 (x, 32); mpfr_init2 (y, 4); mpfr_init2 (z, 33); mpfr_set_ui (x, 1, GMP_RNDN); mpfr_nextbelow (x); mpfr_set_ui_2exp (y, 11, -2, GMP_RNDN); inex = mpfr_pow (z, x, y, GMP_RNDN); if (mpfr_cmp_str (z, "0.111111111111111111111111111111011E0", 2, GMP_RNDN) || inex <= 0) { printf ("Failure in x_near_one, got inex = %d and\nz = ", inex); mpfr_dump (z); } mpfr_clears (x, y, z, (void *) 0); } static int mpfr_pow275 (mpfr_t y, mpfr_t x, mp_rnd_t r) { mpfr_t z; int inex; mpfr_init2 (z, 4); mpfr_set_ui_2exp (z, 11, -2, GMP_RNDN); inex = mpfr_pow (y, x, z, GMP_RNDN); mpfr_clear (z); return inex; } int main (void) { mp_prec_t p; MPFR_TEST_USE_RANDS (); tests_start_mpfr (); special (); particular_cases (); check_pow_ui (); check_pow_si (); check_special_pow_si (); pow_si_long_min (); for (p = 2; p < 100; p++) check_inexact (p); underflows (); overflows (); x_near_one (); test_generic (2, 100, 100); test_generic_ui (2, 100, 100); test_generic_si (2, 100, 100); data_check ("data/pow275", mpfr_pow275, "mpfr_pow275"); tests_end_mpfr (); return 0; }