The contracts of the packing #
The packing of the numerators of each class of the denominators modulo 64 into one class modulo a
power of 2 (Ratpoints.Model.Packing), as @[spec] theorems proved with vcgen, the program logic
of Lean core, with loop invariants that are named definitions. The class of the word w of the
admissible numerators modulo 64 of a class of denominators packs it
(Ratpoints.Sieve.NumClass.Packs): its stride 2 ^ k is that of a packing, k ≤ 6 and
k < Ratpoints.numStrides, every set bit of w lies in the class a₀ mod 2 ^ k, and its pattern
has the bit of the numerator a₀ + 2 ^ k t at t, so that the class word lets the numerator of a
bit through exactly when the pattern has the bit, and lets nothing off the class through. The loop
over the 64 classes makes such classes, with no row offsets yet, and the word den_bits of the
classes whose word is not 0. The number of the packings counts the first class of each key
2 ^ k + a₀ among the classes with a pattern (Ratpoints.Sieve.firstKeys). The row offsets of the
packings read, of each sieve entry, an odd modulus 1 < p ≤ Ratpoints.maxPrimeEven with its
reciprocal, the inverse of Ratpoints.rbaLength modulo p and the bias, the least multiple of p
from Ratpoints.rowBias on, as examine_prime, make_power and make_modulus set them
(Ratpoints.Sieve.SieveEntry.Packable), which the sieve entry of a modulus has
(Ratpoints.IsModulusEntry); they give each class with a pattern a row of the array of the
offsets, with the offset of its packing for each sieve entry
(Ratpoints.Sieve.SieveEntry.PackedFor): between Ratpoints.rowBias and Ratpoints.rowBias + 2 p,
a₀ (2 ^ k Ratpoints.rbaLength)⁻¹ modulo p, with the inverse of the stride modulo p in the
entry. fill_bp_list divides the denominator by the stride modulo each modulus, exactly in each of
its branches, since its products stay below 2 ^ 64 / p.
Main definitions #
Ratpoints.Sieve.NumClass.numerator: the numeratora₀ + 2 ^ k jof bitjof a class.Ratpoints.Sieve.NumClass.WF,Ratpoints.Sieve.NumClass.Packs: the stride and the residue of a packing, and a class that packs a word of numerators modulo 64.Ratpoints.Sieve.NumClass.key,Ratpoints.Sieve.IsFirstKey,Ratpoints.Sieve.firstKeys: the key2 ^ k + a₀of a packing, and the number of the distinct packings of the classes belown.Ratpoints.Sieve.halveIter,Ratpoints.Sieve.halveChain: the halvings modulo an odd modulus.Ratpoints.Sieve.classOffset: the offset of the row of a class for a sieve entry.Ratpoints.Sieve.SieveEntry.Packable,Ratpoints.Sieve.SieveEntry.PackedFor,Ratpoints.Sieve.OffsetsFor: the fields of a sieve entry that the row offsets of the packing read, the offset of the packing of a class for an entry, and the rows of offsets of all the classes with a pattern.
Main statements #
Ratpoints.Sieve.NumClass.Packs.classBit_bits,Ratpoints.Sieve.NumClass.Packs.emod_eq_of_classBit,Ratpoints.Sieve.NumClass.Packs.bits_eq_zero_iff: the pattern lets bitjthrough exactly when the word lets the numerator ofjthrough, the word lets nothing off the class through, and the pattern is0exactly when the word is;Ratpoints.Sieve.NumClass.Packs.filter_filter_emod: so the numerators that the word lets through are among those of the class;Ratpoints.Sieve.NumClass.Packs.bits_bne_zero: the test of the pattern is the test of the word.Ratpoints.Sieve.getLsbD_classMasks: the masks of the strides,0beyond the seven ofk ≤ 6.Ratpoints.Sieve.packPattern_spec,Ratpoints.Sieve.numClasses_spec: the packed pattern, and the classes of the 64 words withden_bits.Ratpoints.Sieve.numPackings_spec: the number of the packings is that of the distinct keys, at least 1.Ratpoints.Sieve.classRows_spec,Ratpoints.Sieve.classOffsets_spec: the rows of offsets of the classes and the inverses of the strides in the entries.Ratpoints.Sieve.SieveEntry.PackedFor.fits: the sieve spec of an entry with the offset of the packing of a class and the closed form of a row fits the reductions of the row indices of the first two stages and the chunked first stage.Ratpoints.Sieve.fillBpList_eq_map: the residues of the denominator divided by the stride.
Implementation notes #
The file uses Lean core and Std only, so that the contracts of the sieve, in files without
Mathlib, can use it. The proofs use only the facts on the constants that decide checks next to
them, never their values: here that Ratpoints.numStrides ≥ 1, that Ratpoints.maxBitsInPrime ≤ 10
(Ratpoints.maxPrimeEven_le_two_pow_10) and that Ratpoints.mulModLimit < 2 ^ 32; that the masks
of the strides beyond k = 6 are 0 is read with the default of the array. The facts on words that
are not about the model are in Ratpoints.Proof.Bits, those on natural numbers and integers in
Ratpoints.Proof.Containers. The bounds of the products of fill_bp_list and of class_offsets
are in Ratpoints.Proof.Reductions, the bits of an interval of numerators and the other range
lemmas of the longs of the packing in Ratpoints.Proof.BitRange.
Residues modulo 64 and the strides of the packing #
The classes #
The stride and the residue of a class are those of a packing: the stride exponent below
Ratpoints.numStrides and at most 6, the residue below the stride. The keys 2 ^ k + a₀ of such
packings are below 2 ^ Ratpoints.numStrides and 128.
The stride exponent is below
Ratpoints.numStrides.The stride is at most
2 ^ 6, the modulus 64 of the 2-adic information.The residue is below the stride.
Instances For
The class cl packs the word w of the numerators modulo 64 of a class of denominators: its
stride and residue are those of a packing (Ratpoints.Sieve.NumClass.WF), every set bit a < 64
of w is a₀ modulo 2 ^ k, and bit t of the pattern is bit (a₀ + 2 ^ k t) mod 64 of w.
Every set bit of the word lies in the class
a₀ mod 2 ^ k.- getLsbD_bits (t : Nat) : t < 64 → cl.bits.toBitVec.getLsbD t = w.toBitVec.getLsbD ((cl.a0 + 2 ^ cl.k * t) % 64)
Bit
tof the pattern is the bit of the numerator of bitt.
Instances For
The numerators in the class a₀ mod 2 ^ k of a list that the class word w and a test p let
through are those of the list that they let through, since the class word lets nothing off the
class through.
The test EXT0(cl->bits) of the C code on a class that packs the word w is the test w ≠ 0:
the classes with a pattern are those whose word admits a numerator, the classes of den_bits.
Ratpoints.Sieve.NumClass.Packs reads only the pattern, the stride and the residue of the
class, not its row offsets.
The masks of the strides #
A mask beyond the seven of the strides k ≤ 6 is read as 0.
The test of the loop over the strides of Ratpoints.Sieve.numClasses at k lets the loop go
on only for k ≤ 6, where the masks are not 0, and when every set bit of w ≠ 0 is
≡ c (mod 2 ^ k).
The pattern of a class #
The invariant of the loop of Ratpoints.Sieve.packPattern over the set bits of w: the packed
word after the set bits below n, bit t set exactly when some set bit j < n has the place
t.
Equations
Instances For
The invariant of the doubling loop of Ratpoints.Sieve.packPattern, from the packed word p0
of period 64 / 2 ^ k: the shift s = 2 ^ j, from 64 / 2 ^ k up to 64, and bit t of the word
the bit t mod (64 / 2 ^ k) of p0 below s.
Equations
- One or more equations did not get rendered due to their size.
Instances For
At the exit of the packing loop the packed word has its bits below 64 / 2 ^ k.
The bit of the packed pattern at t, read off the set bits of w: some set bit j has its
place t mod (64 / 2 ^ k) exactly when bit (a0 + 2 ^ k t) mod 64 of w is set.
The packed word at the exit of the loops of Ratpoints.Sieve.packPattern.
Bit t of the packed pattern of w for the stride 2 ^ k, k ≤ 6, and the residue
a₀ = c mod 2 ^ k of all the set bits of w is bit (a₀ + 2 ^ k t) mod 64 of w.
The classes of the 64 words #
A class of the stride 2 ^ k, k ≤ 6 and k < Ratpoints.numStrides, with the residue
c mod 2 ^ k of all the set bits of w and the pattern of bit t the bit (a₀ + 2 ^ k t) mod 64
of w packs w.
The invariant of the loop over the strides of Ratpoints.Sieve.numClasses for the word w with
its lowest set bit c: the stride exponent k from 1 up to Ratpoints.numStrides and 7, and every
set bit of w ≡ c (mod 2 ^ (k - 1)).
Equations
- Ratpoints.Sieve.StrideInvariant w c = Std.WP.WhileInvariant.mk fun (x : Bool) (k : Nat) => 1 ≤ k ∧ k ≤ Ratpoints.numStrides ∧ k ≤ 7 ∧ Ratpoints.Sieve.ClassOf w c (k - 1)
Instances For
The loop over the strides goes on at k: k ≤ 6 and every set bit ≡ c (mod 2 ^ k).
The class after the loop over the strides packs the word, with the pattern w itself for
k = 1 and with the packed pattern packed otherwise.
The invariant of the loop over the classes of Ratpoints.Sieve.numClasses after the classes
below n: each packs its word and has no row offsets yet, and the word den_bits has the bits of
the classes below n whose word is not 0.
Equations
Instances For
The class cur set to cl, which packs its word, and its bit put into den_bits if its word
is not 0.
Each class packs its word of the 2-adic information and has no row offsets yet, and the word
den_bits has the bit of each class whose word is not 0, as Ratpoints.Sieve.denBits has.
Each class that Ratpoints.Sieve.numClasses makes packs its word of the 2-adic information
(Ratpoints.Sieve.numClasses_spec).
The fields of the sieve entries #
The fields of a sieve entry that the row offsets of the packing read: an odd modulus
1 < p ≤ Ratpoints.maxPrimeEven with its reciprocal, the inverse rbainv < p of
Ratpoints.rbaLength modulo p, and the bias, a multiple of p from Ratpoints.rowBias to below
Ratpoints.rowBias + p, as examine_prime, make_power and make_modulus set them.
The modulus is above 1.
The modulus is odd.
The modulus is at most
Ratpoints.maxPrimeEven.The reciprocal is that of the modulus.
rbainvis the inverse ofRatpoints.rbaLengthmodulo the modulus.rbainvis below the modulus.The bias is a multiple of the modulus.
The bias is at least
Ratpoints.rowBias.The bias is below
Ratpoints.rowBias + p.
Instances For
The number of the packings #
Whether the class b of cls is the first with a pattern whose packing has its key.
Equations
Instances For
Equations
- One or more equations did not get rendered due to their size.
The number of the distinct packings of the classes below n with a pattern, the classes that
are the first with their key.
Equations
- Ratpoints.Sieve.firstKeys cls n = (List.filter (fun (b : Nat) => decide (Ratpoints.Sieve.IsFirstKey cls b)) (List.range n)).length
Instances For
The invariant of the loop of Ratpoints.Sieve.numPackings after the classes below n: the two
words seen mark the keys of the classes below n with a pattern, and the count is the number of
their distinct packings.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The test of num_packings at the class cur, that it has a pattern and that seen does not
mark its key, is whether it is the first class with its key.
A class that is the first with its key gets its key marked and is counted.
A class that is not the first with its key leaves the marks and the count as they are.
The rows of the packings #
The offset of the row of the packing of the class cl for the n-th modulus p of the sieve
entries es, from the inverse rinv[n][k] of 2 ^ k Ratpoints.rbaLength modulo p: the remainder
of a₀ rinv[n][k] by a multiplication with the reciprocal of the entry, plus its bias, as
class_offsets computes it.
Equations
Instances For
The invariant of the loop of Ratpoints.Sieve.classRows over the classes after those below
m, for the classes cls it starts from and the sieve entries es with the inverses rinv, rows
of np offsets: the state is the classes cls', the array of the offsets o, the table of the
rows rowOf at the keys of the packings and the number rows of rows made.
The array of the offsets keeps its size.
The table of the rows keeps its
2 ^ Ratpoints.numStridesentries.One row is made for each distinct packing of the classes below
mwith a pattern.The classes from
mon are as they were.- entry (b : Nat) : b < m → (cls'[b]! = let __src := cls[b]!; { bits := __src.bits, k := __src.k, a0 := __src.a0, offset := cls'[b]!.offset }) ∧ (cls[b]!.bits ≠ 0 → ∃ (r : Nat), r < rows ∧ cls'[b]!.offset = some (r * np) ∧ rowOf[cls[b]!.key]! = some (r * np) ∧ ∀ (n : Nat), n < np → o[r * np + n]! = classOffset es rinv cls[b]! n)
Each class below
mchanges only in its row offsets, and one with a pattern has the row of its packing, at a positionr npfor somer < rows, which the table of the rows holds at its key and whosenpoffsets are those of the class. - exists_of_isSome (K : Nat) : rowOf[K]!.isSome = true → ∃ (b : Nat), b < m ∧ cls[b]!.bits ≠ 0 ∧ cls[b]!.key = K
The table holds a row only at the key of a class below
mwith a pattern.
Instances For
The invariant of the loop of Ratpoints.Sieve.classRows that writes the row of the class cl
at the position row into the array of the offsets o₀, after the moduli below j: the array
keeps its size, and holds the offsets of the class for these moduli at their positions in the
array.
Equations
- One or more equations did not get rendered due to their size.
Instances For
A class without a pattern is stepped over: it is not the first with its key, and it keeps its offsets.
A key with a row is the key of an earlier class with a pattern, whose row it is: a class with that key is not the first with it, and its row holds its offsets, since the earlier class has the same stride and residue.
A class with a pattern whose key has a row already gets that row: an earlier class has its key, so it is not the first with it, and has the same stride and residue, so the same offsets.
The class cur with a pattern whose key has no row is the first with its key: an earlier class
with its key would have put its row into the table.
The first class with its key gets the row rows, which the array has room for when it has room
for a row for each distinct packing.
A class with a pattern whose key has no row gets a new row, after the rows made so far: it is the first with its key, and the earlier rows keep their offsets.
Each class with a pattern gets the row of its packing, whose offset for the n-th modulus is
Ratpoints.Sieve.classOffset, when the array of the offsets has room for a row of np offsets for
each distinct packing; the classes keep their patterns, strides and residues.
The offsets of the rows #
x halved n times modulo p (Ratpoints.Sieve.halve).
Equations
- Ratpoints.Sieve.halveIter p 0 x✝ = x✝
- Ratpoints.Sieve.halveIter p n.succ x✝ = Ratpoints.Sieve.halve (Ratpoints.Sieve.halveIter p n x✝) p
Instances For
The chain of halvings of x modulo p of class_offsets, x, x / 2, … modulo p, n of
them.
Equations
- Ratpoints.Sieve.halveChain p n x = List.map (fun (x_1 : Nat) => Ratpoints.Sieve.halveIter p x_1 x) (List.range n)
Instances For
The offset off of the row of the packing of the class cl for the sieve entry e with its
inverses of the strides: off lies between Ratpoints.rowBias and Ratpoints.rowBias + 2 p, it
shifts the rows so that bit t of the bit array with the word number w stands for the numerator
a₀ + 2 ^ k (Ratpoints.rbaLength w + t) (off 2 ^ k Ratpoints.rbaLength ≡ a₀ (mod p)), and the
inverse of the stride 2 ^ k modulo p is entry k of dinv.
The modulus is positive.
The modulus is at most
Ratpoints.maxPrimeEven.The offset is at least
Ratpoints.rowBias.The offset is below
Ratpoints.rowBias + 2 p.The offset times
2 ^ k Ratpoints.rbaLengthis the residuea₀modulo the modulus.Entry
kofdinvis the inverse of2 ^ kmodulo the modulus.Entry
kofdinvis below the modulus.
Instances For
Ratpoints.Sieve.SieveEntry.PackedFor reads only the stride and the residue of the class, not
its row offsets.
The sieve spec of a modulus with the offset of the packing of a class, the closed form of a row
of the entry and the end p has the modulus and the offset in the range that the reductions of the
row indices need, and the copies of the first bit arrays of its row
(Ratpoints.Sieve.SieveEntry.wraps_closedRow).
Every class with a pattern among cls has a row of offsets in the array offsets, at the
position pos that it holds, with the offset for the n-th sieve entry of es at pos + n.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The rows of offsets of the classes for the sieve entries es serve the first k of them.
The offset that class_offsets computes for the class cl and the sieve entry e, from the
inverse of 2 ^ k Ratpoints.rbaLength that the halvings give, is that of the packing.
The loops of the row offsets #
The invariant of the loop of Ratpoints.Sieve.classOffsets that finds the largest stride
exponent: the classes below m with a pattern have stride exponents at most kmax.
Equations
Instances For
The invariant of the loop over the halvings of Ratpoints.Sieve.classOffsets for the modulus
p and the inverse x₀ of Ratpoints.rbaLength, after j steps: d and x are 1 and x₀
halved j times, and the arrays dinv and ri hold the chains of the halvings so far.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The invariant of the loop over the sieve entries of Ratpoints.Sieve.classOffsets after the
entries pref: the entries so far with their inverses of the strides, and the chains of the
halvings of their inverses of Ratpoints.rbaLength, for the strides up to kmax.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The offset of the row of a class for the n-th entry, from the arrays that the halvings give,
is that of the packing of the class for that entry with its inverses of the strides.
The classes after class_offsets have the rows of their packings for the entries with their
inverses of the strides.
The row offsets of the classes, once the moduli of the run are known: each class with a pattern gets the row of its packing in the array of the offsets, for the sieve entries with their inverses of the strides, when the array has room for a row for each distinct packing; the classes keep their patterns, strides and residues, and the entries are those of the run with the inverses of the strides.
The residues of a denominator #
The first branch of fill_bp_list: for b ≤ Ratpoints.mulModLimit / Ratpoints.maxPrimeEven
the product b dinv is reduced at once, exactly.
The second branch of fill_bp_list: for b ≤ Ratpoints.mulModLimit, b is reduced first and
then its product with dinv, both exactly.
fill_bp_list computes b dinv[k] mod p for every modulus 0 < p ≤ Ratpoints.maxPrimeEven
with dinv[k] < p, in each of its three branches, with the reciprocals of the moduli.