mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-30 12:10:03 +02:00
[poincare] Cheat on evaluation of power, cosine and sine
Change-Id: Iebe4433b6bde35b92df78986f3360aa3a936024a
This commit is contained in:
@@ -141,6 +141,7 @@ public:
|
||||
protected:
|
||||
typedef float SinglePrecision;
|
||||
typedef double DoublePrecision;
|
||||
template<typename T> static T epsilon();
|
||||
private:
|
||||
virtual ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const = 0;
|
||||
virtual Evaluation<float> * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const = 0;
|
||||
|
||||
@@ -53,7 +53,16 @@ Complex<T> Complex<T>::Cartesian(T a, T b) {
|
||||
|
||||
template<typename T>
|
||||
Complex<T> Complex<T>::Polar(T r, T th) {
|
||||
return Complex(r*std::cos(th),r*std::sin(th));
|
||||
T c = std::cos(th);
|
||||
T s = std::sin(th);
|
||||
/* Cheat: see comment on cosine.cpp.
|
||||
* Sine and cosine openbsd immplementationd are numerical approximation.
|
||||
* We though want to avoid evaluating e^(i*pi) to -1+1E-17i. We thus round
|
||||
* cosine and sine results to 0 if they are negligible compared to the
|
||||
* argument th. */
|
||||
c = th != 0 && std::fabs(c/th) <= Expression::epsilon<T>() ? 0 : c;
|
||||
s = th != 0 && std::fabs(s/th) <= Expression::epsilon<T>() ? 0 : s;
|
||||
return Complex(r*c,r*s);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
||||
@@ -34,8 +34,14 @@ Complex<T> Cosine::compute(const Complex<T> c, AngleUnit angleUnit) {
|
||||
input *= M_PI/180.0f;
|
||||
}
|
||||
T result = std::cos(input);
|
||||
// TODO: See if necessary with double????
|
||||
if (input != 0 && std::fabs(result/input) <= 1E-7f) {
|
||||
/* Cheat: openbsd trigonometric functions (cos, sin & tan) 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
|
||||
* cos(90) = 6E-17, we neglect the result when its ratio with the argument
|
||||
* (pi in the exemple) is smaller than epsilon.
|
||||
* We can't do that for all evaluation as the user can operate on values as
|
||||
* small as 1E-308 (in double) and most results still be correct. */
|
||||
if (input != 0 && std::fabs(result/input) <= epsilon<T>()) {
|
||||
return Complex<T>::Float(0);
|
||||
}
|
||||
return Complex<T>::Float(result);
|
||||
|
||||
@@ -87,6 +87,11 @@ template<typename T> T Expression::approximate(const char * text, Context& conte
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename T> T Expression::epsilon() {
|
||||
static T epsilon = sizeof(T) == sizeof(double) ? 1E-15 : 1E-7f;
|
||||
return epsilon;
|
||||
}
|
||||
|
||||
Expression * Expression::simplify() const {
|
||||
/* We make sure that the simplification is deletable.
|
||||
* Indeed, we don't want an expression with some parts deletable and some not
|
||||
@@ -254,3 +259,5 @@ template double Poincare::Expression::approximate<double>(char const*, Poincare:
|
||||
template float Poincare::Expression::approximate<float>(char const*, Poincare::Context&, Poincare::Expression::AngleUnit);
|
||||
template double Poincare::Expression::approximate<double>(Poincare::Context&, Poincare::Expression::AngleUnit) const;
|
||||
template float Poincare::Expression::approximate<float>(Poincare::Context&, Poincare::Expression::AngleUnit) const;
|
||||
template double Poincare::Expression::epsilon<double>();
|
||||
template float Poincare::Expression::epsilon<float>();
|
||||
|
||||
@@ -34,8 +34,9 @@ Complex<T> Sine::compute(const Complex<T> c, AngleUnit angleUnit) {
|
||||
input *= M_PI/180;
|
||||
}
|
||||
T result = std::sin(input);
|
||||
// TODO: See if necessary with double????
|
||||
if (input != 0 && std::fabs(result/input) <= 1E-7f) {
|
||||
/* Cheat: see comment in cosine.cpp
|
||||
* We cheat to avoid returning sin(Pi) = epsilon */
|
||||
if (input != 0 && std::fabs(result/input) <= epsilon<T>()) {
|
||||
return Complex<T>::Float(0);
|
||||
}
|
||||
return Complex<T>::Float(result);
|
||||
|
||||
Reference in New Issue
Block a user