diff --git a/apps/calculation/additional_outputs/matrix_list_controller.cpp b/apps/calculation/additional_outputs/matrix_list_controller.cpp index 4eaf9e465..274c0a125 100644 --- a/apps/calculation/additional_outputs/matrix_list_controller.cpp +++ b/apps/calculation/additional_outputs/matrix_list_controller.cpp @@ -56,13 +56,13 @@ void MatrixListController::setExpression(Poincare::Expression e) { } // 3. Matrix row echelon form messageIndex = 2; - Expression rowEchelonForm = MatrixRef::Builder(m_expression.clone()); + Expression rowEchelonForm = MatrixRowEchelonForm::Builder(m_expression.clone()); m_indexMessageMap[index] = messageIndex++; m_layouts[index++] = getLayoutFromExpression(rowEchelonForm, context, preferences); /* 4. Matrix reduced row echelon form * it can be computed from row echelon form to save computation time.*/ m_indexMessageMap[index] = messageIndex++; - m_layouts[index++] = getLayoutFromExpression(MatrixRref::Builder(rowEchelonForm), context, preferences); + m_layouts[index++] = getLayoutFromExpression(MatrixReducedRowEchelonForm::Builder(rowEchelonForm), context, preferences); // 5. Matrix trace if square matrix if (mIsSquared) { m_indexMessageMap[index] = messageIndex++; diff --git a/poincare/Makefile b/poincare/Makefile index 482617398..71dcd46db 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -101,8 +101,9 @@ poincare_src += $(addprefix poincare/src/,\ matrix_inverse.cpp \ matrix_trace.cpp \ matrix_transpose.cpp \ - matrix_ref.cpp \ - matrix_rref.cpp \ + matrix_echelon_form.cpp \ + matrix_row_echelon_form.cpp \ + matrix_reduced_row_echelon_form.cpp \ multiplication.cpp \ n_ary_expression.cpp \ naperian_logarithm.cpp \ diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index b6d16787b..e5aa58747 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -63,8 +63,9 @@ class Expression : public TreeHandle { friend class MatrixInverse; friend class MatrixTrace; friend class MatrixTranspose; - friend class MatrixRef; - friend class MatrixRref; + friend class MatrixEchelonForm; + friend class MatrixRowEchelonForm; + friend class MatrixReducedRowEchelonForm; friend class Multiplication; friend class MultiplicationNode; friend class NaperianLogarithm; diff --git a/poincare/include/poincare/expression_node.h b/poincare/include/poincare/expression_node.h index 4ad6b91b3..79c6eaa88 100644 --- a/poincare/include/poincare/expression_node.h +++ b/poincare/include/poincare/expression_node.h @@ -103,8 +103,8 @@ public: MatrixIdentity, MatrixInverse, MatrixTranspose, - MatrixRef, - MatrixRref, + MatrixRowEchelonForm, + MatrixReducedRowEchelonForm, PredictionInterval, Matrix, EmptyExpression diff --git a/poincare/include/poincare/matrix_ref.h b/poincare/include/poincare/matrix_echelon_form.h similarity index 66% rename from poincare/include/poincare/matrix_ref.h rename to poincare/include/poincare/matrix_echelon_form.h index a707776ce..1a2ff0f7c 100644 --- a/poincare/include/poincare/matrix_ref.h +++ b/poincare/include/poincare/matrix_echelon_form.h @@ -1,24 +1,17 @@ -#ifndef POINCARE_MATRIX_REF_H -#define POINCARE_MATRIX_REF_H +#ifndef POINCARE_MATRIX_ECHELON_FORM_H +#define POINCARE_MATRIX_ECHELON_FORM_H #include namespace Poincare { -class MatrixRefNode final : public ExpressionNode { +class MatrixEchelonFormNode : public ExpressionNode { public: // TreeNode - size_t size() const override { return sizeof(MatrixRefNode); } int numberOfChildren() const override; -#if POINCARE_TREE_LOG - void logNodeName(std::ostream & stream) const override { - stream << "MatrixRef"; - } -#endif - - // Properties - Type type() const override { return Type::MatrixRef; } + virtual bool isFormReduced() const = 0; + static constexpr int sNumberOfChildren = 1; private: // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; @@ -31,16 +24,16 @@ private: Evaluation approximate(SinglePrecision p, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } Evaluation approximate(DoublePrecision p, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } template Evaluation templatedApproximate(Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; + + // Properties + virtual const char * functionHelperName() const = 0; }; -class MatrixRef final : public Expression { +class MatrixEchelonForm : public Expression { public: - MatrixRef(const MatrixRefNode * n) : Expression(n) {} - static MatrixRef Builder(Expression child) { return TreeHandle::FixedArityBuilder({child}); } - - static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("ref", 1, &UntypedBuilderOneChild); - + MatrixEchelonForm(const MatrixEchelonFormNode * n) : Expression(n) {} Expression shallowReduce(ExpressionNode::ReductionContext reductionContext); + bool isFormReduced() const { return static_cast(node())->isFormReduced(); } }; } diff --git a/poincare/include/poincare/matrix_reduced_row_echelon_form.h b/poincare/include/poincare/matrix_reduced_row_echelon_form.h new file mode 100644 index 000000000..2058f626e --- /dev/null +++ b/poincare/include/poincare/matrix_reduced_row_echelon_form.h @@ -0,0 +1,37 @@ +#ifndef POINCARE_MATRIX_REDUCED_ROW_ECHELON_FORM_H +#define POINCARE_MATRIX_REDUCED_ROW_ECHELON_FORM_H + +#include + +namespace Poincare { + +class MatrixReducedRowEchelonFormNode final : public MatrixEchelonFormNode { +public: + + // TreeNode + size_t size() const override { return sizeof(MatrixReducedRowEchelonFormNode); } + +#if POINCARE_TREE_LOG + void logNodeName(std::ostream & stream) const override { + stream << "MatrixReducedRowEchelonForm"; + } +#endif + + // Properties + Type type() const override { return Type::MatrixReducedRowEchelonForm; } +private: + const char * functionHelperName() const override; + bool isFormReduced() const override { return true; } +}; + + +class MatrixReducedRowEchelonForm final : public MatrixEchelonForm { +public: + MatrixReducedRowEchelonForm(const MatrixReducedRowEchelonFormNode * n) : MatrixEchelonForm(n) {} + static MatrixReducedRowEchelonForm Builder(Expression child) { return TreeHandle::FixedArityBuilder({child}); } + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("rref", MatrixEchelonFormNode::sNumberOfChildren, &UntypedBuilderOneChild); +}; + +} + +#endif diff --git a/poincare/include/poincare/matrix_row_echelon_form.h b/poincare/include/poincare/matrix_row_echelon_form.h new file mode 100644 index 000000000..baaa80962 --- /dev/null +++ b/poincare/include/poincare/matrix_row_echelon_form.h @@ -0,0 +1,37 @@ +#ifndef POINCARE_MATRIX_ROW_ECHELON_FORM_H +#define POINCARE_MATRIX_ROW_ECHELON_FORM_H + +#include + +namespace Poincare { + +class MatrixRowEchelonFormNode final : public MatrixEchelonFormNode { +public: + + // TreeNode + size_t size() const override { return sizeof(MatrixRowEchelonFormNode); } + +#if POINCARE_TREE_LOG + void logNodeName(std::ostream & stream) const override { + stream << "MatrixRowEchelonForm"; + } +#endif + + // Properties + Type type() const override { return Type::MatrixRowEchelonForm; } +private: + const char * functionHelperName() const override; + bool isFormReduced() const override { return false; } +}; + + +class MatrixRowEchelonForm final : public MatrixEchelonForm { +public: + MatrixRowEchelonForm(const MatrixRowEchelonFormNode * n) : MatrixEchelonForm(n) {} + static MatrixRowEchelonForm Builder(Expression child) { return TreeHandle::FixedArityBuilder({child}); } + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("ref", MatrixEchelonFormNode::sNumberOfChildren, &UntypedBuilderOneChild); +}; + +} + +#endif diff --git a/poincare/include/poincare/matrix_rref.h b/poincare/include/poincare/matrix_rref.h deleted file mode 100644 index 66d44b257..000000000 --- a/poincare/include/poincare/matrix_rref.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef POINCARE_MATRIX_RREF_H -#define POINCARE_MATRIX_RREF_H - -#include - -namespace Poincare { - -class MatrixRrefNode final : public ExpressionNode { -public: - - // TreeNode - size_t size() const override { return sizeof(MatrixRrefNode); } - int numberOfChildren() const override; -#if POINCARE_TREE_LOG - void logNodeName(std::ostream & stream) const override { - stream << "MatrixRref"; - } -#endif - - // Properties - Type type() const override { return Type::MatrixRref; } -private: - // Layout - Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; - int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; - // Simplification - Expression shallowReduce(ReductionContext reductionContext) override; - LayoutShape leftLayoutShape() const override { return LayoutShape::MoreLetters; }; - LayoutShape rightLayoutShape() const override { return LayoutShape::BoundaryPunctuation; } - // Evaluation - Evaluation approximate(SinglePrecision p, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } - Evaluation approximate(DoublePrecision p, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return templatedApproximate(context, complexFormat, angleUnit); } - template Evaluation templatedApproximate(Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; -}; - -class MatrixRref final : public Expression { -public: - MatrixRref(const MatrixRrefNode * n) : Expression(n) {} - static MatrixRref Builder(Expression child) { return TreeHandle::FixedArityBuilder({child}); } - - static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("rref", 1, &UntypedBuilderOneChild); - - Expression shallowReduce(ExpressionNode::ReductionContext reductionContext); -}; - -} - -#endif diff --git a/poincare/include/poincare_nodes.h b/poincare/include/poincare_nodes.h index 469013a9d..41f1d0d92 100644 --- a/poincare/include/poincare_nodes.h +++ b/poincare/include/poincare_nodes.h @@ -54,8 +54,8 @@ #include #include #include -#include -#include +#include +#include #include #include #include diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index cfde3b045..62592f10c 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -186,8 +186,8 @@ bool Expression::IsMatrix(const Expression e, Context * context) { || e.type() == ExpressionNode::Type::MatrixInverse || e.type() == ExpressionNode::Type::MatrixIdentity || e.type() == ExpressionNode::Type::MatrixTranspose - || e.type() == ExpressionNode::Type::MatrixRef - || e.type() == ExpressionNode::Type::MatrixRref; + || e.type() == ExpressionNode::Type::MatrixRowEchelonForm + || e.type() == ExpressionNode::Type::MatrixReducedRowEchelonForm; } bool Expression::IsInfinity(const Expression e, Context * context) { diff --git a/poincare/src/matrix_echelon_form.cpp b/poincare/src/matrix_echelon_form.cpp new file mode 100644 index 000000000..cffcad695 --- /dev/null +++ b/poincare/src/matrix_echelon_form.cpp @@ -0,0 +1,59 @@ +#include +#include +#include +#include +#include + +namespace Poincare { + +int MatrixEchelonFormNode::numberOfChildren() const { return sNumberOfChildren; } + +Expression MatrixEchelonFormNode::shallowReduce(ReductionContext reductionContext) { + return MatrixEchelonForm(this).shallowReduce(reductionContext); +} + +Layout MatrixEchelonFormNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { + return LayoutHelper::Prefix(MatrixEchelonForm(this), floatDisplayMode, numberOfSignificantDigits, functionHelperName()); +} + +int MatrixEchelonFormNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { + return SerializationHelper::Prefix(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, functionHelperName()); +} + +template +Evaluation MatrixEchelonFormNode::templatedApproximate(Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { + Evaluation input = childAtIndex(0)->approximate(T(), context, complexFormat, angleUnit); + Evaluation ref; + if (input.type() == EvaluationNode::Type::MatrixComplex) { + ref = static_cast&>(input).ref(isFormReduced()); + } else { + ref = Complex::Undefined(); + } + assert(!ref.isUninitialized()); + return ref; +} + + +Expression MatrixEchelonForm::shallowReduce(ExpressionNode::ReductionContext reductionContext) { + { + Expression e = Expression::defaultShallowReduce(); + e = e.defaultHandleUnitsInChildren(); + if (e.isUndefined()) { + return e; + } + } + Expression c = childAtIndex(0); + if (c.type() == ExpressionNode::Type::Matrix) { + bool couldComputeRef = false; + Expression result = static_cast(c).createRef(reductionContext, &couldComputeRef, isFormReduced()); + if (couldComputeRef) { + replaceWithInPlace(result); + return result; + } + // The matrix could not be transformed properly + return *this; + } + return replaceWithUndefinedInPlace(); +} + +} diff --git a/poincare/src/matrix_reduced_row_echelon_form.cpp b/poincare/src/matrix_reduced_row_echelon_form.cpp new file mode 100644 index 000000000..a06bb98d8 --- /dev/null +++ b/poincare/src/matrix_reduced_row_echelon_form.cpp @@ -0,0 +1,9 @@ +#include + +namespace Poincare { + +constexpr Expression::FunctionHelper MatrixReducedRowEchelonForm::s_functionHelper; + +const char * MatrixReducedRowEchelonFormNode::functionHelperName() const { return MatrixReducedRowEchelonForm::s_functionHelper.name(); } + +} diff --git a/poincare/src/matrix_ref.cpp b/poincare/src/matrix_ref.cpp deleted file mode 100644 index 0feb755ca..000000000 --- a/poincare/src/matrix_ref.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include -#include -#include -#include -#include - -namespace Poincare { - -constexpr Expression::FunctionHelper MatrixRef::s_functionHelper; - -int MatrixRefNode::numberOfChildren() const { return MatrixRef::s_functionHelper.numberOfChildren(); } - -Expression MatrixRefNode::shallowReduce(ReductionContext reductionContext) { - return MatrixRef(this).shallowReduce(reductionContext); -} - -Layout MatrixRefNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { - return LayoutHelper::Prefix(MatrixRef(this), floatDisplayMode, numberOfSignificantDigits, MatrixRef::s_functionHelper.name()); -} - -int MatrixRefNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { - return SerializationHelper::Prefix(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, MatrixRef::s_functionHelper.name()); -} - -template -Evaluation MatrixRefNode::templatedApproximate(Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { - Evaluation input = childAtIndex(0)->approximate(T(), context, complexFormat, angleUnit); - Evaluation ref; - if (input.type() == EvaluationNode::Type::MatrixComplex) { - ref = static_cast&>(input).ref(false); - } else { - ref = Complex::Undefined(); - } - assert(!ref.isUninitialized()); - return ref; -} - - -Expression MatrixRef::shallowReduce(ExpressionNode::ReductionContext reductionContext) { - { - Expression e = Expression::defaultShallowReduce(); - e = e.defaultHandleUnitsInChildren(); - if (e.isUndefined()) { - return e; - } - } - Expression c = childAtIndex(0); - if (c.type() == ExpressionNode::Type::Matrix) { - bool couldComputeRef = false; - Expression result = static_cast(c).createRef(reductionContext, &couldComputeRef, false); - if (couldComputeRef) { - replaceWithInPlace(result); - return result; - } - // The matrix could not be transformed properly - return *this; - } - return replaceWithUndefinedInPlace(); -} - -} diff --git a/poincare/src/matrix_row_echelon_form.cpp b/poincare/src/matrix_row_echelon_form.cpp new file mode 100644 index 000000000..fe8d8ec9d --- /dev/null +++ b/poincare/src/matrix_row_echelon_form.cpp @@ -0,0 +1,9 @@ +#include + +namespace Poincare { + +constexpr Expression::FunctionHelper MatrixRowEchelonForm::s_functionHelper; + +const char * MatrixRowEchelonFormNode::functionHelperName() const { return MatrixRowEchelonForm::s_functionHelper.name(); } + +} diff --git a/poincare/src/matrix_rref.cpp b/poincare/src/matrix_rref.cpp deleted file mode 100644 index d7562aa9e..000000000 --- a/poincare/src/matrix_rref.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include -#include -#include -#include -#include - -namespace Poincare { - -constexpr Expression::FunctionHelper MatrixRref::s_functionHelper; - -int MatrixRrefNode::numberOfChildren() const { return MatrixRref::s_functionHelper.numberOfChildren(); } - -Expression MatrixRrefNode::shallowReduce(ReductionContext reductionContext) { - return MatrixRref(this).shallowReduce(reductionContext); -} - -Layout MatrixRrefNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { - return LayoutHelper::Prefix(MatrixRref(this), floatDisplayMode, numberOfSignificantDigits, MatrixRref::s_functionHelper.name()); -} - -int MatrixRrefNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { - return SerializationHelper::Prefix(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, MatrixRref::s_functionHelper.name()); -} - -template -Evaluation MatrixRrefNode::templatedApproximate(Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { - Evaluation input = childAtIndex(0)->approximate(T(), context, complexFormat, angleUnit); - Evaluation rref; - if (input.type() == EvaluationNode::Type::MatrixComplex) { - rref = static_cast&>(input).ref(true); - } else { - rref = Complex::Undefined(); - } - assert(!rref.isUninitialized()); - return rref; -} - - -Expression MatrixRref::shallowReduce(ExpressionNode::ReductionContext reductionContext) { - { - Expression e = Expression::defaultShallowReduce(); - e = e.defaultHandleUnitsInChildren(); - if (e.isUndefined()) { - return e; - } - } - Expression c = childAtIndex(0); - if (c.type() == ExpressionNode::Type::Matrix) { - bool couldComputeRref = false; - Expression result = static_cast(c).createRef(reductionContext, &couldComputeRref, true); - if (couldComputeRref) { - replaceWithInPlace(result); - return result; - } - // The matrix could not be transformed properly - return *this; - } - return replaceWithUndefinedInPlace(); -} - -} diff --git a/poincare/src/parsing/parser.h b/poincare/src/parsing/parser.h index efe071406..5064d12f7 100644 --- a/poincare/src/parsing/parser.h +++ b/poincare/src/parsing/parser.h @@ -138,11 +138,11 @@ private: &Randint::s_functionHelper, &Random::s_functionHelper, &RealPart::s_functionHelper, - &MatrixRef::s_functionHelper, + &MatrixRowEchelonForm::s_functionHelper, &DivisionRemainder::s_functionHelper, &NthRoot::s_functionHelper, &Round::s_functionHelper, - &MatrixRref::s_functionHelper, + &MatrixReducedRowEchelonForm::s_functionHelper, &SignFunction::s_functionHelper, &Sine::s_functionHelper, &HyperbolicSine::s_functionHelper, diff --git a/poincare/src/tree_handle.cpp b/poincare/src/tree_handle.cpp index f75d3442a..54d663401 100644 --- a/poincare/src/tree_handle.cpp +++ b/poincare/src/tree_handle.cpp @@ -336,8 +336,8 @@ template MatrixIdentity TreeHandle::FixedArityBuilder(const Tuple &); template MatrixTrace TreeHandle::FixedArityBuilder(const Tuple &); template MatrixTranspose TreeHandle::FixedArityBuilder(const Tuple &); -template MatrixRef TreeHandle::FixedArityBuilder(const Tuple &); -template MatrixRref TreeHandle::FixedArityBuilder(const Tuple &); +template MatrixRowEchelonForm TreeHandle::FixedArityBuilder(const Tuple &); +template MatrixReducedRowEchelonForm TreeHandle::FixedArityBuilder(const Tuple &); template Multiplication TreeHandle::NAryBuilder(const Tuple &); template NaperianLogarithm TreeHandle::FixedArityBuilder(const Tuple &); template NormCDF TreeHandle::FixedArityBuilder(const Tuple &); diff --git a/poincare/test/parsing.cpp b/poincare/test/parsing.cpp index db521129c..f8bed5cc4 100644 --- a/poincare/test/parsing.cpp +++ b/poincare/test/parsing.cpp @@ -410,8 +410,8 @@ QUIZ_CASE(poincare_parsing_identifiers) { assert_parsed_expression_is("tanh(1)", HyperbolicTangent::Builder(BasedInteger::Builder(1))); assert_parsed_expression_is("trace(1)", MatrixTrace::Builder(BasedInteger::Builder(1))); assert_parsed_expression_is("transpose(1)", MatrixTranspose::Builder(BasedInteger::Builder(1))); - assert_parsed_expression_is("ref(1)", MatrixRef::Builder(BasedInteger::Builder(1))); - assert_parsed_expression_is("rref(1)", MatrixRref::Builder(BasedInteger::Builder(1))); + assert_parsed_expression_is("ref(1)", MatrixRowEchelonForm::Builder(BasedInteger::Builder(1))); + assert_parsed_expression_is("rref(1)", MatrixReducedRowEchelonForm::Builder(BasedInteger::Builder(1))); assert_parsed_expression_is("√(1)", SquareRoot::Builder(BasedInteger::Builder(1))); assert_text_not_parsable("cos(1,2)"); assert_text_not_parsable("log(1,2,3)");