(root)/
gmp-6.3.0/
tests/
mpf/
t-sub.c
       1  /* Test mpf_sub.
       2  
       3  Copyright 1996, 2001, 2004, 2014 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  
      23  #include "gmp-impl.h"
      24  #include "tests.h"
      25  
      26  #ifndef SIZE
      27  #define SIZE 16
      28  #endif
      29  
      30  void
      31  check_rand (int argc, char **argv)
      32  {
      33    mp_size_t size;
      34    mp_exp_t exp;
      35    int reps = 20000;
      36    int i;
      37    mpf_t u, v, w, wref;
      38    mp_size_t bprec = 100;
      39    mpf_t rerr, max_rerr, limit_rerr;
      40  
      41    if (argc > 1)
      42      {
      43        reps = strtol (argv[1], 0, 0);
      44        if (argc > 2)
      45  	bprec = strtol (argv[2], 0, 0);
      46      }
      47  
      48    mpf_set_default_prec (bprec);
      49  
      50    mpf_init_set_ui (limit_rerr, 1);
      51    mpf_div_2exp (limit_rerr, limit_rerr, bprec);
      52  #if VERBOSE
      53    mpf_dump (limit_rerr);
      54  #endif
      55    mpf_init (rerr);
      56    mpf_init_set_ui (max_rerr, 0);
      57  
      58    mpf_init (u);
      59    mpf_init (v);
      60    mpf_init (w);
      61    mpf_init (wref);
      62    for (i = 0; i < reps; i++)
      63      {
      64        size = urandom () % (2 * SIZE) - SIZE;
      65        exp = urandom () % SIZE;
      66        mpf_random2 (u, size, exp);
      67  
      68        size = urandom () % (2 * SIZE) - SIZE;
      69        exp = urandom () % SIZE;
      70        mpf_random2 (v, size, exp);
      71  
      72        if ((urandom () & 1) != 0)
      73  	mpf_add_ui (u, v, 1);
      74        else if ((urandom () & 1) != 0)
      75  	mpf_sub_ui (u, v, 1);
      76  
      77        mpf_sub (w, u, v);
      78        refmpf_sub (wref, u, v);
      79  
      80        mpf_reldiff (rerr, w, wref);
      81        if (mpf_cmp (rerr, max_rerr) > 0)
      82  	{
      83  	  mpf_set (max_rerr, rerr);
      84  #if VERBOSE
      85  	  mpf_dump (max_rerr);
      86  #endif
      87  	  if (mpf_cmp (rerr, limit_rerr) > 0)
      88  	    {
      89  	      printf ("ERROR after %d tests\n", i);
      90  	      printf ("   u = "); mpf_dump (u);
      91  	      printf ("   v = "); mpf_dump (v);
      92  	      printf ("wref = "); mpf_dump (wref);
      93  	      printf ("   w = "); mpf_dump (w);
      94  	      abort ();
      95  	    }
      96  	}
      97      }
      98  
      99    mpf_clear (limit_rerr);
     100    mpf_clear (rerr);
     101    mpf_clear (max_rerr);
     102  
     103    mpf_clear (u);
     104    mpf_clear (v);
     105    mpf_clear (w);
     106    mpf_clear (wref);
     107  }
     108  
     109  #define W GMP_NUMB_MAX
     110  
     111  void
     112  check_data (void)
     113  {
     114    static const struct {
     115      struct {
     116        int        exp, size;
     117        mp_limb_t  d[10];
     118      } x, y, want;
     119  
     120    } data[] = {
     121      { { 123, 2, { 8, 9 } },             { 123, 1, { 9 } }, { 122, 1, { 8 } } },
     122      { { 1, 1, { 9 } },                  { 1, 1, { 8 } },   { 1, 1, { 1 } } },
     123      { { 1, 1, { 9 } },                 { 1, -1, { 6 } },   { 1, 1, { 15 } } },
     124      { { 1, 2, { 8, 9 } },               { 1, 1, { 8 } },   { 1, 2, { 8, 1 } } },
     125      { { 2, 2, { 8, 1 } },               { 1, 1, { 9 } },   { 1, 1, { W } } },
     126      { { 2, 2, { 9, 8 } },               { 1, 1, { 9 } },   { 2, 1, { 8 } } },
     127      { { 2, 1, { 1 } },                  { 1, 1, { 1 } },   { 1, 1, { W } } },
     128      { { 2, 1, { 9 } },                  { 1, 1, { W } },   { 2, 2, { 1, 8 } } },
     129  
     130      { { 1, 2, { W, 8 } },             { 1, 1, { 9 } },   { 0, -1, { 1 } } },
     131      { { 1, 2, { W, 7 } },             { 1, 1, { 9 } },   { 1, -2, { 1, 1 } } },
     132      { { 1, 2, { 1, 8 } },             { 1, 1, { 9 } },   { 0, -1, { W } } },
     133      { { 1, 2, { 1, 7 } },             { 1, 1, { 9 } },   { 1, -2, { W, 1 } } },
     134      { { 1, 2, { 0, 8 } },             { 1, 1, { 9 } },   { 1, -1, { 1 } } },
     135      { { 2, 3, { 5, 8, 1 } },          { 1, 1, { 9 } },   { 1, 2, { 5, W } } },
     136      { { 3, 1, { 1 } },                { 1, 1, { 1 } },   { 2, 2, { W, W } } },
     137      { { 1, 6, { W, W, W, W, W, 8 } }, { 1, 1, { 9 } },   { -4, -1, { 1 } } },
     138      { { 5, 5, { W-6, W, W, W, W } },  { 6, 1, { 1 } },   { 1, -1, { 7 } } },
     139  
     140      /* f - f == 0, various sizes.
     141         These exercise a past problem (gmp 4.1.3 and earlier) where the
     142         result exponent was not zeroed on a zero result like this.  */
     143      { { 0, 0 }, { 0, 0 }, { 0, 0 } },
     144      { { 99, 3, { 0, 0, 1 } },       { 99, 1, { 1 } },             { 0, 0 } },
     145      { { 99, 3, { 0, 123, 456 } },   { 99, 2, { 123, 456 } },      { 0, 0 } },
     146      { { 99, 3, { 123, 456, 789 } }, { 99, 3, { 123, 456, 789 } }, { 0, 0 } },
     147  
     148      /* High limbs cancel, leaving just the low limbs of the longer operand.
     149         This exercises a past problem (gmp 4.1.3 and earlier) where high zero
     150         limbs on the remainder were not stripped before truncating to the
     151         destination, causing loss of precision.  */
     152      { { 123, 2, { 8, 9 } },             { 123, 1, { 9 } }, { 122, 1, { 8 } } },
     153      { { 123, 3, { 8, 0, 9 } },          { 123, 1, { 9 } }, { 121, 1, { 8 } } },
     154      { { 123, 4, { 8, 0, 0, 9 } },       { 123, 1, { 9 } }, { 120, 1, { 8 } } },
     155      { { 123, 5, { 8, 0, 0, 0, 9 } },    { 123, 1, { 9 } }, { 119, 1, { 8 } } },
     156      { { 123, 6, { 8, 0, 0, 0, 0, 9 } }, { 123, 1, { 9 } }, { 118, 1, { 8 } } },
     157      /* { { 123, 6, { 8, 0, 0, 0, 0, 9 } }, { 123, 6, { 9, 0, 0, 0, 0, 8 } }, { 122, 5, { W, W, W, W, W } } }, */
     158  
     159    };
     160  
     161    mpf_t  x, y, got, want;
     162    int  i, swap, fail;
     163  
     164    fail = 0;
     165    mp_trace_base = 16;
     166    mpf_init (got);
     167  
     168    for (i = 0; i < numberof (data); i++)
     169      {
     170        for (swap = 0; swap <= 7; swap++)
     171          {
     172            PTR(x) = (mp_ptr) data[i].x.d;
     173            SIZ(x) = data[i].x.size;
     174            EXP(x) = data[i].x.exp;
     175            PREC(x) = numberof (data[i].x.d);
     176            MPF_CHECK_FORMAT (x);
     177  
     178            PTR(y) = (mp_ptr) data[i].y.d;
     179            SIZ(y) = data[i].y.size;
     180            EXP(y) = data[i].y.exp;
     181            PREC(y) = numberof (data[i].y.d);
     182            MPF_CHECK_FORMAT (y);
     183  
     184            PTR(want) = (mp_ptr) data[i].want.d;
     185            SIZ(want) = data[i].want.size;
     186            EXP(want) = data[i].want.exp;
     187            PREC(want) = numberof (data[i].want.d);
     188            MPF_CHECK_FORMAT (want);
     189  
     190            if (swap & 4)
     191              {
     192                mpf_swap (want, y);
     193              }
     194  
     195  	  if ((SIZ (x) ^ SIZ (y)) < 0)
     196  	    continue; /* It's an addition, not a subtraction (TO BE REMOVED) */
     197  
     198            if (swap & 1)
     199              {
     200                mpf_swap (x, y);
     201                SIZ(want) = - SIZ(want);
     202              }
     203  
     204            if (swap & 2)
     205              {
     206                SIZ(want) = - SIZ(want);
     207                SIZ(x) = - SIZ(x);
     208                SIZ(y) = - SIZ(y);
     209              }
     210  
     211            mpf_sub (got, x, y);
     212  /*           MPF_CHECK_FORMAT (got); */
     213  
     214            if (! refmpf_validate ("mpf_sub", got, want))
     215              {
     216                printf ("check_data() wrong result at data[%d] (operands%s swapped)\n", i, swap ? "" : " not");
     217                mpf_trace ("x   ", x);
     218                mpf_trace ("y   ", y);
     219                mpf_trace ("got ", got);
     220                mpf_trace ("want", want);
     221  	      fail = 1;
     222              }
     223  
     224  	  if (SIZ (x) == 1 || SIZ (x) == 0 )
     225  	    {
     226  	      if (SIZ (y)) EXP (y) -= EXP (x) - (mp_exp_t) SIZ (x);
     227  	      if (SIZ (want)) EXP (want) -= EXP (x) - (mp_exp_t) SIZ (x);
     228  	      EXP (x) = (mp_exp_t) SIZ (x);
     229  
     230  	      if (mpf_fits_uint_p (x))
     231  		{
     232  		  mpf_ui_sub (got, mpf_get_ui (x), y);
     233  
     234  		  if (! refmpf_validate ("mpf_ui_sub", got, want))
     235  		    {
     236  		      printf ("check_data() wrong result at data[%d] (operands%s swapped)\n", i, swap ? "" : " not");
     237  		      mpf_trace ("x   ", x);
     238  		      mpf_trace ("y   ", y);
     239  		      mpf_trace ("got ", got);
     240  		      mpf_trace ("want", want);
     241  		      fail = 1;
     242  		    }
     243  		}
     244  	    }
     245  
     246  	  if (SIZ (y) == 1 || SIZ (y) == 0)
     247  	    {
     248  	      if (SIZ (x)) EXP (x) -= EXP (y) - (mp_exp_t) SIZ (y);
     249  	      if (SIZ (want)) EXP (want) -= EXP (y) - (mp_exp_t) SIZ (y);
     250  	      EXP (y) = (mp_exp_t) SIZ (y);
     251  
     252  	      if (mpf_fits_uint_p (x))
     253  		{
     254  		  mpf_sub_ui (got, x, mpf_get_ui (y));
     255  
     256  		  if (! refmpf_validate ("mpf_sub_ui", got, want))
     257  		    {
     258  		      printf ("check_data() wrong result at data[%d] (operands%s swapped)\n", i, swap ? "" : " not");
     259  		      mpf_trace ("x   ", x);
     260  		      mpf_trace ("y   ", y);
     261  		      mpf_trace ("got ", got);
     262  		      mpf_trace ("want", want);
     263  		      fail = 1;
     264  		    }
     265  		}
     266  	    }
     267  
     268          }
     269      }
     270  
     271    mpf_clear (got);
     272    if (fail)
     273      abort ();
     274  }
     275  
     276  
     277  int
     278  main (int argc, char **argv)
     279  {
     280    tests_start ();
     281  
     282    check_data ();
     283    check_rand (argc, argv);
     284  
     285    tests_end ();
     286    exit (0);
     287  }