(root)/
gmp-6.3.0/
mini-gmp/
tests/
t-cmp_d.c
       1  /* Test mpz_cmp_d and mpz_cmpabs_d.
       2  
       3  Copyright 2001-2003, 2005, 2013 Free Software Foundation, Inc.
       4  
       5  This file is part of the GNU MP Library test suite.
       6  
       7  The GNU MP Library test suite is free software; you can redistribute it
       8  and/or modify it under the terms of the GNU General Public License as
       9  published by the Free Software Foundation; either version 3 of the License,
      10  or (at your option) any later version.
      11  
      12  The GNU MP Library test suite is distributed in the hope that it will be
      13  useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
      14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
      15  Public License for more details.
      16  
      17  You should have received a copy of the GNU General Public License along with
      18  the GNU MP Library test suite.  If not, see https://www.gnu.org/licenses/.  */
      19  
      20  #include <math.h>
      21  
      22  #include "testutils.h"
      23  
      24  /* FIXME: Not sure if the tests here are exhaustive.  Ought to try to get
      25     each possible exit from mpz_cmp_d (and mpz_cmpabs_d) exercised.  */
      26  
      27  
      28  #define SGN(n)  ((n) > 0 ? 1 : (n) < 0 ? -1 : 0)
      29  
      30  
      31  void
      32  check_one (const char *name, mpz_srcptr x, double y, int cmp, int cmpabs)
      33  {
      34    int   got;
      35  
      36    got = mpz_cmp_d (x, y);
      37    if (SGN(got) != cmp)
      38      {
      39        unsigned i;
      40        printf    ("mpz_cmp_d wrong (from %s)\n", name);
      41        printf    ("  got  %d\n", got);
      42        printf    ("  want %d\n", cmp);
      43      fail:
      44        printf ("  x=");
      45        mpz_out_str (stdout, 10, x);
      46        printf    ("\n  y %g\n", y);
      47        printf ("  x=0x");
      48        mpz_out_str (stdout, -16, x);
      49        printf    ("\n  y %g\n", y);
      50        printf    ("  y");
      51        for (i = 0; i < sizeof(y); i++)
      52          printf (" %02X", (unsigned) ((unsigned char *) &y)[i]);
      53        printf ("\n");
      54        abort ();
      55      }
      56  
      57    got = mpz_cmpabs_d (x, y);
      58    if (SGN(got) != cmpabs)
      59      {
      60        printf    ("mpz_cmpabs_d wrong\n");
      61        printf    ("  got  %d\n", got);
      62        printf    ("  want %d\n", cmpabs);
      63        goto fail;
      64      }
      65  }
      66  
      67  void
      68  check_data (void)
      69  {
      70    static const struct {
      71      const char  *x;
      72      double      y;
      73      int         cmp, cmpabs;
      74  
      75    } data[] = {
      76  
      77      {  "0",  0.0,  0,  0 },
      78  
      79      {  "1",  0.0,  1,  1 },
      80      { "-1",  0.0, -1,  1 },
      81  
      82      {  "1",  0.5,  1,  1 },
      83      { "-1", -0.5, -1,  1 },
      84  
      85      {  "0",  1.0, -1, -1 },
      86      {  "0", -1.0,  1, -1 },
      87  
      88      {  "0x1000000000000000000000000000000000000000000000000", 1.0,  1, 1 },
      89      { "-0x1000000000000000000000000000000000000000000000000", 1.0, -1, 1 },
      90  
      91      {  "0",  1e100, -1, -1 },
      92      {  "0", -1e100,  1, -1 },
      93  
      94      {  "2",  1.5,   1,  1 },
      95      {  "2", -1.5,   1,  1 },
      96      { "-2",  1.5,  -1,  1 },
      97      { "-2", -1.5,  -1,  1 },
      98    };
      99  
     100    mpz_t    x;
     101    unsigned i;
     102  
     103    mpz_init (x);
     104  
     105    for (i = 0; i < numberof (data); i++)
     106      {
     107        mpz_set_str_or_abort (x, data[i].x, 0);
     108        check_one ("check_data", x, data[i].y, data[i].cmp, data[i].cmpabs);
     109      }
     110  
     111    mpz_clear (x);
     112  }
     113  
     114  
     115  /* Equality of integers with up to 53 bits */
     116  void
     117  check_onebits (void)
     118  {
     119    mpz_t   x, x2;
     120    double  y;
     121    int     i;
     122  
     123    mpz_init_set_ui (x, 0L);
     124    mpz_init (x2);
     125  
     126    for (i = 0; i < 512; i++)
     127      {
     128        mpz_mul_2exp (x, x, 1);
     129        mpz_add_ui (x, x, 1L);
     130  
     131        y = mpz_get_d (x);
     132        mpz_set_d (x2, y);
     133  
     134        /* stop if any truncation is occurring */
     135        if (mpz_cmp (x, x2) != 0)
     136          break;
     137  
     138        check_one ("check_onebits", x, y, 0, 0);
     139        check_one ("check_onebits", x, -y, 1, 0);
     140        mpz_neg (x, x);
     141        check_one ("check_onebits", x, y, -1, 0);
     142        check_one ("check_onebits", x, -y, 0, 0);
     143        mpz_neg (x, x);
     144      }
     145  
     146    mpz_clear (x);
     147    mpz_clear (x2);
     148  }
     149  
     150  
     151  /* With the mpz differing by 1, in a limb position possibly below the double */
     152  void
     153  check_low_z_one (void)
     154  {
     155    mpz_t          x;
     156    double         y;
     157    unsigned long  i;
     158  
     159    mpz_init (x);
     160  
     161    /* FIXME: It'd be better to base this on the float format. */
     162  #if defined (__vax) || defined (__vax__)
     163  #define LIM 127			/* vax fp numbers have limited range */
     164  #else
     165  #define LIM 512
     166  #endif
     167  
     168    for (i = 1; i < LIM; i++)
     169      {
     170        mpz_set_ui (x, 1L);
     171        mpz_mul_2exp (x, x, i);
     172        y = mpz_get_d (x);
     173  
     174        check_one ("check_low_z_one", x, y,   0, 0);
     175        check_one ("check_low_z_one", x, -y,  1, 0);
     176        mpz_neg (x, x);
     177        check_one ("check_low_z_one", x, y,  -1, 0);
     178        check_one ("check_low_z_one", x, -y,  0, 0);
     179        mpz_neg (x, x);
     180  
     181        mpz_sub_ui (x, x, 1);
     182  
     183        check_one ("check_low_z_one", x, y,  -1, -1);
     184        check_one ("check_low_z_one", x, -y,  1, -1);
     185        mpz_neg (x, x);
     186        check_one ("check_low_z_one", x, y,  -1, -1);
     187        check_one ("check_low_z_one", x, -y,  1, -1);
     188        mpz_neg (x, x);
     189  
     190        mpz_add_ui (x, x, 2);
     191  
     192        check_one ("check_low_z_one", x, y,   1, 1);
     193        check_one ("check_low_z_one", x, -y,  1, 1);
     194        mpz_neg (x, x);
     195        check_one ("check_low_z_one", x, y,  -1, 1);
     196        check_one ("check_low_z_one", x, -y, -1, 1);
     197        mpz_neg (x, x);
     198      }
     199  
     200    mpz_clear (x);
     201  }
     202  
     203  /* Comparing 1 and 1+2^-n.  "y" is volatile to make gcc store and fetch it,
     204     which forces it to a 64-bit double, whereas on x86 it would otherwise
     205     remain on the float stack as an 80-bit long double.  */
     206  void
     207  check_one_2exp (void)
     208  {
     209    double           e;
     210    mpz_t            x;
     211    volatile double  y;
     212    int              i;
     213  
     214    mpz_init (x);
     215  
     216    e = 1.0;
     217    for (i = 0; i < 128; i++)
     218      {
     219        e /= 2.0;
     220        y = 1.0 + e;
     221        if (y == 1.0)
     222          break;
     223  
     224        mpz_set_ui (x, 1L);
     225        check_one ("check_one_2exp", x,  y, -1, -1);
     226        check_one ("check_one_2exp", x, -y,  1, -1);
     227  
     228        mpz_set_si (x, -1L);
     229        check_one ("check_one_2exp", x,  y, -1, -1);
     230        check_one ("check_one_2exp", x, -y,  1, -1);
     231      }
     232  
     233    mpz_clear (x);
     234  }
     235  
     236  void
     237  check_infinity (void)
     238  {
     239    mpz_t   x;
     240    double  y = HUGE_VAL;
     241    if (y != 2*y)
     242      return;
     243  
     244    mpz_init (x);
     245  
     246    /* 0 cmp inf */
     247    mpz_set_ui (x, 0L);
     248    check_one ("check_infinity", x,  y, -1, -1);
     249    check_one ("check_infinity", x, -y,  1, -1);
     250  
     251    /* 123 cmp inf */
     252    mpz_set_ui (x, 123L);
     253    check_one ("check_infinity", x,  y, -1, -1);
     254    check_one ("check_infinity", x, -y,  1, -1);
     255  
     256    /* -123 cmp inf */
     257    mpz_set_si (x, -123L);
     258    check_one ("check_infinity", x,  y, -1, -1);
     259    check_one ("check_infinity", x, -y,  1, -1);
     260  
     261    /* 2^5000 cmp inf */
     262    mpz_set_ui (x, 1L);
     263    mpz_mul_2exp (x, x, 5000L);
     264    check_one ("check_infinity", x,  y, -1, -1);
     265    check_one ("check_infinity", x, -y,  1, -1);
     266  
     267    /* -2^5000 cmp inf */
     268    mpz_neg (x, x);
     269    check_one ("check_infinity", x,  y, -1, -1);
     270    check_one ("check_infinity", x, -y,  1, -1);
     271  
     272    mpz_clear (x);
     273  }
     274  
     275  void
     276  testmain (int argc, char *argv[])
     277  {
     278    check_data ();
     279    check_onebits ();
     280    check_low_z_one ();
     281    check_one_2exp ();
     282    check_infinity ();
     283  }