Skip to content

Commit

Permalink
Minor performance improvements and cleanups in the implementation of …
Browse files Browse the repository at this point in the history
…Int32, Int64, Nativeint (#12511)

- Define `equal` directly using `=`
- In `unsigned_to_int`, use `>=` and `<=` where appropriate
- Improve `unsigned_div` by using an ad-hoc predicate `unsigned_lt`
- Remove TODO comments that are not planned
- Fix Hacker's Delight comment
  • Loading branch information
xavierleroy committed Aug 30, 2023
1 parent a6847be commit bd952ad
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 22 deletions.
4 changes: 4 additions & 0 deletions Changes
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,10 @@ Working version
(Nicolás Ojeda Bär, review by Jeremy Yallop, Xavier Leroy, Gabriel Scherer,
David Allsopp)

- #12511: Minor performance improvements and cleanups in the implementation
of modules Int32, Int64, and Nativeint
(Xavier Leroy, review by Gabriel Scherer and Daniel Bünzli)

### Other libraries:

- #12213: Dynlink library, improve legibility of error messages
Expand Down
16 changes: 9 additions & 7 deletions stdlib/int32.ml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ let unsigned_to_int =
| 32 ->
let max_int = of_int Stdlib.max_int in
fun n ->
if compare zero n <= 0 && compare n max_int <= 0 then
if n >= 0l && n <= max_int then
Some (to_int n)
else
None
Expand All @@ -74,31 +74,33 @@ let to_string n = format "%d" n
external of_string : string -> int32 = "caml_int32_of_string"

let of_string_opt s =
(* TODO: expose a non-raising primitive directly. *)
try Some (of_string s)
with Failure _ -> None

type t = int32

let compare (x: t) (y: t) = Stdlib.compare x y
let equal (x: t) (y: t) = compare x y = 0
let equal (x: t) (y: t) = x = y

let unsigned_compare n m =
compare (sub n min_int) (sub m min_int)

let unsigned_lt n m =
sub n min_int < sub m min_int

let min x y : t = if x <= y then x else y
let max x y : t = if x >= y then x else y

(* Unsigned division from signed division of the same
bitness. See Warren Jr., Henry S. (2013). Hacker's Delight (2 ed.), Sec 9-3.
(* Unsigned division from signed division of the same bitness.
See Warren Jr., Henry S. (2013). Hacker's Delight (2 ed.), Sec 9-3.
*)
let unsigned_div n d =
if d < zero then
if unsigned_compare n d < 0 then zero else one
if unsigned_lt n d then zero else one
else
let q = shift_left (div (shift_right_logical n 1) d) 1 in
let r = sub n (mul q d) in
if unsigned_compare r d >= 0 then succ q else q
if unsigned_lt r d then q else succ q

let unsigned_rem n d =
sub n (mul (unsigned_div n d) d)
Expand Down
18 changes: 9 additions & 9 deletions stdlib/int64.ml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ let lognot n = logxor n (-1L)
let unsigned_to_int =
let max_int = of_int Stdlib.max_int in
fun n ->
if compare zero n <= 0 && compare n max_int <= 0 then
if n >= 0L && n <= max_int then
Some (to_int n)
else
None
Expand All @@ -64,12 +64,9 @@ let to_string n = format "%d" n
external of_string : string -> int64 = "caml_int64_of_string"

let of_string_opt s =
(* TODO: expose a non-raising primitive directly. *)
try Some (of_string s)
with Failure _ -> None



external bits_of_float : float -> int64
= "caml_int64_bits_of_float" "caml_int64_bits_of_float_unboxed"
[@@unboxed] [@@noalloc]
Expand All @@ -80,24 +77,27 @@ external float_of_bits : int64 -> float
type t = int64

let compare (x: t) (y: t) = Stdlib.compare x y
let equal (x: t) (y: t) = compare x y = 0
let equal (x: t) (y: t) = x = y

let unsigned_compare n m =
compare (sub n min_int) (sub m min_int)

let unsigned_lt n m =
sub n min_int < sub m min_int

let min x y : t = if x <= y then x else y
let max x y : t = if x >= y then x else y

(* Unsigned division from signed division of the same
bitness. See Warren Jr., Henry S. (2013). Hacker's Delight (2 ed.), Sec 9-3.
(* Unsigned division from signed division of the same bitness.
See Warren Jr., Henry S. (2013). Hacker's Delight (2 ed.), Sec 9-3.
*)
let unsigned_div n d =
if d < zero then
if unsigned_compare n d < 0 then zero else one
if unsigned_lt n d then zero else one
else
let q = shift_left (div (shift_right_logical n 1) d) 1 in
let r = sub n (mul q d) in
if unsigned_compare r d >= 0 then succ q else q
if unsigned_lt r d then q else succ q

let unsigned_rem n d =
sub n (mul (unsigned_div n d) d)
Expand Down
14 changes: 8 additions & 6 deletions stdlib/nativeint.ml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ let lognot n = logxor n (-1n)
let unsigned_to_int =
let max_int = of_int Stdlib.max_int in
fun n ->
if compare zero n <= 0 && compare n max_int <= 0 then
if n >= 0n && n <= max_int then
Some (to_int n)
else
None
Expand All @@ -63,7 +63,6 @@ let to_string n = format "%d" n
external of_string: string -> nativeint = "caml_nativeint_of_string"

let of_string_opt s =
(* TODO: expose a non-raising primitive directly. *)
try Some (of_string s)
with Failure _ -> None

Expand All @@ -75,19 +74,22 @@ let equal (x: t) (y: t) = compare x y = 0
let unsigned_compare n m =
compare (sub n min_int) (sub m min_int)

let unsigned_lt n m =
sub n min_int < sub m min_int

let min x y : t = if x <= y then x else y
let max x y : t = if x >= y then x else y

(* Unsigned division from signed division of the same
bitness. See Warren Jr., Henry S. (2013). Hacker's Delight (2 ed.), Sec 9-3.
(* Unsigned division from signed division of the same bitness.
See Warren Jr., Henry S. (2013). Hacker's Delight (2 ed.), Sec 9-3.
*)
let unsigned_div n d =
if d < zero then
if unsigned_compare n d < 0 then zero else one
if unsigned_lt n d then zero else one
else
let q = shift_left (div (shift_right_logical n 1) d) 1 in
let r = sub n (mul q d) in
if unsigned_compare r d >= 0 then succ q else q
if unsigned_lt r d then q else succ q

let unsigned_rem n d =
sub n (mul (unsigned_div n d) d)
Expand Down

0 comments on commit bd952ad

Please sign in to comment.