[poincare] Fix primeFactorization to factorize any number (no bound

anymore)

Change-Id: I389124fcca03843aadcae4a6d5db10188f14c194
This commit is contained in:
Émilie Feral
2017-10-09 12:03:15 +02:00
parent 63583eb972
commit a61470e84a
2 changed files with 18 additions and 8 deletions

View File

@@ -30,8 +30,9 @@ int primeFactors[Arithmetic::k_numberOfPrimeFactors] = {2, 3, 5, 7, 11, 13, 17,
// we can go to 7907*7907 = 62 520 649
void Arithmetic::PrimeFactorization(const Integer * n, Integer * outputFactors, Integer * outputCoefficients, int outputLength) {
// TODO: Find the prime factorization of any number. When k_numberOfPrimeFactors is overflow, try every number as divisor.
assert(n->isLowerThan(Integer(primeFactors[k_numberOfPrimeFactors-1]*primeFactors[k_numberOfPrimeFactors-1])));
/* 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. */
for (int index = 0; index < outputLength; index++) {
outputCoefficients[index] = Integer(0);
}
@@ -42,11 +43,12 @@ void Arithmetic::PrimeFactorization(const Integer * n, Integer * outputFactors,
}
int t = 0; // n prime factor index
int k = 0; // prime factor index
outputFactors[t] = Integer(primeFactors[k]);
Integer testedPrimeFactor = Integer(primeFactors[k]); // prime factor
outputFactors[t] = testedPrimeFactor;
IntegerDivision d = {.quotient = 0, .remainder = 0};
bool stopCondition;
do {
d = Integer::Division(m, Integer(primeFactors[k]));
d = Integer::Division(m, testedPrimeFactor);
stopCondition = outputFactors[t].isLowerThan(d.quotient); // We evaluate the condition here in case we move d.quotient in n
if (d.remainder.isEqualTo(Integer(0))) {
outputCoefficients[t] = Integer::Addition(outputCoefficients[t], Integer(1));
@@ -56,11 +58,12 @@ void Arithmetic::PrimeFactorization(const Integer * n, Integer * outputFactors,
}
continue;
}
k++;
if (!outputCoefficients[t].isEqualTo(Integer(0))) {
t++;
}
outputFactors[t] = Integer(primeFactors[k]);
k++;
testedPrimeFactor = k < k_numberOfPrimeFactors ? Integer(primeFactors[k]) : Integer::Addition(testedPrimeFactor, Integer(1));
outputFactors[t] = testedPrimeFactor;
} while (stopCondition);
outputFactors[t] = std::move(m);
outputCoefficients[t] = Integer::Addition(outputCoefficients[t], Integer(1));

View File

@@ -42,8 +42,12 @@ void assert_prime_factorization_equals_to(Integer a, int * factors, int * coeffi
if (outputCoefficients[index].isEqualTo(Integer(0))) {
break;
}
assert(outputFactors[index].identifier() == factors[index]); // Cheat: instead of comparing to integers, we compare only identifier as we know that prime factors and their coefficients will always be lower than 2^32.
assert(outputCoefficients[index].identifier() == coefficients[index]);
/* Cheat: instead of comparing to integers, we compare their approximations
* (the relation between integers and their approximation is a surjection,
* however different integers are really likely to have different
* approximations... */
assert(outputFactors[index].approximate<float>(context) == Integer(factors[index]).approximate<float>(context));
assert(outputCoefficients[index].approximate<float>(context) == Integer(coefficients[index]).approximate<float>(context));
}
}
@@ -62,4 +66,7 @@ QUIZ_CASE(poincare_arithmetic) {
int factors2[3] = {2,5, 7};
int coefficients2[3] = {2,4,2};
assert_prime_factorization_equals_to(Integer(122500), factors2, coefficients2, 3);
int factors3[8] = {3,7,11, 13, 19, 3607, 3803, 52579};
int coefficients3[8] = {4,2,2,2,2,2,2,2};
assert_prime_factorization_equals_to(Integer("15241578780673678515622620750190521"), factors3, coefficients3, 8);
}