Numworks Epsilon  1.4.1
Graphing Calculator Operating System
great_common_divisor.cpp
Go to the documentation of this file.
2 #include <poincare/complex.h>
3 #include <poincare/undefined.h>
4 #include <poincare/rational.h>
5 #include <poincare/arithmetic.h>
6 
7 extern "C" {
8 #include <assert.h>
9 }
10 #include <cmath>
11 
12 namespace Poincare {
13 
16 }
17 
20  return a;
21 }
22 
23 Expression * GreatCommonDivisor::shallowReduce(Context& context, AngleUnit angleUnit) {
24  Expression * e = Expression::shallowReduce(context, angleUnit);
25  if (e != this) {
26  return e;
27  }
28  Expression * op0 = editableOperand(0);
29  Expression * op1 = editableOperand(1);
30 #if MATRIX_EXACT_REDUCING
31  if (op0->type() == Type::Matrix || op1->type() == Type::Matrix) {
32  return replaceWith(new Undefined(), true);
33  }
34 #endif
35  if (op0->type() == Type::Rational) {
36  Rational * r0 = static_cast<Rational *>(op0);
37  if (!r0->denominator().isOne()) {
38  return replaceWith(new Undefined(), true);
39  }
40  }
41  if (op1->type() == Type::Rational) {
42  Rational * r1 = static_cast<Rational *>(op1);
43  if (!r1->denominator().isOne()) {
44  return replaceWith(new Undefined(), true);
45  }
46  }
47  if (op0->type() != Type::Rational || op1->type() != Type::Rational) {
48  return this;
49  }
50  Rational * r0 = static_cast<Rational *>(op0);
51  Rational * r1 = static_cast<Rational *>(op1);
52 
53  Integer a = r0->numerator();
54  Integer b = r1->numerator();
55  Integer gcd = Arithmetic::GCD(&a, &b);
56  return replaceWith(new Rational(gcd), true);
57 }
58 
59 template<typename T>
60 Complex<T> * GreatCommonDivisor::templatedApproximate(Context& context, AngleUnit angleUnit) const {
61  Expression * f1Input = operand(0)->approximate<T>(context, angleUnit);
62  Expression * f2Input = operand(1)->approximate<T>(context, angleUnit);
63  T f1 = f1Input->type() == Type::Complex ? static_cast<Complex<T> *>(f1Input)->toScalar() : NAN;
64  T f2 = f2Input->type() == Type::Complex ? static_cast<Complex<T> *>(f2Input)->toScalar() : NAN;
65  delete f1Input;
66  delete f2Input;
67  if (std::isnan(f1) || std::isnan(f2) || f1 != (int)f1 || f2 != (int)f2) {
68  return new Complex<T>(Complex<T>::Float(NAN));
69  }
70  int a = (int)f2;
71  int b = (int)f1;
72  if (f1 > f2) {
73  b = a;
74  a = (int)f1;
75  }
76  int r = 0;
77  while((int)b!=0){
78  r = a - ((int)(a/b))*b;
79  a = b;
80  b = r;
81  }
82  return new Complex<T>(Complex<T>::Float(std::round((T)a)));
83 }
84 
85 }
86 
#define NAN
Definition: math.h:30
Expression * replaceWith(Expression *newOperand, bool deleteAfterReplace=true)
Definition: expression.cpp:85
friend class GreatCommonDivisor
Definition: expression.h:45
Expression * approximate(Context &context, AngleUnit angleUnit=AngleUnit::Default) const
Definition: expression.cpp:338
#define T(x)
Definition: events.cpp:26
static Integer GCD(const Integer *i, const Integer *j)
Definition: arithmetic.cpp:15
Expression * editableOperand(int i)
Definition: expression.h:176
friend class Rational
Definition: expression.h:18
#define round(x)
Definition: math.h:192
const Expression * m_operands[T]
Expression * clone() const override
#define isnan(x)
Definition: math.h:43
static Complex< T > Float(T x)
Definition: complex.cpp:23
const Expression * operand(int i) const
Definition: expression.cpp:78
friend class Undefined
Definition: expression.h:17