(* $Id: CPoly_Degree.v,v 1.3 2000/11/10 11:27:28 freek Exp $ *)

Require Export CPoly_NthCoeff.
Require Export CFields.

(* Tex_Prose
\section{Polynomials: Degree}
\begin{convention}
Let \verb!R! be a ring and write \verb!RX! for the ring of polynomials
over \verb!R!.
\end{convention}
*)

Section Degree_def.

Variable R: CRing.

Syntactic Definition RX := (cpoly_cring R).

(* Tex_Prose
The length of a polynomial is the number of its coefficients. This is a
syntactical property, as the highest coefficient may be $0$. Note that the
`zero' polynomial \verb!cpoly_zero! has length $0$, a constant
polynomial has length $1$ and so forth. So the length is always $1$ higher
than the `degree' (assuming that the highest coefficient is $\noto 0$)!
*)
(* Begin_Tex_Verb *)
Fixpoint lth_of_poly [p: RX] : nat :=
  Cases p of
     	cpoly_zero => O
	| (cpoly_linear d q) => (S(lth_of_poly q))
  end.
(* End_Tex_Verb *)

(* Tex_Prose
   When dealing with constructive polynomials, notably
   over the reals or complex numbers, the degree may be unknown, as we can not
   decide whether the highest coeffiecient is $\noto 0$.
   Hence, degree is a {\em relation\/} between polynomials and natural numbers;
   if the degree is unknown for polynomial $p$, degree$(n,p)$ doesn't hold for
   any $n$.
   If we don't know the degree of $p$, we may still know it to be below or
   above a certain number. E.g.\ for the polynomial
   $p_0 +p_1 X +\cdots + p_{n-1} X^{n-1}$,
   if $p_i \noto 0$, we can say that the `degree is
   at least $i$' and if $p_{j+1} = \ldots =p_n =0$ (with $n$ the length of the
   polynomial), we can say that the `degree is
   at most $j$'.
*)

(* Begin_Tex_Verb *)
Definition degree_le : nat -> RX -> Prop :=
[n:nat][p:RX] (m:nat)((lt n m)-> ((Nth_coeff m p) [=] Zero)).

Definition degree : nat -> RX -> Prop :=
[n:nat][p:RX] ((Nth_coeff n p) [#] Zero) /\ (degree_le n p).

Definition monic : nat -> RX -> Prop :=
[n:nat][p:RX] ((Nth_coeff n p) [=] One) /\ (degree_le n p).

Definition odd_cpoly : RX -> Prop :=
[p:RX](EX n | (odd n)/\(degree n p)).

Definition even_cpoly : RX -> Prop :=
[p:RX](EX n | (even n)/\(degree n p)).

Definition regular :RX-> Prop :=
[p:RX](EX n |(degree n p)).
(* End_Tex_Verb *)

End Degree_def.

Syntactic Definition Degree_le := (degree_le ?).
Syntactic Definition Degree := (degree ?).
Syntactic Definition Monic := (monic ?).
Syntactic Definition Lth_of_poly := (lth_of_poly ?).


Section Degree_props.

Variable R: CRing.

Syntactic Definition RX := (cpoly_cring R).

(* Begin_Tex_Verb *)
Lemma Degree_le_wd : (p,p':RX)(n:nat)
  (p [=] p')->(Degree_le n p)->(Degree_le n p').
(* End_Tex_Verb *)
Unfold degree_le. Intros.
Step_final (Nth_coeff m p).
Qed.

(* Begin_Tex_Verb *)
Lemma Degree_wd : (p,p':RX)(n:nat)
  (p [=] p')->(Degree n p)->(Degree n p').
(* End_Tex_Verb *)
Unfold degree. Intros.
Elim H0. Clear H0. Intros. Split.
Step_ap_lft (Nth_coeff n p).
Apply Degree_le_wd with p; Auto.
Qed.

(* Begin_Tex_Verb *)
Lemma Monic_wd : (p,p':RX)(n:nat)
  (p [=] p')->(Monic n p)->(Monic n p').
(* End_Tex_Verb *)
Unfold monic. Intros.
Elim H0. Clear H0. Intros. Split.
Step_final (Nth_coeff n p).
Apply Degree_le_wd with p; Auto.
Qed.

(* Begin_Tex_Verb *)
Lemma Degree_imp_Degree_le : (p:RX)(n:nat)(Degree n p)->(Degree_le n p).
(* End_Tex_Verb *)
Unfold degree. Intros. Elim H. Auto.
Qed.

(* Begin_Tex_Verb *)
Lemma Degree_le_c_ : (c:R)(Degree_le O (_C_ c)).
(* End_Tex_Verb *)
Unfold degree_le. Intros c m. Elim m; Intros.
Elim (lt_n_n ? H).
Simpl. Algebra.
Qed.

(* Begin_Tex_Verb *)
Lemma Degree_c_ : (c:R)(c [#] Zero)->(Degree O (_C_ c)).
(* End_Tex_Verb *)
Unfold degree. Intros. Split. Simpl. Auto. Apply Degree_le_c_.
Qed.

(* Begin_Tex_Verb *)
Lemma Monic_c_one : (Monic O (_C_ One::R)).
(* End_Tex_Verb *)
Unfold monic. Intros. Split. Simpl. Algebra. Apply Degree_le_c_.
Qed.

(* Begin_Tex_Verb *)
Lemma Degree_le_x_ : (Degree_le (1) _X_::RX).
(* End_Tex_Verb *)
Unfold degree_le.
Intro. Elim m. Intros. Elim (lt_n_O ? H).
Intro. Elim n. Intros. Elim (lt_n_n ? H0).
Intros. Simpl. Algebra.
Qed.

(* Begin_Tex_Verb *)
Lemma Degree_x_ : (Degree (1) _X_::RX).
(* End_Tex_Verb *)
Unfold degree. Split. Simpl. Algebra. Exact Degree_le_x_.
Qed.

(* Begin_Tex_Verb *)
Lemma Monic_x_ : (Monic (1) _X_::RX).
(* End_Tex_Verb *)
Unfold monic. Split. Simpl. Algebra. Exact Degree_le_x_.
Qed.

(* Begin_Tex_Verb *)
Lemma degree_le_mon : (p:RX)(m,n:nat)
  (le m n) -> (Degree_le m p) -> (Degree_le n p).
(* End_Tex_Verb *)
Unfold degree_le. Intros. Apply H0. Omega.
Qed.

(* Begin_Tex_Verb *)
Lemma Degree_le_min : (p:RX)(n:nat)(Degree_le n p)->(Degree_le n [--]p).
(* End_Tex_Verb *)
Unfold degree_le. Intros.
Step [--](Nth_coeff m p).
Step_final [--]Zero::R.
Qed.

(* Begin_Tex_Verb *)
Lemma Degree_le_plus : (p,q:RX)(n:nat)
  (Degree_le n p) -> (Degree_le n q) -> (Degree_le n p[+]q).
(* End_Tex_Verb *)
Unfold degree_le. Intros.
Step (Nth_coeff m p)[+](Nth_coeff m q).
Step_final Zero[+]Zero::R.
Qed.

(* Begin_Tex_Verb *)
Lemma Degree_le_minus : (p,q:RX)(n:nat)
  (Degree_le n p) -> (Degree_le n q) -> (Degree_le n p[-]q).
(* End_Tex_Verb *)
Unfold degree_le. Intros.
Step (Nth_coeff m p)[-](Nth_coeff m q).
Step_final Zero[-]Zero::R.
Qed.

(* Begin_Tex_Verb *)
Lemma sum_degree_le : (f:nat->RX)(n,k,l:nat)(le k (S l)) ->
  ((i:nat)(le k i) -> (le i l) -> (Degree_le n (f i))) ->
    (Degree_le n (Sum k l f)).
(* End_Tex_Verb *)
Unfold degree_le. Intros. Induction l; Intros.
Inversion H.
Unfold sum. Unfold sum1. Simpl.
Apply eq_transitive_unfolded with (Nth_coeff m Zero::RX).
Apply Nth_coeff_wd. Algebra. Algebra.
Inversion H3. Unfold sum. Unfold sum1. Simpl.
Apply eq_transitive_unfolded with (Nth_coeff m (f (0))).
Apply Nth_coeff_wd. Cut (f (0))[-]Zero [=] (f (0)). Auto. Algebra. Auto.
Elim (le_lt_eq_dec ?? H); Intros.
Apply eq_transitive_unfolded with (Nth_coeff m (Sum k l f)[+](f (S l))).
Apply Nth_coeff_wd. Algebra.
Step (Nth_coeff m (Sum k l f))[+](Nth_coeff m (f (S l))).
Step_rht Zero[+]Zero::R. Apply bin_op_wd_unfolded.
Apply Hrecl. Auto with arith. Intros.
Apply H0. Auto. Auto. Auto.
Apply H0. Auto with arith. Auto. Auto.
Rewrite y. Unfold sum. Unfold sum1. Simpl.
Apply eq_transitive_unfolded with (Nth_coeff m Zero::RX).
Apply Nth_coeff_wd. Algebra. Algebra.
Qed.

(* Begin_Tex_Verb *)
Lemma Degree_min : (p:RX)(n:nat)(Degree n p)->(Degree n [--]p).
(* End_Tex_Verb *)
Unfold degree. Intros.
Elim H. Clear H. Intros. Split.
Step_ap_lft [--](Nth_coeff n p).
Apply Degree_le_min; Auto.
Qed.

(* Begin_Tex_Verb *)
Lemma Degree_plus_rht : (p,q:RX)(m,n:nat)
             (Degree_le m p)->(Degree n q)->(lt m n)->(Degree n (p [+] q)).
(* End_Tex_Verb *)
Unfold degree. Unfold degree_le. Intros.
Elim H0. Clear H0. Intros.
Split.
Step_ap_lft (Nth_coeff n p)[+](Nth_coeff n q).
Step_ap_lft Zero[+](Nth_coeff n q).
Step_ap_lft (Nth_coeff n q).
Intros.
Step (Nth_coeff m0 p)[+](Nth_coeff m0 q).
Cut (lt m m0). Intro.
Step_final Zero[+]Zero::R.
Omega.
Qed.

(* Begin_Tex_Verb *)
Lemma Degree_minus_lft : (p,q:RX)(m,n:nat)
             (Degree_le m p)->(Degree n q)->(lt m n)->(Degree n (q [-] p)).
(* End_Tex_Verb *)
Intros.
Apply Degree_wd with ([--]p)[+]q.
Step_final q[+][--]p.
Apply Degree_plus_rht with m.
Apply Degree_le_min. Auto. Auto. Auto.
Qed.

(* Begin_Tex_Verb *)
Lemma Monic_plus : (p,q:RX)(m,n:nat)
  (Degree_le m p) -> (Monic n q) -> (lt m n) -> (Monic n p[+]q).
(* End_Tex_Verb *)
Unfold monic. Unfold degree_le. Intros.
Elim H0. Clear H0. Intros.
Split.
Step (Nth_coeff n p)[+](Nth_coeff n q).
Step Zero[+](Nth_coeff n q).
Step_final (Nth_coeff n q).
Intros.
Step (Nth_coeff m0 p)[+](Nth_coeff m0 q).
Cut (lt m m0). Intro.
Step_final Zero[+]Zero::R.
Omega.
Qed.

(* Begin_Tex_Verb *)
Lemma Monic_minus : (p,q:RX)(m,n:nat)
  (Degree_le m p) -> (Monic n q) -> (lt m n) -> (Monic n q[-]p).
(* End_Tex_Verb *)
Intros.
Apply Monic_wd with ([--]p)[+]q.
Step_final q[+][--]p.
Apply Monic_plus with m.
Apply Degree_le_min. Auto. Auto. Auto.
Qed.

(* Begin_Tex_Verb *)
Lemma Degree_le_mult : (p,q:RX)(m,n:nat)
             (Degree_le m p)->(Degree_le n q)->(Degree_le (plus m n) p[*]q).
(* End_Tex_Verb *)
Unfold degree_le. Intros.
Step (Sum (0) m0 [i:nat](Nth_coeff i p)[*](Nth_coeff (minus m0 i) q)).
Apply sum_zero. Auto with arith.
Intros.
Cut (lt m i) \/ (lt n (minus m0 i)). Intro.
Elim H4; Clear H4; Intros.
Step_final Zero[*](Nth_coeff (minus m0 i) q).
Step_final (Nth_coeff i p)[*]Zero.
Omega.
Qed.

(* Begin_Tex_Verb *)
Lemma Degree_mult_aux : (p,q:RX)(m,n:nat)
 (Degree_le m p)->(Degree_le n q)->
             (Nth_coeff (plus m n) p[*]q) [=]
               (Nth_coeff m p)[*](Nth_coeff n q).
(* End_Tex_Verb *)
Unfold degree_le. Intros.
Step (Sum (0) (plus m n)
  [i:nat](Nth_coeff i p)[*](Nth_coeff (minus (plus m n) i) q)).
Step (Sum (0) m [i:nat](Nth_coeff i p)[*](Nth_coeff (minus (plus m n) i) q))[+]
  (Sum (S m) (plus m n)
    [i:nat](Nth_coeff i p)[*](Nth_coeff (minus (plus m n) i) q)).
Step_rht (nth_coeff R m p)[*](nth_coeff R n q)[+]Zero.
Apply bin_op_wd_unfolded.
Elim (O_or_S m); Intros.
Elim y. Clear y. Intros. Rewrite <- y in H. Rewrite <- y.
Apply eq_transitive_unfolded with (Sum (0) x
  [i:nat](Nth_coeff i p)[*](Nth_coeff (minus (plus (S x) n) i) q))[+]
    (Nth_coeff (S x) p)[*](Nth_coeff (minus (plus (S x) n) (S x)) q).
Apply sum_last with f :=
  [i:nat](Nth_coeff i p)[*](Nth_coeff (minus (plus (S x) n) i) q).
Step_rht Zero[+](Nth_coeff (S x) p)[*](Nth_coeff n q).
Apply bin_op_wd_unfolded.
Apply sum_zero. Auto with arith. Intros.
Cut (lt n (minus (plus (S x) n) i)). Intro.
Step_final (Nth_coeff i p)[*]Zero.
Omega.
Replace (minus (plus (S x) n) (S x)) with n. Algebra. Omega.
Rewrite <- y in H. Rewrite <- y.
Pattern 2 n. Replace n with (minus (plus (0) n) (0)).
Apply sum_one with f :=
  [i:nat](Nth_coeff i p)[*](Nth_coeff (minus (plus (0) n) i) q).
Omega.
Apply sum_zero. Auto with arith. Intros.
Cut (lt m i). Intro.
Step_final Zero[*](Nth_coeff (minus (plus m n) i) q).
Auto.
Qed.

Hints Resolve Degree_mult_aux : algebra.

(* Begin_Tex_Verb *)
Lemma Monic_mult : (p,q:RX)(m,n:nat)
             (Monic m p)->(Monic n q)->(Monic (plus m n) p[*]q).
(* End_Tex_Verb *)
Unfold monic. Intros.
Elim H. Clear H. Intros. Elim H0. Clear H0. Intros. Split.
Step (Nth_coeff m p)[*](Nth_coeff n q).
Step_final One[*]One::R.
Apply Degree_le_mult; Auto.
Qed.

(* Begin_Tex_Verb *)
Lemma Degree_le_nexp : (p:RX)(m,n:nat)
             (Degree_le m p)->(Degree_le (mult m n) p[^]n).
(* End_Tex_Verb *)
Intros. Induction n; Intros.
Replace (mult m (0)) with (0).
Apply Degree_le_wd with (_C_ One::R). Algebra.
Apply Degree_le_c_.
Auto.
Replace (mult m (S n)) with (plus (mult m n) m).
Apply Degree_le_wd with p[^]n[*]p. Algebra.
Apply Degree_le_mult; Auto.
Auto.
Qed.

(* Begin_Tex_Verb *)
Lemma Monic_nexp : (p:RX)(m,n:nat)(Monic m p)->(Monic (mult m n) p[^]n).
(* End_Tex_Verb *)
Intros. Induction n; Intros.
Replace (mult m (0)) with (0).
Apply Monic_wd with (_C_ One::R). Algebra.
Apply Monic_c_one.
Auto.
Replace (mult m (S n)) with (plus (mult m n) m).
Apply Monic_wd with p[^]n[*]p. Algebra.
Apply Monic_mult; Auto.
Auto.
Qed.

(* Begin_Tex_Verb *)
Lemma lt_i_Lth_of_poly : (i:nat)(p:RX)
  ((Nth_coeff i p) [#] Zero) -> (lt i (Lth_of_poly p)).
(* End_Tex_Verb *)
Intros i. Induction i; Intros.
Induction p; Intros.
Simpl in H. Elim (ap_irreflexive_unfolded ?? H).
Simpl. Auto with arith.
Induction p; Intros.
Simpl in H. Elim (ap_irreflexive_unfolded ?? H).
Simpl. Simpl in H. Apply lt_n_S. Auto.
Qed.

(* Begin_Tex_Verb *)
Lemma poly_degree_lth : (p:RX)
  (Degree_le (Lth_of_poly p) p).
(* End_Tex_Verb *)
Unfold degree_le. Intros. Apply not_ap_imp_eq. Intro.
Apply (lt_not_le ?? H). Apply lt_le_weak.
Apply lt_i_Lth_of_poly. Auto.
Qed.

(* Begin_Tex_Verb *)
Lemma poly_ex_degree : (p:RX)(EX n | (Degree_le n p)).
(* End_Tex_Verb *)
Intros. Exists (Lth_of_poly p). Apply poly_degree_lth.
Qed.

(* Begin_Tex_Verb *)
Lemma poly_as_sum'' : (p:RX)(n:nat)(Degree_le n p)->
  p [=] (Sum (0) n [i:nat](_C_ (Nth_coeff i p))[*]_X_[^]i).
(* End_Tex_Verb *)
Unfold degree_le. Intros. Apply all_Nth_coeff_eq_imp. Intros.
Apply eq_symmetric_unfolded.
Apply eq_transitive_unfolded with
  (Sum (0) n [i0:nat](Nth_coeff i (_C_ (Nth_coeff i0 p))[*]_X_[^]i0)).
Apply nth_coeff_sum with p_ := [i:nat](_C_ (Nth_coeff i p))[*]_X_[^]i.
Apply eq_transitive_unfolded with
  (Sum (0) n [i0:nat](Nth_coeff i0 p)[*](Nth_coeff i _X_[^]i0)).
Apply sum_wd. Intros. Algebra.
Elim (le_lt_dec i n); Intros.
Step_rht (Nth_coeff i p)[*]One.
Step_rht (Nth_coeff i p)[*](Nth_coeff i _X_[^]i).
Apply sum_term with i0 := i
  a := [i0:nat](Nth_coeff i0 p)[*](Nth_coeff i _X_[^]i0).
Auto with arith. Auto.
Intros.
Step_final (Nth_coeff i0 p)[*]Zero.
Step_rht Zero::R.
Apply sum_zero. Auto with arith. Intros.
Cut (~i=i0). Intro.
Step_final (Nth_coeff i0 p)[*]Zero.
Omega.
Qed.

Hints Resolve poly_as_sum'' : algebra.

(* Begin_Tex_Verb *)
Lemma poly_as_sum' : (p:RX)
  p [=] (Sum (0) (Lth_of_poly p) [i:nat](_C_ (Nth_coeff i p))[*]_X_[^]i).
(* End_Tex_Verb *)
Intros. Apply poly_as_sum''. Apply poly_degree_lth.
Qed.

(* Begin_Tex_Verb *)
Lemma poly_as_sum : (p:RX)(n:nat)(Degree_le n p)->
  (x:R)(p!x [=] (Sum (0) n [i:nat](Nth_coeff i p)[*]x[^]i)).
(* End_Tex_Verb *)
Intros.
Step (Sum (0) n [i:nat](_C_ (Nth_coeff i p))[*]_X_[^]i)!x.
Apply eq_transitive_unfolded with
  (Sum (0) n [i:nat]((_C_ (Nth_coeff i p))[*]_X_[^]i)!x).
Apply sum_cpoly_ap with f := [i:nat](_C_ (Nth_coeff i p))[*]_X_[^]i.
Apply sum_wd. Intros.
Step (_C_ (Nth_coeff i p))!x[*](_X_[^]i)!x.
Step_final (Nth_coeff i p)[*](_X_!x)[^]i.
Qed.

(* Begin_Tex_Verb *)
Lemma degree_le_zero : (p:RX)
  (Degree_le (0) p) -> (EX a | p [=] (_C_ a)).
(* End_Tex_Verb *)
Unfold degree_le. Intros.
Exists (Nth_coeff (0) p).
Apply all_Nth_coeff_eq_imp. Intros.
Elim (O_or_S i); Intros.
Elim y. Clear y. Intros. Rewrite <- y.
Cut (lt (0) (S x)). Intro. Step_final Zero::R. Auto with arith.
Rewrite <- y. Algebra.
Qed.

(* Begin_Tex_Verb *)
Lemma Degree_le_1_imp : (p:RX)
  (Degree_le (1) p) -> (EX a | (EX b | p [=] (_C_ a)[*]_X_[+](_C_ b))).
(* End_Tex_Verb *)
Unfold degree_le. Intros.
Exists (Nth_coeff (1) p). Exists (Nth_coeff (0) p).
Apply all_Nth_coeff_eq_imp. Intros.
Elim i; Intros.
Simpl. Rational.
Elim n; Intros.
Simpl. Algebra.
Simpl. Apply H. Auto with arith.
Qed.

(* Begin_Tex_Verb *)
Lemma degree_le_cpoly_linear :
  (p:(cpoly R))(c:R)(n:nat)
    (Degree_le (S n) (cpoly_linear ? c p)) -> (Degree_le n p).
(* End_Tex_Verb *)
Unfold degree_le. Intros.
Change (Nth_coeff (S m) (cpoly_linear ? c p)) [=] Zero.
Apply H. Auto with arith.
Qed.

(* Begin_Tex_Verb *)
Lemma monic_cpoly_linear :
  (p:(cpoly R))(c:R)(n:nat)
    (Monic (S n) (cpoly_linear ? c p)) -> (Monic n p).
(* End_Tex_Verb *)
Unfold monic. Intros. Elim H. Clear H. Intros. Split. Auto.
Apply degree_le_cpoly_linear with c. Auto.
Qed.

(* Begin_Tex_Verb *)
Lemma monic_one :
  (p:(cpoly R))(c:R)
    (Monic (1) (cpoly_linear ? c p)) -> (x:R)(p!x [=] One).
(* End_Tex_Verb *)
Intros. Cut (Monic (0) p). Unfold monic. Intros. Elim H0. Clear H0. Intros.
Elim (degree_le_zero ? H1). Intro d. Intros.
Step (_C_ d)!x.
Step d.
Step (Nth_coeff (0) (_C_ d)).
Step_final (Nth_coeff (0) p).
Apply monic_cpoly_linear with c. Auto.
Qed.

(* Begin_Tex_Verb *)
Lemma monic_apzero :
  (p:RX)(n:nat)(Monic n p) -> (p [#] Zero).
(* End_Tex_Verb *)
Unfold monic. Intros.
Elim H. Clear H. Intros.
Apply Nth_coeff_ap_zero_imp with n.
Step_ap_lft One::R.
Qed.

End Degree_props.

Hints Resolve poly_as_sum'' poly_as_sum' poly_as_sum : algebra.
Hints Resolve Degree_mult_aux : algebra.


Section Degree_props_Field.

Variable F: CField.

Syntactic Definition FX := (cpoly_cring F).

(* Begin_Tex_Verb *)
Lemma Degree_mult : (p,q:FX)(m,n:nat)
             (Degree m p)->(Degree n q)->(Degree (plus m n) p[*]q).
(* End_Tex_Verb *)
Unfold degree. Intros.
Elim H. Clear H. Intros. Elim H0. Clear H0. Intros. Split.
Step_ap_lft (Nth_coeff m p)[*](Nth_coeff n q).
Apply Degree_le_mult; Auto.
Qed.

(* Begin_Tex_Verb *)
Lemma Degree_nexp : (p:FX)(m,n:nat)(Degree m p)->(Degree (mult m n) p[^]n).
(* End_Tex_Verb *)
Intros. Induction n; Intros.
Replace (mult m (0)) with (0).
Apply Degree_wd with (_C_ One::F). Algebra.
Apply Degree_c_. Algebra.
Auto.
Replace (mult m (S n)) with (plus (mult m n) m).
Apply Degree_wd with p[^]n[*]p. Algebra.
Apply Degree_mult; Auto.
Auto.
Qed.

(* Begin_Tex_Verb *)
Lemma Degree_le_mult_imp : (m,n:nat)(p,q:FX)
  (Degree m p) -> (Degree_le (plus m n) p[*]q) -> (Degree_le n q).
(* End_Tex_Verb *)
Unfold degree. Unfold degree_le. Intros. Elim H. Clear H. Intros.
Elim (poly_ex_degree ? q). Unfold degree_le. Intro N. Intros.
Cut (k,i:nat)(lt n i) -> (lt (minus N k) i) -> (Nth_coeff i q) [=] Zero. Intro.
Elim (le_lt_dec m0 N); Intros.
Replace m0 with (minus N (minus N m0)). Apply H4 with (minus N n).
Omega. Omega. Omega.
Apply H3; Auto.
Intro. Induction k; Intros.
Apply H3. Omega.
Elim (le_lt_eq_dec (minus N k) i); Intros. Auto. Rewrite y in Hreck.
Apply mult_cancel_lft with (Nth_coeff m p). Auto. Step_rht Zero::F.
Apply eq_transitive_unfolded with (Sum (0) (plus m i)
  [j:nat](Nth_coeff j p)[*](Nth_coeff (minus (plus m i) j) q)).
Pattern 1 i. Replace i with (minus (plus m i) m).
Apply eq_symmetric_unfolded.
Apply sum_term with a :=
 [j:nat](Nth_coeff j p)[*](Nth_coeff (minus (plus m i) j) q).
Auto with arith. Auto with arith.
Intros. Elim (le_lt_dec i0 m); Intros.
Cut (lt i (minus (plus m i) i0)). Intro.
Cut (lt n (minus (plus m i) i0)). Intro.
Step_final (Nth_coeff i0 p)[*]Zero.
Omega. Omega.
Step_final Zero[*](Nth_coeff (minus (plus m i) i0) q).
Omega.
Step (Nth_coeff (plus m i) p[*]q).
Cut (lt (plus m n) (plus m i)). Intro.
Auto.
Omega. Omega.
Qed.

(* Begin_Tex_Verb *)
Lemma Degree_mult_imp : (p,q:FX)(m,n:nat)
  (Degree m p) -> (Degree (plus m n) p[*]q) -> (Degree n q).
(* End_Tex_Verb *)
Unfold degree. Intros.
Elim H. Clear H. Intros. Elim H0. Clear H0. Intros.
Cut (Degree_le n q). Intro. Split.
Apply mult_cancel_ap_zero_rht with (Nth_coeff m p).
Step_ap_lft (Nth_coeff (plus m n) p[*]q). Auto.
Apply Degree_le_mult_imp with m p; Auto.
Unfold degree. Auto.
Qed.

End Degree_props_Field.


