pax_global_header00006660000000000000000000000064152025465440014521gustar00rootroot0000000000000052 comment=7e4350eff1d1823530c5cade13f4472f2eeb2356 ocaml-integers-0.8.0/000077500000000000000000000000001520254654400144375ustar00rootroot00000000000000ocaml-integers-0.8.0/.github/000077500000000000000000000000001520254654400157775ustar00rootroot00000000000000ocaml-integers-0.8.0/.github/workflows/000077500000000000000000000000001520254654400200345ustar00rootroot00000000000000ocaml-integers-0.8.0/.github/workflows/test.yml000066400000000000000000000013171520254654400215400ustar00rootroot00000000000000name: Integers on: push: branches: [ master ] pull_request: branches: [ master ] jobs: tests: strategy: fail-fast: false matrix: os: - ubuntu-latest - windows-latest - macos-latest ocaml-compiler: - 4.14 - 5.2 - 5.3 runs-on: ${{ matrix.os }} steps: - name: Checkout code uses: actions/checkout@v6 - name: Use OCaml ${{ matrix.ocaml-compiler }} uses: ocaml/setup-ocaml@v3 with: ocaml-compiler: ${{ matrix.ocaml-compiler }} - run: opam install . --deps-only --with-test - run: opam exec -- dune build - run: opam exec -- dune runtest ocaml-integers-0.8.0/.gitignore000066400000000000000000000000431520254654400164240ustar00rootroot00000000000000*~ _build integers.install .merlin ocaml-integers-0.8.0/CHANGES.md000066400000000000000000000026551520254654400160410ustar00rootroot00000000000000v0.8.0 2026-05-18 ----------------- * add Signed.Int8 and Signed.Int16 modules (@tmcgilchrist, @brendanzab, @zbaylin, @yallop, #54) * improve top-level printer installation (@brendanzab, #52) v0.7.0 2022-03-23 ----------------- * restore dll support for cygwin64 / newer binutils versions (mingw64) (@fdopen, #40) v0.6.0 2022-02-05 ----------------- * Add dependency on stdlib-shims (@kit-ty-kate, #38) v0.5.1 2021-08-12 ----------------- * Restore support for pre-4.05 OCaml versions (@yallop, #37) v0.5.0 2021-07-31 ----------------- * Hex printing, and option-based parsing (@raphael-proust, #34) * Add stdlib-compatible string parsing (@mrmr1993, #32) v0.4.0 2020-05-01 ----------------- * Expose Signed.S.Infix.(asr) (@dra27, #30) v0.3.0 2019-02-15 ----------------- * Drop 4.01 support (@yallop, #23) * Add equal and pp to the output signatures (@emillon, #22) * Dune port (@rgrinberg, #21) * Add UInt64.(of|to)_uint32 (@yallop, #17) v0.2.2 2016-12-19 ----------------- * Fix truncation in UInt64.of_int; remove other uses of `Val_int`/`Int_val` v0.2.1 2016-11-14 ----------------- * Register the custom deserializers v0.2.0 2016-10-04 ----------------- * Expose from_byte_size functions in Unsigned and Signed * Support for platforms where standard integer types are macros * Add 'max' and 'min' functions to Unsigned.S. * Expose private types for UChar, UInt8, UInt16. 0.1.0 2016-09-26 ---------------- * Initial public release ocaml-integers-0.8.0/LICENSE.md000066400000000000000000000020451520254654400160440ustar00rootroot00000000000000Copyright (c) 2013-2016 Jeremy Yallop Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.ocaml-integers-0.8.0/Makefile000066400000000000000000000001551520254654400161000ustar00rootroot00000000000000.PHONY: all clean test doc all: dune build test: dune runtest doc: dune build @doc clean: dune clean ocaml-integers-0.8.0/README.md000066400000000000000000000042001520254654400157120ustar00rootroot00000000000000# ocaml-integers The `ocaml-integers` library provides a number of 8-, 16-, 32- and 64-bit signed and unsigned integer types, together with aliases such as `long` and `size_t` whose sizes depend on the host platform. ### Features * The interfaces follow the pattern of the signatures of the [`Int32`][int32], [`Int64`][int64], and [`Nativeint`][nativeint] modules in the OCaml standard library. The behaviour also follows the standard library; for example, conversions such as `of_int` truncate, and operations are "modulo" in general: ```ocaml # Unsigned.UInt8.(pred zero);; - : Unsigned.UInt8.t = ``` * Top-level printers for each type are included ```ocaml # Unsigned.UInt32.[of_int 103; one; of_string "1000"];; - : Unsigned.UInt32.t list = [; ; ] ``` * Infix operators are available: ```ocaml # Unsigned.UInt32.(Infix.(one + one));; - : Unsigned.UInt32.t = ``` * Polymorphic operations such as comparison behave correctly: ```ocaml # open Unsigned.UInt32 # zero < one;; - : bool = true # max_int < zero;; - : bool = false ``` * Integers 32 bits and above are boxed; integers below 32 bits are unboxed. ```ocaml # Obj.(tag (repr Unsigned.UInt32.zero));; - : int = 255 # Obj.(tag (repr Unsigned.UInt16.zero));; - : int = 1000 ``` ### Using `integers` with js_of_ocaml The [`integers_stubs_js`][integers_stubs_js] package provides JavaScript stubs that make it possible to use this library with [`js_of_ocaml`][js_of_ocaml] [API documentation][doc] [![Main workflow](https://github.com/ocamllabs/ocaml-integers/actions/workflows/test.yml/badge.svg)](https://github.com/ocamllabs/ocaml-integers/actions/workflows/test.yml) [int32]: http://caml.inria.fr/pub/docs/manual-ocaml/libref/Int32.html [int64]: http://caml.inria.fr/pub/docs/manual-ocaml/libref/Int64.html [nativeint]: http://caml.inria.fr/pub/docs/manual-ocaml/libref/Nativeint.html [doc]: https://yallop.github.io/ocaml-integers/api.docdir/ [integers_stubs_js]: https://github.com/o1-labs/integers_stubs_js [js_of_ocaml]: https://github.com/ocsigen/js_of_ocaml ocaml-integers-0.8.0/dune-project000066400000000000000000000000371520254654400167610ustar00rootroot00000000000000(lang dune 1.0) (name integers)ocaml-integers-0.8.0/integers.opam000066400000000000000000000011651520254654400171400ustar00rootroot00000000000000opam-version: "2.0" maintainer: "yallop@gmail.com" authors: ["Jeremy Yallop" "Demi Obenour" "Stephane Glondu" "Andreas Hauptmann"] homepage: "https://github.com/ocamllabs/ocaml-integers" bug-reports: "https://github.com/ocamllabs/ocaml-integers/issues" dev-repo: "git+https://github.com/ocamllabs/ocaml-integers.git" license: "MIT" build: [ ["dune" "subst"] {dev} ["dune" "build" "-p" name "-j" jobs] ["dune" "runtest" "-p" name "-j" jobs] {with-test} ] depends: [ "ocaml" {>= "4.03"} "dune" {>= "1.0"} "stdlib-shims" ] synopsis: "Various signed and unsigned integer types for OCaml" ocaml-integers-0.8.0/src/000077500000000000000000000000001520254654400152265ustar00rootroot00000000000000ocaml-integers-0.8.0/src/dune000066400000000000000000000003301520254654400161000ustar00rootroot00000000000000(library (name integers) (public_name integers) (wrapped false) (install_c_headers ocaml_integers) (c_names unsigned_stubs) (libraries stdlib-shims) (synopsis "Signed and unsigned integers of various sizes")) ocaml-integers-0.8.0/src/ocaml_integers.h000066400000000000000000000020111520254654400203640ustar00rootroot00000000000000/* * Copyright (c) 2013 Jeremy Yallop. * * This file is distributed under the terms of the MIT License. * See the file LICENSE for details. */ #ifndef INTEGERS_UNSIGNED_STUBS_H #define INTEGERS_UNSIGNED_STUBS_H #include #include #ifndef OCAML_INTEGERS_INTERNAL #ifdef __cplusplus extern "C" { #endif CAMLextern value integers_copy_uint32(uint32_t u); CAMLextern value integers_copy_uint64(uint64_t u); #ifdef __cplusplus } #endif #endif #define Integers_val_uint8(t) ((Val_int((uint8_t)t))) #define Integers_val_uint16(t) ((Val_int((uint16_t)t))) #define Integers_val_int8(t) ((Val_int((int8_t)t))) #define Integers_val_int16(t) ((Val_int((int16_t)t))) #define Uint8_val(V) ((uint8_t)(Int_val(V))) #define Uint16_val(V) ((uint16_t)(Int_val(V))) #define Uint32_val(V) (*((uint32_t *) Data_custom_val(V))) #define Uint64_val(V) (*((uint64_t *) Data_custom_val(V))) #define Int8_val(V) ((int8_t)(Int_val(V))) #define Int16_val(V) ((int16_t)(Int_val(V))) #endif /* INTEGERS_UNSIGNED_STUBS_H */ ocaml-integers-0.8.0/src/signed.ml000066400000000000000000000144771520254654400170460ustar00rootroot00000000000000(* * Copyright (c) 2013 Jeremy Yallop. * Copyright (c) 2021 Nomadic Labs * * This file is distributed under the terms of the MIT License. * See the file LICENSE for details. *) module type Infix = sig type t include Unsigned.Infix with type t := t val (asr) : t -> int -> t end module type S = sig type t module Infix : Infix with type t := t include Unsigned.S with type t := t with module Infix := Infix val neg : t -> t val abs : t -> t val minus_one : t val min_int : t val shift_right_logical : t -> int -> t val of_nativeint : nativeint -> t val to_nativeint : t -> nativeint val of_int64 : int64 -> t val to_int64 : t -> int64 end module type Basics = sig type t val add : t -> t -> t val sub : t -> t -> t val mul : t -> t -> t val div : t -> t -> t val rem : t -> t -> t val logand : t -> t -> t val logor : t -> t -> t val logxor : t -> t -> t val shift_left : t -> int -> t val shift_right : t -> int -> t val shift_right_logical : t -> int -> t end module MakeInfix(S : Basics) = struct open S let (+) = add let (-) = sub let ( * ) = mul let (/) = div let (mod) = rem let (land) = logand let (lor) = logor let (lxor) = logxor let (lsl) = shift_left let (lsr) = shift_right_logical let (asr) = shift_right end module type Small = sig val bits : int end module MakeSmall(S : Small) = struct let shift = Sys.int_size - S.bits let trunc i = (i lsl shift) asr shift module Basics = struct type t = int external to_int : t -> int = "%identity" let to_string i = Printf.sprintf "%d" i let to_hexstring i = let m = 1 lsl S.bits in Printf.sprintf "%x" ((i + m) mod m) let max_int = pred (1 lsl pred S.bits) let min_int = -(1 lsl pred S.bits) let of_string s = match int_of_string_opt s with | Some i when i >= min_int && i <= max_int -> i | _ -> Printf.ksprintf failwith "Int%d.of_string" S.bits let add : t -> t -> t = fun x y -> trunc (x + y) let sub : t -> t -> t = fun x y -> trunc (x - y) let mul : t -> t -> t = fun x y -> trunc (x * y) let div : t -> t -> t = ( / ) let rem : t -> t -> t = ( mod ) let logand : t -> t -> t = ( land ) let logor : t -> t -> t = ( lor ) let logxor : t -> t -> t = ( lxor ) let shift_left : t -> int -> t = fun x y -> trunc (x lsl y) let shift_right : t -> int -> t = ( asr ) let shift_right_logical : t -> int -> t = fun x y -> ((x lsl shift) lsr y) asr shift let of_int : int -> t = trunc let of_string_opt s = try Some (of_string s) with Failure _ -> None let zero = 0 let one = 1 let minus_one = -1 let lognot = lnot let succ : t -> t = fun x -> trunc (Stdlib.succ x) let pred : t -> t = fun x -> trunc (Stdlib.pred x) let compare : t -> t -> int = Stdlib.compare let equal : t -> t -> bool = Stdlib.( = ) let min : t -> t -> t = Stdlib.min let max : t -> t -> t = Stdlib.max end include Basics module Infix = MakeInfix(Basics) let pp fmt x = Format.fprintf fmt "%s" (to_string x) let pp_hex fmt x = Format.fprintf fmt "%s" (to_hexstring x) let neg = fun x -> trunc (- x) let abs = fun x -> trunc (abs x) let of_int64 = fun x -> trunc (Int64.to_int x) let to_int64 = Int64.of_int let of_nativeint = fun x -> trunc (Nativeint.to_int x) let to_nativeint = Nativeint.of_int end external format_int : string -> int -> string = "caml_format_int" module Int8 = MakeSmall( struct let bits = 8 end) module Int16 = MakeSmall( struct let bits = 16 end) module Int = struct module Basics = struct type t = int let add = ( + ) let sub = ( - ) let mul = ( * ) let div = ( / ) let rem = ( mod ) let max_int = Stdlib.max_int let min_int = Stdlib.min_int let logand = ( land ) let logor = ( lor ) let logxor = ( lxor ) let shift_left = ( lsl ) let shift_right = ( asr ) let shift_right_logical = ( lsr ) let of_int x = x let to_int x = x let of_string = int_of_string let of_string_opt s = try Some (of_string s) with Failure _ -> None let to_string = string_of_int let to_hexstring = format_int "%x" let zero = 0 let one = 1 let minus_one = -1 let lognot = lnot let succ = Stdlib.succ let pred = Stdlib.pred let compare = Stdlib.compare let equal = Stdlib.(=) let max = Stdlib.max let min = Stdlib.min end include Basics module Infix = MakeInfix(Basics) let to_int64 = Int64.of_int let of_int64 = Int64.to_int let to_nativeint = Nativeint.of_int let of_nativeint = Nativeint.to_int let abs = Stdlib.abs let neg x = -x let pp fmt n = Format.fprintf fmt "%d" n let pp_hex fmt n = Format.fprintf fmt "%x" n end module Int32 = struct [@@@ocaml.warning "-32"] (* Int32.of_string_opt was introduced in OCaml 4.5b0.0 *) let of_string_opt s = try Some (Int32.of_string s) with Failure _ -> None include Int32 module Infix = MakeInfix(Int32) let of_nativeint = Nativeint.to_int32 let to_nativeint = Nativeint.of_int32 let of_int64 = Int64.to_int32 let to_int64 = Int64.of_int32 let max = Stdlib.max let min = Stdlib.min let pp fmt n = Format.fprintf fmt "%ld" n let pp_hex fmt n = Format.fprintf fmt "%lx" n let to_hexstring n = Format.asprintf "%lx" n end module Int64 = struct [@@@ocaml.warning "-32"] (* Int32.of_string_opt was introduced in OCaml 4.5b0.0 *) let of_string_opt s = try Some (Int64.of_string s) with Failure _ -> None include Int64 module Infix = MakeInfix(Int64) let of_int64 x = x let to_int64 x = x let max = Stdlib.max let min = Stdlib.min let pp fmt n = Format.fprintf fmt "%Ld" n let pp_hex fmt n = Format.fprintf fmt "%Lx" n let to_hexstring n = Format.asprintf "%Lx" n end (* C guarantees that sizeof(t) == sizeof(unsigned t) *) external int_size : unit -> int = "integers_uint_size" external long_size : unit -> int = "integers_ulong_size" external llong_size : unit -> int = "integers_ulonglong_size" let of_byte_size : int -> (module S) = function | 1 -> (module Int8) | 2 -> (module Int16) | 4 -> (module Int32) | 8 -> (module Int64) | _ -> invalid_arg "Signed.of_byte_size" module SInt = (val of_byte_size (int_size ())) module Long = (val of_byte_size (long_size ())) module LLong = (val of_byte_size (llong_size ())) type sint = SInt.t type long = Long.t type llong = LLong.t ocaml-integers-0.8.0/src/signed.mli000066400000000000000000000045401520254654400172050ustar00rootroot00000000000000(* * Copyright (c) 2013 Jeremy Yallop. * Copyright (c) 2021 Nomadic Labs * * This file is distributed under the terms of the MIT License. * See the file LICENSE for details. *) (** Types and operations for signed integers. *) module type Infix = sig type t include Unsigned.Infix with type t := t val (asr) : t -> int -> t (** [x asr y] shifts [x] to the right by [y] bits. See {!shift_right}. *) end module type S = sig type t module Infix : Infix with type t := t include Unsigned.S with type t := t with module Infix := Infix val neg : t -> t (** Unary negation. *) val abs : t -> t (** Return the absolute value of its argument. *) val minus_one : t (** The value -1 *) val min_int : t (** The smallest representable integer. *) val shift_right_logical : t -> int -> t (** {!shift_right_logical} [x] [y] shifts [x] to the right by [y] bits. See {!Int32.shift_right_logical}. *) val of_nativeint : nativeint -> t (** Convert the given nativeint value to a signed integer. *) val to_nativeint : t -> nativeint (** Convert the given signed integer to a nativeint value. *) val of_int64 : int64 -> t (** Convert the given int64 value to a signed integer. *) val to_int64 : t -> int64 (** Convert the given signed integer to an int64 value. *) end (** Signed integer operations *) module Int8 : S with type t = private int (** Signed 8-bit integer type and operations. *) module Int16 : S with type t = private int (** Signed 16-bit integer type and operations. *) module Int : S with type t = int (** Signed integer type and operations. *) module Int32 : S with type t = int32 (** Signed 32-bit integer type and operations. *) module Int64 : S with type t = int64 (** Signed 64-bit integer type and operations. *) module SInt : S (** C's signed integer type and operations. *) module Long : S (** The signed long integer type and operations. *) module LLong : S (** The signed long long integer type and operations. *) type sint = SInt.t (** C's signed integer type. *) type long = Long.t (** The signed long integer type. *) type llong = LLong.t (** The signed long long integer type. *) val of_byte_size : int -> (module S) (** [of_byte_size b] is a module of type S that implements a signed type with [b] bytes. Raise [Invalid_argument] if no suitable type is available. *) ocaml-integers-0.8.0/src/unsigned.ml000066400000000000000000000231211520254654400173730ustar00rootroot00000000000000(* * Copyright (c) 2013 Jeremy Yallop. * Copyright (c) 2021 Nomadic Labs * * This file is distributed under the terms of the MIT License. * See the file LICENSE for details. *) external init : unit -> unit = "integers_unsigned_init" let () = init () (* Boxed unsigned types *) module type Basics = sig type t val add : t -> t -> t val sub : t -> t -> t val mul : t -> t -> t val div : t -> t -> t val rem : t -> t -> t val max_int : t val logand : t -> t -> t val logor : t -> t -> t val logxor : t -> t -> t val shift_left : t -> int -> t val shift_right : t -> int -> t val of_int : int -> t val to_int : t -> int val of_int64 : int64 -> t val to_int64 : t -> int64 val of_string : string -> t val to_string : t -> string val to_hexstring : t -> string end module type Extras = sig type t val zero : t val one : t val lognot : t -> t val succ : t -> t val pred : t -> t val compare : t -> t -> int val equal : t -> t -> bool val max : t -> t -> t val min : t -> t -> t val of_string_opt : string -> t option val pp : Format.formatter -> t -> unit val pp_hex : Format.formatter -> t -> unit end module type Infix = sig type t val (+) : t -> t -> t val (-) : t -> 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 (lsl) : t -> int -> t val (lsr) : t -> int -> t end module type S = sig include Basics include Extras with type t := t module Infix : Infix with type t := t end module MakeInfix (B : Basics) = struct open B let (+) = add let (-) = sub let ( * ) = mul let (/) = div let (mod) = rem let (land) = logand let (lor) = logor let (lxor) = logxor let (lsl) = shift_left let (lsr) = shift_right end module Extras(Basics : Basics) : Extras with type t := Basics.t = struct open Basics let zero = of_int 0 let one = of_int 1 let succ n = add n one let pred n = sub n one let lognot n = logxor n max_int let compare (x : t) (y : t) = Stdlib.compare x y let equal (x : t) (y : t) = Stdlib.(=) x y let max (x : t) (y : t) = Stdlib.max x y let min (x : t) (y : t) = Stdlib.min x y let of_string_opt (s : string) = try Some (of_string s) with Failure _ -> None let pp fmt x = Format.fprintf fmt "%s" (to_string x) let pp_hex fmt x = Format.fprintf fmt "%s" (to_hexstring x) end external format_int : string -> int -> string = "caml_format_int" module UInt8 : S with type t = private int = struct module B = struct type t = int let max_int = 255 let add : t -> t -> t = fun x y -> (x + y) land max_int let sub : t -> t -> t = fun x y -> (x - y) land max_int let mul : t -> t -> t = fun x y -> (x * y) land max_int let div : t -> t -> t = (/) let rem : t -> t -> t = (mod) let logand: t -> t -> t = (land) let logor: t -> t -> t = (lor) let logxor : t -> t -> t = (lxor) let shift_left : t -> int -> t = fun x y -> (x lsl y) land max_int let shift_right : t -> int -> t = (lsr) let of_int (x: int): t = (* For backwards compatibility, this wraps *) x land max_int external to_int : t -> int = "%identity" let of_int64 : int64 -> t = fun x -> of_int (Int64.to_int x) let to_int64 : t -> int64 = fun x -> Int64.of_int (to_int x) external of_string : string -> t = "integers_uint8_of_string" let to_string : t -> string = string_of_int let to_hexstring : t -> string = format_int "%x" end include B include Extras(B) module Infix = MakeInfix(B) end module UInt16 : S with type t = private int = struct module B = struct type t = int let max_int = 65535 let add : t -> t -> t = fun x y -> (x + y) land max_int let sub : t -> t -> t = fun x y -> (x - y) land max_int let mul : t -> t -> t = fun x y -> (x * y) land max_int let div : t -> t -> t = (/) let rem : t -> t -> t = (mod) let logand: t -> t -> t = (land) let logor: t -> t -> t = (lor) let logxor : t -> t -> t = (lxor) let shift_left : t -> int -> t = fun x y -> (x lsl y) land max_int let shift_right : t -> int -> t = (lsr) let of_int (x: int): t = (* For backwards compatibility, this wraps *) x land max_int external to_int : t -> int = "%identity" let of_int64 : int64 -> t = fun x -> Int64.to_int x |> of_int let to_int64 : t -> int64 = fun x -> to_int x |> Int64.of_int external of_string : string -> t = "integers_uint16_of_string" let to_string : t -> string = string_of_int let to_hexstring : t -> string = format_int "%x" end include B include Extras(B) module Infix = MakeInfix(B) end module UInt32 : sig include S val of_int32 : int32 -> t val to_int32 : t -> int32 end = struct module B = struct type t external add : t -> t -> t = "integers_uint32_add" external sub : t -> t -> t = "integers_uint32_sub" external mul : t -> t -> t = "integers_uint32_mul" external div : t -> t -> t = "integers_uint32_div" external rem : t -> t -> t = "integers_uint32_rem" external logand : t -> t -> t = "integers_uint32_logand" external logor : t -> t -> t = "integers_uint32_logor" external logxor : t -> t -> t = "integers_uint32_logxor" external shift_left : t -> int -> t = "integers_uint32_shift_left" external shift_right : t -> int -> t = "integers_uint32_shift_right" external of_string : string -> t = "integers_uint32_of_string" external to_string : t -> string = "integers_uint32_to_string" external to_hexstring : t -> string = "integers_uint32_to_hexstring" external of_int : int -> t = "integers_uint32_of_int" external to_int : t -> int = "integers_uint32_to_int" external of_int32 : int32 -> t = "integers_uint32_of_int32" let half_max_plus_two = of_string "0x80000001" let half_max_minus_one_signed = 0x7fffffffl let of_int32 i32 = if i32 >= 0l then of_int32 i32 else add half_max_plus_two (of_int32 (Int32.add i32 half_max_minus_one_signed)) external to_int32 : t -> int32 = "integers_int32_of_uint32" let max_signed = of_int32 Int32.max_int let to_int32 u32 = if Stdlib.compare u32 max_signed <= 0 then to_int32 u32 else Int32.sub (to_int32 (sub u32 half_max_plus_two)) half_max_minus_one_signed external of_int64 : int64 -> t = "integers_uint32_of_int64" external to_int64 : t -> int64 = "integers_uint32_to_int64" external _max_int : unit -> t = "integers_uint32_max" let max_int = _max_int () end include B include Extras(B) module Infix = MakeInfix(B) end module UInt64 : sig include S external of_uint32 : UInt32.t -> t = "integers_uint64_of_uint32" external to_uint32 : t -> UInt32.t = "integers_uint32_of_uint64" end = struct module B = struct type t external add : t -> t -> t = "integers_uint64_add" external sub : t -> t -> t = "integers_uint64_sub" external mul : t -> t -> t = "integers_uint64_mul" external div : t -> t -> t = "integers_uint64_div" external rem : t -> t -> t = "integers_uint64_rem" external logand : t -> t -> t = "integers_uint64_logand" external logor : t -> t -> t = "integers_uint64_logor" external logxor : t -> t -> t = "integers_uint64_logxor" external shift_left : t -> int -> t = "integers_uint64_shift_left" external shift_right : t -> int -> t = "integers_uint64_shift_right" external of_int : int -> t = "integers_uint64_of_int" external to_int : t -> int = "integers_uint64_to_int" external of_string : string -> t = "integers_uint64_of_string" external to_string : t -> string = "integers_uint64_to_string" external to_hexstring : t -> string = "integers_uint64_to_hexstring" external of_int64 : int64 -> t = "integers_uint64_of_int64" let half_max_plus_two = of_string "0x8000000000000001" let half_max_minus_one_signed = 0x7fffffffffffffffL let of_int64 i64 = if i64 >= 0L then of_int64 i64 else add half_max_plus_two (of_int64 (Int64.add i64 half_max_minus_one_signed)) external to_int64 : t -> int64 = "integers_uint64_to_int64" let max_signed = of_int64 Int64.max_int let to_int64 u64 = if Stdlib.compare u64 max_signed <= 0 then to_int64 u64 else Int64.sub (to_int64 (sub u64 half_max_plus_two)) half_max_minus_one_signed external of_uint32 : UInt32.t -> t = "integers_uint64_of_uint32" external to_uint32 : t -> UInt32.t = "integers_uint32_of_uint64" external _max_int : unit -> t = "integers_uint64_max" let max_int = _max_int () end include B include Extras(B) module Infix = MakeInfix(B) end let of_byte_size : int -> (module S) = function | 1 -> (module UInt8) | 2 -> (module UInt16) | 4 -> (module UInt32) | 8 -> (module UInt64) | _ -> invalid_arg "Unsigned.of_byte_size" external size_t_size : unit -> int = "integers_size_t_size" external ushort_size : unit -> int = "integers_ushort_size" external uint_size : unit -> int = "integers_uint_size" external ulong_size : unit -> int = "integers_ulong_size" external ulonglong_size : unit -> int = "integers_ulonglong_size" module Size_t : S = (val of_byte_size (size_t_size ())) module UChar = UInt8 module UShort : S = (val of_byte_size (ushort_size ())) module UInt : S = (val of_byte_size (uint_size ())) module ULong : S = (val of_byte_size (ulong_size ())) module ULLong : S = (val of_byte_size (ulonglong_size ())) type uchar = UChar.t type uint8 = UInt8.t type uint16 = UInt16.t type uint32 = UInt32.t type uint64 = UInt64.t type size_t = Size_t.t type ushort = UShort.t type uint = UInt.t type ulong = ULong.t type ullong = ULLong.t ocaml-integers-0.8.0/src/unsigned.mli000066400000000000000000000172761520254654400175620ustar00rootroot00000000000000(* * Copyright (c) 2013 Jeremy Yallop. * Copyright (c) 2021 Nomadic Labs * * This file is distributed under the terms of the MIT License. * See the file LICENSE for details. *) (** Types and operations for unsigned integers. *) module type Infix = sig type t val (+) : t -> t -> t (** Addition. See {!add}. *) val (-) : t -> t -> t (** Subtraction. See {!sub}.*) val ( * ) : t -> t -> t (** Multiplication. See {!mul}.*) val (/) : t -> t -> t (** Division. See {!div}.*) val (mod) : t -> t -> t (** Integer remainder. See {!rem}. *) val (land) : t -> t -> t (** Bitwise logical and. See {!logand}. *) val (lor) : t -> t -> t (** Bitwise logical or. See {!logor}. *) val (lxor) : t -> t -> t (** Bitwise logical exclusive or. See {!logxor}. *) val (lsl) : t -> int -> t (** [x lsl y] shifts [x] to the left by [y] bits. See {!shift_left}. *) val (lsr) : t -> int -> t (** [x lsr y] shifts [x] to the right by [y] bits. See {!shift_right}. *) end (** Infix names for the unsigned integer operations. *) module type S = sig type t val add : t -> t -> t (** Addition. *) val sub : t -> t -> t (** Subtraction. *) val mul : t -> t -> t (** Multiplication. *) val div : t -> t -> t (** Division. Raise {!Division_by_zero} if the second argument is zero. *) val rem : t -> t -> t (** Integer remainder. Raise {!Division_by_zero} if the second argument is zero. *) val max_int : t (** The greatest representable integer. *) val logand : t -> t -> t (** Bitwise logical and. *) val logor : t -> t -> t (** Bitwise logical or. *) val logxor : t -> t -> t (** Bitwise logical exclusive or. *) val shift_left : t -> int -> t (** {!shift_left} [x] [y] shifts [x] to the left by [y] bits. *) val shift_right : t -> int -> t (** {!shift_right} [x] [y] shifts [x] to the right by [y] bits. *) val of_int : int -> t (** Convert the given int value to an unsigned integer. *) val to_int : t -> int (** Convert the given unsigned integer value to an int. *) val of_int64 : int64 -> t (** Convert the given int64 value to an unsigned integer. *) val to_int64 : t -> int64 (** Convert the given unsigned integer value to an int64. *) val of_string : string -> t (** Convert the given string to an unsigned integer. Raise {!Failure} if the given string is not a valid representation of an unsigned integer. *) val to_string : t -> string (** Return the string representation of its argument. *) val to_hexstring : t -> string (** Return the hexadecimal string representation of its argument. *) val zero : t (** The integer 0. *) val one : t (** The integer 1. *) val lognot : t -> t (** Bitwise logical negation. *) val succ : t -> t (** Successor. *) val pred : t -> t (** Predecessor. *) val compare : t -> t -> int (** The comparison function for unsigned integers, with the same specification as {!Stdlib.compare}. *) val equal : t -> t -> bool (** Tests for equality, with the same specification as {!Stdlib.(=)}. *) val max : t -> t -> t (** [max x y] is the greater of [x] and [y] *) val min : t -> t -> t (** [min x y] is the lesser of [x] and [y] *) val of_string_opt : string -> t option (** Convert the given string to an unsigned integer. Returns [None] if the given string is not a valid representation of an unsigned integer. *) val pp : Format.formatter -> t -> unit (** Output the result of {!to_string} on a formatter. *) val pp_hex : Format.formatter -> t -> unit (** Output the result of {!to_hexstring} on a formatter. *) module Infix : Infix with type t := t end (** Unsigned integer operations. *) module UChar : S with type t = private int (** Unsigned char type and operations. *) module UInt8 : S with type t = private int (** Unsigned 8-bit integer type and operations. *) module UInt16 : S with type t = private int (** Unsigned 16-bit integer type and operations. *) module UInt32 : sig include S val of_int32 : int32 -> t (** Convert the given 32-bit signed integer to an unsigned 32-bit integer. If the signed integer fits within the unsigned range (in other words, if the signed integer is positive) then the numerical values represented by the signed and unsigned integers are the same. Whether the signed integer fits or not, the function [of_int32] is always the inverse of the function {!to_int32}. In other words, [to_int32 (of_int32 x) = x] holds for all [x : int32]. *) val to_int32 : t -> int32 (** Convert the given 32-bit unsigned integer to a signed 32-bit integer. If the unsigned integer fits within the signed range (in other words, if the unsigned integer is less than {!Int32.max_int}) then the numerical values represented by unsigned and signed integers are the same. Whether the unsigned integer fits or not, the function [to_int32] is always the inverse of the function {!of_int32}. In other words, [of_int32 (to_int32 x) = x] holds for all [x : t]. *) end (** Unsigned 32-bit integer type and operations. *) module UInt64 : sig include S val of_int64 : int64 -> t (** Convert the given 64-bit signed integer to an unsigned 64-bit integer. If the signed integer fits within the unsigned range (in other words, if the signed integer is positive) then the numerical values represented by the signed and unsigned integers are the same. Whether the signed integer fits or not, the function [of_int64] is always the inverse of the function {!to_int64}. In other words, [to_int64 (of_int64 x) = x] holds for all [x : int64]. *) val to_int64 : t -> int64 (** Convert the given 64-bit unsigned integer to a signed 64-bit integer. If the unsigned integer fits within the signed range (in other words, if the unsigned integer is less than {!Int64.max_int}) then the numerical values represented by unsigned and signed integers are the same. Whether the unsigned integer fits or not, the function [to_int64] is always the inverse of the function {!of_int64}. In other words, [of_int64 (to_int64 x) = x] holds for all [x : t]. *) val of_uint32 : UInt32.t -> t (** Convert the given 32-bit unsigned integer to a 64-bit unsigned integer. *) val to_uint32 : t -> UInt32.t (** Convert the given 64-bit unsigned integer to a 32-bit unsigned integer. The 64-bit unsigned integer is taken modulo 2{^32}, i.e. the top 32 bits are lost during the conversion. *) end (** Unsigned 64-bit integer type and operations. *) module Size_t : S (** The size_t unsigned integer type and operations. *) module UShort : S (** The unsigned short integer type and operations. *) module UInt : S (** The unsigned int type and operations. *) module ULong : S (** The unsigned long integer type and operations. *) module ULLong : S (** The unsigned long long integer type and operations. *) type uchar = UChar.t (** The unsigned char type. *) type uint8 = UInt8.t (** Unsigned 8-bit integer type. *) type uint16 = UInt16.t (** Unsigned 16-bit integer type. *) type uint32 = UInt32.t (** Unsigned 32-bit integer type. *) type uint64 = UInt64.t (** Unsigned 64-bit integer type. *) type size_t = Size_t.t (** The size_t unsigned integer type. *) type ushort = UShort.t (** The unsigned short unsigned integer type. *) type uint = UInt.t (** The unsigned int type. *) type ulong = ULong.t (** The unsigned long integer type. *) type ullong = ULLong.t (** The unsigned long long integer type. *) val of_byte_size : int -> (module S) (** [of_byte_size b] is a module of type S that implements an unsigned type with [b] bytes. Raise [Invalid_argument] if no suitable type is available. *) ocaml-integers-0.8.0/src/unsigned_stubs.c000066400000000000000000000544731520254654400204430ustar00rootroot00000000000000/* * Copyright (c) 2013 Jeremy Yallop. * * This file is distributed under the terms of the MIT License. * See the file LICENSE for details. */ #if !__USE_MINGW_ANSI_STDIO && (defined(__MINGW32__) || defined(__MINGW64__)) #define __USE_MINGW_ANSI_STDIO 1 #endif #include #include #include #include #include #include #include #include #include #define OCAML_INTEGERS_INTERNAL 1 #include "ocaml_integers.h" #define UINT_DECLS(BITS) \ extern value integers_copy_uint ## BITS(uint ## BITS ## _t u); \ /* uintX_add : t -> t -> t */ \ extern value integers_uint ## BITS ## _ ## add(value a, value b); \ /* uintX_sub : t -> t -> t */ \ extern value integers_uint ## BITS ## _ ## sub(value a, value b); \ /* uintX_mul : t -> t -> t */ \ extern value integers_uint ## BITS ## _ ## mul(value a, value b); \ /* uintX_div : t -> t -> t */ \ extern value integers_uint ## BITS ## _ ## div(value a, value b); \ /* uintX_rem : t -> t -> t */ \ extern value integers_uint ## BITS ## _ ## rem(value a, value b); \ /* uintX_logand : t -> t -> t */ \ extern value integers_uint ## BITS ## _ ## logand(value a, value b); \ /* uintX_logor : t -> t -> t */ \ extern value integers_uint ## BITS ## _ ## logor(value a, value b); \ /* uintX_logxor : t -> t -> t */ \ extern value integers_uint ## BITS ## _ ## logxor(value a, value b); \ /* uintX_shift_left : t -> t -> t */ \ extern value integers_uint ## BITS ## _ ## shift_left(value a, value b); \ /* uintX_shift_right : t -> t -> t */ \ extern value integers_uint ## BITS ## _ ## shift_right(value a, value b); \ /* of_int : int -> t */ \ extern value integers_uint ## BITS ## _of_int(value a); \ /* to_int : t -> int */ \ extern value integers_uint ## BITS ## _to_int(value a); \ /* of_string : string -> t */ \ extern value integers_uint ## BITS ## _of_string(value a); \ /* to_string : t -> string */ \ extern value integers_uint ## BITS ## _to_string(value a); \ /* max : unit -> t */ \ extern value integers_uint ## BITS ## _max(value a); #define UINT_SMALL_DECLS(BITS) \ /* of_string : string -> t */ \ extern value integers_uint ## BITS ## _of_string(value a); \ /* to_string : t -> string */ \ extern value integers_uint ## BITS ## _to_string(value a); \ /* max : unit -> t */ \ extern value integers_uint ## BITS ## _max(value a); UINT_SMALL_DECLS(8) UINT_SMALL_DECLS(16) UINT_DECLS(32) UINT_DECLS(64) /* X_size : unit -> int */ extern value integers_size_t_size (value _); extern value integers_ushort_size (value _); extern value integers_uint_size (value _); extern value integers_ulong_size (value _); extern value integers_ulonglong_size (value _); static int parse_digit(char c) { if (c >= '0' && c <= '9') return c - '0'; else if (c >= 'A' && c <= 'F') return c - 'A' + 10; else if (c >= 'a' && c <= 'f') return c - 'a' + 10; else return -1; } #define Uint_custom_val(SIZE, V) Uint_custom_val_(SIZE, V) #define Uint_custom_val_(SIZE, V) \ (*(uint ## SIZE ## _t *)(Data_custom_val(V))) #define TYPE(SIZE) uint ## SIZE ## _t #define BUF_SIZE(TYPE) ((sizeof(TYPE) * CHAR_BIT + 2) / 3 + 1) #define UINT_PRIMOP(NAME, SIZE, OP) \ /* OP : t -> t -> t */ \ value integers_uint ## SIZE ## _ ## NAME(value a, value b) \ { \ return integers_copy_uint ## SIZE(Uint_custom_val(SIZE, a) \ OP Uint_custom_val(SIZE, b)); \ } #define UINT_OF_STRING(BITS, COPY) \ value integers_uint ## BITS ## _of_string(value a) \ { \ TYPE(BITS) u, max_prefix; \ const char *pos = String_val(a); \ int base = 10, d; \ \ /* Strip a leading + sign, if given */ \ if (*pos == '+') pos++; \ if (*pos == '0') { \ switch (pos[1]) { \ case 'x': case 'X': \ base = 16; pos += 2; break; \ case 'o': case 'O': \ base = 8; pos += 2; break; \ case 'b': case 'B': \ base = 2; pos += 2; break; \ case 'u': case 'U': /* Unsigned prefix. No-op for unsigned types */ \ pos += 2; break; \ } \ } \ \ max_prefix = ((TYPE(BITS)) -1) / base; \ \ d = parse_digit(*pos); \ if (d < 0 || d >= base) { \ caml_failwith("UInt"#BITS".of_string"); \ } \ u = (TYPE(BITS)) d; \ pos++; \ \ for (;; pos++) { \ if (*pos == '_') continue; \ d = parse_digit(*pos); \ /* Halt if the digit isn't valid (or this is the string terminator) */ \ if (d < 0 || d >= base) break; \ /* Check that we can add another digit */ \ if (u > max_prefix) break; \ u = d + u * base; \ /* Check for overflow */ \ if (u < (TYPE(BITS)) d) break; \ } \ \ if (pos != String_val(a) + caml_string_length(a)){ \ caml_failwith("UInt"#BITS".of_string"); \ } \ \ return COPY(u); \ } \ #define UINT_DEFS(BITS, BYTES) \ static int uint ## BITS ## _cmp(value v1, value v2) \ { \ TYPE(BITS) u1 = Uint_custom_val(BITS, v1); \ TYPE(BITS) u2 = Uint_custom_val(BITS, v2); \ return (u1 > u2) - (u1 < u2); \ } \ \ static intnat uint ## BITS ## _hash(value v) \ { \ return Uint_custom_val(BITS, v); \ } \ \ static void uint ## BITS ## _serialize(value v, \ uintnat *wsize_32, \ uintnat *wsize_64) \ { \ caml_serialize_int_ ## BYTES(Uint_custom_val(BITS, v)); \ *wsize_32 = *wsize_64 = BYTES; \ } \ \ static uintnat uint ## BITS ## _deserialize(void *dst) \ { \ *(TYPE(BITS) *)dst = caml_deserialize_uint_ ## BYTES(); \ return BYTES; \ } \ \ static struct custom_operations caml_uint ## BITS ## _ops = { \ "integers:uint" #BITS, \ custom_finalize_default, \ uint ## BITS ## _cmp, \ uint ## BITS ## _hash, \ uint ## BITS ## _serialize, \ uint ## BITS ## _deserialize, \ custom_compare_ext_default \ }; \ \ value integers_copy_uint ## BITS(TYPE(BITS) u) \ { \ value res = caml_alloc_custom(&caml_uint ## BITS ## _ops, BYTES, 0, 1); \ Uint_custom_val(BITS, res) = u; \ return res; \ } \ UINT_PRIMOP(add, BITS, +) \ UINT_PRIMOP(sub, BITS, -) \ UINT_PRIMOP(mul, BITS, *) \ UINT_PRIMOP(logand, BITS, &) \ UINT_PRIMOP(logor, BITS, |) \ UINT_PRIMOP(logxor, BITS, ^) \ \ /* div : t -> t -> t */ \ value integers_uint ## BITS ## _div(value n_, value d_) \ { \ TYPE(BITS) n = Uint_custom_val(BITS, n_); \ TYPE(BITS) d = Uint_custom_val(BITS, d_); \ if (d == (TYPE(BITS)) 0) \ caml_raise_zero_divide(); \ return integers_copy_uint ## BITS (n / d); \ } \ \ /* rem : t -> t -> t */ \ value integers_uint ## BITS ## _rem(value n_, value d_) \ { \ TYPE(BITS) n = Uint_custom_val(BITS, n_); \ TYPE(BITS) d = Uint_custom_val(BITS, d_); \ if (d == (TYPE(BITS)) 0) \ caml_raise_zero_divide(); \ return integers_copy_uint ## BITS (n % d); \ } \ \ /* shift_left : t -> int -> t */ \ value integers_uint ## BITS ## _shift_left(value a, value b) \ { \ return integers_copy_uint ## BITS(Uint_custom_val(BITS, a) \ << Long_val(b)); \ } \ \ /* shift_right : t -> int -> t */ \ value integers_uint ## BITS ## _shift_right(value a, value b) \ { \ return integers_copy_uint ## BITS(Uint_custom_val(BITS, a) \ >> Long_val(b)); \ } \ \ /* of_int : int -> t */ \ value integers_uint ## BITS ## _of_int(value a) \ { \ return integers_copy_uint ## BITS (Long_val(a)); \ } \ \ /* to_int : t -> int */ \ value integers_uint ## BITS ## _to_int(value a) \ { \ return Val_long(Uint_custom_val(BITS, a)); \ } \ \ /* of_int64 : int64 -> t */ \ value integers_uint ## BITS ## _of_int64(value a) \ { \ return integers_copy_uint ## BITS(Int64_val(a)); \ } \ \ /* to_int64 : t -> int64 */ \ value integers_uint ## BITS ## _to_int64(value a) \ { \ return caml_copy_int64(Uint_custom_val(BITS, a)); \ } \ \ /* of_string : string -> t */ \ UINT_OF_STRING(BITS, integers_copy_uint ## BITS) \ \ /* to_string : t -> string */ \ value integers_uint ## BITS ## _to_string(value a) \ { \ char buf[BUF_SIZE(TYPE(BITS))]; \ if (sprintf(buf, "%" PRIu ## BITS , Uint_custom_val(BITS, a)) < 0) \ caml_failwith("UInt ## BITS ## .to_string"); \ else \ return caml_copy_string(buf); \ } \ \ /* to_hexstring : t -> string */ \ value integers_uint ## BITS ## _to_hexstring(value a) \ { \ char buf[BUF_SIZE(TYPE(BITS))]; \ if (sprintf(buf, "%" PRIx ## BITS , Uint_custom_val(BITS, a)) < 0) \ caml_failwith("UInt ## BITS ## .to_hexstring"); \ else \ return caml_copy_string(buf); \ } \ \ /* max : unit -> t */ \ value integers_uint ## BITS ## _max(value a) \ { \ return integers_copy_uint ## BITS ((TYPE(BITS))(-1)); \ } #define UINT_SMALL_DEFS(BITS, BYTES) \ /* of_string : string -> t */ \ UINT_OF_STRING(BITS, Integers_val_uint ## BITS) \ \ /* to_string : t -> string */ \ value integers_uint ## BITS ## _to_string(value a) \ { \ char buf[BUF_SIZE(TYPE(BITS))]; \ if (sprintf(buf, "%" PRIu ## BITS , Uint ## BITS ##_val(a)) < 0) \ caml_failwith("UInt ## BITS ## .to_string"); \ else \ return caml_copy_string(buf); \ } \ \ /* to_hexstring : t -> string */ \ value integers_uint ## BITS ## _to_hexstring(value a) \ { \ char buf[BUF_SIZE(TYPE(BITS))]; \ if (sprintf(buf, "%" PRIx ## BITS , Uint ## BITS ##_val(a)) < 0) \ caml_failwith("UInt ## BITS ## .to_hexstring"); \ else \ return caml_copy_string(buf); \ } \ \ /* max : unit -> t */ \ value integers_uint ## BITS ## _max(value unit) \ { \ return Integers_val_uint ## BITS((TYPE(BITS))(-1)); \ } UINT_SMALL_DEFS(8, 1) UINT_SMALL_DEFS(16, 2) UINT_DEFS(32, 4) UINT_DEFS(64, 8) value integers_size_t_size (value _) { return Val_long(sizeof (size_t)); } value integers_ushort_size (value _) { return Val_long(sizeof (unsigned short)); } value integers_uint_size (value _) { return Val_long(sizeof (unsigned int)); } value integers_ulong_size (value _) { return Val_long(sizeof (unsigned long)); } value integers_ulonglong_size (value _) { return Val_long(sizeof (unsigned long long)); } value integers_uint32_of_int32 (value i) { return integers_copy_uint32(Int32_val(i)); } value integers_int32_of_uint32 (value u) { return caml_copy_int32(Uint_custom_val(32, u)); } value integers_uintptr_t_size (value _) { return Val_long(sizeof (uintptr_t)); } value integers_intptr_t_size (value _) { return Val_long(sizeof (intptr_t)); } value integers_ptrdiff_t_size (value _) { return Val_long(sizeof (ptrdiff_t)); } value integers_uint32_of_uint64 (value u) { return integers_copy_uint32(Uint_custom_val(64,u)); } value integers_uint64_of_uint32 (value u) { return integers_copy_uint64(Uint_custom_val(32,u)); } value integers_unsigned_init(value unit) { caml_register_custom_operations(&caml_uint32_ops); caml_register_custom_operations(&caml_uint64_ops); return Val_unit; } ocaml-integers-0.8.0/test/000077500000000000000000000000001520254654400154165ustar00rootroot00000000000000ocaml-integers-0.8.0/test/dune000066400000000000000000000001711520254654400162730ustar00rootroot00000000000000(tests (package integers) (libraries integers) (names hexprinting uint64conversions uint32conversions smallsint)) ocaml-integers-0.8.0/test/hexprinting.ml000066400000000000000000000041101520254654400203030ustar00rootroot00000000000000(* * Copyright (c) 2021 Nomadic Labs * * This file is distributed under the terms of the MIT License. * See the file LICENSE for details. *) let () = print_endline "Hexstring test: ?" let () = Printexc.record_backtrace true let () = assert Signed.Int.(to_hexstring (of_string "0x23") = "23"); assert Signed.Int8.(to_hexstring (of_string "0x23") = "23"); assert Signed.Int16.(to_hexstring (of_string "0x23") = "23"); assert Signed.Int32.(to_hexstring (of_string "0x23") = "23"); assert Signed.Int64.(to_hexstring (of_string "0x23") = "23"); assert Unsigned.UInt8.(to_hexstring (of_string "0x23") = "23"); assert Unsigned.UInt16.(to_hexstring (of_string "0x23") = "23"); assert Unsigned.UInt32.(to_hexstring (of_string "0x23") = "23"); assert Unsigned.UInt64.(to_hexstring (of_string "0x23") = "23"); () let () = assert Signed.Int.(to_hexstring (of_string "0xDeadBeef") = "deadbeef"); assert Signed.Int8.(to_hexstring (of_string "0xD") = "d"); assert Signed.Int16.(to_hexstring (of_string "0xDea") = "dea"); assert Signed.Int32.(to_hexstring (of_string "0xDeadBeef") = "deadbeef"); assert Signed.Int64.(to_hexstring (of_string "0xDeadBeef") = "deadbeef"); assert Unsigned.UInt8.(to_hexstring (of_string "0xDe") = "de"); assert Unsigned.UInt16.(to_hexstring (of_string "0xDead") = "dead"); assert Unsigned.UInt32.(to_hexstring (of_string "0xDeadBeef") = "deadbeef"); assert Unsigned.UInt64.(to_hexstring (of_string "0xDeadBeef") = "deadbeef"); () let () = assert Signed.Int.(to_hexstring (of_string "0x0") = "0"); assert Signed.Int8.(to_hexstring (of_string "0x0") = "0"); assert Signed.Int16.(to_hexstring (of_string "0x0") = "0"); assert Signed.Int32.(to_hexstring (of_string "0x0") = "0"); assert Signed.Int64.(to_hexstring (of_string "0x0") = "0"); assert Unsigned.UInt8.(to_hexstring (of_string "0x0") = "0"); assert Unsigned.UInt16.(to_hexstring (of_string "0x0") = "0"); assert Unsigned.UInt32.(to_hexstring (of_string "0x0") = "0"); assert Unsigned.UInt64.(to_hexstring (of_string "0x0") = "0"); () let () = print_endline "Hexstring test: ✓" ocaml-integers-0.8.0/test/smallsint.ml000066400000000000000000000325661520254654400177720ustar00rootroot00000000000000let () = print_endline "Small signed int operations test: ?" (* --- Int8 tests --- *) (* Asserting max and min integers are correct *) let () = let open Signed.Int8 in assert (to_int max_int = 127); assert (to_int min_int = (-128)); () (* Asserting that of_int truncates to 8 bits *) let () = let open Signed.Int8 in let check expected res = Stdlib.( = ) expected (to_int res) in assert (check 0 zero); assert (check 1 one); assert (check (-1) minus_one); assert (check 127 (of_int 127)); (* of_int truncates: 128 wraps to -128 in 8-bit signed *) assert (check (-128) (of_int 128)); assert (check (-64) (of_int 192)); () (* Asserting that roundtrip int -> string -> int conversions survive *) let () = let open Signed.Int8 in let check i = let str = to_string i in equal i (of_string str) in assert (check (of_int 0)); assert (check (of_int 1)); assert (check (of_int 127)); assert (check (of_int (-1))); assert (check (of_int (-128))); () (* Asserting that addition performs as expected *) let () = let open Signed.Int8 in let check expected res = Stdlib.( = ) expected (to_int res) in assert (check 1 (add zero one)); assert (check (-128) (add max_int one)); assert (check (-65) (add max_int (of_int 64))); () (* Asserting that subtraction performs as expected *) let () = let open Signed.Int8 in let check expected res = Stdlib.( = ) expected (to_int res) in assert (check (-1) (sub zero one)); assert (check 127 (sub min_int one)); assert (check 64 (sub min_int (of_int 64))); () (* Asserting that multiplication performs as expected *) let () = let open Signed.Int8 in let check expected res = Stdlib.( = ) expected (to_int res) in assert (check (-1) (mul minus_one one)); assert (check (-128) (mul minus_one min_int)); assert (check (-2) (mul max_int (of_int 2))); () (* Asserting that division and remainder perform as expected *) let () = let open Signed.Int8 in let check expected res = Stdlib.( = ) expected (to_int res) in assert (check 63 (div max_int (of_int 2))); assert (check (-64) (div min_int (of_int 2))); assert (check 1 (rem max_int (of_int 2))); assert (check 0 (rem min_int (of_int 2))); () (* Asserting that bitwise operations perform as expected *) let () = let open Signed.Int8 in let check expected res = Stdlib.( = ) expected (to_int res) in assert (check 0 (logand (of_int 0x0F) (of_int 0x70))); assert (check 0x7F (logor (of_int 0x0F) (of_int 0x70))); assert (check 0x7F (logxor (of_int 0x0F) (of_int 0x70))); assert (check 0 (logxor max_int max_int)); assert (check 0 (logand zero max_int)); assert (check (-1) (lognot zero)); assert (check 0 (lognot minus_one)); () (* Asserting that shift operations perform as expected *) let () = let open Signed.Int8 in let check expected res = Stdlib.( = ) expected (to_int res) in assert (check 2 (shift_left one 1)); assert (check (-128) (shift_left one 7)); assert (check (-1) (shift_right minus_one 1)); assert (check 63 (shift_right max_int 1)); assert (check (-1) (shift_right_logical minus_one 0)); assert (check 127 (shift_right_logical minus_one 1)); () (* Asserting that neg and abs perform as expected *) let () = let open Signed.Int8 in let check expected res = Stdlib.( = ) expected (to_int res) in assert (check (-1) (neg one)); assert (check 1 (neg minus_one)); assert (check 1 (abs one)); assert (check 1 (abs minus_one)); assert (check 127 (abs max_int)); () (* Asserting that succ and pred perform as expected *) let () = let open Signed.Int8 in let check expected res = Stdlib.( = ) expected (to_int res) in assert (check 1 (succ zero)); assert (check (-1) (pred zero)); assert (check (-128) (succ max_int)); assert (check 127 (pred min_int)); () (* Asserting that compare and equal perform as expected *) let () = let open Signed.Int8 in assert (equal zero zero); assert (equal max_int max_int); assert (not (equal zero one)); assert (compare zero one < 0); assert (compare one zero > 0); assert (compare min_int max_int < 0); assert (Stdlib.( = ) (max zero one) one); assert (Stdlib.( = ) (min zero one) zero); () (* Asserting that integer parsing performs as expected *) let () = let open Signed.Int8 in let check expected res = Stdlib.( = ) expected (to_int res) in assert (check 1 (of_string "1")); assert (check 127 (of_string "127")); assert (check (-128) (of_string "-128")); assert (try (ignore (of_string "128"); false) with Failure _ -> true); assert (try (ignore (of_string "-129"); false) with Failure _ -> true); assert (check (-1) (of_string "-1")); assert (check 0b01 (of_string "0b01")); assert (check (-0b01) (of_string "-0b01")); assert (check 0xf (of_string "0xf")); assert (check (-0xf) (of_string "-0xf")); assert (check 0x7f (of_string "0x7f")); assert (check (-0x80) (of_string "-0x80")); assert (try (ignore (of_string "0x80"); false) with Failure _ -> true); assert (try (ignore (of_string "-0x81"); false) with Failure _ -> true); assert (Signed.Int8.of_string_opt "127" <> None); assert (Signed.Int8.of_string_opt "bad" = None); () (* Asserting that integer printing performs as expected *) let () = let open Signed.Int8 in assert (to_string one = "1"); assert (to_string (of_int 127) = "127"); (* of_int truncates: 128 wraps to -128 in 8-bit signed *) assert (to_string (of_int 128) = "-128"); assert (to_string (of_int (-128)) = "-128"); (* of_int truncates: -129 wraps to 127 in 8-bit signed *) assert (to_string (of_int (-129)) = "127"); assert (to_string (of_int (-1)) = "-1"); (* hexstring prints unsigned two's complement representation *) assert (to_hexstring (of_int 0xf) = "f"); assert (to_hexstring max_int = "7f"); assert (to_hexstring min_int = "80"); assert (to_hexstring (of_int (-0x7f)) = "81"); () (* Asserting that of_int64/to_int64 conversions work *) let () = let open Signed.Int8 in let check expected res = Stdlib.( = ) expected (to_int res) in assert (check 0 (of_int64 0L)); assert (check 1 (of_int64 1L)); assert (check 127 (of_int64 127L)); assert (check (-128) (of_int64 128L)); assert (Int64.equal (to_int64 one) 1L); assert (Int64.equal (to_int64 minus_one) (-1L)); assert (Int64.equal (to_int64 max_int) 127L); assert (Int64.equal (to_int64 min_int) (-128L)); () (* Asserting that of_nativeint/to_nativeint conversions work *) let () = let open Signed.Int8 in let check expected res = Stdlib.( = ) expected (to_int res) in assert (check 0 (of_nativeint 0n)); assert (check 127 (of_nativeint 127n)); assert (check (-128) (of_nativeint 128n)); assert (Nativeint.equal (to_nativeint one) 1n); assert (Nativeint.equal (to_nativeint minus_one) (-1n)); () (* --- Int16 tests --- *) (* Asserting max and min integers are correct *) let () = let open Signed.Int16 in assert (to_int max_int = 32767); assert (to_int min_int = (-32768)); () (* Asserting that of_int truncates to 16 bits *) let () = let open Signed.Int16 in let check expected res = Stdlib.( = ) expected (to_int res) in assert (check 0 zero); assert (check 1 one); assert (check (-1) minus_one); assert (check 32767 (of_int 32767)); (* of_int truncates: 32768 wraps to -32768 in 16-bit signed *) assert (check (-32768) (of_int 32768)); assert (check (-1) (of_int 65535)); () (* Asserting that roundtrip int -> string -> int conversions survive *) let () = let open Signed.Int16 in let check i = let str = to_string i in equal i (of_string str) in assert (check (of_int 0)); assert (check (of_int 1)); assert (check (of_int 32767)); assert (check (of_int (-1))); assert (check (of_int (-32768))); () (* Asserting that addition performs as expected *) let () = let open Signed.Int16 in let check expected res = Stdlib.( = ) expected (to_int res) in assert (check 1 (add zero one)); assert (check (-32768) (add max_int one)); assert (check (-1) (add max_int (of_int 32768))); () (* Asserting that subtraction performs as expected *) let () = let open Signed.Int16 in let check expected res = Stdlib.( = ) expected (to_int res) in assert (check (-1) (sub zero one)); assert (check 32767 (sub min_int one)); () (* Asserting that multiplication performs as expected *) let () = let open Signed.Int16 in let check expected res = Stdlib.( = ) expected (to_int res) in assert (check (-1) (mul minus_one one)); assert (check (-32768) (mul minus_one min_int)); assert (check (-2) (mul max_int (of_int 2))); () (* Asserting that division and remainder perform as expected *) let () = let open Signed.Int16 in let check expected res = Stdlib.( = ) expected (to_int res) in assert (check 16383 (div max_int (of_int 2))); assert (check (-16384) (div min_int (of_int 2))); assert (check 1 (rem max_int (of_int 2))); assert (check 0 (rem min_int (of_int 2))); () (* Asserting that bitwise operations perform as expected *) let () = let open Signed.Int16 in let check expected res = Stdlib.( = ) expected (to_int res) in assert (check 0 (logand (of_int 0x00FF) (of_int 0x7F00))); assert (check 0x7FFF (logor (of_int 0x00FF) (of_int 0x7F00))); assert (check 0x7FFF (logxor (of_int 0x00FF) (of_int 0x7F00))); assert (check 0 (logxor max_int max_int)); assert (check (-1) (lognot zero)); assert (check 0 (lognot minus_one)); () (* Asserting that shift operations perform as expected *) let () = let open Signed.Int16 in let check expected res = Stdlib.( = ) expected (to_int res) in assert (check 2 (shift_left one 1)); assert (check (-32768) (shift_left one 15)); assert (check (-1) (shift_right minus_one 1)); assert (check 16383 (shift_right max_int 1)); assert (check (-1) (shift_right_logical minus_one 0)); assert (check 32767 (shift_right_logical minus_one 1)); () (* Asserting that neg and abs perform as expected *) let () = let open Signed.Int16 in let check expected res = Stdlib.( = ) expected (to_int res) in assert (check (-1) (neg one)); assert (check 1 (neg minus_one)); assert (check 1 (abs one)); assert (check 1 (abs minus_one)); assert (check 32767 (abs max_int)); () (* Asserting that succ and pred perform as expected *) let () = let open Signed.Int16 in let check expected res = Stdlib.( = ) expected (to_int res) in assert (check 1 (succ zero)); assert (check (-1) (pred zero)); assert (check (-32768) (succ max_int)); assert (check 32767 (pred min_int)); () (* Asserting that compare and equal perform as expected *) let () = let open Signed.Int16 in assert (equal zero zero); assert (equal max_int max_int); assert (not (equal zero one)); assert (compare zero one < 0); assert (compare one zero > 0); assert (compare min_int max_int < 0); assert (Stdlib.( = ) (max zero one) one); assert (Stdlib.( = ) (min zero one) zero); () (* Asserting that integer parsing performs as expected *) let () = let open Signed.Int16 in let check expected res = Stdlib.( = ) expected (to_int res) in assert (check 1 (of_string "1")); assert (check 32767 (of_string "32767")); assert (check (-32768) (of_string "-32768")); assert (try (ignore (of_string "32768"); false) with Failure _ -> true); assert (try (ignore (of_string "-32769"); false) with Failure _ -> true); assert (check (-1) (of_string "-1")); assert (check 0b01 (of_string "0b01")); assert (check (-0b01) (of_string "-0b01")); assert (check 0xff (of_string "0xff")); assert (check (-0xff) (of_string "-0xff")); assert (check 0x7fff (of_string "0x7fff")); assert (check (-0x8000) (of_string "-0x8000")); assert (try (ignore (of_string "0x8000"); false) with Failure _ -> true); assert (try (ignore (of_string "-0x8001"); false) with Failure _ -> true); assert (Signed.Int16.of_string_opt "32767" <> None); assert (Signed.Int16.of_string_opt "bad" = None); () (* Asserting that integer printing performs as expected *) let () = let open Signed.Int16 in assert (to_string one = "1"); assert (to_string (of_int 32767) = "32767"); (* of_int truncates: 32768 wraps to -32768 in 16-bit signed *) assert (to_string (of_int 32768) = "-32768"); assert (to_string (of_int (-32768)) = "-32768"); assert (to_string (of_int (-1)) = "-1"); (* hexstring prints unsigned two's complement representation *) assert (to_hexstring (of_int 0xff) = "ff"); assert (to_hexstring max_int = "7fff"); assert (to_hexstring min_int = "8000"); assert (to_hexstring (of_int (-1)) = "ffff"); () (* Asserting that of_int64/to_int64 conversions work *) let () = let open Signed.Int16 in let check expected res = Stdlib.( = ) expected (to_int res) in assert (check 0 (of_int64 0L)); assert (check 1 (of_int64 1L)); assert (check 32767 (of_int64 32767L)); assert (check (-32768) (of_int64 32768L)); assert (Int64.equal (to_int64 one) 1L); assert (Int64.equal (to_int64 minus_one) (-1L)); assert (Int64.equal (to_int64 max_int) 32767L); assert (Int64.equal (to_int64 min_int) (-32768L)); () (* Asserting that of_nativeint/to_nativeint conversions work *) let () = let open Signed.Int16 in let check expected res = Stdlib.( = ) expected (to_int res) in assert (check 0 (of_nativeint 0n)); assert (check 32767 (of_nativeint 32767n)); assert (check (-32768) (of_nativeint 32768n)); assert (Nativeint.equal (to_nativeint one) 1n); assert (Nativeint.equal (to_nativeint minus_one) (-1n)); () let () = print_endline "Small signed int operations test: ✓" ocaml-integers-0.8.0/test/uint32conversions.ml000066400000000000000000000042201520254654400213630ustar00rootroot00000000000000(* * Copyright (c) 2021 Nomadic Labs * * This file is distributed under the terms of the MIT License. * See the file LICENSE for details. *) let () = print_endline "UInt32-Int32 conversion test: ?" (* Asserting that signed->unsigned conversion is trivial when within range *) let () = let check i32 = let s32 = Int32.to_string i32 in Unsigned.UInt32.(equal (of_int32 i32) (of_string s32)) in assert (check 0l); assert (check 1l); assert (check 23l); assert (check 112783646l); assert (check Int32.max_int) (* Asserting that unsinged->signed conversion is trivial when within range *) let () = let check u32 = let s32 = Unsigned.UInt32.to_string u32 in Int32.equal (Unsigned.UInt32.to_int32 u32) (Int32.of_string s32) in assert (check Unsigned.UInt32.zero); assert (check Unsigned.UInt32.one); assert (check (Unsigned.UInt32.of_string "23")); assert (check (Unsigned.UInt32.of_string "112783646")); assert (check (Unsigned.UInt32.of_string "2147483647")); () (* Asserting that signed->unsigned->signed roundtrips *) let () = assert Unsigned.UInt32.(to_int32 (of_int32 23l) = 23l); assert Unsigned.UInt32.(to_int32 (of_int32 0l) = 0l); assert Unsigned.UInt32.(to_int32 (of_int32 (-1l)) = -1l); assert Unsigned.UInt32.(to_int32 (of_int32 (-23l)) = -23l); assert Unsigned.UInt32.(to_int32 (of_int32 Int32.max_int) = Int32.max_int); assert Unsigned.UInt32.(to_int32 (of_int32 Int32.min_int) = Int32.min_int); () (* Asserting that unsigned->signed->unsigned roundtrips *) let () = assert Unsigned.UInt32.(equal (of_int32 (to_int32 (of_string "0"))) (of_string "0")); assert Unsigned.UInt32.(equal (of_int32 (to_int32 (of_string "23"))) (of_string "23")); assert Unsigned.UInt32.(equal (of_int32 (to_int32 (of_string "2147483647"))) (of_string "2147483647")); assert Unsigned.UInt32.(equal (of_int32 (to_int32 (of_string "2147483648"))) (of_string "2147483648")); assert Unsigned.UInt32.(equal (of_int32 (to_int32 (of_string "2147493648"))) (of_string "2147493648")); assert Unsigned.UInt32.(equal (of_int32 (to_int32 max_int)) max_int); () let () = print_endline "UInt32-Int32 conversion test: ✓" ocaml-integers-0.8.0/test/uint64conversions.ml000066400000000000000000000043251520254654400213760ustar00rootroot00000000000000(* * Copyright (c) 2021 Nomadic Labs * * This file is distributed under the terms of the MIT License. * See the file LICENSE for details. *) let () = print_endline "UInt64-Int64 conversion test: ?" (* Asserting that signed->unsigned conversion is trivial when within range *) let () = let check i64 = let s64 = Int64.to_string i64 in Unsigned.UInt64.(equal (of_int64 i64) (of_string s64)) in assert (check 0L); assert (check 1L); assert (check 23L); assert (check 709182743098L); assert (check Int64.max_int) (* Asserting that unsinged->signed conversion is trivial when within range *) let () = let check u64 = let s64 = Unsigned.UInt64.to_string u64 in Int64.equal (Unsigned.UInt64.to_int64 u64) (Int64.of_string s64) in assert (check Unsigned.UInt64.zero); assert (check Unsigned.UInt64.one); assert (check (Unsigned.UInt64.of_string "23")); assert (check (Unsigned.UInt64.of_string "709182743098")); assert (check (Unsigned.UInt64.of_string "9223372036854775807")); () (* Asserting that signed->unsigned->signed roundtrips *) let () = assert Unsigned.UInt64.(to_int64 (of_int64 23L) = 23L); assert Unsigned.UInt64.(to_int64 (of_int64 0L) = 0L); assert Unsigned.UInt64.(to_int64 (of_int64 (-1L)) = -1L); assert Unsigned.UInt64.(to_int64 (of_int64 (-23L)) = -23L); assert Unsigned.UInt64.(to_int64 (of_int64 Int64.max_int) = Int64.max_int); assert Unsigned.UInt64.(to_int64 (of_int64 Int64.min_int) = Int64.min_int); () (* Asserting that unsigned->signed->unsigned roundtrips *) let () = assert Unsigned.UInt64.(equal (of_int64 (to_int64 (of_string "0"))) (of_string "0")); assert Unsigned.UInt64.(equal (of_int64 (to_int64 (of_string "23"))) (of_string "23")); assert Unsigned.UInt64.(equal (of_int64 (to_int64 (of_string "9223372036854775807"))) (of_string "9223372036854775807")); assert Unsigned.UInt64.(equal (of_int64 (to_int64 (of_string "9223372036854775808"))) (of_string "9223372036854775808")); assert Unsigned.UInt64.(equal (of_int64 (to_int64 (of_string "9223372036954775808"))) (of_string "9223372036954775808")); assert Unsigned.UInt64.(equal (of_int64 (to_int64 max_int)) max_int); () let () = print_endline "UInt64-Int64 conversion test: ✓" ocaml-integers-0.8.0/top/000077500000000000000000000000001520254654400152415ustar00rootroot00000000000000ocaml-integers-0.8.0/top/dune000066400000000000000000000002241520254654400161150ustar00rootroot00000000000000(library (name integers_top) (public_name integers.top) (modes byte) (synopsis "toplevel pretty printers") (libraries integers compiler-libs)) ocaml-integers-0.8.0/top/install_integer_printers.ml000066400000000000000000000041341520254654400227060ustar00rootroot00000000000000(* Adapted from Anil Madhavapeddy's ocaml-uri package. *) let printers = [ "fun fmt v -> Format.fprintf fmt \"\" (Signed.SInt.to_string v)"; "fun fmt v -> Format.fprintf fmt \"\" (Signed.Long.to_string v)"; "fun fmt v -> Format.fprintf fmt \"\" (Signed.LLong.to_string v)"; "fun fmt v -> Format.fprintf fmt \"\" (Unsigned.UChar.to_string v)"; "fun fmt v -> Format.fprintf fmt \"\" (Unsigned.UInt8.to_string v)"; "fun fmt v -> Format.fprintf fmt \"\" (Unsigned.UInt16.to_string v)"; "fun fmt v -> Format.fprintf fmt \"\" (Unsigned.UInt32.to_string v)"; "fun fmt v -> Format.fprintf fmt \"\" (Unsigned.UInt64.to_string v)"; "fun fmt v -> Format.fprintf fmt \"\" (Unsigned.UShort.to_string v)"; "fun fmt v -> Format.fprintf fmt \"\" (Unsigned.UInt.to_string v)"; "fun fmt v -> Format.fprintf fmt \"\" (Unsigned.ULong.to_string v)"; "fun fmt v -> Format.fprintf fmt \"\" (Unsigned.ULLong.to_string v)";] let eval_string ?(print_outcome = false) ?(err_formatter = Format.err_formatter) str = let lexbuf = Lexing.from_string str in let phrase = !Toploop.parse_toplevel_phrase lexbuf in Toploop.execute_phrase print_outcome err_formatter phrase let install_printer printer = begin ignore (eval_string (Printf.sprintf "let _printer = %s;;" printer)); ignore (eval_string (Printf.sprintf "#install_printer _printer;;")); end let is_utop () = Hashtbl.mem Toploop.directive_table "utop_help" [@@ocaml.warning "-3"] let () = (* Preload the toplevel environment and integers library if we are in utop. This is done to ensure the required modules are in scope before the printers are installed, as dune will not do this automatically. *) if is_utop () then begin Toploop.initialize_toplevel_env (); ignore (eval_string "#require \"integers\";;"); end; List.iter install_printer printers