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