mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-18 16:27:34 +01:00
[poincare] Enbale to evaluate expression in degrees or radian
Change-Id: I8b08e7fa93431817559a594a1ea03d4414f0c830
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user