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