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