Merge branch 'cas_with_app_copy' into python_console

This commit is contained in:
Romain Goyet
2017-11-21 18:44:38 +01:00
273 changed files with 10671 additions and 4643 deletions

10
.gitignore vendored
View File

@@ -12,11 +12,11 @@ poincare/src/expression_parser.cpp
poincare/src/expression_parser.hpp
# No rulegen generated files
poincare/src/simplify/rules_generation/rules_tokens.h
poincare/src/simplify/rules_generation/rules_lexer.cpp
poincare/src/simplify/rules_generation/rules_parser.cpp
poincare/src/simplify/rules_generation/rulegen
poincare/src/simplify/rules.cpp
poincare/src/simplification/rulegen/rules_tokens.h
poincare/src/simplification/rulegen/rules_lexer.cpp
poincare/src/simplification/rulegen/rules_parser.cpp
poincare/src/simplification/rulegen/rulegen
poincare/src/simplification/demo_ruleset.h
# Font related generated files.
kandinsky/fonts/rasterizer

View File

@@ -29,7 +29,7 @@ AppsContainer::AppsContainer() :
Poincare::Expression::setCircuitBreaker(AppsContainer::poincareCircuitBreaker);
}
bool AppsContainer::poincareCircuitBreaker(const Poincare::Expression * e) {
bool AppsContainer::poincareCircuitBreaker() {
Ion::Keyboard::State state = Ion::Keyboard::scan();
return state.keyDown(Ion::Keyboard::Key::A6);
}

View File

@@ -26,7 +26,7 @@
class AppsContainer : public Container {
public:
AppsContainer();
static bool poincareCircuitBreaker(const Poincare::Expression * e);
static bool poincareCircuitBreaker();
virtual int numberOfApps() = 0;
virtual App::Snapshot * appSnapshotAtIndex(int index) = 0;
App::Snapshot * hardwareTestAppSnapshot();

View File

@@ -9,7 +9,9 @@ app_objs += $(addprefix apps/calculation/,\
history_view_cell.o\
history_controller.o\
local_context.o\
output_expressions_view.o\
scrollable_expression_view.o\
scrollable_output_expressions_view.o\
selectable_table_view.o\
text_field.o\
)

View File

@@ -7,11 +7,14 @@ namespace Calculation {
Calculation::Calculation() :
m_inputText(),
m_outputText(),
m_exactOutputText(),
m_approximateOutputText(),
m_input(nullptr),
m_inputLayout(nullptr),
m_output(nullptr),
m_outputLayout(nullptr)
m_exactOutput(nullptr),
m_exactOutputLayout(nullptr),
m_approximateOutput(nullptr),
m_approximateOutputLayout(nullptr)
{
}
@@ -24,37 +27,51 @@ Calculation::~Calculation() {
delete m_input;
m_input = nullptr;
}
if (m_output != nullptr) {
delete m_output;
m_output = nullptr;
if (m_exactOutput != nullptr) {
delete m_exactOutput;
m_exactOutput = nullptr;
}
if (m_outputLayout != nullptr) {
delete m_outputLayout;
m_outputLayout = nullptr;
if (m_exactOutputLayout != nullptr) {
delete m_exactOutputLayout;
m_exactOutputLayout = nullptr;
}
if (m_approximateOutput != nullptr) {
delete m_approximateOutput;
m_approximateOutput = nullptr;
}
if (m_approximateOutputLayout != nullptr) {
delete m_approximateOutputLayout;
m_approximateOutputLayout = nullptr;
}
}
Calculation& Calculation::operator=(const Calculation& other) {
const char * otherInputText = other.m_inputText;
const char * otherOutputText = other.m_outputText;
const char * otherExactOutputText = other.m_exactOutputText;
const char * otherApproximateOutputText = other.m_approximateOutputText;
reset();
strlcpy(m_inputText, otherInputText, sizeof(m_inputText));
strlcpy(m_outputText, otherOutputText, sizeof(m_outputText));
strlcpy(m_exactOutputText, otherExactOutputText, sizeof(m_exactOutputText));
strlcpy(m_approximateOutputText, otherApproximateOutputText, sizeof(m_approximateOutputText));
return *this;
}
void Calculation::reset() {
m_inputText[0] = 0;
m_outputText[0] = 0;
m_exactOutputText[0] = 0;
m_approximateOutputText[0] = 0;
tidy();
}
void Calculation::setContent(const char * c, Context * context) {
reset();
strlcpy(m_inputText, c, sizeof(m_inputText));
Evaluation<double> * evaluation = input()->evaluate<double>(*context);
evaluation->writeTextInBuffer(m_outputText, sizeof(m_outputText));
delete evaluation;
m_input = Expression::parse(c);
m_input->writeTextInBuffer(m_inputText, sizeof(m_inputText));
m_exactOutput = input()->clone();
Expression::Simplify(&m_exactOutput, *context);
m_exactOutput->writeTextInBuffer(m_exactOutputText, sizeof(m_exactOutputText));
m_approximateOutput = m_exactOutput->evaluate<double>(*context);
m_approximateOutput->writeTextInBuffer(m_approximateOutputText, sizeof(m_approximateOutputText));
}
const char * Calculation::inputText() {
@@ -62,7 +79,18 @@ const char * Calculation::inputText() {
}
const char * Calculation::outputText() {
return m_outputText;
if (shouldApproximateOutput()) {
return m_approximateOutputText;
}
return m_exactOutputText;
}
const char * Calculation::exactOutputText() {
return m_exactOutputText;
}
const char * Calculation::approximateOutputText() {
return m_approximateOutputText;
}
Expression * Calculation::input() {
@@ -79,36 +107,29 @@ ExpressionLayout * Calculation::inputLayout() {
return m_inputLayout;
}
Evaluation<double> * Calculation::output(Context * context) {
if (m_output == nullptr) {
/* To ensure that the expression 'm_output' is a matrix or a complex, we
* call 'evaluate'. */
Expression * exp = Expression::parse(m_outputText);
if (exp != nullptr) {
m_output = exp->evaluate<double>(*context);
delete exp;
} else {
m_output = new Complex<double>(Complex<double>::Float(NAN));
}
Expression * Calculation::output(Context * context) {
if (shouldApproximateOutput()) {
return approximateOutput(context);
}
return m_output;
return exactOutput(context);
}
ExpressionLayout * Calculation::outputLayout(Context * context) {
if (m_outputLayout == nullptr && output(context) != nullptr) {
m_outputLayout = output(context)->createLayout();
if (shouldApproximateOutput()) {
return approximateOutputLayout(context);
}
return m_outputLayout;
return exactOutputLayout(context);
}
bool Calculation::isEmpty() {
/* To test if a calculation is empty, we need to test either m_inputText or
* m_outputText, the only two fields that are not lazy-loaded. We choose
* m_outputText to consider that a calculation being added is still empty
* until the end of the method 'setContent'. Indeed, during 'setContent'
* method, 'ans' evaluation calls the evaluation of the last calculation
* only if the calculation being filled is not taken into account.*/
if (strlen(m_outputText) == 0) {
* m_exactOutputText or m_approximateOutputText, the only three fields that
* are not lazy-loaded. We choose m_exactOutputText to consider that a
* calculation being added is still empty until the end of the method
* 'setContent'. Indeed, during 'setContent' method, 'ans' evaluation calls
* the evaluation of the last calculation only if the calculation being
* filled is not taken into account.*/
if (strlen(m_approximateOutputText) == 0) {
return true;
}
return false;
@@ -123,14 +144,77 @@ void Calculation::tidy() {
delete m_inputLayout;
}
m_inputLayout = nullptr;
if (m_output != nullptr) {
delete m_output;
if (m_exactOutput != nullptr) {
delete m_exactOutput;
}
m_output = nullptr;
if (m_outputLayout != nullptr) {
delete m_outputLayout;
m_exactOutput = nullptr;
if (m_exactOutputLayout != nullptr) {
delete m_exactOutputLayout;
}
m_outputLayout = nullptr;
m_exactOutputLayout = nullptr;
if (m_approximateOutput != nullptr) {
delete m_approximateOutput;
}
m_approximateOutput = nullptr;
if (m_approximateOutputLayout != nullptr) {
delete m_approximateOutputLayout;
}
m_approximateOutputLayout = nullptr;
}
Expression * Calculation::exactOutput(Context * context) {
if (m_exactOutput == nullptr) {
/* To ensure that the expression 'm_exactOutput' is a simplified, we
* call 'simplifyAndBeautify'. */
m_exactOutput = Expression::parse(m_exactOutputText);
if (m_exactOutput != nullptr) {
Expression::Simplify(&m_exactOutput, *context);
} else {
m_exactOutput = new Undefined();
}
}
return m_exactOutput;
}
ExpressionLayout * Calculation::exactOutputLayout(Context * context) {
if (m_exactOutputLayout == nullptr && exactOutput(context) != nullptr) {
m_exactOutputLayout = exactOutput(context)->createLayout();
}
return m_exactOutputLayout;
}
Expression * Calculation::approximateOutput(Context * context) {
if (m_approximateOutput == nullptr) {
/* To ensure that the expression 'm_output' is a matrix or a complex, we
* call 'evaluate'. */
Expression * exp = Expression::parse(m_approximateOutputText);
if (exp != nullptr) {
m_approximateOutput = exp->evaluate<double>(*context);
delete exp;
} else {
m_approximateOutput = new Complex<double>(Complex<double>::Float(NAN));
}
}
return m_approximateOutput;
}
ExpressionLayout * Calculation::approximateOutputLayout(Context * context) {
if (m_approximateOutputLayout == nullptr && approximateOutput(context) != nullptr) {
m_approximateOutputLayout = approximateOutput(context)->createLayout();
}
return m_approximateOutputLayout;
}
bool Calculation::shouldApproximateOutput() {
if (strcmp(m_exactOutputText, m_approximateOutputText) == 0) {
return true;
}
if (strcmp(m_exactOutputText, m_inputText) == 0) {
return true;
}
return input()->recursivelyMatches([](const Expression * e) {
return e->type() == Expression::Type::Decimal || Expression::IsMatrix(e);
});
}
}

View File

@@ -16,22 +16,32 @@ public:
Calculation& operator=(Calculation&& other) = delete;
/* c.reset() is the equivalent of c = Calculation() without copy assingment. */
void reset();
void setContent(const char * c, Poincare::Context * context);
const char * inputText();
const char * outputText();
const char * exactOutputText();
const char * approximateOutputText();
Poincare::Expression * input();
Poincare::ExpressionLayout * inputLayout();
Poincare::Evaluation<double> * output(Poincare::Context * context);
Poincare::Expression * output(Poincare::Context * context);
Poincare::Expression * approximateOutput(Poincare::Context * context);
Poincare::ExpressionLayout * outputLayout(Poincare::Context * context);
void setContent(const char * c, Poincare::Context * context);
Poincare::ExpressionLayout * exactOutputLayout(Poincare::Context * context);
Poincare::ExpressionLayout * approximateOutputLayout(Poincare::Context * context);
bool isEmpty();
void tidy();
bool shouldApproximateOutput();
private:
Poincare::Expression * exactOutput(Poincare::Context * context);
char m_inputText[::TextField::maxBufferSize()];
char m_outputText[2*::TextField::maxBufferSize()];
char m_exactOutputText[2*::TextField::maxBufferSize()];
char m_approximateOutputText[2*::TextField::maxBufferSize()];
Poincare::Expression * m_input;
Poincare::ExpressionLayout * m_inputLayout;
Poincare::Evaluation<double> * m_output;
Poincare::ExpressionLayout * m_outputLayout;
Poincare::Expression * m_exactOutput;
Poincare::ExpressionLayout * m_exactOutputLayout;
Poincare::Expression * m_approximateOutput;
Poincare::ExpressionLayout * m_approximateOutputLayout;
};
}

View File

@@ -47,7 +47,12 @@ bool HistoryController::handleEvent(Ion::Events::Event event) {
if (subviewType == HistoryViewCell::SubviewType::Input) {
editController->insertTextBody(calculation->inputText());
} else {
editController->insertTextBody(calculation->outputText());
OutputExpressionsView::SubviewType outputSubviewType = selectedCell->outputView()->selectedSubviewType();
if (outputSubviewType == OutputExpressionsView::SubviewType::ExactOutput) {
editController->insertTextBody(calculation->exactOutputText());
} else {
editController->insertTextBody(calculation->approximateOutputText());
}
}
return true;
}
@@ -97,7 +102,12 @@ bool HistoryController::handleEvent(Ion::Events::Event event) {
if (subviewType == HistoryViewCell::SubviewType::Input) {
Clipboard::sharedClipboard()->store(calculation->inputText());
} else {
Clipboard::sharedClipboard()->store(calculation->outputText());
OutputExpressionsView::SubviewType outputSubviewType = selectedCell->outputView()->selectedSubviewType();
if (outputSubviewType == OutputExpressionsView::SubviewType::ExactOutput) {
Clipboard::sharedClipboard()->store(calculation->exactOutputText());
} else {
Clipboard::sharedClipboard()->store(calculation->approximateOutputText());
}
}
return true;
}
@@ -109,14 +119,12 @@ void HistoryController::tableViewDidChangeSelection(SelectableTableView * t, int
if (selectedCell == nullptr) {
return;
}
if (selectedRow() < previousSelectedCellY) {
selectedCell->setSelectedSubviewType(HistoryViewCell::SubviewType::Output);
}
if (selectedRow() >= previousSelectedCellY) {
selectedCell->setSelectedSubviewType(HistoryViewCell::SubviewType::Input);
}
if (previousSelectedCellY == -1) {
selectedCell->setSelectedSubviewType(HistoryViewCell::SubviewType::Output);
} else if (selectedRow() < previousSelectedCellY) {
selectedCell->setSelectedSubviewType(HistoryViewCell::SubviewType::Output);
} else if (selectedRow() > previousSelectedCellY) {
selectedCell->setSelectedSubviewType(HistoryViewCell::SubviewType::Input);
}
app()->setFirstResponder(selectedCell);
selectedCell->reloadCell();
@@ -142,6 +150,7 @@ void HistoryController::willDisplayCellForIndex(HighlightCell * cell, int index)
HistoryViewCell * myCell = (HistoryViewCell *)cell;
myCell->setCalculation(m_calculationStore->calculationAtIndex(index));
myCell->setEven(index%2 == 0);
myCell->reloadCell();
}
KDCoordinate HistoryController::rowHeight(int j) {
@@ -151,7 +160,9 @@ KDCoordinate HistoryController::rowHeight(int j) {
Calculation * calculation = m_calculationStore->calculationAtIndex(j);
KDCoordinate inputHeight = calculation->inputLayout()->size().height();
App * calculationApp = (App *)app();
KDCoordinate outputHeight = calculation->outputLayout(calculationApp->localContext())->size().height();
KDCoordinate exactOutputHeight = calculation->exactOutputLayout(calculationApp->localContext())->size().height();
KDCoordinate approximateOutputHeight = calculation->approximateOutputLayout(calculationApp->localContext())->size().height();
KDCoordinate outputHeight = calculation->shouldApproximateOutput() || approximateOutputHeight > exactOutputHeight ? approximateOutputHeight : exactOutputHeight;
return inputHeight + outputHeight + 3*HistoryViewCell::k_digitVerticalMargin;
}

View File

@@ -10,11 +10,46 @@ namespace Calculation {
HistoryViewCell::HistoryViewCell(Responder * parentResponder) :
Responder(parentResponder),
m_inputView(this),
m_outputView(this),
m_scrollableOutputView(this),
m_selectedSubviewType(HistoryViewCell::SubviewType::Output)
{
}
OutputExpressionsView * HistoryViewCell::outputView() {
return m_scrollableOutputView.outputView();
}
void HistoryViewCell::setEven(bool even) {
EvenOddCell::setEven(even);
m_inputView.setBackgroundColor(backgroundColor());
m_scrollableOutputView.outputView()->setEven(even);
}
void HistoryViewCell::setHighlighted(bool highlight) {
m_highlighted = highlight;
m_inputView.setBackgroundColor(backgroundColor());
m_scrollableOutputView.outputView()->setHighlighted(false);
if (isHighlighted()) {
if (m_selectedSubviewType == SubviewType::Input) {
m_inputView.setBackgroundColor(Palette::Select);
} else {
m_scrollableOutputView.outputView()->setHighlighted(true);
}
}
reloadScroll();
}
void HistoryViewCell::reloadCell() {
m_scrollableOutputView.outputView()->reloadCell();
layoutSubviews();
reloadScroll();
}
void HistoryViewCell::reloadScroll() {
m_inputView.reloadScroll();
m_scrollableOutputView.reloadScroll();
}
KDColor HistoryViewCell::backgroundColor() const {
KDColor background = m_even ? Palette::WallScreen : KDColorWhite;
return background;
@@ -26,7 +61,7 @@ int HistoryViewCell::numberOfSubviews() const {
}
View * HistoryViewCell::subviewAtIndex(int index) {
View * views[2] = {&m_inputView, &m_outputView};
View * views[2] = {&m_inputView, &m_scrollableOutputView};
return views[index];
}
@@ -39,41 +74,29 @@ void HistoryViewCell::layoutSubviews() {
} else {
m_inputView.setFrame(KDRect(Metric::HistoryHorizontalMargin, k_digitVerticalMargin, inputSize.width(), inputSize.height()));
}
KDSize outputSize = m_outputView.minimalSizeForOptimalDisplay();
KDSize outputSize = m_scrollableOutputView.minimalSizeForOptimalDisplay();
if (outputSize.width() + Metric::HistoryHorizontalMargin > width) {
m_outputView.setFrame(KDRect(Metric::HistoryHorizontalMargin, inputSize.height() + 2*k_digitVerticalMargin, width - Metric::HistoryHorizontalMargin, height - inputSize.height() - 3*k_digitVerticalMargin));
m_scrollableOutputView.setFrame(KDRect(Metric::HistoryHorizontalMargin, inputSize.height() + 2*k_digitVerticalMargin, width - Metric::HistoryHorizontalMargin, height - inputSize.height() - 3*k_digitVerticalMargin));
} else {
m_outputView.setFrame(KDRect(width - outputSize.width() - Metric::HistoryHorizontalMargin, inputSize.height() + 2*k_digitVerticalMargin, outputSize.width(), height - inputSize.height() - 3*k_digitVerticalMargin));
m_scrollableOutputView.setFrame(KDRect(width - outputSize.width() - Metric::HistoryHorizontalMargin, inputSize.height() + 2*k_digitVerticalMargin, outputSize.width(), height - inputSize.height() - 3*k_digitVerticalMargin));
}
}
void HistoryViewCell::setCalculation(Calculation * calculation) {
m_inputView.setExpression(calculation->inputLayout());
App * calculationApp = (App *)app();
m_outputView.setExpression(calculation->outputLayout(calculationApp->localContext()));
}
void HistoryViewCell::reloadCell() {
m_outputView.setBackgroundColor(backgroundColor());
m_inputView.setBackgroundColor(backgroundColor());
if (isHighlighted()) {
if (m_selectedSubviewType == SubviewType::Output) {
m_outputView.setBackgroundColor(Palette::Select);
} else {
m_inputView.setBackgroundColor(Palette::Select);
}
}
layoutSubviews();
EvenOddCell::reloadCell();
m_inputView.reloadScroll();
m_outputView.reloadScroll();
/* Both output expressions have to be updated at the same time. The
* outputView points to deleted layouts and a call to
* outputView()->layoutSubviews() is going to fail. */
Poincare::ExpressionLayout * outputExpressions[2] = {calculation->approximateOutputLayout(calculationApp->localContext()), calculation->shouldApproximateOutput() ? nullptr : calculation->exactOutputLayout(calculationApp->localContext())};
m_scrollableOutputView.outputView()->setExpressions(outputExpressions);
}
void HistoryViewCell::didBecomeFirstResponder() {
if (m_selectedSubviewType == SubviewType::Input) {
app()->setFirstResponder(&m_inputView);
} else {
app()->setFirstResponder(&m_outputView);
app()->setFirstResponder(&m_scrollableOutputView);
}
}
@@ -83,6 +106,7 @@ HistoryViewCell::SubviewType HistoryViewCell::selectedSubviewType() {
void HistoryViewCell::setSelectedSubviewType(HistoryViewCell::SubviewType subviewType) {
m_selectedSubviewType = subviewType;
setHighlighted(isHighlighted());
}
bool HistoryViewCell::handleEvent(Ion::Events::Event event) {
@@ -94,7 +118,6 @@ bool HistoryViewCell::handleEvent(Ion::Events::Event event) {
HistoryViewCell * selectedCell = (HistoryViewCell *)(tableView->selectedCell());
selectedCell->setSelectedSubviewType(otherSubviewType);
app()->setFirstResponder(selectedCell);
selectedCell->reloadCell();
return true;
}
return false;

View File

@@ -4,6 +4,7 @@
#include <escher.h>
#include "calculation.h"
#include "scrollable_expression_view.h"
#include "scrollable_output_expressions_view.h"
namespace Calculation {
@@ -15,6 +16,9 @@ public:
};
HistoryViewCell(Responder * parentResponder);
void reloadCell() override;
void reloadScroll();
void setEven(bool even) override;
void setHighlighted(bool highlight) override;
KDColor backgroundColor() const override;
void setCalculation(Calculation * calculation);
int numberOfSubviews() const override;
@@ -25,10 +29,11 @@ public:
constexpr static KDCoordinate k_digitVerticalMargin = 5;
SubviewType selectedSubviewType();
void setSelectedSubviewType(HistoryViewCell::SubviewType subviewType);
OutputExpressionsView * outputView();
private:
constexpr static KDCoordinate k_resultWidth = 80;
ScrollableExpressionView m_inputView;
ScrollableExpressionView m_outputView;
ScrollableOutputExpressionsView m_scrollableOutputView;
SubviewType m_selectedSubviewType;
};

View File

@@ -10,17 +10,17 @@ LocalContext::LocalContext(GlobalContext * parentContext, CalculationStore * cal
{
}
Evaluation<double> * LocalContext::ansValue() {
Expression * LocalContext::ansValue() {
if (m_calculationStore->numberOfCalculations() == 0) {
return m_parentContext->defaultExpression();
}
Calculation * lastCalculation = m_calculationStore->calculationAtIndex(m_calculationStore->numberOfCalculations()-1);
return lastCalculation->output(m_parentContext);
return lastCalculation->approximateOutput(m_parentContext);
}
void LocalContext::setExpressionForSymbolName(Expression * expression, const Symbol * symbol) {
void LocalContext::setExpressionForSymbolName(const Expression * expression, const Symbol * symbol, Context & context) {
if (symbol->name() != Symbol::SpecialSymbols::Ans) {
m_parentContext->setExpressionForSymbolName(expression, symbol);
m_parentContext->setExpressionForSymbolName(expression, symbol, context);
}
}

View File

@@ -9,10 +9,10 @@ namespace Calculation {
class LocalContext : public Poincare::Context {
public:
LocalContext(Poincare::GlobalContext * parentContext, CalculationStore * calculationStore);
void setExpressionForSymbolName(Poincare::Expression * expression, const Poincare::Symbol * symbol) override;
void setExpressionForSymbolName(const Poincare::Expression * expression, const Poincare::Symbol * symbol, Context & context) override;
const Poincare::Expression * expressionForSymbol(const Poincare::Symbol * symbol) override;
private:
Poincare::Evaluation<double> * ansValue();
Poincare::Expression * ansValue();
CalculationStore * m_calculationStore;
Poincare::GlobalContext * m_parentContext;
};

View File

@@ -0,0 +1,125 @@
#include "output_expressions_view.h"
#include "scrollable_output_expressions_view.h"
#include "../i18n.h"
#include <assert.h>
using namespace Poincare;
namespace Calculation {
OutputExpressionsView::OutputExpressionsView(Responder * parentResponder) :
Responder(parentResponder),
m_approximateExpressionView(),
m_approximateSign(KDText::FontSize::Large, I18n::Message::AlmostEqual, 0.5f, 0.5f, Palette::GreyDark),
m_exactExpressionView(),
m_selectedSubviewType(OutputExpressionsView::SubviewType::ExactOutput)
{
}
void OutputExpressionsView::setExpressions(ExpressionLayout ** expressionsLayout) {
m_approximateExpressionView.setExpression(expressionsLayout[0]);
m_exactExpressionView.setExpression(expressionsLayout[1]);
layoutSubviews();
}
void OutputExpressionsView::setHighlighted(bool highlight) {
// Do not call HighlightCell::setHighlighted to avoid marking all cell as dirty
m_highlighted = highlight;
m_exactExpressionView.setBackgroundColor(backgroundColor());
m_approximateExpressionView.setBackgroundColor(backgroundColor());
if (highlight) {
if (m_selectedSubviewType == SubviewType::ExactOutput) {
m_exactExpressionView.setBackgroundColor(Palette::Select);
} else {
m_approximateExpressionView.setBackgroundColor(Palette::Select);
}
}
}
KDColor OutputExpressionsView::backgroundColor() const {
KDColor background = m_even ? Palette::WallScreen : KDColorWhite;
return background;
}
void OutputExpressionsView::reloadCell() {
setHighlighted(isHighlighted());
m_approximateSign.setBackgroundColor(backgroundColor());
if (numberOfSubviews() == 1) {
m_approximateExpressionView.setTextColor(KDColorBlack);
} else {
m_approximateExpressionView.setTextColor(Palette::GreyDark);
}
layoutSubviews();
}
KDSize OutputExpressionsView::minimalSizeForOptimalDisplay() const {
KDSize approximateExpressionSize = m_approximateExpressionView.minimalSizeForOptimalDisplay();
if (numberOfSubviews() == 1) {
return approximateExpressionSize;
}
KDSize exactExpressionSize = m_exactExpressionView.minimalSizeForOptimalDisplay();
KDSize approximateSignSize = m_approximateSign.minimalSizeForOptimalDisplay();
return KDSize(exactExpressionSize.width()+approximateSignSize.width()+approximateExpressionSize.width()+2*k_digitHorizontalMargin, exactExpressionSize.height() > approximateExpressionSize.height() ? exactExpressionSize.height() : approximateExpressionSize.height());
}
void OutputExpressionsView::didBecomeFirstResponder() {
if (numberOfSubviews() == 1) {
setSelectedSubviewType(SubviewType::ApproximativeOutput);
} else {
setSelectedSubviewType(SubviewType::ExactOutput);
}
}
bool OutputExpressionsView::handleEvent(Ion::Events::Event event) {
if (numberOfSubviews() == 1) {
return false;
}
ScrollableOutputExpressionsView * scrollResponder = static_cast<ScrollableOutputExpressionsView *>(parentResponder());
KDCoordinate offset = scrollResponder->manualScrollingOffset().x();
bool rightExpressionIsVisible = minimalSizeForOptimalDisplay().width() - m_approximateExpressionView.minimalSizeForOptimalDisplay().width() - offset < scrollResponder->bounds().width()
;
bool leftExpressionIsVisible = m_exactExpressionView.minimalSizeForOptimalDisplay().width() - offset < scrollResponder->bounds().width();
if ((event == Ion::Events::Right && m_selectedSubviewType == SubviewType::ExactOutput && rightExpressionIsVisible) ||
(event == Ion::Events::Left && m_selectedSubviewType == SubviewType::ApproximativeOutput && leftExpressionIsVisible)) {
SubviewType otherSubviewType = m_selectedSubviewType == SubviewType::ExactOutput ? SubviewType::ApproximativeOutput : SubviewType::ExactOutput;
setSelectedSubviewType(otherSubviewType);
return true;
}
return false;
}
OutputExpressionsView::SubviewType OutputExpressionsView::selectedSubviewType() {
return m_selectedSubviewType;
}
void OutputExpressionsView::setSelectedSubviewType(OutputExpressionsView::SubviewType subviewType) {
m_selectedSubviewType = subviewType;
setHighlighted(isHighlighted());
}
int OutputExpressionsView::numberOfSubviews() const {
if (m_exactExpressionView.expressionLayout() != nullptr) {
return 3;
}
return 1;
}
View * OutputExpressionsView::subviewAtIndex(int index) {
View * views[3] = {&m_approximateExpressionView, &m_approximateSign, &m_exactExpressionView};
return views[index];
}
void OutputExpressionsView::layoutSubviews() {
KDCoordinate height = bounds().height();
KDSize approximateExpressionSize = m_approximateExpressionView.minimalSizeForOptimalDisplay();
if (numberOfSubviews() == 1) {
m_approximateExpressionView.setFrame(KDRect(0, 0, approximateExpressionSize.width(), height));
return;
}
KDSize exactExpressionSize = m_exactExpressionView.minimalSizeForOptimalDisplay();
m_exactExpressionView.setFrame(KDRect(0, 0, exactExpressionSize.width(), height));
KDSize approximateSignSize = m_approximateSign.minimalSizeForOptimalDisplay();
m_approximateSign.setFrame(KDRect(k_digitHorizontalMargin+exactExpressionSize.width(), 0, approximateSignSize.width(), height));
m_approximateExpressionView.setFrame(KDRect(2*k_digitHorizontalMargin+exactExpressionSize.width()+approximateSignSize.width(), 0, approximateExpressionSize.width(), height));
}
}

View File

@@ -0,0 +1,37 @@
#ifndef CALCULATION_OUTPUT_EXPRESSIONS_VIEW_H
#define CALCULATION_OUTPUT_EXPRESSIONS_VIEW_H
#include <escher.h>
namespace Calculation {
class OutputExpressionsView : public EvenOddCell, public Responder {
public:
enum class SubviewType {
ExactOutput,
ApproximativeOutput
};
OutputExpressionsView(Responder * parentResponder);
void setExpressions(Poincare::ExpressionLayout ** expressionsLayout);
KDColor backgroundColor() const override;
void setHighlighted(bool highlight) override;
void reloadCell() override;
KDSize minimalSizeForOptimalDisplay() const override;
void didBecomeFirstResponder() override;
bool handleEvent(Ion::Events::Event event) override;
SubviewType selectedSubviewType();
void setSelectedSubviewType(SubviewType subviewType);
private:
int numberOfSubviews() const override;
View * subviewAtIndex(int index) override;
void layoutSubviews() override;
constexpr static KDCoordinate k_digitHorizontalMargin = 10;
ExpressionView m_approximateExpressionView;
MessageTextView m_approximateSign;
ExpressionView m_exactExpressionView;
SubviewType m_selectedSubviewType;
};
}
#endif

View File

@@ -0,0 +1,29 @@
#include "scrollable_output_expressions_view.h"
#include <assert.h>
using namespace Poincare;
namespace Calculation {
ScrollableOutputExpressionsView::ScrollableOutputExpressionsView(Responder * parentResponder) :
ScrollableView(parentResponder, &m_outputView, this),
m_outputView(this)
{
}
OutputExpressionsView * ScrollableOutputExpressionsView::outputView() {
return &m_outputView;
}
void ScrollableOutputExpressionsView::didBecomeFirstResponder() {
app()->setFirstResponder(&m_outputView);
}
KDSize ScrollableOutputExpressionsView::minimalSizeForOptimalDisplay() const {
return m_outputView.minimalSizeForOptimalDisplay();
}
KDPoint ScrollableOutputExpressionsView::manualScrollingOffset() const {
return m_manualScrollingOffset;
}
}

View File

@@ -0,0 +1,22 @@
#ifndef CALCULATION_SCROLLABLE_OUTPUT_EXPRESSIONS_VIEW_H
#define CALCULATION_SCROLLABLE_OUTPUT_EXPRESSIONS_VIEW_H
#include <escher.h>
#include "output_expressions_view.h"
namespace Calculation {
class ScrollableOutputExpressionsView : public ScrollableView, public ScrollViewDataSource {
public:
ScrollableOutputExpressionsView(Responder * parentResponder);
OutputExpressionsView * outputView();
void didBecomeFirstResponder() override;
KDSize minimalSizeForOptimalDisplay() const override;
KDPoint manualScrollingOffset() const;
private:
OutputExpressionsView m_outputView;
};
}
#endif

View File

@@ -19,8 +19,7 @@ void CartesianFunction::setDisplayDerivative(bool display) {
double CartesianFunction::approximateDerivative(double x, Poincare::Context * context) const {
Poincare::Complex<double> abscissa = Poincare::Complex<double>::Float(x);
Poincare::Expression * args[2] = {expression(), &abscissa};
Poincare::Derivative derivative;
derivative.setArgument(args, 2, true);
Poincare::Derivative derivative(args, true);
return derivative.approximate<double>(*context);
}

View File

@@ -12,7 +12,8 @@ ion_special_characters = {
u'λ': "Ion::Charset::SmallLambda",
u'μ': "Ion::Charset::SmallMu",
u'σ': "Ion::Charset::SmallSigma",
u'': "Ion::Charset::LessEqual"
u'': "Ion::Charset::LessEqual",
u'': "Ion::Charset::AlmostEqual"
}
def ion_char(i18n_letter):

View File

@@ -286,13 +286,13 @@ T Sequence::templatedEvaluateAtAbscissa(T x, Poincare::Context * context) const
return bufferValue<T>(0);
}
LocalContext<T> subContext = LocalContext<T>(context);
Poincare::Symbol nSymbol = Poincare::Symbol(symbol());
Poincare::Symbol nSymbol(symbol());
int start = indexBuffer<T>(0) < 0 || indexBuffer<T>(0) > n ? 0 : indexBuffer<T>(0);
T un = indexBuffer<T>(0) < 0 || indexBuffer<T>(0) > n ? firstInitialConditionExpression()->approximate<T>(*context) : bufferValue<T>(0);
for (int i = start; i < n; i++) {
subContext.setValueForSequenceRank(un, name(), 0);
Poincare::Complex<T> e = Poincare::Complex<T>::Float(i);
subContext.setExpressionForSymbolName(&e, &nSymbol);
subContext.setExpressionForSymbolName(&e, &nSymbol, subContext);
un = expression()->approximate<T>(subContext);
}
setBufferValue(un, 0);
@@ -315,7 +315,7 @@ T Sequence::templatedEvaluateAtAbscissa(T x, Poincare::Context * context) const
return bufferValue<T>(1);
}
LocalContext<T> subContext = LocalContext<T>(context);
Poincare::Symbol nSymbol = Poincare::Symbol(symbol());
Poincare::Symbol nSymbol(symbol());
int start = indexBuffer<T>(0) >= 0 && indexBuffer<T>(0) < n && indexBuffer<T>(1) > 0 && indexBuffer<T>(1) <= n && indexBuffer<T>(0) + 1 == indexBuffer<T>(1) ? indexBuffer<T>(0) : 0;
T un = indexBuffer<T>(0) >= 0 && indexBuffer<T>(0) < n && indexBuffer<T>(1) > 0 && indexBuffer<T>(1) <= n && indexBuffer<T>(0) + 1 == indexBuffer<T>(1) ? bufferValue<T>(0) : firstInitialConditionExpression()->approximate<T>(*context);
T un1 = indexBuffer<T>(0) >= 0 && indexBuffer<T>(0) < n && indexBuffer<T>(1) > 0 && indexBuffer<T>(1) <= n && indexBuffer<T>(0) + 1 == indexBuffer<T>(1) ? bufferValue<T>(1) : secondInitialConditionExpression()->approximate<T>(*context);
@@ -323,7 +323,7 @@ T Sequence::templatedEvaluateAtAbscissa(T x, Poincare::Context * context) const
subContext.setValueForSequenceRank(un, name(), 0);
subContext.setValueForSequenceRank(un1, name(), 1);
Poincare::Complex<T> e = Poincare::Complex<T>::Float(i);
subContext.setExpressionForSymbolName(&e, &nSymbol);
subContext.setExpressionForSymbolName(&e, &nSymbol, subContext);
un = un1;
un1 = expression()->approximate<T>(subContext);
}

View File

@@ -65,3 +65,4 @@ AtanhCommandWithArg = "atanh(x)"
Prediction95CommandWithArg = "prediction95(p,n)"
PredictionCommandWithArg = "prediction(p,n)"
ConfidenceCommandWithArg = "confidence(f,n)"
AlmostEqual = "≈"

View File

@@ -3,6 +3,7 @@
#include "../constant.h"
#include "text_field_delegate_app.h"
#include <assert.h>
#include <cmath>
using namespace Poincare;

View File

@@ -3,6 +3,7 @@
#include "../apps_container.h"
#include "text_field_delegate_app.h"
#include <assert.h>
#include <cmath>
using namespace Poincare;

View File

@@ -102,9 +102,9 @@ bool Function::isEmpty() {
template<typename T>
T Function::templatedEvaluateAtAbscissa(T x, Poincare::Context * context) const {
Poincare::VariableContext<T> variableContext = Poincare::VariableContext<T>(symbol(), context);
Poincare::Symbol xSymbol = Poincare::Symbol(symbol());
Poincare::Symbol xSymbol(symbol());
Poincare::Complex<T> e = Poincare::Complex<T>::Float(x);
variableContext.setExpressionForSymbolName(&e, &xSymbol);
variableContext.setExpressionForSymbolName(&e, &xSymbol, variableContext);
return expression()->approximate<T>(variableContext);
}

View File

@@ -126,6 +126,7 @@ void ListController::willDisplayCellAtLocation(HighlightCell * cell, int i, int
EvenOddCell * myCell = (EvenOddCell *)cell;
myCell->setEven(j%2 == 0);
myCell->setHighlighted(i == selectedColumn() && j == selectedRow());
myCell->reloadCell();
}
int ListController::numberOfButtons(ButtonRowController::Position position) const {

View File

@@ -9,8 +9,13 @@ NewFunctionCell::NewFunctionCell(I18n::Message text) :
{
}
void NewFunctionCell::reloadCell() {
EvenOddCell::reloadCell();
void NewFunctionCell::setEven(bool even) {
EvenOddCell::setEven(even);
m_messageTextView.setBackgroundColor(backgroundColor());
}
void NewFunctionCell::setHighlighted(bool highlight) {
EvenOddCell::setHighlighted(highlight);
m_messageTextView.setBackgroundColor(backgroundColor());
}

View File

@@ -8,7 +8,8 @@ namespace Shared {
class NewFunctionCell : public EvenOddCell {
public:
NewFunctionCell(I18n::Message text);
void reloadCell() override;
void setEven(bool even) override;
void setHighlighted(bool highlight) override;
int numberOfSubviews() const override;
View * subviewAtIndex(int index) override;
void layoutSubviews() override;

View File

@@ -79,11 +79,10 @@ bool TextFieldDelegateApp::textFieldShouldFinishEditing(TextField * textField, I
bool TextFieldDelegateApp::textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) {
if (textField->textFieldShouldFinishEditing(event) && textField->isEditing()) {
Expression * exp = Expression::parse(textField->text());
bool invalidText = (exp == nullptr || !exp->hasValidNumberOfArguments());
if (exp != nullptr) {
delete exp;
}
if (invalidText) {
if (exp == nullptr) {
textField->app()->displayWarning(I18n::Message::SyntaxError);
return true;
}

View File

@@ -77,12 +77,12 @@ bool VariableBoxController::ContentViewController::handleEvent(Ion::Events::Even
}
if (event == Ion::Events::Backspace && m_currentPage != Page::RootMenu) {
if (m_currentPage == Page::Scalar) {
const Symbol symbol = Symbol('A'+selectedRow());
m_context->setExpressionForSymbolName(nullptr, &symbol);
const Symbol symbol('A'+selectedRow());
m_context->setExpressionForSymbolName(nullptr, &symbol, *m_context);
}
if (m_currentPage == Page::Matrix) {
const Symbol symbol = Symbol::matrixSymbol('0'+(char)selectedRow());
m_context->setExpressionForSymbolName(nullptr, &symbol);
m_context->setExpressionForSymbolName(nullptr, &symbol, *m_context);
}
m_selectableTableView.reloadData();
return true;
@@ -137,7 +137,7 @@ void VariableBoxController::ContentViewController::willDisplayCellForIndex(Highl
char label[3];
putLabelAtIndexInBuffer(index, label);
myCell->setLabel(label);
const Evaluation<double> * evaluation = expressionForIndex(index);
const Expression * evaluation = expressionForIndex(index);
if (m_currentPage == Page::Scalar) {
myCell->displayExpression(false);
char buffer[PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)];
@@ -148,11 +148,13 @@ void VariableBoxController::ContentViewController::willDisplayCellForIndex(Highl
myCell->displayExpression(true);
if (evaluation) {
/* TODO: implement list contexts */
myCell->setExpression(evaluation);
// TODO: handle matrix and scalar!
const Matrix * matrixEvaluation = static_cast<const Matrix *>(evaluation);
myCell->setExpression(matrixEvaluation);
char buffer[2*PrintFloat::bufferSizeForFloatsWithPrecision(2)+1];
int numberOfChars = Complex<float>::convertFloatToText(evaluation->numberOfRows(), buffer, PrintFloat::bufferSizeForFloatsWithPrecision(2), 2, Expression::FloatDisplayMode::Decimal);
int numberOfChars = Complex<float>::convertFloatToText(matrixEvaluation->numberOfRows(), buffer, PrintFloat::bufferSizeForFloatsWithPrecision(2), 2, Expression::FloatDisplayMode::Decimal);
buffer[numberOfChars++] = 'x';
Complex<float>::convertFloatToText(evaluation->numberOfColumns(), buffer+numberOfChars, PrintFloat::bufferSizeForFloatsWithPrecision(2), 2, Expression::FloatDisplayMode::Decimal);
Complex<float>::convertFloatToText(matrixEvaluation->numberOfColumns(), buffer+numberOfChars, PrintFloat::bufferSizeForFloatsWithPrecision(2), 2, Expression::FloatDisplayMode::Decimal);
myCell->setSubtitle(buffer);
} else {
myCell->setExpression(nullptr);
@@ -167,7 +169,7 @@ KDCoordinate VariableBoxController::ContentViewController::rowHeight(int index)
if (m_currentPage == Page::Scalar) {
return k_leafRowHeight;
}
const Evaluation<double> * expression = expressionForIndex(index);
const Expression * expression = expressionForIndex(index);
if (expression) {
ExpressionLayout * layout = expression->createLayout();
KDCoordinate expressionHeight = layout->size().height();
@@ -201,14 +203,14 @@ int VariableBoxController::ContentViewController::typeAtLocation(int i, int j) {
return 0;
}
const Evaluation<double> * VariableBoxController::ContentViewController::expressionForIndex(int index) {
const Expression * VariableBoxController::ContentViewController::expressionForIndex(int index) {
if (m_currentPage == Page::Scalar) {
const Symbol symbol = Symbol('A'+index);
return m_context->evaluationForSymbol(&symbol);
return m_context->expressionForSymbol(&symbol);
}
if (m_currentPage == Page::Matrix) {
const Symbol symbol = Symbol::matrixSymbol('0'+(char)index);
return m_context->evaluationForSymbol(&symbol);
return m_context->expressionForSymbol(&symbol);
}
#if LIST_VARIABLES
if (m_currentPage == Page::List) {

View File

@@ -56,7 +56,7 @@ private:
Page pageAtIndex(int index);
void putLabelAtIndexInBuffer(int index, char * buffer);
I18n::Message nodeLabelAtIndex(int index);
const Poincare::Evaluation<double> * expressionForIndex(int index);
const Poincare::Expression * expressionForIndex(int index);
Poincare::GlobalContext * m_context;
TextField * m_textFieldCaller;

View File

@@ -15,6 +15,7 @@ class ExpressionView : public View {
public:
ExpressionView(float horizontalAlignment = 0.0f, float verticalAlignment = 0.5f,
KDColor textColor = KDColorBlack, KDColor backgroundColor = KDColorWhite);
Poincare::ExpressionLayout * expressionLayout() const;
void setExpression(Poincare::ExpressionLayout * expressionLayout);
void drawRect(KDContext * ctx, KDRect rect) const override;
void setBackgroundColor(KDColor backgroundColor);

View File

@@ -71,7 +71,7 @@ protected:
* [[1.234567e-123*e^(1.234567e-123*i), 1.234567e-123*e^(1.234567e-123*i)]]).
* In order to be able to record those output text, k_maxBufferSize must be
* over 70. */
constexpr static int k_maxBufferSize = 100;
constexpr static int k_maxBufferSize = 152;
private:
int numberOfSubviews() const override { return 1; }
void layoutSubviews() override;

View File

@@ -8,8 +8,10 @@ EvenOddCell::EvenOddCell() :
}
void EvenOddCell::setEven(bool even) {
if (even != m_even) {
m_even = even;
reloadCell();
}
}
KDColor EvenOddCell::backgroundColor() const {

View File

@@ -11,19 +11,27 @@ ExpressionView::ExpressionView(float horizontalAlignment, float verticalAlignmen
{
}
ExpressionLayout * ExpressionView::expressionLayout() const {
return m_expressionLayout;
}
void ExpressionView::setExpression(ExpressionLayout * expressionLayout) {
m_expressionLayout = expressionLayout;
markRectAsDirty(bounds());
}
void ExpressionView::setBackgroundColor(KDColor backgroundColor) {
m_backgroundColor = backgroundColor;
markRectAsDirty(bounds());
if (m_backgroundColor != backgroundColor) {
m_backgroundColor = backgroundColor;
markRectAsDirty(bounds());
}
}
void ExpressionView::setTextColor(KDColor textColor) {
m_textColor = textColor;
markRectAsDirty(bounds());
if (textColor != m_textColor) {
m_textColor = textColor;
markRectAsDirty(bounds());
}
}
void ExpressionView::setAlignment(float horizontalAlignment, float verticalAlignment) {

View File

@@ -22,6 +22,9 @@ enum Charset : char {
Root = (char)144,
LessEqual = (char)145,
GreaterEqual = (char)146,
MultiplicationSign = (char)147,
MiddleDot = (char)148,
AlmostEqual = (char)149
};
}

View File

@@ -31,6 +31,7 @@ static constexpr const char k_complexI[2] = {Ion::Charset::IComplex, 0};
static constexpr const char k_exponential[5] = {Ion::Charset::Exponential, '^', '(', ')', 0};
static constexpr const char k_sto[2] = {Ion::Charset::Sto, 0};
static constexpr const char k_exponent[2] = {Ion::Charset::Exponent, 0};
static constexpr const char k_multiplicationSign[2] = {Ion::Charset::MultiplicationSign, 0};
static constexpr EventData s_dataForEvent[4*Event::PageSize] = {
// Plain
@@ -40,7 +41,7 @@ static constexpr EventData s_dataForEvent[4*Event::PageSize] = {
T(k_exponential), T("ln()"), T("log()"), T(k_complexI), T(","), T("^"),
T("sin()"), T("cos()"), T("tan()"), T(k_pi), T(k_root), T("^2"),
T("7"), T("8"), T("9"), T("("), T(")"), U(),
T("4"), T("5"), T("6"), T("*"), T("/"), U(),
T("4"), T("5"), T("6"), T(k_multiplicationSign), T("/"), U(),
T("1"), T("2"), T("3"), T("+"), T("-"), U(),
T("0"), T("."), T(k_exponent), TL(), TL(), U(),
// Shift

View File

@@ -2,4 +2,4 @@
wchar_t codePointForSymbol[NUMBER_OF_SYMBOLS] = {0x222b, 0x0078, 0x0305,
0x0079, 0x0305, 0x0393, 0x03a3, 0x03b8, 0x03bb, 0x03bc, 0x03c0, 0x03c3, 0x0456,
0x1D07, 0x2032, 0x212e, 0x2192, 0x221A, 0x2264, 0x2265};
0x1D07, 0x2032, 0x212e, 0x2192, 0x221A, 0x2264, 0x2265, 0x00D7, 0x00B7, 0x2248};

View File

@@ -3,7 +3,7 @@
#include <stddef.h>
#define NUMBER_OF_SYMBOLS 20
#define NUMBER_OF_SYMBOLS 23
extern wchar_t codePointForSymbol[NUMBER_OF_SYMBOLS];

View File

@@ -7,8 +7,8 @@ template <class T> struct remove_reference {typedef T type;};
template <class T> struct remove_reference<T&> {typedef T type;};
template <class T> struct remove_reference<T&&> {typedef T type;};
template <class T> typename remove_reference<T>::type&& move(T&&) {
return a;
template <class T> typename remove_reference<T>::type&& move(T&& a) {
return (typename remove_reference<T>::type&&)a;
}
}

View File

@@ -1,6 +1,7 @@
SFLAGS += -Ipoincare/include
#include poincare/src/simplify/Makefile
#include poincare/src/simplification/Makefile
objs += $(addprefix poincare/src/,\
absolute_value.o\
@@ -8,31 +9,32 @@ objs += $(addprefix poincare/src/,\
arc_cosine.o\
arc_sine.o\
arc_tangent.o\
binary_operation.o\
arithmetic.o\
binomial_coefficient.o\
bounded_static_hierarchy.o\
ceiling.o\
complex.o\
complex_argument.o\
complex_matrix.o\
confidence_interval.o\
conjugate.o\
cosine.o\
decimal.o\
derivative.o\
determinant.o\
division.o\
division_quotient.o\
division_remainder.o\
evaluation.o\
dynamic_hierarchy.o\
evaluation_engine.o\
expression.o\
expression_lexer.o\
expression_parser.o\
factorial.o\
floor.o\
frac_part.o\
fraction.o\
function.o\
expression_matrix.o\
global_context.o\
great_common_divisor.o\
hierarchy.o\
hyperbolic_arc_cosine.o\
hyperbolic_arc_sine.o\
hyperbolic_arc_tangent.o\
@@ -42,8 +44,8 @@ objs += $(addprefix poincare/src/,\
imaginary_part.o\
integer.o\
integral.o\
layout_engine.o\
list_data.o\
leaf_expression.o\
least_common_multiple.o\
logarithm.o\
matrix.o\
@@ -62,18 +64,24 @@ objs += $(addprefix poincare/src/,\
prediction_interval.o\
preferences.o\
product.o\
rational.o\
real_part.o\
round.o\
sequence.o\
simplification_engine.o\
sine.o\
square_root.o\
static_hierarchy.o\
store.o\
subtraction.o\
sum.o\
symbol.o\
tangent.o\
trigonometry.o\
undefined.o\
variable_context.o\
)
objs += $(addprefix poincare/src/layout/,\
baseline_relative_layout.o\
bracket_layout.o\
@@ -93,9 +101,18 @@ objs += $(addprefix poincare/src/layout/,\
)
tests += $(addprefix poincare/test/,\
arithmetic.cpp\
convert_expression_to_text.cpp\
helper.cpp\
integer.cpp\
simplify_easy.cpp\
)
testsi += $(addprefix poincare/test/,\
addition.cpp\
arithmetic.cpp\
complex.cpp\
fraction.cpp\
division.cpp\
function.cpp\
helper.cpp\
integer.cpp\
@@ -104,23 +121,8 @@ tests += $(addprefix poincare/test/,\
product.cpp\
power.cpp\
subtraction.cpp\
symbol.cpp\
trigo.cpp\
)
# tests += $(addprefix poincare/test/,\
addition.cpp\
float.cpp\
fraction.cpp\
identity.cpp\
integer.cpp\
matrix.cpp\
product.cpp\
power.cpp\
simplify_utils.cpp\
simplify_addition.cpp\
simplify_product.cpp\
subtraction.cpp\
symbol.cpp\
trigo.cpp\
)

View File

@@ -11,7 +11,7 @@ Simplify fractions
(x^2+5.x+6)/(x+2) -> x+3
Polynomials
(x+1)^2-x^2 -> 2*x+1
Fractions
Divisions
(2*x)/(x^2-1) - 1/(x-1) -> 1/(x+1)
Functional identities
ln(2x) - ln(x) -> ln(2)

View File

@@ -12,24 +12,21 @@
#include <poincare/ceiling.h>
#include <poincare/complex.h>
#include <poincare/complex_argument.h>
#include <poincare/complex_matrix.h>
#include <poincare/confidence_interval.h>
#include <poincare/conjugate.h>
#include <poincare/context.h>
#include <poincare/cosine.h>
#include <poincare/decimal.h>
#include <poincare/derivative.h>
#include <poincare/determinant.h>
#include <poincare/division.h>
#include <poincare/division_quotient.h>
#include <poincare/division_remainder.h>
#include <poincare/evaluation.h>
#include <poincare/expression.h>
#include <poincare/expression_layout.h>
#include <poincare/factorial.h>
#include <poincare/floor.h>
#include <poincare/frac_part.h>
#include <poincare/fraction.h>
#include <poincare/function.h>
#include <poincare/expression_matrix.h>
#include <poincare/global_context.h>
#include <poincare/great_common_divisor.h>
#include <poincare/hyperbolic_arc_cosine.h>
@@ -38,7 +35,6 @@
#include <poincare/hyperbolic_cosine.h>
#include <poincare/hyperbolic_sine.h>
#include <poincare/hyperbolic_tangent.h>
#include <poincare/integer.h>
#include <poincare/imaginary_part.h>
#include <poincare/integral.h>
#include <poincare/least_common_multiple.h>
@@ -58,6 +54,7 @@
#include <poincare/prediction_interval.h>
#include <poincare/preferences.h>
#include <poincare/product.h>
#include <poincare/rational.h>
#include <poincare/real_part.h>
#include <poincare/round.h>
#include <poincare/sine.h>
@@ -67,6 +64,7 @@
#include <poincare/sum.h>
#include <poincare/symbol.h>
#include <poincare/tangent.h>
#include <poincare/undefined.h>
#include <poincare/variable_context.h>
#endif

View File

@@ -1,25 +1,35 @@
#ifndef POINCARE_ABSOLUTE_VALUE_H
#define POINCARE_ABSOLUTE_VALUE_H
#include <poincare/function.h>
#include <poincare/static_hierarchy.h>
#include <poincare/evaluation_engine.h>
#include <poincare/layout_engine.h>
namespace Poincare {
class AbsoluteValue : public Function {
class AbsoluteValue : public StaticHierarchy<1> {
using StaticHierarchy<1>::StaticHierarchy;
public:
AbsoluteValue();
Type type() const override;
Expression * cloneWithDifferentOperands(Expression ** newOperands,
int numberOfOperands, bool cloneOperands = true) const override;
Expression * clone() const override;
Sign sign() const override { return Sign::Positive; }
private:
Complex<float> computeComplex(const Complex<float> c, AngleUnit angleUnit) const override {
return templatedComputeComplex(c);
}
Complex<double> computeComplex(const Complex<double> c, AngleUnit angleUnit) const override {
return templatedComputeComplex(c);
}
template<typename T> Complex<T> templatedComputeComplex(const Complex<T> c) const;
Expression * setSign(Sign s, Context & context, AngleUnit angleUnit) override;
/* Layout */
ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override;
int writeTextInBuffer(char * buffer, int bufferSize) const override {
return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, "abs");
}
/* Simplification */
Expression * shallowReduce(Context& context, AngleUnit angleUnit) override;
/* Evaluation */
template<typename T> static Complex<T> computeOnComplex(const Complex<T> c, AngleUnit angleUnit);
Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override {
return EvaluationEngine::map<float>(this, context, angleUnit, computeOnComplex<float>);
}
Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override {
return EvaluationEngine::map<double>(this, context, angleUnit, computeOnComplex<double>);
}
};
}

View File

@@ -1,28 +1,56 @@
#ifndef POINCARE_ADDITION_H
#define POINCARE_ADDITION_H
#include <poincare/binary_operation.h>
#include <poincare/dynamic_hierarchy.h>
#include <poincare/rational.h>
#include <poincare/layout_engine.h>
#include <poincare/evaluation_engine.h>
namespace Poincare {
class Addition : public BinaryOperation {
using BinaryOperation::BinaryOperation;
class Addition : public DynamicHierarchy {
using DynamicHierarchy::DynamicHierarchy;
friend class Logarithm;
friend class Multiplication;
friend class Subtraction;
public:
Type type() const override;
Expression * cloneWithDifferentOperands(Expression** newOperands,
int numnerOfOperands, bool cloneOperands = true) const override;
bool isCommutative() const override;
Expression * clone() const override;
/* Evaluation */
template<typename T> static Complex<T> compute(const Complex<T> c, const Complex<T> d);
template<typename T> static Evaluation<T> * computeOnMatrices(Evaluation<T> * m, Evaluation<T> * n);
template<typename T> static Evaluation<T> * computeOnComplexAndMatrix(const Complex<T> * c, Evaluation<T> * m);
template<typename T> static Matrix * computeOnMatrices(const Matrix * m, const Matrix * n) {
return EvaluationEngine::elementWiseOnComplexMatrices(m, n, compute<T>);
}
template<typename T> static Matrix * computeOnComplexAndMatrix(const Complex<T> * c, const Matrix * m) {
return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute<T>);
}
private:
Complex<float> privateCompute(const Complex<float> c, const Complex<float> d) const override {
return compute(c, d);
/* Layout */
ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override {
return LayoutEngine::createInfixLayout(this, floatDisplayMode, complexFormat, name());
}
Complex<double> privateCompute(const Complex<double> c, const Complex<double> d) const override {
return compute(c, d);
int writeTextInBuffer(char * buffer, int bufferSize) const override {
return LayoutEngine::writeInfixExpressionTextInBuffer(this, buffer, bufferSize, name());
}
ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override;
static const char * name() { return "+"; }
/* Simplification */
Expression * shallowReduce(Context& context, AngleUnit angleUnit) override;
Expression * shallowBeautify(Context & context, AngleUnit angleUnit) override;
Expression * factorizeOnCommonDenominator(Context & context, AngleUnit angleUnit);
void factorizeOperands(Expression * e1, Expression * e2, Context & context, AngleUnit angleUnit);
static const Rational RationalFactor(Expression * e);
static bool TermsHaveIdenticalNonRationalFactors(const Expression * e1, const Expression * e2);
/* Evaluation */
template<typename T> static Matrix * computeOnMatrixAndComplex(const Matrix * m, const Complex<T> * c) {
return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute<T>);
}
Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override {
return EvaluationEngine::mapReduce<float>(this, context, angleUnit, compute<float>, computeOnComplexAndMatrix<float>, computeOnMatrixAndComplex<float>, computeOnMatrices<float>);
}
Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override {
return EvaluationEngine::mapReduce<double>(this, context, angleUnit, compute<double>, computeOnComplexAndMatrix<double>, computeOnMatrixAndComplex<double>, computeOnMatrices<double>);
}
};
}

View File

@@ -1,24 +1,38 @@
#ifndef POINCARE_ARC_COSINE_H
#define POINCARE_ARC_COSINE_H
#include <poincare/function.h>
#include <poincare/layout_engine.h>
#include <poincare/static_hierarchy.h>
#include <poincare/evaluation_engine.h>
namespace Poincare {
class ArcCosine : public Function {
class ArcCosine : public StaticHierarchy<1> {
using StaticHierarchy<1>::StaticHierarchy;
public:
ArcCosine();
Type type() const override;
Expression * cloneWithDifferentOperands(Expression ** newOperands,
int numberOfOperands, bool cloneOperands = true) const override;
Expression * clone() const override;
private:
Complex<float> computeComplex(const Complex<float> c, AngleUnit angleUnit) const override {
return templatedComputeComplex(c, angleUnit);
/* Layout */
ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override {
return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name());
}
Complex<double> computeComplex(const Complex<double> c, AngleUnit angleUnit) const override {
return templatedComputeComplex(c, angleUnit);
int writeTextInBuffer(char * buffer, int bufferSize) const override {
return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name());
}
const char * name() const {
return "acos";
}
/* Simplification */
Expression * shallowReduce(Context& context, AngleUnit angleUnit) override;
/* Evaluation */
template<typename T> static Complex<T> computeOnComplex(const Complex<T> c, AngleUnit angleUnit);
Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override {
return EvaluationEngine::map<float>(this, context, angleUnit,computeOnComplex<float>);
}
Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override {
return EvaluationEngine::map<double>(this, context, angleUnit, computeOnComplex<double>);
}
template<typename T> Complex<T> templatedComputeComplex(const Complex<T> c, AngleUnit angleUnit) const;
};
}

View File

@@ -1,24 +1,36 @@
#ifndef POINCARE_ARC_SINE_H
#define POINCARE_ARC_SINE_H
#include <poincare/function.h>
#include <poincare/layout_engine.h>
#include <poincare/static_hierarchy.h>
#include <poincare/evaluation_engine.h>
namespace Poincare {
class ArcSine : public Function {
class ArcSine : public StaticHierarchy<1> {
using StaticHierarchy<1>::StaticHierarchy;
public:
ArcSine();
Type type() const override;
Expression * cloneWithDifferentOperands(Expression ** newOperands,
int numberOfOperands, bool cloneOperands = true) const override;
Expression * clone() const override;
private:
Complex<float> computeComplex(const Complex<float> c, AngleUnit angleUnit) const override {
return templatedComputeComplex(c, angleUnit);
/* Layout */
ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override {
return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name());
}
Complex<double> computeComplex(const Complex<double> c, AngleUnit angleUnit) const override {
return templatedComputeComplex(c, angleUnit);
int writeTextInBuffer(char * buffer, int bufferSize) const override {
return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name());
}
const char * name() const { return "asin"; }
/* Simplification */
Expression * shallowReduce(Context & context, AngleUnit angleUnit) override;
/* Evaluation */
template<typename T> static Complex<T> computeOnComplex(const Complex<T> c, AngleUnit angleUnit);
Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override {
return EvaluationEngine::map<float>(this, context, angleUnit,computeOnComplex<float>);
}
Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override {
return EvaluationEngine::map<double>(this, context, angleUnit, computeOnComplex<double>);
}
template<typename T> Complex<T> templatedComputeComplex(const Complex<T> c, AngleUnit angleUnit) const;
};
}

View File

@@ -1,24 +1,36 @@
#ifndef POINCARE_ARC_TANGENT_H
#define POINCARE_ARC_TANGENT_H
#include <poincare/function.h>
#include <poincare/layout_engine.h>
#include <poincare/static_hierarchy.h>
#include <poincare/evaluation_engine.h>
namespace Poincare {
class ArcTangent: public Function {
class ArcTangent : public StaticHierarchy<1> {
using StaticHierarchy<1>::StaticHierarchy;
public:
ArcTangent();
Type type() const override;
Expression * cloneWithDifferentOperands(Expression ** newOperands,
int numberOfOperands, bool cloneOperands = true) const override;
Expression * clone() const override;
private:
Complex<float> computeComplex(const Complex<float> c, AngleUnit angleUnit) const override {
return templatedComputeComplex(c, angleUnit);
/* Layout */
ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override {
return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name());
}
Complex<double> computeComplex(const Complex<double> c, AngleUnit angleUnit) const override {
return templatedComputeComplex(c, angleUnit);
int writeTextInBuffer(char * buffer, int bufferSize) const override {
return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name());
}
const char * name() const { return "atan"; }
/* Simplification */
Expression * shallowReduce(Context& context, AngleUnit angleUnit) override;
/* Evaluation */
template<typename T> static Complex<T> computeOnComplex(const Complex<T> c, AngleUnit angleUnit);
Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override {
return EvaluationEngine::map<float>(this, context, angleUnit,computeOnComplex<float>);
}
Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override {
return EvaluationEngine::map<double>(this, context, angleUnit, computeOnComplex<double>);
}
template<typename T> Complex<T> templatedComputeComplex(const Complex<T> c, AngleUnit angleUnit) const;
};
}

View File

@@ -0,0 +1,19 @@
#ifndef POINCARE_ARITHMETIC_H
#define POINCARE_ARITHMETIC_H
#include <poincare/integer.h>
namespace Poincare {
class Arithmetic {
public:
static Integer LCM(const Integer * i, const Integer * j);
static Integer GCD(const Integer * i, const Integer * j);
static void PrimeFactorization(const Integer * i, Integer * outputFactors, Integer * outputCoefficients, int outputLength);
constexpr static int k_numberOfPrimeFactors = 1000;
constexpr static int k_maxNumberOfPrimeFactors = 32;
static const Integer k_primorial32;
};
}
#endif

View File

@@ -1,60 +0,0 @@
#ifndef POINCARE_BINARY_OPERATION_H
#define POINCARE_BINARY_OPERATION_H
#include <poincare/expression.h>
#include <poincare/matrix.h>
#include <poincare/complex.h>
#include <poincare/complex_matrix.h>
namespace Poincare {
class BinaryOperation : public Expression {
public:
BinaryOperation();
BinaryOperation(Expression ** operands, bool cloneOperands = true);
~BinaryOperation();
BinaryOperation(const BinaryOperation& other) = delete;
BinaryOperation(BinaryOperation&& other) = delete;
BinaryOperation& operator=(const BinaryOperation& other) = delete;
BinaryOperation& operator=(BinaryOperation&& other) = delete;
bool hasValidNumberOfArguments() const override;
const Expression * operand(int i) const override;
int numberOfOperands() const override;
Expression * clone() const override;
protected:
Expression * m_operands[2];
virtual Evaluation<float> * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<float>(context, angleUnit); }
virtual Evaluation<double> * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<double>(context, angleUnit); }
template<typename T> Evaluation<T> * templatedEvaluate(Context& context, AngleUnit angleUnit) const;
virtual Evaluation<float> * computeOnComplexAndComplexMatrix(const Complex<float> * c, Evaluation<float> * n) const {
return templatedComputeOnComplexAndComplexMatrix(c, n);
}
virtual Evaluation<double> * computeOnComplexAndComplexMatrix(const Complex<double> * c, Evaluation<double> * n) const {
return templatedComputeOnComplexAndComplexMatrix(c, n);
}
template<typename T> Evaluation<T> * templatedComputeOnComplexAndComplexMatrix(const Complex<T> * c, Evaluation<T> * n) const;
virtual Evaluation<float> * computeOnComplexMatrixAndComplex(Evaluation<float> * m, const Complex<float> * d) const {
return templatedComputeOnComplexMatrixAndComplex(m, d);
}
virtual Evaluation<double> * computeOnComplexMatrixAndComplex(Evaluation<double> * m, const Complex<double> * d) const {
return templatedComputeOnComplexMatrixAndComplex(m, d);
}
template<typename T> Evaluation<T> * templatedComputeOnComplexMatrixAndComplex(Evaluation<T> * m, const Complex<T> * d) const;
virtual Evaluation<float> * computeOnComplexMatrices(Evaluation<float> * m, Evaluation<float> * n) const {
return templatedComputeOnComplexMatrices(m, n);
}
virtual Evaluation<double> * computeOnComplexMatrices(Evaluation<double> * m, Evaluation<double> * n) const {
return templatedComputeOnComplexMatrices(m, n);
}
template<typename T> Evaluation<T> * templatedComputeOnComplexMatrices(Evaluation<T> * m, Evaluation<T> * n) const;
virtual Complex<float> privateCompute(const Complex<float> c, const Complex<float> d) const = 0;
virtual Complex<double> privateCompute(const Complex<double> c, const Complex<double> d) const = 0;
};
}
#endif

View File

@@ -1,21 +1,29 @@
#ifndef POINCARE_BINOMIAL_COEFFICIENT_H
#define POINCARE_BINOMIAL_COEFFICIENT_H
#include <poincare/function.h>
#include <poincare/layout_engine.h>
#include <poincare/static_hierarchy.h>
namespace Poincare {
class BinomialCoefficient : public Function {
class BinomialCoefficient : public StaticHierarchy<2> {
using StaticHierarchy<2>::StaticHierarchy;
public:
BinomialCoefficient();
Type type() const override;
Expression * cloneWithDifferentOperands(Expression ** newOperands,
int numberOfOperands, bool cloneOperands = true) const override;
Expression * clone() const override;
private:
Evaluation<float> * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<float>(context, angleUnit); }
Evaluation<double> * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<double>(context, angleUnit); }
template<typename T> Evaluation<T> * templatedEvaluate(Context& context, AngleUnit angleUnit) const;
constexpr static int k_maxNValue = 300;
/* Layout */
ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override;
int writeTextInBuffer(char * buffer, int bufferSize) const override {
return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, "binomial");
}
/* Simplification */
Expression * shallowReduce(Context& context, AngleUnit angleUnit) override;
/* Evaluation */
Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<float>(context, angleUnit); }
Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<double>(context, angleUnit); }
template<typename T> Expression * templatedEvaluate(Context& context, AngleUnit angleUnit) const;
};
}

View File

@@ -0,0 +1,24 @@
#ifndef POINCARE_BOUNDED_STATIC_HIERARCHY_H
#define POINCARE_BOUNDED_STATIC_HIERARCHY_H
#include <poincare/static_hierarchy.h>
namespace Poincare {
template<int T>
class BoundedStaticHierarchy : public StaticHierarchy<T> {
public:
BoundedStaticHierarchy();
BoundedStaticHierarchy(const Expression * expression, bool cloneOperands = true); // Specialized constructor for StaticHierarchy<2>
BoundedStaticHierarchy(const Expression * expression1, const Expression * expression2, bool cloneOperands = true); // Specialized constructor for StaticHierarchy<2>
BoundedStaticHierarchy(const Expression * const * operands, int numberOfOperands, bool cloneOperands = true);
void setArgument(ListData * listData, int numberOfEntries, bool clone) override;
int numberOfOperands() const override { return m_numberOfOperands; }
bool hasValidNumberOfOperands(int numberOfOperands) const override;
private:
int m_numberOfOperands;
};
}
#endif

View File

@@ -1,25 +1,34 @@
#ifndef POINCARE_CEILING_H
#define POINCARE_CEILING_H
#include <poincare/function.h>
#include <poincare/layout_engine.h>
#include <poincare/static_hierarchy.h>
#include <poincare/evaluation_engine.h>
namespace Poincare {
class Ceiling : public Function {
class Ceiling : public StaticHierarchy<1> {
using StaticHierarchy<1>::StaticHierarchy;
public:
Ceiling();
Type type() const override;
Expression * cloneWithDifferentOperands(Expression ** newOperands,
int numberOfOperands, bool cloneOperands = true) const override;
Expression * clone() const override;
private:
Complex<float> computeComplex(const Complex<float> c, AngleUnit angleUnit) const override {
return templatedComputeComplex(c);
}
Complex<double> computeComplex(const Complex<double> c, AngleUnit angleUnit) const override {
return templatedComputeComplex(c);
}
template<typename T> Complex<T> templatedComputeComplex(const Complex<T> c) const;
/* Layout */
ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override;
int writeTextInBuffer(char * buffer, int bufferSize) const override {
return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name());
}
const char * name() const { return "ceil"; }
/* Simplification */
Expression * shallowReduce(Context& context, AngleUnit angleUnit) override;
/* Evaluation */
template<typename T> static Complex<T> computeOnComplex(const Complex<T> c, AngleUnit angleUnit);
Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override {
return EvaluationEngine::map<float>(this, context, angleUnit, computeOnComplex<float>);
}
Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override {
return EvaluationEngine::map<double>(this, context, angleUnit, computeOnComplex<double>);
}
};
}

View File

@@ -1,8 +1,9 @@
#ifndef POINCARE_COMPLEX_H
#define POINCARE_COMPLEX_H
#include <poincare/evaluation.h>
#include <poincare/preferences.h>
#include <poincare/static_hierarchy.h>
#include <assert.h>
namespace Poincare {
@@ -22,7 +23,7 @@ namespace PrintFloat {
}
template<typename T>
class Complex : public Evaluation<T> {
class Complex : public StaticHierarchy<0> {
public:
Complex() : m_a(0), m_b(0) {}
static Complex<T> Float(T x);
@@ -31,29 +32,21 @@ public:
Complex(const char * integralPart, int integralPartLength, bool integralNegative,
const char * fractionalPart, int fractionalPartLength,
const char * exponent, int exponentLength, bool exponentNegative);
T toScalar() const override;
const Complex<T> * operand(int i) const override {
return complexOperand(i);
}
int numberOfRows() const override;
int numberOfColumns() const override;
Expression::Type type() const override;
Complex<T> * clone() const override;
Evaluation<T> * cloneWithDifferentOperands(Expression** newOperands,
int numberOfOperands, bool cloneOperands = true) const override;
int writeTextInBuffer(char * buffer, int bufferSize) const override;
Evaluation<T> * createDeterminant() const override {
return clone();
}
Evaluation<T> * createInverse() const override;
Evaluation<T> * createTrace() const override {
return clone();
}
Complex(const Complex & other);
Complex& operator=(const Complex& other);
T a() const;
T b() const;
T r() const;
T th() const;
Complex<T> conjugate() const;
T toScalar() const;
/* Expression */
Expression::Type type() const override;
Complex<T> * clone() const override;
int writeTextInBuffer(char * buffer, int bufferSize) const override;
/* The parameter 'DisplayMode' refers to the way to display float 'scientific'
* or 'auto'. The scientific mode returns float with style -1.2E2 whereas
* the auto mode tries to return 'natural' float like (0.021) and switches
@@ -68,12 +61,11 @@ public:
static int convertFloatToText(T d, char * buffer, int bufferSize, int numberOfSignificantDigits, Expression::FloatDisplayMode mode = Expression::FloatDisplayMode::Default);
private:
Complex(T a, T b);
const Complex<T> * complexOperand(int i) const override;
constexpr static int k_numberOfSignificantDigits = 7;
ExpressionLayout * privateCreateLayout(Expression::FloatDisplayMode floatDisplayMode, Expression::ComplexFormat complexFormat) const override;
Evaluation<float> * privateEvaluate(Expression::SinglePrecision p, Context& context, Expression::AngleUnit angleUnit) const override { return templatedEvaluate<float>(context, angleUnit); }
Evaluation<double> * privateEvaluate(Expression::DoublePrecision p, Context& context, Expression::AngleUnit angleUnit) const override { return templatedEvaluate<double>(context, angleUnit); }
template<typename U> Evaluation<U> * templatedEvaluate(Context& context, Expression::AngleUnit angleUnit) const;
Expression * privateEvaluate(Expression::SinglePrecision p, Context& context, Expression::AngleUnit angleUnit) const override { return templatedEvaluate<float>(context, angleUnit); }
Expression * privateEvaluate(Expression::DoublePrecision p, Context& context, Expression::AngleUnit angleUnit) const override { return templatedEvaluate<double>(context, angleUnit); }
template<typename U> Complex<U> * templatedEvaluate(Context& context, Expression::AngleUnit angleUnit) const;
/* We here define the buffer size to write the lengthest float possible.
* At maximum, the number has 7 significant digits so, in the worst case it
* has the form -1.999999e-308 (7+7+1 char) (the auto mode is always

View File

@@ -1,24 +1,36 @@
#ifndef POINCARE_COMPLEX_ARGUMENT_H
#define POINCARE_COMPLEX_ARGUMENT_H
#include <poincare/function.h>
#include <poincare/layout_engine.h>
#include <poincare/static_hierarchy.h>
#include <poincare/evaluation_engine.h>
namespace Poincare {
class ComplexArgument : public Function {
class ComplexArgument : public StaticHierarchy<1> {
using StaticHierarchy<1>::StaticHierarchy;
public:
ComplexArgument();
Type type() const override;
Expression * cloneWithDifferentOperands(Expression ** newOperands,
int numberOfOperands, bool cloneOperands = true) const override;
Expression * clone() const override;
private:
Complex<float> computeComplex(const Complex<float> c, AngleUnit angleUnit) const override {
return templatedComputeComplex(c);
/* Layout */
ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override {
return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name());
}
Complex<double> computeComplex(const Complex<double> c, AngleUnit angleUnit) const override {
return templatedComputeComplex(c);
int writeTextInBuffer(char * buffer, int bufferSize) const override {
return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name());
}
const char * name() const { return "arg"; }
/* Simplification */
Expression * shallowReduce(Context& context, AngleUnit angleUnit) override;
/* Evaluation */
template<typename T> static Complex<T> computeOnComplex(const Complex<T> c, AngleUnit angleUnit);
Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override {
return EvaluationEngine::map<float>(this, context, angleUnit,computeOnComplex<float>);
}
Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override {
return EvaluationEngine::map<double>(this, context, angleUnit, computeOnComplex<double>);
}
template<typename T> Complex<T> templatedComputeComplex(const Complex<T> c) const;
};
}

View File

@@ -1,37 +0,0 @@
#ifndef POINCARE_COMPLEX_MATRIX_H
#define POINCARE_COMPLEX_MATRIX_H
#include <poincare/evaluation.h>
namespace Poincare {
template<typename T>
class ComplexMatrix : public Evaluation<T> {
public:
ComplexMatrix(const Complex<T> * complexes, int numberOfRows, int numberOfColumns);
~ComplexMatrix();
ComplexMatrix(const ComplexMatrix& other) = delete;
ComplexMatrix(ComplexMatrix&& other) = delete;
ComplexMatrix& operator=(const ComplexMatrix& other) = delete;
ComplexMatrix& operator=(ComplexMatrix&& other) = delete;
T toScalar() const override;
const Complex<T> * complexOperand(int i) const override;
int numberOfRows() const override;
int numberOfColumns() const override;
ComplexMatrix<T> * clone() const override;
ComplexMatrix<T> * cloneWithDifferentOperands(Expression** newOperands,
int numberOfOperands, bool cloneOperands = true) const override;
static Evaluation<T> * createIdentity(int dim);
private:
Evaluation<float> * privateEvaluate(Expression::SinglePrecision p, Context& context, Expression::AngleUnit angleUnit) const override { return templatedEvaluate<float>(context, angleUnit); }
Evaluation<double> * privateEvaluate(Expression::DoublePrecision p, Context& context, Expression::AngleUnit angleUnit) const override { return templatedEvaluate<double>(context, angleUnit); }
template<typename U> Evaluation<U> * templatedEvaluate(Context& context, Expression::AngleUnit angleUnit) const;
Complex<T> * m_values;
int m_numberOfRows;
int m_numberOfColumns;
};
}
#endif

View File

@@ -1,20 +1,31 @@
#ifndef POINCARE_CONFIDENCE_INTERVAL_H
#define POINCARE_CONFIDENCE_INTERVAL_H
#include <poincare/function.h>
#include <poincare/layout_engine.h>
#include <poincare/static_hierarchy.h>
namespace Poincare {
class ConfidenceInterval : public Function {
class ConfidenceInterval : public StaticHierarchy<2> {
using StaticHierarchy<2>::StaticHierarchy;
public:
ConfidenceInterval();
Type type() const override;
Expression * cloneWithDifferentOperands(Expression ** newOperands,
int numberOfOperands, bool cloneOperands = true) const override;
Expression * clone() const override;
private:
Evaluation<float> * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<float>(context, angleUnit); }
Evaluation<double> * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<double>(context, angleUnit); }
template<typename T> Evaluation<T> * templatedEvaluate(Context& context, AngleUnit angleUnit) const;
/* Layout */
ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override {
return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name());
}
int writeTextInBuffer(char * buffer, int bufferSize) const override {
return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name());
}
const char * name() const { return "confidence"; }
/* Simplification */
Expression * shallowReduce(Context& context, AngleUnit angleUnit) override;
/* Evaluation */
Expression * privateEvaluate(Expression::SinglePrecision p, Context& context, Expression::AngleUnit angleUnit) const override { return templatedEvaluate<float>(context, angleUnit); }
Expression * privateEvaluate(Expression::DoublePrecision p, Context& context, Expression::AngleUnit angleUnit) const override { return templatedEvaluate<float>(context, angleUnit); }
template<typename T> Expression * templatedEvaluate(Context& context, AngleUnit angleUnit) const;
};
}

View File

@@ -1,25 +1,33 @@
#ifndef POINCARE_CONJUGATE_H
#define POINCARE_CONJUGATE_H
#include <poincare/function.h>
#include <poincare/static_hierarchy.h>
#include <poincare/evaluation_engine.h>
#include <poincare/layout_engine.h>
namespace Poincare {
class Conjugate : public Function {
class Conjugate : public StaticHierarchy<1> {
using StaticHierarchy<1>::StaticHierarchy;
public:
Conjugate();
Type type() const override;
Expression * cloneWithDifferentOperands(Expression ** newOperands,
int numberOfOperands, bool cloneOperands = true) const override;
Expression * clone() const override;
private:
Complex<float> computeComplex(const Complex<float> c, AngleUnit angleUnit) const override {
return templatedComputeComplex(c);
}
Complex<double> computeComplex(const Complex<double> c, AngleUnit angleUnit) const override {
return templatedComputeComplex(c);
}
template<typename T> Complex<T> templatedComputeComplex(const Complex<T> c) const;
/* Layout */
ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override;
int writeTextInBuffer(char * buffer, int bufferSize) const override {
return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, "conjugate");
}
/* Simplification */
Expression * shallowReduce(Context& context, AngleUnit angleUnit) override;
/* Evaluation */
template<typename T> static Complex<T> computeOnComplex(const Complex<T> c, AngleUnit angleUnit);
Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override {
return EvaluationEngine::map<float>(this, context, angleUnit,computeOnComplex<float>);
}
Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override {
return EvaluationEngine::map<double>(this, context, angleUnit, computeOnComplex<double>);
}
};
}

View File

@@ -9,7 +9,7 @@ namespace Poincare {
class Context {
public:
virtual const Expression * expressionForSymbol(const Symbol * symbol) = 0;
virtual void setExpressionForSymbolName(Expression * expression, const Symbol * symbol) = 0;
virtual void setExpressionForSymbolName(const Expression * expression, const Symbol * symbol, Context & context) = 0;
};
}

View File

@@ -1,23 +1,37 @@
#ifndef POINCARE_COSINE_H
#define POINCARE_COSINE_H
#include <poincare/function.h>
#include <poincare/layout_engine.h>
#include <poincare/static_hierarchy.h>
#include <poincare/evaluation_engine.h>
#include <poincare/trigonometry.h>
namespace Poincare {
class Cosine : public Function {
class Cosine : public StaticHierarchy<1>::StaticHierarchy {
using StaticHierarchy<1>::StaticHierarchy;
friend class Tangent;
public:
Cosine();
Type type() const override;
Expression * cloneWithDifferentOperands(Expression ** newOperands,
int numberOfOperands, bool cloneOperands = true) const override;
template<typename T> static Complex<T> compute(const Complex<T> c, AngleUnit angleUnit = AngleUnit::Radian);
Expression * clone() const override;
template<typename T> static Complex<T> computeOnComplex(const Complex<T> c, AngleUnit angleUnit = AngleUnit::Radian);
private:
Complex<float> computeComplex(const Complex<float> c, AngleUnit angleUnit) const override {
return compute(c, angleUnit);
/* Layout */
ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override {
return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name());
}
Complex<double> computeComplex(const Complex<double> c, AngleUnit angleUnit) const override {
return compute(c, angleUnit);
int writeTextInBuffer(char * buffer, int bufferSize) const override {
return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name());
}
const char * name() const { return "cos"; }
/* Simplication */
Expression * shallowReduce(Context& context, AngleUnit angleUnit) override;
/* Evaluation */
Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override {
return EvaluationEngine::map<float>(this, context, angleUnit,computeOnComplex<float>);
}
Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override {
return EvaluationEngine::map<double>(this, context, angleUnit, computeOnComplex<double>);
}
};

View File

@@ -0,0 +1,51 @@
#ifndef POINCARE_DECIMAL_H
#define POINCARE_DECIMAL_H
#include <poincare/static_hierarchy.h>
#include <poincare/integer.h>
namespace Poincare {
/* A decimal as 0.01234 is stored that way:
* - m_mantissa = 1234
* - m_exponent = -2
*/
class Decimal : public StaticHierarchy<0> {
public:
static int exponent(const char * integralPart, int integralPartLength, const char * fractionalPart, int fractionalPartLength, const char * exponent, int exponentLength, bool exponentNegative);
static Integer mantissa(const char * integralPart, int integralPartLength, const char * fractionalPart, int fractionalPartLength, bool negative);
Decimal(Integer mantissa, int exponent);
Decimal(double f);
int exponent() const { return m_exponent; }
Integer mantissa() const { return m_mantissa; }
// Expression subclassing
Type type() const override;
Expression * clone() const override;
int writeTextInBuffer(char * buffer, int bufferSize) const override;
Sign sign() const override { return m_mantissa.isNegative() ? Sign::Negative : Sign::Positive; }
private:
constexpr static int k_doublePrecision = 15;
constexpr static double k_biggestMantissaFromDouble = 999999999999999;
constexpr static int k_maxDoubleExponent = 308;
int numberOfDigitsInMantissaWithoutSign() const;
/* Comparison */
int simplificationOrderSameType(const Expression * e) const override;
/* Layout */
ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override;
/* Simplification */
Expression * shallowReduce(Context& context, AngleUnit angleUnit) override;
Expression * shallowBeautify(Context& context, AngleUnit angleUnit) override;
/* Evaluation */
Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<float>(context, angleUnit); }
Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<double>(context, angleUnit); }
template<typename T> Expression * templatedEvaluate(Context& context, Expression::AngleUnit angleUnit) const;
constexpr static int k_maxLength = 10;
Integer m_mantissa;
int m_exponent;
};
}
#endif

View File

@@ -1,21 +1,32 @@
#ifndef POINCARE_DERIVATIVE_H
#define POINCARE_DERIVATIVE_H
#include <poincare/function.h>
#include <poincare/layout_engine.h>
#include <poincare/static_hierarchy.h>
#include <poincare/variable_context.h>
namespace Poincare {
class Derivative : public Function {
class Derivative : public StaticHierarchy<2> {
using StaticHierarchy<2>::StaticHierarchy;
public:
Derivative();
Type type() const override;
Expression * cloneWithDifferentOperands(Expression ** newOperands,
int numberOfOperands, bool cloneOperands = true) const override;
Expression * clone() const override;
private:
Evaluation<float> * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<float>(context, angleUnit); }
Evaluation<double> * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<double>(context, angleUnit); }
template<typename T> Evaluation<T> * templatedEvaluate(Context& context, AngleUnit angleUnit) const;
/* Layout */
ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override {
return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name());
}
int writeTextInBuffer(char * buffer, int bufferSize) const override {
return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name());
}
const char * name() const { return "diff"; }
/* Simplification */
Expression * shallowReduce(Context& context, AngleUnit angleUnit) override;
/* Evaluation */
Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<float>(context, angleUnit); }
Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<double>(context, angleUnit); }
template<typename T> Expression * templatedEvaluate(Context& context, AngleUnit angleUnit) const;
template<typename T> T growthRateAroundAbscissa(T x, T h, VariableContext<T> variableContext, AngleUnit angleUnit) const;
template<typename T> T approximateDerivate2(T x, T h, VariableContext<T> xContext, AngleUnit angleUnit) const;
// TODO: Change coefficients?

View File

@@ -1,20 +1,32 @@
#ifndef POINCARE_DETERMINANT_H
#define POINCARE_DETERMINANT_H
#include <poincare/function.h>
#include <poincare/layout_engine.h>
#include <poincare/static_hierarchy.h>
#include <poincare/complex.h>
namespace Poincare {
class Determinant : public Function {
class Determinant : public StaticHierarchy<1> {
using StaticHierarchy<1>::StaticHierarchy;
public:
Determinant();
Type type() const override;
Expression * cloneWithDifferentOperands(Expression ** newOperands,
int numberOfOperands, bool cloneOperands = true) const override;
Expression * clone() const override;
private:
Evaluation<float> * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<float>(context, angleUnit); }
Evaluation<double> * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<double>(context, angleUnit); }
template<typename T> Evaluation<T> * templatedEvaluate(Context& context, AngleUnit angleUnit) const;
/* Layout */
ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override {
return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name());
}
int writeTextInBuffer(char * buffer, int bufferSize) const override {
return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name());
}
const char * name() const { return "det"; }
/* Simplification */
Expression * shallowReduce(Context & context, AngleUnit angleUnit) override;
/* Evaluation */
Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<float>(context, angleUnit); }
Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<double>(context, angleUnit); }
template<typename T> Expression * templatedEvaluate(Context& context, AngleUnit angleUnit) const;
};
}

View File

@@ -0,0 +1,45 @@
#ifndef POINCARE_DIVISION_H
#define POINCARE_DIVISION_H
#include <poincare/static_hierarchy.h>
#include <poincare/evaluation_engine.h>
#include <poincare/layout_engine.h>
namespace Poincare {
class Division : public StaticHierarchy<2> {
using StaticHierarchy<2>::StaticHierarchy;
friend class Multiplication;
friend class Power;
public:
Type type() const override;
Expression * clone() const override;
template<typename T> static Complex<T> compute(const Complex<T> c, const Complex<T> d);
private:
/* Layout */
ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override;
int writeTextInBuffer(char * buffer, int bufferSize) const override {
return LayoutEngine::writeInfixExpressionTextInBuffer(this, buffer, bufferSize, "/", [](const Expression * e) {
return e->type() == Type::Multiplication || e->type() == Type::Addition || e->type() == Type::Subtraction || e->type() == Type::Opposite;
});
}
/* Simplification */
Expression * shallowReduce(Context& context, AngleUnit angleUnit) override;
/* Evaluation */
template<typename T> static Matrix * computeOnMatrixAndComplex(const Matrix * m, const Complex<T> * c) {
return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute<T>);
}
template<typename T> static Matrix * computeOnComplexAndMatrix(const Complex<T> * c, const Matrix * n);
template<typename T> static Matrix * computeOnMatrices(const Matrix * m, const Matrix * n);
virtual Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override {
return EvaluationEngine::mapReduce<float>(this, context, angleUnit, compute<float>, computeOnComplexAndMatrix<float>, computeOnMatrixAndComplex<float>, computeOnMatrices<float>);
}
virtual Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override {
return EvaluationEngine::mapReduce<double>(this, context, angleUnit, compute<double>, computeOnComplexAndMatrix<double>, computeOnMatrixAndComplex<double>, computeOnMatrices<double>);
}
};
}
#endif

View File

@@ -1,20 +1,32 @@
#ifndef POINCARE_DIVISION_QUOTIENT_H
#define POINCARE_DIVISION_QUOTIENT_H
#include <poincare/function.h>
#include <poincare/layout_engine.h>
#include <poincare/static_hierarchy.h>
#include <poincare/complex.h>
namespace Poincare {
class DivisionQuotient : public Function {
class DivisionQuotient : public StaticHierarchy<2> {
using StaticHierarchy<2>::StaticHierarchy;
public:
DivisionQuotient();
Type type() const override;
Expression * cloneWithDifferentOperands(Expression ** newOperands,
int numberOfOperands, bool cloneOperands = true) const override;
Expression * clone() const override;
private:
Evaluation<float> * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<float>(context, angleUnit); }
Evaluation<double> * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<double>(context, angleUnit); }
template<typename T> Evaluation<T> * templatedEvaluate(Context& context, AngleUnit angleUnit) const;
/* Layout */
ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override {
return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name());
}
int writeTextInBuffer(char * buffer, int bufferSize) const override {
return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name());
}
const char * name() const { return "quo"; }
/* Simplification */
Expression * shallowReduce(Context & context, AngleUnit angleUnit) override;
/* Evaluation */
Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<float>(context, angleUnit); }
Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<double>(context, angleUnit); }
template<typename T> Complex<T> * templatedEvaluate(Context& context, AngleUnit angleUnit) const;
};
}

View File

@@ -1,20 +1,33 @@
#ifndef POINCARE_DIVISION_REMAINDER_H
#define POINCARE_DIVISION_REMAINDER_H
#include <poincare/function.h>
#include <poincare/layout_engine.h>
#include <poincare/static_hierarchy.h>
#include <poincare/complex.h>
namespace Poincare {
class DivisionRemainder : public Function {
class DivisionRemainder : public StaticHierarchy<2> {
using StaticHierarchy<2>::StaticHierarchy;
public:
DivisionRemainder();
Type type() const override;
Expression * cloneWithDifferentOperands(Expression ** newOperands,
int numberOfOperands, bool cloneOperands = true) const override;
Expression * clone() const override;
private:
Evaluation<float> * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<float>(context, angleUnit); }
Evaluation<double> * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<double>(context, angleUnit); }
template<typename T> Evaluation<T> * templatedEvaluate(Context& context, AngleUnit angleUnit) const;
/* Layout */
ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override {
return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name());
}
int writeTextInBuffer(char * buffer, int bufferSize) const override {
return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name());
}
const char * name() const { return "rem"; }
/* Simplification */
Expression * shallowReduce(Context & context, AngleUnit angleUnit) override;
/* Evaluation */
Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<float>(context, angleUnit); }
Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<double>(context, angleUnit); }
template<typename T> Complex<T> * templatedEvaluate(Context& context, AngleUnit angleUnit) const;
};
}

View File

@@ -0,0 +1,43 @@
#ifndef POINCARE_DYNAMIC_HIERARCHY_H
#define POINCARE_DYNAMIC_HIERARCHY_H
#include <poincare/hierarchy.h>
#include <poincare/rational.h>
namespace Poincare {
class DynamicHierarchy : public Hierarchy {
public:
DynamicHierarchy();
DynamicHierarchy(const Expression * const * operands, int numberOfOperands, bool cloneOperands = true);
DynamicHierarchy(const Expression * operand1, const Expression * operand2, bool cloneOperands = true) :
DynamicHierarchy(ExpressionArray(operand1, operand2), 2, cloneOperands) {}
~DynamicHierarchy();
DynamicHierarchy(const DynamicHierarchy & other) = delete;
DynamicHierarchy(DynamicHierarchy && other) = delete;
DynamicHierarchy& operator=(const DynamicHierarchy & other) = delete;
DynamicHierarchy& operator=(DynamicHierarchy && other) = delete;
int numberOfOperands() const override { return m_numberOfOperands; }
const Expression * const * operands() const override { return m_operands; };
void removeOperand(const Expression * e, bool deleteAfterRemoval = true);
void addOperands(const Expression * const * operands, int numberOfOperands);
void addOperand(Expression * operand);
void addOperandAtIndex(Expression * operand, int index);
void mergeOperands(DynamicHierarchy * d);
typedef int (*ExpressionOrder)(const Expression * e1, const Expression * e2);
void sortOperands(ExpressionOrder order);
Expression * squashUnaryHierarchy();
protected:
const Expression ** m_operands;
int m_numberOfOperands;
private:
void removeOperandAtIndex(int i, bool deleteAfterRemoval);
int simplificationOrderSameType(const Expression * e) const override;
int simplificationOrderGreaterType(const Expression * e) const override;
};
}
#endif

View File

@@ -1,28 +0,0 @@
#ifndef POINCARE_EVALUATION_H
#define POINCARE_EVALUATION_H
#include <poincare/matrix.h>
namespace Poincare {
template<class T>
class Complex;
template<typename T>
class Evaluation : public Matrix {
public:
virtual T toScalar() const = 0;
Type type() const override;
bool hasValidNumberOfArguments() const override;
virtual const Expression * operand(int i) const override;
virtual const Complex<T> * complexOperand(int i) const = 0;
virtual Evaluation<T> * clone() const override = 0;
virtual Evaluation<T> * createTrace() const;
virtual Evaluation<T> * createDeterminant() const;
virtual Evaluation<T> * createInverse() const;
Evaluation<T> * createTranspose() const;
};
}
#endif

View File

@@ -0,0 +1,28 @@
#ifndef POINCARE_EVALUATION_ENGINE_H
#define POINCARE_EVALUATION_ENGINE_H
#include <poincare/expression.h>
#include <poincare/complex.h>
#include <poincare/matrix.h>
namespace Poincare {
class EvaluationEngine {
public:
template <typename T> using ComplexCompute = Complex<T>(*)(const Complex<T>, Expression::AngleUnit angleUnit);
template<typename T> static Expression * map(const Expression * expression, Context& context, Expression::AngleUnit angleUnit, ComplexCompute<T> compute);
template <typename T> using ComplexAndComplexReduction = Complex<T>(*)(const Complex<T>, const Complex<T>);
template <typename T> using ComplexAndMatrixReduction = Matrix * (*)(const Complex<T> * c, const Matrix * m);
template <typename T> using MatrixAndComplexReduction = Matrix * (*)(const Matrix * m, const Complex<T> * c);
template <typename T> using MatrixAndMatrixReduction = Matrix * (*)(const Matrix * m, const Matrix * n);
template<typename T> static Expression * mapReduce(const Expression * expression, Context& context, Expression::AngleUnit angleUnit, ComplexAndComplexReduction<T> computeOnComplexes, ComplexAndMatrixReduction<T> computeOnComplexAndMatrix, MatrixAndComplexReduction<T> computeOnMatrixAndComplex, MatrixAndMatrixReduction<T> computeOnMatrices);
template<typename T> static Matrix * elementWiseOnComplexAndComplexMatrix(const Complex<T> * c, const Matrix * n, ComplexAndComplexReduction<T> computeOnComplexes);
template<typename T> static Matrix * elementWiseOnComplexMatrices(const Matrix * m, const Matrix * n, ComplexAndComplexReduction<T> computeOnComplexes);
};
}
#endif

View File

@@ -2,38 +2,107 @@
#define POINCARE_EXPRESSION_H
#include <poincare/expression_layout.h>
#include <kandinsky.h>
extern "C" {
#include <assert.h>
}
namespace Poincare {
class Context;
template<class T>
class Evaluation;
template<class T> class Complex;
class Rational;
class Expression {
friend class Undefined;
friend class Rational;
friend class Decimal;
friend class Multiplication;
friend class Power;
friend class Addition;
friend class Factorial;
friend class Division;
friend class Store;
friend class Sine;
friend class Cosine;
friend class Tangent;
friend class AbsoluteValue;
friend class ArcCosine;
friend class ArcSine;
friend class ArcTangent;
friend class BinomialCoefficient;
friend class Ceiling;
friend class ComplexArgument;
friend class ConfidenceInterval;
friend class Conjugate;
friend class Derivative;
friend class Determinant;
friend class DivisionQuotient;
friend class DivisionRemainder;
friend class Floor;
friend class FracPart;
friend class GreatCommonDivisor;
friend class HyperbolicArcCosine;
friend class HyperbolicArcSine;
friend class HyperbolicArcTangent;
friend class HyperbolicCosine;
friend class HyperbolicSine;
friend class HyperbolicTangent;
friend class ImaginaryPart;
friend class Integral;
friend class LeastCommonMultiple;
friend class Logarithm;
friend class MatrixDimension;
friend class MatrixInverse;
friend class MatrixTrace;
friend class MatrixTranspose;
friend class NaperianLogarithm;
friend class NthRoot;
friend class Opposite;
friend class Parenthesis;
friend class PermuteCoefficient;
friend class PredictionInterval;
friend class Product;
friend class RealPart;
friend class Round;
friend class SquareRoot;
friend class Subtraction;
friend class Sum;
friend class Symbol;
friend class Matrix;
friend class SimplificationRoot;
friend class Sequence;
friend class Trigonometry;
friend class EvaluationEngine;
friend class SimplificationEngine;
public:
enum class Type : uint8_t {
AbsoluteValue,
Undefined = 0,
Rational = 1,
Decimal,
Multiplication,
Power,
Addition,
Factorial,
Division,
Store,
Sine,
Cosine,
Tangent,
AbsoluteValue,
ArcCosine,
ArcSine,
ArcTangent,
BinomialCoefficient,
Ceiling,
Complex,
ComplexArgument,
ConfidenceInterval,
Conjugate,
Cosine,
Derivative,
Determinant,
DivisionQuotient,
DivisionRemainder,
Factorial,
Float,
Floor,
FracPart,
ExpressionMatrix,
GreatCommonDivisor,
HyperbolicArcCosine,
HyperbolicArcSine,
@@ -42,39 +111,31 @@ public:
HyperbolicSine,
HyperbolicTangent,
ImaginaryPart,
Integer,
Integral,
Logarithm,
LeastCommonMultiple,
MatrixDimension,
MatrixInverse,
Logarithm,
MatrixTrace,
MatrixTranspose,
Multiplication,
NaperianLogarithm,
NthRoot,
Evaluation,
Opposite,
PredictionInterval,
Fraction,
Parenthesis,
PermuteCoefficient,
Power,
Product,
RealPart,
Round,
Sine,
SquareRoot,
Store,
Sum,
Subtraction,
Sum,
Symbol,
Tangent,
};
enum class AngleUnit {
Degree = 0,
Radian = 1,
Default = 2
Complex,
Matrix,
ConfidenceInterval,
MatrixDimension,
MatrixInverse,
MatrixTranspose,
PredictionInterval,
SimplificationRoot,
};
enum class FloatDisplayMode {
Decimal = 0,
@@ -86,70 +147,122 @@ public:
Polar = 1,
Default = 2
};
enum class AngleUnit {
Degree = 0,
Radian = 1,
Default = 2
};
/* Constructor & Destructor */
static Expression * parse(char const * string);
virtual ~Expression() = default;
virtual bool hasValidNumberOfArguments() const = 0;
ExpressionLayout * createLayout(FloatDisplayMode floatDisplayMode = FloatDisplayMode::Default, ComplexFormat complexFormat = ComplexFormat::Default) const; // Returned object must be deleted
virtual const Expression * operand(int i) const = 0;
virtual int numberOfOperands() const = 0;
virtual Expression * clone() const = 0;
virtual Expression * cloneWithDifferentOperands(Expression** newOperands,
int numberOfOperands, bool cloneOperands = true) const = 0;
// TODO: Consider std::unique_ptr - see https://google-styleguide.googlecode.com/svn/trunk/cppguide.html#Ownership_and_Smart_Pointers
/* This tests whether two expressions are the same, this takes into account
* commutativity of operators.
*
* For example 3+5 is identical to 5+3 but is not identical to 8.
*/
bool isIdenticalTo(const Expression * e) const;
/* This tests whether two expressions are equivalent.
* This is done by testing wheter they simplify to the same expression.
*
* For example:
* - 3+5 and 4+4 are equivalent.
* - (x+y)*z and x*z+y*z are equivalent.
*
* Here we assume that two equivalent expressions have the same
* simplification, we don't really know whether that's the case,
* nevertheless we are sure that if two expressions simplify to the same
* expression they are indeed equivalent.
*/
bool isEquivalentTo(Expression * e) const;
/* Compare the value of two expressions.
* This only make sense if the two values are of the same type
*/
virtual bool valueEquals(const Expression * e) const;
Expression * simplify() const;
/* Poor man's RTTI */
virtual Type type() const = 0;
virtual bool isCommutative() const;
typedef bool (*CircuitBreaker)(const Expression * e);
static void setCircuitBreaker(CircuitBreaker cb);
bool shouldStopProcessing() const;
/* Circuit breaker */
typedef bool (*CircuitBreaker)();
static void setCircuitBreaker(CircuitBreaker cb);
static bool shouldStopProcessing();
/* The function evaluate creates a new expression and thus mallocs memory.
/* Hierarchy */
virtual const Expression * operand(int i) const = 0;
Expression * editableOperand(int i) { return const_cast<Expression *>(operand(i)); }
virtual int numberOfOperands() const = 0;
Expression * parent() const { return m_parent; }
void setParent(Expression * parent) { m_parent = parent; }
bool hasAncestor(const Expression * e) const;
virtual void replaceOperand(const Expression * oldOperand, Expression * newOperand, bool deleteOldOperand = true) = 0;
Expression * replaceWith(Expression * newOperand, bool deleteAfterReplace = true);
virtual void swapOperands(int i, int j) = 0;
/* Properties */
enum class Sign {
Negative = -1,
Unknown = 0,
Positive = 1
};
virtual Sign sign() const { return Sign::Unknown; }
typedef bool (*ExpressionTest)(const Expression * e);
bool recursivelyMatches(ExpressionTest test) const;
static bool IsMatrix(const Expression * e);
/* Comparison */
/* isIdenticalTo is the "easy" equality, it returns true if both trees have
* same structures and all their nodes have same types and values (ie,
* sqrt(pi^2) is NOT identical to pi). */
bool isIdenticalTo(const Expression * e) const {
/* We use the simplification order only because it is a already-coded total
* order on expresssions. */
return SimplificationOrder(this, e) == 0;
}
/* Layout Engine */
ExpressionLayout * createLayout(FloatDisplayMode floatDisplayMode = FloatDisplayMode::Default, ComplexFormat complexFormat = ComplexFormat::Default) const; // Returned object must be deleted
virtual int writeTextInBuffer(char * buffer, int bufferSize) const = 0;
/* Simplification */
static void Simplify(Expression ** expressionAddress, Context & context, AngleUnit angleUnit = AngleUnit::Default);
/* Evaluation Engine
* The function evaluate creates a new expression and thus mallocs memory.
* Do not forget to delete the new expression to avoid leaking. */
template<typename T> Evaluation<T> * evaluate(Context& context, AngleUnit angleUnit = AngleUnit::Default) const;
template<typename T> Expression * evaluate(Context& context, AngleUnit angleUnit = AngleUnit::Default) const;
template<typename T> T approximate(Context& context, AngleUnit angleUnit = AngleUnit::Default) const;
template<typename T> static T approximate(const char * text, Context& context, AngleUnit angleUnit = AngleUnit::Default);
virtual int writeTextInBuffer(char * buffer, int bufferSize) const;
protected:
/* Constructor */
Expression() : m_parent(nullptr) {}
/* Evaluation Engine */
typedef float SinglePrecision;
typedef double DoublePrecision;
template<typename T> static T epsilon();
constexpr static int k_maxNumberOfSteps = 10000;
/* Simplification */
/* SimplificationOrder returns:
* 1 if e1 > e2
* -1 if e1 < e2
* 0 if e1 == e
* Following the order described in Computer Algebra and Symbolic Computation,
* Joel S. Cohen (section 3.1). The order groups like terms together to avoid
* quadratic complexity when factorizing addition or multiplication. For
* example, it groups terms with same bases together (ie Pi, Pi^3) and with
* same non-rational factors together (ie Pi, 2*Pi). */
static int SimplificationOrder(const Expression * e1, const Expression * e2);
private:
/* Properties */
virtual Expression * setSign(Sign s, Context & context, AngleUnit angleUnit) { assert(false); return nullptr; }
/* Comparison */
/* In the simplification order, most expressions are compared by only
* comparing their types. However hierarchical expressions of same type would
* compare their operands and thus need to reimplement
* simplificationOrderSameType. Besides, operations that can be simplified
* (ie +, *, ^, !) have specific rules to group like terms together and thus
* reimplement simplificationOrderGreaterType. */
virtual int simplificationOrderGreaterType(const Expression * e) const { return -1; }
//TODO: What should be the implementation for complex?
virtual int simplificationOrderSameType(const Expression * e) const { return 0; }
/* Layout Engine */
virtual ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const = 0;
virtual Evaluation<float> * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const = 0;
virtual Evaluation<double> * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const = 0;
bool sequentialOperandsIdentity(const Expression * e) const;
bool commutativeOperandsIdentity(const Expression * e) const;
bool combinatoryCommutativeOperandsIdentity(const Expression * e,
bool * operandMatched, int leftToMatch) const;
/* Simplification */
static void Reduce(Expression ** expressionAddress, Context & context, AngleUnit angleUnit, bool recursively = true);
Expression * deepBeautify(Context & context, AngleUnit angleUnit);
Expression * deepReduce(Context & context, AngleUnit angleUnit);
// TODO: should be virtual pure
virtual Expression * shallowReduce(Context & context, AngleUnit angleUnit);
virtual Expression * shallowBeautify(Context & context, AngleUnit angleUnit) { return this; };
// Private methods used in simplification process
virtual Expression * cloneDenominator(Context & context, AngleUnit angleUnit) const {
return nullptr;
}
/* Evaluation Engine */
virtual Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const = 0;
virtual Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const = 0;
Expression * m_parent;
};
}

View File

@@ -1,34 +0,0 @@
#ifndef POINCARE_EXPRESSION_MATRIX_H
#define POINCARE_EXPRESSION_MATRIX_H
#include <poincare/matrix.h>
namespace Poincare {
class ExpressionMatrix : public Matrix {
public:
ExpressionMatrix(MatrixData * matrixData);
ExpressionMatrix(Expression ** newOperands, int numberOfOperands, int m_numberOfRows, int m_numberOfColumns, bool cloneOperands);
~ExpressionMatrix();
ExpressionMatrix(const Matrix& other) = delete;
ExpressionMatrix(Matrix&& other) = delete;
ExpressionMatrix& operator=(const ExpressionMatrix& other) = delete;
ExpressionMatrix& operator=(ExpressionMatrix&& other) = delete;
bool hasValidNumberOfArguments() const override;
int numberOfRows() const override;
int numberOfColumns() const override;
const Expression * operand(int i) const override;
Expression * clone() const override;
Type type() const override;
Expression * cloneWithDifferentOperands(Expression** newOperands,
int numberOfOperands, bool cloneOperands = true) const override;
private:
Evaluation<float> * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<float>(context, angleUnit); }
Evaluation<double> * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<double>(context, angleUnit); }
template<typename T> Evaluation<T> * templatedEvaluate(Context& context, AngleUnit angleUnit) const;
MatrixData * m_matrixData;
};
}
#endif

View File

@@ -1,25 +1,30 @@
#ifndef POINCARE_FACTORIAL_H
#define POINCARE_FACTORIAL_H
#include <poincare/function.h>
#include <poincare/static_hierarchy.h>
#include <poincare/evaluation_engine.h>
namespace Poincare {
class Factorial : public Function {
class Factorial : public StaticHierarchy<1> {
public:
Factorial(Expression * argument, bool clone = true);
Factorial(const Expression * argument, bool clone = true);
Type type() const override;
Expression * cloneWithDifferentOperands(Expression ** newOperands,
int numberOfOperands, bool cloneOperands = true) const override;
Expression * clone() const override;
private:
Complex<float> computeComplex(const Complex<float> c, AngleUnit angleUnit) const override {
return templatedComputeComplex(c);
constexpr static int k_maxOperandValue = 100;
template<typename T> static Complex<T> computeOnComplex(const Complex<T> c, AngleUnit angleUnit);
Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override {
return EvaluationEngine::map<float>(this, context, angleUnit,computeOnComplex<float>);
}
Complex<double> computeComplex(const Complex<double> c, AngleUnit angleUnit) const override {
return templatedComputeComplex(c);
Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override {
return EvaluationEngine::map<double>(this, context, angleUnit, computeOnComplex<double>);
}
template<typename T> Complex<T> templatedComputeComplex(const Complex<T> c) const;
Expression * shallowReduce(Context& context, AngleUnit angleUnit) override;
ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override;
int writeTextInBuffer(char * buffer, int bufferSize) const override;
int simplificationOrderGreaterType(const Expression * e) const override;
int simplificationOrderSameType(const Expression * e) const override;
};
}

View File

@@ -1,25 +1,34 @@
#ifndef POINCARE_FLOOR_H
#define POINCARE_FLOOR_H
#include <poincare/function.h>
#include <poincare/layout_engine.h>
#include <poincare/static_hierarchy.h>
#include <poincare/evaluation_engine.h>
namespace Poincare {
class Floor : public Function {
class Floor : public StaticHierarchy<1> {
using StaticHierarchy<1>::StaticHierarchy;
public:
Floor();
Type type() const override;
Expression * cloneWithDifferentOperands(Expression ** newOperands,
int numberOfOperands, bool cloneOperands = true) const override;
Expression * clone() const override;
private:
Complex<float> computeComplex(const Complex<float> c, AngleUnit angleUnit) const override {
return templatedComputeComplex(c);
}
Complex<double> computeComplex(const Complex<double> c, AngleUnit angleUnit) const override {
return templatedComputeComplex(c);
}
template<typename T> Complex<T> templatedComputeComplex(const Complex<T> c) const;
/* Layout */
ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override;
int writeTextInBuffer(char * buffer, int bufferSize) const override {
return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name());
}
const char * name() const { return "floor"; }
/* Simplification */
Expression * shallowReduce(Context& context, AngleUnit angleUnit) override;
/* Evaluation */
template<typename T> static Complex<T> computeOnComplex(const Complex<T> c, AngleUnit angleUnit);
Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override {
return EvaluationEngine::map<float>(this, context, angleUnit, computeOnComplex<float>);
}
Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override {
return EvaluationEngine::map<double>(this, context, angleUnit, computeOnComplex<double>);
}
};
}

View File

@@ -1,24 +1,36 @@
#ifndef POINCARE_FRAC_PART_H
#define POINCARE_FRAC_PART_H
#include <poincare/function.h>
#include <poincare/layout_engine.h>
#include <poincare/static_hierarchy.h>
#include <poincare/evaluation_engine.h>
namespace Poincare {
class FracPart : public Function {
class FracPart : public StaticHierarchy<1> {
using StaticHierarchy<1>::StaticHierarchy;
public:
FracPart();
Type type() const override;
Expression * cloneWithDifferentOperands(Expression ** newOperands,
int numberOfOperands, bool cloneOperands = true) const override;
Expression * clone() const override;
private:
Complex<float> computeComplex(const Complex<float> c, AngleUnit angleUnit) const override {
return templatedComputeComplex(c);
/* Layout */
ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override {
return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name());
}
Complex<double> computeComplex(const Complex<double> c, AngleUnit angleUnit) const override {
return templatedComputeComplex(c);
int writeTextInBuffer(char * buffer, int bufferSize) const override {
return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name());
}
const char * name() const { return "frac"; }
/* Simplification */
Expression * shallowReduce(Context& context, AngleUnit angleUnit) override;
/* Evaluation */
template<typename T> static Complex<T> computeOnComplex(const Complex<T> c, AngleUnit angleUnit);
Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override {
return EvaluationEngine::map<float>(this, context, angleUnit, computeOnComplex<float>);
}
Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override {
return EvaluationEngine::map<double>(this, context, angleUnit, computeOnComplex<double>);
}
template<typename T> Complex<T> templatedComputeComplex(const Complex<T> c) const;
};
}

View File

@@ -1,44 +0,0 @@
#ifndef POINCARE_FRACTION_H
#define POINCARE_FRACTION_H
#include <poincare/binary_operation.h>
namespace Poincare {
class Fraction : public BinaryOperation {
using BinaryOperation::BinaryOperation;
public:
Type type() const override;
Expression * cloneWithDifferentOperands(Expression** newOperands,
int numnerOfOperands, bool cloneOperands = true) const override;
template<typename T> static Complex<T> compute(const Complex<T> c, const Complex<T> d);
private:
ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override;
Evaluation<float> * computeOnComplexAndComplexMatrix(const Complex<float> * c, Evaluation<float> * n) const override {
return templatedComputeOnComplexAndComplexMatrix(c, n);
}
Evaluation<double> * computeOnComplexAndComplexMatrix(const Complex<double> * c, Evaluation<double> * n) const override {
return templatedComputeOnComplexAndComplexMatrix(c, n);
}
template<typename T> Evaluation<T> * templatedComputeOnComplexAndComplexMatrix(const Complex<T> * c, Evaluation<T> * n) const;
Evaluation<float> * computeOnComplexMatrices(Evaluation<float> * m, Evaluation<float> * n) const override {
return templatedComputeOnComplexMatrices(m, n);
}
Evaluation<double> * computeOnComplexMatrices(Evaluation<double> * m, Evaluation<double> * n) const override {
return templatedComputeOnComplexMatrices(m, n);
}
template<typename T> Evaluation<T> * templatedComputeOnComplexMatrices(Evaluation<T> * m, Evaluation<T> * n) const;
Complex<float> privateCompute(const Complex<float> c, const Complex<float> d) const override {
return compute(c, d);
}
Complex<double> privateCompute(const Complex<double> c, const Complex<double> d) const override {
return compute(c, d);
}
};
}
#endif

View File

@@ -1,50 +0,0 @@
#ifndef POINCARE_FUNCTION_H
#define POINCARE_FUNCTION_H
#include <poincare/expression.h>
#include <poincare/list_data.h>
#include <poincare/complex.h>
#include <poincare/complex_matrix.h>
#include <cmath>
namespace Poincare {
/* The Function class represents the built-in math functions such as cos, sin,
* tan, log, etc... */
class Function : public Expression {
public:
Function(const char * name, int requiredNumberOfArguments = 1);
~Function();
Function(const Function& other) = delete;
Function(Function&& other) = delete;
Function& operator=(const Function& other) = delete;
Function& operator=(Function&& other) = delete;
void setArgument(Expression ** args, int numberOfArguments, bool clone = true);
void setArgument(ListData * listData, bool clone = true);
bool hasValidNumberOfArguments() const override;
const Expression * operand(int i) const override;
int numberOfOperands() const override;
Expression * clone() const override;
protected:
virtual Complex<float> computeComplex(const Complex<float> c, AngleUnit angleUnit) const {
return Complex<float>::Float(NAN);
}
virtual Complex<double> computeComplex(const Complex<double> c, AngleUnit angleUnit) const {
return Complex<double>::Float(NAN);
}
virtual Evaluation<float> * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<float>(context, angleUnit); }
virtual Evaluation<double> * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<double>(context, angleUnit); }
template<typename T> Evaluation<T> * templatedEvaluate(Context& context, AngleUnit angleUnit) const;
ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override;
void build(Expression ** args, int numberOfArguments, bool clone);
void clean();
Expression ** m_args;
int m_numberOfArguments;
int m_requiredNumberOfArguments;
const char * m_name;
};
}
#endif

View File

@@ -2,8 +2,8 @@
#define POINCARE_GLOBAL_CONTEXT_H
#include <poincare/context.h>
#include <poincare/matrix.h>
#include <poincare/complex.h>
#include <poincare/complex_matrix.h>
namespace Poincare {
@@ -21,11 +21,8 @@ public:
GlobalContext& operator=(GlobalContext&& other) = delete;
/* The expression recorded in global context is already a expression.
* Otherwise, we would need the context and the angle unit to evaluate it */
const Expression * expressionForSymbol(const Symbol * symbol) override {
return evaluationForSymbol(symbol);
}
const Evaluation<double> * evaluationForSymbol(const Symbol * symbol);
void setExpressionForSymbolName(Expression * expression, const Symbol * symbol) override;
const Expression * expressionForSymbol(const Symbol * symbol) override;
void setExpressionForSymbolName(const Expression * expression, const Symbol * symbol, Context & context) override;
static constexpr uint16_t k_maxNumberOfScalarExpressions = 26;
static constexpr uint16_t k_maxNumberOfListExpressions = 10;
static constexpr uint16_t k_maxNumberOfMatrixExpressions = 10;
@@ -33,9 +30,10 @@ public:
private:
int symbolIndex(const Symbol * symbol) const;
Complex<double> * m_expressions[k_maxNumberOfScalarExpressions];
ComplexMatrix<double> * m_matrixExpressions[k_maxNumberOfMatrixExpressions];
Matrix * m_matrixExpressions[k_maxNumberOfMatrixExpressions];
Complex<double> m_pi;
Complex<double> m_e;
Complex<double> m_i;
};
}

View File

@@ -1,20 +1,32 @@
#ifndef POINCARE_GREAT_COMMON_DIVISOR_H
#define POINCARE_GREAT_COMMON_DIVISOR_H
#include <poincare/function.h>
#include <poincare/layout_engine.h>
#include <poincare/static_hierarchy.h>
#include <poincare/complex.h>
namespace Poincare {
class GreatCommonDivisor : public Function {
class GreatCommonDivisor : public StaticHierarchy<2> {
using StaticHierarchy<2>::StaticHierarchy;
public:
GreatCommonDivisor();
Type type() const override;
Expression * cloneWithDifferentOperands(Expression ** newOperands,
int numberOfOperands, bool cloneOperands = true) const override;
Expression * clone() const override;
private:
Evaluation<float> * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<float>(context, angleUnit); }
Evaluation<double> * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<double>(context, angleUnit); }
template<typename T> Evaluation<T> * templatedEvaluate(Context& context, AngleUnit angleUnit) const;
/* Layout */
ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override {
return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name());
}
int writeTextInBuffer(char * buffer, int bufferSize) const override {
return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name());
}
const char * name() const { return "gcd"; }
/* Simplification */
Expression * shallowReduce(Context& context, AngleUnit angleUnit) override;
/* Evaluation */
Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<float>(context, angleUnit); }
Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<double>(context, angleUnit); }
template<typename T> Complex<T> * templatedEvaluate(Context& context, AngleUnit angleUnit) const;
};
}

View File

@@ -0,0 +1,25 @@
#ifndef POINCARE_HIERARCHY_H
#define POINCARE_HIERARCHY_H
#include <poincare/expression.h>
namespace Poincare {
class Hierarchy : public Expression {
public:
using Expression::Expression;
const Expression * operand(int i) const override;
void swapOperands(int i, int j) override;
void replaceOperand(const Expression * oldOperand, Expression * newOperand, bool deleteOldOperand = true) override;
void detachOperand(const Expression * e); // Removes an operand WITHOUT deleting it
void detachOperands(); // Removes all operands WITHOUT deleting them
virtual const Expression * const * operands() const = 0;
protected:
static const Expression * const * ExpressionArray(const Expression * e1, const Expression * e2);
private:
void detachOperandAtIndex(int i);
};
}
#endif

View File

@@ -1,24 +1,36 @@
#ifndef POINCARE_HYPERBOLIC_ARC_COSINE_H
#define POINCARE_HYPERBOLIC_ARC_COSINE_H
#include <poincare/function.h>
#include <poincare/layout_engine.h>
#include <poincare/static_hierarchy.h>
#include <poincare/evaluation_engine.h>
namespace Poincare {
class HyperbolicArcCosine : public Function {
class HyperbolicArcCosine : public StaticHierarchy<1> {
using StaticHierarchy<1>::StaticHierarchy;
public:
HyperbolicArcCosine();
Type type() const override;
Expression * cloneWithDifferentOperands(Expression ** newOperands,
int numberOfOperands, bool cloneOperands = true) const override;
Expression * clone() const override;
private:
Complex<float> computeComplex(const Complex<float> c, AngleUnit angleUnit) const override {
return templatedComputeComplex(c);
/* Layout */
ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override {
return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name());
}
Complex<double> computeComplex(const Complex<double> c, AngleUnit angleUnit) const override {
return templatedComputeComplex(c);
int writeTextInBuffer(char * buffer, int bufferSize) const override {
return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name());
}
const char * name() const { return "acosh"; }
/* Simplification */
Expression * shallowReduce(Context& context, AngleUnit angleUnit) override;
/* Evaluation */
template<typename T> static Complex<T> computeOnComplex(const Complex<T> c, AngleUnit angleUnit);
Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override {
return EvaluationEngine::map<float>(this, context, angleUnit,computeOnComplex<float>);
}
Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override {
return EvaluationEngine::map<double>(this, context, angleUnit, computeOnComplex<double>);
}
template<typename T> Complex<T> templatedComputeComplex(const Complex<T> c) const;
};
}

View File

@@ -1,24 +1,36 @@
#ifndef POINCARE_HYPERBOLIC_ARC_SINE_H
#define POINCARE_HYPERBOLIC_ARC_SINE_H
#include <poincare/function.h>
#include <poincare/layout_engine.h>
#include <poincare/static_hierarchy.h>
#include <poincare/evaluation_engine.h>
namespace Poincare {
class HyperbolicArcSine : public Function {
class HyperbolicArcSine : public StaticHierarchy<1> {
using StaticHierarchy<1>::StaticHierarchy;
public:
HyperbolicArcSine();
Type type() const override;
Expression * cloneWithDifferentOperands(Expression ** newOperands,
int numberOfOperands, bool cloneOperands = true) const override;
Expression * clone() const override;
private:
Complex<float> computeComplex(const Complex<float> c, AngleUnit angleUnit) const override {
return templatedComputeComplex(c);
/* Layout */
ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override {
return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name());
}
Complex<double> computeComplex(const Complex<double> c, AngleUnit angleUnit) const override {
return templatedComputeComplex(c);
int writeTextInBuffer(char * buffer, int bufferSize) const override {
return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name());
}
const char * name() const { return "asinh"; }
/* Simplification */
Expression * shallowReduce(Context& context, AngleUnit angleUnit) override;
/* Evaluation */
template<typename T> static Complex<T> computeOnComplex(const Complex<T> c, AngleUnit angleUnit);
Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override {
return EvaluationEngine::map<float>(this, context, angleUnit,computeOnComplex<float>);
}
Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override {
return EvaluationEngine::map<double>(this, context, angleUnit, computeOnComplex<double>);
}
template<typename T> Complex<T> templatedComputeComplex(const Complex<T> c) const;
};
}

View File

@@ -1,24 +1,36 @@
#ifndef POINCARE_HYPERBOLIC_ARC_TANGENT_H
#define POINCARE_HYPERBOLIC_ARC_TANGENT_H
#include <poincare/function.h>
#include <poincare/layout_engine.h>
#include <poincare/static_hierarchy.h>
#include <poincare/evaluation_engine.h>
namespace Poincare {
class HyperbolicArcTangent : public Function {
class HyperbolicArcTangent : public StaticHierarchy<1> {
using StaticHierarchy<1>::StaticHierarchy;
public:
HyperbolicArcTangent();
Type type() const override;
Expression * cloneWithDifferentOperands(Expression ** newOperands,
int numberOfOperands, bool cloneOperands = true) const override;
Expression * clone() const override;
private:
Complex<float> computeComplex(const Complex<float> c, AngleUnit angleUnit) const override {
return templatedComputeComplex(c);
/* Layout */
ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override {
return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name());
}
Complex<double> computeComplex(const Complex<double> c, AngleUnit angleUnit) const override {
return templatedComputeComplex(c);
int writeTextInBuffer(char * buffer, int bufferSize) const override {
return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name());
}
const char * name() const { return "atanh"; }
/* Simplification */
Expression * shallowReduce(Context& context, AngleUnit angleUnit) override;
/* Evaluation */
template<typename T> static Complex<T> computeOnComplex(const Complex<T> c, AngleUnit angleUnit);
Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override {
return EvaluationEngine::map<float>(this, context, angleUnit,computeOnComplex<float>);
}
Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override {
return EvaluationEngine::map<double>(this, context, angleUnit, computeOnComplex<double>);
}
template<typename T> Complex<T> templatedComputeComplex(const Complex<T> c) const;
};
}

View File

@@ -1,23 +1,35 @@
#ifndef POINCARE_HYPERBOLIC_COSINE_H
#define POINCARE_HYPERBOLIC_COSINE_H
#include <poincare/function.h>
#include <poincare/layout_engine.h>
#include <poincare/static_hierarchy.h>
#include <poincare/evaluation_engine.h>
namespace Poincare {
class HyperbolicCosine : public Function {
class HyperbolicCosine : public StaticHierarchy<1> {
using StaticHierarchy<1>::StaticHierarchy;
public:
HyperbolicCosine();
Type type() const override;
Expression * cloneWithDifferentOperands(Expression ** newOperands,
int numberOfOperands, bool cloneOperands = true) const override;
template<typename T> static Complex<T> compute(const Complex<T> c);
Expression * clone() const override;
template<typename T> static Complex<T> computeOnComplex(const Complex<T> c, AngleUnit angleUnit);
private:
Complex<float> computeComplex(const Complex<float> c, AngleUnit angleUnit) const override {
return compute(c);
/* Layout */
ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override {
return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name());
}
Complex<double> computeComplex(const Complex<double> c, AngleUnit angleUnit) const override {
return compute(c);
int writeTextInBuffer(char * buffer, int bufferSize) const override {
return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name());
}
const char * name() const { return "cosh"; }
/* Simplification */
Expression * shallowReduce(Context& context, AngleUnit angleUnit) override;
/* Evaluation */
Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override {
return EvaluationEngine::map<float>(this, context, angleUnit,computeOnComplex<float>);
}
Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override {
return EvaluationEngine::map<double>(this, context, angleUnit, computeOnComplex<double>);
}
};

View File

@@ -1,23 +1,35 @@
#ifndef POINCARE_HYPERBOLIC_SINE_H
#define POINCARE_HYPERBOLIC_SINE_H
#include <poincare/function.h>
#include <poincare/layout_engine.h>
#include <poincare/static_hierarchy.h>
#include <poincare/evaluation_engine.h>
namespace Poincare {
class HyperbolicSine : public Function {
class HyperbolicSine : public StaticHierarchy<1> {
using StaticHierarchy<1>::StaticHierarchy;
public:
HyperbolicSine();
Type type() const override;
Expression * cloneWithDifferentOperands(Expression ** newOperands,
int numberOfOperands, bool cloneOperands = true) const override;
template<typename T> static Complex<T> compute(const Complex<T> c);
Expression * clone() const override;
template<typename T> static Complex<T> computeOnComplex(const Complex<T> c, AngleUnit angleUnit);
private:
Complex<float> computeComplex(const Complex<float> c, AngleUnit angleUnit) const override {
return compute(c);
/* Layout */
ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override {
return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name());
}
Complex<double> computeComplex(const Complex<double> c, AngleUnit angleUnit) const override {
return compute(c);
int writeTextInBuffer(char * buffer, int bufferSize) const override {
return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name());
}
const char * name() const { return "sinh"; }
/* Simplification */
Expression * shallowReduce(Context& context, AngleUnit angleUnit) override;
/* Evaluation */
Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override {
return EvaluationEngine::map<float>(this, context, angleUnit,computeOnComplex<float>);
}
Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override {
return EvaluationEngine::map<double>(this, context, angleUnit, computeOnComplex<double>);
}
};

View File

@@ -1,23 +1,35 @@
#ifndef POINCARE_HYPERBOLIC_TANGENT_H
#define POINCARE_HYPERBOLIC_TANGENT_H
#include <poincare/function.h>
#include <poincare/layout_engine.h>
#include <poincare/static_hierarchy.h>
#include <poincare/evaluation_engine.h>
namespace Poincare {
class HyperbolicTangent : public Function {
class HyperbolicTangent : public StaticHierarchy<1> {
using StaticHierarchy<1>::StaticHierarchy;
public:
HyperbolicTangent();
Type type() const override;
Expression * cloneWithDifferentOperands(Expression ** newOperands,
int numberOfOperands, bool cloneOperands = true) const override;
template<typename T> static Complex<T> compute(const Complex<T> c);
Expression * clone() const override;
template<typename T> static Complex<T> computeOnComplex(const Complex<T> c, AngleUnit angleUnit);
private:
Complex<float> computeComplex(const Complex<float> c, AngleUnit angleUnit) const override {
return compute(c);
/* Layout */
ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override {
return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name());
}
Complex<double> computeComplex(const Complex<double> c, AngleUnit angleUnit) const override {
return compute(c);
int writeTextInBuffer(char * buffer, int bufferSize) const override {
return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name());
}
const char * name() const { return "tanh"; }
/* Simplification */
Expression * shallowReduce(Context& context, AngleUnit angleUnit) override;
/* Evaluation */
Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override {
return EvaluationEngine::map<float>(this, context, angleUnit,computeOnComplex<float>);
}
Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override {
return EvaluationEngine::map<double>(this, context, angleUnit, computeOnComplex<double>);
}
};

View File

@@ -1,24 +1,36 @@
#ifndef POINCARE_IMAGINARY_PART_H
#define POINCARE_IMAGINARY_PART_H
#include <poincare/function.h>
#include <poincare/layout_engine.h>
#include <poincare/static_hierarchy.h>
#include <poincare/evaluation_engine.h>
namespace Poincare {
class ImaginaryPart : public Function {
class ImaginaryPart : public StaticHierarchy<1> {
using StaticHierarchy<1>::StaticHierarchy;
public:
ImaginaryPart();
Type type() const override;
Expression * cloneWithDifferentOperands(Expression ** newOperands,
int numberOfOperands, bool cloneOperands = true) const override;
Expression * clone() const override;
private:
Complex<float> computeComplex(const Complex<float> c, AngleUnit angleUnit) const override {
return templatedComputeComplex(c);
/* Layout */
ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override {
return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name());
}
Complex<double> computeComplex(const Complex<double> c, AngleUnit angleUnit) const override {
return templatedComputeComplex(c);
int writeTextInBuffer(char * buffer, int bufferSize) const override {
return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name());
}
const char * name() const { return "im"; }
/* Simplification */
Expression * shallowReduce(Context& context, AngleUnit angleUnit) override;
/* Evaluation */
template<typename T> static Complex<T> computeOnComplex(const Complex<T> c, AngleUnit angleUnit);
Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override {
return EvaluationEngine::map<float>(this, context, angleUnit,computeOnComplex<float>);
}
Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override {
return EvaluationEngine::map<double>(this, context, angleUnit, computeOnComplex<double>);
}
template<typename T> Complex<T> templatedComputeComplex(const Complex<T> c) const;
};
}

View File

@@ -1,66 +1,116 @@
#ifndef POINCARE_INTEGER_H
#define POINCARE_INTEGER_H
#include <poincare/leaf_expression.h>
#include <poincare/static_hierarchy.h>
#include <stdint.h>
typedef int32_t native_int_t;
typedef uint32_t native_uint_t;
typedef uint64_t double_native_uint_t;
#include <assert.h>
namespace Poincare {
class Integer : public LeafExpression {
/* All algorithm should be improved with:
* Modern Computer Arithmetic, Richard P. Brent and Paul Zimmermann */
struct IntegerDivision;
class Integer {
public:
Integer(native_int_t i);
typedef uint16_t half_native_uint_t;
typedef int32_t native_int_t;
typedef int64_t double_native_int_t;
typedef uint32_t native_uint_t;
typedef uint64_t double_native_uint_t;
// FIXME: This constructor should be constexpr
Integer(native_int_t i = 0) :
m_digit(i>0 ? i : -i),
m_numberOfDigits(1),
m_negative(i<0)
{
}
Integer(double_native_int_t i);
Integer(const char * digits, bool negative = false); // Digits are NOT NULL-terminated
Type type() const override;
static Integer exponent(int fractionalPartLength, const char * exponent, int exponentLength, bool exponentNegative);
static Integer numerator(const char * integralPart, int integralPartLength, const char * fractionalPart, int fractionalPartLength, bool negative, Integer * exponent);
static Integer denominator(Integer * exponent);
~Integer();
Integer(Integer&& other); // C++11 move constructor
Integer& operator=(Integer&& other); // C++11 move assignment operator
Integer(const Integer& other) = delete;
Integer& operator=(const Integer& other) = delete;
Integer(const Integer& other); // C++11 copy constructor
Integer& operator=(const Integer& other); // C++11 copy assignment operator
// Getter & Setter
bool isNegative() const { return m_negative; }
void setNegative(bool negative);
int extractedInt() { assert(m_numberOfDigits == 1 && m_digit <= 0x7FFFFFFF); return m_negative ? -m_digit : m_digit; }
// Comparison
static int NaturalOrder(const Integer & i, const Integer & j);
bool isEqualTo(const Integer & other) const;
bool isLowerThan(const Integer & other) const;
// Layout
int writeTextInBuffer(char * buffer, int bufferSize) const;
ExpressionLayout * createLayout() const;
// Approximation
template<typename T> T approximate() const;
// Arithmetic
Integer add(const Integer &other) const;
Integer subtract(const Integer &other) const;
Integer multiply_by(const Integer &other) const;
Integer divide_by(const Integer &other) const;
bool operator<(const Integer &other) const;
bool operator==(const Integer &other) const;
bool valueEquals(const Expression * e) const override;
Expression * clone() const override;
static Integer Addition(const Integer & i, const Integer & j);
static Integer Subtraction(const Integer & i, const Integer & j);
static Integer Multiplication(const Integer & i, const Integer & j);
static Integer Factorial(const Integer & i);
static IntegerDivision Division(const Integer & numerator, const Integer & denominator);
static Integer Power(const Integer & i, const Integer & j);
//static Integer Division(const Integer & i, const Integer & j);
//static IntegerDivision division(const Integer & i, const Integer & j);
bool isOne() const { return (m_numberOfDigits == 1 && digit(0) == 1 && !m_negative); };
bool isTwo() const { return (m_numberOfDigits == 1 && digit(0) == 2 && !m_negative); };
bool isTen() const { return (m_numberOfDigits == 1 && digit(0) == 10 && !m_negative); };
bool isMinusOne() const { return (m_numberOfDigits == 1 && digit(0) == 1 && m_negative); };
bool isZero() const { return (m_numberOfDigits == 1 && digit(0) == 0); };
private:
ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override;
Evaluation<float> * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override;
Evaluation<double> * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override;
Integer add(const Integer &other, bool inverse_other_negative) const;
int8_t ucmp(const Integer &other) const; // -1, 0, or 1
Integer usum(const Integer &other, bool subtract, bool output_negative) const;
/* WARNING: This constructor takes ownership of the bits array and will free it! */
Integer(native_uint_t * digits, uint16_t numberOfDigits, bool negative);
native_uint_t * m_digits; // LITTLE-ENDIAN
uint16_t m_numberOfDigits; // In base native_uint_max
bool m_negative;
Integer(const native_uint_t * digits, uint16_t numberOfDigits, bool negative);
static Integer IntegerWithHalfDigitAtIndex(half_native_uint_t halfDigit, int index);
/*
// TODO: Small-int optimization
union {
uint32_t m_staticBits;
char * m_dynamicBits;
};
*/
void releaseDynamicIvars();
static int8_t ucmp(const Integer & a, const Integer & b); // -1, 0, or 1
static Integer usum(const Integer & a, const Integer & b, bool subtract, bool outputNegative);
static Integer addition(const Integer & a, const Integer & b, bool inverseBNegative);
static IntegerDivision udiv(const Integer & a, const Integer & b);
bool usesImmediateDigit() const { return m_numberOfDigits == 1; }
native_uint_t digit(int i) const {
assert(i >= 0 && i < m_numberOfDigits);
return (usesImmediateDigit() ? m_digit : m_digits[i]);
}
uint16_t numberOfHalfDigits() const {
native_uint_t d = digit(m_numberOfDigits-1);
native_uint_t halfBase = 1 << (8*sizeof(half_native_uint_t));
return (d >= halfBase ? 2*m_numberOfDigits : 2*m_numberOfDigits-1);
}
half_native_uint_t halfDigit(int i) const {
assert(i >= 0);
if (i >= numberOfHalfDigits()) {
return 0;
}
return (usesImmediateDigit() ? ((half_native_uint_t *)&m_digit)[i] : ((half_native_uint_t *)m_digits)[i]);
}
// Small integer optimization. Similar to short string optimization.
union {
const native_uint_t * m_digits; // Little-endian
native_uint_t m_digit;
};
uint16_t m_numberOfDigits; // In base native_uint_max
bool m_negative; // Make sure zero cannot be negative
static_assert(sizeof(native_int_t) <= sizeof(native_uint_t), "native_uint_t should be able to contain native_int_t data");
static_assert(sizeof(double_native_uint_t) == 2*sizeof(native_uint_t), "double_native_uint_t should be twice the size of native_uint_t");
};
class Division {
public:
Division(const Integer &numerator, const Integer &denominator);
Integer m_quotient;
Integer m_remainder;
struct IntegerDivision {
Integer quotient;
Integer remainder;
};
}

View File

@@ -1,22 +1,30 @@
#ifndef POINCARE_INTEGRAL_H
#define POINCARE_INTEGRAL_H
#include <poincare/function.h>
#include <poincare/static_hierarchy.h>
#include <poincare/variable_context.h>
#include <poincare/layout_engine.h>
#include <poincare/complex.h>
namespace Poincare {
class Integral : public Function {
class Integral : public StaticHierarchy<3> {
using StaticHierarchy<3>::StaticHierarchy;
public:
Integral();
Type type() const override;
Expression * cloneWithDifferentOperands(Expression ** newOperands,
int numberOfOperands, bool cloneOperands = true) const override;
Expression * clone() const override;
private:
Evaluation<float> * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<float>(context, angleUnit); }
Evaluation<double> * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<double>(context, angleUnit); }
template<typename T> Evaluation<T> * templatedEvaluate(Context& context, AngleUnit angleUnit) const;
/* Layout */
ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override;
int writeTextInBuffer(char * buffer, int bufferSize) const override {
return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, "int");
}
/* Simplification */
Expression * shallowReduce(Context& context, AngleUnit angleUnit) override;
/* Evaluation */
Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<float>(context, angleUnit); }
Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<double>(context, angleUnit); }
template<typename T> Complex<T> * templatedEvaluate(Context& context, AngleUnit angleUnit) const;
template<typename T>
struct DetailedResult
{

View File

@@ -0,0 +1,20 @@
#ifndef POINCARE_LAYOUT_ENGINE_H
#define POINCARE_LAYOUT_ENGINE_H
#include <poincare/expression.h>
namespace Poincare {
class LayoutEngine {
public:
static ExpressionLayout * createInfixLayout(const Expression * expression, Expression::FloatDisplayMode floatDisplayMode, Expression::ComplexFormat complexFormat, const char * operatorName);
static ExpressionLayout * createPrefixLayout(const Expression * expression, Expression::FloatDisplayMode floatDisplayMode, Expression::ComplexFormat complexFormat, const char * operatorName);
typedef bool (*OperandNeedParenthesis)(const Expression * e);
static int writeInfixExpressionTextInBuffer(const Expression * expression, char * buffer, int bufferSize, const char * operatorName, OperandNeedParenthesis operandNeedParenthesis = [](const Expression * e) { return e->type() == Expression::Type::Opposite; });
static int writePrefixExpressionTextInBuffer(const Expression * expression, char * buffer, int bufferSize, const char * operatorName);
};
}
#endif

View File

@@ -1,19 +0,0 @@
#ifndef POINCARE_LEAF_EXPRESSION_H
#define POINCARE_LEAF_EXPRESSION_H
#include <poincare/expression.h>
namespace Poincare {
class LeafExpression : public Expression {
public:
bool hasValidNumberOfArguments() const override;
const Expression * operand(int i) const override;
int numberOfOperands() const override;
Expression * cloneWithDifferentOperands(Expression** newOperands,
int numberOfOperands, bool cloneOperands = true) const override;
};
}
#endif

View File

@@ -1,20 +1,32 @@
#ifndef POINCARE_LEAST_COMMON_MULTIPLE_H
#define POINCARE_LEAST_COMMON_MULTIPLE_H
#include <poincare/function.h>
#include <poincare/layout_engine.h>
#include <poincare/static_hierarchy.h>
#include <poincare/complex.h>
namespace Poincare {
class LeastCommonMultiple : public Function {
class LeastCommonMultiple : public StaticHierarchy<2> {
using StaticHierarchy<2>::StaticHierarchy;
public:
LeastCommonMultiple();
Type type() const override;
Expression * cloneWithDifferentOperands(Expression ** newOperands,
int numberOfOperands, bool cloneOperands = true) const override;
Expression * clone() const override;
private:
Evaluation<float> * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<float>(context, angleUnit); }
Evaluation<double> * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<double>(context, angleUnit); }
template<typename T> Evaluation<T> * templatedEvaluate(Context& context, AngleUnit angleUnit) const;
/* Layout */
ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override {
return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name());
}
int writeTextInBuffer(char * buffer, int bufferSize) const override {
return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name());
}
const char * name() const { return "lcm"; }
/* Simplification */
Expression * shallowReduce(Context& context, AngleUnit angleUnit) override;
/* Evaluation */
Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<float>(context, angleUnit); }
Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<double>(context, angleUnit); }
template<typename T> Complex<T> * templatedEvaluate(Context& context, AngleUnit angleUnit) const;
};
}

View File

@@ -17,6 +17,7 @@ public:
Expression ** operands() const;
const Expression * operand(int i) const;
void pushExpression(Expression * operand);
void detachOperands();
private:
int m_numberOfOperands;
Expression ** m_operands;

View File

@@ -1,29 +1,34 @@
#ifndef POINCARE_LOGARITHM_H
#define POINCARE_LOGARITHM_H
#include <poincare/function.h>
#include <poincare/layout_engine.h>
#include <poincare/bounded_static_hierarchy.h>
#include <poincare/integer.h>
namespace Poincare {
class Logarithm : public Function {
class Logarithm : public BoundedStaticHierarchy<2> {
using BoundedStaticHierarchy<2>::BoundedStaticHierarchy;
friend class NaperianLogarithm;
public:
Logarithm();
bool hasValidNumberOfArguments() const override;
Type type() const override;
Expression * cloneWithDifferentOperands(Expression ** newOperands,
int numberOfOperands, bool cloneOperands = true) const override;
Expression * clone() const override;
private:
Evaluation<float> * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<float>(context, angleUnit); }
Evaluation<double> * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<double>(context, angleUnit); }
template<typename T> Evaluation<T> * templatedEvaluate(Context& context, AngleUnit angleUnit) const;
/* Layout */
ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override;
Complex<float> computeComplex(const Complex<float> c, AngleUnit angleUnit) const override {
return templatedComputeComplex(c);
int writeTextInBuffer(char * buffer, int bufferSize) const override {
return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, "log");
}
Complex<double> computeComplex(const Complex<double> c, AngleUnit angleUnit) const override {
return templatedComputeComplex(c);
}
template<typename T> Complex<T> templatedComputeComplex(const Complex<T> c) const;
/* Simplification */
Expression * shallowReduce(Context & context, AngleUnit angleUnit) override;
Expression * shallowBeautify(Context & context, AngleUnit angleUnit) override;
bool parentIsAPowerOfSameBase() const;
Expression * splitInteger(Integer i, bool isDenominator, Context & context, AngleUnit angleUnit);
/* Evaluation */
template<typename T> static Complex<T> computeOnComplex(const Complex<T> c, AngleUnit angleUnit);
Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<float>(context, angleUnit); }
Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<double>(context, angleUnit); }
template<typename T> Expression * templatedEvaluate(Context& context, AngleUnit angleUnit) const;
};
}

View File

@@ -1,22 +1,42 @@
#ifndef POINCARE_MATRIX_H
#define POINCARE_MATRIX_H
#include <poincare/expression.h>
#include <poincare/dynamic_hierarchy.h>
#include <poincare/matrix_data.h>
namespace Poincare {
class Matrix : public Expression {
class Matrix : public DynamicHierarchy {
public:
virtual const Expression * operand(int i) const override = 0;
int numberOfOperands() const override;
virtual int numberOfRows() const = 0;
virtual int numberOfColumns() const = 0;
/* If the buffer is too small, the function fills the buffer until reaching
* buffer size */
Matrix(MatrixData * matrixData); // pilfer the operands of matrixData
Matrix(const Expression * const * operands, int numberOfRows, int numberOfColumns, bool cloneOperands = true);
int numberOfRows() const;
int numberOfColumns() const;
/* Expression */
Type type() const override;
Expression * clone() const override;
int writeTextInBuffer(char * buffer, int bufferSize) const override;
/* Operation on matrix */
/* createDeterminant, createTrace and createInverse can only be called on an
* matrix of complex expressions. createDeterminant and createTrace return
* a complex expression and createInverse returns a matrix of complex
* expressions or nullptr if the inverse could not be computed. */
template<typename T> Complex<T> * createTrace() const;
template<typename T> Complex<T> * createDeterminant() const;
template<typename T> Matrix * createInverse() const;
Matrix * createTranspose() const;
static Matrix * createIdentity(int dim);
template<typename T> static Matrix * createApproximateIdentity(int dim);
private:
/* Layout */
ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override;
/* Evaluation */
Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<float>(context, angleUnit); }
Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<double>(context, angleUnit); }
template<typename T> Expression * templatedEvaluate(Context& context, AngleUnit angleUnit) const;
int m_numberOfRows;
};
}

View File

@@ -12,7 +12,6 @@ class Complex;
class MatrixData {
public:
MatrixData(ListData * listData, bool clone);
MatrixData(Expression ** newOperands, int numberOfOperands, int m_numberOfRows, int m_numberOfColumns, bool cloneOperands);
~MatrixData();
MatrixData(const MatrixData& other) = delete;
MatrixData(MatrixData&& other) = delete;
@@ -21,11 +20,11 @@ public:
void pushListData(ListData * listData, bool clone);
int numberOfRows();
int numberOfColumns();
Expression ** operands() const;
void pilferOperands(const Expression *** newStorageAddress);
private:
int m_numberOfRows;
int m_numberOfColumns;
Expression ** m_operands;
const Expression ** m_operands;
static Complex<double> * defaultExpression();
};

View File

@@ -1,20 +1,32 @@
#ifndef POINCARE_MATRIX_DIMENSION_H
#define POINCARE_MATRIX_DIMENSION_H
#include <poincare/function.h>
#include <poincare/layout_engine.h>
#include <poincare/static_hierarchy.h>
#include <poincare/complex.h>
namespace Poincare {
class MatrixDimension : public Function {
class MatrixDimension : public StaticHierarchy<1> {
using StaticHierarchy<1>::StaticHierarchy;
public:
MatrixDimension();
Type type() const override;
Expression * cloneWithDifferentOperands(Expression ** newOperands,
int numberOfOperands, bool cloneOperands = true) const override;
Expression * clone() const override;
private:
Evaluation<float> * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<float>(context, angleUnit); }
Evaluation<double> * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<double>(context, angleUnit); }
template<typename T> Evaluation<T> * templatedEvaluate(Context& context, AngleUnit angleUnit) const;
/* Layout */
ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override {
return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name());
}
int writeTextInBuffer(char * buffer, int bufferSize) const override {
return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name());
}
const char * name() const { return "dimension"; }
/* Simplification */
Expression * shallowReduce(Context& context, AngleUnit angleUnit) override;
/* Evaluation */
Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<float>(context, angleUnit); }
Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<double>(context, angleUnit); }
template<typename T> Expression * templatedEvaluate(Context& context, AngleUnit angleUnit) const;
};
}

View File

@@ -1,20 +1,32 @@
#ifndef POINCARE_MATRIX_INVERSE_H
#define POINCARE_MATRIX_INVERSE_H
#include <poincare/function.h>
#include <poincare/layout_engine.h>
#include <poincare/static_hierarchy.h>
#include <poincare/complex.h>
namespace Poincare {
class MatrixInverse : public Function {
class MatrixInverse : public StaticHierarchy<1> {
using StaticHierarchy<1>::StaticHierarchy;
public:
MatrixInverse();
Type type() const override;
Expression * cloneWithDifferentOperands(Expression ** newOperands,
int numberOfOperands, bool cloneOperands = true) const override;
Expression * clone() const override;
private:
Evaluation<float> * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<float>(context, angleUnit); }
Evaluation<double> * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<double>(context, angleUnit); }
template<typename T> Evaluation<T> * templatedEvaluate(Context& context, AngleUnit angleUnit) const;
/* Evaluation */
ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override {
return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name());
}
int writeTextInBuffer(char * buffer, int bufferSize) const override {
return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name());
}
const char * name() const { return "inverse"; }
/* Simplification */
Expression * shallowReduce(Context & context, AngleUnit angleUnit) override;
/* Evaluation */
Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<float>(context, angleUnit); }
Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<double>(context, angleUnit); }
template<typename T> Expression * templatedEvaluate(Context& context, AngleUnit angleUnit) const;
};
}

View File

@@ -1,20 +1,32 @@
#ifndef POINCARE_MATRIX_TRACE_H
#define POINCARE_MATRIX_TRACE_H
#include <poincare/function.h>
#include <poincare/layout_engine.h>
#include <poincare/static_hierarchy.h>
#include <poincare/complex.h>
namespace Poincare {
class MatrixTrace : public Function {
class MatrixTrace : public StaticHierarchy<1> {
using StaticHierarchy<1>::StaticHierarchy;
public:
MatrixTrace();
Type type() const override;
Expression * cloneWithDifferentOperands(Expression ** newOperands,
int numberOfOperands, bool cloneOperands = true) const override;
Expression * clone() const override;
private:
Evaluation<float> * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<float>(context, angleUnit); }
Evaluation<double> * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<double>(context, angleUnit); }
template<typename T> Evaluation<T> * templatedEvaluate(Context& context, AngleUnit angleUnit) const;
/* Layout */
ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override {
return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name());
}
int writeTextInBuffer(char * buffer, int bufferSize) const override {
return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name());
}
const char * name() const { return "trace"; }
/* Simplification */
Expression * shallowReduce(Context & context, AngleUnit angleUnit) override;
/* Evaluation */
Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<float>(context, angleUnit); }
Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<double>(context, angleUnit); }
template<typename T> Expression * templatedEvaluate(Context& context, AngleUnit angleUnit) const;
};
}

View File

@@ -1,20 +1,32 @@
#ifndef POINCARE_MATRIX_TRANSPOSE_H
#define POINCARE_MATRIX_TRANSPOSE_H
#include <poincare/function.h>
#include <poincare/layout_engine.h>
#include <poincare/static_hierarchy.h>
#include <poincare/complex.h>
namespace Poincare {
class MatrixTranspose : public Function {
class MatrixTranspose : public StaticHierarchy<1> {
using StaticHierarchy<1>::StaticHierarchy;
public:
MatrixTranspose();
Type type() const override;
Expression * cloneWithDifferentOperands(Expression ** newOperands,
int numberOfOperands, bool cloneOperands = true) const override;
Expression * clone() const override;
private:
Evaluation<float> * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<float>(context, angleUnit); }
Evaluation<double> * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<double>(context, angleUnit); }
template<typename T> Evaluation<T> * templatedEvaluate(Context& context, AngleUnit angleUnit) const;
/* Layout */
ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override {
return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name());
}
int writeTextInBuffer(char * buffer, int bufferSize) const override {
return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name());
}
const char * name() const { return "transpose"; }
/* Simplification */
Expression * shallowReduce(Context & context, AngleUnit angleUnit) override;
/* Evaluation */
Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<float>(context, angleUnit); }
Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<double>(context, angleUnit); }
template<typename T> Expression * templatedEvaluate(Context& context, AngleUnit angleUnit) const;
};
}

View File

@@ -1,34 +1,65 @@
#ifndef POINCARE_MULTIPLICATION_H
#define POINCARE_MULTIPLICATION_H
#include <poincare/binary_operation.h>
#include <poincare/dynamic_hierarchy.h>
#include <poincare/layout_engine.h>
#include <poincare/evaluation_engine.h>
namespace Poincare {
class Multiplication : public BinaryOperation {
using BinaryOperation::BinaryOperation;
class Multiplication : public DynamicHierarchy {
using DynamicHierarchy::DynamicHierarchy;
friend class Addition;
friend class Division;
friend class Logarithm;
friend class Opposite;
friend class Power;
friend class Subtraction;
public:
Type type() const override;
Expression * cloneWithDifferentOperands(Expression** newOperands,
int numnerOfOperands, bool cloneOperands = true) const override;
template<typename T> static Evaluation<T> * computeOnMatrices(Evaluation<T> * m, Evaluation<T> * n);
template<typename T> static Evaluation<T> * computeOnComplexAndMatrix(const Complex<T> * c, Evaluation<T> * m);
Expression * clone() const override;
Sign sign() const override;
/* Evaluation */
template<typename T> static Complex<T> compute(const Complex<T> c, const Complex<T> d);
template<typename T> static Matrix * computeOnComplexAndMatrix(const Complex<T> * c, const Matrix * m) {
return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute<T>);
}
template<typename T> static Matrix * computeOnMatrices(const Matrix * m, const Matrix * n);
private:
/* Property */
Expression * setSign(Sign s, Context & context, AngleUnit angleUnit) override;
/* Layout */
ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override;
int writeTextInBuffer(char * buffer, int bufferSize) const override;
/* Simplification */
Expression * shallowReduce(Context& context, AngleUnit angleUnit) override;
Expression * privateShallowReduce(Context& context, AngleUnit angleUnit, bool expand);
void factorizeBase(Expression * e1, Expression * e2, Context & context, AngleUnit angleUnit);
void factorizeExponent(Expression * e1, Expression * e2, Context & context, AngleUnit angleUnit);
Expression * distributeOnOperandAtIndex(int index, Context & context, AngleUnit angleUnit);
Expression * cloneDenominator(Context & context, AngleUnit angleUnit) const override;
void addMissingFactors(Expression * factor, Context & context, AngleUnit angleUnit);
void factorizeSineAndCosine(Expression * o1, Expression * o2, Context & context, AngleUnit angleUnit);
static bool HaveSameNonRationalFactors(const Expression * e1, const Expression * e2);
static bool TermsHaveIdenticalBase(const Expression * e1, const Expression * e2);
static bool TermsHaveIdenticalExponent(const Expression * e1, const Expression * e2);
static bool TermHasRationalBase(const Expression * e);
static bool TermHasIntegerExponent(const Expression * e);
static bool TermHasRationalExponent(const Expression * e);
static const Expression * CreateExponent(Expression * e);
Expression * shallowBeautify(Context & context, AngleUnit angleUnit) override;
// Warning: mergeNegativePower not always returns a multiplication: *(b^-1,c^-1) -> (bc)^-1
Expression * mergeNegativePower(Context & context, AngleUnit angleUnit);
/* Evaluation */
Evaluation<float> * computeOnComplexMatrices(Evaluation<float> * m, Evaluation<float> * n) const override {
return computeOnMatrices(m, n);
template<typename T> static Matrix * computeOnMatrixAndComplex(const Matrix * m, const Complex<T> * c) {
return EvaluationEngine::elementWiseOnComplexAndComplexMatrix(c, m, compute<T>);
}
Evaluation<double> * computeOnComplexMatrices(Evaluation<double> * m, Evaluation<double> * n) const override {
return computeOnMatrices(m, n);
Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override {
return EvaluationEngine::mapReduce<float>(this, context, angleUnit, compute<float>, computeOnComplexAndMatrix<float>, computeOnMatrixAndComplex<float>, computeOnMatrices<float>);
}
Complex<float> privateCompute(const Complex<float> c, const Complex<float> d) const override {
return compute(c, d);
}
Complex<double> privateCompute(const Complex<double> c, const Complex<double> d) const override {
return compute(c, d);
Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override {
return EvaluationEngine::mapReduce<double>(this, context, angleUnit, compute<double>, computeOnComplexAndMatrix<double>, computeOnMatrixAndComplex<double>, computeOnMatrices<double>);
}
};

View File

@@ -1,24 +1,36 @@
#ifndef POINCARE_NAPERIAN_LOGARITHM_H
#define POINCARE_NAPERIAN_LOGARITHM_H
#include <poincare/function.h>
#include <poincare/layout_engine.h>
#include <poincare/static_hierarchy.h>
#include <poincare/evaluation_engine.h>
namespace Poincare {
class NaperianLogarithm : public Function {
class NaperianLogarithm : public StaticHierarchy<1> {
using StaticHierarchy<1>::StaticHierarchy;
public:
NaperianLogarithm();
Type type() const override;
Expression * cloneWithDifferentOperands(Expression ** newOperands,
int numberOfOperands, bool cloneOperands = true) const override;
Expression * clone() const override;
private:
Complex<float> computeComplex(const Complex<float> c, AngleUnit angleUnit) const override {
return templatedComputeComplex(c);
/* Layout */
ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override {
return LayoutEngine::createPrefixLayout(this, floatDisplayMode, complexFormat, name());
}
Complex<double> computeComplex(const Complex<double> c, AngleUnit angleUnit) const override {
return templatedComputeComplex(c);
int writeTextInBuffer(char * buffer, int bufferSize) const override {
return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, name());
}
const char * name() const { return "ln"; }
/* Simplification */
Expression * shallowReduce(Context& context, AngleUnit angleUnit) override;
/* Evaluation */
template<typename T> static Complex<T> computeOnComplex(const Complex<T> c, AngleUnit angleUnit);
Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override {
return EvaluationEngine::map<float>(this, context, angleUnit,computeOnComplex<float>);
}
Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override {
return EvaluationEngine::map<double>(this, context, angleUnit, computeOnComplex<double>);
}
template<typename T> Complex<T> templatedComputeComplex(const Complex<T> c) const;
};
}

View File

@@ -1,22 +1,31 @@
#ifndef POINCARE_NTH_ROOT_H
#define POINCARE_NTH_ROOT_H
#include <poincare/function.h>
#include <poincare/static_hierarchy.h>
#include <poincare/layout_engine.h>
#include <poincare/complex.h>
namespace Poincare {
class NthRoot : public Function {
class NthRoot : public StaticHierarchy<2> {
using StaticHierarchy<2>::StaticHierarchy;
public:
NthRoot();
Type type() const override;
Expression * cloneWithDifferentOperands(Expression ** newOperands,
int numberOfOperands, bool cloneOperands = true) const override;
Expression * clone() const override;
private:
Evaluation<float> * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<float>(context, angleUnit); }
Evaluation<double> * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<double>(context, angleUnit); }
template<typename T> Evaluation<T> * templatedEvaluate(Context& context, AngleUnit angleUnit) const;
/* Layout */
ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override;
template<typename T> Complex<T> compute(const Complex<T> c, const Complex<T> d) const;
int writeTextInBuffer(char * buffer, int bufferSize) const override {
return LayoutEngine::writePrefixExpressionTextInBuffer(this, buffer, bufferSize, "root");
}
/* Simplification */
Expression * shallowReduce(Context& context, AngleUnit angleUnit) override;
/* Evaluation */
template<typename T> static Complex<T> compute(const Complex<T> c, const Complex<T> d);
Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<float>(context, angleUnit); }
Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<double>(context, angleUnit); }
template<typename T> Expression * templatedEvaluate(Context& context, AngleUnit angleUnit) const;
};
}

View File

@@ -1,34 +1,31 @@
#ifndef POINCARE_OPPOSITE_H
#define POINCARE_OPPOSITE_H
#include <poincare/expression.h>
#include <poincare/matrix.h>
#include <poincare/static_hierarchy.h>
#include <poincare/layout_engine.h>
#include <poincare/evaluation_engine.h>
namespace Poincare {
class Opposite : public Expression {
class Opposite : public StaticHierarchy<1> {
using StaticHierarchy<1>::StaticHierarchy;
public:
Opposite(Expression * operand, bool cloneOperands = true);
~Opposite();
Opposite(const Opposite& other) = delete;
Opposite(Opposite&& other) = delete;
Opposite& operator=(const Opposite& other) = delete;
Opposite& operator=(Opposite&& other) = delete;
bool hasValidNumberOfArguments() const override;
const Expression * operand(int i) const override;
int numberOfOperands() const override;
Expression * clone() const override;
Type type() const override;
Expression * cloneWithDifferentOperands(Expression** newOperands,
int numnerOfOperands, bool cloneOperands = true) const override;
template<typename T> static Complex<T> compute(const Complex<T> c);
template<typename T> static Evaluation<T> * computeOnMatrix(Evaluation<T> * m);
template<typename T> static Complex<T> compute(const Complex<T> c, AngleUnit angleUnit);
private:
Evaluation<float> * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<float>(context, angleUnit); }
Evaluation<double> * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate<double>(context, angleUnit); }
template<typename T> Evaluation<T> * templatedEvaluate(Context& context, AngleUnit angleUnit) const;
/* Layout */
ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override;
Expression * m_operand;
int writeTextInBuffer(char * buffer, int bufferSize) const override;
/* Simplification */
Expression * shallowReduce(Context& context, AngleUnit angleUnit) override;
/* Evaluation */
Expression * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override {
return EvaluationEngine::map<float>(this, context, angleUnit, compute<float>);
}
Expression * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override {
return EvaluationEngine::map<double>(this, context, angleUnit, compute<double>);
}
};
}

Some files were not shown because too many files have changed in this diff Show More