diff options
author | Nicolas Ojeda Bar <n.oje.bar@gmail.com> | 2017-10-30 10:24:49 +0100 |
---|---|---|
committer | Nicolás Ojeda Bär <n.oje.bar@gmail.com> | 2018-11-10 12:48:11 +0100 |
commit | 30969895ac8470deb9341d6c950ab2f42bc1c3b4 (patch) | |
tree | 3b6f7eb01520f8d52dc702155520398c567cf4f6 /stdlib/int32.ml | |
parent | cbefaee438c9769d90db8518030c93355e7caaef (diff) | |
download | ocaml-30969895ac8470deb9341d6c950ab2f42bc1c3b4.tar.gz |
Add {Int32,Int64,Nativeint}.unsigned_{compare,div,rem}
Diffstat (limited to 'stdlib/int32.ml')
-rw-r--r-- | stdlib/int32.ml | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/stdlib/int32.ml b/stdlib/int32.ml index 9e1eabf5e4..e159851e5a 100644 --- a/stdlib/int32.ml +++ b/stdlib/int32.ml @@ -52,6 +52,22 @@ let min_int = 0x80000000l let max_int = 0x7FFFFFFFl let lognot n = logxor n (-1l) +let unsigned_to_int = + match Sys.word_size with + | 32 -> + let max_int = of_int Stdlib.max_int in + fun n -> + if compare zero n <= 0 && compare n max_int <= 0 then + Some (to_int n) + else + None + | 64 -> + (* So that it compiles in 32-bit *) + let move = int_of_string "0x1_0000_0000" in + fun n -> let i = to_int n in Some (if i < 0 then i + move else i) + | _ -> + assert false + external format : string -> int32 -> string = "caml_int32_format" let to_string n = format "%d" n @@ -66,3 +82,20 @@ type t = int32 let compare (x: t) (y: t) = Stdlib.compare x y let equal (x: t) (y: t) = compare x y = 0 + +let unsigned_compare n m = + compare (sub n min_int) (sub m min_int) + +(* 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 + 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 + +let unsigned_rem n d = + sub n (mul (unsigned_div n d) d) |