more lemmas to emphasize {0::nat..(<)n} as canonical representation of intervals on nat
authorhaftmann
Sat, 09 Jul 2016 13:26:16 +0200
changeset 63417 c184ec919c70
parent 63416 6af79184bef3
child 63418 ce7088e0e628
more lemmas to emphasize {0::nat..(<)n} as canonical representation of intervals on nat * * * more rules for setsum, setprod on intervals
src/HOL/Binomial.thy
src/HOL/Decision_Procs/Approximation.thy
src/HOL/Divides.thy
src/HOL/Library/Formal_Power_Series.thy
src/HOL/Multivariate_Analysis/Gamma.thy
src/HOL/Multivariate_Analysis/Generalised_Binomial_Theorem.thy
src/HOL/Multivariate_Analysis/ex/Approximations.thy
src/HOL/NthRoot.thy
src/HOL/Number_Theory/Residues.thy
src/HOL/Power.thy
src/HOL/Set_Interval.thy
src/HOL/Transcendental.thy
src/HOL/ex/Sum_of_Powers.thy
--- a/src/HOL/Binomial.thy	Fri Jul 08 23:43:11 2016 +0200
+++ b/src/HOL/Binomial.thy	Sat Jul 09 13:26:16 2016 +0200
@@ -14,38 +14,53 @@
 
 subsection \<open>Factorial\<close>
 
-definition (in semiring_char_0) fact :: "nat \<Rightarrow> 'a"
+context semiring_char_0
+begin
+
+definition fact :: "nat \<Rightarrow> 'a"
 where
-  "fact n = of_nat (\<Prod>{1..n})"
+  fact_setprod: "fact n = of_nat (\<Prod>{1..n})"
 
-lemma fact_altdef': "fact n = of_nat (\<Prod>{1..n})"
-  by (fact fact_def)
+lemma fact_setprod_Suc:
+  "fact n = of_nat (setprod Suc {0..<n})"
+  by (cases n) (simp_all add: fact_setprod setprod.atLeast_Suc_atMost_Suc_shift atLeastLessThanSuc_atLeastAtMost)
 
-lemma fact_altdef_nat: "fact n = \<Prod>{1..n}"
-  by (simp add: fact_def)
-
-lemma fact_altdef: "fact n = (\<Prod>i=1..n. of_nat i)"
-  by (simp add: fact_def)
+lemma fact_setprod_rev:
+  "fact n = of_nat (\<Prod>i = 0..<n. n - i)"
+  using setprod.atLeast_atMost_rev [of "\<lambda>i. i" 1 n]
+  by (cases n) (simp_all add: fact_setprod_Suc setprod.atLeast_Suc_atMost_Suc_shift atLeastLessThanSuc_atLeastAtMost)
 
 lemma fact_0 [simp]: "fact 0 = 1"
-  by (simp add: fact_def)
+  by (simp add: fact_setprod)
 
 lemma fact_1 [simp]: "fact 1 = 1"
-  by (simp add: fact_def)
+  by (simp add: fact_setprod)
 
-lemma fact_Suc_0 [simp]: "fact (Suc 0) = Suc 0"
-  by (simp add: fact_def)
+lemma fact_Suc_0 [simp]: "fact (Suc 0) = 1"
+  by (simp add: fact_setprod)
 
 lemma fact_Suc [simp]: "fact (Suc n) = of_nat (Suc n) * fact n"
-  by (simp add: fact_def atLeastAtMostSuc_conv algebra_simps)
+  by (simp add: fact_setprod atLeastAtMostSuc_conv algebra_simps)
+
+lemma fact_2 [simp]:
+  "fact 2 = 2"
+  by (simp add: numeral_2_eq_2)
+
+lemma fact_split:
+  assumes "k \<le> n"
+  shows "fact n = of_nat (setprod Suc {n - k..<n}) * fact (n - k)"
+  using assms by (simp add: fact_setprod_Suc setprod.union_disjoint [symmetric] ivl_disj_un
+    ac_simps of_nat_mult [symmetric])
+
+end
 
 lemma of_nat_fact [simp]:
   "of_nat (fact n) = fact n"
-  by (simp add: fact_def)
+  by (simp add: fact_setprod)
 
 lemma of_int_fact [simp]:
   "of_int (fact n) = fact n"
-  by (simp only: fact_def of_int_of_nat_eq)
+  by (simp only: fact_setprod of_int_of_nat_eq)
 
 lemma fact_reduce: "n > 0 \<Longrightarrow> fact n = of_nat n * fact (n - 1)"
   by (cases n) auto
@@ -149,10 +164,6 @@
     "fact m = (if m=0 then 1 else of_nat m * fact (m - 1))"
 by (cases m) auto
 
-lemma fact_eq_rev_setprod_nat: "fact k = (\<Prod>i<k. k - i)"
-  unfolding fact_altdef_nat
-  by (rule setprod.reindex_bij_witness[where i="\<lambda>i. k - i" and j="\<lambda>i. k - i"]) auto
-
 lemma fact_div_fact_le_pow:
   assumes "r \<le> n" shows "fact n div fact (n - r) \<le> n ^ r"
 proof -
@@ -177,30 +188,30 @@
 
 definition binomial :: "nat \<Rightarrow> nat \<Rightarrow> nat" (infixl "choose" 65)
 where
-  "n choose k = card {K\<in>Pow {..<n}. card K = k}"
+  "n choose k = card {K\<in>Pow {0..<n}. card K = k}"
 
 theorem n_subsets:
   assumes "finite A"
   shows "card {B. B \<subseteq> A \<and> card B = k} = card A choose k"
 proof -
-  from assms obtain f where bij: "bij_betw f {..<card A} A"
-    by (blast elim: bij_betw_nat_finite)
-  then have [simp]: "card (f ` C) = card C" if "C \<subseteq> {..<card A}" for C
+  from assms obtain f where bij: "bij_betw f {0..<card A} A"
+    by (blast dest: ex_bij_betw_nat_finite)
+  then have [simp]: "card (f ` C) = card C" if "C \<subseteq> {0..<card A}" for C
     by (meson bij_betw_imp_inj_on bij_betw_subset card_image that)
-  from bij have "bij_betw (image f) (Pow {..<card A}) (Pow A)"
+  from bij have "bij_betw (image f) (Pow {0..<card A}) (Pow A)"
     by (rule bij_betw_Pow)
-  then have "inj_on (image f) (Pow {..<card A})"
+  then have "inj_on (image f) (Pow {0..<card A})"
     by (rule bij_betw_imp_inj_on)
-  moreover have "{K. K \<subseteq> {..<card A} \<and> card K = k} \<subseteq> Pow {..<card A}"
+  moreover have "{K. K \<subseteq> {0..<card A} \<and> card K = k} \<subseteq> Pow {0..<card A}"
     by auto
-  ultimately have "inj_on (image f) {K. K \<subseteq> {..<card A} \<and> card K = k}"
+  ultimately have "inj_on (image f) {K. K \<subseteq> {0..<card A} \<and> card K = k}"
     by (rule inj_on_subset)
-  then have "card {K. K \<subseteq> {..<card A} \<and> card K = k} =
-    card (image f ` {K. K \<subseteq> {..<card A} \<and> card K = k})" (is "_ = card ?C")
+  then have "card {K. K \<subseteq> {0..<card A} \<and> card K = k} =
+    card (image f ` {K. K \<subseteq> {0..<card A} \<and> card K = k})" (is "_ = card ?C")
     by (simp add: card_image)
-  also have "?C = {K. K \<subseteq> f ` {..<card A} \<and> card K = k}"
+  also have "?C = {K. K \<subseteq> f ` {0..<card A} \<and> card K = k}"
     by (auto elim!: subset_imageE)
-  also have "f ` {..<card A} = A"
+  also have "f ` {0..<card A} = A"
     by (meson bij bij_betw_def)
   finally show ?thesis
     by (simp add: binomial_def)
@@ -211,8 +222,8 @@
 lemma binomial_n_0 [simp, code]:
   "n choose 0 = 1"
 proof -
-  have "{K \<in> Pow {..<n}. card K = 0} = {{}}"
-    by (auto dest: subset_eq_range_finite) 
+  have "{K \<in> Pow {0..<n}. card K = 0} = {{}}"
+    by (auto dest: finite_subset)
   then show ?thesis
     by (simp add: binomial_def)
 qed
@@ -224,10 +235,10 @@
 lemma binomial_Suc_Suc [simp, code]:
   "Suc n choose Suc k = (n choose k) + (n choose Suc k)"
 proof -
-  let ?P = "\<lambda>n k. {K. K \<subseteq> {..<n} \<and> card K = k}"
+  let ?P = "\<lambda>n k. {K. K \<subseteq> {0..<n} \<and> card K = k}"
   let ?Q = "?P (Suc n) (Suc k)"
   have inj: "inj_on (insert n) (?P n k)"
-    by rule auto
+    by rule (auto, (metis atLeastLessThan_iff insert_iff less_irrefl subsetCE)+)
   have disjoint: "insert n ` ?P n k \<inter> ?P n (Suc k) = {}"
     by auto
   have "?Q = {K\<in>?Q. n \<in> K} \<union> {K\<in>?Q. n \<notin> K}"
@@ -235,7 +246,7 @@
   also have "{K\<in>?Q. n \<in> K} = insert n ` ?P n k" (is "?A = ?B")
   proof (rule set_eqI)
     fix K
-    have K_finite: "finite K" if "K \<subseteq> insert n {..<n}"
+    have K_finite: "finite K" if "K \<subseteq> insert n {0..<n}"
       using that by (rule finite_subset) simp_all
     have Suc_card_K: "Suc (card K - Suc 0) = card K" if "n \<in> K"
       and "finite K"
@@ -246,17 +257,17 @@
     qed
     show "K \<in> ?A \<longleftrightarrow> K \<in> ?B"
       by (subst in_image_insert_iff)
-        (auto simp add: card_insert subset_eq_range_finite Diff_subset_conv K_finite Suc_card_K)
+        (auto simp add: card_insert subset_eq_atLeast0_lessThan_finite Diff_subset_conv K_finite Suc_card_K)
   qed    
   also have "{K\<in>?Q. n \<notin> K} = ?P n (Suc k)"
-    by (auto simp add: lessThan_Suc)
+    by (auto simp add: atLeast0_lessThan_Suc)
   finally show ?thesis using inj disjoint
     by (simp add: binomial_def card_Un_disjoint card_image)
 qed
 
 lemma binomial_eq_0:
   "n < k \<Longrightarrow> n choose k = 0"
-  by (auto simp add: binomial_def dest: subset_eq_range_card)
+  by (auto simp add: binomial_def dest: subset_eq_atLeast0_lessThan_card)
 
 lemma zero_less_binomial: "k \<le> n \<Longrightarrow> n choose k > 0"
   by (induct n k rule: diff_induct) simp_all
@@ -409,6 +420,29 @@
   apply (simp add: field_simps)
   by (metis mult.commute of_nat_fact of_nat_mult)
 
+lemma fact_binomial:
+  assumes "k \<le> n"
+  shows "fact k * of_nat (n choose k) = (fact n / fact (n - k) :: 'a::field_char_0)"
+  unfolding binomial_fact [OF assms] by (simp add: field_simps)
+
+lemma choose_two:
+  "n choose 2 = n * (n - 1) div 2"
+proof (cases "n \<ge> 2")
+  case False
+  then have "n = 0 \<or> n = 1"
+    by auto
+  then show ?thesis by auto
+next
+  case True
+  define m where "m = n - 2"
+  with True have "n = m + 2"
+    by simp
+  then have "fact n = n * (n - 1) * fact (n - 2)"
+    by (simp add: fact_setprod_Suc atLeast0_lessThan_Suc algebra_simps)
+  with True show ?thesis
+    by (simp add: binomial_fact')
+qed
+
 lemma choose_row_sum: "(\<Sum>k=0..n. n choose k) = 2^n"
   using binomial [of 1 "1" n]
   by (simp add: numeral_2_eq_2)
@@ -454,17 +488,13 @@
 lemma choose_row_sum': "(\<Sum>k\<le>n. (n choose k)) = 2 ^ n"
   using choose_row_sum[of n] by (simp add: atLeast0AtMost)
 
-lemma natsum_reverse_index:
-  fixes m::nat
-  shows "(\<And>k. m \<le> k \<Longrightarrow> k \<le> n \<Longrightarrow> g k = f (m + n - k)) \<Longrightarrow> (\<Sum>k=m..n. f k) = (\<Sum>k=m..n. g k)"
-  by (rule setsum.reindex_bij_witness[where i="\<lambda>k. m+n-k" and j="\<lambda>k. m+n-k"]) auto
-
 text\<open>NW diagonal sum property\<close>
 lemma sum_choose_diagonal:
   assumes "m\<le>n" shows "(\<Sum>k=0..m. (n-k) choose (m-k)) = Suc n choose m"
 proof -
   have "(\<Sum>k=0..m. (n-k) choose (m-k)) = (\<Sum>k=0..m. (n-m+k) choose k)"
-    by (rule natsum_reverse_index) (simp add: assms)
+    using setsum.atLeast_atMost_rev [of "\<lambda>k. (n - k) choose (m - k)" 0 m] assms
+      by simp
   also have "... = Suc (n-m+m) choose m"
     by (rule sum_choose_lower)
   also have "... = Suc n choose m" using assms
@@ -477,86 +507,59 @@
 
 text \<open>See @{url "http://en.wikipedia.org/wiki/Pochhammer_symbol"}\<close>
 
-definition (in comm_semiring_1) pochhammer :: "'a \<Rightarrow> nat \<Rightarrow> 'a"
+context comm_semiring_1
+begin
+
+definition pochhammer :: "'a \<Rightarrow> nat \<Rightarrow> 'a"
 where
-  "pochhammer (a :: 'a) n = setprod (\<lambda>n. a + of_nat n) {..<n}"
+  pochhammer_setprod: "pochhammer a n = setprod (\<lambda>i. a + of_nat i) {0..<n}"
+
+lemma pochhammer_setprod_rev:
+  "pochhammer a n = setprod (\<lambda>i. a + of_nat (n - i)) {1..n}"
+  using setprod.atLeast_lessThan_rev_at_least_Suc_atMost [of "\<lambda>i. a + of_nat i" 0 n]
+  by (simp add: pochhammer_setprod)
 
 lemma pochhammer_Suc_setprod:
-  "pochhammer a (Suc n) = setprod (\<lambda>n. a + of_nat n) {..n}"
-  by (simp add: pochhammer_def lessThan_Suc_atMost)
- 
+  "pochhammer a (Suc n) = setprod (\<lambda>i. a + of_nat i) {0..n}"
+  by (simp add: pochhammer_setprod atLeastLessThanSuc_atLeastAtMost)
+
+lemma pochhammer_Suc_setprod_rev:
+  "pochhammer a (Suc n) = setprod (\<lambda>i. a + of_nat (n - i)) {0..n}"
+  by (simp add: pochhammer_setprod_rev setprod.atLeast_Suc_atMost_Suc_shift)
+
 lemma pochhammer_0 [simp]: "pochhammer a 0 = 1"
-  by (simp add: pochhammer_def)
+  by (simp add: pochhammer_setprod)
  
 lemma pochhammer_1 [simp]: "pochhammer a 1 = a"
-  by (simp add: pochhammer_def lessThan_Suc)
+  by (simp add: pochhammer_setprod lessThan_Suc)
  
 lemma pochhammer_Suc0 [simp]: "pochhammer a (Suc 0) = a"
-  by (simp add: pochhammer_def lessThan_Suc)
+  by (simp add: pochhammer_setprod lessThan_Suc)
  
 lemma pochhammer_Suc: "pochhammer a (Suc n) = pochhammer a n * (a + of_nat n)"
-  by (simp add: pochhammer_def lessThan_Suc ac_simps)
+  by (simp add: pochhammer_setprod atLeast0_lessThan_Suc ac_simps)
  
+end
+
 lemma pochhammer_of_nat: "pochhammer (of_nat x) n = of_nat (pochhammer x n)"
-  by (simp add: pochhammer_def)
+  by (simp add: pochhammer_setprod)
 
 lemma pochhammer_of_int: "pochhammer (of_int x) n = of_int (pochhammer x n)"
-  by (simp add: pochhammer_def)
-
-lemma setprod_nat_ivl_Suc: "setprod f {.. Suc n} = setprod f {..n} * f (Suc n)"
-proof -
-  have "{..Suc n} = {..n} \<union> {Suc n}" by auto
-  then show ?thesis by (simp add: field_simps)
-qed
-
-lemma setprod_nat_ivl_1_Suc: "setprod f {.. Suc n} = f 0 * setprod f {1.. Suc n}"
-proof -
-  have "{..Suc n} = {0} \<union> {1 .. Suc n}" by auto
-  then show ?thesis by simp
-qed
+  by (simp add: pochhammer_setprod)
 
 lemma pochhammer_rec: "pochhammer a (Suc n) = a * pochhammer (a + 1) n"
-proof (cases "n = 0")
-  case True
-  then show ?thesis by (simp add: pochhammer_Suc_setprod)
-next
-  case False
-  have *: "finite {1 .. n}" "0 \<notin> {1 .. n}" by auto
-  have eq: "insert 0 {1 .. n} = {..n}" by auto
-  have **: "(\<Prod>n\<in>{1..n}. a + of_nat n) = (\<Prod>n\<in>{..<n}. a + 1 + of_nat n)"
-    apply (rule setprod.reindex_cong [where l = Suc])
-    using False
-    apply (auto simp add: fun_eq_iff field_simps image_Suc_lessThan)
-    done
-  show ?thesis
-    apply (simp add: pochhammer_def lessThan_Suc_atMost)
-    unfolding setprod.insert [OF *, unfolded eq]
-    using ** apply (simp add: field_simps)
-    done
-qed
+  by (simp add: pochhammer_setprod setprod.atLeast0_lessThan_Suc_shift ac_simps)
 
 lemma pochhammer_rec': "pochhammer z (Suc n) = (z + of_nat n) * pochhammer z n"
-proof (induction n arbitrary: z)
-  case (Suc n z)
-  have "pochhammer z (Suc (Suc n)) = z * pochhammer (z + 1) (Suc n)"
-    by (simp add: pochhammer_rec)
-  also note Suc
-  also have "z * ((z + 1 + of_nat n) * pochhammer (z + 1) n) =
-               (z + of_nat (Suc n)) * pochhammer z (Suc n)"
-    by (simp_all add: pochhammer_rec algebra_simps)
-  finally show ?case .
-qed simp_all
+  by (simp add: pochhammer_setprod setprod.atLeast0_lessThan_Suc ac_simps)
 
 lemma pochhammer_fact: "fact n = pochhammer 1 n"
-  apply (auto simp add: pochhammer_def fact_altdef)
-  apply (rule setprod.reindex_cong [where l = Suc])
-  apply (auto simp add: image_Suc_lessThan)
-  done
+  by (simp add: pochhammer_setprod fact_setprod_Suc)
 
 lemma pochhammer_of_nat_eq_0_lemma:
   assumes "k > n"
   shows "pochhammer (- (of_nat n :: 'a:: idom)) k = 0"
-  using assms by (auto simp add: pochhammer_def)
+  using assms by (auto simp add: pochhammer_setprod)
 
 lemma pochhammer_of_nat_eq_0_lemma':
   assumes kn: "k \<le> n"
@@ -580,7 +583,7 @@
   by (auto simp add: not_le[symmetric])
 
 lemma pochhammer_eq_0_iff: "pochhammer a n = (0::'a::field_char_0) \<longleftrightarrow> (\<exists>k < n. a = - of_nat k)"
-  by (auto simp add: pochhammer_def eq_neg_iff_add_eq_0)
+  by (auto simp add: pochhammer_setprod eq_neg_iff_add_eq_0)
 
 lemma pochhammer_eq_0_mono:
   "pochhammer a n = (0::'a::field_char_0) \<Longrightarrow> m \<ge> n \<Longrightarrow> pochhammer a m = 0"
@@ -591,19 +594,18 @@
   unfolding pochhammer_eq_0_iff by auto
 
 lemma pochhammer_minus:
-    "pochhammer (- b) k = ((- 1) ^ k :: 'a::comm_ring_1) * pochhammer (b - of_nat k + 1) k"
+  "pochhammer (- b) k = ((- 1) ^ k :: 'a::comm_ring_1) * pochhammer (b - of_nat k + 1) k"
 proof (cases k)
   case 0
   then show ?thesis by simp
 next
   case (Suc h)
-  have eq: "((- 1) ^ Suc h :: 'a) = (\<Prod>i\<le>h. - 1)"
-    using setprod_constant[where A="{.. h}" and y="- 1 :: 'a"]
+  have eq: "((- 1) ^ Suc h :: 'a) = (\<Prod>i = 0..h. - 1)"
+    using setprod_constant [where A="{0.. h}" and y="- 1 :: 'a"]
     by auto
-  show ?thesis
-    unfolding Suc pochhammer_Suc_setprod eq setprod.distrib[symmetric]
-    by (rule setprod.reindex_bij_witness[where i="op - h" and j="op - h"])
-       (auto simp: of_nat_diff)
+  with Suc show ?thesis
+    using pochhammer_Suc_setprod_rev [of "b - of_nat k + 1"]
+    by (auto simp add: pochhammer_Suc_setprod setprod.distrib [symmetric] eq of_nat_diff)
 qed
 
 lemma pochhammer_minus':
@@ -637,7 +639,7 @@
 
 lemma pochhammer_times_pochhammer_half:
   fixes z :: "'a :: field_char_0"
-  shows "pochhammer z (Suc n) * pochhammer (z + 1/2) (Suc n) = (\<Prod>k\<le>2*n+1. z + of_nat k / 2)"
+  shows "pochhammer z (Suc n) * pochhammer (z + 1/2) (Suc n) = (\<Prod>k=0..2*n+1. z + of_nat k / 2)"
 proof (induction n)
   case (Suc n)
   define n' where "n' = Suc n"
@@ -648,10 +650,10 @@
   also have "?A = (z + of_nat (Suc (2 * n + 1)) / 2) * (z + of_nat (Suc (Suc (2 * n + 1))) / 2)"
     (is "_ = ?A") by (simp add: field_simps n'_def)
   also note Suc[folded n'_def]
-  also have "(\<Prod>k\<le>2 * n + 1. z + of_nat k / 2) * ?A = (\<Prod>k\<le>2 * Suc n + 1. z + of_nat k / 2)"
-    by (simp add: setprod_nat_ivl_Suc)
+  also have "(\<Prod>k=0..2 * n + 1. z + of_nat k / 2) * ?A = (\<Prod>k=0..2 * Suc n + 1. z + of_nat k / 2)"
+    by (simp add: atLeast0_atMost_Suc)
   finally show ?case by (simp add: n'_def)
-qed (simp add: setprod_nat_ivl_Suc)
+qed (simp add: atLeast0_atMost_Suc)
 
 lemma pochhammer_double:
   fixes z :: "'a :: field_char_0"
@@ -687,34 +689,39 @@
 
 definition gbinomial :: "'a :: {semidom_divide, semiring_char_0} \<Rightarrow> nat \<Rightarrow> 'a" (infixl "gchoose" 65)
 where
-  "a gchoose n = setprod (\<lambda>i. a - of_nat i) {..<n} div fact n"
+  gbinomial_setprod_rev: "a gchoose n = setprod (\<lambda>i. a - of_nat i) {0..<n} div fact n"
+
+lemma gbinomial_0 [simp]:
+  "a gchoose 0 = 1"
+  "0 gchoose (Suc n) = 0"
+  by (simp_all add: gbinomial_setprod_rev setprod.atLeast0_lessThan_Suc_shift)
 
 lemma gbinomial_Suc:
-  "a gchoose (Suc k) = setprod (\<lambda>i. a - of_nat i) {..k} / fact (Suc k)"
-  by (simp add: gbinomial_def lessThan_Suc_atMost)
+  "a gchoose (Suc k) = setprod (\<lambda>i. a - of_nat i) {0..k} div fact (Suc k)"
+  by (simp add: gbinomial_setprod_rev atLeastLessThanSuc_atLeastAtMost)
 
-lemma gbinomial_0 [simp]:
+lemma gbinomial_mult_fact:
   fixes a :: "'a::field_char_0"
-  shows "a gchoose 0 = 1" "(0::'a) gchoose (Suc n) = 0"
-  by (simp_all add: gbinomial_def)
+  shows
+    "fact n * (a gchoose n) = (\<Prod>i = 0..<n. a - of_nat i)"
+  by (simp_all add: gbinomial_setprod_rev field_simps)
+
+lemma gbinomial_mult_fact':
+  fixes a :: "'a::field_char_0"
+  shows
+    "(a gchoose n) * fact n = (\<Prod>i = 0..<n. a - of_nat i)"
+  using gbinomial_mult_fact [of n a] by (simp add: ac_simps)
 
 lemma gbinomial_pochhammer:
   fixes a :: "'a::field_char_0"
-  shows "a gchoose n = (- 1) ^ n * pochhammer (- a) n / (fact n)"
-proof (cases "n = 0")
-  case True
-  then show ?thesis by simp
-next
-  case False
-  then have eq: "(- 1) ^ n = (\<Prod>i<n. - 1)"
-    by (auto simp add: setprod_constant)
-  from False show ?thesis
-    by (simp add: pochhammer_def gbinomial_def field_simps
-      eq setprod.distrib[symmetric])
-qed
+  shows "a gchoose n = (- 1) ^ n * pochhammer (- a) n / fact n"
+  by (cases n)
+    (simp_all add: pochhammer_minus, simp_all add: gbinomial_setprod_rev pochhammer_setprod_rev
+      power_mult_distrib [symmetric] atLeastLessThanSuc_atLeastAtMost setprod.atLeast_Suc_atMost_Suc_shift of_nat_diff)
 
 lemma gbinomial_pochhammer':
-  "(s :: 'a :: field_char_0) gchoose n = pochhammer (s - of_nat n + 1) n / fact n"
+  fixes s :: "'a::field_char_0"
+  shows "s gchoose n = pochhammer (s - of_nat n + 1) n / fact n"
 proof -
   have "s gchoose n = ((-1)^n * (-1)^n) * pochhammer (s - of_nat n + 1) n / fact n"
     by (simp add: gbinomial_pochhammer pochhammer_minus mult_ac)
@@ -727,76 +734,66 @@
 proof (cases "k \<le> n")
   case False
   then have "n < k" by (simp add: not_le)
-  then have "0 \<in> (op - n) ` {..<k}"
+  then have "0 \<in> (op - n) ` {0..<k}"
     by auto
-  then have "setprod (op - n) {..<k} = 0"
+  then have "setprod (op - n) {0..<k} = 0"
     by (auto intro: setprod_zero)
   with \<open>n < k\<close> show ?thesis
-    by (simp add: binomial_eq_0 gbinomial_def setprod_zero)
+    by (simp add: binomial_eq_0 gbinomial_setprod_rev setprod_zero)
 next
   case True
-  then have "inj_on (op - n) {..<k}"
+  then have "inj_on (op - n) {0..<k}"
     by (auto intro: inj_onI)
-  then have "\<Prod>(op - n ` {..<k}) = setprod (op - n) {..<k}"
+  then have "\<Prod>(op - n ` {0..<k}) = setprod (op - n) {0..<k}"
     by (auto dest: setprod.reindex)
-  also have "op - n ` {..<k} = {Suc (n - k)..n}"
+  also have "op - n ` {0..<k} = {Suc (n - k)..n}"
     using True by (auto simp add: image_def Bex_def) arith
-  finally have *: "setprod (\<lambda>q. n - q) {..<k} = \<Prod>{Suc (n - k)..n}" ..
+  finally have *: "setprod (\<lambda>q. n - q) {0..<k} = \<Prod>{Suc (n - k)..n}" ..
   from True have "(n choose k) = fact n div (fact k * fact (n - k))"
     by (rule binomial_fact')
   with * show ?thesis
-    by (simp add: gbinomial_def mult.commute [of "fact k"] div_mult2_eq fact_div_fact)
+    by (simp add: gbinomial_setprod_rev mult.commute [of "fact k"] div_mult2_eq fact_div_fact)
+qed
+
+lemma of_nat_gbinomial:
+  "of_nat (n gchoose k) = (of_nat n gchoose k :: 'a::field_char_0)"
+proof (cases "k \<le> n")
+  case False then show ?thesis
+    by (simp add: not_le gbinomial_binomial binomial_eq_0 gbinomial_setprod_rev)
+next
+  case True 
+  moreover define m where "m = n - k"
+  ultimately have n: "n = m + k"
+    by arith
+  from n have "fact n = ((\<Prod>i = 0..<m + k. of_nat (m + k - i) ):: 'a)"
+    by (simp add: fact_setprod_rev)
+  also have "\<dots> = ((\<Prod>i\<in>{0..<k} \<union> {k..<m + k}. of_nat (m + k - i)) :: 'a)"
+    by (simp add: ivl_disj_un)
+  finally have 
+    "fact n = (fact m * (\<Prod>i = 0..<k. of_nat m + of_nat k - of_nat i) :: 'a)"
+    using setprod_shift_bounds_nat_ivl [of "\<lambda>i. of_nat (m + k - i) :: 'a" 0 k m]
+    by (simp add: fact_setprod_rev [of m] setprod.union_disjoint of_nat_diff)
+  then have "fact n / fact (n - k) =
+    ((\<Prod>i = 0..<k. of_nat n - of_nat i) :: 'a)"
+    by (simp add: n)
+  with True have "fact k * of_nat (n gchoose k) = (fact k * (of_nat n gchoose k) :: 'a)"
+    by (simp only: gbinomial_mult_fact [of k "of_nat n"]
+      gbinomial_binomial [of n k]
+      fact_binomial)
+  then show ?thesis by simp
 qed
 
 lemma binomial_gbinomial:
-    "of_nat (n choose k) = (of_nat n gchoose k :: 'a::field_char_0)"
-proof -
-  { assume kn: "k > n"
-    then have ?thesis
-      by (subst binomial_eq_0[OF kn])
-         (simp add: gbinomial_pochhammer field_simps  pochhammer_of_nat_eq_0_iff) }
-  moreover
-  { assume "k=0" then have ?thesis by simp }
-  moreover
-  { assume kn: "k \<le> n" and k0: "k\<noteq> 0"
-    from k0 obtain h where h: "k = Suc h" by (cases k) auto
-    from h
-    have eq:"(- 1 :: 'a) ^ k = setprod (\<lambda>i. - 1) {..h}"
-      by (subst setprod_constant) auto
-    have eq': "(\<Prod>i\<le>h. of_nat n + - (of_nat i :: 'a)) = (\<Prod>i\<in>{n - h..n}. of_nat i)"
-        using h kn
-      by (intro setprod.reindex_bij_witness[where i="op - n" and j="op - n"])
-         (auto simp: of_nat_diff)
-    have th0: "finite {1..n - Suc h}" "finite {n - h .. n}"
-        "{1..n - Suc h} \<inter> {n - h .. n} = {}" and
-        eq3: "{1..n - Suc h} \<union> {n - h .. n} = {1..n}"
-      using h kn by auto
-    from eq[symmetric]
-    have ?thesis using kn
-      apply (simp add: binomial_fact[OF kn, where ?'a = 'a]
-        gbinomial_pochhammer field_simps pochhammer_Suc_setprod)
-      apply (simp add: pochhammer_Suc_setprod fact_altdef h
-        setprod.distrib[symmetric] eq' del: One_nat_def power_Suc)
-      unfolding setprod.union_disjoint[OF th0, unfolded eq3, of "of_nat:: nat \<Rightarrow> 'a"] eq[unfolded h]
-      unfolding mult.assoc
-      unfolding setprod.distrib[symmetric]
-      apply simp
-      apply (intro setprod.reindex_bij_witness[where i="op - n" and j="op - n"])
-      apply (auto simp: of_nat_diff)
-      done
-  }
-  moreover
-  have "k > n \<or> k = 0 \<or> (k \<le> n \<and> k \<noteq> 0)" by arith
-  ultimately show ?thesis by blast
-qed
+  "of_nat (n choose k) = (of_nat n gchoose k :: 'a::field_char_0)"
+  by (simp add: gbinomial_binomial [symmetric] of_nat_gbinomial)
 
 setup \<open>Sign.add_const_constraint (@{const_name gbinomial}, SOME @{typ "'a::field_char_0 \<Rightarrow> nat \<Rightarrow> 'a"})\<close>
 
 lemma gbinomial_1[simp]: "a gchoose 1 = a"
-  by (simp add: gbinomial_def lessThan_Suc)
+  by (simp add: gbinomial_setprod_rev lessThan_Suc)
 
 lemma gbinomial_Suc0[simp]: "a gchoose (Suc 0) = a"
-  by (simp add: gbinomial_def lessThan_Suc)
+  by (simp add: gbinomial_setprod_rev lessThan_Suc)
 
 lemma gbinomial_mult_1:
   fixes a :: "'a :: field_char_0"
@@ -819,19 +816,6 @@
   shows "(a gchoose n) * a = of_nat n * (a gchoose n) + of_nat (Suc n) * (a gchoose (Suc n))"
   by (simp add: mult.commute gbinomial_mult_1)
 
-lemma gbinomial_mult_fact:
-  fixes a :: "'a::field_char_0"
-  shows
-   "fact (Suc k) * (a gchoose (Suc k)) =
-    (setprod (\<lambda>i. a - of_nat i) {.. k})"
-  by (simp_all add: gbinomial_Suc field_simps del: fact_Suc)
-
-lemma gbinomial_mult_fact':
-  fixes a :: "'a::field_char_0"
-  shows "(a gchoose (Suc k)) * fact (Suc k) = (setprod (\<lambda>i. a - of_nat i) {.. k})"
-  using gbinomial_mult_fact[of k a]
-  by (subst mult.commute)
-
 lemma gbinomial_Suc_Suc:
   fixes a :: "'a :: field_char_0"
   shows "(a + 1) gchoose (Suc k) = a gchoose k + (a gchoose (Suc k))"
@@ -840,7 +824,7 @@
   then show ?thesis by simp
 next
   case (Suc h)
-  have eq0: "(\<Prod>i\<in>{1..k}. (a + 1) - of_nat i) = (\<Prod>i\<in>{..h}. a - of_nat i)"
+  have eq0: "(\<Prod>i\<in>{1..k}. (a + 1) - of_nat i) = (\<Prod>i\<in>{0..h}. a - of_nat i)"
     apply (rule setprod.reindex_cong [where l = Suc])
       using Suc
       apply (auto simp add: image_Suc_atMost)
@@ -850,32 +834,33 @@
         (a gchoose Suc (Suc h)) * (fact (Suc (Suc h)))"
     by (simp add: Suc field_simps del: fact_Suc)
   also have "... = (a gchoose Suc h) * of_nat (Suc (Suc h) * fact (Suc h)) +
-                   (\<Prod>i\<le>Suc h. a - of_nat i)"
-    by (metis fact_Suc gbinomial_mult_fact' of_nat_fact of_nat_id)
+                   (\<Prod>i=0..Suc h. a - of_nat i)"
+    apply (simp del: fact_Suc add: gbinomial_mult_fact field_simps mult.left_commute [of _ "2"])
+    apply (simp del: fact_Suc add: fact_Suc [of "Suc h"] field_simps gbinomial_mult_fact mult.left_commute [of _ "2"] atLeastLessThanSuc_atLeastAtMost)
+    done
   also have "... = (fact (Suc h) * (a gchoose Suc h)) * of_nat (Suc (Suc h)) +
-                   (\<Prod>i\<le>Suc h. a - of_nat i)"
+                   (\<Prod>i=0..Suc h. a - of_nat i)"
     by (simp only: fact_Suc mult.commute mult.left_commute of_nat_fact of_nat_id of_nat_mult)
-  also have "... =  of_nat (Suc (Suc h)) * (\<Prod>i\<le>h. a - of_nat i) +
-                    (\<Prod>i\<le>Suc h. a - of_nat i)"
-    by (metis gbinomial_mult_fact mult.commute)
-  also have "... = (\<Prod>i\<le>Suc h. a - of_nat i) +
-                   (of_nat h * (\<Prod>i\<le>h. a - of_nat i) + 2 * (\<Prod>i\<le>h. a - of_nat i))"
+  also have "... =  of_nat (Suc (Suc h)) * (\<Prod>i=0..h. a - of_nat i) +
+                    (\<Prod>i=0..Suc h. a - of_nat i)"
+    unfolding gbinomial_mult_fact atLeastLessThanSuc_atLeastAtMost by auto
+  also have "... = (\<Prod>i=0..Suc h. a - of_nat i) +
+                   (of_nat h * (\<Prod>i=0..h. a - of_nat i) + 2 * (\<Prod>i=0..h. a - of_nat i))"
     by (simp add: field_simps)
   also have "... =
-    ((a gchoose Suc h) * (fact (Suc h)) * of_nat (Suc k)) + (\<Prod>i\<in>{..Suc h}. a - of_nat i)"
+    ((a gchoose Suc h) * (fact (Suc h)) * of_nat (Suc k)) + (\<Prod>i\<in>{0..Suc h}. a - of_nat i)"
     unfolding gbinomial_mult_fact'
-    by (simp add: comm_semiring_class.distrib field_simps Suc)
-  also have "\<dots> = (\<Prod>i\<in>{..h}. a - of_nat i) * (a + 1)"
-    unfolding gbinomial_mult_fact' setprod_nat_ivl_Suc
-      atMost_Suc
-    by (simp add: field_simps Suc)
-  also have "\<dots> = (\<Prod>i\<in>{..k}. (a + 1) - of_nat i)"
-    using eq0 setprod_nat_ivl_1_Suc
-    by (simp add: Suc setprod_nat_ivl_1_Suc)
+    by (simp add: comm_semiring_class.distrib field_simps Suc atLeastLessThanSuc_atLeastAtMost)
+  also have "\<dots> = (\<Prod>i\<in>{0..h}. a - of_nat i) * (a + 1)"
+    unfolding gbinomial_mult_fact' atLeast0_atMost_Suc
+    by (simp add: field_simps Suc atLeastLessThanSuc_atLeastAtMost)
+  also have "\<dots> = (\<Prod>i\<in>{0..k}. (a + 1) - of_nat i)"
+    using eq0
+    by (simp add: Suc setprod.atLeast0_atMost_Suc_shift)
   also have "\<dots> = (fact (Suc k)) * ((a + 1) gchoose (Suc k))"
-    unfolding gbinomial_mult_fact ..
+    unfolding gbinomial_mult_fact atLeastLessThanSuc_atLeastAtMost ..
   finally show ?thesis
-    by (metis fact_nonzero mult_cancel_left)
+    using fact_nonzero [of "Suc k"] by auto
 qed
 
 lemma gbinomial_reduce_nat:
@@ -992,17 +977,9 @@
   Alternative definition of the binomial coefficient as @{term "\<Prod>i<k. (n - i) / (k - i)"}\<close>
 lemma gbinomial_altdef_of_nat:
   fixes k :: nat
-    and x :: "'a :: {field_char_0,field}"
-  shows "x gchoose k = (\<Prod>i<k. (x - of_nat i) / of_nat (k - i) :: 'a)"
-proof -
-  have "(x gchoose k) = (\<Prod>i<k. x - of_nat i) / of_nat (fact k)"
-    unfolding gbinomial_def
-    by (auto simp: gr0_conv_Suc lessThan_Suc_atMost atLeast0AtMost)
-  also have "\<dots> = (\<Prod>i<k. (x - of_nat i) / of_nat (k - i) :: 'a)"
-    unfolding fact_eq_rev_setprod_nat of_nat_setprod
-    by (auto simp add: setprod_dividef intro!: setprod.cong of_nat_diff[symmetric])
-  finally show ?thesis .
-qed
+    and x :: "'a :: field_char_0"
+  shows "x gchoose k = (\<Prod>i = 0..<k. (x - of_nat i) / of_nat (k - i) :: 'a)"
+  by (simp add: setprod_dividef gbinomial_setprod_rev fact_setprod_rev)
 
 lemma gbinomial_ge_n_over_k_pow_k:
   fixes k :: nat
@@ -1012,11 +989,11 @@
 proof -
   have x: "0 \<le> x"
     using assms of_nat_0_le_iff order_trans by blast
-  have "(x / of_nat k :: 'a) ^ k = (\<Prod>i<k. x / of_nat k :: 'a)"
+  have "(x / of_nat k :: 'a) ^ k = (\<Prod>i = 0..<k. x / of_nat k :: 'a)"
     by (simp add: setprod_constant)
   also have "\<dots> \<le> x gchoose k"
     unfolding gbinomial_altdef_of_nat
-  proof (safe intro!: setprod_mono)
+  proof (safe intro!: setprod_mono, simp_all) -- \<open>FIXME\<close>
     fix i :: nat
     assume ik: "i < k"
     from assms have "x * of_nat i \<ge> of_nat (i * k)"
@@ -1044,12 +1021,12 @@
 proof (cases b)
   case (Suc b)
   hence "((a + 1) gchoose (Suc (Suc b))) =
-             (\<Prod>i\<le>Suc b. a + (1 - of_nat i)) / fact (b + 2)"
-    by (simp add: field_simps gbinomial_def lessThan_Suc_atMost)
-  also have "(\<Prod>i\<le>Suc b. a + (1 - of_nat i)) = (a + 1) * (\<Prod>i\<le>b. a - of_nat i)"
-    by (simp add: setprod_nat_ivl_1_Suc setprod_shift_bounds_cl_Suc_ivl atLeast0AtMost)
+             (\<Prod>i = 0..Suc b. a + (1 - of_nat i)) / fact (b + 2)"
+    by (simp add: field_simps gbinomial_setprod_rev atLeastLessThanSuc_atLeastAtMost)
+  also have "(\<Prod>i = 0..Suc b. a + (1 - of_nat i)) = (a + 1) * (\<Prod>i = 0..b. a - of_nat i)"
+    by (simp add: setprod.atLeast0_atMost_Suc_shift)
   also have "... / fact (b + 2) = (a + 1) / of_nat (Suc (Suc b)) * (a gchoose Suc b)"
-    by (simp_all add: gbinomial_def setprod_nat_ivl_1_Suc setprod_shift_bounds_cl_Suc_ivl lessThan_Suc_atMost)
+    by (simp_all add: gbinomial_setprod_rev atLeastLessThanSuc_atLeastAtMost)
   finally show ?thesis by (simp add: Suc field_simps del: of_nat_Suc)
 qed simp
 
@@ -1058,12 +1035,12 @@
 proof (cases b)
   case (Suc b)
   hence "((a + 1) gchoose (Suc (Suc b))) =
-             (\<Prod>i\<le>Suc b. a + (1 - of_nat i)) / fact (b + 2)"
-    by (simp add: field_simps gbinomial_def lessThan_Suc_atMost)
-  also have "(\<Prod>i\<le>Suc b. a + (1 - of_nat i)) = (a + 1) * (\<Prod>i = 0..b. a - of_nat i)"
-    by (simp add: setprod_nat_ivl_1_Suc setprod_shift_bounds_cl_Suc_ivl)
+             (\<Prod>i = 0 .. Suc b. a + (1 - of_nat i)) / fact (b + 2)"
+    by (simp add: field_simps gbinomial_setprod_rev atLeastLessThanSuc_atLeastAtMost)
+  also have "(\<Prod>i = 0 .. Suc b. a + (1 - of_nat i)) = (a + 1) * (\<Prod>i = 0..b. a - of_nat i)"
+    by (simp add: setprod.atLeast0_atMost_Suc_shift)
   also have "... / fact (b + 2) = (a + 1) / of_nat (Suc (Suc b)) * (a gchoose Suc b)"
-    by (simp_all add: gbinomial_def setprod_nat_ivl_1_Suc setprod_shift_bounds_cl_Suc_ivl lessThan_Suc_atMost atLeast0AtMost)
+    by (simp_all add: gbinomial_setprod_rev atLeastLessThanSuc_atLeastAtMost atLeast0AtMost)
   finally show ?thesis by (simp add: Suc)
 qed simp
 
@@ -1256,10 +1233,6 @@
   apply (simp add: power_mult_distrib [symmetric])
   done
 
-lemma setsum_nat_symmetry:
-  "(\<Sum>k = 0..(m::nat). f k) = (\<Sum>k = 0..m. f (m - k))"
-  by (rule setsum.reindex_bij_witness[where i="\<lambda>i. m - i" and j="\<lambda>i. m - i"]) auto
-
 lemma binomial_r_part_sum: "(\<Sum>k\<le>m. (2 * m + 1 choose k)) = 2 ^ (2 * m)"
 proof -
   have "2 * 2^(2*m) = (\<Sum>k = 0..(2 * m + 1). (2 * m + 1 choose k))"
@@ -1273,7 +1246,8 @@
   also have "\<dots> = (\<Sum>k = 0..m. (2 * m + 1 choose (m - k)))"
     by (intro setsum.cong[OF refl], subst binomial_symmetric) simp_all
   also have "\<dots> = (\<Sum>k = 0..m. (2 * m + 1 choose k))"
-    by (subst (2) setsum_nat_symmetry) (rule refl)
+    using setsum.atLeast_atMost_rev [of "\<lambda>k. 2 * m + 1 choose (m - k)" 0 m]
+    by simp
   also have "\<dots> + \<dots> = 2 * \<dots>" by simp
   finally show ?thesis by (subst (asm) mult_cancel1) (simp add: atLeast0AtMost)
 qed
@@ -1316,11 +1290,10 @@
 text\<open>Versions of the theorems above for the natural-number version of "choose"\<close>
 lemma binomial_altdef_of_nat:
   fixes n k :: nat
-    and x :: "'a :: {field_char_0,field}"  \<comment>\<open>the point is to constrain @{typ 'a}\<close>
+    and x :: "'a :: field_char_0"
   assumes "k \<le> n"
-  shows "of_nat (n choose k) = (\<Prod>i<k. of_nat (n - i) / of_nat (k - i) :: 'a)"
-using assms
-by (simp add: gbinomial_altdef_of_nat binomial_gbinomial of_nat_diff)
+  shows "of_nat (n choose k) = (\<Prod>i = 0..<k. of_nat (n - i) / of_nat (k - i) :: 'a)"
+  using assms by (simp add: gbinomial_altdef_of_nat binomial_gbinomial of_nat_diff)
 
 lemma binomial_ge_n_over_k_pow_k:
   fixes k n :: nat
@@ -1593,7 +1566,8 @@
 lemma fact_code [code]:
   "fact n = (of_nat (fold_atLeastAtMost_nat (op *) 2 n 1) :: 'a :: semiring_char_0)"
 proof -
-  have "fact n = (of_nat (\<Prod>{1..n}) :: 'a)" by (simp add: fact_altdef')
+  have "fact n = (of_nat (\<Prod>{1..n}) :: 'a)"
+    by (simp add: fact_setprod)
   also have "\<Prod>{1..n} = \<Prod>{2..n}"
     by (intro setprod.mono_neutral_right) auto
   also have "\<dots> = fold_atLeastAtMost_nat (op *) 2 n 1"
@@ -1601,19 +1575,15 @@
   finally show ?thesis .
 qed
 
-lemma setprod_lessThan_fold_atLeastAtMost_nat:
-  "setprod f {..<Suc n} = fold_atLeastAtMost_nat (times \<circ> f) 0 n 1"
-  by (simp add: lessThan_Suc_atMost atLeast0AtMost [symmetric] setprod_atLeastAtMost_code comp_def)
-
 lemma pochhammer_code [code]:
   "pochhammer a n = (if n = 0 then 1 else
-       fold_atLeastAtMost_nat (\<lambda>n acc. (a + of_nat n) * acc) 0 (n - 1) 1)"
-  by (cases n) (simp_all add: pochhammer_def setprod_lessThan_fold_atLeastAtMost_nat comp_def)
+     fold_atLeastAtMost_nat (\<lambda>n acc. (a + of_nat n) * acc) 0 (n - 1) 1)"
+  by (cases n) (simp_all add: pochhammer_setprod setprod_atLeastAtMost_code [symmetric] atLeastLessThanSuc_atLeastAtMost)
 
 lemma gbinomial_code [code]:
   "a gchoose n = (if n = 0 then 1 else
      fold_atLeastAtMost_nat (\<lambda>n acc. (a - of_nat n) * acc) 0 (n - 1) 1 / fact n)"
-  by (cases n) (simp_all add: gbinomial_def setprod_lessThan_fold_atLeastAtMost_nat comp_def)
+  by (cases n) (simp_all add: gbinomial_setprod_rev setprod_atLeastAtMost_code [symmetric] atLeastLessThanSuc_atLeastAtMost)
 
 (*TODO: This code equation breaks Scala code generation in HOL-Codegenerator_Test. We have to figure out why and how to prevent that. *)
 
--- a/src/HOL/Decision_Procs/Approximation.thy	Fri Jul 08 23:43:11 2016 +0200
+++ b/src/HOL/Decision_Procs/Approximation.thy	Sat Jul 09 13:26:16 2016 +0200
@@ -4027,7 +4027,7 @@
 qed
 
 lemma setprod_fact: "real (\<Prod> {1..<1 + k}) = fact (k :: nat)"
-by (metis Suc_eq_plus1_left atLeastLessThanSuc_atLeastAtMost fact_altdef_nat of_nat_fact)
+  by (simp add: fact_setprod atLeastLessThanSuc_atLeastAtMost)
 
 lemma approx_tse:
   assumes "bounded_by xs vs"
--- a/src/HOL/Divides.thy	Fri Jul 08 23:43:11 2016 +0200
+++ b/src/HOL/Divides.thy	Sat Jul 09 13:26:16 2016 +0200
@@ -1432,6 +1432,15 @@
   apply (metis (full_types) One_nat_def Suc_lessI div_less_dividend less_not_refl3)
   done
 
+lemma (in field_char_0) of_nat_div:
+  "of_nat (m div n) = ((of_nat m - of_nat (m mod n)) / of_nat n)"
+proof -
+  have "of_nat (m div n) = ((of_nat (m div n * n + m mod n) - of_nat (m mod n)) / of_nat n :: 'a)"
+    unfolding of_nat_add by (cases "n = 0") simp_all
+  then show ?thesis
+    by simp
+qed
+
 
 subsubsection \<open>An ``induction'' law for modulus arithmetic.\<close>
 
--- a/src/HOL/Library/Formal_Power_Series.thy	Fri Jul 08 23:43:11 2016 +0200
+++ b/src/HOL/Library/Formal_Power_Series.thy	Sat Jul 09 13:26:16 2016 +0200
@@ -1711,7 +1711,7 @@
 
 lemma fps_deriv_maclauren_0:
   "(fps_nth_deriv k (f :: 'a::comm_semiring_1 fps)) $ 0 = of_nat (fact k) * f $ k"
-  by (induct k arbitrary: f) (auto simp add: field_simps of_nat_mult)
+  by (induct k arbitrary: f) (auto simp add: field_simps)
 
 
 subsection \<open>Powers\<close>
@@ -3701,7 +3701,7 @@
   have "?l$n = ?r $ n" for n
     apply (auto simp add: E_def field_simps power_Suc[symmetric]
       simp del: fact_Suc of_nat_Suc power_Suc)
-    apply (simp add: of_nat_mult field_simps)
+    apply (simp add: field_simps)
     done
   then show ?thesis
     by (simp add: fps_eq_iff)
@@ -4110,6 +4110,7 @@
       (is ?pochhammer)
     if kn: "k \<in> {0..n}" for k
   proof -
+    from kn have "k \<le> n" by simp
     have nz: "pochhammer (1 + b - of_nat n) n \<noteq> 0"
     proof
       assume "pochhammer (1 + b - of_nat n) n = 0"
@@ -4169,32 +4170,25 @@
           by (intro setprod.reindex_bij_witness[where i="\<lambda>k. Suc m - k" and j="\<lambda>k. Suc m - k"])
              (auto simp: of_nat_diff)
         have th1: "(?m1 k * ?p (of_nat n) k) / ?f n = 1 / of_nat(fact (n - k))"
-          unfolding m1nk
-          apply (simp add: field_simps m h pochhammer_Suc_setprod del: fact_Suc)
-          apply (simp add: fact_altdef id_def atLeast0AtMost setprod.distrib [symmetric] eq1)
-          apply (subst setprod.union_disjoint [symmetric])
-          apply (auto intro!: setprod.cong)
+          apply (simp add: pochhammer_minus field_simps)
+          using \<open>k \<le> n\<close> apply (simp add: fact_split [of k n])
+          apply (simp add: pochhammer_setprod)
+          using setprod.atLeast_lessThan_shift_bounds [where ?'a = 'a, of "\<lambda>i. 1 + of_nat i" 0 "n - k" k]
+          apply (auto simp add: of_nat_diff field_simps)
           done
-        have th20: "?m1 n * ?p b n = setprod (\<lambda>i. b - of_nat i) {..m}"
-          unfolding m1nk
-          unfolding m h pochhammer_Suc_setprod
-          unfolding setprod.distrib[symmetric]
-          apply (rule setprod.cong)
-          apply auto
+        have th20: "?m1 n * ?p b n = setprod (\<lambda>i. b - of_nat i) {0..m}"
+          apply (simp add: pochhammer_minus field_simps m)
+          apply (auto simp add: pochhammer_setprod_rev of_nat_diff setprod.atLeast_Suc_atMost_Suc_shift)
           done
         have th21:"pochhammer (b - of_nat n + 1) k = setprod (\<lambda>i. b - of_nat i) {n - k .. n - 1}"
-          unfolding h m
-          unfolding pochhammer_Suc_setprod
-          using kn m h
-          by (intro setprod.reindex_bij_witness[where i="\<lambda>k. n - 1 - k" and j="\<lambda>i. m-i"])
-             (auto simp: of_nat_diff)
-
+          using kn apply (simp add: pochhammer_setprod_rev m h setprod.atLeast_Suc_atMost_Suc_shift)
+          using setprod.atLeast_atMost_shift_0 [of "m - h" m, where ?'a = 'a]
+          apply (auto simp add: of_nat_diff field_simps)
+          done
         have "?m1 n * ?p b n =
-          pochhammer (b - of_nat n + 1) k * setprod (\<lambda>i. b - of_nat i) {0.. n - k - 1}"
-          unfolding th20 th21
-          unfolding h m
-          apply (subst setprod.union_disjoint[symmetric])
-          using kn' h m
+          setprod (\<lambda>i. b - of_nat i) {0.. n - k - 1} * pochhammer (b - of_nat n + 1) k"
+          using kn' m h unfolding th20 th21 apply simp
+          apply (subst setprod.union_disjoint [symmetric])
           apply auto
           apply (rule setprod.cong)
           apply auto
@@ -4208,10 +4202,11 @@
           by (simp add: field_simps)
         also have "\<dots> = b gchoose (n - k)"
           unfolding th1 th2
-          using kn' apply (simp add: gbinomial_def atLeast0AtMost)
-            apply (rule setprod.cong)
-            apply auto
-            done
+          using kn' m h
+          apply (simp add: field_simps gbinomial_mult_fact)
+          apply (rule setprod.cong)
+          apply auto
+          done
         finally show ?thesis by simp
       qed
     qed
@@ -4230,10 +4225,6 @@
     unfolding gbinomial_pochhammer
     using bn0
     apply (simp add: setsum_left_distrib setsum_right_distrib field_simps)
-    apply (rule setsum.cong)
-    apply (rule refl)
-    apply (drule th00(2))
-    apply (simp add: field_simps power_add[symmetric])
     done
   finally show ?thesis by simp
 qed
@@ -4355,7 +4346,7 @@
   apply (cases n)
   apply simp
   apply (simp add: nonzero_divide_eq_eq nonzero_eq_divide_eq del: of_nat_Suc fact_Suc)
-  apply (simp add: of_nat_mult del: of_nat_Suc mult_Suc)
+  apply simp
   done
 
 lemma fps_cos_nth_0 [simp]: "fps_cos c $ 0 = 1"
@@ -4368,7 +4359,7 @@
   "fps_cos c $ (n + 2) = - (c * c * fps_cos c $ n / (of_nat (n + 1) * of_nat (n + 2)))"
   unfolding fps_cos_def
   apply (simp add: nonzero_divide_eq_eq nonzero_eq_divide_eq del: of_nat_Suc fact_Suc)
-  apply (simp add: of_nat_mult del: of_nat_Suc mult_Suc)
+  apply simp
   done
 
 lemma nat_induct2: "P 0 \<Longrightarrow> P 1 \<Longrightarrow> (\<And>n. P n \<Longrightarrow> P (n + 2)) \<Longrightarrow> P (n::nat)"
@@ -4593,7 +4584,7 @@
   apply (simp del: of_nat_Suc of_nat_add fact_Suc)
   apply (simp add: foldl_mult_start del: fact_Suc of_nat_Suc)
   unfolding foldl_prod_prod[unfolded foldl_mult_start] pochhammer_Suc
-  apply (simp add: algebra_simps of_nat_mult)
+  apply (simp add: algebra_simps)
   done
 
 lemma XD_nth[simp]: "XD a $ n = (if n = 0 then 0 else of_nat n * a$n)"
--- a/src/HOL/Multivariate_Analysis/Gamma.thy	Fri Jul 08 23:43:11 2016 +0200
+++ b/src/HOL/Multivariate_Analysis/Gamma.thy	Sat Jul 09 13:26:16 2016 +0200
@@ -504,18 +504,21 @@
   assumes "n > 0" "z \<notin> \<int>\<^sub>\<le>\<^sub>0"
   shows   "exp (ln_Gamma_series z n :: complex) = Gamma_series z n"
 proof -
+  from assms obtain m where m: "n = Suc m" by (cases n) blast
   from assms have "z \<noteq> 0" by (intro notI) auto
   with assms have "exp (ln_Gamma_series z n) =
           (of_nat n) powr z / (z * (\<Prod>k=1..n. exp (Ln (z / of_nat k + 1))))"
     unfolding ln_Gamma_series_def powr_def by (simp add: exp_diff exp_setsum)
   also from assms have "(\<Prod>k=1..n. exp (Ln (z / of_nat k + 1))) = (\<Prod>k=1..n. z / of_nat k + 1)"
     by (intro setprod.cong[OF refl], subst exp_Ln) (auto simp: field_simps plus_of_nat_eq_0_imp)
-  also have "... = (\<Prod>k=1..n. z + k) / fact n" unfolding fact_altdef
-    by (subst setprod_dividef [symmetric]) (simp_all add: field_simps)
-  also from assms have "z * ... = (\<Prod>k\<le>n. z + k) / fact n"
-    by (cases n) (simp_all add: setprod_nat_ivl_1_Suc)
-  also have "(\<Prod>k\<le>n. z + k) = pochhammer z (Suc n)" unfolding pochhammer_def
-    by (simp add: lessThan_Suc_atMost)
+  also have "... = (\<Prod>k=1..n. z + k) / fact n"
+    by (simp add: fact_setprod)
+    (subst setprod_dividef [symmetric], simp_all add: field_simps)
+  also from m have "z * ... = (\<Prod>k=0..n. z + k) / fact n"
+    by (simp add: setprod.atLeast0_atMost_Suc_shift setprod.atLeast_Suc_atMost_Suc_shift)
+  also have "(\<Prod>k=0..n. z + k) = pochhammer z (Suc n)"
+    unfolding pochhammer_setprod
+    by (simp add: setprod.atLeast0_atMost_Suc atLeastLessThanSuc_atLeastAtMost)
   also have "of_nat n powr z / (pochhammer z (Suc n) / fact n) = Gamma_series z n"
     unfolding Gamma_series_def using assms by (simp add: divide_simps powr_def Ln_of_nat)
   finally show ?thesis .
@@ -999,7 +1002,7 @@
   case False
   hence "z \<noteq> - of_nat n" for n by auto
   from rGamma_series_aux[OF this] show ?thesis
-    by (simp add: rGamma_series_def[abs_def] fact_altdef pochhammer_Suc_setprod
+    by (simp add: rGamma_series_def[abs_def] fact_setprod pochhammer_Suc_setprod
                   exp_def of_real_def[symmetric] suminf_def sums_def[abs_def] atLeast0AtMost)
 qed (insert rGamma_eq_zero_iff[of z], simp_all add: rGamma_series_nonpos_Ints_LIMSEQ)
 
@@ -1149,7 +1152,7 @@
   apply (rule has_field_derivative_at_within)
   using differentiable_rGamma_aux2[of n]
   unfolding Let_def has_field_derivative_def has_derivative_def netlimit_at
-  by (simp only: bounded_linear_mult_right mult_ac of_real_def [symmetric] fact_altdef)
+  by (simp only: bounded_linear_mult_right mult_ac of_real_def [symmetric] fact_setprod) simp
 
 lemma has_field_derivative_rGamma [derivative_intros]:
   "(rGamma has_field_derivative (if z \<in> \<int>\<^sub>\<le>\<^sub>0 then (-1)^(nat \<lfloor>norm z\<rfloor>) * fact (nat \<lfloor>norm z\<rfloor>)
@@ -1355,7 +1358,7 @@
   from has_field_derivative_rGamma_complex_nonpos_Int[of n]
   show "let z = - of_nat n in (\<lambda>y. (rGamma y - rGamma z - (- 1) ^ n * setprod of_nat {1..n} *
                   (y - z)) /\<^sub>R cmod (y - z)) \<midarrow>z\<rightarrow> 0"
-    by (simp add: has_field_derivative_def has_derivative_def fact_altdef netlimit_at Let_def)
+    by (simp add: has_field_derivative_def has_derivative_def fact_setprod netlimit_at Let_def)
 next
   fix z :: complex
   from rGamma_series_complex_converges[of z] have "rGamma_series z \<longlonglongrightarrow> rGamma z"
@@ -1364,7 +1367,7 @@
             exp = \<lambda>x. THE e. (\<lambda>n. \<Sum>k<n. x ^ k /\<^sub>R fact k) \<longlonglongrightarrow> e;
             pochhammer' = \<lambda>a n. \<Prod>n = 0..n. a + of_nat n
         in  (\<lambda>n. pochhammer' z n / (fact' n * exp (z * ln (real_of_nat n) *\<^sub>R 1))) \<longlonglongrightarrow> rGamma z"
-    by (simp add: fact_altdef pochhammer_Suc_setprod rGamma_series_def [abs_def] exp_def
+    by (simp add: fact_setprod pochhammer_Suc_setprod rGamma_series_def [abs_def] exp_def
                   of_real_def [symmetric] suminf_def sums_def [abs_def] atLeast0AtMost)
 qed
 
@@ -1485,7 +1488,7 @@
                   simp: Polygamma_of_real rGamma_real_def [abs_def])
   thus "let x = - of_nat n in (\<lambda>y. (rGamma y - rGamma x - (- 1) ^ n * setprod of_nat {1..n} *
                   (y - x)) /\<^sub>R norm (y - x)) \<midarrow>x::real\<rightarrow> 0"
-    by (simp add: has_field_derivative_def has_derivative_def fact_altdef netlimit_at Let_def)
+    by (simp add: has_field_derivative_def has_derivative_def fact_setprod netlimit_at Let_def)
 next
   fix x :: real
   have "rGamma_series x \<longlonglongrightarrow> rGamma x"
@@ -1497,7 +1500,7 @@
             exp = \<lambda>x. THE e. (\<lambda>n. \<Sum>k<n. x ^ k /\<^sub>R fact k) \<longlonglongrightarrow> e;
             pochhammer' = \<lambda>a n. \<Prod>n = 0..n. a + of_nat n
         in  (\<lambda>n. pochhammer' x n / (fact' n * exp (x * ln (real_of_nat n) *\<^sub>R 1))) \<longlonglongrightarrow> rGamma x"
-    by (simp add: fact_altdef pochhammer_Suc_setprod rGamma_series_def [abs_def] exp_def
+    by (simp add: fact_setprod pochhammer_Suc_setprod rGamma_series_def [abs_def] exp_def
                   of_real_def [symmetric] suminf_def sums_def [abs_def] atLeast0AtMost)
 qed
 
@@ -2424,8 +2427,8 @@
          (simp_all add: Gamma_series_euler'_def setprod.distrib
                         setprod_inversef[symmetric] divide_inverse)
     also have "(\<Prod>k=1..n. (1 + z / of_nat k)) = pochhammer (z + 1) n / fact n"
-      by (cases n) (simp_all add: pochhammer_def fact_altdef setprod_shift_bounds_cl_Suc_ivl
-                                  setprod_dividef[symmetric] divide_simps add_ac atLeast0AtMost lessThan_Suc_atMost)
+      by (cases n) (simp_all add: pochhammer_setprod fact_setprod atLeastLessThanSuc_atLeastAtMost
+        setprod_dividef [symmetric] field_simps setprod.atLeast_Suc_atMost_Suc_shift)
     also have "z * \<dots> = pochhammer z (Suc n) / fact n" by (simp add: pochhammer_rec)
     finally show "?r n = Gamma_series_euler' z n / Gamma_series z n" by simp
   qed
@@ -2679,7 +2682,7 @@
         using Suc.IH[of "z+1"] Suc.prems by (intro has_integral_mult_left) (simp_all add: add_ac pochhammer_rec)
       also have "?A = (\<lambda>t. ?f t * ?g' t)" by (intro ext) (simp_all add: field_simps)
       also have "?B = - (of_nat (Suc n) * fact n / pochhammer z (n+2))"
-        by (simp add: divide_simps setprod_nat_ivl_1_Suc pochhammer_rec
+        by (simp add: divide_simps pochhammer_rec
               setprod_shift_bounds_cl_Suc_ivl del: of_nat_Suc)
       finally show "((\<lambda>t. ?f t * ?g' t) has_integral (?f 1 * ?g 1 - ?f 0 * ?g 0 - ?I)) {0..1}"
         by simp
--- a/src/HOL/Multivariate_Analysis/Generalised_Binomial_Theorem.thy	Fri Jul 08 23:43:11 2016 +0200
+++ b/src/HOL/Multivariate_Analysis/Generalised_Binomial_Theorem.thy	Sat Jul 09 13:26:16 2016 +0200
@@ -27,12 +27,13 @@
     show "eventually (\<lambda>n. ?f n = (a gchoose n) /(a gchoose Suc n)) sequentially"
   proof eventually_elim
     fix n :: nat assume n: "n > 0"
-    let ?P = "\<Prod>i<n. a - of_nat i"
+    then obtain q where q: "n = Suc q" by (cases n) blast
+    let ?P = "\<Prod>i=0..<n. a - of_nat i"
     from n have "(a gchoose n) / (a gchoose Suc n) = (of_nat (Suc n) :: 'a) *
-                   (?P / (\<Prod>i\<le>n. a - of_nat i))"
-      by (simp add: gbinomial_def lessThan_Suc_atMost)
-    also from n have "(\<Prod>i\<le>n. a - of_nat i) = ?P * (a - of_nat n)"
-      by (cases n) (simp_all add: setprod_nat_ivl_Suc lessThan_Suc_atMost)
+                   (?P / (\<Prod>i=0..n. a - of_nat i))"
+      by (simp add: gbinomial_setprod_rev atLeastLessThanSuc_atLeastAtMost)
+    also from q have "(\<Prod>i=0..n. a - of_nat i) = ?P * (a - of_nat n)"
+      by (simp add: setprod.atLeast0_atMost_Suc atLeastLessThanSuc_atLeastAtMost)
     also have "?P / \<dots> = (?P / ?P) / (a - of_nat n)" by (rule divide_divide_eq_left[symmetric])
     also from assms have "?P / ?P = 1" by auto
     also have "of_nat (Suc n) * (1 / (a - of_nat n)) = 
@@ -119,7 +120,7 @@
   have "\<exists>c. \<forall>z\<in>ball 0 K. f z * (1 + z) powr (-a) = c"
   proof (rule has_field_derivative_zero_constant)
     fix z :: complex assume z': "z \<in> ball 0 K"
-    hence z: "norm z < K" by (simp add: dist_0_norm)
+    hence z: "norm z < K" by simp
     with K have nz: "1 + z \<noteq> 0" by (auto dest!: minus_unique)
     from z K have "norm z < 1" by simp
     hence "(1 + z) \<notin> \<real>\<^sub>\<le>\<^sub>0" by (cases z) (auto simp: complex_nonpos_Reals_iff)
@@ -209,7 +210,7 @@
   also have "(of_real (1 + z) :: complex) powr (of_real a) = of_real ((1 + z) powr a)"
     using assms by (subst powr_of_real) simp_all
   also have "(of_real a gchoose n :: complex) = of_real (a gchoose n)" for n 
-    by (simp add: gbinomial_def)
+    by (simp add: gbinomial_setprod_rev)
   hence "(\<lambda>n. (of_real a gchoose n :: complex) * of_real z ^ n) =
            (\<lambda>n. of_real ((a gchoose n) * z ^ n))" by (intro ext) simp
   finally show ?thesis by (simp only: sums_of_real_iff)
--- a/src/HOL/Multivariate_Analysis/ex/Approximations.thy	Fri Jul 08 23:43:11 2016 +0200
+++ b/src/HOL/Multivariate_Analysis/ex/Approximations.thy	Sat Jul 09 13:26:16 2016 +0200
@@ -185,11 +185,11 @@
   also have "\<dots> = (\<Sum>k\<le>n. 1 / fact k)"
   proof (intro setsum.cong refl)
     fix k assume k: "k \<in> {..n}"
-    have "fact n = (\<Prod>i=1..n. real i)" by (rule fact_altdef)
+    have "fact n = (\<Prod>i=1..n. real i)" by (simp add: fact_setprod)
     also from k have "{1..n} = {1..k} \<union> {k+1..n}" by auto
     also have "setprod real \<dots> / (\<Prod>i=k+1..n. real i) = (\<Prod>i=1..k. real i)"
       by (subst nonzero_divide_eq_eq, simp, subst setprod.union_disjoint [symmetric]) auto
-    also have "\<dots> = fact k" by (simp only: fact_altdef)
+    also have "\<dots> = fact k" by (simp add: fact_setprod)
     finally show "1 / (fact n / setprod real {k + 1..n}) = 1 / fact k" by simp
   qed
   also have "\<dots> = euler_approx n" by (simp add: euler_approx_def field_simps)
--- a/src/HOL/NthRoot.thy	Fri Jul 08 23:43:11 2016 +0200
+++ b/src/HOL/NthRoot.thy	Sat Jul 09 13:26:16 2016 +0200
@@ -246,7 +246,7 @@
   have "continuous_on ({0..} \<union> {.. 0}) (\<lambda>x. if 0 < x then x ^ n else - ((-x) ^ n) :: real)"
     using n by (intro continuous_on_If continuous_intros) auto
   then have "continuous_on UNIV ?f"
-    by (rule continuous_on_cong[THEN iffD1, rotated 2]) (auto simp: not_less sgn_neg le_less n)
+    by (rule continuous_on_cong[THEN iffD1, rotated 2]) (auto simp: not_less le_less n)
   then have [simp]: "\<And>x. isCont ?f x"
     by (simp add: continuous_on_eq_continuous_at)
 
@@ -654,8 +654,7 @@
          (simp_all add: at_infinity_eq_at_top_bot)
     { fix n :: nat assume "2 < n"
       have "1 + (real (n - 1) * n) / 2 * x n^2 = 1 + of_nat (n choose 2) * x n^2"
-        using \<open>2 < n\<close> unfolding gbinomial_def binomial_gbinomial
-        by (simp add: atLeast0AtMost lessThan_Suc field_simps of_nat_diff numeral_2_eq_2)
+        by (auto simp add: choose_two of_nat_div mod_eq_0_iff_dvd)
       also have "\<dots> \<le> (\<Sum>k\<in>{0, 2}. of_nat (n choose k) * x n^k)"
         by (simp add: x_def)
       also have "\<dots> \<le> (\<Sum>k=0..n. of_nat (n choose k) * x n^k)"
@@ -692,8 +691,7 @@
            (simp_all add: at_infinity_eq_at_top_bot)
       { fix n :: nat assume "1 < n"
         have "1 + x n * n = 1 + of_nat (n choose 1) * x n^1"
-          using \<open>1 < n\<close> unfolding gbinomial_def binomial_gbinomial
-            by (simp add: lessThan_Suc)
+          by (simp add: choose_one)
         also have "\<dots> \<le> (\<Sum>k\<in>{0, 1}. of_nat (n choose k) * x n^k)"
           by (simp add: x_def)
         also have "\<dots> \<le> (\<Sum>k=0..n. of_nat (n choose k) * x n^k)"
--- a/src/HOL/Number_Theory/Residues.thy	Fri Jul 08 23:43:11 2016 +0200
+++ b/src/HOL/Number_Theory/Residues.thy	Sat Jul 09 13:26:16 2016 +0200
@@ -426,7 +426,7 @@
     apply auto
     done
   also have "\<dots> = fact (p - 1) mod p"
-    apply (subst fact_altdef_nat)
+    apply (simp add: fact_setprod)
     apply (insert assms)
     apply (subst res_prime_units_eq)
     apply (simp add: int_setprod zmod_int setprod_int_eq)
@@ -443,7 +443,7 @@
 proof (cases "p = 2")
   case True
   then show ?thesis
-    by (simp add: cong_int_def fact_altdef_nat)
+    by (simp add: cong_int_def fact_setprod)
 next
   case False
   then show ?thesis
--- a/src/HOL/Power.thy	Fri Jul 08 23:43:11 2016 +0200
+++ b/src/HOL/Power.thy	Sat Jul 09 13:26:16 2016 +0200
@@ -164,7 +164,7 @@
 
 lemma of_nat_power [simp]:
   "of_nat (m ^ n) = of_nat m ^ n"
-  by (induct n) (simp_all add: of_nat_mult)
+  by (induct n) simp_all
 
 lemma zero_power:
   "0 < n \<Longrightarrow> 0 ^ n = 0"
@@ -645,10 +645,10 @@
   by (simp add: le_less)
 
 lemma abs_power2 [simp]: "\<bar>a\<^sup>2\<bar> = a\<^sup>2"
-  by (simp add: power2_eq_square abs_mult abs_mult_self)
+  by (simp add: power2_eq_square)
 
 lemma power2_abs [simp]: "\<bar>a\<bar>\<^sup>2 = a\<^sup>2"
-  by (simp add: power2_eq_square abs_mult_self)
+  by (simp add: power2_eq_square)
 
 lemma odd_power_less_zero:
   "a < 0 \<Longrightarrow> a ^ Suc (2*n) < 0"
@@ -749,6 +749,18 @@
   "(x - y)\<^sup>2 = (y - x)\<^sup>2"
   by (simp add: algebra_simps power2_eq_square)
 
+lemma (in comm_ring_1) minus_power_mult_self:
+  "(- a) ^ n * (- a) ^ n = a ^ (2 * n)"
+  by (simp add: power_mult_distrib [symmetric]) (simp add: power2_eq_square [symmetric] power_mult [symmetric])
+  
+lemma (in comm_ring_1) minus_one_mult_self [simp]:
+  "(- 1) ^ n * (- 1) ^ n = 1"
+  using minus_power_mult_self [of 1 n] by simp
+
+lemma (in comm_ring_1) left_minus_one_mult_self [simp]:
+  "(- 1) ^ n * ((- 1) ^ n * a) = a"
+  by (simp add: mult.assoc [symmetric])
+
 text \<open>Simprules for comparisons where common factors can be cancelled.\<close>
 
 lemmas zero_compare_simps =
--- a/src/HOL/Set_Interval.thy	Fri Jul 08 23:43:11 2016 +0200
+++ b/src/HOL/Set_Interval.thy	Sat Jul 09 13:26:16 2016 +0200
@@ -743,18 +743,43 @@
 used, the opposite orientation seems preferable because it reduces a
 specific concept to a more general one.\<close>
 
-lemma atLeast0LessThan: "{0::nat..<n} = {..<n}"
+lemma atLeast0LessThan [code_abbrev]: "{0::nat..<n} = {..<n}"
 by(simp add:lessThan_def atLeastLessThan_def)
 
-lemma atLeast0AtMost: "{0..n::nat} = {..n}"
+lemma atLeast0AtMost [code_abbrev]: "{0..n::nat} = {..n}"
 by(simp add:atMost_def atLeastAtMost_def)
 
-declare atLeast0LessThan[symmetric, code_unfold]
-        atLeast0AtMost[symmetric, code_unfold]
+lemma lessThan_atLeast0:
+  "{..<n} = {0::nat..<n}"
+  by (simp add: atLeast0LessThan)
+
+lemma atMost_atLeast0:
+  "{..n} = {0::nat..n}"
+  by (simp add: atLeast0AtMost)
 
 lemma atLeastLessThan0: "{m..<0::nat} = {}"
 by (simp add: atLeastLessThan_def)
 
+lemma atLeast0_lessThan_Suc:
+  "{0..<Suc n} = insert n {0..<n}"
+  by (simp add: atLeast0LessThan lessThan_Suc)
+
+lemma atLeast0_lessThan_Suc_eq_insert_0:
+  "{0..<Suc n} = insert 0 (Suc ` {0..<n})"
+  by (simp add: atLeast0LessThan lessThan_Suc_eq_insert_0)
+
+
+subsubsection \<open>The Constant @{term atLeastAtMost}\<close>
+
+lemma atLeast0_atMost_Suc:
+  "{0..Suc n} = insert (Suc n) {0..n}"
+  by (simp add: atLeast0AtMost atMost_Suc)
+
+lemma atLeast0_atMost_Suc_eq_insert_0:
+  "{0..Suc n} = insert 0 (Suc ` {0..n})"
+  by (simp add: atLeast0AtMost Iic_Suc_eq_insert_0)
+
+
 subsubsection \<open>Intervals of nats with @{term Suc}\<close>
 
 text\<open>Not a simprule because the RHS is too messy.\<close>
@@ -1164,11 +1189,17 @@
 lemma card_greaterThanLessThan [simp]: "card {l<..<u} = u - Suc l"
   by (subst atLeastSucLessThan_greaterThanLessThan [THEN sym], simp)
 
-lemma subset_eq_range_finite:
+lemma subset_eq_atLeast0_lessThan_finite:
   fixes n :: nat
-  assumes "N \<subseteq> {..<n}"
+  assumes "N \<subseteq> {0..<n}"
   shows "finite N" 
-  using assms finite_lessThan by (rule finite_subset)
+  using assms finite_atLeastLessThan by (rule finite_subset)
+
+lemma subset_eq_atLeast0_atMost_finite:
+  fixes n :: nat
+  assumes "N \<subseteq> {0..n}"
+  shows "finite N" 
+  using assms finite_atLeastAtMost by (rule finite_subset)
 
 lemma ex_bij_betw_nat_finite:
   "finite M \<Longrightarrow> \<exists>h. bij_betw h {0..<card M} M"
@@ -1180,18 +1211,6 @@
   "finite M \<Longrightarrow> \<exists>h. bij_betw h M {0..<card M}"
 by (blast dest: ex_bij_betw_nat_finite bij_betw_inv)
 
-lemma bij_betw_nat_finite:
-  assumes "finite A"
-  obtains f where "bij_betw f {..<card A} A"
-proof -
-  from assms obtain f where "bij_betw f {0..<card A} A"
-    by (blast dest: ex_bij_betw_nat_finite)
-  also have "{0..<card A} = {..<card A}"
-    by auto
-  finally show thesis using that
-    by blast
-qed
-
 lemma finite_same_card_bij:
   "finite A \<Longrightarrow> finite B \<Longrightarrow> card A = card B \<Longrightarrow> EX h. bij_betw h A B"
 apply(drule ex_bij_betw_finite_nat)
@@ -1236,12 +1255,12 @@
   ultimately show "(\<exists>f. inj_on f A \<and> f ` A \<le> B)" by blast
 qed (insert assms, auto)
 
-lemma subset_eq_range_card:
+lemma subset_eq_atLeast0_lessThan_card:
   fixes n :: nat
-  assumes "N \<subseteq> {..<n}"
+  assumes "N \<subseteq> {0..<n}"
   shows "card N \<le> n"
 proof -
-  from assms finite_lessThan have "card N \<le> card {..<n}"
+  from assms finite_lessThan have "card N \<le> card {0..<n}"
     using card_mono by blast
   then show ?thesis by simp
 qed
@@ -1480,6 +1499,100 @@
 done
 
 
+subsection \<open>Generic big monoid operation over intervals\<close>
+
+lemma inj_on_add_nat' [simp]:
+  "inj_on (plus k) N" for k :: nat
+  by rule simp
+
+context comm_monoid_set
+begin
+
+lemma atLeast_lessThan_shift_bounds:
+  fixes m n k :: nat
+  shows "F g {m + k..<n + k} = F (g \<circ> plus k) {m..<n}"
+proof -
+  have "{m + k..<n + k} = plus k ` {m..<n}"
+    by (auto simp add: image_add_atLeastLessThan [symmetric])
+  also have "F g (plus k ` {m..<n}) = F (g \<circ> plus k) {m..<n}"
+    by (rule reindex) simp
+  finally show ?thesis .
+qed
+
+lemma atLeast_atMost_shift_bounds:
+  fixes m n k :: nat
+  shows "F g {m + k..n + k} = F (g \<circ> plus k) {m..n}"
+proof -
+  have "{m + k..n + k} = plus k ` {m..n}"
+    by (auto simp del: image_add_atLeastAtMost simp add: image_add_atLeastAtMost [symmetric])
+  also have "F g (plus k ` {m..n}) = F (g \<circ> plus k) {m..n}"
+    by (rule reindex) simp
+  finally show ?thesis .
+qed
+
+lemma atLeast_Suc_lessThan_Suc_shift:
+  "F g {Suc m..<Suc n} = F (g \<circ> Suc) {m..<n}"
+  using atLeast_lessThan_shift_bounds [of _ _ 1] by simp
+
+lemma atLeast_Suc_atMost_Suc_shift:
+  "F g {Suc m..Suc n} = F (g \<circ> Suc) {m..n}"
+  using atLeast_atMost_shift_bounds [of _ _ 1] by simp
+
+lemma atLeast0_lessThan_Suc:
+  "F g {0..<Suc n} = F g {0..<n} \<^bold>* g n"
+  by (simp add: atLeast0_lessThan_Suc ac_simps)
+
+lemma atLeast0_atMost_Suc:
+  "F g {0..Suc n} = F g {0..n} \<^bold>* g (Suc n)"
+  by (simp add: atLeast0_atMost_Suc ac_simps)
+
+lemma atLeast0_lessThan_Suc_shift:
+  "F g {0..<Suc n} = g 0 \<^bold>* F (g \<circ> Suc) {0..<n}"
+  by (simp add: atLeast0_lessThan_Suc_eq_insert_0 atLeast_Suc_lessThan_Suc_shift)
+
+lemma atLeast0_atMost_Suc_shift:
+  "F g {0..Suc n} = g 0 \<^bold>* F (g \<circ> Suc) {0..n}"
+  by (simp add: atLeast0_atMost_Suc_eq_insert_0 atLeast_Suc_atMost_Suc_shift)
+
+lemma ivl_cong:
+  "a = c \<Longrightarrow> b = d \<Longrightarrow> (\<And>x. c \<le> x \<Longrightarrow> x < d \<Longrightarrow> g x = h x)
+    \<Longrightarrow> F g {a..<b} = F h {c..<d}"
+  by (rule cong) simp_all
+
+lemma atLeast_lessThan_shift_0:
+  fixes m n p :: nat
+  shows "F g {m..<n} = F (g \<circ> plus m) {0..<n - m}"
+  using atLeast_lessThan_shift_bounds [of g 0 m "n - m"]
+  by (cases "m \<le> n") simp_all
+
+lemma atLeast_atMost_shift_0:
+  fixes m n p :: nat
+  assumes "m \<le> n"
+  shows "F g {m..n} = F (g \<circ> plus m) {0..n - m}"
+  using assms atLeast_atMost_shift_bounds [of g 0 m "n - m"] by simp
+
+lemma atLeast_lessThan_concat:
+  fixes m n p :: nat
+  shows "m \<le> n \<Longrightarrow> n \<le> p \<Longrightarrow> F g {m..<n} \<^bold>* F g {n..<p} = F g {m..<p}"
+  by (simp add: union_disjoint [symmetric] ivl_disj_un)
+
+lemma atLeast_lessThan_rev:
+  "F g {n..<m} = F (\<lambda>i. g (m + n - Suc i)) {n..<m}"
+  by (rule reindex_bij_witness [where i="\<lambda>i. m + n - Suc i" and j="\<lambda>i. m + n - Suc i"], auto)
+
+lemma atLeast_atMost_rev:
+  fixes n m :: nat
+  shows "F g {n..m} = F (\<lambda>i. g (m + n - i)) {n..m}"
+  by (rule reindex_bij_witness [where i="\<lambda>i. m + n - i" and j="\<lambda>i. m + n - i"]) auto
+
+lemma atLeast_lessThan_rev_at_least_Suc_atMost:
+  "F g {n..<m} = F (\<lambda>i. g (m + n - i)) {Suc n..m}"
+  unfolding atLeast_lessThan_rev [of g n m]
+  by (cases m) (simp_all add: atLeast_Suc_atMost_Suc_shift atLeastLessThanSuc_atLeastAtMost)
+
+end
+
+
 subsection \<open>Summation indexed over intervals\<close>
 
 syntax (ASCII)
@@ -1539,27 +1652,26 @@
 with the simplifier who adds the unsimplified premise @{term"x:B"} to
 the context.\<close>
 
-lemma setsum_ivl_cong:
- "\<lbrakk>a = c; b = d; !!x. \<lbrakk> c \<le> x; x < d \<rbrakk> \<Longrightarrow> f x = g x \<rbrakk> \<Longrightarrow>
- setsum f {a..<b} = setsum g {c..<d}"
-by(rule setsum.cong, simp_all)
+lemmas setsum_ivl_cong = setsum.ivl_cong
 
 (* FIXME why are the following simp rules but the corresponding eqns
 on intervals are not? *)
 
-lemma setsum_atMost_Suc[simp]: "(\<Sum>i \<le> Suc n. f i) = (\<Sum>i \<le> n. f i) + f(Suc n)"
-by (simp add:atMost_Suc ac_simps)
+lemma setsum_atMost_Suc [simp]:
+  "(\<Sum>i \<le> Suc n. f i) = (\<Sum>i \<le> n. f i) + f (Suc n)"
+  by (simp add: atMost_Suc ac_simps)
 
-lemma setsum_lessThan_Suc[simp]: "(\<Sum>i < Suc n. f i) = (\<Sum>i < n. f i) + f n"
-by (simp add:lessThan_Suc ac_simps)
+lemma setsum_lessThan_Suc [simp]:
+  "(\<Sum>i < Suc n. f i) = (\<Sum>i < n. f i) + f n"
+  by (simp add: lessThan_Suc ac_simps)
 
-lemma setsum_cl_ivl_Suc[simp]:
+lemma setsum_cl_ivl_Suc [simp]:
   "setsum f {m..Suc n} = (if Suc n < m then 0 else setsum f {m..n} + f(Suc n))"
-by (auto simp:ac_simps atLeastAtMostSuc_conv)
+  by (auto simp: ac_simps atLeastAtMostSuc_conv)
 
-lemma setsum_op_ivl_Suc[simp]:
+lemma setsum_op_ivl_Suc [simp]:
   "setsum f {m..<Suc n} = (if n < m then 0 else setsum f {m..<n} + f(n))"
-by (auto simp:ac_simps atLeastLessThanSuc)
+  by (auto simp: ac_simps atLeastLessThanSuc)
 (*
 lemma setsum_cl_ivl_add_one_nat: "(n::nat) <= m + 1 ==>
     (\<Sum>i=n..m+1. f i) = (\<Sum>i=n..m. f i) + f(m + 1)"
@@ -1598,9 +1710,7 @@
     atLeastSucAtMost_greaterThanAtMost)
 qed
 
-lemma setsum_add_nat_ivl: "\<lbrakk> m \<le> n; n \<le> p \<rbrakk> \<Longrightarrow>
-  setsum f {m..<n} + setsum f {n..<p} = setsum f {m..<p::nat}"
-by (simp add:setsum.union_disjoint[symmetric] ivl_disj_int ivl_disj_un)
+lemmas setsum_add_nat_ivl = setsum.atLeast_lessThan_concat
 
 lemma setsum_diff_nat_ivl:
 fixes f :: "nat \<Rightarrow> 'a::ab_group_add"
@@ -1639,7 +1749,8 @@
 lemma nat_diff_setsum_reindex: "(\<Sum>i<n. f (n - Suc i)) = (\<Sum>i<n. f i)"
   by (rule setsum.reindex_bij_witness[where i="\<lambda>i. n - Suc i" and j="\<lambda>i. n - Suc i"]) auto
 
-subsection\<open>Shifting bounds\<close>
+
+subsubsection \<open>Shifting bounds\<close>
 
 lemma setsum_shift_bounds_nat_ivl:
   "setsum f {m+k..<n+k} = setsum (%i. f(i + k)){m..<n::nat}"
@@ -1723,7 +1834,7 @@
 qed
 
 
-subsection \<open>Telescoping\<close>
+subsubsection \<open>Telescoping\<close>
 
 lemma setsum_telescope:
   fixes f::"nat \<Rightarrow> 'a::ab_group_add"
@@ -1735,7 +1846,8 @@
   shows   "(\<Sum>k\<in>{Suc m..n}. f k - f (k - 1)) = f n - (f m :: 'a :: ab_group_add)"
   by (rule dec_induct[OF assms]) (simp_all add: algebra_simps)
 
-subsection \<open>The formula for geometric sums\<close>
+
+subsubsection \<open>The formula for geometric sums\<close>
 
 lemma geometric_sum:
   assumes "x \<noteq> 1"
@@ -1743,7 +1855,7 @@
 proof -
   from assms obtain y where "y = x - 1" and "y \<noteq> 0" by simp_all
   moreover have "(\<Sum>i<n. (y + 1) ^ i) = ((y + 1) ^ n - 1) / y"
-    by (induct n) (simp_all add: power_Suc field_simps \<open>y \<noteq> 0\<close>)
+    by (induct n) (simp_all add: field_simps \<open>y \<noteq> 0\<close>)
   ultimately show ?thesis by simp
 qed
 
@@ -1755,15 +1867,15 @@
 proof (induct n)
   case (Suc n)
   have "x ^ Suc (Suc n) - y ^ Suc (Suc n) = x * (x * x^n) - y * (y * y ^ n)"
-    by (simp add: power_Suc)
+    by simp
   also have "... = y * (x ^ (Suc n) - y ^ (Suc n)) + (x - y) * (x * x^n)"
-    by (simp add: power_Suc algebra_simps)
+    by (simp add: algebra_simps)
   also have "... = y * ((x - y) * (\<Sum>p<Suc n. (x ^ p) * y ^ (n - p))) + (x - y) * (x * x^n)"
     by (simp only: Suc)
   also have "... = (x - y) * (y * (\<Sum>p<Suc n. (x ^ p) * y ^ (n - p))) + (x - y) * (x * x^n)"
     by (simp only: mult.left_commute)
   also have "... = (x - y) * (\<Sum>p<Suc (Suc n). x ^ p * y ^ (Suc n - p))"
-    by (simp add: power_Suc field_simps Suc_diff_le setsum_left_distrib setsum_right_distrib)
+    by (simp add: field_simps Suc_diff_le setsum_left_distrib setsum_right_distrib)
   finally show ?case .
 qed simp
 
@@ -1791,7 +1903,7 @@
 by (metis one_diff_power_eq' [of n x] nat_diff_setsum_reindex)
 
 
-subsection \<open>The formula for arithmetic sums\<close>
+subsubsection \<open>The formula for arithmetic sums\<close>
 
 lemma gauss_sum:
   "(2::'a::comm_semiring_1)*(\<Sum>i\<in>{1..n}. of_nat i) = of_nat n*((of_nat n)+1)"
@@ -1854,6 +1966,29 @@
   by (subst setsum_subtractf_nat) auto
 
 
+subsubsection \<open>Division remainder\<close>
+
+lemma range_mod:
+  fixes n :: nat
+  assumes "n > 0"
+  shows "range (\<lambda>m. m mod n) = {0..<n}" (is "?A = ?B")
+proof (rule set_eqI)
+  fix m
+  show "m \<in> ?A \<longleftrightarrow> m \<in> ?B"
+  proof
+    assume "m \<in> ?A"
+    with assms show "m \<in> ?B"
+      by auto 
+  next
+    assume "m \<in> ?B"
+    moreover have "m mod n \<in> ?A"
+      by (rule rangeI)
+    ultimately show "m \<in> ?A"
+      by simp
+  qed
+qed
+
+
 subsection \<open>Products indexed over intervals\<close>
 
 syntax (ASCII)
@@ -1884,44 +2019,6 @@
   "\<Prod>i\<le>n. t" \<rightleftharpoons> "CONST setprod (\<lambda>i. t) {..n}"
   "\<Prod>i<n. t" \<rightleftharpoons> "CONST setprod (\<lambda>i. t) {..<n}"
 
-
-subsection \<open>Transfer setup\<close>
-
-lemma transfer_nat_int_set_functions:
-    "{..n} = nat ` {0..int n}"
-    "{m..n} = nat ` {int m..int n}"  (* need all variants of these! *)
-  apply (auto simp add: image_def)
-  apply (rule_tac x = "int x" in bexI)
-  apply auto
-  apply (rule_tac x = "int x" in bexI)
-  apply auto
-  done
-
-lemma transfer_nat_int_set_function_closures:
-    "x >= 0 \<Longrightarrow> nat_set {x..y}"
-  by (simp add: nat_set_def)
-
-declare transfer_morphism_nat_int[transfer add
-  return: transfer_nat_int_set_functions
-    transfer_nat_int_set_function_closures
-]
-
-lemma transfer_int_nat_set_functions:
-    "is_nat m \<Longrightarrow> is_nat n \<Longrightarrow> {m..n} = int ` {nat m..nat n}"
-  by (simp only: is_nat_def transfer_nat_int_set_functions
-    transfer_nat_int_set_function_closures
-    transfer_nat_int_set_return_embed nat_0_le
-    cong: transfer_nat_int_set_cong)
-
-lemma transfer_int_nat_set_function_closures:
-    "is_nat x \<Longrightarrow> nat_set {x..y}"
-  by (simp only: transfer_nat_int_set_function_closures is_nat_def)
-
-declare transfer_morphism_int_nat[transfer add
-  return: transfer_int_nat_set_functions
-    transfer_int_nat_set_function_closures
-]
-
 lemma setprod_int_plus_eq: "setprod int {i..i+j} =  \<Prod>{int i..int (i+j)}"
   by (induct j) (auto simp add: atLeastAtMostSuc_conv atLeastAtMostPlus1_int_conv)
 
@@ -1937,7 +2034,7 @@
 qed
 
 
-subsection \<open>Shifting bounds\<close>
+subsubsection \<open>Shifting bounds\<close>
 
 lemma setprod_shift_bounds_nat_ivl:
   "setprod f {m+k..<n+k} = setprod (%i. f(i + k)){m..<n::nat}"
@@ -1974,29 +2071,6 @@
 qed
 
 
-subsection \<open>Division remainder\<close>
-
-lemma range_mod:
-  fixes n :: nat
-  assumes "n > 0"
-  shows "range (\<lambda>m. m mod n) = {0..<n}" (is "?A = ?B")
-proof (rule set_eqI)
-  fix m
-  show "m \<in> ?A \<longleftrightarrow> m \<in> ?B"
-  proof
-    assume "m \<in> ?A"
-    with assms show "m \<in> ?B"
-      by auto 
-  next
-    assume "m \<in> ?B"
-    moreover have "m mod n \<in> ?A"
-      by (rule rangeI)
-    ultimately show "m \<in> ?A"
-      by simp
-  qed
-qed
-
-
 subsection \<open>Efficient folding over intervals\<close>
 
 function fold_atLeastAtMost_nat where
@@ -2044,4 +2118,42 @@
 
 (* TODO: Add support for more kinds of intervals here *)
 
+
+subsection \<open>Transfer setup\<close>
+
+lemma transfer_nat_int_set_functions:
+    "{..n} = nat ` {0..int n}"
+    "{m..n} = nat ` {int m..int n}"  (* need all variants of these! *)
+  apply (auto simp add: image_def)
+  apply (rule_tac x = "int x" in bexI)
+  apply auto
+  apply (rule_tac x = "int x" in bexI)
+  apply auto
+  done
+
+lemma transfer_nat_int_set_function_closures:
+    "x >= 0 \<Longrightarrow> nat_set {x..y}"
+  by (simp add: nat_set_def)
+
+declare transfer_morphism_nat_int[transfer add
+  return: transfer_nat_int_set_functions
+    transfer_nat_int_set_function_closures
+]
+
+lemma transfer_int_nat_set_functions:
+    "is_nat m \<Longrightarrow> is_nat n \<Longrightarrow> {m..n} = int ` {nat m..nat n}"
+  by (simp only: is_nat_def transfer_nat_int_set_functions
+    transfer_nat_int_set_function_closures
+    transfer_nat_int_set_return_embed nat_0_le
+    cong: transfer_nat_int_set_cong)
+
+lemma transfer_int_nat_set_function_closures:
+    "is_nat x \<Longrightarrow> nat_set {x..y}"
+  by (simp only: transfer_nat_int_set_function_closures is_nat_def)
+
+declare transfer_morphism_int_nat[transfer add
+  return: transfer_int_nat_set_functions
+    transfer_int_nat_set_function_closures
+]
+
 end
--- a/src/HOL/Transcendental.thy	Fri Jul 08 23:43:11 2016 +0200
+++ b/src/HOL/Transcendental.thy	Sat Jul 09 13:26:16 2016 +0200
@@ -36,7 +36,7 @@
   by (metis of_nat_fact of_real_of_nat_eq)
 
 lemma pochhammer_of_real: "pochhammer (of_real x) n = of_real (pochhammer x n)"
-  by (simp add: pochhammer_def)
+  by (simp add: pochhammer_setprod)
 
 lemma norm_fact [simp]:
   "norm (fact n :: 'a :: {real_normed_algebra_1}) = fact n"
--- a/src/HOL/ex/Sum_of_Powers.thy	Fri Jul 08 23:43:11 2016 +0200
+++ b/src/HOL/ex/Sum_of_Powers.thy	Sat Jul 09 13:26:16 2016 +0200
@@ -7,32 +7,32 @@
 
 subsection \<open>Additions to @{theory Binomial} Theory\<close>
 
+lemma (in field_char_0) one_plus_of_nat_neq_zero [simp]:
+  "1 + of_nat n \<noteq> 0"
+proof -
+  have "of_nat (Suc n) \<noteq> of_nat 0"
+    unfolding of_nat_eq_iff by simp
+  then show ?thesis by simp
+qed
+
 lemma of_nat_binomial_eq_mult_binomial_Suc:
   assumes "k \<le> n"
   shows "(of_nat :: (nat \<Rightarrow> ('a :: field_char_0))) (n choose k) = of_nat (n + 1 - k) / of_nat (n + 1) * of_nat (Suc n choose k)"
-proof -
-  have "of_nat (n + 1) * (\<Prod>i<k. of_nat (n - i)) = (of_nat :: (nat \<Rightarrow> 'a)) (n + 1 - k) * (\<Prod>i<k. of_nat (Suc n - i))"
-  proof -
-    have "of_nat (n + 1) * (\<Prod>i<k. of_nat (n - i)) = (of_nat :: (nat \<Rightarrow> 'a)) (n + 1) * (\<Prod>i\<in>Suc ` {..<k}. of_nat (Suc n - i))"
-      by (auto simp add: setprod.reindex)
-    also have "... = (\<Prod>i\<le>k. of_nat (Suc n - i))"
-    proof (cases k)
-      case (Suc k')
-      have "of_nat (n + 1) * (\<Prod>i\<in>Suc ` {..<Suc k'}. of_nat (Suc n - i)) = (\<Prod>i\<in>insert 0 (Suc ` {..k'}). of_nat (Suc n - i))"
-        by (subst setprod.insert) (auto simp add: lessThan_Suc_atMost)
-      also have "... = (\<Prod>i\<le>Suc k'. of_nat (Suc n - i))" by (simp only: Iic_Suc_eq_insert_0)
-      finally show ?thesis using Suc by simp
-    qed (simp)
-    also have "... = (of_nat :: (nat \<Rightarrow> 'a)) (Suc n - k) * (\<Prod>i<k. of_nat (Suc n - i))"
-      by (cases k) (auto simp add: atMost_Suc lessThan_Suc_atMost)
-    also have "... = (of_nat :: (nat \<Rightarrow> 'a)) (n + 1 - k) * (\<Prod>i<k. of_nat (Suc n - i))"
-      by (simp only: Suc_eq_plus1)
-    finally show ?thesis .
-  qed
-  then have "(\<Prod>i<k. of_nat (n - i)) = (of_nat :: (nat \<Rightarrow> 'a)) (n + 1 - k) / of_nat (n + 1) * (\<Prod>i<k. of_nat (Suc n - i))"
-    by (metis (no_types, lifting) le_add2 nonzero_mult_divide_cancel_left not_one_le_zero of_nat_eq_0_iff times_divide_eq_left)
-  from assms this show ?thesis
-    by (auto simp add: binomial_altdef_of_nat setprod_dividef)
+proof (cases k)
+  case 0 then show ?thesis by simp
+next
+  case (Suc l)
+  have "of_nat (n + 1) * (\<Prod>i=0..<k. of_nat (n - i)) = (of_nat :: (nat \<Rightarrow> 'a)) (n + 1 - k) * (\<Prod>i=0..<k. of_nat (Suc n - i))"
+    using setprod.atLeast0_lessThan_Suc [where ?'a = 'a, symmetric, of "\<lambda>i. of_nat (Suc n - i)" k]
+    by (simp add: ac_simps setprod.atLeast0_lessThan_Suc_shift)
+  also have "... = (of_nat :: (nat \<Rightarrow> 'a)) (Suc n - k) * (\<Prod>i=0..<k. of_nat (Suc n - i))"
+    by (simp add: Suc atLeast0_atMost_Suc atLeastLessThanSuc_atLeastAtMost)
+  also have "... = (of_nat :: (nat \<Rightarrow> 'a)) (n + 1 - k) * (\<Prod>i=0..<k. of_nat (Suc n - i))"
+    by (simp only: Suc_eq_plus1)
+  finally have "(\<Prod>i=0..<k. of_nat (n - i)) = (of_nat :: (nat \<Rightarrow> 'a)) (n + 1 - k) / of_nat (n + 1) * (\<Prod>i=0..<k. of_nat (Suc n - i))"
+    by (simp add: field_simps)
+  with assms show ?thesis
+    by (simp add: binomial_altdef_of_nat setprod_dividef)
 qed
 
 lemma real_binomial_eq_mult_binomial_Suc: