(* $Id: OddPolyRootIR.v,v 1.7 2000/11/07 16:04:08 janz Exp $ *)

Require Export IVT.

Section CPoly_Big.

Variable R : COrdField.

Lemma bigger : (x,y:R)(EX z | (x [:<] z) /\ (y [:<] z)).
Intros.
Elim (cotrans_less_unfolded ? x x[+]One (less_plusOne ??) y); Intro.
Exists y[+]One. Split.
Apply less_transitive_unfolded with y. Auto. Apply less_plusOne.
Apply less_plusOne.
Exists x[+]One. Split.
Apply less_plusOne.
Auto.
Qed.

Lemma cpoly_big :
  (p:(cpoly R))(n:nat)(lt (0) n) -> (Monic n p) ->
    (Y:R)(EX X | (x:R)(X [:<] x) -> (Y [:<] p!x)).
Intro. Elim p.
Unfold monic. Simpl. Intros. Elim H0. Intros.
Cut ~(Zero [=] One::R). Intro. Elim (H3 H1).
Fold (Zero [~=] One::R).
Apply ap_imp_neq. Apply ap_symmetric_unfolded. Apply ring_non_triv.
Intros c q. Intros.
Elim (O_or_S n); Intro. Elim y. Intro m. Intros.
Rewrite <- y0 in H1.
Elim (zerop m); Intros. Simpl.
Exists Y[-]c. Intros.
Rewrite y1 in H1.
Apply shift_less_plus'.
Cut q!x [=] One. Intro.
Step_less_rht x[*]One. Step_less_rht x. Auto.
Apply monic_one with c. Auto.
Cut (monic ? m q). Intro.
Elim (bigger Zero Y[-]c). Intro Y'. Intros. Elim H3. Clear H3. Intros.
Elim (H m y1 H2 Y'). Intro X'. Intros.
Simpl.
Elim (bigger One X'). Intro X. Intros. Elim H6. Clear H6. Intros.
Exists X. Intros.
Apply shift_less_plus'.
Apply less_transitive_unfolded with One[*]Y'.
Step_less_rht Y'. Auto.
Apply mult_resp_less_both; Auto.
Apply less_leEq. Apply pos_one.
Apply less_transitive_unfolded with X; Auto.
Apply less_leEq. Auto.
Change Y' [:<] q!x.
Apply H5.
Apply less_transitive_unfolded with X; Auto.
Apply monic_cpoly_linear with c; Auto.
Rewrite <- y in H0.
Elim (lt_n_n ? H0).
Qed.

Lemma cpoly_pos :
  (p:(cpoly R))(n:nat)(lt (0) n) -> (Monic n p) -> (EX x | Zero [:<] p!x).
Intros.
Elim (cpoly_big ?? H H0 Zero). Intros.
Exists x[+]One.
Apply H1. Apply less_plusOne.
Qed.

Lemma cpoly_pos' :
  (p:(cpoly R))(a:R)(n:nat)(lt (0) n) -> (Monic n p) ->
    (EX x | (a [:<] x) /\ (Zero [:<] p!x)).
Intros.
Elim (cpoly_big ?? H H0 Zero). Intro x'. Intros.
Elim (bigger a x'). Intro x. Intros.
Elim H2. Clear H2. Intros.
Exists x. Split; Auto.
Qed.

End CPoly_Big.


Section Flip_Poly.

Variable R : CRing.

Fixpoint flip [p:(cpoly R)] : (cpoly R) :=
  Cases p of
    cpoly_zero => (cpoly_zero ?)
  | (cpoly_linear c q) => (cpoly_min ? (cpoly_linear ? c (flip q)))
  end.

Lemma flip_poly : (p:(cpoly R))(x:R)((flip p)!x [=] [--](p!([--]x))).
Intro p. Elim p.
Intros. Simpl. Algebra.
Intros c q. Intros.
Change  [--]c[+]x[*]((cpoly_min ? (flip q)) ! x)
    [=] [--](c[+][--]x[*](q !([--]x))).
Step [--]c[+]x[*][--]((flip q)!x).
Step [--]c[+]x[*]([--][--](q!([--]x))).
Rational.
Qed.

Lemma flip_coefficient :
  (p:(cpoly R))(i:nat)
    ((Nth_coeff i (flip p)) [=] [--](([--]One)[^]i)[*](Nth_coeff i p)).
Intro p. Elim p.
Simpl. Algebra.
Intros c q. Intros.
Elim i. Simpl. Rational.
Intros. Simpl.
Step [--](Nth_coeff n (flip q)).
Step [--]([--](([--]One)[^]n)[*](Nth_coeff n q)).
Simpl. Rational.
Qed.

Hints Resolve flip_coefficient : algebra.

Lemma flip_odd :
  (p:(cpoly R))(n:nat)(odd n) -> (Monic n p) -> (Monic n (flip p)).
Unfold monic. Unfold degree_le.
Intros.
Elim H0. Clear H0. Intros.
Split.
Step [--](([--]One)[^]n)[*](Nth_coeff n p).
Step ([--][--]One[^]n)[*](Nth_coeff n p).
Step One[^]n[*](Nth_coeff n p).
Step One[*](Nth_coeff n p).
Step_final One[*]One::R.
Intros.
Step [--](([--]One)[^]m)[*](Nth_coeff m p).
Step_final [--](([--]One)[^]m)[*]Zero::R.
Qed.

End Flip_Poly.

Hints Resolve flip_poly : algebra.


Section OddPoly_Signs.

Variable R : COrdField.

Lemma oddpoly_pos :
  (p:(cpoly R))(n:nat)(odd n) -> (Monic n p) -> (EX x | Zero [:<] p!x).
Intros.
Apply cpoly_pos with n; Auto.
Elim H. Intros. Auto with arith.
Qed.

Lemma oddpoly_pos' :
  (p:(cpoly R))(a:R)(n:nat)(odd n) -> (Monic n p) ->
    (EX x | (a [:<] x) /\ (Zero [:<] p!x)).
Intros.
Apply cpoly_pos' with n; Auto.
Elim H. Intros. Auto with arith.
Qed.

Lemma oddpoly_neg :
  (p:(cpoly R))(n:nat)(odd n) -> (Monic n p) -> (EX x | p!x [:<] Zero).
Intros.
Elim (oddpoly_pos ?? H (flip_odd ??? H H0)). Intro x. Intros.
Exists [--]x.
Step_less_lft [--][--](p!([--]x)). Step_less_rht [--]Zero::R.
Apply min_resp_less.
Step_less_rht (flip ? p)!x. Auto.
Qed.

End OddPoly_Signs.


Section Poly_Norm.

Variable R : CField.
Local RX := (cpoly_cring R).

Lemma poly_norm_aux :
  (p:RX; n:nat; H:(Degree n p))
    (Nth_coeff n p) [#] Zero.
Unfold Degree. Intros.
Elim H. Auto.
Qed.

Definition poly_norm :=
  [p:RX; n:nat; H:(Degree n p)]
    (_C_ (One[/](Nth_coeff n p)[//](poly_norm_aux p n H)))[*]p.

Lemma poly_norm_monic :
  (p:RX; n:nat; H:(Degree n p))
    (Monic n (poly_norm p n H)).
Unfold poly_norm. Unfold monic. Unfold degree. Unfold degree_le. Intros.
Elim H. Intros. Split.
Step_final (One[/](Nth_coeff n p)[//](poly_norm_aux p n H))[*](Nth_coeff n p).
Intros.
Step (One[/](Nth_coeff n p)[//](poly_norm_aux p n H))[*](Nth_coeff m p).
Step_final (One[/](Nth_coeff n p)[//](poly_norm_aux p n H))[*]Zero.
Qed.

Lemma poly_norm_apply :
  (p:RX; n:nat; H:(Degree n p))
    (x:R)((poly_norm p n H)!x [=] Zero) -> (p!x [=] Zero).
Unfold poly_norm. Intros.
Apply mult_cancel_lft with (One[/](Nth_coeff n p)[//](poly_norm_aux p n H)).
Apply div_resp_ap_zero_rev. Apply ring_non_triv.
Step (_C_ One[/](Nth_coeff n p)[//](poly_norm_aux p n H))!x[*]p!x.
Step ((_C_ (One[/](Nth_coeff n p)[//](poly_norm_aux p n H)))[*]p)!x.
Step_final Zero::R.
Qed.

End Poly_Norm.


Section OddPoly_Root.

Lemma oddpoly_root' :
  (f:(cpoly IR))(n:nat)(odd n) -> (Monic n f) -> (EX x | f!x [=] Zero).
Intros.
Elim (oddpoly_neg ? f n); Auto. Intro a. Intros.
Elim (oddpoly_pos' ? f a n); Auto. Intro b. Intros.
Elim H2. Clear H2. Intros.
Cut (EX x | (a [:<=] x) /\ (x [:<=] b) /\ (f!x [=] Zero)).
Intro.
Elim H4. Clear H4. Intros.
Elim H4. Clear H4. Intros. Elim H5. Clear H5. Intros.
Exists x. Auto.
Apply ivt_poly; Auto.
Apply monic_apzero with n; Auto.
Simpl. Apply less_leEq. Auto.
Simpl. Apply less_leEq. Auto.
Qed.

Lemma oddpoly_root :
  (f:(cpoly IR))(n: nat)(odd n) -> (Degree n f) -> (EX x | f!x [=] Zero).
Intros.
Elim (oddpoly_root' (poly_norm ? f n H0) n); Auto.
Intros. Exists x.
Apply poly_norm_apply with n H0; Auto.
Apply poly_norm_monic; Auto.
Qed.

Lemma realpolyn_oddhaszero :
  (f:(cpoly_cring IR))(odd_cpoly ? f) -> (EX x | f!x [=] Zero).
Unfold odd_cpoly.
Intros.
Elim H. Clear H. Intro n. Intros.
Elim H. Clear H. Intros.
Elim (oddpoly_root f n H H0). Intros. Exists x. Auto.
Qed.

End OddPoly_Root.


