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 <algorithm>
10 #include <complex>
11 #include <limits>
12 #include <type_traits>
13 #include <utility>
14 
15 #include <mp++/complex.hpp>
16 #include <mp++/config.hpp>
17 #include <mp++/detail/mpfr.hpp>
18 #include <mp++/integer.hpp>
19 #include <mp++/rational.hpp>
20 #include <mp++/real.hpp>
21 
22 #if defined(MPPP_WITH_QUADMATH)
23 
24 #include <mp++/complex128.hpp>
25 #include <mp++/real128.hpp>
26 
27 #endif
28 
29 #include "catch.hpp"
30 
31 // NOLINTNEXTLINE(google-build-using-namespace)
32 using namespace mppp;
33 
34 TEST_CASE("identity")
35 {
36     complex r1{4, 5};
37     REQUIRE(+r1 == r1);
38 
39     // Check stealing.
40     const auto p = r1.get_prec();
41     auto r2 = +std::move(r1);
42     REQUIRE(r2.get_prec() == p);
43     REQUIRE(r2 == complex{4, 5});
44     // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
45     REQUIRE(!r1.is_valid());
46 }
47 
48 TEST_CASE("increment")
49 {
50     complex r0{0};
51     REQUIRE(++r0 == 1);
52     REQUIRE(r0++ == 1);
53     REQUIRE(r0 == 2);
54 
55     // Check precision handling.
56     r0 = complex{0, complex_prec_t(4)};
57     ++r0;
58     REQUIRE(r0.get_prec() == detail::real_deduce_precision(1));
59     REQUIRE(r0 == 1);
60     r0 = complex{0, complex_prec_t(4)};
61     r0++;
62     REQUIRE(r0.get_prec() == detail::real_deduce_precision(1));
63     REQUIRE(r0 == 1);
64 }
65 
66 // NOLINTNEXTLINE(google-readability-function-size, hicpp-function-size, readability-function-size)
67 TEST_CASE("binary plus")
68 {
69     // complex-complex.
70     {
71         complex r1{4, 5}, r2{-4, 7};
72         const auto p = r1.get_prec();
73         auto ret = r1 + r2;
74         REQUIRE(std::is_same<complex, decltype(ret)>::value);
75         REQUIRE(ret == complex{0, 12});
76         REQUIRE(ret.get_prec() == r1.get_prec());
77 
78         // Test moves.
79         ret = std::move(r1) + r2;
80         REQUIRE(ret == complex{0, 12});
81         REQUIRE(ret.get_prec() == p);
82         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
83         REQUIRE(!r1.is_valid());
84 
85         r1 = complex{4, 5};
86         ret = r1 + std::move(r2);
87         REQUIRE(ret == complex{0, 12});
88         REQUIRE(ret.get_prec() == p);
89         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
90         REQUIRE(!r2.is_valid());
91 
92         r2 = complex{-4, 7};
93         ret = std::move(r1) + std::move(r2);
94         REQUIRE(ret == complex{0, 12});
95         REQUIRE(ret.get_prec() == p);
96         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
97         REQUIRE((!r1.is_valid() || !r2.is_valid()));
98 
99         // Self add.
100         r2 = complex{-4, 6};
101         REQUIRE(r2 + r2 == complex{-8, 12});
102     }
103     // complex-real.
104     {
105         complex c1{45, 6, complex_prec_t(128)};
106         real r1{23, 10};
107         auto ret = c1 + r1;
108         REQUIRE(std::is_same<complex, decltype(ret)>::value);
109         REQUIRE(ret == complex{68, 6, complex_prec_t(128)});
110         REQUIRE(ret.get_prec() == 128);
111         ret = r1 + c1;
112         REQUIRE(std::is_same<complex, decltype(r1 + c1)>::value);
113         REQUIRE(ret == complex{68, 6, complex_prec_t(128)});
114         REQUIRE(ret.get_prec() == 128);
115 
116         // Try with higher precision on the non-complex argument.
117         ret = c1 + real{23, 256};
118         REQUIRE(ret == complex{68, 6, complex_prec_t(128)});
119         REQUIRE(ret.get_prec() == 256);
120         ret = real{23, 256} + c1;
121         REQUIRE(ret == complex{68, 6, complex_prec_t(128)});
122         REQUIRE(ret.get_prec() == 256);
123 
124         // Try with moves.
125         auto c2 = c1;
126         ret = complex{};
127         ret = std::move(c1) + r1;
128         REQUIRE(ret == complex{68, 6, complex_prec_t(128)});
129         REQUIRE(ret.get_prec() == 128);
130         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
131         REQUIRE(!c1.is_valid());
132 
133         c1 = c2;
134         ret = complex{};
135         ret = r1 + std::move(c1);
136         REQUIRE(ret == complex{68, 6, complex_prec_t(128)});
137         REQUIRE(ret.get_prec() == 128);
138         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
139         REQUIRE(!c1.is_valid());
140     }
141     // complex-rv interoperable.
142     {
143         complex c1{45, 6, complex_prec_t(128)};
144         auto ret = c1 + 6;
145         REQUIRE(ret == complex{51, 6});
146         REQUIRE(std::is_same<complex, decltype(ret)>::value);
147         REQUIRE(ret.get_prec() == std::max<::mpfr_prec_t>(128, detail::real_deduce_precision(6)));
148         ret = 6. + c1;
149         REQUIRE(ret == complex{51, 6});
150         REQUIRE(std::is_same<complex, decltype(6. + c1)>::value);
151         REQUIRE(ret.get_prec() == std::max<::mpfr_prec_t>(128, detail::real_deduce_precision(6.)));
152 
153         // Try with higher precision on the non-complex argument.
154         c1 = complex{1, 1, complex_prec_t(real_prec_min())};
155         ret = c1 + 45_z1;
156         REQUIRE(ret == complex{46, 1});
157         REQUIRE(ret.get_prec() == detail::real_deduce_precision(45_z1));
158         ret = 45_q1 + c1;
159         REQUIRE(ret == complex{46, 1});
160         REQUIRE(ret.get_prec() == detail::real_deduce_precision(45_q1));
161 
162         // Moves.
163         auto c2 = c1;
164         ret = std::move(c1) + 45;
165         REQUIRE(ret == complex{46, 1});
166         REQUIRE(ret.get_prec() == detail::real_deduce_precision(45));
167         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
168         REQUIRE(c1.is_valid());
169         c1 = complex{1, 1, complex_prec_t(detail::real_deduce_precision(45) + 1)};
170         ret = std::move(c1) + 45;
171         REQUIRE(ret == complex{46, 1});
172         REQUIRE(ret.get_prec() == detail::real_deduce_precision(45) + 1);
173         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
174         REQUIRE(!c1.is_valid());
175 
176         c1 = c2;
177         ret = 45. + std::move(c1);
178         REQUIRE(ret == complex{46, 1});
179         REQUIRE(ret.get_prec() == detail::real_deduce_precision(45.));
180         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
181         REQUIRE(c1.is_valid());
182         c1 = complex{1, 1, complex_prec_t(detail::real_deduce_precision(45.) + 1)};
183         ret = 45. + std::move(c1);
184         REQUIRE(ret == complex{46, 1});
185         REQUIRE(ret.get_prec() == detail::real_deduce_precision(45.) + 1);
186         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
187         REQUIRE(!c1.is_valid());
188 
189 #if defined(MPPP_WITH_QUADMATH)
190         c1 = c2;
191         ret = 45_rq + std::move(c1);
192         REQUIRE(ret == complex{46, 1});
193         REQUIRE(ret.get_prec() == 113);
194         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
195         REQUIRE(c1.is_valid());
196         c1 = complex{1, 1, complex_prec_t(114)};
197         ret = 45_rq + std::move(c1);
198         REQUIRE(ret == complex{46, 1});
199         REQUIRE(ret.get_prec() == 114);
200         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
201         REQUIRE(!c1.is_valid());
202 #endif
203     }
204     // complex-unsigned integral.
205     {
206         complex c1{45, 6, complex_prec_t(128)};
207         auto ret = c1 + 6u;
208         REQUIRE(ret == complex{51, 6});
209         REQUIRE(std::is_same<complex, decltype(ret)>::value);
210         REQUIRE(ret.get_prec() == std::max<::mpfr_prec_t>(128, detail::real_deduce_precision(6u)));
211         ret = 6u + c1;
212         REQUIRE(ret == complex{51, 6});
213         REQUIRE(std::is_same<complex, decltype(6u + c1)>::value);
214         REQUIRE(ret.get_prec() == std::max<::mpfr_prec_t>(128, detail::real_deduce_precision(6u)));
215 
216         // Try with higher precision on the non-complex argument.
217         c1 = complex{1, 1, complex_prec_t(real_prec_min())};
218         ret = c1 + 45u;
219         REQUIRE(ret == complex{46, 1});
220         REQUIRE(ret.get_prec() == detail::real_deduce_precision(45u));
221         ret = 45u + c1;
222         REQUIRE(ret == complex{46, 1});
223         REQUIRE(ret.get_prec() == detail::real_deduce_precision(45u));
224 
225         // Moves.
226         auto c2 = c1;
227         ret = std::move(c1) + 45u;
228         REQUIRE(ret == complex{46, 1});
229         REQUIRE(ret.get_prec() == detail::real_deduce_precision(45u));
230         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
231         REQUIRE(c1.is_valid());
232         c1 = complex{1, 1, complex_prec_t(detail::real_deduce_precision(45u) + 1)};
233         ret = std::move(c1) + 45u;
234         REQUIRE(ret == complex{46, 1});
235         REQUIRE(ret.get_prec() == detail::real_deduce_precision(45u) + 1);
236         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
237         REQUIRE(!c1.is_valid());
238 
239         c1 = c2;
240         ret = 45u + std::move(c1);
241         REQUIRE(ret == complex{46, 1});
242         REQUIRE(ret.get_prec() == detail::real_deduce_precision(45u));
243         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
244         REQUIRE(c1.is_valid());
245         c1 = complex{1, 1, complex_prec_t(detail::real_deduce_precision(45u) + 1)};
246         ret = 45u + std::move(c1);
247         REQUIRE(ret == complex{46, 1});
248         REQUIRE(ret.get_prec() == detail::real_deduce_precision(45u) + 1);
249         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
250         REQUIRE(!c1.is_valid());
251 
252         // Bool special casing.
253         c1 = c2;
254         ret = true + c1;
255         REQUIRE(ret == complex{2, 1});
256         ret = c1 + false;
257         REQUIRE(ret == complex{1, 1});
258         ret = true + std::move(c1);
259         REQUIRE(ret == complex{2, 1});
260         c1 = c2;
261         ret = std::move(c1) + false;
262         REQUIRE(ret == complex{1, 1});
263 
264 #if defined(MPPP_HAVE_GCC_INT128)
265         // Try with a large integral.
266         c1 = c2;
267         ret = __uint128_t(-1) + std::move(c1);
268         REQUIRE(ret == complex{1_z1 + __uint128_t(-1), 1, complex_prec_t(128)});
269         REQUIRE(ret.get_prec() == 128);
270         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
271         REQUIRE(c1.is_valid());
272         c1 = complex{1, 1, complex_prec_t(129)};
273         ret = __uint128_t(-1) + std::move(c1);
274         REQUIRE(ret == complex{1_z1 + __uint128_t(-1), 1, complex_prec_t(129)});
275         REQUIRE(ret.get_prec() == 129);
276         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
277         REQUIRE(!c1.is_valid());
278 
279         c1 = c2;
280         ret = std::move(c1) + __uint128_t(-1);
281         REQUIRE(ret == complex{1_z1 + __uint128_t(-1), 1, complex_prec_t(128)});
282         REQUIRE(ret.get_prec() == 128);
283         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
284         REQUIRE(c1.is_valid());
285         c1 = complex{1, 1, complex_prec_t(129)};
286         ret = std::move(c1) + __uint128_t(-1);
287         REQUIRE(ret == complex{1_z1 + __uint128_t(-1), 1, complex_prec_t(129)});
288         REQUIRE(ret.get_prec() == 129);
289         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
290         REQUIRE(!c1.is_valid());
291 #endif
292     }
293 
294     // Complex-std::complex.
295     {
296         complex c1{45, 6, complex_prec_t(128)};
297         auto ret = c1 + std::complex<double>(6, 7);
298         REQUIRE(ret == complex{51, 13});
299         REQUIRE(std::is_same<complex, decltype(ret)>::value);
300         REQUIRE(ret.get_prec() == std::max<::mpfr_prec_t>(128, detail::real_deduce_precision(6.)));
301         ret = std::complex<double>(6, 7) + c1;
302         REQUIRE(ret == complex{51, 13});
303         REQUIRE(std::is_same<complex, decltype(std::complex<double>(6, 7) + c1)>::value);
304         REQUIRE(ret.get_prec() == std::max<::mpfr_prec_t>(128, detail::real_deduce_precision(6.)));
305 
306         // Try with higher precision on the non-complex argument.
307         c1 = complex{1, 1, complex_prec_t(real_prec_min())};
308         ret = c1 + std::complex<double>(6, 7);
309         REQUIRE(ret == complex{7, 8});
310         REQUIRE(ret.get_prec() == detail::real_deduce_precision(6.));
311         ret = std::complex<double>(6, 7) + c1;
312         REQUIRE(ret == complex{7, 8});
313         REQUIRE(ret.get_prec() == detail::real_deduce_precision(6.));
314 
315         // Moves.
316         auto c2 = c1;
317         ret = std::move(c1) + std::complex<double>(6, 7);
318         REQUIRE(ret == complex{7, 8});
319         REQUIRE(ret.get_prec() == detail::real_deduce_precision(6.));
320         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
321         REQUIRE(c1.is_valid());
322         c1 = complex{1, 1, complex_prec_t(detail::real_deduce_precision(6.) + 1)};
323         ret = std::move(c1) + std::complex<double>(6, 7);
324         REQUIRE(ret == complex{7, 8});
325         REQUIRE(ret.get_prec() == detail::real_deduce_precision(6.) + 1);
326         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
327         REQUIRE(!c1.is_valid());
328 
329         c1 = c2;
330         ret = std::complex<double>(6, 7) + std::move(c1);
331         REQUIRE(ret == complex{7, 8});
332         REQUIRE(ret.get_prec() == detail::real_deduce_precision(6.));
333         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
334         REQUIRE(c1.is_valid());
335         c1 = complex{1, 1, complex_prec_t(detail::real_deduce_precision(6.) + 1)};
336         ret = std::complex<double>(6, 7) + std::move(c1);
337         REQUIRE(ret == complex{7, 8});
338         REQUIRE(ret.get_prec() == detail::real_deduce_precision(6.) + 1);
339         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
340         REQUIRE(!c1.is_valid());
341     }
342 
343 #if defined(MPPP_WITH_QUADMATH)
344     // Complex-complex128.
345     {
346         complex c1{45, 6, complex_prec_t(128)};
347         auto ret = c1 + complex128(6, 7);
348         REQUIRE(ret == complex{51, 13});
349         REQUIRE(std::is_same<complex, decltype(ret)>::value);
350         REQUIRE(ret.get_prec() == 128);
351         ret = complex128(6, 7) + c1;
352         REQUIRE(ret == complex{51, 13});
353         REQUIRE(std::is_same<complex, decltype(complex128(6, 7) + c1)>::value);
354         REQUIRE(ret.get_prec() == 128);
355 
356         // Try with higher precision on the non-complex argument.
357         c1 = complex{1, 1, complex_prec_t(real_prec_min())};
358         ret = c1 + complex128(6, 7);
359         REQUIRE(ret == complex{7, 8});
360         REQUIRE(ret.get_prec() == 113);
361         ret = complex128(6, 7) + c1;
362         REQUIRE(ret == complex{7, 8});
363         REQUIRE(ret.get_prec() == 113);
364 
365         // Moves.
366         auto c2 = c1;
367         ret = std::move(c1) + complex128(6, 7);
368         REQUIRE(ret == complex{7, 8});
369         REQUIRE(ret.get_prec() == 113);
370         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
371         REQUIRE(c1.is_valid());
372         c1 = complex{1, 1, complex_prec_t(114)};
373         ret = std::move(c1) + complex128(6, 7);
374         REQUIRE(ret == complex{7, 8});
375         REQUIRE(ret.get_prec() == 114);
376         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
377         REQUIRE(!c1.is_valid());
378 
379         c1 = c2;
380         ret = complex128(6, 7) + std::move(c1);
381         REQUIRE(ret == complex{7, 8});
382         REQUIRE(ret.get_prec() == 113);
383         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
384         REQUIRE(c1.is_valid());
385         c1 = complex{1, 1, complex_prec_t(114)};
386         ret = complex128(6, 7) + std::move(c1);
387         REQUIRE(ret == complex{7, 8});
388         REQUIRE(ret.get_prec() == 114);
389         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
390         REQUIRE(!c1.is_valid());
391     }
392 #endif
393 
394     // real-std::complex.
395     {
396         real r{5, 5};
397         auto ret = r + std::complex<double>{5, 6};
398         REQUIRE(ret == complex{10, 6});
399         REQUIRE(std::is_same<complex, decltype(ret)>::value);
400         REQUIRE(ret.get_prec() == detail::real_deduce_precision(5.));
401         ret = std::complex<double>{5, 6} + r;
402         REQUIRE(ret == complex{10, 6});
403         REQUIRE(std::is_same<complex, decltype(std::complex<double>{5, 6} + r)>::value);
404         REQUIRE(ret.get_prec() == detail::real_deduce_precision(5.));
405 
406         // Switch precisions around.
407         r = real{5, detail::real_deduce_precision(5.) + 1};
408         ret = r + std::complex<double>{5, 6};
409         REQUIRE(ret == complex{10, 6});
410         REQUIRE(ret.get_prec() == detail::real_deduce_precision(5.) + 1);
411         ret = std::complex<double>{5, 6} + r;
412         REQUIRE(ret == complex{10, 6});
413         REQUIRE(ret.get_prec() == detail::real_deduce_precision(5.) + 1);
414     }
415 
416 #if defined(MPPP_WITH_QUADMATH)
417     // real-complex128.
418     {
419         real r{5, 5};
420         auto ret = r + complex128{5, 6};
421         REQUIRE(ret == complex{10, 6});
422         REQUIRE(std::is_same<complex, decltype(ret)>::value);
423         REQUIRE(ret.get_prec() == 113);
424         ret = complex128{5, 6} + r;
425         REQUIRE(ret == complex{10, 6});
426         REQUIRE(std::is_same<complex, decltype(complex128{5, 6} + r)>::value);
427         REQUIRE(ret.get_prec() == 113);
428 
429         // Switch precisions around.
430         r = real{5, 114};
431         ret = r + complex128{5, 6};
432         REQUIRE(ret == complex{10, 6});
433         REQUIRE(ret.get_prec() == 114);
434         ret = complex128{5, 6} + r;
435         REQUIRE(ret == complex{10, 6});
436         REQUIRE(ret.get_prec() == 114);
437     }
438 #endif
439 }
440 
441 TEST_CASE("in-place plus")
442 {
443     // complex-complex.
444     {
445         complex c1{1, 2}, c2{3, 4};
446         c1 += c2;
447         REQUIRE(std::is_same<complex &, decltype(c1 += c2)>::value);
448         REQUIRE(c1 == complex{4, 6});
449         REQUIRE(c1.get_prec() == detail::real_deduce_precision(1));
450 
451         // Move which does not steal.
452         c1 += std::move(c2);
453         REQUIRE(c1 == complex{7, 10});
454         REQUIRE(c1.get_prec() == detail::real_deduce_precision(1));
455         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
456         REQUIRE(c2.is_valid());
457 
458         // Move which steals.
459         complex c3{4, 5, complex_prec_t(detail::real_deduce_precision(1) + 1)};
460         c1 += std::move(c3);
461         REQUIRE(c1.get_prec() == detail::real_deduce_precision(1) + 1);
462         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
463         REQUIRE(c3.is_valid());
464         REQUIRE(c3 == complex{7, 10});
465         REQUIRE(c3.get_prec() == detail::real_deduce_precision(1));
466 
467         // Self add.
468         c3 += c3;
469         REQUIRE(c3 == complex{14, 20});
470     }
471     // complex-real.
472     {
473         // Same precision.
474         complex c1{1, 2};
475         real r{4};
476         c1 += r;
477         REQUIRE(std::is_same<complex &, decltype(c1 += r)>::value);
478         REQUIRE(c1 == complex{5, 2});
479         REQUIRE(c1.get_prec() == detail::real_deduce_precision(1));
480 
481         // r with higher precision.
482         c1 = complex{1, 1, complex_prec_t(real_prec_min())};
483         c1 += r;
484         REQUIRE(c1 == complex{5, 1});
485         REQUIRE(c1.get_prec() == detail::real_deduce_precision(1));
486 
487         // r with smaller precision.
488         c1 = complex{1, 1, complex_prec_t(detail::real_deduce_precision(1) + 1)};
489         c1 += r;
490         REQUIRE(c1 == complex{5, 1});
491         REQUIRE(c1.get_prec() == detail::real_deduce_precision(1) + 1);
492     }
493     // complex-real valued.
494     {
495         // Other op with same precision.
496         complex c1{1, 2};
497         c1 += 4;
498         REQUIRE(std::is_same<complex &, decltype(c1 += 4)>::value);
499         REQUIRE(c1 == complex{5, 2});
500         REQUIRE(c1.get_prec() == detail::real_deduce_precision(1));
501 
502         // Other op with higher precision.
503         c1 = complex{1, 1, complex_prec_t(real_prec_min())};
504         c1 += 4.;
505         REQUIRE(c1 == complex{5, 1});
506         REQUIRE(c1.get_prec() == detail::real_deduce_precision(4.));
507 
508         // Other op with lower precision.
509         c1 = complex{1, 2, complex_prec_t(detail::real_deduce_precision(1) + 1)};
510         c1 += 4;
511         REQUIRE(c1 == complex{5, 2});
512         REQUIRE(c1.get_prec() == detail::real_deduce_precision(1) + 1);
513     }
514     // complex-unsigned integral.
515     {
516         // Other op with same precision.
517         complex c1{1u, 2u};
518         c1 += 4u;
519         REQUIRE(std::is_same<complex &, decltype(c1 += 4u)>::value);
520         REQUIRE(c1 == complex{5, 2});
521         REQUIRE(c1.get_prec() == detail::real_deduce_precision(1u));
522 
523         // Other op with higher precision.
524         c1 = complex{1, 1, complex_prec_t(real_prec_min())};
525         c1 += 4u;
526         REQUIRE(c1 == complex{5, 1});
527         REQUIRE(c1.get_prec() == detail::real_deduce_precision(4u));
528 
529         // Other op with lower precision.
530         c1 = complex{1, 2, complex_prec_t(detail::real_deduce_precision(1u) + 1)};
531         c1 += 4u;
532         REQUIRE(c1 == complex{5, 2});
533         REQUIRE(c1.get_prec() == detail::real_deduce_precision(1u) + 1);
534 
535 #if defined(MPPP_HAVE_GCC_INT128)
536         // Test with large unsigned integral type.
537         c1 = complex{1, 0, complex_prec_t(real_prec_min())};
538         c1 += __uint128_t(-1);
539         REQUIRE(std::is_same<complex &, decltype(c1 += __uint128_t(-1))>::value);
540         REQUIRE(c1 == 1_z1 + __uint128_t(-1));
541         REQUIRE(c1.get_prec() == 128);
542 
543         c1 = complex{1, 0, complex_prec_t(256)};
544         c1 += __uint128_t(-1);
545         REQUIRE(c1 == 1_z1 + __uint128_t(-1));
546         REQUIRE(c1.get_prec() == 256);
547 #endif
548     }
549     // Special casing for bool.
550     {
551         // Other op with same precision.
552         complex c1{true, false};
553         c1 += true;
554         REQUIRE(std::is_same<complex &, decltype(c1 += true)>::value);
555         REQUIRE(c1 == complex{2, 0});
556         REQUIRE(c1.get_prec() == detail::real_deduce_precision(true));
557 
558         // Other op with higher precision.
559         c1 = complex{true, false, complex_prec_t(real_prec_min())};
560         c1 += true;
561         REQUIRE(c1 == complex{2, 0});
562         REQUIRE(c1.get_prec() == detail::real_deduce_precision(true));
563 
564         // Other op with lower precision.
565         c1 = complex{1, 2, complex_prec_t(detail::real_deduce_precision(true) + 1)};
566         c1 += false;
567         REQUIRE(c1 == complex{1, 2});
568         REQUIRE(c1.get_prec() == detail::real_deduce_precision(true) + 1);
569     }
570 
571     // complex-std::complex.
572     {
573         // Other op with same precision.
574         complex c1{1., 2.};
575         c1 += std::complex<double>{3, 4};
576         REQUIRE(std::is_same<complex &, decltype(c1 += std::complex<double>{3, 4})>::value);
577         REQUIRE(c1 == complex{4, 6});
578         REQUIRE(c1.get_prec() == detail::real_deduce_precision(1.));
579 
580         // Other op with higher precision.
581         c1 = complex{1, 1, complex_prec_t(real_prec_min())};
582         c1 += std::complex<double>{3, 4};
583         REQUIRE(c1 == complex{4, 5});
584         REQUIRE(c1.get_prec() == detail::real_deduce_precision(4.));
585 
586         // Other op with lower precision.
587         c1 = complex{1, 2, complex_prec_t(detail::real_deduce_precision(1.) + 1)};
588         c1 += std::complex<double>{3, 4};
589         REQUIRE(c1 == complex{4, 6});
590         REQUIRE(c1.get_prec() == detail::real_deduce_precision(1.) + 1);
591     }
592 
593 #if defined(MPPP_WITH_QUADMATH)
594     // complex-complex128.
595     {
596         // Other op with same precision.
597         complex c1{1., 2., complex_prec_t(113)};
598         c1 += complex128{3, 4};
599         REQUIRE(std::is_same<complex &, decltype(c1 += complex128{3, 4})>::value);
600         REQUIRE(c1 == complex{4, 6});
601         REQUIRE(c1.get_prec() == 113);
602 
603         // Other op with higher precision.
604         c1 = complex{1, 1, complex_prec_t(real_prec_min())};
605         c1 += complex128{3, 4};
606         REQUIRE(c1 == complex{4, 5});
607         REQUIRE(c1.get_prec() == 113);
608 
609         // Other op with lower precision.
610         c1 = complex{1, 2, complex_prec_t(114)};
611         c1 += std::complex<double>{3, 4};
612         REQUIRE(c1 == complex{4, 6});
613         REQUIRE(c1.get_prec() == 114);
614     }
615 #endif
616 
617     // complex interoperable-complex.
618     {
619         int n = 5;
620         n += complex{4, 0};
621         REQUIRE(std::is_same<int &, decltype(n += complex{4, 0})>::value);
622         REQUIRE(n == 9);
623 
624         // Check move semantics.
625         complex c{4, 0, complex_prec_t(detail::real_deduce_precision(1) + 1)};
626         n += std::move(c);
627         REQUIRE(n == 13);
628         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
629         REQUIRE(!c.is_valid());
630 
631         // Check conversion failure.
632         REQUIRE_THROWS_AS((n += complex{4, 1}), std::domain_error);
633         REQUIRE(n == 13);
634         if (std::numeric_limits<double>::has_infinity) {
635             REQUIRE_THROWS_AS((n += complex{std::numeric_limits<double>::infinity(), 0}), std::domain_error);
636             REQUIRE(n == 13);
637         }
638 
639         // Try with complex-valued too.
640         std::complex<double> cd{4, 5};
641         cd += complex{4, 1};
642         REQUIRE(std::is_same<std::complex<double> &, decltype(cd += complex{4, 1})>::value);
643         REQUIRE(cd == std::complex<double>{8, 6});
644 
645 #if defined(MPPP_WITH_QUADMATH)
646         complex128 cq{4, 5};
647         cq += complex{4, 1};
648         REQUIRE(std::is_same<complex128 &, decltype(cq += complex{4, 1})>::value);
649         REQUIRE(cq == complex128{8, 6});
650 #endif
651     }
652 
653     // real-complex valued
654     {
655         real r{4, 5};
656         r += std::complex<double>{4, 0};
657         REQUIRE(std::is_same<real &, decltype(r += std::complex<double>{4, 0})>::value);
658         REQUIRE(r == 8);
659         REQUIRE(r.get_prec() == detail::real_deduce_precision(1.));
660 
661         // Check conversion failure.
662         REQUIRE_THROWS_AS((r += complex{4, 1}), std::domain_error);
663         REQUIRE(r == 8);
664 
665 #if defined(MPPP_WITH_QUADMATH)
666         r += complex128{4, 0};
667         REQUIRE(std::is_same<real &, decltype(r += complex128{4, 0})>::value);
668         REQUIRE(r == 12);
669         REQUIRE(r.get_prec() == detail::c_max(detail::real_deduce_precision(1.), mpfr_prec_t(113)));
670 #endif
671     }
672 
673     // complex valued-real.
674     {
675         std::complex<double> c{1, 2};
676         c += real{2, 5};
677         REQUIRE(std::is_same<std::complex<double> &, decltype(c += real{2, 5})>::value);
678         REQUIRE(c == std::complex<double>{3, 2});
679 
680         // Check move semantics.
681         real r{4, detail::real_deduce_precision(1.) + 1};
682         c += std::move(r);
683         REQUIRE(c == std::complex<double>{7, 2});
684         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
685         REQUIRE(!r.is_valid());
686 
687 #if defined(MPPP_WITH_QUADMATH)
688         complex128 c2{3, 4};
689         c2 += real{2, 114};
690         REQUIRE(std::is_same<complex128 &, decltype(c2 += real{2, 114})>::value);
691         REQUIRE(c2 == complex128{5, 4});
692 #endif
693     }
694 }
695 
696 TEST_CASE("negation")
697 {
698     complex r1{4, 5};
699     REQUIRE(-r1 == complex{-4, -5});
700 
701     // Check stealing.
702     const auto p = r1.get_prec();
703     auto r2 = -std::move(r1);
704     REQUIRE(r2.get_prec() == p);
705     REQUIRE(r2 == complex{-4, -5});
706     // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
707     REQUIRE(!r1.is_valid());
708 }
709 
710 TEST_CASE("decrement")
711 {
712     complex r0{0};
713     REQUIRE(--r0 == -1);
714     REQUIRE(r0-- == -1);
715     REQUIRE(r0 == -2);
716 
717     // Check precision handling.
718     r0 = complex{0, complex_prec_t(4)};
719     --r0;
720     REQUIRE(r0.get_prec() == detail::real_deduce_precision(1));
721     REQUIRE(r0 == -1);
722     r0 = complex{0, complex_prec_t(4)};
723     r0--;
724     REQUIRE(r0.get_prec() == detail::real_deduce_precision(1));
725     REQUIRE(r0 == -1);
726 }
727 
728 // NOLINTNEXTLINE(google-readability-function-size, hicpp-function-size, readability-function-size)
729 TEST_CASE("binary minus")
730 {
731     // complex-complex.
732     {
733         complex r1{4, 5}, r2{-4, 7};
734         const auto p = r1.get_prec();
735         auto ret = r1 - r2;
736         REQUIRE(std::is_same<complex, decltype(ret)>::value);
737         REQUIRE(ret == complex{8, -2});
738         REQUIRE(ret.get_prec() == r1.get_prec());
739 
740         // Test moves.
741         ret = std::move(r1) - r2;
742         REQUIRE(ret == complex{8, -2});
743         REQUIRE(ret.get_prec() == p);
744         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
745         REQUIRE(!r1.is_valid());
746 
747         r1 = complex{4, 5};
748         ret = r1 - std::move(r2);
749         REQUIRE(ret == complex{8, -2});
750         REQUIRE(ret.get_prec() == p);
751         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
752         REQUIRE(!r2.is_valid());
753 
754         r2 = complex{-4, 7};
755         ret = std::move(r1) - std::move(r2);
756         REQUIRE(ret == complex{8, -2});
757         REQUIRE(ret.get_prec() == p);
758         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
759         REQUIRE((!r1.is_valid() || !r2.is_valid()));
760 
761         // Self sub.
762         r2 = complex{-4, 6};
763         REQUIRE(r2 - r2 == complex{});
764     }
765     // complex-real.
766     {
767         complex c1{45, 6, complex_prec_t(128)};
768         real r1{23, 10};
769         auto ret = c1 - r1;
770         REQUIRE(std::is_same<complex, decltype(ret)>::value);
771         REQUIRE(ret == complex{22, 6, complex_prec_t(128)});
772         REQUIRE(ret.get_prec() == 128);
773         ret = r1 - c1;
774         REQUIRE(std::is_same<complex, decltype(r1 - c1)>::value);
775         REQUIRE(ret == complex{-22, -6, complex_prec_t(128)});
776         REQUIRE(ret.get_prec() == 128);
777 
778         // Try with higher precision on the non-complex argument.
779         ret = c1 - real{23, 256};
780         REQUIRE(ret == complex{22, 6, complex_prec_t(128)});
781         REQUIRE(ret.get_prec() == 256);
782         ret = real{23, 256} - c1;
783         REQUIRE(ret == complex{-22, -6, complex_prec_t(128)});
784         REQUIRE(ret.get_prec() == 256);
785 
786         // Try with moves.
787         auto c2 = c1;
788         ret = complex{};
789         ret = std::move(c1) - r1;
790         REQUIRE(ret == complex{22, 6, complex_prec_t(128)});
791         REQUIRE(ret.get_prec() == 128);
792         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
793         REQUIRE(!c1.is_valid());
794 
795         c1 = c2;
796         ret = complex{};
797         ret = r1 - std::move(c1);
798         REQUIRE(ret == complex{-22, -6, complex_prec_t(128)});
799         REQUIRE(ret.get_prec() == 128);
800         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
801         REQUIRE(!c1.is_valid());
802     }
803     // complex-rv interoperable.
804     {
805         complex c1{45, 6, complex_prec_t(128)};
806         auto ret = c1 - 6;
807         REQUIRE(ret == complex{39, 6});
808         REQUIRE(std::is_same<complex, decltype(ret)>::value);
809         REQUIRE(ret.get_prec() == std::max<::mpfr_prec_t>(128, detail::real_deduce_precision(6)));
810         ret = 6. - c1;
811         REQUIRE(ret == complex{-39, -6});
812         REQUIRE(std::is_same<complex, decltype(6. - c1)>::value);
813         REQUIRE(ret.get_prec() == std::max<::mpfr_prec_t>(128, detail::real_deduce_precision(6.)));
814 
815         // Try with higher precision on the non-complex argument.
816         c1 = complex{1, 1, complex_prec_t(real_prec_min())};
817         ret = c1 - 45_z1;
818         REQUIRE(ret == complex{-44, 1});
819         REQUIRE(ret.get_prec() == detail::real_deduce_precision(45_z1));
820         ret = 45_q1 - c1;
821         REQUIRE(ret == complex{44, -1});
822         REQUIRE(ret.get_prec() == detail::real_deduce_precision(45_q1));
823 
824         // Moves.
825         auto c2 = c1;
826         ret = std::move(c1) - 45;
827         REQUIRE(ret == complex{-44, 1});
828         REQUIRE(ret.get_prec() == detail::real_deduce_precision(45));
829         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
830         REQUIRE(c1.is_valid());
831         c1 = complex{1, 1, complex_prec_t(detail::real_deduce_precision(45) + 1)};
832         ret = std::move(c1) - 45;
833         REQUIRE(ret == complex{-44, 1});
834         REQUIRE(ret.get_prec() == detail::real_deduce_precision(45) + 1);
835         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
836         REQUIRE(!c1.is_valid());
837 
838         c1 = c2;
839         ret = 45. - std::move(c1);
840         REQUIRE(ret == complex{44, -1});
841         REQUIRE(ret.get_prec() == detail::real_deduce_precision(45.));
842         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
843         REQUIRE(c1.is_valid());
844         c1 = complex{1, 1, complex_prec_t(detail::real_deduce_precision(45.) + 1)};
845         ret = 45. - std::move(c1);
846         REQUIRE(ret == complex{44, -1});
847         REQUIRE(ret.get_prec() == detail::real_deduce_precision(45.) + 1);
848         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
849         REQUIRE(!c1.is_valid());
850 
851 #if defined(MPPP_WITH_QUADMATH)
852         c1 = c2;
853         ret = 45_rq - std::move(c1);
854         REQUIRE(ret == complex{44, -1});
855         REQUIRE(ret.get_prec() == 113);
856         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
857         REQUIRE(c1.is_valid());
858         c1 = complex{1, 1, complex_prec_t(114)};
859         ret = 45_rq - std::move(c1);
860         REQUIRE(ret == complex{44, -1});
861         REQUIRE(ret.get_prec() == 114);
862         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
863         REQUIRE(!c1.is_valid());
864 #endif
865     }
866     // complex-unsigned integral.
867     {
868         complex c1{45, 6, complex_prec_t(128)};
869         auto ret = c1 - 6u;
870         REQUIRE(ret == complex{39, 6});
871         REQUIRE(std::is_same<complex, decltype(ret)>::value);
872         REQUIRE(ret.get_prec() == std::max<::mpfr_prec_t>(128, detail::real_deduce_precision(6u)));
873         ret = 6u - c1;
874         REQUIRE(ret == complex{-39, -6});
875         REQUIRE(std::is_same<complex, decltype(6u - c1)>::value);
876         REQUIRE(ret.get_prec() == std::max<::mpfr_prec_t>(128, detail::real_deduce_precision(6u)));
877 
878         // Try with higher precision on the non-complex argument.
879         c1 = complex{1, 1, complex_prec_t(real_prec_min())};
880         ret = c1 - 45u;
881         REQUIRE(ret == complex{-44, 1});
882         REQUIRE(ret.get_prec() == detail::real_deduce_precision(45u));
883         ret = 45u - c1;
884         REQUIRE(ret == complex{44, -1});
885         REQUIRE(ret.get_prec() == detail::real_deduce_precision(45u));
886 
887         // Moves.
888         auto c2 = c1;
889         ret = std::move(c1) - 45u;
890         REQUIRE(ret == complex{-44, 1});
891         REQUIRE(ret.get_prec() == detail::real_deduce_precision(45u));
892         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
893         REQUIRE(c1.is_valid());
894         c1 = complex{1, 1, complex_prec_t(detail::real_deduce_precision(45u) + 1)};
895         ret = std::move(c1) - 45u;
896         REQUIRE(ret == complex{-44, 1});
897         REQUIRE(ret.get_prec() == detail::real_deduce_precision(45u) + 1);
898         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
899         REQUIRE(!c1.is_valid());
900 
901         c1 = c2;
902         ret = 45u - std::move(c1);
903         REQUIRE(ret == complex{44, -1});
904         REQUIRE(ret.get_prec() == detail::real_deduce_precision(45u));
905         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
906         REQUIRE(c1.is_valid());
907         c1 = complex{1, 1, complex_prec_t(detail::real_deduce_precision(45u) + 1)};
908         ret = 45u - std::move(c1);
909         REQUIRE(ret == complex{44, -1});
910         REQUIRE(ret.get_prec() == detail::real_deduce_precision(45u) + 1);
911         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
912         REQUIRE(!c1.is_valid());
913 
914         // Bool special casing.
915         c1 = c2;
916         ret = true - c1;
917         REQUIRE(ret == complex{0, -1});
918         ret = c1 - false;
919         REQUIRE(ret == complex{1, 1});
920         ret = true - std::move(c1);
921         REQUIRE(ret == complex{0, -1});
922         c1 = c2;
923         ret = std::move(c1) - false;
924         REQUIRE(ret == complex{1, 1});
925 
926 #if defined(MPPP_HAVE_GCC_INT128)
927         // Try with a large integral.
928         c1 = c2;
929         ret = __uint128_t(-1) - std::move(c1);
930         REQUIRE(ret == complex{__uint128_t(-1) - 1u, -1, complex_prec_t(128)});
931         REQUIRE(ret.get_prec() == 128);
932         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
933         REQUIRE(c1.is_valid());
934         c1 = complex{1, 1, complex_prec_t(129)};
935         ret = __uint128_t(-1) - std::move(c1);
936         REQUIRE(ret == complex{__uint128_t(-1) - 1u, -1, complex_prec_t(129)});
937         REQUIRE(ret.get_prec() == 129);
938         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
939         REQUIRE(!c1.is_valid());
940 
941         c1 = c2;
942         ret = std::move(c1) - __uint128_t(-1);
943         REQUIRE(ret == complex{1_z1 - __uint128_t(-1), 1, complex_prec_t(128)});
944         REQUIRE(ret.get_prec() == 128);
945         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
946         REQUIRE(c1.is_valid());
947         c1 = complex{1, 1, complex_prec_t(129)};
948         ret = std::move(c1) - __uint128_t(-1);
949         REQUIRE(ret == complex{1_z1 - __uint128_t(-1), 1, complex_prec_t(129)});
950         REQUIRE(ret.get_prec() == 129);
951         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
952         REQUIRE(!c1.is_valid());
953 #endif
954     }
955 
956     // Complex-std::complex.
957     {
958         complex c1{45, 6, complex_prec_t(128)};
959         auto ret = c1 - std::complex<double>(6, 7);
960         REQUIRE(ret == complex{39, -1});
961         REQUIRE(std::is_same<complex, decltype(ret)>::value);
962         REQUIRE(ret.get_prec() == std::max<::mpfr_prec_t>(128, detail::real_deduce_precision(6.)));
963         ret = std::complex<double>(6, 7) - c1;
964         REQUIRE(ret == complex{-39, 1});
965         REQUIRE(std::is_same<complex, decltype(std::complex<double>(6, 7) - c1)>::value);
966         REQUIRE(ret.get_prec() == std::max<::mpfr_prec_t>(128, detail::real_deduce_precision(6.)));
967 
968         // Try with higher precision on the non-complex argument.
969         c1 = complex{1, 1, complex_prec_t(real_prec_min())};
970         ret = c1 - std::complex<double>(6, 7);
971         REQUIRE(ret == complex{-5, -6});
972         REQUIRE(ret.get_prec() == detail::real_deduce_precision(6.));
973         ret = std::complex<double>(6, 7) - c1;
974         REQUIRE(ret == complex{5, 6});
975         REQUIRE(ret.get_prec() == detail::real_deduce_precision(6.));
976 
977         // Moves.
978         auto c2 = c1;
979         ret = std::move(c1) - std::complex<double>(6, 7);
980         REQUIRE(ret == complex{-5, -6});
981         REQUIRE(ret.get_prec() == detail::real_deduce_precision(6.));
982         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
983         REQUIRE(c1.is_valid());
984         c1 = complex{1, 1, complex_prec_t(detail::real_deduce_precision(6.) + 1)};
985         ret = std::move(c1) - std::complex<double>(6, 7);
986         REQUIRE(ret == complex{-5, -6});
987         REQUIRE(ret.get_prec() == detail::real_deduce_precision(6.) + 1);
988         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
989         REQUIRE(!c1.is_valid());
990 
991         c1 = c2;
992         ret = std::complex<double>(6, 7) - std::move(c1);
993         REQUIRE(ret == complex{5, 6});
994         REQUIRE(ret.get_prec() == detail::real_deduce_precision(6.));
995         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
996         REQUIRE(c1.is_valid());
997         c1 = complex{1, 1, complex_prec_t(detail::real_deduce_precision(6.) + 1)};
998         ret = std::complex<double>(6, 7) - std::move(c1);
999         REQUIRE(ret == complex{5, 6});
1000         REQUIRE(ret.get_prec() == detail::real_deduce_precision(6.) + 1);
1001         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
1002         REQUIRE(!c1.is_valid());
1003     }
1004 
1005 #if defined(MPPP_WITH_QUADMATH)
1006     // Complex-complex128.
1007     {
1008         complex c1{45, 6, complex_prec_t(128)};
1009         auto ret = c1 - complex128(6, 7);
1010         REQUIRE(ret == complex{39, -1});
1011         REQUIRE(std::is_same<complex, decltype(ret)>::value);
1012         REQUIRE(ret.get_prec() == 128);
1013         ret = complex128(6, 7) - c1;
1014         REQUIRE(ret == complex{-39, 1});
1015         REQUIRE(std::is_same<complex, decltype(complex128(6, 7) - c1)>::value);
1016         REQUIRE(ret.get_prec() == 128);
1017 
1018         // Try with higher precision on the non-complex argument.
1019         c1 = complex{1, 1, complex_prec_t(real_prec_min())};
1020         ret = c1 - complex128(6, 7);
1021         REQUIRE(ret == complex{-5, -6});
1022         REQUIRE(ret.get_prec() == 113);
1023         ret = complex128(6, 7) - c1;
1024         REQUIRE(ret == complex{5, 6});
1025         REQUIRE(ret.get_prec() == 113);
1026 
1027         // Moves.
1028         auto c2 = c1;
1029         ret = std::move(c1) - complex128(6, 7);
1030         REQUIRE(ret == complex{-5, -6});
1031         REQUIRE(ret.get_prec() == 113);
1032         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
1033         REQUIRE(c1.is_valid());
1034         c1 = complex{1, 1, complex_prec_t(114)};
1035         ret = std::move(c1) - complex128(6, 7);
1036         REQUIRE(ret == complex{-5, -6});
1037         REQUIRE(ret.get_prec() == 114);
1038         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
1039         REQUIRE(!c1.is_valid());
1040 
1041         c1 = c2;
1042         ret = complex128(6, 7) - std::move(c1);
1043         REQUIRE(ret == complex{5, 6});
1044         REQUIRE(ret.get_prec() == 113);
1045         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
1046         REQUIRE(c1.is_valid());
1047         c1 = complex{1, 1, complex_prec_t(114)};
1048         ret = complex128(6, 7) - std::move(c1);
1049         REQUIRE(ret == complex{5, 6});
1050         REQUIRE(ret.get_prec() == 114);
1051         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
1052         REQUIRE(!c1.is_valid());
1053     }
1054 #endif
1055 
1056     // real-std::complex.
1057     {
1058         real r{5, 5};
1059         auto ret = r - std::complex<double>{5, 6};
1060         REQUIRE(ret == complex{0, -6});
1061         REQUIRE(std::is_same<complex, decltype(ret)>::value);
1062         REQUIRE(ret.get_prec() == detail::real_deduce_precision(5.));
1063         ret = std::complex<double>{5, 6} - r;
1064         REQUIRE(ret == complex{0, 6});
1065         REQUIRE(std::is_same<complex, decltype(std::complex<double>{5, 6} - r)>::value);
1066         REQUIRE(ret.get_prec() == detail::real_deduce_precision(5.));
1067 
1068         // Switch precisions around.
1069         r = real{5, detail::real_deduce_precision(5.) + 1};
1070         ret = r - std::complex<double>{5, 6};
1071         REQUIRE(ret == complex{0, -6});
1072         REQUIRE(ret.get_prec() == detail::real_deduce_precision(5.) + 1);
1073         ret = std::complex<double>{5, 6} - r;
1074         REQUIRE(ret == complex{0, 6});
1075         REQUIRE(ret.get_prec() == detail::real_deduce_precision(5.) + 1);
1076     }
1077 
1078 #if defined(MPPP_WITH_QUADMATH)
1079     // real-complex128.
1080     {
1081         real r{5, 5};
1082         auto ret = r - complex128{5, 6};
1083         REQUIRE(ret == complex{0, -6});
1084         REQUIRE(std::is_same<complex, decltype(ret)>::value);
1085         REQUIRE(ret.get_prec() == 113);
1086         ret = complex128{5, 6} - r;
1087         REQUIRE(ret == complex{0, 6});
1088         REQUIRE(std::is_same<complex, decltype(complex128{5, 6} - r)>::value);
1089         REQUIRE(ret.get_prec() == 113);
1090 
1091         // Switch precisions around.
1092         r = real{5, 114};
1093         ret = r - complex128{5, 6};
1094         REQUIRE(ret == complex{0, -6});
1095         REQUIRE(ret.get_prec() == 114);
1096         ret = complex128{5, 6} - r;
1097         REQUIRE(ret == complex{0, 6});
1098         REQUIRE(ret.get_prec() == 114);
1099     }
1100 #endif
1101 }
1102 
1103 TEST_CASE("in-place minus")
1104 {
1105     // complex-complex.
1106     {
1107         complex c1{1, 2}, c2{3, 4};
1108         c1 -= c2;
1109         REQUIRE(std::is_same<complex &, decltype(c1 -= c2)>::value);
1110         REQUIRE(c1 == complex{-2, -2});
1111         REQUIRE(c1.get_prec() == detail::real_deduce_precision(1));
1112 
1113         // Move which does not steal.
1114         c1 -= std::move(c2);
1115         REQUIRE(c1 == complex{-5, -6});
1116         REQUIRE(c1.get_prec() == detail::real_deduce_precision(1));
1117         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
1118         REQUIRE(c2.is_valid());
1119 
1120         // Move which steals.
1121         complex c3{4, 5, complex_prec_t(detail::real_deduce_precision(1) + 1)};
1122         c1 -= std::move(c3);
1123         REQUIRE(c1.get_prec() == detail::real_deduce_precision(1) + 1);
1124         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
1125         REQUIRE(c3.is_valid());
1126         REQUIRE(c3 == complex{-5, -6});
1127         REQUIRE(c3.get_prec() == detail::real_deduce_precision(1));
1128 
1129         // Self sub.
1130         c3 -= *&c3;
1131         REQUIRE(c3 == complex{});
1132     }
1133     // complex-real.
1134     {
1135         // Same precision.
1136         complex c1{1, 2};
1137         real r{4};
1138         c1 -= r;
1139         REQUIRE(std::is_same<complex &, decltype(c1 -= r)>::value);
1140         REQUIRE(c1 == complex{-3, 2});
1141         REQUIRE(c1.get_prec() == detail::real_deduce_precision(1));
1142 
1143         // r with higher precision.
1144         c1 = complex{1, 1, complex_prec_t(real_prec_min())};
1145         c1 -= r;
1146         REQUIRE(c1 == complex{-3, 1});
1147         REQUIRE(c1.get_prec() == detail::real_deduce_precision(1));
1148 
1149         // r with smaller precision.
1150         c1 = complex{1, 1, complex_prec_t(detail::real_deduce_precision(1) + 1)};
1151         c1 -= r;
1152         REQUIRE(c1 == complex{-3, 1});
1153         REQUIRE(c1.get_prec() == detail::real_deduce_precision(1) + 1);
1154     }
1155     // complex-real valued.
1156     {
1157         // Other op with same precision.
1158         complex c1{1, 2};
1159         c1 -= 4;
1160         REQUIRE(std::is_same<complex &, decltype(c1 -= 4)>::value);
1161         REQUIRE(c1 == complex{-3, 2});
1162         REQUIRE(c1.get_prec() == detail::real_deduce_precision(1));
1163 
1164         // Other op with higher precision.
1165         c1 = complex{1, 1, complex_prec_t(real_prec_min())};
1166         c1 -= 4.;
1167         REQUIRE(c1 == complex{-3, 1});
1168         REQUIRE(c1.get_prec() == detail::real_deduce_precision(4.));
1169 
1170         // Other op with lower precision.
1171         c1 = complex{1, 2, complex_prec_t(detail::real_deduce_precision(1) + 1)};
1172         c1 -= 4;
1173         REQUIRE(c1 == complex{-3, 2});
1174         REQUIRE(c1.get_prec() == detail::real_deduce_precision(1) + 1);
1175     }
1176     // complex-unsigned integral.
1177     {
1178         // Other op with same precision.
1179         complex c1{1u, 2u};
1180         c1 -= 4u;
1181         REQUIRE(std::is_same<complex &, decltype(c1 -= 4u)>::value);
1182         REQUIRE(c1 == complex{-3, 2});
1183         REQUIRE(c1.get_prec() == detail::real_deduce_precision(1u));
1184 
1185         // Other op with higher precision.
1186         c1 = complex{1, 1, complex_prec_t(real_prec_min())};
1187         c1 -= 4u;
1188         REQUIRE(c1 == complex{-3, 1});
1189         REQUIRE(c1.get_prec() == detail::real_deduce_precision(4u));
1190 
1191         // Other op with lower precision.
1192         c1 = complex{1, 2, complex_prec_t(detail::real_deduce_precision(1u) + 1)};
1193         c1 -= 4u;
1194         REQUIRE(c1 == complex{-3, 2});
1195         REQUIRE(c1.get_prec() == detail::real_deduce_precision(1u) + 1);
1196 
1197 #if defined(MPPP_HAVE_GCC_INT128)
1198         // Test with large unsigned integral type.
1199         c1 = complex{1, 0, complex_prec_t(real_prec_min())};
1200         c1 -= __uint128_t(-1);
1201         REQUIRE(std::is_same<complex &, decltype(c1 -= __uint128_t(-1))>::value);
1202         REQUIRE(c1 == 1_z1 - __uint128_t(-1));
1203         REQUIRE(c1.get_prec() == 128);
1204 
1205         c1 = complex{1, 0, complex_prec_t(256)};
1206         c1 -= __uint128_t(-1);
1207         REQUIRE(c1 == 1_z1 - __uint128_t(-1));
1208         REQUIRE(c1.get_prec() == 256);
1209 #endif
1210     }
1211     // Special casing for bool.
1212     {
1213         // Other op with same precision.
1214         complex c1{true, false};
1215         c1 -= true;
1216         REQUIRE(std::is_same<complex &, decltype(c1 -= true)>::value);
1217         REQUIRE(c1 == complex{0, 0});
1218         REQUIRE(c1.get_prec() == detail::real_deduce_precision(true));
1219 
1220         // Other op with higher precision.
1221         c1 = complex{true, false, complex_prec_t(real_prec_min())};
1222         c1 -= true;
1223         REQUIRE(c1 == complex{0, 0});
1224         REQUIRE(c1.get_prec() == detail::real_deduce_precision(true));
1225 
1226         // Other op with lower precision.
1227         c1 = complex{1, 2, complex_prec_t(detail::real_deduce_precision(true) + 1)};
1228         c1 -= false;
1229         REQUIRE(c1 == complex{1, 2});
1230         REQUIRE(c1.get_prec() == detail::real_deduce_precision(true) + 1);
1231     }
1232 
1233     // complex-std::complex.
1234     {
1235         // Other op with same precision.
1236         complex c1{1., 2.};
1237         c1 -= std::complex<double>{3, 4};
1238         REQUIRE(std::is_same<complex &, decltype(c1 -= std::complex<double>{3, 4})>::value);
1239         REQUIRE(c1 == complex{-2, -2});
1240         REQUIRE(c1.get_prec() == detail::real_deduce_precision(1.));
1241 
1242         // Other op with higher precision.
1243         c1 = complex{1, 1, complex_prec_t(real_prec_min())};
1244         c1 -= std::complex<double>{3, 4};
1245         REQUIRE(c1 == complex{-2, -3});
1246         REQUIRE(c1.get_prec() == detail::real_deduce_precision(4.));
1247 
1248         // Other op with lower precision.
1249         c1 = complex{1, 2, complex_prec_t(detail::real_deduce_precision(1.) + 1)};
1250         c1 -= std::complex<double>{3, 4};
1251         REQUIRE(c1 == complex{-2, -2});
1252         REQUIRE(c1.get_prec() == detail::real_deduce_precision(1.) + 1);
1253     }
1254 
1255 #if defined(MPPP_WITH_QUADMATH)
1256     // complex-complex128.
1257     {
1258         // Other op with same precision.
1259         complex c1{1., 2., complex_prec_t(113)};
1260         c1 -= complex128{3, 4};
1261         REQUIRE(std::is_same<complex &, decltype(c1 -= complex128{3, 4})>::value);
1262         REQUIRE(c1 == complex{-2, -2});
1263         REQUIRE(c1.get_prec() == 113);
1264 
1265         // Other op with higher precision.
1266         c1 = complex{1, 1, complex_prec_t(real_prec_min())};
1267         c1 -= complex128{3, 4};
1268         REQUIRE(c1 == complex{-2, -3});
1269         REQUIRE(c1.get_prec() == 113);
1270 
1271         // Other op with lower precision.
1272         c1 = complex{1, 2, complex_prec_t(114)};
1273         c1 -= std::complex<double>{3, 4};
1274         REQUIRE(c1 == complex{-2, -2});
1275         REQUIRE(c1.get_prec() == 114);
1276     }
1277 #endif
1278 
1279     // complex interoperable-complex.
1280     {
1281         int n = 5;
1282         n -= complex{4, 0};
1283         REQUIRE(std::is_same<int &, decltype(n -= complex{4, 0})>::value);
1284         REQUIRE(n == 1);
1285 
1286         // Check move semantics.
1287         complex c{4, 0, complex_prec_t(detail::real_deduce_precision(1) + 1)};
1288         n -= std::move(c);
1289         REQUIRE(n == -3);
1290         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
1291         REQUIRE(!c.is_valid());
1292 
1293         // Check conversion failure.
1294         REQUIRE_THROWS_AS((n -= complex{4, 1}), std::domain_error);
1295         REQUIRE(n == -3);
1296         if (std::numeric_limits<double>::has_infinity) {
1297             REQUIRE_THROWS_AS((n -= complex{std::numeric_limits<double>::infinity(), 0}), std::domain_error);
1298             REQUIRE(n == -3);
1299         }
1300 
1301         // Try with complex-valued too.
1302         std::complex<double> cd{4, 5};
1303         cd -= complex{4, 1};
1304         REQUIRE(std::is_same<std::complex<double> &, decltype(cd -= complex{4, 1})>::value);
1305         REQUIRE(cd == std::complex<double>{0, 4});
1306 
1307 #if defined(MPPP_WITH_QUADMATH)
1308         complex128 cq{4, 5};
1309         cq -= complex{4, 1};
1310         REQUIRE(std::is_same<complex128 &, decltype(cq -= complex{4, 1})>::value);
1311         REQUIRE(cq == complex128{0, 4});
1312 #endif
1313     }
1314 
1315     // real-complex valued
1316     {
1317         real r{4, 5};
1318         r -= std::complex<double>{4, 0};
1319         REQUIRE(std::is_same<real &, decltype(r -= std::complex<double>{4, 0})>::value);
1320         REQUIRE(r == 0);
1321         REQUIRE(r.get_prec() == detail::real_deduce_precision(1.));
1322 
1323         // Check conversion failure.
1324         REQUIRE_THROWS_AS((r -= complex{4, 1}), std::domain_error);
1325         REQUIRE(r == 0);
1326 
1327 #if defined(MPPP_WITH_QUADMATH)
1328         r -= complex128{4, 0};
1329         REQUIRE(std::is_same<real &, decltype(r -= complex128{4, 0})>::value);
1330         REQUIRE(r == -4);
1331         REQUIRE(r.get_prec() == detail::c_max(detail::real_deduce_precision(1.), mpfr_prec_t(113)));
1332 #endif
1333     }
1334 
1335     // complex valued-real.
1336     {
1337         std::complex<double> c{1, 2};
1338         c -= real{2, 5};
1339         REQUIRE(std::is_same<std::complex<double> &, decltype(c -= real{2, 5})>::value);
1340         REQUIRE(c == std::complex<double>{-1, 2});
1341 
1342         // Check move semantics.
1343         real r{4, detail::real_deduce_precision(1.) + 1};
1344         c -= std::move(r);
1345         REQUIRE(c == std::complex<double>{-5, 2});
1346         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
1347         REQUIRE(!r.is_valid());
1348 
1349 #if defined(MPPP_WITH_QUADMATH)
1350         complex128 c2{3, 4};
1351         c2 -= real{2, 114};
1352         REQUIRE(std::is_same<complex128 &, decltype(c2 -= real{2, 114})>::value);
1353         REQUIRE(c2 == complex128{1, 4});
1354 #endif
1355     }
1356 }
1357 
1358 // NOLINTNEXTLINE(google-readability-function-size, hicpp-function-size, readability-function-size)
1359 TEST_CASE("binary mul")
1360 {
1361     // complex-complex.
1362     {
1363         complex r1{4, 5}, r2{-4, 7};
1364         const auto p = r1.get_prec();
1365         auto ret = r1 * r2;
1366         REQUIRE(std::is_same<complex, decltype(ret)>::value);
1367         REQUIRE(ret == complex{-51, 8});
1368         REQUIRE(ret.get_prec() == r1.get_prec());
1369 
1370         // Test moves.
1371         ret = std::move(r1) * r2;
1372         REQUIRE(ret == complex{-51, 8});
1373         REQUIRE(ret.get_prec() == p);
1374         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
1375         REQUIRE(!r1.is_valid());
1376 
1377         r1 = complex{4, 5};
1378         ret = r1 * std::move(r2);
1379         REQUIRE(ret == complex{-51, 8});
1380         REQUIRE(ret.get_prec() == p);
1381         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
1382         REQUIRE(!r2.is_valid());
1383 
1384         r2 = complex{-4, 7};
1385         ret = std::move(r1) * std::move(r2);
1386         REQUIRE(ret == complex{-51, 8});
1387         REQUIRE(ret.get_prec() == p);
1388         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
1389         REQUIRE((!r1.is_valid() || !r2.is_valid()));
1390 
1391         // Self mul.
1392         r2 = complex{-4, 6};
1393         REQUIRE(r2 * r2 == complex{-20, -48});
1394     }
1395     // complex-real.
1396     {
1397         complex c1{45, 6, complex_prec_t(128)};
1398         real r1{23, 10};
1399         auto ret = c1 * r1;
1400         REQUIRE(std::is_same<complex, decltype(ret)>::value);
1401         REQUIRE(ret == complex{1035, 138, complex_prec_t(128)});
1402         REQUIRE(ret.get_prec() == 128);
1403         ret = r1 * c1;
1404         REQUIRE(std::is_same<complex, decltype(r1 * c1)>::value);
1405         REQUIRE(ret == complex{1035, 138, complex_prec_t(128)});
1406         REQUIRE(ret.get_prec() == 128);
1407 
1408         // Try with higher precision on the non-complex argument.
1409         ret = c1 * real{23, 256};
1410         REQUIRE(ret == complex{1035, 138, complex_prec_t(128)});
1411         REQUIRE(ret.get_prec() == 256);
1412         ret = real{23, 256} * c1;
1413         REQUIRE(ret == complex{1035, 138, complex_prec_t(128)});
1414         REQUIRE(ret.get_prec() == 256);
1415 
1416         // Try with moves.
1417         auto c2 = c1;
1418         ret = complex{};
1419         ret = std::move(c1) * r1;
1420         REQUIRE(ret == complex{1035, 138, complex_prec_t(128)});
1421         REQUIRE(ret.get_prec() == 128);
1422         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
1423         REQUIRE(!c1.is_valid());
1424 
1425         c1 = c2;
1426         ret = complex{};
1427         ret = r1 * std::move(c1);
1428         REQUIRE(ret == complex{1035, 138, complex_prec_t(128)});
1429         REQUIRE(ret.get_prec() == 128);
1430         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
1431         REQUIRE(!c1.is_valid());
1432     }
1433     // complex-rv interoperable.
1434     {
1435         complex c1{45, 6, complex_prec_t(128)};
1436         auto ret = c1 * 6.;
1437         REQUIRE(ret == complex{270, 36});
1438         REQUIRE(std::is_same<complex, decltype(ret)>::value);
1439         REQUIRE(ret.get_prec() == std::max<::mpfr_prec_t>(128, detail::real_deduce_precision(6.)));
1440         ret = 6. * c1;
1441         REQUIRE(ret == complex{270, 36});
1442         REQUIRE(std::is_same<complex, decltype(6. * c1)>::value);
1443         REQUIRE(ret.get_prec() == std::max<::mpfr_prec_t>(128, detail::real_deduce_precision(6.)));
1444 
1445         // Try with higher precision on the non-complex argument.
1446         c1 = complex{1, 1, complex_prec_t(real_prec_min())};
1447         ret = c1 * 45_z1;
1448         REQUIRE(ret == complex{45, 45});
1449         REQUIRE(ret.get_prec() == detail::real_deduce_precision(45_z1));
1450         ret = 45_q1 * c1;
1451         REQUIRE(ret == complex{45, 45});
1452         REQUIRE(ret.get_prec() == detail::real_deduce_precision(45_q1));
1453 
1454         // Moves.
1455         auto c2 = c1;
1456         ret = std::move(c1) * 45;
1457         REQUIRE(ret == complex{45, 45});
1458         REQUIRE(ret.get_prec() == detail::real_deduce_precision(45));
1459         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
1460         REQUIRE(c1.is_valid());
1461         c1 = complex{1, 1, complex_prec_t(detail::real_deduce_precision(45) + 1)};
1462         ret = std::move(c1) * 45;
1463         REQUIRE(ret == complex{45, 45});
1464         REQUIRE(ret.get_prec() == detail::real_deduce_precision(45) + 1);
1465         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
1466         REQUIRE(!c1.is_valid());
1467 
1468         c1 = c2;
1469         ret = 45. * std::move(c1);
1470         REQUIRE(ret == complex{45, 45});
1471         REQUIRE(ret.get_prec() == detail::real_deduce_precision(45.));
1472         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
1473         REQUIRE(c1.is_valid());
1474         c1 = complex{1, 1, complex_prec_t(detail::real_deduce_precision(45.) + 1)};
1475         ret = 45. * std::move(c1);
1476         REQUIRE(ret == complex{45, 45});
1477         REQUIRE(ret.get_prec() == detail::real_deduce_precision(45.) + 1);
1478         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
1479         REQUIRE(!c1.is_valid());
1480 
1481 #if defined(MPPP_WITH_QUADMATH)
1482         c1 = c2;
1483         ret = 45_rq * std::move(c1);
1484         REQUIRE(ret == complex{45, 45});
1485         REQUIRE(ret.get_prec() == 113);
1486         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
1487         REQUIRE(c1.is_valid());
1488         c1 = complex{1, 1, complex_prec_t(114)};
1489         ret = 45_rq * std::move(c1);
1490         REQUIRE(ret == complex{45, 45});
1491         REQUIRE(ret.get_prec() == 114);
1492         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
1493         REQUIRE(!c1.is_valid());
1494 #endif
1495     }
1496     // complex-unsigned integral.
1497     {
1498         complex c1{45, 6, complex_prec_t(128)};
1499         auto ret = c1 * 6u;
1500         REQUIRE(ret == complex{270, 36});
1501         REQUIRE(std::is_same<complex, decltype(ret)>::value);
1502         REQUIRE(ret.get_prec() == std::max<::mpfr_prec_t>(128, detail::real_deduce_precision(6u)));
1503         ret = 6u * c1;
1504         REQUIRE(ret == complex{270, 36});
1505         REQUIRE(std::is_same<complex, decltype(6u * c1)>::value);
1506         REQUIRE(ret.get_prec() == std::max<::mpfr_prec_t>(128, detail::real_deduce_precision(6u)));
1507 
1508         // Try with higher precision on the non-complex argument.
1509         c1 = complex{1, 1, complex_prec_t(real_prec_min())};
1510         ret = c1 * 45u;
1511         REQUIRE(ret == complex{45, 45});
1512         REQUIRE(ret.get_prec() == detail::real_deduce_precision(45u));
1513         ret = 45u * c1;
1514         REQUIRE(ret == complex{45, 45});
1515         REQUIRE(ret.get_prec() == detail::real_deduce_precision(45u));
1516 
1517         // Moves.
1518         auto c2 = c1;
1519         ret = std::move(c1) * 45u;
1520         REQUIRE(ret == complex{45, 45});
1521         REQUIRE(ret.get_prec() == detail::real_deduce_precision(45u));
1522         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
1523         REQUIRE(c1.is_valid());
1524         c1 = complex{1, 1, complex_prec_t(detail::real_deduce_precision(45u) + 1)};
1525         ret = std::move(c1) * 45u;
1526         REQUIRE(ret == complex{45, 45});
1527         REQUIRE(ret.get_prec() == detail::real_deduce_precision(45u) + 1);
1528         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
1529         REQUIRE(!c1.is_valid());
1530 
1531         c1 = c2;
1532         ret = 45u * std::move(c1);
1533         REQUIRE(ret == complex{45, 45});
1534         REQUIRE(ret.get_prec() == detail::real_deduce_precision(45u));
1535         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
1536         REQUIRE(c1.is_valid());
1537         c1 = complex{1, 1, complex_prec_t(detail::real_deduce_precision(45u) + 1)};
1538         ret = 45u * std::move(c1);
1539         REQUIRE(ret == complex{45, 45});
1540         REQUIRE(ret.get_prec() == detail::real_deduce_precision(45u) + 1);
1541         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
1542         REQUIRE(!c1.is_valid());
1543 
1544         // Bool special casing.
1545         c1 = c2;
1546         ret = true * c1;
1547         REQUIRE(ret == complex{1, 1});
1548         ret = c1 * false;
1549         REQUIRE(ret == complex{0, 0});
1550         ret = true * std::move(c1);
1551         REQUIRE(ret == complex{1, 1});
1552         c1 = c2;
1553         ret = std::move(c1) * false;
1554         REQUIRE(ret == complex{0, 0});
1555 
1556 #if defined(MPPP_HAVE_GCC_INT128)
1557         // Try with a large integral.
1558         c1 = c2;
1559         ret = __uint128_t(-1) * std::move(c1);
1560         REQUIRE(ret == complex{__uint128_t(-1), __uint128_t(-1), complex_prec_t(128)});
1561         REQUIRE(ret.get_prec() == 128);
1562         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
1563         REQUIRE(c1.is_valid());
1564         c1 = complex{1, 1, complex_prec_t(129)};
1565         ret = __uint128_t(-1) * std::move(c1);
1566         REQUIRE(ret == complex{__uint128_t(-1), __uint128_t(-1), complex_prec_t(129)});
1567         REQUIRE(ret.get_prec() == 129);
1568         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
1569         REQUIRE(!c1.is_valid());
1570 
1571         c1 = c2;
1572         ret = std::move(c1) * __uint128_t(-1);
1573         REQUIRE(ret == complex{__uint128_t(-1), __uint128_t(-1), complex_prec_t(128)});
1574         REQUIRE(ret.get_prec() == 128);
1575         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
1576         REQUIRE(c1.is_valid());
1577         c1 = complex{1, 1, complex_prec_t(129)};
1578         ret = std::move(c1) * __uint128_t(-1);
1579         REQUIRE(ret == complex{__uint128_t(-1), __uint128_t(-1), complex_prec_t(129)});
1580         REQUIRE(ret.get_prec() == 129);
1581         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
1582         REQUIRE(!c1.is_valid());
1583 #endif
1584     }
1585     // complex-signed integral.
1586     {
1587         complex c1{45, 6, complex_prec_t(128)};
1588         auto ret = c1 * -6;
1589         REQUIRE(ret == complex{-270, -36});
1590         REQUIRE(std::is_same<complex, decltype(ret)>::value);
1591         REQUIRE(ret.get_prec() == std::max<::mpfr_prec_t>(128, detail::real_deduce_precision(6)));
1592         ret = -6 * c1;
1593         REQUIRE(ret == complex{-270, -36});
1594         REQUIRE(std::is_same<complex, decltype(6 * c1)>::value);
1595         REQUIRE(ret.get_prec() == std::max<::mpfr_prec_t>(128, detail::real_deduce_precision(6)));
1596 
1597         // Try with higher precision on the non-complex argument.
1598         c1 = complex{1, 1, complex_prec_t(real_prec_min())};
1599         ret = c1 * -45;
1600         REQUIRE(ret == complex{-45, -45});
1601         REQUIRE(ret.get_prec() == detail::real_deduce_precision(45));
1602         ret = -45 * c1;
1603         REQUIRE(ret == complex{-45, -45});
1604         REQUIRE(ret.get_prec() == detail::real_deduce_precision(45));
1605 
1606         // Moves.
1607         auto c2 = c1;
1608         ret = std::move(c1) * -45;
1609         REQUIRE(ret == complex{-45, -45});
1610         REQUIRE(ret.get_prec() == detail::real_deduce_precision(-45));
1611         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
1612         REQUIRE(c1.is_valid());
1613         c1 = complex{1, 1, complex_prec_t(detail::real_deduce_precision(45) + 1)};
1614         ret = std::move(c1) * -45;
1615         REQUIRE(ret == complex{-45, -45});
1616         REQUIRE(ret.get_prec() == detail::real_deduce_precision(-45) + 1);
1617         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
1618         REQUIRE(!c1.is_valid());
1619 
1620         c1 = c2;
1621         ret = -45 * std::move(c1);
1622         REQUIRE(ret == complex{-45, -45});
1623         REQUIRE(ret.get_prec() == detail::real_deduce_precision(-45));
1624         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
1625         REQUIRE(c1.is_valid());
1626         c1 = complex{1, 1, complex_prec_t(detail::real_deduce_precision(45) + 1)};
1627         ret = -45 * std::move(c1);
1628         REQUIRE(ret == complex{-45, -45});
1629         REQUIRE(ret.get_prec() == detail::real_deduce_precision(-45) + 1);
1630         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
1631         REQUIRE(!c1.is_valid());
1632 
1633 #if defined(MPPP_HAVE_GCC_INT128)
1634         // Try with a large integral.
1635         c1 = c2;
1636         const auto big_n = -(__int128_t(1) << 86);
1637         ret = big_n * std::move(c1);
1638         REQUIRE(ret == complex{big_n, big_n, complex_prec_t(128)});
1639         REQUIRE(ret.get_prec() == 128);
1640         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
1641         REQUIRE(c1.is_valid());
1642         c1 = complex{1, 1, complex_prec_t(129)};
1643         ret = big_n * std::move(c1);
1644         REQUIRE(ret == complex{big_n, big_n, complex_prec_t(129)});
1645         REQUIRE(ret.get_prec() == 129);
1646         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
1647         REQUIRE(!c1.is_valid());
1648 
1649         c1 = c2;
1650         ret = std::move(c1) * big_n;
1651         REQUIRE(ret == complex{big_n, big_n, complex_prec_t(128)});
1652         REQUIRE(ret.get_prec() == 128);
1653         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
1654         REQUIRE(c1.is_valid());
1655         c1 = complex{1, 1, complex_prec_t(129)};
1656         ret = std::move(c1) * big_n;
1657         REQUIRE(ret == complex{big_n, big_n, complex_prec_t(129)});
1658         REQUIRE(ret.get_prec() == 129);
1659         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
1660         REQUIRE(!c1.is_valid());
1661 #endif
1662     }
1663 
1664     // Complex-std::complex.
1665     {
1666         complex c1{45, 6, complex_prec_t(128)};
1667         auto ret = c1 * std::complex<double>(6, 7);
1668         REQUIRE(ret == complex{228, 351});
1669         REQUIRE(std::is_same<complex, decltype(ret)>::value);
1670         REQUIRE(ret.get_prec() == std::max<::mpfr_prec_t>(128, detail::real_deduce_precision(6.)));
1671         ret = std::complex<double>(6, 7) * c1;
1672         REQUIRE(ret == complex{228, 351});
1673         REQUIRE(std::is_same<complex, decltype(std::complex<double>(6, 7) * c1)>::value);
1674         REQUIRE(ret.get_prec() == std::max<::mpfr_prec_t>(128, detail::real_deduce_precision(6.)));
1675 
1676         // Try with higher precision on the non-complex argument.
1677         c1 = complex{1, 1, complex_prec_t(real_prec_min())};
1678         ret = c1 * std::complex<double>(6, 7);
1679         REQUIRE(ret == complex{-1, 13});
1680         REQUIRE(ret.get_prec() == detail::real_deduce_precision(6.));
1681         ret = std::complex<double>(6, 7) * c1;
1682         REQUIRE(ret == complex{-1, 13});
1683         REQUIRE(ret.get_prec() == detail::real_deduce_precision(6.));
1684 
1685         // Moves.
1686         auto c2 = c1;
1687         ret = std::move(c1) * std::complex<double>(6, 7);
1688         REQUIRE(ret == complex{-1, 13});
1689         REQUIRE(ret.get_prec() == detail::real_deduce_precision(6.));
1690         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
1691         REQUIRE(c1.is_valid());
1692         c1 = complex{1, 1, complex_prec_t(detail::real_deduce_precision(6.) + 1)};
1693         ret = std::move(c1) * std::complex<double>(6, 7);
1694         REQUIRE(ret == complex{-1, 13});
1695         REQUIRE(ret.get_prec() == detail::real_deduce_precision(6.) + 1);
1696         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
1697         REQUIRE(!c1.is_valid());
1698 
1699         c1 = c2;
1700         ret = std::complex<double>(6, 7) * std::move(c1);
1701         REQUIRE(ret == complex{-1, 13});
1702         REQUIRE(ret.get_prec() == detail::real_deduce_precision(6.));
1703         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
1704         REQUIRE(c1.is_valid());
1705         c1 = complex{1, 1, complex_prec_t(detail::real_deduce_precision(6.) + 1)};
1706         ret = std::complex<double>(6, 7) * std::move(c1);
1707         REQUIRE(ret == complex{-1, 13});
1708         REQUIRE(ret.get_prec() == detail::real_deduce_precision(6.) + 1);
1709         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
1710         REQUIRE(!c1.is_valid());
1711     }
1712 
1713 #if defined(MPPP_WITH_QUADMATH)
1714     // Complex-complex128.
1715     {
1716         complex c1{45, 6, complex_prec_t(128)};
1717         auto ret = c1 * complex128(6, 7);
1718         REQUIRE(ret == complex{228, 351});
1719         REQUIRE(std::is_same<complex, decltype(ret)>::value);
1720         REQUIRE(ret.get_prec() == 128);
1721         ret = complex128(6, 7) * c1;
1722         REQUIRE(ret == complex{228, 351});
1723         REQUIRE(std::is_same<complex, decltype(complex128(6, 7) * c1)>::value);
1724         REQUIRE(ret.get_prec() == 128);
1725 
1726         // Try with higher precision on the non-complex argument.
1727         c1 = complex{1, 1, complex_prec_t(real_prec_min())};
1728         ret = c1 * complex128(6, 7);
1729         REQUIRE(ret == complex{-1, 13});
1730         REQUIRE(ret.get_prec() == 113);
1731         ret = complex128(6, 7) * c1;
1732         REQUIRE(ret == complex{-1, 13});
1733         REQUIRE(ret.get_prec() == 113);
1734 
1735         // Moves.
1736         auto c2 = c1;
1737         ret = std::move(c1) * complex128(6, 7);
1738         REQUIRE(ret == complex{-1, 13});
1739         REQUIRE(ret.get_prec() == 113);
1740         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
1741         REQUIRE(c1.is_valid());
1742         c1 = complex{1, 1, complex_prec_t(114)};
1743         ret = std::move(c1) * complex128(6, 7);
1744         REQUIRE(ret == complex{-1, 13});
1745         REQUIRE(ret.get_prec() == 114);
1746         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
1747         REQUIRE(!c1.is_valid());
1748 
1749         c1 = c2;
1750         ret = complex128(6, 7) * std::move(c1);
1751         REQUIRE(ret == complex{-1, 13});
1752         REQUIRE(ret.get_prec() == 113);
1753         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
1754         REQUIRE(c1.is_valid());
1755         c1 = complex{1, 1, complex_prec_t(114)};
1756         ret = complex128(6, 7) * std::move(c1);
1757         REQUIRE(ret == complex{-1, 13});
1758         REQUIRE(ret.get_prec() == 114);
1759         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
1760         REQUIRE(!c1.is_valid());
1761     }
1762 #endif
1763 
1764     // real-std::complex.
1765     {
1766         real r{5, 5};
1767         auto ret = r * std::complex<double>{5, 6};
1768         REQUIRE(ret == complex{25, 30});
1769         REQUIRE(std::is_same<complex, decltype(ret)>::value);
1770         REQUIRE(ret.get_prec() == detail::real_deduce_precision(5.));
1771         ret = std::complex<double>{5, 6} * r;
1772         REQUIRE(ret == complex{25, 30});
1773         REQUIRE(std::is_same<complex, decltype(std::complex<double>{5, 6} * r)>::value);
1774         REQUIRE(ret.get_prec() == detail::real_deduce_precision(5.));
1775 
1776         // Switch precisions around.
1777         r = real{5, detail::real_deduce_precision(5.) + 1};
1778         ret = r * std::complex<double>{5, 6};
1779         REQUIRE(ret == complex{25, 30});
1780         REQUIRE(ret.get_prec() == detail::real_deduce_precision(5.) + 1);
1781         ret = std::complex<double>{5, 6} * r;
1782         REQUIRE(ret == complex{25, 30});
1783         REQUIRE(ret.get_prec() == detail::real_deduce_precision(5.) + 1);
1784 
1785         // Check moves.
1786         ret = std::move(r) * std::complex<double>{5, 6};
1787         REQUIRE(ret == complex{25, 30});
1788         REQUIRE(ret.get_prec() == detail::real_deduce_precision(5.) + 1);
1789         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
1790         REQUIRE(!r.is_valid());
1791         r = real{5, detail::real_deduce_precision(5.) + 1};
1792         ret = std::complex<double>{5, 6} * std::move(r);
1793         REQUIRE(ret == complex{25, 30});
1794         REQUIRE(ret.get_prec() == detail::real_deduce_precision(5.) + 1);
1795         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
1796         REQUIRE(!r.is_valid());
1797     }
1798 
1799 #if defined(MPPP_WITH_QUADMATH)
1800     // real-complex128.
1801     {
1802         real r{5, 5};
1803         auto ret = r * complex128{5, 6};
1804         REQUIRE(ret == complex{25, 30});
1805         REQUIRE(std::is_same<complex, decltype(ret)>::value);
1806         REQUIRE(ret.get_prec() == 113);
1807         ret = complex128{5, 6} * r;
1808         REQUIRE(ret == complex{25, 30});
1809         REQUIRE(std::is_same<complex, decltype(complex128{5, 6} * r)>::value);
1810         REQUIRE(ret.get_prec() == 113);
1811 
1812         // Switch precisions around.
1813         r = real{5, 114};
1814         ret = r * complex128{5, 6};
1815         REQUIRE(ret == complex{25, 30});
1816         REQUIRE(ret.get_prec() == 114);
1817         ret = complex128{5, 6} * r;
1818         REQUIRE(ret == complex{25, 30});
1819         REQUIRE(ret.get_prec() == 114);
1820 
1821         // Check moves.
1822         ret = std::move(r) * complex128{5, 6};
1823         REQUIRE(ret == complex{25, 30});
1824         REQUIRE(ret.get_prec() == 114);
1825         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
1826         REQUIRE(!r.is_valid());
1827         r = real{5, 114};
1828         ret = complex128{5, 6} * std::move(r);
1829         REQUIRE(ret == complex{25, 30});
1830         REQUIRE(ret.get_prec() == 114);
1831         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
1832         REQUIRE(!r.is_valid());
1833     }
1834 #endif
1835 }
1836 
1837 TEST_CASE("in-place mul")
1838 {
1839     // complex-complex.
1840     {
1841         complex c1{1, 2}, c2{3, 4};
1842         c1 *= c2;
1843         REQUIRE(std::is_same<complex &, decltype(c1 *= c2)>::value);
1844         REQUIRE(c1 == complex{-5, 10});
1845         REQUIRE(c1.get_prec() == detail::real_deduce_precision(1));
1846 
1847         // Move which does not steal.
1848         c1 *= std::move(c2);
1849         REQUIRE(c1 == complex{-55, 10});
1850         REQUIRE(c1.get_prec() == detail::real_deduce_precision(1));
1851         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
1852         REQUIRE(c2.is_valid());
1853 
1854         // Move which steals.
1855         complex c3{4, 5, complex_prec_t(detail::real_deduce_precision(1) + 1)};
1856         c1 *= std::move(c3);
1857         REQUIRE(c1.get_prec() == detail::real_deduce_precision(1) + 1);
1858         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
1859         REQUIRE(c3.is_valid());
1860         REQUIRE(c3 == complex{-55, 10});
1861         REQUIRE(c3.get_prec() == detail::real_deduce_precision(1));
1862 
1863         // Self add.
1864         c3 *= c3;
1865         REQUIRE(c3 == complex{2925, -1100});
1866     }
1867     // complex-real.
1868     {
1869         // Same precision.
1870         complex c1{1, 2};
1871         real r{4};
1872         c1 *= r;
1873         REQUIRE(std::is_same<complex &, decltype(c1 *= r)>::value);
1874         REQUIRE(c1 == complex{4, 8});
1875         REQUIRE(c1.get_prec() == detail::real_deduce_precision(1));
1876 
1877         // r with higher precision.
1878         c1 = complex{1, 1, complex_prec_t(real_prec_min())};
1879         c1 *= r;
1880         REQUIRE(c1 == complex{4, 4});
1881         REQUIRE(c1.get_prec() == detail::real_deduce_precision(1));
1882 
1883         // r with smaller precision.
1884         c1 = complex{1, 1, complex_prec_t(detail::real_deduce_precision(1) + 1)};
1885         c1 *= r;
1886         REQUIRE(c1 == complex{4, 4});
1887         REQUIRE(c1.get_prec() == detail::real_deduce_precision(1) + 1);
1888     }
1889     // complex-real valued.
1890     {
1891         // Other op with same precision.
1892         complex c1{1, 2, complex_prec_t(detail::real_deduce_precision(4.))};
1893         c1 *= 4.;
1894         REQUIRE(std::is_same<complex &, decltype(c1 *= 4.)>::value);
1895         REQUIRE(c1 == complex{4, 8});
1896         REQUIRE(c1.get_prec() == detail::real_deduce_precision(1.));
1897 
1898         // Other op with higher precision.
1899         c1 = complex{1, 1, complex_prec_t(real_prec_min())};
1900         c1 *= 4.;
1901         REQUIRE(c1 == complex{4, 4});
1902         REQUIRE(c1.get_prec() == detail::real_deduce_precision(4.));
1903 
1904         // Other op with lower precision.
1905         c1 = complex{1, 2, complex_prec_t(detail::real_deduce_precision(1.) + 1)};
1906         c1 *= 4.;
1907         REQUIRE(c1 == complex{4, 8});
1908         REQUIRE(c1.get_prec() == detail::real_deduce_precision(1.) + 1);
1909     }
1910     // complex-unsigned integral.
1911     {
1912         // Other op with same precision.
1913         complex c1{1u, 2u};
1914         c1 *= 4u;
1915         REQUIRE(std::is_same<complex &, decltype(c1 *= 4u)>::value);
1916         REQUIRE(c1 == complex{4, 8});
1917         REQUIRE(c1.get_prec() == detail::real_deduce_precision(1u));
1918 
1919         // Other op with higher precision.
1920         c1 = complex{1, 1, complex_prec_t(real_prec_min())};
1921         c1 *= 4u;
1922         REQUIRE(c1 == complex{4, 4});
1923         REQUIRE(c1.get_prec() == detail::real_deduce_precision(4u));
1924 
1925         // Other op with lower precision.
1926         c1 = complex{1, 2, complex_prec_t(detail::real_deduce_precision(1u) + 1)};
1927         c1 *= 4u;
1928         REQUIRE(c1 == complex{4, 8});
1929         REQUIRE(c1.get_prec() == detail::real_deduce_precision(1u) + 1);
1930 
1931 #if defined(MPPP_HAVE_GCC_INT128)
1932         // Test with large unsigned integral type.
1933         c1 = complex{1, 0, complex_prec_t(real_prec_min())};
1934         c1 *= __uint128_t(-1);
1935         REQUIRE(std::is_same<complex &, decltype(c1 *= __uint128_t(-1))>::value);
1936         REQUIRE(c1 == 1_z1 * __uint128_t(-1));
1937         REQUIRE(c1.get_prec() == 128);
1938 
1939         c1 = complex{1, 0, complex_prec_t(256)};
1940         c1 *= __uint128_t(-1);
1941         REQUIRE(c1 == 1_z1 * __uint128_t(-1));
1942         REQUIRE(c1.get_prec() == 256);
1943 #endif
1944     }
1945     // Special casing for bool.
1946     {
1947         // Other op with same precision.
1948         complex c1{true, false};
1949         c1 *= true;
1950         REQUIRE(std::is_same<complex &, decltype(c1 *= true)>::value);
1951         REQUIRE(c1 == complex{1, 0});
1952         REQUIRE(c1.get_prec() == detail::real_deduce_precision(true));
1953 
1954         // Other op with higher precision.
1955         c1 = complex{true, false, complex_prec_t(real_prec_min())};
1956         c1 *= true;
1957         REQUIRE(c1 == complex{1, 0});
1958         REQUIRE(c1.get_prec() == detail::real_deduce_precision(true));
1959 
1960         // Other op with lower precision.
1961         c1 = complex{1, 2, complex_prec_t(detail::real_deduce_precision(true) + 1)};
1962         c1 *= false;
1963         REQUIRE(c1 == complex{0, 0});
1964         REQUIRE(c1.get_prec() == detail::real_deduce_precision(true) + 1);
1965     }
1966     // complex-signed integral.
1967     {
1968         // Other op with same precision.
1969         complex c1{1u, 2u};
1970         c1 *= 4;
1971         REQUIRE(std::is_same<complex &, decltype(c1 *= 4)>::value);
1972         REQUIRE(c1 == complex{4, 8});
1973         REQUIRE(c1.get_prec() == detail::real_deduce_precision(1));
1974 
1975         // Other op with higher precision.
1976         c1 = complex{1, 1, complex_prec_t(real_prec_min())};
1977         c1 *= 4;
1978         REQUIRE(c1 == complex{4, 4});
1979         REQUIRE(c1.get_prec() == detail::real_deduce_precision(4));
1980 
1981         // Other op with lower precision.
1982         c1 = complex{1, 2, complex_prec_t(detail::real_deduce_precision(1) + 1)};
1983         c1 *= 4;
1984         REQUIRE(c1 == complex{4, 8});
1985         REQUIRE(c1.get_prec() == detail::real_deduce_precision(1) + 1);
1986 
1987 #if defined(MPPP_HAVE_GCC_INT128)
1988         // Test with large unsigned integral type.
1989         c1 = complex{1, 0, complex_prec_t(real_prec_min())};
1990         const auto big_n = -(__int128_t(1) << 87);
1991         c1 *= big_n;
1992         REQUIRE(std::is_same<complex &, decltype(c1 *= big_n)>::value);
1993         REQUIRE(c1 == 1_z1 * big_n);
1994         REQUIRE(c1.get_prec() == 128);
1995 
1996         c1 = complex{1, 0, complex_prec_t(256)};
1997         c1 *= big_n;
1998         REQUIRE(c1 == 1_z1 * big_n);
1999         REQUIRE(c1.get_prec() == 256);
2000 #endif
2001     }
2002 
2003     // complex-std::complex.
2004     {
2005         // Other op with same precision.
2006         complex c1{1., 2.};
2007         c1 *= std::complex<double>{3, 4};
2008         REQUIRE(std::is_same<complex &, decltype(c1 *= std::complex<double>{3, 4})>::value);
2009         REQUIRE(c1 == complex{-5, 10});
2010         REQUIRE(c1.get_prec() == detail::real_deduce_precision(1.));
2011 
2012         // Other op with higher precision.
2013         c1 = complex{1, 1, complex_prec_t(real_prec_min())};
2014         c1 *= std::complex<double>{3, 4};
2015         REQUIRE(c1 == complex{-1, 7});
2016         REQUIRE(c1.get_prec() == detail::real_deduce_precision(4.));
2017 
2018         // Other op with lower precision.
2019         c1 = complex{1, 2, complex_prec_t(detail::real_deduce_precision(1.) + 1)};
2020         c1 *= std::complex<double>{3, 4};
2021         REQUIRE(c1 == complex{-5, 10});
2022         REQUIRE(c1.get_prec() == detail::real_deduce_precision(1.) + 1);
2023     }
2024 
2025 #if defined(MPPP_WITH_QUADMATH)
2026     // complex-complex128.
2027     {
2028         // Other op with same precision.
2029         complex c1{1., 2., complex_prec_t(113)};
2030         c1 *= complex128{3, 4};
2031         REQUIRE(std::is_same<complex &, decltype(c1 *= complex128{3, 4})>::value);
2032         REQUIRE(c1 == complex{-5, 10});
2033         REQUIRE(c1.get_prec() == 113);
2034 
2035         // Other op with higher precision.
2036         c1 = complex{1, 1, complex_prec_t(real_prec_min())};
2037         c1 *= complex128{3, 4};
2038         REQUIRE(c1 == complex{-1, 7});
2039         REQUIRE(c1.get_prec() == 113);
2040 
2041         // Other op with lower precision.
2042         c1 = complex{1, 2, complex_prec_t(114)};
2043         c1 *= std::complex<double>{3, 4};
2044         REQUIRE(c1 == complex{-5, 10});
2045         REQUIRE(c1.get_prec() == 114);
2046     }
2047 #endif
2048 
2049     // complex interoperable-complex.
2050     {
2051         int n = 5;
2052         n *= complex{4, 0};
2053         REQUIRE(std::is_same<int &, decltype(n *= complex{4, 0})>::value);
2054         REQUIRE(n == 20);
2055 
2056         // Check move semantics.
2057         complex c{4, 0, complex_prec_t(detail::real_deduce_precision(1) + 1)};
2058         n *= std::move(c);
2059         REQUIRE(n == 80);
2060         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
2061         REQUIRE(!c.is_valid());
2062 
2063         // Check conversion failure.
2064         REQUIRE_THROWS_AS((n *= complex{4, 1}), std::domain_error);
2065         REQUIRE(n == 80);
2066         if (std::numeric_limits<double>::has_infinity) {
2067             REQUIRE_THROWS_AS((n *= complex{std::numeric_limits<double>::infinity(), 0}), std::domain_error);
2068             REQUIRE(n == 80);
2069         }
2070 
2071         // Try with complex-valued too.
2072         std::complex<double> cd{4, 5};
2073         cd *= complex{4, 1};
2074         REQUIRE(std::is_same<std::complex<double> &, decltype(cd *= complex{4, 1})>::value);
2075         REQUIRE(cd == std::complex<double>{11, 24});
2076 
2077 #if defined(MPPP_WITH_QUADMATH)
2078         complex128 cq{4, 5};
2079         cq *= complex{4, 1};
2080         REQUIRE(std::is_same<complex128 &, decltype(cq *= complex{4, 1})>::value);
2081         REQUIRE(cq == complex128{11, 24});
2082 #endif
2083     }
2084 
2085     // real-complex valued
2086     {
2087         real r{4, 5};
2088         r *= std::complex<double>{4, 0};
2089         REQUIRE(std::is_same<real &, decltype(r *= std::complex<double>{4, 0})>::value);
2090         REQUIRE(r == 16);
2091         REQUIRE(r.get_prec() == detail::real_deduce_precision(1.));
2092 
2093         // Check conversion failure.
2094         REQUIRE_THROWS_AS((r *= complex{4, 1}), std::domain_error);
2095         REQUIRE(r == 16);
2096 
2097 #if defined(MPPP_WITH_QUADMATH)
2098         r *= complex128{4, 0};
2099         REQUIRE(std::is_same<real &, decltype(r *= complex128{4, 0})>::value);
2100         REQUIRE(r == 64);
2101         REQUIRE(r.get_prec() == detail::c_max(detail::real_deduce_precision(1.), mpfr_prec_t(113)));
2102 #endif
2103     }
2104 
2105     // complex valued-real.
2106     {
2107         std::complex<double> c{1, 2};
2108         c *= real{2, 5};
2109         REQUIRE(std::is_same<std::complex<double> &, decltype(c *= real{2, 5})>::value);
2110         REQUIRE(c == std::complex<double>{2, 4});
2111 
2112         // Check move semantics.
2113         real r{4, detail::real_deduce_precision(1.) + 1};
2114         c *= std::move(r);
2115         REQUIRE(c == std::complex<double>{8, 16});
2116         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
2117         REQUIRE(!r.is_valid());
2118 
2119 #if defined(MPPP_WITH_QUADMATH)
2120         complex128 c2{3, 4};
2121         c2 *= real{2, 114};
2122         REQUIRE(std::is_same<complex128 &, decltype(c2 *= real{2, 114})>::value);
2123         REQUIRE(c2 == complex128{6, 8});
2124 #endif
2125     }
2126 }
2127 
2128 // NOLINTNEXTLINE(google-readability-function-size, hicpp-function-size, readability-function-size)
2129 TEST_CASE("binary div")
2130 {
2131     // complex-complex.
2132     {
2133         complex r1{11, 24}, r2{4, 5};
2134         const auto p = r1.get_prec();
2135         auto ret = r1 / r2;
2136         REQUIRE(std::is_same<complex, decltype(ret)>::value);
2137         REQUIRE(ret == complex{4, 1});
2138         REQUIRE(ret.get_prec() == r1.get_prec());
2139 
2140         // Test moves.
2141         ret = std::move(r1) / r2;
2142         REQUIRE(ret == complex{4, 1});
2143         REQUIRE(ret.get_prec() == p);
2144         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
2145         REQUIRE(!r1.is_valid());
2146 
2147         r1 = complex{11, 24};
2148         ret = r1 / std::move(r2);
2149         REQUIRE(ret == complex{4, 1});
2150         REQUIRE(ret.get_prec() == p);
2151         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
2152         REQUIRE(!r2.is_valid());
2153 
2154         r2 = complex{4, 5};
2155         ret = std::move(r1) / std::move(r2);
2156         REQUIRE(ret == complex{4, 1});
2157         REQUIRE(ret.get_prec() == p);
2158         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
2159         REQUIRE((!r1.is_valid() || !r2.is_valid()));
2160 
2161         // Self div.
2162         r2 = complex{-4, 6};
2163         REQUIRE(r2 / r2 == complex{1, 0});
2164     }
2165     // complex-real.
2166     {
2167         complex c1{44, 4, complex_prec_t(128)};
2168         real r1{2, 10};
2169         auto ret = c1 / r1;
2170         REQUIRE(std::is_same<complex, decltype(ret)>::value);
2171         REQUIRE(ret == complex{22, 2, complex_prec_t(128)});
2172         REQUIRE(ret.get_prec() == 128);
2173         ret = r1 / c1;
2174         REQUIRE(std::is_same<complex, decltype(r1 / c1)>::value);
2175         REQUIRE(ret == complex{88 / 1952_q1, -8 / 1952_q1, complex_prec_t(128)});
2176         REQUIRE(ret.get_prec() == 128);
2177 
2178         // Try with higher precision on the non-complex argument.
2179         ret = c1 / real{2, 256};
2180         REQUIRE(ret == complex{22, 2, complex_prec_t(128)});
2181         REQUIRE(ret.get_prec() == 256);
2182         ret = real{2, 256} / c1;
2183         REQUIRE(ret == complex{88 / 1952_q1, -8 / 1952_q1, complex_prec_t(256)});
2184         REQUIRE(ret.get_prec() == 256);
2185 
2186         // Try with moves.
2187         auto c2 = c1;
2188         ret = complex{};
2189         ret = std::move(c1) / r1;
2190         REQUIRE(ret == complex{22, 2, complex_prec_t(128)});
2191         REQUIRE(ret.get_prec() == 128);
2192         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
2193         REQUIRE(!c1.is_valid());
2194 
2195         c1 = c2;
2196         ret = complex{};
2197         ret = r1 / std::move(c1);
2198         REQUIRE(ret == complex{88 / 1952_q1, -8 / 1952_q1, complex_prec_t(128)});
2199         REQUIRE(ret.get_prec() == 128);
2200         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
2201         REQUIRE(!c1.is_valid());
2202     }
2203     // complex-rv interoperable.
2204     {
2205         complex c1{44, 4, complex_prec_t(128)};
2206         auto ret = c1 / 2;
2207         REQUIRE(ret == complex{22, 2});
2208         REQUIRE(std::is_same<complex, decltype(ret)>::value);
2209         REQUIRE(ret.get_prec() == std::max<::mpfr_prec_t>(128, detail::real_deduce_precision(2)));
2210         ret = 2. / c1;
2211         REQUIRE(ret
2212                 == complex{88 / 1952_q1, -8 / 1952_q1,
2213                            complex_prec_t(std::max<::mpfr_prec_t>(128, detail::real_deduce_precision(2.)))});
2214         REQUIRE(std::is_same<complex, decltype(2. / c1)>::value);
2215         REQUIRE(ret.get_prec() == std::max<::mpfr_prec_t>(128, detail::real_deduce_precision(6.)));
2216 
2217         // Try with higher precision on the non-complex argument.
2218         c1 = complex{2, -8, complex_prec_t(real_prec_min())};
2219         ret = c1 / 2_z1;
2220         REQUIRE(ret == complex{1, -4});
2221         REQUIRE(ret.get_prec() == detail::real_deduce_precision(2_z1));
2222         ret = 45_q1 / c1;
2223         REQUIRE(ret == complex{90 / 68_q1, 360 / 68_q1, complex_prec_t(detail::real_deduce_precision(45_q1))});
2224         REQUIRE(ret.get_prec() == detail::real_deduce_precision(45_q1));
2225 
2226         // Moves.
2227         auto c2 = c1;
2228         ret = std::move(c1) / 2;
2229         REQUIRE(ret == complex{1, -4});
2230         REQUIRE(ret.get_prec() == detail::real_deduce_precision(2));
2231         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
2232         REQUIRE(c1.is_valid());
2233         c1 = complex{44, 4, complex_prec_t(detail::real_deduce_precision(2) + 1)};
2234         ret = std::move(c1) / 2;
2235         REQUIRE(ret == complex{22, 2});
2236         REQUIRE(ret.get_prec() == detail::real_deduce_precision(2) + 1);
2237         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
2238         REQUIRE(!c1.is_valid());
2239 
2240         c1 = c2;
2241         ret = 45. / std::move(c1);
2242         REQUIRE(ret == complex{90 / 68_q1, 360 / 68_q1, complex_prec_t(detail::real_deduce_precision(45.))});
2243         REQUIRE(ret.get_prec() == detail::real_deduce_precision(45.));
2244         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
2245         REQUIRE(c1.is_valid());
2246         c1 = complex{2, -8, complex_prec_t(detail::real_deduce_precision(45.) + 1)};
2247         ret = 45. / std::move(c1);
2248         REQUIRE(ret == complex{90 / 68_q1, 360 / 68_q1, complex_prec_t(detail::real_deduce_precision(45.) + 1)});
2249         REQUIRE(ret.get_prec() == detail::real_deduce_precision(45.) + 1);
2250         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
2251         REQUIRE(!c1.is_valid());
2252 
2253 #if defined(MPPP_WITH_QUADMATH)
2254         c1 = c2;
2255         ret = 45_rq / std::move(c1);
2256         REQUIRE(ret == complex{90 / 68_q1, 360 / 68_q1, complex_prec_t(113)});
2257         REQUIRE(ret.get_prec() == 113);
2258         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
2259         REQUIRE(c1.is_valid());
2260         c1 = complex{2, -8, complex_prec_t(114)};
2261         ret = 45_rq / std::move(c1);
2262         REQUIRE(ret == complex{90 / 68_q1, 360 / 68_q1, complex_prec_t(114)});
2263         REQUIRE(ret.get_prec() == 114);
2264         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
2265         REQUIRE(!c1.is_valid());
2266 #endif
2267     }
2268     // complex-unsigned integral.
2269     {
2270         complex c1{44, 4, complex_prec_t(128)};
2271         auto ret = c1 / 2u;
2272         REQUIRE(ret == complex{22, 2});
2273         REQUIRE(std::is_same<complex, decltype(ret)>::value);
2274         REQUIRE(ret.get_prec() == std::max<::mpfr_prec_t>(128, detail::real_deduce_precision(2u)));
2275         ret = 2u / c1;
2276         REQUIRE(ret
2277                 == complex{88 / 1952_q1, -8 / 1952_q1,
2278                            complex_prec_t(std::max<::mpfr_prec_t>(128, detail::real_deduce_precision(2u)))});
2279         REQUIRE(std::is_same<complex, decltype(2u / c1)>::value);
2280         REQUIRE(ret.get_prec() == std::max<::mpfr_prec_t>(128, detail::real_deduce_precision(2u)));
2281 
2282         // Try with higher precision on the non-complex argument.
2283         c1 = complex{2, -8, complex_prec_t(real_prec_min())};
2284         ret = c1 / 2u;
2285         REQUIRE(ret == complex{1, -4});
2286         REQUIRE(ret.get_prec() == detail::real_deduce_precision(2u));
2287         ret = 45u / c1;
2288         REQUIRE(ret == complex{90 / 68_q1, 360 / 68_q1, complex_prec_t(detail::real_deduce_precision(45u))});
2289         REQUIRE(ret.get_prec() == detail::real_deduce_precision(45u));
2290 
2291         // Moves.
2292         auto c2 = c1;
2293         ret = std::move(c1) / 2u;
2294         REQUIRE(ret == complex{1, -4});
2295         REQUIRE(ret.get_prec() == detail::real_deduce_precision(2u));
2296         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
2297         REQUIRE(c1.is_valid());
2298         c1 = complex{44, 4, complex_prec_t(detail::real_deduce_precision(2u) + 1)};
2299         ret = std::move(c1) / 2u;
2300         REQUIRE(ret == complex{22, 2});
2301         REQUIRE(ret.get_prec() == detail::real_deduce_precision(2u) + 1);
2302         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
2303         REQUIRE(!c1.is_valid());
2304 
2305         c1 = c2;
2306         ret = 45u / std::move(c1);
2307         REQUIRE(ret == complex{90 / 68_q1, 360 / 68_q1, complex_prec_t(detail::real_deduce_precision(45u))});
2308         REQUIRE(ret.get_prec() == detail::real_deduce_precision(45u));
2309         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
2310         REQUIRE(c1.is_valid());
2311         c1 = complex{2, -8, complex_prec_t(detail::real_deduce_precision(45u) + 1)};
2312         ret = 45u / std::move(c1);
2313         REQUIRE(ret == complex{90 / 68_q1, 360 / 68_q1, complex_prec_t(detail::real_deduce_precision(45u) + 1)});
2314         REQUIRE(ret.get_prec() == detail::real_deduce_precision(45u) + 1);
2315         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
2316         REQUIRE(!c1.is_valid());
2317 
2318         // Bool special casing.
2319         c1 = c2;
2320         ret = false / c1;
2321         REQUIRE(ret == complex{});
2322         ret = c1 / true;
2323         REQUIRE(ret == c1);
2324         ret = false / std::move(c1);
2325         REQUIRE(ret == complex{});
2326         c1 = c2;
2327         ret = std::move(c1) / true;
2328         REQUIRE(ret == c2);
2329 
2330 #if defined(MPPP_HAVE_GCC_INT128)
2331         // Try with a large integral.
2332         c1 = complex{1, complex_prec_t(real_prec_min())};
2333         ret = __uint128_t(-1) / std::move(c1);
2334         REQUIRE(ret == complex{__uint128_t(-1), 0, complex_prec_t(128)});
2335         REQUIRE(ret.get_prec() == 128);
2336         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
2337         REQUIRE(c1.is_valid());
2338         c1 = complex{1, complex_prec_t(129)};
2339         ret = __uint128_t(-1) / std::move(c1);
2340         REQUIRE(ret == complex{__uint128_t(-1), 0, complex_prec_t(129)});
2341         REQUIRE(ret.get_prec() == 129);
2342         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
2343         REQUIRE(!c1.is_valid());
2344 
2345         c1 = complex{1, complex_prec_t(real_prec_min())};
2346         ret = std::move(c1) / __uint128_t(-1);
2347         REQUIRE(ret == complex{1_q1 / __uint128_t(-1), complex_prec_t(128)});
2348         REQUIRE(ret.get_prec() == 128);
2349         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
2350         REQUIRE(c1.is_valid());
2351         c1 = complex{1, complex_prec_t(129)};
2352         ret = std::move(c1) / __uint128_t(-1);
2353         REQUIRE(ret == complex{1_q1 / __uint128_t(-1), complex_prec_t(129)});
2354         REQUIRE(ret.get_prec() == 129);
2355         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
2356         REQUIRE(!c1.is_valid());
2357 #endif
2358     }
2359 
2360     // Complex-std::complex.
2361     {
2362         complex c1{11, 24, complex_prec_t(128)};
2363         auto ret = c1 / std::complex<double>(4, 5);
2364         REQUIRE(ret == complex{4, 1});
2365         REQUIRE(std::is_same<complex, decltype(ret)>::value);
2366         REQUIRE(ret.get_prec() == std::max<::mpfr_prec_t>(128, detail::real_deduce_precision(6.)));
2367         ret = std::complex<double>(35, 13) / c1;
2368         REQUIRE(ret == complex{1, -1});
2369         REQUIRE(std::is_same<complex, decltype(std::complex<double>(35, 13) / c1)>::value);
2370         REQUIRE(ret.get_prec() == std::max<::mpfr_prec_t>(128, detail::real_deduce_precision(6.)));
2371 
2372         // Try with higher precision on the non-complex argument.
2373         c1 = complex{4, 0, complex_prec_t(real_prec_min())};
2374         ret = c1 / std::complex<double>(2, 2);
2375         REQUIRE(ret == complex{1, -1});
2376         REQUIRE(ret.get_prec() == detail::real_deduce_precision(6.));
2377         ret = std::complex<double>(8, -12) / c1;
2378         REQUIRE(ret == complex{2, -3});
2379         REQUIRE(ret.get_prec() == detail::real_deduce_precision(6.));
2380 
2381         // Moves.
2382         auto c2 = c1;
2383         ret = std::move(c1) / std::complex<double>(2, 2);
2384         REQUIRE(ret == complex{1, -1});
2385         REQUIRE(ret.get_prec() == detail::real_deduce_precision(6.));
2386         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
2387         REQUIRE(c1.is_valid());
2388         c1 = complex{4, -8, complex_prec_t(detail::real_deduce_precision(6.) + 1)};
2389         ret = std::move(c1) / std::complex<double>(2, 0);
2390         REQUIRE(ret == complex{2, -4});
2391         REQUIRE(ret.get_prec() == detail::real_deduce_precision(6.) + 1);
2392         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
2393         REQUIRE(!c1.is_valid());
2394 
2395         c1 = c2;
2396         ret = std::complex<double>(8, -12) / std::move(c1);
2397         REQUIRE(ret == complex{2, -3});
2398         REQUIRE(ret.get_prec() == detail::real_deduce_precision(6.));
2399         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
2400         REQUIRE(c1.is_valid());
2401         c1 = complex{4, 0, complex_prec_t(detail::real_deduce_precision(6.) + 1)};
2402         ret = std::complex<double>(8, -12) / std::move(c1);
2403         REQUIRE(ret == complex{2, -3});
2404         REQUIRE(ret.get_prec() == detail::real_deduce_precision(6.) + 1);
2405         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
2406         REQUIRE(!c1.is_valid());
2407     }
2408 
2409 #if defined(MPPP_WITH_QUADMATH)
2410     // Complex-complex128.
2411     {
2412         complex c1{11, 24, complex_prec_t(128)};
2413         auto ret = c1 / complex128(4, 5);
2414         REQUIRE(ret == complex{4, 1});
2415         REQUIRE(std::is_same<complex, decltype(ret)>::value);
2416         REQUIRE(ret.get_prec() == 128);
2417         ret = complex128(35, 13) / c1;
2418         REQUIRE(ret == complex{1, -1});
2419         REQUIRE(std::is_same<complex, decltype(complex128(6, 7) / c1)>::value);
2420         REQUIRE(ret.get_prec() == 128);
2421 
2422         // Try with higher precision on the non-complex argument.
2423         c1 = complex{4, 0, complex_prec_t(real_prec_min())};
2424         ret = c1 / complex128(2, 2);
2425         REQUIRE(ret == complex{1, -1});
2426         REQUIRE(ret.get_prec() == 113);
2427         ret = complex128(8, -12) / c1;
2428         REQUIRE(ret == complex{2, -3});
2429         REQUIRE(ret.get_prec() == 113);
2430 
2431         // Moves.
2432         auto c2 = c1;
2433         ret = std::move(c1) / complex128(2, 2);
2434         REQUIRE(ret == complex{1, -1});
2435         REQUIRE(ret.get_prec() == 113);
2436         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
2437         REQUIRE(c1.is_valid());
2438         c1 = complex{4, -8, complex_prec_t(114)};
2439         ret = std::move(c1) / complex128(2, 0);
2440         REQUIRE(ret == complex{2, -4});
2441         REQUIRE(ret.get_prec() == 114);
2442         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
2443         REQUIRE(!c1.is_valid());
2444 
2445         c1 = c2;
2446         ret = complex128(8, -12) / std::move(c1);
2447         REQUIRE(ret == complex{2, -3});
2448         REQUIRE(ret.get_prec() == 113);
2449         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
2450         REQUIRE(c1.is_valid());
2451         c1 = complex{4, 0, complex_prec_t(114)};
2452         ret = complex128(8, -12) / std::move(c1);
2453         REQUIRE(ret == complex{2, -3});
2454         REQUIRE(ret.get_prec() == 114);
2455         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
2456         REQUIRE(!c1.is_valid());
2457     }
2458 #endif
2459 
2460     // real-std::complex.
2461     {
2462         real r{50, 5};
2463         auto ret = r / std::complex<double>{6, -8};
2464         REQUIRE(ret == complex{3, 4});
2465         REQUIRE(std::is_same<complex, decltype(ret)>::value);
2466         REQUIRE(ret.get_prec() == detail::real_deduce_precision(5.));
2467         ret = std::complex<double>{50, 600} / r;
2468         REQUIRE(ret == complex{1, 12});
2469         REQUIRE(std::is_same<complex, decltype(std::complex<double>{5, 6} / r)>::value);
2470         REQUIRE(ret.get_prec() == detail::real_deduce_precision(5.));
2471 
2472         // Switch precisions around.
2473         r = real{50, detail::real_deduce_precision(5.) + 1};
2474         ret = r / std::complex<double>{6, -8};
2475         REQUIRE(ret == complex{3, 4});
2476         REQUIRE(ret.get_prec() == detail::real_deduce_precision(5.) + 1);
2477         ret = std::complex<double>{50, 600} / r;
2478         REQUIRE(ret == complex{1, 12});
2479         REQUIRE(ret.get_prec() == detail::real_deduce_precision(5.) + 1);
2480 
2481         // Check moves.
2482         r = real{50, detail::real_deduce_precision(5.) + 1};
2483         ret = std::complex<double>{50, 600} / std::move(r);
2484         REQUIRE(ret == complex{1, 12});
2485         REQUIRE(ret.get_prec() == detail::real_deduce_precision(5.) + 1);
2486         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
2487         REQUIRE(!r.is_valid());
2488     }
2489 
2490 #if defined(MPPP_WITH_QUADMATH)
2491     // real-complex128.
2492     {
2493         real r{50, 5};
2494         auto ret = r / complex128{6, -8};
2495         REQUIRE(ret == complex{3, 4});
2496         REQUIRE(std::is_same<complex, decltype(ret)>::value);
2497         REQUIRE(ret.get_prec() == 113);
2498         ret = complex128{50, 600} / r;
2499         REQUIRE(ret == complex{1, 12});
2500         REQUIRE(std::is_same<complex, decltype(complex128{5, 6} / r)>::value);
2501         REQUIRE(ret.get_prec() == 113);
2502 
2503         // Switch precisions around.
2504         r = real{50, 114};
2505         ret = r / complex128{6, -8};
2506         REQUIRE(ret == complex{3, 4});
2507         REQUIRE(ret.get_prec() == 114);
2508         ret = complex128{50, 600} / r;
2509         REQUIRE(ret == complex{1, 12});
2510         REQUIRE(ret.get_prec() == 114);
2511 
2512         // Check moves.
2513         r = real{50, 114};
2514         ret = complex128{50, 600} / std::move(r);
2515         REQUIRE(ret == complex{1, 12});
2516         REQUIRE(ret.get_prec() == 114);
2517         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
2518         REQUIRE(!r.is_valid());
2519     }
2520 #endif
2521 }
2522 
2523 TEST_CASE("in-place div")
2524 {
2525     // complex-complex.
2526     {
2527         complex c1{909, -188}, c2{5, -6};
2528         c1 /= c2;
2529         REQUIRE(std::is_same<complex &, decltype(c1 /= c2)>::value);
2530         REQUIRE(c1 == complex{93, 74});
2531         REQUIRE(c1.get_prec() == detail::real_deduce_precision(1));
2532 
2533         // Move which does not steal.
2534         c2 = complex{1, -2};
2535         c1 /= std::move(c2);
2536         REQUIRE(c1 == complex{-11, 52});
2537         REQUIRE(c1.get_prec() == detail::real_deduce_precision(1));
2538         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
2539         REQUIRE(c2.is_valid());
2540 
2541         // Move which steals.
2542         complex c3{3, 4, complex_prec_t(detail::real_deduce_precision(1) + 1)};
2543         c1 /= std::move(c3);
2544         REQUIRE(c1.get_prec() == detail::real_deduce_precision(1) + 1);
2545         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
2546         REQUIRE(c3.is_valid());
2547         REQUIRE(c3 == complex{-11, 52});
2548         REQUIRE(c1 == complex{7, 8});
2549         REQUIRE(c3.get_prec() == detail::real_deduce_precision(1));
2550 
2551         // Self div.
2552         c3 /= *&c3;
2553         REQUIRE(c3 == complex{1, 0});
2554     }
2555     // complex-real.
2556     {
2557         // Same precision.
2558         complex c1{8, -12};
2559         real r{4};
2560         c1 /= r;
2561         REQUIRE(std::is_same<complex &, decltype(c1 /= r)>::value);
2562         REQUIRE(c1 == complex{2, -3});
2563         REQUIRE(c1.get_prec() == detail::real_deduce_precision(1));
2564 
2565         // r with higher precision.
2566         c1 = complex{8, -16, complex_prec_t(real_prec_min())};
2567         c1 /= r;
2568         REQUIRE(c1 == complex{2, -4});
2569         REQUIRE(c1.get_prec() == detail::real_deduce_precision(1));
2570 
2571         // r with smaller precision.
2572         c1 = complex{8, -16, complex_prec_t(detail::real_deduce_precision(1) + 1)};
2573         c1 /= r;
2574         REQUIRE(c1 == complex{2, -4});
2575         REQUIRE(c1.get_prec() == detail::real_deduce_precision(1) + 1);
2576     }
2577     // complex-real valued.
2578     {
2579         // Other op with same precision.
2580         complex c1{8, -16, complex_prec_t(detail::real_deduce_precision(4.))};
2581         c1 /= 4.;
2582         REQUIRE(std::is_same<complex &, decltype(c1 /= 4.)>::value);
2583         REQUIRE(c1 == complex{2, -4});
2584         REQUIRE(c1.get_prec() == detail::real_deduce_precision(1.));
2585 
2586         // Other op with higher precision.
2587         c1 = complex{8, -16, complex_prec_t(real_prec_min())};
2588         c1 /= 4;
2589         REQUIRE(c1 == complex{2, -4});
2590         REQUIRE(c1.get_prec() == detail::real_deduce_precision(4));
2591 
2592         // Other op with lower precision.
2593         c1 = complex{8, -16, complex_prec_t(detail::real_deduce_precision(1.) + 1)};
2594         c1 /= 4.;
2595         REQUIRE(c1 == complex{2, -4});
2596         REQUIRE(c1.get_prec() == detail::real_deduce_precision(1.) + 1);
2597     }
2598     // complex-unsigned integral.
2599     {
2600         // Other op with same precision.
2601         complex c1{8u, 16u};
2602         c1 /= 4u;
2603         REQUIRE(std::is_same<complex &, decltype(c1 /= 4u)>::value);
2604         REQUIRE(c1 == complex{2, 4});
2605         REQUIRE(c1.get_prec() == detail::real_deduce_precision(1u));
2606 
2607         // Other op with higher precision.
2608         c1 = complex{8, -16, complex_prec_t(real_prec_min())};
2609         c1 /= 4u;
2610         REQUIRE(c1 == complex{2, -4});
2611         REQUIRE(c1.get_prec() == detail::real_deduce_precision(4u));
2612 
2613         // Other op with lower precision.
2614         c1 = complex{8, -16, complex_prec_t(detail::real_deduce_precision(1u) + 1)};
2615         c1 /= 4u;
2616         REQUIRE(c1 == complex{2, -4});
2617         REQUIRE(c1.get_prec() == detail::real_deduce_precision(1u) + 1);
2618 
2619 #if defined(MPPP_HAVE_GCC_INT128)
2620         // Test with large unsigned integral type.
2621         c1 = complex{8, -16, complex_prec_t(real_prec_min())};
2622         c1 /= __uint128_t(-1);
2623         REQUIRE(std::is_same<complex &, decltype(c1 /= __uint128_t(-1))>::value);
2624         REQUIRE(c1 == complex{8_q1 / __uint128_t(-1), -16_q1 / __uint128_t(-1), complex_prec_t(128)});
2625         REQUIRE(c1.get_prec() == 128);
2626 
2627         c1 = complex{8, -16, complex_prec_t(256)};
2628         c1 /= __uint128_t(-1);
2629         REQUIRE(c1 == complex{8_q1 / __uint128_t(-1), -16_q1 / __uint128_t(-1), complex_prec_t(256)});
2630         REQUIRE(c1.get_prec() == 256);
2631 #endif
2632     }
2633     // Special casing for bool.
2634     {
2635         // Other op with same precision.
2636         complex c1{true, false};
2637         c1 /= true;
2638         REQUIRE(std::is_same<complex &, decltype(c1 /= true)>::value);
2639         REQUIRE(c1 == complex{1, 0});
2640         REQUIRE(c1.get_prec() == detail::real_deduce_precision(true));
2641 
2642         // Other op with higher precision.
2643         c1 = complex{true, false, complex_prec_t(real_prec_min())};
2644         c1 /= true;
2645         REQUIRE(c1 == complex{1, 0});
2646         REQUIRE(c1.get_prec() == detail::real_deduce_precision(true));
2647 
2648         // Other op with lower precision.
2649         c1 = complex{1, 2, complex_prec_t(detail::real_deduce_precision(true) + 1)};
2650         c1 /= false;
2651         REQUIRE(c1 == complex{"(inf,inf)", complex_prec_t(5)});
2652         REQUIRE(c1.get_prec() == detail::real_deduce_precision(true) + 1);
2653     }
2654 
2655     // complex-std::complex.
2656     {
2657         // Other op with same precision.
2658         complex c1{909, -188};
2659         c1 /= std::complex<double>{5, -6};
2660         REQUIRE(std::is_same<complex &, decltype(c1 /= std::complex<double>{3, 4})>::value);
2661         REQUIRE(c1 == complex{93, 74});
2662         REQUIRE(c1.get_prec() == detail::real_deduce_precision(1.));
2663 
2664         // Other op with higher precision.
2665         c1 = complex{8, -16, complex_prec_t(real_prec_min())};
2666         c1 /= std::complex<double>{2, -4};
2667         REQUIRE(c1 == complex{4, 0});
2668         REQUIRE(c1.get_prec() == detail::real_deduce_precision(4.));
2669 
2670         // Other op with lower precision.
2671         c1 = complex{8, -16, complex_prec_t(detail::real_deduce_precision(1.) + 1)};
2672         c1 /= std::complex<double>{-2, 4};
2673         REQUIRE(c1 == complex{-4, 0});
2674         REQUIRE(c1.get_prec() == detail::real_deduce_precision(1.) + 1);
2675     }
2676 
2677 #if defined(MPPP_WITH_QUADMATH)
2678     // complex-complex128.
2679     {
2680         // Other op with same precision.
2681         complex c1{909, -188, complex_prec_t(113)};
2682         c1 /= complex128{5, -6};
2683         REQUIRE(std::is_same<complex &, decltype(c1 /= complex128{3, 4})>::value);
2684         REQUIRE(c1 == complex{93, 74});
2685         REQUIRE(c1.get_prec() == 113);
2686 
2687         // Other op with higher precision.
2688         c1 = complex{8, -16, complex_prec_t(real_prec_min())};
2689         c1 /= complex128{2, -4};
2690         REQUIRE(c1 == complex{4, 0});
2691         REQUIRE(c1.get_prec() == 113);
2692 
2693         // Other op with lower precision.
2694         c1 = complex{8, -16, complex_prec_t(114)};
2695         c1 /= std::complex<double>{-2, 4};
2696         REQUIRE(c1 == complex{-4, 0});
2697         REQUIRE(c1.get_prec() == 114);
2698     }
2699 #endif
2700 
2701     // complex interoperable-complex.
2702     {
2703         int n = 4;
2704         n /= complex{-2, 0};
2705         REQUIRE(std::is_same<int &, decltype(n /= complex{4, 0})>::value);
2706         REQUIRE(n == -2);
2707 
2708         // Check move semantics.
2709         complex c{-2, 0, complex_prec_t(detail::real_deduce_precision(1) + 1)};
2710         n /= std::move(c);
2711         REQUIRE(n == 1);
2712         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
2713         REQUIRE(!c.is_valid());
2714 
2715         // Check conversion failure.
2716         REQUIRE_THROWS_AS((n /= complex{4, 1}), std::domain_error);
2717         REQUIRE(n == 1);
2718         if (std::numeric_limits<double>::has_quiet_NaN) {
2719             REQUIRE_THROWS_AS((n /= complex{std::numeric_limits<double>::quiet_NaN(), 0}), std::domain_error);
2720             REQUIRE(n == 1);
2721         }
2722 
2723         // Try with complex-valued too.
2724         std::complex<double> cd{8, 10};
2725         cd /= complex{-4, -5};
2726         REQUIRE(std::is_same<std::complex<double> &, decltype(cd /= complex{4, 1})>::value);
2727         REQUIRE(cd == std::complex<double>{-2, 0});
2728 
2729 #if defined(MPPP_WITH_QUADMATH)
2730         complex128 cq{8, 10};
2731         cq /= complex{-4, -5};
2732         REQUIRE(std::is_same<complex128 &, decltype(cq /= complex{4, 1})>::value);
2733         REQUIRE(cq == complex128{-2, 0});
2734 #endif
2735     }
2736 
2737     // real-complex valued
2738     {
2739         real r{8, 5};
2740         r /= std::complex<double>{4, 0};
2741         REQUIRE(std::is_same<real &, decltype(r /= std::complex<double>{4, 0})>::value);
2742         REQUIRE(r == 2);
2743         REQUIRE(r.get_prec() == detail::real_deduce_precision(1.));
2744 
2745         // Check conversion failure.
2746         REQUIRE_THROWS_AS((r /= complex{4, 1}), std::domain_error);
2747         REQUIRE(r == 2);
2748 
2749 #if defined(MPPP_WITH_QUADMATH)
2750         r /= complex128{-2, 0};
2751         REQUIRE(std::is_same<real &, decltype(r /= complex128{4, 0})>::value);
2752         REQUIRE(r == -1);
2753         REQUIRE(r.get_prec() == detail::c_max(detail::real_deduce_precision(1.), mpfr_prec_t(113)));
2754 #endif
2755     }
2756 
2757     // complex valued-real.
2758     {
2759         std::complex<double> c{4, -8};
2760         c /= real{2, 5};
2761         REQUIRE(std::is_same<std::complex<double> &, decltype(c /= real{2, 5})>::value);
2762         REQUIRE(c == std::complex<double>{2, -4});
2763 
2764         // Check move semantics.
2765         real r{2, detail::real_deduce_precision(1.) + 1};
2766         c /= std::move(r);
2767         REQUIRE(c == std::complex<double>{1, -2});
2768         // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
2769         REQUIRE(!r.is_valid());
2770 
2771 #if defined(MPPP_WITH_QUADMATH)
2772         complex128 c2{8, 4};
2773         c2 /= real{2, 114};
2774         REQUIRE(std::is_same<complex128 &, decltype(c2 /= real{2, 114})>::value);
2775         REQUIRE(c2 == complex128{4, 2});
2776 #endif
2777     }
2778 }
2779 
2780 // NOLINTNEXTLINE(google-readability-function-size, hicpp-function-size, readability-function-size)
2781 TEST_CASE("eq ineq")
2782 {
2783     // complex-complex.
2784     {
2785         REQUIRE(complex{1, 2} == complex{1, 2});
2786         REQUIRE(!(complex{1, 2} != complex{1, 2}));
2787         REQUIRE(complex{1, 2} != complex{2, 2});
2788         REQUIRE(!(complex{1, 2} == complex{2, 2}));
2789 
2790         // NaN testing.
2791         REQUIRE(!(complex{"(nan,0)", complex_prec_t(5)} == complex{"(nan,0)", complex_prec_t(5)}));
2792         REQUIRE(complex{"(nan,0)", complex_prec_t(5)} != complex{"(nan,0)", complex_prec_t(5)});
2793         REQUIRE(!(complex{"(nan,0)", complex_prec_t(5)} == complex{"(2,0)", complex_prec_t(5)}));
2794         REQUIRE(complex{"(nan,0)", complex_prec_t(5)} != complex{"(2,0)", complex_prec_t(5)});
2795 
2796         REQUIRE(!(complex{"(0,nan)", complex_prec_t(5)} == complex{"(0,nan)", complex_prec_t(5)}));
2797         REQUIRE(complex{"(0,nan)", complex_prec_t(5)} != complex{"(0,nan)", complex_prec_t(5)});
2798         REQUIRE(!(complex{"(0,nan)", complex_prec_t(5)} == complex{"(2,nan)", complex_prec_t(5)}));
2799         REQUIRE(complex{"(0,nan)", complex_prec_t(5)} != complex{"(2,nan)", complex_prec_t(5)});
2800 
2801         REQUIRE(!(complex{"(nan,nan)", complex_prec_t(5)} == complex{"(nan,nan)", complex_prec_t(5)}));
2802         REQUIRE(complex{"(nan,nan)", complex_prec_t(5)} != complex{"(nan,nan)", complex_prec_t(5)});
2803     }
2804     // complex-real valued (except signed integral).
2805     {
2806         REQUIRE(complex{2, 0} == 2.);
2807         REQUIRE(complex{-2, -0.} == real{-2});
2808         REQUIRE(!(complex{2, 0} != 2_z1));
2809         REQUIRE(!(complex{-2, -0.} != -2_q1));
2810         REQUIRE(2. == complex{2, 0});
2811         REQUIRE(real{-2} == complex{-2, -0.});
2812         REQUIRE(!(2_z1 != complex{2, 0}));
2813         REQUIRE(!(-2_q1 != complex{-2, -0.}));
2814 #if defined(MPPP_WITH_QUADMATH)
2815         REQUIRE(complex{2, 0} == 2_rq);
2816         REQUIRE(!(complex{2, 0} != 2_rq));
2817         REQUIRE(2_rq == complex{2, 0});
2818         REQUIRE(!(2_rq != complex{2, 0}));
2819 #endif
2820 
2821         REQUIRE(!(complex{3, 0} == 2.));
2822         REQUIRE(!(complex{-3, -0.} == real{-2}));
2823         REQUIRE(complex{3, 0} != 2_z1);
2824         REQUIRE(complex{-3, -0.} != 2_q1);
2825         REQUIRE(!(2. == complex{3, 0}));
2826         REQUIRE(!(real{-2} == complex{-3, -0.}));
2827         REQUIRE(2_z1 != complex{3, 0});
2828         REQUIRE(2_q1 != complex{-3, -0.});
2829 #if defined(MPPP_WITH_QUADMATH)
2830         REQUIRE(!(complex{3, 0} == 2_rq));
2831         REQUIRE(complex{3, 0} != 2_rq);
2832         REQUIRE(!(2_rq == complex{3, 0}));
2833         REQUIRE(2_rq != complex{3, 0});
2834 #endif
2835 
2836         REQUIRE(!(complex{2, 1} == 2.));
2837         REQUIRE(!(complex{-2, -1.} == real{-2}));
2838         REQUIRE(complex{2, 1} != 2_z1);
2839         REQUIRE(complex{-2, -1.} != 2_q1);
2840         REQUIRE(!(2. == complex{2, 1}));
2841         REQUIRE(!(real{-2} == complex{-2, -1.}));
2842         REQUIRE(2_z1 != complex{2, 1});
2843         REQUIRE(2_q1 != complex{-2, -1.});
2844 #if defined(MPPP_WITH_QUADMATH)
2845         REQUIRE(!(complex{3, 1} == 2_rq));
2846         REQUIRE(complex{3, 1} != 2_rq);
2847         REQUIRE(!(2_rq == complex{3, 1}));
2848         REQUIRE(2_rq != complex{3, 1});
2849 #endif
2850 
2851         // NaN testing.
2852         REQUIRE(!(complex{"(nan,0)", complex_prec_t(5)} == 1.));
2853         REQUIRE(complex{"(nan,0)", complex_prec_t(5)} != 1.);
2854         REQUIRE(!(complex{"(1.,nan)", complex_prec_t(5)} == 1.));
2855         REQUIRE(complex{"(1.,nan)", complex_prec_t(5)} != 1.);
2856         REQUIRE(!(1. == complex{"(nan,0)", complex_prec_t(5)}));
2857         REQUIRE(1. != complex{"(nan,0)", complex_prec_t(5)});
2858         REQUIRE(!(1. == complex{"(1.,nan)", complex_prec_t(5)}));
2859         REQUIRE(1. != complex{"(1.,nan)", complex_prec_t(5)});
2860 #if defined(MPPP_WITH_QUADMATH)
2861         REQUIRE(!(complex{"(nan,0)", complex_prec_t(5)} == 1_rq));
2862         REQUIRE(complex{"(nan,0)", complex_prec_t(5)} != 1_rq);
2863         REQUIRE(!(complex{"(1.,nan)", complex_prec_t(5)} == 1_rq));
2864         REQUIRE(complex{"(1.,nan)", complex_prec_t(5)} != 1_rq);
2865         REQUIRE(!(1_rq == complex{"(nan,0)", complex_prec_t(5)}));
2866         REQUIRE(1_rq != complex{"(nan,0)", complex_prec_t(5)});
2867         REQUIRE(!(1_rq == complex{"(1.,nan)", complex_prec_t(5)}));
2868         REQUIRE(1_rq != complex{"(1.,nan)", complex_prec_t(5)});
2869 #endif
2870     }
2871     // complex-signed integral.
2872     {
2873         REQUIRE(complex{2, 0} == 2);
2874         REQUIRE(!(complex{2, 0} != 2l));
2875         REQUIRE(2 == complex{2, 0});
2876         REQUIRE(!(2l != complex{2, 0}));
2877 
2878         REQUIRE(!(complex{3, 0} == 2));
2879         REQUIRE(!(complex{-3, -0.} == -2l));
2880         REQUIRE(complex{3, 0} != short(2));
2881         REQUIRE(complex{-3, -0.} != static_cast<signed char>(2));
2882         REQUIRE(!(2 == complex{3, 0}));
2883         REQUIRE(!(-2l == complex{-3, -0.}));
2884         REQUIRE(short(2) != complex{3, 0});
2885         REQUIRE(static_cast<signed char>(2) != complex{-3, -0.});
2886 
2887         REQUIRE(!(complex{2, 1} == 2));
2888         REQUIRE(!(complex{-2, -1.} == -2ll));
2889         REQUIRE(complex{2, 1} != 2);
2890         REQUIRE(complex{-2, -1.} != 2);
2891         REQUIRE(!(2 == complex{2, 1}));
2892         REQUIRE(!(-2ll == complex{-2, -1.}));
2893         REQUIRE(2 != complex{2, 1});
2894         REQUIRE(2 != complex{-2, -1.});
2895 
2896         // NaN testing.
2897         REQUIRE(!(complex{"(nan,0)", complex_prec_t(5)} == 1));
2898         REQUIRE(complex{"(nan,0)", complex_prec_t(5)} != 1l);
2899         REQUIRE(!(complex{"(1.,nan)", complex_prec_t(5)} == 1ll));
2900         REQUIRE(complex{"(1.,nan)", complex_prec_t(5)} != 1ll);
2901         REQUIRE(!(1 == complex{"(nan,0)", complex_prec_t(5)}));
2902         REQUIRE(1l != complex{"(nan,0)", complex_prec_t(5)});
2903         REQUIRE(!(1ll == complex{"(1.,nan)", complex_prec_t(5)}));
2904         REQUIRE(1ll != complex{"(1.,nan)", complex_prec_t(5)});
2905     }
2906     // complex-complex valued.
2907     {
2908         REQUIRE(complex{1, 2} == std::complex<double>{1, 2});
2909         REQUIRE(std::complex<double>{1, 2} == complex{1, 2});
2910         REQUIRE(!(complex{1, 2} != std::complex<double>{1, 2}));
2911         REQUIRE(!(std::complex<double>{1, 2} != complex{1, 2}));
2912 
2913         REQUIRE(complex{1, 3} != std::complex<double>{1, 2});
2914         REQUIRE(std::complex<double>{1, 2} != complex{1, 3});
2915         REQUIRE(!(complex{1, 3} == std::complex<double>{1, 2}));
2916         REQUIRE(!(std::complex<double>{1, 2} == complex{1, 3}));
2917 
2918         REQUIRE(complex{1, 2} != std::complex<double>{2, 2});
2919         REQUIRE(std::complex<double>{2, 2} != complex{1, 2});
2920         REQUIRE(!(complex{1, 2} == std::complex<double>{2, 2}));
2921         REQUIRE(!(std::complex<double>{2, 2} == complex{1, 2}));
2922 
2923 #if defined(MPPP_WITH_QUADMATH)
2924         REQUIRE(complex{1, 2} == complex128{1, 2});
2925         REQUIRE(complex128{1, 2} == complex{1, 2});
2926         REQUIRE(!(complex{1, 2} != complex128{1, 2}));
2927         REQUIRE(!(complex128{1, 2} != complex{1, 2}));
2928 
2929         REQUIRE(complex{1, 3} != complex128{1, 2});
2930         REQUIRE(complex128{1, 2} != complex{1, 3});
2931         REQUIRE(!(complex{1, 3} == complex128{1, 2}));
2932         REQUIRE(!(complex128{1, 2} == complex{1, 3}));
2933 
2934         REQUIRE(complex{1, 2} != complex128{2, 2});
2935         REQUIRE(complex128{2, 2} != complex{1, 2});
2936         REQUIRE(!(complex{1, 2} == complex128{2, 2}));
2937         REQUIRE(!(complex128{2, 2} == complex{1, 2}));
2938 #endif
2939 
2940         // NaN testing.
2941         if (std::numeric_limits<double>::has_quiet_NaN) {
2942             const auto dnan = std::numeric_limits<double>::quiet_NaN();
2943 
2944             REQUIRE(complex{"(1, nan)", complex_prec_t(5)} != std::complex<double>{1, dnan});
2945             REQUIRE(std::complex<double>{1, dnan} != complex{"(1, nan)", complex_prec_t(5)});
2946             REQUIRE(!(complex{"(1, nan)", complex_prec_t(5)} == std::complex<double>{1, dnan}));
2947             REQUIRE(!(std::complex<double>{1, dnan} == complex{"(1, nan)", complex_prec_t(5)}));
2948 
2949             REQUIRE(complex{"(nan,1)", complex_prec_t(5)} != std::complex<double>{dnan, 1});
2950             REQUIRE(std::complex<double>{dnan, 1} != complex{"(nan,1)", complex_prec_t(5)});
2951             REQUIRE(!(complex{"(nan,1)", complex_prec_t(5)} == std::complex<double>{dnan, 1}));
2952             REQUIRE(!(std::complex<double>{dnan, 1} == complex{"(nan,1)", complex_prec_t(5)}));
2953 
2954             REQUIRE(complex{"(nan,nan)", complex_prec_t(5)} != std::complex<double>{dnan, dnan});
2955             REQUIRE(std::complex<double>{dnan, dnan} != complex{"(nan,nan)", complex_prec_t(5)});
2956             REQUIRE(!(complex{"(nan,nan)", complex_prec_t(5)} == std::complex<double>{dnan, dnan}));
2957             REQUIRE(!(std::complex<double>{dnan, dnan} == complex{"(nan,nan)", complex_prec_t(5)}));
2958         }
2959     }
2960 
2961 #if defined(MPPP_WITH_QUADMATH)
2962     REQUIRE(complex{"(1, nan)", complex_prec_t(5)} != complex128{"(1,nan)"});
2963     REQUIRE(complex128{"(1,nan)"} != complex{"(1, nan)", complex_prec_t(5)});
2964     REQUIRE(!(complex{"(1, nan)", complex_prec_t(5)} == complex128{"(1,nan)"}));
2965     REQUIRE(!(complex128{"(1,nan)"} == complex{"(1, nan)", complex_prec_t(5)}));
2966 
2967     REQUIRE(complex{"(nan,1)", complex_prec_t(5)} != complex128{"(nan,1)"});
2968     REQUIRE(complex128{"(nan,1)"} != complex{"(nan,1)", complex_prec_t(5)});
2969     REQUIRE(!(complex{"(nan,1)", complex_prec_t(5)} == complex128{"(nan,1)"}));
2970     REQUIRE(!(complex128{"(nan,1)"} == complex{"(nan,1)", complex_prec_t(5)}));
2971 
2972     REQUIRE(complex{"(nan,nan)", complex_prec_t(5)} != complex128{"(nan,nan)"});
2973     REQUIRE(complex128{"(nan,nan)"} != complex{"(nan,nan)", complex_prec_t(5)});
2974     REQUIRE(!(complex{"(nan,nan)", complex_prec_t(5)} == complex128{"(nan,nan)"}));
2975     REQUIRE(!(complex128{"(nan,nan)"} == complex{"(nan,nan)", complex_prec_t(5)}));
2976 #endif
2977 }
2978