[poincare] Add NullStatus and sign for more expressions

Change-Id: I4443a28532f5b728afe169a3d2a70d9026bc1909
This commit is contained in:
Hugo Saint-Vignes
2020-10-23 15:34:54 +02:00
committed by Émilie Feral
parent 4a3f749cc6
commit 61d33be2a7
27 changed files with 79 additions and 14 deletions

View File

@@ -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

View File

@@ -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:

View File

@@ -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

View File

@@ -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:

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -20,6 +20,7 @@ public:
#endif
// ExpressionNode
Sign sign(Context * context) const override { return Sign::Positive; }
Type type() const override { return Type::DivisionRemainder; }

View File

@@ -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 */

View File

@@ -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;

View File

@@ -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:

View File

@@ -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;

View File

@@ -17,6 +17,7 @@ public:
#endif
// ExpressionNode
Sign sign(Context * context) const override { return Sign::Positive; }
Type type() const override { return Type::GreatCommonDivisor; }
private:

View File

@@ -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;

View File

@@ -17,6 +17,7 @@ public:
#endif
// ExpressionNode
Sign sign(Context * context) const override { return Sign::Positive; }
Type type() const override { return Type::LeastCommonMultiple; }
private:

View File

@@ -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;

View File

@@ -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); }

View File

@@ -22,7 +22,7 @@ public:
// Properties
Type type() const override{ return Type::PermuteCoefficient; }
Sign sign(Context * context) const override { return Sign::Positive; }
private:
// Layout

View File

@@ -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; }

View File

@@ -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

View File

@@ -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;

View File

@@ -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 */

View File

@@ -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

View File

@@ -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();
}

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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);