src/HOL/Library/Polynomial.thy
changeset 64635 255741c5f862
parent 64592 7759f1766189
child 64793 3df00fb1ce0b
equal deleted inserted replaced
64634:5bd30359e46e 64635:255741c5f862
  1611   by (auto simp add: poly_eq_poly_eq_iff [symmetric])
  1611   by (auto simp add: poly_eq_poly_eq_iff [symmetric])
  1612 
  1612 
  1613 
  1613 
  1614 subsection \<open>Long division of polynomials\<close>
  1614 subsection \<open>Long division of polynomials\<close>
  1615 
  1615 
  1616 definition pdivmod_rel :: "'a::field poly \<Rightarrow> 'a poly \<Rightarrow> 'a poly \<Rightarrow> 'a poly \<Rightarrow> bool"
  1616 inductive eucl_rel_poly :: "'a::field poly \<Rightarrow> 'a poly \<Rightarrow> 'a poly \<times> 'a poly \<Rightarrow> bool"
  1617 where
  1617   where eucl_rel_poly_by0: "eucl_rel_poly x 0 (0, x)"
  1618   "pdivmod_rel x y q r \<longleftrightarrow>
  1618   | eucl_rel_poly_dividesI: "y \<noteq> 0 \<Longrightarrow> x = q * y \<Longrightarrow> eucl_rel_poly x y (q, 0)"
  1619     x = q * y + r \<and> (if y = 0 then q = 0 else r = 0 \<or> degree r < degree y)"
  1619   | eucl_rel_poly_remainderI: "y \<noteq> 0 \<Longrightarrow> degree r < degree y
  1620 
  1620       \<Longrightarrow> x = q * y + r \<Longrightarrow> eucl_rel_poly x y (q, r)"
  1621 lemma pdivmod_rel_0:
  1621   
  1622   "pdivmod_rel 0 y 0 0"
  1622 lemma eucl_rel_poly_iff:
  1623   unfolding pdivmod_rel_def by simp
  1623   "eucl_rel_poly x y (q, r) \<longleftrightarrow>
  1624 
  1624     x = q * y + r \<and>
  1625 lemma pdivmod_rel_by_0:
  1625       (if y = 0 then q = 0 else r = 0 \<or> degree r < degree y)"
  1626   "pdivmod_rel x 0 0 x"
  1626   by (auto elim: eucl_rel_poly.cases
  1627   unfolding pdivmod_rel_def by simp
  1627     intro: eucl_rel_poly_by0 eucl_rel_poly_dividesI eucl_rel_poly_remainderI)
       
  1628   
       
  1629 lemma eucl_rel_poly_0:
       
  1630   "eucl_rel_poly 0 y (0, 0)"
       
  1631   unfolding eucl_rel_poly_iff by simp
       
  1632 
       
  1633 lemma eucl_rel_poly_by_0:
       
  1634   "eucl_rel_poly x 0 (0, x)"
       
  1635   unfolding eucl_rel_poly_iff by simp
  1628 
  1636 
  1629 lemma eq_zero_or_degree_less:
  1637 lemma eq_zero_or_degree_less:
  1630   assumes "degree p \<le> n" and "coeff p n = 0"
  1638   assumes "degree p \<le> n" and "coeff p n = 0"
  1631   shows "p = 0 \<or> degree p < n"
  1639   shows "p = 0 \<or> degree p < n"
  1632 proof (cases n)
  1640 proof (cases n)
  1648   then have "degree p < n"
  1656   then have "degree p < n"
  1649     using \<open>n = Suc m\<close> by (simp add: less_Suc_eq_le)
  1657     using \<open>n = Suc m\<close> by (simp add: less_Suc_eq_le)
  1650   then show ?thesis ..
  1658   then show ?thesis ..
  1651 qed
  1659 qed
  1652 
  1660 
  1653 lemma pdivmod_rel_pCons:
  1661 lemma eucl_rel_poly_pCons:
  1654   assumes rel: "pdivmod_rel x y q r"
  1662   assumes rel: "eucl_rel_poly x y (q, r)"
  1655   assumes y: "y \<noteq> 0"
  1663   assumes y: "y \<noteq> 0"
  1656   assumes b: "b = coeff (pCons a r) (degree y) / coeff y (degree y)"
  1664   assumes b: "b = coeff (pCons a r) (degree y) / coeff y (degree y)"
  1657   shows "pdivmod_rel (pCons a x) y (pCons b q) (pCons a r - smult b y)"
  1665   shows "eucl_rel_poly (pCons a x) y (pCons b q, pCons a r - smult b y)"
  1658     (is "pdivmod_rel ?x y ?q ?r")
  1666     (is "eucl_rel_poly ?x y (?q, ?r)")
  1659 proof -
  1667 proof -
  1660   have x: "x = q * y + r" and r: "r = 0 \<or> degree r < degree y"
  1668   have x: "x = q * y + r" and r: "r = 0 \<or> degree r < degree y"
  1661     using assms unfolding pdivmod_rel_def by simp_all
  1669     using assms unfolding eucl_rel_poly_iff by simp_all
  1662 
  1670 
  1663   have 1: "?x = ?q * y + ?r"
  1671   have 1: "?x = ?q * y + ?r"
  1664     using b x by simp
  1672     using b x by simp
  1665 
  1673 
  1666   have 2: "?r = 0 \<or> degree ?r < degree y"
  1674   have 2: "?r = 0 \<or> degree ?r < degree y"
  1676     show "coeff ?r (degree y) = 0"
  1684     show "coeff ?r (degree y) = 0"
  1677       using \<open>y \<noteq> 0\<close> unfolding b by simp
  1685       using \<open>y \<noteq> 0\<close> unfolding b by simp
  1678   qed
  1686   qed
  1679 
  1687 
  1680   from 1 2 show ?thesis
  1688   from 1 2 show ?thesis
  1681     unfolding pdivmod_rel_def
  1689     unfolding eucl_rel_poly_iff
  1682     using \<open>y \<noteq> 0\<close> by simp
  1690     using \<open>y \<noteq> 0\<close> by simp
  1683 qed
  1691 qed
  1684 
  1692 
  1685 lemma pdivmod_rel_exists: "\<exists>q r. pdivmod_rel x y q r"
  1693 lemma eucl_rel_poly_exists: "\<exists>q r. eucl_rel_poly x y (q, r)"
  1686 apply (cases "y = 0")
  1694 apply (cases "y = 0")
  1687 apply (fast intro!: pdivmod_rel_by_0)
  1695 apply (fast intro!: eucl_rel_poly_by_0)
  1688 apply (induct x)
  1696 apply (induct x)
  1689 apply (fast intro!: pdivmod_rel_0)
  1697 apply (fast intro!: eucl_rel_poly_0)
  1690 apply (fast intro!: pdivmod_rel_pCons)
  1698 apply (fast intro!: eucl_rel_poly_pCons)
  1691 done
  1699 done
  1692 
  1700 
  1693 lemma pdivmod_rel_unique:
  1701 lemma eucl_rel_poly_unique:
  1694   assumes 1: "pdivmod_rel x y q1 r1"
  1702   assumes 1: "eucl_rel_poly x y (q1, r1)"
  1695   assumes 2: "pdivmod_rel x y q2 r2"
  1703   assumes 2: "eucl_rel_poly x y (q2, r2)"
  1696   shows "q1 = q2 \<and> r1 = r2"
  1704   shows "q1 = q2 \<and> r1 = r2"
  1697 proof (cases "y = 0")
  1705 proof (cases "y = 0")
  1698   assume "y = 0" with assms show ?thesis
  1706   assume "y = 0" with assms show ?thesis
  1699     by (simp add: pdivmod_rel_def)
  1707     by (simp add: eucl_rel_poly_iff)
  1700 next
  1708 next
  1701   assume [simp]: "y \<noteq> 0"
  1709   assume [simp]: "y \<noteq> 0"
  1702   from 1 have q1: "x = q1 * y + r1" and r1: "r1 = 0 \<or> degree r1 < degree y"
  1710   from 1 have q1: "x = q1 * y + r1" and r1: "r1 = 0 \<or> degree r1 < degree y"
  1703     unfolding pdivmod_rel_def by simp_all
  1711     unfolding eucl_rel_poly_iff by simp_all
  1704   from 2 have q2: "x = q2 * y + r2" and r2: "r2 = 0 \<or> degree r2 < degree y"
  1712   from 2 have q2: "x = q2 * y + r2" and r2: "r2 = 0 \<or> degree r2 < degree y"
  1705     unfolding pdivmod_rel_def by simp_all
  1713     unfolding eucl_rel_poly_iff by simp_all
  1706   from q1 q2 have q3: "(q1 - q2) * y = r2 - r1"
  1714   from q1 q2 have q3: "(q1 - q2) * y = r2 - r1"
  1707     by (simp add: algebra_simps)
  1715     by (simp add: algebra_simps)
  1708   from r1 r2 have r3: "(r2 - r1) = 0 \<or> degree (r2 - r1) < degree y"
  1716   from r1 r2 have r3: "(r2 - r1) = 0 \<or> degree (r2 - r1) < degree y"
  1709     by (auto intro: degree_diff_less)
  1717     by (auto intro: degree_diff_less)
  1710 
  1718 
  1721     finally have "degree (r2 - r1) < degree (r2 - r1)" .
  1729     finally have "degree (r2 - r1) < degree (r2 - r1)" .
  1722     then show "False" by simp
  1730     then show "False" by simp
  1723   qed
  1731   qed
  1724 qed
  1732 qed
  1725 
  1733 
  1726 lemma pdivmod_rel_0_iff: "pdivmod_rel 0 y q r \<longleftrightarrow> q = 0 \<and> r = 0"
  1734 lemma eucl_rel_poly_0_iff: "eucl_rel_poly 0 y (q, r) \<longleftrightarrow> q = 0 \<and> r = 0"
  1727 by (auto dest: pdivmod_rel_unique intro: pdivmod_rel_0)
  1735 by (auto dest: eucl_rel_poly_unique intro: eucl_rel_poly_0)
  1728 
  1736 
  1729 lemma pdivmod_rel_by_0_iff: "pdivmod_rel x 0 q r \<longleftrightarrow> q = 0 \<and> r = x"
  1737 lemma eucl_rel_poly_by_0_iff: "eucl_rel_poly x 0 (q, r) \<longleftrightarrow> q = 0 \<and> r = x"
  1730 by (auto dest: pdivmod_rel_unique intro: pdivmod_rel_by_0)
  1738 by (auto dest: eucl_rel_poly_unique intro: eucl_rel_poly_by_0)
  1731 
  1739 
  1732 lemmas pdivmod_rel_unique_div = pdivmod_rel_unique [THEN conjunct1]
  1740 lemmas eucl_rel_poly_unique_div = eucl_rel_poly_unique [THEN conjunct1]
  1733 
  1741 
  1734 lemmas pdivmod_rel_unique_mod = pdivmod_rel_unique [THEN conjunct2]
  1742 lemmas eucl_rel_poly_unique_mod = eucl_rel_poly_unique [THEN conjunct2]
  1735 
  1743 
  1736 
  1744 
  1737 
  1745 
  1738 subsection \<open>Pseudo-Division and Division of Polynomials\<close>
  1746 subsection \<open>Pseudo-Division and Division of Polynomials\<close>
  1739 
  1747 
  2234 definition modulo_poly where
  2242 definition modulo_poly where
  2235   mod_poly_def: "f mod g \<equiv>
  2243   mod_poly_def: "f mod g \<equiv>
  2236     if g = 0 then f
  2244     if g = 0 then f
  2237     else pseudo_mod (smult ((1/coeff g (degree g)) ^ (Suc (degree f) - degree g)) f) g"
  2245     else pseudo_mod (smult ((1/coeff g (degree g)) ^ (Suc (degree f) - degree g)) f) g"
  2238 
  2246 
  2239 lemma pdivmod_rel: "pdivmod_rel (x::'a::field poly) y (x div y) (x mod y)"
  2247 lemma eucl_rel_poly: "eucl_rel_poly (x::'a::field poly) y (x div y, x mod y)"
  2240   unfolding pdivmod_rel_def
  2248   unfolding eucl_rel_poly_iff
  2241 proof (intro conjI)
  2249 proof (intro conjI)
  2242   show "x = x div y * y + x mod y"
  2250   show "x = x div y * y + x mod y"
  2243   proof(cases "y = 0")
  2251   proof(cases "y = 0")
  2244     case True show ?thesis by(simp add: True divide_poly_def divide_poly_0 mod_poly_def)
  2252     case True show ?thesis by(simp add: True divide_poly_def divide_poly_0 mod_poly_def)
  2245   next
  2253   next
  2259       with pseudo_mod[OF this] show ?thesis unfolding mod_poly_def by simp
  2267       with pseudo_mod[OF this] show ?thesis unfolding mod_poly_def by simp
  2260   qed
  2268   qed
  2261 qed
  2269 qed
  2262 
  2270 
  2263 lemma div_poly_eq:
  2271 lemma div_poly_eq:
  2264   "pdivmod_rel (x::'a::field poly) y q r \<Longrightarrow> x div y = q"
  2272   "eucl_rel_poly (x::'a::field poly) y (q, r) \<Longrightarrow> x div y = q"
  2265   by(rule pdivmod_rel_unique_div[OF pdivmod_rel])
  2273   by(rule eucl_rel_poly_unique_div[OF eucl_rel_poly])
  2266 
  2274 
  2267 lemma mod_poly_eq:
  2275 lemma mod_poly_eq:
  2268   "pdivmod_rel (x::'a::field poly) y q r \<Longrightarrow> x mod y = r"
  2276   "eucl_rel_poly (x::'a::field poly) y (q, r) \<Longrightarrow> x mod y = r"
  2269   by (rule pdivmod_rel_unique_mod[OF pdivmod_rel])
  2277   by (rule eucl_rel_poly_unique_mod[OF eucl_rel_poly])
  2270 
  2278 
  2271 instance
  2279 instance
  2272 proof
  2280 proof
  2273   fix x y :: "'a poly"
  2281   fix x y :: "'a poly"
  2274   from pdivmod_rel[of x y,unfolded pdivmod_rel_def]
  2282   from eucl_rel_poly[of x y,unfolded eucl_rel_poly_iff]
  2275   show "x div y * y + x mod y = x" by auto
  2283   show "x div y * y + x mod y = x" by auto
  2276 next
  2284 next
  2277   fix x y z :: "'a poly"
  2285   fix x y z :: "'a poly"
  2278   assume "y \<noteq> 0"
  2286   assume "y \<noteq> 0"
  2279   hence "pdivmod_rel (x + z * y) y (z + x div y) (x mod y)"
  2287   hence "eucl_rel_poly (x + z * y) y (z + x div y, x mod y)"
  2280     using pdivmod_rel [of x y]
  2288     using eucl_rel_poly [of x y]
  2281     by (simp add: pdivmod_rel_def distrib_right)
  2289     by (simp add: eucl_rel_poly_iff distrib_right)
  2282   thus "(x + z * y) div y = z + x div y"
  2290   thus "(x + z * y) div y = z + x div y"
  2283     by (rule div_poly_eq)
  2291     by (rule div_poly_eq)
  2284 next
  2292 next
  2285   fix x y z :: "'a poly"
  2293   fix x y z :: "'a poly"
  2286   assume "x \<noteq> 0"
  2294   assume "x \<noteq> 0"
  2287   show "(x * y) div (x * z) = y div z"
  2295   show "(x * y) div (x * z) = y div z"
  2288   proof (cases "y \<noteq> 0 \<and> z \<noteq> 0")
  2296   proof (cases "y \<noteq> 0 \<and> z \<noteq> 0")
  2289     have "\<And>x::'a poly. pdivmod_rel x 0 0 x"
  2297     have "\<And>x::'a poly. eucl_rel_poly x 0 (0, x)"
  2290       by (rule pdivmod_rel_by_0)
  2298       by (rule eucl_rel_poly_by_0)
  2291     then have [simp]: "\<And>x::'a poly. x div 0 = 0"
  2299     then have [simp]: "\<And>x::'a poly. x div 0 = 0"
  2292       by (rule div_poly_eq)
  2300       by (rule div_poly_eq)
  2293     have "\<And>x::'a poly. pdivmod_rel 0 x 0 0"
  2301     have "\<And>x::'a poly. eucl_rel_poly 0 x (0, 0)"
  2294       by (rule pdivmod_rel_0)
  2302       by (rule eucl_rel_poly_0)
  2295     then have [simp]: "\<And>x::'a poly. 0 div x = 0"
  2303     then have [simp]: "\<And>x::'a poly. 0 div x = 0"
  2296       by (rule div_poly_eq)
  2304       by (rule div_poly_eq)
  2297     case False then show ?thesis by auto
  2305     case False then show ?thesis by auto
  2298   next
  2306   next
  2299     case True then have "y \<noteq> 0" and "z \<noteq> 0" by auto
  2307     case True then have "y \<noteq> 0" and "z \<noteq> 0" by auto
  2300     with \<open>x \<noteq> 0\<close>
  2308     with \<open>x \<noteq> 0\<close>
  2301     have "\<And>q r. pdivmod_rel y z q r \<Longrightarrow> pdivmod_rel (x * y) (x * z) q (x * r)"
  2309     have "\<And>q r. eucl_rel_poly y z (q, r) \<Longrightarrow> eucl_rel_poly (x * y) (x * z) (q, x * r)"
  2302       by (auto simp add: pdivmod_rel_def algebra_simps)
  2310       by (auto simp add: eucl_rel_poly_iff algebra_simps)
  2303         (rule classical, simp add: degree_mult_eq)
  2311         (rule classical, simp add: degree_mult_eq)
  2304     moreover from pdivmod_rel have "pdivmod_rel y z (y div z) (y mod z)" .
  2312     moreover from eucl_rel_poly have "eucl_rel_poly y z (y div z, y mod z)" .
  2305     ultimately have "pdivmod_rel (x * y) (x * z) (y div z) (x * (y mod z))" .
  2313     ultimately have "eucl_rel_poly (x * y) (x * z) (y div z, x * (y mod z))" .
  2306     then show ?thesis by (simp add: div_poly_eq)
  2314     then show ?thesis by (simp add: div_poly_eq)
  2307   qed
  2315   qed
  2308 qed
  2316 qed
  2309 
  2317 
  2310 end
  2318 end
  2311 
  2319 
  2312 lemma degree_mod_less:
  2320 lemma degree_mod_less:
  2313   "y \<noteq> 0 \<Longrightarrow> x mod y = 0 \<or> degree (x mod y) < degree y"
  2321   "y \<noteq> 0 \<Longrightarrow> x mod y = 0 \<or> degree (x mod y) < degree y"
  2314   using pdivmod_rel [of x y]
  2322   using eucl_rel_poly [of x y]
  2315   unfolding pdivmod_rel_def by simp
  2323   unfolding eucl_rel_poly_iff by simp
  2316 
  2324 
  2317 lemma div_poly_less: "degree (x::'a::field poly) < degree y \<Longrightarrow> x div y = 0"
  2325 lemma div_poly_less: "degree (x::'a::field poly) < degree y \<Longrightarrow> x div y = 0"
  2318 proof -
  2326 proof -
  2319   assume "degree x < degree y"
  2327   assume "degree x < degree y"
  2320   hence "pdivmod_rel x y 0 x"
  2328   hence "eucl_rel_poly x y (0, x)"
  2321     by (simp add: pdivmod_rel_def)
  2329     by (simp add: eucl_rel_poly_iff)
  2322   thus "x div y = 0" by (rule div_poly_eq)
  2330   thus "x div y = 0" by (rule div_poly_eq)
  2323 qed
  2331 qed
  2324 
  2332 
  2325 lemma mod_poly_less: "degree x < degree y \<Longrightarrow> x mod y = x"
  2333 lemma mod_poly_less: "degree x < degree y \<Longrightarrow> x mod y = x"
  2326 proof -
  2334 proof -
  2327   assume "degree x < degree y"
  2335   assume "degree x < degree y"
  2328   hence "pdivmod_rel x y 0 x"
  2336   hence "eucl_rel_poly x y (0, x)"
  2329     by (simp add: pdivmod_rel_def)
  2337     by (simp add: eucl_rel_poly_iff)
  2330   thus "x mod y = x" by (rule mod_poly_eq)
  2338   thus "x mod y = x" by (rule mod_poly_eq)
  2331 qed
  2339 qed
  2332 
  2340 
  2333 lemma pdivmod_rel_smult_left:
  2341 lemma eucl_rel_poly_smult_left:
  2334   "pdivmod_rel x y q r
  2342   "eucl_rel_poly x y (q, r)
  2335     \<Longrightarrow> pdivmod_rel (smult a x) y (smult a q) (smult a r)"
  2343     \<Longrightarrow> eucl_rel_poly (smult a x) y (smult a q, smult a r)"
  2336   unfolding pdivmod_rel_def by (simp add: smult_add_right)
  2344   unfolding eucl_rel_poly_iff by (simp add: smult_add_right)
  2337 
  2345 
  2338 lemma div_smult_left: "(smult (a::'a::field) x) div y = smult a (x div y)"
  2346 lemma div_smult_left: "(smult (a::'a::field) x) div y = smult a (x div y)"
  2339   by (rule div_poly_eq, rule pdivmod_rel_smult_left, rule pdivmod_rel)
  2347   by (rule div_poly_eq, rule eucl_rel_poly_smult_left, rule eucl_rel_poly)
  2340 
  2348 
  2341 lemma mod_smult_left: "(smult a x) mod y = smult a (x mod y)"
  2349 lemma mod_smult_left: "(smult a x) mod y = smult a (x mod y)"
  2342   by (rule mod_poly_eq, rule pdivmod_rel_smult_left, rule pdivmod_rel)
  2350   by (rule mod_poly_eq, rule eucl_rel_poly_smult_left, rule eucl_rel_poly)
  2343 
  2351 
  2344 lemma poly_div_minus_left [simp]:
  2352 lemma poly_div_minus_left [simp]:
  2345   fixes x y :: "'a::field poly"
  2353   fixes x y :: "'a::field poly"
  2346   shows "(- x) div y = - (x div y)"
  2354   shows "(- x) div y = - (x div y)"
  2347   using div_smult_left [of "- 1::'a"] by simp
  2355   using div_smult_left [of "- 1::'a"] by simp
  2349 lemma poly_mod_minus_left [simp]:
  2357 lemma poly_mod_minus_left [simp]:
  2350   fixes x y :: "'a::field poly"
  2358   fixes x y :: "'a::field poly"
  2351   shows "(- x) mod y = - (x mod y)"
  2359   shows "(- x) mod y = - (x mod y)"
  2352   using mod_smult_left [of "- 1::'a"] by simp
  2360   using mod_smult_left [of "- 1::'a"] by simp
  2353 
  2361 
  2354 lemma pdivmod_rel_add_left:
  2362 lemma eucl_rel_poly_add_left:
  2355   assumes "pdivmod_rel x y q r"
  2363   assumes "eucl_rel_poly x y (q, r)"
  2356   assumes "pdivmod_rel x' y q' r'"
  2364   assumes "eucl_rel_poly x' y (q', r')"
  2357   shows "pdivmod_rel (x + x') y (q + q') (r + r')"
  2365   shows "eucl_rel_poly (x + x') y (q + q', r + r')"
  2358   using assms unfolding pdivmod_rel_def
  2366   using assms unfolding eucl_rel_poly_iff
  2359   by (auto simp add: algebra_simps degree_add_less)
  2367   by (auto simp add: algebra_simps degree_add_less)
  2360 
  2368 
  2361 lemma poly_div_add_left:
  2369 lemma poly_div_add_left:
  2362   fixes x y z :: "'a::field poly"
  2370   fixes x y z :: "'a::field poly"
  2363   shows "(x + y) div z = x div z + y div z"
  2371   shows "(x + y) div z = x div z + y div z"
  2364   using pdivmod_rel_add_left [OF pdivmod_rel pdivmod_rel]
  2372   using eucl_rel_poly_add_left [OF eucl_rel_poly eucl_rel_poly]
  2365   by (rule div_poly_eq)
  2373   by (rule div_poly_eq)
  2366 
  2374 
  2367 lemma poly_mod_add_left:
  2375 lemma poly_mod_add_left:
  2368   fixes x y z :: "'a::field poly"
  2376   fixes x y z :: "'a::field poly"
  2369   shows "(x + y) mod z = x mod z + y mod z"
  2377   shows "(x + y) mod z = x mod z + y mod z"
  2370   using pdivmod_rel_add_left [OF pdivmod_rel pdivmod_rel]
  2378   using eucl_rel_poly_add_left [OF eucl_rel_poly eucl_rel_poly]
  2371   by (rule mod_poly_eq)
  2379   by (rule mod_poly_eq)
  2372 
  2380 
  2373 lemma poly_div_diff_left:
  2381 lemma poly_div_diff_left:
  2374   fixes x y z :: "'a::field poly"
  2382   fixes x y z :: "'a::field poly"
  2375   shows "(x - y) div z = x div z - y div z"
  2383   shows "(x - y) div z = x div z - y div z"
  2378 lemma poly_mod_diff_left:
  2386 lemma poly_mod_diff_left:
  2379   fixes x y z :: "'a::field poly"
  2387   fixes x y z :: "'a::field poly"
  2380   shows "(x - y) mod z = x mod z - y mod z"
  2388   shows "(x - y) mod z = x mod z - y mod z"
  2381   by (simp only: diff_conv_add_uminus poly_mod_add_left poly_mod_minus_left)
  2389   by (simp only: diff_conv_add_uminus poly_mod_add_left poly_mod_minus_left)
  2382 
  2390 
  2383 lemma pdivmod_rel_smult_right:
  2391 lemma eucl_rel_poly_smult_right:
  2384   "\<lbrakk>a \<noteq> 0; pdivmod_rel x y q r\<rbrakk>
  2392   "a \<noteq> 0 \<Longrightarrow> eucl_rel_poly x y (q, r)
  2385     \<Longrightarrow> pdivmod_rel x (smult a y) (smult (inverse a) q) r"
  2393     \<Longrightarrow> eucl_rel_poly x (smult a y) (smult (inverse a) q, r)"
  2386   unfolding pdivmod_rel_def by simp
  2394   unfolding eucl_rel_poly_iff by simp
  2387 
  2395 
  2388 lemma div_smult_right:
  2396 lemma div_smult_right:
  2389   "(a::'a::field) \<noteq> 0 \<Longrightarrow> x div (smult a y) = smult (inverse a) (x div y)"
  2397   "(a::'a::field) \<noteq> 0 \<Longrightarrow> x div (smult a y) = smult (inverse a) (x div y)"
  2390   by (rule div_poly_eq, erule pdivmod_rel_smult_right, rule pdivmod_rel)
  2398   by (rule div_poly_eq, erule eucl_rel_poly_smult_right, rule eucl_rel_poly)
  2391 
  2399 
  2392 lemma mod_smult_right: "a \<noteq> 0 \<Longrightarrow> x mod (smult a y) = x mod y"
  2400 lemma mod_smult_right: "a \<noteq> 0 \<Longrightarrow> x mod (smult a y) = x mod y"
  2393   by (rule mod_poly_eq, erule pdivmod_rel_smult_right, rule pdivmod_rel)
  2401   by (rule mod_poly_eq, erule eucl_rel_poly_smult_right, rule eucl_rel_poly)
  2394 
  2402 
  2395 lemma poly_div_minus_right [simp]:
  2403 lemma poly_div_minus_right [simp]:
  2396   fixes x y :: "'a::field poly"
  2404   fixes x y :: "'a::field poly"
  2397   shows "x div (- y) = - (x div y)"
  2405   shows "x div (- y) = - (x div y)"
  2398   using div_smult_right [of "- 1::'a"] by (simp add: nonzero_inverse_minus_eq)
  2406   using div_smult_right [of "- 1::'a"] by (simp add: nonzero_inverse_minus_eq)
  2400 lemma poly_mod_minus_right [simp]:
  2408 lemma poly_mod_minus_right [simp]:
  2401   fixes x y :: "'a::field poly"
  2409   fixes x y :: "'a::field poly"
  2402   shows "x mod (- y) = x mod y"
  2410   shows "x mod (- y) = x mod y"
  2403   using mod_smult_right [of "- 1::'a"] by simp
  2411   using mod_smult_right [of "- 1::'a"] by simp
  2404 
  2412 
  2405 lemma pdivmod_rel_mult:
  2413 lemma eucl_rel_poly_mult:
  2406   "\<lbrakk>pdivmod_rel x y q r; pdivmod_rel q z q' r'\<rbrakk>
  2414   "eucl_rel_poly x y (q, r) \<Longrightarrow> eucl_rel_poly q z (q', r')
  2407     \<Longrightarrow> pdivmod_rel x (y * z) q' (y * r' + r)"
  2415     \<Longrightarrow> eucl_rel_poly x (y * z) (q', y * r' + r)"
  2408 apply (cases "z = 0", simp add: pdivmod_rel_def)
  2416 apply (cases "z = 0", simp add: eucl_rel_poly_iff)
  2409 apply (cases "y = 0", simp add: pdivmod_rel_by_0_iff pdivmod_rel_0_iff)
  2417 apply (cases "y = 0", simp add: eucl_rel_poly_by_0_iff eucl_rel_poly_0_iff)
  2410 apply (cases "r = 0")
  2418 apply (cases "r = 0")
  2411 apply (cases "r' = 0")
  2419 apply (cases "r' = 0")
  2412 apply (simp add: pdivmod_rel_def)
  2420 apply (simp add: eucl_rel_poly_iff)
  2413 apply (simp add: pdivmod_rel_def field_simps degree_mult_eq)
  2421 apply (simp add: eucl_rel_poly_iff field_simps degree_mult_eq)
  2414 apply (cases "r' = 0")
  2422 apply (cases "r' = 0")
  2415 apply (simp add: pdivmod_rel_def degree_mult_eq)
  2423 apply (simp add: eucl_rel_poly_iff degree_mult_eq)
  2416 apply (simp add: pdivmod_rel_def field_simps)
  2424 apply (simp add: eucl_rel_poly_iff field_simps)
  2417 apply (simp add: degree_mult_eq degree_add_less)
  2425 apply (simp add: degree_mult_eq degree_add_less)
  2418 done
  2426 done
  2419 
  2427 
  2420 lemma poly_div_mult_right:
  2428 lemma poly_div_mult_right:
  2421   fixes x y z :: "'a::field poly"
  2429   fixes x y z :: "'a::field poly"
  2422   shows "x div (y * z) = (x div y) div z"
  2430   shows "x div (y * z) = (x div y) div z"
  2423   by (rule div_poly_eq, rule pdivmod_rel_mult, (rule pdivmod_rel)+)
  2431   by (rule div_poly_eq, rule eucl_rel_poly_mult, (rule eucl_rel_poly)+)
  2424 
  2432 
  2425 lemma poly_mod_mult_right:
  2433 lemma poly_mod_mult_right:
  2426   fixes x y z :: "'a::field poly"
  2434   fixes x y z :: "'a::field poly"
  2427   shows "x mod (y * z) = y * (x div y mod z) + x mod y"
  2435   shows "x mod (y * z) = y * (x div y mod z) + x mod y"
  2428   by (rule mod_poly_eq, rule pdivmod_rel_mult, (rule pdivmod_rel)+)
  2436   by (rule mod_poly_eq, rule eucl_rel_poly_mult, (rule eucl_rel_poly)+)
  2429 
  2437 
  2430 lemma mod_pCons:
  2438 lemma mod_pCons:
  2431   fixes a and x
  2439   fixes a and x
  2432   assumes y: "y \<noteq> 0"
  2440   assumes y: "y \<noteq> 0"
  2433   defines b: "b \<equiv> coeff (pCons a (x mod y)) (degree y) / coeff y (degree y)"
  2441   defines b: "b \<equiv> coeff (pCons a (x mod y)) (degree y) / coeff y (degree y)"
  2434   shows "(pCons a x) mod y = (pCons a (x mod y) - smult b y)"
  2442   shows "(pCons a x) mod y = (pCons a (x mod y) - smult b y)"
  2435 unfolding b
  2443 unfolding b
  2436 apply (rule mod_poly_eq)
  2444 apply (rule mod_poly_eq)
  2437 apply (rule pdivmod_rel_pCons [OF pdivmod_rel y refl])
  2445 apply (rule eucl_rel_poly_pCons [OF eucl_rel_poly y refl])
  2438 done
  2446 done
  2439 
  2447 
  2440 definition pdivmod :: "'a::field poly \<Rightarrow> 'a poly \<Rightarrow> 'a poly \<times> 'a poly"
  2448 definition pdivmod :: "'a::field poly \<Rightarrow> 'a poly \<Rightarrow> 'a poly \<times> 'a poly"
  2441 where
  2449 where
  2442   "pdivmod p q = (p div q, p mod q)"
  2450   "pdivmod p q = (p div q, p mod q)"
  2451       (let (s, r) = pdivmod p q;
  2459       (let (s, r) = pdivmod p q;
  2452            b = coeff (pCons a r) (degree q) / coeff q (degree q)
  2460            b = coeff (pCons a r) (degree q) / coeff q (degree q)
  2453         in (pCons b s, pCons a r - smult b q)))"
  2461         in (pCons b s, pCons a r - smult b q)))"
  2454   apply (simp add: pdivmod_def Let_def, safe)
  2462   apply (simp add: pdivmod_def Let_def, safe)
  2455   apply (rule div_poly_eq)
  2463   apply (rule div_poly_eq)
  2456   apply (erule pdivmod_rel_pCons [OF pdivmod_rel _ refl])
  2464   apply (erule eucl_rel_poly_pCons [OF eucl_rel_poly _ refl])
  2457   apply (rule mod_poly_eq)
  2465   apply (rule mod_poly_eq)
  2458   apply (erule pdivmod_rel_pCons [OF pdivmod_rel _ refl])
  2466   apply (erule eucl_rel_poly_pCons [OF eucl_rel_poly _ refl])
  2459   done
  2467   done
  2460 
  2468 
  2461 lemma pdivmod_fold_coeffs:
  2469 lemma pdivmod_fold_coeffs:
  2462   "pdivmod p q = (if q = 0 then (0, p)
  2470   "pdivmod p q = (if q = 0 then (0, p)
  2463     else fold_coeffs (\<lambda>a (s, r).
  2471     else fold_coeffs (\<lambda>a (s, r).
  2698 
  2706 
  2699 
  2707 
  2700 (* *************** *)
  2708 (* *************** *)
  2701 subsubsection \<open>Improved Code-Equations for Polynomial (Pseudo) Division\<close>
  2709 subsubsection \<open>Improved Code-Equations for Polynomial (Pseudo) Division\<close>
  2702 
  2710 
  2703 lemma pdivmod_pdivmodrel: "pdivmod_rel p q r s = (pdivmod p q = (r, s))"
  2711 lemma pdivmod_pdivmodrel: "eucl_rel_poly p q (r, s) \<longleftrightarrow> pdivmod p q = (r, s)"
  2704   by (metis pdivmod_def pdivmod_rel pdivmod_rel_unique prod.sel)
  2712   by (metis pdivmod_def eucl_rel_poly eucl_rel_poly_unique)
  2705 
  2713 
  2706 lemma pdivmod_via_pseudo_divmod: "pdivmod f g = (if g = 0 then (0,f) 
  2714 lemma pdivmod_via_pseudo_divmod: "pdivmod f g = (if g = 0 then (0,f) 
  2707      else let 
  2715      else let 
  2708        ilc = inverse (coeff g (degree g));       
  2716        ilc = inverse (coeff g (degree g));       
  2709        h = smult ilc g;
  2717        h = smult ilc g;
  2718   obtain q r where p: "pseudo_divmod f h = (q,r)" by force
  2726   obtain q r where p: "pseudo_divmod f h = (q,r)" by force
  2719   from False have id: "?r = (smult lc q, r)" 
  2727   from False have id: "?r = (smult lc q, r)" 
  2720     unfolding Let_def h_def[symmetric] lc_def[symmetric] p by auto
  2728     unfolding Let_def h_def[symmetric] lc_def[symmetric] p by auto
  2721   from pseudo_divmod[OF h0 p, unfolded h1] 
  2729   from pseudo_divmod[OF h0 p, unfolded h1] 
  2722   have f: "f = h * q + r" and r: "r = 0 \<or> degree r < degree h" by auto
  2730   have f: "f = h * q + r" and r: "r = 0 \<or> degree r < degree h" by auto
  2723   have "pdivmod_rel f h q r" unfolding pdivmod_rel_def using f r h0 by auto
  2731   have "eucl_rel_poly f h (q, r)" unfolding eucl_rel_poly_iff using f r h0 by auto
  2724   hence "pdivmod f h = (q,r)" by (simp add: pdivmod_pdivmodrel)
  2732   hence "pdivmod f h = (q,r)" by (simp add: pdivmod_pdivmodrel)
  2725   hence "pdivmod f g = (smult lc q, r)" 
  2733   hence "pdivmod f g = (smult lc q, r)" 
  2726     unfolding pdivmod_def h_def div_smult_right[OF lc] mod_smult_right[OF lc]
  2734     unfolding pdivmod_def h_def div_smult_right[OF lc] mod_smult_right[OF lc]
  2727     using lc by auto
  2735     using lc by auto
  2728   with id show ?thesis by auto
  2736   with id show ?thesis by auto