mirror of
https://gitlab.com/libeigen/eigen.git
synced 2026-04-10 11:34:33 +08:00
Fix three flaky tests: packetmath, array_cwise, polynomialsolver
libeigen/eigen!2267 Co-authored-by: Rasmus Munk Larsen <rmlarsen@gmail.com>
This commit is contained in:
@@ -1006,21 +1006,10 @@ void array_complex(const ArrayType& m) {
|
|||||||
|
|
||||||
std::complex<RealScalar> zero(0.0, 0.0);
|
std::complex<RealScalar> zero(0.0, 0.0);
|
||||||
VERIFY((Eigen::isnan)(m1 * zero / zero).all());
|
VERIFY((Eigen::isnan)(m1 * zero / zero).all());
|
||||||
#if EIGEN_COMP_MSVC
|
// Complex division by zero may produce inf or NaN depending on the std::complex
|
||||||
// msvc complex division is not robust
|
// implementation (algebraic formula gives 0/0=NaN for some components). Only require
|
||||||
VERIFY((Eigen::isinf)(m4 / RealScalar(0)).all());
|
// the result to be non-finite.
|
||||||
#else
|
VERIFY((!(Eigen::isfinite)(m4 / zero)).all());
|
||||||
#if EIGEN_COMP_CLANG
|
|
||||||
// clang's complex division is notoriously broken too
|
|
||||||
if ((numext::isinf)(m4(0, 0) / RealScalar(0))) {
|
|
||||||
#endif
|
|
||||||
VERIFY((Eigen::isinf)(m4 / zero).all());
|
|
||||||
#if EIGEN_COMP_CLANG
|
|
||||||
} else {
|
|
||||||
VERIFY((Eigen::isinf)(m4.real() / zero.real()).all());
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif // MSVC
|
|
||||||
|
|
||||||
VERIFY(((Eigen::isfinite)(m1) && (!(Eigen::isfinite)(m1 * zero / zero)) && (!(Eigen::isfinite)(m1 / zero))).all());
|
VERIFY(((Eigen::isfinite)(m1) && (!(Eigen::isfinite)(m1 * zero / zero)) && (!(Eigen::isfinite)(m1 / zero))).all());
|
||||||
|
|
||||||
|
|||||||
@@ -1221,7 +1221,17 @@ std::enable_if_t<Cond, void> run_ieee_cases(const FunctorT& fun) {
|
|||||||
const Scalar norm_max = (std::numeric_limits<Scalar>::max)();
|
const Scalar norm_max = (std::numeric_limits<Scalar>::max)();
|
||||||
const Scalar inf = (std::numeric_limits<Scalar>::infinity)();
|
const Scalar inf = (std::numeric_limits<Scalar>::infinity)();
|
||||||
const Scalar nan = (std::numeric_limits<Scalar>::quiet_NaN)();
|
const Scalar nan = (std::numeric_limits<Scalar>::quiet_NaN)();
|
||||||
std::vector<Scalar> values{norm_min, Scalar(0), Scalar(1), norm_max, inf, nan};
|
std::vector<Scalar> values{Scalar(0), Scalar(1), norm_max, inf, nan};
|
||||||
|
// On ARM, NEON flush-to-zero mode can flush intermediate subnormal results to zero,
|
||||||
|
// causing functions like sin(norm_min) to return 0 instead of norm_min. Skip norm_min
|
||||||
|
// in that case, along with truly subnormal values.
|
||||||
|
if (!SkipDenorms) {
|
||||||
|
values.push_back(norm_min);
|
||||||
|
if (std::numeric_limits<Scalar>::has_denorm == std::denorm_present) {
|
||||||
|
values.push_back(std::numeric_limits<Scalar>::denorm_min());
|
||||||
|
values.push_back(norm_min / Scalar(2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
constexpr int size = PacketSize * 2;
|
constexpr int size = PacketSize * 2;
|
||||||
EIGEN_ALIGN_MAX Scalar data1[size];
|
EIGEN_ALIGN_MAX Scalar data1[size];
|
||||||
@@ -1231,11 +1241,6 @@ std::enable_if_t<Cond, void> run_ieee_cases(const FunctorT& fun) {
|
|||||||
data1[i] = data2[i] = ref[i] = Scalar(0);
|
data1[i] = data2[i] = ref[i] = Scalar(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Cond && !SkipDenorms && std::numeric_limits<Scalar>::has_denorm == std::denorm_present) {
|
|
||||||
values.push_back(std::numeric_limits<Scalar>::denorm_min());
|
|
||||||
values.push_back(norm_min / Scalar(2));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Scalar abs_value : values) {
|
for (Scalar abs_value : values) {
|
||||||
data1[0] = abs_value;
|
data1[0] = abs_value;
|
||||||
data1[1] = -data1[0];
|
data1[1] = -data1[0];
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ void evalSolverSugarFunction(const POLYNOMIAL& pols, const ROOTS& roots, const R
|
|||||||
|
|
||||||
for (size_t i = 0; i < calc_realRoots.size(); ++i) {
|
for (size_t i = 0; i < calc_realRoots.size(); ++i) {
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (size_t j = 0; j < calc_realRoots.size() && !found; ++j) {
|
for (size_t j = 0; j < real_roots.size() && !found; ++j) {
|
||||||
if (internal::isApprox(calc_realRoots[i], real_roots[j], psPrec)) {
|
if (internal::isApprox(calc_realRoots[i], real_roots[j], psPrec)) {
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
@@ -178,13 +178,19 @@ void polynomialsolver(int deg) {
|
|||||||
roots_to_monicPolynomial(allRoots, pols);
|
roots_to_monicPolynomial(allRoots, pols);
|
||||||
evalSolver<Deg_, PolynomialType>(pols);
|
evalSolver<Deg_, PolynomialType>(pols);
|
||||||
|
|
||||||
cout << "Test sugar" << endl;
|
// The companion matrix eigenvalue approach has limited accuracy for float at
|
||||||
RealRootsType realRoots = RealRootsType::Random(deg);
|
// high degrees. The PolynomialSolver documentation itself warns: "With 32bit
|
||||||
// sort by ascending absolute value to mitigate precision lost during polynomial expansion
|
// (float) floating types this problem shows up frequently." Skip the sugar
|
||||||
std::sort(realRoots.begin(), realRoots.end(),
|
// function test (which requires exact root matching) for float beyond degree 8.
|
||||||
[](RealScalar a, RealScalar b) { return numext::abs(a) < numext::abs(b); });
|
if (deg <= 8 || sizeof(RealScalar) > sizeof(float)) {
|
||||||
roots_to_monicPolynomial(realRoots, pols);
|
cout << "Test sugar" << endl;
|
||||||
evalSolverSugarFunction<Deg_>(pols, realRoots.template cast<std::complex<RealScalar> >().eval(), realRoots);
|
RealRootsType realRoots = RealRootsType::Random(deg);
|
||||||
|
// sort by ascending absolute value to mitigate precision lost during polynomial expansion
|
||||||
|
std::sort(realRoots.begin(), realRoots.end(),
|
||||||
|
[](RealScalar a, RealScalar b) { return numext::abs(a) < numext::abs(b); });
|
||||||
|
roots_to_monicPolynomial(realRoots, pols);
|
||||||
|
evalSolverSugarFunction<Deg_>(pols, realRoots.template cast<std::complex<RealScalar> >().eval(), realRoots);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EIGEN_DECLARE_TEST(polynomialsolver) {
|
EIGEN_DECLARE_TEST(polynomialsolver) {
|
||||||
|
|||||||
Reference in New Issue
Block a user