Merge pull request #308 from FardaleM/ccint

CCInt{,32,64} and CCNativeint
This commit is contained in:
Fardale 2020-05-24 00:53:08 +02:00 committed by GitHub
commit 685efeae28
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 1212 additions and 394 deletions

View file

@ -3,9 +3,35 @@
open CCShims_
include CCShimsInt_
type t = int
type 'a iter = ('a -> unit) -> unit
let zero = 0
let one = 1
let minus_one = -1
let add = (+)
let sub = (-)
let mul = ( * )
let div = (/)
let succ = succ
let pred = pred
let abs = abs
let max_int = max_int
let min_int = min_int
let equal (a:int) b = Stdlib.(=) a b
let compare (a:int) b = compare a b
@ -45,10 +71,7 @@ let range' i j yield =
[5;4;3] (range' 5 2 |> Iter.to_list)
*)
let sign i =
if i < 0 then -1
else if i>0 then 1
else 0
let sign i = compare i 0
let neg i = -i
@ -211,6 +234,8 @@ let of_string s =
let of_string_exn = Stdlib.int_of_string
let to_float = float_of_int
let of_float = int_of_float
(*$=
@ -267,7 +292,7 @@ let range_by ~step i j yield =
)
in
if step = 0 then
raise (Invalid_argument "CCList.range_by")
raise (Invalid_argument "CCInt.range_by")
else if (if step > 0 then i>j else i<j) then ()
else range i ((j-i)/step*step + i) yield
@ -359,3 +384,17 @@ let popcount (b:int) : int =
);
true)
*)
let logand = (land)
let logor = (lor)
let logxor = (lxor)
let lognot = lnot
let shift_left = (lsl)
let shift_right = (asr)
let shift_right_logical = (lsr)

View file

@ -3,10 +3,61 @@
(** {1 Basic Int functions} *)
include module type of CCShimsInt_
type t = int
val zero : t
(** [zero] is the integer [0].
@since NEXT_RELEASE *)
val one : t
(** [one] is the integer [1].
@since NEXT_RELEASE *)
val minus_one : t
(** [minus_one] is the integer [-1].
@since NEXT_RELEASE *)
val add : t -> t -> t
(** [add x y] is [x + y].
@since NEXT_RELEASE *)
val sub : t -> t -> t
(** [sub x y] is [x - y].
@since NEXT_RELEASE *)
val mul : t -> t -> t
(** [mul x y] is [x * y].
@since NEXT_RELEASE *)
val div : t -> t -> t
(** [div x y] is [x / y]
@since NEXT_RELEASE *)
val succ : t -> t
(** [succ x] is [x + 1].
@since NEXT_RELEASE *)
val pred : t -> t
(** [pred x] is [x - 1].
@since NEXT_RELEASE *)
val abs : t -> t
(** [abs x] is the absolute value of [x]. It is [x] if [x] is positive
and [neg x] otherwise.
@since NEXT_RELEASE *)
val max_int : t
(** [max_int] is the maximum integer.
@since NEXT_RELEASE *)
val min_int : t
(** [min_int] is the minimum integer.
@since NEXT_RELEASE *)
val compare : t -> t -> int
(** [compare x y] is the comparison function for integers
(** [compare x y] is the comparison function for integers
with the same specification as {!Stdlib.compare}. *)
val equal : t -> t -> bool
@ -15,9 +66,10 @@ val equal : t -> t -> bool
val hash : t -> int
(** [hash x] computes the hash of [x]. *)
val sign : t -> int
(** [sign x] is one of [-1, 0, 1]. *)
(** [sign x] return [0] if [x = 0], [-1] if [x < 0] and [1] if [x > 0].
Same as [compare x 0].*)
val neg : t -> t
(** [neg x] is [- x].
@ -49,7 +101,15 @@ val random_small : t random_gen
val random_range : int -> int -> t random_gen
val pp : t printer
(** [pp ppf x] prints the integer [x] on [ppf]. *)
(** [pp ppf x] prints the integer [x] on [ppf]. *)
val to_float : t -> float
(** [to_float] is the same as [float_of_int]
@since NEXT_RELEASE*)
val of_float : float -> t
(** [to_float] is the same as [int_of_float]
@since NEXT_RELEASE*)
val to_string : t -> string
(** [to_string x] returns the string representation of the integer [x], in signed decimal.
@ -109,6 +169,34 @@ val popcount : t -> int
(** Number of bits set to 1
@since NEXT_RELEASE *)
val logand : t -> t -> t
(** [logand] is the same as [(land)].
@since NEXT_RELEASE *)
val logor : t -> t -> t
(** [logand] is the same as [(lor)].
@since NEXT_RELEASE *)
val logxor : t -> t -> t
(** [logxor] is the same as [(lxor)].
@since NEXT_RELEASE *)
val lognot : t -> t
(** [logand] is the same as [lnot].
@since NEXT_RELEASE *)
val shift_left : t -> int -> t
(** [shift_left] is the same as [(lsl)].
@since NEXT_RELEASE *)
val shift_right : t -> int -> t
(** [shift_right] is the same as [(asr)].
@since NEXT_RELEASE *)
val shift_right_logical : t -> int -> t
(** [shift_right_logical] is the same as [(lsr)].
@since NEXT_RELEASE *)
(** {2 Infix Operators}
@since 0.17 *)

View file

@ -3,6 +3,200 @@
open CCShims_
include Int32
let min : t -> t -> t = Stdlib.min
let max : t -> t -> t = Stdlib.max
let hash x = Stdlib.abs (to_int x)
let sign i = compare i zero
let pow a b =
let rec aux acc = function
| 1l -> acc
| n ->
if equal (rem n 2l) zero
then aux (mul acc acc) (div n 2l)
else mul acc (aux (mul acc acc) (div n 2l))
in
match b with
| 0l -> if equal a 0l then raise (Invalid_argument "pow: undefined value 0^0") else 1l
| b when compare b 0l < 0 -> raise (Invalid_argument "pow: can't raise int to negative power")
| b -> aux a b
(*$T
pow 2l 10l = 1024l
pow 2l 15l = 32768l
pow 10l 5l = 100000l
pow 42l 0l = 1l
pow 0l 1l = 0l
*)
let floor_div a n =
if compare a 0l < 0 && compare n 0l >= 0 then
sub (div (add a 1l) n) 1l
else if compare a 0l > 0 && compare n 0l < 0 then
sub (div (sub a 1l) n) 1l
else
div a n
(*$T
(floor_div 3l 5l = 0l)
(floor_div 5l 5l = 1l)
(floor_div 20l 5l = 4l)
(floor_div 12l 5l = 2l)
(floor_div 0l 5l = 0l)
(floor_div (-1l) 5l = -1l)
(floor_div (-5l) 5l = -1l)
(floor_div (-12l) 5l = -3l)
(floor_div 0l (-5l) = 0l)
(floor_div 3l (-5l) = -1l)
(floor_div 5l (-5l) = -1l)
(floor_div 9l (-5l) = -2l)
(floor_div 20l (-5l) = -4l)
(floor_div (-2l) (-5l) = 0l)
(floor_div (-8l) (-5l) = 1l)
(floor_div (-35l) (-5l) = 7l)
try ignore (floor_div 12l 0l); false with Division_by_zero -> true
try ignore (floor_div (-12l) 0l); false with Division_by_zero -> true
*)
(*$Q
(Q.pair (Q.map of_int Q.small_signed_int) (Q.map of_int Q.small_nat)) \
(fun (n, m) -> let m = m + 1l in \
floor_div n m = of_float @@ floor (to_float n /. to_float m))
(Q.pair (Q.map of_int Q.small_signed_int) (Q.map of_int Q.small_nat)) \
(fun (n, m) -> let m = m + 1l in \
floor_div n (-m) = of_float @@ floor (to_float n /. to_float (-m)))
*)
type 'a printer = Format.formatter -> 'a -> unit
type 'a random_gen = Random.State.t -> 'a
type 'a iter = ('a -> unit) -> unit
let range i j yield =
let rec up i j yield =
if equal i j then yield i
else (
yield i;
up (add i 1l) j yield
)
and down i j yield =
if equal i j then yield i
else (
yield i;
down (sub i 1l) j yield
)
in
if compare i j <= 0 then up i j yield else down i j yield
(*$= & ~printer:Q.Print.(list to_string)
[0l;1l;2l;3l;4l;5l] (range 0l 5l |> Iter.to_list)
[0l] (range 0l 0l |> Iter.to_list)
[5l;4l;3l;2l] (range 5l 2l |> Iter.to_list)
*)
let range' i j yield =
if compare i j < 0 then range i (sub j 1l) yield
else if equal i j then ()
else range i (add j 1l) yield
let range_by ~step i j yield =
let rec range i j yield =
if equal i j then yield i
else (
yield i;
range (add i step) j yield
)
in
if equal step 0l then
raise (Invalid_argument "CCInt32.range_by")
else if (if compare step 0l > 0 then compare i j > 0 else compare i j < 0) then ()
else range i (add (mul (div (sub j i) step) step) i) yield
(* note: the last test checks that no error occurs due to overflows. *)
(*$= & ~printer:Q.Print.(list to_string)
[0l] (range_by ~step:1l 0l 0l |> Iter.to_list)
[] (range_by ~step:1l 5l 0l |> Iter.to_list)
[] (range_by ~step:2l 1l 0l |> Iter.to_list)
[0l;2l;4l] (range_by ~step:2l 0l 4l |> Iter.to_list)
[0l;2l;4l] (range_by ~step:2l 0l 5l |> Iter.to_list)
[0l] (range_by ~step:(neg 1l) 0l 0l |> Iter.to_list)
[] (range_by ~step:(neg 1l) 0l 5l |> Iter.to_list)
[] (range_by ~step:(neg 2l) 0l 1l |> Iter.to_list)
[5l;3l;1l] (range_by ~step:(neg 2l) 5l 1l |> Iter.to_list)
[5l;3l;1l] (range_by ~step:(neg 2l) 5l 0l |> Iter.to_list)
[0l] (range_by ~step:max_int 0l 2l |> Iter.to_list)
*)
(*$Q
Q.(pair (map of_int small_int) (map of_int small_int)) (fun (i,j) -> \
let i = min i j and j = max i j in \
CCList.equal CCInt32.equal \
(CCInt32.range_by ~step:1l i j |> Iter.to_list) \
(CCInt32.range i j |> Iter.to_list) )
*)
let random n st = Random.State.int32 st n
let random_small = random 100l
let random_range i j st = add i (random (sub j i) st)
(** {2 Conversion} *)
let of_string_exn = of_string
let of_string x = try Some (of_string_exn x) with Failure _ -> None
let of_string_opt = of_string
let most_significant_bit =
logxor (neg 1l) (shift_right_logical (neg 1l) 1)
type output = char -> unit
(* abstract printer *)
let to_binary_gen (out:output) n =
let n = if compare n 0l <0 then (out '-'; neg n) else n in
out '0'; out 'b';
let rec loop started bit n =
if equal bit 0l then (
if not started then out '0'
) else (
let b = logand n bit in
if equal b 0l then (
if started then out '0';
loop started (shift_right_logical bit 1) n
) else (
out '1';
loop true (shift_right_logical bit 1) n
)
)
in
loop false most_significant_bit n
let to_string_binary n =
let buf = Buffer.create 16 in
to_binary_gen (Buffer.add_char buf) n;
Buffer.contents buf
(*$= & ~printer:CCFun.id
"0b111" (to_string_binary 7l)
"-0b111" (to_string_binary (-7l))
"0b0" (to_string_binary 0l)
*)
(** {2 Printing} *)
let pp out n = Format.pp_print_string out (to_string n)
let pp_binary out n =
to_binary_gen (Format.pp_print_char out) n
(** {2 Infix Operators} *)
module Infix = struct
let (+) = add
@ -14,6 +208,12 @@ module Infix = struct
let (/) = div
let ( ** ) = pow
let (--) = range
let (--^) = range'
let (mod) = rem
let (land) = logand
@ -39,12 +239,3 @@ module Infix = struct
let (>=) = Stdlib.(>=)
end
include Infix
let hash x = Stdlib.abs (to_int x)
(** {2 Conversion} *)
let of_string_exn = of_string
let of_string x = try Some (of_string_exn x) with Failure _ -> None
let of_string_opt = of_string

View file

@ -17,116 +17,69 @@
include module type of struct include Int32 end
val ( + ) : t -> t -> t
(** [x + y] is the sum of [x] and [y].
Addition. *)
val min : t -> t -> t
(** [min x y] returns the minimum of the two integers [x] and [y].
@since NEXT_RELEASE *)
val ( - ) : t -> t -> t
(** [x - y] is the difference of [x] and [y].
Subtraction. *)
val ( ~- ) : t -> t
(** [~- x] is the negation of [x].
Unary negation. *)
val ( * ) : t -> t -> t
(** [ x * y] is the product of [x] and [y].
Multiplication. *)
val ( / ) : t -> t -> t
(** [x / y] is the integer quotient of [x] and [y].
Integer division. Raise [Division_by_zero] if the second
argument [y] is zero. This division rounds the real quotient of
its arguments towards zero, as specified for {!Stdlib.(/)}. *)
val ( mod ) : t -> t -> t
(** [x mod y] is the integer remainder of [x / y].
If [y <> zero], the result of [x mod y] satisfies the following property:
[x = ((x / y) * y) + (x mod y)].
If [y = 0], [x mod y] raises [Division_by_zero]. *)
val ( land ) : t -> t -> t
(** [x land y] is the bitwise logical and of [x] and [y]. *)
val ( lor ) : t -> t -> t
(** [x lor y] is the bitwise logical or of [x] and [y]. *)
val ( lxor ) : t -> t -> t
(** [x lxor y] is the bitwise logical exclusive or of [x] and [y]. *)
val lnot : t -> t
(** [lnot x] is the bitwise logical negation of [x] (the bits of [x] are inverted). *)
val ( lsl ) : t -> int -> t
(** [ x lsl y] shifts [x] to the left by [y] bits, filling in with zeroes.
The result is unspecified if [y < 0] or [y >= 32]. *)
val ( lsr ) : t -> int -> t
(** [x lsr y] shifts [x] to the right by [y] bits.
This is a logical shift: zeroes are inserted in the vacated bits
regardless of the sign of [x].
The result is unspecified if [y < 0] or [y >= 32]. *)
val ( asr ) : t -> int -> t
(** [x asr y] shifts [x] to the right by [y] bits.
This is an arithmetic shift: the sign bit of [x] is replicated
and inserted in the vacated bits.
The result is unspecified if [y < 0] or [y >= 32]. *)
module Infix : sig
val (+) : t -> t -> t
val (-) : t -> t -> t
val (~-) : t -> t
val ( * ) : t -> t -> t
val (/) : t -> t -> t
val (mod) : t -> t -> t
val (land) : t -> t -> t
val (lor) : t -> t -> t
val (lxor) : t -> t -> t
val lnot : t -> t
val (lsl) : t -> int -> t
val (lsr) : t -> int -> t
val (asr) : t -> int -> t
val (=) : t -> t -> bool
val (<>) : t -> t -> bool
val (>) : t -> t -> bool
val (>=) : t -> t -> bool
val (<=) : t -> t -> bool
val (<) : t -> t -> bool
end
include module type of Infix
val max : t -> t -> t
(** [max x y] returns the maximum of the two integers [x] and [y].
@since NEXT_RELEASE *)
val hash : t -> int
(** [hash x] computes the hash of [x].
Like {!Stdlib.abs (to_int x)}. *)
val sign : t -> int
(** [sign x] return [0] if [x = 0], [-1] if [x < 0] and [1] if [x > 0].
Same as [compare x zero].
@since NEXT_RELEASE*)
val pow : t -> t -> t
(** [pow base exponent] returns [base] raised to the power of [exponent].
[pow x y = x^y] for positive integers [x] and [y].
Raises [Invalid_argument] if [x = y = 0] or [y] < 0.
@since 0.11 *)
val floor_div : t -> t -> t
(** [floor_div x n] is integer division rounding towards negative infinity.
It satisfies [x = m * floor_div x n + rem x n].
@since NEXT_RELEASE *)
type 'a printer = Format.formatter -> 'a -> unit
type 'a random_gen = Random.State.t -> 'a
type 'a iter = ('a -> unit) -> unit
val range_by : step:t -> t -> t -> t iter
(** [range_by ~step i j] iterates on integers from [i] to [j] included,
where the difference between successive elements is [step].
Use a negative [step] for a decreasing list.
@raise Invalid_argument if [step=0].
@since NEXT_RELEASE *)
val range : t -> t -> t iter
(** [range i j] iterates on integers from [i] to [j] included . It works
both for decreasing and increasing ranges.
@since NEXT_RELEASE *)
val range' : t -> t -> t iter
(** [range' i j] is like {!range} but the second bound [j] is excluded.
For instance [range' 0 5 = Iter.of_list [0;1;2;3;4]].
@since NEXT_RELEASE *)
val random : t -> t random_gen
val random_small : t random_gen
val random_range : t -> t -> t random_gen
(** {2 Conversion} *)
val to_int : t -> int
(** [to_int x] converts the given 32-bit integer [x] (type [int32]) into an
integer (type [int]). On 32-bit platforms, the 32-bit integer
is taken modulo 2{^31}, i.e. the high-order bit is lost
during the conversion. On 64-bit platforms, the conversion is exact. *)
val of_string : string -> t option
(** [of_string s] is the safe version of {!of_string_exn}.
Like {!of_string_exn}, but return [None] instead of raising. *)
val of_int : int -> t
(** [of_int x] converts the given integer [x] (type [int]) into an
32-bit integer (type [int32]).
Alias to {!Int32.of_int}. *)
val to_float : t -> float
(** [to_float x] converts the given 32-bit integer [x]
into a floating-point number (type [float]). *)
val of_float : float -> t
(** [of_float x] converts the given floating-point number [x] into a 32-bit integer,
discarding the fractional part (truncate towards 0).
The result of the conversion is undefined if, after truncation, the number
is outside the range \[{!CCInt32.min_int}, {!CCInt32.max_int}\].
Alias to {!Int32.of_float}. *)
val to_string : t -> string
(** [to_string x] returns the string representation of its argument [x], in signed decimal. *)
val of_string_opt : string -> t option
(** [of_string_opt s] is an alias to {!of_string}. *)
val of_string_exn : string -> t
(** [of_string_exn s] converts the given string [s] into a 32-bit integer.
@ -146,9 +99,101 @@ val of_string_exn : string -> t
a valid representation of an integer, or if the integer represented
exceeds the range of integers representable in type [int32]. *)
val of_string : string -> t option
(** [of_string s] is the safe version of {!of_string_exn}.
Like {!of_string_exn}, but return [None] instead of raising. *)
val to_string_binary : t -> string
(** [to_string_binary x] returns the string representation of the integer [x], in binary.
@since NEXT_RELEASE *)
val of_string_opt : string -> t option
(** [of_string_opt s] is an alias to {!of_string}. *)
(** {2 Printing} *)
val pp : t printer
(** [pp ppf x] prints the integer [x] on [ppf].
@since NEXT_RELEASE *)
val pp_binary : t printer
(** [pp_binary ppf x] prints [x] on [ppf].
Print as "0b00101010".
@since NEXT_RELEASE *)
(** {2 Infix Operators} *)
module Infix : sig
val ( + ) : t -> t -> t
(** [x + y] is the sum of [x] and [y].
Addition. *)
val ( - ) : t -> t -> t
(** [x - y] is the difference of [x] and [y].
Subtraction. *)
val ( ~- ) : t -> t
(** [~- x] is the negation of [x].
Unary negation. *)
val ( * ) : t -> t -> t
(** [ x * y] is the product of [x] and [y].
Multiplication. *)
val ( / ) : t -> t -> t
(** [x / y] is the integer quotient of [x] and [y].
Integer division. Raise [Division_by_zero] if the second
argument [y] is zero. This division rounds the real quotient of
its arguments towards zero, as specified for {!Stdlib.(/)}. *)
val ( mod ) : t -> t -> t
(** [x mod y] is the integer remainder of [x / y].
If [y <> zero], the result of [x mod y] satisfies the following properties:
[zero <= x mod y < abs y] and
[x = ((x / y) * y) + (x mod y)].
If [y = 0], [x mod y] raises [Division_by_zero]. *)
val ( ** ) : t -> t -> t
(** Alias to {!pow}
@since NEXT_RELEASE *)
val (--) : t -> t -> t iter
(** Alias to {!range}.
@since NEXT_RELEASE *)
val (--^) : t -> t -> t iter
(** Alias to {!range'}.
@since NEXT_RELEASE *)
val ( land ) : t -> t -> t
(** [x land y] is the bitwise logical and of [x] and [y]. *)
val ( lor ) : t -> t -> t
(** [x lor y] is the bitwise logical or of [x] and [y]. *)
val ( lxor ) : t -> t -> t
(** [x lxor y] is the bitwise logical exclusive or of [x] and [y]. *)
val lnot : t -> t
(** [lnot x] is the bitwise logical negation of [x] (the bits of [x] are inverted). *)
val ( lsl ) : t -> int -> t
(** [ x lsl y] shifts [x] to the left by [y] bits, filling in with zeroes.
The result is unspecified if [y < 0] or [y >= 32]. *)
val ( lsr ) : t -> int -> t
(** [x lsr y] shifts [x] to the right by [y] bits.
This is a logical shift: zeroes are inserted in the vacated bits
regardless of the sign of [x].
The result is unspecified if [y < 0] or [y >= 32]. *)
val ( asr ) : t -> int -> t
(** [x asr y] shifts [x] to the right by [y] bits.
This is an arithmetic shift: the sign bit of [x] is replicated
and inserted in the vacated bits.
The result is unspecified if [y < 0] or [y >= 32]. *)
val (=) : t -> t -> bool
val (<>) : t -> t -> bool
val (>) : t -> t -> bool
val (>=) : t -> t -> bool
val (<=) : t -> t -> bool
val (<) : t -> t -> bool
end
include module type of Infix

View file

@ -3,6 +3,200 @@
open CCShims_
include Int64
let min : t -> t -> t = Stdlib.min
let max : t -> t -> t = Stdlib.max
let hash x = Stdlib.abs (to_int x)
let sign i = compare i zero
let pow a b =
let rec aux acc = function
| 1L -> acc
| n ->
if equal (rem n 2L) zero
then aux (mul acc acc) (div n 2L)
else mul acc (aux (mul acc acc) (div n 2L))
in
match b with
| 0L -> if equal a 0L then raise (Invalid_argument "pow: undefined value 0^0") else 1L
| b when compare b 0L < 0 -> raise (Invalid_argument "pow: can't raise int to negative power")
| b -> aux a b
(*$T
pow 2L 10L = 1024L
pow 2L 15L = 32768L
pow 10L 5L = 100000L
pow 42L 0L = 1L
pow 0L 1L = 0L
*)
let floor_div a n =
if compare a 0L < 0 && compare n 0L >= 0 then
sub (div (add a 1L) n) 1L
else if compare a 0L > 0 && compare n 0L < 0 then
sub (div (sub a 1L) n) 1L
else
div a n
(*$T
(floor_div 3L 5L = 0L)
(floor_div 5L 5L = 1L)
(floor_div 20L 5L = 4L)
(floor_div 12L 5L = 2L)
(floor_div 0L 5L = 0L)
(floor_div (-1L) 5L = -1L)
(floor_div (-5L) 5L = -1L)
(floor_div (-12L) 5L = -3L)
(floor_div 0L (-5L) = 0L)
(floor_div 3L (-5L) = -1L)
(floor_div 5L (-5L) = -1L)
(floor_div 9L (-5L) = -2L)
(floor_div 20L (-5L) = -4L)
(floor_div (-2L) (-5L) = 0L)
(floor_div (-8L) (-5L) = 1L)
(floor_div (-35L) (-5L) = 7L)
try ignore (floor_div 12L 0L); false with Division_by_zero -> true
try ignore (floor_div (-12L) 0L); false with Division_by_zero -> true
*)
(*$Q
(Q.pair (Q.map of_int Q.small_signed_int) (Q.map of_int Q.small_nat)) \
(fun (n, m) -> let m = m + 1L in \
floor_div n m = of_float @@ floor (to_float n /. to_float m))
(Q.pair (Q.map of_int Q.small_signed_int) (Q.map of_int Q.small_nat)) \
(fun (n, m) -> let m = m + 1L in \
floor_div n (-m) = of_float @@ floor (to_float n /. to_float (-m)))
*)
type 'a printer = Format.formatter -> 'a -> unit
type 'a random_gen = Random.State.t -> 'a
type 'a iter = ('a -> unit) -> unit
let range i j yield =
let rec up i j yield =
if equal i j then yield i
else (
yield i;
up (add i 1L) j yield
)
and down i j yield =
if equal i j then yield i
else (
yield i;
down (sub i 1L) j yield
)
in
if compare i j <= 0 then up i j yield else down i j yield
(*$= & ~printer:Q.Print.(list to_string)
[0L;1L;2L;3L;4L;5L] (range 0L 5L |> Iter.to_list)
[0L] (range 0L 0L |> Iter.to_list)
[5L;4L;3L;2L] (range 5L 2L |> Iter.to_list)
*)
let range' i j yield =
if compare i j < 0 then range i (sub j 1L) yield
else if equal i j then ()
else range i (add j 1L) yield
let range_by ~step i j yield =
let rec range i j yield =
if equal i j then yield i
else (
yield i;
range (add i step) j yield
)
in
if equal step 0L then
raise (Invalid_argument "CCInt64.range_by")
else if (if compare step 0L > 0 then compare i j > 0 else compare i j < 0) then ()
else range i (add (mul (div (sub j i) step) step) i) yield
(* note: the last test checks that no error occurs due to overflows. *)
(*$= & ~printer:Q.Print.(list to_string)
[0L] (range_by ~step:1L 0L 0L |> Iter.to_list)
[] (range_by ~step:1L 5L 0L |> Iter.to_list)
[] (range_by ~step:2L 1L 0L |> Iter.to_list)
[0L;2L;4L] (range_by ~step:2L 0L 4L |> Iter.to_list)
[0L;2L;4L] (range_by ~step:2L 0L 5L |> Iter.to_list)
[0L] (range_by ~step:(neg 1L) 0L 0L |> Iter.to_list)
[] (range_by ~step:(neg 1L) 0L 5L |> Iter.to_list)
[] (range_by ~step:(neg 2L) 0L 1L |> Iter.to_list)
[5L;3L;1L] (range_by ~step:(neg 2L) 5L 1L |> Iter.to_list)
[5L;3L;1L] (range_by ~step:(neg 2L) 5L 0L |> Iter.to_list)
[0L] (range_by ~step:max_int 0L 2L |> Iter.to_list)
*)
(*$Q
Q.(pair (map of_int small_int) (map of_int small_int)) (fun (i,j) -> \
let i = min i j and j = max i j in \
CCList.equal CCInt64.equal \
(CCInt64.range_by ~step:1L i j |> Iter.to_list) \
(CCInt64.range i j |> Iter.to_list) )
*)
let random n st = Random.State.int64 st n
let random_small = random 100L
let random_range i j st = add i (random (sub j i) st)
(** {2 Conversion} *)
let of_string_exn = of_string
let of_string x = try Some (of_string_exn x) with Failure _ -> None
let of_string_opt = of_string
let most_significant_bit =
logxor (neg 1L) (shift_right_logical (neg 1L) 1)
type output = char -> unit
(* abstract printer *)
let to_binary_gen (out:output) n =
let n = if compare n 0L <0 then (out '-'; neg n) else n in
out '0'; out 'b';
let rec loop started bit n =
if equal bit 0L then (
if not started then out '0'
) else (
let b = logand n bit in
if equal b 0L then (
if started then out '0';
loop started (shift_right_logical bit 1) n
) else (
out '1';
loop true (shift_right_logical bit 1) n
)
)
in
loop false most_significant_bit n
let to_string_binary n =
let buf = Buffer.create 16 in
to_binary_gen (Buffer.add_char buf) n;
Buffer.contents buf
(*$= & ~printer:CCFun.id
"0b111" (to_string_binary 7L)
"-0b111" (to_string_binary (-7L))
"0b0" (to_string_binary 0L)
*)
(** {2 Printing} *)
let pp out n = Format.pp_print_string out (to_string n)
let pp_binary out n =
to_binary_gen (Format.pp_print_char out) n
(** {2 Infix Operators} *)
module Infix = struct
let (+) = add
@ -14,6 +208,12 @@ module Infix = struct
let (/) = div
let ( ** ) = pow
let (--) = range
let (--^) = range'
let (mod) = rem
let (land) = logand
@ -38,14 +238,4 @@ module Infix = struct
let (>) = Stdlib.(>)
let (>=) = Stdlib.(>=)
end
include Infix
let hash x = Stdlib.abs (to_int x)
(** {2 Conversion} *)
let of_string_exn = of_string
let of_string x = try Some (of_string_exn x) with Failure _ -> None
let of_string_opt = of_string

View file

@ -2,169 +2,81 @@
(** {1 Int64}
Helpers for 64-bit integers
Helpers for 64-bit integers.
This module provides operations on the type int64 of signed 64-bit integers.
Unlike the built-in int type, the type int64 is guaranteed to be exactly
64-bit wide on all platforms. All arithmetic operations over int64 are taken
modulo 2{^64}.
Performance notice: values of type int64 occupy more memory space than values
of type int, and arithmetic operations on int64 are generally slower than
those on int. Use int64 only when the application requires exact 64-bit arithmetic.
@since 0.13 *)
include module type of struct include Int64 end
val ( + ) : t -> t -> t
(** [x + y] is the sum of [x] and [y].
Addition. *)
val min : t -> t -> t
(** [min x y] returns the minimum of the two integers [x] and [y].
@since NEXT_RELEASE *)
val ( - ) : t -> t -> t
(** [x - y] is the difference of [x] and [y].
Subtraction. *)
val ( ~- ) : t -> t
(** [~- x] is the negation of [x].
Unary negation. *)
val ( * ) : t -> t -> t
(** [ x * y] is the product of [x] and [y].
Multiplication. *)
val ( / ) : t -> t -> t
(** [x / y] is the integer quotient of [x] and [y].
Integer division. Raise [Division_by_zero] if the second
argument [y] is zero. This division rounds the real quotient of
its arguments towards zero, as specified for {!Stdlib.(/)}. *)
val ( mod ) : t -> t -> t
(** [x mod y] is the integer remainder of [x / y].
If [y <> zero], the result of [x mod y] satisfies the following property:
[x = ((x / y) * y) + (x mod y)].
If [y = 0], [x mod y] raises [Division_by_zero]. *)
val abs : t -> t
(** [abs x] returns the absolute value (or magnitude) of its argument [x]. *)
val max_int : t
(** [max_int] is the greatest representable 64-bit integer, 2{^63} - 1 = [9_223_372_036_854_775_807]. *)
val min_int : t
(** [min_int] is the smallest representable 64-bit integer, -2{^63} = [-9_223_372_036_854_775_808]. *)
val ( land ) : t -> t -> t
(** [x land y] is the bitwise logical and of [x] and [y]. *)
val ( lor ) : t -> t -> t
(** [x lor y] is the bitwise logical or of [x] and [y]. *)
val ( lxor ) : t -> t -> t
(** [x lxor y] is the bitwise logical exclusive or of [x] and [y]. *)
val lnot : t -> t
(** [lnot x] is the bitwise logical negation of [x] (the bits of [x] are inverted). *)
val ( lsl ) : t -> int -> t
(** [ x lsl y] shifts [x] to the left by [y] bits, filling in with zeroes.
The result is unspecified if [y < 0] or [y >= 64]. *)
val ( lsr ) : t -> int -> t
(** [x lsr y] shifts [x] to the right by [y] bits.
This is a logical shift: zeroes are inserted in the vacated bits
regardless of the sign of [x].
The result is unspecified if [y < 0] or [y >= 64]. *)
val ( asr ) : t -> int -> t
(** [x asr y] shifts [x] to the right by [y] bits.
This is an arithmetic shift: the sign bit of [x] is replicated
and inserted in the vacated bits.
The result is unspecified if [y < 0] or [y >= 64]. *)
(** Infix operators
@since 2.1 *)
module Infix : sig
val (+) : t -> t -> t
val (-) : t -> t -> t
val (~-) : t -> t
val ( * ) : t -> t -> t
val (/) : t -> t -> t
val (mod) : t -> t -> t
val (land) : t -> t -> t
val (lor) : t -> t -> t
val (lxor) : t -> t -> t
val lnot : t -> t
val (lsl) : t -> int -> t
val (lsr) : t -> int -> t
val (asr) : t -> int -> t
val (=) : t -> t -> bool
val (<>) : t -> t -> bool
val (>) : t -> t -> bool
val (>=) : t -> t -> bool
val (<=) : t -> t -> bool
val (<) : t -> t -> bool
end
include module type of Infix
val compare : t -> t -> int
(** [compare x y] is the comparison function for 64-bit integers, with the same specification as
{!Stdlib.compare}. Along with the type [t], this function [compare]
allows the module [CCInt64] to be passed as argument to the functors
{!Set.Make} and {!Map.Make}. *)
val max : t -> t -> t
(** [max x y] returns the maximum of the two integers [x] and [y].
@since NEXT_RELEASE *)
val hash : t -> int
(** [hash x] computes the hash of [x].
Like {!Stdlib.abs (to_int x)}. *)
val sign : t -> int
(** [sign x] return [0] if [x = 0], [-1] if [x < 0] and [1] if [x > 0].
Same as [compare x zero].
@since NEXT_RELEASE*)
val pow : t -> t -> t
(** [pow base exponent] returns [base] raised to the power of [exponent].
[pow x y = x^y] for positive integers [x] and [y].
Raises [Invalid_argument] if [x = y = 0] or [y] < 0.
@since 0.11 *)
val floor_div : t -> t -> t
(** [floor_div x n] is integer division rounding towards negative infinity.
It satisfies [x = m * floor_div x n + rem x n].
@since NEXT_RELEASE *)
type 'a printer = Format.formatter -> 'a -> unit
type 'a random_gen = Random.State.t -> 'a
type 'a iter = ('a -> unit) -> unit
val range_by : step:t -> t -> t -> t iter
(** [range_by ~step i j] iterates on integers from [i] to [j] included,
where the difference between successive elements is [step].
Use a negative [step] for a decreasing list.
@raise Invalid_argument if [step=0].
@since NEXT_RELEASE *)
val range : t -> t -> t iter
(** [range i j] iterates on integers from [i] to [j] included . It works
both for decreasing and increasing ranges.
@since NEXT_RELEASE *)
val range' : t -> t -> t iter
(** [range' i j] is like {!range} but the second bound [j] is excluded.
For instance [range' 0 5 = Iter.of_list [0;1;2;3;4]].
@since NEXT_RELEASE *)
val random : t -> t random_gen
val random_small : t random_gen
val random_range : t -> t -> t random_gen
(** {2 Conversion} *)
val to_int : t -> int
(** [to_int x] converts the given 64-bit integer [x] (type [int64]) into an
integer (type [int]). On 64-bit platforms, the 64-bit integer
is taken modulo 2{^63}, i.e. the high-order bit is lost
during the conversion. On 32-bit platforms, the 64-bit integer
is taken modulo 2{^31}, i.e. the top 33 bits are lost
during the conversion. *)
val of_int : int -> t
(** [of_int x] converts the given integer [x] (type [int]) into an
64-bit integer (type [int64]).
Alias to {!Int64.of_int}.
NOTE: used to return an option, but the function actually never fails. *)
val to_int32 : t -> int32
(** [to_int32 x] converts the given 64-bit integer [x] (type [int64]) to a
32-bit integer (type [int32]). The 64-bit integer
is taken modulo 2{^32}, i.e. the top 32 bits are lost
during the conversion. *)
val of_int32 : int32 -> t
(** [of_int32 x] converts the given 32-bit integer [x] (type [int32]) into an
64-bit integer (type [int64]).
Alias to {!Int64.of_int32}.
NOTE: use to return an option, but the function actually never fails. *)
val to_nativeint : t -> nativeint
(** [to_nativeint x] converts the given 64-bit integer [x] (type [int64]) into a
native integer. On 32-bit platforms, the 64-bit integer
is taken modulo 2{^32}. On 64-bit platforms,
the conversion is exact. *)
val of_nativeint : nativeint -> t
(** [of_nativeint x] converts the given nativeint integer [x] (type [nativeint]) into an
64-bit integer (type [int64]).
Alias to {!Int64.of_nativeint}.
NOTE: use to return an option, but the function actually never fails. *)
val to_float : t -> float
(** [to_float x] converts the given 64-bit integer [x] into a floating-point number. *)
val of_float : float -> t
(** [of_float x] converts the given floating-point number [x] into a 64-bit integer,
discarding the fractional part (truncate towards 0).
The result of the conversion is undefined if, after truncation,
the number is outside the range \[{!CCInt64.min_int}, {!CCInt64.max_int}\].
Alias to {!Int64.of_float}.
NOTE: used to return an option, but the function never fails. *)
val to_string : t -> string
(** [to_string x] returns the string representation of its argument [x], in decimal. *)
val of_string : string -> t option
(** [of_string s] is the safe version of {!of_string_exn}. *)
(** [of_string s] is the safe version of {!of_string_exn}.
Like {!of_string_exn}, but return [None] instead of raising. *)
val of_string_opt : string -> t option
(** [of_string_opt s] is an alias to {!of_string}.
@ -187,3 +99,104 @@ val of_string_exn : string -> t
Raise [Failure "Int64.of_string"] if the given string is not
a valid representation of an integer, or if the integer represented
exceeds the range of integers representable in type [int64]. *)
val to_string_binary : t -> string
(** [to_string_binary x] returns the string representation of the integer [x], in binary.
@since NEXT_RELEASE *)
(** {2 Printing} *)
val pp : t printer
(** [pp ppf x] prints the integer [x] on [ppf].
@since NEXT_RELEASE *)
val pp_binary : t printer
(** [pp_binary ppf x] prints [x] on [ppf].
Print as "0b00101010".
@since NEXT_RELEASE *)
(** {2 Infix Operators} *)
(** Infix operators
@since 2.1 *)
module Infix : sig
val ( + ) : t -> t -> t
(** [x + y] is the sum of [x] and [y].
Addition. *)
val ( - ) : t -> t -> t
(** [x - y] is the difference of [x] and [y].
Subtraction. *)
val ( ~- ) : t -> t
(** [~- x] is the negation of [x].
Unary negation. *)
val ( * ) : t -> t -> t
(** [ x * y] is the product of [x] and [y].
Multiplication. *)
val ( / ) : t -> t -> t
(** [x / y] is the integer quotient of [x] and [y].
Integer division. Raise [Division_by_zero] if the second
argument [y] is zero. This division rounds the real quotient of
its arguments towards zero, as specified for {!Stdlib.(/)}. *)
val ( mod ) : t -> t -> t
(** [x mod y] is the integer remainder of [x / y].
If [y <> zero], the result of [x mod y] satisfies the following properties:
[zero <= x mod y < abs y] and
[x = ((x / y) * y) + (x mod y)].
If [y = 0], [x mod y] raises [Division_by_zero]. *)
val ( ** ) : t -> t -> t
(** Alias to {!pow}
@since NEXT_RELEASE *)
val (--) : t -> t -> t iter
(** Alias to {!range}.
@since NEXT_RELEASE *)
val (--^) : t -> t -> t iter
(** Alias to {!range'}.
@since NEXT_RELEASE *)
val ( land ) : t -> t -> t
(** [x land y] is the bitwise logical and of [x] and [y]. *)
val ( lor ) : t -> t -> t
(** [x lor y] is the bitwise logical or of [x] and [y]. *)
val ( lxor ) : t -> t -> t
(** [x lxor y] is the bitwise logical exclusive or of [x] and [y]. *)
val lnot : t -> t
(** [lnot x] is the bitwise logical negation of [x] (the bits of [x] are inverted). *)
val ( lsl ) : t -> int -> t
(** [ x lsl y] shifts [x] to the left by [y] bits, filling in with zeroes.
The result is unspecified if [y < 0] or [y >= 64]. *)
val ( lsr ) : t -> int -> t
(** [x lsr y] shifts [x] to the right by [y] bits.
This is a logical shift: zeroes are inserted in the vacated bits
regardless of the sign of [x].
The result is unspecified if [y < 0] or [y >= 64]. *)
val ( asr ) : t -> int -> t
(** [x asr y] shifts [x] to the right by [y] bits.
This is an arithmetic shift: the sign bit of [x] is replicated
and inserted in the vacated bits.
The result is unspecified if [y < 0] or [y >= 64]. *)
val (=) : t -> t -> bool
val (<>) : t -> t -> bool
val (>) : t -> t -> bool
val (>=) : t -> t -> bool
val (<=) : t -> t -> bool
val (<) : t -> t -> bool
end
include module type of Infix

View file

@ -3,6 +3,200 @@
open CCShims_
include Nativeint
let min : t -> t -> t = Stdlib.min
let max : t -> t -> t = Stdlib.max
let hash x = Stdlib.abs (to_int x)
let sign i = compare i zero
let pow a b =
let rec aux acc = function
| 1n -> acc
| n ->
if equal (rem n 2n) zero
then aux (mul acc acc) (div n 2n)
else mul acc (aux (mul acc acc) (div n 2n))
in
match b with
| 0n -> if equal a 0n then raise (Invalid_argument "pow: undefined value 0^0") else 1n
| b when compare b 0n < 0 -> raise (Invalid_argument "pow: can't raise int to negative power")
| b -> aux a b
(*$T
pow 2n 10n = 1024n
pow 2n 15n = 32768n
pow 10n 5n = 100000n
pow 42n 0n = 1n
pow 0n 1n = 0n
*)
let floor_div a n =
if compare a 0n < 0 && compare n 0n >= 0 then
sub (div (add a 1n) n) 1n
else if compare a 0n > 0 && compare n 0n < 0 then
sub (div (sub a 1n) n) 1n
else
div a n
(*$T
(floor_div 3n 5n = 0n)
(floor_div 5n 5n = 1n)
(floor_div 20n 5n = 4n)
(floor_div 12n 5n = 2n)
(floor_div 0n 5n = 0n)
(floor_div (-1n) 5n = -1n)
(floor_div (-5n) 5n = -1n)
(floor_div (-12n) 5n = -3n)
(floor_div 0n (-5n) = 0n)
(floor_div 3n (-5n) = -1n)
(floor_div 5n (-5n) = -1n)
(floor_div 9n (-5n) = -2n)
(floor_div 20n (-5n) = -4n)
(floor_div (-2n) (-5n) = 0n)
(floor_div (-8n) (-5n) = 1n)
(floor_div (-35n) (-5n) = 7n)
try ignore (floor_div 12n 0n); false with Division_by_zero -> true
try ignore (floor_div (-12n) 0n); false with Division_by_zero -> true
*)
(*$Q
(Q.pair (Q.map of_int Q.small_signed_int) (Q.map of_int Q.small_nat)) \
(fun (n, m) -> let m = m + 1n in \
floor_div n m = of_float @@ floor (to_float n /. to_float m))
(Q.pair (Q.map of_int Q.small_signed_int) (Q.map of_int Q.small_nat)) \
(fun (n, m) -> let m = m + 1n in \
floor_div n (-m) = of_float @@ floor (to_float n /. to_float (-m)))
*)
type 'a printer = Format.formatter -> 'a -> unit
type 'a random_gen = Random.State.t -> 'a
type 'a iter = ('a -> unit) -> unit
let range i j yield =
let rec up i j yield =
if equal i j then yield i
else (
yield i;
up (add i 1n) j yield
)
and down i j yield =
if equal i j then yield i
else (
yield i;
down (sub i 1n) j yield
)
in
if compare i j <= 0 then up i j yield else down i j yield
(*$= & ~printer:Q.Print.(list to_string)
[0n;1n;2n;3n;4n;5n] (range 0n 5n |> Iter.to_list)
[0n] (range 0n 0n |> Iter.to_list)
[5n;4n;3n;2n] (range 5n 2n |> Iter.to_list)
*)
let range' i j yield =
if compare i j < 0 then range i (sub j 1n) yield
else if equal i j then ()
else range i (add j 1n) yield
let range_by ~step i j yield =
let rec range i j yield =
if equal i j then yield i
else (
yield i;
range (add i step) j yield
)
in
if equal step 0n then
raise (Invalid_argument "CCNativeint.range_by")
else if (if compare step 0n > 0 then compare i j > 0 else compare i j < 0) then ()
else range i (add (mul (div (sub j i) step) step) i) yield
(* note: the last test checks that no error occurs due to overflows. *)
(*$= & ~printer:Q.Print.(list to_string)
[0n] (range_by ~step:1n 0n 0n |> Iter.to_list)
[] (range_by ~step:1n 5n 0n |> Iter.to_list)
[] (range_by ~step:2n 1n 0n |> Iter.to_list)
[0n;2n;4n] (range_by ~step:2n 0n 4n |> Iter.to_list)
[0n;2n;4n] (range_by ~step:2n 0n 5n |> Iter.to_list)
[0n] (range_by ~step:(neg 1n) 0n 0n |> Iter.to_list)
[] (range_by ~step:(neg 1n) 0n 5n |> Iter.to_list)
[] (range_by ~step:(neg 2n) 0n 1n |> Iter.to_list)
[5n;3n;1n] (range_by ~step:(neg 2n) 5n 1n |> Iter.to_list)
[5n;3n;1n] (range_by ~step:(neg 2n) 5n 0n |> Iter.to_list)
[0n] (range_by ~step:max_int 0n 2n |> Iter.to_list)
*)
(*$Q
Q.(pair (map of_int small_int) (map of_int small_int)) (fun (i,j) -> \
let i = min i j and j = max i j in \
CCList.equal CCNativeint.equal \
(CCNativeint.range_by ~step:1n i j |> Iter.to_list) \
(CCNativeint.range i j |> Iter.to_list) )
*)
let random n st = Random.State.nativeint st n
let random_small = random 100n
let random_range i j st = add i (random (sub j i) st)
(** {2 Conversion} *)
let of_string_exn = of_string
let of_string x = try Some (of_string_exn x) with Failure _ -> None
let of_string_opt = of_string
let most_significant_bit =
logxor (neg 1n) (shift_right_logical (neg 1n) 1)
type output = char -> unit
(* abstract printer *)
let to_binary_gen (out:output) n =
let n = if compare n 0n <0 then (out '-'; neg n) else n in
out '0'; out 'b';
let rec loop started bit n =
if equal bit 0n then (
if not started then out '0'
) else (
let b = logand n bit in
if equal b 0n then (
if started then out '0';
loop started (shift_right_logical bit 1) n
) else (
out '1';
loop true (shift_right_logical bit 1) n
)
)
in
loop false most_significant_bit n
let to_string_binary n =
let buf = Buffer.create 16 in
to_binary_gen (Buffer.add_char buf) n;
Buffer.contents buf
(*$= & ~printer:CCFun.id
"0b111" (to_string_binary 7n)
"-0b111" (to_string_binary (-7n))
"0b0" (to_string_binary 0n)
*)
(** {2 Printing} *)
let pp out n = Format.pp_print_string out (to_string n)
let pp_binary out n =
to_binary_gen (Format.pp_print_char out) n
(** {2 Infix Operators} *)
module Infix = struct
let (+) = add
@ -14,6 +208,12 @@ module Infix = struct
let (/) = div
let ( ** ) = pow
let (--) = range
let (--^) = range'
let (mod) = rem
let (land) = logand
@ -39,12 +239,3 @@ module Infix = struct
let (>=) = Stdlib.(>=)
end
include Infix
let hash x = Stdlib.abs (to_int x)
(** {2 Conversion} *)
let of_string_exn = of_string
let of_string x = try Some (of_string_exn x) with Failure _ -> None
let of_string_opt = of_string

View file

@ -18,110 +18,73 @@
include module type of struct include Nativeint end
val ( + ) : t -> t -> t
(** Addition. *)
val min : t -> t -> t
(** [min x y] returns the minimum of the two integers [x] and [y].
@since NEXT_RELEASE *)
val ( - ) : t -> t -> t
(** Subtraction. *)
val ( ~- ) : t -> t
(** Unary negation. *)
val ( * ) : t -> t -> t
(** Multiplication. *)
val ( / ) : t -> t -> t
(** Integer division. Raise [Division_by_zero] if the second
argument is zero. This division rounds the real quotient of
its arguments towards zero, as specified for {!Stdlib.(/)}. *)
val ( mod ) : t -> t -> t
(** [x mod y ] is the integer remainder.
If [y <> zero], the result of [x mod y] satisfies the following properties:
[zero <= x mod y < abs y] and
[x = ((x / y) * y) + (x mod y)].
If [y = 0], [x mod y] raises [Division_by_zero]. *)
val ( land ) : t -> t -> t
(** Bitwise logical and. *)
val ( lor ) : t -> t -> t
(** Bitwise logical or. *)
val ( lxor ) : t -> t -> t
(** Bitwise logical exclusive or. *)
val lnot : t -> t
(** Bitwise logical negation. *)
val ( lsl ) : t -> int -> t
(** [ x lsl y] shifts [x] to the left by [y] bits.
The result is unspecified if [y < 0] or [y >= bitsize], where [bitsize] is [32] on a 32-bit platform
and [64] on a 64-bit platform. *)
val ( lsr ) : t -> int -> t
(** [x lsr y] shifts [x] to the right by [y] bits.
This is a logical shift: zeroes are inserted in the vacated bits
regardless of the sign of [x].
The result is unspecified if [y < 0] or [y >= bitsize]. *)
val ( asr ) : t -> int -> t
(** [x asr y] shifts [x] to the right by [y] bits.
This is an arithmetic shift: the sign bit of [x] is replicated
and inserted in the vacated bits.
The result is unspecified if [y < 0] or [y >= bitsize]. *)
module Infix : sig
val (+) : t -> t -> t
val (-) : t -> t -> t
val (~-) : t -> t
val ( * ) : t -> t -> t
val (/) : t -> t -> t
val (mod) : t -> t -> t
val (land) : t -> t -> t
val (lor) : t -> t -> t
val (lxor) : t -> t -> t
val lnot : t -> t
val (lsl) : t -> int -> t
val (lsr) : t -> int -> t
val (asr) : t -> int -> t
val (=) : t -> t -> bool
val (<>) : t -> t -> bool
val (>) : t -> t -> bool
val (>=) : t -> t -> bool
val (<=) : t -> t -> bool
val (<) : t -> t -> bool
end
val max : t -> t -> t
(** [max x y] returns the maximum of the two integers [x] and [y].
@since NEXT_RELEASE *)
val hash : t -> int
(** Like {!Stdlib.abs (to_int x)}. *)
(** [hash x] computes the hash of [x].
Like {!Stdlib.abs (to_int x)}. *)
val sign : t -> int
(** [sign x] return [0] if [x = 0], [-1] if [x < 0] and [1] if [x > 0].
Same as [compare x zero].
@since NEXT_RELEASE*)
val pow : t -> t -> t
(** [pow base exponent] returns [base] raised to the power of [exponent].
[pow x y = x^y] for positive integers [x] and [y].
Raises [Invalid_argument] if [x = y = 0] or [y] < 0.
@since 0.11 *)
val floor_div : t -> t -> t
(** [floor_div x n] is integer division rounding towards negative infinity.
It satisfies [x = m * floor_div x n + rem x n].
@since NEXT_RELEASE *)
type 'a printer = Format.formatter -> 'a -> unit
type 'a random_gen = Random.State.t -> 'a
type 'a iter = ('a -> unit) -> unit
val range_by : step:t -> t -> t -> t iter
(** [range_by ~step i j] iterates on integers from [i] to [j] included,
where the difference between successive elements is [step].
Use a negative [step] for a decreasing list.
@raise Invalid_argument if [step=0].
@since NEXT_RELEASE *)
val range : t -> t -> t iter
(** [range i j] iterates on integers from [i] to [j] included . It works
both for decreasing and increasing ranges.
@since NEXT_RELEASE *)
val range' : t -> t -> t iter
(** [range' i j] is like {!range} but the second bound [j] is excluded.
For instance [range' 0 5 = Iter.of_list [0;1;2;3;4]].
@since NEXT_RELEASE *)
val random : t -> t random_gen
val random_small : t random_gen
val random_range : t -> t -> t random_gen
(** {2 Conversion} *)
val to_int : t -> int
(** Convert the given native integer (type [nativeint]) to an
integer (type [int]). The high-order bit is lost
during the conversion. *)
val of_string : string -> t option
(** [of_string s] is the safe version of {!of_string_exn}.
Like {!of_string_exn}, but return [None] instead of raising. *)
val of_int : int -> t
(** Alias to {!Nativeint.of_int}.
Convert the given integer (type [int]) to a native integer (type [nativeint]). *)
val to_float : t -> float
(** Convert the given native integer to a floating-point number. *)
val of_float : float -> t
(** Alias to {!Nativeint.of_float}.
Convert the given floating-point number to a native integer,
discarding the fractional part (truncate towards 0).
The result of the conversion is undefined if, after truncation, the number
is outside the range \[{!CCNativeint.min_int}, {!CCNativeint.max_int}\]. *)
val to_string : t -> string
(** Return the string representation of its argument, in decimal. *)
val of_string_opt : string -> t option
(** [of_string_opt s] is an alias to {!of_string}. *)
val of_string_exn : string -> t
(** Alias to {!Nativeint.of_string}.
(** [of_string_exn s] converts the given string [s] into a native integer.
Alias to {!Nativeint.of_string}.
Convert the given string to a native integer.
The string is read in decimal (by default, or if the string
begins with [0u]) or in hexadecimal, octal or binary if the
@ -136,9 +99,102 @@ val of_string_exn : string -> t
a valid representation of an integer, or if the integer represented
exceeds the range of integers representable in type [nativeint]. *)
val of_string : string -> t option
(** Safe version of {!of_string_exn}.
Like {!of_string_exn}, but return [None] instead of raising. *)
val to_string_binary : t -> string
(** [to_string_binary x] returns the string representation of the integer [x], in binary.
@since NEXT_RELEASE *)
val of_string_opt : string -> t option
(** Alias to {!of_string}. *)
(** {2 Printing} *)
val pp : t printer
(** [pp ppf x] prints the integer [x] on [ppf].
@since NEXT_RELEASE *)
val pp_binary : t printer
(** [pp_binary ppf x] prints [x] on [ppf].
Print as "0b00101010".
@since NEXT_RELEASE *)
(** {2 Infix Operators} *)
module Infix : sig
val ( + ) : t -> t -> t
(** [x + y] is the sum of [x] and [y].
Addition. *)
val ( - ) : t -> t -> t
(** [x - y] is the difference of [x] and [y].
Subtraction. *)
val ( ~- ) : t -> t
(** [~- x] is the negation of [x].
Unary negation. *)
val ( * ) : t -> t -> t
(** [ x * y] is the product of [x] and [y].
Multiplication. *)
val ( / ) : t -> t -> t
(** [x / y] is the integer quotient of [x] and [y].
Integer division. Raise [Division_by_zero] if the second
argument [y] is zero. This division rounds the real quotient of
its arguments towards zero, as specified for {!Stdlib.(/)}. *)
val ( mod ) : t -> t -> t
(** [x mod y] is the integer remainder of [x / y].
If [y <> zero], the result of [x mod y] satisfies the following properties:
[zero <= x mod y < abs y] and
[x = ((x / y) * y) + (x mod y)].
If [y = 0], [x mod y] raises [Division_by_zero]. *)
val ( ** ) : t -> t -> t
(** Alias to {!pow}
@since NEXT_RELEASE *)
val (--) : t -> t -> t iter
(** Alias to {!range}.
@since NEXT_RELEASE *)
val (--^) : t -> t -> t iter
(** Alias to {!range'}.
@since NEXT_RELEASE *)
val ( land ) : t -> t -> t
(** [x land y] is the bitwise logical and of [x] and [y]. *)
val ( lor ) : t -> t -> t
(** [x lor y] is the bitwise logical or of [x] and [y]. *)
val ( lxor ) : t -> t -> t
(** [x lxor y] is the bitwise logical exclusive or of [x] and [y]. *)
val lnot : t -> t
(** [lnot x] is the bitwise logical negation of [x] (the bits of [x] are inverted). *)
val ( lsl ) : t -> int -> t
(** [ x lsl y] shifts [x] to the left by [y] bits.
The result is unspecified if [y < 0] or [y >= bitsize], where [bitsize] is [32] on a 32-bit platform
and [64] on a 64-bit platform. *)
val ( lsr ) : t -> int -> t
(** [x lsr y] shifts [x] to the right by [y] bits.
This is a logical shift: zeroes are inserted in the vacated bits
regardless of the sign of [x].
The result is unspecified if [y < 0] or [y >= bitsize]. *)
val ( asr ) : t -> int -> t
(** [x asr y] shifts [x] to the right by [y] bits.
This is an arithmetic shift: the sign bit of [x] is replicated
and inserted in the vacated bits.
The result is unspecified if [y < 0] or [y >= bitsize]. *)
val (=) : t -> t -> bool
val (<>) : t -> t -> bool
val (>) : t -> t -> bool
val (>=) : t -> t -> bool
val (<=) : t -> t -> bool
val (<) : t -> t -> bool
end
include module type of Infix

View file

@ -6,7 +6,8 @@
(rule
(targets CCShims_.ml CCShimsList_.ml CCShimsFun_.ml CCShimsFun_.mli
CCShimsArray_.ml CCShimsFormat_.ml CCShimsMkLet_.ml CCShimsArrayLabels_.ml)
CCShimsArray_.ml CCShimsFormat_.ml CCShimsMkLet_.ml CCShimsArrayLabels_.ml
CCShimsInt_.ml)
(deps ./mkshims.exe)
(action
(run ./mkshims.exe)))

View file

@ -150,6 +150,9 @@ let shims_let_op_post_408 =
end[@@inline]
"
let shims_int_pre_408 = ""
let shims_int_post_408 = "include Int"
let () =
C.main ~name:"mkshims" (fun c ->
let version = C.ocaml_config_var_exn c "version" in
@ -168,4 +171,5 @@ let () =
write_file "CCShimsFun_.ml" (if (major, minor) >= (4,8) then shims_fun_post_408 else shims_fun_pre_408);
write_file "CCShimsFun_.mli" (if (major, minor) >= (4,8) then shims_fun_mli_post_408 else shims_fun_mli_pre_408);
write_file "CCShimsMkLet_.ml" (if (major, minor) >= (4,8) then shims_let_op_post_408 else shims_let_op_pre_408);
write_file "CCShimsInt_.ml" (if (major, minor) >= (4,8) then shims_int_post_408 else shims_int_pre_408);
)