diff --git a/poincare/include/poincare/absolute_value.h b/poincare/include/poincare/absolute_value.h index bdbfc37d5..6e841e7a7 100644 --- a/poincare/include/poincare/absolute_value.h +++ b/poincare/include/poincare/absolute_value.h @@ -21,6 +21,7 @@ public: // Properties Type type() const override { return Type::AbsoluteValue; } Sign sign(Context * context) const override { return Sign::Positive; } + NullStatus nullStatus(Context * context) const override { return childAtIndex(0)->nullStatus(context); } Expression setSign(Sign s, ReductionContext reductionContext) override; // Approximation diff --git a/poincare/include/poincare/arc_cosine.h b/poincare/include/poincare/arc_cosine.h index 43bac523f..389ac4c79 100644 --- a/poincare/include/poincare/arc_cosine.h +++ b/poincare/include/poincare/arc_cosine.h @@ -20,6 +20,7 @@ public: #endif // Properties + Sign sign(Context * context) const override { return childAtIndex(0)->sign(context) == Sign::Unknown ? Sign::Unknown : Sign::Positive; } Type type() const override { return Type::ArcCosine; } private: diff --git a/poincare/include/poincare/arc_sine.h b/poincare/include/poincare/arc_sine.h index 2747bda13..a567d55a1 100644 --- a/poincare/include/poincare/arc_sine.h +++ b/poincare/include/poincare/arc_sine.h @@ -20,6 +20,8 @@ public: #endif // Properties + Sign sign(Context * context) const override { return childAtIndex(0)->sign(context); } + NullStatus nullStatus(Context * context) const override { return childAtIndex(0)->nullStatus(context); } Type type() const override { return Type::ArcSine; } private: // Layout diff --git a/poincare/include/poincare/arc_tangent.h b/poincare/include/poincare/arc_tangent.h index 47b6f5638..44c0ff887 100644 --- a/poincare/include/poincare/arc_tangent.h +++ b/poincare/include/poincare/arc_tangent.h @@ -20,6 +20,8 @@ public: #endif // Properties + Sign sign(Context * context) const override { return childAtIndex(0)->sign(context); } + NullStatus nullStatus(Context * context) const override { return childAtIndex(0)->nullStatus(context); } Type type() const override { return Type::ArcTangent; } private: diff --git a/poincare/include/poincare/ceiling.h b/poincare/include/poincare/ceiling.h index ff1bc5a10..a85897706 100644 --- a/poincare/include/poincare/ceiling.h +++ b/poincare/include/poincare/ceiling.h @@ -19,6 +19,7 @@ public: #endif // Properties + Sign sign(Context * context) const override { return childAtIndex(0)->sign(context); } Type type() const override { return Type::Ceiling; } private: // Layout diff --git a/poincare/include/poincare/complex_cartesian.h b/poincare/include/poincare/complex_cartesian.h index f9a71c5fd..7d9730482 100644 --- a/poincare/include/poincare/complex_cartesian.h +++ b/poincare/include/poincare/complex_cartesian.h @@ -19,6 +19,8 @@ public: #endif // Properties + Sign sign(Context * context) const override { return childAtIndex(1)->nullStatus(context) == NullStatus::Null ? childAtIndex(0)->sign(context) : Sign::Unknown; } + NullStatus nullStatus(Context * context) const override; Type type() const override { return Type::ComplexCartesian; } private: // Layout diff --git a/poincare/include/poincare/conjugate.h b/poincare/include/poincare/conjugate.h index 61b442fc5..e2f90f170 100644 --- a/poincare/include/poincare/conjugate.h +++ b/poincare/include/poincare/conjugate.h @@ -19,6 +19,8 @@ public: #endif // Properties + Sign sign(Context * context) const override { return childAtIndex(0)->sign(context); } + NullStatus nullStatus(Context * context) const override { return childAtIndex(0)->nullStatus(context); } Type type() const override { return Type::Conjugate; } private: // Layout diff --git a/poincare/include/poincare/division_remainder.h b/poincare/include/poincare/division_remainder.h index 3794c370d..e8262c7a2 100644 --- a/poincare/include/poincare/division_remainder.h +++ b/poincare/include/poincare/division_remainder.h @@ -20,6 +20,7 @@ public: #endif // ExpressionNode + Sign sign(Context * context) const override { return Sign::Positive; } Type type() const override { return Type::DivisionRemainder; } diff --git a/poincare/include/poincare/factor.h b/poincare/include/poincare/factor.h index 39e1ce4d5..329fe1902 100644 --- a/poincare/include/poincare/factor.h +++ b/poincare/include/poincare/factor.h @@ -18,6 +18,8 @@ public: stream << "Factor"; } #endif + Sign sign(Context * context) const override { return childAtIndex(0)->sign(context); } + NullStatus nullStatus(Context * context) const override { return childAtIndex(0)->nullStatus(context); } Type type() const override { return Type::Factor; } private: /* Layout */ diff --git a/poincare/include/poincare/factorial.h b/poincare/include/poincare/factorial.h index 212a94c57..2f39b2062 100644 --- a/poincare/include/poincare/factorial.h +++ b/poincare/include/poincare/factorial.h @@ -19,6 +19,7 @@ public: #endif // Properties + NullStatus nullStatus(Context * context) const override { return NullStatus::NonNull; } Type type() const override { return Type::Factorial; } Sign sign(Context * context) const override { return Sign::Positive; } Expression setSign(Sign s, ReductionContext reductionContext) override; diff --git a/poincare/include/poincare/floor.h b/poincare/include/poincare/floor.h index 65115adaa..5d360389f 100644 --- a/poincare/include/poincare/floor.h +++ b/poincare/include/poincare/floor.h @@ -19,6 +19,7 @@ public: #endif // Properties + Sign sign(Context * context) const override { return childAtIndex(0)->sign(context); } Type type() const override { return Type::Floor; } private: diff --git a/poincare/include/poincare/frac_part.h b/poincare/include/poincare/frac_part.h index 0158bb9e7..54e95817e 100644 --- a/poincare/include/poincare/frac_part.h +++ b/poincare/include/poincare/frac_part.h @@ -19,10 +19,9 @@ public: #endif // Properties + Sign sign(Context * context) const override { return Sign::Positive; } Type type() const override { return Type::FracPart; } - - private: // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/great_common_divisor.h b/poincare/include/poincare/great_common_divisor.h index d5a6c4ae3..09ef262ba 100644 --- a/poincare/include/poincare/great_common_divisor.h +++ b/poincare/include/poincare/great_common_divisor.h @@ -17,6 +17,7 @@ public: #endif // ExpressionNode + Sign sign(Context * context) const override { return Sign::Positive; } Type type() const override { return Type::GreatCommonDivisor; } private: diff --git a/poincare/include/poincare/imaginary_part.h b/poincare/include/poincare/imaginary_part.h index 345ddbc50..6fd7209ff 100644 --- a/poincare/include/poincare/imaginary_part.h +++ b/poincare/include/poincare/imaginary_part.h @@ -19,9 +19,9 @@ public: #endif // Properties + NullStatus nullStatus(Context * context) const override { return childAtIndex(0)->sign(context) != Sign::Unknown ? NullStatus::Null : NullStatus::Unknown; } Type type() const override { return Type::ImaginaryPart; } - private: // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/least_common_multiple.h b/poincare/include/poincare/least_common_multiple.h index 1feda8cb7..fe0e15a8e 100644 --- a/poincare/include/poincare/least_common_multiple.h +++ b/poincare/include/poincare/least_common_multiple.h @@ -17,6 +17,7 @@ public: #endif // ExpressionNode + Sign sign(Context * context) const override { return Sign::Positive; } Type type() const override { return Type::LeastCommonMultiple; } private: diff --git a/poincare/include/poincare/opposite.h b/poincare/include/poincare/opposite.h index c4fc89166..de8e0996f 100644 --- a/poincare/include/poincare/opposite.h +++ b/poincare/include/poincare/opposite.h @@ -23,6 +23,7 @@ public: #endif // Properties + NullStatus nullStatus(Context * context) const override { return childAtIndex(0)->nullStatus(context); } Type type() const override { return Type::Opposite; } int polynomialDegree(Context * context, const char * symbolName) const override; Sign sign(Context * context) const override; diff --git a/poincare/include/poincare/parenthesis.h b/poincare/include/poincare/parenthesis.h index 66fe39ca2..bf1fcae89 100644 --- a/poincare/include/poincare/parenthesis.h +++ b/poincare/include/poincare/parenthesis.h @@ -19,6 +19,8 @@ public: #endif // Properties + Sign sign(Context * context) const override { return childAtIndex(0)->sign(context); } + NullStatus nullStatus(Context * context) const override { return childAtIndex(0)->nullStatus(context); } Type type() const override { return Type::Parenthesis; } 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/permute_coefficient.h b/poincare/include/poincare/permute_coefficient.h index 1bc05924b..5ebfb0032 100644 --- a/poincare/include/poincare/permute_coefficient.h +++ b/poincare/include/poincare/permute_coefficient.h @@ -22,7 +22,7 @@ public: // Properties Type type() const override{ return Type::PermuteCoefficient; } - + Sign sign(Context * context) const override { return Sign::Positive; } private: // Layout diff --git a/poincare/include/poincare/real_part.h b/poincare/include/poincare/real_part.h index ddcbd24a7..a35db4b94 100644 --- a/poincare/include/poincare/real_part.h +++ b/poincare/include/poincare/real_part.h @@ -19,6 +19,8 @@ public: #endif // Properties + Sign sign(Context * context) const override { return childAtIndex(0)->sign(context); } + NullStatus nullStatus(Context * context) const override { return childAtIndex(0)->nullStatus(context) == NullStatus::Null ? NullStatus::Null : NullStatus::Unknown; } Type type() const override { return Type::RealPart; } diff --git a/poincare/include/poincare/round.h b/poincare/include/poincare/round.h index bb4a769aa..1d4ec886b 100644 --- a/poincare/include/poincare/round.h +++ b/poincare/include/poincare/round.h @@ -20,6 +20,7 @@ public: // Properties + Sign sign(Context * context) const override { return childAtIndex(0)->sign(context); } Type type() const override { return Type::Round; } private: // Layout diff --git a/poincare/include/poincare/sign_function.h b/poincare/include/poincare/sign_function.h index d5379058a..dbb590c35 100644 --- a/poincare/include/poincare/sign_function.h +++ b/poincare/include/poincare/sign_function.h @@ -20,7 +20,8 @@ public: // Properties Type type() const override { return Type::SignFunction; } - Sign sign(Context * context) const override; + Sign sign(Context * context) const override { return childAtIndex(0)->sign(context); } + NullStatus nullStatus(Context * context) const override { return childAtIndex(0)->nullStatus(context); } Expression setSign(Sign s, ReductionContext reductionContext) override; diff --git a/poincare/include/poincare/unit.h b/poincare/include/poincare/unit.h index c44138a41..2437e83d4 100644 --- a/poincare/include/poincare/unit.h +++ b/poincare/include/poincare/unit.h @@ -456,7 +456,8 @@ public: // Expression Properties Type type() const override { return Type::Unit; } - Sign sign(Context * context) const override; + Sign sign(Context * context) const override { return Sign::Positive; } + NullStatus nullStatus(Context * context) const override { return NullStatus::NonNull; } Expression removeUnit(Expression * unit) override; /* Layout */ diff --git a/poincare/include/poincare/vector_norm.h b/poincare/include/poincare/vector_norm.h index c13a6a1d8..3d2da252a 100644 --- a/poincare/include/poincare/vector_norm.h +++ b/poincare/include/poincare/vector_norm.h @@ -18,6 +18,7 @@ public: #endif // Properties + Sign sign(Context * context) const override { return Sign::Positive; } Type type() const override { return Type::VectorNorm; } private: // Layout diff --git a/poincare/src/complex_cartesian.cpp b/poincare/src/complex_cartesian.cpp index df7cea0c5..b02cd4199 100644 --- a/poincare/src/complex_cartesian.cpp +++ b/poincare/src/complex_cartesian.cpp @@ -19,6 +19,15 @@ namespace Poincare { +ExpressionNode::NullStatus ComplexCartesianNode::nullStatus(Context * context) const { + ExpressionNode::NullStatus realNullStatus = childAtIndex(0)->nullStatus(context); + ExpressionNode::NullStatus imagNullStatus = childAtIndex(1)->nullStatus(context); + if (realNullStatus == ExpressionNode::NullStatus::NonNull || imagNullStatus == ExpressionNode::NullStatus::NonNull) { + return ExpressionNode::NullStatus::NonNull; + } + return (realNullStatus == ExpressionNode::NullStatus::Null && imagNullStatus == ExpressionNode::NullStatus::Null) ? ExpressionNode::NullStatus::Null : ExpressionNode::NullStatus::Unknown; +} + Expression ComplexCartesianNode::shallowReduce(ReductionContext reductionContext) { return ComplexCartesian(this).shallowReduce(); } diff --git a/poincare/src/sign_function.cpp b/poincare/src/sign_function.cpp index ba4765413..335c02543 100644 --- a/poincare/src/sign_function.cpp +++ b/poincare/src/sign_function.cpp @@ -15,10 +15,6 @@ constexpr Expression::FunctionHelper SignFunction::s_functionHelper; int SignFunctionNode::numberOfChildren() const { return SignFunction::s_functionHelper.numberOfChildren(); } -ExpressionNode::Sign SignFunctionNode::sign(Context * context) const { - return childAtIndex(0)->sign(context); -} - Expression SignFunctionNode::setSign(Sign s, ReductionContext reductionContext) { assert(s == ExpressionNode::Sign::Positive || s == ExpressionNode::Sign::Negative); SignFunction sign(this); diff --git a/poincare/src/unit.cpp b/poincare/src/unit.cpp index 44649c450..d6d355da7 100644 --- a/poincare/src/unit.cpp +++ b/poincare/src/unit.cpp @@ -653,10 +653,6 @@ int UnitNode::SpeedRepresentative::setAdditionalExpressions(double value, Expres } // UnitNode -ExpressionNode::Sign UnitNode::sign(Context * context) const { - return Sign::Positive; -} - Expression UnitNode::removeUnit(Expression * unit) { return Unit(this).removeUnit(unit); } diff --git a/poincare/test/expression_properties.cpp b/poincare/test/expression_properties.cpp index 379775b2f..2f83a5c7d 100644 --- a/poincare/test/expression_properties.cpp +++ b/poincare/test/expression_properties.cpp @@ -36,6 +36,19 @@ QUIZ_CASE(poincare_properties_is_number_zero) { quiz_assert(Symbol::Builder('a').nullStatus(&context) == ExpressionNode::NullStatus::Unknown); quiz_assert(Multiplication::Builder(Rational::Builder(1), Rational::Builder(0)).nullStatus(&context) == ExpressionNode::NullStatus::Unknown); quiz_assert(Addition::Builder(Rational::Builder(1), Rational::Builder(-1)).nullStatus(&context) == ExpressionNode::NullStatus::Unknown); + + quiz_assert(AbsoluteValue::Builder(Rational::Builder(0)).nullStatus(&context) == ExpressionNode::NullStatus::Null); + quiz_assert(ArcSine::Builder(Rational::Builder(1,7)).nullStatus(&context) == ExpressionNode::NullStatus::NonNull); + quiz_assert(ComplexCartesian::Builder(Rational::Builder(0), Rational::Builder(3, 2)).nullStatus(&context) == ExpressionNode::NullStatus::NonNull); + quiz_assert(ComplexCartesian::Builder(Rational::Builder(0), Rational::Builder(0)).nullStatus(&context) == ExpressionNode::NullStatus::Null); + quiz_assert(Conjugate::Builder(ComplexCartesian::Builder(Rational::Builder(2, 3), Rational::Builder(3, 2))).nullStatus(&context) == ExpressionNode::NullStatus::NonNull); + quiz_assert(Factor::Builder(Rational::Builder(0)).nullStatus(&context) == ExpressionNode::NullStatus::Null); + quiz_assert(Factorial::Builder(Rational::Builder(0)).nullStatus(&context) == ExpressionNode::NullStatus::NonNull); + quiz_assert(ImaginaryPart::Builder(Rational::Builder(14)).nullStatus(&context) == ExpressionNode::NullStatus::Null); + quiz_assert(RealPart::Builder(Rational::Builder(0)).nullStatus(&context) == ExpressionNode::NullStatus::Null); + 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_CASE(poincare_properties_is_random) { @@ -154,6 +167,31 @@ QUIZ_CASE(poincare_properties_rational_sign) { quiz_assert(Rational::Builder(0, 3).sign() == ExpressionNode::Sign::Positive); } +QUIZ_CASE(poincare_properties_expression_sign) { + Shared::GlobalContext context; + quiz_assert(ArcCosine::Builder(Rational::Builder(-1,7)).sign(&context) == ExpressionNode::Sign::Positive); + quiz_assert(ArcCosine::Builder(Symbol::Builder('a')).sign(&context) == ExpressionNode::Sign::Unknown); + quiz_assert(ArcSine::Builder(Rational::Builder(-1,7)).sign(&context) == ExpressionNode::Sign::Negative); + quiz_assert(ArcTangent::Builder(Rational::Builder(1,7)).sign(&context) == ExpressionNode::Sign::Positive); + quiz_assert(Ceiling::Builder(Rational::Builder(7,3)).sign(&context) == ExpressionNode::Sign::Positive); + quiz_assert(Floor::Builder(Rational::Builder(7,3)).sign(&context) == ExpressionNode::Sign::Positive); + quiz_assert(Round::Builder(Rational::Builder(7,3), Rational::Builder(1)).sign(&context) == ExpressionNode::Sign::Positive); + quiz_assert(Conjugate::Builder(ComplexCartesian::Builder(Rational::Builder(2, 3), BasedInteger::Builder(0, Integer::Base::Binary))).sign(&context) == ExpressionNode::Sign::Positive); + quiz_assert(DivisionRemainder::Builder(Decimal::Builder(2.0), Decimal::Builder(3.0)).sign(&context) == ExpressionNode::Sign::Positive); + quiz_assert(AbsoluteValue::Builder(Rational::Builder(-14)).sign(&context) == ExpressionNode::Sign::Positive); + quiz_assert(FracPart::Builder(Rational::Builder(-7,3)).sign(&context) == ExpressionNode::Sign::Positive); + quiz_assert(GreatCommonDivisor::Builder({Rational::Builder(-7),Rational::Builder(-7)}).sign(&context) == ExpressionNode::Sign::Positive); + quiz_assert(LeastCommonMultiple::Builder({Rational::Builder(-7),Rational::Builder(-7)}).sign(&context) == ExpressionNode::Sign::Positive); + quiz_assert(Opposite::Builder(Rational::Builder(7)).sign(&context) == ExpressionNode::Sign::Negative); + quiz_assert(Parenthesis::Builder(Rational::Builder(-7)).sign(&context) == ExpressionNode::Sign::Negative); + quiz_assert(PermuteCoefficient::Builder(Rational::Builder(7),Rational::Builder(8)).sign(&context) == ExpressionNode::Sign::Positive); + quiz_assert(RealPart::Builder(Rational::Builder(-7)).sign(&context) == ExpressionNode::Sign::Negative); + 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(ArcSine::Builder(Floor::Builder(ArcTangent::Builder(Opposite::Builder(RealPart::Builder(ArcCosine::Builder(Constant::Builder(UCodePointGreekSmallLetterPi))))))).sign(&context) == ExpressionNode::Sign::Negative); +} + QUIZ_CASE(poincare_properties_sign) { assert_reduced_expression_sign("abs(-cos(2)+I)", Positive); assert_reduced_expression_sign("2.345ᴇ-23", Positive);