diff --git a/poincare/include/poincare/absolute_value.h b/poincare/include/poincare/absolute_value.h index 2aad1feed..357198c54 100644 --- a/poincare/include/poincare/absolute_value.h +++ b/poincare/include/poincare/absolute_value.h @@ -55,7 +55,7 @@ public: static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("abs", 1, &UntypedBuilder); - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit); + Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); private: explicit AbsoluteValue(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child); diff --git a/poincare/include/poincare/complex_argument.h b/poincare/include/poincare/complex_argument.h index 014b8956d..9040a8b62 100644 --- a/poincare/include/poincare/complex_argument.h +++ b/poincare/include/poincare/complex_argument.h @@ -47,7 +47,7 @@ public: static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("arg", 1, &UntypedBuilder); - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit); + Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); private: explicit ComplexArgument(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child); diff --git a/poincare/include/poincare/imaginary_part.h b/poincare/include/poincare/imaginary_part.h index 8b40bfdd8..80da8e387 100644 --- a/poincare/include/poincare/imaginary_part.h +++ b/poincare/include/poincare/imaginary_part.h @@ -50,7 +50,7 @@ public: static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("im", 1, &UntypedBuilder); - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit); + Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); private: explicit ImaginaryPart(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child); diff --git a/poincare/include/poincare/real_part.h b/poincare/include/poincare/real_part.h index e719175cd..f1d99b93d 100644 --- a/poincare/include/poincare/real_part.h +++ b/poincare/include/poincare/real_part.h @@ -50,7 +50,7 @@ public: static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("re", 1, &UntypedBuilder); - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit); + Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); private: explicit RealPart(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child); diff --git a/poincare/src/absolute_value.cpp b/poincare/src/absolute_value.cpp index 0270ba146..4e2655683 100644 --- a/poincare/src/absolute_value.cpp +++ b/poincare/src/absolute_value.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -25,7 +26,7 @@ int AbsoluteValueNode::serialize(char * buffer, int bufferSize, Preferences::Pri } Expression AbsoluteValueNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return AbsoluteValue(this).shallowReduce(context, angleUnit); + return AbsoluteValue(this).shallowReduce(context, angleUnit, target); } Expression AbsoluteValue::setSign(ExpressionNode::Sign s, Context * context, Preferences::AngleUnit angleUnit) { @@ -33,12 +34,11 @@ Expression AbsoluteValue::setSign(ExpressionNode::Sign s, Context * context, Pre return *this; } -Expression AbsoluteValue::shallowReduce(Context & context, Preferences::AngleUnit angleUnit) { +Expression AbsoluteValue::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { Expression e = Expression::defaultShallowReduce(context, angleUnit); if (e.isUndefined()) { return e; } - Expression c = childAtIndex(0); #if MATRIX_EXACT_REDUCING #if 0 if (c->type() == Type::Matrix) { @@ -46,14 +46,11 @@ Expression AbsoluteValue::shallowReduce(Context & context, Preferences::AngleUni } #endif #endif - if (c.sign(&context, angleUnit) == ExpressionNode::Sign::Positive) { - replaceWithInPlace(c); - return c; - } - if (c.sign(&context, angleUnit) == ExpressionNode::Sign::Negative) { - Expression result = c.setSign(ExpressionNode::Sign::Positive, &context, angleUnit); - replaceWithInPlace(result); - return result; + Expression c = childAtIndex(0); + Expression norm = c.complexNorm(context, angleUnit); + if (!norm.isUninitialized()) { + replaceWithInPlace(norm); + return norm.deepReduce(context, angleUnit, target); } return *this; } diff --git a/poincare/src/complex_argument.cpp b/poincare/src/complex_argument.cpp index c7d6d0396..01893996b 100644 --- a/poincare/src/complex_argument.cpp +++ b/poincare/src/complex_argument.cpp @@ -22,7 +22,7 @@ int ComplexArgumentNode::serialize(char * buffer, int bufferSize, Preferences::P } Expression ComplexArgumentNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return ComplexArgument(this).shallowReduce(context, angleUnit); + return ComplexArgument(this).shallowReduce(context, angleUnit, target); } template @@ -30,19 +30,24 @@ Complex ComplexArgumentNode::computeOnComplex(const std::complex c, Prefer return Complex(std::arg(c)); } -Expression ComplexArgument::shallowReduce(Context & context, Preferences::AngleUnit angleUnit) { +Expression ComplexArgument::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { Expression e = Expression::defaultShallowReduce(context, angleUnit); if (e.isUndefined()) { return e; } } -#if MATRIX_EXACT_REDUCING Expression c = childAtIndex(0); +#if MATRIX_EXACT_REDUCING if (c.type() == ExpressionNode::Type::Matrix) { return SimplificationHelper::Map(*this, context, angleUnit); } #endif + Expression arg = c.complexArgument(context, angleUnit); + if (!arg.isUninitialized()) { + replaceWithInPlace(arg); + return arg.deepReduce(context, angleUnit, target); + } return *this; } diff --git a/poincare/src/expression_node.cpp b/poincare/src/expression_node.cpp index cc5c0432f..9541ee766 100644 --- a/poincare/src/expression_node.cpp +++ b/poincare/src/expression_node.cpp @@ -109,7 +109,7 @@ Expression ExpressionNode::complexArgument(Context & context, Preferences::Angle Multiplication( SignFunction::Builder(b).shallowReduce(context, angleUnit), Division(Constant(Ion::Charset::SmallPi), Rational(2)).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation) - ), + ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation), arcTangent ).shallowReduce(context, angleUnit, ReductionTarget::BottomUpComputation); } else { diff --git a/poincare/src/imaginary_part.cpp b/poincare/src/imaginary_part.cpp index 2a5c3ae43..9379d5ec4 100644 --- a/poincare/src/imaginary_part.cpp +++ b/poincare/src/imaginary_part.cpp @@ -20,10 +20,10 @@ int ImaginaryPartNode::serialize(char * buffer, int bufferSize, Preferences::Pri } Expression ImaginaryPartNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return ImaginaryPart(this).shallowReduce(context, angleUnit); + return ImaginaryPart(this).shallowReduce(context, angleUnit, target); } -Expression ImaginaryPart::shallowReduce(Context & context, Preferences::AngleUnit angleUnit) { +Expression ImaginaryPart::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { Expression e = Expression::defaultShallowReduce(context, angleUnit); if (e.isUndefined()) { @@ -41,6 +41,11 @@ Expression ImaginaryPart::shallowReduce(Context & context, Preferences::AngleUni replaceWithInPlace(result); return result; } + Expression im = c.imaginaryPart(context, angleUnit); + if (!im.isUninitialized()) { + replaceWithInPlace(im); + return im.deepReduce(context, angleUnit, target); + } return *this; } diff --git a/poincare/src/real_part.cpp b/poincare/src/real_part.cpp index b4fdf9e88..e599dce38 100644 --- a/poincare/src/real_part.cpp +++ b/poincare/src/real_part.cpp @@ -20,10 +20,10 @@ int RealPartNode::serialize(char * buffer, int bufferSize, Preferences::PrintFlo } Expression RealPartNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return RealPart(this).shallowReduce(context, angleUnit); + return RealPart(this).shallowReduce(context, angleUnit, target); } -Expression RealPart::shallowReduce(Context & context, Preferences::AngleUnit angleUnit) { +Expression RealPart::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { Expression e = Expression::defaultShallowReduce(context, angleUnit); if (e.isUndefined()) { @@ -40,6 +40,11 @@ Expression RealPart::shallowReduce(Context & context, Preferences::AngleUnit ang replaceWithInPlace(c); return c; } + Expression re = c.realPart(context, angleUnit); + if (!re.isUninitialized()) { + replaceWithInPlace(re); + return re.deepReduce(context, angleUnit, target); + } return *this; } diff --git a/poincare/test/complex.cpp b/poincare/test/complex.cpp index d47451641..e86e56afb 100644 --- a/poincare/test/complex.cpp +++ b/poincare/test/complex.cpp @@ -69,12 +69,12 @@ QUIZ_CASE(poincare_complex_parts) { assert_expression_has_complex_cartesian_parts("I", "0", "1"); assert_expression_has_complex_cartesian_parts("abs(-3)", "3", "0"); - assert_expression_has_complex_cartesian_parts("abs(-3+I)", "abs(-3+I)", "0"); + assert_expression_has_complex_cartesian_parts("abs(-3+I)", "R(10)", "0"); assert_expression_has_complex_cartesian_parts("atan(2)", "atan(2)", "0"); assert_expression_has_complex_cartesian_parts("atan(2+I)", nullptr, nullptr); assert_expression_has_complex_cartesian_parts("binomial(10, 4)", "210", "0"); assert_expression_has_complex_cartesian_parts("ceil(-1.3)", "-1", "0"); - assert_expression_has_complex_cartesian_parts("arg(-2)", "arg(-2)", "0"); + assert_expression_has_complex_cartesian_parts("arg(-2)", "P", "0"); // TODO: confidence is not simplified yet //assert_expression_has_complex_cartesian_parts("confidence(-2,-3)", "confidence(-2)", "0"); assert_expression_has_complex_cartesian_parts("conj(-2)", "-2", "0"); @@ -87,7 +87,7 @@ QUIZ_CASE(poincare_complex_parts) { assert_expression_has_complex_cartesian_parts("floor(x)", "floor(x)", "0"); assert_expression_has_complex_cartesian_parts("frac(x)", "frac(x)", "0"); assert_expression_has_complex_cartesian_parts("gcd(x,y)", "gcd(x,y)", "0"); - assert_expression_has_complex_cartesian_parts("im(x)", "im(x)", "0"); + assert_expression_has_complex_cartesian_parts("im(1+I)", "1", "0"); assert_expression_has_complex_cartesian_parts("int(x^2, x, 1, 2)", "int(x^2,x,1,2)", "0"); assert_expression_has_complex_cartesian_parts("lcm(x,y)", "lcm(x,y)", "0"); // TODO: dim is not simplified yet @@ -101,7 +101,7 @@ QUIZ_CASE(poincare_complex_parts) { //assert_expression_has_complex_cartesian_parts("prediction(-2,-3)", "prediction(-2)", "0"); assert_expression_has_complex_cartesian_parts("randint(2,4)", "randint(2,4)", "0"); assert_expression_has_complex_cartesian_parts("random()", "random()", "0"); - assert_expression_has_complex_cartesian_parts("re(x)", "re(x)", "0"); + assert_expression_has_complex_cartesian_parts("re(x)", "x", "0"); assert_expression_has_complex_cartesian_parts("round(x,y)", "round(x,y)", "0"); assert_expression_has_complex_cartesian_parts("sign(x)", "sign(x)", "0"); assert_expression_has_complex_cartesian_parts("sin(23)", "sin(23)", "0"); @@ -148,5 +148,5 @@ QUIZ_CASE(poincare_complex_parts) { assert_expression_has_complex_polar_parts("P", "P", "0"); assert_expression_has_complex_polar_parts("I", "1", "P/2"); assert_expression_has_complex_polar_parts("abs(-3)", "3", "0"); - assert_expression_has_complex_polar_parts("abs(-3+I)", "abs(-3+I)", "0"); + assert_expression_has_complex_polar_parts("abs(-3+I)", "R(10)", "0"); } diff --git a/poincare/test/function.cpp b/poincare/test/function.cpp index 8c711a7b5..d8d9d654a 100644 --- a/poincare/test/function.cpp +++ b/poincare/test/function.cpp @@ -238,6 +238,8 @@ QUIZ_CASE(poincare_function_evaluate) { QUIZ_CASE(poincare_function_simplify) { assert_parsed_expression_simplify_to("abs(P)", "P"); assert_parsed_expression_simplify_to("abs(-P)", "P"); + assert_parsed_expression_simplify_to("abs(1+I)", "R(2)"); + assert_parsed_expression_simplify_to("arg(1+I)", "P/4"); assert_parsed_expression_simplify_to("binomial(20,3)", "1140"); assert_parsed_expression_simplify_to("binomial(20,10)", "184756"); assert_parsed_expression_simplify_to("ceil(-1.3)", "-1"); @@ -257,9 +259,11 @@ QUIZ_CASE(poincare_function_simplify) { assert_parsed_expression_simplify_to("frac(-1.3)", "7/10"); assert_parsed_expression_simplify_to("gcd(123,278)", "1"); assert_parsed_expression_simplify_to("gcd(11,121)", "11"); + assert_parsed_expression_simplify_to("im(1+5*I)", "5"); assert_parsed_expression_simplify_to("lcm(123,278)", "34194"); assert_parsed_expression_simplify_to("lcm(11,121)", "121"); assert_parsed_expression_simplify_to("R(4)", "2"); + assert_parsed_expression_simplify_to("re(1+5*I)", "1"); assert_parsed_expression_simplify_to("root(4,3)", "root(4,3)"); assert_parsed_expression_simplify_to("root(4,P)", "4^(1/P)"); assert_parsed_expression_simplify_to("root(27,3)", "3");