=head1 NAME Catacomb::MP::Prime - prime number generation =head1 SYNOPSIS use Catacomb qw(:const :mp :random :pgen); $p = newprime($nbits, [$rng]); $filt = Catacomb::MP::Prime::Filter->new($x); $filt = $x->filter(); $rc = $filt->status(); $x = $filt->m(); $rc = $filt->step($n); $rc = $filt->jump($jfilt); $newfilt = $filt->muladd($mul, $add); # integers $stepper = Catacomb::MP::Prime::Filter->stepper($step); # integer $stepper = filterstepper($step); $jumper = Catacomb::MP::Prime::Filter->stepper($jump); # MP $jumper = filterjumper($jump); $rabin = Catacomb::MP::Prime::Rabin->new($m); $rabin = $p->rabin(); $m = $rabin->m(); $rc = $rabin->test($wit); $n = $rabin->iters(); $n = Catacomb::MP::Prime::Rabin->ntests($bits); $tester = Catacomb::MP::Prime::Rabin->tester(); $tester = $rabintester; $events = Catacomb::MP::Prime::Gen::Proc->ev(); $events = Catacomb::MP::Prime::Gen::Proc->evspin(); $events = Catacomb::MP::Prime::Gen::Proc->subev(); $p = Catacomb::MP::Prime->gen ($name, $x, $nsteps, $stepper, $ntests, $tester, [$events]); $p = primegen ($name, $x, $nsteps, $stepper, $ntests, $tester, [$events]); if (($x, $j) = Catacomb::MP::Prime->strongprime_setup ($name, $nbits, [$rng], [$nsteps], [$subevents])) { $p = Catacomb::MP::Prime->gen ($name, $x, $nsteps, $j, $ntests, $tester, [$events]); } ($p, @f) = Catacomb::MP::Prime->limlee ($name, $qbits, $pbits, [$rng], [$on], [$oev], [$iev]); ($p, @f) = limleegen ($name, $qbits, $pbits, [$rng], [$on], [$oev], [$iev]); package MyPrimeGenObject; sub new { ... }; sub BEGIN { ... }; sub TRY { ... }; sub FAIL { ... }; sub PASS { ... }; sub DONE { ... }; sub ABORT { ... }; $name = $ev->name(); $x = $ev->m([$xx]); $rng = $ev->rand(); =head1 DESCRIPTION The B and related packages provide a framework for generating prime numbers of various special forms. Read Catacomb::MP(3) for more information about Catacomb's multiprecision integer support. =head2 Simple functions =over =item BIB<,> [I]B<)> Returns a random prime between 2^I and 2^(I+1) (unless you're very unlucky). Here, I must be a random number generator object: see Catacomb::Crypto(3). =back =head2 Result codes The following result codes are used by various of the prime-number generation functions. They may be imported using the B<:consts> tag. =over =item B About to test a new candidate prime discovered by filtering. This shouldn't be returned by functions, but it is used as part of the event-handling system. =item B A new candidate has been found by a filter, but has not yet passed a primality test. =item B The number is definitely composite. =item B The number has passed at least one primality test, and is therefore likely to be prime. =item B The number is definitely prime. =item B The search for a prime number has been aborted. =back =head2 Filtering for small primes The class B implements a relatively efficient technique for finding numbers with no small factors. =over =item IB<-Esmallfactor()> Returns B if I is definitely prime (and therefore fairly small), B if it has some small factor, or B if it has no small factors but might be composite anyway. =item Bnew(>IB<)> =item IB<-Efilter()> Returns a new small-primes filter, initially looking at the number I. =item IB<-Em()> Returns the current number I in the filter. =item IB<-Estatus()> Returns the state (a B code) for the current number I in the filter. This will usually be B if I has a small factor, or B if not; though B is also possible if I is small enough. =item IB<-Estep(>IB<)> Advances the number in the filter by a small step I, returning the new status. =item IB<-Ejump(>IB<)> Advances the number in the filter by a large jump, as represented by another filter I. This is useful for finding a prime which has the form I I + I for some other prime I -- store 2 I in a filter and use it as a jump to search for another prime. =item IB<-Emuladd(>IB<,> IB<)> Returns a new filter whose number is I I + I. =back =head2 Miller-Rabin primality tests Catacomb's main primality test is the Miller-Rabin test. It is a probabilistic test, with a 1/4 probability that any particular test will fail to recognize a given number as being composite. However, it is important to observe that this is not the same as the probability that a random number is composite given that it passed a test -- this latter is much smaller. =over =item Bnew(>IB<)> =item IB<-Erabin()> Constructs a new Rabin-Miller testing context for the purpose of testing the candidate I. Returns B if I is negative or even. =item IB<-Em()> Returns the integer under test in the given context. =item IB<-Etest(>IB<)> Tests I with witness I. Returns B or B. The witness should usually be chosen randomly. =item IB<-Eiters()> Returns the recommended number of tests for the candidate under test, assuming that we came across the candidate at random. =item Bntests(>IB<)> Returns the recommended number of tests for a candidate which is I bits long, assuming that we came across the candidate at random. =back =head2 Prime generation concepts The prime generator is based on the concepts of I, I and I. =over =item * Steppers are responsible for producing candidate primes, and (usually) testing them for small factors (e.g., using B). A stepper is expected to be relatively fast, and leave the heavy lifting to testers. =item * Testers are responsible for applying primality tests to candidates. =item * Event handlers report interesting events during prime generation, to maintain a progress display or similar. =back These various kinds of objects all have essentially the same interface, which is built from I. An event contains all the useful information about the current progress of a prime generation task. Events are objects of type B, though fortunately one rarely needs to type this. Event objects can't be created by Perl code. =over =item IB<-Ename()> Returns the name of the prime being generated. =item IB<-Em(>[I]B<)> Returns the current candidate prime. If I is supplied then it sets a new candidate prime. This is used by the stepper interface. =item IB<-Esteps()> Returns the number of steps remaining before the generation task fails. =item IB<-Etests()> Returns the name of tests remaining before the generation task succeeds. =item IB<-Erand()> Returns a pseudorandom number generator which is likely to be fast but not cryptographically strong. =back =head2 Built-in steppers and testers =over =item Bstepper(>IB<)> =item BIB<)> Returns a stepper object which steps on by I (a small Perl integer) until it finds a number with no small prime factors. =item Bjumper(>IB<)> =item IB<-Ejumper()> Returns a jumper object which jumps on by I (a large multiprecision integer) until it finds a number with no small prime factors. =item Btester()> Returns a tester object which applies an iteration of the Miller-Rabin probabilistic primality test. In fact, there only needs to be one of these, so it's called B<$rabintester>. =item Bev()> A standard event handler which prints the name of the prime being generated and a string of C<.> and C<+> signs for failures and successes, such as is relatively commonplace. In fact, there only needs to be one of these, so it's called B<$pg_events>. =item Bevspin()> An event handler which shows a spinning baton while it works. This is mainly used as the subsidiary event handler when generating Lim-Lee primes. There only needs to be one of these, so it's called B<$pg_evspin>. =item Bsubev()> An event handler which works like B above, but puts square brackets around its output. Also suitable for use in Lim-Lee generation. There only needs to be one of these, so it's called B<$pg_subev>. =back =head2 Prime generation Prime generation is driven by the procedure Bgen()>, which is also named B for convenience. =over =item Bgen(>IB<,> IB<,> IB<,> IB<,> IB<,> IB<,> [I]B<)> =item BIB<,> IB<,> IB<,> IB<,> IB<,> IB<,> [I]B<)> Generates a prime number. It will start with the integer I, and run the I for at most I times (infinitely if I is zero), returning B if it fails. Each time the stepper reports a plausible candidate, it runs the tester up to I times; it returns the candidate if all these tests succeeded. It will call the event handler after each step and test. =back =head2 Writing your own steppers, testers and event handlers As mentioned, steppers, testers and event handlers have similar interfaces. Each is represented by an object whose class is a descendent (via B<@ISA>) of B. The prime generator will call methods on your object as required. Event handlers are the easiest, so we deal with them first. All methods are called with one argument which is the event object. The methods called are as follows. =over =item B Prime generation has begun. =item B About to start testing a new number. =item B Number passed a primality test. =item B Number failed a primality test. =item B Prime number found successfully. =item B No prime number found; we gave up. =back Any of these methods may return B (-1) to abandon prime searching. This is intended to be used, for example, by a progress dialogue box if its cancel button is pressed. Any other value is ignored. Here's a simple example of an event handler. package Strange::Events; @ISA = qw(Catacomb::MP::Prime::Gen::Proc); sub new { bless {}, $_[0]; } sub PG_BEGIN { my ($me, $ev) = @_; local $| = 1; print $ev->name(), " ["; } sub PG_PASS { local $| = 1; print "*"; } sub PG_FAIL { local $| = 1; print "."; } sub PG_ABORT { local $| = 1; print "] :-(\n"; } sub PG_DONE { local $| = 1; print "]\n"; } Steppers use fewer methods, but are a bit more involved. =over =item B Initialize the stepper. Read the starting point from the event, or store a new starting point, as appropriate. Return B if the starting point is satisfactory, B for failure, or B to run the tester. =item B Advance the stepper. Write the new number to the event. Return as for B. =item B All is over. Tidy up. =back Testers are similar. =over =item B Initialize the tester. Read the starting point from the event. Return B if the starting point is satisfactory, B if you've actually run a successful test, B to reject the candidate, or B to proceed to testing. =item B Run a test. Return B if the number is satisfactory, B if it passed a test, or B if it failed. =item B Testing is done. Tidy up. =back Finally, any method can return B to stop prime generation in its tracks almost immediately. (The B methods are still called for the stepper, and for the tester if it's active.) It's probably best to do tidying in B rather than leaving it until B, since testers and steppers and things may get left around for a while, espectially if they're simple. Since steppers and testers often work together, here's an example of a pair for generating I. A prime number I is Sophie-Germain prime if 2 I + 1 is also prime. We work by maintaining separate filters and testing contexts for I and 2 I + 1, and checking both in parallel. Generating Sophie Germain primes is a long job. package SophieGermain::Stepper; use Catacomb qw(:const :mp :pgen); @ISA = qw(Catacomb::MP::Prime::Gen::Proc); sub new { bless [undef, undef], $_[0]; } sub _step { my ($me, $ev) = @_; while ($me->[0]->status() == PGEN_FAIL || $me->[1]->status() == PGEN_FAIL) { $me->[0]->step(2); $me->[1]->step(4); } $ev->m($me->[0]->m()); return PGEN_TRY; } sub PG_BEGIN { my ($me, $ev) = @_; my $x = $ev->m(); $me->[0] = $x->filter(); $me->[1] = (2*$x + 1)->filter(); _step($me, $ev); } sub PG_TRY { my ($me, $ev) = @_; $me->[0]->step(2); $me->[1]->step(4); _step($me, $ev); } sub PG_DONE { my ($me, $ev) = @_; $me->[0] = $me->[1] = undef; } package SophieGermain::Tester; use Catacomb qw(:const :mp :pgen); @ISA = qw(Catacomb::MP::Prime::Gen::Proc); sub new { bless [undef, undef], $_[0]; } sub PG_BEGIN { my ($me, $ev) = @_; my $x = $ev->m(); $me->[0] = $x->rabin(); $me->[1] = (2*$x + 1)->rabin(); return PGEN_TRY; } sub _test { my ($r, $rabin) = @_; my $w = $r->mprange($rabin->m()); return $rabin->test($w) == PGEN_PASS; } sub PG_TRY { my ($me, $ev) = @_; my $r = $ev->rand(); return _test($r, $me->[0]) && _test($r, $me->[1]) ? PGEN_PASS : PGEN_FAIL; } sub PG_DONE { my ($me, $ev) = @_; $me->[0] = $me->[1] = undef; }