Opaque bs2nat.
Opaque Cond.
Definition False_e n :=
Comp n (Succ false) [Zero_e n].
Opaque Zero_e One_e False_e Rev_e RemoveLSZ_e.
Definition Normalize_e : Cobham :=
Comp 1 Rev_e [Comp 1 RemoveLSZ_e [Rev_e]].
Opaque Normalize_e.
(** Def 1 of (Rose) *)
Definition Succ_e : Cobham :=
Rec
(Comp 0 (Succ true) [Zero])
(Comp 2 (Succ true) [Proj 2 0])
(Comp 2 (Succ false) [Proj 2 1])
(Comp 1 (Succ true) [Proj 1 0]).
Opaque Succ_e.
(** Def 2 of (Rose) *)
Definition Pred'_e : Cobham :=
Rec
Zero
(Comp 2 (Succ true) [Proj 2 1])
(Comp 2 (Succ false) [Proj 2 0])
(Proj 1 0).
Opaque Pred'_e.
Definition Pred_e : Cobham :=
Comp 1 Pred'_e [Normalize_e].
Opaque Pred_e.
(** Def 3 of (Rose) *)
Definition OneMinus'_e : Cobham :=
Rec2
(One_e 0)
(Zero_e 2)
(One_e 1).
Opaque OneMinus'_e.
Definition OneMinus_e : Cobham :=
Comp 1 OneMinus'_e [Normalize_e].
Opaque OneMinus_e.
(** Def 4 of (Rose) *)
Definition Div2_e : Cobham :=
Rec2
Zero
(Proj 2 0)
(Proj 1 0).
Opaque Div2_e.
(** Def 5 of (Rose) *)
Definition Mod2_e : Cobham :=
Rec
Zero
(False_e 2)
(One_e 2)
(One_e 1).
Opaque Mod2_e.
(** Def 6 of (Rose) *)
Definition Length_e : Cobham :=
Rec2
Zero
(Comp 2 Succ_e [Proj 2 1])
(Proj 1 0).
Opaque Length_e.
(** Def 7 of (Rose) *)
Definition MultOneMinus'_e : Cobham :=
Comp 2 Cond [
Proj 2 1;
Proj 2 0;
Zero_e 2;
Zero_e 2
].
Opaque MultOneMinus'_e.
Definition MultOneMinus_e : Cobham :=
Comp 2 MultOneMinus'_e [Proj 2 0; Comp 2 Normalize_e [Proj 2 1]].
Opaque MultOneMinus_e.
(** Def 8 of (Rose) *)
Definition PlusOneMinus'_e : Cobham :=
Comp 2 Cond [
Proj 2 1;
Comp 2 Succ_e [Proj 2 0];
Proj 2 0;
Proj 2 0
].
Opaque PlusOneMinus'_e.
Definition PlusOneMinus_e : Cobham :=
Comp 2 PlusOneMinus'_e [Proj 2 0; Comp 2 Normalize_e [Proj 2 1] ].
Opaque PlusOneMinus_e.
(** Def 9 of (Rose) *)
Definition OneMinusMultPlus'_e : Cobham :=
Rec
(Proj 1 0)
(Comp 3 (Succ false) [Proj 3 0])
(Comp 3 (Succ true) [Proj 3 0])
(Comp 2 Smash [Comp 2 Succ_e [Proj 2 1]; Comp 2 (Succ true) [Proj 2 0]]).
Opaque OneMinusMultPlus'_e.
Definition OneMinusMultPlus_e : Cobham :=
Comp 2 OneMinusMultPlus'_e [Comp 2 Normalize_e [Proj 2 0]; Proj 2 1].
Opaque OneMinusMultPlus_e.
(** Def 10 of (Rose) *)
Definition PlusMod2_e : Cobham :=
Comp 2 Cond [
Proj 2 1;
Proj 2 0;
Comp 2 Succ_e [Proj 2 0];
Proj 2 0
].
Opaque PlusMod2_e.
(** Def 11 of (Rose) *)
Definition PlusOneMinusMod2_e : Cobham :=
Comp 3 Cond [
Proj 3 2;
Proj 3 0;
Comp 3 PlusOneMinus_e [Proj 3 0; Proj 3 1];
Proj 3 0
].
Opaque PlusOneMinusMod2_e.
(** Def 13 of (Rose) *)
Definition MultTwoPowerLength'_e : Cobham :=
Rec2
(Proj 1 0)
(Comp 3 (Succ false) [Proj 3 1])
(Comp 2 Smash [Comp 2 (Succ true) [Proj 2 0]; Comp 2 (Succ true) [Proj 2 1] ] ).
(* FIXME: According to Rose (Def 13), 'plus 1' in arguments of Smash are not necessary *)
Opaque MultTwoPowerLength'_e.
Definition MultTwoPowerLength_e : Cobham :=
Comp 2 MultTwoPowerLength'_e [Proj 2 1; Proj 2 0].

Lemma MultTwoPowerLength_correct : forall l,
bs2nat (Sem MultTwoPowerLength_e l) =
bs2nat (hd nil l) * power 2 (length (hd nil (tl l))).