aboutsummaryrefslogtreecommitdiff
path: root/theories/Ints/num
diff options
context:
space:
mode:
authorthery2007-05-21 07:47:46 +0000
committerthery2007-05-21 07:47:46 +0000
commit2c1c506d23118fb56fc07b4e334e0e1c7995e36b (patch)
tree40fe1b8d8b6225ef09443f3073840e0b65f73536 /theories/Ints/num
parent79d1421ce90b7f3c0c6a719a93a87d36b3abdfcd (diff)
add_mul_pos uses int31 only
git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/coq/trunk@9845 85f007b7-540e-0410-9357-904b9bb8a0f7
Diffstat (limited to 'theories/Ints/num')
-rw-r--r--theories/Ints/num/GenBase.v4
-rw-r--r--theories/Ints/num/GenDiv.v527
-rw-r--r--theories/Ints/num/GenDivn1.v282
-rw-r--r--theories/Ints/num/GenLift.v270
-rw-r--r--theories/Ints/num/GenSqrt.v342
-rw-r--r--theories/Ints/num/NMake.v130
-rw-r--r--theories/Ints/num/Zn2Z.v230
-rw-r--r--theories/Ints/num/ZnZ.v19
8 files changed, 1129 insertions, 675 deletions
diff --git a/theories/Ints/num/GenBase.v b/theories/Ints/num/GenBase.v
index b953566ede..04749f79c6 100644
--- a/theories/Ints/num/GenBase.v
+++ b/theories/Ints/num/GenBase.v
@@ -25,11 +25,15 @@ Section GenBase.
Variable w_WW : w -> w -> zn2z w.
Variable w_0W : w -> zn2z w.
Variable w_digits : positive.
+ Variable w_zdigits: w.
+ Variable w_add: w -> w -> zn2z w.
Variable w_to_Z : w -> Z.
Variable w_compare : w -> w -> comparison.
Definition ww_digits := xO w_digits.
+ Definition ww_zdigits := w_add w_zdigits w_zdigits.
+
Definition ww_to_Z := zn2z_to_Z (base w_digits) w_to_Z.
Definition ww_1 := WW w_0 w_1.
diff --git a/theories/Ints/num/GenDiv.v b/theories/Ints/num/GenDiv.v
index 4bcea709d0..4a30fa2c32 100644
--- a/theories/Ints/num/GenDiv.v
+++ b/theories/Ints/num/GenDiv.v
@@ -12,6 +12,7 @@ Require Import ZArith.
Require Import ZAux.
Require Import ZDivModAux.
Require Import ZPowerAux.
+Require Import Zmod.
Require Import Basic_type.
Require Import GenBase.
Require Import GenDivn1.
@@ -28,19 +29,32 @@ Section POS_MOD.
Variable w:Set.
Variable w_0 : w.
Variable w_digits : positive.
+ Variable w_zdigits : w.
Variable w_WW : w -> w -> zn2z w.
- Variable w_pos_mod : positive -> w -> w.
+ Variable w_pos_mod : w -> w -> w.
+ Variable w_compare : w -> w -> comparison.
+ Variable ww_compare : zn2z w -> zn2z w -> comparison.
+ Variable w_0W : w -> zn2z w.
+ Variable low: zn2z w -> w.
+ Variable ww_sub: zn2z w -> zn2z w -> zn2z w.
+ Variable ww_zdigits : zn2z w.
+
Definition ww_pos_mod p x :=
+ let zdigits := w_0W w_zdigits in
match x with
| W0 => W0
| WW xh xl =>
- match Pcompare p w_digits Eq with
+ match ww_compare p zdigits with
| Eq => w_WW w_0 xl
- | Lt => w_WW w_0 (w_pos_mod p xl)
+ | Lt => w_WW w_0 (w_pos_mod (low p) xl)
| Gt =>
- let n := Pminus p w_digits in
- w_WW (w_pos_mod n xh) xl
+ match ww_compare p ww_zdigits with
+ | Lt =>
+ let n := low (ww_sub p zdigits) in
+ w_WW (w_pos_mod n xh) xl
+ | _ => x
+ end
end
end.
@@ -58,79 +72,129 @@ Section POS_MOD.
Variable spec_to_Z : forall x, 0 <= [|x|] < wB.
+ Variable spec_to_w_Z : forall x, 0 <= [[x]] < wwB.
+
Variable spec_w_WW : forall h l, [[w_WW h l]] = [|h|] * wB + [|l|].
Variable spec_pos_mod : forall w p,
- [|w_pos_mod p w|] = [|w|] mod (2 ^ Zpos p).
+ [|w_pos_mod p w|] = [|w|] mod (2 ^ [|p|]).
+
+ Variable spec_w_0W : forall l, [[w_0W l]] = [|l|].
+ Variable spec_ww_compare : forall x y,
+ match ww_compare x y with
+ | Eq => [[x]] = [[y]]
+ | Lt => [[x]] < [[y]]
+ | Gt => [[x]] > [[y]]
+ end.
+ Variable spec_ww_sub: forall x y,
+ [[ww_sub x y]] = ([[x]] - [[y]]) mod wwB.
+
+ Variable spec_zdigits : [| w_zdigits |] = Zpos w_digits.
+ Variable spec_low: forall x, [| low x|] = [[x]] mod wB.
+ Variable spec_ww_zdigits : [[ww_zdigits]] = 2 * [|w_zdigits|].
+ Variable spec_ww_digits : ww_digits w_digits = xO w_digits.
+
Hint Rewrite spec_w_0 spec_w_WW : w_rewrite.
Lemma spec_ww_pos_mod : forall w p,
- [[ww_pos_mod p w]] = [[w]] mod (2 ^ Zpos p).
+ [[ww_pos_mod p w]] = [[w]] mod (2 ^ [[p]]).
assert (HHHHH:= lt_0_wB w_digits).
assert (F0: forall x y, x - y + y = x); auto with zarith.
- intros w1 p; unfold ww_pos_mod; case w1.
- autorewrite with w_rewrite; rewrite Zmod_def_small; auto with zarith.
- match goal with |- context [(?X ?= ?Y)%positive Eq] =>
- case_eq (Pcompare X Y Eq) end; intros H1.
- assert (E1: Zpos p = Zpos w_digits); auto.
- rewrite Pcompare_Eq_eq with (1:= H1); auto with zarith.
- rewrite E1.
- intros xh xl; simpl ww_to_Z;autorewrite with w_rewrite rm10.
- match goal with |- context id [2 ^Zpos w_digits] =>
- let v := context id [wB] in change v
- end.
- rewrite Zmod_plus; auto with zarith.
- rewrite Zmod_mult_0; auto with zarith.
- autorewrite with rm10.
- rewrite Zmod_mod; auto with zarith.
- rewrite Zmod_def_small; auto with zarith.
- assert (Eq1: Zpos p < Zpos w_digits); auto.
- intros xh xl; autorewrite with w_rewrite rm10.
- rewrite spec_pos_mod; auto with zarith.
- assert (Eq2: Zpos p+(Zpos w_digits -Zpos p) = Zpos w_digits);auto with zarith.
- simpl ww_to_Z;unfold base; rewrite <- Eq2.
- rewrite Zpower_exp; auto with zarith.
- rewrite (fun x => (Zmult_comm (2 ^ x))); rewrite Zmult_assoc.
- rewrite Zmod_plus; auto with zarith.
- rewrite Zmod_mult_0; auto with zarith.
- autorewrite with rm10.
- rewrite Zmod_mod; auto with zarith.
- assert (Eq1: Zpos p > Zpos w_digits); auto.
- intros xh xl; autorewrite with w_rewrite rm10.
- rewrite spec_pos_mod; auto with zarith.
- simpl ww_to_Z.
- pattern [|xh|] at 2; rewrite Z_div_mod_eq with (b := 2 ^ Zpos (p - w_digits));
- auto with zarith.
- rewrite (fun x => (Zmult_comm (2 ^ x))); rewrite Zmult_plus_distr_l.
- unfold base; rewrite <- Zmult_assoc; rewrite <- Zpower_exp;
+ intros w1 p; case (spec_to_w_Z p); intros HH1 HH2.
+ unfold ww_pos_mod; case w1.
+ simpl; rewrite Zmod_def_small; split; auto with zarith.
+ intros xh xl; generalize (spec_ww_compare p (w_0W w_zdigits));
+ case ww_compare;
+ rewrite spec_w_0W; rewrite spec_zdigits; fold wB;
+ intros H1.
+ rewrite H1; simpl ww_to_Z.
+ autorewrite with w_rewrite rm10.
+ rewrite Zmod_plus; auto with zarith.
+ rewrite Zmod_mult_0; auto with zarith.
+ autorewrite with rm10.
+ rewrite Zmod_mod; auto with zarith.
+ rewrite Zmod_def_small; auto with zarith.
+ autorewrite with w_rewrite rm10.
+ simpl ww_to_Z.
+ rewrite spec_pos_mod.
+ assert (HH0: [|low p|] = [[p]]).
+ rewrite spec_low.
+ apply Zmod_def_small; auto with zarith.
+ case (spec_to_w_Z p); intros HHH1 HHH2; split; auto with zarith.
+ apply Zlt_le_trans with (1 := H1).
+ unfold base.
+ apply Zpower2_le_lin; auto with zarith.
+ rewrite HH0.
+ rewrite Zmod_plus; auto with zarith.
+ unfold base.
+ rewrite <- (F0 (Zpos w_digits) [[p]]).
+ rewrite Zpower_exp; auto with zarith.
+ rewrite Zmult_assoc.
+ rewrite Zmod_mult_0; auto with zarith.
+ autorewrite with w_rewrite rm10.
+ rewrite Zmod_mod; auto with zarith.
+generalize (spec_ww_compare p ww_zdigits);
+ case ww_compare; rewrite spec_ww_zdigits;
+ rewrite spec_zdigits; intros H2.
+ replace (2^[[p]]) with wwB.
+ rewrite Zmod_def_small; auto with zarith.
+ unfold base; rewrite H2.
+ rewrite spec_ww_digits; auto.
+ assert (HH0: [|low (ww_sub p (w_0W w_zdigits))|] =
+ [[p]] - Zpos w_digits).
+ rewrite spec_low.
+ rewrite spec_ww_sub.
+ rewrite spec_w_0W; rewrite spec_zdigits.
+ rewrite <- Zmod_div_mod; auto with zarith.
+ rewrite Zmod_def_small; auto with zarith.
+ split; auto with zarith.
+ apply Zlt_le_trans with (Zpos w_digits); auto with zarith.
+ unfold base; apply Zpower2_le_lin; auto with zarith.
+ exists wB; unfold base; rewrite <- Zpower_exp; auto with zarith.
+ rewrite spec_ww_digits;
+ apply f_equal with (f := Zpower 2); rewrite Zpos_xO; auto with zarith.
+ simpl ww_to_Z; autorewrite with w_rewrite.
+ rewrite spec_pos_mod; rewrite HH0.
+ pattern [|xh|] at 2;
+ rewrite Z_div_mod_eq with (b := 2 ^ ([[p]] - Zpos w_digits));
+ auto with zarith.
+ rewrite (fun x => (Zmult_comm (2 ^ x))); rewrite Zmult_plus_distr_l.
+ unfold base; rewrite <- Zmult_assoc; rewrite <- Zpower_exp;
auto with zarith.
- rewrite Zpos_minus; auto with zarith.
- rewrite F0; auto with zarith.
- rewrite <- Zplus_assoc; rewrite Zmod_plus; auto with zarith.
- rewrite Zmod_mult_0; auto with zarith.
- autorewrite with rm10.
- rewrite Zmod_mod; auto with zarith.
- apply sym_equal; apply Zmod_def_small; auto with zarith.
- case (spec_to_Z xh); intros U1 U2.
- case (spec_to_Z xl); intros U3 U4.
- split; auto with zarith.
- apply Zplus_le_0_compat; auto with zarith.
- apply Zmult_le_0_compat; auto with zarith.
- match goal with |- 0 <= ?X mod ?Y =>
- case (Z_mod_lt X Y); auto with zarith
- end.
- match goal with |- ?X mod ?Y * ?U + ?Z < ?T =>
- apply Zle_lt_trans with ((Y - 1) * U + Z );
- [case (Z_mod_lt X Y); auto with zarith | idtac]
- end.
- match goal with |- ?X * ?U + ?Y < ?Z =>
- apply Zle_lt_trans with (X * U + (U - 1))
- end.
- apply Zplus_le_compat_l; auto with zarith.
- case (spec_to_Z xl); unfold base; auto with zarith.
- rewrite Zmult_minus_distr_r; rewrite <- Zpower_exp; auto with zarith.
- rewrite F0; auto with zarith.
+ rewrite F0; auto with zarith.
+ rewrite <- Zplus_assoc; rewrite Zmod_plus; auto with zarith.
+ rewrite Zmod_mult_0; auto with zarith.
+ autorewrite with rm10.
+ rewrite Zmod_mod; auto with zarith.
+ apply sym_equal; apply Zmod_def_small; auto with zarith.
+ case (spec_to_Z xh); intros U1 U2.
+ case (spec_to_Z xl); intros U3 U4.
+ split; auto with zarith.
+ apply Zplus_le_0_compat; auto with zarith.
+ apply Zmult_le_0_compat; auto with zarith.
+ match goal with |- 0 <= ?X mod ?Y =>
+ case (Z_mod_lt X Y); auto with zarith
+ end.
+ match goal with |- ?X mod ?Y * ?U + ?Z < ?T =>
+ apply Zle_lt_trans with ((Y - 1) * U + Z );
+ [case (Z_mod_lt X Y); auto with zarith | idtac]
+ end.
+ match goal with |- ?X * ?U + ?Y < ?Z =>
+ apply Zle_lt_trans with (X * U + (U - 1))
+ end.
+ apply Zplus_le_compat_l; auto with zarith.
+ case (spec_to_Z xl); unfold base; auto with zarith.
+ rewrite Zmult_minus_distr_r; rewrite <- Zpower_exp; auto with zarith.
+ rewrite F0; auto with zarith.
+ rewrite Zmod_def_small; auto with zarith.
+ case (spec_to_w_Z (WW xh xl)); intros U1 U2.
+ split; auto with zarith.
+ apply Zlt_le_trans with (1:= U2).
+ unfold base; rewrite spec_ww_digits.
+ apply Zpower_le_monotone; auto with zarith.
+ split; auto with zarith.
+ rewrite Zpos_xO; auto with zarith.
Qed.
End POS_MOD.
@@ -587,30 +651,34 @@ Section GenDivGt.
Variable w_div_gt : w -> w -> w*w.
Variable w_mod_gt : w -> w -> w.
Variable w_gcd_gt : w -> w -> w.
- Variable w_add_mul_div : positive -> w -> w -> w.
- Variable w_head0 : w -> N.
+ Variable w_add_mul_div : w -> w -> w -> w.
+ Variable w_head0 : w -> w.
Variable w_div21 : w -> w -> w -> w * w.
Variable w_div32 : w -> w -> w -> w -> w -> w * zn2z w.
- Variable _ww_digits : positive.
+ Variable _ww_zdigits : zn2z w.
Variable ww_1 : zn2z w.
- Variable ww_add_mul_div : positive -> zn2z w -> zn2z w -> zn2z w.
+ Variable ww_add_mul_div : zn2z w -> zn2z w -> zn2z w -> zn2z w.
+
+ Variable w_zdigits : w.
Definition ww_div_gt_aux ah al bh bl :=
Eval lazy beta iota delta [ww_sub ww_opp] in
- let nb0 := w_head0 bh in
- match nb0 with
- | N0 => (ww_1, ww_sub w_0 w_WW w_opp_c w_opp_carry w_sub_c
- w_opp w_sub w_sub_carry (WW ah al) (WW bh bl))
- | Npos p =>
+ let p := w_head0 bh in
+ match w_compare p w_0 with
+ | Gt =>
let b1 := w_add_mul_div p bh bl in
let b2 := w_add_mul_div p bl w_0 in
let a1 := w_add_mul_div p w_0 ah in
let a2 := w_add_mul_div p ah al in
let a3 := w_add_mul_div p al w_0 in
let (q,r) := w_div32 a1 a2 a3 b1 b2 in
- (WW w_0 q, ww_add_mul_div (Pminus _ww_digits p) W0 r)
+ (WW w_0 q, ww_add_mul_div
+ (ww_sub w_0 w_WW w_opp_c w_opp_carry w_sub_c
+ w_opp w_sub w_sub_carry _ww_zdigits (w_0W p)) W0 r)
+ | _ => (ww_1, ww_sub w_0 w_WW w_opp_c w_opp_carry w_sub_c
+ w_opp w_sub w_sub_carry (WW ah al) (WW bh bl))
end.
Definition ww_div_gt a b :=
@@ -628,7 +696,8 @@ Section GenDivGt.
match w_compare w_0 bh with
| Eq =>
let(q,r):=
- gen_divn1 w_digits w_0 w_WW w_head0 w_add_mul_div w_div21 1 a bl in
+ gen_divn1 w_zdigits w_0 w_WW w_head0 w_add_mul_div w_div21
+ w_compare w_sub 1 a bl in
(q, w_0W r)
| Lt => ww_div_gt_aux ah al bh bl
| Gt => (W0,W0) (* cas absurde *)
@@ -637,19 +706,20 @@ Section GenDivGt.
Definition ww_mod_gt_aux ah al bh bl :=
Eval lazy beta iota delta [ww_sub ww_opp] in
- let nb0 := w_head0 bh in
- match nb0 with
- | N0 =>
- ww_sub w_0 w_WW w_opp_c w_opp_carry w_sub_c
- w_opp w_sub w_sub_carry (WW ah al) (WW bh bl)
- | Npos p =>
+ let p := w_head0 bh in
+ match w_compare p w_0 with
+ | Gt =>
let b1 := w_add_mul_div p bh bl in
let b2 := w_add_mul_div p bl w_0 in
let a1 := w_add_mul_div p w_0 ah in
let a2 := w_add_mul_div p ah al in
let a3 := w_add_mul_div p al w_0 in
let (q,r) := w_div32 a1 a2 a3 b1 b2 in
- ww_add_mul_div (Pminus _ww_digits p) W0 r
+ ww_add_mul_div (ww_sub w_0 w_WW w_opp_c w_opp_carry w_sub_c
+ w_opp w_sub w_sub_carry _ww_zdigits (w_0W p)) W0 r
+ | _ =>
+ ww_sub w_0 w_WW w_opp_c w_opp_carry w_sub_c
+ w_opp w_sub w_sub_carry (WW ah al) (WW bh bl)
end.
Definition ww_mod_gt a b :=
@@ -664,7 +734,8 @@ Section GenDivGt.
else
match w_compare w_0 bh with
| Eq =>
- w_0W (gen_modn1 w_digits w_0 w_head0 w_add_mul_div w_div21 1 a bl)
+ w_0W (gen_modn1 w_zdigits w_0 w_head0 w_add_mul_div w_div21
+ w_compare w_sub 1 a bl)
| Lt => ww_mod_gt_aux ah al bh bl
| Gt => W0 (* cas absurde *)
end
@@ -679,8 +750,8 @@ Section GenDivGt.
match w_compare w_0 bl with
| Eq => WW ah al (* normalement n'arrive pas si forme normale *)
| Lt =>
- let m := gen_modn1 w_digits w_0 w_head0 w_add_mul_div w_div21 1
- (WW ah al) bl in
+ let m := gen_modn1 w_zdigits w_0 w_head0 w_add_mul_div w_div21
+ w_compare w_sub 1 (WW ah al) bl in
WW w_0 (w_gcd_gt bl m)
| Gt => W0 (* absurde *)
end
@@ -694,8 +765,8 @@ Section GenDivGt.
match w_compare w_0 ml with
| Eq => WW bh bl
| _ =>
- let r := gen_modn1 w_digits w_0 w_head0 w_add_mul_div w_div21 1
- (WW bh bl) ml in
+ let r := gen_modn1 w_zdigits w_0 w_head0 w_add_mul_div w_div21
+ w_compare w_sub 1 (WW bh bl) ml in
WW w_0 (w_gcd_gt ml r)
end
| Lt =>
@@ -734,6 +805,7 @@ Section GenDivGt.
Variable spec_w_0 : [|w_0|] = 0.
Variable spec_to_Z : forall x, 0 <= [|x|] < wB.
+ Variable spec_to_w_Z : forall x, 0 <= [[x]] < wwB.
Variable spec_w_WW : forall h l, [[w_WW h l]] = [|h|] * wB + [|l|].
Variable spec_w_0W : forall l, [[w_0W l]] = [|l|].
@@ -765,12 +837,12 @@ Section GenDivGt.
Zis_gcd [|a|] [|b|] [|w_gcd_gt a b|].
Variable spec_add_mul_div : forall x y p,
- Zpos p < Zpos w_digits ->
+ [|p|] <= Zpos w_digits ->
[| w_add_mul_div p x y |] =
- ([|x|] * (Zpower 2 (Zpos p)) +
- [|y|] / (Zpower 2 ((Zpos w_digits) - (Zpos p)))) mod wB.
+ ([|x|] * (2 ^ ([|p|])) +
+ [|y|] / (2 ^ ((Zpos w_digits) - [|p|]))) mod wB.
Variable spec_head0 : forall x, 0 < [|x|] ->
- wB/ 2 <= 2 ^ (Z_of_N (w_head0 x)) * [|x|] < wB.
+ wB/ 2 <= 2 ^ [|w_head0 x|] * [|x|] < wB.
Variable spec_div21 : forall a1 a2 b,
wB/2 <= [|b|] ->
@@ -787,13 +859,15 @@ Section GenDivGt.
[|q|] * ([|b1|] * wB + [|b2|]) + [[r]] /\
0 <= [[r]] < [|b1|] * wB + [|b2|].
- Variable spec_ww_digits_ : _ww_digits = xO w_digits.
+ Variable spec_w_zdigits: [|w_zdigits|] = Zpos w_digits.
+
+ Variable spec_ww_digits_ : [[_ww_zdigits]] = Zpos (xO w_digits).
Variable spec_ww_1 : [[ww_1]] = 1.
Variable spec_ww_add_mul_div : forall x y p,
- Zpos p < Zpos (xO w_digits) ->
+ [[p]] <= Zpos (xO w_digits) ->
[[ ww_add_mul_div p x y ]] =
- ([[x]] * (2^Zpos p) +
- [[y]] / (2^(Zpos (xO w_digits) - Zpos p))) mod wwB.
+ ([[x]] * (2^[[p]]) +
+ [[y]] / (2^(Zpos (xO w_digits) - [[p]]))) mod wwB.
Ltac Spec_w_to_Z x :=
let H:= fresh "HH" in
@@ -804,14 +878,14 @@ Section GenDivGt.
assert (H:= spec_ww_to_Z w_digits w_to_Z spec_to_Z x).
Lemma to_Z_div_minus_p : forall x p,
- 0 < Zpos p < Zpos w_digits ->
- 0 <= [|x|] / 2 ^ (Zpos w_digits - Zpos p) < 2 ^ Zpos p.
+ 0 < [|p|] < Zpos w_digits ->
+ 0 <= [|x|] / 2 ^ (Zpos w_digits - [|p|]) < 2 ^ [|p|].
Proof.
intros x p H;Spec_w_to_Z x.
split. apply Zdiv_le_lower_bound;zarith.
apply Zdiv_lt_upper_bound;zarith.
rewrite <- Zpower_exp;zarith.
- ring_simplify (Zpos p + (Zpos w_digits - Zpos p)); unfold base in HH;zarith.
+ ring_simplify ([|p|] + (Zpos w_digits - [|p|])); unfold base in HH;zarith.
Qed.
Hint Resolve to_Z_div_minus_p : zarith.
@@ -824,20 +898,27 @@ Section GenDivGt.
Proof.
intros ah al bh bl Hgt Hpos;unfold ww_div_gt_aux.
change
- (let (q, r) := match w_head0 bh with
- | N0 => (ww_1, ww_sub w_0 w_WW w_opp_c w_opp_carry w_sub_c
- w_opp w_sub w_sub_carry (WW ah al) (WW bh bl))
- | Npos p =>
+ (let (q, r) := let p := w_head0 bh in
+ match w_compare p w_0 with
+ | Gt =>
let b1 := w_add_mul_div p bh bl in
let b2 := w_add_mul_div p bl w_0 in
let a1 := w_add_mul_div p w_0 ah in
let a2 := w_add_mul_div p ah al in
let a3 := w_add_mul_div p al w_0 in
let (q,r) := w_div32 a1 a2 a3 b1 b2 in
- (WW w_0 q, ww_add_mul_div (Pminus _ww_digits p) W0 r)
+ (WW w_0 q, ww_add_mul_div
+ (ww_sub w_0 w_WW w_opp_c w_opp_carry w_sub_c
+ w_opp w_sub w_sub_carry _ww_zdigits (w_0W p)) W0 r)
+ | _ => (ww_1, ww_sub w_0 w_WW w_opp_c w_opp_carry w_sub_c
+ w_opp w_sub w_sub_carry (WW ah al) (WW bh bl))
end in [[WW ah al]]=[[q]]*[[WW bh bl]]+[[r]] /\ 0 <=[[r]]< [[WW bh bl]]).
- assert (Hh := spec_head0 Hpos);destruct (w_head0 bh).
- simpl Zpower in Hh;rewrite Zmult_1_l in Hh;destruct Hh.
+ assert (Hh := spec_head0 Hpos).
+ lazy zeta.
+ generalize (spec_compare (w_head0 bh) w_0); case w_compare;
+ rewrite spec_w_0; intros HH.
+ generalize Hh; rewrite HH; simpl Zpower;
+ rewrite Zmult_1_l; intros (HH1, HH2); clear HH.
assert (wwB <= 2*[[WW bh bl]]).
apply Zle_trans with (2*[|bh|]*wB).
rewrite wwB_wBwB; rewrite Zpower_2; apply Zmult_le_compat_r; zarith.
@@ -847,22 +928,22 @@ Section GenDivGt.
Spec_ww_to_Z (WW ah al).
rewrite spec_ww_sub;eauto.
simpl;rewrite spec_ww_1;rewrite Zmult_1_l;simpl.
- simpl ww_to_Z in Hgt, H1, HH;rewrite Zmod_def_small;split;zarith.
- unfold Z_of_N in Hh.
- assert (Zpos p < Zpos w_digits).
- destruct (Z_lt_ge_dec (Zpos p) (Zpos w_digits));trivial.
+ simpl ww_to_Z in Hgt, H, HH;rewrite Zmod_def_small;split;zarith.
+ case (spec_to_Z (w_head0 bh)); auto with zarith.
+ assert ([|w_head0 bh|] < Zpos w_digits).
+ destruct (Z_lt_ge_dec [|w_head0 bh|] (Zpos w_digits));trivial.
elimtype False.
- assert (2 ^ Zpos p * [|bh|] >= wB);auto with zarith.
+ assert (2 ^ [|w_head0 bh|] * [|bh|] >= wB);auto with zarith.
apply Zle_ge; replace wB with (wB * 1);try ring.
Spec_w_to_Z bh;apply Zmult_le_compat;zarith.
unfold base;apply Zpower_le_monotone;zarith.
- assert (HHHH : 0 < Zpos p < Zpos w_digits).
- split;trivial. unfold Zlt;reflexivity.
- generalize (spec_add_mul_div w_0 ah H)
- (spec_add_mul_div ah al H)
- (spec_add_mul_div al w_0 H)
- (spec_add_mul_div bh bl H)
- (spec_add_mul_div bl w_0 H);
+ assert (HHHH : 0 < [|w_head0 bh|] < Zpos w_digits); auto with zarith.
+ assert (Hb:= Zlt_le_weak _ _ H).
+ generalize (spec_add_mul_div w_0 ah Hb)
+ (spec_add_mul_div ah al Hb)
+ (spec_add_mul_div al w_0 Hb)
+ (spec_add_mul_div bh bl Hb)
+ (spec_add_mul_div bl w_0 Hb);
rewrite spec_w_0; repeat rewrite Zmult_0_l;repeat rewrite Zplus_0_l;
rewrite Zdiv_0;repeat rewrite Zplus_0_r.
Spec_w_to_Z ah;Spec_w_to_Z bh. 2:apply Zpower_lt_0;zarith.
@@ -870,35 +951,35 @@ Section GenDivGt.
assert (H3:=to_Z_div_minus_p ah HHHH);assert(H4:=to_Z_div_minus_p al HHHH);
assert (H5:=to_Z_div_minus_p bl HHHH).
rewrite Zmult_comm in Hh.
- assert (2^Zpos p < wB). unfold base;apply Zpower_lt_monotone;zarith.
+ assert (2^[|w_head0 bh|] < wB). unfold base;apply Zpower_lt_monotone;zarith.
unfold base in H0;rewrite Zmod_def_small;zarith.
- fold wB; rewrite (Zmod_def_small ([|bh|] * 2 ^ Zpos p));zarith.
+ fold wB; rewrite (Zmod_def_small ([|bh|] * 2 ^ [|w_head0 bh|]));zarith.
intros U1 U2 U3 V1 V2.
- generalize (@spec_w_div32 (w_add_mul_div p w_0 ah)
- (w_add_mul_div p ah al)
- (w_add_mul_div p al w_0)
- (w_add_mul_div p bh bl)
- (w_add_mul_div p bl w_0)).
- destruct (w_div32 (w_add_mul_div p w_0 ah)
- (w_add_mul_div p ah al)
- (w_add_mul_div p al w_0)
- (w_add_mul_div p bh bl)
- (w_add_mul_div p bl w_0)) as (q,r).
+ generalize (@spec_w_div32 (w_add_mul_div (w_head0 bh) w_0 ah)
+ (w_add_mul_div (w_head0 bh) ah al)
+ (w_add_mul_div (w_head0 bh) al w_0)
+ (w_add_mul_div (w_head0 bh) bh bl)
+ (w_add_mul_div (w_head0 bh) bl w_0)).
+ destruct (w_div32 (w_add_mul_div (w_head0 bh) w_0 ah)
+ (w_add_mul_div (w_head0 bh) ah al)
+ (w_add_mul_div (w_head0 bh) al w_0)
+ (w_add_mul_div (w_head0 bh) bh bl)
+ (w_add_mul_div (w_head0 bh) bl w_0)) as (q,r).
rewrite V1;rewrite V2. rewrite Zmult_plus_distr_l.
- rewrite <- (Zplus_assoc ([|bh|] * 2 ^ Zpos p * wB)).
+ rewrite <- (Zplus_assoc ([|bh|] * 2 ^ [|w_head0 bh|] * wB)).
unfold base;rewrite <- shift_unshift_mod;zarith. fold wB.
- replace ([|bh|] * 2 ^ Zpos p * wB + [|bl|] * 2 ^ Zpos p) with
- ([[WW bh bl]] * 2^Zpos p). 2:simpl;ring.
+ replace ([|bh|] * 2 ^ [|w_head0 bh|] * wB + [|bl|] * 2 ^ [|w_head0 bh|]) with
+ ([[WW bh bl]] * 2^[|w_head0 bh|]). 2:simpl;ring.
fold wwB. rewrite wwB_wBwB. rewrite Zpower_2. rewrite U1;rewrite U2;rewrite U3.
rewrite Zmult_assoc. rewrite Zmult_plus_distr_l.
- rewrite (Zplus_assoc ([|ah|] / 2^(Zpos(w_digits) - Zpos p)*wB * wB)).
+ rewrite (Zplus_assoc ([|ah|] / 2^(Zpos(w_digits) - [|w_head0 bh|])*wB * wB)).
rewrite <- Zmult_plus_distr_l. rewrite <- Zplus_assoc.
unfold base;repeat rewrite <- shift_unshift_mod;zarith. fold wB.
- replace ([|ah|] * 2 ^ Zpos p * wB + [|al|] * 2 ^ Zpos p) with
- ([[WW ah al]] * 2^Zpos p). 2:simpl;ring.
+ replace ([|ah|] * 2 ^ [|w_head0 bh|] * wB + [|al|] * 2 ^ [|w_head0 bh|]) with
+ ([[WW ah al]] * 2^[|w_head0 bh|]). 2:simpl;ring.
intros Hd;destruct Hd;zarith.
simpl. apply beta_lex_inv;zarith. rewrite U1;rewrite V1.
- assert ([|ah|] / 2 ^ (Zpos (w_digits) - Zpos p) < wB/2);zarith.
+ assert ([|ah|] / 2 ^ (Zpos (w_digits) - [|w_head0 bh|]) < wB/2);zarith.
apply Zdiv_lt_upper_bound;zarith.
unfold base.
replace (2^Zpos (w_digits)) with (2^(Zpos (w_digits) - 1)*2).
@@ -908,24 +989,39 @@ Section GenDivGt.
pattern 2 at 2;replace 2 with (2^1);trivial.
rewrite <- Zpower_exp;zarith. ring_simplify (Zpos (w_digits) - 1 + 1);trivial.
change [[WW w_0 q]] with ([|w_0|]*wB+[|q|]);rewrite spec_w_0;rewrite
- Zmult_0_l;rewrite Zplus_0_l;rewrite spec_ww_digits_.
- replace [[ww_add_mul_div (xO (w_digits) - p) W0 r]] with ([[r]]/2^Zpos p).
- assert (0 < 2^Zpos p). apply Zpower_lt_0;zarith.
+ Zmult_0_l;rewrite Zplus_0_l.
+ replace [[ww_add_mul_div (ww_sub w_0 w_WW w_opp_c w_opp_carry w_sub_c w_opp w_sub w_sub_carry
+ _ww_zdigits (w_0W (w_head0 bh))) W0 r]] with ([[r]]/2^[|w_head0 bh|]).
+ assert (0 < 2^[|w_head0 bh|]). apply Zpower_lt_0;zarith.
split.
- rewrite <- (Z_div_mult [[WW ah al]] (2^Zpos p));zarith.
+ rewrite <- (Z_div_mult [[WW ah al]] (2^[|w_head0 bh|]));zarith.
rewrite H1;rewrite Zmult_assoc;apply Z_div_plus_l;trivial.
split;[apply Zdiv_le_lower_bound| apply Zdiv_lt_upper_bound];zarith.
- rewrite spec_ww_add_mul_div;rewrite Zpos_minus.
+ rewrite spec_ww_add_mul_div.
+ rewrite spec_ww_sub; auto with zarith.
+ rewrite spec_ww_digits_.
change (Zpos (xO (w_digits))) with (2*Zpos (w_digits));zarith.
simpl ww_to_Z;rewrite Zmult_0_l;rewrite Zplus_0_l.
- ring_simplify (2*Zpos (w_digits)-(2*Zpos (w_digits) - Zpos p));trivial.
+ rewrite spec_w_0W.
+ rewrite (fun x y => Zmod_def_small (x-y)); auto with zarith.
+ ring_simplify (2 * Zpos w_digits - (2 * Zpos w_digits - [|w_head0 bh|])).
rewrite Zmod_def_small;zarith.
split;[apply Zdiv_le_lower_bound| apply Zdiv_lt_upper_bound];zarith.
Spec_ww_to_Z r.
apply Zlt_le_trans with wwB;zarith.
rewrite <- (Zmult_1_r wwB);apply Zmult_le_compat;zarith.
- rewrite Zpos_xO;zarith. rewrite Zpos_xO;zarith. rewrite Zpos_xO;zarith.
- Qed.
+ split; auto with zarith.
+ apply Zle_lt_trans with (2 * Zpos w_digits); auto with zarith.
+ unfold base, ww_digits; rewrite (Zpos_xO w_digits).
+ apply Zpower2_lt_lin; auto with zarith.
+ rewrite spec_ww_sub; auto with zarith.
+ rewrite spec_ww_digits_; rewrite spec_w_0W.
+ rewrite Zmod_def_small;zarith.
+ rewrite Zpos_xO; split; auto with zarith.
+ apply Zle_lt_trans with (2 * Zpos w_digits); auto with zarith.
+ unfold base, ww_digits; rewrite (Zpos_xO w_digits).
+ apply Zpower2_lt_lin; auto with zarith.
+ Qed.
Lemma spec_ww_div_gt : forall a b, [[a]] > [[b]] -> 0 < [[b]] ->
let (q,r) := ww_div_gt a b in
@@ -933,21 +1029,24 @@ Section GenDivGt.
0 <= [[r]] < [[b]].
Proof.
intros a b Hgt Hpos;unfold ww_div_gt.
- change (let (q,r) := match a, b with
- | W0, _ => (W0,W0)
- | _, W0 => (W0,W0)
- | WW ah al, WW bh bl =>
- if w_eq0 ah then let (q,r) := w_div_gt al bl in (WW w_0 q, w_0W r)
- else
- match w_compare w_0 bh with
- | Eq =>
- let(q,r):=
- gen_divn1 w_digits w_0 w_WW w_head0 w_add_mul_div w_div21 1 a bl in
- (q, w_0W r)
- | Lt => ww_div_gt_aux ah al bh bl
- | Gt => (W0,W0) (* cas absurde *)
- end
- end in [[a]] = [[q]] * [[b]] + [[r]] /\ 0 <= [[r]] < [[b]]).
+ change (let (q,r) := match a, b with
+ | W0, _ => (W0,W0)
+ | _, W0 => (W0,W0)
+ | WW ah al, WW bh bl =>
+ if w_eq0 ah then
+ let (q,r) := w_div_gt al bl in
+ (WW w_0 q, w_0W r)
+ else
+ match w_compare w_0 bh with
+ | Eq =>
+ let(q,r):=
+ gen_divn1 w_zdigits w_0 w_WW w_head0 w_add_mul_div w_div21
+ w_compare w_sub 1 a bl in
+ (q, w_0W r)
+ | Lt => ww_div_gt_aux ah al bh bl
+ | Gt => (W0,W0) (* cas absurde *)
+ end
+ end in [[a]] = [[q]] * [[b]] + [[r]] /\ 0 <= [[r]] < [[b]]).
destruct a as [ |ah al]. simpl in Hgt;omega.
destruct b as [ |bh bl]. simpl in Hpos;omega.
Spec_w_to_Z ah; Spec_w_to_Z al; Spec_w_to_Z bh; Spec_w_to_Z bl.
@@ -964,11 +1063,12 @@ Section GenDivGt.
rewrite spec_w_0 in Hcmp. change [[WW bh bl]] with ([|bh|]*wB+[|bl|]).
rewrite <- Hcmp;rewrite Zmult_0_l;rewrite Zplus_0_l.
simpl in Hpos;rewrite <- Hcmp in Hpos;simpl in Hpos.
- assert (H2:= @spec_gen_divn1 w w_digits w_0 w_WW w_head0 w_add_mul_div
- w_div21 w_to_Z spec_to_Z spec_w_0 spec_w_WW spec_head0
- spec_add_mul_div spec_div21 1 (WW ah al) bl Hpos).
+ assert (H2:= @spec_gen_divn1 w w_digits w_zdigits w_0 w_WW w_head0 w_add_mul_div
+ w_div21 w_compare w_sub w_to_Z spec_to_Z spec_w_zdigits spec_w_0 spec_w_WW spec_head0
+ spec_add_mul_div spec_div21 spec_compare spec_sub 1 (WW ah al) bl Hpos).
unfold gen_to_Z,gen_wB,gen_digits in H2.
- destruct (gen_divn1 w_digits w_0 w_WW w_head0 w_add_mul_div w_div21 1
+ destruct (gen_divn1 w_zdigits w_0 w_WW w_head0 w_add_mul_div w_div21
+ w_compare w_sub 1
(WW ah al) bl).
rewrite spec_w_0W;unfold ww_to_Z;trivial.
apply spec_ww_div_gt_aux;trivial. rewrite spec_w_0 in Hcmp;trivial.
@@ -979,10 +1079,8 @@ Section GenDivGt.
ww_mod_gt_aux ah al bh bl = snd (ww_div_gt_aux ah al bh bl).
Proof.
intros ah al bh bl. unfold ww_mod_gt_aux, ww_div_gt_aux.
- destruct (w_head0 bh). trivial.
- destruct (w_div32 (w_add_mul_div p w_0 ah) (w_add_mul_div p ah al)
- (w_add_mul_div p al w_0) (w_add_mul_div p bh bl)
- (w_add_mul_div p bl w_0));trivial.
+ case w_compare; auto.
+ case w_div32; auto.
Qed.
Lemma spec_ww_mod_gt_aux : forall ah al bh bl,
@@ -1014,34 +1112,37 @@ Section GenDivGt.
intros a b Hgt Hpos.
change (ww_mod_gt a b) with
(match a, b with
- | W0, _ => W0
- | _, W0 => W0
- | WW ah al, WW bh bl =>
- if w_eq0 ah then w_0W (w_mod_gt al bl)
- else
- match w_compare w_0 bh with
- | Eq =>
- w_0W (gen_modn1 w_digits w_0 w_head0 w_add_mul_div w_div21 1 a bl)
- | Lt => ww_mod_gt_aux ah al bh bl
- | Gt => W0 (* cas absurde *)
- end
- end).
+ | W0, _ => W0
+ | _, W0 => W0
+ | WW ah al, WW bh bl =>
+ if w_eq0 ah then w_0W (w_mod_gt al bl)
+ else
+ match w_compare w_0 bh with
+ | Eq =>
+ w_0W (gen_modn1 w_zdigits w_0 w_head0 w_add_mul_div w_div21
+ w_compare w_sub 1 a bl)
+ | Lt => ww_mod_gt_aux ah al bh bl
+ | Gt => W0 (* cas absurde *)
+ end end).
change (ww_div_gt a b) with
(match a, b with
- | W0, _ => (W0,W0)
- | _, W0 => (W0,W0)
- | WW ah al, WW bh bl =>
- if w_eq0 ah then let (q,r) := w_div_gt al bl in (WW w_0 q, w_0W r)
- else
- match w_compare w_0 bh with
- | Eq =>
- let(q,r):=
- gen_divn1 w_digits w_0 w_WW w_head0 w_add_mul_div w_div21 1 a bl in
- (q, w_0W r)
- | Lt => ww_div_gt_aux ah al bh bl
- | Gt => (W0,W0) (* cas absurde *)
- end
- end).
+ | W0, _ => (W0,W0)
+ | _, W0 => (W0,W0)
+ | WW ah al, WW bh bl =>
+ if w_eq0 ah then
+ let (q,r) := w_div_gt al bl in
+ (WW w_0 q, w_0W r)
+ else
+ match w_compare w_0 bh with
+ | Eq =>
+ let(q,r):=
+ gen_divn1 w_zdigits w_0 w_WW w_head0 w_add_mul_div w_div21
+ w_compare w_sub 1 a bl in
+ (q, w_0W r)
+ | Lt => ww_div_gt_aux ah al bh bl
+ | Gt => (W0,W0) (* cas absurde *)
+ end
+ end).
destruct a as [ |ah al];trivial.
destruct b as [ |bh bl];trivial.
Spec_w_to_Z ah; Spec_w_to_Z al; Spec_w_to_Z bh; Spec_w_to_Z bl.
@@ -1055,9 +1156,9 @@ Section GenDivGt.
destruct (w_div_gt al bl);simpl;rewrite spec_w_0W;trivial.
clear H.
assert (H2 := spec_compare w_0 bh);destruct (w_compare w_0 bh).
- rewrite (@spec_gen_modn1_aux w w_digits w_0 w_WW w_head0 w_add_mul_div
- w_div21 1 (WW ah al) bl).
- destruct (gen_divn1 w_digits w_0 w_WW w_head0 w_add_mul_div w_div21 1
+ rewrite (@spec_gen_modn1_aux w w_zdigits w_0 w_WW w_head0 w_add_mul_div
+ w_div21 w_compare w_sub w_to_Z spec_w_0 spec_compare 1 (WW ah al) bl).
+ destruct (gen_divn1 w_zdigits w_0 w_WW w_head0 w_add_mul_div w_div21 w_compare w_sub 1
(WW ah al) bl);simpl;trivial.
rewrite spec_ww_mod_gt_aux_eq;trivial;symmetry;trivial.
trivial.
@@ -1097,8 +1198,8 @@ Section GenDivGt.
match w_compare w_0 bl with
| Eq => WW ah al (* normalement n'arrive pas si forme normale *)
| Lt =>
- let m := gen_modn1 w_digits w_0 w_head0 w_add_mul_div w_div21 1
- (WW ah al) bl in
+ let m := gen_modn1 w_zdigits w_0 w_head0 w_add_mul_div w_div21
+ w_compare w_sub 1 (WW ah al) bl in
WW w_0 (w_gcd_gt bl m)
| Gt => W0 (* absurde *)
end
@@ -1112,8 +1213,8 @@ Section GenDivGt.
match w_compare w_0 ml with
| Eq => WW bh bl
| _ =>
- let r := gen_modn1 w_digits w_0 w_head0 w_add_mul_div w_div21 1
- (WW bh bl) ml in
+ let r := gen_modn1 w_zdigits w_0 w_head0 w_add_mul_div w_div21
+ w_compare w_sub 1 (WW bh bl) ml in
WW w_0 (w_gcd_gt ml r)
end
| Lt =>
@@ -1136,10 +1237,11 @@ Section GenDivGt.
rewrite spec_w_0 in Hbl.
apply Zis_gcd_mod;zarith.
change ([|ah|] * wB + [|al|]) with (gen_to_Z w_digits w_to_Z 1 (WW ah al)).
- rewrite <- (@spec_gen_modn1 w w_digits w_0 w_WW w_head0 w_add_mul_div
- w_div21 w_to_Z spec_to_Z spec_w_0 spec_w_WW spec_head0 spec_add_mul_div
- spec_div21 1 (WW ah al) bl Hbl).
- apply spec_gcd_gt. rewrite spec_gen_modn1 with (w_WW := w_WW);trivial.
+ rewrite <- (@spec_gen_modn1 w w_digits w_zdigits w_0 w_WW w_head0 w_add_mul_div
+ w_div21 w_compare w_sub w_to_Z spec_to_Z spec_w_zdigits spec_w_0 spec_w_WW spec_head0 spec_add_mul_div
+ spec_div21 spec_compare spec_sub 1 (WW ah al) bl Hbl).
+ apply spec_gcd_gt.
+ rewrite (@spec_gen_modn1 w w_digits w_zdigits w_0 w_WW); trivial.
apply Zlt_gt;match goal with | |- ?x mod ?y < ?y =>
destruct (Z_mod_lt x y);zarith end.
rewrite spec_w_0 in Hbl;Spec_w_to_Z bl;elimtype False;omega.
@@ -1157,10 +1259,11 @@ Section GenDivGt.
simpl;rewrite spec_w_0;simpl.
rewrite spec_w_0 in Hml. apply Zis_gcd_mod;zarith.
change ([|bh|] * wB + [|bl|]) with (gen_to_Z w_digits w_to_Z 1 (WW bh bl)).
- rewrite <- (@spec_gen_modn1 w w_digits w_0 w_WW w_head0 w_add_mul_div
- w_div21 w_to_Z spec_to_Z spec_w_0 spec_w_WW spec_head0 spec_add_mul_div
- spec_div21 1 (WW bh bl) ml Hml).
- apply spec_gcd_gt. rewrite spec_gen_modn1 with (w_WW := w_WW);trivial.
+ rewrite <- (@spec_gen_modn1 w w_digits w_zdigits w_0 w_WW w_head0 w_add_mul_div
+ w_div21 w_compare w_sub w_to_Z spec_to_Z spec_w_zdigits spec_w_0 spec_w_WW spec_head0 spec_add_mul_div
+ spec_div21 spec_compare spec_sub 1 (WW bh bl) ml Hml).
+ apply spec_gcd_gt.
+ rewrite (@spec_gen_modn1 w w_digits w_zdigits w_0 w_WW); trivial.
apply Zlt_gt;match goal with | |- ?x mod ?y < ?y =>
destruct (Z_mod_lt x y);zarith end.
rewrite spec_w_0 in Hml;Spec_w_to_Z ml;elimtype False;omega.
diff --git a/theories/Ints/num/GenDivn1.v b/theories/Ints/num/GenDivn1.v
index 4b54d825d1..34b3b35e06 100644
--- a/theories/Ints/num/GenDivn1.v
+++ b/theories/Ints/num/GenDivn1.v
@@ -20,11 +20,16 @@ Section GENDIVN1.
Variable w : Set.
Variable w_digits : positive.
+ Variable w_zdigits : w.
Variable w_0 : w.
Variable w_WW : w -> w -> zn2z w.
- Variable w_head0 : w -> N.
- Variable w_add_mul_div : positive -> w -> w -> w.
+ Variable w_head0 : w -> w.
+ Variable w_add_mul_div : w -> w -> w -> w.
Variable w_div21 : w -> w -> w -> w * w.
+ Variable w_compare : w -> w -> comparison.
+ Variable w_sub : w -> w -> w.
+
+
(* ** For proofs ** *)
Variable w_to_Z : w -> Z.
@@ -37,22 +42,34 @@ Section GENDIVN1.
Notation "[[ x ]]" := (zn2z_to_Z wB w_to_Z x) (at level 0, x at level 99).
Variable spec_to_Z : forall x, 0 <= [| x |] < wB.
+ Variable spec_w_zdigits: [|w_zdigits|] = Zpos w_digits.
Variable spec_0 : [|w_0|] = 0.
Variable spec_WW : forall h l, [[w_WW h l]] = [|h|] * wB + [|l|].
Variable spec_head0 : forall x, 0 < [|x|] ->
- wB/ 2 <= 2 ^ (Z_of_N (w_head0 x)) * [|x|] < wB.
+ wB/ 2 <= 2 ^ [|w_head0 x|] * [|x|] < wB.
Variable spec_add_mul_div : forall x y p,
- Zpos p < Zpos w_digits ->
+ [|p|] <= Zpos w_digits ->
[| w_add_mul_div p x y |] =
- ([|x|] * (Zpower 2 (Zpos p)) +
- [|y|] / (Zpower 2 ((Zpos w_digits) - (Zpos p)))) mod wB.
+ ([|x|] * (2 ^ [|p|]) +
+ [|y|] / (2 ^ ((Zpos w_digits) - [|p|]))) mod wB.
Variable spec_div21 : forall a1 a2 b,
wB/2 <= [|b|] ->
[|a1|] < [|b|] ->
let (q,r) := w_div21 a1 a2 b in
[|a1|] *wB+ [|a2|] = [|q|] * [|b|] + [|r|] /\
0 <= [|r|] < [|b|].
+ Variable spec_compare :
+ forall x y,
+ match w_compare x y with
+ | Eq => [|x|] = [|y|]
+ | Lt => [|x|] < [|y|]
+ | Gt => [|x|] > [|y|]
+ end.
+ Variable spec_sub: forall x y,
+ [|w_sub x y|] = ([|x|] - [|y|]) mod wB.
+
+
Section DIVAUX.
Variable b2p : w.
Variable b2p_le : wB/2 <= [|b2p|].
@@ -117,13 +134,13 @@ Section GENDIVN1.
rewrite IHn. destruct (gen_divn1_0 n rh hl);trivial.
Qed.
- Variable p : positive.
- Variable p_bounded : Zpos p < Zpos w_digits.
+ Variable p : w.
+ Variable p_bounded : [|p|] <= Zpos w_digits.
Lemma spec_add_mul_divp : forall x y,
[| w_add_mul_div p x y |] =
- ([|x|] * (Zpower 2 (Zpos p)) +
- [|y|] / (Zpower 2 ((Zpos w_digits) - (Zpos p)))) mod wB.
+ ([|x|] * (2 ^ [|p|]) +
+ [|y|] / (2 ^ ((Zpos w_digits) - [|p|]))) mod wB.
Proof.
intros;apply spec_add_mul_div;auto.
Qed.
@@ -142,22 +159,26 @@ Section GENDIVN1.
| S n => gen_divn1_p_aux n (gen_divn1_p n)
end.
- Lemma p_lt_gen_digits : forall n, Zpos p < Zpos (gen_digits w_digits n).
+ Lemma p_lt_gen_digits : forall n, [|p|] <= Zpos (gen_digits w_digits n).
Proof.
+(*
induction n;simpl. destruct p_bounded;trivial.
- assert (0 < Zpos p). unfold Zlt;reflexivity.
- rewrite Zpos_xO;auto with zarith.
+ case (spec_to_Z p); rewrite Zpos_xO;auto with zarith.
+*)
+ induction n;simpl. trivial.
+ case (spec_to_Z p); rewrite Zpos_xO;auto with zarith.
Qed.
Lemma spec_gen_divn1_p : forall n r h l,
[|r|] < [|b2p|] ->
let (q,r') := gen_divn1_p n r h l in
[|r|] * gen_wB w_digits n +
- ([!n|h!]*2^(Zpos p) +
- [!n|l!] / (2^(Zpos(gen_digits w_digits n) - Zpos p)))
+ ([!n|h!]*2^[|p|] +
+ [!n|l!] / (2^(Zpos(gen_digits w_digits n) - [|p|])))
mod gen_wB w_digits n = [!n|q!] * [|b2p|] + [|r'|] /\
0 <= [|r'|] < [|b2p|].
Proof.
+ case (spec_to_Z p); intros HH0 HH1.
induction n;intros.
unfold gen_divn1_p, gen_divn1_p_aux, gen_to_Z, gen_wB, gen_digits.
rewrite <- spec_add_mul_divp.
@@ -168,26 +189,26 @@ Section GENDIVN1.
assert (H2 := spec_split n l);destruct (gen_split w_0 n l) as (lh,ll).
rewrite H2.
replace ([|r|] * (gen_wB w_digits n * gen_wB w_digits n) +
- (([!n|hh!] * gen_wB w_digits n + [!n|hl!]) * 2 ^ Zpos p +
+ (([!n|hh!] * gen_wB w_digits n + [!n|hl!]) * 2 ^ [|p|] +
([!n|lh!] * gen_wB w_digits n + [!n|ll!]) /
- 2^(Zpos (gen_digits w_digits (S n)) - Zpos p)) mod
+ 2^(Zpos (gen_digits w_digits (S n)) - [|p|])) mod
(gen_wB w_digits n * gen_wB w_digits n)) with
- (([|r|] * gen_wB w_digits n + ([!n|hh!] * 2^Zpos p +
- [!n|hl!] / 2^(Zpos (gen_digits w_digits n) - Zpos p)) mod
+ (([|r|] * gen_wB w_digits n + ([!n|hh!] * 2^[|p|] +
+ [!n|hl!] / 2^(Zpos (gen_digits w_digits n) - [|p|])) mod
gen_wB w_digits n) * gen_wB w_digits n +
- ([!n|hl!] * 2^Zpos p +
- [!n|lh!] / 2^(Zpos (gen_digits w_digits n) - Zpos p)) mod
+ ([!n|hl!] * 2^[|p|] +
+ [!n|lh!] / 2^(Zpos (gen_digits w_digits n) - [|p|])) mod
gen_wB w_digits n).
generalize (IHn r hh hl H);destruct (gen_divn1_p n r hh hl) as (qh,rh);
intros (H3,H4);rewrite H3.
assert ([|rh|] < [|b2p|]). omega.
replace (([!n|qh!] * [|b2p|] + [|rh|]) * gen_wB w_digits n +
- ([!n|hl!] * 2 ^ Zpos p +
- [!n|lh!] / 2 ^ (Zpos (gen_digits w_digits n) - Zpos p)) mod
+ ([!n|hl!] * 2 ^ [|p|] +
+ [!n|lh!] / 2 ^ (Zpos (gen_digits w_digits n) - [|p|])) mod
gen_wB w_digits n) with
([!n|qh!] * [|b2p|] *gen_wB w_digits n + ([|rh|]*gen_wB w_digits n +
- ([!n|hl!] * 2 ^ Zpos p +
- [!n|lh!] / 2 ^ (Zpos (gen_digits w_digits n) - Zpos p)) mod
+ ([!n|hl!] * 2 ^ [|p|] +
+ [!n|lh!] / 2 ^ (Zpos (gen_digits w_digits n) - [|p|])) mod
gen_wB w_digits n)). 2:ring.
generalize (IHn rh hl lh H0);destruct (gen_divn1_p n rh hl lh) as (ql,rl);
intros (H5,H6);rewrite H5.
@@ -205,32 +226,32 @@ Section GENDIVN1.
rewrite Zdiv_shift_r;auto with zarith.
2:change (Zpos (gen_digits w_digits (S n)))
with (2*Zpos (gen_digits w_digits n));auto with zarith.
- replace (2 ^ (Zpos (gen_digits w_digits (S n)) - Zpos p)) with
- (2^(Zpos (gen_digits w_digits n) - Zpos p)*2^Zpos (gen_digits w_digits n)).
+ replace (2 ^ (Zpos (gen_digits w_digits (S n)) - [|p|])) with
+ (2^(Zpos (gen_digits w_digits n) - [|p|])*2^Zpos (gen_digits w_digits n)).
rewrite Zdiv_Zmult_compat_r;auto with zarith.
- rewrite Zmult_plus_distr_l with (p:= 2^Zpos p).
- pattern ([!n|hl!] * 2^Zpos p) at 2;
- rewrite (shift_unshift_mod (Zpos(gen_digits w_digits n))(Zpos p)([!n|hl!]));
+ rewrite Zmult_plus_distr_l with (p:= 2^[|p|]).
+ pattern ([!n|hl!] * 2^[|p|]) at 2;
+ rewrite (shift_unshift_mod (Zpos(gen_digits w_digits n))([|p|])([!n|hl!]));
auto with zarith.
rewrite Zplus_assoc.
replace
- ([!n|hh!] * 2^Zpos (gen_digits w_digits n)* 2^Zpos p +
- ([!n|hl!] / 2^(Zpos (gen_digits w_digits n)-Zpos p)*
+ ([!n|hh!] * 2^Zpos (gen_digits w_digits n)* 2^[|p|] +
+ ([!n|hl!] / 2^(Zpos (gen_digits w_digits n)-[|p|])*
2^Zpos(gen_digits w_digits n)))
with
- (([!n|hh!] *2^Zpos p + gen_to_Z w_digits w_to_Z n hl /
- 2^(Zpos (gen_digits w_digits n)-Zpos p))
+ (([!n|hh!] *2^[|p|] + gen_to_Z w_digits w_to_Z n hl /
+ 2^(Zpos (gen_digits w_digits n)-[|p|]))
* 2^Zpos(gen_digits w_digits n));try (ring;fail).
rewrite <- Zplus_assoc.
- rewrite <- (Zmod_shift_r (Zpos p));auto with zarith.
+ rewrite <- (Zmod_shift_r ([|p|]));auto with zarith.
replace
(2 ^ Zpos (gen_digits w_digits n) * 2 ^ Zpos (gen_digits w_digits n)) with
(2 ^ (Zpos (gen_digits w_digits n) + Zpos (gen_digits w_digits n))).
rewrite (Zmod_shift_r (Zpos (gen_digits w_digits n)));auto with zarith.
replace (2 ^ (Zpos (gen_digits w_digits n) + Zpos (gen_digits w_digits n)))
with (2^Zpos(gen_digits w_digits n) *2^Zpos(gen_digits w_digits n)).
- rewrite (Zmult_comm (([!n|hh!] * 2 ^ Zpos p +
- [!n|hl!] / 2 ^ (Zpos (gen_digits w_digits n) - Zpos p)))).
+ rewrite (Zmult_comm (([!n|hh!] * 2 ^ [|p|] +
+ [!n|hl!] / 2 ^ (Zpos (gen_digits w_digits n) - [|p|])))).
rewrite Zmod_Zmult_compat_l;auto with zarith.
ring.
rewrite Zpower_exp;auto with zarith.
@@ -241,12 +262,11 @@ Section GENDIVN1.
split;auto with zarith.
apply Zdiv_lt_upper_bound;auto with zarith.
rewrite <- Zpower_exp;auto with zarith.
- replace (Zpos p + (Zpos (gen_digits w_digits n) - Zpos p)) with
+ replace ([|p|] + (Zpos (gen_digits w_digits n) - [|p|])) with
(Zpos(gen_digits w_digits n));auto with zarith.
- assert (0 < Zpos p). unfold Zlt;reflexivity. auto with zarith.
rewrite <- Zpower_exp;auto with zarith.
- replace (Zpos (gen_digits w_digits (S n)) - Zpos p) with
- (Zpos (gen_digits w_digits n) - Zpos p +
+ replace (Zpos (gen_digits w_digits (S n)) - [|p|]) with
+ (Zpos (gen_digits w_digits n) - [|p|] +
Zpos (gen_digits w_digits n));trivial.
change (Zpos (gen_digits w_digits (S n))) with
(2*Zpos (gen_digits w_digits n)). ring.
@@ -275,14 +295,14 @@ Section GENDIVN1.
End DIVAUX.
- Fixpoint hight (n:nat) : word w n -> w :=
+ Fixpoint high (n:nat) : word w n -> w :=
match n return word w n -> w with
| O => fun a => a
| S n =>
fun (a:zn2z (word w n)) =>
match a with
| W0 => w_0
- | WW h l => hight n h
+ | WW h l => high n h
end
end.
@@ -295,16 +315,16 @@ Section GENDIVN1.
exact (refl_equal Lt).
Qed.
- Lemma spec_hight : forall n (x:word w n),
- [|hight n x|] = [!n|x!] / 2^(Zpos (gen_digits w_digits n) - Zpos w_digits).
+ Lemma spec_high : forall n (x:word w n),
+ [|high n x|] = [!n|x!] / 2^(Zpos (gen_digits w_digits n) - Zpos w_digits).
Proof.
induction n;intros.
- unfold hight,gen_digits,gen_to_Z.
+ unfold high,gen_digits,gen_to_Z.
replace (Zpos w_digits - Zpos w_digits) with 0;try ring.
simpl. rewrite <- (Zdiv_unique [|x|] 1 [|x|] 0);auto with zarith.
assert (U2 := spec_gen_digits n).
assert (U3 : 0 < Zpos w_digits). exact (refl_equal Lt).
- destruct x;unfold hight;fold hight.
+ destruct x;unfold high;fold high.
unfold gen_to_Z,zn2z_to_Z;rewrite spec_0.
rewrite Zdiv_0;trivial.
apply Zpower_lt_0;auto with zarith.
@@ -330,16 +350,17 @@ Section GENDIVN1.
Qed.
Definition gen_divn1 (n:nat) (a:word w n) (b:w) :=
- match w_head0 b with
- | N0 => gen_divn1_0 b n w_0 a
- | Npos p =>
+ let p := w_head0 b in
+ match w_compare p w_0 with
+ | Gt =>
let b2p := w_add_mul_div p b w_0 in
- let ha := hight n a in
- let k := Pminus w_digits p in
+ let ha := high n a in
+ let k := w_sub w_zdigits p in
let lsr_n := w_add_mul_div k w_0 in
let r0 := w_add_mul_div p w_0 ha in
let (q,r) := gen_divn1_p b2p p n r0 a (gen_0 w_0 n) in
(q, lsr_n r)
+ | _ => gen_divn1_0 b n w_0 a
end.
Lemma spec_gen_divn1 : forall n a b,
@@ -349,131 +370,150 @@ Section GENDIVN1.
0 <= [|r|] < [|b|].
Proof.
intros n a b H. unfold gen_divn1.
- assert (H0 := spec_head0 H).
- destruct (w_head0 b).
- unfold Z_of_N, Zpower in H0.
- rewrite Zmult_1_l in H0;destruct H0.
- rewrite <- spec_0 in H.
- assert (H2 := spec_gen_divn1_0 H0 n a H).
- rewrite spec_0 in H2;rewrite Zmult_0_l in H2;rewrite Zplus_0_l in H2.
- exact H2.
- unfold Z_of_N in H0.
- assert (HHHH : 0 < Zpos p). unfold Zlt;reflexivity.
- assert (Zpos p < Zpos w_digits).
- destruct (Z_lt_le_dec (Zpos p) (Zpos w_digits));trivial.
- assert (2 ^ Zpos p < wB).
- apply Zle_lt_trans with (2 ^ Zpos p * [|b|]);auto with zarith.
- replace (2 ^ Zpos p) with (2^Zpos p * 1);try (ring;fail).
+ case (spec_head0 H); intros H0 H1.
+ case (spec_to_Z (w_head0 b)); intros HH1 HH2.
+ generalize (spec_compare (w_head0 b) w_0); case w_compare;
+ rewrite spec_0; intros H2; auto with zarith.
+ assert (Hv1: wB/2 <= [|b|]).
+ generalize H0; rewrite H2; rewrite Zpower_exp_0;
+ rewrite Zmult_1_l; auto.
+ assert (Hv2: [|w_0|] < [|b|]).
+ rewrite spec_0; auto.
+ generalize (spec_gen_divn1_0 Hv1 n a Hv2).
+ rewrite spec_0;rewrite Zmult_0_l; rewrite Zplus_0_l; auto.
+ contradict H2; auto with zarith.
+ assert (HHHH : 0 < [|w_head0 b|]); auto with zarith.
+ assert ([|w_head0 b|] < Zpos w_digits).
+ case (Zle_or_lt (Zpos w_digits) [|w_head0 b|]); auto; intros HH.
+ assert (2 ^ [|w_head0 b|] < wB).
+ apply Zle_lt_trans with (2 ^ [|w_head0 b|] * [|b|]);auto with zarith.
+ replace (2 ^ [|w_head0 b|]) with (2^[|w_head0 b|] * 1);try (ring;fail).
apply Zmult_le_compat;auto with zarith.
- assert (wB <= 2^Zpos p).
+ assert (wB <= 2^[|w_head0 b|]).
unfold base;apply Zpower_le_monotone;auto with zarith. omega.
- assert ([|w_add_mul_div p b w_0|] = 2 ^ Zpos p * [|b|]).
- assert (H2 := spec_add_mul_div b w_0 H1).
- rewrite spec_0 in H2;rewrite Zdiv_0 in H2;
- rewrite Zplus_0_r in H2;rewrite Zmult_comm in H2.
- rewrite Zmod_def_small in H2;auto with zarith.
- apply Zpower_lt_0;auto with zarith.
- destruct H0.
- assert (H4 := spec_to_Z (hight n a)).
+ assert ([|w_add_mul_div (w_head0 b) b w_0|] =
+ 2 ^ [|w_head0 b|] * [|b|]).
+ rewrite (spec_add_mul_div b w_0); auto with zarith.
+ rewrite spec_0;rewrite Zdiv_0; try omega.
+ rewrite Zplus_0_r; rewrite Zmult_comm.
+ rewrite Zmod_def_small; auto with zarith.
+ apply Zpower_lt_0; try omega.
+ assert (H5 := spec_to_Z (high n a)).
assert
- ([|w_add_mul_div p w_0 (hight n a)|]<[|w_add_mul_div p b w_0|]).
- rewrite H2.
+ ([|w_add_mul_div (w_head0 b) w_0 (high n a)|]
+ <[|w_add_mul_div (w_head0 b) b w_0|]).
+ rewrite H4.
rewrite spec_add_mul_div;auto with zarith.
rewrite spec_0;rewrite Zmult_0_l;rewrite Zplus_0_l.
- assert (([|hight n a|]/2^(Zpos w_digits - Zpos p)) < wB).
+ assert (([|high n a|]/2^(Zpos w_digits - [|w_head0 b|])) < wB).
apply Zdiv_lt_upper_bound;auto with zarith.
apply Zlt_le_trans with wB;auto with zarith.
pattern wB at 1;replace wB with (wB*1);try ring.
apply Zmult_le_compat;auto with zarith.
- assert (H5 := Zpower_lt_0 2 (Zpos w_digits - Zpos p));
+ assert (H6 := Zpower_lt_0 2 (Zpos w_digits - [|w_head0 b|]));
auto with zarith.
rewrite Zmod_def_small;auto with zarith.
apply Zdiv_lt_upper_bound;auto with zarith.
apply Zlt_le_trans with wB;auto with zarith.
- apply Zle_trans with (2 ^ Zpos p * [|b|] * 2).
- rewrite <- wB_div_2;auto with zarith.
+ apply Zle_trans with (2 ^ [|w_head0 b|] * [|b|] * 2).
+ rewrite <- wB_div_2; try omega.
apply Zmult_le_compat;auto with zarith.
pattern 2 at 1;rewrite <- Zpower_exp_1.
apply Zpower_le_monotone;split;auto with zarith.
- rewrite <- H2 in H0.
- assert (H6:= spec_gen_divn1_p H0 H1 n a (gen_0 w_0 n) H5).
- destruct (gen_divn1_p (w_add_mul_div p b w_0) p n
- (w_add_mul_div p w_0 (hight n a)) a
+ rewrite <- H4 in H0.
+ assert (Hb3: [|w_head0 b|] <= Zpos w_digits); auto with zarith.
+ assert (H7:= spec_gen_divn1_p H0 Hb3 n a (gen_0 w_0 n) H6).
+ destruct (gen_divn1_p (w_add_mul_div (w_head0 b) b w_0) (w_head0 b) n
+ (w_add_mul_div (w_head0 b) w_0 (high n a)) a
(gen_0 w_0 n)) as (q,r).
assert (U:= spec_gen_digits n).
- rewrite spec_gen_0 in H6;trivial;rewrite Zdiv_0 in H6.
- rewrite Zplus_0_r in H6.
- rewrite spec_add_mul_div in H6;auto with zarith.
- rewrite spec_0 in H6;rewrite Zmult_0_l in H6;rewrite Zplus_0_l in H6.
- assert (([|hight n a|] / 2 ^ (Zpos w_digits - Zpos p)) mod wB
- = [!n|a!] / 2^(Zpos (gen_digits w_digits n) - Zpos p)).
+ rewrite spec_gen_0 in H7;trivial;rewrite Zdiv_0 in H7.
+ rewrite Zplus_0_r in H7.
+ rewrite spec_add_mul_div in H7;auto with zarith.
+ rewrite spec_0 in H7;rewrite Zmult_0_l in H7;rewrite Zplus_0_l in H7.
+ assert (([|high n a|] / 2 ^ (Zpos w_digits - [|w_head0 b|])) mod wB
+ = [!n|a!] / 2^(Zpos (gen_digits w_digits n) - [|w_head0 b|])).
rewrite Zmod_def_small;auto with zarith.
- rewrite spec_hight. rewrite Zdiv_Zdiv;auto with zarith.
+ rewrite spec_high. rewrite Zdiv_Zdiv;auto with zarith.
rewrite <- Zpower_exp;auto with zarith.
replace (Zpos (gen_digits w_digits n) - Zpos w_digits +
- (Zpos w_digits - Zpos p))
- with (Zpos (gen_digits w_digits n) - Zpos p);trivial;ring.
- assert (H7 := Zpower_lt_0 2 (Zpos w_digits - Zpos p));auto with zarith.
+ (Zpos w_digits - [|w_head0 b|]))
+ with (Zpos (gen_digits w_digits n) - [|w_head0 b|]);trivial;ring.
+ assert (H8 := Zpower_lt_0 2 (Zpos w_digits - [|w_head0 b|]));auto with zarith.
split;auto with zarith.
- apply Zle_lt_trans with ([|hight n a|]);auto with zarith.
+ apply Zle_lt_trans with ([|high n a|]);auto with zarith.
apply Zdiv_le_upper_bound;auto with zarith.
- pattern ([|hight n a|]) at 1;rewrite <- Zmult_1_r.
+ pattern ([|high n a|]) at 1;rewrite <- Zmult_1_r.
apply Zmult_le_compat;auto with zarith.
- rewrite H7 in H6;unfold gen_wB,base in H6.
- rewrite <- shift_unshift_mod in H6;auto with zarith.
- rewrite H2 in H6.
- assert ([|w_add_mul_div (w_digits - p) w_0 r|] = [|r|]/2^Zpos p).
+ rewrite H8 in H7;unfold gen_wB,base in H7.
+ rewrite <- shift_unshift_mod in H7;auto with zarith.
+ rewrite H4 in H7.
+ assert ([|w_add_mul_div (w_sub w_zdigits (w_head0 b)) w_0 r|]
+ = [|r|]/2^[|w_head0 b|]).
rewrite spec_add_mul_div.
rewrite spec_0;rewrite Zmult_0_l;rewrite Zplus_0_l.
- replace (Zpos w_digits - Zpos (w_digits - p)) with (Zpos p).
+ replace (Zpos w_digits - [|w_sub w_zdigits (w_head0 b)|])
+ with ([|w_head0 b|]).
rewrite Zmod_def_small;auto with zarith.
- assert (H8 := spec_to_Z r).
+ assert (H9 := spec_to_Z r).
split;auto with zarith.
apply Zle_lt_trans with ([|r|]);auto with zarith.
apply Zdiv_le_upper_bound;auto with zarith.
pattern ([|r|]) at 1;rewrite <- Zmult_1_r.
apply Zmult_le_compat;auto with zarith.
- assert (H9 := Zpower_lt_0 2 (Zpos p));auto with zarith.
- rewrite Zpos_minus;auto with zarith.
- rewrite Zpos_minus;auto with zarith.
- destruct H6.
+ assert (H10 := Zpower_lt_0 2 ([|w_head0 b|]));auto with zarith.
+ rewrite spec_sub.
+ rewrite Zmod_def_small; auto with zarith.
+ split; auto with zarith.
+ case (spec_to_Z w_zdigits); auto with zarith.
+ rewrite spec_sub.
+ rewrite Zmod_def_small; auto with zarith.
+ split; auto with zarith.
+ case (spec_to_Z w_zdigits); auto with zarith.
+ case H7; intros H71 H72.
split.
- rewrite <- (Z_div_mult [!n|a!] (2^Zpos p));auto with zarith.
- rewrite H8;rewrite H6.
- replace ([!n|q!] * (2 ^ Zpos p * [|b|])) with ([!n|q!] *[|b|] * 2^Zpos p);
+ rewrite <- (Z_div_mult [!n|a!] (2^[|w_head0 b|]));auto with zarith.
+ rewrite H71;rewrite H9.
+ replace ([!n|q!] * (2 ^ [|w_head0 b|] * [|b|]))
+ with ([!n|q!] *[|b|] * 2^[|w_head0 b|]);
try (ring;fail).
rewrite Z_div_plus_l;auto with zarith.
- assert (H10 := spec_to_Z (w_add_mul_div (w_digits - p) w_0 r));split;
+ assert (H10 := spec_to_Z
+ (w_add_mul_div (w_sub w_zdigits (w_head0 b)) w_0 r));split;
auto with zarith.
- rewrite H8.
+ rewrite H9.
apply Zdiv_lt_upper_bound;auto with zarith.
rewrite Zmult_comm;auto with zarith.
exact (spec_gen_to_Z w_digits w_to_Z spec_to_Z n a).
apply Zpower_lt_0;auto with zarith.
Qed.
+
Definition gen_modn1 (n:nat) (a:word w n) (b:w) :=
- match w_head0 b with
- | N0 => gen_modn1_0 b n w_0 a
- | Npos p =>
+ let p := w_head0 b in
+ match w_compare p w_0 with
+ | Gt =>
let b2p := w_add_mul_div p b w_0 in
- let ha := hight n a in
- let k := Pminus w_digits p in
+ let ha := high n a in
+ let k := w_sub w_zdigits p in
let lsr_n := w_add_mul_div k w_0 in
let r0 := w_add_mul_div p w_0 ha in
let r := gen_modn1_p b2p p n r0 a (gen_0 w_0 n) in
lsr_n r
+ | _ => gen_modn1_0 b n w_0 a
end.
Lemma spec_gen_modn1_aux : forall n a b,
gen_modn1 n a b = snd (gen_divn1 n a b).
Proof.
intros n a b;unfold gen_divn1,gen_modn1.
- destruct (w_head0 b).
+ generalize (spec_compare (w_head0 b) w_0); case w_compare;
+ rewrite spec_0; intros H2; auto with zarith.
+ apply spec_gen_modn1_0.
apply spec_gen_modn1_0.
rewrite spec_gen_modn1_p.
- destruct (gen_divn1_p (w_add_mul_div p b w_0) p n
- (w_add_mul_div p w_0 (hight n a)) a (gen_0 w_0 n));simpl;trivial.
+ destruct (gen_divn1_p (w_add_mul_div (w_head0 b) b w_0) (w_head0 b) n
+ (w_add_mul_div (w_head0 b) w_0 (high n a)) a (gen_0 w_0 n));simpl;trivial.
Qed.
Lemma spec_gen_modn1 : forall n a b, 0 < [|b|] ->
diff --git a/theories/Ints/num/GenLift.v b/theories/Ints/num/GenLift.v
index 14aa869796..8b9271e32a 100644
--- a/theories/Ints/num/GenLift.v
+++ b/theories/Ints/num/GenLift.v
@@ -12,6 +12,7 @@ Require Import ZArith.
Require Import ZAux.
Require Import ZPowerAux.
Require Import ZDivModAux.
+Require Import Zmod.
Require Import Basic_type.
Require Import GenBase.
@@ -24,47 +25,54 @@ Section GenLift.
Variable w_W0 : w -> zn2z w.
Variable w_0W : w -> zn2z w.
Variable w_compare : w -> w -> comparison.
- Variable w_head0 : w -> N.
- Variable w_add_mul_div : positive -> w -> w -> w.
+ Variable ww_compare : zn2z w -> zn2z w -> comparison.
+ Variable w_head0 : w -> w.
+ Variable w_add: w -> w -> zn2z w.
+ Variable w_add_mul_div : w -> w -> w -> w.
+ Variable ww_sub: zn2z w -> zn2z w -> zn2z w.
Variable w_digits : positive.
Variable ww_Digits : positive.
+ Variable w_zdigits : w.
+ Variable ww_zdigits : zn2z w.
+ Variable low: zn2z w -> w.
Definition ww_head0 x :=
match x with
- | W0 => Npos ww_Digits
+ | W0 => ww_zdigits
| WW xh xl =>
match w_compare w_0 xh with
- | Eq => Nplus (Npos w_digits) (w_head0 xl)
- | _ => w_head0 xh
+ | Eq => w_add w_zdigits (w_head0 xl)
+ | _ => w_0W (w_head0 xh)
end
end.
(* 0 < p < ww_digits *)
Definition ww_add_mul_div p x y :=
+ let zdigits := w_0W w_zdigits in
match x, y with
| W0, W0 => W0
| W0, WW yh yl =>
- match Pcompare p w_digits Eq with
+ match ww_compare p zdigits with
| Eq => w_0W yh
- | Lt => w_0W (w_add_mul_div p w_0 yh)
+ | Lt => w_0W (w_add_mul_div (low p) w_0 yh)
| Gt =>
- let n := Pminus p w_digits in
+ let n := low (ww_sub p zdigits) in
w_WW (w_add_mul_div n w_0 yh) (w_add_mul_div n yh yl)
end
| WW xh xl, W0 =>
- match Pcompare p w_digits Eq with
+ match ww_compare p zdigits with
| Eq => w_W0 xl
- | Lt => w_WW (w_add_mul_div p xh xl) (w_add_mul_div p xl w_0)
+ | Lt => w_WW (w_add_mul_div (low p) xh xl) (w_add_mul_div (low p) xl w_0)
| Gt =>
- let n := Pminus p w_digits in
+ let n := low (ww_sub p zdigits) in
w_W0 (w_add_mul_div n xl w_0)
end
| WW xh xl, WW yh yl =>
- match Pcompare p w_digits Eq with
+ match ww_compare p zdigits with
| Eq => w_WW xl yh
- | Lt => w_WW (w_add_mul_div p xh xl) (w_add_mul_div p xl yh)
+ | Lt => w_WW (w_add_mul_div (low p) xh xl) (w_add_mul_div (low p) xl yh)
| Gt =>
- let n := Pminus p w_digits in
+ let n := low (ww_sub p zdigits) in
w_WW (w_add_mul_div n xl yh) (w_add_mul_div n yh yl)
end
end.
@@ -79,6 +87,7 @@ Section GenLift.
Variable spec_w_0 : [|w_0|] = 0.
Variable spec_to_Z : forall x, 0 <= [|x|] < wB.
+ Variable spec_to_w_Z : forall x, 0 <= [[x]] < wwB.
Variable spec_w_WW : forall h l, [[w_WW h l]] = [|h|] * wB + [|l|].
Variable spec_w_W0 : forall h, [[w_W0 h]] = [|h|] * wB.
Variable spec_w_0W : forall l, [[w_0W l]] = [|l|].
@@ -88,47 +97,60 @@ Section GenLift.
| Lt => [|x|] < [|y|]
| Gt => [|x|] > [|y|]
end.
+ Variable spec_ww_compare : forall x y,
+ match ww_compare x y with
+ | Eq => [[x]] = [[y]]
+ | Lt => [[x]] < [[y]]
+ | Gt => [[x]] > [[y]]
+ end.
Variable spec_ww_digits : ww_Digits = xO w_digits.
Variable spec_w_head0 : forall x, 0 < [|x|] ->
- wB/ 2 <= 2 ^ (Z_of_N (w_head0 x)) * [|x|] < wB.
+ wB/ 2 <= 2 ^ ([|w_head0 x|]) * [|x|] < wB.
Variable spec_w_add_mul_div : forall x y p,
- Zpos p < Zpos w_digits ->
+ [|p|] <= Zpos w_digits ->
[| w_add_mul_div p x y |] =
- ([|x|] * (Zpower 2 (Zpos p)) +
- [|y|] / (Zpower 2 ((Zpos w_digits) - (Zpos p)))) mod wB.
+ ([|x|] * (2 ^ [|p|]) +
+ [|y|] / (2 ^ ((Zpos w_digits) - [|p|]))) mod wB.
+ Variable spec_w_add: forall x y,
+ [[w_add x y]] = [|x|] + [|y|].
+ Variable spec_ww_sub: forall x y,
+ [[ww_sub x y]] = ([[x]] - [[y]]) mod wwB.
+
+ Variable spec_zdigits : [| w_zdigits |] = Zpos w_digits.
+ Variable spec_low: forall x, [| low x|] = [[x]] mod wB.
Hint Resolve div_le_0 div_lt w_to_Z_wwB: lift.
Ltac zarith := auto with zarith lift.
Lemma spec_ww_head0 : forall x, 0 < [[x]] ->
- wwB/ 2 <= 2 ^ (Z_of_N (ww_head0 x)) * [[x]] < wwB.
+ wwB/ 2 <= 2 ^ [[ww_head0 x]] * [[x]] < wwB.
Proof.
rewrite wwB_div_2;rewrite Zmult_comm;rewrite wwB_wBwB.
assert (U:= lt_0_wB w_digits); destruct x as [ |xh xl];simpl ww_to_Z;intros H.
unfold Zlt in H;discriminate H.
assert (H0 := spec_compare w_0 xh);rewrite spec_w_0 in H0.
- simpl Z_of_N; destruct (w_compare w_0 xh).
+ destruct (w_compare w_0 xh).
rewrite <- H0. simpl Zplus. rewrite <- H0 in H;simpl in H.
- generalize (spec_w_head0 H);destruct (w_head0 xl) as [ |q].
- intros H1;simpl Zpower in H1;rewrite Zmult_1_l in H1.
- change (2 ^ Z_of_N (Npos w_digits)) with wB;split;zarith.
- rewrite Zpower_2; apply Zmult_lt_compat_l;zarith.
- unfold Z_of_N;intros.
- change (Zpos(w_digits + q))with (Zpos w_digits + Zpos q);rewrite Zpower_exp.
- fold wB;rewrite <- Zmult_assoc;split;zarith.
- rewrite Zpower_2; apply Zmult_lt_compat_l;zarith.
- intro H2;discriminate H2. intro H2;discriminate H2.
+ case (spec_to_Z w_zdigits);
+ case (spec_to_Z (w_head0 xl)); intros HH1 HH2 HH3 HH4.
+ rewrite spec_w_add.
+ rewrite spec_zdigits; rewrite Zpower_exp; auto with zarith.
+ case (spec_w_head0 H); intros H1 H2.
+ rewrite Zpower_2; fold wB; rewrite <- Zmult_assoc; split.
+ apply Zmult_le_compat_l; auto with zarith.
+ apply Zmult_lt_compat_l; auto with zarith.
assert (H1 := spec_w_head0 H0).
+ rewrite spec_w_0W.
split.
rewrite Zmult_plus_distr_r;rewrite Zmult_assoc.
- apply Zle_trans with (2 ^ Z_of_N (w_head0 xh) * [|xh|] * wB).
- rewrite Zmult_comm;zarith.
- assert (0 <= 2 ^ Z_of_N (w_head0 xh) * [|xl|]);zarith.
+ apply Zle_trans with (2 ^ [|w_head0 xh|] * [|xh|] * wB).
+ rewrite Zmult_comm; zarith.
+ assert (0 <= 2 ^ [|w_head0 xh|] * [|xl|]);zarith.
assert (H2:=spec_to_Z xl);apply Zmult_le_0_compat;zarith.
- assert (0<= Z_of_N (w_head0 xh)).
- case (w_head0 xh);intros;simpl;intro H2;discriminate H2.
- generalize (Z_of_N (w_head0 xh)) H1 H2;clear H1 H2;intros p H1 H2.
+ case (spec_to_Z (w_head0 xh)); intros H2 _.
+ generalize ([|w_head0 xh|]) H1 H2;clear H1 H2;
+ intros p H1 H2.
assert (Eq1 : 2^p < wB).
rewrite <- (Zmult_1_r (2^p));apply Zle_lt_trans with (2^p*[|xh|]);zarith.
assert (Eq2: p < Zpos w_digits).
@@ -150,59 +172,62 @@ Section GenLift.
(wB_div w_digits w_to_Z spec_to_Z)
(wB_div_plus w_digits w_to_Z spec_to_Z) : w_rewrite.
Ltac w_rewrite := autorewrite with w_rewrite;trivial.
-
+
Lemma spec_ww_add_mul_div_aux : forall xh xl yh yl p,
- Zpos p < Zpos (xO w_digits) ->
- [[match (p ?= w_digits)%positive Eq with
+ let zdigits := w_0W w_zdigits in
+ [[p]] <= Zpos (xO w_digits) ->
+ [[match ww_compare p zdigits with
| Eq => w_WW xl yh
- | Lt => w_WW (w_add_mul_div p xh xl) (w_add_mul_div p xl yh)
+ | Lt => w_WW (w_add_mul_div (low p) xh xl)
+ (w_add_mul_div (low p) xl yh)
| Gt =>
- let n := (p - w_digits)%positive in
+ let n := low (ww_sub p zdigits) in
w_WW (w_add_mul_div n xl yh) (w_add_mul_div n yh yl)
end]] =
- ([[WW xh xl]] * (2^Zpos p) +
- [[WW yh yl]] / (2^(Zpos (xO w_digits) - Zpos p))) mod wwB.
+ ([[WW xh xl]] * (2^[[p]]) +
+ [[WW yh yl]] / (2^(Zpos (xO w_digits) - [[p]]))) mod wwB.
Proof.
- intros xh xl yh yl p;assert (HwwB := wwB_pos w_digits).
- assert (0 < Zpos p). unfold Zlt;reflexivity.
+ intros xh xl yh yl p zdigits;assert (HwwB := wwB_pos w_digits).
+ case (spec_to_w_Z p); intros Hv1 Hv2.
replace (Zpos (xO w_digits)) with (Zpos w_digits + Zpos w_digits).
2 : rewrite Zpos_xO;ring.
- replace (Zpos w_digits + Zpos w_digits - Zpos p) with
- (Zpos w_digits + (Zpos w_digits - Zpos p)). 2:ring.
+ replace (Zpos w_digits + Zpos w_digits - [[p]]) with
+ (Zpos w_digits + (Zpos w_digits - [[p]])). 2:ring.
intros Hp; assert (Hxh := spec_to_Z xh);assert (Hxl:=spec_to_Z xl);
assert (Hx := spec_ww_to_Z w_digits w_to_Z spec_to_Z (WW xh xl));
simpl in Hx;assert (Hyh := spec_to_Z yh);assert (Hyl:=spec_to_Z yl);
assert (Hy:=spec_ww_to_Z w_digits w_to_Z spec_to_Z (WW yh yl));simpl in Hy.
- case_eq ((p ?= w_digits)%positive Eq);intros;w_rewrite;
- match goal with
- | [H: (p ?= w_digits)%positive Eq = Eq |- _] =>
- let H1:= fresh "H" in
- (assert (H1 : Zpos p = Zpos w_digits);
- [ rewrite Pcompare_Eq_eq with (1:= H);trivial
- | rewrite H1;try rewrite Zminus_diag;try rewrite Zplus_0_r]);
- fold wB
- | [H: (p ?= w_digits)%positive Eq = Lt |- _] =>
- change ((p ?= w_digits)%positive Eq = Lt) with
- (Zpos p < Zpos w_digits) in H;
- repeat rewrite spec_w_add_mul_div;zarith
- | [H: (p ?= w_digits)%positive Eq = Gt |- _] =>
- change ((p ?= w_digits)%positive Eq=Gt)with(Zpos p > Zpos w_digits) in H;
- let H1 := fresh "H" in
- assert (H1 := Zpos_minus _ _ (Zgt_lt _ _ H));
- replace (Zpos w_digits + (Zpos w_digits - Zpos p)) with
- (Zpos w_digits - Zpos (p - w_digits));
- [ repeat rewrite spec_w_add_mul_div;zarith
- | zarith ]
- | _ => idtac
- end;simpl ww_to_Z;w_rewrite;zarith.
+ generalize (spec_ww_compare p zdigits); case ww_compare; intros H1.
+ rewrite H1; unfold zdigits; rewrite spec_w_0W.
+ rewrite spec_zdigits; rewrite Zminus_diag; rewrite Zplus_0_r.
+ simpl ww_to_Z; w_rewrite;zarith.
+ fold wB.
rewrite Zmult_plus_distr_l;rewrite <- Zmult_assoc;rewrite <- Zplus_assoc.
rewrite <- Zpower_2.
rewrite <- wwB_wBwB;apply Zmod_unique with [|xh|]. apply lt_0_wwB.
exact (spec_ww_to_Z w_digits w_to_Z spec_to_Z (WW xl yh)). ring.
+ simpl ww_to_Z; w_rewrite;zarith.
+ assert (HH0: [|low p|] = [[p]]).
+ rewrite spec_low.
+ apply Zmod_def_small.
+ case (spec_to_w_Z p); intros HH1 HH2; split; auto.
+ generalize H1; unfold zdigits; rewrite spec_w_0W;
+ rewrite spec_zdigits; intros tmp.
+ apply Zlt_le_trans with (1 := tmp).
+ unfold base.
+ apply Zpower2_le_lin; auto with zarith.
+ 2: generalize H1; unfold zdigits; rewrite spec_w_0W;
+ rewrite spec_zdigits; auto with zarith.
+ generalize H1; unfold zdigits; rewrite spec_w_0W;
+ rewrite spec_zdigits; auto; clear H1; intros H1.
+ assert (HH: [|low p|] <= Zpos w_digits).
+ rewrite HH0; auto with zarith.
+ repeat rewrite spec_w_add_mul_div with (1 := HH).
+ rewrite HH0.
rewrite Zmult_plus_distr_l.
- pattern ([|xl|] * 2 ^ Zpos p) at 2;
+ pattern ([|xl|] * 2 ^ [[p]]) at 2;
rewrite shift_unshift_mod with (n:= Zpos w_digits);fold wB;zarith.
- replace ([|xh|] * wB * 2^Zpos p) with ([|xh|] * 2^Zpos p * wB). 2:ring.
+ replace ([|xh|] * wB * 2^[[p]]) with ([|xh|] * 2^[[p]] * wB). 2:ring.
rewrite Zplus_assoc;rewrite <- Zmult_plus_distr_l. rewrite <- Zplus_assoc.
unfold base at 5;rewrite <- Zmod_shift_r;zarith.
unfold base;rewrite Zmod_shift_r with (b:= Zpos (ww_digits w_digits));
@@ -211,14 +236,40 @@ Section GenLift.
unfold ww_digits;rewrite Zpos_xO;zarith. apply Z_mod_lt;zarith.
split;zarith. apply Zdiv_lt_upper_bound;zarith.
rewrite <- Zpower_exp;zarith.
- ring_simplify (Zpos p + (Zpos w_digits - Zpos p));fold wB;zarith.
+ ring_simplify ([[p]] + (Zpos w_digits - [[p]]));fold wB;zarith.
+ assert (Hv: [[p]] > Zpos w_digits).
+ generalize H1; clear H1.
+ unfold zdigits; rewrite spec_w_0W; rewrite spec_zdigits; auto.
+ clear H1.
+ assert (HH0: [|low (ww_sub p zdigits)|] = [[p]] - Zpos w_digits).
+ rewrite spec_low.
+ rewrite spec_ww_sub.
+ unfold zdigits; rewrite spec_w_0W; rewrite spec_zdigits.
+ rewrite <- Zmod_div_mod; auto with zarith.
+ rewrite Zmod_def_small; auto with zarith.
+ split; auto with zarith.
+ apply Zle_lt_trans with (Zpos w_digits); auto with zarith.
+ unfold base; apply Zpower2_lt_lin; auto with zarith.
+ exists wB; unfold base.
+ unfold ww_digits; rewrite (Zpos_xO w_digits).
+ rewrite <- Zpower_exp; auto with zarith.
+ apply f_equal with (f := fun x => 2 ^ x); auto with zarith.
+ assert (HH: [|low (ww_sub p zdigits)|] <= Zpos w_digits).
+ rewrite HH0; auto with zarith.
+ replace (Zpos w_digits + (Zpos w_digits - [[p]])) with
+ (Zpos w_digits - ([[p]] - Zpos w_digits)); zarith.
+ lazy zeta; simpl ww_to_Z; w_rewrite;zarith.
+ repeat rewrite spec_w_add_mul_div;zarith.
+ rewrite HH0.
pattern wB at 5;replace wB with
- (2^(Zpos (p - w_digits) + (Zpos w_digits - Zpos (p - w_digits)))).
+ (2^(([[p]] - Zpos w_digits)
+ + (Zpos w_digits - ([[p]] - Zpos w_digits)))).
rewrite Zpower_exp;zarith. rewrite Zmult_assoc.
rewrite Z_div_plus_l;zarith.
- rewrite shift_unshift_mod with (a:= [|yh|]) (p:= Zpos (p - w_digits))
+ rewrite shift_unshift_mod with (a:= [|yh|]) (p:= [[p]] - Zpos w_digits)
(n := Zpos w_digits);zarith. fold wB.
- replace (Zpos p) with (Zpos (p - w_digits) + Zpos w_digits);zarith.
+ set (u := [[p]] - Zpos w_digits).
+ replace [[p]] with (u + Zpos w_digits);zarith.
rewrite Zpower_exp;zarith. rewrite Zmult_assoc. fold wB.
repeat rewrite Zplus_assoc. rewrite <- Zmult_plus_distr_l.
repeat rewrite <- Zplus_assoc.
@@ -228,30 +279,36 @@ Section GenLift.
(b:= Zpos w_digits);fold wB;fold wwB;zarith.
rewrite wwB_wBwB; rewrite Zpower_2; rewrite Zmult_mod_distr_r;zarith.
rewrite Zmult_plus_distr_l.
- replace ([|xh|] * wB * 2 ^ Zpos (p - w_digits)) with
- ([|xh|]*2^Zpos(p - w_digits)*wB). 2:ring.
+ replace ([|xh|] * wB * 2 ^ u) with
+ ([|xh|]*2^u*wB). 2:ring.
repeat rewrite <- Zplus_assoc.
- rewrite (Zplus_comm ([|xh|] * 2 ^ Zpos (p - w_digits) * wB)).
+ rewrite (Zplus_comm ([|xh|] * 2 ^ u * wB)).
rewrite Z_mod_plus;zarith. rewrite Zmod_mult_0;zarith.
unfold base;rewrite <- Zmod_shift_r;zarith. fold base;apply Z_mod_lt;zarith.
- split;zarith. apply Zdiv_lt_upper_bound;zarith.
- rewrite <- Zpower_exp;zarith.
- ring_simplify (Zpos (p - w_digits) + (Zpos w_digits - Zpos (p - w_digits))); fold
+ unfold u; split;zarith.
+ split;zarith. unfold u; apply Zdiv_lt_upper_bound;zarith.
+ rewrite <- Zpower_exp;zarith.
+ fold u.
+ ring_simplify (u + (Zpos w_digits - u)); fold
wB;zarith. unfold ww_digits;rewrite Zpos_xO;zarith.
unfold base;rewrite <- Zmod_shift_r;zarith. fold base;apply Z_mod_lt;zarith.
- split;zarith. apply Zdiv_lt_upper_bound;zarith.
- rewrite <- Zpower_exp;zarith.
- ring_simplify (Zpos (p - w_digits) + (Zpos w_digits - Zpos (p - w_digits))); fold
- wB;zarith.
- ring_simplify (Zpos (p - w_digits) + (Zpos w_digits - Zpos (p - w_digits))); fold
- wB;trivial.
+ unfold u; split;zarith.
+ unfold u; split;zarith.
+ apply Zdiv_lt_upper_bound;zarith.
+ rewrite <- Zpower_exp;zarith.
+ fold u.
+ ring_simplify (u + (Zpos w_digits - u)); fold wB; auto with zarith.
+ unfold u;zarith.
+ unfold u;zarith.
+ set (u := [[p]] - Zpos w_digits).
+ ring_simplify (u + (Zpos w_digits - u)); fold wB; auto with zarith.
Qed.
Lemma spec_ww_add_mul_div : forall x y p,
- Zpos p < Zpos (xO w_digits) ->
+ [[p]] <= Zpos (xO w_digits) ->
[[ ww_add_mul_div p x y ]] =
- ([[x]] * (2^Zpos p) +
- [[y]] / (2^(Zpos (xO w_digits) - Zpos p))) mod wwB.
+ ([[x]] * (2^[[p]]) +
+ [[y]] / (2^(Zpos (xO w_digits) - [[p]]))) mod wwB.
Proof.
intros x y p H.
destruct x as [ |xh xl];
@@ -261,15 +318,40 @@ Section GenLift.
[generalize (H1 w_0 w_0 p H) | generalize (H1 yh yl p H)];
clear H1;w_rewrite);simpl ww_add_mul_div.
replace [[WW w_0 w_0]] with 0;[w_rewrite|simpl;w_rewrite;trivial].
- intros Heq;rewrite <- Heq;clear Heq.
- case_eq ((p ?= w_digits)%positive Eq);w_rewrite;intros;trivial.
+ intros Heq;rewrite <- Heq;clear Heq; auto.
+ generalize (spec_ww_compare p (w_0W w_zdigits));
+ case ww_compare; intros H1; w_rewrite.
rewrite (spec_w_add_mul_div w_0 w_0);w_rewrite;zarith.
+ generalize H1; w_rewrite; rewrite spec_zdigits; clear H1; intros H1.
+ assert (HH0: [|low p|] = [[p]]).
+ rewrite spec_low.
+ apply Zmod_def_small.
+ case (spec_to_w_Z p); intros HH1 HH2; split; auto.
+ apply Zlt_le_trans with (1 := H1).
+ unfold base; apply Zpower2_le_lin; auto with zarith.
+ rewrite HH0; auto with zarith.
replace [[WW w_0 w_0]] with 0;[w_rewrite|simpl;w_rewrite;trivial].
intros Heq;rewrite <- Heq;clear Heq.
- case_eq ((p ?= w_digits)%positive Eq);w_rewrite;intros;trivial.
+ generalize (spec_ww_compare p (w_0W w_zdigits));
+ case ww_compare; intros H1; w_rewrite.
rewrite (spec_w_add_mul_div w_0 w_0);w_rewrite;zarith.
- change ((p ?= w_digits)%positive Eq = Gt)with(Zpos p > Zpos w_digits) in H0.
- rewrite Zpos_minus;zarith. rewrite Zpos_xO in H;zarith.
+ rewrite Zpos_xO in H;zarith.
+ assert (HH: [|low (ww_sub p (w_0W w_zdigits)) |] = [[p]] - Zpos w_digits).
+ generalize H1; clear H1.
+ rewrite spec_low.
+ rewrite spec_ww_sub; w_rewrite; intros H1.
+ rewrite <- Zmod_div_mod; auto with zarith.
+ rewrite Zmod_def_small; auto with zarith.
+ split; auto with zarith.
+ apply Zle_lt_trans with (Zpos w_digits); auto with zarith.
+ unfold base; apply Zpower2_lt_lin; auto with zarith.
+ unfold base; auto with zarith.
+ unfold base; auto with zarith.
+ exists wB; unfold base.
+ unfold ww_digits; rewrite (Zpos_xO w_digits).
+ rewrite <- Zpower_exp; auto with zarith.
+ apply f_equal with (f := fun x => 2 ^ x); auto with zarith.
+ case (spec_to_Z xh); auto with zarith.
Qed.
End GenProof.
diff --git a/theories/Ints/num/GenSqrt.v b/theories/Ints/num/GenSqrt.v
index 074f7eb537..3d1bb6a24c 100644
--- a/theories/Ints/num/GenSqrt.v
+++ b/theories/Ints/num/GenSqrt.v
@@ -11,6 +11,7 @@ Set Implicit Arguments.
Require Import ZArith.
Require Import ZAux.
Require Import ZDivModAux.
+Require Import ZPowerAux.
Require Import Basic_type.
Require Import GenBase.
@@ -30,18 +31,22 @@ Section GenSqrt.
Variable w_sub_c : w -> w -> carry w.
Variable w_square_c : w -> zn2z w.
Variable w_div21 : w -> w -> w -> w * w.
- Variable w_add_mul_div : positive -> w -> w -> w.
+ Variable w_add_mul_div : w -> w -> w -> w.
Variable w_digits : positive.
+ Variable w_zdigits : w.
+ Variable ww_zdigits : zn2z w.
Variable w_add_c : w -> w -> carry w.
Variable w_sqrt2 : w -> w -> w * carry w.
+ Variable w_pred : w -> w.
Variable ww_pred_c : zn2z w -> carry (zn2z w).
Variable ww_pred : zn2z w -> zn2z w.
Variable ww_add_c : zn2z w -> zn2z w -> carry (zn2z w).
Variable ww_add : zn2z w -> zn2z w -> zn2z w.
Variable ww_sub_c : zn2z w -> zn2z w -> carry (zn2z w).
- Variable ww_add_mul_div : positive -> zn2z w -> zn2z w -> zn2z w.
- Variable ww_head0 : zn2z w -> N.
+ Variable ww_add_mul_div : zn2z w -> zn2z w -> zn2z w -> zn2z w.
+ Variable ww_head0 : zn2z w -> zn2z w.
Variable ww_compare : zn2z w -> zn2z w -> comparison.
+ Variable low : zn2z w -> w.
Let wwBm1 := ww_Bm1 w_Bm1.
@@ -76,28 +81,28 @@ Section GenSqrt.
match q with
C0 q1 =>
if w_is_even q1 then
- (C0 (w_add_mul_div (w_digits - 1) w_1 q1), C0 r)
+ (C0 (w_add_mul_div (w_pred w_zdigits) w_1 q1), C0 r)
else
- (C0 (w_add_mul_div (w_digits - 1) w_1 q1), w_add_c r s)
+ (C0 (w_add_mul_div (w_pred w_zdigits) w_1 q1), w_add_c r s)
| C1 q1 =>
if w_is_even q1 then
- (C1 (w_add_mul_div (w_digits - 1) w_0 q1), C0 r)
+ (C1 (w_add_mul_div (w_pred w_zdigits) w_0 q1), C0 r)
else
- (C1 (w_add_mul_div (w_digits - 1) w_0 q1), w_add_c r s)
+ (C1 (w_add_mul_div (w_pred w_zdigits) w_0 q1), w_add_c r s)
end
| C0 x1 =>
let (q, r) := w_div21c x1 y s in
match q with
C0 q1 =>
if w_is_even q1 then
- (C0 (w_add_mul_div (w_digits - 1) w_0 q1), C0 r)
+ (C0 (w_add_mul_div (w_pred w_zdigits) w_0 q1), C0 r)
else
- (C0 (w_add_mul_div (w_digits - 1) w_0 q1), w_add_c r s)
+ (C0 (w_add_mul_div (w_pred w_zdigits) w_0 q1), w_add_c r s)
| C1 q1 =>
if w_is_even q1 then
- (C0 (w_add_mul_div (w_digits - 1) w_1 q1), C0 r)
+ (C0 (w_add_mul_div (w_pred w_zdigits) w_1 q1), C0 r)
else
- (C0 (w_add_mul_div (w_digits - 1) w_1 q1), w_add_c r s)
+ (C0 (w_add_mul_div (w_pred w_zdigits) w_1 q1), w_add_c r s)
end
end.
@@ -126,7 +131,7 @@ Section GenSqrt.
match ww_sub_c (WW r2 y2) q2 with
C0 r3 => (a, C0 r3)
| C1 r3 =>
- let a2 := ww_add_mul_div 1 a W0 in
+ let a2 := ww_add_mul_div (w_0W w_1) a W0 in
match ww_pred_c a2 with
C0 a3 =>
(ww_pred a, ww_add_c a3 r3)
@@ -137,7 +142,7 @@ Section GenSqrt.
end
| C1 q1 =>
let a1 := WW q w_Bm1 in
- let a2 := ww_add_mul_div 1 a1 wwBm1 in
+ let a2 := ww_add_mul_div (w_0W w_1) a1 wwBm1 in
(a1, ww_add_c a2 y)
end.
@@ -148,28 +153,28 @@ Section GenSqrt.
end.
Definition ww_head1 x :=
- match ww_head0 x with
- N0 => N0
- | Npos xH => N0
- | Npos (xO _) as U => U
- | Npos (xI V) => Npos (xO V)
- end.
+ let p := ww_head0 x in
+ if (ww_is_even p) then p else ww_pred p.
Definition ww_sqrt x :=
if (ww_is_zero x) then W0
else
- match (ww_head1 x) with
- N0 =>
- match x with
- W0 => W0
- | WW x1 x2 => WW w_0 (fst (w_sqrt2 x1 x2))
- end
- | Npos p =>
+ let p := ww_head1 x in
+ match ww_compare p W0 with
+ | Gt =>
match ww_add_mul_div p x W0 with
W0 => W0
| WW x1 x2 =>
let (r, _) := w_sqrt2 x1 x2 in
- WW w_0 (w_add_mul_div (w_digits - (Pdiv2 p)) w_0 r)
+ WW w_0 (w_add_mul_div
+ (w_sub w_zdigits
+ (low (ww_add_mul_div (ww_pred ww_zdigits)
+ W0 p))) w_0 r)
+ end
+ | _ =>
+ match x with
+ W0 => W0
+ | WW x1 x2 => WW w_0 (fst (w_sqrt2 x1 x2))
end
end.
@@ -201,8 +206,10 @@ Section GenSqrt.
Variable spec_w_0 : [|w_0|] = 0.
Variable spec_w_1 : [|w_1|] = 1.
Variable spec_w_Bm1 : [|w_Bm1|] = wB - 1.
-
+ Variable spec_w_zdigits : [|w_zdigits|] = Zpos w_digits.
+ Variable spec_ww_zdigits : [[ww_zdigits]] = Zpos (xO w_digits).
Variable spec_to_Z : forall x, 0 <= [|x|] < wB.
+ Variable spec_to_w_Z : forall x, 0 <= [[x]] < wwB.
Variable spec_w_WW : forall h l, [[w_WW h l]] = [|h|] * wB + [|l|].
Variable spec_w_W0 : forall h, [[w_W0 h]] = [|h|] * wB.
@@ -224,15 +231,15 @@ Section GenSqrt.
[|a1|] *wB+ [|a2|] = [|q|] * [|b|] + [|r|] /\
0 <= [|r|] < [|b|].
Variable spec_w_add_mul_div : forall x y p,
- Zpos p < Zpos w_digits ->
+ [|p|] <= Zpos w_digits ->
[| w_add_mul_div p x y |] =
- ([|x|] * (Zpower 2 (Zpos p)) +
- [|y|] / (Zpower 2 ((Zpos w_digits) - (Zpos p)))) mod wB.
+ ([|x|] * (2 ^ [|p|]) +
+ [|y|] / (Zpower 2 ((Zpos w_digits) - [|p|]))) mod wB.
Variable spec_ww_add_mul_div : forall x y p,
- Zpos p < Zpos (xO w_digits) ->
+ [[p]] <= Zpos (xO w_digits) ->
[[ ww_add_mul_div p x y ]] =
- ([[x]] * (2^ Zpos p) +
- [[y]] / (2^ (Zpos (xO w_digits) - Zpos p))) mod wwB.
+ ([[x]] * (2^ [[p]]) +
+ [[y]] / (2^ (Zpos (xO w_digits) - [[p]]))) mod wwB.
Variable spec_w_add_c : forall x y, [+|w_add_c x y|] = [|x|] + [|y|].
Variable spec_ww_add : forall x y, [[ww_add x y]] = ([[x]] + [[y]]) mod wwB.
Variable spec_w_sqrt2 : forall x y,
@@ -242,6 +249,7 @@ Section GenSqrt.
[+|r|] <= 2 * [|s|].
Variable spec_ww_sub_c : forall x y, [-[ww_sub_c x y]] = [[x]] - [[y]].
Variable spec_ww_pred_c : forall x, [-[ww_pred_c x]] = [[x]] - 1.
+ Variable spec_pred : forall x, [|w_pred x|] = ([|x|] - 1) mod wB.
Variable spec_ww_pred : forall x, [[ww_pred x]] = ([[x]] - 1) mod wwB.
Variable spec_ww_add_c : forall x y, [+[ww_add_c x y]] = [[x]] + [[y]].
Variable spec_ww_compare : forall x y,
@@ -251,7 +259,8 @@ Section GenSqrt.
| Gt => [[x]] > [[y]]
end.
Variable spec_ww_head0 : forall x, 0 < [[x]] ->
- wwB/ 2 <= 2 ^ (Z_of_N (ww_head0 x)) * [[x]] < wwB.
+ wwB/ 2 <= 2 ^ [[ww_head0 x]] * [[x]] < wwB.
+ Variable spec_low: forall x, [|low x|] = [[x]] mod wB.
Let spec_ww_Bm1 : [[wwBm1]] = wwB - 1.
Proof. refine (spec_ww_Bm1 w_Bm1 w_digits w_to_Z _);auto. Qed.
@@ -351,8 +360,14 @@ Section GenSqrt.
Hypothesis more_than_one_bit: 1 < Zpos w_digits.
Theorem add_mult_div_2: forall w,
- [|w_add_mul_div (w_digits - 1) w_0 w|] = [|w|] / 2.
+ [|w_add_mul_div (w_pred w_zdigits) w_0 w|] = [|w|] / 2.
intros w1.
+ assert (Hp: [|w_pred w_zdigits|] = Zpos w_digits - 1).
+ rewrite spec_pred; rewrite spec_w_zdigits.
+ rewrite Zmod_def_small; auto with zarith.
+ split; auto with zarith.
+ apply Zlt_le_trans with (Zpos w_digits); auto with zarith.
+ unfold base; apply Zpower2_le_lin; auto with zarith.
rewrite spec_w_add_mul_div; auto with zarith.
autorewrite with w_rewrite rm10.
match goal with |- context[?X - ?Y] =>
@@ -361,19 +376,25 @@ Section GenSqrt.
rewrite Zpower_exp_1; rewrite Zmod_def_small; auto with zarith.
destruct (spec_to_Z w1) as [H1 H2];auto with zarith.
split; auto with zarith.
- apply Zdiv_lt_upper_bound; auto with zarith.
- rewrite Zpos_minus; auto with zarith.
- rewrite Zpos_minus; auto with zarith.
+ apply Zdiv_lt_upper_bound; auto with zarith.
+ rewrite Hp; ring.
Qed.
Theorem add_mult_div_2_plus_1: forall w,
- [|w_add_mul_div (w_digits - 1) w_1 w|] =
+ [|w_add_mul_div (w_pred w_zdigits) w_1 w|] =
[|w|] / 2 + 2 ^ Zpos (w_digits - 1).
intros w1.
+ assert (Hp: [|w_pred w_zdigits|] = Zpos w_digits - 1).
+ rewrite spec_pred; rewrite spec_w_zdigits.
+ rewrite Zmod_def_small; auto with zarith.
+ split; auto with zarith.
+ apply Zlt_le_trans with (Zpos w_digits); auto with zarith.
+ unfold base; apply Zpower2_le_lin; auto with zarith.
autorewrite with w_rewrite rm10; auto with zarith.
match goal with |- context[?X - ?Y] =>
replace (X - Y) with 1
- end.
+ end; rewrite Hp; try ring.
+ rewrite Zpos_minus; auto with zarith.
rewrite Zpower_exp_1; rewrite Zmod_def_small; auto with zarith.
destruct (spec_to_Z w1) as [H1 H2];auto with zarith.
split; auto with zarith.
@@ -383,7 +404,8 @@ Section GenSqrt.
rewrite <- (tmp X); clear tmp
end.
rewrite Zpower_exp; try rewrite Zpower_exp_1; auto with zarith.
- rewrite Zpos_minus; auto with zarith.
+ assert (tmp: forall p, 1 + (p -1) - 1 = p - 1); auto with zarith;
+ rewrite tmp; clear tmp; auto with zarith.
match goal with |- ?X + ?Y < _ =>
assert (Y < X); auto with zarith
end.
@@ -392,12 +414,10 @@ Section GenSqrt.
auto with zarith.
assert (tmp: forall p, (p - 1) + 1 = p); auto with zarith;
rewrite tmp; clear tmp; auto with zarith.
- rewrite Zpos_minus; auto with zarith.
- rewrite Zpos_minus; auto with zarith.
Qed.
Theorem add_mult_mult_2: forall w,
- [|w_add_mul_div 1 w w_0|] = 2 * [|w|] mod wB.
+ [|w_add_mul_div w_1 w w_0|] = 2 * [|w|] mod wB.
intros w1.
autorewrite with w_rewrite rm10; auto with zarith.
rewrite Zpower_exp_1; auto with zarith.
@@ -405,19 +425,23 @@ Section GenSqrt.
Qed.
Theorem ww_add_mult_mult_2: forall w,
- [[ww_add_mul_div 1 w W0]] = 2 * [[w]] mod wwB.
+ [[ww_add_mul_div (w_0W w_1) w W0]] = 2 * [[w]] mod wwB.
intros w1.
rewrite spec_ww_add_mul_div; auto with zarith.
autorewrite with w_rewrite rm10.
+ rewrite spec_w_0W; rewrite spec_w_1.
rewrite Zpower_exp_1; auto with zarith.
rewrite Zmult_comm; auto.
+ rewrite spec_w_0W; rewrite spec_w_1; auto with zarith.
+ red; simpl; intros; discriminate.
Qed.
Theorem ww_add_mult_mult_2_plus_1: forall w,
- [[ww_add_mul_div 1 w wwBm1]] =
+ [[ww_add_mul_div (w_0W w_1) w wwBm1]] =
(2 * [[w]] + 1) mod wwB.
intros w1.
rewrite spec_ww_add_mul_div; auto with zarith.
+ rewrite spec_w_0W; rewrite spec_w_1; auto with zarith.
rewrite Zpower_exp_1; auto with zarith.
eq_tac; auto.
rewrite Zmult_comm; eq_tac; auto.
@@ -450,6 +474,8 @@ Section GenSqrt.
match goal with |- ?X - 1 >= 0 =>
assert (0 < X); auto with zarith; red; reflexivity
end.
+ rewrite spec_w_0W; rewrite spec_w_1; auto with zarith.
+ red; simpl; intros; discriminate.
Qed.
Theorem Zmod_plus_one: forall a1 b1, 0 < b1 -> (a1 + b1) mod b1 = a1 mod b1.
@@ -1114,50 +1140,54 @@ Section GenSqrt.
Lemma spec_ww_head1
: forall x : zn2z w,
- (forall p, ww_head1 x = Npos p -> (2 * Zpos (Pdiv2 p) = Zpos p)) /\
- (0 < [[x]] -> wwB / 4 <= 2 ^ Z_of_N (ww_head1 x) * [[x]] < wwB).
+ (ww_is_even (ww_head1 x) = true) /\
+ (0 < [[x]] -> wwB / 4 <= 2 ^ [[ww_head1 x]] * [[x]] < wwB).
assert (U := wB_pos w_digits).
intros x; unfold ww_head1.
- generalize (spec_ww_head0 x); case (ww_head0 x); simpl Z_of_N;
- autorewrite with rm10.
- intros H1; split.
- intros; discriminate.
- intros H2; assert (H3:= H1 H2).
- split; auto with zarith.
- apply Zle_trans with (wwB/2); auto with zarith.
+ generalize (spec_ww_is_even (ww_head0 x)); case_eq (ww_is_even (ww_head0 x)).
+ intros HH H1; rewrite HH; split; auto.
+ intros H2.
+ generalize (spec_ww_head0 x H2); case (ww_head0 x); autorewrite with rm10.
+ intros (H3, H4); split; auto with zarith.
+ apply Zle_trans with (2 := H3).
apply Zdiv_le_monotone; auto with zarith.
- intros p; case p; clear p; simpl Z_of_N.
- intros p H1; split.
- intros p1 H2; injection H2; intros; subst; clear H2; auto.
- intros H2; assert (H3:= H1 H2).
- split; auto with zarith.
- apply Zmult_le_reg_r with 2; auto with zarith.
- repeat rewrite (fun x => Zmult_comm x 2).
- rewrite wwB_4_2.
- pattern 2 at 2; rewrite <- Zpower_exp_1; rewrite Zmult_assoc;
- rewrite <- Zpower_exp; auto with zarith.
- replace (1 + Zpos (xO p)) with (Zpos (xI p)); auto with zarith.
- case H3; intros _ tmp; apply Zlt_trans with (2 := tmp).
- apply Zmult_lt_compat_r; auto with zarith.
- apply Zpower_lt_monotone; auto with zarith.
- split; try (red; intros; discriminate).
- replace (Zpos (xI p)) with (1 + Zpos (xO p)); auto with zarith.
- intros p H1; split.
- intros p1 H2; injection H2; intros; subst; clear H2; auto.
- intros H2; assert (H3:= H1 H2).
- split; auto with zarith.
- apply Zle_trans with (wwB/2); auto with zarith.
+ intros xh xl (H3, H4); split; auto with zarith.
+ apply Zle_trans with (2 := H3).
apply Zdiv_le_monotone; auto with zarith.
- generalize (wwB_pos w_digits); auto with zarith.
- rewrite Zpower_exp_1; try rewrite Zpower_exp_0.
- intros H1; split.
- intros; discriminate.
- intros H2; assert (H3 := H1 H2).
- autorewrite with rm10.
+ intros H1.
+ case (spec_to_w_Z (ww_head0 x)); intros Hv1 Hv2.
+ assert (Hp0: 0 < [[ww_head0 x]]).
+ generalize (spec_ww_is_even (ww_head0 x)); rewrite H1.
+ generalize Hv1; case [[ww_head0 x]].
+ rewrite Zmod_def_small; auto with zarith.
+ intros; assert (0 < Zpos p); auto with zarith.
+ red; simpl; auto.
+ intros p H2; case H2; auto.
+ assert (Hp: [[ww_pred (ww_head0 x)]] = [[ww_head0 x]] - 1).
+ rewrite spec_ww_pred.
+ rewrite Zmod_def_small; auto with zarith.
+ intros H2; split.
+ generalize (spec_ww_is_even (ww_pred (ww_head0 x)));
+ case ww_is_even; auto.
+ rewrite Hp.
+ rewrite Zmod_minus; auto with zarith.
+ rewrite H2; repeat rewrite Zmod_def_small; auto with zarith.
+ intros H3; rewrite Hp.
+ case (spec_ww_head0 x); auto; intros Hv3 Hv4.
+ assert (Hu: forall u, 0 < u -> 2 * 2 ^ (u - 1) = 2 ^u).
+ intros u Hu.
+ pattern 2 at 1; rewrite <- Zpower_exp_1.
+ rewrite <- Zpower_exp; auto with zarith.
+ ring_simplify (1 + (u - 1)); auto with zarith.
split; auto with zarith.
apply Zmult_le_reg_r with 2; auto with zarith.
repeat rewrite (fun x => Zmult_comm x 2).
- rewrite wwB_4_2; auto with zarith.
+ rewrite wwB_4_2.
+ rewrite Zmult_assoc; rewrite Hu; auto with zarith.
+ apply Zle_lt_trans with (2 * 2 ^ ([[ww_head0 x]] - 1) * [[x]]); auto with zarith;
+ rewrite Hu; auto with zarith.
+ apply Zmult_le_compat_r; auto with zarith.
+ apply Zpower_le_monotone; auto with zarith.
Qed.
Theorem wwB_4_wB_4: wwB / 4 = wB / 4 * wB.
@@ -1173,14 +1203,16 @@ Section GenSqrt.
intro x; unfold ww_sqrt.
generalize (spec_ww_is_zero x); case (ww_is_zero x).
simpl ww_to_Z; simpl Zpower; unfold Zpower_pos; simpl;
- auto with zarith.
- intros H1; generalize (spec_ww_head1 x); case (ww_head1 x); simpl Z_of_N;
- autorewrite with rm10.
+ auto with zarith.
+ intros H1.
+ generalize (spec_ww_compare (ww_head1 x) W0); case ww_compare;
+ simpl ww_to_Z; autorewrite with rm10.
generalize H1; case x.
intros HH; contradict HH; simpl ww_to_Z; auto with zarith.
intros w0 w1; simpl ww_to_Z; autorewrite with w_rewrite rm10.
- intros H2 (H3, H4).
- generalize (H4 H2); clear H4; intros (H4, H5).
+ intros H2; case (spec_ww_head1 (WW w0 w1)); intros H3 H4 H5.
+ generalize (H4 H2); clear H4; rewrite H5; clear H5; autorewrite with rm10.
+ intros (H4, H5).
assert (V: wB/4 <= [|w0|]).
apply beta_lex with 0 [|w1|] wB; auto with zarith; autorewrite with rm10.
rewrite <- wwB_4_wB_4; auto.
@@ -1204,21 +1236,21 @@ Section GenSqrt.
replace Z with (X + 1); auto with zarith
end.
repeat rewrite Zsquare_mult; ring.
- intros p (Hp1, Hp2).
- assert (F0: 0 < Zpos (Pdiv2 p)); try (red; reflexivity).
- assert (Hp3 := Hp1 p (refl_equal _)).
- assert (U0: Zpos p < Zpos (ww_digits w_digits)).
- case (Zle_or_lt (Zpos (ww_digits w_digits)) (Zpos p)); auto; intros H2;
- case (Hp2 H1); intros _ tmp; contradict tmp; apply Zle_not_lt;
- unfold base.
- apply Zle_trans with (2 ^ Zpos p * 1); auto with zarith.
- autorewrite with rm10; apply Zpower_le_monotone; auto with zarith.
- assert (U1: Zpos (Pdiv2 p) < Zpos (ww_digits w_digits)); auto with zarith.
- match goal with |- context[ww_add_mul_div ?y ?z ?t] =>
- assert (UU:= spec_ww_add_mul_div z t );
- generalize (UU p U0);
- case (ww_add_mul_div y z t)
- end.
+ intros HH; case (spec_to_w_Z (ww_head1 x)); auto with zarith.
+ intros Hv1.
+ case (spec_ww_head1 x); intros Hp1 Hp2.
+ generalize (Hp2 H1); clear Hp2; intros Hp2.
+ assert (Hv2: [[ww_head1 x]] <= Zpos (xO w_digits)).
+ case (Zle_or_lt (Zpos (xO w_digits)) [[ww_head1 x]]); auto with zarith; intros HH1.
+ case Hp2; intros _ HH2; contradict HH2.
+ apply Zle_not_lt; unfold base.
+ apply Zle_trans with (2 ^ [[ww_head1 x]]).
+ apply Zpower_le_monotone; auto with zarith.
+ pattern (2 ^ [[ww_head1 x]]) at 1;
+ rewrite <- (Zmult_1_r (2 ^ [[ww_head1 x]])).
+ apply Zmult_le_compat_l; auto with zarith.
+ generalize (spec_ww_add_mul_div x W0 (ww_head1 x) Hv2);
+ case ww_add_mul_div.
simpl ww_to_Z; autorewrite with w_rewrite rm10.
rewrite Zmod_def_small; auto with zarith.
intros H2; case (Zmult_integral _ _ (sym_equal H2)); clear H2; intros H2.
@@ -1228,9 +1260,14 @@ Section GenSqrt.
end.
apply Zpower_lt_0; auto with zarith.
split; auto with zarith.
- case (Hp2 H1); intros _ tmp; apply Zle_lt_trans with (2 := tmp);
+ case Hp2; intros _ tmp; apply Zle_lt_trans with (2 := tmp);
clear tmp.
rewrite Zmult_comm; apply Zmult_le_compat_r; auto with zarith.
+ assert (Hv0: [[ww_head1 x]] = 2 * ([[ww_head1 x]]/2)).
+ pattern [[ww_head1 x]] at 1; rewrite (Z_div_mod_eq [[ww_head1 x]] 2);
+ auto with zarith.
+ generalize (spec_ww_is_even (ww_head1 x)); rewrite Hp1;
+ intros tmp; rewrite tmp; rewrite Zplus_0_r; auto.
intros w0 w1; autorewrite with w_rewrite rm10.
rewrite Zmod_def_small; auto with zarith.
2: rewrite Zmult_comm; auto with zarith.
@@ -1243,42 +1280,71 @@ Section GenSqrt.
assert (V1 := spec_to_Z w1);auto with zarith.
generalize (@spec_w_sqrt2 w0 w1 V);auto with zarith.
case (w_sqrt2 w0 w1); intros w2 c.
+ case (spec_to_Z w2); intros HH1 HH2.
simpl ww_to_Z; simpl fst.
- assert (U2: Zpos (Pdiv2 p) < Zpos w_digits).
- apply Zmult_lt_reg_r with 2; auto with zarith.
- repeat rewrite (fun x => Zmult_comm x 2).
- rewrite Hp3.
- rewrite <- Zpos_xO; auto.
- autorewrite with w_rewrite rm10.
- 2: rewrite Zpos_minus; auto with zarith; auto.
- rewrite Zpos_minus; auto with zarith.
- match goal with |- context[?X - (?X -?Y)] =>
- replace (X - (X - Y)) with Y; try ring
- end.
- assert (V2 := spec_to_Z w2);auto with zarith.
- rewrite Zmod_def_small; auto with zarith.
+ assert (Hv3: [[ww_pred ww_zdigits]]
+ = Zpos (xO w_digits) - 1).
+ rewrite spec_ww_pred; rewrite spec_ww_zdigits.
+ rewrite Zmod_def_small; auto with zarith.
+ split; auto with zarith.
+ apply Zlt_le_trans with (Zpos (xO w_digits)); auto with zarith.
+ unfold base; apply Zpower2_le_lin; auto with zarith.
+ assert (Hv4: [[ww_head1 x]]/2 < wB).
+ apply Zle_lt_trans with (Zpos w_digits).
+ apply Zmult_le_reg_r with 2; auto with zarith.
+ repeat rewrite (fun x => Zmult_comm x 2).
+ rewrite <- Hv0; rewrite <- Zpos_xO; auto.
+ unfold base; apply Zpower2_lt_lin; auto with zarith.
+ assert (Hv5: [[(ww_add_mul_div (ww_pred ww_zdigits) W0 (ww_head1 x))]]
+ = [[ww_head1 x]]/2).
+ rewrite spec_ww_add_mul_div.
+ simpl ww_to_Z; autorewrite with rm10.
+ rewrite Hv3.
+ ring_simplify (Zpos (xO w_digits) - (Zpos (xO w_digits) - 1)).
+ rewrite Zpower_exp_1.
+ rewrite Zmod_def_small; auto with zarith.
+ split; auto with zarith.
+ apply Zlt_le_trans with (1 := Hv4); auto with zarith.
+ unfold base; apply Zpower_le_monotone; auto with zarith.
+ split; unfold ww_digits; try rewrite Zpos_xO; auto with zarith.
+ rewrite Hv3; auto with zarith.
+ assert (Hv6: [|low(ww_add_mul_div (ww_pred ww_zdigits) W0 (ww_head1 x))|]
+ = [[ww_head1 x]]/2).
+ rewrite spec_low.
+ rewrite Hv5; rewrite Zmod_def_small; auto with zarith.
+ rewrite spec_w_add_mul_div; auto with zarith.
+ rewrite spec_w_sub; auto with zarith.
+ rewrite spec_w_0.
+ simpl ww_to_Z; autorewrite with rm10.
+ rewrite Hv6; rewrite spec_w_zdigits.
+ rewrite (fun x y => Zmod_def_small (x - y)).
+ ring_simplify (Zpos w_digits - (Zpos w_digits - [[ww_head1 x]] / 2)).
+ rewrite Zmod_def_small.
simpl ww_to_Z in H2; rewrite H2; auto with zarith.
intros (H4, H5); split.
- apply Zmult_le_reg_r with (2 ^ Zpos p); auto with zarith.
+ apply Zmult_le_reg_r with (2 ^ [[ww_head1 x]]); auto with zarith.
rewrite H4.
apply Zle_trans with ([|w2|] ^ 2); auto with zarith.
- repeat rewrite (fun x => Zmult_comm x (2 ^ Zpos p)).
- rewrite <- Hp3; rewrite (Zmult_comm 2); rewrite Zpower_mult;
- auto with zarith.
+ rewrite Zmult_comm.
+ pattern [[ww_head1 x]] at 1;
+ rewrite Hv0; auto with zarith.
+ rewrite (Zmult_comm 2); rewrite Zpower_mult;
+ auto with zarith.
assert (tmp: forall p q, p ^ 2 * q ^ 2 = (p * q) ^2);
try (intros; repeat rewrite Zsquare_mult; ring);
rewrite tmp; clear tmp.
apply ZPowerAux.Zpower_le_monotone_exp; auto with zarith.
split; auto with zarith.
- pattern [|w2|] at 2; rewrite (Z_div_mod_eq [|w2|] (2 ^ Zpos (Pdiv2 p)));
- auto with zarith.
+ pattern [|w2|] at 2;
+ rewrite (Z_div_mod_eq [|w2|] (2 ^ ([[ww_head1 x]] / 2)));
+ auto with zarith.
match goal with |- ?X <= ?X + ?Y =>
assert (0 <= Y); auto with zarith
end.
- case (Z_mod_lt [|w2|] (2 ^ Zpos (Pdiv2 p))); auto with zarith.
+ case (Z_mod_lt [|w2|] (2 ^ ([[ww_head1 x]] / 2))); auto with zarith.
case c; unfold interp_carry; autorewrite with rm10;
intros w3; assert (V3 := spec_to_Z w3);auto with zarith.
- apply Zmult_lt_reg_r with (2 ^ Zpos p); auto with zarith.
+ apply Zmult_lt_reg_r with (2 ^ [[ww_head1 x]]); auto with zarith.
rewrite H4.
apply Zle_lt_trans with ([|w2|] ^ 2 + 2 * [|w2|]); auto with zarith.
apply Zlt_le_trans with (([|w2|] + 1) ^ 2); auto with zarith.
@@ -1286,19 +1352,20 @@ Section GenSqrt.
replace Y with (X + 1); auto with zarith
end.
repeat rewrite (Zsquare_mult); ring.
- repeat rewrite (fun x => Zmult_comm x (2 ^ Zpos p)).
- rewrite <- Hp3; rewrite (Zmult_comm 2); rewrite Zpower_mult;
+ rewrite Zmult_comm.
+ pattern [[ww_head1 x]] at 1; rewrite Hv0.
+ rewrite (Zmult_comm 2); rewrite Zpower_mult;
auto with zarith.
assert (tmp: forall p q, p ^ 2 * q ^ 2 = (p * q) ^2);
try (intros; repeat rewrite Zsquare_mult; ring);
rewrite tmp; clear tmp.
apply ZPowerAux.Zpower_le_monotone_exp; auto with zarith.
split; auto with zarith.
- pattern [|w2|] at 1; rewrite (Z_div_mod_eq [|w2|] (2 ^ Zpos (Pdiv2 p)));
+ pattern [|w2|] at 1; rewrite (Z_div_mod_eq [|w2|] (2 ^ ([[ww_head1 x]]/2)));
auto with zarith.
rewrite <- Zplus_assoc; rewrite Zmult_plus_distr_r.
autorewrite with rm10; apply Zplus_le_compat_l; auto with zarith.
- case (Z_mod_lt [|w2|] (2 ^ Zpos (Pdiv2 p))); auto with zarith.
+ case (Z_mod_lt [|w2|] (2 ^ ([[ww_head1 x]]/2))); auto with zarith.
split; auto with zarith.
apply Zle_lt_trans with ([|w2|]); auto with zarith.
apply Zdiv_le_upper_bound; auto with zarith.
@@ -1307,6 +1374,21 @@ Section GenSqrt.
apply Zmult_le_compat_l; auto with zarith.
apply Zpower_le_monotone; auto with zarith.
rewrite Zpower_exp_0; autorewrite with rm10; auto.
+ split; auto with zarith.
+ rewrite Hv0 in Hv2; rewrite (Zpos_xO w_digits) in Hv2; auto with zarith.
+ apply Zle_lt_trans with (Zpos w_digits); auto with zarith.
+ unfold base; apply Zpower2_lt_lin; auto with zarith.
+ rewrite spec_w_sub; auto with zarith.
+ rewrite Hv6; rewrite spec_w_zdigits; auto with zarith.
+ assert (Hv7: 0 < [[ww_head1 x]]/2); auto with zarith.
+ rewrite Zmod_def_small; auto with zarith.
+ split; auto with zarith.
+ assert ([[ww_head1 x]]/2 <= Zpos w_digits); auto with zarith.
+ apply Zmult_le_reg_r with 2; auto with zarith.
+ repeat rewrite (fun x => Zmult_comm x 2).
+ rewrite <- Hv0; rewrite <- Zpos_xO; auto with zarith.
+ apply Zle_lt_trans with (Zpos w_digits); auto with zarith.
+ unfold base; apply Zpower2_lt_lin; auto with zarith.
Qed.
End GenSqrt.
diff --git a/theories/Ints/num/NMake.v b/theories/Ints/num/NMake.v
index c7cd3360fc..dbc893c84b 100644
--- a/theories/Ints/num/NMake.v
+++ b/theories/Ints/num/NMake.v
@@ -2317,57 +2317,70 @@ Module Make (W0:W0Type).
Definition w12_div_gt := w12_op.(znz_div_gt).
Definition w0_divn1 :=
- gen_divn1 w0_op.(znz_digits) w0_op.(znz_0)
+ gen_divn1 w0_op.(znz_zdigits) w0_op.(znz_0)
w0_op.(znz_WW) w0_op.(znz_head0)
- w0_op.(znz_add_mul_div) w0_op.(znz_div21).
+ w0_op.(znz_add_mul_div) w0_op.(znz_div21)
+ w0_op.(znz_compare) w0_op.(znz_sub).
Definition w1_divn1 :=
- gen_divn1 w1_op.(znz_digits) w1_op.(znz_0)
+ gen_divn1 w1_op.(znz_zdigits) w1_op.(znz_0)
w1_op.(znz_WW) w1_op.(znz_head0)
- w1_op.(znz_add_mul_div) w1_op.(znz_div21).
+ w1_op.(znz_add_mul_div) w1_op.(znz_div21)
+ w1_op.(znz_compare) w1_op.(znz_sub).
Definition w2_divn1 :=
- gen_divn1 w2_op.(znz_digits) w2_op.(znz_0)
+ gen_divn1 w2_op.(znz_zdigits) w2_op.(znz_0)
w2_op.(znz_WW) w2_op.(znz_head0)
- w2_op.(znz_add_mul_div) w2_op.(znz_div21).
+ w2_op.(znz_add_mul_div) w2_op.(znz_div21)
+ w2_op.(znz_compare) w2_op.(znz_sub).
Definition w3_divn1 :=
- gen_divn1 w3_op.(znz_digits) w3_op.(znz_0)
+ gen_divn1 w3_op.(znz_zdigits) w3_op.(znz_0)
w3_op.(znz_WW) w3_op.(znz_head0)
- w3_op.(znz_add_mul_div) w3_op.(znz_div21).
+ w3_op.(znz_add_mul_div) w3_op.(znz_div21)
+ w3_op.(znz_compare) w3_op.(znz_sub).
Definition w4_divn1 :=
- gen_divn1 w4_op.(znz_digits) w4_op.(znz_0)
+ gen_divn1 w4_op.(znz_zdigits) w4_op.(znz_0)
w4_op.(znz_WW) w4_op.(znz_head0)
- w4_op.(znz_add_mul_div) w4_op.(znz_div21).
+ w4_op.(znz_add_mul_div) w4_op.(znz_div21)
+ w4_op.(znz_compare) w4_op.(znz_sub).
Definition w5_divn1 :=
- gen_divn1 w5_op.(znz_digits) w5_op.(znz_0)
+ gen_divn1 w5_op.(znz_zdigits) w5_op.(znz_0)
w5_op.(znz_WW) w5_op.(znz_head0)
- w5_op.(znz_add_mul_div) w5_op.(znz_div21).
+ w5_op.(znz_add_mul_div) w5_op.(znz_div21)
+ w5_op.(znz_compare) w5_op.(znz_sub).
Definition w6_divn1 :=
- gen_divn1 w6_op.(znz_digits) w6_op.(znz_0)
+ gen_divn1 w6_op.(znz_zdigits) w6_op.(znz_0)
w6_op.(znz_WW) w6_op.(znz_head0)
- w6_op.(znz_add_mul_div) w6_op.(znz_div21).
+ w6_op.(znz_add_mul_div) w6_op.(znz_div21)
+ w6_op.(znz_compare) w6_op.(znz_sub).
Definition w7_divn1 :=
- gen_divn1 w7_op.(znz_digits) w7_op.(znz_0)
+ gen_divn1 w7_op.(znz_zdigits) w7_op.(znz_0)
w7_op.(znz_WW) w7_op.(znz_head0)
- w7_op.(znz_add_mul_div) w7_op.(znz_div21).
+ w7_op.(znz_add_mul_div) w7_op.(znz_div21)
+ w7_op.(znz_compare) w7_op.(znz_sub).
Definition w8_divn1 :=
- gen_divn1 w8_op.(znz_digits) w8_op.(znz_0)
+ gen_divn1 w8_op.(znz_zdigits) w8_op.(znz_0)
w8_op.(znz_WW) w8_op.(znz_head0)
- w8_op.(znz_add_mul_div) w8_op.(znz_div21).
+ w8_op.(znz_add_mul_div) w8_op.(znz_div21)
+ w8_op.(znz_compare) w8_op.(znz_sub).
Definition w9_divn1 :=
- gen_divn1 w9_op.(znz_digits) w9_op.(znz_0)
+ gen_divn1 w9_op.(znz_zdigits) w9_op.(znz_0)
w9_op.(znz_WW) w9_op.(znz_head0)
- w9_op.(znz_add_mul_div) w9_op.(znz_div21).
+ w9_op.(znz_add_mul_div) w9_op.(znz_div21)
+ w9_op.(znz_compare) w9_op.(znz_sub).
Definition w10_divn1 :=
- gen_divn1 w10_op.(znz_digits) w10_op.(znz_0)
+ gen_divn1 w10_op.(znz_zdigits) w10_op.(znz_0)
w10_op.(znz_WW) w10_op.(znz_head0)
- w10_op.(znz_add_mul_div) w10_op.(znz_div21).
+ w10_op.(znz_add_mul_div) w10_op.(znz_div21)
+ w10_op.(znz_compare) w10_op.(znz_sub).
Definition w11_divn1 :=
- gen_divn1 w11_op.(znz_digits) w11_op.(znz_0)
+ gen_divn1 w11_op.(znz_zdigits) w11_op.(znz_0)
w11_op.(znz_WW) w11_op.(znz_head0)
- w11_op.(znz_add_mul_div) w11_op.(znz_div21).
+ w11_op.(znz_add_mul_div) w11_op.(znz_div21)
+ w11_op.(znz_compare) w11_op.(znz_sub).
Definition w12_divn1 :=
- gen_divn1 w12_op.(znz_digits) w12_op.(znz_0)
+ gen_divn1 w12_op.(znz_zdigits) w12_op.(znz_0)
w12_op.(znz_WW) w12_op.(znz_head0)
- w12_op.(znz_add_mul_div) w12_op.(znz_div21).
+ w12_op.(znz_add_mul_div) w12_op.(znz_div21)
+ w12_op.(znz_compare) w12_op.(znz_sub).
Definition div_gt x y :=
match x, y with
@@ -2913,44 +2926,57 @@ Module Make (W0:W0Type).
Definition w12_mod_gt := w12_op.(znz_mod_gt).
Definition w0_modn1 :=
- gen_modn1 w0_op.(znz_digits) w0_op.(znz_0)
- w0_op.(znz_head0) w0_op.(znz_add_mul_div) w0_op.(znz_div21).
+ gen_modn1 w0_op.(znz_zdigits) w0_op.(znz_0)
+ w0_op.(znz_head0) w0_op.(znz_add_mul_div) w0_op.(znz_div21)
+ w0_op.(znz_compare) w0_op.(znz_sub).
Definition w1_modn1 :=
- gen_modn1 w1_op.(znz_digits) w1_op.(znz_0)
- w1_op.(znz_head0) w1_op.(znz_add_mul_div) w1_op.(znz_div21).
+ gen_modn1 w1_op.(znz_zdigits) w1_op.(znz_0)
+ w1_op.(znz_head0) w1_op.(znz_add_mul_div) w1_op.(znz_div21)
+ w1_op.(znz_compare) w1_op.(znz_sub).
Definition w2_modn1 :=
- gen_modn1 w2_op.(znz_digits) w2_op.(znz_0)
- w2_op.(znz_head0) w2_op.(znz_add_mul_div) w2_op.(znz_div21).
+ gen_modn1 w2_op.(znz_zdigits) w2_op.(znz_0)
+ w2_op.(znz_head0) w2_op.(znz_add_mul_div) w2_op.(znz_div21)
+ w2_op.(znz_compare) w2_op.(znz_sub).
Definition w3_modn1 :=
- gen_modn1 w3_op.(znz_digits) w3_op.(znz_0)
- w3_op.(znz_head0) w3_op.(znz_add_mul_div) w3_op.(znz_div21).
+ gen_modn1 w3_op.(znz_zdigits) w3_op.(znz_0)
+ w3_op.(znz_head0) w3_op.(znz_add_mul_div) w3_op.(znz_div21)
+ w3_op.(znz_compare) w3_op.(znz_sub).
Definition w4_modn1 :=
- gen_modn1 w4_op.(znz_digits) w4_op.(znz_0)
- w4_op.(znz_head0) w4_op.(znz_add_mul_div) w4_op.(znz_div21).
+ gen_modn1 w4_op.(znz_zdigits) w4_op.(znz_0)
+ w4_op.(znz_head0) w4_op.(znz_add_mul_div) w4_op.(znz_div21)
+ w4_op.(znz_compare) w4_op.(znz_sub).
Definition w5_modn1 :=
- gen_modn1 w5_op.(znz_digits) w5_op.(znz_0)
- w5_op.(znz_head0) w5_op.(znz_add_mul_div) w5_op.(znz_div21).
+ gen_modn1 w5_op.(znz_zdigits) w5_op.(znz_0)
+ w5_op.(znz_head0) w5_op.(znz_add_mul_div) w5_op.(znz_div21)
+ w5_op.(znz_compare) w5_op.(znz_sub).
Definition w6_modn1 :=
- gen_modn1 w6_op.(znz_digits) w6_op.(znz_0)
- w6_op.(znz_head0) w6_op.(znz_add_mul_div) w6_op.(znz_div21).
+ gen_modn1 w6_op.(znz_zdigits) w6_op.(znz_0)
+ w6_op.(znz_head0) w6_op.(znz_add_mul_div) w6_op.(znz_div21)
+ w6_op.(znz_compare) w6_op.(znz_sub).
Definition w7_modn1 :=
- gen_modn1 w7_op.(znz_digits) w7_op.(znz_0)
- w7_op.(znz_head0) w7_op.(znz_add_mul_div) w7_op.(znz_div21).
+ gen_modn1 w7_op.(znz_zdigits) w7_op.(znz_0)
+ w7_op.(znz_head0) w7_op.(znz_add_mul_div) w7_op.(znz_div21)
+ w7_op.(znz_compare) w7_op.(znz_sub).
Definition w8_modn1 :=
- gen_modn1 w8_op.(znz_digits) w8_op.(znz_0)
- w8_op.(znz_head0) w8_op.(znz_add_mul_div) w8_op.(znz_div21).
+ gen_modn1 w8_op.(znz_zdigits) w8_op.(znz_0)
+ w8_op.(znz_head0) w8_op.(znz_add_mul_div) w8_op.(znz_div21)
+ w8_op.(znz_compare) w8_op.(znz_sub).
Definition w9_modn1 :=
- gen_modn1 w9_op.(znz_digits) w9_op.(znz_0)
- w9_op.(znz_head0) w9_op.(znz_add_mul_div) w9_op.(znz_div21).
+ gen_modn1 w9_op.(znz_zdigits) w9_op.(znz_0)
+ w9_op.(znz_head0) w9_op.(znz_add_mul_div) w9_op.(znz_div21)
+ w9_op.(znz_compare) w9_op.(znz_sub).
Definition w10_modn1 :=
- gen_modn1 w10_op.(znz_digits) w10_op.(znz_0)
- w10_op.(znz_head0) w10_op.(znz_add_mul_div) w10_op.(znz_div21).
+ gen_modn1 w10_op.(znz_zdigits) w10_op.(znz_0)
+ w10_op.(znz_head0) w10_op.(znz_add_mul_div) w10_op.(znz_div21)
+ w10_op.(znz_compare) w10_op.(znz_sub).
Definition w11_modn1 :=
- gen_modn1 w11_op.(znz_digits) w11_op.(znz_0)
- w11_op.(znz_head0) w11_op.(znz_add_mul_div) w11_op.(znz_div21).
+ gen_modn1 w11_op.(znz_zdigits) w11_op.(znz_0)
+ w11_op.(znz_head0) w11_op.(znz_add_mul_div) w11_op.(znz_div21)
+ w11_op.(znz_compare) w11_op.(znz_sub).
Definition w12_modn1 :=
- gen_modn1 w12_op.(znz_digits) w12_op.(znz_0)
- w12_op.(znz_head0) w12_op.(znz_add_mul_div) w12_op.(znz_div21).
+ gen_modn1 w12_op.(znz_zdigits) w12_op.(znz_0)
+ w12_op.(znz_head0) w12_op.(znz_add_mul_div) w12_op.(znz_div21)
+ w12_op.(znz_compare) w12_op.(znz_sub).
Definition mod_gt x y :=
match x, y with
diff --git a/theories/Ints/num/Zn2Z.v b/theories/Ints/num/Zn2Z.v
index b5c6466584..ac13d6922e 100644
--- a/theories/Ints/num/Zn2Z.v
+++ b/theories/Ints/num/Zn2Z.v
@@ -30,6 +30,7 @@ Section Zn2Z.
Variable w : Set.
Variable w_op : znz_op w.
Let w_digits := w_op.(znz_digits).
+ Let w_zdigits := w_op.(znz_zdigits).
Variable more_than_one_digit: 1 < Zpos w_digits.
@@ -98,8 +99,12 @@ Section Zn2Z.
Let ww_1 := ww_1 w_0 w_1.
Let ww_Bm1 := ww_Bm1 w_Bm1.
+ Let w_add2 a b := match w_add_c a b with C0 p => WW w_0 p | C1 p => WW w_1 p end.
+
Let _ww_digits := xO w_digits.
+ Let _ww_zdigits := w_add2 w_zdigits w_zdigits.
+
Let to_Z := zn2z_to_Z wB w_to_Z.
Let ww_of_pos p :=
@@ -109,9 +114,10 @@ Section Zn2Z.
let (n,h) := w_of_pos ph in (n, w_WW h l)
end.
+
Let head0 :=
Eval lazy beta delta [ww_head0] in
- ww_head0 w_0 w_compare w_head0 w_digits _ww_digits.
+ ww_head0 w_0 w_0W w_compare w_head0 w_add2 w_zdigits _ww_zdigits.
Let ww_WW := Eval lazy beta delta [ww_WW] in (@ww_WW w).
Let ww_0W := Eval lazy beta delta [ww_0W] in (@ww_0W w).
@@ -215,47 +221,53 @@ Section Zn2Z.
Eval lazy beta iota delta [ww_div21] in
ww_div21 w_0 w_0W div32 ww_1 compare sub.
+ Let low (p: zn2z w) := match p with WW _ p1 => p1 | _ => w_0 end.
+
Let add_mul_div :=
Eval lazy beta delta [ww_add_mul_div] in
- ww_add_mul_div w_0 w_WW w_W0 w_0W w_add_mul_div w_digits.
+ ww_add_mul_div w_0 w_WW w_W0 w_0W compare w_add_mul_div sub w_zdigits low.
Let div_gt :=
Eval lazy beta delta [ww_div_gt] in
- ww_div_gt w_digits w_0 w_WW w_0W w_compare w_eq0 w_sub_c w_sub w_sub_carry
- w_div_gt w_add_mul_div w_head0 w_div21 div32 _ww_digits ww_1 add_mul_div.
+ ww_div_gt w_0 w_WW w_0W w_compare w_eq0 w_opp_c w_opp
+ w_opp_carry w_sub_c w_sub w_sub_carry
+ w_div_gt w_add_mul_div w_head0 w_div21 div32 _ww_zdigits ww_1 add_mul_div w_zdigits.
Let div :=
Eval lazy beta delta [ww_div] in ww_div ww_1 compare div_gt.
Let mod_gt :=
Eval lazy beta delta [ww_mod_gt] in
- ww_mod_gt w_digits w_0 w_WW w_0W w_compare w_eq0 w_sub_c w_sub w_sub_carry
- w_mod_gt w_add_mul_div w_head0 w_div21 div32 _ww_digits add_mul_div.
+ ww_mod_gt w_0 w_WW w_0W w_compare w_eq0 w_opp_c w_opp w_opp_carry w_sub_c w_sub w_sub_carry
+ w_mod_gt w_add_mul_div w_head0 w_div21 div32 _ww_zdigits add_mul_div w_zdigits.
Let mod_ :=
Eval lazy beta delta [ww_mod] in ww_mod compare mod_gt.
Let pos_mod :=
- Eval lazy beta delta [ww_pos_mod] in ww_pos_mod w_0 w_digits w_WW w_pos_mod.
+ Eval lazy beta delta [ww_pos_mod] in
+ ww_pos_mod w_0 w_zdigits w_WW w_pos_mod compare w_0W low sub _ww_zdigits.
Let is_even :=
Eval lazy beta delta [ww_is_even] in ww_is_even w_is_even.
Let sqrt2 :=
Eval lazy beta delta [ww_sqrt2] in
- ww_sqrt2 w_is_even w_compare w_0 w_1 w_Bm1 w_sub w_square_c
- w_div21 w_add_mul_div w_digits w_add_c w_sqrt2 pred_c
+ ww_sqrt2 w_is_even w_compare w_0 w_1 w_Bm1 w_0W w_sub w_square_c
+ w_div21 w_add_mul_div w_zdigits w_add_c w_sqrt2 w_pred pred_c
pred add_c add sub_c add_mul_div.
Let sqrt :=
Eval lazy beta delta [ww_sqrt] in
- ww_sqrt w_0 w_add_mul_div w_digits w_sqrt2
- add_mul_div head0 compare.
+ ww_sqrt w_is_even w_0 w_sub w_add_mul_div w_zdigits
+ _ww_zdigits w_sqrt2 pred add_mul_div head0 compare low.
Let gcd_gt_fix :=
Eval cbv beta delta [ww_gcd_gt_aux ww_gcd_gt_body] in
- ww_gcd_gt_aux w_digits w_0 w_WW w_compare w_sub_c w_sub w_sub_carry w_gcd_gt
- w_add_mul_div w_head0 w_div21 div32 _ww_digits add_mul_div.
+ ww_gcd_gt_aux w_0 w_WW w_0W w_compare w_opp_c w_opp w_opp_carry
+ w_sub_c w_sub w_sub_carry w_gcd_gt
+ w_add_mul_div w_head0 w_div21 div32 _ww_zdigits add_mul_div
+ w_zdigits.
Let gcd_cont :=
Eval lazy beta delta [gcd_cont] in gcd_cont ww_1 w_1 w_compare.
@@ -271,7 +283,7 @@ Section Zn2Z.
(* ** Record of operators on 2 words *)
Definition mk_zn2z_op :=
- mk_znz_op _ww_digits
+ mk_znz_op _ww_digits _ww_zdigits
to_Z ww_of_pos head0
W0 ww_1 ww_Bm1
ww_WW ww_W0 ww_0W
@@ -292,7 +304,7 @@ Section Zn2Z.
sqrt.
Definition mk_zn2z_op_karatsuba :=
- mk_znz_op _ww_digits
+ mk_znz_op _ww_digits _ww_zdigits
to_Z ww_of_pos head0
W0 ww_1 ww_Bm1
ww_WW ww_W0 ww_0W
@@ -588,22 +600,65 @@ Section Zn2Z.
_ _ _ _ _ _ _);auto. exact (spec_0W op_spec).
Qed.
+ Let spec_add2: forall x y,
+ [|w_add2 x y|] = w_to_Z x + w_to_Z y.
+ unfold w_add2.
+ intros xh xl; generalize (spec_add_c op_spec xh xl).
+ unfold w_add_c; case znz_add_c; unfold interp_carry; simpl ww_to_Z.
+ intros w0 Hw0; simpl; unfold w_to_Z; rewrite Hw0.
+ unfold w_0; rewrite spec_0; simpl; auto with zarith.
+ intros w0; rewrite Zmult_1_l; simpl.
+ unfold w_to_Z, w_1; rewrite spec_1; auto with zarith.
+ rewrite Zmult_1_l; auto.
+ Qed.
+
+ Let spec_low: forall x,
+ w_to_Z (low x) = [|x|] mod wB.
+ intros x; case x; simpl low.
+ unfold ww_to_Z, w_to_Z, w_0; rewrite (spec_0 op_spec); simpl.
+ rewrite Zmod_def_small; auto with zarith.
+ split; auto with zarith.
+ unfold wB, base; auto with zarith.
+ intros xh xl; simpl.
+ rewrite Zplus_comm; rewrite Z_mod_plus; auto with zarith.
+ rewrite Zmod_def_small; auto with zarith.
+ unfold wB, base; auto with zarith.
+ Qed.
+
+ Let spec_ww_digits:
+ [|_ww_zdigits|] = Zpos (xO w_digits).
+ Proof.
+ unfold w_to_Z, _ww_zdigits.
+ rewrite spec_add2.
+ unfold w_to_Z, w_zdigits, w_digits.
+ rewrite spec_zdigits; auto.
+ rewrite Zpos_xO; auto with zarith.
+ Qed.
+
Let spec_ww_head0 : forall x, 0 < [|x|] ->
- wwB/ 2 <= 2 ^ (Z_of_N (head0 x)) * [|x|] < wwB.
+ wwB/ 2 <= 2 ^ [|head0 x|] * [|x|] < wwB.
Proof.
- refine (spec_ww_head0 w_0 w_compare w_head0 w_digits _ww_digits
- w_to_Z _ _ _ _);auto. exact (spec_compare op_spec).
+ refine (spec_ww_head0 w_0 w_0W w_compare w_head0
+ w_add2 w_zdigits _ww_zdigits
+ w_to_Z _ _ _ _ _ _ _);auto.
+ exact (spec_0W op_spec).
+ exact (spec_compare op_spec).
+ exact (spec_zdigits op_spec).
Qed.
Lemma spec_ww_add_mul_div : forall x y p,
- Zpos p < Zpos _ww_digits ->
+ [|p|] <= Zpos _ww_digits ->
[| add_mul_div p x y |] =
- ([|x|] * (Zpower 2 (Zpos p)) +
- [|y|] / (Zpower 2 ((Zpos _ww_digits) - (Zpos p)))) mod wwB.
+ ([|x|] * (2 ^ [|p|]) +
+ [|y|] / (2 ^ ((Zpos _ww_digits) - [|p|]))) mod wwB.
Proof.
- refine (@spec_ww_add_mul_div w w_0 w_WW w_W0 w_0W w_add_mul_div w_digits
- w_to_Z _ _ _ _ _ _);auto. exact (spec_WW op_spec).
- exact (spec_W0 op_spec). exact (spec_0W op_spec).
+ refine (@spec_ww_add_mul_div w w_0 w_WW w_W0 w_0W compare w_add_mul_div
+ sub w_digits w_zdigits low w_to_Z
+ _ _ _ _ _ _ _ _ _ _ _);auto.
+ exact (spec_WW op_spec).
+ exact (spec_W0 op_spec).
+ exact (spec_0W op_spec).
+ exact (spec_zdigits op_spec).
Qed.
Let spec_ww_div_gt : forall a b,
@@ -611,13 +666,33 @@ Section Zn2Z.
let (q,r) := div_gt a b in
[|a|] = [|q|] * [|b|] + [|r|] /\ 0 <= [|r|] < [|b|].
Proof.
- refine (@spec_ww_div_gt w w_digits w_0 w_WW w_0W w_compare w_eq0
+refine
+(@spec_ww_div_gt w w_digits w_0 w_WW w_0W w_compare w_eq0
w_opp_c w_opp w_opp_carry w_sub_c w_sub w_sub_carry w_div_gt
- w_add_mul_div w_head0 w_div21 div32 _ww_digits ww_1 add_mul_div w_to_Z
- _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _);auto.
- exact (spec_WW op_spec). exact (spec_0W op_spec).
- exact (spec_compare op_spec). exact (spec_div_gt op_spec).
- exact (spec_div21 op_spec). exact spec_ww_add_mul_div.
+ w_add_mul_div w_head0 w_div21 div32 _ww_zdigits ww_1 add_mul_div w_zdigits w_to_Z
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+).
+ exact (spec_0 op_spec).
+ exact (spec_to_Z op_spec).
+ exact (spec_WW op_spec).
+ exact (spec_0W op_spec).
+ exact (spec_compare op_spec).
+ exact (spec_eq0 op_spec).
+ exact (spec_opp_c op_spec).
+ exact (spec_opp op_spec).
+ exact (spec_opp_carry op_spec).
+ exact (spec_sub_c op_spec).
+ exact (spec_sub op_spec).
+ exact (spec_sub_carry op_spec).
+ exact (spec_div_gt op_spec).
+ exact (spec_add_mul_div op_spec).
+ exact (spec_head0 op_spec).
+ exact (spec_div21 op_spec).
+ exact spec_w_div32.
+ exact (spec_zdigits op_spec).
+ exact spec_ww_digits.
+ exact spec_ww_1.
+ exact spec_ww_add_mul_div.
Qed.
Let spec_ww_div : forall a b, 0 < [|b|] ->
@@ -634,11 +709,16 @@ Section Zn2Z.
Proof.
refine (@spec_ww_mod_gt w w_digits w_0 w_WW w_0W w_compare w_eq0
w_opp_c w_opp w_opp_carry w_sub_c w_sub w_sub_carry w_div_gt w_mod_gt
- w_add_mul_div w_head0 w_div21 div32 _ww_digits ww_1 add_mul_div w_to_Z
- _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _);auto.
- exact (spec_WW op_spec). exact (spec_0W op_spec).
- exact (spec_compare op_spec). exact (spec_div_gt op_spec).
- exact (spec_div21 op_spec). exact spec_ww_add_mul_div.
+ w_add_mul_div w_head0 w_div21 div32 _ww_zdigits ww_1 add_mul_div
+ w_zdigits w_to_Z
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _);auto.
+ exact (spec_WW op_spec).
+ exact (spec_0W op_spec).
+ exact (spec_compare op_spec).
+ exact (spec_div_gt op_spec).
+ exact (spec_div21 op_spec).
+ exact (spec_zdigits op_spec).
+ exact spec_ww_add_mul_div.
Qed.
Let spec_ww_mod : forall a b, 0 < [|b|] -> [|mod_ a b|] = [|a|] mod [|b|].
@@ -652,28 +732,38 @@ Section Zn2Z.
refine (@spec_ww_gcd_gt w w_digits W0 w_to_Z _
w_0 w_0 w_eq0 w_gcd_gt _ww_digits
_ gcd_gt_fix _ _ _ _ gcd_cont _);auto.
- refine (@spec_ww_gcd_gt_aux w w_digits w_0 w_WW w_compare w_opp_c w_opp
+ refine (@spec_ww_gcd_gt_aux w w_digits w_0 w_WW w_0W w_compare w_opp_c w_opp
w_opp_carry w_sub_c w_sub w_sub_carry w_gcd_gt w_add_mul_div w_head0
- w_div21 div32 _ww_digits ww_1 add_mul_div w_to_Z
- _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _);auto.
- exact (spec_WW op_spec). exact (spec_compare op_spec).
- exact (spec_div21 op_spec). exact spec_ww_add_mul_div.
+ w_div21 div32 _ww_zdigits ww_1 add_mul_div w_zdigits w_to_Z
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _);auto.
+ exact (spec_WW op_spec).
+ exact (spec_0W op_spec).
+ exact (spec_compare op_spec).
+ exact (spec_div21 op_spec).
+ exact (spec_zdigits op_spec).
+ exact spec_ww_add_mul_div.
refine (@spec_gcd_cont w w_digits ww_1 w_to_Z _ _ w_0 w_1 w_compare
- _ _);auto. exact (spec_compare op_spec).
+ _ _);auto.
+ exact (spec_compare op_spec).
Qed.
Let spec_ww_gcd : forall a b, Zis_gcd [|a|] [|b|] [|gcd a b|].
Proof.
refine (@spec_ww_gcd w w_digits W0 compare w_to_Z _ _ w_0 w_0 w_eq0 w_gcd_gt
_ww_digits _ gcd_gt_fix _ _ _ _ gcd_cont _);auto.
- refine (@spec_ww_gcd_gt_aux w w_digits w_0 w_WW w_compare w_opp_c w_opp
+ refine (@spec_ww_gcd_gt_aux w w_digits w_0 w_WW w_0W w_compare w_opp_c w_opp
w_opp_carry w_sub_c w_sub w_sub_carry w_gcd_gt w_add_mul_div w_head0
- w_div21 div32 _ww_digits ww_1 add_mul_div w_to_Z
- _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _);auto.
- exact (spec_WW op_spec). exact (spec_compare op_spec).
- exact (spec_div21 op_spec). exact spec_ww_add_mul_div.
+ w_div21 div32 _ww_zdigits ww_1 add_mul_div w_zdigits w_to_Z
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _);auto.
+ exact (spec_WW op_spec).
+ exact (spec_0W op_spec).
+ exact (spec_compare op_spec).
+ exact (spec_div21 op_spec).
+ exact (spec_zdigits op_spec).
+ exact spec_ww_add_mul_div.
refine (@spec_gcd_cont w w_digits ww_1 w_to_Z _ _ w_0 w_1 w_compare
- _ _);auto. exact (spec_compare op_spec).
+ _ _);auto.
+ exact (spec_compare op_spec).
Qed.
Let spec_ww_is_even : forall x,
@@ -682,7 +772,7 @@ Section Zn2Z.
| false => [|x|] mod 2 = 1
end.
Proof.
- refine (@spec_ww_is_even w w_is_even w_0 w_1 w_Bm1 w_digits _ _ _); auto.
+ refine (@spec_ww_is_even w w_is_even w_0 w_1 w_Bm1 w_digits _ _ _ _ _); auto.
exact (spec_is_even op_spec).
Qed.
@@ -694,9 +784,12 @@ Section Zn2Z.
Proof.
intros x y H.
refine (@spec_ww_sqrt2 w w_is_even w_compare w_0 w_1 w_Bm1
- w_sub w_square_c w_div21 w_add_mul_div w_digits
- w_add_c w_sqrt2 pred_c pred add_c add sub_c add_mul_div
- _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _); auto.
+ w_0W w_sub w_square_c w_div21 w_add_mul_div w_digits w_zdigits
+ _ww_zdigits
+ w_add_c w_sqrt2 w_pred pred_c pred add_c add sub_c add_mul_div
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _); auto.
+ exact (spec_zdigits op_spec).
+ exact (spec_0W op_spec).
exact (spec_is_even op_spec).
exact (spec_compare op_spec).
exact (spec_square_c op_spec).
@@ -708,9 +801,12 @@ Section Zn2Z.
Let spec_ww_sqrt : forall x,
[|sqrt x|] ^ 2 <= [|x|] < ([|sqrt x|] + 1) ^ 2.
Proof.
- refine (@spec_ww_sqrt w w_0 w_1 w_Bm1 w_add_mul_div w_digits
- w_sqrt2 add_mul_div head0 compare
- _ _ _ _ _ _ _ _ _ _); auto.
+ refine (@spec_ww_sqrt w w_is_even w_0 w_1 w_Bm1
+ w_sub w_add_mul_div w_digits w_zdigits _ww_zdigits
+ w_sqrt2 pred add_mul_div head0 compare
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _); auto.
+ exact (spec_zdigits op_spec).
+ exact (spec_is_even op_spec).
exact (spec_ww_add_mul_div).
exact (spec_sqrt2 op_spec).
Qed.
@@ -719,17 +815,35 @@ Section Zn2Z.
Proof.
apply mk_znz_spec;auto.
exact spec_ww_add_mul_div.
- refine (@spec_ww_pos_mod w w_0 w_digits w_WW w_pos_mod w_to_Z
- _ _ _ _);auto. exact (spec_WW op_spec). exact (spec_pos_mod op_spec).
+
+ refine (@spec_ww_pos_mod w w_0 w_digits w_zdigits w_WW
+ w_pos_mod compare w_0W low sub _ww_zdigits w_to_Z
+ _ _ _ _ _ _ _ _ _ _ _ _);auto.
+ exact (spec_WW op_spec).
+ exact (spec_pos_mod op_spec).
+ exact (spec_0W op_spec).
+ exact (spec_zdigits op_spec).
+ unfold w_to_Z, w_zdigits.
+ rewrite (spec_zdigits op_spec).
+ rewrite <- Zpos_xO; exact spec_ww_digits.
Qed.
Lemma mk_znz2_karatsuba_spec : znz_spec mk_zn2z_op_karatsuba.
Proof.
apply mk_znz_spec;auto.
exact spec_ww_add_mul_div.
- refine (@spec_ww_pos_mod w w_0 w_digits w_WW w_pos_mod w_to_Z
- _ _ _ _);auto. exact (spec_WW op_spec). exact (spec_pos_mod op_spec).
+ refine (@spec_ww_pos_mod w w_0 w_digits w_zdigits w_WW
+ w_pos_mod compare w_0W low sub _ww_zdigits w_to_Z
+ _ _ _ _ _ _ _ _ _ _ _ _);auto.
+ exact (spec_WW op_spec).
+ exact (spec_pos_mod op_spec).
+ exact (spec_0W op_spec).
+ exact (spec_zdigits op_spec).
+ unfold w_to_Z, w_zdigits.
+ rewrite (spec_zdigits op_spec).
+ rewrite <- Zpos_xO; exact spec_ww_digits.
Qed.
+
End Zn2Z.
diff --git a/theories/Ints/num/ZnZ.v b/theories/Ints/num/ZnZ.v
index 5efcad2d0f..5096c81cf8 100644
--- a/theories/Ints/num/ZnZ.v
+++ b/theories/Ints/num/ZnZ.v
@@ -23,9 +23,10 @@ Section ZnZ_Op.
Record znz_op : Set := mk_znz_op {
(* Conversion functions with Z *)
znz_digits : positive;
+ znz_zdigits: znz;
znz_to_Z : znz -> Z;
znz_of_pos : positive -> N * znz;
- znz_head0 : znz -> N;
+ znz_head0 : znz -> znz;
(* Basic constructors *)
znz_0 : znz;
znz_1 : znz;
@@ -71,8 +72,8 @@ Section ZnZ_Op.
znz_gcd_gt : znz -> znz -> znz;
znz_gcd : znz -> znz -> znz;
- znz_add_mul_div : positive -> znz -> znz -> znz;
- znz_pos_mod : positive -> znz -> znz;
+ znz_add_mul_div : znz -> znz -> znz -> znz;
+ znz_pos_mod : znz -> znz -> znz;
(* square root *)
znz_is_even : znz -> bool;
@@ -86,6 +87,7 @@ Section Spec.
Variable w_op : znz_op w.
Let w_digits := w_op.(znz_digits).
+ Let w_zdigits := w_op.(znz_zdigits).
Let w_to_Z := w_op.(znz_to_Z).
Let w_of_pos := w_op.(znz_of_pos).
Let w_head0 := w_op.(znz_head0).
@@ -163,6 +165,7 @@ Section Spec.
spec_to_Z : forall x, 0 <= [| x |] < wB;
spec_of_pos : forall p,
Zpos p = (Z_of_N (fst (w_of_pos p)))*wB + [|(snd (w_of_pos p))|];
+ spec_zdigits : [| w_zdigits |] = Zpos w_digits;
(* Basic constructors *)
spec_0 : [|w0|] = 0;
@@ -234,14 +237,14 @@ Section Spec.
(* shift operations *)
spec_head0 : forall x, 0 < [|x|] ->
- wB/ 2 <= 2 ^ (Z_of_N (w_head0 x)) * [|x|] < wB;
+ wB/ 2 <= 2 ^ ([|w_head0 x|]) * [|x|] < wB;
spec_add_mul_div : forall x y p,
- Zpos p < Zpos w_digits ->
+ [|p|] <= Zpos w_digits ->
[| w_add_mul_div p x y |] =
- ([|x|] * (Zpower 2 (Zpos p)) +
- [|y|] / (Zpower 2 ((Zpos w_digits) - (Zpos p)))) mod wB;
+ ([|x|] * (2 ^ [|p|]) +
+ [|y|] / (2 ^ ((Zpos w_digits) - [|p|]))) mod wB;
spec_pos_mod : forall w p,
- [|w_pos_mod p w|] = [|w|] mod (2 ^ Zpos p);
+ [|w_pos_mod p w|] = [|w|] mod (2 ^ [|p|]);
(* sqrt *)
spec_is_even : forall x,
if w_is_even x then [|x|] mod 2 = 0 else [|x|] mod 2 = 1;