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