src/HOL/Polynomial.thy
changeset 29537 50345a0f9df8
parent 29480 4e08ee896e81
child 29539 abfe2af6883e
equal deleted inserted replaced
29536:2de73447d47c 29537:50345a0f9df8
   645 
   645 
   646 
   646 
   647 subsection {* Long division of polynomials *}
   647 subsection {* Long division of polynomials *}
   648 
   648 
   649 definition
   649 definition
   650   divmod_poly_rel :: "'a::field poly \<Rightarrow> 'a poly \<Rightarrow> 'a poly \<Rightarrow> 'a poly \<Rightarrow> bool"
   650   pdivmod_rel :: "'a::field poly \<Rightarrow> 'a poly \<Rightarrow> 'a poly \<Rightarrow> 'a poly \<Rightarrow> bool"
   651 where
   651 where
   652   [code del]:
   652   [code del]:
   653   "divmod_poly_rel x y q r \<longleftrightarrow>
   653   "pdivmod_rel x y q r \<longleftrightarrow>
   654     x = q * y + r \<and> (if y = 0 then q = 0 else r = 0 \<or> degree r < degree y)"
   654     x = q * y + r \<and> (if y = 0 then q = 0 else r = 0 \<or> degree r < degree y)"
   655 
   655 
   656 lemma divmod_poly_rel_0:
   656 lemma pdivmod_rel_0:
   657   "divmod_poly_rel 0 y 0 0"
   657   "pdivmod_rel 0 y 0 0"
   658   unfolding divmod_poly_rel_def by simp
   658   unfolding pdivmod_rel_def by simp
   659 
   659 
   660 lemma divmod_poly_rel_by_0:
   660 lemma pdivmod_rel_by_0:
   661   "divmod_poly_rel x 0 0 x"
   661   "pdivmod_rel x 0 0 x"
   662   unfolding divmod_poly_rel_def by simp
   662   unfolding pdivmod_rel_def by simp
   663 
   663 
   664 lemma eq_zero_or_degree_less:
   664 lemma eq_zero_or_degree_less:
   665   assumes "degree p \<le> n" and "coeff p n = 0"
   665   assumes "degree p \<le> n" and "coeff p n = 0"
   666   shows "p = 0 \<or> degree p < n"
   666   shows "p = 0 \<or> degree p < n"
   667 proof (cases n)
   667 proof (cases n)
   683   then have "degree p < n"
   683   then have "degree p < n"
   684     using `n = Suc m` by (simp add: less_Suc_eq_le)
   684     using `n = Suc m` by (simp add: less_Suc_eq_le)
   685   then show ?thesis ..
   685   then show ?thesis ..
   686 qed
   686 qed
   687 
   687 
   688 lemma divmod_poly_rel_pCons:
   688 lemma pdivmod_rel_pCons:
   689   assumes rel: "divmod_poly_rel x y q r"
   689   assumes rel: "pdivmod_rel x y q r"
   690   assumes y: "y \<noteq> 0"
   690   assumes y: "y \<noteq> 0"
   691   assumes b: "b = coeff (pCons a r) (degree y) / coeff y (degree y)"
   691   assumes b: "b = coeff (pCons a r) (degree y) / coeff y (degree y)"
   692   shows "divmod_poly_rel (pCons a x) y (pCons b q) (pCons a r - smult b y)"
   692   shows "pdivmod_rel (pCons a x) y (pCons b q) (pCons a r - smult b y)"
   693     (is "divmod_poly_rel ?x y ?q ?r")
   693     (is "pdivmod_rel ?x y ?q ?r")
   694 proof -
   694 proof -
   695   have x: "x = q * y + r" and r: "r = 0 \<or> degree r < degree y"
   695   have x: "x = q * y + r" and r: "r = 0 \<or> degree r < degree y"
   696     using assms unfolding divmod_poly_rel_def by simp_all
   696     using assms unfolding pdivmod_rel_def by simp_all
   697 
   697 
   698   have 1: "?x = ?q * y + ?r"
   698   have 1: "?x = ?q * y + ?r"
   699     using b x by simp
   699     using b x by simp
   700 
   700 
   701   have 2: "?r = 0 \<or> degree ?r < degree y"
   701   have 2: "?r = 0 \<or> degree ?r < degree y"
   714     show "coeff ?r (degree y) = 0"
   714     show "coeff ?r (degree y) = 0"
   715       using `y \<noteq> 0` unfolding b by simp
   715       using `y \<noteq> 0` unfolding b by simp
   716   qed
   716   qed
   717 
   717 
   718   from 1 2 show ?thesis
   718   from 1 2 show ?thesis
   719     unfolding divmod_poly_rel_def
   719     unfolding pdivmod_rel_def
   720     using `y \<noteq> 0` by simp
   720     using `y \<noteq> 0` by simp
   721 qed
   721 qed
   722 
   722 
   723 lemma divmod_poly_rel_exists: "\<exists>q r. divmod_poly_rel x y q r"
   723 lemma pdivmod_rel_exists: "\<exists>q r. pdivmod_rel x y q r"
   724 apply (cases "y = 0")
   724 apply (cases "y = 0")
   725 apply (fast intro!: divmod_poly_rel_by_0)
   725 apply (fast intro!: pdivmod_rel_by_0)
   726 apply (induct x)
   726 apply (induct x)
   727 apply (fast intro!: divmod_poly_rel_0)
   727 apply (fast intro!: pdivmod_rel_0)
   728 apply (fast intro!: divmod_poly_rel_pCons)
   728 apply (fast intro!: pdivmod_rel_pCons)
   729 done
   729 done
   730 
   730 
   731 lemma divmod_poly_rel_unique:
   731 lemma pdivmod_rel_unique:
   732   assumes 1: "divmod_poly_rel x y q1 r1"
   732   assumes 1: "pdivmod_rel x y q1 r1"
   733   assumes 2: "divmod_poly_rel x y q2 r2"
   733   assumes 2: "pdivmod_rel x y q2 r2"
   734   shows "q1 = q2 \<and> r1 = r2"
   734   shows "q1 = q2 \<and> r1 = r2"
   735 proof (cases "y = 0")
   735 proof (cases "y = 0")
   736   assume "y = 0" with assms show ?thesis
   736   assume "y = 0" with assms show ?thesis
   737     by (simp add: divmod_poly_rel_def)
   737     by (simp add: pdivmod_rel_def)
   738 next
   738 next
   739   assume [simp]: "y \<noteq> 0"
   739   assume [simp]: "y \<noteq> 0"
   740   from 1 have q1: "x = q1 * y + r1" and r1: "r1 = 0 \<or> degree r1 < degree y"
   740   from 1 have q1: "x = q1 * y + r1" and r1: "r1 = 0 \<or> degree r1 < degree y"
   741     unfolding divmod_poly_rel_def by simp_all
   741     unfolding pdivmod_rel_def by simp_all
   742   from 2 have q2: "x = q2 * y + r2" and r2: "r2 = 0 \<or> degree r2 < degree y"
   742   from 2 have q2: "x = q2 * y + r2" and r2: "r2 = 0 \<or> degree r2 < degree y"
   743     unfolding divmod_poly_rel_def by simp_all
   743     unfolding pdivmod_rel_def by simp_all
   744   from q1 q2 have q3: "(q1 - q2) * y = r2 - r1"
   744   from q1 q2 have q3: "(q1 - q2) * y = r2 - r1"
   745     by (simp add: ring_simps)
   745     by (simp add: ring_simps)
   746   from r1 r2 have r3: "(r2 - r1) = 0 \<or> degree (r2 - r1) < degree y"
   746   from r1 r2 have r3: "(r2 - r1) = 0 \<or> degree (r2 - r1) < degree y"
   747     by (auto intro: degree_diff_less)
   747     by (auto intro: degree_diff_less)
   748 
   748 
   759     finally have "degree (r2 - r1) < degree (r2 - r1)" .
   759     finally have "degree (r2 - r1) < degree (r2 - r1)" .
   760     then show "False" by simp
   760     then show "False" by simp
   761   qed
   761   qed
   762 qed
   762 qed
   763 
   763 
   764 lemmas divmod_poly_rel_unique_div =
   764 lemmas pdivmod_rel_unique_div =
   765   divmod_poly_rel_unique [THEN conjunct1, standard]
   765   pdivmod_rel_unique [THEN conjunct1, standard]
   766 
   766 
   767 lemmas divmod_poly_rel_unique_mod =
   767 lemmas pdivmod_rel_unique_mod =
   768   divmod_poly_rel_unique [THEN conjunct2, standard]
   768   pdivmod_rel_unique [THEN conjunct2, standard]
   769 
   769 
   770 instantiation poly :: (field) ring_div
   770 instantiation poly :: (field) ring_div
   771 begin
   771 begin
   772 
   772 
   773 definition div_poly where
   773 definition div_poly where
   774   [code del]: "x div y = (THE q. \<exists>r. divmod_poly_rel x y q r)"
   774   [code del]: "x div y = (THE q. \<exists>r. pdivmod_rel x y q r)"
   775 
   775 
   776 definition mod_poly where
   776 definition mod_poly where
   777   [code del]: "x mod y = (THE r. \<exists>q. divmod_poly_rel x y q r)"
   777   [code del]: "x mod y = (THE r. \<exists>q. pdivmod_rel x y q r)"
   778 
   778 
   779 lemma div_poly_eq:
   779 lemma div_poly_eq:
   780   "divmod_poly_rel x y q r \<Longrightarrow> x div y = q"
   780   "pdivmod_rel x y q r \<Longrightarrow> x div y = q"
   781 unfolding div_poly_def
   781 unfolding div_poly_def
   782 by (fast elim: divmod_poly_rel_unique_div)
   782 by (fast elim: pdivmod_rel_unique_div)
   783 
   783 
   784 lemma mod_poly_eq:
   784 lemma mod_poly_eq:
   785   "divmod_poly_rel x y q r \<Longrightarrow> x mod y = r"
   785   "pdivmod_rel x y q r \<Longrightarrow> x mod y = r"
   786 unfolding mod_poly_def
   786 unfolding mod_poly_def
   787 by (fast elim: divmod_poly_rel_unique_mod)
   787 by (fast elim: pdivmod_rel_unique_mod)
   788 
   788 
   789 lemma divmod_poly_rel:
   789 lemma pdivmod_rel:
   790   "divmod_poly_rel x y (x div y) (x mod y)"
   790   "pdivmod_rel x y (x div y) (x mod y)"
   791 proof -
   791 proof -
   792   from divmod_poly_rel_exists
   792   from pdivmod_rel_exists
   793     obtain q r where "divmod_poly_rel x y q r" by fast
   793     obtain q r where "pdivmod_rel x y q r" by fast
   794   thus ?thesis
   794   thus ?thesis
   795     by (simp add: div_poly_eq mod_poly_eq)
   795     by (simp add: div_poly_eq mod_poly_eq)
   796 qed
   796 qed
   797 
   797 
   798 instance proof
   798 instance proof
   799   fix x y :: "'a poly"
   799   fix x y :: "'a poly"
   800   show "x div y * y + x mod y = x"
   800   show "x div y * y + x mod y = x"
   801     using divmod_poly_rel [of x y]
   801     using pdivmod_rel [of x y]
   802     by (simp add: divmod_poly_rel_def)
   802     by (simp add: pdivmod_rel_def)
   803 next
   803 next
   804   fix x :: "'a poly"
   804   fix x :: "'a poly"
   805   have "divmod_poly_rel x 0 0 x"
   805   have "pdivmod_rel x 0 0 x"
   806     by (rule divmod_poly_rel_by_0)
   806     by (rule pdivmod_rel_by_0)
   807   thus "x div 0 = 0"
   807   thus "x div 0 = 0"
   808     by (rule div_poly_eq)
   808     by (rule div_poly_eq)
   809 next
   809 next
   810   fix y :: "'a poly"
   810   fix y :: "'a poly"
   811   have "divmod_poly_rel 0 y 0 0"
   811   have "pdivmod_rel 0 y 0 0"
   812     by (rule divmod_poly_rel_0)
   812     by (rule pdivmod_rel_0)
   813   thus "0 div y = 0"
   813   thus "0 div y = 0"
   814     by (rule div_poly_eq)
   814     by (rule div_poly_eq)
   815 next
   815 next
   816   fix x y z :: "'a poly"
   816   fix x y z :: "'a poly"
   817   assume "y \<noteq> 0"
   817   assume "y \<noteq> 0"
   818   hence "divmod_poly_rel (x + z * y) y (z + x div y) (x mod y)"
   818   hence "pdivmod_rel (x + z * y) y (z + x div y) (x mod y)"
   819     using divmod_poly_rel [of x y]
   819     using pdivmod_rel [of x y]
   820     by (simp add: divmod_poly_rel_def left_distrib)
   820     by (simp add: pdivmod_rel_def left_distrib)
   821   thus "(x + z * y) div y = z + x div y"
   821   thus "(x + z * y) div y = z + x div y"
   822     by (rule div_poly_eq)
   822     by (rule div_poly_eq)
   823 qed
   823 qed
   824 
   824 
   825 end
   825 end
   826 
   826 
   827 lemma degree_mod_less:
   827 lemma degree_mod_less:
   828   "y \<noteq> 0 \<Longrightarrow> x mod y = 0 \<or> degree (x mod y) < degree y"
   828   "y \<noteq> 0 \<Longrightarrow> x mod y = 0 \<or> degree (x mod y) < degree y"
   829   using divmod_poly_rel [of x y]
   829   using pdivmod_rel [of x y]
   830   unfolding divmod_poly_rel_def by simp
   830   unfolding pdivmod_rel_def by simp
   831 
   831 
   832 lemma div_poly_less: "degree x < degree y \<Longrightarrow> x div y = 0"
   832 lemma div_poly_less: "degree x < degree y \<Longrightarrow> x div y = 0"
   833 proof -
   833 proof -
   834   assume "degree x < degree y"
   834   assume "degree x < degree y"
   835   hence "divmod_poly_rel x y 0 x"
   835   hence "pdivmod_rel x y 0 x"
   836     by (simp add: divmod_poly_rel_def)
   836     by (simp add: pdivmod_rel_def)
   837   thus "x div y = 0" by (rule div_poly_eq)
   837   thus "x div y = 0" by (rule div_poly_eq)
   838 qed
   838 qed
   839 
   839 
   840 lemma mod_poly_less: "degree x < degree y \<Longrightarrow> x mod y = x"
   840 lemma mod_poly_less: "degree x < degree y \<Longrightarrow> x mod y = x"
   841 proof -
   841 proof -
   842   assume "degree x < degree y"
   842   assume "degree x < degree y"
   843   hence "divmod_poly_rel x y 0 x"
   843   hence "pdivmod_rel x y 0 x"
   844     by (simp add: divmod_poly_rel_def)
   844     by (simp add: pdivmod_rel_def)
   845   thus "x mod y = x" by (rule mod_poly_eq)
   845   thus "x mod y = x" by (rule mod_poly_eq)
   846 qed
   846 qed
   847 
   847 
   848 lemma mod_pCons:
   848 lemma mod_pCons:
   849   fixes a and x
   849   fixes a and x
   850   assumes y: "y \<noteq> 0"
   850   assumes y: "y \<noteq> 0"
   851   defines b: "b \<equiv> coeff (pCons a (x mod y)) (degree y) / coeff y (degree y)"
   851   defines b: "b \<equiv> coeff (pCons a (x mod y)) (degree y) / coeff y (degree y)"
   852   shows "(pCons a x) mod y = (pCons a (x mod y) - smult b y)"
   852   shows "(pCons a x) mod y = (pCons a (x mod y) - smult b y)"
   853 unfolding b
   853 unfolding b
   854 apply (rule mod_poly_eq)
   854 apply (rule mod_poly_eq)
   855 apply (rule divmod_poly_rel_pCons [OF divmod_poly_rel y refl])
   855 apply (rule pdivmod_rel_pCons [OF pdivmod_rel y refl])
   856 done
   856 done
   857 
   857 
   858 
   858 
   859 subsection {* Evaluation of polynomials *}
   859 subsection {* Evaluation of polynomials *}
   860 
   860 
  1085   synthetic_divmod_0 synthetic_divmod_pCons
  1085   synthetic_divmod_0 synthetic_divmod_pCons
  1086 
  1086 
  1087 text {* code generator setup for div and mod *}
  1087 text {* code generator setup for div and mod *}
  1088 
  1088 
  1089 definition
  1089 definition
  1090   divmod_poly :: "'a::field poly \<Rightarrow> 'a poly \<Rightarrow> 'a poly \<times> 'a poly"
  1090   pdivmod :: "'a::field poly \<Rightarrow> 'a poly \<Rightarrow> 'a poly \<times> 'a poly"
  1091 where
  1091 where
  1092   [code del]: "divmod_poly x y = (x div y, x mod y)"
  1092   [code del]: "pdivmod x y = (x div y, x mod y)"
  1093 
  1093 
  1094 lemma div_poly_code [code]: "x div y = fst (divmod_poly x y)"
  1094 lemma div_poly_code [code]: "x div y = fst (pdivmod x y)"
  1095   unfolding divmod_poly_def by simp
  1095   unfolding pdivmod_def by simp
  1096 
  1096 
  1097 lemma mod_poly_code [code]: "x mod y = snd (divmod_poly x y)"
  1097 lemma mod_poly_code [code]: "x mod y = snd (pdivmod x y)"
  1098   unfolding divmod_poly_def by simp
  1098   unfolding pdivmod_def by simp
  1099 
  1099 
  1100 lemma divmod_poly_0 [code]: "divmod_poly 0 y = (0, 0)"
  1100 lemma pdivmod_0 [code]: "pdivmod 0 y = (0, 0)"
  1101   unfolding divmod_poly_def by simp
  1101   unfolding pdivmod_def by simp
  1102 
  1102 
  1103 lemma divmod_poly_pCons [code]:
  1103 lemma pdivmod_pCons [code]:
  1104   "divmod_poly (pCons a x) y =
  1104   "pdivmod (pCons a x) y =
  1105     (if y = 0 then (0, pCons a x) else
  1105     (if y = 0 then (0, pCons a x) else
  1106       (let (q, r) = divmod_poly x y;
  1106       (let (q, r) = pdivmod x y;
  1107            b = coeff (pCons a r) (degree y) / coeff y (degree y)
  1107            b = coeff (pCons a r) (degree y) / coeff y (degree y)
  1108         in (pCons b q, pCons a r - smult b y)))"
  1108         in (pCons b q, pCons a r - smult b y)))"
  1109 apply (simp add: divmod_poly_def Let_def, safe)
  1109 apply (simp add: pdivmod_def Let_def, safe)
  1110 apply (rule div_poly_eq)
  1110 apply (rule div_poly_eq)
  1111 apply (erule divmod_poly_rel_pCons [OF divmod_poly_rel _ refl])
  1111 apply (erule pdivmod_rel_pCons [OF pdivmod_rel _ refl])
  1112 apply (rule mod_poly_eq)
  1112 apply (rule mod_poly_eq)
  1113 apply (erule divmod_poly_rel_pCons [OF divmod_poly_rel _ refl])
  1113 apply (erule pdivmod_rel_pCons [OF pdivmod_rel _ refl])
  1114 done
  1114 done
  1115 
  1115 
  1116 end
  1116 end