1 (* Title: ZF/Tools/twos_compl.ML |
|
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 |
|
20 infix 5 $$ $$$ |
|
21 |
|
22 (*Recursive datatype of binary integers*) |
|
23 datatype bin = Pls | Min | $$ of bin * int; |
|
24 |
|
25 (** Conversions between bin and int **) |
|
26 |
|
27 fun int_of_binary Pls = 0 |
|
28 | int_of_binary Min = ~1 |
|
29 | int_of_binary (w$$b) = 2 * int_of_binary w + b; |
|
30 |
|
31 fun binary_of_int 0 = Pls |
|
32 | binary_of_int ~1 = Min |
|
33 | binary_of_int n = binary_of_int (n div 2) $$ (n mod 2); |
|
34 |
|
35 (*** Addition ***) |
|
36 |
|
37 (*Attach a bit while preserving the normal form. Cases left as default |
|
38 are Pls$$$1 and Min$$$0. *) |
|
39 fun Pls $$$ 0 = Pls |
|
40 | Min $$$ 1 = Min |
|
41 | v $$$ x = v$$x; |
|
42 |
|
43 (*Successor of an integer, assumed to be in normal form. |
|
44 If w$$1 is normal then w is not Min, so bin_succ(w) $$ 0 is normal. |
|
45 But Min$$0 is normal while Min$$1 is not.*) |
|
46 fun bin_succ Pls = Pls$$1 |
|
47 | bin_succ Min = Pls |
|
48 | bin_succ (w$$1) = bin_succ(w) $$ 0 |
|
49 | bin_succ (w$$0) = w $$$ 1; |
|
50 |
|
51 (*Predecessor of an integer, assumed to be in normal form. |
|
52 If w$$0 is normal then w is not Pls, so bin_pred(w) $$ 1 is normal. |
|
53 But Pls$$1 is normal while Pls$$0 is not.*) |
|
54 fun bin_pred Pls = Min |
|
55 | bin_pred Min = Min$$0 |
|
56 | bin_pred (w$$1) = w $$$ 0 |
|
57 | bin_pred (w$$0) = bin_pred(w) $$ 1; |
|
58 |
|
59 (*Sum of two binary integers in normal form. |
|
60 Ensure last $$ preserves normal form! *) |
|
61 fun bin_add (Pls, w) = w |
|
62 | bin_add (Min, w) = bin_pred w |
|
63 | bin_add (v$$x, Pls) = v$$x |
|
64 | bin_add (v$$x, Min) = bin_pred (v$$x) |
|
65 | bin_add (v$$x, w$$y) = |
|
66 bin_add(v, if x+y=2 then bin_succ w else w) $$$ ((x+y) mod 2); |
|
67 |
|
68 (*** Subtraction ***) |
|
69 |
|
70 (*Unary minus*) |
|
71 fun bin_minus Pls = Pls |
|
72 | bin_minus Min = Pls$$1 |
|
73 | bin_minus (w$$1) = bin_pred (bin_minus(w) $$$ 0) |
|
74 | bin_minus (w$$0) = bin_minus(w) $$ 0; |
|
75 |
|
76 (*** Multiplication ***) |
|
77 |
|
78 (*product of two bins; a factor of 0 might cause leading 0s in result*) |
|
79 fun bin_mult (Pls, _) = Pls |
|
80 | bin_mult (Min, v) = bin_minus v |
|
81 | bin_mult (w$$1, v) = bin_add(bin_mult(w,v) $$$ 0, v) |
|
82 | bin_mult (w$$0, v) = bin_mult(w,v) $$$ 0; |
|
83 |
|
84 (*** Testing ***) |
|
85 |
|
86 (*tests addition*) |
|
87 fun checksum m n = |
|
88 let val wm = binary_of_int m |
|
89 and wn = binary_of_int n |
|
90 val wsum = bin_add(wm,wn) |
|
91 in if m+n = int_of_binary wsum then (wm, wn, wsum, m+n) |
|
92 else raise Match |
|
93 end; |
|
94 |
|
95 fun bfact n = if n=0 then Pls$$1 |
|
96 else bin_mult(binary_of_int n, bfact(n-1)); |
|
97 |
|
98 (*Examples... |
|
99 bfact 5; |
|
100 int_of_binary it; |
|
101 bfact 69; |
|
102 int_of_binary it; |
|
103 |
|
104 (*For {HOL,ZF}/ex/BinEx.ML*) |
|
105 bin_add(binary_of_int 13, binary_of_int 19); |
|
106 bin_add(binary_of_int 1234, binary_of_int 5678); |
|
107 bin_add(binary_of_int 1359, binary_of_int ~2468); |
|
108 bin_add(binary_of_int 93746, binary_of_int ~46375); |
|
109 bin_minus(binary_of_int 65745); |
|
110 bin_minus(binary_of_int ~54321); |
|
111 bin_mult(binary_of_int 13, binary_of_int 19); |
|
112 bin_mult(binary_of_int ~84, binary_of_int 51); |
|
113 bin_mult(binary_of_int 255, binary_of_int 255); |
|
114 bin_mult(binary_of_int 1359, binary_of_int ~2468); |
|
115 |
|
116 |
|
117 (*leading zeros??*) |
|
118 bin_add(binary_of_int 1234, binary_of_int ~1234); |
|
119 bin_mult(binary_of_int 1234, Pls); |
|
120 |
|
121 (*leading ones??*) |
|
122 bin_add(binary_of_int 1, binary_of_int ~2); |
|
123 bin_add(binary_of_int 1234, binary_of_int ~1235); |
|
124 *) |
|