Home | History | Annotate | Line # | Download | only in mpz
t-aorsmul.c revision 1.1.1.1
      1 /* Test mpz_addmul, mpz_addmul_ui, mpz_submul, mpz_submul_ui.
      2 
      3 Copyright 2001, 2002 Free Software Foundation, Inc.
      4 
      5 This file is part of the GNU MP Library.
      6 
      7 The GNU MP Library is free software; you can redistribute it and/or modify
      8 it under the terms of the GNU Lesser General Public License as published by
      9 the Free Software Foundation; either version 3 of the License, or (at your
     10 option) any later version.
     11 
     12 The GNU MP Library is distributed in the hope that it will be useful, but
     13 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     14 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
     15 License for more details.
     16 
     17 You should have received a copy of the GNU Lesser General Public License
     18 along with the GNU MP Library.  If not, see http://www.gnu.org/licenses/.  */
     19 
     20 
     21 #include <stdio.h>
     22 #include <stdlib.h>
     23 #include <string.h>
     24 
     25 #include "gmp.h"
     26 #include "gmp-impl.h"
     27 #include "tests.h"
     28 
     29 
     30 #define M GMP_NUMB_MAX
     31 
     32 
     33 void
     34 check_one_inplace (mpz_srcptr w, mpz_srcptr y)
     35 {
     36   mpz_t  want, got;
     37 
     38   mpz_init (want);
     39   mpz_init (got);
     40 
     41   mpz_mul (want, w, y);
     42   mpz_add (want, w, want);
     43   mpz_set (got, w);
     44   mpz_addmul (got, got, y);
     45   MPZ_CHECK_FORMAT (got);
     46   if (mpz_cmp (want, got) != 0)
     47     {
     48       printf ("mpz_addmul inplace fail\n");
     49     fail:
     50       mpz_trace ("w", w);
     51       mpz_trace ("y", y);
     52       mpz_trace ("want", want);
     53       mpz_trace ("got ", got);
     54       abort ();
     55     }
     56 
     57   mpz_mul (want, w, y);
     58   mpz_sub (want, w, want);
     59   mpz_set (got, w);
     60   mpz_submul (got, got, y);
     61   MPZ_CHECK_FORMAT (got);
     62   if (mpz_cmp (want, got) != 0)
     63     {
     64       printf ("mpz_submul inplace fail\n");
     65       goto fail;
     66     }
     67 
     68   mpz_clear (want);
     69   mpz_clear (got);
     70 }
     71 
     72 void
     73 check_one_ui_inplace (mpz_ptr w, unsigned long y)
     74 {
     75   mpz_t  want, got;
     76 
     77   mpz_init (want);
     78   mpz_init (got);
     79 
     80   mpz_mul_ui (want, w, (unsigned long) y);
     81   mpz_add (want, w, want);
     82   mpz_set (got, w);
     83   mpz_addmul_ui (got, got, (unsigned long) y);
     84   MPZ_CHECK_FORMAT (got);
     85   if (mpz_cmp (want, got) != 0)
     86     {
     87       printf ("mpz_addmul_ui fail\n");
     88     fail:
     89       mpz_trace ("w", w);
     90       printf    ("y=0x%lX   %lu\n", y, y);
     91       mpz_trace ("want", want);
     92       mpz_trace ("got ", got);
     93       abort ();
     94     }
     95 
     96   mpz_mul_ui (want, w, y);
     97   mpz_sub (want, w, want);
     98   mpz_set (got, w);
     99   mpz_submul_ui (got, got, y);
    100   MPZ_CHECK_FORMAT (got);
    101   if (mpz_cmp (want, got) != 0)
    102     {
    103       printf ("mpz_submul_ui fail\n");
    104       goto fail;
    105     }
    106 
    107   mpz_clear (want);
    108   mpz_clear (got);
    109 }
    110 
    111 void
    112 check_all_inplace (mpz_ptr w, mpz_ptr y)
    113 {
    114   int  wneg, yneg;
    115 
    116   MPZ_CHECK_FORMAT (w);
    117   MPZ_CHECK_FORMAT (y);
    118 
    119   for (wneg = 0; wneg < 2; wneg++)
    120     {
    121       for (yneg = 0; yneg < 2; yneg++)
    122         {
    123           check_one_inplace (w, y);
    124 
    125           if (mpz_fits_ulong_p (y))
    126             check_one_ui_inplace (w, mpz_get_ui (y));
    127 
    128           mpz_neg (y, y);
    129         }
    130       mpz_neg (w, w);
    131     }
    132 }
    133 
    134 void
    135 check_one (mpz_srcptr w, mpz_srcptr x, mpz_srcptr y)
    136 {
    137   mpz_t  want, got;
    138 
    139   mpz_init (want);
    140   mpz_init (got);
    141 
    142   mpz_mul (want, x, y);
    143   mpz_add (want, w, want);
    144   mpz_set (got, w);
    145   mpz_addmul (got, x, y);
    146   MPZ_CHECK_FORMAT (got);
    147   if (mpz_cmp (want, got) != 0)
    148     {
    149       printf ("mpz_addmul fail\n");
    150     fail:
    151       mpz_trace ("w", w);
    152       mpz_trace ("x", x);
    153       mpz_trace ("y", y);
    154       mpz_trace ("want", want);
    155       mpz_trace ("got ", got);
    156       abort ();
    157     }
    158 
    159   mpz_mul (want, x, y);
    160   mpz_sub (want, w, want);
    161   mpz_set (got, w);
    162   mpz_submul (got, x, y);
    163   MPZ_CHECK_FORMAT (got);
    164   if (mpz_cmp (want, got) != 0)
    165     {
    166       printf ("mpz_submul fail\n");
    167       goto fail;
    168     }
    169 
    170   mpz_clear (want);
    171   mpz_clear (got);
    172 }
    173 
    174 void
    175 check_one_ui (mpz_ptr w, mpz_ptr x, unsigned long y)
    176 {
    177   mpz_t  want, got;
    178 
    179   mpz_init (want);
    180   mpz_init (got);
    181 
    182   mpz_mul_ui (want, x, (unsigned long) y);
    183   mpz_add (want, w, want);
    184   mpz_set (got, w);
    185   mpz_addmul_ui (got, x, (unsigned long) y);
    186   MPZ_CHECK_FORMAT (got);
    187   if (mpz_cmp (want, got) != 0)
    188     {
    189       printf ("mpz_addmul_ui fail\n");
    190     fail:
    191       mpz_trace ("w", w);
    192       mpz_trace ("x", x);
    193       printf    ("y=0x%lX   %lu\n", y, y);
    194       mpz_trace ("want", want);
    195       mpz_trace ("got ", got);
    196       abort ();
    197     }
    198 
    199   mpz_mul_ui (want, x, y);
    200   mpz_sub (want, w, want);
    201   mpz_set (got, w);
    202   mpz_submul_ui (got, x, y);
    203   MPZ_CHECK_FORMAT (got);
    204   if (mpz_cmp (want, got) != 0)
    205     {
    206       printf ("mpz_submul_ui fail\n");
    207       goto fail;
    208     }
    209 
    210   mpz_clear (want);
    211   mpz_clear (got);
    212 }
    213 
    214 
    215 void
    216 check_all (mpz_ptr w, mpz_ptr x, mpz_ptr y)
    217 {
    218   int    swap, wneg, xneg, yneg;
    219 
    220   MPZ_CHECK_FORMAT (w);
    221   MPZ_CHECK_FORMAT (x);
    222   MPZ_CHECK_FORMAT (y);
    223 
    224   for (swap = 0; swap < 2; swap++)
    225     {
    226       for (wneg = 0; wneg < 2; wneg++)
    227         {
    228           for (xneg = 0; xneg < 2; xneg++)
    229             {
    230               for (yneg = 0; yneg < 2; yneg++)
    231                 {
    232                   check_one (w, x, y);
    233 
    234                   if (mpz_fits_ulong_p (y))
    235                     check_one_ui (w, x, mpz_get_ui (y));
    236 
    237                   mpz_neg (y, y);
    238                 }
    239               mpz_neg (x, x);
    240             }
    241           mpz_neg (w, w);
    242         }
    243       mpz_swap (x, y);
    244     }
    245 }
    246 
    247 void
    248 check_data_inplace_ui (void)
    249 {
    250   static const struct {
    251     mp_limb_t      w[6];
    252     unsigned long  y;
    253 
    254   } data[] = {
    255 
    256     { { 0 }, 0 },
    257     { { 0 }, 1 },
    258     { { 1 }, 1 },
    259     { { 2 }, 1 },
    260 
    261     { { 123 }, 1 },
    262     { { 123 }, ULONG_MAX },
    263     { { M }, 1 },
    264     { { M }, ULONG_MAX },
    265 
    266     { { 123, 456 }, 1 },
    267     { { M, M }, 1 },
    268     { { 123, 456 }, ULONG_MAX },
    269     { { M, M }, ULONG_MAX },
    270 
    271     { { 123, 456, 789 }, 1 },
    272     { { M, M, M }, 1 },
    273     { { 123, 456, 789 }, ULONG_MAX },
    274     { { M, M, M }, ULONG_MAX },
    275   };
    276 
    277   mpz_t  w, y;
    278   int    i;
    279 
    280   mpz_init (w);
    281   mpz_init (y);
    282 
    283   for (i = 0; i < numberof (data); i++)
    284     {
    285       mpz_set_n (w, data[i].w, (mp_size_t) numberof(data[i].w));
    286       mpz_set_ui (y, data[i].y);
    287       check_all_inplace (w, y);
    288     }
    289 
    290   mpz_clear (w);
    291   mpz_clear (y);
    292 }
    293 
    294 void
    295 check_data (void)
    296 {
    297   static const struct {
    298     mp_limb_t  w[6];
    299     mp_limb_t  x[6];
    300     mp_limb_t  y[6];
    301 
    302   } data[] = {
    303 
    304     /* reducing to zero */
    305     { { 1 }, { 1 }, { 1 } },
    306     { { 2 }, { 1 }, { 2 } },
    307     { { 0,1 }, { 0,1 }, { 1 } },
    308 
    309     /* reducing to 1 */
    310     { { 0,1 },       { M },       { 1 } },
    311     { { 0,0,1 },     { M,M },     { 1 } },
    312     { { 0,0,0,1 },   { M,M,M },   { 1 } },
    313     { { 0,0,0,0,1 }, { M,M,M,M }, { 1 } },
    314 
    315     /* reducing to -1 */
    316     { { M },       { 0,1 },       { 1 } },
    317     { { M,M },     { 0,0,1 },     { 1 } },
    318     { { M,M,M },   { 0,0,0,1 },   { 1 } },
    319     { { M,M,M,M }, { 0,0,0,0,1 }, { 1 } },
    320 
    321     /* carry out of addmul */
    322     { { M },     { 1 }, { 1 } },
    323     { { M,M },   { 1 }, { 1 } },
    324     { { M,M,M }, { 1 }, { 1 } },
    325 
    326     /* borrow from submul */
    327     { { 0,1 },     { 1 }, { 1 } },
    328     { { 0,0,1 },   { 1 }, { 1 } },
    329     { { 0,0,0,1 }, { 1 }, { 1 } },
    330 
    331     /* borrow from submul */
    332     { { 0,0,1 },     { 0,1 }, { 1 } },
    333     { { 0,0,0,1 },   { 0,1 }, { 1 } },
    334     { { 0,0,0,0,1 }, { 0,1 }, { 1 } },
    335 
    336     /* more borrow from submul */
    337     { { M }, { 0,1 },       { 1 } },
    338     { { M }, { 0,0,1 },     { 1 } },
    339     { { M }, { 0,0,0,1 },   { 1 } },
    340     { { M }, { 0,0,0,0,1 }, { 1 } },
    341 
    342     /* big borrow from submul */
    343     { { 0,0,1 },     { M,M }, { M } },
    344     { { 0,0,0,1 },   { M,M }, { M } },
    345     { { 0,0,0,0,1 }, { M,M }, { M } },
    346 
    347     /* small w */
    348     { { 0,1 }, { M,M },       { M } },
    349     { { 0,1 }, { M,M,M },     { M } },
    350     { { 0,1 }, { M,M,M,M },   { M } },
    351     { { 0,1 }, { M,M,M,M,M }, { M } },
    352   };
    353 
    354   mpz_t  w, x, y;
    355   int    i;
    356 
    357   mpz_init (w);
    358   mpz_init (x);
    359   mpz_init (y);
    360 
    361   for (i = 0; i < numberof (data); i++)
    362     {
    363       mpz_set_n (w, data[i].w, (mp_size_t) numberof(data[i].w));
    364       mpz_set_n (x, data[i].x, (mp_size_t) numberof(data[i].x));
    365       mpz_set_n (y, data[i].y, (mp_size_t) numberof(data[i].y));
    366       check_all (w, x, y);
    367     }
    368 
    369   mpz_clear (w);
    370   mpz_clear (x);
    371   mpz_clear (y);
    372 }
    373 
    374 
    375 void
    376 check_random (int argc, char *argv[])
    377 {
    378   gmp_randstate_ptr rands = RANDS;
    379   mpz_t  w, x, y;
    380   int    i, reps = 2000;
    381 
    382   mpz_init (w);
    383   mpz_init (x);
    384   mpz_init (y);
    385 
    386   if (argc == 2)
    387     reps = atoi (argv[1]);
    388 
    389   for (i = 0; i < reps; i++)
    390     {
    391       mpz_errandomb (w, rands, 5*GMP_LIMB_BITS);
    392       mpz_errandomb (x, rands, 5*GMP_LIMB_BITS);
    393       mpz_errandomb (y, rands, 5*GMP_LIMB_BITS);
    394       check_all (w, x, y);
    395       check_all_inplace (w, y);
    396 
    397       mpz_errandomb (w, rands, 5*GMP_LIMB_BITS);
    398       mpz_errandomb (x, rands, 5*GMP_LIMB_BITS);
    399       mpz_errandomb (y, rands, BITS_PER_ULONG);
    400       check_all (w, x, y);
    401       check_all_inplace (w, y);
    402     }
    403 
    404   mpz_clear (w);
    405   mpz_clear (x);
    406   mpz_clear (y);
    407 }
    408 
    409 
    410 int
    411 main (int argc, char *argv[])
    412 {
    413   tests_start ();
    414   mp_trace_base = -16;
    415 
    416   check_data ();
    417   check_data_inplace_ui ();
    418   check_random (argc, argv);
    419 
    420   tests_end ();
    421   exit (0);
    422 }
    423