Numworks Epsilon  1.4.1
Graphing Calculator Operating System
round.cpp
Go to the documentation of this file.
1 #include <poincare/round.h>
2 #include <poincare/undefined.h>
3 #include <poincare/rational.h>
4 #include <poincare/power.h>
5 
6 extern "C" {
7 #include <assert.h>
8 }
9 #include <cmath>
10 
11 namespace Poincare {
12 
14  return Type::Round;
15 }
16 
18  Round * c = new Round(m_operands, true);
19  return c;
20 }
21 
22 Expression * Round::shallowReduce(Context& context, AngleUnit angleUnit) {
23  Expression * e = Expression::shallowReduce(context, angleUnit);
24  if (e != this) {
25  return e;
26  }
27 #if MATRIX_EXACT_REDUCING
28  if (operand(0)->type() == Type::Matrix || operand(1)->type() == Type::Matrix) {
29  return replaceWith(new Undefined(), true);
30  }
31 #endif
32  if (operand(0)->type() == Type::Rational && operand(1)->type() == Type::Rational) {
33  Rational * r1 = static_cast<Rational *>(editableOperand(0));
34  Rational * r2 = static_cast<Rational *>(editableOperand(1));
35  if (!r2->denominator().isOne()) {
36  return replaceWith(new Undefined(), true);
37  }
38  if (Power::RationalExponentShouldNotBeReduced(r2)) {
39  return this;
40  }
41  Rational err = Rational::Power(Rational(10), r2->numerator());
42  Rational mult = Rational::Multiplication(*r1, Rational(err));
43  IntegerDivision d = Integer::Division(mult.numerator(), mult.denominator());
44  Integer rounding = d.quotient;
45  if (Rational::NaturalOrder(Rational(d.remainder, mult.denominator()), Rational(1,2)) >= 0) {
46  rounding = Integer::Addition(rounding, Integer(1));
47  }
48  Rational result = Rational::Multiplication(rounding, Rational::Power(Rational(1,10), r2->numerator()));
49  return replaceWith(new Rational(result), true);
50  }
51  return this; // TODO: implement for rationals!
52 }
53 
54 template<typename T>
55 Complex<T> * Round::templatedApproximate(Context& context, AngleUnit angleUnit) const {
56  Expression * f1Input = operand(0)->approximate<T>(context, angleUnit);
57  Expression * f2Input = operand(1)->approximate<T>(context, angleUnit);
58  T f1 = f1Input->type() == Type::Complex ? static_cast<Complex<T> *>(f1Input)->toScalar() : NAN;
59  T f2 = f2Input->type() == Type::Complex ? static_cast<Complex<T> *>(f2Input)->toScalar() : NAN;
60  delete f1Input;
61  delete f2Input;
62  if (std::isnan(f2) || f2 != std::round(f2)) {
63  return new Complex<T>(Complex<T>::Float(NAN));
64  }
65  T err = std::pow(10, std::floor(f2));
66  return new Complex<T>(Complex<T>::Float(std::round(f1*err)/err));
67 }
68 
69 }
70 
71 
#define NAN
Definition: math.h:30
friend class Multiplication
Definition: rational.h:12
Expression * replaceWith(Expression *newOperand, bool deleteAfterReplace=true)
Definition: expression.cpp:85
Expression * approximate(Context &context, AngleUnit angleUnit=AngleUnit::Default) const
Definition: expression.cpp:338
#define T(x)
Definition: events.cpp:26
c(generic_all_nodes)
Expression * editableOperand(int i)
Definition: expression.h:176
friend class Rational
Definition: expression.h:18
Type type() const override
Definition: round.cpp:13
#define round(x)
Definition: math.h:192
static int NaturalOrder(const Rational &i, const Rational &j)
Definition: rational.cpp:127
#define pow(x, y)
Definition: math.h:190
static Integer Addition(const Integer &i, const Integer &j)
Definition: integer.cpp:232
const Expression * m_operands[T]
#define isnan(x)
Definition: math.h:43
static Complex< T > Float(T x)
Definition: complex.cpp:23
friend class Round
Definition: expression.h:68
friend class Power
Definition: rational.h:11
#define floor(x)
Definition: math.h:179
const Expression * operand(int i) const
Definition: expression.cpp:78
static IntegerDivision Division(const Integer &numerator, const Integer &denominator)
Definition: integer.cpp:281
Expression * clone() const override
Definition: round.cpp:17
friend class Undefined
Definition: expression.h:17