The contracts of the stages of the sieve #
The test for common factors on the 64-bit words of the C code (Ratpoints.Sieve.relprime) decides
whether a numerator is prime to the denominator, and none of its operations leaves the range of a
long. For a numerator a prime to the denominator b with |a| ≤ H, the third stage
(Ratpoints.Sieve.stage3) with the sieve entries of primes 1 < p ≤ 2 ^ 32 with their tables and
reciprocals (Ratpoints.Sieve.SieveEntry.IsPrimeEntry) is the test of the rows of these entries: it
reads the table of each prime at a b⁻¹ mod p, in both branches of the bias, and a prime that
divides b admits every numerator prime to b; the values that the C code holds in longs stay in
range. The exact check (Ratpoints.Sieve.checkPoint) and the points at infinity
(Ratpoints.Sieve.pointsAtInfinity), on a delivery whose flag of the stop is clear, are the
reference of the delivery (Ratpoints.Delivery.deliver) of the lists of the points they deliver for
the flags of the search: the points of the check of the reference, without the point with y < 0
under RATPOINTS_NO_Y, or the one survivor with y = 0 under RATPOINTS_NO_CHECK, mapped back
after a reversal. So the test of a candidate (Ratpoints.Sieve.accepted), for |a| < 2 ^ 63 and
0 < b < 2 ^ 63, followed by the exact check, delivers the points of the check with the flags
(Ratpoints.Sieve.checkNumWith), which is the check of the reference (Ratpoints.Sieve.checkNum)
with the flags of the output clear, for the numerators that survive these entries. The second stage
on a bit array (Ratpoints.Sieve.secondStage), or on one of its words
(Ratpoints.Sieve.secondStageWord), with moduli in the range of the packing and their reciprocals
and the test small of the piece, gives its words and-ed with the rows of all its moduli at their
offsets (Ratpoints.Sieve.andWords), although it stops when the bit array or the word is zero. The
contracts of the loops are @[spec] theorems proved with vcgen, the program logic of Lean core,
with loop invariants that are named definitions.
Main definitions #
Ratpoints.Sieve.RelprimeOddInvariant: the invariant of the loop of the binary algorithm.Ratpoints.Sieve.CheckSpec.admits,Ratpoints.Sieve.Stage3Invariant: whether the third stage lets a numerator through one of its primes, and the invariant of its loop.Ratpoints.Sieve.SieveEntry.IsPrimeEntry: the shape of the sieve entries of the third stage.Ratpoints.Sieve.checkPointList,Ratpoints.Sieve.checkNumWith: the points that the exact check delivers for a numerator with the flags of the search, and the same when the numerator is prime to the denominator, the check of the reference with the flags.Ratpoints.Sieve.acceptedPoints: the points that the extraction delivers for a numerator, those of the exact check when the numerator passes the test of a candidate, the test for common factors and the third stage.Ratpoints.Sieve.pointsAtInfinityList: the points at infinity that the search delivers with the flags of the search.Ratpoints.Sieve.testedCounts: the counts of the tests of a candidate of a list of numerators, the closed form of what the components of the sieve add to the counters (Ratpoints.Sieve.Counters, added field by field).Ratpoints.Sieve.SecondStageInvariant,Ratpoints.Sieve.SecondStageWordInvariant: the invariants of the loops of the second stage on a bit array and on a word, over the moduli with their reciprocals.
Main statements #
Ratpoints.Sieve.relprimeOdd_spec,Ratpoints.Sieve.relprime_spec: the binary algorithm decides whethergcd(m, n) = 1for odd positive wordsmandn, and for wordsm > -2 ^ 63andn ≥ 1.Ratpoints.Sieve.stage3_spec: the third stage is whether all its primes admit the numerator.Ratpoints.Sieve.CheckSpec.index_eq: the residue at which it reads the table of a prime is(a mod p) binv mod p, with the bias and without it.Ratpoints.Sieve.SieveEntry.IsPrimeEntry.admits_checkOf,Ratpoints.Sieve.all_admits_fillChecks: for a numerator prime tobwith|a| ≤ H, a prime entry admits it in the third stage exactly when its row ofbdoes, and the third stage is the survivor test of its entries.Ratpoints.Sieve.accepted_spec: the test of a candidate is the test ofgcd(a, b) = 1followed by the third stage;Ratpoints.Sieve.acceptedPoints_eq_ite: for a numeratorawith|a| ≤ H < 2 ^ 63and a denominator0 < b < 2 ^ 63, the test with the exact check gives the points of the check with the flags (Ratpoints.Sieve.checkNumWith) whenasurvives the entries of the third stage, and none otherwise.Ratpoints.Sieve.snd_run_accepted: the test of a candidate with the count of the numerator before it adds the counts ofRatpoints.Sieve.testedCountsto the counters.Ratpoints.Sieve.checkPoint_eq_deliver,Ratpoints.Sieve.pointsAtInfinity_eq_deliver: the exact check and the points at infinity deliver their lists to the callback, the second call left out after a call that stops the search.Ratpoints.Sieve.checkNumWith_of_noCheck_eq_false,Ratpoints.Sieve.checkNumWith_of_noCheck_eq_true,Ratpoints.Sieve.flatMap_checkNumWith_of_noCheck_eq_false,Ratpoints.Sieve.pointsAtInfinityList_of_noCheck_eq_false,Ratpoints.Sieve.pointsAtInfinityList_of_noCheck_eq_true: the lists with the flags of the output, in terms of the brute-force reference withoutRATPOINTS_NO_CHECK, and the survivors with it.Ratpoints.Sieve.checkNumWith_eq_map,Ratpoints.Sieve.pointsAtInfinityList_eq_map: the lists with the flag of the reversal are those without it, mapped;Ratpoints.Sieve.map_checkNumWith_sublist,Ratpoints.Sieve.map_pointsAtInfinityList: withoutRATPOINTS_NO_CHECKand withRATPOINTS_NO_Y, withyreplaced by0, they are sublists of those underRATPOINTS_NO_CHECK.Ratpoints.Sieve.snd_snd_eq_zero_of_mem_pointsAtInfinityList,Ratpoints.Sieve.fst_eq_and_snd_snd_eq_of_mem_checkNumWith: without the flag of the reversal, the points at infinity havez = 0, and the points of a numeratoraoverbare(a, y, b).Ratpoints.Sieve.secondStage_spec,Ratpoints.Sieve.secondStageWord_spec: the second stage on a bit array, or on one of its words, gives its words and-ed with the rows of all its moduli.
Implementation notes #
The file uses Lean core and Std only, as Ratpoints.Proof.Delivery and Ratpoints.Proof.Words
do; the second stage builds on the words of the rows of the latter
(Ratpoints.Sieve.SieveSpec.wordAt, Ratpoints.Sieve.andWords) and on its reading of the
reciprocals in step with the moduli (Ratpoints.Sieve.eq_magic_and_of_next?_eq_some,
Ratpoints.Sieve.next?_ne_none_of_lt). The proofs use only the facts on the
constants that decide checks next to them, that Ratpoints.mulModLimit < 2 ^ 32 and
Ratpoints.stage3Limit ≤ 2 ^ 32, never their values. The words of the test for common factors are
read as natural numbers by Int64.toNatClampNeg, which is faithful on the non-negative words that
the binary algorithm keeps; the facts on words that are not about the model are in
Ratpoints.Proof.Bits.
The test for common factors #
The invariant of the loop of Ratpoints.Sieve.relprimeOdd, whose state is (m, n): both words
are odd as natural numbers (Int64.toNatClampNeg), and so positive, they have the gcd g of the
operands, and m = n at the exit.
Equations
- One or more equations did not get rendered due to their size.
Instances For
In the loop of Ratpoints.Sieve.relprimeOdd, from m ≠ n, the absolute value of the difference
is a word other than 0, whose lowest set bit RP_CTZL may look for.
A step of the loop of Ratpoints.Sieve.relprimeOdd from m ≠ n, in the shape of the
verification condition: n becomes the smaller of the two and m the odd part of their distance
d, which keep what the loop keeps, and their sum, the measure, decreases.
At the exit of the loop of Ratpoints.Sieve.relprimeOdd, m = n is the gcd g.
The loop ends, since the sum of the two values decreases, and it ends at m = n = gcd(m, n);
no operation leaves the range of a long, since the values stay positive.
The binary algorithm decides whether the numerator m is prime to the denominator n ≥ 1, for
m other than -2 ^ 63, whose negation would leave the range of a long; no operation leaves
it.
The third stage #
Whether the third stage lets the numerator a through the prime of cs: when the prime divides
the denominator (binv = 0), or when its table marks the residue at which the stage reads it
(Ratpoints.Sieve.CheckSpec.index).
Instances For
The invariant of the loop of Ratpoints.Sieve.stage3 over checks, after the checks pref
with the checks suff still to come, on the result of an early return: without one, the checks so
far let a through; with one, at the end, the result is whether all the checks do.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The inverse of the denominator b that Ratpoints.Sieve.checkOf takes from the table t of
the single factor of the sieve entry e of a modulus 0 < p ≤ 2 ^ 32, with the reciprocal of p:
0 when p divides b, and otherwise the entry of t at b mod p, which the reduction by the
reciprocal gives for b ≤ Ratpoints.mulModLimit.
The value a binv + p H that the third stage reduces with the bias p H, for |a| ≤ H and
binv < p, is at most 2 p H - H (sift.c:303), below the bound 2 p H < Ratpoints.stage3Limit
of the bias, and so a long.
The product am binv that the third stage reduces without the bias, of the residue am of the
numerator modulo p and the inverse binv < p, is below p ^ 2 (sift.c:307), a long for the
moduli below 2 ^ 31.
With the bias p H, for |a| ≤ H, binv < p and 2 p H < 2 ^ 32, the value a binv + p H
reduced by the reciprocal of p is the residue of (a mod p) binv: the value is below 2 ^ 32,
and so is p unless a = H = 0.
The residue at which the third stage reads the table of the prime p of cs for the
numerator a with |a| ≤ H is (a mod p) binv mod p, for binv < p, in both branches: with the
bias p H, for 2 p H < 2 ^ 32 and the reciprocal of p, and without it.
The bias of what the third stage needs of the entry e of a prime, when it is not 0, is
p H with 2 p H < 2 ^ 32, and its reciprocal, that of the entry, is that of p when the entry's
is.
The sieve entry e is that of a modulus 1 < p ≤ 2 ^ 32 whose single factor is a table t of
p with inverses of the residues 0 < r < p that are residues 0 < t.inverses[r]! < p, and whose
reciprocal is that of p (Ratpoints.Sieve.magic): the shape that the third stage needs of its
entries (Ratpoints.Sieve.checkOf), whose rows it then tests
(Ratpoints.Sieve.all_admits_fillChecks); the fields of the packing (the bias, the inverses of
Ratpoints.rbaLength and of the strides) do not matter. The entry of a prime with the table of the
reference has it (Ratpoints.Sieve.isPrimeEntry_examinePrime).
Equations
- One or more equations did not get rendered due to their size.
Instances For
The third stage with the entry of a prime 1 < p ≤ 2 ^ 32 whose single factor is its table, of
the shape of Ratpoints.Sieve.SieveEntry.IsPrimeEntry, lets a numerator a prime to b with
|a| ≤ H through exactly when the row of b in the entry admits it: when p divides b, since
then p ∤ a, and otherwise since the stage reads the table at (a mod p) b⁻¹ mod p
(Ratpoints.Sieve.CheckSpec.index_eq).
For a numerator a prime to b with |a| ≤ H, what the third stage needs of the sieve entries
es of the shape of Ratpoints.Sieve.SieveEntry.IsPrimeEntry, with the reciprocals of their
moduli, lets a through exactly when a survives these entries.
The test of a candidate #
The test for common factors on the words of the numerator |a| < 2 ^ 63 and the denominator
0 < b < 2 ^ 63 is the test on the integers, and the thunk of the third stage is forced only when
the numerator is prime to b.
The test of a candidate as its value: the walks through the set bits of a word read it so, and
their contracts need none of the hypotheses of Ratpoints.Sieve.accepted_spec.
For |a| ≤ H < 2 ^ 63, a denominator 0 < b < 2 ^ 63 and the thunk of what the third stage
needs of the sieve entries es of the shape of Ratpoints.Sieve.SieveEntry.IsPrimeEntry, with the
reciprocals of their moduli, for b and H, a numerator goes on to the exact check when it is
prime to b and survives these entries.
The counters #
The counters c and k (Ratpoints.Sieve.Counters) added field by field, wrapping as the
UInt64s do: the counts of two pieces of work of the sieve, one after the other, as
Ratpoints.Sieve.RunCounts.fold adds those of a block to those of the run.
Equations
- One or more equations did not get rendered due to their size.
The counts of the tests of a candidate (Ratpoints.Sieve.accepted) of the numerators as over
the denominator b, with the thunk checks of the third stage, each numerator counted in bits
before its test, as the walk through the set bits of a word counts them
(Ratpoints.Sieve.walkWord): bits the number of the numerators, coprime the number of those
prime to b on the words of the C code (Ratpoints.Sieve.relprime), and checks the number of
those that pass the third stage too, each as a UInt64, wrapping.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The counts of the test of a candidate, with the count of the numerator in bits before it as
the walk through the set bits of a word counts it (Ratpoints.Sieve.walkWord).
The counters c' after the test of a candidate of a, with its count in bits before it, in
the shape of the verification conditions of the walk through the set bits of a word.
The exact check #
One call of the callback with the point (a : y : b), mapped back after a reversal, on a
delivery whose flag is clear, is the delivery of that point mapped by Ratpoints.Sieve.swapPoint
when rev is set.
The points that the exact check (Ratpoints.Sieve.checkPoint) of the numerator a over the
denominator b delivers to a callback that does not stop the search, for the products w, the
factor f and the flags fl: unless fl.noCheck, the points (a, y, b) and, for y ≠ 0,
(a, -y, b) when the value v of Horner's rule in a on w, times f, is y ^ 2 with y ≥ 0
(Ratpoints.BruteForce.pointsAbove), the point with y < 0 left out when fl.noY is set; with
fl.noCheck, the one survivor (a, 0, b); each mapped by Ratpoints.Sieve.swapPoint when the flag
fl.reversed of the reversal is set.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The exact check on a delivery whose flag is clear delivers the points of
Ratpoints.Sieve.checkPointList, the call with -y left out after a call that stops the search.
The check of the numerator a over the denominator b with the flags fl: the points of
Ratpoints.Sieve.checkPointList when a is prime to b, and none otherwise. With the flags
RATPOINTS_NO_CHECK and RATPOINTS_NO_Y clear, it is the check of the reference
(Ratpoints.Sieve.checkNumWith_of_noCheck_eq_false).
Equations
- Ratpoints.Sieve.checkNumWith w f b fl a = if a.gcd b = 1 then Ratpoints.Sieve.checkPointList w f b fl a else []
Instances For
Without RATPOINTS_NO_CHECK, the check with the flags is the check of the reference with the
flag of the reversal, without the points with y < 0 under RATPOINTS_NO_Y.
Under RATPOINTS_NO_CHECK, the check with the flags gives the survivor (a, 0, b) of a
numerator prime to b, mapped after a reversal.
The check with the flags gives the points of the check without the flag of the reversal, mapped
by Ratpoints.Sieve.swapPoint when it is set.
Without the flag of the reversal, the points of the check with the flags of the numerator a
over b are (a, y, b).
Without RATPOINTS_NO_CHECK and with RATPOINTS_NO_Y, the check of a numerator a over b
gives at most one point, the one with y ≥ 0; with y replaced by 0 it is the survivor that the
check gives under RATPOINTS_NO_CHECK.
The points that the extraction delivers for the numerator a over the denominator b: those of
the exact check (Ratpoints.Sieve.checkPointList, with the thunk w of the products, the degree
d and the flags fl) when a passes the test of a candidate (Ratpoints.Sieve.accepted, with
the thunk checks of the third stage), and none otherwise.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The points of Ratpoints.Sieve.acceptedPoints, the test of Ratpoints.Sieve.accepted followed
by the exact check, are those of the check with the flags Ratpoints.Sieve.checkNumWith for a
numerator a with |a| ≤ H < 2 ^ 63 that survives the sieve entries es of the third stage, of
the shape of Ratpoints.Sieve.SieveEntry.IsPrimeEntry, and none for the others, for a denominator
0 < b < 2 ^ 63.
The exact check of a numerator that passes the test of a candidate, on a delivery whose flag is
clear, delivers the points of Ratpoints.Sieve.acceptedPoints.
A numerator that does not pass the test of a candidate has no points to deliver.
Without RATPOINTS_NO_CHECK, the checks with the flags of the numerators xs over b give the
points of the brute-force reference, mapped by Ratpoints.Sieve.swapPoint after a reversal,
without those with y < 0 under RATPOINTS_NO_Y.
The points at infinity #
The points that Ratpoints.Sieve.pointsAtInfinity delivers to a callback that does not stop the
search, for the polynomial of degree d with the coefficient list c and the flags fl: when
there are points at infinity, for odd d or c_d a square (Ratpoints.Setup.isSquare), with
fl.noCheck or odd d the point (1, 0, 0), and otherwise (1, s, 0) for s = √c_d followed,
unless fl.noY, by (1, -s, 0); each mapped by Ratpoints.Sieve.swapPoint to (0, y, 1) when the
flag fl.reversed of the reversal is set.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The points at infinity on a delivery whose flag is clear deliver the points of
Ratpoints.Sieve.pointsAtInfinityList, the call with -√c_d left out after a call that stops the
search.
Without RATPOINTS_NO_CHECK, for odd d or c_d ≠ 0, the points at infinity delivered are
those of the candidate (1, 0) with the value F(1, 0), which is c_d for even d and 0 for
odd d, without the point with y < 0 under RATPOINTS_NO_Y, and mapped after a reversal. (For
even d and c_d = 0, which the search refuses before, the point (1 : 0 : 0) is delivered
twice, once under RATPOINTS_NO_Y.)
Under RATPOINTS_NO_CHECK, the points at infinity delivered are the one survivor (1, 0, 0),
mapped after a reversal, when there are points at infinity.
The points at infinity are those without the flag of the reversal, mapped by
Ratpoints.Sieve.swapPoint when it is set.
Without the flag of the reversal, the points at infinity that the search delivers have
z = 0.
Without RATPOINTS_NO_CHECK and with RATPOINTS_NO_Y, the points at infinity, with y
replaced by 0, are those under RATPOINTS_NO_CHECK.
The second stage #
The invariant of the loop of Ratpoints.Sieve.secondStage over the moduli specs and their
reciprocals mgs on the bit array nums with the word number i, after the moduli pref, whose
state is the bit array and the reciprocals still to come: before the loop has gone through all the
moduli, these are the reciprocals after the first pref.length; and word κ of the bit array is
word κ of nums and-ed with the row words of the moduli of pref.
Equations
- One or more equations did not get rendered due to their size.
Instances For
At the stop the bit array is zero, and so is its and with the rows of the other moduli.
A step of the loop of Ratpoints.Sieve.secondStage: the bit array and-ed with bit array
(i + offset) mod p of the row of the next modulus s, the index that the reduction by the
reciprocal of the cursor gives under the test small
(Ratpoints.Sieve.SieveSpec.Fits.ite_mulMod_modLong_eq_toNat_emod).
The stop when the bit array is zero loses nothing, since a zero bit array stays zero; the reciprocals run in step with the moduli and do not run out before them.
The invariant of the loop of Ratpoints.Sieve.secondStageWord over the moduli specs and their
reciprocals mgs on word κ of the bit array with the word number i, from the word x0 on,
after the moduli pref, whose state is the word and the reciprocals still to come: before the loop
has gone through all the moduli, these are the reciprocals after the first pref.length; and the
word is x0 and-ed with the row words of the moduli of pref.
Equations
Instances For
A step of the loop of Ratpoints.Sieve.secondStageWord, as for
Ratpoints.Sieve.SecondStageInvariant.andBitArray.
At the stop the word is zero, and so is its and with the rows of the other moduli.
The stop when the word is zero loses nothing, since a zero word stays zero; the reciprocals run in step with the moduli and do not run out before them.