Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add predefined types for tagged int8 and int16 #3347

Merged
merged 11 commits into from
Dec 20, 2024
15 changes: 15 additions & 0 deletions otherlibs/stdlib_beta/.ocamlformat
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Please make a pull request to change this file.
# Keep the remainder of this file in sync with other .ocamlformat files in this repo.
assignment-operator=begin-line
cases-exp-indent=2
doc-comments=before
dock-collection-brackets=false
if-then-else=keyword-first
module-item-spacing=sparse
parens-tuple=multi-line-only
sequence-blank-line=compact
space-around-lists=false
space-around-variants=false
type-decl=sparse
wrap-comments=true
version=0.24.1
5 changes: 4 additions & 1 deletion otherlibs/stdlib_beta/.ocamlformat-enable
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
stdlib_beta.mli
stdlib_beta.ml

int8.ml
int8.mli
int16.ml
int16.mli
5 changes: 4 additions & 1 deletion otherlibs/stdlib_beta/dune
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@
-safe-string
-strict-formats
-extension-universe
beta))
beta
-extension
small_numbers_beta
))
(ocamlopt_flags
(:include %{project_root}/ocamlopt_flags.sexp))
(library_flags
Expand Down
96 changes: 96 additions & 0 deletions otherlibs/stdlib_beta/int16.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
(**************************************************************************)
jvanburen marked this conversation as resolved.
Show resolved Hide resolved
(* *)
(* OCaml *)
(* *)
(* Jacob Van Buren, Jane Street, New York *)
(* *)
(* Copyright 2024 Jane Street Group LLC *)
(* *)
(* All rights reserved. This file is distributed under the terms of *)
(* the GNU Lesser General Public License version 2.1, with the *)
(* special exception on linking described in the file LICENSE. *)
(* *)
(**************************************************************************)

open! Stdlib

type t = int16

[@@@ocaml.flambda_o3]

external to_int : t -> int = "%identity"

external unsafe_of_int : int -> t = "%identity"

let int_size = 16

let max_int = (1 lsl (int_size - 1)) - 1

let min_int = -1 lsl (int_size - 1)

let mask = (1 lsl int_size) - 1

let unused_bits = Sys.int_size - int_size

let[@inline] of_int i = unsafe_of_int ((i lsl unused_bits) asr unused_bits)

let zero = of_int 0

let one = of_int 1

let minus_one = of_int (-1)

let[@inline always] neg x = of_int (Int.neg (to_int x))

let[@inline always] add x y = of_int (Int.add (to_int x) (to_int y))

let[@inline always] sub x y = of_int (Int.sub (to_int x) (to_int y))

let[@inline always] mul x y = of_int (Int.mul (to_int x) (to_int y))

let[@inline always] div x y = of_int (Int.div (to_int x) (to_int y))

let[@inline always] rem x y = of_int (Int.rem (to_int x) (to_int y))

let[@inline always] succ x = of_int (Int.succ (to_int x))

let[@inline always] pred x = of_int (Int.pred (to_int x))

let[@inline always] abs x = of_int (Int.abs (to_int x))

let[@inline always] logand x y =
unsafe_of_int (Int.logand (to_int x) (to_int y))
jvanburen marked this conversation as resolved.
Show resolved Hide resolved

let[@inline always] logor x y = unsafe_of_int (Int.logor (to_int x) (to_int y))

let[@inline always] logxor x y =
unsafe_of_int (Int.logxor (to_int x) (to_int y))

let[@inline always] lognot x = unsafe_of_int (Int.lognot (to_int x))

let[@inline always] shift_left x y = of_int (Int.shift_left (to_int x) y)

let[@inline always] shift_right x y = of_int (Int.shift_right (to_int x) y)

let[@inline always] shift_right_logical x y =
of_int (Int.shift_right_logical (to_int x land mask) y)

let[@inline always] equal x y = Int.equal (to_int x) (to_int y)

let[@inline always] compare x y = Int.compare (to_int x) (to_int y)

let[@inline always] min x y = if to_int x > to_int y then y else x

let[@inline always] max x y = if to_int x < to_int y then y else x

let[@inline always] of_float f =
let i = Int.of_float f in
if min_int <= i && i <= max_int then unsafe_of_int i else zero

let[@inline always] to_float t = Int.to_float (to_int t)

let[@inline always] to_string t = Int.to_string (to_int t)

let max_int = of_int max_int

let min_int = of_int min_int
136 changes: 136 additions & 0 deletions otherlibs/stdlib_beta/int16.mli
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
(**************************************************************************)
jvanburen marked this conversation as resolved.
Show resolved Hide resolved
(* *)
(* OCaml *)
(* *)
(* The OCaml programmers *)
(* Jacob Van Buren, Jane Street, New York *)
(* *)
(* Copyright 2018 Institut National de Recherche en Informatique et *)
(* en Automatique. *)
(* *)
(* All rights reserved. This file is distributed under the terms of *)
(* the GNU Lesser General Public License version 2.1, with the *)
(* special exception on linking described in the file LICENSE. *)
(* *)
(**************************************************************************)

(** Signed 16-bit integer values.

These integers are {16} bits wide and use two's complement
representation. All operations are taken modulo
2{^16}. They do not fail on overflow. *)

(** {1:ints 16-bit Integers} *)

(** The type for 16-bit integer values. *)
type t = int16

(** [int_size] is the number of bits in an integer (i.e., 16). *)
val int_size : int

(** [zero] is the integer [0]. *)
val zero : int16

(** [one] is the integer [1]. *)
val one : int16

(** [minus_one] is the integer [-1]. *)
val minus_one : int16

(** [neg x] is [~-x]. *)
val neg : int16 -> int16

(** [add x y] is the addition [x + y]. *)
val add : int16 -> int16 -> int16

(** [sub x y] is the subtraction [x - y]. *)
val sub : int16 -> int16 -> int16

(** [mul x y] is the multiplication [x * y]. *)
val mul : int16 -> int16 -> int16

(** [div x y] is the division [x / y]. See {!Stdlib.( / )} for details. *)
val div : int16 -> int16 -> int16

(** [rem x y] is the remainder [x mod y]. See {!Stdlib.( mod )} for details. *)
val rem : int16 -> int16 -> int16

(** [succ x] is [add x 1]. *)
val succ : int16 -> int16

(** [pred x] is [sub x 1]. *)
val pred : int16 -> int16

(** [abs x] is the absolute value of [x]. That is [x] if [x] is positive
and [neg x] if [x] is negative. {b Warning.} This may be negative if
the argument is {!min_int}. *)
val abs : int16 -> int16

(** [max_int] is the greatest representable integer,
[2{^[16 - 1]} - 1]. *)
val max_int : int16

(** [min_int] is the smallest representable integer,
[-2{^[16 - 1]}]. *)
val min_int : int16

(** [logand x y] is the bitwise logical and of [x] and [y]. *)
val logand : int16 -> int16 -> int16

(** [logor x y] is the bitwise logical or of [x] and [y]. *)
val logor : int16 -> int16 -> int16

(** [logxor x y] is the bitwise logical exclusive or of [x] and [y]. *)
val logxor : int16 -> int16 -> int16

(** [lognot x] is the bitwise logical negation of [x]. *)
val lognot : int16 -> int16

(** [shift_left x n] shifts [x] to the left by [n] bits. The result
is unspecified if [n < 0] or [n > ]{!16}. *)
val shift_left : int16 -> int -> int16

(** [shift_right x n] shifts [x] to the right by [n] bits. This is an
arithmetic shift: the sign bit of [x] is replicated and inserted
in the vacated bits. The result is unspecified if [n < 0] or
[n > ]{!16}. *)
val shift_right : int16 -> int -> int16

(** [shift_right x n] shifts [x] to the right by [n] bits. This is a
logical shift: zeroes are inserted in the vacated bits regardless
of the sign of [x]. The result is unspecified if [n < 0] or
[n > ]{!16}. *)
val shift_right_logical : int16 -> int -> int16

(** {1:preds Predicates and comparisons} *)

(** [equal x y] is [true] if and only if [x = y]. *)
val equal : int16 -> int16 -> bool

(** [compare x y] is {!Stdlib.compare}[ x y] but more efficient. *)
val compare : int16 -> int16 -> int

(** Return the smaller of the two arguments. *)
val min : int16 -> int16 -> int16

(** Return the greater of the two arguments. *)
val max : int16 -> int16 -> int16

(** {1:convert Converting} *)

(** [to_int x] is [x] as an {!int}. *)
val to_int : int16 -> int

(** [of_int x] represents [x] as an 16-bit integer. *)
val of_int : int -> int16

(** [to_float x] is [x] as a floating point number. *)
val to_float : int16 -> float

(** [of_float x] truncates [x] to an integer. The result is
unspecified if the argument is [nan] or falls outside the range of
representable integers. *)
val of_float : float -> int16

(** [to_string x] is the written representation of [x] in decimal. *)
val to_string : int16 -> string
96 changes: 96 additions & 0 deletions otherlibs/stdlib_beta/int8.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
(**************************************************************************)
(* *)
(* OCaml *)
(* *)
(* Jacob Van Buren, Jane Street, New York *)
(* *)
(* Copyright 2024 Jane Street Group LLC *)
(* *)
(* All rights reserved. This file is distributed under the terms of *)
(* the GNU Lesser General Public License version 2.1, with the *)
(* special exception on linking described in the file LICENSE. *)
(* *)
(**************************************************************************)

open! Stdlib

type t = int8

[@@@ocaml.flambda_o3]

external to_int : t -> int = "%identity"

external unsafe_of_int : int -> t = "%identity"

let int_size = 8

let max_int = (1 lsl (int_size - 1)) - 1

let min_int = -1 lsl (int_size - 1)

let mask = (1 lsl int_size) - 1

let unused_bits = Sys.int_size - int_size

let[@inline] of_int i = unsafe_of_int ((i lsl unused_bits) asr unused_bits)

let zero = of_int 0

let one = of_int 1

let minus_one = of_int (-1)

let[@inline always] neg x = of_int (Int.neg (to_int x))

let[@inline always] add x y = of_int (Int.add (to_int x) (to_int y))

let[@inline always] sub x y = of_int (Int.sub (to_int x) (to_int y))

let[@inline always] mul x y = of_int (Int.mul (to_int x) (to_int y))

let[@inline always] div x y = of_int (Int.div (to_int x) (to_int y))

let[@inline always] rem x y = of_int (Int.rem (to_int x) (to_int y))

let[@inline always] succ x = of_int (Int.succ (to_int x))

let[@inline always] pred x = of_int (Int.pred (to_int x))

let[@inline always] abs x = of_int (Int.abs (to_int x))

let[@inline always] logand x y =
unsafe_of_int (Int.logand (to_int x) (to_int y))

let[@inline always] logor x y = unsafe_of_int (Int.logor (to_int x) (to_int y))

let[@inline always] logxor x y =
unsafe_of_int (Int.logxor (to_int x) (to_int y))

let[@inline always] lognot x = unsafe_of_int (Int.lognot (to_int x))

let[@inline always] shift_left x y = of_int (Int.shift_left (to_int x) y)

let[@inline always] shift_right x y = of_int (Int.shift_right (to_int x) y)

let[@inline always] shift_right_logical x y =
of_int (Int.shift_right_logical (to_int x land mask) y)

let[@inline always] equal x y = Int.equal (to_int x) (to_int y)

let[@inline always] compare x y = Int.compare (to_int x) (to_int y)

let[@inline always] min x y = if to_int x > to_int y then y else x

let[@inline always] max x y = if to_int x < to_int y then y else x

let[@inline always] of_float f =
let i = Int.of_float f in
if min_int <= i && i <= max_int then unsafe_of_int i else zero

let[@inline always] to_float t = Int.to_float (to_int t)

let[@inline always] to_string t = Int.to_string (to_int t)

let max_int = of_int max_int

let min_int = of_int min_int
Loading
Loading