src/HOL/Analysis/Infinite_Products.thy
changeset 68361 20375f232f3b
parent 68138 c738f40e88d4
child 68424 02e5a44ffe7d
     1.1 --- a/src/HOL/Analysis/Infinite_Products.thy	Sat Jun 02 22:57:44 2018 +0100
     1.2 +++ b/src/HOL/Analysis/Infinite_Products.thy	Sun Jun 03 15:22:30 2018 +0100
     1.3 @@ -50,21 +50,21 @@
     1.4      by (rule tendsto_eq_intros refl | simp)+
     1.5  qed auto
     1.6  
     1.7 -definition gen_has_prod :: "[nat \<Rightarrow> 'a::{t2_space, comm_semiring_1}, nat, 'a] \<Rightarrow> bool" 
     1.8 -  where "gen_has_prod f M p \<equiv> (\<lambda>n. \<Prod>i\<le>n. f (i+M)) \<longlonglongrightarrow> p \<and> p \<noteq> 0"
     1.9 +definition raw_has_prod :: "[nat \<Rightarrow> 'a::{t2_space, comm_semiring_1}, nat, 'a] \<Rightarrow> bool" 
    1.10 +  where "raw_has_prod f M p \<equiv> (\<lambda>n. \<Prod>i\<le>n. f (i+M)) \<longlonglongrightarrow> p \<and> p \<noteq> 0"
    1.11  
    1.12  text\<open>The nonzero and zero cases, as in \emph{Complex Analysis} by Joseph Bak and Donald J.Newman, page 241\<close>
    1.13  definition has_prod :: "(nat \<Rightarrow> 'a::{t2_space, comm_semiring_1}) \<Rightarrow> 'a \<Rightarrow> bool" (infixr "has'_prod" 80)
    1.14 -  where "f has_prod p \<equiv> gen_has_prod f 0 p \<or> (\<exists>i q. p = 0 \<and> f i = 0 \<and> gen_has_prod f (Suc i) q)"
    1.15 +  where "f has_prod p \<equiv> raw_has_prod f 0 p \<or> (\<exists>i q. p = 0 \<and> f i = 0 \<and> raw_has_prod f (Suc i) q)"
    1.16  
    1.17  definition convergent_prod :: "(nat \<Rightarrow> 'a :: {t2_space,comm_semiring_1}) \<Rightarrow> bool" where
    1.18 -  "convergent_prod f \<equiv> \<exists>M p. gen_has_prod f M p"
    1.19 +  "convergent_prod f \<equiv> \<exists>M p. raw_has_prod f M p"
    1.20  
    1.21  definition prodinf :: "(nat \<Rightarrow> 'a::{t2_space, comm_semiring_1}) \<Rightarrow> 'a"
    1.22      (binder "\<Prod>" 10)
    1.23    where "prodinf f = (THE p. f has_prod p)"
    1.24  
    1.25 -lemmas prod_defs = gen_has_prod_def has_prod_def convergent_prod_def prodinf_def
    1.26 +lemmas prod_defs = raw_has_prod_def has_prod_def convergent_prod_def prodinf_def
    1.27  
    1.28  lemma has_prod_subst[trans]: "f = g \<Longrightarrow> g has_prod z \<Longrightarrow> f has_prod z"
    1.29    by simp
    1.30 @@ -72,34 +72,39 @@
    1.31  lemma has_prod_cong: "(\<And>n. f n = g n) \<Longrightarrow> f has_prod c \<longleftrightarrow> g has_prod c"
    1.32    by presburger
    1.33  
    1.34 -lemma gen_has_prod_nonzero [simp]: "\<not> gen_has_prod f M 0"
    1.35 -  by (simp add: gen_has_prod_def)
    1.36 +lemma raw_has_prod_nonzero [simp]: "\<not> raw_has_prod f M 0"
    1.37 +  by (simp add: raw_has_prod_def)
    1.38  
    1.39 -lemma gen_has_prod_eq_0:
    1.40 -  fixes f :: "nat \<Rightarrow> 'a::{idom,t2_space}"
    1.41 -  assumes p: "gen_has_prod f m p" and i: "f i = 0" "i \<ge> m"
    1.42 +lemma raw_has_prod_eq_0:
    1.43 +  fixes f :: "nat \<Rightarrow> 'a::{semidom,t2_space}"
    1.44 +  assumes p: "raw_has_prod f m p" and i: "f i = 0" "i \<ge> m"
    1.45    shows "p = 0"
    1.46  proof -
    1.47    have eq0: "(\<Prod>k\<le>n. f (k+m)) = 0" if "i - m \<le> n" for n
    1.48 -    by (metis i that atMost_atLeast0 atMost_iff diff_add finite_atLeastAtMost prod_zero_iff)
    1.49 +  proof -
    1.50 +    have "\<exists>k\<le>n. f (k + m) = 0"
    1.51 +      using i that by auto
    1.52 +    then show ?thesis
    1.53 +      by auto
    1.54 +  qed
    1.55    have "(\<lambda>n. \<Prod>i\<le>n. f (i + m)) \<longlonglongrightarrow> 0"
    1.56      by (rule LIMSEQ_offset [where k = "i-m"]) (simp add: eq0)
    1.57      with p show ?thesis
    1.58 -      unfolding gen_has_prod_def
    1.59 +      unfolding raw_has_prod_def
    1.60      using LIMSEQ_unique by blast
    1.61  qed
    1.62  
    1.63 -lemma has_prod_0_iff: "f has_prod 0 \<longleftrightarrow> (\<exists>i. f i = 0 \<and> (\<exists>p. gen_has_prod f (Suc i) p))"
    1.64 +lemma has_prod_0_iff: "f has_prod 0 \<longleftrightarrow> (\<exists>i. f i = 0 \<and> (\<exists>p. raw_has_prod f (Suc i) p))"
    1.65    by (simp add: has_prod_def)
    1.66        
    1.67  lemma has_prod_unique2: 
    1.68 -  fixes f :: "nat \<Rightarrow> 'a::{idom,t2_space}"
    1.69 +  fixes f :: "nat \<Rightarrow> 'a::{semidom,t2_space}"
    1.70    assumes "f has_prod a" "f has_prod b" shows "a = b"
    1.71    using assms
    1.72 -  by (auto simp: has_prod_def gen_has_prod_eq_0) (meson gen_has_prod_def sequentially_bot tendsto_unique)
    1.73 +  by (auto simp: has_prod_def raw_has_prod_eq_0) (meson raw_has_prod_def sequentially_bot tendsto_unique)
    1.74  
    1.75  lemma has_prod_unique:
    1.76 -  fixes f :: "nat \<Rightarrow> 'a :: {idom,t2_space}"
    1.77 +  fixes f :: "nat \<Rightarrow> 'a :: {semidom,t2_space}"
    1.78    shows "f has_prod s \<Longrightarrow> s = prodinf f"
    1.79    by (simp add: has_prod_unique2 prodinf_def the_equality)
    1.80  
    1.81 @@ -378,42 +383,55 @@
    1.82    shows   "abs_convergent_prod f"
    1.83    using assms unfolding abs_convergent_prod_def by (rule convergent_prod_offset)
    1.84  
    1.85 -lemma convergent_prod_ignore_initial_segment:
    1.86 -  fixes f :: "nat \<Rightarrow> 'a :: {real_normed_field}"
    1.87 -  assumes "convergent_prod f"
    1.88 -  shows   "convergent_prod (\<lambda>n. f (n + m))"
    1.89 +lemma raw_has_prod_ignore_initial_segment:
    1.90 +  fixes f :: "nat \<Rightarrow> 'a :: real_normed_field"
    1.91 +  assumes "raw_has_prod f M p" "N \<ge> M"
    1.92 +  obtains q where  "raw_has_prod f N q"
    1.93  proof -
    1.94 -  from assms obtain M L 
    1.95 -    where L: "(\<lambda>n. \<Prod>k\<le>n. f (k + M)) \<longlonglongrightarrow> L" "L \<noteq> 0" and nz: "\<And>n. n \<ge> M \<Longrightarrow> f n \<noteq> 0"
    1.96 -    by (auto simp: convergent_prod_altdef)
    1.97 -  define C where "C = (\<Prod>k<m. f (k + M))"
    1.98 +  have p: "(\<lambda>n. \<Prod>k\<le>n. f (k + M)) \<longlonglongrightarrow> p" and "p \<noteq> 0" 
    1.99 +    using assms by (auto simp: raw_has_prod_def)
   1.100 +  then have nz: "\<And>n. n \<ge> M \<Longrightarrow> f n \<noteq> 0"
   1.101 +    using assms by (auto simp: raw_has_prod_eq_0)
   1.102 +  define C where "C = (\<Prod>k<N-M. f (k + M))"
   1.103    from nz have [simp]: "C \<noteq> 0" 
   1.104      by (auto simp: C_def)
   1.105  
   1.106 -  from L(1) have "(\<lambda>n. \<Prod>k\<le>n+m. f (k + M)) \<longlonglongrightarrow> L" 
   1.107 +  from p have "(\<lambda>i. \<Prod>k\<le>i + (N-M). f (k + M)) \<longlonglongrightarrow> p" 
   1.108      by (rule LIMSEQ_ignore_initial_segment)
   1.109 -  also have "(\<lambda>n. \<Prod>k\<le>n+m. f (k + M)) = (\<lambda>n. C * (\<Prod>k\<le>n. f (k + M + m)))"
   1.110 +  also have "(\<lambda>i. \<Prod>k\<le>i + (N-M). f (k + M)) = (\<lambda>n. C * (\<Prod>k\<le>n. f (k + N)))"
   1.111    proof (rule ext, goal_cases)
   1.112      case (1 n)
   1.113 -    have "{..n+m} = {..<m} \<union> {m..n+m}" by auto
   1.114 -    also have "(\<Prod>k\<in>\<dots>. f (k + M)) = C * (\<Prod>k=m..n+m. f (k + M))"
   1.115 +    have "{..n+(N-M)} = {..<(N-M)} \<union> {(N-M)..n+(N-M)}" by auto
   1.116 +    also have "(\<Prod>k\<in>\<dots>. f (k + M)) = C * (\<Prod>k=(N-M)..n+(N-M). f (k + M))"
   1.117        unfolding C_def by (rule prod.union_disjoint) auto
   1.118 -    also have "(\<Prod>k=m..n+m. f (k + M)) = (\<Prod>k\<le>n. f (k + m + M))"
   1.119 -      by (intro ext prod.reindex_bij_witness[of _ "\<lambda>k. k + m" "\<lambda>k. k - m"]) auto
   1.120 -    finally show ?case by (simp add: add_ac)
   1.121 +    also have "(\<Prod>k=(N-M)..n+(N-M). f (k + M)) = (\<Prod>k\<le>n. f (k + (N-M) + M))"
   1.122 +      by (intro ext prod.reindex_bij_witness[of _ "\<lambda>k. k + (N-M)" "\<lambda>k. k - (N-M)"]) auto
   1.123 +    finally show ?case
   1.124 +      using \<open>N \<ge> M\<close> by (simp add: add_ac)
   1.125    qed
   1.126 -  finally have "(\<lambda>n. C * (\<Prod>k\<le>n. f (k + M + m)) / C) \<longlonglongrightarrow> L / C"
   1.127 +  finally have "(\<lambda>n. C * (\<Prod>k\<le>n. f (k + N)) / C) \<longlonglongrightarrow> p / C"
   1.128      by (intro tendsto_divide tendsto_const) auto
   1.129 -  hence "(\<lambda>n. \<Prod>k\<le>n. f (k + M + m)) \<longlonglongrightarrow> L / C" by simp
   1.130 -  moreover from \<open>L \<noteq> 0\<close> have "L / C \<noteq> 0" by simp
   1.131 -  ultimately show ?thesis 
   1.132 -    unfolding prod_defs by blast
   1.133 +  hence "(\<lambda>n. \<Prod>k\<le>n. f (k + N)) \<longlonglongrightarrow> p / C" by simp
   1.134 +  moreover from \<open>p \<noteq> 0\<close> have "p / C \<noteq> 0" by simp
   1.135 +  ultimately show ?thesis
   1.136 +    using raw_has_prod_def that by blast 
   1.137  qed
   1.138  
   1.139 +corollary convergent_prod_ignore_initial_segment:
   1.140 +  fixes f :: "nat \<Rightarrow> 'a :: real_normed_field"
   1.141 +  assumes "convergent_prod f"
   1.142 +  shows   "convergent_prod (\<lambda>n. f (n + m))"
   1.143 +  using assms
   1.144 +  unfolding convergent_prod_def 
   1.145 +  apply clarify
   1.146 +  apply (erule_tac N="M+m" in raw_has_prod_ignore_initial_segment)
   1.147 +  apply (auto simp add: raw_has_prod_def add_ac)
   1.148 +  done
   1.149 +
   1.150  corollary convergent_prod_ignore_nonzero_segment:
   1.151    fixes f :: "nat \<Rightarrow> 'a :: real_normed_field"
   1.152    assumes f: "convergent_prod f" and nz: "\<And>i. i \<ge> M \<Longrightarrow> f i \<noteq> 0"
   1.153 -  shows "\<exists>p. gen_has_prod f M p"
   1.154 +  shows "\<exists>p. raw_has_prod f M p"
   1.155    using convergent_prod_ignore_initial_segment [OF f]
   1.156    by (metis convergent_LIMSEQ_iff convergent_prod_iff_convergent le_add_same_cancel2 nz prod_defs(1) zero_order(1))
   1.157  
   1.158 @@ -551,13 +569,13 @@
   1.159    with L show ?thesis by (auto simp: prod_defs)
   1.160  qed
   1.161  
   1.162 -lemma gen_has_prod_cases:
   1.163 +lemma raw_has_prod_cases:
   1.164    fixes f :: "nat \<Rightarrow> 'a :: {idom,topological_semigroup_mult,t2_space}"
   1.165 -  assumes "gen_has_prod f M p"
   1.166 -  obtains i where "i<M" "f i = 0" | p where "gen_has_prod f 0 p"
   1.167 +  assumes "raw_has_prod f M p"
   1.168 +  obtains i where "i<M" "f i = 0" | p where "raw_has_prod f 0 p"
   1.169  proof -
   1.170    have "(\<lambda>n. \<Prod>i\<le>n. f (i + M)) \<longlonglongrightarrow> p" "p \<noteq> 0"
   1.171 -    using assms unfolding gen_has_prod_def by blast+
   1.172 +    using assms unfolding raw_has_prod_def by blast+
   1.173    then have "(\<lambda>n. prod f {..<M} * (\<Prod>i\<le>n. f (i + M))) \<longlonglongrightarrow> prod f {..<M} * p"
   1.174      by (metis tendsto_mult_left)
   1.175    moreover have "prod f {..<M} * (\<Prod>i\<le>n. f (i + M)) = prod f {..n+M}" for n
   1.176 @@ -572,8 +590,8 @@
   1.177    qed
   1.178    ultimately have "(\<lambda>n. prod f {..n}) \<longlonglongrightarrow> prod f {..<M} * p"
   1.179      by (auto intro: LIMSEQ_offset [where k=M])
   1.180 -  then have "gen_has_prod f 0 (prod f {..<M} * p)" if "\<forall>i<M. f i \<noteq> 0"
   1.181 -    using \<open>p \<noteq> 0\<close> assms that by (auto simp: gen_has_prod_def)
   1.182 +  then have "raw_has_prod f 0 (prod f {..<M} * p)" if "\<forall>i<M. f i \<noteq> 0"
   1.183 +    using \<open>p \<noteq> 0\<close> assms that by (auto simp: raw_has_prod_def)
   1.184    then show thesis
   1.185      using that by blast
   1.186  qed
   1.187 @@ -581,8 +599,8 @@
   1.188  corollary convergent_prod_offset_0:
   1.189    fixes f :: "nat \<Rightarrow> 'a :: {idom,topological_semigroup_mult,t2_space}"
   1.190    assumes "convergent_prod f" "\<And>i. f i \<noteq> 0"
   1.191 -  shows "\<exists>p. gen_has_prod f 0 p"
   1.192 -  using assms convergent_prod_def gen_has_prod_cases by blast
   1.193 +  shows "\<exists>p. raw_has_prod f 0 p"
   1.194 +  using assms convergent_prod_def raw_has_prod_cases by blast
   1.195  
   1.196  lemma prodinf_eq_lim:
   1.197    fixes f :: "nat \<Rightarrow> 'a :: {idom,topological_semigroup_mult,t2_space}"
   1.198 @@ -648,7 +666,7 @@
   1.199  qed
   1.200  
   1.201  lemma has_prod_finite:
   1.202 -  fixes f :: "nat \<Rightarrow> 'a::{idom,t2_space}"
   1.203 +  fixes f :: "nat \<Rightarrow> 'a::{semidom,t2_space}"
   1.204    assumes [simp]: "finite N"
   1.205      and f: "\<And>n. n \<notin> N \<Longrightarrow> f n = 1"
   1.206    shows "f has_prod (\<Prod>n\<in>N. f n)"
   1.207 @@ -668,7 +686,7 @@
   1.208      moreover have "(\<lambda>n. prod f {..n}) \<longlonglongrightarrow> prod f N"
   1.209        by (rule LIMSEQ_offset[of _ "Suc (Max N)"]) (simp add: eq atLeast0LessThan del: add_Suc_right)
   1.210      ultimately show ?thesis
   1.211 -      by (simp add: gen_has_prod_def has_prod_def)
   1.212 +      by (simp add: raw_has_prod_def has_prod_def)
   1.213    next
   1.214      case False
   1.215      then obtain k where "k \<in> N" "f k = 0"
   1.216 @@ -692,8 +710,8 @@
   1.217             (use Max.coboundedI [OF \<open>finite N\<close>] f in \<open>force+\<close>)
   1.218        finally show ?thesis .
   1.219      qed
   1.220 -    have q: "gen_has_prod f (Suc (Max ?Z)) ?q"
   1.221 -    proof (simp add: gen_has_prod_def)
   1.222 +    have q: "raw_has_prod f (Suc (Max ?Z)) ?q"
   1.223 +    proof (simp add: raw_has_prod_def)
   1.224        show "(\<lambda>n. \<Prod>i\<le>n. f (Suc (i + Max ?Z))) \<longlonglongrightarrow> ?q"
   1.225          by (rule LIMSEQ_offset[of _ "(Max N)"]) (simp add: eq)
   1.226      qed
   1.227 @@ -709,17 +727,20 @@
   1.228  qed
   1.229  
   1.230  corollary has_prod_0:
   1.231 -  fixes f :: "nat \<Rightarrow> 'a::{idom,t2_space}"
   1.232 +  fixes f :: "nat \<Rightarrow> 'a::{semidom,t2_space}"
   1.233    assumes "\<And>n. f n = 1"
   1.234    shows "f has_prod 1"
   1.235    by (simp add: assms has_prod_cong)
   1.236  
   1.237 +lemma prodinf_zero[simp]: "prodinf (\<lambda>n. 1::'a::real_normed_field) = 1"
   1.238 +  using has_prod_unique by force
   1.239 +
   1.240  lemma convergent_prod_finite:
   1.241    fixes f :: "nat \<Rightarrow> 'a::{idom,t2_space}"
   1.242    assumes "finite N" "\<And>n. n \<notin> N \<Longrightarrow> f n = 1"
   1.243    shows "convergent_prod f"
   1.244  proof -
   1.245 -  have "\<exists>n p. gen_has_prod f n p"
   1.246 +  have "\<exists>n p. raw_has_prod f n p"
   1.247      using assms has_prod_def has_prod_finite by blast
   1.248    then show ?thesis
   1.249      by (simp add: convergent_prod_def)
   1.250 @@ -759,12 +780,12 @@
   1.251    assumes "convergent_prod f"
   1.252    shows "\<exists>p. f has_prod p"
   1.253  proof -
   1.254 -  obtain M p where p: "gen_has_prod f M p"
   1.255 +  obtain M p where p: "raw_has_prod f M p"
   1.256      using assms convergent_prod_def by blast
   1.257    then have "p \<noteq> 0"
   1.258 -    using gen_has_prod_nonzero by blast
   1.259 +    using raw_has_prod_nonzero by blast
   1.260    with p have fnz: "f i \<noteq> 0" if "i \<ge> M" for i
   1.261 -    using gen_has_prod_eq_0 that by blast
   1.262 +    using raw_has_prod_eq_0 that by blast
   1.263    define C where "C = (\<Prod>n<M. f n)"
   1.264    show ?thesis
   1.265    proof (cases "\<forall>n\<le>M. f n \<noteq> 0")
   1.266 @@ -781,7 +802,7 @@
   1.267        by (metis (mono_tags, lifting) GreatestI_ex_nat nat_le_linear)
   1.268      have "f i \<noteq> 0" if "i > ?N" for i
   1.269        by (metis (mono_tags, lifting) Greatest_le_nat fnz leD linear that)
   1.270 -    then have "\<exists>p. gen_has_prod f (Suc ?N) p"
   1.271 +    then have "\<exists>p. raw_has_prod f (Suc ?N) p"
   1.272        using assms by (auto simp: intro!: convergent_prod_ignore_nonzero_segment)
   1.273      then show ?thesis
   1.274        unfolding has_prod_def using 0 by blast
   1.275 @@ -796,7 +817,7 @@
   1.276  lemma convergent_prod_LIMSEQ:
   1.277    shows "convergent_prod f \<Longrightarrow> (\<lambda>n. \<Prod>i\<le>n. f i) \<longlonglongrightarrow> prodinf f"
   1.278    by (metis convergent_LIMSEQ_iff convergent_prod_has_prod convergent_prod_imp_convergent 
   1.279 -      convergent_prod_to_zero_iff gen_has_prod_eq_0 has_prod_def prodinf_eq_lim zero_le)
   1.280 +      convergent_prod_to_zero_iff raw_has_prod_eq_0 has_prod_def prodinf_eq_lim zero_le)
   1.281  
   1.282  lemma has_prod_iff: "f has_prod x \<longleftrightarrow> convergent_prod f \<and> prodinf f = x"
   1.283  proof
   1.284 @@ -818,4 +839,494 @@
   1.285  
   1.286  end
   1.287  
   1.288 +subsection \<open>Infinite products on ordered, topological monoids\<close>
   1.289 +
   1.290 +lemma LIMSEQ_prod_0: 
   1.291 +  fixes f :: "nat \<Rightarrow> 'a::{semidom,topological_space}"
   1.292 +  assumes "f i = 0"
   1.293 +  shows "(\<lambda>n. prod f {..n}) \<longlonglongrightarrow> 0"
   1.294 +proof (subst tendsto_cong)
   1.295 +  show "\<forall>\<^sub>F n in sequentially. prod f {..n} = 0"
   1.296 +  proof
   1.297 +    show "prod f {..n} = 0" if "n \<ge> i" for n
   1.298 +      using that assms by auto
   1.299 +  qed
   1.300 +qed auto
   1.301 +
   1.302 +lemma LIMSEQ_prod_nonneg: 
   1.303 +  fixes f :: "nat \<Rightarrow> 'a::{linordered_semidom,linorder_topology}"
   1.304 +  assumes 0: "\<And>n. 0 \<le> f n" and a: "(\<lambda>n. prod f {..n}) \<longlonglongrightarrow> a"
   1.305 +  shows "a \<ge> 0"
   1.306 +  by (simp add: "0" prod_nonneg LIMSEQ_le_const [OF a])
   1.307 +
   1.308 +
   1.309 +context
   1.310 +  fixes f :: "nat \<Rightarrow> 'a::{linordered_semidom,linorder_topology}"
   1.311 +begin
   1.312 +
   1.313 +lemma has_prod_le:
   1.314 +  assumes f: "f has_prod a" and g: "g has_prod b" and le: "\<And>n. 0 \<le> f n \<and> f n \<le> g n"
   1.315 +  shows "a \<le> b"
   1.316 +proof (cases "a=0 \<or> b=0")
   1.317 +  case True
   1.318 +  then show ?thesis
   1.319 +  proof
   1.320 +    assume [simp]: "a=0"
   1.321 +    have "b \<ge> 0"
   1.322 +    proof (rule LIMSEQ_prod_nonneg)
   1.323 +      show "(\<lambda>n. prod g {..n}) \<longlonglongrightarrow> b"
   1.324 +        using g by (auto simp: has_prod_def raw_has_prod_def LIMSEQ_prod_0)
   1.325 +    qed (use le order_trans in auto)
   1.326 +    then show ?thesis
   1.327 +      by auto
   1.328 +  next
   1.329 +    assume [simp]: "b=0"
   1.330 +    then obtain i where "g i = 0"    
   1.331 +      using g by (auto simp: prod_defs)
   1.332 +    then have "f i = 0"
   1.333 +      using antisym le by force
   1.334 +    then have "a=0"
   1.335 +      using f by (auto simp: prod_defs LIMSEQ_prod_0 LIMSEQ_unique)
   1.336 +    then show ?thesis
   1.337 +      by auto
   1.338 +  qed
   1.339 +next
   1.340 +  case False
   1.341 +  then show ?thesis
   1.342 +    using assms
   1.343 +    unfolding has_prod_def raw_has_prod_def
   1.344 +    by (force simp: LIMSEQ_prod_0 intro!: LIMSEQ_le prod_mono)
   1.345 +qed
   1.346 +
   1.347 +lemma prodinf_le: 
   1.348 +  assumes f: "f has_prod a" and g: "g has_prod b" and le: "\<And>n. 0 \<le> f n \<and> f n \<le> g n"
   1.349 +  shows "prodinf f \<le> prodinf g"
   1.350 +  using has_prod_le [OF assms] has_prod_unique f g  by blast
   1.351 +
   1.352  end
   1.353 +
   1.354 +
   1.355 +lemma prod_le_prodinf: 
   1.356 +  fixes f :: "nat \<Rightarrow> 'a::{linordered_idom,linorder_topology}"
   1.357 +  assumes "f has_prod a" "\<And>i. 0 \<le> f i" "\<And>i. i\<ge>n \<Longrightarrow> 1 \<le> f i"
   1.358 +  shows "prod f {..<n} \<le> prodinf f"
   1.359 +  by(rule has_prod_le[OF has_prod_If_finite_set]) (use assms has_prod_unique in auto)
   1.360 +
   1.361 +lemma prodinf_nonneg:
   1.362 +  fixes f :: "nat \<Rightarrow> 'a::{linordered_idom,linorder_topology}"
   1.363 +  assumes "f has_prod a" "\<And>i. 1 \<le> f i" 
   1.364 +  shows "1 \<le> prodinf f"
   1.365 +  using prod_le_prodinf[of f a 0] assms
   1.366 +  by (metis order_trans prod_ge_1 zero_le_one)
   1.367 +
   1.368 +lemma prodinf_le_const:
   1.369 +  fixes f :: "nat \<Rightarrow> real"
   1.370 +  assumes "convergent_prod f" "\<And>n. prod f {..<n} \<le> x" 
   1.371 +  shows "prodinf f \<le> x"
   1.372 +  by (metis lessThan_Suc_atMost assms convergent_prod_LIMSEQ LIMSEQ_le_const2)
   1.373 +
   1.374 +lemma prodinf_eq_one_iff: 
   1.375 +  fixes f :: "nat \<Rightarrow> real"
   1.376 +  assumes f: "convergent_prod f" and ge1: "\<And>n. 1 \<le> f n"
   1.377 +  shows "prodinf f = 1 \<longleftrightarrow> (\<forall>n. f n = 1)"
   1.378 +proof
   1.379 +  assume "prodinf f = 1" 
   1.380 +  then have "(\<lambda>n. \<Prod>i<n. f i) \<longlonglongrightarrow> 1"
   1.381 +    using convergent_prod_LIMSEQ[of f] assms by (simp add: LIMSEQ_lessThan_iff_atMost)
   1.382 +  then have "\<And>i. (\<Prod>n\<in>{i}. f n) \<le> 1"
   1.383 +  proof (rule LIMSEQ_le_const)
   1.384 +    have "1 \<le> prod f n" for n
   1.385 +      by (simp add: ge1 prod_ge_1)
   1.386 +    have "prod f {..<n} = 1" for n
   1.387 +      by (metis \<open>\<And>n. 1 \<le> prod f n\<close> \<open>prodinf f = 1\<close> antisym f convergent_prod_has_prod ge1 order_trans prod_le_prodinf zero_le_one)
   1.388 +    then have "(\<Prod>n\<in>{i}. f n) \<le> prod f {..<n}" if "n \<ge> Suc i" for i n
   1.389 +      by (metis mult.left_neutral order_refl prod.cong prod.neutral_const prod_lessThan_Suc)
   1.390 +    then show "\<exists>N. \<forall>n\<ge>N. (\<Prod>n\<in>{i}. f n) \<le> prod f {..<n}" for i
   1.391 +      by blast      
   1.392 +  qed
   1.393 +  with ge1 show "\<forall>n. f n = 1"
   1.394 +    by (auto intro!: antisym)
   1.395 +qed (metis prodinf_zero fun_eq_iff)
   1.396 +
   1.397 +lemma prodinf_pos_iff:
   1.398 +  fixes f :: "nat \<Rightarrow> real"
   1.399 +  assumes "convergent_prod f" "\<And>n. 1 \<le> f n"
   1.400 +  shows "1 < prodinf f \<longleftrightarrow> (\<exists>i. 1 < f i)"
   1.401 +  using prod_le_prodinf[of f 1] prodinf_eq_one_iff
   1.402 +  by (metis convergent_prod_has_prod assms less_le prodinf_nonneg)
   1.403 +
   1.404 +lemma less_1_prodinf2:
   1.405 +  fixes f :: "nat \<Rightarrow> real"
   1.406 +  assumes "convergent_prod f" "\<And>n. 1 \<le> f n" "1 < f i"
   1.407 +  shows "1 < prodinf f"
   1.408 +proof -
   1.409 +  have "1 < (\<Prod>n<Suc i. f n)"
   1.410 +    using assms  by (intro less_1_prod2[where i=i]) auto
   1.411 +  also have "\<dots> \<le> prodinf f"
   1.412 +    by (intro prod_le_prodinf) (use assms order_trans zero_le_one in \<open>blast+\<close>)
   1.413 +  finally show ?thesis .
   1.414 +qed
   1.415 +
   1.416 +lemma less_1_prodinf:
   1.417 +  fixes f :: "nat \<Rightarrow> real"
   1.418 +  shows "\<lbrakk>convergent_prod f; \<And>n. 1 < f n\<rbrakk> \<Longrightarrow> 1 < prodinf f"
   1.419 +  by (intro less_1_prodinf2[where i=1]) (auto intro: less_imp_le)
   1.420 +
   1.421 +lemma prodinf_nonzero:
   1.422 +  fixes f :: "nat \<Rightarrow> 'a :: {idom,topological_semigroup_mult,t2_space}"
   1.423 +  assumes "convergent_prod f" "\<And>i. f i \<noteq> 0"
   1.424 +  shows "prodinf f \<noteq> 0"
   1.425 +  by (metis assms convergent_prod_offset_0 has_prod_unique raw_has_prod_def has_prod_def)
   1.426 +
   1.427 +lemma less_0_prodinf:
   1.428 +  fixes f :: "nat \<Rightarrow> real"
   1.429 +  assumes f: "convergent_prod f" and 0: "\<And>i. f i > 0"
   1.430 +  shows "0 < prodinf f"
   1.431 +proof -
   1.432 +  have "prodinf f \<noteq> 0"
   1.433 +    by (metis assms less_irrefl prodinf_nonzero)
   1.434 +  moreover have "0 < (\<Prod>n<i. f n)" for i
   1.435 +    by (simp add: 0 prod_pos)
   1.436 +  then have "prodinf f \<ge> 0"
   1.437 +    using convergent_prod_LIMSEQ [OF f] LIMSEQ_prod_nonneg 0 less_le by blast
   1.438 +  ultimately show ?thesis
   1.439 +    by auto
   1.440 +qed
   1.441 +
   1.442 +lemma prod_less_prodinf2:
   1.443 +  fixes f :: "nat \<Rightarrow> real"
   1.444 +  assumes f: "convergent_prod f" and 1: "\<And>m. m\<ge>n \<Longrightarrow> 1 \<le> f m" and 0: "\<And>m. 0 < f m" and i: "n \<le> i" "1 < f i"
   1.445 +  shows "prod f {..<n} < prodinf f"
   1.446 +proof -
   1.447 +  have "prod f {..<n} \<le> prod f {..<i}"
   1.448 +    by (rule prod_mono2) (use assms less_le in auto)
   1.449 +  then have "prod f {..<n} < f i * prod f {..<i}"
   1.450 +    using mult_less_le_imp_less[of 1 "f i" "prod f {..<n}" "prod f {..<i}"] assms
   1.451 +    by (simp add: prod_pos)
   1.452 +  moreover have "prod f {..<Suc i} \<le> prodinf f"
   1.453 +    using prod_le_prodinf[of f _ "Suc i"]
   1.454 +    by (meson "0" "1" Suc_leD convergent_prod_has_prod f \<open>n \<le> i\<close> le_trans less_eq_real_def)
   1.455 +  ultimately show ?thesis
   1.456 +    by (metis le_less_trans mult.commute not_le prod_lessThan_Suc)
   1.457 +qed
   1.458 +
   1.459 +lemma prod_less_prodinf:
   1.460 +  fixes f :: "nat \<Rightarrow> real"
   1.461 +  assumes f: "convergent_prod f" and 1: "\<And>m. m\<ge>n \<Longrightarrow> 1 < f m" and 0: "\<And>m. 0 < f m" 
   1.462 +  shows "prod f {..<n} < prodinf f"
   1.463 +  by (meson "0" "1" f le_less prod_less_prodinf2)
   1.464 +
   1.465 +lemma raw_has_prodI_bounded:
   1.466 +  fixes f :: "nat \<Rightarrow> real"
   1.467 +  assumes pos: "\<And>n. 1 \<le> f n"
   1.468 +    and le: "\<And>n. (\<Prod>i<n. f i) \<le> x"
   1.469 +  shows "\<exists>p. raw_has_prod f 0 p"
   1.470 +  unfolding raw_has_prod_def add_0_right
   1.471 +proof (rule exI LIMSEQ_incseq_SUP conjI)+
   1.472 +  show "bdd_above (range (\<lambda>n. prod f {..n}))"
   1.473 +    by (metis bdd_aboveI2 le lessThan_Suc_atMost)
   1.474 +  then have "(SUP i. prod f {..i}) > 0"
   1.475 +    by (metis UNIV_I cSUP_upper less_le_trans pos prod_pos zero_less_one)
   1.476 +  then show "(SUP i. prod f {..i}) \<noteq> 0"
   1.477 +    by auto
   1.478 +  show "incseq (\<lambda>n. prod f {..n})"
   1.479 +    using pos order_trans [OF zero_le_one] by (auto simp: mono_def intro!: prod_mono2)
   1.480 +qed
   1.481 +
   1.482 +lemma convergent_prodI_nonneg_bounded:
   1.483 +  fixes f :: "nat \<Rightarrow> real"
   1.484 +  assumes "\<And>n. 1 \<le> f n" "\<And>n. (\<Prod>i<n. f i) \<le> x"
   1.485 +  shows "convergent_prod f"
   1.486 +  using convergent_prod_def raw_has_prodI_bounded [OF assms] by blast
   1.487 +
   1.488 +
   1.489 +subsection \<open>Infinite products on topological monoids\<close>
   1.490 +
   1.491 +context
   1.492 +  fixes f g :: "nat \<Rightarrow> 'a::{t2_space,topological_semigroup_mult,idom}"
   1.493 +begin
   1.494 +
   1.495 +lemma raw_has_prod_mult: "\<lbrakk>raw_has_prod f M a; raw_has_prod g M b\<rbrakk> \<Longrightarrow> raw_has_prod (\<lambda>n. f n * g n) M (a * b)"
   1.496 +  by (force simp add: prod.distrib tendsto_mult raw_has_prod_def)
   1.497 +
   1.498 +lemma has_prod_mult_nz: "\<lbrakk>f has_prod a; g has_prod b; a \<noteq> 0; b \<noteq> 0\<rbrakk> \<Longrightarrow> (\<lambda>n. f n * g n) has_prod (a * b)"
   1.499 +  by (simp add: raw_has_prod_mult has_prod_def)
   1.500 +
   1.501 +end
   1.502 +
   1.503 +
   1.504 +context
   1.505 +  fixes f g :: "nat \<Rightarrow> 'a::real_normed_field"
   1.506 +begin
   1.507 +
   1.508 +lemma has_prod_mult:
   1.509 +  assumes f: "f has_prod a" and g: "g has_prod b"
   1.510 +  shows "(\<lambda>n. f n * g n) has_prod (a * b)"
   1.511 +  using f [unfolded has_prod_def]
   1.512 +proof (elim disjE exE conjE)
   1.513 +  assume f0: "raw_has_prod f 0 a"
   1.514 +  show ?thesis
   1.515 +    using g [unfolded has_prod_def]
   1.516 +  proof (elim disjE exE conjE)
   1.517 +    assume g0: "raw_has_prod g 0 b"
   1.518 +    with f0 show ?thesis
   1.519 +      by (force simp add: has_prod_def prod.distrib tendsto_mult raw_has_prod_def)
   1.520 +  next
   1.521 +    fix j q
   1.522 +    assume "b = 0" and "g j = 0" and q: "raw_has_prod g (Suc j) q"
   1.523 +    obtain p where p: "raw_has_prod f (Suc j) p"
   1.524 +      using f0 raw_has_prod_ignore_initial_segment by blast
   1.525 +    then have "Ex (raw_has_prod (\<lambda>n. f n * g n) (Suc j))"
   1.526 +      using q raw_has_prod_mult by blast
   1.527 +    then show ?thesis
   1.528 +      using \<open>b = 0\<close> \<open>g j = 0\<close> has_prod_0_iff by fastforce
   1.529 +  qed
   1.530 +next
   1.531 +  fix i p
   1.532 +  assume "a = 0" and "f i = 0" and p: "raw_has_prod f (Suc i) p"
   1.533 +  show ?thesis
   1.534 +    using g [unfolded has_prod_def]
   1.535 +  proof (elim disjE exE conjE)
   1.536 +    assume g0: "raw_has_prod g 0 b"
   1.537 +    obtain q where q: "raw_has_prod g (Suc i) q"
   1.538 +      using g0 raw_has_prod_ignore_initial_segment by blast
   1.539 +    then have "Ex (raw_has_prod (\<lambda>n. f n * g n) (Suc i))"
   1.540 +      using raw_has_prod_mult p by blast
   1.541 +    then show ?thesis
   1.542 +      using \<open>a = 0\<close> \<open>f i = 0\<close> has_prod_0_iff by fastforce
   1.543 +  next
   1.544 +    fix j q
   1.545 +    assume "b = 0" and "g j = 0" and q: "raw_has_prod g (Suc j) q"
   1.546 +    obtain p' where p': "raw_has_prod f (Suc (max i j)) p'"
   1.547 +      by (metis raw_has_prod_ignore_initial_segment max_Suc_Suc max_def p)
   1.548 +    moreover
   1.549 +    obtain q' where q': "raw_has_prod g (Suc (max i j)) q'"
   1.550 +      by (metis raw_has_prod_ignore_initial_segment max.cobounded2 max_Suc_Suc q)
   1.551 +    ultimately show ?thesis
   1.552 +      using \<open>b = 0\<close> by (simp add: has_prod_def) (metis \<open>f i = 0\<close> \<open>g j = 0\<close> raw_has_prod_mult max_def)
   1.553 +  qed
   1.554 +qed
   1.555 +
   1.556 +lemma convergent_prod_mult:
   1.557 +  assumes f: "convergent_prod f" and g: "convergent_prod g"
   1.558 +  shows "convergent_prod (\<lambda>n. f n * g n)"
   1.559 +  unfolding convergent_prod_def
   1.560 +proof -
   1.561 +  obtain M p N q where p: "raw_has_prod f M p" and q: "raw_has_prod g N q"
   1.562 +    using convergent_prod_def f g by blast+
   1.563 +  then obtain p' q' where p': "raw_has_prod f (max M N) p'" and q': "raw_has_prod g (max M N) q'"
   1.564 +    by (meson raw_has_prod_ignore_initial_segment max.cobounded1 max.cobounded2)
   1.565 +  then show "\<exists>M p. raw_has_prod (\<lambda>n. f n * g n) M p"
   1.566 +    using raw_has_prod_mult by blast
   1.567 +qed
   1.568 +
   1.569 +lemma prodinf_mult: "convergent_prod f \<Longrightarrow> convergent_prod g \<Longrightarrow> prodinf f * prodinf g = (\<Prod>n. f n * g n)"
   1.570 +  by (intro has_prod_unique has_prod_mult convergent_prod_has_prod)
   1.571 +
   1.572 +end
   1.573 +
   1.574 +context
   1.575 +  fixes f :: "'i \<Rightarrow> nat \<Rightarrow> 'a::real_normed_field"
   1.576 +    and I :: "'i set"
   1.577 +begin
   1.578 +
   1.579 +lemma has_prod_prod: "(\<And>i. i \<in> I \<Longrightarrow> (f i) has_prod (x i)) \<Longrightarrow> (\<lambda>n. \<Prod>i\<in>I. f i n) has_prod (\<Prod>i\<in>I. x i)"
   1.580 +  by (induct I rule: infinite_finite_induct) (auto intro!: has_prod_mult)
   1.581 +
   1.582 +lemma prodinf_prod: "(\<And>i. i \<in> I \<Longrightarrow> convergent_prod (f i)) \<Longrightarrow> (\<Prod>n. \<Prod>i\<in>I. f i n) = (\<Prod>i\<in>I. \<Prod>n. f i n)"
   1.583 +  using has_prod_unique[OF has_prod_prod, OF convergent_prod_has_prod] by simp
   1.584 +
   1.585 +lemma convergent_prod_prod: "(\<And>i. i \<in> I \<Longrightarrow> convergent_prod (f i)) \<Longrightarrow> convergent_prod (\<lambda>n. \<Prod>i\<in>I. f i n)"
   1.586 +  using convergent_prod_has_prod_iff has_prod_prod prodinf_prod by force
   1.587 +
   1.588 +end
   1.589 +
   1.590 +subsection \<open>Infinite summability on real normed vector spaces\<close>
   1.591 +
   1.592 +context
   1.593 +  fixes f :: "nat \<Rightarrow> 'a::real_normed_field"
   1.594 +begin
   1.595 +
   1.596 +lemma raw_has_prod_Suc_iff: "raw_has_prod f M (a * f M) \<longleftrightarrow> raw_has_prod (\<lambda>n. f (Suc n)) M a \<and> f M \<noteq> 0"
   1.597 +proof -
   1.598 +  have "raw_has_prod f M (a * f M) \<longleftrightarrow> (\<lambda>i. \<Prod>j\<le>Suc i. f (j+M)) \<longlonglongrightarrow> a * f M \<and> a * f M \<noteq> 0"
   1.599 +    by (subst LIMSEQ_Suc_iff) (simp add: raw_has_prod_def)
   1.600 +  also have "\<dots> \<longleftrightarrow> (\<lambda>i. (\<Prod>j\<le>i. f (Suc j + M)) * f M) \<longlonglongrightarrow> a * f M \<and> a * f M \<noteq> 0"
   1.601 +    by (simp add: ac_simps atMost_Suc_eq_insert_0 image_Suc_atMost prod_atLeast1_atMost_eq lessThan_Suc_atMost)
   1.602 +  also have "\<dots> \<longleftrightarrow> raw_has_prod (\<lambda>n. f (Suc n)) M a \<and> f M \<noteq> 0"
   1.603 +  proof safe
   1.604 +    assume tends: "(\<lambda>i. (\<Prod>j\<le>i. f (Suc j + M)) * f M) \<longlonglongrightarrow> a * f M" and 0: "a * f M \<noteq> 0"
   1.605 +    with tendsto_divide[OF tends tendsto_const, of "f M"]    
   1.606 +    show "raw_has_prod (\<lambda>n. f (Suc n)) M a"
   1.607 +      by (simp add: raw_has_prod_def)
   1.608 +  qed (auto intro: tendsto_mult_right simp:  raw_has_prod_def)
   1.609 +  finally show ?thesis .
   1.610 +qed
   1.611 +
   1.612 +lemma has_prod_Suc_iff:
   1.613 +  assumes "f 0 \<noteq> 0" shows "(\<lambda>n. f (Suc n)) has_prod a \<longleftrightarrow> f has_prod (a * f 0)"
   1.614 +proof (cases "a = 0")
   1.615 +  case True
   1.616 +  then show ?thesis
   1.617 +  proof (simp add: has_prod_def, safe)
   1.618 +    fix i x
   1.619 +    assume "f (Suc i) = 0" and "raw_has_prod (\<lambda>n. f (Suc n)) (Suc i) x"
   1.620 +    then obtain y where "raw_has_prod f (Suc (Suc i)) y"
   1.621 +      by (metis (no_types) raw_has_prod_eq_0 Suc_n_not_le_n raw_has_prod_Suc_iff raw_has_prod_ignore_initial_segment raw_has_prod_nonzero linear)
   1.622 +    then show "\<exists>i. f i = 0 \<and> Ex (raw_has_prod f (Suc i))"
   1.623 +      using \<open>f (Suc i) = 0\<close> by blast
   1.624 +  next
   1.625 +    fix i x
   1.626 +    assume "f i = 0" and x: "raw_has_prod f (Suc i) x"
   1.627 +    then obtain j where j: "i = Suc j"
   1.628 +      by (metis assms not0_implies_Suc)
   1.629 +    moreover have "\<exists> y. raw_has_prod (\<lambda>n. f (Suc n)) i y"
   1.630 +      using x by (auto simp: raw_has_prod_def)
   1.631 +    then show "\<exists>i. f (Suc i) = 0 \<and> Ex (raw_has_prod (\<lambda>n. f (Suc n)) (Suc i))"
   1.632 +      using \<open>f i = 0\<close> j by blast
   1.633 +  qed
   1.634 +next
   1.635 +  case False
   1.636 +  then show ?thesis
   1.637 +    by (auto simp: has_prod_def raw_has_prod_Suc_iff assms)
   1.638 +qed
   1.639 +
   1.640 +lemma convergent_prod_Suc_iff:
   1.641 +  assumes "\<And>k. f k \<noteq> 0" shows "convergent_prod (\<lambda>n. f (Suc n)) = convergent_prod f"
   1.642 +proof
   1.643 +  assume "convergent_prod f"
   1.644 +  then have "f has_prod prodinf f"
   1.645 +    by (rule convergent_prod_has_prod)
   1.646 +  moreover have "prodinf f \<noteq> 0"
   1.647 +    by (simp add: \<open>convergent_prod f\<close> assms prodinf_nonzero)
   1.648 +  ultimately have "(\<lambda>n. f (Suc n)) has_prod (prodinf f * inverse (f 0))"
   1.649 +    by (simp add: has_prod_Suc_iff inverse_eq_divide assms)
   1.650 +  then show "convergent_prod (\<lambda>n. f (Suc n))"
   1.651 +    using has_prod_iff by blast
   1.652 +next
   1.653 +  assume "convergent_prod (\<lambda>n. f (Suc n))"
   1.654 +  then show "convergent_prod f"
   1.655 +    using assms convergent_prod_def raw_has_prod_Suc_iff by blast
   1.656 +qed
   1.657 +
   1.658 +lemma raw_has_prod_inverse: 
   1.659 +  assumes "raw_has_prod f M a" shows "raw_has_prod (\<lambda>n. inverse (f n)) M (inverse a)"
   1.660 +  using assms unfolding raw_has_prod_def by (auto dest: tendsto_inverse simp: prod_inversef [symmetric])
   1.661 +
   1.662 +lemma has_prod_inverse: 
   1.663 +  assumes "f has_prod a" shows "(\<lambda>n. inverse (f n)) has_prod (inverse a)"
   1.664 +using assms raw_has_prod_inverse unfolding has_prod_def by auto 
   1.665 +
   1.666 +lemma convergent_prod_inverse:
   1.667 +  assumes "convergent_prod f" 
   1.668 +  shows "convergent_prod (\<lambda>n. inverse (f n))"
   1.669 +  using assms unfolding convergent_prod_def  by (blast intro: raw_has_prod_inverse elim: )
   1.670 +
   1.671 +end
   1.672 +
   1.673 +context (* Separate contexts are necessary to allow general use of the results above, here. *)
   1.674 +  fixes f :: "nat \<Rightarrow> 'a::real_normed_field"
   1.675 +begin
   1.676 +
   1.677 +lemma raw_has_prod_Suc_iff': "raw_has_prod f M a \<longleftrightarrow> raw_has_prod (\<lambda>n. f (Suc n)) M (a / f M) \<and> f M \<noteq> 0"
   1.678 +  by (metis raw_has_prod_eq_0 add.commute add.left_neutral raw_has_prod_Suc_iff raw_has_prod_nonzero le_add1 nonzero_mult_div_cancel_right times_divide_eq_left)
   1.679 +
   1.680 +lemma has_prod_divide: "f has_prod a \<Longrightarrow> g has_prod b \<Longrightarrow> (\<lambda>n. f n / g n) has_prod (a / b)"
   1.681 +  unfolding divide_inverse by (intro has_prod_inverse has_prod_mult)
   1.682 +
   1.683 +lemma convergent_prod_divide:
   1.684 +  assumes f: "convergent_prod f" and g: "convergent_prod g"
   1.685 +  shows "convergent_prod (\<lambda>n. f n / g n)"
   1.686 +  using f g has_prod_divide has_prod_iff by blast
   1.687 +
   1.688 +lemma prodinf_divide: "convergent_prod f \<Longrightarrow> convergent_prod g \<Longrightarrow> prodinf f / prodinf g = (\<Prod>n. f n / g n)"
   1.689 +  by (intro has_prod_unique has_prod_divide convergent_prod_has_prod)
   1.690 +
   1.691 +lemma prodinf_inverse: "convergent_prod f \<Longrightarrow> (\<Prod>n. inverse (f n)) = inverse (\<Prod>n. f n)"
   1.692 +  by (intro has_prod_unique [symmetric] has_prod_inverse convergent_prod_has_prod)
   1.693 +
   1.694 +lemma has_prod_iff_shift: 
   1.695 +  assumes "\<And>i. i < n \<Longrightarrow> f i \<noteq> 0"
   1.696 +  shows "(\<lambda>i. f (i + n)) has_prod a \<longleftrightarrow> f has_prod (a * (\<Prod>i<n. f i))"
   1.697 +  using assms
   1.698 +proof (induct n arbitrary: a)
   1.699 +  case 0
   1.700 +  then show ?case by simp
   1.701 +next
   1.702 +  case (Suc n)
   1.703 +  then have "(\<lambda>i. f (Suc i + n)) has_prod a \<longleftrightarrow> (\<lambda>i. f (i + n)) has_prod (a * f n)"
   1.704 +    by (subst has_prod_Suc_iff) auto
   1.705 +  with Suc show ?case
   1.706 +    by (simp add: ac_simps)
   1.707 +qed
   1.708 +
   1.709 +corollary has_prod_iff_shift':
   1.710 +  assumes "\<And>i. i < n \<Longrightarrow> f i \<noteq> 0"
   1.711 +  shows "(\<lambda>i. f (i + n)) has_prod (a / (\<Prod>i<n. f i)) \<longleftrightarrow> f has_prod a"
   1.712 +  by (simp add: assms has_prod_iff_shift)
   1.713 +
   1.714 +lemma has_prod_one_iff_shift:
   1.715 +  assumes "\<And>i. i < n \<Longrightarrow> f i = 1"
   1.716 +  shows "(\<lambda>i. f (i+n)) has_prod a \<longleftrightarrow> (\<lambda>i. f i) has_prod a"
   1.717 +  by (simp add: assms has_prod_iff_shift)
   1.718 +
   1.719 +lemma convergent_prod_iff_shift:
   1.720 +  shows "convergent_prod (\<lambda>i. f (i + n)) \<longleftrightarrow> convergent_prod f"
   1.721 +  apply safe
   1.722 +  using convergent_prod_offset apply blast
   1.723 +  using convergent_prod_ignore_initial_segment convergent_prod_def by blast
   1.724 +
   1.725 +lemma has_prod_split_initial_segment:
   1.726 +  assumes "f has_prod a" "\<And>i. i < n \<Longrightarrow> f i \<noteq> 0"
   1.727 +  shows "(\<lambda>i. f (i + n)) has_prod (a / (\<Prod>i<n. f i))"
   1.728 +  using assms has_prod_iff_shift' by blast
   1.729 +
   1.730 +lemma prodinf_divide_initial_segment:
   1.731 +  assumes "convergent_prod f" "\<And>i. i < n \<Longrightarrow> f i \<noteq> 0"
   1.732 +  shows "(\<Prod>i. f (i + n)) = (\<Prod>i. f i) / (\<Prod>i<n. f i)"
   1.733 +  by (rule has_prod_unique[symmetric]) (auto simp: assms has_prod_iff_shift)
   1.734 +
   1.735 +lemma prodinf_split_initial_segment:
   1.736 +  assumes "convergent_prod f" "\<And>i. i < n \<Longrightarrow> f i \<noteq> 0"
   1.737 +  shows "prodinf f = (\<Prod>i. f (i + n)) * (\<Prod>i<n. f i)"
   1.738 +  by (auto simp add: assms prodinf_divide_initial_segment)
   1.739 +
   1.740 +lemma prodinf_split_head:
   1.741 +  assumes "convergent_prod f" "f 0 \<noteq> 0"
   1.742 +  shows "(\<Prod>n. f (Suc n)) = prodinf f / f 0"
   1.743 +  using prodinf_split_initial_segment[of 1] assms by simp
   1.744 +
   1.745 +end
   1.746 +
   1.747 +context (* Separate contexts are necessary to allow general use of the results above, here. *)
   1.748 +  fixes f :: "nat \<Rightarrow> 'a::real_normed_field"
   1.749 +begin
   1.750 +
   1.751 +lemma convergent_prod_inverse_iff: "convergent_prod (\<lambda>n. inverse (f n)) \<longleftrightarrow> convergent_prod f"
   1.752 +  by (auto dest: convergent_prod_inverse)
   1.753 +
   1.754 +lemma convergent_prod_const_iff:
   1.755 +  fixes c :: "'a :: {real_normed_field}"
   1.756 +  shows "convergent_prod (\<lambda>_. c) \<longleftrightarrow> c = 1"
   1.757 +proof
   1.758 +  assume "convergent_prod (\<lambda>_. c)"
   1.759 +  then show "c = 1"
   1.760 +    using convergent_prod_imp_LIMSEQ LIMSEQ_unique by blast 
   1.761 +next
   1.762 +  assume "c = 1"
   1.763 +  then show "convergent_prod (\<lambda>_. c)"
   1.764 +    by auto
   1.765 +qed
   1.766 +
   1.767 +lemma has_prod_power: "f has_prod a \<Longrightarrow> (\<lambda>i. f i ^ n) has_prod (a ^ n)"
   1.768 +  by (induction n) (auto simp: has_prod_mult)
   1.769 +
   1.770 +lemma convergent_prod_power: "convergent_prod f \<Longrightarrow> convergent_prod (\<lambda>i. f i ^ n)"
   1.771 +  by (induction n) (auto simp: convergent_prod_mult)
   1.772 +
   1.773 +lemma prodinf_power: "convergent_prod f \<Longrightarrow> prodinf (\<lambda>i. f i ^ n) = prodinf f ^ n"
   1.774 +  by (metis has_prod_unique convergent_prod_imp_has_prod has_prod_power)
   1.775 +
   1.776 +end
   1.777 +
   1.778 +end