github.com/aergoio/aergo@v1.3.1/libtool/src/gmp-6.1.2/demos/factorize.c (about)

     1  /* Factoring with Pollard's rho method.
     2  
     3  Copyright 1995, 1997-2003, 2005, 2009, 2012, 2015 Free Software
     4  Foundation, Inc.
     5  
     6  This program is free software; you can redistribute it and/or modify it under
     7  the terms of the GNU General Public License as published by the Free Software
     8  Foundation; either version 3 of the License, or (at your option) any later
     9  version.
    10  
    11  This program is distributed in the hope that it will be useful, but WITHOUT ANY
    12  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
    13  PARTICULAR PURPOSE.  See the GNU General Public License for more details.
    14  
    15  You should have received a copy of the GNU General Public License along with
    16  this program.  If not, see https://www.gnu.org/licenses/.  */
    17  
    18  
    19  #include <stdlib.h>
    20  #include <stdio.h>
    21  #include <string.h>
    22  #include <inttypes.h>
    23  
    24  #include "gmp.h"
    25  
    26  static unsigned char primes_diff[] = {
    27  #define P(a,b,c) a,
    28  #include "primes.h"
    29  #undef P
    30  };
    31  #define PRIMES_PTAB_ENTRIES (sizeof(primes_diff) / sizeof(primes_diff[0]))
    32  
    33  int flag_verbose = 0;
    34  
    35  /* Prove primality or run probabilistic tests.  */
    36  int flag_prove_primality = 1;
    37  
    38  /* Number of Miller-Rabin tests to run when not proving primality. */
    39  #define MR_REPS 25
    40  
    41  struct factors
    42  {
    43    mpz_t         *p;
    44    unsigned long *e;
    45    long nfactors;
    46  };
    47  
    48  void factor (mpz_t, struct factors *);
    49  
    50  void
    51  factor_init (struct factors *factors)
    52  {
    53    factors->p = malloc (1);
    54    factors->e = malloc (1);
    55    factors->nfactors = 0;
    56  }
    57  
    58  void
    59  factor_clear (struct factors *factors)
    60  {
    61    int i;
    62  
    63    for (i = 0; i < factors->nfactors; i++)
    64      mpz_clear (factors->p[i]);
    65  
    66    free (factors->p);
    67    free (factors->e);
    68  }
    69  
    70  void
    71  factor_insert (struct factors *factors, mpz_t prime)
    72  {
    73    long    nfactors  = factors->nfactors;
    74    mpz_t         *p  = factors->p;
    75    unsigned long *e  = factors->e;
    76    long i, j;
    77  
    78    /* Locate position for insert new or increment e.  */
    79    for (i = nfactors - 1; i >= 0; i--)
    80      {
    81        if (mpz_cmp (p[i], prime) <= 0)
    82  	break;
    83      }
    84  
    85    if (i < 0 || mpz_cmp (p[i], prime) != 0)
    86      {
    87        p = realloc (p, (nfactors + 1) * sizeof p[0]);
    88        e = realloc (e, (nfactors + 1) * sizeof e[0]);
    89  
    90        mpz_init (p[nfactors]);
    91        for (j = nfactors - 1; j > i; j--)
    92  	{
    93  	  mpz_set (p[j + 1], p[j]);
    94  	  e[j + 1] = e[j];
    95  	}
    96        mpz_set (p[i + 1], prime);
    97        e[i + 1] = 1;
    98  
    99        factors->p = p;
   100        factors->e = e;
   101        factors->nfactors = nfactors + 1;
   102      }
   103    else
   104      {
   105        e[i] += 1;
   106      }
   107  }
   108  
   109  void
   110  factor_insert_ui (struct factors *factors, unsigned long prime)
   111  {
   112    mpz_t pz;
   113  
   114    mpz_init_set_ui (pz, prime);
   115    factor_insert (factors, pz);
   116    mpz_clear (pz);
   117  }
   118  
   119  
   120  void
   121  factor_using_division (mpz_t t, struct factors *factors)
   122  {
   123    mpz_t q;
   124    unsigned long int p;
   125    int i;
   126  
   127    if (flag_verbose > 0)
   128      {
   129        printf ("[trial division] ");
   130      }
   131  
   132    mpz_init (q);
   133  
   134    p = mpz_scan1 (t, 0);
   135    mpz_fdiv_q_2exp (t, t, p);
   136    while (p)
   137      {
   138        factor_insert_ui (factors, 2);
   139        --p;
   140      }
   141  
   142    p = 3;
   143    for (i = 1; i <= PRIMES_PTAB_ENTRIES;)
   144      {
   145        if (! mpz_divisible_ui_p (t, p))
   146  	{
   147  	  p += primes_diff[i++];
   148  	  if (mpz_cmp_ui (t, p * p) < 0)
   149  	    break;
   150  	}
   151        else
   152  	{
   153  	  mpz_tdiv_q_ui (t, t, p);
   154  	  factor_insert_ui (factors, p);
   155  	}
   156      }
   157  
   158    mpz_clear (q);
   159  }
   160  
   161  static int
   162  mp_millerrabin (mpz_srcptr n, mpz_srcptr nm1, mpz_ptr x, mpz_ptr y,
   163  		mpz_srcptr q, unsigned long int k)
   164  {
   165    unsigned long int i;
   166  
   167    mpz_powm (y, x, q, n);
   168  
   169    if (mpz_cmp_ui (y, 1) == 0 || mpz_cmp (y, nm1) == 0)
   170      return 1;
   171  
   172    for (i = 1; i < k; i++)
   173      {
   174        mpz_powm_ui (y, y, 2, n);
   175        if (mpz_cmp (y, nm1) == 0)
   176  	return 1;
   177        if (mpz_cmp_ui (y, 1) == 0)
   178  	return 0;
   179      }
   180    return 0;
   181  }
   182  
   183  int
   184  mp_prime_p (mpz_t n)
   185  {
   186    int k, r, is_prime;
   187    mpz_t q, a, nm1, tmp;
   188    struct factors factors;
   189  
   190    if (mpz_cmp_ui (n, 1) <= 0)
   191      return 0;
   192  
   193    /* We have already casted out small primes. */
   194    if (mpz_cmp_ui (n, (long) FIRST_OMITTED_PRIME * FIRST_OMITTED_PRIME) < 0)
   195      return 1;
   196  
   197    mpz_inits (q, a, nm1, tmp, NULL);
   198  
   199    /* Precomputation for Miller-Rabin.  */
   200    mpz_sub_ui (nm1, n, 1);
   201  
   202    /* Find q and k, where q is odd and n = 1 + 2**k * q.  */
   203    k = mpz_scan1 (nm1, 0);
   204    mpz_tdiv_q_2exp (q, nm1, k);
   205  
   206    mpz_set_ui (a, 2);
   207  
   208    /* Perform a Miller-Rabin test, finds most composites quickly.  */
   209    if (!mp_millerrabin (n, nm1, a, tmp, q, k))
   210      {
   211        is_prime = 0;
   212        goto ret2;
   213      }
   214  
   215    if (flag_prove_primality)
   216      {
   217        /* Factor n-1 for Lucas.  */
   218        mpz_set (tmp, nm1);
   219        factor (tmp, &factors);
   220      }
   221  
   222    /* Loop until Lucas proves our number prime, or Miller-Rabin proves our
   223       number composite.  */
   224    for (r = 0; r < PRIMES_PTAB_ENTRIES; r++)
   225      {
   226        int i;
   227  
   228        if (flag_prove_primality)
   229  	{
   230  	  is_prime = 1;
   231  	  for (i = 0; i < factors.nfactors && is_prime; i++)
   232  	    {
   233  	      mpz_divexact (tmp, nm1, factors.p[i]);
   234  	      mpz_powm (tmp, a, tmp, n);
   235  	      is_prime = mpz_cmp_ui (tmp, 1) != 0;
   236  	    }
   237  	}
   238        else
   239  	{
   240  	  /* After enough Miller-Rabin runs, be content. */
   241  	  is_prime = (r == MR_REPS - 1);
   242  	}
   243  
   244        if (is_prime)
   245  	goto ret1;
   246  
   247        mpz_add_ui (a, a, primes_diff[r]);	/* Establish new base.  */
   248  
   249        if (!mp_millerrabin (n, nm1, a, tmp, q, k))
   250  	{
   251  	  is_prime = 0;
   252  	  goto ret1;
   253  	}
   254      }
   255  
   256    fprintf (stderr, "Lucas prime test failure.  This should not happen\n");
   257    abort ();
   258  
   259   ret1:
   260    if (flag_prove_primality)
   261      factor_clear (&factors);
   262   ret2:
   263    mpz_clears (q, a, nm1, tmp, NULL);
   264  
   265    return is_prime;
   266  }
   267  
   268  void
   269  factor_using_pollard_rho (mpz_t n, unsigned long a, struct factors *factors)
   270  {
   271    mpz_t x, z, y, P;
   272    mpz_t t, t2;
   273    unsigned long long k, l, i;
   274  
   275    if (flag_verbose > 0)
   276      {
   277        printf ("[pollard-rho (%lu)] ", a);
   278      }
   279  
   280    mpz_inits (t, t2, NULL);
   281    mpz_init_set_si (y, 2);
   282    mpz_init_set_si (x, 2);
   283    mpz_init_set_si (z, 2);
   284    mpz_init_set_ui (P, 1);
   285    k = 1;
   286    l = 1;
   287  
   288    while (mpz_cmp_ui (n, 1) != 0)
   289      {
   290        for (;;)
   291  	{
   292  	  do
   293  	    {
   294  	      mpz_mul (t, x, x);
   295  	      mpz_mod (x, t, n);
   296  	      mpz_add_ui (x, x, a);
   297  
   298  	      mpz_sub (t, z, x);
   299  	      mpz_mul (t2, P, t);
   300  	      mpz_mod (P, t2, n);
   301  
   302  	      if (k % 32 == 1)
   303  		{
   304  		  mpz_gcd (t, P, n);
   305  		  if (mpz_cmp_ui (t, 1) != 0)
   306  		    goto factor_found;
   307  		  mpz_set (y, x);
   308  		}
   309  	    }
   310  	  while (--k != 0);
   311  
   312  	  mpz_set (z, x);
   313  	  k = l;
   314  	  l = 2 * l;
   315  	  for (i = 0; i < k; i++)
   316  	    {
   317  	      mpz_mul (t, x, x);
   318  	      mpz_mod (x, t, n);
   319  	      mpz_add_ui (x, x, a);
   320  	    }
   321  	  mpz_set (y, x);
   322  	}
   323  
   324      factor_found:
   325        do
   326  	{
   327  	  mpz_mul (t, y, y);
   328  	  mpz_mod (y, t, n);
   329  	  mpz_add_ui (y, y, a);
   330  
   331  	  mpz_sub (t, z, y);
   332  	  mpz_gcd (t, t, n);
   333  	}
   334        while (mpz_cmp_ui (t, 1) == 0);
   335  
   336        mpz_divexact (n, n, t);	/* divide by t, before t is overwritten */
   337  
   338        if (!mp_prime_p (t))
   339  	{
   340  	  if (flag_verbose > 0)
   341  	    {
   342  	      printf ("[composite factor--restarting pollard-rho] ");
   343  	    }
   344  	  factor_using_pollard_rho (t, a + 1, factors);
   345  	}
   346        else
   347  	{
   348  	  factor_insert (factors, t);
   349  	}
   350  
   351        if (mp_prime_p (n))
   352  	{
   353  	  factor_insert (factors, n);
   354  	  break;
   355  	}
   356  
   357        mpz_mod (x, x, n);
   358        mpz_mod (z, z, n);
   359        mpz_mod (y, y, n);
   360      }
   361  
   362    mpz_clears (P, t2, t, z, x, y, NULL);
   363  }
   364  
   365  void
   366  factor (mpz_t t, struct factors *factors)
   367  {
   368    factor_init (factors);
   369  
   370    if (mpz_sgn (t) != 0)
   371      {
   372        factor_using_division (t, factors);
   373  
   374        if (mpz_cmp_ui (t, 1) != 0)
   375  	{
   376  	  if (flag_verbose > 0)
   377  	    {
   378  	      printf ("[is number prime?] ");
   379  	    }
   380  	  if (mp_prime_p (t))
   381  	    factor_insert (factors, t);
   382  	  else
   383  	    factor_using_pollard_rho (t, 1, factors);
   384  	}
   385      }
   386  }
   387  
   388  int
   389  main (int argc, char *argv[])
   390  {
   391    mpz_t t;
   392    int i, j, k;
   393    struct factors factors;
   394  
   395    while (argc > 1)
   396      {
   397        if (!strcmp (argv[1], "-v"))
   398  	flag_verbose = 1;
   399        else if (!strcmp (argv[1], "-w"))
   400  	flag_prove_primality = 0;
   401        else
   402  	break;
   403  
   404        argv++;
   405        argc--;
   406      }
   407  
   408    mpz_init (t);
   409    if (argc > 1)
   410      {
   411        for (i = 1; i < argc; i++)
   412  	{
   413  	  mpz_set_str (t, argv[i], 0);
   414  
   415  	  gmp_printf ("%Zd:", t);
   416  	  factor (t, &factors);
   417  
   418  	  for (j = 0; j < factors.nfactors; j++)
   419  	    for (k = 0; k < factors.e[j]; k++)
   420  	      gmp_printf (" %Zd", factors.p[j]);
   421  
   422  	  puts ("");
   423  	  factor_clear (&factors);
   424  	}
   425      }
   426    else
   427      {
   428        for (;;)
   429  	{
   430  	  mpz_inp_str (t, stdin, 0);
   431  	  if (feof (stdin))
   432  	    break;
   433  
   434  	  gmp_printf ("%Zd:", t);
   435  	  factor (t, &factors);
   436  
   437  	  for (j = 0; j < factors.nfactors; j++)
   438  	    for (k = 0; k < factors.e[j]; k++)
   439  	      gmp_printf (" %Zd", factors.p[j]);
   440  
   441  	  puts ("");
   442  	  factor_clear (&factors);
   443  	}
   444      }
   445  
   446    exit (0);
   447  }