diff --git a/poincare/include/poincare/approximation_helper.h b/poincare/include/poincare/approximation_helper.h index b079d6a62..6634e7646 100644 --- a/poincare/include/poincare/approximation_helper.h +++ b/poincare/include/poincare/approximation_helper.h @@ -9,6 +9,7 @@ namespace Poincare { namespace ApproximationHelper { + template int IntegerApproximationIfPossible(const ExpressionNode * expression, bool * isUndefined, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); template std::complex TruncateRealOrImaginaryPartAccordingToArgument(std::complex c); template using ComplexCompute = Complex(*)(const std::complex, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); diff --git a/poincare/src/approximation_helper.cpp b/poincare/src/approximation_helper.cpp index 2d7eafc39..2cc0b81a5 100644 --- a/poincare/src/approximation_helper.cpp +++ b/poincare/src/approximation_helper.cpp @@ -15,6 +15,18 @@ template T absMod(T a, T b) { return result > b/2 ? b-result : result; } +static inline int absInt(int x) { return x < 0 ? -x : x; } + +template int ApproximationHelper::IntegerApproximationIfPossible(const ExpressionNode * expression, bool * isUndefined, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { + Evaluation evaluation = expression->approximate(T(), context, complexFormat, angleUnit); + T scalar = evaluation.toScalar(); + if (std::isnan(scalar) || scalar != (int)scalar) { + *isUndefined = true; + return 0; + } + return absInt((int)scalar); +} + template std::complex ApproximationHelper::TruncateRealOrImaginaryPartAccordingToArgument(std::complex c) { T arg = std::arg(c); T precision = 10*Expression::Epsilon(); @@ -92,6 +104,8 @@ template MatrixComplex ApproximationHelper::ElementWiseOnComplexM return matrix; } +template int Poincare::ApproximationHelper::IntegerApproximationIfPossible(Poincare::ExpressionNode const*, bool*, Poincare::Context*, Poincare::Preferences::ComplexFormat, Poincare::Preferences::AngleUnit); +template int Poincare::ApproximationHelper::IntegerApproximationIfPossible(Poincare::ExpressionNode const*, bool*, Poincare::Context*, Poincare::Preferences::ComplexFormat, Poincare::Preferences::AngleUnit); template std::complex Poincare::ApproximationHelper::TruncateRealOrImaginaryPartAccordingToArgument(std::complex); template std::complex Poincare::ApproximationHelper::TruncateRealOrImaginaryPartAccordingToArgument(std::complex); template Poincare::Evaluation Poincare::ApproximationHelper::Map(const Poincare::ExpressionNode * expression, Poincare::Context * context, Poincare::Preferences::ComplexFormat, Poincare::Preferences::AngleUnit angleUnit, Poincare::ApproximationHelper::ComplexCompute compute); diff --git a/poincare/src/great_common_divisor.cpp b/poincare/src/great_common_divisor.cpp index 51afde0c1..a66d3525e 100644 --- a/poincare/src/great_common_divisor.cpp +++ b/poincare/src/great_common_divisor.cpp @@ -1,5 +1,6 @@ #include +#include #include #include #include @@ -27,22 +28,20 @@ Expression GreatCommonDivisorNode::shallowReduce(ReductionContext reductionConte template Evaluation GreatCommonDivisorNode::templatedApproximate(Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { - Evaluation f1Input = childAtIndex(0)->approximate(T(), context, complexFormat, angleUnit); - Evaluation f2Input = childAtIndex(1)->approximate(T(), context, complexFormat, angleUnit); - T f1 = f1Input.toScalar(); - T f2 = f2Input.toScalar(); - if (std::isnan(f1) || std::isnan(f2) || f1 != (int)f1 || f2 != (int)f2) { + bool isUndefined = false; + int a = ApproximationHelper::IntegerApproximationIfPossible(childAtIndex(0), &isUndefined, context, complexFormat, angleUnit); + int b = ApproximationHelper::IntegerApproximationIfPossible(childAtIndex(1), &isUndefined, context, complexFormat, angleUnit); + if (isUndefined) { return Complex::Undefined(); } - int a = (int)f2; - int b = (int)f1; - if (f1 > f2) { + if (b > a) { + int temp = b; b = a; - a = (int)f1; + a = temp; } int r = 0; while((int)b!=0){ - r = a - ((int)(a/b))*b; + r = a - (a/b)*b; a = b; b = r; } diff --git a/poincare/src/least_common_multiple.cpp b/poincare/src/least_common_multiple.cpp index c94547809..c6a104fed 100644 --- a/poincare/src/least_common_multiple.cpp +++ b/poincare/src/least_common_multiple.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -27,26 +28,24 @@ Expression LeastCommonMultipleNode::shallowReduce(ReductionContext reductionCont template Evaluation LeastCommonMultipleNode::templatedApproximate(Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { - Evaluation f1Input = childAtIndex(0)->approximate(T(), context, complexFormat, angleUnit); - Evaluation f2Input = childAtIndex(1)->approximate(T(), context, complexFormat, angleUnit); - T f1 = f1Input.toScalar(); - T f2 = f2Input.toScalar(); - if (std::isnan(f1) || std::isnan(f2) || f1 != (int)f1 || f2 != (int)f2) { + bool isUndefined = false; + int a = ApproximationHelper::IntegerApproximationIfPossible(childAtIndex(0), &isUndefined, context, complexFormat, angleUnit); + int b = ApproximationHelper::IntegerApproximationIfPossible(childAtIndex(1), &isUndefined, context, complexFormat, angleUnit); + if (isUndefined) { return Complex::Undefined(); } - if (f1 == 0.0f || f2 == 0.0f) { + if (a == 0 || b == 0) { return Complex::Builder(0.0); } - int a = (int)f2; - int b = (int)f1; - if (f1 > f2) { + if (b > a) { + int temp = b; b = a; - a = (int)f1; + a = temp; } int product = a*b; int r = 0; while((int)b!=0){ - r = a - ((int)(a/b))*b; + r = a - (a/b)*b; a = b; b = r; }