Skip to content

Commit e3cdb6a

Browse files
committed
refactor: split is_dup_lo/is_dup_hi into named predicates
Address review: the shared is_dup_from_half<Hi> helper hid the intent behind 'v[i] < lo || v[i] >= hi || v[i + half] != v[i]'. Each direction is now a conjunction of named properties (in-range, only-from-half, equal-halves), differing by exactly one term. Adds the negative-index dup_lo case previously covered by the explicit lower bound.
1 parent 5a7dc07 commit e3cdb6a

2 files changed

Lines changed: 21 additions & 8 deletions

File tree

include/xsimd/arch/common/xsimd_common_swizzle.hpp

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,24 +47,36 @@ namespace xsimd
4747
return ((Vs >= static_cast<T>(sizeof...(Vs) / 2)) && ...);
4848
}
4949

50-
// both halves read the same indices, all taken from the Hi ? high : low half
51-
template <typename T, bool Hi, T... Vs>
52-
XSIMD_INLINE constexpr bool is_dup_from_half() noexcept
50+
// 0 <= v[i] < N for every i (negative values wrap to a huge size_t)
51+
template <typename T, T... Vs>
52+
XSIMD_INLINE constexpr bool is_in_range() noexcept
53+
{
54+
return ((static_cast<std::size_t>(Vs) < sizeof...(Vs)) && ...);
55+
}
56+
57+
// v[i] == v[i + N / 2] for every i in the low half
58+
template <typename T, T... Vs>
59+
XSIMD_INLINE constexpr bool has_equal_halves() noexcept
5360
{
5461
constexpr std::size_t half = sizeof...(Vs) / 2;
55-
constexpr T lo = Hi ? static_cast<T>(half) : T(0);
56-
constexpr T hi = Hi ? static_cast<T>(sizeof...(Vs)) : static_cast<T>(half);
5762
constexpr T v[] = { Vs... };
5863
for (std::size_t i = 0; i < half; ++i)
59-
if (v[i] < lo || v[i] >= hi || v[i + half] != v[i])
64+
if (v[i] != v[i + half])
6065
return false;
6166
return true;
6267
}
6368

69+
// both halves read the same indices, all taken from the low / high half
6470
template <typename T, T... Vs>
65-
XSIMD_INLINE constexpr bool is_dup_lo() noexcept { return is_dup_from_half<T, false, Vs...>(); }
71+
XSIMD_INLINE constexpr bool is_dup_lo() noexcept
72+
{
73+
return is_in_range<T, Vs...>() && is_only_from_lo<T, Vs...>() && has_equal_halves<T, Vs...>();
74+
}
6675
template <typename T, T... Vs>
67-
XSIMD_INLINE constexpr bool is_dup_hi() noexcept { return is_dup_from_half<T, true, Vs...>(); }
76+
XSIMD_INLINE constexpr bool is_dup_hi() noexcept
77+
{
78+
return is_in_range<T, Vs...>() && is_only_from_hi<T, Vs...>() && has_equal_halves<T, Vs...>();
79+
}
6880

6981
/**
7082
* @brief Internal: Check if a swizzle pattern crosses lane boundaries

test/test_batch_manip.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ namespace xsimd
6060
static_assert(is_dup_hi<std::int8_t, 4, 7, 5, 5, 4, 7, 5, 5>(), "int8_t dup_hi failed");
6161
static_assert(!is_dup_hi<std::int8_t, 4, 7, 5, 5, 4, 7, 5, 4>(), "int8_t dup_hi on non-dup");
6262
static_assert(!is_dup_hi<std::int8_t, 4, 7, 5, 8, 4, 7, 5, 8>(), "int8_t dup_hi with out-of-range index");
63+
static_assert(!is_dup_lo<std::int8_t, -1, 1, -1, 1>(), "int8_t dup_lo with negative index");
6364
static_assert(is_only_from_lo<std::int64_t, 0, 1, 1, 0>(), "int64_t only_from_lo failed");
6465
static_assert(is_only_from_hi<std::int64_t, 2, 3, 3, 2>(), "int64_t only_from_hi failed");
6566
// degenerate pack sizes

0 commit comments

Comments
 (0)