Fixpoint wf_btree_over t :=
match t with BNode keys children =>
(length keys = 2 * d + 1)%nat /\
(children = [] \/ length children = S (length keys) /\ Forall wf_btree_aux children)
end.

(* Specifications: *)
Lemma alt_Forall : forall P (lt : list bnode),
(fix f lt := match lt with [] => True | t :: rest => P t /\ f rest end) lt <->
Forall P lt.
Lemma wf_or_iff : forall keys children,
(wf_btree_aux (BNode keys children) \/ wf_btree_over (BNode keys children)) <->
((d <= length keys <= 2 * d \/ length keys = 2 * d + 1)%nat /\
(children = [] \/ keys <> [] /\ length children = S (length keys) /\
Forall wf_btree_aux children)).
Lemma wf_or_iff' : forall keys children,
(wf_btree (BNode keys children) \/ wf_btree_over (BNode keys children)) <->
((length keys <= 2 * d \/ length keys = 2 * d + 1)%nat /\
(children = [] \/ keys <> [] /\ length children = S (length keys) /\
Forall wf_btree_aux children)).
Lemma odd_div : forall n, (S (2 * n) / 2)%nat = n.
Lemma Forall_skipn : forall {A} P (l : list A) n, Forall P l -> Forall P (skipn n l).
Lemma Forall_firstn : forall {A} P (l : list A) n, Forall P l -> Forall P (firstn n l).
Lemma insert_nonnil : forall {A} i (x : A) l, insert i x l <> [].
Lemma split_wf : forall keys children i c (Hc : nth_error children i = Some c)
(Hover : wf_btree_over c) (Hrest : Forall wf_btree_aux (remove_at i children))
(Hkeys : (d <= length keys <= 2 * d)%nat)
(Hchildren : length children = S (length keys)),
wf_btree_aux (split (BNode keys children) i) \/
wf_btree_over (split (BNode keys children) i).
Lemma split_wf' : forall keys children i c (Hc : nth_error children i = Some c)
(Hover : wf_btree_over c) (Hrest : Forall wf_btree_aux (remove_at i children))
(Hkeys : (length keys <= 2 * d)%nat)
(Hchildren : length children = S (length keys)),
wf_btree (split (BNode keys children) i) \/
wf_btree_over (split (BNode keys children) i).
Lemma split_contents : forall t i, contents (split t i) = contents t.
Lemma remove_In : forall {A} (x : A) i l, In x (remove_at i l) -> In x l.
Lemma Forall_remove : forall {A} P i (l : list A), Forall P l ->
Forall P (remove_at i l).
Lemma insert_at_wf : forall v p t t' (Hinsert : insert_at v t p = Some t')
(Hwf : wf_btree_aux t) (Hp : leaf_path t (removelast p)),
wf_btree_aux t' \/ wf_btree_over t'.
Corollary insert_at_wf' : forall v p t t' (Hinsert : insert_at v t p = Some t')
(Hwf : wf_btree t) (Hp : leaf_path t (removelast p)),
wf_btree t' \/ wf_btree_over t'.
Lemma find_leaf_aux : forall tgt lt i, (fix f children i :=
match children with
| [] => Some []
| c :: rest => match i with
| 0%nat => find_leaf tgt c
| S i0 => f rest i0
end
end) lt i = match nth_error lt i with Some c => find_leaf tgt c | None => Some [] end.
Lemma find_leaf_nonnil : forall v t p (Hfind : find_leaf v t = Some p), p <> [].
Lemma wf_weak : forall t, wf_btree_aux t -> wf_btree t.
Lemma find_index_le : forall tgt keys i
(Hfind : find_index tgt keys = NotFound i),
(i <= length keys)%nat.
Corollary find_index_valid : forall tgt keys (children : list bnode) i
(Hwf : children = [] \/ length children = S (length keys))
(Hfind : find_index tgt keys = NotFound i),
(i < length children)%nat \/ children = [].
Lemma nth_error_succeeds : forall {A} n (l : list A) (Hlt : (n < length l)%nat),
exists x, nth_error l n = Some x.
Lemma find_leaf_path : forall v t p (Hfind : find_leaf v t = Some p)
(Hwf : wf_btree t),
leaf_path t (removelast p).
Lemma insert_wf : forall v t t' (Hinsert : b_insert v t = Some t') (Hwf : wf_btree t),
wf_btree t'.
Lemma insert_In2 : forall {A} i (x : A) l, In x (insert i x l).
Lemma insert_at_In : forall v t p t' (Hinsert : insert_at v t p = Some t'),
In v (contents t').
Lemma Znth_In : forall A i (l : list A) d x (Hrange : 0 <= i < Zlength l)
(Hnth : Znth i l d = x), In x l.
Lemma In_Znth : forall A (l : list A) x d,
In x l ->
exists i, 0 <= i < Zlength l /\ Znth i l d = x.
Lemma sublist_of_nil : forall A i j, sublist i j (nil : list A) = [].
Fixpoint sorted2 l :=
match l with
| [] => True
| x :: rest => Forall (fun y => x <= y) rest /\ sorted2 rest
end.
Lemma sorted_equiv : forall l, sorted l <-> sorted2 l.
Lemma sorted_mono : forall d l i j (Hsort : sorted l) (Hi : 0 <= i <= j)
(Hj : j < Zlength l),
Znth i l d <= Znth j l d.
Lemma In_sorted_range : forall d lo hi x l (Hsort : sorted l) (Hlo : 0 <= lo <= hi)
(Hhi : hi <= Zlength l)
(Hin : In x (sublist lo hi l)),
Znth lo l d <= x <= Znth (hi - 1) l d.
Lemma In_sorted_gt : forall x i n l lo hi (Hsort : sorted l) (Hlo : lo >= 0)
(Hhi : hi <= Zlength l)
(Hin : In x (sublist lo hi l))
(Hi : lo <= i < hi) (Hn : Znth i l 0 = n)
(Hgt : n < x),
In x (sublist (i + 1) hi l).
Lemma In_sorted_lt : forall x i n l lo hi (Hsort : sorted l) (Hlo : lo >= 0)
(Hhi : hi <= Zlength l)
(Hin : In x (sublist lo hi l))
(Hi : lo <= i < hi) (Hn : Znth i l 0 = n)
(Hgt : x < n),
In x (sublist lo i l).