Bit shifting functions

This commit is contained in:
Charles Schlosser
2024-05-03 18:55:02 +00:00
committed by Rasmus Munk Larsen
parent 9700fc847a
commit 8e47971789
6 changed files with 113 additions and 48 deletions

View File

@@ -1068,24 +1068,45 @@ void min_max(const ArrayType& m) {
}
}
template <int N>
struct shift_left {
template <typename Scalar>
Scalar operator()(const Scalar& v) const {
return (v << N);
template <typename Scalar>
struct shift_imm_traits {
enum { Cost = 1, PacketAccess = internal::packet_traits<Scalar>::HasShift };
};
template <int N, typename Scalar>
struct logical_left_shift_op {
Scalar operator()(const Scalar& v) const { return numext::logical_shift_left(v, N); }
template <typename Packet>
Packet packetOp(const Packet& v) const {
return internal::plogical_shift_left<N>(v);
}
};
template <int N, typename Scalar>
struct logical_right_shift_op {
Scalar operator()(const Scalar& v) const { return numext::logical_shift_right(v, N); }
template <typename Packet>
Packet packetOp(const Packet& v) const {
return internal::plogical_shift_right<N>(v);
}
};
template <int N, typename Scalar>
struct arithmetic_right_shift_op {
Scalar operator()(const Scalar& v) const { return numext::arithmetic_shift_right(v, N); }
template <typename Packet>
Packet packetOp(const Packet& v) const {
return internal::parithmetic_shift_right<N>(v);
}
};
template <int N>
struct arithmetic_shift_right {
template <typename Scalar>
Scalar operator()(const Scalar& v) const {
return (v >> N);
}
};
template <int N, typename Scalar>
struct internal::functor_traits<logical_left_shift_op<N, Scalar>> : shift_imm_traits<Scalar> {};
template <int N, typename Scalar>
struct internal::functor_traits<logical_right_shift_op<N, Scalar>> : shift_imm_traits<Scalar> {};
template <int N, typename Scalar>
struct internal::functor_traits<arithmetic_right_shift_op<N, Scalar>> : shift_imm_traits<Scalar> {};
template <typename ArrayType>
struct signed_shift_test_impl {
struct shift_test_impl {
typedef typename ArrayType::Scalar Scalar;
static constexpr size_t Size = sizeof(Scalar);
static constexpr size_t MaxShift = (CHAR_BIT * Size) - 1;
@@ -1099,20 +1120,24 @@ struct signed_shift_test_impl {
ArrayType m1 = ArrayType::Random(rows, cols), m2(rows, cols), m3(rows, cols);
m2 = m1.unaryExpr(internal::scalar_shift_right_op<Scalar, N>());
m3 = m1.unaryExpr(arithmetic_shift_right<N>());
m2 = m1.unaryExpr([](const Scalar& v) { return numext::logical_shift_left(v, N); });
m3 = m1.unaryExpr(logical_left_shift_op<N, Scalar>());
VERIFY_IS_CWISE_EQUAL(m2, m3);
m2 = m1.unaryExpr(internal::scalar_shift_left_op<Scalar, N>());
m3 = m1.unaryExpr(shift_left<N>());
m2 = m1.unaryExpr([](const Scalar& v) { return numext::logical_shift_right(v, N); });
m3 = m1.unaryExpr(logical_right_shift_op<N, Scalar>());
VERIFY_IS_CWISE_EQUAL(m2, m3);
m2 = m1.unaryExpr([](const Scalar& v) { return numext::arithmetic_shift_right(v, N); });
m3 = m1.unaryExpr(arithmetic_right_shift_op<N, Scalar>());
VERIFY_IS_CWISE_EQUAL(m2, m3);
run<N + 1>(m);
}
};
template <typename ArrayType>
void signed_shift_test(const ArrayType& m) {
signed_shift_test_impl<ArrayType>::run(m);
void shift_test(const ArrayType& m) {
shift_test_impl<ArrayType>::run(m);
}
template <typename ArrayType>
@@ -1361,10 +1386,10 @@ EIGEN_DECLARE_TEST(array_cwise) {
ArrayXXi(internal::random<int>(1, EIGEN_TEST_MAX_SIZE), internal::random<int>(1, EIGEN_TEST_MAX_SIZE))));
CALL_SUBTEST_7(array_generic(Array<Index, Dynamic, Dynamic>(internal::random<int>(1, EIGEN_TEST_MAX_SIZE),
internal::random<int>(1, EIGEN_TEST_MAX_SIZE))));
CALL_SUBTEST_8(signed_shift_test(
CALL_SUBTEST_8(shift_test(
ArrayXXi(internal::random<int>(1, EIGEN_TEST_MAX_SIZE), internal::random<int>(1, EIGEN_TEST_MAX_SIZE))));
CALL_SUBTEST_9(signed_shift_test(Array<Index, Dynamic, Dynamic>(internal::random<int>(1, EIGEN_TEST_MAX_SIZE),
internal::random<int>(1, EIGEN_TEST_MAX_SIZE))));
CALL_SUBTEST_9(shift_test(Array<Index, Dynamic, Dynamic>(internal::random<int>(1, EIGEN_TEST_MAX_SIZE),
internal::random<int>(1, EIGEN_TEST_MAX_SIZE))));
CALL_SUBTEST_10(array_generic(Array<uint32_t, Dynamic, Dynamic>(internal::random<int>(1, EIGEN_TEST_MAX_SIZE),
internal::random<int>(1, EIGEN_TEST_MAX_SIZE))));
CALL_SUBTEST_11(array_generic(Array<uint64_t, Dynamic, Dynamic>(internal::random<int>(1, EIGEN_TEST_MAX_SIZE),

View File

@@ -292,6 +292,27 @@ void check_signbit() {
check_signbit_impl<T>::run();
}
template <typename T>
void check_shift() {
using SignedT = typename numext::get_integer_by_size<sizeof(T)>::signed_type;
using UnsignedT = typename numext::get_integer_by_size<sizeof(T)>::unsigned_type;
constexpr int kNumBits = CHAR_BIT * sizeof(T);
for (int i = 0; i < 1000; ++i) {
const T a = internal::random<T>();
for (int s = 1; s < kNumBits; s++) {
T a_bsll = numext::logical_shift_left(a, s);
T a_bsll_ref = a << s;
VERIFY_IS_EQUAL(a_bsll, a_bsll_ref);
T a_bsrl = numext::logical_shift_right(a, s);
T a_bsrl_ref = numext::bit_cast<T, UnsignedT>(numext::bit_cast<UnsignedT, T>(a) >> s);
VERIFY_IS_EQUAL(a_bsrl, a_bsrl_ref);
T a_bsra = numext::arithmetic_shift_right(a, s);
T a_bsra_ref = numext::bit_cast<T, SignedT>(numext::bit_cast<SignedT, T>(a) >> s);
VERIFY_IS_EQUAL(a_bsra, a_bsra_ref);
}
}
}
EIGEN_DECLARE_TEST(numext) {
for (int k = 0; k < g_repeat; ++k) {
CALL_SUBTEST(check_negate<signed char>());
@@ -354,5 +375,15 @@ EIGEN_DECLARE_TEST(numext) {
CALL_SUBTEST(check_signbit<int16_t>());
CALL_SUBTEST(check_signbit<int32_t>());
CALL_SUBTEST(check_signbit<int64_t>());
CALL_SUBTEST(check_shift<int8_t>());
CALL_SUBTEST(check_shift<int16_t>());
CALL_SUBTEST(check_shift<int32_t>());
CALL_SUBTEST(check_shift<int64_t>());
CALL_SUBTEST(check_shift<uint8_t>());
CALL_SUBTEST(check_shift<uint16_t>());
CALL_SUBTEST(check_shift<uint32_t>());
CALL_SUBTEST(check_shift<uint64_t>());
}
}