# Theory NatBin

Up to index of Isabelle/HOL

theory NatBin
imports IntDiv
begin

    (*  Title:      HOL/NatBin.thy
        ID:         $Id: NatBin.thy,v 1.46 2005/09/29 15:02:57 paulson Exp $
        Author:     Lawrence C Paulson, Cambridge University Computer Laboratory
        Copyright   1999  University of Cambridge
    *)

    header {* Binary arithmetic for the natural numbers *}

    theory NatBin
    imports IntDiv
    begin

    text {*
      Arithmetic for naturals is reduced to that for the non-negative integers.
    *}

    instance nat :: number ..

    defs (overloaded)
      nat_number_of_def:
         "(number_of::bin => nat) v == nat ((number_of :: bin => int) v)"

    subsection{*Function @{term nat}: Coercion from Type @{typ int} to @{typ nat}*}

    declare nat_0 [simp] nat_1 [simp]

    lemma nat_number_of [simp]: "nat (number_of w) = number_of w"
    by (simp add: nat_number_of_def)

    lemma nat_numeral_0_eq_0 [simp]: "Numeral0 = (0::nat)"
    by (simp add: nat_number_of_def)

    lemma nat_numeral_1_eq_1 [simp]: "Numeral1 = (1::nat)"
    by (simp add: nat_1 nat_number_of_def)

    lemma numeral_1_eq_Suc_0: "Numeral1 = Suc 0"
    by (simp add: nat_numeral_1_eq_1)

    lemma numeral_2_eq_2: "2 = Suc (Suc 0)"
    apply (unfold nat_number_of_def)
    apply (rule nat_2)
    done

    text{*Distributive laws for type @{text nat}.  The others are in theory
       @{text IntArith}, but these require div and mod to be defined for type
       "int".  They also need some of the lemmas proved above.*}

    lemma nat_div_distrib: "(0::int) <= z ==> nat (z div z') = nat z div nat z'"
    apply (case_tac "0 <= z'")
    apply (auto simp add: div_nonneg_neg_le0 DIVISION_BY_ZERO_DIV)
    apply (case_tac "z' = 0", simp add: DIVISION_BY_ZERO)
    apply (auto elim!: nonneg_eq_int)
    apply (rename_tac m m')
    apply (subgoal_tac "0 <= int m div int m'")
     prefer 2 apply (simp add: nat_numeral_0_eq_0 pos_imp_zdiv_nonneg_iff)
    apply (rule inj_int [THEN injD], simp)
    apply (rule_tac r = "int (m mod m') " in quorem_div)
     prefer 2 apply force
    apply (simp add: nat_less_iff [symmetric] quorem_def nat_numeral_0_eq_0 zadd_int
                     zmult_int)
    done

    (*Fails if z'<0: the LHS collapses to (nat z) but the RHS doesn't*)
    lemma nat_mod_distrib:
         "[| (0::int) <= z;  0 <= z' |] ==> nat (z mod z') = nat z mod nat z'"
    apply (case_tac "z' = 0", simp add: DIVISION_BY_ZERO)
    apply (auto elim!: nonneg_eq_int)
    apply (rename_tac m m')
    apply (subgoal_tac "0 <= int m mod int m'")
     prefer 2 apply (simp add: nat_less_iff nat_numeral_0_eq_0 pos_mod_sign)
    apply (rule inj_int [THEN injD], simp)
    apply (rule_tac q = "int (m div m') " in quorem_mod)
     prefer 2 apply force
    apply (simp add: nat_less_iff [symmetric] quorem_def nat_numeral_0_eq_0 zadd_int zmult_int)
    done

    text{*Suggested by Matthias Daum*}
    lemma int_div_less_self: "[|0 < x; 1 < k|] ==> x div k < (x::int)"
    apply (subgoal_tac "nat x div nat k < nat x")
     apply (simp add: nat_div_distrib [symmetric])
    apply (rule Divides.div_less_dividend, simp_all)
    done

    subsection{*Function @{term int}: Coercion from Type @{typ nat} to @{typ int}*}

    (*"neg" is used in rewrite rules for binary comparisons*)
    lemma int_nat_number_of [simp]:
         "int (number_of v :: nat) =
             (if neg (number_of v :: int) then 0
              else (number_of v :: int))"
    by (simp del: nat_number_of
             add: neg_nat nat_number_of_def not_neg_nat add_assoc)

    subsubsection{*Successor *}

    lemma Suc_nat_eq_nat_zadd1: "(0::int) <= z ==> Suc (nat z) = nat (1 + z)"
    apply (rule sym)
    apply (simp add: nat_eq_iff int_Suc)
    done

    lemma Suc_nat_number_of_add:
         "Suc (number_of v + n) =
            (if neg (number_of v :: int) then 1+n else number_of (bin_succ v) + n)"
    by (simp del: nat_number_of
             add: nat_number_of_def neg_nat
                  Suc_nat_eq_nat_zadd1 number_of_succ)

    lemma Suc_nat_number_of [simp]:
         "Suc (number_of v) =
            (if neg (number_of v :: int) then 1 else number_of (bin_succ v))"
    apply (cut_tac n = 0 in Suc_nat_number_of_add)
    apply (simp cong del: if_weak_cong)
    done

    subsubsection{*Addition *}

    (*"neg" is used in rewrite rules for binary comparisons*)
    lemma add_nat_number_of [simp]:
         "(number_of v :: nat) + number_of v' =
             (if neg (number_of v :: int) then number_of v'
              else if neg (number_of v' :: int) then number_of v
              else number_of (bin_add v v'))"
    by (force dest!: neg_nat
              simp del: nat_number_of
              simp add: nat_number_of_def nat_add_distrib [symmetric])

    subsubsection{*Subtraction *}

    lemma diff_nat_eq_if:
         "nat z - nat z' =
            (if neg z' then nat z
             else let d = z-z' in
                  if neg d then 0 else nat d)"
    apply (simp add: Let_def nat_diff_distrib [symmetric] neg_eq_less_0 not_neg_eq_ge_0)
    apply (simp add: diff_is_0_eq nat_le_eq_zle)
    done

    lemma diff_nat_number_of [simp]:
         "(number_of v :: nat) - number_of v' =
            (if neg (number_of v' :: int) then number_of v
             else let d = number_of (bin_add v (bin_minus v')) in
                  if neg d then 0 else nat d)"
    by (simp del: nat_number_of add: diff_nat_eq_if nat_number_of_def)

    subsubsection{*Multiplication *}

    lemma mult_nat_number_of [simp]:
         "(number_of v :: nat) * number_of v' =
           (if neg (number_of v :: int) then 0 else number_of (bin_mult v v'))"
    by (force dest!: neg_nat
              simp del: nat_number_of
              simp add: nat_number_of_def nat_mult_distrib [symmetric])

    subsubsection{*Quotient *}

    lemma div_nat_number_of [simp]:
         "(number_of v :: nat)  div  number_of v' =
              (if neg (number_of v :: int) then 0
               else nat (number_of v div number_of v'))"
    by (force dest!: neg_nat
              simp del: nat_number_of
              simp add: nat_number_of_def nat_div_distrib [symmetric])

    lemma one_div_nat_number_of [simp]:
         "(Suc 0)  div  number_of v' = (nat (1 div number_of v'))"
    by (simp del: nat_numeral_1_eq_1 add: numeral_1_eq_Suc_0 [symmetric])

    subsubsection{*Remainder *}

    lemma mod_nat_number_of [simp]:
         "(number_of v :: nat)  mod  number_of v' =
            (if neg (number_of v :: int) then 0
             else if neg (number_of v' :: int) then number_of v
             else nat (number_of v mod number_of v'))"
    by (force dest!: neg_nat
              simp del: nat_number_of
              simp add: nat_number_of_def nat_mod_distrib [symmetric])

    lemma one_mod_nat_number_of [simp]:
         "(Suc 0)  mod  number_of v' =
            (if neg (number_of v' :: int) then Suc 0
             else nat (1 mod number_of v'))"
    by (simp del: nat_numeral_1_eq_1 add: numeral_1_eq_Suc_0 [symmetric])

    ML
    {*
    val nat_number_of_def = thm"nat_number_of_def";

    val nat_number_of = thm"nat_number_of";
    val nat_numeral_0_eq_0 = thm"nat_numeral_0_eq_0";
    val nat_numeral_1_eq_1 = thm"nat_numeral_1_eq_1";
    val numeral_1_eq_Suc_0 = thm"numeral_1_eq_Suc_0";
    val numeral_2_eq_2 = thm"numeral_2_eq_2";
    val nat_div_distrib = thm"nat_div_distrib";
    val nat_mod_distrib = thm"nat_mod_distrib";
    val int_nat_number_of = thm"int_nat_number_of";
    val Suc_nat_eq_nat_zadd1 = thm"Suc_nat_eq_nat_zadd1";
    val Suc_nat_number_of_add = thm"Suc_nat_number_of_add";
    val Suc_nat_number_of = thm"Suc_nat_number_of";
    val add_nat_number_of = thm"add_nat_number_of";
    val diff_nat_eq_if = thm"diff_nat_eq_if";
    val diff_nat_number_of = thm"diff_nat_number_of";
    val mult_nat_number_of = thm"mult_nat_number_of";
    val div_nat_number_of = thm"div_nat_number_of";
    val mod_nat_number_of = thm"mod_nat_number_of";
    *}

    subsection{*Comparisons*}

    subsubsection{*Equals (=) *}

    lemma eq_nat_nat_iff:
         "[| (0::int) <= z;  0 <= z' |] ==> (nat z = nat z') = (z=z')"
    by (auto elim!: nonneg_eq_int)

    (*"neg" is used in rewrite rules for binary comparisons*)
    lemma eq_nat_number_of [simp]:
         "((number_of v :: nat) = number_of v') =
          (if neg (number_of v :: int) then (iszero (number_of v' :: int) | neg (number_of v' :: int))
           else if neg (number_of v' :: int) then iszero (number_of v :: int)
           else iszero (number_of (bin_add v (bin_minus v')) :: int))"
    apply (simp only: simp_thms neg_nat not_neg_eq_ge_0 nat_number_of_def
                      eq_nat_nat_iff eq_number_of_eq nat_0 iszero_def
                split add: split_if cong add: imp_cong)
    apply (simp only: nat_eq_iff nat_eq_iff2)
    apply (simp add: not_neg_eq_ge_0 [symmetric])
    done

    subsubsection{*Less-than (<) *}

    (*"neg" is used in rewrite rules for binary comparisons*)
    lemma less_nat_number_of [simp]:
         "((number_of v :: nat) < number_of v') =
             (if neg (number_of v :: int) then neg (number_of (bin_minus v') :: int)
              else neg (number_of (bin_add v (bin_minus v')) :: int))"
    by (simp only: simp_thms neg_nat not_neg_eq_ge_0 nat_number_of_def
                    nat_less_eq_zless less_number_of_eq_neg zless_nat_eq_int_zless
             cong add: imp_cong, simp)

    (*Maps #n to n for n = 0, 1, 2*)
    lemmas numerals = nat_numeral_0_eq_0 nat_numeral_1_eq_1 numeral_2_eq_2

    subsection{*Powers with Numeric Exponents*}

    text{*We cannot refer to the number @{term 2} in @{text Ring_and_Field.thy}.
    We cannot prove general results about the numeral @{term "-1"}, so we have to
    use @{term "- 1"} instead.*}

    lemma power2_eq_square: "(a::'a::{comm_semiring_1_cancel,recpower})² = a * a"
      by (simp add: numeral_2_eq_2 Power.power_Suc)

    lemma zero_power2 [simp]: "(0::'a::{comm_semiring_1_cancel,recpower})² = 0"
      by (simp add: power2_eq_square)

    lemma one_power2 [simp]: "(1::'a::{comm_semiring_1_cancel,recpower})² = 1"
      by (simp add: power2_eq_square)

    lemma power3_eq_cube: "(x::'a::recpower) ^ 3 = x * x * x"
      apply (subgoal_tac "3 = Suc (Suc (Suc 0))")
      apply (erule ssubst)
      apply (simp add: power_Suc mult_ac)
      apply (unfold nat_number_of_def)
      apply (subst nat_eq_iff)
      apply simp
    done

    text{*Squares of literal numerals will be evaluated.*}
    lemmas power2_eq_square_number_of =
        power2_eq_square [of "number_of w", standard]
    declare power2_eq_square_number_of [simp]

    lemma zero_le_power2: "0 ≤ (a²::'a::{ordered_idom,recpower})"
      by (simp add: power2_eq_square zero_le_square)

    lemma zero_less_power2:
         "(0 < a²) = (a ≠ (0::'a::{ordered_idom,recpower}))"
      by (force simp add: power2_eq_square zero_less_mult_iff linorder_neq_iff)

    lemma power2_less_0:
      fixes a :: "'a::{ordered_idom,recpower}"
      shows "~ (a² < 0)"
    by (force simp add: power2_eq_square mult_less_0_iff)

    lemma zero_eq_power2:
         "(a² = 0) = (a = (0::'a::{ordered_idom,recpower}))"
      by (force simp add: power2_eq_square mult_eq_0_iff)

    lemma abs_power2:
         "abs(a²) = (a²::'a::{ordered_idom,recpower})"
      by (simp add: power2_eq_square abs_mult abs_mult_self)

    lemma power2_abs:
         "(abs a)² = (a²::'a::{ordered_idom,recpower})"
      by (simp add: power2_eq_square abs_mult_self)

    lemma power2_minus:
         "(- a)² = (a²::'a::{comm_ring_1,recpower})"
      by (simp add: power2_eq_square)

    lemma power_minus1_even: "(- 1) ^ (2*n) = (1::'a::{comm_ring_1,recpower})"
    apply (induct "n")
    apply (auto simp add: power_Suc power_add power2_minus)
    done

    lemma power_even_eq: "(a::'a::recpower) ^ (2*n) = (a^n)^2"
    by (simp add: power_mult power_mult_distrib power2_eq_square)

    lemma power_odd_eq: "(a::int) ^ Suc(2*n) = a * (a^n)^2"
    by (simp add: power_even_eq)

    lemma power_minus_even [simp]:
         "(-a) ^ (2*n) = (a::'a::{comm_ring_1,recpower}) ^ (2*n)"
    by (simp add: power_minus1_even power_minus [of a])

    lemma zero_le_even_power':
         "0 ≤ (a::'a::{ordered_idom,recpower}) ^ (2*n)"
    proof (induct "n")
      case 0
        show ?case by (simp add: zero_le_one)
    next
      case (Suc n)
        have "a ^ (2 * Suc n) = (a*a) * a ^ (2*n)"
          by (simp add: mult_ac power_add power2_eq_square)
        thus ?case
          by (simp add: prems zero_le_square zero_le_mult_iff)
    qed

    lemma odd_power_less_zero:
         "(a::'a::{ordered_idom,recpower}) < 0 ==> a ^ Suc(2*n) < 0"
    proof (induct "n")
      case 0
        show ?case by (simp add: Power.power_Suc)
    next
      case (Suc n)
        have "a ^ Suc (2 * Suc n) = (a*a) * a ^ Suc(2*n)"
          by (simp add: mult_ac power_add power2_eq_square Power.power_Suc)
        thus ?case
          by (simp add: prems mult_less_0_iff mult_neg_neg)
    qed

    lemma odd_0_le_power_imp_0_le:
         "0 ≤ a  ^ Suc(2*n) ==> 0 ≤ (a::'a::{ordered_idom,recpower})"
    apply (insert odd_power_less_zero [of a n])
    apply (force simp add: linorder_not_less [symmetric])
    done

    text{*Simprules for comparisons where common factors can be cancelled.*}
    lemmas zero_compare_simps =
        add_strict_increasing add_strict_increasing2 add_increasing
        zero_le_mult_iff zero_le_divide_iff
        zero_less_mult_iff zero_less_divide_iff
        mult_le_0_iff divide_le_0_iff
        mult_less_0_iff divide_less_0_iff
        zero_le_power2 power2_less_0

    subsubsection{*Nat *}

    lemma Suc_pred': "0 < n ==> n = Suc(n - 1)"
    by (simp add: numerals)

    (*Expresses a natural number constant as the Suc of another one.
      NOT suitable for rewriting because n recurs in the condition.*)
    lemmas expand_Suc = Suc_pred' [of "number_of v", standard]

    subsubsection{*Arith *}

    lemma Suc_eq_add_numeral_1: "Suc n = n + 1"
    by (simp add: numerals)

    lemma Suc_eq_add_numeral_1_left: "Suc n = 1 + n"
    by (simp add: numerals)

    (* These two can be useful when m = number_of... *)

    lemma add_eq_if: "(m::nat) + n = (if m=0 then n else Suc ((m - 1) + n))"
    apply (case_tac "m")
    apply (simp_all add: numerals)
    done

    lemma mult_eq_if: "(m::nat) * n = (if m=0 then 0 else n + ((m - 1) * n))"
    apply (case_tac "m")
    apply (simp_all add: numerals)
    done

    lemma power_eq_if: "(p ^ m :: nat) = (if m=0 then 1 else p * (p ^ (m - 1)))"
    apply (case_tac "m")
    apply (simp_all add: numerals)
    done

    subsection{*Comparisons involving (0::nat) *}

    text{*Simplification already does @{term "n<0"}, @{term "n≤0"} and @{term "0≤n"}.*}

    lemma eq_number_of_0 [simp]:
         "(number_of v = (0::nat)) =
          (if neg (number_of v :: int) then True else iszero (number_of v :: int))"
    by (simp del: nat_numeral_0_eq_0 add: nat_numeral_0_eq_0 [symmetric] iszero_0)

    lemma eq_0_number_of [simp]:
         "((0::nat) = number_of v) =
          (if neg (number_of v :: int) then True else iszero (number_of v :: int))"
    by (rule trans [OF eq_sym_conv eq_number_of_0])

    lemma less_0_number_of [simp]:
         "((0::nat) < number_of v) = neg (number_of (bin_minus v) :: int)"
    by (simp del: nat_numeral_0_eq_0 add: nat_numeral_0_eq_0 [symmetric])

    lemma neg_imp_number_of_eq_0: "neg (number_of v :: int) ==> number_of v = (0::nat)"
    by (simp del: nat_numeral_0_eq_0 add: nat_numeral_0_eq_0 [symmetric] iszero_0)

    subsection{*Comparisons involving Suc *}

    lemma eq_number_of_Suc [simp]:
         "(number_of v = Suc n) =
            (let pv = number_of (bin_pred v) in
             if neg pv then False else nat pv = n)"
    apply (simp only: simp_thms Let_def neg_eq_less_0 linorder_not_less
                      number_of_pred nat_number_of_def
                split add: split_if)
    apply (rule_tac x = "number_of v" in spec)
    apply (auto simp add: nat_eq_iff)
    done

    lemma Suc_eq_number_of [simp]:
         "(Suc n = number_of v) =
            (let pv = number_of (bin_pred v) in
             if neg pv then False else nat pv = n)"
    by (rule trans [OF eq_sym_conv eq_number_of_Suc])

    lemma less_number_of_Suc [simp]:
         "(number_of v < Suc n) =
            (let pv = number_of (bin_pred v) in
             if neg pv then True else nat pv < n)"
    apply (simp only: simp_thms Let_def neg_eq_less_0 linorder_not_less
                      number_of_pred nat_number_of_def
                split add: split_if)
    apply (rule_tac x = "number_of v" in spec)
    apply (auto simp add: nat_less_iff)
    done

    lemma less_Suc_number_of [simp]:
         "(Suc n < number_of v) =
            (let pv = number_of (bin_pred v) in
             if neg pv then False else n < nat pv)"
    apply (simp only: simp_thms Let_def neg_eq_less_0 linorder_not_less
                      number_of_pred nat_number_of_def
                split add: split_if)
    apply (rule_tac x = "number_of v" in spec)
    apply (auto simp add: zless_nat_eq_int_zless)
    done

    lemma le_number_of_Suc [simp]:
         "(number_of v <= Suc n) =
            (let pv = number_of (bin_pred v) in
             if neg pv then True else nat pv <= n)"
    by (simp add: Let_def less_Suc_number_of linorder_not_less [symmetric])

    lemma le_Suc_number_of [simp]:
         "(Suc n <= number_of v) =
            (let pv = number_of (bin_pred v) in
             if neg pv then False else n <= nat pv)"
    by (simp add: Let_def less_number_of_Suc linorder_not_less [symmetric])

    (* Push int(.) inwards: *)
    declare zadd_int [symmetric, simp]

    lemma lemma1: "(m+m = n+n) = (m = (n::int))"
    by auto

    lemma lemma2: "m+m ~= (1::int) + (n + n)"
    apply auto
    apply (drule_tac f = "%x. x mod 2" in arg_cong)
    apply (simp add: zmod_zadd1_eq)
    done

    lemma eq_number_of_BIT_BIT:
         "((number_of (v BIT x) ::int) = number_of (w BIT y)) =
          (x=y & (((number_of v) ::int) = number_of w))"
    apply (simp only: number_of_BIT lemma1 lemma2 eq_commute
                   OrderedGroup.add_left_cancel add_assoc OrderedGroup.add_0
                split add: bit.split)
    apply simp
    done

    lemma eq_number_of_BIT_Pls:
         "((number_of (v BIT x) ::int) = Numeral0) =
          (x=bit.B0 & (((number_of v) ::int) = Numeral0))"
    apply (simp only: simp_thms  add: number_of_BIT number_of_Pls eq_commute
                split add: bit.split cong: imp_cong)
    apply (rule_tac x = "number_of v" in spec, safe)
    apply (simp_all (no_asm_use))
    apply (drule_tac f = "%x. x mod 2" in arg_cong)
    apply (simp add: zmod_zadd1_eq)
    done

    lemma eq_number_of_BIT_Min:
         "((number_of (v BIT x) ::int) = number_of Numeral.Min) =
          (x=bit.B1 & (((number_of v) ::int) = number_of Numeral.Min))"
    apply (simp only: simp_thms  add: number_of_BIT number_of_Min eq_commute
                split add: bit.split cong: imp_cong)
    apply (rule_tac x = "number_of v" in spec, auto)
    apply (drule_tac f = "%x. x mod 2" in arg_cong, auto)
    done

    lemma eq_number_of_Pls_Min: "(Numeral0 ::int) ~= number_of Numeral.Min"
    by auto

    subsection{*Literal arithmetic involving powers*}

    lemma nat_power_eq: "(0::int) <= z ==> nat (z^n) = nat z ^ n"
    apply (induct "n")
    apply (simp_all (no_asm_simp) add: nat_mult_distrib)
    done

    lemma power_nat_number_of:
         "(number_of v :: nat) ^ n =
           (if neg (number_of v :: int) then 0^n else nat ((number_of v :: int) ^ n))"
    by (simp only: simp_thms neg_nat not_neg_eq_ge_0 nat_number_of_def nat_power_eq
             split add: split_if cong: imp_cong)

    lemmas power_nat_number_of_number_of = power_nat_number_of [of _ "number_of w", standard]
    declare power_nat_number_of_number_of [simp]

    text{*For the integers*}

    lemma zpower_number_of_even:
         "(z::int) ^ number_of (w BIT bit.B0) =
          (let w = z ^ (number_of w) in  w*w)"
    apply (simp del: nat_number_of  add: nat_number_of_def number_of_BIT Let_def)
    apply (simp only: number_of_add)
    apply (rule_tac x = "number_of w" in spec, clarify)
    apply (case_tac " (0::int) <= x")
    apply (auto simp add: nat_mult_distrib power_even_eq power2_eq_square)
    done

    lemma zpower_number_of_odd:
         "(z::int) ^ number_of (w BIT bit.B1) =
              (if (0::int) <= number_of w
               then (let w = z ^ (number_of w) in  z*w*w)
               else 1)"
    apply (simp del: nat_number_of  add: nat_number_of_def number_of_BIT Let_def)
    apply (simp only: number_of_add nat_numeral_1_eq_1 not_neg_eq_ge_0 neg_eq_less_0)
    apply (rule_tac x = "number_of w" in spec, clarify)
    apply (auto simp add: nat_add_distrib nat_mult_distrib power_even_eq power2_eq_square neg_nat)
    done

    lemmas zpower_number_of_even_number_of =
        zpower_number_of_even [of "number_of v", standard]
    declare zpower_number_of_even_number_of [simp]

    lemmas zpower_number_of_odd_number_of =
        zpower_number_of_odd [of "number_of v", standard]
    declare zpower_number_of_odd_number_of [simp]

    ML
    {*
    val numerals = thms"numerals";
    val numeral_ss = simpset() addsimps numerals;

    val nat_bin_arith_setup =
     [Fast_Arith.map_data
       (fn {add_mono_thms, mult_mono_thms, inj_thms, lessD, neqE, simpset} =>
         {add_mono_thms = add_mono_thms, mult_mono_thms = mult_mono_thms,
          inj_thms = inj_thms,
          lessD = lessD, neqE = neqE,
          simpset = simpset addsimps [Suc_nat_number_of, int_nat_number_of,
                                      not_neg_number_of_Pls,
                                      neg_number_of_Min,neg_number_of_BIT]})]
    *}

    setup nat_bin_arith_setup

    (* Enable arith to deal with div/mod k where k is a numeral: *)
    declare split_div[of _ _ "number_of k", standard, arith_split]
    declare split_mod[of _ _ "number_of k", standard, arith_split]

    lemma nat_number_of_Pls: "Numeral0 = (0::nat)"
      by (simp add: number_of_Pls nat_number_of_def)

    lemma nat_number_of_Min: "number_of Numeral.Min = (0::nat)"
      apply (simp only: number_of_Min nat_number_of_def nat_zminus_int)
      apply (simp add: neg_nat)
      done

    lemma nat_number_of_BIT_1:
      "number_of (w BIT bit.B1) =
        (if neg (number_of w :: int) then 0
         else let n = number_of w in Suc (n + n))"
      apply (simp only: nat_number_of_def Let_def split: split_if)
      apply (intro conjI impI)
       apply (simp add: neg_nat neg_number_of_BIT)
      apply (rule int_int_eq [THEN iffD1])
      apply (simp only: not_neg_nat neg_number_of_BIT int_Suc zadd_int [symmetric] simp_thms)
      apply (simp only: number_of_BIT zadd_assoc split: bit.split)
      apply simp
      done

    lemma nat_number_of_BIT_0:
        "number_of (w BIT bit.B0) = (let n::nat = number_of w in n + n)"
      apply (simp only: nat_number_of_def Let_def)
      apply (cases "neg (number_of w :: int)")
       apply (simp add: neg_nat neg_number_of_BIT)
      apply (rule int_int_eq [THEN iffD1])
      apply (simp only: not_neg_nat neg_number_of_BIT int_Suc zadd_int [symmetric] simp_thms)
      apply (simp only: number_of_BIT zadd_assoc)
      apply simp
      done

    lemmas nat_number =
      nat_number_of_Pls nat_number_of_Min
      nat_number_of_BIT_1 nat_number_of_BIT_0

    lemma Let_Suc [simp]: "Let (Suc n) f == f (Suc n)"
      by (simp add: Let_def)

    lemma power_m1_even: "(-1) ^ (2*n) = (1::'a::{number_ring,recpower})"
    by (simp add: power_mult);

    lemma power_m1_odd: "(-1) ^ Suc(2*n) = (-1::'a::{number_ring,recpower})"
    by (simp add: power_mult power_Suc);

    subsection{*Literal arithmetic and @{term of_nat}*}

    lemma of_nat_double:
         "0 ≤ x ==> of_nat (nat (2 * x)) = of_nat (nat x) + of_nat (nat x)"
    by (simp only: mult_2 nat_add_distrib of_nat_add)

    lemma nat_numeral_m1_eq_0: "-1 = (0::nat)"
    by (simp only:  nat_number_of_def, simp)

    lemma of_nat_number_of_lemma:
         "of_nat (number_of v :: nat) =
             (if 0 ≤ (number_of v :: int)
              then (number_of v :: 'a :: number_ring)
              else 0)"
    by (simp add: int_number_of_def nat_number_of_def number_of_eq of_nat_nat);

    lemma of_nat_number_of_eq [simp]:
         "of_nat (number_of v :: nat) =
             (if neg (number_of v :: int) then 0
              else (number_of v :: 'a :: number_ring))"
    by (simp only: of_nat_number_of_lemma neg_def, simp)

    subsection {*Lemmas for the Combination and Cancellation Simprocs*}

    lemma nat_number_of_add_left:
         "number_of v + (number_of v' + (k::nat)) =
             (if neg (number_of v :: int) then number_of v' + k
              else if neg (number_of v' :: int) then number_of v + k
              else number_of (bin_add v v') + k)"
    by simp

    lemma nat_number_of_mult_left:
         "number_of v * (number_of v' * (k::nat)) =
             (if neg (number_of v :: int) then 0
              else number_of (bin_mult v v') * k)"
    by simp

    subsubsection{*For @{text combine_numerals}*}

    lemma left_add_mult_distrib: "i*u + (j*u + k) = (i+j)*u + (k::nat)"
    by (simp add: add_mult_distrib)

    subsubsection{*For @{text cancel_numerals}*}

    lemma nat_diff_add_eq1:
         "j <= (i::nat) ==> ((i*u + m) - (j*u + n)) = (((i-j)*u + m) - n)"
    by (simp split add: nat_diff_split add: add_mult_distrib)

    lemma nat_diff_add_eq2:
         "i <= (j::nat) ==> ((i*u + m) - (j*u + n)) = (m - ((j-i)*u + n))"
    by (simp split add: nat_diff_split add: add_mult_distrib)

    lemma nat_eq_add_iff1:
         "j <= (i::nat) ==> (i*u + m = j*u + n) = ((i-j)*u + m = n)"
    by (auto split add: nat_diff_split simp add: add_mult_distrib)

    lemma nat_eq_add_iff2:
         "i <= (j::nat) ==> (i*u + m = j*u + n) = (m = (j-i)*u + n)"
    by (auto split add: nat_diff_split simp add: add_mult_distrib)

    lemma nat_less_add_iff1:
         "j <= (i::nat) ==> (i*u + m < j*u + n) = ((i-j)*u + m < n)"
    by (auto split add: nat_diff_split simp add: add_mult_distrib)

    lemma nat_less_add_iff2:
         "i <= (j::nat) ==> (i*u + m < j*u + n) = (m < (j-i)*u + n)"
    by (auto split add: nat_diff_split simp add: add_mult_distrib)

    lemma nat_le_add_iff1:
         "j <= (i::nat) ==> (i*u + m <= j*u + n) = ((i-j)*u + m <= n)"
    by (auto split add: nat_diff_split simp add: add_mult_distrib)

    lemma nat_le_add_iff2:
         "i <= (j::nat) ==> (i*u + m <= j*u + n) = (m <= (j-i)*u + n)"
    by (auto split add: nat_diff_split simp add: add_mult_distrib)

    subsubsection{*For @{text cancel_numeral_factors} *}

    lemma nat_mult_le_cancel1: "(0::nat) < k ==> (k*m <= k*n) = (m<=n)"
    by auto

    lemma nat_mult_less_cancel1: "(0::nat) < k ==> (k*m < k*n) = (m<n)"
    by auto

    lemma nat_mult_eq_cancel1: "(0::nat) < k ==> (k*m = k*n) = (m=n)"
    by auto

    lemma nat_mult_div_cancel1: "(0::nat) < k ==> (k*m) div (k*n) = (m div n)"
    by auto

    subsubsection{*For @{text cancel_factor} *}

    lemma nat_mult_le_cancel_disj: "(k*m <= k*n) = ((0::nat) < k --> m<=n)"
    by auto

    lemma nat_mult_less_cancel_disj: "(k*m < k*n) = ((0::nat) < k & m<n)"
    by auto

    lemma nat_mult_eq_cancel_disj: "(k*m = k*n) = (k = (0::nat) | m=n)"
    by auto

    lemma nat_mult_div_cancel_disj:
         "(k*m) div (k*n) = (if k = (0::nat) then 0 else m div n)"
    by (simp add: nat_mult_div_cancel1)

    ML
    {*
    val eq_nat_nat_iff = thm"eq_nat_nat_iff";
    val eq_nat_number_of = thm"eq_nat_number_of";
    val less_nat_number_of = thm"less_nat_number_of";
    val power2_eq_square = thm "power2_eq_square";
    val zero_le_power2 = thm "zero_le_power2";
    val zero_less_power2 = thm "zero_less_power2";
    val zero_eq_power2 = thm "zero_eq_power2";
    val abs_power2 = thm "abs_power2";
    val power2_abs = thm "power2_abs";
    val power2_minus = thm "power2_minus";
    val power_minus1_even = thm "power_minus1_even";
    val power_minus_even = thm "power_minus_even";
    (* val zero_le_even_power = thm "zero_le_even_power"; *)
    val odd_power_less_zero = thm "odd_power_less_zero";
    val odd_0_le_power_imp_0_le = thm "odd_0_le_power_imp_0_le";

    val Suc_pred' = thm"Suc_pred'";
    val expand_Suc = thm"expand_Suc";
    val Suc_eq_add_numeral_1 = thm"Suc_eq_add_numeral_1";
    val Suc_eq_add_numeral_1_left = thm"Suc_eq_add_numeral_1_left";
    val add_eq_if = thm"add_eq_if";
    val mult_eq_if = thm"mult_eq_if";
    val power_eq_if = thm"power_eq_if";
    val eq_number_of_0 = thm"eq_number_of_0";
    val eq_0_number_of = thm"eq_0_number_of";
    val less_0_number_of = thm"less_0_number_of";
    val neg_imp_number_of_eq_0 = thm"neg_imp_number_of_eq_0";
    val eq_number_of_Suc = thm"eq_number_of_Suc";
    val Suc_eq_number_of = thm"Suc_eq_number_of";
    val less_number_of_Suc = thm"less_number_of_Suc";
    val less_Suc_number_of = thm"less_Suc_number_of";
    val le_number_of_Suc = thm"le_number_of_Suc";
    val le_Suc_number_of = thm"le_Suc_number_of";
    val eq_number_of_BIT_BIT = thm"eq_number_of_BIT_BIT";
    val eq_number_of_BIT_Pls = thm"eq_number_of_BIT_Pls";
    val eq_number_of_BIT_Min = thm"eq_number_of_BIT_Min";
    val eq_number_of_Pls_Min = thm"eq_number_of_Pls_Min";
    val of_nat_number_of_eq = thm"of_nat_number_of_eq";
    val nat_power_eq = thm"nat_power_eq";
    val power_nat_number_of = thm"power_nat_number_of";
    val zpower_number_of_even = thm"zpower_number_of_even";
    val zpower_number_of_odd = thm"zpower_number_of_odd";
    val nat_number_of_Pls = thm"nat_number_of_Pls";
    val nat_number_of_Min = thm"nat_number_of_Min";
    val Let_Suc = thm"Let_Suc";

    val nat_number = thms"nat_number";

    val nat_number_of_add_left = thm"nat_number_of_add_left";
    val nat_number_of_mult_left = thm"nat_number_of_mult_left";
    val left_add_mult_distrib = thm"left_add_mult_distrib";
    val nat_diff_add_eq1 = thm"nat_diff_add_eq1";
    val nat_diff_add_eq2 = thm"nat_diff_add_eq2";
    val nat_eq_add_iff1 = thm"nat_eq_add_iff1";
    val nat_eq_add_iff2 = thm"nat_eq_add_iff2";
    val nat_less_add_iff1 = thm"nat_less_add_iff1";
    val nat_less_add_iff2 = thm"nat_less_add_iff2";
    val nat_le_add_iff1 = thm"nat_le_add_iff1";
    val nat_le_add_iff2 = thm"nat_le_add_iff2";
    val nat_mult_le_cancel1 = thm"nat_mult_le_cancel1";
    val nat_mult_less_cancel1 = thm"nat_mult_less_cancel1";
    val nat_mult_eq_cancel1 = thm"nat_mult_eq_cancel1";
    val nat_mult_div_cancel1 = thm"nat_mult_div_cancel1";
    val nat_mult_le_cancel_disj = thm"nat_mult_le_cancel_disj";
    val nat_mult_less_cancel_disj = thm"nat_mult_less_cancel_disj";
    val nat_mult_eq_cancel_disj = thm"nat_mult_eq_cancel_disj";
    val nat_mult_div_cancel_disj = thm"nat_mult_div_cancel_disj";

    val power_minus_even = thm"power_minus_even";
    (* val zero_le_even_power = thm"zero_le_even_power"; *)
    *}

    end

### Function @{term nat}: Coercion from Type @{typ int} to @{typ nat}

lemma nat_number_of:

      nat (number_of w) = number_of w

lemma nat_numeral_0_eq_0:

      Numeral0 = 0

lemma nat_numeral_1_eq_1:

      Numeral1 = 1

lemma numeral_1_eq_Suc_0:

      Numeral1 = Suc 0

lemma numeral_2_eq_2:

      2 = Suc (Suc 0)

lemma nat_div_distrib:

      0 ≤ z ==> nat (z div z') = nat z div nat z'

lemma nat_mod_distrib:

      [| 0 ≤ z; 0 ≤ z' |] ==> nat (z mod z') = nat z mod nat z'

lemma int_div_less_self:

      [| 0 < x; 1 < k |] ==> x div k < x

### Function @{term int}: Coercion from Type @{typ nat} to @{typ int}

lemma int_nat_number_of:

      int (number_of v) = (if neg (number_of v) then 0 else number_of v)

#### Successor

lemma Suc_nat_eq_nat_zadd1:

      0 ≤ z ==> Suc (nat z) = nat (1 + z)

lemma Suc_nat_number_of_add:

      Suc (number_of v + n) =
      (if neg (number_of v) then 1 + n else number_of (bin_succ v) + n)

lemma Suc_nat_number_of:

      Suc (number_of v) = (if neg (number_of v) then 1 else number_of (bin_succ v))

#### Addition

lemma add_nat_number_of:

      number_of v + number_of v' =
      (if neg (number_of v) then number_of v'
       else if neg (number_of v') then number_of v else number_of (bin_add v v'))

#### Subtraction

lemma diff_nat_eq_if:

      nat z - nat z' =
      (if neg z' then nat z else let d = z - z' in if neg d then 0 else nat d)

lemma diff_nat_number_of:

      number_of v - number_of v' =
      (if neg (number_of v') then number_of v
       else let d = number_of (bin_add v (bin_minus v'))
            in if neg d then 0 else nat d)

#### Multiplication

lemma mult_nat_number_of:

      number_of v * number_of v' =
      (if neg (number_of v) then 0 else number_of (bin_mult v v'))

#### Quotient

lemma div_nat_number_of:

      number_of v div number_of v' =
      (if neg (number_of v) then 0 else nat (number_of v div number_of v'))

lemma one_div_nat_number_of:

      Suc 0 div number_of v' = nat (1 div number_of v')

#### Remainder

lemma mod_nat_number_of:

      number_of v mod number_of v' =
      (if neg (number_of v) then 0
       else if neg (number_of v') then number_of v
            else nat (number_of v mod number_of v'))

lemma one_mod_nat_number_of:

      Suc 0 mod number_of v' =
      (if neg (number_of v') then Suc 0 else nat (1 mod number_of v'))

### Comparisons

#### Equals (=)

lemma eq_nat_nat_iff:

      [| 0 ≤ z; 0 ≤ z' |] ==> (nat z = nat z') = (z = z')

lemma eq_nat_number_of:

      (number_of v = number_of v') =
      (if neg (number_of v) then iszero (number_of v') ∨ neg (number_of v')
       else if neg (number_of v') then iszero (number_of v)
            else iszero (number_of (bin_add v (bin_minus v'))))

#### Less-than (<)

lemma less_nat_number_of:

      (number_of v < number_of v') =
      (if neg (number_of v) then neg (number_of (bin_minus v'))
       else neg (number_of (bin_add v (bin_minus v'))))

lemmas numerals:

      Numeral0 = 0

      Numeral1 = 1

      2 = Suc (Suc 0)

lemmas numerals:

      Numeral0 = 0

      Numeral1 = 1

      2 = Suc (Suc 0)

### Powers with Numeric Exponents

lemma power2_eq_square:

      a² = a * a

lemma zero_power2:

      (0::'a)² = (0::'a)

lemma one_power2:

      (1::'a)² = (1::'a)

lemma power3_eq_cube:

      x ^ 3 = x * x * x

lemmas power2_eq_square_number_of:

      (number_of w)² = number_of w * number_of w

lemmas power2_eq_square_number_of:

      (number_of w)² = number_of w * number_of w

lemma zero_le_power2:

      (0::'a) ≤ a²

lemma zero_less_power2:

      ((0::'a) < a²) = (a ≠ (0::'a))

lemma power2_less_0:

      ¬ a² < (0::'a)

lemma zero_eq_power2:

      (a² = (0::'a)) = (a = (0::'a))

lemma abs_power2:

      ¦a²¦ = a²

lemma power2_abs:

      ¦a¦² = a²

lemma power2_minus:

      (- a)² = a²

lemma power_minus1_even:

      (- (1::'a)) ^ (2 * n) = (1::'a)

lemma power_even_eq:

      a ^ (2 * n) = (a ^ n)²

lemma power_odd_eq:

      a ^ Suc (2 * n) = a * (a ^ n)²

lemma power_minus_even:

      (- a) ^ (2 * n) = a ^ (2 * n)

lemma zero_le_even_power':

      (0::'a) ≤ a ^ (2 * n)

lemma odd_power_less_zero:

      a < (0::'a) ==> a ^ Suc (2 * n) < (0::'a)

lemma odd_0_le_power_imp_0_le:

      (0::'a) ≤ a ^ Suc (2 * n) ==> (0::'a) ≤ a

lemmas zero_compare_simps:

      [| (0::'a) < a; b ≤ c |] ==> b < a + c

      [| (0::'a) ≤ a; b < c |] ==> b < a + c

      [| (0::'a) ≤ a; b ≤ c |] ==> b ≤ a + c

      ((0::'a) ≤ a * b) = ((0::'a) ≤ a ∧ (0::'a) ≤ b ∨ a ≤ (0::'a) ∧ b ≤ (0::'a))

      ((0::'a) ≤ a / b) = ((0::'a) ≤ a ∧ (0::'a) ≤ b ∨ a ≤ (0::'a) ∧ b ≤ (0::'a))

      ((0::'a) < a * b) = ((0::'a) < a ∧ (0::'a) < b ∨ a < (0::'a) ∧ b < (0::'a))

      ((0::'a) < a / b) = ((0::'a) < a ∧ (0::'a) < b ∨ a < (0::'a) ∧ b < (0::'a))

      (a * b ≤ (0::'a)) = ((0::'a) ≤ a ∧ b ≤ (0::'a) ∨ a ≤ (0::'a) ∧ (0::'a) ≤ b)

      (a / b ≤ (0::'a)) = ((0::'a) ≤ a ∧ b ≤ (0::'a) ∨ a ≤ (0::'a) ∧ (0::'a) ≤ b)

      (a * b < (0::'a)) = ((0::'a) < a ∧ b < (0::'a) ∨ a < (0::'a) ∧ (0::'a) < b)

      (a / b < (0::'a)) = ((0::'a) < a ∧ b < (0::'a) ∨ a < (0::'a) ∧ (0::'a) < b)

      (0::'a) ≤ a²

      ¬ a² < (0::'a)

lemmas zero_compare_simps:

      [| (0::'a) < a; b ≤ c |] ==> b < a + c

      [| (0::'a) ≤ a; b < c |] ==> b < a + c

      [| (0::'a) ≤ a; b ≤ c |] ==> b ≤ a + c

      ((0::'a) ≤ a * b) = ((0::'a) ≤ a ∧ (0::'a) ≤ b ∨ a ≤ (0::'a) ∧ b ≤ (0::'a))

      ((0::'a) ≤ a / b) = ((0::'a) ≤ a ∧ (0::'a) ≤ b ∨ a ≤ (0::'a) ∧ b ≤ (0::'a))

      ((0::'a) < a * b) = ((0::'a) < a ∧ (0::'a) < b ∨ a < (0::'a) ∧ b < (0::'a))

      ((0::'a) < a / b) = ((0::'a) < a ∧ (0::'a) < b ∨ a < (0::'a) ∧ b < (0::'a))

      (a * b ≤ (0::'a)) = ((0::'a) ≤ a ∧ b ≤ (0::'a) ∨ a ≤ (0::'a) ∧ (0::'a) ≤ b)

      (a / b ≤ (0::'a)) = ((0::'a) ≤ a ∧ b ≤ (0::'a) ∨ a ≤ (0::'a) ∧ (0::'a) ≤ b)

      (a * b < (0::'a)) = ((0::'a) < a ∧ b < (0::'a) ∨ a < (0::'a) ∧ (0::'a) < b)

      (a / b < (0::'a)) = ((0::'a) < a ∧ b < (0::'a) ∨ a < (0::'a) ∧ (0::'a) < b)

      (0::'a) ≤ a²

      ¬ a² < (0::'a)

#### Nat

lemma Suc_pred':

      0 < n ==> n = Suc (n - 1)

lemmas expand_Suc:

      0 < number_of v ==> number_of v = Suc (number_of v - 1)

lemmas expand_Suc:

      0 < number_of v ==> number_of v = Suc (number_of v - 1)

#### Arith

lemma Suc_eq_add_numeral_1:

      Suc n = n + 1

lemma Suc_eq_add_numeral_1_left:

      Suc n = 1 + n

lemma add_eq_if:

      m + n = (if m = 0 then n else Suc (m - 1 + n))

lemma mult_eq_if:

      m * n = (if m = 0 then 0 else n + (m - 1) * n)

lemma power_eq_if:

      p ^ m = (if m = 0 then 1 else p * p ^ (m - 1))

### Comparisons involving (0::nat)

lemma eq_number_of_0:

      (number_of v = 0) = (if neg (number_of v) then True else iszero (number_of v))

lemma eq_0_number_of:

      (0 = number_of v) = (if neg (number_of v) then True else iszero (number_of v))

lemma less_0_number_of:

      (0 < number_of v) = neg (number_of (bin_minus v))

lemma neg_imp_number_of_eq_0:

      neg (number_of v) ==> number_of v = 0

### Comparisons involving Suc

lemma eq_number_of_Suc:

      (number_of v = Suc n) =
      (let pv = number_of (bin_pred v) in if neg pv then False else nat pv = n)

lemma Suc_eq_number_of:

      (Suc n = number_of v) =
      (let pv = number_of (bin_pred v) in if neg pv then False else nat pv = n)

lemma less_number_of_Suc:

      (number_of v < Suc n) =
      (let pv = number_of (bin_pred v) in if neg pv then True else nat pv < n)

lemma less_Suc_number_of:

      (Suc n < number_of v) =
      (let pv = number_of (bin_pred v) in if neg pv then False else n < nat pv)

lemma le_number_of_Suc:

      (number_of v ≤ Suc n) =
      (let pv = number_of (bin_pred v) in if neg pv then True else nat pv ≤ n)

lemma le_Suc_number_of:

      (Suc n ≤ number_of v) =
      (let pv = number_of (bin_pred v) in if neg pv then False else n ≤ nat pv)

lemma lemma1:

      (m + m = n + n) = (m = n)

lemma lemma2:

      m + m ≠ 1 + (n + n)

lemma eq_number_of_BIT_BIT:

      (number_of (v BIT x) = number_of (w BIT y)) =
      (x = y ∧ number_of v = number_of w)

lemma eq_number_of_BIT_Pls:

      (number_of (v BIT x) = Numeral0) = (x = bit.B0 ∧ number_of v = Numeral0)

lemma eq_number_of_BIT_Min:

      (number_of (v BIT x) = -1) = (x = bit.B1 ∧ number_of v = -1)

lemma eq_number_of_Pls_Min:

      Numeral0 ≠ -1

### Literal arithmetic involving powers

lemma nat_power_eq:

      0 ≤ z ==> nat (z ^ n) = nat z ^ n

lemma power_nat_number_of:

      number_of v ^ n = (if neg (number_of v) then 0 ^ n else nat (number_of v ^ n))

lemmas power_nat_number_of_number_of:

      number_of v ^ number_of w =
      (if neg (number_of v) then 0 ^ number_of w else nat (number_of v ^ number_of w))

lemmas power_nat_number_of_number_of:

      number_of v ^ number_of w =
      (if neg (number_of v) then 0 ^ number_of w else nat (number_of v ^ number_of w))

lemma zpower_number_of_even:

      z ^ number_of (w BIT bit.B0) = (let w = z ^ number_of w in w * w)

lemma zpower_number_of_odd:

      z ^ number_of (w BIT bit.B1) =
      (if 0 ≤ number_of w then let w = z ^ number_of w in z * w * w else 1)

lemmas zpower_number_of_even_number_of:

      number_of v ^ number_of (w BIT bit.B0) =
      (let w = number_of v ^ number_of w in w * w)

lemmas zpower_number_of_even_number_of:

      number_of v ^ number_of (w BIT bit.B0) =
      (let w = number_of v ^ number_of w in w * w)

lemmas zpower_number_of_odd_number_of:

      number_of v ^ number_of (w BIT bit.B1) =
      (if 0 ≤ number_of w
       then let w = number_of v ^ number_of w in number_of v * w * w else 1)

lemmas zpower_number_of_odd_number_of:

      number_of v ^ number_of (w BIT bit.B1) =
      (if 0 ≤ number_of w
       then let w = number_of v ^ number_of w in number_of v * w * w else 1)

lemma nat_number_of_Pls:

      Numeral0 = 0

lemma nat_number_of_Min:

      -1 = 0

lemma nat_number_of_BIT_1:

      number_of (w BIT bit.B1) =
      (if neg (number_of w) then 0 else let n = number_of w in Suc (n + n))

lemma nat_number_of_BIT_0:

      number_of (w BIT bit.B0) = (let n = number_of w in n + n)

lemmas nat_number:

      Numeral0 = 0

      -1 = 0

      number_of (w BIT bit.B1) =
      (if neg (number_of w) then 0 else let n = number_of w in Suc (n + n))

      number_of (w BIT bit.B0) = (let n = number_of w in n + n)

lemmas nat_number:

      Numeral0 = 0

      -1 = 0

      number_of (w BIT bit.B1) =
      (if neg (number_of w) then 0 else let n = number_of w in Suc (n + n))

      number_of (w BIT bit.B0) = (let n = number_of w in n + n)

lemma Let_Suc:

      Let (Suc n) f == f (Suc n)

lemma power_m1_even:

      (-1::'a) ^ (2 * n) = (1::'a)

lemma power_m1_odd:

      (-1::'a) ^ Suc (2 * n) = (-1::'a)

### Literal arithmetic and @{term of_nat}

lemma of_nat_double:

      0 ≤ x ==> of_nat (nat (2 * x)) = of_nat (nat x) + of_nat (nat x)

lemma nat_numeral_m1_eq_0:

      -1 = 0

lemma of_nat_number_of_lemma:

      of_nat (number_of v) = (if 0 ≤ number_of v then number_of v else 0::'a)

lemma of_nat_number_of_eq:

      of_nat (number_of v) = (if neg (number_of v) then 0::'a else number_of v)

### Lemmas for the Combination and Cancellation Simprocs

lemma nat_number_of_add_left:

      number_of v + (number_of v' + k) =
      (if neg (number_of v) then number_of v' + k
       else if neg (number_of v') then number_of v + k
            else number_of (bin_add v v') + k)

lemma nat_number_of_mult_left:

      number_of v * (number_of v' * k) =
      (if neg (number_of v) then 0 else number_of (bin_mult v v') * k)

#### For @{text combine_numerals}

lemma left_add_mult_distrib:

      i * u + (j * u + k) = (i + j) * u + k

#### For @{text cancel_numerals}

lemma nat_diff_add_eq1:

      j ≤ i ==> i * u + m - (j * u + n) = (i - j) * u + m - n

lemma nat_diff_add_eq2:

      i ≤ j ==> i * u + m - (j * u + n) = m - ((j - i) * u + n)

lemma nat_eq_add_iff1:

      j ≤ i ==> (i * u + m = j * u + n) = ((i - j) * u + m = n)

lemma nat_eq_add_iff2:

      i ≤ j ==> (i * u + m = j * u + n) = (m = (j - i) * u + n)

lemma nat_less_add_iff1:

      j ≤ i ==> (i * u + m < j * u + n) = ((i - j) * u + m < n)

lemma nat_less_add_iff2:

      i ≤ j ==> (i * u + m < j * u + n) = (m < (j - i) * u + n)

lemma nat_le_add_iff1:

      j ≤ i ==> (i * u + m ≤ j * u + n) = ((i - j) * u + m ≤ n)

lemma nat_le_add_iff2:

      i ≤ j ==> (i * u + m ≤ j * u + n) = (m ≤ (j - i) * u + n)

#### For @{text cancel_numeral_factors}

lemma nat_mult_le_cancel1:

      0 < k ==> (k * m ≤ k * n) = (m ≤ n)

lemma nat_mult_less_cancel1:

      0 < k ==> (k * m < k * n) = (m < n)

lemma nat_mult_eq_cancel1:

      0 < k ==> (k * m = k * n) = (m = n)

lemma nat_mult_div_cancel1:

      0 < k ==> k * m div (k * n) = m div n

#### For @{text cancel_factor}

lemma nat_mult_le_cancel_disj:

      (k * m ≤ k * n) = (0 < k --> m ≤ n)

lemma nat_mult_less_cancel_disj:

      (k * m < k * n) = (0 < k ∧ m < n)

lemma nat_mult_eq_cancel_disj:

      (k * m = k * n) = (k = 0 ∨ m = n)

lemma nat_mult_div_cancel_disj:

      k * m div (k * n) = (if k = 0 then 0 else m div n)