From 42f20fb58d466c26190690b917ebb38590817d13 Mon Sep 17 00:00:00 2001 From: Hugo Saint-Vignes Date: Fri, 23 Oct 2020 16:14:54 +0200 Subject: [PATCH] [poincare] Add NullStatus and sign for more complex expressions Change-Id: Ic593517bf7a983985fe3c521e10c19ab0bca4191 --- poincare/include/poincare/division.h | 5 +++++ poincare/include/poincare/division_quotient.h | 1 + poincare/include/poincare/power.h | 4 ++++ poincare/include/poincare/square_root.h | 2 ++ poincare/src/division.cpp | 9 +++++++++ poincare/src/division_quotient.cpp | 9 +++++++++ poincare/test/expression_properties.cpp | 5 +++++ 7 files changed, 35 insertions(+) diff --git a/poincare/include/poincare/division.h b/poincare/include/poincare/division.h index 4b924844d..b48a4d883 100644 --- a/poincare/include/poincare/division.h +++ b/poincare/include/poincare/division.h @@ -23,6 +23,11 @@ public: #endif // Properties + Sign sign(Context * context) const override; + NullStatus nullStatus(Context * context) const override { + // NonNull Status can't be returned because denominator could be infinite. + return childAtIndex(0)->nullStatus(context) == NullStatus::Null ? NullStatus::Null : NullStatus::Unknown; + } Type type() const override { return Type::Division; } int polynomialDegree(Context * context, const char * symbolName) const override; Expression removeUnit(Expression * unit) override { assert(false); return ExpressionNode::removeUnit(unit); } diff --git a/poincare/include/poincare/division_quotient.h b/poincare/include/poincare/division_quotient.h index e55fcec65..2db2f95db 100644 --- a/poincare/include/poincare/division_quotient.h +++ b/poincare/include/poincare/division_quotient.h @@ -19,6 +19,7 @@ public: #endif // ExpressionNode + Sign sign(Context * context) const override; Type type() const override { return Type::DivisionQuotient; } // Simplification diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index 0363718a2..e8f7f384b 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -27,6 +27,10 @@ public: // Properties Type type() const override { return Type::Power; } Sign sign(Context * context) const override; + NullStatus nullStatus(Context * context) const override { + // NonNull Status can't be returned because base could be infinite. + return childAtIndex(0)->nullStatus(context) == NullStatus::Null ? NullStatus::Null : NullStatus::Unknown; + } Expression setSign(Sign s, ReductionContext reductionContext) override; bool childAtIndexNeedsUserParentheses(const Expression & child, int childIndex) const override; Expression removeUnit(Expression * unit) override; diff --git a/poincare/include/poincare/square_root.h b/poincare/include/poincare/square_root.h index 6a46aee29..a6f9a69d1 100644 --- a/poincare/include/poincare/square_root.h +++ b/poincare/include/poincare/square_root.h @@ -10,6 +10,8 @@ namespace Poincare { class SquareRootNode /*final*/ : public ExpressionNode { public: // ExpressionNode + Sign sign(Context * context) const override { return childAtIndex(0)->sign(context) == Sign::Positive ? Sign::Positive : Sign::Unknown ; } + NullStatus nullStatus(Context * context) const override { return childAtIndex(0)->nullStatus(context); } Type type() const override { return Type::SquareRoot; } // TreeNode diff --git a/poincare/src/division.cpp b/poincare/src/division.cpp index 77ff4c825..488d3f23a 100644 --- a/poincare/src/division.cpp +++ b/poincare/src/division.cpp @@ -14,6 +14,15 @@ namespace Poincare { +ExpressionNode::Sign DivisionNode::sign(Context * context) const { + ExpressionNode::Sign numeratorSign = childAtIndex(0)->sign(context); + ExpressionNode::Sign denominatorSign = childAtIndex(1)->sign(context); + if (numeratorSign == ExpressionNode::Sign::Unknown || denominatorSign == ExpressionNode::Sign::Unknown) { + return ExpressionNode::Sign::Unknown; + } + return numeratorSign == denominatorSign ? ExpressionNode::Sign::Positive : ExpressionNode::Sign::Negative; +} + int DivisionNode::polynomialDegree(Context * context, const char * symbolName) const { if (childAtIndex(1)->polynomialDegree(context, symbolName) != 0) { return -1; diff --git a/poincare/src/division_quotient.cpp b/poincare/src/division_quotient.cpp index dfbc04c3f..f081031de 100644 --- a/poincare/src/division_quotient.cpp +++ b/poincare/src/division_quotient.cpp @@ -12,6 +12,15 @@ constexpr Expression::FunctionHelper DivisionQuotient::s_functionHelper; int DivisionQuotientNode::numberOfChildren() const { return DivisionQuotient::s_functionHelper.numberOfChildren(); } +ExpressionNode::Sign DivisionQuotientNode::sign(Context * context) const { + ExpressionNode::Sign numeratorSign = childAtIndex(0)->sign(context); + ExpressionNode::Sign denominatorSign = childAtIndex(1)->sign(context); + if (numeratorSign == ExpressionNode::Sign::Unknown || denominatorSign == ExpressionNode::Sign::Unknown) { + return ExpressionNode::Sign::Unknown; + } + return numeratorSign == denominatorSign ? ExpressionNode::Sign::Positive : ExpressionNode::Sign::Negative; +} + Expression DivisionQuotientNode::shallowReduce(ReductionContext reductionContext) { return DivisionQuotient(this).shallowReduce(reductionContext.context()); } diff --git a/poincare/test/expression_properties.cpp b/poincare/test/expression_properties.cpp index 2f83a5c7d..0fdc1e493 100644 --- a/poincare/test/expression_properties.cpp +++ b/poincare/test/expression_properties.cpp @@ -49,6 +49,9 @@ QUIZ_CASE(poincare_properties_is_number_zero) { quiz_assert(Parenthesis::Builder(Rational::Builder(-7)).nullStatus(&context) == ExpressionNode::NullStatus::NonNull); quiz_assert(SignFunction::Builder(Rational::Builder(0)).nullStatus(&context) == ExpressionNode::NullStatus::Null); quiz_assert(Unit::Builder(Unit::k_powerRepresentatives, Unit::Prefix::EmptyPrefix()).nullStatus(&context) == ExpressionNode::NullStatus::NonNull); + quiz_assert(Division::Builder(Rational::Builder(0), Rational::Builder(3,7)).nullStatus(&context) == ExpressionNode::NullStatus::Null); + quiz_assert(Power::Builder(Rational::Builder(0), Rational::Builder(3,7)).nullStatus(&context) == ExpressionNode::NullStatus::Null); + quiz_assert(SquareRoot::Builder(Rational::Builder(2,5)).nullStatus(&context) == ExpressionNode::NullStatus::NonNull); } QUIZ_CASE(poincare_properties_is_random) { @@ -189,6 +192,8 @@ QUIZ_CASE(poincare_properties_expression_sign) { quiz_assert(SignFunction::Builder(Rational::Builder(-7)).sign(&context) == ExpressionNode::Sign::Negative); quiz_assert(Unit::Builder(Unit::k_powerRepresentatives, Unit::Prefix::EmptyPrefix()).sign(&context) == ExpressionNode::Sign::Positive); quiz_assert(VectorNorm::Builder(BasedInteger::Builder(1)).sign(&context) == ExpressionNode::Sign::Positive); + quiz_assert(Division::Builder(Rational::Builder(7,3), Rational::Builder(-1)).sign(&context) == ExpressionNode::Sign::Negative); + quiz_assert(DivisionQuotient::Builder(Rational::Builder(-7), Rational::Builder(-1)).sign(&context) == ExpressionNode::Sign::Positive); quiz_assert(ArcSine::Builder(Floor::Builder(ArcTangent::Builder(Opposite::Builder(RealPart::Builder(ArcCosine::Builder(Constant::Builder(UCodePointGreekSmallLetterPi))))))).sign(&context) == ExpressionNode::Sign::Negative); }