mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-18 21:30:38 +01:00
Merge changes Ic3151274,I44131774,I2afed196,Ib903a31d,I74cad802
* changes: [apps] Fix bug: display 'n' when clicking on XNT in sum and product function [poincare] Add comments to integral approximation for future improvements [poincare] Create a first version of a class integral (approx method is to be improved with QUADPACK algo) [poincare] Create a class opposite [poincare] Add a class exponential
This commit is contained in:
@@ -9,13 +9,16 @@ const char * ExpressionTextFieldDelegate::XNT() {
|
||||
|
||||
bool ExpressionTextFieldDelegate::cursorInToken(TextField * textField, const char * token) {
|
||||
const char * text = textField->text();
|
||||
int cursorLocation = textField->cursorLocation();
|
||||
int location = textField->cursorLocation();
|
||||
int tokenLength = strlen(token);
|
||||
if (cursorLocation - tokenLength < 0) {
|
||||
while (text[location] != '(') {
|
||||
location --;
|
||||
}
|
||||
if (location - tokenLength < 0) {
|
||||
return false;
|
||||
}
|
||||
char previousToken[10];
|
||||
strlcpy(previousToken, text+cursorLocation-tokenLength, tokenLength+1);
|
||||
strlcpy(previousToken, text+location-tokenLength, tokenLength+1);
|
||||
if (strcmp(previousToken, token) == 0) {
|
||||
return true;
|
||||
}
|
||||
@@ -61,7 +64,7 @@ bool ExpressionTextFieldDelegate::textFieldDidReceiveEvent(TextField * textField
|
||||
textField->setEditing(true);
|
||||
textField->setText("");
|
||||
}
|
||||
if (cursorInToken(textField, "sum(") || cursorInToken(textField, "product(")) {
|
||||
if (cursorInToken(textField, "sum") || cursorInToken(textField, "product")) {
|
||||
textField->insertTextAtLocation("n", textField->cursorLocation());
|
||||
textField->setCursorLocation(textField->cursorLocation()+strlen("n"));
|
||||
return true;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* and the text which would be edited by clicking on the row. When the node is a
|
||||
* subtree, the edited text is set at nullptr. */
|
||||
|
||||
const ToolboxNode calculChildren[4] = {ToolboxNode("diff(,)", "Nombre derive"), ToolboxNode("Int(,,)", "Integrale"), ToolboxNode("sum(,,)", "Somme"), ToolboxNode("product(,,)", "Produit")};
|
||||
const ToolboxNode calculChildren[4] = {ToolboxNode("diff(,)", "Nombre derive"), ToolboxNode("int(,,)", "Integrale"), ToolboxNode("sum(,,)", "Somme"), ToolboxNode("product(,,)", "Produit")};
|
||||
const ToolboxNode complexChildren[5] = {ToolboxNode("abs()", "Module"), ToolboxNode("arg()", "Argument"), ToolboxNode("re()", "Partie reelle"), ToolboxNode("im()", "Partie imaginaire"), ToolboxNode("conj()", "Conjugue")};
|
||||
const ToolboxNode probabilityChildren[4] = {ToolboxNode("binomial()", "Combinaison"), ToolboxNode("permute(,)", "Arrangement"), ToolboxNode("random(,)", "Nombre aleatoire"), ToolboxNode("gamma()", "Fonction gamma")};
|
||||
const ToolboxNode arithmeticChildren[4] = {ToolboxNode("gcd()", "PGCD"), ToolboxNode("lcm()", "PPCM"), ToolboxNode("rem()", "Reste division euclidienne"), ToolboxNode("quo()","Quotien division euclidienne")};
|
||||
|
||||
@@ -8,6 +8,7 @@ objs += $(addprefix poincare/src/,\
|
||||
binary_operation.o\
|
||||
cosine.o\
|
||||
derivative.o\
|
||||
exponential.o\
|
||||
expression.o\
|
||||
expression_lexer.o\
|
||||
expression_parser.o\
|
||||
@@ -16,12 +17,14 @@ objs += $(addprefix poincare/src/,\
|
||||
function.o\
|
||||
global_context.o\
|
||||
integer.o\
|
||||
integral.o\
|
||||
list_data.o\
|
||||
leaf_expression.o\
|
||||
logarithm.o\
|
||||
matrix.o\
|
||||
matrix_data.o\
|
||||
nth_root.o\
|
||||
opposite.o\
|
||||
parenthesis.o\
|
||||
power.o\
|
||||
product.o\
|
||||
|
||||
@@ -7,16 +7,19 @@
|
||||
#include <poincare/cosine.h>
|
||||
#include <poincare/derivative.h>
|
||||
#include <poincare/expression.h>
|
||||
#include <poincare/exponential.h>
|
||||
#include <poincare/float.h>
|
||||
#include <poincare/fraction.h>
|
||||
#include <poincare/function.h>
|
||||
#include <poincare/global_context.h>
|
||||
#include <poincare/integer.h>
|
||||
#include <poincare/integral.h>
|
||||
#include <poincare/list_data.h>
|
||||
#include <poincare/logarithm.h>
|
||||
#include <poincare/matrix.h>
|
||||
#include <poincare/matrix_data.h>
|
||||
#include <poincare/nth_root.h>
|
||||
#include <poincare/opposite.h>
|
||||
#include <poincare/parenthesis.h>
|
||||
#include <poincare/power.h>
|
||||
#include <poincare/product.h>
|
||||
|
||||
15
poincare/include/poincare/exponential.h
Normal file
15
poincare/include/poincare/exponential.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef POINCARE_EXPONENTIAL_H
|
||||
#define POINCARE_EXPONENTIAL_H
|
||||
|
||||
#include <poincare/function.h>
|
||||
|
||||
class Exponential : public Function {
|
||||
public:
|
||||
Exponential();
|
||||
float approximate(Context & context) const override;
|
||||
Type type() const override;
|
||||
Expression * cloneWithDifferentOperands(Expression ** newOperands,
|
||||
int numberOfOperands, bool cloneOperands = true) const override;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -13,11 +13,14 @@ class Expression {
|
||||
Addition,
|
||||
Cosine,
|
||||
Derivative,
|
||||
Exponential,
|
||||
Float,
|
||||
Integer,
|
||||
Integral,
|
||||
Logarithm,
|
||||
Matrix,
|
||||
NthRoot,
|
||||
Opposite,
|
||||
Fraction,
|
||||
Parenthesis,
|
||||
Power,
|
||||
|
||||
18
poincare/include/poincare/integral.h
Normal file
18
poincare/include/poincare/integral.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef POINCARE_INTEGRAL_H
|
||||
#define POINCARE_INTEGRAL_H
|
||||
|
||||
#include <poincare/function.h>
|
||||
#include <poincare/x_context.h>
|
||||
|
||||
class Integral : public Function {
|
||||
public:
|
||||
Integral();
|
||||
float approximate(Context & context) const override;
|
||||
Type type() const override;
|
||||
Expression * cloneWithDifferentOperands(Expression ** newOperands,
|
||||
int numberOfOperands, bool cloneOperands = true) const override;
|
||||
private:
|
||||
float functionValueAtAbscissa(float x, XContext xcontext) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
26
poincare/include/poincare/opposite.h
Normal file
26
poincare/include/poincare/opposite.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef POINCARE_OPPOSITE_H
|
||||
#define POINCARE_OPPOSITE_H
|
||||
|
||||
#include <poincare/expression.h>
|
||||
#include <poincare/matrix.h>
|
||||
#include <poincare/float.h>
|
||||
|
||||
class Opposite : public Expression {
|
||||
public:
|
||||
Opposite(Expression * operand, bool cloneOperands = true);
|
||||
~Opposite();
|
||||
const Expression * operand(int i) const override;
|
||||
int numberOfOperands() const override;
|
||||
Expression * clone() const override;
|
||||
Expression * evaluate(Context& context) const override;
|
||||
ExpressionLayout * createLayout() const override;
|
||||
float approximate(Context& context) 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;
|
||||
};
|
||||
|
||||
#endif
|
||||
28
poincare/src/exponential.cpp
Normal file
28
poincare/src/exponential.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
#include <poincare/exponential.h>
|
||||
|
||||
extern "C" {
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
}
|
||||
|
||||
Exponential::Exponential() :
|
||||
Function("exp")
|
||||
{
|
||||
}
|
||||
|
||||
Expression::Type Exponential::type() const {
|
||||
return Type::Exponential;
|
||||
}
|
||||
|
||||
Expression * Exponential::cloneWithDifferentOperands(Expression** newOperands,
|
||||
int numberOfOperands, bool cloneOperands) const {
|
||||
assert(numberOfOperands == 1);
|
||||
assert(newOperands != nullptr);
|
||||
Exponential * e = new Exponential();
|
||||
e->setArgument(newOperands, numberOfOperands, cloneOperands);
|
||||
return e;
|
||||
}
|
||||
|
||||
float Exponential::approximate(Context& context) const {
|
||||
return expf(m_args[0]->approximate(context));
|
||||
}
|
||||
@@ -82,8 +82,10 @@ E { return EE; }
|
||||
abs { poincare_expression_yylval.expression = new AbsoluteValue(); return FUNCTION; }
|
||||
diff { poincare_expression_yylval.expression = new Derivative(); return FUNCTION; }
|
||||
ans { poincare_expression_yylval.character = Symbol::Ans; return SYMBOL; }
|
||||
exp { poincare_expression_yylval.expression = new Exponential(); return FUNCTION; }
|
||||
sin { poincare_expression_yylval.expression = new Sine(); return FUNCTION; }
|
||||
cos { poincare_expression_yylval.expression = new Cosine(); return FUNCTION; }
|
||||
int { poincare_expression_yylval.expression = new Integral(); return FUNCTION; }
|
||||
tan { poincare_expression_yylval.expression = new Tangent(); return FUNCTION; }
|
||||
log { poincare_expression_yylval.expression = new Logarithm(); return FUNCTION; }
|
||||
root { poincare_expression_yylval.expression = new NthRoot(); return FUNCTION; }
|
||||
|
||||
@@ -112,13 +112,9 @@ mtxData:
|
||||
|
||||
number:
|
||||
DIGITS { $$ = new Integer($1.address, false); }
|
||||
| MINUS DIGITS { $$ = new Integer($2.address, true); }
|
||||
| DIGITS DOT DIGITS { $$ = new Float($1.address, $1.length, false, $3.address, $3.length, nullptr, 0, false); }
|
||||
| MINUS DIGITS DOT DIGITS { $$ = new Float($2.address, $2.length, true, $4.address, $4.length, nullptr, 0, false); }
|
||||
| DIGITS DOT DIGITS EE DIGITS { $$ = new Float($1.address, $1.length, false, $3.address, $3.length, $5.address, $5.length, false); }
|
||||
| MINUS DIGITS DOT DIGITS EE DIGITS { $$ = new Float($2.address, $2.length, true, $4.address, $4.length, $6.address, $6.length, false); }
|
||||
| DIGITS DOT DIGITS EE MINUS DIGITS { $$ = new Float($1.address, $1.length, false, $3.address, $3.length, $6.address, $6.length, true); }
|
||||
| MINUS DIGITS DOT DIGITS EE MINUS DIGITS { $$ = new Float($2.address, $2.length, true, $4.address, $4.length, $7.address, $7.length, true); }
|
||||
|
||||
exp:
|
||||
number { $$ = $1; }
|
||||
@@ -128,6 +124,7 @@ exp:
|
||||
| exp MULTIPLY exp { Expression * terms[2] = {$1,$3}; $$ = new Product(terms, false); }
|
||||
| exp DIVIDE exp { Expression * terms[2] = {$1,$3}; $$ = new Fraction(terms, false); }
|
||||
| exp POW exp { Expression * terms[2] = {$1,$3}; $$ = new Power(terms, false); }
|
||||
| MINUS exp { $$ = new Opposite($2, false); }
|
||||
| LEFT_PARENTHESIS exp RIGHT_PARENTHESIS { $$ = new Parenthesis($2, false); }
|
||||
| LEFT_BRACKET mtxData RIGHT_BRACKET { $$ = new Matrix($2); }
|
||||
| FUNCTION LEFT_PARENTHESIS lstData RIGHT_PARENTHESIS { $$ = $1; $1->setArgument($3, false);}
|
||||
|
||||
60
poincare/src/integral.cpp
Normal file
60
poincare/src/integral.cpp
Normal file
@@ -0,0 +1,60 @@
|
||||
#include <poincare/integral.h>
|
||||
#include <poincare/symbol.h>
|
||||
#include <poincare/float.h>
|
||||
#include <poincare/context.h>
|
||||
extern "C" {
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
}
|
||||
|
||||
Integral::Integral() :
|
||||
Function("int")
|
||||
{
|
||||
}
|
||||
|
||||
Expression::Type Integral::type() const {
|
||||
return Type::Integral;
|
||||
}
|
||||
|
||||
Expression * Integral::cloneWithDifferentOperands(Expression** newOperands,
|
||||
int numberOfOperands, bool cloneOperands) const {
|
||||
assert(numberOfOperands == 3);
|
||||
assert(newOperands != nullptr);
|
||||
Integral * i = new Integral();
|
||||
i->setArgument(newOperands, numberOfOperands, cloneOperands);
|
||||
return i;
|
||||
}
|
||||
|
||||
float Integral::approximate(Context& context) 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/*/
|
||||
/* TODO: implement an adaptive quadrature version
|
||||
* Use Gauss-Konrad quadrature (the one used in GNU scientific library)?
|
||||
* QAGS and QAGI from netlib?
|
||||
* Add to this version:
|
||||
* - assess error
|
||||
* - higher degree if error > threshold
|
||||
* - find a way to reuse x and w ? Or useless, store all values ? */
|
||||
XContext xContext = XContext(&context);
|
||||
static float x[5]={0.1488743389816312108848260f, 0.4333953941292471907992659f, 0.6794095682990244062343274f, 0.8650633666889845107320967f, 0.9739065285171717200779640f};
|
||||
static float w[5]={0.2955242247147528701738930f, 0.2692667193099963550912269f, 0.2190863625159820439955349f, 0.1494513491505805931457763f, 0.0666713443086881375935688f};
|
||||
float a = m_args[1]->approximate(context);
|
||||
float b = m_args[2]->approximate(context);
|
||||
float xm = 0.5f*(a+b);
|
||||
float xr = 0.5f*(b-a);
|
||||
float result = 0.0f;
|
||||
for (int j = 0; j < 5; j++) {
|
||||
float dx = xr * x[j];
|
||||
result += w[j]*(functionValueAtAbscissa(xm+dx, xContext) + functionValueAtAbscissa(xm-dx, xContext));
|
||||
}
|
||||
result *= xr;
|
||||
return result;
|
||||
}
|
||||
|
||||
float Integral::functionValueAtAbscissa(float x, XContext xContext) const {
|
||||
Float e = Float(x);
|
||||
Symbol xSymbol = Symbol('x');
|
||||
xContext.setExpressionForSymbolName(&e, &xSymbol);
|
||||
return m_args[0]->approximate(xContext);
|
||||
}
|
||||
80
poincare/src/opposite.cpp
Normal file
80
poincare/src/opposite.cpp
Normal file
@@ -0,0 +1,80 @@
|
||||
#include <poincare/opposite.h>
|
||||
extern "C" {
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
}
|
||||
#include "layout/horizontal_layout.h"
|
||||
#include "layout/string_layout.h"
|
||||
|
||||
Opposite::Opposite(Expression * operand, bool cloneOperands) {
|
||||
assert(operand != nullptr);
|
||||
if (cloneOperands) {
|
||||
m_operand = operand->clone();
|
||||
} else {
|
||||
m_operand = operand;
|
||||
}
|
||||
}
|
||||
|
||||
Opposite::~Opposite() {
|
||||
delete m_operand;
|
||||
}
|
||||
|
||||
const Expression * Opposite::operand(int i) const {
|
||||
assert(i == 0);
|
||||
return m_operand;
|
||||
}
|
||||
|
||||
int Opposite::numberOfOperands() const {
|
||||
return 1;
|
||||
}
|
||||
|
||||
Expression * Opposite::clone() const {
|
||||
return this->cloneWithDifferentOperands((Expression**)&m_operand, 1, true);
|
||||
}
|
||||
|
||||
Expression * Opposite::evaluate(Context& context) const {
|
||||
Expression * operandEvalutation = m_operand->evaluate(context);
|
||||
if (operandEvalutation == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
Expression * result = nullptr;
|
||||
if (operandEvalutation->type() == Type::Float) {
|
||||
result = new Float(this->approximate(context));
|
||||
}
|
||||
if (operandEvalutation->type() == Type::Matrix) {
|
||||
result = evaluateOnMatrix((Matrix *)operandEvalutation, context);
|
||||
}
|
||||
delete operandEvalutation;
|
||||
return result;
|
||||
}
|
||||
|
||||
ExpressionLayout * Opposite::createLayout() const {
|
||||
ExpressionLayout** children_layouts = (ExpressionLayout **)malloc(2*sizeof(ExpressionLayout *));
|
||||
char string[2] = {'-', '\0'};
|
||||
children_layouts[0] = new StringLayout(string, 1);
|
||||
children_layouts[1] = m_operand->createLayout();
|
||||
return new HorizontalLayout(children_layouts, 2);
|
||||
}
|
||||
|
||||
float Opposite::approximate(Context& context) const {
|
||||
return -m_operand->approximate(context);
|
||||
}
|
||||
|
||||
Expression::Type Opposite::type() const {
|
||||
return Expression::Type::Opposite;
|
||||
}
|
||||
|
||||
Expression * Opposite::cloneWithDifferentOperands(Expression** newOperands,
|
||||
int numberOfOperands, bool cloneOperands) const {
|
||||
assert(newOperands != nullptr);
|
||||
assert(numberOfOperands == 1);
|
||||
return new Opposite(newOperands[0], cloneOperands);
|
||||
}
|
||||
|
||||
Expression * Opposite::evaluateOnMatrix(Matrix * m, Context& context) 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));
|
||||
}
|
||||
return new Matrix(operands, m->numberOfRows() * m->numberOfColumns(), m->numberOfColumns(), m->numberOfRows(), false);
|
||||
}
|
||||
Reference in New Issue
Block a user