mirror of
https://review.haiku-os.org/buildtools
synced 2025-01-31 18:44:48 +01:00
974e12c1f0
Old version was 3.1.2 and is quite old: 2013-03-13 A lot has happened since then 4.0.1 is from 2018-02-07
299 lines
7.6 KiB
C
299 lines
7.6 KiB
C
/* Test file for mpfr_frac.
|
|
|
|
Copyright 2002-2018 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
|
|
http://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 PIP 70
|
|
#define PFP 70
|
|
#define PMAX (PIP+2*PFP)
|
|
|
|
static void
|
|
check0 (mpfr_ptr ip, mpfr_ptr fp, mpfr_prec_t prec, mpfr_rnd_t rnd)
|
|
{
|
|
mpfr_t sum, tmp, dst, fp2;
|
|
int inex1, inex2;
|
|
|
|
mpfr_init2 (sum, PMAX);
|
|
mpfr_init2 (tmp, PMAX);
|
|
mpfr_init2 (dst, prec);
|
|
mpfr_init2 (fp2, prec);
|
|
|
|
if (MPFR_SIGN (ip) != MPFR_SIGN (fp))
|
|
{
|
|
printf ("Internal error (1)\n");
|
|
exit (1);
|
|
}
|
|
if (mpfr_add (sum, ip, fp, MPFR_RNDZ))
|
|
{
|
|
printf ("Wrong inexact flag in mpfr_add\n");
|
|
exit (1);
|
|
}
|
|
if (MPFR_SIGN (sum) != MPFR_SIGN (fp))
|
|
{
|
|
printf ("Internal error (2)\n");
|
|
exit (1);
|
|
}
|
|
|
|
inex1 = mpfr_frac (dst, sum, rnd);
|
|
inex2 = mpfr_set (fp2, fp, rnd);
|
|
if (inex1 != inex2)
|
|
{
|
|
printf ("Wrong inexact flag in mpfr_frac for\n");
|
|
mpfr_out_str (stdout, 2, 0, sum, MPFR_RNDN);
|
|
printf ("\nGot %d instead of %d\n", inex1, inex2);
|
|
exit (1);
|
|
}
|
|
if (!mpfr_number_p (dst) ||
|
|
MPFR_SIGN (dst) != MPFR_SIGN (fp2) ||
|
|
mpfr_cmp (dst, fp2))
|
|
{
|
|
printf ("Error in mpfr_frac (y, x, %s) with\nx = ",
|
|
mpfr_print_rnd_mode (rnd));
|
|
mpfr_out_str (stdout, 2, 0, sum, MPFR_RNDN);
|
|
printf ("\nGot ");
|
|
mpfr_out_str (stdout, 2, 0, dst, MPFR_RNDN);
|
|
printf ("\ninstead of ");
|
|
mpfr_out_str (stdout, 2, 0, fp2, MPFR_RNDN);
|
|
printf ("\n");
|
|
exit (1);
|
|
}
|
|
|
|
if (prec == PMAX)
|
|
{
|
|
inex1 = mpfr_frac (sum, sum, rnd);
|
|
if (inex1)
|
|
{
|
|
printf ("Wrong inexact flag in mpfr_frac\n");
|
|
exit (1);
|
|
}
|
|
if (!mpfr_number_p (sum) ||
|
|
MPFR_SIGN (sum) != MPFR_SIGN (fp) ||
|
|
mpfr_cmp (sum, fp))
|
|
{
|
|
printf ("Error in mpfr_frac (x, x, %s) with\nx = ",
|
|
mpfr_print_rnd_mode (rnd));
|
|
mpfr_add (tmp, ip, fp, MPFR_RNDZ);
|
|
mpfr_out_str (stdout, 2, 0, tmp, MPFR_RNDN);
|
|
printf ("\nGot ");
|
|
mpfr_out_str (stdout, 2, 0, sum, MPFR_RNDN);
|
|
printf ("\ninstead of ");
|
|
mpfr_out_str (stdout, 2, 0, fp, MPFR_RNDN);
|
|
printf ("\n");
|
|
exit (1);
|
|
}
|
|
}
|
|
|
|
mpfr_clear (fp2);
|
|
mpfr_clear (dst);
|
|
mpfr_clear (tmp);
|
|
mpfr_clear (sum);
|
|
}
|
|
|
|
static void
|
|
check1 (mpfr_ptr ip, mpfr_ptr fp)
|
|
{
|
|
int rnd;
|
|
|
|
for (rnd = 0; rnd < MPFR_RND_MAX ; rnd++)
|
|
{
|
|
check0 (ip, fp, PMAX, (mpfr_rnd_t) rnd);
|
|
check0 (ip, fp, 70, (mpfr_rnd_t) rnd);
|
|
mpfr_neg (fp, fp, MPFR_RNDN);
|
|
mpfr_neg (ip, ip, MPFR_RNDN);
|
|
check0 (ip, fp, PMAX, (mpfr_rnd_t) rnd);
|
|
check0 (ip, fp, 70, (mpfr_rnd_t) rnd);
|
|
mpfr_neg (fp, fp, MPFR_RNDN);
|
|
mpfr_neg (ip, ip, MPFR_RNDN);
|
|
}
|
|
}
|
|
|
|
static void
|
|
special (void)
|
|
{
|
|
mpfr_t z, t;
|
|
|
|
mpfr_init (z);
|
|
mpfr_init (t);
|
|
|
|
mpfr_set_nan (z);
|
|
mpfr_frac (t, z, MPFR_RNDN);
|
|
if (!mpfr_nan_p (t))
|
|
{
|
|
printf ("Error for frac(NaN)\n");
|
|
exit (1);
|
|
}
|
|
|
|
mpfr_set_prec (z, 6);
|
|
mpfr_set_prec (t, 3);
|
|
|
|
mpfr_set_str_binary (z, "0.101101E3");
|
|
mpfr_frac (t, z, MPFR_RNDN);
|
|
mpfr_set_str_binary (z, "0.101");
|
|
if (mpfr_cmp (t, z))
|
|
{
|
|
printf ("Error in frac(0.101101E3)\n");
|
|
exit (1);
|
|
}
|
|
|
|
mpfr_set_prec (z, 34);
|
|
mpfr_set_prec (t, 26);
|
|
mpfr_set_str_binary (z, "0.101101010000010011110011001101E9");
|
|
mpfr_frac (t, z, MPFR_RNDN);
|
|
mpfr_set_str_binary (z, "0.000010011110011001101");
|
|
if (mpfr_cmp (t, z))
|
|
{
|
|
printf ("Error in frac(0.101101010000010011110011001101E9)\n");
|
|
exit (1);
|
|
}
|
|
|
|
mpfr_clear (z);
|
|
mpfr_clear (t);
|
|
}
|
|
|
|
static void
|
|
bug20090918 (void)
|
|
{
|
|
mpfr_t x, y, z;
|
|
mp_limb_t y0;
|
|
int inexy, inexz;
|
|
int r, i;
|
|
const char *s[] = { "61680.352935791015625", "61680.999999" };
|
|
mpfr_exp_t emin;
|
|
|
|
emin = mpfr_get_emin ();
|
|
mpfr_init2 (x, 32);
|
|
mpfr_init2 (y, 13);
|
|
|
|
for (i = 0; i <= 9; i++)
|
|
{
|
|
mpfr_set_str (x, s[i & 1], 10, MPFR_RNDZ);
|
|
|
|
RND_LOOP(r)
|
|
{
|
|
set_emin ((i >> 1) - 3);
|
|
inexy = mpfr_frac (y, x, (mpfr_rnd_t) r);
|
|
set_emin (emin);
|
|
y0 = MPFR_MANT(y)[0];
|
|
while (y0 != 0 && (y0 >> 1) << 1 == y0)
|
|
y0 >>= 1;
|
|
if (y0 > 0x2000)
|
|
{
|
|
printf ("Error in bug20090918 (significand has more than"
|
|
" 13 bits), i = %d, %s.\n", i,
|
|
mpfr_print_rnd_mode ((mpfr_rnd_t) r));
|
|
exit (1);
|
|
}
|
|
mpfr_init2 (z, 32);
|
|
inexz = mpfr_frac (z, x, MPFR_RNDN);
|
|
MPFR_ASSERTN (inexz == 0); /* exact */
|
|
inexz = mpfr_prec_round (z, 13, (mpfr_rnd_t) r);
|
|
set_emin ((i >> 1) - 3);
|
|
inexz = mpfr_check_range (z, inexz, (mpfr_rnd_t) r);
|
|
set_emin (emin);
|
|
if (mpfr_cmp0 (y, z) != 0)
|
|
{
|
|
printf ("Error in bug20090918, i = %d, %s.\n", i,
|
|
mpfr_print_rnd_mode ((mpfr_rnd_t) r));
|
|
printf ("Expected ");
|
|
mpfr_dump (z);
|
|
printf ("Got ");
|
|
mpfr_dump (y);
|
|
exit (1);
|
|
}
|
|
if (! SAME_SIGN (inexy, inexz))
|
|
{
|
|
printf ("Incorrect ternary value in bug20090918, i = %d, %s.\n",
|
|
i, mpfr_print_rnd_mode ((mpfr_rnd_t) r));
|
|
printf ("Expected %d, got %d.\n", inexz, inexy);
|
|
exit (1);
|
|
}
|
|
mpfr_clear (z);
|
|
}
|
|
}
|
|
|
|
mpfr_clear (x);
|
|
mpfr_clear (y);
|
|
}
|
|
|
|
#define TEST_FUNCTION mpfr_frac
|
|
#include "tgeneric.c"
|
|
|
|
int
|
|
main (void)
|
|
{
|
|
mpfr_t ip, fp;
|
|
int ni, nf1, nf2;
|
|
|
|
tests_start_mpfr ();
|
|
|
|
special ();
|
|
|
|
mpfr_init2 (ip, PIP);
|
|
mpfr_init2 (fp, PFP);
|
|
|
|
for (ni = -1; ni < PIP; ni++)
|
|
{
|
|
if (ni <= 0)
|
|
{ /* ni + 1 */
|
|
mpfr_set_si (ip, ni, MPFR_RNDN);
|
|
mpfr_add_ui (ip, ip, 1, MPFR_RNDN);
|
|
}
|
|
else
|
|
{ /* 2^ni + 1 */
|
|
mpfr_set_ui (ip, 1, MPFR_RNDN);
|
|
mpfr_mul_2ui (ip, ip, ni, MPFR_RNDN);
|
|
mpfr_add_ui (ip, ip, 1, MPFR_RNDN);
|
|
}
|
|
|
|
mpfr_set_ui (fp, 0, MPFR_RNDN);
|
|
check1 (ip, fp);
|
|
|
|
for (nf1 = 1; nf1 < PFP; nf1++)
|
|
{
|
|
mpfr_set_ui (fp, 1, MPFR_RNDN);
|
|
mpfr_div_2ui (fp, fp, nf1, MPFR_RNDN);
|
|
check1 (ip, fp);
|
|
nf2 = 1 + (randlimb () % (PFP - 1));
|
|
mpfr_set_ui (fp, 1, MPFR_RNDN);
|
|
mpfr_div_2ui (fp, fp, nf2, MPFR_RNDN);
|
|
mpfr_add_ui (fp, fp, 1, MPFR_RNDN);
|
|
mpfr_div_2ui (fp, fp, nf1, MPFR_RNDN);
|
|
check1 (ip, fp);
|
|
}
|
|
}
|
|
|
|
mpfr_set_ui (ip, 1, MPFR_RNDN);
|
|
mpfr_div_ui (ip, ip, 0, MPFR_RNDN);
|
|
mpfr_set_ui (fp, 0, MPFR_RNDN);
|
|
check1 (ip, fp); /* test infinities */
|
|
|
|
mpfr_clear (ip);
|
|
mpfr_clear (fp);
|
|
|
|
bug20090918 ();
|
|
|
|
test_generic (MPFR_PREC_MIN, 1000, 10);
|
|
|
|
tests_end_mpfr ();
|
|
return 0;
|
|
}
|