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