From 67cf8a1a460136de4023da79b3cff5c52cd189cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 23 Aug 2018 14:06:31 +0200 Subject: [PATCH] [poincare] Sine --- poincare/Makefile | 1 + poincare/include/poincare.h | 1 + poincare/include/poincare/expression.h | 1 + poincare/include/poincare/sine.h | 55 ++++++++++++++++++++------ poincare/src/expression_lexer.l | 5 ++- poincare/src/sine.cpp | 46 ++++++++++----------- poincare/test/trigo.cpp | 6 +-- 7 files changed, 70 insertions(+), 45 deletions(-) diff --git a/poincare/Makefile b/poincare/Makefile index 42b453c32..480967591 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -69,6 +69,7 @@ objs += $(addprefix poincare/src/,\ rational.o\ serialization_helper.o\ simplification_helper.o\ + sine.o\ square_root.o\ subtraction.o\ symbol.o\ diff --git a/poincare/include/poincare.h b/poincare/include/poincare.h index be4217aaf..aa9077b5e 100644 --- a/poincare/include/poincare.h +++ b/poincare/include/poincare.h @@ -108,6 +108,7 @@ #include #include #include +#include #include #include #include diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 7392d96a8..fdc658a8c 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -14,6 +14,7 @@ class Context; class Expression : public TreeByValue { friend class CosineNode; + friend class SineNode; friend class ExpressionNode; friend class Multiplication; friend class Subtraction; diff --git a/poincare/include/poincare/sine.h b/poincare/include/poincare/sine.h index 1eb4a2b51..fba8a52b3 100644 --- a/poincare/include/poincare/sine.h +++ b/poincare/include/poincare/sine.h @@ -1,32 +1,50 @@ #ifndef POINCARE_SINE_H #define POINCARE_SINE_H -#include -#include #include +#include +#include +#include #include namespace Poincare { -class Sine : public StaticHierarchy<1> { - using StaticHierarchy<1>::StaticHierarchy; - friend class Tangent; - float characteristicXRange(Context & context, Preferences::AngleUnit angleUnit) const override; +class SineNode : public ExpressionNode { + //friend class Tangent; public: - Type type() const override; - template static std::complex computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit = Preferences::AngleUnit::Radian); + // Allocation Failure + static SineNode * FailedAllocationStaticNode(); + SineNode * failedAllocationStaticNode() override { return FailedAllocationStaticNode(); } + + // TreeNode + size_t size() const override { return sizeof(SineNode); } + int numberOfChildren() const override { return 1; } +#if POINCARE_TREE_LOG + virtual void logNodeName(std::ostream & stream) const override { + stream << "Sine"; + } +#endif + + // Properties + Type type() const override { return Type::Sine; } + float characteristicXRange(Context & context, Preferences::AngleUnit angleUnit) const override; + + template static Complex computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit = Preferences::AngleUnit::Radian); + private: - /* Layout */ - LayoutRef createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override { + // Layout + LayoutReference createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override { return LayoutHelper::Prefix(this, floatDisplayMode, numberOfSignificantDigits, name()); } int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override { return SerializationHelper::Prefix(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, name()); } const char * name() const { return "sin"; } - /* Simplication */ - Expression shallowReduce(Context& context, Preferences::AngleUnit angleUnit) override; - /* Evaluation */ + + // Simplication + Expression shallowReduce(Context& context, Preferences::AngleUnit angleUnit) const override; + + // Evaluation Evaluation approximate(SinglePrecision p, Context& context, Preferences::AngleUnit angleUnit) const override { return ApproximationHelper::Map(this, context, angleUnit,computeOnComplex); } @@ -35,6 +53,17 @@ private: } }; +class Sine : public Expression { +public: + Sine() : Expression(TreePool::sharedPool()->createTreeNode()) {} + Sine(const SineNode * n) : Expression(n) {} + Sine(Expression operand) : Sine() { + replaceChildAtIndexInPlace(0, operand); + } + + Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit) const; +}; + } #endif diff --git a/poincare/src/expression_lexer.l b/poincare/src/expression_lexer.l index 5aedb4989..fc89d87a8 100644 --- a/poincare/src/expression_lexer.l +++ b/poincare/src/expression_lexer.l @@ -156,8 +156,9 @@ rem { poincare_expression_yylval.expression = new DivisionRemainder(); return FU */ root { poincare_expression_yylval.expression = NthRoot(); return FUNCTION; } /*round { poincare_expression_yylval.expression = new Round(); return FUNCTION; } -sin { poincare_expression_yylval.expression = new Sine(); return FUNCTION; } -sinh { poincare_expression_yylval.expression = new HyperbolicSine(); return FUNCTION; } +*/ +sin { poincare_expression_yylval.expression = Sine(); return FUNCTION; } + /*sinh { poincare_expression_yylval.expression = new HyperbolicSine(); return FUNCTION; } sum { poincare_expression_yylval.expression = new Sum(); return FUNCTION; } tan { poincare_expression_yylval.expression = new Tangent(); return FUNCTION; } tanh { poincare_expression_yylval.expression = new HyperbolicTangent(); return FUNCTION; } diff --git a/poincare/src/sine.cpp b/poincare/src/sine.cpp index 12bebe8ad..e9fd8dce6 100644 --- a/poincare/src/sine.cpp +++ b/poincare/src/sine.cpp @@ -1,49 +1,43 @@ #include -#include -#include -#include -#include +#include #include -#include -extern "C" { -#include -} #include namespace Poincare { -Expression::Type Sine::type() const { - return Expression::Type::Sine; +SineNode * SineNode::FailedAllocationStaticNode() { + static AllocationFailureExpressionNode failure; + TreePool::sharedPool()->registerStaticNodeIfRequired(&failure); + return &failure; } -Expression * Sine::clone() const { - Sine * a = new Sine(m_operands, true); - return a; -} - -float Sine::characteristicXRange(Context & context, Preferences::AngleUnit angleUnit) const { - return Trigonometry::characteristicXRange(this, context, angleUnit); +float SineNode::characteristicXRange(Context & context, Preferences::AngleUnit angleUnit) const { + return Trigonometry::characteristicXRange(Sine(this), context, angleUnit); } template -std::complex Sine::computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit) { +Complex SineNode::computeOnComplex(const std::complex c, Preferences::AngleUnit angleUnit) { std::complex angleInput = Trigonometry::ConvertToRadian(c, angleUnit); std::complex res = std::sin(angleInput); - return Trigonometry::RoundToMeaningfulDigits(res); + return Complex(Trigonometry::RoundToMeaningfulDigits(res)); } -Expression Sine::shallowReduce(Context& context, Preferences::AngleUnit angleUnit) { - Expression * e = Expression::defaultShallowReduce(context, angleUnit); - if (e != this) { +Expression SineNode::shallowReduce(Context& context, Preferences::AngleUnit angleUnit) const { + return Sine(this).shallowReduce(context, angleUnit); +} + +Expression Sine::shallowReduce(Context& context, Preferences::AngleUnit angleUnit) const { + Expression e = Expression::defaultShallowReduce(context, angleUnit); + if (e.isUndefinedOrAllocationFailure()) { return e; } #if MATRIX_EXACT_REDUCING - Expression * op = editableOperand(0); - if (op->type() == Type::Matrix) { - return SimplificationHelper::Map(this, context, angleUnit); + Expression op = childAtIndex(0); + if (op.type() == ExpressionNode::Type::Matrix) { + return SimplificationHelper::Map(*this, context, angleUnit); } #endif - return Trigonometry::shallowReduceDirectFunction(this, context, angleUnit); + return Trigonometry::shallowReduceDirectFunction(*this, context, angleUnit); } } diff --git a/poincare/test/trigo.cpp b/poincare/test/trigo.cpp index cc8323c3a..94d2a92ad 100644 --- a/poincare/test/trigo.cpp +++ b/poincare/test/trigo.cpp @@ -7,9 +7,7 @@ using namespace Poincare; QUIZ_CASE(poincare_parse_trigo) { -#if 0 assert_parsed_expression_type("sin(0)", ExpressionNode::Type::Sine); -#endif assert_parsed_expression_type("cos(0)", ExpressionNode::Type::Cosine); #if 0 assert_parsed_expression_type("tan(0)", ExpressionNode::Type::Tangent); @@ -47,7 +45,6 @@ QUIZ_CASE(poincare_trigo_evaluate) { assert_parsed_expression_evaluates_to("cos(I-4)", "(-1.008625)-0.889395*I", Radian); assert_parsed_expression_evaluates_to("cos(I-4)", "0.997716+0.001218*I", Degree, Cartesian, 6); -#if 0 /* sin: R -> R (oscillator) * Ri -> Ri (odd) */ @@ -69,6 +66,7 @@ QUIZ_CASE(poincare_trigo_evaluate) { assert_parsed_expression_evaluates_to("sin(I-4)", "1.16781-0.768163*I", Radian, Cartesian, 6); assert_parsed_expression_evaluates_to("sin(I-4)", "(-0.069767)+0.017412*I", Degree, Cartesian, 6); +#if 0 /* tan: R -> R (tangent-style) * Ri -> Ri (odd) */ @@ -389,7 +387,6 @@ QUIZ_CASE(poincare_trigo_simplify) { assert_parsed_expression_simplify_to("cos(-60)", "1/2", Preferences::AngleUnit::Degree); assert_parsed_expression_simplify_to("cos(7380/5)", "(1+R(5))/4", Preferences::AngleUnit::Degree); assert_parsed_expression_simplify_to("cos(112.5)", "-R(2-R(2))/2", Preferences::AngleUnit::Degree); -#if 0 // -- sin assert_parsed_expression_simplify_to("sin(0)", "0"); assert_parsed_expression_simplify_to("sin(P)", "0"); @@ -426,6 +423,7 @@ QUIZ_CASE(poincare_trigo_simplify) { assert_parsed_expression_simplify_to("sin(-60)", "-R(3)/2", Preferences::AngleUnit::Degree); assert_parsed_expression_simplify_to("sin(612)", "-(R(2)*R(5+R(5)))/4", Preferences::AngleUnit::Degree); assert_parsed_expression_simplify_to("sin(36)", "(R(2)*R(5-R(5)))/4", Preferences::AngleUnit::Degree); +#if 0 // -- tan assert_parsed_expression_simplify_to("tan(0)", "0"); assert_parsed_expression_simplify_to("tan(P)", "0");