src/ZF/Integ/Bin.thy
author wenzelm
Sun, 25 Oct 1998 12:33:27 +0100
changeset 5769 6a422b22ba02
parent 5561 426c1e330903
child 6046 2c8a8be36c94
permissions -rw-r--r--
tuned checklist;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
5528
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
     1
(*  Title:      ZF/ex/Bin.thy
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
     2
    ID:         $Id$
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
     3
    Author:     Lawrence C Paulson, Cambridge University Computer Laboratory
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
     4
    Copyright   1994  University of Cambridge
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
     5
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
     6
Arithmetic on binary integers.
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
     7
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
     8
   The sign Pls stands for an infinite string of leading 0's.
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
     9
   The sign Min stands for an infinite string of leading 1's.
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    10
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    11
A number can have multiple representations, namely leading 0's with sign
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    12
Pls and leading 1's with sign Min.  See twos-compl.ML/int_of_binary for
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    13
the numerical interpretation.
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    14
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    15
The representation expects that (m mod 2) is 0 or 1, even if m is negative;
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    16
For instance, ~5 div 2 = ~3 and ~5 mod 2 = 1; thus ~5 = (~3)*2 + 1
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    17
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    18
Division is not defined yet!
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    19
*)
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    20
5561
426c1e330903 Renaming of Integ/Integ.* to Integ/Int.*, and renaming of related constants
paulson
parents: 5528
diff changeset
    21
Bin = Int + Datatype + 
5528
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    22
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    23
consts
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    24
  bin_rec   :: [i, i, i, [i,i,i]=>i] => i
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    25
  integ_of  :: i=>i
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    26
  NCons     :: [i,i]=>i
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    27
  bin_succ  :: i=>i
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    28
  bin_pred  :: i=>i
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    29
  bin_minus :: i=>i
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    30
  bin_add   :: [i,i]=>i
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    31
  bin_mult  :: [i,i]=>i
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    32
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    33
  bin       :: i
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    34
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    35
syntax
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    36
  "_Int"           :: xnum => i        ("_")
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    37
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    38
datatype
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    39
  "bin" = Pls
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    40
        | Min
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    41
        | Cons ("w: bin", "b: bool")
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    42
  type_intrs "[bool_into_univ]"
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    43
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    44
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    45
defs
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    46
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    47
  bin_rec_def
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    48
      "bin_rec(z,a,b,h) == 
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    49
      Vrec(z, %z g. bin_case(a, b, %w x. h(w, x, g`w), z))"
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    50
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    51
  integ_of_def
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    52
      "integ_of(w) == bin_rec(w, $#0, $~($#1), %w x r. $#x $+ r $+ r)"
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    53
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    54
    (** recall that cond(1,b,c)=b and cond(0,b,c)=0 **)
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    55
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    56
  (*NCons adds a bit, suppressing leading 0s and 1s*)
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    57
  NCons_def
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    58
      "NCons(w,b) ==   
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    59
       bin_case(cond(b,Cons(w,b),w), cond(b,w,Cons(w,b)),   
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    60
                %w' x'. Cons(w,b), w)"
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    61
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    62
  bin_succ_def
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    63
      "bin_succ(w0) ==   
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    64
       bin_rec(w0, Cons(Pls,1), Pls,   
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    65
               %w x r. cond(x, Cons(r,0), NCons(w,1)))"
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    66
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    67
  bin_pred_def
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    68
      "bin_pred(w0) == 
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    69
       bin_rec(w0, Min, Cons(Min,0),   
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    70
               %w x r. cond(x, NCons(w,0), Cons(r,1)))"
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    71
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    72
  bin_minus_def
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    73
      "bin_minus(w0) == 
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    74
       bin_rec(w0, Pls, Cons(Pls,1),   
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    75
               %w x r. cond(x, bin_pred(NCons(r,0)), Cons(r,0)))"
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    76
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    77
  bin_add_def
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    78
      "bin_add(v0,w0) ==                        
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    79
       bin_rec(v0,                             
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    80
         lam w:bin. w,                 
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    81
         lam w:bin. bin_pred(w),       
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    82
         %v x r. lam w1:bin.           
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    83
                  bin_rec(w1, Cons(v,x), bin_pred(Cons(v,x)),    
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    84
                    %w y s. NCons(r`cond(x and y, bin_succ(w), w), 
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    85
                                          x xor y)))    ` w0"
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    86
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    87
  bin_mult_def
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    88
      "bin_mult(v0,w) ==                        
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    89
       bin_rec(v0, Pls, bin_minus(w),         
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    90
         %v x r. cond(x, bin_add(NCons(r,0),w), NCons(r,0)))"
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    91
end
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    92
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    93
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    94
ML
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    95
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    96
(** Concrete syntax for integers **)
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    97
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    98
local
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
    99
  open Syntax;
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   100
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   101
  (* Bits *)
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   102
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   103
  fun mk_bit 0 = const "0"
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   104
    | mk_bit 1 = const "succ" $ const "0"
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   105
    | mk_bit _ = sys_error "mk_bit";
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   106
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   107
  fun dest_bit (Const ("0", _)) = 0
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   108
    | dest_bit (Const ("succ", _) $ Const ("0", _)) = 1
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   109
    | dest_bit _ = raise Match;
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   110
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   111
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   112
  (* Bit strings *)   (*we try to handle superfluous leading digits nicely*)
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   113
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   114
  fun prefix_len _ [] = 0
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   115
    | prefix_len pred (x :: xs) =
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   116
        if pred x then 1 + prefix_len pred xs else 0;
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   117
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   118
  fun mk_bin str =
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   119
    let
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   120
      val (sign, digs) =
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   121
        (case Symbol.explode str of
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   122
          "#" :: "-" :: cs => (~1, cs)
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   123
        | "#" :: cs => (1, cs)
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   124
        | _ => raise ERROR);
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   125
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   126
      val zs = prefix_len (equal "0") digs;
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   127
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   128
      fun bin_of 0  = []
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   129
        | bin_of ~1 = [~1]
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   130
        | bin_of n  = (n mod 2) :: bin_of (n div 2);
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   131
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   132
      fun term_of [] = const "Pls"
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   133
        | term_of [~1] = const "Min"
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   134
        | term_of (b :: bs) = const "Cons" $ term_of bs $ mk_bit b;
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   135
    in
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   136
      term_of (bin_of (sign * (#1 (read_int digs))))
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   137
    end;
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   138
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   139
  fun dest_bin tm =
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   140
    let
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   141
      fun bin_of (Const ("Pls", _)) = []
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   142
        | bin_of (Const ("Min", _)) = [~1]
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   143
        | bin_of (Const ("Cons", _) $ bs $ b) = dest_bit b :: bin_of bs
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   144
        | bin_of _ = raise Match;
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   145
5561
426c1e330903 Renaming of Integ/Integ.* to Integ/Int.*, and renaming of related constants
paulson
parents: 5528
diff changeset
   146
      fun integ_of [] = 0
426c1e330903 Renaming of Integ/Integ.* to Integ/Int.*, and renaming of related constants
paulson
parents: 5528
diff changeset
   147
        | integ_of (b :: bs) = b + 2 * integ_of bs;
5528
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   148
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   149
      val rev_digs = bin_of tm;
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   150
      val (sign, zs) =
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   151
        (case rev rev_digs of
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   152
          ~1 :: bs => ("-", prefix_len (equal 1) bs)
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   153
        | bs => ("", prefix_len (equal 0) bs));
5561
426c1e330903 Renaming of Integ/Integ.* to Integ/Int.*, and renaming of related constants
paulson
parents: 5528
diff changeset
   154
      val num = string_of_int (abs (integ_of rev_digs));
5528
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   155
    in
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   156
      "#" ^ sign ^ implode (replicate zs "0") ^ num
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   157
    end;
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   158
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   159
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   160
  (* translation of integer constant tokens to and from binary *)
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   161
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   162
  fun int_tr (*"_Int"*) [t as Free (str, _)] =
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   163
        (const "integ_of" $
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   164
          (mk_bin str handle ERROR => raise TERM ("int_tr", [t])))
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   165
    | int_tr (*"_Int"*) ts = raise TERM ("int_tr", ts);
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   166
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   167
  fun int_tr' (*"integ_of"*) [t] = const "_Int" $ free (dest_bin t)
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   168
    | int_tr' (*"integ_of"*) _ = raise Match;
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   169
in
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   170
  val parse_translation = [("_Int", int_tr)];
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   171
  val print_translation = [("integ_of", int_tr')];
4896b4e4077b new directory for Integers
paulson
parents:
diff changeset
   172
end;