X-Git-Url: https://git.distorted.org.uk/u/mdw/catacomb/blobdiff_plain/0f5ec153dcb1c20a765d0420cc189ebac1b9682d..cc3ca08f22460b15423bb88632f3a12741b19003:/pgen.h diff --git a/pgen.h b/pgen.h index 536ba0a..a066e28 100644 --- a/pgen.h +++ b/pgen.h @@ -1,13 +1,13 @@ /* -*-c-*- * - * $Id: pgen.h,v 1.1 1999/11/19 13:17:57 mdw Exp $ + * $Id$ * - * Finding and testing prime numbers + * Prime generation glue * * (c) 1999 Straylight/Edgeware */ -/*----- Licensing notice --------------------------------------------------* +/*----- Licensing notice --------------------------------------------------* * * This file is part of Catacomb. * @@ -15,28 +15,20 @@ * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. - * + * * Catacomb 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 Library General Public License for more details. - * + * * You should have received a copy of the GNU Library General Public * License along with Catacomb; if not, write to the Free * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ -/*----- Revision history --------------------------------------------------* - * - * $Log: pgen.h,v $ - * Revision 1.1 1999/11/19 13:17:57 mdw - * Prime number generator and tester. - * - */ - -#ifndef PGEN_H -#define PGEN_H +#ifndef CATACOMB_PGEN_H +#define CATACOMB_PGEN_H #ifdef __cplusplus extern "C" { @@ -44,89 +36,251 @@ /*----- Header files ------------------------------------------------------*/ -#ifndef MP_H +#ifndef CATACOMB_GRAND_H +# include "grand.h" +#endif + +#ifndef CATACOMB_MP_H # include "mp.h" #endif -#ifndef PTAB_H -# include "ptab.h" +#ifndef CATACOMB_PFILT_H +# include "pfilt.h" #endif -/*----- Constants ---------------------------------------------------------*/ +#ifndef CATACOMB_RABIN_H +# include "rabin.h" +#endif -#define PGEN_COMPOSITE (-1) /* Number is definitely composite */ -#define PGEN_MAYBE (0) /* Number may be prime */ -#define PGEN_PRIME (1) /* Number is definitely prime */ +/*----- Event handling ----------------------------------------------------* + * + * Different programs and architectures will want to show progress of prime + * searches and similar processes in different ways. Of course, for simple + * searches, it's possible to use the @pfilt@ and @rabin@ functions and + * maintain control over the general control flow throughout the search. + * + * For more complex cases, this sort of control is undesirable. It's + * possible to specify an event handler which is informed in abstract about + * the search. The event handler can also request the search be aborted. + */ -/*----- Data structures ---------------------------------------------------*/ +/* --- Event code constants --- * + * + * You're allowed to rely on the values of @PGEN_DONE@ and @PGEN_ABORT@. + */ -typedef struct pgen { - mp *m; - unsigned char r[NPRIME]; -} pgen; +enum { + PGEN_BEGIN = 1, /* Search for value begins */ + PGEN_TRY, /* A new candidate has appeared */ + PGEN_FAIL, /* The candidate failed the test */ + PGEN_PASS, /* The candidate passed a test */ + PGEN_DONE = 0, /* A good value has been found */ + PGEN_ABORT = -1 /* The search has been aborted */ +}; -/*----- Functions provided ------------------------------------------------*/ +/* --- Event information --- * + * + * Note that the pseudorandom number generator supplied is not + * cryptographically strong. + */ -/* --- @pgen_create@ --- * +typedef struct pgen_event { + const char *name; /* Which quantity is being found */ + mp *m; /* Current value under test */ + unsigned steps; /* Number of candidates left */ + unsigned tests; /* Tests left before passing */ + grand *r; /* Source of random numbers */ +} pgen_event; + +/*----- Prime search parameters -------------------------------------------* + * + * The prime search is parameterized in a large number of ways, although this + * isn't so much of a surprise given the different sorts of properties + * required from prime numbers in cryptographic applications. + * + * There are two main things which need to be configured: stepping, and + * testing. (Filtering is done as part of stepping.) + * + * The functions here provide a toolkit for constructing stepping and testing + * routines. In a lot of cases, the functions can be used directly; in + * others, simple bits of glue need be written. * - * Arguments: @pgen *p@ = pointer to prime generation context - * @mp *m@ = pointer to initial number to test + * Two types of functions are defined: steppers and testers, but their + * interfaces are substantially similar. Each is given a request code, a + * context block and an event block. It is meant to update its context and + * the event block and return an event code. * - * Returns: One of the @PGEN@ constants above. + * A call with a request of @PGEN_BEGIN@ asks the stepper or tester to + * initialize itself using the information in its event block and context. A + * return of @PGEN_FAIL@ reports an immediate failure; @PGEN_ABORT@ reports a + * fatal problem; @PGEN_DONE@ reports immediate success. @PGEN_TRY@ reports + * successful initialization and requests test iterations. * - * Use: Tests an initial number for primality by computing its - * residue modulo various small prime numbers. This is fairly - * quick, but not particularly certain. If a @PGEN_MAYBE@ - * result is returned, perform Rabin-Miller tests to confirm. + * A call to a stepper with a request of @PGEN_TRY@ asks it to step to the + * next possible candidate, replacing the value @m@ in the event block with + * the new candidate. A call to a tester with a request of @PGEN_TRY@ + * runs one pass of the test. It should return @PGEN_FAIL@ to report a + * failure, @PGEN_PASS@ to report a success and request another iteration, + * @PGEN_DONE@ to report final acceptance and @PGEN_ABORT@ to terminate the + * search unsuccessfully. Note that even if the search is aborted, a + * shutdown request is still made. + * + * A call with a request of @PGEN_DONE@ closes down the stepper or tester. + * After a successful initialization (i.e., a return of something other than + * @PGEN_ABORT@), a shutdown call is guaranteed. The return code is ignored. */ -extern int pgen_create(pgen */*p*/, mp */*m*/); +typedef int pgen_proc(int /*rq*/, pgen_event */*ev*/, void */*p*/); + +/*----- Simple handler functions ------------------------------------------*/ -/* --- @pgen_destroy@ --- * +/* --- @pgen_filter@ --- * * - * Arguments: @pgen *p@ = pointer to prime generation context + * A prime generation context contains the information required for the + * simple prime filter and tester presented here. + */ + +typedef struct pgen_filterctx { + unsigned step; /* Step size (set by client) */ + pfilt f; /* The rapid prime filter */ +} pgen_filterctx; + +extern pgen_proc pgen_filter; + +/* --- @pgen_jump@ --- * * - * Returns: --- + * Similar to the standard @pgen_filter@, but jumps in large steps rather + * than small ones. + */ + +typedef struct pgen_jumpctx { + const pfilt *j; + pfilt f; +} pgen_jumpctx; + +extern pgen_proc pgen_jump; + +/* --- @pgen_test@ --- * * - * Use: Discards a context and all the resources it holds. + * Runs the Rabin-Miller primality test. The context block is simply a + * @rabin@ context. */ -extern void pgen_destroy(pgen */*p*/); +extern pgen_proc pgen_test; -/* --- @pgen_step@ --- * +/*----- Simultaneous primality checking -----------------------------------*/ + +typedef struct pgen_simulprime { + mp *mul, *add; /* Arguments from the client */ + unsigned f; /* Flags, set by client, changed */ +#define PGENF_KEEP 1u /* Keep this prime's value */ +#define PGENF_JUMP 8u /* Use jump table, not stepping */ + pfilt p; /* This prime's filter */ + rabin r; /* Rabin testing context */ + union { + mpw step; /* The simple step to use */ + pfilt *jump; /* The jump to move by */ + mp *x; /* The result, if wanted */ + } u; +} pgen_simulprime; + +typedef struct pgen_simulctx { + pgen_simulprime *v; /* Vector of related primes */ + unsigned n; /* Size of the vector */ + mp *step; /* Basic stepping value */ +} pgen_simulctx; + +/* --- @pgen_simulstep@ --- * * - * Arguments: @pgen *p@ = pointer to prime generation context - * @mpw step@ = how much to step the number + * Step a collection of numbers simultaneously. + */ + +extern pgen_proc pgen_simulstep; + +/* --- @pgen_simultest@ --- * * - * Returns: One of the @PGEN@ constants above. + * Test a collection of numbers simultaneously. + */ + +extern pgen_proc pgen_simultest; + +/*----- Miscellaneous steppers and testers --------------------------------*/ + +typedef struct pgen_gcdstepctx { + pfilt p, jp; /* Prime filter and step filter */ + mp *q, *jq; /* %$p - 1$%, and a step value*/ + mp *r; /* Other argument for GCD */ + mp *g; /* GCD output (must be inited) */ + mp *max; /* Maximum permissible GCD */ +} pgen_gcdstepctx; + +/* --- @pgen_gcdstep@ --- * * - * Use: Steps a number by a small amount. Stepping is much faster - * than initializing with a new number. The test performed is - * the same simple one used by @ptab_create@, so @PGEN_MAYBE@ - * results should be followed up by a Rabin-Miller test. + * Steps @p@ and @q@, until @p@ has no small factors, and + * %$\gcd(p, r) \le max$%. */ -extern int pgen_step(pgen */*p*/, mpw /*step*/); +extern pgen_proc pgen_gcdstep; -/* --- @pgen_jump@ --- * +/*----- Standard event handlers -------------------------------------------*/ + +/* --- @pgen_evspin@ --- * + * + * Displays a spinning baton to show progress. + */ + +extern pgen_proc pgen_evspin; + +/* --- @pgen_ev@ --- * * - * Arguments: @pgen *p@ = pointer to prime generation context - * @pgen *j@ = pointer to another generation context + * Traditional event handler, shows dots for each test. + */ + +extern pgen_proc pgen_ev; + +/* --- @pgen_subev@ --- * * - * Returns: One of the @PGEN@ constants above. + * Subsidiary event handler, mainly for Lim-Lee searches and so on. + */ + +extern pgen_proc pgen_subev; + +/*----- The main driver ---------------------------------------------------*/ + +/* --- @pgen@ --- * + * + * Arguments: @const char *name@ = name of the value being searched for + * @mp *d@ = destination for resulting integer + * @mp *m@ = start value to pass to stepper + * @pgen_proc *event@ = event handler function + * @void *ectx@ = context argument for event andler + * @unsigned steps@ = number of steps to take in search + * @pgen_proc *step@ = stepper function to use + * @void *sctx@ = context argument for stepper + * @unsigned tests@ = number of tests to make + * @pgen_proc *test@ = tester function to use + * @void *tctx@ = context argument for tester + * + * Returns: The resulting value, or null. + * + * Use: A generalized prime-number search skeleton. Yes, that's a + * scary number of arguments. + */ + +extern mp *pgen(const char */*name*/, mp */*d*/, mp */*m*/, + pgen_proc */*event*/, void */*ectx*/, + unsigned /*steps*/, pgen_proc */*step*/, void */*sctx*/, + unsigned /*tests*/, pgen_proc */*test*/, void */*tctx*/); + +/* --- @pgen_primep@ --- * * - * Use: Steps a number by a large amount. Even so, jumping is much - * faster than initializing a new number. The test peformed is - * the same simple one used by @ptab_create@, so @PGEN_MAYBE@ - * results should be followed up by a Rabin-Miller test. + * Arguments: @mp *p@ = a number to check + * @grand *gr@ = a random number source * - * Note that the number stored in the @j@ context is probably - * better off being even than prime. The important thing is - * that all of the residues for the number have already been - * computed. + * Returns: Nonzero if @p@ is really prime. */ -extern int pgen_jump(pgen */*p*/, pgen */*j*/); +extern int pgen_primep(mp */*p*/, grand */*gr*/); /*----- That's all, folks -------------------------------------------------*/