/* Factoring with Pollard's rho method.
Copyright 1995 , 1997 - 2003 , 2005 , 2009 , 2012 , 2015 Free Software
Foundation , Inc .
This program is free software ; you can redistribute it and / or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation ; either version 3 of the License , or ( at your option ) any later
version .
This program is distributed in the hope that it will be useful , but WITHOUT ANY
WARRANTY ; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE . See the GNU General Public License for more details .
You should have received a copy of the GNU General Public License along with
this program. If not, see https://www.gnu.org/licenses/. */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include "gmp.h"
static unsigned char primes_diff[] = {
#define P(a,b,c) a,
#include "primes.h"
#undef P
};
#define PRIMES_PTAB_ENTRIES (
sizeof (primes_diff) /
sizeof (primes_diff[
0 ]))
int flag_verbose =
0 ;
/* Prove primality or run probabilistic tests. */
int flag_prove_primality =
1 ;
/* Number of Miller-Rabin tests to run when not proving primality. */
#define MR_REPS
25
struct factors
{
mpz_t *p;
unsigned long *e;
long nfactors;
};
void factor (mpz_t,
struct factors *);
void
factor_init (
struct factors *factors)
{
factors->p = malloc (
1 );
factors->e = malloc (
1 );
factors->nfactors =
0 ;
}
void
factor_clear (
struct factors *factors)
{
int i;
for (i =
0 ; i < factors->nfactors; i++)
mpz_clear (factors->p[i]);
free (factors->p);
free (factors->e);
}
void
factor_insert (
struct factors *factors, mpz_t prime)
{
long nfactors = factors->nfactors;
mpz_t *p = factors->p;
unsigned long *e = factors->e;
long i, j;
/* Locate position for insert new or increment e. */
for (i = nfactors -
1 ; i >=
0 ; i--)
{
if (mpz_cmp (p[i], prime) <=
0 )
break ;
}
if (i <
0 || mpz_cmp (p[i], prime) !=
0 )
{
p = realloc (p, (nfactors +
1 ) *
sizeof p[
0 ]);
e = realloc (e, (nfactors +
1 ) *
sizeof e[
0 ]);
mpz_init (p[nfactors]);
for (j = nfactors -
1 ; j > i; j--)
{
mpz_set (p[j +
1 ], p[j]);
e[j +
1 ] = e[j];
}
mpz_set (p[i +
1 ], prime);
e[i +
1 ] =
1 ;
factors->p = p;
factors->e = e;
factors->nfactors = nfactors +
1 ;
}
else
{
e[i] +=
1 ;
}
}
void
factor_insert_ui (
struct factors *factors,
unsigned long prime)
{
mpz_t pz;
mpz_init_set_ui (pz, prime);
factor_insert (factors, pz);
mpz_clear (pz);
}
void
factor_using_division (mpz_t t,
struct factors *factors)
{
mpz_t q;
unsigned long int p;
int i;
if (flag_verbose >
0 )
{
printf (
"[trial division] " );
}
mpz_init (q);
p = mpz_scan1 (t,
0 );
mpz_fdiv_q_2exp (t, t, p);
while (p)
{
factor_insert_ui (factors,
2 );
--p;
}
p =
3 ;
for (i =
1 ; i <= PRIMES_PTAB_ENTRIES;)
{
if (! mpz_divisible_ui_p (t, p))
{
p += primes_diff[i++];
if (mpz_cmp_ui (t, p * p) <
0 )
break ;
}
else
{
mpz_tdiv_q_ui (t, t, p);
factor_insert_ui (factors, p);
}
}
mpz_clear (q);
}
static int
mp_millerrabin (mpz_srcptr n, mpz_srcptr nm1, mpz_ptr x, mpz_ptr y,
mpz_srcptr q,
unsigned long int k)
{
unsigned long int i;
mpz_powm (y, x, q, n);
if (mpz_cmp_ui (y,
1 ) ==
0 || mpz_cmp (y, nm1) ==
0 )
return 1 ;
for (i =
1 ; i < k; i++)
{
mpz_powm_ui (y, y,
2 , n);
if (mpz_cmp (y, nm1) ==
0 )
return 1 ;
if (mpz_cmp_ui (y,
1 ) ==
0 )
return 0 ;
}
return 0 ;
}
int
mp_prime_p (mpz_t n)
{
int k, r, is_prime;
mpz_t q, a, nm1, tmp;
struct factors factors;
if (mpz_cmp_ui (n,
1 ) <=
0 )
return 0 ;
/* We have already casted out small primes. */
if (mpz_cmp_ui (n, (
long ) FIRST_OMITTED_PRIME * FIRST_OMITTED_PRIME) <
0 )
return 1 ;
mpz_inits (q, a, nm1, tmp, NULL);
/* Precomputation for Miller-Rabin. */
mpz_sub_ui (nm1, n,
1 );
/* Find q and k, where q is odd and n = 1 + 2**k * q. */
k = mpz_scan1 (nm1,
0 );
mpz_tdiv_q_2exp (q, nm1, k);
mpz_set_ui (a,
2 );
/* Perform a Miller-Rabin test, finds most composites quickly. */
if (!mp_millerrabin (n, nm1, a, tmp, q, k))
{
is_prime =
0 ;
goto ret2;
}
if (flag_prove_primality)
{
/* Factor n-1 for Lucas. */
mpz_set (tmp, nm1);
factor (tmp, &factors);
}
/* Loop until Lucas proves our number prime, or Miller-Rabin proves our
number composite. */
for (r =
0 ; r < PRIMES_PTAB_ENTRIES; r++)
{
int i;
if (flag_prove_primality)
{
is_prime =
1 ;
for (i =
0 ; i < factors.nfactors && is_prime; i++)
{
mpz_divexact (tmp, nm1, factors.p[i]);
mpz_powm (tmp, a, tmp, n);
is_prime = mpz_cmp_ui (tmp,
1 ) !=
0 ;
}
}
else
{
/* After enough Miller-Rabin runs, be content. */
is_prime = (r == MR_REPS -
1 );
}
if (is_prime)
goto ret1;
mpz_add_ui (a, a, primes_diff[r]);
/* Establish new base. */
if (!mp_millerrabin (n, nm1, a, tmp, q, k))
{
is_prime =
0 ;
goto ret1;
}
}
fprintf (stderr,
"Lucas prime test failure. This should not happen\n" );
abort ();
ret1:
if (flag_prove_primality)
factor_clear (&factors);
ret2:
mpz_clears (q, a, nm1, tmp, NULL);
return is_prime;
}
void
factor_using_pollard_rho (mpz_t n,
unsigned long a,
struct factors *factors)
{
mpz_t x, z, y, P;
mpz_t t, t2;
unsigned long long k, l, i;
if (flag_verbose >
0 )
{
printf (
"[pollard-rho (%lu)] " , a);
}
mpz_inits (t, t2, NULL);
mpz_init_set_si (y,
2 );
mpz_init_set_si (x,
2 );
mpz_init_set_si (z,
2 );
mpz_init_set_ui (P,
1 );
k =
1 ;
l =
1 ;
while (mpz_cmp_ui (n,
1 ) !=
0 )
{
for (;;)
{
do
{
mpz_mul (t, x, x);
mpz_mod (x, t, n);
mpz_add_ui (x, x, a);
mpz_sub (t, z, x);
mpz_mul (t2, P, t);
mpz_mod (P, t2, n);
if (k %
32 ==
1 )
{
mpz_gcd (t, P, n);
if (mpz_cmp_ui (t,
1 ) !=
0 )
goto factor_found;
mpz_set (y, x);
}
}
while (--k !=
0 );
mpz_set (z, x);
k = l;
l =
2 * l;
for (i =
0 ; i < k; i++)
{
mpz_mul (t, x, x);
mpz_mod (x, t, n);
mpz_add_ui (x, x, a);
}
mpz_set (y, x);
}
factor_found:
do
{
mpz_mul (t, y, y);
mpz_mod (y, t, n);
mpz_add_ui (y, y, a);
mpz_sub (t, z, y);
mpz_gcd (t, t, n);
}
while (mpz_cmp_ui (t,
1 ) ==
0 );
mpz_divexact (n, n, t);
/* divide by t, before t is overwritten */
if (!mp_prime_p (t))
{
if (flag_verbose >
0 )
{
printf (
"[composite factor--restarting pollard-rho] " );
}
factor_using_pollard_rho (t, a +
1 , factors);
}
else
{
factor_insert (factors, t);
}
if (mp_prime_p (n))
{
factor_insert (factors, n);
break ;
}
mpz_mod (x, x, n);
mpz_mod (z, z, n);
mpz_mod (y, y, n);
}
mpz_clears (P, t2, t, z, x, y, NULL);
}
void
factor (mpz_t t,
struct factors *factors)
{
factor_init (factors);
if (mpz_sgn (t) !=
0 )
{
factor_using_division (t, factors);
if (mpz_cmp_ui (t,
1 ) !=
0 )
{
if (flag_verbose >
0 )
{
printf (
"[is number prime?] " );
}
if (mp_prime_p (t))
factor_insert (factors, t);
else
factor_using_pollard_rho (t,
1 , factors);
}
}
}
int
main (
int argc,
char *argv[])
{
mpz_t t;
int i, j, k;
struct factors factors;
while (argc >
1 )
{
if (!strcmp (argv[
1 ],
"-v" ))
flag_verbose =
1 ;
else if (!strcmp (argv[
1 ],
"-w" ))
flag_prove_primality =
0 ;
else
break ;
argv++;
argc--;
}
mpz_init (t);
if (argc >
1 )
{
for (i =
1 ; i < argc; i++)
{
mpz_set_str (t, argv[i],
0 );
gmp_printf (
"%Zd:" , t);
factor (t, &factors);
for (j =
0 ; j < factors.nfactors; j++)
for (k =
0 ; k < factors.e[j]; k++)
gmp_printf (
" %Zd" , factors.p[j]);
puts (
"" );
factor_clear (&factors);
}
}
else
{
for (;;)
{
mpz_inp_str (t, stdin,
0 );
if (feof (stdin))
break ;
gmp_printf (
"%Zd:" , t);
factor (t, &factors);
for (j =
0 ; j < factors.nfactors; j++)
for (k =
0 ; k < factors.e[j]; k++)
gmp_printf (
" %Zd" , factors.p[j]);
puts (
"" );
factor_clear (&factors);
}
}
exit (
0 );
}
Messung V0.5 in Prozent C=92 H=78 G=84
¤ Dauer der Verarbeitung: 0.11 Sekunden
(vorverarbeitet am 2026-06-17)
¤
*© Formatika GbR, Deutschland