ADD: added other eigen lib
This commit is contained in:
@@ -7,12 +7,22 @@
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include <vector>
|
||||
#include "main.h"
|
||||
|
||||
template <typename Scalar, std::enable_if_t<NumTraits<Scalar>::IsInteger,int> = 0>
|
||||
std::vector<Scalar> special_values() {
|
||||
const Scalar zero = Scalar(0);
|
||||
const Scalar one = Scalar(1);
|
||||
const Scalar two = Scalar(2);
|
||||
const Scalar three = Scalar(3);
|
||||
const Scalar min = (std::numeric_limits<Scalar>::min)();
|
||||
const Scalar max = (std::numeric_limits<Scalar>::max)();
|
||||
return { zero, min, one, two, three, max };
|
||||
}
|
||||
|
||||
// Test the corner cases of pow(x, y) for real types.
|
||||
template<typename Scalar>
|
||||
void pow_test() {
|
||||
template <typename Scalar, std::enable_if_t<!NumTraits<Scalar>::IsInteger, int> = 0>
|
||||
std::vector<Scalar> special_values() {
|
||||
const Scalar zero = Scalar(0);
|
||||
const Scalar eps = Eigen::NumTraits<Scalar>::epsilon();
|
||||
const Scalar one = Scalar(1);
|
||||
@@ -26,36 +36,29 @@ void pow_test() {
|
||||
const Scalar min = (std::numeric_limits<Scalar>::min)();
|
||||
const Scalar max = (std::numeric_limits<Scalar>::max)();
|
||||
const Scalar max_exp = (static_cast<Scalar>(int(Eigen::NumTraits<Scalar>::max_exponent())) * Scalar(EIGEN_LN2)) / eps;
|
||||
return { zero, denorm_min, min, eps, sqrt_half, one, sqrt2, two, three, max_exp, max, inf, nan };
|
||||
}
|
||||
|
||||
const static Scalar abs_vals[] = {zero,
|
||||
denorm_min,
|
||||
min,
|
||||
eps,
|
||||
sqrt_half,
|
||||
one,
|
||||
sqrt2,
|
||||
two,
|
||||
three,
|
||||
max_exp,
|
||||
max,
|
||||
inf,
|
||||
nan};
|
||||
const int abs_cases = 13;
|
||||
const int num_cases = 2*abs_cases * 2*abs_cases;
|
||||
// Repeat the same value to make sure we hit the vectorized path.
|
||||
const int num_repeats = 32;
|
||||
Array<Scalar, Dynamic, Dynamic> x(num_repeats, num_cases);
|
||||
Array<Scalar, Dynamic, Dynamic> y(num_repeats, num_cases);
|
||||
template<typename Scalar>
|
||||
void special_value_pairs(Array<Scalar, Dynamic, Dynamic>& x,
|
||||
Array<Scalar, Dynamic, Dynamic>& y) {
|
||||
std::vector<Scalar> abs_vals = special_values<Scalar>();
|
||||
const Index abs_cases = (Index)abs_vals.size();
|
||||
const Index num_cases = 2*abs_cases * 2*abs_cases;
|
||||
// ensure both vectorized and non-vectorized paths taken
|
||||
const Index num_repeats = 2 * (Index)internal::packet_traits<Scalar>::size + 1;
|
||||
x.resize(num_repeats, num_cases);
|
||||
y.resize(num_repeats, num_cases);
|
||||
int count = 0;
|
||||
for (int i = 0; i < abs_cases; ++i) {
|
||||
for (Index i = 0; i < abs_cases; ++i) {
|
||||
const Scalar abs_x = abs_vals[i];
|
||||
for (int sign_x = 0; sign_x < 2; ++sign_x) {
|
||||
for (Index sign_x = 0; sign_x < 2; ++sign_x) {
|
||||
Scalar x_case = sign_x == 0 ? -abs_x : abs_x;
|
||||
for (int j = 0; j < abs_cases; ++j) {
|
||||
for (Index j = 0; j < abs_cases; ++j) {
|
||||
const Scalar abs_y = abs_vals[j];
|
||||
for (int sign_y = 0; sign_y < 2; ++sign_y) {
|
||||
for (Index sign_y = 0; sign_y < 2; ++sign_y) {
|
||||
Scalar y_case = sign_y == 0 ? -abs_y : abs_y;
|
||||
for (int repeat = 0; repeat < num_repeats; ++repeat) {
|
||||
for (Index repeat = 0; repeat < num_repeats; ++repeat) {
|
||||
x(repeat, count) = x_case;
|
||||
y(repeat, count) = y_case;
|
||||
}
|
||||
@@ -64,24 +67,266 @@ void pow_test() {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Array<Scalar, Dynamic, Dynamic> actual = x.pow(y);
|
||||
template <typename Scalar, typename Fn, typename RefFn>
|
||||
void binary_op_test(std::string name, Fn fun, RefFn ref) {
|
||||
const Scalar tol = test_precision<Scalar>();
|
||||
Array<Scalar, Dynamic, Dynamic> x;
|
||||
Array<Scalar, Dynamic, Dynamic> y;
|
||||
special_value_pairs(x, y);
|
||||
|
||||
Array<Scalar, Dynamic, Dynamic> actual = fun(x, y);
|
||||
bool all_pass = true;
|
||||
for (int i = 0; i < 1; ++i) {
|
||||
for (int j = 0; j < num_cases; ++j) {
|
||||
Scalar e = static_cast<Scalar>(std::pow(x(i,j), y(i,j)));
|
||||
for (Index i = 0; i < x.rows(); ++i) {
|
||||
for (Index j = 0; j < x.cols(); ++j) {
|
||||
Scalar e = static_cast<Scalar>(ref(x(i,j), y(i,j)));
|
||||
Scalar a = actual(i, j);
|
||||
bool fail = !(a==e) && !internal::isApprox(a, e, tol) && !((numext::isnan)(a) && (numext::isnan)(e));
|
||||
all_pass &= !fail;
|
||||
if (fail) {
|
||||
std::cout << "pow(" << x(i,j) << "," << y(i,j) << ") = " << a << " != " << e << std::endl;
|
||||
bool success = (a==e) || ((numext::isfinite)(e) && internal::isApprox(a, e, tol)) || ((numext::isnan)(a) && (numext::isnan)(e));
|
||||
all_pass &= success;
|
||||
if (!success) {
|
||||
std::cout << name << "(" << x(i,j) << "," << y(i,j) << ") = " << a << " != " << e << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
VERIFY(all_pass);
|
||||
}
|
||||
|
||||
template <typename Scalar>
|
||||
void binary_ops_test() {
|
||||
binary_op_test<Scalar>("pow",
|
||||
[](auto x, auto y) { return Eigen::pow(x, y); },
|
||||
[](auto x, auto y) { return std::pow(x, y); });
|
||||
binary_op_test<Scalar>("atan2",
|
||||
[](auto x, auto y) { return Eigen::atan2(x, y); },
|
||||
[](auto x, auto y) { return std::atan2(x, y); });
|
||||
}
|
||||
|
||||
template <typename Scalar>
|
||||
void pow_scalar_exponent_test() {
|
||||
using Int_t = typename internal::make_integer<Scalar>::type;
|
||||
const Scalar tol = test_precision<Scalar>();
|
||||
|
||||
std::vector<Scalar> abs_vals = special_values<Scalar>();
|
||||
const Index num_vals = (Index)abs_vals.size();
|
||||
Map<Array<Scalar, Dynamic, 1>> bases(abs_vals.data(), num_vals);
|
||||
|
||||
bool all_pass = true;
|
||||
for (Scalar abs_exponent : abs_vals) {
|
||||
for (Scalar exponent : {-abs_exponent, abs_exponent}) {
|
||||
// test integer exponent code path
|
||||
bool exponent_is_integer = (numext::isfinite)(exponent) && (numext::round(exponent) == exponent) &&
|
||||
(numext::abs(exponent) < static_cast<Scalar>(NumTraits<Int_t>::highest()));
|
||||
if (exponent_is_integer) {
|
||||
Int_t exponent_as_int = static_cast<Int_t>(exponent);
|
||||
Array<Scalar, Dynamic, 1> eigenPow = bases.pow(exponent_as_int);
|
||||
for (Index j = 0; j < num_vals; j++) {
|
||||
Scalar e = static_cast<Scalar>(std::pow(bases(j), exponent));
|
||||
Scalar a = eigenPow(j);
|
||||
bool success = (a == e) || ((numext::isfinite)(e) && internal::isApprox(a, e, tol)) ||
|
||||
((numext::isnan)(a) && (numext::isnan)(e));
|
||||
all_pass &= success;
|
||||
if (!success) {
|
||||
std::cout << "pow(" << bases(j) << "," << exponent << ") = " << a << " != " << e << std::endl;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// test floating point exponent code path
|
||||
Array<Scalar, Dynamic, 1> eigenPow = bases.pow(exponent);
|
||||
for (Index j = 0; j < num_vals; j++) {
|
||||
Scalar e = static_cast<Scalar>(std::pow(bases(j), exponent));
|
||||
Scalar a = eigenPow(j);
|
||||
bool success = (a == e) || ((numext::isfinite)(e) && internal::isApprox(a, e, tol)) ||
|
||||
((numext::isnan)(a) && (numext::isnan)(e));
|
||||
all_pass &= success;
|
||||
if (!success) {
|
||||
std::cout << "pow(" << bases(j) << "," << exponent << ") = " << a << " != " << e << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
VERIFY(all_pass);
|
||||
}
|
||||
|
||||
template <typename Scalar, typename ScalarExponent>
|
||||
Scalar calc_overflow_threshold(const ScalarExponent exponent) {
|
||||
EIGEN_USING_STD(exp2);
|
||||
EIGEN_USING_STD(log2);
|
||||
EIGEN_STATIC_ASSERT((NumTraits<Scalar>::digits() < 2 * NumTraits<double>::digits()), BASE_TYPE_IS_TOO_BIG);
|
||||
|
||||
if (exponent < 2)
|
||||
return NumTraits<Scalar>::highest();
|
||||
else {
|
||||
// base^e <= highest ==> base <= 2^(log2(highest)/e)
|
||||
// For floating-point types, consider the bound for integer values that can be reproduced exactly = 2 ^ digits
|
||||
double highest_bits = numext::mini(static_cast<double>(NumTraits<Scalar>::digits()),
|
||||
static_cast<double>(log2(NumTraits<Scalar>::highest())));
|
||||
return static_cast<Scalar>(
|
||||
numext::floor(exp2(highest_bits / static_cast<double>(exponent))));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Base, typename Exponent, bool ExpIsInteger = NumTraits<Exponent>::IsInteger>
|
||||
struct ref_pow {
|
||||
static Base run(Base base, Exponent exponent) {
|
||||
EIGEN_USING_STD(pow);
|
||||
return pow(base, static_cast<Base>(exponent));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Base, typename Exponent>
|
||||
struct ref_pow<Base, Exponent, true> {
|
||||
static Base run(Base base, Exponent exponent) {
|
||||
EIGEN_USING_STD(pow);
|
||||
return pow(base, exponent);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Base, typename Exponent>
|
||||
void test_exponent(Exponent exponent) {
|
||||
const Base max_abs_bases = static_cast<Base>(10000);
|
||||
// avoid integer overflow in Base type
|
||||
Base threshold = calc_overflow_threshold<Base, Exponent>(numext::abs(exponent));
|
||||
// avoid numbers that can't be verified with std::pow
|
||||
double double_threshold = calc_overflow_threshold<double, Exponent>(numext::abs(exponent));
|
||||
// use the lesser of these two thresholds
|
||||
Base testing_threshold =
|
||||
static_cast<double>(threshold) < double_threshold ? threshold : static_cast<Base>(double_threshold);
|
||||
// test both vectorized and non-vectorized code paths
|
||||
const Index array_size = 2 * internal::packet_traits<Base>::size + 1;
|
||||
|
||||
Base max_base = numext::mini(testing_threshold, max_abs_bases);
|
||||
Base min_base = NumTraits<Base>::IsSigned ? -max_base : Base(0);
|
||||
|
||||
ArrayX<Base> x(array_size), y(array_size);
|
||||
bool all_pass = true;
|
||||
for (Base base = min_base; base <= max_base; base++) {
|
||||
if (exponent < 0 && base == 0) continue;
|
||||
x.setConstant(base);
|
||||
y = x.pow(exponent);
|
||||
for (Base a : y) {
|
||||
Base e = ref_pow<Base, Exponent>::run(base, exponent);
|
||||
bool pass = (a == e);
|
||||
if (!NumTraits<Base>::IsInteger) {
|
||||
pass = pass || (((numext::isfinite)(e) && internal::isApprox(a, e)) ||
|
||||
((numext::isnan)(a) && (numext::isnan)(e)));
|
||||
}
|
||||
all_pass &= pass;
|
||||
if (!pass) {
|
||||
std::cout << "pow(" << base << "," << exponent << ") = " << a << " != " << e << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
VERIFY(all_pass);
|
||||
}
|
||||
|
||||
template <typename Base, typename Exponent>
|
||||
void unary_pow_test() {
|
||||
Exponent max_exponent = static_cast<Exponent>(NumTraits<Base>::digits());
|
||||
Exponent min_exponent = static_cast<Exponent>(NumTraits<Exponent>::IsSigned ? -max_exponent : 0);
|
||||
|
||||
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
|
||||
// to a wider base type.
|
||||
unary_pow_test<double, int>();
|
||||
unary_pow_test<double, float>();
|
||||
unary_pow_test<float, half>();
|
||||
unary_pow_test<double, half>();
|
||||
unary_pow_test<float, bfloat16>();
|
||||
unary_pow_test<double, bfloat16>();
|
||||
|
||||
// Although in the following cases the exponent cannot be represented exactly
|
||||
// in the base type, we do not perform a conversion, but implement
|
||||
// the operation using repeated squaring.
|
||||
unary_pow_test<float, int>();
|
||||
unary_pow_test<double, long long>();
|
||||
|
||||
// The following cases will test promoting a wider exponent type
|
||||
// to a narrower base type. This should compile but generate a
|
||||
// deprecation warning:
|
||||
unary_pow_test<float, double>();
|
||||
}
|
||||
|
||||
void int_pow_test() {
|
||||
unary_pow_test<int, int>();
|
||||
unary_pow_test<unsigned int, unsigned int>();
|
||||
unary_pow_test<long long, long long>();
|
||||
unary_pow_test<unsigned long long, unsigned long long>();
|
||||
|
||||
// Although in the following cases the exponent cannot be represented exactly
|
||||
// in the base type, we do not perform a conversion, but implement the
|
||||
// operation using repeated squaring.
|
||||
unary_pow_test<long long, int>();
|
||||
unary_pow_test<int, unsigned int>();
|
||||
unary_pow_test<unsigned int, int>();
|
||||
unary_pow_test<long long, unsigned long long>();
|
||||
unary_pow_test<unsigned long long, long long>();
|
||||
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 Scalar>
|
||||
void signbit_test() {
|
||||
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 = numext::signbit(x(i));
|
||||
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;
|
||||
@@ -92,8 +337,20 @@ template<typename ArrayType> void array(const ArrayType& m)
|
||||
Index rows = m.rows();
|
||||
Index cols = m.cols();
|
||||
|
||||
ArrayType m1 = ArrayType::Random(rows, cols),
|
||||
m2 = ArrayType::Random(rows, cols),
|
||||
ArrayType m1 = ArrayType::Random(rows, cols);
|
||||
if (NumTraits<RealScalar>::IsInteger && NumTraits<RealScalar>::IsSigned
|
||||
&& !NumTraits<Scalar>::IsComplex) {
|
||||
// Here we cap the size of the values in m1 such that pow(3)/cube()
|
||||
// doesn't overflow and result in undefined behavior. Notice that because
|
||||
// pow(int, int) promotes its inputs and output to double (according to
|
||||
// the C++ standard), we have to make sure that the result fits in 53 bits
|
||||
// for int64,
|
||||
RealScalar max_val =
|
||||
numext::mini(RealScalar(std::cbrt(NumTraits<RealScalar>::highest())),
|
||||
RealScalar(std::cbrt(1LL << 53)))/2;
|
||||
m1.array() = (m1.abs().array() <= max_val).select(m1, Scalar(max_val));
|
||||
}
|
||||
ArrayType m2 = ArrayType::Random(rows, cols),
|
||||
m3(rows, cols);
|
||||
ArrayType m4 = m1; // copy constructor
|
||||
VERIFY_IS_APPROX(m1, m4);
|
||||
@@ -119,23 +376,23 @@ template<typename ArrayType> void array(const ArrayType& m)
|
||||
VERIFY_IS_APPROX(m3, m1 - s1);
|
||||
|
||||
// scalar operators via Maps
|
||||
m3 = m1;
|
||||
ArrayType::Map(m1.data(), m1.rows(), m1.cols()) -= ArrayType::Map(m2.data(), m2.rows(), m2.cols());
|
||||
VERIFY_IS_APPROX(m1, m3 - m2);
|
||||
m3 = m1; m4 = m1;
|
||||
ArrayType::Map(m4.data(), m4.rows(), m4.cols()) -= ArrayType::Map(m2.data(), m2.rows(), m2.cols());
|
||||
VERIFY_IS_APPROX(m4, m3 - m2);
|
||||
|
||||
m3 = m1;
|
||||
ArrayType::Map(m1.data(), m1.rows(), m1.cols()) += ArrayType::Map(m2.data(), m2.rows(), m2.cols());
|
||||
VERIFY_IS_APPROX(m1, m3 + m2);
|
||||
m3 = m1; m4 = m1;
|
||||
ArrayType::Map(m4.data(), m4.rows(), m4.cols()) += ArrayType::Map(m2.data(), m2.rows(), m2.cols());
|
||||
VERIFY_IS_APPROX(m4, m3 + m2);
|
||||
|
||||
m3 = m1;
|
||||
ArrayType::Map(m1.data(), m1.rows(), m1.cols()) *= ArrayType::Map(m2.data(), m2.rows(), m2.cols());
|
||||
VERIFY_IS_APPROX(m1, m3 * m2);
|
||||
m3 = m1; m4 = m1;
|
||||
ArrayType::Map(m4.data(), m4.rows(), m4.cols()) *= ArrayType::Map(m2.data(), m2.rows(), m2.cols());
|
||||
VERIFY_IS_APPROX(m4, m3 * m2);
|
||||
|
||||
m3 = m1;
|
||||
m3 = m1; m4 = m1;
|
||||
m2 = ArrayType::Random(rows,cols);
|
||||
m2 = (m2==0).select(1,m2);
|
||||
ArrayType::Map(m1.data(), m1.rows(), m1.cols()) /= ArrayType::Map(m2.data(), m2.rows(), m2.cols());
|
||||
VERIFY_IS_APPROX(m1, m3 / m2);
|
||||
ArrayType::Map(m4.data(), m4.rows(), m4.cols()) /= ArrayType::Map(m2.data(), m2.rows(), m2.cols());
|
||||
VERIFY_IS_APPROX(m4, m3 / m2);
|
||||
|
||||
// reductions
|
||||
VERIFY_IS_APPROX(m1.abs().colwise().sum().sum(), m1.abs().sum());
|
||||
@@ -176,7 +433,6 @@ template<typename ArrayType> void array(const ArrayType& m)
|
||||
FixedArrayType f4(f1.data());
|
||||
VERIFY_IS_APPROX(f4, f1);
|
||||
}
|
||||
#if EIGEN_HAS_CXX11
|
||||
{
|
||||
FixedArrayType f1{s1};
|
||||
VERIFY_IS_APPROX(f1, FixedArrayType::Constant(s1));
|
||||
@@ -188,7 +444,6 @@ template<typename ArrayType> void array(const ArrayType& m)
|
||||
FixedArrayType f4{f1.data()};
|
||||
VERIFY_IS_APPROX(f4, f1);
|
||||
}
|
||||
#endif
|
||||
|
||||
// pow
|
||||
VERIFY_IS_APPROX(m1.pow(2), m1.square());
|
||||
@@ -214,14 +469,12 @@ template<typename ArrayType> void array(const ArrayType& m)
|
||||
OneDArrayType o2(static_cast<int>(rows));
|
||||
VERIFY(o2.size()==rows);
|
||||
}
|
||||
#if EIGEN_HAS_CXX11
|
||||
{
|
||||
OneDArrayType o1{rows};
|
||||
VERIFY(o1.size()==rows);
|
||||
OneDArrayType o4{int(rows)};
|
||||
VERIFY(o4.size()==rows);
|
||||
}
|
||||
#endif
|
||||
// Check possible conflicts with 2D ctor
|
||||
typedef Array<Scalar, Dynamic, Dynamic> TwoDArrayType;
|
||||
typedef Array<Scalar, 2, 1> ArrayType2;
|
||||
@@ -238,7 +491,6 @@ template<typename ArrayType> void array(const ArrayType& m)
|
||||
ArrayType2 o4(static_cast<int>(rows),static_cast<int>(cols));
|
||||
VERIFY(o4(0)==Scalar(rows) && o4(1)==Scalar(cols));
|
||||
}
|
||||
#if EIGEN_HAS_CXX11
|
||||
{
|
||||
TwoDArrayType o1{rows,cols};
|
||||
VERIFY(o1.rows()==rows);
|
||||
@@ -252,7 +504,6 @@ template<typename ArrayType> void array(const ArrayType& m)
|
||||
ArrayType2 o4{int(rows),int(cols)};
|
||||
VERIFY(o4(0)==Scalar(rows) && o4(1)==Scalar(cols));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename ArrayType> void comparisons(const ArrayType& m)
|
||||
@@ -360,11 +611,11 @@ template<typename ArrayType> void array_real(const ArrayType& m)
|
||||
VERIFY_IS_APPROX(m1.sinh(), sinh(m1));
|
||||
VERIFY_IS_APPROX(m1.cosh(), cosh(m1));
|
||||
VERIFY_IS_APPROX(m1.tanh(), tanh(m1));
|
||||
#if EIGEN_HAS_CXX11_MATH
|
||||
VERIFY_IS_APPROX(m1.atan2(m2), atan2(m1,m2));
|
||||
|
||||
VERIFY_IS_APPROX(m1.tanh().atanh(), atanh(tanh(m1)));
|
||||
VERIFY_IS_APPROX(m1.sinh().asinh(), asinh(sinh(m1)));
|
||||
VERIFY_IS_APPROX(m1.cosh().acosh(), acosh(cosh(m1)));
|
||||
#endif
|
||||
VERIFY_IS_APPROX(m1.logistic(), logistic(m1));
|
||||
|
||||
VERIFY_IS_APPROX(m1.arg(), arg(m1));
|
||||
@@ -421,6 +672,13 @@ template<typename ArrayType> void array_real(const ArrayType& m)
|
||||
VERIFY_IS_APPROX( m1.sign(), -(-m1).sign() );
|
||||
VERIFY_IS_APPROX( m1*m1.sign(),m1.abs());
|
||||
VERIFY_IS_APPROX(m1.sign() * m1.abs(), m1);
|
||||
|
||||
ArrayType tmp = m1.atan2(m2);
|
||||
for (Index i = 0; i < tmp.size(); ++i) {
|
||||
Scalar actual = tmp.array()(i);
|
||||
Scalar expected = atan2(m1.array()(i), m2.array()(i));
|
||||
VERIFY_IS_APPROX(actual, expected);
|
||||
}
|
||||
|
||||
VERIFY_IS_APPROX(numext::abs2(numext::real(m1)) + numext::abs2(numext::imag(m1)), numext::abs2(m1));
|
||||
VERIFY_IS_APPROX(numext::abs2(Eigen::real(m1)) + numext::abs2(Eigen::imag(m1)), numext::abs2(m1));
|
||||
@@ -448,7 +706,10 @@ template<typename ArrayType> void array_real(const ArrayType& m)
|
||||
// Avoid inf and NaN.
|
||||
m3 = (m1.square()<NumTraits<Scalar>::epsilon()).select(Scalar(1),m3);
|
||||
VERIFY_IS_APPROX(m3.pow(RealScalar(-2)), m3.square().inverse());
|
||||
pow_test<Scalar>();
|
||||
|
||||
// Test pow and atan2 on special IEEE values.
|
||||
binary_ops_test<Scalar>();
|
||||
pow_scalar_exponent_test<Scalar>();
|
||||
|
||||
VERIFY_IS_APPROX(log10(m3), log(m3)/numext::log(Scalar(10)));
|
||||
VERIFY_IS_APPROX(log2(m3), log(m3)/numext::log(Scalar(2)));
|
||||
@@ -457,7 +718,7 @@ template<typename ArrayType> void array_real(const ArrayType& m)
|
||||
const RealScalar tiny = sqrt(std::numeric_limits<RealScalar>::epsilon());
|
||||
s1 += Scalar(tiny);
|
||||
m1 += ArrayType::Constant(rows,cols,Scalar(tiny));
|
||||
VERIFY_IS_APPROX(s1/m1, s1 * m1.inverse());
|
||||
VERIFY_IS_CWISE_APPROX(s1/m1, s1 * m1.inverse());
|
||||
|
||||
// check inplace transpose
|
||||
m3 = m1;
|
||||
@@ -467,6 +728,7 @@ template<typename ArrayType> void array_real(const ArrayType& m)
|
||||
VERIFY_IS_APPROX(m3, m1);
|
||||
}
|
||||
|
||||
|
||||
template<typename ArrayType> void array_complex(const ArrayType& m)
|
||||
{
|
||||
typedef typename ArrayType::Scalar Scalar;
|
||||
@@ -512,7 +774,6 @@ template<typename ArrayType> void array_complex(const ArrayType& m)
|
||||
VERIFY_IS_APPROX(cos(m1+RealScalar(3)*m2), cos((m1+RealScalar(3)*m2).eval()));
|
||||
VERIFY_IS_APPROX(m1.sign(), sign(m1));
|
||||
|
||||
|
||||
VERIFY_IS_APPROX(m1.exp() * m2.exp(), exp(m1+m2));
|
||||
VERIFY_IS_APPROX(m1.exp(), exp(m1));
|
||||
VERIFY_IS_APPROX(m1.exp() / m2.exp(),(m1-m2).exp());
|
||||
@@ -661,6 +922,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++) {
|
||||
@@ -673,6 +963,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>()) );
|
||||
@@ -700,6 +993,12 @@ EIGEN_DECLARE_TEST(array_cwise)
|
||||
CALL_SUBTEST_4( array_complex(ArrayXXcf(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_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));
|
||||
VERIFY((internal::is_same< internal::global_math_functions_filtering_base<float>::type, float >::value));
|
||||
VERIFY((internal::is_same< internal::global_math_functions_filtering_base<Array2i>::type, ArrayBase<Array2i> >::value));
|
||||
|
||||
Reference in New Issue
Block a user