mirror of
https://gitlab.com/libeigen/eigen.git
synced 2026-04-10 11:34:33 +08:00
Add signbit function
This commit is contained in:
committed by
Rasmus Munk Larsen
parent
8f8e36458f
commit
82b152dbe7
@@ -219,7 +219,7 @@ void unary_pow_test() {
|
||||
for (Exponent exponent = min_exponent; exponent < max_exponent; ++exponent) {
|
||||
test_exponent<Base, Exponent>(exponent);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void mixed_pow_test() {
|
||||
// The following cases will test promoting a smaller exponent type
|
||||
@@ -260,6 +260,81 @@ void int_pow_test() {
|
||||
unary_pow_test<long long, int>();
|
||||
}
|
||||
|
||||
namespace Eigen {
|
||||
namespace internal {
|
||||
template <typename Scalar>
|
||||
struct test_signbit_op {
|
||||
Scalar constexpr operator()(const Scalar& a) const { return numext::signbit(a); }
|
||||
template <typename Packet>
|
||||
inline Packet packetOp(const Packet& a) const {
|
||||
return psignbit(a);
|
||||
}
|
||||
};
|
||||
template <typename Scalar>
|
||||
struct functor_traits<test_signbit_op<Scalar>> {
|
||||
enum { Cost = 1, PacketAccess = true }; //todo: define HasSignbit flag
|
||||
};
|
||||
} // namespace internal
|
||||
} // namespace Eigen
|
||||
|
||||
template <typename T, bool IsInteger = NumTraits<T>::IsInteger>
|
||||
struct ref_signbit_func_impl {
|
||||
static bool run(const T& x) { return std::signbit(x); }
|
||||
};
|
||||
template <typename T>
|
||||
struct ref_signbit_func_impl<T, true> {
|
||||
// MSVC (perhaps others) does not have a std::signbit overload for integers
|
||||
static bool run(const T& x) { return x < T(0); }
|
||||
};
|
||||
template <typename T>
|
||||
bool ref_signbit_func(const T& x) {
|
||||
return ref_signbit_func_impl<T>::run(x);
|
||||
}
|
||||
|
||||
template <typename Scalar>
|
||||
void signbit_test() {
|
||||
Scalar true_mask;
|
||||
std::memset(static_cast<void*>(&true_mask), 0xff, sizeof(Scalar));
|
||||
Scalar false_mask;
|
||||
std::memset(static_cast<void*>(&false_mask), 0x00, sizeof(Scalar));
|
||||
|
||||
const size_t size = 100 * internal::packet_traits<Scalar>::size;
|
||||
ArrayX<Scalar> x(size), y(size);
|
||||
x.setRandom();
|
||||
std::vector<Scalar> special_vals = special_values<Scalar>();
|
||||
for (size_t i = 0; i < special_vals.size(); i++) {
|
||||
x(2 * i + 0) = special_vals[i];
|
||||
x(2 * i + 1) = -special_vals[i];
|
||||
}
|
||||
y = x.unaryExpr(internal::test_signbit_op<Scalar>());
|
||||
|
||||
bool all_pass = true;
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
const Scalar ref_val = ref_signbit_func(x(i)) ? true_mask : false_mask;
|
||||
bool not_same = internal::predux_any(internal::bitwise_helper<Scalar>::bitwise_xor(ref_val, y(i)));
|
||||
if (not_same) std::cout << "signbit(" << x(i) << ") != " << y(i) << "\n";
|
||||
all_pass = all_pass && !not_same;
|
||||
}
|
||||
|
||||
VERIFY(all_pass);
|
||||
}
|
||||
void signbit_tests() {
|
||||
signbit_test<float>();
|
||||
signbit_test<double>();
|
||||
signbit_test<Eigen::half>();
|
||||
signbit_test<Eigen::bfloat16>();
|
||||
|
||||
signbit_test<uint8_t>();
|
||||
signbit_test<uint16_t>();
|
||||
signbit_test<uint32_t>();
|
||||
signbit_test<uint64_t>();
|
||||
|
||||
signbit_test<int8_t>();
|
||||
signbit_test<int16_t>();
|
||||
signbit_test<int32_t>();
|
||||
signbit_test<int64_t>();
|
||||
}
|
||||
|
||||
template<typename ArrayType> void array(const ArrayType& m)
|
||||
{
|
||||
typedef typename ArrayType::Scalar Scalar;
|
||||
@@ -855,6 +930,35 @@ template<typename ArrayType> void array_integer(const ArrayType& m)
|
||||
VERIFY( (m2 == m1.unaryExpr(arithmetic_shift_right<9>())).all() );
|
||||
}
|
||||
|
||||
template <typename ArrayType>
|
||||
struct signed_shift_test_impl {
|
||||
typedef typename ArrayType::Scalar Scalar;
|
||||
static constexpr size_t Size = sizeof(Scalar);
|
||||
static constexpr size_t MaxShift = (CHAR_BIT * Size) - 1;
|
||||
|
||||
template <size_t N = 0>
|
||||
static inline std::enable_if_t<(N > MaxShift), void> run(const ArrayType& ) {}
|
||||
template <size_t N = 0>
|
||||
static inline std::enable_if_t<(N <= MaxShift), void> run(const ArrayType& m) {
|
||||
const Index rows = m.rows();
|
||||
const Index cols = m.cols();
|
||||
|
||||
ArrayType m1 = ArrayType::Random(rows, cols), m2(rows, cols);
|
||||
|
||||
m2 = m1.unaryExpr([](const Scalar& x) { return x >> N; });
|
||||
VERIFY((m2 == m1.unaryExpr(internal::scalar_shift_right_op<Scalar, N>())).all());
|
||||
|
||||
m2 = m1.unaryExpr([](const Scalar& x) { return x << N; });
|
||||
VERIFY((m2 == m1.unaryExpr( internal::scalar_shift_left_op<Scalar, N>())).all());
|
||||
|
||||
run<N + 1>(m);
|
||||
}
|
||||
};
|
||||
template <typename ArrayType>
|
||||
void signed_shift_test(const ArrayType& m) {
|
||||
signed_shift_test_impl<ArrayType>::run(m);
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(array_cwise)
|
||||
{
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
@@ -867,6 +971,9 @@ EIGEN_DECLARE_TEST(array_cwise)
|
||||
CALL_SUBTEST_6( array(Array<Index,Dynamic,Dynamic>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||
CALL_SUBTEST_6( array_integer(ArrayXXi(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||
CALL_SUBTEST_6( array_integer(Array<Index,Dynamic,Dynamic>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||
CALL_SUBTEST_7( signed_shift_test(ArrayXXi(internal::random<int>(1, EIGEN_TEST_MAX_SIZE), internal::random<int>(1, EIGEN_TEST_MAX_SIZE))));
|
||||
CALL_SUBTEST_7( signed_shift_test(Array<Index, Dynamic, Dynamic>(internal::random<int>(1, EIGEN_TEST_MAX_SIZE), internal::random<int>(1, EIGEN_TEST_MAX_SIZE))));
|
||||
|
||||
}
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1( comparisons(Array<float, 1, 1>()) );
|
||||
@@ -897,6 +1004,7 @@ EIGEN_DECLARE_TEST(array_cwise)
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_6( int_pow_test() );
|
||||
CALL_SUBTEST_7( mixed_pow_test() );
|
||||
CALL_SUBTEST_8( signbit_tests() );
|
||||
}
|
||||
|
||||
VERIFY((internal::is_same< internal::global_math_functions_filtering_base<int>::type, int >::value));
|
||||
|
||||
Reference in New Issue
Block a user