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

Require Export CPoly_ApZero1.

Section Poly_Shifted.

(* this can be done for CRings in general, but we do it here
only for CC because extensionality makes everything much easier,
and we only need it for CC *)

Local R := CC.
Local RX := (cpoly_cring R).

Definition poly_shift :=
  [a:R; p:RX]
    (Sum (0) (Lth_of_poly p)
      [i:nat](_C_ (Nth_coeff i p))[*](_X_[+](_C_ a))[^]i).

Lemma poly_shift_apply :
  (a:R)(p:RX)(x:R)((poly_shift a p)!x [=] p!(x[+]a)).
Intros.
Unfold poly_shift.
Apply eq_transitive_unfolded with
  (Sum (0) (Lth_of_poly p)
    [i:nat]((_C_ (Nth_coeff i p))[*](_X_[+](_C_ a))[^]i)!x).
Apply sum_cpoly_ap with f :=
  [i:nat](_C_ (Nth_coeff i p))[*](_X_[+](_C_ a))[^]i.
Apply eq_symmetric_unfolded.
Step (Sum (0) (Lth_of_poly p) [i:nat](_C_ (Nth_coeff i p))[*]_X_[^]i)!(x[+]a).
Apply eq_transitive_unfolded with
  (Sum (0) (Lth_of_poly p) [i:nat]((_C_ (Nth_coeff i p))[*]_X_[^]i)!(x[+]a)).
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[+]a)[*](_X_[^]i)!(x[+]a).
Step (Nth_coeff i p)[*](_X_!(x[+]a))[^]i.
Step (Nth_coeff i p)[*](x[+]a)[^]i.
Step (Nth_coeff i p)[*](_X_!x[+](_C_ a)!x)[^]i.
Step (Nth_coeff i p)[*]((_X_[+](_C_ a))!x)[^]i.
Step_final (_C_ (Nth_coeff i p))!x[*]((_X_[+](_C_ a))[^]i)!x.
Qed.

Hints Resolve poly_shift_apply : algebra.

Lemma poly_shift_wd_rht :
  (a:R)(p,p':RX)(p [=] p') -> ((poly_shift a p) [=] (poly_shift a p')).
Intros. Apply poly_CC_extensional. Intros.
Step p!(x[+]a). Step_final p'!(x[+]a).
Qed.

Lemma poly_shift_shift :
  (a:R)(p:RX)((poly_shift [--]a (poly_shift a p)) [=] p).
Intros. Apply poly_CC_extensional. Intros.
Step (poly_shift a p)!(x[+][--]a).
Step p!((x[+][--]a)[+]a).
Apply apply_wd. Algebra. Rational.
Qed.

Lemma poly_shift_mult :
  (a:R)(p1,p2:RX)
    ((poly_shift a p1[*]p2) [=] (poly_shift a p1)[*](poly_shift a p2)).
Intros. Apply poly_CC_extensional. Intros.
Step (p1[*]p2)!(x[+]a). Unfold RX.
Step (p1!(x[+]a))[*](p2!(x[+]a)).
Step_final ((poly_shift a p1)!x)[*]((poly_shift a p2)!x).
Qed.

Lemma poly_shift_degree_le :
  (a:R)(p:RX)(n:nat)(Degree_le n p) -> (Degree_le n (poly_shift a p)).
Intros.
Unfold poly_shift.
Apply sum_degree_le. Auto with arith. Intros.
Elim (le_lt_dec i n); Intros.
Replace n with (plus (0) n).
Apply Degree_le_mult. Apply Degree_le_c_.
Apply degree_le_mon with (mult (1) i).
Omega.
Apply Degree_le_nexp. Apply Degree_imp_Degree_le.
Apply Degree_wd with (_C_ a)[+]_X_. Algebra.
Apply Degree_plus_rht with (0). Apply Degree_le_c_. Apply Degree_x_.
Auto. Auto.
Unfold degree_le in H.
Apply Degree_le_wd with (_C_ Zero::CC).
Step Zero::(cpoly_cring CC).
Step Zero[*](_X_[+](_C_ a))[^]i.
Apply bin_op_wd_unfolded.
Step_final (_C_ Zero::CC).
Algebra.
Apply degree_le_mon with (0).
Auto with arith.
Apply Degree_le_c_.
Qed.

Lemma poly_shift_monic :
  (a:R)(p:RX)(n:nat)(Monic n p) -> (Monic n (poly_shift a p)).
Intros.
Unfold monic in H. Elim H. Clear H. Intros. Unfold degree_le in H0.
Apply Monic_wd with
  (Sum (0) n [i:nat](_C_ (Nth_coeff i p))[*](_X_[+](_C_ a))[^]i).
Step (Sum (0) n [i:nat](_C_ (Nth_coeff i p))[*](_X_[+](_C_ a))[^]i)[+]Zero.
Apply eq_transitive_unfolded with
  (Sum (0) n [i:nat](_C_ (Nth_coeff i p))[*](_X_[+](_C_ a))[^]i)[+]
    (Sum (S n) (Lth_of_poly p)
      [i:nat](_C_ (Nth_coeff i p))[*](_X_[+](_C_ a))[^]i).
Apply bin_op_wd_unfolded. Algebra.
Apply eq_symmetric_unfolded.
Apply sum_zero.
Cut (lt n (Lth_of_poly p)). Intro. Auto with arith.
Apply lt_i_Lth_of_poly. Step_ap_lft One::R.
Intros. Cut (lt n i). Intro.
Step (_C_ Zero)[*](_X_[+](_C_ a))[^]i.
Step_final Zero[*](_X_[+](_C_ a))[^]i.
Auto with arith.
Unfold poly_shift.
Apply sum_sum.
Elim (O_or_S n); Intros. Elim y. Clear y. Intros.
Rewrite <- y in H. Rewrite <- y in H0. Rewrite <- y.
Apply Monic_wd with
  (Sum (0) x [i:nat](_C_ (Nth_coeff i p))[*](_X_[+](_C_ a))[^]i)[+]
    (_X_[+](_C_ a))[^](S x).
Apply eq_transitive_unfolded with
  (Sum (0) x [i:nat](_C_ (Nth_coeff i p))[*](_X_[+](_C_ a))[^]i)[+]
    (_C_ (Nth_coeff (S x) p))[*](_X_[+](_C_ a))[^](S x).
Apply bin_op_wd_unfolded. Algebra.
Step One[*](_X_[+](_C_ a))[^](S x).
Apply bin_op_wd_unfolded.
Step_final (_C_ One::R). Algebra.
Apply eq_symmetric_unfolded.
Apply sum_last with
  f := [i:nat](_C_ (Nth_coeff i p))[*](_X_[+](_C_ a))[^]i.
Apply Monic_plus with x.
Apply sum_degree_le. Auto with arith. Intros.
Replace x with (plus (0) x).
Apply Degree_le_mult. Apply Degree_le_c_.
Apply degree_le_mon with (mult (1) i).
Omega.
Apply Degree_le_nexp. Apply Degree_imp_Degree_le.
Apply Degree_wd with (_C_ a)[+]_X_. Algebra.
Apply Degree_plus_rht with (0). Apply Degree_le_c_. Apply Degree_x_.
Auto. Auto.
Pattern 1 (S x). Replace (S x) with (mult (1) (S x)).
Apply Monic_nexp.
Apply Monic_wd with ((_C_ a)[+]_X_). Algebra.
Apply Monic_plus with (0). Apply Degree_le_c_.
Apply Monic_x_.
Auto. Auto with arith. Auto.
Rewrite <- y in H. Rewrite <- y in H0. Rewrite <- y.
Apply Monic_wd with One::RX.
Unfold sum. Unfold sum1. Simpl. Split.
Cut One [=] (Nth_coeff (0) p)[*]One[+]Zero. Auto.
Step (Nth_coeff (0) p). Rational. Auto.
Apply Monic_wd with (_C_ One::R). Algebra.
Apply Monic_c_one.
Qed.

End Poly_Shifted.

Hints Resolve poly_shift_wd_rht : algebra_c.
Hints Resolve poly_shift_apply poly_shift_shift poly_shift_mult : algebra.

Syntactic Definition Shift := (poly_shift).


