#include <stdlib.h>
#include "profiler.h"
#include "ulong_extras.h"
#include "fmpz.h"
#include "qfb.h"
int main(void)
{
fmpz_t n, p;
slong iters, i, j;
qfb_t pow, oldpow, twopow;
ulong pr, oldpr, nmodpr;
int done = 1;
fmpz_init(n);
fmpz_init(p);
qfb_init(pow);
qfb_init(oldpow);
qfb_init(twopow);
printf("Enter number to be factored: "); fflush(stdout);
if (!fmpz_read(n))
{
printf("Read failed\n");
abort();
}
fmpz_neg(n, n);
printf("Enter a number of iterations: "); fflush(stdout);
if (!scanf("%ld", &iters))
{
printf("Read failed\n");
abort();
}
if (fmpz_is_even(n))
{
printf("Factor: 2\n");
return 0;
}
pr = 2;
if (fmpz_fdiv_ui(n, 4) == 3)
{
if (fmpz_fdiv_ui(n, 3) == 0)
{
printf("Factor: 3\n");
return 0;
}
fmpz_mul_ui(n, n, 3);
pr = 3;
}
do
{
pr = n_nextprime(pr, 0);
nmodpr = fmpz_fdiv_ui(n, pr);
if (nmodpr == 0)
{
printf("Factor: %lu\n", pr);
return 0;
}
} while (n_jacobi(nmodpr, pr) < 0);
fmpz_set_ui(p, pr);
qfb_prime_form(pow, n, p);
qfb_pow_ui(pow, pow, n, 59049);
qfb_pow_ui(twopow, pow, n, 4096);
if (qfb_is_principal_form(twopow, n))
goto done;
qfb_pow_ui(pow, pow, n, 390625);
qfb_pow_ui(twopow, pow, n, 4096);
if (qfb_is_principal_form(twopow, n))
goto done;
qfb_pow_ui(pow, pow, n, 117649);
qfb_pow_ui(twopow, pow, n, 4096);
if (qfb_is_principal_form(twopow, n))
goto done;
qfb_pow_ui(pow, pow, n, 14641);
qfb_pow_ui(twopow, pow, n, 4096);
if (qfb_is_principal_form(twopow, n))
goto done;
qfb_pow_ui(pow, pow, n, 169);
qfb_pow_ui(twopow, pow, n, 4096);
if (qfb_is_principal_form(twopow, n))
goto done;
pr = 13;
for (i = 0; i < iters; )
{
j = FLINT_MIN(i + 1024, iters);
qfb_set(oldpow, pow);
oldpr = pr;
for ( ; i < j; i++)
{
pr = n_nextprime(pr, 0);
qfb_pow_ui(pow, pow, n, pr*pr);
}
qfb_pow_ui(twopow, pow, n, 4096);
if (qfb_is_principal_form(twopow, n))
{
qfb_set(pow, oldpow);
pr = oldpr;
while (1)
{
pr = n_nextprime(pr, 0);
qfb_pow_ui(pow, pow, n, pr*pr);
qfb_pow_ui(twopow, pow, n, 4096);
if (qfb_is_principal_form(twopow, n))
goto done;
}
}
}
if (i == iters)
done = 0;
done:
if (done)
{
for (i = 0; i < 12; i++)
{
qfb_pow_ui(twopow, pow, n, 2);
if (qfb_is_principal_form(twopow, n))
{
qfb_print(pow); printf("\n");
return 0;
}
qfb_set(pow, twopow);
}
} else
printf("Failed\n");
qfb_clear(pow);
qfb_clear(oldpow);
qfb_clear(twopow);
fmpz_clear(n);
fmpz_clear(p);
return 0;
}