(** ** 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_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_pow_correct 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).