Blame mini-gmp/tests/t-cmp_d.c

Packit 5c3484
/* Test mpz_cmp_d and mpz_cmpabs_d.
Packit 5c3484
Packit 5c3484
Copyright 2001-2003, 2005, 2013 Free Software Foundation, Inc.
Packit 5c3484
Packit 5c3484
This file is part of the GNU MP Library test suite.
Packit 5c3484
Packit 5c3484
The GNU MP Library test suite is free software; you can redistribute it
Packit 5c3484
and/or modify it under the terms of the GNU General Public License as
Packit 5c3484
published by the Free Software Foundation; either version 3 of the License,
Packit 5c3484
or (at your option) any later version.
Packit 5c3484
Packit 5c3484
The GNU MP Library test suite is distributed in the hope that it will be
Packit 5c3484
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 5c3484
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
Packit 5c3484
Public License for more details.
Packit 5c3484
Packit 5c3484
You should have received a copy of the GNU General Public License along with
Packit 5c3484
the GNU MP Library test suite.  If not, see https://www.gnu.org/licenses/.  */
Packit 5c3484
Packit 5c3484
#include <math.h>
Packit 5c3484
Packit 5c3484
#include "testutils.h"
Packit 5c3484
Packit 5c3484
/* FIXME: Not sure if the tests here are exhaustive.  Ought to try to get
Packit 5c3484
   each possible exit from mpz_cmp_d (and mpz_cmpabs_d) exercised.  */
Packit 5c3484
Packit 5c3484
Packit 5c3484
#define SGN(n)  ((n) > 0 ? 1 : (n) < 0 ? -1 : 0)
Packit 5c3484
Packit 5c3484
Packit 5c3484
void
Packit 5c3484
check_one (const char *name, mpz_srcptr x, double y, int cmp, int cmpabs)
Packit 5c3484
{
Packit 5c3484
  int   got;
Packit 5c3484
Packit 5c3484
  got = mpz_cmp_d (x, y);
Packit 5c3484
  if (SGN(got) != cmp)
Packit 5c3484
    {
Packit 5c3484
      unsigned i;
Packit 5c3484
      printf    ("mpz_cmp_d wrong (from %s)\n", name);
Packit 5c3484
      printf    ("  got  %d\n", got);
Packit 5c3484
      printf    ("  want %d\n", cmp);
Packit 5c3484
    fail:
Packit 5c3484
      printf ("  x=");
Packit 5c3484
      mpz_out_str (stdout, 10, x);
Packit 5c3484
      printf    ("\n  y %g\n", y);
Packit 5c3484
      printf ("  x=0x");
Packit 5c3484
      mpz_out_str (stdout, -16, x);
Packit 5c3484
      printf    ("\n  y %g\n", y);
Packit 5c3484
      printf    ("  y");
Packit 5c3484
      for (i = 0; i < sizeof(y); i++)
Packit 5c3484
        printf (" %02X", (unsigned) ((unsigned char *) &y)[i]);
Packit 5c3484
      printf ("\n");
Packit 5c3484
      abort ();
Packit 5c3484
    }
Packit 5c3484
Packit 5c3484
  got = mpz_cmpabs_d (x, y);
Packit 5c3484
  if (SGN(got) != cmpabs)
Packit 5c3484
    {
Packit 5c3484
      printf    ("mpz_cmpabs_d wrong\n");
Packit 5c3484
      printf    ("  got  %d\n", got);
Packit 5c3484
      printf    ("  want %d\n", cmpabs);
Packit 5c3484
      goto fail;
Packit 5c3484
    }
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
void
Packit 5c3484
check_data (void)
Packit 5c3484
{
Packit 5c3484
  static const struct {
Packit 5c3484
    const char  *x;
Packit 5c3484
    double      y;
Packit 5c3484
    int         cmp, cmpabs;
Packit 5c3484
Packit 5c3484
  } data[] = {
Packit 5c3484
Packit 5c3484
    {  "0",  0.0,  0,  0 },
Packit 5c3484
Packit 5c3484
    {  "1",  0.0,  1,  1 },
Packit 5c3484
    { "-1",  0.0, -1,  1 },
Packit 5c3484
Packit 5c3484
    {  "1",  0.5,  1,  1 },
Packit 5c3484
    { "-1", -0.5, -1,  1 },
Packit 5c3484
Packit 5c3484
    {  "0",  1.0, -1, -1 },
Packit 5c3484
    {  "0", -1.0,  1, -1 },
Packit 5c3484
Packit 5c3484
    {  "0x1000000000000000000000000000000000000000000000000", 1.0,  1, 1 },
Packit 5c3484
    { "-0x1000000000000000000000000000000000000000000000000", 1.0, -1, 1 },
Packit 5c3484
Packit 5c3484
    {  "0",  1e100, -1, -1 },
Packit 5c3484
    {  "0", -1e100,  1, -1 },
Packit 5c3484
Packit 5c3484
    {  "2",  1.5,   1,  1 },
Packit 5c3484
    {  "2", -1.5,   1,  1 },
Packit 5c3484
    { "-2",  1.5,  -1,  1 },
Packit 5c3484
    { "-2", -1.5,  -1,  1 },
Packit 5c3484
  };
Packit 5c3484
Packit 5c3484
  mpz_t    x;
Packit 5c3484
  unsigned i;
Packit 5c3484
Packit 5c3484
  mpz_init (x);
Packit 5c3484
Packit 5c3484
  for (i = 0; i < numberof (data); i++)
Packit 5c3484
    {
Packit 5c3484
      mpz_set_str_or_abort (x, data[i].x, 0);
Packit 5c3484
      check_one ("check_data", x, data[i].y, data[i].cmp, data[i].cmpabs);
Packit 5c3484
    }
Packit 5c3484
Packit 5c3484
  mpz_clear (x);
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
Packit 5c3484
/* Equality of integers with up to 53 bits */
Packit 5c3484
void
Packit 5c3484
check_onebits (void)
Packit 5c3484
{
Packit 5c3484
  mpz_t   x, x2;
Packit 5c3484
  double  y;
Packit 5c3484
  int     i;
Packit 5c3484
Packit 5c3484
  mpz_init_set_ui (x, 0L);
Packit 5c3484
  mpz_init (x2);
Packit 5c3484
Packit 5c3484
  for (i = 0; i < 512; i++)
Packit 5c3484
    {
Packit 5c3484
      mpz_mul_2exp (x, x, 1);
Packit 5c3484
      mpz_add_ui (x, x, 1L);
Packit 5c3484
Packit 5c3484
      y = mpz_get_d (x);
Packit 5c3484
      mpz_set_d (x2, y);
Packit 5c3484
Packit 5c3484
      /* stop if any truncation is occurring */
Packit 5c3484
      if (mpz_cmp (x, x2) != 0)
Packit 5c3484
        break;
Packit 5c3484
Packit 5c3484
      check_one ("check_onebits", x, y, 0, 0);
Packit 5c3484
      check_one ("check_onebits", x, -y, 1, 0);
Packit 5c3484
      mpz_neg (x, x);
Packit 5c3484
      check_one ("check_onebits", x, y, -1, 0);
Packit 5c3484
      check_one ("check_onebits", x, -y, 0, 0);
Packit 5c3484
      mpz_neg (x, x);
Packit 5c3484
    }
Packit 5c3484
Packit 5c3484
  mpz_clear (x);
Packit 5c3484
  mpz_clear (x2);
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
Packit 5c3484
/* With the mpz differing by 1, in a limb position possibly below the double */
Packit 5c3484
void
Packit 5c3484
check_low_z_one (void)
Packit 5c3484
{
Packit 5c3484
  mpz_t          x;
Packit 5c3484
  double         y;
Packit 5c3484
  unsigned long  i;
Packit 5c3484
Packit 5c3484
  mpz_init (x);
Packit 5c3484
Packit 5c3484
  /* FIXME: It'd be better to base this on the float format. */
Packit 5c3484
#if defined (__vax) || defined (__vax__)
Packit 5c3484
#define LIM 127			/* vax fp numbers have limited range */
Packit 5c3484
#else
Packit 5c3484
#define LIM 512
Packit 5c3484
#endif
Packit 5c3484
Packit 5c3484
  for (i = 1; i < LIM; i++)
Packit 5c3484
    {
Packit 5c3484
      mpz_set_ui (x, 1L);
Packit 5c3484
      mpz_mul_2exp (x, x, i);
Packit 5c3484
      y = mpz_get_d (x);
Packit 5c3484
Packit 5c3484
      check_one ("check_low_z_one", x, y,   0, 0);
Packit 5c3484
      check_one ("check_low_z_one", x, -y,  1, 0);
Packit 5c3484
      mpz_neg (x, x);
Packit 5c3484
      check_one ("check_low_z_one", x, y,  -1, 0);
Packit 5c3484
      check_one ("check_low_z_one", x, -y,  0, 0);
Packit 5c3484
      mpz_neg (x, x);
Packit 5c3484
Packit 5c3484
      mpz_sub_ui (x, x, 1);
Packit 5c3484
Packit 5c3484
      check_one ("check_low_z_one", x, y,  -1, -1);
Packit 5c3484
      check_one ("check_low_z_one", x, -y,  1, -1);
Packit 5c3484
      mpz_neg (x, x);
Packit 5c3484
      check_one ("check_low_z_one", x, y,  -1, -1);
Packit 5c3484
      check_one ("check_low_z_one", x, -y,  1, -1);
Packit 5c3484
      mpz_neg (x, x);
Packit 5c3484
Packit 5c3484
      mpz_add_ui (x, x, 2);
Packit 5c3484
Packit 5c3484
      check_one ("check_low_z_one", x, y,   1, 1);
Packit 5c3484
      check_one ("check_low_z_one", x, -y,  1, 1);
Packit 5c3484
      mpz_neg (x, x);
Packit 5c3484
      check_one ("check_low_z_one", x, y,  -1, 1);
Packit 5c3484
      check_one ("check_low_z_one", x, -y, -1, 1);
Packit 5c3484
      mpz_neg (x, x);
Packit 5c3484
    }
Packit 5c3484
Packit 5c3484
  mpz_clear (x);
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
/* Comparing 1 and 1+2^-n.  "y" is volatile to make gcc store and fetch it,
Packit 5c3484
   which forces it to a 64-bit double, whereas on x86 it would otherwise
Packit 5c3484
   remain on the float stack as an 80-bit long double.  */
Packit 5c3484
void
Packit 5c3484
check_one_2exp (void)
Packit 5c3484
{
Packit 5c3484
  double           e;
Packit 5c3484
  mpz_t            x;
Packit 5c3484
  volatile double  y;
Packit 5c3484
  int              i;
Packit 5c3484
Packit 5c3484
  mpz_init (x);
Packit 5c3484
Packit 5c3484
  e = 1.0;
Packit 5c3484
  for (i = 0; i < 128; i++)
Packit 5c3484
    {
Packit 5c3484
      e /= 2.0;
Packit 5c3484
      y = 1.0 + e;
Packit 5c3484
      if (y == 1.0)
Packit 5c3484
        break;
Packit 5c3484
Packit 5c3484
      mpz_set_ui (x, 1L);
Packit 5c3484
      check_one ("check_one_2exp", x,  y, -1, -1);
Packit 5c3484
      check_one ("check_one_2exp", x, -y,  1, -1);
Packit 5c3484
Packit 5c3484
      mpz_set_si (x, -1L);
Packit 5c3484
      check_one ("check_one_2exp", x,  y, -1, -1);
Packit 5c3484
      check_one ("check_one_2exp", x, -y,  1, -1);
Packit 5c3484
    }
Packit 5c3484
Packit 5c3484
  mpz_clear (x);
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
void
Packit 5c3484
check_infinity (void)
Packit 5c3484
{
Packit 5c3484
  mpz_t   x;
Packit 5c3484
  double  y = HUGE_VAL;
Packit 5c3484
  if (y != 2*y)
Packit 5c3484
    return;
Packit 5c3484
Packit 5c3484
  mpz_init (x);
Packit 5c3484
Packit 5c3484
  /* 0 cmp inf */
Packit 5c3484
  mpz_set_ui (x, 0L);
Packit 5c3484
  check_one ("check_infinity", x,  y, -1, -1);
Packit 5c3484
  check_one ("check_infinity", x, -y,  1, -1);
Packit 5c3484
Packit 5c3484
  /* 123 cmp inf */
Packit 5c3484
  mpz_set_ui (x, 123L);
Packit 5c3484
  check_one ("check_infinity", x,  y, -1, -1);
Packit 5c3484
  check_one ("check_infinity", x, -y,  1, -1);
Packit 5c3484
Packit 5c3484
  /* -123 cmp inf */
Packit 5c3484
  mpz_set_si (x, -123L);
Packit 5c3484
  check_one ("check_infinity", x,  y, -1, -1);
Packit 5c3484
  check_one ("check_infinity", x, -y,  1, -1);
Packit 5c3484
Packit 5c3484
  /* 2^5000 cmp inf */
Packit 5c3484
  mpz_set_ui (x, 1L);
Packit 5c3484
  mpz_mul_2exp (x, x, 5000L);
Packit 5c3484
  check_one ("check_infinity", x,  y, -1, -1);
Packit 5c3484
  check_one ("check_infinity", x, -y,  1, -1);
Packit 5c3484
Packit 5c3484
  /* -2^5000 cmp inf */
Packit 5c3484
  mpz_neg (x, x);
Packit 5c3484
  check_one ("check_infinity", x,  y, -1, -1);
Packit 5c3484
  check_one ("check_infinity", x, -y,  1, -1);
Packit 5c3484
Packit 5c3484
  mpz_clear (x);
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
void
Packit 5c3484
testmain (int argc, char *argv[])
Packit 5c3484
{
Packit 5c3484
  check_data ();
Packit 5c3484
  check_onebits ();
Packit 5c3484
  check_low_z_one ();
Packit 5c3484
  check_one_2exp ();
Packit 5c3484
  check_infinity ();
Packit 5c3484
}