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