From 4f8d37b67ad197c511df19acc4a82a1f66fea87a Mon Sep 17 00:00:00 2001 From: Luc Blaeser <112870813+luc-blaeser@users.noreply.github.com> Date: Thu, 5 Jan 2023 16:48:13 +0100 Subject: [PATCH] Int8/16/32/64 documentation and unit tests (#475) Improve `Int8.mo`, `Int16.mo`, `Int32.mo`, and `Int64.mo`: * Documentation * Unit tests * Related to: https://github.com/dfinity/motoko-base/pull/473 Possible improvements for Int8/16/32/64 (https://github.com/dfinity/motoko-base/issues/476): * Minimum value and maximum value constants are missing. * `bitnot()` has a superfluous second argument: `bitnot(x, y)` should be `bitnot(x)`. * Inconsistent naming of functions, e.g. `bitrotLeft` (instead of `bitRotLeft`). * Inconsistent type of second argument in bit operations: `bitshiftLeft` uses `Int64` but `bittest` uses `Nat`. --- src/Int16.mo | 426 ++++++++- src/Int32.mo | 424 ++++++++- src/Int64.mo | 424 ++++++++- src/Int8.mo | 424 ++++++++- test/int16Test.mo | 2303 ++++++++++++++++++++++++++++++++++++++++++++ test/int32Test.mo | 2303 ++++++++++++++++++++++++++++++++++++++++++++ test/int64Test.mo | 2302 ++++++++++++++++++++++++++++++++++++++++++++ test/int8Test.mo | 2307 ++++++++++++++++++++++++++++++++++++++++++++- 8 files changed, 10787 insertions(+), 126 deletions(-) create mode 100644 test/int16Test.mo create mode 100644 test/int32Test.mo create mode 100644 test/int64Test.mo diff --git a/src/Int16.mo b/src/Int16.mo index dfc8b176..a0c7183f 100644 --- a/src/Int16.mo +++ b/src/Int16.mo @@ -1,157 +1,521 @@ -/// 16-bit signed integers with checked arithmetic +/// 16-bit signed integers with checked arithmetic. /// +/// Common 16-bit integer functions. /// Most operations are available as built-in operators (e.g. `1 + 1`). import Int "Int"; import Prim "mo:⛔"; module { - /// 16-bit signed integers + /// 16-bit signed integers. public type Int16 = Prim.Types.Int16; - /// Conversion. + /// Minimum 16-bit integer value, `-2 ** 15`. + public let minimumValue = -32_768 : Int16; + + /// Maximum 16-bit integer value, `+2 ** 15 - 1`. + public let maximumValue = 32_767 : Int16; + + /// Converts a 16-bit signed integer to a signed integer with infinite precision. + /// + /// Example: + /// ```motoko + /// import Int16 "mo:base/Int16"; + /// + /// Int16.toInt(12_345) // => 12_345 : Int + /// ``` public let toInt : Int16 -> Int = Prim.int16ToInt; - /// Conversion. Traps on overflow/underflow. + /// Converts a signed integer with infinite precision to a 16-bit signed integer. + /// + /// Traps on overflow/underflow. + /// + /// Example: + /// ```motoko + /// import Int16 "mo:base/Int16"; + /// + /// Int16.fromInt(12_345) // => +12_345 : Int16 + /// ``` public let fromInt : Int -> Int16 = Prim.intToInt16; - /// Conversion. Wraps on overflow/underflow. + /// Converts a signed integer with infinite precision to a 16-bit signed integer. + /// + /// Wraps on overflow/underflow. + /// + /// Example: + /// ```motoko + /// import Int16 "mo:base/Int16"; + /// + /// Int16.fromIntWrap(-12_345) // => -12_345 : Int + /// ``` public let fromIntWrap : Int -> Int16 = Prim.intToInt16Wrap; - /// Conversion. Wraps on overflow/underflow. + /// Converts an unsigned 16-bit integer to a signed 16-bit integer. + /// + /// Wraps on overflow/underflow. + /// + /// Example: + /// ```motoko + /// import Int16 "mo:base/Int16"; + /// + /// Int16.fromNat16(12_345) // => +12_345 : Int16 + /// ``` public let fromNat16 : Nat16 -> Int16 = Prim.nat16ToInt16; - /// Conversion. Wraps on overflow/underflow. + /// Converts a signed 16-bit integer to an unsigned 16-bit integer. + /// + /// Wraps on overflow/underflow. + /// + /// Example: + /// ```motoko + /// import Int16 "mo:base/Int16"; + /// + /// Int16.toNat16(-1) // => 65_535 : Nat16 // underflow + /// ``` public let toNat16 : Int16 -> Nat16 = Prim.int16ToNat16; /// Returns the Text representation of `x`. + /// Formats the integer in decimal representation without underscore separators for thousand figures. + /// + /// Example: + /// ```motoko + /// import Int16 "mo:base/Int16"; + /// + /// Int16.toText(-12345) // => "-12345" + /// ``` public func toText(x : Int16) : Text { Int.toText(toInt(x)) }; - /// Returns the absolute value of `x`. Traps when `x = -2^15`. + /// Returns the absolute value of `x`. + /// + /// Traps when `x == -2 ** 15` (the minimum `Int16` value). + /// + /// Example: + /// ```motoko + /// import Int16 "mo:base/Int16"; + /// + /// Int16.abs(-12345) // => +12_345 + /// ``` public func abs(x : Int16) : Int16 { fromInt(Int.abs(toInt(x))) }; /// Returns the minimum of `x` and `y`. + /// + /// Example: + /// ```motoko + /// import Int16 "mo:base/Int16"; + /// + /// Int16.min(+2, -3) // => -3 + /// ``` public func min(x : Int16, y : Int16) : Int16 { if (x < y) { x } else { y } }; /// Returns the maximum of `x` and `y`. + /// + /// Example: + /// ```motoko + /// import Int16 "mo:base/Int16"; + /// + /// Int16.max(+2, -3) // => +2 + /// ``` public func max(x : Int16, y : Int16) : Int16 { if (x < y) { y } else { x } }; /// Returns `x == y`. + /// + /// Example: + /// ```motoko + /// import Int16 "mo:base/Int16"; + /// + /// Int16.equal(123, 123) // => true + /// ``` public func equal(x : Int16, y : Int16) : Bool { x == y }; /// Returns `x != y`. + /// + /// Example: + /// ```motoko + /// import Int16 "mo:base/Int16"; + /// + /// Int16.notEqual(123, 123) // => false + /// ``` public func notEqual(x : Int16, y : Int16) : Bool { x != y }; /// Returns `x < y`. + /// + /// Example: + /// ```motoko + /// import Int16 "mo:base/Int16"; + /// + /// Int16.less(123, 1234) // => true + /// ``` public func less(x : Int16, y : Int16) : Bool { x < y }; /// Returns `x <= y`. + /// + /// Example: + /// ```motoko + /// import Int16 "mo:base/Int16"; + /// + /// Int16.lessOrEqual(123, 1234) // => true + /// ``` public func lessOrEqual(x : Int16, y : Int16) : Bool { x <= y }; /// Returns `x > y`. + /// + /// Example: + /// ```motoko + /// import Int16 "mo:base/Int16"; + /// + /// Int16.greater(1234, 123) // => true + /// ``` public func greater(x : Int16, y : Int16) : Bool { x > y }; /// Returns `x >= y`. + /// + /// Example: + /// ```motoko + /// import Int16 "mo:base/Int16"; + /// + /// Int16.greaterOrEqual(1234, 123) // => true + /// ``` public func greaterOrEqual(x : Int16, y : Int16) : Bool { x >= y }; /// Returns the order of `x` and `y`. + /// + /// Example: + /// ```motoko + /// import Int16 "mo:base/Int16"; + /// + /// Int16.compare(123, 1234) // => #less + /// ``` public func compare(x : Int16, y : Int16) : { #less; #equal; #greater } { if (x < y) { #less } else if (x == y) { #equal } else { #greater } }; - /// Returns the negation of `x`, `-x`. Traps on overflow. + /// Returns the negation of `x`, `-x`. + /// + /// Traps on overflow, i.e. for `neg(-2 ** 15)`. + /// + /// + /// Example: + /// ```motoko + /// import Int16 "mo:base/Int16"; + /// + /// Int16.neg(123) // => -123 + /// ``` public func neg(x : Int16) : Int16 { -x }; - /// Returns the sum of `x` and `y`, `x + y`. Traps on overflow. + /// Returns the sum of `x` and `y`, `x + y`. + /// + /// Traps on overflow/underflow. + /// + /// Example: + /// ```motoko + /// import Int16 "mo:base/Int16"; + /// + /// Int16.add(1234, 123) // => +1_357 + /// ``` public func add(x : Int16, y : Int16) : Int16 { x + y }; - /// Returns the difference of `x` and `y`, `x - y`. Traps on underflow. + /// Returns the difference of `x` and `y`, `x - y`. + /// + /// Traps on overflow/underflow. + /// + /// Example: + /// ```motoko + /// import Int16 "mo:base/Int16"; + /// + /// Int16.sub(1234, 123) // => +1_111 + /// ``` public func sub(x : Int16, y : Int16) : Int16 { x - y }; - /// Returns the product of `x` and `y`, `x * y`. Traps on overflow. + /// Returns the product of `x` and `y`, `x * y`. + /// + /// Traps on overflow/underflow. + /// + /// Example: + /// ```motoko + /// import Int16 "mo:base/Int16"; + /// + /// Int16.mul(123, 100) // => +12_300 + /// ``` public func mul(x : Int16, y : Int16) : Int16 { x * y }; - /// Returns the division of `x by y`, `x / y`. + /// Returns the signed integer division of `x` by `y`, `x / y`. + /// Rounds the quotient towards zero, which is the same as truncating the decimal places of the quotient. + /// /// Traps when `y` is zero. + /// + /// Example: + /// ```motoko + /// import Int16 "mo:base/Int16"; + /// + /// Int16.div(123, 10) // => +12 + /// ``` public func div(x : Int16, y : Int16) : Int16 { x / y }; - /// Returns the remainder of `x` divided by `y`, `x % y`. + /// Returns the remainder of the signed integer division of `x` by `y`, `x % y`, + /// which is defined as `x - x / y * y`. + /// /// Traps when `y` is zero. + /// + /// Example: + /// ```motoko + /// import Int16 "mo:base/Int16"; + /// + /// Int16.rem(123, 10) // => +3 + /// ``` public func rem(x : Int16, y : Int16) : Int16 { x % y }; - /// Returns `x` to the power of `y`, `x ** y`. Traps on overflow. + /// Returns `x` to the power of `y`, `x ** y`. + /// + /// Traps on overflow/underflow and when `y < 0 or y >= 16`. + /// + /// Example: + /// ```motoko + /// import Int16 "mo:base/Int16"; + /// + /// Int16.pow(2, 10) // => +1_024 + /// ``` public func pow(x : Int16, y : Int16) : Int16 { x ** y }; /// Returns the bitwise negation of `x`, `^x`. - public func bitnot(x : Int16, y : Int16) : Int16 { ^x }; - - /// Returns the bitwise and of `x` and `y`, `x & y`. + /// + /// Example: + /// ```motoko + /// import Int16 "mo:base/Int16"; + /// + /// Int16.bitnot(-256 /* 0xff00 */) // => +255 // 0xff + /// ``` + public func bitnot(x : Int16) : Int16 { ^x }; + + /// Returns the bitwise "and" of `x` and `y`, `x & y`. + /// + /// Example: + /// ```motoko + /// import Int16 "mo:base/Int16"; + /// + /// Int16.bitand(0x0fff, 0x00f0) // => +240 // 0xf0 + /// ``` public func bitand(x : Int16, y : Int16) : Int16 { x & y }; - /// Returns the bitwise or of `x` and `y`, `x \| y`. + /// Returns the bitwise "or" of `x` and `y`, `x | y`. + /// + /// Example: + /// ```motoko + /// import Int16 "mo:base/Int16"; + /// + /// Int16.bitor(0x0f0f, 0x00f0) // => +4_095 // 0x0fff + /// ``` public func bitor(x : Int16, y : Int16) : Int16 { x | y }; - /// Returns the bitwise exclusive or of `x` and `y`, `x ^ y`. + /// Returns the bitwise "exclusive or" of `x` and `y`, `x ^ y`. + /// + /// Example: + /// ```motoko + /// import Int16 "mo:base/Int16"; + /// + /// Int16.bitxor(0x0fff, 0x00f0) // => +3_855 // 0x0f0f + /// ``` public func bitxor(x : Int16, y : Int16) : Int16 { x ^ y }; - /// Returns the bitwise shift left of `x` by `y`, `x << y`. + /// Returns the bitwise left shift of `x` by `y`, `x << y`. + /// The right bits of the shift filled with zeros. + /// Left-overflowing bits, including the sign bit, are discarded. + /// + /// For `y >= 16`, the semantics is the same as for `bitshiftLeft(x, y % 16)`. + /// For `y < 0`, the semantics is the same as for `bitshiftLeft(x, y + y % 16)`. + /// + /// Example: + /// ```motoko + /// import Int16 "mo:base/Int16"; + /// + /// Int16.bitshiftLeft(1, 8) // => +256 // 0x100 equivalent to `2 ** 8`. + /// ``` public func bitshiftLeft(x : Int16, y : Int16) : Int16 { x << y }; - /// Returns the bitwise shift right of `x` by `y`, `x >> y`. + /// Returns the signed bitwise right shift of `x` by `y`, `x >> y`. + /// The sign bit is retained and the left side is filled with the sign bit. + /// Right-underflowing bits are discarded, i.e. not rotated to the left side. + /// + /// For `y >= 16`, the semantics is the same as for `bitshiftRight(x, y % 16)`. + /// For `y < 0`, the semantics is the same as for `bitshiftRight (x, y + y % 16)`. + /// + /// Example: + /// ```motoko + /// import Int16 "mo:base/Int16"; + /// + /// Int16.bitshiftRight(1024, 8) // => +4 // equivalent to `1024 / (2 ** 8)` + /// ``` public func bitshiftRight(x : Int16, y : Int16) : Int16 { x >> y }; - /// Returns the bitwise rotate left of `x` by `y`, `x <<> y`. + /// Returns the bitwise left rotatation of `x` by `y`, `x <<> y`. + /// Each left-overflowing bit is inserted again on the right side. + /// The sign bit is rotated like other bits, i.e. the rotation interprets the number as unsigned. + /// + /// Changes the direction of rotation for negative `y`. + /// For `y >= 16`, the semantics is the same as for `bitrotLeft(x, y % 16)`. + /// + /// Example: + /// ```motoko + /// import Int16 "mo:base/Int16"; + /// + /// Int16.bitrotLeft(0x2001, 4) // => +18 // 0x12. + /// ``` public func bitrotLeft(x : Int16, y : Int16) : Int16 { x <<> y }; - /// Returns the bitwise rotate right of `x` by `y`, `x <>> y`. + /// Returns the bitwise right rotation of `x` by `y`, `x <>> y`. + /// Each right-underflowing bit is inserted again on the right side. + /// The sign bit is rotated like other bits, i.e. the rotation interprets the number as unsigned. + /// + /// Changes the direction of rotation for negative `y`. + /// For `y >= 16`, the semantics is the same as for `bitrotRight(x, y % 16)`. + /// + /// Example: + /// ```motoko + /// import Int16 "mo:base/Int16"; + /// + /// Int16.bitrotRight(0x2010, 8) // => +4_128 // 0x01020. + /// ``` public func bitrotRight(x : Int16, y : Int16) : Int16 { x <>> y }; - /// Returns the value of bit `p mod 16` in `x`, `(x & 2^(p mod 16)) == 2^(p mod 16)`. + /// Returns the value of bit `p` in `x`, `x & 2**p == 2**p`. + /// If `p >= 16`, the semantics is the same as for `bittest(x, p % 16)`. + /// + /// Example: + /// ```motoko + /// import Int16 "mo:base/Int16"; + /// + /// Int16.bittest(128, 7) // => true + /// ``` public func bittest(x : Int16, p : Nat) : Bool { Prim.btstInt16(x, Prim.intToInt16(p)) }; - /// Returns the value of setting bit `p mod 16` in `x` to `1`. + /// Returns the value of setting bit `p` in `x` to `1`. + /// If `p >= 16`, the semantics is the same as for `bitset(x, p % 16)`. + /// + /// Example: + /// ```motoko + /// import Int16 "mo:base/Int16"; + /// + /// Int16.bitset(0, 7) // => +128 + /// ``` public func bitset(x : Int16, p : Nat) : Int16 { x | (1 << Prim.intToInt16(p)) }; - /// Returns the value of clearing bit `p mod 16` in `x` to `0`. + /// Returns the value of clearing bit `p` in `x` to `0`. + /// If `p >= 16`, the semantics is the same as for `bitclear(x, p % 16)`. + /// + /// Example: + /// ```motoko + /// import Int16 "mo:base/Int16"; + /// + /// Int16.bitclear(-1, 7) // => -129 + /// ``` public func bitclear(x : Int16, p : Nat) : Int16 { x & ^(1 << Prim.intToInt16(p)) }; - /// Returns the value of flipping bit `p mod 16` in `x`. + /// Returns the value of flipping bit `p` in `x`. + /// If `p >= 16`, the semantics is the same as for `bitclear(x, p % 16)`. + /// + /// Example: + /// ```motoko + /// import Int16 "mo:base/Int16"; + /// + /// Int16.bitflip(255, 7) // => +127 + /// ``` public func bitflip(x : Int16, p : Nat) : Int16 { x ^ (1 << Prim.intToInt16(p)) }; /// Returns the count of non-zero bits in `x`. + /// + /// Example: + /// ```motoko + /// import Int16 "mo:base/Int16"; + /// + /// Int16.bitcountNonZero(0xff) // => +8 + /// ``` public let bitcountNonZero : (x : Int16) -> Int16 = Prim.popcntInt16; /// Returns the count of leading zero bits in `x`. + /// + /// Example: + /// ```motoko + /// import Int16 "mo:base/Int16"; + /// + /// Int16.bitcountLeadingZero(0x80) // => +8 + /// ``` public let bitcountLeadingZero : (x : Int16) -> Int16 = Prim.clzInt16; /// Returns the count of trailing zero bits in `x`. + /// + /// Example: + /// ```motoko + /// import Int16 "mo:base/Int16"; + /// + /// Int16.bitcountTrailingZero(0x0100) // => +8 + /// ``` public let bitcountTrailingZero : (x : Int16) -> Int16 = Prim.ctzInt16; - /// Returns the sum of `x` and `y`, `x +% y`. Wraps on overflow. + /// Returns the sum of `x` and `y`, `x +% y`. + /// + /// Wraps on overflow/underflow. + /// + /// + /// Example: + /// ```motoko + /// import Int16 "mo:base/Int16"; + /// + /// Int16.addWrap(2 ** 14, 2 ** 14) // => -32_768 // overflow + /// ``` public func addWrap(x : Int16, y : Int16) : Int16 { x +% y }; - /// Returns the difference of `x` and `y`, `x -% y`. Wraps on underflow. + /// Returns the difference of `x` and `y`, `x -% y`. + /// + /// Wraps on overflow/underflow. + /// + /// + /// Example: + /// ```motoko + /// import Int16 "mo:base/Int16"; + /// + /// Int16.subWrap(-2 ** 15, 1) // => +32_767 // underflow + /// ``` public func subWrap(x : Int16, y : Int16) : Int16 { x -% y }; /// Returns the product of `x` and `y`, `x *% y`. Wraps on overflow. + /// + /// Wraps on overflow/underflow. + /// + /// + /// Example: + /// ```motoko + /// import Int16 "mo:base/Int16"; + /// + /// Int16.mulWrap(2 ** 8, 2 ** 8) // => 0 // overflow + /// ``` public func mulWrap(x : Int16, y : Int16) : Int16 { x *% y }; - /// Returns `x` to the power of `y`, `x **% y`. Wraps on overflow. Traps if `y < 0`. + /// Returns `x` to the power of `y`, `x **% y`. + /// + /// Wraps on overflow/underflow. + /// Traps if `y < 0 or y >= 16`. + /// + /// + /// Example: + /// ```motoko + /// import Int16 "mo:base/Int16"; + /// + /// Int16.powWrap(2, 15) // => -32_768 // overflow + /// ``` public func powWrap(x : Int16, y : Int16) : Int16 { x **% y } } diff --git a/src/Int32.mo b/src/Int32.mo index 7f5bd4f3..aa634fd7 100644 --- a/src/Int32.mo +++ b/src/Int32.mo @@ -1,5 +1,6 @@ -/// 32-bit signed integers with checked arithmetic +/// 32-bit signed integers with checked arithmetic. /// +/// Common 32-bit integer functions. /// Most operations are available as built-in operators (e.g. `1 + 1`). import Int "Int"; import Prim "mo:⛔"; @@ -9,150 +10,513 @@ module { /// 32-bit signed integers. public type Int32 = Prim.Types.Int32; - /// Conversion. + /// Minimum 32-bit integer value, `-2 ** 31`. + public let minimumValue = -2_147_483_648 : Int32; + + /// Maximum 32-bit integer value, `+2 ** 31 - 1`. + public let maximumValue = 2_147_483_647 : Int32; + + /// Converts a 32-bit signed integer to a signed integer with infinite precision. + /// + /// Example: + /// ```motoko + /// import Int32 "mo:base/Int32"; + /// + /// Int32.toInt(123_456) // => 123_456 : Int + /// ``` public let toInt : Int32 -> Int = Prim.int32ToInt; - /// Conversion. Traps on overflow/underflow. + /// Converts a signed integer with infinite precision to a 32-bit signed integer. + /// + /// Traps on overflow/underflow. + /// + /// Example: + /// ```motoko + /// import Int32 "mo:base/Int32"; + /// + /// Int32.fromInt(123_456) // => +123_456 : Int32 + /// ``` public let fromInt : Int -> Int32 = Prim.intToInt32; - /// Conversion. Wraps on overflow/underflow. + /// Converts a signed integer with infinite precision to a 32-bit signed integer. + /// + /// Wraps on overflow/underflow. + /// + /// Example: + /// ```motoko + /// import Int32 "mo:base/Int32"; + /// + /// Int32.fromIntWrap(-123_456) // => -123_456 : Int + /// ``` public let fromIntWrap : Int -> Int32 = Prim.intToInt32Wrap; - /// Conversion. Wraps on overflow/underflow. + /// Converts an unsigned 32-bit integer to a signed 32-bit integer. + /// + /// Wraps on overflow/underflow. + /// + /// Example: + /// ```motoko + /// import Int32 "mo:base/Int32"; + /// + /// Int32.fromNat32(123_456) // => +123_456 : Int32 + /// ``` public let fromNat32 : Nat32 -> Int32 = Prim.nat32ToInt32; - /// Conversion. Wraps on overflow/underflow. + /// Converts a signed 32-bit integer to an unsigned 32-bit integer. + /// + /// Wraps on overflow/underflow. + /// + /// Example: + /// ```motoko + /// import Int32 "mo:base/Int32"; + /// + /// Int32.toNat32(-1) // => 4_294_967_295 : Nat32 // underflow + /// ``` public let toNat32 : Int32 -> Nat32 = Prim.int32ToNat32; /// Returns the Text representation of `x`. + /// Formats the integer in decimal representation without underscore separators for thousand figures. + /// + /// Example: + /// ```motoko + /// import Int32 "mo:base/Int32"; + /// + /// Int32.toText(-123456) // => "-123456" + /// ``` public func toText(x : Int32) : Text { Int.toText(toInt(x)) }; - /// Returns the absolute value of `x`. Traps when `x = -2^31`. + /// Returns the absolute value of `x`. + /// + /// Traps when `x == -2 ** 31` (the minimum `Int32` value). + /// + /// Example: + /// ```motoko + /// import Int32 "mo:base/Int32"; + /// + /// Int32.abs(-123456) // => +123_456 + /// ``` public func abs(x : Int32) : Int32 { fromInt(Int.abs(toInt(x))) }; /// Returns the minimum of `x` and `y`. + /// + /// Example: + /// ```motoko + /// import Int32 "mo:base/Int32"; + /// + /// Int32.min(+2, -3) // => -3 + /// ``` public func min(x : Int32, y : Int32) : Int32 { if (x < y) { x } else { y } }; /// Returns the maximum of `x` and `y`. + /// + /// Example: + /// ```motoko + /// import Int32 "mo:base/Int32"; + /// + /// Int32.max(+2, -3) // => +2 + /// ``` public func max(x : Int32, y : Int32) : Int32 { if (x < y) { y } else { x } }; /// Returns `x == y`. + /// + /// Example: + /// ```motoko + /// import Int32 "mo:base/Int32"; + /// + /// Int32.equal(123, 123) // => true + /// ``` public func equal(x : Int32, y : Int32) : Bool { x == y }; /// Returns `x != y`. + /// + /// Example: + /// ```motoko + /// import Int32 "mo:base/Int32"; + /// + /// Int32.notEqual(123, 123) // => false + /// ``` public func notEqual(x : Int32, y : Int32) : Bool { x != y }; /// Returns `x < y`. + /// + /// Example: + /// ```motoko + /// import Int32 "mo:base/Int32"; + /// + /// Int32.less(123, 1234) // => true + /// ``` public func less(x : Int32, y : Int32) : Bool { x < y }; /// Returns `x <= y`. + /// + /// Example: + /// ```motoko + /// import Int32 "mo:base/Int32"; + /// + /// Int32.lessOrEqual(123, 1234) // => true + /// ``` public func lessOrEqual(x : Int32, y : Int32) : Bool { x <= y }; /// Returns `x > y`. + /// + /// Example: + /// ```motoko + /// import Int32 "mo:base/Int32"; + /// + /// Int32.greater(1234, 123) // => true + /// ``` public func greater(x : Int32, y : Int32) : Bool { x > y }; /// Returns `x >= y`. + /// + /// Example: + /// ```motoko + /// import Int32 "mo:base/Int32"; + /// + /// Int32.greaterOrEqual(1234, 123) // => true + /// ``` public func greaterOrEqual(x : Int32, y : Int32) : Bool { x >= y }; /// Returns the order of `x` and `y`. + /// + /// Example: + /// ```motoko + /// import Int32 "mo:base/Int32"; + /// + /// Int32.compare(123, 1234) // => #less + /// ``` public func compare(x : Int32, y : Int32) : { #less; #equal; #greater } { if (x < y) { #less } else if (x == y) { #equal } else { #greater } }; - /// Returns the negation of `x`, `-x`. Traps on overflow. + /// Returns the negation of `x`, `-x`. + /// + /// Traps on overflow, i.e. for `neg(-2 ** 31)`. + /// + /// + /// Example: + /// ```motoko + /// import Int32 "mo:base/Int32"; + /// + /// Int32.neg(123) // => -123 + /// ``` public func neg(x : Int32) : Int32 { -x }; - /// Returns the sum of `x` and `y`, `x + y`. Traps on overflow. + /// Returns the sum of `x` and `y`, `x + y`. + /// + /// Traps on overflow/underflow. + /// + /// Example: + /// ```motoko + /// import Int32 "mo:base/Int32"; + /// + /// Int32.add(1234, 123) // => +1_357 + /// ``` public func add(x : Int32, y : Int32) : Int32 { x + y }; - /// Returns the difference of `x` and `y`, `x - y`. Traps on underflow. + /// Returns the difference of `x` and `y`, `x - y`. + /// + /// Traps on overflow/underflow. + /// + /// Example: + /// ```motoko + /// import Int32 "mo:base/Int32"; + /// + /// Int32.sub(1234, 123) // => +1_111 + /// ``` public func sub(x : Int32, y : Int32) : Int32 { x - y }; - /// Returns the product of `x` and `y`, `x * y`. Traps on overflow. + /// Returns the product of `x` and `y`, `x * y`. + /// + /// Traps on overflow/underflow. + /// + /// Example: + /// ```motoko + /// import Int32 "mo:base/Int32"; + /// + /// Int32.mul(123, 100) // => +12_300 + /// ``` public func mul(x : Int32, y : Int32) : Int32 { x * y }; - /// Returns the division of `x by y`, `x / y`. + /// Returns the signed integer division of `x` by `y`, `x / y`. + /// Rounds the quotient towards zero, which is the same as truncating the decimal places of the quotient. + /// /// Traps when `y` is zero. + /// + /// Example: + /// ```motoko + /// import Int32 "mo:base/Int32"; + /// + /// Int32.div(123, 10) // => +12 + /// ``` public func div(x : Int32, y : Int32) : Int32 { x / y }; - /// Returns the remainder of `x` divided by `y`, `x % y`. + /// Returns the remainder of the signed integer division of `x` by `y`, `x % y`, + /// which is defined as `x - x / y * y`. + /// /// Traps when `y` is zero. + /// + /// Example: + /// ```motoko + /// import Int32 "mo:base/Int32"; + /// + /// Int32.rem(123, 10) // => +3 + /// ``` public func rem(x : Int32, y : Int32) : Int32 { x % y }; - /// Returns `x` to the power of `y`, `x ** y`. Traps on overflow. + /// Returns `x` to the power of `y`, `x ** y`. + /// + /// Traps on overflow/underflow and when `y < 0 or y >= 32`. + /// + /// Example: + /// ```motoko + /// import Int32 "mo:base/Int32"; + /// + /// Int32.pow(2, 10) // => +1_024 + /// ``` public func pow(x : Int32, y : Int32) : Int32 { x ** y }; /// Returns the bitwise negation of `x`, `^x`. - public func bitnot(x : Int32, y : Int32) : Int32 { ^x }; - - /// Returns the bitwise and of `x` and `y`, `x & y`. + /// + /// Example: + /// ```motoko + /// import Int32 "mo:base/Int32"; + /// + /// Int32.bitnot(-256 /* 0xffff_ff00 */) // => +255 // 0xff + /// ``` + public func bitnot(x : Int32) : Int32 { ^x }; + + /// Returns the bitwise "and" of `x` and `y`, `x & y`. + /// + /// Example: + /// ```motoko + /// import Int32 "mo:base/Int32"; + /// + /// Int32.bitand(0xffff, 0x00f0) // => +240 // 0xf0 + /// ``` public func bitand(x : Int32, y : Int32) : Int32 { x & y }; - /// Returns the bitwise or of `x` and `y`, `x \| y`. + /// Returns the bitwise "or" of `x` and `y`, `x | y`. + /// + /// Example: + /// ```motoko + /// import Int32 "mo:base/Int32"; + /// + /// Int32.bitor(0xffff, 0x00f0) // => +65_535 // 0xffff + /// ``` public func bitor(x : Int32, y : Int32) : Int32 { x | y }; - /// Returns the bitwise exclusive or of `x` and `y`, `x ^ y`. + /// Returns the bitwise "exclusive or" of `x` and `y`, `x ^ y`. + /// + /// Example: + /// ```motoko + /// import Int32 "mo:base/Int32"; + /// + /// Int32.bitxor(0xffff, 0x00f0) // => +65_295 // 0xff0f + /// ``` public func bitxor(x : Int32, y : Int32) : Int32 { x ^ y }; - /// Returns the bitwise shift left of `x` by `y`, `x << y`. + /// Returns the bitwise left shift of `x` by `y`, `x << y`. + /// The right bits of the shift filled with zeros. + /// Left-overflowing bits, including the sign bit, are discarded. + /// + /// For `y >= 32`, the semantics is the same as for `bitshiftLeft(x, y % 32)`. + /// For `y < 0`, the semantics is the same as for `bitshiftLeft(x, y + y % 32)`. + /// + /// Example: + /// ```motoko + /// import Int32 "mo:base/Int32"; + /// + /// Int32.bitshiftLeft(1, 8) // => +256 // 0x100 equivalent to `2 ** 8`. + /// ``` public func bitshiftLeft(x : Int32, y : Int32) : Int32 { x << y }; - /// Returns the bitwise shift right of `x` by `y`, `x >> y`. + /// Returns the signed bitwise right shift of `x` by `y`, `x >> y`. + /// The sign bit is retained and the left side is filled with the sign bit. + /// Right-underflowing bits are discarded, i.e. not rotated to the left side. + /// + /// For `y >= 32`, the semantics is the same as for `bitshiftRight(x, y % 32)`. + /// For `y < 0`, the semantics is the same as for `bitshiftRight (x, y + y % 32)`. + /// + /// Example: + /// ```motoko + /// import Int32 "mo:base/Int32"; + /// + /// Int32.bitshiftRight(1024, 8) // => +4 // equivalent to `1024 / (2 ** 8)` + /// ``` public func bitshiftRight(x : Int32, y : Int32) : Int32 { x >> y }; - /// Returns the bitwise rotate left of `x` by `y`, `x <<> y`. + /// Returns the bitwise left rotatation of `x` by `y`, `x <<> y`. + /// Each left-overflowing bit is inserted again on the right side. + /// The sign bit is rotated like other bits, i.e. the rotation interprets the number as unsigned. + /// + /// Changes the direction of rotation for negative `y`. + /// For `y >= 32`, the semantics is the same as for `bitrotLeft(x, y % 32)`. + /// + /// Example: + /// ```motoko + /// import Int32 "mo:base/Int32"; + /// + /// Int32.bitrotLeft(0x2000_0001, 4) // => +18 // 0x12. + /// ``` public func bitrotLeft(x : Int32, y : Int32) : Int32 { x <<> y }; - /// Returns the bitwise rotate right of `x` by `y`, `x <>> y`. + /// Returns the bitwise right rotation of `x` by `y`, `x <>> y`. + /// Each right-underflowing bit is inserted again on the right side. + /// The sign bit is rotated like other bits, i.e. the rotation interprets the number as unsigned. + /// + /// Changes the direction of rotation for negative `y`. + /// For `y >= 32`, the semantics is the same as for `bitrotRight(x, y % 32)`. + /// + /// Example: + /// ```motoko + /// import Int32 "mo:base/Int32"; + /// + /// Int32.bitrotRight(0x0002_0001, 8) // => +16_777_728 // 0x0100_0200. + /// ``` public func bitrotRight(x : Int32, y : Int32) : Int32 { x <>> y }; - /// Returns the value of bit `p mod 16` in `x`, `(x & 2^(p mod 16)) == 2^(p mod 16)`. + /// Returns the value of bit `p` in `x`, `x & 2**p == 2**p`. + /// If `p >= 32`, the semantics is the same as for `bittest(x, p % 32)`. + /// + /// Example: + /// ```motoko + /// import Int32 "mo:base/Int32"; + /// + /// Int32.bittest(128, 7) // => true + /// ``` public func bittest(x : Int32, p : Nat) : Bool { Prim.btstInt32(x, Prim.intToInt32(p)) }; - /// Returns the value of setting bit `p mod 16` in `x` to `1`. + /// Returns the value of setting bit `p` in `x` to `1`. + /// If `p >= 32`, the semantics is the same as for `bitset(x, p % 32)`. + /// + /// Example: + /// ```motoko + /// import Int32 "mo:base/Int32"; + /// + /// Int32.bitset(0, 7) // => +128 + /// ``` public func bitset(x : Int32, p : Nat) : Int32 { x | (1 << Prim.intToInt32(p)) }; - /// Returns the value of clearing bit `p mod 16` in `x` to `0`. + /// Returns the value of clearing bit `p` in `x` to `0`. + /// If `p >= 32`, the semantics is the same as for `bitclear(x, p % 32)`. + /// + /// Example: + /// ```motoko + /// import Int32 "mo:base/Int32"; + /// + /// Int32.bitclear(-1, 7) // => -129 + /// ``` public func bitclear(x : Int32, p : Nat) : Int32 { x & ^(1 << Prim.intToInt32(p)) }; - /// Returns the value of flipping bit `p mod 16` in `x`. + /// Returns the value of flipping bit `p` in `x`. + /// If `p >= 32`, the semantics is the same as for `bitclear(x, p % 32)`. + /// + /// Example: + /// ```motoko + /// import Int32 "mo:base/Int32"; + /// + /// Int32.bitflip(255, 7) // => +127 + /// ``` public func bitflip(x : Int32, p : Nat) : Int32 { x ^ (1 << Prim.intToInt32(p)) }; /// Returns the count of non-zero bits in `x`. + /// + /// Example: + /// ```motoko + /// import Int32 "mo:base/Int32"; + /// + /// Int32.bitcountNonZero(0xffff) // => +16 + /// ``` public let bitcountNonZero : (x : Int32) -> Int32 = Prim.popcntInt32; /// Returns the count of leading zero bits in `x`. + /// + /// Example: + /// ```motoko + /// import Int32 "mo:base/Int32"; + /// + /// Int32.bitcountLeadingZero(0x8000) // => +16 + /// ``` public let bitcountLeadingZero : (x : Int32) -> Int32 = Prim.clzInt32; /// Returns the count of trailing zero bits in `x`. + /// + /// Example: + /// ```motoko + /// import Int32 "mo:base/Int32"; + /// + /// Int32.bitcountTrailingZero(0x0201_0000) // => +16 + /// ``` public let bitcountTrailingZero : (x : Int32) -> Int32 = Prim.ctzInt32; - /// Returns the sum of `x` and `y`, `x +% y`. Wraps on overflow. + /// Returns the sum of `x` and `y`, `x +% y`. + /// + /// Wraps on overflow/underflow. + /// + /// + /// Example: + /// ```motoko + /// import Int32 "mo:base/Int32"; + /// + /// Int32.addWrap(2 ** 30, 2 ** 30) // => -2_147_483_648 // overflow + /// ``` public func addWrap(x : Int32, y : Int32) : Int32 { x +% y }; - /// Returns the difference of `x` and `y`, `x -% y`. Wraps on underflow. + /// Returns the difference of `x` and `y`, `x -% y`. + /// + /// Wraps on overflow/underflow. + /// + /// + /// Example: + /// ```motoko + /// import Int32 "mo:base/Int32"; + /// + /// Int32.subWrap(-2 ** 31, 1) // => +2_147_483_647 // underflow + /// ``` public func subWrap(x : Int32, y : Int32) : Int32 { x -% y }; /// Returns the product of `x` and `y`, `x *% y`. Wraps on overflow. + /// + /// Wraps on overflow/underflow. + /// + /// + /// Example: + /// ```motoko + /// import Int32 "mo:base/Int32"; + /// + /// Int32.mulWrap(2 ** 16, 2 ** 16) // => 0 // overflow + /// ``` public func mulWrap(x : Int32, y : Int32) : Int32 { x *% y }; - /// Returns `x` to the power of `y`, `x **% y`. Wraps on overflow. Traps if `y < 0`. + /// Returns `x` to the power of `y`, `x **% y`. + /// + /// Wraps on overflow/underflow. + /// Traps if `y < 0 or y >= 32`. + /// + /// + /// Example: + /// ```motoko + /// import Int32 "mo:base/Int32"; + /// + /// Int32.powWrap(2, 31) // => -2_147_483_648 // overflow + /// ``` public func powWrap(x : Int32, y : Int32) : Int32 { x **% y }; } diff --git a/src/Int64.mo b/src/Int64.mo index d4739abe..386fa957 100644 --- a/src/Int64.mo +++ b/src/Int64.mo @@ -1,5 +1,6 @@ -/// 64-bit signed integers with checked arithmetic +/// 64-bit signed integers with checked arithmetic. /// +/// Common 64-bit integer functions. /// Most operations are available as built-in operators (e.g. `1 + 1`). import Int "Int"; import Prim "mo:⛔"; @@ -9,150 +10,513 @@ module { /// 64-bit signed integers. public type Int64 = Prim.Types.Int64; - /// Conversion. + /// Minimum 64-bit integer value, `-2 ** 63`. + public let minimumValue = -9_223_372_036_854_775_808 : Int64; + + /// Maximum 64-bit integer value, `+2 ** 63 - 1`. + public let maximumValue = 9_223_372_036_854_775_807 : Int64; + + /// Converts a 64-bit signed integer to a signed integer with infinite precision. + /// + /// Example: + /// ```motoko + /// import Int64 "mo:base/Int64"; + /// + /// Int64.toInt(123_456) // => 123_456 : Int + /// ``` public let toInt : Int64 -> Int = Prim.int64ToInt; - /// Conversion. Traps on overflow/underflow. + /// Converts a signed integer with infinite precision to a 64-bit signed integer. + /// + /// Traps on overflow/underflow. + /// + /// Example: + /// ```motoko + /// import Int64 "mo:base/Int64"; + /// + /// Int64.fromInt(123_456) // => +123_456 : Int64 + /// ``` public let fromInt : Int -> Int64 = Prim.intToInt64; - /// Conversion. Wraps on overflow/underflow. + /// Converts a signed integer with infinite precision to a 64-bit signed integer. + /// + /// Wraps on overflow/underflow. + /// + /// Example: + /// ```motoko + /// import Int64 "mo:base/Int64"; + /// + /// Int64.fromIntWrap(-123_456) // => -123_456 : Int64 + /// ``` public let fromIntWrap : Int -> Int64 = Prim.intToInt64Wrap; - /// Conversion. Wraps on overflow/underflow. + /// Converts an unsigned 64-bit integer to a signed 64-bit integer. + /// + /// Wraps on overflow/underflow. + /// + /// Example: + /// ```motoko + /// import Int64 "mo:base/Int64"; + /// + /// Int64.fromNat64(123_456) // => +123_456 : Int64 + /// ``` public let fromNat64 : Nat64 -> Int64 = Prim.nat64ToInt64; - /// Conversion. Wraps on overflow/underflow. + /// Converts a signed 64-bit integer to an unsigned 64-bit integer. + /// + /// Wraps on overflow/underflow. + /// + /// Example: + /// ```motoko + /// import Int64 "mo:base/Int64"; + /// + /// Int64.toNat64(-1) // => 18_446_744_073_709_551_615 : Nat64 // underflow + /// ``` public let toNat64 : Int64 -> Nat64 = Prim.int64ToNat64; /// Returns the Text representation of `x`. + /// Formats the integer in decimal representation without underscore separators for thousand figures. + /// + /// Example: + /// ```motoko + /// import Int64 "mo:base/Int64"; + /// + /// Int64.toText(-123456) // => "-123456" + /// ``` public func toText(x : Int64) : Text { Int.toText(toInt(x)) }; - /// Returns the absolute value of `x`. Traps when `x = -2^63`. + /// Returns the absolute value of `x`. + /// + /// Traps when `x == -2 ** 63` (the minimum `Int64` value). + /// + /// Example: + /// ```motoko + /// import Int64 "mo:base/Int64"; + /// + /// Int64.abs(-123456) // => +123_456 + /// ``` public func abs(x : Int64) : Int64 { fromInt(Int.abs(toInt(x))) }; /// Returns the minimum of `x` and `y`. + /// + /// Example: + /// ```motoko + /// import Int64 "mo:base/Int64"; + /// + /// Int64.min(+2, -3) // => -3 + /// ``` public func min(x : Int64, y : Int64) : Int64 { if (x < y) { x } else { y } }; /// Returns the maximum of `x` and `y`. + /// + /// Example: + /// ```motoko + /// import Int64 "mo:base/Int64"; + /// + /// Int64.max(+2, -3) // => +2 + /// ``` public func max(x : Int64, y : Int64) : Int64 { if (x < y) { y } else { x } }; /// Returns `x == y`. + /// + /// Example: + /// ```motoko + /// import Int64 "mo:base/Int64"; + /// + /// Int64.equal(123, 123) // => true + /// ``` public func equal(x : Int64, y : Int64) : Bool { x == y }; /// Returns `x != y`. + /// + /// Example: + /// ```motoko + /// import Int64 "mo:base/Int64"; + /// + /// Int64.notEqual(123, 123) // => false + /// ``` public func notEqual(x : Int64, y : Int64) : Bool { x != y }; /// Returns `x < y`. + /// + /// Example: + /// ```motoko + /// import Int64 "mo:base/Int64"; + /// + /// Int64.less(123, 1234) // => true + /// ``` public func less(x : Int64, y : Int64) : Bool { x < y }; /// Returns `x <= y`. + /// + /// Example: + /// ```motoko + /// import Int64 "mo:base/Int64"; + /// + /// Int64.lessOrEqual(123, 1234) // => true + /// ``` public func lessOrEqual(x : Int64, y : Int64) : Bool { x <= y }; /// Returns `x > y`. + /// + /// Example: + /// ```motoko + /// import Int64 "mo:base/Int64"; + /// + /// Int64.greater(1234, 123) // => true + /// ``` public func greater(x : Int64, y : Int64) : Bool { x > y }; /// Returns `x >= y`. + /// + /// Example: + /// ```motoko + /// import Int64 "mo:base/Int64"; + /// + /// Int64.greaterOrEqual(1234, 123) // => true + /// ``` public func greaterOrEqual(x : Int64, y : Int64) : Bool { x >= y }; /// Returns the order of `x` and `y`. + /// + /// Example: + /// ```motoko + /// import Int64 "mo:base/Int64"; + /// + /// Int64.compare(123, 1234) // => #less + /// ``` public func compare(x : Int64, y : Int64) : { #less; #equal; #greater } { if (x < y) { #less } else if (x == y) { #equal } else { #greater } }; - /// Returns the negation of `x`, `-x`. Traps on overflow. + /// Returns the negation of `x`, `-x`. + /// + /// Traps on overflow, i.e. for `neg(-2 ** 63)`. + /// + /// + /// Example: + /// ```motoko + /// import Int64 "mo:base/Int64"; + /// + /// Int64.neg(123) // => -123 + /// ``` public func neg(x : Int64) : Int64 { -x }; - /// Returns the sum of `x` and `y`, `x + y`. Traps on overflow. + /// Returns the sum of `x` and `y`, `x + y`. + /// + /// Traps on overflow/underflow. + /// + /// Example: + /// ```motoko + /// import Int64 "mo:base/Int64"; + /// + /// Int64.add(1234, 123) // => +1_357 + /// ``` public func add(x : Int64, y : Int64) : Int64 { x + y }; - /// Returns the difference of `x` and `y`, `x - y`. Traps on underflow. + /// Returns the difference of `x` and `y`, `x - y`. + /// + /// Traps on overflow/underflow. + /// + /// Example: + /// ```motoko + /// import Int64 "mo:base/Int64"; + /// + /// Int64.sub(1234, 123) // => +1_111 + /// ``` public func sub(x : Int64, y : Int64) : Int64 { x - y }; - /// Returns the product of `x` and `y`, `x * y`. Traps on overflow. + /// Returns the product of `x` and `y`, `x * y`. + /// + /// Traps on overflow/underflow. + /// + /// Example: + /// ```motoko + /// import Int64 "mo:base/Int64"; + /// + /// Int64.mul(123, 100) // => +12_300 + /// ``` public func mul(x : Int64, y : Int64) : Int64 { x * y }; - /// Returns the division of `x by y`, `x / y`. + /// Returns the signed integer division of `x` by `y`, `x / y`. + /// Rounds the quotient towards zero, which is the same as truncating the decimal places of the quotient. + /// /// Traps when `y` is zero. + /// + /// Example: + /// ```motoko + /// import Int64 "mo:base/Int64"; + /// + /// Int64.div(123, 10) // => +12 + /// ``` public func div(x : Int64, y : Int64) : Int64 { x / y }; - /// Returns the remainder of `x` divided by `y`, `x % y`. + /// Returns the remainder of the signed integer division of `x` by `y`, `x % y`, + /// which is defined as `x - x / y * y`. + /// /// Traps when `y` is zero. + /// + /// Example: + /// ```motoko + /// import Int64 "mo:base/Int64"; + /// + /// Int64.rem(123, 10) // => +3 + /// ``` public func rem(x : Int64, y : Int64) : Int64 { x % y }; - /// Returns `x` to the power of `y`, `x ** y`. Traps on overflow. + /// Returns `x` to the power of `y`, `x ** y`. + /// + /// Traps on overflow/underflow and when `y < 0 or y >= 64`. + /// + /// Example: + /// ```motoko + /// import Int64 "mo:base/Int64"; + /// + /// Int64.pow(2, 10) // => +1_024 + /// ``` public func pow(x : Int64, y : Int64) : Int64 { x ** y }; /// Returns the bitwise negation of `x`, `^x`. - public func bitnot(x : Int64, y : Int64) : Int64 { ^x }; - - /// Returns the bitwise and of `x` and `y`, `x & y`. + /// + /// Example: + /// ```motoko + /// import Int64 "mo:base/Int64"; + /// + /// Int64.bitnot(-256 /* 0xffff_ffff_ffff_ff00 */) // => +255 // 0xff + /// ``` + public func bitnot(x : Int64) : Int64 { ^x }; + + /// Returns the bitwise "and" of `x` and `y`, `x & y`. + /// + /// Example: + /// ```motoko + /// import Int64 "mo:base/Int64"; + /// + /// Int64.bitand(0xffff, 0x00f0) // => +240 // 0xf0 + /// ``` public func bitand(x : Int64, y : Int64) : Int64 { x & y }; - /// Returns the bitwise or of `x` and `y`, `x \| y`. + /// Returns the bitwise "or" of `x` and `y`, `x | y`. + /// + /// Example: + /// ```motoko + /// import Int64 "mo:base/Int64"; + /// + /// Int64.bitor(0xffff, 0x00f0) // => +65_535 // 0xffff + /// ``` public func bitor(x : Int64, y : Int64) : Int64 { x | y }; - /// Returns the bitwise exclusive or of `x` and `y`, `x ^ y`. + /// Returns the bitwise "exclusive or" of `x` and `y`, `x ^ y`. + /// + /// Example: + /// ```motoko + /// import Int64 "mo:base/Int64"; + /// + /// Int64.bitxor(0xffff, 0x00f0) // => +65_295 // 0xff0f + /// ``` public func bitxor(x : Int64, y : Int64) : Int64 { x ^ y }; - /// Returns the bitwise shift left of `x` by `y`, `x << y`. + /// Returns the bitwise left shift of `x` by `y`, `x << y`. + /// The right bits of the shift filled with zeros. + /// Left-overflowing bits, including the sign bit, are discarded. + /// + /// For `y >= 64`, the semantics is the same as for `bitshiftLeft(x, y % 64)`. + /// For `y < 0`, the semantics is the same as for `bitshiftLeft(x, y + y % 64)`. + /// + /// Example: + /// ```motoko + /// import Int64 "mo:base/Int64"; + /// + /// Int64.bitshiftLeft(1, 8) // => +256 // 0x100 equivalent to `2 ** 8`. + /// ``` public func bitshiftLeft(x : Int64, y : Int64) : Int64 { x << y }; - /// Returns the bitwise shift right of `x` by `y`, `x >> y`. + /// Returns the signed bitwise right shift of `x` by `y`, `x >> y`. + /// The sign bit is retained and the left side is filled with the sign bit. + /// Right-underflowing bits are discarded, i.e. not rotated to the left side. + /// + /// For `y >= 64`, the semantics is the same as for `bitshiftRight(x, y % 64)`. + /// For `y < 0`, the semantics is the same as for `bitshiftRight (x, y + y % 64)`. + /// + /// Example: + /// ```motoko + /// import Int64 "mo:base/Int64"; + /// + /// Int64.bitshiftRight(1024, 8) // => +4 // equivalent to `1024 / (2 ** 8)` + /// ``` public func bitshiftRight(x : Int64, y : Int64) : Int64 { x >> y }; - /// Returns the bitwise rotate left of `x` by `y`, `x <<> y`. + /// Returns the bitwise left rotatation of `x` by `y`, `x <<> y`. + /// Each left-overflowing bit is inserted again on the right side. + /// The sign bit is rotated like other bits, i.e. the rotation interprets the number as unsigned. + /// + /// Changes the direction of rotation for negative `y`. + /// For `y >= 64`, the semantics is the same as for `bitrotLeft(x, y % 64)`. + /// + /// Example: + /// ```motoko + /// import Int64 "mo:base/Int64"; + /// + /// Int64.bitrotLeft(0x2000_0000_0000_0001, 4) // => +18 // 0x12. + /// ``` public func bitrotLeft(x : Int64, y : Int64) : Int64 { x <<> y }; - /// Returns the bitwise rotate right of `x` by `y`, `x <>> y`. + /// Returns the bitwise right rotation of `x` by `y`, `x <>> y`. + /// Each right-underflowing bit is inserted again on the right side. + /// The sign bit is rotated like other bits, i.e. the rotation interprets the number as unsigned. + /// + /// Changes the direction of rotation for negative `y`. + /// For `y >= 64`, the semantics is the same as for `bitrotRight(x, y % 64)`. + /// + /// Example: + /// ```motoko + /// import Int64 "mo:base/Int64"; + /// + /// Int64.bitrotRight(0x0002_0000_0000_0001, 48) // => +65538 // 0x1_0002. + /// ``` public func bitrotRight(x : Int64, y : Int64) : Int64 { x <>> y }; - /// Returns the value of bit `p mod 64` in `x`, `(x & 2^(p mod 64)) == 2^(p mod 64)`. + /// Returns the value of bit `p` in `x`, `x & 2**p == 2**p`. + /// If `p >= 64`, the semantics is the same as for `bittest(x, p % 64)`. + /// + /// Example: + /// ```motoko + /// import Int64 "mo:base/Int64"; + /// + /// Int64.bittest(128, 7) // => true + /// ``` public func bittest(x : Int64, p : Nat) : Bool { Prim.btstInt64(x, Prim.intToInt64(p)) }; - /// Returns the value of setting bit `p mod 64` in `x` to `1`. + /// Returns the value of setting bit `p` in `x` to `1`. + /// If `p >= 64`, the semantics is the same as for `bitset(x, p % 64)`. + /// + /// Example: + /// ```motoko + /// import Int64 "mo:base/Int64"; + /// + /// Int64.bitset(0, 7) // => +128 + /// ``` public func bitset(x : Int64, p : Nat) : Int64 { x | (1 << Prim.intToInt64(p)) }; - /// Returns the value of clearing bit `p mod 64` in `x` to `0`. + /// Returns the value of clearing bit `p` in `x` to `0`. + /// If `p >= 64`, the semantics is the same as for `bitclear(x, p % 64)`. + /// + /// Example: + /// ```motoko + /// import Int64 "mo:base/Int64"; + /// + /// Int64.bitclear(-1, 7) // => -129 + /// ``` public func bitclear(x : Int64, p : Nat) : Int64 { x & ^(1 << Prim.intToInt64(p)) }; - /// Returns the value of flipping bit `p mod 64` in `x`. + /// Returns the value of flipping bit `p` in `x`. + /// If `p >= 64`, the semantics is the same as for `bitclear(x, p % 64)`. + /// + /// Example: + /// ```motoko + /// import Int64 "mo:base/Int64"; + /// + /// Int64.bitflip(255, 7) // => +127 + /// ``` public func bitflip(x : Int64, p : Nat) : Int64 { x ^ (1 << Prim.intToInt64(p)) }; /// Returns the count of non-zero bits in `x`. + /// + /// Example: + /// ```motoko + /// import Int64 "mo:base/Int64"; + /// + /// Int64.bitcountNonZero(0xffff) // => +16 + /// ``` public let bitcountNonZero : (x : Int64) -> Int64 = Prim.popcntInt64; /// Returns the count of leading zero bits in `x`. + /// + /// Example: + /// ```motoko + /// import Int64 "mo:base/Int64"; + /// + /// Int64.bitcountLeadingZero(0x8000_0000) // => +32 + /// ``` public let bitcountLeadingZero : (x : Int64) -> Int64 = Prim.clzInt64; /// Returns the count of trailing zero bits in `x`. + /// + /// Example: + /// ```motoko + /// import Int64 "mo:base/Int64"; + /// + /// Int64.bitcountTrailingZero(0x0201_0000) // => +16 + /// ``` public let bitcountTrailingZero : (x : Int64) -> Int64 = Prim.ctzInt64; - /// Returns the sum of `x` and `y`, `x +% y`. Wraps on overflow. + /// Returns the sum of `x` and `y`, `x +% y`. + /// + /// Wraps on overflow/underflow. + /// + /// + /// Example: + /// ```motoko + /// import Int64 "mo:base/Int64"; + /// + /// Int64.addWrap(2 ** 62, 2 ** 62) // => -9_223_372_036_854_775_808 // overflow + /// ``` public func addWrap(x : Int64, y : Int64) : Int64 { x +% y }; - /// Returns the difference of `x` and `y`, `x -% y`. Wraps on underflow. + /// Returns the difference of `x` and `y`, `x -% y`. + /// + /// Wraps on overflow/underflow. + /// + /// + /// Example: + /// ```motoko + /// import Int64 "mo:base/Int64"; + /// + /// Int64.subWrap(-2 ** 63, 1) // => +9_223_372_036_854_775_807 // underflow + /// ``` public func subWrap(x : Int64, y : Int64) : Int64 { x -% y }; /// Returns the product of `x` and `y`, `x *% y`. Wraps on overflow. + /// + /// Wraps on overflow/underflow. + /// + /// + /// Example: + /// ```motoko + /// import Int64 "mo:base/Int64"; + /// + /// Int64.mulWrap(2 ** 32, 2 ** 32) // => 0 // overflow + /// ``` public func mulWrap(x : Int64, y : Int64) : Int64 { x *% y }; - /// Returns `x` to the power of `y`, `x **% y`. Wraps on overflow. Traps if `y < 0`. + /// Returns `x` to the power of `y`, `x **% y`. + /// + /// Wraps on overflow/underflow. + /// Traps if `y < 0 or y >= 64`. + /// + /// + /// Example: + /// ```motoko + /// import Int64 "mo:base/Int64"; + /// + /// Int64.powWrap(2, 63) // => -9_223_372_036_854_775_808 // overflow + /// ``` public func powWrap(x : Int64, y : Int64) : Int64 { x **% y }; } diff --git a/src/Int8.mo b/src/Int8.mo index a2e81f5b..4f7a2857 100644 --- a/src/Int8.mo +++ b/src/Int8.mo @@ -1,5 +1,6 @@ -/// 8-bit signed integers with checked arithmetic +/// 8-bit signed integers with checked arithmetic. /// +/// Common 8-bit integer functions. /// Most operations are available as built-in operators (e.g. `1 + 1`). import Int "Int"; import Prim "mo:⛔"; @@ -9,150 +10,513 @@ module { /// 8-bit signed integers. public type Int8 = Prim.Types.Int8; - /// Conversion. + /// Minimum 8-bit integer value, `-2 ** 7`. + public let minimumValue = -128 : Int8; + + /// Maximum 8-bit integer value, `+2 ** 7 - 1`. + public let maximumValue = 127 : Int8; + + /// Converts a 8-bit signed integer to a signed integer with infinite precision. + /// + /// Example: + /// ```motoko + /// import Int8 "mo:base/Int8"; + /// + /// Int8.toInt(123) // => 123 : Int + /// ``` public let toInt : Int8 -> Int = Prim.int8ToInt; - /// Conversion. Traps on overflow/underflow. + /// Converts a signed integer with infinite precision to a 8-bit signed integer. + /// + /// Traps on overflow/underflow. + /// + /// Example: + /// ```motoko + /// import Int8 "mo:base/Int8"; + /// + /// Int8.fromInt(123) // => +123 : Int8 + /// ``` public let fromInt : Int -> Int8 = Prim.intToInt8; - /// Conversion. Wraps on overflow/underflow. + /// Converts a signed integer with infinite precision to a 8-bit signed integer. + /// + /// Wraps on overflow/underflow. + /// + /// Example: + /// ```motoko + /// import Int8 "mo:base/Int8"; + /// + /// Int8.fromIntWrap(-123) // => -123 : Int + /// ``` public let fromIntWrap : Int -> Int8 = Prim.intToInt8Wrap; - /// Conversion. Wraps on overflow/underflow. + /// Converts an unsigned 8-bit integer to a signed 8-bit integer. + /// + /// Wraps on overflow/underflow. + /// + /// Example: + /// ```motoko + /// import Int8 "mo:base/Int8"; + /// + /// Int8.fromNat8(123) // => +123 : Int8 + /// ``` public let fromNat8 : Nat8 -> Int8 = Prim.nat8ToInt8; - /// Conversion. Wraps on overflow/underflow. + /// Converts a signed 8-bit integer to an unsigned 8-bit integer. + /// + /// Wraps on overflow/underflow. + /// + /// Example: + /// ```motoko + /// import Int8 "mo:base/Int8"; + /// + /// Int8.toNat8(-1) // => 255 : Nat8 // underflow + /// ``` public let toNat8 : Int8 -> Nat8 = Prim.int8ToNat8; /// Returns the Text representation of `x`. + /// Formats the integer in decimal representation. + /// + /// Example: + /// ```motoko + /// import Int8 "mo:base/Int8"; + /// + /// Int8.toText(-123) // => "-123" + /// ``` public func toText(x : Int8) : Text { Int.toText(toInt(x)) }; - /// Returns the absolute value of `x`. Traps when `x = -2^7`. + /// Returns the absolute value of `x`. + /// + /// Traps when `x == -2 ** 7` (the minimum `Int8` value). + /// + /// Example: + /// ```motoko + /// import Int8 "mo:base/Int8"; + /// + /// Int8.abs(-123) // => +123 + /// ``` public func abs(x : Int8) : Int8 { fromInt(Int.abs(toInt(x))) }; /// Returns the minimum of `x` and `y`. + /// + /// Example: + /// ```motoko + /// import Int8 "mo:base/Int8"; + /// + /// Int8.min(+2, -3) // => -3 + /// ``` public func min(x : Int8, y : Int8) : Int8 { if (x < y) { x } else { y } }; /// Returns the maximum of `x` and `y`. + /// + /// Example: + /// ```motoko + /// import Int8 "mo:base/Int8"; + /// + /// Int8.max(+2, -3) // => +2 + /// ``` public func max(x : Int8, y : Int8) : Int8 { if (x < y) { y } else { x } }; /// Returns `x == y`. + /// + /// Example: + /// ```motoko + /// import Int8 "mo:base/Int8"; + /// + /// Int8.equal(123, 123) // => true + /// ``` public func equal(x : Int8, y : Int8) : Bool { x == y }; /// Returns `x != y`. + /// + /// Example: + /// ```motoko + /// import Int8 "mo:base/Int8"; + /// + /// Int8.notEqual(123, 123) // => false + /// ``` public func notEqual(x : Int8, y : Int8) : Bool { x != y }; /// Returns `x < y`. + /// + /// Example: + /// ```motoko + /// import Int8 "mo:base/Int8"; + /// + /// Int8.less(123, 124) // => true + /// ``` public func less(x : Int8, y : Int8) : Bool { x < y }; /// Returns `x <= y`. + /// + /// Example: + /// ```motoko + /// import Int8 "mo:base/Int8"; + /// + /// Int8.lessOrEqual(123, 124) // => true + /// ``` public func lessOrEqual(x : Int8, y : Int8) : Bool { x <= y }; /// Returns `x > y`. + /// + /// Example: + /// ```motoko + /// import Int8 "mo:base/Int8"; + /// + /// Int8.greater(124, 123) // => true + /// ``` public func greater(x : Int8, y : Int8) : Bool { x > y }; /// Returns `x >= y`. + /// + /// Example: + /// ```motoko + /// import Int8 "mo:base/Int8"; + /// + /// Int8.greaterOrEqual(124, 123) // => true + /// ``` public func greaterOrEqual(x : Int8, y : Int8) : Bool { x >= y }; /// Returns the order of `x` and `y`. + /// + /// Example: + /// ```motoko + /// import Int8 "mo:base/Int8"; + /// + /// Int8.compare(123, 124) // => #less + /// ``` public func compare(x : Int8, y : Int8) : { #less; #equal; #greater } { if (x < y) { #less } else if (x == y) { #equal } else { #greater } }; - /// Returns the negation of `x`, `-x`. Traps on overflow. + /// Returns the negation of `x`, `-x`. + /// + /// Traps on overflow, i.e. for `neg(-2 ** 7)`. + /// + /// + /// Example: + /// ```motoko + /// import Int8 "mo:base/Int8"; + /// + /// Int8.neg(123) // => -123 + /// ``` public func neg(x : Int8) : Int8 { -x }; - /// Returns the sum of `x` and `y`, `x + y`. Traps on overflow. + /// Returns the sum of `x` and `y`, `x + y`. + /// + /// Traps on overflow/underflow. + /// + /// Example: + /// ```motoko + /// import Int8 "mo:base/Int8"; + /// + /// Int8.add(100, 23) // => +123 + /// ``` public func add(x : Int8, y : Int8) : Int8 { x + y }; - /// Returns the difference of `x` and `y`, `x - y`. Traps on underflow. + /// Returns the difference of `x` and `y`, `x - y`. + /// + /// Traps on overflow/underflow. + /// + /// Example: + /// ```motoko + /// import Int8 "mo:base/Int8"; + /// + /// Int8.sub(123, 23) // => +100 + /// ``` public func sub(x : Int8, y : Int8) : Int8 { x - y }; - /// Returns the product of `x` and `y`, `x * y`. Traps on overflow. + /// Returns the product of `x` and `y`, `x * y`. + /// + /// Traps on overflow/underflow. + /// + /// Example: + /// ```motoko + /// import Int8 "mo:base/Int8"; + /// + /// Int8.mul(12, 10) // => +120 + /// ``` public func mul(x : Int8, y : Int8) : Int8 { x * y }; - /// Returns the division of `x by y`, `x / y`. + /// Returns the signed integer division of `x` by `y`, `x / y`. + /// Rounds the quotient towards zero, which is the same as truncating the decimal places of the quotient. + /// /// Traps when `y` is zero. + /// + /// Example: + /// ```motoko + /// import Int8 "mo:base/Int8"; + /// + /// Int8.div(123, 10) // => +12 + /// ``` public func div(x : Int8, y : Int8) : Int8 { x / y }; - /// Returns the remainder of `x` divided by `y`, `x % y`. + /// Returns the remainder of the signed integer division of `x` by `y`, `x % y`, + /// which is defined as `x - x / y * y`. + /// /// Traps when `y` is zero. + /// + /// Example: + /// ```motoko + /// import Int8 "mo:base/Int8"; + /// + /// Int8.rem(123, 10) // => +3 + /// ``` public func rem(x : Int8, y : Int8) : Int8 { x % y }; - /// Returns `x` to the power of `y`, `x ** y`. Traps on overflow. + /// Returns `x` to the power of `y`, `x ** y`. + /// + /// Traps on overflow/underflow and when `y < 0 or y >= 8`. + /// + /// Example: + /// ```motoko + /// import Int8 "mo:base/Int8"; + /// + /// Int8.pow(2, 6) // => +64 + /// ``` public func pow(x : Int8, y : Int8) : Int8 { x ** y }; /// Returns the bitwise negation of `x`, `^x`. - public func bitnot(x : Int8, y : Int8) : Int8 { ^x }; - - /// Returns the bitwise and of `x` and `y`, `x & y`. + /// + /// Example: + /// ```motoko + /// import Int8 "mo:base/Int8"; + /// + /// Int8.bitnot(-16 /* 0xf0 */) // => +15 // 0x0f + /// ``` + public func bitnot(x : Int8) : Int8 { ^x }; + + /// Returns the bitwise "and" of `x` and `y`, `x & y`. + /// + /// Example: + /// ```motoko + /// import Int8 "mo:base/Int8"; + /// + /// Int8.bitand(0x1f, 0x70) // => +16 // 0x10 + /// ``` public func bitand(x : Int8, y : Int8) : Int8 { x & y }; - /// Returns the bitwise or of `x` and `y`, `x \| y`. + /// Returns the bitwise "or" of `x` and `y`, `x | y`. + /// + /// Example: + /// ```motoko + /// import Int8 "mo:base/Int8"; + /// + /// Int8.bitor(0x0f, 0x70) // => +127 // 0x7f + /// ``` public func bitor(x : Int8, y : Int8) : Int8 { x | y }; - /// Returns the bitwise exclusive or of `x` and `y`, `x ^ y`. + /// Returns the bitwise "exclusive or" of `x` and `y`, `x ^ y`. + /// + /// Example: + /// ```motoko + /// import Int8 "mo:base/Int8"; + /// + /// Int8.bitxor(0x70, 0x7f) // => +15 // 0x0f + /// ``` public func bitxor(x : Int8, y : Int8) : Int8 { x ^ y }; - /// Returns the bitwise shift left of `x` by `y`, `x << y`. + /// Returns the bitwise left shift of `x` by `y`, `x << y`. + /// The right bits of the shift filled with zeros. + /// Left-overflowing bits, including the sign bit, are discarded. + /// + /// For `y >= 8`, the semantics is the same as for `bitshiftLeft(x, y % 8)`. + /// For `y < 0`, the semantics is the same as for `bitshiftLeft(x, y + y % 8)`. + /// + /// Example: + /// ```motoko + /// import Int8 "mo:base/Int8"; + /// + /// Int8.bitshiftLeft(1, 4) // => +16 // 0x10 equivalent to `2 ** 4`. + /// ``` public func bitshiftLeft(x : Int8, y : Int8) : Int8 { x << y }; - /// Returns the bitwise shift right of `x` by `y`, `x >> y`. + /// Returns the signed bitwise right shift of `x` by `y`, `x >> y`. + /// The sign bit is retained and the left side is filled with the sign bit. + /// Right-underflowing bits are discarded, i.e. not rotated to the left side. + /// + /// For `y >= 8`, the semantics is the same as for `bitshiftRight(x, y % 8)`. + /// For `y < 0`, the semantics is the same as for `bitshiftRight (x, y + y % 8)`. + /// + /// Example: + /// ```motoko + /// import Int8 "mo:base/Int8"; + /// + /// Int8.bitshiftRight(64, 4) // => +4 // equivalent to `64 / (2 ** 4)` + /// ``` public func bitshiftRight(x : Int8, y : Int8) : Int8 { x >> y }; - /// Returns the bitwise rotate left of `x` by `y`, `x <<> y`. + /// Returns the bitwise left rotatation of `x` by `y`, `x <<> y`. + /// Each left-overflowing bit is inserted again on the right side. + /// The sign bit is rotated like other bits, i.e. the rotation interprets the number as unsigned. + /// + /// Changes the direction of rotation for negative `y`. + /// For `y >= 8`, the semantics is the same as for `bitrotLeft(x, y % 8)`. + /// + /// Example: + /// ```motoko + /// import Int8 "mo:base/Int8"; + /// + /// Int8.bitrotLeft(0x11 /* 0b0001_0001 */, 2) // => +68 // 0b0100_0100 == 0x44. + /// ``` public func bitrotLeft(x : Int8, y : Int8) : Int8 { x <<> y }; - /// Returns the bitwise rotate right of `x` by `y`, `x <>> y`. + /// Returns the bitwise right rotation of `x` by `y`, `x <>> y`. + /// Each right-underflowing bit is inserted again on the right side. + /// The sign bit is rotated like other bits, i.e. the rotation interprets the number as unsigned. + /// + /// Changes the direction of rotation for negative `y`. + /// For `y >= 8`, the semantics is the same as for `bitrotRight(x, y % 8)`. + /// + /// Example: + /// ```motoko + /// import Int8 "mo:base/Int8"; + /// + /// Int8.bitrotRight(0x11 /* 0b0001_0001 */, 1) // => -120 // 0b1000_1000 == 0x88. + /// ``` public func bitrotRight(x : Int8, y : Int8) : Int8 { x <>> y }; - /// Returns the value of bit `p mod 8` in `x`, `(x & 2^(p mod 8)) == 2^(p mod 8)`. + /// Returns the value of bit `p` in `x`, `x & 2**p == 2**p`. + /// If `p >= 8`, the semantics is the same as for `bittest(x, p % 8)`. + /// + /// Example: + /// ```motoko + /// import Int8 "mo:base/Int8"; + /// + /// Int8.bittest(64, 6) // => true + /// ``` public func bittest(x : Int8, p : Nat) : Bool { Prim.btstInt8(x, Prim.intToInt8(p)) }; - /// Returns the value of setting bit `p mod 8` in `x` to `1`. + /// Returns the value of setting bit `p` in `x` to `1`. + /// If `p >= 8`, the semantics is the same as for `bitset(x, p % 8)`. + /// + /// Example: + /// ```motoko + /// import Int8 "mo:base/Int8"; + /// + /// Int8.bitset(0, 6) // => +64 + /// ``` public func bitset(x : Int8, p : Nat) : Int8 { x | (1 << Prim.intToInt8(p)) }; - /// Returns the value of clearing bit `p mod 8` in `x` to `0`. + /// Returns the value of clearing bit `p` in `x` to `0`. + /// If `p >= 8`, the semantics is the same as for `bitclear(x, p % 8)`. + /// + /// Example: + /// ```motoko + /// import Int8 "mo:base/Int8"; + /// + /// Int8.bitclear(-1, 6) // => -65 + /// ``` public func bitclear(x : Int8, p : Nat) : Int8 { x & ^(1 << Prim.intToInt8(p)) }; - /// Returns the value of flipping bit `p mod 8` in `x`. + /// Returns the value of flipping bit `p` in `x`. + /// If `p >= 8`, the semantics is the same as for `bitclear(x, p % 8)`. + /// + /// Example: + /// ```motoko + /// import Int8 "mo:base/Int8"; + /// + /// Int8.bitflip(127, 6) // => +63 + /// ``` public func bitflip(x : Int8, p : Nat) : Int8 { x ^ (1 << Prim.intToInt8(p)) }; /// Returns the count of non-zero bits in `x`. + /// + /// Example: + /// ```motoko + /// import Int8 "mo:base/Int8"; + /// + /// Int8.bitcountNonZero(0x0f) // => +4 + /// ``` public let bitcountNonZero : (x : Int8) -> Int8 = Prim.popcntInt8; /// Returns the count of leading zero bits in `x`. + /// + /// Example: + /// ```motoko + /// import Int8 "mo:base/Int8"; + /// + /// Int8.bitcountLeadingZero(0x08) // => +4 + /// ``` public let bitcountLeadingZero : (x : Int8) -> Int8 = Prim.clzInt8; /// Returns the count of trailing zero bits in `x`. + /// + /// Example: + /// ```motoko + /// import Int8 "mo:base/Int8"; + /// + /// Int8.bitcountTrailingZero(0x10) // => +4 + /// ``` public let bitcountTrailingZero : (x : Int8) -> Int8 = Prim.ctzInt8; - /// Returns the sum of `x` and `y`, `x +% y`. Wraps on overflow. + /// Returns the sum of `x` and `y`, `x +% y`. + /// + /// Wraps on overflow/underflow. + /// + /// + /// Example: + /// ```motoko + /// import Int8 "mo:base/Int8"; + /// + /// Int8.addWrap(2 ** 6, 2 ** 6) // => -128 // overflow + /// ``` public func addWrap(x : Int8, y : Int8) : Int8 { x +% y }; - /// Returns the difference of `x` and `y`, `x -% y`. Wraps on underflow. + /// Returns the difference of `x` and `y`, `x -% y`. + /// + /// Wraps on overflow/underflow. + /// + /// + /// Example: + /// ```motoko + /// import Int8 "mo:base/Int8"; + /// + /// Int8.subWrap(-2 ** 7, 1) // => +127 // underflow + /// ``` public func subWrap(x : Int8, y : Int8) : Int8 { x -% y }; /// Returns the product of `x` and `y`, `x *% y`. Wraps on overflow. + /// + /// Wraps on overflow/underflow. + /// + /// + /// Example: + /// ```motoko + /// import Int8 "mo:base/Int8"; + /// + /// Int8.mulWrap(2 ** 4, 2 ** 4) // => 0 // overflow + /// ``` public func mulWrap(x : Int8, y : Int8) : Int8 { x *% y }; - /// Returns `x` to the power of `y`, `x **% y`. Wraps on overflow. Traps if `y < 0`. + /// Returns `x` to the power of `y`, `x **% y`. + /// + /// Wraps on overflow/underflow. + /// Traps if `y < 0 or y >= 8`. + /// + /// + /// Example: + /// ```motoko + /// import Int8 "mo:base/Int8"; + /// + /// Int8.powWrap(2, 7) // => -128 // overflow + /// ``` public func powWrap(x : Int8, y : Int8) : Int8 { x **% y }; } diff --git a/test/int16Test.mo b/test/int16Test.mo new file mode 100644 index 00000000..6b3a2399 --- /dev/null +++ b/test/int16Test.mo @@ -0,0 +1,2303 @@ +import Int16 "mo:base/Int16"; +import Order "mo:base/Order"; +import Iter "mo:base/Iter"; + +import Suite "mo:matchers/Suite"; +import T "mo:matchers/Testable"; +import M "mo:matchers/Matchers"; + +let { run; test; suite } = Suite; + +let maximumInt16asInt = +2 ** 15 - 1 : Int; +let maximumInt16asNat16 = 2 ** 15 - 1 : Nat16; + +let minimumInt16asInt = -2 ** 15 : Int; + +let maximumNat16 = 65_535 : Nat16; + +class Int16Testable(number : Int16) : T.TestableItem { + public let item = number; + public func display(number : Int16) : Text { + debug_show (number) + }; + public let equals = func(x : Int16, y : Int16) : Bool { + x == y + } +}; + +class Nat16Testable(number : Nat16) : T.TestableItem { + public let item = number; + public func display(number : Nat16) : Text { + debug_show (number) + }; + public let equals = func(x : Nat16, y : Nat16) : Bool { + x == y + } +}; + +type Order = { #less; #equal; #greater }; + +class OrderTestable(value : Order) : T.TestableItem { + public let item = value; + public func display(value : Order) : Text { + debug_show (value) + }; + public let equals = func(x : Order, y : Order) : Bool { + x == y + } +}; + +/* --------------------------------------- */ + +run( + suite( + "constants", + [ + test( + "minimum value", + Int16.minimumValue, + M.equals(Int16Testable(Int16.fromInt(-2 ** 15))) + ), + test( + "maximum value", + Int16.maximumValue, + M.equals(Int16Testable(Int16.fromInt(+2 ** 15 - 1))) + ), + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "toInt", + [ + test( + "maximum number", + Int16.toInt(Int16.maximumValue), + M.equals(T.int(maximumInt16asInt)) + ), + test( + "minimum number", + Int16.toInt(Int16.minimumValue), + M.equals(T.int(minimumInt16asInt)) + ), + test( + "one", + Int16.toInt(1), + M.equals(T.int(1)) + ), + test( + "minus one", + Int16.toInt(-1), + M.equals(T.int(-1)) + ), + test( + "zero", + Int16.toInt(0), + M.equals(T.int(0)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "fromInt", + [ + test( + "maximum number", + Int16.fromInt(maximumInt16asInt), + M.equals(Int16Testable(Int16.maximumValue)) + ), + test( + "minimum number", + Int16.fromInt(minimumInt16asInt), + M.equals(Int16Testable(Int16.minimumValue)) + ), + test( + "one", + Int16.fromInt(1), + M.equals(Int16Testable(1)) + ), + test( + "minus one", + Int16.fromInt(-1), + M.equals(Int16Testable(-1)) + ), + test( + "zero", + Int16.fromInt(0), + M.equals(Int16Testable(0)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "fromIntWrap", + [ + test( + "maximum number", + Int16.fromIntWrap(maximumInt16asInt), + M.equals(Int16Testable(Int16.maximumValue)) + ), + test( + "minimum number", + Int16.fromIntWrap(minimumInt16asInt), + M.equals(Int16Testable(Int16.minimumValue)) + ), + test( + "one", + Int16.fromIntWrap(1), + M.equals(Int16Testable(1)) + ), + test( + "minus one", + Int16.fromIntWrap(-1), + M.equals(Int16Testable(-1)) + ), + test( + "zero", + Int16.fromIntWrap(0), + M.equals(Int16Testable(0)) + ), + test( + "overflow", + Int16.fromIntWrap(maximumInt16asInt + 1), + M.equals(Int16Testable(Int16.minimumValue)) + ), + test( + "underflow", + Int16.fromIntWrap(minimumInt16asInt - 1), + M.equals(Int16Testable(Int16.maximumValue)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "fromNat16", + [ + test( + "maximum number", + Int16.fromNat16(maximumInt16asNat16), + M.equals(Int16Testable(Int16.maximumValue)) + ), + test( + "one", + Int16.fromNat16(1), + M.equals(Int16Testable(1)) + ), + test( + "zero", + Int16.fromNat16(0), + M.equals(Int16Testable(0)) + ), + test( + "overflow", + Int16.fromNat16(maximumInt16asNat16 + 1), + M.equals(Int16Testable(Int16.minimumValue)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "toNat16", + [ + test( + "maximum number", + Int16.toNat16(Int16.maximumValue), + M.equals(Nat16Testable(maximumInt16asNat16)) + ), + test( + "one", + Int16.toNat16(1), + M.equals(Nat16Testable(1)) + ), + test( + "zero", + Int16.toNat16(0), + M.equals(Nat16Testable(0)) + ), + test( + "underflow", + Int16.toNat16(-1), + M.equals(Nat16Testable(maximumNat16)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "toText", + [ + test( + "positive", + Int16.toText(12345), + M.equals(T.text("12345")) + ), + test( + "negative", + Int16.toText(-12345), + M.equals(T.text("-12345")) + ), + test( + "zero", + Int16.toText(0), + M.equals(T.text("0")) + ), + test( + "maximum number", + Int16.toText(Int16.maximumValue), + M.equals(T.text("32767")) + ), + test( + "minimum number", + Int16.toText(Int16.minimumValue), + M.equals(T.text("-32768")) + ) + ] + ) +); + + +/* --------------------------------------- */ + +run( + suite( + "abs", + [ + test( + "positive number", + Int16.abs(123), + M.equals(Int16Testable(123)) + ), + test( + "negative number", + Int16.abs(-123), + M.equals(Int16Testable(123)) + ), + test( + "zero", + Int16.abs(0), + M.equals(Int16Testable(0)) + ), + test( + "maximum number", + Int16.abs(Int16.maximumValue), + M.equals(Int16Testable(Int16.maximumValue)) + ), + test( + "smallest possible", + Int16.abs(-Int16.maximumValue), + M.equals(Int16Testable(Int16.maximumValue)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "min", + [ + test( + "both positive", + Int16.min(2, 3), + M.equals(Int16Testable(2)) + ), + test( + "positive, negative", + Int16.min(2, -3), + M.equals(Int16Testable(-3)) + ), + test( + "both negative", + Int16.min(-2, -3), + M.equals(Int16Testable(-3)) + ), + test( + "negative, positive", + Int16.min(-2, 3), + M.equals(Int16Testable(-2)) + ), + test( + "equal values", + Int16.min(123, 123), + M.equals(Int16Testable(123)) + ), + test( + "maximum and minimum number", + Int16.min(Int16.maximumValue, Int16.minimumValue), + M.equals(Int16Testable(Int16.minimumValue)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "max", + [ + test( + "both positive", + Int16.max(2, 3), + M.equals(Int16Testable(3)) + ), + test( + "positive, negative", + Int16.max(2, -3), + M.equals(Int16Testable(2)) + ), + test( + "both negative", + Int16.max(-2, -3), + M.equals(Int16Testable(-2)) + ), + test( + "negative, positive", + Int16.max(-2, 3), + M.equals(Int16Testable(3)) + ), + test( + "equal values", + Int16.max(123, 123), + M.equals(Int16Testable(123)) + ), + test( + "maximum and minimum number", + Int16.max(Int16.maximumValue, Int16.minimumValue), + M.equals(Int16Testable(Int16.maximumValue)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "equal", + [ + test( + "positive equal", + Int16.equal(123, 123), + M.equals(T.bool(true)) + ), + test( + "negative equal", + Int16.equal(-123, -123), + M.equals(T.bool(true)) + ), + test( + "zero", + Int16.equal(0, 0), + M.equals(T.bool(true)) + ), + test( + "positive not equal", + Int16.equal(123, 124), + M.equals(T.bool(false)) + ), + test( + "negative not equal", + Int16.equal(-123, -124), + M.equals(T.bool(false)) + ), + test( + "mixed signs", + Int16.equal(123, -123), + M.equals(T.bool(false)) + ), + test( + "maxmimum equal", + Int16.equal(Int16.maximumValue, Int16.maximumValue), + M.equals(T.bool(true)) + ), + test( + "minimum equal", + Int16.equal(Int16.minimumValue, Int16.minimumValue), + M.equals(T.bool(true)) + ), + test( + "minimum and maximum", + Int16.equal(Int16.minimumValue, Int16.maximumValue), + M.equals(T.bool(false)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "notEqual", + [ + test( + "positive equal", + Int16.notEqual(123, 123), + M.equals(T.bool(false)) + ), + test( + "negative equal", + Int16.notEqual(-123, -123), + M.equals(T.bool(false)) + ), + test( + "zero", + Int16.notEqual(0, 0), + M.equals(T.bool(false)) + ), + test( + "positive not equal", + Int16.notEqual(123, 124), + M.equals(T.bool(true)) + ), + test( + "negative not equal", + Int16.notEqual(-123, -124), + M.equals(T.bool(true)) + ), + test( + "mixed signs", + Int16.notEqual(123, -123), + M.equals(T.bool(true)) + ), + test( + "maxmimum equal", + Int16.notEqual(Int16.maximumValue, Int16.maximumValue), + M.equals(T.bool(false)) + ), + test( + "minimum equal", + Int16.notEqual(Int16.minimumValue, Int16.minimumValue), + M.equals(T.bool(false)) + ), + test( + "minimum and maximum", + Int16.notEqual(Int16.minimumValue, Int16.maximumValue), + M.equals(T.bool(true)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "less", + [ + test( + "positive equal", + Int16.less(123, 123), + M.equals(T.bool(false)) + ), + test( + "positive less", + Int16.less(123, 245), + M.equals(T.bool(true)) + ), + test( + "positive greater", + Int16.less(245, 123), + M.equals(T.bool(false)) + ), + test( + "negative equal", + Int16.less(-123, -123), + M.equals(T.bool(false)) + ), + test( + "negative less", + Int16.less(-245, -123), + M.equals(T.bool(true)) + ), + test( + "negative greater", + Int16.less(-123, -245), + M.equals(T.bool(false)) + ), + test( + "zero", + Int16.less(0, 0), + M.equals(T.bool(false)) + ), + test( + "mixed signs less", + Int16.less(-123, 123), + M.equals(T.bool(true)) + ), + test( + "mixed signs greater", + Int16.less(123, -123), + M.equals(T.bool(false)) + ), + test( + "minimum and maximum", + Int16.less(Int16.minimumValue, Int16.maximumValue), + M.equals(T.bool(true)) + ), + test( + "maximum and minimum", + Int16.less(Int16.maximumValue, Int16.minimumValue), + M.equals(T.bool(false)) + ), + test( + "maximum and maximum", + Int16.less(Int16.maximumValue, Int16.maximumValue), + M.equals(T.bool(false)) + ), + test( + "minimum and minimum", + Int16.less(Int16.minimumValue, Int16.minimumValue), + M.equals(T.bool(false)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "lessOrEqual", + [ + test( + "positive equal", + Int16.lessOrEqual(123, 123), + M.equals(T.bool(true)) + ), + test( + "positive less", + Int16.lessOrEqual(123, 245), + M.equals(T.bool(true)) + ), + test( + "positive greater", + Int16.lessOrEqual(245, 123), + M.equals(T.bool(false)) + ), + test( + "negative equal", + Int16.lessOrEqual(-123, -123), + M.equals(T.bool(true)) + ), + test( + "negative less", + Int16.lessOrEqual(-245, -123), + M.equals(T.bool(true)) + ), + test( + "negative greater", + Int16.lessOrEqual(-123, -245), + M.equals(T.bool(false)) + ), + test( + "zero", + Int16.lessOrEqual(0, 0), + M.equals(T.bool(true)) + ), + test( + "mixed signs less", + Int16.lessOrEqual(-123, 123), + M.equals(T.bool(true)) + ), + test( + "mixed signs greater", + Int16.lessOrEqual(123, -123), + M.equals(T.bool(false)) + ), + test( + "minimum and maximum", + Int16.lessOrEqual(Int16.minimumValue, Int16.maximumValue), + M.equals(T.bool(true)) + ), + test( + "maximum and minimum", + Int16.lessOrEqual(Int16.maximumValue, Int16.minimumValue), + M.equals(T.bool(false)) + ), + test( + "maximum and maximum", + Int16.lessOrEqual(Int16.maximumValue, Int16.maximumValue), + M.equals(T.bool(true)) + ), + test( + "minimum and minimum", + Int16.lessOrEqual(Int16.minimumValue, Int16.minimumValue), + M.equals(T.bool(true)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "greater", + [ + test( + "positive equal", + Int16.greater(123, 123), + M.equals(T.bool(false)) + ), + test( + "positive less", + Int16.greater(123, 245), + M.equals(T.bool(false)) + ), + test( + "positive greater", + Int16.greater(245, 123), + M.equals(T.bool(true)) + ), + test( + "negative equal", + Int16.greater(-123, -123), + M.equals(T.bool(false)) + ), + test( + "negative less", + Int16.greater(-245, -123), + M.equals(T.bool(false)) + ), + test( + "negative greater", + Int16.greater(-123, -245), + M.equals(T.bool(true)) + ), + test( + "zero", + Int16.greater(0, 0), + M.equals(T.bool(false)) + ), + test( + "mixed signs less", + Int16.greater(-123, 123), + M.equals(T.bool(false)) + ), + test( + "mixed signs greater", + Int16.greater(123, -123), + M.equals(T.bool(true)) + ), + test( + "minimum and maximum", + Int16.greater(Int16.minimumValue, Int16.maximumValue), + M.equals(T.bool(false)) + ), + test( + "maximum and minimum", + Int16.greater(Int16.maximumValue, Int16.minimumValue), + M.equals(T.bool(true)) + ), + test( + "maximum and maximum", + Int16.greater(Int16.maximumValue, Int16.maximumValue), + M.equals(T.bool(false)) + ), + test( + "minimum and minimum", + Int16.greater(Int16.minimumValue, Int16.minimumValue), + M.equals(T.bool(false)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "greaterOrEqual", + [ + test( + "positive equal", + Int16.greaterOrEqual(123, 123), + M.equals(T.bool(true)) + ), + test( + "positive less", + Int16.greaterOrEqual(123, 245), + M.equals(T.bool(false)) + ), + test( + "positive greater", + Int16.greaterOrEqual(245, 123), + M.equals(T.bool(true)) + ), + test( + "negative equal", + Int16.greaterOrEqual(-123, -123), + M.equals(T.bool(true)) + ), + test( + "negative less", + Int16.greaterOrEqual(-245, -123), + M.equals(T.bool(false)) + ), + test( + "negative greater", + Int16.greaterOrEqual(-123, -245), + M.equals(T.bool(true)) + ), + test( + "zero", + Int16.greaterOrEqual(0, 0), + M.equals(T.bool(true)) + ), + test( + "mixed signs less", + Int16.greaterOrEqual(-123, 123), + M.equals(T.bool(false)) + ), + test( + "mixed signs greater", + Int16.greaterOrEqual(123, -123), + M.equals(T.bool(true)) + ), + test( + "minimum and maximum", + Int16.greaterOrEqual(Int16.minimumValue, Int16.maximumValue), + M.equals(T.bool(false)) + ), + test( + "maximum and minimum", + Int16.greaterOrEqual(Int16.maximumValue, Int16.minimumValue), + M.equals(T.bool(true)) + ), + test( + "maximum and maximum", + Int16.greaterOrEqual(Int16.maximumValue, Int16.maximumValue), + M.equals(T.bool(true)) + ), + test( + "minimum and minimum", + Int16.greaterOrEqual(Int16.minimumValue, Int16.minimumValue), + M.equals(T.bool(true)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "compare", + [ + test( + "positive equal", + Int16.compare(123, 123), + M.equals(OrderTestable(#equal)) + ), + test( + "positive less", + Int16.compare(123, 245), + M.equals(OrderTestable(#less)) + ), + test( + "positive greater", + Int16.compare(245, 123), + M.equals(OrderTestable(#greater)) + ), + test( + "negative equal", + Int16.compare(-123, -123), + M.equals(OrderTestable(#equal)) + ), + test( + "negative less", + Int16.compare(-245, -123), + M.equals(OrderTestable(#less)) + ), + test( + "negative greater", + Int16.compare(-123, -245), + M.equals(OrderTestable(#greater)) + ), + test( + "zero", + Int16.compare(0, 0), + M.equals(OrderTestable(#equal)) + ), + test( + "mixed signs less", + Int16.compare(-123, 123), + M.equals(OrderTestable(#less)) + ), + test( + "mixed signs greater", + Int16.compare(123, -123), + M.equals(OrderTestable(#greater)) + ), + test( + "minimum and maximum", + Int16.compare(Int16.minimumValue, Int16.maximumValue), + M.equals(OrderTestable(#less)) + ), + test( + "maximum and minimum", + Int16.compare(Int16.maximumValue, Int16.minimumValue), + M.equals(OrderTestable(#greater)) + ), + test( + "maximum and maximum", + Int16.compare(Int16.maximumValue, Int16.maximumValue), + M.equals(OrderTestable(#equal)) + ), + test( + "minimum and minimum", + Int16.compare(Int16.minimumValue, Int16.minimumValue), + M.equals(OrderTestable(#equal)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "neg", + [ + test( + "positive number", + Int16.neg(123), + M.equals(Int16Testable(-123)) + ), + test( + "negative number", + Int16.neg(-123), + M.equals(Int16Testable(123)) + ), + test( + "zero", + Int16.neg(0), + M.equals(Int16Testable(0)) + ), + test( + "maximum number", + Int16.neg(Int16.maximumValue), + M.equals(Int16Testable(-Int16.maximumValue)) + ), + test( + "smallest possible", + Int16.neg(-Int16.maximumValue), + M.equals(Int16Testable(Int16.maximumValue)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "add", + [ + test( + "positive", + Int16.add(123, 123), + M.equals(Int16Testable(246)) + ), + test( + "negative", + Int16.add(-123, -123), + M.equals(Int16Testable(-246)) + ), + test( + "mixed signs", + Int16.add(-123, 223), + M.equals(Int16Testable(100)) + ), + test( + "zero", + Int16.add(0, 0), + M.equals(Int16Testable(0)) + ), + test( + "minimum and maximum", + Int16.add(Int16.minimumValue, Int16.maximumValue), + M.equals(Int16Testable(-1)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "sub", + [ + test( + "positive", + Int16.sub(123, 123), + M.equals(Int16Testable(0)) + ), + test( + "negative", + Int16.sub(-123, -123), + M.equals(Int16Testable(0)) + ), + test( + "mixed signs", + Int16.sub(-123, 223), + M.equals(Int16Testable(-346)) + ), + test( + "zero", + Int16.sub(0, 0), + M.equals(Int16Testable(0)) + ), + test( + "maximum and maximum", + Int16.sub(Int16.maximumValue, Int16.maximumValue), + M.equals(Int16Testable(0)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "mul", + [ + test( + "positive", + Int16.mul(123, 234), + M.equals(Int16Testable(28782)) + ), + test( + "negative", + Int16.mul(-123, -234), + M.equals(Int16Testable(28782)) + ), + test( + "mixed signs", + Int16.mul(-123, 234), + M.equals(Int16Testable(-28782)) + ), + test( + "zeros", + Int16.mul(0, 0), + M.equals(Int16Testable(0)) + ), + test( + "zero and maximum", + Int16.mul(0, Int16.maximumValue), + M.equals(Int16Testable(0)) + ), + test( + "minimum and zero", + Int16.mul(Int16.minimumValue, 0), + M.equals(Int16Testable(0)) + ), + test( + "one and maximum", + Int16.mul(1, Int16.maximumValue), + M.equals(Int16Testable(Int16.maximumValue)) + ), + test( + "minimum and one", + Int16.mul(Int16.minimumValue, 1), + M.equals(Int16Testable(Int16.minimumValue)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "div", + [ + test( + "positive multiple", + Int16.div(156, 13), + M.equals(Int16Testable(12)) + ), + test( + "positive remainder", + Int16.div(1234, 100), + M.equals(Int16Testable(12)) + ), + test( + "negative multiple", + Int16.div(-156, -13), + M.equals(Int16Testable(12)) + ), + test( + "negative remainder", + Int16.div(-1234, -100), + M.equals(Int16Testable(12)) + ), + test( + "mixed signs", + Int16.div(-123, 23), + M.equals(Int16Testable(-5)) + ), + test( + "zero and number", + Int16.div(0, -123), + M.equals(Int16Testable(0)) + ), + test( + "zero and maximum", + Int16.div(0, Int16.maximumValue), + M.equals(Int16Testable(0)) + ), + test( + "zero and minimum", + Int16.div(0, Int16.minimumValue), + M.equals(Int16Testable(0)) + ), + test( + "maximum and maximum", + Int16.div(Int16.maximumValue, Int16.maximumValue), + M.equals(Int16Testable(1)) + ), + test( + "minimum and minimum", + Int16.div(Int16.minimumValue, Int16.minimumValue), + M.equals(Int16Testable(1)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "rem", + [ + test( + "positive multiple", + Int16.rem(156, 13), + M.equals(Int16Testable(0)) + ), + test( + "positive/positive remainder", + Int16.rem(1234, 100), + M.equals(Int16Testable(34)) + ), + test( + "positive/negative remainder", + Int16.rem(1234, -100), + M.equals(Int16Testable(34)) + ), + test( + "negative multiple", + Int16.rem(-156, -13), + M.equals(Int16Testable(0)) + ), + test( + "negative/positive remainder", + Int16.rem(-1234, 100), + M.equals(Int16Testable(-34)) + ), + test( + "negative/negative remainder", + Int16.rem(-1234, -100), + M.equals(Int16Testable(-34)) + ), + test( + "zero and maximum", + Int16.rem(0, Int16.maximumValue), + M.equals(Int16Testable(0)) + ), + test( + "zero and minimum", + Int16.rem(0, Int16.minimumValue), + M.equals(Int16Testable(0)) + ), + test( + "maximum and maximum", + Int16.rem(Int16.maximumValue, Int16.maximumValue), + M.equals(Int16Testable(0)) + ), + test( + "minimum and minimum", + Int16.rem(Int16.minimumValue, Int16.minimumValue), + M.equals(Int16Testable(0)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "pow", + [ + test( + "positive base, positive exponent", + Int16.pow(24, 3), + M.equals(Int16Testable(13824)) + ), + test( + "positive base, zero exponent", + Int16.pow(24, 0), + M.equals(Int16Testable(1)) + ), + test( + "negative base, odd exponent", + Int16.pow(-24, 3), + M.equals(Int16Testable(-13824)) + ), + test( + "negative base, even exponent", + Int16.pow(-24, 2), + M.equals(Int16Testable(576)) + ), + test( + "negative base, zero exponent", + Int16.pow(-24, 0), + M.equals(Int16Testable(1)) + ), + test( + "maximum and zero", + Int16.pow(Int16.maximumValue, 0), + M.equals(Int16Testable(1)) + ), + test( + "minimum and zero", + Int16.pow(Int16.minimumValue, 0), + M.equals(Int16Testable(1)) + ), + test( + "plus one and maximum", + Int16.pow(1, Int16.maximumValue), + M.equals(Int16Testable(1)) + ), + test( + "minus one and maximum", + Int16.pow(-1, Int16.maximumValue), + M.equals(Int16Testable(-1)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitnot", + [ + test( + "zero", + Int16.bitnot(0), + M.equals(Int16Testable(-1)) + ), + test( + "minus 1", + Int16.bitnot(-1), + M.equals(Int16Testable(0)) + ), + test( + "maximum", + Int16.bitnot(Int16.maximumValue), + M.equals(Int16Testable(Int16.minimumValue)) + ), + test( + "minimum", + Int16.bitnot(Int16.minimumValue), + M.equals(Int16Testable(Int16.maximumValue)) + ), + test( + "arbitrary", + Int16.bitnot(1234), + M.equals(Int16Testable(-1235)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitand", + [ + test( + "inverted", + Int16.bitand(0x70f0, 0x0f0f), + M.equals(Int16Testable(0)) + ), + test( + "overlap", + Int16.bitand(0x0ff0, 0x7fff), + M.equals(Int16Testable(0xff0)) + ), + test( + "arbitrary", + Int16.bitand(0x1234, 0x7654), + M.equals(Int16Testable(0x1214)) + ), + test( + "negative", + Int16.bitand(-123, -123), + M.equals(Int16Testable(-123)) + ), + test( + "mixed signs", + Int16.bitand(-256, 255), + M.equals(Int16Testable(0)) + ), + test( + "zero", + Int16.bitand(0, 0), + M.equals(Int16Testable(0)) + ), + test( + "zero and maximum", + Int16.bitand(0, Int16.maximumValue), + M.equals(Int16Testable(0)) + ), + test( + "minimum and zero", + Int16.bitand(Int16.minimumValue, 0), + M.equals(Int16Testable(0)) + ), + test( + "minimum and maximum", + Int16.bitand(Int16.minimumValue, Int16.maximumValue), + M.equals(Int16Testable(0)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitor", + [ + test( + "inverted", + Int16.bitor(0x70f0, 0x0f0f), + M.equals(Int16Testable(0x7fff)) + ), + test( + "overlap", + Int16.bitor(0x0ff0, 0x7fff), + M.equals(Int16Testable(0x7fff)) + ), + test( + "arbitrary", + Int16.bitor(0x1234, 0x7654), + M.equals(Int16Testable(0x7674)) + ), + test( + "negative", + Int16.bitor(-123, -123), + M.equals(Int16Testable(-123)) + ), + test( + "mixed signs", + Int16.bitor(-256, 255), + M.equals(Int16Testable(-1)) + ), + test( + "zero", + Int16.bitor(0, 0), + M.equals(Int16Testable(0)) + ), + test( + "zero and maximum", + Int16.bitor(0, Int16.maximumValue), + M.equals(Int16Testable(Int16.maximumValue)) + ), + test( + "minimum and zero", + Int16.bitor(Int16.minimumValue, 0), + M.equals(Int16Testable(Int16.minimumValue)) + ), + test( + "minimum and maximum", + Int16.bitor(Int16.minimumValue, Int16.maximumValue), + M.equals(Int16Testable(-1)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitxor", + [ + test( + "inverted", + Int16.bitxor(0x70f0, 0x0f0f), + M.equals(Int16Testable(0x7fff)) + ), + test( + "overlap", + Int16.bitxor(0x0ff0, 0x7fff), + M.equals(Int16Testable(0x700f)) + ), + test( + "arbitrary", + Int16.bitxor(0x1234, 0x7654), + M.equals(Int16Testable(0x6460)) + ), + test( + "negative", + Int16.bitxor(-123, -123), + M.equals(Int16Testable(0)) + ), + test( + "mixed signs", + Int16.bitxor(-256, 255), + M.equals(Int16Testable(-1)) + ), + test( + "zero", + Int16.bitxor(0, 0), + M.equals(Int16Testable(0)) + ), + test( + "zero and maximum", + Int16.bitxor(0, Int16.maximumValue), + M.equals(Int16Testable(Int16.maximumValue)) + ), + test( + "minimum and zero", + Int16.bitxor(Int16.minimumValue, 0), + M.equals(Int16Testable(Int16.minimumValue)) + ), + test( + "minimum and maximum", + Int16.bitxor(Int16.minimumValue, Int16.maximumValue), + M.equals(Int16Testable(-1)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitshiftLeft", + [ + test( + "positive number", + Int16.bitshiftLeft(0x70f1, 4), + M.equals(Int16Testable(0x0f10)) + ), + test( + "negative number", + Int16.bitshiftLeft(-256, 4), + M.equals(Int16Testable(-4096)) + ), + test( + "arbitrary", + Int16.bitshiftLeft(1234, 7), + M.equals(Int16Testable(26_880)) + ), + test( + "zero shift", + Int16.bitshiftLeft(1234, 0), + M.equals(Int16Testable(1234)) + ), + test( + "one maximum shift", + Int16.bitshiftLeft(1, 15), + M.equals(Int16Testable(Int16.minimumValue)) + ), + test( + "minimum number", + Int16.bitshiftLeft(-1, 15), + M.equals(Int16Testable(Int16.minimumValue)) + ), + test( + "discard overflow", + Int16.bitshiftLeft(0x7fff, 8), + M.equals(Int16Testable(-256)) + ), + test( + "beyond bit length positive", + Int16.bitshiftLeft(0x1234, 32 + 7), + M.equals(Int16Testable(Int16.bitshiftLeft(0x1234, 7))) + ), + test( + "beyond bit length negative", + Int16.bitshiftLeft(-0x1234, 16 + 7), + M.equals(Int16Testable(Int16.bitshiftLeft(-0x1234, 7))) + ), + test( + "negative shift argument", + Int16.bitshiftLeft(0x1234, -7), + M.equals(Int16Testable(Int16.bitshiftLeft(0x1234, 16 - 7))) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitshiftRight", + [ + test( + "positive number", + Int16.bitshiftRight(0x70f1, 4), + M.equals(Int16Testable(0x070f)) + ), + test( + "negative number", + Int16.bitshiftRight(-256, 4), + M.equals(Int16Testable(-16)) + ), + test( + "arbitrary", + Int16.bitshiftRight(1234, 7), + M.equals(Int16Testable(9)) + ), + test( + "zero shift", + Int16.bitshiftRight(1234, 0), + M.equals(Int16Testable(1234)) + ), + test( + "minus one maximum shift", + Int16.bitshiftRight(-1, 15), + M.equals(Int16Testable(-1)) + ), + test( + "minimum number", + Int16.bitshiftRight(Int16.minimumValue, 15), + M.equals(Int16Testable(-1)) + ), + test( + "discard underflow", + Int16.bitshiftRight(0x00ff, 8), + M.equals(Int16Testable(0)) + ), + test( + "beyond bit length positive", + Int16.bitshiftRight(0x1234, 32 + 7), + M.equals(Int16Testable(Int16.bitshiftRight(0x1234, 7))) + ), + test( + "beyond bit length negative", + Int16.bitshiftRight(-0x1234, 16 + 7), + M.equals(Int16Testable(Int16.bitshiftRight(-0x1234, 7))) + ), + test( + "negative shift argument", + Int16.bitshiftRight(0x1234, -7), + M.equals(Int16Testable(Int16.bitshiftRight(0x1234, 16 - 7))) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitrotLeft", + [ + test( + "positive number non-overflow", + Int16.bitrotLeft(0x070f, 4), + M.equals(Int16Testable(0x70f0)) + ), + test( + "positive number overflow", + Int16.bitrotLeft(0x3412, 8), + M.equals(Int16Testable(0x1234)) + ), + test( + "negative number", + Int16.bitrotLeft(-256, 4), + M.equals(Int16Testable(-4081)) + ), + test( + "arbitrary", + Int16.bitrotLeft(12_345, 7), + M.equals(Int16Testable(7_320)) + ), + test( + "zero shift", + Int16.bitrotLeft(1234, 0), + M.equals(Int16Testable(1234)) + ), + test( + "minus one maximum rotate", + Int16.bitrotLeft(-1, 15), + M.equals(Int16Testable(-1)) + ), + test( + "maximum number", + Int16.bitrotLeft(Int16.maximumValue, 1), + M.equals(Int16Testable(-2)) + ), + test( + "minimum number", + Int16.bitrotLeft(1, 15), + M.equals(Int16Testable(Int16.minimumValue)) + ), + test( + "opposite rotation", + Int16.bitrotLeft(256, -2), + M.equals(Int16Testable(64)) + ), + test( + "rotate beyond bit length", + Int16.bitrotLeft(128, 18), + M.equals(Int16Testable(512)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitrotRight", + [ + test( + "positive number non-underflow", + Int16.bitrotRight(0x70f0, 4), + M.equals(Int16Testable(0x070f)) + ), + test( + "positive number underflow", + Int16.bitrotRight(0x3412, 8), + M.equals(Int16Testable(0x1234)) + ), + test( + "negative number", + Int16.bitrotRight(-256, 8), + M.equals(Int16Testable(255)) + ), + test( + "arbitrary", + Int16.bitrotRight(12_345, 7), + M.equals(Int16Testable(29_280)) + ), + test( + "zero shift", + Int16.bitrotRight(1234, 0), + M.equals(Int16Testable(1234)) + ), + test( + "minus one maximum rotate", + Int16.bitrotRight(-1, 15), + M.equals(Int16Testable(-1)) + ), + test( + "maximum number", + Int16.bitrotRight(-2, 1), + M.equals(Int16Testable(Int16.maximumValue)) + ), + test( + "minimum number", + Int16.bitrotRight(Int16.minimumValue, 15), + M.equals(Int16Testable(1)) + ), + test( + "opposite rotation", + Int16.bitrotRight(256, -2), + M.equals(Int16Testable(1024)) + ), + test( + "rotate beyond bit length", + Int16.bitrotRight(128, 18), + M.equals(Int16Testable(32)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bittest", + [ + test( + "set bit", + Int16.bittest(128, 7), + M.equals(T.bool(true)) + ), + test( + "cleared bit", + Int16.bittest(-129, 7), + M.equals(T.bool(false)) + ), + test( + "all zero", + do { + let number = 0 : Int16; + var count = 0; + for (index in Iter.range(0, 15)) { + if (Int16.bittest(number, index)) { + count += 1 + } + }; + count + }, + M.equals(T.int(0)) + ), + test( + "all one", + do { + let number = -1 : Int16; + var count = 0; + for (index in Iter.range(0, 15)) { + if (Int16.bittest(number, index)) { + count += 1 + } + }; + count + }, + M.equals(T.int(16)) + ), + test( + "set bit beyond bit length", + Int16.bittest(128, 16 + 7), + M.equals(T.bool(true)) + ), + test( + "cleared bit beyond bit length", + Int16.bittest(-129, 32 + 7), + M.equals(T.bool(false)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitset", + [ + test( + "set bit", + Int16.bitset(0, 7), + M.equals(Int16Testable(128)) + ), + test( + "minus one", + Int16.bitset(-129, 7), + M.equals(Int16Testable(-1)) + ), + test( + "no effect", + Int16.bitset(128, 7), + M.equals(Int16Testable(128)) + ), + test( + "set all", + do { + var number = 0 : Int16; + for (index in Iter.range(0, 15)) { + number := Int16.bitset(number, index) + }; + number + }, + M.equals(Int16Testable(-1)) + ), + test( + "all no effect", + do { + var number = -1 : Int16; + for (index in Iter.range(0, 15)) { + number := Int16.bitset(number, index) + }; + number + }, + M.equals(Int16Testable(-1)) + ), + test( + "set bit beyond bit length", + Int16.bitset(0, 16 + 7), + M.equals(Int16Testable(128)) + ), + test( + "minus one beyond bit length", + Int16.bitset(-129, 32 + 7), + M.equals(Int16Testable(-1)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitclear", + [ + test( + "clear bit", + Int16.bitclear(128, 7), + M.equals(Int16Testable(0)) + ), + test( + "minus one", + Int16.bitclear(-1, 7), + M.equals(Int16Testable(-129)) + ), + test( + "no effect", + Int16.bitclear(0, 7), + M.equals(Int16Testable(0)) + ), + test( + "clear all", + do { + var number = -1 : Int16; + for (index in Iter.range(0, 15)) { + number := Int16.bitclear(number, index) + }; + number + }, + M.equals(Int16Testable(0)) + ), + test( + "all no effect", + do { + var number = 0 : Int16; + for (index in Iter.range(0, 15)) { + number := Int16.bitclear(number, index) + }; + number + }, + M.equals(Int16Testable(0)) + ), + test( + "clear bit beyond bit length", + Int16.bitclear(128, 16 + 7), + M.equals(Int16Testable(0)) + ), + test( + "minus one beyond bit length", + Int16.bitclear(-1, 32 + 7), + M.equals(Int16Testable(-129)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitflip", + [ + test( + "clear bit", + Int16.bitflip(255, 7), + M.equals(Int16Testable(127)) + ), + test( + "set bit", + Int16.bitflip(127, 7), + M.equals(Int16Testable(255)) + ), + test( + "double flip", + Int16.bitflip(Int16.bitflip(0x1234, 13), 13), + M.equals(Int16Testable(0x1234)) + ), + test( + "clear all", + do { + var number = -1 : Int16; + for (index in Iter.range(0, 15)) { + number := Int16.bitflip(number, index) + }; + number + }, + M.equals(Int16Testable(0)) + ), + test( + "set all", + do { + var number = 0 : Int16; + for (index in Iter.range(0, 15)) { + number := Int16.bitflip(number, index) + }; + number + }, + M.equals(Int16Testable(-1)) + ), + test( + "clear bit beyond bit length", + Int16.bitflip(255, 16 + 7), + M.equals(Int16Testable(127)) + ), + test( + "set bit beyond bit length", + Int16.bitflip(127, 32 + 7), + M.equals(Int16Testable(255)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitcountNonZero", + [ + test( + "zero", + Int16.bitcountNonZero(0), + M.equals(Int16Testable(0)) + ), + test( + "minus one", + Int16.bitcountNonZero(-1), + M.equals(Int16Testable(16)) + ), + test( + "minus two", + Int16.bitcountNonZero(-2), + M.equals(Int16Testable(15)) + ), + test( + "one", + Int16.bitcountNonZero(1), + M.equals(Int16Testable(1)) + ), + test( + "minimum value", + Int16.bitcountNonZero(Int16.minimumValue), + M.equals(Int16Testable(1)) + ), + test( + "maximum value", + Int16.bitcountNonZero(Int16.maximumValue), + M.equals(Int16Testable(15)) + ), + test( + "alternating bits positive", + Int16.bitcountNonZero(0x5555), + M.equals(Int16Testable(8)) + ), + test( + "alternating bits negative", + Int16.bitcountNonZero(-0x5556), + M.equals(Int16Testable(8)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitcountLeadingZero", + [ + test( + "zero", + Int16.bitcountLeadingZero(0), + M.equals(Int16Testable(16)) + ), + test( + "minus one", + Int16.bitcountLeadingZero(-1), + M.equals(Int16Testable(0)) + ), + test( + "minus two", + Int16.bitcountLeadingZero(-2), + M.equals(Int16Testable(0)) + ), + test( + "one", + Int16.bitcountLeadingZero(1), + M.equals(Int16Testable(15)) + ), + test( + "two", + Int16.bitcountLeadingZero(2), + M.equals(Int16Testable(14)) + ), + test( + "arbitrary", + Int16.bitcountLeadingZero(0x0010), + M.equals(Int16Testable(11)) + ), + test( + "minimum value", + Int16.bitcountLeadingZero(Int16.minimumValue), + M.equals(Int16Testable(0)) + ), + test( + "maximum value", + Int16.bitcountLeadingZero(Int16.maximumValue), + M.equals(Int16Testable(1)) + ), + test( + "alternating bits positive", + Int16.bitcountLeadingZero(0x5555), + M.equals(Int16Testable(1)) + ), + test( + "alternating bits negative", + Int16.bitcountLeadingZero(-0x5556), + M.equals(Int16Testable(0)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitcountTrailingZero", + [ + test( + "zero", + Int16.bitcountTrailingZero(0), + M.equals(Int16Testable(16)) + ), + test( + "minus one", + Int16.bitcountTrailingZero(-1), + M.equals(Int16Testable(0)) + ), + test( + "minus two", + Int16.bitcountTrailingZero(-2), + M.equals(Int16Testable(1)) + ), + test( + "one", + Int16.bitcountTrailingZero(1), + M.equals(Int16Testable(0)) + ), + test( + "two", + Int16.bitcountTrailingZero(2), + M.equals(Int16Testable(1)) + ), + test( + "arbitrary", + Int16.bitcountTrailingZero(0x5060), + M.equals(Int16Testable(5)) + ), + test( + "minimum value", + Int16.bitcountTrailingZero(Int16.minimumValue), + M.equals(Int16Testable(15)) + ), + test( + "maximum value", + Int16.bitcountTrailingZero(Int16.maximumValue), + M.equals(Int16Testable(0)) + ), + test( + "alternating bits positive", + Int16.bitcountTrailingZero(0x5555), + M.equals(Int16Testable(0)) + ), + test( + "alternating bits negative", + Int16.bitcountTrailingZero(-0x5556), + M.equals(Int16Testable(1)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "addWrap", + [ + test( + "positive", + Int16.addWrap(123, 123), + M.equals(Int16Testable(246)) + ), + test( + "negative", + Int16.addWrap(-123, -123), + M.equals(Int16Testable(-246)) + ), + test( + "mixed signs", + Int16.addWrap(-123, 223), + M.equals(Int16Testable(100)) + ), + test( + "zero", + Int16.addWrap(0, 0), + M.equals(Int16Testable(0)) + ), + test( + "minimum and maximum", + Int16.addWrap(Int16.minimumValue, Int16.maximumValue), + M.equals(Int16Testable(-1)) + ), + test( + "small overflow", + Int16.addWrap(Int16.maximumValue, 1), + M.equals(Int16Testable(Int16.minimumValue)) + ), + test( + "large overflow", + Int16.addWrap(Int16.maximumValue, Int16.maximumValue), + M.equals(Int16Testable(-2)) + ), + test( + "small underflow", + Int16.addWrap(Int16.minimumValue, -1), + M.equals(Int16Testable(Int16.maximumValue)) + ), + test( + "large underflow", + Int16.addWrap(Int16.minimumValue, Int16.minimumValue), + M.equals(Int16Testable(0)) + ), + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "subWrap", + [ + test( + "positive", + Int16.subWrap(123, 123), + M.equals(Int16Testable(0)) + ), + test( + "negative", + Int16.subWrap(-123, -123), + M.equals(Int16Testable(0)) + ), + test( + "mixed signs", + Int16.subWrap(-123, 223), + M.equals(Int16Testable(-346)) + ), + test( + "zero", + Int16.subWrap(0, 0), + M.equals(Int16Testable(0)) + ), + test( + "maximum and maximum", + Int16.subWrap(Int16.maximumValue, Int16.maximumValue), + M.equals(Int16Testable(0)) + ), + test( + "small overflow", + Int16.subWrap(Int16.maximumValue, -1), + M.equals(Int16Testable(Int16.minimumValue)) + ), + test( + "large overflow", + Int16.subWrap(Int16.maximumValue, Int16.minimumValue), + M.equals(Int16Testable(-1)) + ), + test( + "small underflow", + Int16.subWrap(Int16.minimumValue, 1), + M.equals(Int16Testable(Int16.maximumValue)) + ), + test( + "large underflow", + Int16.subWrap(Int16.minimumValue, Int16.maximumValue), + M.equals(Int16Testable(1)) + ), + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "mulWrap", + [ + test( + "positive", + Int16.mulWrap(123, 234), + M.equals(Int16Testable(28782)) + ), + test( + "negative", + Int16.mulWrap(-123, -234), + M.equals(Int16Testable(28782)) + ), + test( + "mixed signs", + Int16.mulWrap(-123, 234), + M.equals(Int16Testable(-28782)) + ), + test( + "zeros", + Int16.mulWrap(0, 0), + M.equals(Int16Testable(0)) + ), + test( + "zero and maximum", + Int16.mulWrap(0, Int16.maximumValue), + M.equals(Int16Testable(0)) + ), + test( + "minimum and zero", + Int16.mulWrap(Int16.minimumValue, 0), + M.equals(Int16Testable(0)) + ), + test( + "one and maximum", + Int16.mulWrap(1, Int16.maximumValue), + M.equals(Int16Testable(Int16.maximumValue)) + ), + test( + "minimum and one", + Int16.mulWrap(Int16.minimumValue, 1), + M.equals(Int16Testable(Int16.minimumValue)) + ), + test( + "small overflow", + Int16.mulWrap(2, Int16.maximumValue), + M.equals(Int16Testable(-2)) + ), + test( + "large overflow", + Int16.mulWrap(Int16.maximumValue, Int16.maximumValue), + M.equals(Int16Testable(1)) + ), + test( + "small underflow", + Int16.mulWrap(Int16.minimumValue, 2), + M.equals(Int16Testable(0)) + ), + test( + "large underflow", + Int16.mulWrap(Int16.minimumValue, Int16.minimumValue), + M.equals(Int16Testable(0)) + ), + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "powWrap", + [ + test( + "positive base, positive exponent", + Int16.powWrap(24, 3), + M.equals(Int16Testable(13824)) + ), + test( + "positive base, zero exponent", + Int16.powWrap(24, 0), + M.equals(Int16Testable(1)) + ), + test( + "negative base, positive exponent", + Int16.powWrap(-24, 3), + M.equals(Int16Testable(-13824)) + ), + test( + "negative base, zero exponent", + Int16.powWrap(-24, 0), + M.equals(Int16Testable(1)) + ), + test( + "maximum and zero", + Int16.powWrap(Int16.maximumValue, 0), + M.equals(Int16Testable(1)) + ), + test( + "minimum and zero", + Int16.powWrap(Int16.minimumValue, 0), + M.equals(Int16Testable(1)) + ), + test( + "plus one and maximum", + Int16.powWrap(1, Int16.maximumValue), + M.equals(Int16Testable(1)) + ), + test( + "minus one and maximum", + Int16.powWrap(-1, Int16.maximumValue), + M.equals(Int16Testable(-1)) + ), + test( + "minimum value", + Int16.powWrap(-2, 15), + M.equals(Int16Testable(Int16.minimumValue)) + ), + test( + "small overflow", + Int16.powWrap(2, 15), + M.equals(Int16Testable(Int16.minimumValue)) + ), + test( + "large overflow", + Int16.powWrap(Int16.maximumValue, 10), + M.equals(Int16Testable(1)) + ), + test( + "small underflow", + Int16.powWrap(-2, 17), + M.equals(Int16Testable(0)) + ), + test( + "large underflow", + Int16.powWrap(Int16.minimumValue, 10), + M.equals(Int16Testable(0)) + ), + ] + ) +) diff --git a/test/int32Test.mo b/test/int32Test.mo new file mode 100644 index 00000000..682548ff --- /dev/null +++ b/test/int32Test.mo @@ -0,0 +1,2303 @@ +import Int32 "mo:base/Int32"; +import Order "mo:base/Order"; +import Iter "mo:base/Iter"; + +import Suite "mo:matchers/Suite"; +import T "mo:matchers/Testable"; +import M "mo:matchers/Matchers"; + +let { run; test; suite } = Suite; + +let maximumInt32asInt = +2 ** 31 - 1 : Int; +let maximumInt32asNat32 = 2 ** 31 - 1 : Nat32; + +let minimumInt32asInt = -2 ** 31 : Int; + +let maximumNat32 = 4_294_967_295 : Nat32; + +class Int32Testable(number : Int32) : T.TestableItem { + public let item = number; + public func display(number : Int32) : Text { + debug_show (number) + }; + public let equals = func(x : Int32, y : Int32) : Bool { + x == y + } +}; + +class Nat32Testable(number : Nat32) : T.TestableItem { + public let item = number; + public func display(number : Nat32) : Text { + debug_show (number) + }; + public let equals = func(x : Nat32, y : Nat32) : Bool { + x == y + } +}; + +type Order = { #less; #equal; #greater }; + +class OrderTestable(value : Order) : T.TestableItem { + public let item = value; + public func display(value : Order) : Text { + debug_show (value) + }; + public let equals = func(x : Order, y : Order) : Bool { + x == y + } +}; + +/* --------------------------------------- */ + +run( + suite( + "constants", + [ + test( + "minimum value", + Int32.minimumValue, + M.equals(Int32Testable(Int32.fromInt(-2 ** 31))) + ), + test( + "maximum value", + Int32.maximumValue, + M.equals(Int32Testable(Int32.fromInt(+2 ** 31 - 1))) + ), + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "toInt", + [ + test( + "maximum number", + Int32.toInt(Int32.maximumValue), + M.equals(T.int(maximumInt32asInt)) + ), + test( + "minimum number", + Int32.toInt(Int32.minimumValue), + M.equals(T.int(minimumInt32asInt)) + ), + test( + "one", + Int32.toInt(1), + M.equals(T.int(1)) + ), + test( + "minus one", + Int32.toInt(-1), + M.equals(T.int(-1)) + ), + test( + "zero", + Int32.toInt(0), + M.equals(T.int(0)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "fromInt", + [ + test( + "maximum number", + Int32.fromInt(maximumInt32asInt), + M.equals(Int32Testable(Int32.maximumValue)) + ), + test( + "minimum number", + Int32.fromInt(minimumInt32asInt), + M.equals(Int32Testable(Int32.minimumValue)) + ), + test( + "one", + Int32.fromInt(1), + M.equals(Int32Testable(1)) + ), + test( + "minus one", + Int32.fromInt(-1), + M.equals(Int32Testable(-1)) + ), + test( + "zero", + Int32.fromInt(0), + M.equals(Int32Testable(0)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "fromIntWrap", + [ + test( + "maximum number", + Int32.fromIntWrap(maximumInt32asInt), + M.equals(Int32Testable(Int32.maximumValue)) + ), + test( + "minimum number", + Int32.fromIntWrap(minimumInt32asInt), + M.equals(Int32Testable(Int32.minimumValue)) + ), + test( + "one", + Int32.fromIntWrap(1), + M.equals(Int32Testable(1)) + ), + test( + "minus one", + Int32.fromIntWrap(-1), + M.equals(Int32Testable(-1)) + ), + test( + "zero", + Int32.fromIntWrap(0), + M.equals(Int32Testable(0)) + ), + test( + "overflow", + Int32.fromIntWrap(maximumInt32asInt + 1), + M.equals(Int32Testable(Int32.minimumValue)) + ), + test( + "underflow", + Int32.fromIntWrap(minimumInt32asInt - 1), + M.equals(Int32Testable(Int32.maximumValue)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "fromNat32", + [ + test( + "maximum number", + Int32.fromNat32(maximumInt32asNat32), + M.equals(Int32Testable(Int32.maximumValue)) + ), + test( + "one", + Int32.fromNat32(1), + M.equals(Int32Testable(1)) + ), + test( + "zero", + Int32.fromNat32(0), + M.equals(Int32Testable(0)) + ), + test( + "overflow", + Int32.fromNat32(maximumInt32asNat32 + 1), + M.equals(Int32Testable(Int32.minimumValue)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "toNat32", + [ + test( + "maximum number", + Int32.toNat32(Int32.maximumValue), + M.equals(Nat32Testable(maximumInt32asNat32)) + ), + test( + "one", + Int32.toNat32(1), + M.equals(Nat32Testable(1)) + ), + test( + "zero", + Int32.toNat32(0), + M.equals(Nat32Testable(0)) + ), + test( + "underflow", + Int32.toNat32(-1), + M.equals(Nat32Testable(maximumNat32)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "toText", + [ + test( + "positive", + Int32.toText(123456), + M.equals(T.text("123456")) + ), + test( + "negative", + Int32.toText(-123456), + M.equals(T.text("-123456")) + ), + test( + "zero", + Int32.toText(0), + M.equals(T.text("0")) + ), + test( + "maximum number", + Int32.toText(Int32.maximumValue), + M.equals(T.text("2147483647")) + ), + test( + "minimum number", + Int32.toText(Int32.minimumValue), + M.equals(T.text("-2147483648")) + ) + ] + ) +); + + +/* --------------------------------------- */ + +run( + suite( + "abs", + [ + test( + "positive number", + Int32.abs(123), + M.equals(Int32Testable(123)) + ), + test( + "negative number", + Int32.abs(-123), + M.equals(Int32Testable(123)) + ), + test( + "zero", + Int32.abs(0), + M.equals(Int32Testable(0)) + ), + test( + "maximum number", + Int32.abs(Int32.maximumValue), + M.equals(Int32Testable(Int32.maximumValue)) + ), + test( + "smallest possible", + Int32.abs(-Int32.maximumValue), + M.equals(Int32Testable(Int32.maximumValue)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "min", + [ + test( + "both positive", + Int32.min(2, 3), + M.equals(Int32Testable(2)) + ), + test( + "positive, negative", + Int32.min(2, -3), + M.equals(Int32Testable(-3)) + ), + test( + "both negative", + Int32.min(-2, -3), + M.equals(Int32Testable(-3)) + ), + test( + "negative, positive", + Int32.min(-2, 3), + M.equals(Int32Testable(-2)) + ), + test( + "equal values", + Int32.min(123, 123), + M.equals(Int32Testable(123)) + ), + test( + "maximum and minimum number", + Int32.min(Int32.maximumValue, Int32.minimumValue), + M.equals(Int32Testable(Int32.minimumValue)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "max", + [ + test( + "both positive", + Int32.max(2, 3), + M.equals(Int32Testable(3)) + ), + test( + "positive, negative", + Int32.max(2, -3), + M.equals(Int32Testable(2)) + ), + test( + "both negative", + Int32.max(-2, -3), + M.equals(Int32Testable(-2)) + ), + test( + "negative, positive", + Int32.max(-2, 3), + M.equals(Int32Testable(3)) + ), + test( + "equal values", + Int32.max(123, 123), + M.equals(Int32Testable(123)) + ), + test( + "maximum and minimum number", + Int32.max(Int32.maximumValue, Int32.minimumValue), + M.equals(Int32Testable(Int32.maximumValue)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "equal", + [ + test( + "positive equal", + Int32.equal(123, 123), + M.equals(T.bool(true)) + ), + test( + "negative equal", + Int32.equal(-123, -123), + M.equals(T.bool(true)) + ), + test( + "zero", + Int32.equal(0, 0), + M.equals(T.bool(true)) + ), + test( + "positive not equal", + Int32.equal(123, 124), + M.equals(T.bool(false)) + ), + test( + "negative not equal", + Int32.equal(-123, -124), + M.equals(T.bool(false)) + ), + test( + "mixed signs", + Int32.equal(123, -123), + M.equals(T.bool(false)) + ), + test( + "maxmimum equal", + Int32.equal(Int32.maximumValue, Int32.maximumValue), + M.equals(T.bool(true)) + ), + test( + "minimum equal", + Int32.equal(Int32.minimumValue, Int32.minimumValue), + M.equals(T.bool(true)) + ), + test( + "minimum and maximum", + Int32.equal(Int32.minimumValue, Int32.maximumValue), + M.equals(T.bool(false)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "notEqual", + [ + test( + "positive equal", + Int32.notEqual(123, 123), + M.equals(T.bool(false)) + ), + test( + "negative equal", + Int32.notEqual(-123, -123), + M.equals(T.bool(false)) + ), + test( + "zero", + Int32.notEqual(0, 0), + M.equals(T.bool(false)) + ), + test( + "positive not equal", + Int32.notEqual(123, 124), + M.equals(T.bool(true)) + ), + test( + "negative not equal", + Int32.notEqual(-123, -124), + M.equals(T.bool(true)) + ), + test( + "mixed signs", + Int32.notEqual(123, -123), + M.equals(T.bool(true)) + ), + test( + "maxmimum equal", + Int32.notEqual(Int32.maximumValue, Int32.maximumValue), + M.equals(T.bool(false)) + ), + test( + "minimum equal", + Int32.notEqual(Int32.minimumValue, Int32.minimumValue), + M.equals(T.bool(false)) + ), + test( + "minimum and maximum", + Int32.notEqual(Int32.minimumValue, Int32.maximumValue), + M.equals(T.bool(true)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "less", + [ + test( + "positive equal", + Int32.less(123, 123), + M.equals(T.bool(false)) + ), + test( + "positive less", + Int32.less(123, 245), + M.equals(T.bool(true)) + ), + test( + "positive greater", + Int32.less(245, 123), + M.equals(T.bool(false)) + ), + test( + "negative equal", + Int32.less(-123, -123), + M.equals(T.bool(false)) + ), + test( + "negative less", + Int32.less(-245, -123), + M.equals(T.bool(true)) + ), + test( + "negative greater", + Int32.less(-123, -245), + M.equals(T.bool(false)) + ), + test( + "zero", + Int32.less(0, 0), + M.equals(T.bool(false)) + ), + test( + "mixed signs less", + Int32.less(-123, 123), + M.equals(T.bool(true)) + ), + test( + "mixed signs greater", + Int32.less(123, -123), + M.equals(T.bool(false)) + ), + test( + "minimum and maximum", + Int32.less(Int32.minimumValue, Int32.maximumValue), + M.equals(T.bool(true)) + ), + test( + "maximum and minimum", + Int32.less(Int32.maximumValue, Int32.minimumValue), + M.equals(T.bool(false)) + ), + test( + "maximum and maximum", + Int32.less(Int32.maximumValue, Int32.maximumValue), + M.equals(T.bool(false)) + ), + test( + "minimum and minimum", + Int32.less(Int32.minimumValue, Int32.minimumValue), + M.equals(T.bool(false)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "lessOrEqual", + [ + test( + "positive equal", + Int32.lessOrEqual(123, 123), + M.equals(T.bool(true)) + ), + test( + "positive less", + Int32.lessOrEqual(123, 245), + M.equals(T.bool(true)) + ), + test( + "positive greater", + Int32.lessOrEqual(245, 123), + M.equals(T.bool(false)) + ), + test( + "negative equal", + Int32.lessOrEqual(-123, -123), + M.equals(T.bool(true)) + ), + test( + "negative less", + Int32.lessOrEqual(-245, -123), + M.equals(T.bool(true)) + ), + test( + "negative greater", + Int32.lessOrEqual(-123, -245), + M.equals(T.bool(false)) + ), + test( + "zero", + Int32.lessOrEqual(0, 0), + M.equals(T.bool(true)) + ), + test( + "mixed signs less", + Int32.lessOrEqual(-123, 123), + M.equals(T.bool(true)) + ), + test( + "mixed signs greater", + Int32.lessOrEqual(123, -123), + M.equals(T.bool(false)) + ), + test( + "minimum and maximum", + Int32.lessOrEqual(Int32.minimumValue, Int32.maximumValue), + M.equals(T.bool(true)) + ), + test( + "maximum and minimum", + Int32.lessOrEqual(Int32.maximumValue, Int32.minimumValue), + M.equals(T.bool(false)) + ), + test( + "maximum and maximum", + Int32.lessOrEqual(Int32.maximumValue, Int32.maximumValue), + M.equals(T.bool(true)) + ), + test( + "minimum and minimum", + Int32.lessOrEqual(Int32.minimumValue, Int32.minimumValue), + M.equals(T.bool(true)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "greater", + [ + test( + "positive equal", + Int32.greater(123, 123), + M.equals(T.bool(false)) + ), + test( + "positive less", + Int32.greater(123, 245), + M.equals(T.bool(false)) + ), + test( + "positive greater", + Int32.greater(245, 123), + M.equals(T.bool(true)) + ), + test( + "negative equal", + Int32.greater(-123, -123), + M.equals(T.bool(false)) + ), + test( + "negative less", + Int32.greater(-245, -123), + M.equals(T.bool(false)) + ), + test( + "negative greater", + Int32.greater(-123, -245), + M.equals(T.bool(true)) + ), + test( + "zero", + Int32.greater(0, 0), + M.equals(T.bool(false)) + ), + test( + "mixed signs less", + Int32.greater(-123, 123), + M.equals(T.bool(false)) + ), + test( + "mixed signs greater", + Int32.greater(123, -123), + M.equals(T.bool(true)) + ), + test( + "minimum and maximum", + Int32.greater(Int32.minimumValue, Int32.maximumValue), + M.equals(T.bool(false)) + ), + test( + "maximum and minimum", + Int32.greater(Int32.maximumValue, Int32.minimumValue), + M.equals(T.bool(true)) + ), + test( + "maximum and maximum", + Int32.greater(Int32.maximumValue, Int32.maximumValue), + M.equals(T.bool(false)) + ), + test( + "minimum and minimum", + Int32.greater(Int32.minimumValue, Int32.minimumValue), + M.equals(T.bool(false)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "greaterOrEqual", + [ + test( + "positive equal", + Int32.greaterOrEqual(123, 123), + M.equals(T.bool(true)) + ), + test( + "positive less", + Int32.greaterOrEqual(123, 245), + M.equals(T.bool(false)) + ), + test( + "positive greater", + Int32.greaterOrEqual(245, 123), + M.equals(T.bool(true)) + ), + test( + "negative equal", + Int32.greaterOrEqual(-123, -123), + M.equals(T.bool(true)) + ), + test( + "negative less", + Int32.greaterOrEqual(-245, -123), + M.equals(T.bool(false)) + ), + test( + "negative greater", + Int32.greaterOrEqual(-123, -245), + M.equals(T.bool(true)) + ), + test( + "zero", + Int32.greaterOrEqual(0, 0), + M.equals(T.bool(true)) + ), + test( + "mixed signs less", + Int32.greaterOrEqual(-123, 123), + M.equals(T.bool(false)) + ), + test( + "mixed signs greater", + Int32.greaterOrEqual(123, -123), + M.equals(T.bool(true)) + ), + test( + "minimum and maximum", + Int32.greaterOrEqual(Int32.minimumValue, Int32.maximumValue), + M.equals(T.bool(false)) + ), + test( + "maximum and minimum", + Int32.greaterOrEqual(Int32.maximumValue, Int32.minimumValue), + M.equals(T.bool(true)) + ), + test( + "maximum and maximum", + Int32.greaterOrEqual(Int32.maximumValue, Int32.maximumValue), + M.equals(T.bool(true)) + ), + test( + "minimum and minimum", + Int32.greaterOrEqual(Int32.minimumValue, Int32.minimumValue), + M.equals(T.bool(true)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "compare", + [ + test( + "positive equal", + Int32.compare(123, 123), + M.equals(OrderTestable(#equal)) + ), + test( + "positive less", + Int32.compare(123, 245), + M.equals(OrderTestable(#less)) + ), + test( + "positive greater", + Int32.compare(245, 123), + M.equals(OrderTestable(#greater)) + ), + test( + "negative equal", + Int32.compare(-123, -123), + M.equals(OrderTestable(#equal)) + ), + test( + "negative less", + Int32.compare(-245, -123), + M.equals(OrderTestable(#less)) + ), + test( + "negative greater", + Int32.compare(-123, -245), + M.equals(OrderTestable(#greater)) + ), + test( + "zero", + Int32.compare(0, 0), + M.equals(OrderTestable(#equal)) + ), + test( + "mixed signs less", + Int32.compare(-123, 123), + M.equals(OrderTestable(#less)) + ), + test( + "mixed signs greater", + Int32.compare(123, -123), + M.equals(OrderTestable(#greater)) + ), + test( + "minimum and maximum", + Int32.compare(Int32.minimumValue, Int32.maximumValue), + M.equals(OrderTestable(#less)) + ), + test( + "maximum and minimum", + Int32.compare(Int32.maximumValue, Int32.minimumValue), + M.equals(OrderTestable(#greater)) + ), + test( + "maximum and maximum", + Int32.compare(Int32.maximumValue, Int32.maximumValue), + M.equals(OrderTestable(#equal)) + ), + test( + "minimum and minimum", + Int32.compare(Int32.minimumValue, Int32.minimumValue), + M.equals(OrderTestable(#equal)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "neg", + [ + test( + "positive number", + Int32.neg(123), + M.equals(Int32Testable(-123)) + ), + test( + "negative number", + Int32.neg(-123), + M.equals(Int32Testable(123)) + ), + test( + "zero", + Int32.neg(0), + M.equals(Int32Testable(0)) + ), + test( + "maximum number", + Int32.neg(Int32.maximumValue), + M.equals(Int32Testable(-Int32.maximumValue)) + ), + test( + "smallest possible", + Int32.neg(-Int32.maximumValue), + M.equals(Int32Testable(Int32.maximumValue)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "add", + [ + test( + "positive", + Int32.add(123, 123), + M.equals(Int32Testable(246)) + ), + test( + "negative", + Int32.add(-123, -123), + M.equals(Int32Testable(-246)) + ), + test( + "mixed signs", + Int32.add(-123, 223), + M.equals(Int32Testable(100)) + ), + test( + "zero", + Int32.add(0, 0), + M.equals(Int32Testable(0)) + ), + test( + "minimum and maximum", + Int32.add(Int32.minimumValue, Int32.maximumValue), + M.equals(Int32Testable(-1)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "sub", + [ + test( + "positive", + Int32.sub(123, 123), + M.equals(Int32Testable(0)) + ), + test( + "negative", + Int32.sub(-123, -123), + M.equals(Int32Testable(0)) + ), + test( + "mixed signs", + Int32.sub(-123, 223), + M.equals(Int32Testable(-346)) + ), + test( + "zero", + Int32.sub(0, 0), + M.equals(Int32Testable(0)) + ), + test( + "maximum and maximum", + Int32.sub(Int32.maximumValue, Int32.maximumValue), + M.equals(Int32Testable(0)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "mul", + [ + test( + "positive", + Int32.mul(123, 234), + M.equals(Int32Testable(28782)) + ), + test( + "negative", + Int32.mul(-123, -234), + M.equals(Int32Testable(28782)) + ), + test( + "mixed signs", + Int32.mul(-123, 234), + M.equals(Int32Testable(-28782)) + ), + test( + "zeros", + Int32.mul(0, 0), + M.equals(Int32Testable(0)) + ), + test( + "zero and maximum", + Int32.mul(0, Int32.maximumValue), + M.equals(Int32Testable(0)) + ), + test( + "minimum and zero", + Int32.mul(Int32.minimumValue, 0), + M.equals(Int32Testable(0)) + ), + test( + "one and maximum", + Int32.mul(1, Int32.maximumValue), + M.equals(Int32Testable(Int32.maximumValue)) + ), + test( + "minimum and one", + Int32.mul(Int32.minimumValue, 1), + M.equals(Int32Testable(Int32.minimumValue)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "div", + [ + test( + "positive multiple", + Int32.div(156, 13), + M.equals(Int32Testable(12)) + ), + test( + "positive remainder", + Int32.div(1234, 100), + M.equals(Int32Testable(12)) + ), + test( + "negative multiple", + Int32.div(-156, -13), + M.equals(Int32Testable(12)) + ), + test( + "negative remainder", + Int32.div(-1234, -100), + M.equals(Int32Testable(12)) + ), + test( + "mixed signs", + Int32.div(-123, 23), + M.equals(Int32Testable(-5)) + ), + test( + "zero and number", + Int32.div(0, -123), + M.equals(Int32Testable(0)) + ), + test( + "zero and maximum", + Int32.div(0, Int32.maximumValue), + M.equals(Int32Testable(0)) + ), + test( + "zero and minimum", + Int32.div(0, Int32.minimumValue), + M.equals(Int32Testable(0)) + ), + test( + "maximum and maximum", + Int32.div(Int32.maximumValue, Int32.maximumValue), + M.equals(Int32Testable(1)) + ), + test( + "minimum and minimum", + Int32.div(Int32.minimumValue, Int32.minimumValue), + M.equals(Int32Testable(1)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "rem", + [ + test( + "positive multiple", + Int32.rem(156, 13), + M.equals(Int32Testable(0)) + ), + test( + "positive/positive remainder", + Int32.rem(1234, 100), + M.equals(Int32Testable(34)) + ), + test( + "positive/negative remainder", + Int32.rem(1234, -100), + M.equals(Int32Testable(34)) + ), + test( + "negative multiple", + Int32.rem(-156, -13), + M.equals(Int32Testable(0)) + ), + test( + "negative/positive remainder", + Int32.rem(-1234, 100), + M.equals(Int32Testable(-34)) + ), + test( + "negative/negative remainder", + Int32.rem(-1234, -100), + M.equals(Int32Testable(-34)) + ), + test( + "zero and maximum", + Int32.rem(0, Int32.maximumValue), + M.equals(Int32Testable(0)) + ), + test( + "zero and minimum", + Int32.rem(0, Int32.minimumValue), + M.equals(Int32Testable(0)) + ), + test( + "maximum and maximum", + Int32.rem(Int32.maximumValue, Int32.maximumValue), + M.equals(Int32Testable(0)) + ), + test( + "minimum and minimum", + Int32.rem(Int32.minimumValue, Int32.minimumValue), + M.equals(Int32Testable(0)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "pow", + [ + test( + "positive base, positive exponent", + Int32.pow(72, 3), + M.equals(Int32Testable(373248)) + ), + test( + "positive base, zero exponent", + Int32.pow(72, 0), + M.equals(Int32Testable(1)) + ), + test( + "negative base, odd exponent", + Int32.pow(-72, 3), + M.equals(Int32Testable(-373248)) + ), + test( + "negative base, even exponent", + Int32.pow(-72, 2), + M.equals(Int32Testable(5184)) + ), + test( + "negative base, zero exponent", + Int32.pow(-72, 0), + M.equals(Int32Testable(1)) + ), + test( + "maximum and zero", + Int32.pow(Int32.maximumValue, 0), + M.equals(Int32Testable(1)) + ), + test( + "minimum and zero", + Int32.pow(Int32.minimumValue, 0), + M.equals(Int32Testable(1)) + ), + test( + "plus one and maximum", + Int32.pow(1, Int32.maximumValue), + M.equals(Int32Testable(1)) + ), + test( + "minus one and maximum", + Int32.pow(-1, Int32.maximumValue), + M.equals(Int32Testable(-1)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitnot", + [ + test( + "zero", + Int32.bitnot(0), + M.equals(Int32Testable(-1)) + ), + test( + "minus 1", + Int32.bitnot(-1), + M.equals(Int32Testable(0)) + ), + test( + "maximum", + Int32.bitnot(Int32.maximumValue), + M.equals(Int32Testable(Int32.minimumValue)) + ), + test( + "minimum", + Int32.bitnot(Int32.minimumValue), + M.equals(Int32Testable(Int32.maximumValue)) + ), + test( + "arbitrary", + Int32.bitnot(1234), + M.equals(Int32Testable(-1235)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitand", + [ + test( + "inverted", + Int32.bitand(0xf0f0, 0x0f0f), + M.equals(Int32Testable(0)) + ), + test( + "overlap", + Int32.bitand(0x0ff0, 0xffff), + M.equals(Int32Testable(0xff0)) + ), + test( + "arbitrary", + Int32.bitand(0x1234_5678, 0x7654_3210), + M.equals(Int32Testable(0x1214_1210)) + ), + test( + "negative", + Int32.bitand(-123, -123), + M.equals(Int32Testable(-123)) + ), + test( + "mixed signs", + Int32.bitand(-256, 255), + M.equals(Int32Testable(0)) + ), + test( + "zero", + Int32.bitand(0, 0), + M.equals(Int32Testable(0)) + ), + test( + "zero and maximum", + Int32.bitand(0, Int32.maximumValue), + M.equals(Int32Testable(0)) + ), + test( + "minimum and zero", + Int32.bitand(Int32.minimumValue, 0), + M.equals(Int32Testable(0)) + ), + test( + "minimum and maximum", + Int32.bitand(Int32.minimumValue, Int32.maximumValue), + M.equals(Int32Testable(0)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitor", + [ + test( + "inverted", + Int32.bitor(0xf0f0, 0x0f0f), + M.equals(Int32Testable(0xffff)) + ), + test( + "overlap", + Int32.bitor(0x0ff0, 0xffff), + M.equals(Int32Testable(0xffff)) + ), + test( + "arbitrary", + Int32.bitor(0x1234_5678, 0x7654_3210), + M.equals(Int32Testable(0x7674_7678)) + ), + test( + "negative", + Int32.bitor(-123, -123), + M.equals(Int32Testable(-123)) + ), + test( + "mixed signs", + Int32.bitor(-256, 255), + M.equals(Int32Testable(-1)) + ), + test( + "zero", + Int32.bitor(0, 0), + M.equals(Int32Testable(0)) + ), + test( + "zero and maximum", + Int32.bitor(0, Int32.maximumValue), + M.equals(Int32Testable(Int32.maximumValue)) + ), + test( + "minimum and zero", + Int32.bitor(Int32.minimumValue, 0), + M.equals(Int32Testable(Int32.minimumValue)) + ), + test( + "minimum and maximum", + Int32.bitor(Int32.minimumValue, Int32.maximumValue), + M.equals(Int32Testable(-1)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitxor", + [ + test( + "inverted", + Int32.bitxor(0xf0f0, 0x0f0f), + M.equals(Int32Testable(0xffff)) + ), + test( + "overlap", + Int32.bitxor(0x0ff0, 0xffff), + M.equals(Int32Testable(0xf00f)) + ), + test( + "arbitrary", + Int32.bitxor(0x1234_5678, 0x7654_3210), + M.equals(Int32Testable(0x6460_6468)) + ), + test( + "negative", + Int32.bitxor(-123, -123), + M.equals(Int32Testable(0)) + ), + test( + "mixed signs", + Int32.bitxor(-256, 255), + M.equals(Int32Testable(-1)) + ), + test( + "zero", + Int32.bitxor(0, 0), + M.equals(Int32Testable(0)) + ), + test( + "zero and maximum", + Int32.bitxor(0, Int32.maximumValue), + M.equals(Int32Testable(Int32.maximumValue)) + ), + test( + "minimum and zero", + Int32.bitxor(Int32.minimumValue, 0), + M.equals(Int32Testable(Int32.minimumValue)) + ), + test( + "minimum and maximum", + Int32.bitxor(Int32.minimumValue, Int32.maximumValue), + M.equals(Int32Testable(-1)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitshiftLeft", + [ + test( + "positive number", + Int32.bitshiftLeft(0xf0f0, 4), + M.equals(Int32Testable(0xf_0f00)) + ), + test( + "negative number", + Int32.bitshiftLeft(-256, 4), + M.equals(Int32Testable(-4096)) + ), + test( + "arbitrary", + Int32.bitshiftLeft(1234_5678, 7), + M.equals(Int32Testable(1_580_246_784)) + ), + test( + "zero shift", + Int32.bitshiftLeft(1234, 0), + M.equals(Int32Testable(1234)) + ), + test( + "one maximum shift", + Int32.bitshiftLeft(1, 31), + M.equals(Int32Testable(Int32.minimumValue)) + ), + test( + "minimum number", + Int32.bitshiftLeft(-1, 31), + M.equals(Int32Testable(Int32.minimumValue)) + ), + test( + "discard overflow", + Int32.bitshiftLeft(0x7fff_0000, 16), + M.equals(Int32Testable(0)) + ), + test( + "beyond bit length positive", + Int32.bitshiftLeft(0x1234_5678, 64 + 7), + M.equals(Int32Testable(Int32.bitshiftLeft(0x1234_5678, 7))) + ), + test( + "beyond bit length negative", + Int32.bitshiftLeft(-0x1234_5678, 32 + 7), + M.equals(Int32Testable(Int32.bitshiftLeft(-0x1234_5678, 7))) + ), + test( + "negative shift argument", + Int32.bitshiftLeft(0x1234_5678, -7), + M.equals(Int32Testable(Int32.bitshiftLeft(0x1234_5678, 32 - 7))) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitshiftRight", + [ + test( + "positive number", + Int32.bitshiftRight(0xf0f0, 4), + M.equals(Int32Testable(0x0f0f)) + ), + test( + "negative number", + Int32.bitshiftRight(-256, 4), + M.equals(Int32Testable(-16)) + ), + test( + "arbitrary", + Int32.bitshiftRight(1234_5678, 7), + M.equals(Int32Testable(96_450)) + ), + test( + "zero shift", + Int32.bitshiftRight(1234, 0), + M.equals(Int32Testable(1234)) + ), + test( + "minus one maximum shift", + Int32.bitshiftRight(-1, 31), + M.equals(Int32Testable(-1)) + ), + test( + "minimum number", + Int32.bitshiftRight(Int32.minimumValue, 31), + M.equals(Int32Testable(-1)) + ), + test( + "discard underflow", + Int32.bitshiftRight(0x0000_ffff, 16), + M.equals(Int32Testable(0)) + ), + test( + "beyond bit length positive", + Int32.bitshiftRight(0x1234_5678, 64 + 7), + M.equals(Int32Testable(Int32.bitshiftRight(0x1234_5678, 7))) + ), + test( + "beyond bit length negative", + Int32.bitshiftRight(-0x1234_5678, 32 + 7), + M.equals(Int32Testable(Int32.bitshiftRight(-0x1234_5678, 7))) + ), + test( + "negative shift argument", + Int32.bitshiftRight(0x1234_5678, -7), + M.equals(Int32Testable(Int32.bitshiftRight(0x1234_5678, 32 - 7))) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitrotLeft", + [ + test( + "positive number non-overflow", + Int32.bitrotLeft(0xf0f0, 4), + M.equals(Int32Testable(0xf_0f00)) + ), + test( + "positive number overflow", + Int32.bitrotLeft(0x5600_1234, 8), + M.equals(Int32Testable(0x12_3456)) + ), + test( + "negative number", + Int32.bitrotLeft(-256, 4), + M.equals(Int32Testable(-4081)) + ), + test( + "arbitrary", + Int32.bitrotLeft(1_234_567_890, 7), + M.equals(Int32Testable(-889_099_996)) + ), + test( + "zero shift", + Int32.bitrotLeft(1234, 0), + M.equals(Int32Testable(1234)) + ), + test( + "minus one maximum rotate", + Int32.bitrotLeft(-1, 31), + M.equals(Int32Testable(-1)) + ), + test( + "maximum number", + Int32.bitrotLeft(Int32.maximumValue, 1), + M.equals(Int32Testable(-2)) + ), + test( + "minimum number", + Int32.bitrotLeft(1, 31), + M.equals(Int32Testable(Int32.minimumValue)) + ), + test( + "opposite rotation", + Int32.bitrotLeft(256, -2), + M.equals(Int32Testable(64)) + ), + test( + "rotate beyond bit length", + Int32.bitrotLeft(128, 34), + M.equals(Int32Testable(512)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitrotRight", + [ + test( + "positive number non-underflow", + Int32.bitrotRight(0xf0f0, 4), + M.equals(Int32Testable(0x0f0f)) + ), + test( + "positive number underflow", + Int32.bitrotRight(0x5600_1234, 8), + M.equals(Int32Testable(0x3456_0012)) + ), + test( + "negative number", + Int32.bitrotRight(-256, 8), + M.equals(Int32Testable(0x00ff_ffff)) + ), + test( + "arbitrary", + Int32.bitrotRight(1_234_567_890, 7), + M.equals(Int32Testable(-1_533_858_811)) + ), + test( + "zero shift", + Int32.bitrotRight(1234, 0), + M.equals(Int32Testable(1234)) + ), + test( + "minus one maximum rotate", + Int32.bitrotRight(-1, 31), + M.equals(Int32Testable(-1)) + ), + test( + "maximum number", + Int32.bitrotRight(-2, 1), + M.equals(Int32Testable(Int32.maximumValue)) + ), + test( + "minimum number", + Int32.bitrotRight(Int32.minimumValue, 31), + M.equals(Int32Testable(1)) + ), + test( + "opposite rotation", + Int32.bitrotRight(256, -2), + M.equals(Int32Testable(1024)) + ), + test( + "rotate beyond bit length", + Int32.bitrotRight(128, 34), + M.equals(Int32Testable(32)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bittest", + [ + test( + "set bit", + Int32.bittest(128, 7), + M.equals(T.bool(true)) + ), + test( + "cleared bit", + Int32.bittest(-129, 7), + M.equals(T.bool(false)) + ), + test( + "all zero", + do { + let number = 0 : Int32; + var count = 0; + for (index in Iter.range(0, 31)) { + if (Int32.bittest(number, index)) { + count += 1 + } + }; + count + }, + M.equals(T.int(0)) + ), + test( + "all one", + do { + let number = -1 : Int32; + var count = 0; + for (index in Iter.range(0, 31)) { + if (Int32.bittest(number, index)) { + count += 1 + } + }; + count + }, + M.equals(T.int(32)) + ), + test( + "set bit beyond bit length", + Int32.bittest(128, 32 + 7), + M.equals(T.bool(true)) + ), + test( + "cleared bit beyond bit length", + Int32.bittest(-129, 64 + 7), + M.equals(T.bool(false)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitset", + [ + test( + "set bit", + Int32.bitset(0, 7), + M.equals(Int32Testable(128)) + ), + test( + "minus one", + Int32.bitset(-129, 7), + M.equals(Int32Testable(-1)) + ), + test( + "no effect", + Int32.bitset(128, 7), + M.equals(Int32Testable(128)) + ), + test( + "set all", + do { + var number = 0 : Int32; + for (index in Iter.range(0, 31)) { + number := Int32.bitset(number, index) + }; + number + }, + M.equals(Int32Testable(-1)) + ), + test( + "all no effect", + do { + var number = -1 : Int32; + for (index in Iter.range(0, 31)) { + number := Int32.bitset(number, index) + }; + number + }, + M.equals(Int32Testable(-1)) + ), + test( + "set bit beyond bit length", + Int32.bitset(0, 32 + 7), + M.equals(Int32Testable(128)) + ), + test( + "minus one beyond bit length", + Int32.bitset(-129, 64 + 7), + M.equals(Int32Testable(-1)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitclear", + [ + test( + "clear bit", + Int32.bitclear(128, 7), + M.equals(Int32Testable(0)) + ), + test( + "minus one", + Int32.bitclear(-1, 7), + M.equals(Int32Testable(-129)) + ), + test( + "no effect", + Int32.bitclear(0, 7), + M.equals(Int32Testable(0)) + ), + test( + "clear all", + do { + var number = -1 : Int32; + for (index in Iter.range(0, 31)) { + number := Int32.bitclear(number, index) + }; + number + }, + M.equals(Int32Testable(0)) + ), + test( + "all no effect", + do { + var number = 0 : Int32; + for (index in Iter.range(0, 31)) { + number := Int32.bitclear(number, index) + }; + number + }, + M.equals(Int32Testable(0)) + ), + test( + "clear bit beyond bit length", + Int32.bitclear(128, 32 + 7), + M.equals(Int32Testable(0)) + ), + test( + "minus one beyond bit length", + Int32.bitclear(-1, 64 + 7), + M.equals(Int32Testable(-129)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitflip", + [ + test( + "clear bit", + Int32.bitflip(255, 7), + M.equals(Int32Testable(127)) + ), + test( + "set bit", + Int32.bitflip(127, 7), + M.equals(Int32Testable(255)) + ), + test( + "double flip", + Int32.bitflip(Int32.bitflip(0x1234_5678, 13), 13), + M.equals(Int32Testable(0x1234_5678)) + ), + test( + "clear all", + do { + var number = -1 : Int32; + for (index in Iter.range(0, 31)) { + number := Int32.bitflip(number, index) + }; + number + }, + M.equals(Int32Testable(0)) + ), + test( + "set all", + do { + var number = 0 : Int32; + for (index in Iter.range(0, 31)) { + number := Int32.bitflip(number, index) + }; + number + }, + M.equals(Int32Testable(-1)) + ), + test( + "clear bit beyond bit length", + Int32.bitflip(255, 32 + 7), + M.equals(Int32Testable(127)) + ), + test( + "set bit beyond bit length", + Int32.bitflip(127, 64 + 7), + M.equals(Int32Testable(255)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitcountNonZero", + [ + test( + "zero", + Int32.bitcountNonZero(0), + M.equals(Int32Testable(0)) + ), + test( + "minus one", + Int32.bitcountNonZero(-1), + M.equals(Int32Testable(32)) + ), + test( + "minus two", + Int32.bitcountNonZero(-2), + M.equals(Int32Testable(31)) + ), + test( + "one", + Int32.bitcountNonZero(1), + M.equals(Int32Testable(1)) + ), + test( + "minimum value", + Int32.bitcountNonZero(Int32.minimumValue), + M.equals(Int32Testable(1)) + ), + test( + "maximum value", + Int32.bitcountNonZero(Int32.maximumValue), + M.equals(Int32Testable(31)) + ), + test( + "alternating bits positive", + Int32.bitcountNonZero(0x5555_5555), + M.equals(Int32Testable(16)) + ), + test( + "alternating bits negative", + Int32.bitcountNonZero(-0x5555_5556), + M.equals(Int32Testable(16)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitcountLeadingZero", + [ + test( + "zero", + Int32.bitcountLeadingZero(0), + M.equals(Int32Testable(32)) + ), + test( + "minus one", + Int32.bitcountLeadingZero(-1), + M.equals(Int32Testable(0)) + ), + test( + "minus two", + Int32.bitcountLeadingZero(-2), + M.equals(Int32Testable(0)) + ), + test( + "one", + Int32.bitcountLeadingZero(1), + M.equals(Int32Testable(31)) + ), + test( + "two", + Int32.bitcountLeadingZero(2), + M.equals(Int32Testable(30)) + ), + test( + "arbitrary", + Int32.bitcountLeadingZero(0x0000_1020), + M.equals(Int32Testable(19)) + ), + test( + "minimum value", + Int32.bitcountLeadingZero(Int32.minimumValue), + M.equals(Int32Testable(0)) + ), + test( + "maximum value", + Int32.bitcountLeadingZero(Int32.maximumValue), + M.equals(Int32Testable(1)) + ), + test( + "alternating bits positive", + Int32.bitcountLeadingZero(0x5555_5555), + M.equals(Int32Testable(1)) + ), + test( + "alternating bits negative", + Int32.bitcountLeadingZero(-0x5555_5556), + M.equals(Int32Testable(0)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitcountTrailingZero", + [ + test( + "zero", + Int32.bitcountTrailingZero(0), + M.equals(Int32Testable(32)) + ), + test( + "minus one", + Int32.bitcountTrailingZero(-1), + M.equals(Int32Testable(0)) + ), + test( + "minus two", + Int32.bitcountTrailingZero(-2), + M.equals(Int32Testable(1)) + ), + test( + "one", + Int32.bitcountTrailingZero(1), + M.equals(Int32Testable(0)) + ), + test( + "two", + Int32.bitcountTrailingZero(2), + M.equals(Int32Testable(1)) + ), + test( + "arbitrary", + Int32.bitcountTrailingZero(0x5060_0000), + M.equals(Int32Testable(21)) + ), + test( + "minimum value", + Int32.bitcountTrailingZero(Int32.minimumValue), + M.equals(Int32Testable(31)) + ), + test( + "maximum value", + Int32.bitcountTrailingZero(Int32.maximumValue), + M.equals(Int32Testable(0)) + ), + test( + "alternating bits positive", + Int32.bitcountTrailingZero(0x5555_5555), + M.equals(Int32Testable(0)) + ), + test( + "alternating bits negative", + Int32.bitcountTrailingZero(-0x5555_5556), + M.equals(Int32Testable(1)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "addWrap", + [ + test( + "positive", + Int32.addWrap(123, 123), + M.equals(Int32Testable(246)) + ), + test( + "negative", + Int32.addWrap(-123, -123), + M.equals(Int32Testable(-246)) + ), + test( + "mixed signs", + Int32.addWrap(-123, 223), + M.equals(Int32Testable(100)) + ), + test( + "zero", + Int32.addWrap(0, 0), + M.equals(Int32Testable(0)) + ), + test( + "minimum and maximum", + Int32.addWrap(Int32.minimumValue, Int32.maximumValue), + M.equals(Int32Testable(-1)) + ), + test( + "small overflow", + Int32.addWrap(Int32.maximumValue, 1), + M.equals(Int32Testable(Int32.minimumValue)) + ), + test( + "large overflow", + Int32.addWrap(Int32.maximumValue, Int32.maximumValue), + M.equals(Int32Testable(-2)) + ), + test( + "small underflow", + Int32.addWrap(Int32.minimumValue, -1), + M.equals(Int32Testable(Int32.maximumValue)) + ), + test( + "large underflow", + Int32.addWrap(Int32.minimumValue, Int32.minimumValue), + M.equals(Int32Testable(0)) + ), + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "subWrap", + [ + test( + "positive", + Int32.subWrap(123, 123), + M.equals(Int32Testable(0)) + ), + test( + "negative", + Int32.subWrap(-123, -123), + M.equals(Int32Testable(0)) + ), + test( + "mixed signs", + Int32.subWrap(-123, 223), + M.equals(Int32Testable(-346)) + ), + test( + "zero", + Int32.subWrap(0, 0), + M.equals(Int32Testable(0)) + ), + test( + "maximum and maximum", + Int32.subWrap(Int32.maximumValue, Int32.maximumValue), + M.equals(Int32Testable(0)) + ), + test( + "small overflow", + Int32.subWrap(Int32.maximumValue, -1), + M.equals(Int32Testable(Int32.minimumValue)) + ), + test( + "large overflow", + Int32.subWrap(Int32.maximumValue, Int32.minimumValue), + M.equals(Int32Testable(-1)) + ), + test( + "small underflow", + Int32.subWrap(Int32.minimumValue, 1), + M.equals(Int32Testable(Int32.maximumValue)) + ), + test( + "large underflow", + Int32.subWrap(Int32.minimumValue, Int32.maximumValue), + M.equals(Int32Testable(1)) + ), + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "mulWrap", + [ + test( + "positive", + Int32.mulWrap(123, 234), + M.equals(Int32Testable(28782)) + ), + test( + "negative", + Int32.mulWrap(-123, -234), + M.equals(Int32Testable(28782)) + ), + test( + "mixed signs", + Int32.mulWrap(-123, 234), + M.equals(Int32Testable(-28782)) + ), + test( + "zeros", + Int32.mulWrap(0, 0), + M.equals(Int32Testable(0)) + ), + test( + "zero and maximum", + Int32.mulWrap(0, Int32.maximumValue), + M.equals(Int32Testable(0)) + ), + test( + "minimum and zero", + Int32.mulWrap(Int32.minimumValue, 0), + M.equals(Int32Testable(0)) + ), + test( + "one and maximum", + Int32.mulWrap(1, Int32.maximumValue), + M.equals(Int32Testable(Int32.maximumValue)) + ), + test( + "minimum and one", + Int32.mulWrap(Int32.minimumValue, 1), + M.equals(Int32Testable(Int32.minimumValue)) + ), + test( + "small overflow", + Int32.mulWrap(2, Int32.maximumValue), + M.equals(Int32Testable(-2)) + ), + test( + "large overflow", + Int32.mulWrap(Int32.maximumValue, Int32.maximumValue), + M.equals(Int32Testable(1)) + ), + test( + "small underflow", + Int32.mulWrap(Int32.minimumValue, 2), + M.equals(Int32Testable(0)) + ), + test( + "large underflow", + Int32.mulWrap(Int32.minimumValue, Int32.minimumValue), + M.equals(Int32Testable(0)) + ), + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "powWrap", + [ + test( + "positive base, positive exponent", + Int32.powWrap(72, 3), + M.equals(Int32Testable(373248)) + ), + test( + "positive base, zero exponent", + Int32.powWrap(72, 0), + M.equals(Int32Testable(1)) + ), + test( + "negative base, positive exponent", + Int32.powWrap(-72, 3), + M.equals(Int32Testable(-373248)) + ), + test( + "negative base, zero exponent", + Int32.powWrap(-72, 0), + M.equals(Int32Testable(1)) + ), + test( + "maximum and zero", + Int32.powWrap(Int32.maximumValue, 0), + M.equals(Int32Testable(1)) + ), + test( + "minimum and zero", + Int32.powWrap(Int32.minimumValue, 0), + M.equals(Int32Testable(1)) + ), + test( + "plus one and maximum", + Int32.powWrap(1, Int32.maximumValue), + M.equals(Int32Testable(1)) + ), + test( + "minus one and maximum", + Int32.powWrap(-1, Int32.maximumValue), + M.equals(Int32Testable(-1)) + ), + test( + "minimum value", + Int32.powWrap(-2, 31), + M.equals(Int32Testable(Int32.minimumValue)) + ), + test( + "small overflow", + Int32.powWrap(2, 31), + M.equals(Int32Testable(Int32.minimumValue)) + ), + test( + "large overflow", + Int32.powWrap(Int32.maximumValue, 10), + M.equals(Int32Testable(1)) + ), + test( + "small underflow", + Int32.powWrap(-2, 33), + M.equals(Int32Testable(0)) + ), + test( + "large underflow", + Int32.powWrap(Int32.minimumValue, 10), + M.equals(Int32Testable(0)) + ), + ] + ) +) diff --git a/test/int64Test.mo b/test/int64Test.mo new file mode 100644 index 00000000..cc3a45ed --- /dev/null +++ b/test/int64Test.mo @@ -0,0 +1,2302 @@ +import Int64 "mo:base/Int64"; +import Order "mo:base/Order"; +import Iter "mo:base/Iter"; + +import Suite "mo:matchers/Suite"; +import T "mo:matchers/Testable"; +import M "mo:matchers/Matchers"; + +let { run; test; suite } = Suite; + +let maximumInt64asInt = +2 ** 63 - 1 : Int; +let maximumInt64asNat64 = 2 ** 63 - 1 : Nat64; + +let minimumInt64asInt = -2 ** 63 : Int; + +let maximumNat64 = 18_446_744_073_709_551_615 : Nat64; + +class Int64Testable(number : Int64) : T.TestableItem { + public let item = number; + public func display(number : Int64) : Text { + debug_show (number) + }; + public let equals = func(x : Int64, y : Int64) : Bool { + x == y + } +}; + +class Nat64Testable(number : Nat64) : T.TestableItem { + public let item = number; + public func display(number : Nat64) : Text { + debug_show (number) + }; + public let equals = func(x : Nat64, y : Nat64) : Bool { + x == y + } +}; + +type Order = { #less; #equal; #greater }; + +class OrderTestable(value : Order) : T.TestableItem { + public let item = value; + public func display(value : Order) : Text { + debug_show (value) + }; + public let equals = func(x : Order, y : Order) : Bool { + x == y + } +}; + +/* --------------------------------------- */ + +run( + suite( + "constants", + [ + test( + "minimum value", + Int64.minimumValue, + M.equals(Int64Testable(Int64.fromInt(-2 ** 63))) + ), + test( + "maximum value", + Int64.maximumValue, + M.equals(Int64Testable(Int64.fromInt(+2 ** 63 - 1))) + ), + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "toInt", + [ + test( + "maximum number", + Int64.toInt(Int64.maximumValue), + M.equals(T.int(maximumInt64asInt)) + ), + test( + "minimum number", + Int64.toInt(Int64.minimumValue), + M.equals(T.int(minimumInt64asInt)) + ), + test( + "one", + Int64.toInt(1), + M.equals(T.int(1)) + ), + test( + "minus one", + Int64.toInt(-1), + M.equals(T.int(-1)) + ), + test( + "zero", + Int64.toInt(0), + M.equals(T.int(0)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "fromInt", + [ + test( + "maximum number", + Int64.fromInt(maximumInt64asInt), + M.equals(Int64Testable(Int64.maximumValue)) + ), + test( + "minimum number", + Int64.fromInt(minimumInt64asInt), + M.equals(Int64Testable(Int64.minimumValue)) + ), + test( + "one", + Int64.fromInt(1), + M.equals(Int64Testable(1)) + ), + test( + "minus one", + Int64.fromInt(-1), + M.equals(Int64Testable(-1)) + ), + test( + "zero", + Int64.fromInt(0), + M.equals(Int64Testable(0)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "fromIntWrap", + [ + test( + "maximum number", + Int64.fromIntWrap(maximumInt64asInt), + M.equals(Int64Testable(Int64.maximumValue)) + ), + test( + "minimum number", + Int64.fromIntWrap(minimumInt64asInt), + M.equals(Int64Testable(Int64.minimumValue)) + ), + test( + "one", + Int64.fromIntWrap(1), + M.equals(Int64Testable(1)) + ), + test( + "minus one", + Int64.fromIntWrap(-1), + M.equals(Int64Testable(-1)) + ), + test( + "zero", + Int64.fromIntWrap(0), + M.equals(Int64Testable(0)) + ), + test( + "overflow", + Int64.fromIntWrap(maximumInt64asInt + 1), + M.equals(Int64Testable(Int64.minimumValue)) + ), + test( + "underflow", + Int64.fromIntWrap(minimumInt64asInt - 1), + M.equals(Int64Testable(Int64.maximumValue)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "fromNat64", + [ + test( + "maximum number", + Int64.fromNat64(maximumInt64asNat64), + M.equals(Int64Testable(Int64.maximumValue)) + ), + test( + "one", + Int64.fromNat64(1), + M.equals(Int64Testable(1)) + ), + test( + "zero", + Int64.fromNat64(0), + M.equals(Int64Testable(0)) + ), + test( + "overflow", + Int64.fromNat64(maximumInt64asNat64 + 1), + M.equals(Int64Testable(Int64.minimumValue)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "toNat64", + [ + test( + "maximum number", + Int64.toNat64(Int64.maximumValue), + M.equals(Nat64Testable(maximumInt64asNat64)) + ), + test( + "one", + Int64.toNat64(1), + M.equals(Nat64Testable(1)) + ), + test( + "zero", + Int64.toNat64(0), + M.equals(Nat64Testable(0)) + ), + test( + "underflow", + Int64.toNat64(-1), + M.equals(Nat64Testable(maximumNat64)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "toText", + [ + test( + "positive", + Int64.toText(123456), + M.equals(T.text("123456")) + ), + test( + "negative", + Int64.toText(-123456), + M.equals(T.text("-123456")) + ), + test( + "zero", + Int64.toText(0), + M.equals(T.text("0")) + ), + test( + "maximum number", + Int64.toText(Int64.maximumValue), + M.equals(T.text("9223372036854775807")) + ), + test( + "minimum number", + Int64.toText(Int64.minimumValue), + M.equals(T.text("-9223372036854775808")) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "abs", + [ + test( + "positive number", + Int64.abs(123), + M.equals(Int64Testable(123)) + ), + test( + "negative number", + Int64.abs(-123), + M.equals(Int64Testable(123)) + ), + test( + "zero", + Int64.abs(0), + M.equals(Int64Testable(0)) + ), + test( + "maximum number", + Int64.abs(Int64.maximumValue), + M.equals(Int64Testable(Int64.maximumValue)) + ), + test( + "smallest possible", + Int64.abs(-Int64.maximumValue), + M.equals(Int64Testable(Int64.maximumValue)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "min", + [ + test( + "both positive", + Int64.min(2, 3), + M.equals(Int64Testable(2)) + ), + test( + "positive, negative", + Int64.min(2, -3), + M.equals(Int64Testable(-3)) + ), + test( + "both negative", + Int64.min(-2, -3), + M.equals(Int64Testable(-3)) + ), + test( + "negative, positive", + Int64.min(-2, 3), + M.equals(Int64Testable(-2)) + ), + test( + "equal values", + Int64.min(123, 123), + M.equals(Int64Testable(123)) + ), + test( + "maximum and minimum number", + Int64.min(Int64.maximumValue, Int64.minimumValue), + M.equals(Int64Testable(Int64.minimumValue)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "max", + [ + test( + "both positive", + Int64.max(2, 3), + M.equals(Int64Testable(3)) + ), + test( + "positive, negative", + Int64.max(2, -3), + M.equals(Int64Testable(2)) + ), + test( + "both negative", + Int64.max(-2, -3), + M.equals(Int64Testable(-2)) + ), + test( + "negative, positive", + Int64.max(-2, 3), + M.equals(Int64Testable(3)) + ), + test( + "equal values", + Int64.max(123, 123), + M.equals(Int64Testable(123)) + ), + test( + "maximum and minimum number", + Int64.max(Int64.maximumValue, Int64.minimumValue), + M.equals(Int64Testable(Int64.maximumValue)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "equal", + [ + test( + "positive equal", + Int64.equal(123, 123), + M.equals(T.bool(true)) + ), + test( + "negative equal", + Int64.equal(-123, -123), + M.equals(T.bool(true)) + ), + test( + "zero", + Int64.equal(0, 0), + M.equals(T.bool(true)) + ), + test( + "positive not equal", + Int64.equal(123, 124), + M.equals(T.bool(false)) + ), + test( + "negative not equal", + Int64.equal(-123, -124), + M.equals(T.bool(false)) + ), + test( + "mixed signs", + Int64.equal(123, -123), + M.equals(T.bool(false)) + ), + test( + "maxmimum equal", + Int64.equal(Int64.maximumValue, Int64.maximumValue), + M.equals(T.bool(true)) + ), + test( + "minimum equal", + Int64.equal(Int64.minimumValue, Int64.minimumValue), + M.equals(T.bool(true)) + ), + test( + "minimum and maximum", + Int64.equal(Int64.minimumValue, Int64.maximumValue), + M.equals(T.bool(false)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "notEqual", + [ + test( + "positive equal", + Int64.notEqual(123, 123), + M.equals(T.bool(false)) + ), + test( + "negative equal", + Int64.notEqual(-123, -123), + M.equals(T.bool(false)) + ), + test( + "zero", + Int64.notEqual(0, 0), + M.equals(T.bool(false)) + ), + test( + "positive not equal", + Int64.notEqual(123, 124), + M.equals(T.bool(true)) + ), + test( + "negative not equal", + Int64.notEqual(-123, -124), + M.equals(T.bool(true)) + ), + test( + "mixed signs", + Int64.notEqual(123, -123), + M.equals(T.bool(true)) + ), + test( + "maxmimum equal", + Int64.notEqual(Int64.maximumValue, Int64.maximumValue), + M.equals(T.bool(false)) + ), + test( + "minimum equal", + Int64.notEqual(Int64.minimumValue, Int64.minimumValue), + M.equals(T.bool(false)) + ), + test( + "minimum and maximum", + Int64.notEqual(Int64.minimumValue, Int64.maximumValue), + M.equals(T.bool(true)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "less", + [ + test( + "positive equal", + Int64.less(123, 123), + M.equals(T.bool(false)) + ), + test( + "positive less", + Int64.less(123, 245), + M.equals(T.bool(true)) + ), + test( + "positive greater", + Int64.less(245, 123), + M.equals(T.bool(false)) + ), + test( + "negative equal", + Int64.less(-123, -123), + M.equals(T.bool(false)) + ), + test( + "negative less", + Int64.less(-245, -123), + M.equals(T.bool(true)) + ), + test( + "negative greater", + Int64.less(-123, -245), + M.equals(T.bool(false)) + ), + test( + "zero", + Int64.less(0, 0), + M.equals(T.bool(false)) + ), + test( + "mixed signs less", + Int64.less(-123, 123), + M.equals(T.bool(true)) + ), + test( + "mixed signs greater", + Int64.less(123, -123), + M.equals(T.bool(false)) + ), + test( + "minimum and maximum", + Int64.less(Int64.minimumValue, Int64.maximumValue), + M.equals(T.bool(true)) + ), + test( + "maximum and minimum", + Int64.less(Int64.maximumValue, Int64.minimumValue), + M.equals(T.bool(false)) + ), + test( + "maximum and maximum", + Int64.less(Int64.maximumValue, Int64.maximumValue), + M.equals(T.bool(false)) + ), + test( + "minimum and minimum", + Int64.less(Int64.minimumValue, Int64.minimumValue), + M.equals(T.bool(false)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "lessOrEqual", + [ + test( + "positive equal", + Int64.lessOrEqual(123, 123), + M.equals(T.bool(true)) + ), + test( + "positive less", + Int64.lessOrEqual(123, 245), + M.equals(T.bool(true)) + ), + test( + "positive greater", + Int64.lessOrEqual(245, 123), + M.equals(T.bool(false)) + ), + test( + "negative equal", + Int64.lessOrEqual(-123, -123), + M.equals(T.bool(true)) + ), + test( + "negative less", + Int64.lessOrEqual(-245, -123), + M.equals(T.bool(true)) + ), + test( + "negative greater", + Int64.lessOrEqual(-123, -245), + M.equals(T.bool(false)) + ), + test( + "zero", + Int64.lessOrEqual(0, 0), + M.equals(T.bool(true)) + ), + test( + "mixed signs less", + Int64.lessOrEqual(-123, 123), + M.equals(T.bool(true)) + ), + test( + "mixed signs greater", + Int64.lessOrEqual(123, -123), + M.equals(T.bool(false)) + ), + test( + "minimum and maximum", + Int64.lessOrEqual(Int64.minimumValue, Int64.maximumValue), + M.equals(T.bool(true)) + ), + test( + "maximum and minimum", + Int64.lessOrEqual(Int64.maximumValue, Int64.minimumValue), + M.equals(T.bool(false)) + ), + test( + "maximum and maximum", + Int64.lessOrEqual(Int64.maximumValue, Int64.maximumValue), + M.equals(T.bool(true)) + ), + test( + "minimum and minimum", + Int64.lessOrEqual(Int64.minimumValue, Int64.minimumValue), + M.equals(T.bool(true)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "greater", + [ + test( + "positive equal", + Int64.greater(123, 123), + M.equals(T.bool(false)) + ), + test( + "positive less", + Int64.greater(123, 245), + M.equals(T.bool(false)) + ), + test( + "positive greater", + Int64.greater(245, 123), + M.equals(T.bool(true)) + ), + test( + "negative equal", + Int64.greater(-123, -123), + M.equals(T.bool(false)) + ), + test( + "negative less", + Int64.greater(-245, -123), + M.equals(T.bool(false)) + ), + test( + "negative greater", + Int64.greater(-123, -245), + M.equals(T.bool(true)) + ), + test( + "zero", + Int64.greater(0, 0), + M.equals(T.bool(false)) + ), + test( + "mixed signs less", + Int64.greater(-123, 123), + M.equals(T.bool(false)) + ), + test( + "mixed signs greater", + Int64.greater(123, -123), + M.equals(T.bool(true)) + ), + test( + "minimum and maximum", + Int64.greater(Int64.minimumValue, Int64.maximumValue), + M.equals(T.bool(false)) + ), + test( + "maximum and minimum", + Int64.greater(Int64.maximumValue, Int64.minimumValue), + M.equals(T.bool(true)) + ), + test( + "maximum and maximum", + Int64.greater(Int64.maximumValue, Int64.maximumValue), + M.equals(T.bool(false)) + ), + test( + "minimum and minimum", + Int64.greater(Int64.minimumValue, Int64.minimumValue), + M.equals(T.bool(false)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "greaterOrEqual", + [ + test( + "positive equal", + Int64.greaterOrEqual(123, 123), + M.equals(T.bool(true)) + ), + test( + "positive less", + Int64.greaterOrEqual(123, 245), + M.equals(T.bool(false)) + ), + test( + "positive greater", + Int64.greaterOrEqual(245, 123), + M.equals(T.bool(true)) + ), + test( + "negative equal", + Int64.greaterOrEqual(-123, -123), + M.equals(T.bool(true)) + ), + test( + "negative less", + Int64.greaterOrEqual(-245, -123), + M.equals(T.bool(false)) + ), + test( + "negative greater", + Int64.greaterOrEqual(-123, -245), + M.equals(T.bool(true)) + ), + test( + "zero", + Int64.greaterOrEqual(0, 0), + M.equals(T.bool(true)) + ), + test( + "mixed signs less", + Int64.greaterOrEqual(-123, 123), + M.equals(T.bool(false)) + ), + test( + "mixed signs greater", + Int64.greaterOrEqual(123, -123), + M.equals(T.bool(true)) + ), + test( + "minimum and maximum", + Int64.greaterOrEqual(Int64.minimumValue, Int64.maximumValue), + M.equals(T.bool(false)) + ), + test( + "maximum and minimum", + Int64.greaterOrEqual(Int64.maximumValue, Int64.minimumValue), + M.equals(T.bool(true)) + ), + test( + "maximum and maximum", + Int64.greaterOrEqual(Int64.maximumValue, Int64.maximumValue), + M.equals(T.bool(true)) + ), + test( + "minimum and minimum", + Int64.greaterOrEqual(Int64.minimumValue, Int64.minimumValue), + M.equals(T.bool(true)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "compare", + [ + test( + "positive equal", + Int64.compare(123, 123), + M.equals(OrderTestable(#equal)) + ), + test( + "positive less", + Int64.compare(123, 245), + M.equals(OrderTestable(#less)) + ), + test( + "positive greater", + Int64.compare(245, 123), + M.equals(OrderTestable(#greater)) + ), + test( + "negative equal", + Int64.compare(-123, -123), + M.equals(OrderTestable(#equal)) + ), + test( + "negative less", + Int64.compare(-245, -123), + M.equals(OrderTestable(#less)) + ), + test( + "negative greater", + Int64.compare(-123, -245), + M.equals(OrderTestable(#greater)) + ), + test( + "zero", + Int64.compare(0, 0), + M.equals(OrderTestable(#equal)) + ), + test( + "mixed signs less", + Int64.compare(-123, 123), + M.equals(OrderTestable(#less)) + ), + test( + "mixed signs greater", + Int64.compare(123, -123), + M.equals(OrderTestable(#greater)) + ), + test( + "minimum and maximum", + Int64.compare(Int64.minimumValue, Int64.maximumValue), + M.equals(OrderTestable(#less)) + ), + test( + "maximum and minimum", + Int64.compare(Int64.maximumValue, Int64.minimumValue), + M.equals(OrderTestable(#greater)) + ), + test( + "maximum and maximum", + Int64.compare(Int64.maximumValue, Int64.maximumValue), + M.equals(OrderTestable(#equal)) + ), + test( + "minimum and minimum", + Int64.compare(Int64.minimumValue, Int64.minimumValue), + M.equals(OrderTestable(#equal)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "neg", + [ + test( + "positive number", + Int64.neg(123), + M.equals(Int64Testable(-123)) + ), + test( + "negative number", + Int64.neg(-123), + M.equals(Int64Testable(123)) + ), + test( + "zero", + Int64.neg(0), + M.equals(Int64Testable(0)) + ), + test( + "maximum number", + Int64.neg(Int64.maximumValue), + M.equals(Int64Testable(-Int64.maximumValue)) + ), + test( + "smallest possible", + Int64.neg(-Int64.maximumValue), + M.equals(Int64Testable(Int64.maximumValue)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "add", + [ + test( + "positive", + Int64.add(123, 123), + M.equals(Int64Testable(246)) + ), + test( + "negative", + Int64.add(-123, -123), + M.equals(Int64Testable(-246)) + ), + test( + "mixed signs", + Int64.add(-123, 223), + M.equals(Int64Testable(100)) + ), + test( + "zero", + Int64.add(0, 0), + M.equals(Int64Testable(0)) + ), + test( + "minimum and maximum", + Int64.add(Int64.minimumValue, Int64.maximumValue), + M.equals(Int64Testable(-1)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "sub", + [ + test( + "positive", + Int64.sub(123, 123), + M.equals(Int64Testable(0)) + ), + test( + "negative", + Int64.sub(-123, -123), + M.equals(Int64Testable(0)) + ), + test( + "mixed signs", + Int64.sub(-123, 223), + M.equals(Int64Testable(-346)) + ), + test( + "zero", + Int64.sub(0, 0), + M.equals(Int64Testable(0)) + ), + test( + "maximum and maximum", + Int64.sub(Int64.maximumValue, Int64.maximumValue), + M.equals(Int64Testable(0)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "mul", + [ + test( + "positive", + Int64.mul(123, 234), + M.equals(Int64Testable(28782)) + ), + test( + "negative", + Int64.mul(-123, -234), + M.equals(Int64Testable(28782)) + ), + test( + "mixed signs", + Int64.mul(-123, 234), + M.equals(Int64Testable(-28782)) + ), + test( + "zeros", + Int64.mul(0, 0), + M.equals(Int64Testable(0)) + ), + test( + "zero and maximum", + Int64.mul(0, Int64.maximumValue), + M.equals(Int64Testable(0)) + ), + test( + "minimum and zero", + Int64.mul(Int64.minimumValue, 0), + M.equals(Int64Testable(0)) + ), + test( + "one and maximum", + Int64.mul(1, Int64.maximumValue), + M.equals(Int64Testable(Int64.maximumValue)) + ), + test( + "minimum and one", + Int64.mul(Int64.minimumValue, 1), + M.equals(Int64Testable(Int64.minimumValue)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "div", + [ + test( + "positive multiple", + Int64.div(156, 13), + M.equals(Int64Testable(12)) + ), + test( + "positive remainder", + Int64.div(1234, 100), + M.equals(Int64Testable(12)) + ), + test( + "negative multiple", + Int64.div(-156, -13), + M.equals(Int64Testable(12)) + ), + test( + "negative remainder", + Int64.div(-1234, -100), + M.equals(Int64Testable(12)) + ), + test( + "mixed signs", + Int64.div(-123, 23), + M.equals(Int64Testable(-5)) + ), + test( + "zero and number", + Int64.div(0, -123), + M.equals(Int64Testable(0)) + ), + test( + "zero and maximum", + Int64.div(0, Int64.maximumValue), + M.equals(Int64Testable(0)) + ), + test( + "zero and minimum", + Int64.div(0, Int64.minimumValue), + M.equals(Int64Testable(0)) + ), + test( + "maximum and maximum", + Int64.div(Int64.maximumValue, Int64.maximumValue), + M.equals(Int64Testable(1)) + ), + test( + "minimum and minimum", + Int64.div(Int64.minimumValue, Int64.minimumValue), + M.equals(Int64Testable(1)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "rem", + [ + test( + "positive multiple", + Int64.rem(156, 13), + M.equals(Int64Testable(0)) + ), + test( + "positive/positive remainder", + Int64.rem(1234, 100), + M.equals(Int64Testable(34)) + ), + test( + "positive/negative remainder", + Int64.rem(1234, -100), + M.equals(Int64Testable(34)) + ), + test( + "negative multiple", + Int64.rem(-156, -13), + M.equals(Int64Testable(0)) + ), + test( + "negative/positive remainder", + Int64.rem(-1234, 100), + M.equals(Int64Testable(-34)) + ), + test( + "negative/negative remainder", + Int64.rem(-1234, -100), + M.equals(Int64Testable(-34)) + ), + test( + "zero and maximum", + Int64.rem(0, Int64.maximumValue), + M.equals(Int64Testable(0)) + ), + test( + "zero and minimum", + Int64.rem(0, Int64.minimumValue), + M.equals(Int64Testable(0)) + ), + test( + "maximum and maximum", + Int64.rem(Int64.maximumValue, Int64.maximumValue), + M.equals(Int64Testable(0)) + ), + test( + "minimum and minimum", + Int64.rem(Int64.minimumValue, Int64.minimumValue), + M.equals(Int64Testable(0)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "pow", + [ + test( + "positive base, positive exponent", + Int64.pow(72, 3), + M.equals(Int64Testable(373248)) + ), + test( + "positive base, zero exponent", + Int64.pow(72, 0), + M.equals(Int64Testable(1)) + ), + test( + "negative base, odd exponent", + Int64.pow(-72, 3), + M.equals(Int64Testable(-373248)) + ), + test( + "negative base, even exponent", + Int64.pow(-72, 4), + M.equals(Int64Testable(26_873_856)) + ), + test( + "negative base, zero exponent", + Int64.pow(-72, 0), + M.equals(Int64Testable(1)) + ), + test( + "maximum and zero", + Int64.pow(Int64.maximumValue, 0), + M.equals(Int64Testable(1)) + ), + test( + "minimum and zero", + Int64.pow(Int64.minimumValue, 0), + M.equals(Int64Testable(1)) + ), + test( + "plus one and maximum", + Int64.pow(1, Int64.maximumValue), + M.equals(Int64Testable(1)) + ), + test( + "minus one and maximum", + Int64.pow(-1, Int64.maximumValue), + M.equals(Int64Testable(-1)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitnot", + [ + test( + "zero", + Int64.bitnot(0), + M.equals(Int64Testable(-1)) + ), + test( + "minus 1", + Int64.bitnot(-1), + M.equals(Int64Testable(0)) + ), + test( + "maximum", + Int64.bitnot(Int64.maximumValue), + M.equals(Int64Testable(Int64.minimumValue)) + ), + test( + "minimum", + Int64.bitnot(Int64.minimumValue), + M.equals(Int64Testable(Int64.maximumValue)) + ), + test( + "arbitrary", + Int64.bitnot(1234), + M.equals(Int64Testable(-1235)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitand", + [ + test( + "inverted", + Int64.bitand(0xf0f0, 0x0f0f), + M.equals(Int64Testable(0)) + ), + test( + "overlap", + Int64.bitand(0x0ff0, 0xffff), + M.equals(Int64Testable(0xff0)) + ), + test( + "arbitrary", + Int64.bitand(0x1234_5678_90ab_cdef, 0x7654_3210_fedc_ba98), + M.equals(Int64Testable(0x1214_1210_9088_8888)) + ), + test( + "negative", + Int64.bitand(-123, -123), + M.equals(Int64Testable(-123)) + ), + test( + "mixed signs", + Int64.bitand(-256, 255), + M.equals(Int64Testable(0)) + ), + test( + "zero", + Int64.bitand(0, 0), + M.equals(Int64Testable(0)) + ), + test( + "zero and maximum", + Int64.bitand(0, Int64.maximumValue), + M.equals(Int64Testable(0)) + ), + test( + "minimum and zero", + Int64.bitand(Int64.minimumValue, 0), + M.equals(Int64Testable(0)) + ), + test( + "minimum and maximum", + Int64.bitand(Int64.minimumValue, Int64.maximumValue), + M.equals(Int64Testable(0)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitor", + [ + test( + "inverted", + Int64.bitor(0xf0f0, 0x0f0f), + M.equals(Int64Testable(0xffff)) + ), + test( + "overlap", + Int64.bitor(0x0ff0, 0xffff), + M.equals(Int64Testable(0xffff)) + ), + test( + "arbitrary", + Int64.bitor(0x1234_5678_90ab_cdef, 0x7654_3210_fedc_ba98), + M.equals(Int64Testable(0x7674_7678_feff_ffff)) + ), + test( + "negative", + Int64.bitor(-123, -123), + M.equals(Int64Testable(-123)) + ), + test( + "mixed signs", + Int64.bitor(-256, 255), + M.equals(Int64Testable(-1)) + ), + test( + "zero", + Int64.bitor(0, 0), + M.equals(Int64Testable(0)) + ), + test( + "zero and maximum", + Int64.bitor(0, Int64.maximumValue), + M.equals(Int64Testable(Int64.maximumValue)) + ), + test( + "minimum and zero", + Int64.bitor(Int64.minimumValue, 0), + M.equals(Int64Testable(Int64.minimumValue)) + ), + test( + "minimum and maximum", + Int64.bitor(Int64.minimumValue, Int64.maximumValue), + M.equals(Int64Testable(-1)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitxor", + [ + test( + "inverted", + Int64.bitxor(0xf0f0, 0x0f0f), + M.equals(Int64Testable(0xffff)) + ), + test( + "overlap", + Int64.bitxor(0x0ff0, 0xffff), + M.equals(Int64Testable(0xf00f)) + ), + test( + "arbitrary", + Int64.bitxor(0x1234_5678_90ab_cdef, 0x7654_3210_fedc_ba98), + M.equals(Int64Testable(0x6460_6468_6e77_7777)) + ), + test( + "negative", + Int64.bitxor(-123, -123), + M.equals(Int64Testable(0)) + ), + test( + "mixed signs", + Int64.bitxor(-256, 255), + M.equals(Int64Testable(-1)) + ), + test( + "zero", + Int64.bitxor(0, 0), + M.equals(Int64Testable(0)) + ), + test( + "zero and maximum", + Int64.bitxor(0, Int64.maximumValue), + M.equals(Int64Testable(Int64.maximumValue)) + ), + test( + "minimum and zero", + Int64.bitxor(Int64.minimumValue, 0), + M.equals(Int64Testable(Int64.minimumValue)) + ), + test( + "minimum and maximum", + Int64.bitxor(Int64.minimumValue, Int64.maximumValue), + M.equals(Int64Testable(-1)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitshiftLeft", + [ + test( + "positive number", + Int64.bitshiftLeft(0xf0f0, 4), + M.equals(Int64Testable(0xf_0f00)) + ), + test( + "negative number", + Int64.bitshiftLeft(-256, 4), + M.equals(Int64Testable(-4096)) + ), + test( + "arbitrary", + Int64.bitshiftLeft(1234_5678, 7), + M.equals(Int64Testable(1_580_246_784)) + ), + test( + "zero shift", + Int64.bitshiftLeft(1234, 0), + M.equals(Int64Testable(1234)) + ), + test( + "one maximum shift", + Int64.bitshiftLeft(1, 63), + M.equals(Int64Testable(Int64.minimumValue)) + ), + test( + "minimum number", + Int64.bitshiftLeft(-1, 63), + M.equals(Int64Testable(Int64.minimumValue)) + ), + test( + "discard overflow", + Int64.bitshiftLeft(0x7fff_ffff_0000_0000, 32), + M.equals(Int64Testable(0)) + ), + test( + "beyond bit length positive", + Int64.bitshiftLeft(0x1234_5678_90ab_cdef, 128 + 7), + M.equals(Int64Testable(Int64.bitshiftLeft(0x1234_5678_90ab_cdef, 7))) + ), + test( + "beyond bit length negative", + Int64.bitshiftLeft(-0x1234_5678_90ab_cdef, 64 + 7), + M.equals(Int64Testable(Int64.bitshiftLeft(-0x1234_5678_90ab_cdef, 7))) + ), + test( + "negative shift argument", + Int64.bitshiftLeft(0x1234_5678_90ab_cdef, -7), + M.equals(Int64Testable(Int64.bitshiftLeft(0x1234_5678_90ab_cdef, 64 - 7))) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitshiftRight", + [ + test( + "positive number", + Int64.bitshiftRight(0xf0f0, 4), + M.equals(Int64Testable(0x0f0f)) + ), + test( + "negative number", + Int64.bitshiftRight(-256, 4), + M.equals(Int64Testable(-16)) + ), + test( + "arbitrary", + Int64.bitshiftRight(1234_5678, 7), + M.equals(Int64Testable(96_450)) + ), + test( + "zero shift", + Int64.bitshiftRight(1234, 0), + M.equals(Int64Testable(1234)) + ), + test( + "minus one maximum shift", + Int64.bitshiftRight(-1, 63), + M.equals(Int64Testable(-1)) + ), + test( + "minimum number", + Int64.bitshiftRight(Int64.minimumValue, 63), + M.equals(Int64Testable(-1)) + ), + test( + "discard underflow", + Int64.bitshiftRight(0x0000_0000_ffff_ffff, 32), + M.equals(Int64Testable(0)) + ), + test( + "beyond bit length positive", + Int64.bitshiftRight(0x1234_5678_90ab_cdef, 128 + 7), + M.equals(Int64Testable(Int64.bitshiftRight(0x1234_5678_90ab_cdef, 7))) + ), + test( + "beyond bit length negative", + Int64.bitshiftRight(-0x1234_5678_90ab_cdef, 64 + 7), + M.equals(Int64Testable(Int64.bitshiftRight(-0x1234_5678_90ab_cdef, 7))) + ), + test( + "negative shift argument", + Int64.bitshiftRight(0x1234_5678_90ab_cdef, -7), + M.equals(Int64Testable(Int64.bitshiftRight(0x1234_5678_90ab_cdef, 64 - 7))) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitrotLeft", + [ + test( + "positive number non-overflow", + Int64.bitrotLeft(0xf0f0, 4), + M.equals(Int64Testable(0xf_0f00)) + ), + test( + "positive number overflow", + Int64.bitrotLeft(0x5600_0000_0000_1234, 8), + M.equals(Int64Testable(0x12_3456)) + ), + test( + "negative number", + Int64.bitrotLeft(-256, 4), + M.equals(Int64Testable(-4081)) + ), + test( + "arbitrary", + Int64.bitrotLeft(123_4567_8901_2345_6789, 7), + M.equals(Int64Testable(-799_6006_7275_8349_5544)) + ), + test( + "zero shift", + Int64.bitrotLeft(1234, 0), + M.equals(Int64Testable(1234)) + ), + test( + "minus one maximum rotate", + Int64.bitrotLeft(-1, 63), + M.equals(Int64Testable(-1)) + ), + test( + "maximum number", + Int64.bitrotLeft(Int64.maximumValue, 1), + M.equals(Int64Testable(-2)) + ), + test( + "minimum number", + Int64.bitrotLeft(1, 63), + M.equals(Int64Testable(Int64.minimumValue)) + ), + test( + "opposite rotation", + Int64.bitrotLeft(256, -2), + M.equals(Int64Testable(64)) + ), + test( + "rotate beyond bit length", + Int64.bitrotLeft(128, 66), + M.equals(Int64Testable(512)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitrotRight", + [ + test( + "positive number non-underflow", + Int64.bitrotRight(0xf0f0, 4), + M.equals(Int64Testable(0x0f0f)) + ), + test( + "positive number underflow", + Int64.bitrotRight(0x5600_0000_0000_1234, 8), + M.equals(Int64Testable(0x3456_0000_0000_0012)) + ), + test( + "negative number", + Int64.bitrotRight(-256, 8), + M.equals(Int64Testable(0x00ff_ffff_ffff_ffff)) + ), + test( + "arbitrary", + Int64.bitrotRight(123_4567_8901_2345_6789, 7), + M.equals(Int64Testable(303_6064_0112_3456_2818)) + ), + test( + "zero shift", + Int64.bitrotRight(1234, 0), + M.equals(Int64Testable(1234)) + ), + test( + "minus one maximum rotate", + Int64.bitrotRight(-1, 63), + M.equals(Int64Testable(-1)) + ), + test( + "maximum number", + Int64.bitrotRight(-2, 1), + M.equals(Int64Testable(Int64.maximumValue)) + ), + test( + "minimum number", + Int64.bitrotRight(Int64.minimumValue, 63), + M.equals(Int64Testable(1)) + ), + test( + "opposite rotation", + Int64.bitrotRight(256, -2), + M.equals(Int64Testable(1024)) + ), + test( + "rotate beyond bit length", + Int64.bitrotRight(128, 66), + M.equals(Int64Testable(32)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bittest", + [ + test( + "set bit", + Int64.bittest(128, 7), + M.equals(T.bool(true)) + ), + test( + "cleared bit", + Int64.bittest(-129, 7), + M.equals(T.bool(false)) + ), + test( + "all zero", + do { + let number = 0 : Int64; + var count = 0; + for (index in Iter.range(0, 63)) { + if (Int64.bittest(number, index)) { + count += 1 + } + }; + count + }, + M.equals(T.int(0)) + ), + test( + "all one", + do { + let number = -1 : Int64; + var count = 0; + for (index in Iter.range(0, 63)) { + if (Int64.bittest(number, index)) { + count += 1 + } + }; + count + }, + M.equals(T.int(64)) + ), + test( + "set bit beyond bit length", + Int64.bittest(128, 64 + 7), + M.equals(T.bool(true)) + ), + test( + "cleared bit beyond bit length", + Int64.bittest(-129, 128 + 7), + M.equals(T.bool(false)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitset", + [ + test( + "set bit", + Int64.bitset(0, 7), + M.equals(Int64Testable(128)) + ), + test( + "minus one", + Int64.bitset(-129, 7), + M.equals(Int64Testable(-1)) + ), + test( + "no effect", + Int64.bitset(128, 7), + M.equals(Int64Testable(128)) + ), + test( + "set all", + do { + var number = 0 : Int64; + for (index in Iter.range(0, 63)) { + number := Int64.bitset(number, index) + }; + number + }, + M.equals(Int64Testable(-1)) + ), + test( + "all no effect", + do { + var number = -1 : Int64; + for (index in Iter.range(0, 63)) { + number := Int64.bitset(number, index) + }; + number + }, + M.equals(Int64Testable(-1)) + ), + test( + "set bit beyond bit length", + Int64.bitset(0, 64 + 7), + M.equals(Int64Testable(128)) + ), + test( + "minus one beyond bit length", + Int64.bitset(-129, 128 + 7), + M.equals(Int64Testable(-1)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitclear", + [ + test( + "clear bit", + Int64.bitclear(128, 7), + M.equals(Int64Testable(0)) + ), + test( + "minus one", + Int64.bitclear(-1, 7), + M.equals(Int64Testable(-129)) + ), + test( + "no effect", + Int64.bitclear(0, 7), + M.equals(Int64Testable(0)) + ), + test( + "clear all", + do { + var number = -1 : Int64; + for (index in Iter.range(0, 63)) { + number := Int64.bitclear(number, index) + }; + number + }, + M.equals(Int64Testable(0)) + ), + test( + "all no effect", + do { + var number = 0 : Int64; + for (index in Iter.range(0, 63)) { + number := Int64.bitclear(number, index) + }; + number + }, + M.equals(Int64Testable(0)) + ), + test( + "clear bit beyond bit length", + Int64.bitclear(128, 64 + 7), + M.equals(Int64Testable(0)) + ), + test( + "minus one beyond bit length", + Int64.bitclear(-1, 128 + 7), + M.equals(Int64Testable(-129)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitflip", + [ + test( + "clear bit", + Int64.bitflip(255, 7), + M.equals(Int64Testable(127)) + ), + test( + "set bit", + Int64.bitflip(127, 7), + M.equals(Int64Testable(255)) + ), + test( + "double flip", + Int64.bitflip(Int64.bitflip(0x1234_5678_90ab_cdef, 13), 13), + M.equals(Int64Testable(0x1234_5678_90ab_cdef)) + ), + test( + "clear all", + do { + var number = -1 : Int64; + for (index in Iter.range(0, 63)) { + number := Int64.bitflip(number, index) + }; + number + }, + M.equals(Int64Testable(0)) + ), + test( + "set all", + do { + var number = 0 : Int64; + for (index in Iter.range(0, 63)) { + number := Int64.bitflip(number, index) + }; + number + }, + M.equals(Int64Testable(-1)) + ), + test( + "clear bit beyond bit length", + Int64.bitflip(255, 64 + 7), + M.equals(Int64Testable(127)) + ), + test( + "set bit beyond bit length", + Int64.bitflip(127, 128 + 7), + M.equals(Int64Testable(255)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitcountNonZero", + [ + test( + "zero", + Int64.bitcountNonZero(0), + M.equals(Int64Testable(0)) + ), + test( + "minus one", + Int64.bitcountNonZero(-1), + M.equals(Int64Testable(64)) + ), + test( + "minus two", + Int64.bitcountNonZero(-2), + M.equals(Int64Testable(63)) + ), + test( + "one", + Int64.bitcountNonZero(1), + M.equals(Int64Testable(1)) + ), + test( + "minimum value", + Int64.bitcountNonZero(Int64.minimumValue), + M.equals(Int64Testable(1)) + ), + test( + "maximum value", + Int64.bitcountNonZero(Int64.maximumValue), + M.equals(Int64Testable(63)) + ), + test( + "alternating bits positive", + Int64.bitcountNonZero(0x5555_5555_5555_5555), + M.equals(Int64Testable(32)) + ), + test( + "alternating bits negative", + Int64.bitcountNonZero(-0x5555_5555_5555_5556), + M.equals(Int64Testable(32)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitcountLeadingZero", + [ + test( + "zero", + Int64.bitcountLeadingZero(0), + M.equals(Int64Testable(64)) + ), + test( + "minus one", + Int64.bitcountLeadingZero(-1), + M.equals(Int64Testable(0)) + ), + test( + "minus two", + Int64.bitcountLeadingZero(-2), + M.equals(Int64Testable(0)) + ), + test( + "one", + Int64.bitcountLeadingZero(1), + M.equals(Int64Testable(63)) + ), + test( + "two", + Int64.bitcountLeadingZero(2), + M.equals(Int64Testable(62)) + ), + test( + "arbitrary", + Int64.bitcountLeadingZero(0x0000_1020_3040_5060), + M.equals(Int64Testable(19)) + ), + test( + "minimum value", + Int64.bitcountLeadingZero(Int64.minimumValue), + M.equals(Int64Testable(0)) + ), + test( + "maximum value", + Int64.bitcountLeadingZero(Int64.maximumValue), + M.equals(Int64Testable(1)) + ), + test( + "alternating bits positive", + Int64.bitcountLeadingZero(0x5555_5555_5555_5555), + M.equals(Int64Testable(1)) + ), + test( + "alternating bits negative", + Int64.bitcountLeadingZero(-0x5555_5555_5555_5556), + M.equals(Int64Testable(0)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitcountTrailingZero", + [ + test( + "zero", + Int64.bitcountTrailingZero(0), + M.equals(Int64Testable(64)) + ), + test( + "minus one", + Int64.bitcountTrailingZero(-1), + M.equals(Int64Testable(0)) + ), + test( + "minus two", + Int64.bitcountTrailingZero(-2), + M.equals(Int64Testable(1)) + ), + test( + "one", + Int64.bitcountTrailingZero(1), + M.equals(Int64Testable(0)) + ), + test( + "two", + Int64.bitcountTrailingZero(2), + M.equals(Int64Testable(1)) + ), + test( + "arbitrary", + Int64.bitcountTrailingZero(0x1020_3040_5060_0000), + M.equals(Int64Testable(21)) + ), + test( + "minimum value", + Int64.bitcountTrailingZero(Int64.minimumValue), + M.equals(Int64Testable(63)) + ), + test( + "maximum value", + Int64.bitcountTrailingZero(Int64.maximumValue), + M.equals(Int64Testable(0)) + ), + test( + "alternating bits positive", + Int64.bitcountTrailingZero(0x5555_5555_5555_5555), + M.equals(Int64Testable(0)) + ), + test( + "alternating bits negative", + Int64.bitcountTrailingZero(-0x5555_5555_5555_5556), + M.equals(Int64Testable(1)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "addWrap", + [ + test( + "positive", + Int64.addWrap(123, 123), + M.equals(Int64Testable(246)) + ), + test( + "negative", + Int64.addWrap(-123, -123), + M.equals(Int64Testable(-246)) + ), + test( + "mixed signs", + Int64.addWrap(-123, 223), + M.equals(Int64Testable(100)) + ), + test( + "zero", + Int64.addWrap(0, 0), + M.equals(Int64Testable(0)) + ), + test( + "minimum and maximum", + Int64.addWrap(Int64.minimumValue, Int64.maximumValue), + M.equals(Int64Testable(-1)) + ), + test( + "small overflow", + Int64.addWrap(Int64.maximumValue, 1), + M.equals(Int64Testable(Int64.minimumValue)) + ), + test( + "large overflow", + Int64.addWrap(Int64.maximumValue, Int64.maximumValue), + M.equals(Int64Testable(-2)) + ), + test( + "small underflow", + Int64.addWrap(Int64.minimumValue, -1), + M.equals(Int64Testable(Int64.maximumValue)) + ), + test( + "large underflow", + Int64.addWrap(Int64.minimumValue, Int64.minimumValue), + M.equals(Int64Testable(0)) + ), + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "subWrap", + [ + test( + "positive", + Int64.subWrap(123, 123), + M.equals(Int64Testable(0)) + ), + test( + "negative", + Int64.subWrap(-123, -123), + M.equals(Int64Testable(0)) + ), + test( + "mixed signs", + Int64.subWrap(-123, 223), + M.equals(Int64Testable(-346)) + ), + test( + "zero", + Int64.subWrap(0, 0), + M.equals(Int64Testable(0)) + ), + test( + "maximum and maximum", + Int64.subWrap(Int64.maximumValue, Int64.maximumValue), + M.equals(Int64Testable(0)) + ), + test( + "small overflow", + Int64.subWrap(Int64.maximumValue, -1), + M.equals(Int64Testable(Int64.minimumValue)) + ), + test( + "large overflow", + Int64.subWrap(Int64.maximumValue, Int64.minimumValue), + M.equals(Int64Testable(-1)) + ), + test( + "small underflow", + Int64.subWrap(Int64.minimumValue, 1), + M.equals(Int64Testable(Int64.maximumValue)) + ), + test( + "large underflow", + Int64.subWrap(Int64.minimumValue, Int64.maximumValue), + M.equals(Int64Testable(1)) + ), + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "mulWrap", + [ + test( + "positive", + Int64.mulWrap(123, 234), + M.equals(Int64Testable(28782)) + ), + test( + "negative", + Int64.mulWrap(-123, -234), + M.equals(Int64Testable(28782)) + ), + test( + "mixed signs", + Int64.mulWrap(-123, 234), + M.equals(Int64Testable(-28782)) + ), + test( + "zeros", + Int64.mulWrap(0, 0), + M.equals(Int64Testable(0)) + ), + test( + "zero and maximum", + Int64.mulWrap(0, Int64.maximumValue), + M.equals(Int64Testable(0)) + ), + test( + "minimum and zero", + Int64.mulWrap(Int64.minimumValue, 0), + M.equals(Int64Testable(0)) + ), + test( + "one and maximum", + Int64.mulWrap(1, Int64.maximumValue), + M.equals(Int64Testable(Int64.maximumValue)) + ), + test( + "minimum and one", + Int64.mulWrap(Int64.minimumValue, 1), + M.equals(Int64Testable(Int64.minimumValue)) + ), + test( + "small overflow", + Int64.mulWrap(2, Int64.maximumValue), + M.equals(Int64Testable(-2)) + ), + test( + "large overflow", + Int64.mulWrap(Int64.maximumValue, Int64.maximumValue), + M.equals(Int64Testable(1)) + ), + test( + "small underflow", + Int64.mulWrap(Int64.minimumValue, 2), + M.equals(Int64Testable(0)) + ), + test( + "large underflow", + Int64.mulWrap(Int64.minimumValue, Int64.minimumValue), + M.equals(Int64Testable(0)) + ), + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "powWrap", + [ + test( + "positive base, positive exponent", + Int64.powWrap(72, 3), + M.equals(Int64Testable(373248)) + ), + test( + "positive base, zero exponent", + Int64.powWrap(72, 0), + M.equals(Int64Testable(1)) + ), + test( + "negative base, positive exponent", + Int64.powWrap(-72, 3), + M.equals(Int64Testable(-373248)) + ), + test( + "negative base, zero exponent", + Int64.powWrap(-72, 0), + M.equals(Int64Testable(1)) + ), + test( + "maximum and zero", + Int64.powWrap(Int64.maximumValue, 0), + M.equals(Int64Testable(1)) + ), + test( + "minimum and zero", + Int64.powWrap(Int64.minimumValue, 0), + M.equals(Int64Testable(1)) + ), + test( + "plus one and maximum", + Int64.powWrap(1, Int64.maximumValue), + M.equals(Int64Testable(1)) + ), + test( + "minus one and maximum", + Int64.powWrap(-1, Int64.maximumValue), + M.equals(Int64Testable(-1)) + ), + test( + "minimum value", + Int64.powWrap(-2, 63), + M.equals(Int64Testable(Int64.minimumValue)) + ), + test( + "small overflow", + Int64.powWrap(2, 63), + M.equals(Int64Testable(Int64.minimumValue)) + ), + test( + "large overflow", + Int64.powWrap(Int64.maximumValue, 10), + M.equals(Int64Testable(1)) + ), + test( + "small underflow", + Int64.powWrap(-2, 65), + M.equals(Int64Testable(0)) + ), + test( + "large underflow", + Int64.powWrap(Int64.minimumValue, 10), + M.equals(Int64Testable(0)) + ), + ] + ) +) diff --git a/test/int8Test.mo b/test/int8Test.mo index f9335e7c..559bb084 100644 --- a/test/int8Test.mo +++ b/test/int8Test.mo @@ -1,7 +1,2304 @@ -import Debug "mo:base/Debug"; import Int8 "mo:base/Int8"; +import Order "mo:base/Order"; +import Iter "mo:base/Iter"; -assert (Int8.fromIntWrap(256) == (0 : Int8)); -assert (Int8.fromIntWrap(-256) == (0 : Int8)); -assert (Int8.fromIntWrap(128) == (-128 : Int8)); -assert (Int8.fromIntWrap(255) == (-1 : Int8)) +import Suite "mo:matchers/Suite"; +import T "mo:matchers/Testable"; +import M "mo:matchers/Matchers"; + +let { run; test; suite } = Suite; + +let maximumInt8asInt = +2 ** 7 - 1 : Int; +let maximumInt8asNat8 = 2 ** 7 - 1 : Nat8; + +let minimumInt8asInt = -2 ** 7 : Int; + +let maximumNat8 = 255 : Nat8; + +class Int8Testable(number : Int8) : T.TestableItem { + public let item = number; + public func display(number : Int8) : Text { + debug_show (number) + }; + public let equals = func(x : Int8, y : Int8) : Bool { + x == y + } +}; + +class Nat8Testable(number : Nat8) : T.TestableItem { + public let item = number; + public func display(number : Nat8) : Text { + debug_show (number) + }; + public let equals = func(x : Nat8, y : Nat8) : Bool { + x == y + } +}; + +type Order = { #less; #equal; #greater }; + +class OrderTestable(value : Order) : T.TestableItem { + public let item = value; + public func display(value : Order) : Text { + debug_show (value) + }; + public let equals = func(x : Order, y : Order) : Bool { + x == y + } +}; + +/* --------------------------------------- */ + +run( + suite( + "constants", + [ + test( + "minimum value", + Int8.minimumValue, + M.equals(Int8Testable(Int8.fromInt(-2 ** 7))) + ), + test( + "maximum value", + Int8.maximumValue, + M.equals(Int8Testable(Int8.fromInt(+2 ** 7 - 1))) + ), + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "toInt", + [ + test( + "maximum number", + Int8.toInt(Int8.maximumValue), + M.equals(T.int(maximumInt8asInt)) + ), + test( + "minimum number", + Int8.toInt(Int8.minimumValue), + M.equals(T.int(minimumInt8asInt)) + ), + test( + "one", + Int8.toInt(1), + M.equals(T.int(1)) + ), + test( + "minus one", + Int8.toInt(-1), + M.equals(T.int(-1)) + ), + test( + "zero", + Int8.toInt(0), + M.equals(T.int(0)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "fromInt", + [ + test( + "maximum number", + Int8.fromInt(maximumInt8asInt), + M.equals(Int8Testable(Int8.maximumValue)) + ), + test( + "minimum number", + Int8.fromInt(minimumInt8asInt), + M.equals(Int8Testable(Int8.minimumValue)) + ), + test( + "one", + Int8.fromInt(1), + M.equals(Int8Testable(1)) + ), + test( + "minus one", + Int8.fromInt(-1), + M.equals(Int8Testable(-1)) + ), + test( + "zero", + Int8.fromInt(0), + M.equals(Int8Testable(0)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "fromIntWrap", + [ + test( + "maximum number", + Int8.fromIntWrap(maximumInt8asInt), + M.equals(Int8Testable(Int8.maximumValue)) + ), + test( + "minimum number", + Int8.fromIntWrap(minimumInt8asInt), + M.equals(Int8Testable(Int8.minimumValue)) + ), + test( + "one", + Int8.fromIntWrap(1), + M.equals(Int8Testable(1)) + ), + test( + "minus one", + Int8.fromIntWrap(-1), + M.equals(Int8Testable(-1)) + ), + test( + "zero", + Int8.fromIntWrap(0), + M.equals(Int8Testable(0)) + ), + test( + "overflow", + Int8.fromIntWrap(maximumInt8asInt + 1), + M.equals(Int8Testable(Int8.minimumValue)) + ), + test( + "underflow", + Int8.fromIntWrap(minimumInt8asInt - 1), + M.equals(Int8Testable(Int8.maximumValue)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "fromNat8", + [ + test( + "maximum number", + Int8.fromNat8(maximumInt8asNat8), + M.equals(Int8Testable(Int8.maximumValue)) + ), + test( + "one", + Int8.fromNat8(1), + M.equals(Int8Testable(1)) + ), + test( + "zero", + Int8.fromNat8(0), + M.equals(Int8Testable(0)) + ), + test( + "overflow", + Int8.fromNat8(maximumInt8asNat8 + 1), + M.equals(Int8Testable(Int8.minimumValue)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "toNat8", + [ + test( + "maximum number", + Int8.toNat8(Int8.maximumValue), + M.equals(Nat8Testable(maximumInt8asNat8)) + ), + test( + "one", + Int8.toNat8(1), + M.equals(Nat8Testable(1)) + ), + test( + "zero", + Int8.toNat8(0), + M.equals(Nat8Testable(0)) + ), + test( + "underflow", + Int8.toNat8(-1), + M.equals(Nat8Testable(maximumNat8)) + ) + ] + ) +); + + +/* --------------------------------------- */ + +run( + suite( + "toText", + [ + test( + "positive", + Int8.toText(123), + M.equals(T.text("123")) + ), + test( + "negative", + Int8.toText(-123), + M.equals(T.text("-123")) + ), + test( + "zero", + Int8.toText(0), + M.equals(T.text("0")) + ), + test( + "maximum number", + Int8.toText(Int8.maximumValue), + M.equals(T.text("127")) + ), + test( + "minimum number", + Int8.toText(Int8.minimumValue), + M.equals(T.text("-128")) + ) + ] + ) +); + + +/* --------------------------------------- */ + +run( + suite( + "abs", + [ + test( + "positive number", + Int8.abs(123), + M.equals(Int8Testable(123)) + ), + test( + "negative number", + Int8.abs(-123), + M.equals(Int8Testable(123)) + ), + test( + "zero", + Int8.abs(0), + M.equals(Int8Testable(0)) + ), + test( + "maximum number", + Int8.abs(Int8.maximumValue), + M.equals(Int8Testable(Int8.maximumValue)) + ), + test( + "smallest possible", + Int8.abs(-Int8.maximumValue), + M.equals(Int8Testable(Int8.maximumValue)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "min", + [ + test( + "both positive", + Int8.min(2, 3), + M.equals(Int8Testable(2)) + ), + test( + "positive, negative", + Int8.min(2, -3), + M.equals(Int8Testable(-3)) + ), + test( + "both negative", + Int8.min(-2, -3), + M.equals(Int8Testable(-3)) + ), + test( + "negative, positive", + Int8.min(-2, 3), + M.equals(Int8Testable(-2)) + ), + test( + "equal values", + Int8.min(123, 123), + M.equals(Int8Testable(123)) + ), + test( + "maximum and minimum number", + Int8.min(Int8.maximumValue, Int8.minimumValue), + M.equals(Int8Testable(Int8.minimumValue)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "max", + [ + test( + "both positive", + Int8.max(2, 3), + M.equals(Int8Testable(3)) + ), + test( + "positive, negative", + Int8.max(2, -3), + M.equals(Int8Testable(2)) + ), + test( + "both negative", + Int8.max(-2, -3), + M.equals(Int8Testable(-2)) + ), + test( + "negative, positive", + Int8.max(-2, 3), + M.equals(Int8Testable(3)) + ), + test( + "equal values", + Int8.max(123, 123), + M.equals(Int8Testable(123)) + ), + test( + "maximum and minimum number", + Int8.max(Int8.maximumValue, Int8.minimumValue), + M.equals(Int8Testable(Int8.maximumValue)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "equal", + [ + test( + "positive equal", + Int8.equal(123, 123), + M.equals(T.bool(true)) + ), + test( + "negative equal", + Int8.equal(-123, -123), + M.equals(T.bool(true)) + ), + test( + "zero", + Int8.equal(0, 0), + M.equals(T.bool(true)) + ), + test( + "positive not equal", + Int8.equal(123, 124), + M.equals(T.bool(false)) + ), + test( + "negative not equal", + Int8.equal(-123, -124), + M.equals(T.bool(false)) + ), + test( + "mixed signs", + Int8.equal(123, -123), + M.equals(T.bool(false)) + ), + test( + "maxmimum equal", + Int8.equal(Int8.maximumValue, Int8.maximumValue), + M.equals(T.bool(true)) + ), + test( + "minimum equal", + Int8.equal(Int8.minimumValue, Int8.minimumValue), + M.equals(T.bool(true)) + ), + test( + "minimum and maximum", + Int8.equal(Int8.minimumValue, Int8.maximumValue), + M.equals(T.bool(false)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "notEqual", + [ + test( + "positive equal", + Int8.notEqual(123, 123), + M.equals(T.bool(false)) + ), + test( + "negative equal", + Int8.notEqual(-123, -123), + M.equals(T.bool(false)) + ), + test( + "zero", + Int8.notEqual(0, 0), + M.equals(T.bool(false)) + ), + test( + "positive not equal", + Int8.notEqual(123, 124), + M.equals(T.bool(true)) + ), + test( + "negative not equal", + Int8.notEqual(-123, -124), + M.equals(T.bool(true)) + ), + test( + "mixed signs", + Int8.notEqual(123, -123), + M.equals(T.bool(true)) + ), + test( + "maxmimum equal", + Int8.notEqual(Int8.maximumValue, Int8.maximumValue), + M.equals(T.bool(false)) + ), + test( + "minimum equal", + Int8.notEqual(Int8.minimumValue, Int8.minimumValue), + M.equals(T.bool(false)) + ), + test( + "minimum and maximum", + Int8.notEqual(Int8.minimumValue, Int8.maximumValue), + M.equals(T.bool(true)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "less", + [ + test( + "positive equal", + Int8.less(123, 123), + M.equals(T.bool(false)) + ), + test( + "positive less", + Int8.less(123, 124), + M.equals(T.bool(true)) + ), + test( + "positive greater", + Int8.less(124, 123), + M.equals(T.bool(false)) + ), + test( + "negative equal", + Int8.less(-123, -123), + M.equals(T.bool(false)) + ), + test( + "negative less", + Int8.less(-124, -123), + M.equals(T.bool(true)) + ), + test( + "negative greater", + Int8.less(-123, -124), + M.equals(T.bool(false)) + ), + test( + "zero", + Int8.less(0, 0), + M.equals(T.bool(false)) + ), + test( + "mixed signs less", + Int8.less(-123, 123), + M.equals(T.bool(true)) + ), + test( + "mixed signs greater", + Int8.less(123, -123), + M.equals(T.bool(false)) + ), + test( + "minimum and maximum", + Int8.less(Int8.minimumValue, Int8.maximumValue), + M.equals(T.bool(true)) + ), + test( + "maximum and minimum", + Int8.less(Int8.maximumValue, Int8.minimumValue), + M.equals(T.bool(false)) + ), + test( + "maximum and maximum", + Int8.less(Int8.maximumValue, Int8.maximumValue), + M.equals(T.bool(false)) + ), + test( + "minimum and minimum", + Int8.less(Int8.minimumValue, Int8.minimumValue), + M.equals(T.bool(false)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "lessOrEqual", + [ + test( + "positive equal", + Int8.lessOrEqual(123, 123), + M.equals(T.bool(true)) + ), + test( + "positive less", + Int8.lessOrEqual(123, 124), + M.equals(T.bool(true)) + ), + test( + "positive greater", + Int8.lessOrEqual(124, 123), + M.equals(T.bool(false)) + ), + test( + "negative equal", + Int8.lessOrEqual(-123, -123), + M.equals(T.bool(true)) + ), + test( + "negative less", + Int8.lessOrEqual(-124, -123), + M.equals(T.bool(true)) + ), + test( + "negative greater", + Int8.lessOrEqual(-123, -124), + M.equals(T.bool(false)) + ), + test( + "zero", + Int8.lessOrEqual(0, 0), + M.equals(T.bool(true)) + ), + test( + "mixed signs less", + Int8.lessOrEqual(-123, 123), + M.equals(T.bool(true)) + ), + test( + "mixed signs greater", + Int8.lessOrEqual(123, -123), + M.equals(T.bool(false)) + ), + test( + "minimum and maximum", + Int8.lessOrEqual(Int8.minimumValue, Int8.maximumValue), + M.equals(T.bool(true)) + ), + test( + "maximum and minimum", + Int8.lessOrEqual(Int8.maximumValue, Int8.minimumValue), + M.equals(T.bool(false)) + ), + test( + "maximum and maximum", + Int8.lessOrEqual(Int8.maximumValue, Int8.maximumValue), + M.equals(T.bool(true)) + ), + test( + "minimum and minimum", + Int8.lessOrEqual(Int8.minimumValue, Int8.minimumValue), + M.equals(T.bool(true)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "greater", + [ + test( + "positive equal", + Int8.greater(123, 123), + M.equals(T.bool(false)) + ), + test( + "positive less", + Int8.greater(123, 124), + M.equals(T.bool(false)) + ), + test( + "positive greater", + Int8.greater(124, 123), + M.equals(T.bool(true)) + ), + test( + "negative equal", + Int8.greater(-123, -123), + M.equals(T.bool(false)) + ), + test( + "negative less", + Int8.greater(-124, -123), + M.equals(T.bool(false)) + ), + test( + "negative greater", + Int8.greater(-123, -124), + M.equals(T.bool(true)) + ), + test( + "zero", + Int8.greater(0, 0), + M.equals(T.bool(false)) + ), + test( + "mixed signs less", + Int8.greater(-123, 123), + M.equals(T.bool(false)) + ), + test( + "mixed signs greater", + Int8.greater(123, -123), + M.equals(T.bool(true)) + ), + test( + "minimum and maximum", + Int8.greater(Int8.minimumValue, Int8.maximumValue), + M.equals(T.bool(false)) + ), + test( + "maximum and minimum", + Int8.greater(Int8.maximumValue, Int8.minimumValue), + M.equals(T.bool(true)) + ), + test( + "maximum and maximum", + Int8.greater(Int8.maximumValue, Int8.maximumValue), + M.equals(T.bool(false)) + ), + test( + "minimum and minimum", + Int8.greater(Int8.minimumValue, Int8.minimumValue), + M.equals(T.bool(false)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "greaterOrEqual", + [ + test( + "positive equal", + Int8.greaterOrEqual(123, 123), + M.equals(T.bool(true)) + ), + test( + "positive less", + Int8.greaterOrEqual(123, 124), + M.equals(T.bool(false)) + ), + test( + "positive greater", + Int8.greaterOrEqual(124, 123), + M.equals(T.bool(true)) + ), + test( + "negative equal", + Int8.greaterOrEqual(-123, -123), + M.equals(T.bool(true)) + ), + test( + "negative less", + Int8.greaterOrEqual(-124, -123), + M.equals(T.bool(false)) + ), + test( + "negative greater", + Int8.greaterOrEqual(-123, -124), + M.equals(T.bool(true)) + ), + test( + "zero", + Int8.greaterOrEqual(0, 0), + M.equals(T.bool(true)) + ), + test( + "mixed signs less", + Int8.greaterOrEqual(-123, 123), + M.equals(T.bool(false)) + ), + test( + "mixed signs greater", + Int8.greaterOrEqual(123, -123), + M.equals(T.bool(true)) + ), + test( + "minimum and maximum", + Int8.greaterOrEqual(Int8.minimumValue, Int8.maximumValue), + M.equals(T.bool(false)) + ), + test( + "maximum and minimum", + Int8.greaterOrEqual(Int8.maximumValue, Int8.minimumValue), + M.equals(T.bool(true)) + ), + test( + "maximum and maximum", + Int8.greaterOrEqual(Int8.maximumValue, Int8.maximumValue), + M.equals(T.bool(true)) + ), + test( + "minimum and minimum", + Int8.greaterOrEqual(Int8.minimumValue, Int8.minimumValue), + M.equals(T.bool(true)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "compare", + [ + test( + "positive equal", + Int8.compare(123, 123), + M.equals(OrderTestable(#equal)) + ), + test( + "positive less", + Int8.compare(123, 124), + M.equals(OrderTestable(#less)) + ), + test( + "positive greater", + Int8.compare(124, 123), + M.equals(OrderTestable(#greater)) + ), + test( + "negative equal", + Int8.compare(-123, -123), + M.equals(OrderTestable(#equal)) + ), + test( + "negative less", + Int8.compare(-124, -123), + M.equals(OrderTestable(#less)) + ), + test( + "negative greater", + Int8.compare(-123, -124), + M.equals(OrderTestable(#greater)) + ), + test( + "zero", + Int8.compare(0, 0), + M.equals(OrderTestable(#equal)) + ), + test( + "mixed signs less", + Int8.compare(-123, 123), + M.equals(OrderTestable(#less)) + ), + test( + "mixed signs greater", + Int8.compare(123, -123), + M.equals(OrderTestable(#greater)) + ), + test( + "minimum and maximum", + Int8.compare(Int8.minimumValue, Int8.maximumValue), + M.equals(OrderTestable(#less)) + ), + test( + "maximum and minimum", + Int8.compare(Int8.maximumValue, Int8.minimumValue), + M.equals(OrderTestable(#greater)) + ), + test( + "maximum and maximum", + Int8.compare(Int8.maximumValue, Int8.maximumValue), + M.equals(OrderTestable(#equal)) + ), + test( + "minimum and minimum", + Int8.compare(Int8.minimumValue, Int8.minimumValue), + M.equals(OrderTestable(#equal)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "neg", + [ + test( + "positive number", + Int8.neg(123), + M.equals(Int8Testable(-123)) + ), + test( + "negative number", + Int8.neg(-123), + M.equals(Int8Testable(123)) + ), + test( + "zero", + Int8.neg(0), + M.equals(Int8Testable(0)) + ), + test( + "maximum number", + Int8.neg(Int8.maximumValue), + M.equals(Int8Testable(-Int8.maximumValue)) + ), + test( + "smallest possible", + Int8.neg(-Int8.maximumValue), + M.equals(Int8Testable(Int8.maximumValue)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "add", + [ + test( + "positive", + Int8.add(100, 23), + M.equals(Int8Testable(123)) + ), + test( + "negative", + Int8.add(-100, -23), + M.equals(Int8Testable(-123)) + ), + test( + "mixed signs", + Int8.add(-123, 23), + M.equals(Int8Testable(-100)) + ), + test( + "zero", + Int8.add(0, 0), + M.equals(Int8Testable(0)) + ), + test( + "minimum and maximum", + Int8.add(Int8.minimumValue, Int8.maximumValue), + M.equals(Int8Testable(-1)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "sub", + [ + test( + "positive", + Int8.sub(123, 123), + M.equals(Int8Testable(0)) + ), + test( + "negative", + Int8.sub(-123, -123), + M.equals(Int8Testable(0)) + ), + test( + "mixed signs", + Int8.sub(-100, 23), + M.equals(Int8Testable(-123)) + ), + test( + "zero", + Int8.sub(0, 0), + M.equals(Int8Testable(0)) + ), + test( + "maximum and maximum", + Int8.sub(Int8.maximumValue, Int8.maximumValue), + M.equals(Int8Testable(0)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "mul", + [ + test( + "positive", + Int8.mul(7, 15), + M.equals(Int8Testable(105)) + ), + test( + "negative", + Int8.mul(-7, -15), + M.equals(Int8Testable(105)) + ), + test( + "mixed signs", + Int8.mul(-7, 15), + M.equals(Int8Testable(-105)) + ), + test( + "zeros", + Int8.mul(0, 0), + M.equals(Int8Testable(0)) + ), + test( + "zero and maximum", + Int8.mul(0, Int8.maximumValue), + M.equals(Int8Testable(0)) + ), + test( + "minimum and zero", + Int8.mul(Int8.minimumValue, 0), + M.equals(Int8Testable(0)) + ), + test( + "one and maximum", + Int8.mul(1, Int8.maximumValue), + M.equals(Int8Testable(Int8.maximumValue)) + ), + test( + "minimum and one", + Int8.mul(Int8.minimumValue, 1), + M.equals(Int8Testable(Int8.minimumValue)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "div", + [ + test( + "positive multiple", + Int8.div(121, 11), + M.equals(Int8Testable(11)) + ), + test( + "positive remainder", + Int8.div(121, 13), + M.equals(Int8Testable(9)) + ), + test( + "negative multiple", + Int8.div(-121, -11), + M.equals(Int8Testable(11)) + ), + test( + "negative remainder", + Int8.div(-121, -13), + M.equals(Int8Testable(9)) + ), + test( + "mixed signs", + Int8.div(-121, 13), + M.equals(Int8Testable(-9)) + ), + test( + "zero and number", + Int8.div(0, -123), + M.equals(Int8Testable(0)) + ), + test( + "zero and maximum", + Int8.div(0, Int8.maximumValue), + M.equals(Int8Testable(0)) + ), + test( + "zero and minimum", + Int8.div(0, Int8.minimumValue), + M.equals(Int8Testable(0)) + ), + test( + "maximum and maximum", + Int8.div(Int8.maximumValue, Int8.maximumValue), + M.equals(Int8Testable(1)) + ), + test( + "minimum and minimum", + Int8.div(Int8.minimumValue, Int8.minimumValue), + M.equals(Int8Testable(1)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "rem", + [ + test( + "positive multiple", + Int8.rem(121, 11), + M.equals(Int8Testable(0)) + ), + test( + "positive/positive remainder", + Int8.rem(121, 13), + M.equals(Int8Testable(4)) + ), + test( + "positive/negative remainder", + Int8.rem(121, -13), + M.equals(Int8Testable(4)) + ), + test( + "negative multiple", + Int8.rem(-121, -11), + M.equals(Int8Testable(0)) + ), + test( + "negative/positive remainder", + Int8.rem(-121, 13), + M.equals(Int8Testable(-4)) + ), + test( + "negative/negative remainder", + Int8.rem(-121, -13), + M.equals(Int8Testable(-4)) + ), + test( + "zero and maximum", + Int8.rem(0, Int8.maximumValue), + M.equals(Int8Testable(0)) + ), + test( + "zero and minimum", + Int8.rem(0, Int8.minimumValue), + M.equals(Int8Testable(0)) + ), + test( + "maximum and maximum", + Int8.rem(Int8.maximumValue, Int8.maximumValue), + M.equals(Int8Testable(0)) + ), + test( + "minimum and minimum", + Int8.rem(Int8.minimumValue, Int8.minimumValue), + M.equals(Int8Testable(0)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "pow", + [ + test( + "positive base, positive exponent", + Int8.pow(3, 4), + M.equals(Int8Testable(81)) + ), + test( + "positive base, zero exponent", + Int8.pow(2, 0), + M.equals(Int8Testable(1)) + ), + test( + "negative base, odd exponent", + Int8.pow(-3, 3), + M.equals(Int8Testable(-27)) + ), + test( + "negative base, even exponent", + Int8.pow(-3, 4), + M.equals(Int8Testable(81)) + ), + test( + "negative base, zero exponent", + Int8.pow(-3, 0), + M.equals(Int8Testable(1)) + ), + test( + "maximum and zero", + Int8.pow(Int8.maximumValue, 0), + M.equals(Int8Testable(1)) + ), + test( + "minimum and zero", + Int8.pow(Int8.minimumValue, 0), + M.equals(Int8Testable(1)) + ), + test( + "plus one and maximum", + Int8.pow(1, Int8.maximumValue), + M.equals(Int8Testable(1)) + ), + test( + "minus one and maximum", + Int8.pow(-1, Int8.maximumValue), + M.equals(Int8Testable(-1)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitnot", + [ + test( + "zero", + Int8.bitnot(0), + M.equals(Int8Testable(-1)) + ), + test( + "minus 1", + Int8.bitnot(-1), + M.equals(Int8Testable(0)) + ), + test( + "maximum", + Int8.bitnot(Int8.maximumValue), + M.equals(Int8Testable(Int8.minimumValue)) + ), + test( + "minimum", + Int8.bitnot(Int8.minimumValue), + M.equals(Int8Testable(Int8.maximumValue)) + ), + test( + "arbitrary", + Int8.bitnot(123), + M.equals(Int8Testable(-124)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitand", + [ + test( + "inverted", + Int8.bitand(0x70, 0x0f), + M.equals(Int8Testable(0)) + ), + test( + "overlap", + Int8.bitand(0x50, 0x7f), + M.equals(Int8Testable(0x50)) + ), + test( + "arbitrary", + Int8.bitand(0x12, 0x76), + M.equals(Int8Testable(0x12)) + ), + test( + "negative", + Int8.bitand(-123, -123), + M.equals(Int8Testable(-123)) + ), + test( + "mixed signs", + Int8.bitand(-64, 63), + M.equals(Int8Testable(0)) + ), + test( + "zero", + Int8.bitand(0, 0), + M.equals(Int8Testable(0)) + ), + test( + "zero and maximum", + Int8.bitand(0, Int8.maximumValue), + M.equals(Int8Testable(0)) + ), + test( + "minimum and zero", + Int8.bitand(Int8.minimumValue, 0), + M.equals(Int8Testable(0)) + ), + test( + "minimum and maximum", + Int8.bitand(Int8.minimumValue, Int8.maximumValue), + M.equals(Int8Testable(0)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitor", + [ + test( + "inverted", + Int8.bitor(0x70, 0x0f), + M.equals(Int8Testable(0x7f)) + ), + test( + "overlap", + Int8.bitor(0x0f, 0x7f), + M.equals(Int8Testable(0x7f)) + ), + test( + "arbitrary", + Int8.bitor(0x12, 0x76), + M.equals(Int8Testable(0x76)) + ), + test( + "negative", + Int8.bitor(-123, -123), + M.equals(Int8Testable(-123)) + ), + test( + "mixed signs", + Int8.bitor(-128, 127), + M.equals(Int8Testable(-1)) + ), + test( + "zero", + Int8.bitor(0, 0), + M.equals(Int8Testable(0)) + ), + test( + "zero and maximum", + Int8.bitor(0, Int8.maximumValue), + M.equals(Int8Testable(Int8.maximumValue)) + ), + test( + "minimum and zero", + Int8.bitor(Int8.minimumValue, 0), + M.equals(Int8Testable(Int8.minimumValue)) + ), + test( + "minimum and maximum", + Int8.bitor(Int8.minimumValue, Int8.maximumValue), + M.equals(Int8Testable(-1)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitxor", + [ + test( + "inverted", + Int8.bitxor(0x70, 0x0f), + M.equals(Int8Testable(0x7f)) + ), + test( + "overlap", + Int8.bitxor(0x0f, 0x7f), + M.equals(Int8Testable(0x70)) + ), + test( + "arbitrary", + Int8.bitxor(0x12, 0x76), + M.equals(Int8Testable(0x64)) + ), + test( + "negative", + Int8.bitxor(-123, -123), + M.equals(Int8Testable(0)) + ), + test( + "mixed signs", + Int8.bitxor(-128, 127), + M.equals(Int8Testable(-1)) + ), + test( + "zero", + Int8.bitxor(0, 0), + M.equals(Int8Testable(0)) + ), + test( + "zero and maximum", + Int8.bitxor(0, Int8.maximumValue), + M.equals(Int8Testable(Int8.maximumValue)) + ), + test( + "minimum and zero", + Int8.bitxor(Int8.minimumValue, 0), + M.equals(Int8Testable(Int8.minimumValue)) + ), + test( + "minimum and maximum", + Int8.bitxor(Int8.minimumValue, Int8.maximumValue), + M.equals(Int8Testable(-1)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitshiftLeft", + [ + test( + "positive number", + Int8.bitshiftLeft(0x71, 4), + M.equals(Int8Testable(0x10)) + ), + test( + "negative number", + Int8.bitshiftLeft(-32, 2), + M.equals(Int8Testable(-128)) + ), + test( + "arbitrary", + Int8.bitshiftLeft(100, 3), + M.equals(Int8Testable(32)) + ), + test( + "zero shift", + Int8.bitshiftLeft(123, 0), + M.equals(Int8Testable(123)) + ), + test( + "one maximum shift", + Int8.bitshiftLeft(1, 7), + M.equals(Int8Testable(Int8.minimumValue)) + ), + test( + "minimum number", + Int8.bitshiftLeft(-1, 7), + M.equals(Int8Testable(Int8.minimumValue)) + ), + test( + "discard overflow", + Int8.bitshiftLeft(0x7f, 4), + M.equals(Int8Testable(-16)) + ), + test( + "beyond bit length positive", + Int8.bitshiftLeft(0x12, 16 + 7), + M.equals(Int8Testable(Int8.bitshiftLeft(0x12, 7))) + ), + test( + "beyond bit length negative", + Int8.bitshiftLeft(-0x12, 8 + 7), + M.equals(Int8Testable(Int8.bitshiftLeft(-0x12, 7))) + ), + test( + "negative shift argument", + Int8.bitshiftLeft(0x12, -7), + M.equals(Int8Testable(Int8.bitshiftLeft(0x12, 8 - 7))) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitshiftRight", + [ + test( + "positive number", + Int8.bitshiftRight(0x71, 4), + M.equals(Int8Testable(0x07)) + ), + test( + "negative number", + Int8.bitshiftRight(-32, 2), + M.equals(Int8Testable(-8)) + ), + test( + "arbitrary", + Int8.bitshiftRight(100, 3), + M.equals(Int8Testable(12)) + ), + test( + "zero shift", + Int8.bitshiftRight(123, 0), + M.equals(Int8Testable(123)) + ), + test( + "minus one maximum shift", + Int8.bitshiftRight(-1, 7), + M.equals(Int8Testable(-1)) + ), + test( + "minimum number", + Int8.bitshiftRight(Int8.minimumValue, 7), + M.equals(Int8Testable(-1)) + ), + test( + "discard underflow", + Int8.bitshiftRight(0x0f, 4), + M.equals(Int8Testable(0)) + ), + test( + "beyond bit length positive", + Int8.bitshiftRight(0x12, 16 + 3), + M.equals(Int8Testable(Int8.bitshiftRight(0x12, 3))) + ), + test( + "beyond bit length negative", + Int8.bitshiftRight(-0x12, 8 + 3), + M.equals(Int8Testable(Int8.bitshiftRight(-0x12, 3))) + ), + test( + "negative shift argument", + Int8.bitshiftRight(0x12, -3), + M.equals(Int8Testable(Int8.bitshiftRight(0x12, 8 - 3))) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitrotLeft", + [ + test( + "positive number non-overflow", + Int8.bitrotLeft(0x07, 4), + M.equals(Int8Testable(0x70)) + ), + test( + "positive number overflow", + Int8.bitrotLeft(0x12, 4), + M.equals(Int8Testable(0x21)) + ), + test( + "negative number", + Int8.bitrotLeft(-128, 2), + M.equals(Int8Testable(2)) + ), + test( + "arbitrary", + Int8.bitrotLeft(123, 3), + M.equals(Int8Testable(-37)) + ), + test( + "zero shift", + Int8.bitrotLeft(123, 0), + M.equals(Int8Testable(123)) + ), + test( + "minus one maximum rotate", + Int8.bitrotLeft(-1, 7), + M.equals(Int8Testable(-1)) + ), + test( + "maximum number", + Int8.bitrotLeft(Int8.maximumValue, 1), + M.equals(Int8Testable(-2)) + ), + test( + "minimum number", + Int8.bitrotLeft(1, 7), + M.equals(Int8Testable(Int8.minimumValue)) + ), + test( + "opposite rotation", + Int8.bitrotLeft(64, -2), + M.equals(Int8Testable(16)) + ), + test( + "rotate beyond bit length", + Int8.bitrotLeft(64, 10), + M.equals(Int8Testable(1)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitrotRight", + [ + test( + "positive number non-underflow", + Int8.bitrotRight(0x70, 4), + M.equals(Int8Testable(0x07)) + ), + test( + "positive number underflow", + Int8.bitrotRight(0x12, 4), + M.equals(Int8Testable(0x21)) + ), + test( + "negative number", + Int8.bitrotRight(-128, 2), + M.equals(Int8Testable(32)) + ), + test( + "arbitrary", + Int8.bitrotRight(123, 3), + M.equals(Int8Testable(111)) + ), + test( + "zero shift", + Int8.bitrotRight(123, 0), + M.equals(Int8Testable(123)) + ), + test( + "minus one maximum rotate", + Int8.bitrotRight(-1, 7), + M.equals(Int8Testable(-1)) + ), + test( + "maximum number", + Int8.bitrotRight(-2, 1), + M.equals(Int8Testable(Int8.maximumValue)) + ), + test( + "minimum number", + Int8.bitrotRight(Int8.minimumValue, 7), + M.equals(Int8Testable(1)) + ), + test( + "opposite rotation", + Int8.bitrotRight(16, -2), + M.equals(Int8Testable(64)) + ), + test( + "rotate beyond bit length", + Int8.bitrotRight(64, 10), + M.equals(Int8Testable(16)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bittest", + [ + test( + "set bit", + Int8.bittest(64, 6), + M.equals(T.bool(true)) + ), + test( + "cleared bit", + Int8.bittest(-65, 6), + M.equals(T.bool(false)) + ), + test( + "all zero", + do { + let number = 0 : Int8; + var count = 0; + for (index in Iter.range(0, 7)) { + if (Int8.bittest(number, index)) { + count += 1 + } + }; + count + }, + M.equals(T.int(0)) + ), + test( + "all one", + do { + let number = -1 : Int8; + var count = 0; + for (index in Iter.range(0, 7)) { + if (Int8.bittest(number, index)) { + count += 1 + } + }; + count + }, + M.equals(T.int(8)) + ), + test( + "set bit beyond bit length", + Int8.bittest(64, 8 + 6), + M.equals(T.bool(true)) + ), + test( + "cleared bit beyond bit length", + Int8.bittest(-65, 16 + 6), + M.equals(T.bool(false)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitset", + [ + test( + "set bit", + Int8.bitset(0, 6), + M.equals(Int8Testable(64)) + ), + test( + "minus one", + Int8.bitset(-65, 6), + M.equals(Int8Testable(-1)) + ), + test( + "no effect", + Int8.bitset(64, 6), + M.equals(Int8Testable(64)) + ), + test( + "set all", + do { + var number = 0 : Int8; + for (index in Iter.range(0, 7)) { + number := Int8.bitset(number, index) + }; + number + }, + M.equals(Int8Testable(-1)) + ), + test( + "all no effect", + do { + var number = -1 : Int8; + for (index in Iter.range(0, 7)) { + number := Int8.bitset(number, index) + }; + number + }, + M.equals(Int8Testable(-1)) + ), + test( + "set bit beyond bit length", + Int8.bitset(0, 8 + 6), + M.equals(Int8Testable(64)) + ), + test( + "minus one beyond bit length", + Int8.bitset(-65, 16 + 6), + M.equals(Int8Testable(-1)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitclear", + [ + test( + "clear bit", + Int8.bitclear(64, 6), + M.equals(Int8Testable(0)) + ), + test( + "minus one", + Int8.bitclear(-1, 6), + M.equals(Int8Testable(-65)) + ), + test( + "no effect", + Int8.bitclear(0, 6), + M.equals(Int8Testable(0)) + ), + test( + "clear all", + do { + var number = -1 : Int8; + for (index in Iter.range(0, 7)) { + number := Int8.bitclear(number, index) + }; + number + }, + M.equals(Int8Testable(0)) + ), + test( + "all no effect", + do { + var number = 0 : Int8; + for (index in Iter.range(0, 7)) { + number := Int8.bitclear(number, index) + }; + number + }, + M.equals(Int8Testable(0)) + ), + test( + "clear bit beyond bit length", + Int8.bitclear(64, 8 + 6), + M.equals(Int8Testable(0)) + ), + test( + "minus one beyond bit length", + Int8.bitclear(-1, 16 + 6), + M.equals(Int8Testable(-65)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitflip", + [ + test( + "clear bit", + Int8.bitflip(127, 6), + M.equals(Int8Testable(63)) + ), + test( + "set bit", + Int8.bitflip(63, 6), + M.equals(Int8Testable(127)) + ), + test( + "double flip", + Int8.bitflip(Int8.bitflip(0x12, 5), 5), + M.equals(Int8Testable(0x12)) + ), + test( + "clear all", + do { + var number = -1 : Int8; + for (index in Iter.range(0, 7)) { + number := Int8.bitflip(number, index) + }; + number + }, + M.equals(Int8Testable(0)) + ), + test( + "set all", + do { + var number = 0 : Int8; + for (index in Iter.range(0, 7)) { + number := Int8.bitflip(number, index) + }; + number + }, + M.equals(Int8Testable(-1)) + ), + test( + "clear bit beyond bit length", + Int8.bitflip(127, 8 + 6), + M.equals(Int8Testable(63)) + ), + test( + "set bit beyond bit length", + Int8.bitflip(63, 16 + 6), + M.equals(Int8Testable(127)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitcountNonZero", + [ + test( + "zero", + Int8.bitcountNonZero(0), + M.equals(Int8Testable(0)) + ), + test( + "minus one", + Int8.bitcountNonZero(-1), + M.equals(Int8Testable(8)) + ), + test( + "minus two", + Int8.bitcountNonZero(-2), + M.equals(Int8Testable(7)) + ), + test( + "one", + Int8.bitcountNonZero(1), + M.equals(Int8Testable(1)) + ), + test( + "minimum value", + Int8.bitcountNonZero(Int8.minimumValue), + M.equals(Int8Testable(1)) + ), + test( + "maximum value", + Int8.bitcountNonZero(Int8.maximumValue), + M.equals(Int8Testable(7)) + ), + test( + "alternating bits positive", + Int8.bitcountNonZero(0x55), + M.equals(Int8Testable(4)) + ), + test( + "alternating bits negative", + Int8.bitcountNonZero(-0x56), + M.equals(Int8Testable(4)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitcountLeadingZero", + [ + test( + "zero", + Int8.bitcountLeadingZero(0), + M.equals(Int8Testable(8)) + ), + test( + "minus one", + Int8.bitcountLeadingZero(-1), + M.equals(Int8Testable(0)) + ), + test( + "minus two", + Int8.bitcountLeadingZero(-2), + M.equals(Int8Testable(0)) + ), + test( + "one", + Int8.bitcountLeadingZero(1), + M.equals(Int8Testable(7)) + ), + test( + "two", + Int8.bitcountLeadingZero(2), + M.equals(Int8Testable(6)) + ), + test( + "arbitrary", + Int8.bitcountLeadingZero(0x10), + M.equals(Int8Testable(3)) + ), + test( + "minimum value", + Int8.bitcountLeadingZero(Int8.minimumValue), + M.equals(Int8Testable(0)) + ), + test( + "maximum value", + Int8.bitcountLeadingZero(Int8.maximumValue), + M.equals(Int8Testable(1)) + ), + test( + "alternating bits positive", + Int8.bitcountLeadingZero(0x55), + M.equals(Int8Testable(1)) + ), + test( + "alternating bits negative", + Int8.bitcountLeadingZero(-0x56), + M.equals(Int8Testable(0)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "bitcountTrailingZero", + [ + test( + "zero", + Int8.bitcountTrailingZero(0), + M.equals(Int8Testable(8)) + ), + test( + "minus one", + Int8.bitcountTrailingZero(-1), + M.equals(Int8Testable(0)) + ), + test( + "minus two", + Int8.bitcountTrailingZero(-2), + M.equals(Int8Testable(1)) + ), + test( + "one", + Int8.bitcountTrailingZero(1), + M.equals(Int8Testable(0)) + ), + test( + "two", + Int8.bitcountTrailingZero(2), + M.equals(Int8Testable(1)) + ), + test( + "arbitrary", + Int8.bitcountTrailingZero(0x60), + M.equals(Int8Testable(5)) + ), + test( + "minimum value", + Int8.bitcountTrailingZero(Int8.minimumValue), + M.equals(Int8Testable(7)) + ), + test( + "maximum value", + Int8.bitcountTrailingZero(Int8.maximumValue), + M.equals(Int8Testable(0)) + ), + test( + "alternating bits positive", + Int8.bitcountTrailingZero(0x55), + M.equals(Int8Testable(0)) + ), + test( + "alternating bits negative", + Int8.bitcountTrailingZero(-0x56), + M.equals(Int8Testable(1)) + ) + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "addWrap", + [ + test( + "positive", + Int8.addWrap(100, 23), + M.equals(Int8Testable(123)) + ), + test( + "negative", + Int8.addWrap(-100, -23), + M.equals(Int8Testable(-123)) + ), + test( + "mixed signs", + Int8.addWrap(-123, 23), + M.equals(Int8Testable(-100)) + ), + test( + "zero", + Int8.addWrap(0, 0), + M.equals(Int8Testable(0)) + ), + test( + "minimum and maximum", + Int8.addWrap(Int8.minimumValue, Int8.maximumValue), + M.equals(Int8Testable(-1)) + ), + test( + "small overflow", + Int8.addWrap(Int8.maximumValue, 1), + M.equals(Int8Testable(Int8.minimumValue)) + ), + test( + "large overflow", + Int8.addWrap(Int8.maximumValue, Int8.maximumValue), + M.equals(Int8Testable(-2)) + ), + test( + "small underflow", + Int8.addWrap(Int8.minimumValue, -1), + M.equals(Int8Testable(Int8.maximumValue)) + ), + test( + "large underflow", + Int8.addWrap(Int8.minimumValue, Int8.minimumValue), + M.equals(Int8Testable(0)) + ), + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "subWrap", + [ + test( + "positive", + Int8.subWrap(123, 23), + M.equals(Int8Testable(100)) + ), + test( + "negative", + Int8.subWrap(-123, -23), + M.equals(Int8Testable(-100)) + ), + test( + "mixed signs", + Int8.subWrap(-100, 23), + M.equals(Int8Testable(-123)) + ), + test( + "zero", + Int8.subWrap(0, 0), + M.equals(Int8Testable(0)) + ), + test( + "maximum and maximum", + Int8.subWrap(Int8.maximumValue, Int8.maximumValue), + M.equals(Int8Testable(0)) + ), + test( + "small overflow", + Int8.subWrap(Int8.maximumValue, -1), + M.equals(Int8Testable(Int8.minimumValue)) + ), + test( + "large overflow", + Int8.subWrap(Int8.maximumValue, Int8.minimumValue), + M.equals(Int8Testable(-1)) + ), + test( + "small underflow", + Int8.subWrap(Int8.minimumValue, 1), + M.equals(Int8Testable(Int8.maximumValue)) + ), + test( + "large underflow", + Int8.subWrap(Int8.minimumValue, Int8.maximumValue), + M.equals(Int8Testable(1)) + ), + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "mulWrap", + [ + test( + "positive", + Int8.mulWrap(12, 10), + M.equals(Int8Testable(120)) + ), + test( + "negative", + Int8.mulWrap(-12, -10), + M.equals(Int8Testable(120)) + ), + test( + "mixed signs", + Int8.mulWrap(-12, 10), + M.equals(Int8Testable(-120)) + ), + test( + "zeros", + Int8.mulWrap(0, 0), + M.equals(Int8Testable(0)) + ), + test( + "zero and maximum", + Int8.mulWrap(0, Int8.maximumValue), + M.equals(Int8Testable(0)) + ), + test( + "minimum and zero", + Int8.mulWrap(Int8.minimumValue, 0), + M.equals(Int8Testable(0)) + ), + test( + "one and maximum", + Int8.mulWrap(1, Int8.maximumValue), + M.equals(Int8Testable(Int8.maximumValue)) + ), + test( + "minimum and one", + Int8.mulWrap(Int8.minimumValue, 1), + M.equals(Int8Testable(Int8.minimumValue)) + ), + test( + "small overflow", + Int8.mulWrap(2, Int8.maximumValue), + M.equals(Int8Testable(-2)) + ), + test( + "large overflow", + Int8.mulWrap(Int8.maximumValue, Int8.maximumValue), + M.equals(Int8Testable(1)) + ), + test( + "small underflow", + Int8.mulWrap(Int8.minimumValue, 2), + M.equals(Int8Testable(0)) + ), + test( + "large underflow", + Int8.mulWrap(Int8.minimumValue, Int8.minimumValue), + M.equals(Int8Testable(0)) + ), + ] + ) +); + +/* --------------------------------------- */ + +run( + suite( + "powWrap", + [ + test( + "positive base, positive exponent", + Int8.powWrap(4, 3), + M.equals(Int8Testable(64)) + ), + test( + "positive base, zero exponent", + Int8.powWrap(12, 0), + M.equals(Int8Testable(1)) + ), + test( + "negative base, positive exponent", + Int8.powWrap(-4, 3), + M.equals(Int8Testable(-64)) + ), + test( + "negative base, zero exponent", + Int8.powWrap(-12, 0), + M.equals(Int8Testable(1)) + ), + test( + "maximum and zero", + Int8.powWrap(Int8.maximumValue, 0), + M.equals(Int8Testable(1)) + ), + test( + "minimum and zero", + Int8.powWrap(Int8.minimumValue, 0), + M.equals(Int8Testable(1)) + ), + test( + "plus one and maximum", + Int8.powWrap(1, Int8.maximumValue), + M.equals(Int8Testable(1)) + ), + test( + "minus one and maximum", + Int8.powWrap(-1, Int8.maximumValue), + M.equals(Int8Testable(-1)) + ), + test( + "minimum value", + Int8.powWrap(-2, 7), + M.equals(Int8Testable(Int8.minimumValue)) + ), + test( + "small overflow", + Int8.powWrap(2, 7), + M.equals(Int8Testable(Int8.minimumValue)) + ), + test( + "large overflow", + Int8.powWrap(Int8.maximumValue, 2), + M.equals(Int8Testable(1)) + ), + test( + "small underflow", + Int8.powWrap(-2, 9), + M.equals(Int8Testable(0)) + ), + test( + "large underflow", + Int8.powWrap(Int8.minimumValue, 2), + M.equals(Int8Testable(0)) + ), + ] + ) +)