From 2d97b43e63cdb77054abc7df1846fc780679932e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 6 Dec 2018 14:47:24 +0100 Subject: [PATCH] [poincare] Fix Power::compute precision on real numbers Fix bug: if we define f(x) = x^3-x-6, f(2) was not equal to 0 in the values table --- poincare/src/power.cpp | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 7e9e88860..e6e46dec3 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -82,14 +82,19 @@ int PowerNode::getPolynomialCoefficients(Context & context, const char * symbolN template Complex PowerNode::compute(const std::complex c, const std::complex d) { - std::complex result = std::pow(c, d); + std::complex result; if (c.imag() == 0.0 && d.imag() == 0.0 && c.real() >= 0.0) { /* pow: (R+, R) -> R+ - * However, std::pow(2.0, 1000) = (INFINITY, NAN). Openbsd pow of a - * positive real and another real has a undefined imaginary when the real - * result is infinity. To avoid this, we force the imaginary part of - * pow(R+,R) to 0.0. */ - result.imag(0.0); + * For pow on (R+,R) we rather use std::pow(double, double) because: + * - pow on complexes is not as precise as pow on double: for instance, + * pow(complex(2.0,0.0), complex(3.0,0.0) = complex(7.9999999999999982,0.0) + * and pow(2.0,3.0) = 8.0 + * - Using complex pow, std::pow(2.0, 1000) = (INFINITY, NAN). + * Openbsd pow of a positive real and another real has a undefined + * imaginary when the real result is infinity. */ + result = std::complex(std::pow(c.real(), d.real())); + } else { + result = std::pow(c, d); } /* Openbsd trigonometric functions are numerical implementation and thus are * approximative.