mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-19 00:37:25 +01:00
[poincare] Cheat on trigonometric functions
Change-Id: If49f6e25403dcf09736e1cd3e9c5f25bba140af3
This commit is contained in:
@@ -67,6 +67,7 @@ objs += $(addprefix poincare/src/,\
|
||||
sum.o\
|
||||
symbol.o\
|
||||
tangent.o\
|
||||
trigonometric_function.o\
|
||||
variable_context.o\
|
||||
)
|
||||
objs += $(addprefix poincare/src/layout/,\
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
#ifndef POINCARE_COSINE_H
|
||||
#define POINCARE_COSINE_H
|
||||
|
||||
#include <poincare/function.h>
|
||||
#include <poincare/trigonometric_function.h>
|
||||
|
||||
namespace Poincare {
|
||||
|
||||
class Cosine : public Function {
|
||||
class Cosine : public TrigonometricFunction {
|
||||
public:
|
||||
Cosine();
|
||||
Type type() const override;
|
||||
Expression * cloneWithDifferentOperands(Expression ** newOperands,
|
||||
int numberOfOperands, bool cloneOperands = true) const override;
|
||||
private:
|
||||
float privateApproximate(Context & context, AngleUnit angleUnit) const override;
|
||||
Expression * privateEvaluate(Context& context, AngleUnit angleUnit) const override;
|
||||
float trigonometricApproximation(float x) const override;
|
||||
Expression * createComplexEvaluation(Expression * arg, Context & context, AngleUnit angleUnit) const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
#ifndef POINCARE_SINE_H
|
||||
#define POINCARE_SINE_H
|
||||
|
||||
#include <poincare/function.h>
|
||||
#include <poincare/trigonometric_function.h>
|
||||
|
||||
namespace Poincare {
|
||||
|
||||
class Sine : public Function {
|
||||
class Sine : public TrigonometricFunction {
|
||||
public:
|
||||
Sine();
|
||||
Type type() const override;
|
||||
Expression * cloneWithDifferentOperands(Expression ** newOperands,
|
||||
int numberOfOperands, bool cloneOperands = true) const override;
|
||||
private:
|
||||
float privateApproximate(Context & context, AngleUnit angleUnit) const override;
|
||||
Expression * privateEvaluate(Context& context, AngleUnit angleUnit) const override;
|
||||
float trigonometricApproximation(float x) const override;
|
||||
Expression * createComplexEvaluation(Expression * arg, Context & context, AngleUnit angleUnit) const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
#ifndef POINCARE_TANGENT_H
|
||||
#define POINCARE_TANGENT_H
|
||||
|
||||
#include <poincare/function.h>
|
||||
#include <poincare/trigonometric_function.h>
|
||||
|
||||
namespace Poincare {
|
||||
|
||||
class Tangent : public Function {
|
||||
class Tangent : public TrigonometricFunction {
|
||||
public:
|
||||
Tangent();
|
||||
Type type() const override;
|
||||
Expression * cloneWithDifferentOperands(Expression ** newOperands,
|
||||
int numnerOfOperands, bool cloneOperands = true) const override;
|
||||
private:
|
||||
float privateApproximate(Context & context, AngleUnit angleUnit) const override;
|
||||
Expression * privateEvaluate(Context& context, AngleUnit angleUnit) const override;
|
||||
float trigonometricApproximation(float x) const override;
|
||||
Expression * createComplexEvaluation(Expression * arg, Context & context, AngleUnit angleUnit) const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
20
poincare/include/poincare/trigonometric_function.h
Normal file
20
poincare/include/poincare/trigonometric_function.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef POINCARE_TRIGONOMETRIC_FUNCTION_H
|
||||
#define POINCARE_TRIGONOMETRIC_FUNCTION_H
|
||||
|
||||
#include <poincare/function.h>
|
||||
|
||||
namespace Poincare {
|
||||
|
||||
class TrigonometricFunction : public Function {
|
||||
public:
|
||||
TrigonometricFunction(const char * name);
|
||||
private:
|
||||
float privateApproximate(Context & context, AngleUnit angleUnit) const override;
|
||||
Expression * privateEvaluate(Context& context, AngleUnit angleUnit) const override;
|
||||
virtual float trigonometricApproximation(float x) const = 0;
|
||||
virtual Expression * createComplexEvaluation(Expression * arg, Context & context, AngleUnit angleUnit) const = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -9,7 +9,7 @@ extern "C" {
|
||||
namespace Poincare {
|
||||
|
||||
Cosine::Cosine() :
|
||||
Function("cos")
|
||||
TrigonometricFunction("cos")
|
||||
{
|
||||
}
|
||||
|
||||
@@ -25,32 +25,15 @@ Expression * Cosine::cloneWithDifferentOperands(Expression** newOperands,
|
||||
return c;
|
||||
}
|
||||
|
||||
float Cosine::privateApproximate(Context& context, AngleUnit angleUnit) const {
|
||||
assert(angleUnit != AngleUnit::Default);
|
||||
if (angleUnit == AngleUnit::Degree) {
|
||||
return cosf(m_args[0]->approximate(context, angleUnit)*M_PI/180.0f);
|
||||
}
|
||||
return cosf(m_args[0]->approximate(context, angleUnit));
|
||||
float Cosine::trigonometricApproximation(float x) const {
|
||||
return cosf(x);
|
||||
}
|
||||
|
||||
Expression * Cosine::privateEvaluate(Context& context, AngleUnit angleUnit) const {
|
||||
assert(angleUnit != AngleUnit::Default);
|
||||
Expression * evaluation = m_args[0]->evaluate(context, angleUnit);
|
||||
assert(evaluation->type() == Type::Matrix || evaluation->type() == Type::Complex);
|
||||
if (evaluation->type() == Type::Matrix) {
|
||||
delete evaluation;
|
||||
return new Complex(Complex::Float(NAN));
|
||||
}
|
||||
/* Float case */
|
||||
if (((Complex *)evaluation)->b() == 0) {
|
||||
delete evaluation;
|
||||
return Function::privateEvaluate(context, angleUnit);
|
||||
}
|
||||
/* Complex case */
|
||||
Expression * arg = new Complex(Complex::Cartesian(-((Complex *)evaluation)->b(), ((Complex *)evaluation)->a()));
|
||||
Expression * Cosine::createComplexEvaluation(Expression * exp, Context & context, AngleUnit angleUnit) const {
|
||||
assert(exp->type() == Type::Complex);
|
||||
Expression * arg = new Complex(Complex::Cartesian(-((Complex *)exp)->b(), ((Complex *)exp)->a()));
|
||||
Function * cosh = new HyperbolicCosine();
|
||||
cosh->setArgument(&arg, 1, true);
|
||||
delete evaluation;
|
||||
delete arg;
|
||||
Expression * resultEvaluation = cosh->evaluate(context, angleUnit);
|
||||
delete cosh;
|
||||
|
||||
@@ -10,10 +10,14 @@ extern "C" {
|
||||
namespace Poincare {
|
||||
|
||||
Sine::Sine() :
|
||||
Function("sin")
|
||||
TrigonometricFunction("sin")
|
||||
{
|
||||
}
|
||||
|
||||
Expression::Type Sine::type() const {
|
||||
return Expression::Type::Sine;
|
||||
}
|
||||
|
||||
Expression * Sine::cloneWithDifferentOperands(Expression** newOperands,
|
||||
int numberOfOperands, bool cloneOperands) const {
|
||||
assert(newOperands != nullptr);
|
||||
@@ -22,36 +26,15 @@ Expression * Sine::cloneWithDifferentOperands(Expression** newOperands,
|
||||
return s;
|
||||
}
|
||||
|
||||
Expression::Type Sine::type() const {
|
||||
return Expression::Type::Sine;
|
||||
float Sine::trigonometricApproximation(float x) const {
|
||||
return sinf(x);
|
||||
}
|
||||
|
||||
float Sine::privateApproximate(Context& context, AngleUnit angleUnit) const {
|
||||
assert(angleUnit != AngleUnit::Default);
|
||||
if (angleUnit == AngleUnit::Degree) {
|
||||
return sinf(m_args[0]->approximate(context, angleUnit)*M_PI/180.0f);
|
||||
}
|
||||
return sinf(m_args[0]->approximate(context, angleUnit));
|
||||
}
|
||||
|
||||
Expression * Sine::privateEvaluate(Context& context, AngleUnit angleUnit) const {
|
||||
assert(angleUnit != AngleUnit::Default);
|
||||
Expression * evaluation = m_args[0]->evaluate(context, angleUnit);
|
||||
assert(evaluation->type() == Type::Matrix || evaluation->type() == Type::Complex);
|
||||
if (evaluation->type() == Type::Matrix) {
|
||||
delete evaluation;
|
||||
return new Complex(Complex::Float(NAN));
|
||||
}
|
||||
/* Float case */
|
||||
if (((Complex *)evaluation)->b() == 0) {
|
||||
delete evaluation;
|
||||
return Function::privateEvaluate(context, angleUnit);
|
||||
}
|
||||
/* Complex case */
|
||||
Expression * arg = new Complex(Complex::Cartesian(-((Complex *)evaluation)->b(), ((Complex *)evaluation)->a()));
|
||||
Expression * Sine::createComplexEvaluation(Expression * exp, Context & context, AngleUnit angleUnit) const {
|
||||
assert(exp->type() == Type::Complex);
|
||||
Expression * arg = new Complex(Complex::Cartesian(-((Complex *)exp)->b(), ((Complex *)exp)->a()));
|
||||
Function * sinh = new HyperbolicSine();
|
||||
sinh->setArgument(&arg, 1, true);
|
||||
delete evaluation;
|
||||
delete arg;
|
||||
Expression * args[2];
|
||||
args[0] = new Complex(Complex::Cartesian(0.0f, -1.0f));
|
||||
|
||||
@@ -11,7 +11,7 @@ extern "C" {
|
||||
namespace Poincare {
|
||||
|
||||
Tangent::Tangent() :
|
||||
Function("tan")
|
||||
TrigonometricFunction("tan")
|
||||
{
|
||||
}
|
||||
|
||||
@@ -27,34 +27,17 @@ Expression::Type Tangent::type() const {
|
||||
return Expression::Type::Tangent;
|
||||
}
|
||||
|
||||
float Tangent::privateApproximate(Context& context, AngleUnit angleUnit) const {
|
||||
assert(angleUnit != AngleUnit::Default);
|
||||
if (angleUnit == AngleUnit::Degree) {
|
||||
return tanf(m_args[0]->approximate(context, angleUnit)*M_PI/180.0f);
|
||||
}
|
||||
return tanf(m_args[0]->approximate(context, angleUnit));
|
||||
float Tangent::trigonometricApproximation(float x) const {
|
||||
return tanf(x);
|
||||
}
|
||||
|
||||
Expression * Tangent::privateEvaluate(Context& context, AngleUnit angleUnit) const {
|
||||
assert(angleUnit != AngleUnit::Default);
|
||||
Expression * evaluation = m_args[0]->evaluate(context, angleUnit);
|
||||
assert(evaluation->type() == Type::Matrix || evaluation->type() == Type::Complex);
|
||||
if (evaluation->type() == Type::Matrix) {
|
||||
delete evaluation;
|
||||
return new Complex(Complex::Float(NAN));
|
||||
}
|
||||
/* Float case */
|
||||
if (((Complex *)evaluation)->b() == 0) {
|
||||
delete evaluation;
|
||||
return Function::privateEvaluate(context, angleUnit);
|
||||
}
|
||||
/* Complex case */
|
||||
Expression * Tangent::createComplexEvaluation(Expression * exp, Context & context, AngleUnit angleUnit) const {
|
||||
assert(exp->type() == Type::Complex);
|
||||
Expression * arguments[2];
|
||||
arguments[0] = new Sine();
|
||||
((Function *)arguments[0])->setArgument(&evaluation, 1, true);
|
||||
((Function *)arguments[0])->setArgument(&exp, 1, true);
|
||||
arguments[1] = new Cosine();
|
||||
((Function *)arguments[1])->setArgument(&evaluation, 1, true);
|
||||
delete evaluation;
|
||||
((Function *)arguments[1])->setArgument(&exp, 1, true);
|
||||
Expression * result = new Fraction(arguments, true);
|
||||
delete arguments[1];
|
||||
delete arguments[0];
|
||||
|
||||
47
poincare/src/trigonometric_function.cpp
Normal file
47
poincare/src/trigonometric_function.cpp
Normal file
@@ -0,0 +1,47 @@
|
||||
#include <poincare/trigonometric_function.h>
|
||||
#include <poincare/complex.h>
|
||||
extern "C" {
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
}
|
||||
|
||||
namespace Poincare {
|
||||
|
||||
TrigonometricFunction::TrigonometricFunction(const char * name) :
|
||||
Function(name)
|
||||
{
|
||||
}
|
||||
|
||||
float TrigonometricFunction::privateApproximate(Context& context, AngleUnit angleUnit) const {
|
||||
assert(angleUnit != AngleUnit::Default);
|
||||
float input = m_args[0]->approximate(context, angleUnit);
|
||||
if (angleUnit == AngleUnit::Degree) {
|
||||
input *= M_PI/180.0f;
|
||||
}
|
||||
float result = trigonometricApproximation(input);
|
||||
if (input != 0.0f && fabsf(result/input) <= 1E-7f) {
|
||||
return 0.0f;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Expression * TrigonometricFunction::privateEvaluate(Context& context, AngleUnit angleUnit) const {
|
||||
assert(angleUnit != AngleUnit::Default);
|
||||
Expression * evaluation = m_args[0]->evaluate(context, angleUnit);
|
||||
assert(evaluation->type() == Type::Matrix || evaluation->type() == Type::Complex);
|
||||
if (evaluation->type() == Type::Matrix) {
|
||||
delete evaluation;
|
||||
return new Complex(Complex::Float(NAN));
|
||||
}
|
||||
/* Float case */
|
||||
if (((Complex *)evaluation)->b() == 0) {
|
||||
delete evaluation;
|
||||
return Function::privateEvaluate(context, angleUnit);
|
||||
}
|
||||
/* Complex case */
|
||||
Expression * resultEvaluation = createComplexEvaluation(evaluation, context, angleUnit);
|
||||
delete evaluation;
|
||||
return resultEvaluation;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user