Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-11-07 10:37:00

0001 /***************************************************************************
0002  * Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *
0003  * Martin Renou                                                             *
0004  * Copyright (c) QuantStack                                                 *
0005  * Copyright (c) Serge Guelton                                              *
0006  * Copyright (c) Marco Barbone                                              *
0007  *                                                                          *
0008  * Distributed under the terms of the BSD 3-Clause License.                 *
0009  *                                                                          *
0010  * The full license is in the file LICENSE, distributed with this software. *
0011  ****************************************************************************/
0012 
0013 #ifndef XSIMD_UTILS_SHIFTS_HPP
0014 #define XSIMD_UTILS_SHIFTS_HPP
0015 
0016 #include "../../config/xsimd_macros.hpp"
0017 #include "../../types/xsimd_batch.hpp"
0018 #include "../../types/xsimd_batch_constant.hpp"
0019 #include "../../types/xsimd_traits.hpp"
0020 
0021 namespace xsimd
0022 {
0023     namespace kernel
0024     {
0025         namespace utils
0026         {
0027             template <typename I, I offset, I length, I... Vs>
0028             struct select_stride
0029             {
0030                 template <typename K>
0031                 static constexpr K get(K i, K)
0032                 {
0033                     constexpr I values_array[] = { Vs... };
0034                     return static_cast<K>(values_array[length * i + offset]);
0035                 }
0036             };
0037 
0038             template <typename I>
0039             constexpr I lsb_mask(I bit_index)
0040             {
0041                 if (bit_index == 8 * sizeof(I))
0042                 {
0043                     return ~I { 0 };
0044                 }
0045                 return static_cast<I>((I { 1 } << bit_index) - I { 1 });
0046             }
0047 
0048             template <class T, class A, T V0, T... Vs>
0049             constexpr bool all_equals(batch_constant<T, A, V0, Vs...> c)
0050             {
0051                 return (c == std::integral_constant<T, V0> {}).all();
0052             }
0053 
0054             template <class T, class A, T... Vs>
0055             XSIMD_INLINE batch<T, A> bitwise_lshift_as_twice_larger(
0056                 batch<T, A> const& self, batch_constant<T, A, Vs...>) noexcept
0057             {
0058                 using T2 = widen_t<T>;
0059 
0060                 const auto self2 = bitwise_cast<T2>(self);
0061 
0062                 // Lower byte: shift as twice the size and mask bits flowing to higher byte.
0063                 constexpr auto shifts_lo = make_batch_constant<T2, select_stride<T, 0, 2, Vs...>, A>();
0064                 constexpr auto mask_lo = lsb_mask<T2>(8 * sizeof(T));
0065                 const auto shifted_lo = bitwise_lshift(self2, shifts_lo);
0066                 constexpr auto batch_mask_lo = make_batch_constant<T2, mask_lo, A>();
0067                 const auto masked_lo = bitwise_and(shifted_lo, batch_mask_lo.as_batch());
0068 
0069                 // Higher byte: mask bits that would flow from lower byte and shift as twice the size.
0070                 constexpr auto shifts_hi = make_batch_constant<T2, select_stride<T, 1, 2, Vs...>, A>();
0071                 constexpr auto mask_hi = mask_lo << (8 * sizeof(T));
0072                 constexpr auto batch_mask_hi = make_batch_constant<T2, mask_hi, A>();
0073                 const auto masked_hi = bitwise_and(self2, batch_mask_hi.as_batch());
0074                 const auto shifted_hi = bitwise_lshift(masked_hi, shifts_hi);
0075 
0076                 return bitwise_cast<T>(bitwise_or(masked_lo, shifted_hi));
0077             }
0078         }
0079     }
0080 }
0081 
0082 #endif