Section Sk.
Hypothesis k:nat.
Hypothesis Base_k: k<>0.
Inductive Base: (nat*(list nat))->Prop :=
| Base_intro s
(Base_a0':fst s = S O)
(Base_a:forall i, ai i s = if Nat.ltb i (k*2) then 2^(k*2-i) else O)
(Base_l:to_l s = k*2+1):
Base s.
Ltac pose_Heb Heb Hl e2 Heb2 rw :=
epose proof (embanked_batch_precond'' Heb Hl _ _) as tmp;
edestruct tmp as [e2 Heb2]; clear tmp;
rewrite rw in Heb2;
cbn in Heb2.
Ltac ex_Heb e Heb :=
exists e; eexists;
split;
[ apply Heb | idtac ].
Ltac pose_eb_len Heb Hl0 Hl :=
pose proof (embanked_batch_len Heb) as Hl;
rewrite Hl0 in Hl; symmetry in Hl.
Ltac pose_eb_a0_a1 Heb Ha0 Ha1 rw :=
destruct (embanked_batch_a0_a1 Heb) as [Ha0 Ha1];
rewrite rw in Ha0,Ha1;
cbn in Ha0,Ha1.
Ltac simpl_Add2s :=
unfold ai';
cbn[negb]; cbn[Bool.eqb];
repeat rewrite Bool.andb_true_r;
repeat rewrite Bool.andb_false_r;
repeat (rewrite Nat_leb_S);
repeat (rewrite Nat_leb_S_l; [idtac|congruence]).
Ltac inv_eb_Add2s Heb := pose proof (embanked_batch_Add2s Heb) as tmp; inverts tmp.
Inductive ctzS_chain:nat->Prop :=
| ctzS_chain_O:
ctzS_chain O
| ctzS_chain_S2 n:
ctzS_chain n ->
ctzS n mod 2 = 0 ->
ctzS (n+1) mod 2 = 1 ->
ctzS_chain (n+2)
| ctzS_chain_S4 n:
ctzS_chain n ->
ctzS n mod 2 = 0 ->
ctzS (n+1) mod 2 = 0 ->
ctzS (n+2) mod 2 = 0 ->
ctzS (n+3) mod 2 = 1 ->
ctzS_chain (n+4)
.
Inductive N'steps: (nat*(list nat))->nat->nat->(nat*(list nat))->nat->nat->Prop :=
| N'steps_O i e ne h1 h2:
embanked_batch i e ne h1 h2 ->
N'steps ne h1 h2 ne h1 h2
| N'steps_S i e ne nne h1 h2 h1a h2a h1b h2b:
N'steps e h1 h2 ne h1a h2a ->
embanked_batch i ne nne h1b h2b ->
N'steps e h1 h2 nne h1b h2b
.
Hypothesis Sk:nat*(list nat).
Hypothesis Base_Sk: Base Sk.
Inductive ZIHIO: (nat*(list nat))->(nat*(list nat))->Prop :=
| ZIHIO_intro n_1 n_2 s1 s2 s3 s4 s5 s6
(Z12':Zero s1 s2)
(I23':Increments n_1 s2 s3)
(H34':Halve s3 s4)
(I45':Increments (S n_2) s4 s5)
(O56':Overflow s5 s6)
(Hwf6':WF1 s6)
(Hs6':to_s s6 = false)
(Hn6':to_n s6 = 0)
(Hl6':to_l s6 = k * 2 + 3)
(Ha60':fst s6 = 1)
(Ha61':ai 0 s6 = 2 ^ (k * 2 + 2) - 4)
(Ha6':forall i : nat, 2 <= i -> i <= k * 2 + 2 -> ai' i s6 = 2 ^ (k * 2 + 3 - i) - i mod 2 * 2)
(Ha6_last:ai' (k*2+3) s6 = 0):
ZIHIO s1 s6.
Ltac simpl_divpow2r_pow2sub1 H :=
repeat (
(rewrite divpow2r_pow2sub1 in H; [idtac|lia;fail])||
(rewrite divpow2r_pow2sub1_small in H; [idtac|lia;fail])).
Ltac simpl_a7_expr a7_expr :=
simpl_divpow2r_pow2sub1 a7_expr;
simpl_add_sub_in a7_expr;
repeat rewrite pow_add_r in a7_expr;
change (2^3) with 8 in a7_expr;
change (2^2) with 4 in a7_expr;
replace (2^(k*2)*4-2) with ((2^(k*2)*2-1)*2) in a7_expr by lia;
replace (2^(k*2)*8-4) with ((2^(k*2)*2-1)*2*2) in a7_expr by lia;
(repeat rewrite <-divpow2r_div2 in a7_expr);
(repeat (rewrite div_mul in a7_expr; [idtac|congruence]));
replace (2^(k*2)*2) with (2^(k*2+1)) in a7_expr by (rewrite pow_add_r; cbn; reflexivity);
simpl_divpow2r_pow2sub1 a7_expr;
simpl_add_sub_in a7_expr.
End Sk.

Lemma Increments_precond_toConfig {n s1 s2}:
Increments (S n) s1 s2 ->
exists c1, toConfig s1 c1.