Skip to content

Instantly share code, notes, and snippets.

@CTMacUser
Last active August 30, 2019 08:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save CTMacUser/b807fbefae19be7f3c52016c8069b5fb to your computer and use it in GitHub Desktop.
Save CTMacUser/b807fbefae19be7f3c52016c8069b5fb to your computer and use it in GitHub Desktop.
Another zero-width signed and unsigned integer type pair for Swift
//
// IntegerNull.swift
// ZeroInteger
//
// Created by Daryle Walker on 8/27/19.
// Copyright © 2019 Daryle Walker. All rights reserved.
//
// MARK: Zero-bit Integer Primary Definitions
/// A signed integer type with no bits, capable of only representing zero.
public struct Int0 {
// The initializer should use minimal code, unlike the potential one
// imported as a default implementation from BinaryInteger.
/// Creates an instance equal to zero.
@inline(__always)
public init() {} // Replaces internal implicit implementation; overrules extension from BinaryInteger
}
/// An unsigned integer type with no bits, capable of only representing zero.
public struct UInt0 {
// The initializer should use minimal code, unlike the potential one
// imported as a default implementation from BinaryInteger.
/// Creates an instance equal to zero.
@inline(__always)
public init() {} // Replaces internal implicit implementation; overrules extension from BinaryInteger
}
// MARK: - Comparisons
extension Int0: Comparable {
/// These methods prevent an infinite recursion loop with some methods in
/// Strideable.
@inlinable
public static func == (lhs: Int0, rhs: Int0) -> Bool { // Replaces implicit implementation (Update: from Strideable)
return true
}
@inlinable
public static func < (lhs: Int0, rhs: Int0) -> Bool { // Replaces default implementation from Strideable
return false
}
}
extension UInt0: Comparable {
/// These methods prevent an infinite recursion loop with some methods in
/// Strideable.
@inlinable
public static func == (lhs: UInt0, rhs: UInt0) -> Bool { // Replaces implicit implementation (Update: from Strideable)
return true
}
@inlinable
public static func < (lhs: UInt0, rhs: UInt0) -> Bool { // Replaces default implementation from Strideable
return false
}
}
// MARK: Hashing
extension Int0: Hashable {
@inlinable
public func hash(into hasher: inout Hasher) { // Replaces implicit implementation
hasher.combine(0)
}
}
extension UInt0: Hashable {
@inlinable
public func hash(into hasher: inout Hasher) { // Replaces implicit implementation
hasher.combine(0)
}
}
// MARK: - Miscellaneous
extension Int0: ExpressibleByIntegerLiteral {
@inlinable
public init(integerLiteral value: Int) {
precondition(value == 0)
self.init()
//self.init(exactly: value)!
}
}
extension UInt0: ExpressibleByIntegerLiteral {
@inlinable
public init(integerLiteral value: Int) {
precondition(value == 0)
self.init()
//self.init(exactly: value)!
}
}
// MARK: String Serialization
extension Int0: CustomStringConvertible {
}
extension UInt0: CustomStringConvertible {
}
extension Int0: LosslessStringConvertible {
}
extension UInt0: LosslessStringConvertible {
}
// MARK: Offsets
extension Int0: Strideable {
@inlinable
public func distance(to other: Int0) -> Int0 {
// The default implementation from BinaryIntger can't be used because
// we're using a different Stride type (Int vs. Int0)!
return Int0()
}
@inlinable
public func advanced(by n: Int0) -> Int0 {
// The default implementation from BinaryIntger can't be used because
// we're using a different Stride type (Int vs. Int0)!
return self
}
}
extension UInt0: Strideable {
@inlinable
public func distance(to other: UInt0) -> Int0 {
// The default implementation from BinaryIntger can't be used because
// we're using a different Stride type (Int vs. Int0)!
return Int0()
}
@inlinable
public func advanced(by n: Int0) -> UInt0 {
// The default implementation from BinaryIntger can't be used because
// we're using a different Stride type (Int vs. Int0)!
return self
}
}
// MARK: - Basic Numerics
extension Int0: AdditiveArithmetic {
@inlinable
public static func + (lhs: Int0, rhs: Int0) -> Int0 {
return .zero
}
@inlinable
public static func += (lhs: inout Int0, rhs: Int0) {} // Future: Replaces default implementation
@inlinable
public static func - (lhs: Int0, rhs: Int0) -> Int0 {
return .zero
}
@inlinable
public static func -= (lhs: inout Int0, rhs: Int0) {} // Future: Replaces default implementation
}
extension UInt0: AdditiveArithmetic {
@inlinable
public static func + (lhs: UInt0, rhs: UInt0) -> UInt0 {
return .zero
}
@inlinable
public static func += (lhs: inout UInt0, rhs: UInt0) {} // Future: Replaces default implementation
@inlinable
public static func - (lhs: UInt0, rhs: UInt0) -> UInt0 {
return .zero
}
@inlinable
public static func -= (lhs: inout UInt0, rhs: UInt0) {} // Future: Replaces default implementation
}
extension Int0: Numeric {
@inlinable
public var magnitude: UInt0 { return .zero }
@inlinable
public static func * (lhs: Int0, rhs: Int0) -> Int0 {
return .zero
}
@inlinable
public static func *= (lhs: inout Int0, rhs: Int0) {}
}
extension UInt0: Numeric {
@inlinable
public static func * (lhs: UInt0, rhs: UInt0) -> UInt0 {
return .zero
}
@inlinable
public static func *= (lhs: inout UInt0, rhs: UInt0) {}
}
extension Int0: SignedNumeric {
}
extension UInt0: SignedNumeric {
}
// MARK: - Advanced Numerics
extension Int0: BinaryInteger {
@inlinable
public init?<T: BinaryFloatingPoint>(exactly source: T) {
// Overrule the default implementation from FixedWidthInteger, since
// that uses a value of 1, which this type doesn't support.
guard source.isZero else { return nil }
self.init()
}
@inlinable
public init<T: BinaryFloatingPoint>(_ source: T) {
// Overrule the default implementation from FixedWidthInteger, since
// that uses a value of 1, which this type doesn't support.
self.init(exactly: source.rounded(.towardZero))!
}
@inlinable
public var words: EmptyCollection<UInt> { return EmptyCollection() }
@inlinable
public var trailingZeroBitCount: Int { return 0 }
@inlinable
public static func / (lhs: Int0, rhs: Int0) -> Int0 {
preconditionFailure("Division by zero")
}
@inlinable
public static func /= (lhs: inout Int0, rhs: Int0) {
preconditionFailure("Division by zero")
}
@inlinable
public static func % (lhs: Int0, rhs: Int0) -> Int0 {
preconditionFailure("Division by zero")
}
@inlinable
public static func %= (lhs: inout Int0, rhs: Int0) {
preconditionFailure("Division by zero")
}
@inlinable
public static prefix func ~ (x: Int0) -> Int0 {
// Overrule the default implementation from FixedWidthInteger, since
// that uses a value of 1, which this type doesn't support.
return x
}
@inlinable
public static func &= (lhs: inout Int0, rhs: Int0) {}
@inlinable
public static func |= (lhs: inout Int0, rhs: Int0) {}
@inlinable
public static func ^= (lhs: inout Int0, rhs: Int0) {}
}
extension UInt0: BinaryInteger {
@inlinable
public init?<T: BinaryFloatingPoint>(exactly source: T) {
// Overrule the default implementation from FixedWidthInteger, since
// that uses a value of 1, which this type doesn't support.
guard source.isZero else { return nil }
self.init()
}
@inlinable
public init<T: BinaryFloatingPoint>(_ source: T) {
// Overrule the default implementation from FixedWidthInteger, since
// that uses a value of 1, which this type doesn't support.
self.init(exactly: source.rounded(.towardZero))!
}
@inlinable
public var words: EmptyCollection<UInt> { return EmptyCollection() }
@inlinable
public var trailingZeroBitCount: Int { return 0 }
@inlinable
public static func / (lhs: UInt0, rhs: UInt0) -> UInt0 {
preconditionFailure("Division by zero")
}
@inlinable
public static func /= (lhs: inout UInt0, rhs: UInt0) {
preconditionFailure("Division by zero")
}
@inlinable
public static func % (lhs: UInt0, rhs: UInt0) -> UInt0 {
preconditionFailure("Division by zero")
}
@inlinable
public static func %= (lhs: inout UInt0, rhs: UInt0) {
preconditionFailure("Division by zero")
}
@inlinable
public static prefix func ~ (x: UInt0) -> UInt0 {
// Overrule the default implementation from FixedWidthInteger, since
// that uses a value of 1, which this type doesn't support.
return x
}
@inlinable
public static func &= (lhs: inout UInt0, rhs: UInt0) {}
@inlinable
public static func |= (lhs: inout UInt0, rhs: UInt0) {}
@inlinable
public static func ^= (lhs: inout UInt0, rhs: UInt0) {}
}
extension Int0: FixedWidthInteger, SignedInteger {
public static let bitWidth: Int = 0
@inlinable
public func addingReportingOverflow(_ rhs: Int0) -> (partialValue: Int0, overflow: Bool) {
return (.zero, false)
}
@inlinable
public func subtractingReportingOverflow(_ rhs: Int0) -> (partialValue: Int0, overflow: Bool) {
return (.zero, false)
}
@inlinable
public func multipliedReportingOverflow(by rhs: Int0) -> (partialValue: Int0, overflow: Bool) {
return (.zero, false)
}
@inlinable
public func dividedReportingOverflow(by rhs: Int0) -> (partialValue: Int0, overflow: Bool) {
return (self, true)
}
@inlinable
public func remainderReportingOverflow(dividingBy rhs: Int0) -> (partialValue: Int0, overflow: Bool) {
return (self, true)
}
@inlinable
public func multipliedFullWidth(by other: Int0) -> (high: Int0, low: UInt0) {
// As of this writing, Swift 5.0 does not supply a default
// implementation for this method. A later version will, but that code
// uses values of 1, which type doesn't support, so we won't use it.
return (.zero, UInt0())
}
@inlinable
public func dividingFullWidth(_ dividend: (high: Int0, low: UInt0)) -> (quotient: Int0, remainder: Int0) {
fatalError("Division by zero")
}
@inlinable
public init(_truncatingBits bits: UInt) {
self.init() // Truncate all the bits
}
@inlinable
public var nonzeroBitCount: Int { return 0 }
@inlinable
public var leadingZeroBitCount: Int { return 0 }
@inlinable
public var byteSwapped: Int0 { return self }
@inlinable
public static func &>>= (lhs: inout Int0, rhs: Int0) {
// Do nothing.
// This method has a default implementation via a cross-version variant.
// The &>> operation also has a default implementation. They will
// infinitely recurse each other unless at least one is custom-defined.
}
@inlinable
public static func &<<= (lhs: inout Int0, rhs: Int0) {
// Do nothing.
// This method has a default implementation via a cross-version variant.
// The &<< operation also has a default implementation. They will
// infinitely recurse each other unless at least one is custom-defined.
}
}
extension UInt0: FixedWidthInteger, UnsignedInteger {
public static let bitWidth: Int = 0
@inlinable
public func addingReportingOverflow(_ rhs: UInt0) -> (partialValue: UInt0, overflow: Bool) {
return (.zero, false)
}
@inlinable
public func subtractingReportingOverflow(_ rhs: UInt0) -> (partialValue: UInt0, overflow: Bool) {
return (.zero, false)
}
@inlinable
public func multipliedReportingOverflow(by rhs: UInt0) -> (partialValue: UInt0, overflow: Bool) {
return (.zero, false)
}
@inlinable
public func dividedReportingOverflow(by rhs: UInt0) -> (partialValue: UInt0, overflow: Bool) {
return (self, true)
}
@inlinable
public func remainderReportingOverflow(dividingBy rhs: UInt0) -> (partialValue: UInt0, overflow: Bool) {
return (self, true)
}
@inlinable
public func multipliedFullWidth(by other: UInt0) -> (high: UInt0, low: UInt0) {
// As of this writing, Swift 5.0 does not supply a default
// implementation for this method. A later version will, but that code
// uses values of 1, which type doesn't support, so we won't use it.
return (.zero, UInt0())
}
@inlinable
public func dividingFullWidth(_ dividend: (high: UInt0, low: UInt0)) -> (quotient: UInt0, remainder: UInt0) {
fatalError("Division by zero")
}
@inlinable
public init(_truncatingBits bits: UInt) {
self.init() // Truncate all the bits
}
@inlinable
public var nonzeroBitCount: Int { return 0 }
@inlinable
public var leadingZeroBitCount: Int { return 0 }
@inlinable
public var byteSwapped: UInt0 { return self }
@inlinable
public static func &>>= (lhs: inout UInt0, rhs: UInt0) {
// Do nothing.
// This method has a default implementation via a cross-version variant.
// The &>> operation also has a default implementation. They will
// infinitely recurse each other unless at least one is custom-defined.
}
@inlinable
public static func &<<= (lhs: inout UInt0, rhs: UInt0) {
// Do nothing.
// This method has a default implementation via a cross-version variant.
// The &<< operation also has a default implementation. They will
// infinitely recurse each other unless at least one is custom-defined.
}
}
// MARK: - Requirements Overriding Standard Library Defaults
#if true
extension Int0 {
// Comparable
@inlinable
public static func <= (lhs: Int0, rhs: Int0) -> Bool { // Replaces default implementation
return true
}
@inlinable
public static func >= (lhs: Int0, rhs: Int0) -> Bool { // Replaces default implementation
return true
}
@inlinable
public static func > (lhs: Int0, rhs: Int0) -> Bool { // Replaces default implementation
return false
}
// ExpressibleByIntegerLiteral
public typealias IntegerLiteralType = Int
// CustomStringConvertible
@inlinable
public var description: String { return "0" } // Replaces default implementation from BinaryInteger
// LosslessStringConvertible
@inlinable
public init?(_ description: String) { // Replaces default implementation from FixedWidthInteger
let rest = description.dropFirst()
switch description.first {
case "+", "-":
guard !rest.isEmpty else { return nil }
fallthrough
case "0":
guard rest.allSatisfy({ $0 == "0" }) else { return nil }
self.init()
default:
return nil
}
}
// Strideable
public typealias Stride = Int0
// AdditiveArithmetic
public static let zero = Int0() // Replaces default implementation when also conforming to ExpressibleByIntegerLiteral
// Numeric
@inlinable
public init?<T: BinaryInteger>(exactly source: T) { // Replaces default implementation from SignedInteger when also conforming to FixedWidthInteger
guard source == 0 else { return nil }
self.init()
}
public typealias Magnitude = UInt0
// SignedNumeric
@inlinable
public static prefix func - (_ operand: Int0) -> Int0 { // Replaces default implementation
return operand
}
@inlinable
public mutating func negate() {} // Replaces default implementation
// BinaryInteger
public static let isSigned = true // Replaces default implementation from SignedInteger
@inlinable
public init<T: BinaryInteger>(_ source: T) { // Replaces default implementation from SignedInteger when also conforming to FixedWidthInteger
self.init(exactly: source)!
}
@inlinable
public init<T: BinaryInteger>(truncatingIfNeeded source: T) { // Replaces default implementation from FixedWidthInteger
self = .zero
}
@inlinable
public init<T: BinaryInteger>(clamping source: T) { // Replaces default implementation from FixedWidthInteger
self = .zero
}
public typealias Words = EmptyCollection<UInt>
@inlinable
public var bitWidth: Int { return 0 } // Replaces default implementation from FixedWidthInteger
@inlinable
public static func & (lhs: Int0, rhs: Int0) -> Int0 { // Replaces default implementation
return .zero
}
@inlinable
public static func | (lhs: Int0, rhs: Int0) -> Int0 { // Replaces default implementation
return .zero
}
@inlinable
public static func ^ (lhs: Int0, rhs: Int0) -> Int0 { // Replaces default implementation
return .zero
}
@inlinable
public static func << <RHS: BinaryInteger>(lhs: Int0, rhs: RHS) -> Int0 { // Replaces default implementation (Update: from FixedWidthInteger)
return .zero
}
@inlinable
public static func <<= <RHS: BinaryInteger>(lhs: inout Int0, rhs: RHS) {} // Replaces default implementation from FixedWidthInteger
@inlinable
public static func >> <RHS: BinaryInteger>(lhs: Int0, rhs: RHS) -> Int0 { // Replaces default implementation (Update: from FixedWidthInteger)
return .zero
}
@inlinable
public static func >>= <RHS: BinaryInteger>(lhs: inout Int0, rhs: RHS) {} // Replaces default implementation from FixedWidthInteger
@inlinable
public func quotientAndRemainder(dividingBy rhs: Int0) -> (quotient: Int0, remainder: Int0) { // Replaces default implementation
fatalError("Division by zero")
}
@inlinable
public func isMultiple(of other: Int0) -> Bool { // Replaces default implementation (Update: from SignedInteger when also conforming to FixedWidthInteger)
return true
}
@inlinable
public func signum() -> Int0 { // Replaces default implementation
return self
}
// FixedWidthInteger
public static let max: Int0 = .zero // Replaces default implementation from SignedInteger when also conforming to FixedWidthInteger
public static let min: Int0 = .zero // Replaces default implementation from SignedInteger when also conforming to FixedWidthInteger
@inlinable
public init(bigEndian value: Int0) { // Replaces default implementation
self = value
}
@inlinable
public init(littleEndian value: Int0) { // Replaces default implementation
self = value
}
@inlinable
public var bigEndian: Int0 { return self } // Replaces default implementation
@inlinable
public var littleEndian: Int0 { return self } // Replaces default implementation
@inlinable
public static func &>> (lhs: Int0, rhs: Int0) -> Int0 { // Replaces default implementation
return .zero
}
@inlinable
public static func &<< (lhs: Int0, rhs: Int0) -> Int0 { // Replaces default implementation
return .zero
}
}
extension UInt0 {
// Comparable
@inlinable
public static func <= (lhs: UInt0, rhs: UInt0) -> Bool { // Replaces default implementation
return true
}
@inlinable
public static func >= (lhs: UInt0, rhs: UInt0) -> Bool { // Replaces default implementation
return true
}
@inlinable
public static func > (lhs: UInt0, rhs: UInt0) -> Bool { // Replaces default implementation
return false
}
// ExpressibleByIntegerLiteral
public typealias IntegerLiteralType = Int
// CustomStringConvertible
@inlinable
public var description: String { return "0" } // Replaces default implementation from BinaryInteger
// LosslessStringConvertible
@inlinable
public init?(_ description: String) { // Replaces default implementation from FixedWidthInteger
let rest = description.dropFirst()
switch description.first {
case "+", "-":
guard !rest.isEmpty else { return nil }
fallthrough
case "0":
guard rest.allSatisfy({ $0 == "0" }) else { return nil }
self.init()
default:
return nil
}
}
// Strideable
public typealias Stride = Int0
// AdditiiveArithmetic
public static let zero = UInt0() // Replaces default implementation when also conforming to ExpressibleByIntegerLiteral
// Numeric
@inlinable
public init?<T: BinaryInteger>(exactly source: T) { // Replaces default implementation from UnsignedInteger when also conforming to FixedWidthInteger
guard source == 0 else { return nil }
self.init()
}
public typealias Magnitude = UInt0
@inlinable
public var magnitude: UInt0 { return self } // Replaces default implementation from UnsignedInteger
// SignedNumeric
@inlinable
public static prefix func - (_ operand: UInt0) -> UInt0 { // Replaces default implementation
return operand
}
@inlinable
public mutating func negate() {} // Replaces default implementation
// BinaryInteger
public static let isSigned = false // Replaces default implementation from UnsignedInteger
@inlinable
public init<T: BinaryInteger>(_ source: T) { // Replaces default implementation from UnsignedInteger when also conforming to FixedWidthInteger
self.init(exactly: source)!
}
@inlinable
public init<T: BinaryInteger>(truncatingIfNeeded source: T) { // Replaces default implementation from FixedWidthInteger
self = .zero
}
@inlinable
public init<T: BinaryInteger>(clamping source: T) { // Replaces default implementation from FixedWidthInteger
self = .zero
}
public typealias Words = EmptyCollection<UInt>
@inlinable
public var bitWidth: Int { return 0 } // Replaces default implementation from FixedWidthInteger
@inlinable
public static func & (lhs: UInt0, rhs: UInt0) -> UInt0 { // Replaces default implementation
return .zero
}
@inlinable
public static func | (lhs: UInt0, rhs: UInt0) -> UInt0 { // Replaces default implementation
return .zero
}
@inlinable
public static func ^ (lhs: UInt0, rhs: UInt0) -> UInt0 { // Replaces default implementation
return .zero
}
@inlinable
public static func << <RHS: BinaryInteger>(lhs: UInt0, rhs: RHS) -> UInt0 { // Replaces default implementation (Update: from FixedWidthInteger)
return .zero
}
@inlinable
public static func <<= <RHS: BinaryInteger>(lhs: inout UInt0, rhs: RHS) {} // Replaces default implementation from FixedWidthInteger
@inlinable
public static func >> <RHS: BinaryInteger>(lhs: UInt0, rhs: RHS) -> UInt0 { // Replaces default implementation (Update: from FixedWidthInteger)
return .zero
}
@inlinable
public static func >>= <RHS: BinaryInteger>(lhs: inout UInt0, rhs: RHS) {} // Replaces default implementation from FixedWidthInteger
@inlinable
public func quotientAndRemainder(dividingBy rhs: UInt0) -> (quotient: UInt0, remainder: UInt0) { // Replaces default implementation
fatalError("Division by zero")
}
@inlinable
public func isMultiple(of other: UInt0) -> Bool { // Replaces default implementation
return true
}
@inlinable
public func signum() -> UInt0 { // Replaces default implementation
return self
}
// FixedWidthInteger
public static let max: UInt0 = .zero // Replaces default implementation from UnsignedInteger when also conforming to FixedWidthInteger
public static let min: UInt0 = .zero // Replaces default implementation from UnsignedInteger when also conforming to FixedWidthInteger
@inlinable
public init(bigEndian value: UInt0) { // Replaces default implementation
self = value
}
@inlinable
public init(littleEndian value: UInt0) { // Replaces default implementation
self = value
}
@inlinable
public var bigEndian: UInt0 { return self } // Replaces default implementation
@inlinable
public var littleEndian: UInt0 { return self } // Replaces default implementation
@inlinable
public static func &>> (lhs: UInt0, rhs: UInt0) -> UInt0 { // Replaces default implementation
return .zero
}
@inlinable
public static func &<< (lhs: UInt0, rhs: UInt0) -> UInt0 { // Replaces default implementation
return .zero
}
}
#endif
//
// IntegerNullTests.swift
// ZeroIntegerTests
//
// Created by Daryle Walker on 8/27/19.
// Copyright © 2019 Daryle Walker. All rights reserved.
//
import XCTest
@testable import ZeroInteger
class IntegerNullTests: XCTestCase {
func testComparisons() {
let sample1 = Int0(), sample2 = Int0()
let sample3 = UInt0(), sample4 = UInt0()
// Equality
XCTAssertTrue(sample1 == sample2)
XCTAssertFalse(sample1 != sample2)
XCTAssertTrue(sample3 == sample4)
XCTAssertFalse(sample3 != sample4)
// Less-than, etc.
XCTAssertFalse(sample1 < sample2)
XCTAssertFalse(sample1 > sample2)
XCTAssertTrue(sample1 <= sample2)
XCTAssertTrue(sample1 >= sample2)
XCTAssertFalse(sample3 < sample4)
XCTAssertFalse(sample3 > sample4)
XCTAssertTrue(sample3 <= sample4)
XCTAssertTrue(sample3 >= sample4)
// Hashing
XCTAssertEqual(sample1.hashValue, sample2.hashValue)
XCTAssertEqual(sample3.hashValue, sample4.hashValue)
}
func testAdditiveArithmetic() {
// Zero-value
let sample1 = Int0(), sample3 = UInt0()
XCTAssertEqual(Int0.zero, sample1)
XCTAssertEqual(UInt0.zero, sample3)
// Addition and subtraction, non-mutating
var sample2 = Int0(), sample4 = UInt0()
XCTAssertEqual(sample1 + sample2, Int0())
XCTAssertEqual(sample1 - sample2, Int0())
XCTAssertEqual(sample3 + sample4, UInt0())
XCTAssertEqual(sample3 - sample4, UInt0())
// Addition and subtraction, mutating
sample2 += sample1
XCTAssertEqual(sample2, Int0())
sample2 -= sample1
XCTAssertEqual(sample2, Int0())
sample4 += sample3
XCTAssertEqual(sample4, UInt0())
sample4 -= sample3
XCTAssertEqual(sample4, UInt0())
// Non-requirement operations
XCTAssertEqual(+sample1, sample1)
XCTAssertEqual(+sample3, sample3)
}
func testExpressibleByIntegerLiteral() {
// Zero-value
let sample1: Int0 = 0, sample2: UInt0 = 0
XCTAssertEqual(sample1, Int0())
XCTAssertEqual(sample2, UInt0())
#if false
// Non-zero values error out!
let sample3: Int0 = -1, sample4: UInt0 = +1
XCTAssertNotEqual(sample3, Int0())
XCTAssertNotEqual(sample4, UInt0())
#endif
}
func testNumeric() {
// Initialization with integers
let sample1 = UInt0(exactly: 0), sample2 = Int0(exactly: 0)
XCTAssertEqual(sample1, UInt0())
XCTAssertEqual(sample2, Int0())
let sample3 = UInt0(exactly: -1), sample4 = Int0(exactly: -1)
XCTAssertNil(sample3)
XCTAssertNil(sample4)
let sample5 = UInt0(exactly: +1), sample6 = Int0(exactly: +1)
XCTAssertNil(sample5)
XCTAssertNil(sample6)
// Magnitude
XCTAssertEqual(sample1!.magnitude, UInt0())
XCTAssertEqual(sample2!.magnitude, UInt0()) // Different type!
// Multiplication, non-mutating
var sample7 = UInt0(), sample8 = Int0()
XCTAssertEqual(sample1! * sample7, UInt0())
XCTAssertEqual(sample2! * sample8, Int0())
// Multiplication, mutating
sample7 *= sample1!
XCTAssertEqual(sample7, UInt0())
sample8 *= sample2!
XCTAssertEqual(sample8, Int0())
}
func testSignedNumeric() {
// Negation, non-mutating
var sample1 = Int0(), sample2 = UInt0()
XCTAssertEqual(-sample1, Int0())
XCTAssertEqual(-sample2, UInt0())
// Negation, mutating
sample1.negate()
sample2.negate()
XCTAssertEqual(sample1, Int0())
XCTAssertEqual(sample2, UInt0())
// Non-requirement support function: absolute value
XCTAssertEqual(abs(Int0()), Int0())
XCTAssertEqual(abs(UInt0()), UInt0())
}
func testCustomStringConvertible() {
XCTAssertEqual(String(describing: Int0()), "0")
XCTAssertEqual(String(describing: UInt0()), "0")
}
func testStrideable() {
// Offset, verb
let sample1 = Int0(), sample2 = UInt0()
XCTAssertEqual(sample1.advanced(by: 0 /*Int0()*/), Int0())
XCTAssertEqual(sample2.advanced(by: 0 /*Int0()*/), UInt0())
// Offset, noun
XCTAssertEqual(sample1.distance(to: Int0()), Int0())
XCTAssertEqual(sample2.distance(to: UInt0()), Int0()) // Different type
}
func testBinaryInteger() {
// Sign-ness
XCTAssertTrue(Int0.isSigned)
XCTAssertFalse(UInt0.isSigned)
// Floating-point conversion
XCTAssertEqual(Int0(exactly: 0.0), Int0())
XCTAssertEqual(UInt0(exactly: 0.0), UInt0())
XCTAssertNil(Int0(exactly: -0.5))
XCTAssertNil(Int0(exactly: -2.0))
XCTAssertNil(Int0(exactly: +0.5))
XCTAssertNil(Int0(exactly: +1.0))
XCTAssertNil(Int0(exactly: -Double.infinity))
XCTAssertNil(UInt0(exactly: -0.5))
XCTAssertNil(UInt0(exactly: -2.0))
XCTAssertNil(UInt0(exactly: +0.5))
XCTAssertNil(UInt0(exactly: +1.0))
XCTAssertNil(UInt0(exactly: Double.nan))
XCTAssertEqual(Int0(0.0), Int0())
XCTAssertEqual(Int0(-0.3), Int0())
XCTAssertEqual(Int0(+0.7), Int0())
XCTAssertEqual(UInt0(0.0), UInt0())
XCTAssertEqual(UInt0(-0.3), UInt0())
XCTAssertEqual(UInt0(+0.7), UInt0())
#if false
// Non-zero values error out!
XCTAssertNotEqual(Int0(1.0), Int0())
XCTAssertNotEqual(Int0(-5.0), Int0())
XCTAssertNotEqual(Int0(Double.infinity), Int0())
XCTAssertNotEqual(UInt0(1.0), UInt0())
XCTAssertNotEqual(UInt0(-5.0), UInt0())
XCTAssertNotEqual(UInt0(Double.infinity), UInt0())
#endif
// Integer conversion
XCTAssertEqual(Int0(0 as UInt16), Int0())
XCTAssertEqual(UInt0(0 as Int16), UInt0())
#if false
// Non-zero values error out!
XCTAssertNotEqual(Int0(-1 as Int16), Int0())
XCTAssertNotEqual(Int0(+1 as UInt16), Int0())
XCTAssertNotEqual(UInt0(-1 as Int16), UInt0())
XCTAssertNotEqual(UInt0(+1 as UInt16), UInt0())
#endif
// Massaged integer conversion
XCTAssertEqual(Int0(truncatingIfNeeded: -128), Int0())
XCTAssertEqual(Int0(truncatingIfNeeded: 0), Int0())
XCTAssertEqual(Int0(truncatingIfNeeded: +127), Int0())
XCTAssertEqual(Int0(clamping: -128), Int0())
XCTAssertEqual(Int0(clamping: 0), Int0())
XCTAssertEqual(Int0(clamping: +127), Int0())
XCTAssertEqual(UInt0(truncatingIfNeeded: -128), UInt0())
XCTAssertEqual(UInt0(truncatingIfNeeded: 0), UInt0())
XCTAssertEqual(UInt0(truncatingIfNeeded: +127), UInt0())
XCTAssertEqual(UInt0(clamping: -128), UInt0())
XCTAssertEqual(UInt0(clamping: 0), UInt0())
XCTAssertEqual(UInt0(clamping: +127), UInt0())
// Bit-layout status
let sample1 = Int0(), sample2 = UInt0()
XCTAssertTrue(sample1.words.allSatisfy({ $0 == 0 }))
XCTAssertEqual(sample1.bitWidth, 0)
XCTAssertEqual(sample1.trailingZeroBitCount, 0)
XCTAssertTrue(sample2.words.allSatisfy({ $0 == 0 }))
XCTAssertEqual(sample2.bitWidth, 0)
XCTAssertEqual(sample2.trailingZeroBitCount, 0)
// Bit twiddling, non-mutating
var sample3 = Int0(), sample4 = UInt0()
XCTAssertEqual(~sample1, Int0())
XCTAssertEqual(sample1 & sample3, Int0())
XCTAssertEqual(sample1 | sample3, Int0())
XCTAssertEqual(sample1 ^ sample3, Int0())
XCTAssertEqual(sample1 << sample3, Int0())
XCTAssertEqual(sample1 >> sample3, Int0())
XCTAssertEqual(sample1 << Int.random(in: -128...127), Int0())
XCTAssertEqual(sample1 >> Int.random(in: -128...127), Int0())
XCTAssertEqual(~sample2, UInt0())
XCTAssertEqual(sample2 & sample4, UInt0())
XCTAssertEqual(sample2 | sample4, UInt0())
XCTAssertEqual(sample2 ^ sample4, UInt0())
XCTAssertEqual(sample2 << sample4, UInt0())
XCTAssertEqual(sample2 >> sample4, UInt0())
XCTAssertEqual(sample2 << Int.random(in: -128...127), UInt0())
XCTAssertEqual(sample2 >> Int.random(in: -128...127), UInt0())
// Bit twiddling, mutating
sample3 &= sample1
XCTAssertEqual(sample3, Int0())
sample3 |= sample1
XCTAssertEqual(sample3, Int0())
sample3 ^= sample1
XCTAssertEqual(sample3, Int0())
sample3 <<= sample1
XCTAssertEqual(sample3, Int0())
sample3 >>= sample1
XCTAssertEqual(sample3, Int0())
sample3 <<= Int.random(in: -128...127)
XCTAssertEqual(sample3, Int0())
sample3 >>= Int.random(in: -128...127)
XCTAssertEqual(sample3, Int0())
sample4 &= sample2
XCTAssertEqual(sample4, UInt0())
sample4 |= sample2
XCTAssertEqual(sample4, UInt0())
sample4 ^= sample2
XCTAssertEqual(sample4, UInt0())
sample4 <<= sample2
XCTAssertEqual(sample4, UInt0())
sample4 >>= sample2
XCTAssertEqual(sample4, UInt0())
sample4 <<= Int.random(in: -128...127)
XCTAssertEqual(sample4, UInt0())
sample4 >>= Int.random(in: -128...127)
XCTAssertEqual(sample4, UInt0())
#if false
// Division, non-mutating
let qrInt0 = sample1.quotientAndRemainder(dividingBy: sample3)
XCTAssertNotEqual(qrInt0.quotient, Int0())
XCTAssertNotEqual(qrInt0.remainder, Int0())
XCTAssertNotEqual(sample1 / sample3, Int0())
XCTAssertNotEqual(sample1 % sample3, Int0())
let qrUInt0 = sample2.quotientAndRemainder(dividingBy: sample4)
XCTAssertNotEqual(qrUInt0.quotient, UInt0())
XCTAssertNotEqual(qrUInt0.remainder, UInt0())
XCTAssertNotEqual(sample2 / sample4, UInt0())
XCTAssertNotEqual(sample2 % sample4, UInt0())
// Division, mutating
sample3 /= sample1
XCTAssertNotEqual(sample3, Int0())
sample3 %= sample1
XCTAssertNotEqual(sample3, Int0())
sample4 /= sample2
XCTAssertNotEqual(sample4, UInt0())
sample4 %= sample2
XCTAssertNotEqual(sample4, UInt0())
#endif
// Multiples
XCTAssertTrue(sample3.isMultiple(of: sample1))
XCTAssertTrue(sample4.isMultiple(of: sample2))
// Signs
XCTAssertEqual(sample1.signum(), Int0())
XCTAssertEqual(sample2.signum(), UInt0())
// Non-requirement: Mixed comparisons
XCTAssertTrue(sample1 == sample2)
XCTAssertTrue(sample2 == sample1)
XCTAssertFalse(sample1 != sample2)
XCTAssertFalse(sample2 != sample1)
XCTAssertFalse(sample1 < sample2)
XCTAssertFalse(sample2 < sample1)
XCTAssertTrue(sample1 >= sample2)
XCTAssertTrue(sample2 >= sample1)
XCTAssertFalse(sample1 > sample2)
XCTAssertFalse(sample2 > sample1)
XCTAssertTrue(sample1 <= sample2)
XCTAssertTrue(sample2 <= sample1)
}
func testLosslessStringConvertible() {
// Accepting standard output format
XCTAssertEqual(Int0("0"), Int0())
XCTAssertEqual(UInt0("0"), UInt0())
// Signed zero
XCTAssertEqual(Int0("+0"), Int0())
XCTAssertEqual(Int0("-0"), Int0())
XCTAssertEqual(UInt0("+0"), UInt0())
XCTAssertEqual(UInt0("-0"), UInt0())
// Multiple zeros
XCTAssertEqual(Int0("000000000"), Int0())
XCTAssertEqual(UInt0("000000000"), UInt0())
XCTAssertEqual(Int0("+000000000"), Int0())
XCTAssertEqual(Int0("-000000000"), Int0())
XCTAssertEqual(UInt0("+000000000"), UInt0())
XCTAssertEqual(UInt0("-000000000"), UInt0())
// Parsing errors
XCTAssertNil(Int0(""))
XCTAssertNil(Int0("+"))
XCTAssertNil(Int0("-"))
XCTAssertNil(Int0("1"))
XCTAssertNil(Int0("a"))
XCTAssertNil(Int0(";"))
XCTAssertNil(Int0("000030"))
XCTAssertNil(Int0("+r"))
XCTAssertNil(Int0("-*"))
XCTAssertNil(Int0("+000W"))
XCTAssertNil(Int0("-00|"))
XCTAssertNil(UInt0(""))
XCTAssertNil(UInt0("+"))
XCTAssertNil(UInt0("-"))
XCTAssertNil(UInt0("1"))
XCTAssertNil(UInt0("a"))
XCTAssertNil(UInt0(";"))
XCTAssertNil(UInt0("000030"))
XCTAssertNil(UInt0("+r"))
XCTAssertNil(UInt0("-*"))
XCTAssertNil(UInt0("+000W"))
XCTAssertNil(UInt0("-00|"))
}
func testFixedWidthInteger() {
// Size and bounds
XCTAssertEqual(Int0.bitWidth, 0)
XCTAssertEqual(Int0.max, Int0())
XCTAssertEqual(Int0.min, Int0())
XCTAssertEqual(UInt0.bitWidth, 0)
XCTAssertEqual(UInt0.max, UInt0())
XCTAssertEqual(UInt0.min, UInt0())
// Bit counts
let sample1 = Int0()
XCTAssertEqual(sample1.nonzeroBitCount, 0)
XCTAssertEqual(sample1.leadingZeroBitCount, 0)
let sample2 = UInt0()
XCTAssertEqual(sample2.nonzeroBitCount, 0)
XCTAssertEqual(sample2.leadingZeroBitCount, 0)
// Endian
XCTAssertEqual(Int0(bigEndian: sample1), Int0())
XCTAssertEqual(Int0(littleEndian: sample1), Int0())
XCTAssertEqual(sample1.bigEndian, Int0())
XCTAssertEqual(sample1.littleEndian, Int0())
XCTAssertEqual(sample1.byteSwapped, Int0())
XCTAssertEqual(UInt0(bigEndian: sample2), UInt0())
XCTAssertEqual(UInt0(littleEndian: sample2), UInt0())
XCTAssertEqual(sample2.bigEndian, UInt0())
XCTAssertEqual(sample2.littleEndian, UInt0())
XCTAssertEqual(sample2.byteSwapped, UInt0())
// Addition/Subtraction/Multiplication
let fullAdd1 = sample1.addingReportingOverflow(sample1)
let fullSubtract1 = sample1.subtractingReportingOverflow(sample1)
let easyMultiply1 = sample1.multipliedReportingOverflow(by: sample1)
let hardMultiply1 = sample1.multipliedFullWidth(by: sample1)
XCTAssertEqual(fullAdd1.partialValue, Int0())
XCTAssertFalse(fullAdd1.overflow)
XCTAssertEqual(fullSubtract1.partialValue, Int0())
XCTAssertFalse(fullSubtract1.overflow)
XCTAssertEqual(easyMultiply1.partialValue, Int0())
XCTAssertFalse(easyMultiply1.overflow)
XCTAssertEqual(hardMultiply1.low, UInt0())
XCTAssertEqual(hardMultiply1.high, Int0())
let fullAdd2 = sample2.addingReportingOverflow(sample2)
let fullSubtract2 = sample2.subtractingReportingOverflow(sample2)
let easyMultiply2 = sample2.multipliedReportingOverflow(by: sample2)
let hardMultiply2 = sample2.multipliedFullWidth(by: sample2)
XCTAssertEqual(fullAdd2.partialValue, UInt0())
XCTAssertFalse(fullAdd2.overflow)
XCTAssertEqual(fullSubtract2.partialValue, UInt0())
XCTAssertFalse(fullSubtract2.overflow)
XCTAssertEqual(easyMultiply2.partialValue, UInt0())
XCTAssertFalse(easyMultiply2.overflow)
XCTAssertEqual(hardMultiply2.low, UInt0())
XCTAssertEqual(hardMultiply2.high, UInt0())
// Division
let fullDivision1 = sample1.dividedReportingOverflow(by: sample1)
let fullRemainder1 = sample1.remainderReportingOverflow(dividingBy: sample1)
XCTAssertEqual(fullDivision1.partialValue, sample1)
XCTAssertTrue(fullDivision1.overflow)
XCTAssertEqual(fullRemainder1.partialValue, sample1)
XCTAssertTrue(fullRemainder1.overflow)
let fullDivision2 = sample2.dividedReportingOverflow(by: sample2)
let fullRemainder2 = sample2.remainderReportingOverflow(dividingBy: sample2)
XCTAssertEqual(fullDivision2.partialValue, sample2)
XCTAssertTrue(fullDivision2.overflow)
XCTAssertEqual(fullRemainder2.partialValue, sample2)
XCTAssertTrue(fullRemainder2.overflow)
#if false
let hardDivision1 = sample1.dividingFullWidth((high: sample1, low: sample1.magnitude))
XCTAssertNotEqual(hardDivision1.quotient, Int0())
XCTAssertNotEqual(hardDivision1.remainder, Int0())
let hardDivision2 = sample2.dividingFullWidth((high: sample2, low: sample2.magnitude))
XCTAssertNotEqual(hardDivision2.quotient, UInt0())
XCTAssertNotEqual(hardDivision2.remainder, UInt0())
#endif
// Wrap-reduced Bit-shifting
XCTAssertEqual(sample1 &>> sample1, Int0())
XCTAssertEqual(sample1 &<< sample1, Int0())
var sample3 = Int0()
sample3 &>>= sample1
XCTAssertEqual(sample3, Int0())
sample3 &<<= sample1
XCTAssertEqual(sample3, Int0())
XCTAssertEqual(sample2 &>> sample2, UInt0())
XCTAssertEqual(sample2 &<< sample2, UInt0())
var sample4 = UInt0()
sample4 &>>= sample2
XCTAssertEqual(sample4, UInt0())
sample4 &<<= sample2
XCTAssertEqual(sample4, UInt0())
#if false
// Non-requirement: Text input with arbitrary radix
// FAIL! The code for the initializer converts the radix to the result
// type. Since all valid radices (2...36) are outside these types'
// ranges, we can never get this initializer to work.
XCTAssertEqual(Int0("0", radix: 10), Int0())
XCTAssertEqual(UInt0("0", radix: 10), UInt0())
// Put various passing and failing conditions here....
#endif
// Non-requirement: Random values
// (Since there's only one valid value, not hard to guess.)
XCTAssertEqual(Int0.random(in: sample1...sample1), Int0())
XCTAssertEqual(UInt0.random(in: sample2...sample2), UInt0())
var rng = SystemRandomNumberGenerator()
for _ in 0..<100 {
XCTAssertEqual(Int0.random(in: sample1...sample1, using: &rng), Int0())
XCTAssertEqual(UInt0.random(in: sample2...sample2, using: &rng), UInt0())
}
#if false
// Since these type each support one value, you cannot make a non-empty
// range with them, and the random methods that use Range require a
// non-empty one.
XCTAssertNotEqual(Int0.random(in: sample1..<sample1), Int0())
XCTAssertNotEqual(UInt0.random(in: sample2..<sample2), UInt0())
for _ in 0..<100 {
XCTAssertEqual(Int0.random(in: sample1..<sample1, using: &rng), Int0())
XCTAssertEqual(UInt0.random(in: sample2..<sample2, using: &rng), UInt0())
}
#endif
// Non-requirement: Wrapping arithmetic
XCTAssertEqual(sample1 &+ sample1, Int0())
XCTAssertEqual(sample1 &- sample1, Int0())
XCTAssertEqual(sample1 &* sample1, Int0())
sample3 &+= sample1
XCTAssertEqual(sample3, Int0())
sample3 &-= sample1
XCTAssertEqual(sample3, Int0())
sample3 &*= sample1
XCTAssertEqual(sample3, Int0())
XCTAssertEqual(sample2 &+ sample2, UInt0())
XCTAssertEqual(sample2 &- sample2, UInt0())
XCTAssertEqual(sample2 &* sample2, UInt0())
sample4 &+= sample2
XCTAssertEqual(sample4, UInt0())
sample4 &-= sample2
XCTAssertEqual(sample4, UInt0())
sample4 &*= sample2
XCTAssertEqual(sample4, UInt0())
// Non-requirement: Cross-version wrap-reduced bit-shifting
XCTAssertEqual(sample1 &>> sample2, Int0())
XCTAssertEqual(sample1 &<< sample2, Int0())
XCTAssertEqual(sample2 &>> sample1, UInt0())
XCTAssertEqual(sample2 &<< sample1, UInt0())
sample3 &>>= sample2
XCTAssertEqual(sample3, Int0())
sample3 &<<= sample2
XCTAssertEqual(sample3, Int0())
sample4 &>>= sample1
XCTAssertEqual(sample4, UInt0())
sample4 &<<= sample1
XCTAssertEqual(sample4, UInt0())
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment