Numworks Epsilon  1.4.1
Graphing Calculator Operating System
rational.cpp
Go to the documentation of this file.
1 #include <poincare/rational.h>
2 extern "C" {
3 #include <stdlib.h>
4 #include <string.h>
5 #include <assert.h>
6 #include <math.h>
7 }
8 #include <poincare/arithmetic.h>
9 #include <poincare/opposite.h>
10 #include "layout/string_layout.h"
11 #include "layout/fraction_layout.h"
12 
13 namespace Poincare {
14 
15 // Constructors
16 
17 Rational::Rational(const Integer numerator, const Integer denominator) {
19  if (numerator.isOne() || denominator.isOne()) {
20  // Avoid computing GCD if possible
21  m_numerator = numerator;
22  m_denominator = denominator;
23  } else {
25  m_numerator = Integer::Division(numerator, gcd).quotient;
26  m_denominator = Integer::Division(denominator, gcd).quotient;
27  }
28  if (m_numerator.isNegative() && m_denominator.isNegative()) {
29  m_numerator.setNegative(false);
30  m_denominator.setNegative(false);
31  } else if (m_denominator.isNegative()) {
32  m_numerator.setNegative(true);
33  m_denominator.setNegative(false);
34  }
35 }
36 
37 Rational::Rational(const Integer numerator) {
38  m_numerator = numerator;
39  m_denominator = Integer(1);
40 }
41 
42 Rational::Rational(const Rational & other) {
43  m_numerator = other.m_numerator;
44  m_denominator = other.m_denominator;
45 }
46 
48  m_numerator = other.m_numerator;
49  m_numerator = other.m_numerator;
50  m_denominator = other.m_denominator;
51  return *this;
52 }
53 
54 // Getter
56  return m_numerator;
57 }
58 
60  return m_denominator;
61 }
62 // Expression subclassing
63 
65  return Type::Rational;
66 }
67 
69  return new Rational(m_numerator, m_denominator);
70 }
71 
73  if (m_numerator.isNegative()) {
74  return Sign::Negative;
75  }
76  return Sign::Positive;
77 }
78 
79 Expression * Rational::setSign(Sign s) {
80  assert(s != Sign::Unknown);
81  bool negative = s == Sign::Negative ? true : false;
82  m_numerator.setNegative(negative);
83  return this;
84 }
85 
86 Expression * Rational::shallowBeautify(Context & context, AngleUnit angleUnit) {
87  if (m_numerator.isNegative()) {
88  m_numerator.setNegative(false);
89  Opposite * o = new Opposite(this, true);
90  return replaceWith(o, true);
91  }
92  return this;
93 }
94 
95 Expression * Rational::cloneDenominator(Context & context, AngleUnit angleUnit) const {
96  if (m_denominator.isOne()) {
97  return nullptr;
98  }
99  return new Rational(m_denominator);
100 }
101 
102 // Basic operations
103 
106  Integer newDenominator = Integer::Multiplication(i.denominator(), j.denominator());
107  return Rational(newNumerator, newDenominator);
108 }
109 
111  Integer newNumerator = Integer::Multiplication(i.numerator(), j.numerator());
112  Integer newDenominator = Integer::Multiplication(i.denominator(), j.denominator());
113  return Rational(newNumerator, newDenominator);
114 }
115 
116 Rational Rational::Power(const Rational & i, const Integer & j) {
117  Integer absJ = j;
118  absJ.setNegative(false);
119  Integer newNumerator = Integer::Power(i.numerator(), absJ);
120  Integer newDenominator = Integer::Power(i.denominator(), absJ);
121  if (j.isNegative()) {
122  return Rational(newDenominator, newNumerator);
123  }
124  return Rational(newNumerator, newDenominator);
125 }
126 
127 int Rational::NaturalOrder(const Rational & i, const Rational & j) {
130  return Integer::NaturalOrder(i1, i2);
131 }
132 
133 // Comparison
134 
135 int Rational::simplificationOrderSameType(const Expression * e, bool canBeInterrupted) const {
137  const Rational * other = static_cast<const Rational *>(e);
138  return NaturalOrder(*this, *other);
139 }
140 
141 template<typename T> Complex<T> * Rational::templatedApproximate(Context& context, Expression::AngleUnit angleUnit) const {
142  T n = m_numerator.approximate<T>();
143  T d = m_denominator.approximate<T>();
144  return new Complex<T>(Complex<T>::Float(n/d));
145 }
146 
147 bool Rational::needParenthesisWithParent(const Expression * e) const {
148  if (m_denominator.isOne()) {
149  return false;
150  }
152  return e->isOfType(types, 3);
153 }
154 
155 ExpressionLayout * Rational::privateCreateLayout(PrintFloat::Mode floatDisplayMode, ComplexFormat complexFormat) const {
156  ExpressionLayout * numeratorLayout = m_numerator.createLayout();
157  if (m_denominator.isOne()) {
158  return numeratorLayout;
159  }
160  ExpressionLayout * denominatorLayout = m_denominator.createLayout();
161  return new FractionLayout(numeratorLayout, denominatorLayout);
162 }
163 
164 int Rational::writeTextInBuffer(char * buffer, int bufferSize, int numberOfSignificantDigits) const {
165  buffer[bufferSize-1] = 0;
166  int numberOfChar = m_numerator.writeTextInBuffer(buffer, bufferSize);
167  if (m_denominator.isOne()) {
168  return numberOfChar;
169  }
170  if (numberOfChar >= bufferSize-1) {
171  return numberOfChar;
172  }
173  buffer[numberOfChar++] = '/';
174  numberOfChar += m_denominator.writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar);
175  return numberOfChar;
176 }
177 
178 }
179 
T approximate() const
Definition: integer.cpp:479
static Integer Power(const Integer &i, const Integer &j)
Definition: integer.cpp:313
bool isZero() const
Definition: integer.h:72
#define assert(e)
Definition: assert.h:9
int writeTextInBuffer(char *buffer, int bufferSize) const
Definition: integer.cpp:545
friend class Multiplication
Definition: rational.h:12
Expression * replaceWith(Expression *newOperand, bool deleteAfterReplace=true)
Definition: expression.cpp:85
#define T(x)
Definition: events.cpp:26
static Rational Addition(const Rational &i, const Rational &j)
Definition: rational.cpp:104
static Integer GCD(const Integer *i, const Integer *j)
Definition: arithmetic.cpp:15
Rational(const Integer numerator, const Integer denominator)
Definition: rational.cpp:17
Rational & operator=(const Rational &other)
Definition: rational.cpp:47
const Integer denominator() const
Definition: rational.cpp:59
Sign sign() const override
Definition: rational.cpp:72
Type type() const override
Definition: rational.cpp:64
void setNegative(bool negative)
Definition: integer.cpp:203
static int NaturalOrder(const Rational &i, const Rational &j)
Definition: rational.cpp:127
friend class Opposite
Definition: expression.h:62
static Integer Addition(const Integer &i, const Integer &j)
Definition: integer.cpp:232
bool isNegative() const
Definition: integer.h:43
const Integer numerator() const
Definition: rational.cpp:55
static int NaturalOrder(const Integer &i, const Integer &j)
Definition: integer.cpp:212
bool isOne() const
Definition: integer.h:68
static Complex< T > Float(T x)
Definition: complex.cpp:23
Expression * cloneDenominator(Context &context, AngleUnit angleUnit) const override
Definition: rational.cpp:95
ExpressionLayout * createLayout() const
Definition: integer.cpp:590
Expression * clone() const override
Definition: rational.cpp:68
friend class Power
Definition: rational.h:11
static Integer Multiplication(const Integer &i, const Integer &j)
Definition: integer.cpp:240
static IntegerDivision Division(const Integer &numerator, const Integer &denominator)
Definition: integer.cpp:281
virtual Type type() const =0
#define true
Definition: stdbool.h:8