File indexing completed on 2025-08-28 09:11:39
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #ifndef XSIMD_BATCH_CONSTANT_HPP
0013 #define XSIMD_BATCH_CONSTANT_HPP
0014
0015 #include "./xsimd_batch.hpp"
0016 #include "./xsimd_utils.hpp"
0017
0018 namespace xsimd
0019 {
0020
0021
0022
0023
0024
0025
0026
0027
0028 template <typename T, class A, bool... Values>
0029 struct batch_bool_constant
0030 {
0031 using batch_type = batch_bool<T, A>;
0032 static constexpr std::size_t size = sizeof...(Values);
0033 using value_type = bool;
0034 static_assert(sizeof...(Values) == batch_type::size, "consistent batch size");
0035
0036 public:
0037
0038
0039
0040 constexpr batch_type as_batch_bool() const noexcept { return { Values... }; }
0041
0042
0043
0044
0045 constexpr operator batch_type() const noexcept { return as_batch_bool(); }
0046
0047 constexpr bool get(size_t i) const noexcept
0048 {
0049 return std::array<value_type, size> { { Values... } }[i];
0050 }
0051
0052 static constexpr int mask() noexcept
0053 {
0054 return mask_helper(0, static_cast<int>(Values)...);
0055 }
0056
0057 private:
0058 static constexpr int mask_helper(int acc) noexcept { return acc; }
0059
0060 template <class... Tys>
0061 static constexpr int mask_helper(int acc, int mask, Tys... masks) noexcept
0062 {
0063 return mask_helper(acc | mask, (masks << 1)...);
0064 }
0065
0066 struct logical_or
0067 {
0068 constexpr bool operator()(bool x, bool y) const { return x || y; }
0069 };
0070 struct logical_and
0071 {
0072 constexpr bool operator()(bool x, bool y) const { return x && y; }
0073 };
0074 struct logical_xor
0075 {
0076 constexpr bool operator()(bool x, bool y) const { return x ^ y; }
0077 };
0078
0079 template <class F, class SelfPack, class OtherPack, size_t... Indices>
0080 static constexpr batch_bool_constant<T, A, F()(std::tuple_element<Indices, SelfPack>::type::value, std::tuple_element<Indices, OtherPack>::type::value)...>
0081 apply(detail::index_sequence<Indices...>)
0082 {
0083 return {};
0084 }
0085
0086 template <class F, bool... OtherValues>
0087 static constexpr auto apply(batch_bool_constant<T, A, Values...>, batch_bool_constant<T, A, OtherValues...>)
0088 -> decltype(apply<F, std::tuple<std::integral_constant<bool, Values>...>, std::tuple<std::integral_constant<bool, OtherValues>...>>(detail::make_index_sequence<sizeof...(Values)>()))
0089 {
0090 static_assert(sizeof...(Values) == sizeof...(OtherValues), "compatible constant batches");
0091 return apply<F, std::tuple<std::integral_constant<bool, Values>...>, std::tuple<std::integral_constant<bool, OtherValues>...>>(detail::make_index_sequence<sizeof...(Values)>());
0092 }
0093
0094 public:
0095 #define MAKE_BINARY_OP(OP, NAME) \
0096 template <bool... OtherValues> \
0097 constexpr auto operator OP(batch_bool_constant<T, A, OtherValues...> other) const \
0098 -> decltype(apply<NAME>(*this, other)) \
0099 { \
0100 return apply<NAME>(*this, other); \
0101 }
0102
0103 MAKE_BINARY_OP(|, logical_or)
0104 MAKE_BINARY_OP(||, logical_or)
0105 MAKE_BINARY_OP(&, logical_and)
0106 MAKE_BINARY_OP(&&, logical_and)
0107 MAKE_BINARY_OP(^, logical_xor)
0108
0109 #undef MAKE_BINARY_OP
0110
0111 constexpr batch_bool_constant<T, A, !Values...> operator!() const
0112 {
0113 return {};
0114 }
0115
0116 constexpr batch_bool_constant<T, A, !Values...> operator~() const
0117 {
0118 return {};
0119 }
0120 };
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130 template <typename T, class A, T... Values>
0131 struct batch_constant
0132 {
0133 static constexpr std::size_t size = sizeof...(Values);
0134 using batch_type = batch<T, A>;
0135 using value_type = typename batch_type::value_type;
0136 static_assert(sizeof...(Values) == batch_type::size, "consistent batch size");
0137
0138
0139
0140
0141 XSIMD_INLINE batch_type as_batch() const noexcept { return { Values... }; }
0142
0143
0144
0145
0146 XSIMD_INLINE operator batch_type() const noexcept { return as_batch(); }
0147
0148
0149
0150
0151 constexpr T get(size_t i) const noexcept
0152 {
0153 return get(i, std::array<T, size> { Values... });
0154 }
0155
0156 private:
0157 constexpr T get(size_t i, std::array<T, size> const& values) const noexcept
0158 {
0159 return values[i];
0160 }
0161
0162 struct arithmetic_add
0163 {
0164 constexpr T operator()(T x, T y) const { return x + y; }
0165 };
0166 struct arithmetic_sub
0167 {
0168 constexpr T operator()(T x, T y) const { return x - y; }
0169 };
0170 struct arithmetic_mul
0171 {
0172 constexpr T operator()(T x, T y) const { return x * y; }
0173 };
0174 struct arithmetic_div
0175 {
0176 constexpr T operator()(T x, T y) const { return x / y; }
0177 };
0178 struct arithmetic_mod
0179 {
0180 constexpr T operator()(T x, T y) const { return x % y; }
0181 };
0182 struct binary_and
0183 {
0184 constexpr T operator()(T x, T y) const { return x & y; }
0185 };
0186 struct binary_or
0187 {
0188 constexpr T operator()(T x, T y) const { return x | y; }
0189 };
0190 struct binary_xor
0191 {
0192 constexpr T operator()(T x, T y) const { return x ^ y; }
0193 };
0194
0195 template <class F, class SelfPack, class OtherPack, size_t... Indices>
0196 static constexpr batch_constant<T, A, F()(std::tuple_element<Indices, SelfPack>::type::value, std::tuple_element<Indices, OtherPack>::type::value)...>
0197 apply(detail::index_sequence<Indices...>)
0198 {
0199 return {};
0200 }
0201
0202 template <class F, T... OtherValues>
0203 static constexpr auto apply(batch_constant<T, A, Values...>, batch_constant<T, A, OtherValues...>)
0204 -> decltype(apply<F, std::tuple<std::integral_constant<T, Values>...>, std::tuple<std::integral_constant<T, OtherValues>...>>(detail::make_index_sequence<sizeof...(Values)>()))
0205 {
0206 static_assert(sizeof...(Values) == sizeof...(OtherValues), "compatible constant batches");
0207 return apply<F, std::tuple<std::integral_constant<T, Values>...>, std::tuple<std::integral_constant<T, OtherValues>...>>(detail::make_index_sequence<sizeof...(Values)>());
0208 }
0209
0210 public:
0211 #define MAKE_BINARY_OP(OP, NAME) \
0212 template <T... OtherValues> \
0213 constexpr auto operator OP(batch_constant<T, A, OtherValues...> other) const \
0214 -> decltype(apply<NAME>(*this, other)) \
0215 { \
0216 return apply<NAME>(*this, other); \
0217 }
0218
0219 MAKE_BINARY_OP(+, arithmetic_add)
0220 MAKE_BINARY_OP(-, arithmetic_sub)
0221 MAKE_BINARY_OP(*, arithmetic_mul)
0222 MAKE_BINARY_OP(/, arithmetic_div)
0223 MAKE_BINARY_OP(%, arithmetic_mod)
0224 MAKE_BINARY_OP(&, binary_and)
0225 MAKE_BINARY_OP(|, binary_or)
0226 MAKE_BINARY_OP(^, binary_xor)
0227
0228 #undef MAKE_BINARY_OP
0229
0230 constexpr batch_constant<T, A, (T)-Values...> operator-() const
0231 {
0232 return {};
0233 }
0234
0235 constexpr batch_constant<T, A, (T) + Values...> operator+() const
0236 {
0237 return {};
0238 }
0239
0240 constexpr batch_constant<T, A, (T)~Values...> operator~() const
0241 {
0242 return {};
0243 }
0244 };
0245
0246 namespace detail
0247 {
0248 template <typename T, class A, class G, std::size_t... Is>
0249 XSIMD_INLINE constexpr auto make_batch_constant(detail::index_sequence<Is...>) noexcept
0250 -> batch_constant<T, A, (T)G::get(Is, sizeof...(Is))...>
0251 {
0252 return {};
0253 }
0254 template <typename T, class A, class G, std::size_t... Is>
0255 XSIMD_INLINE constexpr auto make_batch_bool_constant(detail::index_sequence<Is...>) noexcept
0256 -> batch_bool_constant<T, A, G::get(Is, sizeof...(Is))...>
0257 {
0258 return {};
0259 }
0260
0261 }
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280
0281
0282
0283 template <typename T, class A, class G>
0284 XSIMD_INLINE constexpr auto make_batch_constant() noexcept -> decltype(detail::make_batch_constant<T, A, G>(detail::make_index_sequence<batch<T, A>::size>()))
0285 {
0286 return detail::make_batch_constant<T, A, G>(detail::make_index_sequence<batch<T, A>::size>());
0287 }
0288
0289 template <typename T, class A, class G>
0290 XSIMD_INLINE constexpr auto make_batch_bool_constant() noexcept
0291 -> decltype(detail::make_batch_bool_constant<T, A, G>(
0292 detail::make_index_sequence<batch<T, A>::size>()))
0293 {
0294 return detail::make_batch_bool_constant<T, A, G>(
0295 detail::make_index_sequence<batch<T, A>::size>());
0296 }
0297
0298 }
0299
0300 #endif