Module Import Prog := Syn.MkProg (EMProg).
Definition rank : function -> nat := ltac:(autorank function_beq ranklist).
(* QI *)
Definition cs (c : constructor) := 1%nat. (* same for all *)
(* Specifications *)
(* Conversion functions from/to term values/Coq types. *)
Fixpoint Pos_of_value (v : value) : positive := match v with
| Syntax.c_capply XHC [] => xH
| Syntax.c_capply XOC [v] => xO (Pos_of_value v)
| Syntax.c_capply XIC [v] => xI (Pos_of_value v)
| _ => xH
end.
Fixpoint N_of_value (v : value) : N := match v with
| Syntax.c_capply N0C [] => 0
| Syntax.c_capply NPosC [v] => N.pos (Pos_of_value v)
| _ => 0
end.
Fixpoint value_of_pos (n : positive) : value := match n with
| xH => c_capply XHC []
| xO a => c_capply XOC [value_of_pos a]
| xI a => c_capply XIC [value_of_pos a]
end.
Fixpoint pos_of_value p := match p with
| Syntax.c_capply XHC [] => xH
| Syntax.c_capply XOC [a] => xO (pos_of_value a)
| Syntax.c_capply XIC [a] => xI (pos_of_value a)
| _ => xH
end.
Definition value_of_N (n : N) : Syntax.value EMSyntax.constructor (* value *) :=
match n with
| 0%N => c_capply N0C []
| Npos a => c_capply NposC [value_of_pos a]
end.
Definition value_of_mask (m : Pos.mask) := match m with
| IsPos a => c_capply IsPosC [value_of_pos a]
| IsNeg => c_capply IsNegC []
| IsNul => c_capply IsNulC []
end.
Definition mask_of_value m := match m with
| Syntax.c_capply IsPosC [a] => IsPos (pos_of_value a)
| Syntax.c_capply IsNegC [] => IsNeg
| Syntax.c_capply IsNulC [] => IsNul
| _ => IsNul
end.
Definition value_of_comp c := match c with
| Eq => c_capply EqC []
| Lt => c_capply LtC []
| Gt => c_capply GtC []
end.
Definition comp_of_value v := match v with
| Syntax.c_capply EqC [] => Eq
| Syntax.c_capply LtC [] => Lt
| Syntax.c_capply GtC [] => Gt
| _ => Eq
end.
Definition value_of_bool b := match b with
| true => c_capply TrueC []
| false => c_capply FalseC []
end.
Definition bool_of_value v := match v with
| Syntax.c_capply TrueC [] => true
| Syntax.c_capply FalseC [] => false
| _ => false
end.
Definition pairN : Type := (N * N).
Definition value_of_pair (x : pairN) := c_capply PairC [value_of_N (fst x); value_of_N (snd x)].
Coercion value_of_N : N >-> Syntax.value.
Coercion value_of_pair : pairN >-> value.
Open Scope N_scope.
Definition sub_mask_correct' : ltac:(auto_for_auto sub_mask_correct) := sub_mask_correct.
Hint Resolve sub_mask_correct' : eval.
Definition compare_cont_correct' : ltac:(auto_for_auto compare_cont_correct) := compare_cont_correct.
Hint Resolve compare_cont_correct' : eval.
Definition compare_correct' : ltac:(auto_for_auto compare_correct) := compare_correct.
Hint Resolve compare_correct' : eval.
Definition sub_correct' : ltac:(auto_for_auto sub_correct) := sub_correct.
Hint Resolve sub_correct' : eval.
Definition mod_aux_correct' : ltac:(auto_for_auto mod_aux_correct) := mod_aux_correct.
Hint Resolve mod_aux_correct' : eval.
Definition mod_correct' : ltac:(auto_for_auto mod_correct) := mod_correct.
Hint Resolve mod_correct' : eval.
Inductive larger_bound : positive -> positive -> Type :=
| larger_1  : forall b, larger_bound xH b
| larger_xI : forall x b, larger_bound x b -> larger_bound (xI x) (xO b)
| larger_xO : forall x b, larger_bound x b -> larger_bound (xO x) (xO b).
Definition N_larger_bound n b := match n with
| 0 => larger_bound xH b
| Npos p0 => larger_bound p0 b
end.
Fixpoint lower_bound p0 := match p0 with
| xH => xH
| xO p0 => xO (lower_bound p0)
| xI p0 => xO (lower_bound p0)
end.
Hint Resolve N_larger_bound_mod : eval.

Lemma mul_mod_correct n n' m b: forall tn tn' tm tb,
m <> 0 ->
N_larger_bound n b ->
evaluates tn (value_of_N n) ->
evaluates tn' (value_of_N n') ->
evaluates tm (value_of_N m) ->
evaluates tb (value_of_pos b) ->
evaluates (mul_modF (: tn, tn', tm, tb:))
((n * n') mod m).