mirror of
https://review.haiku-os.org/buildtools
synced 2025-02-12 08:47:41 +01:00
Change-Id: I42dc2a783b3e0082a7583cc7ecaa6b043ba162f4 Reviewed-on: https://review.haiku-os.org/c/buildtools/+/3021 Reviewed-by: Fredrik Holmqvist <fredrik.holmqvist@gmail.com>
403 lines
11 KiB
C
403 lines
11 KiB
C
/* Test file for mpfr_gamma_inc
|
|
|
|
Copyright 2016-2020 Free Software Foundation, Inc.
|
|
Contributed by the AriC 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/ or write to the Free Software Foundation, Inc.,
|
|
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
|
|
|
#include "mpfr-test.h"
|
|
|
|
#define TEST_FUNCTION mpfr_gamma_inc
|
|
#define TWO_ARGS
|
|
#define TEST_RANDOM_POS2 0 /* the 2nd argument is never negative */
|
|
#define TGENERIC_NOWARNING 1
|
|
#define TEST_RANDOM_EMAX 8
|
|
#define TEST_RANDOM_EMIN -32
|
|
#define REDUCE_EMAX TEST_RANDOM_EMAX
|
|
#define REDUCE_EMIN TEST_RANDOM_EMIN
|
|
#include "tgeneric.c"
|
|
|
|
/* do k random tests at precision p */
|
|
static void
|
|
test_random (mpfr_prec_t p, int k)
|
|
{
|
|
mpfr_t a, x, y, z, t;
|
|
|
|
mpfr_inits2 (p, a, x, y, z, (mpfr_ptr) 0);
|
|
mpfr_init2 (t, p + 20);
|
|
while (k--)
|
|
{
|
|
do mpfr_urandomb (a, RANDS); while (mpfr_zero_p (a));
|
|
if (randlimb () & 1)
|
|
mpfr_neg (a, a, MPFR_RNDN);
|
|
do mpfr_urandomb (x, RANDS); while (mpfr_zero_p (x));
|
|
mpfr_gamma_inc (y, a, x, MPFR_RNDN);
|
|
mpfr_gamma_inc (t, a, x, MPFR_RNDN);
|
|
if (mpfr_can_round (t, mpfr_get_prec (z), MPFR_RNDN, MPFR_RNDN, p))
|
|
{
|
|
mpfr_set (z, t, MPFR_RNDN);
|
|
if (mpfr_cmp (y, z))
|
|
{
|
|
printf ("mpfr_gamma_inc failed for a=");
|
|
mpfr_out_str (stdout, 10, 0, a, MPFR_RNDN);
|
|
printf (" x=");
|
|
mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN);
|
|
printf ("\nexpected ");
|
|
mpfr_out_str (stdout, 10, 0, z, MPFR_RNDN);
|
|
printf ("\ngot ");
|
|
mpfr_out_str (stdout, 10, 0, y, MPFR_RNDN);
|
|
printf ("\n");
|
|
exit (1);
|
|
}
|
|
}
|
|
}
|
|
mpfr_clears (a, x, y, z, (mpfr_ptr) 0);
|
|
mpfr_clear (t);
|
|
}
|
|
|
|
static void
|
|
specials (void)
|
|
{
|
|
mpfr_t a, x;
|
|
int inex;
|
|
|
|
mpfr_init2 (a, 2);
|
|
mpfr_init2 (x, 2);
|
|
|
|
mpfr_set_inf (a, 1);
|
|
mpfr_set_inf (x, 1);
|
|
mpfr_gamma_inc (a, a, x, MPFR_RNDN);
|
|
MPFR_ASSERTN (mpfr_nan_p (a));
|
|
|
|
mpfr_set_inf (a, 1);
|
|
mpfr_set_inf (x, -1);
|
|
mpfr_gamma_inc (a, a, x, MPFR_RNDN);
|
|
MPFR_ASSERTN (mpfr_nan_p (a));
|
|
|
|
mpfr_set_inf (a, -1);
|
|
mpfr_set_inf (x, -1);
|
|
mpfr_gamma_inc (a, a, x, MPFR_RNDN);
|
|
MPFR_ASSERTN (mpfr_nan_p (a));
|
|
|
|
mpfr_set_inf (a, -1);
|
|
mpfr_set_inf (x, 1);
|
|
mpfr_gamma_inc (a, a, x, MPFR_RNDN);
|
|
MPFR_ASSERTN (mpfr_zero_p (a) || mpfr_signbit (a) == 0);
|
|
|
|
mpfr_set_inf (a, 1);
|
|
mpfr_set_ui (x, 1, MPFR_RNDN);
|
|
mpfr_gamma_inc (a, a, x, MPFR_RNDN);
|
|
MPFR_ASSERTN (mpfr_inf_p (a) || mpfr_signbit (a) == 0);
|
|
|
|
mpfr_set_inf (a, -1);
|
|
mpfr_set_ui (x, 2, MPFR_RNDN);
|
|
mpfr_gamma_inc (a, a, x, MPFR_RNDN);
|
|
MPFR_ASSERTN (mpfr_zero_p (a) || mpfr_signbit (a) == 0);
|
|
|
|
mpfr_set_inf (a, -1);
|
|
mpfr_set_ui (x, 1, MPFR_RNDN);
|
|
mpfr_gamma_inc (a, a, x, MPFR_RNDN);
|
|
MPFR_ASSERTN (mpfr_zero_p (a) || mpfr_signbit (a) == 0);
|
|
|
|
mpfr_set_inf (a, -1);
|
|
mpfr_set_ui_2exp (x, 1, -1, MPFR_RNDN);
|
|
mpfr_gamma_inc (a, a, x, MPFR_RNDN);
|
|
MPFR_ASSERTN (mpfr_inf_p (a) || mpfr_signbit (a) == 0);
|
|
|
|
mpfr_set_ui (a, 1, MPFR_RNDN);
|
|
mpfr_set_inf (x, 1);
|
|
mpfr_gamma_inc (a, a, x, MPFR_RNDN);
|
|
MPFR_ASSERTN (mpfr_zero_p (a) || mpfr_signbit (a) == 0);
|
|
|
|
/* gamma_inc(1,-x) = exp(x) tends to +Inf */
|
|
mpfr_set_ui (a, 1, MPFR_RNDN);
|
|
mpfr_set_inf (x, -1);
|
|
mpfr_gamma_inc (a, a, x, MPFR_RNDN);
|
|
MPFR_ASSERTN (mpfr_inf_p (a) || mpfr_signbit (a) == 0);
|
|
|
|
/* gamma_inc(0,x) for x < 0 has imaginary part -Pi and thus gives NaN
|
|
over the reals */
|
|
mpfr_set_zero (a, 1);
|
|
mpfr_set_inf (x, -1);
|
|
mpfr_gamma_inc (a, a, x, MPFR_RNDN);
|
|
MPFR_ASSERTN (mpfr_nan_p (a));
|
|
|
|
/* gamma_inc(-1,x) for x < 0 has imaginary part +Pi and thus gives NaN */
|
|
mpfr_set_si (a, -1, MPFR_RNDN);
|
|
mpfr_set_inf (x, -1);
|
|
mpfr_gamma_inc (a, a, x, MPFR_RNDN);
|
|
MPFR_ASSERTN (mpfr_nan_p (a));
|
|
|
|
/* gamma_inc(-2,x) for x < 0 has imaginary part -Pi/2 and thus gives NaN */
|
|
mpfr_set_si (a, -2, MPFR_RNDN);
|
|
mpfr_set_inf (x, -1);
|
|
mpfr_gamma_inc (a, a, x, MPFR_RNDN);
|
|
MPFR_ASSERTN (mpfr_nan_p (a));
|
|
|
|
mpfr_set_ui_2exp (a, 1, -1, MPFR_RNDN);
|
|
mpfr_set_inf (x, -1);
|
|
mpfr_gamma_inc (a, a, x, MPFR_RNDN);
|
|
MPFR_ASSERTN (mpfr_nan_p (a));
|
|
|
|
mpfr_set_si_2exp (a, -1, -1, MPFR_RNDN);
|
|
mpfr_set_inf (x, -1);
|
|
mpfr_gamma_inc (a, a, x, MPFR_RNDN);
|
|
MPFR_ASSERTN (mpfr_nan_p (a));
|
|
|
|
/* gamma_inc(0,x) = -Ei(-x) */
|
|
mpfr_set_zero (a, 1);
|
|
mpfr_set_si (x, -1, MPFR_RNDN);
|
|
mpfr_gamma_inc (a, a, x, MPFR_RNDN);
|
|
MPFR_ASSERTN (mpfr_nan_p (a));
|
|
|
|
/* gamma_inc(a,0) = gamma(a) thus gamma_inc(-Inf,0) = gamma(-Inf) = NaN */
|
|
mpfr_set_inf (a, -1);
|
|
mpfr_set_zero (x, 1);
|
|
mpfr_gamma_inc (a, a, x, MPFR_RNDN);
|
|
MPFR_ASSERTN (mpfr_nan_p (a));
|
|
|
|
mpfr_set_inf (a, -1);
|
|
mpfr_set_si (x, -1, MPFR_RNDN);
|
|
mpfr_gamma_inc (a, a, x, MPFR_RNDN);
|
|
MPFR_ASSERTN (mpfr_nan_p (a));
|
|
|
|
/* check gamma_inc(2,0) = 1 is exact */
|
|
mpfr_set_ui (a, 2, MPFR_RNDN);
|
|
mpfr_set_ui (x, 0, MPFR_RNDN);
|
|
mpfr_clear_inexflag ();
|
|
inex = mpfr_gamma_inc (a, a, x, MPFR_RNDN);
|
|
if (mpfr_cmp_ui (a, 1))
|
|
{
|
|
printf ("Error for gamma_inc(2,0)\n");
|
|
printf ("expected 1\n");
|
|
printf ("got ");
|
|
mpfr_out_str (stdout, 10, 0, a, MPFR_RNDN);
|
|
printf ("\n");
|
|
exit (1);
|
|
}
|
|
if (inex != 0)
|
|
{
|
|
printf ("Wrong ternary value for gamma_inc(2,0)\n");
|
|
printf ("expected 0\n");
|
|
printf ("got %d\n", inex);
|
|
exit (1);
|
|
}
|
|
if (mpfr_inexflag_p ())
|
|
{
|
|
printf ("Wrong inexact flag for gamma_inc(2,0)\n");
|
|
printf ("expected 0\n");
|
|
printf ("got 1\n");
|
|
exit (1);
|
|
}
|
|
|
|
/* check gamma_inc(0,1) = 0.219383934395520 */
|
|
mpfr_set_ui (a, 0, MPFR_RNDN);
|
|
mpfr_set_ui (x, 1, MPFR_RNDN);
|
|
mpfr_gamma_inc (a, a, x, MPFR_RNDN);
|
|
if (mpfr_cmp_ui_2exp (a, 1, -2))
|
|
{
|
|
printf ("Error for gamma_inc(0,1)\n");
|
|
printf ("expected 0.25\n");
|
|
printf ("got ");
|
|
mpfr_out_str (stdout, 10, 0, a, MPFR_RNDN);
|
|
printf ("\n");
|
|
exit (1);
|
|
}
|
|
|
|
/* check gamma_inc(-1,1) = 0.148495506775922 */
|
|
mpfr_set_si (a, -1, MPFR_RNDN);
|
|
mpfr_set_ui (x, 1, MPFR_RNDN);
|
|
mpfr_gamma_inc (a, a, x, MPFR_RNDN);
|
|
if (mpfr_cmp_ui_2exp (a, 1, -3))
|
|
{
|
|
printf ("Error for gamma_inc(-1,1)\n");
|
|
printf ("expected 0.125\n");
|
|
printf ("got ");
|
|
mpfr_out_str (stdout, 10, 0, a, MPFR_RNDN);
|
|
printf ("\n");
|
|
exit (1);
|
|
}
|
|
|
|
/* check gamma_inc(-2,1) = 0.109691967197760 */
|
|
mpfr_set_si (a, -2, MPFR_RNDN);
|
|
mpfr_set_ui (x, 1, MPFR_RNDN);
|
|
mpfr_gamma_inc (a, a, x, MPFR_RNDN);
|
|
if (mpfr_cmp_ui_2exp (a, 1, -3))
|
|
{
|
|
printf ("Error for gamma_inc(-2,1)\n");
|
|
printf ("expected 0.125\n");
|
|
printf ("got ");
|
|
mpfr_out_str (stdout, 10, 0, a, MPFR_RNDN);
|
|
printf ("\n");
|
|
exit (1);
|
|
}
|
|
|
|
/* check gamma_inc(-3,1) = 0.109691967197760 */
|
|
mpfr_set_si (a, -3, MPFR_RNDN);
|
|
mpfr_set_ui (x, 1, MPFR_RNDN);
|
|
mpfr_gamma_inc (a, a, x, MPFR_RNDN);
|
|
if (mpfr_cmp_ui_2exp (a, 3, -5))
|
|
{
|
|
printf ("Error for gamma_inc(-3,1)\n");
|
|
printf ("expected 3/32\n");
|
|
printf ("got ");
|
|
mpfr_out_str (stdout, 10, 0, a, MPFR_RNDN);
|
|
printf ("\n");
|
|
exit (1);
|
|
}
|
|
|
|
/* check gamma_inc(-100,1) = 0.00364201018241046 */
|
|
mpfr_set_si (a, -100, MPFR_RNDN);
|
|
mpfr_set_ui (x, 1, MPFR_RNDN);
|
|
mpfr_gamma_inc (a, a, x, MPFR_RNDN);
|
|
if (mpfr_cmp_ui_2exp (a, 1, -8))
|
|
{
|
|
printf ("Error for gamma_inc(-100,1)\n");
|
|
printf ("expected 1/256\n");
|
|
printf ("got ");
|
|
mpfr_out_str (stdout, 10, 0, a, MPFR_RNDN);
|
|
printf ("\n");
|
|
exit (1);
|
|
}
|
|
|
|
/* TODO: Once internal overflow is supported, add new tests with
|
|
larger exponents, e.g. 64 (in addition to 25). */
|
|
mpfr_set_prec (a, 1);
|
|
mpfr_set_prec (x, 1);
|
|
mpfr_set_ui_2exp (a, 1, 25, MPFR_RNDN);
|
|
mpfr_set_ui_2exp (x, 1, -25, MPFR_RNDN);
|
|
mpfr_gamma_inc (a, a, x, MPFR_RNDN);
|
|
|
|
mpfr_clear (a);
|
|
mpfr_clear (x);
|
|
}
|
|
|
|
/* tests for negative integer a: for -n <= a <= -1, perform k tests
|
|
with random x in 0..|a| and precision 'prec' */
|
|
static void
|
|
test_negint (long n, unsigned long k, mpfr_prec_t prec)
|
|
{
|
|
long i, j;
|
|
mpfr_t a, x, y;
|
|
|
|
mpfr_init2 (a, prec);
|
|
mpfr_init2 (x, prec);
|
|
mpfr_init2 (y, prec);
|
|
for (i = 1; i <= n; i++)
|
|
{
|
|
mpfr_set_si (a, -i, MPFR_RNDN);
|
|
for (j = 1; j <= k; j++)
|
|
{
|
|
mpfr_urandomb (x, RANDS);
|
|
mpfr_mul_si (x, x, j, MPFR_RNDN);
|
|
mpfr_set_prec (y, prec + 20);
|
|
mpfr_gamma_inc (y, a, x, MPFR_RNDZ);
|
|
mpfr_gamma_inc (x, a, x, MPFR_RNDZ);
|
|
mpfr_prec_round (y, prec, MPFR_RNDZ);
|
|
if (mpfr_cmp (x, y))
|
|
{
|
|
printf ("Error in mpfr_gamma_inc(%ld,%ld) with MPFR_RNDZ\n",
|
|
-i, j);
|
|
printf ("expected ");
|
|
mpfr_out_str (stdout, 10, 0, y, MPFR_RNDN);
|
|
printf ("\ngot ");
|
|
mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN);
|
|
printf ("\n");
|
|
exit (1);
|
|
}
|
|
}
|
|
}
|
|
mpfr_clear (a);
|
|
mpfr_clear (x);
|
|
mpfr_clear (y);
|
|
}
|
|
|
|
static void
|
|
coverage (void)
|
|
{
|
|
mpfr_t a, x, y;
|
|
int inex;
|
|
|
|
mpfr_init2 (a, MPFR_PREC_MIN);
|
|
mpfr_init2 (x, MPFR_PREC_MIN);
|
|
mpfr_init2 (y, MPFR_PREC_MIN);
|
|
|
|
/* exercise test MPFR_GET_EXP(a) + 3 > w in mpfr_gamma_inc_negint */
|
|
mpfr_set_si (a, -256, MPFR_RNDN);
|
|
mpfr_set_ui (x, 1, MPFR_RNDN);
|
|
inex = mpfr_gamma_inc (y, a, x, MPFR_RNDN);
|
|
/* gamma_inc(-256,1) = 0.00143141575826821 is rounded to 2^(-10) */
|
|
MPFR_ASSERTN(inex < 0);
|
|
MPFR_ASSERTN(mpfr_cmp_ui_2exp (y, 1, -10) == 0);
|
|
|
|
/* exercise the case MPFR_IS_ZERO(s) in mpfr_gamma_inc_negint */
|
|
mpfr_set_prec (a, 4);
|
|
mpfr_set_prec (x, 4);
|
|
mpfr_set_prec (y, 4);
|
|
inex = mpfr_set_si (a, -15, MPFR_RNDN);
|
|
MPFR_ASSERTN (inex == 0);
|
|
inex = mpfr_set_ui (x, 15, MPFR_RNDN);
|
|
MPFR_ASSERTN (inex == 0);
|
|
/* gamma_inc(-15,15) = 0.2290433491e-25, rounded to 14*2^(-89) */
|
|
inex = mpfr_gamma_inc (y, a, x, MPFR_RNDN);
|
|
MPFR_ASSERTN(inex < 0);
|
|
MPFR_ASSERTN(mpfr_cmp_ui_2exp (y, 14, -89) == 0);
|
|
|
|
mpfr_clear (a);
|
|
mpfr_clear (x);
|
|
mpfr_clear (y);
|
|
}
|
|
|
|
int
|
|
main (int argc, char *argv[])
|
|
{
|
|
mpfr_prec_t p;
|
|
|
|
tests_start_mpfr ();
|
|
|
|
if (argc == 4) /* tgamma_inc a x prec: print gamma_inc(a,x) to prec bits */
|
|
{
|
|
mpfr_prec_t p = atoi (argv[3]);
|
|
mpfr_t a, x;
|
|
mpfr_init2 (a, p);
|
|
mpfr_init2 (x, p);
|
|
mpfr_set_str (a, argv[1], 10, MPFR_RNDN);
|
|
mpfr_set_str (x, argv[2], 10, MPFR_RNDN);
|
|
mpfr_gamma_inc (x, a, x, MPFR_RNDN);
|
|
mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN);
|
|
printf ("\n");
|
|
mpfr_clear (a);
|
|
mpfr_clear (x);
|
|
return 0;
|
|
}
|
|
|
|
coverage ();
|
|
|
|
specials ();
|
|
|
|
test_negint (30, 10, 53);
|
|
|
|
for (p = MPFR_PREC_MIN; p < 100; p++)
|
|
test_random (p, 10);
|
|
|
|
test_generic (MPFR_PREC_MIN, 100, 5);
|
|
|
|
tests_end_mpfr ();
|
|
return 0;
|
|
}
|