Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-08-28 09:11:39

0001 /***************************************************************************
0002  * Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *
0003  * Martin Renou                                                             *
0004  * Copyright (c) QuantStack                                                 *
0005  * Copyright (c) Serge Guelton                                              *
0006  *                                                                          *
0007  * Distributed under the terms of the BSD 3-Clause License.                 *
0008  *                                                                          *
0009  * The full license is in the file LICENSE, distributed with this software. *
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      * @brief batch of boolean constant
0022      *
0023      * Abstract representation of a batch of boolean constants.
0024      *
0025      * @tparam batch_type the type of the associated batch values.
0026      * @tparam Values boolean constant represented by this batch
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          * @brief Generate a batch of @p batch_type from this @p batch_bool_constant
0039          */
0040         constexpr batch_type as_batch_bool() const noexcept { return { Values... }; }
0041 
0042         /**
0043          * @brief Generate a batch of @p batch_type from this @p batch_bool_constant
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      * @brief batch of integral constants
0124      *
0125      * Abstract representation of a batch of integral constants.
0126      *
0127      * @tparam batch_type the type of the associated batch values.
0128      * @tparam Values constants represented by this batch
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          * @brief Generate a batch of @p batch_type from this @p batch_constant
0140          */
0141         XSIMD_INLINE batch_type as_batch() const noexcept { return { Values... }; }
0142 
0143         /**
0144          * @brief Generate a batch of @p batch_type from this @p batch_constant
0145          */
0146         XSIMD_INLINE operator batch_type() const noexcept { return as_batch(); }
0147 
0148         /**
0149          * @brief Get the @p i th element of this @p batch_constant
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     } // namespace detail
0262 
0263     /**
0264      * @brief Build a @c batch_constant out of a generator function
0265      *
0266      * @tparam batch_type type of the (non-constant) batch to build
0267      * @tparam G type used to generate that batch. That type must have a static
0268      * member @c get that's used to generate the batch constant. Conversely, the
0269      * generated batch_constant has value `{G::get(0, batch_size), ... , G::get(batch_size - 1, batch_size)}`
0270      *
0271      * The following generator produces a batch of `(n - 1, 0, 1, ... n-2)`
0272      *
0273      * @code
0274      * struct Rot
0275      * {
0276      *     static constexpr unsigned get(unsigned i, unsigned n)
0277      *     {
0278      *         return (i + n - 1) % n;
0279      *     }
0280      * };
0281      * @endcode
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 } // namespace xsimd
0299 
0300 #endif