(** ** Composition of polynomials  - [pcomp p pl] is the polynomial [p] where each variable [i] is replaced by the [i]th polynomial in the list [pl]. *)
Definition pcomp_pow' (xn:pow)(pl:list pol) : pol :=
ppower (nth (fst xn) pl (pcst 0 0)) (snd xn).
Definition pcomp_pow (xn:pow)(pl:list pol) : pol :=
(maxl (map parity pl), snd (pcomp_pow' xn pl)).
Definition pcomp_mon' (m:mon)(pl:list pol) : pol :=
pscalar (fst m) (pmultl (map (fun xn => pcomp_pow xn pl) (snd m))).
Definition pcomp_mon (m:mon)(pl:list pol) : pol :=
(maxl (map parity pl), snd (pcomp_mon' m pl)).
Definition pcomp' (p:pol)(pl:list pol) : pol :=
pplusl (map (fun m => pcomp_mon m pl) (snd p)).
Definition pcomp (p:pol)(pl:list pol) : pol :=
(maxl (map parity pl), snd (pcomp' p pl)).

(* Specifications: *)
Lemma parity_pcomp_pow : forall xn pl,
parity (pcomp_pow xn pl) = maxl (map parity pl).
Lemma map_parity_pcomp_pow xl pl :
map (fun xn => parity (pcomp_pow xn pl)) xl = map (fun _ => maxl (map parity pl)) xl.
Lemma parity_pcomp_mon : forall m pl,
parity (pcomp_mon m pl) = maxl (map parity pl).
Lemma parity_pcomp p pl :
parity (pcomp p pl) = maxl (map parity pl).
Lemma pWF_pcomp_pow' : forall xn pl,
andl pWF pl -> pWF (pcomp_pow' xn pl).
Lemma pWF_pcomp_pow : forall xn pl,
andl pWF pl -> pWF (pcomp_pow xn pl).
Lemma pWF_pcomp_mon' : forall m pl,
andl pWF pl -> pWF (pcomp_mon' m pl).
Lemma pWF_pcomp_mon : forall m pl,
andl pWF pl -> pWF (pcomp_mon m pl).
Lemma pWF_pcomp' : forall p pl,
andl pWF pl -> pWF (pcomp' p pl).
Lemma pWF_pcomp : forall p pl,
andl pWF pl -> pWF (pcomp p pl).
Lemma pcomp_pow'_correct : forall xn pl l,
peval (pcomp_pow' xn pl) l =
power (peval (nth (fst xn) pl (pcst 0 0)) l) (snd xn).
Lemma pcomp_mon'_correct : forall m pl l,
peval (pcomp_mon' m pl) l = peval_mon m (map (fun p => peval p l) pl).
Lemma pcomp_mon_correct : forall m pl l,
peval (pcomp_mon m pl) l = peval_mon m (map (fun p => peval p l) pl).
Lemma pcomp'_correct : forall p pl l,
peval (pcomp' p pl) l = peval p (map (fun p' => peval p' l) pl).
Lemma pcomp_correct p pl l :
peval (pcomp p pl) l = peval p (map (fun p => peval p l) pl).