mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-19 00:37:25 +01:00
[poincare] Implement factorial
Change-Id: I2344d12fdc9084db84247a096110efe0e909e32a
This commit is contained in:
@@ -23,6 +23,7 @@ objs += $(addprefix poincare/src/,\
|
||||
expression.o\
|
||||
expression_lexer.o\
|
||||
expression_parser.o\
|
||||
factorial.o\
|
||||
floor.o\
|
||||
frac_part.o\
|
||||
fraction.o\
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <poincare/division_quotient.h>
|
||||
#include <poincare/division_remainder.h>
|
||||
#include <poincare/expression.h>
|
||||
#include <poincare/factorial.h>
|
||||
#include <poincare/floor.h>
|
||||
#include <poincare/frac_part.h>
|
||||
#include <poincare/fraction.h>
|
||||
|
||||
@@ -27,6 +27,7 @@ public:
|
||||
Determinant,
|
||||
DivisionQuotient,
|
||||
DivisionRemainder,
|
||||
Factorial,
|
||||
Float,
|
||||
Floor,
|
||||
FracPart,
|
||||
|
||||
21
poincare/include/poincare/factorial.h
Normal file
21
poincare/include/poincare/factorial.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#ifndef POINCARE_FACTORIAL_H
|
||||
#define POINCARE_FACTORIAL_H
|
||||
|
||||
#include <poincare/function.h>
|
||||
|
||||
namespace Poincare {
|
||||
|
||||
class Factorial : public Function {
|
||||
public:
|
||||
Factorial(Expression * argument, bool clone = true);
|
||||
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
|
||||
@@ -145,6 +145,7 @@ inf { poincare_expression_yylval.expression = new Complex(Complex::Float(INFINIT
|
||||
\* { return MULTIPLY; }
|
||||
\/ { return DIVIDE; }
|
||||
\^ { return POW; }
|
||||
\! { return BANG; }
|
||||
\( { return LEFT_PARENTHESIS; }
|
||||
\) { return RIGHT_PARENTHESIS; }
|
||||
\{ { return LEFT_BRACE; }
|
||||
|
||||
@@ -58,6 +58,7 @@ void poincare_expression_yyerror(Poincare::Expression ** expressionOutput, char
|
||||
%token MULTIPLY
|
||||
%token DIVIDE
|
||||
%token POW
|
||||
%token BANG
|
||||
%token LEFT_PARENTHESIS
|
||||
%token RIGHT_PARENTHESIS
|
||||
%token LEFT_BRACE
|
||||
@@ -89,6 +90,7 @@ void poincare_expression_yyerror(Poincare::Expression ** expressionOutput, char
|
||||
%left MULTIPLY
|
||||
%left DIVIDE
|
||||
%left POW
|
||||
%left BANG
|
||||
|
||||
/* The "exp" symbol uses the "expression" part of the union. */
|
||||
%type <expression> exp;
|
||||
@@ -131,7 +133,8 @@ symb:
|
||||
|
||||
exp:
|
||||
UNDEFINED { $$ = $1; }
|
||||
| exp STO symb {$$ = new Poincare::Store($3, $1, false); }
|
||||
| exp BANG { $$ = new Poincare::Factorial($1, false); }
|
||||
| exp STO symb { $$ = new Poincare::Store($3, $1, false); }
|
||||
| number { $$ = $1; }
|
||||
| ICOMPLEX { $$ = new Poincare::Complex(Poincare::Complex::Cartesian(0.0f, 1.0f)); }
|
||||
| symb { $$ = $1; }
|
||||
|
||||
53
poincare/src/factorial.cpp
Normal file
53
poincare/src/factorial.cpp
Normal file
@@ -0,0 +1,53 @@
|
||||
#include <poincare/factorial.h>
|
||||
#include "layout/string_layout.h"
|
||||
#include "layout/horizontal_layout.h"
|
||||
extern "C" {
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
}
|
||||
|
||||
namespace Poincare {
|
||||
|
||||
Factorial::Factorial(Expression * argument, bool clone) :
|
||||
Function("fact")
|
||||
{
|
||||
setArgument(&argument, 1, clone);
|
||||
}
|
||||
|
||||
Expression::Type Factorial::type() const {
|
||||
return Type::Factorial;
|
||||
}
|
||||
|
||||
Expression * Factorial::cloneWithDifferentOperands(Expression** newOperands,
|
||||
int numberOfOperands, bool cloneOperands) const {
|
||||
assert(newOperands != nullptr);
|
||||
Factorial * f = new Factorial(newOperands[0], cloneOperands);
|
||||
return f;
|
||||
}
|
||||
|
||||
float Factorial::privateApproximate(Context& context, AngleUnit angleUnit) const {
|
||||
assert(angleUnit != AngleUnit::Default);
|
||||
float n = m_args[0]->approximate(context, angleUnit);
|
||||
if (isnan(n) || n != (int)n || n < 0.0f) {
|
||||
return NAN;
|
||||
}
|
||||
float result = 1.0f;
|
||||
for (int i = 1; i <= (int)n; i++) {
|
||||
result *= (float)i;
|
||||
if (isinf(result)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return roundf(result);
|
||||
}
|
||||
|
||||
ExpressionLayout * Factorial::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const {
|
||||
assert(floatDisplayMode != FloatDisplayMode::Default);
|
||||
assert(complexFormat != ComplexFormat::Default);
|
||||
ExpressionLayout * childrenLayouts[2];
|
||||
childrenLayouts[0] = m_args[0]->createLayout(floatDisplayMode, complexFormat);
|
||||
childrenLayouts[1] = new StringLayout("!", 1);
|
||||
return new HorizontalLayout(childrenLayouts, 2);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user