diff --git a/poincare/Makefile b/poincare/Makefile index 81015f044..371618610 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -6,6 +6,7 @@ objs += $(addprefix poincare/src/,\ absolute_value.o\ addition.o\ binary_operation.o\ + binomial_coefficient.o\ complex.o\ complex_argument.o\ conjugate.o\ diff --git a/poincare/include/poincare.h b/poincare/include/poincare.h index ba1302608..2faf63037 100644 --- a/poincare/include/poincare.h +++ b/poincare/include/poincare.h @@ -3,6 +3,7 @@ #include #include +#include #include #include #include diff --git a/poincare/include/poincare/binomial_coefficient.h b/poincare/include/poincare/binomial_coefficient.h new file mode 100644 index 000000000..06a25ea8b --- /dev/null +++ b/poincare/include/poincare/binomial_coefficient.h @@ -0,0 +1,22 @@ +#ifndef POINCARE_BINOMIAL_COEFFICIENT_H +#define POINCARE_BINOMIAL_COEFFICIENT_H + +#include + +namespace Poincare { + +class BinomialCoefficient : public Function { +public: + BinomialCoefficient(); + Type type() const override; + Expression * cloneWithDifferentOperands(Expression ** newOperands, + int numberOfOperands, bool cloneOperands = true) const override; +private: + float privateApproximate(Context & context, AngleUnit angleUnit) const override; + ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; +}; + +} + +#endif + diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 493a89dd5..7d6d68feb 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -13,6 +13,7 @@ public: enum class Type : uint8_t { AbsoluteValue, Addition, + BinomialCoefficient, Complex, ComplexArgument, Conjugate, diff --git a/poincare/src/binomial_coefficient.cpp b/poincare/src/binomial_coefficient.cpp new file mode 100644 index 000000000..35e51bb00 --- /dev/null +++ b/poincare/src/binomial_coefficient.cpp @@ -0,0 +1,56 @@ +#include +#include +#include "layout/parenthesis_layout.h" +#include "layout/grid_layout.h" + +extern "C" { +#include +#include +#include +} + +namespace Poincare { + +BinomialCoefficient::BinomialCoefficient() : + Function("binomial") +{ +} + +Expression::Type BinomialCoefficient::type() const { + return Type::BinomialCoefficient; +} + +Expression * BinomialCoefficient::cloneWithDifferentOperands(Expression** newOperands, + int numberOfOperands, bool cloneOperands) const { + assert(numberOfOperands == 1); + assert(newOperands != nullptr); + BinomialCoefficient * bc = new BinomialCoefficient(); + bc->setArgument(newOperands, numberOfOperands, cloneOperands); + return bc; +} + +float BinomialCoefficient::privateApproximate(Context& context, AngleUnit angleUnit) const { + assert(angleUnit != AngleUnit::Default); + float n = m_args[0]->approximate(context, angleUnit); + float k = m_args[1]->approximate(context, angleUnit); + if (isnan(n) || isnan(k) || n != (int)n || k != (int)k) { + return NAN; + } + float result = 1.0f; + for (int i = 0; i < (int)k; i++) { + result *= (n-(float)i)/(k-(float)i); + } + return roundf(result); +} + +ExpressionLayout * BinomialCoefficient::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { + assert(floatDisplayMode != FloatDisplayMode::Default); + assert(complexFormat != ComplexFormat::Default); + ExpressionLayout ** childrenLayouts = (ExpressionLayout **)malloc(2*sizeof(ExpressionLayout *)); + childrenLayouts[0] = m_args[0]->createLayout(floatDisplayMode, complexFormat); + childrenLayouts[1] = m_args[1]->createLayout(floatDisplayMode, complexFormat); + return new ParenthesisLayout(new GridLayout(childrenLayouts, 2, 1)); +} + +} + diff --git a/poincare/src/expression_lexer.l b/poincare/src/expression_lexer.l index 544100b91..6ec6f28f3 100644 --- a/poincare/src/expression_lexer.l +++ b/poincare/src/expression_lexer.l @@ -92,6 +92,7 @@ w\(n\+1\) { poincare_expression_yylval.character = Symbol::SpecialSymbols::wn1; abs { poincare_expression_yylval.expression = new AbsoluteValue(); return FUNCTION; } ans { poincare_expression_yylval.character = Symbol::SpecialSymbols::Ans; return SYMBOL; } arg { poincare_expression_yylval.expression = new ComplexArgument(); return FUNCTION; } +binomial { poincare_expression_yylval.expression = new BinomialCoefficient(); return FUNCTION; } diff { poincare_expression_yylval.expression = new Derivative(); return FUNCTION; } det { poincare_expression_yylval.expression = new Determinant(); return FUNCTION; } conj { poincare_expression_yylval.expression = new Conjugate(); return FUNCTION; }