ff4ff35918
Red Bear OS is a full fork. All sources must be available from git clone with zero network access. Removed gitignore rules that excluded fetched source trees under recipes/*/source/, local/recipes/kde/*/source/, local/recipes/qt/*/source/, and vendor source trees. Build artifacts (target/, build/, source.tar, *.o, *.so) remain excluded. 127291 files added — kernel, relibc, base, bootloader, pkgar, all KDE/Qt frameworks, mesa, wayland, DRM drivers, and every other recipe source.
1958 lines
58 KiB
C
1958 lines
58 KiB
C
/* Test file for mpfr_pow, mpfr_pow_ui and mpfr_pow_si.
|
||
|
||
Copyright 2000-2025 Free Software Foundation, Inc.
|
||
Contributed by the Pascaline and Caramba projects, INRIA.
|
||
|
||
This file is part of the GNU MPFR Library.
|
||
|
||
The GNU 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 3 of the License, or (at your
|
||
option) any later version.
|
||
|
||
The GNU 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 GNU MPFR Library; see the file COPYING.LESSER.
|
||
If not, see <https://www.gnu.org/licenses/>. */
|
||
|
||
#define _MPFR_NO_DEPRECATED_ROOT
|
||
#define MPFR_NEED_INTMAX_H
|
||
#include "mpfr-test.h"
|
||
|
||
#ifdef CHECK_EXTERNAL
|
||
static int
|
||
test_pow (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode)
|
||
{
|
||
int res;
|
||
int ok = rnd_mode == MPFR_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
|
||
#define TEST_RANDOM_POS 16 /* the 2nd argument is negative with prob. 16/512 */
|
||
#define TGENERIC_NOWARNING 1
|
||
#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, RANDS)
|
||
#define INT_RAND_FUNCTION() \
|
||
(randlimb () % 16 == 0 ? randulong () : (unsigned long) (randlimb () % 32))
|
||
#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, RANDS)
|
||
#define INT_RAND_FUNCTION() \
|
||
(randlimb () % 16 == 0 ? randlong () : (long) (randlimb () % 31) - 15)
|
||
#define test_generic_ui test_generic_si
|
||
#include "tgeneric_ui.c"
|
||
|
||
#define DEFN(N) \
|
||
static int powu##N (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd) \
|
||
{ return mpfr_pow_ui (y, x, N, rnd); } \
|
||
static int pows##N (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd) \
|
||
{ return mpfr_pow_si (y, x, N, rnd); } \
|
||
static int powm##N (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd) \
|
||
{ return mpfr_pow_si (y, x, -(N), rnd); } \
|
||
static int root##N (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd) \
|
||
{ return RAND_BOOL () ? \
|
||
mpfr_root (y, x, N, rnd) : mpfr_rootn_ui (y, x, N, rnd); } \
|
||
static int rootm##N (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd) \
|
||
{ return mpfr_rootn_si (y, x, -(N), rnd); }
|
||
|
||
|
||
DEFN(2)
|
||
DEFN(3)
|
||
DEFN(4)
|
||
DEFN(5)
|
||
DEFN(17)
|
||
DEFN(120)
|
||
|
||
static void
|
||
check_pow_ui (void)
|
||
{
|
||
mpfr_t a, b;
|
||
unsigned long n;
|
||
int res;
|
||
|
||
mpfr_init2 (a, 53);
|
||
mpfr_init2 (b, 53);
|
||
|
||
/* check in-place operations */
|
||
mpfr_set_str (b, "0.6926773", 10, MPFR_RNDN);
|
||
mpfr_pow_ui (a, b, 10, MPFR_RNDN);
|
||
mpfr_pow_ui (b, b, 10, MPFR_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, MPFR_RNDN);
|
||
mpfr_pow_ui (a, b, 4294967295UL, MPFR_RNDN);
|
||
|
||
mpfr_set_inf (a, -1);
|
||
mpfr_pow_ui (a, a, 4049053855UL, MPFR_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, MPFR_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 (), MPFR_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 (), MPFR_RNDZ);
|
||
if (MPFR_NOTZERO (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, MPFR_RNDN);
|
||
if (!MPFR_IS_INF (a) || MPFR_IS_NEG (a))
|
||
{
|
||
printf ("Error for (1e10)^ULONG_MAX\n");
|
||
exit (1);
|
||
}
|
||
|
||
/* Bug in pow_ui.c from r3214 to r5107: if x = y (same mpfr_t argument),
|
||
the input argument is negative, n is odd, an overflow or underflow
|
||
occurs, and the temporary result res is positive, then the result
|
||
gets a wrong sign (positive instead of negative). */
|
||
mpfr_set_str_binary (a, "-1E10");
|
||
n = (ULONG_MAX ^ (ULONG_MAX >> 1)) + 1;
|
||
res = mpfr_pow_ui (a, a, n, MPFR_RNDN);
|
||
if (!MPFR_IS_INF (a) || MPFR_IS_POS (a))
|
||
{
|
||
printf ("Error for (-1e10)^%lu, expected -Inf,\ngot ", n);
|
||
mpfr_dump (a);
|
||
exit (1);
|
||
}
|
||
|
||
/* Check 0 */
|
||
MPFR_SET_ZERO (a);
|
||
MPFR_SET_POS (a);
|
||
mpfr_set_si (b, -1, MPFR_RNDN);
|
||
res = mpfr_pow_ui (b, a, 1, MPFR_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, MPFR_RNDN);
|
||
res = mpfr_pow_ui (b, a, 5, MPFR_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, MPFR_RNDN);
|
||
res = mpfr_pow_ui (b, a, 6, MPFR_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, MPFR_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, MPFR_RNDZ);
|
||
if (mpfr_cmp (a, b) != 0)
|
||
{
|
||
printf ("Error for x^2055225053\n");
|
||
printf ("Expected ");
|
||
mpfr_out_str (stdout, 2, 0, b, MPFR_RNDN);
|
||
printf ("\nGot ");
|
||
mpfr_out_str (stdout, 2, 0, a, MPFR_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, MPFR_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, MPFR_RNDN);
|
||
printf ("\nGot ");
|
||
mpfr_out_str (stdout, 2, 0, a, MPFR_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, MPFR_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, MPFR_RNDN);
|
||
printf ("\nGot ");
|
||
mpfr_out_str (stdout, 2, 0, a, MPFR_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, MPFR_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, MPFR_RNDN);
|
||
printf ("\nGot ");
|
||
mpfr_out_str (stdout, 2, 0, a, MPFR_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, MPFR_RNDN);
|
||
MPFR_ASSERTN(mpfr_nan_p (x));
|
||
|
||
mpfr_set_inf (x, 1);
|
||
mpfr_pow_si (x, x, -1, MPFR_RNDN);
|
||
MPFR_ASSERTN(MPFR_IS_ZERO (x) && MPFR_IS_POS (x));
|
||
|
||
mpfr_set_inf (x, -1);
|
||
mpfr_pow_si (x, x, -1, MPFR_RNDN);
|
||
MPFR_ASSERTN(MPFR_IS_ZERO (x) && MPFR_IS_NEG (x));
|
||
|
||
mpfr_set_inf (x, -1);
|
||
mpfr_pow_si (x, x, -2, MPFR_RNDN);
|
||
MPFR_ASSERTN(MPFR_IS_ZERO (x) && MPFR_IS_POS (x));
|
||
|
||
mpfr_set_ui (x, 0, MPFR_RNDN);
|
||
mpfr_pow_si (x, x, -1, MPFR_RNDN);
|
||
MPFR_ASSERTN(mpfr_inf_p (x) && mpfr_sgn (x) > 0);
|
||
|
||
mpfr_set_ui (x, 0, MPFR_RNDN);
|
||
mpfr_neg (x, x, MPFR_RNDN);
|
||
mpfr_pow_si (x, x, -1, MPFR_RNDN);
|
||
MPFR_ASSERTN(mpfr_inf_p (x) && mpfr_sgn (x) < 0);
|
||
|
||
mpfr_set_ui (x, 0, MPFR_RNDN);
|
||
mpfr_neg (x, x, MPFR_RNDN);
|
||
mpfr_pow_si (x, x, -2, MPFR_RNDN);
|
||
MPFR_ASSERTN(mpfr_inf_p (x) && mpfr_sgn (x) > 0);
|
||
|
||
mpfr_set_si (x, 2, MPFR_RNDN);
|
||
mpfr_pow_si (x, x, LONG_MAX, MPFR_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, (mpfr_exp_t) LONG_MAX));
|
||
}
|
||
|
||
mpfr_set_si (x, 2, MPFR_RNDN);
|
||
mpfr_pow_si (x, x, LONG_MIN, MPFR_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, (mpfr_exp_t) LONG_MIN));
|
||
}
|
||
|
||
mpfr_set_si (x, 2, MPFR_RNDN);
|
||
mpfr_pow_si (x, x, LONG_MIN + 1, MPFR_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, (mpfr_exp_t) (LONG_MIN + 1)));
|
||
}
|
||
|
||
mpfr_set_si_2exp (x, 1, -1, MPFR_RNDN); /* 0.5 */
|
||
mpfr_pow_si (x, x, LONG_MIN, MPFR_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, (mpfr_exp_t) - (LONG_MIN + 1)));
|
||
}
|
||
|
||
mpfr_clear (x);
|
||
}
|
||
|
||
/* check the IEEE 754-2019 special rules for pown */
|
||
static void
|
||
check_pown_ieee754_2019 (void)
|
||
{
|
||
#ifdef _MPFR_H_HAVE_INTMAX_T
|
||
mpfr_t x;
|
||
|
||
mpfr_init2 (x, 5); /* ensures 17 is exact */
|
||
|
||
/* pown (x, 0) is 1 if x is not a signaling NaN: in MPFR we decide to
|
||
return 1 for a NaN */
|
||
mpfr_set_nan (x);
|
||
mpfr_pown (x, x, 0, MPFR_RNDN);
|
||
MPFR_ASSERTN(mpfr_cmp_ui0 (x, 1) == 0);
|
||
mpfr_set_inf (x, 1);
|
||
mpfr_pown (x, x, 0, MPFR_RNDN);
|
||
MPFR_ASSERTN(mpfr_cmp_ui0 (x, 1) == 0);
|
||
mpfr_set_inf (x, -1);
|
||
mpfr_pown (x, x, 0, MPFR_RNDN);
|
||
MPFR_ASSERTN(mpfr_cmp_ui0 (x, 1) == 0);
|
||
mpfr_set_zero (x, 1);
|
||
mpfr_pown (x, x, 0, MPFR_RNDN);
|
||
MPFR_ASSERTN(mpfr_cmp_ui0 (x, 1) == 0);
|
||
mpfr_set_zero (x, -1);
|
||
mpfr_pown (x, x, 0, MPFR_RNDN);
|
||
MPFR_ASSERTN(mpfr_cmp_ui0 (x, 1) == 0);
|
||
mpfr_set_si (x, 17, MPFR_RNDN);
|
||
mpfr_pown (x, x, 0, MPFR_RNDN);
|
||
MPFR_ASSERTN(mpfr_cmp_ui0 (x, 1) == 0);
|
||
mpfr_set_si (x, -17, MPFR_RNDN);
|
||
mpfr_pown (x, x, 0, MPFR_RNDN);
|
||
MPFR_ASSERTN(mpfr_cmp_ui0 (x, 1) == 0);
|
||
|
||
/* pown (±0, n) is ±∞ and signals the divideByZero exception for odd n < 0 */
|
||
mpfr_set_zero (x, 1);
|
||
mpfr_clear_divby0 ();
|
||
mpfr_pown (x, x, -17, MPFR_RNDN);
|
||
MPFR_ASSERTN(mpfr_inf_p (x) && mpfr_sgn (x) > 0 && mpfr_divby0_p ());
|
||
mpfr_set_zero (x, -1);
|
||
mpfr_clear_divby0 ();
|
||
mpfr_pown (x, x, -17, MPFR_RNDN);
|
||
MPFR_ASSERTN(mpfr_inf_p (x) && mpfr_sgn (x) < 0 && mpfr_divby0_p ());
|
||
|
||
/* pown (±0, n) is +∞ and signals the divideByZero exception for even n < 0*/
|
||
mpfr_set_zero (x, 1);
|
||
mpfr_clear_divby0 ();
|
||
mpfr_pown (x, x, -42, MPFR_RNDN);
|
||
MPFR_ASSERTN(mpfr_inf_p (x) && mpfr_sgn (x) > 0 && mpfr_divby0_p ());
|
||
mpfr_set_zero (x, -1);
|
||
mpfr_clear_divby0 ();
|
||
mpfr_pown (x, x, -42, MPFR_RNDN);
|
||
MPFR_ASSERTN(mpfr_inf_p (x) && mpfr_sgn (x) > 0 && mpfr_divby0_p ());
|
||
|
||
/* pown (±0, n) is +0 for even n > 0 */
|
||
mpfr_set_zero (x, 1);
|
||
mpfr_pown (x, x, 42, MPFR_RNDN);
|
||
MPFR_ASSERTN(mpfr_zero_p (x) && mpfr_signbit (x) == 0);
|
||
mpfr_set_zero (x, -1);
|
||
mpfr_pown (x, x, 42, MPFR_RNDN);
|
||
MPFR_ASSERTN(mpfr_zero_p (x) && mpfr_signbit (x) == 0);
|
||
|
||
/* pown (±0, n) is ±0 for odd n > 0 */
|
||
mpfr_set_zero (x, 1);
|
||
mpfr_pown (x, x, 17, MPFR_RNDN);
|
||
MPFR_ASSERTN(mpfr_zero_p (x) && mpfr_signbit (x) == 0);
|
||
mpfr_set_zero (x, -1);
|
||
mpfr_pown (x, x, 17, MPFR_RNDN);
|
||
MPFR_ASSERTN(mpfr_zero_p (x) && mpfr_signbit (x) == 1);
|
||
|
||
/* pown (+∞, n) is +∞ for n > 0 */
|
||
mpfr_set_inf (x, 1);
|
||
mpfr_pown (x, x, 17, MPFR_RNDN);
|
||
MPFR_ASSERTN(mpfr_inf_p (x) && mpfr_sgn (x) > 0);
|
||
|
||
/* pown (−∞, n) is −∞ for odd n > 0 */
|
||
mpfr_set_inf (x, -1);
|
||
mpfr_pown (x, x, 17, MPFR_RNDN);
|
||
MPFR_ASSERTN(mpfr_inf_p (x) && mpfr_sgn (x) < 0);
|
||
|
||
/* pown (−∞, n) is +∞ for even n > 0 */
|
||
mpfr_set_inf (x, -1);
|
||
mpfr_pown (x, x, 42, MPFR_RNDN);
|
||
MPFR_ASSERTN(mpfr_inf_p (x) && mpfr_sgn (x) > 0);
|
||
|
||
/* pown (+∞, n) is +0 for n < 0 */
|
||
mpfr_set_inf (x, 1);
|
||
mpfr_pown (x, x, -17, MPFR_RNDN);
|
||
MPFR_ASSERTN(mpfr_zero_p (x) && mpfr_signbit (x) == 0);
|
||
mpfr_set_inf (x, 1);
|
||
mpfr_pown (x, x, -42, MPFR_RNDN);
|
||
MPFR_ASSERTN(mpfr_zero_p (x) && mpfr_signbit (x) == 0);
|
||
|
||
/* pown (−∞, n) is −0 for odd n < 0 */
|
||
mpfr_set_inf (x, -1);
|
||
mpfr_pown (x, x, -17, MPFR_RNDN);
|
||
MPFR_ASSERTN(mpfr_zero_p (x) && mpfr_signbit (x) != 0);
|
||
|
||
/* pown (−∞, n) is +0 for even n < 0 */
|
||
mpfr_set_inf (x, -1);
|
||
mpfr_pown (x, x, -42, MPFR_RNDN);
|
||
MPFR_ASSERTN(mpfr_zero_p (x) && mpfr_signbit (x) == 0);
|
||
|
||
mpfr_clear (x);
|
||
#endif
|
||
}
|
||
|
||
static void
|
||
check_special_pow_si (void)
|
||
{
|
||
mpfr_t a, b;
|
||
mpfr_exp_t emin;
|
||
|
||
mpfr_init (a);
|
||
mpfr_init (b);
|
||
mpfr_set_str (a, "2E100000000", 10, MPFR_RNDN);
|
||
mpfr_set_si (b, -10, MPFR_RNDN);
|
||
test_pow (b, a, b, MPFR_RNDN);
|
||
if (MPFR_NOTZERO(b))
|
||
{
|
||
printf("Pow(2E10000000, -10) failed\n");
|
||
mpfr_dump (a);
|
||
mpfr_dump (b);
|
||
exit(1);
|
||
}
|
||
|
||
emin = mpfr_get_emin ();
|
||
set_emin (-10);
|
||
mpfr_set_si (a, -2, MPFR_RNDN);
|
||
mpfr_pow_si (b, a, -10000, MPFR_RNDN);
|
||
if (MPFR_NOTZERO (b))
|
||
{
|
||
printf ("Pow_so (1, -10000) doesn't underflow if emin=-10.\n");
|
||
mpfr_dump (a);
|
||
mpfr_dump (b);
|
||
exit (1);
|
||
}
|
||
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, (mpfr_ptr) 0);
|
||
mpfr_set_si_2exp (x, 3, -1, MPFR_RNDN); /* 1.5 */
|
||
|
||
inex = mpfr_set_si (y, LONG_MIN, MPFR_RNDN);
|
||
MPFR_ASSERTN (inex == 0);
|
||
mpfr_nextbelow (y);
|
||
mpfr_pow (y, x, y, MPFR_RNDD);
|
||
|
||
inex = mpfr_set_si (z, LONG_MIN, MPFR_RNDN);
|
||
MPFR_ASSERTN (inex == 0);
|
||
mpfr_nextabove (z);
|
||
mpfr_pow (z, x, z, MPFR_RNDU);
|
||
|
||
mpfr_pow_si (x, x, LONG_MIN, MPFR_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, (mpfr_ptr) 0);
|
||
}
|
||
|
||
static void
|
||
check_inexact (mpfr_prec_t p)
|
||
{
|
||
mpfr_t x, y, z, t;
|
||
unsigned long u;
|
||
mpfr_prec_t q;
|
||
int inexact, cmp;
|
||
int rnd;
|
||
|
||
mpfr_init2 (x, p);
|
||
mpfr_init (y);
|
||
mpfr_init (z);
|
||
mpfr_init (t);
|
||
mpfr_urandomb (x, RANDS);
|
||
u = RAND_BOOL ();
|
||
for (q = MPFR_PREC_MIN; q <= p; q++)
|
||
RND_LOOP_NO_RNDF(rnd)
|
||
{
|
||
mpfr_set_prec (y, q);
|
||
mpfr_set_prec (z, q + 10);
|
||
mpfr_set_prec (t, q);
|
||
inexact = mpfr_pow_ui (y, x, u, (mpfr_rnd_t) rnd);
|
||
cmp = mpfr_pow_ui (z, x, u, (mpfr_rnd_t) rnd);
|
||
/* Note: that test makes no sense for RNDF, since according to the
|
||
reference manual, if the mpfr_can_round() call succeeds, one would
|
||
have to use RNDN in the mpfr_set() call below, which might give a
|
||
different value for t that the value y obtained above. */
|
||
if (mpfr_can_round (z, q + 10, (mpfr_rnd_t) rnd, (mpfr_rnd_t) rnd, q))
|
||
{
|
||
cmp = mpfr_set (t, z, (mpfr_rnd_t) rnd) || cmp;
|
||
if (mpfr_cmp (y, t))
|
||
{
|
||
printf ("results differ for u=%lu rnd=%s\n",
|
||
u, mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
|
||
printf ("x="); mpfr_dump (x);
|
||
printf ("y="); mpfr_dump (y);
|
||
printf ("t="); mpfr_dump (t);
|
||
printf ("z="); mpfr_dump (z);
|
||
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 ((mpfr_rnd_t) rnd));
|
||
printf ("expected %d, got %d\n", cmp, inexact);
|
||
printf ("u=%lu x=", u); mpfr_dump (x);
|
||
printf ("y="); mpfr_dump (y);
|
||
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, MPFR_RNDN);
|
||
mpfr_set_str (y, "0.5", 10, MPFR_RNDN);
|
||
test_pow (z, x, y, MPFR_RNDZ);
|
||
|
||
mpfr_clear (x);
|
||
mpfr_clear (y);
|
||
mpfr_clear (z);
|
||
mpfr_clear (t);
|
||
}
|
||
|
||
static void
|
||
special (void)
|
||
{
|
||
mpfr_t x, y, z, t;
|
||
mpfr_exp_t emin, emax;
|
||
int inex;
|
||
|
||
mpfr_init2 (x, 53);
|
||
mpfr_init2 (y, 53);
|
||
mpfr_init2 (z, 53);
|
||
mpfr_init2 (t, 2);
|
||
|
||
mpfr_set_ui (x, 2, MPFR_RNDN);
|
||
mpfr_pow_si (x, x, -2, MPFR_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, MPFR_RNDN);
|
||
mpfr_set_si (y, -2, MPFR_RNDN);
|
||
test_pow (x, x, y, MPFR_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, MPFR_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, MPFR_RNDN);
|
||
if (mpfr_cmp (z, t))
|
||
{
|
||
printf ("Error in mpfr_pow for prec=64, rnd=MPFR_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, MPFR_RNDN);
|
||
mpfr_set_str (y, "9.03327850535952658895e-01", 10, MPFR_RNDN);
|
||
test_pow (z, x, y, MPFR_RNDZ);
|
||
if (mpfr_cmp_str1 (z, "0.60071044650456473235"))
|
||
{
|
||
printf ("Error in mpfr_pow for prec=53, rnd=MPFR_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, MPFR_RNDN);
|
||
mpfr_set_str (t, "-0.5", 10, MPFR_RNDN);
|
||
test_pow (z, x, t, MPFR_RNDN);
|
||
mpfr_set_str (y, "1.01101001111010101110000101111e-1", 2, MPFR_RNDN);
|
||
if (mpfr_cmp (z, y))
|
||
{
|
||
printf ("Error in mpfr_pow for prec=30, rnd=MPFR_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, MPFR_RNDN);
|
||
test_pow (z, x, t, MPFR_RNDZ);
|
||
mpfr_set_str (y, "1.01101011010001100000e-1", 2, MPFR_RNDN);
|
||
if (mpfr_cmp (z, y))
|
||
{
|
||
printf ("Error in mpfr_pow for prec=21, rnd=MPFR_RNDZ\n");
|
||
printf ("Expected ");
|
||
mpfr_out_str (stdout, 2, 0, y, MPFR_RNDN);
|
||
printf ("\nGot ");
|
||
mpfr_out_str (stdout, 2, 0, z, MPFR_RNDN);
|
||
printf ("\n");
|
||
exit (1);
|
||
}
|
||
|
||
/* From https://web.archive.org/web/20050824044408/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, MPFR_RNDN);
|
||
test_pow (z, x, y, MPFR_RNDZ);
|
||
if (mpfr_cmp_str1 (z, "473928882491000966028828671876527456070714790264144"))
|
||
{
|
||
printf ("Error in mpfr_pow for 6078673043126084065007902175846955");
|
||
printf ("^(3/2), MPFR_RNDZ\nExpected ");
|
||
printf ("4.73928882491000966028828671876527456070714790264144e50");
|
||
printf ("\nGot ");
|
||
mpfr_out_str (stdout, 10, 0, z, MPFR_RNDN);
|
||
printf ("\n");
|
||
exit (1);
|
||
}
|
||
test_pow (z, x, y, MPFR_RNDU);
|
||
if (mpfr_cmp_str1 (z, "473928882491000966028828671876527456070714790264145"))
|
||
{
|
||
printf ("Error in mpfr_pow for 6078673043126084065007902175846955");
|
||
printf ("^(3/2), MPFR_RNDU\nExpected ");
|
||
printf ("4.73928882491000966028828671876527456070714790264145e50");
|
||
printf ("\nGot ");
|
||
mpfr_out_str (stdout, 10, 0, z, MPFR_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, MPFR_RNDN);
|
||
MPFR_ASSERTN(mpfr_inf_p (z) && MPFR_IS_POS(z));
|
||
mpfr_set_inf (x, -1);
|
||
test_pow (z, x, y, MPFR_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, MPFR_RNDN);
|
||
MPFR_ASSERTN(mpfr_inf_p (z) && MPFR_IS_NEG(z));
|
||
mpfr_set_str_binary (y, "1.000000001E8");
|
||
test_pow (z, x, y, MPFR_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, MPFR_RNDN);
|
||
mpfr_mul_2ui (y, y, mp_bits_per_limb - 1, MPFR_RNDN);
|
||
/* y = 2^(mp_bits_per_limb - 1) */
|
||
test_pow (z, x, y, MPFR_RNDN);
|
||
MPFR_ASSERTN(mpfr_inf_p (z) && MPFR_IS_POS(z));
|
||
mpfr_nextabove (y);
|
||
test_pow (z, x, y, MPFR_RNDN);
|
||
/* y = 2^(mp_bits_per_limb - 1) + epsilon */
|
||
MPFR_ASSERTN(mpfr_inf_p (z) && MPFR_IS_POS(z));
|
||
mpfr_nextbelow (y);
|
||
mpfr_div_2ui (y, y, 1, MPFR_RNDN);
|
||
mpfr_nextabove (y);
|
||
test_pow (z, x, y, MPFR_RNDN);
|
||
/* y = 2^(mp_bits_per_limb - 2) + epsilon */
|
||
MPFR_ASSERTN(mpfr_inf_p (z) && MPFR_IS_POS(z));
|
||
|
||
mpfr_set_si (x, -1, MPFR_RNDN);
|
||
mpfr_set_prec (y, 2);
|
||
mpfr_set_str_binary (y, "1E10");
|
||
test_pow (z, x, y, MPFR_RNDN);
|
||
MPFR_ASSERTN(mpfr_cmp_ui0 (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, MPFR_RNDN); mpfr_nextabove (y);
|
||
test_pow (z, x, y, MPFR_RNDN);
|
||
MPFR_ASSERTN (MPFR_IS_ZERO (z) && MPFR_IS_POS (z));
|
||
|
||
/* Bugs reported by Kevin Rauch on 29 Oct 2007 */
|
||
emin = mpfr_get_emin ();
|
||
emax = mpfr_get_emax ();
|
||
set_emin (-1000000);
|
||
set_emax ( 1000000);
|
||
mpfr_set_prec (x, 64);
|
||
mpfr_set_prec (y, 64);
|
||
mpfr_set_prec (z, 64);
|
||
mpfr_set_str (x, "-0.5", 10, MPFR_RNDN);
|
||
mpfr_set_str (y, "-0.ffffffffffffffff", 16, MPFR_RNDN);
|
||
mpfr_set_exp (y, mpfr_get_emax ());
|
||
inex = mpfr_pow (z, x, y, MPFR_RNDN);
|
||
/* (-0.5)^(-n) = 1/2^n for n even */
|
||
MPFR_ASSERTN(mpfr_inf_p (z) && MPFR_IS_POS (z) && inex > 0);
|
||
|
||
/* (-1)^(-n) = 1 for n even */
|
||
mpfr_set_str (x, "-1", 10, MPFR_RNDN);
|
||
inex = mpfr_pow (z, x, y, MPFR_RNDN);
|
||
MPFR_ASSERTN(mpfr_cmp_ui0 (z, 1) == 0 && inex == 0);
|
||
|
||
/* (-1)^n = 1 for n even */
|
||
mpfr_set_str (x, "-1", 10, MPFR_RNDN);
|
||
mpfr_neg (y, y, MPFR_RNDN);
|
||
inex = mpfr_pow (z, x, y, MPFR_RNDN);
|
||
MPFR_ASSERTN(mpfr_cmp_ui0 (z, 1) == 0 && inex == 0);
|
||
|
||
/* (-1.5)^n = +Inf for n even */
|
||
mpfr_set_str (x, "-1.5", 10, MPFR_RNDN);
|
||
inex = mpfr_pow (z, x, y, MPFR_RNDN);
|
||
MPFR_ASSERTN(mpfr_inf_p (z) && MPFR_IS_POS (z) && inex > 0);
|
||
|
||
/* (-n)^1.5 = NaN for n even */
|
||
mpfr_neg (y, y, MPFR_RNDN);
|
||
mpfr_set_str (x, "1.5", 10, MPFR_RNDN);
|
||
inex = mpfr_pow (z, y, x, MPFR_RNDN);
|
||
MPFR_ASSERTN(mpfr_nan_p (z));
|
||
|
||
/* x^(-1.5) = NaN for x small < 0 */
|
||
mpfr_set_str (x, "-0.8", 16, MPFR_RNDN);
|
||
mpfr_set_exp (x, mpfr_get_emin ());
|
||
mpfr_set_str (y, "-1.5", 10, MPFR_RNDN);
|
||
inex = mpfr_pow (z, x, y, MPFR_RNDN);
|
||
MPFR_ASSERTN(mpfr_nan_p (z));
|
||
|
||
set_emin (emin);
|
||
set_emax (emax);
|
||
mpfr_clear (x);
|
||
mpfr_clear (y);
|
||
mpfr_clear (z);
|
||
mpfr_clear (t);
|
||
}
|
||
|
||
static void
|
||
particular_cases (void)
|
||
{
|
||
mpfr_t t[11], r, r2;
|
||
mpz_t z;
|
||
long si;
|
||
|
||
static const char *name[11] = {
|
||
"NaN", "+inf", "-inf", "+0", "-0", "+1", "-1", "+2", "-2", "+0.5", "-0.5"};
|
||
int i, j;
|
||
int error = 0;
|
||
|
||
mpz_init (z);
|
||
|
||
for (i = 0; i < 11; i++)
|
||
mpfr_init2 (t[i], 2);
|
||
mpfr_init2 (r, 6);
|
||
mpfr_init2 (r2, 6);
|
||
|
||
mpfr_set_nan (t[0]);
|
||
mpfr_set_inf (t[1], 1);
|
||
mpfr_set_ui (t[3], 0, MPFR_RNDN);
|
||
mpfr_set_ui (t[5], 1, MPFR_RNDN);
|
||
mpfr_set_ui (t[7], 2, MPFR_RNDN);
|
||
mpfr_div_2ui (t[9], t[5], 1, MPFR_RNDN);
|
||
for (i = 1; i < 11; i += 2)
|
||
mpfr_neg (t[i+1], t[i], MPFR_RNDN);
|
||
|
||
for (i = 0; i < 11; i++)
|
||
for (j = 0; j < 11; j++)
|
||
{
|
||
double d;
|
||
int p;
|
||
static const 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 }
|
||
};
|
||
/* This define is used to make the following table readable */
|
||
#define N MPFR_FLAGS_NAN
|
||
#define I MPFR_FLAGS_INEXACT
|
||
#define D MPFR_FLAGS_DIVBY0
|
||
static const unsigned int f[11][11] = {
|
||
/* NaN +inf -inf +0 -0 +1 -1 +2 -2 +0.5 -0.5 */
|
||
/* NaN */ { N, N, N, 0, 0, N, N, N, N, N, N },
|
||
/* +inf */ { N, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||
/* -inf */ { N, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||
/* +0 */ { N, 0, 0, 0, 0, 0, D, 0, D, 0, D },
|
||
/* -0 */ { N, 0, 0, 0, 0, 0, D, 0, D, 0, D },
|
||
/* +1 */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||
/* -1 */ { N, 0, 0, 0, 0, 0, 0, 0, 0, N, N },
|
||
/* +2 */ { N, 0, 0, 0, 0, 0, 0, 0, 0, I, I },
|
||
/* -2 */ { N, 0, 0, 0, 0, 0, 0, 0, 0, N, N },
|
||
/* +0.5 */ { N, 0, 0, 0, 0, 0, 0, 0, 0, I, I },
|
||
/* -0.5 */ { N, 0, 0, 0, 0, 0, 0, 0, 0, N, N }
|
||
};
|
||
#undef N
|
||
#undef I
|
||
#undef D
|
||
mpfr_clear_flags ();
|
||
test_pow (r, t[i], t[j], MPFR_RNDN);
|
||
p = mpfr_nan_p (r) ? 0 : mpfr_inf_p (r) ? 1 :
|
||
mpfr_zero_p (r) ? 2 :
|
||
(d = mpfr_get_d (r, MPFR_RNDN), (int) (ABS(d) * 128.0));
|
||
if (p != 0 && MPFR_IS_NEG (r))
|
||
p = -p;
|
||
if (p != q[i][j])
|
||
{
|
||
printf ("Error in mpfr_pow for (%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;
|
||
}
|
||
if (__gmpfr_flags != f[i][j])
|
||
{
|
||
printf ("Error in mpfr_pow for (%s)^(%s) (%d,%d):\n"
|
||
"Flags = %u instead of expected %u\n",
|
||
name[i], name[j], i, j,
|
||
(unsigned int) __gmpfr_flags, f[i][j]);
|
||
mpfr_dump (r);
|
||
error = 1;
|
||
}
|
||
/* Perform the same tests with pow_z & pow_si & pow_ui
|
||
if t[j] is an integer */
|
||
if (mpfr_integer_p (t[j]))
|
||
{
|
||
/* mpfr_pow_z */
|
||
mpfr_clear_flags ();
|
||
mpfr_get_z (z, t[j], MPFR_RNDN);
|
||
mpfr_pow_z (r, t[i], z, MPFR_RNDN);
|
||
p = mpfr_nan_p (r) ? 0 : mpfr_inf_p (r) ? 1 :
|
||
mpfr_zero_p (r) ? 2 :
|
||
(d = mpfr_get_d (r, MPFR_RNDN), (int) (ABS(d) * 128.0));
|
||
if (p != 0 && MPFR_IS_NEG (r))
|
||
p = -p;
|
||
if (p != q[i][j])
|
||
{
|
||
printf ("Error in mpfr_pow_z for (%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;
|
||
}
|
||
if (__gmpfr_flags != f[i][j])
|
||
{
|
||
printf ("Error in mpfr_pow_z for (%s)^(%s) (%d,%d):\n"
|
||
"Flags = %u instead of expected %u\n",
|
||
name[i], name[j], i, j,
|
||
(unsigned int) __gmpfr_flags, f[i][j]);
|
||
mpfr_dump (r);
|
||
error = 1;
|
||
}
|
||
/* mpfr_pow_si */
|
||
mpfr_clear_flags ();
|
||
si = mpfr_get_si (t[j], MPFR_RNDN);
|
||
mpfr_pow_si (r, t[i], si, MPFR_RNDN);
|
||
p = mpfr_nan_p (r) ? 0 : mpfr_inf_p (r) ? 1 :
|
||
mpfr_zero_p (r) ? 2 :
|
||
(d = mpfr_get_d (r, MPFR_RNDN), (int) (ABS(d) * 128.0));
|
||
if (p != 0 && MPFR_IS_NEG (r))
|
||
p = -p;
|
||
if (p != q[i][j])
|
||
{
|
||
printf ("Error in mpfr_pow_si for (%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;
|
||
}
|
||
if (__gmpfr_flags != f[i][j])
|
||
{
|
||
printf ("Error in mpfr_pow_si for (%s)^(%s) (%d,%d):\n"
|
||
"Flags = %u instead of expected %u\n",
|
||
name[i], name[j], i, j,
|
||
(unsigned int) __gmpfr_flags, f[i][j]);
|
||
mpfr_dump (r);
|
||
error = 1;
|
||
}
|
||
/* if si >= 0, test mpfr_pow_ui */
|
||
if (si >= 0)
|
||
{
|
||
mpfr_clear_flags ();
|
||
mpfr_pow_ui (r, t[i], si, MPFR_RNDN);
|
||
p = mpfr_nan_p (r) ? 0 : mpfr_inf_p (r) ? 1 :
|
||
mpfr_zero_p (r) ? 2 :
|
||
(d = mpfr_get_d (r, MPFR_RNDN), (int) (ABS(d) * 128.0));
|
||
if (p != 0 && MPFR_IS_NEG (r))
|
||
p = -p;
|
||
if (p != q[i][j])
|
||
{
|
||
printf ("Error in mpfr_pow_ui for (%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;
|
||
}
|
||
if (__gmpfr_flags != f[i][j])
|
||
{
|
||
printf ("Error in mpfr_pow_ui for (%s)^(%s) (%d,%d):\n"
|
||
"Flags = %u instead of expected %u\n",
|
||
name[i], name[j], i, j,
|
||
(unsigned int) __gmpfr_flags, f[i][j]);
|
||
mpfr_dump (r);
|
||
error = 1;
|
||
}
|
||
}
|
||
} /* integer_p */
|
||
/* Perform the same tests with mpfr_ui_pow */
|
||
if (mpfr_integer_p (t[i]) && MPFR_IS_POS (t[i]))
|
||
{
|
||
/* mpfr_ui_pow */
|
||
mpfr_clear_flags ();
|
||
si = mpfr_get_si (t[i], MPFR_RNDN);
|
||
mpfr_ui_pow (r, si, t[j], MPFR_RNDN);
|
||
p = mpfr_nan_p (r) ? 0 : mpfr_inf_p (r) ? 1 :
|
||
mpfr_zero_p (r) ? 2 :
|
||
(d = mpfr_get_d (r, MPFR_RNDN), (int) (ABS(d) * 128.0));
|
||
if (p != 0 && MPFR_IS_NEG (r))
|
||
p = -p;
|
||
if (p != q[i][j])
|
||
{
|
||
printf ("Error in mpfr_ui_pow for (%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;
|
||
}
|
||
if (__gmpfr_flags != f[i][j])
|
||
{
|
||
printf ("Error in mpfr_ui_pow for (%s)^(%s) (%d,%d):\n"
|
||
"Flags = %u instead of expected %u\n",
|
||
name[i], name[j], i, j,
|
||
(unsigned int) __gmpfr_flags, f[i][j]);
|
||
mpfr_dump (r);
|
||
error = 1;
|
||
}
|
||
}
|
||
}
|
||
|
||
for (i = 0; i < 11; i++)
|
||
mpfr_clear (t[i]);
|
||
mpfr_clear (r);
|
||
mpfr_clear (r2);
|
||
mpz_clear (z);
|
||
|
||
if (error)
|
||
exit (1);
|
||
}
|
||
|
||
static void
|
||
underflows (void)
|
||
{
|
||
mpfr_t x, y, z;
|
||
int err = 0;
|
||
int inexact;
|
||
int i;
|
||
mpfr_exp_t emin;
|
||
|
||
mpfr_init2 (x, 64);
|
||
mpfr_init2 (y, 64);
|
||
|
||
mpfr_set_ui (x, 1, MPFR_RNDN);
|
||
mpfr_set_exp (x, mpfr_get_emin());
|
||
|
||
for (i = 3; i < 10; i++)
|
||
{
|
||
mpfr_set_ui (y, i, MPFR_RNDN);
|
||
mpfr_div_2ui (y, y, 1, MPFR_RNDN);
|
||
test_pow (y, x, y, MPFR_RNDN);
|
||
if (MPFR_NOTZERO (y))
|
||
{
|
||
printf ("Error in mpfr_pow for ");
|
||
mpfr_out_str (stdout, 2, 0, x, MPFR_RNDN);
|
||
printf (" ^ (%d/2)\nGot ", i);
|
||
mpfr_out_str (stdout, 2, 0, y, MPFR_RNDN);
|
||
printf (" instead of 0.\n");
|
||
exit (1);
|
||
}
|
||
}
|
||
|
||
mpfr_init2 (z, 55);
|
||
mpfr_set_str (x, "0.110011010011101001110001110100010000110111101E0",
|
||
2, MPFR_RNDN);
|
||
mpfr_set_str (y, "0.101110010011111001011010100011011100111110011E40",
|
||
2, MPFR_RNDN);
|
||
mpfr_clear_flags ();
|
||
inexact = mpfr_pow (z, x, y, MPFR_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, MPFR_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, MPFR_RNDN);
|
||
printf ("\ninstead of ");
|
||
mpfr_out_str (stdout, 2, 2, x, MPFR_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, MPFR_RNDN);
|
||
mpfr_set_ui_2exp (y, 1, mpfr_get_emax () - 1, MPFR_RNDN);
|
||
mpfr_clear_flags ();
|
||
mpfr_pow (z, x, y, MPFR_RNDN);
|
||
if (!mpfr_underflow_p () || MPFR_NOTZERO (z))
|
||
{
|
||
printf ("Underflow test with large y fails.\n");
|
||
exit (1);
|
||
}
|
||
|
||
emin = mpfr_get_emin ();
|
||
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, MPFR_RNDN);
|
||
mpfr_set_ui_2exp (y, 1, 38, MPFR_RNDN);
|
||
mpfr_clear_flags ();
|
||
inexact = mpfr_pow (z, x, y, MPFR_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);
|
||
}
|
||
set_emin (emin);
|
||
|
||
emin = mpfr_get_emin ();
|
||
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, MPFR_RNDN);
|
||
mpfr_set_si_2exp (y, -1, 38, MPFR_RNDN);
|
||
for (i = 0; i < 4; i++)
|
||
{
|
||
if (i == 2)
|
||
mpfr_neg (x, x, MPFR_RNDN);
|
||
mpfr_clear_flags ();
|
||
inexact = mpfr_pow (z, x, y, MPFR_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, MPFR_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, MPFR_RNDN);
|
||
MPFR_ASSERTN (inexact == 0);
|
||
}
|
||
set_emin (emin);
|
||
|
||
mpfr_clears (x, y, z, (mpfr_ptr) 0);
|
||
}
|
||
|
||
static void
|
||
overflows (void)
|
||
{
|
||
mpfr_t a, b;
|
||
|
||
/* bug found by Ming J. Tsai <mingjt@delvron.us>, 4 Oct 2003 */
|
||
|
||
mpfr_init_set_str (a, "5.1e32", 10, MPFR_RNDN);
|
||
mpfr_init (b);
|
||
|
||
test_pow (b, a, a, MPFR_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, MPFR_RNDN);
|
||
printf ("\n");
|
||
exit (1);
|
||
}
|
||
|
||
mpfr_clear(a);
|
||
mpfr_clear(b);
|
||
}
|
||
|
||
static void
|
||
overflows2 (void)
|
||
{
|
||
mpfr_t x, y, z;
|
||
mpfr_exp_t emin, emax;
|
||
int e;
|
||
|
||
/* x^y in reduced exponent range, where x = 2^b and y is not an integer
|
||
(so that mpfr_pow_z is not used). */
|
||
|
||
emin = mpfr_get_emin ();
|
||
emax = mpfr_get_emax ();
|
||
set_emin (-128);
|
||
|
||
mpfr_inits2 (16, x, y, z, (mpfr_ptr) 0);
|
||
|
||
mpfr_set_si_2exp (x, 1, -64, MPFR_RNDN); /* 2^(-64) */
|
||
mpfr_set_si_2exp (y, -1, -1, MPFR_RNDN); /* -0.5 */
|
||
for (e = 2; e <= 32; e += 17)
|
||
{
|
||
set_emax (e);
|
||
mpfr_clear_flags ();
|
||
mpfr_pow (z, x, y, MPFR_RNDN);
|
||
if (MPFR_IS_NEG (z) || ! mpfr_inf_p (z))
|
||
{
|
||
printf ("Error in overflows2 (e = %d): expected +Inf, got ", e);
|
||
mpfr_dump (z);
|
||
exit (1);
|
||
}
|
||
if (__gmpfr_flags != (MPFR_FLAGS_OVERFLOW | MPFR_FLAGS_INEXACT))
|
||
{
|
||
printf ("Error in overflows2 (e = %d): bad flags (%u)\n",
|
||
e, (unsigned int) __gmpfr_flags);
|
||
exit (1);
|
||
}
|
||
}
|
||
|
||
mpfr_clears (x, y, z, (mpfr_ptr) 0);
|
||
|
||
set_emin (emin);
|
||
set_emax (emax);
|
||
}
|
||
|
||
static void
|
||
overflows3 (void)
|
||
{
|
||
/* x^y where x = 2^b, y is not an integer (so that mpfr_pow_z is not used)
|
||
and b * y = emax in the extended exponent range. If emax is divisible
|
||
by 3, we choose x = 2^(-2*emax/3) and y = -3/2.
|
||
Test also with nextbelow(x). */
|
||
|
||
if (MPFR_EMAX_MAX % 3 == 0)
|
||
{
|
||
mpfr_t x, y, z, t;
|
||
mpfr_exp_t emin, emax;
|
||
unsigned int flags;
|
||
int i;
|
||
|
||
emin = mpfr_get_emin ();
|
||
emax = mpfr_get_emax ();
|
||
set_emin (MPFR_EMIN_MIN);
|
||
set_emax (MPFR_EMAX_MAX);
|
||
|
||
mpfr_inits2 (16, x, y, z, t, (mpfr_ptr) 0);
|
||
|
||
mpfr_set_si_2exp (x, 1, -2 * (MPFR_EMAX_MAX / 3), MPFR_RNDN);
|
||
for (i = 0; i <= 1; i++)
|
||
{
|
||
mpfr_set_si_2exp (y, -3, -1, MPFR_RNDN);
|
||
mpfr_clear_flags ();
|
||
mpfr_pow (z, x, y, MPFR_RNDN);
|
||
if (MPFR_IS_NEG (z) || ! mpfr_inf_p (z))
|
||
{
|
||
printf ("Error in overflows3 (RNDN, i = %d): expected +Inf,"
|
||
" got ", i);
|
||
mpfr_dump (z);
|
||
exit (1);
|
||
}
|
||
if (__gmpfr_flags != (MPFR_FLAGS_OVERFLOW | MPFR_FLAGS_INEXACT))
|
||
{
|
||
printf ("Error in overflows3 (RNDN, i = %d): bad flags (%u)\n",
|
||
i, (unsigned int) __gmpfr_flags);
|
||
exit (1);
|
||
}
|
||
|
||
mpfr_clear_flags ();
|
||
mpfr_pow (z, x, y, MPFR_RNDZ);
|
||
flags = __gmpfr_flags;
|
||
mpfr_set (t, z, MPFR_RNDN);
|
||
mpfr_nextabove (t);
|
||
if (MPFR_IS_NEG (z) || mpfr_inf_p (z) || ! mpfr_inf_p (t))
|
||
{
|
||
printf ("Error in overflows3 (RNDZ, i = %d):\nexpected ", i);
|
||
mpfr_set_inf (t, 1);
|
||
mpfr_nextbelow (t);
|
||
mpfr_dump (t);
|
||
printf ("got ");
|
||
mpfr_dump (z);
|
||
exit (1);
|
||
}
|
||
if (flags != (MPFR_FLAGS_OVERFLOW | MPFR_FLAGS_INEXACT))
|
||
{
|
||
printf ("Error in overflows3 (RNDZ, i = %d): bad flags (%u)\n",
|
||
i, flags);
|
||
exit (1);
|
||
}
|
||
mpfr_nextbelow (x);
|
||
}
|
||
|
||
mpfr_clears (x, y, z, t, (mpfr_ptr) 0);
|
||
|
||
set_emin (emin);
|
||
set_emax (emax);
|
||
}
|
||
}
|
||
|
||
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, MPFR_RNDN);
|
||
mpfr_nextbelow (x);
|
||
mpfr_set_ui_2exp (y, 11, -2, MPFR_RNDN);
|
||
inex = mpfr_pow (z, x, y, MPFR_RNDN);
|
||
if (mpfr_cmp_str (z, "0.111111111111111111111111111111011E0", 2, MPFR_RNDN)
|
||
|| inex <= 0)
|
||
{
|
||
printf ("Failure in x_near_one, got inex = %d and\nz = ", inex);
|
||
mpfr_dump (z);
|
||
}
|
||
|
||
mpfr_clears (x, y, z, (mpfr_ptr) 0);
|
||
}
|
||
|
||
static int
|
||
mpfr_pow275 (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t r)
|
||
{
|
||
mpfr_t z;
|
||
int inex;
|
||
|
||
mpfr_init2 (z, 4);
|
||
mpfr_set_ui_2exp (z, 11, -2, MPFR_RNDN);
|
||
inex = mpfr_pow (y, x, z, MPFR_RNDN);
|
||
mpfr_clear (z);
|
||
return inex;
|
||
}
|
||
|
||
/* Bug found by Kevin P. Rauch */
|
||
static void
|
||
bug20071103 (void)
|
||
{
|
||
mpfr_t x, y, z;
|
||
mpfr_exp_t emin, emax;
|
||
|
||
emin = mpfr_get_emin ();
|
||
emax = mpfr_get_emax ();
|
||
set_emin (-1000000);
|
||
set_emax ( 1000000);
|
||
|
||
mpfr_inits2 (64, x, y, z, (mpfr_ptr) 0);
|
||
mpfr_set_si_2exp (x, -3, -1, MPFR_RNDN); /* x = -1.5 */
|
||
mpfr_set_str (y, "-0.ffffffffffffffff", 16, MPFR_RNDN);
|
||
mpfr_set_exp (y, mpfr_get_emax ());
|
||
mpfr_clear_flags ();
|
||
mpfr_pow (z, x, y, MPFR_RNDN);
|
||
MPFR_ASSERTN (mpfr_zero_p (z) && MPFR_IS_POS (z) &&
|
||
__gmpfr_flags == (MPFR_FLAGS_UNDERFLOW | MPFR_FLAGS_INEXACT));
|
||
mpfr_clears (x, y, z, (mpfr_ptr) 0);
|
||
|
||
set_emin (emin);
|
||
set_emax (emax);
|
||
}
|
||
|
||
/* Bug found by Kevin P. Rauch */
|
||
static void
|
||
bug20071104 (void)
|
||
{
|
||
mpfr_t x, y, z;
|
||
mpfr_exp_t emin, emax;
|
||
int inex;
|
||
|
||
emin = mpfr_get_emin ();
|
||
emax = mpfr_get_emax ();
|
||
set_emin (-1000000);
|
||
set_emax ( 1000000);
|
||
|
||
mpfr_inits2 (20, x, y, z, (mpfr_ptr) 0);
|
||
mpfr_set_ui (x, 0, MPFR_RNDN);
|
||
mpfr_nextbelow (x); /* x = -2^(emin-1) */
|
||
mpfr_set_si (y, -2, MPFR_RNDN); /* y = -2 */
|
||
mpfr_clear_flags ();
|
||
inex = mpfr_pow (z, x, y, MPFR_RNDN);
|
||
if (! mpfr_inf_p (z) || MPFR_IS_NEG (z))
|
||
{
|
||
printf ("Error in bug20071104: expected +Inf, got ");
|
||
mpfr_dump (z);
|
||
exit (1);
|
||
}
|
||
if (inex <= 0)
|
||
{
|
||
printf ("Error in bug20071104: bad ternary value (%d)\n", inex);
|
||
exit (1);
|
||
}
|
||
if (__gmpfr_flags != (MPFR_FLAGS_OVERFLOW | MPFR_FLAGS_INEXACT))
|
||
{
|
||
printf ("Error in bug20071104: bad flags (%u)\n",
|
||
(unsigned int) __gmpfr_flags);
|
||
exit (1);
|
||
}
|
||
mpfr_clears (x, y, z, (mpfr_ptr) 0);
|
||
|
||
set_emin (emin);
|
||
set_emax (emax);
|
||
}
|
||
|
||
/* Bug found by Kevin P. Rauch */
|
||
static void
|
||
bug20071127 (void)
|
||
{
|
||
mpfr_t x, y, z;
|
||
int i, tern;
|
||
mpfr_exp_t emin, emax;
|
||
|
||
emin = mpfr_get_emin ();
|
||
emax = mpfr_get_emax ();
|
||
set_emin (-1000000);
|
||
set_emax ( 1000000);
|
||
|
||
mpfr_init2 (x, 128);
|
||
mpfr_init2 (y, 128);
|
||
mpfr_init2 (z, 128);
|
||
|
||
mpfr_set_str (x, "0.80000000000000000000000000000001", 16, MPFR_RNDN);
|
||
|
||
for (i = 1; i < 9; i *= 2)
|
||
{
|
||
mpfr_set_str (y, "8000000000000000", 16, MPFR_RNDN);
|
||
mpfr_add_si (y, y, i, MPFR_RNDN);
|
||
tern = mpfr_pow (z, x, y, MPFR_RNDN);
|
||
MPFR_ASSERTN (mpfr_zero_p (z) && MPFR_IS_POS (z) && tern < 0);
|
||
}
|
||
|
||
mpfr_clear (x);
|
||
mpfr_clear (y);
|
||
mpfr_clear (z);
|
||
|
||
set_emin (emin);
|
||
set_emax (emax);
|
||
}
|
||
|
||
/* Bug found by Kevin P. Rauch */
|
||
static void
|
||
bug20071128 (void)
|
||
{
|
||
mpfr_t max_val, x, y, z;
|
||
int i, tern;
|
||
mpfr_exp_t emin, emax;
|
||
|
||
emin = mpfr_get_emin ();
|
||
emax = mpfr_get_emax ();
|
||
set_emin (-1000000);
|
||
set_emax ( 1000000);
|
||
|
||
mpfr_init2 (max_val, 64);
|
||
mpfr_init2 (x, 64);
|
||
mpfr_init2 (y, 64);
|
||
mpfr_init2 (z, 64);
|
||
|
||
mpfr_set_str (max_val, "0.ffffffffffffffff", 16, MPFR_RNDN);
|
||
mpfr_set_exp (max_val, mpfr_get_emax ());
|
||
|
||
mpfr_neg (x, max_val, MPFR_RNDN);
|
||
|
||
/* on 64-bit machines */
|
||
for (i = 41; i < 45; i++)
|
||
{
|
||
mpfr_set_si_2exp (y, -1, i, MPFR_RNDN);
|
||
mpfr_add_si (y, y, 1, MPFR_RNDN);
|
||
tern = mpfr_pow (z, x, y, MPFR_RNDN);
|
||
MPFR_ASSERTN (mpfr_zero_p (z) && MPFR_IS_NEG (z) && tern > 0);
|
||
}
|
||
|
||
/* on 32-bit machines */
|
||
for (i = 9; i < 13; i++)
|
||
{
|
||
mpfr_set_si_2exp (y, -1, i, MPFR_RNDN);
|
||
mpfr_add_si (y, y, 1, MPFR_RNDN);
|
||
tern = mpfr_pow (z, x, y, MPFR_RNDN);
|
||
MPFR_ASSERTN(mpfr_zero_p (z) && MPFR_IS_NEG (z));
|
||
}
|
||
|
||
mpfr_clear (x);
|
||
mpfr_clear (y);
|
||
mpfr_clear (z);
|
||
mpfr_clear (max_val);
|
||
|
||
set_emin (emin);
|
||
set_emax (emax);
|
||
}
|
||
|
||
/* Bug found by Kevin P. Rauch */
|
||
static void
|
||
bug20071218 (void)
|
||
{
|
||
mpfr_t x, y, z, t;
|
||
int tern;
|
||
|
||
mpfr_inits2 (64, x, y, z, t, (mpfr_ptr) 0);
|
||
mpfr_set_str (x, "0x.80000000000002P-1023", 0, MPFR_RNDN);
|
||
mpfr_set_str (y, "100000.000000002", 16, MPFR_RNDN);
|
||
mpfr_set_ui (t, 0, MPFR_RNDN);
|
||
mpfr_nextabove (t);
|
||
tern = mpfr_pow (z, x, y, MPFR_RNDN);
|
||
if (mpfr_cmp0 (z, t) != 0)
|
||
{
|
||
printf ("Error in bug20071218 (1): Expected\n");
|
||
mpfr_dump (t);
|
||
printf ("Got\n");
|
||
mpfr_dump (z);
|
||
exit (1);
|
||
}
|
||
if (tern <= 0)
|
||
{
|
||
printf ("Error in bug20071218 (1): bad ternary value"
|
||
" (%d instead of positive)\n", tern);
|
||
exit (1);
|
||
}
|
||
mpfr_mul_2ui (y, y, 32, MPFR_RNDN);
|
||
tern = mpfr_pow (z, x, y, MPFR_RNDN);
|
||
if (MPFR_NOTZERO (z) || MPFR_IS_NEG (z))
|
||
{
|
||
printf ("Error in bug20071218 (2): expected 0, got\n");
|
||
mpfr_dump (z);
|
||
exit (1);
|
||
}
|
||
if (tern >= 0)
|
||
{
|
||
printf ("Error in bug20071218 (2): bad ternary value"
|
||
" (%d instead of negative)\n", tern);
|
||
exit (1);
|
||
}
|
||
mpfr_clears (x, y, z, t, (mpfr_ptr) 0);
|
||
}
|
||
|
||
/* With revision 5429, this gives:
|
||
* pow.c:43: assertion failed: !mpfr_integer_p (y)
|
||
* This is fixed in revision 5432.
|
||
*/
|
||
static void
|
||
bug20080721 (void)
|
||
{
|
||
mpfr_t x, y, z, t[2];
|
||
int inex;
|
||
int rnd;
|
||
int err = 0;
|
||
|
||
/* Note: input values have been chosen in a way to select the
|
||
* general case. If mpfr_pow is modified, in particular line
|
||
* if (y_is_integer && (MPFR_GET_EXP (y) <= 256))
|
||
* make sure that this test still does what we want.
|
||
*/
|
||
mpfr_inits2 (4913, x, y, (mpfr_ptr) 0);
|
||
mpfr_inits2 (8, z, t[0], t[1], (mpfr_ptr) 0);
|
||
mpfr_set_si (x, -1, MPFR_RNDN);
|
||
mpfr_nextbelow (x);
|
||
mpfr_set_ui_2exp (y, 1, mpfr_get_prec (y) - 1, MPFR_RNDN);
|
||
inex = mpfr_add_ui (y, y, 1, MPFR_RNDN);
|
||
MPFR_ASSERTN (inex == 0);
|
||
mpfr_set_str_binary (t[0], "-0.10101101e2");
|
||
mpfr_set_str_binary (t[1], "-0.10101110e2");
|
||
RND_LOOP_NO_RNDF (rnd)
|
||
{
|
||
int i, inex0;
|
||
|
||
i = (rnd == MPFR_RNDN || rnd == MPFR_RNDD || rnd == MPFR_RNDA);
|
||
inex0 = i ? -1 : 1;
|
||
mpfr_clear_flags ();
|
||
inex = mpfr_pow (z, x, y, (mpfr_rnd_t) rnd);
|
||
|
||
if (__gmpfr_flags != MPFR_FLAGS_INEXACT || ! SAME_SIGN (inex, inex0)
|
||
|| MPFR_IS_NAN (z) || mpfr_cmp (z, t[i]) != 0)
|
||
{
|
||
unsigned int flags = __gmpfr_flags;
|
||
|
||
printf ("Error in bug20080721 with %s\n",
|
||
mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
|
||
printf ("expected ");
|
||
mpfr_out_str (stdout, 2, 0, t[i], MPFR_RNDN);
|
||
printf (", inex = %d, flags = %u\n", inex0,
|
||
(unsigned int) MPFR_FLAGS_INEXACT);
|
||
printf ("got ");
|
||
mpfr_out_str (stdout, 2, 0, z, MPFR_RNDN);
|
||
printf (", inex = %d, flags = %u\n", inex, flags);
|
||
err = 1;
|
||
}
|
||
}
|
||
mpfr_clears (x, y, z, t[0], t[1], (mpfr_ptr) 0);
|
||
if (err)
|
||
exit (1);
|
||
}
|
||
|
||
/* The following test fails in r5552 (32-bit and 64-bit). This is due to:
|
||
* mpfr_log (t, absx, MPFR_RNDU);
|
||
* mpfr_mul (t, y, t, MPFR_RNDU);
|
||
* in pow.c, that is supposed to compute an upper bound on exp(y*ln|x|),
|
||
* but this is incorrect if y is negative.
|
||
*/
|
||
static void
|
||
bug20080820 (void)
|
||
{
|
||
mpfr_exp_t emin;
|
||
mpfr_t x, y, z1, z2;
|
||
|
||
emin = mpfr_get_emin ();
|
||
set_emin (MPFR_EMIN_MIN);
|
||
mpfr_init2 (x, 80);
|
||
mpfr_init2 (y, sizeof (mpfr_exp_t) * CHAR_BIT + 32);
|
||
mpfr_init2 (z1, 2);
|
||
mpfr_init2 (z2, 80);
|
||
mpfr_set_ui (x, 2, MPFR_RNDN);
|
||
mpfr_nextbelow (x);
|
||
mpfr_set_exp_t (y, mpfr_get_emin () - 2, MPFR_RNDN);
|
||
mpfr_nextabove (y);
|
||
mpfr_pow (z1, x, y, MPFR_RNDN);
|
||
mpfr_pow (z2, x, y, MPFR_RNDN);
|
||
/* As x > 0, the rounded value of x^y to nearest in precision p is equal
|
||
to 0 iff x^y <= 2^(emin - 2). In particular, this does not depend on
|
||
the precision p. Hence the following test. */
|
||
if (MPFR_IS_ZERO (z1) && MPFR_NOTZERO (z2))
|
||
{
|
||
printf ("Error in bug20080820\n");
|
||
exit (1);
|
||
}
|
||
mpfr_clears (x, y, z1, z2, (mpfr_ptr) 0);
|
||
set_emin (emin);
|
||
}
|
||
|
||
static void
|
||
bug20110320 (void)
|
||
{
|
||
mpfr_exp_t emin;
|
||
mpfr_t x, y, z1, z2;
|
||
int inex;
|
||
unsigned int flags;
|
||
|
||
emin = mpfr_get_emin ();
|
||
set_emin (11);
|
||
mpfr_inits2 (2, x, y, z1, z2, (mpfr_ptr) 0);
|
||
mpfr_set_ui_2exp (x, 1, 215, MPFR_RNDN);
|
||
mpfr_set_ui (y, 1024, MPFR_RNDN);
|
||
mpfr_clear_flags ();
|
||
inex = mpfr_pow (z1, x, y, MPFR_RNDN);
|
||
flags = __gmpfr_flags;
|
||
mpfr_set_ui_2exp (z2, 1, 215*1024, MPFR_RNDN);
|
||
if (inex != 0 || flags != 0 || ! mpfr_equal_p (z1, z2))
|
||
{
|
||
printf ("Error in bug20110320\n");
|
||
printf ("Expected inex = 0, flags = 0, z = ");
|
||
mpfr_dump (z2);
|
||
printf ("Got inex = %d, flags = %u, z = ", inex, flags);
|
||
mpfr_dump (z1);
|
||
exit (1);
|
||
}
|
||
mpfr_clears (x, y, z1, z2, (mpfr_ptr) 0);
|
||
set_emin (emin);
|
||
}
|
||
|
||
static void
|
||
tst20140422 (void)
|
||
{
|
||
mpfr_t x, y, z1, z2;
|
||
int inex, rnd;
|
||
unsigned int flags;
|
||
|
||
mpfr_inits2 (128, x, y, z1, z2, (mpfr_ptr) 0);
|
||
mpfr_set_ui (x, 1296, MPFR_RNDN);
|
||
mpfr_set_ui_2exp (y, 3, -2, MPFR_RNDN);
|
||
mpfr_set_ui (z2, 216, MPFR_RNDN);
|
||
RND_LOOP (rnd)
|
||
{
|
||
mpfr_clear_flags ();
|
||
inex = mpfr_pow (z1, x, y, (mpfr_rnd_t) rnd);
|
||
flags = __gmpfr_flags;
|
||
if (inex != 0 || flags != 0 || ! mpfr_equal_p (z1, z2))
|
||
{
|
||
printf ("Error in bug20140422 with %s\n",
|
||
mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
|
||
printf ("Expected inex = 0, flags = 0, z = ");
|
||
mpfr_dump (z2);
|
||
printf ("Got inex = %d, flags = %u, z = ", inex, flags);
|
||
mpfr_dump (z1);
|
||
exit (1);
|
||
}
|
||
}
|
||
mpfr_clears (x, y, z1, z2, (mpfr_ptr) 0);
|
||
}
|
||
|
||
static void
|
||
coverage (void)
|
||
{
|
||
mpfr_t x, y, z, t, u;
|
||
mpfr_exp_t emin;
|
||
int inex;
|
||
int i;
|
||
|
||
/* check a corner case with prec(z)=1 */
|
||
mpfr_init2 (x, 2);
|
||
mpfr_init2 (y, 8);
|
||
mpfr_init2 (z, 1);
|
||
mpfr_set_ui_2exp (x, 3, -2, MPFR_RNDN); /* x = 3/4 */
|
||
emin = mpfr_get_emin ();
|
||
set_emin (-40);
|
||
mpfr_set_ui_2exp (y, 199, -1, MPFR_RNDN); /* y = 99.5 */
|
||
/* x^y ~ 0.81*2^-41 */
|
||
mpfr_clear_underflow ();
|
||
inex = mpfr_pow (z, x, y, MPFR_RNDN);
|
||
MPFR_ASSERTN(inex > 0);
|
||
MPFR_ASSERTN(mpfr_cmp_ui_2exp (z, 1, -41) == 0);
|
||
/* there should be no underflow, since with unbounded exponent range,
|
||
and a precision of 1 bit, x^y is rounded to 1.0*2^-41 */
|
||
MPFR_ASSERTN(!mpfr_underflow_p ());
|
||
mpfr_set_ui_2exp (y, 201, -1, MPFR_RNDN); /* y = 100.5 */
|
||
/* x^y ~ 0.61*2^-41 */
|
||
mpfr_clear_underflow ();
|
||
inex = mpfr_pow (z, x, y, MPFR_RNDN);
|
||
MPFR_ASSERTN(inex > 0);
|
||
MPFR_ASSERTN(mpfr_cmp_ui_2exp (z, 1, -41) == 0);
|
||
/* there should be an underflow, since with unbounded exponent range,
|
||
and a precision of 1 bit, x^y is rounded to 0.5*2^-41 */
|
||
MPFR_ASSERTN(mpfr_underflow_p ());
|
||
mpfr_set_ui_2exp (y, 203, -1, MPFR_RNDN); /* y = 101.5 */
|
||
/* x^y ~ 0.46*2^-41 */
|
||
mpfr_clear_underflow ();
|
||
inex = mpfr_pow (z, x, y, MPFR_RNDN);
|
||
MPFR_ASSERTN(inex < 0);
|
||
MPFR_ASSERTN(mpfr_zero_p (z) && mpfr_signbit (z) == 0);
|
||
MPFR_ASSERTN(mpfr_underflow_p ());
|
||
mpfr_clears (x, y, z, (mpfr_ptr) 0);
|
||
set_emin (emin);
|
||
|
||
/* test for x = -2, y an odd integer with EXP(y) > i */
|
||
mpfr_inits2 (10, t, u, (mpfr_ptr) 0);
|
||
mpfr_set_ui_2exp (t, 1, 1UL << 8, MPFR_RNDN);
|
||
for (i = 8; i <= 300; i++)
|
||
{
|
||
mpfr_flags_t flags, flags_u;
|
||
int inex_u;
|
||
|
||
mpfr_mul_si (u, t, -2, MPFR_RNDN); /* u = (-2)^(2^i + 1) */
|
||
mpfr_init2 (x, 10);
|
||
mpfr_init2 (y, i+1);
|
||
mpfr_init2 (z, 10);
|
||
mpfr_set_si (x, -2, MPFR_RNDN);
|
||
mpfr_set_ui_2exp (y, 1, i, MPFR_RNDN);
|
||
mpfr_nextabove (y); /* y = 2^i + 1 */
|
||
if (MPFR_IS_INF (u))
|
||
{
|
||
inex_u = -1;
|
||
flags_u = MPFR_FLAGS_OVERFLOW | MPFR_FLAGS_INEXACT;
|
||
}
|
||
else
|
||
{
|
||
inex_u = 0;
|
||
flags_u = 0;
|
||
}
|
||
mpfr_clear_flags ();
|
||
inex = mpfr_pow (z, x, y, MPFR_RNDN);
|
||
flags = __gmpfr_flags;
|
||
if (mpfr_cmp0 (z, u) != 0 ||
|
||
! SAME_SIGN (inex, inex_u) ||
|
||
flags != flags_u)
|
||
{
|
||
printf ("Error in coverage for (-2)^(2^%d + 1):\n", i);
|
||
printf ("Expected ");
|
||
mpfr_dump (u);
|
||
printf (" with inex = %d and flags:", inex_u);
|
||
flags_out (flags_u);
|
||
printf ("Got ");
|
||
mpfr_dump (z);
|
||
printf (" with inex = %d and flags:", inex);
|
||
flags_out (flags);
|
||
exit (1);
|
||
}
|
||
mpfr_sqr (t, t, MPFR_RNDN);
|
||
mpfr_clears (x, y, z, (mpfr_ptr) 0);
|
||
}
|
||
mpfr_clears (t, u, (mpfr_ptr) 0);
|
||
|
||
#if _MPFR_EXP_FORMAT >= 3 && _MPFR_PREC_FORMAT == 3 && MPFR_PREC_BITS == 64
|
||
/* thus an unsigned long has at least 64 bits and x will be finite */
|
||
{
|
||
mpfr_exp_t emax;
|
||
|
||
emax = mpfr_get_emax ();
|
||
set_emax ((1UL << 62) - 1);
|
||
/* emax = 4611686018427387903 on a 64-bit machine */
|
||
mpfr_init2 (x, 65);
|
||
mpfr_init2 (y, 65);
|
||
mpfr_init2 (z, 64);
|
||
mpfr_set_ui_2exp (x, 512, 3074457345618258593UL, MPFR_RNDN);
|
||
mpfr_nextbelow (x);
|
||
mpfr_set_str_binary (y, "1.1"); /* y = 3/2 */
|
||
mpfr_nextabove (y);
|
||
inex = mpfr_pow (z, x, y, MPFR_RNDN);
|
||
MPFR_ASSERTN(inex > 0);
|
||
MPFR_ASSERTN(mpfr_inf_p (z));
|
||
mpfr_clears (x, y, z, (mpfr_ptr) 0);
|
||
set_emax (emax);
|
||
}
|
||
#endif
|
||
}
|
||
|
||
static void
|
||
check_binary128 (void)
|
||
{
|
||
mpfr_t x, y, z, t;
|
||
|
||
mpfr_init2 (x, 113);
|
||
mpfr_init2 (y, 113);
|
||
mpfr_init2 (z, 113);
|
||
mpfr_init2 (t, 113);
|
||
|
||
/* x = 1-2^(-113) */
|
||
mpfr_set_ui (x, 1, MPFR_RNDN);
|
||
mpfr_nextbelow (x);
|
||
/* y = 1.125*2^126 = 9*2^123 */
|
||
mpfr_set_ui_2exp (y, 9, 123, MPFR_RNDN);
|
||
mpfr_pow (z, x, y, MPFR_RNDN);
|
||
/* x^y ~ 3.48e-4003 */
|
||
mpfr_set_str (t, "1.16afef53c30899a5c172bb302882p-13296", 16, MPFR_RNDN);
|
||
if (! mpfr_equal_p (z, t))
|
||
{
|
||
printf ("Error in check_binary128\n");
|
||
printf ("expected "); mpfr_dump (t);
|
||
printf ("got "); mpfr_dump (z);
|
||
exit (1);
|
||
}
|
||
|
||
/* x = 5192296858534827628530496329220095/2^112 */
|
||
mpfr_set_str (x, "1.fffffffffffffffffffffffffffep-1", 16, MPFR_RNDN);
|
||
/* y = -58966440806378323534486035691038613504 */
|
||
mpfr_set_str (y, "-1.62e42fefa39ef35793c7673007e5p125", 16, MPFR_RNDN);
|
||
mpfr_pow (z, x, y, MPFR_RNDN);
|
||
mpfr_set_str (t, "1.fffffffffffffffffffffffff105p16383", 16, MPFR_RNDN);
|
||
if (! mpfr_equal_p (z, t))
|
||
{
|
||
printf ("Error in check_binary128 (2)\n");
|
||
printf ("expected "); mpfr_dump (t);
|
||
printf ("got "); mpfr_dump (z);
|
||
exit (1);
|
||
}
|
||
|
||
mpfr_clear (x);
|
||
mpfr_clear (y);
|
||
mpfr_clear (z);
|
||
mpfr_clear (t);
|
||
}
|
||
|
||
int
|
||
main (int argc, char **argv)
|
||
{
|
||
mpfr_prec_t p;
|
||
|
||
tests_start_mpfr ();
|
||
|
||
coverage ();
|
||
bug20071127 ();
|
||
special ();
|
||
particular_cases ();
|
||
check_pow_ui ();
|
||
check_pow_si ();
|
||
check_pown_ieee754_2019 ();
|
||
check_special_pow_si ();
|
||
pow_si_long_min ();
|
||
for (p = MPFR_PREC_MIN; p < 100; p++)
|
||
check_inexact (p);
|
||
underflows ();
|
||
overflows ();
|
||
overflows2 ();
|
||
overflows3 ();
|
||
x_near_one ();
|
||
bug20071103 ();
|
||
bug20071104 ();
|
||
bug20071128 ();
|
||
bug20071218 ();
|
||
bug20080721 ();
|
||
bug20080820 ();
|
||
bug20110320 ();
|
||
tst20140422 ();
|
||
check_binary128 ();
|
||
|
||
test_generic (MPFR_PREC_MIN, 100, 100);
|
||
test_generic_ui (MPFR_PREC_MIN, 100, 100);
|
||
test_generic_si (MPFR_PREC_MIN, 100, 100);
|
||
|
||
data_check ("data/pow275", mpfr_pow275, "mpfr_pow275");
|
||
|
||
bad_cases (powu2, root2, "mpfr_pow_ui[2]",
|
||
8, -256, 255, 4, 128, 800, 40);
|
||
bad_cases (pows2, root2, "mpfr_pow_si[2]",
|
||
8, -256, 255, 4, 128, 800, 40);
|
||
bad_cases (powm2, rootm2, "mpfr_pow_si[-2]",
|
||
8, -256, 255, 4, 128, 800, 40);
|
||
bad_cases (powu3, root3, "mpfr_pow_ui[3]",
|
||
256, -256, 255, 4, 128, 800, 40);
|
||
bad_cases (pows3, root3, "mpfr_pow_si[3]",
|
||
256, -256, 255, 4, 128, 800, 40);
|
||
bad_cases (powm3, rootm3, "mpfr_pow_si[-3]",
|
||
256, -256, 255, 4, 128, 800, 40);
|
||
bad_cases (powu4, root4, "mpfr_pow_ui[4]",
|
||
8, -256, 255, 4, 128, 800, 40);
|
||
bad_cases (pows4, root4, "mpfr_pow_si[4]",
|
||
8, -256, 255, 4, 128, 800, 40);
|
||
bad_cases (powm4, rootm4, "mpfr_pow_si[-4]",
|
||
8, -256, 255, 4, 128, 800, 40);
|
||
bad_cases (powu5, root5, "mpfr_pow_ui[5]",
|
||
256, -256, 255, 4, 128, 800, 40);
|
||
bad_cases (pows5, root5, "mpfr_pow_si[5]",
|
||
256, -256, 255, 4, 128, 800, 40);
|
||
bad_cases (powm5, rootm5, "mpfr_pow_si[-5]",
|
||
256, -256, 255, 4, 128, 800, 40);
|
||
bad_cases (powu17, root17, "mpfr_pow_ui[17]",
|
||
256, -256, 255, 4, 128, 800, 40);
|
||
bad_cases (pows17, root17, "mpfr_pow_si[17]",
|
||
256, -256, 255, 4, 128, 800, 40);
|
||
bad_cases (powm17, rootm17, "mpfr_pow_si[-17]",
|
||
256, -256, 255, 4, 128, 800, 40);
|
||
bad_cases (powu120, root120, "mpfr_pow_ui[120]",
|
||
8, -256, 255, 4, 128, 800, 40);
|
||
bad_cases (pows120, root120, "mpfr_pow_si[120]",
|
||
8, -256, 255, 4, 128, 800, 40);
|
||
bad_cases (powm120, rootm120, "mpfr_pow_si[-120]",
|
||
8, -256, 255, 4, 128, 800, 40);
|
||
|
||
tests_end_mpfr ();
|
||
return 0;
|
||
}
|