github.com/aergoio/aergo@v1.3.1/libtool/src/gmp-6.1.2/tests/mpz/t-mul.c (about)

     1  /* Test mpz_cmp, mpz_mul.
     2  
     3  Copyright 1991, 1993, 1994, 1996, 1997, 2000-2004 Free Software Foundation,
     4  Inc.
     5  
     6  This file is part of the GNU MP Library test suite.
     7  
     8  The GNU MP Library test suite is free software; you can redistribute it
     9  and/or modify it under the terms of the GNU General Public License as
    10  published by the Free Software Foundation; either version 3 of the License,
    11  or (at your option) any later version.
    12  
    13  The GNU MP Library test suite is distributed in the hope that it will be
    14  useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
    15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
    16  Public License for more details.
    17  
    18  You should have received a copy of the GNU General Public License along with
    19  the GNU MP Library test suite.  If not, see https://www.gnu.org/licenses/.  */
    20  
    21  #include <stdio.h>
    22  #include <stdlib.h>
    23  
    24  #include "gmp.h"
    25  #include "gmp-impl.h"
    26  #include "longlong.h"
    27  #include "tests.h"
    28  
    29  void debug_mp (mpz_t);
    30  static void refmpz_mul (mpz_t, const mpz_t, const mpz_t);
    31  void dump_abort (int, const char *, mpz_t, mpz_t, mpz_t, mpz_t);
    32  
    33  #define FFT_MIN_BITSIZE 100000
    34  
    35  char *extra_fft;
    36  
    37  void
    38  one (int i, mpz_t multiplicand, mpz_t multiplier)
    39  {
    40    mpz_t product, ref_product;
    41  
    42    mpz_init (product);
    43    mpz_init (ref_product);
    44  
    45    /* Test plain multiplication comparing results against reference code.  */
    46    mpz_mul (product, multiplier, multiplicand);
    47    refmpz_mul (ref_product, multiplier, multiplicand);
    48    if (mpz_cmp (product, ref_product))
    49      dump_abort (i, "incorrect plain product",
    50  		multiplier, multiplicand, product, ref_product);
    51  
    52    /* Test squaring, comparing results against plain multiplication  */
    53    mpz_mul (product, multiplier, multiplier);
    54    mpz_set (multiplicand, multiplier);
    55    mpz_mul (ref_product, multiplier, multiplicand);
    56    if (mpz_cmp (product, ref_product))
    57      dump_abort (i, "incorrect square product",
    58  		multiplier, multiplier, product, ref_product);
    59  
    60    mpz_clear (product);
    61    mpz_clear (ref_product);
    62  }
    63  
    64  int
    65  main (int argc, char **argv)
    66  {
    67    mpz_t op1, op2;
    68    int i;
    69    int fft_max_2exp;
    70  
    71    gmp_randstate_ptr rands;
    72    mpz_t bs;
    73    unsigned long bsi, size_range, fsize_range;
    74  
    75    tests_start ();
    76    rands = RANDS;
    77  
    78    extra_fft = getenv ("GMP_CHECK_FFT");
    79    fft_max_2exp = 0;
    80    if (extra_fft != NULL)
    81      fft_max_2exp = atoi (extra_fft);
    82  
    83    if (fft_max_2exp <= 1)	/* compat with old use of GMP_CHECK_FFT */
    84      fft_max_2exp = 22;		/* default limit, good for any machine */
    85  
    86    mpz_init (bs);
    87    mpz_init (op1);
    88    mpz_init (op2);
    89  
    90    fsize_range = 4 << 8;		/* a fraction 1/256 of size_range */
    91    for (i = 0;; i++)
    92      {
    93        size_range = fsize_range >> 8;
    94        fsize_range = fsize_range * 33 / 32;
    95  
    96        if (size_range > fft_max_2exp)
    97  	break;
    98  
    99        mpz_urandomb (bs, rands, size_range);
   100        mpz_rrandomb (op1, rands, mpz_get_ui (bs));
   101        if (i & 1)
   102  	mpz_urandomb (bs, rands, size_range);
   103        mpz_rrandomb (op2, rands, mpz_get_ui (bs));
   104  
   105        mpz_urandomb (bs, rands, 4);
   106        bsi = mpz_get_ui (bs);
   107        if ((bsi & 0x3) == 0)
   108  	mpz_neg (op1, op1);
   109        if ((bsi & 0xC) == 0)
   110  	mpz_neg (op2, op2);
   111  
   112        /* printf ("%d %d\n", SIZ (op1), SIZ (op2)); */
   113        one (i, op2, op1);
   114      }
   115  
   116    for (i = -50; i < 0; i++)
   117      {
   118        mpz_urandomb (bs, rands, 32);
   119        size_range = mpz_get_ui (bs) % fft_max_2exp;
   120  
   121        mpz_urandomb (bs, rands, size_range);
   122        mpz_rrandomb (op1, rands, mpz_get_ui (bs) + FFT_MIN_BITSIZE);
   123        mpz_urandomb (bs, rands, size_range);
   124        mpz_rrandomb (op2, rands, mpz_get_ui (bs) + FFT_MIN_BITSIZE);
   125  
   126        /* printf ("%d: %d %d\n", i, SIZ (op1), SIZ (op2)); */
   127        fflush (stdout);
   128        one (-1, op2, op1);
   129      }
   130  
   131    mpz_clear (bs);
   132    mpz_clear (op1);
   133    mpz_clear (op2);
   134  
   135    tests_end ();
   136    exit (0);
   137  }
   138  
   139  static void
   140  refmpz_mul (mpz_t w, const mpz_t u, const mpz_t v)
   141  {
   142    mp_size_t usize = u->_mp_size;
   143    mp_size_t vsize = v->_mp_size;
   144    mp_size_t wsize;
   145    mp_size_t sign_product;
   146    mp_ptr up, vp;
   147    mp_ptr wp;
   148    mp_size_t talloc;
   149  
   150    sign_product = usize ^ vsize;
   151    usize = ABS (usize);
   152    vsize = ABS (vsize);
   153  
   154    if (usize == 0 || vsize == 0)
   155      {
   156        SIZ (w) = 0;
   157        return;
   158      }
   159  
   160    talloc = usize + vsize;
   161  
   162    up = u->_mp_d;
   163    vp = v->_mp_d;
   164  
   165    wp = __GMP_ALLOCATE_FUNC_LIMBS (talloc);
   166  
   167    if (usize > vsize)
   168      refmpn_mul (wp, up, usize, vp, vsize);
   169    else
   170      refmpn_mul (wp, vp, vsize, up, usize);
   171    wsize = usize + vsize;
   172    wsize -= wp[wsize - 1] == 0;
   173    MPZ_REALLOC (w, wsize);
   174    MPN_COPY (PTR(w), wp, wsize);
   175  
   176    SIZ(w) = sign_product < 0 ? -wsize : wsize;
   177    __GMP_FREE_FUNC_LIMBS (wp, talloc);
   178  }
   179  
   180  void
   181  dump_abort (int i, const char *s,
   182              mpz_t op1, mpz_t op2, mpz_t product, mpz_t ref_product)
   183  {
   184    mp_size_t b, e;
   185    fprintf (stderr, "ERROR: %s in test %d\n", s, i);
   186    fprintf (stderr, "op1          = "); debug_mp (op1);
   187    fprintf (stderr, "op2          = "); debug_mp (op2);
   188    fprintf (stderr, "    product  = "); debug_mp (product);
   189    fprintf (stderr, "ref_product  = "); debug_mp (ref_product);
   190    for (b = 0; b < ABSIZ(ref_product); b++)
   191      if (PTR(ref_product)[b] != PTR(product)[b])
   192        break;
   193    for (e = ABSIZ(ref_product) - 1; e >= 0; e--)
   194      if (PTR(ref_product)[e] != PTR(product)[e])
   195        break;
   196    printf ("ERRORS in %ld--%ld\n", b, e);
   197    abort();
   198  }
   199  
   200  void
   201  debug_mp (mpz_t x)
   202  {
   203    size_t siz = mpz_sizeinbase (x, 16);
   204  
   205    if (siz > 65)
   206      {
   207        mpz_t q;
   208        mpz_init (q);
   209        mpz_tdiv_q_2exp (q, x, 4 * (mpz_sizeinbase (x, 16) - 25));
   210        gmp_fprintf (stderr, "%ZX...", q);
   211        mpz_tdiv_r_2exp (q, x, 4 * 25);
   212        gmp_fprintf (stderr, "%025ZX [%d]\n", q, (int) siz);
   213        mpz_clear (q);
   214      }
   215    else
   216      {
   217        gmp_fprintf (stderr, "%ZX\n", x);
   218      }
   219  }