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());