1/* 2 3Copyright 2012, 2014, 2016, Free Software Foundation, Inc. 4 5This file is part of the GNU MP Library test suite. 6 7The GNU MP Library test suite is free software; you can redistribute it 8and/or modify it under the terms of the GNU General Public License as 9published by the Free Software Foundation; either version 3 of the License, 10or (at your option) any later version. 11 12The GNU MP Library test suite is distributed in the hope that it will be 13useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 15Public License for more details. 16 17You should have received a copy of the GNU General Public License along with 18the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */ 19 20#include <assert.h> 21#include <limits.h> 22#include <stdlib.h> 23#include <stdio.h> 24#include <string.h> 25 26#include "testutils.h" 27 28#define MAXBITS 400 29#define COUNT 100 30 31void 32my_mpz_mul (mpz_t r, mpz_srcptr a, mpz_srcptr b) 33{ 34 mp_limb_t *tp; 35 mp_size_t tn, an, bn; 36 37 an = mpz_size (a); 38 bn = mpz_size (b); 39 40 assert (an > 0); 41 assert (bn > 0); 42 43 tn = an + bn; 44 tp = mpz_limbs_write (r, tn); 45 if (an > bn) 46 mpn_mul (tp, mpz_limbs_read (a), an, mpz_limbs_read (b), bn); 47 else 48 mpn_mul (tp, mpz_limbs_read (b), bn, mpz_limbs_read (a), an); 49 50 if (mpz_sgn (a) != mpz_sgn(b)) 51 tn = - tn; 52 53 mpz_limbs_finish (r, tn); 54} 55 56void 57testmain (int argc, char **argv) 58{ 59 unsigned i; 60 mpz_t a, b, res, ref; 61 62 mpz_init (a); 63 mpz_init (b); 64 mpz_init (res); 65 mpz_init (ref); 66 67 for (i = 0; i < COUNT; i++) 68 { 69 mini_random_op3 (OP_MUL, MAXBITS, a, b, ref); 70 if (mpz_sgn(ref) == 0) 71 /* my_mpz_mul requires a != 0, b != 0 */ 72 continue; 73 my_mpz_mul (res, a, b); 74 if (mpz_cmp (res, ref)) 75 { 76 fprintf (stderr, "my_mpz_mul failed:\n"); 77 dump ("a", a); 78 dump ("b", b); 79 dump ("r", res); 80 dump ("ref", ref); 81 abort (); 82 } 83 /* The following test exploits a side-effect of my_mpz_mul: res 84 points to a buffer with at least an+bn limbs, and the limbs 85 above the result are zeroed. */ 86 if (mpz_size (b) > 0 && mpz_getlimbn (res, mpz_size(a)) != mpz_limbs_read (res) [mpz_size(a)]) 87 { 88 fprintf (stderr, "getlimbn - limbs_read differ.\n"); 89 abort (); 90 } 91 if ((i % 4 == 0) && mpz_size (res) > 1) 92 { 93 mpz_realloc2 (res, 1); 94 if (mpz_cmp_ui (res, 0)) 95 { 96 fprintf (stderr, "mpz_realloc2 did not clear res.\n"); 97 abort (); 98 } 99 mpz_limbs_finish (ref, 0); 100 if (mpz_cmp_d (ref, 0)) 101 { 102 fprintf (stderr, "mpz_limbs_finish did not clear res.\n"); 103 abort (); 104 } 105 } 106 } 107 mpz_clear (a); 108 mpz_clear (b); 109 mpz_clear (res); 110 mpz_clear (ref); 111} 112