Library Coq.Numbers.Cyclic.Int31.Cyclic31
Int31 numbers defines indeed a cyclic structure : Z/(2^31)Z
Author: Arnaud Spiwack (+ Pierre Letouzey)
Basic results about iszero, shiftl, shiftr
Iterated shift to the right
Iterated shift to the left
More advanced results about nshiftr
Some induction principles over int31
Not used for the moment. Are they really useful ?
Some generic results about recr
recr satisfies the fixpoint equation used for its definition.
recr is usually equivalent to a variant recrbis
written without iszero check.
Variant of incr via recrbis
Recursive equations satisfied by incr
The previous result is actually true even without the
constraint on firstl, but this is harder to prove
(see later).
Conversion to Z : the phi function
Variant of phi via recrbis
Recursive equations satisfied by phi
phi x is positive and lower than 2^31
After killing n bits at the left, are the numbers equal ?
From int31 to list of digits.
Lower (=rightmost) bits comes first.
i2l can be used to define a relation equivalent to EqShiftL
This equivalence allows to prove easily the following delicate
result
More equations about incr
Conversion from Z : the phi_inv function
First, recursive equations
phi_inv o inv, the always-exact and easy-to-prove trip :
from int31 to Z and then back to int31.
The other composition
phi o phi_inv is harder to prove correct.
In particular, an overflow can happen, so a modulo is needed.
For the moment, we proceed via several steps, the first one
being a detour to
positive_to_in31.
positive_to_int31
A variant of
p2i with
twice and
twice_plus_one instead of
2*i and
2*i+1
We now prove that this p2ibis is related to phi_inv_positive
This gives the expected result about phi o phi_inv, at least
for the positive case.
Moreover, p2ibis is also related with p2i and hence with
positive_to_int31.
Thanks to the result about phi o phi_inv_positive, we can
now establish easily the most general results about
phi o twice and so one.
With the previous results, we can deal with phi o phi_inv even
in the negative case
Lemma phi_phi_inv_negative :
forall p,
phi (
incr (
complement_negative p))
= (Zneg p) mod 2
^(Z.of_nat size).
Lemma phi_phi_inv :
forall z,
phi (
phi_inv z)
= z mod 2
^ (Z.of_nat size).
End Basics.
Instance int31_ops :
ZnZ.Ops int31 :=
{
digits := 31%
positive;
zdigits := 31;
to_Z :=
phi;
of_pos :=
positive_to_int31;
head0 :=
head031;
tail0 :=
tail031;
zero := 0;
one := 1;
minus_one :=
Tn;
compare :=
compare31;
eq0 :=
fun i =>
match i ?= 0
with Eq =>
true |
_ =>
false end;
opp_c :=
fun i => 0
-c i;
opp :=
opp31;
opp_carry :=
fun i => 0
-i-1;
succ_c :=
fun i =>
i +c 1;
add_c :=
add31c;
add_carry_c :=
add31carryc;
succ :=
fun i =>
i + 1;
add :=
add31;
add_carry :=
fun i j =>
i + j + 1;
pred_c :=
fun i =>
i -c 1;
sub_c :=
sub31c;
sub_carry_c :=
sub31carryc;
pred :=
fun i =>
i - 1;
sub :=
sub31;
sub_carry :=
fun i j =>
i - j - 1;
mul_c :=
mul31c;
mul :=
mul31;
square_c :=
fun x =>
x *c x;
div21 :=
div3121;
div_gt :=
div31;
div :=
div31;
modulo_gt :=
fun i j =>
let (
_,
r) :=
i/j in r;
modulo :=
fun i j =>
let (
_,
r) :=
i/j in r;
gcd_gt :=
gcd31;
gcd :=
gcd31;
add_mul_div :=
addmuldiv31;
pos_mod :=
fun p i =>
match p ?= 31
with
|
Lt =>
addmuldiv31 p 0 (
addmuldiv31 (31
-p)
i 0)
|
_ =>
i
end;
is_even :=
fun i =>
let (
_,
r) :=
i/2
in
match r ?= 0
with Eq =>
true |
_ =>
false end;
sqrt2 :=
sqrt312;
sqrt :=
sqrt31
}.
Section Int31_Specs.
Local Open Scope Z_scope.
Notation "[| x |]" := (
phi x) (
at level 0,
x at level 99).
Local Notation wB := (2
^ (Z.of_nat size)).
Lemma wB_pos :
wB > 0.
Notation "[+| c |]" :=
(
interp_carry 1
wB phi c) (
at level 0,
x at level 99).
Notation "[-| c |]" :=
(
interp_carry (-1)
wB phi c) (
at level 0,
x at level 99).
Notation "[|| x ||]" :=
(
zn2z_to_Z wB phi x) (
at level 0,
x at level 99).
Lemma spec_zdigits :
[| 31
|] = 31.
Lemma spec_more_than_1_digit: 1
< 31.
Lemma spec_0 :
[| 0
|] = 0.
Lemma spec_1 :
[| 1
|] = 1.
Lemma spec_m1 :
[| Tn |] = wB - 1.
Lemma spec_compare :
forall x y,
(
x ?= y)%
int31 = ([|x|] ?= [|y|]).
Addition
Substraction
Multiplication
Division
Lemma spec_div21 :
forall a1 a2 b,
wB/2
<= [|b|] ->
[|a1|] < [|b|] ->
let (
q,
r) :=
div3121 a1 a2 b in
[|a1|] *wB+ [|a2|] = [|q|] * [|b|] + [|r|] /\
0
<= [|r|] < [|b|].
Lemma spec_div :
forall a b, 0
< [|b|] ->
let (
q,
r) :=
div31 a b in
[|a|] = [|q|] * [|b|] + [|r|] /\
0
<= [|r|] < [|b|].
Lemma spec_mod :
forall a b, 0
< [|b|] ->
[|let (
_,
r) := (
a/b)%
int31 in r|] = [|a|] mod [|b|].
Lemma phi_gcd :
forall i j,
[|gcd31 i j|] = Zgcdn (2
*size)
[|j|] [|i|].
Lemma spec_gcd :
forall a b,
Zis_gcd [|a|] [|b|] [|gcd31 a b|].
Lemma iter_int31_iter_nat :
forall A f i a,
iter_int31 i A f a = iter_nat (
Z.abs_nat [|i|])
A f a.
Fixpoint addmuldiv31_alt n i j :=
match n with
|
O =>
i
|
S n =>
addmuldiv31_alt n (
sneakl (
firstl j)
i) (
shiftl j)
end.
Lemma addmuldiv31_equiv :
forall p x y,
addmuldiv31 p x y = addmuldiv31_alt (
Z.abs_nat [|p|])
x y.
Lemma spec_add_mul_div :
forall x y p,
[|p|] <= Zpos 31 ->
[| addmuldiv31 p x y |] =
([|x|] * (2
^ [|p|]) + [|y|] / (2
^ ((Zpos 31
) - [|p|]))) mod wB.
Lemma spec_pos_mod :
forall w p,
[|ZnZ.pos_mod p w|] = [|w|] mod (2
^ [|p|]).
Shift operations
Lemma spec_head00:
forall x,
[|x|] = 0 ->
[|head031 x|] = Zpos 31.
Fixpoint head031_alt n x :=
match n with
|
O => 0%
nat
|
S n =>
match firstl x with
|
D0 =>
S (
head031_alt n (
shiftl x))
|
D1 => 0%
nat
end
end.
Lemma head031_equiv :
forall x,
[|head031 x|] = Z.of_nat (
head031_alt size x).
Lemma phi_nz :
forall x, 0
< [|x|] <-> x <> 0%
int31.
Lemma spec_head0 :
forall x, 0
< [|x|] ->
wB/ 2
<= 2
^ ([|head031 x|]) * [|x|] < wB.
Lemma spec_tail00:
forall x,
[|x|] = 0 ->
[|tail031 x|] = Zpos 31.
Fixpoint tail031_alt n x :=
match n with
|
O => 0%
nat
|
S n =>
match firstr x with
|
D0 =>
S (
tail031_alt n (
shiftr x))
|
D1 => 0%
nat
end
end.
Lemma tail031_equiv :
forall x,
[|tail031 x|] = Z.of_nat (
tail031_alt size x).
Lemma spec_tail0 :
forall x, 0
< [|x|] ->
exists y, 0
<= y /\ [|x|] = (2
* y + 1
) * (2
^ [|tail031 x|]).
Lemma quotient_by_2 a:
a - 1
<= (a/2
) + (a/2
).
Lemma sqrt_main_trick j k: 0
<= j -> 0
<= k ->
(j * k) + j <= ((j + k)/2
+ 1
) ^ 2.
Lemma sqrt_main i j: 0
<= i -> 0
< j ->
i < ((j + (i/j))/2
+ 1
) ^ 2.
Lemma sqrt_init i: 1
< i ->
i < (i/2
+ 1
) ^ 2.
Lemma sqrt_test_true i j: 0
<= i -> 0
< j ->
i/j >= j ->
j ^ 2
<= i.
Lemma sqrt_test_false i j: 0
<= i -> 0
< j ->
i/j < j ->
(j + (i/j))/2
< j.
Lemma sqrt31_step_def rec i j:
sqrt31_step rec i j =
match (
fst (
i/j)
?= j)%
int31 with
Lt =>
rec i (
fst (
(j + fst(
i/j)
)/2))%
int31
|
_ =>
j
end.
Lemma div31_phi i j: 0
< [|j|] ->
[|fst (
i/j)%
int31|] = [|i|]/[|j|].
Lemma sqrt31_step_correct rec i j:
0
< [|i|] -> 0
< [|j|] ->
[|i|] < ([|j|] + 1
) ^ 2 ->
2
* [|j|] < wB ->
(
forall j1 :
int31,
0
< [|j1|] < [|j|] ->
[|i|] < ([|j1|] + 1
) ^ 2 ->
[|rec i j1|] ^ 2
<= [|i|] < ([|rec i j1|] + 1
) ^ 2) ->
[|sqrt31_step rec i j|] ^ 2
<= [|i|] < ([|sqrt31_step rec i j|] + 1
) ^ 2.
Lemma iter31_sqrt_correct n rec i j: 0
< [|i|] -> 0
< [|j|] ->
[|i|] < ([|j|] + 1
) ^ 2 -> 2
* [|j|] < 2
^ (Z.of_nat size) ->
(
forall j1, 0
< [|j1|] -> 2
^(Z.of_nat n) + [|j1|] <= [|j|] ->
[|i|] < ([|j1|] + 1
) ^ 2 -> 2
* [|j1|] < 2
^ (Z.of_nat size) ->
[|rec i j1|] ^ 2
<= [|i|] < ([|rec i j1|] + 1
) ^ 2) ->
[|iter31_sqrt n rec i j|] ^ 2
<= [|i|] < ([|iter31_sqrt n rec i j|] + 1
) ^ 2.
Lemma spec_sqrt :
forall x,
[|sqrt31 x|] ^ 2
<= [|x|] < ([|sqrt31 x|] + 1
) ^ 2.
Lemma sqrt312_step_def rec ih il j:
sqrt312_step rec ih il j =
match (
ih ?= j)%
int31 with
Eq =>
j
|
Gt =>
j
|
_ =>
match (
fst (
div3121 ih il j)
?= j)%
int31 with
Lt =>
let m :=
match j +c fst (
div3121 ih il j)
with
C0 m1 =>
fst (
m1/2)%
int31
|
C1 m1 => (
fst (
m1/2)
+ v30)%
int31
end in rec ih il m
|
_ =>
j
end
end.
Lemma sqrt312_lower_bound ih il j:
phi2 ih il < ([|j|] + 1
) ^ 2 ->
[|ih|] <= [|j|].
Lemma div312_phi ih il j: (2
^30
<= [|j|] ->
[|ih|] < [|j|] ->
[|fst (
div3121 ih il j)
|] = phi2 ih il/[|j|])%
Z.
Lemma sqrt312_step_correct rec ih il j:
2
^ 29
<= [|ih|] -> 0
< [|j|] ->
phi2 ih il < ([|j|] + 1
) ^ 2 ->
(
forall j1, 0
< [|j1|] < [|j|] ->
phi2 ih il < ([|j1|] + 1
) ^ 2 ->
[|rec ih il j1|] ^ 2
<= phi2 ih il < ([|rec ih il j1|] + 1
) ^ 2) ->
[|sqrt312_step rec ih il j|] ^ 2
<= phi2 ih il
< ([|sqrt312_step rec ih il j|] + 1
) ^ 2.
Lemma iter312_sqrt_correct n rec ih il j:
2
^29
<= [|ih|] -> 0
< [|j|] ->
phi2 ih il < ([|j|] + 1
) ^ 2 ->
(
forall j1, 0
< [|j1|] -> 2
^(Z.of_nat n) + [|j1|] <= [|j|] ->
phi2 ih il < ([|j1|] + 1
) ^ 2 ->
[|rec ih il j1|] ^ 2
<= phi2 ih il < ([|rec ih il j1|] + 1
) ^ 2) ->
[|iter312_sqrt n rec ih il j|] ^ 2
<= phi2 ih il
< ([|iter312_sqrt n rec ih il j|] + 1
) ^ 2.
Lemma spec_sqrt2 :
forall x y,
wB/ 4
<= [|x|] ->
let (
s,
r) :=
sqrt312 x y in
[||WW x y||] = [|s|] ^ 2
+ [+|r|] /\
[+|r|] <= 2
* [|s|].
iszero