From fa4a43a49a017d09d04f5ca4dbbd0ca2b0491c2a Mon Sep 17 00:00:00 2001 From: Lukas Tenbrink Date: Sun, 5 Jul 2026 18:43:23 +0200 Subject: [PATCH] Add xtl::select overload for complex values. xtl::select is constrained to scalar types, so xt::where (xt::detail::conditional_ternary, which calls xtl::select on its scalar path) does not compile for complex operands, e.g.: xt::xarray> r = xt::where(cond, a, b); xoperation.hpp:136:24: error: no matching function for call to 'select' Add an overload in xcomplex.hpp covering std::complex and xtl::xcomplex, where at least one of the value arguments is complex and the other may be a scalar. Mirrors how xoptional.hpp hosts the select overload for its own types. Co-Authored-By: Claude Fable 5 --- include/xtl/xcomplex.hpp | 17 +++++++++++++++++ test/test_xcomplex.cpp | 22 ++++++++++++++++++++++ 2 files changed, 39 insertions(+) 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); + } }