mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-18 21:30:38 +01:00
[poincare] Power: approximation of power of positive real and real is
real. Fix 10^1000 = inf instead of undef
This commit is contained in:
@@ -150,6 +150,7 @@ tests += $(addprefix poincare/test/,\
|
|||||||
function.cpp\
|
function.cpp\
|
||||||
helper.cpp\
|
helper.cpp\
|
||||||
helpers.cpp\
|
helpers.cpp\
|
||||||
|
infinity.cpp\
|
||||||
integer.cpp\
|
integer.cpp\
|
||||||
layouts.cpp\
|
layouts.cpp\
|
||||||
logarithm.cpp\
|
logarithm.cpp\
|
||||||
|
|||||||
@@ -81,13 +81,21 @@ int PowerNode::getPolynomialCoefficients(Context & context, const char * symbolN
|
|||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
Complex<T> PowerNode::compute(const std::complex<T> c, const std::complex<T> d) {
|
Complex<T> PowerNode::compute(const std::complex<T> c, const std::complex<T> d) {
|
||||||
|
std::complex<T> 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
|
/* Openbsd trigonometric functions are numerical implementation and thus are
|
||||||
* approximative.
|
* approximative.
|
||||||
* The error epsilon is ~1E-7 on float and ~1E-15 on double. In order to
|
* 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
|
* 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
|
* 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. */
|
* part and if arg ~ Pi/2 [Pi], we discard the residual real part. */
|
||||||
std::complex<T> result = std::pow(c, d);
|
|
||||||
return Complex<T>(ApproximationHelper::TruncateRealOrImaginaryPartAccordingToArgument(result));
|
return Complex<T>(ApproximationHelper::TruncateRealOrImaginaryPartAccordingToArgument(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
26
poincare/test/infinity.cpp
Normal file
26
poincare/test/infinity.cpp
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#include <quiz.h>
|
||||||
|
#include <ion.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include "helper.h"
|
||||||
|
#if POINCARE_TESTS_PRINT_EXPRESSIONS
|
||||||
|
#include "../src/expression_debug.h"
|
||||||
|
#include <iostream>
|
||||||
|
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<double>("1*10^1000", "inf");
|
||||||
|
}
|
||||||
@@ -11,14 +11,6 @@ using namespace std;
|
|||||||
using namespace Poincare;
|
using namespace Poincare;
|
||||||
|
|
||||||
QUIZ_CASE(poincare_simplify_mix) {
|
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
|
// Root at denominator
|
||||||
assert_parsed_expression_simplify_to("1/(R(2)+R(3))", "(-R(2))+R(3)");
|
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");
|
assert_parsed_expression_simplify_to("1/(5+R(3))", "(5-R(3))/22");
|
||||||
|
|||||||
Reference in New Issue
Block a user