mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-18 21:30:38 +01:00
[poincare] Implement cos/acos in degree in complex domain
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
#include <poincare/layout_engine.h>
|
||||
#include <poincare/static_hierarchy.h>
|
||||
#include <poincare/approximation_engine.h>
|
||||
#include <poincare/trigonometry.h>
|
||||
|
||||
namespace Poincare {
|
||||
|
||||
@@ -26,7 +27,9 @@ private:
|
||||
/* Simplification */
|
||||
Expression * shallowReduce(Context& context, AngleUnit angleUnit) override;
|
||||
/* Evaluation */
|
||||
template<typename T> static std::complex<T> computeOnComplex(const std::complex<T> c, AngleUnit angleUnit);
|
||||
template<typename T> static std::complex<T> computeOnComplex(const std::complex<T> c, AngleUnit angleUnit) {
|
||||
return Trigonometry::computeInverseOnComplex(c, angleUnit, std::acos);
|
||||
}
|
||||
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override {
|
||||
return ApproximationEngine::map<float>(this, context, angleUnit,computeOnComplex<float>);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <poincare/layout_engine.h>
|
||||
#include <poincare/static_hierarchy.h>
|
||||
#include <poincare/approximation_engine.h>
|
||||
#include <poincare/trigonometry.h>
|
||||
|
||||
namespace Poincare {
|
||||
|
||||
@@ -24,7 +25,9 @@ private:
|
||||
/* Simplification */
|
||||
Expression * shallowReduce(Context & context, AngleUnit angleUnit) override;
|
||||
/* Evaluation */
|
||||
template<typename T> static std::complex<T> computeOnComplex(const std::complex<T> c, AngleUnit angleUnit);
|
||||
template<typename T> static std::complex<T> computeOnComplex(const std::complex<T> c, AngleUnit angleUnit) {
|
||||
return Trigonometry::computeInverseOnComplex(c, angleUnit, std::asin);
|
||||
}
|
||||
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override {
|
||||
return ApproximationEngine::map<float>(this, context, angleUnit, computeOnComplex<float>);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <poincare/layout_engine.h>
|
||||
#include <poincare/static_hierarchy.h>
|
||||
#include <poincare/approximation_engine.h>
|
||||
#include <poincare/trigonometry.h>
|
||||
|
||||
namespace Poincare {
|
||||
|
||||
@@ -24,7 +25,9 @@ private:
|
||||
/* Simplification */
|
||||
Expression * shallowReduce(Context& context, AngleUnit angleUnit) override;
|
||||
/* Evaluation */
|
||||
template<typename T> static std::complex<T> computeOnComplex(const std::complex<T> c, AngleUnit angleUnit);
|
||||
template<typename T> static std::complex<T> computeOnComplex(const std::complex<T> c, AngleUnit angleUnit) {
|
||||
return Trigonometry::computeInverseOnComplex(c, angleUnit, std::atan);
|
||||
}
|
||||
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override {
|
||||
return ApproximationEngine::map<float>(this, context, angleUnit,computeOnComplex<float>);
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ public:
|
||||
Expression * clone() const override;
|
||||
float characteristicXRange(Context & context, AngleUnit angleUnit) const override;
|
||||
template<typename T> static std::complex<T> computeOnComplex(const std::complex<T> c, AngleUnit angleUnit = AngleUnit::Radian) {
|
||||
return Trigonometry::computeOnComplex(c, angleUnit, std::cos);
|
||||
return Trigonometry::computeDirectOnComplex(c, angleUnit, std::cos);
|
||||
}
|
||||
private:
|
||||
/* Layout */
|
||||
|
||||
@@ -28,7 +28,7 @@ public:
|
||||
template<typename T>
|
||||
class Complex : public std::complex<T>, public Evaluation<T> {
|
||||
public:
|
||||
Complex(T a, T b = 0.0) : std::complex<T>(a, b) {}
|
||||
Complex(T a, T b = -0.0) : std::complex<T>(a, b) {}
|
||||
Complex(std::complex<T> c) : std::complex<T>(c) {}
|
||||
static Complex Undefined() {
|
||||
return Complex(NAN, NAN);
|
||||
|
||||
@@ -16,7 +16,7 @@ public:
|
||||
Type type() const override;
|
||||
Expression * clone() const override;
|
||||
template<typename T> static std::complex<T> computeOnComplex(const std::complex<T> c, AngleUnit angleUnit = AngleUnit::Radian) {
|
||||
return Trigonometry::computeOnComplex(c, angleUnit, std::sin);
|
||||
return Trigonometry::computeDirectOnComplex(c, angleUnit, std::sin);
|
||||
}
|
||||
private:
|
||||
/* Layout */
|
||||
|
||||
@@ -27,7 +27,7 @@ private:
|
||||
Expression * shallowReduce(Context& context, AngleUnit angleUnit) override;
|
||||
/* Evaluation */
|
||||
template<typename T> static std::complex<T> computeOnComplex(const std::complex<T> c, AngleUnit angleUnit = AngleUnit::Radian) {
|
||||
return Trigonometry::computeOnComplex(c, angleUnit, std::tan);
|
||||
return Trigonometry::computeDirectOnComplex(c, angleUnit, std::tan);
|
||||
}
|
||||
Evaluation<float> * privateApproximate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override {
|
||||
return ApproximationEngine::map<float>(this, context, angleUnit,computeOnComplex<float>);
|
||||
|
||||
@@ -18,7 +18,8 @@ public:
|
||||
constexpr static int k_numberOfEntries = 37;
|
||||
static Expression * table(const Expression * e, Expression::Type type, Context & context, Expression::AngleUnit angleUnit); // , Function f, bool inverse
|
||||
template <typename T> using Approximation = std::complex<T> (*)(const std::complex<T>&);
|
||||
template <typename T> static std::complex<T> computeOnComplex(const std::complex<T> c, Expression::AngleUnit angleUnit, Approximation<T> approximate);
|
||||
template <typename T> static std::complex<T> computeDirectOnComplex(const std::complex<T> c, Expression::AngleUnit angleUnit, Approximation<T> approximate);
|
||||
template <typename T> static std::complex<T> computeInverseOnComplex(const std::complex<T> c, Expression::AngleUnit angleUnit, Approximation<T> approximate);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -30,13 +30,4 @@ Expression * ArcCosine::shallowReduce(Context& context, AngleUnit angleUnit) {
|
||||
return Trigonometry::shallowReduceInverseFunction(this, context, angleUnit);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::complex<T> ArcCosine::computeOnComplex(const std::complex<T> c, AngleUnit angleUnit) {
|
||||
std::complex<T> result = std::acos(c);
|
||||
if (angleUnit == AngleUnit::Degree && result.imag() == 0.0) {
|
||||
result *= 180/M_PI;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -30,13 +30,4 @@ Expression * ArcSine::shallowReduce(Context& context, AngleUnit angleUnit) {
|
||||
return Trigonometry::shallowReduceInverseFunction(this, context, angleUnit);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::complex<T> ArcSine::computeOnComplex(const std::complex<T> c, AngleUnit angleUnit) {
|
||||
std::complex<T> result = std::asin(c);
|
||||
if (angleUnit == AngleUnit::Degree && result.imag() == 0.0) {
|
||||
result *= 180/M_PI;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -30,13 +30,4 @@ Expression * ArcTangent::shallowReduce(Context& context, AngleUnit angleUnit) {
|
||||
return Trigonometry::shallowReduceInverseFunction(this, context, angleUnit);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::complex<T> ArcTangent::computeOnComplex(const std::complex<T> c, AngleUnit angleUnit) {
|
||||
std::complex<T> result = std::atan(c);
|
||||
if (angleUnit == AngleUnit::Degree && result.imag() == 0.0) {
|
||||
result *= 180/M_PI;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -49,10 +49,7 @@ Expression * Trigonometry::shallowReduceDirectFunction(Expression * e, Context&
|
||||
}
|
||||
Expression::Type correspondingType = e->type() == Expression::Type::Cosine ? Expression::Type::ArcCosine : (e->type() == Expression::Type::Sine ? Expression::Type::ArcSine : Expression::Type::ArcTangent);
|
||||
if (e->operand(0)->type() == correspondingType) {
|
||||
float trigoOp = e->operand(0)->operand(0)->approximateToScalar<float>(context, angleUnit);
|
||||
if (e->type() == Expression::Type::Tangent || (trigoOp >= -1.0f && trigoOp <= 1.0f)) {
|
||||
return e->replaceWith(e->editableOperand(0)->editableOperand(0), true);
|
||||
}
|
||||
return e->replaceWith(e->editableOperand(0)->editableOperand(0), true);
|
||||
}
|
||||
if (e->operand(0)->sign() == Expression::Sign::Negative) {
|
||||
Expression * op = e->editableOperand(0);
|
||||
@@ -109,12 +106,6 @@ bool Trigonometry::ExpressionIsEquivalentToTangent(const Expression * e) {
|
||||
|
||||
Expression * Trigonometry::shallowReduceInverseFunction(Expression * e, Context& context, Expression::AngleUnit angleUnit) {
|
||||
assert(e->type() == Expression::Type::ArcCosine || e->type() == Expression::Type::ArcSine || e->type() == Expression::Type::ArcTangent);
|
||||
if (e->type() != Expression::Type::ArcTangent) {
|
||||
float approxOp = e->operand(0)->approximateToScalar<float>(context, angleUnit);
|
||||
if (approxOp > 1.0f || approxOp < -1.0f) {
|
||||
return e->replaceWith(new Undefined(), true);
|
||||
}
|
||||
}
|
||||
Expression::Type correspondingType = e->type() == Expression::Type::ArcCosine ? Expression::Type::Cosine : (e->type() == Expression::Type::ArcSine ? Expression::Type::Sine : Expression::Type::Tangent);
|
||||
float pi = angleUnit == Expression::AngleUnit::Radian ? M_PI : 180;
|
||||
if (e->operand(0)->type() == correspondingType) {
|
||||
@@ -239,9 +230,9 @@ Expression * Trigonometry::table(const Expression * e, Expression::Type type, Co
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::complex<T> Trigonometry::computeOnComplex(const std::complex<T> c, Expression::AngleUnit angleUnit, Approximation<T> approximate) {
|
||||
std::complex<T> Trigonometry::computeDirectOnComplex(const std::complex<T> c, Expression::AngleUnit angleUnit, Approximation<T> approximate) {
|
||||
std::complex<T> input(c);
|
||||
if (angleUnit == Expression::AngleUnit::Degree && input.imag() == 0.0) {
|
||||
if (angleUnit == Expression::AngleUnit::Degree) {
|
||||
input = input*std::complex<T>(M_PI/180.0);
|
||||
}
|
||||
std::complex<T> result = approximate(input);
|
||||
@@ -261,7 +252,18 @@ std::complex<T> Trigonometry::computeOnComplex(const std::complex<T> c, Expressi
|
||||
return result;
|
||||
}
|
||||
|
||||
template std::complex<double> Trigonometry::computeOnComplex<double>(const std::complex<double>, Expression::AngleUnit, Approximation<double>);
|
||||
template std::complex<float> Trigonometry::computeOnComplex<float>(const std::complex<float>, Expression::AngleUnit, Approximation<float>);
|
||||
template<typename T>
|
||||
std::complex<T> Trigonometry::computeInverseOnComplex(const std::complex<T> c, Expression::AngleUnit angleUnit, Approximation<T> approximate) {
|
||||
std::complex<T> result = approximate(c);
|
||||
if (angleUnit == Expression::AngleUnit::Degree) {
|
||||
result *= 180/M_PI;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template std::complex<double> Trigonometry::computeDirectOnComplex<double>(const std::complex<double>, Expression::AngleUnit, Approximation<double>);
|
||||
template std::complex<float> Trigonometry::computeDirectOnComplex<float>(const std::complex<float>, Expression::AngleUnit, Approximation<float>);
|
||||
template std::complex<double> Trigonometry::computeInverseOnComplex<double>(const std::complex<double>, Expression::AngleUnit, Approximation<double>);
|
||||
template std::complex<float> Trigonometry::computeInverseOnComplex<float>(const std::complex<float>, Expression::AngleUnit, Approximation<float>);
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user