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 |