[BACK]Return to factorize.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / gmp / demos

Annotation of OpenXM_contrib/gmp/demos/factorize.c, Revision 1.1.1.2

1.1       maekawa     1: /* Factoring with Pollard's rho method.
                      2:
1.1.1.2 ! maekawa     3:    Copyright (C) 1995, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
1.1       maekawa     4:
1.1.1.2 ! maekawa     5:    This program is free software; you can redistribute it and/or modify it
        !             6:    under the terms of the GNU General Public License as published by the
        !             7:    Free Software Foundation; either version 2, or (at your option) any
        !             8:    later version.
        !             9:
        !            10:    This program is distributed in the hope that it will be useful, but
        !            11:    WITHOUT ANY WARRANTY; without even the implied warranty of
        !            12:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
        !            13:    General Public License for more details.
        !            14:
        !            15:    You should have received a copy of the GNU General Public License along
        !            16:    with this program; see the file COPYING.  If not, write to the Free
        !            17:    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
        !            18:    02111-1307, USA.  */
1.1       maekawa    19:
1.1.1.2 ! maekawa    20: #include <stdlib.h>
1.1       maekawa    21: #include <stdio.h>
1.1.1.2 ! maekawa    22: #include <string.h>
        !            23:
1.1       maekawa    24: #include "gmp.h"
                     25:
1.1.1.2 ! maekawa    26: int flag_verbose = 0;
1.1       maekawa    27:
                     28: static unsigned add[] = {4, 2, 4, 2, 4, 6, 2, 6};
                     29:
1.1.1.2 ! maekawa    30: #if defined (__hpux) || defined (__alpha)  || defined (__svr4__) || defined (__SVR4)
        !            31: /* HPUX lacks random().  DEC OSF/1 1.2 random() returns a double.  */
        !            32: long mrand48 ();
        !            33: static long
        !            34: random ()
        !            35: {
        !            36:   return mrand48 ();
        !            37: }
        !            38: #else
        !            39: /* Glibc stdlib.h has "int32_t random();" which, on i386 at least, conflicts
        !            40:    with a redeclaration as "long". */
        !            41: #ifndef __GLIBC__
        !            42: long random ();
        !            43: #endif
        !            44: #endif
        !            45:
        !            46: void
        !            47: factor_using_division (mpz_t t, unsigned int limit)
1.1       maekawa    48: {
                     49:   mpz_t q, r;
                     50:   unsigned long int f;
1.1.1.2 ! maekawa    51:   int ai;
1.1       maekawa    52:   unsigned *addv = add;
1.1.1.2 ! maekawa    53:   unsigned int failures;
        !            54:
        !            55:   if (flag_verbose)
        !            56:     {
        !            57:       printf ("[trial division (%u)] ", limit);
        !            58:       fflush (stdout);
        !            59:     }
1.1       maekawa    60:
                     61:   mpz_init (q);
                     62:   mpz_init (r);
                     63:
1.1.1.2 ! maekawa    64:   f = mpz_scan1 (t, 0);
        !            65:   mpz_div_2exp (t, t, f);
        !            66:   while (f)
1.1       maekawa    67:     {
                     68:       printf ("2 ");
                     69:       fflush (stdout);
1.1.1.2 ! maekawa    70:       --f;
1.1       maekawa    71:     }
                     72:
                     73:   for (;;)
                     74:     {
                     75:       mpz_tdiv_qr_ui (q, r, t, 3);
                     76:       if (mpz_cmp_ui (r, 0) != 0)
                     77:        break;
                     78:       mpz_set (t, q);
                     79:       printf ("3 ");
                     80:       fflush (stdout);
                     81:     }
                     82:
                     83:   for (;;)
                     84:     {
                     85:       mpz_tdiv_qr_ui (q, r, t, 5);
                     86:       if (mpz_cmp_ui (r, 0) != 0)
                     87:        break;
                     88:       mpz_set (t, q);
                     89:       printf ("5 ");
                     90:       fflush (stdout);
                     91:     }
                     92:
1.1.1.2 ! maekawa    93:   failures = 0;
1.1       maekawa    94:   f = 7;
                     95:   ai = 0;
1.1.1.2 ! maekawa    96:   while (mpz_cmp_ui (t, 1) != 0)
1.1       maekawa    97:     {
                     98:       mpz_tdiv_qr_ui (q, r, t, f);
                     99:       if (mpz_cmp_ui (r, 0) != 0)
                    100:        {
                    101:          f += addv[ai];
1.1.1.2 ! maekawa   102:          if (mpz_cmp_ui (q, f) < 0)
        !           103:            break;
1.1       maekawa   104:          ai = (ai + 1) & 7;
1.1.1.2 ! maekawa   105:          failures++;
        !           106:          if (failures > limit)
        !           107:            break;
1.1       maekawa   108:        }
                    109:       else
                    110:        {
1.1.1.2 ! maekawa   111:          mpz_swap (t, q);
1.1       maekawa   112:          printf ("%lu ", f);
                    113:          fflush (stdout);
1.1.1.2 ! maekawa   114:          failures = 0;
1.1       maekawa   115:        }
                    116:     }
                    117:
                    118:   mpz_clear (q);
                    119:   mpz_clear (r);
                    120: }
                    121:
                    122: void
1.1.1.2 ! maekawa   123: factor_using_division_2kp (mpz_t t, unsigned int limit, unsigned long p)
1.1       maekawa   124: {
1.1.1.2 ! maekawa   125:   mpz_t r;
        !           126:   mpz_t f;
        !           127:   unsigned int k;
        !           128:
        !           129:   mpz_init (r);
        !           130:   mpz_init_set_ui (f, 2 * p);
        !           131:   mpz_add_ui (f, f, 1);
        !           132:   for (k = 1; k < limit; k++)
        !           133:     {
        !           134:       mpz_tdiv_r (r, t, f);
        !           135:       while (mpz_cmp_ui (r, 0) == 0)
        !           136:        {
        !           137:          mpz_tdiv_q (t, t, f);
        !           138:          mpz_tdiv_r (r, t, f);
        !           139:          mpz_out_str (stdout, 10, f);
        !           140:          fflush (stdout);
        !           141:          fputc (' ', stdout);
        !           142:        }
        !           143:       mpz_add_ui (f, f, 2 * p);
        !           144:     }
        !           145:
        !           146:   mpz_clear (f);
        !           147:   mpz_clear (r);
        !           148: }
        !           149:
        !           150: void
        !           151: factor_using_pollard_rho (mpz_t n, int a_int, unsigned long p)
        !           152: {
        !           153:   mpz_t x, x1, y, P;
1.1       maekawa   154:   mpz_t a;
1.1.1.2 ! maekawa   155:   mpz_t g;
        !           156:   mpz_t t1, t2;
        !           157:   int k, l, c, i;
        !           158:
        !           159:   if (flag_verbose)
        !           160:     {
        !           161:       printf ("[pollard-rho (%d)] ", a_int);
        !           162:       fflush (stdout);
        !           163:     }
        !           164:
        !           165:   mpz_init (g);
        !           166:   mpz_init (t1);
        !           167:   mpz_init (t2);
1.1       maekawa   168:
                    169:   mpz_init_set_si (a, a_int);
1.1.1.2 ! maekawa   170:   mpz_init_set_si (y, 2);
        !           171:   mpz_init_set_si (x, 2);
        !           172:   mpz_init_set_si (x1, 2);
        !           173:   k = 1;
        !           174:   l = 1;
        !           175:   mpz_init_set_ui (P, 1);
        !           176:   c = 0;
1.1       maekawa   177:
                    178:   while (mpz_cmp_ui (n, 1) != 0)
                    179:     {
1.1.1.2 ! maekawa   180: S2:
        !           181:       if (p != 0)
1.1       maekawa   182:        {
1.1.1.2 ! maekawa   183:          mpz_powm_ui (x, x, p, n); mpz_add (x, x, a);
1.1       maekawa   184:        }
                    185:       else
                    186:        {
1.1.1.2 ! maekawa   187:          mpz_mul (x, x, x); mpz_add (x, x, a); mpz_mod (x, x, n);
1.1       maekawa   188:        }
1.1.1.2 ! maekawa   189:       mpz_sub (t1, x1, x); mpz_mul (t2, P, t1); mpz_mod (P, t2, n);
        !           190:       c++;
        !           191:       if (c == 20)
        !           192:        {
        !           193:          c = 0;
        !           194:          mpz_gcd (g, P, n);
        !           195:          if (mpz_cmp_ui (g, 1) != 0)
        !           196:            goto S4;
        !           197:          mpz_set (y, x);
        !           198:        }
        !           199: S3:
        !           200:       k--;
        !           201:       if (k != 0)
        !           202:        goto S2;
        !           203:
        !           204:       mpz_gcd (g, P, n);
        !           205:       if (mpz_cmp_ui (g, 1) != 0)
        !           206:        goto S4;
        !           207:
        !           208:       mpz_set (x1, x);
        !           209:       k = l;
        !           210:       l = 2 * l;
        !           211:       for (i = 0; i < k; i++)
        !           212:        {
        !           213:          if (p != 0)
        !           214:            {
        !           215:              mpz_powm_ui (x, x, p, n); mpz_add (x, x, a);
        !           216:            }
        !           217:          else
        !           218:            {
        !           219:              mpz_mul (x, x, x); mpz_add (x, x, a); mpz_mod (x, x, n);
        !           220:            }
        !           221:        }
        !           222:       mpz_set (y, x);
        !           223:       c = 0;
        !           224:       goto S2;
        !           225: S4:
        !           226:       do
        !           227:        {
        !           228:          if (p != 0)
        !           229:            {
        !           230:              mpz_powm_ui (y, y, p, n); mpz_add (y, y, a);
        !           231:            }
        !           232:          else
        !           233:            {
        !           234:              mpz_mul (y, y, y); mpz_add (y, y, a); mpz_mod (y, y, n);
        !           235:            }
        !           236:          mpz_sub (t1, x1, y); mpz_gcd (g, t1, n);
        !           237:        }
        !           238:       while (mpz_cmp_ui (g, 1) == 0);
1.1       maekawa   239:
1.1.1.2 ! maekawa   240:       if (!mpz_probab_prime_p (g, 3))
1.1       maekawa   241:        {
1.1.1.2 ! maekawa   242:          do
        !           243:            a_int = random ();
        !           244:          while (a_int == -2 || a_int == 0);
        !           245:
        !           246:          if (flag_verbose)
1.1       maekawa   247:            {
1.1.1.2 ! maekawa   248:              printf ("[composite factor--restarting pollard-rho] ");
        !           249:              fflush (stdout);
1.1       maekawa   250:            }
1.1.1.2 ! maekawa   251:          factor_using_pollard_rho (g, a_int, p);
        !           252:          break;
        !           253:        }
        !           254:       else
        !           255:        {
        !           256:          mpz_out_str (stdout, 10, g);
        !           257:          fflush (stdout);
        !           258:          fputc (' ', stdout);
        !           259:        }
        !           260:       mpz_div (n, n, g);
        !           261:       mpz_mod (x, x, n);
        !           262:       mpz_mod (x1, x1, n);
        !           263:       mpz_mod (y, y, n);
        !           264:       if (mpz_probab_prime_p (n, 3))
        !           265:        {
        !           266:          mpz_out_str (stdout, 10, n);
        !           267:          fflush (stdout);
        !           268:          fputc (' ', stdout);
        !           269:          break;
1.1       maekawa   270:        }
                    271:     }
                    272:
1.1.1.2 ! maekawa   273:   mpz_clear (g);
        !           274:   mpz_clear (P);
        !           275:   mpz_clear (t2);
        !           276:   mpz_clear (t1);
1.1       maekawa   277:   mpz_clear (a);
1.1.1.2 ! maekawa   278:   mpz_clear (x1);
1.1       maekawa   279:   mpz_clear (x);
                    280:   mpz_clear (y);
                    281: }
                    282:
1.1.1.2 ! maekawa   283: void
        !           284: factor (mpz_t t, unsigned long p)
        !           285: {
        !           286:   unsigned int division_limit;
        !           287:
        !           288:   /* Set the trial division limit according the size of t.  */
        !           289:   division_limit = mpz_sizeinbase (t, 2);
        !           290:   if (division_limit > 1000)
        !           291:     division_limit = 1000 * 1000;
        !           292:   else
        !           293:     division_limit = division_limit * division_limit;
        !           294:
        !           295:   if (p != 0)
        !           296:     factor_using_division_2kp (t, division_limit / 10, p);
        !           297:   else
        !           298:     factor_using_division (t, division_limit);
        !           299:
        !           300:   if (mpz_cmp_ui (t, 1) != 0)
        !           301:     {
        !           302:       if (flag_verbose)
        !           303:        {
        !           304:          printf ("[is number prime?] ");
        !           305:          fflush (stdout);
        !           306:        }
        !           307:       if (mpz_probab_prime_p (t, 3))
        !           308:        mpz_out_str (stdout, 10, t);
        !           309:       else
        !           310:        factor_using_pollard_rho (t, 1, p);
        !           311:     }
1.1       maekawa   312: }
                    313:
1.1.1.2 ! maekawa   314: main (int argc, char *argv[])
1.1       maekawa   315: {
                    316:   mpz_t t;
                    317:   unsigned long p;
                    318:   int i;
                    319:
1.1.1.2 ! maekawa   320:   if (argc > 1 && !strcmp (argv[1], "-v"))
        !           321:     {
        !           322:       flag_verbose = 1;
        !           323:       argv++;
        !           324:       argc--;
        !           325:     }
        !           326:
        !           327:   p = 0;
1.1       maekawa   328:   for (i = 1; i < argc; i++)
                    329:     {
                    330:       if (!strncmp (argv[i], "-Mp", 3))
                    331:        {
                    332:          p = atoi (argv[i] + 3);
                    333:          mpz_init_set_ui (t, 1);
                    334:          mpz_mul_2exp (t, t, p);
                    335:          mpz_sub_ui (t, t, 1);
1.1.1.2 ! maekawa   336:        }
        !           337:       else if (!strncmp (argv[i], "-2kp", 4))
        !           338:        {
        !           339:          p = atoi (argv[i] + 4);
        !           340:          continue;
1.1       maekawa   341:        }
                    342:       else
                    343:        {
                    344:          mpz_init_set_str (t, argv[i], 0);
                    345:        }
                    346:
1.1.1.2 ! maekawa   347:       if (mpz_cmp_ui (t, 0) == 0)
        !           348:        puts ("-");
        !           349:       else
        !           350:        {
        !           351:          factor (t, p);
        !           352:          puts ("");
        !           353:        }
1.1       maekawa   354:     }
1.1.1.2 ! maekawa   355:   exit (0);
        !           356: }
        !           357:
        !           358: void
        !           359: dmp (mpz_t x)
        !           360: {
        !           361:   mpz_out_str (stdout, 10, x);
        !           362:   puts ("");
1.1       maekawa   363: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>