Fixpoint multpf (p : list (Term A n)) : list (Term A n) -> list (Term A n) :=
  fun q : list (Term A n) =>
  match p with
  | nil => pO A n
  | a :: p' =>
      pluspf (A:=A) A0 (eqA:=eqA) plusA eqA_dec (n:=n) (ltM:=ltM) ltM_dec
        (mults (A:=A) multA (n:=n) a q) (multpf p' q)
  end.

(* Specifications: *)
Theorem canonical_multpf : forall l1 l2 : list (Term A n), canonical A0 eqA ltM l1 -> canonical A0 eqA ltM l2 -> canonical A0 eqA ltM (multpf l1 l2).
Theorem pluspf_pX : forall (p : list (Term A n)) (a : Term A n), canonical A0 eqA ltM (pX a p) -> eqP A eqA n (pX a p) (pluspf (A:=A) A0 (eqA:=eqA) plusA eqA_dec (n:=n) (ltM:=ltM) ltM_dec (pX a (pO A n)) p).
Theorem multpf_disr_pX : forall (p q : list (Term A n)) (a : Term A n), canonical A0 eqA ltM p -> canonical A0 eqA ltM (pX a q) -> eqP A eqA n (multpf p (pX a q)) (pluspf (A:=A) A0 (eqA:=eqA) plusA eqA_dec (n:=n) (ltM:=ltM) ltM_dec (mults (A:=A) multA (n:=n) a p) (multpf p q)).
Theorem multpf_head : forall (p q : list (Term A n)) (a b : Term A n), canonical A0 eqA ltM (pX a p) -> canonical A0 eqA ltM (pX b q) -> exists c : list (Term A n), multpf (pX a p) (pX b q) = pX (multTerm (A:=A) multA (n:=n) a b) c.
Theorem in_multpf_head : forall (p q : list (Term A n)) (a b : Term A n), canonical A0 eqA ltM (pX a p) -> canonical A0 eqA ltM (pX b q) -> In (multTerm (A:=A) multA (n:=n) a b) (multpf (pX a p) (pX b q)).
Theorem multpf_comp : forall p r : list (Term A n), eqP A eqA n p r -> forall q s : list (Term A n), canonical A0 eqA ltM p -> canonical A0 eqA ltM q -> canonical A0 eqA ltM r -> canonical A0 eqA ltM s -> eqP A eqA n q s -> eqP A eqA n (multpf p q) (multpf r s).
Theorem multpf_com : forall p q : list (Term A n), canonical A0 eqA ltM p -> canonical A0 eqA ltM q -> eqP A eqA n (multpf p q) (multpf q p).
Theorem multpf_dist_plusr : forall (p q r : list (Term A n)) (a : Term A n), canonical A0 eqA ltM p -> canonical A0 eqA ltM q -> canonical A0 eqA ltM r -> eqP A eqA n (multpf (pluspf (A:=A) A0 (eqA:=eqA) plusA eqA_dec (n:=n) (ltM:=ltM) ltM_dec p q) r) (pluspf (A:=A) A0 (eqA:=eqA) plusA eqA_dec (n:=n) (ltM:=ltM) ltM_dec (multpf p r) (multpf q r)).
Theorem multpf_dist_plusl : forall (p q r : list (Term A n)) (a : Term A n), canonical A0 eqA ltM p -> canonical A0 eqA ltM q -> canonical A0 eqA ltM r -> eqP A eqA n (multpf p (pluspf (A:=A) A0 (eqA:=eqA) plusA eqA_dec (n:=n) (ltM:=ltM) ltM_dec q r)) (pluspf (A:=A) A0 (eqA:=eqA) plusA eqA_dec (n:=n) (ltM:=ltM) ltM_dec (multpf p q) (multpf p r)).
Theorem multpf_smultm_assoc : forall (p q : list (Term A n)) (a : Term A n), canonical A0 eqA ltM p -> canonical A0 eqA ltM q -> ~ zeroP (A:=A) A0 eqA (n:=n) a -> eqP A eqA n (mults (A:=A) multA (n:=n) a (multpf p q)) (multpf (mults (A:=A) multA (n:=n) a p) q).
Theorem multpf_assoc : forall p q r : list (Term A n), canonical A0 eqA ltM p -> canonical A0 eqA ltM q -> canonical A0 eqA ltM r -> eqP A eqA n (multpf p (multpf q r)) (multpf (multpf p q) r).