Section OrdinalSub.
Variable n : nat.
Inductive ordinal : predArgType := Ordinal m of m < n.
Coercion nat_of_ord i := let: Ordinal m _ := i in m.
Canonical ordinal_subType := [subType for nat_of_ord].
Definition ordinal_eqMixin := Eval hnf in [eqMixin of ordinal by <:].
Canonical ordinal_eqType := Eval hnf in EqType ordinal ordinal_eqMixin.
Definition ordinal_choiceMixin := [choiceMixin of ordinal by <:].
Canonical ordinal_choiceType :=
Eval hnf in ChoiceType ordinal ordinal_choiceMixin.
Definition ordinal_countMixin := [countMixin of ordinal by <:].
Canonical ordinal_countType := Eval hnf in CountType ordinal ordinal_countMixin.
Canonical ordinal_subCountType := [subCountType of ordinal].
Definition ord_enum : seq ordinal := pmap insub (iota 0 n).
End OrdinalEnum.
End EnumRank.
Arguments enum_val_inj {T A} [i1 i2] : rename.
Arguments enum_rank_inj {T} [x1 x2].
Prenex Implicits enum_val enum_rank enum_valK enum_rankK.
(* The integer bump / unbump operations. *)
Definition bump h i := (h <= i) + i.
Definition unbump h i := i - (h < i).
(* The lift operations on ordinals; to avoid a messy dependent type, *)
(* unlift is a partial operation (returns an option).                *)
Definition unlift n (h i : 'I_n) :=
omap (fun u : {j | j != h} => Ordinal (unlift_subproof u)) (insub i).
Variant unlift_spec n h i : option 'I_n.-1 -> Type :=
| UnliftSome j of i = lift h j : unlift_spec h i (Some j)
| UnliftNone   of i = h        : unlift_spec h i None.
Variant split_ord_spec m n (i : 'I_(m + n)) : 'I_m + 'I_n -> bool -> Type :=
| SplitOrdLo (j : 'I_m) of i = lshift _ j : split_ord_spec i (inl _ j) true
| SplitOrdHi (k : 'I_n) of i = rshift _ k : split_ord_spec i (inr _ k) false.

Lemma split_ordP m n (i : 'I_(m + n)) : split_ord_spec i (split i) (i < m).