blob: 5e1d96b5783dc5dbb028178ec272f4eac0a10484 [file] [edit]
// SPDX-FileCopyrightText: The Eigen Authors
// SPDX-License-Identifier: MPL-2.0
#include "packetmath_test_shared.h"
#include <Eigen/Geometry>
#include <Eigen/SparseCore>
template <typename Real>
void comparison_helpers() {
const Real inf = NumTraits<Real>::infinity();
const Real nan = NumTraits<Real>::quiet_NaN();
VERIFY(test_isCwiseApprox(inf, inf, true));
VERIFY(!test_isCwiseApprox(inf, -inf, false));
VERIFY(!test_isApprox(inf, -inf));
VERIFY(test_isApprox(inf, inf));
VERIFY(test_isApprox(nan, nan));
VERIFY(!test_isMuchSmallerThan(inf, inf));
VERIFY(!test_isMuchSmallerThan(nan, nan));
VERIFY(!test_isApproxOrLessThan(inf, -inf));
VERIFY(!test_isApproxOrLessThan(nan, nan));
VERIFY(test_isApproxOrLessThan(inf, inf));
VERIFY(test_isCwiseApprox(nan, nan, true));
VERIFY(!test_isCwiseApprox(nan, Real(0), false));
VERIFY(!test_isCwiseApprox(inf, NumTraits<Real>::highest(), false));
VERIFY(test_isCwiseApprox(Real(0), Real(-0.0), true));
VERIFY(!test_isCwiseApprox(Real(1), Real(2), false));
const Real eps = NumTraits<Real>::epsilon();
const Real near = Real(1) + Real(8) * eps;
VERIFY(test_isCwiseApprox(Real(1), near, false, Real(8) * eps));
VERIFY(!test_isCwiseApprox(Real(1), near, false, Real(7) * eps));
VERIFY(test_isCwiseApprox(Real(1), Real(1) + test_precision<Real>() / Real(2), false));
using Complex = std::complex<Real>;
VERIFY(test_isApprox(Complex(1), Real(1)));
VERIFY(test_isApprox(Real(1), Complex(1)));
VERIFY(test_isMuchSmallerThan(Complex(0), Real(1)));
VERIFY(test_isMuchSmallerThan(Real(0), Complex(1)));
using ArrayType = Array<Complex, 2, 2>;
ArrayType x, y;
x << Complex(inf), Complex(nan), Complex(1), Complex(0);
y = x;
VERIFY(test_isCwiseApprox(x, y, true));
VERIFY(test_isCwiseApprox(x, y, false));
y(1, 0) = Complex(1, test_precision<Real>() / Real(2));
VERIFY(test_isCwiseApprox(x, y, false));
VERIFY(!test_isCwiseApprox(x, y, true));
y(0, 0) = Complex(-inf);
VERIFY(!test_isCwiseApprox(x, y, false));
VERIFY(!test_isCwiseApprox(x, y.row(0), false));
VERIFY(!test_isApprox(Complex(inf), Complex(inf)));
VERIFY(!test_isApprox(Complex(nan), Complex(nan)));
for (Real scale :
{Real(1), NumTraits<Real>::highest() / Real(32), (numext::numeric_limits<Real>::min)() * Real(32)}) {
x.setConstant(Complex(scale));
y = Real(2) * x;
VERIFY(!test_isCwiseApprox(x, y, false));
VERIFY(!test_isApprox(Complex(scale), Complex(Real(2) * scale)));
VERIFY(!test_isMuchSmallerThan(Complex(scale), Complex(Real(2) * scale)));
VERIFY(test_isMuchSmallerThan(x * Real(0), y));
VERIFY(test_isMuchSmallerThan(x * Real(0), scale));
VERIFY_IS_EQUAL(test_relative_error(x, y), Real(1));
VERIFY_IS_EQUAL(test_relative_error(x.real(), y), Real(1));
VERIFY_IS_EQUAL(test_relative_error(scale, Real(2) * scale), Real(1));
}
x.setZero();
y.setZero();
VERIFY_IS_EQUAL(test_relative_error(x, y), Real(0));
VERIFY_IS_EQUAL(test_relative_error(Real(0), Real(0)), Real(0));
y.setOnes();
VERIFY((numext::isinf)(test_relative_error(x, y)));
const SparseMatrix<Complex> sx = x.matrix().sparseView();
const SparseMatrix<Complex> sy = y.matrix().sparseView();
VERIFY(test_isCwiseApprox(sx, sx, true));
VERIFY(!test_isCwiseApprox(sx, sy, false));
using Vector = Matrix<Real, 2, 1>;
ParametrizedLine<Real, 2> a(Vector::Ones(), Vector::UnitX());
ParametrizedLine<Real, 2> b(Vector::Ones(), -Vector::UnitX());
VERIFY_IS_EQUAL(test_relative_error(a, b), Real(2));
}
void integer_diagnostics() {
const int low = NumTraits<int>::lowest();
const int high = NumTraits<int>::highest();
VERIFY(test_relative_error(low, high) >= 2.0);
VERIFY(test_relative_error(Matrix2i::Constant(low), Matrix2i::Constant(high)) >= 2.0);
VERIFY_IS_EQUAL(test_relative_error(false, false), 0.0f);
VERIFY((numext::isinf)(test_relative_error(false, true)));
VERIFY(test_isCwiseApprox(false, false, true));
VERIFY(!test_isCwiseApprox(false, true, false));
VERIFY_IS_EQUAL(test_relative_error(half(1), 2.0f), half(1));
VERIFY_IS_EQUAL(test_relative_error(bfloat16(1), 2.0f), bfloat16(1));
}
template <typename Real>
void scaled_comparison_helpers() {
using MatrixType = Matrix<Real, 2, 2>;
const MatrixType zero = MatrixType::Zero();
for (Index i = 0; i < zero.size(); ++i) {
MatrixType value = zero;
value(i) = NumTraits<Real>::quiet_NaN();
VERIFY(!verifyIsApproxScaled(value, zero, Real(1)));
VERIFY(!verifyIsApproxScaled(value.array(), zero.array(), Real(1)));
}
VERIFY(!verifyIsApproxScaled(zero, zero, NumTraits<Real>::infinity()));
VERIFY(!verifyIsApproxScaled(zero, zero, NumTraits<Real>::quiet_NaN()));
const Matrix<Real, Dynamic, Dynamic> empty(0, 3);
VERIFY(verifyIsApproxScaled(empty, empty, Real(1)));
}
void packet_comparison_helpers() {
const double inf = NumTraits<double>::infinity();
const double opposite = -inf;
const double one = 1, near = 1 + 1e-8;
VERIFY(test::areApprox(&inf, &inf, 1));
VERIFY(!test::areApprox(&inf, &opposite, 1));
VERIFY(!test::areApprox(&inf, &opposite, 1, NumTraits<double>::epsilon()));
// Packet checks retain dummy_precision(), which is tighter than the legacy test_precision().
VERIFY(!test::areApprox(&one, &near, 1));
}
EIGEN_DECLARE_TEST(numerical_test_helpers) {
comparison_helpers<float>();
comparison_helpers<double>();
comparison_helpers<long double>();
integer_diagnostics();
scaled_comparison_helpers<float>();
scaled_comparison_helpers<double>();
packet_comparison_helpers();
}