Implement CCInt.floor_div and CCInt.rem

This commit is contained in:
Fabian 2017-04-28 14:40:15 -05:00
parent 43bccceac7
commit 883eb611f0
2 changed files with 82 additions and 0 deletions

View file

@ -37,6 +37,78 @@ let pow a b =
pow 0 1 = 0 pow 0 1 = 0
*) *)
let floor_div a n =
if a < 0 && n >= 0 then
(a + 1) / n - 1
else if a > 0 && n < 0 then
(a - 1) / n - 1
else
a / n
(*$T
(floor_div 3 5 = 0)
(floor_div 5 5 = 1)
(floor_div 12 5 = 2)
(floor_div 0 5 = 0)
(floor_div (-1) 5 = -1)
(floor_div (-5) 5 = -1)
(floor_div (-12) 5 = -3)
(floor_div 0 (-5) = 0)
(floor_div 3 (-5) = -1)
(floor_div 5 (-5) = -1)
(floor_div 9 (-5) = -2)
(floor_div (-2) (-5) = 0)
(floor_div (-8) (-5) = 1)
try ignore (floor_div 12 0); false with Division_by_zero -> true
try ignore (floor_div (-12) 0); false with Division_by_zero -> true
*)
(*$Q
(Q.pair Q.small_signed_int Q.pos_int) \
(fun (n, m) -> floor_div n m = int_of_float @@ floor (float n /. float m))
(Q.pair Q.small_signed_int Q.pos_int) \
(fun (n, m) -> floor_div n (-m) = int_of_float @@ floor (float n /. float (-m)))
*)
let rem a n =
let y = a mod n in
if (y < 0) <> (n < 0) && y <> 0 then
y + n
else
y
(*$T
(rem 3 5 = 3)
(rem 5 5 = 0)
(rem 9 5 = 4)
(rem (-1) 5 = 4)
(rem (-5) 5 = 0)
(rem (-9) 5 = 1)
(rem 0 5 = 0)
(rem 0 (-5) = 0)
(rem 3 (-5) = -2)
(rem 5 (-5) = 0)
(rem 9 (-5) = -1)
(rem (-2) (-5) = -2)
(rem (-8) (-5) = -3)
try ignore (rem 12 0); false with Division_by_zero -> true
try ignore (rem (-12) 0); false with Division_by_zero -> true
*)
(*$Q
(Q.pair Q.int Q.pos_int) (fun (n, m) -> let y = rem n m in y >= 0 && y < m)
(Q.pair Q.int Q.pos_int) (fun (n, m) -> let y = rem n (-m) in y > (-m) && y <= 0)
*)
(*$Q
(Q.pair Q.int Q.pos_int) (fun (n, m) -> n = m * floor_div n m + rem n m)
(Q.pair Q.int Q.pos_int) (fun (n, m) -> n = (-m) * floor_div n (-m) + rem n (-m))
*)
type 'a printer = Format.formatter -> 'a -> unit type 'a printer = Format.formatter -> 'a -> unit
type 'a random_gen = Random.State.t -> 'a type 'a random_gen = Random.State.t -> 'a
type 'a sequence = ('a -> unit) -> unit type 'a sequence = ('a -> unit) -> unit

View file

@ -23,6 +23,16 @@ val pow : t -> t -> t
Raises [Invalid_argument] if [a = b = 0] or [b] < 0. Raises [Invalid_argument] if [a = b = 0] or [b] < 0.
@since 0.11 *) @since 0.11 *)
val floor_div : t -> t -> t
(** [floor_div a n] is integer division rounding towards negative infinity.
It satisfies [a = m * floor_div a n + rem a n].
@since NEXT_RELEASE *)
val rem : t -> t -> t
(** [rem a n] is the remainder of dividing [a] by [n], with the same
sign as [n].
@since NEXT_RELEASE *)
type 'a printer = Format.formatter -> 'a -> unit type 'a printer = Format.formatter -> 'a -> unit
type 'a random_gen = Random.State.t -> 'a type 'a random_gen = Random.State.t -> 'a
type 'a sequence = ('a -> unit) -> unit type 'a sequence = ('a -> unit) -> unit