Theory IntMod

Up to index of Isabelle/HOL/Bits

theory IntMod
imports NumeralType
begin

header {* Integers mod n *}

theory IntMod
imports NumeralType
begin

subsection {* Locale for modular arithmetic subtypes *}

locale mod_type =
  fixes n :: int
  and Rep :: "'a::{zero,one,plus,times,minus,power} => int"
  and Abs :: "int => 'a::{zero,one,plus,times,minus,power}"
  assumes type: "type_definition Rep Abs {0..<n}" and size1: "1 < n"
  and zero_def: "0 ≡ Abs 0"
  and one_def:  "1 ≡ Abs 1"
  and add_def:  "x + y ≡ Abs ((Rep x + Rep y) mod n)"
  and mult_def: "x * y ≡ Abs ((Rep x * Rep y) mod n)"
  and diff_def: "x - y ≡ Abs ((Rep x - Rep y) mod n)"
  and minus_def: "- x ≡ Abs ((- Rep x) mod n)"
  and power_def: "x ^ k ≡ Abs (Rep x ^ k mod n)"

lemma (in mod_type) size0: "0 < n"
by (cut_tac size1, simp)

lemmas (in mod_type) definitions =
  zero_def one_def add_def mult_def minus_def diff_def power_def

lemma (in mod_type) Rep_less_n: "Rep x < n"
by (rule type_definition.Rep [OF type, simplified, THEN conjunct2])

lemma (in mod_type) Rep_le_n: "Rep x ≤ n"
by (rule Rep_less_n [THEN order_less_imp_le])

lemma (in mod_type) Rep_inject_sym: "(x = y) = (Rep x = Rep y)"
by (rule type_definition.Rep_inject [OF type, symmetric])

lemma (in mod_type) Rep_inverse: "Abs (Rep x) = x"
by (rule type_definition.Rep_inverse [OF type])

lemma (in mod_type) Abs_inverse: "m ∈ {0..<n} ==> Rep (Abs m) = m"
by (rule type_definition.Abs_inverse [OF type])

lemma (in mod_type) Rep_Abs_mod: "Rep (Abs (m mod n)) = m mod n"
by (simp add: Abs_inverse IntDiv.pos_mod_conj [OF size0])

lemma (in mod_type) Rep_Abs_0: "Rep (Abs 0) = 0"
by (simp add: Abs_inverse size0)

lemma (in mod_type) Rep_0: "Rep 0 = 0"
by (simp add: zero_def Rep_Abs_0)

lemma (in mod_type) Rep_Abs_1: "Rep (Abs 1) = 1"
by (simp add: Abs_inverse size1)

lemma (in mod_type) Rep_1: "Rep 1 = 1"
by (simp add: one_def Rep_Abs_1)

lemma (in mod_type) Rep_mod: "Rep x mod n = Rep x"
apply (rule_tac x=x in type_definition.Abs_cases [OF type])
apply (simp add: type_definition.Abs_inverse [OF type])
apply (simp add: mod_pos_pos_trivial)
done

text "The following 3 lemmas belong in Integ/IntDiv.thy"

lemma zminus_zmod: "- ((x::int) mod m) mod m = - x mod m"
by (simp only: zmod_zminus1_eq_if mod_mod_trivial)

lemma zdiff_zmod_left: "(x mod m - y) mod m = (x - y) mod (m::int)"
by (simp only: diff_def zmod_zadd_left_eq [symmetric])

lemma zdiff_zmod_right: "(x - y mod m) mod m = (x - y) mod (m::int)"
proof -
  have "(x + - (y mod m) mod m) mod m = (x + - y mod m) mod m"
    by (simp only: zminus_zmod)
  hence "(x + - (y mod m)) mod m = (x + - y) mod m"
    by (simp only: zmod_zadd_right_eq [symmetric])
  thus "(x - y mod m) mod m = (x - y) mod m"
    by (simp only: diff_def)
qed

lemmas zmod_simps =
  IntDiv.zmod_zadd_left_eq  [symmetric]
  IntDiv.zmod_zadd_right_eq [symmetric]
  IntDiv.zmod_zmult1_eq     [symmetric]
  IntDiv.zmod_zmult1_eq'    [symmetric]
  IntDiv.zpower_zmod
  zminus_zmod zdiff_zmod_left zdiff_zmod_right

lemmas (in mod_type) Rep_simps =
  Rep_inject_sym Rep_inverse Rep_Abs_mod Rep_mod Rep_Abs_0 Rep_Abs_1

lemma (in mod_type) comm_ring_1: "OFCLASS('a, comm_ring_1_class)"
apply (intro_classes, unfold definitions)
apply (simp_all add: Rep_simps zmod_simps add_ac mult_ac ring_distrib)
done

lemma (in mod_type) recpower: "OFCLASS('a, recpower_class)"
apply (intro_classes, unfold definitions)
apply (simp_all add: Rep_simps zmod_simps add_ac mult_assoc
                     mod_pos_pos_trivial size1)
done

locale (open) mod_ring = mod_type +
  constrains n :: int
  and Rep :: "'a::{number_ring,power} => int"
  and Abs :: "int => 'a::{number_ring,power}"

lemma (in mod_ring) of_nat_eq: "of_nat k = Abs (int k mod n)"
apply (induct k)
apply (simp add: zero_def)
apply (simp add: Rep_simps add_def one_def zmod_simps add_ac)
done

lemma (in mod_ring) of_int_eq: "of_int z = Abs (z mod n)"
apply (cases z rule: int_diff_cases)
apply (simp add: Rep_simps of_nat_eq diff_def zmod_simps)
done

lemma (in mod_ring) Rep_number_of:
  "Rep (number_of w) = number_of w mod n"
by (simp add: number_of_eq of_int_eq Rep_Abs_mod)

lemma (in mod_ring) iszero_number_of:
  "iszero (number_of w::'a) = (number_of w mod n = 0)"
by (simp add: Rep_simps number_of_eq of_int_eq iszero_def zero_def)

lemma (in mod_ring) cases:
  assumes 1: "!!z. [|(x::'a) = of_int z; 0 ≤ z; z < n|] ==> P"
  shows "P"
apply (cases x rule: type_definition.Abs_cases [OF type])
apply (rule_tac z="y" in 1)
apply (simp_all add: of_int_eq mod_pos_pos_trivial)
done

lemma (in mod_ring) induct:
  "(!!z. [|0 ≤ z; z < n|] ==> P (of_int z)) ==> P (x::'a)"
by (cases x rule: cases) simp

subsection {* Type Constructor for Integers mod n *}

typedef (open) 'a intmod = "{0..<int_of_type TYPE('a::numeral2)}"
by (rule_tac x=0 in exI, simp add: zero_less_int_of_type)

constdefs
  Abs_intmod' :: "int => 'a::numeral2 intmod"
  "Abs_intmod' x ≡ Abs_intmod (x mod (int_of_type TYPE('a)))"

instance intmod :: (numeral1) "{zero,one,plus,times,minus,power}" ..

defs (overloaded)
  zero_intmod_def: "0 ≡ Abs_intmod 0"
  one_intmod_def:  "1 ≡ Abs_intmod 1"
  add_intmod_def:  "x + y ≡ Abs_intmod' (Rep_intmod x + Rep_intmod y)"
  mult_intmod_def: "x * y ≡ Abs_intmod' (Rep_intmod x * Rep_intmod y)"
  diff_intmod_def: "x - y ≡ Abs_intmod' (Rep_intmod x - Rep_intmod y)"
  minus_intmod_def: "- x ≡ Abs_intmod' (- Rep_intmod x)"
  power_intmod_def: "x ^ k ≡ Abs_intmod' (Rep_intmod x ^ k)"

interpretation intmod:
  mod_type ["int_of_type TYPE('a::numeral2)"
            "Rep_intmod::'a::numeral2 intmod => int"
            "Abs_intmod::int => 'a::numeral2 intmod"]
apply (rule mod_type.intro)
apply (rule type_definition_intmod)
apply (rule one_less_int_of_type)
apply (rule zero_intmod_def)
apply (rule one_intmod_def)
apply (rule add_intmod_def [unfolded Abs_intmod'_def])
apply (rule mult_intmod_def [unfolded Abs_intmod'_def])
apply (rule diff_intmod_def [unfolded Abs_intmod'_def])
apply (rule minus_intmod_def [unfolded Abs_intmod'_def])
apply (rule power_intmod_def [unfolded Abs_intmod'_def])
done

instance intmod :: (numeral2) comm_ring_1
by (rule intmod.comm_ring_1)

instance intmod :: (numeral2) recpower
by (rule intmod.recpower)

instance intmod :: (numeral2) number ..

defs (overloaded)
  number_intmod_def: "number_of w::'a::numeral2 intmod ≡ of_int w"

instance intmod :: (numeral2) number_ring
by intro_classes (simp only: number_intmod_def)

interpretation intmod:
  mod_ring ["int_of_type TYPE('a::numeral2)"
            "Rep_intmod::'a::numeral2 intmod => int"
            "Abs_intmod::int => 'a::numeral2 intmod"] .

lemmas intmod_cases [cases type: intmod, case_names of_int] =
  intmod.cases [unfolded int_of_type_def]

lemmas intmod_induct [induct type: intmod, case_names of_int] =
  intmod.induct [unfolded int_of_type_def]

lemma intmod_iszero_number_of [unfolded int_of_type_def, simp]:
  "iszero (number_of w::'a::numeral2 intmod) =
   (number_of w mod int_of_type TYPE('a) = 0)"
by (rule intmod.iszero_number_of)

syntax
  "intmod" :: "type => type"  ("Z[_]" [1000] 1000)

syntax (xsymbols)
  "intmod" :: "type => type"  ("\<int>_" [1000] 1000)

end

Locale for modular arithmetic subtypes

lemma size0:

  0 < n  [.]

lemma definitions:

  0::'a == Abs 0  [.]
  1::'a == Abs 1  [.]
  x + y == Abs ((Rep x + Rep y) mod n)  [.]
  x * y == Abs (Rep x * Rep y mod n)  [.]
  - x == Abs (- Rep x mod n)  [.]
  x - y == Abs ((Rep x - Rep y) mod n)  [.]
  x ^ k == Abs (Rep x ^ k mod n)  [.]

lemma Rep_less_n:

  Rep x < n  [.]

lemma Rep_le_n:

  Rep xn  [.]

lemma Rep_inject_sym:

  (x = y) = (Rep x = Rep y)  [.]

lemma Rep_inverse:

  Abs (Rep x) = x  [.]

lemma Abs_inverse:

  m ∈ {0..<n} ==> Rep (Abs m) = m  [.]

lemma Rep_Abs_mod:

  Rep (Abs (m mod n)) = m mod n  [.]

lemma Rep_Abs_0:

  Rep (Abs 0) = 0  [.]

lemma Rep_0:

  Rep (0::'a) = 0  [.]

lemma Rep_Abs_1:

  Rep (Abs 1) = 1  [.]

lemma Rep_1:

  Rep (1::'a) = 1  [.]

lemma Rep_mod:

  Rep x mod n = Rep x  [.]

lemma zminus_zmod:

  - (x mod m) mod m = - x mod m

lemma zdiff_zmod_left:

  (x mod m - y) mod m = (x - y) mod m

lemma zdiff_zmod_right:

  (x - y mod m) mod m = (x - y) mod m

lemma zmod_simps:

  (a mod c + b) mod c = (a + b) mod c
  (a + b mod c) mod c = (a + b) mod c
  a * (b mod c) mod c = a * b mod c
  a mod c * b mod c = a * b mod c
  (x mod m) ^ y mod m = x ^ y mod m
  - (x mod m) mod m = - x mod m
  (x mod m - y) mod m = (x - y) mod m
  (x - y mod m) mod m = (x - y) mod m

lemma Rep_simps:

  (x = y) = (Rep x = Rep y)  [.]
  Abs (Rep x) = x  [.]
  Rep (Abs (m mod n)) = m mod n  [.]
  Rep x mod n = Rep x  [.]
  Rep (Abs 0) = 0  [.]
  Rep (Abs 1) = 1  [.]

lemma comm_ring_1:

  OFCLASS('a, comm_ring_1_class)  [.]

lemma recpower:

  OFCLASS('a, recpower_class)  [.]

lemma of_nat_eq:

  of_nat k = Abs (int k mod n)  [.]

lemma of_int_eq:

  of_int z = Abs (z mod n)  [.]

lemma Rep_number_of:

  Rep (number_of w) = number_of w mod n  [.]

lemma iszero_number_of:

  iszero (number_of w) = (number_of w mod n = 0)  [.]

lemma cases:

  (!!z. [| x = of_int z; 0 ≤ z; z < n |] ==> P) ==> P  [.]

lemma induct:

  (!!z. [| 0 ≤ z; z < n |] ==> P (of_int z)) ==> P x  [.]

Type Constructor for Integers mod n

lemma intmod_cases:

  (!!z. [| x = of_int z; 0 ≤ z; z < number_of (bin_of_type TYPE('b)) |] ==> P)
  ==> P

lemma intmod_induct:

  (!!z. [| 0 ≤ z; z < number_of (bin_of_type TYPE('b)) |] ==> P (of_int z))
  ==> P x

lemma intmod_iszero_number_of:

  iszero (number_of w) = (number_of w mod number_of (bin_of_type TYPE('a)) = 0)