mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-27 17:50:04 +01:00
[poincare] Arithmetic
This commit is contained in:
@@ -4,6 +4,7 @@ SFLAGS += -Ipoincare/include
|
||||
#include poincare/src/simplification/Makefile
|
||||
objs += $(addprefix poincare/src/,\
|
||||
addition.o\
|
||||
arithmetic.o\
|
||||
matrix_complex.o\
|
||||
multiplication.o\
|
||||
power.o\
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define POINCARE_ARITHMETIC_H
|
||||
|
||||
#include <poincare/integer.h>
|
||||
|
||||
namespace Poincare {
|
||||
|
||||
class Arithmetic {
|
||||
|
||||
@@ -18,6 +18,7 @@ public:
|
||||
TreeByValue& operator=(const TreeByValue& tr);
|
||||
|
||||
bool isDefined() const { return TreeByReference::isDefined(); }
|
||||
bool isAllocationFailure() const { return TreeByReference::isAllocationFailure(); }
|
||||
|
||||
TreeNode * node() const override { return TreeByReference::node(); }
|
||||
|
||||
|
||||
@@ -3,24 +3,19 @@
|
||||
|
||||
namespace Poincare {
|
||||
|
||||
IntegerReference Arithmetic::LCM(const IntegerReference a, const IntegerReference b) {
|
||||
if (a.isAllocationFailure() || b.isAllocationFailure()) {
|
||||
return IntegerReference(ExpressionNode::FailedAllocationStaticNode());
|
||||
}
|
||||
Integer Arithmetic::LCM(const Integer a, const Integer b) {
|
||||
if (a.isZero() || b.isZero()) {
|
||||
return IntegerReference(0);
|
||||
return Integer(0);
|
||||
}
|
||||
IntegerReference signResult = IntegerReference::Division(IntegerReference::Multiplication(a, b), GCD(a,b)).quotient;
|
||||
Integer signResult = Integer::Division(Integer::Multiplication(a, b), GCD(a,b)).quotient;
|
||||
signResult.setNegative(false);
|
||||
return signResult;
|
||||
}
|
||||
|
||||
IntegerReference Arithmetic::GCD(const IntegerReference a, const IntegerReference b) {
|
||||
if (a.isAllocationFailure() || b.isAllocationFailure()) {
|
||||
return IntegerReference(ExpressionNode::FailedAllocationStaticNode());
|
||||
}
|
||||
IntegerReference i = IntegerReference(a.clone().node());
|
||||
IntegerReference j = IntegerReference(b.clone().node());
|
||||
Integer Arithmetic::GCD(const Integer a, const Integer b) {
|
||||
|
||||
Integer i = a;
|
||||
Integer j = b;
|
||||
i.setNegative(false);
|
||||
j.setNegative(false);
|
||||
do {
|
||||
@@ -30,10 +25,10 @@ IntegerReference Arithmetic::GCD(const IntegerReference a, const IntegerReferenc
|
||||
if (j.isZero()) {
|
||||
return i;
|
||||
}
|
||||
if (IntegerReference::NaturalOrder(i, j) > 0) {
|
||||
i = IntegerReference::Division(i, j).remainder;
|
||||
if (Integer::NaturalOrder(i, j) > 0) {
|
||||
i = Integer::Division(i, j).remainder;
|
||||
} else {
|
||||
j = IntegerReference::Division(j, i).remainder;
|
||||
j = Integer::Division(j, i).remainder;
|
||||
}
|
||||
} while(true);
|
||||
}
|
||||
@@ -42,51 +37,49 @@ int primeFactors[Arithmetic::k_numberOfPrimeFactors] = {2, 3, 5, 7, 11, 13, 17,
|
||||
3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, 3823, 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989, 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, 4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177, 4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297, 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, 4421, 4423, 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547, 4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, 4933, 4937, 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003, 5009, 5011, 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, 5099, 5101, 5107, 5113, 5119, 5147, 5153, 5167, 5171, 5179, 5189, 5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279, 5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387, 5393, 5399, 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443, 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, 5519, 5521, 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639, 5641, 5647, 5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693, 5701, 5711, 5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791, 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857, 5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939, 5953, 5981, 5987, 6007, 6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073, 6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133, 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221, 6229, 6247, 6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329, 6337, 6343, 6353, 6359, 6361, 6367, 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473, 6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571, 6577, 6581, 6599, 6607, 6619, 6637, 6653, 6659, 6661, 6673, 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, 6737, 6761, 6763, 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833, 6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917, 6947, 6949, 6959, 6961, 6967, 6971, 6977, 6983, 6991, 6997, 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103, 7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, 7211, 7213, 7219, 7229, 7237, 7243, 7247, 7253, 7283, 7297, 7307, 7309, 7321, 7331, 7333, 7349, 7351, 7369, 7393, 7411, 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499, 7507, 7517, 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, 7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621, 7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723, 7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829, 7841, 7853, 7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919};
|
||||
|
||||
// we can go to 7907*7907 = 62 520 649
|
||||
void Arithmetic::PrimeFactorization(const IntegerReference n, IntegerReference outputFactors[], IntegerReference outputCoefficients[], int outputLength) {
|
||||
void Arithmetic::PrimeFactorization(const Integer n, Integer outputFactors[], Integer outputCoefficients[], int outputLength) {
|
||||
if (n.isAllocationFailure()) {
|
||||
/* Special case 0: Allocation failure. */
|
||||
outputCoefficients[0] = -1;
|
||||
return;
|
||||
}
|
||||
// To avoid cloning n to get its absolute value m, we change n sign and reset it before returning
|
||||
bool nIsNegative = n.isNegative();
|
||||
IntegerReference m = *(const_cast<IntegerReference *>(&n));
|
||||
|
||||
// Compute the absolute value of n
|
||||
Integer m = n;
|
||||
m.setNegative(false);
|
||||
|
||||
/* First we look for prime divisors in the table primeFactors (to speed up
|
||||
* the prime factorization for low numbers). When k_numberOfPrimeFactors is
|
||||
* overflow, try every number as divisor. */
|
||||
if (IntegerReference::NaturalOrder(m, IntegerReference(1))) {
|
||||
m.setNegative(nIsNegative);
|
||||
if (Integer::NaturalOrder(m, Integer(1)) == 0) {
|
||||
return;
|
||||
}
|
||||
const IntegerReference primorial32("525896479052627740771371797072411912900610967452630", false);
|
||||
if (IntegerReference::NaturalOrder(primorial32, m) < 0) {
|
||||
const char * primorial = "525896479052627740771371797072411912900610967452630";
|
||||
const Integer primorial32(primorial, strlen(primorial), false);
|
||||
if (Integer::NaturalOrder(primorial32, m) < 0) {
|
||||
/* Special case 1: We do not want to break i in prime factor because it
|
||||
* might take too many factors... More than k_maxNumberOfPrimeFactors.
|
||||
* outputCoefficients[0] is set to -1 to indicate a special case. */
|
||||
outputCoefficients[0] = -1;
|
||||
m.setNegative(nIsNegative);
|
||||
return;
|
||||
}
|
||||
for (int index = 0; index < outputLength; index++) {
|
||||
outputCoefficients[index] = IntegerReference(0);
|
||||
outputCoefficients[index] = Integer(0);
|
||||
}
|
||||
|
||||
int t = 0; // n prime factor index
|
||||
int k = 0; // prime factor index
|
||||
IntegerReference testedPrimeFactor(primeFactors[k]); // prime factor
|
||||
Integer testedPrimeFactor(primeFactors[k]); // prime factor
|
||||
outputFactors[t] = testedPrimeFactor;
|
||||
IntegerDivisionReference d = {.quotient = 0, .remainder = 0};
|
||||
IntegerDivision d = {.quotient = 0, .remainder = 0};
|
||||
bool stopCondition;
|
||||
do {
|
||||
stopCondition = IntegerReference::NaturalOrder(IntegerReference::Power(outputFactors[t], IntegerReference(2)), m) < 0;
|
||||
d = IntegerReference::Division(m, testedPrimeFactor);
|
||||
stopCondition = Integer::NaturalOrder(Integer::Power(outputFactors[t], Integer(2)), m) < 0;
|
||||
d = Integer::Division(m, testedPrimeFactor);
|
||||
if (d.remainder.isZero()) {
|
||||
outputCoefficients[t] = IntegerReference::Addition(outputCoefficients[t], IntegerReference(1));
|
||||
outputCoefficients[t] = Integer::Addition(outputCoefficients[t], Integer(1));
|
||||
m = d.quotient;
|
||||
if (m.isOne()) {
|
||||
m.setNegative(nIsNegative);
|
||||
return;
|
||||
}
|
||||
continue;
|
||||
@@ -95,21 +88,19 @@ void Arithmetic::PrimeFactorization(const IntegerReference n, IntegerReference o
|
||||
t++;
|
||||
}
|
||||
k++;
|
||||
testedPrimeFactor = k < k_numberOfPrimeFactors ? IntegerReference(primeFactors[k]) : IntegerReference::Addition(testedPrimeFactor, IntegerReference(1));
|
||||
testedPrimeFactor = k < k_numberOfPrimeFactors ? Integer(primeFactors[k]) : Integer::Addition(testedPrimeFactor, Integer(1));
|
||||
outputFactors[t] = testedPrimeFactor;
|
||||
} while (stopCondition && IntegerReference::NaturalOrder(testedPrimeFactor,IntegerReference(k_biggestPrimeFactor)) < 0);
|
||||
if (IntegerReference::NaturalOrder(IntegerReference::Power(IntegerReference(k_biggestPrimeFactor), IntegerReference(2)), m) < 0) {
|
||||
} while (stopCondition && Integer::NaturalOrder(testedPrimeFactor,Integer(k_biggestPrimeFactor)) < 0);
|
||||
if (Integer::NaturalOrder(Integer::Power(Integer(k_biggestPrimeFactor), Integer(2)), m) < 0) {
|
||||
/* Special case 2: We do not want to break i in prime factor because it
|
||||
* take too much time: the prime factor that should be tested is above
|
||||
* k_biggestPrimeFactor.
|
||||
* outputCoefficients[0] is set to -1 to indicate a special case. */
|
||||
outputCoefficients[0] = -1;
|
||||
m.setNegative(nIsNegative);
|
||||
return;
|
||||
}
|
||||
outputFactors[t] = m;
|
||||
outputCoefficients[t] = IntegerReference::Addition(outputCoefficients[t], IntegerReference(1));
|
||||
m.setNegative(nIsNegative);
|
||||
outputCoefficients[t] = Integer::Addition(outputCoefficients[t], Integer(1));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -69,8 +69,8 @@ Expression Division::shallowReduce(Context & context, Preferences::AngleUnit ang
|
||||
return result;
|
||||
}
|
||||
Power p = Power(childAtIndex(1), Rational(-1));
|
||||
p = p.shallowReduce(context, angleUnit); // Imagine Division(2,1). p would be 1^(-1) which can be simplified
|
||||
Multiplication m = Multiplication(childAtIndex(0), p);
|
||||
Expression e = p.shallowReduce(context, angleUnit); // Imagine Division(2,1). p would be 1^(-1) which can be simplified
|
||||
Multiplication m = Multiplication(childAtIndex(0), e);
|
||||
return m.shallowReduce(context, angleUnit);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user