Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/games/factor -Fix an old bug in the "pollard" code: it gets ...



details:   https://anonhg.NetBSD.org/src/rev/380552243e8c
branches:  trunk
changeset: 754320:380552243e8c
user:      drochner <drochner%NetBSD.org@localhost>
date:      Tue Apr 27 18:11:19 2010 +0000

description:
-Fix an old bug in the "pollard" code: it gets its argument passed
 by reference, and changes the value behind the pointer under some
 circumstances (basically if it finds more than 2 different factors).
 It also calls itself if it finds a factor which is not considered prime
 (by openssl's miller-rabin check) and uses the call argument afterwards.
 This doesn't work -- we need to copy the argument into its own storage.
-Modify the code to do the "rho" algorithm as was initially announced.
 It takes somewhat longer in rare cases, but still works in cases where
 the "p-1" algorithm is unusable. This might fix PR misc/43192
 by Luiz Henrique de Figueiredo.
-Add some optional debug support, minor cleanup.

diffstat:

 games/factor/factor.c |  87 ++++++++++++++++++++++++++++++++++----------------
 1 files changed, 59 insertions(+), 28 deletions(-)

diffs (139 lines):

diff -r 99a5613fff28 -r 380552243e8c games/factor/factor.c
--- a/games/factor/factor.c     Tue Apr 27 15:26:59 2010 +0000
+++ b/games/factor/factor.c     Tue Apr 27 18:11:19 2010 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: factor.c,v 1.20 2010/04/22 14:28:48 drochner Exp $     */
+/*     $NetBSD: factor.c,v 1.21 2010/04/27 18:11:19 drochner Exp $     */
 
 /*
  * Copyright (c) 1989, 1993
@@ -42,7 +42,7 @@
 #if 0
 static char sccsid[] = "@(#)factor.c   8.4 (Berkeley) 5/4/95";
 #else
-__RCSID("$NetBSD: factor.c,v 1.20 2010/04/22 14:28:48 drochner Exp $");
+__RCSID("$NetBSD: factor.c,v 1.21 2010/04/27 18:11:19 drochner Exp $");
 #endif
 #endif /* not lint */
 
@@ -98,6 +98,9 @@
  */
 extern const ubig prime[];
 extern const ubig *pr_limit;           /* largest prime in the prime array */
+#if 0 /* debugging: limit table use to stress the "pollard" code */
+#define pr_limit &prime[0]
+#endif
 
 #define        PRIME_CHECKS    5
 
@@ -226,7 +229,7 @@
                        BIGNUM *bnfact;
 
                        bnfact = BN_new();
-                       BN_set_word(bnfact, *(fact - 1));
+                       BN_set_word(bnfact, (BN_ULONG)*(fact - 1));
                        BN_sqr(bnfact, bnfact, ctx);
                        if (BN_cmp(bnfact, val) > 0
                            || BN_is_prime(val, PRIME_CHECKS, NULL, NULL,
@@ -284,39 +287,54 @@
 static void
 pollard_pminus1(BIGNUM *val)
 {
-       BIGNUM *base, *rbase, *num, *i, *x;
+       BIGNUM *x, *y, *tmp, *num;
+       BN_ULONG a;
+       unsigned int steps_taken, steps_limit;
 
-       base = BN_new();
-       rbase = BN_new();
-       num = BN_new();
-       i = BN_new();
        x = BN_new();
-
-       BN_set_word(rbase, 1);
- newbase:
-       BN_add_word(rbase, 1);
-       BN_set_word(i, 2);
-       BN_copy(base, rbase);
+       y = BN_new();
+       tmp = BN_new();
+       num = BN_new();
+       a = 1;
+restart:
+       steps_taken = 0;
+       steps_limit = 2;
+       BN_set_word(x, 1);
+       BN_copy(y, x);
 
        for (;;) {
-               BN_mod_exp(base, base, i, val, ctx);
-               if (BN_is_one(base))
-                       goto newbase;
+               BN_sqr(tmp, x, ctx);
+               BN_add_word(tmp, a);
+               BN_mod(x, tmp, val, ctx);
+               BN_sub(tmp, x, y);
+               if (BN_is_zero(tmp)) {
+#ifdef DEBUG
+                       printf(" (loop)");
+#endif
+                       a++;
+                       goto restart;
+               }
+               BN_gcd(tmp, tmp, val, ctx);
 
-               BN_copy(x, base);
-               BN_sub_word(x, 1);
-               BN_gcd(x, x, val, ctx);
-
-               if (!BN_is_one(x)) {
-                       if (BN_is_prime(x, PRIME_CHECKS, NULL, NULL,
+               if (!BN_is_one(tmp)) {
+                       if (BN_is_prime(tmp, PRIME_CHECKS, NULL, NULL,
                            NULL) == 1) {
                                putchar(' ');
-                               BN_print_dec_fp(stdout, x);
-                       } else
-                               pollard_pminus1(x);
+                               BN_print_dec_fp(stdout, tmp);
+                       } else {
+#ifdef DEBUG
+                               printf(" (recurse for ");
+                               BN_print_dec_fp(stdout, tmp);
+                               putchar(')');
+#endif
+                               pollard_pminus1(BN_dup(tmp));
+#ifdef DEBUG
+                               printf(" (back)");
+#endif
+                       }
                        fflush(stdout);
 
-                       BN_div(num, NULL, val, x, ctx);
+                       BN_div(num, NULL, val, tmp, ctx);
                        if (BN_is_one(num))
                                return;
                        if (BN_is_prime(num, PRIME_CHECKS, NULL, NULL,
@@ -327,8 +345,21 @@
                                return;
                        }
                        BN_copy(val, num);
+                       goto restart;
                }
-               BN_add_word(i, 1);
+               steps_taken++;
+               if (steps_taken == steps_limit) {
+                       BN_copy(y, x); /* teleport the turtle */
+                       steps_taken = 0;
+                       steps_limit *= 2;
+                       if (steps_limit == 0) {
+#ifdef DEBUG
+                               printf(" (overflow)");
+#endif
+                               a++;
+                               goto restart;
+                       }
+               }
        }
 }
 #else



Home | Main Index | Thread Index | Old Index