%--------------------------------------------------%
% vim: ts=4 sw=4 et ft=mercury
%--------------------------------------------------%
% Copyright (C) 1997-2000, 2003-2007, 2011-2012 The University of Melbourne.
% Copyright (C) 2014-2018 The Mercury team.
% This file is distributed under the terms specified in COPYING.LIB.
%--------------------------------------------------%
%
% File: integer.m.
% Main authors: aet, Dan Hazel <odin@svrc.uq.edu.au>.
% Stability: high.
%
% This module defines an arbitrary precision integer type (named "integer")
% and basic arithmetic operations on it.
%
% The builtin Mercury type "int" is implemented as machine integers,
% which on virtually all modern machines will be 32 or 64 bits in size.
% If you need to manipulate integers that may not fit into this many bits,
% you will want to use "integer"s instead of "int"s.
%
% NOTE: All the operators we define on "integers" behave the same as the
% corresponding operators on "int"s. This includes the operators related
% to division: /, //, rem, div, and mod.
%
%--------------------------------------------------%
%--------------------------------------------------%
:- module integer.
:- interface.
:- type integer.
%--------------------------------------------------%
%
% Constants.
%
% Equivalent to integer(-1).
%
:- func negative_one = integer.
% Equivalent to integer(0).
%
:- func zero = integer.
% Equivalent to integer(1).
%
:- func one = integer.
% Equivalent to integer(2).
%
:- func two = integer.
% Equivalent to integer(8).
%
:- func eight = integer.
% Equivalent to integer(10).
%
:- func ten = integer.
% Equivalent to integer(16).
%
:- func sixteen = integer.
%--------------------------------------------------%
% X < Y: Succeed if and only if X is less than Y.
%
:- pred '<'(integer::in, integer::in) is semidet.
% X > Y: Succeed if and only if X is greater than Y.
%
:- pred '>'(integer::in, integer::in) is semidet.
% X =< Y: Succeed if and only if X is less than or equal to Y.
%
:- pred '=<'(integer::in, integer::in) is semidet.
% X >= Y: Succeed if and only if X is greater than or equal to Y.
%
:- pred '>='(integer::in, integer::in) is semidet.
% Absolute value.
%
:- func abs(integer) = integer.
% True if the argument is equal to integer.zero.
%
:- pred is_zero(integer::in) is semidet.
%--------------------------------------------------%
% Unary plus.
%
:- func '+'(integer) = integer.
% Unary minus.
%
:- func '-'(integer) = integer.
% Addition.
%
:- func integer + integer = integer.
% Subtraction.
%
:- func integer - integer = integer.
% Multiplication.
%
:- func integer * integer = integer.
% Flooring integer division.
% Behaves as int.div.
%
:- func integer div integer = integer.
% Truncating integer division.
% Behaves as int.(//).
%
:- func integer // integer = integer.
% Modulus.
% Behaves as int.mod.
%
:- func integer mod integer = integer.
% Remainder.
% Behaves as int.rem.
%
:- func integer rem integer = integer.
% divide_with_rem(X, Y, Q, R) where Q = X // Y and R = X rem Y
% where both answers are calculated at the same time.
%
:- pred divide_with_rem(integer::in, integer::in,
integer::out, integer::out) is det.
% Exponentiation.
% pow(X, Y) = Z: Z is X raised to the Yth power.
% Throws a `domain_error' exception if Y is negative.
%
:- func pow(integer, integer) = integer.
%--------------------------------------------------%
% Left shift.
% Behaves as int.(<<).
%
:- func integer << int = integer.
% Right shift.
% Behaves as int.(>>).
%
:- func integer >> int = integer.
%--------------------------------------------------%
% Bitwise complement.
%
:- func \ integer = integer.
% Bitwise and.
%
:- func integer /\ integer = integer.
% Bitwise or.
%
:- func integer \/ integer = integer.
% Bitwise exclusive or (xor).
%
:- func integer `xor` integer = integer.
%--------------------------------------------------%
% Convert an integer to an int.
% Fails if the integer is not in the range [min_int, max_int].
%
:- pred to_int(integer::in, int::out) is semidet.
% As above, but throws an exception rather than failing.
%
:- func det_to_int(integer) = int.
%--------------------------------------------------%
% Convert an integer to a uint.
% Fails if the integer is not in the range [0, max_uint].
%
:- pred to_uint(integer::in, uint::out) is semidet.
% As above, but throws an exception rather than failing.
%
:- func det_to_uint(integer) = uint.
% Convert an integer to an int8.
% Fails if the integer is not in the range [-128, 127].
%
:- pred to_int8(integer::in, int8::out) is semidet.
% As above, but throws an exception rather than failing.
%
:- func det_to_int8(integer) = int8.
% Convert an integer to a uint8.
% Fails if the integer is not in the range [0, 255].
%
:- pred to_uint8(integer::in, uint8::out) is semidet.
% As above, but throws an exception rather than failing.
%
:- func det_to_uint8(integer) = uint8.
% Convert an integer to an int16.
% Fails if the integer is not in the range [-32768, 32767].
%
:- pred to_int16(integer::in, int16::out) is semidet.
% As above, but throws an exception rather than failing.
%
:- func det_to_int16(integer) = int16.
% Convert an integer to a uint16.
% Fails if the integer is not in the range [0, 65535].
%
:- pred to_uint16(integer::in, uint16::out) is semidet.
% As above, but throws an exception rather than failing.
%
:- func det_to_uint16(integer) = uint16.
% Convert an integer to an int32.
% Fails if the integer is not in the range [-2147483648, 2147483647].
%
:- pred to_int32(integer::in, int32::out) is semidet.
% As above, but throws an exception rather than failing.
%
:- func det_to_int32(integer) = int32.
% Convert an integer to a uint32.
% Fails if the integer is not in range [0, 4294967295].
%
:- pred to_uint32(integer::in, uint32::out) is semidet.
% As above, but throws an exception rather than failing.
%
:- func det_to_uint32(integer) = uint32.
% Convert an integer to an int64.
% Fails if the integer is not in the range
% [-9223372036854775808, 9223372036854775807].
%
:- pred to_int64(integer::in, int64::out) is semidet.
% As above, but throws an exception rather than failing.
%
:- func det_to_int64(integer) = int64.
% Convert an integer to a uint64.
% Fails if the integer is not in range [0, 18446744073709551615].
%
:- pred to_uint64(integer::in, uint64::out) is semidet.
% As above, but throws an exception rather than failing.
%
:- func det_to_uint64(integer) = uint64.
%--------------------------------------------------%
% Convert an integer to a float.
%
:- func float(integer) = float.
%--------------------------------------------------%
% Convert an integer to a string (in base 10).
%
:- func to_string(integer) = string.
% to_base_string(Integer, Base) = String:
%
% Convert an integer to a string in a given Base.
%
% Base must be between 2 and 36, both inclusive; if it is not,
% the predicate will throw an exception.
%
:- func to_base_string(integer, int) = string.
%--------------------------------------------------%
% Convert an int to integer.
%
:- func integer(int) = integer.
% Convert a uint to an integer.
%
:- func from_uint(uint) = integer.
% Convert an int8 to an integer.
%
:- func from_int8(int8) = integer.
% Convert a uint8 to an integer.
%
:- func from_uint8(uint8) = integer.
% Convert an int16 to an integer.
%
:- func from_int16(int16) = integer.
% Convert a uint16 to an integer.
%
:- func from_uint16(uint16) = integer.
% Convert an int32 to an integer.
%
:- func from_int32(int32) = integer.
% Convert a uint32 to an integer.
%
:- func from_uint32(uint32) = integer.
% Convert an int64 to an integer.
%
:- func from_int64(int64) = integer.
% Convert a uint64 to an integer.
%
:- func from_uint64(uint64) = integer.
% Convert a string to an integer. The string must contain only digits
% [0-9], optionally preceded by a plus or minus sign. If the string does
% not match this syntax, then the predicate fails.
%
:- pred from_string(string::in, integer::out) is semidet.
% As above, but throws an exception rather than failing.
%
:- func det_from_string(string) = integer.
% Convert a string in the specified base (2-36) to an integer.
% The string must contain one or more digits in the specified base,
% optionally preceded by a plus or minus sign. For bases > 10, digits
% 10 to 35 are represented by the letters A-Z or a-z. If the string
% does not match this syntax, then the predicate fails.
%
:- pred from_base_string(int::in, string::in, integer::out) is semidet.
% As above, but throws an exception rather than failing.
%
:- func det_from_base_string(int, string) = integer.
%--------------------------------------------------%
%--------------------------------------------------%