Copyright 2000-2003, 2005, 2013, 2015, 2019 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it and/or modify it under the terms of the GNU 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 MP Library test suite 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 General Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#if HAVE_FLOAT_H #include <float.h> /* for DBL_MANT_DIG */ #endif
#if TIME_WITH_SYS_TIME # include <sys/time.h> /* for struct timeval */ # include <time.h> #else # if HAVE_SYS_TIME_H # include <sys/time.h> # else # include <time.h> # endif #endif
#include"gmp-impl.h" #include"tests.h"
/* The various tests setups and final checks, collected up together. */ void
tests_start (void)
{ char version[10];
snprintf (version, 10, "%u.%u.%u",
__GNU_MP_VERSION,
__GNU_MP_VERSION_MINOR,
__GNU_MP_VERSION_PATCHLEVEL);
if (strcmp (gmp_version, version) != 0)
{
fprintf (stderr, "tests are not linked to the newly compiled library\n");
fprintf (stderr, " local version is: %s\n", version);
fprintf (stderr, " linked version is: %s\n", gmp_version);
abort ();
}
/* don't buffer, so output is not lost if a test causes a segv etc */
setbuf (stdout, NULL);
setbuf (stderr, NULL);
if (__gmp_rands_initialized)
{
printf ("Please let tests_start() initialize the global __gmp_rands.\n");
printf ("ie. ensure that function is called before the first use of RANDS.\n");
abort ();
}
/* Only used if CPU calling conventions checking is available. */
mp_limb_t (*calling_conventions_function) (ANYARGS);
/* Return p advanced to the next multiple of "align" bytes. "align" must be a power of 2. Care is taken not to assume sizeof(int)==sizeof(pointer).
Using "unsigned long" avoids a warning on hpux. */ void *
align_pointer (void *p, size_t align)
{
gmp_intptr_t d;
d = ((gmp_intptr_t) p) & (align-1);
d = (d != 0 ? align-d : 0); return (void *) (((char *) p) + d);
}
/* Note that memory allocated with this function can never be freed, because
the start address of the block allocated is lost. */ void *
__gmp_allocate_func_aligned (size_t bytes, size_t align)
{ return align_pointer ((*__gmp_allocate_func) (bytes + align-1), align);
}
/* Whether the absolute value of z is a power of 2. */ int
mpz_pow2abs_p (mpz_srcptr z)
{
mp_size_t size, i;
mp_srcptr ptr;
size = SIZ (z); if (size == 0) return 0; /* zero is not a power of 2 */
size = ABS (size);
ptr = PTR (z); for (i = 0; i < size-1; i++) if (ptr[i] != 0) return 0; /* non-zero low limb means not a power of 2 */
return POW2_P (ptr[i]); /* high limb power of 2 */
}
/* Exponentially distributed between 0 and 2^nbits-1, meaning the number of bits in the result is uniformly distributed between 0 and nbits-1.
FIXME: This is not a proper exponential distribution, since the probability function will have a stepped shape due to using a uniform
distribution after choosing how many bits. */
/* Return +infinity if available, or 0 if not. We don't want to use libm, so INFINITY or other system values are not
used here. */ double
tests_infinity_d (void)
{ #if _GMP_IEEE_FLOATS union ieee_double_extract x;
x.s.exp = 2047;
x.s.manl = 0;
x.s.manh = 0;
x.s.sig = 0; return x.d; #else return 0; #endif
}
/* Return non-zero if d is an infinity (either positive or negative).
Don't want libm, so don't use isinf() or other system tests. */ int
tests_isinf (double d)
{ #if _GMP_IEEE_FLOATS union ieee_double_extract x;
x.d = d; return (x.s.exp == 2047 && x.s.manl == 0 && x.s.manh == 0); #else return 0; #endif
}
/* Set the hardware floating point rounding mode. Same mode values as mpfr, namely 0=nearest, 1=tozero, 2=up, 3=down. Return 1 if successful, 0 if
not. */ int
tests_hardware_setround (int mode)
{ #if ! defined NO_ASM && HAVE_HOST_CPU_FAMILY_x86 int rc; switch (mode) { case 0: rc = 0; break; /* nearest */ case 1: rc = 3; break; /* tozero */ case 2: rc = 2; break; /* up */ case 3: rc = 1; break; /* down */ default: return 0;
}
x86_fldcw ((x86_fstcw () & ~0xC00) | (rc << 10)); return 1; #endif
return 0;
}
/* Return the hardware floating point rounding mode, or -1 if unknown. */ int
tests_hardware_getround (void)
{ #if ! defined NO_ASM && HAVE_HOST_CPU_FAMILY_x86 switch ((x86_fstcw () & ~0xC00) >> 10) { case 0: return 0; break; /* nearest */ case 1: return 3; break; /* down */ case 2: return 2; break; /* up */ case 3: return 1; break; /* tozero */
} #endif
return -1;
}
/* tests_dbl_mant_bits() determines by experiment the number of bits in the mantissa of a "double". If it's not possible to find a value (perhaps due to the compiler optimizing too aggressively), then return 0.
This code is used rather than DBL_MANT_DIG from <float.h> since ancient systems like SunOS don't have that file, and since one GNU/Linux ARM system was seen where the float emulation seemed to have only 32 working
bits, not the 53 float.h claimed. */
int
tests_dbl_mant_bits (void)
{ staticint n = -1; volatiledouble x, y, d;
if (n != -1) return n;
n = 1;
x = 2.0; for (;;)
{ /* see if 2^(n+1)+1 can be formed without rounding, if so then
continue, if not then "n" is the answer */
y = x + 1.0;
d = y - x; if (d != 1.0)
{ #ifdefined (DBL_MANT_DIG) && DBL_RADIX == 2 if (n != DBL_MANT_DIG)
printf ("Warning, tests_dbl_mant_bits got %d but DBL_MANT_DIG says %d\n", n, DBL_MANT_DIG); #endif break;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.