src/HOL/Library/Formal_Power_Series.thy
changeset 31968 0314441a53a6
parent 31790 05c92381363c
child 32042 df28ead1cf19
child 32157 adea7a729c7a
equal deleted inserted replaced
31967:81dbc693143b 31968:0314441a53a6
     3 *)
     3 *)
     4 
     4 
     5 header{* A formalization of formal power series *}
     5 header{* A formalization of formal power series *}
     6 
     6 
     7 theory Formal_Power_Series
     7 theory Formal_Power_Series
     8 imports Main Fact Parity Rational
     8 imports Complex_Main
     9 begin
     9 begin
       
    10 
    10 
    11 
    11 subsection {* The type of formal power series*}
    12 subsection {* The type of formal power series*}
    12 
    13 
    13 typedef (open) 'a fps = "{f :: nat \<Rightarrow> 'a. True}"
    14 typedef (open) 'a fps = "{f :: nat \<Rightarrow> 'a. True}"
    14   morphisms fps_nth Abs_fps
    15   morphisms fps_nth Abs_fps
   406     by (simp add: fps_const_add[symmetric] del: fps_const_add)
   407     by (simp add: fps_const_add[symmetric] del: fps_const_add)
   407 next
   408 next
   408   case (step2 i) thus ?case unfolding number_of_fps_def 
   409   case (step2 i) thus ?case unfolding number_of_fps_def 
   409     by (simp add: fps_const_sub[symmetric] del: fps_const_sub)
   410     by (simp add: fps_const_sub[symmetric] del: fps_const_sub)
   410 qed
   411 qed
       
   412 subsection{* The eXtractor series X*}
       
   413 
       
   414 lemma minus_one_power_iff: "(- (1::'a :: {comm_ring_1})) ^ n = (if even n then 1 else - 1)"
       
   415   by (induct n, auto)
       
   416 
       
   417 definition "X = Abs_fps (\<lambda>n. if n = 1 then 1 else 0)"
       
   418 lemma X_mult_nth[simp]: "(X * (f :: ('a::semiring_1) fps)) $n = (if n = 0 then 0 else f $ (n - 1))"
       
   419 proof-
       
   420   {assume n: "n \<noteq> 0"
       
   421     have fN: "finite {0 .. n}" by simp
       
   422     have "(X * f) $n = (\<Sum>i = 0..n. X $ i * f $ (n - i))" by (simp add: fps_mult_nth)
       
   423     also have "\<dots> = f $ (n - 1)"
       
   424       using n by (simp add: X_def mult_delta_left setsum_delta [OF fN])
       
   425   finally have ?thesis using n by simp }
       
   426   moreover
       
   427   {assume n: "n=0" hence ?thesis by (simp add: fps_mult_nth X_def)}
       
   428   ultimately show ?thesis by blast
       
   429 qed
       
   430 
       
   431 lemma X_mult_right_nth[simp]: "((f :: ('a::comm_semiring_1) fps) * X) $n = (if n = 0 then 0 else f $ (n - 1))"
       
   432   by (metis X_mult_nth mult_commute)
       
   433 
       
   434 lemma X_power_iff: "X^k = Abs_fps (\<lambda>n. if n = k then (1::'a::comm_ring_1) else 0)"
       
   435 proof(induct k)
       
   436   case 0 thus ?case by (simp add: X_def fps_eq_iff)
       
   437 next
       
   438   case (Suc k)
       
   439   {fix m
       
   440     have "(X^Suc k) $ m = (if m = 0 then (0::'a) else (X^k) $ (m - 1))"
       
   441       by (simp add: power_Suc del: One_nat_def)
       
   442     then     have "(X^Suc k) $ m = (if m = Suc k then (1::'a) else 0)"
       
   443       using Suc.hyps by (auto cong del: if_weak_cong)}
       
   444   then show ?case by (simp add: fps_eq_iff)
       
   445 qed
       
   446 
       
   447 lemma X_power_mult_nth: "(X^k * (f :: ('a::comm_ring_1) fps)) $n = (if n < k then 0 else f $ (n - k))"
       
   448   apply (induct k arbitrary: n)
       
   449   apply (simp)
       
   450   unfolding power_Suc mult_assoc
       
   451   by (case_tac n, auto)
       
   452 
       
   453 lemma X_power_mult_right_nth: "((f :: ('a::comm_ring_1) fps) * X^k) $n = (if n < k then 0 else f $ (n - k))"
       
   454   by (metis X_power_mult_nth mult_commute)
       
   455 
       
   456 
       
   457 
   411   
   458   
       
   459 subsection{* Formal Power series form a metric space *}
       
   460 
       
   461 definition (in dist) ball_def: "ball x r = {y. dist y x < r}"
       
   462 instantiation fps :: (comm_ring_1) dist
       
   463 begin
       
   464 
       
   465 definition dist_fps_def: "dist (a::'a fps) b = (if (\<exists>n. a$n \<noteq> b$n) then inverse (2 ^ The (leastP (\<lambda>n. a$n \<noteq> b$n))) else 0)"
       
   466 
       
   467 lemma dist_fps_ge0: "dist (a::'a fps) b \<ge> 0"
       
   468   by (simp add: dist_fps_def)
       
   469 
       
   470 lemma dist_fps_sym: "dist (a::'a fps) b = dist b a"
       
   471   apply (auto simp add: dist_fps_def)
       
   472   thm cong[OF refl]
       
   473   apply (rule cong[OF refl, where x="(\<lambda>n\<Colon>nat. a $ n \<noteq> b $ n)"])
       
   474   apply (rule ext)
       
   475   by auto
       
   476 instance ..
       
   477 end
       
   478 
       
   479 lemma fps_nonzero_least_unique: assumes a0: "a \<noteq> 0"
       
   480   shows "\<exists>! n. leastP (\<lambda>n. a$n \<noteq> 0) n"
       
   481 proof-
       
   482   from fps_nonzero_nth_minimal[of a] a0
       
   483   obtain n where n: "a$n \<noteq> 0" "\<forall>m < n. a$m = 0" by blast
       
   484   from n have ln: "leastP (\<lambda>n. a$n \<noteq> 0) n" 
       
   485     by (auto simp add: leastP_def setge_def not_le[symmetric])
       
   486   moreover
       
   487   {fix m assume "leastP (\<lambda>n. a$n \<noteq> 0) m"
       
   488     then have "m = n" using ln
       
   489       apply (auto simp add: leastP_def setge_def)
       
   490       apply (erule allE[where x=n])
       
   491       apply (erule allE[where x=m])
       
   492       by simp}
       
   493   ultimately show ?thesis by blast
       
   494 qed
       
   495 
       
   496 lemma fps_eq_least_unique: assumes ab: "(a::('a::ab_group_add) fps) \<noteq> b"
       
   497   shows "\<exists>! n. leastP (\<lambda>n. a$n \<noteq> b$n) n"
       
   498 using fps_nonzero_least_unique[of "a - b"] ab
       
   499 by auto
       
   500 
       
   501 instantiation fps :: (comm_ring_1) metric_space
       
   502 begin
       
   503 
       
   504 definition open_fps_def: "open (S :: 'a fps set) = (\<forall>a \<in> S. \<exists>r. r >0 \<and> ball a r \<subseteq> S)"
       
   505 
       
   506 instance
       
   507 proof
       
   508   fix S :: "'a fps set" 
       
   509   show "open S = (\<forall>x\<in>S. \<exists>e>0. \<forall>y. dist y x < e \<longrightarrow> y \<in> S)"
       
   510     by (auto simp add: open_fps_def ball_def subset_eq)
       
   511 next
       
   512 {  fix a b :: "'a fps"
       
   513   {assume ab: "a = b"
       
   514    then have "\<not> (\<exists>n. a$n \<noteq> b$n)" by simp
       
   515    then have "dist a b = 0" by (simp add: dist_fps_def)}
       
   516  moreover
       
   517  {assume d: "dist a b = 0"
       
   518    then have "\<forall>n. a$n = b$n" 
       
   519      by - (rule ccontr, simp add: dist_fps_def)
       
   520    then have "a = b" by (simp add: fps_eq_iff)}
       
   521  ultimately show "dist a b =0 \<longleftrightarrow> a = b" by blast}
       
   522 note th = this
       
   523 from th have th'[simp]: "\<And>a::'a fps. dist a a = 0" by simp
       
   524   fix a b c :: "'a fps"
       
   525   {assume ab: "a = b" then have d0: "dist a b = 0"  unfolding th .
       
   526     then have "dist a b \<le> dist a c + dist b c" 
       
   527       using dist_fps_ge0[of a c] dist_fps_ge0[of b c] by simp}
       
   528   moreover
       
   529   {assume c: "c = a \<or> c = b" then have "dist a b \<le> dist a c + dist b c"
       
   530       by (cases "c=a", simp_all add: th dist_fps_sym) }
       
   531   moreover
       
   532   {assume ab: "a \<noteq> b" and ac: "a \<noteq> c" and bc: "b \<noteq> c"
       
   533     let ?P = "\<lambda>a b n. a$n \<noteq> b$n"
       
   534     from fps_eq_least_unique[OF ab] fps_eq_least_unique[OF ac] 
       
   535       fps_eq_least_unique[OF bc]
       
   536     obtain nab nac nbc where nab: "leastP (?P a b) nab" 
       
   537       and nac: "leastP (?P a c) nac" 
       
   538       and nbc: "leastP (?P b c) nbc" by blast
       
   539     from nab have nab': "\<And>m. m < nab \<Longrightarrow> a$m = b$m" "a$nab \<noteq> b$nab"
       
   540       by (auto simp add: leastP_def setge_def)
       
   541     from nac have nac': "\<And>m. m < nac \<Longrightarrow> a$m = c$m" "a$nac \<noteq> c$nac"
       
   542       by (auto simp add: leastP_def setge_def)
       
   543     from nbc have nbc': "\<And>m. m < nbc \<Longrightarrow> b$m = c$m" "b$nbc \<noteq> c$nbc"
       
   544       by (auto simp add: leastP_def setge_def)
       
   545 
       
   546     have th0: "\<And>(a::'a fps) b. a \<noteq> b \<longleftrightarrow> (\<exists>n. a$n \<noteq> b$n)"
       
   547       by (simp add: fps_eq_iff)
       
   548     from ab ac bc nab nac nbc 
       
   549     have dab: "dist a b = inverse (2 ^ nab)" 
       
   550       and dac: "dist a c = inverse (2 ^ nac)" 
       
   551       and dbc: "dist b c = inverse (2 ^ nbc)"
       
   552       unfolding th0
       
   553       apply (simp_all add: dist_fps_def)
       
   554       apply (erule the1_equality[OF fps_eq_least_unique[OF ab]])
       
   555       apply (erule the1_equality[OF fps_eq_least_unique[OF ac]])
       
   556       by (erule the1_equality[OF fps_eq_least_unique[OF bc]])
       
   557     from ab ac bc have nz: "dist a b \<noteq> 0" "dist a c \<noteq> 0" "dist b c \<noteq> 0"
       
   558       unfolding th by simp_all
       
   559     from nz have pos: "dist a b > 0" "dist a c > 0" "dist b c > 0"
       
   560       using dist_fps_ge0[of a b] dist_fps_ge0[of a c] dist_fps_ge0[of b c] 
       
   561       by auto
       
   562     have th1: "\<And>n. (2::real)^n >0" by auto
       
   563     {assume h: "dist a b > dist a c + dist b c"
       
   564       then have gt: "dist a b > dist a c" "dist a b > dist b c"
       
   565 	using pos by auto
       
   566       from gt have gtn: "nab < nbc" "nab < nac"
       
   567 	unfolding dab dbc dac by (auto simp add: th1)
       
   568       from nac'(1)[OF gtn(2)] nbc'(1)[OF gtn(1)]
       
   569       have "a$nab = b$nab" by simp
       
   570       with nab'(2) have False  by simp}
       
   571     then have "dist a b \<le> dist a c + dist b c"
       
   572       by (auto simp add: not_le[symmetric]) }
       
   573   ultimately show "dist a b \<le> dist a c + dist b c" by blast
       
   574 qed
       
   575   
       
   576 end
       
   577 
       
   578 text{* The infinite sums and justification of the notation in textbooks*}
       
   579 
       
   580 lemma reals_power_lt_ex: assumes xp: "x > 0" and y1: "(y::real) > 1"
       
   581   shows "\<exists>k>0. (1/y)^k < x"
       
   582 proof-
       
   583   have yp: "y > 0" using y1 by simp
       
   584   from reals_Archimedean2[of "max 0 (- log y x) + 1"]
       
   585   obtain k::nat where k: "real k > max 0 (- log y x) + 1" by blast
       
   586   from k have kp: "k > 0" by simp
       
   587   from k have "real k > - log y x" by simp
       
   588   then have "ln y * real k > - ln x" unfolding log_def
       
   589     using ln_gt_zero_iff[OF yp] y1
       
   590     by (simp add: minus_divide_left field_simps del:minus_divide_left[symmetric] )
       
   591   then have "ln y * real k + ln x > 0" by simp
       
   592   then have "exp (real k * ln y + ln x) > exp 0"
       
   593     by (simp add: mult_ac)
       
   594   then have "y ^ k * x > 1"
       
   595     unfolding exp_zero exp_add exp_real_of_nat_mult
       
   596     exp_ln[OF xp] exp_ln[OF yp] by simp
       
   597   then have "x > (1/y)^k" using yp 
       
   598     by (simp add: field_simps nonzero_power_divide )
       
   599   then show ?thesis using kp by blast
       
   600 qed
       
   601 lemma X_nth[simp]: "X$n = (if n = 1 then 1 else 0)" by (simp add: X_def)
       
   602 lemma X_power_nth[simp]: "(X^k) $n = (if n = k then 1 else (0::'a::comm_ring_1))"
       
   603   by (simp add: X_power_iff)
       
   604  
       
   605 
       
   606 lemma fps_sum_rep_nth: "(setsum (%i. fps_const(a$i)*X^i) {0..m})$n = (if n \<le> m then a$n else (0::'a::comm_ring_1))"
       
   607   apply (auto simp add: fps_eq_iff fps_setsum_nth X_power_nth cond_application_beta cond_value_iff  cong del: if_weak_cong)
       
   608   by (simp add: setsum_delta')
       
   609   
       
   610 lemma fps_notation: 
       
   611   "(%n. setsum (%i. fps_const(a$i) * X^i) {0..n}) ----> a" (is "?s ----> a")
       
   612 proof-
       
   613     {fix r:: real
       
   614       assume rp: "r > 0"
       
   615       have th0: "(2::real) > 1" by simp
       
   616       from reals_power_lt_ex[OF rp th0] 
       
   617       obtain n0 where n0: "(1/2)^n0 < r" "n0 > 0" by blast
       
   618       {fix n::nat
       
   619 	assume nn0: "n \<ge> n0"
       
   620 	then have thnn0: "(1/2)^n <= (1/2 :: real)^n0"
       
   621 	  by (auto intro: power_decreasing)
       
   622 	{assume "?s n = a" then have "dist (?s n) a < r" 
       
   623 	    unfolding dist_eq_0_iff[of "?s n" a, symmetric]
       
   624 	    using rp by (simp del: dist_eq_0_iff)}
       
   625 	moreover
       
   626 	{assume neq: "?s n \<noteq> a"
       
   627 	  from fps_eq_least_unique[OF neq] 
       
   628 	  obtain k where k: "leastP (\<lambda>i. ?s n $ i \<noteq> a$i) k" by blast
       
   629 	  have th0: "\<And>(a::'a fps) b. a \<noteq> b \<longleftrightarrow> (\<exists>n. a$n \<noteq> b$n)"
       
   630 	    by (simp add: fps_eq_iff)
       
   631 	  from neq have dth: "dist (?s n) a = (1/2)^k"
       
   632 	    unfolding th0 dist_fps_def
       
   633 	    unfolding the1_equality[OF fps_eq_least_unique[OF neq], OF k]
       
   634 	    by (auto simp add: inverse_eq_divide power_divide)
       
   635 
       
   636 	  from k have kn: "k > n"
       
   637 	    apply (simp add: leastP_def setge_def fps_sum_rep_nth)
       
   638 	    by (cases "k \<le> n", auto)
       
   639 	  then have "dist (?s n) a < (1/2)^n" unfolding dth
       
   640 	    by (auto intro: power_strict_decreasing)
       
   641 	  also have "\<dots> <= (1/2)^n0" using nn0
       
   642 	    by (auto intro: power_decreasing)
       
   643 	  also have "\<dots> < r" using n0 by simp
       
   644 	  finally have "dist (?s n) a < r" .}
       
   645 	ultimately have "dist (?s n) a < r" by blast}
       
   646       then have "\<exists>n0. \<forall> n \<ge> n0. dist (?s n) a < r " by blast}
       
   647     then show ?thesis  unfolding  LIMSEQ_def by blast
       
   648   qed
       
   649 
   412 subsection{* Inverses of formal power series *}
   650 subsection{* Inverses of formal power series *}
   413 
   651 
   414 declare setsum_cong[fundef_cong]
   652 declare setsum_cong[fundef_cong]
   415 
   653 
   416 
   654 
   583       by (auto simp add: of_nat_diff ring_simps)
   821       by (auto simp add: of_nat_diff ring_simps)
   584     finally have "(f * ?D g + ?D f * g) $ n = ?D (f*g) $ n" .}
   822     finally have "(f * ?D g + ?D f * g) $ n = ?D (f*g) $ n" .}
   585   then show ?thesis unfolding fps_eq_iff by auto
   823   then show ?thesis unfolding fps_eq_iff by auto
   586 qed
   824 qed
   587 
   825 
       
   826 lemma fps_deriv_X[simp]: "fps_deriv X = 1"
       
   827   by (simp add: fps_deriv_def X_def fps_eq_iff)
       
   828 
   588 lemma fps_deriv_neg[simp]: "fps_deriv (- (f:: ('a:: comm_ring_1) fps)) = - (fps_deriv f)"
   829 lemma fps_deriv_neg[simp]: "fps_deriv (- (f:: ('a:: comm_ring_1) fps)) = - (fps_deriv f)"
   589   by (simp add: fps_eq_iff fps_deriv_def)
   830   by (simp add: fps_eq_iff fps_deriv_def)
   590 lemma fps_deriv_add[simp]: "fps_deriv ((f:: ('a::comm_ring_1) fps) + g) = fps_deriv f + fps_deriv g"
   831 lemma fps_deriv_add[simp]: "fps_deriv ((f:: ('a::comm_ring_1) fps) + g) = fps_deriv f + fps_deriv g"
   591   using fps_deriv_linear[of 1 f 1 g] by simp
   832   using fps_deriv_linear[of 1 f 1 g] by simp
   592 
   833 
   865   assumes a0: "b$0 \<noteq> 0"
  1106   assumes a0: "b$0 \<noteq> 0"
   866   shows "fps_deriv (a / b) = (fps_deriv a * b - a * fps_deriv b) / b ^ 2"
  1107   shows "fps_deriv (a / b) = (fps_deriv a * b - a * fps_deriv b) / b ^ 2"
   867   using fps_inverse_deriv[OF a0]
  1108   using fps_inverse_deriv[OF a0]
   868   by (simp add: fps_divide_def ring_simps power2_eq_square fps_inverse_mult inverse_mult_eq_1'[OF a0])
  1109   by (simp add: fps_divide_def ring_simps power2_eq_square fps_inverse_mult inverse_mult_eq_1'[OF a0])
   869 
  1110 
   870 subsection{* The eXtractor series X*}
       
   871 
       
   872 lemma minus_one_power_iff: "(- (1::'a :: {comm_ring_1})) ^ n = (if even n then 1 else - 1)"
       
   873   by (induct n, auto)
       
   874 
       
   875 definition "X = Abs_fps (\<lambda>n. if n = 1 then 1 else 0)"
       
   876 
  1111 
   877 lemma fps_inverse_gp': "inverse (Abs_fps(\<lambda>n. (1::'a::field)))
  1112 lemma fps_inverse_gp': "inverse (Abs_fps(\<lambda>n. (1::'a::field)))
   878   = 1 - X"
  1113   = 1 - X"
   879   by (simp add: fps_inverse_gp fps_eq_iff X_def)
  1114   by (simp add: fps_inverse_gp fps_eq_iff X_def)
   880 
  1115 
   881 lemma X_mult_nth[simp]: "(X * (f :: ('a::semiring_1) fps)) $n = (if n = 0 then 0 else f $ (n - 1))"
       
   882 proof-
       
   883   {assume n: "n \<noteq> 0"
       
   884     have fN: "finite {0 .. n}" by simp
       
   885     have "(X * f) $n = (\<Sum>i = 0..n. X $ i * f $ (n - i))" by (simp add: fps_mult_nth)
       
   886     also have "\<dots> = f $ (n - 1)"
       
   887       using n by (simp add: X_def mult_delta_left setsum_delta [OF fN])
       
   888   finally have ?thesis using n by simp }
       
   889   moreover
       
   890   {assume n: "n=0" hence ?thesis by (simp add: fps_mult_nth X_def)}
       
   891   ultimately show ?thesis by blast
       
   892 qed
       
   893 
       
   894 lemma X_mult_right_nth[simp]: "((f :: ('a::comm_semiring_1) fps) * X) $n = (if n = 0 then 0 else f $ (n - 1))"
       
   895   by (metis X_mult_nth mult_commute)
       
   896 
       
   897 lemma X_power_iff: "X^k = Abs_fps (\<lambda>n. if n = k then (1::'a::comm_ring_1) else 0)"
       
   898 proof(induct k)
       
   899   case 0 thus ?case by (simp add: X_def fps_eq_iff)
       
   900 next
       
   901   case (Suc k)
       
   902   {fix m
       
   903     have "(X^Suc k) $ m = (if m = 0 then (0::'a) else (X^k) $ (m - 1))"
       
   904       by (simp add: power_Suc del: One_nat_def)
       
   905     then     have "(X^Suc k) $ m = (if m = Suc k then (1::'a) else 0)"
       
   906       using Suc.hyps by (auto cong del: if_weak_cong)}
       
   907   then show ?case by (simp add: fps_eq_iff)
       
   908 qed
       
   909 
       
   910 lemma X_power_mult_nth: "(X^k * (f :: ('a::comm_ring_1) fps)) $n = (if n < k then 0 else f $ (n - k))"
       
   911   apply (induct k arbitrary: n)
       
   912   apply (simp)
       
   913   unfolding power_Suc mult_assoc
       
   914   by (case_tac n, auto)
       
   915 
       
   916 lemma X_power_mult_right_nth: "((f :: ('a::comm_ring_1) fps) * X^k) $n = (if n < k then 0 else f $ (n - k))"
       
   917   by (metis X_power_mult_nth mult_commute)
       
   918 lemma fps_deriv_X[simp]: "fps_deriv X = 1"
       
   919   by (simp add: fps_deriv_def X_def fps_eq_iff)
       
   920 
       
   921 lemma fps_nth_deriv_X[simp]: "fps_nth_deriv n X = (if n = 0 then X else if n=1 then 1 else 0)"
  1116 lemma fps_nth_deriv_X[simp]: "fps_nth_deriv n X = (if n = 0 then X else if n=1 then 1 else 0)"
   922   by (cases "n", simp_all)
  1117   by (cases "n", simp_all)
   923 
  1118 
   924 lemma X_nth[simp]: "X$n = (if n = 1 then 1 else 0)" by (simp add: X_def)
       
   925 lemma X_power_nth[simp]: "(X^k) $n = (if n = k then 1 else (0::'a::comm_ring_1))"
       
   926   by (simp add: X_power_iff)
       
   927 
  1119 
   928 lemma fps_inverse_X_plus1:
  1120 lemma fps_inverse_X_plus1:
   929   "inverse (1 + X) = Abs_fps (\<lambda>n. (- (1::'a::{field})) ^ n)" (is "_ = ?r")
  1121   "inverse (1 + X) = Abs_fps (\<lambda>n. (- (1::'a::{field})) ^ n)" (is "_ = ?r")
   930 proof-
  1122 proof-
   931   have eq: "(1 + X) * ?r = 1"
  1123   have eq: "(1 + X) * ?r = 1"
  2657 apply (simp del: fps_const_neg fps_const_add fps_const_mult
  2849 apply (simp del: fps_const_neg fps_const_add fps_const_mult
  2658             add: fps_const_add [symmetric] fps_const_neg [symmetric]
  2850             add: fps_const_add [symmetric] fps_const_neg [symmetric]
  2659                  fps_sin_deriv fps_cos_deriv algebra_simps)
  2851                  fps_sin_deriv fps_cos_deriv algebra_simps)
  2660 done
  2852 done
  2661 
  2853 
       
  2854 lemma fps_sin_even: "fps_sin (- c) = - fps_sin c"
       
  2855   by (auto simp add: fps_eq_iff fps_sin_def)
       
  2856 
       
  2857 lemma fps_cos_odd: "fps_cos (- c) = fps_cos c"
       
  2858   by (auto simp add: fps_eq_iff fps_cos_def)
       
  2859 
  2662 definition "fps_tan c = fps_sin c / fps_cos c"
  2860 definition "fps_tan c = fps_sin c / fps_cos c"
  2663 
  2861 
  2664 lemma fps_tan_deriv: "fps_deriv(fps_tan c) = fps_const c/ (fps_cos c ^ 2)"
  2862 lemma fps_tan_deriv: "fps_deriv(fps_tan c) = fps_const c/ (fps_cos c ^ 2)"
  2665 proof-
  2863 proof-
  2666   have th0: "fps_cos c $ 0 \<noteq> 0" by (simp add: fps_cos_def)
  2864   have th0: "fps_cos c $ 0 \<noteq> 0" by (simp add: fps_cos_def)