diff --git a/include/xtl/xcomplex.hpp b/include/xtl/xcomplex.hpp index 53fb52a..5767689 100644 --- a/include/xtl/xcomplex.hpp +++ b/include/xtl/xcomplex.hpp @@ -106,6 +106,23 @@ namespace xtl template using enable_scalar = std::enable_if_t::value, R>; + /************************* + * select implementation * + *************************/ + + // Complex overload of xtl::select (see xfunctional.hpp, which covers + // scalars only): at least one of v1 / v2 is complex, the other may be a + // scalar. + template , + std::disjunction, is_gen_complex>, + std::disjunction, is_gen_complex>, + std::disjunction, is_gen_complex>)> + inline std::common_type_t select(const B& cond, const T1& v1, const T2& v2) noexcept + { + return cond ? v1 : v2; + } + /******************* * common_xcomplex * *******************/ diff --git a/test/test_xcomplex.cpp b/test/test_xcomplex.cpp index fa42633..a632419 100644 --- a/test/test_xcomplex.cpp +++ b/test/test_xcomplex.cpp @@ -328,5 +328,27 @@ namespace xtl EXPECT_COMPLEX_APPROX_EQ(b / x_closure, b / 5.0); EXPECT_COMPLEX_APPROX_EQ(x_closure / b, 5.0 / b); } + + TEST(xcomplex, select) + { + std::complex a(1., 2.); + std::complex b(3., 4.); + EXPECT_EQ(select(true, a, b), a); + EXPECT_EQ(select(false, a, b), b); + + // Mixed precision promotes to the common type. + std::complex af(1.f, 2.f); + EXPECT_EQ(select(true, af, b), std::complex(1., 2.)); + EXPECT_EQ(select(false, af, b), b); + + // Mixed real / complex. + EXPECT_EQ(select(true, 5., b), std::complex(5., 0.)); + EXPECT_EQ(select(false, 5., b), b); + + xcomplex xa(1., 2.); + xcomplex xb(3., 4.); + EXPECT_EQ(select(true, xa, xb), xa); + EXPECT_EQ(select(false, xa, xb), xb); + } }