/*=============================================================================
This file is part of Antic.
Antic is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See .
=============================================================================*/
/******************************************************************************
Copyright 2012 William Hart
******************************************************************************/
#include
#include
#include "profiler.h"
#include "flint.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();
}
/* find prime such that n is a square mod p (or p divides n) */
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) /* pr is a factor */
{
printf("Factor: %lu\n", pr);
return 0;
}
} while (n_jacobi(nmodpr, pr) < 0);
fmpz_set_ui(p, pr);
/* find prime form of discriminant n */
qfb_prime_form(pow, n, p);
/* raise to various powers of small primes */
qfb_pow_ui(pow, pow, n, 59049); /* 3^10 */
qfb_pow_ui(twopow, pow, n, 4096);
if (qfb_is_principal_form(twopow, n))
goto done;
qfb_pow_ui(pow, pow, n, 390625); /* 5^8 */
qfb_pow_ui(twopow, pow, n, 4096);
if (qfb_is_principal_form(twopow, n))
goto done;
qfb_pow_ui(pow, pow, n, 117649); /* 7^6 */
qfb_pow_ui(twopow, pow, n, 4096);
if (qfb_is_principal_form(twopow, n))
goto done;
qfb_pow_ui(pow, pow, n, 14641); /* 11^4 */
qfb_pow_ui(twopow, pow, n, 4096);
if (qfb_is_principal_form(twopow, n))
goto done;
qfb_pow_ui(pow, pow, n, 169); /* 13^2 */
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;
}