/* Auxiliary functions for GMP-ECM. Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2011, 2012 Paul Zimmermann, Alexander Kruppa, Laurent Fousse, Jim Fougeron, Cyril Bouvier. 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; see the file COPYING. If not, see http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include "ecm-impl.h" #include "ecm-ecm.h" #ifdef HAVE_GWNUM /* For GWNUM_VERSION */ #include "gwnum.h" #endif #include "champions.h" /****************************************************************************** * * * Auxiliary functions * * * ******************************************************************************/ /* returns the number of decimal digits of n */ unsigned int nb_digits (const mpz_t n) { mpz_t x; unsigned int size; size = mpz_sizeinbase (n, 10); /* the GMP documentation says mpz_sizeinbase returns the exact value, or one too big, thus: (a) either n < 10^(size-1), and n has size-1 digits (b) or n >= size-1, and n has size digits Note: mpz_sizeinbase returns 1 for n=0, thus we always have size >= 1. */ mpz_init (x); mpz_ui_pow_ui (x, 10, size - 1); if (mpz_cmpabs (n, x) < 0) size --; mpz_clear (x); return size; } /* Tries to read a number from a line from fd and stores it in r. Keeps reading lines until a number is found. Lines beginning with "#" are skipped. Returns 1 if a number was successfully read, 0 if no number can be read (i.e. at EOF) Function is now simpler. Much of the logic (other than skipping # lines is now contained within eval() function. */ int read_number (mpcandi_t *n, FILE *fd, int primetest) { int c; new_line: c = fgetc (fd); /* Skip comment lines beginning with '#' */ if (c == '#') { do c = fgetc (fd); while (c != EOF && !IS_NEWLINE(c)); if (IS_NEWLINE(c)) goto new_line; } if (c == EOF) return 0; ungetc (c, fd); if (!eval (n, fd, primetest)) goto new_line; #if 0 /* Code to test out eval_str function, which "appears" to work correctly. */ { /* warning!! Line is pretty small, but since this is just testing code, we can easily control the input for this test. This code should NEVER be compiled into released build, its only for testing of eval_str() */ char Line[500], *cp; fgets (Line, sizeof(Line), fd); if (!eval_str (n, Line, primetest, &cp)) goto new_line; fprintf (stderr, "\nLine is at %X cp is at %X\n", Line, cp); } #endif #if defined (DEBUG_EVALUATOR) if (n->cpExpr) fprintf (stderr, "Input Expr: %s\n", n->cpExpr); gmp_fprintf(stderr, "N: %Zd\n", n->n); #endif return 1; } int process_newfactor (mpz_t g, int result, mpcandi_t *n, int method, int returncode, int gpu, unsigned int *cnt, int *resume_wasPrp, mpz_t resume_lastfac, FILE *resumefile, int verbose, int deep) { int factor_is_prime = 0; /* If a factor was found, indicate whether factor, cofactor are */ /* prime. If no factor was found, both are zero. */ int cofactor_is_prime = 0; int method1; int found_n; mpz_t f; mpz_init (f); mpz_gcd (f, g, n->n); /* When GPU is not used, the factor should divide n->n */ if (gpu == 0) ASSERT_ALWAYS(mpz_cmp (g, f) == 0); else if (mpz_cmp (g, f) != 0 && mpz_cmp_ui (f, 1) == 0) /* GPU case: all factors of g were already found */ { /* FIXME Maybe print something in very verbose mode */ mpz_clear (f); return returncode; } /* Restoring print statement that was disabled from previous code clean-up efforts */ /* This print statement is important to the function of external factoring programs */ /* that rely on the following information being printed out */ /* g = f (gpu or not gpu) or g != 1 with gpu */ if (mpz_cmp (g, f) == 0 || (gpu != 0 && mpz_cmp_ui (g, 1) != 0)) { if (verbose > 0) printf ("********** Factor found in step %u: ", ABS (result)); mpz_out_str (stdout, 10, f); if (verbose > 0) printf ("\n"); } /* Complain about non-proper factors (0, negative) */ ASSERT_ALWAYS(mpz_cmp_ui (f, 1) >= 1); found_n = mpz_cmp (f, n->n) == 0; /* 1 for display warning if factor does not divide the current candidate */ mpcandi_t_addfoundfactor (n, f, gpu == 0); if (found_n == 0) { /* prints factor found and cofactor on standard output. */ /* the second argument here tells aprtcle to not print primality proving progress info */ factor_is_prime = mpz_aprtcle (f, 0); if (verbose >= 1) { if (factor_is_prime == ECM_FAC_PRIME) printf ("Found prime factor of %u digits: ", nb_digits (f)); else if (factor_is_prime == ECM_FAC_PRP) printf ("Found probable prime factor of %u digits: ", nb_digits (f)); else printf ("Found composite factor of %u digits: ", nb_digits (f)); mpz_out_str (stdout, 10, f); printf ("\n"); } if (resumefile != NULL) { /* If we are resuming from a save file, add factor to the discovered factors for the current number */ mpz_mul (resume_lastfac, resume_lastfac, f); *resume_wasPrp = n->isPrp; } if (factor_is_prime && returncode == 0) returncode = (n->isPrp) ? ECM_PRIME_FAC_PRIME_COFAC : ECM_PRIME_FAC_COMP_COFAC; else returncode = (n->isPrp) ? ECM_COMP_FAC_PRIME_COFAC : ECM_COMP_FAC_COMP_COFAC; if (verbose >= 1) { cofactor_is_prime = n->isPrp; /* from mpcandi_t_addfoundfactor */ if (cofactor_is_prime == ECM_FAC_PRIME) printf ("Prime cofactor "); else if (cofactor_is_prime == ECM_FAC_PRP) printf ("Probable prime cofactor "); else printf ("Composite cofactor "); if (n->cpExpr) printf ("%s", n->cpExpr); else mpz_out_str (stdout, 10, n->n); printf (" has %u digits\n", n->ndigits); } else /* quiet mode: just print a space here, remaining cofactor will be printed after last curve */ printf (" "); /* check for champions (top ten for each method) */ method1 = ((method == ECM_PP1) && (result < 0)) ? ECM_PM1 : method; if ((verbose > 0) && factor_is_prime && nb_digits (f) >= champion_digits[method1]) { printf ("Report your potential champion to %s\n", champion_keeper[method1]); printf ("(see %s)\n", champion_url[method1]); } /* Take care of fully factoring this number, in case we are in deep mode */ if (n->isPrp) *cnt = 0; /* no more curve to perform */ if (!deep) *cnt = 0; } else { *cnt = 0; /* no more curve to perform */ if (verbose > 0) printf ("Found input number N"); printf ("\n"); returncode = ECM_INPUT_NUMBER_FOUND; } fflush (stdout); mpz_clear (f); return returncode; }