src/HOL/Computational_Algebra/Polynomial.thy
changeset 73510 c526eb2c7ca0
parent 73114 9bf36baa8686
child 73932 fd21b4a93043
equal deleted inserted replaced
73509:5d750df8e894 73510:c526eb2c7ca0
   595   by (cases "c = 0") (simp_all add: degree_monom_eq)
   595   by (cases "c = 0") (simp_all add: degree_monom_eq)
   596 
   596 
   597 lemma last_coeffs_eq_coeff_degree:
   597 lemma last_coeffs_eq_coeff_degree:
   598   "last (coeffs p) = lead_coeff p" if "p \<noteq> 0"
   598   "last (coeffs p) = lead_coeff p" if "p \<noteq> 0"
   599   using that by (simp add: coeffs_def)
   599   using that by (simp add: coeffs_def)
   600   
   600 
   601 
   601 
   602 subsection \<open>Addition and subtraction\<close>
   602 subsection \<open>Addition and subtraction\<close>
   603 
   603 
   604 instantiation poly :: (comm_monoid_add) comm_monoid_add
   604 instantiation poly :: (comm_monoid_add) comm_monoid_add
   605 begin
   605 begin
   909 proof -
   909 proof -
   910   have eq_0: "HOL.eq 0 \<circ> times a = HOL.eq (0::'a)" if "a \<noteq> 0"
   910   have eq_0: "HOL.eq 0 \<circ> times a = HOL.eq (0::'a)" if "a \<noteq> 0"
   911     using that by (simp add: fun_eq_iff)
   911     using that by (simp add: fun_eq_iff)
   912   show ?thesis
   912   show ?thesis
   913     by (rule coeffs_eqI) (auto simp add: no_trailing_map nth_default_map_eq nth_default_coeffs_eq eq_0)
   913     by (rule coeffs_eqI) (auto simp add: no_trailing_map nth_default_map_eq nth_default_coeffs_eq eq_0)
   914 qed  
   914 qed
   915 
   915 
   916 lemma smult_eq_iff:
   916 lemma smult_eq_iff:
   917   fixes b :: "'a :: field"
   917   fixes b :: "'a :: field"
   918   assumes "b \<noteq> 0"
   918   assumes "b \<noteq> 0"
   919   shows "smult a p = smult b q \<longleftrightarrow> smult (a / b) p = q"
   919   shows "smult a p = smult b q \<longleftrightarrow> smult (a / b) p = q"
  1066   "monom c n = 1 \<longleftrightarrow> c = 1 \<and> n = 0"
  1066   "monom c n = 1 \<longleftrightarrow> c = 1 \<and> n = 0"
  1067   using monom_eq_const_iff [of c n 1] by auto
  1067   using monom_eq_const_iff [of c n 1] by auto
  1068 
  1068 
  1069 lemma monom_altdef:
  1069 lemma monom_altdef:
  1070   "monom c n = smult c ([:0, 1:] ^ n)"
  1070   "monom c n = smult c ([:0, 1:] ^ n)"
  1071   by (induct n) (simp_all add: monom_0 monom_Suc)  
  1071   by (induct n) (simp_all add: monom_0 monom_Suc)
  1072 
  1072 
  1073 instance poly :: ("{comm_semiring_1,semiring_1_no_zero_divisors}") semiring_1_no_zero_divisors ..
  1073 instance poly :: ("{comm_semiring_1,semiring_1_no_zero_divisors}") semiring_1_no_zero_divisors ..
  1074 instance poly :: (comm_ring) comm_ring ..
  1074 instance poly :: (comm_ring) comm_ring ..
  1075 instance poly :: (comm_ring_1) comm_ring_1 ..
  1075 instance poly :: (comm_ring_1) comm_ring_1 ..
  1076 instance poly :: (comm_ring_1) comm_semiring_1_cancel ..
  1076 instance poly :: (comm_ring_1) comm_semiring_1_cancel ..
  1495   by (simp add: pos_poly_def)
  1495   by (simp add: pos_poly_def)
  1496 
  1496 
  1497 lemma pos_poly_add: "pos_poly p \<Longrightarrow> pos_poly q \<Longrightarrow> pos_poly (p + q)"
  1497 lemma pos_poly_add: "pos_poly p \<Longrightarrow> pos_poly q \<Longrightarrow> pos_poly (p + q)"
  1498 proof (induction p arbitrary: q)
  1498 proof (induction p arbitrary: q)
  1499   case (pCons a p)
  1499   case (pCons a p)
  1500   then show ?case 
  1500   then show ?case
  1501     by (cases q; force simp add: pos_poly_pCons add_pos_pos)
  1501     by (cases q; force simp add: pos_poly_pCons add_pos_pos)
  1502 qed auto
  1502 qed auto
  1503 
  1503 
  1504 lemma pos_poly_mult: "pos_poly p \<Longrightarrow> pos_poly q \<Longrightarrow> pos_poly (p * q)"
  1504 lemma pos_poly_mult: "pos_poly p \<Longrightarrow> pos_poly q \<Longrightarrow> pos_poly (p * q)"
  1505   by (simp add: pos_poly_def coeff_degree_mult)
  1505   by (simp add: pos_poly_def coeff_degree_mult)
  1732 qed (simp add: coeff_linear_power le_degree)
  1732 qed (simp add: coeff_linear_power le_degree)
  1733 
  1733 
  1734 lemma order_1: "[:-a, 1:] ^ order a p dvd p"
  1734 lemma order_1: "[:-a, 1:] ^ order a p dvd p"
  1735 proof (cases "p = 0")
  1735 proof (cases "p = 0")
  1736   case False
  1736   case False
  1737   show ?thesis 
  1737   show ?thesis
  1738   proof (cases "order a p")
  1738   proof (cases "order a p")
  1739     case (Suc n)
  1739     case (Suc n)
  1740     then show ?thesis
  1740     then show ?thesis
  1741       by (metis lessI not_less_Least order_def)
  1741       by (metis lessI not_less_Least order_def)
  1742   qed auto
  1742   qed auto
  1743 qed auto
  1743 qed auto
  1744 
  1744 
  1745 lemma order_2: 
  1745 lemma order_2:
  1746   assumes "p \<noteq> 0" 
  1746   assumes "p \<noteq> 0"
  1747   shows "\<not> [:-a, 1:] ^ Suc (order a p) dvd p"
  1747   shows "\<not> [:-a, 1:] ^ Suc (order a p) dvd p"
  1748 proof -
  1748 proof -
  1749   have False if "[:- a, 1:] ^ Suc (degree p) dvd p"
  1749   have False if "[:- a, 1:] ^ Suc (degree p) dvd p"
  1750     using dvd_imp_degree_le [OF that]
  1750     using dvd_imp_degree_le [OF that]
  1751     by (metis Suc_n_not_le_n assms degree_linear_power)
  1751     by (metis Suc_n_not_le_n assms degree_linear_power)
  1784   assumes "[:-a, 1:] ^ n dvd p" "\<not> [:-a, 1:] ^ Suc n dvd p"
  1784   assumes "[:-a, 1:] ^ n dvd p" "\<not> [:-a, 1:] ^ Suc n dvd p"
  1785   shows "order a p = n"
  1785   shows "order a p = n"
  1786   unfolding Polynomial.order_def
  1786   unfolding Polynomial.order_def
  1787   by (metis (mono_tags, lifting) Least_equality assms not_less_eq_eq power_le_dvd)
  1787   by (metis (mono_tags, lifting) Least_equality assms not_less_eq_eq power_le_dvd)
  1788 
  1788 
  1789 lemma order_mult: 
  1789 lemma order_mult:
  1790   assumes "p * q \<noteq> 0" shows "order a (p * q) = order a p + order a q"
  1790   assumes "p * q \<noteq> 0" shows "order a (p * q) = order a p + order a q"
  1791 proof -
  1791 proof -
  1792   define i where "i \<equiv> order a p"
  1792   define i where "i \<equiv> order a p"
  1793   define j where "j \<equiv> order a q"
  1793   define j where "j \<equiv> order a q"
  1794   define t where "t \<equiv> [:-a, 1:]"
  1794   define t where "t \<equiv> [:-a, 1:]"
  1826 text \<open>Next three lemmas contributed by Wenda Li\<close>
  1826 text \<open>Next three lemmas contributed by Wenda Li\<close>
  1827 lemma order_1_eq_0 [simp]:"order x 1 = 0"
  1827 lemma order_1_eq_0 [simp]:"order x 1 = 0"
  1828   by (metis order_root poly_1 zero_neq_one)
  1828   by (metis order_root poly_1 zero_neq_one)
  1829 
  1829 
  1830 lemma order_uminus[simp]: "order x (-p) = order x p"
  1830 lemma order_uminus[simp]: "order x (-p) = order x p"
  1831   by (metis neg_equal_0_iff_equal order_smult smult_1_left smult_minus_left) 
  1831   by (metis neg_equal_0_iff_equal order_smult smult_1_left smult_minus_left)
  1832 
  1832 
  1833 lemma order_power_n_n: "order a ([:-a,1:]^n)=n"
  1833 lemma order_power_n_n: "order a ([:-a,1:]^n)=n"
  1834 proof (induct n) (*might be proved more concisely using nat_less_induct*)
  1834 proof (induct n) (*might be proved more concisely using nat_less_induct*)
  1835   case 0
  1835   case 0
  1836   then show ?case
  1836   then show ?case
  2508 
  2508 
  2509 lemma pderiv_eq_0_iff: "pderiv p = 0 \<longleftrightarrow> degree p = 0"
  2509 lemma pderiv_eq_0_iff: "pderiv p = 0 \<longleftrightarrow> degree p = 0"
  2510   for p :: "'a::{comm_semiring_1,semiring_no_zero_divisors,semiring_char_0} poly"
  2510   for p :: "'a::{comm_semiring_1,semiring_no_zero_divisors,semiring_char_0} poly"
  2511 proof (cases "degree p")
  2511 proof (cases "degree p")
  2512   case 0
  2512   case 0
  2513   then show ?thesis 
  2513   then show ?thesis
  2514     by (metis degree_eq_zeroE pderiv.simps)
  2514     by (metis degree_eq_zeroE pderiv.simps)
  2515 next
  2515 next
  2516   case (Suc n)
  2516   case (Suc n)
  2517   then show ?thesis
  2517   then show ?thesis
  2518     using coeff_0 coeff_pderiv degree_0 leading_coeff_0_iff mult_eq_0_iff nat.distinct(1) of_nat_eq_0_iff
  2518     using coeff_0 coeff_pderiv degree_0 leading_coeff_0_iff mult_eq_0_iff nat.distinct(1) of_nat_eq_0_iff
  2524 proof -
  2524 proof -
  2525   have "degree p - 1 \<le> degree (pderiv p)"
  2525   have "degree p - 1 \<le> degree (pderiv p)"
  2526   proof (cases "degree p")
  2526   proof (cases "degree p")
  2527     case (Suc n)
  2527     case (Suc n)
  2528     then show ?thesis
  2528     then show ?thesis
  2529       by (metis coeff_pderiv degree_0 diff_Suc_1 le_degree leading_coeff_0_iff mult_eq_0_iff nat.distinct(1) of_nat_eq_0_iff)      
  2529       by (metis coeff_pderiv degree_0 diff_Suc_1 le_degree leading_coeff_0_iff mult_eq_0_iff nat.distinct(1) of_nat_eq_0_iff)
  2530   qed auto
  2530   qed auto
  2531   moreover have "\<forall>i>degree p - 1. coeff (pderiv p) i = 0"
  2531   moreover have "\<forall>i>degree p - 1. coeff (pderiv p) i = 0"
  2532     by (simp add: coeff_eq_0 coeff_pderiv)
  2532     by (simp add: coeff_eq_0 coeff_pderiv)
  2533   ultimately show ?thesis
  2533   ultimately show ?thesis
  2534     using order_antisym [OF degree_le] by blast
  2534     using order_antisym [OF degree_le] by blast
  2573 lemma pderiv_power_Suc: "pderiv (p ^ Suc n) = smult (of_nat (Suc n)) (p ^ n) * pderiv p"
  2573 lemma pderiv_power_Suc: "pderiv (p ^ Suc n) = smult (of_nat (Suc n)) (p ^ n) * pderiv p"
  2574 proof (induction n)
  2574 proof (induction n)
  2575   case (Suc n)
  2575   case (Suc n)
  2576   then show ?case
  2576   then show ?case
  2577     by (simp add: pderiv_mult smult_add_left algebra_simps)
  2577     by (simp add: pderiv_mult smult_add_left algebra_simps)
  2578 qed auto 
  2578 qed auto
  2579 
  2579 
  2580 lemma pderiv_pcompose: "pderiv (pcompose p q) = pcompose (pderiv p) q * pderiv q"
  2580 lemma pderiv_pcompose: "pderiv (pcompose p q) = pcompose (pderiv p) q * pderiv q"
  2581   by (induction p rule: pCons_induct)
  2581   by (induction p rule: pCons_induct)
  2582      (auto simp: pcompose_pCons pderiv_add pderiv_mult pderiv_pCons pcompose_add algebra_simps)
  2582      (auto simp: pcompose_pCons pderiv_add pderiv_mult pderiv_pCons pcompose_add algebra_simps)
  2583 
  2583 
  2608   by (rule DERIV_cong, rule DERIV_add) auto
  2608   by (rule DERIV_cong, rule DERIV_add) auto
  2609 
  2609 
  2610 lemma poly_DERIV [simp]: "DERIV (\<lambda>x. poly p x) x :> poly (pderiv p) x"
  2610 lemma poly_DERIV [simp]: "DERIV (\<lambda>x. poly p x) x :> poly (pderiv p) x"
  2611   by (induct p) (auto intro!: derivative_eq_intros simp add: pderiv_pCons)
  2611   by (induct p) (auto intro!: derivative_eq_intros simp add: pderiv_pCons)
  2612 
  2612 
  2613 lemma poly_isCont[simp]: 
  2613 lemma poly_isCont[simp]:
  2614   fixes x::"'a::real_normed_field"
  2614   fixes x::"'a::real_normed_field"
  2615   shows "isCont (\<lambda>x. poly p x) x"
  2615   shows "isCont (\<lambda>x. poly p x) x"
  2616 by (rule poly_DERIV [THEN DERIV_isCont])
  2616 by (rule poly_DERIV [THEN DERIV_isCont])
  2617 
  2617 
  2618 lemma tendsto_poly [tendsto_intros]: "(f \<longlongrightarrow> a) F \<Longrightarrow> ((\<lambda>x. poly p (f x)) \<longlongrightarrow> poly p a) F"
  2618 lemma tendsto_poly [tendsto_intros]: "(f \<longlongrightarrow> a) F \<Longrightarrow> ((\<lambda>x. poly p (f x)) \<longlongrightarrow> poly p a) F"
  2619   for f :: "_ \<Rightarrow> 'a::real_normed_field"  
  2619   for f :: "_ \<Rightarrow> 'a::real_normed_field"
  2620   by (rule isCont_tendsto_compose [OF poly_isCont])
  2620   by (rule isCont_tendsto_compose [OF poly_isCont])
  2621 
  2621 
  2622 lemma continuous_within_poly: "continuous (at z within s) (poly p)"
  2622 lemma continuous_within_poly: "continuous (at z within s) (poly p)"
  2623   for z :: "'a::{real_normed_field}"
  2623   for z :: "'a::{real_normed_field}"
  2624   by (simp add: continuous_within tendsto_poly)  
  2624   by (simp add: continuous_within tendsto_poly)
  2625     
  2625 
  2626 lemma continuous_poly [continuous_intros]: "continuous F f \<Longrightarrow> continuous F (\<lambda>x. poly p (f x))"
  2626 lemma continuous_poly [continuous_intros]: "continuous F f \<Longrightarrow> continuous F (\<lambda>x. poly p (f x))"
  2627   for f :: "_ \<Rightarrow> 'a::real_normed_field"
  2627   for f :: "_ \<Rightarrow> 'a::real_normed_field"
  2628   unfolding continuous_def by (rule tendsto_poly)
  2628   unfolding continuous_def by (rule tendsto_poly)
  2629       
  2629 
  2630 lemma continuous_on_poly [continuous_intros]:
  2630 lemma continuous_on_poly [continuous_intros]:
  2631   fixes p :: "'a :: {real_normed_field} poly"
  2631   fixes p :: "'a :: {real_normed_field} poly"
  2632   assumes "continuous_on A f"
  2632   assumes "continuous_on A f"
  2633   shows "continuous_on A (\<lambda>x. poly p (f x))"
  2633   shows "continuous_on A (\<lambda>x. poly p (f x))"
  2634   by (metis DERIV_continuous_on assms continuous_on_compose2 poly_DERIV subset_UNIV)
  2634   by (metis DERIV_continuous_on assms continuous_on_compose2 poly_DERIV subset_UNIV)
  3080   show "poly (reflect_poly p) (inverse x) = 0"
  3080   show "poly (reflect_poly p) (inverse x) = 0"
  3081     using assms by (simp add: poly_reflect_poly_nz)
  3081     using assms by (simp add: poly_reflect_poly_nz)
  3082 qed (use assms in \<open>auto simp: coeff_reflect_poly\<close>)
  3082 qed (use assms in \<open>auto simp: coeff_reflect_poly\<close>)
  3083 
  3083 
  3084 lemma algebraic_int_root:
  3084 lemma algebraic_int_root:
  3085   assumes "algebraic_int y" 
  3085   assumes "algebraic_int y"
  3086       and "poly p x = y" and "\<forall>i. coeff p i \<in> \<int>" and "lead_coeff p = 1" and "degree p > 0"
  3086       and "poly p x = y" and "\<forall>i. coeff p i \<in> \<int>" and "lead_coeff p = 1" and "degree p > 0"
  3087   shows   "algebraic_int x"
  3087   shows   "algebraic_int x"
  3088 proof -
  3088 proof -
  3089   from assms obtain q where q: "poly q y = 0" "\<forall>i. coeff q i \<in> \<int>" "lead_coeff q = 1"
  3089   from assms obtain q where q: "poly q y = 0" "\<forall>i. coeff q i \<in> \<int>" "lead_coeff q = 1"
  3090     by (auto simp: algebraic_int.simps)
  3090     by (auto simp: algebraic_int.simps)
  3733   fix p :: "'a poly"
  3733   fix p :: "'a poly"
  3734   assume "p \<noteq> 0"
  3734   assume "p \<noteq> 0"
  3735   then show "is_unit (unit_factor p)"
  3735   then show "is_unit (unit_factor p)"
  3736     by (simp add: unit_factor_poly_def monom_0 is_unit_poly_iff unit_factor_is_unit)
  3736     by (simp add: unit_factor_poly_def monom_0 is_unit_poly_iff unit_factor_is_unit)
  3737 next
  3737 next
  3738   fix a b :: "'a poly" assume "is_unit a" 
  3738   fix a b :: "'a poly" assume "is_unit a"
  3739   thus "unit_factor (a * b) = a * unit_factor b"
  3739   thus "unit_factor (a * b) = a * unit_factor b"
  3740     by (auto simp: unit_factor_poly_def lead_coeff_mult unit_factor_mult elim!: is_unit_polyE)
  3740     by (auto simp: unit_factor_poly_def lead_coeff_mult unit_factor_mult elim!: is_unit_polyE)
  3741 qed (simp_all add: normalize_poly_def unit_factor_poly_def monom_0 lead_coeff_mult unit_factor_mult)
  3741 qed (simp_all add: normalize_poly_def unit_factor_poly_def monom_0 lead_coeff_mult unit_factor_mult)
  3742 
  3742 
  3743 end
  3743 end
  3744 
  3744 
  3745 instance poly :: ("{semidom_divide_unit_factor,idom_divide,normalization_semidom_multiplicative}") 
  3745 instance poly :: ("{semidom_divide_unit_factor,idom_divide,normalization_semidom_multiplicative}")
  3746   normalization_semidom_multiplicative
  3746   normalization_semidom_multiplicative
  3747   by intro_classes (auto simp: unit_factor_poly_def lead_coeff_mult unit_factor_mult)
  3747   by intro_classes (auto simp: unit_factor_poly_def lead_coeff_mult unit_factor_mult)
  3748 
  3748 
  3749 lemma normalize_poly_eq_map_poly: "normalize p = map_poly (\<lambda>x. x div unit_factor (lead_coeff p)) p"
  3749 lemma normalize_poly_eq_map_poly: "normalize p = map_poly (\<lambda>x. x div unit_factor (lead_coeff p)) p"
  3750 proof -
  3750 proof -
  3847   case False
  3847   case False
  3848   show ?thesis
  3848   show ?thesis
  3849   proof (induction x)
  3849   proof (induction x)
  3850     case 0
  3850     case 0
  3851     then show ?case
  3851     then show ?case
  3852       using eucl_rel_poly_0 by blast 
  3852       using eucl_rel_poly_0 by blast
  3853   next
  3853   next
  3854     case (pCons a x)
  3854     case (pCons a x)
  3855     then show ?case
  3855     then show ?case
  3856       using False eucl_rel_poly_pCons by blast
  3856       using False eucl_rel_poly_pCons by blast
  3857   qed
  3857   qed
  4335   moreover have "pseudo_divmod_main_list
  4335   moreover have "pseudo_divmod_main_list
  4336     (hd (rev (coeffs g))) []
  4336     (hd (rev (coeffs g))) []
  4337     (rev (coeffs f)) (rev (coeffs g))
  4337     (rev (coeffs f)) (rev (coeffs g))
  4338     (1 + length (coeffs f) -
  4338     (1 + length (coeffs f) -
  4339     length (coeffs g)) = (q, r)"
  4339     length (coeffs g)) = (q, r)"
  4340     using qr hd_rev [OF \<open>coeffs g \<noteq> []\<close>] by simp
  4340     by (metis hd_rev qr rev.simps(1) rev_swap)
  4341   ultimately show ?thesis
  4341   ultimately show ?thesis
  4342     by (auto simp: degree_eq_length_coeffs pseudo_divmod_def pseudo_divmod_list_def Let_def)
  4342     by (simp add: degree_eq_length_coeffs pseudo_divmod_def pseudo_divmod_list_def)
  4343 next
  4343 next
  4344   case True
  4344   case True
  4345   then show ?thesis
  4345   then show ?thesis
  4346     by (auto simp add: pseudo_divmod_def pseudo_divmod_list_def)
  4346     by (auto simp add: pseudo_divmod_def pseudo_divmod_list_def)
  4347 qed
  4347 qed
  4870   case False
  4870   case False
  4871   then have "p = smult (content p) (primitive_part p)" "content (primitive_part p) = 1"
  4871   then have "p = smult (content p) (primitive_part p)" "content (primitive_part p) = 1"
  4872     by simp_all
  4872     by simp_all
  4873   then show ?thesis ..
  4873   then show ?thesis ..
  4874 qed
  4874 qed
  4875   
  4875 
  4876 lemma content_dvd_contentI [intro]: "p dvd q \<Longrightarrow> content p dvd content q"
  4876 lemma content_dvd_contentI [intro]: "p dvd q \<Longrightarrow> content p dvd content q"
  4877   using const_poly_dvd_iff_dvd_content content_dvd dvd_trans by blast
  4877   using const_poly_dvd_iff_dvd_content content_dvd dvd_trans by blast
  4878 
  4878 
  4879 lemma primitive_part_const_poly [simp]: "primitive_part [:x:] = [:unit_factor x:]"
  4879 lemma primitive_part_const_poly [simp]: "primitive_part [:x:] = [:unit_factor x:]"
  4880   by (simp add: primitive_part_def map_poly_pCons)
  4880   by (simp add: primitive_part_def map_poly_pCons)
  4982 proof -
  4982 proof -
  4983   have "smult a p = [:a:] * p" by simp
  4983   have "smult a p = [:a:] * p" by simp
  4984   also have "primitive_part \<dots> = smult (unit_factor a) (primitive_part p)"
  4984   also have "primitive_part \<dots> = smult (unit_factor a) (primitive_part p)"
  4985     by (subst primitive_part_mult) simp_all
  4985     by (subst primitive_part_mult) simp_all
  4986   finally show ?thesis .
  4986   finally show ?thesis .
  4987 qed  
  4987 qed
  4988 
  4988 
  4989 lemma primitive_part_dvd_primitive_partI [intro]:
  4989 lemma primitive_part_dvd_primitive_partI [intro]:
  4990   fixes p q :: "'a :: {factorial_semiring, semiring_Gcd, ring_gcd, idom_divide,
  4990   fixes p q :: "'a :: {factorial_semiring, semiring_Gcd, ring_gcd, idom_divide,
  4991                        normalization_semidom_multiplicative} poly"
  4991                        normalization_semidom_multiplicative} poly"
  4992   shows "p dvd q \<Longrightarrow> primitive_part p dvd primitive_part q"
  4992   shows "p dvd q \<Longrightarrow> primitive_part p dvd primitive_part q"
  4993   by (auto elim!: dvdE simp: primitive_part_mult)
  4993   by (auto elim!: dvdE simp: primitive_part_mult)
  4994 
  4994 
  4995 lemma content_prod_mset: 
  4995 lemma content_prod_mset:
  4996   fixes A :: "'a :: {factorial_semiring, semiring_Gcd, normalization_semidom_multiplicative}
  4996   fixes A :: "'a :: {factorial_semiring, semiring_Gcd, normalization_semidom_multiplicative}
  4997       poly multiset"
  4997       poly multiset"
  4998   shows "content (prod_mset A) = prod_mset (image_mset content A)"
  4998   shows "content (prod_mset A) = prod_mset (image_mset content A)"
  4999   by (induction A) (simp_all add: content_mult mult_ac)
  4999   by (induction A) (simp_all add: content_mult mult_ac)
  5000 
  5000 
  5001 lemma content_prod_eq_1_iff: 
  5001 lemma content_prod_eq_1_iff:
  5002   fixes p q :: "'a :: {factorial_semiring, semiring_Gcd, normalization_semidom_multiplicative} poly"
  5002   fixes p q :: "'a :: {factorial_semiring, semiring_Gcd, normalization_semidom_multiplicative} poly"
  5003   shows "content (p * q) = 1 \<longleftrightarrow> content p = 1 \<and> content q = 1"
  5003   shows "content (p * q) = 1 \<longleftrightarrow> content p = 1 \<and> content q = 1"
  5004 proof safe
  5004 proof safe
  5005   assume A: "content (p * q) = 1"
  5005   assume A: "content (p * q) = 1"
  5006   {
  5006   {
  5007     fix p q :: "'a poly" assume "content p * content q = 1"
  5007     fix p q :: "'a poly" assume "content p * content q = 1"
  5008     hence "1 = content p * content q" by simp
  5008     hence "1 = content p * content q" by simp
  5009     hence "content p dvd 1" by (rule dvdI)
  5009     hence "content p dvd 1" by (rule dvdI)
  5010     hence "content p = 1" by simp
  5010     hence "content p = 1" by simp
  5011   } note B = this
  5011   } note B = this
  5012   from A B[of p q] B [of q p] show "content p = 1" "content q = 1" 
  5012   from A B[of p q] B [of q p] show "content p = 1" "content q = 1"
  5013     by (simp_all add: content_mult mult_ac)
  5013     by (simp_all add: content_mult mult_ac)
  5014 qed (auto simp: content_mult)
  5014 qed (auto simp: content_mult)
  5015 
  5015 
  5016 
  5016 
  5017 no_notation cCons (infixr "##" 65)
  5017 no_notation cCons (infixr "##" 65)