huffman@47108: (* Title: HOL/Num.thy huffman@47108: Author: Florian Haftmann huffman@47108: Author: Brian Huffman huffman@47108: *) huffman@47108: huffman@47108: header {* Binary Numerals *} huffman@47108: huffman@47108: theory Num huffman@47191: imports Datatype huffman@47108: begin huffman@47108: huffman@47108: subsection {* The @{text num} type *} huffman@47108: huffman@47108: datatype num = One | Bit0 num | Bit1 num huffman@47108: huffman@47108: text {* Increment function for type @{typ num} *} huffman@47108: huffman@47108: primrec inc :: "num \ num" where huffman@47108: "inc One = Bit0 One" | huffman@47108: "inc (Bit0 x) = Bit1 x" | huffman@47108: "inc (Bit1 x) = Bit0 (inc x)" huffman@47108: huffman@47108: text {* Converting between type @{typ num} and type @{typ nat} *} huffman@47108: huffman@47108: primrec nat_of_num :: "num \ nat" where huffman@47108: "nat_of_num One = Suc 0" | huffman@47108: "nat_of_num (Bit0 x) = nat_of_num x + nat_of_num x" | huffman@47108: "nat_of_num (Bit1 x) = Suc (nat_of_num x + nat_of_num x)" huffman@47108: huffman@47108: primrec num_of_nat :: "nat \ num" where huffman@47108: "num_of_nat 0 = One" | huffman@47108: "num_of_nat (Suc n) = (if 0 < n then inc (num_of_nat n) else One)" huffman@47108: huffman@47108: lemma nat_of_num_pos: "0 < nat_of_num x" huffman@47108: by (induct x) simp_all huffman@47108: huffman@47108: lemma nat_of_num_neq_0: " nat_of_num x \ 0" huffman@47108: by (induct x) simp_all huffman@47108: huffman@47108: lemma nat_of_num_inc: "nat_of_num (inc x) = Suc (nat_of_num x)" huffman@47108: by (induct x) simp_all huffman@47108: huffman@47108: lemma num_of_nat_double: huffman@47108: "0 < n \ num_of_nat (n + n) = Bit0 (num_of_nat n)" huffman@47108: by (induct n) simp_all huffman@47108: huffman@47108: text {* huffman@47108: Type @{typ num} is isomorphic to the strictly positive huffman@47108: natural numbers. huffman@47108: *} huffman@47108: huffman@47108: lemma nat_of_num_inverse: "num_of_nat (nat_of_num x) = x" huffman@47108: by (induct x) (simp_all add: num_of_nat_double nat_of_num_pos) huffman@47108: huffman@47108: lemma num_of_nat_inverse: "0 < n \ nat_of_num (num_of_nat n) = n" huffman@47108: by (induct n) (simp_all add: nat_of_num_inc) huffman@47108: huffman@47108: lemma num_eq_iff: "x = y \ nat_of_num x = nat_of_num y" huffman@47108: apply safe huffman@47108: apply (drule arg_cong [where f=num_of_nat]) huffman@47108: apply (simp add: nat_of_num_inverse) huffman@47108: done huffman@47108: huffman@47108: lemma num_induct [case_names One inc]: huffman@47108: fixes P :: "num \ bool" huffman@47108: assumes One: "P One" huffman@47108: and inc: "\x. P x \ P (inc x)" huffman@47108: shows "P x" huffman@47108: proof - huffman@47108: obtain n where n: "Suc n = nat_of_num x" huffman@47108: by (cases "nat_of_num x", simp_all add: nat_of_num_neq_0) huffman@47108: have "P (num_of_nat (Suc n))" huffman@47108: proof (induct n) huffman@47108: case 0 show ?case using One by simp huffman@47108: next huffman@47108: case (Suc n) huffman@47108: then have "P (inc (num_of_nat (Suc n)))" by (rule inc) huffman@47108: then show "P (num_of_nat (Suc (Suc n)))" by simp huffman@47108: qed huffman@47108: with n show "P x" huffman@47108: by (simp add: nat_of_num_inverse) huffman@47108: qed huffman@47108: huffman@47108: text {* huffman@47108: From now on, there are two possible models for @{typ num}: huffman@47108: as positive naturals (rule @{text "num_induct"}) huffman@47108: and as digit representation (rules @{text "num.induct"}, @{text "num.cases"}). huffman@47108: *} huffman@47108: huffman@47108: huffman@47108: subsection {* Numeral operations *} huffman@47108: huffman@47108: instantiation num :: "{plus,times,linorder}" huffman@47108: begin huffman@47108: huffman@47108: definition [code del]: huffman@47108: "m + n = num_of_nat (nat_of_num m + nat_of_num n)" huffman@47108: huffman@47108: definition [code del]: huffman@47108: "m * n = num_of_nat (nat_of_num m * nat_of_num n)" huffman@47108: huffman@47108: definition [code del]: huffman@47108: "m \ n \ nat_of_num m \ nat_of_num n" huffman@47108: huffman@47108: definition [code del]: huffman@47108: "m < n \ nat_of_num m < nat_of_num n" huffman@47108: huffman@47108: instance huffman@47108: by (default, auto simp add: less_num_def less_eq_num_def num_eq_iff) huffman@47108: huffman@47108: end huffman@47108: huffman@47108: lemma nat_of_num_add: "nat_of_num (x + y) = nat_of_num x + nat_of_num y" huffman@47108: unfolding plus_num_def huffman@47108: by (intro num_of_nat_inverse add_pos_pos nat_of_num_pos) huffman@47108: huffman@47108: lemma nat_of_num_mult: "nat_of_num (x * y) = nat_of_num x * nat_of_num y" huffman@47108: unfolding times_num_def huffman@47108: by (intro num_of_nat_inverse mult_pos_pos nat_of_num_pos) huffman@47108: huffman@47108: lemma add_num_simps [simp, code]: huffman@47108: "One + One = Bit0 One" huffman@47108: "One + Bit0 n = Bit1 n" huffman@47108: "One + Bit1 n = Bit0 (n + One)" huffman@47108: "Bit0 m + One = Bit1 m" huffman@47108: "Bit0 m + Bit0 n = Bit0 (m + n)" huffman@47108: "Bit0 m + Bit1 n = Bit1 (m + n)" huffman@47108: "Bit1 m + One = Bit0 (m + One)" huffman@47108: "Bit1 m + Bit0 n = Bit1 (m + n)" huffman@47108: "Bit1 m + Bit1 n = Bit0 (m + n + One)" huffman@47108: by (simp_all add: num_eq_iff nat_of_num_add) huffman@47108: huffman@47108: lemma mult_num_simps [simp, code]: huffman@47108: "m * One = m" huffman@47108: "One * n = n" huffman@47108: "Bit0 m * Bit0 n = Bit0 (Bit0 (m * n))" huffman@47108: "Bit0 m * Bit1 n = Bit0 (m * Bit1 n)" huffman@47108: "Bit1 m * Bit0 n = Bit0 (Bit1 m * n)" huffman@47108: "Bit1 m * Bit1 n = Bit1 (m + n + Bit0 (m * n))" huffman@47108: by (simp_all add: num_eq_iff nat_of_num_add webertj@49962: nat_of_num_mult distrib_right distrib_left) huffman@47108: huffman@47108: lemma eq_num_simps: huffman@47108: "One = One \ True" huffman@47108: "One = Bit0 n \ False" huffman@47108: "One = Bit1 n \ False" huffman@47108: "Bit0 m = One \ False" huffman@47108: "Bit1 m = One \ False" huffman@47108: "Bit0 m = Bit0 n \ m = n" huffman@47108: "Bit0 m = Bit1 n \ False" huffman@47108: "Bit1 m = Bit0 n \ False" huffman@47108: "Bit1 m = Bit1 n \ m = n" huffman@47108: by simp_all huffman@47108: huffman@47108: lemma le_num_simps [simp, code]: huffman@47108: "One \ n \ True" huffman@47108: "Bit0 m \ One \ False" huffman@47108: "Bit1 m \ One \ False" huffman@47108: "Bit0 m \ Bit0 n \ m \ n" huffman@47108: "Bit0 m \ Bit1 n \ m \ n" huffman@47108: "Bit1 m \ Bit1 n \ m \ n" huffman@47108: "Bit1 m \ Bit0 n \ m < n" huffman@47108: using nat_of_num_pos [of n] nat_of_num_pos [of m] huffman@47108: by (auto simp add: less_eq_num_def less_num_def) huffman@47108: huffman@47108: lemma less_num_simps [simp, code]: huffman@47108: "m < One \ False" huffman@47108: "One < Bit0 n \ True" huffman@47108: "One < Bit1 n \ True" huffman@47108: "Bit0 m < Bit0 n \ m < n" huffman@47108: "Bit0 m < Bit1 n \ m \ n" huffman@47108: "Bit1 m < Bit1 n \ m < n" huffman@47108: "Bit1 m < Bit0 n \ m < n" huffman@47108: using nat_of_num_pos [of n] nat_of_num_pos [of m] huffman@47108: by (auto simp add: less_eq_num_def less_num_def) huffman@47108: huffman@47108: text {* Rules using @{text One} and @{text inc} as constructors *} huffman@47108: huffman@47108: lemma add_One: "x + One = inc x" huffman@47108: by (simp add: num_eq_iff nat_of_num_add nat_of_num_inc) huffman@47108: huffman@47108: lemma add_One_commute: "One + n = n + One" huffman@47108: by (induct n) simp_all huffman@47108: huffman@47108: lemma add_inc: "x + inc y = inc (x + y)" huffman@47108: by (simp add: num_eq_iff nat_of_num_add nat_of_num_inc) huffman@47108: huffman@47108: lemma mult_inc: "x * inc y = x * y + x" huffman@47108: by (simp add: num_eq_iff nat_of_num_mult nat_of_num_add nat_of_num_inc) huffman@47108: huffman@47108: text {* The @{const num_of_nat} conversion *} huffman@47108: huffman@47108: lemma num_of_nat_One: huffman@47300: "n \ 1 \ num_of_nat n = One" huffman@47108: by (cases n) simp_all huffman@47108: huffman@47108: lemma num_of_nat_plus_distrib: huffman@47108: "0 < m \ 0 < n \ num_of_nat (m + n) = num_of_nat m + num_of_nat n" huffman@47108: by (induct n) (auto simp add: add_One add_One_commute add_inc) huffman@47108: huffman@47108: text {* A double-and-decrement function *} huffman@47108: huffman@47108: primrec BitM :: "num \ num" where huffman@47108: "BitM One = One" | huffman@47108: "BitM (Bit0 n) = Bit1 (BitM n)" | huffman@47108: "BitM (Bit1 n) = Bit1 (Bit0 n)" huffman@47108: huffman@47108: lemma BitM_plus_one: "BitM n + One = Bit0 n" huffman@47108: by (induct n) simp_all huffman@47108: huffman@47108: lemma one_plus_BitM: "One + BitM n = Bit0 n" huffman@47108: unfolding add_One_commute BitM_plus_one .. huffman@47108: huffman@47108: text {* Squaring and exponentiation *} huffman@47108: huffman@47108: primrec sqr :: "num \ num" where huffman@47108: "sqr One = One" | huffman@47108: "sqr (Bit0 n) = Bit0 (Bit0 (sqr n))" | huffman@47108: "sqr (Bit1 n) = Bit1 (Bit0 (sqr n + n))" huffman@47108: huffman@47108: primrec pow :: "num \ num \ num" where huffman@47108: "pow x One = x" | huffman@47108: "pow x (Bit0 y) = sqr (pow x y)" | huffman@47191: "pow x (Bit1 y) = sqr (pow x y) * x" huffman@47108: huffman@47108: lemma nat_of_num_sqr: "nat_of_num (sqr x) = nat_of_num x * nat_of_num x" huffman@47108: by (induct x, simp_all add: algebra_simps nat_of_num_add) huffman@47108: huffman@47108: lemma sqr_conv_mult: "sqr x = x * x" huffman@47108: by (simp add: num_eq_iff nat_of_num_sqr nat_of_num_mult) huffman@47108: huffman@47108: huffman@47211: subsection {* Binary numerals *} huffman@47108: huffman@47108: text {* huffman@47211: We embed binary representations into a generic algebraic huffman@47108: structure using @{text numeral}. huffman@47108: *} huffman@47108: huffman@47108: class numeral = one + semigroup_add huffman@47108: begin huffman@47108: huffman@47108: primrec numeral :: "num \ 'a" where huffman@47108: numeral_One: "numeral One = 1" | huffman@47108: numeral_Bit0: "numeral (Bit0 n) = numeral n + numeral n" | huffman@47108: numeral_Bit1: "numeral (Bit1 n) = numeral n + numeral n + 1" huffman@47108: haftmann@50817: lemma numeral_code [code]: haftmann@50817: "numeral One = 1" haftmann@50817: "numeral (Bit0 n) = (let m = numeral n in m + m)" haftmann@50817: "numeral (Bit1 n) = (let m = numeral n in m + m + 1)" haftmann@50817: by (simp_all add: Let_def) haftmann@50817: huffman@47108: lemma one_plus_numeral_commute: "1 + numeral x = numeral x + 1" huffman@47108: apply (induct x) huffman@47108: apply simp huffman@47108: apply (simp add: add_assoc [symmetric], simp add: add_assoc) huffman@47108: apply (simp add: add_assoc [symmetric], simp add: add_assoc) huffman@47108: done huffman@47108: huffman@47108: lemma numeral_inc: "numeral (inc x) = numeral x + 1" huffman@47108: proof (induct x) huffman@47108: case (Bit1 x) huffman@47108: have "numeral x + (1 + numeral x) + 1 = numeral x + (numeral x + 1) + 1" huffman@47108: by (simp only: one_plus_numeral_commute) huffman@47108: with Bit1 show ?case huffman@47108: by (simp add: add_assoc) huffman@47108: qed simp_all huffman@47108: huffman@47108: declare numeral.simps [simp del] huffman@47108: huffman@47108: abbreviation "Numeral1 \ numeral One" huffman@47108: huffman@47108: declare numeral_One [code_post] huffman@47108: huffman@47108: end huffman@47108: huffman@47108: text {* Negative numerals. *} huffman@47108: huffman@47108: class neg_numeral = numeral + group_add huffman@47108: begin huffman@47108: huffman@47108: definition neg_numeral :: "num \ 'a" where huffman@47108: "neg_numeral k = - numeral k" huffman@47108: huffman@47108: end huffman@47108: huffman@47108: text {* Numeral syntax. *} huffman@47108: huffman@47108: syntax huffman@47108: "_Numeral" :: "num_const \ 'a" ("_") huffman@47108: huffman@47108: parse_translation {* wenzelm@52143: let wenzelm@52143: fun num_of_int n = wenzelm@52143: if n > 0 then wenzelm@52143: (case IntInf.quotRem (n, 2) of wenzelm@52143: (0, 1) => Syntax.const @{const_name One} wenzelm@52143: | (n, 0) => Syntax.const @{const_name Bit0} $ num_of_int n wenzelm@52143: | (n, 1) => Syntax.const @{const_name Bit1} $ num_of_int n) wenzelm@52143: else raise Match wenzelm@52143: val pos = Syntax.const @{const_name numeral} wenzelm@52143: val neg = Syntax.const @{const_name neg_numeral} wenzelm@52143: val one = Syntax.const @{const_name Groups.one} wenzelm@52143: val zero = Syntax.const @{const_name Groups.zero} wenzelm@52143: fun numeral_tr [(c as Const (@{syntax_const "_constrain"}, _)) $ t $ u] = wenzelm@52143: c $ numeral_tr [t] $ u wenzelm@52143: | numeral_tr [Const (num, _)] = wenzelm@52143: let wenzelm@52143: val {value, ...} = Lexicon.read_xnum num; wenzelm@52143: in wenzelm@52143: if value = 0 then zero else wenzelm@52143: if value > 0 wenzelm@52143: then pos $ num_of_int value wenzelm@52143: else neg $ num_of_int (~value) wenzelm@52143: end wenzelm@52143: | numeral_tr ts = raise TERM ("numeral_tr", ts); wenzelm@52143: in [("_Numeral", K numeral_tr)] end huffman@47108: *} huffman@47108: wenzelm@52143: typed_print_translation {* wenzelm@52143: let wenzelm@52143: fun dest_num (Const (@{const_syntax Bit0}, _) $ n) = 2 * dest_num n wenzelm@52143: | dest_num (Const (@{const_syntax Bit1}, _) $ n) = 2 * dest_num n + 1 wenzelm@52143: | dest_num (Const (@{const_syntax One}, _)) = 1; wenzelm@52143: fun num_tr' sign ctxt T [n] = wenzelm@52143: let wenzelm@52143: val k = dest_num n; wenzelm@52187: val t' = wenzelm@52187: Syntax.const @{syntax_const "_Numeral"} $ wenzelm@52187: Syntax.free (sign ^ string_of_int k); wenzelm@52143: in wenzelm@52143: (case T of wenzelm@52143: Type (@{type_name fun}, [_, T']) => wenzelm@52210: if Printer.type_emphasis ctxt T' then wenzelm@52210: Syntax.const @{syntax_const "_constrain"} $ t' $ wenzelm@52210: Syntax_Phases.term_of_typ ctxt T' wenzelm@52210: else t' wenzelm@52187: | _ => if T = dummyT then t' else raise Match) wenzelm@52143: end; wenzelm@52143: in wenzelm@52143: [(@{const_syntax numeral}, num_tr' ""), wenzelm@52143: (@{const_syntax neg_numeral}, num_tr' "-")] wenzelm@52143: end huffman@47108: *} huffman@47108: wenzelm@48891: ML_file "Tools/numeral.ML" huffman@47228: huffman@47228: huffman@47108: subsection {* Class-specific numeral rules *} huffman@47108: huffman@47108: text {* huffman@47108: @{const numeral} is a morphism. huffman@47108: *} huffman@47108: huffman@47108: subsubsection {* Structures with addition: class @{text numeral} *} huffman@47108: huffman@47108: context numeral huffman@47108: begin huffman@47108: huffman@47108: lemma numeral_add: "numeral (m + n) = numeral m + numeral n" huffman@47108: by (induct n rule: num_induct) huffman@47108: (simp_all only: numeral_One add_One add_inc numeral_inc add_assoc) huffman@47108: huffman@47108: lemma numeral_plus_numeral: "numeral m + numeral n = numeral (m + n)" huffman@47108: by (rule numeral_add [symmetric]) huffman@47108: huffman@47108: lemma numeral_plus_one: "numeral n + 1 = numeral (n + One)" huffman@47108: using numeral_add [of n One] by (simp add: numeral_One) huffman@47108: huffman@47108: lemma one_plus_numeral: "1 + numeral n = numeral (One + n)" huffman@47108: using numeral_add [of One n] by (simp add: numeral_One) huffman@47108: huffman@47108: lemma one_add_one: "1 + 1 = 2" huffman@47108: using numeral_add [of One One] by (simp add: numeral_One) huffman@47108: huffman@47108: lemmas add_numeral_special = huffman@47108: numeral_plus_one one_plus_numeral one_add_one huffman@47108: huffman@47108: end huffman@47108: huffman@47108: subsubsection {* huffman@47108: Structures with negation: class @{text neg_numeral} huffman@47108: *} huffman@47108: huffman@47108: context neg_numeral huffman@47108: begin huffman@47108: huffman@47108: text {* Numerals form an abelian subgroup. *} huffman@47108: huffman@47108: inductive is_num :: "'a \ bool" where huffman@47108: "is_num 1" | huffman@47108: "is_num x \ is_num (- x)" | huffman@47108: "\is_num x; is_num y\ \ is_num (x + y)" huffman@47108: huffman@47108: lemma is_num_numeral: "is_num (numeral k)" huffman@47108: by (induct k, simp_all add: numeral.simps is_num.intros) huffman@47108: huffman@47108: lemma is_num_add_commute: huffman@47108: "\is_num x; is_num y\ \ x + y = y + x" huffman@47108: apply (induct x rule: is_num.induct) huffman@47108: apply (induct y rule: is_num.induct) huffman@47108: apply simp huffman@47108: apply (rule_tac a=x in add_left_imp_eq) huffman@47108: apply (rule_tac a=x in add_right_imp_eq) huffman@47108: apply (simp add: add_assoc minus_add_cancel) huffman@47108: apply (simp add: add_assoc [symmetric], simp add: add_assoc) huffman@47108: apply (rule_tac a=x in add_left_imp_eq) huffman@47108: apply (rule_tac a=x in add_right_imp_eq) haftmann@54230: apply (simp add: add_assoc) huffman@47108: apply (simp add: add_assoc, simp add: add_assoc [symmetric]) huffman@47108: done huffman@47108: huffman@47108: lemma is_num_add_left_commute: huffman@47108: "\is_num x; is_num y\ \ x + (y + z) = y + (x + z)" huffman@47108: by (simp only: add_assoc [symmetric] is_num_add_commute) huffman@47108: huffman@47108: lemmas is_num_normalize = huffman@47108: add_assoc is_num_add_commute is_num_add_left_commute huffman@47108: is_num.intros is_num_numeral haftmann@54230: minus_add huffman@47108: huffman@47108: definition dbl :: "'a \ 'a" where "dbl x = x + x" huffman@47108: definition dbl_inc :: "'a \ 'a" where "dbl_inc x = x + x + 1" huffman@47108: definition dbl_dec :: "'a \ 'a" where "dbl_dec x = x + x - 1" huffman@47108: huffman@47108: definition sub :: "num \ num \ 'a" where huffman@47108: "sub k l = numeral k - numeral l" huffman@47108: huffman@47108: lemma numeral_BitM: "numeral (BitM n) = numeral (Bit0 n) - 1" huffman@47108: by (simp only: BitM_plus_one [symmetric] numeral_add numeral_One eq_diff_eq) huffman@47108: huffman@47108: lemma dbl_simps [simp]: huffman@47108: "dbl (neg_numeral k) = neg_numeral (Bit0 k)" huffman@47108: "dbl 0 = 0" huffman@47108: "dbl 1 = 2" huffman@47108: "dbl (numeral k) = numeral (Bit0 k)" haftmann@54230: by (simp_all add: dbl_def neg_numeral_def numeral.simps minus_add) huffman@47108: huffman@47108: lemma dbl_inc_simps [simp]: huffman@47108: "dbl_inc (neg_numeral k) = neg_numeral (BitM k)" huffman@47108: "dbl_inc 0 = 1" huffman@47108: "dbl_inc 1 = 3" huffman@47108: "dbl_inc (numeral k) = numeral (Bit1 k)" haftmann@54230: by (simp_all add: dbl_inc_def neg_numeral_def numeral.simps numeral_BitM is_num_normalize algebra_simps del: add_uminus_conv_diff) huffman@47108: huffman@47108: lemma dbl_dec_simps [simp]: huffman@47108: "dbl_dec (neg_numeral k) = neg_numeral (Bit1 k)" huffman@47108: "dbl_dec 0 = -1" huffman@47108: "dbl_dec 1 = 1" huffman@47108: "dbl_dec (numeral k) = numeral (BitM k)" haftmann@54230: by (simp_all add: dbl_dec_def neg_numeral_def numeral.simps numeral_BitM is_num_normalize) huffman@47108: huffman@47108: lemma sub_num_simps [simp]: huffman@47108: "sub One One = 0" huffman@47108: "sub One (Bit0 l) = neg_numeral (BitM l)" huffman@47108: "sub One (Bit1 l) = neg_numeral (Bit0 l)" huffman@47108: "sub (Bit0 k) One = numeral (BitM k)" huffman@47108: "sub (Bit1 k) One = numeral (Bit0 k)" huffman@47108: "sub (Bit0 k) (Bit0 l) = dbl (sub k l)" huffman@47108: "sub (Bit0 k) (Bit1 l) = dbl_dec (sub k l)" huffman@47108: "sub (Bit1 k) (Bit0 l) = dbl_inc (sub k l)" huffman@47108: "sub (Bit1 k) (Bit1 l) = dbl (sub k l)" haftmann@54230: by (simp_all add: dbl_def dbl_dec_def dbl_inc_def sub_def neg_numeral_def numeral.simps haftmann@54230: numeral_BitM is_num_normalize del: add_uminus_conv_diff add: diff_conv_add_uminus) huffman@47108: huffman@47108: lemma add_neg_numeral_simps: huffman@47108: "numeral m + neg_numeral n = sub m n" huffman@47108: "neg_numeral m + numeral n = sub n m" huffman@47108: "neg_numeral m + neg_numeral n = neg_numeral (m + n)" haftmann@54230: by (simp_all add: sub_def neg_numeral_def numeral_add numeral.simps is_num_normalize haftmann@54230: del: add_uminus_conv_diff add: diff_conv_add_uminus) huffman@47108: huffman@47108: lemma add_neg_numeral_special: huffman@47108: "1 + neg_numeral m = sub One m" huffman@47108: "neg_numeral m + 1 = sub One m" haftmann@54230: by (simp_all add: sub_def neg_numeral_def numeral_add numeral.simps is_num_normalize) huffman@47108: huffman@47108: lemma diff_numeral_simps: huffman@47108: "numeral m - numeral n = sub m n" huffman@47108: "numeral m - neg_numeral n = numeral (m + n)" huffman@47108: "neg_numeral m - numeral n = neg_numeral (m + n)" huffman@47108: "neg_numeral m - neg_numeral n = sub n m" haftmann@54230: by (simp_all add: neg_numeral_def sub_def numeral_add numeral.simps is_num_normalize haftmann@54230: del: add_uminus_conv_diff add: diff_conv_add_uminus) huffman@47108: huffman@47108: lemma diff_numeral_special: huffman@47108: "1 - numeral n = sub One n" huffman@47108: "1 - neg_numeral n = numeral (One + n)" huffman@47108: "numeral m - 1 = sub m One" huffman@47108: "neg_numeral m - 1 = neg_numeral (m + One)" haftmann@54230: by (simp_all add: neg_numeral_def sub_def numeral_add numeral.simps add: is_num_normalize) huffman@47108: huffman@47108: lemma minus_one: "- 1 = -1" huffman@47108: unfolding neg_numeral_def numeral.simps .. huffman@47108: huffman@47108: lemma minus_numeral: "- numeral n = neg_numeral n" huffman@47108: unfolding neg_numeral_def .. huffman@47108: huffman@47108: lemma minus_neg_numeral: "- neg_numeral n = numeral n" huffman@47108: unfolding neg_numeral_def by simp huffman@47108: huffman@47108: lemmas minus_numeral_simps [simp] = huffman@47108: minus_one minus_numeral minus_neg_numeral huffman@47108: huffman@47108: end huffman@47108: huffman@47108: subsubsection {* huffman@47108: Structures with multiplication: class @{text semiring_numeral} huffman@47108: *} huffman@47108: huffman@47108: class semiring_numeral = semiring + monoid_mult huffman@47108: begin huffman@47108: huffman@47108: subclass numeral .. huffman@47108: huffman@47108: lemma numeral_mult: "numeral (m * n) = numeral m * numeral n" huffman@47108: apply (induct n rule: num_induct) huffman@47108: apply (simp add: numeral_One) webertj@49962: apply (simp add: mult_inc numeral_inc numeral_add distrib_left) huffman@47108: done huffman@47108: huffman@47108: lemma numeral_times_numeral: "numeral m * numeral n = numeral (m * n)" huffman@47108: by (rule numeral_mult [symmetric]) huffman@47108: haftmann@53064: lemma mult_2: "2 * z = z + z" haftmann@53064: unfolding one_add_one [symmetric] distrib_right by simp haftmann@53064: haftmann@53064: lemma mult_2_right: "z * 2 = z + z" haftmann@53064: unfolding one_add_one [symmetric] distrib_left by simp haftmann@53064: huffman@47108: end huffman@47108: huffman@47108: subsubsection {* huffman@47108: Structures with a zero: class @{text semiring_1} huffman@47108: *} huffman@47108: huffman@47108: context semiring_1 huffman@47108: begin huffman@47108: huffman@47108: subclass semiring_numeral .. huffman@47108: huffman@47108: lemma of_nat_numeral [simp]: "of_nat (numeral n) = numeral n" huffman@47108: by (induct n, huffman@47108: simp_all only: numeral.simps numeral_class.numeral.simps of_nat_add of_nat_1) huffman@47108: huffman@47108: end huffman@47108: haftmann@51143: lemma nat_of_num_numeral [code_abbrev]: haftmann@51143: "nat_of_num = numeral" huffman@47108: proof huffman@47108: fix n huffman@47108: have "numeral n = nat_of_num n" huffman@47108: by (induct n) (simp_all add: numeral.simps) huffman@47108: then show "nat_of_num n = numeral n" by simp huffman@47108: qed huffman@47108: haftmann@51143: lemma nat_of_num_code [code]: haftmann@51143: "nat_of_num One = 1" haftmann@51143: "nat_of_num (Bit0 n) = (let m = nat_of_num n in m + m)" haftmann@51143: "nat_of_num (Bit1 n) = (let m = nat_of_num n in Suc (m + m))" haftmann@51143: by (simp_all add: Let_def) haftmann@51143: huffman@47108: subsubsection {* huffman@47108: Equality: class @{text semiring_char_0} huffman@47108: *} huffman@47108: huffman@47108: context semiring_char_0 huffman@47108: begin huffman@47108: huffman@47108: lemma numeral_eq_iff: "numeral m = numeral n \ m = n" huffman@47108: unfolding of_nat_numeral [symmetric] nat_of_num_numeral [symmetric] huffman@47108: of_nat_eq_iff num_eq_iff .. huffman@47108: huffman@47108: lemma numeral_eq_one_iff: "numeral n = 1 \ n = One" huffman@47108: by (rule numeral_eq_iff [of n One, unfolded numeral_One]) huffman@47108: huffman@47108: lemma one_eq_numeral_iff: "1 = numeral n \ One = n" huffman@47108: by (rule numeral_eq_iff [of One n, unfolded numeral_One]) huffman@47108: huffman@47108: lemma numeral_neq_zero: "numeral n \ 0" huffman@47108: unfolding of_nat_numeral [symmetric] nat_of_num_numeral [symmetric] huffman@47108: by (simp add: nat_of_num_pos) huffman@47108: huffman@47108: lemma zero_neq_numeral: "0 \ numeral n" huffman@47108: unfolding eq_commute [of 0] by (rule numeral_neq_zero) huffman@47108: huffman@47108: lemmas eq_numeral_simps [simp] = huffman@47108: numeral_eq_iff huffman@47108: numeral_eq_one_iff huffman@47108: one_eq_numeral_iff huffman@47108: numeral_neq_zero huffman@47108: zero_neq_numeral huffman@47108: huffman@47108: end huffman@47108: huffman@47108: subsubsection {* huffman@47108: Comparisons: class @{text linordered_semidom} huffman@47108: *} huffman@47108: huffman@47108: text {* Could be perhaps more general than here. *} huffman@47108: huffman@47108: context linordered_semidom huffman@47108: begin huffman@47108: huffman@47108: lemma numeral_le_iff: "numeral m \ numeral n \ m \ n" huffman@47108: proof - huffman@47108: have "of_nat (numeral m) \ of_nat (numeral n) \ m \ n" huffman@47108: unfolding less_eq_num_def nat_of_num_numeral of_nat_le_iff .. huffman@47108: then show ?thesis by simp huffman@47108: qed huffman@47108: huffman@47108: lemma one_le_numeral: "1 \ numeral n" huffman@47108: using numeral_le_iff [of One n] by (simp add: numeral_One) huffman@47108: huffman@47108: lemma numeral_le_one_iff: "numeral n \ 1 \ n \ One" huffman@47108: using numeral_le_iff [of n One] by (simp add: numeral_One) huffman@47108: huffman@47108: lemma numeral_less_iff: "numeral m < numeral n \ m < n" huffman@47108: proof - huffman@47108: have "of_nat (numeral m) < of_nat (numeral n) \ m < n" huffman@47108: unfolding less_num_def nat_of_num_numeral of_nat_less_iff .. huffman@47108: then show ?thesis by simp huffman@47108: qed huffman@47108: huffman@47108: lemma not_numeral_less_one: "\ numeral n < 1" huffman@47108: using numeral_less_iff [of n One] by (simp add: numeral_One) huffman@47108: huffman@47108: lemma one_less_numeral_iff: "1 < numeral n \ One < n" huffman@47108: using numeral_less_iff [of One n] by (simp add: numeral_One) huffman@47108: huffman@47108: lemma zero_le_numeral: "0 \ numeral n" huffman@47108: by (induct n) (simp_all add: numeral.simps) huffman@47108: huffman@47108: lemma zero_less_numeral: "0 < numeral n" huffman@47108: by (induct n) (simp_all add: numeral.simps add_pos_pos) huffman@47108: huffman@47108: lemma not_numeral_le_zero: "\ numeral n \ 0" huffman@47108: by (simp add: not_le zero_less_numeral) huffman@47108: huffman@47108: lemma not_numeral_less_zero: "\ numeral n < 0" huffman@47108: by (simp add: not_less zero_le_numeral) huffman@47108: huffman@47108: lemmas le_numeral_extra = huffman@47108: zero_le_one not_one_le_zero huffman@47108: order_refl [of 0] order_refl [of 1] huffman@47108: huffman@47108: lemmas less_numeral_extra = huffman@47108: zero_less_one not_one_less_zero huffman@47108: less_irrefl [of 0] less_irrefl [of 1] huffman@47108: huffman@47108: lemmas le_numeral_simps [simp] = huffman@47108: numeral_le_iff huffman@47108: one_le_numeral huffman@47108: numeral_le_one_iff huffman@47108: zero_le_numeral huffman@47108: not_numeral_le_zero huffman@47108: huffman@47108: lemmas less_numeral_simps [simp] = huffman@47108: numeral_less_iff huffman@47108: one_less_numeral_iff huffman@47108: not_numeral_less_one huffman@47108: zero_less_numeral huffman@47108: not_numeral_less_zero huffman@47108: huffman@47108: end huffman@47108: huffman@47108: subsubsection {* huffman@47108: Multiplication and negation: class @{text ring_1} huffman@47108: *} huffman@47108: huffman@47108: context ring_1 huffman@47108: begin huffman@47108: huffman@47108: subclass neg_numeral .. huffman@47108: huffman@47108: lemma mult_neg_numeral_simps: huffman@47108: "neg_numeral m * neg_numeral n = numeral (m * n)" huffman@47108: "neg_numeral m * numeral n = neg_numeral (m * n)" huffman@47108: "numeral m * neg_numeral n = neg_numeral (m * n)" huffman@47108: unfolding neg_numeral_def mult_minus_left mult_minus_right huffman@47108: by (simp_all only: minus_minus numeral_mult) huffman@47108: huffman@47108: lemma mult_minus1 [simp]: "-1 * z = - z" huffman@47108: unfolding neg_numeral_def numeral.simps mult_minus_left by simp huffman@47108: huffman@47108: lemma mult_minus1_right [simp]: "z * -1 = - z" huffman@47108: unfolding neg_numeral_def numeral.simps mult_minus_right by simp huffman@47108: huffman@47108: end huffman@47108: huffman@47108: subsubsection {* huffman@47108: Equality using @{text iszero} for rings with non-zero characteristic huffman@47108: *} huffman@47108: huffman@47108: context ring_1 huffman@47108: begin huffman@47108: huffman@47108: definition iszero :: "'a \ bool" huffman@47108: where "iszero z \ z = 0" huffman@47108: huffman@47108: lemma iszero_0 [simp]: "iszero 0" huffman@47108: by (simp add: iszero_def) huffman@47108: huffman@47108: lemma not_iszero_1 [simp]: "\ iszero 1" huffman@47108: by (simp add: iszero_def) huffman@47108: huffman@47108: lemma not_iszero_Numeral1: "\ iszero Numeral1" huffman@47108: by (simp add: numeral_One) huffman@47108: huffman@47108: lemma iszero_neg_numeral [simp]: huffman@47108: "iszero (neg_numeral w) \ iszero (numeral w)" huffman@47108: unfolding iszero_def neg_numeral_def huffman@47108: by (rule neg_equal_0_iff_equal) huffman@47108: huffman@47108: lemma eq_iff_iszero_diff: "x = y \ iszero (x - y)" huffman@47108: unfolding iszero_def by (rule eq_iff_diff_eq_0) huffman@47108: huffman@47108: text {* The @{text "eq_numeral_iff_iszero"} lemmas are not declared huffman@47108: @{text "[simp]"} by default, because for rings of characteristic zero, huffman@47108: better simp rules are possible. For a type like integers mod @{text huffman@47108: "n"}, type-instantiated versions of these rules should be added to the huffman@47108: simplifier, along with a type-specific rule for deciding propositions huffman@47108: of the form @{text "iszero (numeral w)"}. huffman@47108: huffman@47108: bh: Maybe it would not be so bad to just declare these as simp huffman@47108: rules anyway? I should test whether these rules take precedence over huffman@47108: the @{text "ring_char_0"} rules in the simplifier. huffman@47108: *} huffman@47108: huffman@47108: lemma eq_numeral_iff_iszero: huffman@47108: "numeral x = numeral y \ iszero (sub x y)" huffman@47108: "numeral x = neg_numeral y \ iszero (numeral (x + y))" huffman@47108: "neg_numeral x = numeral y \ iszero (numeral (x + y))" huffman@47108: "neg_numeral x = neg_numeral y \ iszero (sub y x)" huffman@47108: "numeral x = 1 \ iszero (sub x One)" huffman@47108: "1 = numeral y \ iszero (sub One y)" huffman@47108: "neg_numeral x = 1 \ iszero (numeral (x + One))" huffman@47108: "1 = neg_numeral y \ iszero (numeral (One + y))" huffman@47108: "numeral x = 0 \ iszero (numeral x)" huffman@47108: "0 = numeral y \ iszero (numeral y)" huffman@47108: "neg_numeral x = 0 \ iszero (numeral x)" huffman@47108: "0 = neg_numeral y \ iszero (numeral y)" huffman@47108: unfolding eq_iff_iszero_diff diff_numeral_simps diff_numeral_special huffman@47108: by simp_all huffman@47108: huffman@47108: end huffman@47108: huffman@47108: subsubsection {* huffman@47108: Equality and negation: class @{text ring_char_0} huffman@47108: *} huffman@47108: huffman@47108: class ring_char_0 = ring_1 + semiring_char_0 huffman@47108: begin huffman@47108: huffman@47108: lemma not_iszero_numeral [simp]: "\ iszero (numeral w)" huffman@47108: by (simp add: iszero_def) huffman@47108: huffman@47108: lemma neg_numeral_eq_iff: "neg_numeral m = neg_numeral n \ m = n" huffman@47108: by (simp only: neg_numeral_def neg_equal_iff_equal numeral_eq_iff) huffman@47108: huffman@47108: lemma numeral_neq_neg_numeral: "numeral m \ neg_numeral n" huffman@47108: unfolding neg_numeral_def eq_neg_iff_add_eq_0 huffman@47108: by (simp add: numeral_plus_numeral) huffman@47108: huffman@47108: lemma neg_numeral_neq_numeral: "neg_numeral m \ numeral n" huffman@47108: by (rule numeral_neq_neg_numeral [symmetric]) huffman@47108: huffman@47108: lemma zero_neq_neg_numeral: "0 \ neg_numeral n" huffman@47108: unfolding neg_numeral_def neg_0_equal_iff_equal by simp huffman@47108: huffman@47108: lemma neg_numeral_neq_zero: "neg_numeral n \ 0" huffman@47108: unfolding neg_numeral_def neg_equal_0_iff_equal by simp huffman@47108: huffman@47108: lemma one_neq_neg_numeral: "1 \ neg_numeral n" huffman@47108: using numeral_neq_neg_numeral [of One n] by (simp add: numeral_One) huffman@47108: huffman@47108: lemma neg_numeral_neq_one: "neg_numeral n \ 1" huffman@47108: using neg_numeral_neq_numeral [of n One] by (simp add: numeral_One) huffman@47108: huffman@47108: lemmas eq_neg_numeral_simps [simp] = huffman@47108: neg_numeral_eq_iff huffman@47108: numeral_neq_neg_numeral neg_numeral_neq_numeral huffman@47108: one_neq_neg_numeral neg_numeral_neq_one huffman@47108: zero_neq_neg_numeral neg_numeral_neq_zero huffman@47108: huffman@47108: end huffman@47108: huffman@47108: subsubsection {* huffman@47108: Structures with negation and order: class @{text linordered_idom} huffman@47108: *} huffman@47108: huffman@47108: context linordered_idom huffman@47108: begin huffman@47108: huffman@47108: subclass ring_char_0 .. huffman@47108: huffman@47108: lemma neg_numeral_le_iff: "neg_numeral m \ neg_numeral n \ n \ m" huffman@47108: by (simp only: neg_numeral_def neg_le_iff_le numeral_le_iff) huffman@47108: huffman@47108: lemma neg_numeral_less_iff: "neg_numeral m < neg_numeral n \ n < m" huffman@47108: by (simp only: neg_numeral_def neg_less_iff_less numeral_less_iff) huffman@47108: huffman@47108: lemma neg_numeral_less_zero: "neg_numeral n < 0" huffman@47108: by (simp only: neg_numeral_def neg_less_0_iff_less zero_less_numeral) huffman@47108: huffman@47108: lemma neg_numeral_le_zero: "neg_numeral n \ 0" huffman@47108: by (simp only: neg_numeral_def neg_le_0_iff_le zero_le_numeral) huffman@47108: huffman@47108: lemma not_zero_less_neg_numeral: "\ 0 < neg_numeral n" huffman@47108: by (simp only: not_less neg_numeral_le_zero) huffman@47108: huffman@47108: lemma not_zero_le_neg_numeral: "\ 0 \ neg_numeral n" huffman@47108: by (simp only: not_le neg_numeral_less_zero) huffman@47108: huffman@47108: lemma neg_numeral_less_numeral: "neg_numeral m < numeral n" huffman@47108: using neg_numeral_less_zero zero_less_numeral by (rule less_trans) huffman@47108: huffman@47108: lemma neg_numeral_le_numeral: "neg_numeral m \ numeral n" huffman@47108: by (simp only: less_imp_le neg_numeral_less_numeral) huffman@47108: huffman@47108: lemma not_numeral_less_neg_numeral: "\ numeral m < neg_numeral n" huffman@47108: by (simp only: not_less neg_numeral_le_numeral) huffman@47108: huffman@47108: lemma not_numeral_le_neg_numeral: "\ numeral m \ neg_numeral n" huffman@47108: by (simp only: not_le neg_numeral_less_numeral) huffman@47108: huffman@47108: lemma neg_numeral_less_one: "neg_numeral m < 1" huffman@47108: by (rule neg_numeral_less_numeral [of m One, unfolded numeral_One]) huffman@47108: huffman@47108: lemma neg_numeral_le_one: "neg_numeral m \ 1" huffman@47108: by (rule neg_numeral_le_numeral [of m One, unfolded numeral_One]) huffman@47108: huffman@47108: lemma not_one_less_neg_numeral: "\ 1 < neg_numeral m" huffman@47108: by (simp only: not_less neg_numeral_le_one) huffman@47108: huffman@47108: lemma not_one_le_neg_numeral: "\ 1 \ neg_numeral m" huffman@47108: by (simp only: not_le neg_numeral_less_one) huffman@47108: huffman@47108: lemma sub_non_negative: huffman@47108: "sub n m \ 0 \ n \ m" huffman@47108: by (simp only: sub_def le_diff_eq) simp huffman@47108: huffman@47108: lemma sub_positive: huffman@47108: "sub n m > 0 \ n > m" huffman@47108: by (simp only: sub_def less_diff_eq) simp huffman@47108: huffman@47108: lemma sub_non_positive: huffman@47108: "sub n m \ 0 \ n \ m" huffman@47108: by (simp only: sub_def diff_le_eq) simp huffman@47108: huffman@47108: lemma sub_negative: huffman@47108: "sub n m < 0 \ n < m" huffman@47108: by (simp only: sub_def diff_less_eq) simp huffman@47108: huffman@47108: lemmas le_neg_numeral_simps [simp] = huffman@47108: neg_numeral_le_iff huffman@47108: neg_numeral_le_numeral not_numeral_le_neg_numeral huffman@47108: neg_numeral_le_zero not_zero_le_neg_numeral huffman@47108: neg_numeral_le_one not_one_le_neg_numeral huffman@47108: huffman@47108: lemmas less_neg_numeral_simps [simp] = huffman@47108: neg_numeral_less_iff huffman@47108: neg_numeral_less_numeral not_numeral_less_neg_numeral huffman@47108: neg_numeral_less_zero not_zero_less_neg_numeral huffman@47108: neg_numeral_less_one not_one_less_neg_numeral huffman@47108: huffman@47108: lemma abs_numeral [simp]: "abs (numeral n) = numeral n" huffman@47108: by simp huffman@47108: huffman@47108: lemma abs_neg_numeral [simp]: "abs (neg_numeral n) = numeral n" huffman@47108: by (simp only: neg_numeral_def abs_minus_cancel abs_numeral) huffman@47108: huffman@47108: end huffman@47108: huffman@47108: subsubsection {* huffman@47108: Natural numbers huffman@47108: *} huffman@47108: huffman@47299: lemma Suc_1 [simp]: "Suc 1 = 2" huffman@47299: unfolding Suc_eq_plus1 by (rule one_add_one) huffman@47299: huffman@47108: lemma Suc_numeral [simp]: "Suc (numeral n) = numeral (n + One)" huffman@47299: unfolding Suc_eq_plus1 by (rule numeral_plus_one) huffman@47108: huffman@47209: definition pred_numeral :: "num \ nat" huffman@47209: where [code del]: "pred_numeral k = numeral k - 1" huffman@47209: huffman@47209: lemma numeral_eq_Suc: "numeral k = Suc (pred_numeral k)" huffman@47209: unfolding pred_numeral_def by simp huffman@47209: huffman@47220: lemma eval_nat_numeral: huffman@47108: "numeral One = Suc 0" huffman@47108: "numeral (Bit0 n) = Suc (numeral (BitM n))" huffman@47108: "numeral (Bit1 n) = Suc (numeral (Bit0 n))" huffman@47108: by (simp_all add: numeral.simps BitM_plus_one) huffman@47108: huffman@47209: lemma pred_numeral_simps [simp]: huffman@47300: "pred_numeral One = 0" huffman@47300: "pred_numeral (Bit0 k) = numeral (BitM k)" huffman@47300: "pred_numeral (Bit1 k) = numeral (Bit0 k)" huffman@47220: unfolding pred_numeral_def eval_nat_numeral huffman@47209: by (simp_all only: diff_Suc_Suc diff_0) huffman@47209: huffman@47192: lemma numeral_2_eq_2: "2 = Suc (Suc 0)" huffman@47220: by (simp add: eval_nat_numeral) huffman@47192: huffman@47192: lemma numeral_3_eq_3: "3 = Suc (Suc (Suc 0))" huffman@47220: by (simp add: eval_nat_numeral) huffman@47192: huffman@47207: lemma numeral_1_eq_Suc_0: "Numeral1 = Suc 0" huffman@47207: by (simp only: numeral_One One_nat_def) huffman@47207: huffman@47207: lemma Suc_nat_number_of_add: huffman@47300: "Suc (numeral v + n) = numeral (v + One) + n" huffman@47207: by simp huffman@47207: huffman@47207: (*Maps #n to n for n = 1, 2*) huffman@47207: lemmas numerals = numeral_One [where 'a=nat] numeral_2_eq_2 huffman@47207: huffman@47209: text {* Comparisons involving @{term Suc}. *} huffman@47209: huffman@47209: lemma eq_numeral_Suc [simp]: "numeral k = Suc n \ pred_numeral k = n" huffman@47209: by (simp add: numeral_eq_Suc) huffman@47209: huffman@47209: lemma Suc_eq_numeral [simp]: "Suc n = numeral k \ n = pred_numeral k" huffman@47209: by (simp add: numeral_eq_Suc) huffman@47209: huffman@47209: lemma less_numeral_Suc [simp]: "numeral k < Suc n \ pred_numeral k < n" huffman@47209: by (simp add: numeral_eq_Suc) huffman@47209: huffman@47209: lemma less_Suc_numeral [simp]: "Suc n < numeral k \ n < pred_numeral k" huffman@47209: by (simp add: numeral_eq_Suc) huffman@47209: huffman@47209: lemma le_numeral_Suc [simp]: "numeral k \ Suc n \ pred_numeral k \ n" huffman@47209: by (simp add: numeral_eq_Suc) huffman@47209: huffman@47209: lemma le_Suc_numeral [simp]: "Suc n \ numeral k \ n \ pred_numeral k" huffman@47209: by (simp add: numeral_eq_Suc) huffman@47209: huffman@47218: lemma diff_Suc_numeral [simp]: "Suc n - numeral k = n - pred_numeral k" huffman@47218: by (simp add: numeral_eq_Suc) huffman@47218: huffman@47218: lemma diff_numeral_Suc [simp]: "numeral k - Suc n = pred_numeral k - n" huffman@47218: by (simp add: numeral_eq_Suc) huffman@47218: huffman@47209: lemma max_Suc_numeral [simp]: huffman@47209: "max (Suc n) (numeral k) = Suc (max n (pred_numeral k))" huffman@47209: by (simp add: numeral_eq_Suc) huffman@47209: huffman@47209: lemma max_numeral_Suc [simp]: huffman@47209: "max (numeral k) (Suc n) = Suc (max (pred_numeral k) n)" huffman@47209: by (simp add: numeral_eq_Suc) huffman@47209: huffman@47209: lemma min_Suc_numeral [simp]: huffman@47209: "min (Suc n) (numeral k) = Suc (min n (pred_numeral k))" huffman@47209: by (simp add: numeral_eq_Suc) huffman@47209: huffman@47209: lemma min_numeral_Suc [simp]: huffman@47209: "min (numeral k) (Suc n) = Suc (min (pred_numeral k) n)" huffman@47209: by (simp add: numeral_eq_Suc) huffman@47209: huffman@47216: text {* For @{term nat_case} and @{term nat_rec}. *} huffman@47216: huffman@47216: lemma nat_case_numeral [simp]: huffman@47216: "nat_case a f (numeral v) = (let pv = pred_numeral v in f pv)" huffman@47216: by (simp add: numeral_eq_Suc) huffman@47216: huffman@47216: lemma nat_case_add_eq_if [simp]: huffman@47216: "nat_case a f ((numeral v) + n) = (let pv = pred_numeral v in f (pv + n))" huffman@47216: by (simp add: numeral_eq_Suc) huffman@47216: huffman@47216: lemma nat_rec_numeral [simp]: huffman@47216: "nat_rec a f (numeral v) = huffman@47216: (let pv = pred_numeral v in f pv (nat_rec a f pv))" huffman@47216: by (simp add: numeral_eq_Suc Let_def) huffman@47216: huffman@47216: lemma nat_rec_add_eq_if [simp]: huffman@47216: "nat_rec a f (numeral v + n) = huffman@47216: (let pv = pred_numeral v in f (pv + n) (nat_rec a f (pv + n)))" huffman@47216: by (simp add: numeral_eq_Suc Let_def) huffman@47216: huffman@47255: text {* Case analysis on @{term "n < 2"} *} huffman@47255: huffman@47255: lemma less_2_cases: "n < 2 \ n = 0 \ n = Suc 0" huffman@47255: by (auto simp add: numeral_2_eq_2) huffman@47255: huffman@47255: text {* Removal of Small Numerals: 0, 1 and (in additive positions) 2 *} huffman@47255: text {* bh: Are these rules really a good idea? *} huffman@47255: huffman@47255: lemma add_2_eq_Suc [simp]: "2 + n = Suc (Suc n)" huffman@47255: by simp huffman@47255: huffman@47255: lemma add_2_eq_Suc' [simp]: "n + 2 = Suc (Suc n)" huffman@47255: by simp huffman@47255: huffman@47255: text {* Can be used to eliminate long strings of Sucs, but not by default. *} huffman@47255: huffman@47255: lemma Suc3_eq_add_3: "Suc (Suc (Suc n)) = 3 + n" huffman@47255: by simp huffman@47255: huffman@47255: lemmas nat_1_add_1 = one_add_one [where 'a=nat] (* legacy *) huffman@47255: huffman@47108: huffman@47108: subsection {* Numeral equations as default simplification rules *} huffman@47108: huffman@47108: declare (in numeral) numeral_One [simp] huffman@47108: declare (in numeral) numeral_plus_numeral [simp] huffman@47108: declare (in numeral) add_numeral_special [simp] huffman@47108: declare (in neg_numeral) add_neg_numeral_simps [simp] huffman@47108: declare (in neg_numeral) add_neg_numeral_special [simp] huffman@47108: declare (in neg_numeral) diff_numeral_simps [simp] huffman@47108: declare (in neg_numeral) diff_numeral_special [simp] huffman@47108: declare (in semiring_numeral) numeral_times_numeral [simp] huffman@47108: declare (in ring_1) mult_neg_numeral_simps [simp] huffman@47108: huffman@47108: subsection {* Setting up simprocs *} huffman@47108: huffman@47108: lemma mult_numeral_1: "Numeral1 * a = (a::'a::semiring_numeral)" huffman@47108: by simp huffman@47108: huffman@47108: lemma mult_numeral_1_right: "a * Numeral1 = (a::'a::semiring_numeral)" huffman@47108: by simp huffman@47108: huffman@47108: lemma divide_numeral_1: "a / Numeral1 = (a::'a::field)" huffman@47108: by simp huffman@47108: huffman@47108: lemma inverse_numeral_1: huffman@47108: "inverse Numeral1 = (Numeral1::'a::division_ring)" huffman@47108: by simp huffman@47108: huffman@47211: text{*Theorem lists for the cancellation simprocs. The use of a binary huffman@47108: numeral for 1 reduces the number of special cases.*} huffman@47108: huffman@47108: lemmas mult_1s = huffman@47108: mult_numeral_1 mult_numeral_1_right huffman@47108: mult_minus1 mult_minus1_right huffman@47108: huffman@47226: setup {* huffman@47226: Reorient_Proc.add huffman@47226: (fn Const (@{const_name numeral}, _) $ _ => true huffman@47226: | Const (@{const_name neg_numeral}, _) $ _ => true huffman@47226: | _ => false) huffman@47226: *} huffman@47226: huffman@47226: simproc_setup reorient_numeral huffman@47226: ("numeral w = x" | "neg_numeral w = y") = Reorient_Proc.proc huffman@47226: huffman@47108: huffman@47108: subsubsection {* Simplification of arithmetic operations on integer constants. *} huffman@47108: huffman@47108: lemmas arith_special = (* already declared simp above *) huffman@47108: add_numeral_special add_neg_numeral_special huffman@47108: diff_numeral_special minus_one huffman@47108: huffman@47108: (* rules already in simpset *) huffman@47108: lemmas arith_extra_simps = huffman@47108: numeral_plus_numeral add_neg_numeral_simps add_0_left add_0_right huffman@47108: minus_numeral minus_neg_numeral minus_zero minus_one huffman@47108: diff_numeral_simps diff_0 diff_0_right huffman@47108: numeral_times_numeral mult_neg_numeral_simps huffman@47108: mult_zero_left mult_zero_right huffman@47108: abs_numeral abs_neg_numeral huffman@47108: huffman@47108: text {* huffman@47108: For making a minimal simpset, one must include these default simprules. huffman@47108: Also include @{text simp_thms}. huffman@47108: *} huffman@47108: huffman@47108: lemmas arith_simps = huffman@47108: add_num_simps mult_num_simps sub_num_simps huffman@47108: BitM.simps dbl_simps dbl_inc_simps dbl_dec_simps huffman@47108: abs_zero abs_one arith_extra_simps huffman@47108: huffman@47108: text {* Simplification of relational operations *} huffman@47108: huffman@47108: lemmas eq_numeral_extra = huffman@47108: zero_neq_one one_neq_zero huffman@47108: huffman@47108: lemmas rel_simps = huffman@47108: le_num_simps less_num_simps eq_num_simps huffman@47108: le_numeral_simps le_neg_numeral_simps le_numeral_extra huffman@47108: less_numeral_simps less_neg_numeral_simps less_numeral_extra huffman@47108: eq_numeral_simps eq_neg_numeral_simps eq_numeral_extra huffman@47108: huffman@47108: huffman@47108: subsubsection {* Simplification of arithmetic when nested to the right. *} huffman@47108: huffman@47108: lemma add_numeral_left [simp]: huffman@47108: "numeral v + (numeral w + z) = (numeral(v + w) + z)" huffman@47108: by (simp_all add: add_assoc [symmetric]) huffman@47108: huffman@47108: lemma add_neg_numeral_left [simp]: huffman@47108: "numeral v + (neg_numeral w + y) = (sub v w + y)" huffman@47108: "neg_numeral v + (numeral w + y) = (sub w v + y)" huffman@47108: "neg_numeral v + (neg_numeral w + y) = (neg_numeral(v + w) + y)" huffman@47108: by (simp_all add: add_assoc [symmetric]) huffman@47108: huffman@47108: lemma mult_numeral_left [simp]: huffman@47108: "numeral v * (numeral w * z) = (numeral(v * w) * z :: 'a::semiring_numeral)" huffman@47108: "neg_numeral v * (numeral w * y) = (neg_numeral(v * w) * y :: 'b::ring_1)" huffman@47108: "numeral v * (neg_numeral w * y) = (neg_numeral(v * w) * y :: 'b::ring_1)" huffman@47108: "neg_numeral v * (neg_numeral w * y) = (numeral(v * w) * y :: 'b::ring_1)" huffman@47108: by (simp_all add: mult_assoc [symmetric]) huffman@47108: huffman@47108: hide_const (open) One Bit0 Bit1 BitM inc pow sqr sub dbl dbl_inc dbl_dec huffman@47108: haftmann@51143: huffman@47108: subsection {* code module namespace *} huffman@47108: haftmann@52435: code_identifier haftmann@52435: code_module Num \ (SML) Arith and (OCaml) Arith and (Haskell) Arith huffman@47108: huffman@47108: end haftmann@50817: haftmann@51143: