Library begcd
Require Import Psatz.
Require Import ssreflect ssrbool eqtype.
Require Import Arith_ext ZArith_ext Lists_ext.
Require Import integral_type nodup.
Ltac myomega := first [lia | omega].
Require Import simu.
Import simu.simu_m.
Ltac local_Var_unchanged v st :=
match goal with
| |- context [syntax_m.seplog_m.assert_m.expr_m.store.get v ?st'] =>
cutrewrite (syntax_m.seplog_m.assert_m.expr_m.store.get v st' =
syntax_m.seplog_m.assert_m.expr_m.store.get v st);
[ idtac |
symmetry;
Var_unchanged ;
rewrite [syntax_m.seplog_m.modified_vars _]/= ;
Nodup_not_In ; fail ]
end.
Ltac Not_In_dom2list :=
match goal with
| |- ~ In _ (seq_ext.s2l (assoc.dom _)) =>
let hypo := fresh in
assoc.From_dom_to_list hypo ;
simpl in hypo ;
apply (Permutation_notin _ _ _ hypo) ;
clear hypo
| |- ~ In _ (seq_ext.s2l (assoc.cdom _)) =>
let hypo := fresh in
assoc.From_cdom_to_list hypo ;
simpl in hypo ;
apply (Permutation_notin _ _ _ hypo) ;
clear hypo
end.
Ltac Disj_f_cdom2list K :=
match goal with
| |- Lists_ext.disj _ (?f (seq_ext.s2l (assoc.cdom _))) =>
let hypo := fresh in
assoc.From_cdom_to_list hypo ;
simpl in hypo ;
let subgoal := fresh in
cut ( (Permutation_preserving f) );
[ intro subgoal ;
apply subgoal in hypo ;
apply (Permutation_disj_R _ _ _ hypo) ;
clear hypo ;
simpl f
|
exact K
]
| |- Lists_ext.disj (?f (seq_ext.s2l (assoc.cdom _))) _ =>
let hypo := fresh in
assoc.From_cdom_to_list hypo ;
simpl in hypo ;
let subgoal := fresh in
cut (Permutation_preserving f) ;
[ intro subgoal ;
apply subgoal in hypo ;
apply (Permutation_disj_L _ _ _ hypo) ;
clear hypo ;
simpl f
|
exact K
]
end.
Module EGCD.
Import syntax_m.seplog_m.assert_m.expr_m.
Import syntax_m.seplog_m.assert_m.
Import syntax_m.seplog_m.
Local Open Scope seplog_cmd_scope.
Local Open Scope seplog_expr_scope.
Local Open Scope nodup_scope.
Local Open Scope zarith_ext_scope.
Lemma div_e_exact_full_2 : forall e s,
[ e ]e_ s mod 2 = 0 -> 2 * [ e ./e nat_e 2 ]e_s = [ e ]e_s.
Require Import ssreflect ssrbool eqtype.
Require Import Arith_ext ZArith_ext Lists_ext.
Require Import integral_type nodup.
Ltac myomega := first [lia | omega].
Require Import simu.
Import simu.simu_m.
Ltac local_Var_unchanged v st :=
match goal with
| |- context [syntax_m.seplog_m.assert_m.expr_m.store.get v ?st'] =>
cutrewrite (syntax_m.seplog_m.assert_m.expr_m.store.get v st' =
syntax_m.seplog_m.assert_m.expr_m.store.get v st);
[ idtac |
symmetry;
Var_unchanged ;
rewrite [syntax_m.seplog_m.modified_vars _]/= ;
Nodup_not_In ; fail ]
end.
Ltac Not_In_dom2list :=
match goal with
| |- ~ In _ (seq_ext.s2l (assoc.dom _)) =>
let hypo := fresh in
assoc.From_dom_to_list hypo ;
simpl in hypo ;
apply (Permutation_notin _ _ _ hypo) ;
clear hypo
| |- ~ In _ (seq_ext.s2l (assoc.cdom _)) =>
let hypo := fresh in
assoc.From_cdom_to_list hypo ;
simpl in hypo ;
apply (Permutation_notin _ _ _ hypo) ;
clear hypo
end.
Ltac Disj_f_cdom2list K :=
match goal with
| |- Lists_ext.disj _ (?f (seq_ext.s2l (assoc.cdom _))) =>
let hypo := fresh in
assoc.From_cdom_to_list hypo ;
simpl in hypo ;
let subgoal := fresh in
cut ( (Permutation_preserving f) );
[ intro subgoal ;
apply subgoal in hypo ;
apply (Permutation_disj_R _ _ _ hypo) ;
clear hypo ;
simpl f
|
exact K
]
| |- Lists_ext.disj (?f (seq_ext.s2l (assoc.cdom _))) _ =>
let hypo := fresh in
assoc.From_cdom_to_list hypo ;
simpl in hypo ;
let subgoal := fresh in
cut (Permutation_preserving f) ;
[ intro subgoal ;
apply subgoal in hypo ;
apply (Permutation_disj_L _ _ _ hypo) ;
clear hypo ;
simpl f
|
exact K
]
end.
Module EGCD.
Import syntax_m.seplog_m.assert_m.expr_m.
Import syntax_m.seplog_m.assert_m.
Import syntax_m.seplog_m.
Local Open Scope seplog_cmd_scope.
Local Open Scope seplog_expr_scope.
Local Open Scope nodup_scope.
Local Open Scope zarith_ext_scope.
Lemma div_e_exact_full_2 : forall e s,
[ e ]e_ s mod 2 = 0 -> 2 * [ e ./e nat_e 2 ]e_s = [ e ]e_s.
prelude of binary gcd algorithms
Definition prelude x y g :=
while.while (var_e x mode nat_e 2 =e nat_e O &e var_e y mode nat_e 2 =e nat_e O) (
x <- var_e x ./e nat_e 2 ;
y <- var_e y ./e nat_e 2 ;
g <- var_e g *e nat_e 2 ).
Local Open Scope seplog_hoare_scope.
while.while (var_e x mode nat_e 2 =e nat_e O &e var_e y mode nat_e 2 =e nat_e O) (
x <- var_e x ./e nat_e 2 ;
y <- var_e y ./e nat_e 2 ;
g <- var_e g *e nat_e 2 ).
Local Open Scope seplog_hoare_scope.
binary gcd algorithm
Module BGCD_HAC.
Definition bgcd g x y t :=
g <- nat_e 1 ;
prelude x y g ;
while.while (var_e x >> nat_e 0) (
while.while (var_e x mode nat_e 2 =e nat_e 0) ( x <- var_e x ./e nat_e 2 ) ;
while.while (var_e y mode nat_e 2 =e nat_e 0) ( y <- var_e y ./e nat_e 2 ) ;
t <- (uop_e valabs_e (var_e x .-e var_e y)) ./e nat_e 2 ;
ifte (var_e x >>= var_e y) thendo
(x <- var_e t)
elsedo
(y <- var_e t)
).
Section bgcd_hac.
Variables x y g t : ssrnat.nat_eqType.
Variables vx vy : Z.
Lemma prelude_verif : nodup(x, y, g) -> 0 <= vx -> 0 <= vy ->
{{ fun s _ => 0 <= [ x ]_s /\ 0 <= [ y ]_s /\ 0 <= [ g ]_s /\
[ x ]_ s * [ g ]_ s = vx /\ [ y ]_ s * [ g ]_ s = vy }}
prelude x y g
{{ fun s _ => 0 <= [ x ]_ s /\ 0 <= [ y ]_ s /\ 0 <= [ g ]_ s /\
[ x ]_ s * [ g ]_ s = vx /\ [ y ]_ s * [ g ]_ s = vy /\
~~ [ (var_e x mode nat_e 2 =e nat_e 0) &e (var_e y mode nat_e 2 =e nat_e 0) ]b_ s }}.
Proof.
move=> Hset Hvx Hvy.
apply hoare_prop_m.hoare_while_invariant with (fun s _ =>
0 <= [ x ]_ s /\ 0 <= [ y ]_ s /\ 0 <= [ g ]_ s /\
[ x ]_ s * [g ]_ s = vx /\ [ y ]_ s * [ g ]_ s = vy ).
by move=> s h /= [H1 [H2 [H3 [H4 H5]]]].
by move=> s h /= [[H1 [H2 [H3 [H4 H5]]]] H6].
Definition bgcd g x y t :=
g <- nat_e 1 ;
prelude x y g ;
while.while (var_e x >> nat_e 0) (
while.while (var_e x mode nat_e 2 =e nat_e 0) ( x <- var_e x ./e nat_e 2 ) ;
while.while (var_e y mode nat_e 2 =e nat_e 0) ( y <- var_e y ./e nat_e 2 ) ;
t <- (uop_e valabs_e (var_e x .-e var_e y)) ./e nat_e 2 ;
ifte (var_e x >>= var_e y) thendo
(x <- var_e t)
elsedo
(y <- var_e t)
).
Section bgcd_hac.
Variables x y g t : ssrnat.nat_eqType.
Variables vx vy : Z.
Lemma prelude_verif : nodup(x, y, g) -> 0 <= vx -> 0 <= vy ->
{{ fun s _ => 0 <= [ x ]_s /\ 0 <= [ y ]_s /\ 0 <= [ g ]_s /\
[ x ]_ s * [ g ]_ s = vx /\ [ y ]_ s * [ g ]_ s = vy }}
prelude x y g
{{ fun s _ => 0 <= [ x ]_ s /\ 0 <= [ y ]_ s /\ 0 <= [ g ]_ s /\
[ x ]_ s * [ g ]_ s = vx /\ [ y ]_ s * [ g ]_ s = vy /\
~~ [ (var_e x mode nat_e 2 =e nat_e 0) &e (var_e y mode nat_e 2 =e nat_e 0) ]b_ s }}.
Proof.
move=> Hset Hvx Hvy.
apply hoare_prop_m.hoare_while_invariant with (fun s _ =>
0 <= [ x ]_ s /\ 0 <= [ y ]_ s /\ 0 <= [ g ]_ s /\
[ x ]_ s * [g ]_ s = vx /\ [ y ]_ s * [ g ]_ s = vy ).
by move=> s h /= [H1 [H2 [H3 [H4 H5]]]].
by move=> s h /= [[H1 [H2 [H3 [H4 H5]]]] H6].
x <- var_e x ./e nat_e 2
apply hoare_assign with (fun s h => 0 <= [ x ]_s /\ 0 <= [ y ]_s /\ 0 <= [ g ]_s /\
2 * [ x ]_s * [ g ]_s = vx /\ [ y ]_s * [ g ]_s = vy /\ [ y ]_s mod 2 = 0).
move=> s h [[H1 [H2 [H3 [H4 H5]]]] H6].
rewrite /wp_assign.
repeat Store_upd => //.
split; first by apply Z_div_pos.
repeat (split; first by assumption).
split.
- rewrite div_e_exact_full_2 //; by rewrite /hoare_m.eval_b in H6; omegab.
split; first by assumption.
- by rewrite /hoare_m.eval_b in H6; omegab.
2 * [ x ]_s * [ g ]_s = vx /\ [ y ]_s * [ g ]_s = vy /\ [ y ]_s mod 2 = 0).
move=> s h [[H1 [H2 [H3 [H4 H5]]]] H6].
rewrite /wp_assign.
repeat Store_upd => //.
split; first by apply Z_div_pos.
repeat (split; first by assumption).
split.
- rewrite div_e_exact_full_2 //; by rewrite /hoare_m.eval_b in H6; omegab.
split; first by assumption.
- by rewrite /hoare_m.eval_b in H6; omegab.
y <- var_e y ./e nat_e 2;
apply hoare_assign with (fun s h => 0 <= [ x ]_s /\ 0 <= [ y ]_s /\ 0 <= [ g ]_s /\
2 * [ x ]_s * [ g ]_s = vx /\ 2 * [ y ]_s * [ g ]_ s = vy).
move=> s h [H1 [H2 [H3 [H4 [H5 H6]]]]].
rewrite /wp_assign; repeat Store_upd => //.
split; first by assumption.
split; first by apply Z_div_pos.
repeat (split; first by assumption).
by rewrite div_e_exact_full_2.
2 * [ x ]_s * [ g ]_s = vx /\ 2 * [ y ]_s * [ g ]_ s = vy).
move=> s h [H1 [H2 [H3 [H4 [H5 H6]]]]].
rewrite /wp_assign; repeat Store_upd => //.
split; first by assumption.
split; first by apply Z_div_pos.
repeat (split; first by assumption).
by rewrite div_e_exact_full_2.
g <- nat_e 2 *e var_e g
apply hoare_assign'.
move=> s h [H1 [H2 [H3 [H4 H5]]]].
rewrite /wp_assign; repeat Store_upd => //.
repeat (split; first by assumption).
split; first by apply Zmult_le_0_compat.
split; rewrite /= -?H4 -?H5 /ZIT.t_mult; ring.
Qed.
Lemma bgcd_verif : nodup(x, y, g, t) -> 0 <= vx -> 0 <= vy ->
{{ fun s h => [x]_s = vx /\ [y]_s = vy }}
bgcd g x y t
{{ fun s h => 0 <= [ x ]_s /\ 0 <= [ y ]_s /\ 0 <= [ g ]_s /\
Zis_gcd vx vy ([ g ]_s * [y]_s)}}.
Proof.
move=> Hset Hvx Hvy.
rewrite /bgcd.
move=> s h [H1 [H2 [H3 [H4 H5]]]].
rewrite /wp_assign; repeat Store_upd => //.
repeat (split; first by assumption).
split; first by apply Zmult_le_0_compat.
split; rewrite /= -?H4 -?H5 /ZIT.t_mult; ring.
Qed.
Lemma bgcd_verif : nodup(x, y, g, t) -> 0 <= vx -> 0 <= vy ->
{{ fun s h => [x]_s = vx /\ [y]_s = vy }}
bgcd g x y t
{{ fun s h => 0 <= [ x ]_s /\ 0 <= [ y ]_s /\ 0 <= [ g ]_s /\
Zis_gcd vx vy ([ g ]_s * [y]_s)}}.
Proof.
move=> Hset Hvx Hvy.
rewrite /bgcd.
g <- nat_e 1 ;
apply hoare_assign with (fun s _ => [x ]_ s = vx /\ [y ]_ s = vy /\ [g ]_ s = 1).
move=> s h; rewrite /wp_assign; move=> [Hx Hy].
by repeat Store_upd => //.
move=> s h; rewrite /wp_assign; move=> [Hx Hy].
by repeat Store_upd => //.
prelude x y g
apply while.hoare_seq with (fun s _ =>
0 <= [x]_s /\ 0 <= [y]_s /\ 0 <= [g]_s /\
Zgcd vx vy = [g]_s * Zgcd ([x]_s) ([y]_s) /\
~ [ ((var_e x mode nat_e 2) =e nat_e O) &e ((var_e y mode nat_e 2) =e nat_e O) ]b_ s).
have Hset' : nodup(x, y, g).
rewrite [Equality.sort _]/= in Hset *; by Nodup_nodup O.
eapply while.hoare_conseq; last by apply (prelude_verif Hset' Hvx Hvy).
- move=> s h /= [H1 [H2 [H3 [H4 [H5 H6]]]]].
repeat (split => //).
+ rewrite -H4 -H5.
apply Zis_gcd_gcd; last first.
rewrite (Zmult_comm [x]_s) (Zmult_comm [y]_s).
by apply Zis_gcd_mult, Zgcd_is_gcd.
apply Zmult_le_0_compat => //; by apply Zgcd_is_pos.
+ by move/negP: H6.
- move=> s h /= [-> [-> ->]]; by rewrite 2!Zmult_1_r.
0 <= [x]_s /\ 0 <= [y]_s /\ 0 <= [g]_s /\
Zgcd vx vy = [g]_s * Zgcd ([x]_s) ([y]_s) /\
~ [ ((var_e x mode nat_e 2) =e nat_e O) &e ((var_e y mode nat_e 2) =e nat_e O) ]b_ s).
have Hset' : nodup(x, y, g).
rewrite [Equality.sort _]/= in Hset *; by Nodup_nodup O.
eapply while.hoare_conseq; last by apply (prelude_verif Hset' Hvx Hvy).
- move=> s h /= [H1 [H2 [H3 [H4 [H5 H6]]]]].
repeat (split => //).
+ rewrite -H4 -H5.
apply Zis_gcd_gcd; last first.
rewrite (Zmult_comm [x]_s) (Zmult_comm [y]_s).
by apply Zis_gcd_mult, Zgcd_is_gcd.
apply Zmult_le_0_compat => //; by apply Zgcd_is_pos.
+ by move/negP: H6.
- move=> s h /= [-> [-> ->]]; by rewrite 2!Zmult_1_r.
while (nat_e x >> nat_e 0)
apply hoare_prop_m.hoare_while_invariant with (fun s _ => 0 <= [x]_s /\ 0 <= [y]_s /\ 0 <= [g]_s /\
(Zodd [x]_s \/ Zodd [y]_s) /\
Zgcd vx vy = [g]_s * Zgcd ([x]_s) ([y]_s)).
- move=> s h [Hx_pos [Hy_pos [Hg_pos [H1 H2]]]].
repeat (split => //).
rewrite /= in H2.
move/negP : H2.
rewrite negb_and.
case/orP ;
move/Zeq_boolP ;
move/not_Zmod_2_Zodd ;
by auto.
- move=> s h [[Hx_pos [Hy_pos [Hg_pos [Hparity Hgcd]]]] Hx].
repeat (split; first by assumption).
have {Hx} : [x ]_ s = 0.
move: Hx.
rewrite /hoare_m.eval_b /= ZIT.t_gt_t_ge.
move/ZIT.t_geb_true.
rewrite /ZIT.t_ge => ?; by myomega.
rewrite /= => Hx.
rewrite Hx /= Zabs_eq // in Hgcd.
rewrite -Hgcd.
by apply Zgcd_is_gcd.
(Zodd [x]_s \/ Zodd [y]_s) /\
Zgcd vx vy = [g]_s * Zgcd ([x]_s) ([y]_s)).
- move=> s h [Hx_pos [Hy_pos [Hg_pos [H1 H2]]]].
repeat (split => //).
rewrite /= in H2.
move/negP : H2.
rewrite negb_and.
case/orP ;
move/Zeq_boolP ;
move/not_Zmod_2_Zodd ;
by auto.
- move=> s h [[Hx_pos [Hy_pos [Hg_pos [Hparity Hgcd]]]] Hx].
repeat (split; first by assumption).
have {Hx} : [x ]_ s = 0.
move: Hx.
rewrite /hoare_m.eval_b /= ZIT.t_gt_t_ge.
move/ZIT.t_geb_true.
rewrite /ZIT.t_ge => ?; by myomega.
rewrite /= => Hx.
rewrite Hx /= Zabs_eq // in Hgcd.
rewrite -Hgcd.
by apply Zgcd_is_gcd.
while (var_e x mode nat_e 2 =e nat_e 0)
apply while.hoare_seq with (fun s _ => 0 <= [x ]_ s /\ 0 <= [y ]_ s /\ 0 <= [g ]_ s /\
Zodd [x]_s /\
Zgcd vx vy = [g ]_ s * Zgcd [x ]_ s [y ]_ s).
- apply hoare_prop_m.hoare_while_invariant with (fun s _ =>
0 <= [x ]_ s /\ 0 <= [y ]_ s /\ 0 <= [g ]_ s /\
(Zodd [x ]_ s \/ Zodd [y ]_ s) /\
Zgcd vx vy = [g ]_ s * Zgcd [x ]_ s [y ]_ s).
+ by move=> s h /= [[H2 [H3 [H4 [H5 H6]]]] H1].
+ move=> s h /= [[H2 [H3 [H4 [H5 H6]]]]] //.
move/Zeq_boolP.
by move/not_Zmod_2_Zodd.
+ apply hoare_assign' => s h /= [[H2 [H3 [H4 [H5 H6]]]] H1].
rewrite /wp_assign; repeat Store_upd => //.
split; first by apply Z_div_pos.
do 2 split => //.
case: H5 => H5.
* move/Zeq_boolP : H1.
move/Zmod_2_Zeven.
by move/Zeven_not_Zodd.
* split; first by auto.
rewrite /= -Zgcd_even_odd //.
move/Zeq_boolP : H1.
by move/Zmod_2_Zeven.
- apply while.hoare_seq with (fun s _ => 0 <= [x ]_ s /\ 0 <= [y ]_ s /\ 0 <= [g ]_ s /\
Zodd [x ]_ s /\ Zodd [y]_s /\
Zgcd vx vy = [g ]_ s * Zgcd [x ]_ s [y ]_ s).
+ apply hoare_prop_m.hoare_while_invariant with (fun s _ =>
0 <= [x ]_ s /\ 0 <= [y ]_ s /\ 0 <= [g ]_ s /\
Zodd [x ]_ s /\ Zgcd vx vy = [g ]_ s * Zgcd [x ]_ s [y ]_ s) => //.
* move=> s h /= [[H2 [H3 [H4 [H5 H6]]]] H1].
repeat (split => //).
move/Zeq_boolP : H1.
by move/not_Zmod_2_Zodd.
* apply hoare_assign' => s h /= [[H2 [H3 [H4 [H5 H6]]]] H1].
rewrite /wp_assign; repeat Store_upd => //.
split; first by assumption.
split; first by apply Z_div_pos.
repeat (split; first by assumption).
rewrite /= (Zgcd_sym [x]_s) -Zgcd_even_odd //.
by rewrite (Zgcd_sym [y]_s).
move/Zeq_boolP : H1; by move/Zmod_2_Zeven.
+ apply hoare_assign with (fun s _ => (0 <= [x ]_ s /\ 0 <= [y ]_ s /\ 0 <= [g ]_ s /\
Zodd [x ]_ s /\ Zodd [y]_s /\
Zgcd vx vy = [g ]_ s * Zgcd [x ]_ s [y ]_ s /\
[t]_s = Zabs ([x]_s - [y]_s) / 2)).
move=> s h /= [Hx_pos [Hy_pos [Hg_pos [Hx [Hy Hgcd]]]]].
by rewrite /wp_assign; repeat Store_upd.
apply while.hoare_ifte.
+ apply hoare_assign'.
move=> s h /= [[Hx_pos [Hy_pos [Hg_pos [Hx [Hy [Hgcd Ht]]]]]] Hcond].
rewrite /wp_assign; repeat Store_upd => //.
split.
* rewrite /= Ht.
apply Z_div_pos => //; by apply Zabs_pos.
* repeat (split; first by assumption).
split; first by right.
rewrite /= Ht Zabs_eq; last first.
rewrite /ZIT.t_geb in Hcond.
move/Zge_bool_true : Hcond => ?; by myomega.
rewrite -Zgcd_even_odd //; last first.
apply Zodd_plus_Zodd => //; by apply Zodd_opp.
by rewrite -Zgcd_minus.
- apply hoare_assign' => s h /= [[Hx_pos [Hy_pos [Hg_pos [Hx [Hy [Hgcd Ht]]]]]] Hcond].
rewrite /wp_assign; repeat Store_upd => //.
split; first by done.
split.
* rewrite /= Ht.
apply Z_div_pos => //; by apply Zabs_pos.
* split; first by done.
split; first by left.
rewrite /= Ht Zabs_non_eq; last first.
rewrite /ZIT.t_geb in Hcond.
move/negbTE : Hcond.
move/Zge_bool_false => ?; by myomega.
rewrite Zopp_plus_distr Zopp_involutive Zplus_comm (Zgcd_sym [x]_s) -Zgcd_even_odd //; last first.
apply Zodd_plus_Zodd => //; by apply Zodd_opp.
by rewrite -Zgcd_minus (Zgcd_sym [y]_s).
Qed.
End bgcd_hac.
End BGCD_HAC.
Zodd [x]_s /\
Zgcd vx vy = [g ]_ s * Zgcd [x ]_ s [y ]_ s).
- apply hoare_prop_m.hoare_while_invariant with (fun s _ =>
0 <= [x ]_ s /\ 0 <= [y ]_ s /\ 0 <= [g ]_ s /\
(Zodd [x ]_ s \/ Zodd [y ]_ s) /\
Zgcd vx vy = [g ]_ s * Zgcd [x ]_ s [y ]_ s).
+ by move=> s h /= [[H2 [H3 [H4 [H5 H6]]]] H1].
+ move=> s h /= [[H2 [H3 [H4 [H5 H6]]]]] //.
move/Zeq_boolP.
by move/not_Zmod_2_Zodd.
+ apply hoare_assign' => s h /= [[H2 [H3 [H4 [H5 H6]]]] H1].
rewrite /wp_assign; repeat Store_upd => //.
split; first by apply Z_div_pos.
do 2 split => //.
case: H5 => H5.
* move/Zeq_boolP : H1.
move/Zmod_2_Zeven.
by move/Zeven_not_Zodd.
* split; first by auto.
rewrite /= -Zgcd_even_odd //.
move/Zeq_boolP : H1.
by move/Zmod_2_Zeven.
- apply while.hoare_seq with (fun s _ => 0 <= [x ]_ s /\ 0 <= [y ]_ s /\ 0 <= [g ]_ s /\
Zodd [x ]_ s /\ Zodd [y]_s /\
Zgcd vx vy = [g ]_ s * Zgcd [x ]_ s [y ]_ s).
+ apply hoare_prop_m.hoare_while_invariant with (fun s _ =>
0 <= [x ]_ s /\ 0 <= [y ]_ s /\ 0 <= [g ]_ s /\
Zodd [x ]_ s /\ Zgcd vx vy = [g ]_ s * Zgcd [x ]_ s [y ]_ s) => //.
* move=> s h /= [[H2 [H3 [H4 [H5 H6]]]] H1].
repeat (split => //).
move/Zeq_boolP : H1.
by move/not_Zmod_2_Zodd.
* apply hoare_assign' => s h /= [[H2 [H3 [H4 [H5 H6]]]] H1].
rewrite /wp_assign; repeat Store_upd => //.
split; first by assumption.
split; first by apply Z_div_pos.
repeat (split; first by assumption).
rewrite /= (Zgcd_sym [x]_s) -Zgcd_even_odd //.
by rewrite (Zgcd_sym [y]_s).
move/Zeq_boolP : H1; by move/Zmod_2_Zeven.
+ apply hoare_assign with (fun s _ => (0 <= [x ]_ s /\ 0 <= [y ]_ s /\ 0 <= [g ]_ s /\
Zodd [x ]_ s /\ Zodd [y]_s /\
Zgcd vx vy = [g ]_ s * Zgcd [x ]_ s [y ]_ s /\
[t]_s = Zabs ([x]_s - [y]_s) / 2)).
move=> s h /= [Hx_pos [Hy_pos [Hg_pos [Hx [Hy Hgcd]]]]].
by rewrite /wp_assign; repeat Store_upd.
apply while.hoare_ifte.
+ apply hoare_assign'.
move=> s h /= [[Hx_pos [Hy_pos [Hg_pos [Hx [Hy [Hgcd Ht]]]]]] Hcond].
rewrite /wp_assign; repeat Store_upd => //.
split.
* rewrite /= Ht.
apply Z_div_pos => //; by apply Zabs_pos.
* repeat (split; first by assumption).
split; first by right.
rewrite /= Ht Zabs_eq; last first.
rewrite /ZIT.t_geb in Hcond.
move/Zge_bool_true : Hcond => ?; by myomega.
rewrite -Zgcd_even_odd //; last first.
apply Zodd_plus_Zodd => //; by apply Zodd_opp.
by rewrite -Zgcd_minus.
- apply hoare_assign' => s h /= [[Hx_pos [Hy_pos [Hg_pos [Hx [Hy [Hgcd Ht]]]]]] Hcond].
rewrite /wp_assign; repeat Store_upd => //.
split; first by done.
split.
* rewrite /= Ht.
apply Z_div_pos => //; by apply Zabs_pos.
* split; first by done.
split; first by left.
rewrite /= Ht Zabs_non_eq; last first.
rewrite /ZIT.t_geb in Hcond.
move/negbTE : Hcond.
move/Zge_bool_false => ?; by myomega.
rewrite Zopp_plus_distr Zopp_involutive Zplus_comm (Zgcd_sym [x]_s) -Zgcd_even_odd //; last first.
apply Zodd_plus_Zodd => //; by apply Zodd_opp.
by rewrite -Zgcd_minus (Zgcd_sym [y]_s).
Qed.
End bgcd_hac.
End BGCD_HAC.
extended binary gcd algorithm from the Handbook of Applied Cryptography
Module BEGCD_HAC.
Definition inner_loop u x y A B :=
while.while (var_e u mode nat_e 2 =e nat_e O) (
u <- var_e u ./e nat_e 2 ;
ifte (var_e A mode nat_e 2 =e nat_e O &e var_e B mode nat_e 2 =e nat_e O) thendo
( A <- var_e A ./e nat_e 2 ;
B <- var_e B ./e nat_e 2 )
elsedo
( A <- (var_e A +e var_e y) ./e nat_e 2 ;
B <- (var_e B .-e var_e x) ./e nat_e 2 )
).
Definition branch u v A B C D :=
u <- var_e u .-e var_e v ;
A <- var_e A .-e var_e C ;
B <- var_e B .-e var_e D.
Definition outer_loop u v x y A B C D :=
while.while (var_e u >> nat_e 0) (
inner_loop u x y A B;
inner_loop v x y C D;
ifte (var_e u >>= var_e v) thendo
branch u v A B C D
elsedo
branch v u C D A B
).
Definition begcd g x y u v A B C D :=
g <- nat_e 1 ;
prelude x y g ;
u <- var_e x ;
v <- var_e y ;
A <- nat_e 1 ;
B <- nat_e O ;
C <- nat_e O ;
D <- nat_e 1 ;
outer_loop u v x y A B C D.
Lemma inner_loop_verif : forall (x y g u v : ssrnat.nat_eqType) vx vy (A B C D : bipl.var.v),
nodup(x, y, g, u, v, A, B, C, D) ->
{{fun s _ => 0 <= [x ]_ s /\ 0 <= [y ]_ s /\ 0 <= [g ]_ s /\ 0 <= [u ]_ s /\ 0 <= [v ]_ s /\
[ x ]_ s * [ g ]_ s = vx /\ [y ]_ s * [g ]_ s = vy /\
[ A ]_ s * [ x ]_ s + [B ]_ s * [y ]_ s = [u ]_ s /\
[ C ]_ s * [ x ]_ s + [D ]_ s * [y ]_ s = [v ]_ s /\
Zgcd vx vy = [g ]_ s * Zgcd [u ]_ s [v ]_ s /\
(Zodd [x]_s \/ Zodd [y]_s) /\
(Zodd [u]_s \/ Zodd [v]_s) }}
inner_loop u x y A B
{{fun s _ => 0 <= [x ]_ s /\ 0 <= [y ]_ s /\ 0 <= [g ]_ s /\ 0 <= [u ]_ s /\ 0 <= [v ]_ s /\
[x ]_ s * [g ]_ s = vx /\ [y ]_ s * [g ]_ s = vy /\
[ A ]_ s * [ x ]_ s + [B ]_ s * [y ]_ s = [u ]_ s /\
[ C ]_ s * [ x ]_ s + [ D ]_ s * [y ]_ s = [v ]_ s /\
Zgcd vx vy = [g ]_ s * Zgcd [u ]_ s [v ]_ s /\
(Zodd [ x ]_s \/ Zodd [ y ]_s) /\
Zodd [ u ]_s }}.
Proof.
move=> x y g u v vx vy A B C D Hset.
apply hoare_prop_m.hoare_while_invariant with (fun s _ =>
0 <= [x ]_ s /\ 0 <= [y ]_ s /\ 0 <= [g ]_ s /\ 0 <= [u ]_ s /\ 0 <= [v ]_ s /\
[x ]_ s * [g ]_ s = vx /\ [y ]_ s * [g ]_ s = vy /\
[A ]_ s * [x ]_ s + [B ]_ s * [y ]_ s = [u ]_ s /\
[C ]_ s * [x ]_ s + [D ]_ s * [y ]_ s = [v ]_ s /\
Zgcd vx vy = [g ]_ s * Zgcd [u ]_ s [v ]_ s /\
(Zodd [x]_s \/ Zodd [y]_s) /\
(Zodd [u]_s \/ Zodd [v]_s)).
move=> s h /= [H2 [H3 [H4 [H5 [H6 [H7 [H8 [H9 [H10 [H11 [H12 H13]]]]]]]]]]].
by intuition.
move=> s h /= [[H2 [H3 [H4 [H5 [H6 [H7 [H8 [H9 [H10 [H11 [H12 H13]]]]]]]]]]] H1].
repeat (split => //).
move/ZIT.tP : H1.
by move/not_Zmod_2_Zodd.
Definition inner_loop u x y A B :=
while.while (var_e u mode nat_e 2 =e nat_e O) (
u <- var_e u ./e nat_e 2 ;
ifte (var_e A mode nat_e 2 =e nat_e O &e var_e B mode nat_e 2 =e nat_e O) thendo
( A <- var_e A ./e nat_e 2 ;
B <- var_e B ./e nat_e 2 )
elsedo
( A <- (var_e A +e var_e y) ./e nat_e 2 ;
B <- (var_e B .-e var_e x) ./e nat_e 2 )
).
Definition branch u v A B C D :=
u <- var_e u .-e var_e v ;
A <- var_e A .-e var_e C ;
B <- var_e B .-e var_e D.
Definition outer_loop u v x y A B C D :=
while.while (var_e u >> nat_e 0) (
inner_loop u x y A B;
inner_loop v x y C D;
ifte (var_e u >>= var_e v) thendo
branch u v A B C D
elsedo
branch v u C D A B
).
Definition begcd g x y u v A B C D :=
g <- nat_e 1 ;
prelude x y g ;
u <- var_e x ;
v <- var_e y ;
A <- nat_e 1 ;
B <- nat_e O ;
C <- nat_e O ;
D <- nat_e 1 ;
outer_loop u v x y A B C D.
Lemma inner_loop_verif : forall (x y g u v : ssrnat.nat_eqType) vx vy (A B C D : bipl.var.v),
nodup(x, y, g, u, v, A, B, C, D) ->
{{fun s _ => 0 <= [x ]_ s /\ 0 <= [y ]_ s /\ 0 <= [g ]_ s /\ 0 <= [u ]_ s /\ 0 <= [v ]_ s /\
[ x ]_ s * [ g ]_ s = vx /\ [y ]_ s * [g ]_ s = vy /\
[ A ]_ s * [ x ]_ s + [B ]_ s * [y ]_ s = [u ]_ s /\
[ C ]_ s * [ x ]_ s + [D ]_ s * [y ]_ s = [v ]_ s /\
Zgcd vx vy = [g ]_ s * Zgcd [u ]_ s [v ]_ s /\
(Zodd [x]_s \/ Zodd [y]_s) /\
(Zodd [u]_s \/ Zodd [v]_s) }}
inner_loop u x y A B
{{fun s _ => 0 <= [x ]_ s /\ 0 <= [y ]_ s /\ 0 <= [g ]_ s /\ 0 <= [u ]_ s /\ 0 <= [v ]_ s /\
[x ]_ s * [g ]_ s = vx /\ [y ]_ s * [g ]_ s = vy /\
[ A ]_ s * [ x ]_ s + [B ]_ s * [y ]_ s = [u ]_ s /\
[ C ]_ s * [ x ]_ s + [ D ]_ s * [y ]_ s = [v ]_ s /\
Zgcd vx vy = [g ]_ s * Zgcd [u ]_ s [v ]_ s /\
(Zodd [ x ]_s \/ Zodd [ y ]_s) /\
Zodd [ u ]_s }}.
Proof.
move=> x y g u v vx vy A B C D Hset.
apply hoare_prop_m.hoare_while_invariant with (fun s _ =>
0 <= [x ]_ s /\ 0 <= [y ]_ s /\ 0 <= [g ]_ s /\ 0 <= [u ]_ s /\ 0 <= [v ]_ s /\
[x ]_ s * [g ]_ s = vx /\ [y ]_ s * [g ]_ s = vy /\
[A ]_ s * [x ]_ s + [B ]_ s * [y ]_ s = [u ]_ s /\
[C ]_ s * [x ]_ s + [D ]_ s * [y ]_ s = [v ]_ s /\
Zgcd vx vy = [g ]_ s * Zgcd [u ]_ s [v ]_ s /\
(Zodd [x]_s \/ Zodd [y]_s) /\
(Zodd [u]_s \/ Zodd [v]_s)).
move=> s h /= [H2 [H3 [H4 [H5 [H6 [H7 [H8 [H9 [H10 [H11 [H12 H13]]]]]]]]]]].
by intuition.
move=> s h /= [[H2 [H3 [H4 [H5 [H6 [H7 [H8 [H9 [H10 [H11 [H12 H13]]]]]]]]]]] H1].
repeat (split => //).
move/ZIT.tP : H1.
by move/not_Zmod_2_Zodd.
u <- var_e u ./e nat_e 2;
apply hoare_assign with (fun s _ =>
0 <= [x ]_ s /\ 0 <= [y ]_ s /\ 0 <= [g ]_ s /\ 0 <= [u ]_ s /\ 0 <= [v ]_ s /\
[x ]_ s * [g ]_ s = vx /\ [y ]_ s * [g ]_ s = vy /\
[A ]_ s * [x ]_ s + [B ]_ s * [y ]_ s = [u ]_ s * 2 /\
[C ]_ s * [x ]_ s + [D ]_ s * [y ]_ s = [v ]_ s /\
Zgcd vx vy = [g ]_ s * Zgcd [u ]_ s [v ]_ s /\
(Zodd [x]_s \/ Zodd [y]_s) /\
Zodd [v]_s).
move=> s h /= [[H2 [H3 [H4 [H5 [H6 [H7 [H8 [H9 [H10 [H11 [H12 H13]]]]]]]]]]] H1].
rewrite /wp_assign; repeat Store_upd.
move/Zeq_boolP : H1; move/Zmod_2_Zeven => H1.
repeat (split => //).
by apply Z_div_pos.
rewrite /= /ZIT.t_div.
case/Zeven_ex : H1 => u' H1.
by rewrite H1 (Zmult_comm 2) Z_div_mult_full // -(Zmult_comm 2) H9.
rewrite -Zgcd_even_odd //.
case: H13 => //.
by move/Zeven_not_Zodd.
case: H13 => //.
by move/Zeven_not_Zodd.
0 <= [x ]_ s /\ 0 <= [y ]_ s /\ 0 <= [g ]_ s /\ 0 <= [u ]_ s /\ 0 <= [v ]_ s /\
[x ]_ s * [g ]_ s = vx /\ [y ]_ s * [g ]_ s = vy /\
[A ]_ s * [x ]_ s + [B ]_ s * [y ]_ s = [u ]_ s * 2 /\
[C ]_ s * [x ]_ s + [D ]_ s * [y ]_ s = [v ]_ s /\
Zgcd vx vy = [g ]_ s * Zgcd [u ]_ s [v ]_ s /\
(Zodd [x]_s \/ Zodd [y]_s) /\
Zodd [v]_s).
move=> s h /= [[H2 [H3 [H4 [H5 [H6 [H7 [H8 [H9 [H10 [H11 [H12 H13]]]]]]]]]]] H1].
rewrite /wp_assign; repeat Store_upd.
move/Zeq_boolP : H1; move/Zmod_2_Zeven => H1.
repeat (split => //).
by apply Z_div_pos.
rewrite /= /ZIT.t_div.
case/Zeven_ex : H1 => u' H1.
by rewrite H1 (Zmult_comm 2) Z_div_mult_full // -(Zmult_comm 2) H9.
rewrite -Zgcd_even_odd //.
case: H13 => //.
by move/Zeven_not_Zodd.
case: H13 => //.
by move/Zeven_not_Zodd.
ifte (var_e A mode nat_e 2 =e nat_e 0 &e var_e B mode nat_e 2 =e nat_e 0)
apply while.hoare_ifte.
-
-
A <- var_e A ./e nat_e 2;
apply hoare_assign with (fun s _ =>
0 <= [x ]_ s /\ 0 <= [y ]_ s /\ 0 <= [g ]_ s /\ 0 <= [u ]_ s /\ 0 <= [v ]_ s /\
[x ]_ s * [g ]_ s = vx /\ [y ]_ s * [g ]_ s = vy /\
[A ]_ s * [x ]_ s * 2 + [B ]_ s * [y ]_ s = [u ]_ s * 2 /\
[C ]_ s * [x ]_ s + [D ]_ s * [y ]_ s = [v ]_ s /\
Zgcd vx vy = [g ]_ s * Zgcd [u ]_ s [v ]_ s /\
(Zodd [x]_s \/ Zodd [y]_s) /\
Zodd [v ]_ s /\
eval_b (var_e B mode nat_e 2 =e nat_e 0) s).
move=> s h /= [[H2 [H3 [H4 [H5 [H6 [H7 [H8 [H9 [H10 [H11 [H12 H13]]]]]]]]]]] H1].
rewrite /wp_assign.
repeat Store_upd.
repeat (split=> //).
case/andP : H1.
move/ZIT.tP; move/Zmod_2_Zeven; case/Zeven_ex=> a H1a.
move/ZIT.tP; move/Zmod_2_Zeven; case/Zeven_ex=> b H1b.
by rewrite /= /ZIT.t_div H1a (Zmult_comm 2) Z_div_mult_full //
-H9 -(Zmult_comm 2) Zmult_assoc -H1a.
by case/andP : H1.
0 <= [x ]_ s /\ 0 <= [y ]_ s /\ 0 <= [g ]_ s /\ 0 <= [u ]_ s /\ 0 <= [v ]_ s /\
[x ]_ s * [g ]_ s = vx /\ [y ]_ s * [g ]_ s = vy /\
[A ]_ s * [x ]_ s * 2 + [B ]_ s * [y ]_ s = [u ]_ s * 2 /\
[C ]_ s * [x ]_ s + [D ]_ s * [y ]_ s = [v ]_ s /\
Zgcd vx vy = [g ]_ s * Zgcd [u ]_ s [v ]_ s /\
(Zodd [x]_s \/ Zodd [y]_s) /\
Zodd [v ]_ s /\
eval_b (var_e B mode nat_e 2 =e nat_e 0) s).
move=> s h /= [[H2 [H3 [H4 [H5 [H6 [H7 [H8 [H9 [H10 [H11 [H12 H13]]]]]]]]]]] H1].
rewrite /wp_assign.
repeat Store_upd.
repeat (split=> //).
case/andP : H1.
move/ZIT.tP; move/Zmod_2_Zeven; case/Zeven_ex=> a H1a.
move/ZIT.tP; move/Zmod_2_Zeven; case/Zeven_ex=> b H1b.
by rewrite /= /ZIT.t_div H1a (Zmult_comm 2) Z_div_mult_full //
-H9 -(Zmult_comm 2) Zmult_assoc -H1a.
by case/andP : H1.
B <- var_e B ./e nat_e 2
apply hoare_assign'.
move=> s h /= [H2 [H3 [H4 [H5 [H6 [H7 [H8 [H9 [H10 [H11 [H12 [H13 H14]]]]]]]]]]]].
rewrite /wp_assign.
repeat Store_upd.
repeat (split => //).
move/ZIT.tP : H14; move/Zmod_2_Zeven; case/Zeven_ex=> a H14.
rewrite H14 in H9.
ring_simplify in H9.
rewrite -!Zmult_assoc -Zmult_plus_distr_r in H9.
rewrite /= /ZIT.t_div H14 (Zmult_comm 2) Z_div_mult_full //.
by eapply Zmult_reg_l; eauto.
by right.
-
move=> s h /= [H2 [H3 [H4 [H5 [H6 [H7 [H8 [H9 [H10 [H11 [H12 [H13 H14]]]]]]]]]]]].
rewrite /wp_assign.
repeat Store_upd.
repeat (split => //).
move/ZIT.tP : H14; move/Zmod_2_Zeven; case/Zeven_ex=> a H14.
rewrite H14 in H9.
ring_simplify in H9.
rewrite -!Zmult_assoc -Zmult_plus_distr_r in H9.
rewrite /= /ZIT.t_div H14 (Zmult_comm 2) Z_div_mult_full //.
by eapply Zmult_reg_l; eauto.
by right.
-
A <- (var_e A +e var_e y) ./e nat_e 2;
apply hoare_assign with (fun s _ =>
0 <= [x ]_ s /\ 0 <= [y ]_ s /\ 0 <= [g ]_ s /\ 0 <= [u ]_ s /\ 0 <= [v ]_ s /\
[x ]_ s * [g ]_ s = vx /\ [y ]_ s * [g ]_ s = vy /\
[A ]_ s * [x ]_ s * 2 - [y]_s * [x]_s + [B ]_ s * [y ]_ s = [u ]_ s * 2 /\
[C ]_ s * [x ]_ s + [D ]_ s * [y ]_ s = [v ]_ s /\
Zgcd vx vy = [g ]_ s * Zgcd [u ]_ s [v ]_ s /\
(Zodd [x]_s \/ Zodd [y]_s) /\
Zodd [v ]_ s /\
(Zodd ([A]_s *2 - [y]_s) \/ Zodd ([B]_s))).
move=> s h /= [[H2 [H3 [H4 [H5 [H6 [H7 [H8 [H9 [H10 [H11 [H12 H13]]]]]]]]]]] H1].
rewrite /wp_assign; repeat Store_upd.
repeat (split => //).
+ rewrite /= /ZIT.t_div /ZIT.t_plus.
rewrite negb_and in H1.
case/orP : H1.
* move/ZIT.tP; move/not_Zmod_2_Zodd => H1.
rewrite -H9.
ring_simplify.
f_equal.
rewrite -Z_div_exact_full_2 //; first by ring.
rewrite (Zmult_comm _ 2) in H9.
move/Zmult_2_Zeven : H9.
move/Zeven_plus_inv.
case; case => Y1 Y2.
- case: H12 => H12.
+ move: (Zodd_mult_Zodd _ _ H1 H12); by move/Zeven_not_Zodd.
+ by apply Zeven_Zmod_2, Zodd_plus_Zodd.
- apply Zeven_Zmod_2.
case: H12 => H12.
+ case/Zodd_mult_inv : Y2 => Y2 Y3; by apply Zodd_plus_Zodd.
+ by apply Zodd_plus_Zodd.
* move/ZIT.tP. move/not_Zmod_2_Zodd => H1.
rewrite -H9.
ring_simplify.
f_equal.
rewrite -Z_div_exact_full_2 //; first by ring.
rewrite (Zmult_comm _ 2) in H9.
move/Zmult_2_Zeven : H9.
move/Zeven_plus_inv.
case; case=> Y1 Y2.
- case: H12 => H12.
+ case/Zeven_mult_inv : Y1 => Y1; last by move/Zeven_not_Zodd : Y1.
case/Zeven_mult_inv : Y2 => Y2; first by move/Zeven_not_Zodd : Y2.
by apply Zeven_Zmod_2, Zeven_plus_Zeven.
+ move: (Zodd_mult_Zodd _ _ H1 H12).
by move/Zodd_not_Zeven.
- case: H12 => H12.
+ case/Zodd_mult_inv : Y1 => Y1 _.
case/Zodd_mult_inv : Y2 => _ Y2'.
by apply Zeven_Zmod_2, Zodd_plus_Zodd.
+ case/Zodd_mult_inv : Y1 => Y1 _.
by apply Zeven_Zmod_2, Zodd_plus_Zodd.
+ rewrite negb_and in H1.
rewrite /= /ZIT.t_div /ZIT.t_plus.
case/orP : H1.
- move/ZIT.tP. move/not_Zmod_2_Zodd => H1.
case: H12 => H12.
* case: (Zeven_odd_dec [B]_s) => X; auto.
rewrite (Zmult_comm _ 2) in H9.
move/Zmult_2_Zeven : H9.
case/Zeven_plus_inv.
- case=> Y1 Y2.
move: (Zodd_mult_Zodd _ _ H1 H12).
by move/Zodd_not_Zeven.
- case=> Y1.
case/Zodd_mult_inv.
by move/Zodd_not_Zeven.
* left.
apply Zeven_plus_Zodd.
- rewrite Zmult_comm; by apply Zeven_2p.
- by apply Zodd_opp.
- move/ZIT.tP; by move/not_Zmod_2_Zodd; auto.
0 <= [x ]_ s /\ 0 <= [y ]_ s /\ 0 <= [g ]_ s /\ 0 <= [u ]_ s /\ 0 <= [v ]_ s /\
[x ]_ s * [g ]_ s = vx /\ [y ]_ s * [g ]_ s = vy /\
[A ]_ s * [x ]_ s * 2 - [y]_s * [x]_s + [B ]_ s * [y ]_ s = [u ]_ s * 2 /\
[C ]_ s * [x ]_ s + [D ]_ s * [y ]_ s = [v ]_ s /\
Zgcd vx vy = [g ]_ s * Zgcd [u ]_ s [v ]_ s /\
(Zodd [x]_s \/ Zodd [y]_s) /\
Zodd [v ]_ s /\
(Zodd ([A]_s *2 - [y]_s) \/ Zodd ([B]_s))).
move=> s h /= [[H2 [H3 [H4 [H5 [H6 [H7 [H8 [H9 [H10 [H11 [H12 H13]]]]]]]]]]] H1].
rewrite /wp_assign; repeat Store_upd.
repeat (split => //).
+ rewrite /= /ZIT.t_div /ZIT.t_plus.
rewrite negb_and in H1.
case/orP : H1.
* move/ZIT.tP; move/not_Zmod_2_Zodd => H1.
rewrite -H9.
ring_simplify.
f_equal.
rewrite -Z_div_exact_full_2 //; first by ring.
rewrite (Zmult_comm _ 2) in H9.
move/Zmult_2_Zeven : H9.
move/Zeven_plus_inv.
case; case => Y1 Y2.
- case: H12 => H12.
+ move: (Zodd_mult_Zodd _ _ H1 H12); by move/Zeven_not_Zodd.
+ by apply Zeven_Zmod_2, Zodd_plus_Zodd.
- apply Zeven_Zmod_2.
case: H12 => H12.
+ case/Zodd_mult_inv : Y2 => Y2 Y3; by apply Zodd_plus_Zodd.
+ by apply Zodd_plus_Zodd.
* move/ZIT.tP. move/not_Zmod_2_Zodd => H1.
rewrite -H9.
ring_simplify.
f_equal.
rewrite -Z_div_exact_full_2 //; first by ring.
rewrite (Zmult_comm _ 2) in H9.
move/Zmult_2_Zeven : H9.
move/Zeven_plus_inv.
case; case=> Y1 Y2.
- case: H12 => H12.
+ case/Zeven_mult_inv : Y1 => Y1; last by move/Zeven_not_Zodd : Y1.
case/Zeven_mult_inv : Y2 => Y2; first by move/Zeven_not_Zodd : Y2.
by apply Zeven_Zmod_2, Zeven_plus_Zeven.
+ move: (Zodd_mult_Zodd _ _ H1 H12).
by move/Zodd_not_Zeven.
- case: H12 => H12.
+ case/Zodd_mult_inv : Y1 => Y1 _.
case/Zodd_mult_inv : Y2 => _ Y2'.
by apply Zeven_Zmod_2, Zodd_plus_Zodd.
+ case/Zodd_mult_inv : Y1 => Y1 _.
by apply Zeven_Zmod_2, Zodd_plus_Zodd.
+ rewrite negb_and in H1.
rewrite /= /ZIT.t_div /ZIT.t_plus.
case/orP : H1.
- move/ZIT.tP. move/not_Zmod_2_Zodd => H1.
case: H12 => H12.
* case: (Zeven_odd_dec [B]_s) => X; auto.
rewrite (Zmult_comm _ 2) in H9.
move/Zmult_2_Zeven : H9.
case/Zeven_plus_inv.
- case=> Y1 Y2.
move: (Zodd_mult_Zodd _ _ H1 H12).
by move/Zodd_not_Zeven.
- case=> Y1.
case/Zodd_mult_inv.
by move/Zodd_not_Zeven.
* left.
apply Zeven_plus_Zodd.
- rewrite Zmult_comm; by apply Zeven_2p.
- by apply Zodd_opp.
- move/ZIT.tP; by move/not_Zmod_2_Zodd; auto.
B <- (var_e B .-e var_e x) ./e nat_e 2
apply hoare_assign'.
move=> s h /= [H2 [H3 [H4 [H5 [H6 [H7 [H8 [H9 [H10 [H11 [H12 [H13 H14]]]]]]]]]]]].
rewrite /wp_assign; repeat Store_upd.
repeat (split => //).
2: by right.
rewrite /= /ZIT.t_minus /ZIT.t_div.
have {H9}H9 : ([B ]_ s - [x ]_ s) * [y ]_ s = [u ]_ s * 2 - [A ]_ s * [x ]_ s * 2.
rewrite -H9; ring.
rewrite -Zmult_minus_distr_r -(Zmult_comm 2) in H9.
case: H12 => H12.
+ case: (Zeven_odd_dec [y]_s) => X.
* case: H14 => H14.
- move: (Zeven_plus_Zeven _ _ (Zeven_2p [A]_s) (Zeven_opp _ X)).
rewrite Zmult_comm.
by move/Zeven_not_Zodd.
- have Y : Zeven ([B]_s - [x]_s).
apply Zodd_plus_Zodd => //.
by apply Zodd_opp.
case/Zeven_ex : Y => b' Y.
rewrite Y -Zmult_assoc in H9.
apply Zmult_reg_l in H9 => //.
rewrite Y (Zmult_comm 2) Z_div_mult_full // H9; ring.
* case: (Zeven_odd_dec ([B]_s - [x]_s)) => Y.
- case/Zeven_ex : Y => b' Y.
rewrite Y -Zmult_assoc in H9.
apply Zmult_reg_l in H9 => //.
rewrite Y (Zmult_comm 2) Z_div_mult_full // H9; ring.
- have : Zodd ( ([B ]_ s - [x ]_ s) * [y ]_ s ).
apply Zodd_mult_Zodd => //.
rewrite H9.
move: (Zeven_2p (([u ]_ s - [A ]_ s * [x ]_ s))).
by move/Zeven_not_Zodd.
+ case: (Zeven_odd_dec ([B]_s - [x]_s)) => Y.
* case/Zeven_ex : Y => b' Y.
rewrite Y -Zmult_assoc in H9.
apply Zmult_reg_l in H9 => //.
rewrite Y (Zmult_comm 2) Z_div_mult_full // H9; ring.
* have : Zodd ( ([B ]_ s - [x ]_ s) * [y ]_ s ) by apply Zodd_mult_Zodd.
rewrite H9.
move: (Zeven_2p (([u ]_ s - [A ]_ s * [x ]_ s))).
by move/Zeven_not_Zodd.
Qed.
Lemma outer_loop_verif : forall (g x y u v A B C D :ssrnat.nat_eqType) vx vy,
nodup(g, x, y, u, v, A, B, C, D) -> 0 <= vx -> 0 <= vy ->
{{ (fun s _ => 0 <= [x ]_ s /\ 0 <= [y ]_ s /\ 0 <= [g ]_ s /\
0 <= [u ]_ s /\ 0 <= [v ]_ s /\
[x ]_ s * [g ]_ s = vx /\ [y ]_ s * [g ]_ s = vy /\
[A ]_ s * [x ]_ s + [B ]_ s * [y ]_ s = [u ]_ s /\
[C ]_ s * [x ]_ s + [D ]_ s * [y ]_ s = [v ]_ s /\
Zgcd vx vy = [g ]_ s * Zgcd [u ]_ s [v ]_ s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\ (Zodd [x ]_ s \/ Zodd [y ]_ s))}}
outer_loop u v x y A B C D
{{ (fun s h => (0 <= [x ]_ s /\ 0 <= [y ]_ s /\ 0 <= [g ]_ s /\
0 <= [u ]_ s /\ 0 <= [v ]_ s /\
[x ]_ s * [g ]_ s = vx /\ [y ]_ s * [g ]_ s = vy /\
[A ]_ s * [x ]_ s + [B ]_ s * [y ]_ s = [u ]_ s /\
[C ]_ s * [x ]_ s + [D ]_ s * [y ]_ s = [v ]_ s /\
Zgcd vx vy = [g ]_ s * Zgcd [u ]_ s [v ]_ s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\ (Zodd [x ]_ s \/ Zodd [y ]_ s)) /\
~~ hoare_m.eval_b (var_e u >> nat_e 0) (s, h)) }}.
Proof.
move=> g x y u v A B C D vx vy Hset Hvx Hvy.
rewrite /outer_loop.
apply while.hoare_while.
move=> s h /= [H2 [H3 [H4 [H5 [H6 [H7 [H8 [H9 [H10 [H11 [H12 [H13 H14]]]]]]]]]]]].
rewrite /wp_assign; repeat Store_upd.
repeat (split => //).
2: by right.
rewrite /= /ZIT.t_minus /ZIT.t_div.
have {H9}H9 : ([B ]_ s - [x ]_ s) * [y ]_ s = [u ]_ s * 2 - [A ]_ s * [x ]_ s * 2.
rewrite -H9; ring.
rewrite -Zmult_minus_distr_r -(Zmult_comm 2) in H9.
case: H12 => H12.
+ case: (Zeven_odd_dec [y]_s) => X.
* case: H14 => H14.
- move: (Zeven_plus_Zeven _ _ (Zeven_2p [A]_s) (Zeven_opp _ X)).
rewrite Zmult_comm.
by move/Zeven_not_Zodd.
- have Y : Zeven ([B]_s - [x]_s).
apply Zodd_plus_Zodd => //.
by apply Zodd_opp.
case/Zeven_ex : Y => b' Y.
rewrite Y -Zmult_assoc in H9.
apply Zmult_reg_l in H9 => //.
rewrite Y (Zmult_comm 2) Z_div_mult_full // H9; ring.
* case: (Zeven_odd_dec ([B]_s - [x]_s)) => Y.
- case/Zeven_ex : Y => b' Y.
rewrite Y -Zmult_assoc in H9.
apply Zmult_reg_l in H9 => //.
rewrite Y (Zmult_comm 2) Z_div_mult_full // H9; ring.
- have : Zodd ( ([B ]_ s - [x ]_ s) * [y ]_ s ).
apply Zodd_mult_Zodd => //.
rewrite H9.
move: (Zeven_2p (([u ]_ s - [A ]_ s * [x ]_ s))).
by move/Zeven_not_Zodd.
+ case: (Zeven_odd_dec ([B]_s - [x]_s)) => Y.
* case/Zeven_ex : Y => b' Y.
rewrite Y -Zmult_assoc in H9.
apply Zmult_reg_l in H9 => //.
rewrite Y (Zmult_comm 2) Z_div_mult_full // H9; ring.
* have : Zodd ( ([B ]_ s - [x ]_ s) * [y ]_ s ) by apply Zodd_mult_Zodd.
rewrite H9.
move: (Zeven_2p (([u ]_ s - [A ]_ s * [x ]_ s))).
by move/Zeven_not_Zodd.
Qed.
Lemma outer_loop_verif : forall (g x y u v A B C D :ssrnat.nat_eqType) vx vy,
nodup(g, x, y, u, v, A, B, C, D) -> 0 <= vx -> 0 <= vy ->
{{ (fun s _ => 0 <= [x ]_ s /\ 0 <= [y ]_ s /\ 0 <= [g ]_ s /\
0 <= [u ]_ s /\ 0 <= [v ]_ s /\
[x ]_ s * [g ]_ s = vx /\ [y ]_ s * [g ]_ s = vy /\
[A ]_ s * [x ]_ s + [B ]_ s * [y ]_ s = [u ]_ s /\
[C ]_ s * [x ]_ s + [D ]_ s * [y ]_ s = [v ]_ s /\
Zgcd vx vy = [g ]_ s * Zgcd [u ]_ s [v ]_ s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\ (Zodd [x ]_ s \/ Zodd [y ]_ s))}}
outer_loop u v x y A B C D
{{ (fun s h => (0 <= [x ]_ s /\ 0 <= [y ]_ s /\ 0 <= [g ]_ s /\
0 <= [u ]_ s /\ 0 <= [v ]_ s /\
[x ]_ s * [g ]_ s = vx /\ [y ]_ s * [g ]_ s = vy /\
[A ]_ s * [x ]_ s + [B ]_ s * [y ]_ s = [u ]_ s /\
[C ]_ s * [x ]_ s + [D ]_ s * [y ]_ s = [v ]_ s /\
Zgcd vx vy = [g ]_ s * Zgcd [u ]_ s [v ]_ s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\ (Zodd [x ]_ s \/ Zodd [y ]_ s)) /\
~~ hoare_m.eval_b (var_e u >> nat_e 0) (s, h)) }}.
Proof.
move=> g x y u v A B C D vx vy Hset Hvx Hvy.
rewrite /outer_loop.
apply while.hoare_while.
while (var_e u mode nat_e 2 =e nat_e 0)
apply while.hoare_seq with (fun s _ =>
0 <= [x ]_ s /\ 0 <= [y ]_ s /\ 0 <= [g ]_ s /\ 0 <= [u ]_ s /\ 0 <= [v ]_ s /\
[x ]_ s * [g ]_ s = vx /\
[y ]_ s * [g ]_ s = vy /\
[A ]_ s * [x ]_ s + [B ]_ s * [y ]_ s = [u ]_ s /\
[C ]_ s * [x ]_ s + [D ]_ s * [y ]_ s = [v ]_ s /\
Zgcd vx vy = [g ]_ s * Zgcd [u ]_ s [v ]_ s /\
(Zodd [x]_s \/ Zodd [y]_s) /\
Zodd [u]_s).
eapply hoare_prop_m.hoare_stren; last first.
have Hset' : nodup(x, y, g, u, v, A, B, C, D).
rewrite [Equality.sort _]/= in Hset *. by Nodup_nodup O.
by apply (inner_loop_verif x y g u v vx vy A B C D Hset').
move=> s h /= [[H2 [H3 [H4 [H5 [H6 [H7 [H8 [H9 [H10 [H11 H12]]]]]]]]]] H1]; by intuition.
apply hoare_prop_m.hoare_stren with (fun s _ =>
(0 <= [x ]_ s /\ 0 <= [y ]_ s /\ 0 <= [g ]_ s /\ 0 <= [v ]_ s /\ 0 <= [u ]_ s /\
[x ]_ s * [g ]_ s = vx /\ [y ]_ s * [g ]_ s = vy /\
[C ]_ s * [x ]_ s + [D ]_ s * [y ]_ s = [v ]_ s /\
[A ]_ s * [x ]_ s + [B ]_ s * [y ]_ s = [u ]_ s /\
Zgcd vx vy = [g ]_ s * Zgcd [v ]_ s [u ]_ s) /\
(Zodd [x]_s \/ Zodd [y]_s) /\
(Zodd [v]_s \/ Zodd [u]_s)).
move=> s h /=.
rewrite (Zgcd_sym [u]_s); by intuition.
have {Hset}Hset' : nodup(x, y, g, v, u, C, D, A, B).
rewrite [Equality.sort _]/= in Hset *; by Nodup_nodup O.
move: (inner_loop_verif x y g v u vx vy C D A B Hset') => Hi.
eapply while.hoare_seq.
eapply hoare_prop_m.hoare_stren; last by apply Hi.
move=> s h /=; by intuition.
apply while.hoare_ifte.
-
0 <= [x ]_ s /\ 0 <= [y ]_ s /\ 0 <= [g ]_ s /\ 0 <= [u ]_ s /\ 0 <= [v ]_ s /\
[x ]_ s * [g ]_ s = vx /\
[y ]_ s * [g ]_ s = vy /\
[A ]_ s * [x ]_ s + [B ]_ s * [y ]_ s = [u ]_ s /\
[C ]_ s * [x ]_ s + [D ]_ s * [y ]_ s = [v ]_ s /\
Zgcd vx vy = [g ]_ s * Zgcd [u ]_ s [v ]_ s /\
(Zodd [x]_s \/ Zodd [y]_s) /\
Zodd [u]_s).
eapply hoare_prop_m.hoare_stren; last first.
have Hset' : nodup(x, y, g, u, v, A, B, C, D).
rewrite [Equality.sort _]/= in Hset *. by Nodup_nodup O.
by apply (inner_loop_verif x y g u v vx vy A B C D Hset').
move=> s h /= [[H2 [H3 [H4 [H5 [H6 [H7 [H8 [H9 [H10 [H11 H12]]]]]]]]]] H1]; by intuition.
apply hoare_prop_m.hoare_stren with (fun s _ =>
(0 <= [x ]_ s /\ 0 <= [y ]_ s /\ 0 <= [g ]_ s /\ 0 <= [v ]_ s /\ 0 <= [u ]_ s /\
[x ]_ s * [g ]_ s = vx /\ [y ]_ s * [g ]_ s = vy /\
[C ]_ s * [x ]_ s + [D ]_ s * [y ]_ s = [v ]_ s /\
[A ]_ s * [x ]_ s + [B ]_ s * [y ]_ s = [u ]_ s /\
Zgcd vx vy = [g ]_ s * Zgcd [v ]_ s [u ]_ s) /\
(Zodd [x]_s \/ Zodd [y]_s) /\
(Zodd [v]_s \/ Zodd [u]_s)).
move=> s h /=.
rewrite (Zgcd_sym [u]_s); by intuition.
have {Hset}Hset' : nodup(x, y, g, v, u, C, D, A, B).
rewrite [Equality.sort _]/= in Hset *; by Nodup_nodup O.
move: (inner_loop_verif x y g v u vx vy C D A B Hset') => Hi.
eapply while.hoare_seq.
eapply hoare_prop_m.hoare_stren; last by apply Hi.
move=> s h /=; by intuition.
apply while.hoare_ifte.
-
u <- var_e u .-e var_e v;
apply hoare_assign with (fun s _ =>
0 <= [x ]_ s /\ 0 <= [y ]_ s /\ 0 <= [g ]_ s /\ 0 <= [v ]_ s /\ 0 <= [u ]_ s /\
[x ]_ s * [g ]_ s = vx /\ [y ]_ s * [g ]_ s = vy /\
([A ]_ s - [C]_s)* [x ]_ s + ([B ]_ s - [D]_s)* [y ]_ s = [u ]_ s /\
[C ]_ s * [x ]_ s + [D ]_ s * [y ]_ s = [v ]_ s /\
Zgcd vx vy = [g ]_ s * Zgcd [u ]_ s [v ]_ s /\
(Zodd [x]_s \/ Zodd [y]_s) /\
(Zodd [v]_s \/ Zodd [u]_s)).
move=> s h /= [[H3 [H4 [H5 [H6 [H7 [H8 [H9 [H10 [H11 [H12 [H13 H14]]]]]]]]]]] H2].
rewrite /wp_assign; repeat Store_upd => //.
repeat (split => //).
move/Zge_bool_true : H2 => H2.
rewrite /=; by omegab.
rewrite /= /ZIT.t_minus -H10 -H11; ring.
by rewrite /= /ZIT.t_minus -Zgcd_minus (Zgcd_sym [u]_s).
rewrite /= /ZIT.t_minus.
case: (Zeven_odd_dec [v]_s) => Htmp; by auto.
0 <= [x ]_ s /\ 0 <= [y ]_ s /\ 0 <= [g ]_ s /\ 0 <= [v ]_ s /\ 0 <= [u ]_ s /\
[x ]_ s * [g ]_ s = vx /\ [y ]_ s * [g ]_ s = vy /\
([A ]_ s - [C]_s)* [x ]_ s + ([B ]_ s - [D]_s)* [y ]_ s = [u ]_ s /\
[C ]_ s * [x ]_ s + [D ]_ s * [y ]_ s = [v ]_ s /\
Zgcd vx vy = [g ]_ s * Zgcd [u ]_ s [v ]_ s /\
(Zodd [x]_s \/ Zodd [y]_s) /\
(Zodd [v]_s \/ Zodd [u]_s)).
move=> s h /= [[H3 [H4 [H5 [H6 [H7 [H8 [H9 [H10 [H11 [H12 [H13 H14]]]]]]]]]]] H2].
rewrite /wp_assign; repeat Store_upd => //.
repeat (split => //).
move/Zge_bool_true : H2 => H2.
rewrite /=; by omegab.
rewrite /= /ZIT.t_minus -H10 -H11; ring.
by rewrite /= /ZIT.t_minus -Zgcd_minus (Zgcd_sym [u]_s).
rewrite /= /ZIT.t_minus.
case: (Zeven_odd_dec [v]_s) => Htmp; by auto.
A <- var_e A .-e var_e C;
apply hoare_assign with (fun s _ =>
(0 <= [x ]_ s /\ 0 <= [y ]_ s /\ 0 <= [g ]_ s /\ 0 <= [v ]_ s /\ 0 <= [u ]_ s /\
[x ]_ s * [g ]_ s = vx /\ [y ]_ s * [g ]_ s = vy /\
([A ]_ s)* [x ]_ s + ([B ]_ s - [D]_s)* [y ]_ s = [u ]_ s /\
[C ]_ s * [x ]_ s + [D ]_ s * [y ]_ s = [v ]_ s /\
Zgcd vx vy = [g ]_ s * Zgcd [u ]_ s [v ]_ s /\
(Zodd [x]_s \/ Zodd [y]_s) /\
(Zodd [v ]_ s \/ Zodd [u ]_ s))).
move=> s h /= [H2 [H3 [H4 [H5 [H6 [H7 [H8 [H9 [H10 [H11 H12]]]]]]]]]].
by rewrite /wp_assign; repeat Store_upd.
(0 <= [x ]_ s /\ 0 <= [y ]_ s /\ 0 <= [g ]_ s /\ 0 <= [v ]_ s /\ 0 <= [u ]_ s /\
[x ]_ s * [g ]_ s = vx /\ [y ]_ s * [g ]_ s = vy /\
([A ]_ s)* [x ]_ s + ([B ]_ s - [D]_s)* [y ]_ s = [u ]_ s /\
[C ]_ s * [x ]_ s + [D ]_ s * [y ]_ s = [v ]_ s /\
Zgcd vx vy = [g ]_ s * Zgcd [u ]_ s [v ]_ s /\
(Zodd [x]_s \/ Zodd [y]_s) /\
(Zodd [v ]_ s \/ Zodd [u ]_ s))).
move=> s h /= [H2 [H3 [H4 [H5 [H6 [H7 [H8 [H9 [H10 [H11 H12]]]]]]]]]].
by rewrite /wp_assign; repeat Store_upd.
B <- var_e B .-e var_e D
apply hoare_assign'.
move=> s h /= [H2 [H3 [H4 [H5 [H6 [H7 [H8 H9]]]]]]].
rewrite /wp_assign; repeat Store_upd => //.
tauto.
-
move=> s h /= [H2 [H3 [H4 [H5 [H6 [H7 [H8 H9]]]]]]].
rewrite /wp_assign; repeat Store_upd => //.
tauto.
-
v <- var_e v .-e var_e u;
apply hoare_assign with (fun s _ =>
0 <= [x ]_ s /\ 0 <= [y ]_ s /\ 0 <= [g ]_ s /\ 0 <= [v ]_ s /\ 0 <= [u ]_ s /\
[x ]_ s * [g ]_ s = vx /\ [y ]_ s * [g ]_ s = vy /\
[A ]_ s * [x ]_ s + [B ]_ s * [y ]_ s = [u ]_ s /\
([C ]_ s - [A]_s) * [x ]_ s + ([D ]_ s - [B]_s) * [y ]_ s = [v ]_ s /\
Zgcd vx vy = [g ]_ s * Zgcd [u ]_ s [v ]_ s /\
(Zodd [x]_s \/ Zodd [y]_s) /\
(Zodd [v ]_ s \/ Zodd [u ]_ s)).
move=> s h /= [[H3 [H4 [H5 [H6 [H7 [H8 [H9 [H10 [H11 [H12 [H13 H14]]]]]]]]]]] H2].
rewrite /wp_assign; repeat Store_upd => //.
repeat (split => //).
move/negbTE : H2; move/Zge_bool_false=> H2.
rewrite /=; by omegab.
rewrite /= /ZIT.t_minus -H10 -H11; ring.
by rewrite /= /ZIT.t_minus (Zgcd_sym [u]_s) -Zgcd_minus.
case: (Zeven_odd_dec [u]_s) => Htmp; last by right.
left; apply Zodd_plus_Zeven => //.
by destruct ([u]_s).
0 <= [x ]_ s /\ 0 <= [y ]_ s /\ 0 <= [g ]_ s /\ 0 <= [v ]_ s /\ 0 <= [u ]_ s /\
[x ]_ s * [g ]_ s = vx /\ [y ]_ s * [g ]_ s = vy /\
[A ]_ s * [x ]_ s + [B ]_ s * [y ]_ s = [u ]_ s /\
([C ]_ s - [A]_s) * [x ]_ s + ([D ]_ s - [B]_s) * [y ]_ s = [v ]_ s /\
Zgcd vx vy = [g ]_ s * Zgcd [u ]_ s [v ]_ s /\
(Zodd [x]_s \/ Zodd [y]_s) /\
(Zodd [v ]_ s \/ Zodd [u ]_ s)).
move=> s h /= [[H3 [H4 [H5 [H6 [H7 [H8 [H9 [H10 [H11 [H12 [H13 H14]]]]]]]]]]] H2].
rewrite /wp_assign; repeat Store_upd => //.
repeat (split => //).
move/negbTE : H2; move/Zge_bool_false=> H2.
rewrite /=; by omegab.
rewrite /= /ZIT.t_minus -H10 -H11; ring.
by rewrite /= /ZIT.t_minus (Zgcd_sym [u]_s) -Zgcd_minus.
case: (Zeven_odd_dec [u]_s) => Htmp; last by right.
left; apply Zodd_plus_Zeven => //.
by destruct ([u]_s).
C <- var_e C .-e var_e A;
apply hoare_assign with (fun s _ =>
0 <= [x ]_ s /\ 0 <= [y ]_ s /\ 0 <= [g ]_ s /\ 0 <= [v ]_ s /\ 0 <= [u ]_ s /\
[x ]_ s * [g ]_ s = vx /\ [y ]_ s * [g ]_ s = vy /\
[A ]_ s * [x ]_ s + [B ]_ s * [y ]_ s = [u ]_ s /\
[C ]_ s * [x ]_ s + ([D ]_ s - [B]_s) * [y ]_ s = [v ]_ s /\
Zgcd vx vy = [g ]_ s * Zgcd [u ]_ s [v ]_ s /\
(Zodd [x]_s \/ Zodd [y]_s) /\
(Zodd [v ]_ s \/ Zodd [u ]_ s)).
move=> s h /= [H2 [H3 [H4 [H5 [H6 [H7 [H8 [H9 [H10 [H11 [H12 H13]]]]]]]]]]].
by rewrite /wp_assign; repeat Store_upd.
0 <= [x ]_ s /\ 0 <= [y ]_ s /\ 0 <= [g ]_ s /\ 0 <= [v ]_ s /\ 0 <= [u ]_ s /\
[x ]_ s * [g ]_ s = vx /\ [y ]_ s * [g ]_ s = vy /\
[A ]_ s * [x ]_ s + [B ]_ s * [y ]_ s = [u ]_ s /\
[C ]_ s * [x ]_ s + ([D ]_ s - [B]_s) * [y ]_ s = [v ]_ s /\
Zgcd vx vy = [g ]_ s * Zgcd [u ]_ s [v ]_ s /\
(Zodd [x]_s \/ Zodd [y]_s) /\
(Zodd [v ]_ s \/ Zodd [u ]_ s)).
move=> s h /= [H2 [H3 [H4 [H5 [H6 [H7 [H8 [H9 [H10 [H11 [H12 H13]]]]]]]]]]].
by rewrite /wp_assign; repeat Store_upd.
D <- var_e D .-e var_e B
apply hoare_assign' => s h /= [H2 [H3 [H4 [H5 [H6 [H7 [H8 H9]]]]]]].
rewrite /wp_assign; repeat Store_upd => //; by intuition.
Qed.
Lemma begcd_verif : forall (g x y u v A B C D : ssrnat.nat_eqType),
nodup(g, x, y, u, v, A, B, C, D) ->
forall vx vy, 0 <= vx -> 0 <= vy ->
{{ fun s h => [x]_s = vx /\ [y]_s = vy }}
begcd g x y u v A B C D
{{ fun s h => [C]_s * vx + [D]_s * vy = [g]_s * [v]_s /\
Zis_gcd vx vy ([g]_s * [v]_s)}}.
Proof.
move=> g x y u v A B C D Hset vx vy Hvx Hvy.
rewrite /begcd.
rewrite /wp_assign; repeat Store_upd => //; by intuition.
Qed.
Lemma begcd_verif : forall (g x y u v A B C D : ssrnat.nat_eqType),
nodup(g, x, y, u, v, A, B, C, D) ->
forall vx vy, 0 <= vx -> 0 <= vy ->
{{ fun s h => [x]_s = vx /\ [y]_s = vy }}
begcd g x y u v A B C D
{{ fun s h => [C]_s * vx + [D]_s * vy = [g]_s * [v]_s /\
Zis_gcd vx vy ([g]_s * [v]_s)}}.
Proof.
move=> g x y u v A B C D Hset vx vy Hvx Hvy.
rewrite /begcd.
g <- nat_e 1 ;
apply hoare_assign with (fun s h => [x]_s = vx /\ [y]_s = vy /\ [g]_s = 1).
move=> s h [Hx Hy].
by rewrite /wp_assign; repeat Store_upd => //.
move=> s h [Hx Hy].
by rewrite /wp_assign; repeat Store_upd => //.
prelude x y g ;
apply while.hoare_seq with (fun s _ =>
0 <= [x]_s /\ 0 <= [y]_s /\ 0 <= [g]_s /\
[x]_ s * [g]_s = vx /\ [y]_s * [g]_s = vy /\
Zgcd vx vy = [g]_s * Zgcd ([x]_s) ([y]_s) /\
~ eval_b ((var_e x mode nat_e 2 =e nat_e O) &e (var_e y mode nat_e 2) =e nat_e O) s).
have Hset' : nodup(x, y, g).
rewrite [Equality.sort _]/= in Hset *; by Nodup_nodup O.
eapply while.hoare_conseq; last by apply (BGCD_HAC.prelude_verif _ _ _ _ _ Hset' Hvx Hvy).
- move=> s h /= [H1 [H2 [H3 [x_g [y_g H6]]]]].
repeat (split; first by done).
split; last by move/negP: H6.
rewrite -x_g -y_g.
apply Zis_gcd_gcd; last first.
rewrite (Zmult_comm [x]_s) (Zmult_comm [y]_s).
by apply Zis_gcd_mult, Zgcd_is_gcd.
apply Zmult_le_0_compat => //; by apply Zgcd_is_pos.
- move=> s h /= [-> [-> ->]]; by rewrite 2!Zmult_1_r.
0 <= [x]_s /\ 0 <= [y]_s /\ 0 <= [g]_s /\
[x]_ s * [g]_s = vx /\ [y]_s * [g]_s = vy /\
Zgcd vx vy = [g]_s * Zgcd ([x]_s) ([y]_s) /\
~ eval_b ((var_e x mode nat_e 2 =e nat_e O) &e (var_e y mode nat_e 2) =e nat_e O) s).
have Hset' : nodup(x, y, g).
rewrite [Equality.sort _]/= in Hset *; by Nodup_nodup O.
eapply while.hoare_conseq; last by apply (BGCD_HAC.prelude_verif _ _ _ _ _ Hset' Hvx Hvy).
- move=> s h /= [H1 [H2 [H3 [x_g [y_g H6]]]]].
repeat (split; first by done).
split; last by move/negP: H6.
rewrite -x_g -y_g.
apply Zis_gcd_gcd; last first.
rewrite (Zmult_comm [x]_s) (Zmult_comm [y]_s).
by apply Zis_gcd_mult, Zgcd_is_gcd.
apply Zmult_le_0_compat => //; by apply Zgcd_is_pos.
- move=> s h /= [-> [-> ->]]; by rewrite 2!Zmult_1_r.
u <- var_e x ;
apply hoare_assign with (fun s _ =>
0 <= [x]_s /\ 0 <= [y]_s /\ 0 <= [g]_s /\
[x]_ s * [g]_s = vx /\ [y]_s * [g]_s = vy /\
Zgcd vx vy = [g]_s * Zgcd ([x]_s) ([y]_s) /\
~ eval_b (((var_e x mode nat_e 2) =e nat_e O) &e ((var_e y mode nat_e 2) =e nat_e O)) s /\
[u]_s = [x]_s).
move=> s h /= [H1 [H2 [H3 [Hxg [Hyg [H4 H5]]]]]]; by rewrite /wp_assign; repeat Store_upd.
0 <= [x]_s /\ 0 <= [y]_s /\ 0 <= [g]_s /\
[x]_ s * [g]_s = vx /\ [y]_s * [g]_s = vy /\
Zgcd vx vy = [g]_s * Zgcd ([x]_s) ([y]_s) /\
~ eval_b (((var_e x mode nat_e 2) =e nat_e O) &e ((var_e y mode nat_e 2) =e nat_e O)) s /\
[u]_s = [x]_s).
move=> s h /= [H1 [H2 [H3 [Hxg [Hyg [H4 H5]]]]]]; by rewrite /wp_assign; repeat Store_upd.
v <- var_e y ;
apply hoare_assign with (fun s _ =>
0 <= [x]_s /\ 0 <= [y]_s /\ 0 <= [g]_s /\
[x]_ s * [g]_s = vx /\ [y]_s * [g]_s = vy /\
Zgcd vx vy = [g]_s * Zgcd ([x]_s) ([y]_s) /\
~ eval_b (((var_e x mode nat_e 2) =e nat_e O) &e ((var_e y mode nat_e 2) =e nat_e O)) s /\
[u]_s = [x]_s /\ [v]_s = [y]_s).
move=> s h /= [H1 [H2 [H3 [Hxg [Hyg [H4 [H5 Hu]]]]]]]; by rewrite /wp_assign; repeat Store_upd.
0 <= [x]_s /\ 0 <= [y]_s /\ 0 <= [g]_s /\
[x]_ s * [g]_s = vx /\ [y]_s * [g]_s = vy /\
Zgcd vx vy = [g]_s * Zgcd ([x]_s) ([y]_s) /\
~ eval_b (((var_e x mode nat_e 2) =e nat_e O) &e ((var_e y mode nat_e 2) =e nat_e O)) s /\
[u]_s = [x]_s /\ [v]_s = [y]_s).
move=> s h /= [H1 [H2 [H3 [Hxg [Hyg [H4 [H5 Hu]]]]]]]; by rewrite /wp_assign; repeat Store_upd.
A <- nat_e 1 ;
apply hoare_assign with (fun s _ =>
0 <= [x]_s /\ 0 <= [y]_s /\ 0 <= [g]_s /\
[x]_ s * [g]_s = vx /\ [y]_s * [g]_s = vy /\
Zgcd vx vy = [g]_s * Zgcd ([x]_s) ([y]_s) /\
~ eval_b (((var_e x mode nat_e 2) =e nat_e O) &e ((var_e y mode nat_e 2) =e nat_e O)) s /\
[u]_s = [x]_s /\ [v]_s = [y]_s /\ [A]_s = 1).
move=> s h /= [H1 [H2 [H3 [Hxg [Hyg [H4 [H5 [Hu Hv]]]]]]]]; by rewrite /wp_assign; repeat Store_upd.
0 <= [x]_s /\ 0 <= [y]_s /\ 0 <= [g]_s /\
[x]_ s * [g]_s = vx /\ [y]_s * [g]_s = vy /\
Zgcd vx vy = [g]_s * Zgcd ([x]_s) ([y]_s) /\
~ eval_b (((var_e x mode nat_e 2) =e nat_e O) &e ((var_e y mode nat_e 2) =e nat_e O)) s /\
[u]_s = [x]_s /\ [v]_s = [y]_s /\ [A]_s = 1).
move=> s h /= [H1 [H2 [H3 [Hxg [Hyg [H4 [H5 [Hu Hv]]]]]]]]; by rewrite /wp_assign; repeat Store_upd.
B <- nat_e O ;
apply hoare_assign with (fun s _ =>
0 <= [x]_s /\ 0 <= [y]_s /\ 0 <= [g]_s /\
[x]_ s * [g]_s = vx /\ [y]_s * [g]_s = vy /\
Zgcd vx vy = [g]_s * Zgcd ([x]_s) ([y]_s) /\
~ [ ((var_e x mode nat_e 2) =e nat_e O) &e ((var_e y mode nat_e 2) =e nat_e O) ]b_ s /\
[u]_s = [x]_s /\ [v]_s = [y]_s /\ [A]_s = 1 /\ [B]_s = 0).
move=> s h /= [H1 [H2 [H3 [Hxg [Hyg [H4 [H5 [Hu [Hv HA]]]]]]]]]; by rewrite /wp_assign; repeat Store_upd.
0 <= [x]_s /\ 0 <= [y]_s /\ 0 <= [g]_s /\
[x]_ s * [g]_s = vx /\ [y]_s * [g]_s = vy /\
Zgcd vx vy = [g]_s * Zgcd ([x]_s) ([y]_s) /\
~ [ ((var_e x mode nat_e 2) =e nat_e O) &e ((var_e y mode nat_e 2) =e nat_e O) ]b_ s /\
[u]_s = [x]_s /\ [v]_s = [y]_s /\ [A]_s = 1 /\ [B]_s = 0).
move=> s h /= [H1 [H2 [H3 [Hxg [Hyg [H4 [H5 [Hu [Hv HA]]]]]]]]]; by rewrite /wp_assign; repeat Store_upd.
C <- nat_e O ;
apply hoare_assign with (fun s _ =>
0 <= [x]_s /\ 0 <= [y]_s /\ 0 <= [g]_s /\
[x]_ s * [g]_s = vx /\ [y]_s * [g]_s = vy /\
Zgcd vx vy = [g]_s * Zgcd ([x]_s) ([y]_s) /\
~ [ ((var_e x mode nat_e 2) =e nat_e O) &e ((var_e y mode nat_e 2) =e nat_e O) ]b_ s /\
[u]_s = [x]_s /\ [v]_s = [y]_s /\ [A]_s = 1 /\ [B]_s = 0 /\ [C]_s = 0).
move=> s h /= [H1 [H2 [H3 [Hxg [Hyg [H4 [H5 [Hu [Hv [HA HB]]]]]]]]]]; by rewrite /wp_assign; repeat Store_upd.
0 <= [x]_s /\ 0 <= [y]_s /\ 0 <= [g]_s /\
[x]_ s * [g]_s = vx /\ [y]_s * [g]_s = vy /\
Zgcd vx vy = [g]_s * Zgcd ([x]_s) ([y]_s) /\
~ [ ((var_e x mode nat_e 2) =e nat_e O) &e ((var_e y mode nat_e 2) =e nat_e O) ]b_ s /\
[u]_s = [x]_s /\ [v]_s = [y]_s /\ [A]_s = 1 /\ [B]_s = 0 /\ [C]_s = 0).
move=> s h /= [H1 [H2 [H3 [Hxg [Hyg [H4 [H5 [Hu [Hv [HA HB]]]]]]]]]]; by rewrite /wp_assign; repeat Store_upd.
D <- nat_e 1 ;
apply hoare_assign with (fun s _ =>
0 <= [x]_s /\ 0 <= [y]_s /\ 0 <= [g]_s /\
[x]_ s * [g]_s = vx /\ [y]_s * [g]_s = vy /\
Zgcd vx vy = [g]_s * Zgcd ([x]_s) ([y]_s) /\
~ eval_b (((var_e x mode nat_e 2) =e nat_e O) &e ((var_e y mode nat_e 2) =e nat_e O)) s /\
[u]_s = [x]_s /\ [v]_s = [y]_s /\ [A]_s = 1 /\ [B]_s = 0 /\ [C]_s = 0 /\ [D]_s = 1).
move=> s h /= [H1 [H2 [H3 [Hxg [Hyg [H4 [H5 [Hu [Hv [HA [HB HC]]]]]]]]]]]; by rewrite /wp_assign; repeat Store_upd.
0 <= [x]_s /\ 0 <= [y]_s /\ 0 <= [g]_s /\
[x]_ s * [g]_s = vx /\ [y]_s * [g]_s = vy /\
Zgcd vx vy = [g]_s * Zgcd ([x]_s) ([y]_s) /\
~ eval_b (((var_e x mode nat_e 2) =e nat_e O) &e ((var_e y mode nat_e 2) =e nat_e O)) s /\
[u]_s = [x]_s /\ [v]_s = [y]_s /\ [A]_s = 1 /\ [B]_s = 0 /\ [C]_s = 0 /\ [D]_s = 1).
move=> s h /= [H1 [H2 [H3 [Hxg [Hyg [H4 [H5 [Hu [Hv [HA [HB HC]]]]]]]]]]]; by rewrite /wp_assign; repeat Store_upd.
outer_loop
eapply while.hoare_conseq; last by apply (outer_loop_verif g x y u v A B C D vx vy Hset Hvx Hvy).
- move=> s h /= [[Hx [Hy [Hg [Hu_pos [Hv_pos [Hxg [Hyg [HAB [HCD [Hgcd Hparity]]]]]]]]]] Heq].
have {Heq}Heq : [u]_s = 0.
move: Heq.
rewrite /hoare_m.eval_b /= ZIT.t_gt_t_ge.
move/ZIT.t_geb_true.
rewrite /ZIT.t_ge => ?; by myomega.
rewrite Heq /= Zabs_eq // in Hgcd.
split.
rewrite -Hxg -Hyg -HCD; ring.
rewrite -Hgcd; by apply Zgcd_is_gcd.
- move=> s h /= [Hx [Hy [Hg [Hxg [Hyg [Hgcd [Hcond [Hu [Hv [HA [HB [HC HD]]]]]]]]]]]].
rewrite HA HB HC HD 2!Zmult_1_l 2!Zmult_0_l Zplus_0_r Zplus_0_l Hu Hv.
move/negP : Hcond.
rewrite negb_and.
case/orP; move/ZIT.tP; move/not_Zmod_2_Zodd; by intuition.
Qed.
End BEGCD_HAC.
Definition uivi_init u v u1 u2 u3 v1 v2 v3 s :=
[u1]_s = 1 /\ [u2]_s = 0 /\[u3]_s = [u]_s /\
[v1]_s = [v]_s /\ [v2]_s = 1 - [u]_s /\ [v3]_s = [v]_s.
Definition ti_init u v t1 t2 t3 s :=
(Zodd [u]_s -> [t1]_s = 0 /\ [t2]_s = -1 /\ [t3]_s = -[v]_s) /\
(Zeven [u]_s -> [t1]_s = 1 /\ [t2]_s = 0 /\ [t3]_s = [u]_s).
Definition uv_init vu vv u v s := [u]_s = vu /\ [v]_s = vv.
Definition C1 vu vv u v g s := uv_init vu vv u v s /\ [g]_s = 1.
Definition C2 vu vv u v g s := 0 < [u]_s /\ 0 < [v]_s /\ 0 < [g]_s /\
[u]_ s * [g]_s = vu /\ [v]_s * [g]_s = vv.
Definition C3 vu vv u v g s :=
Zgcd vu vv = [g]_s * Zgcd [u]_s [v]_s /\
~ [ (var_e u mode nat_e 2 =e nat_e O) &e (var_e v mode nat_e 2) =e nat_e O ]b_ s.
Definition C4 u3 v3 t3 s := exists k, ([t3]_s * 2 ^^ k = - [v3]_s /\ Zodd [u3]_s) \/
([t3]_s * 2 ^^ k = [u3]_s /\ Zodd [v3]_s) \/
([t3]_s * 2 ^^ k = ([u3]_s - [v3]_s) /\ (Zodd [v3]_s \/ Zodd [u3]_s)).
Definition C5 u3 v3 s := 0 < [u3]_s /\ 0 < [v3]_s.
Definition CVectors u v u1 u2 u3 v1 v2 v3 t1 t2 t3 s :=
[u ]_ s * [t1 ]_ s + [v ]_ s * [t2 ]_ s = [t3 ]_ s /\
[u ]_ s * [u1 ]_ s + [v ]_ s * [u2 ]_ s = [u3 ]_ s /\
[u ]_ s * [v1 ]_ s + [v ]_ s * [v2 ]_ s = [v3 ]_ s.
- move=> s h /= [[Hx [Hy [Hg [Hu_pos [Hv_pos [Hxg [Hyg [HAB [HCD [Hgcd Hparity]]]]]]]]]] Heq].
have {Heq}Heq : [u]_s = 0.
move: Heq.
rewrite /hoare_m.eval_b /= ZIT.t_gt_t_ge.
move/ZIT.t_geb_true.
rewrite /ZIT.t_ge => ?; by myomega.
rewrite Heq /= Zabs_eq // in Hgcd.
split.
rewrite -Hxg -Hyg -HCD; ring.
rewrite -Hgcd; by apply Zgcd_is_gcd.
- move=> s h /= [Hx [Hy [Hg [Hxg [Hyg [Hgcd [Hcond [Hu [Hv [HA [HB [HC HD]]]]]]]]]]]].
rewrite HA HB HC HD 2!Zmult_1_l 2!Zmult_0_l Zplus_0_r Zplus_0_l Hu Hv.
move/negP : Hcond.
rewrite negb_and.
case/orP; move/ZIT.tP; move/not_Zmod_2_Zodd; by intuition.
Qed.
End BEGCD_HAC.
Definition uivi_init u v u1 u2 u3 v1 v2 v3 s :=
[u1]_s = 1 /\ [u2]_s = 0 /\[u3]_s = [u]_s /\
[v1]_s = [v]_s /\ [v2]_s = 1 - [u]_s /\ [v3]_s = [v]_s.
Definition ti_init u v t1 t2 t3 s :=
(Zodd [u]_s -> [t1]_s = 0 /\ [t2]_s = -1 /\ [t3]_s = -[v]_s) /\
(Zeven [u]_s -> [t1]_s = 1 /\ [t2]_s = 0 /\ [t3]_s = [u]_s).
Definition uv_init vu vv u v s := [u]_s = vu /\ [v]_s = vv.
Definition C1 vu vv u v g s := uv_init vu vv u v s /\ [g]_s = 1.
Definition C2 vu vv u v g s := 0 < [u]_s /\ 0 < [v]_s /\ 0 < [g]_s /\
[u]_ s * [g]_s = vu /\ [v]_s * [g]_s = vv.
Definition C3 vu vv u v g s :=
Zgcd vu vv = [g]_s * Zgcd [u]_s [v]_s /\
~ [ (var_e u mode nat_e 2 =e nat_e O) &e (var_e v mode nat_e 2) =e nat_e O ]b_ s.
Definition C4 u3 v3 t3 s := exists k, ([t3]_s * 2 ^^ k = - [v3]_s /\ Zodd [u3]_s) \/
([t3]_s * 2 ^^ k = [u3]_s /\ Zodd [v3]_s) \/
([t3]_s * 2 ^^ k = ([u3]_s - [v3]_s) /\ (Zodd [v3]_s \/ Zodd [u3]_s)).
Definition C5 u3 v3 s := 0 < [u3]_s /\ 0 < [v3]_s.
Definition CVectors u v u1 u2 u3 v1 v2 v3 t1 t2 t3 s :=
[u ]_ s * [t1 ]_ s + [v ]_ s * [t2 ]_ s = [t3 ]_ s /\
[u ]_ s * [u1 ]_ s + [v ]_ s * [u2 ]_ s = [u3 ]_ s /\
[u ]_ s * [v1 ]_ s + [v ]_ s * [v2 ]_ s = [v3 ]_ s.
binary extended gcd algorithm from The Art of Computer Programming
Module TAOCP.
Definition init u v u1 u2 u3 v1 v2 v3 t1 t2 t3 :=
(u1 <- nat_e 1 ;
u2 <- nat_e 0 ;
u3 <- var_e u ;
v1 <- var_e v ;
v2 <- nat_e 1 .-e var_e u ;
v3 <- var_e v) ;
ifte var_e u mode nat_e 2 =e nat_e 1 thendo
(t1 <- nat_e 0 ;
t2 <- cst_e (-1) ;
t3 <- .--e var_e v)
elsedo
(t1 <- nat_e 1 ;
t2 <- nat_e 0 ;
t3 <- var_e u).
Definition halve u v t1 t2 t3 :=
ifte (var_e t1 mode nat_e 2 =e nat_e 0 &e var_e t2 mode nat_e 2 =e nat_e 0) thendo
(t1 <- var_e t1 ./e nat_e 2 ;
t2 <- var_e t2 ./e nat_e 2 ;
t3 <- var_e t3 ./e nat_e 2)
elsedo
(t1 <- (var_e t1 +e var_e v) ./e nat_e 2 ;
t2 <- (var_e t2 .-e var_e u) ./e nat_e 2 ;
t3 <- var_e t3 ./e nat_e 2).
Definition reset u v u1 u2 u3 v1 v2 v3 t1 t2 t3 :=
ifte (var_e t3 >>= nat_e 0) thendo
(u1 <- var_e t1 ;
u2 <- var_e t2 ;
u3 <- var_e t3)
elsedo
(v1 <- var_e v .-e var_e t1 ;
v2 <- .--e (var_e u +e var_e t2) ;
v3 <- .--e var_e t3 ).
Definition subtract u v u1 u2 u3 v1 v2 v3 t1 t2 t3 :=
(t1 <- var_e u1 .-e var_e v1 ;
t2 <- var_e u2 .-e var_e v2 ;
t3 <- var_e u3 .-e var_e v3) ;
ifte (nat_e 0 >>= var_e t1) thendo
(t1 <- var_e t1 +e var_e v ;
t2 <- var_e t2 .-e var_e u)
elsedo
skip.
Definition begcd g u v u1 u2 u3 v1 v2 v3 t1 t2 t3 :=
g <- nat_e 1 ;
prelude u v g ;
init u v u1 u2 u3 v1 v2 v3 t1 t2 t3 ;
while.while (var_e t3 <>e nat_e 0) (
while.while (var_e t3 mode nat_e 2 =e nat_e O) (
halve u v t1 t2 t3) ;
reset u v u1 u2 u3 v1 v2 v3 t1 t2 t3 ;
subtract u v u1 u2 u3 v1 v2 v3 t1 t2 t3).
Section taocp.
Variables g u v u1 u2 u3 v1 v2 v3 t1 t2 t3 : ssrnat.nat_eqType.
Variables vv vu : Z.
Lemma begcd_verif_intermediate :
nodup(g, u, v, u1, u2, u3, v1, v2, v3, t1, t2, t3) -> 0 < vu -> 0 < vv ->
{{ fun s _ => C2 vu vv u v g s /\
C3 vu vv u v g s /\
uivi_init u v u1 u2 u3 v1 v2 v3 s /\
ti_init u v t1 t2 t3 s }}
while.while (var_e t3 <>e nat_e 0)
(while.while (var_e t3 mode nat_e 2 =e nat_e 0) (halve u v t1 t2 t3);
reset u v u1 u2 u3 v1 v2 v3 t1 t2 t3;
subtract u v u1 u2 u3 v1 v2 v3 t1 t2 t3)
{{ fun s _ => vu * [u1 ]_ s + vv * [u2 ]_ s = [g ]_ s * [u3 ]_ s /\
Zgcd vu vv = [g ]_ s * [u3 ]_ s }}.
Proof.
move=> Hset Hvv Hvu.
Definition init u v u1 u2 u3 v1 v2 v3 t1 t2 t3 :=
(u1 <- nat_e 1 ;
u2 <- nat_e 0 ;
u3 <- var_e u ;
v1 <- var_e v ;
v2 <- nat_e 1 .-e var_e u ;
v3 <- var_e v) ;
ifte var_e u mode nat_e 2 =e nat_e 1 thendo
(t1 <- nat_e 0 ;
t2 <- cst_e (-1) ;
t3 <- .--e var_e v)
elsedo
(t1 <- nat_e 1 ;
t2 <- nat_e 0 ;
t3 <- var_e u).
Definition halve u v t1 t2 t3 :=
ifte (var_e t1 mode nat_e 2 =e nat_e 0 &e var_e t2 mode nat_e 2 =e nat_e 0) thendo
(t1 <- var_e t1 ./e nat_e 2 ;
t2 <- var_e t2 ./e nat_e 2 ;
t3 <- var_e t3 ./e nat_e 2)
elsedo
(t1 <- (var_e t1 +e var_e v) ./e nat_e 2 ;
t2 <- (var_e t2 .-e var_e u) ./e nat_e 2 ;
t3 <- var_e t3 ./e nat_e 2).
Definition reset u v u1 u2 u3 v1 v2 v3 t1 t2 t3 :=
ifte (var_e t3 >>= nat_e 0) thendo
(u1 <- var_e t1 ;
u2 <- var_e t2 ;
u3 <- var_e t3)
elsedo
(v1 <- var_e v .-e var_e t1 ;
v2 <- .--e (var_e u +e var_e t2) ;
v3 <- .--e var_e t3 ).
Definition subtract u v u1 u2 u3 v1 v2 v3 t1 t2 t3 :=
(t1 <- var_e u1 .-e var_e v1 ;
t2 <- var_e u2 .-e var_e v2 ;
t3 <- var_e u3 .-e var_e v3) ;
ifte (nat_e 0 >>= var_e t1) thendo
(t1 <- var_e t1 +e var_e v ;
t2 <- var_e t2 .-e var_e u)
elsedo
skip.
Definition begcd g u v u1 u2 u3 v1 v2 v3 t1 t2 t3 :=
g <- nat_e 1 ;
prelude u v g ;
init u v u1 u2 u3 v1 v2 v3 t1 t2 t3 ;
while.while (var_e t3 <>e nat_e 0) (
while.while (var_e t3 mode nat_e 2 =e nat_e O) (
halve u v t1 t2 t3) ;
reset u v u1 u2 u3 v1 v2 v3 t1 t2 t3 ;
subtract u v u1 u2 u3 v1 v2 v3 t1 t2 t3).
Section taocp.
Variables g u v u1 u2 u3 v1 v2 v3 t1 t2 t3 : ssrnat.nat_eqType.
Variables vv vu : Z.
Lemma begcd_verif_intermediate :
nodup(g, u, v, u1, u2, u3, v1, v2, v3, t1, t2, t3) -> 0 < vu -> 0 < vv ->
{{ fun s _ => C2 vu vv u v g s /\
C3 vu vv u v g s /\
uivi_init u v u1 u2 u3 v1 v2 v3 s /\
ti_init u v t1 t2 t3 s }}
while.while (var_e t3 <>e nat_e 0)
(while.while (var_e t3 mode nat_e 2 =e nat_e 0) (halve u v t1 t2 t3);
reset u v u1 u2 u3 v1 v2 v3 t1 t2 t3;
subtract u v u1 u2 u3 v1 v2 v3 t1 t2 t3)
{{ fun s _ => vu * [u1 ]_ s + vv * [u2 ]_ s = [g ]_ s * [u3 ]_ s /\
Zgcd vu vv = [g ]_ s * [u3 ]_ s }}.
Proof.
move=> Hset Hvv Hvu.
while.while (var_e t3 <>e nat_e 0)
apply hoare_prop_m.hoare_while_invariant with (fun s _ =>
C2 vu vv u v g s /\
(Zodd [u]_s \/ Zodd [v]_s) /\
CVectors u v u1 u2 u3 v1 v2 v3 t1 t2 t3 s /\
C4 u3 v3 t3 s /\
C5 u3 v3 s /\
Zgcd [u]_s [v]_s = Zgcd [u3]_s [v3]_s).
rewrite /while.entails => s h.
case => [[Hu [Hv [Hg [u_g v_g]]] [[Hgcd Hcond] [[Hu1 [Hu2 [Hu3 [Hv1 [Hv2 Hv3]]]]]]]] Ht].
rewrite /CVectors Hu1 Hu2 Hu3 Hv1 Hv2 Hv3.
repeat (split; first by tauto).
case: (Zeven_odd_dec [u]_s) => u_parity.
- case: Ht => _.
move/(_ u_parity) => [Ht1 [Ht2 Ht3]].
rewrite /C2 /C4 /C5 Ht1 Ht2 Ht3 Hu3 Hv3 Zmult_1_r Zmult_0_r Zplus_0_r.
split; first by done.
split.
move/negP : Hcond => /=.
rewrite negb_and /ZIT.t_eqb /ZIT.t_mod /=.
case/orP; move/Zeq_boolP => X.
+ left; by apply not_Zmod_2_Zodd.
+ right; by apply not_Zmod_2_Zodd.
split.
repeat (split; first by tauto).
ring.
split; last by done.
exists O; rewrite [Zpower _ _]/= !Zmult_1_r; right; left.
split; first by reflexivity.
move/negP : Hcond => /=.
rewrite negb_and /ZIT.t_eqb /ZIT.t_mod.
case/orP; move/Zeq_boolP.
+ move/not_Zmod_2_Zodd; by move/Zodd_not_Zeven.
+ by move/not_Zmod_2_Zodd.
- case: Ht.
move/(_ u_parity) => [Ht1 [Ht2 Ht3]] _.
rewrite /C2 /C4 /C5 Ht1 Ht2 Ht3 Hu3 Hv3 Zmult_1_r Zmult_0_r Zplus_0_l Zmult_0_r Zplus_0_r.
split; first by done.
split.
move/negP : Hcond => /=.
rewrite negb_and /ZIT.t_eqb /ZIT.t_mod /=.
case/orP; move/Zeq_boolP => X.
* left; by apply not_Zmod_2_Zodd.
* right; by apply not_Zmod_2_Zodd.
split.
split; first by ring.
split; [done | ring].
split; last by done.
exists O; rewrite [Zpower _ _]/= !Zmult_1_r; tauto.
- rewrite /while.entails => s h.
case => [[[Hu [Hv [Hg [u_g v_g]]]] [H6 [[Hti [Hui Hvi]] [H10 [[Hu3 Hv3] H14]]]]] H1].
split; first by rewrite -u_g -v_g -Hui; ring.
rewrite /hoare_m.eval_b /= /ZIT.t_eqb in H1.
move/negPn : H1; move/Zeq_boolP => H1.
case: H10 => k [H10|[H10 | H10]].
+ have abs : [v3 ]_ s = 0.
move: (Zpower_0 k) => X.
case: H10 => H10 H10'.
rewrite H1 Zmult_0_l in H10; by myomega.
rewrite abs Zgcd_0 Zabs_eq in H14; last by myomega.
rewrite -H14 -Zgcd_mult; last by myomega.
by rewrite Zmult_comm u_g Zmult_comm v_g.
+ have abs : [u ]_ s = 0.
rewrite H1 Zmult_0_l in H10; by myomega.
rewrite abs in Hu; by apply Zlt_irrefl in Hu.
+ have abs : [u3 ]_ s = [v3 ]_ s.
rewrite H1 Zmult_0_l in H10; by myomega.
rewrite -abs Zgcd_same in H14; last by myomega.
rewrite -H14 -u_g -v_g -Zgcd_mult; last by myomega.
by rewrite (Zmult_comm [u ]_ s) (Zmult_comm [v ]_ s).
apply while.hoare_seq with (fun s h =>
C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
CVectors u v u1 u2 u3 v1 v2 v3 t1 t2 t3 s /\
C4 u3 v3 t3 s /\
C5 u3 v3 s /\
Zgcd vu vv = [g ]_ s * Zgcd [u3 ]_ s [v3 ]_ s /\
Zodd [t3]_s ).
rewrite /halve.
apply hoare_prop_m.hoare_while_invariant with (fun s h =>
C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
CVectors u v u1 u2 u3 v1 v2 v3 t1 t2 t3 s /\
C4 u3 v3 t3 s /\
C5 u3 v3 s /\
Zgcd [u ]_ s [v ]_ s = Zgcd [u3 ]_ s [v3 ]_ s /\
[t3]_s <> 0).
move=> s h /=.
case => [[[Hu [Hv [Hg [u_g v_g]]]] [H6 [[Hti [Hui Hvi]] [H10 [[Hu3 Hv3] H14]]]]] H1].
repeat (split => //).
by move/Zeq_boolP : H1.
move=> s h /=.
case => [[[Hu [Hv [Hg [u_g v_g]]]] [H6 [[Hti [Hui Hvi]] [H10 [[Hu3 Hv3] [H14 H15]]]]]] H1].
repeat (split; first by done).
split.
rewrite /C2 -u_g -v_g -H14 -Zgcd_mult; last by myomega.
f_equal; by rewrite Zmult_comm.
rewrite /hoare_m.eval_b /= /ZIT.t_eqb /ZIT.t_mod in H1.
move/Zeq_boolP : H1.
by move/not_Zmod_2_Zodd.
apply while.hoare_ifte.
- apply hoare_assign with (fun s h => C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
([u ]_ s * 2 * [t1 ]_ s + [v ]_ s * [t2 ]_ s = [t3 ]_ s /\
[u ]_ s * [u1 ]_ s + [v ]_ s * [u2 ]_ s = [u3 ]_ s /\
[u ]_ s * [v1 ]_ s + [v ]_ s * [v2 ]_ s = [v3 ]_ s) /\
C4 u3 v3 t3 s /\
C5 u3 v3 s /\
Zgcd [u ]_ s [v ]_ s = Zgcd [u3 ]_ s [v3 ]_ s /\
[t3 ]_ s <> 0 /\
Zeven [t3]_s /\
Zeven [t2]_s).
move=> s h /=.
case => [[[[Hu [Hv [Hg [u_g v_g]]]] [H7 [[Hti [Hui Hvi]] [H11 [[Hu3 Hv3] [H14 H16]]]]]] H3] H1].
rewrite /wp_assign /C2 /C4 /C5.
repeat Store_upd.
repeat (split; first by tauto).
split.
rewrite -Zmult_assoc div_e_exact_full_2 //.
rewrite /hoare_m.eval_b /= in H1.
case/andP : H1 => H1 _.
rewrite /ZIT.t_eqb /ZIT.t_mod /= in H1.
by move/Zeq_boolP : H1.
repeat (split; first by done).
rewrite /hoare_m.eval_b /= /ZIT.t_eqb /ZIT.t_mod /= in H1, H3.
move/Zeq_boolP : H3 => H3.
case/andP : H1 => _.
move/Zeq_boolP => H1.
split; by apply Zmod_2_Zeven.
apply hoare_assign with (fun s _ => C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
([u ]_ s * 2 * [t1 ]_ s + [v ]_ s * 2 * [t2 ]_ s = [t3 ]_ s /\
[u ]_ s * [u1 ]_ s + [v ]_ s * [u2 ]_ s = [u3 ]_ s /\
[u ]_ s * [v1 ]_ s + [v ]_ s * [v2 ]_ s = [v3 ]_ s) /\
C4 u3 v3 t3 s /\
C5 u3 v3 s /\
Zgcd [u ]_ s [v ]_ s = Zgcd [u3 ]_ s [v3 ]_ s /\
[t3 ]_ s <> 0 /\ Zeven [t3 ]_ s ).
move=> s h.
case => [[Hu [Hv [Hg [u_g v_g]]]] [H5 [[Hti [Hui Hvi]] [H9 [[Hu3 Hv3] [H12 [H13 [H14 H16]]]]]]]].
rewrite /wp_assign /C2 /C4 /C5.
repeat Store_upd.
repeat (split; first by tauto).
split; last by done.
rewrite -(Zmult_assoc [v]_s) div_e_exact_full_2 //; by apply Zeven_Zmod_2.
apply hoare_assign' => s h.
case => [[Hu [Hv [Hg [u_g v_g]]] [H5 [[Hti [Hui Hvi] [H9 [[Hu3 Hv3] [H15 [H16 H17]]]]]]]]].
rewrite /wp_assign /C2 /C4 /C5 /CVectors.
repeat Store_upd.
repeat (split; first by tauto).
split.
rewrite /= -Hti /ZIT.t_div.
set tmp := _ + [v]_s * 2 * _ .
have -> : tmp = ([u ]_ s * [t1 ]_ s + [v ]_ s * [t2 ]_ s) * 2 by rewrite /tmp; ring.
by rewrite Z_div_mult_full.
repeat (split; first by assumption).
split.
case/Zeven_ex : H17 => m H17.
rewrite [eval _ _]/= H17 (Zmult_comm 2) /ZIT.t_div Z_div_mult_full //.
case: H9 => k [ [H9 H9'] | ].
+ exists (S k); left.
by rewrite Zpower_S Zmult_assoc -(Zmult_comm 2) -H17.
+ case ; exists (S k); right.
* left; by rewrite Zpower_S Zmult_assoc -(Zmult_comm 2) -H17.
* right; by rewrite Zpower_S Zmult_assoc -(Zmult_comm 2) -H17.
repeat (split; first by done).
case/Zeven_ex : H17 => m H17.
rewrite /= H17 (Zmult_comm 2) /ZIT.t_div Z_div_mult_full //; by myomega.
apply hoare_assign with (fun s h => C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
([u ]_ s * (2 * [t1 ]_ s - [v]_s) + [v ]_ s * [t2 ]_ s = [t3 ]_ s /\
[u ]_ s * [u1 ]_ s + [v ]_ s * [u2 ]_ s = [u3 ]_ s /\
[u ]_ s * [v1 ]_ s + [v ]_ s * [v2 ]_ s = [v3 ]_ s) /\
C4 u3 v3 t3 s /\
C5 u3 v3 s /\
Zgcd [u ]_ s [v ]_ s = Zgcd [u3 ]_ s [v3 ]_ s /\
[t3 ]_ s <> 0 /\ Zeven [t3]_s /\
(Zodd (2 * [t1]_s - [v]_s) \/ Zodd [t2]_s)).
move=> s h.
case => [[[[Hu [Hv [Hg [u_g v_g]]]] [H7 [[Hti [Hui Hvi]] [H11 [[Hu3 Hv3] [H14 H16]]]]]] H3] H1].
rewrite /wp_assign /C2 /C4 /C5.
repeat Store_upd.
rewrite /hoare_m.eval_b /= /ZIT.t_eqb /ZIT.t_mod in H1 H3.
rewrite negb_and in H1.
have t1_v : [var_e t1 +e var_e v ]e_ s mod 2 = 0.
rewrite /= /ZIT.t_plus.
case/orP: H1; move/Zeq_boolP => H1.
- apply Zeven_Zmod_2, Zodd_plus_Zodd.
by apply not_Zmod_2_Zodd.
case: H7 => H7; last by exact H7.
move/Zeq_boolP : H3.
move/Zmod_2_Zeven.
rewrite -Hti.
case/Zeven_plus_inv.
+ case=> H31 H32.
have : Zodd ([u ]_ s * [t1 ]_ s).
apply Zodd_mult_Zodd => //; by apply not_Zmod_2_Zodd.
by move/Zodd_not_Zeven.
+ case => _.
by case/Zodd_mult_inv=> ? _.
- case: H7 => H7.
+ move/Zeq_boolP : H3.
move/Zmod_2_Zeven.
rewrite -Hti.
case/Zeven_plus_inv => [[u_t1 v_t2]|[]].
* case/Zeven_mult_inv : v_t2 => v_t2.
- case/Zeven_mult_inv : u_t1 => u_t1.
+ by move/Zodd_not_Zeven : H7.
+ by apply Zeven_Zmod_2, Zeven_plus_Zeven.
- move/not_Zmod_2_Zodd : H1.
by move/Zodd_not_Zeven.
* case/Zodd_mult_inv=> _ odd_t1.
case/Zodd_mult_inv=> odd_v _.
by apply Zeven_Zmod_2, Zodd_plus_Zodd.
+ move/Zeq_boolP : H3.
move/Zmod_2_Zeven.
rewrite -Hti.
case/Zeven_plus_inv => [[u_t1 v_t2]| []].
* have : Zodd ([v ]_ s * [t2 ]_ s).
apply Zodd_mult_Zodd => //; by apply not_Zmod_2_Zodd.
by move/Zodd_not_Zeven.
* case/Zodd_mult_inv=> _ odd_t1 _.
by apply Zeven_Zmod_2, Zodd_plus_Zodd.
split; first by done.
repeat (split; first by assumption).
split.
split; [rewrite div_e_exact_full_2 //= /ZIT.t_plus -Hti; ring | done].
repeat (split; first by done).
split; first by apply Zmod_2_Zeven; by apply/Zeq_boolP.
case/orP : H1 => H1.
- left.
rewrite div_e_exact_full_2 //.
move/Zeq_boolP : H1.
move/not_Zmod_2_Zodd.
suff : [var_e t1 +e var_e v ]e_ s - [v ]_ s = [t1]_s by move=> ->.
rewrite /= /ZIT.t_plus; ring.
- right.
move/Zeq_boolP : H1.
by move/not_Zmod_2_Zodd.
apply hoare_assign with (fun s h => C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
([u ]_ s * (2 * [t1 ]_ s - [v]_s) + [v ]_ s * (2 * [t2 ]_ s + [u]_s) = [t3 ]_ s /\
[u ]_ s * [u1 ]_ s + [v ]_ s * [u2 ]_ s = [u3 ]_ s /\
[u ]_ s * [v1 ]_ s + [v ]_ s * [v2 ]_ s = [v3 ]_ s) /\
C4 u3 v3 t3 s /\
C5 u3 v3 s /\
Zgcd [u ]_ s [v ]_ s = Zgcd [u3 ]_ s [v3 ]_ s /\
[t3 ]_ s <> 0 /\ Zeven [t3]_s).
move=> s h H.
rewrite (Zmult_comm 2) /= -(Zmult_comm 2) in H.
case: H => [[Hu [Hv [Hg [u_g v_g]]]] [H5 [[Hti [Hui Hvi]] [H9 [[Hu3 Hv3] [H12 [H13 [H14 H16]]]]]]]].
rewrite /C2 /wp_assign /C4 /C5.
repeat Store_upd.
have t2_u : [var_e t2 .-e var_e u ]e_ s mod 2 = 0.
rewrite /= /ZIT.t_minus.
apply Zeven_Zmod_2.
case: H5 => [odd_u | odd_v].
- case: H16 => H16.
+ move: H14.
rewrite -Hti.
case/Zeven_plus_inv.
* case.
case/Zeven_mult_inv; by move/Zeven_not_Zodd.
* case.
case/Zodd_mult_inv=> K1 _.
case/Zodd_mult_inv=> _ K4.
apply Zodd_plus_Zodd => //; by apply Zodd_opp.
+ apply Zodd_plus_Zodd => //; by apply Zodd_opp.
- case: H16 => H16.
+ move: H14.
rewrite -Hti.
case/Zeven_plus_inv.
* case.
case/Zeven_mult_inv => [u_even | ].
- case/Zeven_mult_inv => [ | even_t2].
by move/Zeven_not_Zodd.
apply Zeven_plus_Zeven => //; by apply Zeven_opp.
- by move/Zeven_not_Zodd.
* case.
case/Zodd_mult_inv=> odd_u _.
case/Zodd_mult_inv=> _ odd_t2.
apply Zodd_plus_Zodd => //; by apply Zodd_opp.
+ move: H14.
rewrite -Hti.
case/Zeven_plus_inv.
* case.
case/Zeven_mult_inv => [u_even | _]; case/Zeven_mult_inv; by move/Zeven_not_Zodd.
* case.
case/Zodd_mult_inv=> odd_u _ _.
apply Zodd_plus_Zodd => //; by apply Zodd_opp.
repeat (split; first by done).
split; last by done.
split; [rewrite div_e_exact_full_2 // /ZIT.t_plus -Hti (Zmult_comm 2) /= /ZIT.t_minus; ring | done].
apply hoare_assign' => s h H.
rewrite !(Zmult_comm 2) in H.
case: H => [[Hu [Hv [Hg [u_g v_g]]]] [H5 [[Hti [Hui Hvi]] [H9 [[Hu3 Hv3] [H12 [H13 H15]]]]]]].
rewrite /C2 /wp_assign /C4 /C5 /CVectors.
repeat Store_upd.
repeat (split; first by tauto).
split.
rewrite /= -Hti /ZIT.t_div.
have : ([u ]_ s * ([t1 ]_ s * 2 - [v ]_ s) + [v ]_ s * ([t2 ]_ s * 2 + [u ]_ s)) =
([u ]_ s * [t1 ]_ s + [v ]_ s * [t2 ]_ s) * 2 by ring.
move=> ->; by rewrite Z_div_mult_full.
repeat (split; first by done).
split.
case/Zeven_ex : H15 => m H15.
rewrite [eval _ _]/= H15 (Zmult_comm 2) /ZIT.t_div Z_div_mult_full //.
case: H9 => k [[H9 H9']|].
- exists (S k); left.
by rewrite Zpower_S Zmult_assoc -(Zmult_comm 2) -H15.
- case=> H9; exists (S k); right.
+ left; by rewrite Zpower_S Zmult_assoc -(Zmult_comm 2) -H15.
+ right; by rewrite Zpower_S Zmult_assoc -(Zmult_comm 2) -H15.
repeat (split; first by assumption).
case/Zeven_ex : H15 => m H15 /=.
rewrite H15 Zmult_comm /ZIT.t_div Z_div_mult_full //; by myomega.
apply while.hoare_seq with (fun s _ => C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
CVectors u v u1 u2 u3 v1 v2 v3 t1 t2 t3 s /\
(0 <= [t3]_s -> Zgcd vu vv = [g ]_ s * Zgcd [t3 ]_ s [v3 ]_ s /\ Zodd [u3]_s /\
[u3]_s = [t3]_s ) /\
([t3]_s < 0 -> Zgcd vu vv = [g ]_ s * Zgcd [u3 ]_ s [t3 ]_ s /\ Zodd [v3]_s /\
[v3]_s = - [t3]_s ) /\
C5 u3 v3 s).
rewrite /reset.
apply while.hoare_ifte.
apply hoare_assign with (fun s h => C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
([u ]_ s * [t1 ]_ s + [v ]_ s * [t2 ]_ s = [t3 ]_ s /\
[u ]_ s * [u1 ]_ s + [v ]_ s * [t2 ]_ s = [t3 ]_ s /\
[u ]_ s * [v1 ]_ s + [v ]_ s * [v2 ]_ s = [v3 ]_ s) /\
C4 u3 v3 t3 s /\
Zgcd vu vv = [g ]_ s * Zgcd [u3 ]_ s [v3 ]_ s /\ Zodd [t3 ]_ s /\
C5 u3 v3 s /\
0 < [t3]_s).
move=> s h /=.
case => [[[Hu [Hv [Hg [u_g v_g]]]] [H6 [[Hti [Hui Hvi]] [H10 [[Hu3 Hv3] [H13 H15]]]]]] H1].
rewrite /wp_assign /C2 /C4 /C5.
repeat Store_upd.
rewrite /hoare_m.eval_b /= /ZIT.t_geb in H1.
move/Zge_boolP : H1 => H1.
repeat (split; first by tauto).
move/Zge_le : H1.
case/Zle_lt_or_eq => H1 //.
by rewrite -H1 in H15.
apply hoare_assign with (fun s h => C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
([u ]_ s * [t1 ]_ s + [v ]_ s * [t2 ]_ s = [t3 ]_ s /\
[u ]_ s * [u1 ]_ s + [v ]_ s * [u2 ]_ s = [t3 ]_ s /\
[u ]_ s * [v1 ]_ s + [v ]_ s * [v2 ]_ s = [v3 ]_ s) /\
C4 u3 v3 t3 s /\
Zgcd vu vv = [g ]_ s * Zgcd [u3 ]_ s [v3 ]_ s /\
Zodd [t3 ]_ s /\ C5 u3 v3 s /\ 0 < [t3 ]_ s).
move=> s h /= H.
rewrite /wp_assign /C2 /C4 /C5.
repeat Store_upd.
tauto.
apply hoare_assign' => s h.
case => [[Hu [Hv [Hg [u_g v_g]]]] [H5 [[Hti [Hui Hvi]] [H9 [H10 [H11 [[Hu3 Hv3] H15]]]]]]].
rewrite /wp_assign /C2 /C4 /C5 /CVectors.
repeat Store_upd.
repeat (split; first by tauto).
split.
move=> Ht3.
case: H9 => k [ [H9 H9'] | [ [H9 H9'] | [H9 H9']]].
- suff : False by done.
have abs : -[v3]_s < 0 by myomega.
rewrite -H9 in abs.
move/Zlt_not_le : abs.
apply.
apply Zmult_le_0_compat => //; by apply Zpower_0'.
- rewrite -H9 in H10.
by rewrite Zgcd_Zpower_odd // in H10.
- have Htmp : [u3 ]_ s = [t3 ]_ s * 2 ^^ k + [v3 ]_ s by myomega.
rewrite Htmp in H10.
move: (Zgcd_for_euclid ([t3 ]_ s * 2 ^^ k) [v3 ]_ s 1) => X.
rewrite Zmult_1_l in X.
rewrite {}X in H10.
destruct k as [|k].
- by rewrite /= Zmult_1_r in H10.
- case: H9' => // H9'.
by rewrite Zgcd_Zpower_odd // in H10.
rewrite Zgcd_Zpower_odd // in H10.
have -> : [v3 ]_ s = [u3 ]_ s - [t3 ]_ s * 2 ^^ S k by myomega.
apply Zodd_plus_Zeven => //.
by apply Zeven_opp, Zeven_mult_Zeven_r, Zeven_power.
split; last by done.
move=> Ht3.
suff : False by done.
by myomega.
apply hoare_assign with (fun s h => C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
([u ]_ s * [t1 ]_ s + [v ]_ s * [t2 ]_ s = [t3 ]_ s /\
[u ]_ s * [u1 ]_ s + [v ]_ s * [u2 ]_ s = [u3 ]_ s /\
[u ]_ s * [v1]_s + [v]_s * (- [u]_s - [t2]_s ) = - [t3 ]_ s) /\
C4 u3 v3 t3 s /\
C5 u3 v3 s /\
Zgcd vu vv = [g ]_ s * Zgcd [u3 ]_ s [v3 ]_ s /\ Zodd [t3 ]_ s /\
[t3]_s < 0).
move=> s h /= H.
case : H => [[[Hu [Hv [Hg [u_g v_g]]]] [H6 [[Hti [Hui Hvi]] [H10 [[Hu3 Hv3] [H13 H15]]]]]] H1].
rewrite /wp_assign /C2 /C4 /C5.
repeat Store_upd.
repeat (split; first by done).
split.
split; first by rewrite -Hti /= /ZIT.t_minus; ring.
split; [done | rewrite -Hti /= /ZIT.t_minus; ring].
repeat (split; first by done).
rewrite /hoare_m.eval_b /= /ZIT.t_geb in H1.
move/Zge_boolP : H1 => ?; by myomega.
apply hoare_assign with (fun s _ => C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
([u ]_ s * [t1 ]_ s + [v ]_ s * [t2 ]_ s = [t3 ]_ s /\
[u ]_ s * [u1 ]_ s + [v ]_ s * [u2 ]_ s = [u3 ]_ s /\
[u ]_ s * [v1]_s + [v]_s * [v2]_s = - [t3 ]_ s) /\
C4 u3 v3 t3 s /\
C5 u3 v3 s /\
Zgcd vu vv = [g ]_ s * Zgcd [u3 ]_ s [v3 ]_ s /\
Zodd [t3 ]_ s /\ [t3 ]_ s < 0).
move=> s h.
case => [[Hu [Hv [Hg [u_g v_g]]]] [H6 [[Hti [Hui Hvi]] [H10 [H11 [H12 [H13 H15]]]]]]].
rewrite /wp_assign /C2 /C4 /C5.
repeat Store_upd.
repeat (split => //).
rewrite /= /ZIT.t_plus -Hvi; ring.
apply hoare_assign' => s h.
case => [[Hu [Hv [Hg [u_g v_g]]]] [H6 [[Hti [Hui Hvi]] [H10 [[Hu3 Hv3] [H13 [H15 H16]]]]]]].
rewrite /wp_assign /C2 /C4 /C5 /CVectors.
repeat Store_upd.
split; first by done.
repeat (split; first by done).
rewrite /=.
split; first by move/Zle_not_lt.
split; last by myomega.
move=> _.
rewrite /=.
case: H10 => k [ [H10 H10'] | [ [H10 H10'] | [H10 H10'] ] ].
- have X : [v3 ]_ s = - ([t3 ]_ s * 2 ^^ k) by myomega.
rewrite {}X Zgcd_opp in H13.
symmetry in H13.
rewrite Zgcd_sym Zgcd_Zpower_odd // in H13.
split; first by symmetry; rewrite Zgcd_sym.
split; [by apply Zodd_opp | done].
- rewrite -H10 in Hu3.
move: (Zmult_lt_0_reg_r _ _ (Zpower_0 k) Hu3) => abs.
suff : False by done. by myomega.
- have Htmp : [v3]_s = [u3 ]_ s - [t3 ]_ s * 2 ^^ k by myomega.
rewrite Htmp in H13.
move: (Zgcd_for_euclid (-[t3]_s * 2 ^^ k) ([u3]_s) 1).
rewrite Zmult_1_l Zplus_comm -Zopp_mult_distr_l Zplus_Zopp Zgcd_sym.
move=> X.
rewrite X (Zgcd_sym _ [u3]_s) Zgcd_opp (Zgcd_sym [u3]_s) in H13.
destruct k.
+ rewrite /= Zmult_1_r in H13.
split; first by rewrite (Zgcd_sym [u3]_s).
split; [by apply Zodd_opp | done].
+ rewrite Zgcd_Zpower_odd // in H13; last first.
have -> : [u3 ]_ s = [v3 ]_ s + [t3 ]_ s * 2 ^^ S k by myomega.
apply Zodd_plus_Zeven; last by apply Zeven_mult_Zeven_r, Zeven_power.
case: H10' => H10' //.
rewrite Htmp.
apply Zodd_plus_Zeven => //.
by apply Zeven_opp, Zeven_mult_Zeven_r, Zeven_power.
split; first by rewrite (Zgcd_sym [u3]_s).
split; [by apply Zodd_opp | done].
rewrite /subtract.
apply while.hoare_seq with (fun s _ => C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
CVectors u v u1 u2 u3 v1 v2 v3 t1 t2 t3 s /\
[t3]_s = [u3]_s - [v3]_s /\
Zgcd vu vv = [g ]_ s * Zgcd [t3 ]_ s [v3 ]_ s /\
(Zodd [v3 ]_ s \/ Zodd [u3 ]_ s) /\
C5 u3 v3 s).
apply hoare_assign with (fun s _ => C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
([u ]_ s * [t1 ]_ s + [v ]_ s * ([u2]_s - [v2 ]_ s) = [u3 ]_ s - [v3]_s /\
[u ]_ s * [u1 ]_ s + [v ]_ s * [u2 ]_ s = [u3 ]_ s /\
[u ]_ s * [v1 ]_ s + [v ]_ s * [v2 ]_ s = [v3 ]_ s) /\
(0 <= [t3]_s -> Zgcd vu vv = [g ]_ s * Zgcd [t3 ]_ s [v3 ]_ s /\ Zodd [u3]_s /\
[u3]_s = [t3]_s ) /\
([t3]_s < 0 -> Zgcd vu vv = [g ]_ s * Zgcd [u3 ]_ s [t3 ]_ s /\ Zodd [v3]_s /\
[v3]_s = - [t3]_s) /\
C5 u3 v3 s).
move=> s h.
case => [[Hu [Hv [Hg [u_g v_g]]]] [H5 [[Hti [Hui Hvi]] [H9 [H10 [Hu3 Hv3]]]]]].
rewrite /wp_assign /C2 /C5 /CVectors.
repeat Store_upd.
repeat (split; first by done).
split; last by done.
split; [rewrite /= /ZIT.t_minus -Hui -Hvi; ring | done].
apply hoare_assign with (fun s _ => C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
([u ]_ s * [t1 ]_ s + [v ]_ s * [t2]_s = [u3 ]_ s - [v3]_s/\
[u ]_ s * [u1 ]_ s + [v ]_ s * [u2 ]_ s = [u3 ]_ s /\
[u ]_ s * [v1 ]_ s + [v ]_ s * [v2 ]_ s = [v3 ]_ s) /\
(0 <= [t3]_s -> Zgcd vu vv = [g ]_ s * Zgcd [t3 ]_ s [v3 ]_ s /\ Zodd [u3]_s /\
[u3]_s = [t3]_s) /\
([t3]_s < 0 -> Zgcd vu vv = [g ]_ s * Zgcd [u3 ]_ s [t3 ]_ s /\ Zodd [v3]_s /\
[v3]_s = - [t3]_s) /\
C5 u3 v3 s).
move=> s h.
case => [[Hu [Hv [Hg [u_g v_g]]]] [H5 [[Hti [Hui Hvi]] [H9 [H10 [Hu3 Hv3]]]]]].
rewrite /wp_assign /C2 /C5.
by repeat Store_upd.
apply hoare_assign'.
move=> s h [[Hu [Hv [Hg [u_g v_g]]]] [H5 [[Hti [Hui Hvi]] [H9 [H10 [Hu3 Hv3]]]]]].
rewrite /wp_assign /C2 /C5 /CVectors.
repeat Store_upd.
repeat (split; first by tauto).
split.
case: (Z_lt_le_dec [t3]_s 0).
- move/H10 => H10'.
move: (Zgcd_for_euclid [u3]_s [v3]_s (-1)).
rewrite Zopp_eq_mult_neg_1_L Zplus_Zopp => ->.
case: H10' => H10' [H10'' H10'''].
rewrite H10''' Zgcd_opp; tauto.
- move/H9.
case => H9' [H9'' H9'''].
rewrite /= H9'''.
move: (Zgcd_for_euclid [t3]_s [v3]_s (-1)).
by rewrite Zopp_eq_mult_neg_1_L Zplus_Zopp => ->.
split; last by done.
case: (Z_lt_le_dec [t3]_s 0).
- move/H10; tauto.
- move/H9; tauto.
apply while.hoare_ifte.
C2 vu vv u v g s /\
(Zodd [u]_s \/ Zodd [v]_s) /\
CVectors u v u1 u2 u3 v1 v2 v3 t1 t2 t3 s /\
C4 u3 v3 t3 s /\
C5 u3 v3 s /\
Zgcd [u]_s [v]_s = Zgcd [u3]_s [v3]_s).
rewrite /while.entails => s h.
case => [[Hu [Hv [Hg [u_g v_g]]] [[Hgcd Hcond] [[Hu1 [Hu2 [Hu3 [Hv1 [Hv2 Hv3]]]]]]]] Ht].
rewrite /CVectors Hu1 Hu2 Hu3 Hv1 Hv2 Hv3.
repeat (split; first by tauto).
case: (Zeven_odd_dec [u]_s) => u_parity.
- case: Ht => _.
move/(_ u_parity) => [Ht1 [Ht2 Ht3]].
rewrite /C2 /C4 /C5 Ht1 Ht2 Ht3 Hu3 Hv3 Zmult_1_r Zmult_0_r Zplus_0_r.
split; first by done.
split.
move/negP : Hcond => /=.
rewrite negb_and /ZIT.t_eqb /ZIT.t_mod /=.
case/orP; move/Zeq_boolP => X.
+ left; by apply not_Zmod_2_Zodd.
+ right; by apply not_Zmod_2_Zodd.
split.
repeat (split; first by tauto).
ring.
split; last by done.
exists O; rewrite [Zpower _ _]/= !Zmult_1_r; right; left.
split; first by reflexivity.
move/negP : Hcond => /=.
rewrite negb_and /ZIT.t_eqb /ZIT.t_mod.
case/orP; move/Zeq_boolP.
+ move/not_Zmod_2_Zodd; by move/Zodd_not_Zeven.
+ by move/not_Zmod_2_Zodd.
- case: Ht.
move/(_ u_parity) => [Ht1 [Ht2 Ht3]] _.
rewrite /C2 /C4 /C5 Ht1 Ht2 Ht3 Hu3 Hv3 Zmult_1_r Zmult_0_r Zplus_0_l Zmult_0_r Zplus_0_r.
split; first by done.
split.
move/negP : Hcond => /=.
rewrite negb_and /ZIT.t_eqb /ZIT.t_mod /=.
case/orP; move/Zeq_boolP => X.
* left; by apply not_Zmod_2_Zodd.
* right; by apply not_Zmod_2_Zodd.
split.
split; first by ring.
split; [done | ring].
split; last by done.
exists O; rewrite [Zpower _ _]/= !Zmult_1_r; tauto.
- rewrite /while.entails => s h.
case => [[[Hu [Hv [Hg [u_g v_g]]]] [H6 [[Hti [Hui Hvi]] [H10 [[Hu3 Hv3] H14]]]]] H1].
split; first by rewrite -u_g -v_g -Hui; ring.
rewrite /hoare_m.eval_b /= /ZIT.t_eqb in H1.
move/negPn : H1; move/Zeq_boolP => H1.
case: H10 => k [H10|[H10 | H10]].
+ have abs : [v3 ]_ s = 0.
move: (Zpower_0 k) => X.
case: H10 => H10 H10'.
rewrite H1 Zmult_0_l in H10; by myomega.
rewrite abs Zgcd_0 Zabs_eq in H14; last by myomega.
rewrite -H14 -Zgcd_mult; last by myomega.
by rewrite Zmult_comm u_g Zmult_comm v_g.
+ have abs : [u ]_ s = 0.
rewrite H1 Zmult_0_l in H10; by myomega.
rewrite abs in Hu; by apply Zlt_irrefl in Hu.
+ have abs : [u3 ]_ s = [v3 ]_ s.
rewrite H1 Zmult_0_l in H10; by myomega.
rewrite -abs Zgcd_same in H14; last by myomega.
rewrite -H14 -u_g -v_g -Zgcd_mult; last by myomega.
by rewrite (Zmult_comm [u ]_ s) (Zmult_comm [v ]_ s).
apply while.hoare_seq with (fun s h =>
C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
CVectors u v u1 u2 u3 v1 v2 v3 t1 t2 t3 s /\
C4 u3 v3 t3 s /\
C5 u3 v3 s /\
Zgcd vu vv = [g ]_ s * Zgcd [u3 ]_ s [v3 ]_ s /\
Zodd [t3]_s ).
rewrite /halve.
apply hoare_prop_m.hoare_while_invariant with (fun s h =>
C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
CVectors u v u1 u2 u3 v1 v2 v3 t1 t2 t3 s /\
C4 u3 v3 t3 s /\
C5 u3 v3 s /\
Zgcd [u ]_ s [v ]_ s = Zgcd [u3 ]_ s [v3 ]_ s /\
[t3]_s <> 0).
move=> s h /=.
case => [[[Hu [Hv [Hg [u_g v_g]]]] [H6 [[Hti [Hui Hvi]] [H10 [[Hu3 Hv3] H14]]]]] H1].
repeat (split => //).
by move/Zeq_boolP : H1.
move=> s h /=.
case => [[[Hu [Hv [Hg [u_g v_g]]]] [H6 [[Hti [Hui Hvi]] [H10 [[Hu3 Hv3] [H14 H15]]]]]] H1].
repeat (split; first by done).
split.
rewrite /C2 -u_g -v_g -H14 -Zgcd_mult; last by myomega.
f_equal; by rewrite Zmult_comm.
rewrite /hoare_m.eval_b /= /ZIT.t_eqb /ZIT.t_mod in H1.
move/Zeq_boolP : H1.
by move/not_Zmod_2_Zodd.
apply while.hoare_ifte.
- apply hoare_assign with (fun s h => C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
([u ]_ s * 2 * [t1 ]_ s + [v ]_ s * [t2 ]_ s = [t3 ]_ s /\
[u ]_ s * [u1 ]_ s + [v ]_ s * [u2 ]_ s = [u3 ]_ s /\
[u ]_ s * [v1 ]_ s + [v ]_ s * [v2 ]_ s = [v3 ]_ s) /\
C4 u3 v3 t3 s /\
C5 u3 v3 s /\
Zgcd [u ]_ s [v ]_ s = Zgcd [u3 ]_ s [v3 ]_ s /\
[t3 ]_ s <> 0 /\
Zeven [t3]_s /\
Zeven [t2]_s).
move=> s h /=.
case => [[[[Hu [Hv [Hg [u_g v_g]]]] [H7 [[Hti [Hui Hvi]] [H11 [[Hu3 Hv3] [H14 H16]]]]]] H3] H1].
rewrite /wp_assign /C2 /C4 /C5.
repeat Store_upd.
repeat (split; first by tauto).
split.
rewrite -Zmult_assoc div_e_exact_full_2 //.
rewrite /hoare_m.eval_b /= in H1.
case/andP : H1 => H1 _.
rewrite /ZIT.t_eqb /ZIT.t_mod /= in H1.
by move/Zeq_boolP : H1.
repeat (split; first by done).
rewrite /hoare_m.eval_b /= /ZIT.t_eqb /ZIT.t_mod /= in H1, H3.
move/Zeq_boolP : H3 => H3.
case/andP : H1 => _.
move/Zeq_boolP => H1.
split; by apply Zmod_2_Zeven.
apply hoare_assign with (fun s _ => C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
([u ]_ s * 2 * [t1 ]_ s + [v ]_ s * 2 * [t2 ]_ s = [t3 ]_ s /\
[u ]_ s * [u1 ]_ s + [v ]_ s * [u2 ]_ s = [u3 ]_ s /\
[u ]_ s * [v1 ]_ s + [v ]_ s * [v2 ]_ s = [v3 ]_ s) /\
C4 u3 v3 t3 s /\
C5 u3 v3 s /\
Zgcd [u ]_ s [v ]_ s = Zgcd [u3 ]_ s [v3 ]_ s /\
[t3 ]_ s <> 0 /\ Zeven [t3 ]_ s ).
move=> s h.
case => [[Hu [Hv [Hg [u_g v_g]]]] [H5 [[Hti [Hui Hvi]] [H9 [[Hu3 Hv3] [H12 [H13 [H14 H16]]]]]]]].
rewrite /wp_assign /C2 /C4 /C5.
repeat Store_upd.
repeat (split; first by tauto).
split; last by done.
rewrite -(Zmult_assoc [v]_s) div_e_exact_full_2 //; by apply Zeven_Zmod_2.
apply hoare_assign' => s h.
case => [[Hu [Hv [Hg [u_g v_g]]] [H5 [[Hti [Hui Hvi] [H9 [[Hu3 Hv3] [H15 [H16 H17]]]]]]]]].
rewrite /wp_assign /C2 /C4 /C5 /CVectors.
repeat Store_upd.
repeat (split; first by tauto).
split.
rewrite /= -Hti /ZIT.t_div.
set tmp := _ + [v]_s * 2 * _ .
have -> : tmp = ([u ]_ s * [t1 ]_ s + [v ]_ s * [t2 ]_ s) * 2 by rewrite /tmp; ring.
by rewrite Z_div_mult_full.
repeat (split; first by assumption).
split.
case/Zeven_ex : H17 => m H17.
rewrite [eval _ _]/= H17 (Zmult_comm 2) /ZIT.t_div Z_div_mult_full //.
case: H9 => k [ [H9 H9'] | ].
+ exists (S k); left.
by rewrite Zpower_S Zmult_assoc -(Zmult_comm 2) -H17.
+ case ; exists (S k); right.
* left; by rewrite Zpower_S Zmult_assoc -(Zmult_comm 2) -H17.
* right; by rewrite Zpower_S Zmult_assoc -(Zmult_comm 2) -H17.
repeat (split; first by done).
case/Zeven_ex : H17 => m H17.
rewrite /= H17 (Zmult_comm 2) /ZIT.t_div Z_div_mult_full //; by myomega.
apply hoare_assign with (fun s h => C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
([u ]_ s * (2 * [t1 ]_ s - [v]_s) + [v ]_ s * [t2 ]_ s = [t3 ]_ s /\
[u ]_ s * [u1 ]_ s + [v ]_ s * [u2 ]_ s = [u3 ]_ s /\
[u ]_ s * [v1 ]_ s + [v ]_ s * [v2 ]_ s = [v3 ]_ s) /\
C4 u3 v3 t3 s /\
C5 u3 v3 s /\
Zgcd [u ]_ s [v ]_ s = Zgcd [u3 ]_ s [v3 ]_ s /\
[t3 ]_ s <> 0 /\ Zeven [t3]_s /\
(Zodd (2 * [t1]_s - [v]_s) \/ Zodd [t2]_s)).
move=> s h.
case => [[[[Hu [Hv [Hg [u_g v_g]]]] [H7 [[Hti [Hui Hvi]] [H11 [[Hu3 Hv3] [H14 H16]]]]]] H3] H1].
rewrite /wp_assign /C2 /C4 /C5.
repeat Store_upd.
rewrite /hoare_m.eval_b /= /ZIT.t_eqb /ZIT.t_mod in H1 H3.
rewrite negb_and in H1.
have t1_v : [var_e t1 +e var_e v ]e_ s mod 2 = 0.
rewrite /= /ZIT.t_plus.
case/orP: H1; move/Zeq_boolP => H1.
- apply Zeven_Zmod_2, Zodd_plus_Zodd.
by apply not_Zmod_2_Zodd.
case: H7 => H7; last by exact H7.
move/Zeq_boolP : H3.
move/Zmod_2_Zeven.
rewrite -Hti.
case/Zeven_plus_inv.
+ case=> H31 H32.
have : Zodd ([u ]_ s * [t1 ]_ s).
apply Zodd_mult_Zodd => //; by apply not_Zmod_2_Zodd.
by move/Zodd_not_Zeven.
+ case => _.
by case/Zodd_mult_inv=> ? _.
- case: H7 => H7.
+ move/Zeq_boolP : H3.
move/Zmod_2_Zeven.
rewrite -Hti.
case/Zeven_plus_inv => [[u_t1 v_t2]|[]].
* case/Zeven_mult_inv : v_t2 => v_t2.
- case/Zeven_mult_inv : u_t1 => u_t1.
+ by move/Zodd_not_Zeven : H7.
+ by apply Zeven_Zmod_2, Zeven_plus_Zeven.
- move/not_Zmod_2_Zodd : H1.
by move/Zodd_not_Zeven.
* case/Zodd_mult_inv=> _ odd_t1.
case/Zodd_mult_inv=> odd_v _.
by apply Zeven_Zmod_2, Zodd_plus_Zodd.
+ move/Zeq_boolP : H3.
move/Zmod_2_Zeven.
rewrite -Hti.
case/Zeven_plus_inv => [[u_t1 v_t2]| []].
* have : Zodd ([v ]_ s * [t2 ]_ s).
apply Zodd_mult_Zodd => //; by apply not_Zmod_2_Zodd.
by move/Zodd_not_Zeven.
* case/Zodd_mult_inv=> _ odd_t1 _.
by apply Zeven_Zmod_2, Zodd_plus_Zodd.
split; first by done.
repeat (split; first by assumption).
split.
split; [rewrite div_e_exact_full_2 //= /ZIT.t_plus -Hti; ring | done].
repeat (split; first by done).
split; first by apply Zmod_2_Zeven; by apply/Zeq_boolP.
case/orP : H1 => H1.
- left.
rewrite div_e_exact_full_2 //.
move/Zeq_boolP : H1.
move/not_Zmod_2_Zodd.
suff : [var_e t1 +e var_e v ]e_ s - [v ]_ s = [t1]_s by move=> ->.
rewrite /= /ZIT.t_plus; ring.
- right.
move/Zeq_boolP : H1.
by move/not_Zmod_2_Zodd.
apply hoare_assign with (fun s h => C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
([u ]_ s * (2 * [t1 ]_ s - [v]_s) + [v ]_ s * (2 * [t2 ]_ s + [u]_s) = [t3 ]_ s /\
[u ]_ s * [u1 ]_ s + [v ]_ s * [u2 ]_ s = [u3 ]_ s /\
[u ]_ s * [v1 ]_ s + [v ]_ s * [v2 ]_ s = [v3 ]_ s) /\
C4 u3 v3 t3 s /\
C5 u3 v3 s /\
Zgcd [u ]_ s [v ]_ s = Zgcd [u3 ]_ s [v3 ]_ s /\
[t3 ]_ s <> 0 /\ Zeven [t3]_s).
move=> s h H.
rewrite (Zmult_comm 2) /= -(Zmult_comm 2) in H.
case: H => [[Hu [Hv [Hg [u_g v_g]]]] [H5 [[Hti [Hui Hvi]] [H9 [[Hu3 Hv3] [H12 [H13 [H14 H16]]]]]]]].
rewrite /C2 /wp_assign /C4 /C5.
repeat Store_upd.
have t2_u : [var_e t2 .-e var_e u ]e_ s mod 2 = 0.
rewrite /= /ZIT.t_minus.
apply Zeven_Zmod_2.
case: H5 => [odd_u | odd_v].
- case: H16 => H16.
+ move: H14.
rewrite -Hti.
case/Zeven_plus_inv.
* case.
case/Zeven_mult_inv; by move/Zeven_not_Zodd.
* case.
case/Zodd_mult_inv=> K1 _.
case/Zodd_mult_inv=> _ K4.
apply Zodd_plus_Zodd => //; by apply Zodd_opp.
+ apply Zodd_plus_Zodd => //; by apply Zodd_opp.
- case: H16 => H16.
+ move: H14.
rewrite -Hti.
case/Zeven_plus_inv.
* case.
case/Zeven_mult_inv => [u_even | ].
- case/Zeven_mult_inv => [ | even_t2].
by move/Zeven_not_Zodd.
apply Zeven_plus_Zeven => //; by apply Zeven_opp.
- by move/Zeven_not_Zodd.
* case.
case/Zodd_mult_inv=> odd_u _.
case/Zodd_mult_inv=> _ odd_t2.
apply Zodd_plus_Zodd => //; by apply Zodd_opp.
+ move: H14.
rewrite -Hti.
case/Zeven_plus_inv.
* case.
case/Zeven_mult_inv => [u_even | _]; case/Zeven_mult_inv; by move/Zeven_not_Zodd.
* case.
case/Zodd_mult_inv=> odd_u _ _.
apply Zodd_plus_Zodd => //; by apply Zodd_opp.
repeat (split; first by done).
split; last by done.
split; [rewrite div_e_exact_full_2 // /ZIT.t_plus -Hti (Zmult_comm 2) /= /ZIT.t_minus; ring | done].
apply hoare_assign' => s h H.
rewrite !(Zmult_comm 2) in H.
case: H => [[Hu [Hv [Hg [u_g v_g]]]] [H5 [[Hti [Hui Hvi]] [H9 [[Hu3 Hv3] [H12 [H13 H15]]]]]]].
rewrite /C2 /wp_assign /C4 /C5 /CVectors.
repeat Store_upd.
repeat (split; first by tauto).
split.
rewrite /= -Hti /ZIT.t_div.
have : ([u ]_ s * ([t1 ]_ s * 2 - [v ]_ s) + [v ]_ s * ([t2 ]_ s * 2 + [u ]_ s)) =
([u ]_ s * [t1 ]_ s + [v ]_ s * [t2 ]_ s) * 2 by ring.
move=> ->; by rewrite Z_div_mult_full.
repeat (split; first by done).
split.
case/Zeven_ex : H15 => m H15.
rewrite [eval _ _]/= H15 (Zmult_comm 2) /ZIT.t_div Z_div_mult_full //.
case: H9 => k [[H9 H9']|].
- exists (S k); left.
by rewrite Zpower_S Zmult_assoc -(Zmult_comm 2) -H15.
- case=> H9; exists (S k); right.
+ left; by rewrite Zpower_S Zmult_assoc -(Zmult_comm 2) -H15.
+ right; by rewrite Zpower_S Zmult_assoc -(Zmult_comm 2) -H15.
repeat (split; first by assumption).
case/Zeven_ex : H15 => m H15 /=.
rewrite H15 Zmult_comm /ZIT.t_div Z_div_mult_full //; by myomega.
apply while.hoare_seq with (fun s _ => C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
CVectors u v u1 u2 u3 v1 v2 v3 t1 t2 t3 s /\
(0 <= [t3]_s -> Zgcd vu vv = [g ]_ s * Zgcd [t3 ]_ s [v3 ]_ s /\ Zodd [u3]_s /\
[u3]_s = [t3]_s ) /\
([t3]_s < 0 -> Zgcd vu vv = [g ]_ s * Zgcd [u3 ]_ s [t3 ]_ s /\ Zodd [v3]_s /\
[v3]_s = - [t3]_s ) /\
C5 u3 v3 s).
rewrite /reset.
apply while.hoare_ifte.
apply hoare_assign with (fun s h => C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
([u ]_ s * [t1 ]_ s + [v ]_ s * [t2 ]_ s = [t3 ]_ s /\
[u ]_ s * [u1 ]_ s + [v ]_ s * [t2 ]_ s = [t3 ]_ s /\
[u ]_ s * [v1 ]_ s + [v ]_ s * [v2 ]_ s = [v3 ]_ s) /\
C4 u3 v3 t3 s /\
Zgcd vu vv = [g ]_ s * Zgcd [u3 ]_ s [v3 ]_ s /\ Zodd [t3 ]_ s /\
C5 u3 v3 s /\
0 < [t3]_s).
move=> s h /=.
case => [[[Hu [Hv [Hg [u_g v_g]]]] [H6 [[Hti [Hui Hvi]] [H10 [[Hu3 Hv3] [H13 H15]]]]]] H1].
rewrite /wp_assign /C2 /C4 /C5.
repeat Store_upd.
rewrite /hoare_m.eval_b /= /ZIT.t_geb in H1.
move/Zge_boolP : H1 => H1.
repeat (split; first by tauto).
move/Zge_le : H1.
case/Zle_lt_or_eq => H1 //.
by rewrite -H1 in H15.
apply hoare_assign with (fun s h => C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
([u ]_ s * [t1 ]_ s + [v ]_ s * [t2 ]_ s = [t3 ]_ s /\
[u ]_ s * [u1 ]_ s + [v ]_ s * [u2 ]_ s = [t3 ]_ s /\
[u ]_ s * [v1 ]_ s + [v ]_ s * [v2 ]_ s = [v3 ]_ s) /\
C4 u3 v3 t3 s /\
Zgcd vu vv = [g ]_ s * Zgcd [u3 ]_ s [v3 ]_ s /\
Zodd [t3 ]_ s /\ C5 u3 v3 s /\ 0 < [t3 ]_ s).
move=> s h /= H.
rewrite /wp_assign /C2 /C4 /C5.
repeat Store_upd.
tauto.
apply hoare_assign' => s h.
case => [[Hu [Hv [Hg [u_g v_g]]]] [H5 [[Hti [Hui Hvi]] [H9 [H10 [H11 [[Hu3 Hv3] H15]]]]]]].
rewrite /wp_assign /C2 /C4 /C5 /CVectors.
repeat Store_upd.
repeat (split; first by tauto).
split.
move=> Ht3.
case: H9 => k [ [H9 H9'] | [ [H9 H9'] | [H9 H9']]].
- suff : False by done.
have abs : -[v3]_s < 0 by myomega.
rewrite -H9 in abs.
move/Zlt_not_le : abs.
apply.
apply Zmult_le_0_compat => //; by apply Zpower_0'.
- rewrite -H9 in H10.
by rewrite Zgcd_Zpower_odd // in H10.
- have Htmp : [u3 ]_ s = [t3 ]_ s * 2 ^^ k + [v3 ]_ s by myomega.
rewrite Htmp in H10.
move: (Zgcd_for_euclid ([t3 ]_ s * 2 ^^ k) [v3 ]_ s 1) => X.
rewrite Zmult_1_l in X.
rewrite {}X in H10.
destruct k as [|k].
- by rewrite /= Zmult_1_r in H10.
- case: H9' => // H9'.
by rewrite Zgcd_Zpower_odd // in H10.
rewrite Zgcd_Zpower_odd // in H10.
have -> : [v3 ]_ s = [u3 ]_ s - [t3 ]_ s * 2 ^^ S k by myomega.
apply Zodd_plus_Zeven => //.
by apply Zeven_opp, Zeven_mult_Zeven_r, Zeven_power.
split; last by done.
move=> Ht3.
suff : False by done.
by myomega.
apply hoare_assign with (fun s h => C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
([u ]_ s * [t1 ]_ s + [v ]_ s * [t2 ]_ s = [t3 ]_ s /\
[u ]_ s * [u1 ]_ s + [v ]_ s * [u2 ]_ s = [u3 ]_ s /\
[u ]_ s * [v1]_s + [v]_s * (- [u]_s - [t2]_s ) = - [t3 ]_ s) /\
C4 u3 v3 t3 s /\
C5 u3 v3 s /\
Zgcd vu vv = [g ]_ s * Zgcd [u3 ]_ s [v3 ]_ s /\ Zodd [t3 ]_ s /\
[t3]_s < 0).
move=> s h /= H.
case : H => [[[Hu [Hv [Hg [u_g v_g]]]] [H6 [[Hti [Hui Hvi]] [H10 [[Hu3 Hv3] [H13 H15]]]]]] H1].
rewrite /wp_assign /C2 /C4 /C5.
repeat Store_upd.
repeat (split; first by done).
split.
split; first by rewrite -Hti /= /ZIT.t_minus; ring.
split; [done | rewrite -Hti /= /ZIT.t_minus; ring].
repeat (split; first by done).
rewrite /hoare_m.eval_b /= /ZIT.t_geb in H1.
move/Zge_boolP : H1 => ?; by myomega.
apply hoare_assign with (fun s _ => C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
([u ]_ s * [t1 ]_ s + [v ]_ s * [t2 ]_ s = [t3 ]_ s /\
[u ]_ s * [u1 ]_ s + [v ]_ s * [u2 ]_ s = [u3 ]_ s /\
[u ]_ s * [v1]_s + [v]_s * [v2]_s = - [t3 ]_ s) /\
C4 u3 v3 t3 s /\
C5 u3 v3 s /\
Zgcd vu vv = [g ]_ s * Zgcd [u3 ]_ s [v3 ]_ s /\
Zodd [t3 ]_ s /\ [t3 ]_ s < 0).
move=> s h.
case => [[Hu [Hv [Hg [u_g v_g]]]] [H6 [[Hti [Hui Hvi]] [H10 [H11 [H12 [H13 H15]]]]]]].
rewrite /wp_assign /C2 /C4 /C5.
repeat Store_upd.
repeat (split => //).
rewrite /= /ZIT.t_plus -Hvi; ring.
apply hoare_assign' => s h.
case => [[Hu [Hv [Hg [u_g v_g]]]] [H6 [[Hti [Hui Hvi]] [H10 [[Hu3 Hv3] [H13 [H15 H16]]]]]]].
rewrite /wp_assign /C2 /C4 /C5 /CVectors.
repeat Store_upd.
split; first by done.
repeat (split; first by done).
rewrite /=.
split; first by move/Zle_not_lt.
split; last by myomega.
move=> _.
rewrite /=.
case: H10 => k [ [H10 H10'] | [ [H10 H10'] | [H10 H10'] ] ].
- have X : [v3 ]_ s = - ([t3 ]_ s * 2 ^^ k) by myomega.
rewrite {}X Zgcd_opp in H13.
symmetry in H13.
rewrite Zgcd_sym Zgcd_Zpower_odd // in H13.
split; first by symmetry; rewrite Zgcd_sym.
split; [by apply Zodd_opp | done].
- rewrite -H10 in Hu3.
move: (Zmult_lt_0_reg_r _ _ (Zpower_0 k) Hu3) => abs.
suff : False by done. by myomega.
- have Htmp : [v3]_s = [u3 ]_ s - [t3 ]_ s * 2 ^^ k by myomega.
rewrite Htmp in H13.
move: (Zgcd_for_euclid (-[t3]_s * 2 ^^ k) ([u3]_s) 1).
rewrite Zmult_1_l Zplus_comm -Zopp_mult_distr_l Zplus_Zopp Zgcd_sym.
move=> X.
rewrite X (Zgcd_sym _ [u3]_s) Zgcd_opp (Zgcd_sym [u3]_s) in H13.
destruct k.
+ rewrite /= Zmult_1_r in H13.
split; first by rewrite (Zgcd_sym [u3]_s).
split; [by apply Zodd_opp | done].
+ rewrite Zgcd_Zpower_odd // in H13; last first.
have -> : [u3 ]_ s = [v3 ]_ s + [t3 ]_ s * 2 ^^ S k by myomega.
apply Zodd_plus_Zeven; last by apply Zeven_mult_Zeven_r, Zeven_power.
case: H10' => H10' //.
rewrite Htmp.
apply Zodd_plus_Zeven => //.
by apply Zeven_opp, Zeven_mult_Zeven_r, Zeven_power.
split; first by rewrite (Zgcd_sym [u3]_s).
split; [by apply Zodd_opp | done].
rewrite /subtract.
apply while.hoare_seq with (fun s _ => C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
CVectors u v u1 u2 u3 v1 v2 v3 t1 t2 t3 s /\
[t3]_s = [u3]_s - [v3]_s /\
Zgcd vu vv = [g ]_ s * Zgcd [t3 ]_ s [v3 ]_ s /\
(Zodd [v3 ]_ s \/ Zodd [u3 ]_ s) /\
C5 u3 v3 s).
apply hoare_assign with (fun s _ => C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
([u ]_ s * [t1 ]_ s + [v ]_ s * ([u2]_s - [v2 ]_ s) = [u3 ]_ s - [v3]_s /\
[u ]_ s * [u1 ]_ s + [v ]_ s * [u2 ]_ s = [u3 ]_ s /\
[u ]_ s * [v1 ]_ s + [v ]_ s * [v2 ]_ s = [v3 ]_ s) /\
(0 <= [t3]_s -> Zgcd vu vv = [g ]_ s * Zgcd [t3 ]_ s [v3 ]_ s /\ Zodd [u3]_s /\
[u3]_s = [t3]_s ) /\
([t3]_s < 0 -> Zgcd vu vv = [g ]_ s * Zgcd [u3 ]_ s [t3 ]_ s /\ Zodd [v3]_s /\
[v3]_s = - [t3]_s) /\
C5 u3 v3 s).
move=> s h.
case => [[Hu [Hv [Hg [u_g v_g]]]] [H5 [[Hti [Hui Hvi]] [H9 [H10 [Hu3 Hv3]]]]]].
rewrite /wp_assign /C2 /C5 /CVectors.
repeat Store_upd.
repeat (split; first by done).
split; last by done.
split; [rewrite /= /ZIT.t_minus -Hui -Hvi; ring | done].
apply hoare_assign with (fun s _ => C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
([u ]_ s * [t1 ]_ s + [v ]_ s * [t2]_s = [u3 ]_ s - [v3]_s/\
[u ]_ s * [u1 ]_ s + [v ]_ s * [u2 ]_ s = [u3 ]_ s /\
[u ]_ s * [v1 ]_ s + [v ]_ s * [v2 ]_ s = [v3 ]_ s) /\
(0 <= [t3]_s -> Zgcd vu vv = [g ]_ s * Zgcd [t3 ]_ s [v3 ]_ s /\ Zodd [u3]_s /\
[u3]_s = [t3]_s) /\
([t3]_s < 0 -> Zgcd vu vv = [g ]_ s * Zgcd [u3 ]_ s [t3 ]_ s /\ Zodd [v3]_s /\
[v3]_s = - [t3]_s) /\
C5 u3 v3 s).
move=> s h.
case => [[Hu [Hv [Hg [u_g v_g]]]] [H5 [[Hti [Hui Hvi]] [H9 [H10 [Hu3 Hv3]]]]]].
rewrite /wp_assign /C2 /C5.
by repeat Store_upd.
apply hoare_assign'.
move=> s h [[Hu [Hv [Hg [u_g v_g]]]] [H5 [[Hti [Hui Hvi]] [H9 [H10 [Hu3 Hv3]]]]]].
rewrite /wp_assign /C2 /C5 /CVectors.
repeat Store_upd.
repeat (split; first by tauto).
split.
case: (Z_lt_le_dec [t3]_s 0).
- move/H10 => H10'.
move: (Zgcd_for_euclid [u3]_s [v3]_s (-1)).
rewrite Zopp_eq_mult_neg_1_L Zplus_Zopp => ->.
case: H10' => H10' [H10'' H10'''].
rewrite H10''' Zgcd_opp; tauto.
- move/H9.
case => H9' [H9'' H9'''].
rewrite /= H9'''.
move: (Zgcd_for_euclid [t3]_s [v3]_s (-1)).
by rewrite Zopp_eq_mult_neg_1_L Zplus_Zopp => ->.
split; last by done.
case: (Z_lt_le_dec [t3]_s 0).
- move/H10; tauto.
- move/H9; tauto.
apply while.hoare_ifte.
t1 <- svar t1 +e svar v
apply hoare_assign with (fun s h => C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
([u ]_ s * [t1 ]_ s + [v ]_ s * ([t2]_s - [u]_s) = [t3 ]_ s /\
[u ]_ s * [u1 ]_ s + [v ]_ s * [u2 ]_ s = [u3 ]_ s /\
[u ]_ s * [v1 ]_ s + [v ]_ s * [v2 ]_ s = [v3 ]_ s) /\
[t3 ]_ s = [u3 ]_ s - [v3 ]_ s /\
Zgcd vu vv = [g ]_ s * Zgcd [t3 ]_ s [v3 ]_ s /\
(Zodd [v3 ]_ s \/ Zodd [u3 ]_ s) /\
C5 u3 v3 s).
move=> s h.
case => [[[Hu [Hv [Hg [u_g v_g]]]] [H6 [[Hti [Hui Hvi]] [H10 [H11 [H12 [Hu3 Hv3]]]]]]] H1].
rewrite /wp_assign /C2 /C5.
repeat Store_upd.
repeat (split; first by done).
split; last by done.
split; [rewrite /= /ZIT.t_plus -Hti; ring | done].
apply hoare_assign' => s h.
case=> [[Hu [Hv [Hg [u_g v_g]]]] [H5 [[Hti [Hui Hvi]] [H9 [H10 [H11 [Hu3 Hv3]]]]]]].
rewrite /wp_assign /C2 /C4 /C5 /CVectors.
repeat Store_upd.
repeat (split; first by done).
split; first by exists O; right; right; rewrite /= Zmult_1_r.
repeat (split; first by assumption).
rewrite -(Zgcd_for_euclid [u3]_s [v3]_s (-1)) Zopp_eq_mult_neg_1_L Zplus_Zopp.
rewrite H9 -u_g -v_g -2!(Zmult_comm [g]_s) Zgcd_mult in H10; last by myomega.
apply Zmult_reg_l in H10 => //; by myomega.
apply hoare_skip' => s h.
case => [[[Hu [Hv [Hg [u_g v_g]]]] [H6 [[Hti [Hui Hvi]] [H10 [H11 [H12 [Hu3 Hv3]]]]]]] H1].
rewrite /wp_assign /C2 /C4.
repeat Store_upd.
repeat (split; first by done).
split; first by exists O; right; right; rewrite /= Zmult_1_r.
repeat (split; first by assumption).
rewrite -(Zgcd_for_euclid [u3]_s [v3]_s (-1)) Zopp_eq_mult_neg_1_L Zplus_Zopp.
rewrite H10 -v_g -u_g -2!(Zmult_comm [g]_s) Zgcd_mult in H11; last by myomega.
apply Zmult_reg_l in H11 => //; by myomega.
Qed.
Lemma prelude_verif2 : nodup(u, v, g) ->
0 < vu -> 0 < vv ->
{{ fun s _ => C2 vu vv u v g s }}
prelude u v g
{{ fun s _ => C2 vu vv u v g s /\
~~ [ (var_e u mode nat_e 2 =e nat_e 0) &e (var_e v mode nat_e 2 =e nat_e 0) ]b_ s }}.
Proof.
move=> Hset Hvu Hvv.
apply hoare_prop_m.hoare_while_invariant with (fun s _ => C2 vu vv u v g s).
by move=> s h /= [H1 [H2 [H3 [H4 H5]]]].
by move=> s h /= [[H1 [H2 [H3 [H4 H5]]]] H6].
u <- var_e u ./e nat_e 2
apply hoare_assign with (fun s h => 0 < [ u ]_s /\ 0 < [ v ]_s /\ 0 < [ g ]_s /\
2 * [ u ]_s * [ g ]_s = vu /\ [ v ]_s * [ g ]_s = vv /\ [ v ]_s mod 2 = 0).
move=> s h [[H1 [H2 [H3 [H4 H5]]]] H6].
rewrite /hoare_m.eval_b /= in H6; case/andP : H6. rewrite /ZIT.t_mod.
move/ZIT.t_eqb_eq => even_u. move/ZIT.t_eqb_eq => even_v.
rewrite /wp_assign; repeat Store_upd => //.
split.
rewrite /=.
apply Zlt_0_Zdiv => //.
rewrite -> Zmod_divides in even_u; last by auto.
case: even_u => k Hk; by myomega.
repeat (split; first by assumption).
split; last by done.
rewrite div_e_exact_full_2 //; by rewrite /hoare_m.eval_b in H6; omegab.
2 * [ u ]_s * [ g ]_s = vu /\ [ v ]_s * [ g ]_s = vv /\ [ v ]_s mod 2 = 0).
move=> s h [[H1 [H2 [H3 [H4 H5]]]] H6].
rewrite /hoare_m.eval_b /= in H6; case/andP : H6. rewrite /ZIT.t_mod.
move/ZIT.t_eqb_eq => even_u. move/ZIT.t_eqb_eq => even_v.
rewrite /wp_assign; repeat Store_upd => //.
split.
rewrite /=.
apply Zlt_0_Zdiv => //.
rewrite -> Zmod_divides in even_u; last by auto.
case: even_u => k Hk; by myomega.
repeat (split; first by assumption).
split; last by done.
rewrite div_e_exact_full_2 //; by rewrite /hoare_m.eval_b in H6; omegab.
v <- var_e v ./e nat_e 2;
apply hoare_assign with (fun s h => 0 < [ u ]_s /\ 0 < [ v ]_s /\ 0 < [ g ]_s /\
2 * [ u ]_s * [ g ]_s = vu /\ 2 * [ v ]_s * [ g ]_ s = vv).
move=> s h [H1 [H2 [H3 [H4 [H5 H6]]]]].
rewrite /wp_assign; repeat Store_upd => //.
split; first by assumption.
split.
rewrite /=; apply Zlt_0_Zdiv => //.
rewrite -> Zmod_divides in H6; last by auto.
case: H6 => k Hk; by myomega.
repeat (split; first by assumption).
by rewrite div_e_exact_full_2.
2 * [ u ]_s * [ g ]_s = vu /\ 2 * [ v ]_s * [ g ]_ s = vv).
move=> s h [H1 [H2 [H3 [H4 [H5 H6]]]]].
rewrite /wp_assign; repeat Store_upd => //.
split; first by assumption.
split.
rewrite /=; apply Zlt_0_Zdiv => //.
rewrite -> Zmod_divides in H6; last by auto.
case: H6 => k Hk; by myomega.
repeat (split; first by assumption).
by rewrite div_e_exact_full_2.
g <- nat_e 2 *e var_e g
apply hoare_assign' => s h [H1 [H2 [H3 [H4 H5]]]].
rewrite /wp_assign /C2; repeat Store_upd => //.
repeat (split; first by assumption).
split; first by apply Zmult_lt_0_compat.
rewrite /= -H4 -H5 /ZIT.t_mult; split; ring.
Qed.
Lemma begcd_verif_init0 : nodup(g, u, v, u1, u2, u3, v1, v2, v3, t1, t2, t3) ->
0 < vu -> 0 < vv ->
{{fun s _ => C2 vu vv u v g s /\ C3 vu vv u v g s }}
u1 <- nat_e 1;
u2 <- nat_e 0;
u3 <- var_e u;
v1 <- var_e v;
v2 <- nat_e 1 .-e var_e u;
v3 <- var_e v
{{fun s _ => C2 vu vv u v g s /\ C3 vu vv u v g s /\ uivi_init u v u1 u2 u3 v1 v2 v3 s}}.
Lemma begcd_verif_init1 : nodup(g,u,v,u1,u2,u3,v1,v2,v3,t1,t2,t3) ->
0 < vu -> 0 < vv ->
{{fun s _ => C2 vu vv u v g s /\ C3 vu vv u v g s /\ uivi_init u v u1 u2 u3 v1 v2 v3 s}}
ifte var_e u mode nat_e 2 =e nat_e 1 thendo
t1 <- nat_e 0;
t2 <- cst_e (-1);
t3 <- .--e var_e v
elsedo (
t1 <- nat_e 1;
t2 <- nat_e 0;
t3 <- var_e u)
{{fun s _ => C2 vu vv u v g s /\ C3 vu vv u v g s /\
uivi_init u v u1 u2 u3 v1 v2 v3 s /\ ti_init u v t1 t2 t3 s}}.
Lemma begcd_verif_init : nodup(g, u, v, u1, u2, u3, v1, v2, v3, t1, t2, t3) ->
0 < vu -> 0 < vv ->
{{fun s _ => C2 vu vv u v g s /\ C3 vu vv u v g s }}
init u v u1 u2 u3 v1 v2 v3 t1 t2 t3
{{fun s _ => C2 vu vv u v g s /\ C3 vu vv u v g s /\
uivi_init u v u1 u2 u3 v1 v2 v3 s /\ ti_init u v t1 t2 t3 s}}.
Lemma begcd_verif_prelude_init : nodup(g, u, v, u1, u2, u3, v1, v2, v3, t1, t2, t3) ->
0 < vu -> 0 < vv ->
{{ fun s h => [u]_s = vu /\ [v]_s = vv }}
g <- nat_e 1;
prelude u v g;
init u v u1 u2 u3 v1 v2 v3 t1 t2 t3
{{ fun s _ => C2 vu vv u v g s /\ C3 vu vv u v g s /\
uivi_init u v u1 u2 u3 v1 v2 v3 s /\
ti_init u v t1 t2 t3 s }}.
Proof.
move=> Hset Hvu Hvv.
rewrite /wp_assign /C2; repeat Store_upd => //.
repeat (split; first by assumption).
split; first by apply Zmult_lt_0_compat.
rewrite /= -H4 -H5 /ZIT.t_mult; split; ring.
Qed.
Lemma begcd_verif_init0 : nodup(g, u, v, u1, u2, u3, v1, v2, v3, t1, t2, t3) ->
0 < vu -> 0 < vv ->
{{fun s _ => C2 vu vv u v g s /\ C3 vu vv u v g s }}
u1 <- nat_e 1;
u2 <- nat_e 0;
u3 <- var_e u;
v1 <- var_e v;
v2 <- nat_e 1 .-e var_e u;
v3 <- var_e v
{{fun s _ => C2 vu vv u v g s /\ C3 vu vv u v g s /\ uivi_init u v u1 u2 u3 v1 v2 v3 s}}.
Lemma begcd_verif_init1 : nodup(g,u,v,u1,u2,u3,v1,v2,v3,t1,t2,t3) ->
0 < vu -> 0 < vv ->
{{fun s _ => C2 vu vv u v g s /\ C3 vu vv u v g s /\ uivi_init u v u1 u2 u3 v1 v2 v3 s}}
ifte var_e u mode nat_e 2 =e nat_e 1 thendo
t1 <- nat_e 0;
t2 <- cst_e (-1);
t3 <- .--e var_e v
elsedo (
t1 <- nat_e 1;
t2 <- nat_e 0;
t3 <- var_e u)
{{fun s _ => C2 vu vv u v g s /\ C3 vu vv u v g s /\
uivi_init u v u1 u2 u3 v1 v2 v3 s /\ ti_init u v t1 t2 t3 s}}.
Lemma begcd_verif_init : nodup(g, u, v, u1, u2, u3, v1, v2, v3, t1, t2, t3) ->
0 < vu -> 0 < vv ->
{{fun s _ => C2 vu vv u v g s /\ C3 vu vv u v g s }}
init u v u1 u2 u3 v1 v2 v3 t1 t2 t3
{{fun s _ => C2 vu vv u v g s /\ C3 vu vv u v g s /\
uivi_init u v u1 u2 u3 v1 v2 v3 s /\ ti_init u v t1 t2 t3 s}}.
Lemma begcd_verif_prelude_init : nodup(g, u, v, u1, u2, u3, v1, v2, v3, t1, t2, t3) ->
0 < vu -> 0 < vv ->
{{ fun s h => [u]_s = vu /\ [v]_s = vv }}
g <- nat_e 1;
prelude u v g;
init u v u1 u2 u3 v1 v2 v3 t1 t2 t3
{{ fun s _ => C2 vu vv u v g s /\ C3 vu vv u v g s /\
uivi_init u v u1 u2 u3 v1 v2 v3 s /\
ti_init u v t1 t2 t3 s }}.
Proof.
move=> Hset Hvu Hvv.
g <- nat_e 1 ;
apply hoare_assign with (fun s h => C1 vu vv u v g s).
move=> s h [Hu Hv].
by rewrite /wp_assign /C1 /uv_init; repeat Store_upd.
move=> s h [Hu Hv].
by rewrite /wp_assign /C1 /uv_init; repeat Store_upd.
prelude u v g ;
apply while.hoare_seq with (fun s _ => C2 vu vv u v g s /\ C3 vu vv u v g s).
have Hset' : nodup(u, v, g) by rewrite [Equality.sort _]/= in Hset *; Nodup_nodup O.
eapply while.hoare_conseq; last by apply (prelude_verif2 Hset' Hvu Hvv).
- move=> s h /= [[H1 [H2 [H3 [H4 H5]]]] H6].
rewrite /C2 /C3.
repeat (split; first by myomega).
split; last by move/negP: H6.
rewrite -H4 -H5.
apply Zis_gcd_gcd; last first.
rewrite (Zmult_comm [u]_s) (Zmult_comm [v]_s).
by apply Zis_gcd_mult, Zgcd_is_gcd.
apply Zmult_le_0_compat => //; first by myomega.
by apply Zgcd_is_pos.
- rewrite /C1 /uv_init /C2 => s h /= [[-> ->] ->]; by rewrite 2!Zmult_1_r.
by apply begcd_verif_init.
Qed.
have Hset' : nodup(u, v, g) by rewrite [Equality.sort _]/= in Hset *; Nodup_nodup O.
eapply while.hoare_conseq; last by apply (prelude_verif2 Hset' Hvu Hvv).
- move=> s h /= [[H1 [H2 [H3 [H4 H5]]]] H6].
rewrite /C2 /C3.
repeat (split; first by myomega).
split; last by move/negP: H6.
rewrite -H4 -H5.
apply Zis_gcd_gcd; last first.
rewrite (Zmult_comm [u]_s) (Zmult_comm [v]_s).
by apply Zis_gcd_mult, Zgcd_is_gcd.
apply Zmult_le_0_compat => //; first by myomega.
by apply Zgcd_is_pos.
- rewrite /C1 /uv_init /C2 => s h /= [[-> ->] ->]; by rewrite 2!Zmult_1_r.
by apply begcd_verif_init.
Qed.
NB: functional correctness only
Lemma begcd_verif:
nodup(g, u, v, u1, u2, u3, v1, v2, v3, t1, t2, t3) -> 0 < vu -> 0 < vv ->
{{ fun s h => [u]_s = vu /\ [v]_s = vv }}
begcd g u v u1 u2 u3 v1 v2 v3 t1 t2 t3
{{ fun s h => vu * [u1]_s + vv * [u2]_s = [g]_s * [u3]_s /\
Zgcd vu vv = ([g]_s * [u3]_s)}}.
End taocp.
End TAOCP.
Definition uivi_bounds u v u1 v1 u2 v2 u3 v3 s :=
0 <= [u1 ]_ s <= [v ]_ s /\ 0 <= [v1 ]_ s <= [v ]_ s /\
- [u ]_ s <= [u2 ]_ s <= 0 /\ - [u ]_ s <= [v2 ]_ s <= 0 /\
0 < [u3 ]_ s <= [u ]_ s /\ 0 < [v3 ]_ s <= [v ]_ s.
Definition ti_bounds u v t1 t2 t3 s :=
0 <= [t1 ]_ s <= [v ]_ s /\
- [u ]_ s <= [t2 ]_ s <= 0 /\
- [v ]_ s <= [t3 ]_ s <= [u ]_ s.
Lemma init_bounds : forall u v u1 u2 u3 v1 v2 v3 t1 t2 t3 s,
0 < [u]_s -> 0 < [v]_s ->
uivi_init u v u1 u2 u3 v1 v2 v3 s ->
ti_init u v t1 t2 t3 s ->
uivi_bounds u v u1 v1 u2 v2 u3 v3 s /\ ti_bounds u v t1 t2 t3 s.
Module TAOCP2.
Section taocp2.
Variables g u v u1 u2 u3 v1 v2 v3 t1 t2 t3 : ssrnat.nat_eqType.
Variables vu vv : Z.
Lemma begcd_verif_with_bounds_init :
nodup(g, u, v, u1, u2, u3, v1, v2, v3, t1, t2, t3) -> 0 < vu -> 0 < vv ->
{{ fun s h => uv_init vu vv u v s }}
g <- nat_e 1;
prelude u v g;
TAOCP.init u v u1 u2 u3 v1 v2 v3 t1 t2 t3
{{fun s _ => C2 vu vv u v g s /\ C3 vu vv u v g s /\
uivi_init u v u1 u2 u3 v1 v2 v3 s /\
ti_init u v t1 t2 t3 s /\
uivi_bounds u v u1 v1 u2 v2 u3 v3 s /\
ti_bounds u v t1 t2 t3 s}}.
Lemma begcd_while_halve_invariant : nodup(g, u, v, u1, u2, u3, v1, v2, v3, t1, t2, t3) ->
0 < vu -> 0 < vv ->
{{ fun s h => (C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
CVectors u v u1 u2 u3 v1 v2 v3 t1 t2 t3 s /\
C4 u3 v3 t3 s /\
C5 u3 v3 s /\
Zgcd [u ]_ s [v ]_ s = Zgcd [u3 ]_ s [v3 ]_ s /\
uivi_bounds u v u1 v1 u2 v2 u3 v3 s /\
ti_bounds u v t1 t2 t3 s /\ [t3 ]_ s <> 0) /\
hoare_m.eval_b (var_e t3 mode nat_e 2 =e nat_e 0) (s, h)}}
ifte var_e t1 mode nat_e 2 =e nat_e 0 &e var_e t2 mode nat_e 2 =e nat_e 0 thendo
t1 <- var_e t1 ./e nat_e 2;
t2 <- var_e t2 ./e nat_e 2;
t3 <- var_e t3 ./e nat_e 2
elsedo
(t1 <- (var_e t1 +e var_e v) ./e nat_e 2;
t2 <- (var_e t2 .-e var_e u) ./e nat_e 2;
t3 <- var_e t3 ./e nat_e 2)
{{ fun s _ => C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
CVectors u v u1 u2 u3 v1 v2 v3 t1 t2 t3 s /\
C4 u3 v3 t3 s /\
C5 u3 v3 s /\
Zgcd [u ]_ s [v ]_ s = Zgcd [u3 ]_ s [v3 ]_ s /\
uivi_bounds u v u1 v1 u2 v2 u3 v3 s /\
ti_bounds u v t1 t2 t3 s /\ [t3 ]_ s <> 0 }}.
Lemma begcd_while_halve_invariant_stren :
nodup(g, u, v, u1, u2, u3, v1, v2, v3, t1, t2, t3) -> 0 < vu -> 0 < vv ->
while.entails hoare_m.store hoare_m.heap
(fun s h => (C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
CVectors u v u1 u2 u3 v1 v2 v3 t1 t2 t3 s /\
C4 u3 v3 t3 s /\
C5 u3 v3 s /\
Zgcd [u ]_ s [v ]_ s = Zgcd [u3 ]_ s [v3 ]_ s /\
uivi_bounds u v u1 v1 u2 v2 u3 v3 s /\ ti_bounds u v t1 t2 t3 s) /\
hoare_m.eval_b (var_e t3 <>e nat_e 0) (s, h))
(fun s _ => C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
CVectors u v u1 u2 u3 v1 v2 v3 t1 t2 t3 s /\
C4 u3 v3 t3 s /\
C5 u3 v3 s /\
Zgcd [u ]_ s [v ]_ s = Zgcd [u3 ]_ s [v3 ]_ s /\
uivi_bounds u v u1 v1 u2 v2 u3 v3 s /\
ti_bounds u v t1 t2 t3 s /\ [t3 ]_ s <> 0).
Lemma begcd_while_halve_invariant_weak :
nodup(g, u, v, u1, u2, u3, v1, v2, v3, t1, t2, t3) -> 0 < vu -> 0 < vv ->
while.entails hoare_m.store hoare_m.heap
(fun s h => (C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
CVectors u v u1 u2 u3 v1 v2 v3 t1 t2 t3 s /\
C4 u3 v3 t3 s /\
C5 u3 v3 s /\
Zgcd [u ]_ s [v ]_ s = Zgcd [u3 ]_ s [v3 ]_ s /\
uivi_bounds u v u1 v1 u2 v2 u3 v3 s /\
ti_bounds u v t1 t2 t3 s /\ [t3 ]_ s <> 0) /\
~~ hoare_m.eval_b (var_e t3 mode nat_e 2 =e nat_e 0) (s, h))
(fun s _ => C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
CVectors u v u1 u2 u3 v1 v2 v3 t1 t2 t3 s /\
C4 u3 v3 t3 s /\
C5 u3 v3 s /\
Zgcd vu vv = [g ]_ s * Zgcd [u3 ]_ s [v3 ]_ s /\
uivi_bounds u v u1 v1 u2 v2 u3 v3 s /\
ti_bounds u v t1 t2 t3 s /\ Zodd [t3 ]_ s).
Lemma begcd_while_halve :
nodup(g, u, v, u1, u2, u3, v1, v2, v3, t1, t2, t3) -> 0 < vu -> 0 < vv ->
{{ fun s h => (C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
CVectors u v u1 u2 u3 v1 v2 v3 t1 t2 t3 s /\
C4 u3 v3 t3 s /\
C5 u3 v3 s /\
Zgcd [u ]_ s [v ]_ s = Zgcd [u3 ]_ s [v3 ]_ s /\
uivi_bounds u v u1 v1 u2 v2 u3 v3 s /\ ti_bounds u v t1 t2 t3 s) /\
hoare_m.eval_b (var_e t3 <>e nat_e 0) (s, h) }}
while.while (var_e t3 mode nat_e 2 =e nat_e 0) (TAOCP.halve u v t1 t2 t3)
{{ fun s h => C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
CVectors u v u1 u2 u3 v1 v2 v3 t1 t2 t3 s /\
C4 u3 v3 t3 s /\
C5 u3 v3 s /\
Zgcd vu vv = [g ]_ s * Zgcd [u3 ]_ s [v3 ]_ s /\
uivi_bounds u v u1 v1 u2 v2 u3 v3 s /\
ti_bounds u v t1 t2 t3 s /\ Zodd [t3 ]_ s}}.
Lemma begcd_reset :
nodup(g, u, v, u1, u2, u3, v1, v2, v3, t1, t2, t3) -> 0 < vu -> 0 < vv ->
{{fun s _ => C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
CVectors u v u1 u2 u3 v1 v2 v3 t1 t2 t3 s /\
C4 u3 v3 t3 s /\
C5 u3 v3 s /\
Zgcd vu vv = [g ]_ s * Zgcd [u3 ]_ s [v3 ]_ s /\
uivi_bounds u v u1 v1 u2 v2 u3 v3 s /\
ti_bounds u v t1 t2 t3 s /\ Zodd [t3 ]_ s}}
TAOCP.reset u v u1 u2 u3 v1 v2 v3 t1 t2 t3
{{fun s _ => C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
CVectors u v u1 u2 u3 v1 v2 v3 t1 t2 t3 s /\
(0 <= [t3 ]_ s ->
Zgcd vu vv = [g ]_ s * Zgcd [t3 ]_ s [v3 ]_ s /\
Zodd [u3 ]_ s /\ [u3 ]_ s = [t3 ]_ s) /\
([t3 ]_ s < 0 ->
Zgcd vu vv = [g ]_ s * Zgcd [u3 ]_ s [t3 ]_ s /\
Zodd [v3 ]_ s /\ [v3 ]_ s = - [t3 ]_ s) /\
uivi_bounds u v u1 v1 u2 v2 u3 v3 s /\
ti_bounds u v t1 t2 t3 s /\ C5 u3 v3 s}}.
Lemma begcd_subtract_part1 : nodup(g, u, v, u1, u2, u3, v1, v2, v3, t1, t2, t3) -> 0 < vu -> 0 < vv ->
{{fun s _ => C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
CVectors u v u1 u2 u3 v1 v2 v3 t1 t2 t3 s /\
(0 <= [t3 ]_ s ->
Zgcd vu vv = [g ]_ s * Zgcd [t3 ]_ s [v3 ]_ s /\
Zodd [u3 ]_ s /\ [u3 ]_ s = [t3 ]_ s) /\
([t3 ]_ s < 0 ->
Zgcd vu vv = [g ]_ s * Zgcd [u3 ]_ s [t3 ]_ s /\
Zodd [v3 ]_ s /\ [v3 ]_ s = - [t3 ]_ s) /\
uivi_bounds u v u1 v1 u2 v2 u3 v3 s /\
ti_bounds u v t1 t2 t3 s /\ C5 u3 v3 s}}
t1 <- var_e u1 .-e var_e v1;
t2 <- var_e u2 .-e var_e v2; t3 <- var_e u3 .-e var_e v3
{{fun s _ => C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
CVectors u v u1 u2 u3 v1 v2 v3 t1 t2 t3 s /\
[t3 ]_ s = [u3 ]_ s - [v3 ]_ s /\
Zgcd vu vv = [g ]_ s * Zgcd [t3 ]_ s [v3 ]_ s /\
[t1 ]_ s = [u1 ]_ s - [v1 ]_ s /\
uivi_bounds u v u1 v1 u2 v2 u3 v3 s /\
((0 < [t1]_s -> ti_bounds u v t1 t2 t3 s) /\
([t1]_s <= 0 ->
0 <= [t1 ]_ s + [v ]_ s <= [v ]_ s /\
- [u ]_ s <= [t2 ]_ s - [u ]_ s <= 0 /\
- [v ]_ s <= [t3 ]_ s <= [u ]_ s)) /\
(Zodd [v3 ]_ s \/ Zodd [u3 ]_ s) /\ C5 u3 v3 s}}.
Proof.
move=> Hset Hvu Hvv.
nodup(g, u, v, u1, u2, u3, v1, v2, v3, t1, t2, t3) -> 0 < vu -> 0 < vv ->
{{ fun s h => [u]_s = vu /\ [v]_s = vv }}
begcd g u v u1 u2 u3 v1 v2 v3 t1 t2 t3
{{ fun s h => vu * [u1]_s + vv * [u2]_s = [g]_s * [u3]_s /\
Zgcd vu vv = ([g]_s * [u3]_s)}}.
End taocp.
End TAOCP.
Definition uivi_bounds u v u1 v1 u2 v2 u3 v3 s :=
0 <= [u1 ]_ s <= [v ]_ s /\ 0 <= [v1 ]_ s <= [v ]_ s /\
- [u ]_ s <= [u2 ]_ s <= 0 /\ - [u ]_ s <= [v2 ]_ s <= 0 /\
0 < [u3 ]_ s <= [u ]_ s /\ 0 < [v3 ]_ s <= [v ]_ s.
Definition ti_bounds u v t1 t2 t3 s :=
0 <= [t1 ]_ s <= [v ]_ s /\
- [u ]_ s <= [t2 ]_ s <= 0 /\
- [v ]_ s <= [t3 ]_ s <= [u ]_ s.
Lemma init_bounds : forall u v u1 u2 u3 v1 v2 v3 t1 t2 t3 s,
0 < [u]_s -> 0 < [v]_s ->
uivi_init u v u1 u2 u3 v1 v2 v3 s ->
ti_init u v t1 t2 t3 s ->
uivi_bounds u v u1 v1 u2 v2 u3 v3 s /\ ti_bounds u v t1 t2 t3 s.
Module TAOCP2.
Section taocp2.
Variables g u v u1 u2 u3 v1 v2 v3 t1 t2 t3 : ssrnat.nat_eqType.
Variables vu vv : Z.
Lemma begcd_verif_with_bounds_init :
nodup(g, u, v, u1, u2, u3, v1, v2, v3, t1, t2, t3) -> 0 < vu -> 0 < vv ->
{{ fun s h => uv_init vu vv u v s }}
g <- nat_e 1;
prelude u v g;
TAOCP.init u v u1 u2 u3 v1 v2 v3 t1 t2 t3
{{fun s _ => C2 vu vv u v g s /\ C3 vu vv u v g s /\
uivi_init u v u1 u2 u3 v1 v2 v3 s /\
ti_init u v t1 t2 t3 s /\
uivi_bounds u v u1 v1 u2 v2 u3 v3 s /\
ti_bounds u v t1 t2 t3 s}}.
Lemma begcd_while_halve_invariant : nodup(g, u, v, u1, u2, u3, v1, v2, v3, t1, t2, t3) ->
0 < vu -> 0 < vv ->
{{ fun s h => (C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
CVectors u v u1 u2 u3 v1 v2 v3 t1 t2 t3 s /\
C4 u3 v3 t3 s /\
C5 u3 v3 s /\
Zgcd [u ]_ s [v ]_ s = Zgcd [u3 ]_ s [v3 ]_ s /\
uivi_bounds u v u1 v1 u2 v2 u3 v3 s /\
ti_bounds u v t1 t2 t3 s /\ [t3 ]_ s <> 0) /\
hoare_m.eval_b (var_e t3 mode nat_e 2 =e nat_e 0) (s, h)}}
ifte var_e t1 mode nat_e 2 =e nat_e 0 &e var_e t2 mode nat_e 2 =e nat_e 0 thendo
t1 <- var_e t1 ./e nat_e 2;
t2 <- var_e t2 ./e nat_e 2;
t3 <- var_e t3 ./e nat_e 2
elsedo
(t1 <- (var_e t1 +e var_e v) ./e nat_e 2;
t2 <- (var_e t2 .-e var_e u) ./e nat_e 2;
t3 <- var_e t3 ./e nat_e 2)
{{ fun s _ => C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
CVectors u v u1 u2 u3 v1 v2 v3 t1 t2 t3 s /\
C4 u3 v3 t3 s /\
C5 u3 v3 s /\
Zgcd [u ]_ s [v ]_ s = Zgcd [u3 ]_ s [v3 ]_ s /\
uivi_bounds u v u1 v1 u2 v2 u3 v3 s /\
ti_bounds u v t1 t2 t3 s /\ [t3 ]_ s <> 0 }}.
Lemma begcd_while_halve_invariant_stren :
nodup(g, u, v, u1, u2, u3, v1, v2, v3, t1, t2, t3) -> 0 < vu -> 0 < vv ->
while.entails hoare_m.store hoare_m.heap
(fun s h => (C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
CVectors u v u1 u2 u3 v1 v2 v3 t1 t2 t3 s /\
C4 u3 v3 t3 s /\
C5 u3 v3 s /\
Zgcd [u ]_ s [v ]_ s = Zgcd [u3 ]_ s [v3 ]_ s /\
uivi_bounds u v u1 v1 u2 v2 u3 v3 s /\ ti_bounds u v t1 t2 t3 s) /\
hoare_m.eval_b (var_e t3 <>e nat_e 0) (s, h))
(fun s _ => C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
CVectors u v u1 u2 u3 v1 v2 v3 t1 t2 t3 s /\
C4 u3 v3 t3 s /\
C5 u3 v3 s /\
Zgcd [u ]_ s [v ]_ s = Zgcd [u3 ]_ s [v3 ]_ s /\
uivi_bounds u v u1 v1 u2 v2 u3 v3 s /\
ti_bounds u v t1 t2 t3 s /\ [t3 ]_ s <> 0).
Lemma begcd_while_halve_invariant_weak :
nodup(g, u, v, u1, u2, u3, v1, v2, v3, t1, t2, t3) -> 0 < vu -> 0 < vv ->
while.entails hoare_m.store hoare_m.heap
(fun s h => (C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
CVectors u v u1 u2 u3 v1 v2 v3 t1 t2 t3 s /\
C4 u3 v3 t3 s /\
C5 u3 v3 s /\
Zgcd [u ]_ s [v ]_ s = Zgcd [u3 ]_ s [v3 ]_ s /\
uivi_bounds u v u1 v1 u2 v2 u3 v3 s /\
ti_bounds u v t1 t2 t3 s /\ [t3 ]_ s <> 0) /\
~~ hoare_m.eval_b (var_e t3 mode nat_e 2 =e nat_e 0) (s, h))
(fun s _ => C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
CVectors u v u1 u2 u3 v1 v2 v3 t1 t2 t3 s /\
C4 u3 v3 t3 s /\
C5 u3 v3 s /\
Zgcd vu vv = [g ]_ s * Zgcd [u3 ]_ s [v3 ]_ s /\
uivi_bounds u v u1 v1 u2 v2 u3 v3 s /\
ti_bounds u v t1 t2 t3 s /\ Zodd [t3 ]_ s).
Lemma begcd_while_halve :
nodup(g, u, v, u1, u2, u3, v1, v2, v3, t1, t2, t3) -> 0 < vu -> 0 < vv ->
{{ fun s h => (C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
CVectors u v u1 u2 u3 v1 v2 v3 t1 t2 t3 s /\
C4 u3 v3 t3 s /\
C5 u3 v3 s /\
Zgcd [u ]_ s [v ]_ s = Zgcd [u3 ]_ s [v3 ]_ s /\
uivi_bounds u v u1 v1 u2 v2 u3 v3 s /\ ti_bounds u v t1 t2 t3 s) /\
hoare_m.eval_b (var_e t3 <>e nat_e 0) (s, h) }}
while.while (var_e t3 mode nat_e 2 =e nat_e 0) (TAOCP.halve u v t1 t2 t3)
{{ fun s h => C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
CVectors u v u1 u2 u3 v1 v2 v3 t1 t2 t3 s /\
C4 u3 v3 t3 s /\
C5 u3 v3 s /\
Zgcd vu vv = [g ]_ s * Zgcd [u3 ]_ s [v3 ]_ s /\
uivi_bounds u v u1 v1 u2 v2 u3 v3 s /\
ti_bounds u v t1 t2 t3 s /\ Zodd [t3 ]_ s}}.
Lemma begcd_reset :
nodup(g, u, v, u1, u2, u3, v1, v2, v3, t1, t2, t3) -> 0 < vu -> 0 < vv ->
{{fun s _ => C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
CVectors u v u1 u2 u3 v1 v2 v3 t1 t2 t3 s /\
C4 u3 v3 t3 s /\
C5 u3 v3 s /\
Zgcd vu vv = [g ]_ s * Zgcd [u3 ]_ s [v3 ]_ s /\
uivi_bounds u v u1 v1 u2 v2 u3 v3 s /\
ti_bounds u v t1 t2 t3 s /\ Zodd [t3 ]_ s}}
TAOCP.reset u v u1 u2 u3 v1 v2 v3 t1 t2 t3
{{fun s _ => C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
CVectors u v u1 u2 u3 v1 v2 v3 t1 t2 t3 s /\
(0 <= [t3 ]_ s ->
Zgcd vu vv = [g ]_ s * Zgcd [t3 ]_ s [v3 ]_ s /\
Zodd [u3 ]_ s /\ [u3 ]_ s = [t3 ]_ s) /\
([t3 ]_ s < 0 ->
Zgcd vu vv = [g ]_ s * Zgcd [u3 ]_ s [t3 ]_ s /\
Zodd [v3 ]_ s /\ [v3 ]_ s = - [t3 ]_ s) /\
uivi_bounds u v u1 v1 u2 v2 u3 v3 s /\
ti_bounds u v t1 t2 t3 s /\ C5 u3 v3 s}}.
Lemma begcd_subtract_part1 : nodup(g, u, v, u1, u2, u3, v1, v2, v3, t1, t2, t3) -> 0 < vu -> 0 < vv ->
{{fun s _ => C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
CVectors u v u1 u2 u3 v1 v2 v3 t1 t2 t3 s /\
(0 <= [t3 ]_ s ->
Zgcd vu vv = [g ]_ s * Zgcd [t3 ]_ s [v3 ]_ s /\
Zodd [u3 ]_ s /\ [u3 ]_ s = [t3 ]_ s) /\
([t3 ]_ s < 0 ->
Zgcd vu vv = [g ]_ s * Zgcd [u3 ]_ s [t3 ]_ s /\
Zodd [v3 ]_ s /\ [v3 ]_ s = - [t3 ]_ s) /\
uivi_bounds u v u1 v1 u2 v2 u3 v3 s /\
ti_bounds u v t1 t2 t3 s /\ C5 u3 v3 s}}
t1 <- var_e u1 .-e var_e v1;
t2 <- var_e u2 .-e var_e v2; t3 <- var_e u3 .-e var_e v3
{{fun s _ => C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
CVectors u v u1 u2 u3 v1 v2 v3 t1 t2 t3 s /\
[t3 ]_ s = [u3 ]_ s - [v3 ]_ s /\
Zgcd vu vv = [g ]_ s * Zgcd [t3 ]_ s [v3 ]_ s /\
[t1 ]_ s = [u1 ]_ s - [v1 ]_ s /\
uivi_bounds u v u1 v1 u2 v2 u3 v3 s /\
((0 < [t1]_s -> ti_bounds u v t1 t2 t3 s) /\
([t1]_s <= 0 ->
0 <= [t1 ]_ s + [v ]_ s <= [v ]_ s /\
- [u ]_ s <= [t2 ]_ s - [u ]_ s <= 0 /\
- [v ]_ s <= [t3 ]_ s <= [u ]_ s)) /\
(Zodd [v3 ]_ s \/ Zodd [u3 ]_ s) /\ C5 u3 v3 s}}.
Proof.
move=> Hset Hvu Hvv.
t1 <- var_e u1 .-e var_e v1;
apply hoare_assign with (fun s _ => C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
([u ]_ s * [t1 ]_ s + [v ]_ s * ([u2]_s - [v2 ]_ s) = [u3 ]_ s - [v3]_s /\
[u ]_ s * [u1 ]_ s + [v ]_ s * [u2 ]_ s = [u3 ]_ s /\
[u ]_ s * [v1 ]_ s + [v ]_ s * [v2 ]_ s = [v3 ]_ s) /\
(0 <= [t3 ]_ s -> Zgcd vu vv = [g ]_ s * Zgcd [t3 ]_ s [v3 ]_ s/\ Zodd [u3 ]_ s
/\ [u3 ]_ s = [t3 ]_ s) /\
([t3 ]_ s < 0 -> Zgcd vu vv = [g ]_ s * Zgcd [u3 ]_ s [t3 ]_ s /\ Zodd [v3 ]_ s /\
[v3 ]_ s = - [t3 ]_ s) /\
[t1]_s = [u1]_s - [v1]_s /\
uivi_bounds u v u1 v1 u2 v2 u3 v3 s /\
(([v1]_s < [u1]_s -> ti_bounds u v t1 t2 t3 s) /\
([u1]_s <= [v1]_s -> 0 <= [t1 ]_ s + [v]_s <= [v ]_ s /\
- [u ]_ s <= [t2 ]_ s <= 0 /\
- [v ]_ s <= [t3 ]_ s <= [u ]_ s)) /\
C5 u3 v3 s).
move=> s h.
case => [[Hu [Hv [Hg [u_g v_g]]]] [H5 [[Hti [Hui Hvi]] [H9 [H10 [Hinvar1 [Hinvar2 [Hu3 Hv3]]]]]]]].
rewrite /wp_assign /C2.
repeat Store_upd.
repeat (split; first by done).
split.
split; [rewrite /= /ZIT.t_minus -Hui -Hvi; ring | done].
repeat (split; first by done).
split.
rewrite /uivi_bounds; by repeat Store_upd.
split.
split=> u1_v1.
rewrite /ti_bounds in Hinvar2 *.
repeat Store_upd.
split; last by tauto.
rewrite /= /ZIT.t_minus.
rewrite /uivi_bounds in Hinvar1.
by myomega.
rewrite /ti_bounds in Hinvar2 *.
repeat Store_upd.
split; last by tauto.
rewrite /= /ZIT.t_minus.
rewrite /uivi_bounds in Hinvar1.
by myomega.
rewrite /C5; by repeat Store_upd.
t2 <- svar u2 .-e svar v2;
apply hoare_assign with (fun s _ => C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
([u ]_ s * [t1 ]_ s + [v ]_ s * [t2]_s = [u3 ]_ s - [v3]_s/\
[u ]_ s * [u1 ]_ s + [v ]_ s * [u2 ]_ s = [u3 ]_ s /\
[u ]_ s * [v1 ]_ s + [v ]_ s * [v2 ]_ s = [v3 ]_ s) /\
(0 <= [t3 ]_ s ->
Zgcd vu vv = [g ]_ s * Zgcd [t3 ]_ s [v3 ]_ s/\ Zodd [u3 ]_ s /\
[u3 ]_ s = [t3 ]_ s) /\
([t3 ]_ s < 0 ->
Zgcd vu vv = [g ]_ s * Zgcd [u3 ]_ s [t3 ]_ s/\ Zodd [v3 ]_ s /\
[v3 ]_ s = - [t3 ]_ s) /\
[t1]_s = [u1]_s - [v1]_s /\
uivi_bounds u v u1 v1 u2 v2 u3 v3 s /\
(([v1]_s < [u1]_s -> ti_bounds u v t1 t2 t3 s) /\
([u1]_s <= [v1]_s -> 0 <= [t1 ]_ s + [v]_s <= [v ]_ s /\
- [u ]_ s <= [t2 ]_ s - [u]_s <= 0 /\
- [v ]_ s <= [t3 ]_ s <= [u ]_ s)) /\
C5 u3 v3 s).
move=> s h.
case => [[Hu [Hv [Hg [u_g v_g]]]] [H5 [[Hti [Hui Hvi]] [H9 [H10 [tuv1 [Hinvar1 [Hinvar2 [Hu3 Hv3]]]]]]]]].
rewrite /wp_assign /C2.
repeat Store_upd.
repeat (split; first by done).
split.
rewrite /uivi_bounds; by repeat Store_upd.
split.
split=> u1_v1.
rewrite /ti_bounds in Hinvar2 *.
repeat Store_upd.
split; first by tauto.
split; last by tauto.
rewrite /= /ZIT.t_minus.
move: {Hinvar2}(proj1 Hinvar2 u1_v1) => Hinvar2.
rewrite /uivi_bounds in Hinvar1.
split.
by myomega.
have Htmp : [v3]_s + [v]_s * ([u2]_s - [v2]_s) <= 0.
have -> : [v3]_s + [v]_s * ([u2]_s - [v2]_s) = [u3 ]_ s - [u ]_ s * ([u1 ]_ s - [v1 ]_ s).
rewrite !Zmult_minus_distr_l in Hti *.
by myomega.
have Htmp : [u1 ]_ s - [v1 ]_ s > 0.
by myomega.
apply Zle_trans with ([u ]_ s - [u ]_ s * ([u1 ]_ s - [v1 ]_ s)).
apply Zminus_le_compat.
by myomega.
have Htmp2 : [u ]_ s <= [u ]_ s * ([u1 ]_ s - [v1 ]_ s).
apply Zle_scale.
by myomega.
by apply Zgt_lt.
by myomega.
apply Zle_plus_0_inv in Htmp; last by myomega.
apply Zle_mult_0_inv in Htmp; last by myomega.
done.
rewrite /ti_bounds in Hinvar2 *.
repeat Store_upd.
split; first by tauto.
split; last by tauto.
rewrite /= /ZIT.t_minus.
rewrite /uivi_bounds in Hinvar1.
split; last by myomega.
move: {Hinvar2}(proj2 Hinvar2 u1_v1) => Hinvar2.
suff : 0 <= [u2 ]_ s - [v2 ]_ s by move=> ?; by myomega.
have Htmp : - [v]_s * ([u2]_s - [v2]_s) - [v3]_s < 0.
have -> : - [v ]_ s * ([u2 ]_ s - [v2 ]_ s) - [v3 ]_ s =
[u]_s * ([u1]_s - [v1]_s) - [u3]_s.
have Htmp : [u3 ]_ s = [u ]_ s * [t1 ]_ s + [v ]_ s * ([u2 ]_ s - [v2 ]_ s) + [v3 ]_ s.
by myomega.
rewrite Htmp tuv1; ring.
have Htmp : [u1 ]_ s - [v1 ]_ s <= 0 by myomega.
have {Htmp}Htmp : [u ]_ s * ([u1 ]_ s - [v1 ]_ s) <= 0.
apply Zmult_sign => //.
by myomega.
by myomega.
have {Htmp}Htmp : - [v ]_ s * ([u2 ]_ s - [v2 ]_ s) < [v3 ]_ s.
by myomega.
apply Znot_gt_le => abs.
have {Htmp}Htmp : - [v ]_ s * ([u2 ]_ s - [v2 ]_ s) < [v]_s.
by myomega.
rewrite Zmult_opp_comm in Htmp.
apply Zmult_lt_compat3 in Htmp; last 2 first.
by myomega.
by myomega.
by apply Zlt_irrefl in Htmp.
by myomega.
rewrite /C5; by repeat Store_upd.
t3 <- var_e u3 .-e var_e v3
apply hoare_assign'.
move=> s h.
case => [[Hu [Hv [Hg [u_g v_g]]]] [H5 [[Hti [Hui Hvi]] [H9 [H10 [tuv1 [Hinvar1 [Hinvar2 [Hu3 Hv3]]]]]]]]].
rewrite /wp_assign /C2 /CVectors.
repeat Store_upd.
repeat (split; first by tauto).
split.
case: (Z_lt_le_dec [t3]_s 0).
- move/H10 => H10'.
move: (Zgcd_for_euclid [u3]_s [v3]_s (-1)).
rewrite Zopp_eq_mult_neg_1_L Zplus_Zopp => ->.
case: H10' => H10' [H10'' H10'''].
rewrite H10''' Zgcd_opp; tauto.
- move/H9.
case => H9' [H9'' H9'''].
rewrite /= H9'''.
move: (Zgcd_for_euclid [t3]_s [v3]_s (-1)).
by rewrite Zopp_eq_mult_neg_1_L Zplus_Zopp => ->.
split; first by done.
split.
rewrite /uivi_bounds; by repeat Store_upd.
split.
split=> v1_u1.
rewrite /ti_bounds in Hinvar2 *.
repeat Store_upd.
repeat (split; first by tauto).
rewrite /= /ZIT.t_minus.
rewrite /uivi_bounds in Hinvar1.
by myomega.
rewrite /ti_bounds in Hinvar2 *.
repeat Store_upd.
repeat (split; first by tauto).
rewrite /= /ZIT.t_minus.
rewrite /uivi_bounds in Hinvar1.
by myomega.
split; last by rewrite /C5; repeat Store_upd.
case: (Z_lt_le_dec [t3]_s 0).
- move/H10; tauto.
- move/H9; tauto.
Qed.
Lemma begcd_subtract :
nodup(g, u, v, u1, u2, u3, v1, v2, v3, t1, t2, t3) -> 0 < vu -> 0 < vv ->
{{ fun s _ => C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
CVectors u v u1 u2 u3 v1 v2 v3 t1 t2 t3 s /\
(0 <= [t3 ]_ s ->
Zgcd vu vv = [g ]_ s * Zgcd [t3 ]_ s [v3 ]_ s /\
Zodd [u3 ]_ s /\ [u3 ]_ s = [t3 ]_ s) /\
([t3 ]_ s < 0 ->
Zgcd vu vv = [g ]_ s * Zgcd [u3 ]_ s [t3 ]_ s /\
Zodd [v3 ]_ s /\ [v3 ]_ s = - [t3 ]_ s) /\
uivi_bounds u v u1 v1 u2 v2 u3 v3 s /\
ti_bounds u v t1 t2 t3 s /\ C5 u3 v3 s}}
TAOCP.subtract u v u1 u2 u3 v1 v2 v3 t1 t2 t3
{{ fun s _ => C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
CVectors u v u1 u2 u3 v1 v2 v3 t1 t2 t3 s /\
C4 u3 v3 t3 s /\
C5 u3 v3 s /\
Zgcd [u ]_ s [v ]_ s = Zgcd [u3 ]_ s [v3 ]_ s /\
uivi_bounds u v u1 v1 u2 v2 u3 v3 s /\ ti_bounds u v t1 t2 t3 s}}.
Lemma begcd_verif_intermediate_with_bounds_invariant :
nodup(g, u, v, u1, u2, u3, v1, v2, v3, t1, t2, t3) -> 0 < vu -> 0 < vv ->
{{ fun s h => (C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
CVectors u v u1 u2 u3 v1 v2 v3 t1 t2 t3 s /\
C4 u3 v3 t3 s /\
C5 u3 v3 s /\
Zgcd [u ]_ s [v ]_ s = Zgcd [u3 ]_ s [v3 ]_ s /\
uivi_bounds u v u1 v1 u2 v2 u3 v3 s /\ ti_bounds u v t1 t2 t3 s) /\
hoare_m.eval_b (var_e t3 <>e nat_e 0) (s, h)}}
while.while (var_e t3 mode nat_e 2 =e nat_e 0) (TAOCP.halve u v t1 t2 t3);
TAOCP.reset u v u1 u2 u3 v1 v2 v3 t1 t2 t3;
TAOCP.subtract u v u1 u2 u3 v1 v2 v3 t1 t2 t3
{{ fun s h => C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
CVectors u v u1 u2 u3 v1 v2 v3 t1 t2 t3 s /\
C4 u3 v3 t3 s /\
C5 u3 v3 s /\
Zgcd [u ]_ s [v ]_ s = Zgcd [u3 ]_ s [v3 ]_ s /\
uivi_bounds u v u1 v1 u2 v2 u3 v3 s /\ ti_bounds u v t1 t2 t3 s }}.
Lemma begcd_verif_intermediate_with_bounds_invariant_stren :
nodup(g, u, v, u1, u2, u3, v1, v2, v3, t1, t2, t3) -> 0 < vu -> 0 < vv ->
while.entails hoare_m.store hoare_m.heap
(fun s _ =>
C2 vu vv u v g s /\
C3 vu vv u v g s /\
uivi_init u v u1 u2 u3 v1 v2 v3 s /\
ti_init u v t1 t2 t3 s /\
uivi_bounds u v u1 v1 u2 v2 u3 v3 s /\ ti_bounds u v t1 t2 t3 s)
(fun s _ =>
C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
CVectors u v u1 u2 u3 v1 v2 v3 t1 t2 t3 s /\
C4 u3 v3 t3 s /\
C5 u3 v3 s /\
Zgcd [u ]_ s [v ]_ s = Zgcd [u3 ]_ s [v3 ]_ s /\
uivi_bounds u v u1 v1 u2 v2 u3 v3 s /\ ti_bounds u v t1 t2 t3 s).
Lemma begcd_verif_intermediate_with_bounds_invariant_weak :
nodup(g, u, v, u1, u2, u3, v1, v2, v3, t1, t2, t3) -> 0 < vu -> 0 < vv ->
while.entails hoare_m.store hoare_m.heap
(fun s h => (C2 vu vv u v g s /\
(Zodd [u ]_ s \/ Zodd [v ]_ s) /\
CVectors u v u1 u2 u3 v1 v2 v3 t1 t2 t3 s /\
C4 u3 v3 t3 s /\
C5 u3 v3 s /\
Zgcd [u ]_ s [v ]_ s = Zgcd [u3 ]_ s [v3 ]_ s /\
uivi_bounds u v u1 v1 u2 v2 u3 v3 s /\ ti_bounds u v t1 t2 t3 s) /\
~~ hoare_m.eval_b (var_e t3 <>e nat_e 0) (s, h))
(fun s _ =>
vu * [u1 ]_ s + vv * [u2 ]_ s = [g ]_ s * [u3 ]_ s /\
Zgcd vu vv = [g ]_ s * [u3 ]_ s /\
uivi_bounds u v u1 v1 u2 v2 u3 v3 s /\ ti_bounds u v t1 t2 t3 s).
Lemma begcd_verif_intermediate_with_bounds :
nodup(g, u, v, u1, u2, u3, v1, v2, v3, t1, t2, t3) -> 0 < vu -> 0 < vv ->
({{fun s _ => C2 vu vv u v g s /\ C3 vu vv u v g s /\
uivi_init u v u1 u2 u3 v1 v2 v3 s /\
ti_init u v t1 t2 t3 s /\
uivi_bounds u v u1 v1 u2 v2 u3 v3 s /\
ti_bounds u v t1 t2 t3 s }}
while.while (var_e t3 <>e nat_e 0)
(while.while (var_e t3 mode nat_e 2 =e nat_e 0) (TAOCP.halve u v t1 t2 t3);
TAOCP.reset u v u1 u2 u3 v1 v2 v3 t1 t2 t3;
TAOCP.subtract u v u1 u2 u3 v1 v2 v3 t1 t2 t3)
{{fun s _ =>
vu * [u1 ]_ s + vv * [u2 ]_ s = [g ]_ s * [u3 ]_ s /\
Zgcd vu vv = [g ]_ s * [u3 ]_ s /\
uivi_bounds u v u1 v1 u2 v2 u3 v3 s /\
ti_bounds u v t1 t2 t3 s }})%seplog_hoare.
Lemma begcd_verif_with_bounds :
nodup(g, u, v, u1, u2, u3, v1, v2, v3, t1, t2, t3) -> 0 < vu -> 0 < vv ->
({{ fun s h => uv_init vu vv u v s }}
TAOCP.begcd g u v u1 u2 u3 v1 v2 v3 t1 t2 t3
{{ fun s h =>
vu * [u1]_s + vv * [u2]_s = [g]_s * [u3]_s /\
Zgcd vu vv = ([g]_s * [u3]_s) /\
uivi_bounds u v u1 v1 u2 v2 u3 v3 s /\
ti_bounds u v t1 t2 t3 s
}})%seplog_hoare.
End taocp2.
End TAOCP2.
End EGCD.