Formal Laurent series and overhaul of Formal power series (due to Jeremy Sylvestre)
authorManuel Eberl <eberlm@in.tum.de>
Mon Feb 04 17:19:04 2019 +0100 (4 months ago)
changeset 69791195aeee8b30a
parent 69790 154cf64e403e
child 69792 d21789843f01
Formal Laurent series and overhaul of Formal power series (due to Jeremy Sylvestre)
CONTRIBUTORS
NEWS
src/HOL/Computational_Algebra/Computational_Algebra.thy
src/HOL/Computational_Algebra/Formal_Laurent_Series.thy
src/HOL/Computational_Algebra/Formal_Power_Series.thy
src/HOL/Fields.thy
src/HOL/Int.thy
src/HOL/Orderings.thy
src/HOL/Power.thy
     1.1 --- a/CONTRIBUTORS	Mon Feb 04 15:39:37 2019 +0100
     1.2 +++ b/CONTRIBUTORS	Mon Feb 04 17:19:04 2019 +0100
     1.3 @@ -6,6 +6,9 @@
     1.4  Contributions to this Isabelle version
     1.5  --------------------------------------
     1.6  
     1.7 +* February 2019: Jeremy Sylvestre
     1.8 +  Formal Laurent Series and overhaul of Formal power series.
     1.9 +
    1.10  * February 2019: Manuel Eberl
    1.11    Exponentiation by squaring, used to implement "power" in monoid_mult and
    1.12    fast modular exponentiation.
     2.1 --- a/NEWS	Mon Feb 04 15:39:37 2019 +0100
     2.2 +++ b/NEWS	Mon Feb 04 17:19:04 2019 +0100
     2.3 @@ -87,6 +87,9 @@
     2.4  
     2.5  *** HOL ***
     2.6  
     2.7 +* Formal Laurent series and overhaul of Formal power series 
     2.8 +in HOL-Computational_Algebra
     2.9 +
    2.10  * exponentiation by squaring in HOL-Library; used for computing powers in monoid_mult and modular exponentiation in HOL-Number_Theory
    2.11  
    2.12  * more material on residue rings in HOL-Number_Theory:
     3.1 --- a/src/HOL/Computational_Algebra/Computational_Algebra.thy	Mon Feb 04 15:39:37 2019 +0100
     3.2 +++ b/src/HOL/Computational_Algebra/Computational_Algebra.thy	Mon Feb 04 17:19:04 2019 +0100
     3.3 @@ -5,7 +5,7 @@
     3.4  imports
     3.5    Euclidean_Algorithm
     3.6    Factorial_Ring
     3.7 -  Formal_Power_Series
     3.8 +  Formal_Laurent_Series
     3.9    Fraction_Field
    3.10    Fundamental_Theorem_Algebra
    3.11    Group_Closure
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/src/HOL/Computational_Algebra/Formal_Laurent_Series.thy	Mon Feb 04 17:19:04 2019 +0100
     4.3 @@ -0,0 +1,4178 @@
     4.4 +(*
     4.5 +  Title:      HOL/Computational_Algebra/Formal_Laurent_Series.thy
     4.6 +  Author:     Jeremy Sylvestre, University of Alberta (Augustana Campus)
     4.7 +*)
     4.8 +
     4.9 +
    4.10 +section \<open>A formalization of formal Laurent series\<close>
    4.11 +
    4.12 +theory Formal_Laurent_Series
    4.13 +imports
    4.14 +  Polynomial_FPS
    4.15 +begin
    4.16 +
    4.17 +
    4.18 +subsection \<open>The type of formal Laurent series\<close>
    4.19 +
    4.20 +subsubsection \<open>Type definition\<close>
    4.21 +
    4.22 +typedef (overloaded) 'a fls = "{f::int \<Rightarrow> 'a::zero. \<forall>\<^sub>\<infinity> n::nat. f (- int n) = 0}"
    4.23 +  morphisms fls_nth Abs_fls
    4.24 +proof
    4.25 +  show "(\<lambda>x. 0) \<in> {f::int \<Rightarrow> 'a::zero. \<forall>\<^sub>\<infinity> n::nat. f (- int n) = 0}"
    4.26 +    by simp
    4.27 +qed
    4.28 +
    4.29 +setup_lifting type_definition_fls
    4.30 +
    4.31 +unbundle fps_notation
    4.32 +notation fls_nth (infixl "$$" 75)
    4.33 +
    4.34 +lemmas fls_eqI = iffD1[OF fls_nth_inject, OF iffD2, OF fun_eq_iff, OF allI]
    4.35 +
    4.36 +lemma expand_fls_eq: "f = g \<longleftrightarrow> (\<forall>n. f $$ n = g $$ n)"
    4.37 +  by (simp add: fls_nth_inject[symmetric] fun_eq_iff)
    4.38 +
    4.39 +lemma nth_Abs_fls [simp]: "\<forall>\<^sub>\<infinity>n. f (- int n) = 0 \<Longrightarrow> Abs_fls f $$ n = f n"
    4.40 + by (simp add: Abs_fls_inverse[OF CollectI])
    4.41 +
    4.42 +lemmas nth_Abs_fls_finite_nonzero_neg_nth = nth_Abs_fls[OF iffD2, OF eventually_cofinite]
    4.43 +lemmas nth_Abs_fls_ex_nat_lower_bound = nth_Abs_fls[OF iffD2, OF MOST_nat]
    4.44 +lemmas nth_Abs_fls_nat_lower_bound = nth_Abs_fls_ex_nat_lower_bound[OF exI]
    4.45 +
    4.46 +lemma nth_Abs_fls_ex_lower_bound:
    4.47 +  assumes "\<exists>N. \<forall>n<N. f n = 0"
    4.48 +  shows   "Abs_fls f $$ n = f n"
    4.49 +proof (intro nth_Abs_fls_ex_nat_lower_bound)
    4.50 +  from assms obtain N::int where "\<forall>n<N. f n = 0" by fast
    4.51 +  hence "\<forall>n > (if N < 0 then nat (-N) else 0). f (-int n) = 0" by auto
    4.52 +  thus "\<exists>M. \<forall>n>M. f (- int n) = 0" by fast
    4.53 +qed
    4.54 +
    4.55 +lemmas nth_Abs_fls_lower_bound = nth_Abs_fls_ex_lower_bound[OF exI]
    4.56 +
    4.57 +lemmas MOST_fls_neg_nth_eq_0 [simp] = CollectD[OF fls_nth]
    4.58 +lemmas fls_finite_nonzero_neg_nth = iffD1[OF eventually_cofinite MOST_fls_neg_nth_eq_0]
    4.59 +
    4.60 +lemma fls_nth_vanishes_below_natE:
    4.61 +  fixes   f :: "'a::zero fls"
    4.62 +  obtains N :: nat
    4.63 +  where   "\<forall>n>N. f$$(-int n) = 0"
    4.64 +  using   iffD1[OF MOST_nat MOST_fls_neg_nth_eq_0]
    4.65 +  by      blast
    4.66 +
    4.67 +lemma fls_nth_vanishes_belowE:
    4.68 +  fixes   f :: "'a::zero fls"
    4.69 +  obtains N :: int
    4.70 +  where   "\<forall>n<N. f$$n = 0"
    4.71 +proof-
    4.72 +  obtain K :: nat where K: "\<forall>n>K. f$$(-int n) = 0" by (elim fls_nth_vanishes_below_natE)
    4.73 +  have "\<forall>n < -int K. f$$n = 0"
    4.74 +  proof clarify
    4.75 +    fix n assume n: "n < -int K"
    4.76 +    define m where "m \<equiv> nat (-n)"
    4.77 +    with n have "m > K" by simp
    4.78 +    moreover from n m_def have "f$$n = f $$ (-int m)" by simp
    4.79 +    ultimately show "f $$ n = 0" using K by simp
    4.80 +  qed
    4.81 +  thus "(\<And>N. \<forall>n<N. f $$ n = 0 \<Longrightarrow> thesis) \<Longrightarrow> thesis" by fast
    4.82 +qed
    4.83 +
    4.84 +
    4.85 +subsubsection \<open>Definition of basic zero, one, constant, X, and inverse X elements\<close>
    4.86 +
    4.87 +instantiation fls :: (zero) zero
    4.88 +begin
    4.89 +  lift_definition zero_fls :: "'a fls" is "\<lambda>_. 0" by simp
    4.90 +  instance ..
    4.91 +end
    4.92 +
    4.93 +lemma fls_zero_nth [simp]: "0 $$ n = 0"
    4.94 + by (simp add: zero_fls_def)
    4.95 +
    4.96 +lemma fls_zero_eqI: "(\<And>n. f$$n = 0) \<Longrightarrow> f = 0"
    4.97 +  by (fastforce intro: fls_eqI)
    4.98 +
    4.99 +lemma fls_nonzeroI: "f$$n \<noteq> 0 \<Longrightarrow> f \<noteq> 0"
   4.100 +  by auto
   4.101 +
   4.102 +lemma fls_nonzero_nth: "f \<noteq> 0 \<longleftrightarrow> (\<exists> n. f $$ n \<noteq> 0)"
   4.103 +  using fls_zero_eqI by fastforce
   4.104 +
   4.105 +lemma fls_trivial_delta_eq_zero [simp]: "b = 0 \<Longrightarrow> Abs_fls (\<lambda>n. if n=a then b else 0) = 0"
   4.106 +  by (intro fls_zero_eqI) simp
   4.107 +
   4.108 +lemma fls_delta_nth [simp]:
   4.109 +  "Abs_fls (\<lambda>n. if n=a then b else 0) $$ n = (if n=a then b else 0)"
   4.110 +  using nth_Abs_fls_lower_bound[of a "\<lambda>n. if n=a then b else 0"] by simp
   4.111 +
   4.112 +instantiation fls :: ("{zero,one}") one
   4.113 +begin
   4.114 +  lift_definition one_fls :: "'a fls" is "\<lambda>k. if k = 0 then 1 else 0"
   4.115 +    by (simp add: eventually_cofinite)
   4.116 +  instance ..
   4.117 +end
   4.118 +
   4.119 +lemma fls_one_nth [simp]:
   4.120 +  "1 $$ n = (if n = 0 then 1 else 0)"
   4.121 +  by (simp add: one_fls_def eventually_cofinite)
   4.122 +
   4.123 +instance fls :: (zero_neq_one) zero_neq_one
   4.124 +proof (standard, standard)
   4.125 +  assume "(0::'a fls) = (1::'a fls)"
   4.126 +  hence "(0::'a fls) $$ 0 = (1::'a fls) $$ 0" by simp
   4.127 +  thus False by simp
   4.128 +qed
   4.129 +
   4.130 +definition fls_const :: "'a::zero \<Rightarrow> 'a fls"
   4.131 +  where "fls_const c \<equiv> Abs_fls (\<lambda>n. if n = 0 then c else 0)"
   4.132 +
   4.133 +lemma fls_const_nth [simp]: "fls_const c $$ n = (if n = 0 then c else 0)"
   4.134 +  by (simp add: fls_const_def eventually_cofinite)
   4.135 +
   4.136 +lemma fls_const_0 [simp]: "fls_const 0 = 0"
   4.137 +  unfolding fls_const_def using fls_trivial_delta_eq_zero by fast
   4.138 +
   4.139 +lemma fls_const_nonzero: "c \<noteq> 0 \<Longrightarrow> fls_const c \<noteq> 0"
   4.140 +  using fls_nonzeroI[of "fls_const c" 0] by simp
   4.141 +
   4.142 +lemma fls_const_1 [simp]: "fls_const 1 = 1"
   4.143 +  unfolding fls_const_def one_fls_def ..
   4.144 +
   4.145 +lift_definition fls_X :: "'a::{zero,one} fls"
   4.146 +  is "\<lambda>n. if n = 1 then 1 else 0"
   4.147 +  by simp
   4.148 +
   4.149 +lemma fls_X_nth [simp]:
   4.150 +  "fls_X $$ n = (if n = 1 then 1 else 0)"
   4.151 +  by (simp add: fls_X_def)
   4.152 +
   4.153 +lemma fls_X_nonzero [simp]: "(fls_X :: 'a :: zero_neq_one fls) \<noteq> 0"
   4.154 +  by (intro fls_nonzeroI) simp
   4.155 +
   4.156 +lift_definition fls_X_inv :: "'a::{zero,one} fls"
   4.157 +  is "\<lambda>n. if n = -1 then 1 else 0"
   4.158 +  by (simp add: eventually_cofinite)
   4.159 +
   4.160 +lemma fls_X_inv_nth [simp]:
   4.161 +  "fls_X_inv $$ n = (if n = -1 then 1 else 0)"
   4.162 +  by (simp add: fls_X_inv_def eventually_cofinite)
   4.163 +
   4.164 +lemma fls_X_inv_nonzero [simp]: "(fls_X_inv :: 'a :: zero_neq_one fls) \<noteq> 0"
   4.165 +  by (intro fls_nonzeroI) simp
   4.166 +
   4.167 +
   4.168 +subsection \<open>Subdegrees\<close>
   4.169 +
   4.170 +lemma unique_fls_subdegree:
   4.171 +  assumes "f \<noteq> 0"
   4.172 +  shows   "\<exists>!n. f$$n \<noteq> 0 \<and> (\<forall>m. f$$m \<noteq> 0 \<longrightarrow> n \<le> m)"
   4.173 +proof-
   4.174 +  obtain N::nat where N: "\<forall>n>N. f$$(-int n) = 0" by (elim fls_nth_vanishes_below_natE)
   4.175 +  define M where "M \<equiv> -int N"
   4.176 +  have M: "\<And>m. f$$m \<noteq> 0 \<Longrightarrow> M \<le> m"
   4.177 +  proof-
   4.178 +    fix m assume m: "f$$m \<noteq> 0"
   4.179 +    show "M \<le> m"
   4.180 +    proof (cases "m<0")
   4.181 +      case True with m N M_def show ?thesis
   4.182 +        using allE[OF N, of "nat (-m)" False] by force
   4.183 +    qed (simp add: M_def)
   4.184 +  qed
   4.185 +  have "\<not> (\<forall>k::nat. f$$(M + int k) = 0)"
   4.186 +  proof
   4.187 +    assume above0: "\<forall>k::nat. f$$(M + int k) = 0"
   4.188 +    have "f=0"
   4.189 +    proof (rule fls_zero_eqI)
   4.190 +      fix n show "f$$n = 0"
   4.191 +      proof (cases "M \<le> n")
   4.192 +        case True
   4.193 +        define k where "k = nat (n - M)"
   4.194 +        from True have "n = M + int k" by (simp add: k_def)
   4.195 +        with above0 show ?thesis by simp
   4.196 +      next
   4.197 +        case False with M show ?thesis by auto
   4.198 +      qed
   4.199 +    qed
   4.200 +    with assms show False by fast
   4.201 +  qed
   4.202 +  hence ex_k: "\<exists>k::nat. f$$(M + int k) \<noteq> 0" by fast
   4.203 +  define k where "k \<equiv> (LEAST k::nat. f$$(M + int k) \<noteq> 0)"
   4.204 +  define n where "n \<equiv> M + int k"
   4.205 +  from k_def n_def have fn: "f$$n \<noteq> 0" using LeastI_ex[OF ex_k] by simp
   4.206 +  moreover have "\<forall>m. f$$m \<noteq> 0 \<longrightarrow> n \<le> m"
   4.207 +  proof (clarify)
   4.208 +    fix m assume m: "f$$m \<noteq> 0"
   4.209 +    with M have "M \<le> m" by fast
   4.210 +    define l where "l = nat (m - M)"
   4.211 +    from \<open>M \<le> m\<close> have l: "m = M + int l" by (simp add: l_def)
   4.212 +    with n_def m k_def l show "n \<le> m"
   4.213 +      using Least_le[of "\<lambda>k. f$$(M + int k) \<noteq> 0" l] by auto
   4.214 +  qed
   4.215 +  moreover have "\<And>n'. f$$n' \<noteq> 0 \<Longrightarrow> (\<forall>m. f$$m \<noteq> 0 \<longrightarrow> n' \<le> m) \<Longrightarrow> n' = n"
   4.216 +  proof-
   4.217 +    fix n' :: int
   4.218 +    assume n': "f$$n' \<noteq> 0" "\<forall>m. f$$m \<noteq> 0 \<longrightarrow> n' \<le> m"
   4.219 +    from n'(1) M have "M \<le> n'" by fast
   4.220 +    define l where "l = nat (n' - M)"
   4.221 +    from \<open>M \<le> n'\<close> have l: "n' = M + int l" by (simp add: l_def)
   4.222 +    with n_def k_def n' fn show "n' = n"
   4.223 +      using Least_le[of "\<lambda>k. f$$(M + int k) \<noteq> 0" l] by force
   4.224 +  qed
   4.225 +  ultimately show ?thesis
   4.226 +    using ex1I[of "\<lambda>n. f$$n \<noteq> 0 \<and> (\<forall>m. f$$m \<noteq> 0 \<longrightarrow> n \<le> m)" n] by blast
   4.227 +qed
   4.228 +
   4.229 +definition fls_subdegree :: "('a::zero) fls \<Rightarrow> int"
   4.230 +  where "fls_subdegree f \<equiv> (if f = 0 then 0 else LEAST n::int. f$$n \<noteq> 0)"
   4.231 +
   4.232 +lemma fls_zero_subdegree [simp]: "fls_subdegree 0 = 0"
   4.233 +  by (simp add: fls_subdegree_def)
   4.234 +
   4.235 +lemma nth_fls_subdegree_nonzero [simp]: "f \<noteq> 0 \<Longrightarrow> f $$ fls_subdegree f \<noteq> 0"
   4.236 +  using Least1I[OF unique_fls_subdegree] by (simp add: fls_subdegree_def)
   4.237 +
   4.238 +lemma nth_fls_subdegree_zero_iff: "(f $$ fls_subdegree f = 0) \<longleftrightarrow> (f = 0)"
   4.239 +  using nth_fls_subdegree_nonzero by auto
   4.240 +
   4.241 +lemma fls_subdegree_leI: "f $$ n \<noteq> 0 \<Longrightarrow> fls_subdegree f \<le> n"
   4.242 +  using Least1_le[OF unique_fls_subdegree]
   4.243 +  by    (auto simp: fls_subdegree_def)
   4.244 +
   4.245 +lemma fls_subdegree_leI': "f $$ n \<noteq> 0 \<Longrightarrow> n \<le> m \<Longrightarrow> fls_subdegree f \<le> m"
   4.246 +  using fls_subdegree_leI by fastforce
   4.247 +
   4.248 +lemma fls_eq0_below_subdegree [simp]: "n < fls_subdegree f \<Longrightarrow> f $$ n = 0"
   4.249 +  using fls_subdegree_leI by fastforce
   4.250 +
   4.251 +lemma fls_subdegree_geI: "f \<noteq> 0 \<Longrightarrow> (\<And>k. k < n \<Longrightarrow> f $$ k = 0) \<Longrightarrow> n \<le> fls_subdegree f"
   4.252 +  using nth_fls_subdegree_nonzero by force
   4.253 +
   4.254 +lemma fls_subdegree_ge0I: "(\<And>k. k < 0 \<Longrightarrow> f $$ k = 0) \<Longrightarrow> 0 \<le> fls_subdegree f"
   4.255 +  using fls_subdegree_geI[of f 0] by (cases "f=0") auto
   4.256 +
   4.257 +lemma fls_subdegree_greaterI:
   4.258 +  assumes "f \<noteq> 0" "\<And>k. k \<le> n \<Longrightarrow> f $$ k = 0"
   4.259 +  shows   "n < fls_subdegree f"
   4.260 +  using   assms(1) assms(2)[of "fls_subdegree f"] nth_fls_subdegree_nonzero[of f]
   4.261 +  by      force
   4.262 +
   4.263 +lemma fls_subdegree_eqI: "f $$ n \<noteq> 0 \<Longrightarrow> (\<And>k. k < n \<Longrightarrow> f $$ k = 0) \<Longrightarrow> fls_subdegree f = n"
   4.264 +  using fls_subdegree_leI fls_subdegree_geI[of f]
   4.265 +  by    fastforce
   4.266 +
   4.267 +lemma fls_delta_subdegree [simp]:
   4.268 +  "b \<noteq> 0 \<Longrightarrow> fls_subdegree (Abs_fls (\<lambda>n. if n=a then b else 0)) = a"
   4.269 +  by (intro fls_subdegree_eqI) simp_all
   4.270 +
   4.271 +lemma fls_delta0_subdegree: "fls_subdegree (Abs_fls (\<lambda>n. if n=0 then a else 0)) = 0"
   4.272 +  by (cases "a=0") simp_all
   4.273 +
   4.274 +lemma fls_one_subdegree [simp]: "fls_subdegree 1 = 0"
   4.275 +  by (auto intro: fls_delta0_subdegree simp: one_fls_def)
   4.276 +
   4.277 +lemma fls_const_subdegree [simp]: "fls_subdegree (fls_const c) = 0"
   4.278 +  by (cases "c=0") (auto intro: fls_subdegree_eqI)
   4.279 +
   4.280 +lemma fls_X_subdegree [simp]: "fls_subdegree (fls_X::'a::{zero_neq_one} fls) = 1"
   4.281 +  by (intro fls_subdegree_eqI) simp_all
   4.282 +
   4.283 +lemma fls_X_inv_subdegree [simp]: "fls_subdegree (fls_X_inv::'a::{zero_neq_one} fls) = -1"
   4.284 +  by (intro fls_subdegree_eqI) simp_all
   4.285 +
   4.286 +lemma fls_eq_above_subdegreeI:
   4.287 +  assumes "N \<le> fls_subdegree f" "N \<le> fls_subdegree g" "\<forall>k\<ge>N. f $$ k = g $$ k"
   4.288 +  shows   "f = g"
   4.289 +proof (rule fls_eqI)
   4.290 +  fix n from assms show "f $$ n = g $$ n" by (cases "n < N") auto
   4.291 +qed
   4.292 +
   4.293 +
   4.294 +subsection \<open>Shifting\<close>
   4.295 +
   4.296 +subsubsection \<open>Shift definition\<close>
   4.297 +
   4.298 +definition fls_shift :: "int \<Rightarrow> ('a::zero) fls \<Rightarrow> 'a fls"
   4.299 +  where "fls_shift n f \<equiv> Abs_fls (\<lambda>k. f $$ (k+n))"
   4.300 +\<comment> \<open>Since the index set is unbounded in both directions, we can shift in either direction.\<close>
   4.301 +
   4.302 +lemma fls_shift_nth [simp]: "fls_shift m f $$ n = f $$ (n+m)"
   4.303 +  unfolding fls_shift_def
   4.304 +proof (rule nth_Abs_fls_ex_lower_bound)
   4.305 +  obtain K::int where K: "\<forall>n<K. f$$n = 0" by (elim fls_nth_vanishes_belowE)
   4.306 +  hence "\<forall>n<K-m. f$$(n+m) = 0" by auto
   4.307 +  thus "\<exists>N. \<forall>n<N. f $$ (n + m) = 0" by fast
   4.308 +qed
   4.309 +
   4.310 +lemma fls_shift_eq_iff: "(fls_shift m f = fls_shift m g) \<longleftrightarrow> (f = g)"
   4.311 +proof (rule iffI, rule fls_eqI)
   4.312 +  fix k
   4.313 +  assume 1: "fls_shift m f = fls_shift m g"
   4.314 +  have "f $$ k = fls_shift m g $$ (k - m)" by (simp add: 1[symmetric])  
   4.315 +  thus "f $$ k = g $$ k" by simp
   4.316 +qed (intro fls_eqI, simp)
   4.317 +
   4.318 +lemma fls_shift_0 [simp]: "fls_shift 0 f = f"
   4.319 +  by (intro fls_eqI) simp
   4.320 +
   4.321 +lemma fls_shift_subdegree [simp]:
   4.322 +  "f \<noteq> 0 \<Longrightarrow> fls_subdegree (fls_shift n f) = fls_subdegree f - n"
   4.323 +  by (intro fls_subdegree_eqI) simp_all
   4.324 +
   4.325 +lemma fls_shift_fls_shift [simp]: "fls_shift m (fls_shift k f) = fls_shift (k+m) f"
   4.326 +  by (intro fls_eqI) (simp add: algebra_simps)
   4.327 +
   4.328 +lemma fls_shift_fls_shift_reorder:
   4.329 +  "fls_shift m (fls_shift k f) = fls_shift k (fls_shift m f)"
   4.330 +  using fls_shift_fls_shift[of m k f] fls_shift_fls_shift[of k m f] by (simp add: add.commute)
   4.331 +
   4.332 +lemma fls_shift_zero [simp]: "fls_shift m 0 = 0"
   4.333 +  by (intro fls_zero_eqI) simp
   4.334 +
   4.335 +lemma fls_shift_eq0_iff: "fls_shift m f = 0 \<longleftrightarrow> f = 0"
   4.336 +  using fls_shift_eq_iff[of m f 0] by simp
   4.337 +
   4.338 +lemma fls_shift_nonneg_subdegree: "m \<le> fls_subdegree f \<Longrightarrow> fls_subdegree (fls_shift m f) \<ge> 0"
   4.339 +  by (cases "f=0") (auto intro: fls_subdegree_geI)
   4.340 +
   4.341 +lemma fls_shift_delta:
   4.342 +  "fls_shift m (Abs_fls (\<lambda>n. if n=a then b else 0)) = Abs_fls (\<lambda>n. if n=a-m then b else 0)"
   4.343 +  by (intro fls_eqI) simp
   4.344 +
   4.345 +lemma fls_shift_const:
   4.346 +  "fls_shift m (fls_const c) = Abs_fls (\<lambda>n. if n=-m then c else 0)"
   4.347 +  by (intro fls_eqI) simp
   4.348 +
   4.349 +lemma fls_shift_const_nth:
   4.350 +  "fls_shift m (fls_const c) $$ n = (if n=-m then c else 0)"
   4.351 +  by (simp add: fls_shift_const)
   4.352 +
   4.353 +lemma fls_X_conv_shift_1: "fls_X = fls_shift (-1) 1"
   4.354 +  by (intro fls_eqI) simp
   4.355 +
   4.356 +lemma fls_X_shift_to_one [simp]: "fls_shift 1 fls_X = 1"
   4.357 +  using fls_shift_fls_shift[of "-1" 1 1] by (simp add: fls_X_conv_shift_1)
   4.358 +
   4.359 +lemma fls_X_inv_conv_shift_1: "fls_X_inv = fls_shift 1 1"
   4.360 +  by (intro fls_eqI) simp
   4.361 +
   4.362 +lemma fls_X_inv_shift_to_one [simp]: "fls_shift (-1) fls_X_inv = 1"
   4.363 +  using fls_shift_fls_shift[of 1 "-1" 1] by (simp add: fls_X_inv_conv_shift_1)
   4.364 +
   4.365 +lemma fls_X_fls_X_inv_conv:
   4.366 +  "fls_X = fls_shift (-2) fls_X_inv" "fls_X_inv = fls_shift 2 fls_X"
   4.367 +  by (simp_all add: fls_X_conv_shift_1 fls_X_inv_conv_shift_1)
   4.368 +
   4.369 +
   4.370 +subsubsection \<open>Base factor\<close>
   4.371 +
   4.372 +text \<open>
   4.373 +  Similarly to the @{const unit_factor} for formal power series, we can decompose a formal Laurent
   4.374 +  series as a power of the implied variable times a series of subdegree 0.
   4.375 +  (See lemma @{text "fls_base_factor_X_power_decompose"}.)
   4.376 +  But we will call this something other @{const unit_factor}
   4.377 +  because it will not satisfy assumption @{text "is_unit_unit_factor"} of
   4.378 +  @{class semidom_divide_unit_factor}.
   4.379 +\<close>
   4.380 +
   4.381 +definition fls_base_factor :: "('a::zero) fls \<Rightarrow> 'a fls"
   4.382 +  where fls_base_factor_def[simp]: "fls_base_factor f = fls_shift (fls_subdegree f) f"
   4.383 +
   4.384 +lemma fls_base_factor_nth: "fls_base_factor f $$ n = f $$ (n + fls_subdegree f)"
   4.385 +  by simp
   4.386 +
   4.387 +lemma fls_base_factor_nonzero [simp]: "f \<noteq> 0 \<Longrightarrow> fls_base_factor f \<noteq> 0"
   4.388 +  using fls_nonzeroI[of "fls_base_factor f" 0] by simp
   4.389 +
   4.390 +lemma fls_base_factor_subdegree [simp]: "fls_subdegree (fls_base_factor f) = 0"
   4.391 + by (cases "f=0") auto
   4.392 +
   4.393 +lemma fls_base_factor_base [simp]:
   4.394 +  "fls_base_factor f $$ fls_subdegree (fls_base_factor f) = f $$ fls_subdegree f"
   4.395 +  using fls_base_factor_subdegree[of f] by simp
   4.396 +
   4.397 +lemma fls_conv_base_factor_shift_subdegree:
   4.398 +  "f = fls_shift (-fls_subdegree f) (fls_base_factor f)"
   4.399 +  by simp
   4.400 +
   4.401 +lemma fls_base_factor_idem:
   4.402 +  "fls_base_factor (fls_base_factor (f::'a::zero fls)) = fls_base_factor f"
   4.403 +  using fls_base_factor_subdegree[of f] by simp
   4.404 +
   4.405 +lemma fls_base_factor_zero: "fls_base_factor (0::'a::zero fls) = 0"
   4.406 +  by simp
   4.407 +
   4.408 +lemma fls_base_factor_zero_iff: "fls_base_factor (f::'a::zero fls) = 0 \<longleftrightarrow> f = 0"
   4.409 +proof
   4.410 +  have "fls_shift (-fls_subdegree f) (fls_shift (fls_subdegree f) f) = f" by simp
   4.411 +  thus "fls_base_factor f = 0 \<Longrightarrow> f=0" by simp
   4.412 +qed simp
   4.413 +
   4.414 +lemma fls_base_factor_nth_0: "f \<noteq> 0 \<Longrightarrow> fls_base_factor f $$ 0 \<noteq> 0"
   4.415 +  by simp
   4.416 +
   4.417 +lemma fls_base_factor_one: "fls_base_factor (1::'a::{zero,one} fls) = 1"
   4.418 +  by simp
   4.419 +
   4.420 +lemma fls_base_factor_const: "fls_base_factor (fls_const c) = fls_const c"
   4.421 +  by simp
   4.422 +
   4.423 +lemma fls_base_factor_delta:
   4.424 +  "fls_base_factor (Abs_fls (\<lambda>n. if n=a then c else 0)) = fls_const c"
   4.425 +  by  (cases "c=0") (auto intro: fls_eqI)
   4.426 +
   4.427 +lemma fls_base_factor_X: "fls_base_factor (fls_X::'a::{zero_neq_one} fls) = 1"
   4.428 +   by simp
   4.429 +
   4.430 +lemma fls_base_factor_X_inv: "fls_base_factor (fls_X_inv::'a::{zero_neq_one} fls) = 1"
   4.431 +   by simp
   4.432 +
   4.433 +lemma fls_base_factor_shift [simp]: "fls_base_factor (fls_shift n f) = fls_base_factor f"
   4.434 +  by (cases "f=0") simp_all
   4.435 +
   4.436 +
   4.437 +subsection \<open>Conversion between formal power and Laurent series\<close>
   4.438 +
   4.439 +subsubsection \<open>Converting Laurent to power series\<close>
   4.440 +
   4.441 +text \<open>
   4.442 +  We can truncate a Laurent series at index 0 to create a power series, called the regular part.
   4.443 +\<close>
   4.444 +
   4.445 +lift_definition fls_regpart :: "('a::zero) fls \<Rightarrow> 'a fps"
   4.446 +  is "\<lambda>f. Abs_fps (\<lambda>n. f (int n))"
   4.447 +  .
   4.448 +
   4.449 +lemma fls_regpart_nth [simp]: "fls_regpart f $ n = f $$ (int n)"
   4.450 +  by (simp add: fls_regpart_def)
   4.451 +
   4.452 +lemma fls_regpart_zero [simp]: "fls_regpart 0 = 0"
   4.453 +  by (intro fps_ext) simp
   4.454 +
   4.455 +lemma fls_regpart_one [simp]: "fls_regpart 1 = 1"
   4.456 +  by (intro fps_ext) simp
   4.457 +
   4.458 +lemma fls_regpart_Abs_fls:
   4.459 +  "\<forall>\<^sub>\<infinity>n. F (- int n) = 0 \<Longrightarrow> fls_regpart (Abs_fls F) = Abs_fps (\<lambda>n. F (int n))"
   4.460 +  by (intro fps_ext) auto
   4.461 +
   4.462 +lemma fls_regpart_delta:
   4.463 +  "fls_regpart (Abs_fls (\<lambda>n. if n=a then b else 0)) =
   4.464 +    (if a < 0 then 0 else Abs_fps (\<lambda>n. if n=nat a then b else 0))"
   4.465 +  by (rule fps_ext, auto)
   4.466 +
   4.467 +lemma fls_regpart_const [simp]: "fls_regpart (fls_const c) = fps_const c"
   4.468 +  by (intro fps_ext) simp
   4.469 +
   4.470 +lemma fls_regpart_fls_X [simp]: "fls_regpart fls_X = fps_X"
   4.471 +  by (intro fps_ext) simp
   4.472 +
   4.473 +lemma fls_regpart_fls_X_inv [simp]: "fls_regpart fls_X_inv = 0"
   4.474 +  by (intro fps_ext) simp
   4.475 +
   4.476 +lemma fls_regpart_eq0_imp_nonpos_subdegree:
   4.477 +  assumes "fls_regpart f = 0"
   4.478 +  shows   "fls_subdegree f \<le> 0"
   4.479 +proof (cases "f=0")
   4.480 +  case False
   4.481 +  have "fls_subdegree f \<ge> 0 \<Longrightarrow> f $$ fls_subdegree f = 0"
   4.482 +  proof-
   4.483 +    assume "fls_subdegree f \<ge> 0"
   4.484 +    hence "f $$ (fls_subdegree f) = (fls_regpart f) $ (nat (fls_subdegree f))" by simp
   4.485 +    with assms show "f $$ (fls_subdegree f) = 0" by simp
   4.486 +  qed
   4.487 +  with False show ?thesis by fastforce
   4.488 +qed simp
   4.489 +
   4.490 +lemma fls_subdegree_lt_fls_regpart_subdegree:
   4.491 +  "fls_subdegree f \<le> int (subdegree (fls_regpart f))"
   4.492 +  using fls_subdegree_leI nth_subdegree_nonzero[of "fls_regpart f"]
   4.493 +  by    (cases "(fls_regpart f) = 0")
   4.494 +        (simp_all add: fls_regpart_eq0_imp_nonpos_subdegree)
   4.495 +
   4.496 +lemma fls_regpart_subdegree_conv:
   4.497 +  assumes "fls_subdegree f \<ge> 0"
   4.498 +  shows   "subdegree (fls_regpart f) = nat (fls_subdegree f)"
   4.499 +\<comment>\<open>
   4.500 +  This is the best we can do since if the subdegree is negative, we might still have the bad luck
   4.501 +  that the term at index 0 is equal to 0.
   4.502 +\<close>
   4.503 +proof (cases "f=0")
   4.504 +  case False with assms show ?thesis by (intro subdegreeI) simp_all
   4.505 +qed simp
   4.506 +
   4.507 +lemma fls_eq_conv_fps_eqI:
   4.508 +  assumes "0 \<le> fls_subdegree f" "0 \<le> fls_subdegree g" "fls_regpart f = fls_regpart g"
   4.509 +  shows   "f = g"
   4.510 +proof (rule fls_eq_above_subdegreeI, rule assms(1), rule assms(2), clarify)
   4.511 +  fix k::int assume "0 \<le> k"
   4.512 +  with assms(3) show "f $$ k = g $$ k"
   4.513 +    using fls_regpart_nth[of f "nat k"] fls_regpart_nth[of g] by simp
   4.514 +qed
   4.515 +
   4.516 +lemma fls_regpart_shift_conv_fps_shift:
   4.517 +  "m \<ge> 0 \<Longrightarrow> fls_regpart (fls_shift m f) = fps_shift (nat m) (fls_regpart f)"
   4.518 +  by (intro fps_ext) simp_all
   4.519 +
   4.520 +lemma fps_shift_fls_regpart_conv_fls_shift:
   4.521 +  "fps_shift m (fls_regpart f) = fls_regpart (fls_shift m f)"
   4.522 +  by (intro fps_ext) simp_all
   4.523 +
   4.524 +lemma fps_unit_factor_fls_regpart:
   4.525 +  "fls_subdegree f \<ge> 0 \<Longrightarrow> unit_factor (fls_regpart f) = fls_regpart (fls_base_factor f)"
   4.526 +  by (auto intro: fps_ext simp: fls_regpart_subdegree_conv)
   4.527 +
   4.528 +text \<open>
   4.529 +  The terms below the zeroth form a polynomial in the inverse of the implied variable,
   4.530 +  called the principle part.
   4.531 +\<close>
   4.532 +
   4.533 +lift_definition fls_prpart :: "('a::zero) fls \<Rightarrow> 'a poly"
   4.534 +  is "\<lambda>f. Abs_poly (\<lambda>n. if n = 0 then 0 else f (- int n))"
   4.535 +  .
   4.536 +
   4.537 +lemma fls_prpart_coeff [simp]: "coeff (fls_prpart f) n = (if n = 0 then 0 else f $$ (- int n))"
   4.538 +proof-
   4.539 +  have "{x. (if x = 0 then 0 else f $$ - int x) \<noteq> 0} \<subseteq> {x. f $$ - int x \<noteq> 0}"
   4.540 +    by auto
   4.541 +  hence "finite {x. (if x = 0 then 0 else f $$ - int x) \<noteq> 0}"
   4.542 +    using fls_finite_nonzero_neg_nth[of f] by (simp add: rev_finite_subset)
   4.543 +  hence "coeff (fls_prpart f) = (\<lambda>n. if n = 0 then 0 else f $$ (- int n))"
   4.544 +    using Abs_poly_inverse[OF CollectI, OF iffD2, OF eventually_cofinite]
   4.545 +    by (simp add: fls_prpart_def)
   4.546 +  thus ?thesis by simp
   4.547 +qed
   4.548 +
   4.549 +lemma fls_prpart_eq0_iff: "(fls_prpart f = 0) \<longleftrightarrow> (fls_subdegree f \<ge> 0)"
   4.550 +proof
   4.551 +  assume 1: "fls_prpart f = 0"
   4.552 +  show "fls_subdegree f \<ge> 0"
   4.553 +  proof (intro fls_subdegree_ge0I)
   4.554 +    fix k::int assume "k < 0"
   4.555 +    with 1 show "f $$ k = 0" using fls_prpart_coeff[of f "nat (-k)"] by simp
   4.556 +  qed
   4.557 +qed (intro poly_eqI, simp)
   4.558 +
   4.559 +lemma fls_prpart0 [simp]: "fls_prpart 0 = 0"
   4.560 +  by (simp add: fls_prpart_eq0_iff)
   4.561 +
   4.562 +lemma fls_prpart_one [simp]: "fls_prpart 1 = 0"
   4.563 +  by (simp add: fls_prpart_eq0_iff)
   4.564 +
   4.565 +lemma fls_prpart_delta:
   4.566 +  "fls_prpart (Abs_fls (\<lambda>n. if n=a then b else 0)) =
   4.567 +    (if a<0 then Poly (replicate (nat (-a)) 0 @ [b]) else 0)"
   4.568 +  by (intro poly_eqI) (auto simp: nth_default_def nth_append)
   4.569 +
   4.570 +lemma fls_prpart_const [simp]: "fls_prpart (fls_const c) = 0"
   4.571 +  by (simp add: fls_prpart_eq0_iff)
   4.572 +
   4.573 +lemma fls_prpart_X [simp]: "fls_prpart fls_X = 0"
   4.574 +  by (intro poly_eqI) simp
   4.575 +
   4.576 +lemma fls_prpart_X_inv: "fls_prpart fls_X_inv = [:0,1:]"
   4.577 +proof (intro poly_eqI)
   4.578 +  fix n show "coeff (fls_prpart fls_X_inv) n = coeff [:0,1:] n"
   4.579 +  proof (cases n)
   4.580 +    case (Suc i) thus ?thesis by (cases i) simp_all
   4.581 +  qed simp
   4.582 +qed
   4.583 +
   4.584 +lemma degree_fls_prpart [simp]:
   4.585 +  "degree (fls_prpart f) = nat (-fls_subdegree f)"
   4.586 +proof (cases "f=0")
   4.587 +  case False show ?thesis unfolding degree_def
   4.588 +  proof (intro Least_equality)
   4.589 +    fix N assume N: "\<forall>i>N. coeff (fls_prpart f) i = 0"
   4.590 +    have "\<forall>i < -int N. f $$ i = 0"
   4.591 +    proof clarify
   4.592 +      fix i assume i: "i < -int N"
   4.593 +      hence "nat (-i) > N" by simp
   4.594 +      with N i show "f $$ i = 0" using fls_prpart_coeff[of f "nat (-i)"] by auto
   4.595 +    qed
   4.596 +    with False have "fls_subdegree f \<ge> -int N" using fls_subdegree_geI by auto
   4.597 +    thus "nat (- fls_subdegree f) \<le> N" by simp
   4.598 +  qed auto
   4.599 +qed simp
   4.600 +
   4.601 +lemma fls_prpart_shift:
   4.602 +  assumes "m \<le> 0"
   4.603 +  shows   "fls_prpart (fls_shift m f) = pCons 0 (poly_shift (Suc (nat (-m))) (fls_prpart f))"
   4.604 +proof (intro poly_eqI)
   4.605 +  fix n
   4.606 +  define LHS RHS
   4.607 +    where "LHS \<equiv> fls_prpart (fls_shift m f)"
   4.608 +    and   "RHS \<equiv> pCons 0 (poly_shift (Suc (nat (-m))) (fls_prpart f))"
   4.609 +  show "coeff LHS n = coeff RHS n"
   4.610 +  proof (cases n)
   4.611 +    case (Suc k)
   4.612 +    from assms have 1: "-int (Suc k + nat (-m)) = -int (Suc k) + m" by simp
   4.613 +    have "coeff RHS n = f $$ (-int (Suc k) + m)"
   4.614 +      using arg_cong[OF 1, of "($$) f"] by (simp add: Suc RHS_def coeff_poly_shift)
   4.615 +    with Suc show ?thesis by (simp add: LHS_def)
   4.616 +  qed (simp add: LHS_def RHS_def)
   4.617 +qed
   4.618 +
   4.619 +lemma fls_prpart_base_factor: "fls_prpart (fls_base_factor f) = 0"
   4.620 +  using fls_base_factor_subdegree[of f] by (simp add: fls_prpart_eq0_iff)
   4.621 +
   4.622 +text \<open>The essential data of a formal Laurant series resides from the subdegree up.\<close>
   4.623 +
   4.624 +abbreviation fls_base_factor_to_fps :: "('a::zero) fls \<Rightarrow> 'a fps"
   4.625 +  where "fls_base_factor_to_fps f \<equiv> fls_regpart (fls_base_factor f)"
   4.626 +
   4.627 +lemma fls_base_factor_to_fps_conv_fps_shift:
   4.628 +  assumes "fls_subdegree f \<ge> 0"
   4.629 +  shows   "fls_base_factor_to_fps f = fps_shift (nat (fls_subdegree f)) (fls_regpart f)"
   4.630 +  by (simp add: assms fls_regpart_shift_conv_fps_shift)
   4.631 +
   4.632 +lemma fls_base_factor_to_fps_nth:
   4.633 +  "fls_base_factor_to_fps f $ n = f $$ (fls_subdegree f + int n)"
   4.634 +  by (simp add: algebra_simps)
   4.635 +
   4.636 +lemma fls_base_factor_to_fps_base: "f \<noteq> 0 \<Longrightarrow> fls_base_factor_to_fps f $ 0 \<noteq> 0"
   4.637 +  by simp
   4.638 +
   4.639 +lemma fls_base_factor_to_fps_nonzero: "f \<noteq> 0 \<Longrightarrow> fls_base_factor_to_fps f \<noteq> 0"
   4.640 +  using fps_nonzeroI[of "fls_base_factor_to_fps f" 0] fls_base_factor_to_fps_base by simp
   4.641 +
   4.642 +lemma fls_base_factor_to_fps_subdegree [simp]: "subdegree (fls_base_factor_to_fps f) = 0"
   4.643 +  by (cases "f=0") auto
   4.644 +
   4.645 +lemma fls_base_factor_to_fps_trivial:
   4.646 +  "fls_subdegree f = 0 \<Longrightarrow> fls_base_factor_to_fps f = fls_regpart f"
   4.647 +  by simp
   4.648 +
   4.649 +lemma fls_base_factor_to_fps_zero: "fls_base_factor_to_fps 0 = 0"
   4.650 +  by simp
   4.651 +
   4.652 +lemma fls_base_factor_to_fps_one: "fls_base_factor_to_fps 1 = 1"
   4.653 +  by simp
   4.654 +
   4.655 +lemma fls_base_factor_to_fps_delta:
   4.656 +  "fls_base_factor_to_fps (Abs_fls (\<lambda>n. if n=a then c else 0)) = fps_const c"
   4.657 +  using fls_base_factor_delta[of a c] by simp
   4.658 +
   4.659 +lemma fls_base_factor_to_fps_const:
   4.660 +  "fls_base_factor_to_fps (fls_const c) = fps_const c"
   4.661 +  by simp
   4.662 +
   4.663 +lemma fls_base_factor_to_fps_X:
   4.664 +  "fls_base_factor_to_fps (fls_X::'a::{zero_neq_one} fls) = 1"
   4.665 +  by simp
   4.666 +
   4.667 +lemma fls_base_factor_to_fps_X_inv:
   4.668 +  "fls_base_factor_to_fps (fls_X_inv::'a::{zero_neq_one} fls) = 1"
   4.669 +  by simp
   4.670 +
   4.671 +lemma fls_base_factor_to_fps_shift:
   4.672 +  "fls_base_factor_to_fps (fls_shift m f) = fls_base_factor_to_fps f"
   4.673 +  using fls_base_factor_shift[of m f] by simp
   4.674 +
   4.675 +lemma fls_base_factor_to_fps_base_factor:
   4.676 +  "fls_base_factor_to_fps (fls_base_factor f) = fls_base_factor_to_fps f"
   4.677 +  using fls_base_factor_to_fps_shift by simp
   4.678 +
   4.679 +lemma fps_unit_factor_fls_base_factor:
   4.680 +  "unit_factor (fls_base_factor_to_fps f) = fls_base_factor_to_fps f"
   4.681 +  using fls_base_factor_to_fps_subdegree[of f] by simp
   4.682 +
   4.683 +subsubsection \<open>Converting power to Laurent series\<close>
   4.684 +
   4.685 +text \<open>We can extend a power series by 0s below to create a Laurent series.\<close>
   4.686 +
   4.687 +definition fps_to_fls :: "('a::zero) fps \<Rightarrow> 'a fls"
   4.688 +  where "fps_to_fls f \<equiv> Abs_fls (\<lambda>k::int. if k<0 then 0 else f $ (nat k))"
   4.689 +
   4.690 +lemma fps_to_fls_nth [simp]:
   4.691 +  "(fps_to_fls f) $$ n = (if n < 0 then 0 else f$(nat n))"
   4.692 +  using     nth_Abs_fls_lower_bound[of 0 "(\<lambda>k::int. if k<0 then 0 else f $ (nat k))"]
   4.693 +  unfolding fps_to_fls_def
   4.694 +  by        simp
   4.695 +
   4.696 +lemma fps_to_fls_eq_imp_fps_eq:
   4.697 +  assumes "fps_to_fls f = fps_to_fls g"
   4.698 +  shows   "f = g"
   4.699 +proof (intro fps_ext)
   4.700 +  fix n
   4.701 +  have "f $ n = fps_to_fls g $$ int n" by (simp add: assms[symmetric])
   4.702 +  thus "f $ n = g $ n" by simp
   4.703 +qed
   4.704 +
   4.705 +lemma fps_zero_to_fls [simp]: "fps_to_fls 0 = 0"
   4.706 +  by (intro fls_zero_eqI) simp
   4.707 +
   4.708 +lemma fps_to_fls_nonzeroI: "f \<noteq> 0 \<Longrightarrow> fps_to_fls f \<noteq> 0"
   4.709 +  using fps_to_fls_eq_imp_fps_eq[of f 0] by auto
   4.710 +
   4.711 +lemma fps_one_to_fls [simp]: "fps_to_fls 1 = 1"
   4.712 +  by (intro fls_eqI) simp
   4.713 +
   4.714 +lemma fps_to_fls_Abs_fps:
   4.715 +  "fps_to_fls (Abs_fps F) = Abs_fls (\<lambda>n. if n<0 then 0 else F (nat n))"
   4.716 +  using nth_Abs_fls_lower_bound[of 0 "(\<lambda>n::int. if n<0 then 0 else F (nat n))"]
   4.717 +  by    (intro fls_eqI) simp
   4.718 +
   4.719 +lemma fps_delta_to_fls:
   4.720 +  "fps_to_fls (Abs_fps (\<lambda>n. if n=a then b else 0)) = Abs_fls (\<lambda>n. if n=int a then b else 0)"
   4.721 +  using fls_eqI[of _ "Abs_fls (\<lambda>n. if n=int a then b else 0)"] by force
   4.722 +
   4.723 +lemma fps_const_to_fls [simp]: "fps_to_fls (fps_const c) = fls_const c"
   4.724 +  by (intro fls_eqI) simp
   4.725 +
   4.726 +lemma fps_X_to_fls [simp]: "fps_to_fls fps_X = fls_X"
   4.727 +  by (fastforce intro: fls_eqI)
   4.728 +
   4.729 +lemma fps_to_fls_eq_zero_iff: "(fps_to_fls f = 0) \<longleftrightarrow> (f=0)"
   4.730 +  using fps_to_fls_nonzeroI by auto
   4.731 +
   4.732 +lemma fls_subdegree_fls_to_fps_gt0: "fls_subdegree (fps_to_fls f) \<ge> 0"
   4.733 +proof (cases "f=0")
   4.734 +  case False show ?thesis
   4.735 +  proof (rule fls_subdegree_geI, rule fls_nonzeroI)
   4.736 +    from False show "fps_to_fls f $$ int (subdegree f) \<noteq> 0"
   4.737 +      by simp
   4.738 +  qed simp
   4.739 +qed simp
   4.740 +
   4.741 +lemma fls_subdegree_fls_to_fps: "fls_subdegree (fps_to_fls f) = int (subdegree f)"
   4.742 +proof (cases "f=0")
   4.743 +  case False
   4.744 +  have "subdegree f = nat (fls_subdegree (fps_to_fls f))"
   4.745 +  proof (rule subdegreeI)
   4.746 +    from False show "f $ (nat (fls_subdegree (fps_to_fls f))) \<noteq> 0"
   4.747 +      using fls_subdegree_fls_to_fps_gt0[of f] nth_fls_subdegree_nonzero[of "fps_to_fls f"]
   4.748 +            fps_to_fls_nonzeroI[of f]
   4.749 +      by    simp
   4.750 +  next
   4.751 +    fix k assume k: "k < nat (fls_subdegree (fps_to_fls f))"
   4.752 +    thus "f $ k = 0"
   4.753 +      using fls_eq0_below_subdegree[of "int k" "fps_to_fls f"] by simp
   4.754 +  qed
   4.755 +  thus ?thesis by (simp add: fls_subdegree_fls_to_fps_gt0)
   4.756 +qed simp
   4.757 +
   4.758 +lemma fps_shift_to_fls [simp]:
   4.759 +  "n \<le> subdegree f \<Longrightarrow> fps_to_fls (fps_shift n f) = fls_shift (int n) (fps_to_fls f)"
   4.760 +  by (auto intro: fls_eqI simp: nat_add_distrib nth_less_subdegree_zero)
   4.761 +
   4.762 +lemma fls_base_factor_fps_to_fls: "fls_base_factor (fps_to_fls f) = fps_to_fls (unit_factor f)"
   4.763 +  using nth_less_subdegree_zero[of _ f]
   4.764 +  by    (auto intro: fls_eqI simp: fls_subdegree_fls_to_fps nat_add_distrib)
   4.765 +
   4.766 +lemma fls_regpart_to_fls_trivial [simp]:
   4.767 +  "fls_subdegree f \<ge> 0 \<Longrightarrow> fps_to_fls (fls_regpart f) = f"
   4.768 +  by (intro fls_eqI) simp
   4.769 +
   4.770 +lemma fls_regpart_fps_trivial [simp]: "fls_regpart (fps_to_fls f) = f"
   4.771 +  by (intro fps_ext) simp
   4.772 +
   4.773 +lemma fps_to_fls_base_factor_to_fps:
   4.774 +  "fps_to_fls (fls_base_factor_to_fps f) = fls_base_factor f"
   4.775 +  by (intro fls_eqI) simp
   4.776 +
   4.777 +lemma fls_conv_base_factor_to_fps_shift_subdegree:
   4.778 +  "f = fls_shift (-fls_subdegree f) (fps_to_fls (fls_base_factor_to_fps f))"
   4.779 +  using fps_to_fls_base_factor_to_fps[of f] fps_to_fls_base_factor_to_fps[of f] by simp
   4.780 +
   4.781 +lemma fls_base_factor_to_fps_to_fls:
   4.782 +  "fls_base_factor_to_fps (fps_to_fls f) = unit_factor f"
   4.783 +  using fls_base_factor_fps_to_fls[of f] fls_regpart_fps_trivial[of "unit_factor f"]
   4.784 +  by    simp
   4.785 +
   4.786 +abbreviation
   4.787 +  "fls_regpart_as_fls f \<equiv> fps_to_fls (fls_regpart f)"
   4.788 +abbreviation
   4.789 +  "fls_prpart_as_fls f \<equiv>
   4.790 +    fls_shift (-fls_subdegree f) (fps_to_fls (fps_of_poly (reflect_poly (fls_prpart f))))"
   4.791 +
   4.792 +lemma fls_regpart_as_fls_nth:
   4.793 +  "fls_regpart_as_fls f $$ n = (if n < 0 then 0 else f $$ n)"
   4.794 +  by simp
   4.795 +
   4.796 +lemma fls_regpart_idem:
   4.797 +  "fls_regpart (fls_regpart_as_fls f) = fls_regpart f"
   4.798 +  by simp
   4.799 +
   4.800 +lemma fls_prpart_as_fls_nth:
   4.801 +  "fls_prpart_as_fls f $$ n = (if n < 0 then f $$ n else 0)"
   4.802 +proof (cases "n < fls_subdegree f" "n < 0" rule: case_split[case_product case_split])
   4.803 +  case False_True
   4.804 +    hence "nat (-fls_subdegree f) - nat (n - fls_subdegree f) = nat (-n)" by auto
   4.805 +    with False_True show ?thesis
   4.806 +      using coeff_reflect_poly[of "fls_prpart f" "nat (n - fls_subdegree f)"] by auto
   4.807 +  next
   4.808 +    case False_False thus ?thesis
   4.809 +      using coeff_reflect_poly[of "fls_prpart f" "nat (n - fls_subdegree f)"] by auto
   4.810 +qed simp_all
   4.811 +
   4.812 +lemma fls_prpart_idem [simp]: "fls_prpart (fls_prpart_as_fls f) = fls_prpart f"
   4.813 +  using fls_prpart_as_fls_nth[of f] by (intro poly_eqI) simp
   4.814 +
   4.815 +lemma fls_regpart_prpart: "fls_regpart (fls_prpart_as_fls f) = 0"
   4.816 +  using fls_prpart_as_fls_nth[of f] by (intro fps_ext) simp
   4.817 +
   4.818 +lemma fls_prpart_regpart: "fls_prpart (fls_regpart_as_fls f) = 0"
   4.819 +  by (intro poly_eqI) simp
   4.820 +
   4.821 +
   4.822 +subsection \<open>Algebraic structures\<close>
   4.823 +
   4.824 +subsubsection \<open>Addition\<close>
   4.825 +
   4.826 +instantiation fls :: (monoid_add) plus
   4.827 +begin
   4.828 +  lift_definition plus_fls :: "'a fls \<Rightarrow> 'a fls \<Rightarrow> 'a fls" is "\<lambda>f g n. f n + g n"
   4.829 +  proof-
   4.830 +    fix f f' :: "int \<Rightarrow> 'a"
   4.831 +    assume "\<forall>\<^sub>\<infinity>n. f (- int n) = 0" "\<forall>\<^sub>\<infinity>n. f' (- int n) = 0"
   4.832 +    from this obtain N N' where "\<forall>n>N. f (-int n) = 0" "\<forall>n>N'. f' (-int n) = 0"
   4.833 +      by (auto simp: MOST_nat)
   4.834 +    hence "\<forall>n > max N N'. f (-int n) + f' (-int n) = 0" by auto
   4.835 +    hence "\<exists>K. \<forall>n>K. f (-int n) + f' (-int n) = 0" by fast
   4.836 +    thus "\<forall>\<^sub>\<infinity>n. f (- int n) + f' (-int n) = 0" by (simp add: MOST_nat)
   4.837 +  qed
   4.838 +  instance ..
   4.839 +end
   4.840 +
   4.841 +lemma fls_plus_nth [simp]: "(f + g) $$ n = f $$ n + g $$ n"
   4.842 +  by transfer simp
   4.843 +
   4.844 +lemma fls_plus_const: "fls_const x + fls_const y = fls_const (x+y)"
   4.845 +  by (intro fls_eqI) simp
   4.846 +
   4.847 +lemma fls_plus_subdegree:
   4.848 +  "f + g \<noteq> 0 \<Longrightarrow> fls_subdegree (f + g) \<ge> min (fls_subdegree f) (fls_subdegree g)"
   4.849 +  by (auto intro: fls_subdegree_geI)
   4.850 +
   4.851 +lemma fls_shift_plus [simp]:
   4.852 +  "fls_shift m (f + g) = (fls_shift m f) + (fls_shift m g)"
   4.853 +  by (intro fls_eqI) simp
   4.854 +
   4.855 +lemma fls_regpart_plus [simp]: "fls_regpart (f + g) = fls_regpart f + fls_regpart g"
   4.856 +  by (intro fps_ext) simp
   4.857 +
   4.858 +lemma fls_prpart_plus [simp] : "fls_prpart (f + g) = fls_prpart f + fls_prpart g"
   4.859 +  by (intro poly_eqI) simp
   4.860 +
   4.861 +lemma fls_decompose_reg_pr_parts:
   4.862 +  fixes   f :: "'a :: monoid_add fls"
   4.863 +  defines "R  \<equiv> fls_regpart_as_fls f"
   4.864 +  and     "P  \<equiv> fls_prpart_as_fls f"
   4.865 +  shows   "f = P + R"
   4.866 +  and     "f = R + P"
   4.867 +  using   fls_prpart_as_fls_nth[of f]
   4.868 +  by      (auto intro: fls_eqI simp add: assms)
   4.869 +
   4.870 +lemma fps_to_fls_plus [simp]: "fps_to_fls (f + g) = fps_to_fls f + fps_to_fls g"
   4.871 +  by (intro fls_eqI) simp
   4.872 +
   4.873 +instance fls :: (monoid_add) monoid_add
   4.874 +proof
   4.875 +  fix a b c :: "'a fls"
   4.876 +  show "a + b + c = a + (b + c)" by transfer (simp add: add.assoc)
   4.877 +  show "0 + a = a" by transfer simp
   4.878 +  show "a + 0 = a" by transfer simp
   4.879 +qed
   4.880 +
   4.881 +instance fls :: (comm_monoid_add) comm_monoid_add
   4.882 +  by (standard, transfer, auto simp: add.commute)
   4.883 +
   4.884 +
   4.885 +subsubsection \<open>Subtraction and negatives\<close>
   4.886 +
   4.887 +instantiation fls :: (group_add) minus
   4.888 +begin
   4.889 +  lift_definition minus_fls :: "'a fls \<Rightarrow> 'a fls \<Rightarrow> 'a fls" is "\<lambda>f g n. f n - g n"
   4.890 +  proof-
   4.891 +    fix f f' :: "int \<Rightarrow> 'a"
   4.892 +    assume "\<forall>\<^sub>\<infinity>n. f (- int n) = 0" "\<forall>\<^sub>\<infinity>n. f' (- int n) = 0"
   4.893 +    from this obtain N N' where "\<forall>n>N. f (-int n) = 0" "\<forall>n>N'. f' (-int n) = 0"
   4.894 +      by (auto simp: MOST_nat)
   4.895 +    hence "\<forall>n > max N N'. f (-int n) - f' (-int n) = 0" by auto
   4.896 +    hence "\<exists>K. \<forall>n>K. f (-int n) - f' (-int n) = 0" by fast
   4.897 +    thus "\<forall>\<^sub>\<infinity>n. f (- int n) - f' (-int n) = 0" by (simp add: MOST_nat)
   4.898 +  qed
   4.899 +  instance ..
   4.900 +end
   4.901 +
   4.902 +lemma fls_minus_nth [simp]: "(f - g) $$ n = f $$ n - g $$ n"
   4.903 +  by transfer simp
   4.904 +
   4.905 +lemma fls_minus_const: "fls_const x - fls_const y = fls_const (x-y)"
   4.906 +  by (intro fls_eqI) simp
   4.907 +
   4.908 +lemma fls_subdegree_minus:
   4.909 +  "f - g \<noteq> 0 \<Longrightarrow> fls_subdegree (f - g) \<ge> min (fls_subdegree f) (fls_subdegree g)"
   4.910 +  by (intro fls_subdegree_geI) simp_all
   4.911 +
   4.912 +lemma fls_shift_minus [simp]: "fls_shift m (f - g) = (fls_shift m f) - (fls_shift m g)"
   4.913 +  by (auto intro: fls_eqI)
   4.914 +
   4.915 +lemma fls_regpart_minus [simp]: "fls_regpart (f - g) = fls_regpart f - fls_regpart g"
   4.916 +  by (intro fps_ext) simp
   4.917 +
   4.918 +lemma fls_prpart_minus [simp] : "fls_prpart (f - g) = fls_prpart f - fls_prpart g"
   4.919 +  by (intro poly_eqI) simp
   4.920 +
   4.921 +lemma fps_to_fls_minus [simp]: "fps_to_fls (f - g) = fps_to_fls f - fps_to_fls g"
   4.922 +  by (intro fls_eqI) simp
   4.923 +
   4.924 +instantiation fls :: (group_add) uminus
   4.925 +begin
   4.926 +  lift_definition uminus_fls :: "'a fls \<Rightarrow> 'a fls" is "\<lambda>f n. - f n"
   4.927 +  proof-
   4.928 +    fix f :: "int \<Rightarrow> 'a" assume "\<forall>\<^sub>\<infinity>n. f (- int n) = 0"
   4.929 +    from this obtain N where "\<forall>n>N. f (-int n) = 0"
   4.930 +      by (auto simp: MOST_nat)
   4.931 +    hence "\<forall>n>N. - f (-int n) = 0" by auto
   4.932 +    hence "\<exists>K. \<forall>n>K. - f (-int n) = 0" by fast
   4.933 +    thus "\<forall>\<^sub>\<infinity>n. - f (- int n) = 0" by (simp add: MOST_nat)
   4.934 +  qed
   4.935 +  instance ..
   4.936 +end
   4.937 +
   4.938 +lemma fls_uminus_nth [simp]: "(-f) $$ n = - (f $$ n)"
   4.939 +  by transfer simp
   4.940 +
   4.941 +lemma fls_const_uminus[simp]: "fls_const (-x) = -fls_const x"
   4.942 +  by (intro fls_eqI) simp
   4.943 +
   4.944 +lemma fls_shift_uminus [simp]: "fls_shift m (- f) = - (fls_shift m f)"
   4.945 +  by (auto intro: fls_eqI)
   4.946 +
   4.947 +lemma fls_regpart_uminus [simp]: "fls_regpart (- f) = - fls_regpart f"
   4.948 +  by (intro fps_ext) simp
   4.949 +
   4.950 +lemma fls_prpart_uminus [simp] : "fls_prpart (- f) = - fls_prpart f"
   4.951 +  by (intro poly_eqI) simp
   4.952 +
   4.953 +lemma fps_to_fls_uminus [simp]: "fps_to_fls (- f) = - fps_to_fls f"
   4.954 +  by (intro fls_eqI) simp
   4.955 +
   4.956 +instance fls :: (group_add) group_add
   4.957 +proof
   4.958 +  fix a b :: "'a fls"
   4.959 +  show "- a + a = 0" by transfer simp
   4.960 +  show "a + - b = a - b" by transfer simp
   4.961 +qed
   4.962 +
   4.963 +instance fls :: (ab_group_add) ab_group_add
   4.964 +proof
   4.965 +  fix a b :: "'a fls"
   4.966 +  show "- a + a = 0" by transfer simp
   4.967 +  show "a - b = a + - b" by transfer simp
   4.968 +qed
   4.969 +
   4.970 +lemma fls_uminus_subdegree [simp]: "fls_subdegree (-f) = fls_subdegree f"
   4.971 +  by (cases "f=0") (auto intro: fls_subdegree_eqI)
   4.972 +
   4.973 +lemma fls_subdegree_minus_sym: "fls_subdegree (g - f) = fls_subdegree (f - g)"
   4.974 +  using fls_uminus_subdegree[of "g-f"] by (simp add: algebra_simps)
   4.975 +
   4.976 +lemma fls_regpart_sub_prpart: "fls_regpart (f - fls_prpart_as_fls f) = fls_regpart f"
   4.977 +  using fls_decompose_reg_pr_parts(2)[of f]
   4.978 +        add_diff_cancel[of "fls_regpart_as_fls f" "fls_prpart_as_fls f"]
   4.979 +  by    simp
   4.980 +
   4.981 +lemma fls_prpart_sub_regpart: "fls_prpart (f - fls_regpart_as_fls f) = fls_prpart f"
   4.982 +  using fls_decompose_reg_pr_parts(1)[of f]
   4.983 +        add_diff_cancel[of "fls_prpart_as_fls f" "fls_regpart_as_fls f"]
   4.984 +  by    simp
   4.985 +
   4.986 +
   4.987 +subsubsection \<open>Multiplication\<close>
   4.988 +
   4.989 +instantiation fls :: ("{comm_monoid_add, times}") times
   4.990 +begin
   4.991 +  definition fls_times_def:
   4.992 +    "(*) = (\<lambda>f g.
   4.993 +      fls_shift
   4.994 +        (- (fls_subdegree f + fls_subdegree g))
   4.995 +        (fps_to_fls (fls_base_factor_to_fps f * fls_base_factor_to_fps g))
   4.996 +    )"
   4.997 +  instance ..
   4.998 +end
   4.999 +
  4.1000 +lemma fls_times_nth_eq0: "n < fls_subdegree f + fls_subdegree g \<Longrightarrow> (f * g) $$ n = 0"
  4.1001 +  by (simp add: fls_times_def)
  4.1002 +
  4.1003 +lemma fls_times_nth:
  4.1004 +  fixes   f df g dg
  4.1005 +  defines "df \<equiv> fls_subdegree f" and "dg \<equiv> fls_subdegree g"
  4.1006 +  shows   "(f * g) $$ n = (\<Sum>i=df + dg..n. f $$ (i - dg) * g $$ (dg + n - i))"
  4.1007 +  and     "(f * g) $$ n = (\<Sum>i=df..n - dg. f $$ i * g $$ (n - i))"
  4.1008 +  and     "(f * g) $$ n = (\<Sum>i=dg..n - df. f $$ (df + i - dg) * g $$ (dg + n - df - i))"
  4.1009 +  and     "(f * g) $$ n = (\<Sum>i=0..n - (df + dg). f $$ (df + i) * g $$ (n - df - i))"
  4.1010 +proof-
  4.1011 +
  4.1012 +  define dfg where "dfg \<equiv> df + dg"
  4.1013 +
  4.1014 +  show 4: "(f * g) $$ n = (\<Sum>i=0..n - dfg. f $$ (df + i) * g $$ (n - df - i))"
  4.1015 +  proof (cases "n < dfg")
  4.1016 +    case False
  4.1017 +    from False assms have
  4.1018 +      "(f * g) $$ n =
  4.1019 +        (\<Sum>i = 0..nat (n - dfg). f $$ (df + int i) * g $$ (dg + int (nat (n - dfg) - i)))"
  4.1020 +      using fps_mult_nth[of "fls_base_factor_to_fps f" "fls_base_factor_to_fps g"]
  4.1021 +            fls_base_factor_to_fps_nth[of f]
  4.1022 +            fls_base_factor_to_fps_nth[of g]
  4.1023 +      by    (simp add: dfg_def fls_times_def algebra_simps)
  4.1024 +    moreover from False have index:
  4.1025 +      "\<And>i. i \<in> {0..nat (n - dfg)} \<Longrightarrow> dg + int (nat (n - dfg) - i) = n - df - int i"
  4.1026 +      by (auto simp: dfg_def)
  4.1027 +    ultimately have
  4.1028 +      "(f * g) $$ n = (\<Sum>i=0..nat (n - dfg). f $$ (df + int i) * g $$ (n - df - int i))"
  4.1029 +      by simp
  4.1030 +    moreover have
  4.1031 +      "(\<Sum>i=0..nat (n - dfg). f $$ (df + int i) *  g $$ (n - df - int i)) =
  4.1032 +        (\<Sum>i=0..n - dfg. f $$ (df + i) *  g $$ (n - df - i))"
  4.1033 +    proof (intro sum.reindex_cong)
  4.1034 +      show "inj_on nat {0..n - dfg}" by standard auto
  4.1035 +      show "{0..nat (n - dfg)} = nat ` {0..n - dfg}"
  4.1036 +      proof
  4.1037 +        show "{0..nat (n - dfg)} \<subseteq> nat ` {0..n - dfg}"
  4.1038 +        proof
  4.1039 +          fix i assume "i \<in> {0..nat (n - dfg)}"
  4.1040 +          hence i: "i \<ge> 0" "i \<le> nat (n - dfg)" by auto
  4.1041 +          with False have "int i \<ge> 0" "int i \<le> n - dfg" by auto
  4.1042 +          hence "int i \<in> {0..n - dfg}" by simp
  4.1043 +          moreover from i(1) have "i = nat (int i)" by simp
  4.1044 +          ultimately show "i \<in> nat ` {0..n - dfg}" by fast
  4.1045 +        qed
  4.1046 +      qed (auto simp: False)
  4.1047 +    qed (simp add: False)
  4.1048 +    ultimately show "(f * g) $$ n = (\<Sum>i=0..n - dfg. f $$ (df + i) *  g $$ (n - df - i))"
  4.1049 +      by simp
  4.1050 +  qed (simp add: fls_times_nth_eq0 assms dfg_def)
  4.1051 +
  4.1052 +  have
  4.1053 +    "(\<Sum>i=dfg..n. f $$ (i - dg) *  g $$ (dg + n - i)) =
  4.1054 +      (\<Sum>i=0..n - dfg. f $$ (df + i) *  g $$ (n - df - i))"
  4.1055 +  proof (intro sum.reindex_cong)
  4.1056 +    define T where "T \<equiv> \<lambda>i. i + dfg"
  4.1057 +    show "inj_on T {0..n - dfg}" by standard (simp add: T_def)
  4.1058 +  qed (simp_all add: dfg_def algebra_simps)
  4.1059 +  with 4 show 1: "(f * g) $$ n = (\<Sum>i=dfg..n. f $$ (i - dg) *  g $$ (dg + n - i))"
  4.1060 +    by simp
  4.1061 +
  4.1062 +  have
  4.1063 +    "(\<Sum>i=dfg..n. f $$ (i - dg) *  g $$ (dg + n - i)) = (\<Sum>i=df..n - dg. f $$ i *  g $$ (n - i))"
  4.1064 +  proof (intro sum.reindex_cong)
  4.1065 +    define T where "T \<equiv> \<lambda>i. i + dg"
  4.1066 +    show "inj_on T {df..n - dg}" by standard (simp add: T_def)
  4.1067 +  qed (auto simp: dfg_def)
  4.1068 +  with 1 show "(f * g) $$ n = (\<Sum>i=df..n - dg. f $$ i *  g $$ (n - i))"
  4.1069 +    by simp
  4.1070 +
  4.1071 +  have
  4.1072 +    "(\<Sum>i=dfg..n. f $$ (i - dg) *  g $$ (dg + n - i)) =
  4.1073 +      (\<Sum>i=dg..n - df. f $$ (df + i - dg) *  g $$ (dg + n - df - i))"
  4.1074 +  proof (intro sum.reindex_cong)
  4.1075 +    define T where "T \<equiv> \<lambda>i. i + df"
  4.1076 +    show "inj_on T {dg..n - df}" by standard (simp add: T_def)
  4.1077 +  qed (simp_all add: dfg_def algebra_simps)
  4.1078 +  with 1 show "(f * g) $$ n = (\<Sum>i=dg..n - df. f $$ (df + i - dg) *  g $$ (dg + n - df - i))"
  4.1079 +    by simp
  4.1080 +
  4.1081 +qed
  4.1082 +
  4.1083 +lemma fls_times_base [simp]:
  4.1084 +  "(f * g) $$ (fls_subdegree f + fls_subdegree g) =
  4.1085 +    (f $$ fls_subdegree f) * (g $$ fls_subdegree g)"
  4.1086 +  by (simp add: fls_times_nth(1))
  4.1087 +
  4.1088 +instance fls :: ("{comm_monoid_add, mult_zero}") mult_zero
  4.1089 +proof
  4.1090 +  fix a :: "'a fls"
  4.1091 +  have
  4.1092 +    "(0::'a fls) * a =
  4.1093 +      fls_shift (fls_subdegree a) (fps_to_fls ( (0::'a fps)*(fls_base_factor_to_fps a) ))"
  4.1094 +    by (simp add: fls_times_def)
  4.1095 +  moreover have
  4.1096 +    "a * (0::'a fls) =
  4.1097 +      fls_shift (fls_subdegree a) (fps_to_fls ( (fls_base_factor_to_fps a)*(0::'a fps) ))"
  4.1098 +    by (simp add: fls_times_def)
  4.1099 +  ultimately show "0 * a = (0::'a fls)" "a * 0 = (0::'a fls)"
  4.1100 +    by auto
  4.1101 +qed
  4.1102 +
  4.1103 +lemma fls_mult_one:
  4.1104 +  fixes f :: "'a::{comm_monoid_add, mult_zero, monoid_mult} fls"
  4.1105 +  shows "1 * f = f"
  4.1106 +  and   "f * 1 = f"
  4.1107 +  using fls_conv_base_factor_to_fps_shift_subdegree[of f]
  4.1108 +  by    (simp_all add: fls_times_def fps_one_mult)
  4.1109 +
  4.1110 +lemma fls_mult_const_nth [simp]:
  4.1111 +  fixes f :: "'a::{comm_monoid_add, mult_zero} fls"
  4.1112 +  shows "(fls_const x * f) $$ n = x * f$$n"
  4.1113 +  and   "(f * fls_const x ) $$ n = f$$n * x"
  4.1114 +proof-
  4.1115 +  show "(fls_const x * f) $$ n = x * f$$n"
  4.1116 +  proof (cases "n<fls_subdegree f")
  4.1117 +    case False
  4.1118 +    hence "{fls_subdegree f..n} = insert (fls_subdegree f) {fls_subdegree f+1..n}" by auto
  4.1119 +    thus ?thesis by (simp add: fls_times_nth(1))
  4.1120 +  qed (simp add: fls_times_nth_eq0)
  4.1121 +  show "(f * fls_const x ) $$ n = f$$n * x"
  4.1122 +  proof (cases "n<fls_subdegree f")
  4.1123 +    case False
  4.1124 +    hence "{fls_subdegree f..n} = insert n {fls_subdegree f..n-1}" by auto
  4.1125 +    thus ?thesis by (simp add: fls_times_nth(1))
  4.1126 +  qed (simp add: fls_times_nth_eq0)
  4.1127 +qed
  4.1128 +
  4.1129 +lemma fls_const_mult_const[simp]:
  4.1130 +  fixes x y :: "'a::{comm_monoid_add, mult_zero}"
  4.1131 +  shows "fls_const x * fls_const y = fls_const (x*y)"
  4.1132 +  by    (intro fls_eqI) simp
  4.1133 +
  4.1134 +lemma fls_mult_subdegree_ge:
  4.1135 +  fixes   f g :: "'a::{comm_monoid_add,mult_zero} fls"
  4.1136 +  assumes "f*g \<noteq> 0"
  4.1137 +  shows   "fls_subdegree (f*g) \<ge> fls_subdegree f + fls_subdegree g"
  4.1138 +  by      (auto intro: fls_subdegree_geI simp: assms fls_times_nth_eq0)
  4.1139 +
  4.1140 +lemma fls_mult_subdegree_ge_0:
  4.1141 +  fixes   f g :: "'a::{comm_monoid_add,mult_zero} fls"
  4.1142 +  assumes "fls_subdegree f \<ge> 0" "fls_subdegree g \<ge> 0"
  4.1143 +  shows   "fls_subdegree (f*g) \<ge> 0"
  4.1144 +  using   assms fls_mult_subdegree_ge[of f g]
  4.1145 +  by      fastforce
  4.1146 +
  4.1147 +lemma fls_mult_nonzero_base_subdegree_eq:
  4.1148 +  fixes   f g :: "'a::{comm_monoid_add,mult_zero} fls"
  4.1149 +  assumes "f $$ (fls_subdegree f) * g $$ (fls_subdegree g) \<noteq> 0"
  4.1150 +  shows   "fls_subdegree (f*g) = fls_subdegree f + fls_subdegree g"
  4.1151 +proof-
  4.1152 +  from assms have "fls_subdegree (f*g) \<ge> fls_subdegree f + fls_subdegree g"
  4.1153 +    using fls_nonzeroI[of "f*g" "fls_subdegree f + fls_subdegree g"]
  4.1154 +          fls_mult_subdegree_ge[of f g]
  4.1155 +    by    simp
  4.1156 +  moreover from assms have "fls_subdegree (f*g) \<le> fls_subdegree f + fls_subdegree g"
  4.1157 +    by (intro fls_subdegree_leI) simp
  4.1158 +  ultimately show ?thesis by simp
  4.1159 +qed
  4.1160 +
  4.1161 +lemma fls_subdegree_mult [simp]:
  4.1162 +  fixes   f g :: "'a::semiring_no_zero_divisors fls"
  4.1163 +  assumes "f \<noteq> 0" "g \<noteq> 0"
  4.1164 +  shows   "fls_subdegree (f * g) = fls_subdegree f + fls_subdegree g"
  4.1165 +  using   assms
  4.1166 +  by      (auto intro: fls_subdegree_eqI simp: fls_times_nth_eq0)
  4.1167 +
  4.1168 +lemma fls_shifted_times_simps:
  4.1169 +  fixes f g :: "'a::{comm_monoid_add, mult_zero} fls"
  4.1170 +  shows "f * (fls_shift n g) = fls_shift n (f*g)" "(fls_shift n f) * g = fls_shift n (f*g)"
  4.1171 +proof-
  4.1172 +
  4.1173 +  show "f * (fls_shift n g) = fls_shift n (f*g)"
  4.1174 +  proof (cases "g=0")
  4.1175 +    case False
  4.1176 +    hence
  4.1177 +      "f * (fls_shift n g) =
  4.1178 +        fls_shift (- (fls_subdegree f + (fls_subdegree g - n)))
  4.1179 +          (fps_to_fls (fls_base_factor_to_fps f * fls_base_factor_to_fps g))"
  4.1180 +      unfolding fls_times_def by (simp add: fls_base_factor_to_fps_shift)
  4.1181 +    thus "f * (fls_shift n g) = fls_shift n (f*g)"
  4.1182 +      by (simp add: algebra_simps fls_times_def)
  4.1183 +  qed auto
  4.1184 +
  4.1185 +  show "(fls_shift n f)*g = fls_shift n (f*g)"
  4.1186 +  proof (cases "f=0")
  4.1187 +    case False
  4.1188 +    hence
  4.1189 +      "(fls_shift n f)*g =
  4.1190 +        fls_shift (- ((fls_subdegree f - n) + fls_subdegree g))
  4.1191 +          (fps_to_fls (fls_base_factor_to_fps f * fls_base_factor_to_fps g))"
  4.1192 +      unfolding fls_times_def by (simp add: fls_base_factor_to_fps_shift)
  4.1193 +    thus "(fls_shift n f) * g = fls_shift n (f*g)"
  4.1194 +      by (simp add: algebra_simps fls_times_def)
  4.1195 +  qed auto
  4.1196 +
  4.1197 +qed
  4.1198 +
  4.1199 +lemma fls_shifted_times_transfer:
  4.1200 +  fixes f g :: "'a::{comm_monoid_add, mult_zero} fls"
  4.1201 +  shows "fls_shift n f * g = f * fls_shift n g"
  4.1202 +  using fls_shifted_times_simps(1)[of f n g] fls_shifted_times_simps(2)[of n f g]
  4.1203 +  by    simp
  4.1204 +
  4.1205 +lemma fls_times_both_shifted_simp:
  4.1206 +  fixes f g :: "'a::{comm_monoid_add, mult_zero} fls"
  4.1207 +  shows "(fls_shift m f) * (fls_shift n g) = fls_shift (m+n) (f*g)"
  4.1208 +  by    (simp add: fls_shifted_times_simps)
  4.1209 +
  4.1210 +lemma fls_base_factor_mult_base_factor:
  4.1211 +  fixes f g :: "'a::{comm_monoid_add, mult_zero} fls"
  4.1212 +  shows "fls_base_factor (f * fls_base_factor g) = fls_base_factor (f * g)"
  4.1213 +  and   "fls_base_factor (fls_base_factor f * g) = fls_base_factor (f * g)"
  4.1214 +  using fls_base_factor_shift[of "fls_subdegree g" "f*g"]
  4.1215 +        fls_base_factor_shift[of "fls_subdegree f" "f*g"]
  4.1216 +  by    (simp_all add: fls_shifted_times_simps)
  4.1217 +
  4.1218 +lemma fls_base_factor_mult_both_base_factor:
  4.1219 +  fixes f g :: "'a::{comm_monoid_add,mult_zero} fls"
  4.1220 +  shows "fls_base_factor (fls_base_factor f * fls_base_factor g) = fls_base_factor (f * g)"
  4.1221 +  using fls_base_factor_mult_base_factor(1)[of "fls_base_factor f" g]
  4.1222 +        fls_base_factor_mult_base_factor(2)[of f g]
  4.1223 +  by    simp
  4.1224 +
  4.1225 +lemma fls_base_factor_mult:
  4.1226 +  fixes f g :: "'a::semiring_no_zero_divisors fls"
  4.1227 +  shows "fls_base_factor (f * g) = fls_base_factor f * fls_base_factor g"
  4.1228 +  by    (cases "f\<noteq>0 \<and> g\<noteq>0")
  4.1229 +        (auto simp: fls_times_both_shifted_simp)
  4.1230 +
  4.1231 +lemma fls_times_conv_base_factor_times:
  4.1232 +  fixes f g :: "'a::{comm_monoid_add, mult_zero} fls"
  4.1233 +  shows
  4.1234 +    "f * g =
  4.1235 +      fls_shift (-(fls_subdegree f + fls_subdegree g)) (fls_base_factor f * fls_base_factor g)"
  4.1236 +  by (simp add: fls_times_both_shifted_simp)
  4.1237 +
  4.1238 +lemma fls_times_base_factor_conv_shifted_times:
  4.1239 +\<comment> \<open>Convenience form of lemma @{text "fls_times_both_shifted_simp"}.\<close>
  4.1240 +  fixes f g :: "'a::{comm_monoid_add, mult_zero} fls"
  4.1241 +  shows
  4.1242 +    "fls_base_factor f * fls_base_factor g = fls_shift (fls_subdegree f + fls_subdegree g) (f * g)"
  4.1243 +  by (simp add: fls_times_both_shifted_simp)
  4.1244 +
  4.1245 +lemma fls_times_conv_regpart:
  4.1246 +  fixes   f g :: "'a::{comm_monoid_add,mult_zero} fls"
  4.1247 +  assumes "fls_subdegree f \<ge> 0" "fls_subdegree g \<ge> 0"
  4.1248 +  shows "fls_regpart (f * g) = fls_regpart f * fls_regpart g"
  4.1249 +proof-
  4.1250 +  from assms have 1:
  4.1251 +    "f * g =
  4.1252 +      fls_shift (- (fls_subdegree f + fls_subdegree g)) (
  4.1253 +        fps_to_fls (
  4.1254 +          fps_shift (nat (fls_subdegree f) + nat (fls_subdegree g)) (
  4.1255 +            fls_regpart f * fls_regpart g
  4.1256 +          )
  4.1257 +        )
  4.1258 +      )"
  4.1259 +    by (simp add:
  4.1260 +      fls_times_def fls_base_factor_to_fps_conv_fps_shift[symmetric]
  4.1261 +      fls_regpart_subdegree_conv fps_shift_mult_both[symmetric]
  4.1262 +    )
  4.1263 +  show ?thesis
  4.1264 +  proof (cases "fls_regpart f * fls_regpart g = 0")
  4.1265 +    case False
  4.1266 +    with assms have
  4.1267 +      "subdegree (fls_regpart f * fls_regpart g) \<ge>
  4.1268 +        nat (fls_subdegree f) + nat (fls_subdegree g)"
  4.1269 +      by (simp add: fps_mult_subdegree_ge fls_regpart_subdegree_conv[symmetric])
  4.1270 +    with 1 assms show ?thesis by simp
  4.1271 +  qed (simp add: 1)
  4.1272 +qed
  4.1273 +
  4.1274 +lemma fls_base_factor_to_fps_mult_conv_unit_factor:
  4.1275 +  fixes f g :: "'a::{comm_monoid_add,mult_zero} fls"
  4.1276 +  shows
  4.1277 +    "fls_base_factor_to_fps (f * g) =
  4.1278 +      unit_factor (fls_base_factor_to_fps f * fls_base_factor_to_fps g)"
  4.1279 +  using fls_base_factor_mult_both_base_factor[of f g]
  4.1280 +        fps_unit_factor_fls_regpart[of "fls_base_factor f * fls_base_factor g"]
  4.1281 +        fls_base_factor_subdegree[of f] fls_base_factor_subdegree[of g]
  4.1282 +        fls_mult_subdegree_ge_0[of "fls_base_factor f" "fls_base_factor g"]
  4.1283 +        fls_times_conv_regpart[of "fls_base_factor f" "fls_base_factor g"]
  4.1284 +  by    simp
  4.1285 +
  4.1286 +lemma fls_base_factor_to_fps_mult':
  4.1287 +  fixes   f g :: "'a::{comm_monoid_add,mult_zero} fls"
  4.1288 +  assumes "(f $$ fls_subdegree f) * (g $$ fls_subdegree g) \<noteq> 0"
  4.1289 +  shows   "fls_base_factor_to_fps (f * g) = fls_base_factor_to_fps f * fls_base_factor_to_fps g"
  4.1290 +  using   assms fls_mult_nonzero_base_subdegree_eq[of f g]
  4.1291 +          fls_times_base_factor_conv_shifted_times[of f g]
  4.1292 +          fls_times_conv_regpart[of "fls_base_factor f" "fls_base_factor g"]
  4.1293 +          fls_base_factor_subdegree[of f] fls_base_factor_subdegree[of g]
  4.1294 +  by      fastforce
  4.1295 +
  4.1296 +lemma fls_base_factor_to_fps_mult:
  4.1297 +  fixes f g :: "'a::semiring_no_zero_divisors fls"
  4.1298 +  shows "fls_base_factor_to_fps (f * g) = fls_base_factor_to_fps f * fls_base_factor_to_fps g"
  4.1299 +  using fls_base_factor_to_fps_mult'[of f g]
  4.1300 +  by    (cases "f=0 \<or> g=0") auto
  4.1301 +
  4.1302 +lemma fls_times_conv_fps_times:
  4.1303 +  fixes   f g :: "'a::{comm_monoid_add,mult_zero} fls"
  4.1304 +  assumes "fls_subdegree f \<ge> 0" "fls_subdegree g \<ge> 0"
  4.1305 +  shows   "f * g = fps_to_fls (fls_regpart f * fls_regpart g)"
  4.1306 +  using   assms fls_mult_subdegree_ge[of f g]
  4.1307 +  by      (cases "f * g = 0") (simp_all add: fls_times_conv_regpart[symmetric])
  4.1308 +
  4.1309 +lemma fps_times_conv_fls_times:
  4.1310 +  fixes   f g :: "'a::{comm_monoid_add,mult_zero} fps"
  4.1311 +  shows   "f * g = fls_regpart (fps_to_fls f * fps_to_fls g)"
  4.1312 +  using   fls_subdegree_fls_to_fps_gt0 fls_times_conv_regpart[symmetric]
  4.1313 +  by      fastforce
  4.1314 +
  4.1315 +lemma fls_times_fps_to_fls:
  4.1316 +  fixes f g :: "'a::{comm_monoid_add,mult_zero} fps"
  4.1317 +  shows "fps_to_fls (f * g) = fps_to_fls f * fps_to_fls g"
  4.1318 +proof (intro fls_eq_conv_fps_eqI, rule fls_subdegree_fls_to_fps_gt0)
  4.1319 +  show "fls_subdegree (fps_to_fls f * fps_to_fls g) \<ge> 0"
  4.1320 +  proof (cases "fps_to_fls f * fps_to_fls g = 0")
  4.1321 +    case False thus ?thesis
  4.1322 +      using fls_mult_subdegree_ge fls_subdegree_fls_to_fps_gt0[of f]
  4.1323 +            fls_subdegree_fls_to_fps_gt0[of g]
  4.1324 +      by    fastforce
  4.1325 +  qed simp
  4.1326 +qed (simp add: fps_times_conv_fls_times)
  4.1327 +
  4.1328 +lemma fls_X_times_conv_shift:
  4.1329 +  fixes f :: "'a::{comm_monoid_add,mult_zero,monoid_mult} fls"
  4.1330 +  shows "fls_X * f = fls_shift (-1) f" "f * fls_X = fls_shift (-1) f"
  4.1331 +  by    (simp_all add: fls_X_conv_shift_1 fls_mult_one fls_shifted_times_simps)
  4.1332 +
  4.1333 +lemmas fls_X_times_comm = trans_sym[OF fls_X_times_conv_shift]   
  4.1334 +
  4.1335 +lemma fls_subdegree_mult_fls_X:
  4.1336 +  fixes   f :: "'a::{comm_monoid_add,mult_zero,monoid_mult} fls"
  4.1337 +  assumes "f \<noteq> 0"
  4.1338 +  shows   "fls_subdegree (fls_X * f) = fls_subdegree f + 1"
  4.1339 +  and     "fls_subdegree (f * fls_X) = fls_subdegree f + 1"
  4.1340 +  by      (auto simp: fls_X_times_conv_shift assms)
  4.1341 +
  4.1342 +lemma fls_mult_fls_X_nonzero:
  4.1343 +  fixes   f :: "'a::{comm_monoid_add,mult_zero,monoid_mult} fls"
  4.1344 +  assumes "f \<noteq> 0"
  4.1345 +  shows   "fls_X * f \<noteq> 0"
  4.1346 +  and     "f * fls_X \<noteq> 0"
  4.1347 +  by      (auto simp: fls_X_times_conv_shift fls_shift_eq0_iff assms)
  4.1348 +
  4.1349 +lemma fls_base_factor_mult_fls_X:
  4.1350 +  fixes f :: "'a::{comm_monoid_add,monoid_mult,mult_zero} fls"
  4.1351 +  shows "fls_base_factor (fls_X * f) = fls_base_factor f"
  4.1352 +  and   "fls_base_factor (f * fls_X) = fls_base_factor f"
  4.1353 +  using fls_base_factor_shift[of "-1" f]
  4.1354 +  by    (auto simp: fls_X_times_conv_shift)
  4.1355 +
  4.1356 +lemma fls_X_inv_times_conv_shift:
  4.1357 +  fixes f :: "'a::{comm_monoid_add,mult_zero,monoid_mult} fls"
  4.1358 +  shows "fls_X_inv * f = fls_shift 1 f" "f * fls_X_inv = fls_shift 1 f"
  4.1359 +  by    (simp_all add: fls_X_inv_conv_shift_1 fls_mult_one fls_shifted_times_simps)
  4.1360 +
  4.1361 +lemmas fls_X_inv_times_comm = trans_sym[OF fls_X_inv_times_conv_shift]
  4.1362 +
  4.1363 +lemma fls_subdegree_mult_fls_X_inv:
  4.1364 +  fixes   f :: "'a::{comm_monoid_add,mult_zero,monoid_mult} fls"
  4.1365 +  assumes "f \<noteq> 0"
  4.1366 +  shows   "fls_subdegree (fls_X_inv * f) = fls_subdegree f - 1"
  4.1367 +  and     "fls_subdegree (f * fls_X_inv) = fls_subdegree f - 1"
  4.1368 +  by      (auto simp: fls_X_inv_times_conv_shift assms)
  4.1369 +
  4.1370 +lemma fls_mult_fls_X_inv_nonzero:
  4.1371 +  fixes   f :: "'a::{comm_monoid_add,mult_zero,monoid_mult} fls"
  4.1372 +  assumes "f \<noteq> 0"
  4.1373 +  shows   "fls_X_inv * f \<noteq> 0"
  4.1374 +  and     "f * fls_X_inv \<noteq> 0"
  4.1375 +  by      (auto simp: fls_X_inv_times_conv_shift fls_shift_eq0_iff assms)
  4.1376 +
  4.1377 +lemma fls_base_factor_mult_fls_X_inv:
  4.1378 +  fixes f :: "'a::{comm_monoid_add,monoid_mult,mult_zero} fls"
  4.1379 +  shows "fls_base_factor (fls_X_inv * f) = fls_base_factor f"
  4.1380 +  and   "fls_base_factor (f * fls_X_inv) = fls_base_factor f"
  4.1381 +  using fls_base_factor_shift[of 1 f]
  4.1382 +  by    (auto simp: fls_X_inv_times_conv_shift)
  4.1383 +
  4.1384 +lemma fls_mult_assoc_subdegree_ge_0:
  4.1385 +  fixes   f g h :: "'a::semiring_0 fls"
  4.1386 +  assumes "fls_subdegree f \<ge> 0" "fls_subdegree g \<ge> 0" "fls_subdegree h \<ge> 0"
  4.1387 +  shows   "f * g * h = f * (g * h)"
  4.1388 +  using   assms
  4.1389 +  by      (simp add: fls_times_conv_fps_times fls_subdegree_fls_to_fps_gt0 mult.assoc)
  4.1390 +
  4.1391 +lemma fls_mult_assoc_base_factor:
  4.1392 +  fixes a b c :: "'a::semiring_0 fls"
  4.1393 +  shows
  4.1394 +    "fls_base_factor a * fls_base_factor b * fls_base_factor c =
  4.1395 +      fls_base_factor a * (fls_base_factor b * fls_base_factor c)"
  4.1396 +  by    (simp add: fls_mult_assoc_subdegree_ge_0 del: fls_base_factor_def)
  4.1397 +
  4.1398 +lemma fls_mult_distrib_subdegree_ge_0:
  4.1399 +  fixes   f g h :: "'a::semiring_0 fls"
  4.1400 +  assumes "fls_subdegree f \<ge> 0" "fls_subdegree g \<ge> 0" "fls_subdegree h \<ge> 0"
  4.1401 +  shows   "(f + g) * h = f * h + g * h"
  4.1402 +  and     "h * (f + g) = h * f + h * g"
  4.1403 +proof-
  4.1404 +  have "fls_subdegree (f+g) \<ge> 0"
  4.1405 +  proof (cases "f+g = 0")
  4.1406 +    case False
  4.1407 +    with assms(1,2) show ?thesis
  4.1408 +      using fls_plus_subdegree by fastforce
  4.1409 +  qed simp
  4.1410 +  with assms show "(f + g) * h = f * h + g * h" "h * (f + g) = h * f + h * g"
  4.1411 +    using distrib_right[of "fls_regpart f"] distrib_left[of "fls_regpart h"]
  4.1412 +    by    (simp_all add: fls_times_conv_fps_times)
  4.1413 +qed
  4.1414 +
  4.1415 +lemma fls_mult_distrib_base_factor:
  4.1416 +  fixes a b c :: "'a::semiring_0 fls"
  4.1417 +  shows
  4.1418 +    "fls_base_factor a * (fls_base_factor b + fls_base_factor c) =
  4.1419 +      fls_base_factor a * fls_base_factor b + fls_base_factor a * fls_base_factor c"
  4.1420 +  by    (simp add: fls_mult_distrib_subdegree_ge_0 del: fls_base_factor_def)
  4.1421 +
  4.1422 +instance fls :: (semiring_0) semiring_0
  4.1423 +proof
  4.1424 +
  4.1425 +  fix a b c :: "'a fls"
  4.1426 +  have
  4.1427 +    "a * b * c =
  4.1428 +      fls_shift (- (fls_subdegree a + fls_subdegree b + fls_subdegree c))
  4.1429 +        (fls_base_factor a * fls_base_factor b * fls_base_factor c)"
  4.1430 +    by (simp add: fls_times_both_shifted_simp)
  4.1431 +  moreover have
  4.1432 +    "a * (b * c) =
  4.1433 +      fls_shift (- (fls_subdegree a + fls_subdegree b + fls_subdegree c))
  4.1434 +        (fls_base_factor a * fls_base_factor b * fls_base_factor c)"
  4.1435 +    using fls_mult_assoc_base_factor[of a b c] by (simp add: fls_times_both_shifted_simp)
  4.1436 +  ultimately show "a * b * c = a * (b * c)" by simp
  4.1437 +
  4.1438 +  have ab:
  4.1439 +    "fls_subdegree (fls_shift (min (fls_subdegree a) (fls_subdegree b)) a) \<ge> 0"
  4.1440 +    "fls_subdegree (fls_shift (min (fls_subdegree a) (fls_subdegree b)) b) \<ge> 0"
  4.1441 +    by (simp_all add: fls_shift_nonneg_subdegree)
  4.1442 +  have
  4.1443 +    "(a + b) * c =
  4.1444 +      fls_shift (- (min (fls_subdegree a) (fls_subdegree b) + fls_subdegree c)) (
  4.1445 +        (
  4.1446 +          fls_shift (min (fls_subdegree a) (fls_subdegree b)) a +
  4.1447 +          fls_shift (min (fls_subdegree a) (fls_subdegree b)) b
  4.1448 +        ) * fls_base_factor c)"
  4.1449 +    using fls_times_both_shifted_simp[of
  4.1450 +            "-min (fls_subdegree a) (fls_subdegree b)"
  4.1451 +            "fls_shift (min (fls_subdegree a) (fls_subdegree b)) a +
  4.1452 +            fls_shift (min (fls_subdegree a) (fls_subdegree b)) b"
  4.1453 +            "-fls_subdegree c" "fls_base_factor c"
  4.1454 +          ]
  4.1455 +    by    simp
  4.1456 +  also have
  4.1457 +    "\<dots> =
  4.1458 +      fls_shift (-(min (fls_subdegree a) (fls_subdegree b) + fls_subdegree c))
  4.1459 +        (fls_shift (min (fls_subdegree a) (fls_subdegree b)) a * fls_base_factor c)
  4.1460 +      +
  4.1461 +      fls_shift (-(min (fls_subdegree a) (fls_subdegree b) + fls_subdegree c))
  4.1462 +        (fls_shift (min (fls_subdegree a) (fls_subdegree b)) b * fls_base_factor c)"
  4.1463 +    using ab
  4.1464 +    by    (simp add: fls_mult_distrib_subdegree_ge_0(1) del: fls_base_factor_def)
  4.1465 +  finally show "(a + b) * c = a * c + b * c" by (simp add: fls_times_both_shifted_simp)
  4.1466 +
  4.1467 +  have bc:
  4.1468 +    "fls_subdegree (fls_shift (min (fls_subdegree b) (fls_subdegree c)) b) \<ge> 0"
  4.1469 +    "fls_subdegree (fls_shift (min (fls_subdegree b) (fls_subdegree c)) c) \<ge> 0"
  4.1470 +    by (simp_all add: fls_shift_nonneg_subdegree)
  4.1471 +  have
  4.1472 +    "a * (b + c) = 
  4.1473 +      fls_shift (- (fls_subdegree a + min (fls_subdegree b) (fls_subdegree c))) (
  4.1474 +        fls_base_factor a * (
  4.1475 +          fls_shift (min (fls_subdegree b) (fls_subdegree c)) b +
  4.1476 +          fls_shift (min (fls_subdegree b) (fls_subdegree c)) c
  4.1477 +        )
  4.1478 +      )
  4.1479 +    "
  4.1480 +    using fls_times_both_shifted_simp[of
  4.1481 +            "-fls_subdegree a" "fls_base_factor a"
  4.1482 +            "-min (fls_subdegree b) (fls_subdegree c)"
  4.1483 +            "fls_shift (min (fls_subdegree b) (fls_subdegree c)) b +
  4.1484 +            fls_shift (min (fls_subdegree b) (fls_subdegree c)) c"
  4.1485 +          ]
  4.1486 +    by    simp
  4.1487 +  also have
  4.1488 +    "\<dots> =
  4.1489 +      fls_shift (-(fls_subdegree a + min (fls_subdegree b) (fls_subdegree c)))
  4.1490 +        (fls_base_factor a * fls_shift (min (fls_subdegree b) (fls_subdegree c)) b)
  4.1491 +      +
  4.1492 +      fls_shift (-(fls_subdegree a + min (fls_subdegree b) (fls_subdegree c)))
  4.1493 +        (fls_base_factor a * fls_shift (min (fls_subdegree b) (fls_subdegree c)) c)
  4.1494 +    "
  4.1495 +    using bc
  4.1496 +    by    (simp add: fls_mult_distrib_subdegree_ge_0(2) del: fls_base_factor_def)
  4.1497 +  finally show "a * (b + c)  = a * b + a * c" by (simp add: fls_times_both_shifted_simp)
  4.1498 +
  4.1499 +qed
  4.1500 +
  4.1501 +lemma fls_mult_commute_subdegree_ge_0:
  4.1502 +  fixes   f g :: "'a::comm_semiring_0 fls"
  4.1503 +  assumes "fls_subdegree f \<ge> 0" "fls_subdegree g \<ge> 0"
  4.1504 +  shows   "f * g = g * f"
  4.1505 +  using   assms
  4.1506 +  by      (simp add: fls_times_conv_fps_times mult.commute)
  4.1507 +
  4.1508 +lemma fls_mult_commute_base_factor:
  4.1509 +  fixes a b c :: "'a::comm_semiring_0 fls"
  4.1510 +  shows "fls_base_factor a * fls_base_factor b = fls_base_factor b * fls_base_factor a"
  4.1511 +  by    (simp add: fls_mult_commute_subdegree_ge_0 del: fls_base_factor_def)
  4.1512 +
  4.1513 +instance fls :: (comm_semiring_0) comm_semiring_0
  4.1514 +proof
  4.1515 +  fix a b c :: "'a fls"
  4.1516 +  show "a * b = b * a"
  4.1517 +    using fls_times_conv_base_factor_times[of a b] fls_times_conv_base_factor_times[of b a]
  4.1518 +          fls_mult_commute_base_factor[of a b]
  4.1519 +    by    (simp add: add.commute)
  4.1520 +qed (simp add: distrib_right)
  4.1521 +
  4.1522 +instance fls :: (semiring_1) semiring_1
  4.1523 +  by (standard, simp_all add: fls_mult_one)
  4.1524 +
  4.1525 +lemma fls_of_nat: "(of_nat n :: 'a::semiring_1 fls) = fls_const (of_nat n)"
  4.1526 +  by (induct n) (auto intro: fls_eqI)
  4.1527 +
  4.1528 +lemma fls_of_nat_nth: "of_nat n $$ k = (if k=0 then of_nat n else 0)"
  4.1529 +  by (simp add: fls_of_nat)
  4.1530 +
  4.1531 +lemma fls_mult_of_nat_nth [simp]:
  4.1532 +  shows "(of_nat k * f) $$ n = of_nat k * f$$n"
  4.1533 +  and   "(f * of_nat k ) $$ n = f$$n * of_nat k"
  4.1534 +  by    (simp_all add: fls_of_nat)
  4.1535 +
  4.1536 +lemma fls_subdegree_of_nat [simp]: "fls_subdegree (of_nat n) = 0"
  4.1537 +  by (simp add: fls_of_nat)
  4.1538 +
  4.1539 +lemma fls_shift_of_nat_nth:
  4.1540 +  "fls_shift k (of_nat a) $$ n = (if n=-k then of_nat a else 0)"
  4.1541 +  by (simp add: fls_of_nat fls_shift_const_nth)
  4.1542 +
  4.1543 +lemma fls_base_factor_of_nat [simp]:
  4.1544 +  "fls_base_factor (of_nat n :: 'a::semiring_1 fls) = (of_nat n :: 'a fls)"
  4.1545 +  by (simp add: fls_of_nat)
  4.1546 +
  4.1547 +lemma fls_regpart_of_nat [simp]: "fls_regpart (of_nat n) = (of_nat n :: 'a::semiring_1 fps)"
  4.1548 +  by (simp add: fls_of_nat fps_of_nat)
  4.1549 +
  4.1550 +lemma fls_prpart_of_nat [simp]: "fls_prpart (of_nat n) = 0"
  4.1551 +  by (simp add: fls_prpart_eq0_iff)
  4.1552 +
  4.1553 +lemma fls_base_factor_to_fps_of_nat:
  4.1554 +  "fls_base_factor_to_fps (of_nat n) = (of_nat n :: 'a::semiring_1 fps)"
  4.1555 +  by simp
  4.1556 +
  4.1557 +lemma fps_to_fls_of_nat:
  4.1558 +  "fps_to_fls (of_nat n) = (of_nat n :: 'a::semiring_1 fls)"
  4.1559 +proof -
  4.1560 +  have "fps_to_fls (of_nat n) = fps_to_fls (fps_const (of_nat n))"
  4.1561 +    by (simp add: fps_of_nat)
  4.1562 +  thus ?thesis by (simp add: fls_of_nat)
  4.1563 +qed
  4.1564 +
  4.1565 +instance fls :: (comm_semiring_1) comm_semiring_1
  4.1566 +  by standard simp
  4.1567 +
  4.1568 +instance fls :: (ring) ring ..
  4.1569 +
  4.1570 +instance fls :: (comm_ring) comm_ring ..
  4.1571 +
  4.1572 +instance fls :: (ring_1) ring_1 ..
  4.1573 +
  4.1574 +lemma fls_of_int_nonneg: "(of_int (int n) :: 'a::ring_1 fls) = fls_const (of_int (int n))"
  4.1575 +  by (induct n) (auto intro: fls_eqI)
  4.1576 +
  4.1577 +lemma fls_of_int: "(of_int i :: 'a::ring_1 fls) = fls_const (of_int i)"
  4.1578 +proof (induct i)
  4.1579 +  case (neg i)
  4.1580 +  have "of_int (int (Suc i)) = fls_const (of_int (int (Suc i)) :: 'a)"
  4.1581 +    using fls_of_int_nonneg[of "Suc i"] by simp
  4.1582 +  hence "- of_int (int (Suc i)) = - fls_const (of_int (int (Suc i)) :: 'a)"
  4.1583 +    by simp
  4.1584 +  thus ?case by (simp add: fls_const_uminus[symmetric])
  4.1585 +qed (rule fls_of_int_nonneg)
  4.1586 +
  4.1587 +lemma fls_of_int_nth: "of_int n $$ k = (if k=0 then of_int n else 0)"
  4.1588 +  by (simp add: fls_of_int)
  4.1589 +
  4.1590 +lemma fls_mult_of_int_nth [simp]:
  4.1591 +  shows "(of_int k * f) $$ n = of_int k * f$$n"
  4.1592 +  and   "(f * of_int k ) $$ n = f$$n * of_int k"
  4.1593 +  by    (simp_all add: fls_of_int)
  4.1594 +
  4.1595 +lemma fls_subdegree_of_int [simp]: "fls_subdegree (of_int i) = 0"
  4.1596 +  by (simp add: fls_of_int)
  4.1597 +
  4.1598 +lemma fls_shift_of_int_nth:
  4.1599 +  "fls_shift k (of_int i) $$ n = (if n=-k then of_int i else 0)"
  4.1600 +  by (simp add: fls_of_int_nth)
  4.1601 +
  4.1602 +lemma fls_base_factor_of_int [simp]:
  4.1603 +  "fls_base_factor (of_int i :: 'a::ring_1 fls) = (of_int i :: 'a fls)"
  4.1604 +  by (simp add: fls_of_int)
  4.1605 +
  4.1606 +lemma fls_regpart_of_int [simp]:
  4.1607 +  "fls_regpart (of_int i) = (of_int i :: 'a::ring_1 fps)"
  4.1608 +  by (simp add: fls_of_int fps_of_int)
  4.1609 +
  4.1610 +lemma fls_prpart_of_int [simp]: "fls_prpart (of_int n) = 0"
  4.1611 +  by (simp add: fls_prpart_eq0_iff)
  4.1612 +
  4.1613 +lemma fls_base_factor_to_fps_of_int:
  4.1614 +  "fls_base_factor_to_fps (of_int i) = (of_int i :: 'a::ring_1 fps)"
  4.1615 +  by simp
  4.1616 +
  4.1617 +lemma fps_to_fls_of_int:
  4.1618 +  "fps_to_fls (of_int i) = (of_int i :: 'a::ring_1 fls)"
  4.1619 +proof -
  4.1620 +  have "fps_to_fls (of_int i) = fps_to_fls (fps_const (of_int i))"
  4.1621 +    by (simp add: fps_of_int)
  4.1622 +  thus ?thesis by (simp add: fls_of_int)
  4.1623 +qed
  4.1624 +
  4.1625 +instance fls :: (comm_ring_1) comm_ring_1 ..
  4.1626 +
  4.1627 +instance fls :: (semiring_no_zero_divisors) semiring_no_zero_divisors
  4.1628 +proof
  4.1629 +  fix a b :: "'a fls"
  4.1630 +  assume "a \<noteq> 0" and "b \<noteq> 0"
  4.1631 +  hence "(a * b) $$ (fls_subdegree a + fls_subdegree b) \<noteq> 0" by simp
  4.1632 +  thus "a * b \<noteq> 0" using fls_nonzeroI by fast
  4.1633 +qed
  4.1634 +
  4.1635 +instance fls :: (semiring_1_no_zero_divisors) semiring_1_no_zero_divisors ..
  4.1636 +
  4.1637 +instance fls :: (ring_no_zero_divisors) ring_no_zero_divisors ..
  4.1638 +
  4.1639 +instance fls :: (ring_1_no_zero_divisors) ring_1_no_zero_divisors ..
  4.1640 +
  4.1641 +instance fls :: (idom) idom ..
  4.1642 +
  4.1643 +
  4.1644 +subsubsection \<open>Powers\<close>
  4.1645 +
  4.1646 +lemma fls_pow_subdegree_ge:
  4.1647 +  "f^n \<noteq> 0 \<Longrightarrow> fls_subdegree (f^n) \<ge> n * fls_subdegree f"
  4.1648 +proof (induct n)
  4.1649 +  case (Suc n) thus ?case
  4.1650 +    using fls_mult_subdegree_ge[of f "f^n"] by (fastforce simp: algebra_simps)
  4.1651 +qed simp
  4.1652 +
  4.1653 +lemma fls_pow_nth_below_subdegree:
  4.1654 +  "k < n * fls_subdegree f \<Longrightarrow> (f^n) $$ k = 0"
  4.1655 +  using fls_pow_subdegree_ge[of f n] by (cases "f^n = 0") auto
  4.1656 +
  4.1657 +lemma fls_pow_base [simp]:
  4.1658 +  "(f ^ n) $$ (n * fls_subdegree f) = (f $$ fls_subdegree f) ^ n"
  4.1659 +proof (induct n)
  4.1660 +  case (Suc n)
  4.1661 +  show ?case
  4.1662 +  proof (cases "Suc n * fls_subdegree f < fls_subdegree f + fls_subdegree (f^n)")
  4.1663 +    case True with Suc show ?thesis
  4.1664 +      by (simp_all add: fls_times_nth_eq0 distrib_right)
  4.1665 +  next
  4.1666 +    case False
  4.1667 +    from False have
  4.1668 +      "{0..int n * fls_subdegree f - fls_subdegree (f ^ n)} =
  4.1669 +        insert 0 {1..int n * fls_subdegree f - fls_subdegree (f ^ n)}"
  4.1670 +      by (auto simp: algebra_simps)
  4.1671 +    with False Suc show ?thesis
  4.1672 +      by (simp add: algebra_simps fls_times_nth(4) fls_pow_nth_below_subdegree)
  4.1673 +  qed
  4.1674 +qed simp
  4.1675 +
  4.1676 +lemma fls_pow_subdegree_eqI:
  4.1677 +  "(f $$ fls_subdegree f) ^ n \<noteq> 0 \<Longrightarrow> fls_subdegree (f^n) = n * fls_subdegree f"
  4.1678 +  using fls_pow_nth_below_subdegree by (fastforce intro: fls_subdegree_eqI)
  4.1679 +
  4.1680 +lemma fls_unit_base_subdegree_power:
  4.1681 +  "x * f $$ fls_subdegree f = 1 \<Longrightarrow> fls_subdegree (f ^ n) = n * fls_subdegree f"
  4.1682 +  "f $$ fls_subdegree f * y = 1 \<Longrightarrow> fls_subdegree (f ^ n) = n * fls_subdegree f"
  4.1683 +proof-
  4.1684 +  show "x * f $$ fls_subdegree f = 1 \<Longrightarrow> fls_subdegree (f ^ n) = n * fls_subdegree f"
  4.1685 +    using left_right_inverse_power[of x "f $$ fls_subdegree f" n]
  4.1686 +    by    (auto intro: fls_pow_subdegree_eqI)
  4.1687 +  show "f $$ fls_subdegree f * y = 1 \<Longrightarrow> fls_subdegree (f ^ n) = n * fls_subdegree f"
  4.1688 +    using left_right_inverse_power[of "f $$ fls_subdegree f" y n]
  4.1689 +    by    (auto intro: fls_pow_subdegree_eqI)
  4.1690 +qed
  4.1691 +
  4.1692 +lemma fls_base_dvd1_subdegree_power:
  4.1693 +  "f $$ fls_subdegree f dvd 1 \<Longrightarrow> fls_subdegree (f ^ n) = n * fls_subdegree f"
  4.1694 +  using fls_unit_base_subdegree_power unfolding dvd_def by auto
  4.1695 +
  4.1696 +lemma fls_pow_subdegree_ge0:
  4.1697 +  assumes "fls_subdegree f \<ge> 0"
  4.1698 +  shows   "fls_subdegree (f^n) \<ge> 0"
  4.1699 +proof (cases "f^n = 0")
  4.1700 +  case False
  4.1701 +  moreover from assms have "int n * fls_subdegree f \<ge> 0" by simp
  4.1702 +  ultimately show ?thesis using fls_pow_subdegree_ge by fastforce
  4.1703 +qed simp
  4.1704 +
  4.1705 +lemma fls_subdegree_pow:
  4.1706 +  fixes   f :: "'a::semiring_1_no_zero_divisors fls"
  4.1707 +  shows   "fls_subdegree (f ^ n) = n * fls_subdegree f"
  4.1708 +proof (cases "f=0")
  4.1709 +  case False thus ?thesis by (induct n) (simp_all add: algebra_simps)
  4.1710 +qed (cases "n=0", auto simp: zero_power)
  4.1711 +
  4.1712 +lemma fls_shifted_pow:
  4.1713 +  "(fls_shift m f) ^ n = fls_shift (n*m) (f ^ n)"
  4.1714 +  by (induct n) (simp_all add: fls_times_both_shifted_simp algebra_simps)
  4.1715 +
  4.1716 +lemma fls_pow_conv_fps_pow:
  4.1717 +  assumes "fls_subdegree f \<ge> 0"
  4.1718 +  shows   "f ^ n = fps_to_fls ( (fls_regpart f) ^ n )"
  4.1719 +proof (induct n)
  4.1720 +  case (Suc n) with assms show ?case
  4.1721 +    using fls_pow_subdegree_ge0[of f n]
  4.1722 +    by (simp add: fls_times_conv_fps_times)
  4.1723 +qed simp
  4.1724 +
  4.1725 +lemma fls_pow_conv_regpart:
  4.1726 +  "fls_subdegree f \<ge> 0 \<Longrightarrow> fls_regpart (f ^ n) = (fls_regpart f) ^ n"
  4.1727 +  using fls_pow_subdegree_ge0[of f n] fls_pow_conv_fps_pow[of f n]
  4.1728 +  by    (intro fps_to_fls_eq_imp_fps_eq) simp
  4.1729 +
  4.1730 +text \<open>These two lemmas show that shifting 1 is equivalent to powers of the implied variable.\<close>
  4.1731 +
  4.1732 +lemma fls_X_power_conv_shift_1: "fls_X ^ n = fls_shift (-n) 1"
  4.1733 +  by (simp add: fls_X_conv_shift_1 fls_shifted_pow)
  4.1734 +
  4.1735 +lemma fls_X_inv_power_conv_shift_1: "fls_X_inv ^ n = fls_shift n 1"
  4.1736 +  by (simp add: fls_X_inv_conv_shift_1 fls_shifted_pow)
  4.1737 +
  4.1738 +abbreviation "fls_X_intpow \<equiv> (\<lambda>i. fls_shift (-i) 1)"
  4.1739 +\<comment> \<open>
  4.1740 +  Unifies @{term fls_X} and @{term fls_X_inv} so that @{term "fls_X_intpow"} returns the equivalent
  4.1741 +  of the implied variable raised to the supplied integer argument of @{term "fls_X_intpow"}, whether
  4.1742 +  positive or negative.
  4.1743 +\<close>
  4.1744 +
  4.1745 +lemma fls_X_intpow_nonzero[simp]: "(fls_X_intpow i :: 'a::zero_neq_one fls) \<noteq> 0"
  4.1746 +  by (simp add: fls_shift_eq0_iff)
  4.1747 +
  4.1748 +lemma fls_X_intpow_power: "(fls_X_intpow i) ^ n = fls_X_intpow (n * i)"
  4.1749 +  by (simp add: fls_shifted_pow)
  4.1750 +
  4.1751 +lemma fls_X_power_nth [simp]: "fls_X ^ n $$ k = (if k=n then 1 else 0)"
  4.1752 +  by (simp add: fls_X_power_conv_shift_1)
  4.1753 +
  4.1754 +lemma fls_X_inv_power_nth [simp]: "fls_X_inv ^ n $$ k = (if k=-n then 1 else 0)"
  4.1755 +  by (simp add: fls_X_inv_power_conv_shift_1)
  4.1756 +
  4.1757 +lemma fls_X_pow_nonzero[simp]: "(fls_X ^ n :: 'a :: semiring_1 fls) \<noteq> 0"
  4.1758 +proof
  4.1759 +  assume "(fls_X ^ n :: 'a fls) = 0"
  4.1760 +  hence "(fls_X ^ n :: 'a fls) $$ n = 0" by simp
  4.1761 +  thus False by simp
  4.1762 +qed
  4.1763 +
  4.1764 +lemma fls_X_inv_pow_nonzero[simp]: "(fls_X_inv ^ n :: 'a :: semiring_1 fls) \<noteq> 0"
  4.1765 +proof
  4.1766 +  assume "(fls_X_inv ^ n :: 'a fls) = 0"
  4.1767 +  hence "(fls_X_inv ^ n :: 'a fls) $$ -n = 0" by simp
  4.1768 +  thus False by simp
  4.1769 +qed
  4.1770 +
  4.1771 +lemma fls_subdegree_fls_X_pow [simp]: "fls_subdegree (fls_X ^ n) = n"
  4.1772 +  by (intro fls_subdegree_eqI) (simp_all add: fls_X_power_conv_shift_1)
  4.1773 +
  4.1774 +lemma fls_subdegree_fls_X_inv_pow [simp]: "fls_subdegree (fls_X_inv ^ n) = -n"
  4.1775 +  by (intro fls_subdegree_eqI) (simp_all add: fls_X_inv_power_conv_shift_1)
  4.1776 +
  4.1777 +lemma fls_subdegree_fls_X_intpow [simp]:
  4.1778 +  "fls_subdegree ((fls_X_intpow i) :: 'a::zero_neq_one fls) = i"
  4.1779 +  by simp
  4.1780 +
  4.1781 +lemma fls_X_pow_conv_fps_X_pow: "fls_regpart (fls_X ^ n) = fps_X ^ n"
  4.1782 +  by (simp add: fls_pow_conv_regpart)
  4.1783 +
  4.1784 +lemma fls_X_inv_pow_regpart: "n > 0 \<Longrightarrow> fls_regpart (fls_X_inv ^ n) = 0"
  4.1785 +  by (auto intro: fps_ext simp: fls_X_inv_power_conv_shift_1)
  4.1786 +
  4.1787 +lemma fls_X_intpow_regpart:
  4.1788 +  "fls_regpart (fls_X_intpow i) = (if i\<ge>0 then fps_X ^ nat i else 0)"
  4.1789 +  using fls_X_pow_conv_fps_X_pow[of "nat i"]
  4.1790 +        fls_regpart_shift_conv_fps_shift[of "-i" 1]
  4.1791 +  by    (auto simp: fls_X_power_conv_shift_1 fps_shift_one)
  4.1792 +
  4.1793 +lemma fls_X_power_times_conv_shift:
  4.1794 +  "fls_X ^ n * f = fls_shift (-int n) f" "f * fls_X ^ n = fls_shift (-int n) f"
  4.1795 +  using fls_times_both_shifted_simp[of "-int n" 1 0 f]
  4.1796 +        fls_times_both_shifted_simp[of 0 f "-int n" 1]
  4.1797 +  by    (simp_all add: fls_X_power_conv_shift_1)
  4.1798 +
  4.1799 +lemma fls_X_inv_power_times_conv_shift:
  4.1800 +  "fls_X_inv ^ n * f = fls_shift (int n) f" "f * fls_X_inv ^ n = fls_shift (int n) f"
  4.1801 +  using fls_times_both_shifted_simp[of "int n" 1 0 f]
  4.1802 +        fls_times_both_shifted_simp[of 0 f "int n" 1]
  4.1803 +  by    (simp_all add: fls_X_inv_power_conv_shift_1)
  4.1804 +
  4.1805 +lemma fls_X_intpow_times_conv_shift:
  4.1806 +  fixes f :: "'a::semiring_1 fls"
  4.1807 +  shows "fls_X_intpow i * f = fls_shift (-i) f" "f * fls_X_intpow i = fls_shift (-i) f"
  4.1808 +  by    (simp_all add: fls_shifted_times_simps)
  4.1809 +
  4.1810 +lemmas fls_X_power_times_comm     = trans_sym[OF fls_X_power_times_conv_shift]
  4.1811 +lemmas fls_X_inv_power_times_comm = trans_sym[OF fls_X_inv_power_times_conv_shift]
  4.1812 +
  4.1813 +lemma fls_X_intpow_times_comm:
  4.1814 +  fixes f :: "'a::semiring_1 fls"
  4.1815 +  shows "fls_X_intpow i * f = f * fls_X_intpow i"
  4.1816 +  by    (simp add: fls_X_intpow_times_conv_shift)
  4.1817 +
  4.1818 +lemma fls_X_intpow_times_fls_X_intpow:
  4.1819 +  "(fls_X_intpow i :: 'a::semiring_1 fls) * fls_X_intpow j = fls_X_intpow (i+j)"
  4.1820 +  by (simp add: fls_times_both_shifted_simp)
  4.1821 +
  4.1822 +lemma fls_X_intpow_diff_conv_times:
  4.1823 +  "fls_X_intpow (i-j) = (fls_X_intpow i :: 'a::semiring_1 fls) * fls_X_intpow (-j)"
  4.1824 +  using fls_X_intpow_times_fls_X_intpow[of i "-j",symmetric] by simp
  4.1825 +
  4.1826 +lemma fls_mult_fls_X_power_nonzero:
  4.1827 +  assumes "f \<noteq> 0"
  4.1828 +  shows   "fls_X ^ n * f \<noteq> 0" "f * fls_X ^ n \<noteq> 0"
  4.1829 +  by      (auto simp: fls_X_power_times_conv_shift fls_shift_eq0_iff assms)
  4.1830 +
  4.1831 +lemma fls_mult_fls_X_inv_power_nonzero:
  4.1832 +  assumes "f \<noteq> 0"
  4.1833 +  shows   "fls_X_inv ^ n * f \<noteq> 0" "f * fls_X_inv ^ n \<noteq> 0"
  4.1834 +  by      (auto simp: fls_X_inv_power_times_conv_shift fls_shift_eq0_iff assms)
  4.1835 +
  4.1836 +lemma fls_mult_fls_X_intpow_nonzero:
  4.1837 +  fixes f :: "'a::semiring_1 fls"
  4.1838 +  assumes "f \<noteq> 0"
  4.1839 +  shows   "fls_X_intpow i * f \<noteq> 0" "f * fls_X_intpow i \<noteq> 0"
  4.1840 +  by      (auto simp: fls_X_intpow_times_conv_shift fls_shift_eq0_iff assms)
  4.1841 +
  4.1842 +lemma fls_subdegree_mult_fls_X_power:
  4.1843 +  assumes "f \<noteq> 0"
  4.1844 +  shows   "fls_subdegree (fls_X ^ n * f) = fls_subdegree f + n"
  4.1845 +  and     "fls_subdegree (f * fls_X ^ n) = fls_subdegree f + n"
  4.1846 +  by      (auto simp: fls_X_power_times_conv_shift assms)
  4.1847 +
  4.1848 +lemma fls_subdegree_mult_fls_X_inv_power:
  4.1849 +  assumes "f \<noteq> 0"
  4.1850 +  shows   "fls_subdegree (fls_X_inv ^ n * f) = fls_subdegree f - n"
  4.1851 +  and     "fls_subdegree (f * fls_X_inv ^ n) = fls_subdegree f - n"
  4.1852 +  by      (auto simp: fls_X_inv_power_times_conv_shift assms)
  4.1853 +
  4.1854 +lemma fls_subdegree_mult_fls_X_intpow:
  4.1855 +  fixes   f :: "'a::semiring_1 fls"
  4.1856 +  assumes "f \<noteq> 0"
  4.1857 +  shows   "fls_subdegree (fls_X_intpow i * f) = fls_subdegree f + i"
  4.1858 +  and     "fls_subdegree (f * fls_X_intpow i) = fls_subdegree f + i"
  4.1859 +  by      (auto simp: fls_X_intpow_times_conv_shift assms)
  4.1860 +
  4.1861 +lemma fls_X_shift:
  4.1862 +  "fls_shift (-int n) fls_X = fls_X ^ Suc n"
  4.1863 +  "fls_shift (int (Suc n)) fls_X = fls_X_inv ^ n"
  4.1864 +  using fls_X_power_conv_shift_1[of "Suc n", symmetric]
  4.1865 +  by    (simp_all add: fls_X_conv_shift_1 fls_X_inv_power_conv_shift_1)
  4.1866 +
  4.1867 +lemma fls_X_inv_shift:
  4.1868 +  "fls_shift (int n) fls_X_inv = fls_X_inv ^ Suc n"
  4.1869 +  "fls_shift (- int (Suc n)) fls_X_inv = fls_X ^ n"
  4.1870 +  using fls_X_inv_power_conv_shift_1[of "Suc n", symmetric]
  4.1871 +  by    (simp_all add: fls_X_inv_conv_shift_1 fls_X_power_conv_shift_1)
  4.1872 +
  4.1873 +lemma fls_X_power_base_factor: "fls_base_factor (fls_X ^ n) = 1"
  4.1874 +  by (simp add: fls_X_power_conv_shift_1)
  4.1875 +
  4.1876 +lemma fls_X_inv_power_base_factor: "fls_base_factor (fls_X_inv ^ n) = 1"
  4.1877 +  by (simp add: fls_X_inv_power_conv_shift_1)
  4.1878 +
  4.1879 +lemma fls_X_intpow_base_factor: "fls_base_factor (fls_X_intpow i) = 1"
  4.1880 +  using fls_base_factor_shift[of "-i" 1] by simp
  4.1881 +
  4.1882 +lemma fls_base_factor_mult_fls_X_power:
  4.1883 +  shows "fls_base_factor (fls_X ^ n * f) = fls_base_factor f"
  4.1884 +  and   "fls_base_factor (f * fls_X ^ n) = fls_base_factor f"
  4.1885 +  using fls_base_factor_shift[of "-int n" f]
  4.1886 +  by    (auto simp: fls_X_power_times_conv_shift)
  4.1887 +
  4.1888 +lemma fls_base_factor_mult_fls_X_inv_power:
  4.1889 +  shows "fls_base_factor (fls_X_inv ^ n * f) = fls_base_factor f"
  4.1890 +  and   "fls_base_factor (f * fls_X_inv ^ n) = fls_base_factor f"
  4.1891 +  using fls_base_factor_shift[of "int n" f]
  4.1892 +  by    (auto simp: fls_X_inv_power_times_conv_shift)
  4.1893 +
  4.1894 +lemma fls_base_factor_mult_fls_X_intpow:
  4.1895 +  fixes f :: "'a::semiring_1 fls"
  4.1896 +  shows "fls_base_factor (fls_X_intpow i * f) = fls_base_factor f"
  4.1897 +  and   "fls_base_factor (f * fls_X_intpow i) = fls_base_factor f"
  4.1898 +  using fls_base_factor_shift[of "-i" f]
  4.1899 +  by    (auto simp: fls_X_intpow_times_conv_shift)
  4.1900 +
  4.1901 +lemma fls_X_power_base_factor_to_fps: "fls_base_factor_to_fps (fls_X ^ n) = 1"
  4.1902 +proof-
  4.1903 +  define X where "X \<equiv> fls_X :: 'a::semiring_1 fls"
  4.1904 +  hence "fls_base_factor (X ^ n) = 1" using fls_X_power_base_factor by simp
  4.1905 +  thus "fls_base_factor_to_fps (X^n) = 1" by simp
  4.1906 +qed  
  4.1907 +
  4.1908 +lemma fls_X_inv_power_base_factor_to_fps: "fls_base_factor_to_fps (fls_X_inv ^ n) = 1"
  4.1909 +proof-
  4.1910 +  define iX where "iX \<equiv> fls_X_inv :: 'a::semiring_1 fls"
  4.1911 +  hence "fls_base_factor (iX ^ n) = 1" using fls_X_inv_power_base_factor by simp
  4.1912 +  thus "fls_base_factor_to_fps (iX^n) = 1" by simp
  4.1913 +qed  
  4.1914 +
  4.1915 +lemma fls_X_intpow_base_factor_to_fps: "fls_base_factor_to_fps (fls_X_intpow i) = 1"
  4.1916 +proof-
  4.1917 +  define f :: "'a fls" where "f \<equiv> fls_X_intpow i"
  4.1918 +  moreover have "fls_base_factor (fls_X_intpow i) = 1" by (rule fls_X_intpow_base_factor)
  4.1919 +  ultimately have "fls_base_factor f = 1" by simp
  4.1920 +  thus "fls_base_factor_to_fps f = 1" by simp
  4.1921 +qed
  4.1922 +
  4.1923 +lemma fls_base_factor_X_power_decompose:
  4.1924 +  fixes f :: "'a::semiring_1 fls"
  4.1925 +  shows "f = fls_base_factor f * fls_X_intpow (fls_subdegree f)"
  4.1926 +  and   "f = fls_X_intpow (fls_subdegree f) * fls_base_factor f"
  4.1927 +  by    (simp_all add: fls_times_both_shifted_simp)
  4.1928 +
  4.1929 +lemma fls_normalized_product_of_inverses:
  4.1930 +  assumes "f * g = 1"
  4.1931 +  shows   "fls_base_factor f * fls_base_factor g =
  4.1932 +            fls_X ^ (nat (-(fls_subdegree f+fls_subdegree g)))"
  4.1933 +  and     "fls_base_factor f * fls_base_factor g =
  4.1934 +            fls_X_intpow (-(fls_subdegree f+fls_subdegree g))"
  4.1935 +  using   fls_mult_subdegree_ge[of f g]
  4.1936 +          fls_times_base_factor_conv_shifted_times[of f g]
  4.1937 +  by      (simp_all add: assms fls_X_power_conv_shift_1 algebra_simps)
  4.1938 +
  4.1939 +lemma fls_fps_normalized_product_of_inverses:
  4.1940 +  assumes "f * g = 1"
  4.1941 +  shows   "fls_base_factor_to_fps f * fls_base_factor_to_fps g =
  4.1942 +            fps_X ^ (nat (-(fls_subdegree f+fls_subdegree g)))"
  4.1943 +  using fls_times_conv_regpart[of "fls_base_factor f" "fls_base_factor g"]
  4.1944 +        fls_base_factor_subdegree[of f] fls_base_factor_subdegree[of g]
  4.1945 +        fls_normalized_product_of_inverses(1)[OF assms]
  4.1946 +  by    (force simp: fls_X_pow_conv_fps_X_pow)
  4.1947 +
  4.1948 +
  4.1949 +subsubsection \<open>Inverses\<close>
  4.1950 +
  4.1951 +\<comment> \<open>See lemma fls_left_inverse\<close> 
  4.1952 +abbreviation fls_left_inverse ::
  4.1953 +  "'a::{comm_monoid_add,uminus,times} fls \<Rightarrow> 'a \<Rightarrow> 'a fls"
  4.1954 +  where
  4.1955 +  "fls_left_inverse f x \<equiv>
  4.1956 +    fls_shift (fls_subdegree f) (fps_to_fls (fps_left_inverse (fls_base_factor_to_fps f) x))"
  4.1957 +
  4.1958 +\<comment> \<open>See lemma fls_right_inverse\<close> 
  4.1959 +abbreviation fls_right_inverse ::
  4.1960 +  "'a::{comm_monoid_add,uminus,times} fls \<Rightarrow> 'a \<Rightarrow> 'a fls"
  4.1961 +  where
  4.1962 +  "fls_right_inverse f y \<equiv>
  4.1963 +    fls_shift (fls_subdegree f) (fps_to_fls (fps_right_inverse (fls_base_factor_to_fps f) y))"
  4.1964 +
  4.1965 +instantiation fls :: ("{comm_monoid_add,uminus,times,inverse}") inverse
  4.1966 +begin
  4.1967 +  definition fls_divide_def:
  4.1968 +    "f div g =
  4.1969 +      fls_shift (fls_subdegree g - fls_subdegree f) (
  4.1970 +        fps_to_fls ((fls_base_factor_to_fps f) div (fls_base_factor_to_fps g))
  4.1971 +      )
  4.1972 +    "
  4.1973 +  definition fls_inverse_def:
  4.1974 +    "inverse f = fls_shift (fls_subdegree f) (fps_to_fls (inverse (fls_base_factor_to_fps f)))"
  4.1975 +  instance ..
  4.1976 +end
  4.1977 +
  4.1978 +lemma fls_inverse_def':
  4.1979 +  "inverse f = fls_right_inverse f (inverse (f $$ fls_subdegree f))"
  4.1980 +  by (simp add: fls_inverse_def fps_inverse_def)
  4.1981 +
  4.1982 +lemma fls_lr_inverse_base:
  4.1983 +  "fls_left_inverse f x $$ (-fls_subdegree f) = x"
  4.1984 +  "fls_right_inverse f y $$ (-fls_subdegree f) = y"
  4.1985 +  by auto
  4.1986 +
  4.1987 +lemma fls_inverse_base:
  4.1988 +  "f \<noteq> 0 \<Longrightarrow> inverse f $$ (-fls_subdegree f) = inverse (f $$ fls_subdegree f)"
  4.1989 +  by (simp add: fls_inverse_def')
  4.1990 +
  4.1991 +lemma fls_lr_inverse_starting0:
  4.1992 +  fixes f :: "'a::{comm_monoid_add,mult_zero,uminus} fls"
  4.1993 +  and   g :: "'b::{ab_group_add,mult_zero} fls"
  4.1994 +  shows "fls_left_inverse f 0 = 0"
  4.1995 +  and   "fls_right_inverse g 0 = 0"
  4.1996 +  by    (simp_all add: fps_lr_inverse_starting0)
  4.1997 +
  4.1998 +lemma fls_lr_inverse_eq0_imp_starting0:
  4.1999 +  "fls_left_inverse f x = 0 \<Longrightarrow> x = 0"
  4.2000 +  "fls_right_inverse f x = 0 \<Longrightarrow> x = 0"
  4.2001 +proof-
  4.2002 +  assume "fls_left_inverse f x = 0"
  4.2003 +  hence "fps_left_inverse (fls_base_factor_to_fps f) x = 0"
  4.2004 +    using fls_shift_eq_iff fps_to_fls_eq_zero_iff by fastforce
  4.2005 +  thus "x = 0" using fps_lr_inverse_eq0_imp_starting0(1) by fast
  4.2006 +next
  4.2007 +  assume "fls_right_inverse f x = 0"
  4.2008 +  hence "fps_right_inverse (fls_base_factor_to_fps f) x = 0"
  4.2009 +    using fls_shift_eq_iff fps_to_fls_eq_zero_iff by fastforce
  4.2010 +  thus "x = 0" using fps_lr_inverse_eq0_imp_starting0(2) by fast
  4.2011 +qed
  4.2012 +
  4.2013 +lemma fls_lr_inverse_eq_0_iff:
  4.2014 +  fixes x :: "'a::{comm_monoid_add,mult_zero,uminus}"
  4.2015 +  and   y :: "'b::{ab_group_add,mult_zero}"
  4.2016 +  shows "fls_left_inverse f x = 0 \<longleftrightarrow> x = 0"
  4.2017 +  and   "fls_right_inverse g y = 0 \<longleftrightarrow> y = 0"
  4.2018 +  using fls_lr_inverse_starting0 fls_lr_inverse_eq0_imp_starting0
  4.2019 +  by    auto
  4.2020 +
  4.2021 +lemma fls_inverse_eq_0_iff':
  4.2022 +  fixes f :: "'a::{ab_group_add,inverse,mult_zero} fls"
  4.2023 +  shows "inverse f = 0 \<longleftrightarrow> (inverse (f $$ fls_subdegree f) = 0)"
  4.2024 +  using fls_lr_inverse_eq_0_iff(2)[of f "inverse (f $$ fls_subdegree f)"]
  4.2025 +  by    (simp add: fls_inverse_def')
  4.2026 +
  4.2027 +lemma fls_inverse_eq_0_iff[simp]:
  4.2028 +  "inverse f = (0:: ('a::division_ring) fls) \<longleftrightarrow> f $$ fls_subdegree f = 0"
  4.2029 +  using fls_inverse_eq_0_iff'[of f] by (cases "f=0") auto
  4.2030 +
  4.2031 +lemmas fls_inverse_eq_0' = iffD2[OF fls_inverse_eq_0_iff']
  4.2032 +lemmas fls_inverse_eq_0  = iffD2[OF fls_inverse_eq_0_iff]
  4.2033 +
  4.2034 +lemma fls_lr_inverse_const:
  4.2035 +  fixes a :: "'a::{ab_group_add,mult_zero}"
  4.2036 +  and   b :: "'b::{comm_monoid_add,mult_zero,uminus}"
  4.2037 +  shows "fls_left_inverse (fls_const a) x = fls_const x"
  4.2038 +  and   "fls_right_inverse (fls_const b) y = fls_const y"
  4.2039 +  by    (simp_all add: fps_const_lr_inverse)
  4.2040 +
  4.2041 +lemma fls_inverse_const:
  4.2042 +  fixes a :: "'a::{comm_monoid_add,inverse,mult_zero,uminus}"
  4.2043 +  shows "inverse (fls_const a) = fls_const (inverse a)"
  4.2044 +  using fls_lr_inverse_const(2)
  4.2045 +  by    (auto simp: fls_inverse_def')
  4.2046 +
  4.2047 +lemma fls_lr_inverse_of_nat:
  4.2048 +  fixes x :: "'a::{ring_1,mult_zero}"
  4.2049 +  and   y :: "'b::{semiring_1,uminus}"
  4.2050 +  shows "fls_left_inverse (of_nat n) x = fls_const x"
  4.2051 +  and   "fls_right_inverse (of_nat n) y = fls_const y"
  4.2052 +  using fls_lr_inverse_const
  4.2053 +  by    (auto simp: fls_of_nat)
  4.2054 +
  4.2055 +lemma fls_inverse_of_nat:
  4.2056 +  "inverse (of_nat n :: 'a :: {semiring_1,inverse,uminus} fls) = fls_const (inverse (of_nat n))"
  4.2057 +  by (simp add: fls_inverse_const fls_of_nat)
  4.2058 +
  4.2059 +lemma fls_lr_inverse_of_int:
  4.2060 +  fixes x :: "'a::{ring_1,mult_zero}"
  4.2061 +  shows "fls_left_inverse (of_int n) x = fls_const x"
  4.2062 +  and   "fls_right_inverse (of_int n) x = fls_const x"
  4.2063 +  using fls_lr_inverse_const
  4.2064 +  by    (auto simp: fls_of_int)
  4.2065 +
  4.2066 +lemma fls_inverse_of_int:
  4.2067 +  "inverse (of_int n :: 'a :: {ring_1,inverse,uminus} fls) = fls_const (inverse (of_int n))"
  4.2068 +  by      (simp add: fls_inverse_const fls_of_int)
  4.2069 +
  4.2070 +lemma fls_lr_inverse_zero:
  4.2071 +  fixes x :: "'a::{ab_group_add,mult_zero}"
  4.2072 +  and   y :: "'b::{comm_monoid_add,mult_zero,uminus}"
  4.2073 +  shows "fls_left_inverse 0 x = fls_const x"
  4.2074 +  and   "fls_right_inverse 0 y = fls_const y"
  4.2075 +  using fls_lr_inverse_const[of 0]
  4.2076 +  by    auto
  4.2077 +
  4.2078 +lemma fls_inverse_zero_conv_fls_const:
  4.2079 +  "inverse (0::'a::{comm_monoid_add,mult_zero,uminus,inverse} fls) = fls_const (inverse 0)"
  4.2080 +  using fls_lr_inverse_zero(2)[of "inverse (0::'a)"] by (simp add: fls_inverse_def')
  4.2081 +
  4.2082 +lemma fls_inverse_zero':
  4.2083 +  assumes "inverse (0::'a::{comm_monoid_add,inverse,mult_zero,uminus}) = 0"
  4.2084 +  shows   "inverse (0::'a fls) = 0"
  4.2085 +  by      (simp add: fls_inverse_zero_conv_fls_const assms)
  4.2086 +
  4.2087 +lemma fls_inverse_zero [simp]: "inverse (0::'a::division_ring fls) = 0"
  4.2088 +  by (rule fls_inverse_zero'[OF inverse_zero])
  4.2089 +
  4.2090 +lemma fls_inverse_base2:
  4.2091 +  fixes f :: "'a::{comm_monoid_add,mult_zero,uminus,inverse} fls"
  4.2092 +  shows "inverse f $$ (-fls_subdegree f) = inverse (f $$ fls_subdegree f)"
  4.2093 +  by    (cases "f=0") (simp_all add: fls_inverse_zero_conv_fls_const fls_inverse_def')
  4.2094 +
  4.2095 +lemma fls_lr_inverse_one:
  4.2096 +  fixes x :: "'a::{ab_group_add,mult_zero,one}"
  4.2097 +  and   y :: "'b::{comm_monoid_add,mult_zero,uminus,one}"
  4.2098 +  shows "fls_left_inverse 1 x = fls_const x"
  4.2099 +  and   "fls_right_inverse 1 y = fls_const y"
  4.2100 +  using fls_lr_inverse_const[of 1]
  4.2101 +  by    auto
  4.2102 +
  4.2103 +lemma fls_lr_inverse_one_one:
  4.2104 +  "fls_left_inverse 1 1 =
  4.2105 +    (1::'a::{ab_group_add,mult_zero,one} fls)"
  4.2106 +  "fls_right_inverse 1 1 =
  4.2107 +    (1::'b::{comm_monoid_add,mult_zero,uminus,one} fls)"
  4.2108 +  using fls_lr_inverse_one[of 1] by auto
  4.2109 +
  4.2110 +lemma fls_inverse_one:
  4.2111 +  assumes "inverse (1::'a::{comm_monoid_add,inverse,mult_zero,uminus,one}) = 1"
  4.2112 +  shows   "inverse (1::'a fls) = 1"
  4.2113 +  using   assms fls_lr_inverse_one_one(2)
  4.2114 +  by      (simp add: fls_inverse_def')
  4.2115 +
  4.2116 +lemma fls_left_inverse_delta:
  4.2117 +  fixes   b :: "'a::{ab_group_add,mult_zero}"
  4.2118 +  assumes "b \<noteq> 0"
  4.2119 +  shows   "fls_left_inverse (Abs_fls (\<lambda>n. if n=a then b else 0)) x =
  4.2120 +            Abs_fls (\<lambda>n. if n=-a then x else 0)"
  4.2121 +proof (intro fls_eqI)
  4.2122 +  fix n from assms show
  4.2123 +    "fls_left_inverse (Abs_fls (\<lambda>n. if n=a then b else 0)) x $$ n
  4.2124 +      = Abs_fls (\<lambda>n. if n = - a then x else 0) $$ n"
  4.2125 +    using fls_base_factor_to_fps_delta[of a b]
  4.2126 +          fls_lr_inverse_const(1)[of b]
  4.2127 +          fls_shift_const
  4.2128 +    by    simp
  4.2129 +qed
  4.2130 +
  4.2131 +lemma fls_right_inverse_delta:
  4.2132 +  fixes   b :: "'a::{comm_monoid_add,mult_zero,uminus}"
  4.2133 +  assumes "b \<noteq> 0"
  4.2134 +  shows   "fls_right_inverse (Abs_fls (\<lambda>n. if n=a then b else 0)) x =
  4.2135 +            Abs_fls (\<lambda>n. if n=-a then x else 0)"
  4.2136 +proof (intro fls_eqI)
  4.2137 +  fix n from assms show
  4.2138 +    "fls_right_inverse (Abs_fls (\<lambda>n. if n=a then b else 0)) x $$ n
  4.2139 +      = Abs_fls (\<lambda>n. if n = - a then x else 0) $$ n"
  4.2140 +    using fls_base_factor_to_fps_delta[of a b]
  4.2141 +          fls_lr_inverse_const(2)[of b]
  4.2142 +          fls_shift_const
  4.2143 +    by    simp
  4.2144 +qed
  4.2145 +
  4.2146 +lemma fls_inverse_delta_nonzero:
  4.2147 +  fixes   b :: "'a::{comm_monoid_add,inverse,mult_zero,uminus}"
  4.2148 +  assumes "b \<noteq> 0"
  4.2149 +  shows   "inverse (Abs_fls (\<lambda>n. if n=a then b else 0)) =
  4.2150 +            Abs_fls (\<lambda>n. if n=-a then inverse b else 0)"
  4.2151 +  using   assms fls_nonzeroI[of "Abs_fls (\<lambda>n. if n=a then b else 0)" a]
  4.2152 +  by      (simp add: fls_inverse_def' fls_right_inverse_delta[symmetric])
  4.2153 +
  4.2154 +lemma fls_inverse_delta:
  4.2155 +  fixes   b :: "'a::division_ring"
  4.2156 +  shows   "inverse (Abs_fls (\<lambda>n. if n=a then b else 0)) =
  4.2157 +            Abs_fls (\<lambda>n. if n=-a then inverse b else 0)"
  4.2158 +  by      (cases "b=0") (simp_all add: fls_inverse_delta_nonzero)
  4.2159 +
  4.2160 +lemma fls_lr_inverse_X:
  4.2161 +  fixes x :: "'a::{ab_group_add,mult_zero,zero_neq_one}"
  4.2162 +  and   y :: "'b::{comm_monoid_add,uminus,mult_zero,zero_neq_one}"
  4.2163 +  shows "fls_left_inverse fls_X x = fls_shift 1 (fls_const x)"
  4.2164 +  and   "fls_right_inverse fls_X y = fls_shift 1 (fls_const y)"
  4.2165 +  using fls_lr_inverse_one(1)[of x] fls_lr_inverse_one(2)[of y]
  4.2166 +  by    auto
  4.2167 +
  4.2168 +lemma fls_lr_inverse_X':
  4.2169 +  fixes x :: "'a::{ab_group_add,mult_zero,zero_neq_one,monoid_mult}"
  4.2170 +  and   y :: "'b::{comm_monoid_add,uminus,mult_zero,zero_neq_one,monoid_mult}"
  4.2171 +  shows "fls_left_inverse fls_X x = fls_const x * fls_X_inv"
  4.2172 +  and   "fls_right_inverse fls_X y = fls_const y * fls_X_inv"
  4.2173 +  using fls_lr_inverse_X(1)[of x] fls_lr_inverse_X(2)[of y]
  4.2174 +  by    (simp_all add: fls_X_inv_times_conv_shift(2))
  4.2175 +
  4.2176 +lemma fls_inverse_X':
  4.2177 +  assumes "inverse 1 = (1::'a::{comm_monoid_add,inverse,mult_zero,uminus,zero_neq_one})"
  4.2178 +  shows   "inverse (fls_X::'a fls) = fls_X_inv"
  4.2179 +  using   assms fls_lr_inverse_X(2)[of "1::'a"]
  4.2180 +  by      (simp add: fls_inverse_def' fls_X_inv_conv_shift_1)
  4.2181 +
  4.2182 +lemma fls_inverse_X: "inverse (fls_X::'a::division_ring fls) = fls_X_inv"
  4.2183 +  by (simp add: fls_inverse_X')
  4.2184 +
  4.2185 +lemma fls_lr_inverse_X_inv:
  4.2186 +  fixes x :: "'a::{ab_group_add,mult_zero,zero_neq_one}"
  4.2187 +  and   y :: "'b::{comm_monoid_add,uminus,mult_zero,zero_neq_one}"
  4.2188 +  shows "fls_left_inverse fls_X_inv x = fls_shift (-1) (fls_const x)"
  4.2189 +  and   "fls_right_inverse fls_X_inv y = fls_shift (-1) (fls_const y)"
  4.2190 +  using fls_lr_inverse_one(1)[of x] fls_lr_inverse_one(2)[of y]
  4.2191 +  by    auto
  4.2192 +
  4.2193 +lemma fls_lr_inverse_X_inv':
  4.2194 +  fixes x :: "'a::{ab_group_add,mult_zero,zero_neq_one,monoid_mult}"
  4.2195 +  and   y :: "'b::{comm_monoid_add,uminus,mult_zero,zero_neq_one,monoid_mult}"
  4.2196 +  shows "fls_left_inverse fls_X_inv x = fls_const x * fls_X"
  4.2197 +  and   "fls_right_inverse fls_X_inv y = fls_const y * fls_X"
  4.2198 +  using fls_lr_inverse_X_inv(1)[of x] fls_lr_inverse_X_inv(2)[of y]
  4.2199 +  by    (simp_all add: fls_X_times_conv_shift(2))
  4.2200 +
  4.2201 +lemma fls_inverse_X_inv':
  4.2202 +  assumes "inverse 1 = (1::'a::{comm_monoid_add,inverse,mult_zero,uminus,zero_neq_one})"
  4.2203 +  shows   "inverse (fls_X_inv::'a fls) = fls_X"
  4.2204 +  using   assms fls_lr_inverse_X_inv(2)[of "1::'a"]
  4.2205 +  by      (simp add: fls_inverse_def' fls_X_conv_shift_1)
  4.2206 +
  4.2207 +lemma fls_inverse_X_inv: "inverse (fls_X_inv::'a::division_ring fls) = fls_X"
  4.2208 +  by (simp add: fls_inverse_X_inv')
  4.2209 +
  4.2210 +lemma fls_lr_inverse_subdegree:
  4.2211 +  assumes "x \<noteq> 0"
  4.2212 +  shows   "fls_subdegree (fls_left_inverse f x) = - fls_subdegree f"
  4.2213 +  and     "fls_subdegree (fls_right_inverse f x) = - fls_subdegree f"
  4.2214 +  by      (auto intro: fls_subdegree_eqI simp: assms)
  4.2215 +
  4.2216 +lemma fls_inverse_subdegree':
  4.2217 +  "inverse (f $$ fls_subdegree f) \<noteq> 0 \<Longrightarrow> fls_subdegree (inverse f) = - fls_subdegree f"
  4.2218 +  using fls_lr_inverse_subdegree(2)[of "inverse (f $$ fls_subdegree f)"]
  4.2219 +  by    (simp add: fls_inverse_def')
  4.2220 +
  4.2221 +lemma fls_inverse_subdegree [simp]:
  4.2222 +  fixes f :: "'a::division_ring fls"
  4.2223 +  shows "fls_subdegree (inverse f) = - fls_subdegree f"
  4.2224 +  by    (cases "f=0")
  4.2225 +        (auto intro: fls_inverse_subdegree' simp: nonzero_imp_inverse_nonzero)
  4.2226 +
  4.2227 +lemma fls_inverse_subdegree_base_nonzero:
  4.2228 +  assumes "f \<noteq> 0" "inverse (f $$ fls_subdegree f) \<noteq> 0"
  4.2229 +  shows   "inverse f $$ (fls_subdegree (inverse f)) = inverse (f $$ fls_subdegree f)"
  4.2230 +  using   assms fls_inverse_subdegree'[of f] fls_inverse_base[of f]
  4.2231 +  by      simp
  4.2232 +
  4.2233 +lemma fls_inverse_subdegree_base:
  4.2234 +  fixes f :: "'a::{ab_group_add,inverse,mult_zero} fls"
  4.2235 +  shows "inverse f $$ (fls_subdegree (inverse f)) = inverse (f $$ fls_subdegree f)"
  4.2236 +  using fls_inverse_eq_0_iff'[of f] fls_inverse_subdegree_base_nonzero[of f]
  4.2237 +  by    (cases "f=0 \<or> inverse (f $$ fls_subdegree f) = 0")
  4.2238 +        (auto simp: fls_inverse_zero_conv_fls_const)
  4.2239 +
  4.2240 +lemma fls_lr_inverse_subdegree_0:
  4.2241 +  assumes "fls_subdegree f = 0"
  4.2242 +  shows   "fls_subdegree (fls_left_inverse f x) \<ge> 0"
  4.2243 +  and     "fls_subdegree (fls_right_inverse f x) \<ge> 0"
  4.2244 +  using   fls_subdegree_ge0I[of "fls_left_inverse f x"]
  4.2245 +          fls_subdegree_ge0I[of "fls_right_inverse f x"]
  4.2246 +  by      (auto simp: assms)
  4.2247 +
  4.2248 +lemma fls_inverse_subdegree_0:
  4.2249 +  "fls_subdegree f = 0 \<Longrightarrow> fls_subdegree (inverse f) \<ge> 0"
  4.2250 +  using fls_lr_inverse_subdegree_0(2)[of f] by (simp add: fls_inverse_def')
  4.2251 +
  4.2252 +lemma fls_lr_inverse_shift_nonzero:
  4.2253 +  fixes   f :: "'a::{comm_monoid_add,mult_zero,uminus} fls"
  4.2254 +  assumes "f \<noteq> 0"
  4.2255 +  shows   "fls_left_inverse (fls_shift m f) x = fls_shift (-m) (fls_left_inverse f x)"
  4.2256 +  and     "fls_right_inverse (fls_shift m f) x = fls_shift (-m) (fls_right_inverse f x)"
  4.2257 +  using   assms fls_base_factor_to_fps_shift[of m f] fls_shift_subdegree
  4.2258 +  by      auto
  4.2259 +
  4.2260 +lemma fls_inverse_shift_nonzero:
  4.2261 +  fixes   f :: "'a::{comm_monoid_add,inverse,mult_zero,uminus} fls"
  4.2262 +  assumes "f \<noteq> 0"
  4.2263 +  shows   "inverse (fls_shift m f) = fls_shift (-m) (inverse f)"
  4.2264 +  using   assms fls_lr_inverse_shift_nonzero(2)[of f m "inverse (f $$ fls_subdegree f)"]
  4.2265 +  by      (simp add: fls_inverse_def')
  4.2266 +
  4.2267 +lemma fls_inverse_shift:
  4.2268 +  fixes f :: "'a::division_ring fls"
  4.2269 +  shows "inverse (fls_shift m f) = fls_shift (-m) (inverse f)"
  4.2270 +  using fls_inverse_shift_nonzero
  4.2271 +  by    (cases "f=0") simp_all
  4.2272 +
  4.2273 +lemma fls_left_inverse_base_factor:
  4.2274 +  fixes   x :: "'a::{ab_group_add,mult_zero}"
  4.2275 +  assumes "x \<noteq> 0"
  4.2276 +  shows   "fls_left_inverse (fls_base_factor f) x = fls_base_factor (fls_left_inverse f x)"
  4.2277 +  using   assms fls_lr_inverse_zero(1)[of x] fls_lr_inverse_subdegree(1)[of x]
  4.2278 +  by      (cases "f=0") auto
  4.2279 +
  4.2280 +lemma fls_right_inverse_base_factor:
  4.2281 +  fixes   y :: "'a::{comm_monoid_add,mult_zero,uminus}"
  4.2282 +  assumes "y \<noteq> 0"
  4.2283 +  shows   "fls_right_inverse (fls_base_factor f) y = fls_base_factor (fls_right_inverse f y)"
  4.2284 +  using   assms fls_lr_inverse_zero(2)[of y] fls_lr_inverse_subdegree(2)[of y]
  4.2285 +  by      (cases "f=0") auto
  4.2286 +
  4.2287 +lemma fls_inverse_base_factor':
  4.2288 +  fixes   f :: "'a::{comm_monoid_add,inverse,mult_zero,uminus} fls"
  4.2289 +  assumes "inverse (f $$ fls_subdegree f) \<noteq> 0"
  4.2290 +  shows   "inverse (fls_base_factor f) = fls_base_factor (inverse f)"
  4.2291 +  by      (cases "f=0")
  4.2292 +          (simp_all add:
  4.2293 +            assms fls_inverse_shift_nonzero fls_inverse_subdegree'
  4.2294 +            fls_inverse_zero_conv_fls_const
  4.2295 +          )
  4.2296 +
  4.2297 +lemma fls_inverse_base_factor:
  4.2298 +  fixes f :: "'a::{ab_group_add,inverse,mult_zero} fls"
  4.2299 +  shows "inverse (fls_base_factor f) = fls_base_factor (inverse f)"
  4.2300 +  using fls_base_factor_base[of f] fls_inverse_eq_0_iff'[of f]
  4.2301 +        fls_inverse_eq_0_iff'[of "fls_base_factor f"] fls_inverse_base_factor'[of f]
  4.2302 +  by    (cases "inverse (f $$ fls_subdegree f) = 0") simp_all
  4.2303 +
  4.2304 +lemma fls_lr_inverse_regpart:
  4.2305 +  assumes "fls_subdegree f = 0"
  4.2306 +  shows   "fls_regpart (fls_left_inverse f x) = fps_left_inverse (fls_regpart f) x"
  4.2307 +  and     "fls_regpart (fls_right_inverse f y) = fps_right_inverse (fls_regpart f) y"
  4.2308 +  using   assms
  4.2309 +  by      auto
  4.2310 +
  4.2311 +lemma fls_inverse_regpart:
  4.2312 +  assumes "fls_subdegree f = 0"
  4.2313 +  shows   "fls_regpart (inverse f) = inverse (fls_regpart f)"
  4.2314 +  by      (simp add: assms fls_inverse_def)
  4.2315 +
  4.2316 +lemma fls_base_factor_to_fps_left_inverse:
  4.2317 +  fixes   x :: "'a::{ab_group_add,mult_zero}"
  4.2318 +  shows   "fls_base_factor_to_fps (fls_left_inverse f x) =
  4.2319 +            fps_left_inverse (fls_base_factor_to_fps f) x"
  4.2320 +  using   fls_left_inverse_base_factor[of x f] fls_base_factor_subdegree[of f]
  4.2321 +  by      (cases "x=0") (simp_all add: fls_lr_inverse_starting0(1) fps_lr_inverse_starting0(1))
  4.2322 +
  4.2323 +lemma fls_base_factor_to_fps_right_inverse_nonzero:
  4.2324 +  fixes   y :: "'a::{comm_monoid_add,mult_zero,uminus}"
  4.2325 +  assumes "y \<noteq> 0"
  4.2326 +  shows   "fls_base_factor_to_fps (fls_right_inverse f y) =
  4.2327 +            fps_right_inverse (fls_base_factor_to_fps f) y"
  4.2328 +  using   assms fls_right_inverse_base_factor[of y f]
  4.2329 +          fls_base_factor_subdegree[of f]
  4.2330 +  by      simp
  4.2331 +
  4.2332 +lemma fls_base_factor_to_fps_right_inverse:
  4.2333 +  fixes   y :: "'a::{ab_group_add,mult_zero}"
  4.2334 +  shows   "fls_base_factor_to_fps (fls_right_inverse f y) =
  4.2335 +            fps_right_inverse (fls_base_factor_to_fps f) y"
  4.2336 +  using   fls_base_factor_to_fps_right_inverse_nonzero[of y f]
  4.2337 +  by      (cases "y=0") (simp_all add: fls_lr_inverse_starting0(2) fps_lr_inverse_starting0(2))
  4.2338 +
  4.2339 +lemma fls_base_factor_to_fps_inverse_nonzero:
  4.2340 +  fixes   f :: "'a::{comm_monoid_add,inverse,mult_zero,uminus} fls"
  4.2341 +  assumes "inverse (f $$ fls_subdegree f) \<noteq> 0"
  4.2342 +  shows   "fls_base_factor_to_fps (inverse f) = inverse (fls_base_factor_to_fps f)"
  4.2343 +  using   assms fls_base_factor_to_fps_right_inverse_nonzero
  4.2344 +  by      (simp add: fls_inverse_def' fps_inverse_def)
  4.2345 +
  4.2346 +lemma fls_base_factor_to_fps_inverse:
  4.2347 +  fixes f :: "'a::{ab_group_add,inverse,mult_zero} fls"
  4.2348 +  shows "fls_base_factor_to_fps (inverse f) = inverse (fls_base_factor_to_fps f)"
  4.2349 +  using fls_base_factor_to_fps_right_inverse
  4.2350 +  by    (simp add: fls_inverse_def' fps_inverse_def)
  4.2351 +
  4.2352 +lemma fls_lr_inverse_fps_to_fls:
  4.2353 +  assumes "subdegree f = 0"
  4.2354 +  shows   "fls_left_inverse (fps_to_fls f) x = fps_to_fls (fps_left_inverse f x)"
  4.2355 +  and     "fls_right_inverse (fps_to_fls f) x = fps_to_fls (fps_right_inverse f x)"
  4.2356 +  using   assms fls_base_factor_to_fps_to_fls[of f]
  4.2357 +  by      (simp_all add: fls_subdegree_fls_to_fps)
  4.2358 +
  4.2359 +lemma fls_inverse_fps_to_fls:
  4.2360 +  "subdegree f = 0 \<Longrightarrow> inverse (fps_to_fls f) = fps_to_fls (inverse f)"
  4.2361 +  using nth_subdegree_nonzero[of f]
  4.2362 +  by  (cases "f=0")
  4.2363 +      (auto simp add:
  4.2364 +        fps_to_fls_nonzeroI fls_inverse_def' fls_subdegree_fls_to_fps fps_inverse_def
  4.2365 +        fls_lr_inverse_fps_to_fls(2)
  4.2366 +      )
  4.2367 +
  4.2368 +lemma fls_lr_inverse_X_power:
  4.2369 +  fixes x :: "'a::ring_1"
  4.2370 +  and   y :: "'b::{semiring_1,uminus}"
  4.2371 +  shows "fls_left_inverse (fls_X ^ n) x = fls_shift n (fls_const x)"
  4.2372 +  and   "fls_right_inverse (fls_X ^ n) y = fls_shift n (fls_const y)"
  4.2373 +  using fls_lr_inverse_one(1)[of x] fls_lr_inverse_one(2)[of y]
  4.2374 +  by    (simp_all add: fls_X_power_conv_shift_1)
  4.2375 +
  4.2376 +lemma fls_lr_inverse_X_power':
  4.2377 +  fixes x :: "'a::ring_1"
  4.2378 +  and   y :: "'b::{semiring_1,uminus}"
  4.2379 +  shows "fls_left_inverse (fls_X ^ n) x = fls_const x * fls_X_inv ^ n"
  4.2380 +  and   "fls_right_inverse (fls_X ^ n) y = fls_const y * fls_X_inv ^ n"
  4.2381 +  using fls_lr_inverse_X_power(1)[of n x] fls_lr_inverse_X_power(2)[of n y]
  4.2382 +  by    (simp_all add: fls_X_inv_power_times_conv_shift(2))
  4.2383 +
  4.2384 +lemma fls_inverse_X_power':
  4.2385 +  assumes "inverse 1 = (1::'a::{semiring_1,uminus,inverse})"
  4.2386 +  shows   "inverse ((fls_X ^ n)::'a fls) = fls_X_inv ^ n"
  4.2387 +  using   fls_lr_inverse_X_power'(2)[of n 1]
  4.2388 +  by      (simp add: fls_inverse_def' assms )
  4.2389 +
  4.2390 +lemma fls_inverse_X_power:
  4.2391 +  "inverse ((fls_X::'a::division_ring fls) ^ n) = fls_X_inv ^ n"
  4.2392 +  by (simp add: fls_inverse_X_power')
  4.2393 +
  4.2394 +lemma fls_lr_inverse_X_inv_power:
  4.2395 +  fixes x :: "'a::ring_1"
  4.2396 +  and   y :: "'b::{semiring_1,uminus}"
  4.2397 +  shows "fls_left_inverse (fls_X_inv ^ n) x = fls_shift (-n) (fls_const x)"
  4.2398 +  and   "fls_right_inverse (fls_X_inv ^ n) y = fls_shift (-n) (fls_const y)"
  4.2399 +  using fls_lr_inverse_one(1)[of x] fls_lr_inverse_one(2)[of y]
  4.2400 +  by    (simp_all add: fls_X_inv_power_conv_shift_1)
  4.2401 +
  4.2402 +lemma fls_lr_inverse_X_inv_power':
  4.2403 +  fixes x :: "'a::ring_1"
  4.2404 +  and   y :: "'b::{semiring_1,uminus}"
  4.2405 +  shows "fls_left_inverse (fls_X_inv ^ n) x = fls_const x * fls_X ^ n"
  4.2406 +  and   "fls_right_inverse (fls_X_inv ^ n) y = fls_const y * fls_X ^ n"
  4.2407 +  using fls_lr_inverse_X_inv_power(1)[of n x] fls_lr_inverse_X_inv_power(2)[of n y]
  4.2408 +  by    (simp_all add: fls_X_power_times_conv_shift(2))
  4.2409 +
  4.2410 +lemma fls_inverse_X_inv_power':
  4.2411 +  assumes "inverse 1 = (1::'a::{semiring_1,uminus,inverse})"
  4.2412 +  shows   "inverse ((fls_X_inv ^ n)::'a fls) = fls_X ^ n"
  4.2413 +  using   fls_lr_inverse_X_inv_power'(2)[of n 1]
  4.2414 +  by      (simp add: fls_inverse_def' assms)
  4.2415 +
  4.2416 +lemma fls_inverse_X_inv_power:
  4.2417 +  "inverse ((fls_X_inv::'a::division_ring fls) ^ n) = fls_X ^ n"
  4.2418 +  by (simp add: fls_inverse_X_inv_power')
  4.2419 +
  4.2420 +lemma fls_lr_inverse_X_intpow:
  4.2421 +  fixes x :: "'a::ring_1"
  4.2422 +  and   y :: "'b::{semiring_1,uminus}"
  4.2423 +  shows "fls_left_inverse (fls_X_intpow i) x = fls_shift i (fls_const x)"
  4.2424 +  and   "fls_right_inverse (fls_X_intpow i) y = fls_shift i (fls_const y)"
  4.2425 +  using fls_lr_inverse_one(1)[of x] fls_lr_inverse_one(2)[of y]
  4.2426 +  by    auto
  4.2427 +
  4.2428 +lemma fls_lr_inverse_X_intpow':
  4.2429 +  fixes x :: "'a::ring_1"
  4.2430 +  and   y :: "'b::{semiring_1,uminus}"
  4.2431 +  shows "fls_left_inverse (fls_X_intpow i) x = fls_const x * fls_X_intpow (-i)"
  4.2432 +  and   "fls_right_inverse (fls_X_intpow i) y = fls_const y * fls_X_intpow (-i)"
  4.2433 +  using fls_lr_inverse_X_intpow(1)[of i x] fls_lr_inverse_X_intpow(2)[of i y]
  4.2434 +  by    (simp_all add: fls_shifted_times_simps(1))
  4.2435 +
  4.2436 +lemma fls_inverse_X_intpow':
  4.2437 +  assumes "inverse 1 = (1::'a::{semiring_1,uminus,inverse})"
  4.2438 +  shows   "inverse (fls_X_intpow i :: 'a fls) = fls_X_intpow (-i)"
  4.2439 +  using   fls_lr_inverse_X_intpow'(2)[of i 1]
  4.2440 +  by      (simp add: fls_inverse_def' assms)
  4.2441 +
  4.2442 +lemma fls_inverse_X_intpow:
  4.2443 +  "inverse (fls_X_intpow i :: 'a::division_ring fls) = fls_X_intpow (-i)"
  4.2444 +  by (simp add: fls_inverse_X_intpow')
  4.2445 +
  4.2446 +lemma fls_left_inverse:
  4.2447 +  fixes   f :: "'a::ring_1 fls"
  4.2448 +  assumes "x * f $$ fls_subdegree f = 1"
  4.2449 +  shows   "fls_left_inverse f x * f = 1"
  4.2450 +proof-
  4.2451 +  from assms have "x \<noteq> 0" "x * (fls_base_factor_to_fps f$0) = 1" by auto
  4.2452 +  thus ?thesis
  4.2453 +    using fls_base_factor_to_fps_left_inverse[of f x]
  4.2454 +          fls_lr_inverse_subdegree(1)[of x] fps_left_inverse
  4.2455 +    by    (fastforce simp: fls_times_def)
  4.2456 +qed
  4.2457 +
  4.2458 +lemma fls_right_inverse:
  4.2459 +  fixes   f :: "'a::ring_1 fls"
  4.2460 +  assumes "f $$ fls_subdegree f * y = 1"
  4.2461 +  shows   "f * fls_right_inverse f y = 1"
  4.2462 +proof-
  4.2463 +  from assms have "y \<noteq> 0" "(fls_base_factor_to_fps f$0) * y = 1" by auto
  4.2464 +  thus ?thesis
  4.2465 +    using fls_base_factor_to_fps_right_inverse[of f y]
  4.2466 +          fls_lr_inverse_subdegree(2)[of y] fps_right_inverse
  4.2467 +    by    (fastforce simp: fls_times_def)
  4.2468 +qed
  4.2469 +
  4.2470 +\<comment> \<open>
  4.2471 +  It is possible in a ring for an element to have a left inverse but not a right inverse, or
  4.2472 +  vice versa. But when an element has both, they must be the same.
  4.2473 +\<close>
  4.2474 +lemma fls_left_inverse_eq_fls_right_inverse:
  4.2475 +  fixes   f :: "'a::ring_1 fls"
  4.2476 +  assumes "x * f $$ fls_subdegree f = 1" "f $$ fls_subdegree f * y = 1"
  4.2477 +  \<comment> \<open>These assumptions imply x equals y, but no need to assume that.\<close>
  4.2478 +  shows   "fls_left_inverse f x = fls_right_inverse f y"
  4.2479 +  using   assms
  4.2480 +  by      (simp add: fps_left_inverse_eq_fps_right_inverse)
  4.2481 +
  4.2482 +lemma fls_left_inverse_eq_inverse:
  4.2483 +  fixes   f :: "'a::division_ring fls"
  4.2484 +  shows   "fls_left_inverse f (inverse (f $$ fls_subdegree f)) = inverse f"
  4.2485 +proof (cases "f=0")
  4.2486 +  case True
  4.2487 +  hence "fls_left_inverse f (inverse (f $$ fls_subdegree f)) = fls_const (0::'a)"
  4.2488 +    by (simp add: fls_lr_inverse_zero(1)[symmetric])
  4.2489 +  with True show ?thesis by simp
  4.2490 +next
  4.2491 +  case False thus ?thesis
  4.2492 +    using fls_left_inverse_eq_fls_right_inverse[of "inverse (f $$ fls_subdegree f)"]
  4.2493 +    by    (auto simp add: fls_inverse_def')
  4.2494 +qed
  4.2495 +
  4.2496 +lemma fls_right_inverse_eq_inverse:
  4.2497 +  fixes f :: "'a::division_ring fls"
  4.2498 +  shows "fls_right_inverse f (inverse (f $$ fls_subdegree f)) = inverse f"
  4.2499 +proof (cases "f=0")
  4.2500 +  case True
  4.2501 +  hence "fls_right_inverse f (inverse (f $$ fls_subdegree f)) = fls_const (0::'a)"
  4.2502 +    by (simp add: fls_lr_inverse_zero(2)[symmetric])
  4.2503 +  with True show ?thesis by simp
  4.2504 +qed (simp add: fls_inverse_def')
  4.2505 +
  4.2506 +lemma fls_left_inverse_eq_fls_right_inverse_comm:
  4.2507 +  fixes   f :: "'a::comm_ring_1 fls"
  4.2508 +  assumes "x * f $$ fls_subdegree f = 1"
  4.2509 +  shows   "fls_left_inverse f x = fls_right_inverse f x"
  4.2510 +  using   assms fls_left_inverse_eq_fls_right_inverse[of x f x]
  4.2511 +  by      (simp add: mult.commute)
  4.2512 +
  4.2513 +lemma fls_left_inverse':
  4.2514 +  fixes   f :: "'a::ring_1 fls"
  4.2515 +  assumes "x * f $$ fls_subdegree f = 1" "f $$ fls_subdegree f * y = 1"
  4.2516 +  \<comment> \<open>These assumptions imply x equals y, but no need to assume that.\<close>
  4.2517 +  shows   "fls_right_inverse f y * f = 1"
  4.2518 +  using   assms fls_left_inverse_eq_fls_right_inverse[of x f y] fls_left_inverse[of x f]
  4.2519 +  by      simp
  4.2520 +
  4.2521 +lemma fls_right_inverse':
  4.2522 +  fixes   f :: "'a::ring_1 fls"
  4.2523 +  assumes "x * f $$ fls_subdegree f = 1" "f $$ fls_subdegree f * y = 1"
  4.2524 +  \<comment> \<open>These assumptions imply x equals y, but no need to assume that.\<close>
  4.2525 +  shows   "f * fls_left_inverse f x = 1"
  4.2526 +  using   assms fls_left_inverse_eq_fls_right_inverse[of x f y] fls_right_inverse[of f y]
  4.2527 +  by      simp
  4.2528 +
  4.2529 +lemma fls_mult_left_inverse_base_factor:
  4.2530 +  fixes   f :: "'a::ring_1 fls"
  4.2531 +  assumes "x * (f $$ fls_subdegree f) = 1"
  4.2532 +  shows   "fls_left_inverse (fls_base_factor f) x * f = fls_X_intpow (fls_subdegree f)"
  4.2533 +  using   assms fls_base_factor_to_fps_base_factor[of f] fls_base_factor_subdegree[of f]
  4.2534 +          fls_shifted_times_simps(2)[of "-fls_subdegree f" "fls_left_inverse f x" f]
  4.2535 +          fls_left_inverse[of x f]
  4.2536 +  by      simp
  4.2537 +
  4.2538 +lemma fls_mult_right_inverse_base_factor:
  4.2539 +  fixes   f :: "'a::ring_1 fls"
  4.2540 +  assumes "(f $$ fls_subdegree f) * y = 1"
  4.2541 +  shows   "f * fls_right_inverse (fls_base_factor f) y = fls_X_intpow (fls_subdegree f)"
  4.2542 +  using   assms fls_base_factor_to_fps_base_factor[of f] fls_base_factor_subdegree[of f]
  4.2543 +          fls_shifted_times_simps(1)[of f "-fls_subdegree f" "fls_right_inverse f y"]
  4.2544 +          fls_right_inverse[of f y]
  4.2545 +  by      simp
  4.2546 +
  4.2547 +lemma fls_mult_inverse_base_factor:
  4.2548 +  fixes   f :: "'a::division_ring fls"
  4.2549 +  assumes "f \<noteq> 0"
  4.2550 +  shows   "f * inverse (fls_base_factor f) = fls_X_intpow (fls_subdegree f)"
  4.2551 +  using   fls_mult_right_inverse_base_factor[of f "inverse (f $$ fls_subdegree f)"]
  4.2552 +          fls_base_factor_base[of f]
  4.2553 +  by      (simp add: assms fls_right_inverse_eq_inverse[symmetric])
  4.2554 +
  4.2555 +lemma fls_left_inverse_idempotent_ring1:
  4.2556 +  fixes   f :: "'a::ring_1 fls"
  4.2557 +  assumes "x * f $$ fls_subdegree f = 1" "y * x = 1"
  4.2558 +  \<comment> \<open>These assumptions imply y equals f $$ fls_subdegree f, but no need to assume that.\<close>
  4.2559 +  shows   "fls_left_inverse (fls_left_inverse f x) y = f"
  4.2560 +proof-
  4.2561 +  from assms(1) have
  4.2562 +    "fls_left_inverse (fls_left_inverse f x) y * fls_left_inverse f x * f =
  4.2563 +      fls_left_inverse (fls_left_inverse f x) y"
  4.2564 +    using fls_left_inverse[of x f]
  4.2565 +    by    (simp add: mult.assoc)
  4.2566 +  moreover have
  4.2567 +    "fls_left_inverse (fls_left_inverse f x) y * fls_left_inverse f x = 1"
  4.2568 +    using assms fls_lr_inverse_subdegree(1)[of x f] fls_lr_inverse_base(1)[of f x]
  4.2569 +    by    (fastforce intro: fls_left_inverse)
  4.2570 +  ultimately show ?thesis by simp
  4.2571 +qed
  4.2572 +
  4.2573 +lemma fls_left_inverse_idempotent_comm_ring1:
  4.2574 +  fixes   f :: "'a::comm_ring_1 fls"
  4.2575 +  assumes "x * f $$ fls_subdegree f = 1"
  4.2576 +  shows   "fls_left_inverse (fls_left_inverse f x) (f $$ fls_subdegree f) = f"
  4.2577 +  using   assms fls_left_inverse_idempotent_ring1[of x f "f $$ fls_subdegree f"]
  4.2578 +  by      (simp add: mult.commute)
  4.2579 +
  4.2580 +lemma fls_right_inverse_idempotent_ring1:
  4.2581 +  fixes   f :: "'a::ring_1 fls"
  4.2582 +  assumes "f $$ fls_subdegree f * x = 1" "x * y = 1"
  4.2583 +  \<comment> \<open>These assumptions imply y equals f $$ fls_subdegree f, but no need to assume that.\<close>
  4.2584 +  shows   "fls_right_inverse (fls_right_inverse f x) y = f"
  4.2585 +proof-
  4.2586 +  from assms(1) have
  4.2587 +    "f * (fls_right_inverse f x * fls_right_inverse (fls_right_inverse f x) y) =
  4.2588 +      fls_right_inverse (fls_right_inverse f x) y"
  4.2589 +    using fls_right_inverse [of f] 
  4.2590 +    by (simp add: mult.assoc[symmetric])
  4.2591 +  moreover have
  4.2592 +    "fls_right_inverse f x * fls_right_inverse (fls_right_inverse f x) y = 1"
  4.2593 +    using assms fls_lr_inverse_subdegree(2)[of x f] fls_lr_inverse_base(2)[of f x]
  4.2594 +    by    (fastforce intro: fls_right_inverse)
  4.2595 +  ultimately show ?thesis by simp
  4.2596 +qed
  4.2597 +
  4.2598 +lemma fls_right_inverse_idempotent_comm_ring1:
  4.2599 +  fixes   f :: "'a::comm_ring_1 fls"
  4.2600 +  assumes "f $$ fls_subdegree f * x = 1"
  4.2601 +  shows   "fls_right_inverse (fls_right_inverse f x) (f $$ fls_subdegree f) = f"
  4.2602 +  using   assms fls_right_inverse_idempotent_ring1[of f x "f $$ fls_subdegree f"]
  4.2603 +  by      (simp add: mult.commute)
  4.2604 +
  4.2605 +lemma fls_lr_inverse_unique_ring1:
  4.2606 +  fixes   f g :: "'a :: ring_1 fls"
  4.2607 +  assumes fg: "f * g = 1" "g $$ fls_subdegree g * f $$ fls_subdegree f = 1"
  4.2608 +  shows   "fls_left_inverse g (f $$ fls_subdegree f) = f"
  4.2609 +  and     "fls_right_inverse f (g $$ fls_subdegree g) = g"
  4.2610 +proof-
  4.2611 +
  4.2612 +  have "f $$ fls_subdegree f * g $$ fls_subdegree g \<noteq> 0"
  4.2613 +  proof
  4.2614 +    assume "f $$ fls_subdegree f * g $$ fls_subdegree g = 0"
  4.2615 +    hence "f $$ fls_subdegree f * (g $$ fls_subdegree g * f $$ fls_subdegree f) = 0"
  4.2616 +      by (simp add: mult.assoc[symmetric])
  4.2617 +    with fg(2) show False by simp
  4.2618 +  qed
  4.2619 +  with fg(1) have subdeg_sum: "fls_subdegree f + fls_subdegree g = 0"
  4.2620 +    using fls_mult_nonzero_base_subdegree_eq[of f g] by simp
  4.2621 +  hence subdeg_sum':
  4.2622 +    "fls_subdegree f = -fls_subdegree g" "fls_subdegree g = -fls_subdegree f"
  4.2623 +    by auto
  4.2624 +
  4.2625 +  from fg(1) have f_ne_0: "f\<noteq>0" by auto
  4.2626 +  moreover have
  4.2627 +    "fps_left_inverse (fls_base_factor_to_fps g) (fls_regpart (fls_shift (-fls_subdegree g) f)$0)
  4.2628 +      = fls_regpart (fls_shift (-fls_subdegree g) f)"
  4.2629 +  proof (intro fps_lr_inverse_unique_ring1(1))
  4.2630 +    from fg(1) show
  4.2631 +      "fls_regpart (fls_shift (-fls_subdegree g) f) * fls_base_factor_to_fps g = 1"
  4.2632 +      using f_ne_0 fls_times_conv_regpart[of "fls_shift (-fls_subdegree g) f" "fls_base_factor g"]
  4.2633 +            fls_base_factor_subdegree[of g]
  4.2634 +      by    (simp add: fls_times_both_shifted_simp subdeg_sum)
  4.2635 +    from fg(2) show
  4.2636 +      "fls_base_factor_to_fps g $ 0 * fls_regpart (fls_shift (-fls_subdegree g) f) $ 0 = 1"
  4.2637 +      by (simp add: subdeg_sum'(2))
  4.2638 +  qed
  4.2639 +  ultimately show "fls_left_inverse g (f $$ fls_subdegree f) = f"
  4.2640 +    by (simp add: subdeg_sum'(2))
  4.2641 +
  4.2642 +  from fg(1) have g_ne_0: "g\<noteq>0" by auto
  4.2643 +  moreover have
  4.2644 +    "fps_right_inverse (fls_base_factor_to_fps f) (fls_regpart (fls_shift (-fls_subdegree f) g)$0)
  4.2645 +      = fls_regpart (fls_shift (-fls_subdegree f) g)"
  4.2646 +  proof (intro fps_lr_inverse_unique_ring1(2))
  4.2647 +    from fg(1) show
  4.2648 +      "fls_base_factor_to_fps f * fls_regpart (fls_shift (-fls_subdegree f) g) = 1"
  4.2649 +      using g_ne_0 fls_times_conv_regpart[of "fls_base_factor f" "fls_shift (-fls_subdegree f) g"]
  4.2650 +            fls_base_factor_subdegree[of f]
  4.2651 +      by    (simp add: fls_times_both_shifted_simp subdeg_sum add.commute)
  4.2652 +    from fg(2) show
  4.2653 +      "fls_regpart (fls_shift (-fls_subdegree f) g) $ 0 * fls_base_factor_to_fps f $ 0 = 1"
  4.2654 +      by (simp add: subdeg_sum'(1))
  4.2655 +  qed
  4.2656 +  ultimately show "fls_right_inverse f (g $$ fls_subdegree g) = g"
  4.2657 +    by (simp add: subdeg_sum'(2))
  4.2658 +
  4.2659 +qed
  4.2660 +
  4.2661 +lemma fls_lr_inverse_unique_divring:
  4.2662 +  fixes   f g :: "'a ::division_ring fls"
  4.2663 +  assumes fg: "f * g = 1"
  4.2664 +  shows   "fls_left_inverse g (f $$ fls_subdegree f) = f"
  4.2665 +  and     "fls_right_inverse f (g $$ fls_subdegree g) = g"
  4.2666 +proof-
  4.2667 +  from fg have "f \<noteq>0" "g \<noteq> 0" by auto
  4.2668 +  with fg have "fls_subdegree f + fls_subdegree g = 0" using fls_subdegree_mult by force
  4.2669 +  with fg have "f $$ fls_subdegree f * g $$ fls_subdegree g = 1"
  4.2670 +    using fls_times_base[of f g] by simp
  4.2671 +  hence "g $$ fls_subdegree g * f $$ fls_subdegree f = 1"
  4.2672 +    using inverse_unique[of "f $$ fls_subdegree f"] left_inverse[of "f $$ fls_subdegree f"]
  4.2673 +    by    force
  4.2674 +  thus
  4.2675 +    "fls_left_inverse g (f $$ fls_subdegree f) = f"
  4.2676 +    "fls_right_inverse f (g $$ fls_subdegree g) = g"
  4.2677 +    using fg fls_lr_inverse_unique_ring1
  4.2678 +    by    auto
  4.2679 +qed
  4.2680 +
  4.2681 +lemma fls_lr_inverse_minus:
  4.2682 +  fixes f :: "'a::ring_1 fls"
  4.2683 +  shows "fls_left_inverse (-f) (-x) = - fls_left_inverse f x"
  4.2684 +  and   "fls_right_inverse (-f) (-x) = - fls_right_inverse f x"
  4.2685 +  by (simp_all add: fps_lr_inverse_minus)
  4.2686 +
  4.2687 +lemma fls_inverse_minus [simp]: "inverse (-f) = -inverse (f :: 'a :: division_ring fls)"
  4.2688 +  using fls_lr_inverse_minus(2)[of f] by (simp add: fls_inverse_def')
  4.2689 +
  4.2690 +lemma fls_lr_inverse_mult_ring1:
  4.2691 +  fixes   f g :: "'a::ring_1 fls"
  4.2692 +  assumes x: "x * f $$ fls_subdegree f = 1" "f $$ fls_subdegree f * x = 1"
  4.2693 +  and     y: "y * g $$ fls_subdegree g = 1" "g $$ fls_subdegree g * y = 1"
  4.2694 +  shows   "fls_left_inverse (f * g) (y*x) = fls_left_inverse g y * fls_left_inverse f x"
  4.2695 +  and     "fls_right_inverse (f * g) (y*x) = fls_right_inverse g y * fls_right_inverse f x"
  4.2696 +proof-
  4.2697 +  from x(1) y(2) have "x * (f $$ fls_subdegree f * g $$ fls_subdegree g) * y = 1"
  4.2698 +    by (simp add: mult.assoc)
  4.2699 +  hence base_prod: "f $$ fls_subdegree f * g $$ fls_subdegree g \<noteq> 0" by auto
  4.2700 +  hence subdegrees: "fls_subdegree (f*g) = fls_subdegree f + fls_subdegree g"
  4.2701 +    using fls_mult_nonzero_base_subdegree_eq[of f g] by simp
  4.2702 +
  4.2703 +  have norm:
  4.2704 +    "fls_base_factor_to_fps (f * g) = fls_base_factor_to_fps f * fls_base_factor_to_fps g"
  4.2705 +    using base_prod fls_base_factor_to_fps_mult'[of f g] by simp
  4.2706 +
  4.2707 +  have
  4.2708 +    "fls_left_inverse (f * g) (y*x) =
  4.2709 +      fls_shift (fls_subdegree (f * g)) (
  4.2710 +        fps_to_fls (
  4.2711 +          fps_left_inverse (fls_base_factor_to_fps f * fls_base_factor_to_fps g) (y*x)
  4.2712 +        )
  4.2713 +      )
  4.2714 +    "
  4.2715 +    using norm
  4.2716 +    by    simp
  4.2717 +  thus "fls_left_inverse (f * g) (y*x) = fls_left_inverse g y * fls_left_inverse f x"
  4.2718 +    using x y
  4.2719 +          fps_lr_inverse_mult_ring1(1)[of
  4.2720 +            x "fls_base_factor_to_fps f" y "fls_base_factor_to_fps g"
  4.2721 +          ]
  4.2722 +    by    (simp add:
  4.2723 +            fls_times_both_shifted_simp fls_times_fps_to_fls subdegrees algebra_simps
  4.2724 +          )
  4.2725 +
  4.2726 +  have
  4.2727 +    "fls_right_inverse (f * g) (y*x) =
  4.2728 +      fls_shift (fls_subdegree (f * g)) (
  4.2729 +        fps_to_fls (
  4.2730 +          fps_right_inverse (fls_base_factor_to_fps f * fls_base_factor_to_fps g) (y*x)
  4.2731 +        )
  4.2732 +      )
  4.2733 +    "
  4.2734 +    using norm
  4.2735 +    by    simp
  4.2736 +  thus "fls_right_inverse (f * g) (y*x) = fls_right_inverse g y * fls_right_inverse f x"
  4.2737 +    using x y
  4.2738 +          fps_lr_inverse_mult_ring1(2)[of
  4.2739 +            x "fls_base_factor_to_fps f" y "fls_base_factor_to_fps g"
  4.2740 +          ]
  4.2741 +    by    (simp add:
  4.2742 +            fls_times_both_shifted_simp fls_times_fps_to_fls subdegrees algebra_simps
  4.2743 +          )
  4.2744 +
  4.2745 +qed
  4.2746 +
  4.2747 +lemma fls_lr_inverse_power_ring1:
  4.2748 +  fixes   f :: "'a::ring_1 fls"
  4.2749 +  assumes x: "x * f $$ fls_subdegree f = 1" "f $$ fls_subdegree f * x = 1"
  4.2750 +  shows   "fls_left_inverse (f ^ n) (x ^ n) = (fls_left_inverse f x) ^ n"
  4.2751 +          "fls_right_inverse (f ^ n) (x ^ n) = (fls_right_inverse f x) ^ n"
  4.2752 +proof-
  4.2753 +
  4.2754 +  show "fls_left_inverse (f ^ n) (x ^ n) = (fls_left_inverse f x) ^ n"
  4.2755 +  proof (induct n)
  4.2756 +    case 0 show ?case using fls_lr_inverse_one(1)[of 1] by simp
  4.2757 +  next
  4.2758 +    case (Suc n) with assms show ?case
  4.2759 +      using fls_lr_inverse_mult_ring1(1)[of x f "x^n" "f^n"]
  4.2760 +      by    (simp add:
  4.2761 +              power_Suc2[symmetric] fls_unit_base_subdegree_power(1) left_right_inverse_power
  4.2762 +            )
  4.2763 +  qed
  4.2764 +
  4.2765 +  show "fls_right_inverse (f ^ n) (x ^ n) = (fls_right_inverse f x) ^ n"
  4.2766 +  proof (induct n)
  4.2767 +    case 0 show ?case using fls_lr_inverse_one(2)[of 1] by simp
  4.2768 +  next
  4.2769 +    case (Suc n) with assms show ?case
  4.2770 +      using fls_lr_inverse_mult_ring1(2)[of x f "x^n" "f^n"]
  4.2771 +      by    (simp add:
  4.2772 +              power_Suc2[symmetric] fls_unit_base_subdegree_power(1) left_right_inverse_power
  4.2773 +            )
  4.2774 +  qed
  4.2775 +
  4.2776 +qed
  4.2777 +
  4.2778 +lemma fls_divide_convert_times_inverse:
  4.2779 +  fixes   f g :: "'a::{comm_monoid_add,inverse,mult_zero,uminus} fls"
  4.2780 +  shows   "f / g = f * inverse g"
  4.2781 +  using fls_base_factor_to_fps_subdegree[of g] fps_to_fls_base_factor_to_fps[of f]
  4.2782 +        fls_times_both_shifted_simp[of "-fls_subdegree f" "fls_base_factor f"]
  4.2783 +  by    (simp add:
  4.2784 +          fls_divide_def fps_divide_unit' fls_times_fps_to_fls
  4.2785 +          fls_conv_base_factor_shift_subdegree fls_inverse_def
  4.2786 +        )
  4.2787 +
  4.2788 +instance fls :: (division_ring) division_ring
  4.2789 +proof
  4.2790 +  fix a b :: "'a fls"
  4.2791 +  show "a \<noteq> 0 \<Longrightarrow> inverse a * a = 1"
  4.2792 +    using fls_left_inverse'[of "inverse (a $$ fls_subdegree a)" a]
  4.2793 +    by    (simp add: fls_inverse_def')
  4.2794 +  show "a \<noteq> 0 \<Longrightarrow> a * inverse a = 1"
  4.2795 +    using fls_right_inverse[of a]
  4.2796 +    by    (simp add: fls_inverse_def')
  4.2797 +  show "a / b = a * inverse b" using fls_divide_convert_times_inverse by fast
  4.2798 +  show "inverse (0::'a fls) = 0" by simp
  4.2799 +qed
  4.2800 +
  4.2801 +lemma fls_lr_inverse_mult_divring:
  4.2802 +  fixes   f g   :: "'a::division_ring fls"
  4.2803 +  and     df dg :: int
  4.2804 +  defines "df \<equiv> fls_subdegree f"
  4.2805 +  and     "dg \<equiv> fls_subdegree g"
  4.2806 +  shows   "fls_left_inverse (f*g) (inverse ((f*g)$$(df+dg))) =
  4.2807 +            fls_left_inverse g (inverse (g$$dg)) * fls_left_inverse f (inverse (f$$df))"
  4.2808 +  and     "fls_right_inverse (f*g) (inverse ((f*g)$$(df+dg))) =
  4.2809 +            fls_right_inverse g (inverse (g$$dg)) * fls_right_inverse f (inverse (f$$df))"
  4.2810 +proof -
  4.2811 +  show
  4.2812 +    "fls_left_inverse (f*g) (inverse ((f*g)$$(df+dg))) =
  4.2813 +      fls_left_inverse g (inverse (g$$dg)) * fls_left_inverse f (inverse (f$$df))"
  4.2814 +  proof (cases "f=0 \<or> g=0")
  4.2815 +    case True thus ?thesis
  4.2816 +      using fls_lr_inverse_zero(1)[of "inverse (0::'a)"] by (auto simp add: assms)
  4.2817 +  next
  4.2818 +    case False thus ?thesis
  4.2819 +      using fls_left_inverse_eq_inverse[of "f*g"] nonzero_inverse_mult_distrib[of f g]
  4.2820 +            fls_left_inverse_eq_inverse[of g] fls_left_inverse_eq_inverse[of f]
  4.2821 +      by    (simp add: assms)
  4.2822 +  qed
  4.2823 +  show
  4.2824 +    "fls_right_inverse (f*g) (inverse ((f*g)$$(df+dg))) =
  4.2825 +      fls_right_inverse g (inverse (g$$dg)) * fls_right_inverse f (inverse (f$$df))"
  4.2826 +  proof (cases "f=0 \<or> g=0")
  4.2827 +    case True thus ?thesis
  4.2828 +      using fls_lr_inverse_zero(2)[of "inverse (0::'a)"] by (auto simp add: assms)
  4.2829 +  next
  4.2830 +    case False thus ?thesis
  4.2831 +      using fls_inverse_def'[of "f*g"] nonzero_inverse_mult_distrib[of f g]
  4.2832 +            fls_inverse_def'[of g] fls_inverse_def'[of f]
  4.2833 +      by    (simp add: assms)
  4.2834 +  qed
  4.2835 +qed
  4.2836 +
  4.2837 +lemma fls_lr_inverse_power_divring:
  4.2838 +  fixes f :: "'a::division_ring fls"
  4.2839 +  shows "fls_left_inverse (f ^ n) ((inverse (f $$ fls_subdegree f)) ^ n) =
  4.2840 +          (fls_left_inverse f (inverse (f $$ fls_subdegree f))) ^ n"
  4.2841 +        "fls_right_inverse (f ^ n) ((inverse (f $$ fls_subdegree f)) ^ n) =
  4.2842 +          (fls_right_inverse f (inverse (f $$ fls_subdegree f))) ^ n"
  4.2843 +proof -
  4.2844 +  have
  4.2845 +    "fls_right_inverse (f ^ n) ((inverse (f $$ fls_subdegree f)) ^ n) =
  4.2846 +      inverse f ^ n"
  4.2847 +    "fls_left_inverse (f ^ n) ((inverse (f $$ fls_subdegree f)) ^ n) =
  4.2848 +      inverse f ^ n"
  4.2849 +    using fls_left_inverse_eq_inverse[of "f^n"] fls_right_inverse_eq_inverse[of "f^n"]
  4.2850 +    by    (auto simp add: divide_simps fls_subdegree_pow)
  4.2851 +  thus
  4.2852 +    "fls_left_inverse (f ^ n) ((inverse (f $$ fls_subdegree f)) ^ n) =
  4.2853 +      (fls_left_inverse f (inverse (f $$ fls_subdegree f))) ^ n"
  4.2854 +    "fls_right_inverse (f ^ n) ((inverse (f $$ fls_subdegree f)) ^ n) =
  4.2855 +      (fls_right_inverse f (inverse (f $$ fls_subdegree f))) ^ n"
  4.2856 +    using fls_left_inverse_eq_inverse[of f] fls_right_inverse_eq_inverse[of f]
  4.2857 +    by    auto
  4.2858 +qed
  4.2859 +
  4.2860 +instance fls :: (field) field
  4.2861 +  by (standard, simp_all add: field_simps)
  4.2862 +
  4.2863 +
  4.2864 +subsubsection \<open>Division\<close>
  4.2865 +
  4.2866 +lemma fls_divide_nth_below:
  4.2867 +  fixes f g :: "'a::{comm_monoid_add,uminus,times,inverse} fls"
  4.2868 +  shows "n < fls_subdegree f - fls_subdegree g \<Longrightarrow> (f div g) $$ n = 0"
  4.2869 +  by    (simp add: fls_divide_def)
  4.2870 +
  4.2871 +lemma fls_divide_nth_base:
  4.2872 +  fixes f g :: "'a::division_ring fls"
  4.2873 +  shows
  4.2874 +    "(f div g) $$ (fls_subdegree f - fls_subdegree g) =
  4.2875 +      f $$ fls_subdegree f / g $$ fls_subdegree g"
  4.2876 +  using fps_divide_nth_0'[of "fls_base_factor_to_fps g" "fls_base_factor_to_fps f"]
  4.2877 +        fls_base_factor_to_fps_subdegree[of g]
  4.2878 +  by    (simp add: fls_divide_def)
  4.2879 +
  4.2880 +lemma fls_div_zero [simp]:
  4.2881 +  "0 div (g :: 'a :: {comm_monoid_add,inverse,mult_zero,uminus} fls) = 0"
  4.2882 +  by (simp add: fls_divide_def)
  4.2883 +
  4.2884 +lemma fls_div_by_zero:
  4.2885 +  fixes   g :: "'a::{comm_monoid_add,inverse,mult_zero,uminus} fls"
  4.2886 +  assumes "inverse (0::'a) = 0"
  4.2887 +  shows   "g div 0 = 0"
  4.2888 +  by      (simp add: fls_divide_def assms fps_div_by_zero')
  4.2889 +
  4.2890 +lemma fls_divide_times:
  4.2891 +  fixes f g :: "'a::{semiring_0,inverse,uminus} fls"
  4.2892 +  shows "(f * g) / h = f * (g / h)"
  4.2893 +  by    (simp add: fls_divide_convert_times_inverse mult.assoc)
  4.2894 +
  4.2895 +lemma fls_divide_times2:
  4.2896 +  fixes f g :: "'a::{comm_semiring_0,inverse,uminus} fls"
  4.2897 +  shows "(f * g) / h = (f / h) * g"
  4.2898 +  using fls_divide_times[of g f h]
  4.2899 +  by    (simp add: mult.commute)
  4.2900 +
  4.2901 +lemma fls_divide_subdegree_ge:
  4.2902 +  fixes   f g :: "'a::{comm_monoid_add,uminus,times,inverse} fls"
  4.2903 +  assumes "f / g \<noteq> 0"
  4.2904 +  shows   "fls_subdegree (f / g) \<ge> fls_subdegree f - fls_subdegree g"
  4.2905 +  using   assms fls_divide_nth_below
  4.2906 +  by      (intro fls_subdegree_geI) simp
  4.2907 +
  4.2908 +lemma fls_divide_subdegree:
  4.2909 +  fixes   f g :: "'a::division_ring fls"
  4.2910 +  assumes "f \<noteq> 0" "g \<noteq> 0"
  4.2911 +  shows   "fls_subdegree (f / g) = fls_subdegree f - fls_subdegree g"
  4.2912 +proof (intro antisym)
  4.2913 +  from assms have "f $$ fls_subdegree f / g $$ fls_subdegree g \<noteq> 0" by (simp add: field_simps)
  4.2914 +  thus "fls_subdegree (f/g) \<le> fls_subdegree f - fls_subdegree g"
  4.2915 +    using fls_divide_nth_base[of f g] by (intro fls_subdegree_leI) simp
  4.2916 +  from assms have "f / g \<noteq> 0" by (simp add: field_simps)
  4.2917 +  thus "fls_subdegree (f/g) \<ge> fls_subdegree f - fls_subdegree g"
  4.2918 +    using fls_divide_subdegree_ge by fast
  4.2919 +qed
  4.2920 +
  4.2921 +lemma fls_divide_shift_numer_nonzero:
  4.2922 +  fixes   f g :: "'a :: {comm_monoid_add,inverse,times,uminus} fls"
  4.2923 +  assumes "f \<noteq> 0"
  4.2924 +  shows   "fls_shift m f / g = fls_shift m (f/g)"
  4.2925 +  using   assms fls_base_factor_to_fps_shift[of m f]
  4.2926 +  by      (simp add: fls_divide_def algebra_simps)
  4.2927 +
  4.2928 +lemma fls_divide_shift_numer:
  4.2929 +  fixes f g :: "'a :: {comm_monoid_add,inverse,mult_zero,uminus} fls"
  4.2930 +  shows "fls_shift m f / g = fls_shift m (f/g)"
  4.2931 +  using fls_divide_shift_numer_nonzero
  4.2932 +  by    (cases "f=0") auto
  4.2933 +
  4.2934 +lemma fls_divide_shift_denom_nonzero:
  4.2935 +  fixes   f g :: "'a :: {comm_monoid_add,inverse,times,uminus} fls"
  4.2936 +  assumes "g \<noteq> 0"
  4.2937 +  shows   "f / fls_shift m g = fls_shift (-m) (f/g)"
  4.2938 +  using   assms fls_base_factor_to_fps_shift[of m g]
  4.2939 +  by      (simp add: fls_divide_def algebra_simps)
  4.2940 +
  4.2941 +lemma fls_divide_shift_denom:
  4.2942 +  fixes   f g :: "'a :: division_ring fls"
  4.2943 +  shows   "f / fls_shift m g = fls_shift (-m) (f/g)"
  4.2944 +  using   fls_divide_shift_denom_nonzero
  4.2945 +  by      (cases "g=0") auto
  4.2946 +
  4.2947 +lemma fls_divide_shift_both_nonzero:
  4.2948 +  fixes   f g :: "'a :: {comm_monoid_add,inverse,times,uminus} fls"
  4.2949 +  assumes "f \<noteq> 0" "g \<noteq> 0"
  4.2950 +  shows   "fls_shift n f / fls_shift m g = fls_shift (n-m) (f/g)"
  4.2951 +  by      (simp add: assms fls_divide_shift_numer_nonzero fls_divide_shift_denom_nonzero)
  4.2952 +
  4.2953 +lemma fls_divide_shift_both [simp]:
  4.2954 +  fixes   f g :: "'a :: division_ring fls"
  4.2955 +  shows   "fls_shift n f / fls_shift m g = fls_shift (n-m) (f/g)"
  4.2956 +  using   fls_divide_shift_both_nonzero
  4.2957 +  by      (cases "f=0 \<or> g=0") auto
  4.2958 +
  4.2959 +lemma fls_divide_base_factor_numer:
  4.2960 +  "fls_base_factor f / g = fls_shift (fls_subdegree f) (f/g)"
  4.2961 +  using fls_base_factor_to_fps_base_factor[of f]
  4.2962 +        fls_base_factor_subdegree[of f]
  4.2963 +  by    (simp add: fls_divide_def algebra_simps)
  4.2964 +
  4.2965 +lemma fls_divide_base_factor_denom:
  4.2966 +  "f / fls_base_factor g = fls_shift (-fls_subdegree g) (f/g)"
  4.2967 +  using fls_base_factor_to_fps_base_factor[of g]
  4.2968 +        fls_base_factor_subdegree[of g]
  4.2969 +  by    (simp add: fls_divide_def)
  4.2970 +
  4.2971 +lemma fls_divide_base_factor':
  4.2972 +  "fls_base_factor f / fls_base_factor g = fls_shift (fls_subdegree f - fls_subdegree g) (f/g)"
  4.2973 +  using fls_divide_base_factor_numer[of f "fls_base_factor g"]
  4.2974 +        fls_divide_base_factor_denom[of f g]
  4.2975 +  by    simp
  4.2976 +
  4.2977 +lemma fls_divide_base_factor:
  4.2978 +  fixes f g :: "'a :: division_ring fls"
  4.2979 +  shows "fls_base_factor f / fls_base_factor g = fls_base_factor (f/g)"
  4.2980 +  using fls_divide_subdegree[of f g] fls_divide_base_factor'
  4.2981 +  by    fastforce
  4.2982 +
  4.2983 +lemma fls_divide_regpart:
  4.2984 +  fixes   f g :: "'a::{inverse,comm_monoid_add,uminus,mult_zero} fls"
  4.2985 +  assumes "fls_subdegree f \<ge> 0" "fls_subdegree g \<ge> 0"
  4.2986 +  shows   "fls_regpart (f / g) = fls_regpart f / fls_regpart g"
  4.2987 +proof -
  4.2988 +  have deg0:
  4.2989 +    "\<And>g. fls_subdegree g = 0 \<Longrightarrow>
  4.2990 +      fls_regpart (f / g) = fls_regpart f / fls_regpart g"
  4.2991 +    by  (simp add:
  4.2992 +          assms(1) fls_divide_convert_times_inverse fls_inverse_subdegree_0
  4.2993 +          fls_times_conv_regpart fls_inverse_regpart fls_regpart_subdegree_conv fps_divide_unit'
  4.2994 +        )
  4.2995 +  show ?thesis
  4.2996 +  proof (cases "fls_subdegree g = 0")
  4.2997 +    case False
  4.2998 +    hence "fls_base_factor g \<noteq> 0" using fls_base_factor_nonzero[of g] by force
  4.2999 +    with assms(2) show ?thesis
  4.3000 +      using fls_divide_shift_denom_nonzero[of "fls_base_factor g" f "-fls_subdegree g"]
  4.3001 +            fps_shift_fls_regpart_conv_fls_shift[of
  4.3002 +              "nat (fls_subdegree g)" "f / fls_base_factor g"
  4.3003 +            ]
  4.3004 +            fls_base_factor_subdegree[of g] deg0
  4.3005 +            fls_regpart_subdegree_conv[of g] fps_unit_factor_fls_regpart[of g]
  4.3006 +      by    (simp add:
  4.3007 +              fls_conv_base_factor_shift_subdegree fls_regpart_subdegree_conv fps_divide_def
  4.3008 +            )
  4.3009 +  qed (rule deg0)
  4.3010 +qed
  4.3011 +
  4.3012 +lemma fls_divide_fls_base_factor_to_fps':
  4.3013 +  fixes f g :: "'a::{comm_monoid_add,uminus,inverse,mult_zero} fls"
  4.3014 +  shows
  4.3015 +    "fls_base_factor_to_fps f / fls_base_factor_to_fps g =
  4.3016 +      fls_regpart (fls_shift (fls_subdegree f - fls_subdegree g) (f / g))"
  4.3017 +  using fls_base_factor_subdegree[of f] fls_base_factor_subdegree[of g]
  4.3018 +        fls_divide_regpart[of "fls_base_factor f" "fls_base_factor g"]
  4.3019 +        fls_divide_base_factor'[of f g]
  4.3020 +    by  simp
  4.3021 +
  4.3022 +lemma fls_divide_fls_base_factor_to_fps:
  4.3023 +  fixes f g :: "'a::division_ring fls"
  4.3024 +  shows "fls_base_factor_to_fps f / fls_base_factor_to_fps g = fls_base_factor_to_fps (f / g)"
  4.3025 +  using fls_divide_fls_base_factor_to_fps' fls_divide_subdegree[of f g]
  4.3026 +  by    fastforce
  4.3027 +
  4.3028 +lemma fls_divide_fps_to_fls:
  4.3029 +  fixes f g :: "'a::{inverse,ab_group_add,mult_zero} fps"
  4.3030 +  assumes "subdegree f \<ge> subdegree g"
  4.3031 +  shows   "fps_to_fls f / fps_to_fls g = fps_to_fls (f/g)"
  4.3032 +proof-
  4.3033 +  have 1:
  4.3034 +    "fps_to_fls f / fps_to_fls g =
  4.3035 +      fls_shift (int (subdegree g)) (fps_to_fls (f * inverse (unit_factor g)))"
  4.3036 +    using fls_base_factor_to_fps_to_fls[of f] fls_base_factor_to_fps_to_fls[of g]
  4.3037 +          fls_subdegree_fls_to_fps[of f] fls_subdegree_fls_to_fps[of g]
  4.3038 +          fps_divide_def[of "unit_factor f" "unit_factor g"]
  4.3039 +          fls_times_fps_to_fls[of "unit_factor f" "inverse (unit_factor g)"]
  4.3040 +          fls_shifted_times_simps(2)[of "-int (subdegree f)" "fps_to_fls (unit_factor f)"]
  4.3041 +          fls_times_fps_to_fls[of f "inverse (unit_factor g)"]
  4.3042 +    by    (simp add: fls_divide_def)
  4.3043 +  with assms show ?thesis
  4.3044 +    using fps_mult_subdegree_ge[of f "inverse (unit_factor g)"]
  4.3045 +          fps_shift_to_fls[of "subdegree g" "f * inverse (unit_factor g)"]
  4.3046 +    by    (cases "f * inverse (unit_factor g) = 0") (simp_all add: fps_divide_def)
  4.3047 +qed
  4.3048 +
  4.3049 +lemma fls_divide_1':
  4.3050 +  fixes   f :: "'a::{comm_monoid_add,inverse,mult_zero,uminus,zero_neq_one,monoid_mult} fls"
  4.3051 +  assumes "inverse (1::'a) = 1"
  4.3052 +  shows   "f / 1 = f"
  4.3053 +  using   assms fls_conv_base_factor_to_fps_shift_subdegree[of f]
  4.3054 +  by      (simp add: fls_divide_def fps_divide_1')
  4.3055 +
  4.3056 +lemma fls_divide_1 [simp]: "a / 1 = (a::'a::division_ring fls)"
  4.3057 +  by (rule fls_divide_1'[OF inverse_1])
  4.3058 +
  4.3059 +lemma fls_const_divide_const:
  4.3060 +  fixes x y :: "'a::division_ring"
  4.3061 +  shows "fls_const x / fls_const y = fls_const (x/y)"
  4.3062 +  by    (simp add: fls_divide_def fls_base_factor_to_fps_const fps_const_divide)
  4.3063 +
  4.3064 +lemma fls_divide_X':
  4.3065 +  fixes   f :: "'a::{comm_monoid_add,inverse,mult_zero,uminus,zero_neq_one,monoid_mult} fls"
  4.3066 +  assumes "inverse (1::'a) = 1"
  4.3067 +  shows   "f / fls_X = fls_shift 1 f"
  4.3068 +proof-
  4.3069 +  from assms have
  4.3070 +    "f / fls_X =
  4.3071 +      fls_shift 1 (fls_shift (-fls_subdegree f) (fps_to_fls (fls_base_factor_to_fps f)))"
  4.3072 +    by (simp add: fls_divide_def fps_divide_1')
  4.3073 +  also have "\<dots> = fls_shift 1 f"
  4.3074 +    using fls_conv_base_factor_to_fps_shift_subdegree[of f]
  4.3075 +    by simp
  4.3076 +  finally show ?thesis by simp
  4.3077 +qed
  4.3078 +
  4.3079 +lemma fls_divide_X [simp]:
  4.3080 +  fixes f :: "'a::division_ring fls"
  4.3081 +  shows "f / fls_X = fls_shift 1 f"
  4.3082 +  by    (rule fls_divide_X'[OF inverse_1])
  4.3083 +
  4.3084 +lemma fls_divide_X_power':
  4.3085 +  fixes   f :: "'a::{semiring_1,inverse,uminus} fls"
  4.3086 +  assumes "inverse (1::'a) = 1"
  4.3087 +  shows   "f / (fls_X ^ n) = fls_shift n f"
  4.3088 +proof-
  4.3089 +  have "fls_base_factor_to_fps ((fls_X::'a fls) ^ n) = 1" by (rule fls_X_power_base_factor_to_fps)
  4.3090 +  with assms have
  4.3091 +    "f / (fls_X ^ n) =
  4.3092 +      fls_shift n (fls_shift (-fls_subdegree f) (fps_to_fls (fls_base_factor_to_fps f)))"
  4.3093 +    by (simp add: fls_divide_def fps_divide_1')
  4.3094 +  also have "\<dots> = fls_shift n f"
  4.3095 +    using fls_conv_base_factor_to_fps_shift_subdegree[of f] by simp
  4.3096 +  finally show ?thesis by simp
  4.3097 +qed
  4.3098 +
  4.3099 +lemma fls_divide_X_power [simp]:
  4.3100 +  fixes f :: "'a::division_ring fls"
  4.3101 +  shows "f / (fls_X ^ n) = fls_shift n f"
  4.3102 +  by    (rule fls_divide_X_power'[OF inverse_1])
  4.3103 +
  4.3104 +lemma fls_divide_X_inv':
  4.3105 +  fixes   f :: "'a::{comm_monoid_add,inverse,mult_zero,uminus,zero_neq_one,monoid_mult} fls"
  4.3106 +  assumes "inverse (1::'a) = 1"
  4.3107 +  shows   "f / fls_X_inv = fls_shift (-1) f"
  4.3108 +proof-
  4.3109 +  from assms have
  4.3110 +    "f / fls_X_inv =
  4.3111 +      fls_shift (-1) (fls_shift (-fls_subdegree f) (fps_to_fls (fls_base_factor_to_fps f)))"
  4.3112 +    by (simp add: fls_divide_def fps_divide_1' algebra_simps)
  4.3113 +  also have "\<dots> = fls_shift (-1) f"
  4.3114 +    using fls_conv_base_factor_to_fps_shift_subdegree[of f]
  4.3115 +    by simp
  4.3116 +  finally show ?thesis by simp
  4.3117 +qed
  4.3118 +
  4.3119 +lemma fls_divide_X_inv [simp]:
  4.3120 +  fixes f :: "'a::division_ring fls"
  4.3121 +  shows "f / fls_X_inv = fls_shift (-1) f"
  4.3122 +  by    (rule fls_divide_X_inv'[OF inverse_1])
  4.3123 +
  4.3124 +lemma fls_divide_X_inv_power':
  4.3125 +  fixes   f :: "'a::{semiring_1,inverse,uminus} fls"
  4.3126 +  assumes "inverse (1::'a) = 1"
  4.3127 +  shows   "f / (fls_X_inv ^ n) = fls_shift (-int n) f"
  4.3128 +proof-
  4.3129 +  have "fls_base_factor_to_fps ((fls_X_inv::'a fls) ^ n) = 1"
  4.3130 +    by (rule fls_X_inv_power_base_factor_to_fps)
  4.3131 +  with assms have
  4.3132 +    "f / (fls_X_inv ^ n) =
  4.3133 +      fls_shift (-int n + -fls_subdegree f) (fps_to_fls (fls_base_factor_to_fps f))"
  4.3134 +    by (simp add: fls_divide_def fps_divide_1')
  4.3135 +  also have
  4.3136 +    "\<dots> = fls_shift (-int n) (fls_shift (-fls_subdegree f) (fps_to_fls (fls_base_factor_to_fps f)))"
  4.3137 +    by (simp add: add.commute)
  4.3138 +  also have "\<dots> = fls_shift (-int n) f"
  4.3139 +    using fls_conv_base_factor_to_fps_shift_subdegree[of f] by simp
  4.3140 +  finally show ?thesis by simp
  4.3141 +qed
  4.3142 +
  4.3143 +lemma fls_divide_X_inv_power [simp]:
  4.3144 +  fixes f :: "'a::division_ring fls"
  4.3145 +  shows "f / (fls_X_inv ^ n) = fls_shift (-int n) f"
  4.3146 +  by    (rule fls_divide_X_inv_power'[OF inverse_1])
  4.3147 +
  4.3148 +lemma fls_divide_X_intpow':
  4.3149 +  fixes   f :: "'a::{semiring_1,inverse,uminus} fls"
  4.3150 +  assumes "inverse (1::'a) = 1"
  4.3151 +  shows   "f / (fls_X_intpow i) = fls_shift i f"
  4.3152 +  using   assms
  4.3153 +  by      (simp add: fls_divide_shift_denom_nonzero fls_divide_1')
  4.3154 +
  4.3155 +lemma fls_divide_X_intpow_conv_times':
  4.3156 +  fixes   f :: "'a::{semiring_1,inverse,uminus} fls"
  4.3157 +  assumes "inverse (1::'a) = 1"
  4.3158 +  shows   "f / (fls_X_intpow i) = f * fls_X_intpow (-i)"
  4.3159 +  using   assms fls_X_intpow_times_conv_shift(2)[of f "-i"]
  4.3160 +  by      (simp add: fls_divide_X_intpow')
  4.3161 +
  4.3162 +lemma fls_divide_X_intpow:
  4.3163 +  fixes f :: "'a::division_ring fls"
  4.3164 +  shows "f / (fls_X_intpow i) = fls_shift i f"
  4.3165 +  by    (rule fls_divide_X_intpow'[OF inverse_1])
  4.3166 +
  4.3167 +lemma fls_divide_X_intpow_conv_times:
  4.3168 +  fixes f :: "'a::division_ring fls"
  4.3169 +  shows "f / (fls_X_intpow i) = f * fls_X_intpow (-i)"
  4.3170 +  by    (rule fls_divide_X_intpow_conv_times'[OF inverse_1])
  4.3171 +
  4.3172 +lemma fls_X_intpow_div_fls_X_intpow_semiring1:
  4.3173 +  assumes "inverse (1::'a::{semiring_1,inverse,uminus}) = 1"
  4.3174 +  shows   "(fls_X_intpow i :: 'a fls) / fls_X_intpow j = fls_X_intpow (i-j)"
  4.3175 +  by      (simp add: assms fls_divide_shift_both_nonzero fls_divide_1')
  4.3176 +
  4.3177 +lemma fls_X_intpow_div_fls_X_intpow:
  4.3178 +  "(fls_X_intpow i :: 'a::division_ring fls) / fls_X_intpow j = fls_X_intpow (i-j)"
  4.3179 +  by (rule fls_X_intpow_div_fls_X_intpow_semiring1[OF inverse_1])
  4.3180 +
  4.3181 +lemma fls_divide_add:
  4.3182 +  fixes   f g h :: "'a::{semiring_0,inverse,uminus} fls"
  4.3183 +  shows   "(f + g) / h = f / h + g / h"
  4.3184 +  by      (simp add: fls_divide_convert_times_inverse algebra_simps)
  4.3185 +
  4.3186 +lemma fls_divide_diff:
  4.3187 +  fixes f g h :: "'a::{ring,inverse} fls"
  4.3188 +  shows "(f - g) / h = f / h - g / h"
  4.3189 +  by    (simp add: fls_divide_convert_times_inverse algebra_simps)
  4.3190 +
  4.3191 +lemma fls_divide_uminus:
  4.3192 +  fixes f g h :: "'a::{ring,inverse} fls"
  4.3193 +  shows "(- f) / g = - (f / g)"
  4.3194 +  by    (simp add: fls_divide_convert_times_inverse)
  4.3195 +
  4.3196 +lemma fls_divide_uminus':
  4.3197 +  fixes f g h :: "'a::division_ring fls"
  4.3198 +  shows "f / (- g) = - (f / g)"
  4.3199 +  by    (simp add: fls_divide_convert_times_inverse)
  4.3200 +
  4.3201 +
  4.3202 +subsubsection \<open>Units\<close>
  4.3203 +
  4.3204 +lemma fls_is_left_unit_iff_base_is_left_unit:
  4.3205 +  fixes f :: "'a :: ring_1_no_zero_divisors fls"
  4.3206 +  shows "(\<exists>g. 1 = f * g) \<longleftrightarrow> (\<exists>k. 1 = f $$ fls_subdegree f * k)"
  4.3207 +proof
  4.3208 +  assume "\<exists>g. 1 = f * g"
  4.3209 +  then obtain g where "1 = f * g" by fast
  4.3210 +  hence "1 = (f $$ fls_subdegree f) * (g $$ fls_subdegree g)"
  4.3211 +    using fls_subdegree_mult[of f g] fls_times_base[of f g] by fastforce
  4.3212 +  thus "\<exists>k. 1 = f $$ fls_subdegree f * k" by fast
  4.3213 +next
  4.3214 +  assume "\<exists>k. 1 = f $$ fls_subdegree f * k"
  4.3215 +  then obtain k where "1 = f $$ fls_subdegree f * k" by fast
  4.3216 +  hence "1 = f * fls_right_inverse f k"
  4.3217 +    using fls_right_inverse by simp
  4.3218 +  thus "\<exists>g. 1 = f * g" by fast
  4.3219 +qed
  4.3220 +
  4.3221 +lemma fls_is_right_unit_iff_base_is_right_unit:
  4.3222 +  fixes f :: "'a :: ring_1_no_zero_divisors fls"
  4.3223 +  shows "(\<exists>g. 1 = g * f) \<longleftrightarrow> (\<exists>k. 1 = k * f $$ fls_subdegree f)"
  4.3224 +proof
  4.3225 +  assume "\<exists>g. 1 = g * f"
  4.3226 +  then obtain g where "1 = g * f" by fast
  4.3227 +  hence "1 = (g $$ fls_subdegree g) * (f $$ fls_subdegree f)"
  4.3228 +    using fls_subdegree_mult[of g f] fls_times_base[of g f] by fastforce
  4.3229 +  thus "\<exists>k. 1 = k * f $$ fls_subdegree f" by fast
  4.3230 +next
  4.3231 +  assume "\<exists>k. 1 = k * f $$ fls_subdegree f"
  4.3232 +  then obtain k where "1 = k * f $$ fls_subdegree f" by fast
  4.3233 +  hence "1 = fls_left_inverse f k * f"
  4.3234 +    using fls_left_inverse by simp
  4.3235 +  thus "\<exists>g. 1 = g * f" by fast
  4.3236 +qed
  4.3237 +
  4.3238 +
  4.3239 +subsection \<open>Formal differentiation and integration\<close>
  4.3240 +
  4.3241 +
  4.3242 +subsubsection \<open>Derivative definition and basic properties\<close>
  4.3243 +
  4.3244 +definition "fls_deriv f = Abs_fls (\<lambda>n. of_int (n+1) * f$$(n+1))"
  4.3245 +
  4.3246 +lemma fls_deriv_nth[simp]: "fls_deriv f $$ n = of_int (n+1) * f$$(n+1)"
  4.3247 +proof-
  4.3248 +  obtain N where "\<forall>n<N. f$$n = 0" by (elim fls_nth_vanishes_belowE)
  4.3249 +  hence "\<forall>n<N-1. of_int (n+1) * f$$(n+1) = 0" by auto
  4.3250 +  thus ?thesis using nth_Abs_fls_lower_bound unfolding fls_deriv_def by simp
  4.3251 +qed
  4.3252 +
  4.3253 +lemma fls_deriv_residue: "fls_deriv f $$ -1 = 0"
  4.3254 +  by simp
  4.3255 +
  4.3256 +lemma fls_deriv_const[simp]: "fls_deriv (fls_const x) = 0"
  4.3257 +proof (intro fls_eqI)
  4.3258 +  fix n show "fls_deriv (fls_const x) $$ n = 0$$n"
  4.3259 +    by (cases "n+1=0") auto
  4.3260 +qed
  4.3261 +
  4.3262 +lemma fls_deriv_of_nat[simp]: "fls_deriv (of_nat n) = 0"
  4.3263 +  by (simp add: fls_of_nat)
  4.3264 +
  4.3265 +lemma fls_deriv_of_int[simp]: "fls_deriv (of_int i) = 0"
  4.3266 +  by (simp add: fls_of_int)
  4.3267 +
  4.3268 +lemma fls_deriv_zero[simp]: "fls_deriv 0 = 0"
  4.3269 +  using fls_deriv_const[of 0] by simp
  4.3270 +
  4.3271 +lemma fls_deriv_one[simp]: "fls_deriv 1 = 0"
  4.3272 +  using fls_deriv_const[of 1] by simp
  4.3273 +
  4.3274 +lemma fls_deriv_subdegree':
  4.3275 +  assumes "of_int (fls_subdegree f) * f $$ fls_subdegree f \<noteq> 0"
  4.3276 +  shows   "fls_subdegree (fls_deriv f) = fls_subdegree f - 1"
  4.3277 +  by      (auto intro: fls_subdegree_eqI simp: assms)
  4.3278 +
  4.3279 +lemma fls_deriv_subdegree0:
  4.3280 +  assumes "fls_subdegree f = 0"
  4.3281 +  shows   "fls_subdegree (fls_deriv f) \<ge> 0"
  4.3282 +proof (cases "fls_deriv f = 0")
  4.3283 +  case False
  4.3284 +  show ?thesis
  4.3285 +  proof (intro fls_subdegree_geI, rule False)
  4.3286 +    fix k :: int assume "k < 0"
  4.3287 +    with assms show "fls_deriv f $$ k = 0" by (cases "k=-1") auto
  4.3288 +  qed
  4.3289 +qed simp
  4.3290 +
  4.3291 +lemma fls_subdegree_deriv':
  4.3292 +  fixes   f :: "'a::ring_1_no_zero_divisors fls"
  4.3293 +  assumes "(of_int (fls_subdegree f) :: 'a) \<noteq> 0"
  4.3294 +  shows   "fls_subdegree (fls_deriv f) = fls_subdegree f - 1"
  4.3295 +  using   assms nth_fls_subdegree_zero_iff[of f]
  4.3296 +  by      (auto intro: fls_deriv_subdegree')
  4.3297 +
  4.3298 +lemma fls_subdegree_deriv:
  4.3299 +  fixes   f :: "'a::{ring_1_no_zero_divisors,ring_char_0} fls"
  4.3300 +  assumes "fls_subdegree f \<noteq> 0"
  4.3301 +  shows   "fls_subdegree (fls_deriv f) = fls_subdegree f - 1"
  4.3302 +  by      (auto intro: fls_subdegree_deriv' simp: assms)
  4.3303 +
  4.3304 +text \<open>
  4.3305 +  Shifting is like multiplying by a power of the implied variable, and so satisfies a product-like
  4.3306 +  rule.
  4.3307 +\<close>
  4.3308 +
  4.3309 +lemma fls_deriv_shift:
  4.3310 +  "fls_deriv (fls_shift n f) = of_int (-n) * fls_shift (n+1) f + fls_shift n (fls_deriv f)"
  4.3311 +  by (intro fls_eqI) (simp flip: fls_shift_fls_shift add: algebra_simps)
  4.3312 +
  4.3313 +lemma fls_deriv_X [simp]: "fls_deriv fls_X = 1"
  4.3314 +  by (intro fls_eqI) simp
  4.3315 +
  4.3316 +lemma fls_deriv_X_inv [simp]: "fls_deriv fls_X_inv = - (fls_X_inv\<^sup>2)"
  4.3317 +proof-
  4.3318 +  have "fls_deriv fls_X_inv = - (fls_shift 2 1)"
  4.3319 +    by (simp add: fls_X_inv_conv_shift_1 fls_deriv_shift)
  4.3320 +  thus ?thesis by (simp add: fls_X_inv_power_conv_shift_1)
  4.3321 +qed
  4.3322 +
  4.3323 +lemma fls_deriv_delta:
  4.3324 +  "fls_deriv (Abs_fls (\<lambda>n. if n=m then c else 0)) =
  4.3325 +    Abs_fls (\<lambda>n. if n=m-1 then of_int m * c else 0)"
  4.3326 +proof-
  4.3327 +  have
  4.3328 +    "fls_deriv (Abs_fls (\<lambda>n. if n=m then c else 0)) = fls_shift (1-m) (fls_const (of_int m * c))"
  4.3329 +    using fls_deriv_shift[of "-m" "fls_const c"]
  4.3330 +    by    (simp
  4.3331 +            add: fls_shift_const fls_of_int fls_shifted_times_simps(1)[symmetric]
  4.3332 +            fls_const_mult_const[symmetric]
  4.3333 +            del: fls_const_mult_const
  4.3334 +          )
  4.3335 +  thus ?thesis by (simp add: fls_shift_const)
  4.3336 +qed
  4.3337 +
  4.3338 +lemma fls_deriv_base_factor:
  4.3339 +  "fls_deriv (fls_base_factor f) =
  4.3340 +    of_int (-fls_subdegree f) * fls_shift (fls_subdegree f + 1) f +
  4.3341 +    fls_shift (fls_subdegree f) (fls_deriv f)"
  4.3342 +  by (simp add: fls_deriv_shift)
  4.3343 +
  4.3344 +lemma fls_regpart_deriv: "fls_regpart (fls_deriv f) = fps_deriv (fls_regpart f)"
  4.3345 +proof (intro fps_ext)
  4.3346 +  fix n
  4.3347 +  have  1: "(of_nat n :: 'a) + 1 = of_nat (n+1)"
  4.3348 +  and   2: "int n + 1 = int (n + 1)"
  4.3349 +    by  auto
  4.3350 +  show "fls_regpart (fls_deriv f) $ n = fps_deriv (fls_regpart f) $ n" by (simp add: 1 2)
  4.3351 +qed
  4.3352 +
  4.3353 +lemma fls_prpart_deriv:
  4.3354 +  fixes f :: "'a :: {comm_ring_1,ring_no_zero_divisors} fls"
  4.3355 +  \<comment> \<open>Commutivity and no zero divisors are required by the definition of @{const pderiv}.\<close>
  4.3356 +  shows "fls_prpart (fls_deriv f) = - pCons 0 (pCons 0 (pderiv (fls_prpart f)))"
  4.3357 +proof (intro poly_eqI)
  4.3358 +  fix n
  4.3359 +  show
  4.3360 +    "coeff (fls_prpart (fls_deriv f)) n =
  4.3361 +      coeff (- pCons 0 (pCons 0 (pderiv (fls_prpart f)))) n"
  4.3362 +  proof (cases n)
  4.3363 +    case (Suc m)
  4.3364 +    hence n: "n = Suc m" by fast
  4.3365 +    show ?thesis
  4.3366 +    proof (cases m)
  4.3367 +      case (Suc k)
  4.3368 +      with n have
  4.3369 +        "coeff (- pCons 0 (pCons 0 (pderiv (fls_prpart f)))) n =
  4.3370 +          - coeff (pderiv (fls_prpart f)) k"
  4.3371 +        by (simp flip: coeff_minus)
  4.3372 +      with Suc n show ?thesis by (simp add: coeff_pderiv algebra_simps)
  4.3373 +    qed (simp add: n)
  4.3374 +  qed simp
  4.3375 +qed
  4.3376 +
  4.3377 +lemma pderiv_fls_prpart:
  4.3378 +  "pderiv (fls_prpart f) = - poly_shift 2 (fls_prpart (fls_deriv f))"
  4.3379 +  by (intro poly_eqI) (simp add: coeff_pderiv coeff_poly_shift algebra_simps)
  4.3380 +
  4.3381 +lemma fls_deriv_fps_to_fls: "fls_deriv (fps_to_fls f) = fps_to_fls (fps_deriv f)"
  4.3382 +proof (intro fls_eqI)
  4.3383 +  fix n
  4.3384 +  show "fls_deriv (fps_to_fls f) $$ n  = fps_to_fls (fps_deriv f) $$ n"
  4.3385 +  proof (cases "n\<ge>0")
  4.3386 +    case True
  4.3387 +    from True have 1: "nat (n + 1) = nat n + 1" by simp
  4.3388 +    from True have 2: "(of_int (n + 1) :: 'a) = of_nat (nat (n+1))" by simp
  4.3389 +    from True show ?thesis using arg_cong[OF 2, of "\<lambda>x. x * f $ (nat n+1)"] by (simp add: 1)
  4.3390 +  next
  4.3391 +    case False thus ?thesis by (cases "n=-1") auto
  4.3392 +  qed
  4.3393 +qed
  4.3394 +
  4.3395 +
  4.3396 +subsubsection \<open>Algebra rules of the derivative\<close>
  4.3397 +
  4.3398 +lemma fls_deriv_add [simp]: "fls_deriv (f+g) = fls_deriv f + fls_deriv g"
  4.3399 +  by (auto intro: fls_eqI simp: algebra_simps)
  4.3400 +
  4.3401 +lemma fls_deriv_sub [simp]: "fls_deriv (f-g) = fls_deriv f - fls_deriv g"
  4.3402 +  by (auto intro: fls_eqI simp: algebra_simps)
  4.3403 +
  4.3404 +lemma fls_deriv_neg [simp]: "fls_deriv (-f) = - fls_deriv f"
  4.3405 +  using fls_deriv_sub[of 0 f] by simp
  4.3406 +
  4.3407 +lemma fls_deriv_mult [simp]:
  4.3408 +  "fls_deriv (f*g) = f * fls_deriv g + fls_deriv f * g"
  4.3409 +proof-
  4.3410 +  define df dg :: int
  4.3411 +    where "df \<equiv> fls_subdegree f"
  4.3412 +    and   "dg \<equiv> fls_subdegree g"
  4.3413 +  define uf ug :: "'a fls"
  4.3414 +    where "uf \<equiv> fls_base_factor f"
  4.3415 +    and   "ug \<equiv> fls_base_factor g"
  4.3416 +  have
  4.3417 +    "f * fls_deriv g =
  4.3418 +      of_int dg * fls_shift (1 - dg) (f * ug) + fls_shift (-dg) (f * fls_deriv ug)"
  4.3419 +    "fls_deriv f * g =
  4.3420 +      of_int df * fls_shift (1 - df) (uf * g) + fls_shift (-df) (fls_deriv uf * g)"
  4.3421 +    using fls_deriv_shift[of "-df" uf] fls_deriv_shift[of "-dg" ug]
  4.3422 +          mult_of_int_commute[of dg f]
  4.3423 +          mult.assoc[of "of_int dg" f]
  4.3424 +          fls_shifted_times_simps(1)[of f "1 - dg" ug]
  4.3425 +          fls_shifted_times_simps(1)[of f "-dg" "fls_deriv ug"]
  4.3426 +          fls_shifted_times_simps(2)[of "1 - df" uf g]
  4.3427 +          fls_shifted_times_simps(2)[of "-df" "fls_deriv uf" g]
  4.3428 +    by (auto simp add: algebra_simps df_def dg_def uf_def ug_def)
  4.3429 +  moreover have
  4.3430 +    "fls_deriv (f*g) =
  4.3431 +      ( of_int dg * fls_shift (1 - dg) (f * ug) + fls_shift (-dg) (f * fls_deriv ug) ) +
  4.3432 +      ( of_int df * fls_shift (1 - df) (uf * g) + fls_shift (-df) (fls_deriv uf * g) )
  4.3433 +    "
  4.3434 +    using fls_deriv_shift[of
  4.3435 +            "- (df + dg)" "fps_to_fls (fls_base_factor_to_fps f * fls_base_factor_to_fps g)"
  4.3436 +          ]
  4.3437 +          fls_deriv_fps_to_fls[of "fls_base_factor_to_fps f * fls_base_factor_to_fps g"]
  4.3438 +          fps_deriv_mult[of "fls_base_factor_to_fps f" "fls_base_factor_to_fps g"]
  4.3439 +          distrib_right[of
  4.3440 +            "of_int df" "of_int dg"
  4.3441 +            "fls_shift (1 - (df + dg)) (
  4.3442 +              fps_to_fls (fls_base_factor_to_fps f * fls_base_factor_to_fps g)
  4.3443 +            )"
  4.3444 +          ]
  4.3445 +          fls_times_conv_fps_times[of uf ug]
  4.3446 +          fls_base_factor_subdegree[of f] fls_base_factor_subdegree[of g]
  4.3447 +          fls_regpart_deriv[of ug]
  4.3448 +          fls_times_conv_fps_times[of uf "fls_deriv ug"]
  4.3449 +          fls_deriv_subdegree0[of ug]
  4.3450 +          fls_regpart_deriv[of uf]
  4.3451 +          fls_times_conv_fps_times[of "fls_deriv uf" ug]
  4.3452 +          fls_deriv_subdegree0[of uf]
  4.3453 +          fls_shifted_times_simps(1)[of uf "-dg" ug]
  4.3454 +          fls_shifted_times_simps(1)[of "fls_deriv uf" "-dg" ug]
  4.3455 +          fls_shifted_times_simps(2)[of "-df" uf ug]
  4.3456 +          fls_shifted_times_simps(2)[of "-df" uf "fls_deriv ug"]
  4.3457 +    by (simp add: fls_times_def algebra_simps df_def dg_def uf_def ug_def)
  4.3458 +  ultimately show ?thesis by simp
  4.3459 +qed
  4.3460 +
  4.3461 +lemma fls_deriv_mult_const_left:
  4.3462 +  "fls_deriv (fls_const c * f) = fls_const c * fls_deriv f"
  4.3463 +  by simp
  4.3464 +
  4.3465 +lemma fls_deriv_linear:
  4.3466 +  "fls_deriv (fls_const a * f + fls_const b * g) =
  4.3467 +    fls_const a * fls_deriv f + fls_const b * fls_deriv g"
  4.3468 +  by simp
  4.3469 +
  4.3470 +lemma fls_deriv_mult_const_right:
  4.3471 +  "fls_deriv (f * fls_const c) = fls_deriv f * fls_const c"
  4.3472 +  by simp
  4.3473 +
  4.3474 +lemma fls_deriv_linear2:
  4.3475 +  "fls_deriv (f * fls_const a + g * fls_const b) =
  4.3476 +    fls_deriv f * fls_const a + fls_deriv g * fls_const b"
  4.3477 +  by simp
  4.3478 +
  4.3479 +lemma fls_deriv_sum:
  4.3480 +  "fls_deriv (sum f S) = sum (\<lambda>i. fls_deriv (f i)) S"
  4.3481 +proof (cases "finite S")
  4.3482 +  case True show ?thesis
  4.3483 +    by (induct rule: finite_induct [OF True]) simp_all
  4.3484 +qed simp
  4.3485 +
  4.3486 +lemma fls_deriv_power:
  4.3487 +  fixes f :: "'a::comm_ring_1 fls"
  4.3488 +  shows "fls_deriv (f^n) = of_nat n * f^(n-1) * fls_deriv f"
  4.3489 +proof (cases n)
  4.3490 +  case (Suc m)
  4.3491 +  have "fls_deriv (f^Suc m) = of_nat (Suc m) * f^m * fls_deriv f"
  4.3492 +    by (induct m) (simp_all add: algebra_simps)
  4.3493 +  with Suc show ?thesis by simp
  4.3494 +qed simp
  4.3495 +
  4.3496 +lemma fls_deriv_X_power:
  4.3497 +  "fls_deriv (fls_X ^ n) = of_nat n * fls_X ^ (n-1)"
  4.3498 +proof (cases n)
  4.3499 +  case (Suc m)
  4.3500 +  have "fls_deriv (fls_X^Suc m) = of_nat (Suc m) * fls_X^m"
  4.3501 +    by (induct m) (simp_all add: mult_of_nat_commute algebra_simps)
  4.3502 +  with Suc show ?thesis by simp
  4.3503 +qed simp
  4.3504 +
  4.3505 +lemma fls_deriv_X_inv_power:
  4.3506 +  "fls_deriv (fls_X_inv ^ n) = - of_nat n * fls_X_inv ^ (Suc n)"
  4.3507 +proof (cases n)
  4.3508 +  case (Suc m)
  4.3509 +  define iX :: "'a fls" where "iX \<equiv> fls_X_inv"
  4.3510 +  have "fls_deriv (iX ^ Suc m) = - of_nat (Suc m) * iX ^ (Suc (Suc m))"
  4.3511 +  proof (induct m)
  4.3512 +    case (Suc m)
  4.3513 +    have "- of_nat (Suc m + 1) * iX ^ Suc (Suc (Suc m)) =
  4.3514 +            iX * (-of_nat (Suc m) * iX ^ Suc (Suc m)) +
  4.3515 +                  - (iX ^ 2 * iX ^ Suc m)"
  4.3516 +      using distrib_right[of "-of_nat (Suc m)" "-(1::'a fls)" "fls_X_inv ^ Suc (Suc (Suc m))"]
  4.3517 +      by (simp add: algebra_simps mult_of_nat_commute power2_eq_square Suc iX_def)
  4.3518 +    thus ?case using Suc by (simp add: iX_def)
  4.3519 +  qed (simp add: numeral_2_eq_2 iX_def)
  4.3520 +  with Suc show ?thesis by (simp add: iX_def)
  4.3521 +qed simp
  4.3522 +
  4.3523 +lemma fls_deriv_X_intpow:
  4.3524 +  "fls_deriv (fls_X_intpow i) = of_int i * fls_X_intpow (i-1)"
  4.3525 +  by (simp add: fls_deriv_shift)
  4.3526 +
  4.3527 +lemma fls_deriv_lr_inverse:
  4.3528 +  assumes "x * f $$ fls_subdegree f = 1" "f $$ fls_subdegree f * y = 1"
  4.3529 +  \<comment> \<open>These assumptions imply x equals y, but no need to assume that.\<close>
  4.3530 +  shows   "fls_deriv (fls_left_inverse f x) =
  4.3531 +            - fls_left_inverse f x * fls_deriv f * fls_left_inverse f x"
  4.3532 +  and     "fls_deriv (fls_right_inverse f y) =
  4.3533 +            - fls_right_inverse f y * fls_deriv f * fls_right_inverse f y"
  4.3534 +proof-
  4.3535 +
  4.3536 +  define L where "L \<equiv> fls_left_inverse f x"
  4.3537 +  hence "fls_deriv (L * f) = 0" using fls_left_inverse[OF assms(1)] by simp
  4.3538 +  with assms show "fls_deriv L = - L * fls_deriv f * L"
  4.3539 +    using fls_right_inverse'[OF assms]
  4.3540 +    by    (simp add: minus_unique mult.assoc L_def)
  4.3541 +
  4.3542 +  define R where "R \<equiv> fls_right_inverse f y"
  4.3543 +  hence "fls_deriv (f * R) = 0" using fls_right_inverse[OF assms(2)] by simp
  4.3544 +  hence 1: "f * fls_deriv R + fls_deriv f * R = 0" by simp
  4.3545 +  have "R * f * fls_deriv R = - R * fls_deriv f * R"
  4.3546 +    using iffD2[OF eq_neg_iff_add_eq_0, OF 1] by (simp add: mult.assoc)
  4.3547 +  thus "fls_deriv R = - R * fls_deriv f * R"
  4.3548 +    using fls_left_inverse'[OF assms] by (simp add: R_def)
  4.3549 +
  4.3550 +qed
  4.3551 +
  4.3552 +lemma fls_deriv_lr_inverse_comm:
  4.3553 +  fixes   x y :: "'a::comm_ring_1"
  4.3554 +  assumes "x * f $$ fls_subdegree f = 1"
  4.3555 +  shows   "fls_deriv (fls_left_inverse f x) = - fls_deriv f * (fls_left_inverse f x)\<^sup>2"
  4.3556 +  and     "fls_deriv (fls_right_inverse f x) = - fls_deriv f * (fls_right_inverse f x)\<^sup>2"
  4.3557 +  using   assms fls_deriv_lr_inverse[of x f x]
  4.3558 +  by      (simp_all add: mult.commute power2_eq_square)
  4.3559 +
  4.3560 +lemma fls_inverse_deriv_divring:
  4.3561 +  fixes a :: "'a::division_ring fls"
  4.3562 +  shows "fls_deriv (inverse a) = - inverse a * fls_deriv a * inverse a"
  4.3563 +proof (cases "a=0")
  4.3564 +  case False thus ?thesis
  4.3565 +    using fls_deriv_lr_inverse(2)[of
  4.3566 +            "inverse (a $$ fls_subdegree a)" a "inverse (a $$ fls_subdegree a)"
  4.3567 +          ]
  4.3568 +    by    (auto simp add: fls_inverse_def')
  4.3569 +qed simp
  4.3570 +
  4.3571 +lemma fls_inverse_deriv:
  4.3572 +  fixes a :: "'a::field fls"
  4.3573 +  shows "fls_deriv (inverse a) = - fls_deriv a * (inverse a)\<^sup>2"
  4.3574 +  by    (simp add: fls_inverse_deriv_divring power2_eq_square)
  4.3575 +
  4.3576 +lemma fls_inverse_deriv':
  4.3577 +  fixes a :: "'a::field fls"
  4.3578 +  shows "fls_deriv (inverse a) = - fls_deriv a / a\<^sup>2"
  4.3579 +  using fls_inverse_deriv[of a]
  4.3580 +  by    (simp add: field_simps)
  4.3581 +
  4.3582 +
  4.3583 +subsubsection \<open>Equality of derivatives\<close>
  4.3584 +
  4.3585 +lemma fls_deriv_eq_0_iff:
  4.3586 +  "fls_deriv f = 0 \<longleftrightarrow> f = fls_const (f$$0 :: 'a::{ring_1_no_zero_divisors,ring_char_0})"
  4.3587 +proof
  4.3588 +  assume f: "fls_deriv f = 0"
  4.3589 +  show "f = fls_const (f$$0)"
  4.3590 +  proof (intro fls_eqI)
  4.3591 +    fix n
  4.3592 +    from f have "of_int n * f$$ n = 0" using fls_deriv_nth[of f "n-1"] by simp
  4.3593 +    thus "f$$n = fls_const (f$$0) $$ n" by (cases "n=0") auto
  4.3594 +  qed
  4.3595 +next
  4.3596 +  show "f = fls_const (f$$0) \<Longrightarrow> fls_deriv f = 0" using fls_deriv_const[of "f$$0"] by simp
  4.3597 +qed
  4.3598 +
  4.3599 +lemma fls_deriv_eq_iff:
  4.3600 +  fixes f g :: "'a::{ring_1_no_zero_divisors,ring_char_0} fls"
  4.3601 +  shows "fls_deriv f = fls_deriv g \<longleftrightarrow> (f = fls_const(f$$0 - g$$0) + g)"
  4.3602 +proof -
  4.3603 +  have "fls_deriv f = fls_deriv g \<longleftrightarrow> fls_deriv (f - g) = 0"
  4.3604 +    by simp
  4.3605 +  also have "\<dots> \<longleftrightarrow> f - g = fls_const ((f - g) $$ 0)"
  4.3606 +    unfolding fls_deriv_eq_0_iff ..
  4.3607 +  finally show ?thesis
  4.3608 +    by (simp add: field_simps)
  4.3609 +qed
  4.3610 +
  4.3611 +lemma fls_deriv_eq_iff_ex:
  4.3612 +  fixes f g :: "'a::{ring_1_no_zero_divisors,ring_char_0} fls"
  4.3613 +  shows "(fls_deriv f = fls_deriv g) \<longleftrightarrow> (\<exists>c. f = fls_const c + g)"
  4.3614 +  by    (auto simp: fls_deriv_eq_iff)
  4.3615 +
  4.3616 +
  4.3617 +subsubsection \<open>Residues\<close>
  4.3618 +
  4.3619 +definition fls_residue_def[simp]: "fls_residue f \<equiv> f $$ -1"
  4.3620 +
  4.3621 +lemma fls_residue_deriv: "fls_residue (fls_deriv f) = 0"
  4.3622 +  by simp
  4.3623 +
  4.3624 +lemma fls_residue_add: "fls_residue (f+g) = fls_residue f + fls_residue g"
  4.3625 +  by simp
  4.3626 +
  4.3627 +lemma fls_residue_times_deriv:
  4.3628 +  "fls_residue (fls_deriv f * g) = - fls_residue (f * fls_deriv g)"
  4.3629 +  using fls_residue_deriv[of "f*g"] minus_unique[of "fls_residue (f * fls_deriv g)"]
  4.3630 +  by    simp
  4.3631 +
  4.3632 +lemma fls_residue_power_series: "fls_subdegree f \<ge> 0 \<Longrightarrow> fls_residue f = 0"
  4.3633 +  by simp
  4.3634 +
  4.3635 +lemma fls_residue_fls_X_intpow:
  4.3636 +  "fls_residue (fls_X_intpow i) = (if i=-1 then 1 else 0)"
  4.3637 +  by simp
  4.3638 +
  4.3639 +lemma fls_residue_shift_nth:
  4.3640 +  fixes f :: "'a::semiring_1 fls"
  4.3641 +  shows "f$$n = fls_residue (fls_X_intpow (-n-1) * f)"
  4.3642 +  by    (simp add: fls_shifted_times_transfer)
  4.3643 +
  4.3644 +lemma fls_residue_fls_const_times:
  4.3645 +  fixes f :: "'a::{comm_monoid_add, mult_zero} fls"
  4.3646 +  shows "fls_residue (fls_const c * f) = c * fls_residue f"
  4.3647 +  and   "fls_residue (f * fls_const c) = fls_residue f * c"
  4.3648 +  by    simp_all
  4.3649 +
  4.3650 +lemma fls_residue_of_int_times:
  4.3651 +  fixes f :: "'a::ring_1 fls"
  4.3652 +  shows "fls_residue (of_int i * f) = of_int i * fls_residue f"
  4.3653 +  and   "fls_residue (f * of_int i) = fls_residue f * of_int i"
  4.3654 +  by    (simp_all add: fls_residue_fls_const_times fls_of_int)
  4.3655 +
  4.3656 +lemma fls_residue_deriv_times_lr_inverse_eq_subdegree:
  4.3657 +  fixes   f g :: "'a::ring_1 fls"
  4.3658 +  assumes "y * (f $$ fls_subdegree f) = 1" "(f $$ fls_subdegree f) * y = 1"
  4.3659 +  shows   "fls_residue (fls_deriv f * fls_right_inverse f y)  = of_int (fls_subdegree f)"
  4.3660 +  and     "fls_residue (fls_deriv f * fls_left_inverse f y)   = of_int (fls_subdegree f)"
  4.3661 +  and     "fls_residue (fls_left_inverse f y * fls_deriv f)   = of_int (fls_subdegree f)"
  4.3662 +  and     "fls_residue (fls_right_inverse f y * fls_deriv f)  = of_int (fls_subdegree f)"
  4.3663 +proof-
  4.3664 +  define df :: int where "df \<equiv> fls_subdegree f"
  4.3665 +  define B X :: "'a fls"
  4.3666 +    where "B \<equiv> fls_base_factor f"
  4.3667 +    and   "X \<equiv> (fls_X_intpow df :: 'a fls)"
  4.3668 +  define D L R :: "'a fls"
  4.3669 +    where "D \<equiv> fls_deriv B"
  4.3670 +    and   "L \<equiv> fls_left_inverse B y"
  4.3671 +    and   "R \<equiv> fls_right_inverse B y"
  4.3672 +  have intpow_diff: "fls_X_intpow (df - 1) = X * fls_X_inv"
  4.3673 +    using fls_X_intpow_diff_conv_times[of df 1] by (simp add: X_def fls_X_inv_conv_shift_1)
  4.3674 + 
  4.3675 +
  4.3676 +  show "fls_residue (fls_deriv f * fls_right_inverse f y) = of_int df"
  4.3677 +  proof-
  4.3678 +    have subdegree_DR: "fls_subdegree (D * R) \<ge> 0"
  4.3679 +      using fls_base_factor_subdegree[of f] fls_base_factor_subdegree[of "fls_right_inverse f y"]
  4.3680 +            assms(1) fls_right_inverse_base_factor[of y f] fls_mult_subdegree_ge_0[of D R]
  4.3681 +      by    (force simp: fls_deriv_subdegree0 D_def R_def B_def)
  4.3682 +    have decomp: "f = X * B"
  4.3683 +      unfolding X_def B_def df_def by (rule fls_base_factor_X_power_decompose(2)[of f])
  4.3684 +    hence "fls_deriv f = X * D + of_int df * X * fls_X_inv * B"
  4.3685 +      using intpow_diff fls_deriv_mult[of X B]
  4.3686 +      by    (simp add: fls_deriv_X_intpow X_def B_def D_def mult.assoc)
  4.3687 +    moreover from assms have "fls_right_inverse (X * B) y = R * fls_right_inverse X 1"
  4.3688 +      using fls_base_factor_base[of f] fls_lr_inverse_mult_ring1(2)[of 1 X]
  4.3689 +      by    (simp add: X_def B_def R_def)
  4.3690 +    ultimately have
  4.3691 +      "fls_deriv f * fls_right_inverse f y =
  4.3692 +        (D + of_int df * fls_X_inv * B) * R * (X * fls_right_inverse X 1)"
  4.3693 +      by (simp add: decomp algebra_simps X_def fls_X_intpow_times_comm)
  4.3694 +    also have "\<dots> = D * R + of_int df * fls_X_inv"
  4.3695 +      using fls_right_inverse[of X 1]
  4.3696 +            assms fls_base_factor_base[of f] fls_right_inverse[of B y]
  4.3697 +      by    (simp add: X_def distrib_right mult.assoc B_def R_def)
  4.3698 +    finally show ?thesis using subdegree_DR by simp
  4.3699 +  qed
  4.3700 +
  4.3701 +  with assms show "fls_residue (fls_deriv f * fls_left_inverse f y) = of_int df"
  4.3702 +    using fls_left_inverse_eq_fls_right_inverse[of y f] by simp
  4.3703 +
  4.3704 +  show "fls_residue (fls_left_inverse f y * fls_deriv f) = of_int df"
  4.3705 +  proof-
  4.3706 +    have subdegree_LD: "fls_subdegree (L * D) \<ge> 0"
  4.3707 +      using fls_base_factor_subdegree[of f] fls_base_factor_subdegree[of "fls_left_inverse f y"]
  4.3708 +            assms(1) fls_left_inverse_base_factor[of y f] fls_mult_subdegree_ge_0[of L D]
  4.3709 +      by    (force simp: fls_deriv_subdegree0 D_def L_def B_def)
  4.3710 +    have decomp: "f = B * X"
  4.3711 +      unfolding X_def B_def df_def by (rule fls_base_factor_X_power_decompose(1)[of f])
  4.3712 +    hence "fls_deriv f = D * X + B * of_int df * X * fls_X_inv"
  4.3713 +      using intpow_diff fls_deriv_mult[of B X]
  4.3714 +      by    (simp add: fls_deriv_X_intpow X_def D_def B_def mult.assoc)
  4.3715 +    moreover from assms have "fls_left_inverse (B * X) y = fls_left_inverse X 1 * L"
  4.3716 +      using fls_base_factor_base[of f] fls_lr_inverse_mult_ring1(1)[of _ _ 1 X]
  4.3717 +      by    (simp add: X_def B_def L_def)
  4.3718 +    ultimately have
  4.3719 +      "fls_left_inverse f y * fls_deriv f =
  4.3720 +        fls_left_inverse X 1 * X * L * (D + B * (of_int df * fls_X_inv))"
  4.3721 +      by (simp add: decomp algebra_simps X_def fls_X_intpow_times_comm)
  4.3722 +    also have "\<dots> = L * D + of_int df * fls_X_inv"
  4.3723 +      using assms fls_left_inverse[of 1 X] fls_base_factor_base[of f] fls_left_inverse[of y B]
  4.3724 +       by   (simp add: X_def distrib_left mult.assoc[symmetric] L_def B_def)
  4.3725 +    finally show ?thesis using subdegree_LD by simp
  4.3726 +  qed
  4.3727 +
  4.3728 +  with assms show "fls_residue (fls_right_inverse f y * fls_deriv f) = of_int df"
  4.3729 +    using fls_left_inverse_eq_fls_right_inverse[of y f] by simp
  4.3730 +
  4.3731 +qed
  4.3732 +
  4.3733 +lemma fls_residue_deriv_times_inverse_eq_subdegree:
  4.3734 +  fixes f g :: "'a::division_ring fls"
  4.3735 +  shows "fls_residue (fls_deriv f * inverse f) = of_int (fls_subdegree f)"
  4.3736 +  and   "fls_residue (inverse f * fls_deriv f) = of_int (fls_subdegree f)"
  4.3737 +proof-
  4.3738 +  show "fls_residue (fls_deriv f * inverse f) = of_int (fls_subdegree f)"
  4.3739 +    using fls_residue_deriv_times_lr_inverse_eq_subdegree(1)[of _ f]
  4.3740 +    by    (cases "f=0") (auto simp: fls_inverse_def')
  4.3741 +  show "fls_residue (inverse f * fls_deriv f) = of_int (fls_subdegree f)"
  4.3742 +    using fls_residue_deriv_times_lr_inverse_eq_subdegree(4)[of _ f]
  4.3743 +    by    (cases "f=0") (auto simp: fls_inverse_def')
  4.3744 +qed
  4.3745 +
  4.3746 +
  4.3747 +subsubsection \<open>Integral definition and basic properties\<close>
  4.3748 +
  4.3749 +\<comment> \<open>To incorporate a constant of integration, just add an fps_const.\<close>
  4.3750 +definition fls_integral :: "'a::{ring_1,inverse} fls \<Rightarrow> 'a fls"
  4.3751 +  where "fls_integral a = Abs_fls (\<lambda>n. if n=0 then 0 else inverse (of_int n) * a$$(n - 1))"
  4.3752 +
  4.3753 +lemma fls_integral_nth [simp]:
  4.3754 +  "fls_integral a $$ n = (if n=0 then 0 else inverse (of_int n) * a$$(n-1))"
  4.3755 +proof-
  4.3756 +  define F where "F \<equiv> (\<lambda>n. if n=0 then 0 else inverse (of_int n) * a$$(n - 1))"
  4.3757 +  obtain N where "\<forall>n<N. a$$n = 0" by (elim fls_nth_vanishes_belowE)
  4.3758 +  hence "\<forall>n<N. F n = 0" by (auto simp add: F_def)
  4.3759 +  thus ?thesis using nth_Abs_fls_lower_bound[of N F] unfolding fls_integral_def F_def by simp
  4.3760 +qed
  4.3761 +
  4.3762 +lemma fls_integral_conv_fps_zeroth_integral:
  4.3763 +  assumes "fls_subdegree a \<ge> 0"
  4.3764 +  shows   "fls_integral a = fps_to_fls (fps_integral0 (fls_regpart a))"
  4.3765 +proof (rule fls_eqI)
  4.3766 +  fix n
  4.3767 +  show "fls_integral a $$ n = fps_to_fls (fps_integral0 (fls_regpart a)) $$ n"
  4.3768 +  proof (cases "n>0")
  4.3769 +    case False with assms show ?thesis by simp
  4.3770 +  next
  4.3771 +    case True
  4.3772 +    hence "int ((nat n) - 1) = n - 1" by simp
  4.3773 +    with True show ?thesis by (simp add: fps_integral_def)
  4.3774 +  qed
  4.3775 +qed
  4.3776 +
  4.3777 +lemma fls_integral_zero [simp]: "fls_integral 0 = 0"
  4.3778 +  by (intro fls_eqI) simp
  4.3779 +
  4.3780 +lemma fls_integral_const':
  4.3781 +  fixes   x :: "'a::{ring_1,inverse}"
  4.3782 +  assumes "inverse (1::'a) = 1"
  4.3783 +  shows   "fls_integral (fls_const x) = fls_const x * fls_X"
  4.3784 +  by      (intro fls_eqI) (simp add: assms)
  4.3785 +
  4.3786 +lemma fls_integral_const:
  4.3787 +  fixes x :: "'a::division_ring"
  4.3788 +  shows "fls_integral (fls_const x) = fls_const x * fls_X"
  4.3789 +  by    (rule fls_integral_const'[OF inverse_1])
  4.3790 +
  4.3791 +lemma fls_integral_of_nat':
  4.3792 +  assumes "inverse (1::'a::{ring_1,inverse}) = 1"
  4.3793 +  shows   "fls_integral (of_nat n :: 'a fls) = of_nat n * fls_X"
  4.3794 +  by      (simp add: assms fls_integral_const' fls_of_nat)
  4.3795 +
  4.3796 +lemma fls_integral_of_nat:
  4.3797 +  "fls_integral (of_nat n :: 'a::division_ring fls) = of_nat n * fls_X"
  4.3798 +  by (rule fls_integral_of_nat'[OF inverse_1])
  4.3799 +
  4.3800 +lemma fls_integral_of_int':
  4.3801 +  assumes "inverse (1::'a::{ring_1,inverse}) = 1"
  4.3802 +  shows   "fls_integral (of_int i :: 'a fls) = of_int i * fls_X"
  4.3803 +  by      (simp add: assms fls_integral_const' fls_of_int)
  4.3804 +
  4.3805 +lemma fls_integral_of_int:
  4.3806 +  "fls_integral (of_int i :: 'a::division_ring fls) = of_int i * fls_X"
  4.3807 +  by (rule fls_integral_of_int'[OF inverse_1])
  4.3808 +
  4.3809 +lemma fls_integral_one':
  4.3810 +  assumes "inverse (1::'a::{ring_1,inverse}) = 1"
  4.3811 +  shows   "fls_integral (1::'a fls) = fls_X"
  4.3812 +  using   fls_integral_const'[of 1]
  4.3813 +  by      (force simp: assms)
  4.3814 +
  4.3815 +lemma fls_integral_one: "fls_integral (1::'a::division_ring fls) = fls_X"
  4.3816 +  by (rule fls_integral_one'[OF inverse_1])
  4.3817 +
  4.3818 +lemma fls_subdegree_integral_ge:
  4.3819 +  "fls_integral f \<noteq> 0 \<Longrightarrow> fls_subdegree (fls_integral f) \<ge> fls_subdegree f + 1"
  4.3820 +  by (intro fls_subdegree_geI) simp_all
  4.3821 +
  4.3822 +lemma fls_subdegree_integral:
  4.3823 +  fixes   f :: "'a::{division_ring,ring_char_0} fls"
  4.3824 +  assumes "f \<noteq> 0" "fls_subdegree f \<noteq> -1"
  4.3825 +  shows   "fls_subdegree (fls_integral f) = fls_subdegree f + 1"
  4.3826 +  using   assms of_int_0_eq_iff[of "fls_subdegree f + 1"] fls_subdegree_integral_ge
  4.3827 +  by      (intro fls_subdegree_eqI) simp_all
  4.3828 +
  4.3829 +lemma fls_integral_X [simp]:
  4.3830 +  "fls_integral (fls_X::'a::{ring_1,inverse} fls) =
  4.3831 +    fls_const (inverse (of_int 2)) * fls_X\<^sup>2"
  4.3832 +proof (intro fls_eqI)
  4.3833 +  fix n
  4.3834 +  show "fls_integral (fls_X::'a fls) $$ n = (fls_const (inverse (of_int 2)) * fls_X\<^sup>2) $$ n"
  4.3835 +    using arg_cong[OF fls_X_power_nth, of "\<lambda>x. inverse (of_int 2) * x", of 2 n, symmetric]
  4.3836 +    by    (auto simp add: )
  4.3837 +qed
  4.3838 +
  4.3839 +lemma fls_integral_X_power:
  4.3840 +  "fls_integral (fls_X ^ n ::'a :: {ring_1,inverse} fls) =
  4.3841 +    fls_const (inverse (of_nat (Suc n))) * fls_X ^ Suc n"
  4.3842 +proof (intro fls_eqI)
  4.3843 +  fix k
  4.3844 +  have "(fls_X :: 'a fls) ^ Suc n $$ k = (if k=Suc n then 1 else 0)"
  4.3845 +    by (rule fls_X_power_nth)
  4.3846 +  thus 
  4.3847 +    "fls_integral ((fls_X::'a fls) ^ n) $$ k =
  4.3848 +      (fls_const (inverse (of_nat (Suc n))) * (fls_X::'a fls) ^ Suc n) $$ k"
  4.3849 +    by simp
  4.3850 +qed
  4.3851 +
  4.3852 +lemma fls_integral_X_power_char0:
  4.3853 +  "fls_integral (fls_X ^ n :: 'a :: {ring_char_0,inverse} fls) =
  4.3854 +    inverse (of_nat (Suc n)) * fls_X ^ Suc n"
  4.3855 +proof -
  4.3856 +  have "(of_nat (Suc n) :: 'a) \<noteq> 0" by (rule of_nat_neq_0)
  4.3857 +  hence "fls_const (inverse (of_nat (Suc n) :: 'a)) = inverse (fls_const (of_nat (Suc n)))"
  4.3858 +    by (simp add: fls_inverse_const)
  4.3859 +  moreover have
  4.3860 +    "fls_integral ((fls_X::'a fls) ^ n) = fls_const (inverse (of_nat (Suc n))) * fls_X ^ Suc n"
  4.3861 +    by (rule fls_integral_X_power)
  4.3862 +  ultimately show ?thesis by (simp add: fls_of_nat)
  4.3863 +qed
  4.3864 +
  4.3865 +lemma fls_integral_X_inv [simp]: "fls_integral (fls_X_inv::'a::{ring_1,inverse} fls) = 0"
  4.3866 +  by (intro fls_eqI) simp
  4.3867 +
  4.3868 +lemma fls_integral_X_inv_power:
  4.3869 +  assumes "n \<ge> 2"
  4.3870 +  shows
  4.3871 +    "fls_integral (fls_X_inv ^ n :: 'a :: {ring_1,inverse} fls) =
  4.3872 +      fls_const (inverse (of_int (1 - int n))) * fls_X_inv ^ (n-1)"
  4.3873 +proof (rule fls_eqI)
  4.3874 +  fix k show
  4.3875 +    "fls_integral (fls_X_inv ^ n :: 'a fls) $$ k=
  4.3876 +      (fls_const (inverse (of_int (1 - int n))) * fls_X_inv ^ (n-1)) $$ k"
  4.3877 +  proof (cases "k=0")
  4.3878 +    case True with assms show ?thesis by simp
  4.3879 +  next
  4.3880 +    case False
  4.3881 +    from assms have "int (n-1) = int n - 1" by simp
  4.3882 +    hence
  4.3883 +      "(fls_const (inverse (of_int (1 - int n))) * (fls_X_inv:: 'a fls) ^ (n-1)) $$ k =
  4.3884 +      (if k = 1 - int n then inverse (of_int k) else 0)"
  4.3885 +      by (simp add: fls_X_inv_power_times_conv_shift(2))
  4.3886 +    with False show ?thesis by (simp add: algebra_simps)
  4.3887 +  qed
  4.3888 +qed
  4.3889 +
  4.3890 +lemma fls_integral_X_inv_power_char0:
  4.3891 +  assumes "n \<ge> 2"
  4.3892 +  shows
  4.3893 +    "fls_integral (fls_X_inv ^ n :: 'a :: {ring_char_0,inverse} fls) =
  4.3894 +      inverse (of_int (1 - int n)) * fls_X_inv ^ (n-1)"
  4.3895 +proof-
  4.3896 +  from assms have "(of_int (1 - int n) :: 'a) \<noteq> 0" by simp
  4.3897 +  hence
  4.3898 +    "fls_const (inverse (of_int (1 - int n) :: 'a)) = inverse (fls_const (of_int (1 - int n)))"
  4.3899 +    by (simp add: fls_inverse_const)
  4.3900 +  moreover have
  4.3901 +    "fls_integral (fls_X_inv ^ n :: 'a fls) =
  4.3902 +      fls_const (inverse (of_int (1 - int n))) * fls_X_inv ^ (n-1)"
  4.3903 +    using assms by (rule fls_integral_X_inv_power)
  4.3904 +  ultimately show ?thesis by (simp add: fls_of_int)
  4.3905 +qed
  4.3906 +
  4.3907 +lemma fls_integral_X_inv_power':
  4.3908 +  assumes "n \<ge> 1"
  4.3909 +  shows
  4.3910 +    "fls_integral (fls_X_inv ^ n :: 'a :: division_ring fls) =
  4.3911 +      - fls_const (inverse (of_nat (n-1))) * fls_X_inv ^ (n-1)"
  4.3912 +proof (cases "n = 1")
  4.3913 +  case False
  4.3914 +  with assms have n: "n \<ge> 2" by simp
  4.3915 +  hence
  4.3916 +    "fls_integral (fls_X_inv ^ n :: 'a fls) =
  4.3917 +      fls_const (inverse (- of_nat (nat (int n - 1)))) * fls_X_inv ^ (n-1)"
  4.3918 +    by (simp add: fls_integral_X_inv_power)
  4.3919 +  moreover from n have "nat (int n - 1) = n - 1" by simp
  4.3920 +  ultimately show ?thesis
  4.3921 +    using inverse_minus_eq[of "of_nat (n-1) :: 'a"] by simp
  4.3922 +qed simp
  4.3923 +
  4.3924 +lemma fls_integral_X_inv_power_char0':
  4.3925 +  assumes "n \<ge> 1"
  4.3926 +  shows
  4.3927 +    "fls_integral (fls_X_inv ^ n :: 'a :: {division_ring,ring_char_0} fls) =
  4.3928 +      - inverse (of_nat (n-1)) * fls_X_inv ^ (n-1)"
  4.3929 +proof (cases "n=1")
  4.3930 +  case False with assms show ?thesis
  4.3931 +    by (simp add: fls_integral_X_inv_power' fls_inverse_const fls_of_nat)
  4.3932 +qed simp    
  4.3933 +
  4.3934 +lemma fls_integral_delta:
  4.3935 +  assumes "m \<noteq> -1"
  4.3936 +  shows
  4.3937 +    "fls_integral (Abs_fls (\<lambda>n. if n=m then c else 0)) =
  4.3938 +      Abs_fls (\<lambda>n. if n=m+1 then inverse (of_int (m+1)) * c else 0)"
  4.3939 +  using   assms
  4.3940 +  by      (intro fls_eqI) auto
  4.3941 +
  4.3942 +lemma fls_regpart_integral:
  4.3943 +  "fls_regpart (fls_integral f) = fps_integral0 (fls_regpart f)"
  4.3944 +proof (rule fps_ext)
  4.3945 +  fix n
  4.3946 +  show "fls_regpart (fls_integral f) $ n = fps_integral0 (fls_regpart f) $ n"
  4.3947 +    by (cases n) (simp_all add: fps_integral_def)
  4.3948 +qed
  4.3949 +
  4.3950 +lemma fls_integral_fps_to_fls:
  4.3951 +  "fls_integral (fps_to_fls f) = fps_to_fls (fps_integral0 f)"
  4.3952 +proof (intro fls_eqI)
  4.3953 +  fix n :: int
  4.3954 +  show "fls_integral (fps_to_fls f) $$ n = fps_to_fls (fps_integral0 f) $$ n"
  4.3955 +  proof (cases "n<1")
  4.3956 +    case True thus ?thesis by simp
  4.3957 +  next
  4.3958 +    case False
  4.3959 +    hence "nat (n-1) = nat n - 1" by simp
  4.3960 +    with False show ?thesis by (cases "nat n") auto
  4.3961 +  qed
  4.3962 +qed
  4.3963 +
  4.3964 +
  4.3965 +subsubsection \<open>Algebra rules of the integral\<close>
  4.3966 +
  4.3967 +lemma fls_integral_add [simp]: "fls_integral (f+g) = fls_integral f + fls_integral g"
  4.3968 +  by (intro fls_eqI) (simp add: algebra_simps)
  4.3969 +
  4.3970 +lemma fls_integral_sub [simp]: "fls_integral (f-g) = fls_integral f - fls_integral g"
  4.3971 +  by (intro fls_eqI) (simp add: algebra_simps)
  4.3972 +
  4.3973 +lemma fls_integral_neg [simp]: "fls_integral (-f) = - fls_integral f"
  4.3974 +  using fls_integral_sub[of 0 f] by simp
  4.3975 +
  4.3976 +lemma fls_integral_mult_const_left:
  4.3977 +  "fls_integral (fls_const c * f) = fls_const c * fls_integral (f :: 'a::division_ring fls)"
  4.3978 +  by (intro fls_eqI) (simp add: mult.assoc mult_inverse_of_int_commute)
  4.3979 +
  4.3980 +lemma fls_integral_mult_const_left_comm:
  4.3981 +  fixes f :: "'a::{comm_ring_1,inverse} fls"
  4.3982 +  shows "fls_integral (fls_const c * f) = fls_const c * fls_integral f"
  4.3983 +  by (intro fls_eqI) (simp add: mult.assoc mult.commute)
  4.3984 +
  4.3985 +lemma fls_integral_linear:
  4.3986 +  fixes f g :: "'a::division_ring fls"
  4.3987 +  shows
  4.3988 +    "fls_integral (fls_const a * f + fls_const b * g) =
  4.3989 +      fls_const a * fls_integral f + fls_const b * fls_integral g"
  4.3990 +  by    (simp add: fls_integral_mult_const_left)
  4.3991 +
  4.3992 +lemma fls_integral_linear_comm:
  4.3993 +  fixes f g :: "'a::{comm_ring_1,inverse} fls"
  4.3994 +  shows
  4.3995 +    "fls_integral (fls_const a * f + fls_const b * g) =
  4.3996 +      fls_const a * fls_integral f + fls_const b * fls_integral g"
  4.3997 +  by    (simp add: fls_integral_mult_const_left_comm)
  4.3998 +
  4.3999 +lemma fls_integral_mult_const_right:
  4.4000 +  "fls_integral (f * fls_const c) = fls_integral f * fls_const c"
  4.4001 +  by (intro fls_eqI) (simp add: mult.assoc)
  4.4002 +
  4.4003 +lemma fls_integral_linear2:
  4.4004 +    "fls_integral (f * fls_const a + g * fls_const b) =
  4.4005 +      fls_integral f * fls_const a + fls_integral g * fls_const b"
  4.4006 +  by    (simp add: fls_integral_mult_const_right)
  4.4007 +
  4.4008 +lemma fls_integral_sum:
  4.4009 +  "fls_integral (sum f S) = sum (\<lambda>i. fls_integral (f i)) S"
  4.4010 +proof (cases "finite S")
  4.4011 +  case True show ?thesis
  4.4012 +    by (induct rule: finite_induct [OF True]) simp_all
  4.4013 +qed simp
  4.4014 +
  4.4015 +
  4.4016 +subsubsection \<open>Derivatives of integrals and vice versa\<close>
  4.4017 +
  4.4018 +lemma fls_integral_fls_deriv:
  4.4019 +  fixes a :: "'a::{division_ring,ring_char_0} fls"
  4.4020 +  shows "fls_integral (fls_deriv a) + fls_const (a$$0) = a"
  4.4021 +  by    (intro fls_eqI) (simp add: mult.assoc[symmetric])
  4.4022 +
  4.4023 +lemma fls_deriv_fls_integral:
  4.4024 +  fixes   a :: "'a::{division_ring,ring_char_0} fls"
  4.4025 +  assumes "fls_residue a = 0"
  4.4026 +  shows   "fls_deriv (fls_integral a) = a"
  4.4027 +proof (intro fls_eqI)
  4.4028 +  fix n :: int
  4.4029 +  show "fls_deriv (fls_integral a) $$ n = a $$ n"
  4.4030 +  proof (cases "n=-1")
  4.4031 +    case True with assms show ?thesis by simp
  4.4032 +  next
  4.4033 +    case False
  4.4034 +    hence "(of_int (n+1) :: 'a) \<noteq> 0" using of_int_eq_0_iff[of "n+1"] by simp
  4.4035 +    hence "(of_int (n+1) :: 'a) * inverse (of_int (n+1) :: 'a) = (1::'a)"
  4.4036 +      using of_int_eq_0_iff[of "n+1"] by simp
  4.4037 +    moreover have
  4.4038 +      "fls_deriv (fls_integral a) $$ n =
  4.4039 +        (if n=-1 then 0 else of_int (n+1) * inverse (of_int (n+1)) * a$$n)"
  4.4040 +      by (simp add: mult.assoc)
  4.4041 +    ultimately show ?thesis
  4.4042 +      by (simp add: False)
  4.4043 +  qed
  4.4044 +qed
  4.4045 +
  4.4046 +text \<open>Series with zero residue are precisely the derivatives.\<close>
  4.4047 +
  4.4048 +lemma fls_residue_nonzero_ex_antiderivative:
  4.4049 +  fixes   f :: "'a::{division_ring,ring_char_0} fls"
  4.4050 +  assumes "fls_residue f = 0"
  4.4051 +  shows   "\<exists>F. fls_deriv F = f"
  4.4052 +  using   assms fls_deriv_fls_integral
  4.4053 +  by      auto
  4.4054 +
  4.4055 +lemma fls_ex_antiderivative_residue_nonzero:
  4.4056 +  assumes "\<exists>F. fls_deriv F = f"
  4.4057 +  shows   "fls_residue f = 0"
  4.4058 +  using   assms fls_residue_deriv
  4.4059 +  by      auto
  4.4060 +
  4.4061 +lemma fls_residue_nonzero_ex_anitderivative_iff:
  4.4062 +  fixes f :: "'a::{division_ring,ring_char_0} fls"
  4.4063 +  shows "fls_residue f = 0 \<longleftrightarrow> (\<exists>F. fls_deriv F = f)"
  4.4064 +  using fls_residue_nonzero_ex_antiderivative fls_ex_antiderivative_residue_nonzero
  4.4065 +  by    fast
  4.4066 +
  4.4067 +
  4.4068 +subsection \<open>Topology\<close>
  4.4069 +
  4.4070 +instantiation fls :: (group_add) metric_space
  4.4071 +begin
  4.4072 +
  4.4073 +definition
  4.4074 +  dist_fls_def:
  4.4075 +    "dist (a :: 'a fls) b =
  4.4076 +      (if a = b
  4.4077 +        then 0
  4.4078 +        else if fls_subdegree (a-b) \<ge> 0
  4.4079 +          then inverse (2 ^ nat (fls_subdegree (a-b)))
  4.4080 +          else 2 ^ nat (-fls_subdegree (a-b))
  4.4081 +      )"
  4.4082 +
  4.4083 +lemma dist_fls_ge0: "dist (a :: 'a fls) b \<ge> 0"
  4.4084 +  by (simp add: dist_fls_def)
  4.4085 +
  4.4086 +definition uniformity_fls_def [code del]:
  4.4087 +  "(uniformity :: ('a fls \<times> 'a fls) filter) = (INF e:{0 <..}. principal {(x, y). dist x y < e})"
  4.4088 +
  4.4089 +definition open_fls_def' [code del]:
  4.4090 +  "open (U :: 'a fls set) \<longleftrightarrow> (\<forall>x\<in>U. eventually (\<lambda>(x', y). x' = x \<longrightarrow> y \<in> U) uniformity)"
  4.4091 +
  4.4092 +lemma dist_fls_sym: "dist (a :: 'a fls) b = dist b a"
  4.4093 +  by  (cases "a\<noteq>b", cases "fls_subdegree (a-b) \<ge> 0")
  4.4094 +      (simp_all add: fls_subdegree_minus_sym dist_fls_def)
  4.4095 +
  4.4096 +context
  4.4097 +begin
  4.4098 +
  4.4099 +private lemma instance_helper:
  4.4100 +  fixes   a b c :: "'a fls"
  4.4101 +  assumes neq: "a\<noteq>b" "a\<noteq>c"
  4.4102 +  and     dist_ineq: "dist a b > dist a c"
  4.4103 +  shows   "fls_subdegree (a - b) < fls_subdegree (a - c)"
  4.4104 +proof (
  4.4105 +  cases "fls_subdegree (a-b) \<ge> 0" "fls_subdegree (a-c) \<ge> 0"
  4.4106 +  rule: case_split[case_product case_split]
  4.4107 +)
  4.4108 +  case True_True with neq dist_ineq show ?thesis by (simp add: dist_fls_def)
  4.4109 +next
  4.4110 +  case False_True with dist_ineq show ?thesis by (simp add: dist_fls_def)
  4.4111 +next
  4.4112 +  case False_False with neq dist_ineq show ?thesis by (simp add: dist_fls_def)
  4.4113 +next
  4.4114 +  case True_False
  4.4115 +  with neq
  4.4116 +    have "(1::real) > 2 ^ (nat (fls_subdegree (a-b)) + nat (-fls_subdegree (a-c)))"
  4.4117 +    and  "nat (fls_subdegree (a-b)) + nat (-fls_subdegree (a-c)) =
  4.4118 +            nat (fls_subdegree (a-b) - fls_subdegree (a-c))"
  4.4119 +    using dist_ineq
  4.4120 +    by    (simp_all add: dist_fls_def field_simps power_add)
  4.4121 +  hence "\<not> (1::real) < 2 ^ (nat (fls_subdegree (a-b) - fls_subdegree (a-c)))" by simp
  4.4122 +  hence "\<not> (0 < nat (fls_subdegree (a - b) - fls_subdegree (a - c)))" by auto
  4.4123 +  hence "fls_subdegree (a - b) \<le> fls_subdegree (a - c)" by simp
  4.4124 +  with True_False show ?thesis by simp
  4.4125 +qed
  4.4126 +
  4.4127 +instance
  4.4128 +proof
  4.4129 +  show th: "dist a b = 0 \<longleftrightarrow> a = b" for a b :: "'a fls"
  4.4130 +    by (simp add: dist_fls_def split: if_split_asm)
  4.4131 +  then have th'[simp]: "dist a a = 0" for a :: "'a fls" by simp
  4.4132 +
  4.4133 +  fix a b c :: "'a fls"
  4.4134 +  consider "a = b" | "c = a \<or> c = b" | "a \<noteq> b" "a \<noteq> c" "b \<noteq> c" by blast
  4.4135 +  then show "dist a b \<le> dist a c + dist b c"
  4.4136 +  proof cases
  4.4137 +    case 1
  4.4138 +    then show ?thesis by (simp add: dist_fls_def)
  4.4139 +  next
  4.4140 +    case 2
  4.4141 +    then show ?thesis
  4.4142 +      by (cases "c = a") (simp_all add: th dist_fls_sym)
  4.4143 +  next
  4.4144 +    case neq: 3
  4.4145 +    have False if "dist a b > dist a c + dist b c"
  4.4146 +    proof -
  4.4147 +      from neq have "dist a b > 0" "dist b c > 0" "dist a c > 0" by (simp_all add: dist_fls_def)
  4.4148 +      with that have dist_ineq: "dist a b > dist a c" "dist a b > dist b c" by simp_all
  4.4149 +      have "fls_subdegree (a - b) < fls_subdegree (a - c)"
  4.4150 +      and  "fls_subdegree (a - b) < fls_subdegree (b - c)"
  4.4151 +        using instance_helper[of a b c] instance_helper[of b a c] neq dist_ineq
  4.4152 +        by    (simp_all add: dist_fls_sym fls_subdegree_minus_sym)
  4.4153 +      hence "(a - c) $$ fls_subdegree (a - b) = 0" and "(b - c) $$ fls_subdegree (a - b) = 0"
  4.4154 +        by  (simp_all only: fls_eq0_below_subdegree)
  4.4155 +      hence "(a - b) $$ fls_subdegree (a - b) = 0" by simp
  4.4156 +      moreover from neq have "(a - b) $$ fls_subdegree (a - b) \<noteq> 0"
  4.4157 +        by (intro nth_fls_subdegree_nonzero) simp
  4.4158 +      ultimately show False by contradiction
  4.4159 +    qed
  4.4160 +    thus ?thesis by (auto simp: not_le[symmetric])
  4.4161 +  qed
  4.4162 +qed (rule open_fls_def' uniformity_fls_def)+
  4.4163 +
  4.4164 +end
  4.4165 +end
  4.4166 +
  4.4167 +lemma open_fls_def:
  4.4168 +  "open (S :: 'a::group_add fls set) = (\<forall>a \<in> S. \<exists>r. r >0 \<and> {y. dist y a < r} \<subseteq> S)"
  4.4169 +  unfolding open_dist subset_eq by simp
  4.4170 +
  4.4171 +
  4.4172 +subsection \<open>Notation bundle\<close>
  4.4173 +
  4.4174 +no_notation fls_nth (infixl "$$" 75)
  4.4175 +
  4.4176 +bundle fls_notation
  4.4177 +begin
  4.4178 +notation fls_nth (infixl "$$" 75)
  4.4179 +end
  4.4180 +
  4.4181 +end
  4.4182 \ No newline at end of file
     5.1 --- a/src/HOL/Computational_Algebra/Formal_Power_Series.thy	Mon Feb 04 15:39:37 2019 +0100
     5.2 +++ b/src/HOL/Computational_Algebra/Formal_Power_Series.thy	Mon Feb 04 17:19:04 2019 +0100
     5.3 @@ -1,5 +1,7 @@
     5.4  (*  Title:      HOL/Computational_Algebra/Formal_Power_Series.thy
     5.5      Author:     Amine Chaieb, University of Cambridge
     5.6 +    Author:     Jeremy Sylvestre, University of Alberta (Augustana Campus)
     5.7 +    Author:     Manuel Eberl, TU M√ľnchen
     5.8  *)
     5.9  
    5.10  section \<open>A formalization of formal power series\<close>
    5.11 @@ -22,6 +24,8 @@
    5.12  lemma expand_fps_eq: "p = q \<longleftrightarrow> (\<forall>n. p $ n = q $ n)"
    5.13    by (simp add: fps_nth_inject [symmetric] fun_eq_iff)
    5.14  
    5.15 +lemmas fps_eq_iff = expand_fps_eq
    5.16 +
    5.17  lemma fps_ext: "(\<And>n. p $ n = q $ n) \<Longrightarrow> p = q"
    5.18    by (simp add: expand_fps_eq)
    5.19  
    5.20 @@ -40,6 +44,31 @@
    5.21  lemma fps_zero_nth [simp]: "0 $ n = 0"
    5.22    unfolding fps_zero_def by simp
    5.23  
    5.24 +lemma fps_nonzero_nth: "f \<noteq> 0 \<longleftrightarrow> (\<exists> n. f $n \<noteq> 0)"
    5.25 +  by (simp add: expand_fps_eq)
    5.26 +
    5.27 +lemma fps_nonzero_nth_minimal: "f \<noteq> 0 \<longleftrightarrow> (\<exists>n. f $ n \<noteq> 0 \<and> (\<forall>m < n. f $ m = 0))"
    5.28 +  (is "?lhs \<longleftrightarrow> ?rhs")
    5.29 +proof
    5.30 +  let ?n = "LEAST n. f $ n \<noteq> 0"
    5.31 +  show ?rhs if ?lhs
    5.32 +  proof -
    5.33 +    from that have "\<exists>n. f $ n \<noteq> 0"
    5.34 +      by (simp add: fps_nonzero_nth)
    5.35 +    then have "f $ ?n \<noteq> 0"
    5.36 +      by (rule LeastI_ex)
    5.37 +    moreover have "\<forall>m<?n. f $ m = 0"
    5.38 +      by (auto dest: not_less_Least)
    5.39 +    ultimately have "f $ ?n \<noteq> 0 \<and> (\<forall>m<?n. f $ m = 0)" ..
    5.40 +    then show ?thesis ..
    5.41 +  qed
    5.42 +  show ?lhs if ?rhs
    5.43 +    using that by (auto simp add: expand_fps_eq)
    5.44 +qed
    5.45 +
    5.46 +lemma fps_nonzeroI: "f$n \<noteq> 0 \<Longrightarrow> f \<noteq> 0"
    5.47 +  by auto
    5.48 +
    5.49  instantiation fps :: ("{one, zero}") one
    5.50  begin
    5.51    definition fps_one_def: "1 = Abs_fps (\<lambda>n. if n = 0 then 1 else 0)"
    5.52 @@ -76,6 +105,9 @@
    5.53  lemma fps_neg_nth [simp]: "(- f) $ n = - (f $ n)"
    5.54    unfolding fps_uminus_def by simp
    5.55  
    5.56 +lemma fps_neg_0 [simp]: "-(0::'a::group_add fps) = 0"
    5.57 +  by (rule iffD2, rule fps_eq_iff, auto)
    5.58 +
    5.59  instantiation fps :: ("{comm_monoid_add, times}") times
    5.60  begin
    5.61    definition fps_times_def: "(*) = (\<lambda>f g. Abs_fps (\<lambda>n. \<Sum>i=0..n. f $ i * g $ (n - i)))"
    5.62 @@ -88,6 +120,19 @@
    5.63  lemma fps_mult_nth_0 [simp]: "(f * g) $ 0 = f $ 0 * g $ 0"
    5.64    unfolding fps_times_def by simp
    5.65  
    5.66 +lemma fps_mult_nth_1 [simp]: "(f * g) $ 1 = f$0 * g$1 + f$1 * g$0"
    5.67 +  by (simp add: fps_mult_nth)
    5.68 +
    5.69 +lemmas mult_nth_0 = fps_mult_nth_0
    5.70 +lemmas mult_nth_1 = fps_mult_nth_1
    5.71 +
    5.72 +instance fps :: ("{comm_monoid_add, mult_zero}") mult_zero
    5.73 +proof
    5.74 +  fix a :: "'a fps"
    5.75 +  show "0 * a = 0" by (simp add: fps_ext fps_mult_nth)
    5.76 +  show "a * 0 = 0" by (simp add: fps_ext fps_mult_nth)
    5.77 +qed
    5.78 +
    5.79  declare atLeastAtMost_iff [presburger]
    5.80  declare Bex_def [presburger]
    5.81  declare Ball_def [presburger]
    5.82 @@ -102,385 +147,11 @@
    5.83    shows "x * (if b then y else 0) = (if b then x * y else 0)"
    5.84    by simp
    5.85  
    5.86 -lemma cond_value_iff: "f (if b then x else y) = (if b then f x else f y)"
    5.87 -  by auto
    5.88 -
    5.89 -
    5.90 -subsection \<open>Formal power series form a commutative ring with unity, if the range of sequences
    5.91 -  they represent is a commutative ring with unity\<close>
    5.92 -
    5.93 -instance fps :: (semigroup_add) semigroup_add
    5.94 -proof
    5.95 -  fix a b c :: "'a fps"
    5.96 -  show "a + b + c = a + (b + c)"
    5.97 -    by (simp add: fps_ext add.assoc)
    5.98 -qed
    5.99 -
   5.100 -instance fps :: (ab_semigroup_add) ab_semigroup_add
   5.101 -proof
   5.102 -  fix a b :: "'a fps"
   5.103 -  show "a + b = b + a"
   5.104 -    by (simp add: fps_ext add.commute)
   5.105 -qed
   5.106 -
   5.107 -lemma fps_mult_assoc_lemma:
   5.108 -  fixes k :: nat
   5.109 -    and f :: "nat \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> 'a::comm_monoid_add"
   5.110 -  shows "(\<Sum>j=0..k. \<Sum>i=0..j. f i (j - i) (n - j)) =
   5.111 -         (\<Sum>j=0..k. \<Sum>i=0..k - j. f j i (n - j - i))"
   5.112 -  by (induct k) (simp_all add: Suc_diff_le sum.distrib add.assoc)
   5.113 -
   5.114 -instance fps :: (semiring_0) semigroup_mult
   5.115 -proof
   5.116 -  fix a b c :: "'a fps"
   5.117 -  show "(a * b) * c = a * (b * c)"
   5.118 -  proof (rule fps_ext)
   5.119 -    fix n :: nat
   5.120 -    have "(\<Sum>j=0..n. \<Sum>i=0..j. a$i * b$(j - i) * c$(n - j)) =
   5.121 -          (\<Sum>j=0..n. \<Sum>i=0..n - j. a$j * b$i * c$(n - j - i))"
   5.122 -      by (rule fps_mult_assoc_lemma)
   5.123 -    then show "((a * b) * c) $ n = (a * (b * c)) $ n"
   5.124 -      by (simp add: fps_mult_nth sum_distrib_left sum_distrib_right mult.assoc)
   5.125 -  qed
   5.126 -qed
   5.127 -
   5.128 -lemma fps_mult_commute_lemma:
   5.129 -  fixes n :: nat
   5.130 -    and f :: "nat \<Rightarrow> nat \<Rightarrow> 'a::comm_monoid_add"
   5.131 -  shows "(\<Sum>i=0..n. f i (n - i)) = (\<Sum>i=0..n. f (n - i) i)"
   5.132 -  by (rule sum.reindex_bij_witness[where i="(-) n" and j="(-) n"]) auto
   5.133 -
   5.134 -instance fps :: (comm_semiring_0) ab_semigroup_mult
   5.135 -proof
   5.136 -  fix a b :: "'a fps"
   5.137 -  show "a * b = b * a"
   5.138 -  proof (rule fps_ext)
   5.139 -    fix n :: nat
   5.140 -    have "(\<Sum>i=0..n. a$i * b$(n - i)) = (\<Sum>i=0..n. a$(n - i) * b$i)"
   5.141 -      by (rule fps_mult_commute_lemma)
   5.142 -    then show "(a * b) $ n = (b * a) $ n"
   5.143 -      by (simp add: fps_mult_nth mult.commute)
   5.144 -  qed
   5.145 -qed
   5.146 -
   5.147 -instance fps :: (monoid_add) monoid_add
   5.148 -proof
   5.149 -  fix a :: "'a fps"
   5.150 -  show "0 + a = a" by (simp add: fps_ext)
   5.151 -  show "a + 0 = a" by (simp add: fps_ext)
   5.152 -qed
   5.153 -
   5.154 -instance fps :: (comm_monoid_add) comm_monoid_add
   5.155 -proof
   5.156 -  fix a :: "'a fps"
   5.157 -  show "0 + a = a" by (simp add: fps_ext)
   5.158 -qed
   5.159 -
   5.160 -instance fps :: (semiring_1) monoid_mult
   5.161 -proof
   5.162 -  fix a :: "'a fps"
   5.163 -  show "1 * a = a"
   5.164 -    by (simp add: fps_ext fps_mult_nth mult_delta_left sum.delta)
   5.165 -  show "a * 1 = a"
   5.166 -    by (simp add: fps_ext fps_mult_nth mult_delta_right sum.delta')
   5.167 -qed
   5.168 -
   5.169 -instance fps :: (cancel_semigroup_add) cancel_semigroup_add
   5.170 -proof
   5.171 -  fix a b c :: "'a fps"
   5.172 -  show "b = c" if "a + b = a + c"
   5.173 -    using that by (simp add: expand_fps_eq)
   5.174 -  show "b = c" if "b + a = c + a"
   5.175 -    using that by (simp add: expand_fps_eq)
   5.176 -qed
   5.177 -
   5.178 -instance fps :: (cancel_ab_semigroup_add) cancel_ab_semigroup_add
   5.179 -proof
   5.180 -  fix a b c :: "'a fps"
   5.181 -  show "a + b - a = b"
   5.182 -    by (simp add: expand_fps_eq)
   5.183 -  show "a - b - c = a - (b + c)"
   5.184 -    by (simp add: expand_fps_eq diff_diff_eq)
   5.185 -qed
   5.186 -
   5.187 -instance fps :: (cancel_comm_monoid_add) cancel_comm_monoid_add ..
   5.188 -
   5.189 -instance fps :: (group_add) group_add
   5.190 -proof
   5.191 -  fix a b :: "'a fps"
   5.192 -  show "- a + a = 0" by (simp add: fps_ext)
   5.193 -  show "a + - b = a - b" by (simp add: fps_ext)
   5.194 -qed
   5.195 -
   5.196 -instance fps :: (ab_group_add) ab_group_add
   5.197 -proof
   5.198 -  fix a b :: "'a fps"
   5.199 -  show "- a + a = 0" by (simp add: fps_ext)
   5.200 -  show "a - b = a + - b" by (simp add: fps_ext)
   5.201 -qed
   5.202 -
   5.203 -instance fps :: (zero_neq_one) zero_neq_one
   5.204 -  by standard (simp add: expand_fps_eq)
   5.205 -
   5.206 -instance fps :: (semiring_0) semiring
   5.207 -proof
   5.208 -  fix a b c :: "'a fps"
   5.209 -  show "(a + b) * c = a * c + b * c"
   5.210 -    by (simp add: expand_fps_eq fps_mult_nth distrib_right sum.distrib)
   5.211 -  show "a * (b + c) = a * b + a * c"
   5.212 -    by (simp add: expand_fps_eq fps_mult_nth distrib_left sum.distrib)
   5.213 -qed
   5.214 -
   5.215 -instance fps :: (semiring_0) semiring_0
   5.216 -proof
   5.217 -  fix a :: "'a fps"
   5.218 -  show "0 * a = 0"
   5.219 -    by (simp add: fps_ext fps_mult_nth)
   5.220 -  show "a * 0 = 0"
   5.221 -    by (simp add: fps_ext fps_mult_nth)
   5.222 -qed
   5.223 -
   5.224 -instance fps :: (semiring_0_cancel) semiring_0_cancel ..
   5.225 -
   5.226 -instance fps :: (semiring_1) semiring_1 ..
   5.227 -
   5.228 -
   5.229 -subsection \<open>Selection of the nth power of the implicit variable in the infinite sum\<close>
   5.230 -
   5.231 -lemma fps_square_nth: "(f^2) $ n = (\<Sum>k\<le>n. f $ k * f $ (n - k))"
   5.232 -  by (simp add: power2_eq_square fps_mult_nth atLeast0AtMost)
   5.233 -
   5.234 -lemma fps_nonzero_nth: "f \<noteq> 0 \<longleftrightarrow> (\<exists> n. f $n \<noteq> 0)"
   5.235 -  by (simp add: expand_fps_eq)
   5.236 -
   5.237 -lemma fps_nonzero_nth_minimal: "f \<noteq> 0 \<longleftrightarrow> (\<exists>n. f $ n \<noteq> 0 \<and> (\<forall>m < n. f $ m = 0))"
   5.238 -  (is "?lhs \<longleftrightarrow> ?rhs")
   5.239 -proof
   5.240 -  let ?n = "LEAST n. f $ n \<noteq> 0"
   5.241 -  show ?rhs if ?lhs
   5.242 -  proof -
   5.243 -    from that have "\<exists>n. f $ n \<noteq> 0"
   5.244 -      by (simp add: fps_nonzero_nth)
   5.245 -    then have "f $ ?n \<noteq> 0"
   5.246 -      by (rule LeastI_ex)
   5.247 -    moreover have "\<forall>m<?n. f $ m = 0"
   5.248 -      by (auto dest: not_less_Least)
   5.249 -    ultimately have "f $ ?n \<noteq> 0 \<and> (\<forall>m<?n. f $ m = 0)" ..
   5.250 -    then show ?thesis ..
   5.251 -  qed
   5.252 -  show ?lhs if ?rhs
   5.253 -    using that by (auto simp add: expand_fps_eq)
   5.254 -qed
   5.255 -
   5.256 -lemma fps_eq_iff: "f = g \<longleftrightarrow> (\<forall>n. f $ n = g $n)"
   5.257 -  by (rule expand_fps_eq)
   5.258 -
   5.259 -lemma fps_sum_nth: "sum f S $ n = sum (\<lambda>k. (f k) $ n) S"
   5.260 -proof (cases "finite S")
   5.261 -  case True
   5.262 -  then show ?thesis by (induct set: finite) auto
   5.263 -next
   5.264 -  case False
   5.265 -  then show ?thesis by simp
   5.266 -qed
   5.267 -
   5.268 -
   5.269 -subsection \<open>Injection of the basic ring elements and multiplication by scalars\<close>
   5.270 -
   5.271 -definition "fps_const c = Abs_fps (\<lambda>n. if n = 0 then c else 0)"
   5.272 -
   5.273 -lemma fps_nth_fps_const [simp]: "fps_const c $ n = (if n = 0 then c else 0)"
   5.274 -  unfolding fps_const_def by simp
   5.275 -
   5.276 -lemma fps_const_0_eq_0 [simp]: "fps_const 0 = 0"
   5.277 -  by (simp add: fps_ext)
   5.278 -
   5.279 -lemma fps_const_1_eq_1 [simp]: "fps_const 1 = 1"
   5.280 -  by (simp add: fps_ext)
   5.281 -
   5.282 -lemma fps_const_neg [simp]: "- (fps_const (c::'a::ring)) = fps_const (- c)"
   5.283 -  by (simp add: fps_ext)
   5.284 -
   5.285 -lemma fps_const_add [simp]: "fps_const (c::'a::monoid_add) + fps_const d = fps_const (c + d)"
   5.286 -  by (simp add: fps_ext)
   5.287 -
   5.288 -lemma fps_const_sub [simp]: "fps_const (c::'a::group_add) - fps_const d = fps_const (c - d)"
   5.289 -  by (simp add: fps_ext)
   5.290 -
   5.291 -lemma fps_const_mult[simp]: "fps_const (c::'a::ring) * fps_const d = fps_const (c * d)"
   5.292 -  by (simp add: fps_eq_iff fps_mult_nth sum.neutral)
   5.293 -
   5.294 -lemma fps_const_add_left: "fps_const (c::'a::monoid_add) + f =
   5.295 -    Abs_fps (\<lambda>n. if n = 0 then c + f$0 else f$n)"
   5.296 -  by (simp add: fps_ext)
   5.297 -
   5.298 -lemma fps_const_add_right: "f + fps_const (c::'a::monoid_add) =
   5.299 -    Abs_fps (\<lambda>n. if n = 0 then f$0 + c else f$n)"
   5.300 -  by (simp add: fps_ext)
   5.301 -
   5.302 -lemma fps_const_mult_left: "fps_const (c::'a::semiring_0) * f = Abs_fps (\<lambda>n. c * f$n)"
   5.303 -  unfolding fps_eq_iff fps_mult_nth
   5.304 -  by (simp add: fps_const_def mult_delta_left sum.delta)
   5.305 -
   5.306 -lemma fps_const_mult_right: "f * fps_const (c::'a::semiring_0) = Abs_fps (\<lambda>n. f$n * c)"
   5.307 -  unfolding fps_eq_iff fps_mult_nth
   5.308 -  by (simp add: fps_const_def mult_delta_right sum.delta')
   5.309 -
   5.310 -lemma fps_mult_left_const_nth [simp]: "(fps_const (c::'a::semiring_1) * f)$n = c* f$n"
   5.311 -  by (simp add: fps_mult_nth mult_delta_left sum.delta)
   5.312 -
   5.313 -lemma fps_mult_right_const_nth [simp]: "(f * fps_const (c::'a::semiring_1))$n = f$n * c"
   5.314 -  by (simp add: fps_mult_nth mult_delta_right sum.delta')
   5.315 -
   5.316 -
   5.317 -subsection \<open>Formal power series form an integral domain\<close>
   5.318 -
   5.319 -instance fps :: (ring) ring ..
   5.320 -
   5.321 -instance fps :: (ring_1) ring_1
   5.322 -  by (intro_classes, auto simp add: distrib_right)
   5.323 -
   5.324 -instance fps :: (comm_ring_1) comm_ring_1
   5.325 -  by (intro_classes, auto simp add: distrib_right)
   5.326 -
   5.327 -instance fps :: (ring_no_zero_divisors) ring_no_zero_divisors
   5.328 -proof
   5.329 -  fix a b :: "'a fps"
   5.330 -  assume "a \<noteq> 0" and "b \<noteq> 0"
   5.331 -  then obtain i j where i: "a $ i \<noteq> 0" "\<forall>k<i. a $ k = 0" and j: "b $ j \<noteq> 0" "\<forall>k<j. b $ k =0"
   5.332 -    unfolding fps_nonzero_nth_minimal
   5.333 -    by blast+
   5.334 -  have "(a * b) $ (i + j) = (\<Sum>k=0..i+j. a $ k * b $ (i + j - k))"
   5.335 -    by (rule fps_mult_nth)
   5.336 -  also have "\<dots> = (a $ i * b $ (i + j - i)) + (\<Sum>k\<in>{0..i+j} - {i}. a $ k * b $ (i + j - k))"
   5.337 -    by (rule sum.remove) simp_all
   5.338 -  also have "(\<Sum>k\<in>{0..i+j}-{i}. a $ k * b $ (i + j - k)) = 0"
   5.339 -  proof (rule sum.neutral [rule_format])
   5.340 -    fix k assume "k \<in> {0..i+j} - {i}"
   5.341 -    then have "k < i \<or> i+j-k < j"
   5.342 -      by auto
   5.343 -    then show "a $ k * b $ (i + j - k) = 0"
   5.344 -      using i j by auto
   5.345 -  qed
   5.346 -  also have "a $ i * b $ (i + j - i) + 0 = a $ i * b $ j"
   5.347 -    by simp
   5.348 -  also have "a $ i * b $ j \<noteq> 0"
   5.349 -    using i j by simp
   5.350 -  finally have "(a*b) $ (i+j) \<noteq> 0" .
   5.351 -  then show "a * b \<noteq> 0"
   5.352 -    unfolding fps_nonzero_nth by blast
   5.353 -qed
   5.354 -
   5.355 -instance fps :: (ring_1_no_zero_divisors) ring_1_no_zero_divisors ..
   5.356 -
   5.357 -instance fps :: (idom) idom ..
   5.358 -
   5.359 -lemma numeral_fps_const: "numeral k = fps_const (numeral k)"
   5.360 -  by (induct k) (simp_all only: numeral.simps fps_const_1_eq_1
   5.361 -    fps_const_add [symmetric])
   5.362 -
   5.363 -lemma neg_numeral_fps_const:
   5.364 -  "(- numeral k :: 'a :: ring_1 fps) = fps_const (- numeral k)"
   5.365 -  by (simp add: numeral_fps_const)
   5.366 -
   5.367 -lemma fps_numeral_nth: "numeral n $ i = (if i = 0 then numeral n else 0)"
   5.368 -  by (simp add: numeral_fps_const)
   5.369 -
   5.370 -lemma fps_numeral_nth_0 [simp]: "numeral n $ 0 = numeral n"
   5.371 -  by (simp add: numeral_fps_const)
   5.372 -
   5.373 -lemma fps_of_nat: "fps_const (of_nat c) = of_nat c"
   5.374 -  by (induction c) (simp_all add: fps_const_add [symmetric] del: fps_const_add)
   5.375 -
   5.376 -lemma numeral_neq_fps_zero [simp]: "(numeral f :: 'a :: field_char_0 fps) \<noteq> 0"
   5.377 -proof
   5.378 -  assume "numeral f = (0 :: 'a fps)"
   5.379 -  from arg_cong[of _ _ "\<lambda>F. F $ 0", OF this] show False by simp
   5.380 -qed 
   5.381 -
   5.382 -
   5.383 -subsection \<open>The efps_Xtractor series fps_X\<close>
   5.384 -
   5.385 -lemma minus_one_power_iff: "(- (1::'a::comm_ring_1)) ^ n = (if even n then 1 else - 1)"
   5.386 -  by (induct n) auto
   5.387 -
   5.388 -definition "fps_X = Abs_fps (\<lambda>n. if n = 1 then 1 else 0)"
   5.389 -
   5.390 -lemma fps_X_mult_nth [simp]:
   5.391 -  "(fps_X * (f :: 'a::semiring_1 fps)) $n = (if n = 0 then 0 else f $ (n - 1))"
   5.392 -proof (cases "n = 0")
   5.393 -  case False
   5.394 -  have "(fps_X * f) $n = (\<Sum>i = 0..n. fps_X $ i * f $ (n - i))"
   5.395 -    by (simp add: fps_mult_nth)
   5.396 -  also have "\<dots> = f $ (n - 1)"
   5.397 -    using False by (simp add: fps_X_def mult_delta_left sum.delta)
   5.398 -  finally show ?thesis
   5.399 -    using False by simp
   5.400 -next
   5.401 -  case True
   5.402 -  then show ?thesis
   5.403 -    by (simp add: fps_mult_nth fps_X_def)
   5.404 -qed
   5.405 -
   5.406 -lemma fps_X_mult_right_nth[simp]:
   5.407 -  "((a::'a::semiring_1 fps) * fps_X) $ n = (if n = 0 then 0 else a $ (n - 1))"
   5.408 -proof -
   5.409 -  have "(a * fps_X) $ n = (\<Sum>i = 0..n. a $ i * (if n - i = Suc 0 then 1 else 0))"
   5.410 -    by (simp add: fps_times_def fps_X_def)
   5.411 -  also have "\<dots> = (\<Sum>i = 0..n. if i = n - 1 then if n = 0 then 0 else a $ i else 0)"
   5.412 -    by (intro sum.cong) auto
   5.413 -  also have "\<dots> = (if n = 0 then 0 else a $ (n - 1))" by (simp add: sum.delta)
   5.414 -  finally show ?thesis .
   5.415 -qed
   5.416 -
   5.417 -lemma fps_mult_fps_X_commute: "fps_X * (a :: 'a :: semiring_1 fps) = a * fps_X" 
   5.418 -  by (simp add: fps_eq_iff)
   5.419 -
   5.420 -lemma fps_X_power_iff: "fps_X ^ n = Abs_fps (\<lambda>m. if m = n then 1 else 0)"
   5.421 -  by (induction n) (auto simp: fps_eq_iff)
   5.422 -
   5.423 -lemma fps_X_nth[simp]: "fps_X$n = (if n = 1 then 1 else 0)"
   5.424 -  by (simp add: fps_X_def)
   5.425 -
   5.426 -lemma fps_X_power_nth[simp]: "(fps_X^k) $n = (if n = k then 1 else 0::'a::comm_ring_1)"
   5.427 -  by (simp add: fps_X_power_iff)
   5.428 -
   5.429 -lemma fps_X_power_mult_nth: "(fps_X^k * (f :: 'a::comm_ring_1 fps)) $n = (if n < k then 0 else f $ (n - k))"
   5.430 -  apply (induct k arbitrary: n)
   5.431 -  apply simp
   5.432 -  unfolding power_Suc mult.assoc
   5.433 -  apply (case_tac n)
   5.434 -  apply auto
   5.435 -  done
   5.436 -
   5.437 -lemma fps_X_power_mult_right_nth:
   5.438 -    "((f :: 'a::comm_ring_1 fps) * fps_X^k) $n = (if n < k then 0 else f $ (n - k))"
   5.439 -  by (metis fps_X_power_mult_nth mult.commute)
   5.440 -
   5.441 -
   5.442 -lemma fps_X_neq_fps_const [simp]: "(fps_X :: 'a :: zero_neq_one fps) \<noteq> fps_const c"
   5.443 -proof
   5.444 -  assume "(fps_X::'a fps) = fps_const (c::'a)"
   5.445 -  hence "fps_X$1 = (fps_const (c::'a))$1" by (simp only:)
   5.446 -  thus False by auto
   5.447 -qed
   5.448 -
   5.449 -lemma fps_X_neq_zero [simp]: "(fps_X :: 'a :: zero_neq_one fps) \<noteq> 0"
   5.450 -  by (simp only: fps_const_0_eq_0[symmetric] fps_X_neq_fps_const) simp
   5.451 -
   5.452 -lemma fps_X_neq_one [simp]: "(fps_X :: 'a :: zero_neq_one fps) \<noteq> 1"
   5.453 -  by (simp only: fps_const_1_eq_1[symmetric] fps_X_neq_fps_const) simp
   5.454 -
   5.455 -lemma fps_X_neq_numeral [simp]: "(fps_X :: 'a :: {semiring_1,zero_neq_one} fps) \<noteq> numeral c"
   5.456 -  by (simp only: numeral_fps_const fps_X_neq_fps_const) simp
   5.457 -
   5.458 -lemma fps_X_pow_eq_fps_X_pow_iff [simp]:
   5.459 -  "(fps_X :: ('a :: {comm_ring_1}) fps) ^ m = fps_X ^ n \<longleftrightarrow> m = n"
   5.460 -proof
   5.461 -  assume "(fps_X :: 'a fps) ^ m = fps_X ^ n"
   5.462 -  hence "(fps_X :: 'a fps) ^ m $ m = fps_X ^ n $ m" by (simp only:)
   5.463 -  thus "m = n" by (simp split: if_split_asm)
   5.464 -qed simp_all
   5.465 +lemma fps_one_mult:
   5.466 +  fixes f :: "'a::{comm_monoid_add, mult_zero, monoid_mult} fps"
   5.467 +  shows "1 * f = f"
   5.468 +  and   "f * 1 = f"
   5.469 +  by    (simp_all add: fps_ext fps_mult_nth mult_delta_left mult_delta_right)
   5.470  
   5.471  
   5.472  subsection \<open>Subdegrees\<close>
   5.473 @@ -543,21 +214,12 @@
   5.474    "f $ n \<noteq> 0 \<Longrightarrow> subdegree f \<le> n"
   5.475    by (rule leI) auto
   5.476  
   5.477 -
   5.478  lemma subdegree_0 [simp]: "subdegree 0 = 0"
   5.479    by (simp add: subdegree_def)
   5.480  
   5.481 -lemma subdegree_1 [simp]: "subdegree (1 :: ('a :: zero_neq_one) fps) = 0"
   5.482 -  by (auto intro!: subdegreeI)
   5.483 -
   5.484 -lemma subdegree_fps_X [simp]: "subdegree (fps_X :: ('a :: zero_neq_one) fps) = 1"
   5.485 -  by (auto intro!: subdegreeI simp: fps_X_def)
   5.486 -
   5.487 -lemma subdegree_fps_const [simp]: "subdegree (fps_const c) = 0"
   5.488 -  by (cases "c = 0") (auto intro!: subdegreeI)
   5.489 -
   5.490 -lemma subdegree_numeral [simp]: "subdegree (numeral n) = 0"
   5.491 -  by (simp add: numeral_fps_const)
   5.492 +lemma subdegree_1 [simp]: "subdegree 1 = 0"
   5.493 +  by  (cases "(1::'a) = 0")
   5.494 +      (auto intro: subdegreeI fps_ext simp: subdegree_def)
   5.495  
   5.496  lemma subdegree_eq_0_iff: "subdegree f = 0 \<longleftrightarrow> f = 0 \<or> f $ 0 \<noteq> 0"
   5.497  proof (cases "f = 0")
   5.498 @@ -569,6 +231,119 @@
   5.499  lemma subdegree_eq_0 [simp]: "f $ 0 \<noteq> 0 \<Longrightarrow> subdegree f = 0"
   5.500    by (simp add: subdegree_eq_0_iff)
   5.501  
   5.502 +lemma nth_subdegree_zero_iff [simp]: "f $ subdegree f = 0 \<longleftrightarrow> f = 0"
   5.503 +  by (cases "f = 0") auto
   5.504 +
   5.505 +lemma fps_nonzero_subdegree_nonzeroI: "subdegree f > 0 \<Longrightarrow> f \<noteq> 0"
   5.506 + by auto
   5.507 +
   5.508 +lemma subdegree_uminus [simp]:
   5.509 +  "subdegree (-(f::('a::group_add) fps)) = subdegree f"
   5.510 +proof (cases "f=0")
   5.511 +  case False thus ?thesis by (force intro: subdegreeI)
   5.512 +qed simp
   5.513 +
   5.514 +lemma subdegree_minus_commute [simp]:
   5.515 +  "subdegree (f-(g::('a::group_add) fps)) = subdegree (g - f)"
   5.516 +proof (-, cases "g-f=0")
   5.517 +  case True
   5.518 +  have "\<And>n. (f - g) $ n = -((g - f) $ n)" by simp
   5.519 +  with True have "f - g = 0" by (intro fps_ext) simp
   5.520 +  with True show ?thesis by simp
   5.521 +next
   5.522 +  case False show ?thesis
   5.523 +    using nth_subdegree_nonzero[OF False] by (fastforce intro: subdegreeI)
   5.524 +qed
   5.525 +
   5.526 +lemma subdegree_add_ge':
   5.527 +  fixes   f g :: "'a::monoid_add fps"
   5.528 +  assumes "f + g \<noteq> 0"
   5.529 +  shows   "subdegree (f + g) \<ge> min (subdegree f) (subdegree g)"
   5.530 +  using   assms
   5.531 +  by      (force intro: subdegree_geI)
   5.532 +
   5.533 +lemma subdegree_add_ge:
   5.534 +  assumes "f \<noteq> -(g :: ('a :: group_add) fps)"
   5.535 +  shows   "subdegree (f + g) \<ge> min (subdegree f) (subdegree g)"
   5.536 +proof (rule subdegree_add_ge')
   5.537 +  have "f + g = 0 \<Longrightarrow> False"
   5.538 +  proof-
   5.539 +    assume fg: "f + g = 0"
   5.540 +    have "\<And>n. f $ n = - g $ n"
   5.541 +    proof-
   5.542 +      fix n
   5.543 +      from fg have "(f + g) $ n = 0" by simp
   5.544 +      hence "f $ n + g $ n - g $ n = - g $ n" by simp
   5.545 +      thus "f $ n = - g $ n" by simp      
   5.546 +    qed
   5.547 +    with assms show False by (auto intro: fps_ext)
   5.548 +  qed
   5.549 +  thus "f + g \<noteq> 0" by fast
   5.550 +qed
   5.551 +
   5.552 +lemma subdegree_add_eq1:
   5.553 +  assumes "f \<noteq> 0"
   5.554 +  and     "subdegree f < subdegree (g :: 'a::monoid_add fps)"
   5.555 +  shows   "subdegree (f + g) = subdegree f"
   5.556 +  using   assms
   5.557 +  by      (auto intro: subdegreeI simp: nth_less_subdegree_zero)
   5.558 +
   5.559 +lemma subdegree_add_eq2:
   5.560 +  assumes "g \<noteq> 0"
   5.561 +  and     "subdegree g < subdegree (f :: 'a :: monoid_add fps)"
   5.562 +  shows   "subdegree (f + g) = subdegree g"
   5.563 +  using   assms
   5.564 +  by      (auto intro: subdegreeI simp: nth_less_subdegree_zero)
   5.565 +
   5.566 +lemma subdegree_diff_eq1:
   5.567 +  assumes "f \<noteq> 0"
   5.568 +  and     "subdegree f < subdegree (g :: 'a :: group_add fps)"
   5.569 +  shows   "subdegree (f - g) = subdegree f"
   5.570 +  using   assms
   5.571 +  by      (auto intro: subdegreeI simp: nth_less_subdegree_zero)
   5.572 +
   5.573 +lemma subdegree_diff_eq1_cancel:
   5.574 +  assumes "f \<noteq> 0"
   5.575 +  and     "subdegree f < subdegree (g :: 'a :: cancel_comm_monoid_add fps)"
   5.576 +  shows   "subdegree (f - g) = subdegree f"
   5.577 +  using   assms
   5.578 +  by      (auto intro: subdegreeI simp: nth_less_subdegree_zero)
   5.579 +
   5.580 +lemma subdegree_diff_eq2:
   5.581 +  assumes "g \<noteq> 0"
   5.582 +  and     "subdegree g < subdegree (f :: 'a :: group_add fps)"
   5.583 +  shows   "subdegree (f - g) = subdegree g"
   5.584 +  using   assms
   5.585 +  by      (auto intro: subdegreeI simp: nth_less_subdegree_zero)
   5.586 +
   5.587 +lemma subdegree_diff_ge [simp]:
   5.588 +  assumes "f \<noteq> (g :: 'a :: group_add fps)"
   5.589 +  shows   "subdegree (f - g) \<ge> min (subdegree f) (subdegree g)"
   5.590 +proof-
   5.591 +  from assms have "f = - (- g) \<Longrightarrow> False" using expand_fps_eq by fastforce
   5.592 +  hence "f \<noteq> - (- g)" by fast
   5.593 +  moreover have "f + - g = f - g" by (simp add: fps_ext)
   5.594 +  ultimately show ?thesis
   5.595 +    using subdegree_add_ge[of f "-g"] by simp
   5.596 +qed
   5.597 +
   5.598 +lemma subdegree_diff_ge':
   5.599 +  fixes   f g :: "'a :: comm_monoid_diff fps"
   5.600 +  assumes "f - g \<noteq> 0"
   5.601 +  shows   "subdegree (f - g) \<ge> subdegree f"
   5.602 +  using   assms
   5.603 +  by      (auto intro: subdegree_geI simp: nth_less_subdegree_zero)
   5.604 +
   5.605 +lemma nth_subdegree_mult_left [simp]:
   5.606 +  fixes f g :: "('a :: {mult_zero,comm_monoid_add}) fps"
   5.607 +  shows "(f * g) $ (subdegree f) = f $ subdegree f * g $ 0"
   5.608 +  by    (cases "subdegree f") (simp_all add: fps_mult_nth nth_less_subdegree_zero)
   5.609 +
   5.610 +lemma nth_subdegree_mult_right [simp]:
   5.611 +  fixes f g :: "('a :: {mult_zero,comm_monoid_add}) fps"
   5.612 +  shows "(f * g) $ (subdegree g) = f $ 0 * g $ subdegree g"
   5.613 +  by    (cases "subdegree g") (simp_all add: fps_mult_nth nth_less_subdegree_zero sum_head_Suc)
   5.614 +
   5.615  lemma nth_subdegree_mult [simp]:
   5.616    fixes f g :: "('a :: {mult_zero,comm_monoid_add}) fps"
   5.617    shows "(f * g) $ (subdegree f + subdegree g) = f $ subdegree f * g $ subdegree g"
   5.618 @@ -583,100 +358,660 @@
   5.619      thus "f $ x * g $ (?n - x) = (if x = subdegree f then f $ x * g $ (?n - x) else 0)"
   5.620        by (elim disjE conjE) auto
   5.621    qed auto
   5.622 -  also have "... = f $ subdegree f * g $ subdegree g" by (simp add: sum.delta)
   5.623 +  also have "... = f $ subdegree f * g $ subdegree g" by simp
   5.624    finally show ?thesis .
   5.625  qed
   5.626  
   5.627 +lemma fps_mult_nth_eq0:
   5.628 +  fixes f g :: "'a::{comm_monoid_add,mult_zero} fps"
   5.629 +  assumes "n < subdegree f + subdegree g"
   5.630 +  shows   "(f*g) $ n = 0"
   5.631 +proof-
   5.632 +  have "\<And>i. i\<in>{0..n} \<Longrightarrow> f$i * g$(n - i) = 0"
   5.633 +  proof-
   5.634 +    fix i assume i: "i\<in>{0..n}"
   5.635 +    show "f$i * g$(n - i) = 0"
   5.636 +    proof (cases "i < subdegree f \<or> n - i < subdegree g")
   5.637 +      case False with assms i show ?thesis by auto
   5.638 +    qed (auto simp: nth_less_subdegree_zero)
   5.639 +  qed
   5.640 +  thus "(f * g) $ n = 0" by (simp add: fps_mult_nth)
   5.641 +qed
   5.642 +
   5.643 +lemma fps_mult_subdegree_ge:
   5.644 +  fixes   f g :: "'a::{comm_monoid_add,mult_zero} fps"
   5.645 +  assumes "f*g \<noteq> 0"
   5.646 +  shows   "subdegree (f*g) \<ge> subdegree f + subdegree g"
   5.647 +  using   assms fps_mult_nth_eq0
   5.648 +  by      (intro subdegree_geI) simp
   5.649 +
   5.650 +lemma subdegree_mult':
   5.651 +  fixes   f g :: "'a::{comm_monoid_add,mult_zero} fps"
   5.652 +  assumes "f $ subdegree f * g $ subdegree g \<noteq> 0"
   5.653 +  shows   "subdegree (f*g) = subdegree f + subdegree g"
   5.654 +proof-
   5.655 +  from assms have "(f * g) $ (subdegree f + subdegree g) \<noteq> 0" by simp
   5.656 +  hence "f*g \<noteq> 0" by fastforce
   5.657 +  hence "subdegree (f*g) \<ge> subdegree f + subdegree g" using fps_mult_subdegree_ge by fast
   5.658 +  moreover from assms have "subdegree (f*g) \<le> subdegree f + subdegree g"
   5.659 +    by (intro subdegree_leI) simp
   5.660 +  ultimately show ?thesis by simp
   5.661 +qed
   5.662 +
   5.663  lemma subdegree_mult [simp]:
   5.664 +  fixes   f g :: "'a :: {semiring_no_zero_divisors} fps"
   5.665    assumes "f \<noteq> 0" "g \<noteq> 0"
   5.666 -  shows "subdegree ((f :: ('a :: {ring_no_zero_divisors}) fps) * g) = subdegree f + subdegree g"
   5.667 -proof (rule subdegreeI)
   5.668 -  let ?n = "subdegree f + subdegree g"
   5.669 -  have "(f * g) $ ?n = (\<Sum>i=0..?n. f$i * g$(?n-i))" by (simp add: fps_mult_nth)
   5.670 -  also have "... = (\<Sum>i=0..?n. if i = subdegree f then f$i * g$(?n-i) else 0)"
   5.671 -  proof (intro sum.cong)
   5.672 -    fix x assume x: "x \<in> {0..?n}"
   5.673 -    hence "x = subdegree f \<or> x < subdegree f \<or> ?n - x < subdegree g" by auto
   5.674 -    thus "f $ x * g $ (?n - x) = (if x = subdegree f then f $ x * g $ (?n - x) else 0)"
   5.675 -      by (elim disjE conjE) auto
   5.676 +  shows   "subdegree (f * g) = subdegree f + subdegree g"
   5.677 +  using   assms
   5.678 +  by      (intro subdegree_mult') simp
   5.679 +
   5.680 +lemma fps_mult_nth_conv_upto_subdegree_left:
   5.681 +  fixes f g :: "('a :: {mult_zero,comm_monoid_add}) fps"
   5.682 +  shows "(f * g) $ n = (\<Sum>i=subdegree f..n. f $ i * g $ (n - i))"
   5.683 +proof (cases "subdegree f \<le> n")
   5.684 +  case True
   5.685 +  hence "{0..n} = {0..<subdegree f} \<union> {subdegree f..n}" by auto
   5.686 +  moreover have "{0..<subdegree f} \<inter> {subdegree f..n} = {}" by auto
   5.687 +  ultimately show ?thesis
   5.688 +    using nth_less_subdegree_zero[of _ f]
   5.689 +    by    (simp add: fps_mult_nth sum.union_disjoint)
   5.690 +qed (simp add: fps_mult_nth nth_less_subdegree_zero)
   5.691 +
   5.692 +lemma fps_mult_nth_conv_upto_subdegree_right:
   5.693 +  fixes f g :: "('a :: {mult_zero,comm_monoid_add}) fps"
   5.694 +  shows "(f * g) $ n = (\<Sum>i=0..n - subdegree g. f $ i * g $ (n - i))"
   5.695 +proof-
   5.696 +  have "{0..n} = {0..n - subdegree g} \<union> {n - subdegree g<..n}" by auto
   5.697 +  moreover have "{0..n - subdegree g} \<inter> {n - subdegree g<..n} = {}" by auto
   5.698 +  moreover have "\<forall>i\<in>{n - subdegree g<..n}. g $ (n - i) = 0"
   5.699 +    using nth_less_subdegree_zero[of _ g] by auto
   5.700 +  ultimately show ?thesis by (simp add: fps_mult_nth sum.union_disjoint)
   5.701 +qed
   5.702 +
   5.703 +lemma fps_mult_nth_conv_inside_subdegrees:
   5.704 +  fixes f g :: "('a :: {mult_zero,comm_monoid_add}) fps"
   5.705 +  shows "(f * g) $ n = (\<Sum>i=subdegree f..n - subdegree g. f $ i * g $ (n - i))"
   5.706 +proof (cases "subdegree f \<le> n - subdegree g")
   5.707 +  case True
   5.708 +  hence "{subdegree f..n} = {subdegree f..n - subdegree g} \<union> {n - subdegree g<..n}"
   5.709 +    by auto
   5.710 +  moreover have "{subdegree f..n - subdegree g} \<inter> {n - subdegree g<..n} = {}" by auto
   5.711 +  moreover have "\<forall>i\<in>{n - subdegree g<..n}. f $ i * g $ (n - i) = 0"
   5.712 +    using nth_less_subdegree_zero[of _ g] by auto
   5.713 +  ultimately show ?thesis
   5.714 +    using fps_mult_nth_conv_upto_subdegree_left[of f g n]
   5.715 +    by    (simp add: sum.union_disjoint)
   5.716 +next
   5.717 +  case False
   5.718 +  hence 1: "subdegree f > n - subdegree g" by simp
   5.719 +  show ?thesis
   5.720 +  proof (cases "f*g = 0")
   5.721 +    case False
   5.722 +    with 1 have "n < subdegree (f*g)" using fps_mult_subdegree_ge[of f g] by simp
   5.723 +    with 1 show ?thesis by auto
   5.724 +  qed (simp add: 1)
   5.725 +qed
   5.726 +
   5.727 +lemma fps_mult_nth_outside_subdegrees:
   5.728 +  fixes f g :: "('a :: {mult_zero,comm_monoid_add}) fps"
   5.729 +  shows "n < subdegree f \<Longrightarrow> (f * g) $ n = 0"
   5.730 +  and   "n < subdegree g \<Longrightarrow> (f * g) $ n = 0"
   5.731 +  by    (auto simp: fps_mult_nth_conv_inside_subdegrees)
   5.732 +
   5.733 +
   5.734 +subsection \<open>Formal power series form a commutative ring with unity, if the range of sequences
   5.735 +  they represent is a commutative ring with unity\<close>
   5.736 +
   5.737 +instance fps :: (semigroup_add) semigroup_add
   5.738 +proof
   5.739 +  fix a b c :: "'a fps"
   5.740 +  show "a + b + c = a + (b + c)"
   5.741 +    by (simp add: fps_ext add.assoc)
   5.742 +qed
   5.743 +
   5.744 +instance fps :: (ab_semigroup_add) ab_semigroup_add
   5.745 +proof
   5.746 +  fix a b :: "'a fps"
   5.747 +  show "a + b = b + a"
   5.748 +    by (simp add: fps_ext add.commute)
   5.749 +qed
   5.750 +
   5.751 +instance fps :: (monoid_add) monoid_add
   5.752 +proof
   5.753 +  fix a :: "'a fps"
   5.754 +  show "0 + a = a" by (simp add: fps_ext)
   5.755 +  show "a + 0 = a" by (simp add: fps_ext)
   5.756 +qed
   5.757 +
   5.758 +instance fps :: (comm_monoid_add) comm_monoid_add
   5.759 +proof
   5.760 +  fix a :: "'a fps"
   5.761 +  show "0 + a = a" by (simp add: fps_ext)
   5.762 +qed
   5.763 +
   5.764 +instance fps :: (cancel_semigroup_add) cancel_semigroup_add
   5.765 +proof
   5.766 +  fix a b c :: "'a fps"
   5.767 +  show "b = c" if "a + b = a + c"
   5.768 +    using that by (simp add: expand_fps_eq)
   5.769 +  show "b = c" if "b + a = c + a"
   5.770 +    using that by (simp add: expand_fps_eq)
   5.771 +qed
   5.772 +
   5.773 +instance fps :: (cancel_ab_semigroup_add) cancel_ab_semigroup_add
   5.774 +proof
   5.775 +  fix a b c :: "'a fps"
   5.776 +  show "a + b - a = b"
   5.777 +    by (simp add: expand_fps_eq)
   5.778 +  show "a - b - c = a - (b + c)"
   5.779 +    by (simp add: expand_fps_eq diff_diff_eq)
   5.780 +qed
   5.781 +
   5.782 +instance fps :: (cancel_comm_monoid_add) cancel_comm_monoid_add ..
   5.783 +
   5.784 +instance fps :: (group_add) group_add
   5.785 +proof
   5.786 +  fix a b :: "'a fps"
   5.787 +  show "- a + a = 0" by (simp add: fps_ext)
   5.788 +  show "a + - b = a - b" by (simp add: fps_ext)
   5.789 +qed
   5.790 +
   5.791 +instance fps :: (ab_group_add) ab_group_add
   5.792 +proof
   5.793 +  fix a b :: "'a fps"
   5.794 +  show "- a + a = 0" by (simp add: fps_ext)
   5.795 +  show "a - b = a + - b" by (simp add: fps_ext)
   5.796 +qed
   5.797 +
   5.798 +instance fps :: (zero_neq_one) zero_neq_one
   5.799 +  by standard (simp add: expand_fps_eq)
   5.800 +
   5.801 +lemma fps_mult_assoc_lemma:
   5.802 +  fixes k :: nat
   5.803 +    and f :: "nat \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> 'a::comm_monoid_add"
   5.804 +  shows "(\<Sum>j=0..k. \<Sum>i=0..j. f i (j - i) (n - j)) =
   5.805 +         (\<Sum>j=0..k. \<Sum>i=0..k - j. f j i (n - j - i))"
   5.806 +  by (induct k) (simp_all add: Suc_diff_le sum.distrib add.assoc)
   5.807 +
   5.808 +instance fps :: (semiring_0) semiring_0
   5.809 +proof
   5.810 +  fix a b c :: "'a fps"
   5.811 +  show "(a + b) * c = a * c + b * c"
   5.812 +    by (simp add: expand_fps_eq fps_mult_nth distrib_right sum.distrib)
   5.813 +  show "a * (b + c) = a * b + a * c"
   5.814 +    by (simp add: expand_fps_eq fps_mult_nth distrib_left sum.distrib)
   5.815 +  show "(a * b) * c = a * (b * c)"
   5.816 +  proof (rule fps_ext)
   5.817 +    fix n :: nat
   5.818 +    have "(\<Sum>j=0..n. \<Sum>i=0..j. a$i * b$(j - i) * c$(n - j)) =
   5.819 +          (\<Sum>j=0..n. \<Sum>i=0..n - j. a$j * b$i * c$(n - j - i))"
   5.820 +      by (rule fps_mult_assoc_lemma)
   5.821 +    then show "((a * b) * c) $ n = (a * (b * c)) $ n"
   5.822 +      by (simp add: fps_mult_nth sum_distrib_left sum_distrib_right mult.assoc)
   5.823 +  qed
   5.824 +qed
   5.825 +
   5.826 +instance fps :: (semiring_0_cancel) semiring_0_cancel ..
   5.827 +
   5.828 +lemma fps_mult_commute_lemma:
   5.829 +  fixes n :: nat
   5.830 +    and f :: "nat \<Rightarrow> nat \<Rightarrow> 'a::comm_monoid_add"
   5.831 +  shows "(\<Sum>i=0..n. f i (n - i)) = (\<Sum>i=0..n. f (n - i) i)"
   5.832 +  by (rule sum.reindex_bij_witness[where i="(-) n" and j="(-) n"]) auto
   5.833 +
   5.834 +instance fps :: (comm_semiring_0) comm_semiring_0
   5.835 +proof
   5.836 +  fix a b c :: "'a fps"
   5.837 +  show "a * b = b * a"
   5.838 +  proof (rule fps_ext)
   5.839 +    fix n :: nat
   5.840 +    have "(\<Sum>i=0..n. a$i * b$(n - i)) = (\<Sum>i=0..n. a$(n - i) * b$i)"
   5.841 +      by (rule fps_mult_commute_lemma)
   5.842 +    then show "(a * b) $ n = (b * a) $ n"
   5.843 +      by (simp add: fps_mult_nth mult.commute)
   5.844 +  qed 
   5.845 +qed (simp add: distrib_right)
   5.846 +
   5.847 +instance fps :: (comm_semiring_0_cancel) comm_semiring_0_cancel ..
   5.848 +
   5.849 +instance fps :: (semiring_1) semiring_1
   5.850 +proof
   5.851 +  fix a :: "'a fps"
   5.852 +  show "1 * a = a" "a * 1 = a" by (simp_all add: fps_one_mult)
   5.853 +qed
   5.854 +
   5.855 +instance fps :: (comm_semiring_1) comm_semiring_1
   5.856 +  by standard simp
   5.857 +
   5.858 +instance fps :: (semiring_1_cancel) semiring_1_cancel ..
   5.859 +
   5.860 +
   5.861 +subsection \<open>Selection of the nth power of the implicit variable in the infinite sum\<close>
   5.862 +
   5.863 +lemma fps_square_nth: "(f^2) $ n = (\<Sum>k\<le>n. f $ k * f $ (n - k))"
   5.864 +  by (simp add: power2_eq_square fps_mult_nth atLeast0AtMost)
   5.865 +
   5.866 +lemma fps_sum_nth: "sum f S $ n = sum (\<lambda>k. (f k) $ n) S"
   5.867 +proof (cases "finite S")
   5.868 +  case True
   5.869 +  then show ?thesis by (induct set: finite) auto
   5.870 +next
   5.871 +  case False
   5.872 +  then show ?thesis by simp
   5.873 +qed
   5.874 +
   5.875 +
   5.876 +subsection \<open>Injection of the basic ring elements and multiplication by scalars\<close>
   5.877 +
   5.878 +definition "fps_const c = Abs_fps (\<lambda>n. if n = 0 then c else 0)"
   5.879 +
   5.880 +lemma fps_nth_fps_const [simp]: "fps_const c $ n = (if n = 0 then c else 0)"
   5.881 +  unfolding fps_const_def by simp
   5.882 +
   5.883 +lemma fps_const_0_eq_0 [simp]: "fps_const 0 = 0"
   5.884 +  by (simp add: fps_ext)
   5.885 +
   5.886 +lemma fps_const_nonzero_eq_nonzero: "c \<noteq> 0 \<Longrightarrow> fps_const c \<noteq> 0"
   5.887 +  using fps_nonzeroI[of "fps_const c" 0] by simp
   5.888 +
   5.889 +lemma fps_const_1_eq_1 [simp]: "fps_const 1 = 1"
   5.890 +  by (simp add: fps_ext)
   5.891 +
   5.892 +lemma subdegree_fps_const [simp]: "subdegree (fps_const c) = 0"
   5.893 +  by (cases "c = 0") (auto intro!: subdegreeI)
   5.894 +
   5.895 +lemma fps_const_neg [simp]: "- (fps_const (c::'a::group_add)) = fps_const (- c)"
   5.896 +  by (simp add: fps_ext)
   5.897 +
   5.898 +lemma fps_const_add [simp]: "fps_const (c::'a::monoid_add) + fps_const d = fps_const (c + d)"
   5.899 +  by (simp add: fps_ext)
   5.900 +
   5.901 +lemma fps_const_add_left: "fps_const (c::'a::monoid_add) + f =
   5.902 +    Abs_fps (\<lambda>n. if n = 0 then c + f$0 else f$n)"
   5.903 +  by (simp add: fps_ext)
   5.904 +
   5.905 +lemma fps_const_add_right: "f + fps_const (c::'a::monoid_add) =
   5.906 +    Abs_fps (\<lambda>n. if n = 0 then f$0 + c else f$n)"
   5.907 +  by (simp add: fps_ext)
   5.908 +
   5.909 +lemma fps_const_sub [simp]: "fps_const (c::'a::group_add) - fps_const d = fps_const (c - d)"
   5.910 +  by (simp add: fps_ext)
   5.911 +
   5.912 +lemmas fps_const_minus = fps_const_sub
   5.913 +
   5.914 +lemma fps_const_mult[simp]:
   5.915 +  fixes c d :: "'a::{comm_monoid_add,mult_zero}"
   5.916 +  shows "fps_const c * fps_const d = fps_const (c * d)"
   5.917 +  by    (simp add: fps_eq_iff fps_mult_nth sum.neutral)
   5.918 +
   5.919 +lemma fps_const_mult_left:
   5.920 +  "fps_const (c::'a::{comm_monoid_add,mult_zero}) * f = Abs_fps (\<lambda>n. c * f$n)"
   5.921 +  unfolding fps_eq_iff fps_mult_nth
   5.922 +  by (simp add: fps_const_def mult_delta_left)
   5.923 +
   5.924 +lemma fps_const_mult_right:
   5.925 +  "f * fps_const (c::'a::{comm_monoid_add,mult_zero}) = Abs_fps (\<lambda>n. f$n * c)"
   5.926 +  unfolding fps_eq_iff fps_mult_nth
   5.927 +  by (simp add: fps_const_def mult_delta_right)
   5.928 +
   5.929 +lemma fps_mult_left_const_nth [simp]:
   5.930 +  "(fps_const (c::'a::{comm_monoid_add,mult_zero}) * f)$n = c* f$n"
   5.931 +  by (simp add: fps_mult_nth mult_delta_left)
   5.932 +
   5.933 +lemma fps_mult_right_const_nth [simp]:
   5.934 +  "(f * fps_const (c::'a::{comm_monoid_add,mult_zero}))$n = f$n * c"
   5.935 +  by (simp add: fps_mult_nth mult_delta_right)
   5.936 +
   5.937 +lemma fps_const_power [simp]: "fps_const c ^ n = fps_const (c^n)"
   5.938 +  by (induct n) auto
   5.939 +
   5.940 +
   5.941 +subsection \<open>Formal power series form an integral domain\<close>
   5.942 +
   5.943 +instance fps :: (ring) ring ..
   5.944 +
   5.945 +instance fps :: (comm_ring) comm_ring ..
   5.946 +
   5.947 +instance fps :: (ring_1) ring_1 ..
   5.948 +
   5.949 +instance fps :: (comm_ring_1) comm_ring_1 ..
   5.950 +
   5.951 +instance fps :: (semiring_no_zero_divisors) semiring_no_zero_divisors
   5.952 +proof
   5.953 +  fix a b :: "'a fps"
   5.954 +  assume "a \<noteq> 0" and "b \<noteq> 0"
   5.955 +  hence "(a * b) $ (subdegree a + subdegree b) \<noteq> 0" by simp
   5.956 +  thus "a * b \<noteq> 0" using fps_nonzero_nth by fast
   5.957 +qed
   5.958 +
   5.959 +instance fps :: (semiring_1_no_zero_divisors) semiring_1_no_zero_divisors ..
   5.960 +
   5.961 +instance fps :: ("{cancel_semigroup_add,semiring_no_zero_divisors_cancel}")
   5.962 +  semiring_no_zero_divisors_cancel
   5.963 +proof
   5.964 +  fix a b c :: "'a fps"
   5.965 +  show "(a * c = b * c) = (c = 0 \<or> a = b)"
   5.966 +  proof
   5.967 +    assume ab: "a * c = b * c"
   5.968 +    have "c \<noteq> 0 \<Longrightarrow> a = b"
   5.969 +    proof (rule fps_ext)
   5.970 +      fix n
   5.971 +      assume c: "c \<noteq> 0"
   5.972 +      show "a $ n = b $ n"
   5.973 +      proof (induct n rule: nat_less_induct)
   5.974 +        case (1 n)
   5.975 +        with ab c show ?case
   5.976 +          using fps_mult_nth_conv_upto_subdegree_right[of a c "subdegree c + n"]
   5.977 +                fps_mult_nth_conv_upto_subdegree_right[of b c "subdegree c + n"]
   5.978 +          by    (cases n) auto
   5.979 +      qed
   5.980 +    qed
   5.981 +    thus "c = 0 \<or> a = b" by fast
   5.982    qed auto
   5.983 -  also have "... = f $ subdegree f * g $ subdegree g" by (simp add: sum.delta)
   5.984 -  also from assms have "... \<noteq> 0" by auto
   5.985 -  finally show "(f * g) $ (subdegree f + subdegree g) \<noteq> 0" .
   5.986 -next
   5.987 -  fix m assume m: "m < subdegree f + subdegree g"
   5.988 -  have "(f * g) $ m = (\<Sum>i=0..m. f$i * g$(m-i))" by (simp add: fps_mult_nth)
   5.989 -  also have "... = (\<Sum>i=0..m. 0)"
   5.990 -  proof (rule sum.cong)
   5.991 -    fix i assume "i \<in> {0..m}"
   5.992 -    with m have "i < subdegree f \<or> m - i < subdegree g" by auto
   5.993 -    thus "f$i * g$(m-i) = 0" by (elim disjE) auto
   5.994 +  show "(c * a = c * b) = (c = 0 \<or> a = b)"
   5.995 +  proof
   5.996 +    assume ab: "c * a = c * b"
   5.997 +    have "c \<noteq> 0 \<Longrightarrow> a = b"
   5.998 +    proof (rule fps_ext)
   5.999 +      fix n
  5.1000 +      assume c: "c \<noteq> 0"
  5.1001 +      show "a $ n = b $ n"
  5.1002 +      proof (induct n rule: nat_less_induct)
  5.1003 +        case (1 n)
  5.1004 +        moreover have "\<forall>i\<in>{Suc (subdegree c)..subdegree c + n}. subdegree c + n - i < n" by auto
  5.1005 +        ultimately show ?case
  5.1006 +          using ab c fps_mult_nth_conv_upto_subdegree_left[of c a "subdegree c + n"]
  5.1007 +                fps_mult_nth_conv_upto_subdegree_left[of c b "subdegree c + n"]
  5.1008 +          by    (simp add: sum_head_Suc)
  5.1009 +      qed
  5.1010 +    qed    
  5.1011 +    thus "c = 0 \<or> a = b" by fast
  5.1012    qed auto
  5.1013 -  finally show "(f * g) $ m = 0" by simp
  5.1014 -qed
  5.1015 +qed
  5.1016 +
  5.1017 +instance fps :: (ring_no_zero_divisors) ring_no_zero_divisors ..
  5.1018 +
  5.1019 +instance fps :: (ring_1_no_zero_divisors) ring_1_no_zero_divisors ..
  5.1020 +
  5.1021 +instance fps :: (idom) idom ..
  5.1022 +
  5.1023 +lemma fps_numeral_fps_const: "numeral k = fps_const (numeral k)"
  5.1024 +  by (induct k) (simp_all only: numeral.simps fps_const_1_eq_1 fps_const_add [symmetric])
  5.1025 +
  5.1026 +lemmas numeral_fps_const = fps_numeral_fps_const
  5.1027 +
  5.1028 +lemma neg_numeral_fps_const:
  5.1029 +  "(- numeral k :: 'a :: ring_1 fps) = fps_const (- numeral k)"
  5.1030 +  by (simp add: numeral_fps_const)
  5.1031 +
  5.1032 +lemma fps_numeral_nth: "numeral n $ i = (if i = 0 then numeral n else 0)"
  5.1033 +  by (simp add: numeral_fps_const)
  5.1034 +
  5.1035 +lemma fps_numeral_nth_0 [simp]: "numeral n $ 0 = numeral n"
  5.1036 +  by (simp add: numeral_fps_const)
  5.1037 +
  5.1038 +lemma subdegree_numeral [simp]: "subdegree (numeral n) = 0"
  5.1039 +  by (simp add: numeral_fps_const)
  5.1040 +
  5.1041 +lemma fps_of_nat: "fps_const (of_nat c) = of_nat c"
  5.1042 +  by (induction c) (simp_all add: fps_const_add [symmetric] del: fps_const_add)
  5.1043 +
  5.1044 +lemma fps_of_int: "fps_const (of_int c) = of_int c"
  5.1045 +  by (induction c) (simp_all add: fps_const_minus [symmetric] fps_of_nat fps_const_neg [symmetric] 
  5.1046 +                             del: fps_const_minus fps_const_neg)
  5.1047 +
  5.1048 +lemma fps_nth_of_nat [simp]:
  5.1049 +  "(of_nat c) $ n = (if n=0 then of_nat c else 0)"
  5.1050 +  by (simp add: fps_of_nat[symmetric])
  5.1051 +
  5.1052 +lemma fps_nth_of_int [simp]:
  5.1053 +  "(of_int c) $ n = (if n=0 then of_int c else 0)"
  5.1054 +  by (simp add: fps_of_int[symmetric])
  5.1055 +
  5.1056 +lemma fps_mult_of_nat_nth [simp]:
  5.1057 +  shows "(of_nat k * f) $ n = of_nat k * f$n"
  5.1058 +  and   "(f * of_nat k ) $ n = f$n * of_nat k"
  5.1059 +  by    (simp_all add: fps_of_nat[symmetric])
  5.1060 +
  5.1061 +lemma fps_mult_of_int_nth [simp]:
  5.1062 +  shows "(of_int k * f) $ n = of_int k * f$n"
  5.1063 +  and   "(f * of_int k ) $ n = f$n * of_int k"
  5.1064 +  by    (simp_all add: fps_of_int[symmetric])
  5.1065 +
  5.1066 +lemma numeral_neq_fps_zero [simp]: "(numeral f :: 'a :: field_char_0 fps) \<noteq> 0"
  5.1067 +proof
  5.1068 +  assume "numeral f = (0 :: 'a fps)"
  5.1069 +  from arg_cong[of _ _ "\<lambda>F. F $ 0", OF this] show False by simp
  5.1070 +qed 
  5.1071 +
  5.1072 +lemma subdegree_power_ge:
  5.1073 +  "f^n \<noteq> 0 \<Longrightarrow> subdegree (f^n) \<ge> n * subdegree f"
  5.1074 +proof (induct n)
  5.1075 +  case (Suc n) thus ?case using fps_mult_subdegree_ge by fastforce
  5.1076 +qed simp
  5.1077 +
  5.1078 +lemma fps_pow_nth_below_subdegree:
  5.1079 +  "k < n * subdegree f \<Longrightarrow> (f^n) $ k = 0"
  5.1080 +proof (cases "f^n = 0")
  5.1081 +  case False
  5.1082 +  assume "k < n * subdegree f"
  5.1083 +  with False have "k < subdegree (f^n)" using subdegree_power_ge[of f n] by simp
  5.1084 +  thus "(f^n) $ k = 0" by auto
  5.1085 +qed simp
  5.1086 +
  5.1087 +lemma fps_pow_base [simp]:
  5.1088 +  "(f ^ n) $ (n * subdegree f) = (f $ subdegree f) ^ n"
  5.1089 +proof (induct n)
  5.1090 +  case (Suc n)
  5.1091 +  show ?case
  5.1092 +  proof (cases "Suc n * subdegree f < subdegree f + subdegree (f^n)")
  5.1093 +    case True with Suc show ?thesis
  5.1094 +      by (auto simp: fps_mult_nth_eq0 distrib_right)
  5.1095 +  next
  5.1096 +    case False
  5.1097 +    hence "\<forall>i\<in>{Suc (subdegree f)..Suc n * subdegree f - subdegree (f ^ n)}.
  5.1098 +            f ^ n $ (Suc n * subdegree f - i) = 0"
  5.1099 +     by (auto simp: fps_pow_nth_below_subdegree)
  5.1100 +   with False Suc show ?thesis
  5.1101 +      using fps_mult_nth_conv_inside_subdegrees[of f "f^n" "Suc n * subdegree f"]
  5.1102 +            sum_head_Suc[of
  5.1103 +              "subdegree f"
  5.1104 +              "Suc n * subdegree f - subdegree (f ^ n)"
  5.1105 +              "\<lambda>i. f $ i * f ^ n $ (Suc n * subdegree f - i)"
  5.1106 +            ]
  5.1107 +      by    simp
  5.1108 +  qed
  5.1109 +qed simp
  5.1110 +
  5.1111 +lemma subdegree_power_eqI:
  5.1112 +  fixes f :: "'a::semiring_1 fps"
  5.1113 +  shows "(f $ subdegree f) ^ n \<noteq> 0 \<Longrightarrow> subdegree (f ^ n) = n * subdegree f"
  5.1114 +proof (induct n)
  5.1115 +  case (Suc n)
  5.1116 +  from Suc have 1: "subdegree (f ^ n) = n * subdegree f" by fastforce
  5.1117 +  with Suc(2) have "f $ subdegree f * f ^ n $ subdegree (f ^ n) \<noteq> 0" by simp
  5.1118 +  with 1 show ?case using subdegree_mult'[of f "f^n"] by simp
  5.1119 +qed simp
  5.1120  
  5.1121  lemma subdegree_power [simp]:
  5.1122 -  "subdegree ((f :: ('a :: ring_1_no_zero_divisors) fps) ^ n) = n * subdegree f"
  5.1123 +  "subdegree ((f :: ('a :: semiring_1_no_zero_divisors) fps) ^ n) = n * subdegree f"
  5.1124    by (cases "f = 0"; induction n) simp_all
  5.1125  
  5.1126 -lemma subdegree_uminus [simp]:
  5.1127 -  "subdegree (-(f::('a::group_add) fps)) = subdegree f"
  5.1128 -  by (simp add: subdegree_def)
  5.1129 -
  5.1130 -lemma subdegree_minus_commute [simp]:
  5.1131 -  "subdegree (f-(g::('a::group_add) fps)) = subdegree (g - f)"
  5.1132 -proof -
  5.1133 -  have "f - g = -(g - f)" by simp
  5.1134 -  also have "subdegree ... = subdegree (g - f)" by (simp only: subdegree_uminus)
  5.1135 -  finally show ?thesis .
  5.1136 -qed
  5.1137 -
  5.1138 -lemma subdegree_add_ge:
  5.1139 -  assumes "f \<noteq> -(g :: ('a :: {group_add}) fps)"
  5.1140 -  shows   "subdegree (f + g) \<ge> min (subdegree f) (subdegree g)"
  5.1141 -proof (rule subdegree_geI)
  5.1142 -  from assms show "f + g \<noteq> 0" by (subst (asm) eq_neg_iff_add_eq_0)
  5.1143 -next
  5.1144 -  fix i assume "i < min (subdegree f) (subdegree g)"
  5.1145 -  hence "f $ i = 0" and "g $ i = 0" by auto
  5.1146 -  thus "(f + g) $ i = 0" by force
  5.1147 -qed
  5.1148 -
  5.1149 -lemma subdegree_add_eq1:
  5.1150 +
  5.1151 +subsection \<open>The efps_Xtractor series fps_X\<close>
  5.1152 +
  5.1153 +lemma minus_one_power_iff: "(- (1::'a::ring_1)) ^ n = (if even n then 1 else - 1)"
  5.1154 +  by (induct n) auto
  5.1155 +
  5.1156 +definition "fps_X = Abs_fps (\<lambda>n. if n = 1 then 1 else 0)"
  5.1157 +
  5.1158 +lemma subdegree_fps_X [simp]: "subdegree (fps_X :: ('a :: zero_neq_one) fps) = 1"
  5.1159 +  by (auto intro!: subdegreeI simp: fps_X_def)
  5.1160 +
  5.1161 +lemma fps_X_mult_nth [simp]:
  5.1162 +  fixes f :: "'a::{comm_monoid_add,mult_zero,monoid_mult} fps"
  5.1163 +  shows "(fps_X * f) $ n = (if n = 0 then 0 else f $ (n - 1))"
  5.1164 +proof (cases n)
  5.1165 +  case (Suc m)
  5.1166 +  moreover have "(fps_X * f) $ Suc m = f $ (Suc m - 1)"
  5.1167 +  proof (cases m)
  5.1168 +    case 0 thus ?thesis using fps_mult_nth_1[of "fps_X" f] by (simp add: fps_X_def)
  5.1169 +  next
  5.1170 +    case (Suc k) thus ?thesis by (simp add: fps_mult_nth fps_X_def sum_head_Suc)
  5.1171 +  qed
  5.1172 +  ultimately show ?thesis by simp
  5.1173 +qed (simp add: fps_X_def)
  5.1174 +
  5.1175 +lemma fps_X_mult_right_nth [simp]:
  5.1176 +  fixes a :: "'a::{comm_monoid_add,mult_zero,monoid_mult} fps"
  5.1177 +  shows "(a * fps_X) $ n = (if n = 0 then 0 else a $ (n - 1))"
  5.1178 +proof (cases n)
  5.1179 +  case (Suc m)
  5.1180 +  moreover have "(a * fps_X) $ Suc m = a $ (Suc m - 1)"
  5.1181 +  proof (cases m)
  5.1182 +    case 0 thus ?thesis using fps_mult_nth_1[of a "fps_X"] by (simp add: fps_X_def)
  5.1183 +  next
  5.1184 +    case (Suc k)
  5.1185 +    hence "(a * fps_X) $ Suc m = (\<Sum>i=0..k. a$i * fps_X$(Suc m - i)) + a$(Suc k)"
  5.1186 +      by (simp add: fps_mult_nth fps_X_def)
  5.1187 +    moreover have "\<forall>i\<in>{0..k}. a$i * fps_X$(Suc m - i) = 0" by (auto simp: Suc fps_X_def)
  5.1188 +    ultimately show ?thesis by (simp add: Suc)
  5.1189 +  qed
  5.1190 +  ultimately show ?thesis by simp
  5.1191 +qed (simp add: fps_X_def)
  5.1192 +
  5.1193 +lemma fps_mult_fps_X_commute:
  5.1194 +  fixes a :: "'a::{comm_monoid_add,mult_zero,monoid_mult} fps"
  5.1195 +  shows "fps_X * a = a * fps_X" 
  5.1196 +  by (simp add: fps_eq_iff)
  5.1197 +
  5.1198 +lemma fps_mult_fps_X_power_commute: "fps_X ^ k * a = a * fps_X ^ k"
  5.1199 +proof (induct k)
  5.1200 +  case (Suc k)
  5.1201 +  hence "fps_X ^ Suc k * a = a * fps_X * fps_X ^ k"
  5.1202 +    by (simp add: mult.assoc fps_mult_fps_X_commute[symmetric])
  5.1203 +  thus ?case by (simp add: mult.assoc)
  5.1204 +qed simp
  5.1205 +
  5.1206 +lemma fps_subdegree_mult_fps_X:
  5.1207 +  fixes   f :: "'a::{comm_monoid_add,mult_zero,monoid_mult} fps"
  5.1208 +  assumes "f \<noteq> 0"
  5.1209 +  shows   "subdegree (fps_X * f) = subdegree f + 1"
  5.1210 +  and     "subdegree (f * fps_X) = subdegree f + 1"
  5.1211 +proof-
  5.1212 +  show "subdegree (fps_X * f) = subdegree f + 1"
  5.1213 +  proof (intro subdegreeI)
  5.1214 +    fix i :: nat assume i: "i < subdegree f + 1"
  5.1215 +    show "(fps_X * f) $ i = 0"
  5.1216 +    proof (cases "i=0")
  5.1217 +      case False with i show ?thesis by (simp add: nth_less_subdegree_zero)
  5.1218 +    next
  5.1219 +      case True thus ?thesis using fps_X_mult_nth[of f i] by simp
  5.1220 +    qed
  5.1221 +  qed (simp add: assms)
  5.1222 +  thus "subdegree (f * fps_X) = subdegree f + 1"
  5.1223 +    by (simp add: fps_mult_fps_X_commute)
  5.1224 +qed
  5.1225 +
  5.1226 +lemma fps_mult_fps_X_nonzero:
  5.1227 +  fixes   f :: "'a::{comm_monoid_add,mult_zero,monoid_mult} fps"
  5.1228    assumes "f \<noteq> 0"
  5.1229 -  assumes "subdegree f < subdegree (g :: ('a :: {group_add}) fps)"
  5.1230 -  shows   "subdegree (f + g) = subdegree f"
  5.1231 -proof (rule antisym[OF subdegree_leI])
  5.1232 -  from assms show "subdegree (f + g) \<ge> subdegree f"
  5.1233 -    by (intro order.trans[OF min.boundedI subdegree_add_ge]) auto
  5.1234 -  from assms have "f $ subdegree f \<noteq> 0" "g $ subdegree f = 0" by auto
  5.1235 -  thus "(f + g) $ subdegree f \<noteq> 0" by simp
  5.1236 -qed
  5.1237 -
  5.1238 -lemma subdegree_add_eq2:
  5.1239 -  assumes "g \<noteq> 0"
  5.1240 -  assumes "subdegree g < subdegree (f :: ('a :: {ab_group_add}) fps)"
  5.1241 -  shows   "subdegree (f + g) = subdegree g"
  5.1242 -  using subdegree_add_eq1[OF assms] by (simp add: add.commute)
  5.1243 -
  5.1244 -lemma subdegree_diff_eq1:
  5.1245 +  shows   "fps_X * f \<noteq> 0"
  5.1246 +  and     "f * fps_X \<noteq> 0"
  5.1247 +  using   assms fps_subdegree_mult_fps_X[of f]
  5.1248 +          fps_nonzero_subdegree_nonzeroI[of "fps_X * f"]
  5.1249 +          fps_nonzero_subdegree_nonzeroI[of "f * fps_X"]
  5.1250 +  by      auto
  5.1251 +
  5.1252 +lemma fps_mult_fps_X_power_nonzero:
  5.1253 +  assumes "f \<noteq> 0"
  5.1254 +  shows   "fps_X ^ n * f \<noteq> 0"
  5.1255 +  and     "f * fps_X ^ n \<noteq> 0"
  5.1256 +proof -
  5.1257 +  show "fps_X ^ n * f \<noteq> 0"
  5.1258 +    by (induct n) (simp_all add: assms mult.assoc fps_mult_fps_X_nonzero(1))
  5.1259 +  thus "f * fps_X ^ n \<noteq> 0"
  5.1260 +    by (simp add: fps_mult_fps_X_power_commute)
  5.1261 +qed
  5.1262 +
  5.1263 +lemma fps_X_power_iff: "fps_X ^ n = Abs_fps (\<lambda>m. if m = n then 1 else 0)"
  5.1264 +  by (induction n) (auto simp: fps_eq_iff)
  5.1265 +
  5.1266 +lemma fps_X_nth[simp]: "fps_X$n = (if n = 1 then 1 else 0)"
  5.1267 +  by (simp add: fps_X_def)
  5.1268 +
  5.1269 +lemma fps_X_power_nth[simp]: "(fps_X^k) $n = (if n = k then 1 else 0)"
  5.1270 +  by (simp add: fps_X_power_iff)
  5.1271 +
  5.1272 +lemma fps_X_power_subdegree: "subdegree (fps_X^n) = n"
  5.1273 +  by (auto intro: subdegreeI)
  5.1274 +
  5.1275 +lemma fps_X_power_mult_nth:
  5.1276 +  "(fps_X^k * f) $ n = (if n < k then 0 else f $ (n - k))"
  5.1277 +  by  (cases "n<k")
  5.1278 +      (simp_all add: fps_mult_nth_conv_upto_subdegree_left fps_X_power_subdegree sum_head_Suc)
  5.1279 +
  5.1280 +lemma fps_X_power_mult_right_nth:
  5.1281 +  "(f * fps_X^k) $ n = (if n < k then 0 else f $ (n - k))"
  5.1282 +  using fps_mult_fps_X_power_commute[of k f] fps_X_power_mult_nth[of k f] by simp
  5.1283 +
  5.1284 +lemma fps_subdegree_mult_fps_X_power:
  5.1285    assumes "f \<noteq> 0"
  5.1286 -  assumes "subdegree f < subdegree (g :: ('a :: {ab_group_add}) fps)"
  5.1287 -  shows   "subdegree (f - g) = subdegree f"
  5.1288 -  using subdegree_add_eq1[of f "-g"] assms by (simp add: add.commute)
  5.1289 -
  5.1290 -lemma subdegree_diff_eq2:
  5.1291 -  assumes "g \<noteq> 0"
  5.1292 -  assumes "subdegree g < subdegree (f :: ('a :: {ab_group_add}) fps)"
  5.1293 -  shows   "subdegree (f - g) = subdegree g"
  5.1294 -  using subdegree_add_eq2[of "-g" f] assms by (simp add: add.commute)
  5.1295 -
  5.1296 -lemma subdegree_diff_ge [simp]:
  5.1297 -  assumes "f \<noteq> (g :: ('a :: {group_add}) fps)"
  5.1298 -  shows   "subdegree (f - g) \<ge> min (subdegree f) (subdegree g)"
  5.1299 -  using assms subdegree_add_ge[of f "-g"] by simp
  5.1300 -
  5.1301 -
  5.1302 +  shows   "subdegree (fps_X ^ n * f) = subdegree f + n"
  5.1303 +  and     "subdegree (f * fps_X ^ n) = subdegree f + n"
  5.1304 +proof -
  5.1305 +  from assms show "subdegree (fps_X ^ n * f) = subdegree f + n"
  5.1306 +    by (induct n)
  5.1307 +       (simp_all add: algebra_simps fps_subdegree_mult_fps_X(1) fps_mult_fps_X_power_nonzero(1))
  5.1308 +  thus "subdegree (f * fps_X ^ n) = subdegree f + n"
  5.1309 +    by (simp add: fps_mult_fps_X_power_commute)
  5.1310 +qed
  5.1311 +
  5.1312 +lemma fps_mult_fps_X_plus_1_nth:
  5.1313 +  "((1+fps_X)*a) $n = (if n = 0 then (a$n :: 'a::semiring_1) else a$n + a$(n - 1))"
  5.1314 +proof (cases n)
  5.1315 +  case 0
  5.1316 +  then show ?thesis
  5.1317 +    by (simp add: fps_mult_nth)
  5.1318 +next
  5.1319 +  case (Suc m)
  5.1320 +  have "((1 + fps_X)*a) $ n = sum (\<lambda>i. (1 + fps_X) $ i * a $ (n - i)) {0..n}"
  5.1321 +    by (simp add: fps_mult_nth)
  5.1322 +  also have "\<dots> = sum (\<lambda>i. (1+fps_X)$i * a$(n-i)) {0.. 1}"
  5.1323 +    unfolding Suc by (rule sum.mono_neutral_right) auto
  5.1324 +  also have "\<dots> = (if n = 0 then a$n else a$n + a$(n - 1))"
  5.1325 +    by (simp add: Suc)
  5.1326 +  finally show ?thesis .
  5.1327 +qed
  5.1328 +
  5.1329 +lemma fps_mult_right_fps_X_plus_1_nth:
  5.1330 +  fixes a :: "'a :: semiring_1 fps"
  5.1331 +  shows "(a*(1+fps_X)) $ n = (if n = 0 then a$n else a$n + a$(n - 1))"
  5.1332 +  using fps_mult_fps_X_plus_1_nth
  5.1333 +  by    (simp add: distrib_left fps_mult_fps_X_commute distrib_right)
  5.1334 +
  5.1335 +lemma fps_X_neq_fps_const [simp]: "(fps_X :: 'a :: zero_neq_one fps) \<noteq> fps_const c"
  5.1336 +proof
  5.1337 +  assume "(fps_X::'a fps) = fps_const (c::'a)"
  5.1338 +  hence "fps_X$1 = (fps_const (c::'a))$1" by (simp only:)
  5.1339 +  thus False by auto
  5.1340 +qed
  5.1341 +
  5.1342 +lemma fps_X_neq_zero [simp]: "(fps_X :: 'a :: zero_neq_one fps) \<noteq> 0"
  5.1343 +  by (simp only: fps_const_0_eq_0[symmetric] fps_X_neq_fps_const) simp
  5.1344 +
  5.1345 +lemma fps_X_neq_one [simp]: "(fps_X :: 'a :: zero_neq_one fps) \<noteq> 1"
  5.1346 +  by (simp only: fps_const_1_eq_1[symmetric] fps_X_neq_fps_const) simp
  5.1347 +
  5.1348 +lemma fps_X_neq_numeral [simp]: "fps_X \<noteq> numeral c"
  5.1349 +  by (simp only: numeral_fps_const fps_X_neq_fps_const) simp
  5.1350 +
  5.1351 +lemma fps_X_pow_eq_fps_X_pow_iff [simp]: "fps_X ^ m = fps_X ^ n \<longleftrightarrow> m = n"
  5.1352 +proof
  5.1353 +  assume "(fps_X :: 'a fps) ^ m = fps_X ^ n"
  5.1354 +  hence "(fps_X :: 'a fps) ^ m $ m = fps_X ^ n $ m" by (simp only:)
  5.1355 +  thus "m = n" by (simp split: if_split_asm)
  5.1356 +qed simp_all
  5.1357  
  5.1358  
  5.1359  subsection \<open>Shifting and slicing\<close>
  5.1360 @@ -702,65 +1037,287 @@
  5.1361  lemma fps_shift_numeral: "fps_shift n (numeral c) = (if n = 0 then numeral c else 0)"
  5.1362    by (simp add: numeral_fps_const fps_shift_fps_const)
  5.1363  
  5.1364 +lemma fps_shift_fps_X [simp]:
  5.1365 +  "n \<ge> 1 \<Longrightarrow> fps_shift n fps_X = (if n = 1 then 1 else 0)"
  5.1366 +  by (intro fps_ext) (auto simp: fps_X_def)
  5.1367 +
  5.1368  lemma fps_shift_fps_X_power [simp]:
  5.1369 -  "n \<le> m \<Longrightarrow> fps_shift n (fps_X ^ m) = (fps_X ^ (m - n) ::'a::comm_ring_1 fps)"
  5.1370 -  by (intro fps_ext) (auto simp: fps_shift_def )
  5.1371 -
  5.1372 -lemma fps_shift_times_fps_X_power:
  5.1373 -  "n \<le> subdegree f \<Longrightarrow> fps_shift n f * fps_X ^ n = (f :: 'a :: comm_ring_1 fps)"
  5.1374 -  by (intro fps_ext) (auto simp: fps_X_power_mult_right_nth nth_less_subdegree_zero)
  5.1375 -
  5.1376 -lemma fps_shift_times_fps_X_power' [simp]:
  5.1377 -  "fps_shift n (f * fps_X^n) = (f :: 'a :: comm_ring_1 fps)"
  5.1378 -  by (intro fps_ext) (auto simp: fps_X_power_mult_right_nth nth_less_subdegree_zero)
  5.1379 -
  5.1380 -lemma fps_shift_times_fps_X_power'':
  5.1381 -  "m \<le> n \<Longrightarrow> fps_shift n (f * fps_X^m) = fps_shift (n - m) (f :: 'a :: comm_ring_1 fps)"
  5.1382 -  by (intro fps_ext) (auto simp: fps_X_power_mult_right_nth nth_less_subdegree_zero)
  5.1383 +  "n \<le> m \<Longrightarrow> fps_shift n (fps_X ^ m) = fps_X ^ (m - n)"
  5.1384 + by (intro fps_ext) auto
  5.1385  
  5.1386  lemma fps_shift_subdegree [simp]:
  5.1387 -  "n \<le> subdegree f \<Longrightarrow> subdegree (fps_shift n f) = subdegree (f :: 'a :: comm_ring_1 fps) - n"
  5.1388 -  by (cases "f = 0") (force intro: nth_less_subdegree_zero subdegreeI)+
  5.1389 -
  5.1390 -lemma subdegree_decompose:
  5.1391 -  "f = fps_shift (subdegree f) f * fps_X ^ subdegree (f :: ('a :: comm_ring_1) fps)"
  5.1392 -  by (rule fps_ext) (auto simp: fps_X_power_mult_right_nth)
  5.1393 -
  5.1394 -lemma subdegree_decompose':
  5.1395 -  "n \<le> subdegree (f :: ('a :: comm_ring_1) fps) \<Longrightarrow> f = fps_shift n f * fps_X^n"
  5.1396 -  by (rule fps_ext) (auto simp: fps_X_power_mult_right_nth intro!: nth_less_subdegree_zero)
  5.1397 +  "n \<le> subdegree f \<Longrightarrow> subdegree (fps_shift n f) = subdegree f - n"
  5.1398 +  by (cases "f=0") (auto intro: subdegreeI simp: nth_less_subdegree_zero)
  5.1399  
  5.1400  lemma fps_shift_fps_shift:
  5.1401    "fps_shift (m + n) f = fps_shift m (fps_shift n f)"
  5.1402    by (rule fps_ext) (simp add: add_ac)
  5.1403  
  5.1404 +lemma fps_shift_fps_shift_reorder:
  5.1405 +  "fps_shift m (fps_shift n f) = fps_shift n (fps_shift m f)"
  5.1406 +  using fps_shift_fps_shift[of m n f] fps_shift_fps_shift[of n m f] by (simp add: add.commute)
  5.1407 +
  5.1408 +lemma fps_shift_rev_shift:
  5.1409 +  "m \<le> n \<Longrightarrow> fps_shift n (Abs_fps (\<lambda>k. if k<m then 0 else f $ (k-m))) = fps_shift (n-m) f"
  5.1410 +  "m > n \<Longrightarrow> fps_shift n (Abs_fps (\<lambda>k. if k<m then 0 else f $ (k-m))) =
  5.1411 +    Abs_fps (\<lambda>k. if k<m-n then 0 else f $ (k-(m-n)))"
  5.1412 +proof -
  5.1413 +  assume "m \<le> n"
  5.1414 +  thus "fps_shift n (Abs_fps (\<lambda>k. if k<m then 0 else f $ (k-m))) = fps_shift (n-m) f"
  5.1415 +    by (intro fps_ext) auto
  5.1416 +next
  5.1417 +  assume mn: "m > n"
  5.1418 +  hence "\<And>k. k \<ge> m-n \<Longrightarrow> k+n-m = k - (m-n)" by auto
  5.1419 +  thus
  5.1420 +    "fps_shift n (Abs_fps (\<lambda>k. if k<m then 0 else f $ (k-m))) =
  5.1421 +      Abs_fps (\<lambda>k. if k<m-n then 0 else f $ (k-(m-n)))"
  5.1422 +    by (intro fps_ext) auto
  5.1423 +qed
  5.1424 +
  5.1425  lemma fps_shift_add:
  5.1426    "fps_shift n (f + g) = fps_shift n f + fps_shift n g"
  5.1427    by (simp add: fps_eq_iff)
  5.1428  
  5.1429 +lemma fps_shift_diff:
  5.1430 +  "fps_shift n (f - g) = fps_shift n f - fps_shift n g"
  5.1431 +  by (auto intro: fps_ext)
  5.1432 +
  5.1433 +lemma fps_shift_uminus:
  5.1434 +  "fps_shift n (-f) = - fps_shift n f"
  5.1435 +  by (auto intro: fps_ext)
  5.1436 +
  5.1437  lemma fps_shift_mult:
  5.1438 -  assumes "n \<le> subdegree (g :: 'b :: {comm_ring_1} fps)"
  5.1439 -  shows   "fps_shift n (h*g) = h * fps_shift n g"
  5.1440 -proof -
  5.1441 -  from assms have "g = fps_shift n g * fps_X^n" by (rule subdegree_decompose')
  5.1442 -  also have "h * ... = (h * fps_shift n g) * fps_X^n" by simp
  5.1443 -  also have "fps_shift n ... = h * fps_shift n g" by simp
  5.1444 -  finally show ?thesis .
  5.1445 +  assumes "n \<le> subdegree (g :: 'b :: {comm_monoid_add, mult_zero} fps)"
  5.1446 +  shows "fps_shift n (h*g) = h * fps_shift n g"
  5.1447 +proof-
  5.1448 +  have case1: "\<And>a b::'b fps. 1 \<le> subdegree b \<Longrightarrow> fps_shift 1 (a*b) = a * fps_shift 1 b"
  5.1449 +  proof (rule fps_ext)
  5.1450 +    fix a b :: "'b fps"
  5.1451 +    and n :: nat
  5.1452 +    assume b: "1 \<le> subdegree b"
  5.1453 +    have "\<And>i. i \<le> n \<Longrightarrow> n + 1 - i = (n-i) + 1"
  5.1454 +      by (simp add: algebra_simps)
  5.1455 +    with b show "fps_shift 1 (a*b) $ n = (a * fps_shift 1 b) $ n"
  5.1456 +      by (simp add: fps_mult_nth nth_less_subdegree_zero)
  5.1457 +  qed
  5.1458 +  have "n \<le> subdegree g \<Longrightarrow> fps_shift n (h*g) = h * fps_shift n g"
  5.1459 +  proof (induct n)
  5.1460 +    case (Suc n)
  5.1461 +    have "fps_shift (Suc n) (h*g) = fps_shift 1 (fps_shift n (h*g))"
  5.1462 +      by (simp add: fps_shift_fps_shift[symmetric])
  5.1463 +    also have "\<dots> = h * (fps_shift 1 (fps_shift n g))"
  5.1464 +      using Suc case1 by force
  5.1465 +    finally show ?case by (simp add: fps_shift_fps_shift[symmetric])
  5.1466 +  qed simp
  5.1467 +  with assms show ?thesis by fast
  5.1468 +qed
  5.1469 +
  5.1470 +lemma fps_shift_mult_right_noncomm:
  5.1471 +  assumes "n \<le> subdegree (g :: 'b :: {comm_monoid_add, mult_zero} fps)"
  5.1472 +  shows "fps_shift n (g*h) = fps_shift n g * h"
  5.1473 +proof-
  5.1474 +  have case1: "\<And>a b::'b fps. 1 \<le> subdegree a \<Longrightarrow> fps_shift 1 (a*b) = fps_shift 1 a * b"
  5.1475 +  proof (rule fps_ext)
  5.1476 +    fix a b :: "'b fps"
  5.1477 +    and n :: nat
  5.1478 +    assume "1 \<le> subdegree a"
  5.1479 +    hence "fps_shift 1 (a*b) $ n = (\<Sum>i=Suc 0..Suc n. a$i * b$(n+1-i))"
  5.1480 +      using sum_head_Suc[of 0 "n+1" "\<lambda>i. a$i * b$(n+1-i)"]
  5.1481 +      by    (simp add: fps_mult_nth nth_less_subdegree_zero)
  5.1482 +    thus "fps_shift 1 (a*b) $ n = (fps_shift 1 a * b) $ n"
  5.1483 +      using sum_shift_bounds_cl_Suc_ivl[of "\<lambda>i. a$i * b$(n+1-i)" 0 n]
  5.1484 +      by    (simp add: fps_mult_nth)
  5.1485 +  qed
  5.1486 +  have "n \<le> subdegree g \<Longrightarrow> fps_shift n (g*h) = fps_shift n g * h"
  5.1487 +  proof (induct n)
  5.1488 +    case (Suc n)
  5.1489 +    have "fps_shift (Suc n) (g*h) = fps_shift 1 (fps_shift n (g*h))"
  5.1490 +      by (simp add: fps_shift_fps_shift[symmetric])
  5.1491 +    also have "\<dots> = (fps_shift 1 (fps_shift n g)) * h"
  5.1492 +      using Suc case1 by force
  5.1493 +    finally show ?case by (simp add: fps_shift_fps_shift[symmetric])
  5.1494 +  qed simp
  5.1495 +  with assms show ?thesis by fast
  5.1496  qed
  5.1497  
  5.1498  lemma fps_shift_mult_right:
  5.1499 -  assumes "n \<le> subdegree (g :: 'b :: {comm_ring_1} fps)"
  5.1500 +  assumes "n \<le> subdegree (g :: 'b :: comm_semiring_0 fps)"
  5.1501    shows   "fps_shift n (g*h) = h * fps_shift n g"
  5.1502 -  by (subst mult.commute, subst fps_shift_mult) (simp_all add: assms)
  5.1503 -
  5.1504 -lemma nth_subdegree_zero_iff [simp]: "f $ subdegree f = 0 \<longleftrightarrow> f = 0"
  5.1505 -  by (cases "f = 0") auto
  5.1506 +  by      (simp add: assms fps_shift_mult_right_noncomm mult.commute)
  5.1507 +
  5.1508 +lemma fps_shift_mult_both:
  5.1509 +  fixes   f g :: "'a::{comm_monoid_add, mult_zero} fps"
  5.1510 +  assumes "m \<le> subdegree f" "n \<le> subdegree g"
  5.1511 +  shows   "fps_shift m f * fps_shift n g = fps_shift (m+n) (f*g)"
  5.1512 +  using   assms
  5.1513 +  by      (simp add: fps_shift_mult fps_shift_mult_right_noncomm fps_shift_fps_shift)
  5.1514  
  5.1515  lemma fps_shift_subdegree_zero_iff [simp]:
  5.1516    "fps_shift (subdegree f) f = 0 \<longleftrightarrow> f = 0"
  5.1517    by (subst (1) nth_subdegree_zero_iff[symmetric], cases "f = 0")
  5.1518       (simp_all del: nth_subdegree_zero_iff)
  5.1519  
  5.1520 +lemma fps_shift_times_fps_X:
  5.1521 +  fixes f g :: "'a::{comm_monoid_add,mult_zero,monoid_mult} fps"
  5.1522 +  shows "1 \<le> subdegree f \<Longrightarrow> fps_shift 1 f * fps_X = f"
  5.1523 +  by (intro fps_ext) (simp add: nth_less_subdegree_zero)
  5.1524 +
  5.1525 +lemma fps_shift_times_fps_X' [simp]:
  5.1526 +  fixes f :: "'a::{comm_monoid_add,mult_zero,monoid_mult} fps"
  5.1527 +  shows "fps_shift 1 (f * fps_X) = f"
  5.1528 +  by (intro fps_ext) (simp add: nth_less_subdegree_zero)
  5.1529 +
  5.1530 +lemma fps_shift_times_fps_X'':
  5.1531 +  fixes f :: "'a::{comm_monoid_add,mult_zero,monoid_mult} fps"
  5.1532 +  shows "1 \<le> n \<Longrightarrow> fps_shift n (f * fps_X) = fps_shift (n - 1) f"
  5.1533 +  by (intro fps_ext) (simp add: nth_less_subdegree_zero)
  5.1534 +
  5.1535 +lemma fps_shift_times_fps_X_power:
  5.1536 +  "n \<le> subdegree f \<Longrightarrow> fps_shift n f * fps_X ^ n = f"
  5.1537 +  by (intro fps_ext) (simp add: fps_X_power_mult_right_nth nth_less_subdegree_zero)
  5.1538 +
  5.1539 +lemma fps_shift_times_fps_X_power' [simp]:
  5.1540 +  "fps_shift n (f * fps_X^n) = f"
  5.1541 +  by (intro fps_ext) (simp add: fps_X_power_mult_right_nth nth_less_subdegree_zero)
  5.1542 +
  5.1543 +lemma fps_shift_times_fps_X_power'':
  5.1544 +  "m \<le> n \<Longrightarrow> fps_shift n (f * fps_X^m) = fps_shift (n - m) f"
  5.1545 +  by (intro fps_ext) (simp add: fps_X_power_mult_right_nth nth_less_subdegree_zero)
  5.1546 +
  5.1547 +lemma fps_shift_times_fps_X_power''':
  5.1548 +  "m > n \<Longrightarrow> fps_shift n (f * fps_X^m) = f * fps_X^(m - n)"
  5.1549 +proof (cases "f=0")
  5.1550 +  case False
  5.1551 +  assume m: "m>n"
  5.1552 +  hence "m = n + (m-n)" by auto
  5.1553 +  with False m show ?thesis
  5.1554 +    using power_add[of "fps_X::'a fps" n "m-n"]
  5.1555 +          fps_shift_mult_right_noncomm[of n "f * fps_X^n" "fps_X^(m-n)"]
  5.1556 +    by    (simp add: mult.assoc fps_subdegree_mult_fps_X_power(2))
  5.1557 +qed simp
  5.1558 +
  5.1559 +lemma subdegree_decompose:
  5.1560 +  "f = fps_shift (subdegree f) f * fps_X ^ subdegree f"
  5.1561 +  by (rule fps_ext) (auto simp: fps_X_power_mult_right_nth)
  5.1562 +
  5.1563 +lemma subdegree_decompose':
  5.1564 +  "n \<le> subdegree f \<Longrightarrow> f = fps_shift n f * fps_X^n"
  5.1565 +  by (rule fps_ext) (auto simp: fps_X_power_mult_right_nth intro!: nth_less_subdegree_zero)
  5.1566 +
  5.1567 +instantiation fps :: (zero) unit_factor
  5.1568 +begin
  5.1569 +definition fps_unit_factor_def [simp]:
  5.1570 +  "unit_factor f = fps_shift (subdegree f) f"
  5.1571 +instance ..
  5.1572 +end
  5.1573 +
  5.1574 +lemma fps_unit_factor_zero_iff: "unit_factor (f::'a::zero fps) = 0 \<longleftrightarrow> f = 0"
  5.1575 +  by simp
  5.1576 +
  5.1577 +lemma fps_unit_factor_nth_0: "f \<noteq> 0 \<Longrightarrow> unit_factor f $ 0 \<noteq> 0"
  5.1578 +  by simp
  5.1579 +
  5.1580 +lemma fps_X_unit_factor: "unit_factor (fps_X :: 'a :: zero_neq_one fps) = 1"
  5.1581 + by (intro fps_ext) auto
  5.1582 +
  5.1583 +lemma fps_X_power_unit_factor: "unit_factor (fps_X ^ n) = 1"
  5.1584 +proof-
  5.1585 +  define X :: "'a fps" where "X \<equiv> fps_X"
  5.1586 +  hence "unit_factor (X^n) = fps_shift n (X^n)"
  5.1587 +    by (simp add: fps_X_power_subdegree)
  5.1588 +  moreover have "fps_shift n (X^n) = 1"
  5.1589 +    by (auto intro: fps_ext simp: fps_X_power_iff X_def)
  5.1590 +  ultimately show ?thesis by (simp add: X_def)
  5.1591 +qed
  5.1592 +
  5.1593 +lemma fps_unit_factor_decompose:
  5.1594 +  "f = unit_factor f * fps_X ^ subdegree f"
  5.1595 +  by (simp add: subdegree_decompose)
  5.1596 +
  5.1597 +lemma fps_unit_factor_decompose':
  5.1598 +  "f = fps_X ^ subdegree f * unit_factor f"
  5.1599 +  using fps_unit_factor_decompose by (simp add: fps_mult_fps_X_power_commute)
  5.1600 +
  5.1601 +lemma fps_unit_factor_uminus:
  5.1602 +  "unit_factor (-f) = - unit_factor (f::'a::group_add fps)"
  5.1603 +  by    (simp add: fps_shift_uminus)
  5.1604 +
  5.1605 +lemma fps_unit_factor_shift:
  5.1606 +  assumes "n \<le> subdegree f"
  5.1607 +  shows   "unit_factor (fps_shift n f) = unit_factor f"
  5.1608 +  by      (simp add: assms fps_shift_fps_shift[symmetric])
  5.1609 +
  5.1610 +lemma fps_unit_factor_mult_fps_X:
  5.1611 +  fixes f :: "'a::{comm_monoid_add,monoid_mult,mult_zero} fps"
  5.1612 +  shows "unit_factor (fps_X * f) = unit_factor f"
  5.1613 +  and   "unit_factor (f * fps_X) = unit_factor f"
  5.1614 +proof -
  5.1615 +  show "unit_factor (fps_X * f) = unit_factor f"
  5.1616 +    by (cases "f=0") (auto intro: fps_ext simp: fps_subdegree_mult_fps_X(1))
  5.1617 +  thus "unit_factor (f * fps_X) = unit_factor f" by (simp add: fps_mult_fps_X_commute)
  5.1618 +qed
  5.1619 +
  5.1620 +lemma fps_unit_factor_mult_fps_X_power:
  5.1621 +  shows "unit_factor (fps_X ^ n * f) = unit_factor f"
  5.1622 +  and   "unit_factor (f * fps_X ^ n) = unit_factor f"
  5.1623 +proof -
  5.1624 +  show "unit_factor (fps_X ^ n * f) = unit_factor f"
  5.1625 +  proof (induct n)
  5.1626 +    case (Suc m) thus ?case
  5.1627 +      using fps_unit_factor_mult_fps_X(1)[of "fps_X ^ m * f"] by (simp add: mult.assoc)
  5.1628 +  qed simp
  5.1629 +  thus "unit_factor (f * fps_X ^ n) = unit_factor f"
  5.1630 +    by (simp add: fps_mult_fps_X_power_commute)
  5.1631 +qed
  5.1632 +
  5.1633 +lemma fps_unit_factor_mult_unit_factor:
  5.1634 +  fixes f g :: "'a::{comm_monoid_add,mult_zero} fps"
  5.1635 +  shows "unit_factor (f * unit_factor g) = unit_factor (f * g)"
  5.1636 +  and   "unit_factor (unit_factor f * g) = unit_factor (f * g)"
  5.1637 +proof -
  5.1638 +  show "unit_factor (f * unit_factor g) = unit_factor (f * g)"
  5.1639 +  proof (cases "f*g = 0")
  5.1640 +    case False thus ?thesis
  5.1641 +      using fps_mult_subdegree_ge[of f g] fps_unit_factor_shift[of "subdegree g" "f*g"]
  5.1642 +      by    (simp add: fps_shift_mult)
  5.1643 +  next
  5.1644 +    case True
  5.1645 +    moreover have "f * unit_factor g = fps_shift (subdegree g) (f*g)"
  5.1646 +      by (simp add: fps_shift_mult)
  5.1647 +    ultimately show ?thesis by simp
  5.1648 +  qed
  5.1649 +  show "unit_factor (unit_factor f * g) = unit_factor (f * g)"
  5.1650 +  proof (cases "f*g = 0")
  5.1651 +    case False thus ?thesis
  5.1652 +      using fps_mult_subdegree_ge[of f g] fps_unit_factor_shift[of "subdegree f" "f*g"]
  5.1653 +      by    (simp add: fps_shift_mult_right_noncomm)
  5.1654 +  next
  5.1655 +    case True
  5.1656 +    moreover have "unit_factor f * g = fps_shift (subdegree f) (f*g)"
  5.1657 +      by (simp add: fps_shift_mult_right_noncomm)
  5.1658 +    ultimately show ?thesis by simp
  5.1659 +  qed
  5.1660 +qed
  5.1661 +
  5.1662 +lemma fps_unit_factor_mult_both_unit_factor:
  5.1663 +  fixes f g :: "'a::{comm_monoid_add,mult_zero} fps"
  5.1664 +  shows "unit_factor (unit_factor f * unit_factor g) = unit_factor (f * g)"
  5.1665 +  using fps_unit_factor_mult_unit_factor(1)[of "unit_factor f" g]
  5.1666 +        fps_unit_factor_mult_unit_factor(2)[of f g]
  5.1667 +  by    simp
  5.1668 +
  5.1669 +lemma fps_unit_factor_mult':
  5.1670 +  fixes   f g :: "'a::{comm_monoid_add,mult_zero} fps"
  5.1671 +  assumes "f $ subdegree f * g $ subdegree g \<noteq> 0"
  5.1672 +  shows   "unit_factor (f * g) = unit_factor f * unit_factor g"
  5.1673 +  using   assms
  5.1674 +  by      (simp add: subdegree_mult' fps_shift_mult_both)
  5.1675 +
  5.1676 +lemma fps_unit_factor_mult:
  5.1677 +  fixes f g :: "'a::semiring_no_zero_divisors fps"
  5.1678 +  shows "unit_factor (f * g) = unit_factor f * unit_factor g"
  5.1679 +  using fps_unit_factor_mult'[of f g]
  5.1680 +  by    (cases "f=0 \<or> g=0") auto
  5.1681  
  5.1682  definition "fps_cutoff n f = Abs_fps (\<lambda>i. if i < n then f$i else 0)"
  5.1683  
  5.1684 @@ -774,7 +1331,7 @@
  5.1685    proof (cases "f = 0")
  5.1686      assume "f \<noteq> 0"
  5.1687      with A have "n \<le> subdegree f"
  5.1688 -      by (intro subdegree_geI) (auto simp: fps_eq_iff split: if_split_asm)
  5.1689 +      by (intro subdegree_geI) (simp_all add: fps_eq_iff split: if_split_asm)
  5.1690      thus ?thesis ..
  5.1691    qed simp
  5.1692  qed (auto simp: fps_eq_iff intro: nth_less_subdegree_zero)
  5.1693 @@ -795,13 +1352,28 @@
  5.1694    by (simp add: numeral_fps_const fps_cutoff_fps_const)
  5.1695  
  5.1696  lemma fps_shift_cutoff:
  5.1697 -  "fps_shift n (f :: ('a :: comm_ring_1) fps) * fps_X^n + fps_cutoff n f = f"
  5.1698 +  "fps_shift n f * fps_X^n + fps_cutoff n f = f"
  5.1699    by (simp add: fps_eq_iff fps_X_power_mult_right_nth)
  5.1700  
  5.1701 +lemma fps_shift_cutoff':
  5.1702 +  "fps_X^n * fps_shift n f + fps_cutoff n f = f"
  5.1703 +  by (simp add: fps_eq_iff fps_X_power_mult_nth)
  5.1704 +
  5.1705 +lemma fps_cutoff_left_mult_nth:
  5.1706 +  "k < n \<Longrightarrow> (fps_cutoff n f * g) $ k = (f * g) $ k"
  5.1707 +  by (simp add: fps_mult_nth)
  5.1708 +
  5.1709 +lemma fps_cutoff_right_mult_nth:
  5.1710 +  assumes "k < n"
  5.1711 +  shows   "(f * fps_cutoff n g) $ k = (f * g) $ k"
  5.1712 +proof-
  5.1713 +  from assms have "\<forall>i\<in>{0..k}. fps_cutoff n g $ (k - i) = g $ (k - i)" by auto
  5.1714 +  thus ?thesis by (simp add: fps_mult_nth)
  5.1715 +qed
  5.1716  
  5.1717  subsection \<open>Formal Power series form a metric space\<close>
  5.1718  
  5.1719 -instantiation fps :: (comm_ring_1) dist
  5.1720 +instantiation fps :: ("{minus,zero}") dist
  5.1721  begin
  5.1722  
  5.1723  definition
  5.1724 @@ -810,14 +1382,11 @@
  5.1725  lemma dist_fps_ge0: "dist (a :: 'a fps) b \<ge> 0"
  5.1726    by (simp add: dist_fps_def)
  5.1727  
  5.1728 -lemma dist_fps_sym: "dist (a :: 'a fps) b = dist b a"
  5.1729 -  by (simp add: dist_fps_def)
  5.1730 -
  5.1731  instance ..
  5.1732  
  5.1733  end
  5.1734  
  5.1735 -instantiation fps :: (comm_ring_1) metric_space
  5.1736 +instantiation fps :: (group_add) metric_space
  5.1737  begin
  5.1738  
  5.1739  definition uniformity_fps_def [code del]:
  5.1740 @@ -826,6 +1395,9 @@
  5.1741  definition open_fps_def' [code del]:
  5.1742    "open (U :: 'a fps set) \<longleftrightarrow> (\<forall>x\<in>U. eventually (\<lambda>(x', y). x' = x \<longrightarrow> y \<in> U) uniformity)"
  5.1743  
  5.1744 +lemma dist_fps_sym: "dist (a :: 'a fps) b = dist b a"
  5.1745 +  by (simp add: dist_fps_def)
  5.1746 +
  5.1747  instance
  5.1748  proof
  5.1749    show th: "dist a b = 0 \<longleftrightarrow> a = b" for a b :: "'a fps"
  5.1750 @@ -863,9 +1435,9 @@
  5.1751  
  5.1752  end
  5.1753  
  5.1754 -declare uniformity_Abort[where 'a="'a :: comm_ring_1 fps", code]
  5.1755 -
  5.1756 -lemma open_fps_def: "open (S :: 'a::comm_ring_1 fps set) = (\<forall>a \<in> S. \<exists>r. r >0 \<and> {y. dist y a < r} \<subseteq> S)"
  5.1757 +declare uniformity_Abort[where 'a="'a :: group_add fps", code]
  5.1758 +
  5.1759 +lemma open_fps_def: "open (S :: 'a::group_add fps set) = (\<forall>a \<in> S. \<exists>r. r >0 \<and> {y. dist y a < r} \<subseteq> S)"
  5.1760    unfolding open_dist subset_eq by simp
  5.1761  
  5.1762  text \<open>The infinite sums and justification of the notation in textbooks.\<close>
  5.1763 @@ -902,9 +1474,8 @@
  5.1764      using kp by blast
  5.1765  qed
  5.1766  
  5.1767 -lemma fps_sum_rep_nth: "(sum (\<lambda>i. fps_const(a$i)*fps_X^i) {0..m})$n =
  5.1768 -    (if n \<le> m then a$n else 0::'a::comm_ring_1)"
  5.1769 -  by (auto simp add: fps_sum_nth cond_value_iff cong del: if_weak_cong)
  5.1770 +lemma fps_sum_rep_nth: "(sum (\<lambda>i. fps_const(a$i)*fps_X^i) {0..m})$n = (if n \<le> m then a$n else 0)"
  5.1771 +  by (simp add: fps_sum_nth if_distrib cong del: if_weak_cong)
  5.1772  
  5.1773  lemma fps_notation: "(\<lambda>n. sum (\<lambda>i. fps_const(a$i) * fps_X^i) {0..n}) \<longlonglongrightarrow> a"
  5.1774    (is "?s \<longlonglongrightarrow> a")
  5.1775 @@ -948,121 +1519,463 @@
  5.1776  qed
  5.1777  
  5.1778  
  5.1779 -subsection \<open>Inverses of formal power series\<close>
  5.1780 +subsection \<open>Inverses and division of formal power series\<close>
  5.1781  
  5.1782  declare sum.cong[fundef_cong]
  5.1783  
  5.1784 +fun fps_left_inverse_constructor ::
  5.1785 +  "'a::{comm_monoid_add,times,uminus} fps \<Rightarrow> 'a \<Rightarrow> nat \<Rightarrow> 'a"
  5.1786 +where
  5.1787 +  "fps_left_inverse_constructor f a 0 = a"
  5.1788 +| "fps_left_inverse_constructor f a (Suc n) =
  5.1789 +    - sum (\<lambda>i. fps_left_inverse_constructor f a i * f$(Suc n - i)) {0..n} * a"
  5.1790 +
  5.1791 +\<comment> \<open>This will construct a left inverse for f in case that x * f$0 = 1\<close>
  5.1792 +abbreviation "fps_left_inverse \<equiv> (\<lambda>f x. Abs_fps (fps_left_inverse_constructor f x))"
  5.1793 +
  5.1794 +fun fps_right_inverse_constructor ::
  5.1795 +  "'a::{comm_monoid_add,times,uminus} fps \<Rightarrow> 'a \<Rightarrow> nat \<Rightarrow> 'a"
  5.1796 +where
  5.1797 +  "fps_right_inverse_constructor f a 0 = a"
  5.1798 +| "fps_right_inverse_constructor f a n =
  5.1799 +    - a * sum (\<lambda>i. f$i * fps_right_inverse_constructor f a (n - i)) {1..n}"
  5.1800 +
  5.1801 +\<comment> \<open>This will construct a right inverse for f in case that f$0 * y = 1\<close>
  5.1802 +abbreviation "fps_right_inverse \<equiv> (\<lambda>f y. Abs_fps (fps_right_inverse_constructor f y))"
  5.1803 +
  5.1804  instantiation fps :: ("{comm_monoid_add,inverse,times,uminus}") inverse
  5.1805  begin
  5.1806  
  5.1807 -fun natfun_inverse:: "'a fps \<Rightarrow> nat \<Rightarrow> 'a"
  5.1808 -where
  5.1809 -  "natfun_inverse f 0 = inverse (f$0)"
  5.1810 -| "natfun_inverse f n = - inverse (f$0) * sum (\<lambda>i. f$i * natfun_inverse f (n - i)) {1..n}"
  5.1811 -
  5.1812 -definition fps_inverse_def: "inverse f = (if f $ 0 = 0 then 0 else Abs_fps (natfun_inverse f))"
  5.1813 -
  5.1814 -definition fps_divide_def:
  5.1815 -  "f div g = (if g = 0 then 0 else
  5.1816 -     let n = subdegree g; h = fps_shift n g
  5.1817 -     in  fps_shift n (f * inverse h))"
  5.1818 +\<comment> \<open>For backwards compatibility.\<close>
  5.1819 +abbreviation natfun_inverse:: "'a fps \<Rightarrow> nat \<Rightarrow> 'a"
  5.1820 +  where "natfun_inverse f \<equiv> fps_right_inverse_constructor f (inverse (f$0))"
  5.1821 +
  5.1822 +definition fps_inverse_def: "inverse f = Abs_fps (natfun_inverse f)"
  5.1823 +\<comment> \<open>
  5.1824 +  With scalars from a (possibly non-commutative) ring, this defines a right inverse.
  5.1825 +  Furthermore, if scalars are of class @{class mult_zero} and satisfy
  5.1826 +  condition @{term "inverse 0 = 0"}, then this will evaluate to zero when
  5.1827 +  the zeroth term is zero.
  5.1828 +\<close>
  5.1829 +
  5.1830 +definition fps_divide_def: "f div g = fps_shift (subdegree g) (f * inverse (unit_factor g))"
  5.1831 +\<comment> \<open>
  5.1832 +  If scalars are of class @{class mult_zero} and satisfy condition
  5.1833 +  @{term "inverse 0 = 0"}, then div by zero will equal zero.
  5.1834 +\<close>
  5.1835  
  5.1836  instance ..
  5.1837  
  5.1838  end
  5.1839  
  5.1840 +lemma fps_lr_inverse_0_iff:
  5.1841 +  "(fps_left_inverse f x) $ 0 = 0 \<longleftrightarrow> x = 0"
  5.1842 +  "(fps_right_inverse f x) $ 0 = 0 \<longleftrightarrow> x = 0"
  5.1843 +  by auto
  5.1844 +
  5.1845 +lemma fps_inverse_0_iff': "(inverse f) $ 0 = 0 \<longleftrightarrow> inverse (f $ 0) = 0"
  5.1846 +  by (simp add: fps_inverse_def fps_lr_inverse_0_iff(2))
  5.1847 +
  5.1848 +lemma fps_inverse_0_iff[simp]: "(inverse f) $ 0 = (0::'a::division_ring) \<longleftrightarrow> f $ 0 = 0"
  5.1849 +  by (simp add: fps_inverse_0_iff')
  5.1850 +
  5.1851 +lemma fps_lr_inverse_nth_0:
  5.1852 +  "(fps_left_inverse f x) $ 0 = x" "(fps_right_inverse f x) $ 0 = x"
  5.1853 +  by auto
  5.1854 +
  5.1855 +lemma fps_inverse_nth_0 [simp]: "(inverse f) $ 0 = inverse (f $ 0)"
  5.1856 +  by (simp add: fps_inverse_def)
  5.1857 +
  5.1858 +lemma fps_lr_inverse_starting0:
  5.1859 +  fixes f :: "'a::{comm_monoid_add,mult_zero,uminus} fps"
  5.1860 +  and   g :: "'b::{ab_group_add,mult_zero} fps"
  5.1861 +  shows "fps_left_inverse f 0 = 0"
  5.1862 +  and   "fps_right_inverse g 0 = 0"
  5.1863 +proof-
  5.1864 +  show "fps_left_inverse f 0 = 0"
  5.1865 +  proof (rule fps_ext)
  5.1866 +    fix n show "fps_left_inverse f 0 $ n = 0 $ n"
  5.1867 +      by (cases n) (simp_all add: fps_inverse_def)
  5.1868 +  qed
  5.1869 +  show "fps_right_inverse g 0 = 0"
  5.1870 +  proof (rule fps_ext)
  5.1871 +    fix n show "fps_right_inverse g 0 $ n = 0 $ n"
  5.1872 +      by (cases n) (simp_all add: fps_inverse_def)
  5.1873 +  qed
  5.1874 +qed
  5.1875 +
  5.1876 +lemma fps_lr_inverse_eq0_imp_starting0:
  5.1877 +  "fps_left_inverse f x = 0 \<Longrightarrow> x = 0"
  5.1878 +  "fps_right_inverse f x = 0 \<Longrightarrow> x = 0"
  5.1879 +proof-
  5.1880 +  assume A: "fps_left_inverse f x = 0"
  5.1881 +  have "0 = fps_left_inverse f x $ 0" by (subst A) simp
  5.1882 +  thus "x = 0" by simp
  5.1883 +next
  5.1884 +  assume A: "fps_right_inverse f x = 0"
  5.1885 +  have "0 = fps_right_inverse f x $ 0" by (subst A) simp
  5.1886 +  thus "x = 0" by simp
  5.1887 +qed
  5.1888 +
  5.1889 +lemma fps_lr_inverse_eq_0_iff:
  5.1890 +  fixes x :: "'a::{comm_monoid_add,mult_zero,uminus}"
  5.1891 +  and   y :: "'b::{ab_group_add,mult_zero}"
  5.1892 +  shows "fps_left_inverse f x = 0 \<longleftrightarrow> x = 0"
  5.1893 +  and   "fps_right_inverse g y = 0 \<longleftrightarrow> y = 0"
  5.1894 +  using fps_lr_inverse_starting0 fps_lr_inverse_eq0_imp_starting0
  5.1895 +  by    auto
  5.1896 +
  5.1897 +lemma fps_inverse_eq_0_iff':
  5.1898 +  fixes f :: "'a::{ab_group_add,inverse,mult_zero} fps"
  5.1899 +  shows "inverse f = 0 \<longleftrightarrow> inverse (f $ 0) = 0"
  5.1900 +  by    (simp add: fps_inverse_def fps_lr_inverse_eq_0_iff(2))
  5.1901 +
  5.1902 +lemma fps_inverse_eq_0_iff[simp]: "inverse f = (0:: ('a::division_ring) fps) \<longleftrightarrow> f $ 0 = 0"
  5.1903 +  using fps_inverse_eq_0_iff'[of f] by simp
  5.1904 +
  5.1905 +lemmas fps_inverse_eq_0' = iffD2[OF fps_inverse_eq_0_iff']
  5.1906 +lemmas fps_inverse_eq_0  = iffD2[OF fps_inverse_eq_0_iff]
  5.1907 +
  5.1908 +lemma fps_const_lr_inverse:
  5.1909 +  fixes a :: "'a::{ab_group_add,mult_zero}"
  5.1910 +  and   b :: "'b::{comm_monoid_add,mult_zero,uminus}"
  5.1911 +  shows "fps_left_inverse (fps_const a) x = fps_const x"
  5.1912 +  and   "fps_right_inverse (fps_const b) y = fps_const y"
  5.1913 +proof-
  5.1914 +  show "fps_left_inverse (fps_const a) x = fps_const x"
  5.1915 +  proof (rule fps_ext)
  5.1916 +    fix n show "fps_left_inverse (fps_const a) x $ n = fps_const x $ n"
  5.1917 +      by (cases n) auto
  5.1918 +  qed
  5.1919 +  show "fps_right_inverse (fps_const b) y = fps_const y"
  5.1920 +  proof (rule fps_ext)
  5.1921 +    fix n show "fps_right_inverse (fps_const b) y $ n = fps_const y $ n"
  5.1922 +      by (cases n) auto
  5.1923 +  qed
  5.1924 +qed
  5.1925 +
  5.1926 +lemma fps_const_inverse:
  5.1927 +  fixes     a :: "'a::{comm_monoid_add,inverse,mult_zero,uminus}"
  5.1928 +  shows     "inverse (fps_const a) = fps_const (inverse a)"
  5.1929 +  unfolding fps_inverse_def
  5.1930 +  by        (simp add: fps_const_lr_inverse(2))
  5.1931 +
  5.1932 +lemma fps_lr_inverse_zero:
  5.1933 +  fixes x :: "'a::{ab_group_add,mult_zero}"
  5.1934 +  and   y :: "'b::{comm_monoid_add,mult_zero,uminus}"
  5.1935 +  shows "fps_left_inverse 0 x = fps_const x"
  5.1936 +  and   "fps_right_inverse 0 y = fps_const y"
  5.1937 +  using fps_const_lr_inverse[of 0]
  5.1938 +  by    simp_all
  5.1939 +
  5.1940 +lemma fps_inverse_zero_conv_fps_const:
  5.1941 +  "inverse (0::'a::{comm_monoid_add,mult_zero,uminus,inverse} fps) = fps_const (inverse 0)"
  5.1942 +  using fps_lr_inverse_zero(2)[of "inverse (0::'a)"] by (simp add: fps_inverse_def)
  5.1943 +
  5.1944 +lemma fps_inverse_zero':
  5.1945 +  assumes "inverse (0::'a::{comm_monoid_add,inverse,mult_zero,uminus}) = 0"
  5.1946 +  shows   "inverse (0::'a fps) = 0"
  5.1947 +  by      (simp add: assms fps_inverse_zero_conv_fps_const)
  5.1948 +
  5.1949  lemma fps_inverse_zero [simp]:
  5.1950 -  "inverse (0 :: 'a::{comm_monoid_add,inverse,times,uminus} fps) = 0"
  5.1951 -  by (simp add: fps_ext fps_inverse_def)
  5.1952 -
  5.1953 -lemma fps_inverse_one [simp]: "inverse (1 :: 'a::{division_ring,zero_neq_one} fps) = 1"
  5.1954 -  apply (auto simp add: expand_fps_eq fps_inverse_def)
  5.1955 -  apply (case_tac n)
  5.1956 -  apply auto
  5.1957 -  done
  5.1958 +  "inverse (0::'a::division_ring fps) = 0"
  5.1959 +  by (rule fps_inverse_zero'[OF inverse_zero])
  5.1960 +
  5.1961 +lemma fps_lr_inverse_one:
  5.1962 +  fixes x :: "'a::{ab_group_add,mult_zero,one}"
  5.1963 +  and   y :: "'b::{comm_monoid_add,mult_zero,uminus,one}"
  5.1964 +  shows "fps_left_inverse 1 x = fps_const x"
  5.1965 +  and   "fps_right_inverse 1 y = fps_const y"
  5.1966 +  using fps_const_lr_inverse[of 1]
  5.1967 +  by    simp_all
  5.1968 +
  5.1969 +lemma fps_lr_inverse_one_one:
  5.1970 +  "fps_left_inverse 1 1 = (1::'a::{ab_group_add,mult_zero,one} fps)"
  5.1971 +  "fps_right_inverse 1 1 = (1::'b::{comm_monoid_add,mult_zero,uminus,one} fps)"
  5.1972 +  by (simp_all add: fps_lr_inverse_one)
  5.1973 +
  5.1974 +lemma fps_inverse_one':
  5.1975 +  assumes "inverse (1::'a::{comm_monoid_add,inverse,mult_zero,uminus,one}) = 1"
  5.1976 +  shows   "inverse (1 :: 'a fps) = 1"
  5.1977 +  using   assms fps_lr_inverse_one_one(2)
  5.1978 +  by      (simp add: fps_inverse_def)
  5.1979 +
  5.1980 +lemma fps_inverse_one [simp]: "inverse (1 :: 'a :: division_ring fps) = 1"
  5.1981 +  by (rule fps_inverse_one'[OF inverse_1])
  5.1982 +
  5.1983 +lemma fps_lr_inverse_minus:
  5.1984 +  fixes f :: "'a::ring_1 fps"
  5.1985 +  shows "fps_left_inverse (-f) (-x) = - fps_left_inverse f x"
  5.1986 +  and   "fps_right_inverse (-f) (-x) = - fps_right_inverse f x"
  5.1987 +proof-
  5.1988 +
  5.1989 +  show "fps_left_inverse (-f) (-x) = - fps_left_inverse f x"
  5.1990 +  proof (intro fps_ext)
  5.1991 +    fix n show "fps_left_inverse (-f) (-x) $ n = - fps_left_inverse f x $ n"
  5.1992 +    proof (induct n rule: nat_less_induct)
  5.1993 +      case (1 n) thus ?case by (cases n) (simp_all add: sum_negf algebra_simps)
  5.1994 +    qed
  5.1995 +  qed
  5.1996 +
  5.1997 +  show "fps_right_inverse (-f) (-x) = - fps_right_inverse f x"
  5.1998 +  proof (intro fps_ext)
  5.1999 +    fix n show "fps_right_inverse (-f) (-x) $ n = - fps_right_inverse f x $ n"
  5.2000 +    proof (induct n rule: nat_less_induct)
  5.2001 +      case (1 n) show ?case
  5.2002 +      proof (cases n)
  5.2003 +        case (Suc m)
  5.2004 +        with 1 have
  5.2005 +          "\<forall>i\<in>{1..Suc m}. fps_right_inverse (-f) (-x) $ (Suc m - i) =
  5.2006 +            - fps_right_inverse f x $ (Suc m - i)"
  5.2007 +          by auto
  5.2008 +        with Suc show ?thesis by (simp add: sum_negf algebra_simps)
  5.2009 +      qed simp
  5.2010 +    qed
  5.2011 +  qed
  5.2012 +
  5.2013 +qed
  5.2014 +
  5.2015 +lemma fps_inverse_minus [simp]: "inverse (-f) = -inverse (f :: 'a :: division_ring fps)"
  5.2016 +  by (simp add: fps_inverse_def fps_lr_inverse_minus(2))
  5.2017 +
  5.2018 +lemma fps_left_inverse:
  5.2019 +  fixes   f :: "'a::ring_1 fps"
  5.2020 +  assumes f0: "x * f$0 = 1"
  5.2021 +  shows   "fps_left_inverse f x * f = 1"
  5.2022 +proof (rule fps_ext)
  5.2023 +  fix n show "(fps_left_inverse f x * f) $ n = 1 $ n"
  5.2024 +    by (cases n) (simp_all add: f0 fps_mult_nth mult.assoc)
  5.2025 +qed
  5.2026 +
  5.2027 +lemma fps_right_inverse:
  5.2028 +  fixes   f :: "'a::ring_1 fps"
  5.2029 +  assumes f0: "f$0 * y = 1"
  5.2030 +  shows   "f * fps_right_inverse f y = 1"
  5.2031 +proof (rule fps_ext)
  5.2032 +  fix n
  5.2033 +  show "(f * fps_right_inverse f y) $ n = 1 $ n"
  5.2034 +  proof (cases n)
  5.2035 +    case (Suc k)
  5.2036 +    moreover from Suc have "fps_right_inverse f y $ n =
  5.2037 +            - y * sum (\<lambda>i. f$i * fps_right_inverse_constructor f y (n - i)) {1..n}"
  5.2038 +      by simp
  5.2039 +    hence
  5.2040 +      "(f * fps_right_inverse f y) $ n =
  5.2041 +        - 1 * sum (\<lambda>i. f$i * fps_right_inverse_constructor f y (n - i)) {1..n} +
  5.2042 +        sum (\<lambda>i. f$i * (fps_right_inverse_constructor f y (n - i))) {1..n}"
  5.2043 +      by (simp add: fps_mult_nth sum_head_Suc mult.assoc f0[symmetric])
  5.2044 +    thus "(f * fps_right_inverse f y) $ n = 1 $ n" by (simp add: Suc)
  5.2045 +  qed (simp add: f0 fps_inverse_def)
  5.2046 +qed
  5.2047 +
  5.2048 +\<comment> \<open>
  5.2049 +  It is possible in a ring for an element to have a left inverse but not a right inverse, or
  5.2050 +  vice versa. But when an element has both, they must be the same.
  5.2051 +\<close>
  5.2052 +lemma fps_left_inverse_eq_fps_right_inverse:
  5.2053 +  fixes   f :: "'a::ring_1 fps"
  5.2054 +  assumes f0: "x * f$0 = 1" "f $ 0 * y = 1"
  5.2055 +  \<comment> \<open>These assumptions imply x equals y, but no need to assume that.\<close>
  5.2056 +  shows   "fps_left_inverse f x = fps_right_inverse f y"
  5.2057 +proof-
  5.2058 +  from f0(2) have "f * fps_right_inverse f y = 1"
  5.2059 +      by (simp add: fps_right_inverse)
  5.2060 +  hence "fps_left_inverse f x * f * fps_right_inverse f y = fps_left_inverse f x"
  5.2061 +    by (simp add: mult.assoc)
  5.2062 +  moreover from f0(1) have
  5.2063 +    "fps_left_inverse f x * f * fps_right_inverse f y = fps_right_inverse f y"
  5.2064 +    by (simp add: fps_left_inverse)
  5.2065 +  ultimately show ?thesis by simp
  5.2066 +qed
  5.2067 +
  5.2068 +lemma fps_left_inverse_eq_fps_right_inverse_comm:
  5.2069 +  fixes   f :: "'a::comm_ring_1 fps"
  5.2070 +  assumes f0: "x * f$0 = 1"
  5.2071 +  shows   "fps_left_inverse f x = fps_right_inverse f x"
  5.2072 +  using   assms fps_left_inverse_eq_fps_right_inverse[of x f x]
  5.2073 +  by      (simp add: mult.commute)
  5.2074 +
  5.2075 +lemma fps_left_inverse':
  5.2076 +  fixes   f :: "'a::ring_1 fps"
  5.2077 +  assumes "x * f$0 = 1" "f$0 * y = 1"
  5.2078 +  \<comment> \<open>These assumptions imply x equals y, but no need to assume that.\<close>
  5.2079 +  shows   "fps_right_inverse f y * f = 1"
  5.2080 +  using   assms fps_left_inverse_eq_fps_right_inverse[of x f y] fps_left_inverse[of x f]
  5.2081 +  by      simp
  5.2082 +
  5.2083 +lemma fps_right_inverse':
  5.2084 +  fixes   f :: "'a::ring_1 fps"
  5.2085 +  assumes "x * f$0 = 1" "f$0 * y = 1"
  5.2086 +  \<comment> \<open>These assumptions imply x equals y, but no need to assume that.\<close>
  5.2087 +  shows   "f * fps_left_inverse f x = 1"
  5.2088 +  using   assms fps_left_inverse_eq_fps_right_inverse[of x f y] fps_right_inverse[of f y]
  5.2089 +  by      simp
  5.2090  
  5.2091  lemma inverse_mult_eq_1 [intro]:
  5.2092 -  assumes f0: "f$0 \<noteq> (0::'a::field)"
  5.2093 -  shows "inverse f * f = 1"
  5.2094 -proof -
  5.2095 -  have c: "inverse f * f = f * inverse f"
  5.2096 -    by (simp add: mult.commute)
  5.2097 -  from f0 have ifn: "\<And>n. inverse f $ n = natfun_inverse f n"
  5.2098 -    by (simp add: fps_inverse_def)
  5.2099 -  from f0 have th0: "(inverse f * f) $ 0 = 1"
  5.2100 -    by (simp add: fps_mult_nth fps_inverse_def)
  5.2101 -  have "(inverse f * f)$n = 0" if np: "n > 0" for n
  5.2102 -  proof -
  5.2103 -    from np have eq: "{0..n} = {0} \<union> {1 .. n}"
  5.2104 -      by auto
  5.2105 -    have d: "{0} \<inter> {1 .. n} = {}"
  5.2106 -      by auto
  5.2107 -    from f0 np have th0: "- (inverse f $ n) =
  5.2108 -      (sum (\<lambda>i. f$i * natfun_inverse f (n - i)) {1..n}) / (f$0)"
  5.2109 -      by (cases n) (simp_all add: divide_inverse fps_inverse_def)
  5.2110 -    from th0[symmetric, unfolded nonzero_divide_eq_eq[OF f0]]
  5.2111 -    have th1: "sum (\<lambda>i. f$i * natfun_inverse f (n - i)) {1..n} = - (f$0) * (inverse f)$n"
  5.2112 -      by (simp add: field_simps)
  5.2113 -    have "(f * inverse f) $ n = (\<Sum>i = 0..n. f $i * natfun_inverse f (n - i))"
  5.2114 -      unfolding fps_mult_nth ifn ..
  5.2115 -    also have "\<dots> = f$0 * natfun_inverse f n + (\<Sum>i = 1..n. f$i * natfun_inverse f (n-i))"
  5.2116 -      by (simp add: eq)
  5.2117 -    also have "\<dots> = 0"
  5.2118 -      unfolding th1 ifn by simp
  5.2119 -    finally show ?thesis unfolding c .
  5.2120 -  qed
  5.2121 -  with th0 show ?thesis
  5.2122 -    by (simp add: fps_eq_iff)
  5.2123 -qed
  5.2124 -
  5.2125 -lemma fps_inverse_0_iff[simp]: "(inverse f) $ 0 = (0::'a::division_ring) \<longleftrightarrow> f $ 0 = 0"
  5.2126 -  by (simp add: fps_inverse_def nonzero_imp_inverse_nonzero)
  5.2127 -
  5.2128 -lemma fps_inverse_nth_0 [simp]: "inverse f $ 0 = inverse (f $ 0 :: 'a :: division_ring)"
  5.2129 -  by (simp add: fps_inverse_def)
  5.2130 -
  5.2131 -lemma fps_inverse_eq_0_iff[simp]: "inverse f = (0:: ('a::division_ring) fps) \<longleftrightarrow> f $ 0 = 0"
  5.2132 -proof
  5.2133 -  assume A: "inverse f = 0"
  5.2134 -  have "0 = inverse f $ 0" by (subst A) simp
  5.2135 -  thus "f $ 0 = 0" by simp
  5.2136 -qed (simp add: fps_inverse_def)
  5.2137 +  assumes "f$0 \<noteq> (0::'a::division_ring)"
  5.2138 +  shows   "inverse f * f = 1"
  5.2139 +  using   fps_left_inverse'[of "inverse (f$0)"]
  5.2140 +  by      (simp add: assms fps_inverse_def)
  5.2141 +
  5.2142 +lemma inverse_mult_eq_1':
  5.2143 +  assumes "f$0 \<noteq> (0::'a::division_ring)"
  5.2144 +  shows   "f * inverse f = 1"
  5.2145 +  using   assms fps_right_inverse
  5.2146 +  by      (force simp: fps_inverse_def)
  5.2147 +
  5.2148 +lemma fps_mult_left_inverse_unit_factor:
  5.2149 +  fixes   f :: "'a::ring_1 fps"
  5.2150 +  assumes "x * f $ subdegree f = 1"
  5.2151 +  shows   "fps_left_inverse (unit_factor f) x * f = fps_X ^ subdegree f"
  5.2152 +proof-
  5.2153 +  have
  5.2154 +    "fps_left_inverse (unit_factor f) x * f =
  5.2155 +      fps_left_inverse (unit_factor f) x * unit_factor f * fps_X ^ subdegree f"
  5.2156 +    using fps_unit_factor_decompose[of f] by (simp add: mult.assoc)
  5.2157 +  with assms show ?thesis by (simp add: fps_left_inverse)
  5.2158 +qed
  5.2159 +
  5.2160 +lemma fps_mult_right_inverse_unit_factor:
  5.2161 +  fixes   f :: "'a::ring_1 fps"
  5.2162 +  assumes "f $ subdegree f * y = 1"
  5.2163 +  shows   "f * fps_right_inverse (unit_factor f) y = fps_X ^ subdegree f"
  5.2164 +proof-
  5.2165 +  have
  5.2166 +    "f * fps_right_inverse (unit_factor f) y =
  5.2167 +      fps_X ^ subdegree f * (unit_factor f * fps_right_inverse (unit_factor f) y)"
  5.2168 +    using fps_unit_factor_decompose'[of f] by (simp add: mult.assoc[symmetric])
  5.2169 +  with assms show ?thesis by (simp add: fps_right_inverse)
  5.2170 +qed
  5.2171 +
  5.2172 +lemma fps_mult_right_inverse_unit_factor_divring:
  5.2173 +  "(f :: 'a::division_ring fps) \<noteq> 0 \<Longrightarrow> f * inverse (unit_factor f) = fps_X ^ subdegree f"
  5.2174 +  using   fps_mult_right_inverse_unit_factor[of f]
  5.2175 +  by      (simp add: fps_inverse_def)
  5.2176 +
  5.2177 +lemma fps_left_inverse_idempotent_ring1:
  5.2178 +  fixes   f :: "'a::ring_1 fps"
  5.2179 +  assumes "x * f$0 = 1" "y * x = 1"
  5.2180 +  \<comment> \<open>These assumptions imply y equals f$0, but no need to assume that.\<close>
  5.2181 +  shows   "fps_left_inverse (fps_left_inverse f x) y = f"
  5.2182 +proof-
  5.2183 +  from assms(1) have
  5.2184 +    "fps_left_inverse (fps_left_inverse f x) y * fps_left_inverse f x * f =
  5.2185 +      fps_left_inverse (fps_left_inverse f x) y"
  5.2186 +    by (simp add: fps_left_inverse mult.assoc)
  5.2187 +  moreover from assms(2) have
  5.2188 +    "fps_left_inverse (fps_left_inverse f x) y * fps_left_inverse f x = 1"
  5.2189 +    by (simp add: fps_left_inverse)
  5.2190 +  ultimately show ?thesis by simp
  5.2191 +qed
  5.2192 +
  5.2193 +lemma fps_left_inverse_idempotent_comm_ring1:
  5.2194 +  fixes   f :: "'a::comm_ring_1 fps"
  5.2195 +  assumes "x * f$0 = 1"
  5.2196 +  shows   "fps_left_inverse (fps_left_inverse f x) (f$0) = f"
  5.2197 +  using   assms fps_left_inverse_idempotent_ring1[of x f "f$0"]
  5.2198 +  by      (simp add: mult.commute)
  5.2199 +
  5.2200 +lemma fps_right_inverse_idempotent_ring1:
  5.2201 +  fixes   f :: "'a::ring_1 fps"
  5.2202 +  assumes "f$0 * x = 1" "x * y = 1"
  5.2203 +  \<comment> \<open>These assumptions imply y equals f$0, but no need to assume that.\<close>
  5.2204 +  shows   "fps_right_inverse (fps_right_inverse f x) y = f"
  5.2205 +proof-
  5.2206 +  from assms(1) have "f * (fps_right_inverse f x * fps_right_inverse (fps_right_inverse f x) y) =
  5.2207 +      fps_right_inverse (fps_right_inverse f x) y"
  5.2208 +    by (simp add: fps_right_inverse mult.assoc[symmetric])
  5.2209 +  moreover from assms(2) have
  5.2210 +    "fps_right_inverse f x * fps_right_inverse (fps_right_inverse f x) y = 1"
  5.2211 +    by (simp add: fps_right_inverse)
  5.2212 +  ultimately show ?thesis by simp
  5.2213 +qed
  5.2214 +
  5.2215 +lemma fps_right_inverse_idempotent_comm_ring1:
  5.2216 +  fixes   f :: "'a::comm_ring_1 fps"
  5.2217 +  assumes "f$0 * x = 1"
  5.2218 +  shows   "fps_right_inverse (fps_right_inverse f x) (f$0) = f"
  5.2219 +  using   assms fps_right_inverse_idempotent_ring1[of f x "f$0"]
  5.2220 +  by      (simp add: mult.commute)
  5.2221  
  5.2222  lemma fps_inverse_idempotent[intro, simp]:
  5.2223 -  assumes f0: "f$0 \<noteq> (0::'a::field)"
  5.2224 -  shows "inverse (inverse f) = f"
  5.2225 -proof -
  5.2226 -  from f0 have if0: "inverse f $ 0 \<noteq> 0" by simp
  5.2227 -  from inverse_mult_eq_1[OF f0] inverse_mult_eq_1[OF if0]
  5.2228 -  have "inverse f * f = inverse f * inverse (inverse f)"
  5.2229 -    by (simp add: ac_simps)
  5.2230 -  then show ?thesis
  5.2231 -    using f0 unfolding mult_cancel_left by simp
  5.2232 +  "f$0 \<noteq> (0::'a::division_ring) \<Longrightarrow> inverse (inverse f) = f"
  5.2233 +  using fps_right_inverse_idempotent_ring1[of f]
  5.2234 +  by    (simp add: fps_inverse_def)
  5.2235 +
  5.2236 +lemma fps_lr_inverse_unique_ring1:
  5.2237 +  fixes   f g :: "'a :: ring_1 fps"
  5.2238 +  assumes fg: "f * g = 1" "g$0 * f$0 = 1"
  5.2239 +  shows   "fps_left_inverse g (f$0) = f"
  5.2240 +  and     "fps_right_inverse f (g$0) = g"
  5.2241 +proof-
  5.2242 +
  5.2243 +  show "fps_left_inverse g (f$0) = f"
  5.2244 +  proof (intro fps_ext)
  5.2245 +    fix n show "fps_left_inverse g (f$0) $ n = f $ n"
  5.2246 +    proof (induct n rule: nat_less_induct)
  5.2247 +      case (1 n) show ?case
  5.2248 +      proof (cases n)
  5.2249 +        case (Suc k)
  5.2250 +        hence "\<forall>i\<in>{0..k}. fps_left_inverse g (f$0) $ i = f $ i" using 1 by simp
  5.2251 +        hence "fps_left_inverse g (f$0) $ Suc k = f $ Suc k - 1 $ Suc k * f$0"
  5.2252 +          by (simp add: fps_mult_nth fg(1)[symmetric] distrib_right mult.assoc fg(2))
  5.2253 +        with Suc show ?thesis by simp
  5.2254 +      qed simp
  5.2255 +    qed
  5.2256 +  qed
  5.2257 +
  5.2258 +  show "fps_right_inverse f (g$0) = g"
  5.2259 +  proof (intro fps_ext)
  5.2260 +    fix n show "fps_right_inverse f (g$0) $ n = g $ n"
  5.2261 +    proof (induct n rule: nat_less_induct)
  5.2262 +      case (1 n) show ?case
  5.2263 +      proof (cases n)
  5.2264 +        case (Suc k)
  5.2265 +        hence "\<forall>i\<in>{1..Suc k}. fps_right_inverse f (g$0) $ (Suc k - i) = g $ (Suc k - i)"
  5.2266 +          using 1 by auto
  5.2267 +        hence
  5.2268 +          "fps_right_inverse f (g$0) $ Suc k = 1 * g $ Suc k - g$0 * 1 $ Suc k"
  5.2269 +          by (simp add: fps_mult_nth fg(1)[symmetric] algebra_simps fg(2)[symmetric] sum_head_Suc)
  5.2270 +        with Suc show ?thesis by simp
  5.2271 +      qed simp
  5.2272 +    qed
  5.2273 +  qed
  5.2274 +
  5.2275 +qed
  5.2276 +
  5.2277 +lemma fps_lr_inverse_unique_divring:
  5.2278 +  fixes   f g :: "'a ::division_ring fps"
  5.2279 +  assumes fg: "f * g = 1"
  5.2280 +  shows   "fps_left_inverse g (f$0) = f"
  5.2281 +  and     "fps_right_inverse f (g$0) = g"
  5.2282 +proof-
  5.2283 +  from fg have "f$0 * g$0 = 1" using fps_mult_nth_0[of f g] by simp
  5.2284 +  hence "g$0 * f$0 = 1" using inverse_unique[of "f$0"] left_inverse[of "f$0"] by force
  5.2285 +  thus "fps_left_inverse g (f$0) = f" "fps_right_inverse f (g$0) = g"
  5.2286 +    using fg fps_lr_inverse_unique_ring1 by auto
  5.2287  qed
  5.2288  
  5.2289  lemma fps_inverse_unique:
  5.2290 -  assumes fg: "(f :: 'a :: field fps) * g = 1"
  5.2291 +  fixes   f g :: "'a :: division_ring fps"
  5.2292 +  assumes fg: "f * g = 1"
  5.2293    shows   "inverse f = g"
  5.2294  proof -
  5.2295 -  have f0: "f $ 0 \<noteq> 0"
  5.2296 -  proof
  5.2297 -    assume "f $ 0 = 0"
  5.2298 -    hence "0 = (f * g) $ 0" by simp
  5.2299 -    also from fg have "(f * g) $ 0 = 1" by simp
  5.2300 -    finally show False by simp
  5.2301 -  qed
  5.2302 -  from inverse_mult_eq_1[OF this] fg
  5.2303 -  have th0: "inverse f * f = g * f"
  5.2304 -    by (simp add: ac_simps)
  5.2305 -  then show ?thesis
  5.2306 -    using f0
  5.2307 -    unfolding mult_cancel_right
  5.2308 -    by (auto simp add: expand_fps_eq)
  5.2309 -qed
  5.2310 -
  5.2311 -lemma fps_inverse_eq_0: "f$0 = 0 \<Longrightarrow> inverse (f :: 'a :: division_ring fps) = 0"
  5.2312 -  by simp
  5.2313 -  
  5.2314 +  from fg have if0: "inverse (f$0) = g$0" "f$0 \<noteq> 0"
  5.2315 +    using inverse_unique[of "f$0"] fps_mult_nth_0[of f g] by auto
  5.2316 +  with fg have "fps_right_inverse f (g$0) = g"
  5.2317 +    using left_inverse[of "f$0"] by (intro fps_lr_inverse_unique_ring1(2)) simp_all
  5.2318 +  with if0(1) show ?thesis by (simp add: fps_inverse_def)
  5.2319 +qed
  5.2320 +
  5.2321 +lemma inverse_fps_numeral:
  5.2322 +  "inverse (numeral n :: ('a :: field_char_0) fps) = fps_const (inverse (numeral n))"
  5.2323 +  by (intro fps_inverse_unique fps_ext) (simp_all add: fps_numeral_nth)
  5.2324 +
  5.2325 +lemma inverse_fps_of_nat:
  5.2326 +  "inverse (of_nat n :: 'a :: {semiring_1,times,uminus,inverse} fps) =
  5.2327 +    fps_const (inverse (of_nat n))"
  5.2328 +  by (simp add: fps_of_nat fps_const_inverse[symmetric])
  5.2329 +
  5.2330  lemma sum_zero_lemma:
  5.2331    fixes n::nat
  5.2332    assumes "0 < n"
  5.2333 @@ -1088,43 +2001,648 @@
  5.2334      unfolding th1
  5.2335      apply (simp add: sum.union_disjoint[OF f d, unfolded eq[symmetric]] del: One_nat_def)
  5.2336      unfolding th2
  5.2337 -    apply (simp add: sum.delta)
  5.2338 +    apply simp
  5.2339      done
  5.2340  qed
  5.2341  
  5.2342 +lemma fps_lr_inverse_mult_ring1:
  5.2343 +  fixes   f g :: "'a::ring_1 fps"
  5.2344 +  assumes x: "x * f$0 = 1" "f$0 * x = 1"
  5.2345 +  and     y: "y * g$0 = 1" "g$0 * y = 1"
  5.2346 +  shows   "fps_left_inverse (f * g) (y*x) = fps_left_inverse g y * fps_left_inverse f x"
  5.2347 +  and     "fps_right_inverse (f * g) (y*x) = fps_right_inverse g y * fps_right_inverse f x"
  5.2348 +proof -
  5.2349 +  define h where "h \<equiv> fps_left_inverse g y * fps_left_inverse f x"
  5.2350 +  hence h0: "h$0 = y*x" by simp
  5.2351 +  have "fps_left_inverse (f*g) (h$0) = h"
  5.2352 +  proof (intro fps_lr_inverse_unique_ring1(1))
  5.2353 +    from h_def
  5.2354 +      have  "h * (f * g) = fps_left_inverse g y * (fps_left_inverse f x * f) * g"
  5.2355 +      by    (simp add: mult.assoc)
  5.2356 +    thus "h * (f * g) = 1"
  5.2357 +      using fps_left_inverse[OF x(1)] fps_left_inverse[OF y(1)] by simp
  5.2358 +    from h_def have "(f*g)$0 * h$0 = f$0 * 1 * x"
  5.2359 +      by (simp add: mult.assoc y(2)[symmetric])
  5.2360 +    with x(2) show "(f * g) $ 0 * h $ 0 = 1" by simp
  5.2361 +  qed
  5.2362 +  with h_def
  5.2363 +    show  "fps_left_inverse (f * g) (y*x) = fps_left_inverse g y * fps_left_inverse f x"
  5.2364 +    by    simp
  5.2365 +next
  5.2366 +  define h where "h \<equiv> fps_right_inverse g y * fps_right_inverse f x"
  5.2367 +  hence h0: "h$0 = y*x" by simp
  5.2368 +  have "fps_right_inverse (f*g) (h$0) = h"
  5.2369 +  proof (intro fps_lr_inverse_unique_ring1(2))
  5.2370 +    from h_def
  5.2371 +      have  "f * g * h = f * (g * fps_right_inverse g y) * fps_right_inverse f x"
  5.2372 +      by    (simp add: mult.assoc)
  5.2373 +    thus "f * g * h = 1"
  5.2374 +      using fps_right_inverse[OF x(2)] fps_right_inverse[OF y(2)] by simp
  5.2375 +    from h_def have "h$0 * (f*g)$0 = y * 1 * g$0"
  5.2376 +      by (simp add: mult.assoc x(1)[symmetric])
  5.2377 +    with y(1) show "h$0 * (f*g)$0  = 1" by simp
  5.2378 +  qed
  5.2379 +  with h_def
  5.2380 +    show  "fps_right_inverse (f * g) (y*x) = fps_right_inverse g y * fps_right_inverse f x"
  5.2381 +    by    simp
  5.2382 +qed
  5.2383 +
  5.2384 +lemma fps_lr_inverse_mult_divring:
  5.2385 +  fixes f g :: "'a::division_ring fps"
  5.2386 +  shows "fps_left_inverse (f * g) (inverse ((f*g)$0)) =
  5.2387 +          fps_left_inverse g (inverse (g$0)) * fps_left_inverse f (inverse (f$0))"
  5.2388 +  and   "fps_right_inverse (f * g) (inverse ((f*g)$0)) =
  5.2389 +          fps_right_inverse g (inverse (g$0)) * fps_right_inverse f (inverse (f$0))"
  5.2390 +proof-
  5.2391 +  show "fps_left_inverse (f * g) (inverse ((f*g)$0)) =
  5.2392 +          fps_left_inverse g (inverse (g$0)) * fps_left_inverse f (inverse (f$0))"
  5.2393 +  proof (cases "f$0 = 0 \<or> g$0 = 0")
  5.2394 +    case True
  5.2395 +    hence "fps_left_inverse (f * g) (inverse ((f*g)$0)) = 0"
  5.2396 +      by (simp add: fps_lr_inverse_eq_0_iff(1))
  5.2397 +    moreover from True have
  5.2398 +      "fps_left_inverse g (inverse (g$0)) * fps_left_inverse f (inverse (f$0)) = 0"
  5.2399 +      by (auto simp: fps_lr_inverse_eq_0_iff(1))
  5.2400 +    ultimately show ?thesis by simp
  5.2401 +  next
  5.2402 +    case False
  5.2403 +    hence "fps_left_inverse (f * g) (inverse (g$0) * inverse (f$0)) =
  5.2404 +            fps_left_inverse g (inverse (g$0)) * fps_left_inverse f (inverse (f$0))"
  5.2405 +      by  (intro fps_lr_inverse_mult_ring1(1)) simp_all
  5.2406 +    with False show ?thesis by (simp add: nonzero_inverse_mult_distrib)
  5.2407 +  qed
  5.2408 +  show "fps_right_inverse (f * g) (inverse ((f*g)$0)) =
  5.2409 +          fps_right_inverse g (inverse (g$0)) * fps_right_inverse f (inverse (f$0))"
  5.2410 +  proof (cases "f$0 = 0 \<or> g$0 = 0")
  5.2411 +    case True
  5.2412 +    from True have "fps_right_inverse (f * g) (inverse ((f*g)$0)) = 0"
  5.2413 +      by (simp add: fps_lr_inverse_eq_0_iff(2))
  5.2414 +    moreover from True have
  5.2415 +      "fps_right_inverse g (inverse (g$0)) * fps_right_inverse f (inverse (f$0)) = 0"
  5.2416 +      by (auto simp: fps_lr_inverse_eq_0_iff(2))
  5.2417 +    ultimately show ?thesis by simp
  5.2418 +  next
  5.2419 +    case False
  5.2420 +    hence "fps_right_inverse (f * g) (inverse (g$0) * inverse (f$0)) =
  5.2421 +            fps_right_inverse g (inverse (g$0)) * fps_right_inverse f (inverse (f$0))"
  5.2422 +      by  (intro fps_lr_inverse_mult_ring1(2)) simp_all
  5.2423 +    with False show ?thesis by (simp add: nonzero_inverse_mult_distrib)
  5.2424 +  qed
  5.2425 +qed
  5.2426 +
  5.2427 +lemma fps_inverse_mult_divring:
  5.2428 +  "inverse (f * g) = inverse g * inverse (f :: 'a::division_ring fps)"
  5.2429 +  using fps_lr_inverse_mult_divring(2) by (simp add: fps_inverse_def)
  5.2430 +
  5.2431  lemma fps_inverse_mult: "inverse (f * g :: 'a::field fps) = inverse f * inverse g"
  5.2432 -proof (cases "f$0 = 0 \<or> g$0 = 0")
  5.2433 -  assume "\<not>(f$0 = 0 \<or> g$0 = 0)"
  5.2434 -  hence [simp]: "f$0 \<noteq> 0" "g$0 \<noteq> 0" by simp_all
  5.2435 -  show ?thesis
  5.2436 -  proof (rule fps_inverse_unique)
  5.2437 -    have "f * g * (inverse f * inverse g) = (inverse f * f) * (inverse g * g)" by simp
  5.2438 -    also have "... = 1" by (subst (1 2) inverse_mult_eq_1) simp_all
  5.2439 -    finally show "f * g * (inverse f * inverse g) = 1" .
  5.2440 +  by (simp add: fps_inverse_mult_divring)
  5.2441 +
  5.2442 +lemma fps_lr_inverse_gp_ring1:
  5.2443 +  fixes   ones ones_inv :: "'a :: ring_1 fps"
  5.2444 +  defines "ones \<equiv> Abs_fps (\<lambda>n. 1)"
  5.2445 +  and     "ones_inv \<equiv> Abs_fps (\<lambda>n. if n=0 then 1 else if n=1 then - 1 else 0)"
  5.2446 +  shows   "fps_left_inverse ones 1 = ones_inv"
  5.2447 +  and     "fps_right_inverse ones 1 = ones_inv"
  5.2448 +proof-
  5.2449 +  show "fps_left_inverse ones 1 = ones_inv"
  5.2450 +  proof (rule fps_ext)
  5.2451 +    fix n
  5.2452 +    show "fps_left_inverse ones 1 $ n = ones_inv $ n"
  5.2453 +    proof (induct n rule: nat_less_induct)
  5.2454 +      case (1 n) show ?case
  5.2455 +      proof (cases n)
  5.2456 +        case (Suc m)
  5.2457 +        have m: "n = Suc m" by fact
  5.2458 +        moreover have "fps_left_inverse ones 1 $ Suc m = ones_inv $ Suc m"
  5.2459 +        proof (cases m)
  5.2460 +          case (Suc k) thus ?thesis
  5.2461 +            using Suc m 1 by (simp add: ones_def ones_inv_def sum_head_Suc)
  5.2462 +        qed (simp add: ones_def ones_inv_def)
  5.2463 +        ultimately show ?thesis by simp
  5.2464 +      qed (simp add: ones_inv_def)
  5.2465 +    qed
  5.2466 +  qed
  5.2467 +  moreover have "fps_right_inverse ones 1 = fps_left_inverse ones 1"
  5.2468 +    by (auto intro: fps_left_inverse_eq_fps_right_inverse[symmetric] simp: ones_def)
  5.2469 +  ultimately show "fps_right_inverse ones 1 = ones_inv" by simp
  5.2470 +qed
  5.2471 +
  5.2472 +lemma fps_lr_inverse_gp_ring1':
  5.2473 +  fixes   ones :: "'a :: ring_1 fps"
  5.2474 +  defines "ones \<equiv> Abs_fps (\<lambda>n. 1)"
  5.2475 +  shows   "fps_left_inverse ones 1 = 1 - fps_X"
  5.2476 +  and     "fps_right_inverse ones 1 = 1 - fps_X"
  5.2477 +proof-
  5.2478 +  define ones_inv :: "'a :: ring_1 fps" 
  5.2479 +    where "ones_inv \<equiv> Abs_fps (\<lambda>n. if n=0 then 1 else if n=1 then - 1 else 0)"
  5.2480 +  hence "fps_left_inverse ones 1 = ones_inv"
  5.2481 +  and   "fps_right_inverse ones 1 = ones_inv"
  5.2482 +    using ones_def fps_lr_inverse_gp_ring1 by auto
  5.2483 +  thus "fps_left_inverse ones 1 = 1 - fps_X"
  5.2484 +  and   "fps_right_inverse ones 1 = 1 - fps_X"
  5.2485 +    by (auto intro: fps_ext simp: ones_inv_def)
  5.2486 +qed
  5.2487 +
  5.2488 +lemma fps_inverse_gp:
  5.2489 +  "inverse (Abs_fps(\<lambda>n. (1::'a::division_ring))) =
  5.2490 +    Abs_fps (\<lambda>n. if n= 0 then 1 else if n=1 then - 1 else 0)"
  5.2491 +  using fps_lr_inverse_gp_ring1(2) by (simp add: fps_inverse_def)
  5.2492 +
  5.2493 +lemma fps_inverse_gp': "inverse (Abs_fps (\<lambda>n. 1::'a::division_ring)) = 1 - fps_X"
  5.2494 +  by (simp add: fps_inverse_def fps_lr_inverse_gp_ring1'(2))
  5.2495 +
  5.2496 +lemma fps_lr_inverse_one_minus_fps_X:
  5.2497 +  fixes   ones :: "'a :: ring_1 fps"
  5.2498 +  defines "ones \<equiv> Abs_fps (\<lambda>n. 1)"
  5.2499 +  shows "fps_left_inverse (1 - fps_X) 1 = ones"
  5.2500 +  and   "fps_right_inverse (1 - fps_X) 1 = ones"
  5.2501 +proof-
  5.2502 +  have "fps_left_inverse ones 1 = 1 - fps_X"
  5.2503 +    using fps_lr_inverse_gp_ring1'(1) by (simp add: ones_def)
  5.2504 +  thus "fps_left_inverse (1 - fps_X) 1 = ones"
  5.2505 +    using fps_left_inverse_idempotent_ring1[of 1 ones 1] by (simp add: ones_def)
  5.2506 +  have "fps_right_inverse ones 1 = 1 - fps_X"
  5.2507 +    using fps_lr_inverse_gp_ring1'(2) by (simp add: ones_def)
  5.2508 +  thus "fps_right_inverse (1 - fps_X) 1 = ones"
  5.2509 +    using fps_right_inverse_idempotent_ring1[of ones 1 1] by (simp add: ones_def)
  5.2510 +qed
  5.2511 +
  5.2512 +lemma fps_inverse_one_minus_fps_X:
  5.2513 +  fixes   ones :: "'a :: division_ring fps"
  5.2514 +  defines "ones \<equiv> Abs_fps (\<lambda>n. 1)"
  5.2515 +  shows   "inverse (1 - fps_X) = ones"
  5.2516 +  by      (simp add: fps_inverse_def assms fps_lr_inverse_one_minus_fps_X(2))
  5.2517 +
  5.2518 +lemma fps_lr_one_over_one_minus_fps_X_squared:
  5.2519 +  shows   "fps_left_inverse ((1 - fps_X)^2) (1::'a::ring_1) = Abs_fps (\<lambda>n. of_nat (n+1))"
  5.2520 +          "fps_right_inverse ((1 - fps_X)^2) (1::'a) = Abs_fps (\<lambda>n. of_nat (n+1))"
  5.2521 +proof-
  5.2522 +  define  f invf2 :: "'a fps"
  5.2523 +    where "f \<equiv> (1 - fps_X)"
  5.2524 +    and   "invf2 \<equiv> Abs_fps (\<lambda>n. of_nat (n+1))"
  5.2525 +
  5.2526 +  have f2_nth_simps:
  5.2527 +    "f^2 $ 1 = - of_nat 2" "f^2 $ 2 = 1" "\<And>n. n>2 \<Longrightarrow> f^2 $ n = 0"
  5.2528 +      by (simp_all add: power2_eq_square f_def fps_mult_nth sum_head_Suc)
  5.2529 +
  5.2530 +  show "fps_left_inverse (f^2) 1 = invf2"
  5.2531 +  proof (intro fps_ext)
  5.2532 +    fix n show "fps_left_inverse (f^2) 1 $ n = invf2 $ n"
  5.2533 +    proof (induct n rule: nat_less_induct)
  5.2534 +      case (1 t)
  5.2535 +      hence induct_assm:
  5.2536 +        "\<And>m. m < t \<Longrightarrow> fps_left_inverse (f\<^sup>2) 1 $ m = invf2 $ m"
  5.2537 +        by fast
  5.2538 +      show ?case
  5.2539 +      proof (cases t)
  5.2540 +        case (Suc m)
  5.2541 +        have m: "t = Suc m" by fact
  5.2542 +        moreover have "fps_left_inverse (f^2) 1 $ Suc m = invf2 $ Suc m"
  5.2543 +        proof (cases m)
  5.2544 +          case 0 thus ?thesis using f2_nth_simps(1) by (simp add: invf2_def)
  5.2545 +        next
  5.2546 +          case (Suc l)
  5.2547 +          have l: "m = Suc l" by fact
  5.2548 +          moreover have "fps_left_inverse (f^2) 1 $ Suc (Suc l) = invf2 $ Suc (Suc l)"
  5.2549 +          proof (cases l)
  5.2550 +            case 0 thus ?thesis using f2_nth_simps(1,2) by (simp add: Suc_1[symmetric] invf2_def)
  5.2551 +          next
  5.2552 +            case (Suc k)
  5.2553 +            from Suc l m
  5.2554 +              have A: "fps_left_inverse (f\<^sup>2) 1 $ Suc (Suc k) = invf2 $ Suc (Suc k)"
  5.2555 +              and  B: "fps_left_inverse (f\<^sup>2) 1 $ Suc k = invf2 $ Suc k"
  5.2556 +              using induct_assm[of "Suc k"] induct_assm[of "Suc (Suc k)"]
  5.2557 +              by    auto
  5.2558 +            have times2: "\<And>a::nat. 2*a = a + a" by simp
  5.2559 +            have "\<forall>i\<in>{0..k}. (f^2)$(Suc (Suc (Suc k)) - i) = 0"
  5.2560 +              using f2_nth_simps(3) by auto
  5.2561 +            hence
  5.2562 +              "fps_left_inverse (f^2) 1 $ Suc (Suc (Suc k)) =
  5.2563 +                fps_left_inverse (f\<^sup>2) 1 $ Suc (Suc k) * of_nat 2 -
  5.2564 +                fps_left_inverse (f\<^sup>2) 1 $ Suc k"
  5.2565 +              using sum_ub_add_nat f2_nth_simps(1,2) by simp
  5.2566 +            also have "\<dots> = of_nat (2 * Suc (Suc (Suc k))) - of_nat (Suc (Suc k))"
  5.2567 +              by (subst A, subst B) (simp add: invf2_def mult.commute)
  5.2568 +            also have "\<dots> = of_nat (Suc (Suc (Suc k)) + 1)"
  5.2569 +              by (subst times2[of "Suc (Suc (Suc k))"]) simp
  5.2570 +            finally have
  5.2571 +              "fps_left_inverse (f^2) 1 $ Suc (Suc (Suc k)) = invf2 $ Suc (Suc (Suc k))"
  5.2572 +               by (simp add: invf2_def)
  5.2573 +            with Suc show ?thesis by simp
  5.2574 +          qed
  5.2575 +          ultimately show ?thesis by simp
  5.2576 +        qed
  5.2577 +        ultimately show ?thesis by simp
  5.2578 +      qed (simp add: invf2_def)
  5.2579 +    qed
  5.2580 +  qed
  5.2581 +
  5.2582 +  moreover have "fps_right_inverse (f^2) 1 = fps_left_inverse (f^2) 1"
  5.2583 +    by  (auto
  5.2584 +          intro: fps_left_inverse_eq_fps_right_inverse[symmetric]
  5.2585 +          simp: f_def power2_eq_square
  5.2586 +        )
  5.2587 +  ultimately show "fps_right_inverse (f^2) 1 = invf2"
  5.2588 +    by simp
  5.2589 +
  5.2590 +qed
  5.2591 +
  5.2592 +lemma fps_one_over_one_minus_fps_X_squared':
  5.2593 +  assumes "inverse (1::'a::{ring_1,inverse}) = 1"
  5.2594 +  shows   "inverse ((1 - fps_X)^2 :: 'a  fps) = Abs_fps (\<lambda>n. of_nat (n+1))"
  5.2595 +  using   assms fps_lr_one_over_one_minus_fps_X_squared(2)
  5.2596 +  by      (simp add: fps_inverse_def power2_eq_square)
  5.2597 +
  5.2598 +lemma fps_one_over_one_minus_fps_X_squared:
  5.2599 +  "inverse ((1 - fps_X)^2 :: 'a :: division_ring fps) = Abs_fps (\<lambda>n. of_nat (n+1))"
  5.2600 +  by (rule fps_one_over_one_minus_fps_X_squared'[OF inverse_1])
  5.2601 +
  5.2602 +lemma fps_lr_inverse_fps_X_plus1:
  5.2603 +  "fps_left_inverse (1 + fps_X) (1::'a::ring_1) = Abs_fps (\<lambda>n. (-1)^n)"
  5.2604 +  "fps_right_inverse (1 + fps_X) (1::'a) = Abs_fps (\<lambda>n. (-1)^n)"
  5.2605 +proof-
  5.2606 +
  5.2607 +  show "fps_left_inverse (1 + fps_X) (1::'a) = Abs_fps (\<lambda>n. (-1)^n)"
  5.2608 +  proof (rule fps_ext)
  5.2609 +    fix n show "fps_left_inverse (1 + fps_X) (1::'a) $ n = Abs_fps (\<lambda>n. (-1)^n) $ n"
  5.2610 +    proof (induct n rule: nat_less_induct)
  5.2611 +      case (1 n) show ?case
  5.2612 +      proof (cases n)
  5.2613 +        case (Suc m)
  5.2614 +        have m: "n = Suc m" by fact
  5.2615 +        from Suc 1 have
  5.2616 +          A:  "fps_left_inverse (1 + fps_X) (1::'a) $ n =
  5.2617 +                - (\<Sum>i=0..m. (- 1)^i * (1 + fps_X) $ (Suc m - i))"
  5.2618 +          by simp
  5.2619 +        show ?thesis
  5.2620 +        proof (cases m)
  5.2621 +          case (Suc l)
  5.2622 +          have "\<forall>i\<in>{0..l}. ((1::'a fps) + fps_X) $ (Suc (Suc l) - i) = 0" by auto
  5.2623 +          with Suc A m show ?thesis by simp
  5.2624 +        qed (simp add: m A)
  5.2625 +      qed simp
  5.2626 +    qed
  5.2627    qed
  5.2628 +
  5.2629 +  moreover have
  5.2630 +    "fps_right_inverse (1 + fps_X) (1::'a) = fps_left_inverse (1 + fps_X) 1"
  5.2631 +    by (intro fps_left_inverse_eq_fps_right_inverse[symmetric]) simp_all
  5.2632 +  ultimately show "fps_right_inverse (1 + fps_X) (1::'a) = Abs_fps (\<lambda>n. (-1)^n)" by simp
  5.2633 +
  5.2634 +qed
  5.2635 +
  5.2636 +lemma fps_inverse_fps_X_plus1':
  5.2637 +  assumes "inverse (1::'a::{ring_1,inverse}) = 1"
  5.2638 +  shows   "inverse (1 + fps_X) = Abs_fps (\<lambda>n. (- (1::'a)) ^ n)"
  5.2639 +  using   assms fps_lr_inverse_fps_X_plus1(2)
  5.2640 +  by      (simp add: fps_inverse_def)
  5.2641 +
  5.2642 +lemma fps_inverse_fps_X_plus1:
  5.2643 +  "inverse (1 + fps_X) = Abs_fps (\<lambda>n. (- (1::'a::division_ring)) ^ n)"
  5.2644 +  by (rule fps_inverse_fps_X_plus1'[OF inverse_1])
  5.2645 +
  5.2646 +lemma subdegree_lr_inverse:
  5.2647 +  fixes x :: "'a::{comm_monoid_add,mult_zero,uminus}"
  5.2648 +  and   y :: "'b::{ab_group_add,mult_zero}"
  5.2649 +  shows "subdegree (fps_left_inverse f x) = 0"
  5.2650 +  and   "subdegree (fps_right_inverse g y) = 0"
  5.2651 +proof-
  5.2652 +  show "subdegree (fps_left_inverse f x) = 0"
  5.2653 +    using fps_lr_inverse_eq_0_iff(1) subdegree_eq_0_iff by fastforce
  5.2654 +  show "subdegree (fps_right_inverse g y) = 0"
  5.2655 +    using fps_lr_inverse_eq_0_iff(2) subdegree_eq_0_iff by fastforce
  5.2656 +qed
  5.2657 +
  5.2658 +lemma subdegree_inverse [simp]:
  5.2659 +  fixes f :: "'a::{ab_group_add,inverse,mult_zero} fps"
  5.2660 +  shows "subdegree (inverse f) = 0"
  5.2661 +  using subdegree_lr_inverse(2)
  5.2662 +  by    (simp add: fps_inverse_def)
  5.2663 +
  5.2664 +lemma fps_div_zero [simp]:
  5.2665 +  "0 div (g :: 'a :: {comm_monoid_add,inverse,mult_zero,uminus} fps) = 0"
  5.2666 +  by (simp add: fps_divide_def)
  5.2667 +
  5.2668 +lemma fps_div_by_zero':
  5.2669 +  fixes   g :: "'a::{comm_monoid_add,inverse,mult_zero,uminus} fps"
  5.2670 +  assumes "inverse (0::'a) = 0"
  5.2671 +  shows   "g div 0 = 0"
  5.2672 +  by      (simp add: fps_divide_def assms fps_inverse_zero')
  5.2673 +
  5.2674 +lemma fps_div_by_zero [simp]: "(g::'a::division_ring fps) div 0 = 0"
  5.2675 +  by    (rule fps_div_by_zero'[OF inverse_zero])
  5.2676 +
  5.2677 +lemma fps_divide_unit': "subdegree g = 0 \<Longrightarrow> f div g = f * inverse g"
  5.2678 +  by (simp add: fps_divide_def)
  5.2679 +
  5.2680 +lemma fps_divide_unit: "g$0 \<noteq> 0 \<Longrightarrow> f div g = f * inverse g"
  5.2681 +  by (intro fps_divide_unit') (simp add: subdegree_eq_0_iff)
  5.2682 +
  5.2683 +lemma fps_divide_nth_0':
  5.2684 +  "subdegree (g::'a::division_ring fps) = 0 \<Longrightarrow> (f div g) $ 0 = f $ 0 / (g $ 0)"
  5.2685 +  by (simp add: fps_divide_unit' divide_inverse)
  5.2686 +
  5.2687 +lemma fps_divide_nth_0 [simp]:
  5.2688 +  "g $ 0 \<noteq> 0 \<Longrightarrow> (f div g) $ 0 = f $ 0 / (g $ 0 :: _ :: division_ring)"
  5.2689 +  by (simp add: fps_divide_nth_0')
  5.2690 +
  5.2691 +lemma fps_divide_nth_below:
  5.2692 +  fixes f g :: "'a::{comm_monoid_add,uminus,mult_zero,inverse} fps"
  5.2693 +  shows "n < subdegree f - subdegree g \<Longrightarrow> (f div g) $ n = 0"
  5.2694 +  by    (simp add: fps_divide_def fps_mult_nth_eq0)
  5.2695 +
  5.2696 +lemma fps_divide_nth_base:
  5.2697 +  fixes   f g :: "'a::division_ring fps"
  5.2698 +  assumes "subdegree g \<le> subdegree f"
  5.2699 +  shows   "(f div g) $ (subdegree f - subdegree g) = f $ subdegree f * inverse (g $ subdegree g)"
  5.2700 +  by      (simp add: assms fps_divide_def fps_divide_unit')
  5.2701 +
  5.2702 +lemma fps_divide_subdegree_ge:
  5.2703 +  fixes   f g :: "'a::{comm_monoid_add,uminus,mult_zero,inverse} fps"
  5.2704 +  assumes "f / g \<noteq> 0"
  5.2705 +  shows   "subdegree (f / g) \<ge> subdegree f - subdegree g"
  5.2706 +  by      (intro subdegree_geI) (simp_all add: assms fps_divide_nth_below)
  5.2707 +
  5.2708 +lemma fps_divide_subdegree:
  5.2709 +  fixes   f g :: "'a::division_ring fps"
  5.2710 +  assumes "f \<noteq> 0" "g \<noteq> 0" "subdegree g \<le> subdegree f"
  5.2711 +  shows   "subdegree (f / g) = subdegree f - subdegree g"
  5.2712 +proof (intro antisym)
  5.2713 +  from assms have 1: "(f div g) $ (subdegree f - subdegree g) \<noteq> 0"
  5.2714 +    using fps_divide_nth_base[of g f] by simp
  5.2715 +  thus "subdegree (f / g) \<le> subdegree f - subdegree g" by (intro subdegree_leI) simp
  5.2716 +  from 1 have "f / g \<noteq> 0" by (auto intro: fps_nonzeroI)
  5.2717 +  thus "subdegree f - subdegree g \<le> subdegree (f / g)" by (rule fps_divide_subdegree_ge)
  5.2718 +qed
  5.2719 +
  5.2720 +lemma fps_divide_shift_numer:
  5.2721 +  fixes   f g :: "'a::{inverse,comm_monoid_add,uminus,mult_zero} fps"
  5.2722 +  assumes "n \<le> subdegree f"
  5.2723 +  shows   "fps_shift n f / g = fps_shift n (f/g)"
  5.2724 +  using   assms fps_shift_mult_right_noncomm[of n f "inverse (unit_factor g)"]
  5.2725 +          fps_shift_fps_shift_reorder[of "subdegree g" n "f * inverse (unit_factor g)"]
  5.2726 +  by      (simp add: fps_divide_def)
  5.2727 +
  5.2728 +lemma fps_divide_shift_denom:
  5.2729 +  fixes   f g :: "'a::{inverse,comm_monoid_add,uminus,mult_zero} fps"
  5.2730 +  assumes "n \<le> subdegree g" "subdegree g \<le> subdegree f"
  5.2731 +  shows   "f / fps_shift n g = Abs_fps (\<lambda>k. if k<n then 0 else (f/g) $ (k-n))"
  5.2732 +proof (intro fps_ext)
  5.2733 +  fix k
  5.2734 +  from assms(1) have LHS:
  5.2735 +    "(f / fps_shift n g) $ k = (f * inverse (unit_factor g)) $ (k + (subdegree g - n))"
  5.2736 +    using fps_unit_factor_shift[of n g]
  5.2737 +    by    (simp add: fps_divide_def)
  5.2738 +  show "(f / fps_shift n g) $ k = Abs_fps (\<lambda>k. if k<n then 0 else (f/g) $ (k-n)) $ k"
  5.2739 +  proof (cases "k<n")
  5.2740 +    case True with assms LHS show ?thesis using fps_mult_nth_eq0[of _ f] by simp
  5.2741 +  next
  5.2742 +    case False
  5.2743 +    hence "(f/g) $ (k-n) = (f * inverse (unit_factor g)) $ ((k-n) + subdegree g)"
  5.2744 +      by (simp add: fps_divide_def)
  5.2745 +    with False LHS assms(1) show ?thesis by auto
  5.2746 +  qed
  5.2747 +qed
  5.2748 +
  5.2749 +lemma fps_divide_unit_factor_numer:
  5.2750 +  fixes   f g :: "'a::{inverse,comm_monoid_add,uminus,mult_zero} fps"
  5.2751 +  shows   "unit_factor f / g = fps_shift (subdegree f) (f/g)"
  5.2752 +  by      (simp add: fps_divide_shift_numer)
  5.2753 +
  5.2754 +lemma fps_divide_unit_factor_denom:
  5.2755 +  fixes   f g :: "'a::{inverse,comm_monoid_add,uminus,mult_zero} fps"
  5.2756 +  assumes "subdegree g \<le> subdegree f"
  5.2757 +  shows
  5.2758 +    "f / unit_factor g = Abs_fps (\<lambda>k. if k<subdegree g then 0 else (f/g) $ (k-subdegree g))"
  5.2759 +  by      (simp add: assms fps_divide_shift_denom)
  5.2760 +
  5.2761 +lemma fps_divide_unit_factor_both':
  5.2762 +  fixes   f g :: "'a::{inverse,comm_monoid_add,uminus,mult_zero} fps"
  5.2763 +  assumes "subdegree g \<le> subdegree f"
  5.2764 +  shows   "unit_factor f / unit_factor g = fps_shift (subdegree f - subdegree g) (f / g)"
  5.2765 +  using   assms fps_divide_unit_factor_numer[of f "unit_factor g"]
  5.2766 +          fps_divide_unit_factor_denom[of g f]
  5.2767 +          fps_shift_rev_shift(1)[of "subdegree g" "subdegree f" "f/g"]
  5.2768 +  by      simp
  5.2769 +
  5.2770 +lemma fps_divide_unit_factor_both:
  5.2771 +  fixes   f g :: "'a::division_ring fps"
  5.2772 +  assumes "subdegree g \<le> subdegree f"
  5.2773 +  shows   "unit_factor f / unit_factor g = unit_factor (f / g)"
  5.2774 +  using   assms fps_divide_unit_factor_both'[of g f] fps_divide_subdegree[of f g]
  5.2775 +  by      (cases "f=0 \<or> g=0") auto
  5.2776 +
  5.2777 +lemma fps_divide_self:
  5.2778 +  "(f::'a::division_ring fps) \<noteq> 0 \<Longrightarrow> f / f = 1"
  5.2779 +  using   fps_mult_right_inverse_unit_factor_divring[of f]
  5.2780 +  by      (simp add: fps_divide_def)
  5.2781 +
  5.2782 +lemma fps_divide_add:
  5.2783 +  fixes f g h :: "'a::{semiring_0,inverse,uminus} fps"
  5.2784 +  shows "(f + g) / h = f / h + g / h"
  5.2785 +  by    (simp add: fps_divide_def algebra_simps fps_shift_add)
  5.2786 +
  5.2787 +lemma fps_divide_diff:
  5.2788 +  fixes f g h :: "'a::{ring,inverse} fps"
  5.2789 +  shows "(f - g) / h = f / h - g / h"
  5.2790 +  by    (simp add: fps_divide_def algebra_simps fps_shift_diff)
  5.2791 +
  5.2792 +lemma fps_divide_uminus:
  5.2793 +  fixes f g h :: "'a::{ring,inverse} fps"
  5.2794 +  shows "(- f) / g = - (f / g)"
  5.2795 +  by    (simp add: fps_divide_def algebra_simps fps_shift_uminus)
  5.2796 +
  5.2797 +lemma fps_divide_uminus':
  5.2798 +  fixes f g h :: "'a::division_ring fps"
  5.2799 +  shows "f / (- g) = - (f / g)"
  5.2800 +  by (simp add: fps_divide_def fps_unit_factor_uminus fps_shift_uminus)
  5.2801 +
  5.2802 +lemma fps_divide_times:
  5.2803 +  fixes   f g h :: "'a::{semiring_0,inverse,uminus} fps"
  5.2804 +  assumes "subdegree h \<le> subdegree g"
  5.2805 +  shows   "(f * g) / h = f * (g / h)"
  5.2806 +  using   assms fps_mult_subdegree_ge[of g "inverse (unit_factor h)"]
  5.2807 +          fps_shift_mult[of "subdegree h" "g * inverse (unit_factor h)" f]
  5.2808 +  by      (fastforce simp add: fps_divide_def mult.assoc)
  5.2809 +
  5.2810 +lemma fps_divide_times2:
  5.2811 +  fixes   f g h :: "'a::{comm_semiring_0,inverse,uminus} fps"
  5.2812 +  assumes "subdegree h \<le> subdegree f"
  5.2813 +  shows   "(f * g) / h = (f / h) * g"
  5.2814 +  using   assms fps_divide_times[of h f g]
  5.2815 +  by      (simp add: mult.commute)
  5.2816 +
  5.2817 +lemma fps_times_divide_eq:
  5.2818 +  fixes   f g :: "'a::field fps"
  5.2819 +  assumes "g \<noteq> 0" and "subdegree f \<ge> subdegree g"
  5.2820 +  shows   "f div g * g = f"
  5.2821 +  using   assms fps_divide_times2[of g f g]
  5.2822 +  by      (simp add: fps_divide_times fps_divide_self)
  5.2823 +
  5.2824 +lemma fps_divide_times_eq:
  5.2825 +  "(g :: 'a::division_ring fps) \<noteq> 0 \<Longrightarrow> (f * g) div g = f"
  5.2826 +  by (simp add: fps_divide_times fps_divide_self)
  5.2827 +
  5.2828 +lemma fps_divide_by_mult':
  5.2829 +  fixes   f g h :: "'a :: division_ring fps"
  5.2830 +  assumes "subdegree h \<le> subdegree f"
  5.2831 +  shows   "f / (g * h) = f / h / g"
  5.2832 +proof (cases "f=0 \<or> g=0 \<or> h=0")
  5.2833 +  case False with assms show ?thesis
  5.2834 +    using fps_unit_factor_mult[of g h]
  5.2835 +    by    (auto simp:
  5.2836 +            fps_divide_def fps_shift_fps_shift fps_inverse_mult_divring mult.assoc
  5.2837 +            fps_shift_mult_right_noncomm
  5.2838 +          )
  5.2839 +qed auto
  5.2840 +
  5.2841 +lemma fps_divide_by_mult:
  5.2842 +  fixes   f g h :: "'a :: field fps"
  5.2843 +  assumes "subdegree g \<le> subdegree f"
  5.2844 +  shows   "f / (g * h) = f / g / h"
  5.2845 +proof-
  5.2846 +  have "f / (g * h) = f / (h * g)" by (simp add: mult.commute)
  5.2847 +  also have "\<dots> = f / g / h" using fps_divide_by_mult'[OF assms] by simp
  5.2848 +  finally show ?thesis by simp
  5.2849 +qed
  5.2850 +
  5.2851 +lemma fps_divide_cancel:
  5.2852 +  fixes   f g h :: "'a :: division_ring fps"
  5.2853 +  shows "h \<noteq> 0 \<Longrightarrow> (f * h) div (g * h) = f div g"
  5.2854 +  by    (cases "f=0")
  5.2855 +        (auto simp: fps_divide_by_mult' fps_divide_times_eq)
  5.2856 +
  5.2857 +lemma fps_divide_1':
  5.2858 +  fixes   a :: "'a::{comm_monoid_add,inverse,mult_zero,uminus,zero_neq_one,monoid_mult} fps"
  5.2859 +  assumes "inverse (1::'a) = 1"
  5.2860 +  shows   "a / 1 = a"
  5.2861 +  using   assms fps_inverse_one' fps_one_mult(2)[of a]
  5.2862 +  by      (force simp: fps_divide_def)
  5.2863 +
  5.2864 +lemma fps_divide_1 [simp]: "(a :: 'a::division_ring fps) / 1 = a"
  5.2865 +  by (rule fps_divide_1'[OF inverse_1])
  5.2866 +
  5.2867 +lemma fps_divide_X':
  5.2868 +  fixes   f :: "'a::{comm_monoid_add,inverse,mult_zero,uminus,zero_neq_one,monoid_mult} fps"
  5.2869 +  assumes "inverse (1::'a) = 1"
  5.2870 +  shows   "f / fps_X = fps_shift 1 f"
  5.2871 +  using   assms fps_one_mult(2)[of f]
  5.2872 +  by      (simp add: fps_divide_def fps_X_unit_factor fps_inverse_one')
  5.2873 +
  5.2874 +lemma fps_divide_X [simp]: "a / fps_X = fps_shift 1 (a::'a::division_ring fps)"
  5.2875 +  by (rule fps_divide_X'[OF inverse_1])
  5.2876 +
  5.2877 +lemma fps_divide_X_power':
  5.2878 +  fixes   f :: "'a::{semiring_1,inverse,uminus} fps"
  5.2879 +  assumes "inverse (1::'a) = 1"
  5.2880 +  shows   "f / (fps_X ^ n) = fps_shift n f"
  5.2881 +  using   fps_inverse_one'[OF assms] fps_one_mult(2)[of f]
  5.2882 +  by      (simp add: fps_divide_def fps_X_power_subdegree)
  5.2883 +
  5.2884 +lemma fps_divide_X_power [simp]: "a / (fps_X ^ n) = fps_shift n (a::'a::division_ring fps)"
  5.2885 +  by (rule fps_divide_X_power'[OF inverse_1])
  5.2886 +
  5.2887 +lemma fps_divide_shift_denom_conv_times_fps_X_power:
  5.2888 +  fixes   f g :: "'a::{semiring_1,inverse,uminus} fps"
  5.2889 +  assumes "n \<le> subdegree g" "subdegree g \<le> subdegree f"
  5.2890 +  shows   "f / fps_shift n g = f / g * fps_X ^ n"
  5.2891 +  using   assms
  5.2892 +  by      (intro fps_ext) (simp_all add: fps_divide_shift_denom fps_X_power_mult_right_nth)
  5.2893 +
  5.2894 +lemma fps_divide_unit_factor_denom_conv_times_fps_X_power:
  5.2895 +  fixes   f g :: "'a::{semiring_1,inverse,uminus} fps"
  5.2896 +  assumes "subdegree g \<le> subdegree f"
  5.2897 +  shows   "f / unit_factor g = f / g * fps_X ^ subdegree g"
  5.2898 +  by      (simp add: assms fps_divide_shift_denom_conv_times_fps_X_power)
  5.2899 +
  5.2900 +lemma fps_shift_altdef':
  5.2901 +  fixes   f :: "'a::{semiring_1,inverse,uminus} fps"
  5.2902 +  assumes "inverse (1::'a) = 1"
  5.2903 +  shows   "fps_shift n f = f div fps_X^n"
  5.2904 +  using   assms 
  5.2905 +  by      (simp add:
  5.2906 +            fps_divide_def fps_X_power_subdegree fps_X_power_unit_factor fps_inverse_one'
  5.2907 +          )
  5.2908 +
  5.2909 +lemma fps_shift_altdef:
  5.2910 +  "fps_shift n f = (f :: 'a :: division_ring fps) div fps_X^n"
  5.2911 +  by (rule fps_shift_altdef'[OF inverse_1])
  5.2912 +
  5.2913 +lemma fps_div_fps_X_power_nth':
  5.2914 +  fixes   f :: "'a::{semiring_1,inverse,uminus} fps"
  5.2915 +  assumes "inverse (1::'a) = 1"
  5.2916 +  shows   "(f div fps_X^n) $ k = f $ (k + n)"
  5.2917 +  using   assms
  5.2918 +  by      (simp add: fps_shift_altdef' [symmetric])
  5.2919 +
  5.2920 +lemma fps_div_fps_X_power_nth: "((f :: 'a :: division_ring fps) div fps_X^n) $ k = f $ (k + n)"
  5.2921 +  by (rule fps_div_fps_X_power_nth'[OF inverse_1])
  5.2922 +
  5.2923 +lemma fps_div_fps_X_nth':
  5.2924 +  fixes   f :: "'a::{semiring_1,inverse,uminus} fps"
  5.2925 +  assumes "inverse (1::'a) = 1"
  5.2926 +  shows   "(f div fps_X) $ k = f $ Suc k"
  5.2927 +  using   assms fps_div_fps_X_power_nth'[of f 1]
  5.2928 +  by      simp
  5.2929 +
  5.2930 +lemma fps_div_fps_X_nth: "((f :: 'a :: division_ring fps) div fps_X) $ k = f $ Suc k"
  5.2931 +  by (rule fps_div_fps_X_nth'[OF inverse_1])
  5.2932 +
  5.2933 +lemma divide_fps_const':
  5.2934 +  fixes c :: "'a :: {inverse,comm_monoid_add,uminus,mult_zero}"
  5.2935 +  shows   "f / fps_const c = f * fps_const (inverse c)"
  5.2936 +  by      (simp add: fps_divide_def fps_const_inverse)
  5.2937 +
  5.2938 +lemma divide_fps_const [simp]:
  5.2939 +  fixes c :: "'a :: {comm_semiring_0,inverse,uminus}"
  5.2940 +  shows "f / fps_const c = fps_const (inverse c) * f"
  5.2941 +  by    (simp add: divide_fps_const' mult.commute)
  5.2942 +
  5.2943 +lemma fps_const_divide: "fps_const (x :: _ :: division_ring) / fps_const y = fps_const (x / y)"
  5.2944 +  by (simp add: fps_divide_def fps_const_inverse divide_inverse)
  5.2945 +
  5.2946 +lemma fps_numeral_divide_divide:
  5.2947 +  "x / numeral b / numeral c = (x / numeral (b * c) :: 'a :: field fps)"
  5.2948 +  by (simp add: fps_divide_by_mult[symmetric])
  5.2949 +
  5.2950 +lemma fps_numeral_mult_divide:
  5.2951 +  "numeral b * x / numeral c = (numeral b / numeral c * x :: 'a :: field fps)"
  5.2952 +  by (simp add: fps_divide_times2)
  5.2953 +
  5.2954 +lemmas fps_numeral_simps = 
  5.2955 +  fps_numeral_divide_divide fps_numeral_mult_divide inverse_fps_numeral neg_numeral_fps_const
  5.2956 +
  5.2957 +lemma fps_is_left_unit_iff_zeroth_is_left_unit:
  5.2958 +  fixes f :: "'a :: ring_1 fps"
  5.2959 +  shows "(\<exists>g. 1 = f * g) \<longleftrightarrow> (\<exists>k. 1 = f$0 * k)"
  5.2960 +proof
  5.2961 +  assume "\<exists>g. 1 = f * g"
  5.2962 +  then obtain g where "1 = f * g" by fast
  5.2963 +  hence "1 = f$0 * g$0" using fps_mult_nth_0[of f g] by simp
  5.2964 +  thus "\<exists>k. 1 = f$0 * k" by auto
  5.2965  next
  5.2966 -  assume A: "f$0 = 0 \<or> g$0 = 0"
  5.2967 -  hence "inverse (f * g) = 0" by simp
  5.2968 -  also from A have "... = inverse f * inverse g" by auto
  5.2969 -  finally show "inverse (f * g) = inverse f * inverse g" .
  5.2970 -qed
  5.2971 -
  5.2972 -
  5.2973 -lemma fps_inverse_gp: "inverse (Abs_fps(\<lambda>n. (1::'a::field))) =
  5.2974 -    Abs_fps (\<lambda>n. if n= 0 then 1 else if n=1 then - 1 else 0)"
  5.2975 -  apply (rule fps_inverse_unique)
  5.2976 -  apply (simp_all add: fps_eq_iff fps_mult_nth sum_zero_lemma)
  5.2977 -  done
  5.2978 -
  5.2979 -lemma subdegree_inverse [simp]: "subdegree (inverse (f::'a::field fps)) = 0"
  5.2980 -proof (cases "f$0 = 0")
  5.2981 -  assume nz: "f$0 \<noteq> 0"
  5.2982 -  hence "subdegree (inverse f) + subdegree f = subdegree (inverse f * f)"
  5.2983 -    by (subst subdegree_mult) auto
  5.2984 -  also from nz have "subdegree f = 0" by (simp add: subdegree_eq_0_iff)
  5.2985 -  also from nz have "inverse f * f = 1" by (rule inverse_mult_eq_1)
  5.2986 -  finally show "subdegree (inverse f) = 0" by simp
  5.2987 -qed (simp_all add: fps_inverse_def)
  5.2988 +  assume "\<exists>k. 1 = f$0 * k"
  5.2989 +  then obtain k where "1 = f$0 * k" by fast
  5.2990 +  hence "1 = f * fps_right_inverse f k"
  5.2991 +    using fps_right_inverse by simp
  5.2992 +  thus "\<exists>g. 1 = f * g" by fast
  5.2993 +qed
  5.2994 +
  5.2995 +lemma fps_is_right_unit_iff_zeroth_is_right_unit:
  5.2996 +  fixes f :: "'a :: ring_1 fps"
  5.2997 +  shows "(\<exists>g. 1 = g * f) \<longleftrightarrow> (\<exists>k. 1 = k * f$0)"
  5.2998 +proof
  5.2999 +  assume "\<exists>g. 1 = g * f"
  5.3000 +  then obtain g where "1 = g * f" by fast
  5.3001 +  hence "1 = g$0 * f$0" using fps_mult_nth_0[of g f] by simp
  5.3002 +  thus "\<exists>k. 1 = k * f$0" by auto
  5.3003 +next
  5.3004 +  assume "\<exists>k. 1 = k * f$0"
  5.3005 +  then obtain k where "1 = k * f$0" by fast
  5.3006 +  hence "1 = fps_left_inverse f k * f"
  5.3007 +    using fps_left_inverse by simp
  5.3008 +  thus "\<exists>g. 1 = g * f" by fast
  5.3009 +qed
  5.3010  
  5.3011  lemma fps_is_unit_iff [simp]: "(f :: 'a :: field fps) dvd 1 \<longleftrightarrow> f $ 0 \<noteq> 0"
  5.3012  proof
  5.3013 @@ -1137,204 +2655,272 @@
  5.3014    thus "f dvd 1" by (simp add: inverse_mult_eq_1[OF A, symmetric])
  5.3015  qed
  5.3016  
  5.3017 +lemma subdegree_eq_0_left:
  5.3018 +  fixes   f :: "'a::{comm_monoid_add,zero_neq_one,mult_zero} fps"
  5.3019 +  assumes "\<exists>g. 1 = f * g"
  5.3020 +  shows   "subdegree f = 0"
  5.3021 +proof (intro subdegree_eq_0)
  5.3022 +  from assms obtain g where "1 = f * g" by fast
  5.3023 +  hence "f$0 * g$0 = 1" using fps_mult_nth_0[of f g] by simp
  5.3024 +  thus "f$0 \<noteq> 0" by auto
  5.3025 +qed
  5.3026 +
  5.3027 +lemma subdegree_eq_0_right:
  5.3028 +  fixes   f :: "'a::{comm_monoid_add,zero_neq_one,mult_zero} fps"
  5.3029 +  assumes "\<exists>g. 1 = g * f"
  5.3030 +  shows   "subdegree f = 0"
  5.3031 +proof (intro subdegree_eq_0)
  5.3032 +  from assms obtain g where "1 = g * f" by fast
  5.3033 +  hence "g$0 * f$0 = 1" using fps_mult_nth_0[of g f] by simp
  5.3034 +  thus "f$0 \<noteq> 0" by auto
  5.3035 +qed
  5.3036 +
  5.3037  lemma subdegree_eq_0' [simp]: "(f :: 'a :: field fps) dvd 1 \<Longrightarrow> subdegree f = 0"
  5.3038    by simp
  5.3039  
  5.3040 +lemma fps_dvd1_left_trivial_unit_factor:
  5.3041 +  fixes   f :: "'a::{comm_monoid_add, zero_neq_one, mult_zero} fps"
  5.3042 +  assumes "\<exists>g. 1 = f * g"
  5.3043 +  shows   "unit_factor f = f"
  5.3044 +  using   assms subdegree_eq_0_left
  5.3045 +  by      fastforce
  5.3046 +
  5.3047 +lemma fps_dvd1_right_trivial_unit_factor:
  5.3048 +  fixes   f :: "'a::{comm_monoid_add, zero_neq_one, mult_zero} fps"
  5.3049 +  assumes "\<exists>g. 1 = g * f"
  5.3050 +  shows   "unit_factor f = f"
  5.3051 +  using   assms subdegree_eq_0_right
  5.3052 +  by      fastforce
  5.3053 +
  5.3054 +lemma fps_dvd1_trivial_unit_factor:
  5.3055 +  "(f :: 'a::comm_semiring_1 fps) dvd 1 \<Longrightarrow> unit_factor f = f"
  5.3056 +  unfolding dvd_def by (rule fps_dvd1_left_trivial_unit_factor) simp
  5.3057 +
  5.3058 +lemma fps_unit_dvd_left:
  5.3059 +  fixes   f :: "'a :: division_ring fps"
  5.3060 +  assumes "f $ 0 \<noteq> 0"
  5.3061 +  shows   "\<exists>g. 1 = f * g"
  5.3062 +  using   assms fps_is_left_unit_iff_zeroth_is_left_unit right_inverse
  5.3063 +  by      fastforce
  5.3064 +
  5.3065 +lemma fps_unit_dvd_right:
  5.3066 +  fixes   f :: "'a :: division_ring fps"
  5.3067 +  assumes "f $ 0 \<noteq> 0"
  5.3068 +  shows   "\<exists>g. 1 = g * f"
  5.3069 +  using   assms fps_is_right_unit_iff_zeroth_is_right_unit left_inverse
  5.3070 +  by      fastforce
  5.3071 +
  5.3072  lemma fps_unit_dvd [simp]: "(f $ 0 :: 'a :: field) \<noteq> 0 \<Longrightarrow> f dvd g"
  5.3073 -  by (rule dvd_trans, subst fps_is_unit_iff) simp_all
  5.3074 -
  5.3075 -instantiation fps :: (field) normalization_semidom
  5.3076 -begin
  5.3077 -
  5.3078 -definition fps_unit_factor_def [simp]:
  5.3079 -  "unit_factor f = fps_shift (subdegree f) f"
  5.3080 -
  5.3081 -definition fps_normalize_def [simp]:
  5.3082 -  "normalize f = (if f = 0 then 0 else fps_X ^ subdegree f)"
  5.3083 -
  5.3084 -instance proof
  5.3085 -  fix f :: "'a fps"
  5.3086 -  show "unit_factor f * normalize f = f"
  5.3087 -    by (simp add: fps_shift_times_fps_X_power)
  5.3088 -next
  5.3089 -  fix f g :: "'a fps"
  5.3090 -  show "unit_factor (f * g) = unit_factor f * unit_factor g"
  5.3091 -  proof (cases "f = 0 \<or> g = 0")
  5.3092 -    assume "\<not>(f = 0 \<or> g = 0)"
  5.3093 -    thus "unit_factor (f * g) = unit_factor f * unit_factor g"
  5.3094 -    unfolding fps_unit_factor_def
  5.3095 -      by (auto simp: fps_shift_fps_shift fps_shift_mult fps_shift_mult_right)
  5.3096 -  qed auto
  5.3097 -next
  5.3098 -  fix f g :: "'a fps"
  5.3099 -  assume "g \<noteq> 0"
  5.3100 -  then have "f * (fps_shift (subdegree g) g * inverse (fps_shift (subdegree g) g)) = f"
  5.3101 -    by (metis add_cancel_right_left fps_shift_nth inverse_mult_eq_1 mult.commute mult_cancel_left2 nth_subdegree_nonzero)
  5.3102 -  then have "fps_shift (subdegree g) (g * (f * inverse (fps_shift (subdegree g) g))) = f"
  5.3103 -    by (simp add: fps_shift_mult_right mult.commute)
  5.3104 -  with \<open>g \<noteq> 0\<close> show "f * g / g = f"
  5.3105 -    by (simp add: fps_divide_def Let_def ac_simps)
  5.3106 -qed (auto simp add: fps_divide_def Let_def)
  5.3107 -
  5.3108 -end
  5.3109 -
  5.3110 -instantiation fps :: (field) idom_modulo
  5.3111 -begin
  5.3112 -
  5.3113 -definition fps_mod_def:
  5.3114 -  "f mod g = (if g = 0 then f else
  5.3115 -     let n = subdegree g; h = fps_shift n g
  5.3116 -     in  fps_cutoff n (f * inverse h) * h)"
  5.3117 -
  5.3118 -lemma fps_mod_eq_zero:
  5.3119 -  assumes "g \<noteq> 0" and "subdegree f \<ge> subdegree g"
  5.3120 -  shows   "f mod g = 0"
  5.3121 -  using assms by (cases "f = 0") (auto simp: fps_cutoff_zero_iff fps_mod_def Let_def)
  5.3122 -
  5.3123 -lemma fps_times_divide_eq:
  5.3124 -  assumes "g \<noteq> 0" and "subdegree f \<ge> subdegree (g :: 'a fps)"
  5.3125 -  shows   "f div g * g = f"
  5.3126 -proof (cases "f = 0")
  5.3127 -  assume nz: "f \<noteq> 0"
  5.3128 -  define n where "n = subdegree g"
  5.3129 -  define h where "h = fps_shift n g"
  5.3130 -  from assms have [simp]: "h $ 0 \<noteq> 0" unfolding h_def by (simp add: n_def)
  5.3131 -
  5.3132 -  from assms nz have "f div g * g = fps_shift n (f * inverse h) * g"
  5.3133 -    by (simp add: fps_divide_def Let_def h_def n_def)
  5.3134 -  also have "... = fps_shift n (f * inverse h) * fps_X^n * h" unfolding h_def n_def
  5.3135 -    by (subst subdegree_decompose[of g]) simp
  5.3136 -  also have "fps_shift n (f * inverse h) * fps_X^n = f * inverse h"
  5.3137 -    by (rule fps_shift_times_fps_X_power) (simp_all add: nz assms n_def)
  5.3138 -  also have "... * h = f * (inverse h * h)" by simp
  5.3139 -  also have "inverse h * h = 1" by (rule inverse_mult_eq_1) simp
  5.3140 -  finally show ?thesis by simp
  5.3141 -qed (simp_all add: fps_divide_def Let_def)
  5.3142 -
  5.3143 -lemma
  5.3144 -  assumes "g$0 \<noteq> 0"
  5.3145 -  shows   fps_divide_unit: "f div g = f * inverse g" and fps_mod_unit [simp]: "f mod g = 0"
  5.3146 -proof -
  5.3147 -  from assms have [simp]: "subdegree g = 0" by (simp add: subdegree_eq_0_iff)
  5.3148 -  from assms show "f div g = f * inverse g"
  5.3149 -    by (auto simp: fps_divide_def Let_def subdegree_eq_0_iff)
  5.3150 -  from assms show "f mod g = 0" by (intro fps_mod_eq_zero) auto
  5.3151 -qed
  5.3152 -
  5.3153 -instance proof
  5.3154 -  fix f g :: "'a fps"
  5.3155 -  define n where "n = subdegree g"
  5.3156 -  define h where "h = fps_shift n g"
  5.3157 -
  5.3158 -  show "f div g * g + f mod g = f"
  5.3159 -  proof (cases "g = 0 \<or> f = 0")
  5.3160 -    assume "\<not>(g = 0 \<or> f = 0)"
  5.3161 -    hence nz [simp]: "f \<noteq> 0" "g \<noteq> 0" by simp_all
  5.3162 -    show ?thesis
  5.3163 -    proof (rule disjE[OF le_less_linear])
  5.3164 -      assume "subdegree f \<ge> subdegree g"
  5.3165 -      with nz show ?thesis by (simp add: fps_mod_eq_zero fps_times_divide_eq)
  5.3166 -    next
  5.3167 -      assume "subdegree f < subdegree g"
  5.3168 -      have g_decomp: "g = h * fps_X^n" unfolding h_def n_def by (rule subdegree_decompose)
  5.3169 -      have "f div g * g + f mod g =
  5.3170 -              fps_shift n (f * inverse h) * g + fps_cutoff n (f * inverse h) * h"
  5.3171 -        by (simp add: fps_mod_def fps_divide_def Let_def n_def h_def)
  5.3172 -      also have "... = h * (fps_shift n (f * inverse h) * fps_X^n + fps_cutoff n (f * inverse h))"
  5.3173 -        by (subst g_decomp) (simp add: algebra_simps)
  5.3174 -      also have "... = f * (inverse h * h)"
  5.3175 -        by (subst fps_shift_cutoff) simp
  5.3176 -      also have "inverse h * h = 1" by (rule inverse_mult_eq_1) (simp add: h_def n_def)
  5.3177 -      finally show ?thesis by simp
  5.3178 -    qed
  5.3179 -  qed (auto simp: fps_mod_def fps_divide_def Let_def)
  5.3180 -qed
  5.3181 -
  5.3182 -end
  5.3183 -
  5.3184 -lemma subdegree_mod:
  5.3185 -  assumes "f \<noteq> 0" "subdegree f < subdegree g"
  5.3186 -  shows   "subdegree (f mod g) = subdegree f"
  5.3187 -proof (cases "f div g * g = 0")
  5.3188 -  assume "f div g * g \<noteq> 0"
  5.3189 -  hence [simp]: "f div g \<noteq> 0" "g \<noteq> 0" by auto
  5.3190 -  from div_mult_mod_eq[of f g] have "f mod g = f - f div g * g" by (simp add: algebra_simps)
  5.3191 -  also from assms have "subdegree ... = subdegree f"
  5.3192 -    by (intro subdegree_diff_eq1) simp_all
  5.3193 -  finally show ?thesis .
  5.3194 -next
  5.3195 -  assume zero: "f div g * g = 0"
  5.3196 -  from div_mult_mod_eq[of f g] have "f mod g = f - f div g * g" by (simp add: algebra_simps)
  5.3197 -  also note zero
  5.3198 -  finally show ?thesis by simp
  5.3199 -qed
  5.3200 -
  5.3201 -lemma fps_divide_nth_0 [simp]: "g $ 0 \<noteq> 0 \<Longrightarrow> (f div g) $ 0 = f $ 0 / (g $ 0 :: _ :: field)"
  5.3202 -  by (simp add: fps_divide_unit divide_inverse)
  5.3203 -
  5.3204 +  using fps_unit_dvd_left dvd_trans[of f 1] by simp
  5.3205 +
  5.3206 +lemma dvd_left_imp_subdegree_le:
  5.3207 +  fixes   f g :: "'a::{comm_monoid_add,mult_zero} fps"
  5.3208 +  assumes "\<exists>k. g = f * k" "g \<noteq> 0"
  5.3209 +  shows   "subdegree f \<le> subdegree g"
  5.3210 +  using   assms fps_mult_subdegree_ge
  5.3211 +  by      fastforce
  5.3212 +
  5.3213 +lemma dvd_right_imp_subdegree_le:
  5.3214 +  fixes   f g :: "'a::{comm_monoid_add,mult_zero} fps"
  5.3215 +  assumes "\<exists>k. g = k * f" "g \<noteq> 0"
  5.3216 +  shows   "subdegree f \<le> subdegree g"
  5.3217 +  using   assms fps_mult_subdegree_ge
  5.3218 +  by      fastforce
  5.3219  
  5.3220  lemma dvd_imp_subdegree_le:
  5.3221 -  "(f :: 'a :: idom fps) dvd g \<Longrightarrow> g \<noteq> 0 \<Longrightarrow> subdegree f \<le> subdegree g"
  5.3222 -  by (auto elim: dvdE)
  5.3223 +  "f dvd g \<Longrightarrow> g \<noteq> 0 \<Longrightarrow> subdegree f \<le> subdegree g"
  5.3224 +  using dvd_left_imp_subdegree_le by fast
  5.3225 +
  5.3226 +lemma subdegree_le_imp_dvd_left_ring1:
  5.3227 +  fixes   f g :: "'a :: ring_1 fps"
  5.3228 +  assumes "\<exists>y. f $ subdegree f * y = 1" "subdegree f \<le> subdegree g"
  5.3229 +  shows   "\<exists>k. g = f * k"
  5.3230 +proof-
  5.3231 +  define h :: "'a fps" where "h \<equiv> fps_X ^ (subdegree g - subdegree f)"
  5.3232 +  from assms(1) obtain y where "f $ subdegree f * y = 1" by fast
  5.3233 +  hence "unit_factor f $ 0 * y = 1" by simp
  5.3234 +  from this obtain k where "1 = unit_factor f * k"
  5.3235 +    using fps_is_left_unit_iff_zeroth_is_left_unit[of "unit_factor f"] by auto
  5.3236 +  hence "fps_X ^ subdegree f = fps_X ^ subdegree f * unit_factor f * k"
  5.3237 +    by (simp add: mult.assoc)
  5.3238 +  moreover have "fps_X ^ subdegree f * unit_factor f = f"
  5.3239 +    by (rule fps_unit_factor_decompose'[symmetric])
  5.3240 +  ultimately have
  5.3241 +    "fps_X ^ (subdegree f + (subdegree g - subdegree f)) = f * k * h"
  5.3242 +    by (simp add: power_add h_def)
  5.3243 +  hence "g = f * (k * h * unit_factor g)"
  5.3244 +    using fps_unit_factor_decompose'[of g]
  5.3245 +    by    (simp add: assms(2) mult.assoc)
  5.3246 +  thus ?thesis by fast
  5.3247 +qed
  5.3248 +
  5.3249 +lemma subdegree_le_imp_dvd_left_divring:
  5.3250 +  fixes   f g :: "'a :: division_ring fps"
  5.3251 +  assumes "f \<noteq> 0" "subdegree f \<le> subdegree g"
  5.3252 +  shows   "\<exists>k. g = f * k"
  5.3253 +proof (intro subdegree_le_imp_dvd_left_ring1)
  5.3254 +  from assms(1) have "f $ subdegree f \<noteq> 0" by simp
  5.3255 +  thus "\<exists>y. f $ subdegree f * y = 1" using right_inverse by blast
  5.3256 +qed (rule assms(2))
  5.3257 +
  5.3258 +lemma subdegree_le_imp_dvd_right_ring1:
  5.3259 +  fixes   f g :: "'a :: ring_1 fps"
  5.3260 +  assumes "\<exists>x. x * f $ subdegree f = 1" "subdegree f \<le> subdegree g"
  5.3261 +