Source file int.ml
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
(** The are two version of [count_leading_zeros], [count_set_bits] each, which differ in
their native code implementation. The first version takes as input a tagged integer
and the second version takes as input an untagged integer. Generally, the first
version (that operates on a tagged integer) is faster, but if the integer is already
untagged, it may be faster to use the second version. *)
module Stubs = struct
let available = Common.available
(** [count_leading_zeros n] returns the number of most-significant zero bits before the
most significant set bit in [n]. If [n] is 0, the result is the number of bits in
[n], that is 31 or 63, depending on the target. *)
external count_leading_zeros
: int
-> (int[@untagged])
@@ portable
= "caml_int_clz" "caml_int_clz_tagged_to_untagged"
[@@noalloc] [@@no_effects] [@@no_coeffects]
external count_leading_zeros2
: int
-> int
@@ portable
= "caml_int_clz" "caml_int_clz_untagged_to_untagged"
[@@untagged] [@@noalloc] [@@no_effects] [@@no_coeffects]
(** [count_set_bits n] returns the number of bits that are 1 in [n]. *)
external count_set_bits
: int
-> (int[@untagged])
@@ portable
= "caml_int_popcnt" "caml_int_popcnt_tagged_to_untagged"
[@@noalloc] [@@no_effects] [@@no_coeffects]
external count_set_bits2
: int
-> int
@@ portable
= "caml_int_popcnt" "caml_int_popcnt_untagged_to_untagged"
[@@untagged] [@@noalloc] [@@no_effects] [@@no_coeffects]
(** [count_trailing_zeros n] returns the number of least-significant zero bits before
the least significant set bit in [n]. If [n] is 0, the result is the number of bits
in [n], that is 31 or 63, depending on the target. *)
external count_trailing_zeros
: int
-> int
@@ portable
= "caml_int_ctz" "caml_int_ctz_untagged_to_untagged"
[@@untagged] [@@noalloc] [@@no_effects] [@@no_coeffects]
end
module Naive = Naive_ints.Make (struct
include Stdlib.Int
external compare : local_ t -> local_ t -> int @@ portable = "%compare"
external equal : local_ t -> local_ t -> bool @@ portable = "%equal"
let bitwidth = Sys.int_size
let to_int = Fun.id
let of_int t = t
end)
let[@inline always] count_leading_zeros n =
match Stubs.available with
| true -> Stubs.count_leading_zeros n
| false -> Naive.count_leading_zeros n
;;
let[@inline always] count_leading_zeros2 n =
match Stubs.available with
| true -> Stubs.count_leading_zeros2 n
| false -> Naive.count_leading_zeros n
;;
let[@inline always] count_set_bits2 n =
match Stubs.available with
| true -> Stubs.count_set_bits2 n
| false -> Naive.count_set_bits n
;;
let[@inline always] count_trailing_zeros n =
match Stubs.available with
| true -> Stubs.count_trailing_zeros n
| false -> Naive.count_trailing_zeros n
;;
let[@inline always] count_set_bits n =
match Stubs.available with
| true -> Stubs.count_set_bits n
| false -> Naive.count_set_bits n
;;