author | oheimb |
Mon, 26 Jun 2000 16:18:51 +0200 | |
changeset 9147 | 9a64807da023 |
parent 6153 | bff90585cce5 |
child 9207 | 0c294bd701ea |
permissions | -rw-r--r-- |
5528 | 1 |
(* Title: ZF/ex/Bin.thy |
2 |
ID: $Id$ |
|
3 |
Author: Lawrence C Paulson, Cambridge University Computer Laboratory |
|
4 |
Copyright 1994 University of Cambridge |
|
5 |
||
6 |
Arithmetic on binary integers. |
|
7 |
||
8 |
The sign Pls stands for an infinite string of leading 0's. |
|
9 |
The sign Min stands for an infinite string of leading 1's. |
|
10 |
||
11 |
A number can have multiple representations, namely leading 0's with sign |
|
12 |
Pls and leading 1's with sign Min. See twos-compl.ML/int_of_binary for |
|
13 |
the numerical interpretation. |
|
14 |
||
15 |
The representation expects that (m mod 2) is 0 or 1, even if m is negative; |
|
16 |
For instance, ~5 div 2 = ~3 and ~5 mod 2 = 1; thus ~5 = (~3)*2 + 1 |
|
17 |
||
18 |
Division is not defined yet! |
|
19 |
*) |
|
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 | 22 |
|
6117 | 23 |
consts bin :: i |
24 |
datatype |
|
25 |
"bin" = Pls |
|
26 |
| Min |
|
6153 | 27 |
| BIT ("w: bin", "b: bool") (infixl 90) |
6117 | 28 |
|
29 |
syntax |
|
30 |
"_Int" :: xnum => i ("_") |
|
31 |
||
5528 | 32 |
consts |
33 |
integ_of :: i=>i |
|
34 |
NCons :: [i,i]=>i |
|
35 |
bin_succ :: i=>i |
|
36 |
bin_pred :: i=>i |
|
37 |
bin_minus :: i=>i |
|
38 |
bin_add :: [i,i]=>i |
|
6046 | 39 |
adding :: [i,i,i]=>i |
5528 | 40 |
bin_mult :: [i,i]=>i |
41 |
||
6046 | 42 |
primrec |
6153 | 43 |
integ_of_Pls "integ_of (Pls) = $# 0" |
44 |
integ_of_Min "integ_of (Min) = $~($#1)" |
|
45 |
integ_of_BIT "integ_of (w BIT b) = $#b $+ integ_of(w) $+ integ_of(w)" |
|
5528 | 46 |
|
47 |
(** recall that cond(1,b,c)=b and cond(0,b,c)=0 **) |
|
48 |
||
6046 | 49 |
primrec (*NCons adds a bit, suppressing leading 0s and 1s*) |
6153 | 50 |
NCons_Pls "NCons (Pls,b) = cond(b,Pls BIT b,Pls)" |
51 |
NCons_Min "NCons (Min,b) = cond(b,Min,Min BIT b)" |
|
52 |
NCons_BIT "NCons (w BIT c,b) = w BIT c BIT b" |
|
5528 | 53 |
|
6153 | 54 |
primrec (*successor. If a BIT, can change a 0 to a 1 without recursion.*) |
55 |
bin_succ_Pls "bin_succ (Pls) = Pls BIT 1" |
|
56 |
bin_succ_Min "bin_succ (Min) = Pls" |
|
57 |
bin_succ_BIT "bin_succ (w BIT b) = cond(b, bin_succ(w) BIT 0, NCons(w,1))" |
|
5528 | 58 |
|
6046 | 59 |
primrec (*predecessor*) |
6153 | 60 |
bin_pred_Pls "bin_pred (Pls) = Min" |
61 |
bin_pred_Min "bin_pred (Min) = Min BIT 0" |
|
62 |
bin_pred_BIT "bin_pred (w BIT b) = cond(b, NCons(w,0), bin_pred(w) BIT 1)" |
|
5528 | 63 |
|
6046 | 64 |
primrec (*unary negation*) |
65 |
bin_minus_Pls |
|
66 |
"bin_minus (Pls) = Pls" |
|
67 |
bin_minus_Min |
|
6153 | 68 |
"bin_minus (Min) = Pls BIT 1" |
69 |
bin_minus_BIT |
|
70 |
"bin_minus (w BIT b) = cond(b, bin_pred(NCons(bin_minus(w),0)), |
|
71 |
bin_minus(w) BIT 0)" |
|
6046 | 72 |
|
73 |
(*Mutual recursion is not always sound, but it is for primitive recursion.*) |
|
74 |
primrec (*sum*) |
|
6153 | 75 |
bin_add_Pls |
76 |
"bin_add (Pls,w) = w" |
|
77 |
bin_add_Min |
|
78 |
"bin_add (Min,w) = bin_pred(w)" |
|
79 |
bin_add_BIT |
|
80 |
"bin_add (v BIT x,w) = adding(v,x,w)" |
|
5528 | 81 |
|
6046 | 82 |
primrec (*auxilliary function for sum*) |
6153 | 83 |
"adding (v,x,Pls) = v BIT x" |
84 |
"adding (v,x,Min) = bin_pred(v BIT x)" |
|
85 |
"adding (v,x,w BIT y) = NCons(bin_add (v, cond(x and y, bin_succ(w), w)), |
|
86 |
x xor y)" |
|
5528 | 87 |
|
6046 | 88 |
primrec |
89 |
bin_mult_Pls |
|
6153 | 90 |
"bin_mult (Pls,w) = Pls" |
6046 | 91 |
bin_mult_Min |
6153 | 92 |
"bin_mult (Min,w) = bin_minus(w)" |
93 |
bin_mult_BIT |
|
94 |
"bin_mult (v BIT b,w) = cond(b, bin_add(NCons(bin_mult(v,w),0),w), |
|
95 |
NCons(bin_mult(v,w),0))" |
|
6046 | 96 |
|
5528 | 97 |
end |
98 |
||
99 |
||
100 |
ML |
|
101 |
||
102 |
(** Concrete syntax for integers **) |
|
103 |
||
104 |
local |
|
105 |
open Syntax; |
|
106 |
||
107 |
(* Bits *) |
|
108 |
||
109 |
fun mk_bit 0 = const "0" |
|
110 |
| mk_bit 1 = const "succ" $ const "0" |
|
111 |
| mk_bit _ = sys_error "mk_bit"; |
|
112 |
||
113 |
fun dest_bit (Const ("0", _)) = 0 |
|
114 |
| dest_bit (Const ("succ", _) $ Const ("0", _)) = 1 |
|
115 |
| dest_bit _ = raise Match; |
|
116 |
||
117 |
||
118 |
(* Bit strings *) (*we try to handle superfluous leading digits nicely*) |
|
119 |
||
120 |
fun prefix_len _ [] = 0 |
|
121 |
| prefix_len pred (x :: xs) = |
|
122 |
if pred x then 1 + prefix_len pred xs else 0; |
|
123 |
||
124 |
fun mk_bin str = |
|
125 |
let |
|
126 |
val (sign, digs) = |
|
127 |
(case Symbol.explode str of |
|
128 |
"#" :: "-" :: cs => (~1, cs) |
|
129 |
| "#" :: cs => (1, cs) |
|
130 |
| _ => raise ERROR); |
|
131 |
||
132 |
val zs = prefix_len (equal "0") digs; |
|
133 |
||
134 |
fun bin_of 0 = [] |
|
135 |
| bin_of ~1 = [~1] |
|
136 |
| bin_of n = (n mod 2) :: bin_of (n div 2); |
|
137 |
||
138 |
fun term_of [] = const "Pls" |
|
139 |
| term_of [~1] = const "Min" |
|
6153 | 140 |
| term_of (b :: bs) = const "op BIT" $ term_of bs $ mk_bit b; |
5528 | 141 |
in |
142 |
term_of (bin_of (sign * (#1 (read_int digs)))) |
|
143 |
end; |
|
144 |
||
145 |
fun dest_bin tm = |
|
146 |
let |
|
147 |
fun bin_of (Const ("Pls", _)) = [] |
|
148 |
| bin_of (Const ("Min", _)) = [~1] |
|
6153 | 149 |
| bin_of (Const ("op BIT", _) $ bs $ b) = dest_bit b :: bin_of bs |
5528 | 150 |
| bin_of _ = raise Match; |
151 |
||
5561
426c1e330903
Renaming of Integ/Integ.* to Integ/Int.*, and renaming of related constants
paulson
parents:
5528
diff
changeset
|
152 |
fun integ_of [] = 0 |
426c1e330903
Renaming of Integ/Integ.* to Integ/Int.*, and renaming of related constants
paulson
parents:
5528
diff
changeset
|
153 |
| integ_of (b :: bs) = b + 2 * integ_of bs; |
5528 | 154 |
|
155 |
val rev_digs = bin_of tm; |
|
156 |
val (sign, zs) = |
|
157 |
(case rev rev_digs of |
|
158 |
~1 :: bs => ("-", prefix_len (equal 1) bs) |
|
159 |
| 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
|
160 |
val num = string_of_int (abs (integ_of rev_digs)); |
5528 | 161 |
in |
162 |
"#" ^ sign ^ implode (replicate zs "0") ^ num |
|
163 |
end; |
|
164 |
||
165 |
||
166 |
(* translation of integer constant tokens to and from binary *) |
|
167 |
||
168 |
fun int_tr (*"_Int"*) [t as Free (str, _)] = |
|
169 |
(const "integ_of" $ |
|
170 |
(mk_bin str handle ERROR => raise TERM ("int_tr", [t]))) |
|
171 |
| int_tr (*"_Int"*) ts = raise TERM ("int_tr", ts); |
|
172 |
||
173 |
fun int_tr' (*"integ_of"*) [t] = const "_Int" $ free (dest_bin t) |
|
174 |
| int_tr' (*"integ_of"*) _ = raise Match; |
|
175 |
in |
|
176 |
val parse_translation = [("_Int", int_tr)]; |
|
177 |
val print_translation = [("integ_of", int_tr')]; |
|
178 |
end; |