mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-18 21:30:38 +01:00
Poincare: Add a simplifier
Change-Id: Iac53c9b7dda5cb284fe750bb84c92ce5d1fba497
This commit is contained in:
@@ -20,11 +20,15 @@ objs += $(addprefix poincare/src/layout/,\
|
||||
exponent_layout.o\
|
||||
string_layout.o\
|
||||
)
|
||||
objs += $(addprefix poincare/src/simplify/,\
|
||||
simplifier_zero.o\
|
||||
)
|
||||
tests += $(addprefix poincare/test/,\
|
||||
addition.cpp\
|
||||
fraction.cpp\
|
||||
integer.cpp\
|
||||
product.cpp\
|
||||
simplify.cpp\
|
||||
subtraction.cpp\
|
||||
)
|
||||
|
||||
|
||||
@@ -5,10 +5,12 @@
|
||||
|
||||
class Addition : public Expression {
|
||||
public:
|
||||
static const expression_type_t Type = 0x00;
|
||||
Addition(Expression * first_operand, Expression * second_operand);
|
||||
~Addition();
|
||||
ExpressionLayout * createLayout(ExpressionLayout * parent) override;
|
||||
float approximate(Context& context) override;
|
||||
expression_type_t type() override;
|
||||
private:
|
||||
Expression * m_left;
|
||||
Expression * m_right;
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <kandinsky.h>
|
||||
|
||||
class Context;
|
||||
typedef uint8_t expression_type_t;
|
||||
|
||||
class Expression {
|
||||
public:
|
||||
@@ -19,7 +20,9 @@ class Expression {
|
||||
/* identicalTo means strictly the same tree. For example, 3+5 is NOT identi-
|
||||
* cal to 5+3. Those are equal, but not identical. */
|
||||
//virtual bool identicalTo(Expression * e);
|
||||
//virtual Expression * simplify();
|
||||
Expression * simplify();
|
||||
|
||||
virtual expression_type_t type() = 0;
|
||||
|
||||
virtual float approximate(Context& context) = 0;
|
||||
/*private:
|
||||
|
||||
@@ -5,11 +5,13 @@
|
||||
|
||||
class Float : public Expression {
|
||||
public:
|
||||
static const expression_type_t Type = 0x03;
|
||||
Float(float f);
|
||||
~Float();
|
||||
|
||||
ExpressionLayout * createLayout(ExpressionLayout * parent) override;
|
||||
float approximate(Context& context) override;
|
||||
expression_type_t type() override;
|
||||
private:
|
||||
float m_float;
|
||||
};
|
||||
|
||||
@@ -5,10 +5,12 @@
|
||||
|
||||
class Fraction : public Expression {
|
||||
public:
|
||||
static const expression_type_t Type = 0x02;
|
||||
Fraction(Expression * numerator, Expression * denominator);
|
||||
~Fraction();
|
||||
ExpressionLayout * createLayout(ExpressionLayout * parent) override;
|
||||
float approximate(Context& context) override;
|
||||
expression_type_t type() override;
|
||||
private:
|
||||
Expression * m_numerator;
|
||||
Expression * m_denominator;
|
||||
|
||||
@@ -10,10 +10,12 @@ typedef uint64_t double_native_uint_t;
|
||||
|
||||
class Integer : public Expression {
|
||||
public:
|
||||
// TODO static const Integer Zero;
|
||||
static const expression_type_t Type = 0x01;
|
||||
Integer(native_int_t i);
|
||||
Integer(Integer&& other); // C++11 move constructor
|
||||
Integer(const char * string); // NULL-terminated
|
||||
expression_type_t type() override;
|
||||
|
||||
~Integer();
|
||||
|
||||
Integer& operator=(Integer&& other); // C++11 move assignment operator
|
||||
@@ -30,8 +32,8 @@ class Integer : public Expression {
|
||||
/*virtual Expression ** children();
|
||||
virtual bool identicalTo(Expression * e);
|
||||
*/
|
||||
virtual ExpressionLayout * createLayout(ExpressionLayout * parent);
|
||||
virtual float approximate(Context& context);
|
||||
virtual ExpressionLayout * createLayout(ExpressionLayout * parent) override;
|
||||
virtual float approximate(Context& context) override;
|
||||
private:
|
||||
int8_t ucmp(const Integer &other) const; // -1, 0, or 1
|
||||
Integer usum(const Integer &other, bool subtract, bool output_negative) const;
|
||||
|
||||
@@ -5,10 +5,13 @@
|
||||
|
||||
class Power : public Expression {
|
||||
public:
|
||||
static const expression_type_t Type = 0x04;
|
||||
|
||||
Power(Expression * base, Expression * exponent);
|
||||
~Power();
|
||||
ExpressionLayout * createLayout(ExpressionLayout * parent) override;
|
||||
float approximate(Context& context) override;
|
||||
expression_type_t type() override;
|
||||
private:
|
||||
Expression * m_base;
|
||||
Expression * m_exponent;
|
||||
|
||||
@@ -5,11 +5,13 @@
|
||||
|
||||
class Product : public Expression {
|
||||
public:
|
||||
static const expression_type_t Type = 0x05;
|
||||
Product(Expression * first_factor, Expression * second_factor);
|
||||
~Product();
|
||||
ExpressionLayout * createLayout(ExpressionLayout * parent) override;
|
||||
float approximate(Context& context) override;
|
||||
private:
|
||||
expression_type_t type() override;
|
||||
//private:
|
||||
Expression * m_children[2];
|
||||
};
|
||||
|
||||
|
||||
@@ -5,10 +5,12 @@
|
||||
|
||||
class Subtraction : public Expression {
|
||||
public:
|
||||
static const expression_type_t Type = 0x06;
|
||||
Subtraction(Expression * first_operand, Expression * second_operand);
|
||||
~Subtraction();
|
||||
ExpressionLayout * createLayout(ExpressionLayout * parent) override;
|
||||
float approximate(Context& context) override;
|
||||
expression_type_t type() override;
|
||||
private:
|
||||
Expression * m_left;
|
||||
Expression * m_right;
|
||||
|
||||
@@ -5,10 +5,12 @@
|
||||
|
||||
class Symbol : public Expression {
|
||||
public:
|
||||
static const expression_type_t Type = 0x07;
|
||||
Symbol(char * name);
|
||||
~Symbol();
|
||||
ExpressionLayout * createLayout(ExpressionLayout * parent) override;
|
||||
float approximate(Context& context) override;
|
||||
expression_type_t type() override;
|
||||
private:
|
||||
char * m_name;
|
||||
};
|
||||
|
||||
@@ -6,6 +6,10 @@ Addition::Addition(Expression * first_operand, Expression * second_operand) {
|
||||
m_right = second_operand;
|
||||
}
|
||||
|
||||
expression_type_t Addition::type() {
|
||||
return Addition::Type;
|
||||
}
|
||||
|
||||
Addition::~Addition() {
|
||||
delete m_left;
|
||||
delete m_right;
|
||||
|
||||
@@ -1,9 +1,19 @@
|
||||
#include <poincare/expression.h>
|
||||
#include "expression_parser.hpp"
|
||||
#include "expression_lexer.hpp"
|
||||
#include "simplify/simplifier.h"
|
||||
#include "simplify/simplifier_zero.h"
|
||||
|
||||
static expression_simplifier_t kSimplifiers[] = {
|
||||
&SimplifierZero,
|
||||
nullptr
|
||||
};
|
||||
|
||||
int poincare_expression_yyparse(yyscan_t scanner, Expression ** expressionOutput);
|
||||
|
||||
Expression::~Expression() {
|
||||
}
|
||||
|
||||
Expression * Expression::parse(char * string) {
|
||||
void * scanner;
|
||||
poincare_expression_yylex_init(&scanner);
|
||||
@@ -16,5 +26,20 @@ Expression * Expression::parse(char * string) {
|
||||
return expression;
|
||||
}
|
||||
|
||||
Expression::~Expression() {
|
||||
Expression * Expression::simplify() {
|
||||
Expression * result = this;
|
||||
expression_simplifier_t * simplifier_pointer = kSimplifiers;
|
||||
while (expression_simplifier_t simplifier = *simplifier_pointer) {
|
||||
Expression * simplification = simplifier(result);
|
||||
if (simplification != nullptr) {
|
||||
if (result != this) {
|
||||
delete result;
|
||||
}
|
||||
result = simplification;
|
||||
}
|
||||
simplifier_pointer++;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,11 @@ float Float::approximate(Context& context) {
|
||||
return m_float;
|
||||
}
|
||||
|
||||
expression_type_t Float::type() {
|
||||
return Float::Type;
|
||||
}
|
||||
|
||||
|
||||
ExpressionLayout * Float::createLayout(ExpressionLayout * parent) {
|
||||
assert(0); // Should not come here, ever...
|
||||
return nullptr;
|
||||
|
||||
@@ -20,3 +20,8 @@ float Fraction::approximate(Context& context) {
|
||||
// TODO: handle division by zero
|
||||
return m_numerator->approximate(context)/m_denominator->approximate(context);
|
||||
}
|
||||
|
||||
expression_type_t Fraction::type() {
|
||||
return Fraction::Type;
|
||||
}
|
||||
|
||||
|
||||
@@ -305,6 +305,10 @@ float Integer::approximate(Context& context) {
|
||||
return float_result;
|
||||
}
|
||||
|
||||
expression_type_t Integer::type() {
|
||||
return Integer::Type;
|
||||
}
|
||||
|
||||
ExpressionLayout * Integer::createLayout(ExpressionLayout * parent) {
|
||||
char buffer[255];
|
||||
|
||||
|
||||
@@ -16,6 +16,11 @@ float Power::approximate(Context& context) {
|
||||
return powf(m_base->approximate(context), m_exponent->approximate(context));
|
||||
}
|
||||
|
||||
expression_type_t Power::type() {
|
||||
return Power::Type;
|
||||
}
|
||||
|
||||
|
||||
ExpressionLayout * Power::createLayout(ExpressionLayout * parent) {
|
||||
return new ExponentLayout(parent, m_base, m_exponent);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,11 @@ float Product::approximate(Context& context) {
|
||||
return m_children[0]->approximate(context) * m_children[1]->approximate(context);
|
||||
}
|
||||
|
||||
expression_type_t Product::type() {
|
||||
return Product::Type;
|
||||
}
|
||||
|
||||
|
||||
ExpressionLayout * Product::createLayout(ExpressionLayout * parent) {
|
||||
return new HorizontalLayout(parent, m_children[0], '*', m_children[1]);
|
||||
}
|
||||
|
||||
8
poincare/src/simplify/simplifier.h
Normal file
8
poincare/src/simplify/simplifier.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#ifndef POINCARE_SIMPLIFIER_H
|
||||
#define POINCARE_SIMPLIFIER_H
|
||||
|
||||
#include <poincare/expression.h>
|
||||
|
||||
typedef Expression * (*expression_simplifier_t)(Expression *);
|
||||
|
||||
#endif
|
||||
20
poincare/src/simplify/simplifier_zero.cpp
Normal file
20
poincare/src/simplify/simplifier_zero.cpp
Normal file
@@ -0,0 +1,20 @@
|
||||
#include "simplifier_zero.h"
|
||||
#include <poincare/product.h>
|
||||
#include <poincare/integer.h>
|
||||
|
||||
Expression * SimplifierZero(Expression * e) {
|
||||
if (e->type() != Product::Type) {
|
||||
return nullptr;
|
||||
}
|
||||
Product * p = (Product *)e;
|
||||
for (int i=0; i<2; i++) {
|
||||
Expression * factor = p->m_children[i];
|
||||
if (factor->type() == Integer::Type) {
|
||||
Integer * integer = (Integer *)factor;
|
||||
if (*integer == Integer((native_int_t)0)) {
|
||||
return new Integer("0");
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
8
poincare/src/simplify/simplifier_zero.h
Normal file
8
poincare/src/simplify/simplifier_zero.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#ifndef POINCARE_SIMPLIFIER_ZERO_H
|
||||
#define POINCARE_SIMPLIFIER_ZERO_H
|
||||
|
||||
#include "simplifier.h"
|
||||
|
||||
Expression * SimplifierZero(Expression * e);
|
||||
|
||||
#endif
|
||||
@@ -15,6 +15,11 @@ float Subtraction::approximate(Context& context) {
|
||||
return m_left->approximate(context) - m_right->approximate(context);
|
||||
}
|
||||
|
||||
expression_type_t Subtraction::type() {
|
||||
return Subtraction::Type;
|
||||
}
|
||||
|
||||
|
||||
ExpressionLayout * Subtraction::createLayout(ExpressionLayout * parent) {
|
||||
return new HorizontalLayout(parent, m_left, '-', m_right);
|
||||
}
|
||||
|
||||
@@ -18,6 +18,10 @@ float Symbol::approximate(Context& context) {
|
||||
return context[m_name]->approximate(context);
|
||||
}
|
||||
|
||||
expression_type_t Symbol::type() {
|
||||
return Symbol::Type;
|
||||
}
|
||||
|
||||
ExpressionLayout * Symbol::createLayout(ExpressionLayout * parent) {
|
||||
size_t length = strlen(m_name);
|
||||
return new StringLayout(parent, m_name, length);
|
||||
|
||||
16
poincare/test/simplify.cpp
Normal file
16
poincare/test/simplify.cpp
Normal file
@@ -0,0 +1,16 @@
|
||||
#include <quiz.h>
|
||||
#include <poincare.h>
|
||||
#include <assert.h>
|
||||
|
||||
QUIZ_CASE(poincare_simplify) {
|
||||
{
|
||||
Expression * e = Expression::parse((char *)"3*0");
|
||||
Expression * e2 = e->simplify();
|
||||
assert(e2->type() == Integer::Type);
|
||||
}
|
||||
{
|
||||
Expression * e = Expression::parse((char *)"0*foo");
|
||||
Expression * e2 = e->simplify();
|
||||
assert(e2->type() == Integer::Type);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user