diff --git a/poincare/Makefile b/poincare/Makefile index 917fc03bf..532933cf4 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -150,6 +150,7 @@ tests += $(addprefix poincare/test/,\ function.cpp\ helper.cpp\ helpers.cpp\ + infinity.cpp\ integer.cpp\ layouts.cpp\ logarithm.cpp\ diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 9a46b7687..a57c0918e 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -81,13 +81,21 @@ 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); + 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); + } /* Openbsd trigonometric functions are numerical implementation and thus are * approximative. * The error epsilon is ~1E-7 on float and ~1E-15 on double. In order to * avoid weird results as e(i*pi) = -1+6E-17*i, we compute the argument of * the result of c^d and if arg ~ 0 [Pi], we discard the residual imaginary * part and if arg ~ Pi/2 [Pi], we discard the residual real part. */ - std::complex result = std::pow(c, d); return Complex(ApproximationHelper::TruncateRealOrImaginaryPartAccordingToArgument(result)); } diff --git a/poincare/test/infinity.cpp b/poincare/test/infinity.cpp new file mode 100644 index 000000000..1fe7e408b --- /dev/null +++ b/poincare/test/infinity.cpp @@ -0,0 +1,26 @@ +#include +#include +#include +#include "helper.h" +#if POINCARE_TESTS_PRINT_EXPRESSIONS +#include "../src/expression_debug.h" +#include +using namespace std; +#endif + +using namespace Poincare; + +QUIZ_CASE(poincare_infinity) { + + // 0 and infinity + assert_parsed_expression_simplify_to("0/0", Undefined::Name()); + assert_parsed_expression_simplify_to("0/inf", "0"); + assert_parsed_expression_simplify_to("inf/0", Undefined::Name()); + assert_parsed_expression_simplify_to("0*inf", Undefined::Name()); + assert_parsed_expression_simplify_to("3*inf/inf", "inf/inf"); //TODO undef would be better + assert_parsed_expression_simplify_to("1E1000", "inf"); + assert_parsed_expression_simplify_to("-1E1000", "-inf"); + assert_parsed_expression_simplify_to("-1E-1000", "0"); + assert_parsed_expression_simplify_to("1E-1000", "0"); + assert_parsed_expression_evaluates_to("1*10^1000", "inf"); +} diff --git a/poincare/test/simplify_mix.cpp b/poincare/test/simplify_mix.cpp index 50170460f..6ba6b14ff 100644 --- a/poincare/test/simplify_mix.cpp +++ b/poincare/test/simplify_mix.cpp @@ -11,14 +11,6 @@ using namespace std; using namespace Poincare; QUIZ_CASE(poincare_simplify_mix) { - - // 0 and infinity - assert_parsed_expression_simplify_to("0/0", Undefined::Name()); - assert_parsed_expression_simplify_to("0/inf", "0"); - assert_parsed_expression_simplify_to("inf/0", Undefined::Name()); - assert_parsed_expression_simplify_to("0*inf", Undefined::Name()); - assert_parsed_expression_simplify_to("3*inf/inf", "inf/inf"); //TODO undef would be better - // Root at denominator assert_parsed_expression_simplify_to("1/(R(2)+R(3))", "(-R(2))+R(3)"); assert_parsed_expression_simplify_to("1/(5+R(3))", "(5-R(3))/22");