[poincare] Enbale to evaluate expression in degrees or radian

Change-Id: I8b08e7fa93431817559a594a1ea03d4414f0c830
This commit is contained in:
Émilie Feral
2017-02-01 16:07:56 +01:00
parent 8d30d3fd0a
commit 42e4cf408d
55 changed files with 211 additions and 193 deletions

View File

@@ -7,8 +7,8 @@ LIBA_BEGIN_DECLS
#define NAN (0.0f/0.0f)
#define INFINITY __builtin_inff()
#define M_E 2.71828182845904523536028747135266250
#define M_PI 3.14159265358979323846264338327950288
#define M_E 2.71828182845904523536028747135266250f
#define M_PI 3.14159265358979323846264338327950288f
/* The C99 standard requires isinf and isnan to be defined as macros that can
* handle arbitrary precision float numbers. The names of the functions called

View File

@@ -6,7 +6,7 @@
class AbsoluteValue : public Function {
public:
AbsoluteValue();
float approximate(Context & context) const override;
float approximate(Context & context, AngleUnit angleUnit = AngleUnit::Radian) const override;
Type type() const override;
Expression * cloneWithDifferentOperands(Expression ** newOperands,
int numberOfOperands, bool cloneOperands = true) const override;

View File

@@ -12,8 +12,8 @@ class Addition : public Expression {
const Expression * operand(int i) const override;
int numberOfOperands() const override;
Type type() const override;
float approximate(Context& context) const override;
Expression * evaluate(Context& context) const override;
float approximate(Context& context, AngleUnit angleUnit = AngleUnit::Radian) const override;
Expression * evaluate(Context& context, AngleUnit angleUnit = AngleUnit::Radian) const override;
Expression * clone() const override;
Expression * cloneWithDifferentOperands(Expression** newOperands,
int numberOfOperands, bool cloneOperands = true) const override;
@@ -21,9 +21,9 @@ class Addition : public Expression {
bool isCommutative() const override;
private:
float operateApproximatevelyOn(float a, float b) const;
Expression * evaluateOn(Expression * a, Expression * b, Context& context) const;
Expression * evaluateOnFloatAndMatrix(Float * a, Matrix * m, Context& context) const;
Expression * evaluateOnMatrices(Matrix * m, Matrix * n, Context& context) const;
Expression * evaluateOn(Expression * a, Expression * b, Context& context, AngleUnit angleUnit) const;
Expression * evaluateOnFloatAndMatrix(Float * a, Matrix * m, Context& context, AngleUnit angleUnit) const;
Expression * evaluateOnMatrices(Matrix * m, Matrix * n, Context& context, AngleUnit angleUnit) const;
const int m_numberOfOperands;
Expression ** m_operands;
};

View File

@@ -12,12 +12,12 @@ class BinaryOperation : public Expression {
const Expression * operand(int i) const override;
int numberOfOperands() const override;
Expression * clone() const override;
Expression * evaluate(Context& context) const override;
Expression * evaluate(Context& context, AngleUnit angleUnit = AngleUnit::Radian) const override;
protected:
Expression * m_operands[2];
virtual Expression * evaluateOnMatrixAndFloat(Matrix * m, Float * f, Context& context) const;
virtual Expression * evaluateOnFloatAndMatrix(Float * f, Matrix * m, Context& context) const;
virtual Expression * evaluateOnMatrices(Matrix * m, Matrix * n, Context& context) const;
virtual Expression * evaluateOnMatrixAndFloat(Matrix * m, Float * f, Context& context, AngleUnit angleUnit) const;
virtual Expression * evaluateOnFloatAndMatrix(Float * f, Matrix * m, Context& context, AngleUnit angleUnit) const;
virtual Expression * evaluateOnMatrices(Matrix * m, Matrix * n, Context& context, AngleUnit angleUnit) const;
};
#endif

View File

@@ -6,7 +6,7 @@
class Cosine : public Function {
public:
Cosine();
float approximate(Context & context) const override;
float approximate(Context & context, AngleUnit angleUnit = AngleUnit::Radian) const override;
Type type() const override;
Expression * cloneWithDifferentOperands(Expression ** newOperands,
int numberOfOperands, bool cloneOperands = true) const override;

View File

@@ -7,13 +7,13 @@
class Derivative : public Function {
public:
Derivative();
float approximate(Context & context) const override;
float approximate(Context & context, AngleUnit angleUnit = AngleUnit::Radian) const override;
Type type() const override;
Expression * cloneWithDifferentOperands(Expression ** newOperands,
int numberOfOperands, bool cloneOperands = true) const override;
private:
float growthRateAroundAbscissa(float x, float h, VariableContext variableContext) const;
float approximateDerivate2(float x, float h, VariableContext xContext) const;
float growthRateAroundAbscissa(float x, float h, VariableContext variableContext, AngleUnit angleUnit) const;
float approximateDerivate2(float x, float h, VariableContext xContext, AngleUnit angleUnit) const;
constexpr static float k_maxErrorRateOnApproximation = 0.001f;
constexpr static float k_minInitialRate = 0.01f;
constexpr static float k_rateStepSize = 1.4f;

View File

@@ -37,6 +37,10 @@ class Expression {
Auto = 0,
Scientific = 1
};
enum class AngleUnit {
Degree = 0,
Radian = 1
};
static Expression * parse(char const * string);
virtual ~Expression();
@@ -80,8 +84,8 @@ class Expression {
virtual bool isCommutative() const;
/* The function evaluate creates a new expression and thus mallocs memory.
* Do not forget to delete the new expression to avoid leaking. */
virtual Expression * evaluate(Context& context) const = 0;
virtual float approximate(Context& context) const = 0;
virtual Expression * evaluate(Context& context, AngleUnit angleUnit = AngleUnit::Radian) const = 0;
virtual float approximate(Context& context, AngleUnit angleUnit = AngleUnit::Radian) const = 0;
virtual int writeTextInBuffer(char * buffer, int bufferSize);
private:
bool sequentialOperandsIdentity(const Expression * e) const;

View File

@@ -11,8 +11,8 @@ public:
const char * exponent, int exponentLength, bool exponentNegative);
ExpressionLayout * createLayout(DisplayMode displayMode = DisplayMode::Auto) const override;
float approximate(Context& context) const override;
Expression * evaluate(Context& context) const override;
float approximate(Context& context, AngleUnit angleUnit = AngleUnit::Radian) const override;
Expression * evaluate(Context& context, AngleUnit angleUnit = AngleUnit::Radian) const override;
Type type() const override;
Expression * clone() const override;
bool valueEquals(const Expression * e) const override;

View File

@@ -9,13 +9,13 @@ class Fraction : public BinaryOperation {
using BinaryOperation::BinaryOperation;
public:
ExpressionLayout * createLayout(DisplayMode displayMode = DisplayMode::Auto) const override;
float approximate(Context& context) const override;
float approximate(Context& context, AngleUnit angleUnit = AngleUnit::Radian) const override;
Type type() const override;
Expression * cloneWithDifferentOperands(Expression** newOperands,
int numnerOfOperands, bool cloneOperands = true) const override;
private:
Expression * evaluateOnMatrixAndFloat(Matrix * m, Float * f, Context& context) const override;
Expression * evaluateOnMatrices(Matrix * m, Matrix * n, Context& context) const override;
Expression * evaluateOnMatrixAndFloat(Matrix * m, Float * f, Context& context, AngleUnit angleUnit) const override;
Expression * evaluateOnMatrices(Matrix * m, Matrix * n, Context& context, AngleUnit angleUnit) const override;
};
#endif

View File

@@ -17,7 +17,7 @@ public:
const Expression * operand(int i) const override;
int numberOfOperands() const override;
Expression * clone() const override;
Expression * evaluate(Context& context) const override;
Expression * evaluate(Context& context, AngleUnit angleUnit = AngleUnit::Radian) const override;
protected:
Expression ** m_args;
int m_numberOfArguments;

View File

@@ -11,6 +11,8 @@ class Integer;
class GlobalContext : public Context {
public:
GlobalContext();
/* The expression recorded in global context is already a final expression.
* Otherwise, we would need the context and the angle unit to evaluate it */
const Expression * expressionForSymbol(const Symbol * symbol) override;
void setExpressionForSymbolName(Expression * expression, const Symbol * symbol) override;
static constexpr uint16_t k_maxNumberOfScalarExpressions = 26;

View File

@@ -32,8 +32,8 @@ class Integer : public LeafExpression {
Expression * clone() const override;
virtual ExpressionLayout * createLayout(DisplayMode displayMode = DisplayMode::Auto) const override;
float approximate(Context& context) const override;
Expression * evaluate(Context& context) const override;
float approximate(Context& context, AngleUnit angleUnit = AngleUnit::Radian) const override;
Expression * evaluate(Context& context, AngleUnit angleUnit = AngleUnit::Radian) const override;
private:
Integer add(const Integer &other, bool inverse_other_negative) const;
int8_t ucmp(const Integer &other) const; // -1, 0, or 1

View File

@@ -7,7 +7,7 @@
class Integral : public Function {
public:
Integral();
float approximate(Context & context) const override;
float approximate(Context & context, AngleUnit angleUnit = AngleUnit::Radian) const override;
Type type() const override;
Expression * cloneWithDifferentOperands(Expression ** newOperands,
int numberOfOperands, bool cloneOperands = true) const override;
@@ -20,12 +20,12 @@ private:
};
constexpr static int k_maxNumberOfIterations = 100;
#ifdef LAGRANGE_METHOD
float lagrangeGaussQuadrature(float a, float b, VariableContext xContext) const;
float lagrangeGaussQuadrature(float a, float b, VariableContext xContext, AngleUnit angleUnit) const;
#else
DetailedResult kronrodGaussQuadrature(float a, float b, VariableContext xContext) const;
float adaptiveQuadrature(float a, float b, float eps, int numberOfIterations, VariableContext xContext) const;
DetailedResult kronrodGaussQuadrature(float a, float b, VariableContext xContext, AngleUnit angleUnit) const;
float adaptiveQuadrature(float a, float b, float eps, int numberOfIterations, VariableContext xContext, AngleUnit angleUnit) const;
#endif
float functionValueAtAbscissa(float x, VariableContext xcontext) const;
float functionValueAtAbscissa(float x, VariableContext xcontext, AngleUnit angleUnit) const;
};
#endif

View File

@@ -6,7 +6,7 @@
class Logarithm : public Function {
public:
Logarithm();
float approximate(Context & context) const override;
float approximate(Context & context, AngleUnit angleUnit = AngleUnit::Radian) const override;
Type type() const override;
Expression * cloneWithDifferentOperands(Expression ** newOperands,
int numberOfOperands, bool cloneOperands = true) const override;

View File

@@ -14,8 +14,8 @@ class Matrix : public Expression {
int numberOfOperands() const override;
Expression * clone() const override;
ExpressionLayout * createLayout(DisplayMode displayMode = DisplayMode::Auto) const override;
float approximate(Context& context) const override;
Expression * evaluate(Context& context) const override;
float approximate(Context& context, AngleUnit angleUnit = AngleUnit::Radian) const override;
Expression * evaluate(Context& context, AngleUnit angleUnit = AngleUnit::Radian) const override;
Type type() const override;
Expression * cloneWithDifferentOperands(Expression** newOperands,
int numberOfOperands, bool cloneOperands = true) const override;

View File

@@ -10,13 +10,13 @@ class Multiplication : public BinaryOperation {
public:
Type type() const override;
ExpressionLayout * createLayout(DisplayMode displayMode = DisplayMode::Auto) const override;
float approximate(Context& context) const override;
float approximate(Context& context, AngleUnit angleUnit = AngleUnit::Radian) const override;
Expression * cloneWithDifferentOperands(Expression** newOperands,
int numnerOfOperands, bool cloneOperands = true) const override;
private:
Expression * evaluateOnMatrixAndFloat(Matrix * m, Float * f, Context& context) const override;
Expression * evaluateOnFloatAndMatrix(Float * f, Matrix * m, Context& context) const override;
Expression * evaluateOnMatrices(Matrix * m, Matrix * n, Context& context) const override;
Expression * evaluateOnMatrixAndFloat(Matrix * m, Float * f, Context& context, AngleUnit angleUnit) const override;
Expression * evaluateOnFloatAndMatrix(Float * f, Matrix * m, Context& context, AngleUnit angleUnit) const override;
Expression * evaluateOnMatrices(Matrix * m, Matrix * n, Context& context, AngleUnit angleUnit) const override;
};
#endif

View File

@@ -6,7 +6,7 @@
class NaperianLogarithm : public Function {
public:
NaperianLogarithm();
float approximate(Context & context) const override;
float approximate(Context & context, AngleUnit angleUnit = AngleUnit::Radian) const override;
Type type() const override;
Expression * cloneWithDifferentOperands(Expression ** newOperands,
int numberOfOperands, bool cloneOperands = true) const override;

View File

@@ -6,7 +6,7 @@
class NthRoot : public Function {
public:
NthRoot();
float approximate(Context & context) const override;
float approximate(Context & context, AngleUnit angleUnit = AngleUnit::Radian) const override;
Type type() const override;
Expression * cloneWithDifferentOperands(Expression ** newOperands,
int numberOfOperands, bool cloneOperands = true) const override;

View File

@@ -12,15 +12,15 @@ class Opposite : public Expression {
const Expression * operand(int i) const override;
int numberOfOperands() const override;
Expression * clone() const override;
Expression * evaluate(Context& context) const override;
Expression * evaluate(Context& context, AngleUnit angleUnit = AngleUnit::Radian) const override;
ExpressionLayout * createLayout(DisplayMode displayMode = DisplayMode::Auto) const override;
float approximate(Context& context) const override;
float approximate(Context& context, AngleUnit angleUnit = AngleUnit::Radian) const override;
Type type() const override;
Expression * cloneWithDifferentOperands(Expression** newOperands,
int numnerOfOperands, bool cloneOperands = true) const override;
protected:
Expression * m_operand;
Expression * evaluateOnMatrix(Matrix * m, Context& context) const;
Expression * evaluateOnMatrix(Matrix * m, Context& context, AngleUnit angleUnit) const;
};
#endif

View File

@@ -11,8 +11,8 @@ class Parenthesis : public Expression {
int numberOfOperands() const override;
Expression * clone() const override;
ExpressionLayout * createLayout(DisplayMode displayMode = DisplayMode::Auto) const override;
float approximate(Context& context) const override;
Expression * evaluate(Context& context) const override;
float approximate(Context& context, AngleUnit angleUnit = AngleUnit::Radian) const override;
Expression * evaluate(Context& context, AngleUnit angleUnit = AngleUnit::Radian) const override;
Type type() const override;
Expression * cloneWithDifferentOperands(Expression** newOperands,
int numnerOfOperands, bool cloneOperands = true) const override;

View File

@@ -10,12 +10,12 @@ class Power : public BinaryOperation {
using BinaryOperation::BinaryOperation;
public:
ExpressionLayout * createLayout(DisplayMode displayMode = DisplayMode::Auto) const override;
float approximate(Context& context) const override;
float approximate(Context& context, AngleUnit angleUnit = AngleUnit::Radian) const override;
Type type() const override;
Expression * cloneWithDifferentOperands(Expression** newOperands,
int numnerOfOperands, bool cloneOperands = true) const override;
private:
Expression * evaluateOnMatrixAndFloat(Matrix * m, Float * a, Context& context) const override;
Expression * evaluateOnMatrixAndFloat(Matrix * m, Float * a, Context& context, AngleUnit angleUnit) const override;
};
#endif

View File

@@ -6,7 +6,7 @@
class Product : public Function {
public:
Product();
float approximate(Context & context) const override;
float approximate(Context & context, AngleUnit angleUnit) const override;
Type type() const override;
Expression * cloneWithDifferentOperands(Expression ** newOperands,
int numberOfOperands, bool cloneOperands = true) const override;

View File

@@ -6,7 +6,7 @@
class Sine : public Function {
public:
Sine();
float approximate(Context & context) const override;
float approximate(Context & context, AngleUnit angleUnit) const override;
Type type() const override;
Expression * cloneWithDifferentOperands(Expression ** newOperands,
int numberOfOperands, bool cloneOperands = true) const override;

View File

@@ -6,7 +6,7 @@
class SquareRoot : public Function {
public:
SquareRoot();
float approximate(Context & context) const override;
float approximate(Context & context, AngleUnit angleUnit) const override;
Type type() const override;
Expression * cloneWithDifferentOperands(Expression ** newOperands,
int numberOfOperands, bool cloneOperands = true) const override;

View File

@@ -10,14 +10,14 @@ class Subtraction : public BinaryOperation {
using BinaryOperation::BinaryOperation;
public:
ExpressionLayout * createLayout(DisplayMode displayMode = DisplayMode::Auto) const override;
float approximate(Context& context) const override;
float approximate(Context& context, AngleUnit angleUnit = AngleUnit::Radian) const override;
Type type() const override;
Expression * cloneWithDifferentOperands(Expression** newOperands,
int numnerOfOperands, bool cloneOperands = true) const override;
private:
Expression * evaluateOnMatrixAndFloat(Matrix * m, Float * f, Context& context) const override;
Expression * evaluateOnFloatAndMatrix(Float * f, Matrix * m, Context& context) const override;
Expression * evaluateOnMatrices(Matrix * m, Matrix * n, Context& context) const override;
Expression * evaluateOnMatrixAndFloat(Matrix * m, Float * f, Context& context, AngleUnit angleUnit) const override;
Expression * evaluateOnFloatAndMatrix(Float * f, Matrix * m, Context& context, AngleUnit angleUnit) const override;
Expression * evaluateOnMatrices(Matrix * m, Matrix * n, Context& context, AngleUnit angleUnit) const override;
};
#endif

View File

@@ -6,7 +6,7 @@
class Sum : public Function {
public:
Sum();
float approximate(Context & context) const override;
float approximate(Context & context, AngleUnit angleUnit) const override;
Type type() const override;
Expression * cloneWithDifferentOperands(Expression ** newOperands,
int numberOfOperands, bool cloneOperands = true) const override;

View File

@@ -10,8 +10,8 @@ public:
};
Symbol(char name);
ExpressionLayout * createLayout(DisplayMode displayMode = DisplayMode::Auto) const override;
float approximate(Context& context) const override;
Expression * evaluate(Context& context) const override;
float approximate(Context& context, AngleUnit angleUnit = AngleUnit::Radian) const override;
Expression * evaluate(Context& context, AngleUnit angleUnit = AngleUnit::Radian) const override;
Type type() const override;
const char name() const;
Expression * clone() const override;

View File

@@ -6,7 +6,7 @@
class Tangent : public Function {
public:
Tangent();
float approximate(Context & context) const override;
float approximate(Context & context, AngleUnit angleUnit) const override;
Type type() const override;
Expression * cloneWithDifferentOperands(Expression ** newOperands,
int numnerOfOperands, bool cloneOperands = true) const override;

View File

@@ -24,8 +24,8 @@ Expression * AbsoluteValue::cloneWithDifferentOperands(Expression** newOperands,
return a;
}
float AbsoluteValue::approximate(Context& context) const {
return fabsf(m_args[0]->approximate(context));
float AbsoluteValue::approximate(Context& context, AngleUnit angleUnit) const {
return fabsf(m_args[0]->approximate(context, angleUnit));
}
ExpressionLayout * AbsoluteValue::createLayout(DisplayMode displayMode) const {

View File

@@ -45,20 +45,20 @@ Expression::Type Addition::type() const {
return Type::Addition;
}
float Addition::approximate(Context& context) const {
float result = m_operands[0]->approximate(context);
float Addition::approximate(Context& context, AngleUnit angleUnit) const {
float result = m_operands[0]->approximate(context, angleUnit);
for (int i=1; i<m_numberOfOperands; i++) {
float next = m_operands[i]->approximate(context);
float next = m_operands[i]->approximate(context, angleUnit);
result = this->operateApproximatevelyOn(result, next);
}
return result;
}
Expression * Addition::evaluate(Context& context) const {
Expression * result = m_operands[0]->evaluate(context);
Expression * Addition::evaluate(Context& context, AngleUnit angleUnit) const {
Expression * result = m_operands[0]->evaluate(context, angleUnit);
for (int i=1; i<m_numberOfOperands; i++) {
Expression * next = m_operands[i]->evaluate(context);
Expression * newResult = this->evaluateOn(result, next, context);
Expression * next = m_operands[i]->evaluate(context, angleUnit);
Expression * newResult = this->evaluateOn(result, next, context, angleUnit);
delete result;
result = newResult;
delete next;
@@ -95,7 +95,7 @@ float Addition::operateApproximatevelyOn(float a, float b) const {
return a + b;
}
Expression * Addition::evaluateOn(Expression * a, Expression * b, Context& context) const {
Expression * Addition::evaluateOn(Expression * a, Expression * b, Context& context, AngleUnit angleUnit) const {
if (a == nullptr || b == nullptr) {
return nullptr;
}
@@ -103,35 +103,35 @@ Expression * Addition::evaluateOn(Expression * a, Expression * b, Context& conte
assert(b->type() == Type::Float || b->type() == Type::Matrix);
Expression * result = nullptr;
if (a->type() == Type::Float && b->type() == Type::Float) {
result = new Float(a->approximate(context) + b->approximate(context));
result = new Float(a->approximate(context, angleUnit) + b->approximate(context, angleUnit));
}
if (a->type() == Type::Float && b->type() == Type::Matrix) {
result = evaluateOnFloatAndMatrix((Float *)a, (Matrix *)b, context);
result = evaluateOnFloatAndMatrix((Float *)a, (Matrix *)b, context, angleUnit);
}
if (b->type() == Type::Float && a->type() == Type::Matrix) {
result = evaluateOnFloatAndMatrix((Float *)b, (Matrix *)a, context);
result = evaluateOnFloatAndMatrix((Float *)b, (Matrix *)a, context, angleUnit);
}
if (b->type() == Type::Matrix && a->type() == Type::Matrix) {
result = evaluateOnMatrices((Matrix *)a, (Matrix *)b, context);
result = evaluateOnMatrices((Matrix *)a, (Matrix *)b, context, angleUnit);
}
return result;
}
Expression * Addition::evaluateOnFloatAndMatrix(Float * a, Matrix * m, Context& context) const {
Expression * Addition::evaluateOnFloatAndMatrix(Float * a, Matrix * m, Context& context, AngleUnit angleUnit) const {
Expression * operands[m->numberOfRows() * m->numberOfColumns()];
for (int i = 0; i < m->numberOfRows() * m->numberOfColumns(); i++) {
operands[i] = new Float(a->approximate(context) + m->operand(i)->approximate(context));
operands[i] = new Float(a->approximate(context, angleUnit) + m->operand(i)->approximate(context, angleUnit));
}
return new Matrix(operands, m->numberOfRows() * m->numberOfColumns(), m->numberOfColumns(), m->numberOfRows(), false);
}
Expression * Addition::evaluateOnMatrices(Matrix * m, Matrix * n, Context& context) const {
Expression * Addition::evaluateOnMatrices(Matrix * m, Matrix * n, Context& context, AngleUnit angleUnit) const {
if (m->numberOfColumns() != n->numberOfColumns() || m->numberOfRows() != n->numberOfRows()) {
return nullptr;
}
Expression * operands[m->numberOfRows() * m->numberOfColumns()];
for (int i = 0; i < m->numberOfRows() * m->numberOfColumns(); i++) {
operands[i] = new Float(m->operand(i)->approximate(context) + n->operand(i)->approximate(context));
operands[i] = new Float(m->operand(i)->approximate(context, angleUnit) + n->operand(i)->approximate(context, angleUnit));
}
return new Matrix(operands, m->numberOfRows() * m->numberOfColumns(), m->numberOfColumns(), m->numberOfRows(), false);
}

View File

@@ -35,38 +35,38 @@ Expression * BinaryOperation::clone() const {
return this->cloneWithDifferentOperands((Expression**) m_operands, 2, true);
}
Expression * BinaryOperation::evaluate(Context& context) const {
Expression * leftOperandEvalutation = m_operands[0]->evaluate(context);
Expression * rightOperandEvalutation = m_operands[1]->evaluate(context);
Expression * BinaryOperation::evaluate(Context& context, AngleUnit angleUnit) const {
Expression * leftOperandEvalutation = m_operands[0]->evaluate(context, angleUnit);
Expression * rightOperandEvalutation = m_operands[1]->evaluate(context, angleUnit);
if (leftOperandEvalutation == nullptr || rightOperandEvalutation == nullptr) {
return nullptr;
}
Expression * result = nullptr;
if (leftOperandEvalutation->type() == Type::Float && rightOperandEvalutation->type() == Type::Float) {
result = new Float(this->approximate(context));
result = new Float(this->approximate(context, angleUnit));
}
if (leftOperandEvalutation->type() == Type::Matrix && rightOperandEvalutation->type() == Type::Float) {
result = evaluateOnMatrixAndFloat((Matrix *)leftOperandEvalutation, (Float *)rightOperandEvalutation, context);
result = evaluateOnMatrixAndFloat((Matrix *)leftOperandEvalutation, (Float *)rightOperandEvalutation, context, angleUnit);
}
if (leftOperandEvalutation->type() == Type::Float && rightOperandEvalutation->type() == Type::Matrix) {
result = evaluateOnFloatAndMatrix((Float *)leftOperandEvalutation, (Matrix *)rightOperandEvalutation, context);
result = evaluateOnFloatAndMatrix((Float *)leftOperandEvalutation, (Matrix *)rightOperandEvalutation, context, angleUnit);
}
if (leftOperandEvalutation->type() == Type::Matrix && rightOperandEvalutation->type() == Type::Matrix) {
result = evaluateOnMatrices((Matrix *)leftOperandEvalutation, (Matrix *)rightOperandEvalutation, context);
result = evaluateOnMatrices((Matrix *)leftOperandEvalutation, (Matrix *)rightOperandEvalutation, context, angleUnit);
}
delete leftOperandEvalutation;
delete rightOperandEvalutation;
return result;
}
Expression * BinaryOperation::evaluateOnMatrixAndFloat(Matrix * m, Float * a, Context& context) const {
Expression * BinaryOperation::evaluateOnMatrixAndFloat(Matrix * m, Float * a, Context& context, AngleUnit angleUnit) const {
return nullptr;
}
Expression * BinaryOperation::evaluateOnFloatAndMatrix(Float * a, Matrix * m, Context& context) const {
Expression * BinaryOperation::evaluateOnFloatAndMatrix(Float * a, Matrix * m, Context& context, AngleUnit angleUnit) const {
return nullptr;
}
Expression * BinaryOperation::evaluateOnMatrices(Matrix * m, Matrix * n, Context& context) const {
Expression * BinaryOperation::evaluateOnMatrices(Matrix * m, Matrix * n, Context& context, AngleUnit angleUnit) const {
return nullptr;
}

View File

@@ -23,6 +23,9 @@ Expression * Cosine::cloneWithDifferentOperands(Expression** newOperands,
return c;
}
float Cosine::approximate(Context& context) const {
return cosf(m_args[0]->approximate(context));
float Cosine::approximate(Context& context, AngleUnit angleUnit) const {
if (angleUnit == AngleUnit::Degree) {
return cosf(m_args[0]->approximate(context, angleUnit)*M_PI/180.0f);
}
return cosf(m_args[0]->approximate(context, angleUnit));
}

View File

@@ -26,13 +26,13 @@ Expression * Derivative::cloneWithDifferentOperands(Expression** newOperands,
return d;
}
float Derivative::approximate(Context& context) const {
float Derivative::approximate(Context& context, AngleUnit angleUnit) const {
VariableContext xContext = VariableContext('x', &context);
Symbol xSymbol = Symbol('x');
float x = m_args[1]->approximate(context);
float x = m_args[1]->approximate(context, angleUnit);
Float e = Float(x);
xContext.setExpressionForSymbolName(&e, &xSymbol);
float functionValue = m_args[0]->approximate(xContext);
float functionValue = m_args[0]->approximate(xContext, angleUnit);
/* Ridders' Algorithm
* Blibliography:
@@ -43,7 +43,7 @@ float Derivative::approximate(Context& context) const {
// Initiate hh
float h = fabsf(x) < FLT_MIN ? k_minInitialRate : x/1000.0f;
float f2 = approximateDerivate2(x, h, xContext);
float f2 = approximateDerivate2(x, h, xContext, angleUnit);
f2 = fabsf(f2) < FLT_MIN ? k_minInitialRate : f2;
float hh = sqrtf(fabsf(functionValue/(f2/(powf(h,2.0f)))))/10.0f;
hh = fabsf(hh) <FLT_MIN ? k_minInitialRate : hh;
@@ -58,7 +58,7 @@ float Derivative::approximate(Context& context) const {
a[i][j] = 1.0f;
}
}
a[0][0] = growthRateAroundAbscissa(x, hh, xContext);
a[0][0] = growthRateAroundAbscissa(x, hh, xContext, angleUnit);
float err = FLT_MAX;
float ans = 0.0f;
float errt = 0.0f;
@@ -68,7 +68,7 @@ float Derivative::approximate(Context& context) const {
/* Make hh an exactly representable number */
volatile float temp = x+hh;
hh = temp - x;
a[0][i] = growthRateAroundAbscissa(x, hh, xContext);
a[0][i] = growthRateAroundAbscissa(x, hh, xContext, angleUnit);
float fac = k_rateStepSize*k_rateStepSize;
/* Loop on j: compute extrapolation for several orders */
for (int j = 1; j < 10; j++) {
@@ -98,27 +98,27 @@ float Derivative::approximate(Context& context) const {
return roundf(ans/err)*err;
}
float Derivative::growthRateAroundAbscissa(float x, float h, VariableContext xContext) const {
float Derivative::growthRateAroundAbscissa(float x, float h, VariableContext xContext, AngleUnit angleUnit) const {
Symbol xSymbol = Symbol('x');
Float e = Float(x + h);
xContext.setExpressionForSymbolName(&e, &xSymbol);
float expressionPlus = m_args[0]->approximate(xContext);
float expressionPlus = m_args[0]->approximate(xContext, angleUnit);
e = Float(x-h);
xContext.setExpressionForSymbolName(&e, &xSymbol);
float expressionMinus = m_args[0]->approximate(xContext);
float expressionMinus = m_args[0]->approximate(xContext, angleUnit);
return (expressionPlus - expressionMinus)/(2*h);
}
float Derivative::approximateDerivate2(float x, float h, VariableContext xContext) const {
float Derivative::approximateDerivate2(float x, float h, VariableContext xContext, AngleUnit angleUnit) const {
Symbol xSymbol = Symbol('x');
Float e = Float(x + h);
xContext.setExpressionForSymbolName(&e, &xSymbol);
float expressionPlus = m_args[0]->approximate(xContext);
float expressionPlus = m_args[0]->approximate(xContext, angleUnit);
e = Float(x);
xContext.setExpressionForSymbolName(&e, &xSymbol);
float expression = m_args[0]->approximate(xContext);
float expression = m_args[0]->approximate(xContext, angleUnit);
e = Float(x-h);
xContext.setExpressionForSymbolName(&e, &xSymbol);
float expressionMinus = m_args[0]->approximate(xContext);
float expressionMinus = m_args[0]->approximate(xContext, angleUnit);
return expressionPlus - 2.0f*expression + expressionMinus;
}

View File

@@ -53,11 +53,11 @@ Expression * Float::clone() const {
return new Float(m_float);
}
float Float::approximate(Context& context) const {
float Float::approximate(Context& context, AngleUnit angleUnit) const {
return m_float;
}
Expression * Float::evaluate(Context& context) const {
Expression * Float::evaluate(Context& context, AngleUnit angleUnit) const {
return clone();
}

View File

@@ -17,25 +17,25 @@ ExpressionLayout * Fraction::createLayout(DisplayMode displayMode) const {
return new FractionLayout(m_operands[0]->createLayout(displayMode), m_operands[1]->createLayout(displayMode));
}
float Fraction::approximate(Context& context) const {
float Fraction::approximate(Context& context, AngleUnit angleUnit) const {
// TODO: handle division by zero
return m_operands[0]->approximate(context)/m_operands[1]->approximate(context);
return m_operands[0]->approximate(context, angleUnit)/m_operands[1]->approximate(context, angleUnit);
}
Expression::Type Fraction::type() const {
return Type::Fraction;
}
Expression * Fraction::evaluateOnMatrixAndFloat(Matrix * m, Float * a, Context& context) const {
Expression * Fraction::evaluateOnMatrixAndFloat(Matrix * m, Float * a, Context& context, AngleUnit angleUnit) const {
Expression * operands[m->numberOfRows() * m->numberOfColumns()];
for (int i = 0; i < m->numberOfRows() * m->numberOfColumns(); i++) {
operands[i] = new Float(m->operand(i)->approximate(context)/a->approximate(context));
operands[i] = new Float(m->operand(i)->approximate(context, angleUnit)/a->approximate(context, angleUnit));
}
Expression * result = new Matrix(operands, m->numberOfRows() * m->numberOfColumns(), m->numberOfColumns(), m->numberOfRows(), false);
return result;
}
Expression * Fraction::evaluateOnMatrices(Matrix * m, Matrix * n, Context& context) const {
Expression * Fraction::evaluateOnMatrices(Matrix * m, Matrix * n, Context& context, AngleUnit angleUnit) const {
if (m->numberOfColumns() != n->numberOfColumns()) {
return nullptr;
}

View File

@@ -89,6 +89,6 @@ int Function::numberOfOperands() const {
return m_numberOfArguments;
}
Expression * Function::evaluate(Context& context) const {
return new Float(approximate(context));
Expression * Function::evaluate(Context& context, AngleUnit angleUnit) const {
return new Float(approximate(context, angleUnit));
}

View File

@@ -41,5 +41,6 @@ const Expression * GlobalContext::expressionForSymbol(const Symbol * symbol) {
void GlobalContext::setExpressionForSymbolName(Expression * expression, const Symbol * symbol) {
int index = symbolIndex(symbol);
assert(expression->type() == Expression::Type::Float);
m_expressions[index] = expression;
}

View File

@@ -257,7 +257,7 @@ Expression * Integer::clone() const {
return clone;
}
float Integer::approximate(Context& context) const {
float Integer::approximate(Context& context, AngleUnit angleUnit) const {
union {
uint32_t uint_result;
float float_result;
@@ -308,8 +308,8 @@ float Integer::approximate(Context& context) const {
return float_result;
}
Expression * Integer::evaluate(Context& context) const {
return new Float(approximate(context));
Expression * Integer::evaluate(Context& context, AngleUnit angleUnit) const {
return new Float(approximate(context, angleUnit));
}
Expression::Type Integer::type() const {

View File

@@ -30,14 +30,14 @@ Expression * Integral::cloneWithDifferentOperands(Expression** newOperands,
return i;
}
float Integral::approximate(Context& context) const {
float Integral::approximate(Context& context, AngleUnit angleUnit) const {
VariableContext xContext = VariableContext('x', &context);
float a = m_args[1]->approximate(context);
float b = m_args[2]->approximate(context);
float a = m_args[1]->approximate(context, angleUnit);
float b = m_args[2]->approximate(context, angleUnit);
#ifdef LAGRANGE_METHOD
return lagrangeGaussQuadrature(a, b, xContext);
return lagrangeGaussQuadrature(a, b, xContext, angleUnit);
#else
return adaptiveQuadrature(a, b, 0.1, k_maxNumberOfIterations,xContext);
return adaptiveQuadrature(a, b, 0.1, k_maxNumberOfIterations, xContext, angleUnit);
#endif
}
@@ -48,16 +48,16 @@ ExpressionLayout * Integral::createLayout(DisplayMode displayMode) const {
return new IntegralLayout(m_args[1]->createLayout(displayMode), m_args[2]->createLayout(displayMode), new HorizontalLayout(childrenLayouts, 2));
}
float Integral::functionValueAtAbscissa(float x, VariableContext xContext) const {
float Integral::functionValueAtAbscissa(float x, VariableContext xContext, AngleUnit angleUnit) const {
Float e = Float(x);
Symbol xSymbol = Symbol('x');
xContext.setExpressionForSymbolName(&e, &xSymbol);
return m_args[0]->approximate(xContext);
return m_args[0]->approximate(xContext, angleUnit);
}
#ifdef LAGRANGE_METHOD
float Integral::lagrangeGaussQuadrature(float a, float b, VariableContext xContext) const {
float Integral::lagrangeGaussQuadrature(float a, float b, VariableContext xContext, AngleUnit angleUnit) const {
/* We here use Gauss-Legendre quadrature with n = 5
* Gauss-Legendre abscissae and weights taken from
* http://www.holoborodko.com/pavel/numerical-methods/numerical-integration/*/
@@ -71,7 +71,7 @@ float Integral::lagrangeGaussQuadrature(float a, float b, VariableContext xConte
float result = 0.0f;
for (int j = 0; j < 10; j++) {
float dx = xr * x[j];
result += w[j]*(functionValueAtAbscissa(xm+dx, xContext) + functionValueAtAbscissa(xm-dx, xContext));
result += w[j]*(functionValueAtAbscissa(xm+dx, xContext, angleUnit) + functionValueAtAbscissa(xm-dx, xContext, angleUnit));
}
result *= xr;
return result;
@@ -79,7 +79,7 @@ float Integral::lagrangeGaussQuadrature(float a, float b, VariableContext xConte
#else
Integral::DetailedResult Integral::kronrodGaussQuadrature(float a, float b, VariableContext xContext) const {
Integral::DetailedResult Integral::kronrodGaussQuadrature(float a, float b, VariableContext xContext, AngleUnit angleUnit) const {
/* We here use Kronrod-Legendre quadrature with n = 21
* The abscissa and weights are taken from QUADPACK library. */
const static float wg[5]= {0.066671344308688137593568809893332f, 0.149451349150580593145776339657697f,
@@ -100,14 +100,14 @@ Integral::DetailedResult Integral::kronrodGaussQuadrature(float a, float b, Vari
float dhlgth = fabsf(hlgth);
float resg =0.0f;
float fc = functionValueAtAbscissa(centr, xContext);
float fc = functionValueAtAbscissa(centr, xContext, angleUnit);
float resk = wgk[10]*fc;
float resabs = fabsf(resk);
for (int j = 0; j < 5; j++) {
int jtw = 2*j+1;
float absc = hlgth*xgk[jtw];
float fval1 = functionValueAtAbscissa(centr-absc, xContext);
float fval2 = functionValueAtAbscissa(centr+absc, xContext);
float fval1 = functionValueAtAbscissa(centr-absc, xContext, angleUnit);
float fval2 = functionValueAtAbscissa(centr+absc, xContext, angleUnit);
fv1[jtw] = fval1;
fv2[jtw] = fval2;
float fsum = fval1+fval2;
@@ -118,8 +118,8 @@ Integral::DetailedResult Integral::kronrodGaussQuadrature(float a, float b, Vari
for (int j = 0; j < 5; j++) {
int jtwm1 = 2*j;
float absc = hlgth*xgk[jtwm1];
float fval1 = functionValueAtAbscissa(centr-absc, xContext);
float fval2 = functionValueAtAbscissa(centr+absc, xContext);
float fval1 = functionValueAtAbscissa(centr-absc, xContext, angleUnit);
float fval2 = functionValueAtAbscissa(centr+absc, xContext, angleUnit);
fv1[jtwm1] = fval1;
fv2[jtwm1] = fval2;
float fsum = fval1+fval2;
@@ -147,12 +147,12 @@ Integral::DetailedResult Integral::kronrodGaussQuadrature(float a, float b, Vari
return result;
}
float Integral::adaptiveQuadrature(float a, float b, float eps, int numberOfIterations, VariableContext xContext) const {
DetailedResult quadKG = kronrodGaussQuadrature(a, b, xContext);
float Integral::adaptiveQuadrature(float a, float b, float eps, int numberOfIterations, VariableContext xContext, AngleUnit angleUnit) const {
DetailedResult quadKG = kronrodGaussQuadrature(a, b, xContext, angleUnit);
float result = quadKG.integral;
if (numberOfIterations < k_maxNumberOfIterations && quadKG.absoluteError > eps) {
float m = (a+b)/2.0f;
result = adaptiveQuadrature(a, m, eps/2.0f, numberOfIterations+1, xContext) + adaptiveQuadrature(m, b, eps/2.0f, numberOfIterations+1, xContext);
result = adaptiveQuadrature(a, m, eps/2.0f, numberOfIterations+1, xContext, angleUnit) + adaptiveQuadrature(m, b, eps/2.0f, numberOfIterations+1, xContext, angleUnit);
}
if (quadKG.absoluteError > eps) {
return NAN;

View File

@@ -27,11 +27,11 @@ Expression * Logarithm::cloneWithDifferentOperands(Expression** newOperands,
return l;
}
float Logarithm::approximate(Context& context) const {
float Logarithm::approximate(Context& context, AngleUnit angleUnit) const {
if (m_numberOfArguments == 1) {
return log10f(m_args[0]->approximate(context));
return log10f(m_args[0]->approximate(context, angleUnit));
}
return log10f(m_args[1]->approximate(context))/log10f(m_args[0]->approximate(context));
return log10f(m_args[1]->approximate(context, angleUnit))/log10f(m_args[0]->approximate(context, angleUnit));
}
ExpressionLayout * Logarithm::createLayout(DisplayMode displayMode) const {

View File

@@ -49,14 +49,14 @@ ExpressionLayout * Matrix::createLayout(DisplayMode displayMode) const {
return new MatrixLayout(childrenLayouts, numberOfRows(), numberOfColumns());
}
float Matrix::approximate(Context& context) const {
float Matrix::approximate(Context& context, AngleUnit angleUnit) const {
return NAN;
}
Expression * Matrix::evaluate(Context& context) const {
Expression * Matrix::evaluate(Context& context, AngleUnit angleUnit) const {
Expression * operands[numberOfOperands()];
for (int i = 0; i < numberOfOperands(); i++) {
operands[i] = new Float(operand(i)->approximate(context));
operands[i] = new Float(operand(i)->approximate(context, angleUnit));
}
return new Matrix(new MatrixData(operands, numberOfOperands(), numberOfColumns(), numberOfRows(), false));
}

View File

@@ -20,8 +20,8 @@ ExpressionLayout * Multiplication::createLayout(DisplayMode displayMode) const {
return new HorizontalLayout(children_layouts, 3);
}
float Multiplication::approximate(Context& context) const {
return m_operands[0]->approximate(context)*m_operands[1]->approximate(context);;
float Multiplication::approximate(Context& context, AngleUnit angleUnit) const {
return m_operands[0]->approximate(context, angleUnit)*m_operands[1]->approximate(context, angleUnit);;
}
Expression * Multiplication::cloneWithDifferentOperands(Expression** newOperands,
@@ -31,19 +31,19 @@ Expression * Multiplication::cloneWithDifferentOperands(Expression** newOperands
return new Multiplication(newOperands, cloneOperands);
}
Expression * Multiplication::evaluateOnMatrixAndFloat(Matrix * m, Float * a, Context& context) const {
Expression * Multiplication::evaluateOnMatrixAndFloat(Matrix * m, Float * a, Context& context, AngleUnit angleUnit) const {
Expression * operands[m->numberOfRows() * m->numberOfColumns()];
for (int i = 0; i < m->numberOfRows() * m->numberOfColumns(); i++) {
operands[i] = new Float(m->operand(i)->approximate(context)*a->approximate(context));
operands[i] = new Float(m->operand(i)->approximate(context, angleUnit)*a->approximate(context, angleUnit));
}
return new Matrix(operands, m->numberOfRows() * m->numberOfColumns(), m->numberOfColumns(), m->numberOfRows(), false);
}
Expression * Multiplication::evaluateOnFloatAndMatrix(Float * a, Matrix * m, Context& context) const {
return evaluateOnMatrixAndFloat(m, a, context);
Expression * Multiplication::evaluateOnFloatAndMatrix(Float * a, Matrix * m, Context& context, AngleUnit angleUnit) const {
return evaluateOnMatrixAndFloat(m, a, context, angleUnit);
}
Expression * Multiplication::evaluateOnMatrices(Matrix * m, Matrix * n, Context& context) const {
Expression * Multiplication::evaluateOnMatrices(Matrix * m, Matrix * n, Context& context, AngleUnit angleUnit) const {
if (m->numberOfColumns() != n->numberOfRows()) {
return nullptr;
}
@@ -52,7 +52,7 @@ Expression * Multiplication::evaluateOnMatrices(Matrix * m, Matrix * n, Context&
for (int j = 0; j < n->numberOfColumns(); j++) {
float f = 0.0f;
for (int k = 0; k < m->numberOfColumns(); k++) {
f += m->operand(i*m->numberOfColumns()+k)->approximate(context) * n->operand(k*n->numberOfColumns()+j)->approximate(context);
f += m->operand(i*m->numberOfColumns()+k)->approximate(context, angleUnit) * n->operand(k*n->numberOfColumns()+j)->approximate(context, angleUnit);
}
operands[i*n->numberOfColumns()+j] = new Float(f);
}

View File

@@ -26,6 +26,6 @@ Expression * NaperianLogarithm::cloneWithDifferentOperands(Expression** newOpera
return l;
}
float NaperianLogarithm::approximate(Context& context) const {
return log10f(m_args[0]->approximate(context))/log10f(M_E);
float NaperianLogarithm::approximate(Context& context, AngleUnit angleUnit) const {
return log10f(m_args[0]->approximate(context, angleUnit))/log10f(M_E);
}

View File

@@ -24,8 +24,8 @@ Expression * NthRoot::cloneWithDifferentOperands(Expression** newOperands,
return r;
}
float NthRoot::approximate(Context& context) const {
return powf(m_args[0]->approximate(context), 1.0f/m_args[1]->approximate(context));
float NthRoot::approximate(Context& context, AngleUnit angleUnit) const {
return powf(m_args[0]->approximate(context, angleUnit), 1.0f/m_args[1]->approximate(context, angleUnit));
}
ExpressionLayout * NthRoot::createLayout(DisplayMode displayMode) const {

View File

@@ -33,17 +33,17 @@ Expression * Opposite::clone() const {
return this->cloneWithDifferentOperands((Expression**)&m_operand, 1, true);
}
Expression * Opposite::evaluate(Context& context) const {
Expression * operandEvalutation = m_operand->evaluate(context);
Expression * Opposite::evaluate(Context& context, AngleUnit angleUnit) const {
Expression * operandEvalutation = m_operand->evaluate(context, angleUnit);
if (operandEvalutation == nullptr) {
return nullptr;
}
Expression * result = nullptr;
if (operandEvalutation->type() == Type::Float) {
result = new Float(this->approximate(context));
result = new Float(this->approximate(context, angleUnit));
}
if (operandEvalutation->type() == Type::Matrix) {
result = evaluateOnMatrix((Matrix *)operandEvalutation, context);
result = evaluateOnMatrix((Matrix *)operandEvalutation, context, angleUnit);
}
delete operandEvalutation;
return result;
@@ -57,8 +57,8 @@ ExpressionLayout * Opposite::createLayout(DisplayMode displayMode) const {
return new HorizontalLayout(children_layouts, 2);
}
float Opposite::approximate(Context& context) const {
return -m_operand->approximate(context);
float Opposite::approximate(Context& context, AngleUnit angleUnit) const {
return -m_operand->approximate(context, angleUnit);
}
Expression::Type Opposite::type() const {
@@ -72,10 +72,10 @@ Expression * Opposite::cloneWithDifferentOperands(Expression** newOperands,
return new Opposite(newOperands[0], cloneOperands);
}
Expression * Opposite::evaluateOnMatrix(Matrix * m, Context& context) const {
Expression * Opposite::evaluateOnMatrix(Matrix * m, Context& context, AngleUnit angleUnit) const {
Expression * operands[m->numberOfRows() * m->numberOfColumns()];
for (int i = 0; i < m->numberOfRows() * m->numberOfColumns(); i++) {
operands[i] = new Float(- m->operand(i)->approximate(context));
operands[i] = new Float(- m->operand(i)->approximate(context, angleUnit));
}
return new Matrix(operands, m->numberOfRows() * m->numberOfColumns(), m->numberOfColumns(), m->numberOfRows(), false);
}

View File

@@ -35,12 +35,12 @@ ExpressionLayout * Parenthesis::createLayout(DisplayMode displayMode) const {
return new ParenthesisLayout(m_operand->createLayout(displayMode));
}
float Parenthesis::approximate(Context& context) const {
return m_operand->approximate(context);
float Parenthesis::approximate(Context& context, AngleUnit angleUnit) const {
return m_operand->approximate(context, angleUnit);
}
Expression * Parenthesis::evaluate(Context& context) const {
return m_operand->evaluate(context);
Expression * Parenthesis::evaluate(Context& context, AngleUnit angleUnit) const {
return m_operand->evaluate(context, angleUnit);
}
Expression::Type Parenthesis::type() const {

View File

@@ -6,11 +6,11 @@ extern "C" {
#include <poincare/multiplication.h>
#include "layout/baseline_relative_layout.h"
float Power::approximate(Context& context) const {
return powf(m_operands[0]->approximate(context), m_operands[1]->approximate(context));
float Power::approximate(Context& context, AngleUnit angleUnit) const {
return powf(m_operands[0]->approximate(context, angleUnit), m_operands[1]->approximate(context, angleUnit));
}
Expression * Power::evaluateOnMatrixAndFloat(Matrix * m, Float * a, Context& context) const {
Expression * Power::evaluateOnMatrixAndFloat(Matrix * m, Float * a, Context& context, AngleUnit angleUnit) const {
if (m_operands[1]->type() != Expression::Type::Integer) {
return nullptr;
}
@@ -18,14 +18,14 @@ Expression * Power::evaluateOnMatrixAndFloat(Matrix * m, Float * a, Context& con
return nullptr;
}
// TODO: return identity matrix if i == 0
int power = a->approximate(context);
int power = a->approximate(context, angleUnit);
Expression * result = new Float(1);
for (int k = 0; k < power; k++) {
Expression * operands[2];
operands[0] = result;
operands[1] = m;
Expression * multiplication = new Multiplication(operands, true);
Expression * newResult = multiplication->evaluate(context);
Expression * newResult = multiplication->evaluate(context, angleUnit);
delete result;
result = newResult;
delete multiplication;

View File

@@ -28,16 +28,16 @@ Expression * Product::cloneWithDifferentOperands(Expression** newOperands,
return p;
}
float Product::approximate(Context& context) const {
float Product::approximate(Context& context, AngleUnit angleUnit) const {
VariableContext nContext = VariableContext('n', &context);
Symbol nSymbol = Symbol('n');
int start = m_args[1]->approximate(context);
int end = m_args[2]->approximate(context);
int start = m_args[1]->approximate(context, angleUnit);
int end = m_args[2]->approximate(context, angleUnit);
float result = 1.0f;
for (int i = start; i <= end; i++) {
Float iExpression = Float(i);
nContext.setExpressionForSymbolName(&iExpression, &nSymbol);
result = result*m_args[0]->approximate(nContext);
result = result*m_args[0]->approximate(nContext, angleUnit);
}
return result;
}

View File

@@ -23,6 +23,9 @@ Expression::Type Sine::type() const {
return Expression::Type::Sine;
}
float Sine::approximate(Context& context) const {
return sinf(m_args[0]->approximate(context));
float Sine::approximate(Context& context, AngleUnit angleUnit) const {
if (angleUnit == AngleUnit::Degree) {
return sinf(m_args[0]->approximate(context, angleUnit)*M_PI/180.0f);
}
return sinf(m_args[0]->approximate(context, angleUnit));
}

View File

@@ -24,8 +24,8 @@ Expression * SquareRoot::cloneWithDifferentOperands(Expression** newOperands,
return sr;
}
float SquareRoot::approximate(Context& context) const {
return powf(m_args[0]->approximate(context), 1.0f/2.0f);
float SquareRoot::approximate(Context& context, AngleUnit angleUnit) const {
return powf(m_args[0]->approximate(context, angleUnit), 1.0f/2.0f);
}
ExpressionLayout * SquareRoot::createLayout(DisplayMode displayMode) const {

View File

@@ -15,8 +15,8 @@ Expression * Subtraction::cloneWithDifferentOperands(Expression** newOperands,
return new Subtraction(newOperands, cloneOperands);
}
float Subtraction::approximate(Context& context) const {
return m_operands[0]->approximate(context) - m_operands[1]->approximate(context);
float Subtraction::approximate(Context& context, AngleUnit angleUnit) const {
return m_operands[0]->approximate(context, angleUnit) - m_operands[1]->approximate(context, angleUnit);
}
Expression::Type Subtraction::type() const {
@@ -32,32 +32,32 @@ ExpressionLayout * Subtraction::createLayout(DisplayMode displayMode) const {
return new HorizontalLayout(children_layouts, 3);
}
Expression * Subtraction::evaluateOnMatrixAndFloat(Matrix * m, Float * a, Context& context) const {
Expression * Subtraction::evaluateOnMatrixAndFloat(Matrix * m, Float * a, Context& context, AngleUnit angleUnit) const {
Expression * operands[m->numberOfRows() * m->numberOfColumns()];
for (int i = 0; i < m->numberOfRows() * m->numberOfColumns(); i++) {
operands[i] = new Float(m->operand(i)->approximate(context) - a->approximate(context));
operands[i] = new Float(m->operand(i)->approximate(context, angleUnit) - a->approximate(context, angleUnit));
}
return new Matrix(operands, m->numberOfRows() * m->numberOfColumns(), m->numberOfColumns(), m->numberOfRows(), false);
}
Expression * Subtraction::evaluateOnFloatAndMatrix(Float * a, Matrix * m, Context& context) const {
Expression * Subtraction::evaluateOnFloatAndMatrix(Float * a, Matrix * m, Context& context, AngleUnit angleUnit) const {
Expression * operands[m->numberOfRows() * m->numberOfColumns()];
for (int i = 0; i < m->numberOfRows() * m->numberOfColumns(); i++) {
operands[i] = new Float(a->approximate(context) - m->operand(i)->approximate(context));
operands[i] = new Float(a->approximate(context, angleUnit) - m->operand(i)->approximate(context, angleUnit));
}
return new Matrix(operands, m->numberOfRows() * m->numberOfColumns(), m->numberOfColumns(), m->numberOfRows(), false);
}
Expression * Subtraction::evaluateOnMatrices(Matrix * m, Matrix * n, Context& context) const {
Expression * Subtraction::evaluateOnMatrices(Matrix * m, Matrix * n, Context& context, AngleUnit angleUnit) const {
if (m->numberOfColumns() != n->numberOfColumns() || m->numberOfRows() != n->numberOfRows()) {
return nullptr;
}
Expression * operands[m->numberOfRows() * m->numberOfColumns()];
for (int i = 0; i < m->numberOfRows() * m->numberOfColumns(); i++) {
if (!m->operand(i)->approximate(context) || !n->operand(i)->approximate(context)) {
if (!m->operand(i)->approximate(context, angleUnit) || !n->operand(i)->approximate(context, angleUnit)) {
return nullptr;
}
operands[i] = new Float(m->operand(i)->approximate(context) - n->operand(i)->approximate(context));
operands[i] = new Float(m->operand(i)->approximate(context, angleUnit) - n->operand(i)->approximate(context, angleUnit));
}
return new Matrix(operands, m->numberOfRows() * m->numberOfColumns(), m->numberOfColumns(), m->numberOfRows(), false);
}

View File

@@ -28,16 +28,16 @@ Expression * Sum::cloneWithDifferentOperands(Expression** newOperands,
return s;
}
float Sum::approximate(Context& context) const {
float Sum::approximate(Context& context, AngleUnit angleUnit) const {
VariableContext nContext = VariableContext('n', &context);
Symbol nSymbol = Symbol('n');
int start = m_args[1]->approximate(context);
int end = m_args[2]->approximate(context);
int start = m_args[1]->approximate(context, angleUnit);
int end = m_args[2]->approximate(context, angleUnit);
float result = 0.0f;
for (int i = start; i <= end; i++) {
Float iExpression = Float(i);
nContext.setExpressionForSymbolName(&iExpression, &nSymbol);
result += m_args[0]->approximate(nContext);
result += m_args[0]->approximate(nContext, angleUnit);
}
return result;
}

View File

@@ -11,16 +11,16 @@ Symbol::Symbol(char name) :
{
}
float Symbol::approximate(Context& context) const {
float Symbol::approximate(Context& context, AngleUnit angleUnit) const {
if (context.expressionForSymbol(this)) {
return context.expressionForSymbol(this)->approximate(context);
return context.expressionForSymbol(this)->approximate(context, angleUnit);
}
// TODO: decide with Leo what we should return
return NAN;
}
Expression * Symbol::evaluate(Context& context) const {
return context.expressionForSymbol(this)->evaluate(context);
Expression * Symbol::evaluate(Context& context, AngleUnit angleUnit) const {
return context.expressionForSymbol(this)->evaluate(context, angleUnit);
}
Expression::Type Symbol::type() const {

View File

@@ -23,6 +23,9 @@ Expression::Type Tangent::type() const {
return Expression::Type::Tangent;
}
float Tangent::approximate(Context& context) const {
return tanf(m_args[0]->approximate(context));
float Tangent::approximate(Context& context, AngleUnit angleUnit) const {
if (angleUnit == AngleUnit::Degree) {
return tanf(m_args[0]->approximate(context, angleUnit)*M_PI/180.0f);
}
return tanf(m_args[0]->approximate(context, angleUnit));
}

View File

@@ -9,6 +9,8 @@ VariableContext::VariableContext(char name, ::Context * parentContext) :
void VariableContext::setExpressionForSymbolName(Expression * expression, const Symbol * symbol) {
if (symbol->name() == m_name) {
/* WARNING: we here assume that the expression does not content any function
* whose evaluation depends on the angle unit */
m_value = Float(expression->approximate(*m_parentContext));
} else {
m_parentContext->setExpressionForSymbolName(expression, symbol);