src/ZF/Tools/twos_compl.ML
author wenzelm
Mon, 17 May 2010 23:54:15 +0200
changeset 36960 01594f816e3a
parent 35762 af3ff2ba4c54
child 56280 f7de8392a507
permissions -rw-r--r--
prefer structure Keyword, Parse, Parse_Spec, Outer_Syntax; eliminated old-style structure aliases K = Keyword, P = Parse;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
24584
01e83ffa6c54 fixed title
haftmann
parents: 23146
diff changeset
     1
(*  Title:      ZF/Tools/twos_compl.ML
23146
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
     2
    Author:     Lawrence C Paulson, Cambridge University Computer Laboratory
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
     3
    Copyright   1993  University of Cambridge
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
     4
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
     5
ML code for Arithmetic on binary integers; the model for theory Bin
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
     6
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
     7
   The sign Pls stands for an infinite string of leading 0s.
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
     8
   The sign Min stands for an infinite string of leading 1s.
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
     9
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    10
See int_of_binary for the numerical interpretation.  A number can have
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    11
multiple representations, namely leading 0s with sign Pls and leading 1s with
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    12
sign Min.  A number is in NORMAL FORM if it has no such extra bits.
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    13
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    14
The representation expects that (m mod 2) is 0 or 1, even if m is negative;
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    15
For instance, ~5 div 2 = ~3 and ~5 mod 2 = 1; thus ~5 = (~3)*2 + 1
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    16
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    17
Still needs division!
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    18
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    19
print_depth 40;
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    20
System.Control.Print.printDepth := 350; 
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    21
*)
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    22
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    23
infix 5 $$ $$$
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    24
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    25
(*Recursive datatype of binary integers*)
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    26
datatype bin = Pls | Min | $$ of bin * int;
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    27
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    28
(** Conversions between bin and int **)
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    29
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    30
fun int_of_binary Pls = 0
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    31
  | int_of_binary Min = ~1
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    32
  | int_of_binary (w$$b) = 2 * int_of_binary w + b;
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    33
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    34
fun binary_of_int 0 = Pls
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    35
  | binary_of_int ~1 = Min
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    36
  | binary_of_int n = binary_of_int (n div 2) $$ (n mod 2);
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    37
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    38
(*** Addition ***)
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    39
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    40
(*Attach a bit while preserving the normal form.  Cases left as default
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    41
  are Pls$$$1 and Min$$$0. *)
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    42
fun  Pls $$$ 0 = Pls
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    43
  | Min $$$ 1 = Min
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    44
  |     v $$$ x = v$$x;
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    45
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    46
(*Successor of an integer, assumed to be in normal form.
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    47
  If w$$1 is normal then w is not Min, so bin_succ(w) $$ 0 is normal.
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    48
  But Min$$0 is normal while Min$$1 is not.*)
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    49
fun bin_succ Pls = Pls$$1
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    50
  | bin_succ Min = Pls
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    51
  | bin_succ (w$$1) = bin_succ(w) $$ 0
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    52
  | bin_succ (w$$0) = w $$$ 1;
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    53
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    54
(*Predecessor of an integer, assumed to be in normal form.
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    55
  If w$$0 is normal then w is not Pls, so bin_pred(w) $$ 1 is normal.
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    56
  But Pls$$1 is normal while Pls$$0 is not.*)
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    57
fun bin_pred Pls = Min
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    58
  | bin_pred Min = Min$$0
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    59
  | bin_pred (w$$1) = w $$$ 0
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    60
  | bin_pred (w$$0) = bin_pred(w) $$ 1;
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    61
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    62
(*Sum of two binary integers in normal form.  
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    63
  Ensure last $$ preserves normal form! *)
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    64
fun bin_add (Pls, w) = w
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    65
  | bin_add (Min, w) = bin_pred w
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    66
  | bin_add (v$$x, Pls) = v$$x
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    67
  | bin_add (v$$x, Min) = bin_pred (v$$x)
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    68
  | bin_add (v$$x, w$$y) = 
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    69
      bin_add(v, if x+y=2 then bin_succ w else w) $$$ ((x+y) mod 2);
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    70
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    71
(*** Subtraction ***)
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    72
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    73
(*Unary minus*)
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    74
fun bin_minus Pls = Pls
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    75
  | bin_minus Min = Pls$$1
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    76
  | bin_minus (w$$1) = bin_pred (bin_minus(w) $$$ 0)
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    77
  | bin_minus (w$$0) = bin_minus(w) $$ 0;
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    78
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    79
(*** Multiplication ***)
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    80
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    81
(*product of two bins; a factor of 0 might cause leading 0s in result*)
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    82
fun bin_mult (Pls, _) = Pls
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    83
  | bin_mult (Min, v) = bin_minus v
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    84
  | bin_mult (w$$1, v) = bin_add(bin_mult(w,v) $$$ 0,  v)
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    85
  | bin_mult (w$$0, v) = bin_mult(w,v) $$$ 0;
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    86
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    87
(*** Testing ***)
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    88
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    89
(*tests addition*)
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    90
fun checksum m n =
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    91
    let val wm = binary_of_int m
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    92
        and wn = binary_of_int n
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    93
        val wsum = bin_add(wm,wn)
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    94
    in  if m+n = int_of_binary wsum then (wm, wn, wsum, m+n)
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    95
        else raise Match
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    96
    end;
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    97
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    98
fun bfact n = if n=0 then  Pls$$1  
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
    99
              else  bin_mult(binary_of_int n, bfact(n-1));
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
   100
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
   101
(*Examples...
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
   102
bfact 5;
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
   103
int_of_binary it;
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
   104
bfact 69;
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
   105
int_of_binary it;
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
   106
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
   107
(*For {HOL,ZF}/ex/BinEx.ML*)
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
   108
bin_add(binary_of_int 13, binary_of_int 19);
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
   109
bin_add(binary_of_int 1234, binary_of_int 5678);
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
   110
bin_add(binary_of_int 1359, binary_of_int ~2468);
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
   111
bin_add(binary_of_int 93746, binary_of_int ~46375);
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
   112
bin_minus(binary_of_int 65745);
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
   113
bin_minus(binary_of_int ~54321);
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
   114
bin_mult(binary_of_int 13, binary_of_int 19);
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
   115
bin_mult(binary_of_int ~84, binary_of_int 51);
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
   116
bin_mult(binary_of_int 255, binary_of_int 255);
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
   117
bin_mult(binary_of_int 1359, binary_of_int ~2468);
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
   118
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
   119
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
   120
(*leading zeros??*)
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
   121
bin_add(binary_of_int 1234, binary_of_int ~1234);
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
   122
bin_mult(binary_of_int 1234, Pls);
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
   123
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
   124
(*leading ones??*)
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
   125
bin_add(binary_of_int 1, binary_of_int ~2);
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
   126
bin_add(binary_of_int 1234, binary_of_int ~1235);
0bc590051d95 moved Integ files to canonical place;
wenzelm
parents:
diff changeset
   127
*)