Files
swift-mirror/test/stdlib/Integers.swift.gyb
Stephen Canon 35db40c9f9 Make BinaryInteger._binaryLogarithm() return Int instead of Self (#18219)
Returning `Self` was probably a hack from when shifts were required to be homogenous and we didn't have good generic inits between integer types. Returning Int is more natural, because:

1. Dimensional analysis says that we shouldn't expect the logarithm to have the same type.
2. Int is guaranteed to be able to represent any object size, and BinaryInteger does not admit sparse representations, so the logarithm of the value cannot exceed allocated storage size.
3. Every single use case in the stdlib and tests is either unchanged or simplified by this change.
2018-07-25 14:04:32 -04:00

908 lines
26 KiB
Swift

//===--- Integers.swift.gyb -----------------------------------*- swift -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
// RUN: %empty-directory(%t)
// RUN: %gyb -DWORD_BITS=%target-ptrsize %s -o %t/Integers.swift
// RUN: %line-directive %t/Integers.swift -- %target-build-swift %t/Integers.swift -swift-version 4 -Onone -o %t/a.out
// RUN: %line-directive %t/Integers.swift -- %target-run %t/a.out
// REQUIRES: executable_test
// FIXME: this test runs forever on iOS arm64
// REQUIRES: OS=macosx
%{
word_bits = int(WORD_BITS) / 2
from SwiftIntTypes import all_integer_types
}%
/// Prints the message if the body is uncommented; used for
/// diagnostics.
@_transparent
public func _log(_ message: @autoclosure () -> String) {
// print(message())
}
extension FixedWidthInteger where Words : Collection {
/// a hex representation of every bit in the number
func hexBits(_ bitWidth: Int) -> String {
let hexDigits: [Unicode.Scalar] = [
"0", "1", "2", "3", "4", "5", "6", "7",
"8", "9", "A", "B", "C", "D", "E", "F"]
var result = "".unicodeScalars
var x = self
var nibbles: Int = 0
repeat {
if nibbles % 4 == 0 && nibbles != 0 {
result.insert("_", at: result.startIndex)
}
let lowUWord = x.words.first ?? 0
result.insert(
hexDigits[Int(lowUWord._value) & 0xF],
at: result.startIndex
)
x /= 16
nibbles += 1
}
while (nibbles << 2 < bitWidth || (x != 0 && x + 1 != 0))
return (self < 0 ? "[-]" : "[+]") + String(result)
}
var hex: String { return hexBits(0) }
}
typealias Word = Int${word_bits}
typealias UWord = UInt${word_bits}
typealias DWord = Int${word_bits*2}
typealias UDWord = UInt${word_bits*2}
struct MockBinaryInteger<T : BinaryInteger> {
var _value: T
init(_ value: T) {
_value = value
}
}
extension MockBinaryInteger : CustomStringConvertible {
var description: String {
return _value.description
}
}
extension MockBinaryInteger : ExpressibleByIntegerLiteral {
init(integerLiteral value: T.IntegerLiteralType) {
_value = T(integerLiteral: value)
}
}
extension MockBinaryInteger : Comparable {
static func < (lhs: MockBinaryInteger<T>, rhs: MockBinaryInteger<T>) -> Bool {
return lhs._value < rhs._value
}
static func == (
lhs: MockBinaryInteger<T>, rhs: MockBinaryInteger<T>
) -> Bool {
return lhs._value == rhs._value
}
}
extension MockBinaryInteger : Hashable {
var hashValue: Int {
return _value.hashValue
}
}
extension MockBinaryInteger : BinaryInteger {
static var isSigned: Bool {
return T.isSigned
}
init<Source>(_ source: Source) where Source : BinaryFloatingPoint {
_value = T(source)
}
init?<Source>(exactly source: Source) where Source : BinaryFloatingPoint {
guard let result = T(exactly: source) else { return nil }
_value = result
}
init<Source>(_ source: Source) where Source : BinaryInteger {
_value = T(source)
}
init?<Source>(exactly source: Source) where Source : BinaryInteger {
guard let result = T(exactly: source) else { return nil }
_value = result
}
init<Source>(truncatingIfNeeded source: Source) where Source : BinaryInteger {
_value = T(truncatingIfNeeded: source)
}
init<Source>(clamping source: Source) where Source : BinaryInteger {
_value = T(clamping: source)
}
var magnitude: MockBinaryInteger<T.Magnitude> {
return MockBinaryInteger<T.Magnitude>(_value.magnitude)
}
var words: T.Words {
return _value.words
}
var bitWidth: Int {
return _value.bitWidth
}
var trailingZeroBitCount: Int {
return _value.trailingZeroBitCount
}
static func + (
lhs: MockBinaryInteger<T>, rhs: MockBinaryInteger<T>
) -> MockBinaryInteger<T> {
return MockBinaryInteger(lhs._value + rhs._value)
}
static func += (lhs: inout MockBinaryInteger<T>, rhs: MockBinaryInteger<T>) {
lhs._value += rhs._value
}
static func - (
lhs: MockBinaryInteger<T>, rhs: MockBinaryInteger<T>
) -> MockBinaryInteger<T> {
return MockBinaryInteger(lhs._value - rhs._value)
}
static func -= (lhs: inout MockBinaryInteger<T>, rhs: MockBinaryInteger<T>) {
lhs._value -= rhs._value
}
static func * (
lhs: MockBinaryInteger<T>, rhs: MockBinaryInteger<T>
) -> MockBinaryInteger<T> {
return MockBinaryInteger(lhs._value * rhs._value)
}
static func *= (lhs: inout MockBinaryInteger<T>, rhs: MockBinaryInteger<T>) {
lhs._value *= rhs._value
}
static func / (
lhs: MockBinaryInteger<T>, rhs: MockBinaryInteger<T>
) -> MockBinaryInteger<T> {
return MockBinaryInteger(lhs._value / rhs._value)
}
static func /= (lhs: inout MockBinaryInteger<T>, rhs: MockBinaryInteger<T>) {
lhs._value /= rhs._value
}
static func % (
lhs: MockBinaryInteger<T>, rhs: MockBinaryInteger<T>
) -> MockBinaryInteger<T> {
return MockBinaryInteger(lhs._value % rhs._value)
}
static func %= (lhs: inout MockBinaryInteger<T>, rhs: MockBinaryInteger<T>) {
lhs._value %= rhs._value
}
static func &= (lhs: inout MockBinaryInteger<T>, rhs: MockBinaryInteger<T>) {
lhs._value &= rhs._value
}
static func |= (lhs: inout MockBinaryInteger<T>, rhs: MockBinaryInteger<T>) {
lhs._value |= rhs._value
}
static func ^= (lhs: inout MockBinaryInteger<T>, rhs: MockBinaryInteger<T>) {
lhs._value ^= rhs._value
}
static prefix func ~ (x: MockBinaryInteger<T>) -> MockBinaryInteger<T> {
return MockBinaryInteger(~x._value)
}
static func >>= <RHS>(
lhs: inout MockBinaryInteger<T>, rhs: RHS
) where RHS : BinaryInteger {
lhs._value >>= rhs
}
static func <<= <RHS>(
lhs: inout MockBinaryInteger<T>, rhs: RHS
) where RHS : BinaryInteger {
lhs._value <<= rhs
}
}
import StdlibUnittest
func expectEqual<T : FixedWidthInteger>(
_ expected: T, _ actual: T,
_ message: @autoclosure () -> String = "",
stackTrace: SourceLocStack = SourceLocStack(),
showFrame: Bool = true,
file: String = #file, line: UInt = #line
) where T.Words : Collection {
if expected != actual {
expectationFailure(
"expected: \(String(reflecting: expected))"
+ " (of type \(String(reflecting: type(of: expected))))\n"
+ " = \(expected.hex)\n"
+ "actual: \(String(reflecting: actual))"
+ " (of type \(String(reflecting: type(of: actual))))\n"
+ " = \(actual.hex)\n",
trace: message(),
stackTrace: stackTrace.pushIf(showFrame, file: file, line: line))
}
}
func expectEqual<T : FixedWidthInteger>(
_ expected: (T, Bool), _ actual: (T, Bool),
_ message: @autoclosure () -> String = "",
stackTrace: SourceLocStack = SourceLocStack(),
showFrame: Bool = true,
file: String = #file, line: UInt = #line
) {
% for i in 0, 1:
expectEqual(
expected.${i}, actual.${i}, message(),
stackTrace: stackTrace.pushIf(showFrame, file: file, line: line),
showFrame: false)
% end
}
var tests = TestSuite("Integers")
tests.test("Literals") {
// Testing against the official Int types so as not to depend on
// unimplemented stuff.
let a: UInt8 = 0b1_0_11_0_111
expectEqual(a, 0b1_0_11_0_111)
let b: Int16 = 183
expectEqual(b, 0b1_0_11_0_111)
let c: Int16 = -183
expectEqual(c, -183)
let d: Int8 = 127
expectEqual(d, 127)
let e: UInt8 = 255
expectEqual(e, 255)
}
tests.test("Equality") {
expectEqual(183 as UInt8, 183)
expectNotEqual(183 as UInt8, 184)
expectEqual(49 as Int8, 49)
expectNotEqual(-49 as Int8, 49)
}
func indexOrder<T: Comparable>(x: T, y: T)
-> ExpectedComparisonResult {
return x < y ? .lt : x > y ? .gt : .eq
}
tests.test("Ordering") {
checkComparable([127, 183, 184, 255] as [UInt8], oracle: indexOrder)
checkComparable([-128, -1, 83, 84, 127] as [Int8], oracle: indexOrder)
checkComparable([127, 183, 184, 255, 65535] as [UInt16], oracle: indexOrder)
checkComparable([-32768, -32767, 83, 84, 32767] as [Int16], oracle: indexOrder)
}
tests.test("Simple-Arithmetic") {
expectEqual(1 as Int8 + 2, 3)
expectEqual(1 as Int8 - 2, -1)
expectEqual(-5 as Int8 + 11, 6)
expectEqual(3 as Int8 * 4, 12)
expectEqual(4 as Int8 * -7, -28)
expectEqual(-4 as Int8 * -7, 28)
expectEqual(5 as Int8 / 2, 2)
expectEqual(6 as Int8 / 2, 3)
expectEqual(7 as Int8 / 2, 3)
expectEqual(5 as Int8 % 3, 2)
expectEqual(6 as Int8 % 3, 0)
expectEqual(7 as Int8 % 3, 1)
}
% for w in map(lambda x: x.bits, all_integer_types(word_bits)):
% for prefix in ['U', '']:
% Type = '{}Int{}'.format(prefix, w)
tests.test("${Type}/Add/Overflow") {
func f(_ x: ${Type}) -> ${Type} {
return x + 1
}
expectCrashLater()
_ = f(${Type}.max)
}
tests.test("${Type}/Add/MaskingOverflow") {
expectEqual(${Type}.min, ${Type}.max &+ 1)
}
tests.test("${Type}/Subtract/Underflow") {
func f(_ x: ${Type}) -> ${Type} {
return x - 1
}
expectCrashLater()
_ = f(${Type}.min)
}
tests.test("${Type}/Subtract/MaskingUnderflow") {
expectEqual(${Type}.max, ${Type}.min &- 1)
}
tests.test("${Type}/Multiply/MaskingOverflow") {
expectEqual(${Type}.min, (${Type}.max / 2 + 1) &* 2)
}
tests.test("${Type}/AddInPlace/Overflow") {
func f(_ x: inout ${Type}) {
x += 1
}
expectCrashLater()
var x = ${Type}.max
f(&x)
}
tests.test("${Type}/AddInPlace/MaskingOverflow") {
var x = ${Type}.max
x &+= 1
expectEqual(${Type}.min, x)
}
tests.test("${Type}/SubtractInPlace/Underflow") {
func f(_ x: inout ${Type}) {
x -= 1
}
expectCrashLater()
var x = ${Type}.min
f(&x)
}
tests.test("${Type}/SubtractInPlace/MaskingUnderflow") {
var x = ${Type}.min
x &-= 1
expectEqual(${Type}.max, x)
}
tests.test("${Type}/MultiplyInPlace/MaskingOverflow") {
var x = ${Type}.max / 2 + 1
x &*= 2
expectEqual(${Type}.min, x)
}
% end
% end
tests.test("Simple-Bitwise") {
expectEqual(0b100_1001 as Int8 >> 1, 0b10_0100)
expectEqual(-0b100_1001 as Int8 >> 1, -0b10_0101)
expectEqual(0b1011_0111 as UInt8 >> 1, 0b0101_1011)
expectEqual(0b100_1001 as Int8 >> 1, 0b10_0100)
expectEqual(-0b100_1001 as Int8 >> 1, -0b10_0101)
expectEqual(0b1011_0111 as UInt8 >> 1, 0b0101_1011)
expectEqual((0b1011_0111 as UInt8) & 0b0110_1110, 0b0010_0110)
expectEqual((0b1011_0111 as UInt8) | 0b0110_1110, 0xFF)
expectEqual((0b1011_0111 as UInt8) ^ 0b0110_1110, 0b1101_1001)
}
tests.test("MinMax") {
expectEqual(255, UInt8.max)
expectEqual(0, UInt8.min)
expectEqual(127, Int8.max)
expectEqual(-128, Int8.min)
}
tests.test("CountLeadingZeros") {
expectEqual(0, UInt8.max.leadingZeroBitCount)
expectEqual(8, UInt8.min.leadingZeroBitCount)
expectEqual(1, Int8.max.leadingZeroBitCount)
expectEqual(0, Int8.min.leadingZeroBitCount)
}
tests.test("CountTrainlingZeros") {
expectEqual(0, UInt8.max.trailingZeroBitCount)
expectEqual(8, UInt8.min.trailingZeroBitCount)
expectEqual(0, Int8.max.trailingZeroBitCount)
expectEqual(7, Int8.min.trailingZeroBitCount)
}
tests.test("Conversion8to16") {
expectEqual(255, UInt16(UInt8.max))
expectEqual(255, Int16(UInt8.max))
expectEqual(0, UInt16(UInt8.min))
expectEqual(0, Int16(UInt8.min))
expectEqual(127, Int16(Int8.max))
let negativeValue = Int8.min
expectCrashLater()
_ = UInt16(negativeValue)
}
tests.test("Conversion16to8") {
expectEqual(255, UInt8(255 as UInt16))
expectEqual(255, UInt8(255 as Int16))
expectEqual(0, UInt8(0 as UInt16))
expectEqual(0, UInt8(0 as Int16))
expectEqual(127, Int8(127 as UInt16))
expectEqual(127, Int8(127 as Int16))
expectEqual(-128, Int8(-128 as Int16))
let tooLarge: UInt16 = 128
expectCrashLater()
_ = Int8(tooLarge)
}
tests.test("Conversion16to8a") {
let tooLarge: Int16 = 128
expectCrashLater()
_ = Int8(tooLarge)
}
tests.test("Conversion16to8b") {
let tooLarge: Int16 = 256
expectCrashLater()
_ = UInt8(tooLarge)
}
tests.test("Conversion16to8c") {
let tooLarge: UInt16 = 256
expectCrashLater()
_ = UInt8(tooLarge)
}
tests.test("ConversionWordToDWord") {
expectEqual(1 << ${word_bits} - 1, UDWord(UWord.max))
expectEqual(1 << ${word_bits} - 1, DWord(UWord.max))
expectEqual(0, UDWord(UWord.min))
expectEqual(0, DWord(UWord.min))
expectEqual(1 << ${word_bits-1} - 1, DWord(Word.max))
let negativeValue = Word.min
expectCrashLater()
_ = UDWord(negativeValue)
}
tests.test("ConversionDWordToWord") {
expectEqual(~0, UWord(1 << ${word_bits} - 1 as UDWord))
expectEqual(~0, UWord(1 << ${word_bits} - 1 as DWord))
expectEqual(0, UWord(0 as UDWord))
expectEqual(0, UWord(0 as DWord))
expectEqual(Word.max, Word(1 << ${word_bits-1} - 1 as UDWord))
expectEqual(Word.max, Word(1 << ${word_bits-1} - 1 as DWord))
expectEqual(Word.min, Word(-1 << ${word_bits-1} as DWord))
let tooLarge: UDWord = 1 << ${word_bits-1}
expectCrashLater()
_ = Word(tooLarge)
}
tests.test("ConversionDWordToWordA") {
let tooLarge: DWord = 1 << ${word_bits}
expectCrashLater()
_ = Word(tooLarge)
}
tests.test("ConversionDWordToWordB") {
let tooLarge: DWord = 1 << ${word_bits}
expectCrashLater()
_ = UWord(tooLarge)
}
tests.test("ConversionDWordToWordC") {
let tooLarge: UDWord = 1 << ${word_bits}
expectCrashLater()
_ = UWord(tooLarge)
}
tests.test("truncatingIfNeeded") {
expectEqual(-2, Int8(truncatingIfNeeded: UInt8.max - 1))
expectEqual(3, Int8(truncatingIfNeeded: 3 as UInt8))
expectEqual(UInt8.max - 1, UInt8(truncatingIfNeeded: -2 as Int8))
expectEqual(3, UInt8(truncatingIfNeeded: 3 as Int8))
expectEqual(-2, DWord(truncatingIfNeeded: UDWord.max - 1))
expectEqual(3, DWord(truncatingIfNeeded: 3 as UDWord))
expectEqual(UDWord.max - 1, UDWord(truncatingIfNeeded: -2 as DWord))
expectEqual(3, UDWord(truncatingIfNeeded: 3 as DWord))
expectEqual(-2, Int32(truncatingIfNeeded: -2 as Int8))
expectEqual(3, Int32(truncatingIfNeeded: 3 as Int8))
expectEqual(127, Int32(truncatingIfNeeded: 127 as UInt8))
expectEqual(129, Int32(truncatingIfNeeded: 129 as UInt8))
expectEqual((1 << 31 - 1) << 1, UInt32(truncatingIfNeeded: -2 as Int8))
expectEqual(3, UInt32(truncatingIfNeeded: 3 as Int8))
expectEqual(128, UInt32(truncatingIfNeeded: 128 as UInt8))
expectEqual(129, UInt32(truncatingIfNeeded: 129 as UInt8))
expectEqual(-2, DWord(truncatingIfNeeded: -2 as Int8))
expectEqual(3, DWord(truncatingIfNeeded: 3 as Int8))
expectEqual(127, DWord(truncatingIfNeeded: 127 as UInt8))
expectEqual(129, DWord(truncatingIfNeeded: 129 as UInt8))
expectEqual(
(1 << ${word_bits*2-1} - 1) << 1,
UDWord(truncatingIfNeeded: -2 as Int8))
expectEqual(3, UDWord(truncatingIfNeeded: 3 as Int8))
expectEqual(128, UDWord(truncatingIfNeeded: 128 as UInt8))
expectEqual(129, UDWord(truncatingIfNeeded: 129 as UInt8))
expectEqual(-2, Int8(truncatingIfNeeded: -2 as DWord))
expectEqual(-2, Int8(truncatingIfNeeded: -1 << 67 - 2 as DWord))
expectEqual(127, Int8(truncatingIfNeeded: 127 as UDWord))
expectEqual(-127, Int8(truncatingIfNeeded: 129 as UDWord))
expectEqual(0b1111_1100, UInt8(truncatingIfNeeded: -4 as DWord))
expectEqual(0b1111_1100, UInt8(truncatingIfNeeded: -1 << 67 - 4 as DWord))
expectEqual(128, UInt8(truncatingIfNeeded: 128 + 1024 as UDWord))
expectEqual(129, UInt8(truncatingIfNeeded: 129 + 1024 as UDWord))
}
tests.test("Parsing/LosslessStringConvertible") {
func _toArray<T: LosslessStringConvertible>(_ text: String) -> [T] {
return text.split(separator: " ").map { T(String($0)) }.flatMap { $0 }
}
expectEqualSequence([1, 2, 3], _toArray("1 2 3") as [Int])
expectEqualSequence(
[Int](), _toArray("21-50 ff6600 10000000000000000000000000") as [Int])
}
tests.test("HeterogeneousEquality") {
expectTrue(-1 as DWord != UDWord.max)
expectTrue(DWord.max == UDWord.max / 2)
expectTrue((0 as DWord) == 0 as UDWord)
expectTrue(-1 as Int8 == -1 as DWord)
expectTrue(UInt8.max != -1 as DWord)
expectTrue(UInt8.max == 255 as DWord)
expectTrue((0 as UInt8) == 0 as DWord)
expectTrue(UInt8.max == 255 as UDWord)
expectTrue(UInt8.max != UDWord.max)
expectTrue((0 as UInt8) == (0 as UDWord))
}
tests.test("HeterogeneousOrdering") {
expectTrue((-1 as DWord) < UDWord.max)
expectTrue(DWord.max <= UDWord.max / 2)
expectTrue(DWord.max >= UDWord.max / 2)
expectTrue((0 as DWord) <= (0 as UDWord))
expectTrue((0 as DWord) >= (0 as UDWord))
expectTrue((-1 as Int8) <= -1 as DWord)
expectTrue((-1 as Int8) >= -1 as DWord)
expectTrue(UInt8.max > -1 as DWord)
expectTrue(UInt8.max <= 255 as DWord)
expectTrue(UInt8.max >= 255 as DWord)
expectTrue((0 as UInt8) <= (0 as DWord))
expectTrue((0 as UInt8) >= (0 as DWord))
expectTrue(UInt8.max <= 255 as UDWord)
expectTrue(UInt8.max >= 255 as UDWord)
expectTrue(UInt8.max < UDWord.max)
expectTrue((0 as UInt8) <= (0 as UDWord))
expectTrue((0 as UInt8) >= (0 as UDWord))
}
tests.test("SmartBitShift/Homogeneous/Left/Int16") {
let all1s = ~0 as Int16
expectEqual(all1s, all1s << (0 as Int16))
expectEqual(-2, all1s << (1 as Int16))
expectEqual(Int16.min, all1s << (15 as Int16))
expectEqual(0, all1s << (16 as Int16))
expectEqual(-1, all1s << (-1 as Int16))
expectEqual(-1, all1s << (-15 as Int16))
expectEqual(-1, all1s << (-16 as Int16))
}
tests.test("SmartBitShift/Unconstrained/Left/Int16") {
let all1s = ~0 as Int16
expectEqual(all1s, all1s << 0)
expectEqual(-2, all1s << 1)
expectEqual(Int16.min, all1s << 15)
expectEqual(0, all1s << 16)
expectEqual(-1, all1s << -1)
expectEqual(-1, all1s << -15)
expectEqual(-1, all1s << -16)
}
tests.test("SmartBitShift/Homogeneous/Left/UInt16") {
let all1s = ~0 as UInt16
expectEqual(all1s, all1s << 0)
expectEqual(0b1111_1111_1111_1110, all1s << 1)
expectEqual(UInt16.max / 2 + 1, all1s << 15)
expectEqual(0, all1s << 16)
}
tests.test("SmartBitShift/Heterogeneous/Left/Int16") {
let all1s = ~0 as Int16
expectEqual(all1s, all1s << (0 as Int8))
expectEqual(-2, all1s << (1 as Int32))
expectEqual(Int16.min, all1s << (15 as UInt32))
expectEqual(0, all1s << (16 as UInt8))
expectEqual(-1, all1s << (-1 as DWord))
expectEqual(-1, all1s << (-15 as Int))
expectEqual(-1, all1s << (-16 as Int32))
}
tests.test("SmartBitShift/Heterogeneous/Left/UInt16") {
let all1s = ~0 as UInt16
expectEqual(all1s, all1s << (0 as Int8))
expectEqual(0b1111_1111_1111_1110, all1s << (1 as Int32))
expectEqual(UInt16.max / 2 + 1, all1s << (15 as UInt32))
expectEqual(0, all1s << (16 as UInt8))
expectEqual(UInt16.max / 2, all1s << (-1 as DWord))
expectEqual(1, all1s << (-15 as Int))
expectEqual(0, all1s << (-16 as Int32))
}
tests.test("SmartBitShift/Unconstrained/Left/UInt16") {
let all1s = ~0 as UInt16
expectEqual(all1s, all1s << 0)
expectEqual(0b1111_1111_1111_1110, all1s << 1)
expectEqual(UInt16.max / 2 + 1, all1s << 15)
expectEqual(0, all1s << 16)
expectEqual(UInt16.max / 2, all1s << -1)
expectEqual(1, all1s << -15)
expectEqual(0, all1s << -16)
}
tests.test("Basics") {
typealias I8 = UInt8
let b8: I8 = 0b1_0_11_0_111
expectEqual(b8, 0b1_0_11_0_111)
expectEqual(b8, 183)
expectNotEqual(b8, I8())
expectEqual(I8(), 0)
expectEqual(8, I8.bitWidth)
expectEqual(16, Int16.bitWidth)
expectEqual(32, Int32.bitWidth)
}
tests.test("words") {
expectEqualSequence([UInt.max], UInt.max.words)
expectEqualSequence([0xFF as UInt], UInt8.max.words)
expectEqualSequence([0xFFFF as UInt], UInt16.max.words)
expectEqualSequence([0xFFFFFFFF as UInt], UInt32.max.words)
expectEqualSequence([0 as UInt], UInt.min.words)
expectEqualSequence([0 as UInt], UInt8.min.words)
expectEqualSequence([0 as UInt], UInt16.min.words)
expectEqualSequence([0 as UInt], UInt32.min.words)
expectEqualSequence([UInt.max >> 1], Int.max.words)
expectEqualSequence([0x7F as UInt], Int8.max.words)
expectEqualSequence([0x7FFF as UInt], Int16.max.words)
expectEqualSequence([0x7FFFFFFF as UInt], Int32.max.words)
expectEqualSequence([UInt.max << (Int.bitWidth - 1)], Int.min.words)
expectEqualSequence([UInt.max << 7], Int8.min.words)
expectEqualSequence([UInt.max << 15], Int16.min.words)
expectEqualSequence([UInt.max << 31], Int32.min.words)
expectEqualSequence([UInt.max], (-1 as Int).words)
expectEqualSequence([UInt.max], (-1 as Int8).words)
expectEqualSequence([UInt.max], (-1 as Int16).words)
expectEqualSequence([UInt.max], (-1 as Int32).words)
% if int(WORD_BITS) == 64:
expectEqualSequence([UInt.max], UInt64.max.words)
expectEqualSequence([0 as UInt], UInt64.min.words)
expectEqualSequence([UInt.max >> 1], Int64.max.words)
expectEqualSequence([(1 as UInt) << 63], Int64.min.words)
expectEqualSequence([UInt.max], (-1 as Int64).words)
% else:
expectEqualSequence([UInt.max, UInt.max], UInt64.max.words)
expectEqualSequence([0 as UInt, 0], UInt64.min.words)
expectEqualSequence([UInt.max, UInt.max >> 1], Int64.max.words)
expectEqualSequence([0 as UInt, 1 << 31], Int64.min.words)
expectEqualSequence([UInt.max, UInt.max], (-1 as Int64).words)
% end
expectEqualSequence([1], 1.words)
expectEqualSequence([0], 0.words)
}
tests.test("multipliedFullWidth/UInt8") {
let a: UInt8 = 42
let b: UInt8 = 42
let res = a.multipliedFullWidth(by: b)
expectEqual(0x06, res.high)
expectEqual(0xe4, res.low)
}
tests.test("multipliedFullWidth/Int8") {
let a: Int8 = 42
let b: Int8 = -42
let res = a.multipliedFullWidth(by: b)
expectEqual(Int8(bitPattern: 0xf9), res.high)
expectEqual(0x1c, res.low)
}
tests.test("multipliedFullWidth/Int8/BothNegative") {
let a: Int8 = -42
let b: Int8 = -42
let res = a.multipliedFullWidth(by: b)
expectEqual(0x06, res.high)
expectEqual(0xe4, res.low)
}
tests.test("MultiplyAndDivideFullWidth/Int8") {
let a: Int8 = 42
let b: Int8 = 43
let res = a.multipliedFullWidth(by: b)
let (quotient, remainder) = b.dividingFullWidth(res)
expectEqual(a, quotient)
expectEqual(0, remainder)
}
tests.test("Remainder/DividingBy0") {
func f(_ x: Int, _ y: Int) -> Int {
return x % y
}
expectCrashLater()
_ = f(42, 0)
}
tests.test("RemainderReportingOverflow/DividingByMinusOne") {
// Work around SR-5964.
func minusOne<T : SignedInteger>() -> T {
return -1 as T
}
func f(_ x: Int, _ y: Int) -> Int {
return x.remainderReportingOverflow(dividingBy: y).partialValue
}
expectEqual(f(.max, minusOne()), 0)
expectEqual(f(.min, minusOne()), 0)
}
tests.test("Division/By0") {
func f(_ x: Int, _ y: Int) -> Int {
return x / y
}
expectCrashLater()
_ = f(42, 0)
}
tests.test("DivideMinByMinusOne") {
func f(_ x: Int) -> Int {
return x / -1
}
expectCrashLater()
_ = f(Int.min)
}
tests.test("MultiplyMinByMinusOne") {
func f(_ x: Int) -> Int {
return x * -1
}
expectCrashLater()
_ = f(Int.min)
}
tests.test("Strideable") {
func dist<T: BinaryInteger>(_ a: T, _ b: T) -> Int {
return a.distance(to: b)
}
% for u in ['U', '']:
let ${u}x = ${u}Int.max - 10
expectEqual(${u}x.advanced(by: 10), ${u}Int.max)
expectEqual(${u}Int.max.advanced(by: -10), ${u}x)
expectEqual(dist(${u}x, ${u}Int.max), 10)
expectEqual(dist(${u}Int.max, ${u}x), -10)
// FIXME: The compiler spuriously flags these as overflowing:
// https://bugs.swift.org/browse/SR-5882
// expectEqual(${u}x.distance(to: ${u}Int.max), 10)
% end
expectEqual(dist(UInt8.min, UInt8.max), 255)
expectEqual(dist(UInt8.max, UInt8.min), -255)
expectEqual(dist(Int8.min, Int8.max), 255)
expectEqual(dist(Int8.max, Int8.min), -255)
}
tests.test("signum/generic") {
func check<T : BinaryInteger>(_ expected: T, _ x: T) {
expectEqual(expected, x.signum())
}
% for suffix in ['8', '16', '32', '64', '']:
check(-1, Int${suffix}.min)
check(-1, (-42) as Int${suffix})
check(-1, (-1) as Int${suffix})
% for u in ['U', '']:
check(0, 0 as ${u}Int${suffix})
check(1, 1 as ${u}Int${suffix})
check(1, 42 as ${u}Int${suffix})
check(1, ${u}Int${suffix}.max)
% end
% end
}
tests.test("signum/concrete") {
% for suffix in ['8', '16', '32', '64', '']:
expectEqual(-1 as Int${suffix}, Int${suffix}.min.signum())
expectEqual(-1 as Int${suffix}, (-42 as Int${suffix}).signum())
expectEqual(-1 as Int${suffix}, (-1 as Int${suffix}).signum())
% for u in ['U', '']:
expectEqual(0 as ${u}Int${suffix}, (0 as ${u}Int${suffix}).signum())
expectEqual(1 as ${u}Int${suffix}, (1 as ${u}Int${suffix}).signum())
expectEqual(1 as ${u}Int${suffix}, (42 as ${u}Int${suffix}).signum())
expectEqual(1 as ${u}Int${suffix}, ${u}Int${suffix}.max.signum())
% end
% end
}
tests.test("binaryLogarithm/generic") {
expectEqual(
(42 as MockBinaryInteger<Int8>)._binaryLogarithm(),
(42 as Int8)._binaryLogarithm())
expectEqual(
(42 as MockBinaryInteger<UInt8>)._binaryLogarithm(),
(42 as UInt8)._binaryLogarithm())
expectEqual(
(42 as MockBinaryInteger<Int16>)._binaryLogarithm(),
(42 as Int16)._binaryLogarithm())
expectEqual(
(42 as MockBinaryInteger<UInt16>)._binaryLogarithm(),
(42 as UInt16)._binaryLogarithm())
expectEqual(
(42 as MockBinaryInteger<Int32>)._binaryLogarithm(),
(42 as Int32)._binaryLogarithm())
expectEqual(
(42 as MockBinaryInteger<UInt32>)._binaryLogarithm(),
(42 as UInt32)._binaryLogarithm())
expectEqual(
(42 as MockBinaryInteger<Int64>)._binaryLogarithm(),
(42 as Int64)._binaryLogarithm())
expectEqual(
(42 as MockBinaryInteger<UInt64>)._binaryLogarithm(),
(42 as UInt64)._binaryLogarithm())
expectEqual(
(42 as MockBinaryInteger<Int>)._binaryLogarithm(),
(42 as Int)._binaryLogarithm())
expectEqual(
(42 as MockBinaryInteger<UInt>)._binaryLogarithm(),
(42 as UInt)._binaryLogarithm())
// FIXME: DoubleWidth is no longer part of the standard library
#if false
expectEqual(
(42 as MockBinaryInteger<DoubleWidth<Int>>)._binaryLogarithm(),
(42 as DoubleWidth<Int>)._binaryLogarithm())
expectEqual(
(42 as MockBinaryInteger<DoubleWidth<UInt>>)._binaryLogarithm(),
(42 as DoubleWidth<UInt>)._binaryLogarithm())
expectEqual(
(42 as MockBinaryInteger<DoubleWidth<DoubleWidth<Int>>>)._binaryLogarithm(),
(42 as DoubleWidth<DoubleWidth<Int>>)._binaryLogarithm())
#endif
}
runAllTests()