mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-19 00:37:25 +01:00
[poincare/approximation_helper] Changed the way to approximate
To prevent incorrect approximations, such as cos(1.5707963267949) = 0, we lowered the precision value. This way, the approximation is more selective. However, when ploting functions such as e^(i.pi+x), the float approximation fails and therefore, the function appears "undef". As a result we created two functions Epsilon that behave differently according to the number's type. When it is a double, we want a maximal precision -> epsilon_double = 1x10^(-15), and when it is a float, we accept more agressive approximations -> epsilon_float = 10 x 1x10^(-7). Change-Id: I844ac52ade665f51fe6888db38f4485c193286d9
This commit is contained in:
committed by
Émilie Feral
parent
1f9d0b5810
commit
5569ba92a2
@@ -9,6 +9,7 @@
|
||||
namespace Poincare {
|
||||
|
||||
namespace ApproximationHelper {
|
||||
template <typename T> T Epsilon();
|
||||
template <typename T> int PositiveIntegerApproximationIfPossible(const ExpressionNode * expression, bool * isUndefined, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit);
|
||||
template <typename T> std::complex<T> NeglectRealOrImaginaryPartIfNeglectable(std::complex<T> result, std::complex<T> input1, std::complex<T> input2 = 1.0, bool enableNullResult = true);
|
||||
|
||||
|
||||
@@ -27,6 +27,23 @@ template < typename T> T minimalNonNullMagnitudeOfParts(std::complex<T> c) {
|
||||
|
||||
static inline int absInt(int x) { return x < 0 ? -x : x; }
|
||||
|
||||
/* To prevent incorrect approximations, such as cos(1.5707963267949) = 0
|
||||
* we made the neglect threshold stricter. This way, the approximation is more
|
||||
* selective.
|
||||
* However, when ploting functions such as e^(i.pi+x), the float approximation
|
||||
* fails by giving non-real results and therefore, the function appears "undef".
|
||||
* As a result we created two functions Epsilon that behave differently
|
||||
* according to the number's type. When it is a double we want maximal precision
|
||||
* -> precision_double = 1x10^(-15).
|
||||
* When it is a float, we accept more agressive approximations
|
||||
* -> precision_float = x10^(-6). */
|
||||
|
||||
template<typename T>
|
||||
T ApproximationHelper::Epsilon() {
|
||||
static T precision = (sizeof(T) == sizeof(double)) ? 1E-15 : 1E-6f;
|
||||
return precision;
|
||||
}
|
||||
|
||||
template <typename T> int ApproximationHelper::PositiveIntegerApproximationIfPossible(const ExpressionNode * expression, bool * isUndefined, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) {
|
||||
Evaluation<T> evaluation = expression->approximate(T(), context, complexFormat, angleUnit);
|
||||
T scalar = evaluation.toScalar();
|
||||
@@ -52,7 +69,7 @@ template <typename T> std::complex<T> ApproximationHelper::NeglectRealOrImaginar
|
||||
}
|
||||
T magnitude1 = minimalNonNullMagnitudeOfParts(input1);
|
||||
T magnitude2 = minimalNonNullMagnitudeOfParts(input2);
|
||||
T precision = ((T)10.0)*Expression::Epsilon<T>();
|
||||
T precision = Epsilon<T>();
|
||||
if (isNegligeable(result.imag(), precision, magnitude1, magnitude2)) {
|
||||
result.imag(0);
|
||||
}
|
||||
@@ -126,7 +143,8 @@ template<typename T> MatrixComplex<T> ApproximationHelper::ElementWiseOnComplexM
|
||||
matrix.setDimensions(m.numberOfRows(), m.numberOfColumns());
|
||||
return matrix;
|
||||
}
|
||||
|
||||
template float Poincare::ApproximationHelper::Epsilon<float>();
|
||||
template double Poincare::ApproximationHelper::Epsilon<double>();
|
||||
template int Poincare::ApproximationHelper::PositiveIntegerApproximationIfPossible<float>(Poincare::ExpressionNode const*, bool*, Poincare::Context*, Poincare::Preferences::ComplexFormat, Poincare::Preferences::AngleUnit);
|
||||
template int Poincare::ApproximationHelper::PositiveIntegerApproximationIfPossible<double>(Poincare::ExpressionNode const*, bool*, Poincare::Context*, Poincare::Preferences::ComplexFormat, Poincare::Preferences::AngleUnit);
|
||||
template std::complex<float> Poincare::ApproximationHelper::NeglectRealOrImaginaryPartIfNeglectable<float>(std::complex<float>,std::complex<float>,std::complex<float>,bool);
|
||||
|
||||
Reference in New Issue
Block a user