1/* Test mpz_addmul, mpz_addmul_ui, mpz_submul, mpz_submul_ui. 2 3Copyright 2001, 2002 Free Software Foundation, Inc. 4 5This file is part of the GNU MP Library. 6 7The GNU MP Library is free software; you can redistribute it and/or modify 8it under the terms of the GNU Lesser General Public License as published by 9the Free Software Foundation; either version 3 of the License, or (at your 10option) any later version. 11 12The GNU MP Library is distributed in the hope that it will be useful, but 13WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 14or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15License for more details. 16 17You should have received a copy of the GNU Lesser General Public License 18along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */ 19 20 21#include <stdio.h> 22#include <stdlib.h> 23#include <string.h> 24 25#include "gmp.h" 26#include "gmp-impl.h" 27#include "tests.h" 28 29 30#define M GMP_NUMB_MAX 31 32 33void 34check_one_inplace (mpz_srcptr w, mpz_srcptr y) 35{ 36 mpz_t want, got; 37 38 mpz_init (want); 39 mpz_init (got); 40 41 mpz_mul (want, w, y); 42 mpz_add (want, w, want); 43 mpz_set (got, w); 44 mpz_addmul (got, got, y); 45 MPZ_CHECK_FORMAT (got); 46 if (mpz_cmp (want, got) != 0) 47 { 48 printf ("mpz_addmul inplace fail\n"); 49 fail: 50 mpz_trace ("w", w); 51 mpz_trace ("y", y); 52 mpz_trace ("want", want); 53 mpz_trace ("got ", got); 54 abort (); 55 } 56 57 mpz_mul (want, w, y); 58 mpz_sub (want, w, want); 59 mpz_set (got, w); 60 mpz_submul (got, got, y); 61 MPZ_CHECK_FORMAT (got); 62 if (mpz_cmp (want, got) != 0) 63 { 64 printf ("mpz_submul inplace fail\n"); 65 goto fail; 66 } 67 68 mpz_clear (want); 69 mpz_clear (got); 70} 71 72void 73check_one_ui_inplace (mpz_ptr w, unsigned long y) 74{ 75 mpz_t want, got; 76 77 mpz_init (want); 78 mpz_init (got); 79 80 mpz_mul_ui (want, w, (unsigned long) y); 81 mpz_add (want, w, want); 82 mpz_set (got, w); 83 mpz_addmul_ui (got, got, (unsigned long) y); 84 MPZ_CHECK_FORMAT (got); 85 if (mpz_cmp (want, got) != 0) 86 { 87 printf ("mpz_addmul_ui fail\n"); 88 fail: 89 mpz_trace ("w", w); 90 printf ("y=0x%lX %lu\n", y, y); 91 mpz_trace ("want", want); 92 mpz_trace ("got ", got); 93 abort (); 94 } 95 96 mpz_mul_ui (want, w, y); 97 mpz_sub (want, w, want); 98 mpz_set (got, w); 99 mpz_submul_ui (got, got, y); 100 MPZ_CHECK_FORMAT (got); 101 if (mpz_cmp (want, got) != 0) 102 { 103 printf ("mpz_submul_ui fail\n"); 104 goto fail; 105 } 106 107 mpz_clear (want); 108 mpz_clear (got); 109} 110 111void 112check_all_inplace (mpz_ptr w, mpz_ptr y) 113{ 114 int wneg, yneg; 115 116 MPZ_CHECK_FORMAT (w); 117 MPZ_CHECK_FORMAT (y); 118 119 for (wneg = 0; wneg < 2; wneg++) 120 { 121 for (yneg = 0; yneg < 2; yneg++) 122 { 123 check_one_inplace (w, y); 124 125 if (mpz_fits_ulong_p (y)) 126 check_one_ui_inplace (w, mpz_get_ui (y)); 127 128 mpz_neg (y, y); 129 } 130 mpz_neg (w, w); 131 } 132} 133 134void 135check_one (mpz_srcptr w, mpz_srcptr x, mpz_srcptr y) 136{ 137 mpz_t want, got; 138 139 mpz_init (want); 140 mpz_init (got); 141 142 mpz_mul (want, x, y); 143 mpz_add (want, w, want); 144 mpz_set (got, w); 145 mpz_addmul (got, x, y); 146 MPZ_CHECK_FORMAT (got); 147 if (mpz_cmp (want, got) != 0) 148 { 149 printf ("mpz_addmul fail\n"); 150 fail: 151 mpz_trace ("w", w); 152 mpz_trace ("x", x); 153 mpz_trace ("y", y); 154 mpz_trace ("want", want); 155 mpz_trace ("got ", got); 156 abort (); 157 } 158 159 mpz_mul (want, x, y); 160 mpz_sub (want, w, want); 161 mpz_set (got, w); 162 mpz_submul (got, x, y); 163 MPZ_CHECK_FORMAT (got); 164 if (mpz_cmp (want, got) != 0) 165 { 166 printf ("mpz_submul fail\n"); 167 goto fail; 168 } 169 170 mpz_clear (want); 171 mpz_clear (got); 172} 173 174void 175check_one_ui (mpz_ptr w, mpz_ptr x, unsigned long y) 176{ 177 mpz_t want, got; 178 179 mpz_init (want); 180 mpz_init (got); 181 182 mpz_mul_ui (want, x, (unsigned long) y); 183 mpz_add (want, w, want); 184 mpz_set (got, w); 185 mpz_addmul_ui (got, x, (unsigned long) y); 186 MPZ_CHECK_FORMAT (got); 187 if (mpz_cmp (want, got) != 0) 188 { 189 printf ("mpz_addmul_ui fail\n"); 190 fail: 191 mpz_trace ("w", w); 192 mpz_trace ("x", x); 193 printf ("y=0x%lX %lu\n", y, y); 194 mpz_trace ("want", want); 195 mpz_trace ("got ", got); 196 abort (); 197 } 198 199 mpz_mul_ui (want, x, y); 200 mpz_sub (want, w, want); 201 mpz_set (got, w); 202 mpz_submul_ui (got, x, y); 203 MPZ_CHECK_FORMAT (got); 204 if (mpz_cmp (want, got) != 0) 205 { 206 printf ("mpz_submul_ui fail\n"); 207 goto fail; 208 } 209 210 mpz_clear (want); 211 mpz_clear (got); 212} 213 214 215void 216check_all (mpz_ptr w, mpz_ptr x, mpz_ptr y) 217{ 218 int swap, wneg, xneg, yneg; 219 220 MPZ_CHECK_FORMAT (w); 221 MPZ_CHECK_FORMAT (x); 222 MPZ_CHECK_FORMAT (y); 223 224 for (swap = 0; swap < 2; swap++) 225 { 226 for (wneg = 0; wneg < 2; wneg++) 227 { 228 for (xneg = 0; xneg < 2; xneg++) 229 { 230 for (yneg = 0; yneg < 2; yneg++) 231 { 232 check_one (w, x, y); 233 234 if (mpz_fits_ulong_p (y)) 235 check_one_ui (w, x, mpz_get_ui (y)); 236 237 mpz_neg (y, y); 238 } 239 mpz_neg (x, x); 240 } 241 mpz_neg (w, w); 242 } 243 mpz_swap (x, y); 244 } 245} 246 247void 248check_data_inplace_ui (void) 249{ 250 static const struct { 251 mp_limb_t w[6]; 252 unsigned long y; 253 254 } data[] = { 255 256 { { 0 }, 0 }, 257 { { 0 }, 1 }, 258 { { 1 }, 1 }, 259 { { 2 }, 1 }, 260 261 { { 123 }, 1 }, 262 { { 123 }, ULONG_MAX }, 263 { { M }, 1 }, 264 { { M }, ULONG_MAX }, 265 266 { { 123, 456 }, 1 }, 267 { { M, M }, 1 }, 268 { { 123, 456 }, ULONG_MAX }, 269 { { M, M }, ULONG_MAX }, 270 271 { { 123, 456, 789 }, 1 }, 272 { { M, M, M }, 1 }, 273 { { 123, 456, 789 }, ULONG_MAX }, 274 { { M, M, M }, ULONG_MAX }, 275 }; 276 277 mpz_t w, y; 278 int i; 279 280 mpz_init (w); 281 mpz_init (y); 282 283 for (i = 0; i < numberof (data); i++) 284 { 285 mpz_set_n (w, data[i].w, (mp_size_t) numberof(data[i].w)); 286 mpz_set_ui (y, data[i].y); 287 check_all_inplace (w, y); 288 } 289 290 mpz_clear (w); 291 mpz_clear (y); 292} 293 294void 295check_data (void) 296{ 297 static const struct { 298 mp_limb_t w[6]; 299 mp_limb_t x[6]; 300 mp_limb_t y[6]; 301 302 } data[] = { 303 304 /* reducing to zero */ 305 { { 1 }, { 1 }, { 1 } }, 306 { { 2 }, { 1 }, { 2 } }, 307 { { 0,1 }, { 0,1 }, { 1 } }, 308 309 /* reducing to 1 */ 310 { { 0,1 }, { M }, { 1 } }, 311 { { 0,0,1 }, { M,M }, { 1 } }, 312 { { 0,0,0,1 }, { M,M,M }, { 1 } }, 313 { { 0,0,0,0,1 }, { M,M,M,M }, { 1 } }, 314 315 /* reducing to -1 */ 316 { { M }, { 0,1 }, { 1 } }, 317 { { M,M }, { 0,0,1 }, { 1 } }, 318 { { M,M,M }, { 0,0,0,1 }, { 1 } }, 319 { { M,M,M,M }, { 0,0,0,0,1 }, { 1 } }, 320 321 /* carry out of addmul */ 322 { { M }, { 1 }, { 1 } }, 323 { { M,M }, { 1 }, { 1 } }, 324 { { M,M,M }, { 1 }, { 1 } }, 325 326 /* borrow from submul */ 327 { { 0,1 }, { 1 }, { 1 } }, 328 { { 0,0,1 }, { 1 }, { 1 } }, 329 { { 0,0,0,1 }, { 1 }, { 1 } }, 330 331 /* borrow from submul */ 332 { { 0,0,1 }, { 0,1 }, { 1 } }, 333 { { 0,0,0,1 }, { 0,1 }, { 1 } }, 334 { { 0,0,0,0,1 }, { 0,1 }, { 1 } }, 335 336 /* more borrow from submul */ 337 { { M }, { 0,1 }, { 1 } }, 338 { { M }, { 0,0,1 }, { 1 } }, 339 { { M }, { 0,0,0,1 }, { 1 } }, 340 { { M }, { 0,0,0,0,1 }, { 1 } }, 341 342 /* big borrow from submul */ 343 { { 0,0,1 }, { M,M }, { M } }, 344 { { 0,0,0,1 }, { M,M }, { M } }, 345 { { 0,0,0,0,1 }, { M,M }, { M } }, 346 347 /* small w */ 348 { { 0,1 }, { M,M }, { M } }, 349 { { 0,1 }, { M,M,M }, { M } }, 350 { { 0,1 }, { M,M,M,M }, { M } }, 351 { { 0,1 }, { M,M,M,M,M }, { M } }, 352 }; 353 354 mpz_t w, x, y; 355 int i; 356 357 mpz_init (w); 358 mpz_init (x); 359 mpz_init (y); 360 361 for (i = 0; i < numberof (data); i++) 362 { 363 mpz_set_n (w, data[i].w, (mp_size_t) numberof(data[i].w)); 364 mpz_set_n (x, data[i].x, (mp_size_t) numberof(data[i].x)); 365 mpz_set_n (y, data[i].y, (mp_size_t) numberof(data[i].y)); 366 check_all (w, x, y); 367 } 368 369 mpz_clear (w); 370 mpz_clear (x); 371 mpz_clear (y); 372} 373 374 375void 376check_random (int argc, char *argv[]) 377{ 378 gmp_randstate_ptr rands = RANDS; 379 mpz_t w, x, y; 380 int i, reps = 2000; 381 382 mpz_init (w); 383 mpz_init (x); 384 mpz_init (y); 385 386 if (argc == 2) 387 reps = atoi (argv[1]); 388 389 for (i = 0; i < reps; i++) 390 { 391 mpz_errandomb (w, rands, 5*GMP_LIMB_BITS); 392 mpz_errandomb (x, rands, 5*GMP_LIMB_BITS); 393 mpz_errandomb (y, rands, 5*GMP_LIMB_BITS); 394 check_all (w, x, y); 395 check_all_inplace (w, y); 396 397 mpz_errandomb (w, rands, 5*GMP_LIMB_BITS); 398 mpz_errandomb (x, rands, 5*GMP_LIMB_BITS); 399 mpz_errandomb (y, rands, BITS_PER_ULONG); 400 check_all (w, x, y); 401 check_all_inplace (w, y); 402 } 403 404 mpz_clear (w); 405 mpz_clear (x); 406 mpz_clear (y); 407} 408 409 410int 411main (int argc, char *argv[]) 412{ 413 tests_start (); 414 mp_trace_base = -16; 415 416 check_data (); 417 check_data_inplace_ui (); 418 check_random (argc, argv); 419 420 tests_end (); 421 exit (0); 422} 423