(* Title: ZF/IntDiv.thy Author: Lawrence C Paulson, Cambridge University Computer Laboratory Copyright 1999 University of Cambridge Here is the division algorithm in ML: fun posDivAlg (a,b) = if a🚫then (0,a) else let val (q,r) = posDivAlg(a, 2*b) in if 0🚫 then (2*q+1, r-b) else (2*q, r) end fun negDivAlg (a,b) = if 0🚫+b then (¬1,a+b) else let val (q,r) = negDivAlg(a, 2*b) in if 0🚫 then (2*q+1, r-b) else (2*q, r) end; fun negateSnd (q,r:int) = (q,¬r); fun divAlg (a,b) = if 0🚫 then if b>0 then posDivAlg (a,b) else if a=0 then (0,0) else negateSnd (negDivAlg (¬a,¬b)) else if 0🚫then negDivAlg (a,b) else negateSnd (posDivAlg (¬a,¬b)); *)
section‹The Division Operators Div and Mod›
theory IntDiv imports Bin OrderArith begin
definition
quorem :: "[i,i] ==> o"where "quorem ≡ λ⟨a,b⟩⟨q,r⟩. a = b$*q $+ r ∧ (#0$∧ #0$≤r ∧ r$¬(#0$∧ b$∧ r $≤ #0)"
definition
adjust :: "[i,i] ==> i"where "adjust(b) ≡ λ⟨q,r⟩. if #0 $≤ r$-b then <#2$*q $+ #1,r$-b> else <#2$*q,r>"
(** the division algorithm **)
definition
posDivAlg :: "i ==> i"where (*for the case a>=0, b>0*) (*recdef posDivAlg "inv_image less_than (\<lambda>\<langle>a,b\<rangle>. nat_of(a $- b $+ #1))"*) "posDivAlg(ab) ≡ wfrec(measure(int*int, λ⟨a,b⟩. nat_of (a $- b $+ #1)), ab, λ⟨a,b⟩ f. if (a$≤#0) then <#0,a> else adjust(b, f ` ))"
(*for the case a\<langle>0, b\<rangle>0*) definition
negDivAlg :: "i ==> i"where (*recdef negDivAlg "inv_image less_than (\<lambda>\<langle>a,b\<rangle>. nat_of(- a $- b))"*) "negDivAlg(ab) ≡ wfrec(measure(int*int, λ⟨a,b⟩. nat_of ($- a $- b)), ab, λ⟨a,b⟩ f. if (#0 $≤ a$+b | b$≤#0) then <#-1,a$+b> else adjust(b, f ` ))"
(*for the general case @{term"b\<noteq>0"}*)
definition
negateSnd :: "i ==> i"where "negateSnd ≡ λ⟨q,r⟩. "
(*The full division algorithm considers all possible signs for a, b including the special case a=0, b<0, because negDivAlg requires a<0*) definition
divAlg :: "i ==> i"where "divAlg ≡ λ⟨a,b⟩. if #0 $≤ a then if #0 $≤ b then posDivAlg (⟨a,b⟩) else if a=#0 then <#0,#0> else negateSnd (negDivAlg (<$-a,$-b>)) else if #0$⟨a,b⟩) else negateSnd (posDivAlg (<$-a,$-b>))"
definition
zdiv :: "[i,i]==>i" (infixl‹zdiv› 70) where "a zdiv b ≡ fst (divAlg ())"
definition
zmod :: "[i,i]==>i" (infixl‹zmod› 70) where "a zmod b ≡ snd (divAlg ())"
(** Some basic laws by Sidi Ehmety (need linear arithmetic!) **)
lemma zspos_add_zspos_imp_zspos: "[#0 $< x; #0 $< y]==> #0 $< x $+ y" apply (rule_tac y = "y"in zless_trans) apply (rule_tac [2] zdiff_zless_iff [THEN iffD1]) apply auto done
lemma zpos_add_zpos_imp_zpos: "[#0 $≤ x; #0 $≤ y]==> #0 $≤ x $+ y" apply (rule_tac y = "y"in zle_trans) apply (rule_tac [2] zdiff_zle_iff [THEN iffD1]) apply auto done
lemma zneg_add_zneg_imp_zneg: "[x $< #0; y $< #0]==> x $+ y $< #0" apply (rule_tac y = "y"in zless_trans) apply (rule zless_zdiff_iff [THEN iffD1]) apply auto done
(* this theorem is used below *) lemma zneg_or_0_add_zneg_or_0_imp_zneg_or_0: "[x $≤ #0; y $≤ #0]==> x $+ y $≤ #0" apply (rule_tac y = "y"in zle_trans) apply (rule zle_zdiff_iff [THEN iffD1]) apply auto done
lemma posDivAlg_induct_lemma [rule_format]: assumes prem: "∧a b. [a ∈ int; b ∈ int; ¬ (a $< b | b $≤ #0) ⟶ P()]==> P(⟨a,b⟩)" shows"⟨u,v⟩∈ int*int ==> P(⟨u,v⟩)" using wf_measure [where A = "int*int"and f = "λ⟨a,b⟩.nat_of (a $- b $+ #1)"] proof (induct "⟨u,v⟩" arbitrary: u v rule: wf_induct) case (step x) hence uv: "u ∈ int""v ∈ int"by auto thus ?case apply (rule prem) apply (rule impI) apply (rule step) apply (auto simp add: step uv not_zle_iff_zless posDivAlg_termination) done qed
lemma posDivAlg_induct [consumes 2]: assumes u_int: "u ∈ int" and v_int: "v ∈ int" and ih: "∧a b. [a ∈ int; b ∈ int; ¬ (a $< b | b $≤ #0) ⟶ P(a, #2 $* b)]==> P(a,b)" shows"P(u,v)" apply (subgoal_tac "(λ⟨x,y⟩. P (x,y)) (⟨u,v⟩)") apply simp apply (rule posDivAlg_induct_lemma) apply (simp (no_asm_use)) apply (rule ih) apply (auto simp add: u_int v_int) done
(*FIXME: use intify in integ_of so that we always have @{term"integ_of w \<in> int"}. then this rewrite can work for all constants\<And>*) lemma intify_eq_0_iff_zle: "intify(m) = #0 ⟷ (m $≤ #0 ∧ #0 $≤ m)" by (simp add: int_eq_iff_zle)
subsection‹Some convenient biconditionals for products of signs›
lemma zmult_pos: "[#0 $< i; #0 $< j]==> #0 $< i $* j" by (drule zmult_zless_mono1, auto)
lemma zmult_neg: "[i $< #0; j $< #0]==> #0 $< i $* j" by (drule zmult_zless_mono1_neg, auto)
lemma zmult_pos_neg: "[#0 $< i; j $< #0]==> i $* j $< #0" by (drule zmult_zless_mono1_neg, auto)
lemma int_0_less_mult_iff: "(#0 $< x $* y) ⟷ (#0 $< x ∧ #0 $< y | x $< #0 ∧ y $< #0)" apply (cut_tac x = "intify (x)"and y = "intify (y)"in int_0_less_lemma) apply auto done
lemma int_0_le_lemma: "[x ∈ int; y ∈ int] ==> (#0 $≤ x $* y) ⟷ (#0 $≤ x ∧ #0 $≤ y | x $≤ #0 ∧ y $≤ #0)" by (auto simp add: zle_def not_zless_iff_zle int_0_less_mult_iff)
lemma int_0_le_mult_iff: "(#0 $≤ x $* y) ⟷ ((#0 $≤ x ∧ #0 $≤ y) | (x $≤ #0 ∧ y $≤ #0))" apply (cut_tac x = "intify (x)"and y = "intify (y)"in int_0_le_lemma) apply auto done
lemma zmult_less_0_iff: "(x $* y $< #0) ⟷ (#0 $< x ∧ y $< #0 | x $< #0 ∧ #0 $< y)" apply (auto simp add: int_0_le_mult_iff not_zle_iff_zless [THEN iff_sym]) apply (auto dest: zless_not_sym simp add: not_zle_iff_zless) done
lemma zmult_le_0_iff: "(x $* y $≤ #0) ⟷ (#0 $≤ x ∧ y $≤ #0 | x $≤ #0 ∧ #0 $≤ y)" by (auto dest: zless_not_sym
simp add: int_0_less_mult_iff not_zless_iff_zle [THEN iff_sym])
(** Arbitrary definitions for division by zero. Useful to simplify certain equations **)
lemma DIVISION_BY_ZERO_ZDIV: "a zdiv #0 = #0" by (simp add: zdiv_def divAlg_def posDivAlg_zero_divisor)
lemma DIVISION_BY_ZERO_ZMOD: "a zmod #0 = intify(a)" by (simp add: zmod_def divAlg_def posDivAlg_zero_divisor)
(** Basic laws about division and remainder **)
lemma raw_zmod_zdiv_equality: "[a ∈ int; b ∈ int]==> a = b $* (a zdiv b) $+ (a zmod b)" apply (case_tac "b = #0") apply (simp add: DIVISION_BY_ZERO_ZDIV DIVISION_BY_ZERO_ZMOD) apply (cut_tac a = "a"and b = "b"in divAlg_correct) apply (auto simp add: quorem_def zdiv_def zmod_def split_def) done
lemma zmod_zdiv_equality: "intify(a) = b $* (a zdiv b) $+ (a zmod b)" apply (rule trans) apply (rule_tac b = "intify (b)"in raw_zmod_zdiv_equality) apply auto done
lemma pos_mod: "#0 $< b ==> #0 $≤ a zmod b ∧ a zmod b $< b" apply (cut_tac a = "intify (a)"and b = "intify (b)"in divAlg_correct) apply (auto simp add: intify_eq_0_iff_zle quorem_def zmod_def split_def) apply (blast dest: zle_zless_trans)+ done
(** proving general properties of zdiv and zmod **)
lemma quorem_div_mod: "[b ≠ #0; a ∈ int; b ∈ int] ==> quorem (⟨a,b⟩, )" apply (cut_tac a = "a"and b = "b"in zmod_zdiv_equality) apply (auto simp add: quorem_def neq_iff_zless pos_mod_sign pos_mod_bound
neg_mod_sign neg_mod_bound) done
(*Surely quorem(\<langle>a,b\<rangle>,\<langle>q,r\<rangle>) implies @{term"a \<in> int"}, but it doesn't matter*) lemma quorem_div: "[quorem(⟨a,b⟩,⟨q,r⟩); b ≠ #0; a ∈ int; b ∈ int; q ∈ int] ==> a zdiv b = q" by (blast intro: quorem_div_mod [THEN unique_quotient])
lemma quorem_mod: "[quorem(⟨a,b⟩,⟨q,r⟩); b ≠ #0; a ∈ int; b ∈ int; q ∈ int; r ∈ int] ==> a zmod b = r" by (blast intro: quorem_div_mod [THEN unique_remainder])
lemma zdiv_pos_pos_trivial_raw: "[a ∈ int; b ∈ int; #0 $≤ a; a $< b]==> a zdiv b = #0" apply (rule quorem_div) apply (auto simp add: quorem_def) (*linear arithmetic*) apply (blast dest: zle_zless_trans)+ done
lemma zdiv_pos_pos_trivial: "[#0 $≤ a; a $< b]==> a zdiv b = #0" apply (cut_tac a = "intify (a)"and b = "intify (b)" in zdiv_pos_pos_trivial_raw) apply auto done
lemma zdiv_neg_neg_trivial_raw: "[a ∈ int; b ∈ int; a $≤ #0; b $< a]==> a zdiv b = #0" apply (rule_tac r = "a"in quorem_div) apply (auto simp add: quorem_def) (*linear arithmetic*) apply (blast dest: zle_zless_trans zless_trans)+ done
lemma zdiv_neg_neg_trivial: "[a $≤ #0; b $< a]==> a zdiv b = #0" apply (cut_tac a = "intify (a)"and b = "intify (b)" in zdiv_neg_neg_trivial_raw) apply auto done
lemma zdiv_pos_neg_trivial_raw: "[a ∈ int; b ∈ int; #0 $< a; a$+b $≤ #0]==> a zdiv b = #-1" apply (rule_tac r = "a $+ b"in quorem_div) apply (auto simp add: quorem_def) (*linear arithmetic*) apply (blast dest: zadd_le_0_lemma zle_zless_trans)+ done
lemma zdiv_pos_neg_trivial: "[#0 $< a; a$+b $≤ #0]==> a zdiv b = #-1" apply (cut_tac a = "intify (a)"and b = "intify (b)" in zdiv_pos_neg_trivial_raw) apply auto done
(*There is no zdiv_neg_pos_trivial because #0 zdiv b = #0 would supersede it*)
lemma zmod_pos_pos_trivial_raw: "[a ∈ int; b ∈ int; #0 $≤ a; a $< b]==> a zmod b = a" apply (rule_tac q = "#0"in quorem_mod) apply (auto simp add: quorem_def) (*linear arithmetic*) apply (blast dest: zle_zless_trans)+ done
lemma zmod_pos_pos_trivial: "[#0 $≤ a; a $< b]==> a zmod b = intify(a)" apply (cut_tac a = "intify (a)"and b = "intify (b)" in zmod_pos_pos_trivial_raw) apply auto done
lemma zmod_neg_neg_trivial_raw: "[a ∈ int; b ∈ int; a $≤ #0; b $< a]==> a zmod b = a" apply (rule_tac q = "#0"in quorem_mod) apply (auto simp add: quorem_def) (*linear arithmetic*) apply (blast dest: zle_zless_trans zless_trans)+ done
lemma zmod_neg_neg_trivial: "[a $≤ #0; b $< a]==> a zmod b = intify(a)" apply (cut_tac a = "intify (a)"and b = "intify (b)" in zmod_neg_neg_trivial_raw) apply auto done
lemma zmod_pos_neg_trivial: "[#0 $< a; a$+b $≤ #0]==> a zmod b = a$+b" apply (cut_tac a = "intify (a)"and b = "intify (b)" in zmod_pos_neg_trivial_raw) apply auto done
(*There is no zmod_neg_pos_trivial...*)
(*Simpler laws such as -a zdiv b = -(a zdiv b) FAIL*)
lemma zdiv_zminus_zminus_raw: "[a ∈ int; b ∈ int]==> ($-a) zdiv ($-b) = a zdiv b" apply (case_tac "b = #0") apply (simp add: DIVISION_BY_ZERO_ZDIV DIVISION_BY_ZERO_ZMOD) apply (subst quorem_div_mod [THEN quorem_neg, simplified, THEN quorem_div]) apply auto done
lemma zdiv_zminus_zminus [simp]: "($-a) zdiv ($-b) = a zdiv b" apply (cut_tac a = "intify (a)"and b = "intify (b)"in zdiv_zminus_zminus_raw) apply auto done
(*Simpler laws such as -a zmod b = -(a zmod b) FAIL*) lemma zmod_zminus_zminus_raw: "[a ∈ int; b ∈ int]==> ($-a) zmod ($-b) = $- (a zmod b)" apply (case_tac "b = #0") apply (simp add: DIVISION_BY_ZERO_ZDIV DIVISION_BY_ZERO_ZMOD) apply (subst quorem_div_mod [THEN quorem_neg, simplified, THEN quorem_mod]) apply auto done
lemma zmod_zminus_zminus [simp]: "($-a) zmod ($-b) = $- (a zmod b)" apply (cut_tac a = "intify (a)"and b = "intify (b)"in zmod_zminus_zminus_raw) apply auto done
subsection‹division of a number by itself›
lemma self_quotient_aux1: "[#0 $< a; a = r $+ a$*q; r $< a]==> #1 $≤ q" apply (subgoal_tac "#0 $< a$*q") apply (cut_tac w = "#0"and z = "q"in add1_zle_iff) apply (simp add: int_0_less_mult_iff) apply (blast dest: zless_trans) (*linear arithmetic...*) apply (drule_tac t = "λx. x $- r"in subst_context) apply (drule sym) apply (simp add: zcompare_rls) done
lemma self_remainder: "[quorem(⟨a,a⟩,⟨q,r⟩); a ∈ int; q ∈ int; r ∈ int; a ≠ #0]==> r = #0" apply (frule self_quotient) apply (auto simp add: quorem_def) done
lemma zdiv_self_raw: "[a ≠ #0; a ∈ int]==> a zdiv a = #1" apply (blast intro: quorem_div_mod [THEN self_quotient]) done
lemma zdiv_self [simp]: "intify(a) ≠ #0 ==> a zdiv a = #1" apply (drule zdiv_self_raw) apply auto done
(*Here we have 0 zmod 0 = 0, also assumed by Knuth (who puts m zmod 0 = 0) *) lemma zmod_self_raw: "a ∈ int ==> a zmod a = #0" apply (case_tac "a = #0") apply (simp add: DIVISION_BY_ZERO_ZDIV DIVISION_BY_ZERO_ZMOD) apply (blast intro: quorem_div_mod [THEN self_remainder]) done
lemma zmod_self [simp]: "a zmod a = #0" apply (cut_tac a = "intify (a)"in zmod_self_raw) apply auto done
subsection‹Computation of division and remainder›
lemma zdiv_zero [simp]: "#0 zdiv b = #0" by (simp add: zdiv_def divAlg_def)
lemma zdiv_eq_minus1: "#0 $< b ==> #-1 zdiv b = #-1" by (simp (no_asm_simp) add: zdiv_def divAlg_def)
lemma zmod_zero [simp]: "#0 zmod b = #0" by (simp add: zmod_def divAlg_def)
lemma zdiv_minus1: "#0 $< b ==> #-1 zdiv b = #-1" by (simp add: zdiv_def divAlg_def)
lemma zmod_minus1: "#0 $< b ==> #-1 zmod b = b $- #1" by (simp add: zmod_def divAlg_def)
lemma zdiv_pos_neg: "[#0 $< a; b $< #0] ==> a zdiv b = fst (negateSnd(negDivAlg (<$-a, $-b>)))" apply (simp (no_asm_simp) add: zdiv_def divAlg_def intify_eq_0_iff_zle) apply auto apply (blast dest: zle_zless_trans)+ apply (blast dest: zless_trans) apply (blast intro: zless_imp_zle) done
lemma zmod_pos_neg: "[#0 $< a; b $< #0] ==> a zmod b = snd (negateSnd(negDivAlg (<$-a, $-b>)))" apply (simp (no_asm_simp) add: zmod_def divAlg_def intify_eq_0_iff_zle) apply auto apply (blast dest: zle_zless_trans)+ apply (blast dest: zless_trans) apply (blast intro: zless_imp_zle) done
(** a negative, b negative **)
lemma zdiv_neg_neg: "[a $< #0; b $≤ #0] ==> a zdiv b = fst (negateSnd(posDivAlg(<$-a, $-b>)))" apply (simp (no_asm_simp) add: zdiv_def divAlg_def) apply auto apply (blast dest!: zle_zless_trans)+ done
lemma zmod_neg_neg: "[a $< #0; b $≤ #0] ==> a zmod b = snd (negateSnd(posDivAlg(<$-a, $-b>)))" apply (simp (no_asm_simp) add: zmod_def divAlg_def) apply auto apply (blast dest!: zle_zless_trans)+ done
declare zdiv_pos_pos [of "integ_of (v)""integ_of (w)", simp] for v w declare zdiv_neg_pos [of "integ_of (v)""integ_of (w)", simp] for v w declare zdiv_pos_neg [of "integ_of (v)""integ_of (w)", simp] for v w declare zdiv_neg_neg [of "integ_of (v)""integ_of (w)", simp] for v w declare zmod_pos_pos [of "integ_of (v)""integ_of (w)", simp] for v w declare zmod_neg_pos [of "integ_of (v)""integ_of (w)", simp] for v w declare zmod_pos_neg [of "integ_of (v)""integ_of (w)", simp] for v w declare zmod_neg_neg [of "integ_of (v)""integ_of (w)", simp] for v w declare posDivAlg_eqn [of concl: "integ_of (v)""integ_of (w)", simp] for v w declare negDivAlg_eqn [of concl: "integ_of (v)""integ_of (w)", simp] for v w
(** Special-case simplification **)
lemma zmod_1 [simp]: "a zmod #1 = #0" apply (cut_tac a = "a"and b = "#1"in pos_mod_sign) apply (cut_tac [2] a = "a"and b = "#1"in pos_mod_bound) apply auto (*arithmetic*) apply (drule add1_zle_iff [THEN iffD2]) apply (rule zle_anti_sym) apply auto done
lemma zdiv_1 [simp]: "a zdiv #1 = intify(a)" apply (cut_tac a = "a"and b = "#1"in zmod_zdiv_equality) apply auto done
lemma zmod_minus1_right [simp]: "a zmod #-1 = #0" apply (cut_tac a = "a"and b = "#-1"in neg_mod_sign) apply (cut_tac [2] a = "a"and b = "#-1"in neg_mod_bound) apply auto (*arithmetic*) apply (drule add1_zle_iff [THEN iffD2]) apply (rule zle_anti_sym) apply auto done
lemma zdiv_minus1_right_raw: "a ∈ int ==> a zdiv #-1 = $-a" apply (cut_tac a = "a"and b = "#-1"in zmod_zdiv_equality) apply auto apply (rule equation_zminus [THEN iffD2]) apply auto done
lemma zdiv_minus1_right: "a zdiv #-1 = $-a" apply (cut_tac a = "intify (a)"in zdiv_minus1_right_raw) apply auto done declare zdiv_minus1_right [simp]
subsection‹Monotonicity in the first argument (divisor)›
lemma zdiv_mono1: "[a $≤ a'; #0 $< b]==> a zdiv b $≤ a' zdiv b" apply (cut_tac a = "a"and b = "b"in zmod_zdiv_equality) apply (cut_tac a = "a'"and b = "b"in zmod_zdiv_equality) apply (rule unique_quotient_lemma) apply (erule subst) apply (erule subst) apply (simp_all (no_asm_simp) add: pos_mod_sign pos_mod_bound) done
lemma zdiv_mono1_neg: "[a $≤ a'; b $< #0]==> a' zdiv b $≤ a zdiv b" apply (cut_tac a = "a"and b = "b"in zmod_zdiv_equality) apply (cut_tac a = "a'"and b = "b"in zmod_zdiv_equality) apply (rule unique_quotient_lemma_neg) apply (erule subst) apply (erule subst) apply (simp_all (no_asm_simp) add: neg_mod_sign neg_mod_bound) done
subsection‹Monotonicity in the second argument (dividend)›
lemma zdiv_zmult1_eq_raw: "[b ∈ int; c ∈ int] ==> (a$*b) zdiv c = a$*(b zdiv c) $+ a$*(b zmod c) zdiv c" apply (case_tac "c = #0") apply (simp add: DIVISION_BY_ZERO_ZDIV DIVISION_BY_ZERO_ZMOD) apply (rule quorem_div_mod [THEN zmult1_lemma, THEN quorem_div]) apply auto done
lemma zdiv_zmult1_eq: "(a$*b) zdiv c = a$*(b zdiv c) $+ a$*(b zmod c) zdiv c" apply (cut_tac b = "intify (b)"and c = "intify (c)"in zdiv_zmult1_eq_raw) apply auto done
lemma zmod_zmult1_eq_raw: "[b ∈ int; c ∈ int]==> (a$*b) zmod c = a$*(b zmod c) zmod c" apply (case_tac "c = #0") apply (simp add: DIVISION_BY_ZERO_ZDIV DIVISION_BY_ZERO_ZMOD) apply (rule quorem_div_mod [THEN zmult1_lemma, THEN quorem_mod]) apply auto done
lemma zmod_zmult1_eq: "(a$*b) zmod c = a$*(b zmod c) zmod c" apply (cut_tac b = "intify (b)"and c = "intify (c)"in zmod_zmult1_eq_raw) apply auto done
lemma zmod_zmult1_eq': "(a$*b) zmod c = ((a zmod c) $* b) zmod c" apply (rule trans) apply (rule_tac b = " (b $* a) zmod c"in trans) apply (rule_tac [2] zmod_zmult1_eq) apply (simp_all (no_asm) add: zmult_commute) done
(*NOT suitable for rewriting: the RHS has an instance of the LHS*) lemma zdiv_zadd1_eq_raw: "[a ∈ int; b ∈ int; c ∈ int]==> (a$+b) zdiv c = a zdiv c $+ b zdiv c $+ ((a zmod c $+ b zmod c) zdiv c)" apply (case_tac "c = #0") apply (simp add: DIVISION_BY_ZERO_ZDIV DIVISION_BY_ZERO_ZMOD) apply (blast intro: zadd1_lemma [OF quorem_div_mod quorem_div_mod, THEN quorem_div]) done
lemma zdiv_zadd1_eq: "(a$+b) zdiv c = a zdiv c $+ b zdiv c $+ ((a zmod c $+ b zmod c) zdiv c)" apply (cut_tac a = "intify (a)"and b = "intify (b)"and c = "intify (c)" in zdiv_zadd1_eq_raw) apply auto done
lemma zmod_zadd1_eq_raw: "[a ∈ int; b ∈ int; c ∈ int] ==> (a$+b) zmod c = (a zmod c $+ b zmod c) zmod c" apply (case_tac "c = #0") apply (simp add: DIVISION_BY_ZERO_ZDIV DIVISION_BY_ZERO_ZMOD) apply (blast intro: zadd1_lemma [OF quorem_div_mod quorem_div_mod, THEN quorem_mod]) done
lemma zmod_zadd1_eq: "(a$+b) zmod c = (a zmod c $+ b zmod c) zmod c" apply (cut_tac a = "intify (a)"and b = "intify (b)"and c = "intify (c)" in zmod_zadd1_eq_raw) apply auto done
lemma zmod_div_trivial_raw: "[a ∈ int; b ∈ int]==> (a zmod b) zdiv b = #0" apply (case_tac "b = #0") apply (simp add: DIVISION_BY_ZERO_ZDIV DIVISION_BY_ZERO_ZMOD) apply (auto simp add: neq_iff_zless pos_mod_sign pos_mod_bound
zdiv_pos_pos_trivial neg_mod_sign neg_mod_bound zdiv_neg_neg_trivial) done
lemma zmod_div_trivial [simp]: "(a zmod b) zdiv b = #0" apply (cut_tac a = "intify (a)"and b = "intify (b)"in zmod_div_trivial_raw) apply auto done
lemma zmod_mod_trivial_raw: "[a ∈ int; b ∈ int]==> (a zmod b) zmod b = a zmod b" apply (case_tac "b = #0") apply (simp add: DIVISION_BY_ZERO_ZDIV DIVISION_BY_ZERO_ZMOD) apply (auto simp add: neq_iff_zless pos_mod_sign pos_mod_bound
zmod_pos_pos_trivial neg_mod_sign neg_mod_bound zmod_neg_neg_trivial) done
lemma zmod_mod_trivial [simp]: "(a zmod b) zmod b = a zmod b" apply (cut_tac a = "intify (a)"and b = "intify (b)"in zmod_mod_trivial_raw) apply auto done
lemma zmod_zadd_left_eq: "(a$+b) zmod c = ((a zmod c) $+ b) zmod c" apply (rule trans [symmetric]) apply (rule zmod_zadd1_eq) apply (simp (no_asm)) apply (rule zmod_zadd1_eq [symmetric]) done
lemma zmod_zadd_right_eq: "(a$+b) zmod c = (a $+ (b zmod c)) zmod c" apply (rule trans [symmetric]) apply (rule zmod_zadd1_eq) apply (simp (no_asm)) apply (rule zmod_zadd1_eq [symmetric]) done
lemma zdiv_zadd_self1 [simp]: "intify(a) ≠ #0 ==> (a$+b) zdiv a = b zdiv a $+ #1" by (simp (no_asm_simp) add: zdiv_zadd1_eq)
lemma zdiv_zadd_self2 [simp]: "intify(a) ≠ #0 ==> (b$+a) zdiv a = b zdiv a $+ #1" by (simp (no_asm_simp) add: zdiv_zadd1_eq)
lemma zmod_zadd_self1 [simp]: "(a$+b) zmod a = b zmod a" apply (case_tac "a = #0") apply (simp add: DIVISION_BY_ZERO_ZDIV DIVISION_BY_ZERO_ZMOD) apply (simp (no_asm_simp) add: zmod_zadd1_eq) done
lemma zmod_zadd_self2 [simp]: "(b$+a) zmod a = b zmod a" apply (case_tac "a = #0") apply (simp add: DIVISION_BY_ZERO_ZDIV DIVISION_BY_ZERO_ZMOD) apply (simp (no_asm_simp) add: zmod_zadd1_eq) done
subsection‹proving a zdiv (b*c) = (a zdiv b) zdiv c›
(*The condition c>0 seems necessary. Consider that 7 zdiv \<not>6 = \<not>2 but 7 zdiv 2 zdiv ¬3 = 3 zdiv ¬3 = ¬1. The subcase (a zdiv b) zmod c = 0 seems to cause particular problems.*)
(** first, four lemmas to bound the remainder for the cases b<0 and b>0 **)
lemma zdiv_zmult2_eq_raw: "[#0 $< c; a ∈ int; b ∈ int]==> a zdiv (b$*c) = (a zdiv b) zdiv c" apply (case_tac "b = #0") apply (simp add: DIVISION_BY_ZERO_ZDIV DIVISION_BY_ZERO_ZMOD) apply (rule quorem_div_mod [THEN zdiv_zmult2_lemma, THEN quorem_div]) apply (auto simp add: intify_eq_0_iff_zle) apply (blast dest: zle_zless_trans) done
lemma zdiv_zmult2_eq: "#0 $< c ==> a zdiv (b$*c) = (a zdiv b) zdiv c" apply (cut_tac a = "intify (a)"and b = "intify (b)"in zdiv_zmult2_eq_raw) apply auto done
lemma zmod_zmult2_eq_raw: "[#0 $< c; a ∈ int; b ∈ int] ==> a zmod (b$*c) = b$*(a zdiv b zmod c) $+ a zmod b" apply (case_tac "b = #0") apply (simp add: DIVISION_BY_ZERO_ZDIV DIVISION_BY_ZERO_ZMOD) apply (rule quorem_div_mod [THEN zdiv_zmult2_lemma, THEN quorem_mod]) apply (auto simp add: intify_eq_0_iff_zle) apply (blast dest: zle_zless_trans) done
lemma zmod_zmult2_eq: "#0 $< c ==> a zmod (b$*c) = b$*(a zdiv b zmod c) $+ a zmod b" apply (cut_tac a = "intify (a)"and b = "intify (b)"in zmod_zmult2_eq_raw) apply auto done
subsection‹Cancellation of common factors in "zdiv"›
lemma zmod_zmult_zmult1: "(c$*a) zmod (c$*b) = c $* (a zmod b)" apply (cut_tac b = "intify (b)"and c = "intify (c)"in zmod_zmult_zmult1_raw) apply auto done
lemma zmod_zmult_zmult2: "(a$*c) zmod (b$*c) = (a zmod b) $* c" apply (cut_tac c = "c"in zmod_zmult_zmult1) apply (auto simp add: zmult_commute) done
(** Quotients of signs **)
lemma zdiv_neg_pos_less0: "[a $< #0; #0 $< b]==> a zdiv b $< #0" apply (subgoal_tac "a zdiv b $≤ #-1") apply (erule zle_zless_trans) apply (simp (no_asm)) apply (rule zle_trans) apply (rule_tac a' = "#-1"in zdiv_mono1) apply (rule zless_add1_iff_zle [THEN iffD1]) apply (simp (no_asm)) apply (auto simp add: zdiv_minus1) done
lemma zdiv_nonneg_neg_le0: "[#0 $≤ a; b $< #0]==> a zdiv b $≤ #0" apply (drule zdiv_mono1_neg) apply auto done
lemma pos_imp_zdiv_nonneg_iff: "#0 $< b ==> (#0 $≤ a zdiv b) ⟷ (#0 $≤ a)" apply auto apply (drule_tac [2] zdiv_mono1) apply (auto simp add: neq_iff_zless) apply (simp (no_asm_use) add: not_zless_iff_zle [THEN iff_sym]) apply (blast intro: zdiv_neg_pos_less0) done
lemma neg_imp_zdiv_nonneg_iff: "b $< #0 ==> (#0 $≤ a zdiv b) ⟷ (a $≤ #0)" apply (subst zdiv_zminus_zminus [symmetric]) apply (rule iff_trans) apply (rule pos_imp_zdiv_nonneg_iff) apply auto done
(*But not (a zdiv b $\<le> 0 iff a$\<le>0); consider a=1, b=2 when a zdiv b = 0.*) lemma pos_imp_zdiv_neg_iff: "#0 $< b ==> (a zdiv b $< #0) ⟷ (a $< #0)" apply (simp (no_asm_simp) add: not_zle_iff_zless [THEN iff_sym]) apply (erule pos_imp_zdiv_nonneg_iff) done
(*Again the law fails for $\<le>: consider a = -1, b = -2 when a zdiv b = 0*) lemma neg_imp_zdiv_neg_iff: "b $< #0 ==> (a zdiv b $< #0) ⟷ (#0 $< a)" apply (simp (no_asm_simp) add: not_zle_iff_zless [THEN iff_sym]) apply (erule neg_imp_zdiv_nonneg_iff) done
(* THESE REMAIN TO BE CONVERTED -- but aren't that useful! subsection{* Speeding up the division algorithm with shifting *} (** computing "zdiv" by shifting **)
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.