2007-11-18 02:08:12 +01:00
|
|
|
// factor a polynomial or integer
|
|
|
|
|
2004-03-03 21:24:06 +01:00
|
|
|
#include "stdafx.h"
|
|
|
|
#include "defs.h"
|
|
|
|
|
|
|
|
void
|
|
|
|
eval_factor(void)
|
|
|
|
{
|
2006-11-22 03:42:38 +01:00
|
|
|
push(cadr(p1));
|
2004-03-03 21:24:06 +01:00
|
|
|
eval();
|
2007-11-18 02:08:12 +01:00
|
|
|
|
2006-11-22 03:42:38 +01:00
|
|
|
push(caddr(p1));
|
|
|
|
eval();
|
2007-11-18 02:08:12 +01:00
|
|
|
|
|
|
|
p2 = pop();
|
|
|
|
if (p2 == symbol(NIL))
|
2006-11-22 03:42:38 +01:00
|
|
|
guess();
|
|
|
|
else
|
2007-11-18 02:08:12 +01:00
|
|
|
push(p2);
|
|
|
|
|
2006-11-22 03:42:38 +01:00
|
|
|
factor();
|
2007-11-18 02:08:12 +01:00
|
|
|
|
|
|
|
// more factoring?
|
|
|
|
|
|
|
|
p1 = cdddr(p1);
|
|
|
|
while (iscons(p1)) {
|
|
|
|
push(car(p1));
|
|
|
|
eval();
|
|
|
|
factor_again();
|
|
|
|
p1 = cdr(p1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
factor_again(void)
|
|
|
|
{
|
|
|
|
int h, n;
|
|
|
|
|
|
|
|
save();
|
|
|
|
|
|
|
|
p2 = pop();
|
|
|
|
p1 = pop();
|
|
|
|
|
|
|
|
h = tos;
|
|
|
|
|
|
|
|
if (car(p1) == symbol(MULTIPLY)) {
|
|
|
|
p1 = cdr(p1);
|
|
|
|
while (iscons(p1)) {
|
|
|
|
push(car(p1));
|
|
|
|
push(p2);
|
|
|
|
factor_term();
|
|
|
|
p1 = cdr(p1);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
push(p1);
|
|
|
|
push(p2);
|
|
|
|
factor_term();
|
|
|
|
}
|
|
|
|
|
|
|
|
n = tos - h;
|
|
|
|
|
|
|
|
if (n > 1)
|
|
|
|
multiply_all_noexpand(n);
|
|
|
|
|
|
|
|
restore();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
factor_term(void)
|
|
|
|
{
|
|
|
|
save();
|
|
|
|
factorpoly();
|
|
|
|
p1 = pop();
|
|
|
|
if (car(p1) == symbol(MULTIPLY)) {
|
|
|
|
p1 = cdr(p1);
|
|
|
|
while (iscons(p1)) {
|
|
|
|
push(car(p1));
|
|
|
|
p1 = cdr(p1);
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
push(p1);
|
|
|
|
restore();
|
2006-09-20 18:46:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
factor(void)
|
|
|
|
{
|
|
|
|
save();
|
|
|
|
p2 = pop();
|
|
|
|
p1 = pop();
|
|
|
|
if (isinteger(p1)) {
|
|
|
|
push(p1);
|
2004-03-03 21:24:06 +01:00
|
|
|
factor_number(); // see pollard.cpp
|
2006-09-20 18:46:38 +02:00
|
|
|
} else {
|
|
|
|
push(p1);
|
|
|
|
push(p2);
|
2004-03-03 21:24:06 +01:00
|
|
|
factorpoly();
|
|
|
|
}
|
2006-09-20 18:46:38 +02:00
|
|
|
restore();
|
2004-03-03 21:24:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// for factoring small integers (2^32 or less)
|
|
|
|
|
|
|
|
void
|
|
|
|
factor_small_number(void)
|
|
|
|
{
|
|
|
|
int d, expo, i, n;
|
|
|
|
|
|
|
|
save();
|
|
|
|
|
|
|
|
n = pop_integer();
|
|
|
|
|
|
|
|
if (n == (int) 0x80000000)
|
|
|
|
stop("number too big to factor");
|
|
|
|
|
|
|
|
if (n < 0)
|
|
|
|
n = -n;
|
|
|
|
|
|
|
|
for (i = 0; i < MAXPRIMETAB; i++) {
|
|
|
|
|
|
|
|
d = primetab[i];
|
|
|
|
|
|
|
|
if (d > n / d)
|
|
|
|
break;
|
|
|
|
|
|
|
|
expo = 0;
|
|
|
|
|
|
|
|
while (n % d == 0) {
|
|
|
|
n /= d;
|
|
|
|
expo++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (expo) {
|
|
|
|
push_integer(d);
|
|
|
|
push_integer(expo);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (n > 1) {
|
|
|
|
push_integer(n);
|
|
|
|
push_integer(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
restore();
|
|
|
|
}
|
|
|
|
|
2007-05-08 16:57:30 +02:00
|
|
|
#if SELFTEST
|
|
|
|
|
2004-03-03 21:24:06 +01:00
|
|
|
static char *s[] = {
|
|
|
|
|
|
|
|
"factor(0)",
|
|
|
|
"0",
|
|
|
|
|
|
|
|
"factor(1)",
|
|
|
|
"1",
|
|
|
|
|
|
|
|
"factor(2)",
|
|
|
|
"2",
|
|
|
|
|
|
|
|
"factor(3)",
|
|
|
|
"3",
|
|
|
|
|
|
|
|
"factor(4)",
|
|
|
|
"2^2",
|
|
|
|
|
|
|
|
"factor(5)",
|
|
|
|
"5",
|
|
|
|
|
|
|
|
"factor(6)",
|
|
|
|
"2*3",
|
|
|
|
|
|
|
|
"factor(7)",
|
|
|
|
"7",
|
|
|
|
|
|
|
|
"factor(8)",
|
|
|
|
"2^3",
|
|
|
|
|
|
|
|
"factor(9)",
|
|
|
|
"3^2",
|
|
|
|
|
|
|
|
"factor(10)",
|
|
|
|
"2*5",
|
|
|
|
|
|
|
|
"factor(100!)",
|
|
|
|
"2^97*3^48*5^24*7^16*11^9*13^7*17^5*19^5*23^4*29^3*31^3*37^2*41^2*43^2*47^2*53*59*61*67*71*73*79*83*89*97",
|
|
|
|
|
|
|
|
"factor(2*(2^30-35))",
|
|
|
|
"2*1073741789",
|
|
|
|
|
|
|
|
// x is the 10,000th prime
|
|
|
|
|
|
|
|
// Prime factors greater than x^2 are found using the Pollard rho method
|
|
|
|
|
2007-11-18 02:08:12 +01:00
|
|
|
"a=104729",
|
2004-03-03 21:24:06 +01:00
|
|
|
"",
|
|
|
|
|
2007-11-18 02:08:12 +01:00
|
|
|
"factor(2*(a^2+6))",
|
2004-03-03 21:24:06 +01:00
|
|
|
"2*10968163447",
|
|
|
|
|
2007-11-18 02:08:12 +01:00
|
|
|
"factor((a^2+6)^2)",
|
2004-03-03 21:24:06 +01:00
|
|
|
"10968163447*10968163447", // FIXME should be 10968163447^2
|
|
|
|
|
2007-11-18 02:08:12 +01:00
|
|
|
"factor((a^2+6)*(a^2+60))",
|
2004-03-03 21:24:06 +01:00
|
|
|
"10968163501*10968163447", // FIXME sort order
|
|
|
|
|
2007-11-18 02:08:12 +01:00
|
|
|
"f=(x+1)(x+2)(y+3)(y+4)",
|
2004-03-03 21:24:06 +01:00
|
|
|
"",
|
2007-11-18 02:08:12 +01:00
|
|
|
|
|
|
|
"factor(f,x,y)",
|
|
|
|
"(x+1)*(x+2)*(y+3)*(y+4)",
|
|
|
|
|
|
|
|
"factor(f,y,x)",
|
|
|
|
"(x+1)*(x+2)*(y+3)*(y+4)",
|
|
|
|
|
|
|
|
"f=(x+1)(x+1)(y+2)(y+2)",
|
|
|
|
"",
|
|
|
|
|
|
|
|
"factor(f,x,y)",
|
|
|
|
"(x+1)^2*(y+2)^2",
|
|
|
|
|
|
|
|
"factor(f,y,x)",
|
|
|
|
"(x+1)^2*(y+2)^2",
|
2004-03-03 21:24:06 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
void
|
|
|
|
test_factor_number(void)
|
|
|
|
{
|
|
|
|
test(__FILE__, s, sizeof s / sizeof (char *));
|
|
|
|
}
|
2007-05-08 16:57:30 +02:00
|
|
|
|
|
|
|
#endif
|