1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
open! Import
let raise_s = Error.raise_s
module Repr = Int63_emul.Repr
module Immediate64 : sig
module type Non_immediate = sig
type t
end
module type Immediate = sig
type t [@@immediate]
end
module Make (Immediate : Immediate) (Non_immediate : Non_immediate) : sig
type t [@@immediate64]
type 'a repr =
| Immediate : Immediate.t repr
| Non_immediate : Non_immediate.t repr
val repr : t repr
end
end = struct
module type Non_immediate = sig
type t
end
module type Immediate = sig
type t [@@immediate]
end
module Make (Immediate : Immediate) (Non_immediate : Non_immediate) = struct
type t [@@immediate64]
type 'a repr =
| Immediate : Immediate.t repr
| Non_immediate : Non_immediate.t repr
let repr =
match Word_size.word_size with
| W64 -> (Caml.Obj.magic Immediate : t repr)
| W32 -> (Caml.Obj.magic Non_immediate : t repr)
;;
end
end
include Immediate64.Make (Int) (Int63_emul)
module Backend = struct
module type S = sig
type t
include Int_intf.S with type t := t
val of_int : int -> t
val to_int : t -> int option
val to_int_trunc : t -> int
val of_int32 : int32 -> t
val to_int32 : t -> Int32.t option
val to_int32_trunc : t -> Int32.t
val of_int64 : Int64.t -> t option
val of_int64_trunc : Int64.t -> t
val of_nativeint : nativeint -> t option
val to_nativeint : t -> nativeint option
val of_nativeint_trunc : nativeint -> t
val to_nativeint_trunc : t -> nativeint
val of_float_unchecked : float -> t
val repr : (t, t) Int63_emul.Repr.t
val bswap16 : t -> t
val bswap32 : t -> t
val bswap48 : t -> t
end
with type t := t
module Native = struct
include Int
let to_int x = Some x
let to_int_trunc x = x
let of_int32 = of_int32_exn
let to_nativeint_trunc x = to_nativeint x
let to_nativeint x = Some (to_nativeint x)
let repr = Int63_emul.Repr.Int
let bswap32 t = Int64.to_int_trunc (Int64.bswap32 (Int64.of_int t))
let bswap48 t = Int64.to_int_trunc (Int64.bswap48 (Int64.of_int t))
end
let impl : (module S) =
match repr with
| Immediate -> (module Native : S)
| Non_immediate -> (module Int63_emul : S)
;;
end
include (val Backend.impl : Backend.S)
module Overflow_exn = struct
let ( + ) t u =
let sum = t + u in
if bit_or (bit_xor t u) (bit_xor t (bit_not sum)) < zero
then sum
else
raise_s
(Sexp.message
"( + ) overflow"
[ "t", sexp_of_t t; "u", sexp_of_t u; "sum", sexp_of_t sum ])
;;
let ( - ) t u =
let diff = t - u in
let pos_diff = t > u in
if t <> u && Bool.( <> ) pos_diff (is_positive diff)
then
raise_s
(Sexp.message
"( - ) overflow"
[ "t", sexp_of_t t; "u", sexp_of_t u; "diff", sexp_of_t diff ])
else diff
;;
let negative_one = of_int (-1)
let div_would_overflow t u = t = min_value && u = negative_one
let ( * ) t u =
let product = t * u in
if u <> zero && (div_would_overflow product u || product / u <> t)
then
raise_s
(Sexp.message
"( * ) overflow"
[ "t", sexp_of_t t; "u", sexp_of_t u; "product", sexp_of_t product ])
else product
;;
let ( / ) t u =
if div_would_overflow t u
then
raise_s
(Sexp.message
"( / ) overflow"
[ "t", sexp_of_t t; "u", sexp_of_t u; "product", sexp_of_t (t / u) ])
else t / u
;;
let abs t = if t = min_value then failwith "abs overflow" else abs t
let neg t = if t = min_value then failwith "neg overflow" else neg t
end
let () = assert (Int.( = ) num_bits 63)
let random_of_int ?(state = Random.State.default) bound =
of_int (Random.State.int state (to_int_exn bound))
;;
let random_of_int64 ?(state = Random.State.default) bound =
of_int64_exn (Random.State.int64 state (to_int64 bound))
;;
let random =
match Word_size.word_size with
| W64 -> random_of_int
| W32 -> random_of_int64
;;
let random_incl_of_int ?(state = Random.State.default) lo hi =
of_int (Random.State.int_incl state (to_int_exn lo) (to_int_exn hi))
;;
let random_incl_of_int64 ?(state = Random.State.default) lo hi =
of_int64_exn (Random.State.int64_incl state (to_int64 lo) (to_int64 hi))
;;
let random_incl =
match Word_size.word_size with
| W64 -> random_incl_of_int
| W32 -> random_incl_of_int64
;;
let floor_log2 t =
match Word_size.word_size with
| W64 -> t |> to_int_exn |> Int.floor_log2
| W32 ->
if t <= zero
then raise_s (Sexp.message "[Int.floor_log2] got invalid input" [ "", sexp_of_t t ]);
let floor_log2 = ref (Int.( - ) num_bits 2) in
while equal zero (bit_and t (shift_left one !floor_log2)) do
floor_log2 := Int.( - ) !floor_log2 1
done;
!floor_log2
;;
module Private = struct
module Repr = Repr
let repr = repr
module Emul = Int63_emul
end