Record rsplit : Type := mk_rsplit {
rsplit_left : PExpr C;
rsplit_common : PExpr C;
rsplit_right : PExpr C}.
(* Stupid name clash *)
Notation left := rsplit_left.
Notation right := rsplit_right.
Notation common := rsplit_common.
Fixpoint split_aux e1 p e2 {struct e1}: rsplit :=
match e1 with
| e3 * e4 =>
let r1 := split_aux e3 p e2 in
let r2 := split_aux e4 p (right r1) in
mk_rsplit (left r1 ** left r2)
(common r1 ** common r2)
(right r2)
| e3 ^ N0 => mk_rsplit 1 1 e2
| e3 ^ Npos p3 => split_aux e3 (Pos.mul p3 p) e2
| _ =>
match isIn e1 p e2 1 with
| Some (N0,e3) => mk_rsplit 1 (e1 ^^ Npos p) e3
| Some (Npos q, e3) => mk_rsplit (e1 ^^ Npos q) (e1 ^^ Npos (p - q)) e3
| None => mk_rsplit (e1 ^^ Npos p) 1 e2
end
end%poly.

(* Specifications: *)
Lemma split_aux_ok1 e1 p e2 :
(let res := match isIn e1 p e2 1 with
| Some (N0,e3) => mk_rsplit 1 (e1 ^^ Npos p) e3
| Some (Npos q, e3) => mk_rsplit (e1 ^^ Npos q) (e1 ^^ Npos (p - q)) e3
| None => mk_rsplit (e1 ^^ Npos p) 1 e2
end
in
e1 ^ Npos p === left res * common res
/\ e2 === right res * common res)%poly.
Theorem split_aux_ok: forall e1 p e2,
(e1 ^ Npos p === left (split_aux e1 p e2) * common (split_aux e1 p e2)
/\ e2 === right (split_aux e1 p e2) * common (split_aux e1 p e2))%poly.