Numworks Epsilon  1.4.1
Graphing Calculator Operating System
permute_coefficient.cpp
Go to the documentation of this file.
2 #include <poincare/undefined.h>
3 #include <poincare/rational.h>
4 
5 extern "C" {
6 #include <assert.h>
7 }
8 #include <cmath>
9 
10 namespace Poincare {
11 
14 }
15 
18  return b;
19 }
20 
21 Expression * PermuteCoefficient::shallowReduce(Context& context, AngleUnit angleUnit) {
22  Expression * e = Expression::shallowReduce(context, angleUnit);
23  if (e != this) {
24  return e;
25  }
26  Expression * op0 = editableOperand(0);
27  Expression * op1 = editableOperand(1);
28 #if MATRIX_EXACT_REDUCING
29  if (op0->type() == Type::Matrix || op1->type() == Type::Matrix) {
30  return replaceWith(new Undefined(), true);
31  }
32 #endif
33  if (op0->type() == Type::Rational) {
34  Rational * r0 = static_cast<Rational *>(op0);
35  if (!r0->denominator().isOne() || r0->numerator().isNegative()) {
36  return replaceWith(new Undefined(), true);
37  }
38  }
39  if (op1->type() == Type::Rational) {
40  Rational * r1 = static_cast<Rational *>(op1);
41  if (!r1->denominator().isOne() || r1->numerator().isNegative()) {
42  return replaceWith(new Undefined(), true);
43  }
44  }
45  if (op0->type() != Type::Rational || op1->type() != Type::Rational) {
46  return this;
47  }
48  Rational * r0 = static_cast<Rational *>(op0);
49  Rational * r1 = static_cast<Rational *>(op1);
50 
51  Integer n = r0->numerator();
52  Integer k = r1->numerator();
53  if (n.isLowerThan(k)) {
54  return replaceWith(new Rational(0), true);
55  }
56  /* if n is too big, we do not reduce to avoid too long computation.
57  * The permute coefficient will be evaluate approximatively later */
58  if (Integer(k_maxNValue).isLowerThan(n)) {
59  return this;
60  }
61  Integer result(1);
62  int clippedK = k.extractedInt(); // Authorized because k < n < k_maxNValue
63  for (int i = 0; i < clippedK; i++) {
64  Integer factor = Integer::Subtraction(n, Integer(i));
65  result = Integer::Multiplication(result, factor);
66  }
67  return replaceWith(new Rational(result), true);
68 }
69 
70 template<typename T>
71 Complex<T> * PermuteCoefficient::templatedApproximate(Context& context, AngleUnit angleUnit) const {
72  Expression * nInput = operand(0)->approximate<T>(context, angleUnit);
73  Expression * kInput = operand(1)->approximate<T>(context, angleUnit);
74  if (nInput->type() != Type::Complex || kInput->type() != Type::Complex) {
75  return new Complex<T>(Complex<T>::Float(NAN));
76  }
77  T n = static_cast<Complex<T> *>(nInput)->toScalar();
78  T k = static_cast<Complex<T> *>(kInput)->toScalar();
79  delete nInput;
80  delete kInput;
81  if (std::isnan(n) || std::isnan(k) || n != std::round(n) || k != std::round(k) || n < 0.0f || k < 0.0f) {
82  return new Complex<T>(Complex<T>::Float(NAN));
83  }
84  if (k > n) {
85  return new Complex<T>(Complex<T>::Float(0));
86  }
87  T result = 1;
88  for (int i = (int)n-(int)k+1; i <= (int)n; i++) {
89  result *= i;
90  if (std::isinf(result) || std::isnan(result)) {
91  return new Complex<T>(Complex<T>::Float(result));
92  }
93  }
94  return new Complex<T>(Complex<T>::Float(std::round(result)));
95 }
96 
97 }
98 
friend class PermuteCoefficient
Definition: expression.h:64
#define NAN
Definition: math.h:30
#define isinf(x)
Definition: math.h:44
Expression * replaceWith(Expression *newOperand, bool deleteAfterReplace=true)
Definition: expression.cpp:85
Expression * approximate(Context &context, AngleUnit angleUnit=AngleUnit::Default) const
Definition: expression.cpp:338
Expression * clone() const override
#define T(x)
Definition: events.cpp:26
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]
#define isnan(x)
Definition: math.h:43
static Complex< T > Float(T x)
Definition: complex.cpp:23
static Integer Subtraction(const Integer &i, const Integer &j)
Definition: integer.cpp:236
static Integer Multiplication(const Integer &i, const Integer &j)
Definition: integer.cpp:240
const Expression * operand(int i) const
Definition: expression.cpp:78
friend class Undefined
Definition: expression.h:17