1 // Copyright 2016-2021 Francesco Biscani (bluescarni@gmail.com) 2 // 3 // This file is part of the mp++ library. 4 // 5 // This Source Code Form is subject to the terms of the Mozilla 6 // Public License v. 2.0. If a copy of the MPL was not distributed 7 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 9 #include <cstddef> 10 #include <gmp.h> 11 #include <random> 12 #include <stdexcept> 13 #include <tuple> 14 #include <type_traits> 15 16 #include <mp++/integer.hpp> 17 18 #include "catch.hpp" 19 #include "test_utils.hpp" 20 21 static const int ntries = 1000; 22 23 // NOLINTNEXTLINE(google-build-using-namespace) 24 using namespace mppp; 25 // NOLINTNEXTLINE(google-build-using-namespace) 26 using namespace mppp_test; 27 28 using sizes = std::tuple<std::integral_constant<std::size_t, 1>, std::integral_constant<std::size_t, 2>, 29 std::integral_constant<std::size_t, 3>, std::integral_constant<std::size_t, 6>, 30 std::integral_constant<std::size_t, 10>>; 31 32 // NOLINTNEXTLINE(cert-err58-cpp, cert-msc32-c, cert-msc51-cpp, cppcoreguidelines-avoid-non-const-global-variables) 33 static std::mt19937 rng; 34 35 struct add_tester { 36 template <typename S> operator ()add_tester37 inline void operator()(const S &) const 38 { 39 using integer = integer<S::value>; 40 // Start with all zeroes. 41 detail::mpz_raii m1, m2, m3; 42 integer n1, n2, n3; 43 REQUIRE(&add(n1, n2, n3) == &n1); 44 mpz_add(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz); 45 REQUIRE((lex_cast(n1) == lex_cast(m1))); 46 REQUIRE(n1.is_static()); 47 REQUIRE(n2.is_static()); 48 REQUIRE(n3.is_static()); 49 detail::mpz_raii tmp; 50 std::uniform_int_distribution<int> sdist(0, 1); 51 // Run a variety of tests with operands with x and y number of limbs. 52 auto random_xy = [&](unsigned x, unsigned y) { 53 for (int i = 0; i < ntries; ++i) { 54 random_integer(tmp, x, rng); 55 mpz_set(&m2.m_mpz, &tmp.m_mpz); 56 n2 = &tmp.m_mpz; 57 if (sdist(rng)) { 58 mpz_neg(&m2.m_mpz, &m2.m_mpz); 59 n2.neg(); 60 } 61 if (n2.is_static() && sdist(rng)) { 62 // Promote sometimes, if possible. 63 n2.promote(); 64 } 65 random_integer(tmp, y, rng); 66 mpz_set(&m3.m_mpz, &tmp.m_mpz); 67 n3 = &tmp.m_mpz; 68 if (sdist(rng)) { 69 mpz_neg(&m3.m_mpz, &m3.m_mpz); 70 n3.neg(); 71 } 72 if (n3.is_static() && sdist(rng)) { 73 // Promote sometimes, if possible. 74 n3.promote(); 75 } 76 // NOLINTNEXTLINE(misc-redundant-expression) 77 if (sdist(rng) && sdist(rng) && sdist(rng)) { 78 // Reset rop every once in a while. 79 n1 = integer{}; 80 } 81 add(n1, n2, n3); 82 mpz_add(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz); 83 REQUIRE((lex_cast(n1) == lex_cast(m1))); 84 // Various variations of in-place. 85 add(n1, n1, n2); 86 mpz_add(&m1.m_mpz, &m1.m_mpz, &m2.m_mpz); 87 REQUIRE((lex_cast(n1) == lex_cast(m1))); 88 add(n2, n1, n2); 89 mpz_add(&m2.m_mpz, &m1.m_mpz, &m2.m_mpz); 90 REQUIRE((lex_cast(n1) == lex_cast(m1))); 91 REQUIRE((lex_cast(n2) == lex_cast(m2))); 92 add(n1, n1, n1); 93 mpz_add(&m1.m_mpz, &m1.m_mpz, &m1.m_mpz); 94 REQUIRE((lex_cast(n1) == lex_cast(m1))); 95 // Test overflow when second size is larger than the other. 96 if (y > x) { 97 random_integer(tmp, x, rng); 98 mpz_set(&m2.m_mpz, &tmp.m_mpz); 99 n2 = &tmp.m_mpz; 100 if (sdist(rng)) { 101 mpz_neg(&m2.m_mpz, &m2.m_mpz); 102 n2.neg(); 103 } 104 max_integer(tmp, y); 105 mpz_set(&m3.m_mpz, &tmp.m_mpz); 106 n3 = &tmp.m_mpz; 107 if (sdist(rng)) { 108 mpz_neg(&m3.m_mpz, &m3.m_mpz); 109 n3.neg(); 110 } 111 add(n1, n2, n3); 112 mpz_add(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz); 113 REQUIRE((lex_cast(n1) == lex_cast(m1))); 114 } 115 // Test subtraction of equal numbers. 116 if (x == y) { 117 random_integer(tmp, x, rng); 118 mpz_set(&m2.m_mpz, &tmp.m_mpz); 119 n2 = &tmp.m_mpz; 120 const bool neg = sdist(rng) == 1; 121 if (neg) { 122 mpz_neg(&m2.m_mpz, &m2.m_mpz); 123 n2.neg(); 124 } 125 mpz_set(&m3.m_mpz, &tmp.m_mpz); 126 n3 = &tmp.m_mpz; 127 if (!neg) { 128 mpz_neg(&m3.m_mpz, &m3.m_mpz); 129 n3.neg(); 130 } 131 add(n1, n2, n3); 132 mpz_add(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz); 133 REQUIRE((lex_cast(n1) == lex_cast(m1))); 134 REQUIRE((lex_cast(n1) == "0")); 135 } 136 // Test subtraction with equal top limbs. 137 if (x == y) { 138 random_integer(tmp, x, rng); 139 mpz_set(&m2.m_mpz, &tmp.m_mpz); 140 n2 = &tmp.m_mpz; 141 const bool neg = sdist(rng) == 1; 142 if (neg) { 143 mpz_neg(&m2.m_mpz, &m2.m_mpz); 144 n2.neg(); 145 } 146 mpz_set(&m3.m_mpz, &tmp.m_mpz); 147 n3 = &tmp.m_mpz; 148 if (!neg) { 149 mpz_neg(&m3.m_mpz, &m3.m_mpz); 150 n3.neg(); 151 } 152 // Add 1 to bump up the lower limb. 153 integer one(1); 154 add(n2, n2, one); 155 mpz_add_ui(&m2.m_mpz, &m2.m_mpz, 1u); 156 add(n1, n2, n3); 157 mpz_add(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz); 158 REQUIRE((lex_cast(n1) == lex_cast(m1))); 159 add(n1, n3, n2); 160 mpz_add(&m1.m_mpz, &m3.m_mpz, &m2.m_mpz); 161 REQUIRE((lex_cast(n1) == lex_cast(m1))); 162 } 163 } 164 }; 165 166 random_xy(1, 0); 167 random_xy(0, 1); 168 random_xy(1, 1); 169 170 random_xy(0, 2); 171 random_xy(1, 2); 172 random_xy(2, 0); 173 random_xy(2, 1); 174 random_xy(2, 2); 175 176 random_xy(0, 3); 177 random_xy(1, 3); 178 random_xy(2, 3); 179 random_xy(3, 0); 180 random_xy(3, 1); 181 random_xy(3, 2); 182 random_xy(3, 3); 183 184 random_xy(0, 4); 185 random_xy(1, 4); 186 random_xy(2, 4); 187 random_xy(3, 4); 188 random_xy(4, 0); 189 random_xy(4, 1); 190 random_xy(4, 2); 191 random_xy(4, 3); 192 random_xy(4, 4); 193 194 // Testing specific to the 2-limb optimisation. 195 if (S::value == 2u) { 196 // Carry only from lo. 197 max_integer(m2, 1u); 198 mpz_set_ui(&m3.m_mpz, 1u); 199 n2 = integer(::mp_limb_t(-1) & GMP_NUMB_MAX); 200 n3 = integer(1); 201 mpz_add(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz); 202 add(n1, n2, n3); 203 REQUIRE((lex_cast(n1) == lex_cast(m1))); 204 mpz_add(&m1.m_mpz, &m3.m_mpz, &m2.m_mpz); 205 add(n1, n3, n2); 206 REQUIRE((lex_cast(n1) == lex_cast(m1))); 207 // Carry only from hi. 208 max_integer(m2, 2u); 209 mpz_set_ui(&m3.m_mpz, 1u); 210 mpz_mul_2exp(&m3.m_mpz, &m3.m_mpz, GMP_NUMB_BITS); 211 n2 = integer(lex_cast(m2)); 212 n3 = integer(lex_cast(m3)); 213 mpz_add(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz); 214 add(n1, n2, n3); 215 REQUIRE((lex_cast(n1) == lex_cast(m1))); 216 n1 = integer{}; 217 mpz_add(&m1.m_mpz, &m3.m_mpz, &m2.m_mpz); 218 add(n1, n3, n2); 219 REQUIRE((lex_cast(n1) == lex_cast(m1))); 220 n1 = integer{}; 221 // Carry from hi and lo. 222 max_integer(m2, 2u); 223 mpz_set_ui(&m3.m_mpz, 1u); 224 mpz_mul_2exp(&m3.m_mpz, &m3.m_mpz, GMP_NUMB_BITS); 225 mpz_add_ui(&m3.m_mpz, &m3.m_mpz, 1u); 226 n2 = integer(lex_cast(m2)); 227 n3 = integer(lex_cast(m3)); 228 mpz_add(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz); 229 add(n1, n2, n3); 230 REQUIRE((lex_cast(n1) == lex_cast(m1))); 231 n1 = integer{}; 232 mpz_add(&m1.m_mpz, &m3.m_mpz, &m2.m_mpz); 233 add(n1, n3, n2); 234 REQUIRE((lex_cast(n1) == lex_cast(m1))); 235 n1 = integer{}; 236 // Subtraction that kills hi. 237 max_integer(m2, 2u); 238 max_integer(m3, 1u); 239 mpz_mul_2exp(&m3.m_mpz, &m3.m_mpz, GMP_NUMB_BITS); 240 mpz_neg(&m3.m_mpz, &m3.m_mpz); 241 n2 = integer(lex_cast(m2)); 242 n3 = integer(lex_cast(m3)); 243 mpz_add(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz); 244 add(n1, n2, n3); 245 REQUIRE((lex_cast(n1) == lex_cast(m1))); 246 REQUIRE((mpz_size(&m1.m_mpz) == 1u)); 247 mpz_add(&m1.m_mpz, &m3.m_mpz, &m2.m_mpz); 248 add(n1, n3, n2); 249 REQUIRE((lex_cast(n1) == lex_cast(m1))); 250 REQUIRE((mpz_size(&m1.m_mpz) == 1u)); 251 mpz_neg(&m3.m_mpz, &m3.m_mpz); 252 mpz_neg(&m2.m_mpz, &m2.m_mpz); 253 n2 = integer(lex_cast(m2)); 254 n3 = integer(lex_cast(m3)); 255 mpz_add(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz); 256 add(n1, n2, n3); 257 REQUIRE((lex_cast(n1) == lex_cast(m1))); 258 REQUIRE((mpz_size(&m1.m_mpz) == 1u)); 259 mpz_add(&m1.m_mpz, &m3.m_mpz, &m2.m_mpz); 260 add(n1, n3, n2); 261 REQUIRE((lex_cast(n1) == lex_cast(m1))); 262 REQUIRE((mpz_size(&m1.m_mpz) == 1u)); 263 // Subtraction that kills lo. 264 max_integer(m2, 2u); 265 max_integer(m3, 1u); 266 mpz_neg(&m3.m_mpz, &m3.m_mpz); 267 n2 = integer(lex_cast(m2)); 268 n3 = integer(lex_cast(m3)); 269 mpz_add(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz); 270 add(n1, n2, n3); 271 REQUIRE((lex_cast(n1) == lex_cast(m1))); 272 REQUIRE((mpz_size(&m1.m_mpz) == 2u)); 273 mpz_add(&m1.m_mpz, &m3.m_mpz, &m2.m_mpz); 274 add(n1, n3, n2); 275 REQUIRE((lex_cast(n1) == lex_cast(m1))); 276 REQUIRE((mpz_size(&m1.m_mpz) == 2u)); 277 mpz_neg(&m3.m_mpz, &m3.m_mpz); 278 mpz_neg(&m2.m_mpz, &m2.m_mpz); 279 n2 = integer(lex_cast(m2)); 280 n3 = integer(lex_cast(m3)); 281 mpz_add(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz); 282 add(n1, n2, n3); 283 REQUIRE((lex_cast(n1) == lex_cast(m1))); 284 REQUIRE((mpz_size(&m1.m_mpz) == 2u)); 285 mpz_add(&m1.m_mpz, &m3.m_mpz, &m2.m_mpz); 286 add(n1, n3, n2); 287 REQUIRE((lex_cast(n1) == lex_cast(m1))); 288 REQUIRE((mpz_size(&m1.m_mpz) == 2u)); 289 } 290 } 291 }; 292 293 TEST_CASE("add") 294 { 295 tuple_for_each(sizes{}, add_tester{}); 296 } 297 298 struct sub_tester { 299 template <typename S> operator ()sub_tester300 inline void operator()(const S &) const 301 { 302 using integer = integer<S::value>; 303 // Start with all zeroes. 304 detail::mpz_raii m1, m2, m3; 305 integer n1, n2, n3; 306 REQUIRE(&sub(n1, n2, n3) == &n1); 307 mpz_sub(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz); 308 REQUIRE((lex_cast(n1) == lex_cast(m1))); 309 REQUIRE(n1.is_static()); 310 REQUIRE(n2.is_static()); 311 REQUIRE(n3.is_static()); 312 detail::mpz_raii tmp; 313 std::uniform_int_distribution<int> sdist(0, 1); 314 // Run a variety of tests with operands with x and y number of limbs. 315 auto random_xy = [&](unsigned x, unsigned y) { 316 for (int i = 0; i < ntries; ++i) { 317 random_integer(tmp, x, rng); 318 mpz_set(&m2.m_mpz, &tmp.m_mpz); 319 n2 = &tmp.m_mpz; 320 if (sdist(rng)) { 321 mpz_neg(&m2.m_mpz, &m2.m_mpz); 322 n2.neg(); 323 } 324 if (n2.is_static() && sdist(rng)) { 325 // Promote sometimes, if possible. 326 n2.promote(); 327 } 328 random_integer(tmp, y, rng); 329 mpz_set(&m3.m_mpz, &tmp.m_mpz); 330 n3 = &tmp.m_mpz; 331 if (sdist(rng)) { 332 mpz_neg(&m3.m_mpz, &m3.m_mpz); 333 n3.neg(); 334 } 335 if (n3.is_static() && sdist(rng)) { 336 // Promote sometimes, if possible. 337 n3.promote(); 338 } 339 // NOLINTNEXTLINE(misc-redundant-expression) 340 if (sdist(rng) && sdist(rng) && sdist(rng)) { 341 // Reset rop every once in a while. 342 n1 = integer{}; 343 } 344 sub(n1, n2, n3); 345 mpz_sub(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz); 346 REQUIRE((lex_cast(n1) == lex_cast(m1))); 347 // Various variations of in-place. 348 sub(n1, n1, n2); 349 mpz_sub(&m1.m_mpz, &m1.m_mpz, &m2.m_mpz); 350 REQUIRE((lex_cast(n1) == lex_cast(m1))); 351 sub(n2, n1, n2); 352 mpz_sub(&m2.m_mpz, &m1.m_mpz, &m2.m_mpz); 353 REQUIRE((lex_cast(n1) == lex_cast(m1))); 354 REQUIRE((lex_cast(n2) == lex_cast(m2))); 355 sub(n1, n1, n1); 356 mpz_sub(&m1.m_mpz, &m1.m_mpz, &m1.m_mpz); 357 REQUIRE((lex_cast(n1) == lex_cast(m1))); 358 if (y > x) { 359 random_integer(tmp, x, rng); 360 mpz_set(&m2.m_mpz, &tmp.m_mpz); 361 n2 = &tmp.m_mpz; 362 if (sdist(rng)) { 363 mpz_neg(&m2.m_mpz, &m2.m_mpz); 364 n2.neg(); 365 } 366 max_integer(tmp, y); 367 mpz_set(&m3.m_mpz, &tmp.m_mpz); 368 n3 = &tmp.m_mpz; 369 if (sdist(rng)) { 370 mpz_neg(&m3.m_mpz, &m3.m_mpz); 371 n3.neg(); 372 } 373 sub(n1, n2, n3); 374 mpz_sub(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz); 375 REQUIRE((lex_cast(n1) == lex_cast(m1))); 376 } 377 if (x == y) { 378 random_integer(tmp, x, rng); 379 mpz_set(&m2.m_mpz, &tmp.m_mpz); 380 n2 = &tmp.m_mpz; 381 const bool neg = sdist(rng) == 1; 382 if (neg) { 383 mpz_neg(&m2.m_mpz, &m2.m_mpz); 384 n2.neg(); 385 } 386 mpz_set(&m3.m_mpz, &tmp.m_mpz); 387 n3 = &tmp.m_mpz; 388 if (!neg) { 389 mpz_neg(&m3.m_mpz, &m3.m_mpz); 390 n3.neg(); 391 } 392 sub(n1, n2, n3); 393 mpz_sub(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz); 394 REQUIRE((lex_cast(n1) == lex_cast(m1))); 395 } 396 if (x == y) { 397 random_integer(tmp, x, rng); 398 mpz_set(&m2.m_mpz, &tmp.m_mpz); 399 n2 = &tmp.m_mpz; 400 const bool neg = sdist(rng) == 1; 401 if (neg) { 402 mpz_neg(&m2.m_mpz, &m2.m_mpz); 403 n2.neg(); 404 } 405 mpz_set(&m3.m_mpz, &tmp.m_mpz); 406 n3 = &tmp.m_mpz; 407 if (!neg) { 408 mpz_neg(&m3.m_mpz, &m3.m_mpz); 409 n3.neg(); 410 } 411 } 412 } 413 }; 414 415 random_xy(1, 0); 416 random_xy(0, 1); 417 random_xy(1, 1); 418 419 random_xy(0, 2); 420 random_xy(1, 2); 421 random_xy(2, 0); 422 random_xy(2, 1); 423 random_xy(2, 2); 424 425 random_xy(0, 3); 426 random_xy(1, 3); 427 random_xy(2, 3); 428 random_xy(3, 0); 429 random_xy(3, 1); 430 random_xy(3, 2); 431 random_xy(3, 3); 432 433 random_xy(0, 4); 434 random_xy(1, 4); 435 random_xy(2, 4); 436 random_xy(3, 4); 437 random_xy(4, 0); 438 random_xy(4, 1); 439 random_xy(4, 2); 440 random_xy(4, 3); 441 random_xy(4, 4); 442 443 // Testing specific to the 2-limb optimisation. 444 if (S::value == 2u) { 445 max_integer(m2, 1u); 446 mpz_set_ui(&m3.m_mpz, 1u); 447 n2 = integer(::mp_limb_t(-1) & GMP_NUMB_MAX); 448 n3 = integer(1); 449 mpz_sub(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz); 450 sub(n1, n2, n3); 451 REQUIRE((lex_cast(n1) == lex_cast(m1))); 452 mpz_sub(&m1.m_mpz, &m3.m_mpz, &m2.m_mpz); 453 sub(n1, n3, n2); 454 REQUIRE((lex_cast(n1) == lex_cast(m1))); 455 max_integer(m2, 2u); 456 mpz_set_ui(&m3.m_mpz, 1u); 457 mpz_mul_2exp(&m3.m_mpz, &m3.m_mpz, GMP_NUMB_BITS); 458 n2 = integer(lex_cast(m2)); 459 n3 = integer(lex_cast(m3)); 460 mpz_sub(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz); 461 sub(n1, n2, n3); 462 REQUIRE((lex_cast(n1) == lex_cast(m1))); 463 n1 = integer{}; 464 mpz_sub(&m1.m_mpz, &m3.m_mpz, &m2.m_mpz); 465 sub(n1, n3, n2); 466 REQUIRE((lex_cast(n1) == lex_cast(m1))); 467 n1 = integer{}; 468 max_integer(m2, 2u); 469 mpz_set_ui(&m3.m_mpz, 1u); 470 mpz_mul_2exp(&m3.m_mpz, &m3.m_mpz, GMP_NUMB_BITS); 471 mpz_sub_ui(&m3.m_mpz, &m3.m_mpz, 1u); 472 n2 = integer(lex_cast(m2)); 473 n3 = integer(lex_cast(m3)); 474 mpz_sub(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz); 475 sub(n1, n2, n3); 476 REQUIRE((lex_cast(n1) == lex_cast(m1))); 477 n1 = integer{}; 478 mpz_sub(&m1.m_mpz, &m3.m_mpz, &m2.m_mpz); 479 sub(n1, n3, n2); 480 REQUIRE((lex_cast(n1) == lex_cast(m1))); 481 n1 = integer{}; 482 max_integer(m2, 2u); 483 max_integer(m3, 1u); 484 mpz_mul_2exp(&m3.m_mpz, &m3.m_mpz, GMP_NUMB_BITS); 485 mpz_neg(&m3.m_mpz, &m3.m_mpz); 486 n2 = integer(lex_cast(m2)); 487 n3 = integer(lex_cast(m3)); 488 mpz_sub(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz); 489 sub(n1, n2, n3); 490 REQUIRE((lex_cast(n1) == lex_cast(m1))); 491 mpz_sub(&m1.m_mpz, &m3.m_mpz, &m2.m_mpz); 492 sub(n1, n3, n2); 493 REQUIRE((lex_cast(n1) == lex_cast(m1))); 494 mpz_neg(&m3.m_mpz, &m3.m_mpz); 495 mpz_neg(&m2.m_mpz, &m2.m_mpz); 496 n2 = integer(lex_cast(m2)); 497 n3 = integer(lex_cast(m3)); 498 mpz_sub(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz); 499 sub(n1, n2, n3); 500 REQUIRE((lex_cast(n1) == lex_cast(m1))); 501 mpz_sub(&m1.m_mpz, &m3.m_mpz, &m2.m_mpz); 502 sub(n1, n3, n2); 503 REQUIRE((lex_cast(n1) == lex_cast(m1))); 504 max_integer(m2, 2u); 505 max_integer(m3, 1u); 506 mpz_neg(&m3.m_mpz, &m3.m_mpz); 507 n2 = integer(lex_cast(m2)); 508 n3 = integer(lex_cast(m3)); 509 mpz_sub(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz); 510 sub(n1, n2, n3); 511 REQUIRE((lex_cast(n1) == lex_cast(m1))); 512 mpz_sub(&m1.m_mpz, &m3.m_mpz, &m2.m_mpz); 513 sub(n1, n3, n2); 514 REQUIRE((lex_cast(n1) == lex_cast(m1))); 515 mpz_neg(&m3.m_mpz, &m3.m_mpz); 516 mpz_neg(&m2.m_mpz, &m2.m_mpz); 517 n2 = integer(lex_cast(m2)); 518 n3 = integer(lex_cast(m3)); 519 mpz_sub(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz); 520 sub(n1, n2, n3); 521 REQUIRE((lex_cast(n1) == lex_cast(m1))); 522 mpz_sub(&m1.m_mpz, &m3.m_mpz, &m2.m_mpz); 523 sub(n1, n3, n2); 524 REQUIRE((lex_cast(n1) == lex_cast(m1))); 525 } 526 } 527 }; 528 529 TEST_CASE("sub") 530 { 531 tuple_for_each(sizes{}, sub_tester{}); 532 } 533 534 struct mul_tester { 535 template <typename S> operator ()mul_tester536 inline void operator()(const S &) const 537 { 538 using integer = integer<S::value>; 539 // Start with zeroes. 540 detail::mpz_raii m1, m2, m3; 541 integer n1, n2, n3; 542 REQUIRE(&mul(n1, n2, n3) == &n1); 543 mpz_mul(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz); 544 REQUIRE((lex_cast(n1) == lex_cast(m1))); 545 REQUIRE(n1.is_static()); 546 REQUIRE(n2.is_static()); 547 REQUIRE(n3.is_static()); 548 n1 = integer(12); 549 mpz_set_ui(&m1.m_mpz, 12); 550 mul(n1, n2, n3); 551 mpz_mul(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz); 552 REQUIRE((lex_cast(n1) == lex_cast(m1))); 553 REQUIRE(n1.is_static()); 554 REQUIRE(n2.is_static()); 555 REQUIRE(n3.is_static()); 556 mul(n1, n3, n2); 557 mpz_mul(&m1.m_mpz, &m3.m_mpz, &m2.m_mpz); 558 REQUIRE((lex_cast(n1) == lex_cast(m1))); 559 REQUIRE(n1.is_static()); 560 REQUIRE(n2.is_static()); 561 REQUIRE(n3.is_static()); 562 detail::mpz_raii tmp; 563 std::uniform_int_distribution<int> sdist(0, 1); 564 // Run a variety of tests with operands with x and y number of limbs. 565 auto random_xy = [&](unsigned x, unsigned y) { 566 for (int i = 0; i < ntries; ++i) { 567 random_integer(tmp, x, rng); 568 mpz_set(&m2.m_mpz, &tmp.m_mpz); 569 n2 = &tmp.m_mpz; 570 if (sdist(rng)) { 571 mpz_neg(&m2.m_mpz, &m2.m_mpz); 572 n2.neg(); 573 } 574 if (n2.is_static() && sdist(rng)) { 575 // Promote sometimes, if possible. 576 n2.promote(); 577 } 578 random_integer(tmp, y, rng); 579 mpz_set(&m3.m_mpz, &tmp.m_mpz); 580 n3 = &tmp.m_mpz; 581 if (sdist(rng)) { 582 mpz_neg(&m3.m_mpz, &m3.m_mpz); 583 n3.neg(); 584 } 585 if (n3.is_static() && sdist(rng)) { 586 // Promote sometimes, if possible. 587 n3.promote(); 588 } 589 // NOLINTNEXTLINE(misc-redundant-expression) 590 if (sdist(rng) && sdist(rng) && sdist(rng)) { 591 // Reset rop every once in a while. 592 n1 = integer{}; 593 } 594 mul(n1, n2, n3); 595 mpz_mul(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz); 596 REQUIRE((lex_cast(n1) == lex_cast(m1))); 597 // In-place variations. 598 random_integer(tmp, x, rng); 599 mpz_set(&m2.m_mpz, &tmp.m_mpz); 600 n2 = &tmp.m_mpz; 601 if (sdist(rng)) { 602 mpz_neg(&m2.m_mpz, &m2.m_mpz); 603 n2.neg(); 604 } 605 random_integer(tmp, y, rng); 606 mpz_set(&m3.m_mpz, &tmp.m_mpz); 607 n3 = &tmp.m_mpz; 608 if (sdist(rng)) { 609 mpz_neg(&m3.m_mpz, &m3.m_mpz); 610 n3.neg(); 611 } 612 mul(n2, n2, n3); 613 mpz_mul(&m2.m_mpz, &m2.m_mpz, &m3.m_mpz); 614 REQUIRE((lex_cast(n2) == lex_cast(m2))); 615 random_integer(tmp, x, rng); 616 mpz_set(&m2.m_mpz, &tmp.m_mpz); 617 n2 = &tmp.m_mpz; 618 if (sdist(rng)) { 619 mpz_neg(&m2.m_mpz, &m2.m_mpz); 620 n2.neg(); 621 } 622 random_integer(tmp, y, rng); 623 mpz_set(&m3.m_mpz, &tmp.m_mpz); 624 n3 = &tmp.m_mpz; 625 if (sdist(rng)) { 626 mpz_neg(&m3.m_mpz, &m3.m_mpz); 627 n3.neg(); 628 } 629 mul(n2, n3, n2); 630 mpz_mul(&m2.m_mpz, &m3.m_mpz, &m2.m_mpz); 631 REQUIRE((lex_cast(n2) == lex_cast(m2))); 632 random_integer(tmp, x, rng); 633 mpz_set(&m2.m_mpz, &tmp.m_mpz); 634 n2 = &tmp.m_mpz; 635 if (sdist(rng)) { 636 mpz_neg(&m2.m_mpz, &m2.m_mpz); 637 n2.neg(); 638 } 639 mul(n2, n2, n2); 640 mpz_mul(&m2.m_mpz, &m2.m_mpz, &m2.m_mpz); 641 REQUIRE((lex_cast(n2) == lex_cast(m2))); 642 // Specific test for single-limb optimization. 643 if (S::value == 1u && x == 1u && y == 1u) { 644 n1 = integer{}; 645 random_integer(tmp, 1, rng, ::mp_limb_t(1) << (GMP_NUMB_BITS / 2)); 646 mpz_set(&m2.m_mpz, &tmp.m_mpz); 647 n2 = &tmp.m_mpz; 648 if (sdist(rng)) { 649 n2.neg(); 650 mpz_neg(&m2.m_mpz, &m2.m_mpz); 651 } 652 random_integer(tmp, 1, rng, ::mp_limb_t(1) << (GMP_NUMB_BITS / 2)); 653 mpz_set(&m3.m_mpz, &tmp.m_mpz); 654 n3 = &tmp.m_mpz; 655 if (sdist(rng)) { 656 n3.neg(); 657 mpz_neg(&m3.m_mpz, &m3.m_mpz); 658 } 659 mul(n1, n2, n3); 660 mpz_mul(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz); 661 REQUIRE((lex_cast(n1) == lex_cast(m1))); 662 } 663 // Make sure we test 2 x 1 when it succeeds. 664 if (S::value == 2u && x == 1u && y == 2u) { 665 n1 = integer{}; 666 mpz_set_ui(&m2.m_mpz, 1); 667 n2 = integer(1); 668 if (sdist(rng)) { 669 n2.neg(); 670 mpz_neg(&m2.m_mpz, &m2.m_mpz); 671 } 672 random_integer(tmp, y, rng); 673 mpz_set(&m3.m_mpz, &tmp.m_mpz); 674 n3 = &tmp.m_mpz; 675 if (sdist(rng)) { 676 n3.neg(); 677 mpz_neg(&m3.m_mpz, &m3.m_mpz); 678 } 679 mul(n1, n2, n3); 680 mpz_mul(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz); 681 REQUIRE((lex_cast(n1) == lex_cast(m1))); 682 } 683 // When using mpn, test a case in which we can write directly to the output operand, after 684 // verifying that the size fits. 685 if (S::value == 3u && x == 1u && y == 3u) { 686 n1 = integer{}; 687 mpz_set_ui(&m2.m_mpz, 1); 688 n2 = integer(1); 689 if (sdist(rng)) { 690 n2.neg(); 691 mpz_neg(&m2.m_mpz, &m2.m_mpz); 692 } 693 random_integer(tmp, y, rng); 694 mpz_set(&m3.m_mpz, &tmp.m_mpz); 695 n3 = &tmp.m_mpz; 696 if (sdist(rng)) { 697 n3.neg(); 698 mpz_neg(&m3.m_mpz, &m3.m_mpz); 699 } 700 mul(n1, n2, n3); 701 mpz_mul(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz); 702 REQUIRE((lex_cast(n1) == lex_cast(m1))); 703 } 704 } 705 }; 706 707 random_xy(1, 0); 708 random_xy(0, 1); 709 random_xy(1, 1); 710 711 random_xy(0, 2); 712 random_xy(1, 2); 713 random_xy(2, 0); 714 random_xy(2, 1); 715 random_xy(2, 2); 716 717 random_xy(0, 3); 718 random_xy(1, 3); 719 random_xy(2, 3); 720 random_xy(3, 0); 721 random_xy(3, 1); 722 random_xy(3, 2); 723 random_xy(3, 3); 724 725 random_xy(0, 4); 726 random_xy(1, 4); 727 random_xy(2, 4); 728 random_xy(3, 4); 729 random_xy(4, 0); 730 random_xy(4, 1); 731 random_xy(4, 2); 732 random_xy(4, 3); 733 random_xy(4, 4); 734 } 735 }; 736 737 TEST_CASE("mul") 738 { 739 tuple_for_each(sizes{}, mul_tester{}); 740 } 741 742 struct addmul_tester { 743 template <typename S> operator ()addmul_tester744 inline void operator()(const S &) const 745 { 746 using integer = integer<S::value>; 747 // Start with zeroes. 748 detail::mpz_raii m1, m2, m3; 749 integer n1, n2, n3; 750 REQUIRE(&addmul(n1, n2, n3) == &n1); 751 mpz_addmul(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz); 752 REQUIRE((lex_cast(n1) == lex_cast(m1))); 753 REQUIRE(n1.is_static()); 754 REQUIRE(n2.is_static()); 755 REQUIRE(n3.is_static()); 756 n1 = integer(12); 757 mpz_set_ui(&m1.m_mpz, 12); 758 addmul(n1, n2, n3); 759 mpz_addmul(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz); 760 REQUIRE((lex_cast(n1) == lex_cast(m1))); 761 REQUIRE(n1.is_static()); 762 REQUIRE(n2.is_static()); 763 REQUIRE(n3.is_static()); 764 addmul(n1, n3, n2); 765 mpz_addmul(&m1.m_mpz, &m3.m_mpz, &m2.m_mpz); 766 REQUIRE((lex_cast(n1) == lex_cast(m1))); 767 REQUIRE(n1.is_static()); 768 REQUIRE(n2.is_static()); 769 REQUIRE(n3.is_static()); 770 detail::mpz_raii tmp; 771 std::uniform_int_distribution<int> sdist(0, 1); 772 // Run a variety of tests with operands with x and y number of limbs. 773 auto random_xy = [&](unsigned x, unsigned y) { 774 for (int i = 0; i < ntries; ++i) { 775 random_integer(tmp, x, rng); 776 mpz_set(&m2.m_mpz, &tmp.m_mpz); 777 n2 = &tmp.m_mpz; 778 if (n2.is_static() && sdist(rng)) { 779 // Promote sometimes, if possible. 780 n2.promote(); 781 } 782 if (sdist(rng)) { 783 mpz_neg(&m2.m_mpz, &m2.m_mpz); 784 n2.neg(); 785 } 786 random_integer(tmp, y, rng); 787 mpz_set(&m3.m_mpz, &tmp.m_mpz); 788 n3 = &tmp.m_mpz; 789 if (n3.is_static() && sdist(rng)) { 790 // Promote sometimes, if possible. 791 n3.promote(); 792 } 793 if (sdist(rng)) { 794 mpz_neg(&m3.m_mpz, &m3.m_mpz); 795 n3.neg(); 796 } 797 // NOLINTNEXTLINE(misc-redundant-expression) 798 if (sdist(rng) && sdist(rng) && sdist(rng)) { 799 // Reset rop every once in a while. 800 n1 = integer{}; 801 mpz_set_ui(&m1.m_mpz, 0); 802 } 803 addmul(n1, n2, n3); 804 mpz_addmul(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz); 805 REQUIRE((lex_cast(n1) == lex_cast(m1))); 806 // In-place variations. 807 random_integer(tmp, x, rng); 808 mpz_set(&m2.m_mpz, &tmp.m_mpz); 809 n2 = &tmp.m_mpz; 810 if (n2.is_static() && sdist(rng)) { 811 // Promote sometimes, if possible. 812 n2.promote(); 813 } 814 if (sdist(rng)) { 815 mpz_neg(&m2.m_mpz, &m2.m_mpz); 816 n2.neg(); 817 } 818 random_integer(tmp, y, rng); 819 mpz_set(&m3.m_mpz, &tmp.m_mpz); 820 n3 = &tmp.m_mpz; 821 if (n3.is_static() && sdist(rng)) { 822 // Promote sometimes, if possible. 823 n3.promote(); 824 } 825 if (sdist(rng)) { 826 mpz_neg(&m3.m_mpz, &m3.m_mpz); 827 n3.neg(); 828 } 829 addmul(n2, n2, n3); 830 mpz_addmul(&m2.m_mpz, &m2.m_mpz, &m3.m_mpz); 831 REQUIRE((lex_cast(n2) == lex_cast(m2))); 832 random_integer(tmp, x, rng); 833 mpz_set(&m2.m_mpz, &tmp.m_mpz); 834 n2 = &tmp.m_mpz; 835 if (n2.is_static() && sdist(rng)) { 836 // Promote sometimes, if possible. 837 n2.promote(); 838 } 839 if (sdist(rng)) { 840 mpz_neg(&m2.m_mpz, &m2.m_mpz); 841 n2.neg(); 842 } 843 random_integer(tmp, y, rng); 844 mpz_set(&m3.m_mpz, &tmp.m_mpz); 845 n3 = &tmp.m_mpz; 846 if (sdist(rng)) { 847 mpz_neg(&m3.m_mpz, &m3.m_mpz); 848 n3.neg(); 849 } 850 if (n3.is_static() && sdist(rng)) { 851 // Promote sometimes, if possible. 852 n3.promote(); 853 } 854 addmul(n2, n3, n2); 855 mpz_addmul(&m2.m_mpz, &m3.m_mpz, &m2.m_mpz); 856 REQUIRE((lex_cast(n2) == lex_cast(m2))); 857 random_integer(tmp, x, rng); 858 mpz_set(&m2.m_mpz, &tmp.m_mpz); 859 n2 = &tmp.m_mpz; 860 if (n2.is_static() && sdist(rng)) { 861 // Promote sometimes, if possible. 862 n2.promote(); 863 } 864 if (sdist(rng)) { 865 mpz_neg(&m2.m_mpz, &m2.m_mpz); 866 n2.neg(); 867 } 868 addmul(n2, n2, n2); 869 mpz_addmul(&m2.m_mpz, &m2.m_mpz, &m2.m_mpz); 870 REQUIRE((lex_cast(n2) == lex_cast(m2))); 871 // Specific test for single-limb optimization. 872 if (S::value == 1u && x == 1u && y == 1u) { 873 // Check when product succeeds but add fails. 874 max_integer(tmp, 1); 875 mpz_set(&m1.m_mpz, &tmp.m_mpz); 876 n1 = &tmp.m_mpz; 877 mpz_set_ui(&m2.m_mpz, 2); 878 n2 = integer(2); 879 mpz_set_ui(&m3.m_mpz, 2); 880 n3 = integer(2); 881 addmul(n1, n2, n3); 882 mpz_addmul(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz); 883 REQUIRE((lex_cast(n1) == lex_cast(m1))); 884 // Prod cancels rop. 885 std::uniform_int_distribution<int> idist(1, 40); 886 int i2 = -idist(rng), i3 = idist(rng), i1 = -i2 * i3; 887 n1 = integer(i1); 888 n2 = integer(i2); 889 n3 = integer(i3); 890 addmul(n1, n2, n3); 891 mpz_set_si(&m1.m_mpz, i1); 892 mpz_set_si(&m2.m_mpz, i2); 893 mpz_set_si(&m3.m_mpz, i3); 894 mpz_addmul(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz); 895 REQUIRE((lex_cast(n1) == lex_cast(m1))); 896 // Prod different sign from rop and larger in abs. 897 i2 = -idist(rng), i3 = idist(rng), i1 = -i2 * i3 - 1; 898 n1 = integer(i1); 899 n2 = integer(i2); 900 n3 = integer(i3); 901 addmul(n1, n2, n3); 902 mpz_set_si(&m1.m_mpz, i1); 903 mpz_set_si(&m2.m_mpz, i2); 904 mpz_set_si(&m3.m_mpz, i3); 905 mpz_addmul(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz); 906 REQUIRE((lex_cast(n1) == lex_cast(m1))); 907 } 908 // Make sure we test 2 x 1 when it succeeds. 909 if (S::value == 2u && x == 1u && y == 2u) { 910 n1 = integer{1}; 911 mpz_set_ui(&m1.m_mpz, 1); 912 mpz_set_ui(&m2.m_mpz, 1); 913 n2 = integer(1); 914 if (sdist(rng)) { 915 n2.neg(); 916 mpz_neg(&m2.m_mpz, &m2.m_mpz); 917 } 918 random_integer(tmp, y, rng); 919 mpz_set(&m3.m_mpz, &tmp.m_mpz); 920 n3 = &tmp.m_mpz; 921 if (sdist(rng)) { 922 n3.neg(); 923 mpz_neg(&m3.m_mpz, &m3.m_mpz); 924 } 925 addmul(n1, n2, n3); 926 mpz_addmul(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz); 927 REQUIRE((lex_cast(n1) == lex_cast(m1))); 928 } 929 // SSize 2, diff signs, abs(rop) >= abs(prod), result size 1. 930 if (S::value == 2) { 931 random_integer(tmp, 1, rng); 932 mpz_set(&m1.m_mpz, &tmp.m_mpz); 933 n1 = &tmp.m_mpz; 934 mpz_set_si(&m2.m_mpz, -1); 935 n2 = integer(-1); 936 std::uniform_int_distribution<int> idist(1, 40); 937 auto i1 = idist(rng); 938 mpz_set_si(&m3.m_mpz, i1); 939 n3 = integer(i1); 940 addmul(n1, n2, n3); 941 mpz_addmul(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz); 942 REQUIRE((lex_cast(n1) == lex_cast(m1))); 943 } 944 // Overflow in the addition. 945 if (S::value == 2) { 946 max_integer(tmp, 2); 947 mpz_set(&m1.m_mpz, &tmp.m_mpz); 948 n1 = &tmp.m_mpz; 949 std::uniform_int_distribution<int> idist(1, 40); 950 auto i1 = idist(rng); 951 mpz_set_si(&m2.m_mpz, i1); 952 n2 = integer(i1); 953 i1 = idist(rng); 954 mpz_set_si(&m3.m_mpz, i1); 955 n3 = integer(i1); 956 addmul(n1, n2, n3); 957 mpz_addmul(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz); 958 REQUIRE((lex_cast(n1) == lex_cast(m1))); 959 } 960 // SSize 2, diff signs, abs(rop) >= abs(prod), result size 2. 961 if (S::value == 2) { 962 random_integer(tmp, 2, rng); 963 mpz_set(&m1.m_mpz, &tmp.m_mpz); 964 n1 = &tmp.m_mpz; 965 mpz_set_si(&m2.m_mpz, -1); 966 n2 = integer(-1); 967 std::uniform_int_distribution<int> idist(1, 40); 968 auto i1 = idist(rng); 969 mpz_set_si(&m3.m_mpz, i1); 970 n3 = integer(i1); 971 addmul(n1, n2, n3); 972 mpz_addmul(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz); 973 REQUIRE((lex_cast(n1) == lex_cast(m1))); 974 } 975 // SSize 2, diff signs, final result is zero. 976 if (S::value == 2) { 977 std::uniform_int_distribution<int> idist(1, 40); 978 auto i1 = idist(rng), i2 = idist(rng); 979 mpz_set_si(&m1.m_mpz, i1 * i2); 980 n1 = integer(i1 * i2); 981 mpz_set_si(&m2.m_mpz, i1); 982 n2 = integer(i1); 983 mpz_set_si(&m3.m_mpz, -i2); 984 n3 = integer(-i2); 985 addmul(n1, n2, n3); 986 mpz_addmul(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz); 987 REQUIRE((lex_cast(n1) == lex_cast(m1))); 988 } 989 } 990 }; 991 992 random_xy(1, 0); 993 random_xy(0, 1); 994 random_xy(1, 1); 995 996 random_xy(0, 2); 997 random_xy(1, 2); 998 random_xy(2, 0); 999 random_xy(2, 1); 1000 random_xy(2, 2); 1001 1002 random_xy(0, 3); 1003 random_xy(1, 3); 1004 random_xy(2, 3); 1005 random_xy(3, 0); 1006 random_xy(3, 1); 1007 random_xy(3, 2); 1008 random_xy(3, 3); 1009 1010 random_xy(0, 4); 1011 random_xy(1, 4); 1012 random_xy(2, 4); 1013 random_xy(3, 4); 1014 random_xy(4, 0); 1015 random_xy(4, 1); 1016 random_xy(4, 2); 1017 random_xy(4, 3); 1018 random_xy(4, 4); 1019 } 1020 }; 1021 1022 TEST_CASE("addmul") 1023 { 1024 tuple_for_each(sizes{}, addmul_tester{}); 1025 } 1026 1027 struct submul_tester { 1028 template <typename S> operator ()submul_tester1029 inline void operator()(const S &) const 1030 { 1031 using integer = integer<S::value>; 1032 // Start with zeroes. 1033 detail::mpz_raii m1, m2, m3; 1034 integer n1, n2, n3; 1035 REQUIRE(&submul(n1, n2, n3) == &n1); 1036 mpz_submul(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz); 1037 REQUIRE((lex_cast(n1) == lex_cast(m1))); 1038 REQUIRE(n1.is_static()); 1039 REQUIRE(n2.is_static()); 1040 REQUIRE(n3.is_static()); 1041 n1 = integer(12); 1042 mpz_set_ui(&m1.m_mpz, 12); 1043 submul(n1, n2, n3); 1044 mpz_submul(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz); 1045 REQUIRE((lex_cast(n1) == lex_cast(m1))); 1046 REQUIRE(n1.is_static()); 1047 REQUIRE(n2.is_static()); 1048 REQUIRE(n3.is_static()); 1049 submul(n1, n3, n2); 1050 mpz_submul(&m1.m_mpz, &m3.m_mpz, &m2.m_mpz); 1051 REQUIRE((lex_cast(n1) == lex_cast(m1))); 1052 REQUIRE(n1.is_static()); 1053 REQUIRE(n2.is_static()); 1054 REQUIRE(n3.is_static()); 1055 detail::mpz_raii tmp; 1056 std::uniform_int_distribution<int> sdist(0, 1); 1057 // Run a variety of tests with operands with x and y number of limbs. 1058 auto random_xy = [&](unsigned x, unsigned y) { 1059 for (int i = 0; i < ntries; ++i) { 1060 random_integer(tmp, x, rng); 1061 mpz_set(&m2.m_mpz, &tmp.m_mpz); 1062 n2 = &tmp.m_mpz; 1063 if (n2.is_static() && sdist(rng)) { 1064 // Promote sometimes, if possible. 1065 n2.promote(); 1066 } 1067 if (sdist(rng)) { 1068 mpz_neg(&m2.m_mpz, &m2.m_mpz); 1069 n2.neg(); 1070 } 1071 random_integer(tmp, y, rng); 1072 mpz_set(&m3.m_mpz, &tmp.m_mpz); 1073 n3 = &tmp.m_mpz; 1074 if (n3.is_static() && sdist(rng)) { 1075 // Promote sometimes, if possible. 1076 n3.promote(); 1077 } 1078 if (sdist(rng)) { 1079 mpz_neg(&m3.m_mpz, &m3.m_mpz); 1080 n3.neg(); 1081 } 1082 // NOLINTNEXTLINE(misc-redundant-expression) 1083 if (sdist(rng) && sdist(rng) && sdist(rng)) { 1084 // Reset rop every once in a while. 1085 n1 = integer{}; 1086 mpz_set_ui(&m1.m_mpz, 0); 1087 } 1088 submul(n1, n2, n3); 1089 mpz_submul(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz); 1090 REQUIRE((lex_cast(n1) == lex_cast(m1))); 1091 // In-place variations. 1092 random_integer(tmp, x, rng); 1093 mpz_set(&m2.m_mpz, &tmp.m_mpz); 1094 n2 = &tmp.m_mpz; 1095 if (n2.is_static() && sdist(rng)) { 1096 // Promote sometimes, if possible. 1097 n2.promote(); 1098 } 1099 if (sdist(rng)) { 1100 mpz_neg(&m2.m_mpz, &m2.m_mpz); 1101 n2.neg(); 1102 } 1103 random_integer(tmp, y, rng); 1104 mpz_set(&m3.m_mpz, &tmp.m_mpz); 1105 n3 = &tmp.m_mpz; 1106 if (n3.is_static() && sdist(rng)) { 1107 // Promote sometimes, if possible. 1108 n3.promote(); 1109 } 1110 if (sdist(rng)) { 1111 mpz_neg(&m3.m_mpz, &m3.m_mpz); 1112 n3.neg(); 1113 } 1114 submul(n2, n2, n3); 1115 mpz_submul(&m2.m_mpz, &m2.m_mpz, &m3.m_mpz); 1116 REQUIRE((lex_cast(n2) == lex_cast(m2))); 1117 random_integer(tmp, x, rng); 1118 mpz_set(&m2.m_mpz, &tmp.m_mpz); 1119 n2 = &tmp.m_mpz; 1120 if (n2.is_static() && sdist(rng)) { 1121 // Promote sometimes, if possible. 1122 n2.promote(); 1123 } 1124 if (sdist(rng)) { 1125 mpz_neg(&m2.m_mpz, &m2.m_mpz); 1126 n2.neg(); 1127 } 1128 random_integer(tmp, y, rng); 1129 mpz_set(&m3.m_mpz, &tmp.m_mpz); 1130 n3 = &tmp.m_mpz; 1131 if (sdist(rng)) { 1132 mpz_neg(&m3.m_mpz, &m3.m_mpz); 1133 n3.neg(); 1134 } 1135 if (n3.is_static() && sdist(rng)) { 1136 // Promote sometimes, if possible. 1137 n3.promote(); 1138 } 1139 submul(n2, n3, n2); 1140 mpz_submul(&m2.m_mpz, &m3.m_mpz, &m2.m_mpz); 1141 REQUIRE((lex_cast(n2) == lex_cast(m2))); 1142 random_integer(tmp, x, rng); 1143 mpz_set(&m2.m_mpz, &tmp.m_mpz); 1144 n2 = &tmp.m_mpz; 1145 if (n2.is_static() && sdist(rng)) { 1146 // Promote sometimes, if possible. 1147 n2.promote(); 1148 } 1149 if (sdist(rng)) { 1150 mpz_neg(&m2.m_mpz, &m2.m_mpz); 1151 n2.neg(); 1152 } 1153 submul(n2, n2, n2); 1154 mpz_submul(&m2.m_mpz, &m2.m_mpz, &m2.m_mpz); 1155 REQUIRE((lex_cast(n2) == lex_cast(m2))); 1156 // Specific test for single-limb optimization. 1157 if (S::value == 1u && x == 1u && y == 1u) { 1158 // Check when product succeeds but sub fails. 1159 max_integer(tmp, 1); 1160 mpz_neg(&tmp.m_mpz, &tmp.m_mpz); 1161 mpz_set(&m1.m_mpz, &tmp.m_mpz); 1162 n1 = &tmp.m_mpz; 1163 mpz_set_ui(&m2.m_mpz, 2); 1164 n2 = integer(2); 1165 mpz_set_ui(&m3.m_mpz, 2); 1166 n3 = integer(2); 1167 submul(n1, n2, n3); 1168 mpz_submul(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz); 1169 REQUIRE((lex_cast(n1) == lex_cast(m1))); 1170 // Prod cancels rop. 1171 std::uniform_int_distribution<int> idist(1, 40); 1172 int i2 = -idist(rng), i3 = idist(rng), i1 = i2 * i3; 1173 n1 = integer(i1); 1174 n2 = integer(i2); 1175 n3 = integer(i3); 1176 submul(n1, n2, n3); 1177 mpz_set_si(&m1.m_mpz, i1); 1178 mpz_set_si(&m2.m_mpz, i2); 1179 mpz_set_si(&m3.m_mpz, i3); 1180 mpz_submul(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz); 1181 REQUIRE((lex_cast(n1) == lex_cast(m1))); 1182 // Prod different sign from rop and larger in abs. 1183 i2 = -idist(rng), i3 = idist(rng), i1 = i2 * i3 + 1; 1184 n1 = integer(i1); 1185 n2 = integer(i2); 1186 n3 = integer(i3); 1187 submul(n1, n2, n3); 1188 mpz_set_si(&m1.m_mpz, i1); 1189 mpz_set_si(&m2.m_mpz, i2); 1190 mpz_set_si(&m3.m_mpz, i3); 1191 mpz_submul(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz); 1192 REQUIRE((lex_cast(n1) == lex_cast(m1))); 1193 } 1194 // Make sure we test 2 x 1 when it succeeds. 1195 if (S::value == 2u && x == 1u && y == 2u) { 1196 n1 = integer{1}; 1197 mpz_set_ui(&m1.m_mpz, 1); 1198 mpz_set_ui(&m2.m_mpz, 1); 1199 n2 = integer(1); 1200 if (sdist(rng)) { 1201 n2.neg(); 1202 mpz_neg(&m2.m_mpz, &m2.m_mpz); 1203 } 1204 random_integer(tmp, y, rng); 1205 mpz_set(&m3.m_mpz, &tmp.m_mpz); 1206 n3 = &tmp.m_mpz; 1207 if (sdist(rng)) { 1208 n3.neg(); 1209 mpz_neg(&m3.m_mpz, &m3.m_mpz); 1210 } 1211 submul(n1, n2, n3); 1212 mpz_submul(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz); 1213 REQUIRE((lex_cast(n1) == lex_cast(m1))); 1214 } 1215 // SSize 2, diff signs, abs(rop) >= abs(prod), result size 1. 1216 if (S::value == 2) { 1217 random_integer(tmp, 1, rng); 1218 mpz_set(&m1.m_mpz, &tmp.m_mpz); 1219 n1 = &tmp.m_mpz; 1220 mpz_set_si(&m2.m_mpz, 1); 1221 n2 = integer(1); 1222 std::uniform_int_distribution<int> idist(1, 40); 1223 auto i1 = idist(rng); 1224 mpz_set_si(&m3.m_mpz, i1); 1225 n3 = integer(i1); 1226 submul(n1, n2, n3); 1227 mpz_submul(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz); 1228 REQUIRE((lex_cast(n1) == lex_cast(m1))); 1229 } 1230 // Overflow in the addition. 1231 if (S::value == 2) { 1232 max_integer(tmp, 2); 1233 mpz_set(&m1.m_mpz, &tmp.m_mpz); 1234 n1 = &tmp.m_mpz; 1235 std::uniform_int_distribution<int> idist(-40, -1); 1236 auto i1 = idist(rng); 1237 mpz_set_si(&m2.m_mpz, i1); 1238 n2 = integer(i1); 1239 i1 = idist(rng); 1240 mpz_set_si(&m3.m_mpz, i1); 1241 n3 = integer(i1); 1242 submul(n1, n2, n3); 1243 mpz_submul(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz); 1244 REQUIRE((lex_cast(n1) == lex_cast(m1))); 1245 } 1246 // SSize 2, diff signs, abs(rop) >= abs(prod), result size 2. 1247 if (S::value == 2) { 1248 random_integer(tmp, 2, rng); 1249 mpz_set(&m1.m_mpz, &tmp.m_mpz); 1250 n1 = &tmp.m_mpz; 1251 mpz_set_si(&m2.m_mpz, -1); 1252 n2 = integer(-1); 1253 std::uniform_int_distribution<int> idist(-40, -1); 1254 auto i1 = idist(rng); 1255 mpz_set_si(&m3.m_mpz, i1); 1256 n3 = integer(i1); 1257 submul(n1, n2, n3); 1258 mpz_submul(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz); 1259 REQUIRE((lex_cast(n1) == lex_cast(m1))); 1260 } 1261 // SSize 2, diff signs, final result is zero. 1262 if (S::value == 2) { 1263 std::uniform_int_distribution<int> idist(-40, -1); 1264 auto i1 = idist(rng), i2 = idist(rng); 1265 mpz_set_si(&m1.m_mpz, i1 * i2); 1266 n1 = integer(i1 * i2); 1267 mpz_set_si(&m2.m_mpz, i1); 1268 n2 = integer(i1); 1269 mpz_set_si(&m3.m_mpz, -i2); 1270 n3 = integer(-i2); 1271 submul(n1, n2, n3); 1272 mpz_submul(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz); 1273 REQUIRE((lex_cast(n1) == lex_cast(m1))); 1274 } 1275 } 1276 }; 1277 1278 random_xy(1, 0); 1279 random_xy(0, 1); 1280 random_xy(1, 1); 1281 1282 random_xy(0, 2); 1283 random_xy(1, 2); 1284 random_xy(2, 0); 1285 random_xy(2, 1); 1286 random_xy(2, 2); 1287 1288 random_xy(0, 3); 1289 random_xy(1, 3); 1290 random_xy(2, 3); 1291 random_xy(3, 0); 1292 random_xy(3, 1); 1293 random_xy(3, 2); 1294 random_xy(3, 3); 1295 1296 random_xy(0, 4); 1297 random_xy(1, 4); 1298 random_xy(2, 4); 1299 random_xy(3, 4); 1300 random_xy(4, 0); 1301 random_xy(4, 1); 1302 random_xy(4, 2); 1303 random_xy(4, 3); 1304 random_xy(4, 4); 1305 } 1306 }; 1307 1308 TEST_CASE("submul") 1309 { 1310 tuple_for_each(sizes{}, submul_tester{}); 1311 } 1312 1313 struct div_tester { 1314 template <typename S> operator ()div_tester1315 inline void operator()(const S &) const 1316 { 1317 using integer = integer<S::value>; 1318 detail::mpz_raii m1, m2, m3, m4; 1319 integer n1, n2, n3, n4; 1320 // A few simple tests to start. 1321 n3 = integer(12); 1322 n4 = integer(5); 1323 mpz_set_ui(&m3.m_mpz, 12); 1324 mpz_set_ui(&m4.m_mpz, 5); 1325 tdiv_qr(n1, n2, n3, n4); 1326 mpz_tdiv_qr(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz, &m4.m_mpz); 1327 REQUIRE((lex_cast(n1) == lex_cast(m1))); 1328 REQUIRE((lex_cast(n2) == lex_cast(m2))); 1329 n3 = integer(-12); 1330 mpz_set_si(&m3.m_mpz, -12); 1331 tdiv_qr(n1, n2, n3, n4); 1332 mpz_tdiv_qr(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz, &m4.m_mpz); 1333 REQUIRE((lex_cast(n1) == lex_cast(m1))); 1334 REQUIRE((lex_cast(n2) == lex_cast(m2))); 1335 n4 = integer(-5); 1336 mpz_set_si(&m4.m_mpz, -5); 1337 tdiv_qr(n1, n2, n3, n4); 1338 mpz_tdiv_qr(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz, &m4.m_mpz); 1339 REQUIRE((lex_cast(n1) == lex_cast(m1))); 1340 REQUIRE((lex_cast(n2) == lex_cast(m2))); 1341 n3 = integer(12); 1342 mpz_set_ui(&m3.m_mpz, 12); 1343 tdiv_qr(n1, n2, n3, n4); 1344 mpz_tdiv_qr(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz, &m4.m_mpz); 1345 REQUIRE((lex_cast(n1) == lex_cast(m1))); 1346 REQUIRE((lex_cast(n2) == lex_cast(m2))); 1347 // Random testing. 1348 detail::mpz_raii tmp; 1349 std::uniform_int_distribution<int> sdist(0, 1); 1350 auto random_xy = [&](unsigned x, unsigned y) { 1351 for (int i = 0; i < ntries; ++i) { 1352 // Helper to generate randomly dividend and divisor. 1353 auto random_34 = [&]() { 1354 random_integer(tmp, x, rng); 1355 mpz_set(&m3.m_mpz, &tmp.m_mpz); 1356 n3 = &tmp.m_mpz; 1357 if (sdist(rng)) { 1358 mpz_neg(&m3.m_mpz, &m3.m_mpz); 1359 n3.neg(); 1360 } 1361 if (n3.is_static() && sdist(rng)) { 1362 // Promote sometimes, if possible. 1363 n3.promote(); 1364 } 1365 // Make sure divisor is not zero. 1366 do { 1367 random_integer(tmp, y, rng); 1368 mpz_set(&m4.m_mpz, &tmp.m_mpz); 1369 n4 = &tmp.m_mpz; 1370 if (sdist(rng)) { 1371 mpz_neg(&m4.m_mpz, &m4.m_mpz); 1372 n4.neg(); 1373 } 1374 if (n4.is_static() && sdist(rng)) { 1375 // Promote sometimes, if possible. 1376 n4.promote(); 1377 } 1378 } while (n4.sgn() == 0); 1379 }; 1380 random_34(); 1381 // Reset rops every once in a while. 1382 // NOLINTNEXTLINE(misc-redundant-expression) 1383 if (sdist(rng) && sdist(rng) && sdist(rng)) { 1384 n1 = integer{}; 1385 mpz_set_ui(&m1.m_mpz, 0); 1386 } 1387 // NOLINTNEXTLINE(misc-redundant-expression) 1388 if (sdist(rng) && sdist(rng) && sdist(rng)) { 1389 n2 = integer{}; 1390 mpz_set_ui(&m2.m_mpz, 0); 1391 } 1392 tdiv_qr(n1, n2, n3, n4); 1393 mpz_tdiv_qr(&m1.m_mpz, &m2.m_mpz, &m3.m_mpz, &m4.m_mpz); 1394 REQUIRE((lex_cast(n1) == lex_cast(m1))); 1395 REQUIRE((lex_cast(n2) == lex_cast(m2))); 1396 // In-place variations. 1397 random_34(); 1398 tdiv_qr(n1, n3, n3, n4); 1399 mpz_tdiv_qr(&m1.m_mpz, &m3.m_mpz, &m3.m_mpz, &m4.m_mpz); 1400 REQUIRE((lex_cast(n1) == lex_cast(m1))); 1401 REQUIRE((lex_cast(n3) == lex_cast(m3))); 1402 random_34(); 1403 tdiv_qr(n1, n4, n3, n4); 1404 mpz_tdiv_qr(&m1.m_mpz, &m4.m_mpz, &m3.m_mpz, &m4.m_mpz); 1405 REQUIRE((lex_cast(n1) == lex_cast(m1))); 1406 REQUIRE((lex_cast(n4) == lex_cast(m4))); 1407 random_34(); 1408 tdiv_qr(n1, n2, n4, n4); 1409 mpz_tdiv_qr(&m1.m_mpz, &m2.m_mpz, &m4.m_mpz, &m4.m_mpz); 1410 REQUIRE((lex_cast(n1) == lex_cast(m1))); 1411 REQUIRE((lex_cast(n2) == lex_cast(m2))); 1412 random_34(); 1413 tdiv_qr(n1, n4, n4, n4); 1414 mpz_tdiv_qr(&m1.m_mpz, &m4.m_mpz, &m4.m_mpz, &m4.m_mpz); 1415 REQUIRE((lex_cast(n1) == lex_cast(m1))); 1416 REQUIRE((lex_cast(n4) == lex_cast(m4))); 1417 random_34(); 1418 tdiv_qr(n4, n2, n4, n4); 1419 mpz_tdiv_qr(&m4.m_mpz, &m2.m_mpz, &m4.m_mpz, &m4.m_mpz); 1420 REQUIRE((lex_cast(n4) == lex_cast(m4))); 1421 REQUIRE((lex_cast(n2) == lex_cast(m2))); 1422 } 1423 // Error handling. 1424 n3 = integer(12); 1425 n4 = integer(0); 1426 REQUIRE_THROWS_PREDICATE(tdiv_qr(n1, n2, n3, n4), zero_division_error, [](const zero_division_error &ex) { 1427 return std::string(ex.what()) == "Integer division by zero"; 1428 }); 1429 REQUIRE_THROWS_PREDICATE( 1430 tdiv_qr(n1, n1, n3, n3), std::invalid_argument, [](const std::invalid_argument &ex) { 1431 return std::string(ex.what()) 1432 == "When performing a division with remainder, the quotient 'q' and the " 1433 "remainder 'r' must be distinct objects"; 1434 }); 1435 }; 1436 1437 random_xy(0, 1); 1438 random_xy(1, 1); 1439 1440 random_xy(0, 2); 1441 random_xy(1, 2); 1442 random_xy(2, 1); 1443 random_xy(2, 2); 1444 1445 random_xy(0, 3); 1446 random_xy(1, 3); 1447 random_xy(2, 3); 1448 random_xy(3, 1); 1449 random_xy(3, 2); 1450 random_xy(3, 3); 1451 1452 random_xy(0, 4); 1453 random_xy(1, 4); 1454 random_xy(2, 4); 1455 random_xy(3, 4); 1456 random_xy(4, 1); 1457 random_xy(4, 2); 1458 random_xy(4, 3); 1459 random_xy(4, 4); 1460 } 1461 }; 1462 1463 TEST_CASE("div") 1464 { 1465 tuple_for_each(sizes{}, div_tester{}); 1466 } 1467 1468 struct lshift_tester { 1469 template <typename S> operator ()lshift_tester1470 inline void operator()(const S &) const 1471 { 1472 using integer = integer<S::value>; 1473 // A few zero tests to start. 1474 detail::mpz_raii m1, m2; 1475 integer n1, n2; 1476 REQUIRE(&mul_2exp(n1, n2, 0u) == &n1); 1477 mpz_mul_2exp(&m1.m_mpz, &m2.m_mpz, 0u); 1478 REQUIRE((lex_cast(n1) == lex_cast(m1))); 1479 n2 = integer(4); 1480 mpz_set_ui(&m2.m_mpz, 4); 1481 mul_2exp(n1, n2, 0u); 1482 mpz_mul_2exp(&m1.m_mpz, &m2.m_mpz, 0u); 1483 REQUIRE((lex_cast(n1) == lex_cast(m1))); 1484 n2 = integer(-4); 1485 mpz_set_si(&m2.m_mpz, -4); 1486 mul_2exp(n1, n2, 0u); 1487 mpz_mul_2exp(&m1.m_mpz, &m2.m_mpz, 0u); 1488 REQUIRE((lex_cast(n1) == lex_cast(m1))); 1489 n2 = integer(0); 1490 mpz_set_ui(&m2.m_mpz, 0); 1491 mul_2exp(n1, n2, 4u); 1492 mpz_mul_2exp(&m1.m_mpz, &m2.m_mpz, 0u); 1493 REQUIRE((lex_cast(n1) == lex_cast(m1))); 1494 // Simple tests. 1495 n2 = integer(12); 1496 mpz_set_ui(&m2.m_mpz, 12); 1497 mul_2exp(n1, n2, 2u); 1498 mpz_mul_2exp(&m1.m_mpz, &m2.m_mpz, 2u); 1499 REQUIRE((lex_cast(n1) == lex_cast(m1))); 1500 n2 = integer(-12); 1501 mpz_set_si(&m2.m_mpz, -12); 1502 mul_2exp(n1, n2, 2u); 1503 mpz_mul_2exp(&m1.m_mpz, &m2.m_mpz, 2u); 1504 REQUIRE((lex_cast(n1) == lex_cast(m1))); 1505 // Random testing. 1506 detail::mpz_raii tmp; 1507 std::uniform_int_distribution<int> sdist(0, 1); 1508 auto random_x = [&](unsigned x) { 1509 for (int i = 0; i < ntries; ++i) { 1510 // Half limb shift. 1511 // NOLINTNEXTLINE(misc-redundant-expression) 1512 if (sdist(rng) && sdist(rng) && sdist(rng)) { 1513 n1 = integer{}; 1514 mpz_set_ui(&m1.m_mpz, 0); 1515 } 1516 random_integer(tmp, x, rng); 1517 std::uniform_int_distribution<unsigned> bdh(0u, GMP_NUMB_BITS / 2u); 1518 n2 = &tmp.m_mpz; 1519 if (n2.is_static() && sdist(rng)) { 1520 // Promote sometimes, if possible. 1521 n2.promote(); 1522 } 1523 mpz_set(&m2.m_mpz, &tmp.m_mpz); 1524 auto rbs = bdh(rng); 1525 mul_2exp(n1, n2, rbs); 1526 mpz_mul_2exp(&m1.m_mpz, &m2.m_mpz, rbs); 1527 REQUIRE((lex_cast(n1) == lex_cast(m1))); 1528 // Try in-place as well. 1529 mul_2exp(n2, n2, rbs); 1530 mpz_mul_2exp(&m2.m_mpz, &m2.m_mpz, rbs); 1531 REQUIRE((lex_cast(n2) == lex_cast(m2))); 1532 // 1 limb shift. 1533 // NOLINTNEXTLINE(misc-redundant-expression) 1534 if (sdist(rng) && sdist(rng) && sdist(rng)) { 1535 n1 = integer{}; 1536 mpz_set_ui(&m1.m_mpz, 0); 1537 } 1538 random_integer(tmp, x, rng); 1539 std::uniform_int_distribution<unsigned> bd1(0u, GMP_NUMB_BITS); 1540 n2 = &tmp.m_mpz; 1541 if (n2.is_static() && sdist(rng)) { 1542 // Promote sometimes, if possible. 1543 n2.promote(); 1544 } 1545 mpz_set(&m2.m_mpz, &tmp.m_mpz); 1546 if (sdist(rng)) { 1547 mpz_neg(&m2.m_mpz, &m2.m_mpz); 1548 n2.neg(); 1549 } 1550 rbs = bd1(rng); 1551 mul_2exp(n1, n2, rbs); 1552 mpz_mul_2exp(&m1.m_mpz, &m2.m_mpz, rbs); 1553 REQUIRE((lex_cast(n1) == lex_cast(m1))); 1554 mul_2exp(n2, n2, rbs); 1555 mpz_mul_2exp(&m2.m_mpz, &m2.m_mpz, rbs); 1556 REQUIRE((lex_cast(n2) == lex_cast(m2))); 1557 // 1 and half limb shift. 1558 // NOLINTNEXTLINE(misc-redundant-expression) 1559 if (sdist(rng) && sdist(rng) && sdist(rng)) { 1560 n1 = integer{}; 1561 mpz_set_ui(&m1.m_mpz, 0); 1562 } 1563 random_integer(tmp, x, rng); 1564 std::uniform_int_distribution<unsigned> bd1h(0u, GMP_NUMB_BITS + GMP_NUMB_BITS / 2u); 1565 n2 = &tmp.m_mpz; 1566 if (n2.is_static() && sdist(rng)) { 1567 // Promote sometimes, if possible. 1568 n2.promote(); 1569 } 1570 mpz_set(&m2.m_mpz, &tmp.m_mpz); 1571 if (sdist(rng)) { 1572 mpz_neg(&m2.m_mpz, &m2.m_mpz); 1573 n2.neg(); 1574 } 1575 rbs = bd1h(rng); 1576 mul_2exp(n1, n2, rbs); 1577 mpz_mul_2exp(&m1.m_mpz, &m2.m_mpz, rbs); 1578 REQUIRE((lex_cast(n1) == lex_cast(m1))); 1579 mul_2exp(n2, n2, rbs); 1580 mpz_mul_2exp(&m2.m_mpz, &m2.m_mpz, rbs); 1581 REQUIRE((lex_cast(n2) == lex_cast(m2))); 1582 // 2 limbs shift. 1583 // NOLINTNEXTLINE(misc-redundant-expression) 1584 if (sdist(rng) && sdist(rng) && sdist(rng)) { 1585 n1 = integer{}; 1586 mpz_set_ui(&m1.m_mpz, 0); 1587 } 1588 random_integer(tmp, x, rng); 1589 std::uniform_int_distribution<unsigned> bd2(0u, GMP_NUMB_BITS * 2u); 1590 n2 = &tmp.m_mpz; 1591 if (n2.is_static() && sdist(rng)) { 1592 // Promote sometimes, if possible. 1593 n2.promote(); 1594 } 1595 mpz_set(&m2.m_mpz, &tmp.m_mpz); 1596 if (sdist(rng)) { 1597 mpz_neg(&m2.m_mpz, &m2.m_mpz); 1598 n2.neg(); 1599 } 1600 rbs = bd2(rng); 1601 mul_2exp(n1, n2, rbs); 1602 mpz_mul_2exp(&m1.m_mpz, &m2.m_mpz, rbs); 1603 REQUIRE((lex_cast(n1) == lex_cast(m1))); 1604 mul_2exp(n2, n2, rbs); 1605 mpz_mul_2exp(&m2.m_mpz, &m2.m_mpz, rbs); 1606 REQUIRE((lex_cast(n2) == lex_cast(m2))); 1607 // 2 and half limbs shift. 1608 // NOLINTNEXTLINE(misc-redundant-expression) 1609 if (sdist(rng) && sdist(rng) && sdist(rng)) { 1610 n1 = integer{}; 1611 mpz_set_ui(&m1.m_mpz, 0); 1612 } 1613 random_integer(tmp, x, rng); 1614 std::uniform_int_distribution<unsigned> bd2h(0u, GMP_NUMB_BITS * 2u + GMP_NUMB_BITS / 2u); 1615 n2 = &tmp.m_mpz; 1616 if (n2.is_static() && sdist(rng)) { 1617 // Promote sometimes, if possible. 1618 n2.promote(); 1619 } 1620 mpz_set(&m2.m_mpz, &tmp.m_mpz); 1621 if (sdist(rng)) { 1622 mpz_neg(&m2.m_mpz, &m2.m_mpz); 1623 n2.neg(); 1624 } 1625 rbs = bd2h(rng); 1626 mul_2exp(n1, n2, rbs); 1627 mpz_mul_2exp(&m1.m_mpz, &m2.m_mpz, rbs); 1628 REQUIRE((lex_cast(n1) == lex_cast(m1))); 1629 mul_2exp(n2, n2, rbs); 1630 mpz_mul_2exp(&m2.m_mpz, &m2.m_mpz, rbs); 1631 REQUIRE((lex_cast(n2) == lex_cast(m2))); 1632 // 3 limbs shift. 1633 // NOLINTNEXTLINE(misc-redundant-expression) 1634 if (sdist(rng) && sdist(rng) && sdist(rng)) { 1635 n1 = integer{}; 1636 mpz_set_ui(&m1.m_mpz, 0); 1637 } 1638 random_integer(tmp, x, rng); 1639 std::uniform_int_distribution<unsigned> bd3(0u, GMP_NUMB_BITS * 3u); 1640 n2 = &tmp.m_mpz; 1641 if (n2.is_static() && sdist(rng)) { 1642 // Promote sometimes, if possible. 1643 n2.promote(); 1644 } 1645 mpz_set(&m2.m_mpz, &tmp.m_mpz); 1646 if (sdist(rng)) { 1647 mpz_neg(&m2.m_mpz, &m2.m_mpz); 1648 n2.neg(); 1649 } 1650 rbs = bd3(rng); 1651 mul_2exp(n1, n2, rbs); 1652 mpz_mul_2exp(&m1.m_mpz, &m2.m_mpz, rbs); 1653 REQUIRE((lex_cast(n1) == lex_cast(m1))); 1654 mul_2exp(n2, n2, rbs); 1655 mpz_mul_2exp(&m2.m_mpz, &m2.m_mpz, rbs); 1656 REQUIRE((lex_cast(n2) == lex_cast(m2))); 1657 // 3 and half limbs shift. 1658 // NOLINTNEXTLINE(misc-redundant-expression) 1659 if (sdist(rng) && sdist(rng) && sdist(rng)) { 1660 n1 = integer{}; 1661 mpz_set_ui(&m1.m_mpz, 0); 1662 } 1663 random_integer(tmp, x, rng); 1664 std::uniform_int_distribution<unsigned> bd3h(0u, GMP_NUMB_BITS * 3u + GMP_NUMB_BITS / 2u); 1665 n2 = &tmp.m_mpz; 1666 if (n2.is_static() && sdist(rng)) { 1667 // Promote sometimes, if possible. 1668 n2.promote(); 1669 } 1670 mpz_set(&m2.m_mpz, &tmp.m_mpz); 1671 if (sdist(rng)) { 1672 mpz_neg(&m2.m_mpz, &m2.m_mpz); 1673 n2.neg(); 1674 } 1675 rbs = bd3h(rng); 1676 mul_2exp(n1, n2, rbs); 1677 mpz_mul_2exp(&m1.m_mpz, &m2.m_mpz, rbs); 1678 REQUIRE((lex_cast(n1) == lex_cast(m1))); 1679 mul_2exp(n2, n2, rbs); 1680 mpz_mul_2exp(&m2.m_mpz, &m2.m_mpz, rbs); 1681 REQUIRE((lex_cast(n2) == lex_cast(m2))); 1682 // 4 limbs shift. 1683 // NOLINTNEXTLINE(misc-redundant-expression) 1684 if (sdist(rng) && sdist(rng) && sdist(rng)) { 1685 n1 = integer{}; 1686 mpz_set_ui(&m1.m_mpz, 0); 1687 } 1688 random_integer(tmp, x, rng); 1689 std::uniform_int_distribution<unsigned> bd4(0u, GMP_NUMB_BITS * 4u); 1690 n2 = &tmp.m_mpz; 1691 if (n2.is_static() && sdist(rng)) { 1692 // Promote sometimes, if possible. 1693 n2.promote(); 1694 } 1695 mpz_set(&m2.m_mpz, &tmp.m_mpz); 1696 if (sdist(rng)) { 1697 mpz_neg(&m2.m_mpz, &m2.m_mpz); 1698 n2.neg(); 1699 } 1700 rbs = bd4(rng); 1701 mul_2exp(n1, n2, rbs); 1702 mpz_mul_2exp(&m1.m_mpz, &m2.m_mpz, rbs); 1703 REQUIRE((lex_cast(n1) == lex_cast(m1))); 1704 mul_2exp(n2, n2, rbs); 1705 mpz_mul_2exp(&m2.m_mpz, &m2.m_mpz, rbs); 1706 REQUIRE((lex_cast(n2) == lex_cast(m2))); 1707 // 4 limbs and half shift. 1708 // NOLINTNEXTLINE(misc-redundant-expression) 1709 if (sdist(rng) && sdist(rng) && sdist(rng)) { 1710 n1 = integer{}; 1711 mpz_set_ui(&m1.m_mpz, 0); 1712 } 1713 random_integer(tmp, x, rng); 1714 std::uniform_int_distribution<unsigned> bd4h(0u, GMP_NUMB_BITS * 4u + GMP_NUMB_BITS / 2u); 1715 n2 = &tmp.m_mpz; 1716 if (n2.is_static() && sdist(rng)) { 1717 // Promote sometimes, if possible. 1718 n2.promote(); 1719 } 1720 mpz_set(&m2.m_mpz, &tmp.m_mpz); 1721 if (sdist(rng)) { 1722 mpz_neg(&m2.m_mpz, &m2.m_mpz); 1723 n2.neg(); 1724 } 1725 rbs = bd4h(rng); 1726 mul_2exp(n1, n2, rbs); 1727 mpz_mul_2exp(&m1.m_mpz, &m2.m_mpz, rbs); 1728 REQUIRE((lex_cast(n1) == lex_cast(m1))); 1729 mul_2exp(n2, n2, rbs); 1730 mpz_mul_2exp(&m2.m_mpz, &m2.m_mpz, rbs); 1731 REQUIRE((lex_cast(n2) == lex_cast(m2))); 1732 // 5 limbs shift. 1733 // NOLINTNEXTLINE(misc-redundant-expression) 1734 if (sdist(rng) && sdist(rng) && sdist(rng)) { 1735 n1 = integer{}; 1736 mpz_set_ui(&m1.m_mpz, 0); 1737 } 1738 random_integer(tmp, x, rng); 1739 std::uniform_int_distribution<unsigned> bd5(0u, GMP_NUMB_BITS * 5u); 1740 n2 = &tmp.m_mpz; 1741 if (n2.is_static() && sdist(rng)) { 1742 // Promote sometimes, if possible. 1743 n2.promote(); 1744 } 1745 mpz_set(&m2.m_mpz, &tmp.m_mpz); 1746 if (sdist(rng)) { 1747 mpz_neg(&m2.m_mpz, &m2.m_mpz); 1748 n2.neg(); 1749 } 1750 rbs = bd5(rng); 1751 mul_2exp(n1, n2, rbs); 1752 mpz_mul_2exp(&m1.m_mpz, &m2.m_mpz, rbs); 1753 REQUIRE((lex_cast(n1) == lex_cast(m1))); 1754 mul_2exp(n2, n2, rbs); 1755 mpz_mul_2exp(&m2.m_mpz, &m2.m_mpz, rbs); 1756 REQUIRE((lex_cast(n2) == lex_cast(m2))); 1757 } 1758 }; 1759 1760 random_x(0); 1761 random_x(1); 1762 random_x(2); 1763 random_x(3); 1764 random_x(4); 1765 } 1766 }; 1767 1768 TEST_CASE("lshift") 1769 { 1770 tuple_for_each(sizes{}, lshift_tester{}); 1771 } 1772 1773 struct rshift_tester { 1774 template <typename S> operator ()rshift_tester1775 inline void operator()(const S &) const 1776 { 1777 using integer = integer<S::value>; 1778 // A few zero tests to start. 1779 detail::mpz_raii m1, m2; 1780 integer n1, n2; 1781 REQUIRE(&tdiv_q_2exp(n1, n2, 0u) == &n1); 1782 mpz_tdiv_q_2exp(&m1.m_mpz, &m2.m_mpz, 0u); 1783 REQUIRE((lex_cast(n1) == lex_cast(m1))); 1784 n2 = integer(4); 1785 mpz_set_ui(&m2.m_mpz, 4); 1786 tdiv_q_2exp(n1, n2, 0u); 1787 mpz_tdiv_q_2exp(&m1.m_mpz, &m2.m_mpz, 0u); 1788 REQUIRE((lex_cast(n1) == lex_cast(m1))); 1789 n2 = integer(-4); 1790 mpz_set_si(&m2.m_mpz, -4); 1791 tdiv_q_2exp(n1, n2, 0u); 1792 mpz_tdiv_q_2exp(&m1.m_mpz, &m2.m_mpz, 0u); 1793 REQUIRE((lex_cast(n1) == lex_cast(m1))); 1794 n2 = integer(0); 1795 mpz_set_ui(&m2.m_mpz, 0); 1796 tdiv_q_2exp(n1, n2, 4u); 1797 mpz_tdiv_q_2exp(&m1.m_mpz, &m2.m_mpz, 0u); 1798 REQUIRE((lex_cast(n1) == lex_cast(m1))); 1799 // Simple tests. 1800 n2 = integer(12); 1801 mpz_set_ui(&m2.m_mpz, 12); 1802 tdiv_q_2exp(n1, n2, 2u); 1803 mpz_tdiv_q_2exp(&m1.m_mpz, &m2.m_mpz, 2u); 1804 REQUIRE((lex_cast(n1) == lex_cast(m1))); 1805 n2 = integer(-12); 1806 mpz_set_si(&m2.m_mpz, -12); 1807 tdiv_q_2exp(n1, n2, 2u); 1808 mpz_tdiv_q_2exp(&m1.m_mpz, &m2.m_mpz, 2u); 1809 REQUIRE((lex_cast(n1) == lex_cast(m1))); 1810 // Random testing. 1811 detail::mpz_raii tmp; 1812 std::uniform_int_distribution<int> sdist(0, 1); 1813 auto random_x = [&](unsigned x) { 1814 for (int i = 0; i < ntries; ++i) { 1815 // Half limb shift. 1816 // NOLINTNEXTLINE(misc-redundant-expression) 1817 if (sdist(rng) && sdist(rng) && sdist(rng)) { 1818 n1 = integer{}; 1819 mpz_set_ui(&m1.m_mpz, 0); 1820 } 1821 random_integer(tmp, x, rng); 1822 std::uniform_int_distribution<unsigned> bdh(0u, GMP_NUMB_BITS / 2u); 1823 n2 = &tmp.m_mpz; 1824 if (n2.is_static() && sdist(rng)) { 1825 // Promote sometimes, if possible. 1826 n2.promote(); 1827 } 1828 mpz_set(&m2.m_mpz, &tmp.m_mpz); 1829 auto rbs = bdh(rng); 1830 tdiv_q_2exp(n1, n2, rbs); 1831 mpz_tdiv_q_2exp(&m1.m_mpz, &m2.m_mpz, rbs); 1832 REQUIRE((lex_cast(n1) == lex_cast(m1))); 1833 // Try in-place as well. 1834 tdiv_q_2exp(n2, n2, rbs); 1835 mpz_tdiv_q_2exp(&m2.m_mpz, &m2.m_mpz, rbs); 1836 REQUIRE((lex_cast(n2) == lex_cast(m2))); 1837 // 1 limb shift. 1838 // NOLINTNEXTLINE(misc-redundant-expression) 1839 if (sdist(rng) && sdist(rng) && sdist(rng)) { 1840 n1 = integer{}; 1841 mpz_set_ui(&m1.m_mpz, 0); 1842 } 1843 random_integer(tmp, x, rng); 1844 std::uniform_int_distribution<unsigned> bd1(0u, GMP_NUMB_BITS); 1845 n2 = &tmp.m_mpz; 1846 if (n2.is_static() && sdist(rng)) { 1847 // Promote sometimes, if possible. 1848 n2.promote(); 1849 } 1850 mpz_set(&m2.m_mpz, &tmp.m_mpz); 1851 if (sdist(rng)) { 1852 mpz_neg(&m2.m_mpz, &m2.m_mpz); 1853 n2.neg(); 1854 } 1855 rbs = bd1(rng); 1856 tdiv_q_2exp(n1, n2, rbs); 1857 mpz_tdiv_q_2exp(&m1.m_mpz, &m2.m_mpz, rbs); 1858 REQUIRE((lex_cast(n1) == lex_cast(m1))); 1859 tdiv_q_2exp(n2, n2, rbs); 1860 mpz_tdiv_q_2exp(&m2.m_mpz, &m2.m_mpz, rbs); 1861 REQUIRE((lex_cast(n2) == lex_cast(m2))); 1862 // 1 and half limb shift. 1863 // NOLINTNEXTLINE(misc-redundant-expression) 1864 if (sdist(rng) && sdist(rng) && sdist(rng)) { 1865 n1 = integer{}; 1866 mpz_set_ui(&m1.m_mpz, 0); 1867 } 1868 random_integer(tmp, x, rng); 1869 std::uniform_int_distribution<unsigned> bd1h(0u, GMP_NUMB_BITS + GMP_NUMB_BITS / 2u); 1870 n2 = &tmp.m_mpz; 1871 if (n2.is_static() && sdist(rng)) { 1872 // Promote sometimes, if possible. 1873 n2.promote(); 1874 } 1875 mpz_set(&m2.m_mpz, &tmp.m_mpz); 1876 if (sdist(rng)) { 1877 mpz_neg(&m2.m_mpz, &m2.m_mpz); 1878 n2.neg(); 1879 } 1880 rbs = bd1h(rng); 1881 tdiv_q_2exp(n1, n2, rbs); 1882 mpz_tdiv_q_2exp(&m1.m_mpz, &m2.m_mpz, rbs); 1883 REQUIRE((lex_cast(n1) == lex_cast(m1))); 1884 tdiv_q_2exp(n2, n2, rbs); 1885 mpz_tdiv_q_2exp(&m2.m_mpz, &m2.m_mpz, rbs); 1886 REQUIRE((lex_cast(n2) == lex_cast(m2))); 1887 // 2 limbs shift. 1888 // NOLINTNEXTLINE(misc-redundant-expression) 1889 if (sdist(rng) && sdist(rng) && sdist(rng)) { 1890 n1 = integer{}; 1891 mpz_set_ui(&m1.m_mpz, 0); 1892 } 1893 random_integer(tmp, x, rng); 1894 std::uniform_int_distribution<unsigned> bd2(0u, GMP_NUMB_BITS * 2u); 1895 n2 = &tmp.m_mpz; 1896 if (n2.is_static() && sdist(rng)) { 1897 // Promote sometimes, if possible. 1898 n2.promote(); 1899 } 1900 mpz_set(&m2.m_mpz, &tmp.m_mpz); 1901 if (sdist(rng)) { 1902 mpz_neg(&m2.m_mpz, &m2.m_mpz); 1903 n2.neg(); 1904 } 1905 rbs = bd2(rng); 1906 tdiv_q_2exp(n1, n2, rbs); 1907 mpz_tdiv_q_2exp(&m1.m_mpz, &m2.m_mpz, rbs); 1908 REQUIRE((lex_cast(n1) == lex_cast(m1))); 1909 tdiv_q_2exp(n2, n2, rbs); 1910 mpz_tdiv_q_2exp(&m2.m_mpz, &m2.m_mpz, rbs); 1911 REQUIRE((lex_cast(n2) == lex_cast(m2))); 1912 // 2 and half limbs shift. 1913 // NOLINTNEXTLINE(misc-redundant-expression) 1914 if (sdist(rng) && sdist(rng) && sdist(rng)) { 1915 n1 = integer{}; 1916 mpz_set_ui(&m1.m_mpz, 0); 1917 } 1918 random_integer(tmp, x, rng); 1919 std::uniform_int_distribution<unsigned> bd2h(0u, GMP_NUMB_BITS * 2u + GMP_NUMB_BITS / 2u); 1920 n2 = &tmp.m_mpz; 1921 if (n2.is_static() && sdist(rng)) { 1922 // Promote sometimes, if possible. 1923 n2.promote(); 1924 } 1925 mpz_set(&m2.m_mpz, &tmp.m_mpz); 1926 if (sdist(rng)) { 1927 mpz_neg(&m2.m_mpz, &m2.m_mpz); 1928 n2.neg(); 1929 } 1930 rbs = bd2h(rng); 1931 tdiv_q_2exp(n1, n2, rbs); 1932 mpz_tdiv_q_2exp(&m1.m_mpz, &m2.m_mpz, rbs); 1933 REQUIRE((lex_cast(n1) == lex_cast(m1))); 1934 tdiv_q_2exp(n2, n2, rbs); 1935 mpz_tdiv_q_2exp(&m2.m_mpz, &m2.m_mpz, rbs); 1936 REQUIRE((lex_cast(n2) == lex_cast(m2))); 1937 // 3 limbs shift. 1938 // NOLINTNEXTLINE(misc-redundant-expression) 1939 if (sdist(rng) && sdist(rng) && sdist(rng)) { 1940 n1 = integer{}; 1941 mpz_set_ui(&m1.m_mpz, 0); 1942 } 1943 random_integer(tmp, x, rng); 1944 std::uniform_int_distribution<unsigned> bd3(0u, GMP_NUMB_BITS * 3u); 1945 n2 = &tmp.m_mpz; 1946 if (n2.is_static() && sdist(rng)) { 1947 // Promote sometimes, if possible. 1948 n2.promote(); 1949 } 1950 mpz_set(&m2.m_mpz, &tmp.m_mpz); 1951 if (sdist(rng)) { 1952 mpz_neg(&m2.m_mpz, &m2.m_mpz); 1953 n2.neg(); 1954 } 1955 rbs = bd3(rng); 1956 tdiv_q_2exp(n1, n2, rbs); 1957 mpz_tdiv_q_2exp(&m1.m_mpz, &m2.m_mpz, rbs); 1958 REQUIRE((lex_cast(n1) == lex_cast(m1))); 1959 tdiv_q_2exp(n2, n2, rbs); 1960 mpz_tdiv_q_2exp(&m2.m_mpz, &m2.m_mpz, rbs); 1961 REQUIRE((lex_cast(n2) == lex_cast(m2))); 1962 // 3 and half limbs shift. 1963 // NOLINTNEXTLINE(misc-redundant-expression) 1964 if (sdist(rng) && sdist(rng) && sdist(rng)) { 1965 n1 = integer{}; 1966 mpz_set_ui(&m1.m_mpz, 0); 1967 } 1968 random_integer(tmp, x, rng); 1969 std::uniform_int_distribution<unsigned> bd3h(0u, GMP_NUMB_BITS * 3u + GMP_NUMB_BITS / 2u); 1970 n2 = &tmp.m_mpz; 1971 if (n2.is_static() && sdist(rng)) { 1972 // Promote sometimes, if possible. 1973 n2.promote(); 1974 } 1975 mpz_set(&m2.m_mpz, &tmp.m_mpz); 1976 if (sdist(rng)) { 1977 mpz_neg(&m2.m_mpz, &m2.m_mpz); 1978 n2.neg(); 1979 } 1980 rbs = bd3h(rng); 1981 tdiv_q_2exp(n1, n2, rbs); 1982 mpz_tdiv_q_2exp(&m1.m_mpz, &m2.m_mpz, rbs); 1983 REQUIRE((lex_cast(n1) == lex_cast(m1))); 1984 tdiv_q_2exp(n2, n2, rbs); 1985 mpz_tdiv_q_2exp(&m2.m_mpz, &m2.m_mpz, rbs); 1986 REQUIRE((lex_cast(n2) == lex_cast(m2))); 1987 // 4 limbs shift. 1988 // NOLINTNEXTLINE(misc-redundant-expression) 1989 if (sdist(rng) && sdist(rng) && sdist(rng)) { 1990 n1 = integer{}; 1991 mpz_set_ui(&m1.m_mpz, 0); 1992 } 1993 random_integer(tmp, x, rng); 1994 std::uniform_int_distribution<unsigned> bd4(0u, GMP_NUMB_BITS * 4u); 1995 n2 = &tmp.m_mpz; 1996 if (n2.is_static() && sdist(rng)) { 1997 // Promote sometimes, if possible. 1998 n2.promote(); 1999 } 2000 mpz_set(&m2.m_mpz, &tmp.m_mpz); 2001 if (sdist(rng)) { 2002 mpz_neg(&m2.m_mpz, &m2.m_mpz); 2003 n2.neg(); 2004 } 2005 rbs = bd4(rng); 2006 tdiv_q_2exp(n1, n2, rbs); 2007 mpz_tdiv_q_2exp(&m1.m_mpz, &m2.m_mpz, rbs); 2008 REQUIRE((lex_cast(n1) == lex_cast(m1))); 2009 tdiv_q_2exp(n2, n2, rbs); 2010 mpz_tdiv_q_2exp(&m2.m_mpz, &m2.m_mpz, rbs); 2011 REQUIRE((lex_cast(n2) == lex_cast(m2))); 2012 // 4 limbs and half shift. 2013 // NOLINTNEXTLINE(misc-redundant-expression) 2014 if (sdist(rng) && sdist(rng) && sdist(rng)) { 2015 n1 = integer{}; 2016 mpz_set_ui(&m1.m_mpz, 0); 2017 } 2018 random_integer(tmp, x, rng); 2019 std::uniform_int_distribution<unsigned> bd4h(0u, GMP_NUMB_BITS * 4u + GMP_NUMB_BITS / 2u); 2020 n2 = &tmp.m_mpz; 2021 if (n2.is_static() && sdist(rng)) { 2022 // Promote sometimes, if possible. 2023 n2.promote(); 2024 } 2025 mpz_set(&m2.m_mpz, &tmp.m_mpz); 2026 if (sdist(rng)) { 2027 mpz_neg(&m2.m_mpz, &m2.m_mpz); 2028 n2.neg(); 2029 } 2030 rbs = bd4h(rng); 2031 tdiv_q_2exp(n1, n2, rbs); 2032 mpz_tdiv_q_2exp(&m1.m_mpz, &m2.m_mpz, rbs); 2033 REQUIRE((lex_cast(n1) == lex_cast(m1))); 2034 tdiv_q_2exp(n2, n2, rbs); 2035 mpz_tdiv_q_2exp(&m2.m_mpz, &m2.m_mpz, rbs); 2036 REQUIRE((lex_cast(n2) == lex_cast(m2))); 2037 // 5 limbs shift. 2038 // NOLINTNEXTLINE(misc-redundant-expression) 2039 if (sdist(rng) && sdist(rng) && sdist(rng)) { 2040 n1 = integer{}; 2041 mpz_set_ui(&m1.m_mpz, 0); 2042 } 2043 random_integer(tmp, x, rng); 2044 std::uniform_int_distribution<unsigned> bd5(0u, GMP_NUMB_BITS * 5u); 2045 n2 = &tmp.m_mpz; 2046 if (n2.is_static() && sdist(rng)) { 2047 // Promote sometimes, if possible. 2048 n2.promote(); 2049 } 2050 mpz_set(&m2.m_mpz, &tmp.m_mpz); 2051 if (sdist(rng)) { 2052 mpz_neg(&m2.m_mpz, &m2.m_mpz); 2053 n2.neg(); 2054 } 2055 rbs = bd5(rng); 2056 tdiv_q_2exp(n1, n2, rbs); 2057 mpz_tdiv_q_2exp(&m1.m_mpz, &m2.m_mpz, rbs); 2058 REQUIRE((lex_cast(n1) == lex_cast(m1))); 2059 tdiv_q_2exp(n2, n2, rbs); 2060 mpz_tdiv_q_2exp(&m2.m_mpz, &m2.m_mpz, rbs); 2061 REQUIRE((lex_cast(n2) == lex_cast(m2))); 2062 } 2063 }; 2064 2065 random_x(0); 2066 random_x(1); 2067 random_x(2); 2068 random_x(3); 2069 random_x(4); 2070 } 2071 }; 2072 2073 TEST_CASE("rshift") 2074 { 2075 tuple_for_each(sizes{}, rshift_tester{}); 2076 } 2077