1 /* Test mpz_limbs_* functions 2 3 Copyright 2013 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 #include <stdlib.h> 21 #include <stdio.h> 22 23 #include "gmp-impl.h" 24 #include "tests.h" 25 26 #define COUNT 100 27 #define BITSIZE 500 28 29 /* Like mpz_add. For simplicity, support positive inputs only. */ 30 static void 31 alt_add (mpz_ptr r, mpz_srcptr a, mpz_srcptr b) 32 { 33 mp_size_t an = mpz_size (a); 34 mp_size_t bn = mpz_size (b); 35 mp_ptr rp; 36 37 ASSERT (an > 0); 38 ASSERT (bn > 0); 39 if (an < bn) 40 { 41 MP_SIZE_T_SWAP (an, bn); 42 MPZ_SRCPTR_SWAP (a, b); 43 } 44 rp = mpz_limbs_modify (r, an + 1); 45 rp[an] = mpn_add (rp, mpz_limbs_read (a), an, mpz_limbs_read (b), bn); 46 mpz_limbs_finish (r, an + 1); 47 } 48 49 static void 50 check_funcs (const char *name, 51 void (*f)(mpz_ptr, mpz_srcptr, mpz_srcptr), 52 void (*ref_f)(mpz_ptr, mpz_srcptr, mpz_srcptr), 53 mpz_srcptr a, mpz_srcptr b) 54 { 55 mpz_t r, ref; 56 mpz_inits (r, ref, NULL); 57 58 ref_f (ref, a, b); 59 MPZ_CHECK_FORMAT (ref); 60 f (r, a, b); 61 MPZ_CHECK_FORMAT (r); 62 63 if (mpz_cmp (r, ref) != 0) 64 { 65 printf ("%s failed, abits %u, bbits %u\n", 66 name, 67 (unsigned) mpz_sizeinbase (a, 2), 68 (unsigned) mpz_sizeinbase (b, 2)); 69 gmp_printf ("a = %Zx\n", a); 70 gmp_printf ("b = %Zx\n", b); 71 gmp_printf ("r = %Zx (bad)\n", r); 72 gmp_printf ("ref = %Zx\n", ref); 73 abort (); 74 } 75 mpz_clears (r, ref, NULL); 76 } 77 78 static void 79 check_add (void) 80 { 81 gmp_randstate_ptr rands = RANDS; 82 mpz_t bs, a, b; 83 unsigned i; 84 mpz_inits (bs, a, b, NULL); 85 for (i = 0; i < COUNT; i++) 86 { 87 mpz_urandomb (bs, rands, 32); 88 mpz_rrandomb (a, rands, 1 + mpz_get_ui (bs) % BITSIZE); 89 mpz_urandomb (bs, rands, 32); 90 mpz_rrandomb (b, rands, 1 + mpz_get_ui (bs) % BITSIZE); 91 92 check_funcs ("add", alt_add, mpz_add, a, b); 93 } 94 mpz_clears (bs, a, b, NULL); 95 } 96 97 static void 98 alt_mul (mpz_ptr r, mpz_srcptr a, mpz_srcptr b) 99 { 100 mp_size_t an = mpz_size (a); 101 mp_size_t bn = mpz_size (b); 102 mp_srcptr ap, bp; 103 TMP_DECL; 104 105 TMP_MARK; 106 107 ASSERT (an > 0); 108 ASSERT (bn > 0); 109 if (an < bn) 110 { 111 MP_SIZE_T_SWAP (an, bn); 112 MPZ_SRCPTR_SWAP (a, b); 113 } 114 /* NOTE: This copying seems unnecessary; better to allocate new 115 result area, and free the old area when done. */ 116 if (r == a) 117 { 118 mp_ptr tp = TMP_ALLOC_LIMBS (an); 119 MPN_COPY (tp, mpz_limbs_read (a), an); 120 ap = tp; 121 bp = (a == b) ? ap : mpz_limbs_read (b); 122 } 123 else if (r == b) 124 { 125 mp_ptr tp = TMP_ALLOC_LIMBS (bn); 126 MPN_COPY (tp, mpz_limbs_read (b), bn); 127 bp = tp; 128 ap = mpz_limbs_read (a); 129 } 130 else 131 { 132 ap = mpz_limbs_read (a); 133 bp = mpz_limbs_read (b); 134 } 135 mpn_mul (mpz_limbs_write (r, an + bn), 136 ap, an, bp, bn); 137 138 mpz_limbs_finish (r, an + bn); 139 } 140 141 void 142 check_mul (void) 143 { 144 gmp_randstate_ptr rands = RANDS; 145 mpz_t bs, a, b; 146 unsigned i; 147 mpz_inits (bs, a, b, NULL); 148 for (i = 0; i < COUNT; i++) 149 { 150 mpz_urandomb (bs, rands, 32); 151 mpz_rrandomb (a, rands, 1 + mpz_get_ui (bs) % BITSIZE); 152 mpz_urandomb (bs, rands, 32); 153 mpz_rrandomb (b, rands, 1 + mpz_get_ui (bs) % BITSIZE); 154 155 check_funcs ("mul", alt_mul, mpz_mul, a, b); 156 } 157 mpz_clears (bs, a, b, NULL); 158 } 159 160 #define MAX_SIZE 100 161 162 static void 163 check_roinit (void) 164 { 165 gmp_randstate_ptr rands = RANDS; 166 mpz_t bs, a, b, r, ref; 167 unsigned i; 168 169 mpz_inits (bs, a, b, r, ref, NULL); 170 171 for (i = 0; i < COUNT; i++) 172 { 173 mp_srcptr ap, bp; 174 mp_size_t an, bn; 175 mpz_urandomb (bs, rands, 32); 176 mpz_rrandomb (a, rands, 1 + mpz_get_ui (bs) % BITSIZE); 177 mpz_urandomb (bs, rands, 32); 178 mpz_rrandomb (b, rands, 1 + mpz_get_ui (bs) % BITSIZE); 179 180 an = mpz_size (a); 181 ap = mpz_limbs_read (a); 182 bn = mpz_size (b); 183 bp = mpz_limbs_read (b); 184 185 mpz_add (ref, a, b); 186 { 187 mpz_t a1, b1; 188 #if __STDC_VERSION__ >= 199901 189 const mpz_t a2 = MPZ_ROINIT_N ( (mp_ptr) ap, an); 190 const mpz_t b2 = MPZ_ROINIT_N ( (mp_ptr) bp, bn); 191 192 mpz_set_ui (r, 0); 193 mpz_add (r, a2, b2); 194 if (mpz_cmp (r, ref) != 0) 195 { 196 printf ("MPZ_ROINIT_N failed\n"); 197 gmp_printf ("a = %Zx\n", a); 198 gmp_printf ("b = %Zx\n", b); 199 gmp_printf ("r = %Zx (bad)\n", r); 200 gmp_printf ("ref = %Zx\n", ref); 201 abort (); 202 } 203 #endif 204 mpz_set_ui (r, 0); 205 mpz_add (r, mpz_roinit_n (a1, ap, an), mpz_roinit_n (b1, bp, bn)); 206 if (mpz_cmp (r, ref) != 0) 207 { 208 printf ("mpz_roinit_n failed\n"); 209 gmp_printf ("a = %Zx\n", a); 210 gmp_printf ("b = %Zx\n", b); 211 gmp_printf ("r = %Zx (bad)\n", r); 212 gmp_printf ("ref = %Zx\n", ref); 213 abort (); 214 } 215 } 216 } 217 mpz_clears (bs, a, b, r, ref, NULL); 218 } 219 220 int 221 main (int argc, char *argv[]) 222 { 223 tests_start (); 224 tests_end (); 225 226 check_add (); 227 check_mul (); 228 check_roinit (); 229 230 return 0; 231 232 } 233