From 6948de2ad3facc4df0dc8348fceeb0747c26b732 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 16 Jan 2019 12:13:20 +0100 Subject: [PATCH] [poincare] ComplexCartesian: fix approximation The assertions that the real and imaginary parts are real can be false due to double lack of precision. We escape these cases by returning an undefined approximation. --- poincare/src/complex_cartesian.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/poincare/src/complex_cartesian.cpp b/poincare/src/complex_cartesian.cpp index b8682a89e..fc2241a96 100644 --- a/poincare/src/complex_cartesian.cpp +++ b/poincare/src/complex_cartesian.cpp @@ -35,6 +35,18 @@ Complex ComplexCartesianNode::templatedApproximate(Context& context, Preferen assert(imagEvalution.type() == EvaluationNode::Type::Complex); std::complex a = static_cast &>(realEvaluation).stdComplex(); std::complex b = static_cast &>(imagEvalution).stdComplex(); + if ((a.imag() != 0.0 && !std::isnan(a.imag())) || (b.imag() != 0.0 && !std::isnan(b.imag()))) { + /* a and b are supposed to be real (if they are not undefined). However, + * due to double precision limit, the approximation of the real part or the + * imaginary part can lead to complex values. + * For instance, let the real part be + * sqrt(2*sqrt(5E23+1)-1E12*sqrt(2)) ~ 1.1892E-6. Due to std::sqrt(2.0) + * unprecision, 2*sqrt(5E23+1)-1E12*sqrt(2) < 0 which leads to + * sqrt(2*sqrt(5E23+1)-1E12*sqrt(2)) being a complex number. + * In this case, we return an undefined complex because the approximation + * is very likely to be false. */ + return Complex::Undefined(); + } assert(a.imag() == 0.0 || std::isnan(a.imag())); assert(b.imag() == 0.0 || std::isnan(b.imag())); return Complex(a.real(), b.real());