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