(root)/
gmp-6.3.0/
tests/
mpz/
t-aorsmul.c
       1  /* Test mpz_addmul, mpz_addmul_ui, mpz_submul, mpz_submul_ui.
       2  
       3  Copyright 2001, 2002, 2022 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  
      21  #include <stdio.h>
      22  #include <stdlib.h>
      23  #include <string.h>
      24  
      25  #include "gmp-impl.h"
      26  #include "tests.h"
      27  
      28  
      29  #define M GMP_NUMB_MAX
      30  
      31  
      32  void
      33  check_one_inplace (mpz_srcptr w, mpz_srcptr y)
      34  {
      35    mpz_t  want, got;
      36  
      37    mpz_init (want);
      38    mpz_init (got);
      39  
      40    mpz_mul (want, w, y);
      41    mpz_add (want, w, want);
      42    mpz_set (got, w);
      43    mpz_addmul (got, got, y);
      44    MPZ_CHECK_FORMAT (got);
      45    if (mpz_cmp (want, got) != 0)
      46      {
      47        printf ("mpz_addmul inplace fail\n");
      48      fail:
      49        mpz_trace ("w", w);
      50        mpz_trace ("y", y);
      51        mpz_trace ("want", want);
      52        mpz_trace ("got ", got);
      53        abort ();
      54      }
      55  
      56    mpz_mul (want, w, y);
      57    mpz_sub (want, w, want);
      58    mpz_set (got, w);
      59    mpz_submul (got, got, y);
      60    MPZ_CHECK_FORMAT (got);
      61    if (mpz_cmp (want, got) != 0)
      62      {
      63        printf ("mpz_submul inplace fail\n");
      64        goto fail;
      65      }
      66  
      67    mpz_clear (want);
      68    mpz_clear (got);
      69  }
      70  
      71  void
      72  check_one_ui_inplace (mpz_ptr w, unsigned long y)
      73  {
      74    mpz_t  want, got;
      75  
      76    mpz_init (want);
      77    mpz_init (got);
      78  
      79    mpz_mul_ui (want, w, (unsigned long) y);
      80    mpz_add (want, w, want);
      81    mpz_set (got, w);
      82    mpz_addmul_ui (got, got, (unsigned long) y);
      83    MPZ_CHECK_FORMAT (got);
      84    if (mpz_cmp (want, got) != 0)
      85      {
      86        printf ("mpz_addmul_ui fail\n");
      87      fail:
      88        mpz_trace ("w", w);
      89        printf    ("y=0x%lX   %lu\n", y, y);
      90        mpz_trace ("want", want);
      91        mpz_trace ("got ", got);
      92        abort ();
      93      }
      94  
      95    mpz_mul_ui (want, w, y);
      96    mpz_sub (want, w, want);
      97    mpz_set (got, w);
      98    mpz_submul_ui (got, got, y);
      99    MPZ_CHECK_FORMAT (got);
     100    if (mpz_cmp (want, got) != 0)
     101      {
     102        printf ("mpz_submul_ui fail\n");
     103        goto fail;
     104      }
     105  
     106    mpz_clear (want);
     107    mpz_clear (got);
     108  }
     109  
     110  void
     111  check_all_inplace (mpz_ptr w, mpz_ptr y)
     112  {
     113    int  wneg, yneg;
     114  
     115    MPZ_CHECK_FORMAT (w);
     116    MPZ_CHECK_FORMAT (y);
     117  
     118    for (wneg = 0; wneg < 2; wneg++)
     119      {
     120        for (yneg = 0; yneg < 2; yneg++)
     121          {
     122            check_one_inplace (w, y);
     123  
     124            if (mpz_fits_ulong_p (y))
     125              check_one_ui_inplace (w, mpz_get_ui (y));
     126  
     127            mpz_neg (y, y);
     128          }
     129        mpz_neg (w, w);
     130      }
     131  }
     132  
     133  void
     134  check_one (mpz_srcptr w, mpz_srcptr x, mpz_srcptr y)
     135  {
     136    mpz_t  want, got;
     137  
     138    mpz_init (want);
     139    mpz_init (got);
     140  
     141    mpz_mul (want, x, y);
     142    mpz_add (want, w, want);
     143    mpz_set (got, w);
     144    mpz_addmul (got, x, y);
     145    MPZ_CHECK_FORMAT (got);
     146    if (mpz_cmp (want, got) != 0)
     147      {
     148        printf ("mpz_addmul fail\n");
     149      fail:
     150        mpz_trace ("w", w);
     151        mpz_trace ("x", x);
     152        mpz_trace ("y", y);
     153        mpz_trace ("want", want);
     154        mpz_trace ("got ", got);
     155        abort ();
     156      }
     157  
     158  
     159    mpz_sub (want, want, w);
     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_sqr (mpz_srcptr w, mpz_srcptr x)
     176  {
     177    mpz_t  want, got;
     178  
     179    mpz_init (want);
     180    mpz_init (got);
     181  
     182    mpz_mul (want, x, x);
     183    mpz_add (want, w, want);
     184    mpz_set (got, w);
     185    mpz_addmul (got, x, x);
     186    MPZ_CHECK_FORMAT (got);
     187    if (mpz_cmp (want, got) != 0)
     188      {
     189        printf ("mpz_addmul xx fail\n");
     190      sqrfail:
     191        mpz_trace ("w", w);
     192        mpz_trace ("x", x);
     193        mpz_trace ("want", want);
     194        mpz_trace ("got ", got);
     195        abort ();
     196      }
     197  
     198    mpz_sub (want, want, w);
     199    mpz_sub (want, w, want);
     200    mpz_set (got, w);
     201    mpz_submul (got, x, x);
     202    MPZ_CHECK_FORMAT (got);
     203    if (mpz_cmp (want, got) != 0)
     204      {
     205        printf ("mpz_submul xx fail\n");
     206        goto sqrfail;
     207      }
     208  
     209    mpz_clear (want);
     210    mpz_clear (got);
     211  }
     212  
     213  void
     214  check_one_ui (mpz_ptr w, mpz_ptr x, unsigned long y)
     215  {
     216    mpz_t  want, got;
     217  
     218    mpz_init (want);
     219    mpz_init (got);
     220  
     221    mpz_mul_ui (want, x, (unsigned long) y);
     222    mpz_add (want, w, want);
     223    mpz_set (got, w);
     224    mpz_addmul_ui (got, x, (unsigned long) y);
     225    MPZ_CHECK_FORMAT (got);
     226    if (mpz_cmp (want, got) != 0)
     227      {
     228        printf ("mpz_addmul_ui fail\n");
     229      fail:
     230        mpz_trace ("w", w);
     231        mpz_trace ("x", x);
     232        printf    ("y=0x%lX   %lu\n", y, y);
     233        mpz_trace ("want", want);
     234        mpz_trace ("got ", got);
     235        abort ();
     236      }
     237  
     238    mpz_mul_ui (want, x, y);
     239    mpz_sub (want, w, want);
     240    mpz_set (got, w);
     241    mpz_submul_ui (got, x, y);
     242    MPZ_CHECK_FORMAT (got);
     243    if (mpz_cmp (want, got) != 0)
     244      {
     245        printf ("mpz_submul_ui fail\n");
     246        goto fail;
     247      }
     248  
     249    mpz_clear (want);
     250    mpz_clear (got);
     251  }
     252  
     253  
     254  void
     255  check_all (mpz_ptr w, mpz_ptr x, mpz_ptr y)
     256  {
     257    int    swap, wneg, xneg, yneg;
     258  
     259    MPZ_CHECK_FORMAT (w);
     260    MPZ_CHECK_FORMAT (x);
     261    MPZ_CHECK_FORMAT (y);
     262  
     263    for (swap = 0; swap < 2; swap++)
     264      {
     265        for (wneg = 0; wneg < 2; wneg++)
     266          {
     267            for (xneg = 0; xneg < 2; xneg++)
     268              {
     269                for (yneg = 0; yneg < 2; yneg++)
     270                  {
     271                    check_one (w, x, y);
     272  
     273                    if (mpz_fits_ulong_p (y))
     274                      check_one_ui (w, x, mpz_get_ui (y));
     275  
     276                    mpz_neg (y, y);
     277                  }
     278  
     279  	      check_sqr (w, x);
     280  
     281                mpz_neg (x, x);
     282              }
     283            mpz_neg (w, w);
     284          }
     285        mpz_swap (x, y);
     286      }
     287  }
     288  
     289  void
     290  check_data_inplace_ui (void)
     291  {
     292    static const struct {
     293      mp_limb_t      w[6];
     294      unsigned long  y;
     295  
     296    } data[] = {
     297  
     298      { { 0 }, 0 },
     299      { { 0 }, 1 },
     300      { { 1 }, 1 },
     301      { { 2 }, 1 },
     302  
     303      { { 123 }, 1 },
     304      { { 123 }, ULONG_MAX },
     305      { { M }, 1 },
     306      { { M }, ULONG_MAX },
     307  
     308      { { 123, 456 }, 1 },
     309      { { M, M }, 1 },
     310      { { 123, 456 }, ULONG_MAX },
     311      { { M, M }, ULONG_MAX },
     312  
     313      { { 123, 456, 789 }, 1 },
     314      { { M, M, M }, 1 },
     315      { { 123, 456, 789 }, ULONG_MAX },
     316      { { M, M, M }, ULONG_MAX },
     317    };
     318  
     319    mpz_t  w, y;
     320    int    i;
     321  
     322    mpz_init (w);
     323    mpz_init (y);
     324  
     325    for (i = 0; i < numberof (data); i++)
     326      {
     327        mpz_set_n (w, data[i].w, (mp_size_t) numberof(data[i].w));
     328        mpz_set_ui (y, data[i].y);
     329        check_all_inplace (w, y);
     330      }
     331  
     332    mpz_clear (w);
     333    mpz_clear (y);
     334  }
     335  
     336  void
     337  check_data (void)
     338  {
     339    static const struct {
     340      mp_limb_t  w[6];
     341      mp_limb_t  x[6];
     342      mp_limb_t  y[6];
     343  
     344    } data[] = {
     345  
     346      /* reducing to zero */
     347      { { 1 }, { 1 }, { 1 } },
     348      { { 2 }, { 1 }, { 2 } },
     349      { { 0,1 }, { 0,1 }, { 1 } },
     350  
     351      /* reducing to 1 */
     352      { { 0,1 },       { M },       { 1 } },
     353      { { 0,0,1 },     { M,M },     { 1 } },
     354      { { 0,0,0,1 },   { M,M,M },   { 1 } },
     355      { { 0,0,0,0,1 }, { M,M,M,M }, { 1 } },
     356  
     357      /* reducing to -1 */
     358      { { M },       { 0,1 },       { 1 } },
     359      { { M,M },     { 0,0,1 },     { 1 } },
     360      { { M,M,M },   { 0,0,0,1 },   { 1 } },
     361      { { M,M,M,M }, { 0,0,0,0,1 }, { 1 } },
     362  
     363      /* carry out of addmul */
     364      { { M },     { 1 }, { 1 } },
     365      { { M,M },   { 1 }, { 1 } },
     366      { { M,M,M }, { 1 }, { 1 } },
     367  
     368      /* borrow from submul */
     369      { { 0,1 },     { 1 }, { 1 } },
     370      { { 0,0,1 },   { 1 }, { 1 } },
     371      { { 0,0,0,1 }, { 1 }, { 1 } },
     372  
     373      /* borrow from submul */
     374      { { 0,0,1 },     { 0,1 }, { 1 } },
     375      { { 0,0,0,1 },   { 0,1 }, { 1 } },
     376      { { 0,0,0,0,1 }, { 0,1 }, { 1 } },
     377  
     378      /* more borrow from submul */
     379      { { M }, { 0,1 },       { 1 } },
     380      { { M }, { 0,0,1 },     { 1 } },
     381      { { M }, { 0,0,0,1 },   { 1 } },
     382      { { M }, { 0,0,0,0,1 }, { 1 } },
     383  
     384      /* big borrow from submul */
     385      { { 0,0,1 },     { M,M }, { M } },
     386      { { 0,0,0,1 },   { M,M }, { M } },
     387      { { 0,0,0,0,1 }, { M,M }, { M } },
     388  
     389      /* small w */
     390      { { 0,1 }, { M,M },       { M } },
     391      { { 0,1 }, { M,M,M },     { M } },
     392      { { 0,1 }, { M,M,M,M },   { M } },
     393      { { 0,1 }, { M,M,M,M,M }, { M } },
     394    };
     395  
     396    mpz_t  w, x, y;
     397    int    i;
     398  
     399    mpz_init (w);
     400    mpz_init (x);
     401    mpz_init (y);
     402  
     403    for (i = 0; i < numberof (data); i++)
     404      {
     405        mpz_set_n (w, data[i].w, (mp_size_t) numberof(data[i].w));
     406        mpz_set_n (x, data[i].x, (mp_size_t) numberof(data[i].x));
     407        mpz_set_n (y, data[i].y, (mp_size_t) numberof(data[i].y));
     408        check_all (w, x, y);
     409      }
     410  
     411    mpz_clear (w);
     412    mpz_clear (x);
     413    mpz_clear (y);
     414  }
     415  
     416  
     417  void
     418  check_random (int argc, char *argv[])
     419  {
     420    gmp_randstate_ptr rands = RANDS;
     421    mpz_t  w, x, y;
     422    int    i, reps = 2000;
     423  
     424    mpz_init (w);
     425    mpz_init (x);
     426    mpz_init (y);
     427  
     428    if (argc == 2)
     429      reps = atoi (argv[1]);
     430  
     431    for (i = 0; i < reps; i++)
     432      {
     433        mpz_errandomb (w, rands, 5*GMP_LIMB_BITS);
     434        mpz_errandomb (x, rands, 5*GMP_LIMB_BITS);
     435        mpz_errandomb (y, rands, 5*GMP_LIMB_BITS);
     436        check_all (w, x, y);
     437        check_all_inplace (w, y);
     438  
     439        mpz_errandomb (w, rands, 5*GMP_LIMB_BITS);
     440        mpz_errandomb (x, rands, 5*GMP_LIMB_BITS);
     441        mpz_errandomb (y, rands, BITS_PER_ULONG);
     442        check_all (w, x, y);
     443        check_all_inplace (w, y);
     444      }
     445  
     446    mpz_clear (w);
     447    mpz_clear (x);
     448    mpz_clear (y);
     449  }
     450  
     451  
     452  int
     453  main (int argc, char *argv[])
     454  {
     455    tests_start ();
     456    mp_trace_base = -16;
     457  
     458    check_data ();
     459    check_data_inplace_ui ();
     460    check_random (argc, argv);
     461  
     462    tests_end ();
     463    exit (0);
     464  }