From 53880821e775a2090ced842a74fe71b2aa45b800 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Tue, 11 Jul 2023 08:33:49 +0200 Subject: [PATCH 001/133] NBKFlexibleWidthKit (#33). --- .../NBKFlexibleWidthKit-Benchmarks.xctestplan | 28 ++ .swiftpm/NBKFlexibleWidthKit.xctestplan | 32 ++ .swiftpm/Numberick-Benchmarks.xctestplan | 11 + .swiftpm/Numberick.xctestplan | 12 + .../NBKFlexibleWidthKit-Benchmarks.xcscheme | 71 +++ .../xcschemes/NBKFlexibleWidthKit.xcscheme | 71 +++ .../xcschemes/Numberick-Benchmarks.xcscheme | 17 + .../xcshareddata/xcschemes/Numberick.xcscheme | 17 + Package.swift | 22 +- README.md | 8 + .../NBKFlexibleWidth+Addition+Digit.swift | 60 +++ .../NBKFlexibleWidth+Addition.swift | 60 +++ .../NBKFlexibleWidth+Bits.swift | 61 +++ .../NBKFlexibleWidth+Comparisons.swift | 84 ++++ .../NBKFlexibleWidth+Complements.swift | 29 ++ .../NBKFlexibleWidth+Division+Digit.swift | 70 +++ .../NBKFlexibleWidth+Division.swift | 130 ++++++ .../NBKFlexibleWidth+Logic.swift | 87 ++++ ...BKFlexibleWidth+Multiplication+Digit.swift | 59 +++ .../NBKFlexibleWidth+Multiplication.swift | 60 +++ .../NBKFlexibleWidth+Numbers.swift | 125 ++++++ .../NBKFlexibleWidth+Shifts.swift | 200 +++++++++ .../NBKFlexibleWidth+Storage.swift | 91 ++++ .../NBKFlexibleWidth+Subtraction+Digit.swift | 72 +++ .../NBKFlexibleWidth+Subtraction.swift | 61 +++ .../NBKFlexibleWidth+Text+Radix.swift | 158 +++++++ .../NBKFlexibleWidth+Text.swift | 80 ++++ .../NBKFlexibleWidth+Uninitialized.swift | 31 ++ .../NBKFlexibleWidth+Words.swift | 34 ++ .../NBKFlexibleWidth.swift | 59 +++ .../Private/Arithmagick.swift | 60 +++ .../Private/RadixAlphabet.swift | 88 ++++ .../Private/RadixUIntRoot.swift | 274 ++++++++++++ .../NBKFlexibleWidthKit/Private/Text.swift | 134 ++++++ .../Documentation.docc/Documentation.md | 3 + Sources/Numberick/Exports.swift | 1 + .../256+Random.swift | 2 +- .../IntXL+Addition.swift | 58 +++ .../IntXL+Bits.swift | 123 +++++ .../IntXL+Comparisons.swift | 105 +++++ .../IntXL+Division.swift | 103 +++++ .../IntXL+Logic.swift | 74 ++++ .../IntXL+Multiplication.swift | 58 +++ .../IntXL+Numbers.swift | 419 ++++++++++++++++++ .../IntXL+Shifts.swift | 102 +++++ .../IntXL+Subtraction.swift | 58 +++ .../IntXL+Text.swift | 109 +++++ .../NBKFlexibleWidth.swift | 80 ++++ .../Utilities/Stdlib.swift | 23 + .../IntXL+Addition.swift | 94 ++++ .../NBKFlexibleWidthKitTests/IntXL+Bits.swift | 98 ++++ .../IntXL+Comparisons.swift | 147 ++++++ .../IntXL+Division.swift | 122 +++++ .../IntXL+Logic.swift | 73 +++ .../IntXL+Multiplication.swift | 70 +++ .../IntXL+Numbers.swift | 235 ++++++++++ .../IntXL+Shifts.swift | 116 +++++ .../IntXL+Subtraction.swift | 115 +++++ .../NBKFlexibleWidthKitTests/IntXL+Text.swift | 241 ++++++++++ .../IntXL+Words.swift | 73 +++ .../NBKFlexibleWidth.swift | 80 ++++ .../Utilities/NBKAssert+Addition.swift | 42 ++ .../Utilities/NBKAssert+Comparisons.swift | 31 ++ .../Utilities/NBKAssert+Division.swift | 81 ++++ .../Utilities/NBKAssert+Logic.swift | 54 +++ .../Utilities/NBKAssert+Multiplication.swift | 36 ++ .../Utilities/NBKAssert+Numbers.swift | 53 +++ .../Utilities/NBKAssert+Shifts.swift | 80 ++++ .../Utilities/NBKAssert+Subtraction.swift | 48 ++ .../Utilities/NBKAssert+Text.swift | 41 ++ .../Utilities/NBKAssert+Words.swift | 22 + 71 files changed, 5724 insertions(+), 2 deletions(-) create mode 100644 .swiftpm/NBKFlexibleWidthKit-Benchmarks.xctestplan create mode 100644 .swiftpm/NBKFlexibleWidthKit.xctestplan create mode 100644 .swiftpm/xcode/xcshareddata/xcschemes/NBKFlexibleWidthKit-Benchmarks.xcscheme create mode 100644 .swiftpm/xcode/xcshareddata/xcschemes/NBKFlexibleWidthKit.xcscheme create mode 100644 Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift create mode 100644 Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift create mode 100644 Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift create mode 100644 Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift create mode 100644 Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements.swift create mode 100644 Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.swift create mode 100644 Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift create mode 100644 Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift create mode 100644 Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift create mode 100644 Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift create mode 100644 Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift create mode 100644 Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift create mode 100644 Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Storage.swift create mode 100644 Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift create mode 100644 Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift create mode 100644 Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text+Radix.swift create mode 100644 Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text.swift create mode 100644 Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Uninitialized.swift create mode 100644 Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift create mode 100644 Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift create mode 100644 Sources/NBKFlexibleWidthKit/Private/Arithmagick.swift create mode 100644 Sources/NBKFlexibleWidthKit/Private/RadixAlphabet.swift create mode 100644 Sources/NBKFlexibleWidthKit/Private/RadixUIntRoot.swift create mode 100644 Sources/NBKFlexibleWidthKit/Private/Text.swift create mode 100644 Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Addition.swift create mode 100644 Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Bits.swift create mode 100644 Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Comparisons.swift create mode 100644 Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Division.swift create mode 100644 Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Logic.swift create mode 100644 Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Multiplication.swift create mode 100644 Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Numbers.swift create mode 100644 Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Shifts.swift create mode 100644 Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Subtraction.swift create mode 100644 Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Text.swift create mode 100644 Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth.swift create mode 100644 Tests/NBKFlexibleWidthKitBenchmarks/Utilities/Stdlib.swift create mode 100644 Tests/NBKFlexibleWidthKitTests/IntXL+Addition.swift create mode 100644 Tests/NBKFlexibleWidthKitTests/IntXL+Bits.swift create mode 100644 Tests/NBKFlexibleWidthKitTests/IntXL+Comparisons.swift create mode 100644 Tests/NBKFlexibleWidthKitTests/IntXL+Division.swift create mode 100644 Tests/NBKFlexibleWidthKitTests/IntXL+Logic.swift create mode 100644 Tests/NBKFlexibleWidthKitTests/IntXL+Multiplication.swift create mode 100644 Tests/NBKFlexibleWidthKitTests/IntXL+Numbers.swift create mode 100644 Tests/NBKFlexibleWidthKitTests/IntXL+Shifts.swift create mode 100644 Tests/NBKFlexibleWidthKitTests/IntXL+Subtraction.swift create mode 100644 Tests/NBKFlexibleWidthKitTests/IntXL+Text.swift create mode 100644 Tests/NBKFlexibleWidthKitTests/IntXL+Words.swift create mode 100644 Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth.swift create mode 100644 Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Addition.swift create mode 100644 Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Comparisons.swift create mode 100644 Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Division.swift create mode 100644 Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Logic.swift create mode 100644 Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Multiplication.swift create mode 100644 Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Numbers.swift create mode 100644 Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Shifts.swift create mode 100644 Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Subtraction.swift create mode 100644 Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Text.swift create mode 100644 Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Words.swift diff --git a/.swiftpm/NBKFlexibleWidthKit-Benchmarks.xctestplan b/.swiftpm/NBKFlexibleWidthKit-Benchmarks.xctestplan new file mode 100644 index 00000000..55b3abb9 --- /dev/null +++ b/.swiftpm/NBKFlexibleWidthKit-Benchmarks.xctestplan @@ -0,0 +1,28 @@ +{ + "configurations" : [ + { + "id" : "2BBD9A51-D890-4B97-AED4-B9962867DF57", + "name" : "Main", + "options" : { + + } + } + ], + "defaultOptions" : { + "codeCoverage" : false + }, + "testTargets" : [ + { + "skippedTests" : [ + "UIntXLBenchmarksOnText\/testEncodingUsingSwiftStdlibRadix10()", + "UIntXLBenchmarksOnText\/testEncodingUsingSwiftStdlibRadix16()" + ], + "target" : { + "containerPath" : "container:", + "identifier" : "NBKFlexibleWidthKitBenchmarks", + "name" : "NBKFlexibleWidthKitBenchmarks" + } + } + ], + "version" : 1 +} diff --git a/.swiftpm/NBKFlexibleWidthKit.xctestplan b/.swiftpm/NBKFlexibleWidthKit.xctestplan new file mode 100644 index 00000000..de7211dc --- /dev/null +++ b/.swiftpm/NBKFlexibleWidthKit.xctestplan @@ -0,0 +1,32 @@ +{ + "configurations" : [ + { + "id" : "6FC9897F-2BF3-4836-8372-787CE5195F87", + "name" : "Main", + "options" : { + + } + } + ], + "defaultOptions" : { + "codeCoverage" : { + "targets" : [ + { + "containerPath" : "container:", + "identifier" : "NBKFlexibleWidthKit", + "name" : "NBKFlexibleWidthKit" + } + ] + } + }, + "testTargets" : [ + { + "target" : { + "containerPath" : "container:", + "identifier" : "NBKFlexibleWidthKitTests", + "name" : "NBKFlexibleWidthKitTests" + } + } + ], + "version" : 1 +} diff --git a/.swiftpm/Numberick-Benchmarks.xctestplan b/.swiftpm/Numberick-Benchmarks.xctestplan index e3dcc3ec..9e832105 100644 --- a/.swiftpm/Numberick-Benchmarks.xctestplan +++ b/.swiftpm/Numberick-Benchmarks.xctestplan @@ -35,6 +35,17 @@ "identifier" : "NBKDoubleWidthKitBenchmarks", "name" : "NBKDoubleWidthKitBenchmarks" } + }, + { + "skippedTests" : [ + "UIntXLBenchmarksOnText\/testEncodingUsingSwiftStdlibRadix10()", + "UIntXLBenchmarksOnText\/testEncodingUsingSwiftStdlibRadix16()" + ], + "target" : { + "containerPath" : "container:", + "identifier" : "NBKFlexibleWidthKitBenchmarks", + "name" : "NBKFlexibleWidthKitBenchmarks" + } } ], "version" : 1 diff --git a/.swiftpm/Numberick.xctestplan b/.swiftpm/Numberick.xctestplan index ac666b5b..74306fdc 100644 --- a/.swiftpm/Numberick.xctestplan +++ b/.swiftpm/Numberick.xctestplan @@ -20,6 +20,11 @@ "containerPath" : "container:", "identifier" : "NBKDoubleWidthKit", "name" : "NBKDoubleWidthKit" + }, + { + "containerPath" : "container:", + "identifier" : "NBKFlexibleWidthKit", + "name" : "NBKFlexibleWidthKit" } ] } @@ -38,6 +43,13 @@ "identifier" : "NBKDoubleWidthKitTests", "name" : "NBKDoubleWidthKitTests" } + }, + { + "target" : { + "containerPath" : "container:", + "identifier" : "NBKFlexibleWidthKitTests", + "name" : "NBKFlexibleWidthKitTests" + } } ], "version" : 1 diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/NBKFlexibleWidthKit-Benchmarks.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/NBKFlexibleWidthKit-Benchmarks.xcscheme new file mode 100644 index 00000000..75c0e83f --- /dev/null +++ b/.swiftpm/xcode/xcshareddata/xcschemes/NBKFlexibleWidthKit-Benchmarks.xcscheme @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/NBKFlexibleWidthKit.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/NBKFlexibleWidthKit.xcscheme new file mode 100644 index 00000000..c72f5e4d --- /dev/null +++ b/.swiftpm/xcode/xcshareddata/xcschemes/NBKFlexibleWidthKit.xcscheme @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/Numberick-Benchmarks.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/Numberick-Benchmarks.xcscheme index 364160d7..118e12c8 100644 --- a/.swiftpm/xcode/xcshareddata/xcschemes/Numberick-Benchmarks.xcscheme +++ b/.swiftpm/xcode/xcshareddata/xcschemes/Numberick-Benchmarks.xcscheme @@ -48,6 +48,20 @@ ReferencedContainer = "container:"> + + + + + + + + + + + + **Note**: The `Digit` type is `Int` when `Self` is signed, and `UInt` otherwise. +## [NBKFlexibleWidthKit][FLX/D] ([Sources][FLX/S], [Tests][FLX/T], [Benchmarks][FLX/B]) + +👨‍💻🛠️🚧🧱🧱🏗️🧱🧱🚧⏳ + ## Acknowledgements This project is inspired by [**Int128**][Apple/Int128] and [**DoubleWidth**][Apple/DoubleWidth] by Apple. @@ -97,15 +101,19 @@ This project is inspired by [**Int128**][Apple/Int128] and [**DoubleWidth**][App [NBK/D]: https://oscbyspro.github.io/Numberick/documentation/numberick [DBL/D]: https://oscbyspro.github.io/Numberick/documentation/numberick/nbkdoublewidth +[FLX/D]: https://oscbyspro.github.io/Numberick/documentation/numberick/nbkflexiblewidth [COR/S]: Sources/NBKCoreKit [DBL/S]: Sources/NBKDoubleWidthKit +[FLX/S]: Sources/NBKFlexibleWidthKit [COR/T]: Tests/NBKCoreKitTests [DBL/T]: Tests/NBKDoubleWidthKitTests +[FLX/T]: Tests/NBKFlexibleWidthKitTests [COR/B]: Tests/NBKCoreKitBenchmarks [DBL/B]: Tests/NBKDoubleWidthKitBenchmarks +[FLX/B]: Tests/NBKFlexibleWidthKitBenchmarks diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift new file mode 100644 index 00000000..41407904 --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift @@ -0,0 +1,60 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x Addition x Digit x Unsigned +//*============================================================================* + +extension NBKFlexibleWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @_disfavoredOverload @inlinable public static func +=(lhs: inout Self, rhs: UInt) { + lhs.add(rhs, at: Int.zero) + } + + @_disfavoredOverload @inlinable public static func +(lhs: Self, rhs: UInt) -> Self { + lhs.adding(rhs, at: Int.zero) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @_disfavoredOverload @inlinable public mutating func add(_ other: UInt, at index: Int) { + defer { Swift.assert(self.isNormal) } + //=--------------------------------------= + if other.isZero { return } + //=--------------------------------------= + self.resize(minLastIndex: index) + + var index = index as Int + var carry = self.storage[index].addReportingOverflow(other) + self.storage.formIndex(after: &index) + + while carry && index < self.storage.endIndex { + carry = self.storage[index].addReportingOverflow(1 as UInt) + self.storage.formIndex(after: &index) + } + + if carry { + self.storage.append(1 as UInt) + } + } + + @_disfavoredOverload @inlinable public func adding(_ other: UInt, at index: Int) -> Self { + var result = self + result.add(other, at: index) + return result as Self + } +} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift new file mode 100644 index 00000000..25ee2aeb --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift @@ -0,0 +1,60 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x Addition x Unsigned +//*============================================================================* + +extension NBKFlexibleWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public static func +=(lhs: inout Self, rhs: Self) { + lhs.add(rhs, at: Int.zero) + } + + @inlinable public static func +(lhs: Self, rhs: Self) -> Self { + lhs.adding(rhs, at: Int.zero) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public mutating func add(_ other: Self, at index: Int) { + defer { Swift.assert(self.isNormal) } + //=--------------------------------------= + if other.isZero { return } + //=--------------------------------------= + self.resize(minCount: other.storage.count + index) + + var index = index + var carry = false + + for var addend in other.storage { + carry = addend.addReportingOverflow(UInt(bit: carry)) + carry = self.storage[index].addReportingOverflow(addend) || carry + self.storage.formIndex(after: &index) + } + + if carry { + self.storage.append(1 as UInt) + } + } + + @inlinable public func adding(_ other: Self, at index: Int) -> Self { + var result = self + result.add(other, at: index) + return result as Self + } +} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift new file mode 100644 index 00000000..c86f2bec --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift @@ -0,0 +1,61 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x Bits x Unsigned +//*============================================================================* + +extension NBKFlexibleWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + @inlinable public init(bit: Bool) { + self.init(digit: Digit(bit: bit)) + } + + //=------------------------------------------------------------------------= + // MARK: Accessors + //=------------------------------------------------------------------------= + + @inlinable public var bitWidth: Int { + self.storage.count * UInt.bitWidth + } + + @inlinable public var nonzeroBitCount: Int { + self.storage.reduce(0) { $0 + $1.nonzeroBitCount } + } + + @inlinable public var leadingZeroBitCount: Int { + self.storage[self.storage.index(before: self.storage.endIndex)].leadingZeroBitCount + } + + @inlinable public var trailingZeroBitCount: Int { + var index = self.storage.startIndex + var element = UInt.zero + + while index < self.storage.endIndex, element.isZero { + element = self.storage[index] + self.storage.formIndex(after: &index) + } + + return (index - 1) * UInt.bitWidth + element.trailingZeroBitCount + } + + @inlinable public var mostSignificantBit: Bool { + self.storage[self.storage.index(before: self.storage.endIndex)].mostSignificantBit + } + + @inlinable public var leastSignificantBit: Bool { + self.storage[self.storage.startIndex].leastSignificantBit + } +} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift new file mode 100644 index 00000000..6887cbb9 --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift @@ -0,0 +1,84 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x Comparisons x Unsigned +//*============================================================================* + +extension NBKFlexibleWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Accessors + //=------------------------------------------------------------------------= + + @inlinable public var isZero: Bool { + self.storage.count == 1 && self.storage[0].isZero + } + + @inlinable public var isLessThanZero: Bool { + false + } + + @inlinable public var isMoreThanZero: Bool { + !self.isZero + } + + @inlinable public func signum() -> Int { + Int(bit: !self.isZero) + } + + @inlinable public var isPowerOf2: Bool { + var nonzeroBitCountLowerBound = 0 + var index = self.storage.startIndex + //=--------------------------------------= + while index < self.storage.endIndex, nonzeroBitCountLowerBound < 2 { + nonzeroBitCountLowerBound &+= self.storage[index].nonzeroBitCount + self.storage.formIndex(after: &index) + } + //=--------------------------------------= + return nonzeroBitCountLowerBound == 1 + } + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + @inlinable public func hash(into hasher: inout Hasher) { + hasher.combine(self.storage) + } + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + @inlinable public static func ==(lhs: Self, rhs: Self) -> Bool { + lhs.storage == rhs.storage + } + + @inlinable public static func <(lhs: Self, rhs: Self) -> Bool { + lhs.compared(to: rhs) == -1 + } + + @inlinable public func compared(to other: Self) -> Int { + //=--------------------------------------= + if self.storage.count != other.storage.count { + return self.storage.count < other.storage.count ? -1 : 1 + } + //=--------------------------------------= + for index in self.storage.indices.reversed() { + let lhsWord: UInt = self .storage[index] + let rhsWord: UInt = other.storage[index] + if lhsWord != rhsWord { return lhsWord < rhsWord ? -1 : 1 } + } + + return Int.zero + } +} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements.swift new file mode 100644 index 00000000..84c0bc23 --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements.swift @@ -0,0 +1,29 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x Complements x Unsigned +//*============================================================================* + +extension NBKFlexibleWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + @inlinable public mutating func formTwosComplement() { + fatalError("TODO") + } + + @inlinable public func twosComplement() -> Self { + fatalError("TODO") + } +} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.swift new file mode 100644 index 00000000..2f9823b6 --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.swift @@ -0,0 +1,70 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x Division x Digit x Unsigned +//*============================================================================* + +extension NBKFlexibleWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @_disfavoredOverload @inlinable public mutating func divideReportingOverflow(by other: Digit) -> Bool { + let pvo: PVO = self.dividedReportingOverflow(by: other) + self = pvo.partialValue + return pvo.overflow as Bool + } + + @_disfavoredOverload @inlinable public func dividedReportingOverflow(by other: Digit) -> PVO { + let qro: PVO> = self.quotientAndRemainderReportingOverflow(dividingBy: other) + return PVO(qro.partialValue.quotient, qro.overflow) + } + + @_disfavoredOverload @inlinable public mutating func formRemainderReportingOverflow(dividingBy other: Digit) -> Bool { + let pvo: PVO = self.remainderReportingOverflow(dividingBy: other) + self = Self(digit: pvo.partialValue) + return pvo.overflow as Bool + } + + @_disfavoredOverload @inlinable public func remainderReportingOverflow(dividingBy other: Digit) -> PVO { + let qro: PVO> = self.quotientAndRemainderReportingOverflow(dividingBy: other) + return PVO(qro.partialValue.remainder, qro.overflow) + } + + @_disfavoredOverload @inlinable public func quotientAndRemainderReportingOverflow(dividingBy other: UInt) -> PVO> { + var quotient = self + let remainder = quotient.formQuotientWithRemainderReportingOverflow(dividingBy: other) + return PVO(QR(quotient, remainder.partialValue), remainder.overflow) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Private + //=------------------------------------------------------------------------= + + @_disfavoredOverload @inlinable mutating func formQuotientWithRemainderReportingOverflow(dividingBy other: UInt) -> PVO { + defer { Swift.assert(self.isNormal) } + //=--------------------------------------= + if other.isZero { + return NBK.bitCast(PVO(self.storage.first!, true)) + } + //=--------------------------------------= + var remainder = UInt.zero + + for index in self.storage.indices.reversed() { + (self.storage[index], remainder) = other.dividingFullWidth(HL(remainder, self.storage[index])) + } + + self.normalize() + return PVO(remainder, false) + } +} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift new file mode 100644 index 00000000..ec1e325f --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift @@ -0,0 +1,130 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x Division x Unsigned +//*============================================================================* + +extension NBKFlexibleWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public mutating func divideReportingOverflow(by other: Self) -> Bool { + let pvo: PVO = self.dividedReportingOverflow(by: other) + self = pvo.partialValue + return pvo.overflow as Bool + } + + @inlinable public func dividedReportingOverflow(by other: Self) -> PVO { + let qro: PVO> = self.quotientAndRemainderReportingOverflow(dividingBy: other) + return PVO(qro.partialValue.quotient, qro.overflow) + } + + @inlinable public mutating func formRemainderReportingOverflow(dividingBy other: Self) -> Bool { + let pvo: PVO = self.remainderReportingOverflow(dividingBy: other) + self = pvo.partialValue + return pvo.overflow as Bool + } + + @inlinable public func remainderReportingOverflow(dividingBy other: Self) -> PVO { + let qro: PVO> = self.quotientAndRemainderReportingOverflow(dividingBy: other) + return PVO(qro.partialValue.remainder, qro.overflow) + } + + @inlinable public func quotientAndRemainderReportingOverflow(dividingBy other: Self) -> PVO> { + self.quotientAndRemainderReportingOverflowAsNormal(dividingBy: other) + } +} + +//=----------------------------------------------------------------------------= +// MARK: + Normal +//=----------------------------------------------------------------------------= + +extension NBKFlexibleWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Transformations x Private + //=------------------------------------------------------------------------= + + @inlinable func quotientAndRemainderReportingOverflowAsNormal(dividingBy other: Self) -> PVO> { + let otherMinLastIndex = other.storage.index(before: other.storage.endIndex) + //=--------------------------------------= + // divisor is zero + //=--------------------------------------= + if other.isZero { + return PVO(QR(self, self), true) + } + //=--------------------------------------= + // divisor is one word + //=--------------------------------------= + if other.storage.count == 1 { + let divisor = other.storage.first! as UInt + let qro: PVO> = self.quotientAndRemainderReportingOverflow(dividingBy: divisor) + return PVO(QR(qro.partialValue.quotient, Self(digit: qro.partialValue.remainder)), qro.overflow) + } + //=--------------------------------------= + // divisor is greater than or equal + //=--------------------------------------= + if self <= other { + return self == other ? PVO(QR(1, Self.zero), false) : PVO(QR(Self.zero, self), false) + } + //=--------------------------------------= + let gap = self.storage.count - other.storage.count as Int + let shift = other.storage.last!.leadingZeroBitCount as Int + //=--------------------------------------= + // shift to clamp approximation + //=--------------------------------------= + var remainder = self .bitshiftedLeft(words: 000, bits: shift) as Self + var increment = other.bitshiftedLeft(words: gap, bits: shift) as Self + let discriminant = increment.storage.last! as UInt + assert(discriminant.mostSignificantBit) + //=--------------------------------------= + // division + //=--------------------------------------= + var quotient = Storage(repeating: UInt.zero, count: gap + 1) + for quotientIndex in quotient.indices.reversed() { + //=------------------------------= + // approximate quotient digit + //=------------------------------= + var digit: UInt = { + let remainderIndex = otherMinLastIndex + quotientIndex + 1 + let remainderLast0 = remainderIndex < remainder.storage.endIndex ? remainder.storage[remainderIndex] : UInt.zero + if remainderLast0 >= discriminant { return UInt.max } + let remainderLast1 = remainder.storage[remainderIndex - 1] + return discriminant.dividingFullWidth(HL(remainderLast0, remainderLast1)).quotient + }() + + var approximation = increment.multiplied(by: digit) + //=------------------------------= + // decrement if overestimated + //=------------------------------= + if approximation > remainder { + brrrrrrrrrrrrrrrrrrrrrrr: do { digit -= 1; approximation -= increment } + if approximation > remainder { digit -= 1; approximation -= increment } + } + + assert(approximation <= remainder) + //=------------------------------= + remainder -= approximation + quotient[quotientIndex] = digit + //=------------------------------= + guard !quotientIndex.isZero else { break } + increment.bitshiftRight(words: 1) + } + //=--------------------------------------= + // undo shift before division + //=--------------------------------------= + remainder.bitshiftRight(words: Int.zero, bits: shift) + return PVO(QR(Self(words: quotient), remainder), false) + } +} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift new file mode 100644 index 00000000..2d7dfb2c --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift @@ -0,0 +1,87 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x Logic x Unsigned +//*============================================================================* + +extension NBKFlexibleWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public static prefix func ~(x: Self) -> Self { + Self(words: x.storage.map(~)) + } + + @inlinable public static func &=(lhs: inout Self, rhs: Self) { + defer { Swift.assert(lhs.isNormal) } + //=--------------------------------------= + if lhs.storage.endIndex > rhs.storage.endIndex { + lhs.storage.removeSubrange(rhs.storage.endIndex...) + } + //=--------------------------------------= + for index in lhs.storage.indices.reversed() { + let word = lhs.storage[index] & rhs.storage[index] + + if index == lhs.storage.endIndex, word.isZero, index != lhs.storage.startIndex { + lhs.storage.removeLast() + } else { + lhs.storage[index] = word + } + } + } + + @inlinable public static func &(lhs: Self, rhs: Self) -> Self { + var lhs = lhs; lhs &= rhs; return lhs + } + + @inlinable public static func |=(lhs: inout Self, rhs: Self) { + defer { Swift.assert(lhs.isNormal) } + //=--------------------------------------= + lhs.storage.reserveCapacity(rhs.storage.count) + //=--------------------------------------= + for index in rhs.storage.indices { + let source = rhs.storage[index] + + if index < lhs.storage.endIndex { + lhs.storage[index] |= source + } else { + lhs.storage.append(source as UInt) + } + } + } + + @inlinable public static func |(lhs: Self, rhs: Self) -> Self { + var lhs = lhs; lhs |= rhs; return lhs + } + + @inlinable public static func ^=(lhs: inout Self, rhs: Self) { + defer { lhs.normalize() } + //=--------------------------------------= + lhs.storage.reserveCapacity(rhs.storage.count) + //=--------------------------------------= + for index in rhs.storage.indices { + let source = rhs.storage[index] + + if index < lhs.storage.endIndex { + lhs.storage[index] ^= source + } else { + lhs.storage.append(source as UInt) + } + } + } + + @inlinable public static func ^(lhs: Self, rhs: Self) -> Self { + var lhs = lhs; lhs ^= rhs; return lhs + } +} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift new file mode 100644 index 00000000..7438cc97 --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift @@ -0,0 +1,59 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x Multiplication x Digit x Unsigned +//*============================================================================* + +extension NBKFlexibleWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @_disfavoredOverload @inlinable public static func *=(lhs: inout Self, rhs: UInt) { + lhs.multiply(by: rhs) + } + + @_disfavoredOverload @inlinable public static func *(lhs: Self, rhs: UInt) -> Self { + var lhs = lhs; lhs *= rhs; return lhs + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Private + //=------------------------------------------------------------------------= + + @_disfavoredOverload @inlinable mutating func multiply(by other: UInt) { + defer { Swift.assert(self.isNormal) } + //=--------------------------------------= + if other.isZero { + return self = Self.zero + } + //=--------------------------------------= + self.storage.reserveCapacity(self.storage.count + 1) + //=--------------------------------------= + var carry = UInt.zero + + for index in self.storage.indices { + var subproduct = self.storage[index].multipliedFullWidth(by: other) + subproduct.high &+= UInt(bit: subproduct.low.addReportingOverflow(carry)) + (carry, self.storage[index]) = subproduct as HL + } + + if !carry.isZero { + self.storage.append(carry) + } + } + + @_disfavoredOverload @inlinable func multiplied(by other: UInt) -> Self { + var result = self; result.multiply(by: other); return result as Self + } +} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift new file mode 100644 index 00000000..3fab63ca --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift @@ -0,0 +1,60 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x Multiplication x Unsigned +//*============================================================================* + +extension NBKFlexibleWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public static func *=(lhs: inout Self, rhs: Self) { + lhs.multiply(by: rhs) + } + + @inlinable public static func *(lhs: Self, rhs: Self) -> Self { + lhs.multiplied(by: rhs) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Private + //=------------------------------------------------------------------------= + + @inlinable mutating func multiply(by other: Self) { + self = self.multiplied(by: other) + } + + @inlinable func multiplied(by other: Self) -> Self { + //=--------------------------------------= + let capacity: Int = self.storage.count + other.storage.count + var product = Self(unchecked: Storage(repeating: UInt(), count: capacity)) + //=--------------------------------------= + for lhsIndex in self.storage.indices { + var carry = UInt.zero + + for rhsIndex in other.storage.indices { + var subproduct = self.storage[lhsIndex].multipliedFullWidth(by: other.storage[rhsIndex]) + + carry = UInt(bit: subproduct.low.addReportingOverflow(carry)) + carry &+= UInt(bit: product.storage[lhsIndex + rhsIndex].addReportingOverflow(subproduct.low)) + carry &+= subproduct.high + } + + product.storage[lhsIndex + other.storage.endIndex] = carry + } + //=--------------------------------------= + product.normalize() + return product as Self + } +} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift new file mode 100644 index 00000000..7ee377af --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift @@ -0,0 +1,125 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x Numbers x Unsigned +//*============================================================================* + +extension NBKFlexibleWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Accessors + //=------------------------------------------------------------------------= + + public static let zero = Self(0) + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + @inlinable public init(digit: Digit) { + self.init(unchecked: [digit]) + } + + //=------------------------------------------------------------------------= + // MARK: Initializers x Literal + //=------------------------------------------------------------------------= + + @inlinable public init(integerLiteral source: StaticBigInt) { + guard let value = Self(exactlyIntegerLiteral: source) else { + preconditionFailure("\(Self.description) cannot represent \(source)") + } + + self = value + } + + @inlinable init?(exactlyIntegerLiteral source: StaticBigInt) { + guard source.signum() >= 0 else { return nil } + //=--------------------------------------= + let bitWidth = source.bitWidth - 1 + let quotient = bitWidth &>> UInt.bitWidth.trailingZeroBitCount + let remainder = bitWidth & (UInt.bitWidth - 1) + let count = Swift.max(1, quotient + Int(bit: !remainder.isZero)) + //=--------------------------------------= + self = Self.uninitialized(count: count) { storage in + for index in storage.indices { + storage[index] = source[index] + } + } + } + + //=------------------------------------------------------------------------= + // MARK: Initializers x Binary Integer + //=------------------------------------------------------------------------= + + @inlinable public init(_ source: T) where T: BinaryInteger { + guard let result = Self(exactly: source) else { + preconditionFailure("\(Self.description) cannot represent \(source)") + } + + self = result + } + + @inlinable public init?(exactly source: some BinaryInteger) { + guard source.signum() >= 0 else { return nil } + self.init(words: source.words) + } + + @inlinable public init(clamping source: some BinaryInteger) { + self = Self(exactly: source) ?? (0 as Self) + } + + @inlinable public init(truncatingIfNeeded source: some BinaryInteger) { + self.init(words: source.words) + } + + //=------------------------------------------------------------------------= + // MARK: Initializers x Binary Floating Point + //=------------------------------------------------------------------------= + + @inlinable public init(_ source: some BinaryFloatingPoint) { + self.init(exactly: source.rounded(.towardZero))! + } + + @inlinable public init?(exactly source: some BinaryFloatingPoint) { + if source.sign == .minus { return nil } + //=--------------------------------------= + // + //=--------------------------------------= + if source.isZero { self.init(); return } + guard source.isFinite else { return nil } + let value = source.rounded(.towardZero) + guard value == source else { return nil } + //=--------------------------------------= + // + //=--------------------------------------= + let exponent = Int(source.exponent) + let ratio = exponent.quotientAndRemainder(dividingBy: UInt.bitWidth) + //=--------------------------------------= + // + //=--------------------------------------= + self.init(exactly: source.significandBitPattern) + self >>= type(of: source).significandBitCount - exponent + self.add(UInt(1) << ratio.remainder, at: ratio.quotient) + } + + //=------------------------------------------------------------------------= + // MARK: Initializers x Sign & Magnitude + //=------------------------------------------------------------------------= + + @inlinable public static func exactly(sign: FloatingPointSign, magnitude: Self) -> Self? { + if sign == FloatingPointSign.plus || magnitude.isZero { return magnitude } else { return nil } + } + + @inlinable public static func clamping(sign: FloatingPointSign, magnitude: Self) -> Self { + if sign == FloatingPointSign.plus { return magnitude } else { return Self.zero } + } +} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift new file mode 100644 index 00000000..84a03658 --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift @@ -0,0 +1,200 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x Shifts x Unsigned +//*============================================================================* +//=----------------------------------------------------------------------------= +// MARK: + Left +//=----------------------------------------------------------------------------= + +extension NBKFlexibleWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public static func <<=(lhs: inout Self, rhs: some BinaryInteger) { + lhs.bitshiftLeftSmart(by: Int(clamping: rhs)) + } + + @inlinable public static func <<(lhs: Self, rhs: some BinaryInteger) -> Self { + var lhs = lhs; lhs <<= rhs; return lhs + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Int + //=------------------------------------------------------------------------= + + @inlinable public mutating func bitshiftLeftSmart(by distance: Int) { + switch distance >= 0 { + case true: self.bitshiftLeft (by: distance) + case false: self.bitshiftRight(by: distance.negated()) } + } + + @inlinable public func bitshiftedLeftSmart(by distance: Int) -> Self { + var result = self; result.bitshiftLeftSmart(by: distance); return result + } + + @inlinable public mutating func bitshiftLeft(by distance: Int) { + precondition(distance >= 0, NBK.callsiteOutOfBoundsInfo()) + let major = distance .quotientDividingByBitWidthAssumingIsAtLeastZero() + let minor = distance.remainderDividingByBitWidthAssumingIsAtLeastZero() + return self.bitshiftLeft(words: major, bits: minor) + } + + @inlinable public func bitshiftedLeft(by distance: Int) -> Self { + var result = self; result.bitshiftLeft(by: distance); return result + } + + @inlinable public mutating func bitshiftLeft(words: Int, bits: Int) { + precondition(words >= 0, NBK.callsiteOutOfBoundsInfo()) + precondition(bits >= 0 && bits < UInt.bitWidth, NBK.callsiteOutOfBoundsInfo()) + //=--------------------------------------= + if bits.isZero { + return self.bitshiftLeft(words: words) + } + //=--------------------------------------= + if self.isZero { return } + //=--------------------------------------= + let push = UInt(bitPattern: bits) + let pull = UInt(bitPattern: UInt.bitWidth - bits) + //=--------------------------------------= + self.resize(minCount: self.storage.endIndex + words + 1) + //=--------------------------------------= + let offset: Int = ~(words) + var destination = self.storage.endIndex as Int + var word = self.storage[destination &+ offset] + //=--------------------------------------= + while destination > self.storage.startIndex { + self.storage.formIndex(before: &destination) + let pushed = word &<< push + word = destination > words ? self.storage[destination &+ offset] : UInt() + let pulled = word &>> pull + self.storage[destination ] = pushed | pulled + } + //=--------------------------------------= + self.normalize() + } + + @inlinable public func bitshiftedLeft(words: Int, bits: Int) -> Self { + var result = self; result.bitshiftLeft(words: words, bits: bits); return result + } + + @inlinable public mutating func bitshiftLeft(words: Int) { + precondition(words >= 0, NBK.callsiteOutOfBoundsInfo()) + //=--------------------------------------= + if words.isZero { return } + //=--------------------------------------= + if self .isZero { return } + //=--------------------------------------= + let prefix = repeatElement(UInt.zero, count: words) + self.storage.insert(contentsOf: prefix, at: Int()) + } + + @inlinable public func bitshiftedLeft(words: Int) -> Self { + var result = self; result.bitshiftLeft(words: words); return result + } +} + +//=----------------------------------------------------------------------------= +// MARK: + Right +//=----------------------------------------------------------------------------= + +extension NBKFlexibleWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public static func >>=(lhs: inout Self, rhs: some BinaryInteger) { + lhs.bitshiftRightSmart(by: Int(clamping: rhs)) + } + + @inlinable public static func >>(lhs: Self, rhs: some BinaryInteger) -> Self { + var lhs = lhs; lhs >>= rhs; return lhs + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Int + //=------------------------------------------------------------------------= + + @inlinable public mutating func bitshiftRightSmart(by distance: Int) { + switch distance >= 0 { + case true: self.bitshiftRight(by: distance) + case false: self.bitshiftLeft (by: distance.negated()) } + } + + @inlinable public func bitshiftedRightSmart(by distance: Int) -> Self { + var result = self; result.bitshiftRightSmart(by: distance); return result + } + + @inlinable public mutating func bitshiftRight(by distance: Int) { + precondition(distance >= 0, NBK.callsiteOutOfBoundsInfo()) + let major = distance .quotientDividingByBitWidthAssumingIsAtLeastZero() + let minor = distance.remainderDividingByBitWidthAssumingIsAtLeastZero() + return self.bitshiftRight(words: major, bits: minor) + } + + @inlinable public func bitshiftedRight(by distance: Int) -> Self { + var result = self; result.bitshiftRight(by: distance); return result + } + + @inlinable public mutating func bitshiftRight(words: Int, bits: Int) { + precondition(words >= 0, NBK.callsiteOutOfBoundsInfo()) + precondition(bits >= 0 && bits < UInt.bitWidth, NBK.callsiteOutOfBoundsInfo()) + //=--------------------------------------= + if words >= self.storage.count { + return self = Self.zero + } + //=--------------------------------------= + if bits.isZero { + return self.bitshiftRight(words: words) + } + //=--------------------------------------= + let push = UInt(bitPattern: bits) + let pull = UInt(bitPattern: UInt.bitWidth - bits) + let sign = UInt(repeating: self.isLessThanZero) + //=--------------------------------------= + var destination = self.storage.startIndex + let edge = self.storage.distance(from: words, to: self.storage.endIndex) + var word = self.storage[words] as UInt + //=--------------------------------------= + while destination < edge { + let after = self.storage.index(after: destination) + let pushed = word &>> push + word = after < edge ? self.storage[after &+ words] : sign + let pulled = word &<< pull + self.storage[destination ] = pushed | pulled + destination = after + } + //=--------------------------------------= + self.storage.removeLast(words) + self.normalize() + } + + @inlinable public func bitshiftedRight(words: Int, bits: Int) -> Self { + var result = self; result.bitshiftRight(words: words, bits: bits); return result + } + + @inlinable public mutating func bitshiftRight(words: Int) { + precondition(words >= 0, NBK.callsiteOutOfBoundsInfo()) + //=--------------------------------------= + if words.isZero { return } + //=--------------------------------------= + self.storage.removeFirst(Swift.min(words, self.storage.count)) + self.normalize() + } + + @inlinable public func bitshiftedRight(words: Int) -> Self { + var result = self; result.bitshiftRight(words: words); return result + } +} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Storage.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Storage.swift new file mode 100644 index 00000000..3bbcc885 --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Storage.swift @@ -0,0 +1,91 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x Storage x Unsigned +//*============================================================================* + +extension NBKFlexibleWidth.Magnitude { + + @usableFromInline typealias Storage = Array + + //=------------------------------------------------------------------------= + // MARK: Accessors x Private + //=------------------------------------------------------------------------= + + /// Returns whether the underlying storage is normalized. + /// + /// The storage is normalized under each of the following conditions: + /// + /// - `count == 1` + /// - `count >= 2 && last != 0` + /// + @inlinable var isNormal: Bool { + switch self.storage.count > 1 { + case true: return !self.storage.last!.isZero + case false: return !self.storage.isEmpty } + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Private + //=------------------------------------------------------------------------= + + /// Normalizes the underlying storage. + /// + /// The storage is normalized under each of the following conditions: + /// + /// - `count == 1` + /// - `count >= 2 && last != 0` + /// + @inlinable mutating func normalize() { + var index = self.storage.endIndex as Int + if index > self.storage.startIndex { + self.storage.formIndex(before: &index) + while index > self.storage.startIndex, + self.storage[index].isZero { + self.storage.formIndex(before: &index) + self.storage.removeLast() + } + } else { + self.storage.append(UInt.zero) + } + } + + /// Resizes the underlying storage, if needed. + /// + /// The storage is normalized under each of the following conditions: + /// + /// - `count == 1` + /// - `count >= 2 && last != 0` + /// + /// - Note: Calling this method denormalizes `self`. + /// + @inlinable mutating func resize(minCount: Int) { + self.storage.reserveCapacity(minCount) + appending: while self.storage.count < minCount { + self.storage.append(UInt.zero) + } + } + + /// Resizes the underlying storage, if needed. + /// + /// The storage is normalized under each of the following conditions: + /// + /// - `count == 1` + /// - `count >= 2 && last != 0` + /// + /// + /// - Note: Calling this method denormalizes `self`. + /// + @inlinable mutating func resize(minLastIndex: Int) { + self.resize(minCount: minLastIndex + 1) + } +} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift new file mode 100644 index 00000000..f925c138 --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift @@ -0,0 +1,72 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x Subtraction x Digit x Unsigned +//*============================================================================* + +extension NBKFlexibleWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @_disfavoredOverload @inlinable public static func -=(lhs: inout Self, rhs: UInt) { + let overflow: Bool = lhs.subtractReportingOverflow(rhs, at: Int.zero) + precondition(!overflow, NBK.callsiteOverflowInfo()) + } + + @_disfavoredOverload @inlinable public static func -(lhs: Self, rhs: UInt) -> Self { + let pvo: PVO = lhs.subtractingReportingOverflow(rhs, at: Int.zero) + precondition(!pvo.overflow, NBK.callsiteOverflowInfo()) + return pvo.partialValue as Self + } + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @_disfavoredOverload @inlinable public mutating func subtractReportingOverflow(_ other: UInt, at index: Int) -> Bool { + defer { Swift.assert(self.isNormal) } + //=--------------------------------------= + if other.isZero { return false } + //=--------------------------------------= + self.resize(minLastIndex: index) + + var index = index as Int + let borrow = self.storage[index].subtractReportingOverflow(other) + self.storage.formIndex(after: &index) + + return self.subtractUpToEndIndex(borrow, from: &index) + } + + @_disfavoredOverload @inlinable public func subtractingReportingOverflow(_ other: UInt, at index: Int) -> PVO { + var partialValue = self + let overflow: Bool = partialValue.subtractReportingOverflow(other, at: index) + return PVO(partialValue, overflow) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Private + //=------------------------------------------------------------------------= + + @inlinable mutating func subtractUpToEndIndex(_ borrow: Bool, from index: inout Int) -> Bool { + var borrow = borrow + + forwards: while borrow, index < self.storage.endIndex { + borrow = self.storage[index].subtractReportingOverflow(1 as UInt) + self.storage.formIndex(after: &index) + } + + self.normalize() + return borrow as Bool + } +} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift new file mode 100644 index 00000000..b16ec027 --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift @@ -0,0 +1,61 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x Subtraction x Unsigned +//*============================================================================* + +extension NBKFlexibleWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public static func -=(lhs: inout Self, rhs: Self) { + let overflow: Bool = lhs.subtractReportingOverflow(rhs, at: Int.zero) + precondition(!overflow, NBK.callsiteOverflowInfo()) + } + + @inlinable public static func -(lhs: Self, rhs: Self) -> Self { + let pvo: PVO = lhs.subtractingReportingOverflow(rhs, at: Int.zero) + precondition(!pvo.overflow, NBK.callsiteOverflowInfo()) + return pvo.partialValue as Self + } + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public mutating func subtractReportingOverflow(_ other: Self, at index: Int) -> Bool { + defer { Swift.assert(self.isNormal) } + //=--------------------------------------= + if other.isZero { return false } + //=--------------------------------------= + self.resize(minCount: other.storage.count + index) + + var index = index + var borrow = false + + for var subtrahend in other.storage { + borrow = subtrahend.addReportingOverflow(UInt(bit: borrow)) + borrow = self.storage[index].subtractReportingOverflow(subtrahend) || borrow + self.storage.formIndex(after: &index) + } + + return self.subtractUpToEndIndex(borrow, from: &index) + } + + @inlinable public func subtractingReportingOverflow(_ other: Self, at index: Int) -> PVO { + var partialValue = self + let overflow: Bool = partialValue.subtractReportingOverflow(other, at: index) + return PVO(partialValue, overflow) + } +} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text+Radix.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text+Radix.swift new file mode 100644 index 00000000..dd554ef7 --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text+Radix.swift @@ -0,0 +1,158 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x Text x Radix +//*============================================================================* + +extension NBKFlexibleWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Details x Decode + //=------------------------------------------------------------------------= + + @inlinable public init?(_ description: some StringProtocol, radix: Int = 10) { + var description = String(description) + + let value: Optional = description.withUTF8 { utf8 in + let (radix) = AnyRadixUIntRoot(radix) + let (sign,body) = NBK.integerComponents(utf8: utf8) + let (digits) = NBK.UnsafeUTF8(rebasing: body) + let (magnitude) = Magnitude(digits: digits, radix: radix) + return magnitude.flatMap({ Self.exactly(sign: sign, magnitude: $0) }) + } + + if let value { self = value } else { return nil } + } + + //=------------------------------------------------------------------------= + // MARK: Details x Encode + //=------------------------------------------------------------------------= + + @inlinable public func description(radix: Int = 10, uppercase: Bool = false) -> String { + Swift.withUnsafePointer(to: UInt8(ascii: "-")) { minus in + let radix = AnyRadixUIntRoot(radix) + let alphabet = MaxRadixAlphabetEncoder(uppercase: uppercase) + let prefix = NBK.UnsafeUTF8(start: minus, count: Int(bit: self.isLessThanZero)) + let suffix = NBK.UnsafeUTF8(start: nil, count: Int.zero) + return self.magnitude.description(radix: radix, alphabet: alphabet, prefix: prefix, suffix: suffix) + } + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Text x Radix x Unsigned +//*============================================================================* + +extension NBKFlexibleWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Details x Decode x Private + //=------------------------------------------------------------------------= + + @inlinable init?(digits: NBK.UnsafeUTF8, radix: AnyRadixUIntRoot) { + switch radix.power.isZero { + case true: self.init(digits: digits, radix: PerfectRadixUIntRoot(unchecked: radix)) + case false: self.init(digits: digits, radix: ImperfectRadixUIntRoot(unchecked: radix)) } + } + + @inlinable init?(digits: NBK.UnsafeUTF8, radix: PerfectRadixUIntRoot) { + guard !digits.isEmpty else { return nil } + //=--------------------------------------= + var digits = digits.drop(while:{ $0 == 48 }) + let division = digits.count.quotientAndRemainder(dividingBy: radix.exponent) + let count = division.quotient + Int(bit: !division.remainder.isZero) + //=--------------------------------------= + guard !digits.isEmpty else { self = Self.zero; return } + //=--------------------------------------= + var error = false + let value = Self.uninitialized(count: count) { storage in + for index in storage.indices { + let chunk = NBK.UnsafeUTF8(rebasing: NBK.removeSuffix(from: &digits, maxLength: radix.exponent)) + guard let word = UInt.truncating(digits: chunk, radix: radix.base) else { return error = true } + storage[index] = word + } + + Swift.assert(digits.isEmpty) + } + + if !error { self = value } else { return nil } + } + + @inlinable init?(digits: NBK.UnsafeUTF8, radix: ImperfectRadixUIntRoot) { + guard !digits.isEmpty else { return nil } + //=--------------------------------------= + var digits = digits.drop(while:{ $0 == 48 }) + let alignment = digits.count % radix.exponent + //=--------------------------------------= + self.init() + guard let _ = { // this closure makes it 10% faster for some reason + + forwards: if !alignment.isZero { + let chunk = NBK.UnsafeUTF8(rebasing: NBK.removePrefix(from: &digits, count: alignment)) + guard let word = UInt.truncating(digits: chunk, radix: radix.base) else { return nil } + self.storage[self.storage.startIndex] = word + } + + forwards: while !digits.isEmpty { + let chunk = NBK.UnsafeUTF8(rebasing: NBK.removePrefix(from: &digits, count: radix.exponent)) + guard let word = UInt.truncating(digits: chunk, radix: radix.base) else { return nil } + self *= radix.power; self += word // TODO: combined * and + method + } + + }() as Void? else { return nil } + } + + //=------------------------------------------------------------------------= + // MARK: Details x Encode x Private + //=------------------------------------------------------------------------= + + @inlinable func description(radix: AnyRadixUIntRoot, alphabet: MaxRadixAlphabetEncoder, prefix: NBK.UnsafeUTF8, suffix: NBK.UnsafeUTF8) -> String { + switch radix.power.isZero { + case true: return self.description(radix: PerfectRadixUIntRoot(unchecked: radix), alphabet: alphabet, prefix: prefix, suffix: suffix) + case false: return self.description(radix: ImperfectRadixUIntRoot(unchecked: radix), alphabet: alphabet, prefix: prefix, suffix: suffix) } + } + + @inlinable func description(radix: PerfectRadixUIntRoot, alphabet: MaxRadixAlphabetEncoder, prefix: NBK.UnsafeUTF8, suffix: NBK.UnsafeUTF8) -> String { + //=--------------------------------------= + // with one buffer pointer specialization + //=--------------------------------------= + self.storage.withContiguousStorageIfAvailable { buffer in + let index = buffer.lastIndex(where:{ !$0.isZero }) ?? buffer.startIndex + let chunks = NBK.UnsafeWords(rebasing: buffer[...index]) + return String.fromUTF8Unchecked(chunks: chunks, radix: radix, alphabet: alphabet, prefix: prefix, suffix: suffix) + }! + } + + @inlinable func description(radix: ImperfectRadixUIntRoot, alphabet: MaxRadixAlphabetEncoder, prefix: NBK.UnsafeUTF8, suffix: NBK.UnsafeUTF8) -> String { + //=--------------------------------------= + // with one buffer pointer specialization + //=--------------------------------------= + let capacity: Int = radix.divisibilityByPowerUpperBound(self) + return Swift.withUnsafeTemporaryAllocation(of: UInt.self, capacity: capacity) { buffer in + //=----------------------------------= + // de/init: pointee is trivial + //=----------------------------------= + var magnitude: Magnitude = self + var index: Int = buffer.startIndex + //=----------------------------------= + rebasing: repeat { + let (remainder, overflow) = magnitude.formQuotientWithRemainderReportingOverflow(dividingBy: radix.power) + buffer[index] = remainder + buffer.formIndex(after: &index) + assert(!overflow) + } while !magnitude.isZero + //=----------------------------------= + let chunks = NBK.UnsafeWords(rebasing: buffer[.. Void) -> Self { + let storage = Array(unsafeUninitializedCapacity: count) { + storage, endIndex in + body(NBK.UnsafeMutableWords(rebasing: storage.prefix(upTo: count))) + endIndex = count as Int + } + + return Self(unchecked: storage) + } +} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift new file mode 100644 index 00000000..6e9a39f2 --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift @@ -0,0 +1,34 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x Words x Unsigned +//*============================================================================* + +extension NBKFlexibleWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + @inlinable public init(words: some RandomAccessCollection) { + self.init(unchecked: Array(words)) + self.normalize() + } + + //=------------------------------------------------------------------------= + // MARK: Accessors + //=------------------------------------------------------------------------= + + @inlinable public var words: Array { + _read { yield self.storage } + } +} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift new file mode 100644 index 00000000..7799aa11 --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift @@ -0,0 +1,59 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Flexible Width +//*============================================================================* + +@frozen public struct NBKFlexibleWidth: Hashable { + + public typealias Digit = Int + + //=------------------------------------------------------------------------= + // MARK: State + //=------------------------------------------------------------------------= + + @usableFromInline var _signum: Int + @usableFromInline var _magnitude: Magnitude + + //*========================================================================* + // MARK: * Magnitude + //*========================================================================* + + @frozen public struct Magnitude: NBKUnsignedInteger { + + public typealias Digit = UInt + + //=--------------------------------------------------------------------= + // MARK: State + //=--------------------------------------------------------------------= + + @usableFromInline var storage: Storage + + //=--------------------------------------------------------------------= + // MARK: Initializers + //=--------------------------------------------------------------------= + + @inlinable init(unchecked: Storage) { + self.storage = unchecked + } + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Aliases +//*============================================================================* + +/// A signed, flexible-width, integer. +public typealias IntXL = NBKFlexibleWidth + +/// An unsigned, flexible-width, integer. +public typealias UIntXL = NBKFlexibleWidth.Magnitude diff --git a/Sources/NBKFlexibleWidthKit/Private/Arithmagick.swift b/Sources/NBKFlexibleWidthKit/Private/Arithmagick.swift new file mode 100644 index 00000000..fbcdd547 --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/Private/Arithmagick.swift @@ -0,0 +1,60 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Arithmagick x Int +//*============================================================================* + +extension Int { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + /// Returns the `quotient` of dividing this value by its bit width. + /// + /// - Parameter self: `0 <= self <= Self.max` + /// + @inlinable func quotientDividingByBitWidthAssumingIsAtLeastZero() -> Self { + assert(self >= 0, "this value must be at least zero") + return Self(bitPattern: Magnitude(bitPattern: self).quotientDividingByBitWidth()) + } + + /// Returns the `remainder` of dividing this value by its bit width. + /// + /// - Parameter self: `0 <= self <= Self.max` + /// + @inlinable func remainderDividingByBitWidthAssumingIsAtLeastZero() -> Self { + assert(self >= 0, "this value must be at least zero") + return Self(bitPattern: Magnitude(bitPattern: self).remainderDividingByBitWidth()) + } +} + +//*============================================================================* +// MARK: * NBK x Arithmagick x UInt +//*============================================================================* + +extension UInt { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + /// Returns the `quotient` of dividing this value by its bit width. + @inlinable func quotientDividingByBitWidth() -> Self { + self &>> Self(bitPattern: Self.bitWidth.trailingZeroBitCount) + } + + /// Returns the `remainder` of dividing this value by its bit width. + @inlinable func remainderDividingByBitWidth() -> Self { + self & Self(bitPattern: Self.bitWidth &- 1) + } +} diff --git a/Sources/NBKFlexibleWidthKit/Private/RadixAlphabet.swift b/Sources/NBKFlexibleWidthKit/Private/RadixAlphabet.swift new file mode 100644 index 00000000..cda2d496 --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/Private/RadixAlphabet.swift @@ -0,0 +1,88 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +//*============================================================================* +// MARK: * NBK x Radix Alphabet x Decoder x Any +//*============================================================================* + +/// Decodes values in `0` to `36` from ASCII. +@frozen @usableFromInline struct AnyRadixAlphabetDecoder { + + //=------------------------------------------------------------------------= + // MARK: State + //=------------------------------------------------------------------------= + + @usableFromInline let x00x10: UInt8 + @usableFromInline let x10x36: UInt8 + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + @inlinable init(radix: Int) { + precondition(2 ... 36 ~= radix, "radix must be in 2 through 36") + let count = UInt8(truncatingIfNeeded: radix) + let carry = count.subtractingReportingOverflow(10) + if carry.overflow { + self.x00x10 = count + self.x10x36 = 00000 + } else { + self.x00x10 = 00010 + self.x10x36 = carry.partialValue + } + } + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + @inlinable func decode(_ ascii: UInt8) -> UInt8? { + var index: UInt8 + + index = ascii &- UInt8(ascii: "0"); if index < self.x00x10 { return index } + index = ascii &- UInt8(ascii: "A"); if index < self.x10x36 { return index &+ 10 } + index = ascii &- UInt8(ascii: "a"); if index < self.x10x36 { return index &+ 10 } + + return nil + } +} + +//*============================================================================* +// MARK: * NBK x Radix Alphabet x Encoder x Max +//*============================================================================* + +/// Encodes values in `0` to `36` to ASCII. +@frozen @usableFromInline struct MaxRadixAlphabetEncoder { + + //=------------------------------------------------------------------------= + // MARK: State + //=------------------------------------------------------------------------= + + @usableFromInline let x00x10: UInt8 + @usableFromInline let x10x36: UInt8 + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + @inlinable init(uppercase: Bool) { + self.x00x10 = UInt8(ascii: "0") + self.x10x36 = UInt8(ascii: uppercase ? "A" : "a") &- 10 + } + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + @inlinable func encode(_ value: UInt8) -> UInt8? { + if value < 10 { return value &+ self.x00x10 } + if value < 36 { return value &+ self.x10x36 } + return nil + } +} diff --git a/Sources/NBKFlexibleWidthKit/Private/RadixUIntRoot.swift b/Sources/NBKFlexibleWidthKit/Private/RadixUIntRoot.swift new file mode 100644 index 00000000..1cde03c7 --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/Private/RadixUIntRoot.swift @@ -0,0 +1,274 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Radix UInt Root +//*============================================================================* + +/// The largest exponent in `pow(radix, exponent) <= UInt.max + 1`. +/// +/// - Its `base` is `>= 2` and `<= 36` +/// - Its `exponent` is `>= 1` and `<= UInt.bitWidth` +/// - A power of `UInt.max + 1` is represented by `0` +/// +@usableFromInline protocol RadixUIntRoot { + + //=------------------------------------------------------------------------= + // MARK: State + //=------------------------------------------------------------------------= + + @inlinable var base: UInt { get } + + @inlinable var exponent: UInt { get } + + @inlinable var power: UInt { get } + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + /// Divides `dividend` by the `base` of this solution. + @inlinable func dividing(_ dividend: UInt) -> QR +} + +//=----------------------------------------------------------------------------= +// MARK: + Details +//=----------------------------------------------------------------------------= + +extension RadixUIntRoot { + + //=------------------------------------------------------------------------= + // MARK: Accessors + //=------------------------------------------------------------------------= + + @_transparent @usableFromInline var base: Int { + assert((self.base as UInt) <= 36) + return Int(bitPattern: self.base) + } + + @_transparent @usableFromInline var exponent: Int { + assert((self.exponent as UInt) <= UInt.bitWidth) + return Int(bitPattern: self.exponent) + } + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + @inlinable func dividing(_ dividend: UInt) -> QR { + dividend.quotientAndRemainder(dividingBy: self.base) + } +} + +//*============================================================================* +// MARK: * NBK x Radix UInt Root x Perfect +//*============================================================================* + +/// A ``RadixUIntRoot`` with a power that is zero. +@frozen @usableFromInline struct PerfectRadixUIntRoot: RadixUIntRoot { + + //=------------------------------------------------------------------------= + // MARK: State + //=------------------------------------------------------------------------= + + @usableFromInline let root: AnyRadixUIntRoot + @usableFromInline let special: QR + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + @inlinable init(unchecked: AnyRadixUIntRoot) { + assert(unchecked.power.isZero) + assert([2, 4, 16].contains(unchecked.base)) + self.root = unchecked + self.special.quotient = UInt(bitPattern: self.root.base.trailingZeroBitCount) + self.special.remainder = self.root.base &- 1 + } + + //=------------------------------------------------------------------------= + // MARK: Accessors + //=------------------------------------------------------------------------= + + @_transparent @usableFromInline var base: UInt { + self.root.base + } + + @_transparent @usableFromInline var exponent: UInt { + self.root.exponent + } + + @_transparent @usableFromInline var power: UInt { + self.root.power + } + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + @inlinable func dividing(_ dividend: UInt) -> QR { + QR(dividend &>> self.special.quotient, dividend & self.special.remainder) + } +} + +//*============================================================================* +// MARK: * NBK x Radix UInt Root x Imperfect +//*============================================================================* + +/// A ``RadixUIntRoot`` with a power that is non-zero. +@frozen @usableFromInline struct ImperfectRadixUIntRoot: RadixUIntRoot { + + //=------------------------------------------------------------------------= + // MARK: State + //=------------------------------------------------------------------------= + + @usableFromInline let root: AnyRadixUIntRoot + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + @inlinable init(unchecked: AnyRadixUIntRoot) { + assert(!unchecked.power.isZero) + assert(![2, 4, 16].contains(unchecked.base)) + self.root = unchecked + } + + //=------------------------------------------------------------------------= + // MARK: Accessors + //=------------------------------------------------------------------------= + + @_transparent @usableFromInline var base: UInt { + self.root.base + } + + @_transparent @usableFromInline var exponent: UInt { + self.root.exponent + } + + @_transparent @usableFromInline var power: UInt { + self.root.power + } + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + /// Overestimates how many times its power divides the magnitude. + @inlinable func divisibilityByPowerUpperBound(_ magnitude: some UnsignedInteger) -> Int { + magnitude.bitWidth / 36.leadingZeroBitCount &+ 1 + } +} + +//*============================================================================* +// MARK: * NBK x Radix UInt Root x Any +//*============================================================================* + +/// A ``RadixUIntRoot`` with a power that may be zero. +@frozen @usableFromInline struct AnyRadixUIntRoot: RadixUIntRoot { + + @usableFromInline typealias Solution = (exponent: UInt, power: UInt) + + //=------------------------------------------------------------------------= + // MARK: State + //=------------------------------------------------------------------------= + + @usableFromInline let base: UInt + @usableFromInline let exponent: UInt + @usableFromInline let power: UInt + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + /// Creates a new instance from the given radix. + /// + /// The radix must not exceed `36` because that is the size of the alphabet. + /// + /// - Parameter radix: A value from `2` through `36`. + /// + @inlinable init(_ radix: Int) { + Swift.precondition(2 ... 36 ~= radix) + (self.base) = UInt(bitPattern: radix) + (self.exponent, self.power) = Self.solution(unchecked: self.base) + } + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + /// Returns the largest exponent in `pow(radix, exponent) <= UInt.max + 1`. + @inlinable static func solution(unchecked radix: UInt) -> Solution { + switch radix.isPowerOf2 { + case true: return Self.solutionAssumingRadixIsPowerOf2 (unchecked: radix) + case false: return Self.solutionAssumingRadixIsNotPowerOf2(unchecked: radix) } + } + + /// Returns the largest exponent in `pow(radix, exponent) <= UInt.max + 1`. + @inlinable static func solutionAssumingRadixIsPowerOf2(unchecked radix: UInt) -> Solution { + assert(radix >= 2) + assert(radix.isPowerOf2) + //=--------------------------------------= + let zeros = UInt(bitPattern: radix.trailingZeroBitCount) + //=--------------------------------------= + // radix: 002, 004, 016, 256, ... + //=--------------------------------------= + if zeros.isPowerOf2 { + let exponent = UInt(bitPattern: UInt.bitWidth &>> zeros.trailingZeroBitCount) + return Solution(exponent: exponent, power: 0) + //=--------------------------------------= + // radix: 008, 032, 064, 128, ... + //=--------------------------------------= + } else { + let exponent = UInt(bitPattern: UInt.bitWidth) / (zeros as UInt) + return Solution(exponent: exponent, power: 1 &<< (zeros &* exponent)) + } + } + + /// Returns the largest exponent in `pow(radix, exponent) <= UInt.max + 1`. + @inlinable static func solutionAssumingRadixIsNotPowerOf2(unchecked radix: UInt) -> Solution { + assert(radix >= 2) + assert(radix.isPowerOf2 == false) + //=--------------------------------------= + // radix: 003, 005, 006, 007, ... + //=--------------------------------------= + let capacity: Int = UInt.bitWidth.trailingZeroBitCount - 1 + return Swift.withUnsafeTemporaryAllocation(of: Solution.self, capacity: capacity) { squares in + //=----------------------------------= + // de/init: pointee is trivial + //=----------------------------------= + var solution = Solution(1, radix) + var index = squares.startIndex as Int + + loop: while index < squares.endIndex { + squares[index] = solution + let product = solution.power.multipliedReportingOverflow(by: solution.power) + if product.overflow { break loop } + + solution.exponent &<<= 1 as UInt + solution.power = product.partialValue + squares.formIndex(after: &index) + } + + loop: while index > squares.startIndex { + squares.formIndex(before: &index) + let square = squares[index] + let product = solution.power.multipliedReportingOverflow(by: square.power) + if product.overflow { continue loop } + + solution.exponent &+= square.exponent + solution.power = product.partialValue + } + + return solution as Solution + } + } +} diff --git a/Sources/NBKFlexibleWidthKit/Private/Text.swift b/Sources/NBKFlexibleWidthKit/Private/Text.swift new file mode 100644 index 00000000..997b7a90 --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/Private/Text.swift @@ -0,0 +1,134 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Text x UInt +//*============================================================================* + +extension UInt { + + //=------------------------------------------------------------------------= + // MARK: Details x Text + //=------------------------------------------------------------------------= + + /// Creates a new instance by truncating the given `digits` and `radix`. + /// + /// The sequence passed as `digits` may contain one or more numeric digits + /// (0-9) or letters (a-z or A-Z), according to the `radix`. If the sequence + /// passed as `digits` uses an invalid format, the result is nil. If the + /// sequence passed as `digits` cannot be represented, the result is truncated. + /// + /// - Note: The decoding strategy is case insensitive. + /// + /// ### Parameters + /// + /// Creating a new decoder is faster than passing one as an argument. + /// + @inlinable static func truncating(digits: NBK.UnsafeUTF8, radix: Int) -> Self? { + guard !digits.isEmpty else { return nil } + //=--------------------------------------= + let alphabet = AnyRadixAlphabetDecoder(radix: radix) + //=--------------------------------------= + var value = Self.zero + + for digit in digits { + guard let addend = alphabet.decode(digit) else { return nil } + value &*= Self(bitPattern: radix) + value &+= Self(truncatingIfNeeded: addend) + } + + return value as Self + } +} + +//*============================================================================* +// MARK: * NBK x Text x String +//*============================================================================* + +extension String { + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + /// Encodes unchecked chunks, using the given format. + /// + /// In this context, a chunk is a digit in the base of the given radix's power. + /// + @inlinable static func fromUTF8Unchecked(chunks: some RandomAccessCollection, radix: some RadixUIntRoot, + alphabet: MaxRadixAlphabetEncoder, prefix: NBK.UnsafeUTF8, suffix: NBK.UnsafeUTF8) -> String { + assert(!chunks.isEmpty, "chunks must not be empty") + assert(!chunks.last!.isZero || chunks.count == 1, "chunks must not have redundant zeros") + assert( radix.power.isZero || chunks.allSatisfy({ $0 < radix.power }), "chunks must be less than radix's power") + //=--------------------------------------= + var remainders = chunks[...] + let mostSignificantChunk = remainders.removeLast() + return String.withUTF8Unchecked(chunk: mostSignificantChunk, radix: radix, alphabet: alphabet) { first in + var count: Int + count = prefix.count + count += first .count + count += remainders.count * radix.exponent + count += suffix.count + return String(unsafeUninitializedCapacity: count) { utf8 in + //=------------------------------= + // de/init: pointee is trivial + //=------------------------------= + var index = count as Int + func pull(_ unit: UInt8) { + utf8.formIndex(before: &index) + utf8[index] = unit + } + //=------------------------------= + suffix.reversed().forEach(pull) + + for var chunk in remainders { + for _ in 0 ..< radix.exponent { + let digit: UInt + (chunk, digit) = radix.dividing(chunk) + pull(alphabet.encode(UInt8(truncatingIfNeeded: digit))!) + } + } + + first .reversed().forEach(pull) + prefix.reversed().forEach(pull) + //=------------------------------= + assert(utf8.startIndex == index) + assert(utf8[index..(chunk: UInt, radix: some RadixUIntRoot, + alphabet: MaxRadixAlphabetEncoder, body: (NBK.UnsafeUTF8) -> T) -> T { + assert(radix.power.isZero || chunk < radix.power, "chunks must be less than radix's power") + return Swift.withUnsafeTemporaryAllocation(of: UInt8.self, capacity: radix.exponent) { utf8 in + //=----------------------------------= + // de/init: pointee is trivial + //=----------------------------------= + var chunk = chunk as UInt + var index = radix.exponent as Int + //=----------------------------------= + backwards: repeat { + let digit: UInt + (chunk, digit) = radix.dividing(chunk) + utf8.formIndex(before: &index) + utf8[index] = alphabet.encode(UInt8(truncatingIfNeeded: digit))! + } while !chunk.isZero + //=----------------------------------= + return body(NBK.UnsafeUTF8(rebasing: utf8[index...])) + } + } +} diff --git a/Sources/Numberick/Documentation.docc/Documentation.md b/Sources/Numberick/Documentation.docc/Documentation.md index d1399473..0593a830 100644 --- a/Sources/Numberick/Documentation.docc/Documentation.md +++ b/Sources/Numberick/Documentation.docc/Documentation.md @@ -99,9 +99,11 @@ Int256(5) % Int(5), UInt256(5) % UInt(5) ### Models - ``NBKDoubleWidth`` +- ``NBKFlexibleWidth`` ### Integers +- ``IntXL`` - ``Int128`` - ``Int256`` - ``Int512`` @@ -109,6 +111,7 @@ Int256(5) % Int(5), UInt256(5) % UInt(5) - ``Int2048`` - ``Int4096`` +- ``UIntXL`` - ``UInt128`` - ``UInt256`` - ``UInt512`` diff --git a/Sources/Numberick/Exports.swift b/Sources/Numberick/Exports.swift index 77d13b91..73e171b2 100644 --- a/Sources/Numberick/Exports.swift +++ b/Sources/Numberick/Exports.swift @@ -13,3 +13,4 @@ @_exported import NBKCoreKit @_exported import NBKDoubleWidthKit +@_exported import NBKFlexibleWidthKit diff --git a/Tests/NBKDoubleWidthKitBenchmarks/256+Random.swift b/Tests/NBKDoubleWidthKitBenchmarks/256+Random.swift index 19ba76e9..992455a2 100644 --- a/Tests/NBKDoubleWidthKitBenchmarks/256+Random.swift +++ b/Tests/NBKDoubleWidthKitBenchmarks/256+Random.swift @@ -51,7 +51,7 @@ final class UInt256BenchmarksOnRandom: XCTestCase { //=------------------------------------------------------------------------= // MARK: Tests //=------------------------------------------------------------------------= - + func testRandomInRangeUsingSystemRandomNumberGenerator() { var range = NBK.blackHoleIdentity((T.min / 2) ... (T.max / 2)) var randomness = NBK.blackHoleIdentity(SystemRandomNumberGenerator()) diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Addition.swift b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Addition.swift new file mode 100644 index 00000000..cf0d2834 --- /dev/null +++ b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Addition.swift @@ -0,0 +1,58 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if !DEBUG + +import NBKCoreKit +import NBKFlexibleWidthKit +import XCTest + +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x UIntXL x Addition +//*============================================================================* + +final class UIntXLBenchmarksOnAddition: XCTestCase { + + typealias T = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testAdding() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs + rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Digit + //=------------------------------------------------------------------------= + + func testAddingDigit() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(UInt.max) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs + rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } +} + +#endif diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Bits.swift b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Bits.swift new file mode 100644 index 00000000..0ce7f77b --- /dev/null +++ b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Bits.swift @@ -0,0 +1,123 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if !DEBUG + +import NBKCoreKit +import NBKFlexibleWidthKit +import XCTest + +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x UIntXL x Bits +//*============================================================================* + +final class UIntXLBenchmarksOnBits: XCTestCase { + + typealias T = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testInitBit() { + var abc = NBK.blackHoleIdentity(true ) + var xyz = NBK.blackHoleIdentity(false) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(T(bit: abc)) + NBK.blackHole(T(bit: xyz)) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testBitWidth() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.bitWidth) + NBK.blackHole(xyz.bitWidth) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testNonzeroBitCount() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.nonzeroBitCount) + NBK.blackHole(xyz.nonzeroBitCount) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testLeadingZeroBitCount() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.leadingZeroBitCount) + NBK.blackHole(xyz.leadingZeroBitCount) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testTrailingZeroBitCount() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.trailingZeroBitCount) + NBK.blackHole(xyz.trailingZeroBitCount) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testMostSignificantBit() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.mostSignificantBit) + NBK.blackHole(xyz.mostSignificantBit) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testLeastSignificantBit() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.leastSignificantBit) + NBK.blackHole(xyz.leastSignificantBit) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } +} + +#endif diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Comparisons.swift b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Comparisons.swift new file mode 100644 index 00000000..cb385cc8 --- /dev/null +++ b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Comparisons.swift @@ -0,0 +1,105 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if !DEBUG + +import NBKCoreKit +import NBKFlexibleWidthKit +import XCTest + +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x UIntXL x Comparisons +//*============================================================================* + +final class UIntXLBenchmarksOnComparisons: XCTestCase { + + typealias T = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testIsEqualTo() { + var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs == rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testIsLessThan() { + var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs < rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testComparedTo() { + var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs.compared(to: rhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testIsZero() { + var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.isZero) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testIsLessThanZero() { + var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.isLessThanZero) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testIsMoreThanZero() { + var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.isMoreThanZero) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testIsPowerOf2() { + var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.isPowerOf2) + NBK.blackHoleInoutIdentity(&abc) + } + } +} + +#endif diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Division.swift b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Division.swift new file mode 100644 index 00000000..92c3b741 --- /dev/null +++ b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Division.swift @@ -0,0 +1,103 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if !DEBUG + +import NBKCoreKit +import NBKFlexibleWidthKit +import XCTest + +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x UIntXL x Division +//*============================================================================* + +final class UIntXLBenchmarksOnDivision: XCTestCase { + + typealias T = UIntXL + typealias M = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testQuotientAndRemainder() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + + for _ in 0 ..< 250_000 { + NBK.blackHole(lhs.quotientAndRemainder(dividingBy: rhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testQuotientReportingOverflow() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + + for _ in 0 ..< 250_000 { + NBK.blackHole(lhs.dividedReportingOverflow(by: rhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testRemainderReportingOverflow() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + + for _ in 0 ..< 250_000 { + NBK.blackHole(lhs.remainderReportingOverflow(dividingBy: rhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Digit + //=------------------------------------------------------------------------= + + func testQuotientAndRemainderDividingByDigit() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(UInt.max) + + for _ in 0 ..< 250_000 { + NBK.blackHole(lhs.quotientAndRemainder(dividingBy: rhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testQuotientDividingByDigitReportingOverflow() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(UInt.max) + + for _ in 0 ..< 250_000 { + NBK.blackHole(lhs.dividedReportingOverflow(by: rhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testRemainderDividingByDigitReportingOverflow() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(UInt.max) + + for _ in 0 ..< 250_000 { + NBK.blackHole(lhs.remainderReportingOverflow(dividingBy: rhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } +} + +#endif diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Logic.swift b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Logic.swift new file mode 100644 index 00000000..d7ac302d --- /dev/null +++ b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Logic.swift @@ -0,0 +1,74 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if !DEBUG + +import NBKCoreKit +import NBKFlexibleWidthKit +import XCTest + +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x UIntXL x Logic +//*============================================================================* + +final class UIntXLBenchmarksOnLogic: XCTestCase { + + typealias T = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testAnd() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs & rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testOr() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs | rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testXor() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs ^ rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testNot() { + var abc = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(~abc) + NBK.blackHoleInoutIdentity(&abc) + } + } +} + +#endif diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Multiplication.swift b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Multiplication.swift new file mode 100644 index 00000000..5f04f423 --- /dev/null +++ b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Multiplication.swift @@ -0,0 +1,58 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if !DEBUG + +import NBKCoreKit +import NBKFlexibleWidthKit +import XCTest + +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x UIntXL x Multiplication +//*============================================================================* + +final class UIntXLBenchmarksOnMultiplication: XCTestCase { + + typealias T = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testMultiplied() { + var lhs = NBK.blackHoleIdentity(T(x64:[~1, ~2, ~3, ~4] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 1, 2, 3, 4] as X)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs * rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Digit + //=------------------------------------------------------------------------= + + func testMultipliedByDigit() { + var lhs = NBK.blackHoleIdentity(T(x64:[~1, ~2, ~3, ~4] as X)) + var rhs = NBK.blackHoleIdentity(UInt.max) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs * rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } +} + +#endif diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Numbers.swift b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Numbers.swift new file mode 100644 index 00000000..472c59d3 --- /dev/null +++ b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Numbers.swift @@ -0,0 +1,419 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if !DEBUG + +import NBKCoreKit +import NBKFlexibleWidthKit +import XCTest + +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x UIntXL x Numbers +//*============================================================================* + +final class UIntXLBenchmarksOnNumbers: XCTestCase { + + typealias T = UIntXL + typealias M = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testZero() { + for _ in 0 ..< 250_000 { + NBK.blackHole(T()) + NBK.blackHole(T.zero) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Integers + //=------------------------------------------------------------------------= + + func testToInt() { + var abc = NBK.blackHoleIdentity(T(Int.max)) + + for _ in 0 ..< 250_000 { + NBK.blackHole(Int(abc)) + NBK.blackHole(Int(exactly: abc)) + NBK.blackHole(Int(clamping: abc)) + NBK.blackHole(Int(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromInt() { + var abc = NBK.blackHoleIdentity(Int.max) + + for _ in 0 ..< 250_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHole(T(clamping: abc)) + NBK.blackHole(T(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testToUInt() { + var abc = NBK.blackHoleIdentity(T(UInt.max)) + + for _ in 0 ..< 250_000 { + NBK.blackHole(UInt(abc)) + NBK.blackHole(UInt(exactly: abc)) + NBK.blackHole(UInt(clamping: abc)) + NBK.blackHole(UInt(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromUInt() { + var abc = NBK.blackHoleIdentity(UInt.max) + + for _ in 0 ..< 250_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHole(T(clamping: abc)) + NBK.blackHole(T(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testToInt8() { + var abc = NBK.blackHoleIdentity(T(Int8.max)) + + for _ in 0 ..< 250_000 { + NBK.blackHole(Int8(abc)) + NBK.blackHole(Int8(exactly: abc)) + NBK.blackHole(Int8(clamping: abc)) + NBK.blackHole(Int8(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromInt8() { + var abc = NBK.blackHoleIdentity(Int8.max) + + for _ in 0 ..< 250_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHole(T(clamping: abc)) + NBK.blackHole(T(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testToUInt8() { + var abc = NBK.blackHoleIdentity(T(UInt8.max)) + + for _ in 0 ..< 250_000 { + NBK.blackHole(UInt8(abc)) + NBK.blackHole(UInt8(exactly: abc)) + NBK.blackHole(UInt8(clamping: abc)) + NBK.blackHole(UInt8(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromUInt8() { + var abc = NBK.blackHoleIdentity(UInt8.max) + + for _ in 0 ..< 250_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHole(T(clamping: abc)) + NBK.blackHole(T(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testToInt16() { + var abc = NBK.blackHoleIdentity(T(Int16.max)) + + for _ in 0 ..< 250_000 { + NBK.blackHole(Int16(abc)) + NBK.blackHole(Int16(exactly: abc)) + NBK.blackHole(Int16(clamping: abc)) + NBK.blackHole(Int16(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromInt16() { + var abc = NBK.blackHoleIdentity(Int16.max) + + for _ in 0 ..< 250_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHole(T(clamping: abc)) + NBK.blackHole(T(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testToUInt16() { + var abc = NBK.blackHoleIdentity(T(UInt16.max)) + + for _ in 0 ..< 250_000 { + NBK.blackHole(UInt16(abc)) + NBK.blackHole(UInt16(exactly: abc)) + NBK.blackHole(UInt16(clamping: abc)) + NBK.blackHole(UInt16(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromUInt16() { + var abc = NBK.blackHoleIdentity(UInt16.max) + + for _ in 0 ..< 250_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHole(T(clamping: abc)) + NBK.blackHole(T(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testToInt32() { + var abc = NBK.blackHoleIdentity(T(Int32.max)) + + for _ in 0 ..< 250_000 { + NBK.blackHole(Int32(abc)) + NBK.blackHole(Int32(exactly: abc)) + NBK.blackHole(Int32(clamping: abc)) + NBK.blackHole(Int32(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromInt32() { + var abc = NBK.blackHoleIdentity(Int32.max) + + for _ in 0 ..< 250_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHole(T(clamping: abc)) + NBK.blackHole(T(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testToUInt32() { + var abc = NBK.blackHoleIdentity(T(UInt32.max)) + + for _ in 0 ..< 250_000 { + NBK.blackHole(UInt32(abc)) + NBK.blackHole(UInt32(exactly: abc)) + NBK.blackHole(UInt32(clamping: abc)) + NBK.blackHole(UInt32(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromUInt32() { + var abc = NBK.blackHoleIdentity(UInt32.max) + + for _ in 0 ..< 250_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHole(T(clamping: abc)) + NBK.blackHole(T(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testToInt64() { + var abc = NBK.blackHoleIdentity(T(Int64.max)) + + for _ in 0 ..< 250_000 { + NBK.blackHole(Int64(abc)) + NBK.blackHole(Int64(exactly: abc)) + NBK.blackHole(Int64(clamping: abc)) + NBK.blackHole(Int64(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromInt64() { + var abc = NBK.blackHoleIdentity(Int64.max) + + for _ in 0 ..< 250_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHole(T(clamping: abc)) + NBK.blackHole(T(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testToUInt64() { + var abc = NBK.blackHoleIdentity(T(UInt64.max)) + + for _ in 0 ..< 250_000 { + NBK.blackHole(UInt64(abc)) + NBK.blackHole(UInt64(exactly: abc)) + NBK.blackHole(UInt64(clamping: abc)) + NBK.blackHole(UInt64(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromUInt64() { + var abc = NBK.blackHoleIdentity(UInt64.max) + + for _ in 0 ..< 250_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHole(T(clamping: abc)) + NBK.blackHole(T(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Complements + //=------------------------------------------------------------------------= + + func testToDigit() { + var abc = NBK.blackHoleIdentity(T(T.Digit.max)) + + for _ in 0 ..< 250_000 { + NBK.blackHole(T.Digit(abc)) + NBK.blackHole(T.Digit(exactly: abc)) + NBK.blackHole(T.Digit(clamping: abc)) + NBK.blackHole(T.Digit(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromDigit() { + var abc = NBK.blackHoleIdentity(T.Digit.max) + + for _ in 0 ..< 250_000 { + NBK.blackHole(T(digit: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testToMagnitude() { + var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + + for _ in 0 ..< 250_000 { + NBK.blackHole(M(abc)) + NBK.blackHole(M(exactly: abc)) + NBK.blackHole(M(clamping: abc)) + NBK.blackHole(M(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromMagnitude() { + var abc = NBK.blackHoleIdentity(M(x64:[0, 1, 2, 3] as X)) + + for _ in 0 ..< 250_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHole(T(clamping: abc)) + NBK.blackHole(T(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Float + //=------------------------------------------------------------------------= + + // TODO: brrr + func testToFloat16() { + var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + + for _ in 0 ..< 1_000 { + NBK.blackHole(Float16(abc)) + NBK.blackHole(Float16(exactly: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromFloat16() { + var abc = NBK.blackHoleIdentity(Float16(123)) + + for _ in 0 ..< 250_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + // TODO: brrr + func testToFloat32() { + var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + + for _ in 0 ..< 1_000 { + NBK.blackHole(Float32(abc)) + NBK.blackHole(Float32(exactly: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromFloat32() { + var abc = NBK.blackHoleIdentity(Float32(123)) + + for _ in 0 ..< 250_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + // TODO: brrr + func testToFloat64() { + var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + + for _ in 0 ..< 1_000 { + NBK.blackHole(Float64(abc)) + NBK.blackHole(Float64(exactly: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromFloat64() { + var abc = NBK.blackHoleIdentity(Float64(123)) + + for _ in 0 ..< 250_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Sign & Magnitude + //=------------------------------------------------------------------------= + + func testSignAndMagnitude() { + var abc = NBK.blackHoleIdentity((sign: FloatingPointSign.plus, magnitude: M(x64:[0, 1, 2, 3] as X))) + var xyz = NBK.blackHoleIdentity((sign: FloatingPointSign.minus, magnitude: M(x64:[0, 1, 2, 3] as X))) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(T.exactly (sign: abc.sign, magnitude: abc.magnitude)) + NBK.blackHole(T.clamping(sign: abc.sign, magnitude: abc.magnitude)) + NBK.blackHoleInoutIdentity(&abc) + + NBK.blackHole(T.exactly (sign: xyz.sign, magnitude: xyz.magnitude)) + NBK.blackHole(T.clamping(sign: xyz.sign, magnitude: xyz.magnitude)) + NBK.blackHoleInoutIdentity(&xyz) + } + } +} + +#endif diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Shifts.swift b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Shifts.swift new file mode 100644 index 00000000..36709f05 --- /dev/null +++ b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Shifts.swift @@ -0,0 +1,102 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if !DEBUG + +import NBKCoreKit +import NBKFlexibleWidthKit +import XCTest + +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x UIntXL x Shifts +//*============================================================================* + +final class UIntXLBenchmarksOnShifts: XCTestCase { + + typealias T = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests x Left + //=------------------------------------------------------------------------= + + func testBitshiftingLeft() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(UInt.bitWidth * 3/2) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs << rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testBitshiftingLeftByWordsAndBits() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs.bitshiftedLeft(words: rhs.words, bits: rhs.bits)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testBitshiftingLeftByWords() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs.bitshiftedLeft(words: rhs.words)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Right + //=------------------------------------------------------------------------= + + func testBitshiftingRight() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(UInt.bitWidth * 3/2) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs >> rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testBitshiftingRightByWordsAndBits() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs.bitshiftedRight(words: rhs.words, bits: rhs.bits)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testBitshiftingRightByWords() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs.bitshiftedRight(words: rhs.words)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } +} + +#endif diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Subtraction.swift b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Subtraction.swift new file mode 100644 index 00000000..70579de1 --- /dev/null +++ b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Subtraction.swift @@ -0,0 +1,58 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if !DEBUG + +import NBKCoreKit +import NBKFlexibleWidthKit +import XCTest + +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x UIntXL x Subtraction +//*============================================================================* + +final class UIntXLBenchmarksOnSubtraction: XCTestCase { + + typealias T = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testAdding() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs - rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Digit + //=------------------------------------------------------------------------= + + func testAddingDigit() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(UInt.max) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs - rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } +} + +#endif diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Text.swift b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Text.swift new file mode 100644 index 00000000..515e773f --- /dev/null +++ b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Text.swift @@ -0,0 +1,109 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if !DEBUG + +import NBKCoreKit +import NBKFlexibleWidthKit +import XCTest + +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x UIntXL x Division +//*============================================================================* + +final class UIntXLBenchmarksOnText: XCTestCase { + + typealias T = UIntXL + + //=------------------------------------------------------------------------= + // MARK: State + //=------------------------------------------------------------------------= + + static let decoded = NBK.blackHoleIdentity(T(encoded, radix: 16)!) + static let encoded = NBK.blackHoleIdentity(String(repeating: "1", count: 64)) + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testDecodingRadix10() { + var radix = NBK.blackHoleIdentity(10) + var encoded = NBK.blackHoleIdentity(Self.encoded) + + for _ in 0 ..< 250_000 { + NBK.blackHole(T(encoded, radix: radix)!) + NBK.blackHoleInoutIdentity(&radix) + NBK.blackHoleInoutIdentity(&encoded) + } + } + + func testDecodingRadix16() { + var radix = NBK.blackHoleIdentity(16) + var encoded = NBK.blackHoleIdentity(Self.encoded) + + for _ in 0 ..< 250_000 { + NBK.blackHole(T(encoded, radix: radix)!) + NBK.blackHoleInoutIdentity(&radix) + NBK.blackHoleInoutIdentity(&encoded) + } + } + + func testEncodingRadix10() { + var radix = NBK.blackHoleIdentity(10) + var decoded = NBK.blackHoleIdentity(Self.decoded) + + for _ in 0 ..< 250_000 { + NBK.blackHole(String(decoded, radix: radix)) + NBK.blackHoleInoutIdentity(&radix) + NBK.blackHoleInoutIdentity(&decoded) + } + } + + func testEncodingRadix16() { + var radix = NBK.blackHoleIdentity(16) + var decoded = NBK.blackHoleIdentity(Self.decoded) + + for _ in 0 ..< 250_000 { + NBK.blackHole(String(decoded, radix: radix)) + NBK.blackHoleInoutIdentity(&radix) + NBK.blackHoleInoutIdentity(&decoded) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Swift Standard Library Methods + //=------------------------------------------------------------------------= + + func testEncodingUsingSwiftStdlibRadix10() { + var radix = NBK.blackHoleIdentity(10) + var decoded = NBK.blackHoleIdentity(Self.decoded) + + for _ in 0 ..< 1_000 { + NBK.blackHole(String.stdlib(decoded, radix: radix)) + NBK.blackHoleInoutIdentity(&radix) + NBK.blackHoleInoutIdentity(&decoded) + } + } + + func testEncodingUsingSwiftStdlibRadix16() { + var radix = NBK.blackHoleIdentity(16) + var decoded = NBK.blackHoleIdentity(Self.decoded) + + for _ in 0 ..< 1_000 { + NBK.blackHole(String.stdlib(decoded, radix: radix)) + NBK.blackHoleInoutIdentity(&radix) + NBK.blackHoleInoutIdentity(&decoded) + } + } +} + +#endif diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth.swift new file mode 100644 index 00000000..b9734c3e --- /dev/null +++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth.swift @@ -0,0 +1,80 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit +import NBKFlexibleWidthKit +import XCTest + +//*============================================================================* +// MARK: * NBK x Flexible Width x Initializers x Unsigned +//*============================================================================* + +extension NBKFlexibleWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Details x Limbs + //=------------------------------------------------------------------------= + + init(x32 limbs: [UInt32]) { + self.init(limbs: limbs) + } + + init(x64 limbs: [UInt64]) { + self.init(limbs: limbs) + } + + //=------------------------------------------------------------------------= + // MARK: Details x Limbs x Private + //=------------------------------------------------------------------------= + + private init(limbs: [Limb]) where Limb: NBKCoreInteger { + switch Limb.bitWidth >= UInt.bitWidth { + case true: self.init(majorLimbs: limbs) + case false: self.init(minorLimbs: limbs) } + } + + private init(majorLimbs: [Limb]) where Limb: NBKCoreInteger { + precondition(Limb.bitWidth.isPowerOf2) + precondition(Limb.bitWidth >= UInt.bitWidth) + //=--------------------------------------= + let ratio = Limb.bitWidth / UInt.bitWidth + let count = majorLimbs.count * ratio + var words = [UInt](); words.reserveCapacity(count) + //=--------------------------------------= + for limb in majorLimbs { + words.append(contentsOf: limb.words) + } + //=--------------------------------------= + self.init(words: words) + } + + private init(minorLimbs: [Limb]) where Limb: NBKCoreInteger { + precondition(Limb.bitWidth.isPowerOf2) + precondition(Limb.bitWidth <= UInt.bitWidth) + //=--------------------------------------= + let ratio = UInt.bitWidth / Limb.bitWidth + let count = minorLimbs.count / ratio + var words = [UInt](repeating: UInt.zero, count: count) + //=--------------------------------------= + var major = Int.zero + var minor = Int.zero + + for limb in minorLimbs { + words[major] |= UInt(truncatingIfNeeded: limb) &<< minor + minor += Limb.bitWidth + + if minor >= UInt.bitWidth { + minor -= UInt.bitWidth + major += 1 + } + } + //=--------------------------------------= + self.init(words: words) + } +} diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/Utilities/Stdlib.swift b/Tests/NBKFlexibleWidthKitBenchmarks/Utilities/Stdlib.swift new file mode 100644 index 00000000..3b3a6e17 --- /dev/null +++ b/Tests/NBKFlexibleWidthKitBenchmarks/Utilities/Stdlib.swift @@ -0,0 +1,23 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +//*============================================================================* +// MARK: * NBK x Stdlib x Text x Encode +//*============================================================================* + +extension Swift.String { + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + static func stdlib(_ source: some BinaryInteger, radix: Int = 10, uppercase: Bool = false) -> Self { + Self(source, radix: radix, uppercase: uppercase) + } +} diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Addition.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Addition.swift new file mode 100644 index 00000000..8aa3cdb5 --- /dev/null +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Addition.swift @@ -0,0 +1,94 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +@testable import NBKFlexibleWidthKit +import XCTest + +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x UIntXL x Addition +//*============================================================================* + +final class UIntXLTestsOnAddition: XCTestCase { + + typealias T = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testAdding() { + NBKAssertAddition(T(0), T(0), Int(0), T(0)) + NBKAssertAddition(T(0), T(1), Int(0), T(1)) + NBKAssertAddition(T(0), T(2), Int(0), T(2)) + + NBKAssertAddition(T(1), T(0), Int(0), T(1)) + NBKAssertAddition(T(1), T(1), Int(0), T(2)) + NBKAssertAddition(T(1), T(2), Int(0), T(3)) + } + + func testAddingAtIndex() { + NBKAssertAddition(T(words:[ 0, 0, 0, 0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(0), T(words:[ 1, 2, 3, 0] as [UInt])) + NBKAssertAddition(T(words:[~0, 0, 0, 0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(0), T(words:[ 0, 3, 3, 0] as [UInt])) + NBKAssertAddition(T(words:[~0, ~0, 0, 0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(0), T(words:[ 0, 2, 4, 0] as [UInt])) + NBKAssertAddition(T(words:[~0, ~0, ~0, 0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(0), T(words:[ 0, 2, 3, 1] as [UInt])) + + NBKAssertAddition(T(words:[ 0, 0, 0, 0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(1), T(words:[ 0, 1, 2, 3] as [UInt])) + NBKAssertAddition(T(words:[~0, 0, 0, 0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(1), T(words:[~0, 1, 2, 3] as [UInt])) + NBKAssertAddition(T(words:[~0, ~0, 0, 0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(1), T(words:[~0, 0, 3, 3] as [UInt])) + NBKAssertAddition(T(words:[~0, ~0, ~0, 0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(1), T(words:[~0, 0, 2, 4] as [UInt])) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Digit + //=------------------------------------------------------------------------= + + func testAddingDigit() { + NBKAssertAdditionByDigit(T(0), UInt(0), Int(0), T(0)) + NBKAssertAdditionByDigit(T(0), UInt(1), Int(0), T(1)) + NBKAssertAdditionByDigit(T(0), UInt(2), Int(0), T(2)) + + NBKAssertAdditionByDigit(T(1), UInt(0), Int(0), T(1)) + NBKAssertAdditionByDigit(T(1), UInt(1), Int(0), T(2)) + NBKAssertAdditionByDigit(T(1), UInt(2), Int(0), T(3)) + } + + func testAddingDigitAtIndex() { + NBKAssertAdditionByDigit(T(words:[ 0, 0, 0, 0] as [UInt]), UInt(3), Int(0), T(words:[ 3, 0, 0, 0] as [UInt])) + NBKAssertAdditionByDigit(T(words:[~0, 0, 0, 0] as [UInt]), UInt(3), Int(0), T(words:[ 2, 1, 0, 0] as [UInt])) + NBKAssertAdditionByDigit(T(words:[~0, ~0, 0, 0] as [UInt]), UInt(3), Int(0), T(words:[ 2, 0, 1, 0] as [UInt])) + NBKAssertAdditionByDigit(T(words:[~0, ~0, ~0, 0] as [UInt]), UInt(3), Int(0), T(words:[ 2, 0, 0, 1] as [UInt])) + + NBKAssertAdditionByDigit(T(words:[ 0, 0, 0, 0] as [UInt]), UInt(3), Int(1), T(words:[ 0, 3, 0, 0] as [UInt])) + NBKAssertAdditionByDigit(T(words:[~0, 0, 0, 0] as [UInt]), UInt(3), Int(1), T(words:[~0, 3, 0, 0] as [UInt])) + NBKAssertAdditionByDigit(T(words:[~0, ~0, 0, 0] as [UInt]), UInt(3), Int(1), T(words:[~0, 2, 1, 0] as [UInt])) + NBKAssertAdditionByDigit(T(words:[~0, ~0, ~0, 0] as [UInt]), UInt(3), Int(1), T(words:[~0, 2, 0, 1] as [UInt])) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Miscellaneous + //=------------------------------------------------------------------------= + + func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { + func becauseThisCompilesSuccessfully(_ x: inout T) { + XCTAssertNotNil(x += 0) + XCTAssertNotNil(x.add(0, at: 0)) + + XCTAssertNotNil(x + 0) + XCTAssertNotNil(x.adding(0, at: 0)) + } + } +} + +#endif diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Bits.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Bits.swift new file mode 100644 index 00000000..2f00eaa1 --- /dev/null +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Bits.swift @@ -0,0 +1,98 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +import NBKFlexibleWidthKit +import XCTest + +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x UIntXL x Bits +//*============================================================================* + +final class UIntXLTestsOnBits: XCTestCase { + + typealias T = UIntXL + typealias M = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testInitBit() { + XCTAssertEqual(T(bit: false), T( )) + XCTAssertEqual(T(bit: true ), T(1)) + } + + func testBitWidth() { + XCTAssertEqual(T(words: [ 0, 0, 0, 0] as [UInt]).bitWidth, UInt.bitWidth * 1) + XCTAssertEqual(T(words: [~0, ~0, ~0, ~0] as [UInt]).bitWidth, UInt.bitWidth * 4) + } + + func testNonzeroBitCount() { + XCTAssertEqual(T(words: [ 0, 0, 0, 0] as [UInt]).nonzeroBitCount, 0) + XCTAssertEqual(T(words: [ 1, 1, 1, 1] as [UInt]).nonzeroBitCount, 4) + } + + func testLeadingZeroBitCount() { + XCTAssertEqual(T(words: [ 0, 0, 0, 0] as [UInt]).leadingZeroBitCount, UInt.bitWidth * 1) + XCTAssertEqual(T(words: [~0, ~0, ~0, ~0] as [UInt]).leadingZeroBitCount, UInt.bitWidth * 0) + + XCTAssertEqual(T(words: [ 2, 0, 0, 0] as [UInt]).leadingZeroBitCount, UInt.bitWidth * 1 - 2) + XCTAssertEqual(T(words: [ 0, 2, 0, 0] as [UInt]).leadingZeroBitCount, UInt.bitWidth * 1 - 2) + XCTAssertEqual(T(words: [ 0, 0, 2, 0] as [UInt]).leadingZeroBitCount, UInt.bitWidth * 1 - 2) + XCTAssertEqual(T(words: [ 0, 0, 0, 2] as [UInt]).leadingZeroBitCount, UInt.bitWidth * 1 - 2) + } + + func testTrailingZeroBitCount() { + XCTAssertEqual(T(words: [ 0, 0, 0, 0] as [UInt]).leadingZeroBitCount, UInt.bitWidth * 1) + XCTAssertEqual(T(words: [~0, ~0, ~0, ~0] as [UInt]).leadingZeroBitCount, UInt.bitWidth * 0) + + XCTAssertEqual(T(words: [ 2, 0, 0, 0] as [UInt]).trailingZeroBitCount, UInt.bitWidth * 0 + 1) + XCTAssertEqual(T(words: [ 0, 2, 0, 0] as [UInt]).trailingZeroBitCount, UInt.bitWidth * 1 + 1) + XCTAssertEqual(T(words: [ 0, 0, 2, 0] as [UInt]).trailingZeroBitCount, UInt.bitWidth * 2 + 1) + XCTAssertEqual(T(words: [ 0, 0, 0, 2] as [UInt]).trailingZeroBitCount, UInt.bitWidth * 3 + 1) + } + + func testMostSignificantBit() { + XCTAssertEqual(T(words: [ 0, 0, 0, 0] as [UInt]).mostSignificantBit, false) + XCTAssertEqual(T(words: [~0, ~0, ~0, ~0] as [UInt]).mostSignificantBit, true ) + + XCTAssertEqual(T(words: [~0, 0, 0, 0] as [UInt]).mostSignificantBit, true ) + XCTAssertEqual(T(words: [ 0, ~0, 0, 0] as [UInt]).mostSignificantBit, true ) + XCTAssertEqual(T(words: [ 0, 0, ~0, 0] as [UInt]).mostSignificantBit, true ) + XCTAssertEqual(T(words: [ 0, 0, 0, ~0] as [UInt]).mostSignificantBit, true ) + + XCTAssertEqual(T(words: [~0, 1, 0, 0] as [UInt]).mostSignificantBit, false) + XCTAssertEqual(T(words: [ 0, ~0, 1, 0] as [UInt]).mostSignificantBit, false) + XCTAssertEqual(T(words: [ 0, 0, ~0, 1] as [UInt]).mostSignificantBit, false) + XCTAssertEqual(T(words: [ 1, 0, 0, ~0] as [UInt]).mostSignificantBit, true ) + } + + func testLeastSignificantBit() { + XCTAssertEqual(T(words: [ 0, 0, 0, 0] as [UInt]).leastSignificantBit, false) + XCTAssertEqual(T(words: [~0, ~0, ~0, ~0] as [UInt]).leastSignificantBit, true ) + + XCTAssertEqual(T(words: [~0, 0, 0, 0] as [UInt]).leastSignificantBit, true ) + XCTAssertEqual(T(words: [ 0, ~0, 0, 0] as [UInt]).leastSignificantBit, false) + XCTAssertEqual(T(words: [ 0, 0, ~0, 0] as [UInt]).leastSignificantBit, false) + XCTAssertEqual(T(words: [ 0, 0, 0, ~0] as [UInt]).leastSignificantBit, false) + + XCTAssertEqual(T(words: [~0, 1, 0, 0] as [UInt]).leastSignificantBit, true ) + XCTAssertEqual(T(words: [ 0, ~0, 1, 0] as [UInt]).leastSignificantBit, false) + XCTAssertEqual(T(words: [ 0, 0, ~0, 1] as [UInt]).leastSignificantBit, false) + XCTAssertEqual(T(words: [ 1, 0, 0, ~0] as [UInt]).leastSignificantBit, true ) + } +} + +#endif diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Comparisons.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Comparisons.swift new file mode 100644 index 00000000..91ba44cf --- /dev/null +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Comparisons.swift @@ -0,0 +1,147 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +import NBKFlexibleWidthKit +import XCTest + +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x UIntXL x Comparisons +//*============================================================================* + +final class UIntXLTestsOnComparisons: XCTestCase { + + typealias T = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testHashing() { + var union = Set() + union.insert(T(words:[0, 0, 0, 0] as [UInt])) + union.insert(T(words:[1, 0, 0, 0] as [UInt])) + union.insert(T(words:[0, 1, 0, 0] as [UInt])) + union.insert(T(words:[0, 0, 1, 0] as [UInt])) + union.insert(T(words:[0, 0, 0, 1] as [UInt])) + union.insert(T(words:[0, 0, 0, 0] as [UInt])) + XCTAssertEqual(union.count, 5) + } + + func testComparing() { + NBKAssertComparisons(T(0), T(0), Int(0)) + NBKAssertComparisons(T(1), T(1), Int(0)) + NBKAssertComparisons(T(2), T(3), -Int(1)) + NBKAssertComparisons(T(3), T(2), Int(1)) + + NBKAssertComparisons(T(words:[0, 2, 3, 4]), T(words:[1, 2, 3, 4]), -Int(1)) + NBKAssertComparisons(T(words:[1, 0, 3, 4]), T(words:[1, 2, 3, 4]), -Int(1)) + NBKAssertComparisons(T(words:[1, 2, 0, 4]), T(words:[1, 2, 3, 4]), -Int(1)) + NBKAssertComparisons(T(words:[1, 2, 3, 0]), T(words:[1, 2, 3, 4]), -Int(1)) + NBKAssertComparisons(T(words:[0, 2, 3, 4]), T(words:[0, 2, 3, 4]), Int(0)) + NBKAssertComparisons(T(words:[1, 0, 3, 4]), T(words:[1, 0, 3, 4]), Int(0)) + NBKAssertComparisons(T(words:[1, 2, 0, 4]), T(words:[1, 2, 0, 4]), Int(0)) + NBKAssertComparisons(T(words:[1, 2, 3, 0]), T(words:[1, 2, 3, 0]), Int(0)) + NBKAssertComparisons(T(words:[1, 2, 3, 4]), T(words:[0, 2, 3, 4]), Int(1)) + NBKAssertComparisons(T(words:[1, 2, 3, 4]), T(words:[1, 0, 3, 4]), Int(1)) + NBKAssertComparisons(T(words:[1, 2, 3, 4]), T(words:[1, 2, 0, 4]), Int(1)) + NBKAssertComparisons(T(words:[1, 2, 3, 4]), T(words:[1, 2, 3, 0]), Int(1)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testIsZero() { + XCTAssertTrue (( T(0)).isZero) + XCTAssertFalse(( T(1)).isZero) + XCTAssertFalse(( T(2)).isZero) + + XCTAssertFalse((~T(0)).isZero) + XCTAssertFalse((~T(1)).isZero) + XCTAssertFalse((~T(2)).isZero) + } + + func testIsLessThanZero() { + XCTAssertFalse(( T(0)).isLessThanZero) + XCTAssertFalse(( T(1)).isLessThanZero) + XCTAssertFalse(( T(2)).isLessThanZero) + + XCTAssertFalse((~T(0)).isLessThanZero) + XCTAssertFalse((~T(1)).isLessThanZero) + XCTAssertFalse((~T(2)).isLessThanZero) + } + + func testIsMoreThanZero() { + XCTAssertFalse(( T(0)).isMoreThanZero) + XCTAssertTrue (( T(1)).isMoreThanZero) + XCTAssertTrue (( T(2)).isMoreThanZero) + + XCTAssertTrue ((~T(0)).isMoreThanZero) + XCTAssertTrue ((~T(1)).isMoreThanZero) + XCTAssertTrue ((~T(2)).isMoreThanZero) + } + + func testIsOdd() { + XCTAssertFalse(( T(0)).isOdd) + XCTAssertTrue (( T(1)).isOdd) + XCTAssertFalse(( T(2)).isOdd) + + XCTAssertTrue ((~T(0)).isOdd) + XCTAssertFalse((~T(1)).isOdd) + XCTAssertTrue ((~T(2)).isOdd) + } + + func testIsEven() { + XCTAssertTrue (( T(0)).isEven) + XCTAssertFalse(( T(1)).isEven) + XCTAssertTrue (( T(2)).isEven) + + XCTAssertFalse((~T(0)).isEven) + XCTAssertTrue ((~T(1)).isEven) + XCTAssertFalse((~T(2)).isEven) + } + + func testSignum() { + XCTAssertEqual(( T(0)).signum(), Int(0)) + XCTAssertEqual(( T(1)).signum(), Int(1)) + XCTAssertEqual(( T(2)).signum(), Int(1)) + + XCTAssertEqual((~T(0)).signum(), Int(1)) + XCTAssertEqual((~T(1)).signum(), Int(1)) + XCTAssertEqual((~T(2)).signum(), Int(1)) + } + + func testIsPowerOf2() { + XCTAssertFalse((T( 0)).isPowerOf2) + XCTAssertTrue ((T( 1)).isPowerOf2) + XCTAssertTrue ((T( 2)).isPowerOf2) + XCTAssertFalse((T( 3)).isPowerOf2) + XCTAssertTrue ((T( 4)).isPowerOf2) + XCTAssertFalse((T( 5)).isPowerOf2) + XCTAssertFalse((T( 6)).isPowerOf2) + XCTAssertFalse((T( 7)).isPowerOf2) + + XCTAssertFalse(T(words:[0, 0, 0, 0] as [UInt]).isPowerOf2) + XCTAssertTrue (T(words:[1, 0, 0, 0] as [UInt]).isPowerOf2) + XCTAssertFalse(T(words:[1, 1, 0, 0] as [UInt]).isPowerOf2) + XCTAssertTrue (T(words:[0, 1, 0, 0] as [UInt]).isPowerOf2) + XCTAssertFalse(T(words:[0, 1, 1, 0] as [UInt]).isPowerOf2) + XCTAssertTrue (T(words:[0, 0, 1, 0] as [UInt]).isPowerOf2) + XCTAssertFalse(T(words:[0, 0, 1, 1] as [UInt]).isPowerOf2) + XCTAssertTrue (T(words:[0, 0, 0, 1] as [UInt]).isPowerOf2) + } +} + +#endif diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Division.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Division.swift new file mode 100644 index 00000000..9b621a5d --- /dev/null +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Division.swift @@ -0,0 +1,122 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +import NBKFlexibleWidthKit +import XCTest + +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x UIntXL x Division +//*============================================================================* + +final class UIntXLTestsOnDivision: XCTestCase { + + typealias T = UIntXL + typealias M = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testDividing() { + NBKAssertDivision(T( ), T(1), T( ), T( )) + NBKAssertDivision(T( ), T(2), T( ), T( )) + NBKAssertDivision(T(7), T(1), T(7), T( )) + NBKAssertDivision(T(7), T(2), T(3), T(1)) + } + + func testDividingReportingOverflow() { + NBKAssertDivision(T( ), T( ), T( ), T( ), true) + NBKAssertDivision(T(1), T( ), T(1), T(1), true) + NBKAssertDivision(T(2), T( ), T(2), T(2), true) + } + + func testDividingWithLargeDividend() { + NBKAssertDivision(T(x64:[~2, ~4, ~6, 9] as X), T(2), T(x64:[~1, ~2, ~3, 4] as X), T(1)) + NBKAssertDivision(T(x64:[~3, ~6, ~9, 14] as X), T(3), T(x64:[~1, ~2, ~3, 4] as X), T(2)) + NBKAssertDivision(T(x64:[~4, ~8, ~12, 19] as X), T(4), T(x64:[~1, ~2, ~3, 4] as X), T(3)) + NBKAssertDivision(T(x64:[~5, ~10, ~15, 24] as X), T(5), T(x64:[~1, ~2, ~3, 4] as X), T(4)) + + NBKAssertDivision(T(x64:[~2, ~4, ~6, 9] as X), T(x64:[~1, ~2, ~3, 4] as X), T(2), T(1)) + NBKAssertDivision(T(x64:[~3, ~6, ~9, 14] as X), T(x64:[~1, ~2, ~3, 4] as X), T(3), T(2)) + NBKAssertDivision(T(x64:[~4, ~8, ~12, 19] as X), T(x64:[~1, ~2, ~3, 4] as X), T(4), T(3)) + NBKAssertDivision(T(x64:[~5, ~10, ~15, 24] as X), T(x64:[~1, ~2, ~3, 4] as X), T(5), T(4)) + } + + func testDividingWithLargeDivisor() { + NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X), T(x64:[ 1, 2, 3, 4 &+ 1 << 63] as X), T(1), T(x64:[0, 0, 0, 0] as X)) + NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X), T(x64:[ 0, 1, 2, 3 &+ 1 << 63] as X), T(1), T(x64:[1, 1, 1, 1] as X)) + NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X), T(x64:[~0, ~0, 0, 2 &+ 1 << 63] as X), T(1), T(x64:[2, 2, 2, 2] as X)) + NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X), T(x64:[~1, ~1, ~0, 0 &+ 1 << 63] as X), T(1), T(x64:[3, 3, 3, 3] as X)) + + NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X), T(x64:[~2, ~2, ~1, ~0 &+ 1 << 63] as X), T(1), T(x64:[4, 4, 4, 4] as X)) + NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X), T(x64:[~3, ~3, ~2, ~1 &+ 1 << 63] as X), T(1), T(x64:[5, 5, 5, 5] as X)) + NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X), T(x64:[~4, ~4, ~3, ~2 &+ 1 << 63] as X), T(1), T(x64:[6, 6, 6, 6] as X)) + NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X), T(x64:[~5, ~5, ~4, ~3 &+ 1 << 63] as X), T(1), T(x64:[7, 7, 7, 7] as X)) + } + + func testDividingLikeFullWidth() { + NBKAssertDivision(M(x64:[06, 17, 35, 61, 61, 52, 32, 00] as X), T(x64:[1, 2, 3, 4] as X), T(x64:[5, 6, 7, 8] as X), T(x64:[ 1, 1, 1, 1] as X)) + NBKAssertDivision(M(x64:[06, 17, 35, 61, 61, 52, 32, 00] as X), T(x64:[5, 6, 7, 8] as X), T(x64:[1, 2, 3, 4] as X), T(x64:[ 1, 1, 1, 1] as X)) + + NBKAssertDivision(M(x64:[34, 54, 63, 62, 34, 16, 05, 00] as X), T(x64:[4, 3, 2, 1] as X), T(x64:[9, 7, 6, 5] as X), T(x64:[~1, ~1, ~0, 0] as X)) + NBKAssertDivision(M(x64:[34, 54, 63, 62, 34, 16, 05, 00] as X), T(x64:[8, 7, 6, 5] as X), T(x64:[4, 3, 2, 1] as X), T(x64:[ 2, 2, 2, 2] as X)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Digit + //=------------------------------------------------------------------------= + + func testDividingByDigit() { + NBKAssertDivisionByDigit(T( ), UInt(1), T( ), UInt( )) + NBKAssertDivisionByDigit(T( ), UInt(2), T( ), UInt( )) + NBKAssertDivisionByDigit(T(7), UInt(1), T(7), UInt( )) + NBKAssertDivisionByDigit(T(7), UInt(2), T(3), UInt(1)) + } + + func testDividingByDigitReportingOverflow() { + NBKAssertDivisionByDigit(T( ), UInt( ), T( ), UInt( ), true) + NBKAssertDivisionByDigit(T(1), UInt( ), T(1), UInt(1), true) + NBKAssertDivisionByDigit(T(2), UInt( ), T(2), UInt(2), true) + } + + func testDividingByDigitWithLargeDividend() { + NBKAssertDivisionByDigit(T(words:[~2, ~4, ~6, 9] as [UInt]), UInt(2), T(words:[~1, ~2, ~3, 4] as [UInt]), UInt(1)) + NBKAssertDivisionByDigit(T(words:[~3, ~6, ~9, 14] as [UInt]), UInt(3), T(words:[~1, ~2, ~3, 4] as [UInt]), UInt(2)) + NBKAssertDivisionByDigit(T(words:[~4, ~8, ~12, 19] as [UInt]), UInt(4), T(words:[~1, ~2, ~3, 4] as [UInt]), UInt(3)) + NBKAssertDivisionByDigit(T(words:[~5, ~10, ~15, 24] as [UInt]), UInt(5), T(words:[~1, ~2, ~3, 4] as [UInt]), UInt(4)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Miscellaneous + //=------------------------------------------------------------------------= + + func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { + func becauseThisCompilesSuccessfully(_ x: inout T) { + XCTAssertNotNil(x /= 0) + XCTAssertNotNil(x %= 0) + XCTAssertNotNil(x.divideReportingOverflow(by: 0)) + XCTAssertNotNil(x.formRemainderReportingOverflow(dividingBy: 0)) + + XCTAssertNotNil(x / 0) + XCTAssertNotNil(x % 0) + XCTAssertNotNil(x.dividedReportingOverflow(by: 0)) + XCTAssertNotNil(x.remainderReportingOverflow(dividingBy: 0)) + XCTAssertNotNil(x.quotientAndRemainder(dividingBy: 0)) + XCTAssertNotNil(x.quotientAndRemainderReportingOverflow(dividingBy: 0)) + } + } +} + +#endif diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Logic.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Logic.swift new file mode 100644 index 00000000..4735c741 --- /dev/null +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Logic.swift @@ -0,0 +1,73 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +import NBKFlexibleWidthKit +import XCTest + +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x UIntXL x Logic +//*============================================================================* + +final class UIntXLTestsOnLogic: XCTestCase { + + typealias T = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testNot() { + NBKAssertNot(T(words:[ 0, 0, 0, 0] as [UInt]), T(words:[~0, 0, 0, 0] as [UInt])) + NBKAssertNot(T(words:[~0, ~0, ~0, ~0] as [UInt]), T(words:[ 0, 0, 0, 0] as [UInt])) + + NBKAssertNot(T(words:[ 0, 1, 2, 3] as [UInt]), T(words:[~0, ~1, ~2, ~3] as [UInt])) + NBKAssertNot(T(words:[~0, ~1, ~2, ~3] as [UInt]), T(words:[ 0, 1, 2, 3] as [UInt])) + } + + func testAnd() { + NBKAssertAnd(T(words:[ 0, 1, 2, 3] as [UInt]), T(words:[ 0, 0, 0, 0] as [UInt]), T(words:[ 0, 0, 0, 0] as [UInt])) + NBKAssertAnd(T(words:[ 3, 2, 1, 0] as [UInt]), T(words:[ 0, 0, 0, 0] as [UInt]), T(words:[ 0, 0, 0, 0] as [UInt])) + + NBKAssertAnd(T(words:[ 0, 1, 2, 3] as [UInt]), T(words:[~0, ~0, ~0, ~0] as [UInt]), T(words:[ 0, 1, 2, 3] as [UInt])) + NBKAssertAnd(T(words:[ 3, 2, 1, 0] as [UInt]), T(words:[~0, ~0, ~0, ~0] as [UInt]), T(words:[ 3, 2, 1, 0] as [UInt])) + + NBKAssertAnd(T(words:[ 0, 1, 2, 3] as [UInt]), T(words:[ 1, 1, 1, 1] as [UInt]), T(words:[ 0, 1, 0, 1] as [UInt])) + NBKAssertAnd(T(words:[ 3, 2, 1, 0] as [UInt]), T(words:[ 1, 1, 1, 1] as [UInt]), T(words:[ 1, 0, 1, 0] as [UInt])) + } + + func testOr() { + NBKAssertOr (T(words:[ 0, 1, 2, 3] as [UInt]), T(words:[ 0, 0, 0, 0] as [UInt]), T(words:[ 0, 1, 2, 3] as [UInt])) + NBKAssertOr (T(words:[ 3, 2, 1, 0] as [UInt]), T(words:[ 0, 0, 0, 0] as [UInt]), T(words:[ 3, 2, 1, 0] as [UInt])) + + NBKAssertOr (T(words:[ 0, 1, 2, 3] as [UInt]), T(words:[~0, ~0, ~0, ~0] as [UInt]), T(words:[~0, ~0, ~0, ~0] as [UInt])) + NBKAssertOr (T(words:[ 3, 2, 1, 0] as [UInt]), T(words:[~0, ~0, ~0, ~0] as [UInt]), T(words:[~0, ~0, ~0, ~0] as [UInt])) + + NBKAssertOr (T(words:[ 0, 1, 2, 3] as [UInt]), T(words:[ 1, 1, 1, 1] as [UInt]), T(words:[ 1, 1, 3, 3] as [UInt])) + NBKAssertOr (T(words:[ 3, 2, 1, 0] as [UInt]), T(words:[ 1, 1, 1, 1] as [UInt]), T(words:[ 3, 3, 1, 1] as [UInt])) + } + + func testXor() { + NBKAssertXor(T(words:[ 0, 1, 2, 3] as [UInt]), T(words:[ 0, 0, 0, 0] as [UInt]), T(words:[ 0, 1, 2, 3] as [UInt])) + NBKAssertXor(T(words:[ 3, 2, 1, 0] as [UInt]), T(words:[ 0, 0, 0, 0] as [UInt]), T(words:[ 3, 2, 1, 0] as [UInt])) + + NBKAssertXor(T(words:[ 0, 1, 2, 3] as [UInt]), T(words:[~0, ~0, ~0, ~0] as [UInt]), T(words:[~0, ~1, ~2, ~3] as [UInt])) + NBKAssertXor(T(words:[ 3, 2, 1, 0] as [UInt]), T(words:[~0, ~0, ~0, ~0] as [UInt]), T(words:[~3, ~2, ~1, ~0] as [UInt])) + + NBKAssertXor(T(words:[ 0, 1, 2, 3] as [UInt]), T(words:[ 1, 1, 1, 1] as [UInt]), T(words:[ 1, 0, 3, 2] as [UInt])) + NBKAssertXor(T(words:[ 3, 2, 1, 0] as [UInt]), T(words:[ 1, 1, 1, 1] as [UInt]), T(words:[ 2, 3, 0, 1] as [UInt])) + } +} + +#endif diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Multiplication.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Multiplication.swift new file mode 100644 index 00000000..0e5863b4 --- /dev/null +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Multiplication.swift @@ -0,0 +1,70 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +import NBKFlexibleWidthKit +import XCTest + +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x UIntXL x Multiplication +//*============================================================================* + +final class UIntXLTestsOnMultiplication: XCTestCase { + + typealias T = UIntXL + typealias M = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testMultiplying() { + NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as [UInt]), T(words:[2, 0, 0, 0] as [UInt]), T(words:[ 2, 4, 6, 8, 0, 0, 0, 0] as [UInt])) + NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as [UInt]), T(words:[0, 2, 0, 0] as [UInt]), T(words:[ 0, 2, 4, 6, 8, 0, 0, 0] as [UInt])) + NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as [UInt]), T(words:[0, 0, 2, 0] as [UInt]), T(words:[ 0, 0, 2, 4, 6, 8, 0, 0] as [UInt])) + NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as [UInt]), T(words:[0, 0, 0, 2] as [UInt]), T(words:[ 0, 0, 0, 2, 4, 6, 8, 0] as [UInt])) + + NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as [UInt]), T(words:[2, 0, 0, 0] as [UInt]), T(words:[~3, ~4, ~6, ~8, 1, 0, 0, 0] as [UInt])) + NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as [UInt]), T(words:[0, 2, 0, 0] as [UInt]), T(words:[ 0, ~3, ~4, ~6, ~8, 1, 0, 0] as [UInt])) + NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as [UInt]), T(words:[0, 0, 2, 0] as [UInt]), T(words:[ 0, 0, ~3, ~4, ~6, ~8, 1, 0] as [UInt])) + NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as [UInt]), T(words:[0, 0, 0, 2] as [UInt]), T(words:[ 0, 0, 0, ~3, ~4, ~6, ~8, 1] as [UInt])) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Digit + //=------------------------------------------------------------------------= + + func testMultipliedByDigit() { + NBKAssertMultiplicationByDigit(T(words:[1, 2, 3, 4] as [UInt]), UInt(0), T(words:[0, 0, 0, 0, 0] as [UInt])) + NBKAssertMultiplicationByDigit(T(words:[1, 2, 3, 4] as [UInt]), UInt(1), T(words:[1, 2, 3, 4, 0] as [UInt])) + NBKAssertMultiplicationByDigit(T(words:[1, 2, 3, 4] as [UInt]), UInt(2), T(words:[2, 4, 6, 8, 0] as [UInt])) + + NBKAssertMultiplicationByDigit(T(words:[1, 2, 3, 4] as [UInt]), ~UInt(0), ~T(words:[0, 1, 1, 1, ~3] as [UInt])) + NBKAssertMultiplicationByDigit(T(words:[1, 2, 3, 4] as [UInt]), ~UInt(1), ~T(words:[1, 3, 4, 5, ~3] as [UInt])) + NBKAssertMultiplicationByDigit(T(words:[1, 2, 3, 4] as [UInt]), ~UInt(2), ~T(words:[2, 5, 7, 9, ~3] as [UInt])) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Miscellaneous + //=------------------------------------------------------------------------= + + func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { + func becauseThisCompilesSuccessfully(_ x: inout T) { + XCTAssertNotNil(x *= 0) + XCTAssertNotNil(x * 0) + } + } +} + +#endif diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Numbers.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Numbers.swift new file mode 100644 index 00000000..29f2d115 --- /dev/null +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Numbers.swift @@ -0,0 +1,235 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +@testable import NBKFlexibleWidthKit +import XCTest + +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x UIntXL x Numbers +//*============================================================================* + +final class UIntXLTestsOnNumbers: XCTestCase { + + typealias T = UIntXL + typealias M = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testZero() { + XCTAssertEqual(T( 0), T(words:[0])) + XCTAssertEqual(T.zero, T(words:[0])) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Int + //=------------------------------------------------------------------------= + + func testToInt() { + NBKAssertNumbers(from: T(words:[ 1, 0, 0, 0] as [UInt]), default: Int( 1)) + NBKAssertNumbers(from: T(words:[~0, 0, 0, 0] as [UInt]), exactly: nil, clamping: Int.max, truncating: -1) + NBKAssertNumbers(from: T(words:[ 1, 1, 1, 1] as [UInt]), exactly: nil, clamping: Int.max, truncating: 1) + NBKAssertNumbers(from: T(words:[~0, ~0, ~0, ~0] as [UInt]), exactly: nil, clamping: Int.max, truncating: -1) + } + + func testFromInt() { + NBKAssertNumbers(from: Int.min, exactly: nil, clamping: 0, truncating: T(words: Int.min.words)) + NBKAssertNumbers(from: Int.max, default: /*-------------------------*/ T(words: Int.max.words)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Int32 + //=------------------------------------------------------------------------= + + func testToInt32() { + NBKAssertNumbers(from: T(x32: [ 1, 0, 0, 0] as Y), default: Int32( 1)) + NBKAssertNumbers(from: T(x32: [~0, 0, 0, 0] as Y), exactly: nil, clamping: Int32.max, truncating: -1) + NBKAssertNumbers(from: T(x32: [ 1, 1, 1, 1] as Y), exactly: nil, clamping: Int32.max, truncating: 1) + NBKAssertNumbers(from: T(x32: [~0, ~0, ~0, ~0] as Y), exactly: nil, clamping: Int32.max, truncating: -1) + } + + func testFromInt32() { + NBKAssertNumbers(from: Int32.min, exactly: nil, clamping: 0, truncating: T(words: Int32.min.words)) + NBKAssertNumbers(from: Int32.max, default: /*-------------------------*/ T(words: Int32.max.words)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Int64 + //=------------------------------------------------------------------------= + + func testToInt64() { + NBKAssertNumbers(from: T(x64: [ 1, 0, 0, 0] as X), default: Int64( 1)) + NBKAssertNumbers(from: T(x64: [~0, 0, 0, 0] as X), exactly: nil, clamping: Int64.max, truncating: -1) + NBKAssertNumbers(from: T(x64: [ 1, 1, 1, 1] as X), exactly: nil, clamping: Int64.max, truncating: 1) + NBKAssertNumbers(from: T(x64: [~0, ~0, ~0, ~0] as X), exactly: nil, clamping: Int64.max, truncating: -1) + } + + func testFromInt64() { + NBKAssertNumbers(from: Int64.min, exactly: nil, clamping: 0, truncating: T(words: Int64.min.words)) + NBKAssertNumbers(from: Int64.max, default: /*-------------------------*/ T(words: Int64.max.words)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x UInt + //=------------------------------------------------------------------------= + + func testToUInt() { + NBKAssertNumbers(from: T(words:[ 1, 0, 0, 0] as [UInt]), default: UInt( 1)) + NBKAssertNumbers(from: T(words:[~0, 0, 0, 0] as [UInt]), default: ~UInt( 0)) + NBKAssertNumbers(from: T(words:[ 1, 1, 1, 1] as [UInt]), exactly: nil, clamping: UInt.max, truncating: 1) + NBKAssertNumbers(from: T(words:[~0, ~0, ~0, ~0] as [UInt]), exactly: nil, clamping: UInt.max, truncating: ~0) + } + + func testFromUInt() { + NBKAssertNumbers(from: UInt.min, default: T(words: UInt.min.words)) + NBKAssertNumbers(from: UInt.max, default: T(words: UInt.max.words)) + } + + func testFromUIntAsDigit() { + XCTAssertEqual(T(digit: UInt.min), T(words:[UInt.min])) + XCTAssertEqual(T(digit: UInt.max), T(words:[UInt.max])) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x UInt32 + //=------------------------------------------------------------------------= + + func testToUInt32() { + NBKAssertNumbers(from: T(x32: [ 1, 0, 0, 0] as Y), default: UInt32( 1)) + NBKAssertNumbers(from: T(x32: [~0, 0, 0, 0] as Y), default: ~UInt32( 0)) + NBKAssertNumbers(from: T(x32: [ 1, 1, 1, 1] as Y), exactly: nil, clamping: UInt32.max, truncating: 1) + NBKAssertNumbers(from: T(x32: [~0, ~0, ~0, ~0] as Y), exactly: nil, clamping: UInt32.max, truncating: ~0) + } + + func testFromUInt32() { + NBKAssertNumbers(from: UInt32.min, default: T(words: UInt32.min.words)) + NBKAssertNumbers(from: UInt32.max, default: T(words: UInt32.max.words)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x UInt64 + //=------------------------------------------------------------------------= + + func testFromUInt64() { + NBKAssertNumbers(from: UInt64.min, default: T(words: UInt64.min.words)) + NBKAssertNumbers(from: UInt64.max, default: T(words: UInt64.max.words)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Float32 + //=------------------------------------------------------------------------= + + func testToFloat32() { + XCTAssertEqual(Float32(T(0)), Float32(0)) + XCTAssertEqual(Float32(T(1)), Float32(1)) + + XCTAssertEqual(Float32(T(UInt32.min)), Float32(UInt32.min)) + XCTAssertEqual(Float32(T(UInt32.max)), Float32(UInt32.max)) + } + + func testFromFloat32() { + XCTAssertEqual(T(Float32( 22.0)), 22) + XCTAssertEqual(T(Float32( 22.5)), 22) + + XCTAssertEqual(T(exactly: 22.5), nil) + XCTAssertEqual(T(exactly: -22.5), nil) + + XCTAssertEqual(T(exactly: pow(2, Float32(64 * 0 - 1))), nil) + XCTAssertEqual(T(exactly: pow(2, Float32(64 * 0 - 0))), T(x64:[1, 0, 0, 0] as X)) + XCTAssertEqual(T(exactly: pow(2, Float32(64 * 1 - 1))), T(x64:[1 << 63, 0, 0, 0] as X)) + XCTAssertEqual(T(exactly: pow(2, Float32(64 * 2 - 1))), T(x64:[0, 1 << 63, 0, 0] as X)) + XCTAssertEqual(T(exactly: pow(2, Float32(64 * 2 - 0))), nil) + } + + func testFromFloat32ValuesThatAreSpecial() { + XCTAssertNil(T(exactly: Float32.nan)) + XCTAssertNil(T(exactly: Float32.infinity)) + XCTAssertNil(T(exactly: Float32.signalingNaN)) + XCTAssertNil(T(exactly: Float32.leastNormalMagnitude)) + XCTAssertNil(T(exactly: Float32.leastNonzeroMagnitude)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Float64 + //=------------------------------------------------------------------------= + + func testToFloat64() { + XCTAssertEqual(Float64(T(0)), Float64(0)) + XCTAssertEqual(Float64(T(1)), Float64(1)) + + XCTAssertEqual(Float64(T(UInt64.min)), Float64(UInt64.min)) + XCTAssertEqual(Float64(T(UInt64.max)), Float64(UInt64.max)) + } + + func testFromFloat64() { + XCTAssertEqual(T(Float64( 22.0)), 22) + XCTAssertEqual(T(Float64( 22.5)), 22) + + XCTAssertEqual(T(exactly: 22.5), nil) + XCTAssertEqual(T(exactly: -22.5), nil) + + XCTAssertEqual(T(exactly: pow(2, Float64(64 * 0 - 1))), nil) + XCTAssertEqual(T(exactly: pow(2, Float64(64 * 0 - 0))), T(x64:[1, 0, 0, 0] as X)) + XCTAssertEqual(T(exactly: pow(2, Float64(64 * 1 - 1))), T(x64:[1 << 63, 0, 0, 0] as X)) + XCTAssertEqual(T(exactly: pow(2, Float64(64 * 2 - 1))), T(x64:[0, 1 << 63, 0, 0] as X)) + XCTAssertEqual(T(exactly: pow(2, Float64(64 * 3 - 1))), T(x64:[0, 0, 1 << 63, 0] as X)) + XCTAssertEqual(T(exactly: pow(2, Float64(64 * 4 - 1))), T(x64:[0, 0, 0, 1 << 63] as X)) + } + + func testFromFloat64ValuesThatAreSpecial() { + XCTAssertNil(T(exactly: Float64.nan)) + XCTAssertNil(T(exactly: Float64.infinity)) + XCTAssertNil(T(exactly: Float64.signalingNaN)) + XCTAssertNil(T(exactly: Float64.leastNormalMagnitude)) + XCTAssertNil(T(exactly: Float64.leastNonzeroMagnitude)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Sign & Magnitude + //=------------------------------------------------------------------------= + + func testsFromSignAndMagnitude() { + XCTAssertEqual(T.exactly (sign: .plus, magnitude: M( 1)), T( 1)) + XCTAssertEqual(T.clamping(sign: .plus, magnitude: M( 1)), T( 1)) + + XCTAssertEqual(T.exactly (sign: .minus, magnitude: M( 1)), nil) + XCTAssertEqual(T.clamping(sign: .minus, magnitude: M( 1)), T( )) + } + + func testsFromSignAndMagnitudeAsPlusMinusZero() { + XCTAssertEqual(T.exactly (sign: .plus, magnitude: M( )), T( )) + XCTAssertEqual(T.clamping(sign: .plus, magnitude: M( )), T( )) + + XCTAssertEqual(T.exactly (sign: .minus, magnitude: M( )), T( )) + XCTAssertEqual(T.clamping(sign: .minus, magnitude: M( )), T( )) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Literal + //=------------------------------------------------------------------------= + + func testFromLiteral() { + XCTAssertEqual(T(x64: [ 0, 0, 0, 0] as X), 0) + XCTAssertEqual(T(x64: [~0, 0, 0, 0] as X), 18446744073709551615) + XCTAssertEqual(T(x64: [~0, ~0, 0, 0] as X), 340282366920938463463374607431768211455) + XCTAssertEqual(T(x64: [~0, ~0, ~0, 0] as X), 6277101735386680763835789423207666416102355444464034512895) + XCTAssertEqual(T(x64: [~0, ~0, ~0, ~0] as X), 115792089237316195423570985008687907853269984665640564039457584007913129639935) + + XCTAssertNil(T(exactlyIntegerLiteral: -1)) + } +} + +#endif diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Shifts.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Shifts.swift new file mode 100644 index 00000000..e11f90b5 --- /dev/null +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Shifts.swift @@ -0,0 +1,116 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +import NBKFlexibleWidthKit +import XCTest + +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x UIntXL x Shifts +//*============================================================================* + +final class UIntXLTestsOnShifts: XCTestCase { + + typealias T = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests x Left + //=------------------------------------------------------------------------= + + func testBitshiftingLeftByBits() { + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 0, T(x64:[ 1, 2, 3, 4] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 1, T(x64:[ 2, 4, 6, 8] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 2, T(x64:[ 4, 8, 12, 16] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 3, T(x64:[ 8, 16, 24, 32] as X)) + } + + func testBitshiftingLeftByWords() { + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 0, T(x64:[ 1, 2, 3, 4, 0, 0, 0, 0] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 64, T(x64:[ 0, 1, 2, 3, 4, 0, 0, 0] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 128, T(x64:[ 0, 0, 1, 2, 3, 4, 0, 0] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 192, T(x64:[ 0, 0, 0, 1, 2, 3, 4, 0] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 256, T(x64:[ 0, 0, 0, 0, 1, 2, 3, 4] as X)) + } + + func testBitshiftingLeftByWordsAndBits() { + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 3, T(x64:[ 8, 16, 24, 32, 0, 0, 0, 0] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 67, T(x64:[ 0, 8, 16, 24, 32, 0, 0, 0] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 131, T(x64:[ 0, 0, 8, 16, 24, 32, 0, 0] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 195, T(x64:[ 0, 0, 0, 8, 16, 24, 32, 0] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 259, T(x64:[ 0, 0, 0, 0, 8, 16, 24, 32] as X)) + } + + func testBitshiftingLeftSuchThatWordsSplit() { + NBKAssertShiftLeft(T(x64:[~0, 0, 0, 0] as X), 1, T(x64:[~1, 1, 0, 0, 0] as X)) + NBKAssertShiftLeft(T(x64:[ 0, ~0, 0, 0] as X), 1, T(x64:[ 0, ~1, 1, 0, 0] as X)) + NBKAssertShiftLeft(T(x64:[ 0, 0, ~0, 0] as X), 1, T(x64:[ 0, 0, ~1, 1, 0] as X)) + NBKAssertShiftLeft(T(x64:[ 0, 0, 0, ~0] as X), 1, T(x64:[ 0, 0, 0, ~1, 1] as X)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Right + //=------------------------------------------------------------------------= + + func testBitshiftingRightByBits() { + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 0, T(x64:[ 8, 16, 24, 32] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 1, T(x64:[ 4, 8, 12, 16] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 2, T(x64:[ 2, 4, 6, 8] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 3, T(x64:[ 1, 2, 3, 4] as X)) + } + + func testBitshiftingRightByWords() { + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 0, T(x64:[ 8, 16, 24, 32] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 64, T(x64:[16, 24, 32, 0] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 128, T(x64:[24, 32, 0, 0] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 192, T(x64:[32, 0, 0, 0] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 256, T(x64:[ 0, 0, 0, 0] as X)) + } + + func testBitshiftingRightByWordsAndBits() { + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 3, T(x64:[ 1, 2, 3, 4] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 67, T(x64:[ 2, 3, 4, 0] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 131, T(x64:[ 3, 4, 0, 0] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 195, T(x64:[ 4, 0, 0, 0] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 259, T(x64:[ 0, 0, 0, 0] as X)) + } + + func testBitshiftingRightSuchThatWordsSplit() { + NBKAssertShiftRight(T(x64:[0, 0, 0, 7] as X), 1, T(x64:[ 0, 0, 1 << 63, 3] as X)) + NBKAssertShiftRight(T(x64:[0, 0, 7, 0] as X), 1, T(x64:[ 0, 1 << 63, 3, 0] as X)) + NBKAssertShiftRight(T(x64:[0, 7, 0, 0] as X), 1, T(x64:[ 1 << 63, 3, 0, 0] as X)) + NBKAssertShiftRight(T(x64:[7, 0, 0, 0] as X), 1, T(x64:[ 3, 0, 0, 0] as X)) + } + + func testBitshiftingRightIsUnsigned() { + NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X), 0, T(x64:[0, 0, 0, 1 << 63] as X)) + NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X), 64, T(x64:[0, 0, 1 << 63, 0] as X)) + NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X), 128, T(x64:[0, 1 << 63, 0, 0] as X)) + NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X), 192, T(x64:[1 << 63, 0, 0, 0] as X)) + NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X), 256, T(x64:[0, 0, 0, 0] as X)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Miscellaneous + //=------------------------------------------------------------------------= + + func testBitshiftingIsSmart() { + XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) << 1, T(x64:[2, 4, 6, 8, 0] as X)) + XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) >> -1, T(x64:[2, 4, 6, 8, 0] as X)) + + XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) << 64, T(x64:[0, 1, 2, 3, 4] as X)) + XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) >> -64, T(x64:[0, 1, 2, 3, 4] as X)) + } +} + +#endif diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Subtraction.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Subtraction.swift new file mode 100644 index 00000000..1e8eda00 --- /dev/null +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Subtraction.swift @@ -0,0 +1,115 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +import NBKFlexibleWidthKit +import XCTest + +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x UIntXL x Subtraction +//*============================================================================* + +final class UIntXLTestsOnSubtraction: XCTestCase { + + typealias T = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testSubtracting() { + NBKAssertSubtraction(T(3), T(0), Int(0), T(3)) + NBKAssertSubtraction(T(3), T(1), Int(0), T(2)) + NBKAssertSubtraction(T(3), T(2), Int(0), T(1)) + NBKAssertSubtraction(T(3), T(3), Int(0), T(0)) + } + + func testSubtractingReportingOverflow() { + NBKAssertSubtraction(T(1), T(0), Int(0), T(1)) + NBKAssertSubtraction(T(1), T(1), Int(0), T(0)) + NBKAssertSubtraction(T(1), T(2), Int(0), ~T(0), true) + NBKAssertSubtraction(T(1), T(3), Int(0), ~T(1), true) + } + + func testSubtractingAtIndex() { + NBKAssertSubtraction(T(words:[~0, ~0, ~0, ~0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(0), T(words:[~1, ~2, ~3, ~0] as [UInt])) + NBKAssertSubtraction(T(words:[ 0, ~0, ~0, ~0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(0), T(words:[~0, ~3, ~3, ~0] as [UInt])) + NBKAssertSubtraction(T(words:[ 0, 0, ~0, ~0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(0), T(words:[~0, ~2, ~4, ~0] as [UInt])) + NBKAssertSubtraction(T(words:[ 0, 0, 0, ~0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(0), T(words:[~0, ~2, ~3, ~1] as [UInt])) + + NBKAssertSubtraction(T(words:[~0, ~0, ~0, ~0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(1), T(words:[~0, ~1, ~2, ~3] as [UInt])) + NBKAssertSubtraction(T(words:[ 0, ~0, ~0, ~0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(1), T(words:[ 0, ~1, ~2, ~3] as [UInt])) + NBKAssertSubtraction(T(words:[ 0, 0, ~0, ~0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(1), T(words:[ 0, ~0, ~3, ~3] as [UInt])) + NBKAssertSubtraction(T(words:[ 0, 0, 0, ~0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(1), T(words:[ 0, ~0, ~2, ~4] as [UInt])) + } + + func testSubtractingAtIndexReportingOverflow() { + NBKAssertSubtraction(T(words:[ 1, 2, 3, 0] as [UInt]), T(words:[ 4, 5, 0, 0] as [UInt]), Int(0), T(words:[~2, ~3, 2, 0] as [UInt])) + NBKAssertSubtraction(T(words:[ 1, 2, 3, 0] as [UInt]), T(words:[ 4, 5, 0, 0] as [UInt]), Int(1), T(words:[ 1, ~1, ~2, 0] as [UInt]), true) + NBKAssertSubtraction(T(words:[ 1, 2, 3, 0] as [UInt]), T(words:[ 4, 5, 0, 0] as [UInt]), Int(2), T(words:[ 1, 2, ~0, ~5] as [UInt]), true) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Digit + //=------------------------------------------------------------------------= + + func testSubtractingDigit() { + NBKAssertSubtractionByDigit(T(3), UInt(0), Int(0), T(3)) + NBKAssertSubtractionByDigit(T(3), UInt(1), Int(0), T(2)) + NBKAssertSubtractionByDigit(T(3), UInt(2), Int(0), T(1)) + NBKAssertSubtractionByDigit(T(3), UInt(3), Int(0), T(0)) + } + + func testSubtractingDigitReportingOverflow() { + NBKAssertSubtractionByDigit(T(1), UInt(0), Int(0), T(1)) + NBKAssertSubtractionByDigit(T(1), UInt(1), Int(0), T(0)) + NBKAssertSubtractionByDigit(T(1), UInt(2), Int(0), ~T(0), true) + NBKAssertSubtractionByDigit(T(1), UInt(3), Int(0), ~T(1), true) + } + + func testSubtractingDigitAtIndex() { + NBKAssertSubtractionByDigit(T(words:[~0, ~0, ~0, ~0] as [UInt]), UInt(3), Int(0), T(words:[~3, ~0, ~0, ~0] as [UInt])) + NBKAssertSubtractionByDigit(T(words:[ 0, ~0, ~0, ~0] as [UInt]), UInt(3), Int(0), T(words:[~2, ~1, ~0, ~0] as [UInt])) + NBKAssertSubtractionByDigit(T(words:[ 0, 0, ~0, ~0] as [UInt]), UInt(3), Int(0), T(words:[~2, ~0, ~1, ~0] as [UInt])) + NBKAssertSubtractionByDigit(T(words:[ 0, 0, 0, ~0] as [UInt]), UInt(3), Int(0), T(words:[~2, ~0, ~0, ~1] as [UInt])) + + NBKAssertSubtractionByDigit(T(words:[~0, ~0, ~0, ~0] as [UInt]), UInt(3), Int(1), T(words:[~0, ~3, ~0, ~0] as [UInt])) + NBKAssertSubtractionByDigit(T(words:[ 0, ~0, ~0, ~0] as [UInt]), UInt(3), Int(1), T(words:[ 0, ~3, ~0, ~0] as [UInt])) + NBKAssertSubtractionByDigit(T(words:[ 0, 0, ~0, ~0] as [UInt]), UInt(3), Int(1), T(words:[ 0, ~2, ~1, ~0] as [UInt])) + NBKAssertSubtractionByDigit(T(words:[ 0, 0, 0, ~0] as [UInt]), UInt(3), Int(1), T(words:[ 0, ~2, ~0, ~1] as [UInt])) + } + + func testSubtractingDigitAtIndexReportingOverflow() { + NBKAssertSubtractionByDigit(T(words:[ 1, 2, 3, 0] as [UInt]), UInt(5), Int(0), T(words:[~3, 1, 3, 0] as [UInt])) + NBKAssertSubtractionByDigit(T(words:[ 1, 2, 3, 0] as [UInt]), UInt(5), Int(1), T(words:[ 1, ~2, 2, 0] as [UInt])) + NBKAssertSubtractionByDigit(T(words:[ 1, 2, 3, 0] as [UInt]), UInt(5), Int(2), T(words:[ 1, 2, ~1, 0] as [UInt]), true) + NBKAssertSubtractionByDigit(T(words:[ 1, 2, 3, 0] as [UInt]), UInt(5), Int(3), T(words:[ 1, 2, 3, ~4] as [UInt]), true) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Miscellaneous + //=------------------------------------------------------------------------= + + func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { + func becauseThisCompilesSuccessfully(_ x: inout T) { + XCTAssertNotNil(x -= 0) + XCTAssertNotNil(x.subtractReportingOverflow(0, at: 0)) + + XCTAssertNotNil(x - 0) + XCTAssertNotNil(x.subtractingReportingOverflow(0, at: 0)) + } + } +} + +#endif diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Text.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Text.swift new file mode 100644 index 00000000..dfcf1985 --- /dev/null +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Text.swift @@ -0,0 +1,241 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +import NBKFlexibleWidthKit +import XCTest + +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x UIntXL x Text +//*============================================================================* + +final class UIntXLTestsOnText: XCTestCase { + + typealias T = UIntXL + + //=------------------------------------------------------------------------= + // MARK: State + //=------------------------------------------------------------------------= + + let bit256 = 256 as Int + let min256 = T(x64: X(repeating: UInt64.min, count: 4)) + let max256 = T(x64: X(repeating: UInt64.max, count: 4)) + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testInitDescription() { + XCTAssertEqual(T( "10"), 10) + XCTAssertEqual(T( "+10"), 10) + XCTAssertEqual(T( "-10"), nil) + XCTAssertEqual(T( " 10"), nil) + + XCTAssertEqual(T( "0x10"), nil) + XCTAssertEqual(T("+0x10"), nil) + XCTAssertEqual(T("-0x10"), nil) + XCTAssertEqual(T(" 0x10"), nil) + } + + func testInstanceDescriptionUsesRadix10() { + XCTAssertEqual("10", T(10).description) + XCTAssertEqual("10", String(describing: T(10))) + } + + func testMetaTypeDescriptionIsSimple() { + XCTAssertEqual("UIntXL", T.description) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Decode + //=------------------------------------------------------------------------= + + func testDecodingRadix02() { + NBKAssertDecodeText(min256, 02, "0") + NBKAssertDecodeText(max256, 02, String(repeating: "1", count: bit256 / 1)) + } + + func testDecodingRadix03() { + NBKAssertDecodeText(min256, 03, "0" ) + NBKAssertDecodeText(max256, 03, "120220022011" + + "02222202122221121112210000122122012000200021102211" + + "02022111210012120210102102000200101210112021202111" + + "10021000020122121222212000211211110200012022202120" ) + } + + func testDecodingRadix04() { + NBKAssertDecodeText(min256, 04, "0") + NBKAssertDecodeText(max256, 04, String(repeating: "3", count: bit256 / 2)) + } + + func testDecodingRadix08() { + NBKAssertDecodeText(min256, 08, "0") + NBKAssertDecodeText(max256, 08, "1" + String(repeating: "7", count: 85)) + } + + func testDecodingRadix10() { + NBKAssertDecodeText(min256, 10, "0") + NBKAssertDecodeText(max256, 10, "115792089237316195423570985008687907853269984665640564039457584007913129639935") + } + + func testDecodingRadix16() { + NBKAssertDecodeText(min256, 16, "0") + NBKAssertDecodeText(max256, 16, String(repeating: "f", count: bit256 / 4)) + } + + func testDecodingRadix32() { + NBKAssertDecodeText(min256, 32, "0") + NBKAssertDecodeText(max256, 32, "1" + String(repeating: "v", count: 51)) + } + + func testDecodingRadix36() { + NBKAssertDecodeText(min256, 36, "0") + NBKAssertDecodeText(max256, 36, "6dp5qcb22im238nr3wvp0ic7q99w035jmy2iw7i6n43d37jtof") + } + + func testDecodingRadixLiteralAsNumber() { + NBKAssertDecodeText(T(33), 36, "0x") + NBKAssertDecodeText(T(24), 36, "0o") + NBKAssertDecodeText(T(11), 36, "0b") + + NBKAssertDecodeText(T(33), 36, "+0x") + NBKAssertDecodeText(T(24), 36, "+0o") + NBKAssertDecodeText(T(11), 36, "+0b") + } + + func testDecodingRadixLiteralAsRadixReturnsNil() { + NBKAssertDecodeText(T?.none, 10, "0x10") + NBKAssertDecodeText(T?.none, 10, "0o10") + NBKAssertDecodeText(T?.none, 10, "0b10") + + NBKAssertDecodeText(T?.none, 10, "+0x10") + NBKAssertDecodeText(T?.none, 10, "+0o10") + NBKAssertDecodeText(T?.none, 10, "+0b10") + } + + func testDecodingStringsWithAndWithoutSign() { + NBKAssertDecodeText(T(1234567890), 10, "1234567890") + NBKAssertDecodeText(T(1234567890), 10, "+1234567890") + } + + func testDecodingStrategyIsCaseInsensitive() { + NBKAssertDecodeText(T(0xabcdef), 16, "abcdef") + NBKAssertDecodeText(T(0xABCDEF), 16, "ABCDEF") + NBKAssertDecodeText(T(0xaBcDeF), 16, "aBcDeF") + NBKAssertDecodeText(T(0xAbCdEf), 16, "AbCdEf") + } + + func testDecodingUnalignedStringsIsOK() { + NBKAssertDecodeText(T(1), 10, "1") + NBKAssertDecodeText(T(1), 16, "1") + } + + func testDecodingPrefixingZerosHasNoEffect() { + let zero = String(repeating: "0", count: bit256) + "0" + let one = String(repeating: "0", count: bit256) + "1" + + for radix in 02 ... 36 { + NBKAssertDecodeText(T(0), radix, zero) + NBKAssertDecodeText(T(1), radix, one ) + } + } + + func testDecodingInvalidCharactersReturnsNil() { + NBKAssertDecodeText(T?.none, 16, "/") + NBKAssertDecodeText(T?.none, 16, "G") + + NBKAssertDecodeText(T?.none, 10, "/") + NBKAssertDecodeText(T?.none, 10, ":") + + NBKAssertDecodeText(T?.none, 10, String(repeating: "1", count: 19) + "/") + NBKAssertDecodeText(T?.none, 10, String(repeating: "1", count: 19) + ":") + } + + func testDecodingStringsWithoutDigitsReturnsNil() { + NBKAssertDecodeText(T?.none, 10, "") + NBKAssertDecodeText(T?.none, 10, "+") + NBKAssertDecodeText(T?.none, 10, "-") + NBKAssertDecodeText(T?.none, 10, "~") + + NBKAssertDecodeText(T?.none, 16, "") + NBKAssertDecodeText(T?.none, 16, "+") + NBKAssertDecodeText(T?.none, 16, "-") + NBKAssertDecodeText(T?.none, 16, "~") + } + + func testDecodingValuesOutsideOfRepresentableRangeReturnsNil() { + let positive = "+" + String(repeating: "1", count: bit256 + 1) + let negative = "-" + String(repeating: "1", count: 1) + + for radix in 02 ... 36 { + XCTAssertNotNil(T(positive, radix: radix)) + NBKAssertDecodeText(T?.none, radix, negative) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Encode + //=------------------------------------------------------------------------= + + func testEncodingRadix02() { + NBKAssertEncodeText(min256, 02, false, "0") + NBKAssertEncodeText(max256, 02, false, String(repeating: "1", count: bit256 / 1)) + } + + func testEncodingRadix03() { + NBKAssertEncodeText(min256, 03, false, "0" ) + NBKAssertEncodeText(max256, 03, false,"120220022011" + + "02222202122221121112210000122122012000200021102211" + + "02022111210012120210102102000200101210112021202111" + + "10021000020122121222212000211211110200012022202120" ) + } + + func testEncodingRadix04() { + NBKAssertEncodeText(min256, 04, false, "0") + NBKAssertEncodeText(max256, 04, false, String(repeating: "3", count: bit256 / 2)) + } + + func testEncodingRadix08() { + NBKAssertEncodeText(min256, 08, false, "0") + NBKAssertEncodeText(max256, 08, false, "1" + String(repeating: "7", count: 85)) + } + + func testEncodingRadix10() { + NBKAssertEncodeText(min256, 10, false, "0") + NBKAssertEncodeText(max256, 10, false, "115792089237316195423570985008687907853269984665640564039457584007913129639935") + } + + func testEncodingRadix16() { + NBKAssertEncodeText(min256, 16, false, "0") + NBKAssertEncodeText(min256, 16, true , "0") + NBKAssertEncodeText(max256, 16, false, String(repeating: "f", count: bit256 / 4)) + NBKAssertEncodeText(max256, 16, true , String(repeating: "F", count: bit256 / 4)) + } + + func testEncodingRadix32() { + NBKAssertEncodeText(min256, 32, false, "0") + NBKAssertEncodeText(min256, 32, true , "0") + NBKAssertEncodeText(max256, 32, false, "1" + String(repeating: "v", count: 51)) + NBKAssertEncodeText(max256, 32, true , "1" + String(repeating: "V", count: 51)) + } + + func testEncodingRadix36() { + NBKAssertEncodeText(min256, 36, false, "0") + NBKAssertEncodeText(min256, 36, true , "0") + NBKAssertEncodeText(max256, 36, false, "6dp5qcb22im238nr3wvp0ic7q99w035jmy2iw7i6n43d37jtof") + NBKAssertEncodeText(max256, 36, true , "6DP5QCB22IM238NR3WVP0IC7Q99W035JMY2IW7I6N43D37JTOF") + } +} + +#endif diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Words.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Words.swift new file mode 100644 index 00000000..ad38587f --- /dev/null +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Words.swift @@ -0,0 +1,73 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +import NBKFlexibleWidthKit +import XCTest + +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x UIntXL x Words +//*============================================================================* + +final class UIntXLTestsOnWords: XCTestCase { + + typealias T = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testWords() { + NBKAssertWords(T(words:[ ]), [0 ]) + NBKAssertWords(T(words:[0 ]), [0 ]) + NBKAssertWords(T(words:[1 ]), [1 ]) + NBKAssertWords(T(words:[1, 2 ]), [1, 2 ]) + NBKAssertWords(T(words:[1, 2, 3 ]), [1, 2, 3 ]) + NBKAssertWords(T(words:[1, 2, 3, 4]), [1, 2, 3, 4]) + + NBKAssertWords(T(words:[0, 0, 0, 0]), [0 ]) + NBKAssertWords(T(words:[1, 0, 0, 0]), [1 ]) + NBKAssertWords(T(words:[1, 2, 0, 0]), [1, 2 ]) + NBKAssertWords(T(words:[1, 2, 3, 0]), [1, 2, 3 ]) + NBKAssertWords(T(words:[1, 2, 3, 4]), [1, 2, 3, 4]) + } + + func testWordsX64() throws { + guard MemoryLayout.size == MemoryLayout.size else { throw XCTSkip() } + + NBKAssertWords(T(x64: [ ] as X), [0 ]) + NBKAssertWords(T(x64: [0, 0, 0, 0] as X), [0 ]) + NBKAssertWords(T(x64: [1, 0, 0, 0] as X), [1 ]) + NBKAssertWords(T(x64: [1, 2, 0, 0] as X), [1, 2 ]) + NBKAssertWords(T(x64: [1, 2, 3, 0] as X), [1, 2, 3 ]) + NBKAssertWords(T(x64: [1, 2, 3, 4] as X), [1, 2, 3, 4]) + } + + func testWordsX32() throws { + guard MemoryLayout.size == MemoryLayout.size else { throw XCTSkip() } + + NBKAssertWords(T(x32: [ ] as Y), [0 ]) + NBKAssertWords(T(x32: [0, 0, 0, 0, 0, 0, 0, 0] as Y), [0 ]) + NBKAssertWords(T(x32: [1, 0, 0, 0, 0, 0, 0, 0] as Y), [1 ]) + NBKAssertWords(T(x32: [1, 2, 0, 0, 0, 0, 0, 0] as Y), [1, 2 ]) + NBKAssertWords(T(x32: [1, 2, 3, 0, 0, 0, 0, 0] as Y), [1, 2, 3 ]) + NBKAssertWords(T(x32: [1, 2, 3, 4, 0, 0, 0, 0] as Y), [1, 2, 3, 4 ]) + NBKAssertWords(T(x32: [1, 2, 3, 4, 5, 0, 0, 0] as Y), [1, 2, 3, 4, 5 ]) + NBKAssertWords(T(x32: [1, 2, 3, 4, 5, 6, 0, 0] as Y), [1, 2, 3, 4, 5, 6 ]) + NBKAssertWords(T(x32: [1, 2, 3, 4, 5, 6, 7, 0] as Y), [1, 2, 3, 4, 5, 6, 7 ]) + NBKAssertWords(T(x32: [1, 2, 3, 4, 5, 6, 7, 8] as Y), [1, 2, 3, 4, 5, 6, 7, 8]) + } +} + +#endif diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth.swift new file mode 100644 index 00000000..b9734c3e --- /dev/null +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth.swift @@ -0,0 +1,80 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit +import NBKFlexibleWidthKit +import XCTest + +//*============================================================================* +// MARK: * NBK x Flexible Width x Initializers x Unsigned +//*============================================================================* + +extension NBKFlexibleWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Details x Limbs + //=------------------------------------------------------------------------= + + init(x32 limbs: [UInt32]) { + self.init(limbs: limbs) + } + + init(x64 limbs: [UInt64]) { + self.init(limbs: limbs) + } + + //=------------------------------------------------------------------------= + // MARK: Details x Limbs x Private + //=------------------------------------------------------------------------= + + private init(limbs: [Limb]) where Limb: NBKCoreInteger { + switch Limb.bitWidth >= UInt.bitWidth { + case true: self.init(majorLimbs: limbs) + case false: self.init(minorLimbs: limbs) } + } + + private init(majorLimbs: [Limb]) where Limb: NBKCoreInteger { + precondition(Limb.bitWidth.isPowerOf2) + precondition(Limb.bitWidth >= UInt.bitWidth) + //=--------------------------------------= + let ratio = Limb.bitWidth / UInt.bitWidth + let count = majorLimbs.count * ratio + var words = [UInt](); words.reserveCapacity(count) + //=--------------------------------------= + for limb in majorLimbs { + words.append(contentsOf: limb.words) + } + //=--------------------------------------= + self.init(words: words) + } + + private init(minorLimbs: [Limb]) where Limb: NBKCoreInteger { + precondition(Limb.bitWidth.isPowerOf2) + precondition(Limb.bitWidth <= UInt.bitWidth) + //=--------------------------------------= + let ratio = UInt.bitWidth / Limb.bitWidth + let count = minorLimbs.count / ratio + var words = [UInt](repeating: UInt.zero, count: count) + //=--------------------------------------= + var major = Int.zero + var minor = Int.zero + + for limb in minorLimbs { + words[major] |= UInt(truncatingIfNeeded: limb) &<< minor + minor += Limb.bitWidth + + if minor >= UInt.bitWidth { + minor -= UInt.bitWidth + major += 1 + } + } + //=--------------------------------------= + self.init(words: words) + } +} diff --git a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Addition.swift b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Addition.swift new file mode 100644 index 00000000..f2318c6c --- /dev/null +++ b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Addition.swift @@ -0,0 +1,42 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit +import NBKFlexibleWidthKit +import XCTest + +//*============================================================================* +// MARK: * NBK x Assert x Addition +//*============================================================================* + +func NBKAssertAddition( +_ lhs: UIntXL, _ rhs: UIntXL, _ index: Int, _ partialValue: UIntXL, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + if index.isZero { + XCTAssertEqual( lhs + rhs, partialValue, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs += rhs; return lhs }(), partialValue, file: file, line: line) + } + //=------------------------------------------= + XCTAssertEqual(lhs.adding(rhs, at: index), partialValue, file: file, line: line) + XCTAssertEqual({ var x = lhs; let _ = x.add(rhs, at: index); return x }(), partialValue, file: file, line: line) +} + +func NBKAssertAdditionByDigit( +_ lhs: UIntXL, _ rhs: UIntXL.Digit, _ index: Int, _ partialValue: UIntXL, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + if index.isZero { + XCTAssertEqual( lhs + rhs, partialValue, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs += rhs; return lhs }(), partialValue, file: file, line: line) + } + //=------------------------------------------= + XCTAssertEqual(lhs.adding(rhs, at: index), partialValue, file: file, line: line) + XCTAssertEqual({ var x = lhs; let _ = x.add(rhs, at: index); return x }(), partialValue, file: file, line: line) +} diff --git a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Comparisons.swift b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Comparisons.swift new file mode 100644 index 00000000..fed6311c --- /dev/null +++ b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Comparisons.swift @@ -0,0 +1,31 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit +import NBKFlexibleWidthKit +import XCTest + +//*============================================================================* +// MARK: * NBK x Assert x Comparisons +//*============================================================================* + +func NBKAssertComparisons( +_ lhs: T, _ rhs: T, _ result: Int, +file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual(lhs == rhs, result == 0, file: file, line: line) + XCTAssertEqual(lhs != rhs, result != 0, file: file, line: line) + + XCTAssertEqual(lhs < rhs, result == -1, file: file, line: line) + XCTAssertEqual(lhs <= rhs, result != 1, file: file, line: line) + + XCTAssertEqual(lhs > rhs, result == 1, file: file, line: line) + XCTAssertEqual(lhs >= rhs, result != -1, file: file, line: line) + + XCTAssertEqual(lhs.compared(to: rhs), result, file: file, line: line) +} diff --git a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Division.swift b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Division.swift new file mode 100644 index 00000000..d4374033 --- /dev/null +++ b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Division.swift @@ -0,0 +1,81 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit +import NBKFlexibleWidthKit +import XCTest + +//*============================================================================* +// MARK: * NBK x Assert x Division +//*============================================================================* + +func NBKAssertDivision( +_ lhs: UIntXL, _ rhs: UIntXL, _ quotient: UIntXL, _ remainder: UIntXL, _ overflow: Bool = false, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + if !overflow { + XCTAssertEqual(lhs / rhs, quotient, file: file, line: line) + XCTAssertEqual(lhs % rhs, remainder, file: file, line: line) + + XCTAssertEqual({ var x = lhs; x /= rhs; return x }(), quotient, file: file, line: line) + XCTAssertEqual({ var x = lhs; x %= rhs; return x }(), remainder, file: file, line: line) + + XCTAssertEqual(lhs.quotientAndRemainder(dividingBy: rhs).quotient, quotient, file: file, line: line) + XCTAssertEqual(lhs.quotientAndRemainder(dividingBy: rhs).remainder, remainder, file: file, line: line) + } + //=------------------------------------------= + XCTAssertEqual(lhs.dividedReportingOverflow(by: rhs).partialValue, quotient, file: file, line: line) + XCTAssertEqual(lhs.dividedReportingOverflow(by: rhs).overflow, overflow, file: file, line: line) + + XCTAssertEqual({ var x = lhs; let _ = x.divideReportingOverflow(by: rhs); return x }(), quotient, file: file, line: line) + XCTAssertEqual({ var x = lhs; let o = x.divideReportingOverflow(by: rhs); return o }(), overflow, file: file, line: line) + + XCTAssertEqual(lhs.remainderReportingOverflow(dividingBy: rhs).partialValue, remainder, file: file, line: line) + XCTAssertEqual(lhs.remainderReportingOverflow(dividingBy: rhs).overflow, overflow, file: file, line: line) + + XCTAssertEqual({ var x = lhs; let _ = x.formRemainderReportingOverflow(dividingBy: rhs); return x }(), remainder, file: file, line: line) + XCTAssertEqual({ var x = lhs; let o = x.formRemainderReportingOverflow(dividingBy: rhs); return o }(), overflow, file: file, line: line) + + XCTAssertEqual(lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs).partialValue.quotient, quotient, file: file, line: line) + XCTAssertEqual(lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs).partialValue.remainder, remainder, file: file, line: line) + XCTAssertEqual(lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs).overflow, overflow, file: file, line: line) +} + +func NBKAssertDivisionByDigit( +_ lhs: UIntXL, _ rhs: UIntXL.Digit, _ quotient: UIntXL, _ remainder: UIntXL.Digit, _ overflow: Bool = false, +file: StaticString = #file, line: UInt = #line) { + let extended = UIntXL(digit: remainder) + //=------------------------------------------= + if !overflow { + XCTAssertEqual(lhs / rhs, quotient, file: file, line: line) + XCTAssertEqual(lhs % rhs, remainder, file: file, line: line) + + XCTAssertEqual({ var x = lhs; x /= rhs; return x }(), quotient, file: file, line: line) + XCTAssertEqual({ var x = lhs; x %= rhs; return x }(), extended, file: file, line: line) + + XCTAssertEqual(lhs.quotientAndRemainder(dividingBy: rhs).quotient, quotient, file: file, line: line) + XCTAssertEqual(lhs.quotientAndRemainder(dividingBy: rhs).remainder, remainder, file: file, line: line) + } + //=------------------------------------------= + XCTAssertEqual(lhs.dividedReportingOverflow(by: rhs).partialValue, quotient, file: file, line: line) + XCTAssertEqual(lhs.dividedReportingOverflow(by: rhs).overflow, overflow, file: file, line: line) + + XCTAssertEqual({ var x = lhs; let _ = x.divideReportingOverflow(by: rhs); return x }(), quotient, file: file, line: line) + XCTAssertEqual({ var x = lhs; let o = x.divideReportingOverflow(by: rhs); return o }(), overflow, file: file, line: line) + + XCTAssertEqual(lhs.remainderReportingOverflow(dividingBy: rhs).partialValue, remainder, file: file, line: line) + XCTAssertEqual(lhs.remainderReportingOverflow(dividingBy: rhs).overflow, overflow, file: file, line: line) + + XCTAssertEqual({ var x = lhs; let _ = x.formRemainderReportingOverflow(dividingBy: rhs); return x }(), extended, file: file, line: line) + XCTAssertEqual({ var x = lhs; let o = x.formRemainderReportingOverflow(dividingBy: rhs); return o }(), overflow, file: file, line: line) + + XCTAssertEqual(lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs).partialValue.quotient, quotient, file: file, line: line) + XCTAssertEqual(lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs).partialValue.remainder, remainder, file: file, line: line) + XCTAssertEqual(lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs).overflow, overflow, file: file, line: line) +} diff --git a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Logic.swift b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Logic.swift new file mode 100644 index 00000000..1bf9eef1 --- /dev/null +++ b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Logic.swift @@ -0,0 +1,54 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit +import NBKFlexibleWidthKit +import XCTest + +//*============================================================================* +// MARK: * NBK x Assert x Logic +//*============================================================================* + +func NBKAssertNot( +_ operand: T, _ result: T, +file: StaticString = #file, line: UInt = #line) { + if operand.words.last != UInt.max { + XCTAssertEqual(~operand, result, file: file, line: line) + XCTAssertEqual(~result, operand, file: file, line: line) + } else { + XCTAssertEqual(~operand, result, file: file, line: line) + } +} + +func NBKAssertAnd( +_ lhs: T, _ rhs: T, _ result: T, +file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual( lhs & rhs, result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs &= rhs; return lhs }(), result, file: file, line: line) + XCTAssertEqual( rhs & lhs, result, file: file, line: line) + XCTAssertEqual({ var rhs = rhs; rhs &= lhs; return rhs }(), result, file: file, line: line) +} + +func NBKAssertOr( +_ lhs: T, _ rhs: T, _ result: T, +file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual( lhs | rhs, result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs |= rhs; return lhs }(), result, file: file, line: line) + XCTAssertEqual( rhs | lhs, result, file: file, line: line) + XCTAssertEqual({ var rhs = rhs; rhs |= lhs; return rhs }(), result, file: file, line: line) +} + +func NBKAssertXor( +_ lhs: T, _ rhs: T, _ result: T, +file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual( lhs ^ rhs, result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs ^= rhs; return lhs }(), result, file: file, line: line) + XCTAssertEqual( rhs ^ lhs, result, file: file, line: line) + XCTAssertEqual({ var rhs = rhs; rhs ^= lhs; return rhs }(), result, file: file, line: line) +} diff --git a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Multiplication.swift b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Multiplication.swift new file mode 100644 index 00000000..9d2d0013 --- /dev/null +++ b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Multiplication.swift @@ -0,0 +1,36 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit +@testable import NBKFlexibleWidthKit +import XCTest + +//*============================================================================* +// MARK: * NBK x Assert x Multiplication +//*============================================================================* + +func NBKAssertMultiplication( +_ lhs: UIntXL, _ rhs: UIntXL, _ result: UIntXL, +file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual( lhs * rhs, result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs *= rhs; return lhs }(), result, file: file, line: line) + + XCTAssertEqual(lhs.multiplied(by: rhs), result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs.multiply(by: rhs); return lhs }(), result, file: file, line: line) +} + +func NBKAssertMultiplicationByDigit( +_ lhs: UIntXL, _ rhs: UIntXL.Digit, _ result: UIntXL, +file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual( lhs * rhs, result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs *= rhs; return lhs }(), result, file: file, line: line) + + XCTAssertEqual(lhs.multiplied(by: rhs), result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs.multiply(by: rhs); return lhs }(), result, file: file, line: line) +} diff --git a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Numbers.swift b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Numbers.swift new file mode 100644 index 00000000..55a20dd3 --- /dev/null +++ b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Numbers.swift @@ -0,0 +1,53 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit +import NBKFlexibleWidthKit +import XCTest + +//*============================================================================* +// MARK: * NBK x Assert x Numbers +//*============================================================================* + +func NBKAssertNumbers( +from value: I, default: O, +file: StaticString = #file, line: UInt = #line) { + NBKAssertNumbers(from: value, exactly: `default`, clamping: `default`, truncating: `default`, file: file, line: line) +} + +func NBKAssertNumbers( +from value: I, default: O, exactly: O?, +file: StaticString = #file, line: UInt = #line) { + NBKAssertNumbers(from: value, exactly: exactly, clamping: `default`, truncating: `default`, file: file, line: line) +} + +func NBKAssertNumbers( +from value: I, default: O, clamping: O, +file: StaticString = #file, line: UInt = #line) { + NBKAssertNumbers(from: value, exactly: `default`, clamping: clamping, truncating: `default`, file: file, line: line) +} + +func NBKAssertNumbers( +from value: I, default: O, truncating: O, +file: StaticString = #file, line: UInt = #line) { + NBKAssertNumbers(from: value, exactly: `default`, clamping: `default`, truncating: truncating, file: file, line: line) +} + +func NBKAssertNumbers( +from value: I, exactly: O?, clamping: O, truncating: O, +file: StaticString = #file, line: UInt = #line) { + //=--------------------------------------= + if let exactly = exactly { + XCTAssertEqual(O(value), exactly, file: file, line: line) + } + //=--------------------------------------= + XCTAssertEqual(O(exactly: value), exactly, file: file, line: line) + XCTAssertEqual(O(clamping: value), clamping, file: file, line: line) + XCTAssertEqual(O(truncatingIfNeeded: value), truncating, file: file, line: line) +} diff --git a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Shifts.swift b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Shifts.swift new file mode 100644 index 00000000..55dfcb43 --- /dev/null +++ b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Shifts.swift @@ -0,0 +1,80 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit +import NBKFlexibleWidthKit +import XCTest + +//*============================================================================* +// MARK: * NBK x Assert x Shifts +//*============================================================================* + +func NBKAssertShiftLeft( +_ lhs: UIntXL, _ rhs: Int, _ result: UIntXL, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + let (words, bits) = rhs.quotientAndRemainder(dividingBy: UInt.bitWidth) + //=------------------------------------------= + XCTAssertEqual( lhs << rhs, result, file: file, line: line) + XCTAssertEqual( lhs >> -rhs, result, file: file, line: line) + + XCTAssertEqual({ var lhs = lhs; lhs <<= rhs; return lhs }(), result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs >>= -rhs; return lhs }(), result, file: file, line: line) + + XCTAssertEqual(lhs.bitshiftedLeftSmart(by: rhs), result, file: file, line: line) + XCTAssertEqual(lhs.bitshiftedRightSmart(by: -rhs), result, file: file, line: line) + + XCTAssertEqual({ var lhs = lhs; lhs.bitshiftLeftSmart(by: rhs); return lhs }(), result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs.bitshiftRightSmart(by: -rhs); return lhs }(), result, file: file, line: line) + //=------------------------------------------= + if 0 ..< lhs.bitWidth ~= rhs { + XCTAssertEqual(lhs.bitshiftedLeft(by: rhs), result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs.bitshiftLeft(by: rhs); return lhs }(), result, file: file, line: line) + + XCTAssertEqual(lhs.bitshiftedLeft(words: words, bits: bits), result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs.bitshiftLeft(words: words, bits: bits); return lhs }(), result, file: file, line: line) + } + //=------------------------------------------= + if 0 ..< lhs.bitWidth ~= rhs, bits.isZero { + XCTAssertEqual(lhs.bitshiftedLeft(words: words), result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs.bitshiftLeft(words: words); return lhs }(), result, file: file, line: line) + } +} + +func NBKAssertShiftRight( +_ lhs: UIntXL, _ rhs: Int, _ result: UIntXL, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + let (words, bits) = rhs.quotientAndRemainder(dividingBy: UInt.bitWidth) + //=------------------------------------------= + XCTAssertEqual( lhs >> rhs, result, file: file, line: line) + XCTAssertEqual( lhs << -rhs, result, file: file, line: line) + + XCTAssertEqual({ var lhs = lhs; lhs >>= rhs; return lhs }(), result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs <<= -rhs; return lhs }(), result, file: file, line: line) + + XCTAssertEqual(lhs.bitshiftedRightSmart(by: rhs), result, file: file, line: line) + XCTAssertEqual(lhs.bitshiftedLeftSmart(by: -rhs), result, file: file, line: line) + + XCTAssertEqual({ var lhs = lhs; lhs.bitshiftRightSmart(by: rhs); return lhs }(), result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs.bitshiftLeftSmart(by: -rhs); return lhs }(), result, file: file, line: line) + //=------------------------------------------= + if 0 ..< lhs.bitWidth ~= rhs { + XCTAssertEqual(lhs.bitshiftedRight(by: rhs), result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs.bitshiftRight(by: rhs); return lhs }(), result, file: file, line: line) + + XCTAssertEqual(lhs.bitshiftedRight(words: words, bits: bits), result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs.bitshiftRight(words: words, bits: bits); return lhs }(), result, file: file, line: line) + } + //=------------------------------------------= + if 0 ..< lhs.bitWidth ~= rhs, bits.isZero { + XCTAssertEqual(lhs.bitshiftedRight(words: words), result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs.bitshiftRight(words: words); return lhs }(), result, file: file, line: line) + } +} diff --git a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Subtraction.swift b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Subtraction.swift new file mode 100644 index 00000000..28b1ac45 --- /dev/null +++ b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Subtraction.swift @@ -0,0 +1,48 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit +import NBKFlexibleWidthKit +import XCTest + +//*============================================================================* +// MARK: * NBK x Assert x Subtraction +//*============================================================================* + +func NBKAssertSubtraction( +_ lhs: UIntXL, _ rhs: UIntXL, _ index: Int, _ partialValue: UIntXL, _ overflow: Bool = false, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + if !overflow, index.isZero { + XCTAssertEqual( lhs - rhs, partialValue, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs -= rhs; return lhs }(), partialValue, file: file, line: line) + } + //=------------------------------------------= + XCTAssertEqual(lhs.subtractingReportingOverflow(rhs, at: index).partialValue, partialValue, file: file, line: line) + XCTAssertEqual(lhs.subtractingReportingOverflow(rhs, at: index).overflow, overflow, file: file, line: line) + + XCTAssertEqual({ var x = lhs; let _ = x.subtractReportingOverflow(rhs, at: index); return x }(), partialValue, file: file, line: line) + XCTAssertEqual({ var x = lhs; let o = x.subtractReportingOverflow(rhs, at: index); return o }(), overflow, file: file, line: line) +} + +func NBKAssertSubtractionByDigit( +_ lhs: UIntXL, _ rhs: UIntXL.Digit, _ index: Int, _ partialValue: UIntXL, _ overflow: Bool = false, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + if !overflow, index.isZero { + XCTAssertEqual( lhs - rhs, partialValue, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs -= rhs; return lhs }(), partialValue, file: file, line: line) + } + //=------------------------------------------= + XCTAssertEqual(lhs.subtractingReportingOverflow(rhs, at: index).partialValue, partialValue, file: file, line: line) + XCTAssertEqual(lhs.subtractingReportingOverflow(rhs, at: index).overflow, overflow, file: file, line: line) + + XCTAssertEqual({ var x = lhs; let _ = x.subtractReportingOverflow(rhs, at: index); return x }(), partialValue, file: file, line: line) + XCTAssertEqual({ var x = lhs; let o = x.subtractReportingOverflow(rhs, at: index); return o }(), overflow, file: file, line: line) +} diff --git a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Text.swift b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Text.swift new file mode 100644 index 00000000..094039e5 --- /dev/null +++ b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Text.swift @@ -0,0 +1,41 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit +import NBKFlexibleWidthKit +import XCTest + +//*============================================================================* +// MARK: * NBK x Assert x Text +//*============================================================================* + +func NBKAssertDecodeText( +_ integer: UIntXL?, _ radix: Int, _ text: String, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + if radix == 10 { + XCTAssertEqual(UIntXL(text), integer, file: file, line: line) + } + //=------------------------------------------= + XCTAssertEqual(UIntXL(text, radix: radix), integer, file: file, line: line) +} + +func NBKAssertEncodeText( +_ integer: UIntXL, _ radix: Int, _ uppercase: Bool, _ text: String, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + if radix == 10, uppercase == false { + XCTAssertEqual(String(integer), text, file: file, line: line) + XCTAssertEqual(integer.description, text, file: file, line: line) + XCTAssertEqual(integer.description(), text, file: file, line: line) + } + //=------------------------------------------= + XCTAssertEqual(String(integer, radix: radix, uppercase: uppercase), text, file: file, line: line) + XCTAssertEqual(integer.description(radix: radix, uppercase: uppercase), text, file: file, line: line) +} diff --git a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Words.swift b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Words.swift new file mode 100644 index 00000000..59166c6d --- /dev/null +++ b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Words.swift @@ -0,0 +1,22 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit +import NBKFlexibleWidthKit +import XCTest + +//*============================================================================* +// MARK: * NBK x Assert x Words +//*============================================================================* + +func NBKAssertWords( +_ integer: T, _ words: [UInt], +file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual(Array(integer.words), words, file: file, line: line) +} From 707796bf552d12b1e98bbbcf5fa074f0ad57675e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Fri, 14 Jul 2023 22:28:07 +0200 Subject: [PATCH 002/133] NBKFlexibleWidthKit: Cleanup. --- .../NBKFlexibleWidth+Comparisons.swift | 35 ++++++-- .../NBKFlexibleWidth+Division.swift | 83 +++++++++---------- 2 files changed, 67 insertions(+), 51 deletions(-) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift index 6887cbb9..e661e373 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift @@ -68,14 +68,39 @@ extension NBKFlexibleWidth.Magnitude { } @inlinable public func compared(to other: Self) -> Int { + self .storage.withUnsafeBufferPointer { lhs in + other.storage.withUnsafeBufferPointer { rhs in + Self.compareWordsUnchecked(lhs, to: rhs) + }} + } + + @inlinable public func compared(to other: Self, at index: Int) -> Int { + self .storage.withUnsafeBufferPointer { lhs in + other.storage.withUnsafeBufferPointer { rhs in + let partition = Swift.min(lhs.count - 1, index) + let suffix = NBK.UnsafeWords(rebasing: lhs.suffix(from: partition)) + let comparison = Self.compareWordsUnchecked(suffix, to: rhs) + if !comparison.isZero { return comparison } + let prefix = NBK.UnsafeWords(rebasing: lhs.prefix(upTo: partition)) + return Int(bit: !prefix.allSatisfy({ $0.isZero })) + }} + } + + //=------------------------------------------------------------------------= + // MARK: Utilities x Private + //=------------------------------------------------------------------------= + + @inlinable static func compareWordsUnchecked(_ lhs: NBK.UnsafeWords, to rhs: NBK.UnsafeWords) -> Int { + assert(lhs.count == 1 || !lhs.last!.isZero) + assert(rhs.count == 1 || !rhs.last!.isZero) //=--------------------------------------= - if self.storage.count != other.storage.count { - return self.storage.count < other.storage.count ? -1 : 1 + if lhs.count != rhs.count { + return lhs.count < rhs.count ? -1 : 1 } //=--------------------------------------= - for index in self.storage.indices.reversed() { - let lhsWord: UInt = self .storage[index] - let rhsWord: UInt = other.storage[index] + for index in lhs.indices.reversed() { + let lhsWord = lhs[index] as UInt + let rhsWord = rhs[index] as UInt if lhsWord != rhsWord { return lhsWord < rhsWord ? -1 : 1 } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift index ec1e325f..6f416025 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift @@ -57,20 +57,15 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @inlinable func quotientAndRemainderReportingOverflowAsNormal(dividingBy other: Self) -> PVO> { - let otherMinLastIndex = other.storage.index(before: other.storage.endIndex) - //=--------------------------------------= - // divisor is zero - //=--------------------------------------= - if other.isZero { - return PVO(QR(self, self), true) - } //=--------------------------------------= // divisor is one word //=--------------------------------------= if other.storage.count == 1 { + // TODO: test truncation semantcs let divisor = other.storage.first! as UInt - let qro: PVO> = self.quotientAndRemainderReportingOverflow(dividingBy: divisor) - return PVO(QR(qro.partialValue.quotient, Self(digit: qro.partialValue.remainder)), qro.overflow) + let qro = self.quotientAndRemainderReportingOverflow(dividingBy: divisor) + let remainder = qro.overflow ? self : Self(digit: qro.partialValue.remainder) + return PVO(QR(qro.partialValue.quotient, remainder), qro.overflow) } //=--------------------------------------= // divisor is greater than or equal @@ -79,52 +74,48 @@ extension NBKFlexibleWidth.Magnitude { return self == other ? PVO(QR(1, Self.zero), false) : PVO(QR(Self.zero, self), false) } //=--------------------------------------= - let gap = self.storage.count - other.storage.count as Int - let shift = other.storage.last!.leadingZeroBitCount as Int - //=--------------------------------------= // shift to clamp approximation //=--------------------------------------= - var remainder = self .bitshiftedLeft(words: 000, bits: shift) as Self - var increment = other.bitshiftedLeft(words: gap, bits: shift) as Self - let discriminant = increment.storage.last! as UInt - assert(discriminant.mostSignificantBit) + let shift = other.storage.last!.leadingZeroBitCount as Int + var remainderIndex = self.storage.endIndex + var remainder = self.bitshiftedLeft(words: 0, bits: shift) as Self + let divisor = other .bitshiftedLeft(words: 0, bits: shift) as Self + let divisorLast0 = divisor.storage[divisor.storage.endIndex - 1] as UInt + assert(divisorLast0.mostSignificantBit) //=--------------------------------------= - // division + // division: approximate quotient digits //=--------------------------------------= - var quotient = Storage(repeating: UInt.zero, count: gap + 1) - for quotientIndex in quotient.indices.reversed() { - //=------------------------------= - // approximate quotient digit - //=------------------------------= - var digit: UInt = { - let remainderIndex = otherMinLastIndex + quotientIndex + 1 - let remainderLast0 = remainderIndex < remainder.storage.endIndex ? remainder.storage[remainderIndex] : UInt.zero - if remainderLast0 >= discriminant { return UInt.max } - let remainderLast1 = remainder.storage[remainderIndex - 1] - return discriminant.dividingFullWidth(HL(remainderLast0, remainderLast1)).quotient - }() - - var approximation = increment.multiplied(by: digit) - //=------------------------------= - // decrement if overestimated - //=------------------------------= - if approximation > remainder { - brrrrrrrrrrrrrrrrrrrrrrr: do { digit -= 1; approximation -= increment } - if approximation > remainder { digit -= 1; approximation -= increment } - } + var quotientIndex = remainderIndex - divisor.storage.endIndex as Int + var quotient = Self.uninitialized(count: quotientIndex + 1) { quotient in + // TODO: denormalized or fixed-width operations - assert(approximation <= remainder) - //=------------------------------= - remainder -= approximation - quotient[quotientIndex] = digit - //=------------------------------= - guard !quotientIndex.isZero else { break } - increment.bitshiftRight(words: 1) + repeat { + //=------------------------------= + let remainderLast0 = remainderIndex < remainder.storage.endIndex ? remainder.storage[remainderIndex] : UInt.zero + remainder.storage.formIndex(before: &remainderIndex) + let remainderLast1 = remainderIndex < remainder.storage.endIndex ? remainder.storage[remainderIndex] : UInt.zero + //=------------------------------= + var digit = remainderLast0 == divisorLast0 ? UInt.max : divisorLast0.dividingFullWidth(HL(remainderLast0, remainderLast1)).quotient + if !digit.isZero { + var approximation = divisor.multiplied(by: digit) + + while remainder.compared(to: approximation, at: quotientIndex) < 0 as Int { + _ = digit.subtractReportingOverflow(1 as UInt) + _ = approximation.subtractReportingOverflow(divisor, at: quotientIndex) + } + + let _ = remainder.subtractReportingOverflow(approximation, at: quotientIndex) + } + //=----------------------------------= + quotient[quotientIndex] = digit + quotient.formIndex(before: "ientIndex) + } while quotientIndex >= quotient.startIndex } //=--------------------------------------= // undo shift before division //=--------------------------------------= + quotient .normalize() remainder.bitshiftRight(words: Int.zero, bits: shift) - return PVO(QR(Self(words: quotient), remainder), false) + return PVO(QR(quotient, remainder), false) } } From 3596ef158ae677d622ef79a78cd37297d4f9d7b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sat, 15 Jul 2023 12:32:47 +0200 Subject: [PATCH 003/133] NBKFlexibleWidthKit: Storage. --- .../NBKFlexibleWidth+Addition+Digit.swift | 55 +++++++++--- .../NBKFlexibleWidth+Addition.swift | 22 ++--- .../NBKFlexibleWidth+Bits.swift | 18 ++-- .../NBKFlexibleWidth+Comparisons.swift | 18 ++-- .../NBKFlexibleWidth+Division+Digit.swift | 10 +-- .../NBKFlexibleWidth+Division.swift | 29 ++++--- .../NBKFlexibleWidth+Logic.swift | 46 +++++----- ...BKFlexibleWidth+Multiplication+Digit.swift | 12 +-- .../NBKFlexibleWidth+Multiplication.swift | 16 ++-- .../NBKFlexibleWidth+Numbers.swift | 2 +- .../NBKFlexibleWidth+Shifts.swift | 40 ++++----- .../NBKFlexibleWidth+Storage.swift | 68 ++++++++++----- .../NBKFlexibleWidth+Subtraction+Digit.swift | 51 +++++++---- .../NBKFlexibleWidth+Subtraction.swift | 23 +++-- .../NBKFlexibleWidth+Text+Radix.swift | 4 +- .../NBKFlexibleWidth+Uninitialized.swift | 25 +++++- .../NBKFlexibleWidth+Words.swift | 84 ++++++++++++++++++- .../NBKFlexibleWidth.swift | 30 +++++++ .../IntXL+Addition.swift | 4 +- 19 files changed, 383 insertions(+), 174 deletions(-) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift index 41407904..304a75ea 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift @@ -32,24 +32,18 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @_disfavoredOverload @inlinable public mutating func add(_ other: UInt, at index: Int) { - defer { Swift.assert(self.isNormal) } + defer { + Swift.assert(self.storage.isNormal) + } //=--------------------------------------= - if other.isZero { return } + guard !other.isZero else { return } //=--------------------------------------= - self.resize(minLastIndex: index) + self.storage.resize(minLastIndex: index + 1) var index = index as Int - var carry = self.storage[index].addReportingOverflow(other) - self.storage.formIndex(after: &index) - - while carry && index < self.storage.endIndex { - carry = self.storage[index].addReportingOverflow(1 as UInt) - self.storage.formIndex(after: &index) - } + let overflow = self.storage.addAsFixedWidthUnchecked(other, beforeEndIndex: &index) - if carry { - self.storage.append(1 as UInt) - } + self.storage.normalizeAppend(UInt(bit: overflow)) } @_disfavoredOverload @inlinable public func adding(_ other: UInt, at index: Int) -> Self { @@ -58,3 +52,38 @@ extension NBKFlexibleWidth.Magnitude { return result as Self } } + +//*============================================================================* +// MARK: * NBK x Flexible Width x Addition x Digit x Unsigned x Storage +//*============================================================================* + +extension NBKFlexibleWidth.Magnitude.Storage { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable mutating func addAsFixedWidthUnchecked(_ other: UInt, beforeEndIndex index: inout Int) -> Bool { + assert(index < self.elements.endIndex) + //=--------------------------------------= + var carry = self.elements[index].addReportingOverflow(other) + self.elements.formIndex(after: &index) + //=--------------------------------------= + carry = self.addAsFixedWidthUnchecked(carry, upToEndIndex: &index) + //=--------------------------------------= + return carry as Bool + } + + @inlinable mutating func addAsFixedWidthUnchecked(_ other: Bool, upToEndIndex index: inout Int) -> Bool { + assert(index <= self.elements.endIndex) + //=--------------------------------------= + var overflow = other + + while overflow && index < self.elements.endIndex { + overflow = self.elements[index].addReportingOverflow(1 as UInt) + self.elements.formIndex(after: &index) + } + + return overflow as Bool + } +} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift index 25ee2aeb..c9f74f48 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift @@ -32,23 +32,25 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @inlinable public mutating func add(_ other: Self, at index: Int) { - defer { Swift.assert(self.isNormal) } + defer { + Swift.assert(self.storage.isNormal) + } //=--------------------------------------= if other.isZero { return } //=--------------------------------------= - self.resize(minCount: other.storage.count + index) + self.storage.resize(minCount: other.storage.elements.count + index) - var index = index - var carry = false + var index = index + var overflow = false - for var addend in other.storage { - carry = addend.addReportingOverflow(UInt(bit: carry)) - carry = self.storage[index].addReportingOverflow(addend) || carry - self.storage.formIndex(after: &index) + for var addend in other.storage.elements { + overflow = addend.addReportingOverflow(UInt(bit: overflow)) + overflow = self.storage.elements[index].addReportingOverflow(addend) || overflow + self.storage.elements.formIndex(after: &index) } - if carry { - self.storage.append(1 as UInt) + if overflow { + self.storage.elements.append(1 as UInt) } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift index c86f2bec..dc732536 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift @@ -28,34 +28,34 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @inlinable public var bitWidth: Int { - self.storage.count * UInt.bitWidth + self.storage.elements.count * UInt.bitWidth } @inlinable public var nonzeroBitCount: Int { - self.storage.reduce(0) { $0 + $1.nonzeroBitCount } + self.storage.elements.reduce(0) { $0 + $1.nonzeroBitCount } } @inlinable public var leadingZeroBitCount: Int { - self.storage[self.storage.index(before: self.storage.endIndex)].leadingZeroBitCount + self.storage.elements[self.storage.elements.index(before: self.storage.elements.endIndex)].leadingZeroBitCount } @inlinable public var trailingZeroBitCount: Int { - var index = self.storage.startIndex + var index = self.storage.elements.startIndex var element = UInt.zero - while index < self.storage.endIndex, element.isZero { - element = self.storage[index] - self.storage.formIndex(after: &index) + while index < self.storage.elements.endIndex, element.isZero { + element = self.storage.elements[index] + self.storage.elements.formIndex(after: &index) } return (index - 1) * UInt.bitWidth + element.trailingZeroBitCount } @inlinable public var mostSignificantBit: Bool { - self.storage[self.storage.index(before: self.storage.endIndex)].mostSignificantBit + self.storage.elements[self.storage.elements.index(before: self.storage.elements.endIndex)].mostSignificantBit } @inlinable public var leastSignificantBit: Bool { - self.storage[self.storage.startIndex].leastSignificantBit + self.storage.elements[self.storage.elements.startIndex].leastSignificantBit } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift index e661e373..8ff2cf13 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift @@ -20,7 +20,7 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @inlinable public var isZero: Bool { - self.storage.count == 1 && self.storage[0].isZero + self.storage.elements.count == 1 && self.storage.elements[0].isZero } @inlinable public var isLessThanZero: Bool { @@ -37,11 +37,11 @@ extension NBKFlexibleWidth.Magnitude { @inlinable public var isPowerOf2: Bool { var nonzeroBitCountLowerBound = 0 - var index = self.storage.startIndex + var index = self.storage.elements.startIndex //=--------------------------------------= - while index < self.storage.endIndex, nonzeroBitCountLowerBound < 2 { - nonzeroBitCountLowerBound &+= self.storage[index].nonzeroBitCount - self.storage.formIndex(after: &index) + while index < self.storage.elements.endIndex, nonzeroBitCountLowerBound < 2 { + nonzeroBitCountLowerBound &+= self.storage.elements[index].nonzeroBitCount + self.storage.elements.formIndex(after: &index) } //=--------------------------------------= return nonzeroBitCountLowerBound == 1 @@ -68,15 +68,15 @@ extension NBKFlexibleWidth.Magnitude { } @inlinable public func compared(to other: Self) -> Int { - self .storage.withUnsafeBufferPointer { lhs in - other.storage.withUnsafeBufferPointer { rhs in + self .storage.elements.withUnsafeBufferPointer { lhs in + other.storage.elements.withUnsafeBufferPointer { rhs in Self.compareWordsUnchecked(lhs, to: rhs) }} } @inlinable public func compared(to other: Self, at index: Int) -> Int { - self .storage.withUnsafeBufferPointer { lhs in - other.storage.withUnsafeBufferPointer { rhs in + self .storage.elements.withUnsafeBufferPointer { lhs in + other.storage.elements.withUnsafeBufferPointer { rhs in let partition = Swift.min(lhs.count - 1, index) let suffix = NBK.UnsafeWords(rebasing: lhs.suffix(from: partition)) let comparison = Self.compareWordsUnchecked(suffix, to: rhs) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.swift index 2f9823b6..f6a0f140 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.swift @@ -52,19 +52,19 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @_disfavoredOverload @inlinable mutating func formQuotientWithRemainderReportingOverflow(dividingBy other: UInt) -> PVO { - defer { Swift.assert(self.isNormal) } + defer { Swift.assert(self.storage.isNormal) } //=--------------------------------------= if other.isZero { - return NBK.bitCast(PVO(self.storage.first!, true)) + return NBK.bitCast(PVO(self.storage.elements.first!, true)) } //=--------------------------------------= var remainder = UInt.zero - for index in self.storage.indices.reversed() { - (self.storage[index], remainder) = other.dividingFullWidth(HL(remainder, self.storage[index])) + for index in self.storage.elements.indices.reversed() { + (self.storage.elements[index], remainder) = other.dividingFullWidth(HL(remainder, self.storage.elements[index])) } - self.normalize() + self.storage.normalize() return PVO(remainder, false) } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift index 6f416025..4d42e54b 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift @@ -60,9 +60,9 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= // divisor is one word //=--------------------------------------= - if other.storage.count == 1 { + if other.storage.elements.count == 1 { // TODO: test truncation semantcs - let divisor = other.storage.first! as UInt + let divisor = other.storage.elements.first! as UInt let qro = self.quotientAndRemainderReportingOverflow(dividingBy: divisor) let remainder = qro.overflow ? self : Self(digit: qro.partialValue.remainder) return PVO(QR(qro.partialValue.quotient, remainder), qro.overflow) @@ -70,30 +70,33 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= // divisor is greater than or equal //=--------------------------------------= - if self <= other { - return self == other ? PVO(QR(1, Self.zero), false) : PVO(QR(Self.zero, self), false) + let comparison = other.compared(to: self) + if comparison >= 0 { + switch comparison.isZero { + case true: return PVO(QR(0001, Self.zero), false) + case false: return PVO(QR(Self.zero, self), false) } } //=--------------------------------------= // shift to clamp approximation //=--------------------------------------= - let shift = other.storage.last!.leadingZeroBitCount as Int - var remainderIndex = self.storage.endIndex + let shift = other.storage.elements.last!.leadingZeroBitCount as Int + var remainderIndex = self.storage.elements.endIndex var remainder = self.bitshiftedLeft(words: 0, bits: shift) as Self - let divisor = other .bitshiftedLeft(words: 0, bits: shift) as Self - let divisorLast0 = divisor.storage[divisor.storage.endIndex - 1] as UInt + let divisor = other.bitshiftedLeft(words: 0, bits: shift) as Self + let divisorLast0 = divisor.storage.elements[divisor.storage.elements.endIndex - 1] as UInt assert(divisorLast0.mostSignificantBit) //=--------------------------------------= // division: approximate quotient digits //=--------------------------------------= - var quotientIndex = remainderIndex - divisor.storage.endIndex as Int + var quotientIndex = remainderIndex - divisor.storage.elements.endIndex as Int var quotient = Self.uninitialized(count: quotientIndex + 1) { quotient in // TODO: denormalized or fixed-width operations repeat { //=------------------------------= - let remainderLast0 = remainderIndex < remainder.storage.endIndex ? remainder.storage[remainderIndex] : UInt.zero - remainder.storage.formIndex(before: &remainderIndex) - let remainderLast1 = remainderIndex < remainder.storage.endIndex ? remainder.storage[remainderIndex] : UInt.zero + let remainderLast0 = remainderIndex < remainder.storage.elements.endIndex ? remainder.storage.elements[remainderIndex] : UInt.zero + remainder.storage.elements.formIndex(before: &remainderIndex) + let remainderLast1 = remainderIndex < remainder.storage.elements.endIndex ? remainder.storage.elements[remainderIndex] : UInt.zero //=------------------------------= var digit = remainderLast0 == divisorLast0 ? UInt.max : divisorLast0.dividingFullWidth(HL(remainderLast0, remainderLast1)).quotient if !digit.isZero { @@ -114,7 +117,7 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= // undo shift before division //=--------------------------------------= - quotient .normalize() + quotient .storage.normalize() remainder.bitshiftRight(words: Int.zero, bits: shift) return PVO(QR(quotient, remainder), false) } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift index 2d7dfb2c..53d4a31a 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift @@ -20,23 +20,23 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @inlinable public static prefix func ~(x: Self) -> Self { - Self(words: x.storage.map(~)) + Self(words: x.storage.elements.map(~)) } @inlinable public static func &=(lhs: inout Self, rhs: Self) { - defer { Swift.assert(lhs.isNormal) } + defer { Swift.assert(lhs.storage.isNormal) } //=--------------------------------------= - if lhs.storage.endIndex > rhs.storage.endIndex { - lhs.storage.removeSubrange(rhs.storage.endIndex...) + if lhs.storage.elements.endIndex > rhs.storage.elements.endIndex { + lhs.storage.elements.removeSubrange(rhs.storage.elements.endIndex...) } //=--------------------------------------= - for index in lhs.storage.indices.reversed() { - let word = lhs.storage[index] & rhs.storage[index] + for index in lhs.storage.elements.indices.reversed() { + let word = lhs.storage.elements[index] & rhs.storage.elements[index] - if index == lhs.storage.endIndex, word.isZero, index != lhs.storage.startIndex { - lhs.storage.removeLast() + if index == lhs.storage.elements.endIndex, word.isZero, index != lhs.storage.elements.startIndex { + lhs.storage.elements.removeLast() } else { - lhs.storage[index] = word + lhs.storage.elements[index] = word } } } @@ -46,17 +46,17 @@ extension NBKFlexibleWidth.Magnitude { } @inlinable public static func |=(lhs: inout Self, rhs: Self) { - defer { Swift.assert(lhs.isNormal) } + defer { Swift.assert(lhs.storage.isNormal) } //=--------------------------------------= - lhs.storage.reserveCapacity(rhs.storage.count) + lhs.storage.elements.reserveCapacity(rhs.storage.elements.count) //=--------------------------------------= - for index in rhs.storage.indices { - let source = rhs.storage[index] + for index in rhs.storage.elements.indices { + let source = rhs.storage.elements[index] - if index < lhs.storage.endIndex { - lhs.storage[index] |= source + if index < lhs.storage.elements.endIndex { + lhs.storage.elements[index] |= source } else { - lhs.storage.append(source as UInt) + lhs.storage.elements.append(source as UInt) } } } @@ -66,17 +66,17 @@ extension NBKFlexibleWidth.Magnitude { } @inlinable public static func ^=(lhs: inout Self, rhs: Self) { - defer { lhs.normalize() } + defer { lhs.storage.normalize() } //=--------------------------------------= - lhs.storage.reserveCapacity(rhs.storage.count) + lhs.storage.elements.reserveCapacity(rhs.storage.elements.count) //=--------------------------------------= - for index in rhs.storage.indices { - let source = rhs.storage[index] + for index in rhs.storage.elements.indices { + let source = rhs.storage.elements[index] - if index < lhs.storage.endIndex { - lhs.storage[index] ^= source + if index < lhs.storage.elements.endIndex { + lhs.storage.elements[index] ^= source } else { - lhs.storage.append(source as UInt) + lhs.storage.elements.append(source as UInt) } } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift index 7438cc97..c2d129a1 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift @@ -32,24 +32,24 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @_disfavoredOverload @inlinable mutating func multiply(by other: UInt) { - defer { Swift.assert(self.isNormal) } + defer { Swift.assert(self.storage.isNormal) } //=--------------------------------------= if other.isZero { return self = Self.zero } //=--------------------------------------= - self.storage.reserveCapacity(self.storage.count + 1) + self.storage.elements.reserveCapacity(self.storage.elements.count + 1) //=--------------------------------------= var carry = UInt.zero - for index in self.storage.indices { - var subproduct = self.storage[index].multipliedFullWidth(by: other) + for index in self.storage.elements.indices { + var subproduct = self.storage.elements[index].multipliedFullWidth(by: other) subproduct.high &+= UInt(bit: subproduct.low.addReportingOverflow(carry)) - (carry, self.storage[index]) = subproduct as HL + (carry, self.storage.elements[index]) = subproduct as HL } if !carry.isZero { - self.storage.append(carry) + self.storage.elements.append(carry) } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift index 3fab63ca..93b9289f 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift @@ -37,24 +37,24 @@ extension NBKFlexibleWidth.Magnitude { @inlinable func multiplied(by other: Self) -> Self { //=--------------------------------------= - let capacity: Int = self.storage.count + other.storage.count - var product = Self(unchecked: Storage(repeating: UInt(), count: capacity)) + let capacity: Int = self.storage.elements.count + other.storage.elements.count + var product = Storage(repeating: UInt(), count: capacity) //=--------------------------------------= - for lhsIndex in self.storage.indices { + for lhsIndex in self.storage.elements.indices { var carry = UInt.zero - for rhsIndex in other.storage.indices { - var subproduct = self.storage[lhsIndex].multipliedFullWidth(by: other.storage[rhsIndex]) + for rhsIndex in other.storage.elements.indices { + var subproduct = self.storage.elements[lhsIndex].multipliedFullWidth(by: other.storage.elements[rhsIndex]) carry = UInt(bit: subproduct.low.addReportingOverflow(carry)) - carry &+= UInt(bit: product.storage[lhsIndex + rhsIndex].addReportingOverflow(subproduct.low)) + carry &+= UInt(bit: product.elements[lhsIndex + rhsIndex].addReportingOverflow(subproduct.low)) carry &+= subproduct.high } - product.storage[lhsIndex + other.storage.endIndex] = carry + product.elements[lhsIndex + other.storage.elements.endIndex] = carry } //=--------------------------------------= product.normalize() - return product as Self + return Self(unchecked: product) } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift index 7ee377af..60b63367 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift @@ -26,7 +26,7 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @inlinable public init(digit: Digit) { - self.init(unchecked: [digit]) + self.init(storage: Storage(elements: [digit])) } //=------------------------------------------------------------------------= diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift index 84a03658..04533179 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift @@ -68,21 +68,21 @@ extension NBKFlexibleWidth.Magnitude { let push = UInt(bitPattern: bits) let pull = UInt(bitPattern: UInt.bitWidth - bits) //=--------------------------------------= - self.resize(minCount: self.storage.endIndex + words + 1) + self.storage.resize(minCount: self.storage.elements.endIndex + words + 1) //=--------------------------------------= let offset: Int = ~(words) - var destination = self.storage.endIndex as Int - var word = self.storage[destination &+ offset] + var destination = self.storage.elements.endIndex as Int + var word = self.storage.elements[destination &+ offset] //=--------------------------------------= - while destination > self.storage.startIndex { - self.storage.formIndex(before: &destination) + while destination > self.storage.elements.startIndex { + self.storage.elements.formIndex(before: &destination) let pushed = word &<< push - word = destination > words ? self.storage[destination &+ offset] : UInt() + word = destination > words ? self.storage.elements[destination &+ offset] : UInt() let pulled = word &>> pull - self.storage[destination ] = pushed | pulled + self.storage.elements[destination ] = pushed | pulled } //=--------------------------------------= - self.normalize() + self.storage.normalize() } @inlinable public func bitshiftedLeft(words: Int, bits: Int) -> Self { @@ -97,7 +97,7 @@ extension NBKFlexibleWidth.Magnitude { if self .isZero { return } //=--------------------------------------= let prefix = repeatElement(UInt.zero, count: words) - self.storage.insert(contentsOf: prefix, at: Int()) + self.storage.elements.insert(contentsOf: prefix, at: Int()) } @inlinable public func bitshiftedLeft(words: Int) -> Self { @@ -152,7 +152,7 @@ extension NBKFlexibleWidth.Magnitude { precondition(words >= 0, NBK.callsiteOutOfBoundsInfo()) precondition(bits >= 0 && bits < UInt.bitWidth, NBK.callsiteOutOfBoundsInfo()) //=--------------------------------------= - if words >= self.storage.count { + if words >= self.storage.elements.count { return self = Self.zero } //=--------------------------------------= @@ -164,21 +164,21 @@ extension NBKFlexibleWidth.Magnitude { let pull = UInt(bitPattern: UInt.bitWidth - bits) let sign = UInt(repeating: self.isLessThanZero) //=--------------------------------------= - var destination = self.storage.startIndex - let edge = self.storage.distance(from: words, to: self.storage.endIndex) - var word = self.storage[words] as UInt + var destination = self.storage.elements.startIndex + let edge = self.storage.elements.distance(from: words, to: self.storage.elements.endIndex) + var word = self.storage.elements[words] as UInt //=--------------------------------------= while destination < edge { - let after = self.storage.index(after: destination) + let after = self.storage.elements.index(after: destination) let pushed = word &>> push - word = after < edge ? self.storage[after &+ words] : sign + word = after < edge ? self.storage.elements[after &+ words] : sign let pulled = word &<< pull - self.storage[destination ] = pushed | pulled + self.storage.elements[destination ] = pushed | pulled destination = after } //=--------------------------------------= - self.storage.removeLast(words) - self.normalize() + self.storage.elements.removeLast(words) + self.storage.normalize() } @inlinable public func bitshiftedRight(words: Int, bits: Int) -> Self { @@ -190,8 +190,8 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= if words.isZero { return } //=--------------------------------------= - self.storage.removeFirst(Swift.min(words, self.storage.count)) - self.normalize() + self.storage.elements.removeFirst(Swift.min(words, self.storage.elements.count)) + self.storage.normalize() } @inlinable public func bitshiftedRight(words: Int) -> Self { diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Storage.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Storage.swift index 3bbcc885..83d03ac7 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Storage.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Storage.swift @@ -13,14 +13,24 @@ import NBKCoreKit // MARK: * NBK x Flexible Width x Storage x Unsigned //*============================================================================* -extension NBKFlexibleWidth.Magnitude { - - @usableFromInline typealias Storage = Array +extension NBKFlexibleWidth.Magnitude.Storage { //=------------------------------------------------------------------------= - // MARK: Accessors x Private + // MARK: Initializers //=------------------------------------------------------------------------= + @inlinable init(_ elements: some Sequence) { + self.init(elements: Elements(elements)) + } + + @inlinable init(repeating element: UInt, count: Int) { + self.init(elements: Elements(repeating: element, count: count)) + } + + //=--------------------------------------------------------------------= + // MARK: Accessors + //=--------------------------------------------------------------------= + /// Returns whether the underlying storage is normalized. /// /// The storage is normalized under each of the following conditions: @@ -29,14 +39,16 @@ extension NBKFlexibleWidth.Magnitude { /// - `count >= 2 && last != 0` /// @inlinable var isNormal: Bool { - switch self.storage.count > 1 { - case true: return !self.storage.last!.isZero - case false: return !self.storage.isEmpty } + // TODO: self.elements.last != 0 + + switch self.elements.count > 1 { + case true: return !self.elements.last!.isZero + case false: return !self.elements.isEmpty } } - //=------------------------------------------------------------------------= - // MARK: Transformations x Private - //=------------------------------------------------------------------------= + //=--------------------------------------------------------------------= + // MARK: Transformations + //=--------------------------------------------------------------------= /// Normalizes the underlying storage. /// @@ -46,19 +58,33 @@ extension NBKFlexibleWidth.Magnitude { /// - `count >= 2 && last != 0` /// @inlinable mutating func normalize() { - var index = self.storage.endIndex as Int - if index > self.storage.startIndex { - self.storage.formIndex(before: &index) - while index > self.storage.startIndex, - self.storage[index].isZero { - self.storage.formIndex(before: &index) - self.storage.removeLast() + // TODO: while self.elements.last == 0 { self.elements.removeLast() } + + var index = self.elements.endIndex as Int + if index > self.elements.startIndex { + self.elements.formIndex(before: &index) + while index > self.elements.startIndex, + self.elements[index].isZero { + self.elements.formIndex(before: &index) + self.elements.removeLast() } } else { - self.storage.append(UInt.zero) + self.elements.append(UInt.zero) } } + @inlinable mutating func normalizeAppend(_ element: UInt) { + if element.isZero { + self.normalize() + } else { + self.elements.append(element) + } + } + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + /// Resizes the underlying storage, if needed. /// /// The storage is normalized under each of the following conditions: @@ -69,9 +95,9 @@ extension NBKFlexibleWidth.Magnitude { /// - Note: Calling this method denormalizes `self`. /// @inlinable mutating func resize(minCount: Int) { - self.storage.reserveCapacity(minCount) - appending: while self.storage.count < minCount { - self.storage.append(UInt.zero) + self.elements.reserveCapacity(minCount) + appending: while self.elements.count < minCount { + self.elements.append(UInt.zero) } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift index f925c138..62d56afa 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift @@ -35,17 +35,19 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @_disfavoredOverload @inlinable public mutating func subtractReportingOverflow(_ other: UInt, at index: Int) -> Bool { - defer { Swift.assert(self.isNormal) } + defer { + assert(self.storage.isNormal) + } //=--------------------------------------= - if other.isZero { return false } + guard !other.isZero else { return false } //=--------------------------------------= - self.resize(minLastIndex: index) + self.storage.resize(minLastIndex: index) - var index = index as Int - let borrow = self.storage[index].subtractReportingOverflow(other) - self.storage.formIndex(after: &index) + var index = index as Int + let overflow = self.storage.subtractAsFixedWidthUnchecked(other, beforeEndIndex: &index) - return self.subtractUpToEndIndex(borrow, from: &index) + self.storage.normalize() + return overflow as Bool } @_disfavoredOverload @inlinable public func subtractingReportingOverflow(_ other: UInt, at index: Int) -> PVO { @@ -53,20 +55,39 @@ extension NBKFlexibleWidth.Magnitude { let overflow: Bool = partialValue.subtractReportingOverflow(other, at: index) return PVO(partialValue, overflow) } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Subtraction x Digit x Unsigned x Storage +//*============================================================================* + +extension NBKFlexibleWidth.Magnitude.Storage { //=------------------------------------------------------------------------= - // MARK: Transformations x Private + // MARK: Transformations //=------------------------------------------------------------------------= - @inlinable mutating func subtractUpToEndIndex(_ borrow: Bool, from index: inout Int) -> Bool { - var borrow = borrow + @inlinable mutating func subtractAsFixedWidthUnchecked(_ other: UInt, beforeEndIndex index: inout Int) -> Bool { + assert(index < self.elements.endIndex) + //=--------------------------------------= + var overflow = self.elements[index].subtractReportingOverflow(other) + self.elements.formIndex(after: &index) + //=--------------------------------------= + overflow = self.subtractAsFixedWidthUnchecked(overflow, upToEndIndex: &index) + //=--------------------------------------= + return overflow as Bool + } + + @inlinable mutating func subtractAsFixedWidthUnchecked(_ other: Bool, upToEndIndex index: inout Int) -> Bool { + assert(index <= self.elements.endIndex) + //=--------------------------------------= + var overflow = other - forwards: while borrow, index < self.storage.endIndex { - borrow = self.storage[index].subtractReportingOverflow(1 as UInt) - self.storage.formIndex(after: &index) + forwards: while overflow, index < self.elements.endIndex { + overflow = self.elements[index].subtractReportingOverflow(1 as UInt) + self.elements.formIndex(after: &index) } - self.normalize() - return borrow as Bool + return overflow as Bool } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift index b16ec027..beb8ff07 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift @@ -35,22 +35,27 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @inlinable public mutating func subtractReportingOverflow(_ other: Self, at index: Int) -> Bool { - defer { Swift.assert(self.isNormal) } + defer { + Swift.assert(self.storage.isNormal) + } //=--------------------------------------= if other.isZero { return false } //=--------------------------------------= - self.resize(minCount: other.storage.count + index) + self.storage.resize(minCount: other.storage.elements.count + index) - var index = index - var borrow = false + var index = index + var overflow = false - for var subtrahend in other.storage { - borrow = subtrahend.addReportingOverflow(UInt(bit: borrow)) - borrow = self.storage[index].subtractReportingOverflow(subtrahend) || borrow - self.storage.formIndex(after: &index) + for var subtrahend in other.storage.elements { + overflow = subtrahend.addReportingOverflow(UInt(bit: overflow)) + overflow = self.storage.elements[index].subtractReportingOverflow(subtrahend) || overflow + self.storage.elements.formIndex(after: &index) } - return self.subtractUpToEndIndex(borrow, from: &index) + overflow = self.storage.subtractAsFixedWidthUnchecked(overflow, upToEndIndex: &index) + + self.storage.normalize() + return overflow as Bool } @inlinable public func subtractingReportingOverflow(_ other: Self, at index: Int) -> PVO { diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text+Radix.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text+Radix.swift index dd554ef7..08e5cc79 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text+Radix.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text+Radix.swift @@ -99,7 +99,7 @@ extension NBKFlexibleWidth.Magnitude { forwards: if !alignment.isZero { let chunk = NBK.UnsafeUTF8(rebasing: NBK.removePrefix(from: &digits, count: alignment)) guard let word = UInt.truncating(digits: chunk, radix: radix.base) else { return nil } - self.storage[self.storage.startIndex] = word + self.storage.elements[self.storage.elements.startIndex] = word } forwards: while !digits.isEmpty { @@ -125,7 +125,7 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= // with one buffer pointer specialization //=--------------------------------------= - self.storage.withContiguousStorageIfAvailable { buffer in + self.storage.elements.withContiguousStorageIfAvailable { buffer in let index = buffer.lastIndex(where:{ !$0.isZero }) ?? buffer.startIndex let chunks = NBK.UnsafeWords(rebasing: buffer[...index]) return String.fromUTF8Unchecked(chunks: chunks, radix: radix, alphabet: alphabet, prefix: prefix, suffix: suffix) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Uninitialized.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Uninitialized.swift index f72071d1..7b77120b 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Uninitialized.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Uninitialized.swift @@ -20,12 +20,29 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @inlinable static func uninitialized(count: Int, body: (NBK.UnsafeMutableWords) -> Void) -> Self { - let storage = Array(unsafeUninitializedCapacity: count) { - storage, endIndex in - body(NBK.UnsafeMutableWords(rebasing: storage.prefix(upTo: count))) + var storage = Storage.uninitialized(count: count, body: body) + storage.normalize() + return Self(unchecked: storage) + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Uninitialized x Unsigned x Storage +//*============================================================================* + +extension NBKFlexibleWidth.Magnitude.Storage { + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + @inlinable static func uninitialized(count: Int, body: (NBK.UnsafeMutableWords) -> Void) -> Self { + let elements = Elements(unsafeUninitializedCapacity: count) { + elements, endIndex in + body(NBK.UnsafeMutableWords(rebasing: elements.prefix(upTo: count))) endIndex = count as Int } - return Self(unchecked: storage) + return Self(elements: elements) } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift index 6e9a39f2..d78d3f9f 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift @@ -20,15 +20,91 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @inlinable public init(words: some RandomAccessCollection) { - self.init(unchecked: Array(words)) - self.normalize() + var storage = Storage(words) + storage.normalize() + self.init(unchecked: storage) } //=------------------------------------------------------------------------= // MARK: Accessors //=------------------------------------------------------------------------= - @inlinable public var words: Array { - _read { yield self.storage } + @inlinable public var words: Words { + Words(magnitude: self) + } + + //*========================================================================* + // MARK: * Words + //*========================================================================* + + @frozen public struct Words: RandomAccessCollection { + + //=--------------------------------------------------------------------= + // MARK: State + //=--------------------------------------------------------------------= + + @usableFromInline let magnitude: Magnitude + + //=--------------------------------------------------------------------= + // MARK: Initializers + //=--------------------------------------------------------------------= + + @inlinable init(magnitude: Magnitude) { + self.magnitude = magnitude + } + + //=--------------------------------------------------------------------= + // MARK: Accessors + //=--------------------------------------------------------------------= + + @inlinable public var count: Int { + self.magnitude.storage.elements.count + } + + @inlinable public var startIndex: Int { + self.magnitude.storage.elements.startIndex + } + + @inlinable public var endIndex: Int { + self.magnitude.storage.elements.endIndex + } + + @inlinable public subscript(index: Int) -> UInt { + switch index < self.magnitude.storage.elements.endIndex { + case true: return self.magnitude.storage.elements[index] + case false: return UInt.zero } + } + + //=--------------------------------------------------------------------= + // MARK: Utilities + //=--------------------------------------------------------------------= + + @inlinable public func distance(from start: Int, to end: Int) -> Int { + self.magnitude.storage.elements.distance(from: start, to: end) + } + + @inlinable public func index(after index: Int) -> Int { + self.magnitude.storage.elements.index(after: index) + } + + @inlinable public func formIndex(after index: inout Int) { + self.magnitude.storage.elements.formIndex(after: &index) + } + + @inlinable public func index(before index: Int) -> Int { + self.magnitude.storage.elements.index(before: index) + } + + @inlinable public func formIndex(before index: inout Int) { + self.magnitude.storage.elements.formIndex(before: &index) + } + + @inlinable public func index(_ index: Int, offsetBy distance: Int) -> Int { + self.magnitude.storage.elements.index(index, offsetBy: distance) + } + + @inlinable public func index(_ index: Int, offsetBy distance: Int, limitedBy limit: Int) -> Int? { + self.magnitude.storage.elements.index(index, offsetBy: distance, limitedBy: limit) + } } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift index 7799aa11..c48635a9 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift @@ -44,6 +44,36 @@ import NBKCoreKit @inlinable init(unchecked: Storage) { self.storage = unchecked + Swift.assert(self.storage.isNormal) + } + + @inlinable init(storage: Storage) { + self.storage = storage + self.storage.normalize() + Swift.assert(self.storage.isNormal) + } + + //*====================================================================* + // MARK: * Storage + //*====================================================================* + + @frozen @usableFromInline struct Storage: Hashable { + + @usableFromInline typealias Elements = [UInt] + + //=----------------------------------------------------------------= + // MARK: State + //=----------------------------------------------------------------= + + @usableFromInline var elements: Elements + + //=----------------------------------------------------------------= + // MARK: Initializers + //=----------------------------------------------------------------= + + @inlinable init(elements: Elements) { + self.elements = elements + } } } } diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Addition.swift b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Addition.swift index cf0d2834..7ab325bc 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Addition.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Addition.swift @@ -32,7 +32,7 @@ final class UIntXLBenchmarksOnAddition: XCTestCase { var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) - for _ in 0 ..< 5_000_000 { + for _ in 0 ..< 1_000_000 { NBK.blackHole(lhs + rhs) NBK.blackHoleInoutIdentity(&lhs) NBK.blackHoleInoutIdentity(&rhs) @@ -47,7 +47,7 @@ final class UIntXLBenchmarksOnAddition: XCTestCase { var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) var rhs = NBK.blackHoleIdentity(UInt.max) - for _ in 0 ..< 5_000_000 { + for _ in 0 ..< 1_000_000 { NBK.blackHole(lhs + rhs) NBK.blackHoleInoutIdentity(&lhs) NBK.blackHoleInoutIdentity(&rhs) From 74132d12b91dbf57b938d17e4521ba1cb7637942 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sat, 15 Jul 2023 12:53:08 +0200 Subject: [PATCH 004/133] NBKFlexibleWidthKit: Normalization. --- .../NBKFlexibleWidth+Addition+Digit.swift | 24 +-- .../NBKFlexibleWidth+Bits.swift | 6 +- .../NBKFlexibleWidth+Comparisons.swift | 6 +- .../NBKFlexibleWidth+Division+Digit.swift | 2 +- .../NBKFlexibleWidth+Division.swift | 6 + .../NBKFlexibleWidth+Storage.swift | 50 +----- .../NBKFlexibleWidth+Subtraction+Digit.swift | 26 +-- .../NBKFlexibleWidth+Subtraction.swift | 3 +- .../NBKFlexibleWidth+Text+Radix.swift | 15 +- Tests/NBKDoubleWidthKitTests/256+Bits.swift | 4 +- .../NBKFlexibleWidthKitTests/IntXL+Bits.swift | 8 +- .../IntXL+Comparisons.swift | 152 +++++++++--------- .../IntXL+Logic.swift | 2 +- .../IntXL+Subtraction.swift | 16 +- .../IntXL+Words.swift | 51 +++--- 15 files changed, 168 insertions(+), 203 deletions(-) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift index 304a75ea..1b575346 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift @@ -40,8 +40,8 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= self.storage.resize(minLastIndex: index + 1) - var index = index as Int - let overflow = self.storage.addAsFixedWidthUnchecked(other, beforeEndIndex: &index) + var index: Int = index + let overflow = self.storage.addAsFixedWidth(other, at: &index) self.storage.normalizeAppend(UInt(bit: overflow)) } @@ -63,27 +63,17 @@ extension NBKFlexibleWidth.Magnitude.Storage { // MARK: Transformations //=------------------------------------------------------------------------= - @inlinable mutating func addAsFixedWidthUnchecked(_ other: UInt, beforeEndIndex index: inout Int) -> Bool { - assert(index < self.elements.endIndex) - //=--------------------------------------= - var carry = self.elements[index].addReportingOverflow(other) + @inlinable mutating func addAsFixedWidth(_ other: UInt, at index: inout Int) -> Bool { + var overflow = self.elements[index].addReportingOverflow(other) self.elements.formIndex(after: &index) - //=--------------------------------------= - carry = self.addAsFixedWidthUnchecked(carry, upToEndIndex: &index) - //=--------------------------------------= - return carry as Bool + self.carryAsFixedWidth(&overflow, from: &index) + return overflow as Bool } - @inlinable mutating func addAsFixedWidthUnchecked(_ other: Bool, upToEndIndex index: inout Int) -> Bool { - assert(index <= self.elements.endIndex) - //=--------------------------------------= - var overflow = other - + @inlinable mutating func carryAsFixedWidth(_ overflow: inout Bool, from index: inout Int) { while overflow && index < self.elements.endIndex { overflow = self.elements[index].addReportingOverflow(1 as UInt) self.elements.formIndex(after: &index) } - - return overflow as Bool } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift index dc732536..f269f76f 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift @@ -36,7 +36,7 @@ extension NBKFlexibleWidth.Magnitude { } @inlinable public var leadingZeroBitCount: Int { - self.storage.elements[self.storage.elements.index(before: self.storage.elements.endIndex)].leadingZeroBitCount + self.storage.elements.last?.leadingZeroBitCount ?? Int.zero } @inlinable public var trailingZeroBitCount: Int { @@ -52,10 +52,10 @@ extension NBKFlexibleWidth.Magnitude { } @inlinable public var mostSignificantBit: Bool { - self.storage.elements[self.storage.elements.index(before: self.storage.elements.endIndex)].mostSignificantBit + self.storage.elements.last?.mostSignificantBit ?? false } @inlinable public var leastSignificantBit: Bool { - self.storage.elements[self.storage.elements.startIndex].leastSignificantBit + self.storage.elements.first?.leastSignificantBit ?? false } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift index 8ff2cf13..c6b40daf 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift @@ -20,7 +20,7 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @inlinable public var isZero: Bool { - self.storage.elements.count == 1 && self.storage.elements[0].isZero + self.storage.elements.isEmpty } @inlinable public var isLessThanZero: Bool { @@ -91,8 +91,8 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @inlinable static func compareWordsUnchecked(_ lhs: NBK.UnsafeWords, to rhs: NBK.UnsafeWords) -> Int { - assert(lhs.count == 1 || !lhs.last!.isZero) - assert(rhs.count == 1 || !rhs.last!.isZero) + assert(lhs.count == 0 || !lhs.last!.isZero) + assert(rhs.count == 0 || !rhs.last!.isZero) //=--------------------------------------= if lhs.count != rhs.count { return lhs.count < rhs.count ? -1 : 1 diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.swift index f6a0f140..a8bd7271 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.swift @@ -55,7 +55,7 @@ extension NBKFlexibleWidth.Magnitude { defer { Swift.assert(self.storage.isNormal) } //=--------------------------------------= if other.isZero { - return NBK.bitCast(PVO(self.storage.elements.first!, true)) + return NBK.bitCast(PVO(self.storage.elements.first ?? UInt.zero, true)) } //=--------------------------------------= var remainder = UInt.zero diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift index 4d42e54b..044a3494 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift @@ -57,6 +57,12 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @inlinable func quotientAndRemainderReportingOverflowAsNormal(dividingBy other: Self) -> PVO> { + //=--------------------------------------= + // divisor is zero + //=--------------------------------------= + if other.isZero { + return PVO(QR(self, self), true) + } //=--------------------------------------= // divisor is one word //=--------------------------------------= diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Storage.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Storage.swift index 83d03ac7..dc1f7ae6 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Storage.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Storage.swift @@ -32,18 +32,8 @@ extension NBKFlexibleWidth.Magnitude.Storage { //=--------------------------------------------------------------------= /// Returns whether the underlying storage is normalized. - /// - /// The storage is normalized under each of the following conditions: - /// - /// - `count == 1` - /// - `count >= 2 && last != 0` - /// @inlinable var isNormal: Bool { - // TODO: self.elements.last != 0 - - switch self.elements.count > 1 { - case true: return !self.elements.last!.isZero - case false: return !self.elements.isEmpty } + self.elements.last != 0 as UInt } //=--------------------------------------------------------------------= @@ -51,28 +41,13 @@ extension NBKFlexibleWidth.Magnitude.Storage { //=--------------------------------------------------------------------= /// Normalizes the underlying storage. - /// - /// The storage is normalized under each of the following conditions: - /// - /// - `count == 1` - /// - `count >= 2 && last != 0` - /// @inlinable mutating func normalize() { - // TODO: while self.elements.last == 0 { self.elements.removeLast() } - - var index = self.elements.endIndex as Int - if index > self.elements.startIndex { - self.elements.formIndex(before: &index) - while index > self.elements.startIndex, - self.elements[index].isZero { - self.elements.formIndex(before: &index) - self.elements.removeLast() - } - } else { - self.elements.append(UInt.zero) + trimming: while self.elements.last == 0 as UInt { + self.elements.removeLast() } } + /// Normalizes the underlying storage after appending the element. @inlinable mutating func normalizeAppend(_ element: UInt) { if element.isZero { self.normalize() @@ -86,14 +61,6 @@ extension NBKFlexibleWidth.Magnitude.Storage { //=------------------------------------------------------------------------= /// Resizes the underlying storage, if needed. - /// - /// The storage is normalized under each of the following conditions: - /// - /// - `count == 1` - /// - `count >= 2 && last != 0` - /// - /// - Note: Calling this method denormalizes `self`. - /// @inlinable mutating func resize(minCount: Int) { self.elements.reserveCapacity(minCount) appending: while self.elements.count < minCount { @@ -102,15 +69,6 @@ extension NBKFlexibleWidth.Magnitude.Storage { } /// Resizes the underlying storage, if needed. - /// - /// The storage is normalized under each of the following conditions: - /// - /// - `count == 1` - /// - `count >= 2 && last != 0` - /// - /// - /// - Note: Calling this method denormalizes `self`. - /// @inlinable mutating func resize(minLastIndex: Int) { self.resize(minCount: minLastIndex + 1) } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift index 62d56afa..fb0d074c 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift @@ -36,15 +36,15 @@ extension NBKFlexibleWidth.Magnitude { @_disfavoredOverload @inlinable public mutating func subtractReportingOverflow(_ other: UInt, at index: Int) -> Bool { defer { - assert(self.storage.isNormal) + Swift.assert(self.storage.isNormal) } //=--------------------------------------= guard !other.isZero else { return false } //=--------------------------------------= self.storage.resize(minLastIndex: index) - var index = index as Int - let overflow = self.storage.subtractAsFixedWidthUnchecked(other, beforeEndIndex: &index) + var index: Int = index + let overflow = self.storage.subtractAsFixedWidth(other, at: &index) self.storage.normalize() return overflow as Bool @@ -67,27 +67,17 @@ extension NBKFlexibleWidth.Magnitude.Storage { // MARK: Transformations //=------------------------------------------------------------------------= - @inlinable mutating func subtractAsFixedWidthUnchecked(_ other: UInt, beforeEndIndex index: inout Int) -> Bool { - assert(index < self.elements.endIndex) - //=--------------------------------------= + @inlinable mutating func subtractAsFixedWidth(_ other: UInt, at index: inout Int) -> Bool { var overflow = self.elements[index].subtractReportingOverflow(other) self.elements.formIndex(after: &index) - //=--------------------------------------= - overflow = self.subtractAsFixedWidthUnchecked(overflow, upToEndIndex: &index) - //=--------------------------------------= + self.borrowAsFixedWidth(&overflow, from: &index) return overflow as Bool } - - @inlinable mutating func subtractAsFixedWidthUnchecked(_ other: Bool, upToEndIndex index: inout Int) -> Bool { - assert(index <= self.elements.endIndex) - //=--------------------------------------= - var overflow = other - - forwards: while overflow, index < self.elements.endIndex { + + @inlinable mutating func borrowAsFixedWidth(_ overflow: inout Bool, from index: inout Int) { + while overflow && index < self.elements.endIndex { overflow = self.elements[index].subtractReportingOverflow(1 as UInt) self.elements.formIndex(after: &index) } - - return overflow as Bool } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift index beb8ff07..ffc275a5 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift @@ -52,8 +52,7 @@ extension NBKFlexibleWidth.Magnitude { self.storage.elements.formIndex(after: &index) } - overflow = self.storage.subtractAsFixedWidthUnchecked(overflow, upToEndIndex: &index) - + self.storage.borrowAsFixedWidth(&overflow, from: &index) self.storage.normalize() return overflow as Bool } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text+Radix.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text+Radix.swift index 08e5cc79..9031072e 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text+Radix.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text+Radix.swift @@ -99,13 +99,14 @@ extension NBKFlexibleWidth.Magnitude { forwards: if !alignment.isZero { let chunk = NBK.UnsafeUTF8(rebasing: NBK.removePrefix(from: &digits, count: alignment)) guard let word = UInt.truncating(digits: chunk, radix: radix.base) else { return nil } - self.storage.elements[self.storage.elements.startIndex] = word + self += word } forwards: while !digits.isEmpty { let chunk = NBK.UnsafeUTF8(rebasing: NBK.removePrefix(from: &digits, count: radix.exponent)) guard let word = UInt.truncating(digits: chunk, radix: radix.base) else { return nil } - self *= radix.power; self += word // TODO: combined * and + method + self *= radix.power + self += word // TODO: combined * and + method } }() as Void? else { return nil } @@ -122,10 +123,14 @@ extension NBKFlexibleWidth.Magnitude { } @inlinable func description(radix: PerfectRadixUIntRoot, alphabet: MaxRadixAlphabetEncoder, prefix: NBK.UnsafeUTF8, suffix: NBK.UnsafeUTF8) -> String { + //=--------------------------------------= + // TODO: String.fromUTF8Unchecked + //=--------------------------------------= + if self.isZero { return "0" } //=--------------------------------------= // with one buffer pointer specialization //=--------------------------------------= - self.storage.elements.withContiguousStorageIfAvailable { buffer in + return self.storage.elements.withContiguousStorageIfAvailable { buffer in let index = buffer.lastIndex(where:{ !$0.isZero }) ?? buffer.startIndex let chunks = NBK.UnsafeWords(rebasing: buffer[...index]) return String.fromUTF8Unchecked(chunks: chunks, radix: radix, alphabet: alphabet, prefix: prefix, suffix: suffix) @@ -133,6 +138,10 @@ extension NBKFlexibleWidth.Magnitude { } @inlinable func description(radix: ImperfectRadixUIntRoot, alphabet: MaxRadixAlphabetEncoder, prefix: NBK.UnsafeUTF8, suffix: NBK.UnsafeUTF8) -> String { + //=--------------------------------------= + // TODO: String.fromUTF8Unchecked + //=--------------------------------------= + if self.isZero { return "0" } //=--------------------------------------= // with one buffer pointer specialization //=--------------------------------------= diff --git a/Tests/NBKDoubleWidthKitTests/256+Bits.swift b/Tests/NBKDoubleWidthKitTests/256+Bits.swift index 978e4e82..ce41ead2 100644 --- a/Tests/NBKDoubleWidthKitTests/256+Bits.swift +++ b/Tests/NBKDoubleWidthKitTests/256+Bits.swift @@ -60,8 +60,8 @@ final class Int256TestsOnBits: XCTestCase { } func testTrailingZeroBitCount() { - XCTAssertEqual(T(x64: X( 0, 0, 0, 0)).leadingZeroBitCount, 64 * 4) - XCTAssertEqual(T(x64: X(~0, ~0, ~0, ~0)).leadingZeroBitCount, 64 * 0) + XCTAssertEqual(T(x64: X( 0, 0, 0, 0)).trailingZeroBitCount, 64 * 4) + XCTAssertEqual(T(x64: X(~0, ~0, ~0, ~0)).trailingZeroBitCount, 64 * 0) XCTAssertEqual(T(x64: X( 2, 0, 0, 0)).trailingZeroBitCount, 64 * 0 + 1) XCTAssertEqual(T(x64: X( 0, 2, 0, 0)).trailingZeroBitCount, 64 * 1 + 1) diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Bits.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Bits.swift index 2f00eaa1..072bd2d2 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Bits.swift +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Bits.swift @@ -35,7 +35,7 @@ final class UIntXLTestsOnBits: XCTestCase { } func testBitWidth() { - XCTAssertEqual(T(words: [ 0, 0, 0, 0] as [UInt]).bitWidth, UInt.bitWidth * 1) + XCTAssertEqual(T(words: [ 0, 0, 0, 0] as [UInt]).bitWidth, UInt.bitWidth * 0) XCTAssertEqual(T(words: [~0, ~0, ~0, ~0] as [UInt]).bitWidth, UInt.bitWidth * 4) } @@ -45,7 +45,7 @@ final class UIntXLTestsOnBits: XCTestCase { } func testLeadingZeroBitCount() { - XCTAssertEqual(T(words: [ 0, 0, 0, 0] as [UInt]).leadingZeroBitCount, UInt.bitWidth * 1) + XCTAssertEqual(T(words: [ 0, 0, 0, 0] as [UInt]).leadingZeroBitCount, UInt.bitWidth * 0) XCTAssertEqual(T(words: [~0, ~0, ~0, ~0] as [UInt]).leadingZeroBitCount, UInt.bitWidth * 0) XCTAssertEqual(T(words: [ 2, 0, 0, 0] as [UInt]).leadingZeroBitCount, UInt.bitWidth * 1 - 2) @@ -55,8 +55,8 @@ final class UIntXLTestsOnBits: XCTestCase { } func testTrailingZeroBitCount() { - XCTAssertEqual(T(words: [ 0, 0, 0, 0] as [UInt]).leadingZeroBitCount, UInt.bitWidth * 1) - XCTAssertEqual(T(words: [~0, ~0, ~0, ~0] as [UInt]).leadingZeroBitCount, UInt.bitWidth * 0) + XCTAssertEqual(T(words: [ 0, 0, 0, 0] as [UInt]).trailingZeroBitCount, UInt.bitWidth * 0) + XCTAssertEqual(T(words: [~0, ~0, ~0, ~0] as [UInt]).trailingZeroBitCount, UInt.bitWidth * 0) XCTAssertEqual(T(words: [ 2, 0, 0, 0] as [UInt]).trailingZeroBitCount, UInt.bitWidth * 0 + 1) XCTAssertEqual(T(words: [ 0, 2, 0, 0] as [UInt]).trailingZeroBitCount, UInt.bitWidth * 1 + 1) diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Comparisons.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Comparisons.swift index 91ba44cf..2c5c7dae 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Comparisons.swift +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Comparisons.swift @@ -30,33 +30,33 @@ final class UIntXLTestsOnComparisons: XCTestCase { func testHashing() { var union = Set() - union.insert(T(words:[0, 0, 0, 0] as [UInt])) - union.insert(T(words:[1, 0, 0, 0] as [UInt])) - union.insert(T(words:[0, 1, 0, 0] as [UInt])) - union.insert(T(words:[0, 0, 1, 0] as [UInt])) - union.insert(T(words:[0, 0, 0, 1] as [UInt])) - union.insert(T(words:[0, 0, 0, 0] as [UInt])) - XCTAssertEqual(union.count, 5) + union.insert(T(words:[ 0, 0, 0, 0] as [UInt])) + union.insert(T(words:[ 1, 0, 0, 0] as [UInt])) + union.insert(T(words:[ 0, 1, 0, 0] as [UInt])) + union.insert(T(words:[ 0, 0, 1, 0] as [UInt])) + union.insert(T(words:[ 0, 0, 0, 1] as [UInt])) + union.insert(T(words:[ 0, 0, 0, 0] as [UInt])) + XCTAssertEqual(union.count, Int(5)) } func testComparing() { - NBKAssertComparisons(T(0), T(0), Int(0)) - NBKAssertComparisons(T(1), T(1), Int(0)) - NBKAssertComparisons(T(2), T(3), -Int(1)) - NBKAssertComparisons(T(3), T(2), Int(1)) - - NBKAssertComparisons(T(words:[0, 2, 3, 4]), T(words:[1, 2, 3, 4]), -Int(1)) - NBKAssertComparisons(T(words:[1, 0, 3, 4]), T(words:[1, 2, 3, 4]), -Int(1)) - NBKAssertComparisons(T(words:[1, 2, 0, 4]), T(words:[1, 2, 3, 4]), -Int(1)) - NBKAssertComparisons(T(words:[1, 2, 3, 0]), T(words:[1, 2, 3, 4]), -Int(1)) - NBKAssertComparisons(T(words:[0, 2, 3, 4]), T(words:[0, 2, 3, 4]), Int(0)) - NBKAssertComparisons(T(words:[1, 0, 3, 4]), T(words:[1, 0, 3, 4]), Int(0)) - NBKAssertComparisons(T(words:[1, 2, 0, 4]), T(words:[1, 2, 0, 4]), Int(0)) - NBKAssertComparisons(T(words:[1, 2, 3, 0]), T(words:[1, 2, 3, 0]), Int(0)) - NBKAssertComparisons(T(words:[1, 2, 3, 4]), T(words:[0, 2, 3, 4]), Int(1)) - NBKAssertComparisons(T(words:[1, 2, 3, 4]), T(words:[1, 0, 3, 4]), Int(1)) - NBKAssertComparisons(T(words:[1, 2, 3, 4]), T(words:[1, 2, 0, 4]), Int(1)) - NBKAssertComparisons(T(words:[1, 2, 3, 4]), T(words:[1, 2, 3, 0]), Int(1)) + NBKAssertComparisons(T(words:[ 0] as [UInt]), T(words:[ 0] as [UInt]), Int(0)) + NBKAssertComparisons(T(words:[ 1] as [UInt]), T(words:[ 1] as [UInt]), Int(0)) + NBKAssertComparisons(T(words:[ 2] as [UInt]), T(words:[ 3] as [UInt]), -Int(1)) + NBKAssertComparisons(T(words:[ 3] as [UInt]), T(words:[ 2] as [UInt]), Int(1)) + + NBKAssertComparisons(T(words:[ 0, 2, 3, 4] as [UInt]), T(words:[ 1, 2, 3, 4] as [UInt]), -Int(1)) + NBKAssertComparisons(T(words:[ 1, 0, 3, 4] as [UInt]), T(words:[ 1, 2, 3, 4] as [UInt]), -Int(1)) + NBKAssertComparisons(T(words:[ 1, 2, 0, 4] as [UInt]), T(words:[ 1, 2, 3, 4] as [UInt]), -Int(1)) + NBKAssertComparisons(T(words:[ 1, 2, 3, 0] as [UInt]), T(words:[ 1, 2, 3, 4] as [UInt]), -Int(1)) + NBKAssertComparisons(T(words:[ 0, 2, 3, 4] as [UInt]), T(words:[ 0, 2, 3, 4] as [UInt]), Int(0)) + NBKAssertComparisons(T(words:[ 1, 0, 3, 4] as [UInt]), T(words:[ 1, 0, 3, 4] as [UInt]), Int(0)) + NBKAssertComparisons(T(words:[ 1, 2, 0, 4] as [UInt]), T(words:[ 1, 2, 0, 4] as [UInt]), Int(0)) + NBKAssertComparisons(T(words:[ 1, 2, 3, 0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(0)) + NBKAssertComparisons(T(words:[ 1, 2, 3, 4] as [UInt]), T(words:[ 0, 2, 3, 4] as [UInt]), Int(1)) + NBKAssertComparisons(T(words:[ 1, 2, 3, 4] as [UInt]), T(words:[ 1, 0, 3, 4] as [UInt]), Int(1)) + NBKAssertComparisons(T(words:[ 1, 2, 3, 4] as [UInt]), T(words:[ 1, 2, 0, 4] as [UInt]), Int(1)) + NBKAssertComparisons(T(words:[ 1, 2, 3, 4] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(1)) } //=------------------------------------------------------------------------= @@ -64,83 +64,83 @@ final class UIntXLTestsOnComparisons: XCTestCase { //=------------------------------------------------------------------------= func testIsZero() { - XCTAssertTrue (( T(0)).isZero) - XCTAssertFalse(( T(1)).isZero) - XCTAssertFalse(( T(2)).isZero) + XCTAssertTrue (T(words:[ 0] as [UInt]).isZero) + XCTAssertFalse(T(words:[ 1] as [UInt]).isZero) + XCTAssertFalse(T(words:[ 2] as [UInt]).isZero) - XCTAssertFalse((~T(0)).isZero) - XCTAssertFalse((~T(1)).isZero) - XCTAssertFalse((~T(2)).isZero) + XCTAssertFalse(T(words:[~0] as [UInt]).isZero) + XCTAssertFalse(T(words:[~1] as [UInt]).isZero) + XCTAssertFalse(T(words:[~2] as [UInt]).isZero) } func testIsLessThanZero() { - XCTAssertFalse(( T(0)).isLessThanZero) - XCTAssertFalse(( T(1)).isLessThanZero) - XCTAssertFalse(( T(2)).isLessThanZero) + XCTAssertFalse(T(words:[ 0] as [UInt]).isLessThanZero) + XCTAssertFalse(T(words:[ 1] as [UInt]).isLessThanZero) + XCTAssertFalse(T(words:[ 2] as [UInt]).isLessThanZero) - XCTAssertFalse((~T(0)).isLessThanZero) - XCTAssertFalse((~T(1)).isLessThanZero) - XCTAssertFalse((~T(2)).isLessThanZero) + XCTAssertFalse(T(words:[~0] as [UInt]).isLessThanZero) + XCTAssertFalse(T(words:[~1] as [UInt]).isLessThanZero) + XCTAssertFalse(T(words:[~2] as [UInt]).isLessThanZero) } func testIsMoreThanZero() { - XCTAssertFalse(( T(0)).isMoreThanZero) - XCTAssertTrue (( T(1)).isMoreThanZero) - XCTAssertTrue (( T(2)).isMoreThanZero) + XCTAssertFalse(T(words:[ 0] as [UInt]).isMoreThanZero) + XCTAssertTrue (T(words:[ 1] as [UInt]).isMoreThanZero) + XCTAssertTrue (T(words:[ 2] as [UInt]).isMoreThanZero) - XCTAssertTrue ((~T(0)).isMoreThanZero) - XCTAssertTrue ((~T(1)).isMoreThanZero) - XCTAssertTrue ((~T(2)).isMoreThanZero) + XCTAssertTrue (T(words:[~0] as [UInt]).isMoreThanZero) + XCTAssertTrue (T(words:[~1] as [UInt]).isMoreThanZero) + XCTAssertTrue (T(words:[~2] as [UInt]).isMoreThanZero) } func testIsOdd() { - XCTAssertFalse(( T(0)).isOdd) - XCTAssertTrue (( T(1)).isOdd) - XCTAssertFalse(( T(2)).isOdd) + XCTAssertFalse(T(words:[ 0] as [UInt]).isOdd) + XCTAssertTrue (T(words:[ 1] as [UInt]).isOdd) + XCTAssertFalse(T(words:[ 2] as [UInt]).isOdd) - XCTAssertTrue ((~T(0)).isOdd) - XCTAssertFalse((~T(1)).isOdd) - XCTAssertTrue ((~T(2)).isOdd) + XCTAssertTrue (T(words:[~0] as [UInt]).isOdd) + XCTAssertFalse(T(words:[~1] as [UInt]).isOdd) + XCTAssertTrue (T(words:[~2] as [UInt]).isOdd) } func testIsEven() { - XCTAssertTrue (( T(0)).isEven) - XCTAssertFalse(( T(1)).isEven) - XCTAssertTrue (( T(2)).isEven) + XCTAssertTrue (T(words:[ 0] as [UInt]).isEven) + XCTAssertFalse(T(words:[ 1] as [UInt]).isEven) + XCTAssertTrue (T(words:[ 2] as [UInt]).isEven) - XCTAssertFalse((~T(0)).isEven) - XCTAssertTrue ((~T(1)).isEven) - XCTAssertFalse((~T(2)).isEven) + XCTAssertFalse(T(words:[~0] as [UInt]).isEven) + XCTAssertTrue (T(words:[~1] as [UInt]).isEven) + XCTAssertFalse(T(words:[~2] as [UInt]).isEven) } func testSignum() { - XCTAssertEqual(( T(0)).signum(), Int(0)) - XCTAssertEqual(( T(1)).signum(), Int(1)) - XCTAssertEqual(( T(2)).signum(), Int(1)) + XCTAssertEqual(T(words:[ 0] as [UInt]).signum(), Int(0)) + XCTAssertEqual(T(words:[ 1] as [UInt]).signum(), Int(1)) + XCTAssertEqual(T(words:[ 2] as [UInt]).signum(), Int(1)) - XCTAssertEqual((~T(0)).signum(), Int(1)) - XCTAssertEqual((~T(1)).signum(), Int(1)) - XCTAssertEqual((~T(2)).signum(), Int(1)) + XCTAssertEqual(T(words:[~0] as [UInt]).signum(), Int(1)) + XCTAssertEqual(T(words:[~1] as [UInt]).signum(), Int(1)) + XCTAssertEqual(T(words:[~2] as [UInt]).signum(), Int(1)) } func testIsPowerOf2() { - XCTAssertFalse((T( 0)).isPowerOf2) - XCTAssertTrue ((T( 1)).isPowerOf2) - XCTAssertTrue ((T( 2)).isPowerOf2) - XCTAssertFalse((T( 3)).isPowerOf2) - XCTAssertTrue ((T( 4)).isPowerOf2) - XCTAssertFalse((T( 5)).isPowerOf2) - XCTAssertFalse((T( 6)).isPowerOf2) - XCTAssertFalse((T( 7)).isPowerOf2) + XCTAssertFalse(T(words:[ 0] as [UInt]).isPowerOf2) + XCTAssertTrue (T(words:[ 1] as [UInt]).isPowerOf2) + XCTAssertTrue (T(words:[ 2] as [UInt]).isPowerOf2) + XCTAssertFalse(T(words:[ 3] as [UInt]).isPowerOf2) + XCTAssertTrue (T(words:[ 4] as [UInt]).isPowerOf2) + XCTAssertFalse(T(words:[ 5] as [UInt]).isPowerOf2) + XCTAssertFalse(T(words:[ 6] as [UInt]).isPowerOf2) + XCTAssertFalse(T(words:[ 7] as [UInt]).isPowerOf2) - XCTAssertFalse(T(words:[0, 0, 0, 0] as [UInt]).isPowerOf2) - XCTAssertTrue (T(words:[1, 0, 0, 0] as [UInt]).isPowerOf2) - XCTAssertFalse(T(words:[1, 1, 0, 0] as [UInt]).isPowerOf2) - XCTAssertTrue (T(words:[0, 1, 0, 0] as [UInt]).isPowerOf2) - XCTAssertFalse(T(words:[0, 1, 1, 0] as [UInt]).isPowerOf2) - XCTAssertTrue (T(words:[0, 0, 1, 0] as [UInt]).isPowerOf2) - XCTAssertFalse(T(words:[0, 0, 1, 1] as [UInt]).isPowerOf2) - XCTAssertTrue (T(words:[0, 0, 0, 1] as [UInt]).isPowerOf2) + XCTAssertFalse(T(words:[ 0, 0, 0, 0] as [UInt]).isPowerOf2) + XCTAssertTrue (T(words:[ 1, 0, 0, 0] as [UInt]).isPowerOf2) + XCTAssertFalse(T(words:[ 1, 1, 0, 0] as [UInt]).isPowerOf2) + XCTAssertTrue (T(words:[ 0, 1, 0, 0] as [UInt]).isPowerOf2) + XCTAssertFalse(T(words:[ 0, 1, 1, 0] as [UInt]).isPowerOf2) + XCTAssertTrue (T(words:[ 0, 0, 1, 0] as [UInt]).isPowerOf2) + XCTAssertFalse(T(words:[ 0, 0, 1, 1] as [UInt]).isPowerOf2) + XCTAssertTrue (T(words:[ 0, 0, 0, 1] as [UInt]).isPowerOf2) } } diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Logic.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Logic.swift index 4735c741..aac2b96c 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Logic.swift +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Logic.swift @@ -29,7 +29,7 @@ final class UIntXLTestsOnLogic: XCTestCase { //=------------------------------------------------------------------------= func testNot() { - NBKAssertNot(T(words:[ 0, 0, 0, 0] as [UInt]), T(words:[~0, 0, 0, 0] as [UInt])) + NBKAssertNot(T(words:[ 0, 0, 0, 0] as [UInt]), T(words:[ 0, 0, 0, 0] as [UInt])) NBKAssertNot(T(words:[~0, ~0, ~0, ~0] as [UInt]), T(words:[ 0, 0, 0, 0] as [UInt])) NBKAssertNot(T(words:[ 0, 1, 2, 3] as [UInt]), T(words:[~0, ~1, ~2, ~3] as [UInt])) diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Subtraction.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Subtraction.swift index 1e8eda00..fe29b317 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Subtraction.swift +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Subtraction.swift @@ -36,10 +36,10 @@ final class UIntXLTestsOnSubtraction: XCTestCase { } func testSubtractingReportingOverflow() { - NBKAssertSubtraction(T(1), T(0), Int(0), T(1)) - NBKAssertSubtraction(T(1), T(1), Int(0), T(0)) - NBKAssertSubtraction(T(1), T(2), Int(0), ~T(0), true) - NBKAssertSubtraction(T(1), T(3), Int(0), ~T(1), true) + NBKAssertSubtraction(T(1), T(0), Int(0), T(words:[ 1] as [UInt])) + NBKAssertSubtraction(T(1), T(1), Int(0), T(words:[ 0] as [UInt])) + NBKAssertSubtraction(T(1), T(2), Int(0), T(words:[~0] as [UInt]), true) + NBKAssertSubtraction(T(1), T(3), Int(0), T(words:[~1] as [UInt]), true) } func testSubtractingAtIndex() { @@ -72,10 +72,10 @@ final class UIntXLTestsOnSubtraction: XCTestCase { } func testSubtractingDigitReportingOverflow() { - NBKAssertSubtractionByDigit(T(1), UInt(0), Int(0), T(1)) - NBKAssertSubtractionByDigit(T(1), UInt(1), Int(0), T(0)) - NBKAssertSubtractionByDigit(T(1), UInt(2), Int(0), ~T(0), true) - NBKAssertSubtractionByDigit(T(1), UInt(3), Int(0), ~T(1), true) + NBKAssertSubtractionByDigit(T(1), UInt(0), Int(0), T(words:[ 1] as [UInt])) + NBKAssertSubtractionByDigit(T(1), UInt(1), Int(0), T(words:[ 0] as [UInt])) + NBKAssertSubtractionByDigit(T(1), UInt(2), Int(0), T(words:[~0] as [UInt]), true) + NBKAssertSubtractionByDigit(T(1), UInt(3), Int(0), T(words:[~1] as [UInt]), true) } func testSubtractingDigitAtIndex() { diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Words.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Words.swift index ad38587f..1ec31750 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Words.swift +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Words.swift @@ -29,14 +29,13 @@ final class UIntXLTestsOnWords: XCTestCase { //=------------------------------------------------------------------------= func testWords() { - NBKAssertWords(T(words:[ ]), [0 ]) - NBKAssertWords(T(words:[0 ]), [0 ]) + NBKAssertWords(T(words:[ ]), [ ]) NBKAssertWords(T(words:[1 ]), [1 ]) NBKAssertWords(T(words:[1, 2 ]), [1, 2 ]) NBKAssertWords(T(words:[1, 2, 3 ]), [1, 2, 3 ]) NBKAssertWords(T(words:[1, 2, 3, 4]), [1, 2, 3, 4]) - NBKAssertWords(T(words:[0, 0, 0, 0]), [0 ]) + NBKAssertWords(T(words:[0, 0, 0, 0]), [ ]) NBKAssertWords(T(words:[1, 0, 0, 0]), [1 ]) NBKAssertWords(T(words:[1, 2, 0, 0]), [1, 2 ]) NBKAssertWords(T(words:[1, 2, 3, 0]), [1, 2, 3 ]) @@ -46,27 +45,41 @@ final class UIntXLTestsOnWords: XCTestCase { func testWordsX64() throws { guard MemoryLayout.size == MemoryLayout.size else { throw XCTSkip() } - NBKAssertWords(T(x64: [ ] as X), [0 ]) - NBKAssertWords(T(x64: [0, 0, 0, 0] as X), [0 ]) - NBKAssertWords(T(x64: [1, 0, 0, 0] as X), [1 ]) - NBKAssertWords(T(x64: [1, 2, 0, 0] as X), [1, 2 ]) - NBKAssertWords(T(x64: [1, 2, 3, 0] as X), [1, 2, 3 ]) - NBKAssertWords(T(x64: [1, 2, 3, 4] as X), [1, 2, 3, 4]) + NBKAssertWords(T(x64:[ ] as X), [ ]) + NBKAssertWords(T(x64:[1 ] as X), [1 ]) + NBKAssertWords(T(x64:[1, 2 ] as X), [1, 2 ]) + NBKAssertWords(T(x64:[1, 2, 3 ] as X), [1, 2, 3 ]) + NBKAssertWords(T(x64:[1, 2, 3, 4] as X), [1, 2, 3, 4]) + + NBKAssertWords(T(x64:[0, 0, 0, 0] as X), [ ]) + NBKAssertWords(T(x64:[1, 0, 0, 0] as X), [1 ]) + NBKAssertWords(T(x64:[1, 2, 0, 0] as X), [1, 2 ]) + NBKAssertWords(T(x64:[1, 2, 3, 0] as X), [1, 2, 3 ]) + NBKAssertWords(T(x64:[1, 2, 3, 4] as X), [1, 2, 3, 4]) } func testWordsX32() throws { guard MemoryLayout.size == MemoryLayout.size else { throw XCTSkip() } - NBKAssertWords(T(x32: [ ] as Y), [0 ]) - NBKAssertWords(T(x32: [0, 0, 0, 0, 0, 0, 0, 0] as Y), [0 ]) - NBKAssertWords(T(x32: [1, 0, 0, 0, 0, 0, 0, 0] as Y), [1 ]) - NBKAssertWords(T(x32: [1, 2, 0, 0, 0, 0, 0, 0] as Y), [1, 2 ]) - NBKAssertWords(T(x32: [1, 2, 3, 0, 0, 0, 0, 0] as Y), [1, 2, 3 ]) - NBKAssertWords(T(x32: [1, 2, 3, 4, 0, 0, 0, 0] as Y), [1, 2, 3, 4 ]) - NBKAssertWords(T(x32: [1, 2, 3, 4, 5, 0, 0, 0] as Y), [1, 2, 3, 4, 5 ]) - NBKAssertWords(T(x32: [1, 2, 3, 4, 5, 6, 0, 0] as Y), [1, 2, 3, 4, 5, 6 ]) - NBKAssertWords(T(x32: [1, 2, 3, 4, 5, 6, 7, 0] as Y), [1, 2, 3, 4, 5, 6, 7 ]) - NBKAssertWords(T(x32: [1, 2, 3, 4, 5, 6, 7, 8] as Y), [1, 2, 3, 4, 5, 6, 7, 8]) + NBKAssertWords(T(x32:[ ] as Y), [ ]) + NBKAssertWords(T(x32:[1 ] as Y), [1 ]) + NBKAssertWords(T(x32:[1, 2 ] as Y), [1, 2 ]) + NBKAssertWords(T(x32:[1, 2, 3 ] as Y), [1, 2, 3 ]) + NBKAssertWords(T(x32:[1, 2, 3, 4 ] as Y), [1, 2, 3, 4 ]) + NBKAssertWords(T(x32:[1, 2, 3, 4, 5 ] as Y), [1, 2, 3, 4, 5 ]) + NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6 ] as Y), [1, 2, 3, 4, 5, 6 ]) + NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6, 7 ] as Y), [1, 2, 3, 4, 5, 6, 7 ]) + NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6, 7, 8] as Y), [1, 2, 3, 4, 5, 6, 7, 8]) + + NBKAssertWords(T(x32:[0, 0, 0, 0, 0, 0, 0, 0] as Y), [ ]) + NBKAssertWords(T(x32:[1, 0, 0, 0, 0, 0, 0, 0] as Y), [1 ]) + NBKAssertWords(T(x32:[1, 2, 0, 0, 0, 0, 0, 0] as Y), [1, 2 ]) + NBKAssertWords(T(x32:[1, 2, 3, 0, 0, 0, 0, 0] as Y), [1, 2, 3 ]) + NBKAssertWords(T(x32:[1, 2, 3, 4, 0, 0, 0, 0] as Y), [1, 2, 3, 4 ]) + NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 0, 0, 0] as Y), [1, 2, 3, 4, 5 ]) + NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6, 0, 0] as Y), [1, 2, 3, 4, 5, 6 ]) + NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6, 7, 0] as Y), [1, 2, 3, 4, 5, 6, 7 ]) + NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6, 7, 8] as Y), [1, 2, 3, 4, 5, 6, 7, 8]) } } From c9fd45188d87dc26d91243a30d9073930feb6bcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sun, 16 Jul 2023 08:52:45 +0200 Subject: [PATCH 005/133] NBKFlexibleWidthKit: Text. --- Sources/NBKCoreKit/Private/Collection.swift | 17 ++ Sources/NBKCoreKit/Private/Text.swift | 56 ---- .../Private/Text/RadixAlphabet.swift | 95 ++++++ .../Private/Text/RadixIntegers.swift} | 87 ++++-- .../Private/Text/RadixUIntRoot.swift | 279 ++++++++++++++++++ .../NBKDoubleWidth+Text+Radix.swift | 43 ++- .../Private/RadixAlphabet.swift | 88 ------ .../Private/RadixUIntRoot.swift | 274 ----------------- Sources/NBKDoubleWidthKit/Private/Text.swift | 134 --------- .../NBKFlexibleWidth+Text+Radix.swift | 61 ++-- .../Private/RadixAlphabet.swift | 88 ------ .../Private/RadixUIntRoot.swift | 274 ----------------- .../Private/RadixAlphabet.swift | 9 +- .../Private/RadixIntegers.swift} | 63 +++- .../Private/RadixUIntRoot.swift | 5 +- Tests/NBKCoreKitTests/Private/Text.swift | 67 ----- 16 files changed, 560 insertions(+), 1080 deletions(-) delete mode 100644 Sources/NBKCoreKit/Private/Text.swift create mode 100644 Sources/NBKCoreKit/Private/Text/RadixAlphabet.swift rename Sources/{NBKFlexibleWidthKit/Private/Text.swift => NBKCoreKit/Private/Text/RadixIntegers.swift} (59%) create mode 100644 Sources/NBKCoreKit/Private/Text/RadixUIntRoot.swift delete mode 100644 Sources/NBKDoubleWidthKit/Private/RadixAlphabet.swift delete mode 100644 Sources/NBKDoubleWidthKit/Private/RadixUIntRoot.swift delete mode 100644 Sources/NBKDoubleWidthKit/Private/Text.swift delete mode 100644 Sources/NBKFlexibleWidthKit/Private/RadixAlphabet.swift delete mode 100644 Sources/NBKFlexibleWidthKit/Private/RadixUIntRoot.swift rename Tests/{NBKDoubleWidthKitTests => NBKCoreKitTests}/Private/RadixAlphabet.swift (90%) rename Tests/{NBKDoubleWidthKitTests/Private/Text.swift => NBKCoreKitTests/Private/RadixIntegers.swift} (53%) rename Tests/{NBKDoubleWidthKitTests => NBKCoreKitTests}/Private/RadixUIntRoot.swift (92%) delete mode 100644 Tests/NBKCoreKitTests/Private/Text.swift diff --git a/Sources/NBKCoreKit/Private/Collection.swift b/Sources/NBKCoreKit/Private/Collection.swift index 71fd6b6c..8ccebfa9 100644 --- a/Sources/NBKCoreKit/Private/Collection.swift +++ b/Sources/NBKCoreKit/Private/Collection.swift @@ -13,6 +13,23 @@ extension NBK { + //=------------------------------------------------------------------------= + // MARK: Transformations x Drop + //=------------------------------------------------------------------------= + + /// Drops elements that the satisfy the predicate from the end of the given `collection`. + @inlinable public static func dropLast(from collection: T, while predicate: (T.Element) -> Bool) -> T.SubSequence where T: BidirectionalCollection { + var newEndIndex = collection.endIndex + + backwards: while newEndIndex > collection.startIndex { + let newLastIndex = collection.index(before: newEndIndex) + guard predicate(collection[newLastIndex]) else { break } + newEndIndex = newLastIndex + } + + return collection.prefix(upTo: newEndIndex) + } + //=------------------------------------------------------------------------= // MARK: Transformations x Remove Count //=------------------------------------------------------------------------= diff --git a/Sources/NBKCoreKit/Private/Text.swift b/Sources/NBKCoreKit/Private/Text.swift deleted file mode 100644 index ce980042..00000000 --- a/Sources/NBKCoreKit/Private/Text.swift +++ /dev/null @@ -1,56 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -//*============================================================================* -// MARK: * NBK x Text -//*============================================================================* - -extension NBK { - - //=------------------------------------------------------------------------= - // MARK: Utilities - //=------------------------------------------------------------------------= - - /// Returns an `UTF-8` encoded integer's `sign` and `body`. - /// - /// ``` - /// ┌─────── → ──────┬────────┐ - /// │ utf8 │ sign │  body │ - /// ├─────── → ──────┼────────┤ - /// │ "+123" │ plus │ "123" │ - /// │ "-123" │ minus │ "123" │ - /// │ "~123" │ plus │ "~123" │ - /// └─────── → ──────┴────────┘ - /// ``` - /// - @inlinable public static func integerComponents(utf8: T) -> (sign: Sign, body: T.SubSequence) where T: Collection { - var body = utf8[...] as T.SubSequence - let sign = NBK.removeSignPrefix(utf8: &body) ?? Sign.plus - return (sign: sign, body: body) - } - - /// Removes and returns an `UTF-8` encoded `sign` prefix, if it exists. - /// - /// ``` - /// ┌─────── → ──────┬────────┐ - /// │ self │ sign │  self │ - /// ├─────── → ──────┼────────┤ - /// │ "+123" │ plus │ "123" │ - /// │ "-123" │ minus │ "123" │ - /// │ "~123" │ nil │ "~123" │ - /// └─────── → ──────┴────────┘ - /// ``` - /// - @inlinable public static func removeSignPrefix(utf8: inout T) -> Sign? where T: Collection, T == T.SubSequence { - switch utf8.first { - case UInt8(ascii: "+"): utf8.removeFirst(); return Sign.plus - case UInt8(ascii: "-"): utf8.removeFirst(); return Sign.minus - default: return nil } - } -} diff --git a/Sources/NBKCoreKit/Private/Text/RadixAlphabet.swift b/Sources/NBKCoreKit/Private/Text/RadixAlphabet.swift new file mode 100644 index 00000000..a7938c6b --- /dev/null +++ b/Sources/NBKCoreKit/Private/Text/RadixAlphabet.swift @@ -0,0 +1,95 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +//*============================================================================* +// MARK: * NBK x Radix Alphabet +//*============================================================================* + +extension NBK { + + //*========================================================================* + // MARK: * Decoder x Any + //*========================================================================* + + /// Decodes values in `0` to `36` from ASCII. + @frozen public struct AnyRadixAlphabetDecoder { + + //=--------------------------------------------------------------------= + // MARK: State + //=--------------------------------------------------------------------= + + @usableFromInline let x00x10: UInt8 + @usableFromInline let x10x36: UInt8 + + //=--------------------------------------------------------------------= + // MARK: Initializers + //=--------------------------------------------------------------------= + + @inlinable public init(radix: Int) { + precondition(2 ... 36 ~= radix, "radix must be in 2 through 36") + let count = UInt8(truncatingIfNeeded: radix) + let carry = count.subtractingReportingOverflow(10) + if carry.overflow { + self.x00x10 = count + self.x10x36 = 00000 + } else { + self.x00x10 = 00010 + self.x10x36 = carry.partialValue + } + } + + //=--------------------------------------------------------------------= + // MARK: Utilities + //=--------------------------------------------------------------------= + + @inlinable public func decode(_ ascii: UInt8) -> UInt8? { + var index: UInt8 + + index = ascii &- UInt8(ascii: "0"); if index < self.x00x10 { return index } + index = ascii &- UInt8(ascii: "A"); if index < self.x10x36 { return index &+ 10 } + index = ascii &- UInt8(ascii: "a"); if index < self.x10x36 { return index &+ 10 } + + return nil + } + } + + //*========================================================================* + // MARK: * Encoder x Max + //*========================================================================* + + /// Encodes values in `0` to `36` to ASCII. + @frozen public struct MaxRadixAlphabetEncoder { + + //=--------------------------------------------------------------------= + // MARK: State + //=--------------------------------------------------------------------= + + @usableFromInline let x00x10: UInt8 + @usableFromInline let x10x36: UInt8 + + //=--------------------------------------------------------------------= + // MARK: Initializers + //=--------------------------------------------------------------------= + + @inlinable public init(uppercase: Bool) { + self.x00x10 = UInt8(ascii: "0") + self.x10x36 = UInt8(ascii: uppercase ? "A" : "a") &- 10 + } + + //=--------------------------------------------------------------------= + // MARK: Utilities + //=--------------------------------------------------------------------= + + @inlinable public func encode(_ value: UInt8) -> UInt8? { + if value < 10 { return value &+ self.x00x10 } + if value < 36 { return value &+ self.x10x36 } + return nil + } + } +} diff --git a/Sources/NBKFlexibleWidthKit/Private/Text.swift b/Sources/NBKCoreKit/Private/Text/RadixIntegers.swift similarity index 59% rename from Sources/NBKFlexibleWidthKit/Private/Text.swift rename to Sources/NBKCoreKit/Private/Text/RadixIntegers.swift index 997b7a90..5b4e9974 100644 --- a/Sources/NBKFlexibleWidthKit/Private/Text.swift +++ b/Sources/NBKCoreKit/Private/Text/RadixIntegers.swift @@ -7,16 +7,55 @@ // See http://www.apache.org/licenses/LICENSE-2.0 for license information. //=----------------------------------------------------------------------------= -import NBKCoreKit - //*============================================================================* -// MARK: * NBK x Text x UInt +// MARK: * NBK x Integer Text //*============================================================================* -extension UInt { +extension NBK { //=------------------------------------------------------------------------= - // MARK: Details x Text + // MARK: Details x Components + //=------------------------------------------------------------------------= + + /// Returns an `UTF-8` encoded integer's `sign` and `body`. + /// + /// ``` + /// ┌─────── → ──────┬────────┐ + /// │ utf8 │ sign │  body │ + /// ├─────── → ──────┼────────┤ + /// │ "+123" │ plus │ "123" │ + /// │ "-123" │ minus │ "123" │ + /// │ "~123" │ plus │ "~123" │ + /// └─────── → ──────┴────────┘ + /// ``` + /// + @inlinable public static func integerComponents(utf8: T) -> (sign: Sign, body: T.SubSequence) where T: Collection { + var body = utf8[...] as T.SubSequence + let sign = NBK.removeSignPrefix(utf8: &body) ?? Sign.plus + return (sign: sign, body: body) + } + + /// Removes and returns an `UTF-8` encoded `sign` prefix, if it exists. + /// + /// ``` + /// ┌─────── → ──────┬────────┐ + /// │ self │ sign │  self │ + /// ├─────── → ──────┼────────┤ + /// │ "+123" │ plus │ "123" │ + /// │ "-123" │ minus │ "123" │ + /// │ "~123" │ nil │ "~123" │ + /// └─────── → ──────┴────────┘ + /// ``` + /// + @inlinable public static func removeSignPrefix(utf8: inout T) -> Sign? where T: Collection, T == T.SubSequence { + switch utf8.first { + case UInt8(ascii: "+"): utf8.removeFirst(); return Sign.plus + case UInt8(ascii: "-"): utf8.removeFirst(); return Sign.minus + default: return nil } + } + + //=------------------------------------------------------------------------= + // MARK: Details x Decode //=------------------------------------------------------------------------= /// Creates a new instance by truncating the given `digits` and `radix`. @@ -32,46 +71,38 @@ extension UInt { /// /// Creating a new decoder is faster than passing one as an argument. /// - @inlinable static func truncating(digits: NBK.UnsafeUTF8, radix: Int) -> Self? { + @inlinable public static func truncatingAsUInt(digits: NBK.UnsafeUTF8, radix: Int) -> UInt? { guard !digits.isEmpty else { return nil } //=--------------------------------------= - let alphabet = AnyRadixAlphabetDecoder(radix: radix) + let alphabet = NBK.AnyRadixAlphabetDecoder(radix: radix) //=--------------------------------------= - var value = Self.zero + var value = UInt.zero for digit in digits { guard let addend = alphabet.decode(digit) else { return nil } - value &*= Self(bitPattern: radix) - value &+= Self(truncatingIfNeeded: addend) + value &*= UInt(bitPattern: radix) + value &+= UInt(truncatingIfNeeded: addend) } - return value as Self + return value as UInt } -} - -//*============================================================================* -// MARK: * NBK x Text x String -//*============================================================================* - -extension String { //=------------------------------------------------------------------------= - // MARK: Initializers + // MARK: Details x Encode //=------------------------------------------------------------------------= - /// Encodes unchecked chunks, using the given format. + /// Encodes unchecked chunks, using the given UTF-8 format. /// /// In this context, a chunk is a digit in the base of the given radix's power. /// - @inlinable static func fromUTF8Unchecked(chunks: some RandomAccessCollection, radix: some RadixUIntRoot, + @inlinable public static func integerTextUnchecked(chunks: some RandomAccessCollection, radix: some _NBKRadixUIntRoot, alphabet: MaxRadixAlphabetEncoder, prefix: NBK.UnsafeUTF8, suffix: NBK.UnsafeUTF8) -> String { - assert(!chunks.isEmpty, "chunks must not be empty") - assert(!chunks.last!.isZero || chunks.count == 1, "chunks must not have redundant zeros") - assert( radix.power.isZero || chunks.allSatisfy({ $0 < radix.power }), "chunks must be less than radix's power") + assert(chunks.count <= 1 || chunks.last != 0, "chunks must not contain redundant zeros") + assert(radix.power.isZero || chunks.allSatisfy({ $0 < radix.power }), "chunks must be less than radix's power") //=--------------------------------------= var remainders = chunks[...] - let mostSignificantChunk = remainders.removeLast() - return String.withUTF8Unchecked(chunk: mostSignificantChunk, radix: radix, alphabet: alphabet) { first in + let mostSignificantChunk = remainders.popLast() ?? UInt() + return NBK.withIntegerTextUnchecked(chunk: mostSignificantChunk, radix: radix, alphabet: alphabet) { first in var count: Int count = prefix.count count += first .count @@ -107,11 +138,11 @@ extension String { } } - /// Encodes an unchecked chunk, using the given format. + /// Encodes an unchecked chunk, using the given UTF-8 format. /// /// In this context, a chunk is a digit in the base of the given radix's power. /// - @inlinable static func withUTF8Unchecked(chunk: UInt, radix: some RadixUIntRoot, + @inlinable public static func withIntegerTextUnchecked(chunk: UInt, radix: some _NBKRadixUIntRoot, alphabet: MaxRadixAlphabetEncoder, body: (NBK.UnsafeUTF8) -> T) -> T { assert(radix.power.isZero || chunk < radix.power, "chunks must be less than radix's power") return Swift.withUnsafeTemporaryAllocation(of: UInt8.self, capacity: radix.exponent) { utf8 in diff --git a/Sources/NBKCoreKit/Private/Text/RadixUIntRoot.swift b/Sources/NBKCoreKit/Private/Text/RadixUIntRoot.swift new file mode 100644 index 00000000..c60b51cf --- /dev/null +++ b/Sources/NBKCoreKit/Private/Text/RadixUIntRoot.swift @@ -0,0 +1,279 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +//*============================================================================* +// MARK: * NBK x Radix UInt Root +//*============================================================================* + +/// Max power and exponent in `pow(base, exponent) <= UInt.max + 1`. +/// +/// - The `base` is `>= 2` and `<= 36` +/// - The `exponent` is `>= 1` and `<= UInt.bitWidth` +/// - A power of `UInt.max + 1` is represented by `0` +/// +public protocol _NBKRadixUIntRoot { + + //=------------------------------------------------------------------------= + // MARK: State + //=------------------------------------------------------------------------= + + @inlinable var base: UInt { get } + + @inlinable var exponent: UInt { get } + + @inlinable var power: UInt { get } + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + /// Divides `dividend` by the `base` of this solution. + @inlinable func dividing(_ dividend: UInt) -> QR +} + +//=----------------------------------------------------------------------------= +// MARK: + Details +//=----------------------------------------------------------------------------= + +extension _NBKRadixUIntRoot { + + //=------------------------------------------------------------------------= + // MARK: Accessors + //=------------------------------------------------------------------------= + + @inlinable public var base: Int { + assert((self.base as UInt) <= 36) + return Int(bitPattern: self.base) + } + + @inlinable public var exponent: Int { + assert((self.exponent as UInt) <= UInt.bitWidth) + return Int(bitPattern: self.exponent) + } + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + @inlinable public func dividing(_ dividend: UInt) -> QR { + dividend.quotientAndRemainder(dividingBy: self.base) + } +} + +//*============================================================================* +// MARK: * NBK x Radix UInt Root x Implementations +//*============================================================================* + +extension NBK { + + //*========================================================================* + // MARK: * Perfect + //*========================================================================* + + /// A ``RadixUIntRoot`` with a power that is zero. + @frozen public struct PerfectRadixUIntRoot: _NBKRadixUIntRoot { + + //=--------------------------------------------------------------------= + // MARK: State + //=--------------------------------------------------------------------= + + @usableFromInline let root: AnyRadixUIntRoot + @usableFromInline let special: QR + + //=--------------------------------------------------------------------= + // MARK: Initializers + //=--------------------------------------------------------------------= + + @inlinable public init(unchecked: AnyRadixUIntRoot) { + assert(unchecked.power.isZero) + assert([2, 4, 16].contains(unchecked.base)) + self.root = unchecked + self.special.quotient = UInt(bitPattern: self.root.base.trailingZeroBitCount) + self.special.remainder = self.root.base &- 1 + } + + //=--------------------------------------------------------------------= + // MARK: Accessors + //=--------------------------------------------------------------------= + + @inlinable public var base: UInt { + self.root.base + } + + @inlinable public var exponent: UInt { + self.root.exponent + } + + @inlinable public var power: UInt { + self.root.power + } + + //=--------------------------------------------------------------------= + // MARK: Utilities + //=--------------------------------------------------------------------= + + @inlinable public func dividing(_ dividend: UInt) -> QR { + QR(dividend &>> self.special.quotient, dividend & self.special.remainder) + } + } + + //*========================================================================* + // MARK: * NBK x Imperfect + //*========================================================================* + + /// A ``RadixUIntRoot`` with a power that is non-zero. + @frozen public struct ImperfectRadixUIntRoot: _NBKRadixUIntRoot { + + //=--------------------------------------------------------------------= + // MARK: State + //=--------------------------------------------------------------------= + + @usableFromInline let root: AnyRadixUIntRoot + + //=--------------------------------------------------------------------= + // MARK: Initializers + //=--------------------------------------------------------------------= + + @inlinable public init(unchecked: AnyRadixUIntRoot) { + assert(!unchecked.power.isZero) + assert(![2, 4, 16].contains(unchecked.base)) + self.root = unchecked + } + + //=--------------------------------------------------------------------= + // MARK: Accessors + //=--------------------------------------------------------------------= + + @inlinable public var base: UInt { + self.root.base + } + + @inlinable public var exponent: UInt { + self.root.exponent + } + + @inlinable public var power: UInt { + self.root.power + } + + //=--------------------------------------------------------------------= + // MARK: Utilities + //=--------------------------------------------------------------------= + + /// Overestimates how many times its power divides the magnitude. + @inlinable public func divisibilityByPowerUpperBound(_ magnitude: some UnsignedInteger) -> Int { + magnitude.bitWidth / 36.leadingZeroBitCount &+ 1 + } + } + + //*========================================================================* + // MARK: * Any + //*========================================================================* + + /// A ``RadixUIntRoot`` with a power that may be zero. + @frozen public struct AnyRadixUIntRoot: _NBKRadixUIntRoot { + + @usableFromInline typealias Solution = (exponent: UInt, power: UInt) + + //=--------------------------------------------------------------------= + // MARK: State + //=--------------------------------------------------------------------= + + public let base: UInt + public let exponent: UInt + public let power: UInt + + //=--------------------------------------------------------------------= + // MARK: Initializers + //=--------------------------------------------------------------------= + + /// Creates a new instance from the given radix. + /// + /// The radix must not exceed `36` because that is the size of the alphabet. + /// + /// - Parameter radix: A value from `2` through `36`. + /// + @inlinable public init(_ radix: Int) { + Swift.precondition(2 ... 36 ~= radix) + (self.base) = UInt(bitPattern: radix) + (self.exponent, self.power) = Self.solution(unchecked: self.base) + } + + //=--------------------------------------------------------------------= + // MARK: Utilities + //=--------------------------------------------------------------------= + + /// Returns the largest exponent in `pow(radix, exponent) <= UInt.max + 1`. + @inlinable static func solution(unchecked radix: UInt) -> Solution { + switch radix.isPowerOf2 { + case true: return Self.solutionAssumingRadixIsPowerOf2 (unchecked: radix) + case false: return Self.solutionAssumingRadixIsNotPowerOf2(unchecked: radix) } + } + + /// Returns the largest exponent in `pow(radix, exponent) <= UInt.max + 1`. + @inlinable static func solutionAssumingRadixIsPowerOf2(unchecked radix: UInt) -> Solution { + assert(radix >= 2) + assert(radix.isPowerOf2) + //=--------------------------------------= + let zeros = UInt(bitPattern: radix.trailingZeroBitCount) + //=--------------------------------------= + // radix: 002, 004, 016, 256, ... + //=--------------------------------------= + if zeros.isPowerOf2 { + let exponent = UInt(bitPattern: UInt.bitWidth &>> zeros.trailingZeroBitCount) + return Solution(exponent: exponent, power: 0) + //=--------------------------------------= + // radix: 008, 032, 064, 128, ... + //=--------------------------------------= + } else { + let exponent = UInt(bitPattern: UInt.bitWidth) / (zeros as UInt) + return Solution(exponent: exponent, power: 1 &<< (zeros &* exponent)) + } + } + + /// Returns the largest exponent in `pow(radix, exponent) <= UInt.max + 1`. + @inlinable static func solutionAssumingRadixIsNotPowerOf2(unchecked radix: UInt) -> Solution { + assert(radix >= 2) + assert(radix.isPowerOf2 == false) + //=--------------------------------------= + // radix: 003, 005, 006, 007, ... + //=--------------------------------------= + let capacity: Int = UInt.bitWidth.trailingZeroBitCount - 1 + return Swift.withUnsafeTemporaryAllocation(of: Solution.self, capacity: capacity) { squares in + //=----------------------------------= + // de/init: pointee is trivial + //=----------------------------------= + var solution = Solution(1, radix) + var index = squares.startIndex as Int + + loop: while index < squares.endIndex { + squares[index] = solution + let product = solution.power.multipliedReportingOverflow(by: solution.power) + if product.overflow { break loop } + + solution.exponent &<<= 1 as UInt + solution.power = product.partialValue + squares.formIndex(after: &index) + } + + loop: while index > squares.startIndex { + squares.formIndex(before: &index) + let square = squares[index] + let product = solution.power.multipliedReportingOverflow(by: square.power) + if product.overflow { continue loop } + + solution.exponent &+= square.exponent + solution.power = product.partialValue + } + + return solution as Solution + } + } + } +} diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text+Radix.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text+Radix.swift index 4f59a696..2e0ea17e 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text+Radix.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text+Radix.swift @@ -23,7 +23,7 @@ extension NBKDoubleWidth { var description = String(description) let value: Optional = description.withUTF8 { utf8 in - let (radix) = AnyRadixUIntRoot(radix) + let (radix) = NBK.AnyRadixUIntRoot(radix) let (sign,body) = NBK.integerComponents(utf8: utf8) let (digits) = NBK.UnsafeUTF8(rebasing: body) let (magnitude) = Magnitude(digits: digits, radix: radix) @@ -39,8 +39,8 @@ extension NBKDoubleWidth { @inlinable public func description(radix: Int = 10, uppercase: Bool = false) -> String { Swift.withUnsafePointer(to: UInt8(ascii: "-")) { minus in - let radix = AnyRadixUIntRoot(radix) - let alphabet = MaxRadixAlphabetEncoder(uppercase: uppercase) + let radix = NBK.AnyRadixUIntRoot(radix) + let alphabet = NBK.MaxRadixAlphabetEncoder(uppercase: uppercase) let prefix = NBK.UnsafeUTF8(start: minus, count: Int(bit: self.isLessThanZero)) let suffix = NBK.UnsafeUTF8(start: nil, count: Int.zero) return self.magnitude.description(radix: radix, alphabet: alphabet, prefix: prefix, suffix: suffix) @@ -58,13 +58,13 @@ extension NBKDoubleWidth where High == High.Magnitude { // MARK: Details x Decode x Private //=------------------------------------------------------------------------= - @inlinable init?(digits: NBK.UnsafeUTF8, radix: AnyRadixUIntRoot) { + @inlinable init?(digits: NBK.UnsafeUTF8, radix: NBK.AnyRadixUIntRoot) { switch radix.power.isZero { - case true: self.init(digits: digits, radix: PerfectRadixUIntRoot(unchecked: radix)) - case false: self.init(digits: digits, radix: ImperfectRadixUIntRoot(unchecked: radix)) } + case true: self.init(digits: digits, radix: NBK .PerfectRadixUIntRoot(unchecked: radix)) + case false: self.init(digits: digits, radix: NBK.ImperfectRadixUIntRoot(unchecked: radix)) } } - @inlinable init?(digits: NBK.UnsafeUTF8, radix: PerfectRadixUIntRoot) { + @inlinable init?(digits: NBK.UnsafeUTF8, radix: NBK.PerfectRadixUIntRoot) { guard !digits.isEmpty else { return nil } //=--------------------------------------= var digits = digits.drop(while:{ $0 == 48 }) @@ -76,7 +76,7 @@ extension NBKDoubleWidth where High == High.Magnitude { value[index] = UInt.zero } else { let chunk = NBK.UnsafeUTF8(rebasing: NBK.removeSuffix(from: &digits, maxLength: radix.exponent)) - guard let word = UInt.truncating(digits: chunk, radix: radix.base) else { return error = true } + guard let word = NBK.truncatingAsUInt(digits: chunk, radix: radix.base) else { return error = true } value[index] = word } } @@ -85,7 +85,7 @@ extension NBKDoubleWidth where High == High.Magnitude { if !error, digits.isEmpty { self = value } else { return nil } } - @inlinable init?(digits: NBK.UnsafeUTF8, radix: ImperfectRadixUIntRoot) { + @inlinable init?(digits: NBK.UnsafeUTF8, radix: NBK.ImperfectRadixUIntRoot) { guard !digits.isEmpty else { return nil } //=--------------------------------------= var digits = digits.drop(while:{ $0 == 48 }) @@ -96,13 +96,13 @@ extension NBKDoubleWidth where High == High.Magnitude { forwards: if !alignment.isZero { let chunk = NBK.UnsafeUTF8(rebasing: NBK.removePrefix(from: &digits, count: alignment)) - guard let word = UInt.truncating(digits: chunk, radix: radix.base) else { return nil } + guard let word = NBK.truncatingAsUInt(digits: chunk, radix: radix.base) else { return nil } self.first = word } forwards: while !digits.isEmpty { let chunk = NBK.UnsafeUTF8(rebasing: NBK.removePrefix(from: &digits, count: radix.exponent)) - guard let word = UInt.truncating(digits: chunk, radix: radix.base) else { return nil } + guard let word = NBK.truncatingAsUInt(digits: chunk, radix: radix.base) else { return nil } guard !self.multiplyReportingOverflow(by: radix.power) else { return nil } guard !self.addReportingOverflow(word)/*------------*/ else { return nil } } @@ -114,24 +114,23 @@ extension NBKDoubleWidth where High == High.Magnitude { // MARK: Details x Encode x Private //=------------------------------------------------------------------------= - @inlinable func description(radix: AnyRadixUIntRoot, alphabet: MaxRadixAlphabetEncoder, prefix: NBK.UnsafeUTF8, suffix: NBK.UnsafeUTF8) -> String { + @inlinable func description(radix: NBK.AnyRadixUIntRoot, alphabet: NBK.MaxRadixAlphabetEncoder, prefix: NBK.UnsafeUTF8, suffix: NBK.UnsafeUTF8) -> String { switch radix.power.isZero { - case true: return self.description(radix: PerfectRadixUIntRoot(unchecked: radix), alphabet: alphabet, prefix: prefix, suffix: suffix) - case false: return self.description(radix: ImperfectRadixUIntRoot(unchecked: radix), alphabet: alphabet, prefix: prefix, suffix: suffix) } + case true: return self.description(radix: NBK .PerfectRadixUIntRoot(unchecked: radix), alphabet: alphabet, prefix: prefix, suffix: suffix) + case false: return self.description(radix: NBK.ImperfectRadixUIntRoot(unchecked: radix), alphabet: alphabet, prefix: prefix, suffix: suffix) } } - @inlinable func description(radix: PerfectRadixUIntRoot, alphabet: MaxRadixAlphabetEncoder, prefix: NBK.UnsafeUTF8, suffix: NBK.UnsafeUTF8) -> String { + @inlinable func description(radix: NBK.PerfectRadixUIntRoot, alphabet: NBK.MaxRadixAlphabetEncoder, prefix: NBK.UnsafeUTF8, suffix: NBK.UnsafeUTF8) -> String { //=--------------------------------------= // with one buffer pointer specialization //=--------------------------------------= self.withContiguousStorage { buffer in - let index = buffer.lastIndex(where:{ !$0.isZero }) ?? buffer.startIndex - let chunks = NBK.UnsafeWords(rebasing: buffer[...index]) - return String.fromUTF8Unchecked(chunks: chunks, radix: radix, alphabet: alphabet, prefix: prefix, suffix: suffix) + let chunks = NBK.UnsafeWords(rebasing: NBK.dropLast(from: buffer, while: { $0.isZero })) + return NBK.integerTextUnchecked(chunks: chunks, radix: radix, alphabet: alphabet, prefix: prefix, suffix: suffix) } } - @inlinable func description(radix: ImperfectRadixUIntRoot, alphabet: MaxRadixAlphabetEncoder, prefix: NBK.UnsafeUTF8, suffix: NBK.UnsafeUTF8) -> String { + @inlinable func description(radix: NBK.ImperfectRadixUIntRoot, alphabet: NBK.MaxRadixAlphabetEncoder, prefix: NBK.UnsafeUTF8, suffix: NBK.UnsafeUTF8) -> String { //=--------------------------------------= // with one buffer pointer specialization //=--------------------------------------= @@ -143,15 +142,15 @@ extension NBKDoubleWidth where High == High.Magnitude { var magnitude: Magnitude = self var index: Int = buffer.startIndex //=----------------------------------= - rebasing: repeat { + rebasing: while !magnitude.isZero { let (remainder, overflow) = magnitude.formQuotientWithRemainderReportingOverflow(dividingBy: radix.power) buffer[index] = remainder buffer.formIndex(after: &index) assert(!overflow) - } while !magnitude.isZero + } //=----------------------------------= let chunks = NBK.UnsafeWords(rebasing: buffer[.. UInt8? { - var index: UInt8 - - index = ascii &- UInt8(ascii: "0"); if index < self.x00x10 { return index } - index = ascii &- UInt8(ascii: "A"); if index < self.x10x36 { return index &+ 10 } - index = ascii &- UInt8(ascii: "a"); if index < self.x10x36 { return index &+ 10 } - - return nil - } -} - -//*============================================================================* -// MARK: * NBK x Radix Alphabet x Encoder x Max -//*============================================================================* - -/// Encodes values in `0` to `36` to ASCII. -@frozen @usableFromInline struct MaxRadixAlphabetEncoder { - - //=------------------------------------------------------------------------= - // MARK: State - //=------------------------------------------------------------------------= - - @usableFromInline let x00x10: UInt8 - @usableFromInline let x10x36: UInt8 - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - @inlinable init(uppercase: Bool) { - self.x00x10 = UInt8(ascii: "0") - self.x10x36 = UInt8(ascii: uppercase ? "A" : "a") &- 10 - } - - //=------------------------------------------------------------------------= - // MARK: Utilities - //=------------------------------------------------------------------------= - - @inlinable func encode(_ value: UInt8) -> UInt8? { - if value < 10 { return value &+ self.x00x10 } - if value < 36 { return value &+ self.x10x36 } - return nil - } -} diff --git a/Sources/NBKDoubleWidthKit/Private/RadixUIntRoot.swift b/Sources/NBKDoubleWidthKit/Private/RadixUIntRoot.swift deleted file mode 100644 index 1cde03c7..00000000 --- a/Sources/NBKDoubleWidthKit/Private/RadixUIntRoot.swift +++ /dev/null @@ -1,274 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Radix UInt Root -//*============================================================================* - -/// The largest exponent in `pow(radix, exponent) <= UInt.max + 1`. -/// -/// - Its `base` is `>= 2` and `<= 36` -/// - Its `exponent` is `>= 1` and `<= UInt.bitWidth` -/// - A power of `UInt.max + 1` is represented by `0` -/// -@usableFromInline protocol RadixUIntRoot { - - //=------------------------------------------------------------------------= - // MARK: State - //=------------------------------------------------------------------------= - - @inlinable var base: UInt { get } - - @inlinable var exponent: UInt { get } - - @inlinable var power: UInt { get } - - //=------------------------------------------------------------------------= - // MARK: Utilities - //=------------------------------------------------------------------------= - - /// Divides `dividend` by the `base` of this solution. - @inlinable func dividing(_ dividend: UInt) -> QR -} - -//=----------------------------------------------------------------------------= -// MARK: + Details -//=----------------------------------------------------------------------------= - -extension RadixUIntRoot { - - //=------------------------------------------------------------------------= - // MARK: Accessors - //=------------------------------------------------------------------------= - - @_transparent @usableFromInline var base: Int { - assert((self.base as UInt) <= 36) - return Int(bitPattern: self.base) - } - - @_transparent @usableFromInline var exponent: Int { - assert((self.exponent as UInt) <= UInt.bitWidth) - return Int(bitPattern: self.exponent) - } - - //=------------------------------------------------------------------------= - // MARK: Utilities - //=------------------------------------------------------------------------= - - @inlinable func dividing(_ dividend: UInt) -> QR { - dividend.quotientAndRemainder(dividingBy: self.base) - } -} - -//*============================================================================* -// MARK: * NBK x Radix UInt Root x Perfect -//*============================================================================* - -/// A ``RadixUIntRoot`` with a power that is zero. -@frozen @usableFromInline struct PerfectRadixUIntRoot: RadixUIntRoot { - - //=------------------------------------------------------------------------= - // MARK: State - //=------------------------------------------------------------------------= - - @usableFromInline let root: AnyRadixUIntRoot - @usableFromInline let special: QR - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - @inlinable init(unchecked: AnyRadixUIntRoot) { - assert(unchecked.power.isZero) - assert([2, 4, 16].contains(unchecked.base)) - self.root = unchecked - self.special.quotient = UInt(bitPattern: self.root.base.trailingZeroBitCount) - self.special.remainder = self.root.base &- 1 - } - - //=------------------------------------------------------------------------= - // MARK: Accessors - //=------------------------------------------------------------------------= - - @_transparent @usableFromInline var base: UInt { - self.root.base - } - - @_transparent @usableFromInline var exponent: UInt { - self.root.exponent - } - - @_transparent @usableFromInline var power: UInt { - self.root.power - } - - //=------------------------------------------------------------------------= - // MARK: Utilities - //=------------------------------------------------------------------------= - - @inlinable func dividing(_ dividend: UInt) -> QR { - QR(dividend &>> self.special.quotient, dividend & self.special.remainder) - } -} - -//*============================================================================* -// MARK: * NBK x Radix UInt Root x Imperfect -//*============================================================================* - -/// A ``RadixUIntRoot`` with a power that is non-zero. -@frozen @usableFromInline struct ImperfectRadixUIntRoot: RadixUIntRoot { - - //=------------------------------------------------------------------------= - // MARK: State - //=------------------------------------------------------------------------= - - @usableFromInline let root: AnyRadixUIntRoot - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - @inlinable init(unchecked: AnyRadixUIntRoot) { - assert(!unchecked.power.isZero) - assert(![2, 4, 16].contains(unchecked.base)) - self.root = unchecked - } - - //=------------------------------------------------------------------------= - // MARK: Accessors - //=------------------------------------------------------------------------= - - @_transparent @usableFromInline var base: UInt { - self.root.base - } - - @_transparent @usableFromInline var exponent: UInt { - self.root.exponent - } - - @_transparent @usableFromInline var power: UInt { - self.root.power - } - - //=------------------------------------------------------------------------= - // MARK: Utilities - //=------------------------------------------------------------------------= - - /// Overestimates how many times its power divides the magnitude. - @inlinable func divisibilityByPowerUpperBound(_ magnitude: some UnsignedInteger) -> Int { - magnitude.bitWidth / 36.leadingZeroBitCount &+ 1 - } -} - -//*============================================================================* -// MARK: * NBK x Radix UInt Root x Any -//*============================================================================* - -/// A ``RadixUIntRoot`` with a power that may be zero. -@frozen @usableFromInline struct AnyRadixUIntRoot: RadixUIntRoot { - - @usableFromInline typealias Solution = (exponent: UInt, power: UInt) - - //=------------------------------------------------------------------------= - // MARK: State - //=------------------------------------------------------------------------= - - @usableFromInline let base: UInt - @usableFromInline let exponent: UInt - @usableFromInline let power: UInt - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - /// Creates a new instance from the given radix. - /// - /// The radix must not exceed `36` because that is the size of the alphabet. - /// - /// - Parameter radix: A value from `2` through `36`. - /// - @inlinable init(_ radix: Int) { - Swift.precondition(2 ... 36 ~= radix) - (self.base) = UInt(bitPattern: radix) - (self.exponent, self.power) = Self.solution(unchecked: self.base) - } - - //=------------------------------------------------------------------------= - // MARK: Utilities - //=------------------------------------------------------------------------= - - /// Returns the largest exponent in `pow(radix, exponent) <= UInt.max + 1`. - @inlinable static func solution(unchecked radix: UInt) -> Solution { - switch radix.isPowerOf2 { - case true: return Self.solutionAssumingRadixIsPowerOf2 (unchecked: radix) - case false: return Self.solutionAssumingRadixIsNotPowerOf2(unchecked: radix) } - } - - /// Returns the largest exponent in `pow(radix, exponent) <= UInt.max + 1`. - @inlinable static func solutionAssumingRadixIsPowerOf2(unchecked radix: UInt) -> Solution { - assert(radix >= 2) - assert(radix.isPowerOf2) - //=--------------------------------------= - let zeros = UInt(bitPattern: radix.trailingZeroBitCount) - //=--------------------------------------= - // radix: 002, 004, 016, 256, ... - //=--------------------------------------= - if zeros.isPowerOf2 { - let exponent = UInt(bitPattern: UInt.bitWidth &>> zeros.trailingZeroBitCount) - return Solution(exponent: exponent, power: 0) - //=--------------------------------------= - // radix: 008, 032, 064, 128, ... - //=--------------------------------------= - } else { - let exponent = UInt(bitPattern: UInt.bitWidth) / (zeros as UInt) - return Solution(exponent: exponent, power: 1 &<< (zeros &* exponent)) - } - } - - /// Returns the largest exponent in `pow(radix, exponent) <= UInt.max + 1`. - @inlinable static func solutionAssumingRadixIsNotPowerOf2(unchecked radix: UInt) -> Solution { - assert(radix >= 2) - assert(radix.isPowerOf2 == false) - //=--------------------------------------= - // radix: 003, 005, 006, 007, ... - //=--------------------------------------= - let capacity: Int = UInt.bitWidth.trailingZeroBitCount - 1 - return Swift.withUnsafeTemporaryAllocation(of: Solution.self, capacity: capacity) { squares in - //=----------------------------------= - // de/init: pointee is trivial - //=----------------------------------= - var solution = Solution(1, radix) - var index = squares.startIndex as Int - - loop: while index < squares.endIndex { - squares[index] = solution - let product = solution.power.multipliedReportingOverflow(by: solution.power) - if product.overflow { break loop } - - solution.exponent &<<= 1 as UInt - solution.power = product.partialValue - squares.formIndex(after: &index) - } - - loop: while index > squares.startIndex { - squares.formIndex(before: &index) - let square = squares[index] - let product = solution.power.multipliedReportingOverflow(by: square.power) - if product.overflow { continue loop } - - solution.exponent &+= square.exponent - solution.power = product.partialValue - } - - return solution as Solution - } - } -} diff --git a/Sources/NBKDoubleWidthKit/Private/Text.swift b/Sources/NBKDoubleWidthKit/Private/Text.swift deleted file mode 100644 index 997b7a90..00000000 --- a/Sources/NBKDoubleWidthKit/Private/Text.swift +++ /dev/null @@ -1,134 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Text x UInt -//*============================================================================* - -extension UInt { - - //=------------------------------------------------------------------------= - // MARK: Details x Text - //=------------------------------------------------------------------------= - - /// Creates a new instance by truncating the given `digits` and `radix`. - /// - /// The sequence passed as `digits` may contain one or more numeric digits - /// (0-9) or letters (a-z or A-Z), according to the `radix`. If the sequence - /// passed as `digits` uses an invalid format, the result is nil. If the - /// sequence passed as `digits` cannot be represented, the result is truncated. - /// - /// - Note: The decoding strategy is case insensitive. - /// - /// ### Parameters - /// - /// Creating a new decoder is faster than passing one as an argument. - /// - @inlinable static func truncating(digits: NBK.UnsafeUTF8, radix: Int) -> Self? { - guard !digits.isEmpty else { return nil } - //=--------------------------------------= - let alphabet = AnyRadixAlphabetDecoder(radix: radix) - //=--------------------------------------= - var value = Self.zero - - for digit in digits { - guard let addend = alphabet.decode(digit) else { return nil } - value &*= Self(bitPattern: radix) - value &+= Self(truncatingIfNeeded: addend) - } - - return value as Self - } -} - -//*============================================================================* -// MARK: * NBK x Text x String -//*============================================================================* - -extension String { - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - /// Encodes unchecked chunks, using the given format. - /// - /// In this context, a chunk is a digit in the base of the given radix's power. - /// - @inlinable static func fromUTF8Unchecked(chunks: some RandomAccessCollection, radix: some RadixUIntRoot, - alphabet: MaxRadixAlphabetEncoder, prefix: NBK.UnsafeUTF8, suffix: NBK.UnsafeUTF8) -> String { - assert(!chunks.isEmpty, "chunks must not be empty") - assert(!chunks.last!.isZero || chunks.count == 1, "chunks must not have redundant zeros") - assert( radix.power.isZero || chunks.allSatisfy({ $0 < radix.power }), "chunks must be less than radix's power") - //=--------------------------------------= - var remainders = chunks[...] - let mostSignificantChunk = remainders.removeLast() - return String.withUTF8Unchecked(chunk: mostSignificantChunk, radix: radix, alphabet: alphabet) { first in - var count: Int - count = prefix.count - count += first .count - count += remainders.count * radix.exponent - count += suffix.count - return String(unsafeUninitializedCapacity: count) { utf8 in - //=------------------------------= - // de/init: pointee is trivial - //=------------------------------= - var index = count as Int - func pull(_ unit: UInt8) { - utf8.formIndex(before: &index) - utf8[index] = unit - } - //=------------------------------= - suffix.reversed().forEach(pull) - - for var chunk in remainders { - for _ in 0 ..< radix.exponent { - let digit: UInt - (chunk, digit) = radix.dividing(chunk) - pull(alphabet.encode(UInt8(truncatingIfNeeded: digit))!) - } - } - - first .reversed().forEach(pull) - prefix.reversed().forEach(pull) - //=------------------------------= - assert(utf8.startIndex == index) - assert(utf8[index..(chunk: UInt, radix: some RadixUIntRoot, - alphabet: MaxRadixAlphabetEncoder, body: (NBK.UnsafeUTF8) -> T) -> T { - assert(radix.power.isZero || chunk < radix.power, "chunks must be less than radix's power") - return Swift.withUnsafeTemporaryAllocation(of: UInt8.self, capacity: radix.exponent) { utf8 in - //=----------------------------------= - // de/init: pointee is trivial - //=----------------------------------= - var chunk = chunk as UInt - var index = radix.exponent as Int - //=----------------------------------= - backwards: repeat { - let digit: UInt - (chunk, digit) = radix.dividing(chunk) - utf8.formIndex(before: &index) - utf8[index] = alphabet.encode(UInt8(truncatingIfNeeded: digit))! - } while !chunk.isZero - //=----------------------------------= - return body(NBK.UnsafeUTF8(rebasing: utf8[index...])) - } - } -} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text+Radix.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text+Radix.swift index 9031072e..ffb18018 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text+Radix.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text+Radix.swift @@ -23,7 +23,7 @@ extension NBKFlexibleWidth.Magnitude { var description = String(description) let value: Optional = description.withUTF8 { utf8 in - let (radix) = AnyRadixUIntRoot(radix) + let (radix) = NBK.AnyRadixUIntRoot(radix) let (sign,body) = NBK.integerComponents(utf8: utf8) let (digits) = NBK.UnsafeUTF8(rebasing: body) let (magnitude) = Magnitude(digits: digits, radix: radix) @@ -39,8 +39,8 @@ extension NBKFlexibleWidth.Magnitude { @inlinable public func description(radix: Int = 10, uppercase: Bool = false) -> String { Swift.withUnsafePointer(to: UInt8(ascii: "-")) { minus in - let radix = AnyRadixUIntRoot(radix) - let alphabet = MaxRadixAlphabetEncoder(uppercase: uppercase) + let radix = NBK.AnyRadixUIntRoot(radix) + let alphabet = NBK.MaxRadixAlphabetEncoder(uppercase: uppercase) let prefix = NBK.UnsafeUTF8(start: minus, count: Int(bit: self.isLessThanZero)) let suffix = NBK.UnsafeUTF8(start: nil, count: Int.zero) return self.magnitude.description(radix: radix, alphabet: alphabet, prefix: prefix, suffix: suffix) @@ -58,13 +58,13 @@ extension NBKFlexibleWidth.Magnitude { // MARK: Details x Decode x Private //=------------------------------------------------------------------------= - @inlinable init?(digits: NBK.UnsafeUTF8, radix: AnyRadixUIntRoot) { + @inlinable init?(digits: NBK.UnsafeUTF8, radix: NBK.AnyRadixUIntRoot) { switch radix.power.isZero { - case true: self.init(digits: digits, radix: PerfectRadixUIntRoot(unchecked: radix)) - case false: self.init(digits: digits, radix: ImperfectRadixUIntRoot(unchecked: radix)) } + case true: self.init(digits: digits, radix: NBK .PerfectRadixUIntRoot(unchecked: radix)) + case false: self.init(digits: digits, radix: NBK.ImperfectRadixUIntRoot(unchecked: radix)) } } - @inlinable init?(digits: NBK.UnsafeUTF8, radix: PerfectRadixUIntRoot) { + @inlinable init?(digits: NBK.UnsafeUTF8, radix: NBK.PerfectRadixUIntRoot) { guard !digits.isEmpty else { return nil } //=--------------------------------------= var digits = digits.drop(while:{ $0 == 48 }) @@ -77,7 +77,7 @@ extension NBKFlexibleWidth.Magnitude { let value = Self.uninitialized(count: count) { storage in for index in storage.indices { let chunk = NBK.UnsafeUTF8(rebasing: NBK.removeSuffix(from: &digits, maxLength: radix.exponent)) - guard let word = UInt.truncating(digits: chunk, radix: radix.base) else { return error = true } + guard let word = NBK.truncatingAsUInt(digits: chunk, radix: radix.base) else { return error = true } storage[index] = word } @@ -87,7 +87,7 @@ extension NBKFlexibleWidth.Magnitude { if !error { self = value } else { return nil } } - @inlinable init?(digits: NBK.UnsafeUTF8, radix: ImperfectRadixUIntRoot) { + @inlinable init?(digits: NBK.UnsafeUTF8, radix: NBK.ImperfectRadixUIntRoot) { guard !digits.isEmpty else { return nil } //=--------------------------------------= var digits = digits.drop(while:{ $0 == 48 }) @@ -98,15 +98,15 @@ extension NBKFlexibleWidth.Magnitude { forwards: if !alignment.isZero { let chunk = NBK.UnsafeUTF8(rebasing: NBK.removePrefix(from: &digits, count: alignment)) - guard let word = UInt.truncating(digits: chunk, radix: radix.base) else { return nil } - self += word + guard let word = NBK.truncatingAsUInt(digits: chunk, radix: radix.base) else { return nil } + self += word } forwards: while !digits.isEmpty { let chunk = NBK.UnsafeUTF8(rebasing: NBK.removePrefix(from: &digits, count: radix.exponent)) - guard let word = UInt.truncating(digits: chunk, radix: radix.base) else { return nil } - self *= radix.power - self += word // TODO: combined * and + method + guard let word = NBK.truncatingAsUInt(digits: chunk, radix: radix.base) else { return nil } + self *= radix.power // TODO: combined * and + method + self += word } }() as Void? else { return nil } @@ -116,32 +116,23 @@ extension NBKFlexibleWidth.Magnitude { // MARK: Details x Encode x Private //=------------------------------------------------------------------------= - @inlinable func description(radix: AnyRadixUIntRoot, alphabet: MaxRadixAlphabetEncoder, prefix: NBK.UnsafeUTF8, suffix: NBK.UnsafeUTF8) -> String { + @inlinable func description(radix: NBK.AnyRadixUIntRoot, alphabet: NBK.MaxRadixAlphabetEncoder, prefix: NBK.UnsafeUTF8, suffix: NBK.UnsafeUTF8) -> String { switch radix.power.isZero { - case true: return self.description(radix: PerfectRadixUIntRoot(unchecked: radix), alphabet: alphabet, prefix: prefix, suffix: suffix) - case false: return self.description(radix: ImperfectRadixUIntRoot(unchecked: radix), alphabet: alphabet, prefix: prefix, suffix: suffix) } + case true: return self.description(radix: NBK .PerfectRadixUIntRoot(unchecked: radix), alphabet: alphabet, prefix: prefix, suffix: suffix) + case false: return self.description(radix: NBK.ImperfectRadixUIntRoot(unchecked: radix), alphabet: alphabet, prefix: prefix, suffix: suffix) } } - @inlinable func description(radix: PerfectRadixUIntRoot, alphabet: MaxRadixAlphabetEncoder, prefix: NBK.UnsafeUTF8, suffix: NBK.UnsafeUTF8) -> String { - //=--------------------------------------= - // TODO: String.fromUTF8Unchecked - //=--------------------------------------= - if self.isZero { return "0" } + @inlinable func description(radix: NBK.PerfectRadixUIntRoot, alphabet: NBK.MaxRadixAlphabetEncoder, prefix: NBK.UnsafeUTF8, suffix: NBK.UnsafeUTF8) -> String { //=--------------------------------------= // with one buffer pointer specialization //=--------------------------------------= - return self.storage.elements.withContiguousStorageIfAvailable { buffer in - let index = buffer.lastIndex(where:{ !$0.isZero }) ?? buffer.startIndex - let chunks = NBK.UnsafeWords(rebasing: buffer[...index]) - return String.fromUTF8Unchecked(chunks: chunks, radix: radix, alphabet: alphabet, prefix: prefix, suffix: suffix) + return self.storage.elements.withContiguousStorageIfAvailable { buffer in + let chunks = NBK.UnsafeWords(rebasing: NBK.dropLast(from: buffer, while: { $0.isZero })) + return NBK.integerTextUnchecked(chunks: chunks, radix: radix, alphabet: alphabet, prefix: prefix, suffix: suffix) }! } - @inlinable func description(radix: ImperfectRadixUIntRoot, alphabet: MaxRadixAlphabetEncoder, prefix: NBK.UnsafeUTF8, suffix: NBK.UnsafeUTF8) -> String { - //=--------------------------------------= - // TODO: String.fromUTF8Unchecked - //=--------------------------------------= - if self.isZero { return "0" } + @inlinable func description(radix: NBK.ImperfectRadixUIntRoot, alphabet: NBK.MaxRadixAlphabetEncoder, prefix: NBK.UnsafeUTF8, suffix: NBK.UnsafeUTF8) -> String { //=--------------------------------------= // with one buffer pointer specialization //=--------------------------------------= @@ -153,15 +144,15 @@ extension NBKFlexibleWidth.Magnitude { var magnitude: Magnitude = self var index: Int = buffer.startIndex //=----------------------------------= - rebasing: repeat { + rebasing: while !magnitude.isZero { let (remainder, overflow) = magnitude.formQuotientWithRemainderReportingOverflow(dividingBy: radix.power) buffer[index] = remainder buffer.formIndex(after: &index) assert(!overflow) - } while !magnitude.isZero + } //=----------------------------------= - let chunks = NBK.UnsafeWords(rebasing: buffer[.. UInt8? { - var index: UInt8 - - index = ascii &- UInt8(ascii: "0"); if index < self.x00x10 { return index } - index = ascii &- UInt8(ascii: "A"); if index < self.x10x36 { return index &+ 10 } - index = ascii &- UInt8(ascii: "a"); if index < self.x10x36 { return index &+ 10 } - - return nil - } -} - -//*============================================================================* -// MARK: * NBK x Radix Alphabet x Encoder x Max -//*============================================================================* - -/// Encodes values in `0` to `36` to ASCII. -@frozen @usableFromInline struct MaxRadixAlphabetEncoder { - - //=------------------------------------------------------------------------= - // MARK: State - //=------------------------------------------------------------------------= - - @usableFromInline let x00x10: UInt8 - @usableFromInline let x10x36: UInt8 - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - @inlinable init(uppercase: Bool) { - self.x00x10 = UInt8(ascii: "0") - self.x10x36 = UInt8(ascii: uppercase ? "A" : "a") &- 10 - } - - //=------------------------------------------------------------------------= - // MARK: Utilities - //=------------------------------------------------------------------------= - - @inlinable func encode(_ value: UInt8) -> UInt8? { - if value < 10 { return value &+ self.x00x10 } - if value < 36 { return value &+ self.x10x36 } - return nil - } -} diff --git a/Sources/NBKFlexibleWidthKit/Private/RadixUIntRoot.swift b/Sources/NBKFlexibleWidthKit/Private/RadixUIntRoot.swift deleted file mode 100644 index 1cde03c7..00000000 --- a/Sources/NBKFlexibleWidthKit/Private/RadixUIntRoot.swift +++ /dev/null @@ -1,274 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Radix UInt Root -//*============================================================================* - -/// The largest exponent in `pow(radix, exponent) <= UInt.max + 1`. -/// -/// - Its `base` is `>= 2` and `<= 36` -/// - Its `exponent` is `>= 1` and `<= UInt.bitWidth` -/// - A power of `UInt.max + 1` is represented by `0` -/// -@usableFromInline protocol RadixUIntRoot { - - //=------------------------------------------------------------------------= - // MARK: State - //=------------------------------------------------------------------------= - - @inlinable var base: UInt { get } - - @inlinable var exponent: UInt { get } - - @inlinable var power: UInt { get } - - //=------------------------------------------------------------------------= - // MARK: Utilities - //=------------------------------------------------------------------------= - - /// Divides `dividend` by the `base` of this solution. - @inlinable func dividing(_ dividend: UInt) -> QR -} - -//=----------------------------------------------------------------------------= -// MARK: + Details -//=----------------------------------------------------------------------------= - -extension RadixUIntRoot { - - //=------------------------------------------------------------------------= - // MARK: Accessors - //=------------------------------------------------------------------------= - - @_transparent @usableFromInline var base: Int { - assert((self.base as UInt) <= 36) - return Int(bitPattern: self.base) - } - - @_transparent @usableFromInline var exponent: Int { - assert((self.exponent as UInt) <= UInt.bitWidth) - return Int(bitPattern: self.exponent) - } - - //=------------------------------------------------------------------------= - // MARK: Utilities - //=------------------------------------------------------------------------= - - @inlinable func dividing(_ dividend: UInt) -> QR { - dividend.quotientAndRemainder(dividingBy: self.base) - } -} - -//*============================================================================* -// MARK: * NBK x Radix UInt Root x Perfect -//*============================================================================* - -/// A ``RadixUIntRoot`` with a power that is zero. -@frozen @usableFromInline struct PerfectRadixUIntRoot: RadixUIntRoot { - - //=------------------------------------------------------------------------= - // MARK: State - //=------------------------------------------------------------------------= - - @usableFromInline let root: AnyRadixUIntRoot - @usableFromInline let special: QR - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - @inlinable init(unchecked: AnyRadixUIntRoot) { - assert(unchecked.power.isZero) - assert([2, 4, 16].contains(unchecked.base)) - self.root = unchecked - self.special.quotient = UInt(bitPattern: self.root.base.trailingZeroBitCount) - self.special.remainder = self.root.base &- 1 - } - - //=------------------------------------------------------------------------= - // MARK: Accessors - //=------------------------------------------------------------------------= - - @_transparent @usableFromInline var base: UInt { - self.root.base - } - - @_transparent @usableFromInline var exponent: UInt { - self.root.exponent - } - - @_transparent @usableFromInline var power: UInt { - self.root.power - } - - //=------------------------------------------------------------------------= - // MARK: Utilities - //=------------------------------------------------------------------------= - - @inlinable func dividing(_ dividend: UInt) -> QR { - QR(dividend &>> self.special.quotient, dividend & self.special.remainder) - } -} - -//*============================================================================* -// MARK: * NBK x Radix UInt Root x Imperfect -//*============================================================================* - -/// A ``RadixUIntRoot`` with a power that is non-zero. -@frozen @usableFromInline struct ImperfectRadixUIntRoot: RadixUIntRoot { - - //=------------------------------------------------------------------------= - // MARK: State - //=------------------------------------------------------------------------= - - @usableFromInline let root: AnyRadixUIntRoot - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - @inlinable init(unchecked: AnyRadixUIntRoot) { - assert(!unchecked.power.isZero) - assert(![2, 4, 16].contains(unchecked.base)) - self.root = unchecked - } - - //=------------------------------------------------------------------------= - // MARK: Accessors - //=------------------------------------------------------------------------= - - @_transparent @usableFromInline var base: UInt { - self.root.base - } - - @_transparent @usableFromInline var exponent: UInt { - self.root.exponent - } - - @_transparent @usableFromInline var power: UInt { - self.root.power - } - - //=------------------------------------------------------------------------= - // MARK: Utilities - //=------------------------------------------------------------------------= - - /// Overestimates how many times its power divides the magnitude. - @inlinable func divisibilityByPowerUpperBound(_ magnitude: some UnsignedInteger) -> Int { - magnitude.bitWidth / 36.leadingZeroBitCount &+ 1 - } -} - -//*============================================================================* -// MARK: * NBK x Radix UInt Root x Any -//*============================================================================* - -/// A ``RadixUIntRoot`` with a power that may be zero. -@frozen @usableFromInline struct AnyRadixUIntRoot: RadixUIntRoot { - - @usableFromInline typealias Solution = (exponent: UInt, power: UInt) - - //=------------------------------------------------------------------------= - // MARK: State - //=------------------------------------------------------------------------= - - @usableFromInline let base: UInt - @usableFromInline let exponent: UInt - @usableFromInline let power: UInt - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - /// Creates a new instance from the given radix. - /// - /// The radix must not exceed `36` because that is the size of the alphabet. - /// - /// - Parameter radix: A value from `2` through `36`. - /// - @inlinable init(_ radix: Int) { - Swift.precondition(2 ... 36 ~= radix) - (self.base) = UInt(bitPattern: radix) - (self.exponent, self.power) = Self.solution(unchecked: self.base) - } - - //=------------------------------------------------------------------------= - // MARK: Utilities - //=------------------------------------------------------------------------= - - /// Returns the largest exponent in `pow(radix, exponent) <= UInt.max + 1`. - @inlinable static func solution(unchecked radix: UInt) -> Solution { - switch radix.isPowerOf2 { - case true: return Self.solutionAssumingRadixIsPowerOf2 (unchecked: radix) - case false: return Self.solutionAssumingRadixIsNotPowerOf2(unchecked: radix) } - } - - /// Returns the largest exponent in `pow(radix, exponent) <= UInt.max + 1`. - @inlinable static func solutionAssumingRadixIsPowerOf2(unchecked radix: UInt) -> Solution { - assert(radix >= 2) - assert(radix.isPowerOf2) - //=--------------------------------------= - let zeros = UInt(bitPattern: radix.trailingZeroBitCount) - //=--------------------------------------= - // radix: 002, 004, 016, 256, ... - //=--------------------------------------= - if zeros.isPowerOf2 { - let exponent = UInt(bitPattern: UInt.bitWidth &>> zeros.trailingZeroBitCount) - return Solution(exponent: exponent, power: 0) - //=--------------------------------------= - // radix: 008, 032, 064, 128, ... - //=--------------------------------------= - } else { - let exponent = UInt(bitPattern: UInt.bitWidth) / (zeros as UInt) - return Solution(exponent: exponent, power: 1 &<< (zeros &* exponent)) - } - } - - /// Returns the largest exponent in `pow(radix, exponent) <= UInt.max + 1`. - @inlinable static func solutionAssumingRadixIsNotPowerOf2(unchecked radix: UInt) -> Solution { - assert(radix >= 2) - assert(radix.isPowerOf2 == false) - //=--------------------------------------= - // radix: 003, 005, 006, 007, ... - //=--------------------------------------= - let capacity: Int = UInt.bitWidth.trailingZeroBitCount - 1 - return Swift.withUnsafeTemporaryAllocation(of: Solution.self, capacity: capacity) { squares in - //=----------------------------------= - // de/init: pointee is trivial - //=----------------------------------= - var solution = Solution(1, radix) - var index = squares.startIndex as Int - - loop: while index < squares.endIndex { - squares[index] = solution - let product = solution.power.multipliedReportingOverflow(by: solution.power) - if product.overflow { break loop } - - solution.exponent &<<= 1 as UInt - solution.power = product.partialValue - squares.formIndex(after: &index) - } - - loop: while index > squares.startIndex { - squares.formIndex(before: &index) - let square = squares[index] - let product = solution.power.multipliedReportingOverflow(by: square.power) - if product.overflow { continue loop } - - solution.exponent &+= square.exponent - solution.power = product.partialValue - } - - return solution as Solution - } - } -} diff --git a/Tests/NBKDoubleWidthKitTests/Private/RadixAlphabet.swift b/Tests/NBKCoreKitTests/Private/RadixAlphabet.swift similarity index 90% rename from Tests/NBKDoubleWidthKitTests/Private/RadixAlphabet.swift rename to Tests/NBKCoreKitTests/Private/RadixAlphabet.swift index 52910aad..c3f5dd84 100644 --- a/Tests/NBKDoubleWidthKitTests/Private/RadixAlphabet.swift +++ b/Tests/NBKCoreKitTests/Private/RadixAlphabet.swift @@ -10,14 +10,13 @@ #if DEBUG import NBKCoreKit -@testable import NBKDoubleWidthKit import XCTest //*============================================================================* // MARK: * NBK x Radix Alphabet //*============================================================================* -final class RadixAlphabetTests: XCTestCase { +final class NBKRadixAlphabetTests: XCTestCase { //=------------------------------------------------------------------------= // MARK: State @@ -32,7 +31,7 @@ final class RadixAlphabetTests: XCTestCase { func testAnyRadixAlphabetDecoder() { for radix in 2 ... 36 { - let alphabet = AnyRadixAlphabetDecoder(radix: radix) + let alphabet = NBK.AnyRadixAlphabetDecoder(radix: radix) XCTAssertNil(alphabet.decode(UInt8(ascii: "0") - 1)) XCTAssertNil(alphabet.decode(UInt8(ascii: "A") - 1)) @@ -55,8 +54,8 @@ final class RadixAlphabetTests: XCTestCase { //=------------------------------------------------------------------------= func testMaxRadixAlphabetEncoder() { - let lowercase = MaxRadixAlphabetEncoder(uppercase: false) - let uppercase = MaxRadixAlphabetEncoder(uppercase: true ) + let lowercase = NBK.MaxRadixAlphabetEncoder(uppercase: false) + let uppercase = NBK.MaxRadixAlphabetEncoder(uppercase: true ) for value in 0 ..< UInt8(44) { XCTAssertEqual(lowercase.encode(value), value < 36 ? self.lowercase[Int(value)] : nil) diff --git a/Tests/NBKDoubleWidthKitTests/Private/Text.swift b/Tests/NBKCoreKitTests/Private/RadixIntegers.swift similarity index 53% rename from Tests/NBKDoubleWidthKitTests/Private/Text.swift rename to Tests/NBKCoreKitTests/Private/RadixIntegers.swift index b30c58ee..bf82bbf8 100644 --- a/Tests/NBKDoubleWidthKitTests/Private/Text.swift +++ b/Tests/NBKCoreKitTests/Private/RadixIntegers.swift @@ -10,14 +10,65 @@ #if DEBUG import NBKCoreKit -@testable import NBKDoubleWidthKit import XCTest //*============================================================================* -// MARK: * NBK x Text x UInt +// MARK: * NBK x Radix Integers //*============================================================================* -final class TextTestsOnUInt: XCTestCase { +final class NBKRadixIntegersTests: XCTestCase { + + //=------------------------------------------------------------------------= + // MARK: Tests x Components + //=------------------------------------------------------------------------= + + func testIntegerComponents() { + NBKAssertIntegerComponents( "", .plus, "") + NBKAssertIntegerComponents( "+", .plus, "") + NBKAssertIntegerComponents( "-", .minus, "") + NBKAssertIntegerComponents( "~", .plus, "~") + NBKAssertIntegerComponents("+123", .plus, "123") + NBKAssertIntegerComponents("-123", .minus, "123") + NBKAssertIntegerComponents("~123", .plus, "~123") + } + + func testRemoveSignPrefix() { + NBKAssertRemoveSignPrefix( "", nil, "") + NBKAssertRemoveSignPrefix( "+", .plus, "") + NBKAssertRemoveSignPrefix( "-", .minus, "") + NBKAssertRemoveSignPrefix( "~", nil, "~") + NBKAssertRemoveSignPrefix("+123", .plus, "123") + NBKAssertRemoveSignPrefix("-123", .minus, "123") + NBKAssertRemoveSignPrefix("~123", nil, "~123") + } +} + +//=----------------------------------------------------------------------------= +// MARK: + Utilities +//=----------------------------------------------------------------------------= + +private func NBKAssertIntegerComponents( +_ text: String, _ sign: FloatingPointSign?, _ body: String, +file: StaticString = #file, line: UInt = #line) { + let components = NBK.integerComponents(utf8: text.utf8) + XCTAssertEqual(components.sign, sign) + XCTAssertEqual(Array(components.body), Array(body.utf8)) +} + +private func NBKAssertRemoveSignPrefix( +_ text: String, _ sign: FloatingPointSign?, _ body: String, +file: StaticString = #file, line: UInt = #line) { + var componentsBody = text.utf8[...] + let componentsSign = NBK.removeSignPrefix(utf8: &componentsBody) + XCTAssertEqual(componentsSign, sign) + XCTAssertEqual(Array(componentsBody), Array(body.utf8)) +} + +//*============================================================================* +// MARK: * NBK x Radix Integers x UInt +//*============================================================================* + +final class NBKRadixIntegersTestsOnUInt: XCTestCase { typealias T = UInt @@ -65,9 +116,9 @@ final class TextTestsOnUInt: XCTestCase { private func NBKAssertDecodeDigitsAsUIntByTruncating( _ result: UInt?, _ radix: Int, _ digits: String, file: StaticString = #file, line: UInt = #line) { - var digits = digits; digits.withUTF8 { utf8 in - let value = UInt.truncating(digits: utf8, radix: radix) - XCTAssertEqual(value, result, file: file, line: line) + var digits = digits; digits.withUTF8 { utf8 in + let value = NBK.truncatingAsUInt(digits: utf8, radix: radix) + XCTAssertEqual(value, result, file: file, line: line) } } diff --git a/Tests/NBKDoubleWidthKitTests/Private/RadixUIntRoot.swift b/Tests/NBKCoreKitTests/Private/RadixUIntRoot.swift similarity index 92% rename from Tests/NBKDoubleWidthKitTests/Private/RadixUIntRoot.swift rename to Tests/NBKCoreKitTests/Private/RadixUIntRoot.swift index d549460e..0e76968e 100644 --- a/Tests/NBKDoubleWidthKitTests/Private/RadixUIntRoot.swift +++ b/Tests/NBKCoreKitTests/Private/RadixUIntRoot.swift @@ -10,14 +10,13 @@ #if DEBUG import NBKCoreKit -@testable import NBKDoubleWidthKit import XCTest //*============================================================================* // MARK: * NBK x Radix UInt Root //*============================================================================* -final class RadixUIntRootTests: XCTestCase { +final class NBKRadixUIntRootTests: XCTestCase { //=------------------------------------------------------------------------= // MARK: Tests @@ -25,7 +24,7 @@ final class RadixUIntRootTests: XCTestCase { func testAnyRadixUIntRoot() { for radix in 2 ... 36 { - let solution = AnyRadixUIntRoot(radix) + let solution = NBK.AnyRadixUIntRoot(radix) XCTAssertEqual(solution.base, UInt(radix)) var product = HL(UInt(0), UInt(1)) diff --git a/Tests/NBKCoreKitTests/Private/Text.swift b/Tests/NBKCoreKitTests/Private/Text.swift deleted file mode 100644 index e8721daa..00000000 --- a/Tests/NBKCoreKitTests/Private/Text.swift +++ /dev/null @@ -1,67 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2022 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if DEBUG - -import NBKCoreKit -import XCTest - -//*============================================================================* -// MARK: * NBK x Text -//*============================================================================* - -final class NBKTextTests: XCTestCase { - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testIntegerComponents() { - NBKAssertIntegerComponents( "", .plus, "") - NBKAssertIntegerComponents( "+", .plus, "") - NBKAssertIntegerComponents( "-", .minus, "") - NBKAssertIntegerComponents( "~", .plus, "~") - NBKAssertIntegerComponents("+123", .plus, "123") - NBKAssertIntegerComponents("-123", .minus, "123") - NBKAssertIntegerComponents("~123", .plus, "~123") - } - - func testRemoveSignPrefix() { - NBKAssertRemoveSignPrefix( "", nil, "") - NBKAssertRemoveSignPrefix( "+", .plus, "") - NBKAssertRemoveSignPrefix( "-", .minus, "") - NBKAssertRemoveSignPrefix( "~", nil, "~") - NBKAssertRemoveSignPrefix("+123", .plus, "123") - NBKAssertRemoveSignPrefix("-123", .minus, "123") - NBKAssertRemoveSignPrefix("~123", nil, "~123") - } -} - -//=----------------------------------------------------------------------------= -// MARK: + Utilities -//=----------------------------------------------------------------------------= - -private func NBKAssertIntegerComponents( -_ text: String, _ sign: FloatingPointSign?, _ body: String, -file: StaticString = #file, line: UInt = #line) { - let components = NBK.integerComponents(utf8: text.utf8) - XCTAssertEqual(components.sign, sign) - XCTAssertEqual(Array(components.body), Array(body.utf8)) -} - -private func NBKAssertRemoveSignPrefix( -_ text: String, _ sign: FloatingPointSign?, _ body: String, -file: StaticString = #file, line: UInt = #line) { - var componentsBody = text.utf8[...] - let componentsSign = NBK.removeSignPrefix(utf8: &componentsBody) - XCTAssertEqual(componentsSign, sign) - XCTAssertEqual(Array(componentsBody), Array(body.utf8)) -} - -#endif From 178cfd31a5c23ebc715f5543756ffb5b61bb5bd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sun, 16 Jul 2023 14:23:52 +0200 Subject: [PATCH 006/133] NBKFlexibleWidthKit: Cleanup. --- .../NBKFlexibleWidth+Comparisons.swift | 7 +++---- .../NBKFlexibleWidth+Division.swift | 6 +++--- .../NBKFlexibleWidth+Numbers.swift | 14 ++++++++------ .../NBKFlexibleWidth+Text+Radix.swift | 10 +++++----- .../NBKFlexibleWidth+Uninitialized.swift | 19 +------------------ 5 files changed, 20 insertions(+), 36 deletions(-) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift index c6b40daf..4933fc1c 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift @@ -60,7 +60,7 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @inlinable public static func ==(lhs: Self, rhs: Self) -> Bool { - lhs.storage == rhs.storage + lhs.compared(to: rhs) == 0 } @inlinable public static func <(lhs: Self, rhs: Self) -> Bool { @@ -77,7 +77,7 @@ extension NBKFlexibleWidth.Magnitude { @inlinable public func compared(to other: Self, at index: Int) -> Int { self .storage.elements.withUnsafeBufferPointer { lhs in other.storage.elements.withUnsafeBufferPointer { rhs in - let partition = Swift.min(lhs.count - 1, index) + let partition = Swift.min(index, lhs.endIndex) let suffix = NBK.UnsafeWords(rebasing: lhs.suffix(from: partition)) let comparison = Self.compareWordsUnchecked(suffix, to: rhs) if !comparison.isZero { return comparison } @@ -91,8 +91,7 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @inlinable static func compareWordsUnchecked(_ lhs: NBK.UnsafeWords, to rhs: NBK.UnsafeWords) -> Int { - assert(lhs.count == 0 || !lhs.last!.isZero) - assert(rhs.count == 0 || !rhs.last!.isZero) + assert(lhs.last != 0 && rhs.last != 0) //=--------------------------------------= if lhs.count != rhs.count { return lhs.count < rhs.count ? -1 : 1 diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift index 044a3494..8ea8866a 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift @@ -95,7 +95,7 @@ extension NBKFlexibleWidth.Magnitude { // division: approximate quotient digits //=--------------------------------------= var quotientIndex = remainderIndex - divisor.storage.elements.endIndex as Int - var quotient = Self.uninitialized(count: quotientIndex + 1) { quotient in + var quotient = Storage.uninitialized(count: quotientIndex + 1) { quotient in // TODO: denormalized or fixed-width operations repeat { @@ -123,8 +123,8 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= // undo shift before division //=--------------------------------------= - quotient .storage.normalize() + quotient .normalize() remainder.bitshiftRight(words: Int.zero, bits: shift) - return PVO(QR(quotient, remainder), false) + return PVO(QR(Self(unchecked: quotient), remainder), false) } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift index 60b63367..4b596d47 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift @@ -25,7 +25,7 @@ extension NBKFlexibleWidth.Magnitude { // MARK: Initializers //=------------------------------------------------------------------------= - @inlinable public init(digit: Digit) { + @inlinable public init(digit: UInt) { self.init(storage: Storage(elements: [digit])) } @@ -44,16 +44,18 @@ extension NBKFlexibleWidth.Magnitude { @inlinable init?(exactlyIntegerLiteral source: StaticBigInt) { guard source.signum() >= 0 else { return nil } //=--------------------------------------= - let bitWidth = source.bitWidth - 1 - let quotient = bitWidth &>> UInt.bitWidth.trailingZeroBitCount - let remainder = bitWidth & (UInt.bitWidth - 1) - let count = Swift.max(1, quotient + Int(bit: !remainder.isZero)) + let bitWidth = source.bitWidth - 1 + let major = NBK .quotientDividingByBitWidthAssumingIsAtLeastZero(bitWidth) + let minor = NBK.remainderDividingByBitWidthAssumingIsAtLeastZero(bitWidth) + let count = major + Int(bit: !minor.isZero) //=--------------------------------------= - self = Self.uninitialized(count: count) { storage in + let storage = Storage.uninitialized(count: count) { storage in for index in storage.indices { storage[index] = source[index] } } + + self.init(unchecked: storage) } //=------------------------------------------------------------------------= diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text+Radix.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text+Radix.swift index ffb18018..503e6ab7 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text+Radix.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text+Radix.swift @@ -74,7 +74,7 @@ extension NBKFlexibleWidth.Magnitude { guard !digits.isEmpty else { self = Self.zero; return } //=--------------------------------------= var error = false - let value = Self.uninitialized(count: count) { storage in + let value = Storage.uninitialized(count: count) { storage in for index in storage.indices { let chunk = NBK.UnsafeUTF8(rebasing: NBK.removeSuffix(from: &digits, maxLength: radix.exponent)) guard let word = NBK.truncatingAsUInt(digits: chunk, radix: radix.base) else { return error = true } @@ -84,7 +84,7 @@ extension NBKFlexibleWidth.Magnitude { Swift.assert(digits.isEmpty) } - if !error { self = value } else { return nil } + if !error { self.init(unchecked: value) } else { return nil } } @inlinable init?(digits: NBK.UnsafeUTF8, radix: NBK.ImperfectRadixUIntRoot) { @@ -126,10 +126,10 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= // with one buffer pointer specialization //=--------------------------------------= - return self.storage.elements.withContiguousStorageIfAvailable { buffer in - let chunks = NBK.UnsafeWords(rebasing: NBK.dropLast(from: buffer, while: { $0.isZero })) + return self.storage.elements.withUnsafeBufferPointer { buffer in + let chunks = NBK.UnsafeWords(rebasing: NBK.dropLast(from: buffer, while: { $0.isZero })) return NBK.integerTextUnchecked(chunks: chunks, radix: radix, alphabet: alphabet, prefix: prefix, suffix: suffix) - }! + } } @inlinable func description(radix: NBK.ImperfectRadixUIntRoot, alphabet: NBK.MaxRadixAlphabetEncoder, prefix: NBK.UnsafeUTF8, suffix: NBK.UnsafeUTF8) -> String { diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Uninitialized.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Uninitialized.swift index 7b77120b..a5371b47 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Uninitialized.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Uninitialized.swift @@ -9,23 +9,6 @@ import NBKCoreKit -//*============================================================================* -// MARK: * NBK x Flexible Width x Uninitialized x Unsigned -//*============================================================================* - -extension NBKFlexibleWidth.Magnitude { - - //=------------------------------------------------------------------------= - // MARK: Initializers x Private - //=------------------------------------------------------------------------= - - @inlinable static func uninitialized(count: Int, body: (NBK.UnsafeMutableWords) -> Void) -> Self { - var storage = Storage.uninitialized(count: count, body: body) - storage.normalize() - return Self(unchecked: storage) - } -} - //*============================================================================* // MARK: * NBK x Flexible Width x Uninitialized x Unsigned x Storage //*============================================================================* @@ -38,7 +21,7 @@ extension NBKFlexibleWidth.Magnitude.Storage { @inlinable static func uninitialized(count: Int, body: (NBK.UnsafeMutableWords) -> Void) -> Self { let elements = Elements(unsafeUninitializedCapacity: count) { - elements, endIndex in + elements, endIndex in body(NBK.UnsafeMutableWords(rebasing: elements.prefix(upTo: count))) endIndex = count as Int } From 39c24ffc97b7516001e160d0e2691f81be181411 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sun, 16 Jul 2023 15:07:35 +0200 Subject: [PATCH 007/133] NBKFlexibleWidthKit: Cleanup. --- .../NBKFlexibleWidth+Addition+Digit.swift | 6 ++-- .../NBKFlexibleWidth+Addition.swift | 34 +++++++++++++++---- .../NBKFlexibleWidth+Numbers.swift | 12 +++---- .../NBKFlexibleWidth+Subtraction+Digit.swift | 4 +-- .../NBKFlexibleWidth+Subtraction.swift | 33 ++++++++++++++---- 5 files changed, 63 insertions(+), 26 deletions(-) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift index 1b575346..7ee96d10 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift @@ -38,7 +38,7 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= guard !other.isZero else { return } //=--------------------------------------= - self.storage.resize(minLastIndex: index + 1) + self.storage.resize(minLastIndex: index) var index: Int = index let overflow = self.storage.addAsFixedWidth(other, at: &index) @@ -66,11 +66,11 @@ extension NBKFlexibleWidth.Magnitude.Storage { @inlinable mutating func addAsFixedWidth(_ other: UInt, at index: inout Int) -> Bool { var overflow = self.elements[index].addReportingOverflow(other) self.elements.formIndex(after: &index) - self.carryAsFixedWidth(&overflow, from: &index) + self.addAsFixedWidth(Void(), at: &index, carrying: &overflow) return overflow as Bool } - @inlinable mutating func carryAsFixedWidth(_ overflow: inout Bool, from index: inout Int) { + @inlinable mutating func addAsFixedWidth(_ other: Void, at index: inout Int, carrying overflow: inout Bool) { while overflow && index < self.elements.endIndex { overflow = self.elements[index].addReportingOverflow(1 as UInt) self.elements.formIndex(after: &index) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift index c9f74f48..a9bd1f8a 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift @@ -38,16 +38,12 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= if other.isZero { return } //=--------------------------------------= - self.storage.resize(minCount: other.storage.elements.count + index) + self.storage.resize(minCount: index + other.storage.elements.count) var index = index var overflow = false - - for var addend in other.storage.elements { - overflow = addend.addReportingOverflow(UInt(bit: overflow)) - overflow = self.storage.elements[index].addReportingOverflow(addend) || overflow - self.storage.elements.formIndex(after: &index) - } + + self.storage.addAsFixedWidth(other.storage, at: &index, carrying: &overflow) if overflow { self.storage.elements.append(1 as UInt) @@ -60,3 +56,27 @@ extension NBKFlexibleWidth.Magnitude { return result as Self } } + +//*============================================================================* +// MARK: * NBK x Flexible Width x Addition x Unsigned x Storage +//*============================================================================* + +extension NBKFlexibleWidth.Magnitude.Storage { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable mutating func addAsFixedWidth(_ other: Self, at index: inout Int, carrying overflow: inout Bool) { + self.addAsFixedWidthWithoutCarryingBeyondIt(other, at: &index, carrying: &overflow) + self.addAsFixedWidth(Void(), at: &index, carrying: &overflow) + } + + @inlinable mutating func addAsFixedWidthWithoutCarryingBeyondIt(_ other: Self, at index: inout Int, carrying overflow: inout Bool) { + for var addend in other.elements { + overflow = addend.addReportingOverflow(UInt(bit: overflow)) + overflow = self.elements[index].addReportingOverflow(addend) || overflow + self.elements.formIndex(after: &index) + } + } +} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift index 4b596d47..2c5686bb 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift @@ -88,26 +88,24 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @inlinable public init(_ source: some BinaryFloatingPoint) { - self.init(exactly: source.rounded(.towardZero))! + guard let value = Self(exactly: source.rounded(.towardZero)) else { + preconditionFailure("\(Self.description) cannot represent \(source)") + } + + self = value } @inlinable public init?(exactly source: some BinaryFloatingPoint) { if source.sign == .minus { return nil } //=--------------------------------------= - // - //=--------------------------------------= if source.isZero { self.init(); return } guard source.isFinite else { return nil } let value = source.rounded(.towardZero) guard value == source else { return nil } //=--------------------------------------= - // - //=--------------------------------------= let exponent = Int(source.exponent) let ratio = exponent.quotientAndRemainder(dividingBy: UInt.bitWidth) //=--------------------------------------= - // - //=--------------------------------------= self.init(exactly: source.significandBitPattern) self >>= type(of: source).significandBitCount - exponent self.add(UInt(1) << ratio.remainder, at: ratio.quotient) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift index fb0d074c..1b92e426 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift @@ -70,11 +70,11 @@ extension NBKFlexibleWidth.Magnitude.Storage { @inlinable mutating func subtractAsFixedWidth(_ other: UInt, at index: inout Int) -> Bool { var overflow = self.elements[index].subtractReportingOverflow(other) self.elements.formIndex(after: &index) - self.borrowAsFixedWidth(&overflow, from: &index) + self.subtractAsFixedWidth(Void(), at: &index, borrowing: &overflow) return overflow as Bool } - @inlinable mutating func borrowAsFixedWidth(_ overflow: inout Bool, from index: inout Int) { + @inlinable mutating func subtractAsFixedWidth(_ other: Void, at index: inout Int, borrowing overflow: inout Bool) { while overflow && index < self.elements.endIndex { overflow = self.elements[index].subtractReportingOverflow(1 as UInt) self.elements.formIndex(after: &index) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift index ffc275a5..f92a9434 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift @@ -41,18 +41,13 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= if other.isZero { return false } //=--------------------------------------= - self.storage.resize(minCount: other.storage.elements.count + index) + self.storage.resize(minCount: index + other.storage.elements.count) var index = index var overflow = false - for var subtrahend in other.storage.elements { - overflow = subtrahend.addReportingOverflow(UInt(bit: overflow)) - overflow = self.storage.elements[index].subtractReportingOverflow(subtrahend) || overflow - self.storage.elements.formIndex(after: &index) - } + self.storage.subtractAsFixedWidth(other.storage, at: &index, borrowing: &overflow) - self.storage.borrowAsFixedWidth(&overflow, from: &index) self.storage.normalize() return overflow as Bool } @@ -63,3 +58,27 @@ extension NBKFlexibleWidth.Magnitude { return PVO(partialValue, overflow) } } + +//*============================================================================* +// MARK: * NBK x Flexible Width x Subtraction x Unsigned x Storage +//*============================================================================* + +extension NBKFlexibleWidth.Magnitude.Storage { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable mutating func subtractAsFixedWidth(_ other: Self, at index: inout Int, borrowing overflow: inout Bool) { + self.subtractAsFixedWidthWithoutBorrowingBeyondIt(other, at: &index, borrowing: &overflow) + self.subtractAsFixedWidth(Void(), at: &index, borrowing: &overflow) + } + + @inlinable mutating func subtractAsFixedWidthWithoutBorrowingBeyondIt(_ other: Self, at index: inout Int, borrowing overflow: inout Bool) { + for var subtrahend in other.elements { + overflow = subtrahend.addReportingOverflow(UInt(bit: overflow)) + overflow = self.elements[index].subtractReportingOverflow(subtrahend) || overflow + self.elements.formIndex(after: &index) + } + } +} From 4bfaa4c88fd025ea29301c68bf2a0a38c582bc54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sun, 16 Jul 2023 18:11:23 +0200 Subject: [PATCH 008/133] NBKFlexibleWidthKit: Addition, Subtraction. --- .../NBKFlexibleWidth+Addition.swift | 20 +++++++++++++------ .../NBKFlexibleWidth+Subtraction.swift | 20 +++++++++++++------ .../IntXL+Subtraction.swift | 4 ++-- 3 files changed, 30 insertions(+), 14 deletions(-) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift index a9bd1f8a..4ece336c 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift @@ -36,7 +36,7 @@ extension NBKFlexibleWidth.Magnitude { Swift.assert(self.storage.isNormal) } //=--------------------------------------= - if other.isZero { return } + if other.isZero { return } //=--------------------------------------= self.storage.resize(minCount: index + other.storage.elements.count) @@ -68,14 +68,22 @@ extension NBKFlexibleWidth.Magnitude.Storage { //=------------------------------------------------------------------------= @inlinable mutating func addAsFixedWidth(_ other: Self, at index: inout Int, carrying overflow: inout Bool) { - self.addAsFixedWidthWithoutCarryingBeyondIt(other, at: &index, carrying: &overflow) + self.addAsFixedWidthWithoutGoingBeyond(other, at: &index, carrying: &overflow) self.addAsFixedWidth(Void(), at: &index, carrying: &overflow) } - @inlinable mutating func addAsFixedWidthWithoutCarryingBeyondIt(_ other: Self, at index: inout Int, carrying overflow: inout Bool) { - for var addend in other.elements { - overflow = addend.addReportingOverflow(UInt(bit: overflow)) - overflow = self.elements[index].addReportingOverflow(addend) || overflow + @inlinable mutating func addAsFixedWidthWithoutGoingBeyond(_ other: Self, at index: inout Int, carrying overflow: inout Bool) { + for otherIndex in other.elements.indices { + var lhsWord = self .elements[index] + let rhsWord = other.elements[otherIndex] + + if !overflow { + overflow = lhsWord.addReportingOverflow(rhsWord) + } else if rhsWord != UInt.max { + overflow = lhsWord.addReportingOverflow(rhsWord &+ 1) + } + + self.elements[index] = lhsWord self.elements.formIndex(after: &index) } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift index f92a9434..e2b2ea57 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift @@ -39,7 +39,7 @@ extension NBKFlexibleWidth.Magnitude { Swift.assert(self.storage.isNormal) } //=--------------------------------------= - if other.isZero { return false } + if other.isZero { return false } //=--------------------------------------= self.storage.resize(minCount: index + other.storage.elements.count) @@ -70,14 +70,22 @@ extension NBKFlexibleWidth.Magnitude.Storage { //=------------------------------------------------------------------------= @inlinable mutating func subtractAsFixedWidth(_ other: Self, at index: inout Int, borrowing overflow: inout Bool) { - self.subtractAsFixedWidthWithoutBorrowingBeyondIt(other, at: &index, borrowing: &overflow) + self.subtractAsFixedWidthWithoutGoingBeyond(other, at: &index, borrowing: &overflow) self.subtractAsFixedWidth(Void(), at: &index, borrowing: &overflow) } - @inlinable mutating func subtractAsFixedWidthWithoutBorrowingBeyondIt(_ other: Self, at index: inout Int, borrowing overflow: inout Bool) { - for var subtrahend in other.elements { - overflow = subtrahend.addReportingOverflow(UInt(bit: overflow)) - overflow = self.elements[index].subtractReportingOverflow(subtrahend) || overflow + @inlinable mutating func subtractAsFixedWidthWithoutGoingBeyond(_ other: Self, at index: inout Int, borrowing overflow: inout Bool) { + for otherIndex in other.elements.indices { + var lhsWord = self .elements[index] + let rhsWord = other.elements[otherIndex] + + if !overflow { + overflow = lhsWord.subtractReportingOverflow(rhsWord) + } else if rhsWord != UInt.max { + overflow = lhsWord.subtractReportingOverflow(rhsWord &+ 1) + } + + self.elements[index] = lhsWord self.elements.formIndex(after: &index) } } diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Subtraction.swift b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Subtraction.swift index 70579de1..b9e4cfbf 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Subtraction.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Subtraction.swift @@ -28,7 +28,7 @@ final class UIntXLBenchmarksOnSubtraction: XCTestCase { // MARK: Tests //=------------------------------------------------------------------------= - func testAdding() { + func testSubtracting() { var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) @@ -43,7 +43,7 @@ final class UIntXLBenchmarksOnSubtraction: XCTestCase { // MARK: Tests x Digit //=------------------------------------------------------------------------= - func testAddingDigit() { + func testSubtractingDigit() { var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) var rhs = NBK.blackHoleIdentity(UInt.max) From 65882acd771c258f52a0eb000b01591ca104eebc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sun, 16 Jul 2023 20:32:51 +0200 Subject: [PATCH 009/133] NBKFlexibleWidthKit: Cleanup. --- .../NBKFlexibleWidth+Addition+Digit.swift | 36 +++-------- .../NBKFlexibleWidth+Addition+Storage.swift | 62 +++++++++++++++++++ .../NBKFlexibleWidth+Addition.swift | 35 +---------- .../NBKFlexibleWidth+Storage.swift | 9 --- .../NBKFlexibleWidth+Subtraction+Digit.swift | 32 ++-------- ...NBKFlexibleWidth+Subtraction+Storage.swift | 62 +++++++++++++++++++ .../NBKFlexibleWidth+Subtraction.swift | 35 +---------- .../NBKFlexibleWidth.swift | 6 +- 8 files changed, 146 insertions(+), 131 deletions(-) create mode 100644 Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Storage.swift create mode 100644 Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Storage.swift diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift index 7ee96d10..5f23f13c 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift @@ -38,12 +38,17 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= guard !other.isZero else { return } //=--------------------------------------= + // TODO: better resizing methods self.storage.resize(minLastIndex: index) - var index: Int = index - let overflow = self.storage.addAsFixedWidth(other, at: &index) + var index = index + var overflow = false - self.storage.normalizeAppend(UInt(bit: overflow)) + self.storage.add(other, at: &index, carrying: &overflow) + + if overflow { + self.storage.elements.append(1) + } } @_disfavoredOverload @inlinable public func adding(_ other: UInt, at index: Int) -> Self { @@ -52,28 +57,3 @@ extension NBKFlexibleWidth.Magnitude { return result as Self } } - -//*============================================================================* -// MARK: * NBK x Flexible Width x Addition x Digit x Unsigned x Storage -//*============================================================================* - -extension NBKFlexibleWidth.Magnitude.Storage { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable mutating func addAsFixedWidth(_ other: UInt, at index: inout Int) -> Bool { - var overflow = self.elements[index].addReportingOverflow(other) - self.elements.formIndex(after: &index) - self.addAsFixedWidth(Void(), at: &index, carrying: &overflow) - return overflow as Bool - } - - @inlinable mutating func addAsFixedWidth(_ other: Void, at index: inout Int, carrying overflow: inout Bool) { - while overflow && index < self.elements.endIndex { - overflow = self.elements[index].addReportingOverflow(1 as UInt) - self.elements.formIndex(after: &index) - } - } -} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Storage.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Storage.swift new file mode 100644 index 00000000..90ce375d --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Storage.swift @@ -0,0 +1,62 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x Addition x Unsigned x Storage +//*============================================================================* + +extension NBKFlexibleWidth.Magnitude.Storage { + + //=------------------------------------------------------------------------= + // MARK: Transformations x Self + //=------------------------------------------------------------------------= + + @inlinable mutating func add(_ other: Self, at index: inout Int, carrying overflow: inout Bool) { + self.addWithoutGoingBeyond(other, at: &index, carrying: &overflow) + self.add((), at: &index, carrying: &overflow) + } + + @inlinable mutating func addWithoutGoingBeyond(_ other: Self, at index: inout Int, carrying overflow: inout Bool) { + for otherIndex in other.elements.indices { // for-index-in >= for-element-in + self.addWithoutGoingBeyond(other.elements[otherIndex], at: &index, carrying: &overflow) + } + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x UInt + //=------------------------------------------------------------------------= + + @inlinable mutating func add(_ other: UInt, at index: inout Int, carrying overflow: inout Bool) { + self.addWithoutGoingBeyond(other, at: &index, carrying: &overflow) + self.add((), at: &index, carrying: &overflow) + } + + @inlinable mutating func addWithoutGoingBeyond(_ other: UInt, at index: inout Int, carrying overflow: inout Bool) { + if !overflow { + overflow = self.elements[index].addReportingOverflow(other) + } else if other != UInt.max { + overflow = self.elements[index].addReportingOverflow(other &+ 1) + } + + self.elements.formIndex(after: &index) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Void + //=------------------------------------------------------------------------= + + @inlinable mutating func add(_ other: Void, at index: inout Int, carrying overflow: inout Bool) { + while overflow && index < self.elements.endIndex { + overflow = self.elements[index].addReportingOverflow(1 as UInt) + self.elements.formIndex(after: &index) + } + } +} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift index 4ece336c..ef902473 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift @@ -38,12 +38,13 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= if other.isZero { return } //=--------------------------------------= + // TODO: better resizing methods self.storage.resize(minCount: index + other.storage.elements.count) var index = index var overflow = false - self.storage.addAsFixedWidth(other.storage, at: &index, carrying: &overflow) + self.storage.add(other.storage, at: &index, carrying: &overflow) if overflow { self.storage.elements.append(1 as UInt) @@ -56,35 +57,3 @@ extension NBKFlexibleWidth.Magnitude { return result as Self } } - -//*============================================================================* -// MARK: * NBK x Flexible Width x Addition x Unsigned x Storage -//*============================================================================* - -extension NBKFlexibleWidth.Magnitude.Storage { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable mutating func addAsFixedWidth(_ other: Self, at index: inout Int, carrying overflow: inout Bool) { - self.addAsFixedWidthWithoutGoingBeyond(other, at: &index, carrying: &overflow) - self.addAsFixedWidth(Void(), at: &index, carrying: &overflow) - } - - @inlinable mutating func addAsFixedWidthWithoutGoingBeyond(_ other: Self, at index: inout Int, carrying overflow: inout Bool) { - for otherIndex in other.elements.indices { - var lhsWord = self .elements[index] - let rhsWord = other.elements[otherIndex] - - if !overflow { - overflow = lhsWord.addReportingOverflow(rhsWord) - } else if rhsWord != UInt.max { - overflow = lhsWord.addReportingOverflow(rhsWord &+ 1) - } - - self.elements[index] = lhsWord - self.elements.formIndex(after: &index) - } - } -} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Storage.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Storage.swift index dc1f7ae6..f1adfd00 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Storage.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Storage.swift @@ -47,15 +47,6 @@ extension NBKFlexibleWidth.Magnitude.Storage { } } - /// Normalizes the underlying storage after appending the element. - @inlinable mutating func normalizeAppend(_ element: UInt) { - if element.isZero { - self.normalize() - } else { - self.elements.append(element) - } - } - //=------------------------------------------------------------------------= // MARK: Transformations //=------------------------------------------------------------------------= diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift index 1b92e426..deed8af5 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift @@ -41,10 +41,13 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= guard !other.isZero else { return false } //=--------------------------------------= + // TODO: better resizing methods self.storage.resize(minLastIndex: index) - var index: Int = index - let overflow = self.storage.subtractAsFixedWidth(other, at: &index) + var index = index + var overflow = false + + self.storage.subtract(other, at: &index, borrowing: &overflow) self.storage.normalize() return overflow as Bool @@ -56,28 +59,3 @@ extension NBKFlexibleWidth.Magnitude { return PVO(partialValue, overflow) } } - -//*============================================================================* -// MARK: * NBK x Flexible Width x Subtraction x Digit x Unsigned x Storage -//*============================================================================* - -extension NBKFlexibleWidth.Magnitude.Storage { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable mutating func subtractAsFixedWidth(_ other: UInt, at index: inout Int) -> Bool { - var overflow = self.elements[index].subtractReportingOverflow(other) - self.elements.formIndex(after: &index) - self.subtractAsFixedWidth(Void(), at: &index, borrowing: &overflow) - return overflow as Bool - } - - @inlinable mutating func subtractAsFixedWidth(_ other: Void, at index: inout Int, borrowing overflow: inout Bool) { - while overflow && index < self.elements.endIndex { - overflow = self.elements[index].subtractReportingOverflow(1 as UInt) - self.elements.formIndex(after: &index) - } - } -} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Storage.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Storage.swift new file mode 100644 index 00000000..4b9dab84 --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Storage.swift @@ -0,0 +1,62 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x Subtraction x Unsigned x Storage +//*============================================================================* + +extension NBKFlexibleWidth.Magnitude.Storage { + + //=------------------------------------------------------------------------= + // MARK: Transformations x Self + //=------------------------------------------------------------------------= + + @inlinable mutating func subtract(_ other: Self, at index: inout Int, borrowing overflow: inout Bool) { + self.subtractWithoutGoingBeyond(other, at: &index, borrowing: &overflow) + self.subtract((), at: &index, borrowing: &overflow) + } + + @inlinable mutating func subtractWithoutGoingBeyond(_ other: Self, at index: inout Int, borrowing overflow: inout Bool) { + for otherIndex in other.elements.indices { // for-index-in >= for-element-in + self.subtractWithoutGoingBeyond(other.elements[otherIndex], at: &index, borrowing: &overflow) + } + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x UInt + //=------------------------------------------------------------------------= + + @inlinable mutating func subtract(_ other: UInt, at index: inout Int, borrowing overflow: inout Bool) { + self.subtractWithoutGoingBeyond(other, at: &index, borrowing: &overflow) + self.subtract((), at: &index, borrowing: &overflow) + } + + @inlinable mutating func subtractWithoutGoingBeyond(_ other: UInt, at index: inout Int, borrowing overflow: inout Bool) { + if !overflow { + overflow = self.elements[index].subtractReportingOverflow(other) + } else if other != UInt.max { + overflow = self.elements[index].subtractReportingOverflow(other &+ 1) + } + + self.elements.formIndex(after: &index) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Void + //=------------------------------------------------------------------------= + + @inlinable mutating func subtract(_ other: Void, at index: inout Int, borrowing overflow: inout Bool) { + while overflow && index < self.elements.endIndex { + overflow = self.elements[index].subtractReportingOverflow(1 as UInt) + self.elements.formIndex(after: &index) + } + } +} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift index e2b2ea57..9b38cf91 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift @@ -41,12 +41,13 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= if other.isZero { return false } //=--------------------------------------= + // TODO: better resizing methods self.storage.resize(minCount: index + other.storage.elements.count) var index = index var overflow = false - self.storage.subtractAsFixedWidth(other.storage, at: &index, borrowing: &overflow) + self.storage.subtract(other.storage, at: &index, borrowing: &overflow) self.storage.normalize() return overflow as Bool @@ -58,35 +59,3 @@ extension NBKFlexibleWidth.Magnitude { return PVO(partialValue, overflow) } } - -//*============================================================================* -// MARK: * NBK x Flexible Width x Subtraction x Unsigned x Storage -//*============================================================================* - -extension NBKFlexibleWidth.Magnitude.Storage { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable mutating func subtractAsFixedWidth(_ other: Self, at index: inout Int, borrowing overflow: inout Bool) { - self.subtractAsFixedWidthWithoutGoingBeyond(other, at: &index, borrowing: &overflow) - self.subtractAsFixedWidth(Void(), at: &index, borrowing: &overflow) - } - - @inlinable mutating func subtractAsFixedWidthWithoutGoingBeyond(_ other: Self, at index: inout Int, borrowing overflow: inout Bool) { - for otherIndex in other.elements.indices { - var lhsWord = self .elements[index] - let rhsWord = other.elements[otherIndex] - - if !overflow { - overflow = lhsWord.subtractReportingOverflow(rhsWord) - } else if rhsWord != UInt.max { - overflow = lhsWord.subtractReportingOverflow(rhsWord &+ 1) - } - - self.elements[index] = lhsWord - self.elements.formIndex(after: &index) - } - } -} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift index c48635a9..8d8ae3d5 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift @@ -57,9 +57,13 @@ import NBKCoreKit // MARK: * Storage //*====================================================================* + /// A contiguous collection of machine words. + /// + /// - Note: It's methods have fixed-width semantics unless stated otherwise. + /// @frozen @usableFromInline struct Storage: Hashable { - @usableFromInline typealias Elements = [UInt] + @usableFromInline typealias Elements = Array //=----------------------------------------------------------------= // MARK: State From 6b7c4113e36b5f4ffc2fdd2bcc616aedbf0121df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Mon, 17 Jul 2023 12:38:25 +0200 Subject: [PATCH 010/133] NBKFlexibleWidthKit: Addition, Subtraction. --- .../NBKFlexibleWidth+Addition+Storage.swift | 10 ++++++--- .../NBKFlexibleWidth+Storage.swift | 16 +++++--------- ...NBKFlexibleWidth+Subtraction+Storage.swift | 8 +++++-- .../IntXL+Addition.swift | 22 +++++++++++++++++++ .../IntXL+Subtraction.swift | 22 +++++++++++++++++++ 5 files changed, 63 insertions(+), 15 deletions(-) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Storage.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Storage.swift index 90ce375d..73989c39 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Storage.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Storage.swift @@ -40,12 +40,16 @@ extension NBKFlexibleWidth.Magnitude.Storage { } @inlinable mutating func addWithoutGoingBeyond(_ other: UInt, at index: inout Int, carrying overflow: inout Bool) { + var other = other as UInt + + if overflow { + overflow = other.addReportingOverflow(1 as UInt) + } + if !overflow { overflow = self.elements[index].addReportingOverflow(other) - } else if other != UInt.max { - overflow = self.elements[index].addReportingOverflow(other &+ 1) } - + self.elements.formIndex(after: &index) } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Storage.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Storage.swift index f1adfd00..f5aa4c51 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Storage.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Storage.swift @@ -27,19 +27,19 @@ extension NBKFlexibleWidth.Magnitude.Storage { self.init(elements: Elements(repeating: element, count: count)) } - //=--------------------------------------------------------------------= + //=------------------------------------------------------------------------= // MARK: Accessors - //=--------------------------------------------------------------------= - + //=------------------------------------------------------------------------= + /// Returns whether the underlying storage is normalized. @inlinable var isNormal: Bool { self.elements.last != 0 as UInt } - //=--------------------------------------------------------------------= + //=------------------------------------------------------------------------= // MARK: Transformations - //=--------------------------------------------------------------------= - + //=------------------------------------------------------------------------= + /// Normalizes the underlying storage. @inlinable mutating func normalize() { trimming: while self.elements.last == 0 as UInt { @@ -47,10 +47,6 @@ extension NBKFlexibleWidth.Magnitude.Storage { } } - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - /// Resizes the underlying storage, if needed. @inlinable mutating func resize(minCount: Int) { self.elements.reserveCapacity(minCount) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Storage.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Storage.swift index 4b9dab84..1dd15b47 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Storage.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Storage.swift @@ -40,10 +40,14 @@ extension NBKFlexibleWidth.Magnitude.Storage { } @inlinable mutating func subtractWithoutGoingBeyond(_ other: UInt, at index: inout Int, borrowing overflow: inout Bool) { + var other = other as UInt + + if overflow { + overflow = other.addReportingOverflow(1 as UInt) + } + if !overflow { overflow = self.elements[index].subtractReportingOverflow(other) - } else if other != UInt.max { - overflow = self.elements[index].subtractReportingOverflow(other &+ 1) } self.elements.formIndex(after: &index) diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Addition.swift b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Addition.swift index 7ab325bc..e52193ac 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Addition.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Addition.swift @@ -28,6 +28,17 @@ final class UIntXLBenchmarksOnAddition: XCTestCase { // MARK: Tests //=------------------------------------------------------------------------= + func testAdd() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs += rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + func testAdding() { var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) @@ -43,6 +54,17 @@ final class UIntXLBenchmarksOnAddition: XCTestCase { // MARK: Tests x Digit //=------------------------------------------------------------------------= + func testAddDigit() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(UInt.max) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs += rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + func testAddingDigit() { var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) var rhs = NBK.blackHoleIdentity(UInt.max) diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Subtraction.swift b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Subtraction.swift index b9e4cfbf..def33fd5 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Subtraction.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Subtraction.swift @@ -28,6 +28,17 @@ final class UIntXLBenchmarksOnSubtraction: XCTestCase { // MARK: Tests //=------------------------------------------------------------------------= + func testSubtract() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs -= rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + func testSubtracting() { var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) @@ -43,6 +54,17 @@ final class UIntXLBenchmarksOnSubtraction: XCTestCase { // MARK: Tests x Digit //=------------------------------------------------------------------------= + func testSubtractDigit() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(UInt.max) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs -= rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + func testSubtractingDigit() { var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) var rhs = NBK.blackHoleIdentity(UInt.max) From b5b6ba004172dfbf9491746b2651314220268597 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Mon, 17 Jul 2023 13:20:34 +0200 Subject: [PATCH 011/133] NBKFlexibleWidthKit: Multiplication. --- .../NBKFlexibleWidth+Addition+Digit.swift | 7 ++-- .../NBKFlexibleWidth+Addition.swift | 5 +-- .../NBKFlexibleWidth+Division.swift | 2 +- .../NBKFlexibleWidth+Logic.swift | 12 +++++-- .../NBKFlexibleWidth+Miscellaneous.swift | 31 ++++++++++++++++ ...BKFlexibleWidth+Multiplication+Digit.swift | 36 +++++++++---------- ...FlexibleWidth+Multiplication+Storage.swift | 29 +++++++++++++++ .../NBKFlexibleWidth+Shifts.swift | 2 +- .../NBKFlexibleWidth+Storage.swift | 14 +++++--- .../NBKFlexibleWidth+Subtraction+Digit.swift | 5 ++- .../NBKFlexibleWidth+Text+Radix.swift | 5 +-- .../Utilities/NBKAssert+Multiplication.swift | 4 +-- 12 files changed, 105 insertions(+), 47 deletions(-) create mode 100644 Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Miscellaneous.swift create mode 100644 Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Storage.swift diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift index 5f23f13c..55d9e65f 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift @@ -36,9 +36,8 @@ extension NBKFlexibleWidth.Magnitude { Swift.assert(self.storage.isNormal) } //=--------------------------------------= - guard !other.isZero else { return } + if other.isZero { return } //=--------------------------------------= - // TODO: better resizing methods self.storage.resize(minLastIndex: index) var index = index @@ -52,8 +51,6 @@ extension NBKFlexibleWidth.Magnitude { } @_disfavoredOverload @inlinable public func adding(_ other: UInt, at index: Int) -> Self { - var result = self - result.add(other, at: index) - return result as Self + var result = self; result.add(other, at: index); return result } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift index ef902473..0ac0565e 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift @@ -38,7 +38,6 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= if other.isZero { return } //=--------------------------------------= - // TODO: better resizing methods self.storage.resize(minCount: index + other.storage.elements.count) var index = index @@ -52,8 +51,6 @@ extension NBKFlexibleWidth.Magnitude { } @inlinable public func adding(_ other: Self, at index: Int) -> Self { - var result = self - result.add(other, at: index) - return result as Self + var result = self; result.add(other, at: index); return result } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift index 8ea8866a..15a20ac3 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift @@ -106,7 +106,7 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------= var digit = remainderLast0 == divisorLast0 ? UInt.max : divisorLast0.dividingFullWidth(HL(remainderLast0, remainderLast1)).quotient if !digit.isZero { - var approximation = divisor.multiplied(by: digit) + var approximation: Self = divisor * digit while remainder.compared(to: approximation, at: quotientIndex) < 0 as Int { _ = digit.subtractReportingOverflow(1 as UInt) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift index 53d4a31a..402bd5a8 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift @@ -24,7 +24,9 @@ extension NBKFlexibleWidth.Magnitude { } @inlinable public static func &=(lhs: inout Self, rhs: Self) { - defer { Swift.assert(lhs.storage.isNormal) } + defer { + Swift.assert(lhs.storage.isNormal) + } //=--------------------------------------= if lhs.storage.elements.endIndex > rhs.storage.elements.endIndex { lhs.storage.elements.removeSubrange(rhs.storage.elements.endIndex...) @@ -46,7 +48,9 @@ extension NBKFlexibleWidth.Magnitude { } @inlinable public static func |=(lhs: inout Self, rhs: Self) { - defer { Swift.assert(lhs.storage.isNormal) } + defer { + Swift.assert(lhs.storage.isNormal) + } //=--------------------------------------= lhs.storage.elements.reserveCapacity(rhs.storage.elements.count) //=--------------------------------------= @@ -66,7 +70,9 @@ extension NBKFlexibleWidth.Magnitude { } @inlinable public static func ^=(lhs: inout Self, rhs: Self) { - defer { lhs.storage.normalize() } + defer { + lhs.storage.normalize() + } //=--------------------------------------= lhs.storage.elements.reserveCapacity(rhs.storage.elements.count) //=--------------------------------------= diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Miscellaneous.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Miscellaneous.swift new file mode 100644 index 00000000..de4405f0 --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Miscellaneous.swift @@ -0,0 +1,31 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x Miscellaneous x Unsigned +//*============================================================================* + +extension NBKFlexibleWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable mutating func assignZeroValue() { + self.storage.elements.removeAll(keepingCapacity: true) + } + + @inlinable mutating func assign(_ other: UInt) { + self.storage.elements.removeAll(keepingCapacity: true) + guard !other.isZero else { return } + self.storage.elements.append(other) + } +} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift index c2d129a1..e285ecee 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift @@ -20,40 +20,38 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @_disfavoredOverload @inlinable public static func *=(lhs: inout Self, rhs: UInt) { - lhs.multiply(by: rhs) + lhs.multiply(by: rhs, adding: UInt.zero) } @_disfavoredOverload @inlinable public static func *(lhs: Self, rhs: UInt) -> Self { - var lhs = lhs; lhs *= rhs; return lhs + lhs.multiplied(by: rhs, adding: UInt.zero) } //=------------------------------------------------------------------------= - // MARK: Transformations x Private + // MARK: Transformations //=------------------------------------------------------------------------= - @_disfavoredOverload @inlinable mutating func multiply(by other: UInt) { - defer { Swift.assert(self.storage.isNormal) } - //=--------------------------------------= - if other.isZero { - return self = Self.zero + @_disfavoredOverload @inlinable mutating func multiply(by multiplicand: UInt, adding addend: UInt) { + defer { + Swift.assert(self.storage.isNormal) } //=--------------------------------------= - self.storage.elements.reserveCapacity(self.storage.elements.count + 1) + if multiplicand.isZero { + return self.assign(addend) + } //=--------------------------------------= - var carry = UInt.zero + self.storage.reserve(minCount: self.storage.elements.count + 1) - for index in self.storage.elements.indices { - var subproduct = self.storage.elements[index].multipliedFullWidth(by: other) - subproduct.high &+= UInt(bit: subproduct.low.addReportingOverflow(carry)) - (carry, self.storage.elements[index]) = subproduct as HL - } + var overflow = addend as UInt + + self.storage.multiply(by: multiplicand, carrying: &overflow) - if !carry.isZero { - self.storage.elements.append(carry) + if !overflow.isZero { + self.storage.elements.append(overflow) } } - @_disfavoredOverload @inlinable func multiplied(by other: UInt) -> Self { - var result = self; result.multiply(by: other); return result as Self + @_disfavoredOverload @inlinable func multiplied(by multiplicand: UInt, adding addend: UInt) -> Self { + var result = self; result.multiply(by: multiplicand, adding: addend); return result } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Storage.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Storage.swift new file mode 100644 index 00000000..c5df6a8b --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Storage.swift @@ -0,0 +1,29 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x Multiplication x Digit x Unsigned x Storage +//*============================================================================* + +extension NBKFlexibleWidth.Magnitude.Storage { + + //=------------------------------------------------------------------------= + // MARK: Transformations x UInt + //=------------------------------------------------------------------------= + + @inlinable mutating func multiply(by other: UInt, carrying overflow: inout UInt) { + for index in self.elements.indices { + var subproduct = self.elements[index].multipliedFullWidth(by: other) + subproduct.high &+= UInt(bit: subproduct.low.addReportingOverflow(overflow)) + (overflow, self.elements[index]) = subproduct as HL + } + } +} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift index 646daf72..892d87d4 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift @@ -153,7 +153,7 @@ extension NBKFlexibleWidth.Magnitude { precondition(bits >= 0 && bits < UInt.bitWidth, NBK.callsiteOutOfBoundsInfo()) //=--------------------------------------= if words >= self.storage.elements.count { - return self = Self.zero + return self.assignZeroValue() } //=--------------------------------------= if bits.isZero { diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Storage.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Storage.swift index f5aa4c51..087218c0 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Storage.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Storage.swift @@ -31,7 +31,6 @@ extension NBKFlexibleWidth.Magnitude.Storage { // MARK: Accessors //=------------------------------------------------------------------------= - /// Returns whether the underlying storage is normalized. @inlinable var isNormal: Bool { self.elements.last != 0 as UInt } @@ -40,23 +39,28 @@ extension NBKFlexibleWidth.Magnitude.Storage { // MARK: Transformations //=------------------------------------------------------------------------= - /// Normalizes the underlying storage. @inlinable mutating func normalize() { trimming: while self.elements.last == 0 as UInt { self.elements.removeLast() } } - /// Resizes the underlying storage, if needed. @inlinable mutating func resize(minCount: Int) { - self.elements.reserveCapacity(minCount) + self.reserve(minCount: minCount) appending: while self.elements.count < minCount { self.elements.append(UInt.zero) } } - /// Resizes the underlying storage, if needed. @inlinable mutating func resize(minLastIndex: Int) { self.resize(minCount: minLastIndex + 1) } + + @inlinable mutating func reserve(minCount: Int) { + self.elements.reserveCapacity(minCount) + } + + @inlinable mutating func reserve(minLastIndex: Int) { + self.reserve(minCount: minLastIndex + 1) + } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift index deed8af5..ed2354d0 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift @@ -39,12 +39,11 @@ extension NBKFlexibleWidth.Magnitude { Swift.assert(self.storage.isNormal) } //=--------------------------------------= - guard !other.isZero else { return false } + if other.isZero { return false } //=--------------------------------------= - // TODO: better resizing methods self.storage.resize(minLastIndex: index) - var index = index + var index = index var overflow = false self.storage.subtract(other, at: &index, borrowing: &overflow) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text+Radix.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text+Radix.swift index 503e6ab7..1856c135 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text+Radix.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text+Radix.swift @@ -71,8 +71,6 @@ extension NBKFlexibleWidth.Magnitude { let division = digits.count.quotientAndRemainder(dividingBy: radix.exponent) let count = division.quotient + Int(bit: !division.remainder.isZero) //=--------------------------------------= - guard !digits.isEmpty else { self = Self.zero; return } - //=--------------------------------------= var error = false let value = Storage.uninitialized(count: count) { storage in for index in storage.indices { @@ -105,8 +103,7 @@ extension NBKFlexibleWidth.Magnitude { forwards: while !digits.isEmpty { let chunk = NBK.UnsafeUTF8(rebasing: NBK.removePrefix(from: &digits, count: radix.exponent)) guard let word = NBK.truncatingAsUInt(digits: chunk, radix: radix.base) else { return nil } - self *= radix.power // TODO: combined * and + method - self += word + self.multiply(by: radix.power, adding: word) } }() as Void? else { return nil } diff --git a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Multiplication.swift b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Multiplication.swift index 9d2d0013..9c08be90 100644 --- a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Multiplication.swift +++ b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Multiplication.swift @@ -31,6 +31,6 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual( lhs * rhs, result, file: file, line: line) XCTAssertEqual({ var lhs = lhs; lhs *= rhs; return lhs }(), result, file: file, line: line) - XCTAssertEqual(lhs.multiplied(by: rhs), result, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs.multiply(by: rhs); return lhs }(), result, file: file, line: line) + XCTAssertEqual(lhs.multiplied(by: rhs, adding: UInt.zero), result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs.multiply(by: rhs, adding: UInt.zero); return lhs }(), result, file: file, line: line) } From 8cbb0863c1de6adb686623a535fe06bff386b8ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Mon, 17 Jul 2023 16:19:31 +0200 Subject: [PATCH 012/133] NBKFlexibleWidthKit: Multiplication. --- ...FlexibleWidth+Multiplication+Storage.swift | 29 ++++++++++++++++ .../NBKFlexibleWidth+Multiplication.swift | 33 ++++--------------- .../Utilities/NBKAssert+Multiplication.swift | 4 +-- 3 files changed, 38 insertions(+), 28 deletions(-) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Storage.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Storage.swift index c5df6a8b..2a289497 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Storage.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Storage.swift @@ -15,6 +15,35 @@ import NBKCoreKit extension NBKFlexibleWidth.Magnitude.Storage { + //=------------------------------------------------------------------------= + // MARK: Transformations x Self + //=------------------------------------------------------------------------= + + @inlinable func multipliedFullWidth(by multiplicand: Self, adding addend: UInt) -> Self { + Self.uninitialized(count: self.elements.count + multiplicand.elements.count) { product in + //=----------------------------------= + // de/init: pointee is trivial + //=----------------------------------= + product.update(repeating: UInt.zero) + //=----------------------------------= + var overflow = addend as UInt + for lhsIndex in self.elements.indices { + let outer = self.elements[lhsIndex] + + for rhsIndex in multiplicand.elements.indices { + let inner = multiplicand.elements[rhsIndex] + var subproduct = outer.multipliedFullWidth(by: inner) + + overflow = UInt(bit: subproduct.low.addReportingOverflow(overflow)) + overflow &+= UInt(bit: product[lhsIndex + rhsIndex].addReportingOverflow(subproduct.low)) + overflow &+= subproduct.high + } + + (product[lhsIndex + multiplicand.elements.count], overflow) = (overflow, UInt.zero) + } + } + } + //=------------------------------------------------------------------------= // MARK: Transformations x UInt //=------------------------------------------------------------------------= diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift index 93b9289f..6f595962 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift @@ -20,41 +20,22 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @inlinable public static func *=(lhs: inout Self, rhs: Self) { - lhs.multiply(by: rhs) + lhs.multiply(by: rhs, adding: UInt.zero) } @inlinable public static func *(lhs: Self, rhs: Self) -> Self { - lhs.multiplied(by: rhs) + lhs.multiplied(by: rhs, adding: UInt.zero) } //=------------------------------------------------------------------------= - // MARK: Transformations x Private + // MARK: Transformations //=------------------------------------------------------------------------= - @inlinable mutating func multiply(by other: Self) { - self = self.multiplied(by: other) + @inlinable public mutating func multiply(by multiplicand: Self, adding addend: UInt) { + self = self.multiplied(by: multiplicand, adding: addend) } - @inlinable func multiplied(by other: Self) -> Self { - //=--------------------------------------= - let capacity: Int = self.storage.elements.count + other.storage.elements.count - var product = Storage(repeating: UInt(), count: capacity) - //=--------------------------------------= - for lhsIndex in self.storage.elements.indices { - var carry = UInt.zero - - for rhsIndex in other.storage.elements.indices { - var subproduct = self.storage.elements[lhsIndex].multipliedFullWidth(by: other.storage.elements[rhsIndex]) - - carry = UInt(bit: subproduct.low.addReportingOverflow(carry)) - carry &+= UInt(bit: product.elements[lhsIndex + rhsIndex].addReportingOverflow(subproduct.low)) - carry &+= subproduct.high - } - - product.elements[lhsIndex + other.storage.elements.endIndex] = carry - } - //=--------------------------------------= - product.normalize() - return Self(unchecked: product) + @inlinable public func multiplied(by multiplicand: Self, adding addend: UInt) -> Self { + Self(storage: self.storage.multipliedFullWidth(by: multiplicand.storage, adding: addend)) } } diff --git a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Multiplication.swift b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Multiplication.swift index 9c08be90..e5a2a9e4 100644 --- a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Multiplication.swift +++ b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Multiplication.swift @@ -21,8 +21,8 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual( lhs * rhs, result, file: file, line: line) XCTAssertEqual({ var lhs = lhs; lhs *= rhs; return lhs }(), result, file: file, line: line) - XCTAssertEqual(lhs.multiplied(by: rhs), result, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs.multiply(by: rhs); return lhs }(), result, file: file, line: line) + XCTAssertEqual(lhs.multiplied(by: rhs, adding: UInt.zero), result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs.multiply(by: rhs, adding: UInt.zero); return lhs }(), result, file: file, line: line) } func NBKAssertMultiplicationByDigit( From 5947bf4b6801ccc49e9961cd3ef9b50adfec5b97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Mon, 17 Jul 2023 19:33:28 +0200 Subject: [PATCH 013/133] NBKFlexibleWidthKit: Cleanup. --- .../NBKFlexibleWidth+Logic.swift | 22 +++++--- ...FlexibleWidth+Multiplication+Storage.swift | 6 ++- .../NBKFlexibleWidth+Multiplication.swift | 12 ++--- .../NBKFlexibleWidth+Storage.swift | 10 ++++ .../NBKFlexibleWidth+Subtraction.swift | 1 - .../IntXL+Logic.swift | 51 +++++++++++++++---- .../Utilities/NBKAssert+Multiplication.swift | 4 +- 7 files changed, 81 insertions(+), 25 deletions(-) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift index 402bd5a8..e784fea1 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift @@ -16,21 +16,23 @@ import NBKCoreKit extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= - // MARK: Transformations + // MARK: Transformations x NOT //=------------------------------------------------------------------------= @inlinable public static prefix func ~(x: Self) -> Self { Self(words: x.storage.elements.map(~)) } + //=------------------------------------------------------------------------= + // MARK: Transformations x AND + //=------------------------------------------------------------------------= + @inlinable public static func &=(lhs: inout Self, rhs: Self) { defer { Swift.assert(lhs.storage.isNormal) } //=--------------------------------------= - if lhs.storage.elements.endIndex > rhs.storage.elements.endIndex { - lhs.storage.elements.removeSubrange(rhs.storage.elements.endIndex...) - } + lhs.storage.resize(maxCount: rhs.storage.elements.count) //=--------------------------------------= for index in lhs.storage.elements.indices.reversed() { let word = lhs.storage.elements[index] & rhs.storage.elements[index] @@ -47,12 +49,16 @@ extension NBKFlexibleWidth.Magnitude { var lhs = lhs; lhs &= rhs; return lhs } + //=------------------------------------------------------------------------= + // MARK: Transformations x OR + //=------------------------------------------------------------------------= + @inlinable public static func |=(lhs: inout Self, rhs: Self) { defer { Swift.assert(lhs.storage.isNormal) } //=--------------------------------------= - lhs.storage.elements.reserveCapacity(rhs.storage.elements.count) + lhs.storage.reserve(minCount: rhs.storage.elements.count) //=--------------------------------------= for index in rhs.storage.elements.indices { let source = rhs.storage.elements[index] @@ -69,12 +75,16 @@ extension NBKFlexibleWidth.Magnitude { var lhs = lhs; lhs |= rhs; return lhs } + //=------------------------------------------------------------------------= + // MARK: Transformations x XOR + //=------------------------------------------------------------------------= + @inlinable public static func ^=(lhs: inout Self, rhs: Self) { defer { lhs.storage.normalize() } //=--------------------------------------= - lhs.storage.elements.reserveCapacity(rhs.storage.elements.count) + lhs.storage.reserve(minCount: rhs.storage.elements.count) //=--------------------------------------= for index in rhs.storage.elements.indices { let source = rhs.storage.elements[index] diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Storage.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Storage.swift index 2a289497..a85f5767 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Storage.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Storage.swift @@ -19,7 +19,11 @@ extension NBKFlexibleWidth.Magnitude.Storage { // MARK: Transformations x Self //=------------------------------------------------------------------------= - @inlinable func multipliedFullWidth(by multiplicand: Self, adding addend: UInt) -> Self { + @inlinable func multipliedFullWidth(by multiplicand: Self) -> Self { + self.multipliedFullWidthByNaiveMethod(by: multiplicand, adding: UInt.zero) + } + + @inlinable func multipliedFullWidthByNaiveMethod(by multiplicand: Self, adding addend: UInt) -> Self { Self.uninitialized(count: self.elements.count + multiplicand.elements.count) { product in //=----------------------------------= // de/init: pointee is trivial diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift index 6f595962..3f7da9c1 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift @@ -20,22 +20,22 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @inlinable public static func *=(lhs: inout Self, rhs: Self) { - lhs.multiply(by: rhs, adding: UInt.zero) + lhs.multiply(by: rhs) } @inlinable public static func *(lhs: Self, rhs: Self) -> Self { - lhs.multiplied(by: rhs, adding: UInt.zero) + lhs.multiplied(by: rhs) } //=------------------------------------------------------------------------= // MARK: Transformations //=------------------------------------------------------------------------= - @inlinable public mutating func multiply(by multiplicand: Self, adding addend: UInt) { - self = self.multiplied(by: multiplicand, adding: addend) + @inlinable public mutating func multiply(by multiplicand: Self) { + self = self.multiplied(by: multiplicand) } - @inlinable public func multiplied(by multiplicand: Self, adding addend: UInt) -> Self { - Self(storage: self.storage.multipliedFullWidth(by: multiplicand.storage, adding: addend)) + @inlinable public func multiplied(by multiplicand: Self) -> Self { + Self(storage: self.storage.multipliedFullWidth(by: multiplicand.storage)) } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Storage.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Storage.swift index 087218c0..67448b39 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Storage.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Storage.swift @@ -45,6 +45,16 @@ extension NBKFlexibleWidth.Magnitude.Storage { } } + @inlinable mutating func resize(maxCount: Int) { + if self.elements.count > maxCount { + self.elements.removeSubrange(maxCount...) + } + } + + @inlinable mutating func resize(maxLastIndex: Int) { + self.resize(maxCount: maxLastIndex + 1) + } + @inlinable mutating func resize(minCount: Int) { self.reserve(minCount: minCount) appending: while self.elements.count < minCount { diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift index 9b38cf91..d9ad5d3e 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift @@ -41,7 +41,6 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= if other.isZero { return false } //=--------------------------------------= - // TODO: better resizing methods self.storage.resize(minCount: index + other.storage.elements.count) var index = index diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Logic.swift b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Logic.swift index d7ac302d..dcfabed6 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Logic.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Logic.swift @@ -28,6 +28,26 @@ final class UIntXLBenchmarksOnLogic: XCTestCase { // MARK: Tests //=------------------------------------------------------------------------= + func testNot() { + var abc = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(~abc) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testAndInout() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs &= rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + func testAnd() { var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) @@ -39,10 +59,21 @@ final class UIntXLBenchmarksOnLogic: XCTestCase { } } - func testOr() { + func testOrInout() { var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs |= rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testOr() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + for _ in 0 ..< 1_000_000 { NBK.blackHole(lhs | rhs) NBK.blackHoleInoutIdentity(&lhs) @@ -50,23 +81,25 @@ final class UIntXLBenchmarksOnLogic: XCTestCase { } } - func testXor() { + func testXorInout() { var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs ^ rhs) + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs ^= rhs) NBK.blackHoleInoutIdentity(&lhs) NBK.blackHoleInoutIdentity(&rhs) } } - func testNot() { - var abc = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - + func testXor() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + for _ in 0 ..< 1_000_000 { - NBK.blackHole(~abc) - NBK.blackHoleInoutIdentity(&abc) + NBK.blackHole(lhs ^ rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) } } } diff --git a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Multiplication.swift b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Multiplication.swift index e5a2a9e4..9c08be90 100644 --- a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Multiplication.swift +++ b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Multiplication.swift @@ -21,8 +21,8 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual( lhs * rhs, result, file: file, line: line) XCTAssertEqual({ var lhs = lhs; lhs *= rhs; return lhs }(), result, file: file, line: line) - XCTAssertEqual(lhs.multiplied(by: rhs, adding: UInt.zero), result, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs.multiply(by: rhs, adding: UInt.zero); return lhs }(), result, file: file, line: line) + XCTAssertEqual(lhs.multiplied(by: rhs), result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs.multiply(by: rhs); return lhs }(), result, file: file, line: line) } func NBKAssertMultiplicationByDigit( From 8d43c1a17a9721f61031ade5955a068223732a62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Tue, 18 Jul 2023 10:22:45 +0200 Subject: [PATCH 014/133] NBKFlexibleWidthKit: Logic. --- .../NBKFlexibleWidth+Addition.swift | 2 +- .../NBKFlexibleWidth+Division+Digit.swift | 4 +- .../NBKFlexibleWidth+Division.swift | 7 +- .../NBKFlexibleWidth+Logic+Storage.swift | 31 ++++++++ .../NBKFlexibleWidth+Logic.swift | 41 +++-------- .../NBKFlexibleWidth+Subtraction.swift | 2 +- .../Private/Pointers.swift | 32 +++++++++ .../NBKFlexibleWidthKitTests/IntXL+Bits.swift | 72 +++++++++---------- 8 files changed, 114 insertions(+), 77 deletions(-) create mode 100644 Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic+Storage.swift create mode 100644 Sources/NBKFlexibleWidthKit/Private/Pointers.swift diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift index 0ac0565e..9d239dce 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift @@ -38,7 +38,7 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= if other.isZero { return } //=--------------------------------------= - self.storage.resize(minCount: index + other.storage.elements.count) + self.storage.resize(minCount: other.storage.elements.count + index) var index = index var overflow = false diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.swift index a8bd7271..c46d9c5f 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.swift @@ -52,7 +52,9 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @_disfavoredOverload @inlinable mutating func formQuotientWithRemainderReportingOverflow(dividingBy other: UInt) -> PVO { - defer { Swift.assert(self.storage.isNormal) } + defer { + Swift.assert(self.storage.isNormal) + } //=--------------------------------------= if other.isZero { return NBK.bitCast(PVO(self.storage.elements.first ?? UInt.zero, true)) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift index 15a20ac3..1093c3a1 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift @@ -67,11 +67,8 @@ extension NBKFlexibleWidth.Magnitude { // divisor is one word //=--------------------------------------= if other.storage.elements.count == 1 { - // TODO: test truncation semantcs - let divisor = other.storage.elements.first! as UInt - let qro = self.quotientAndRemainderReportingOverflow(dividingBy: divisor) - let remainder = qro.overflow ? self : Self(digit: qro.partialValue.remainder) - return PVO(QR(qro.partialValue.quotient, remainder), qro.overflow) + let qro = self.quotientAndRemainder(dividingBy: other.storage.elements.first!) + return PVO(QR(qro.quotient, Self(digit: qro.remainder)), false) } //=--------------------------------------= // divisor is greater than or equal diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic+Storage.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic+Storage.swift new file mode 100644 index 00000000..70ab3170 --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic+Storage.swift @@ -0,0 +1,31 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x Logic x Unsigned x Storage +//*============================================================================* + +extension NBKFlexibleWidth.Magnitude.Storage { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable mutating func formInIntersection(of other: Self, each element: (UInt, UInt) -> UInt) { + self .elements.withUnsafeMutableBufferPointer { lhs in + other.elements.withUnsafeBufferPointer { rhs in + let endIndex = Swift.min(lhs.endIndex, rhs.endIndex) + let lhsIntersection = NBK.UnsafeMutableWords(rebasing: lhs.prefix(upTo: endIndex)) + let rhsIntersection = /*---*/NBK.UnsafeWords(rebasing: rhs.prefix(upTo: endIndex)) + NBK.merge(into: lhsIntersection, from: NBK.UnsafeWords(lhsIntersection), rhsIntersection, each: element) + }} + } +} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift index e784fea1..e16e4bb2 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift @@ -33,16 +33,8 @@ extension NBKFlexibleWidth.Magnitude { } //=--------------------------------------= lhs.storage.resize(maxCount: rhs.storage.elements.count) - //=--------------------------------------= - for index in lhs.storage.elements.indices.reversed() { - let word = lhs.storage.elements[index] & rhs.storage.elements[index] - - if index == lhs.storage.elements.endIndex, word.isZero, index != lhs.storage.elements.startIndex { - lhs.storage.elements.removeLast() - } else { - lhs.storage.elements[index] = word - } - } + lhs.storage.formInIntersection(of: rhs.storage, each: &) + lhs.storage.normalize() } @inlinable public static func &(lhs: Self, rhs: Self) -> Self { @@ -58,17 +50,8 @@ extension NBKFlexibleWidth.Magnitude { Swift.assert(lhs.storage.isNormal) } //=--------------------------------------= - lhs.storage.reserve(minCount: rhs.storage.elements.count) - //=--------------------------------------= - for index in rhs.storage.elements.indices { - let source = rhs.storage.elements[index] - - if index < lhs.storage.elements.endIndex { - lhs.storage.elements[index] |= source - } else { - lhs.storage.elements.append(source as UInt) - } - } + lhs.storage.resize(minCount: rhs.storage.elements.count) + lhs.storage.formInIntersection(of: rhs.storage, each: |) } @inlinable public static func |(lhs: Self, rhs: Self) -> Self { @@ -81,20 +64,12 @@ extension NBKFlexibleWidth.Magnitude { @inlinable public static func ^=(lhs: inout Self, rhs: Self) { defer { - lhs.storage.normalize() + Swift.assert(lhs.storage.isNormal) } //=--------------------------------------= - lhs.storage.reserve(minCount: rhs.storage.elements.count) - //=--------------------------------------= - for index in rhs.storage.elements.indices { - let source = rhs.storage.elements[index] - - if index < lhs.storage.elements.endIndex { - lhs.storage.elements[index] ^= source - } else { - lhs.storage.elements.append(source as UInt) - } - } + lhs.storage.resize(minCount: rhs.storage.elements.count) + lhs.storage.formInIntersection(of: rhs.storage, each: ^) + lhs.storage.normalize() } @inlinable public static func ^(lhs: Self, rhs: Self) -> Self { diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift index d9ad5d3e..b4886bbe 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift @@ -41,7 +41,7 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= if other.isZero { return false } //=--------------------------------------= - self.storage.resize(minCount: index + other.storage.elements.count) + self.storage.resize(minCount: other.storage.elements.count + index) var index = index var overflow = false diff --git a/Sources/NBKFlexibleWidthKit/Private/Pointers.swift b/Sources/NBKFlexibleWidthKit/Private/Pointers.swift new file mode 100644 index 00000000..6cabcd95 --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/Private/Pointers.swift @@ -0,0 +1,32 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Pointers +//*============================================================================* + +extension NBK { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable static func merge(into result: UnsafeMutableBufferPointer, + from x0: UnsafeBufferPointer, _ x1: UnsafeBufferPointer, each element: (T, T) -> T) { + //=--------------------------------------= + precondition(result.count == x0.count, NBK.callsiteOutOfBoundsInfo()) + precondition(result.count == x1.count, NBK.callsiteOutOfBoundsInfo()) + //=--------------------------------------= + for index in result.indices { + result[index] = element(x0[index], x1[index]) + } + } +} diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Bits.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Bits.swift index 072bd2d2..2116af74 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Bits.swift +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Bits.swift @@ -35,63 +35,63 @@ final class UIntXLTestsOnBits: XCTestCase { } func testBitWidth() { - XCTAssertEqual(T(words: [ 0, 0, 0, 0] as [UInt]).bitWidth, UInt.bitWidth * 0) - XCTAssertEqual(T(words: [~0, ~0, ~0, ~0] as [UInt]).bitWidth, UInt.bitWidth * 4) + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as [UInt]).bitWidth, UInt.bitWidth * 0) + XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as [UInt]).bitWidth, UInt.bitWidth * 4) } func testNonzeroBitCount() { - XCTAssertEqual(T(words: [ 0, 0, 0, 0] as [UInt]).nonzeroBitCount, 0) - XCTAssertEqual(T(words: [ 1, 1, 1, 1] as [UInt]).nonzeroBitCount, 4) + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as [UInt]).nonzeroBitCount, 0) + XCTAssertEqual(T(words:[ 1, 1, 1, 1] as [UInt]).nonzeroBitCount, 4) } func testLeadingZeroBitCount() { - XCTAssertEqual(T(words: [ 0, 0, 0, 0] as [UInt]).leadingZeroBitCount, UInt.bitWidth * 0) - XCTAssertEqual(T(words: [~0, ~0, ~0, ~0] as [UInt]).leadingZeroBitCount, UInt.bitWidth * 0) + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as [UInt]).leadingZeroBitCount, UInt.bitWidth * 0) + XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as [UInt]).leadingZeroBitCount, UInt.bitWidth * 0) - XCTAssertEqual(T(words: [ 2, 0, 0, 0] as [UInt]).leadingZeroBitCount, UInt.bitWidth * 1 - 2) - XCTAssertEqual(T(words: [ 0, 2, 0, 0] as [UInt]).leadingZeroBitCount, UInt.bitWidth * 1 - 2) - XCTAssertEqual(T(words: [ 0, 0, 2, 0] as [UInt]).leadingZeroBitCount, UInt.bitWidth * 1 - 2) - XCTAssertEqual(T(words: [ 0, 0, 0, 2] as [UInt]).leadingZeroBitCount, UInt.bitWidth * 1 - 2) + XCTAssertEqual(T(words:[ 2, 0, 0, 0] as [UInt]).leadingZeroBitCount, UInt.bitWidth * 1 - 2) + XCTAssertEqual(T(words:[ 0, 2, 0, 0] as [UInt]).leadingZeroBitCount, UInt.bitWidth * 1 - 2) + XCTAssertEqual(T(words:[ 0, 0, 2, 0] as [UInt]).leadingZeroBitCount, UInt.bitWidth * 1 - 2) + XCTAssertEqual(T(words:[ 0, 0, 0, 2] as [UInt]).leadingZeroBitCount, UInt.bitWidth * 1 - 2) } func testTrailingZeroBitCount() { - XCTAssertEqual(T(words: [ 0, 0, 0, 0] as [UInt]).trailingZeroBitCount, UInt.bitWidth * 0) - XCTAssertEqual(T(words: [~0, ~0, ~0, ~0] as [UInt]).trailingZeroBitCount, UInt.bitWidth * 0) + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as [UInt]).trailingZeroBitCount, UInt.bitWidth * 0) + XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as [UInt]).trailingZeroBitCount, UInt.bitWidth * 0) - XCTAssertEqual(T(words: [ 2, 0, 0, 0] as [UInt]).trailingZeroBitCount, UInt.bitWidth * 0 + 1) - XCTAssertEqual(T(words: [ 0, 2, 0, 0] as [UInt]).trailingZeroBitCount, UInt.bitWidth * 1 + 1) - XCTAssertEqual(T(words: [ 0, 0, 2, 0] as [UInt]).trailingZeroBitCount, UInt.bitWidth * 2 + 1) - XCTAssertEqual(T(words: [ 0, 0, 0, 2] as [UInt]).trailingZeroBitCount, UInt.bitWidth * 3 + 1) + XCTAssertEqual(T(words:[ 2, 0, 0, 0] as [UInt]).trailingZeroBitCount, UInt.bitWidth * 0 + 1) + XCTAssertEqual(T(words:[ 0, 2, 0, 0] as [UInt]).trailingZeroBitCount, UInt.bitWidth * 1 + 1) + XCTAssertEqual(T(words:[ 0, 0, 2, 0] as [UInt]).trailingZeroBitCount, UInt.bitWidth * 2 + 1) + XCTAssertEqual(T(words:[ 0, 0, 0, 2] as [UInt]).trailingZeroBitCount, UInt.bitWidth * 3 + 1) } func testMostSignificantBit() { - XCTAssertEqual(T(words: [ 0, 0, 0, 0] as [UInt]).mostSignificantBit, false) - XCTAssertEqual(T(words: [~0, ~0, ~0, ~0] as [UInt]).mostSignificantBit, true ) + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as [UInt]).mostSignificantBit, false) + XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as [UInt]).mostSignificantBit, true ) - XCTAssertEqual(T(words: [~0, 0, 0, 0] as [UInt]).mostSignificantBit, true ) - XCTAssertEqual(T(words: [ 0, ~0, 0, 0] as [UInt]).mostSignificantBit, true ) - XCTAssertEqual(T(words: [ 0, 0, ~0, 0] as [UInt]).mostSignificantBit, true ) - XCTAssertEqual(T(words: [ 0, 0, 0, ~0] as [UInt]).mostSignificantBit, true ) + XCTAssertEqual(T(words:[~0, 0, 0, 0] as [UInt]).mostSignificantBit, true ) + XCTAssertEqual(T(words:[ 0, ~0, 0, 0] as [UInt]).mostSignificantBit, true ) + XCTAssertEqual(T(words:[ 0, 0, ~0, 0] as [UInt]).mostSignificantBit, true ) + XCTAssertEqual(T(words:[ 0, 0, 0, ~0] as [UInt]).mostSignificantBit, true ) - XCTAssertEqual(T(words: [~0, 1, 0, 0] as [UInt]).mostSignificantBit, false) - XCTAssertEqual(T(words: [ 0, ~0, 1, 0] as [UInt]).mostSignificantBit, false) - XCTAssertEqual(T(words: [ 0, 0, ~0, 1] as [UInt]).mostSignificantBit, false) - XCTAssertEqual(T(words: [ 1, 0, 0, ~0] as [UInt]).mostSignificantBit, true ) + XCTAssertEqual(T(words:[~0, 1, 0, 0] as [UInt]).mostSignificantBit, false) + XCTAssertEqual(T(words:[ 0, ~0, 1, 0] as [UInt]).mostSignificantBit, false) + XCTAssertEqual(T(words:[ 0, 0, ~0, 1] as [UInt]).mostSignificantBit, false) + XCTAssertEqual(T(words:[ 1, 0, 0, ~0] as [UInt]).mostSignificantBit, true ) } func testLeastSignificantBit() { - XCTAssertEqual(T(words: [ 0, 0, 0, 0] as [UInt]).leastSignificantBit, false) - XCTAssertEqual(T(words: [~0, ~0, ~0, ~0] as [UInt]).leastSignificantBit, true ) + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as [UInt]).leastSignificantBit, false) + XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as [UInt]).leastSignificantBit, true ) - XCTAssertEqual(T(words: [~0, 0, 0, 0] as [UInt]).leastSignificantBit, true ) - XCTAssertEqual(T(words: [ 0, ~0, 0, 0] as [UInt]).leastSignificantBit, false) - XCTAssertEqual(T(words: [ 0, 0, ~0, 0] as [UInt]).leastSignificantBit, false) - XCTAssertEqual(T(words: [ 0, 0, 0, ~0] as [UInt]).leastSignificantBit, false) + XCTAssertEqual(T(words:[~0, 0, 0, 0] as [UInt]).leastSignificantBit, true ) + XCTAssertEqual(T(words:[ 0, ~0, 0, 0] as [UInt]).leastSignificantBit, false) + XCTAssertEqual(T(words:[ 0, 0, ~0, 0] as [UInt]).leastSignificantBit, false) + XCTAssertEqual(T(words:[ 0, 0, 0, ~0] as [UInt]).leastSignificantBit, false) - XCTAssertEqual(T(words: [~0, 1, 0, 0] as [UInt]).leastSignificantBit, true ) - XCTAssertEqual(T(words: [ 0, ~0, 1, 0] as [UInt]).leastSignificantBit, false) - XCTAssertEqual(T(words: [ 0, 0, ~0, 1] as [UInt]).leastSignificantBit, false) - XCTAssertEqual(T(words: [ 1, 0, 0, ~0] as [UInt]).leastSignificantBit, true ) + XCTAssertEqual(T(words:[~0, 1, 0, 0] as [UInt]).leastSignificantBit, true ) + XCTAssertEqual(T(words:[ 0, ~0, 1, 0] as [UInt]).leastSignificantBit, false) + XCTAssertEqual(T(words:[ 0, 0, ~0, 1] as [UInt]).leastSignificantBit, false) + XCTAssertEqual(T(words:[ 1, 0, 0, ~0] as [UInt]).leastSignificantBit, true ) } } From c19d2201ce731da74878a1c18aeed896db8a1f1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Tue, 18 Jul 2023 18:57:50 +0200 Subject: [PATCH 015/133] NBKFlexibleWidthKit: Shifts. --- .../NBKFlexibleWidth+Shifts+Storage.swift | 97 +++++++++++++++++++ .../NBKFlexibleWidth+Shifts.swift | 89 ++++++++--------- 2 files changed, 135 insertions(+), 51 deletions(-) create mode 100644 Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts+Storage.swift diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts+Storage.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts+Storage.swift new file mode 100644 index 00000000..048173fb --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts+Storage.swift @@ -0,0 +1,97 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x Shifts x Unsigned x Storage +//*============================================================================* +//=----------------------------------------------------------------------------= +// MARK: + Left +//=----------------------------------------------------------------------------= + +extension NBKFlexibleWidth.Magnitude.Storage { + + //=------------------------------------------------------------------------= + // MARK: Transformations x Int + //=------------------------------------------------------------------------= + + @inlinable public mutating func bitshiftLeft(words: Int, atLeastOneBit bits: Int) { + precondition(words >= 0 && words < self.elements.count, NBK.callsiteOutOfBoundsInfo()) + precondition(bits >= 1 && bits < UInt.bitWidth, NBK.callsiteOutOfBoundsInfo()) + //=--------------------------------------= + let push = UInt(bitPattern: bits) + let pull = UInt(bitPattern: UInt.bitWidth - bits) + //=--------------------------------------= + let offset: Int = ~(words) + var destination = self.elements.endIndex as Int + var word = self.elements[destination &+ offset] + //=--------------------------------------= + while destination > self.elements.startIndex { + self.elements.formIndex(before: &destination) + let pushed = word &<< push + word = destination > words ? self.elements[destination &+ offset] : UInt() + let pulled = word &>> pull + self.elements[destination] = pushed | pulled + } + } + + @inlinable public mutating func bitshiftLeft(atLeastOneWord words: Int) { + precondition(words >= 1 && words < self.elements.count, NBK.callsiteOutOfBoundsInfo()) + //=--------------------------------------= + for destination in self.elements.indices.reversed() { + self.elements[destination] = destination >= words ? self.elements[destination - words] : UInt() + } + } +} + +//=----------------------------------------------------------------------------= +// MARK: + Right +//=----------------------------------------------------------------------------= + +extension NBKFlexibleWidth.Magnitude.Storage { + + //=------------------------------------------------------------------------= + // MARK: Transformations x Int + //=------------------------------------------------------------------------= + + @inlinable public mutating func bitshiftRight(words: Int, atLeastOneBit bits: Int) { + precondition(words >= 0 && words < self.elements.count, NBK.callsiteOutOfBoundsInfo()) + precondition(bits >= 1 && bits < UInt.bitWidth, NBK.callsiteOutOfBoundsInfo()) + //=--------------------------------------= + let push = UInt(bitPattern: bits) + let pull = UInt(bitPattern: UInt.bitWidth - bits) + let sign = UInt(repeating: false) + //=--------------------------------------= + var destination = self.elements.startIndex + let edge = self.elements.distance(from: words, to: self.elements.endIndex) + var word = self.elements[words] as UInt + //=--------------------------------------= + while destination < edge { + let after = self.elements.index(after: destination) + let pushed = word &>> push + word = after < edge ? self.elements[after &+ words] : sign + let pulled = word &<< pull + self.elements[destination] = pushed | pulled + destination = after + } + } + + @inlinable public mutating func bitshiftRight(atLeastOneWord words: Int) { + precondition(words >= 1 && words < self.elements.count, NBK.callsiteOutOfBoundsInfo()) + //=--------------------------------------= + let sign = UInt(repeating: false) + //=--------------------------------------= + let edge = self.elements.distance(from: words, to: self.elements.endIndex) + //=--------------------------------------= + for destination in self.elements.indices { + self.elements[destination] = destination < edge ? self.elements[destination + words] : sign + } + } +} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift index 892d87d4..7d751ee3 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift @@ -56,33 +56,21 @@ extension NBKFlexibleWidth.Magnitude { } @inlinable public mutating func bitshiftLeft(words: Int, bits: Int) { - precondition(words >= 0, NBK.callsiteOutOfBoundsInfo()) - precondition(bits >= 0 && bits < UInt.bitWidth, NBK.callsiteOutOfBoundsInfo()) + defer { + Swift.assert(self.storage.isNormal) + } //=--------------------------------------= if bits.isZero { return self.bitshiftLeft(words: words) } //=--------------------------------------= - if self.isZero { return } - //=--------------------------------------= - let push = UInt(bitPattern: bits) - let pull = UInt(bitPattern: UInt.bitWidth - bits) - //=--------------------------------------= - self.storage.resize(minCount: self.storage.elements.endIndex + words + 1) - //=--------------------------------------= - let offset: Int = ~(words) - var destination = self.storage.elements.endIndex as Int - var word = self.storage.elements[destination &+ offset] - //=--------------------------------------= - while destination > self.storage.elements.startIndex { - self.storage.elements.formIndex(before: &destination) - let pushed = word &<< push - word = destination > words ? self.storage.elements[destination &+ offset] : UInt() - let pulled = word &>> pull - self.storage.elements[destination ] = pushed | pulled + if self.isZero { + return } //=--------------------------------------= - self.storage.normalize() + let rollover = Int(bit: self.leadingZeroBitCount < bits) + self.storage.resize(minCount: self.storage.elements.count + words + rollover) + self.storage.bitshiftLeft(words: words, atLeastOneBit: bits) } @inlinable public func bitshiftedLeft(words: Int, bits: Int) -> Self { @@ -90,14 +78,20 @@ extension NBKFlexibleWidth.Magnitude { } @inlinable public mutating func bitshiftLeft(words: Int) { - precondition(words >= 0, NBK.callsiteOutOfBoundsInfo()) + defer { + Swift.assert(self.storage.isNormal) + } //=--------------------------------------= - if words.isZero { return } + if words.isZero { + return + } //=--------------------------------------= - if self .isZero { return } + if self.isZero { + return + } //=--------------------------------------= - let prefix = repeatElement(UInt.zero, count: words) - self.storage.elements.insert(contentsOf: prefix, at: Int()) + self.storage.resize(minCount: self.storage.elements.count + words) + self.storage.bitshiftLeft(atLeastOneWord: words) } @inlinable public func bitshiftedLeft(words: Int) -> Self { @@ -149,36 +143,21 @@ extension NBKFlexibleWidth.Magnitude { } @inlinable public mutating func bitshiftRight(words: Int, bits: Int) { - precondition(words >= 0, NBK.callsiteOutOfBoundsInfo()) - precondition(bits >= 0 && bits < UInt.bitWidth, NBK.callsiteOutOfBoundsInfo()) - //=--------------------------------------= - if words >= self.storage.elements.count { - return self.assignZeroValue() + defer { + Swift.assert(self.storage.isNormal) } //=--------------------------------------= if bits.isZero { return self.bitshiftRight(words: words) } //=--------------------------------------= - let push = UInt(bitPattern: bits) - let pull = UInt(bitPattern: UInt.bitWidth - bits) - let sign = UInt(repeating: self.isLessThanZero) - //=--------------------------------------= - var destination = self.storage.elements.startIndex - let edge = self.storage.elements.distance(from: words, to: self.storage.elements.endIndex) - var word = self.storage.elements[words] as UInt - //=--------------------------------------= - while destination < edge { - let after = self.storage.elements.index(after: destination) - let pushed = word &>> push - word = after < edge ? self.storage.elements[after &+ words] : sign - let pulled = word &<< pull - self.storage.elements[destination ] = pushed | pulled - destination = after + if self.storage.elements.count <= words { + return self.assignZeroValue() } //=--------------------------------------= - self.storage.elements.removeLast(words) - self.storage.normalize() + let rollover = Int(bit: bits + self.leadingZeroBitCount - UInt.bitWidth >= 0) + self.storage.bitshiftRight(words: words, atLeastOneBit: bits) + self.storage.resize(maxCount: self.storage.elements.count - words - rollover) } @inlinable public func bitshiftedRight(words: Int, bits: Int) -> Self { @@ -186,12 +165,20 @@ extension NBKFlexibleWidth.Magnitude { } @inlinable public mutating func bitshiftRight(words: Int) { - precondition(words >= 0, NBK.callsiteOutOfBoundsInfo()) + defer { + Swift.assert(self.storage.isNormal) + } //=--------------------------------------= - if words.isZero { return } + if words.isZero { + return + } + //=--------------------------------------= + if self.storage.elements.count <= words { + return self.assignZeroValue() + } //=--------------------------------------= - self.storage.elements.removeFirst(Swift.min(words, self.storage.elements.count)) - self.storage.normalize() + self.storage.bitshiftRight(atLeastOneWord: words) + self.storage.resize(maxCount: self.storage.elements.count - words) } @inlinable public func bitshiftedRight(words: Int) -> Self { From 5a1b3103f4eee23f7d4c5934d45b5f07389508a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Thu, 20 Jul 2023 09:05:20 +0200 Subject: [PATCH 016/133] Cleanup. --- .../NBKFlexibleWidth+Division.swift | 4 +- .../NBKFlexibleWidth+Shifts+Storage.swift | 98 ------------------- .../NBKFlexibleWidth+Shifts.swift | 18 ++-- .../IntXL+Shifts.swift | 13 +++ 4 files changed, 27 insertions(+), 106 deletions(-) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift index 1093c3a1..db16805f 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift @@ -84,8 +84,8 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= let shift = other.storage.elements.last!.leadingZeroBitCount as Int var remainderIndex = self.storage.elements.endIndex - var remainder = self.bitshiftedLeft(words: 0, bits: shift) as Self - let divisor = other.bitshiftedLeft(words: 0, bits: shift) as Self + var remainder = self.bitshiftedLeft(words: Int.zero, bits: shift) as Self + let divisor = other.bitshiftedLeft(words: Int.zero, bits: shift) as Self let divisorLast0 = divisor.storage.elements[divisor.storage.elements.endIndex - 1] as UInt assert(divisorLast0.mostSignificantBit) //=--------------------------------------= diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts+Storage.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts+Storage.swift index aa7dadef..d010e083 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts+Storage.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts+Storage.swift @@ -16,104 +16,6 @@ import NBKCoreKit // MARK: + Left //=----------------------------------------------------------------------------= -//extension NBKFlexibleWidth.Magnitude.Storage { -// -// //=------------------------------------------------------------------------= -// // MARK: Transformations x Int -// //=------------------------------------------------------------------------= -// -// @inlinable public mutating func bitshiftLeft(words: Int, atLeastOneBit bits: Int) { -// precondition(words >= 0 && words < self.elements.count, NBK.callsiteOutOfBoundsInfo()) -// precondition(bits >= 1 && bits < UInt.bitWidth, NBK.callsiteOutOfBoundsInfo()) -// //=--------------------------------------= -// let push = UInt(bitPattern: bits) -// let pull = UInt(bitPattern: UInt.bitWidth - bits) -// //=--------------------------------------= -// let offset: Int = ~(words) -// var destination = self.elements.endIndex as Int -// var word = self.elements[destination &+ offset] -// //=--------------------------------------= -// while destination > self.elements.startIndex { -// self.elements.formIndex(before: &destination) -// let pushed = word &<< push -// word = destination > words ? self.elements[destination &+ offset] : UInt() -// let pulled = word &>> pull -// self.elements[destination] = pushed | pulled -// } -// } -// -// @inlinable public mutating func bitshiftLeft(atLeastOneWord words: Int) { -// precondition(words >= 1 && words < self.elements.count, NBK.callsiteOutOfBoundsInfo()) -// //=--------------------------------------= -// for destination in self.elements.indices.reversed() { -// self.elements[destination] = destination >= words ? self.elements[destination - words] : UInt() -// } -// } -//} -// -////=----------------------------------------------------------------------------= -//// MARK: + Right -////=----------------------------------------------------------------------------= -// -//extension NBKFlexibleWidth.Magnitude.Storage { -// -// //=------------------------------------------------------------------------= -// // MARK: Transformations x Int -// //=------------------------------------------------------------------------= -// -// @inlinable public mutating func bitshiftRight(words: Int, atLeastOneBit bits: Int) { -// precondition(words >= 0 && words < self.elements.count, NBK.callsiteOutOfBoundsInfo()) -// precondition(bits >= 1 && bits < UInt.bitWidth, NBK.callsiteOutOfBoundsInfo()) -// //=--------------------------------------= -// let push = UInt(bitPattern: bits) -// let pull = UInt(bitPattern: UInt.bitWidth - bits) -// let sign = UInt(repeating: false) -// //=--------------------------------------= -// var destination = self.elements.startIndex -// let edge = self.elements.distance(from: words, to: self.elements.endIndex) -// var word = self.elements[words] as UInt -// //=--------------------------------------= -// while destination < edge { -// let after = self.elements.index(after: destination) -// let pushed = word &>> push -// word = after < edge ? self.elements[after &+ words] : sign -// let pulled = word &<< pull -// self.elements[destination] = pushed | pulled -// destination = after -// } -// } -// -// @inlinable public mutating func bitshiftRight(atLeastOneWord words: Int) { -// precondition(words >= 1 && words < self.elements.count, NBK.callsiteOutOfBoundsInfo()) -// //=--------------------------------------= -// let sign = UInt(repeating: false) -// //=--------------------------------------= -// let edge = self.elements.distance(from: words, to: self.elements.endIndex) -// //=--------------------------------------= -// for destination in self.elements.indices { -// self.elements[destination] = destination < edge ? self.elements[destination + words] : sign -// } -// } -//} - -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Flexible Width x Shifts x Unsigned x Storage -//*============================================================================* -//=----------------------------------------------------------------------------= -// MARK: + Left -//=----------------------------------------------------------------------------= - extension NBKFlexibleWidth.Magnitude.Storage { //=------------------------------------------------------------------------= diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift index 7d751ee3..f36ac67d 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift @@ -35,9 +35,12 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @inlinable public mutating func bitshiftLeftSmart(by distance: Int) { - switch distance >= 0 { - case true: self.bitshiftLeft (by: distance) - case false: self.bitshiftRight(by: distance.negated()) } + if distance >= 0 { + self.bitshiftLeft (by: distance) + } else { + // self >> Int.max is equivalent to self << Int.min + self.bitshiftRight(by: Int(clamping: distance.magnitude)) + } } @inlinable public func bitshiftedLeftSmart(by distance: Int) -> Self { @@ -122,9 +125,12 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @inlinable public mutating func bitshiftRightSmart(by distance: Int) { - switch distance >= 0 { - case true: self.bitshiftRight(by: distance) - case false: self.bitshiftLeft (by: distance.negated()) } + if distance >= 0 { + self.bitshiftRight(by: distance) + } else { + // self << Int.max is equivalent to self >> Int.min + self.bitshiftLeft (by: Int(clamping: distance.magnitude)) + } } @inlinable public func bitshiftedRightSmart(by distance: Int) -> Self { diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Shifts.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Shifts.swift index e11f90b5..6d530f17 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Shifts.swift +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Shifts.swift @@ -111,6 +111,19 @@ final class UIntXLTestsOnShifts: XCTestCase { XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) << 64, T(x64:[0, 1, 2, 3, 4] as X)) XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) >> -64, T(x64:[0, 1, 2, 3, 4] as X)) } + + func testBitshiftingRightDoesNotTrap() { + XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) >> Int.max, T.zero) + XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) << Int.min, T.zero) + } + + func testBitshiftingZeroDoesNotTrap() { + XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) << Int.min, T.zero) + XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) << Int.max, T.zero) + + XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) >> Int.min, T.zero) + XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) >> Int.max, T.zero) + } } #endif From abd2f0eb4786f5535834e2e767505f94185f76a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Mon, 24 Jul 2023 13:53:25 +0200 Subject: [PATCH 017/133] NBKFlexibleWidthKit: Division. --- .../NBKFlexibleWidth+Division.swift | 57 +++++++----- .../NBKFlexibleWidth+Shifts+Storage.swift | 92 ++++++++++++++++++- ...NBKFlexibleWidth+Subtraction+Storage.swift | 30 ++++++ .../Utilities/NBKAssert+Division.swift | 4 + 4 files changed, 156 insertions(+), 27 deletions(-) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift index 7d5a6c69..fcad1575 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift @@ -82,38 +82,46 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= // shift to clamp approximation //=--------------------------------------= - let shift = other.storage.elements.last!.leadingZeroBitCount as Int - var remainderIndex = self.storage.elements.endIndex - var remainder = self.bitshiftedLeft(words: Int.zero, bits: shift) as Self - let divisor = other.bitshiftedLeft(words: Int.zero, bits: shift) as Self - let divisorLast0 = divisor.storage.elements[divisor.storage.elements.endIndex - 1] as UInt - assert(divisorLast0.mostSignificantBit) + var divisor = other.storage + let shift = divisor.elements.last!.leadingZeroBitCount as Int + divisor.bitshiftLeft(words: Int.zero, bits: shift) + let divisorLast0 = divisor.elements[divisor.elements.endIndex - 1] as UInt + assert(divisorLast0.mostSignificantBit, "divisor must be normalized") + + var remainder = self.storage + var remainderIndex = remainder.elements.endIndex + remainder.elements.append(0) + remainder.bitshiftLeft(words: Int.zero, bits: shift) //=--------------------------------------= // division: approximate quotient digits //=--------------------------------------= - var quotientIndex = remainderIndex - divisor.storage.elements.endIndex as Int + var quotientIndex = remainderIndex - divisor.elements.endIndex as Int var quotient = Storage.uninitialized(count: quotientIndex + 1) { quotient in - // TODO: denormalized or fixed-width operations - - repeat { + loop: repeat { + let remainderLast0 = remainder.elements[remainderIndex] + remainder.elements.formIndex(before: &remainderIndex) + let remainderLast1 = remainder.elements[remainderIndex] //=------------------------------= - let remainderLast0 = remainderIndex < remainder.storage.elements.endIndex ? remainder.storage.elements[remainderIndex] : UInt.zero - remainder.storage.elements.formIndex(before: &remainderIndex) - let remainderLast1 = remainderIndex < remainder.storage.elements.endIndex ? remainder.storage.elements[remainderIndex] : UInt.zero + var digit: UInt + if divisorLast0 == remainderLast0 { + digit = UInt.max + } else { + digit = divisorLast0.dividingFullWidth(HL(remainderLast0, remainderLast1)).quotient + } //=------------------------------= - var digit = remainderLast0 == divisorLast0 ? UInt.max : divisorLast0.dividingFullWidth(HL(remainderLast0, remainderLast1)).quotient if !digit.isZero { - var approximation: Self = divisor * digit - - while remainder.compared(to: approximation, at: quotientIndex) == -1 as Int { - _ = digit.subtractReportingOverflow(1 as UInt) - _ = approximation.subtractReportingOverflow(divisor, at: quotientIndex) + var overflow = remainder.subtract(divisor, times: digit, plus: UInt.zero, at: quotientIndex) + while overflow { + let _ = digit.subtractReportingOverflow(1 as UInt) + + var carry = false + var index = quotientIndex + remainder.add(divisor, at: &index, carrying: &carry) + overflow = !carry } - - let _ = remainder.subtractReportingOverflow(approximation, at: quotientIndex) } - //=----------------------------------= - quotient[quotientIndex] = digit + //=------------------------------= + quotient[quotientIndex] = digit quotient.formIndex(before: "ientIndex) } while quotientIndex >= quotient.startIndex } @@ -122,6 +130,7 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= quotient .normalize() remainder.bitshiftRight(words: Int.zero, bits: shift) - return PVO(QR(Self(unchecked: quotient), remainder), false) + remainder.normalize() + return PVO(QR(Self(unchecked: quotient), Self(unchecked: remainder)), false) } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts+Storage.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts+Storage.swift index d010e083..f3177d2c 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts+Storage.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts+Storage.swift @@ -17,10 +17,53 @@ import NBKCoreKit //=----------------------------------------------------------------------------= extension NBKFlexibleWidth.Magnitude.Storage { - + //=------------------------------------------------------------------------= // MARK: Transformations x Int //=------------------------------------------------------------------------= + + /// Performs a left shift. + /// + /// - Parameters: + /// - distance: `0 <= distance < self.bitWidth` + /// + @inlinable public mutating func bitshiftLeft(by distance: Int) { + precondition(distance >= 0, NBK.callsiteOutOfBoundsInfo()) + let major = NBK .quotientDividingByBitWidthAssumingIsAtLeastZero(distance) + let minor = NBK.remainderDividingByBitWidthAssumingIsAtLeastZero(distance) + return self.bitshiftLeft(words: major, bits: minor) + } + + /// Performs a left shift. + /// + /// - Parameters: + /// - words: `0 <= words < self.endIndex` + /// - bits: `0 <= bits  < UInt.bitWidth` + /// + @inlinable public mutating func bitshiftLeft(words: Int, bits: Int) { + //=--------------------------------------= + if bits.isZero { + return self.bitshiftLeft(words: words) + } + //=--------------------------------------= + self.bitshiftLeft(words: words, atLeastOneBit: bits) + } + + /// Performs a left shift. + /// + /// - Parameters: + /// - words: `0 <= words < self.endIndex` + /// + @inlinable public mutating func bitshiftLeft(words: Int) { + //=--------------------------------------= + if words.isZero { return } + //=--------------------------------------= + self.bitshiftLeft(atLeastOneWord: words) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Int x Private + //=------------------------------------------------------------------------= @inlinable mutating func bitshiftLeft(words: Int, atLeastOneBit bits: Int) { self.elements.withUnsafeMutableBufferPointer { @@ -40,9 +83,52 @@ extension NBKFlexibleWidth.Magnitude.Storage { //=----------------------------------------------------------------------------= extension NBKFlexibleWidth.Magnitude.Storage { - + //=------------------------------------------------------------------------= - // MARK: Transformations x Int + // MARK: Transformations x Right + //=------------------------------------------------------------------------= + + /// Performs an un/signed right shift. + /// + /// - Parameters: + /// - distance: `0 <= distance < self.bitWidth` + /// + @inlinable public mutating func bitshiftRight(by distance: Int) { + precondition(distance >= 0, NBK.callsiteOutOfBoundsInfo()) + let major = NBK .quotientDividingByBitWidthAssumingIsAtLeastZero(distance) + let minor = NBK.remainderDividingByBitWidthAssumingIsAtLeastZero(distance) + return self.bitshiftRight(words: major, bits: minor) + } + + /// Performs an un/signed right shift. + /// + /// - Parameters: + /// - words: `0 <= words < self.endIndex` + /// - bits: `0 <= bits  < UInt.bitWidth` + /// + @inlinable public mutating func bitshiftRight(words: Int, bits: Int) { + //=--------------------------------------= + if bits.isZero { + return self.bitshiftRight(words: words) + } + //=--------------------------------------= + self.bitshiftRight(words: words, atLeastOneBit: bits) + } + + /// Performs an un/signed right shift. + /// + /// - Parameters: + /// - words: `0 <= words < self.endIndex` + /// + @inlinable public mutating func bitshiftRight(words: Int) { + //=--------------------------------------= + if words.isZero { return } + //=--------------------------------------= + self.bitshiftRight(atLeastOneWord: words) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Int x Private //=------------------------------------------------------------------------= @inlinable mutating func bitshiftRight(words: Int, atLeastOneBit bits: Int) { diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Storage.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Storage.swift index 1dd15b47..7ea65e06 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Storage.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Storage.swift @@ -64,3 +64,33 @@ extension NBKFlexibleWidth.Magnitude.Storage { } } } + +//*============================================================================* +// MARK: * NBK x Flexible Width x Subtraction x Unsigned x Storage x Special +//*============================================================================* + +extension NBKFlexibleWidth.Magnitude.Storage { + + //=------------------------------------------------------------------------= + // MARK: Transformations x Multiplication By UInt + //=------------------------------------------------------------------------= + + // TODO: test cases + @inlinable mutating func subtract(_ other: Self, times multiplicand: UInt, plus addend: UInt, at index: Int) -> Bool { + var index = index + var overflow = false + //=--------------------------------------= + var otherOverflow = addend as UInt + for otherIndex in other.elements.indices { + var subproduct = other.elements[otherIndex].multipliedFullWidth(by: multiplicand) + subproduct.high &+= UInt(bit: subproduct.low.addReportingOverflow(otherOverflow)) + otherOverflow = subproduct.high + + self.subtractWithoutGoingBeyond(subproduct.low, at: &index, borrowing: &overflow) + } + + self.subtract(otherOverflow, at: &index, borrowing: &overflow) + //=--------------------------------------= + return overflow + } +} diff --git a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Division.swift b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Division.swift index d4374033..7266acd0 100644 --- a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Division.swift +++ b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Division.swift @@ -18,6 +18,8 @@ import XCTest func NBKAssertDivision( _ lhs: UIntXL, _ rhs: UIntXL, _ quotient: UIntXL, _ remainder: UIntXL, _ overflow: Bool = false, file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + XCTAssertEqual(lhs, quotient * rhs + remainder, "lhs != rhs * quotient + remainder", file: file, line: line) //=------------------------------------------= if !overflow { XCTAssertEqual(lhs / rhs, quotient, file: file, line: line) @@ -52,6 +54,8 @@ _ lhs: UIntXL, _ rhs: UIntXL.Digit, _ quotient: UIntXL, _ remainder: UIntXL.Digi file: StaticString = #file, line: UInt = #line) { let extended = UIntXL(digit: remainder) //=------------------------------------------= + XCTAssertEqual(lhs, quotient * rhs + remainder, "lhs != rhs * quotient + remainder", file: file, line: line) + //=------------------------------------------= if !overflow { XCTAssertEqual(lhs / rhs, quotient, file: file, line: line) XCTAssertEqual(lhs % rhs, remainder, file: file, line: line) From e13ebf0b3ba329b9dab923c1d3ca445949fdffcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Mon, 24 Jul 2023 17:40:17 +0200 Subject: [PATCH 018/133] NBKFlexibleWidthKit: Storage. --- .../NBKFlexibleWidth+Addition+Digit.swift | 7 +- .../NBKFlexibleWidth+Addition+Storage.swift | 27 +++++++ .../NBKFlexibleWidth+Addition.swift | 9 +-- .../NBKFlexibleWidth+Division.swift | 8 +- ...FlexibleWidth+Multiplication+Storage.swift | 25 +++++- .../NBKFlexibleWidth+Subtraction+Digit.swift | 10 +-- ...NBKFlexibleWidth+Subtraction+Storage.swift | 76 +++++++++++-------- .../NBKFlexibleWidth+Subtraction.swift | 10 +-- .../NBKFlexibleWidth.swift | 4 +- 9 files changed, 105 insertions(+), 71 deletions(-) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift index 55d9e65f..4b6fcbdf 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift @@ -39,12 +39,7 @@ extension NBKFlexibleWidth.Magnitude { if other.isZero { return } //=--------------------------------------= self.storage.resize(minLastIndex: index) - - var index = index - var overflow = false - - self.storage.add(other, at: &index, carrying: &overflow) - + let overflow = self.storage.add(other, plus: false, at: index) if overflow { self.storage.elements.append(1) } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Storage.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Storage.swift index 73989c39..b6166fef 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Storage.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Storage.swift @@ -13,6 +13,33 @@ import NBKCoreKit // MARK: * NBK x Flexible Width x Addition x Unsigned x Storage //*============================================================================* +extension NBKFlexibleWidth.Magnitude.Storage { + + //=------------------------------------------------------------------------= + // MARK: Transformations x Self + //=------------------------------------------------------------------------= + + @inlinable mutating func add(_ other: Self, plus addend: Bool, at index: Int) -> Bool { + var index = index, overflow = addend + self.add(other, at: &index, carrying: &overflow) + return overflow as Bool + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x UInt + //=------------------------------------------------------------------------= + + @inlinable mutating func add(_ other: UInt, plus addend: Bool, at index: Int) -> Bool { + var index = index, overflow = addend + self.add(other, at: &index, carrying: &overflow) + return overflow as Bool + } +} + +//=----------------------------------------------------------------------------= +// MARK: + Algorithms +//=----------------------------------------------------------------------------= + extension NBKFlexibleWidth.Magnitude.Storage { //=------------------------------------------------------------------------= diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift index 9d239dce..f24f672c 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift @@ -38,13 +38,8 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= if other.isZero { return } //=--------------------------------------= - self.storage.resize(minCount: other.storage.elements.count + index) - - var index = index - var overflow = false - - self.storage.add(other.storage, at: &index, carrying: &overflow) - + self.storage.resize(minCount: other.storage.elements.count + index) + let overflow = self.storage.add(other.storage, plus: false, at: index) if overflow { self.storage.elements.append(1 as UInt) } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift index fcad1575..99b1866a 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift @@ -112,12 +112,8 @@ extension NBKFlexibleWidth.Magnitude { if !digit.isZero { var overflow = remainder.subtract(divisor, times: digit, plus: UInt.zero, at: quotientIndex) while overflow { - let _ = digit.subtractReportingOverflow(1 as UInt) - - var carry = false - var index = quotientIndex - remainder.add(divisor, at: &index, carrying: &carry) - overflow = !carry + _ = digit.subtractReportingOverflow(1 as UInt) + overflow = !remainder.add(divisor, plus: false, at: quotientIndex) } } //=------------------------------= diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Storage.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Storage.swift index a85f5767..49ced327 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Storage.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Storage.swift @@ -22,7 +22,7 @@ extension NBKFlexibleWidth.Magnitude.Storage { @inlinable func multipliedFullWidth(by multiplicand: Self) -> Self { self.multipliedFullWidthByNaiveMethod(by: multiplicand, adding: UInt.zero) } - + @inlinable func multipliedFullWidthByNaiveMethod(by multiplicand: Self, adding addend: UInt) -> Self { Self.uninitialized(count: self.elements.count + multiplicand.elements.count) { product in //=----------------------------------= @@ -52,11 +52,28 @@ extension NBKFlexibleWidth.Magnitude.Storage { // MARK: Transformations x UInt //=------------------------------------------------------------------------= + @inlinable mutating func multiply(by other: UInt, plus addend: UInt) -> UInt { + var overflow = addend + self.multiply(by: other, carrying: &overflow) + return overflow as UInt + } +} + +//=----------------------------------------------------------------------------= +// MARK: + Algorithms +//=----------------------------------------------------------------------------= + +extension NBKFlexibleWidth.Magnitude.Storage { + + //=------------------------------------------------------------------------= + // MARK: Transformations x UInt + //=------------------------------------------------------------------------= + @inlinable mutating func multiply(by other: UInt, carrying overflow: inout UInt) { for index in self.elements.indices { - var subproduct = self.elements[index].multipliedFullWidth(by: other) - subproduct.high &+= UInt(bit: subproduct.low.addReportingOverflow(overflow)) - (overflow, self.elements[index]) = subproduct as HL + var subproduct = self.elements[index].multipliedFullWidth(by: other) + overflow = UInt(bit: subproduct.low.addReportingOverflow(overflow)) &+ subproduct.high + self.elements[index] = subproduct.low as UInt } } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift index ed2354d0..9e7f6326 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift @@ -42,14 +42,8 @@ extension NBKFlexibleWidth.Magnitude { if other.isZero { return false } //=--------------------------------------= self.storage.resize(minLastIndex: index) - - var index = index - var overflow = false - - self.storage.subtract(other, at: &index, borrowing: &overflow) - - self.storage.normalize() - return overflow as Bool + defer{ self.storage.normalize() } + return self.storage.subtract(other, plus: false, at: index) } @_disfavoredOverload @inlinable public func subtractingReportingOverflow(_ other: UInt, at index: Int) -> PVO { diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Storage.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Storage.swift index 7ea65e06..0150b936 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Storage.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Storage.swift @@ -13,6 +13,52 @@ import NBKCoreKit // MARK: * NBK x Flexible Width x Subtraction x Unsigned x Storage //*============================================================================* +extension NBKFlexibleWidth.Magnitude.Storage { + + //=------------------------------------------------------------------------= + // MARK: Transformations x Self + //=------------------------------------------------------------------------= + + @inlinable mutating func subtract(_ other: Self, plus addend: Bool, at index: Int) -> Bool { + var index = index, overflow = addend + self.subtract(other, at: &index, borrowing: &overflow) + return overflow as Bool + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x UInt + //=------------------------------------------------------------------------= + + @inlinable mutating func subtract(_ other: UInt, plus addend: Bool, at index: Int) -> Bool { + var index = index, overflow = addend + self.subtract(other, at: &index, borrowing: &overflow) + return overflow as Bool + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Multiplication By UInt + //=------------------------------------------------------------------------= + + // TODO: test cases + @inlinable mutating func subtract(_ other: Self, times multiplicand: UInt, plus addend: UInt, at index: Int) -> Bool { + var index = index + var overflow = false + var last = addend as UInt + + for otherIndex in other.elements.indices { + var subproduct = other.elements[otherIndex].multipliedFullWidth(by: multiplicand) + last = UInt(bit: subproduct.low.addReportingOverflow(last)) &+ subproduct.high + self.subtractWithoutGoingBeyond(subproduct.low, at: &index, borrowing: &overflow) + } + + return self.subtract(last, plus: overflow, at: index) + } +} + +//=----------------------------------------------------------------------------= +// MARK: + Algorithms +//=----------------------------------------------------------------------------= + extension NBKFlexibleWidth.Magnitude.Storage { //=------------------------------------------------------------------------= @@ -64,33 +110,3 @@ extension NBKFlexibleWidth.Magnitude.Storage { } } } - -//*============================================================================* -// MARK: * NBK x Flexible Width x Subtraction x Unsigned x Storage x Special -//*============================================================================* - -extension NBKFlexibleWidth.Magnitude.Storage { - - //=------------------------------------------------------------------------= - // MARK: Transformations x Multiplication By UInt - //=------------------------------------------------------------------------= - - // TODO: test cases - @inlinable mutating func subtract(_ other: Self, times multiplicand: UInt, plus addend: UInt, at index: Int) -> Bool { - var index = index - var overflow = false - //=--------------------------------------= - var otherOverflow = addend as UInt - for otherIndex in other.elements.indices { - var subproduct = other.elements[otherIndex].multipliedFullWidth(by: multiplicand) - subproduct.high &+= UInt(bit: subproduct.low.addReportingOverflow(otherOverflow)) - otherOverflow = subproduct.high - - self.subtractWithoutGoingBeyond(subproduct.low, at: &index, borrowing: &overflow) - } - - self.subtract(otherOverflow, at: &index, borrowing: &overflow) - //=--------------------------------------= - return overflow - } -} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift index b4886bbe..146b04c9 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift @@ -42,14 +42,8 @@ extension NBKFlexibleWidth.Magnitude { if other.isZero { return false } //=--------------------------------------= self.storage.resize(minCount: other.storage.elements.count + index) - - var index = index - var overflow = false - - self.storage.subtract(other.storage, at: &index, borrowing: &overflow) - - self.storage.normalize() - return overflow as Bool + defer{ self.storage.normalize() } + return self.storage.subtract(other.storage, plus: false, at: index) } @inlinable public func subtractingReportingOverflow(_ other: Self, at index: Int) -> PVO { diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift index 8d8ae3d5..78df9297 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift @@ -31,7 +31,7 @@ import NBKCoreKit @frozen public struct Magnitude: NBKUnsignedInteger { public typealias Digit = UInt - + //=--------------------------------------------------------------------= // MARK: State //=--------------------------------------------------------------------= @@ -74,7 +74,7 @@ import NBKCoreKit //=----------------------------------------------------------------= // MARK: Initializers //=----------------------------------------------------------------= - + @inlinable init(elements: Elements) { self.elements = elements } From f9123216c9f152d8936875077bf4ee80134d6781 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Mon, 24 Jul 2023 19:52:16 +0200 Subject: [PATCH 019/133] NBKFlexibleWidthKit: Division. --- .../NBKFlexibleWidth+Division.swift | 49 +++++++++++-------- .../IntXL+Division.swift | 30 ++++++++++++ .../Utilities/NBKAssert+Division.swift | 6 ++- 3 files changed, 64 insertions(+), 21 deletions(-) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift index 99b1866a..8813d2bc 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift @@ -57,27 +57,37 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @inlinable func quotientAndRemainderReportingOverflowAsNormal(dividingBy other: Self) -> PVO> { + var (remainder) = self + let (quotient, overflow) = remainder.formRemainderWithQuotientReportingOverflowAsNormal(dividingBy: other) + return PVO(QR(quotient, remainder), overflow) + } + + @inlinable mutating func formRemainderWithQuotientReportingOverflowAsNormal(dividingBy other: Self) -> PVO { //=--------------------------------------= // divisor is zero //=--------------------------------------= if other.isZero { - return PVO(QR(self, self), true) + return PVO(self, true) } //=--------------------------------------= // divisor is one word //=--------------------------------------= if other.storage.elements.count == 1 { - let qro = self.quotientAndRemainder(dividingBy: other.storage.elements.first!) - return PVO(QR(qro.quotient, Self(digit: qro.remainder)), false) + let qr = self.quotientAndRemainder(dividingBy: other.storage.elements.first!) + self.assign(qr.remainder) + return PVO(qr.quotient, false) } //=--------------------------------------= // divisor is greater than or equal //=--------------------------------------= let comparison = other.compared(to: self) if comparison >= 0 { - switch comparison.isZero { - case true: return PVO(QR(0001, Self.zero), false) - case false: return PVO(QR(Self.zero, self), false) } + if comparison.isZero { + self.assign(UInt.zero) + return PVO(001, false) + } else { + return PVO(000, false) + } } //=--------------------------------------= // shift to clamp approximation @@ -88,19 +98,18 @@ extension NBKFlexibleWidth.Magnitude { let divisorLast0 = divisor.elements[divisor.elements.endIndex - 1] as UInt assert(divisorLast0.mostSignificantBit, "divisor must be normalized") - var remainder = self.storage - var remainderIndex = remainder.elements.endIndex - remainder.elements.append(0) - remainder.bitshiftLeft(words: Int.zero, bits: shift) + var remainderIndex = self.storage.elements.endIndex + self.storage.elements.append(0) + self.storage.bitshiftLeft(words: Int.zero, bits: shift) //=--------------------------------------= // division: approximate quotient digits //=--------------------------------------= var quotientIndex = remainderIndex - divisor.elements.endIndex as Int var quotient = Storage.uninitialized(count: quotientIndex + 1) { quotient in loop: repeat { - let remainderLast0 = remainder.elements[remainderIndex] - remainder.elements.formIndex(before: &remainderIndex) - let remainderLast1 = remainder.elements[remainderIndex] + let remainderLast0 = self.storage.elements[remainderIndex] + self.storage.elements.formIndex(before: &remainderIndex) + let remainderLast1 = self.storage.elements[remainderIndex] //=------------------------------= var digit: UInt if divisorLast0 == remainderLast0 { @@ -110,10 +119,10 @@ extension NBKFlexibleWidth.Magnitude { } //=------------------------------= if !digit.isZero { - var overflow = remainder.subtract(divisor, times: digit, plus: UInt.zero, at: quotientIndex) + var overflow = self.storage.subtract(divisor, times: digit, plus: UInt.zero, at: quotientIndex) while overflow { - _ = digit.subtractReportingOverflow(1 as UInt) - overflow = !remainder.add(divisor, plus: false, at: quotientIndex) + let _ = digit.subtractReportingOverflow(1 as UInt) + overflow = !self.storage.add(divisor, plus: false, at: quotientIndex) } } //=------------------------------= @@ -124,9 +133,9 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= // undo shift before division //=--------------------------------------= - quotient .normalize() - remainder.bitshiftRight(words: Int.zero, bits: shift) - remainder.normalize() - return PVO(QR(Self(unchecked: quotient), Self(unchecked: remainder)), false) + quotient.normalize() + self.storage.bitshiftRight(words: Int.zero, bits: shift) + self.storage.normalize() + return PVO(Self(unchecked: quotient), false) } } diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Division.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Division.swift index 9b621a5d..352bd2fb 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Division.swift +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Division.swift @@ -119,4 +119,34 @@ final class UIntXLTestsOnDivision: XCTestCase { } } +//*============================================================================* +// MARK: * NBK x UIntXL x Division x Code Coverage +//*============================================================================* + +final class UIntXLTestsOnDivisionCodeCoverage: XCTestCase { + + typealias T = UIntXL + typealias M = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testDividingFullWidth3212MSBAsUInt256() { + var dividend: T, divisor: T, quotient: T, remainder: T + //=--------------------------------------= + dividend = T(x64:[ 0, 0, 0, 0, 0, ~0, ~0, ~0] as X) + divisor = T(x64:[~0, ~0, ~0, ~0, 0, 0, 0, 0] as X) + quotient = T(x64:[ 0, ~0, ~0, ~0, 0, 0, 0, 0] as X) + remainder = T(x64:[ 0, ~0, ~0, ~0, 0, 0, 0, 0] as X) + NBKAssertDivision(dividend, divisor, quotient, remainder) + //=--------------------------------------= + dividend = T(x64:[~0, ~0, ~0, ~0, 0, ~0, ~0, ~0] as X) + divisor = T(x64:[~0, ~0, ~0, ~0, 0, 0, 0, 0] as X) + quotient = T(x64:[ 1, ~0, ~0, ~0, 0, 0, 0, 0] as X) + remainder = T(x64:[ 0, ~0, ~0, ~0, 0, 0, 0, 0] as X) + NBKAssertDivision(dividend, divisor, quotient, remainder) + } +} + #endif diff --git a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Division.swift b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Division.swift index 7266acd0..3e6e7644 100644 --- a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Division.swift +++ b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Division.swift @@ -8,7 +8,7 @@ //=----------------------------------------------------------------------------= import NBKCoreKit -import NBKFlexibleWidthKit +@testable import NBKFlexibleWidthKit import XCTest //*============================================================================* @@ -47,6 +47,10 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual(lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs).partialValue.quotient, quotient, file: file, line: line) XCTAssertEqual(lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs).partialValue.remainder, remainder, file: file, line: line) XCTAssertEqual(lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs).overflow, overflow, file: file, line: line) + //=------------------------------------------= + XCTAssertEqual(lhs.quotientAndRemainderReportingOverflowAsNormal(dividingBy: rhs).partialValue.quotient, quotient, file: file, line: line) + XCTAssertEqual(lhs.quotientAndRemainderReportingOverflowAsNormal(dividingBy: rhs).partialValue.remainder, remainder, file: file, line: line) + XCTAssertEqual(lhs.quotientAndRemainderReportingOverflowAsNormal(dividingBy: rhs).overflow, overflow, file: file, line: line) } func NBKAssertDivisionByDigit( From 2fc4b169304e3b1d00f2666df0608702a2ec490e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Tue, 25 Jul 2023 11:25:33 +0200 Subject: [PATCH 020/133] NBKFlexibleWidthKit: Cleanup. --- .../NBKFlexibleWidth+Addition+Digit.swift | 2 +- ...BKFlexibleWidth+Multiplication+Digit.swift | 6 +- ...FlexibleWidth+Multiplication+Storage.swift | 3 +- .../NBKFlexibleWidth+Storage.swift | 12 --- .../NBKFlexibleWidth+Subtraction+Digit.swift | 2 +- .../IntXL+Comparisons.swift | 75 ++++++++++++------- .../Utilities/NBKAssert+Comparisons.swift | 27 +++++-- 7 files changed, 74 insertions(+), 53 deletions(-) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift index 4b6fcbdf..72c446bb 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift @@ -38,7 +38,7 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= if other.isZero { return } //=--------------------------------------= - self.storage.resize(minLastIndex: index) + self.storage.resize(minCount: index + 1) let overflow = self.storage.add(other, plus: false, at: index) if overflow { self.storage.elements.append(1) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift index e285ecee..4680ae21 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift @@ -41,11 +41,7 @@ extension NBKFlexibleWidth.Magnitude { } //=--------------------------------------= self.storage.reserve(minCount: self.storage.elements.count + 1) - - var overflow = addend as UInt - - self.storage.multiply(by: multiplicand, carrying: &overflow) - + let overflow = self.storage.multiply(by: multiplicand, plus: addend) if !overflow.isZero { self.storage.elements.append(overflow) } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Storage.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Storage.swift index 49ced327..47e4214b 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Storage.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Storage.swift @@ -43,7 +43,8 @@ extension NBKFlexibleWidth.Magnitude.Storage { overflow &+= subproduct.high } - (product[lhsIndex + multiplicand.elements.count], overflow) = (overflow, UInt.zero) + product[lhsIndex + multiplicand.elements.count] = overflow + overflow = UInt.zero } } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Storage.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Storage.swift index 67448b39..4a7ba498 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Storage.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Storage.swift @@ -51,10 +51,6 @@ extension NBKFlexibleWidth.Magnitude.Storage { } } - @inlinable mutating func resize(maxLastIndex: Int) { - self.resize(maxCount: maxLastIndex + 1) - } - @inlinable mutating func resize(minCount: Int) { self.reserve(minCount: minCount) appending: while self.elements.count < minCount { @@ -62,15 +58,7 @@ extension NBKFlexibleWidth.Magnitude.Storage { } } - @inlinable mutating func resize(minLastIndex: Int) { - self.resize(minCount: minLastIndex + 1) - } - @inlinable mutating func reserve(minCount: Int) { self.elements.reserveCapacity(minCount) } - - @inlinable mutating func reserve(minLastIndex: Int) { - self.reserve(minCount: minLastIndex + 1) - } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift index 9e7f6326..68a00b20 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift @@ -41,7 +41,7 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= if other.isZero { return false } //=--------------------------------------= - self.storage.resize(minLastIndex: index) + self.storage.resize(minCount: index + 1) defer{ self.storage.normalize() } return self.storage.subtract(other, plus: false, at: index) } diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Comparisons.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Comparisons.swift index 2c5c7dae..02185233 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Comparisons.swift +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Comparisons.swift @@ -30,33 +30,58 @@ final class UIntXLTestsOnComparisons: XCTestCase { func testHashing() { var union = Set() - union.insert(T(words:[ 0, 0, 0, 0] as [UInt])) - union.insert(T(words:[ 1, 0, 0, 0] as [UInt])) - union.insert(T(words:[ 0, 1, 0, 0] as [UInt])) - union.insert(T(words:[ 0, 0, 1, 0] as [UInt])) - union.insert(T(words:[ 0, 0, 0, 1] as [UInt])) - union.insert(T(words:[ 0, 0, 0, 0] as [UInt])) - XCTAssertEqual(union.count, Int(5)) + union.insert(T(words:[0, 0, 0, 0] as [UInt])) + union.insert(T(words:[0, 0, 0, 0] as [UInt])) + union.insert(T(words:[1, 0, 0, 0] as [UInt])) + union.insert(T(words:[1, 0, 0, 0] as [UInt])) + union.insert(T(words:[0, 1, 0, 0] as [UInt])) + union.insert(T(words:[0, 1, 0, 0] as [UInt])) + union.insert(T(words:[0, 0, 1, 0] as [UInt])) + union.insert(T(words:[0, 0, 1, 0] as [UInt])) + union.insert(T(words:[0, 0, 0, 1] as [UInt])) + union.insert(T(words:[0, 0, 0, 1] as [UInt])) + XCTAssertEqual(union.count, 5 as Int) } - func testComparing() { - NBKAssertComparisons(T(words:[ 0] as [UInt]), T(words:[ 0] as [UInt]), Int(0)) - NBKAssertComparisons(T(words:[ 1] as [UInt]), T(words:[ 1] as [UInt]), Int(0)) - NBKAssertComparisons(T(words:[ 2] as [UInt]), T(words:[ 3] as [UInt]), -Int(1)) - NBKAssertComparisons(T(words:[ 3] as [UInt]), T(words:[ 2] as [UInt]), Int(1)) - - NBKAssertComparisons(T(words:[ 0, 2, 3, 4] as [UInt]), T(words:[ 1, 2, 3, 4] as [UInt]), -Int(1)) - NBKAssertComparisons(T(words:[ 1, 0, 3, 4] as [UInt]), T(words:[ 1, 2, 3, 4] as [UInt]), -Int(1)) - NBKAssertComparisons(T(words:[ 1, 2, 0, 4] as [UInt]), T(words:[ 1, 2, 3, 4] as [UInt]), -Int(1)) - NBKAssertComparisons(T(words:[ 1, 2, 3, 0] as [UInt]), T(words:[ 1, 2, 3, 4] as [UInt]), -Int(1)) - NBKAssertComparisons(T(words:[ 0, 2, 3, 4] as [UInt]), T(words:[ 0, 2, 3, 4] as [UInt]), Int(0)) - NBKAssertComparisons(T(words:[ 1, 0, 3, 4] as [UInt]), T(words:[ 1, 0, 3, 4] as [UInt]), Int(0)) - NBKAssertComparisons(T(words:[ 1, 2, 0, 4] as [UInt]), T(words:[ 1, 2, 0, 4] as [UInt]), Int(0)) - NBKAssertComparisons(T(words:[ 1, 2, 3, 0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(0)) - NBKAssertComparisons(T(words:[ 1, 2, 3, 4] as [UInt]), T(words:[ 0, 2, 3, 4] as [UInt]), Int(1)) - NBKAssertComparisons(T(words:[ 1, 2, 3, 4] as [UInt]), T(words:[ 1, 0, 3, 4] as [UInt]), Int(1)) - NBKAssertComparisons(T(words:[ 1, 2, 3, 4] as [UInt]), T(words:[ 1, 2, 0, 4] as [UInt]), Int(1)) - NBKAssertComparisons(T(words:[ 1, 2, 3, 4] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(1)) + func testComparisons() { + NBKAssertComparisons(T(words:[0, 2, 3, 4] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), -Int(1)) + NBKAssertComparisons(T(words:[1, 0, 3, 4] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), -Int(1)) + NBKAssertComparisons(T(words:[1, 2, 0, 4] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), -Int(1)) + NBKAssertComparisons(T(words:[1, 2, 3, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), -Int(1)) + NBKAssertComparisons(T(words:[0, 2, 3, 4] as [UInt]), T(words:[0, 2, 3, 4] as [UInt]), Int(0)) + NBKAssertComparisons(T(words:[1, 0, 3, 4] as [UInt]), T(words:[1, 0, 3, 4] as [UInt]), Int(0)) + NBKAssertComparisons(T(words:[1, 2, 0, 4] as [UInt]), T(words:[1, 2, 0, 4] as [UInt]), Int(0)) + NBKAssertComparisons(T(words:[1, 2, 3, 0] as [UInt]), T(words:[1, 2, 3, 0] as [UInt]), Int(0)) + NBKAssertComparisons(T(words:[1, 2, 3, 4] as [UInt]), T(words:[0, 2, 3, 4] as [UInt]), Int(1)) + NBKAssertComparisons(T(words:[1, 2, 3, 4] as [UInt]), T(words:[1, 0, 3, 4] as [UInt]), Int(1)) + NBKAssertComparisons(T(words:[1, 2, 3, 4] as [UInt]), T(words:[1, 2, 0, 4] as [UInt]), Int(1)) + NBKAssertComparisons(T(words:[1, 2, 3, 4] as [UInt]), T(words:[1, 2, 3, 0] as [UInt]), Int(1)) + } + + func testComparisonsAtIndex() { + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(0), Int(0)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(1), Int(0)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(2), Int(0)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(3), Int(0)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(4), Int(0)) + + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(0), -Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(1), -Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(2), -Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(3), -Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(4), -Int(1)) + + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(0), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(1), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(2), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(3), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(4), Int(1)) + + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(0), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(1), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(2), Int(0)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(3), -Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(4), -Int(1)) } //=------------------------------------------------------------------------= diff --git a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Comparisons.swift b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Comparisons.swift index fed6311c..381abc0a 100644 --- a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Comparisons.swift +++ b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Comparisons.swift @@ -16,16 +16,27 @@ import XCTest //*============================================================================* func NBKAssertComparisons( -_ lhs: T, _ rhs: T, _ result: Int, +_ lhs: T, _ rhs: T, _ signum: Int, file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual(lhs == rhs, result == 0, file: file, line: line) - XCTAssertEqual(lhs != rhs, result != 0, file: file, line: line) + XCTAssertEqual(lhs == rhs, signum == 0, file: file, line: line) + XCTAssertEqual(lhs != rhs, signum != 0, file: file, line: line) - XCTAssertEqual(lhs < rhs, result == -1, file: file, line: line) - XCTAssertEqual(lhs <= rhs, result != 1, file: file, line: line) + XCTAssertEqual(lhs < rhs, signum == -1, file: file, line: line) + XCTAssertEqual(lhs <= rhs, signum != 1, file: file, line: line) - XCTAssertEqual(lhs > rhs, result == 1, file: file, line: line) - XCTAssertEqual(lhs >= rhs, result != -1, file: file, line: line) + XCTAssertEqual(lhs > rhs, signum == 1, file: file, line: line) + XCTAssertEqual(lhs >= rhs, signum != -1, file: file, line: line) - XCTAssertEqual(lhs.compared(to: rhs), result, file: file, line: line) + XCTAssertEqual(lhs.compared(to: rhs), signum, file: file, line: line) +} + +func NBKAssertComparisonsAtIndex( +_ lhs: UIntXL, _ rhs: UIntXL, _ index: Int, _ signum: Int, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + if index.isZero { + NBKAssertComparisons(lhs, rhs, signum, file: file, line: line) + } + //=------------------------------------------= + XCTAssertEqual(lhs.compared(to: rhs, at: index), signum, file: file, line: line) } From a03cbb8c347f7c204d6e5c55892588176b8b565b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Tue, 25 Jul 2023 13:39:03 +0200 Subject: [PATCH 021/133] NBKFlexibleWidthKit: Tests. --- .../IntXL+Shifts.swift | 61 +++++++++++++++++-- .../IntXL+Shifts.swift | 8 +++ .../Utilities/NBKAssert+Words.swift | 4 +- 3 files changed, 66 insertions(+), 7 deletions(-) diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Shifts.swift b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Shifts.swift index 36709f05..3dc6a565 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Shifts.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Shifts.swift @@ -39,23 +39,23 @@ final class UIntXLBenchmarksOnShifts: XCTestCase { } } - func testBitshiftingLeftByWordsAndBits() { + func testBitshiftingLeftByWords() { var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs.bitshiftedLeft(words: rhs.words, bits: rhs.bits)) + NBK.blackHole(lhs.bitshiftedLeft(words: rhs.words)) NBK.blackHoleInoutIdentity(&lhs) NBK.blackHoleInoutIdentity(&rhs) } } - func testBitshiftingLeftByWords() { + func testBitshiftingLeftByWordsAndBits() { var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs.bitshiftedLeft(words: rhs.words)) + NBK.blackHole(lhs.bitshiftedLeft(words: rhs.words, bits: rhs.bits)) NBK.blackHoleInoutIdentity(&lhs) NBK.blackHoleInoutIdentity(&rhs) } @@ -76,6 +76,17 @@ final class UIntXLBenchmarksOnShifts: XCTestCase { } } + func testBitshiftingRightByWords() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs.bitshiftedRight(words: rhs.words)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + func testBitshiftingRightByWordsAndBits() { var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) @@ -87,12 +98,50 @@ final class UIntXLBenchmarksOnShifts: XCTestCase { } } - func testBitshiftingRightByWords() { + //=------------------------------------------------------------------------= + // MARK: Tests x In Both Directions + //=------------------------------------------------------------------------= + + func testBitshiftingInBothDirectionsInout() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(UInt.bitWidth * 3/2) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs.bitshiftLeft (by: rhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + + NBK.blackHole(lhs.bitshiftRight(by: rhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testBitshiftingInBothDirectionsByWordsInout() { var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs.bitshiftedRight(words: rhs.words)) + NBK.blackHole(lhs.bitshiftLeft (words: rhs.words)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + + NBK.blackHole(lhs.bitshiftRight(words: rhs.words)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testBitshiftingInBothDirectionsByWordsAndBitsInout() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs.bitshiftLeft (words: rhs.words, bits: rhs.bits)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + + NBK.blackHole(lhs.bitshiftRight(words: rhs.words, bits: rhs.bits)) NBK.blackHoleInoutIdentity(&lhs) NBK.blackHoleInoutIdentity(&rhs) } diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Shifts.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Shifts.swift index 6d530f17..16e63986 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Shifts.swift +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Shifts.swift @@ -124,6 +124,14 @@ final class UIntXLTestsOnShifts: XCTestCase { XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) >> Int.min, T.zero) XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) >> Int.max, T.zero) } + + func testBitshiftingZeroDoesNotDoAnything() { + XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) << (UInt.bitWidth + 0), T.zero) + XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) << (UInt.bitWidth + 1), T.zero) + + XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) >> (UInt.bitWidth + 0), T.zero) + XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) >> (UInt.bitWidth + 1), T.zero) + } } #endif diff --git a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Words.swift b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Words.swift index 59166c6d..1f5a2a41 100644 --- a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Words.swift +++ b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Words.swift @@ -18,5 +18,7 @@ import XCTest func NBKAssertWords( _ integer: T, _ words: [UInt], file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual(Array(integer.words), words, file: file, line: line) + + XCTAssertEqual(Array(integer.words), Array(words), file: file, line: line) + XCTAssertEqual(Array(integer.words.reversed()), Array(words.reversed()), file: file, line: line) } From 8abfd31c3c457f01ee0fb843e2ee2fd3473ed005 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Wed, 26 Jul 2023 15:38:16 +0200 Subject: [PATCH 022/133] NBKFlexibleWidthKit: IntXL, TODOs. --- .../NBKFlexibleWidth+Addition+Digit.swift | 31 +++++ .../NBKFlexibleWidth+Addition.swift | 31 +++++ .../NBKFlexibleWidth+Bits.swift | 43 +++++++ .../NBKFlexibleWidth+Comparisons.swift | 66 ++++++++++ .../NBKFlexibleWidth+Complements.swift | 29 ++++- .../NBKFlexibleWidth+Division+Digit.swift | 41 +++++- .../NBKFlexibleWidth+Division.swift | 37 ++++++ .../NBKFlexibleWidth+Logic.swift | 51 ++++++++ ...BKFlexibleWidth+Multiplication+Digit.swift | 33 +++++ .../NBKFlexibleWidth+Multiplication.swift | 31 +++++ .../NBKFlexibleWidth+Negation.swift | 30 +++++ .../NBKFlexibleWidth+Numbers.swift | 65 +++++++++- .../NBKFlexibleWidth+Shifts.swift | 120 ++++++++++++++++++ .../NBKFlexibleWidth+Subtraction+Digit.swift | 31 +++++ .../NBKFlexibleWidth+Subtraction.swift | 31 +++++ .../NBKFlexibleWidth+Text+Radix.swift | 26 +++- .../NBKFlexibleWidth+Text.swift | 71 +++++++++++ .../NBKFlexibleWidth+Words.swift | 23 ++++ .../NBKFlexibleWidth.swift | 2 +- .../IntXL+Division.swift | 3 + 20 files changed, 788 insertions(+), 7 deletions(-) create mode 100644 Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Negation.swift diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift index 72c446bb..61668c62 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift @@ -9,6 +9,37 @@ import NBKCoreKit +//*============================================================================* +// MARK: * NBK x Flexible Width x Addition x Digit x Signed +//*============================================================================* + +extension NBKFlexibleWidth { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @_disfavoredOverload @inlinable public static func +=(lhs: inout Self, rhs: Int) { + lhs.add(rhs, at: Int.zero) + } + + @_disfavoredOverload @inlinable public static func +(lhs: Self, rhs: Int) -> Self { + lhs.adding(rhs, at: Int.zero) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @_disfavoredOverload @inlinable public mutating func add(_ other: Int, at index: Int) { + fatalError("TODO") + } + + @_disfavoredOverload @inlinable public func adding(_ other: Int, at index: Int) -> Self { + var result = self; result.add(other, at: index); return result + } +} + //*============================================================================* // MARK: * NBK x Flexible Width x Addition x Digit x Unsigned //*============================================================================* diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift index f24f672c..abf5e200 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift @@ -9,6 +9,37 @@ import NBKCoreKit +//*============================================================================* +// MARK: * NBK x Flexible Width x Addition x Signed +//*============================================================================* + +extension NBKFlexibleWidth { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public static func +=(lhs: inout Self, rhs: Self) { + lhs.add(rhs, at: Int.zero) + } + + @inlinable public static func +(lhs: Self, rhs: Self) -> Self { + lhs.adding(rhs, at: Int.zero) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public mutating func add(_ other: Self, at index: Int) { + fatalError("TODO") + } + + @inlinable public func adding(_ other: Self, at index: Int) -> Self { + var result = self; result.add(other, at: index); return result + } +} + //*============================================================================* // MARK: * NBK x Flexible Width x Addition x Unsigned //*============================================================================* diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift index f269f76f..ed7e9c9c 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift @@ -9,6 +9,49 @@ import NBKCoreKit +//*============================================================================* +// MARK: * NBK x Flexible Width x Bits x Signed +//*============================================================================* + +extension NBKFlexibleWidth { + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + @inlinable public init(bit: Bool) { + self.init(digit: Digit(bit: bit)) + } + + //=------------------------------------------------------------------------= + // MARK: Accessors + //=------------------------------------------------------------------------= + + @inlinable public var bitWidth: Int { + fatalError("TODO") + } + + @inlinable public var nonzeroBitCount: Int { + fatalError("TODO") + } + + @inlinable public var leadingZeroBitCount: Int { + fatalError("TODO") + } + + @inlinable public var trailingZeroBitCount: Int { + fatalError("TODO") + } + + @inlinable public var mostSignificantBit: Bool { + fatalError("TODO") + } + + @inlinable public var leastSignificantBit: Bool { + fatalError("TODO") + } +} + //*============================================================================* // MARK: * NBK x Flexible Width x Bits x Unsigned //*============================================================================* diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift index 4933fc1c..88672bc9 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift @@ -9,6 +9,65 @@ import NBKCoreKit +//*============================================================================* +// MARK: * NBK x Flexible Width x Comparisons x Signed +//*============================================================================* + +extension NBKFlexibleWidth { + + //=------------------------------------------------------------------------= + // MARK: Accessors + //=------------------------------------------------------------------------= + + @inlinable public var isZero: Bool { + fatalError("TODO") + } + + @inlinable public var isLessThanZero: Bool { + fatalError("TODO") + } + + @inlinable public var isMoreThanZero: Bool { + fatalError("TODO") + } + + @inlinable public func signum() -> Int { + fatalError("TODO") + } + + @inlinable public var isPowerOf2: Bool { + fatalError("TODO") + } + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + @inlinable public func hash(into hasher: inout Hasher) { + fatalError("TODO") + } + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + @inlinable public static func ==(lhs: Self, rhs: Self) -> Bool { + lhs.compared(to: rhs) == 0 + } + + @inlinable public static func <(lhs: Self, rhs: Self) -> Bool { + lhs.compared(to: rhs) == -1 + } + + @inlinable public func compared(to other: Self) -> Int { + fatalError("TODO") + } + + @inlinable public func compared(to other: Self, at index: Int) -> Int { + fatalError("TODO") + } +} + //*============================================================================* // MARK: * NBK x Flexible Width x Comparisons x Unsigned //*============================================================================* @@ -85,6 +144,13 @@ extension NBKFlexibleWidth.Magnitude { return Int(bit: !prefix.allSatisfy({ $0.isZero })) }} } +} + +//=----------------------------------------------------------------------------= +// MARK: + Algorithms +//=----------------------------------------------------------------------------= + +extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= // MARK: Utilities x Private diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements.swift index 84c0bc23..d250ee01 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements.swift @@ -9,6 +9,33 @@ import NBKCoreKit +//*============================================================================* +// MARK: * NBK x Flexible Width x Complements x Signed +//*============================================================================* + +extension NBKFlexibleWidth { + + //=------------------------------------------------------------------------= + // MARK: Details x Magnitude + //=------------------------------------------------------------------------= + + @inlinable public var magnitude: Magnitude { + self._magnitude + } + + //=------------------------------------------------------------------------= + // MARK: Details x Two's Complement + //=------------------------------------------------------------------------= + + @inlinable public mutating func formTwosComplement() { + fatalError("TODO") + } + + @inlinable public func twosComplement() -> Self { + fatalError("TODO") + } +} + //*============================================================================* // MARK: * NBK x Flexible Width x Complements x Unsigned //*============================================================================* @@ -16,7 +43,7 @@ import NBKCoreKit extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= - // MARK: Utilities + // MARK: Details x Two's Complement //=------------------------------------------------------------------------= @inlinable public mutating func formTwosComplement() { diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.swift index c46d9c5f..a71beaf8 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.swift @@ -9,6 +9,43 @@ import NBKCoreKit +//*============================================================================* +// MARK: * NBK x Flexible Width x Division x Digit x Signed +//*============================================================================* + +extension NBKFlexibleWidth { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @_disfavoredOverload @inlinable public mutating func divideReportingOverflow(by other: Digit) -> Bool { + let pvo: PVO = self.dividedReportingOverflow(by: other) + self = pvo.partialValue + return pvo.overflow as Bool + } + + @_disfavoredOverload @inlinable public func dividedReportingOverflow(by other: Digit) -> PVO { + let qro: PVO> = self.quotientAndRemainderReportingOverflow(dividingBy: other) + return PVO(qro.partialValue.quotient, qro.overflow) + } + + @_disfavoredOverload @inlinable public mutating func formRemainderReportingOverflow(dividingBy other: Digit) -> Bool { + let pvo: PVO = self.remainderReportingOverflow(dividingBy: other) + self = Self(digit: pvo.partialValue) + return pvo.overflow as Bool + } + + @_disfavoredOverload @inlinable public func remainderReportingOverflow(dividingBy other: Digit) -> PVO { + let qro: PVO> = self.quotientAndRemainderReportingOverflow(dividingBy: other) + return PVO(qro.partialValue.remainder, qro.overflow) + } + + @_disfavoredOverload @inlinable public func quotientAndRemainderReportingOverflow(dividingBy other: Digit) -> PVO> { + fatalError("TODO") + } +} + //*============================================================================* // MARK: * NBK x Flexible Width x Division x Digit x Unsigned //*============================================================================* @@ -41,7 +78,7 @@ extension NBKFlexibleWidth.Magnitude { return PVO(qro.partialValue.remainder, qro.overflow) } - @_disfavoredOverload @inlinable public func quotientAndRemainderReportingOverflow(dividingBy other: UInt) -> PVO> { + @_disfavoredOverload @inlinable public func quotientAndRemainderReportingOverflow(dividingBy other: Digit) -> PVO> { var quotient = self let remainder = quotient.formQuotientWithRemainderReportingOverflow(dividingBy: other) return PVO(QR(quotient, remainder.partialValue), remainder.overflow) @@ -51,7 +88,7 @@ extension NBKFlexibleWidth.Magnitude { // MARK: Transformations x Private //=------------------------------------------------------------------------= - @_disfavoredOverload @inlinable mutating func formQuotientWithRemainderReportingOverflow(dividingBy other: UInt) -> PVO { + @_disfavoredOverload @inlinable mutating func formQuotientWithRemainderReportingOverflow(dividingBy other: Digit) -> PVO { defer { Swift.assert(self.storage.isNormal) } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift index 8813d2bc..0e107037 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift @@ -9,6 +9,43 @@ import NBKCoreKit +//*============================================================================* +// MARK: * NBK x Flexible Width x Division x Signed +//*============================================================================* + +extension NBKFlexibleWidth { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public mutating func divideReportingOverflow(by other: Self) -> Bool { + let pvo: PVO = self.dividedReportingOverflow(by: other) + self = pvo.partialValue + return pvo.overflow as Bool + } + + @inlinable public func dividedReportingOverflow(by other: Self) -> PVO { + let qro: PVO> = self.quotientAndRemainderReportingOverflow(dividingBy: other) + return PVO(qro.partialValue.quotient, qro.overflow) + } + + @inlinable public mutating func formRemainderReportingOverflow(dividingBy other: Self) -> Bool { + let pvo: PVO = self.remainderReportingOverflow(dividingBy: other) + self = pvo.partialValue + return pvo.overflow as Bool + } + + @inlinable public func remainderReportingOverflow(dividingBy other: Self) -> PVO { + let qro: PVO> = self.quotientAndRemainderReportingOverflow(dividingBy: other) + return PVO(qro.partialValue.remainder, qro.overflow) + } + + @inlinable public func quotientAndRemainderReportingOverflow(dividingBy other: Self) -> PVO> { + fatalError("TODO") + } +} + //*============================================================================* // MARK: * NBK x Flexible Width x Division x Unsigned //*============================================================================* diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift index e16e4bb2..0897dff5 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift @@ -9,6 +9,57 @@ import NBKCoreKit +//*============================================================================* +// MARK: * NBK x Flexible Width x Logic x Signed +//*============================================================================* + +extension NBKFlexibleWidth { + + //=------------------------------------------------------------------------= + // MARK: Transformations x NOT + //=------------------------------------------------------------------------= + + @inlinable public static prefix func ~(x: Self) -> Self { + fatalError("TODO") + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x AND + //=------------------------------------------------------------------------= + + @inlinable public static func &=(lhs: inout Self, rhs: Self) { + fatalError("TODO") + } + + @inlinable public static func &(lhs: Self, rhs: Self) -> Self { + var lhs = lhs; lhs &= rhs; return lhs + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x OR + //=------------------------------------------------------------------------= + + @inlinable public static func |=(lhs: inout Self, rhs: Self) { + fatalError("TODO") + } + + @inlinable public static func |(lhs: Self, rhs: Self) -> Self { + var lhs = lhs; lhs |= rhs; return lhs + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x XOR + //=------------------------------------------------------------------------= + + @inlinable public static func ^=(lhs: inout Self, rhs: Self) { + fatalError("TODO") + } + + @inlinable public static func ^(lhs: Self, rhs: Self) -> Self { + var lhs = lhs; lhs ^= rhs; return lhs + } +} + //*============================================================================* // MARK: * NBK x Flexible Width x Logic x Unsigned //*============================================================================* diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift index 4680ae21..67f6a337 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift @@ -9,6 +9,39 @@ import NBKCoreKit +//*============================================================================* +// MARK: * NBK x Flexible Width x Multiplication x Digit x Signed +//*============================================================================* + +extension NBKFlexibleWidth { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @_disfavoredOverload @inlinable public static func *=(lhs: inout Self, rhs: Int) { + lhs.multiply(by: rhs, adding: UInt.zero) + } + + @_disfavoredOverload @inlinable public static func *(lhs: Self, rhs: Int) -> Self { + lhs.multiplied(by: rhs, adding: UInt.zero) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + // TODO: see what kind of addition the algorithm intrinsically permits + @_disfavoredOverload @inlinable mutating func multiply(by multiplicand: Int, adding addend: UInt) { + fatalError("TODO") + } + + // TODO: see what kind of addition the algorithm intrinsically permits + @_disfavoredOverload @inlinable func multiplied(by multiplicand: Int, adding addend: UInt) -> Self { + var result = self; result.multiply(by: multiplicand, adding: addend); return result + } +} + //*============================================================================* // MARK: * NBK x Flexible Width x Multiplication x Digit x Unsigned //*============================================================================* diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift index 3f7da9c1..ad65dbb7 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift @@ -9,6 +9,37 @@ import NBKCoreKit +//*============================================================================* +// MARK: * NBK x Flexible Width x Multiplication x Signed +//*============================================================================* + +extension NBKFlexibleWidth { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public static func *=(lhs: inout Self, rhs: Self) { + lhs.multiply(by: rhs) + } + + @inlinable public static func *(lhs: Self, rhs: Self) -> Self { + lhs.multiplied(by: rhs) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public mutating func multiply(by multiplicand: Self) { + self = self.multiplied(by: multiplicand) + } + + @inlinable public func multiplied(by multiplicand: Self) -> Self { + fatalError("TODO") + } +} + //*============================================================================* // MARK: * NBK x Flexible Width x Multiplication x Unsigned //*============================================================================* diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Negation.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Negation.swift new file mode 100644 index 00000000..c9444ada --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Negation.swift @@ -0,0 +1,30 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +// TODO: consider moving this to complements as the additive inverse +//*============================================================================* +// MARK: * NBK x Flexible Width x Negation x Signed +//*============================================================================* + +extension NBKFlexibleWidth { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public mutating func negateReportingOverflow() -> Bool { + fatalError("TODO") + } + + @inlinable public func negatedReportingOverflow() -> PVO { + fatalError("TODO") + } +} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift index 2c5686bb..32398025 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift @@ -9,6 +9,67 @@ import NBKCoreKit +//*============================================================================* +// MARK: * NBK x Flexible Width x Numbers x Signed +//*============================================================================* + +extension NBKFlexibleWidth { + + //=------------------------------------------------------------------------= + // MARK: Constants + //=------------------------------------------------------------------------= + + public static let zero = Self(0) + + //=------------------------------------------------------------------------= + // MARK: Initializers x Digit + //=------------------------------------------------------------------------= + + @inlinable public init(digit: Int) { + fatalError("TODO") + } + + //=------------------------------------------------------------------------= + // MARK: Initializers x Literal + //=------------------------------------------------------------------------= + + @inlinable public init(integerLiteral value: StaticBigInt) { + fatalError("TODO") + } + + //=------------------------------------------------------------------------= + // MARK: Initializers x Binary Integer + //=------------------------------------------------------------------------= + + @inlinable public init(_ source: some BinaryInteger) { + fatalError("TODO") + } + + @inlinable public init?(exactly source: some BinaryInteger) { + fatalError("TODO") + } + + @inlinable public init(clamping source: some BinaryInteger) { + fatalError("TODO") + } + + @inlinable public init(truncatingIfNeeded source: some BinaryInteger) { + fatalError("TODO") + } + + //=------------------------------------------------------------------------= + // MARK: Initializers x Binary Floating Point + //=------------------------------------------------------------------------= + + @inlinable public init(_ source: some BinaryFloatingPoint) { + fatalError("TODO") + } + + @inlinable public init?(exactly source: some BinaryFloatingPoint) { + fatalError("TODO") + } +} + //*============================================================================* // MARK: * NBK x Flexible Width x Numbers x Unsigned //*============================================================================* @@ -16,13 +77,13 @@ import NBKCoreKit extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= - // MARK: Accessors + // MARK: Constants //=------------------------------------------------------------------------= public static let zero = Self(0) //=------------------------------------------------------------------------= - // MARK: Initializers + // MARK: Initializers x Digit //=------------------------------------------------------------------------= @inlinable public init(digit: UInt) { diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift index ac81385f..50ad3e30 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift @@ -9,6 +9,126 @@ import NBKCoreKit +//*============================================================================* +// MARK: * NBK x Flexible Width x Shifts x Signed +//*============================================================================* +//=----------------------------------------------------------------------------= +// MARK: + Left +//=----------------------------------------------------------------------------= + +extension NBKFlexibleWidth { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public static func <<=(lhs: inout Self, rhs: some BinaryInteger) { + fatalError("TODO") + } + + @inlinable public static func <<(lhs: Self, rhs: some BinaryInteger) -> Self { + var lhs = lhs; lhs <<= rhs; return lhs + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Int + //=------------------------------------------------------------------------= + + @inlinable public mutating func bitshiftLeftSmart(by distance: Int) { + fatalError("TODO") + } + + @inlinable public func bitshiftedLeftSmart(by distance: Int) -> Self { + var result = self; result.bitshiftLeftSmart(by: distance); return result + } + + @inlinable public mutating func bitshiftLeft(by distance: Int) { + precondition(distance >= 0, NBK.callsiteOutOfBoundsInfo()) + let major = NBK .quotientDividingByBitWidthAssumingIsAtLeastZero(distance) + let minor = NBK.remainderDividingByBitWidthAssumingIsAtLeastZero(distance) + return self.bitshiftLeft(words: major, bits: minor) + } + + @inlinable public func bitshiftedLeft(by distance: Int) -> Self { + var result = self; result.bitshiftLeft(by: distance); return result + } + + @inlinable public mutating func bitshiftLeft(words: Int, bits: Int) { + fatalError("TODO") + } + + @inlinable public func bitshiftedLeft(words: Int, bits: Int) -> Self { + var result = self; result.bitshiftLeft(words: words, bits: bits); return result + } + + @inlinable public mutating func bitshiftLeft(words: Int) { + fatalError("TODO") + } + + @inlinable public func bitshiftedLeft(words: Int) -> Self { + var result = self; result.bitshiftLeft(words: words); return result + } +} + +//=----------------------------------------------------------------------------= +// MARK: + Right +//=----------------------------------------------------------------------------= + +extension NBKFlexibleWidth { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public static func >>=(lhs: inout Self, rhs: some BinaryInteger) { + fatalError("TODO") + } + + @inlinable public static func >>(lhs: Self, rhs: some BinaryInteger) -> Self { + var lhs = lhs; lhs >>= rhs; return lhs + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Int + //=------------------------------------------------------------------------= + + @inlinable public mutating func bitshiftRightSmart(by distance: Int) { + fatalError("TODO") + } + + @inlinable public func bitshiftedRightSmart(by distance: Int) -> Self { + var result = self; result.bitshiftRightSmart(by: distance); return result + } + + @inlinable public mutating func bitshiftRight(by distance: Int) { + precondition(distance >= 0, NBK.callsiteOutOfBoundsInfo()) + let major = NBK .quotientDividingByBitWidthAssumingIsAtLeastZero(distance) + let minor = NBK.remainderDividingByBitWidthAssumingIsAtLeastZero(distance) + return self.bitshiftRight(words: major, bits: minor) + } + + @inlinable public func bitshiftedRight(by distance: Int) -> Self { + var result = self; result.bitshiftRight(by: distance); return result + } + + @inlinable public mutating func bitshiftRight(words: Int, bits: Int) { + fatalError("TODO") + } + + @inlinable public func bitshiftedRight(words: Int, bits: Int) -> Self { + var result = self; result.bitshiftRight(words: words, bits: bits); return result + } + + @inlinable public mutating func bitshiftRight(words: Int) { + fatalError("TODO") + } + + @inlinable public func bitshiftedRight(words: Int) -> Self { + var result = self; result.bitshiftRight(words: words); return result + } +} + + //*============================================================================* // MARK: * NBK x Flexible Width x Shifts x Unsigned //*============================================================================* diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift index 68a00b20..681e86e8 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift @@ -9,6 +9,37 @@ import NBKCoreKit +//*============================================================================* +// MARK: * NBK x Flexible Width x Subtraction x Digit x Signed +//*============================================================================* + +extension NBKFlexibleWidth { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @_disfavoredOverload @inlinable public static func -=(lhs: inout Self, rhs: Int) { + lhs.subtract(rhs, at: Int.zero) + } + + @_disfavoredOverload @inlinable public static func -(lhs: Self, rhs: Int) -> Self { + lhs.subtracting(rhs, at: Int.zero) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @_disfavoredOverload @inlinable public mutating func subtract(_ other: Int, at index: Int) { + fatalError("TODO") + } + + @_disfavoredOverload @inlinable public func subtracting(_ other: Int, at index: Int) -> Self { + var result = self; result.subtract(other, at: index); return result + } +} + //*============================================================================* // MARK: * NBK x Flexible Width x Subtraction x Digit x Unsigned //*============================================================================* diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift index 146b04c9..c3e64f57 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift @@ -9,6 +9,37 @@ import NBKCoreKit +//*============================================================================* +// MARK: * NBK x Flexible Width x Subtraction +//*============================================================================* + +extension NBKFlexibleWidth { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public static func -=(lhs: inout Self, rhs: Self) { + lhs.subtract(rhs, at: Int.zero) + } + + @inlinable public static func -(lhs: Self, rhs: Self) -> Self { + lhs.subtracting(rhs, at: Int.zero) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public mutating func subtract(_ other: Self, at index: Int) { + fatalError("TODO") + } + + @inlinable public func subtracting(_ other: Self, at index: Int) -> Self { + var result = self; result.subtract(other, at: index); return result + } +} + //*============================================================================* // MARK: * NBK x Flexible Width x Subtraction x Unsigned //*============================================================================* diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text+Radix.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text+Radix.swift index b85f70e2..de0cca3a 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text+Radix.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text+Radix.swift @@ -9,8 +9,32 @@ import NBKCoreKit +// TODO: IntXL and UIntXL are similar //*============================================================================* -// MARK: * NBK x Flexible Width x Text x Radix +// MARK: * NBK x Flexible Width x Text x Radix x Signed +//*============================================================================* + +extension NBKFlexibleWidth { + + //=------------------------------------------------------------------------= + // MARK: Details x Decode + //=------------------------------------------------------------------------= + + @inlinable public init?(_ description: some StringProtocol, radix: Int = 10) { + fatalError("TODO") + } + + //=------------------------------------------------------------------------= + // MARK: Details x Encode + //=------------------------------------------------------------------------= + + @inlinable public func description(radix: Int = 10, uppercase: Bool = false) -> String { + fatalError("TODO") + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Text x Radix x Unsigned //*============================================================================* extension NBKFlexibleWidth.Magnitude { diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text.swift index 52e6e2c0..379f9261 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text.swift @@ -9,6 +9,77 @@ import NBKCoreKit +// TODO: IntXL and UIntXL are similar +//*============================================================================* +// MARK: * NBK x Flexible Width x Text x Signed +//*============================================================================* + +extension NBKFlexibleWidth { + + //=------------------------------------------------------------------------= + // MARK: Details x Decode + //=------------------------------------------------------------------------= + + /// Creates a new instance from the given `description`. + /// + /// The `description` may contain a plus or minus sign (+ or -), followed + /// by one or more numeric digits (0-9). If the description uses an invalid + /// format, or its value cannot be represented, the result is nil. + /// + /// ``` + /// ┌──────────── → ─────────────┐ + /// │ description │ self │ + /// ├──────────── → ─────────────┤ + /// │ "123" │ Int256( 123) │ + /// │ "+123" │ Int256( 123) │ + /// │ "-123" │ Int256(-123) │ + /// │ "~123" │ nil │ + /// └──────────── → ─────────────┘ + /// ``` + /// + /// - Note: This member is required by `Swift.LosslessStringConvertible`. + /// + @inlinable public init?(_ description: String) { + self.init(description, radix: 10) + } + + //=------------------------------------------------------------------------= + // MARK: Details x Encode + //=------------------------------------------------------------------------= + + /// The `description` of this value. + /// + /// ``` + /// ┌───────────── → ────────────┐ + /// │ self │ description │ + /// ├───────────── → ────────────┤ + /// │ Int256( 123) │ "123" │ + /// │ Int256(-123) │ "-123" │ + /// └───────────── → ────────────┘ + /// ``` + /// + /// - Note: This member is required by `Swift.CustomStringConvertible`. + /// + @inlinable public var description: String { + self.description(radix: 10, uppercase: false) + } + + /// The `description` of this type. + /// + /// ``` + /// ┌───────────── → ────────────┐ + /// │ self │ description │ + /// ├───────────── → ────────────┤ + /// │ Int256.self │ "Int256" │ + /// │ UInt512.self │ "UInt512" │ + /// └───────────── → ────────────┘ + /// ``` + /// + @inlinable public static var description: String { + "IntXL" + } +} + //*============================================================================* // MARK: * NBK x Flexible Width x Text x Unsigned //*============================================================================* diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift index d78d3f9f..442843d2 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift @@ -9,6 +9,29 @@ import NBKCoreKit +//*============================================================================* +// MARK: * NBK x Flexible Width x Words x Signed +//*============================================================================* + +extension NBKFlexibleWidth { + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + @inlinable public init(words: some RandomAccessCollection) { + fatalError("TODO") + } + + //=------------------------------------------------------------------------= + // MARK: Accessors + //=------------------------------------------------------------------------= + + @inlinable public var words: [UInt] { + fatalError("TODO") + } +} + //*============================================================================* // MARK: * NBK x Flexible Width x Words x Unsigned //*============================================================================* diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift index 78df9297..c593208b 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift @@ -13,7 +13,7 @@ import NBKCoreKit // MARK: * NBK x Flexible Width //*============================================================================* -@frozen public struct NBKFlexibleWidth: Hashable { +@frozen public struct NBKFlexibleWidth: NBKSignedInteger { public typealias Digit = Int diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Division.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Division.swift index 352bd2fb..653604fc 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Division.swift +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Division.swift @@ -55,6 +55,9 @@ final class UIntXLTestsOnDivision: XCTestCase { } func testDividingWithLargeDivisor() { + NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X), T(x64:[ 3, 4, 5, 6 &+ 1 << 63] as X), T(0), T(x64:[1, 2, 3, 4 + 1 << 63] as X)) + NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X), T(x64:[ 2, 3, 4, 5 &+ 1 << 63] as X), T(0), T(x64:[1, 2, 3, 4 + 1 << 63] as X)) + NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X), T(x64:[ 1, 2, 3, 4 &+ 1 << 63] as X), T(1), T(x64:[0, 0, 0, 0] as X)) NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X), T(x64:[ 0, 1, 2, 3 &+ 1 << 63] as X), T(1), T(x64:[1, 1, 1, 1] as X)) NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X), T(x64:[~0, ~0, 0, 2 &+ 1 << 63] as X), T(1), T(x64:[2, 2, 2, 2] as X)) From 9d1ff06a9abbc9ae600d648919a9e7008d16d8b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Fri, 28 Jul 2023 13:09:33 +0200 Subject: [PATCH 023/133] NBKFlexibleWidthKit: Sign. --- .../NBKCoreKit/Swift+FloatingPointSign.swift | 219 ++++++++++++++++++ .../NBKFlexibleWidth+Complements.swift | 8 - .../NBKFlexibleWidth.swift | 21 +- .../Swift+FloatingPointSign.swift | 104 +++++++++ .../Swift+FloatingPointSign.swift | 87 +++++++ .../IntXL+Comparisons.swift | 22 +- .../Utilities/NBKAssert+Comparisons.swift | 7 + 7 files changed, 439 insertions(+), 29 deletions(-) create mode 100644 Sources/NBKCoreKit/Swift+FloatingPointSign.swift create mode 100644 Tests/NBKCoreKitBenchmarks/Swift+FloatingPointSign.swift create mode 100644 Tests/NBKCoreKitTests/Swift+FloatingPointSign.swift diff --git a/Sources/NBKCoreKit/Swift+FloatingPointSign.swift b/Sources/NBKCoreKit/Swift+FloatingPointSign.swift new file mode 100644 index 00000000..4aadef32 --- /dev/null +++ b/Sources/NBKCoreKit/Swift+FloatingPointSign.swift @@ -0,0 +1,219 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +//*============================================================================* +// MARK: * NBK x Swift x Floating Point Sign +//*============================================================================* + +extension Swift.FloatingPointSign { + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + /// Creates a new instance from the given `bit`. + /// + /// ``` + /// ┌────── → ──────────┐ + /// │ bit │ sign │ + /// ├────── → ───── = ──┤ + /// │ false │ plus │ 0 │ + /// │ true │ minus │ 1 │ + /// └────── → ───── = ──┘ + /// ``` + /// + @_transparent public init(_ bit: Bool) { + self = Swift.unsafeBitCast(bit, to: Self.self) + } + + //=------------------------------------------------------------------------= + // MARK: Accessors + //=------------------------------------------------------------------------= + + /// The `bit` representation of this value. + /// + /// ``` + /// ┌────────── → ──────┐ + /// │ sign │ bit │ + /// ├────── = ─ → ──────┤ + /// │ plus │ 0 │ false │ + /// │ minus │ 1 │ true │ + /// └────── = ─ → ──────┘ + /// ``` + /// + @_transparent public var bit: Bool { + Swift.unsafeBitCast(self, to: Bool.self) + } + + /// The `data` representation of this value. + /// + /// ``` + /// ┌────────── → ─────────┐ + /// │ sign │ data │ + /// ├────── = ─ → ─────────┤ + /// │ plus │ 0 │ UInt8(0) │ + /// │ minus │ 1 │ UInt8(1) │ + /// └────── = ─ → ─────────┘ + /// ``` + /// + @_transparent @usableFromInline var data: UInt8 { + Swift.unsafeBitCast(self, to: UInt8.self) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + /// Forms the opposite `sign`. + /// + /// ``` + /// ┌────────── → ──────────┐ + /// │ sign │ sign │ + /// ├────── = ─ → ───── = ──┤ + /// │ plus │ 0 │ minus │ 1 │ + /// │ minus │ 1 │ plus │ 0 │ + /// └────── = ─ → ───── = ──┘ + /// ``` + /// + @_transparent public mutating func toggle() { + self = ~self + } + + /// Returns the opposite `sign`. + /// + /// ``` + /// ┌────────── → ──────────┐ + /// │ sign │ sign │ + /// ├────── = ─ → ───── = ──┤ + /// │ plus │ 0 │ minus │ 1 │ + /// │ minus │ 1 │ plus │ 0 │ + /// └────── = ─ → ───── = ──┘ + /// ``` + /// + @_transparent public func toggled() -> Self { + ~self + } + + /// Returns the opposite `sign` of this value. + /// + /// ``` + /// ┌────────── → ──────────┐ + /// │ sign │ sign │ + /// ├────── = ─ → ───── = ──┤ + /// │ plus │ 0 │ minus │ 1 │ + /// │ minus │ 1 │ plus │ 0 │ + /// └────── = ─ → ───── = ──┘ + /// ``` + /// + @_transparent public static prefix func ~(sign: Self) -> Self { + sign ^ minus + } + + /// Forms the logical `AND` of `lhs` and `rhs`. + /// + /// ``` + /// ┌────────────────────── → ────────────┐ + /// │ lhs │ rhs │ lhs AND rhs │ + /// ├────── = ──┼────── = ─ → ───── = ────┤ + /// │ plus │ 0 │ plus │ 0 │ plus │ 0 │ + /// │ plus │ 0 │ minus │ 1 │ plus │ 0 │ + /// │ minus │ 1 │ plus │ 0 │ plus │ 0 │ + /// │ minus │ 1 │ minus │ 1 │ minus │ 1 │ + /// └────── = ─ → ────── = ─ → ──── = ────┘ + /// ``` + /// + @_transparent public static func &=(lhs: inout Self, rhs: Self) { + lhs = lhs & rhs + } + + /// Returns the logical `AND` of `lhs` and `rhs`. + /// + /// ``` + /// ┌────────────────────── → ────────────┐ + /// │ lhs │ rhs │ lhs AND rhs │ + /// ├────── = ──┼────── = ─ → ───── = ────┤ + /// │ plus │ 0 │ plus │ 0 │ plus │ 0 │ + /// │ plus │ 0 │ minus │ 1 │ plus │ 0 │ + /// │ minus │ 1 │ plus │ 0 │ plus │ 0 │ + /// │ minus │ 1 │ minus │ 1 │ minus │ 1 │ + /// └────── = ─ → ────── = ─ → ──── = ────┘ + /// ``` + /// + @_transparent public static func &(lhs: Self, rhs: Self) -> Self { + Swift.unsafeBitCast(lhs.data & rhs.data, to: Self.self) + } + + /// Forms the logical `OR` of `lhs` and `rhs`. + /// + /// ``` + /// ┌────────────────────── → ────────────┐ + /// │ lhs │ rhs │ lhs OR rhs │ + /// ├────── = ──┼────── = ─ → ───── = ────┤ + /// │ plus │ 0 │ plus │ 0 │ plus │ 0 │ + /// │ plus │ 0 │ minus │ 1 │ minus │ 1 │ + /// │ minus │ 1 │ plus │ 0 │ minus │ 1 │ + /// │ minus │ 1 │ minus │ 1 │ minus │ 1 │ + /// └────── = ─ → ────── = ─ → ──── = ────┘ + /// ``` + /// + @_transparent public static func |=(lhs: inout Self, rhs: Self) { + lhs = lhs | rhs + } + + /// Returns the logical `OR` of `lhs` and `rhs`. + /// + /// ``` + /// ┌────────────────────── → ────────────┐ + /// │ lhs │ rhs │ lhs OR rhs │ + /// ├────── = ──┼────── = ─ → ───── = ────┤ + /// │ plus │ 0 │ plus │ 0 │ plus │ 0 │ + /// │ plus │ 0 │ minus │ 1 │ minus │ 1 │ + /// │ minus │ 1 │ plus │ 0 │ minus │ 1 │ + /// │ minus │ 1 │ minus │ 1 │ minus │ 1 │ + /// └────── = ─ → ────── = ─ → ──── = ────┘ + /// ``` + /// + @_transparent public static func |(lhs: Self, rhs: Self) -> Self { + Swift.unsafeBitCast(lhs.data | rhs.data, to: Self.self) + } + + /// Forms the logical `XOR` of `lhs` and `rhs`. + /// + /// ``` + /// ┌────────────────────── → ────────────┐ + /// │ lhs │ rhs │ lhs XOR rhs │ + /// ├────── = ──┼────── = ─ → ───── = ────┤ + /// │ plus │ 0 │ plus │ 0 │ plus │ 0 │ + /// │ plus │ 0 │ minus │ 1 │ minus │ 1 │ + /// │ minus │ 1 │ plus │ 0 │ minus │ 1 │ + /// │ minus │ 1 │ minus │ 1 │ plus │ 0 │ + /// └────── = ─ → ────── = ─ → ──── = ────┘ + /// ``` + /// + @_transparent public static func ^=(lhs: inout Self, rhs: Self) { + lhs = lhs ^ rhs + } + + /// Returns the logical `XOR` of `lhs` and `rhs`. + /// + /// ``` + /// ┌────────────────────── → ────────────┐ + /// │ lhs │ rhs │ lhs XOR rhs │ + /// ├────── = ──┼────── = ─ → ───── = ────┤ + /// │ plus │ 0 │ plus │ 0 │ plus │ 0 │ + /// │ plus │ 0 │ minus │ 1 │ minus │ 1 │ + /// │ minus │ 1 │ plus │ 0 │ minus │ 1 │ + /// │ minus │ 1 │ minus │ 1 │ plus │ 0 │ + /// └────── = ─ → ────── = ─ → ──── = ────┘ + /// ``` + /// + @_transparent public static func ^(lhs: Self, rhs: Self) -> Self { + Swift.unsafeBitCast(lhs.data ^ rhs.data, to: Self.self) + } +} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements.swift index d250ee01..75432890 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements.swift @@ -15,14 +15,6 @@ import NBKCoreKit extension NBKFlexibleWidth { - //=------------------------------------------------------------------------= - // MARK: Details x Magnitude - //=------------------------------------------------------------------------= - - @inlinable public var magnitude: Magnitude { - self._magnitude - } - //=------------------------------------------------------------------------= // MARK: Details x Two's Complement //=------------------------------------------------------------------------= diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift index c593208b..da4fa2c4 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift @@ -21,8 +21,11 @@ import NBKCoreKit // MARK: State //=------------------------------------------------------------------------= - @usableFromInline var _signum: Int - @usableFromInline var _magnitude: Magnitude + /// The sign of this value. + public var sign: NBK.Sign + + /// The magnitude of this value. + public var magnitude: Magnitude //*========================================================================* // MARK: * Magnitude @@ -42,17 +45,17 @@ import NBKCoreKit // MARK: Initializers //=--------------------------------------------------------------------= - @inlinable init(unchecked: Storage) { - self.storage = unchecked - Swift.assert(self.storage.isNormal) - } - @inlinable init(storage: Storage) { self.storage = storage self.storage.normalize() Swift.assert(self.storage.isNormal) } + @inlinable init(unchecked: Storage) { + self.storage = unchecked + Swift.assert(self.storage.isNormal) + } + //*====================================================================* // MARK: * Storage //*====================================================================* @@ -75,9 +78,7 @@ import NBKCoreKit // MARK: Initializers //=----------------------------------------------------------------= - @inlinable init(elements: Elements) { - self.elements = elements - } + @inlinable init(elements: Elements) { self.elements = elements } } } } diff --git a/Tests/NBKCoreKitBenchmarks/Swift+FloatingPointSign.swift b/Tests/NBKCoreKitBenchmarks/Swift+FloatingPointSign.swift new file mode 100644 index 00000000..b9d5a435 --- /dev/null +++ b/Tests/NBKCoreKitBenchmarks/Swift+FloatingPointSign.swift @@ -0,0 +1,104 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if !DEBUG + +import NBKCoreKit +import XCTest + +//*============================================================================* +// MARK: * NBK x Swift x Floating Point Sign +//*============================================================================* + +final class SwiftBenchmarksOnFloatingPointSign: XCTestCase { + + typealias T = FloatingPointSign + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testToBit() { + var abc = NBK.blackHoleIdentity(T.plus ) + var xyz = NBK.blackHoleIdentity(T.minus) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.bit) + NBK.blackHole(xyz.bit) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testFromBit() { + var abc = NBK.blackHoleIdentity(true ) + var xyz = NBK.blackHoleIdentity(false) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(xyz)) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Transformations + //=------------------------------------------------------------------------= + + func testNot() { + var abc = NBK.blackHoleIdentity(T.plus ) + var xyz = NBK.blackHoleIdentity(T.minus) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(~abc) + NBK.blackHole(~xyz) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testAnd() { + var lhs = NBK.blackHoleIdentity(T.plus ) + var rhs = NBK.blackHoleIdentity(T.minus) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs & rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testOr() { + var lhs = NBK.blackHoleIdentity(T.plus ) + var rhs = NBK.blackHoleIdentity(T.minus) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs | rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testXor() { + var lhs = NBK.blackHoleIdentity(T.plus ) + var rhs = NBK.blackHoleIdentity(T.minus) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs ^ rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } +} + +#endif diff --git a/Tests/NBKCoreKitTests/Swift+FloatingPointSign.swift b/Tests/NBKCoreKitTests/Swift+FloatingPointSign.swift new file mode 100644 index 00000000..290f5a1c --- /dev/null +++ b/Tests/NBKCoreKitTests/Swift+FloatingPointSign.swift @@ -0,0 +1,87 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +import XCTest + +//*============================================================================* +// MARK: * NBK x Swift x Floating Point Sign +//*============================================================================* + +final class SwiftTestsOnFloatingPointSign: XCTestCase { + + typealias T = FloatingPointSign + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testBit() { + XCTAssertEqual(T(false), T.plus ) + XCTAssertEqual(T(true ), T.minus) + + XCTAssertEqual(T.plus .bit, false) + XCTAssertEqual(T.minus.bit, true ) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Transformations + //=------------------------------------------------------------------------= + + func testNot() { + XCTAssertEqual(~T.plus, T.minus) + XCTAssertEqual(~T.minus, T.plus ) + + XCTAssertEqual(T.plus .toggled(), T.minus) + XCTAssertEqual(T.minus.toggled(), T.plus ) + + XCTAssertEqual({ var x = T.plus; x.toggle(); return x }(), T.minus) + XCTAssertEqual({ var x = T.minus; x.toggle(); return x }(), T.plus ) + } + + func testAnd() { + XCTAssertEqual(T.plus & T.plus, T.plus ) + XCTAssertEqual(T.plus & T.minus, T.plus ) + XCTAssertEqual(T.minus & T.plus, T.plus ) + XCTAssertEqual(T.minus & T.minus, T.minus) + + XCTAssertEqual({ var x = T.plus; x &= T.plus; return x }(), T.plus ) + XCTAssertEqual({ var x = T.plus; x &= T.minus; return x }(), T.plus ) + XCTAssertEqual({ var x = T.minus; x &= T.plus; return x }(), T.plus ) + XCTAssertEqual({ var x = T.minus; x &= T.minus; return x }(), T.minus) + } + + func testOr() { + XCTAssertEqual(T.plus | T.plus, T.plus ) + XCTAssertEqual(T.plus | T.minus, T.minus) + XCTAssertEqual(T.minus | T.plus, T.minus) + XCTAssertEqual(T.minus | T.minus, T.minus) + + XCTAssertEqual({ var x = T.plus; x |= T.plus; return x }(), T.plus ) + XCTAssertEqual({ var x = T.plus; x |= T.minus; return x }(), T.minus) + XCTAssertEqual({ var x = T.minus; x |= T.plus; return x }(), T.minus) + XCTAssertEqual({ var x = T.minus; x |= T.minus; return x }(), T.minus) + } + + func testXor() { + XCTAssertEqual(T.plus ^ T.plus, T.plus ) + XCTAssertEqual(T.plus ^ T.minus, T.minus) + XCTAssertEqual(T.minus ^ T.plus, T.minus) + XCTAssertEqual(T.minus ^ T.minus, T.plus ) + + XCTAssertEqual({ var x = T.plus; x ^= T.plus; return x }(), T.plus ) + XCTAssertEqual({ var x = T.plus; x ^= T.minus; return x }(), T.minus) + XCTAssertEqual({ var x = T.minus; x ^= T.plus; return x }(), T.minus) + XCTAssertEqual({ var x = T.minus; x ^= T.minus; return x }(), T.plus ) + } +} + +#endif diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Comparisons.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Comparisons.swift index 02185233..39d74f78 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Comparisons.swift +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Comparisons.swift @@ -132,22 +132,12 @@ final class UIntXLTestsOnComparisons: XCTestCase { XCTAssertTrue (T(words:[ 0] as [UInt]).isEven) XCTAssertFalse(T(words:[ 1] as [UInt]).isEven) XCTAssertTrue (T(words:[ 2] as [UInt]).isEven) - + XCTAssertFalse(T(words:[~0] as [UInt]).isEven) XCTAssertTrue (T(words:[~1] as [UInt]).isEven) XCTAssertFalse(T(words:[~2] as [UInt]).isEven) } - func testSignum() { - XCTAssertEqual(T(words:[ 0] as [UInt]).signum(), Int(0)) - XCTAssertEqual(T(words:[ 1] as [UInt]).signum(), Int(1)) - XCTAssertEqual(T(words:[ 2] as [UInt]).signum(), Int(1)) - - XCTAssertEqual(T(words:[~0] as [UInt]).signum(), Int(1)) - XCTAssertEqual(T(words:[~1] as [UInt]).signum(), Int(1)) - XCTAssertEqual(T(words:[~2] as [UInt]).signum(), Int(1)) - } - func testIsPowerOf2() { XCTAssertFalse(T(words:[ 0] as [UInt]).isPowerOf2) XCTAssertTrue (T(words:[ 1] as [UInt]).isPowerOf2) @@ -167,6 +157,16 @@ final class UIntXLTestsOnComparisons: XCTestCase { XCTAssertFalse(T(words:[ 0, 0, 1, 1] as [UInt]).isPowerOf2) XCTAssertTrue (T(words:[ 0, 0, 0, 1] as [UInt]).isPowerOf2) } + + func testSignum() { + NBKAssertSignum(T(words:[ 0] as [UInt]), Int(0)) + NBKAssertSignum(T(words:[ 1] as [UInt]), Int(1)) + NBKAssertSignum(T(words:[ 2] as [UInt]), Int(1)) + + NBKAssertSignum(T(words:[~0] as [UInt]), Int(1)) + NBKAssertSignum(T(words:[~1] as [UInt]), Int(1)) + NBKAssertSignum(T(words:[~2] as [UInt]), Int(1)) + } } #endif diff --git a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Comparisons.swift b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Comparisons.swift index 381abc0a..e119ac16 100644 --- a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Comparisons.swift +++ b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Comparisons.swift @@ -15,6 +15,13 @@ import XCTest // MARK: * NBK x Assert x Comparisons //*============================================================================* +func NBKAssertSignum( +_ operand: T, _ signum: Int, +file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual(Int(operand.signum() as Int), signum, file: file, line: line) + XCTAssertEqual(Int(operand.signum() as T ), signum, file: file, line: line) // stdlib +} + func NBKAssertComparisons( _ lhs: T, _ rhs: T, _ signum: Int, file: StaticString = #file, line: UInt = #line) { From c15221fe0386bdc00f6a75d275466987363c16c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sat, 29 Jul 2023 10:33:08 +0200 Subject: [PATCH 024/133] NBKFlexibleWidthKit: IntXL. --- .../NBKCoreKit/Swift+FloatingPointSign.swift | 15 + .../NBKFlexibleWidth+Addition+Digit.swift | 18 +- .../NBKFlexibleWidth+Bits.swift | 30 +- .../NBKFlexibleWidth+Comparisons.swift | 37 ++- ...NBKFlexibleWidth+Complements+Storage.swift | 35 ++ .../NBKFlexibleWidth+Complements.swift | 22 +- .../NBKFlexibleWidth+Logic.swift | 2 +- .../NBKFlexibleWidth+Numbers+Storage.swift | 35 ++ .../NBKFlexibleWidth+Numbers.swift | 71 ++-- ....swift => NBKFlexibleWidth+Protocol.swift} | 19 +- .../NBKFlexibleWidth+Subtraction+Digit.swift | 20 +- .../NBKFlexibleWidth+Subtraction.swift | 20 +- .../NBKFlexibleWidth+Words.swift | 141 ++++++-- .../NBKFlexibleWidth.swift | 24 +- .../Swift+FloatingPointSign.swift | 5 + .../NBKFlexibleWidth.swift | 103 +++--- .../NBKFlexibleWidthKitTests/IntXL+Bits.swift | 104 ++++++ .../IntXL+Comparisons.swift | 218 +++++++++++++ .../IntXL+Complements.swift | 88 +++++ .../IntXL+Logic.swift | 33 ++ .../IntXL+Numbers.swift | 308 ++++++++++++++++-- .../IntXL+Words.swift | 67 ++++ Tests/NBKFlexibleWidthKitTests/IntXL.swift | 36 ++ .../NBKFlexibleWidth.swift | 103 +++--- .../Utilities/NBKAssert+Comparisons.swift | 4 +- .../Utilities/NBKAssert+Complements.swift | 40 +++ .../Utilities/NBKAssert+Identical.swift | 29 ++ .../Utilities/NBKAssert+Words.swift | 1 - 28 files changed, 1436 insertions(+), 192 deletions(-) create mode 100644 Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements+Storage.swift create mode 100644 Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers+Storage.swift rename Sources/NBKFlexibleWidthKit/{NBKFlexibleWidth+Negation.swift => NBKFlexibleWidth+Protocol.swift} (65%) create mode 100644 Tests/NBKFlexibleWidthKitTests/IntXL+Complements.swift create mode 100644 Tests/NBKFlexibleWidthKitTests/IntXL.swift create mode 100644 Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Complements.swift create mode 100644 Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Identical.swift diff --git a/Sources/NBKCoreKit/Swift+FloatingPointSign.swift b/Sources/NBKCoreKit/Swift+FloatingPointSign.swift index 4aadef32..66da6fd5 100644 --- a/Sources/NBKCoreKit/Swift+FloatingPointSign.swift +++ b/Sources/NBKCoreKit/Swift+FloatingPointSign.swift @@ -36,6 +36,21 @@ extension Swift.FloatingPointSign { // MARK: Accessors //=------------------------------------------------------------------------= + /// The `ascii` representation of this value. + /// + /// ``` + /// ┌────────── → ─────────────┐ + /// │ sign │ ascii │ + /// ├────── = ─ → ────── = ────┤ + /// │ plus │ 0 │ 43 │ "+" │ + /// │ minus │ 1 │ 45 │ "-" │ + /// └────── = ─ → ────── = ────┘ + /// ``` + /// + @_transparent public var ascii: UInt8 { + UInt8(ascii: self.bit ? "-" : "+") + } + /// The `bit` representation of this value. /// /// ``` diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift index 61668c62..f44ece4f 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift @@ -31,8 +31,24 @@ extension NBKFlexibleWidth { // MARK: Transformations //=------------------------------------------------------------------------= + #warning("tests") @_disfavoredOverload @inlinable public mutating func add(_ other: Int, at index: Int) { - fatalError("TODO") + //=--------------------------------------= + if self.sign == Sign(other.isLessThanZero) { + self.magnitude.add(other.magnitude, at: index) + return + } + //=--------------------------------------= + // TODO: func compared(to: Digit) + // TODO: Magnitude.init(digit, at: index) + let extended = Magnitude(digit: other.magnitude).bitshiftedLeft(by: index) + if self.magnitude >= extended { + self.magnitude.subtract(extended, at: Int.zero) + //=--------------------------------------= + } else { + self.sign.toggle() + self.magnitude = extended.subtracting(self.magnitude, at: Int.zero) + } } @_disfavoredOverload @inlinable public func adding(_ other: Int, at index: Int) -> Self { diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift index ed7e9c9c..1f4ecfb6 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift @@ -27,28 +27,45 @@ extension NBKFlexibleWidth { // MARK: Accessors //=------------------------------------------------------------------------= + /// The number of bits in ``words``. @inlinable public var bitWidth: Int { - fatalError("TODO") + self.magnitude.bitWidth + self.extraBitWidthInBitWidth } @inlinable public var nonzeroBitCount: Int { - fatalError("TODO") + if !self.isLessThanZero { + return self.magnitude.nonzeroBitCount + } + + var nonzeroBitCount = self.bitWidth + nonzeroBitCount &-= self.magnitude.nonzeroBitCount + nonzeroBitCount &-= self.magnitude.trailingZeroBitCount + return nonzeroBitCount &+ 1 as Int } @inlinable public var leadingZeroBitCount: Int { - fatalError("TODO") + self.isLessThanZero ? Int.zero : self.magnitude.leadingZeroBitCount + self.extraBitWidthInBitWidth } @inlinable public var trailingZeroBitCount: Int { - fatalError("TODO") + self.magnitude.trailingZeroBitCount } @inlinable public var mostSignificantBit: Bool { - fatalError("TODO") + self.isLessThanZero } @inlinable public var leastSignificantBit: Bool { - fatalError("TODO") + self.magnitude.leastSignificantBit + } + + //=------------------------------------------------------------------------= + // MARK: Utilities x Private + //=------------------------------------------------------------------------= + + /// The number of extra bits in `bitWidth` compared to `magnitude/bitWidth`. + @inlinable var extraBitWidthInBitWidth: Int { + self.wordsNeedsOneMoreWord ? UInt.bitWidth : Int.zero } } @@ -70,6 +87,7 @@ extension NBKFlexibleWidth.Magnitude { // MARK: Accessors //=------------------------------------------------------------------------= + /// The number of bits in ``words``. @inlinable public var bitWidth: Int { self.storage.elements.count * UInt.bitWidth } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift index 72972523..d8039997 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift @@ -20,27 +20,27 @@ extension NBKFlexibleWidth { //=------------------------------------------------------------------------= @inlinable public var isZero: Bool { - fatalError("TODO") + self.magnitude.isZero } @inlinable public var isLessThanZero: Bool { - fatalError("TODO") + self.sign != Sign.plus && !self.isZero } @inlinable public var isMoreThanZero: Bool { - fatalError("TODO") + self.sign == Sign.plus && !self.isZero } @inlinable public func signum() -> Int { - fatalError("TODO") + self.isZero ? 0 : self.sign == Sign.plus ? 1 : -1 } @inlinable public func signum() -> Self { - Self(digit: self.signum() as Digit) + Self(digit: self.signum() as Digit) } @inlinable public var isPowerOf2: Bool { - fatalError("TODO") + self.sign == Sign.plus && self.magnitude.isPowerOf2 } //=------------------------------------------------------------------------= @@ -48,7 +48,8 @@ extension NBKFlexibleWidth { //=------------------------------------------------------------------------= @inlinable public func hash(into hasher: inout Hasher) { - fatalError("TODO") + hasher.combine(self.sign == Sign.minus && self.isZero ? Sign.plus : self.sign) + hasher.combine(self.magnitude) } //=------------------------------------------------------------------------= @@ -64,11 +65,25 @@ extension NBKFlexibleWidth { } @inlinable public func compared(to other: Self) -> Int { - fatalError("TODO") + //=--------------------------------------= + if self.sign != other.sign { + if self.isZero && other.isZero { return 0 } + return self.sign == Sign.plus ? 1 : -1 + } + //=--------------------------------------= + let m = self.magnitude.compared(to: other.magnitude) + return self.sign == Sign.plus ? m : -(m) } @inlinable public func compared(to other: Self, at index: Int) -> Int { - fatalError("TODO") + //=--------------------------------------= + if self.sign != other.sign { + if self.isZero && other.isZero { return 0 } + return self.sign == Sign.plus ? 1 : -1 + } + //=--------------------------------------= + let m = self.magnitude.compared(to: other.magnitude, at: index) + return self.sign == Sign.plus ? m : -(m) } } @@ -160,6 +175,10 @@ extension NBKFlexibleWidth.Magnitude { // MARK: Utilities x Private //=------------------------------------------------------------------------= + /// A three-way comparison of `lhs` against `rhs`. + /// + /// - Requires: The last element in `lhs` and `rhs` must not be zero. + /// @inlinable static func compareWordsUnchecked(_ lhs: NBK.UnsafeWords, to rhs: NBK.UnsafeWords) -> Int { assert(lhs.last != 0 && rhs.last != 0) //=--------------------------------------= diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements+Storage.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements+Storage.swift new file mode 100644 index 00000000..90163c06 --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements+Storage.swift @@ -0,0 +1,35 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x Complements x Unsigned x Storage +//*============================================================================* + +extension NBKFlexibleWidth.Magnitude.Storage { + + //=------------------------------------------------------------------------= + // MARK: Details x Two's Complement + //=------------------------------------------------------------------------= + + @inlinable public mutating func formTwosComplement() { + _ = self.formTwosComplementSubsequence(true) + } + + @inlinable public mutating func formTwosComplementSubsequence(_ carry: Bool) -> Bool { + var carry = carry + + for index in self.elements.indices { + carry = self.elements[index].formTwosComplementSubsequence(carry) + } + + return carry as Bool + } +} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements.swift index 75432890..83a84564 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements.swift @@ -26,6 +26,21 @@ extension NBKFlexibleWidth { @inlinable public func twosComplement() -> Self { fatalError("TODO") } + + //=------------------------------------------------------------------------= + // MARK: Details x Additive Inverse + //=------------------------------------------------------------------------= + + @inlinable public mutating func negateReportingOverflow() -> Bool { + self.sign.toggle() + return false as Bool + } + + @inlinable public func negatedReportingOverflow() -> PVO { + var partialValue = self + let overflow = partialValue.negateReportingOverflow() + return PVO(partialValue, overflow) + } } //*============================================================================* @@ -38,11 +53,14 @@ extension NBKFlexibleWidth.Magnitude { // MARK: Details x Two's Complement //=------------------------------------------------------------------------= + #warning("tests") @inlinable public mutating func formTwosComplement() { - fatalError("TODO") + self.storage.formTwosComplement() + self.storage.normalize() } + #warning("tests") @inlinable public func twosComplement() -> Self { - fatalError("TODO") + var result = self; result.formTwosComplement(); return result } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift index 0897dff5..fff302b2 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift @@ -20,7 +20,7 @@ extension NBKFlexibleWidth { //=------------------------------------------------------------------------= @inlinable public static prefix func ~(x: Self) -> Self { - fatalError("TODO") + -(x + Int(1)) } //=------------------------------------------------------------------------= diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers+Storage.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers+Storage.swift new file mode 100644 index 00000000..d6aec5ef --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers+Storage.swift @@ -0,0 +1,35 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Numbers x Unsigned x Storage +//*============================================================================* + +extension NBKFlexibleWidth.Magnitude.Storage { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable init(truncating source: StaticBigInt) { + //=--------------------------------------= + let bitWidth = source.bitWidth + let major = NBK .quotientDividingByBitWidthAssumingIsAtLeastZero(bitWidth) + let minor = NBK.remainderDividingByBitWidthAssumingIsAtLeastZero(bitWidth) + let count = major + Int(bit: !minor.isZero) + //=--------------------------------------= + self = Self.uninitialized(count: count) { storage in + for index in storage.indices { + storage[index] = source[index] + } + } + } +} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift index 32398025..d5d72ade 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift @@ -16,7 +16,7 @@ import NBKCoreKit extension NBKFlexibleWidth { //=------------------------------------------------------------------------= - // MARK: Constants + // MARK: Initializers //=------------------------------------------------------------------------= public static let zero = Self(0) @@ -26,15 +26,24 @@ extension NBKFlexibleWidth { //=------------------------------------------------------------------------= @inlinable public init(digit: Int) { - fatalError("TODO") + let sign = digit.isLessThanZero + let magnitude = Magnitude(digit: digit.magnitude) + self.init(sign: Sign(sign), magnitude: magnitude) } //=------------------------------------------------------------------------= // MARK: Initializers x Literal //=------------------------------------------------------------------------= - @inlinable public init(integerLiteral value: StaticBigInt) { - fatalError("TODO") + @inlinable public init(integerLiteral source: StaticBigInt) { + let sourceIsLessThanZero = source.signum() == -1 + //=--------------------------------------= + self.init(sign: Sign.plus, magnitude: Magnitude(truncatingIntegerLiteral: source)) + //=--------------------------------------= + if sourceIsLessThanZero { + self.sign.toggle() + self.magnitude.formTwosComplement() + } } //=------------------------------------------------------------------------= @@ -42,19 +51,31 @@ extension NBKFlexibleWidth { //=------------------------------------------------------------------------= @inlinable public init(_ source: some BinaryInteger) { - fatalError("TODO") + //=--------------------------------------= + // Magnitude + //=--------------------------------------= + if let source = source as? Magnitude { + self.init(sign: Sign.plus, magnitude: source) + //=--------------------------------------= + // some BinaryInteger + //=--------------------------------------= + } else { + let sign = Sign(source < 0) + let magnitude = Magnitude(source.magnitude) + self.init(sign: sign, magnitude: magnitude) + } } @inlinable public init?(exactly source: some BinaryInteger) { - fatalError("TODO") + self.init(source) } @inlinable public init(clamping source: some BinaryInteger) { - fatalError("TODO") + self.init(source) } @inlinable public init(truncatingIfNeeded source: some BinaryInteger) { - fatalError("TODO") + self.init(source) } //=------------------------------------------------------------------------= @@ -68,6 +89,18 @@ extension NBKFlexibleWidth { @inlinable public init?(exactly source: some BinaryFloatingPoint) { fatalError("TODO") } + + //=------------------------------------------------------------------------= + // MARK: Initializers x Sign & Magnitude + //=------------------------------------------------------------------------= + + @inlinable public static func exactly(sign: FloatingPointSign, magnitude: Magnitude) -> Self { + Self(sign: sign, magnitude: magnitude) + } + + @inlinable public static func clamping(sign: FloatingPointSign, magnitude: Magnitude) -> Self { + Self(sign: sign, magnitude: magnitude) + } } //*============================================================================* @@ -103,20 +136,14 @@ extension NBKFlexibleWidth.Magnitude { } @inlinable init?(exactlyIntegerLiteral source: StaticBigInt) { - guard source.signum() >= 0 else { return nil } //=--------------------------------------= - let bitWidth = source.bitWidth - 1 - let major = NBK .quotientDividingByBitWidthAssumingIsAtLeastZero(bitWidth) - let minor = NBK.remainderDividingByBitWidthAssumingIsAtLeastZero(bitWidth) - let count = major + Int(bit: !minor.isZero) + if source.signum() == -1 { return nil } //=--------------------------------------= - let storage = Storage.uninitialized(count: count) { storage in - for index in storage.indices { - storage[index] = source[index] - } - } - - self.init(unchecked: storage) + self.init(truncatingIntegerLiteral: source) + } + + @inlinable init(truncatingIntegerLiteral source: StaticBigInt) { + self.init(storage: Storage(truncating: source)) } //=------------------------------------------------------------------------= @@ -176,11 +203,11 @@ extension NBKFlexibleWidth.Magnitude { // MARK: Initializers x Sign & Magnitude //=------------------------------------------------------------------------= - @inlinable public static func exactly(sign: FloatingPointSign, magnitude: Self) -> Self? { + @inlinable public static func exactly(sign: FloatingPointSign, magnitude: Magnitude) -> Self? { if sign == FloatingPointSign.plus || magnitude.isZero { return magnitude } else { return nil } } - @inlinable public static func clamping(sign: FloatingPointSign, magnitude: Self) -> Self { + @inlinable public static func clamping(sign: FloatingPointSign, magnitude: Magnitude) -> Self { if sign == FloatingPointSign.plus { return magnitude } else { return Self.zero } } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Negation.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Protocol.swift similarity index 65% rename from Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Negation.swift rename to Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Protocol.swift index c9444ada..6a0264aa 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Negation.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Protocol.swift @@ -9,22 +9,17 @@ import NBKCoreKit -// TODO: consider moving this to complements as the additive inverse +// TODO: consider a public NBKCoreKit/NBKFlexibleWidthInteger protocol +// TODO: consider a primary associated type similar to NBKCoreKit/NBKCoreInteger //*============================================================================* -// MARK: * NBK x Flexible Width x Negation x Signed +// MARK: * NBK x Flexible Width x Protocol //*============================================================================* -extension NBKFlexibleWidth { +public protocol IntXLOrUIntXL: NBKBinaryInteger { //=------------------------------------------------------------------------= - // MARK: Transformations + // MARK: Details x Comparisons //=------------------------------------------------------------------------= - - @inlinable public mutating func negateReportingOverflow() -> Bool { - fatalError("TODO") - } - - @inlinable public func negatedReportingOverflow() -> PVO { - fatalError("TODO") - } + + func compared(to other: Self, at index: Int) -> Int } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift index 681e86e8..a0e1aae8 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift @@ -51,20 +51,30 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @_disfavoredOverload @inlinable public static func -=(lhs: inout Self, rhs: UInt) { - let overflow: Bool = lhs.subtractReportingOverflow(rhs, at: Int.zero) - precondition(!overflow, NBK.callsiteOverflowInfo()) + lhs.subtract(rhs, at: Int.zero) } @_disfavoredOverload @inlinable public static func -(lhs: Self, rhs: UInt) -> Self { - let pvo: PVO = lhs.subtractingReportingOverflow(rhs, at: Int.zero) - precondition(!pvo.overflow, NBK.callsiteOverflowInfo()) - return pvo.partialValue as Self + lhs.subtracting(rhs, at: Int.zero) } //=------------------------------------------------------------------------= // MARK: Transformations //=------------------------------------------------------------------------= + #warning("tests") + @_disfavoredOverload @inlinable public mutating func subtract(_ other: UInt, at index: Int) { + let overflow: Bool = self.subtractReportingOverflow(other, at: index) + precondition(!overflow, NBK.callsiteOverflowInfo()) + } + + #warning("tests") + @_disfavoredOverload @inlinable public func subtracting(_ other: UInt, at index: Int) -> Self { + let pvo: PVO = self.subtractingReportingOverflow(other, at: index) + precondition(!pvo.overflow, NBK.callsiteOverflowInfo()) + return pvo.partialValue as Self + } + @_disfavoredOverload @inlinable public mutating func subtractReportingOverflow(_ other: UInt, at index: Int) -> Bool { defer { Swift.assert(self.storage.isNormal) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift index c3e64f57..3bf582d2 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift @@ -51,20 +51,30 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @inlinable public static func -=(lhs: inout Self, rhs: Self) { - let overflow: Bool = lhs.subtractReportingOverflow(rhs, at: Int.zero) - precondition(!overflow, NBK.callsiteOverflowInfo()) + lhs.subtract(rhs, at: Int.zero) } @inlinable public static func -(lhs: Self, rhs: Self) -> Self { - let pvo: PVO = lhs.subtractingReportingOverflow(rhs, at: Int.zero) - precondition(!pvo.overflow, NBK.callsiteOverflowInfo()) - return pvo.partialValue as Self + lhs.subtracting(rhs, at: Int.zero) } //=------------------------------------------------------------------------= // MARK: Transformations //=------------------------------------------------------------------------= + #warning("tests") + @inlinable public mutating func subtract(_ other: Self, at index: Int) { + let overflow: Bool = self.subtractReportingOverflow(other, at: index) + precondition(!overflow, NBK.callsiteOverflowInfo()) + } + + #warning("tests") + @inlinable public func subtracting(_ other: Self, at index: Int) -> Self { + let pvo: PVO = self.subtractingReportingOverflow(other, at: index) + precondition(!pvo.overflow, NBK.callsiteOverflowInfo()) + return pvo.partialValue as Self + } + @inlinable public mutating func subtractReportingOverflow(_ other: Self, at index: Int) -> Bool { defer { Swift.assert(self.storage.isNormal) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift index 442843d2..4cdb2acc 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift @@ -19,16 +19,119 @@ extension NBKFlexibleWidth { // MARK: Initializers //=------------------------------------------------------------------------= + /// Creates an instance from the given two's complement machine words. + /// + /// - Note: An empty collection defaults to positive zero. + /// @inlinable public init(words: some RandomAccessCollection) { - fatalError("TODO") + //=--------------------------------------= + // default to zero by nil coalescing + //=--------------------------------------= + let last = words.last ?? UInt() + //=--------------------------------------= + self.init(sign: Sign.plus, magnitude: Magnitude(words: words)) + //=--------------------------------------= + if last.mostSignificantBit { + self.sign.toggle() + self.magnitude.formTwosComplement() + } } //=------------------------------------------------------------------------= // MARK: Accessors //=------------------------------------------------------------------------= - @inlinable public var words: [UInt] { - fatalError("TODO") + @inlinable public var words: Words { + Words(source: self) + } + + //=------------------------------------------------------------------------= + // MARK: Utilities x Private + //=------------------------------------------------------------------------= + + @inlinable var wordsNeedsOneMoreWord: Bool { + self.magnitude.isZero || self.magnitude.mostSignificantBit + } + + //*========================================================================* + // MARK: * Words + //*========================================================================* + + @frozen public struct Words: RandomAccessCollection { + + //=--------------------------------------------------------------------= + // MARK: State + //=--------------------------------------------------------------------= + + public var count: Int + @usableFromInline let sign: UInt + @usableFromInline var storage: Magnitude.Storage + + //=--------------------------------------------------------------------= + // MARK: Initializers + //=--------------------------------------------------------------------= + + @inlinable init(source: NBKFlexibleWidth) { + self.count = Int(bit: source.wordsNeedsOneMoreWord) + self.sign = UInt(repeating: source.isLessThanZero) + self.storage = source.magnitude.storage + //=----------------------------------= + if !self.sign.isZero { + self.storage.formTwosComplement() + } + //=----------------------------------= + self.count += self.storage.elements.count + } + + //=--------------------------------------------------------------------= + // MARK: Accessors + //=--------------------------------------------------------------------= + + @inlinable public var startIndex: Int { + (0 as Int) + } + + @inlinable public var endIndex: Int { + self.count + } + + @inlinable public subscript(index: Int) -> UInt { + switch index < self.storage.elements.endIndex { + case true: return self.storage.elements[index] + case false: return self.sign } + } + + //=--------------------------------------------------------------------= + // MARK: Utilities + //=--------------------------------------------------------------------= + + @inlinable public func distance(from start: Int, to end: Int) -> Int { + self.storage.elements.distance(from: start, to: end) + } + + @inlinable public func index(after index: Int) -> Int { + self.storage.elements.index(after: index) + } + + @inlinable public func formIndex(after index: inout Int) { + self.storage.elements.formIndex(after: &index) + } + + @inlinable public func index(before index: Int) -> Int { + self.storage.elements.index(before: index) + } + + @inlinable public func formIndex(before index: inout Int) { + self.storage.elements.formIndex(before: &index) + } + + @inlinable public func index(_ index: Int, offsetBy distance: Int) -> Int { + self.storage.elements.index(index, offsetBy: distance) + } + + @inlinable public func index(_ index: Int, offsetBy distance: Int, limitedBy limit: Int) -> Int? { + self.storage.elements.index(index, offsetBy: distance, limitedBy: limit) + } } } @@ -53,7 +156,7 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @inlinable public var words: Words { - Words(magnitude: self) + Words(source: self) } //*========================================================================* @@ -66,14 +169,14 @@ extension NBKFlexibleWidth.Magnitude { // MARK: State //=--------------------------------------------------------------------= - @usableFromInline let magnitude: Magnitude + @usableFromInline let storage: Magnitude.Storage //=--------------------------------------------------------------------= // MARK: Initializers //=--------------------------------------------------------------------= - @inlinable init(magnitude: Magnitude) { - self.magnitude = magnitude + @inlinable init(source: Magnitude) { + self.storage = source.storage } //=--------------------------------------------------------------------= @@ -81,20 +184,20 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------------------------------------= @inlinable public var count: Int { - self.magnitude.storage.elements.count + self.storage.elements.count } @inlinable public var startIndex: Int { - self.magnitude.storage.elements.startIndex + (0 as Int) } @inlinable public var endIndex: Int { - self.magnitude.storage.elements.endIndex + self.count } @inlinable public subscript(index: Int) -> UInt { - switch index < self.magnitude.storage.elements.endIndex { - case true: return self.magnitude.storage.elements[index] + switch index < self.storage.elements.endIndex { + case true: return self.storage.elements[index] case false: return UInt.zero } } @@ -103,31 +206,31 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------------------------------------= @inlinable public func distance(from start: Int, to end: Int) -> Int { - self.magnitude.storage.elements.distance(from: start, to: end) + self.storage.elements.distance(from: start, to: end) } @inlinable public func index(after index: Int) -> Int { - self.magnitude.storage.elements.index(after: index) + self.storage.elements.index(after: index) } @inlinable public func formIndex(after index: inout Int) { - self.magnitude.storage.elements.formIndex(after: &index) + self.storage.elements.formIndex(after: &index) } @inlinable public func index(before index: Int) -> Int { - self.magnitude.storage.elements.index(before: index) + self.storage.elements.index(before: index) } @inlinable public func formIndex(before index: inout Int) { - self.magnitude.storage.elements.formIndex(before: &index) + self.storage.elements.formIndex(before: &index) } @inlinable public func index(_ index: Int, offsetBy distance: Int) -> Int { - self.magnitude.storage.elements.index(index, offsetBy: distance) + self.storage.elements.index(index, offsetBy: distance) } @inlinable public func index(_ index: Int, offsetBy distance: Int, limitedBy limit: Int) -> Int? { - self.magnitude.storage.elements.index(index, offsetBy: distance, limitedBy: limit) + self.storage.elements.index(index, offsetBy: distance, limitedBy: limit) } } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift index da4fa2c4..100cd9af 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift @@ -13,25 +13,43 @@ import NBKCoreKit // MARK: * NBK x Flexible Width //*============================================================================* -@frozen public struct NBKFlexibleWidth: NBKSignedInteger { +/// A signed, flexible-width, binary integer. +@frozen public struct NBKFlexibleWidth: NBKSignedInteger, IntXLOrUIntXL { public typealias Digit = Int + public typealias Sign = NBK.Sign + //=------------------------------------------------------------------------= // MARK: State //=------------------------------------------------------------------------= /// The sign of this value. - public var sign: NBK.Sign + public var sign: Sign /// The magnitude of this value. public var magnitude: Magnitude + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + @inlinable public init(sign: Sign, magnitude: Magnitude) { + self.sign = sign + self.magnitude = magnitude + } + //*========================================================================* // MARK: * Magnitude //*========================================================================* - @frozen public struct Magnitude: NBKUnsignedInteger { + /// An unsigned, flexible-width, binary integer. + /// + /// ### Logic + /// + /// - TODO: Comment on bitwise NOT, AND, OR, XOR semantics. + /// + @frozen public struct Magnitude: NBKUnsignedInteger, IntXLOrUIntXL { public typealias Digit = UInt diff --git a/Tests/NBKCoreKitTests/Swift+FloatingPointSign.swift b/Tests/NBKCoreKitTests/Swift+FloatingPointSign.swift index 290f5a1c..ad2ed9ef 100644 --- a/Tests/NBKCoreKitTests/Swift+FloatingPointSign.swift +++ b/Tests/NBKCoreKitTests/Swift+FloatingPointSign.swift @@ -24,6 +24,11 @@ final class SwiftTestsOnFloatingPointSign: XCTestCase { // MARK: Tests //=------------------------------------------------------------------------= + func testASCII() { + XCTAssertEqual(T.plus .ascii, UInt8(ascii: "+")) + XCTAssertEqual(T.minus.ascii, UInt8(ascii: "-")) + } + func testBit() { XCTAssertEqual(T(false), T.plus ) XCTAssertEqual(T(true ), T.minus) diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth.swift index b9734c3e..cbf880ce 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth.swift @@ -12,69 +12,88 @@ import NBKFlexibleWidthKit import XCTest //*============================================================================* -// MARK: * NBK x Flexible Width x Initializers x Unsigned +// MARK: * NBK x Flexible Width x Initializers x Signed //*============================================================================* -extension NBKFlexibleWidth.Magnitude { +extension NBKFlexibleWidth { //=------------------------------------------------------------------------= // MARK: Details x Limbs //=------------------------------------------------------------------------= init(x32 limbs: [UInt32]) { - self.init(limbs: limbs) + self.init(words: makeWords(limbs: limbs)) } init(x64 limbs: [UInt64]) { - self.init(limbs: limbs) + self.init(words: makeWords(limbs: limbs)) } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Initializers x Unsigned +//*============================================================================* + +extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= - // MARK: Details x Limbs x Private + // MARK: Details x Limbs //=------------------------------------------------------------------------= - private init(limbs: [Limb]) where Limb: NBKCoreInteger { - switch Limb.bitWidth >= UInt.bitWidth { - case true: self.init(majorLimbs: limbs) - case false: self.init(minorLimbs: limbs) } + init(x32 limbs: [UInt32]) { + self.init(words: makeWords(limbs: limbs)) } - private init(majorLimbs: [Limb]) where Limb: NBKCoreInteger { - precondition(Limb.bitWidth.isPowerOf2) - precondition(Limb.bitWidth >= UInt.bitWidth) - //=--------------------------------------= - let ratio = Limb.bitWidth / UInt.bitWidth - let count = majorLimbs.count * ratio - var words = [UInt](); words.reserveCapacity(count) - //=--------------------------------------= - for limb in majorLimbs { - words.append(contentsOf: limb.words) - } - //=--------------------------------------= - self.init(words: words) + init(x64 limbs: [UInt64]) { + self.init(words: makeWords(limbs: limbs)) } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Initializers x Algorithms +//*============================================================================* + +private func makeWords(limbs: [Limb]) -> [UInt] where Limb: NBKCoreInteger { + switch Limb.bitWidth >= UInt.bitWidth { + case true: return makeWords(majorLimbs: limbs) + case false: return makeWords(minorLimbs: limbs) } +} + +private func makeWords(majorLimbs: [Limb]) -> [UInt] where Limb: NBKCoreInteger { + precondition(Limb.bitWidth.isPowerOf2) + precondition(Limb.bitWidth >= UInt.bitWidth) + //=--------------------------------------= + let ratio = Limb.bitWidth / UInt.bitWidth + let count = majorLimbs.count * ratio + var words = [UInt](); words.reserveCapacity(count) + //=--------------------------------------= + for limb in majorLimbs { + words.append(contentsOf: limb.words) + } + //=--------------------------------------= + return words as [UInt] +} + +private func makeWords(minorLimbs: [Limb]) -> [UInt] where Limb: NBKCoreInteger { + precondition(Limb.bitWidth.isPowerOf2) + precondition(Limb.bitWidth <= UInt.bitWidth) + //=--------------------------------------= + let ratio = UInt.bitWidth / Limb.bitWidth + let count = minorLimbs.count / ratio + var words = [UInt](repeating: UInt.zero, count: count) + //=--------------------------------------= + var major = Int.zero + var minor = Int.zero - private init(minorLimbs: [Limb]) where Limb: NBKCoreInteger { - precondition(Limb.bitWidth.isPowerOf2) - precondition(Limb.bitWidth <= UInt.bitWidth) - //=--------------------------------------= - let ratio = UInt.bitWidth / Limb.bitWidth - let count = minorLimbs.count / ratio - var words = [UInt](repeating: UInt.zero, count: count) - //=--------------------------------------= - var major = Int.zero - var minor = Int.zero + for limb in minorLimbs { + words[major] |= UInt(truncatingIfNeeded: limb) &<< minor + minor += Limb.bitWidth - for limb in minorLimbs { - words[major] |= UInt(truncatingIfNeeded: limb) &<< minor - minor += Limb.bitWidth - - if minor >= UInt.bitWidth { - minor -= UInt.bitWidth - major += 1 - } + if minor >= UInt.bitWidth { + minor -= UInt.bitWidth + major += 1 } - //=--------------------------------------= - self.init(words: words) } + //=--------------------------------------= + return words as [UInt] } diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Bits.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Bits.swift index 2116af74..4293a058 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Bits.swift +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Bits.swift @@ -16,6 +16,110 @@ import XCTest private typealias X = [UInt64] private typealias Y = [UInt32] +//*============================================================================* +// MARK: * NBK x IntXL x Bits +//*============================================================================* + +final class IntXLTestsOnBits: XCTestCase { + + typealias T = IntXL + typealias M = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testInitBit() { + XCTAssertEqual(T(bit: false), T( )) + XCTAssertEqual(T(bit: true ), T(1)) + } + + func testBitWidth() { + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as [UInt]).bitWidth, UInt.bitWidth * 1) + XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as [UInt]).bitWidth, UInt.bitWidth * 1) + + XCTAssertEqual(T(sign: .plus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as [UInt])).bitWidth, UInt.bitWidth * 4) + XCTAssertEqual(T(sign: .minus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as [UInt])).bitWidth, UInt.bitWidth * 4) + XCTAssertEqual(T(sign: .plus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as [UInt])).bitWidth, UInt.bitWidth * 5) + XCTAssertEqual(T(sign: .minus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as [UInt])).bitWidth, UInt.bitWidth * 5) + } + + func testNonzeroBitCount() { + XCTAssertEqual(T(sign: .minus, magnitude: M.zero).nonzeroBitCount, 0) + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as [UInt]).nonzeroBitCount, 0) + XCTAssertEqual(T(words:[ 1, 1, 1, 1] as [UInt]).nonzeroBitCount, 4) + XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as [UInt]).nonzeroBitCount, UInt.bitWidth * 1) + + XCTAssertEqual(T(sign: .plus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as [UInt])).nonzeroBitCount, UInt.bitWidth * 4 - 1) + XCTAssertEqual(T(sign: .minus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as [UInt])).nonzeroBitCount, UInt.bitWidth * 0 + 2) + XCTAssertEqual(T(sign: .plus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as [UInt])).nonzeroBitCount, UInt.bitWidth * 0 + 1) + XCTAssertEqual(T(sign: .minus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as [UInt])).nonzeroBitCount, UInt.bitWidth * 1 + 1) + } + + func testLeadingZeroBitCount() { + XCTAssertEqual(T(sign: .minus, magnitude: M.zero).leadingZeroBitCount, UInt.bitWidth * 1) + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as [UInt]).leadingZeroBitCount, UInt.bitWidth * 1) + XCTAssertEqual(T(words:[ 1, 1, 1, 1] as [UInt]).leadingZeroBitCount, UInt.bitWidth * 1 - 1) + XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as [UInt]).leadingZeroBitCount, UInt.bitWidth * 0) + + XCTAssertEqual(T(words:[ 2, 0, 0, 0] as [UInt]).leadingZeroBitCount, UInt.bitWidth * 1 - 2) + XCTAssertEqual(T(words:[ 0, 2, 0, 0] as [UInt]).leadingZeroBitCount, UInt.bitWidth * 1 - 2) + XCTAssertEqual(T(words:[ 0, 0, 2, 0] as [UInt]).leadingZeroBitCount, UInt.bitWidth * 1 - 2) + XCTAssertEqual(T(words:[ 0, 0, 0, 2] as [UInt]).leadingZeroBitCount, UInt.bitWidth * 1 - 2) + + XCTAssertEqual(T(sign: .plus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as [UInt])).leadingZeroBitCount, UInt.bitWidth * 0 + 1) + XCTAssertEqual(T(sign: .minus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as [UInt])).leadingZeroBitCount, UInt.bitWidth * 0 + 0) + XCTAssertEqual(T(sign: .plus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as [UInt])).leadingZeroBitCount, UInt.bitWidth * 1 + 0) + XCTAssertEqual(T(sign: .minus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as [UInt])).leadingZeroBitCount, UInt.bitWidth * 0 + 0) + } + + func testTrailingZeroBitCount() { + XCTAssertEqual(T(sign: .minus, magnitude: M.zero).trailingZeroBitCount, UInt.bitWidth * 0) + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as [UInt]).trailingZeroBitCount, UInt.bitWidth * 0) + XCTAssertEqual(T(words:[ 1, 1, 1, 1] as [UInt]).trailingZeroBitCount, UInt.bitWidth * 0) + XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as [UInt]).trailingZeroBitCount, UInt.bitWidth * 0) + + XCTAssertEqual(T(words:[ 2, 0, 0, 0] as [UInt]).trailingZeroBitCount, UInt.bitWidth * 0 + 1) + XCTAssertEqual(T(words:[ 0, 2, 0, 0] as [UInt]).trailingZeroBitCount, UInt.bitWidth * 1 + 1) + XCTAssertEqual(T(words:[ 0, 0, 2, 0] as [UInt]).trailingZeroBitCount, UInt.bitWidth * 2 + 1) + XCTAssertEqual(T(words:[ 0, 0, 0, 2] as [UInt]).trailingZeroBitCount, UInt.bitWidth * 3 + 1) + } + + func testMostSignificantBit() { + XCTAssertEqual(T(sign: .minus, magnitude: M.zero).mostSignificantBit, false) + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as [UInt]).mostSignificantBit, false) + XCTAssertEqual(T(words:[ 1, 1, 1, 1] as [UInt]).mostSignificantBit, false) + XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as [UInt]).mostSignificantBit, true ) + + XCTAssertEqual(T(words:[~0, 0, 0, 0] as [UInt]).mostSignificantBit, false) + XCTAssertEqual(T(words:[ 0, ~0, 0, 0] as [UInt]).mostSignificantBit, false) + XCTAssertEqual(T(words:[ 0, 0, ~0, 0] as [UInt]).mostSignificantBit, false) + XCTAssertEqual(T(words:[ 0, 0, 0, ~0] as [UInt]).mostSignificantBit, true ) + + XCTAssertEqual(T(words:[~0, 1, 0, 0] as [UInt]).mostSignificantBit, false) + XCTAssertEqual(T(words:[ 0, ~0, 1, 0] as [UInt]).mostSignificantBit, false) + XCTAssertEqual(T(words:[ 0, 0, ~0, 1] as [UInt]).mostSignificantBit, false) + XCTAssertEqual(T(words:[ 1, 0, 0, ~0] as [UInt]).mostSignificantBit, true ) + } + + func testLeastSignificantBit() { + XCTAssertEqual(T(sign: .minus, magnitude: M.zero).leastSignificantBit, false) + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as [UInt]).leastSignificantBit, false) + XCTAssertEqual(T(words:[ 1, 1, 1, 1] as [UInt]).leastSignificantBit, true ) + XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as [UInt]).leastSignificantBit, true ) + + XCTAssertEqual(T(words:[~0, 0, 0, 0] as [UInt]).leastSignificantBit, true ) + XCTAssertEqual(T(words:[ 0, ~0, 0, 0] as [UInt]).leastSignificantBit, false) + XCTAssertEqual(T(words:[ 0, 0, ~0, 0] as [UInt]).leastSignificantBit, false) + XCTAssertEqual(T(words:[ 0, 0, 0, ~0] as [UInt]).leastSignificantBit, false) + + XCTAssertEqual(T(words:[~0, 1, 0, 0] as [UInt]).leastSignificantBit, true ) + XCTAssertEqual(T(words:[ 0, ~0, 1, 0] as [UInt]).leastSignificantBit, false) + XCTAssertEqual(T(words:[ 0, 0, ~0, 1] as [UInt]).leastSignificantBit, false) + XCTAssertEqual(T(words:[ 1, 0, 0, ~0] as [UInt]).leastSignificantBit, true ) + } +} + //*============================================================================* // MARK: * NBK x UIntXL x Bits //*============================================================================* diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Comparisons.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Comparisons.swift index 39d74f78..88c8e954 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Comparisons.swift +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Comparisons.swift @@ -16,6 +16,223 @@ import XCTest private typealias X = [UInt64] private typealias Y = [UInt32] +//*============================================================================* +// MARK: * NBK x IntXL x Comparisons +//*============================================================================* + +final class IntXLTestsOnComparisons: XCTestCase { + + typealias T = IntXL + typealias M = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testHashing() { + var union = Set() + union.insert(T(sign: .minus, magnitude: M())) + union.insert(T(sign: .minus, magnitude: M())) + union.insert(T(words:[0, 0, 0, 0] as [UInt])) + union.insert(T(words:[0, 0, 0, 0] as [UInt])) + union.insert(T(words:[1, 0, 0, 0] as [UInt])) + union.insert(T(words:[1, 0, 0, 0] as [UInt])) + union.insert(T(words:[0, 1, 0, 0] as [UInt])) + union.insert(T(words:[0, 1, 0, 0] as [UInt])) + union.insert(T(words:[0, 0, 1, 0] as [UInt])) + union.insert(T(words:[0, 0, 1, 0] as [UInt])) + union.insert(T(words:[0, 0, 0, 1] as [UInt])) + union.insert(T(words:[0, 0, 0, 1] as [UInt])) + XCTAssertEqual(union.count, 5 as Int) + } + + func testComparisons() { + NBKAssertComparisons( T(0), T(0), Int(0)) + NBKAssertComparisons( T(0), -T(0), Int(0)) + NBKAssertComparisons(-T(0), T(0), Int(0)) + NBKAssertComparisons(-T(0), -T(0), Int(0)) + + NBKAssertComparisons( T(1), T(1), Int(0)) + NBKAssertComparisons( T(1), -T(1), Int(1)) + NBKAssertComparisons(-T(1), T(1), -Int(1)) + NBKAssertComparisons(-T(1), -T(1), Int(0)) + + NBKAssertComparisons( T(2), T(3), -Int(1)) + NBKAssertComparisons( T(2), -T(3), Int(1)) + NBKAssertComparisons(-T(2), T(3), -Int(1)) + NBKAssertComparisons(-T(2), -T(3), Int(1)) + + NBKAssertComparisons( T(3), T(2), Int(1)) + NBKAssertComparisons( T(3), -T(2), Int(1)) + NBKAssertComparisons(-T(3), T(2), -Int(1)) + NBKAssertComparisons(-T(3), -T(2), -Int(1)) + + NBKAssertComparisons(T(words:[0, 2, 3, 4] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), -Int(1)) + NBKAssertComparisons(T(words:[1, 0, 3, 4] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), -Int(1)) + NBKAssertComparisons(T(words:[1, 2, 0, 4] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), -Int(1)) + NBKAssertComparisons(T(words:[1, 2, 3, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), -Int(1)) + NBKAssertComparisons(T(words:[0, 2, 3, 4] as [UInt]), T(words:[0, 2, 3, 4] as [UInt]), Int(0)) + NBKAssertComparisons(T(words:[1, 0, 3, 4] as [UInt]), T(words:[1, 0, 3, 4] as [UInt]), Int(0)) + NBKAssertComparisons(T(words:[1, 2, 0, 4] as [UInt]), T(words:[1, 2, 0, 4] as [UInt]), Int(0)) + NBKAssertComparisons(T(words:[1, 2, 3, 0] as [UInt]), T(words:[1, 2, 3, 0] as [UInt]), Int(0)) + NBKAssertComparisons(T(words:[1, 2, 3, 4] as [UInt]), T(words:[0, 2, 3, 4] as [UInt]), Int(1)) + NBKAssertComparisons(T(words:[1, 2, 3, 4] as [UInt]), T(words:[1, 0, 3, 4] as [UInt]), Int(1)) + NBKAssertComparisons(T(words:[1, 2, 3, 4] as [UInt]), T(words:[1, 2, 0, 4] as [UInt]), Int(1)) + NBKAssertComparisons(T(words:[1, 2, 3, 4] as [UInt]), T(words:[1, 2, 3, 0] as [UInt]), Int(1)) + } + + func testComparisonsAtIndex() { + NBKAssertComparisonsAtIndex( T(0), T(0), Int(4), Int(0)) + NBKAssertComparisonsAtIndex( T(0), -T(0), Int(4), Int(0)) + NBKAssertComparisonsAtIndex(-T(0), T(0), Int(4), Int(0)) + NBKAssertComparisonsAtIndex(-T(0), -T(0), Int(4), Int(0)) + + NBKAssertComparisonsAtIndex( T(1), T(1), Int(4), -Int(1)) + NBKAssertComparisonsAtIndex( T(1), -T(1), Int(4), Int(1)) + NBKAssertComparisonsAtIndex(-T(1), T(1), Int(4), -Int(1)) + NBKAssertComparisonsAtIndex(-T(1), -T(1), Int(4), Int(1)) + + NBKAssertComparisonsAtIndex( T(2), T(3), Int(4), -Int(1)) + NBKAssertComparisonsAtIndex( T(2), -T(3), Int(4), Int(1)) + NBKAssertComparisonsAtIndex(-T(2), T(3), Int(4), -Int(1)) + NBKAssertComparisonsAtIndex(-T(2), -T(3), Int(4), Int(1)) + + NBKAssertComparisonsAtIndex( T(3), T(2), Int(4), -Int(1)) + NBKAssertComparisonsAtIndex( T(3), -T(2), Int(4), Int(1)) + NBKAssertComparisonsAtIndex(-T(3), T(2), Int(4), -Int(1)) + NBKAssertComparisonsAtIndex(-T(3), -T(2), Int(4), Int(1)) + + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(0), Int(0)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(1), Int(0)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(2), Int(0)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(3), Int(0)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(4), Int(0)) + + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(0), -Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(1), -Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(2), -Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(3), -Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(4), -Int(1)) + + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(0), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(1), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(2), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(3), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(4), Int(1)) + + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(0), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(1), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(2), Int(0)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(3), -Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(4), -Int(1)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testIsZero() { + XCTAssertTrue (T(sign: .plus, magnitude: M( )).isZero) + XCTAssertTrue (T(sign: .minus, magnitude: M( )).isZero) + + XCTAssertTrue (T(words:[ 0] as [UInt]).isZero) + XCTAssertFalse(T(words:[ 1] as [UInt]).isZero) + XCTAssertFalse(T(words:[ 2] as [UInt]).isZero) + + XCTAssertFalse(T(words:[~0] as [UInt]).isZero) + XCTAssertFalse(T(words:[~1] as [UInt]).isZero) + XCTAssertFalse(T(words:[~2] as [UInt]).isZero) + } + + func testIsLessThanZero() { + XCTAssertFalse(T(sign: .plus, magnitude: M( )).isLessThanZero) + XCTAssertFalse(T(sign: .minus, magnitude: M( )).isLessThanZero) + + XCTAssertFalse(T(words:[ 0] as [UInt]).isLessThanZero) + XCTAssertFalse(T(words:[ 1] as [UInt]).isLessThanZero) + XCTAssertFalse(T(words:[ 2] as [UInt]).isLessThanZero) + + XCTAssertTrue (T(words:[~0] as [UInt]).isLessThanZero) + XCTAssertTrue (T(words:[~1] as [UInt]).isLessThanZero) + XCTAssertTrue (T(words:[~2] as [UInt]).isLessThanZero) + } + + func testIsMoreThanZero() { + XCTAssertFalse(T(sign: .plus, magnitude: M( )).isMoreThanZero) + XCTAssertFalse(T(sign: .minus, magnitude: M( )).isMoreThanZero) + + XCTAssertFalse(T(words:[ 0] as [UInt]).isMoreThanZero) + XCTAssertTrue (T(words:[ 1] as [UInt]).isMoreThanZero) + XCTAssertTrue (T(words:[ 2] as [UInt]).isMoreThanZero) + + XCTAssertFalse(T(words:[~0] as [UInt]).isMoreThanZero) + XCTAssertFalse(T(words:[~1] as [UInt]).isMoreThanZero) + XCTAssertFalse(T(words:[~2] as [UInt]).isMoreThanZero) + } + + func testIsOdd() { + XCTAssertFalse(T(sign: .plus, magnitude: M( )).isOdd) + XCTAssertFalse(T(sign: .minus, magnitude: M( )).isOdd) + + XCTAssertFalse(T(words:[ 0] as [UInt]).isOdd) + XCTAssertTrue (T(words:[ 1] as [UInt]).isOdd) + XCTAssertFalse(T(words:[ 2] as [UInt]).isOdd) + + XCTAssertTrue (T(words:[~0] as [UInt]).isOdd) + XCTAssertFalse(T(words:[~1] as [UInt]).isOdd) + XCTAssertTrue (T(words:[~2] as [UInt]).isOdd) + } + + func testIsEven() { + XCTAssertTrue (T(sign: .plus, magnitude: M( )).isEven) + XCTAssertTrue (T(sign: .minus, magnitude: M( )).isEven) + + XCTAssertTrue (T(words:[ 0] as [UInt]).isEven) + XCTAssertFalse(T(words:[ 1] as [UInt]).isEven) + XCTAssertTrue (T(words:[ 2] as [UInt]).isEven) + + XCTAssertFalse(T(words:[~0] as [UInt]).isEven) + XCTAssertTrue (T(words:[~1] as [UInt]).isEven) + XCTAssertFalse(T(words:[~2] as [UInt]).isEven) + } + + func testIsPowerOf2() { + XCTAssertFalse(T(sign: .plus, magnitude: M( )).isPowerOf2) + XCTAssertFalse(T(sign: .minus, magnitude: M( )).isPowerOf2) + + XCTAssertFalse(T(words:[~3] as [UInt]).isPowerOf2) + XCTAssertFalse(T(words:[~2] as [UInt]).isPowerOf2) + XCTAssertFalse(T(words:[~1] as [UInt]).isPowerOf2) + XCTAssertFalse(T(words:[~0] as [UInt]).isPowerOf2) + XCTAssertFalse(T(words:[ 0] as [UInt]).isPowerOf2) + XCTAssertTrue (T(words:[ 1] as [UInt]).isPowerOf2) + XCTAssertTrue (T(words:[ 2] as [UInt]).isPowerOf2) + XCTAssertFalse(T(words:[ 3] as [UInt]).isPowerOf2) + + XCTAssertFalse(T(words:[ 0, 0, 0, 0] as [UInt]).isPowerOf2) + XCTAssertTrue (T(words:[ 1, 0, 0, 0] as [UInt]).isPowerOf2) + XCTAssertFalse(T(words:[ 1, 1, 0, 0] as [UInt]).isPowerOf2) + XCTAssertTrue (T(words:[ 0, 1, 0, 0] as [UInt]).isPowerOf2) + XCTAssertFalse(T(words:[ 0, 1, 1, 0] as [UInt]).isPowerOf2) + XCTAssertTrue (T(words:[ 0, 0, 1, 0] as [UInt]).isPowerOf2) + XCTAssertFalse(T(words:[ 0, 0, 1, 1] as [UInt]).isPowerOf2) + XCTAssertTrue (T(words:[ 0, 0, 0, 1] as [UInt]).isPowerOf2) + } + + func testSignum() { + NBKAssertSignum(T(sign: .plus, magnitude: M( )), Int( 0)) + NBKAssertSignum(T(sign: .minus, magnitude: M( )), Int( 0)) + + NBKAssertSignum(T(words:[ 0] as [UInt]), Int( 0)) + NBKAssertSignum(T(words:[ 1] as [UInt]), Int( 1)) + NBKAssertSignum(T(words:[ 2] as [UInt]), Int( 1)) + + NBKAssertSignum(T(words:[~0] as [UInt]), Int(-1)) + NBKAssertSignum(T(words:[~1] as [UInt]), Int(-1)) + NBKAssertSignum(T(words:[~2] as [UInt]), Int(-1)) + } +} + //*============================================================================* // MARK: * NBK x UIntXL x Comparisons //*============================================================================* @@ -23,6 +240,7 @@ private typealias Y = [UInt32] final class UIntXLTestsOnComparisons: XCTestCase { typealias T = UIntXL + typealias M = UIntXL //=------------------------------------------------------------------------= // MARK: Tests diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Complements.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Complements.swift new file mode 100644 index 00000000..f16f9eab --- /dev/null +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Complements.swift @@ -0,0 +1,88 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +import NBKFlexibleWidthKit +import XCTest + +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x IntXL x Complements +//*============================================================================* + +final class IntXLTestsOnComplements: XCTestCase { + + typealias T = IntXL + typealias M = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests x Magnitude + //=------------------------------------------------------------------------= + + func testMagnitude() { + XCTAssertEqual(T(words:[ 1, 0, 0, 0] as [UInt]).magnitude, M(words:[ 1, 0, 0, 0] as [UInt])) + XCTAssertEqual(T(words:[~0, 0, 0, 0] as [UInt]).magnitude, M(words:[~0, 0, 0, 0] as [UInt])) + XCTAssertEqual(T(words:[ 1, 1, 1, 1] as [UInt]).magnitude, M(words:[ 1, 1, 1, 1] as [UInt])) + XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as [UInt]).magnitude, M(words:[ 1, 0, 0, 0] as [UInt])) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Two's Complement + //=------------------------------------------------------------------------= + + func testTwosComplement() { + // TODO: (!) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Additive Inverse + //=------------------------------------------------------------------------= + + func testAdditiveInverse() { + NBKAssertAdditiveInverse(T(sign: .plus, magnitude: M( )), T(sign: .minus, magnitude: M( ))) + NBKAssertAdditiveInverse(T(sign: .minus, magnitude: M( )), T(sign: .plus, magnitude: M( ))) + NBKAssertAdditiveInverse(T(sign: .plus, magnitude: M(1)), T(sign: .minus, magnitude: M(1))) + NBKAssertAdditiveInverse(T(sign: .minus, magnitude: M(1)), T(sign: .plus, magnitude: M(1))) + } +} + +//*============================================================================* +// MARK: * NBK x UIntXL x Complements +//*============================================================================* + +final class UIntXLTestsOnComplements: XCTestCase { + + typealias T = UIntXL + typealias M = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests x Magnitude + //=------------------------------------------------------------------------= + + func testMagnitude() { + XCTAssertEqual(T(words:[ 1, 0, 0, 0] as [UInt]).magnitude, M(words:[ 1, 0, 0, 0] as [UInt])) + XCTAssertEqual(T(words:[~0, 0, 0, 0] as [UInt]).magnitude, M(words:[~0, 0, 0, 0] as [UInt])) + XCTAssertEqual(T(words:[ 1, 1, 1, 1] as [UInt]).magnitude, M(words:[ 1, 1, 1, 1] as [UInt])) + XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as [UInt]).magnitude, M(words:[~0, ~0, ~0, ~0] as [UInt])) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Two's Complement + //=------------------------------------------------------------------------= + + func testTwosComplement() { + // TODO: (!) + } +} + +#endif diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Logic.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Logic.swift index aac2b96c..e923c073 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Logic.swift +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Logic.swift @@ -16,6 +16,39 @@ import XCTest private typealias X = [UInt64] private typealias Y = [UInt32] +//*============================================================================* +// MARK: * NBK x IntXL x Logic +//*============================================================================* + +final class IntXLTestsOnLogic: XCTestCase { + + typealias T = IntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testNot() { + NBKAssertNot(T(words:[ 0, 0, 0, 0] as [UInt]), T(words:[~0, ~0, ~0, ~0] as [UInt])) + NBKAssertNot(T(words:[~0, ~0, ~0, ~0] as [UInt]), T(words:[ 0, 0, 0, 0] as [UInt])) + + NBKAssertNot(T(words:[ 0, 1, 2, 3] as [UInt]), T(words:[~0, ~1, ~2, ~3] as [UInt])) + NBKAssertNot(T(words:[~0, ~1, ~2, ~3] as [UInt]), T(words:[ 0, 1, 2, 3] as [UInt])) + } + + func testAnd() { + // TODO: (!) + } + + func testOr() { + // TODO: (!) + } + + func testXor() { + // TODO: (!) + } +} + //*============================================================================* // MARK: * NBK x UIntXL x Logic //*============================================================================* diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Numbers.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Numbers.swift index 29f2d115..eba8cbe8 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Numbers.swift +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Numbers.swift @@ -20,8 +20,233 @@ private typealias Y = [UInt32] // MARK: * NBK x UIntXL x Numbers //*============================================================================* +final class IntXLTestsOnNumbers: XCTestCase { + + typealias S = IntXL + typealias T = IntXL + typealias M = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testZero() { + XCTAssertEqual(T( 0), T(words:[0])) + XCTAssertEqual(T.zero, T(words:[0])) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Int + //=------------------------------------------------------------------------= + + func testToInt() { + NBKAssertNumbers(from: T(words:[ 1, 0, 0, 0] as [UInt]), default: Int( 1)) + NBKAssertNumbers(from: T(words:[~0, 0, 0, 0] as [UInt]), exactly: nil, clamping: Int.max, truncating: -1) + NBKAssertNumbers(from: T(words:[ 1, 1, 1, 1] as [UInt]), exactly: nil, clamping: Int.max, truncating: 1) + NBKAssertNumbers(from: T(words:[~0, ~0, ~0, ~0] as [UInt]), default: Int(-1)) + } + + func testFromInt() { + NBKAssertNumbers(from: Int.min, default: ~T(words:[UInt(Int.max), 0, 0, 0] as [UInt])) + NBKAssertNumbers(from: Int.max, default: T(words:[UInt(Int.max), 0, 0, 0] as [UInt])) + } + + func testFromIntAsDigit() { + NBKAssertNumbers(from: T(digit: Int.min), default: ~T(words:[UInt(Int.max), 0, 0, 0] as [UInt])) + NBKAssertNumbers(from: T(digit: Int.max), default: T(words:[UInt(Int.max), 0, 0, 0] as [UInt])) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Int32 + //=------------------------------------------------------------------------= + + func testToInt32() { + NBKAssertNumbers(from: T(x32:[ 1, 0, 0, 0] as Y), default: Int32( 1)) + NBKAssertNumbers(from: T(x32:[~0, 0, 0, 0] as Y), exactly: nil, clamping: Int32.max, truncating: -1) + NBKAssertNumbers(from: T(x32:[ 1, 1, 1, 1] as Y), exactly: nil, clamping: Int32.max, truncating: 1) + NBKAssertNumbers(from: T(x32:[~0, ~0, ~0, ~0] as Y), default: Int32(-1)) + } + + func testFromInt32() { + NBKAssertNumbers(from: Int32.min, default: T(words: Int32.min.words)) + NBKAssertNumbers(from: Int32.max, default: T(words: Int32.max.words)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Int64 + //=------------------------------------------------------------------------= + + func testToInt64() { + NBKAssertNumbers(from: T(x64:[ 1, 0, 0, 0] as X), default: Int64( 1)) + NBKAssertNumbers(from: T(x64:[~0, 0, 0, 0] as X), exactly: nil, clamping: Int64.max, truncating: -1) + NBKAssertNumbers(from: T(x64:[ 1, 1, 1, 1] as X), exactly: nil, clamping: Int64.max, truncating: 1) + NBKAssertNumbers(from: T(x64:[~0, ~0, ~0, ~0] as X), default: Int64(-1)) + } + + func testFromInt64() { + NBKAssertNumbers(from: Int64.min, default: T(words: Int64.min.words)) + NBKAssertNumbers(from: Int64.max, default: T(words: Int64.max.words)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x UInt + //=------------------------------------------------------------------------= + + func testToUInt() { + NBKAssertNumbers(from: T(words:[ 1, 0, 0, 0] as [UInt]), default: UInt( 1)) + NBKAssertNumbers(from: T(words:[~0, 0, 0, 0] as [UInt]), default: UInt.max) + NBKAssertNumbers(from: T(words:[ 1, 1, 1, 1] as [UInt]), exactly: nil, clamping: ~0, truncating: UInt( 1)) + NBKAssertNumbers(from: T(words:[~0, ~0, ~0, ~0] as [UInt]), exactly: nil, clamping: 0, truncating: UInt.max) + } + + func testFromUInt() { + NBKAssertNumbers(from: UInt.min, default: T(sign: .plus, magnitude: M(words: UInt.min.words))) + NBKAssertNumbers(from: UInt.max, default: T(sign: .plus, magnitude: M(words: UInt.max.words))) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x UInt32 + //=------------------------------------------------------------------------= + + func testToUInt32() { + NBKAssertNumbers(from: T(x32:[ 1, 0, 0, 0] as Y), default: UInt32( 1)) + NBKAssertNumbers(from: T(x32:[~0, 0, 0, 0] as Y), default: UInt32.max) + NBKAssertNumbers(from: T(x32:[ 1, 1, 1, 1] as Y), exactly: nil, clamping: ~0, truncating: UInt32( 1)) + NBKAssertNumbers(from: T(x32:[~0, ~0, ~0, ~0] as Y), exactly: nil, clamping: 0, truncating: UInt32.max) + } + + func testFromUInt32() { + NBKAssertNumbers(from: UInt32.min, default: T(sign: .plus, magnitude: M(words: UInt32.min.words))) + NBKAssertNumbers(from: UInt32.max, default: T(sign: .plus, magnitude: M(words: UInt32.max.words))) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x UInt64 + //=------------------------------------------------------------------------= + + func testToUInt64() { + NBKAssertNumbers(from: T(x64:[ 1, 0, 0, 0] as X), default: UInt64( 1)) + NBKAssertNumbers(from: T(x64:[~0, 0, 0, 0] as X), default: UInt64.max) + NBKAssertNumbers(from: T(x64:[ 1, 1, 1, 1] as X), exactly: nil, clamping: ~0, truncating: UInt64( 1)) + NBKAssertNumbers(from: T(x64:[~0, ~0, ~0, ~0] as X), exactly: nil, clamping: 0, truncating: UInt64.max) + } + + func testFromUInt64() { + NBKAssertNumbers(from: UInt64.min, default: T(sign: .plus, magnitude: M(words: UInt64.min.words))) + NBKAssertNumbers(from: UInt64.max, default: T(sign: .plus, magnitude: M(words: UInt64.max.words))) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Signitude + //=------------------------------------------------------------------------= + + func testToSignitude() { + NBKAssertNumbers(from: T(words:[ 1, 0, 0, 0] as [UInt]), default: S(words:[ 1, 0, 0, 0] as [UInt])) + NBKAssertNumbers(from: T(words:[~0, 0, 0, 0] as [UInt]), default: S(words:[~0, 0, 0, 0] as [UInt])) + NBKAssertNumbers(from: T(words:[ 1, 1, 1, 1] as [UInt]), default: S(words:[ 1, 1, 1, 1] as [UInt])) + NBKAssertNumbers(from: T(words:[~0, ~0, ~0, ~0] as [UInt]), default: S(words:[~0, ~0, ~0, ~0] as [UInt])) + } + + func testFromSignitude() { + NBKAssertNumbers(from: S(words:[ 1, 0, 0, 0] as [UInt]), default: T(words:[ 1, 0, 0, 0] as [UInt])) + NBKAssertNumbers(from: S(words:[~0, 0, 0, 0] as [UInt]), default: T(words:[~0, 0, 0, 0] as [UInt])) + NBKAssertNumbers(from: S(words:[ 1, 1, 1, 1] as [UInt]), default: T(words:[ 1, 1, 1, 1] as [UInt])) + NBKAssertNumbers(from: S(words:[~0, ~0, ~0, ~0] as [UInt]), default: T(words:[~0, ~0, ~0, ~0] as [UInt])) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Magnitude + //=------------------------------------------------------------------------= + + func testToMagnitude() { + NBKAssertNumbers(from: T(words:[ 1, 0, 0, 0] as [UInt]), default: M(words:[ 1, 0, 0, 0] as [UInt])) + NBKAssertNumbers(from: T(words:[~0, 0, 0, 0] as [UInt]), default: M(words:[~0, 0, 0, 0] as [UInt])) + NBKAssertNumbers(from: T(words:[ 1, 1, 1, 1] as [UInt]), default: M(words:[ 1, 1, 1, 1] as [UInt])) + NBKAssertNumbers(from: T(words:[~0, ~0, ~0, ~0] as [UInt]), exactly: nil, clamping: M.zero, truncating: M(UInt.max)) + } + + func testFromMagnitude() { + NBKAssertNumbers(from: M(words:[ 1, 0, 0, 0] as [UInt]), default: T(words:[ 1, 0, 0, 0, 0] as [UInt])) + NBKAssertNumbers(from: M(words:[~0, 0, 0, 0] as [UInt]), default: T(words:[~0, 0, 0, 0, 0] as [UInt])) + NBKAssertNumbers(from: M(words:[ 1, 1, 1, 1] as [UInt]), default: T(words:[ 1, 1, 1, 1, 0] as [UInt])) + NBKAssertNumbers(from: M(words:[~0, ~0, ~0, ~0] as [UInt]), default: T(words:[~0, ~0, ~0, ~0, 0] as [UInt])) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Float32 + //=------------------------------------------------------------------------= + + func testToFloat32() { + // TODO: (!) + } + + func testFromFloat32() { + // TODO: (!) + } + + func testFromFloat32ValuesThatAreSpecial() { + // TODO: (!) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Float64 + //=------------------------------------------------------------------------= + + func testToFloat64() { + // TODO: (!) + } + + func testFromFloat64() { + // TODO: (!) + } + + func testFromFloat64ValuesThatAreSpecial() { + // TODO: (!) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Sign & Magnitude + //=------------------------------------------------------------------------= + + func testsFromSignAndMagnitude() { + NBKAssertIdentical(T.exactly (sign: .plus, magnitude: M(1)), T(1)) + NBKAssertIdentical(T.clamping(sign: .plus, magnitude: M(1)), T(1)) + + NBKAssertIdentical(T.exactly (sign: .minus, magnitude: M(1)), -T(1)) + NBKAssertIdentical(T.clamping(sign: .minus, magnitude: M(1)), -T(1)) + } + + func testsFromSignAndMagnitudeAsPlusMinusZero() { + NBKAssertIdentical(T.exactly (sign: .plus, magnitude: M( )), T( )) + NBKAssertIdentical(T.clamping(sign: .plus, magnitude: M( )), T( )) + + NBKAssertIdentical(T.exactly (sign: .minus, magnitude: M( )), -T( )) + NBKAssertIdentical(T.clamping(sign: .minus, magnitude: M( )), -T( )) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Literal + //=------------------------------------------------------------------------= + + func testFromLiteral() { + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as [UInt]), 0) + XCTAssertEqual(T(words:[~0, 0, 0, 0] as [UInt]), 18446744073709551615) + XCTAssertEqual(T(words:[~0, ~0, 0, 0] as [UInt]), 340282366920938463463374607431768211455) + XCTAssertEqual(T(words:[~0, ~0, ~0, 0] as [UInt]), 6277101735386680763835789423207666416102355444464034512895) + XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as [UInt]), -1) + XCTAssertEqual(T(words:[ 1, ~0, ~0, ~0] as [UInt]), -18446744073709551615) + XCTAssertEqual(T(words:[ 1, 0, ~0, ~0] as [UInt]), -340282366920938463463374607431768211455) + XCTAssertEqual(T(words:[ 1, 0, 0, ~0] as [UInt]), -6277101735386680763835789423207666416102355444464034512895) + } +} + +//*============================================================================* +// MARK: * NBK x UIntXL x Numbers +//*============================================================================* + final class UIntXLTestsOnNumbers: XCTestCase { + typealias S = IntXL typealias T = UIntXL typealias M = UIntXL @@ -55,10 +280,10 @@ final class UIntXLTestsOnNumbers: XCTestCase { //=------------------------------------------------------------------------= func testToInt32() { - NBKAssertNumbers(from: T(x32: [ 1, 0, 0, 0] as Y), default: Int32( 1)) - NBKAssertNumbers(from: T(x32: [~0, 0, 0, 0] as Y), exactly: nil, clamping: Int32.max, truncating: -1) - NBKAssertNumbers(from: T(x32: [ 1, 1, 1, 1] as Y), exactly: nil, clamping: Int32.max, truncating: 1) - NBKAssertNumbers(from: T(x32: [~0, ~0, ~0, ~0] as Y), exactly: nil, clamping: Int32.max, truncating: -1) + NBKAssertNumbers(from: T(x32:[ 1, 0, 0, 0] as Y), default: Int32( 1)) + NBKAssertNumbers(from: T(x32:[~0, 0, 0, 0] as Y), exactly: nil, clamping: Int32.max, truncating: -1) + NBKAssertNumbers(from: T(x32:[ 1, 1, 1, 1] as Y), exactly: nil, clamping: Int32.max, truncating: 1) + NBKAssertNumbers(from: T(x32:[~0, ~0, ~0, ~0] as Y), exactly: nil, clamping: Int32.max, truncating: -1) } func testFromInt32() { @@ -71,10 +296,10 @@ final class UIntXLTestsOnNumbers: XCTestCase { //=------------------------------------------------------------------------= func testToInt64() { - NBKAssertNumbers(from: T(x64: [ 1, 0, 0, 0] as X), default: Int64( 1)) - NBKAssertNumbers(from: T(x64: [~0, 0, 0, 0] as X), exactly: nil, clamping: Int64.max, truncating: -1) - NBKAssertNumbers(from: T(x64: [ 1, 1, 1, 1] as X), exactly: nil, clamping: Int64.max, truncating: 1) - NBKAssertNumbers(from: T(x64: [~0, ~0, ~0, ~0] as X), exactly: nil, clamping: Int64.max, truncating: -1) + NBKAssertNumbers(from: T(x64:[ 1, 0, 0, 0] as X), default: Int64( 1)) + NBKAssertNumbers(from: T(x64:[~0, 0, 0, 0] as X), exactly: nil, clamping: Int64.max, truncating: -1) + NBKAssertNumbers(from: T(x64:[ 1, 1, 1, 1] as X), exactly: nil, clamping: Int64.max, truncating: 1) + NBKAssertNumbers(from: T(x64:[~0, ~0, ~0, ~0] as X), exactly: nil, clamping: Int64.max, truncating: -1) } func testFromInt64() { @@ -99,8 +324,8 @@ final class UIntXLTestsOnNumbers: XCTestCase { } func testFromUIntAsDigit() { - XCTAssertEqual(T(digit: UInt.min), T(words:[UInt.min])) - XCTAssertEqual(T(digit: UInt.max), T(words:[UInt.max])) + XCTAssertEqual(T(digit: UInt.min), T(words:[UInt.min] as [UInt])) + XCTAssertEqual(T(digit: UInt.max), T(words:[UInt.max] as [UInt])) } //=------------------------------------------------------------------------= @@ -108,10 +333,10 @@ final class UIntXLTestsOnNumbers: XCTestCase { //=------------------------------------------------------------------------= func testToUInt32() { - NBKAssertNumbers(from: T(x32: [ 1, 0, 0, 0] as Y), default: UInt32( 1)) - NBKAssertNumbers(from: T(x32: [~0, 0, 0, 0] as Y), default: ~UInt32( 0)) - NBKAssertNumbers(from: T(x32: [ 1, 1, 1, 1] as Y), exactly: nil, clamping: UInt32.max, truncating: 1) - NBKAssertNumbers(from: T(x32: [~0, ~0, ~0, ~0] as Y), exactly: nil, clamping: UInt32.max, truncating: ~0) + NBKAssertNumbers(from: T(x32:[ 1, 0, 0, 0] as Y), default: UInt32( 1)) + NBKAssertNumbers(from: T(x32:[~0, 0, 0, 0] as Y), default: ~UInt32( 0)) + NBKAssertNumbers(from: T(x32:[ 1, 1, 1, 1] as Y), exactly: nil, clamping: UInt32.max, truncating: 1) + NBKAssertNumbers(from: T(x32:[~0, ~0, ~0, ~0] as Y), exactly: nil, clamping: UInt32.max, truncating: ~0) } func testFromUInt32() { @@ -123,11 +348,54 @@ final class UIntXLTestsOnNumbers: XCTestCase { // MARK: Tests x UInt64 //=------------------------------------------------------------------------= + func testToUInt64() { + NBKAssertNumbers(from: T(x64:[ 1, 0, 0, 0] as X), default: UInt64( 1)) + NBKAssertNumbers(from: T(x64:[~0, 0, 0, 0] as X), default: ~UInt64( 0)) + NBKAssertNumbers(from: T(x64:[ 1, 1, 1, 1] as X), exactly: nil, clamping: UInt64.max, truncating: 1) + NBKAssertNumbers(from: T(x64:[~0, ~0, ~0, ~0] as X), exactly: nil, clamping: UInt64.max, truncating: ~0) + } + func testFromUInt64() { NBKAssertNumbers(from: UInt64.min, default: T(words: UInt64.min.words)) NBKAssertNumbers(from: UInt64.max, default: T(words: UInt64.max.words)) } + //=------------------------------------------------------------------------= + // MARK: Tests x Signitude + //=------------------------------------------------------------------------= + + func testToSignitude() { + NBKAssertNumbers(from: T(words:[ 1, 0, 0, 0] as [UInt]), default: S(words:[ 1, 0, 0, 0, 0] as [UInt])) + NBKAssertNumbers(from: T(words:[~0, 0, 0, 0] as [UInt]), default: S(words:[~0, 0, 0, 0, 0] as [UInt])) + NBKAssertNumbers(from: T(words:[ 1, 1, 1, 1] as [UInt]), default: S(words:[ 1, 1, 1, 1, 0] as [UInt])) + NBKAssertNumbers(from: T(words:[~0, ~0, ~0, ~0] as [UInt]), default: S(words:[~0, ~0, ~0, ~0, 0] as [UInt])) + } + + func testFromSignitude() { + NBKAssertNumbers(from: S(words:[ 1, 0, 0, 0] as [UInt]), default: T(words:[ 1, 0, 0, 0, 0] as [UInt])) + NBKAssertNumbers(from: S(words:[~0, 0, 0, 0] as [UInt]), default: T(words:[~0, 0, 0, 0, 0] as [UInt])) + NBKAssertNumbers(from: S(words:[ 1, 1, 1, 1] as [UInt]), default: T(words:[ 1, 1, 1, 1, 0] as [UInt])) + NBKAssertNumbers(from: S(words:[~0, ~0, ~0, ~0] as [UInt]), exactly: nil, clamping: T.zero, truncating: T(UInt.max)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Magnitude + //=------------------------------------------------------------------------= + + func testToMagnitude() { + NBKAssertNumbers(from: T(words:[ 1, 0, 0, 0] as [UInt]), default: M(words:[ 1, 0, 0, 0] as [UInt])) + NBKAssertNumbers(from: T(words:[~0, 0, 0, 0] as [UInt]), default: M(words:[~0, 0, 0, 0] as [UInt])) + NBKAssertNumbers(from: T(words:[ 1, 1, 1, 1] as [UInt]), default: M(words:[ 1, 1, 1, 1] as [UInt])) + NBKAssertNumbers(from: T(words:[~0, ~0, ~0, ~0] as [UInt]), default: M(words:[~0, ~0, ~0, ~0] as [UInt])) + } + + func testFromMagnitude() { + NBKAssertNumbers(from: M(words:[ 1, 0, 0, 0] as [UInt]), default: T(words:[ 1, 0, 0, 0] as [UInt])) + NBKAssertNumbers(from: M(words:[~0, 0, 0, 0] as [UInt]), default: T(words:[~0, 0, 0, 0] as [UInt])) + NBKAssertNumbers(from: M(words:[ 1, 1, 1, 1] as [UInt]), default: T(words:[ 1, 1, 1, 1] as [UInt])) + NBKAssertNumbers(from: M(words:[~0, ~0, ~0, ~0] as [UInt]), default: T(words:[~0, ~0, ~0, ~0] as [UInt])) + } + //=------------------------------------------------------------------------= // MARK: Tests x Float32 //=------------------------------------------------------------------------= @@ -205,7 +473,7 @@ final class UIntXLTestsOnNumbers: XCTestCase { XCTAssertEqual(T.exactly (sign: .plus, magnitude: M( 1)), T( 1)) XCTAssertEqual(T.clamping(sign: .plus, magnitude: M( 1)), T( 1)) - XCTAssertEqual(T.exactly (sign: .minus, magnitude: M( 1)), nil) + XCTAssertEqual(T.exactly (sign: .minus, magnitude: M( 1)), nil) XCTAssertEqual(T.clamping(sign: .minus, magnitude: M( 1)), T( )) } @@ -222,11 +490,11 @@ final class UIntXLTestsOnNumbers: XCTestCase { //=------------------------------------------------------------------------= func testFromLiteral() { - XCTAssertEqual(T(x64: [ 0, 0, 0, 0] as X), 0) - XCTAssertEqual(T(x64: [~0, 0, 0, 0] as X), 18446744073709551615) - XCTAssertEqual(T(x64: [~0, ~0, 0, 0] as X), 340282366920938463463374607431768211455) - XCTAssertEqual(T(x64: [~0, ~0, ~0, 0] as X), 6277101735386680763835789423207666416102355444464034512895) - XCTAssertEqual(T(x64: [~0, ~0, ~0, ~0] as X), 115792089237316195423570985008687907853269984665640564039457584007913129639935) + XCTAssertEqual(T(x64:[ 0, 0, 0, 0] as X), 0) + XCTAssertEqual(T(x64:[~0, 0, 0, 0] as X), 18446744073709551615) + XCTAssertEqual(T(x64:[~0, ~0, 0, 0] as X), 340282366920938463463374607431768211455) + XCTAssertEqual(T(x64:[~0, ~0, ~0, 0] as X), 6277101735386680763835789423207666416102355444464034512895) + XCTAssertEqual(T(x64:[~0, ~0, ~0, ~0] as X), 115792089237316195423570985008687907853269984665640564039457584007913129639935) XCTAssertNil(T(exactlyIntegerLiteral: -1)) } diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Words.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Words.swift index 1ec31750..2d26075f 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Words.swift +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Words.swift @@ -16,6 +16,73 @@ import XCTest private typealias X = [UInt64] private typealias Y = [UInt32] +//*============================================================================* +// MARK: * NBK x IntXL x Words +//*============================================================================* + +final class IntXLTestsOnWords: XCTestCase { + + typealias T = IntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testWords() { + NBKAssertWords(T(words:[ ]), [0 ]) + NBKAssertWords(T(words:[1 ]), [1 ]) + NBKAssertWords(T(words:[1, 2 ]), [1, 2 ]) + NBKAssertWords(T(words:[1, 2, 3 ]), [1, 2, 3 ]) + NBKAssertWords(T(words:[1, 2, 3, 4]), [1, 2, 3, 4]) + + NBKAssertWords(T(words:[0, 0, 0, 0]), [0 ]) + NBKAssertWords(T(words:[1, 0, 0, 0]), [1 ]) + NBKAssertWords(T(words:[1, 2, 0, 0]), [1, 2 ]) + NBKAssertWords(T(words:[1, 2, 3, 0]), [1, 2, 3 ]) + NBKAssertWords(T(words:[1, 2, 3, 4]), [1, 2, 3, 4]) + } + + func testWordsX64() throws { + guard MemoryLayout.size == MemoryLayout.size else { throw XCTSkip() } + + NBKAssertWords(T(x64:[ ] as X), [0 ]) + NBKAssertWords(T(x64:[1 ] as X), [1 ]) + NBKAssertWords(T(x64:[1, 2 ] as X), [1, 2 ]) + NBKAssertWords(T(x64:[1, 2, 3 ] as X), [1, 2, 3 ]) + NBKAssertWords(T(x64:[1, 2, 3, 4] as X), [1, 2, 3, 4]) + + NBKAssertWords(T(x64:[0, 0, 0, 0] as X), [0 ]) + NBKAssertWords(T(x64:[1, 0, 0, 0] as X), [1 ]) + NBKAssertWords(T(x64:[1, 2, 0, 0] as X), [1, 2 ]) + NBKAssertWords(T(x64:[1, 2, 3, 0] as X), [1, 2, 3 ]) + NBKAssertWords(T(x64:[1, 2, 3, 4] as X), [1, 2, 3, 4]) + } + + func testWordsX32() throws { + guard MemoryLayout.size == MemoryLayout.size else { throw XCTSkip() } + + NBKAssertWords(T(x32:[ ] as Y), [0 ]) + NBKAssertWords(T(x32:[1 ] as Y), [1 ]) + NBKAssertWords(T(x32:[1, 2 ] as Y), [1, 2 ]) + NBKAssertWords(T(x32:[1, 2, 3 ] as Y), [1, 2, 3 ]) + NBKAssertWords(T(x32:[1, 2, 3, 4 ] as Y), [1, 2, 3, 4 ]) + NBKAssertWords(T(x32:[1, 2, 3, 4, 5 ] as Y), [1, 2, 3, 4, 5 ]) + NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6 ] as Y), [1, 2, 3, 4, 5, 6 ]) + NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6, 7 ] as Y), [1, 2, 3, 4, 5, 6, 7 ]) + NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6, 7, 8] as Y), [1, 2, 3, 4, 5, 6, 7, 8]) + + NBKAssertWords(T(x32:[0, 0, 0, 0, 0, 0, 0, 0] as Y), [0 ]) + NBKAssertWords(T(x32:[1, 0, 0, 0, 0, 0, 0, 0] as Y), [1 ]) + NBKAssertWords(T(x32:[1, 2, 0, 0, 0, 0, 0, 0] as Y), [1, 2 ]) + NBKAssertWords(T(x32:[1, 2, 3, 0, 0, 0, 0, 0] as Y), [1, 2, 3 ]) + NBKAssertWords(T(x32:[1, 2, 3, 4, 0, 0, 0, 0] as Y), [1, 2, 3, 4 ]) + NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 0, 0, 0] as Y), [1, 2, 3, 4, 5 ]) + NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6, 0, 0] as Y), [1, 2, 3, 4, 5, 6 ]) + NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6, 7, 0] as Y), [1, 2, 3, 4, 5, 6, 7 ]) + NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6, 7, 8] as Y), [1, 2, 3, 4, 5, 6, 7, 8]) + } +} + //*============================================================================* // MARK: * NBK x UIntXL x Words //*============================================================================* diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL.swift b/Tests/NBKFlexibleWidthKitTests/IntXL.swift new file mode 100644 index 00000000..ab998cf2 --- /dev/null +++ b/Tests/NBKFlexibleWidthKitTests/IntXL.swift @@ -0,0 +1,36 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKFlexibleWidthKit +import XCTest + +//*============================================================================* +// MARK: * NBK x IntXL +//*============================================================================* + +final class IntXLTests: XCTestCase { + + typealias T = IntXL + typealias M = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testSign() { + XCTAssertEqual(T(sign: .plus, magnitude: 0).sign, .plus ) + XCTAssertEqual(T(sign: .minus, magnitude: 0).sign, .minus) + XCTAssertEqual(T(sign: .plus, magnitude: 1).sign, .plus ) + XCTAssertEqual(T(sign: .minus, magnitude: 1).sign, .minus) + } +} + +#endif diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth.swift index b9734c3e..cbf880ce 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth.swift @@ -12,69 +12,88 @@ import NBKFlexibleWidthKit import XCTest //*============================================================================* -// MARK: * NBK x Flexible Width x Initializers x Unsigned +// MARK: * NBK x Flexible Width x Initializers x Signed //*============================================================================* -extension NBKFlexibleWidth.Magnitude { +extension NBKFlexibleWidth { //=------------------------------------------------------------------------= // MARK: Details x Limbs //=------------------------------------------------------------------------= init(x32 limbs: [UInt32]) { - self.init(limbs: limbs) + self.init(words: makeWords(limbs: limbs)) } init(x64 limbs: [UInt64]) { - self.init(limbs: limbs) + self.init(words: makeWords(limbs: limbs)) } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Initializers x Unsigned +//*============================================================================* + +extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= - // MARK: Details x Limbs x Private + // MARK: Details x Limbs //=------------------------------------------------------------------------= - private init(limbs: [Limb]) where Limb: NBKCoreInteger { - switch Limb.bitWidth >= UInt.bitWidth { - case true: self.init(majorLimbs: limbs) - case false: self.init(minorLimbs: limbs) } + init(x32 limbs: [UInt32]) { + self.init(words: makeWords(limbs: limbs)) } - private init(majorLimbs: [Limb]) where Limb: NBKCoreInteger { - precondition(Limb.bitWidth.isPowerOf2) - precondition(Limb.bitWidth >= UInt.bitWidth) - //=--------------------------------------= - let ratio = Limb.bitWidth / UInt.bitWidth - let count = majorLimbs.count * ratio - var words = [UInt](); words.reserveCapacity(count) - //=--------------------------------------= - for limb in majorLimbs { - words.append(contentsOf: limb.words) - } - //=--------------------------------------= - self.init(words: words) + init(x64 limbs: [UInt64]) { + self.init(words: makeWords(limbs: limbs)) } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Initializers x Algorithms +//*============================================================================* + +private func makeWords(limbs: [Limb]) -> [UInt] where Limb: NBKCoreInteger { + switch Limb.bitWidth >= UInt.bitWidth { + case true: return makeWords(majorLimbs: limbs) + case false: return makeWords(minorLimbs: limbs) } +} + +private func makeWords(majorLimbs: [Limb]) -> [UInt] where Limb: NBKCoreInteger { + precondition(Limb.bitWidth.isPowerOf2) + precondition(Limb.bitWidth >= UInt.bitWidth) + //=--------------------------------------= + let ratio = Limb.bitWidth / UInt.bitWidth + let count = majorLimbs.count * ratio + var words = [UInt](); words.reserveCapacity(count) + //=--------------------------------------= + for limb in majorLimbs { + words.append(contentsOf: limb.words) + } + //=--------------------------------------= + return words as [UInt] +} + +private func makeWords(minorLimbs: [Limb]) -> [UInt] where Limb: NBKCoreInteger { + precondition(Limb.bitWidth.isPowerOf2) + precondition(Limb.bitWidth <= UInt.bitWidth) + //=--------------------------------------= + let ratio = UInt.bitWidth / Limb.bitWidth + let count = minorLimbs.count / ratio + var words = [UInt](repeating: UInt.zero, count: count) + //=--------------------------------------= + var major = Int.zero + var minor = Int.zero - private init(minorLimbs: [Limb]) where Limb: NBKCoreInteger { - precondition(Limb.bitWidth.isPowerOf2) - precondition(Limb.bitWidth <= UInt.bitWidth) - //=--------------------------------------= - let ratio = UInt.bitWidth / Limb.bitWidth - let count = minorLimbs.count / ratio - var words = [UInt](repeating: UInt.zero, count: count) - //=--------------------------------------= - var major = Int.zero - var minor = Int.zero + for limb in minorLimbs { + words[major] |= UInt(truncatingIfNeeded: limb) &<< minor + minor += Limb.bitWidth - for limb in minorLimbs { - words[major] |= UInt(truncatingIfNeeded: limb) &<< minor - minor += Limb.bitWidth - - if minor >= UInt.bitWidth { - minor -= UInt.bitWidth - major += 1 - } + if minor >= UInt.bitWidth { + minor -= UInt.bitWidth + major += 1 } - //=--------------------------------------= - self.init(words: words) } + //=--------------------------------------= + return words as [UInt] } diff --git a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Comparisons.swift b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Comparisons.swift index e119ac16..17e31bbc 100644 --- a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Comparisons.swift +++ b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Comparisons.swift @@ -37,8 +37,8 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual(lhs.compared(to: rhs), signum, file: file, line: line) } -func NBKAssertComparisonsAtIndex( -_ lhs: UIntXL, _ rhs: UIntXL, _ index: Int, _ signum: Int, +func NBKAssertComparisonsAtIndex( +_ lhs: T, _ rhs: T, _ index: Int, _ signum: Int, file: StaticString = #file, line: UInt = #line) { //=------------------------------------------= if index.isZero { diff --git a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Complements.swift b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Complements.swift new file mode 100644 index 00000000..a2cc3192 --- /dev/null +++ b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Complements.swift @@ -0,0 +1,40 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit +import NBKFlexibleWidthKit +import XCTest + +//*============================================================================* +// MARK: * NBK x Assert x Complements +//*============================================================================* + +func NBKAssertTwosComplement( +_ integer: T, _ result: T, _ overflow: Bool = false, +file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual(integer.twosComplement(), result, file: file, line: line) + XCTAssertEqual({ var x = integer; x.formTwosComplement(); return x }(), result, file: file, line: line) +} + +func NBKAssertAdditiveInverse( +_ operand: IntXL, _ partialValue: IntXL, _ overflow: Bool = false, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + if !overflow { + NBKAssertIdentical(-operand, partialValue, file: file, line: line) + NBKAssertIdentical((operand).negated(), partialValue, file: file, line: line) + NBKAssertIdentical({ var x = operand; x.negate(); return x }(), partialValue, file: file, line: line) + } + //=------------------------------------------= + NBKAssertIdentical(operand.negatedReportingOverflow().partialValue, partialValue, file: file, line: line) + XCTAssertEqual/**/(operand.negatedReportingOverflow().overflow, overflow, file: file, line: line) + + NBKAssertIdentical({ var x = operand; let _ = x.negateReportingOverflow(); return x }(), partialValue, file: file, line: line) + XCTAssertEqual/**/({ var x = operand; let o = x.negateReportingOverflow(); return o }(), overflow, file: file, line: line) +} diff --git a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Identical.swift b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Identical.swift new file mode 100644 index 00000000..de85cefc --- /dev/null +++ b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Identical.swift @@ -0,0 +1,29 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKFlexibleWidthKit +import XCTest + +//*============================================================================* +// MARK: * NBK x Assert x Identical +//*============================================================================* + +func NBKAssertIdentical(_ lhs: IntXL?, _ rhs: IntXL?, file: StaticString = #file, line: UInt = #line) { + func description(of value: IntXL?) -> String { + value.map({ "\(UnicodeScalar($0.sign.ascii))\($0.magnitude)" }) ?? "nil" + } + //=--------------------------------------= + let success: Bool = lhs?.sign == rhs?.sign && lhs?.magnitude == rhs?.magnitude + //=--------------------------------------= + if success { + XCTAssertEqual(lhs, rhs, file: file, line: line) + } + //=--------------------------------------= + XCTAssert(success, "\(description(of: lhs)) is not identical to \(description(of: rhs))", file: file, line: line) +} diff --git a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Words.swift b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Words.swift index 1f5a2a41..0ab79c70 100644 --- a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Words.swift +++ b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Words.swift @@ -18,7 +18,6 @@ import XCTest func NBKAssertWords( _ integer: T, _ words: [UInt], file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual(Array(integer.words), Array(words), file: file, line: line) XCTAssertEqual(Array(integer.words.reversed()), Array(words.reversed()), file: file, line: line) } From a3878deafb6a768e038175b1a840fb880e673025 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sat, 29 Jul 2023 18:36:30 +0200 Subject: [PATCH 025/133] NBKFlexibleWidthKit: IntXL. --- .../NBKFlexibleWidth+Comparisons.swift | 51 +++++++++++++++++++ .../NBKFlexibleWidth+Complements.swift | 7 ++- .../NBKFlexibleWidth+Words.swift | 5 +- .../NBKFlexibleWidthKitTests/IntXL+Bits.swift | 19 +++++-- .../IntXL+Complements.swift | 33 +++++++++++- .../IntXL+Words.swift | 12 ++++- 6 files changed, 114 insertions(+), 13 deletions(-) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift index d8039997..b7160d49 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift @@ -85,6 +85,32 @@ extension NBKFlexibleWidth { let m = self.magnitude.compared(to: other.magnitude, at: index) return self.sign == Sign.plus ? m : -(m) } + + #warning("tests") + // TODO: common implementation + @inlinable public func compared(to other: Digit) -> Int { + //=--------------------------------------= + if self.sign.bit != other.isLessThanZero { + if self.isZero && other.isZero { return 0 } + return self.sign == Sign.plus ? 1 : -1 + } + //=--------------------------------------= + let m = self.magnitude.compared(to: other.magnitude) + return self.sign == Sign.plus ? m : -(m) + } + + #warning("tests") + // TODO: common implementation + @inlinable public func compared(to other: Digit, at index: Int) -> Int { + //=--------------------------------------= + if self.sign.bit != other.isLessThanZero { + if self.isZero && other.isZero { return 0 } + return self.sign == Sign.plus ? 1 : -1 + } + //=--------------------------------------= + let m = self.magnitude.compared(to: other.magnitude, at: index) + return self.sign == Sign.plus ? m : -(m) + } } //*============================================================================* @@ -163,6 +189,31 @@ extension NBKFlexibleWidth.Magnitude { return Int(bit: !prefix.allSatisfy({ $0.isZero })) }} } + + #warning("tests") + // TODO: common implementation + @inlinable public func compared(to other: Digit) -> Int { + self .storage.elements.withUnsafeBufferPointer { lhs in + Swift.withUnsafePointer(to: other) { rhs in + let rhs = NBK.UnsafeWords(start: rhs, count: Int(bit: !rhs.pointee.isZero)) + return Self.compareWordsUnchecked(lhs, to: rhs) + }} + } + + #warning("tests") + // TODO: common implementation + @inlinable public func compared(to other: Digit, at index: Int) -> Int { + self .storage.elements.withUnsafeBufferPointer { lhs in + Swift.withUnsafePointer(to: other) { rhs in + let rhs = NBK.UnsafeWords(start: rhs, count: Int(bit: !rhs.pointee.isZero)) + let partition = Swift.min(index, lhs.endIndex) + let suffix = NBK.UnsafeWords(rebasing: lhs.suffix(from: partition)) + let comparison = Self.compareWordsUnchecked(suffix, to: rhs) + if !comparison.isZero { return comparison } + let prefix = NBK.UnsafeWords(rebasing: lhs.prefix(upTo: partition)) + return Int(bit: !prefix.allSatisfy({ $0.isZero })) + }} + } } //=----------------------------------------------------------------------------= diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements.swift index 83a84564..71189f5c 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements.swift @@ -20,11 +20,11 @@ extension NBKFlexibleWidth { //=------------------------------------------------------------------------= @inlinable public mutating func formTwosComplement() { - fatalError("TODO") + if self.magnitude.isZero || !self.compared(to: Int.min, at: self.magnitude.storage.elements.count - 1).isZero { self.negate() } } @inlinable public func twosComplement() -> Self { - fatalError("TODO") + var result = self; result.formTwosComplement(); return result } //=------------------------------------------------------------------------= @@ -49,17 +49,16 @@ extension NBKFlexibleWidth { extension NBKFlexibleWidth.Magnitude { + // TODO: update NBKBinaryInteger/twosComplement() documentation //=------------------------------------------------------------------------= // MARK: Details x Two's Complement //=------------------------------------------------------------------------= - #warning("tests") @inlinable public mutating func formTwosComplement() { self.storage.formTwosComplement() self.storage.normalize() } - #warning("tests") @inlinable public func twosComplement() -> Self { var result = self; result.formTwosComplement(); return result } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift index 4cdb2acc..4cbb601c 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift @@ -50,7 +50,10 @@ extension NBKFlexibleWidth { //=------------------------------------------------------------------------= @inlinable var wordsNeedsOneMoreWord: Bool { - self.magnitude.isZero || self.magnitude.mostSignificantBit + guard !self.magnitude.isZero else { return true } + let index = self.magnitude.storage.elements.count - 1 + let comparison = self.magnitude.compared(to: UInt(bitPattern: Int.min), at: index) + return comparison >= Int(bit: self.sign.bit) } //*========================================================================* diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Bits.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Bits.swift index 4293a058..a0dd1e92 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Bits.swift +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Bits.swift @@ -39,9 +39,12 @@ final class IntXLTestsOnBits: XCTestCase { XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as [UInt]).bitWidth, UInt.bitWidth * 1) XCTAssertEqual(T(sign: .plus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as [UInt])).bitWidth, UInt.bitWidth * 4) - XCTAssertEqual(T(sign: .minus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as [UInt])).bitWidth, UInt.bitWidth * 4) XCTAssertEqual(T(sign: .plus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as [UInt])).bitWidth, UInt.bitWidth * 5) - XCTAssertEqual(T(sign: .minus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as [UInt])).bitWidth, UInt.bitWidth * 5) + XCTAssertEqual(T(sign: .plus, magnitude: M(words:[ 1, 0, 0, ~0/2 + 1] as [UInt])).bitWidth, UInt.bitWidth * 5) + + XCTAssertEqual(T(sign: .minus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as [UInt])).bitWidth, UInt.bitWidth * 4) + XCTAssertEqual(T(sign: .minus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as [UInt])).bitWidth, UInt.bitWidth * 4) + XCTAssertEqual(T(sign: .minus, magnitude: M(words:[ 1, 0, 0, ~0/2 + 1] as [UInt])).bitWidth, UInt.bitWidth * 5) } func testNonzeroBitCount() { @@ -51,9 +54,12 @@ final class IntXLTestsOnBits: XCTestCase { XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as [UInt]).nonzeroBitCount, UInt.bitWidth * 1) XCTAssertEqual(T(sign: .plus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as [UInt])).nonzeroBitCount, UInt.bitWidth * 4 - 1) - XCTAssertEqual(T(sign: .minus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as [UInt])).nonzeroBitCount, UInt.bitWidth * 0 + 2) XCTAssertEqual(T(sign: .plus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as [UInt])).nonzeroBitCount, UInt.bitWidth * 0 + 1) - XCTAssertEqual(T(sign: .minus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as [UInt])).nonzeroBitCount, UInt.bitWidth * 1 + 1) + XCTAssertEqual(T(sign: .plus, magnitude: M(words:[ 1, 0, 0, ~0/2 + 1] as [UInt])).nonzeroBitCount, UInt.bitWidth * 0 + 2) + + XCTAssertEqual(T(sign: .minus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as [UInt])).nonzeroBitCount, UInt.bitWidth * 0 + 2) + XCTAssertEqual(T(sign: .minus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as [UInt])).nonzeroBitCount, UInt.bitWidth * 0 + 1) + XCTAssertEqual(T(sign: .minus, magnitude: M(words:[ 1, 0, 0, ~0/2 + 1] as [UInt])).nonzeroBitCount, UInt.bitWidth * 5 - 1) } func testLeadingZeroBitCount() { @@ -68,9 +74,12 @@ final class IntXLTestsOnBits: XCTestCase { XCTAssertEqual(T(words:[ 0, 0, 0, 2] as [UInt]).leadingZeroBitCount, UInt.bitWidth * 1 - 2) XCTAssertEqual(T(sign: .plus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as [UInt])).leadingZeroBitCount, UInt.bitWidth * 0 + 1) - XCTAssertEqual(T(sign: .minus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as [UInt])).leadingZeroBitCount, UInt.bitWidth * 0 + 0) XCTAssertEqual(T(sign: .plus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as [UInt])).leadingZeroBitCount, UInt.bitWidth * 1 + 0) + XCTAssertEqual(T(sign: .plus, magnitude: M(words:[ 1, 0, 0, ~0/2 + 1] as [UInt])).leadingZeroBitCount, UInt.bitWidth * 1 + 0) + + XCTAssertEqual(T(sign: .minus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as [UInt])).leadingZeroBitCount, UInt.bitWidth * 0 + 0) XCTAssertEqual(T(sign: .minus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as [UInt])).leadingZeroBitCount, UInt.bitWidth * 0 + 0) + XCTAssertEqual(T(sign: .minus, magnitude: M(words:[ 1, 0, 0, ~0/2 + 1] as [UInt])).leadingZeroBitCount, UInt.bitWidth * 0 + 0) } func testTrailingZeroBitCount() { diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Complements.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Complements.swift index f16f9eab..39bbe060 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Complements.swift +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Complements.swift @@ -41,7 +41,24 @@ final class IntXLTestsOnComplements: XCTestCase { //=------------------------------------------------------------------------= func testTwosComplement() { - // TODO: (!) + NBKAssertTwosComplement(-T(1), T(1)) + NBKAssertTwosComplement(-T(0), T(0)) + NBKAssertTwosComplement( T(0), -T(0)) + NBKAssertTwosComplement( T(1), -T(1)) + + NBKAssertTwosComplement(T(words:[ 0, 0, 0, 0] as [UInt]), T(words:[ 0, 0, 0, 0] as [UInt])) + NBKAssertTwosComplement(T(words:[ 1, 0, 0, 0] as [UInt]), T(words:[~0, ~0, ~0, ~0] as [UInt])) + NBKAssertTwosComplement(T(words:[~0, 0, 0, 0] as [UInt]), T(words:[ 1, ~0, ~0, ~0] as [UInt])) + NBKAssertTwosComplement(T(words:[ 1, 1, 1, 1] as [UInt]), T(words:[~0, ~1, ~1, ~1] as [UInt])) + NBKAssertTwosComplement(T(words:[~0, ~0, ~0, ~0] as [UInt]), T(words:[ 1, 0, 0, 0] as [UInt])) + + NBKAssertTwosComplement(T(words:[~0, ~0, ~0, ~0/2 + 0, 0] as [UInt]), T(words:[ 1, 0, 0, ~0/2 + 1, ~0] as [UInt])) // Int256.max + NBKAssertTwosComplement(T(words:[ 0, 0, 0, ~0/2 + 1, 0] as [UInt]), T(words:[ 0, 0, 0, ~0/2 + 1, ~0] as [UInt])) + NBKAssertTwosComplement(T(words:[ 1, 0, 0, ~0/2 + 1, 0] as [UInt]), T(words:[~0, ~0, ~0, ~0/2 + 0, ~0] as [UInt])) + + NBKAssertTwosComplement(T(words:[ 1, 0, 0, ~0/2 + 1, ~0] as [UInt]), T(words:[~0, ~0, ~0, ~0/2 + 0, 0] as [UInt])) + NBKAssertTwosComplement(T(words:[ 0, 0, 0, ~0/2 + 1, ~0] as [UInt]), T(words:[ 0, 0, 0, ~0/2 + 1, ~0] as [UInt])) // Int256.min + NBKAssertTwosComplement(T(words:[~0, ~0, ~0, ~0/2 + 0, ~0] as [UInt]), T(words:[ 1, 0, 0, ~0/2 + 1, 0] as [UInt])) } //=------------------------------------------------------------------------= @@ -81,7 +98,19 @@ final class UIntXLTestsOnComplements: XCTestCase { //=------------------------------------------------------------------------= func testTwosComplement() { - // TODO: (!) + NBKAssertTwosComplement(T(words:[ 0, 0, 0, 0] as [UInt]), T(words:[ 0, 0, 0, 0] as [UInt])) + NBKAssertTwosComplement(T(words:[ 1, 0, 0, 0] as [UInt]), T(words:[~0, 0, 0, 0] as [UInt])) + NBKAssertTwosComplement(T(words:[~0, 0, 0, 0] as [UInt]), T(words:[ 1, 0, 0, 0] as [UInt])) + NBKAssertTwosComplement(T(words:[ 1, 1, 1, 1] as [UInt]), T(words:[~0, ~1, ~1, ~1] as [UInt])) + NBKAssertTwosComplement(T(words:[~0, ~0, ~0, ~0] as [UInt]), T(words:[ 1, 0, 0, 0] as [UInt])) + + NBKAssertTwosComplement(T(words:[~0, ~0, ~0, ~0/2 + 0] as [UInt]), T(words:[ 1, 0, 0, ~0/2 + 1] as [UInt])) // Int256.max + NBKAssertTwosComplement(T(words:[ 0, 0, 0, ~0/2 + 1] as [UInt]), T(words:[ 0, 0, 0, ~0/2 + 1] as [UInt])) + NBKAssertTwosComplement(T(words:[ 1, 0, 0, ~0/2 + 1] as [UInt]), T(words:[~0, ~0, ~0, ~0/2 + 0] as [UInt])) + + NBKAssertTwosComplement(T(words:[ 1, 0, 0, ~0/2 + 1] as [UInt]), T(words:[~0, ~0, ~0, ~0/2 + 0] as [UInt])) + NBKAssertTwosComplement(T(words:[ 0, 0, 0, ~0/2 + 1] as [UInt]), T(words:[ 0, 0, 0, ~0/2 + 1] as [UInt])) // Int256.min + NBKAssertTwosComplement(T(words:[~0, ~0, ~0, ~0/2 + 0] as [UInt]), T(words:[ 1, 0, 0, ~0/2 + 1] as [UInt])) } } diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Words.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Words.swift index 2d26075f..a7457747 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Words.swift +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Words.swift @@ -22,7 +22,8 @@ private typealias Y = [UInt32] final class IntXLTestsOnWords: XCTestCase { - typealias T = IntXL + typealias T = IntXL + typealias M = UIntXL //=------------------------------------------------------------------------= // MARK: Tests @@ -40,6 +41,14 @@ final class IntXLTestsOnWords: XCTestCase { NBKAssertWords(T(words:[1, 2, 0, 0]), [1, 2 ]) NBKAssertWords(T(words:[1, 2, 3, 0]), [1, 2, 3 ]) NBKAssertWords(T(words:[1, 2, 3, 4]), [1, 2, 3, 4]) + + NBKAssertWords(T(sign: .plus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as [UInt])), [~0, ~0, ~0, ~0/2 + 0 ] as [UInt]) // 4 + NBKAssertWords(T(sign: .plus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as [UInt])), [ 0, 0, 0, ~0/2 + 1, 0] as [UInt]) // 5 + NBKAssertWords(T(sign: .plus, magnitude: M(words:[ 1, 0, 0, ~0/2 + 1] as [UInt])), [ 1, 0, 0, ~0/2 + 1, 0] as [UInt]) // 5 + + NBKAssertWords(T(sign: .minus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as [UInt])), [ 1, 0, 0, ~0/2 + 1 ] as [UInt]) // 4 + NBKAssertWords(T(sign: .minus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as [UInt])), [ 0, 0, 0, ~0/2 + 1 ] as [UInt]) // 4 + NBKAssertWords(T(sign: .minus, magnitude: M(words:[ 1, 0, 0, ~0/2 + 1] as [UInt])), [~0, ~0, ~0, ~0/2 + 0, ~0] as [UInt]) // 5 } func testWordsX64() throws { @@ -90,6 +99,7 @@ final class IntXLTestsOnWords: XCTestCase { final class UIntXLTestsOnWords: XCTestCase { typealias T = UIntXL + typealias M = UIntXL //=------------------------------------------------------------------------= // MARK: Tests From a1ffe872b9ad433be6614f93a5ae3bdcb19ce5ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sun, 30 Jul 2023 08:53:50 +0200 Subject: [PATCH 026/133] NBKFlexibleWidthKit: Cleanup. --- .../NBKFlexibleWidth+Addition+Digit.swift | 21 +- .../NBKFlexibleWidth+Addition.swift | 4 +- .../NBKFlexibleWidth+Comparisons.swift | 121 +++--- .../NBKFlexibleWidth+Numbers.swift | 17 +- .../NBKFlexibleWidth+Protocol.swift | 4 + .../NBKFlexibleWidth+Words.swift | 17 + .../IntXL+Comparisons.swift | 348 ++++++++++++------ .../Utilities/NBKAssert+Comparisons.swift | 26 ++ 8 files changed, 361 insertions(+), 197 deletions(-) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift index f44ece4f..fa47e9e0 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift @@ -33,21 +33,20 @@ extension NBKFlexibleWidth { #warning("tests") @_disfavoredOverload @inlinable public mutating func add(_ other: Int, at index: Int) { - //=--------------------------------------= - if self.sign == Sign(other.isLessThanZero) { + if self.sign == Sign(other.isLessThanZero) { self.magnitude.add(other.magnitude, at: index) return } //=--------------------------------------= - // TODO: func compared(to: Digit) - // TODO: Magnitude.init(digit, at: index) - let extended = Magnitude(digit: other.magnitude).bitshiftedLeft(by: index) - if self.magnitude >= extended { - self.magnitude.subtract(extended, at: Int.zero) + let otherMagnitude = other.magnitude as UInt //=--------------------------------------= + if self.magnitude.compared(to: otherMagnitude, at: index) >= 0 { + self.magnitude.subtract(otherMagnitude, at: index) } else { self.sign.toggle() - self.magnitude = extended.subtracting(self.magnitude, at: Int.zero) + let magnitude = self.magnitude as Magnitude + self.magnitude = Magnitude(digit: otherMagnitude, at: index) + self.magnitude.subtract(magnitude, at: Int.zero) } } @@ -85,11 +84,9 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= if other.isZero { return } //=--------------------------------------= - self.storage.resize(minCount: index + 1) + self.storage.resize(minCount: index + 1) let overflow = self.storage.add(other, plus: false, at: index) - if overflow { - self.storage.elements.append(1) - } + if overflow { self.storage.elements.append(1) } } @_disfavoredOverload @inlinable public func adding(_ other: UInt, at index: Int) -> Self { diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift index abf5e200..1dde6f88 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift @@ -71,9 +71,7 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= self.storage.resize(minCount: other.storage.elements.count + index) let overflow = self.storage.add(other.storage, plus: false, at: index) - if overflow { - self.storage.elements.append(1 as UInt) - } + if overflow { self.storage.elements.append(1) } } @inlinable public func adding(_ other: Self, at index: Int) -> Self { diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift index b7160d49..618db2d1 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift @@ -65,51 +65,41 @@ extension NBKFlexibleWidth { } @inlinable public func compared(to other: Self) -> Int { - //=--------------------------------------= - if self.sign != other.sign { - if self.isZero && other.isZero { return 0 } - return self.sign == Sign.plus ? 1 : -1 - } - //=--------------------------------------= - let m = self.magnitude.compared(to: other.magnitude) - return self.sign == Sign.plus ? m : -(m) + Self.compare(self, to: other, at: Int.zero, magnitude: { lhs, rhs, _ in lhs.compared(to: rhs) }) } @inlinable public func compared(to other: Self, at index: Int) -> Int { - //=--------------------------------------= - if self.sign != other.sign { - if self.isZero && other.isZero { return 0 } - return self.sign == Sign.plus ? 1 : -1 - } - //=--------------------------------------= - let m = self.magnitude.compared(to: other.magnitude, at: index) - return self.sign == Sign.plus ? m : -(m) + Self.compare(self, to: other, at: index, magnitude: { lhs, rhs, index in lhs.compared(to: rhs, at: index) }) } - #warning("tests") - // TODO: common implementation - @inlinable public func compared(to other: Digit) -> Int { - //=--------------------------------------= - if self.sign.bit != other.isLessThanZero { - if self.isZero && other.isZero { return 0 } - return self.sign == Sign.plus ? 1 : -1 - } - //=--------------------------------------= - let m = self.magnitude.compared(to: other.magnitude) - return self.sign == Sign.plus ? m : -(m) + @_disfavoredOverload @inlinable public func compared(to other: Digit) -> Int { + Self.compare(self, to: other, at: Int.zero, magnitude: { lhs, rhs, _ in lhs.compared(to: rhs) }) } + + @_disfavoredOverload @inlinable public func compared(to other: Digit, at index: Int) -> Int { + Self.compare(self, to: other, at: index, magnitude: { lhs, rhs, index in lhs.compared(to: rhs, at: index) }) + } +} - #warning("tests") - // TODO: common implementation - @inlinable public func compared(to other: Digit, at index: Int) -> Int { +//=----------------------------------------------------------------------------= +// MARK: + Algorithms +//=----------------------------------------------------------------------------= + +extension NBKFlexibleWidth { + + //=------------------------------------------------------------------------= + // MARK: Utilities x Private + //=------------------------------------------------------------------------= + + @inlinable static func compare(_ lhs: Self, to rhs: T, at index: Int, + magnitude: (Magnitude, T.Magnitude, Int) -> Int) -> Int where T: NBKBinaryInteger { //=--------------------------------------= - if self.sign.bit != other.isLessThanZero { - if self.isZero && other.isZero { return 0 } - return self.sign == Sign.plus ? 1 : -1 + if lhs.sign.bit != rhs.isLessThanZero { + return lhs.isZero && rhs.isZero ? 0 : lhs.sign.bit ? -1 : 1 } //=--------------------------------------= - let m = self.magnitude.compared(to: other.magnitude, at: index) - return self.sign == Sign.plus ? m : -(m) + let magnitude = magnitude(lhs.magnitude, rhs.magnitude, index) + return lhs.sign.bit ? magnitude.negated() : magnitude } } @@ -140,15 +130,15 @@ extension NBKFlexibleWidth.Magnitude { } @inlinable public var isPowerOf2: Bool { - var nonzeroBitCountLowerBound = 0 + var nonzeroBitCount = Int.zero var index = self.storage.elements.startIndex - //=--------------------------------------= - while index < self.storage.elements.endIndex, nonzeroBitCountLowerBound < 2 { - nonzeroBitCountLowerBound &+= self.storage.elements[index].nonzeroBitCount + + while index < self.storage.elements.endIndex, nonzeroBitCount < 2 { + nonzeroBitCount &+= self.storage.elements[index].nonzeroBitCount self.storage.elements.formIndex(after: &index) } - //=--------------------------------------= - return nonzeroBitCountLowerBound == 1 + + return nonzeroBitCount == 1 as Int } //=------------------------------------------------------------------------= @@ -181,37 +171,21 @@ extension NBKFlexibleWidth.Magnitude { @inlinable public func compared(to other: Self, at index: Int) -> Int { self .storage.elements.withUnsafeBufferPointer { lhs in other.storage.elements.withUnsafeBufferPointer { rhs in - let partition = Swift.min(index, lhs.endIndex) - let suffix = NBK.UnsafeWords(rebasing: lhs.suffix(from: partition)) - let comparison = Self.compareWordsUnchecked(suffix, to: rhs) - if !comparison.isZero { return comparison } - let prefix = NBK.UnsafeWords(rebasing: lhs.prefix(upTo: partition)) - return Int(bit: !prefix.allSatisfy({ $0.isZero })) + Self.compareWordsUnchecked(lhs, to: rhs, at: index) }} } - #warning("tests") - // TODO: common implementation - @inlinable public func compared(to other: Digit) -> Int { - self .storage.elements.withUnsafeBufferPointer { lhs in - Swift.withUnsafePointer(to: other) { rhs in - let rhs = NBK.UnsafeWords(start: rhs, count: Int(bit: !rhs.pointee.isZero)) - return Self.compareWordsUnchecked(lhs, to: rhs) + @_disfavoredOverload @inlinable public func compared(to other: Digit) -> Int { + self.storage.elements.withUnsafeBufferPointer { lhs in + Self.withUnsafeWords(of: other) { rhs in + Self.compareWordsUnchecked(lhs, to: rhs) }} } - #warning("tests") - // TODO: common implementation - @inlinable public func compared(to other: Digit, at index: Int) -> Int { - self .storage.elements.withUnsafeBufferPointer { lhs in - Swift.withUnsafePointer(to: other) { rhs in - let rhs = NBK.UnsafeWords(start: rhs, count: Int(bit: !rhs.pointee.isZero)) - let partition = Swift.min(index, lhs.endIndex) - let suffix = NBK.UnsafeWords(rebasing: lhs.suffix(from: partition)) - let comparison = Self.compareWordsUnchecked(suffix, to: rhs) - if !comparison.isZero { return comparison } - let prefix = NBK.UnsafeWords(rebasing: lhs.prefix(upTo: partition)) - return Int(bit: !prefix.allSatisfy({ $0.isZero })) + @_disfavoredOverload @inlinable public func compared(to other: Digit, at index: Int) -> Int { + self.storage.elements.withUnsafeBufferPointer { lhs in + Self.withUnsafeWords(of: other) { rhs in + Self.compareWordsUnchecked(lhs, to: rhs, at: index) }} } } @@ -245,4 +219,19 @@ extension NBKFlexibleWidth.Magnitude { return Int.zero } + + /// A three-way comparison of `lhs` against `rhs` at `index`. + /// + /// - Requires: The last element in `lhs` and `rhs` must not be zero. + /// + @inlinable static func compareWordsUnchecked(_ lhs: NBK.UnsafeWords, to rhs: NBK.UnsafeWords, at index: Int) -> Int { + assert(lhs.last != 0 && rhs.last != 0 && index >= 0) + //=--------------------------------------= + let partition = Swift.min(index, lhs.endIndex) + let suffix = NBK.UnsafeWords(rebasing: lhs.suffix(from: partition)) + let comparison = Self.compareWordsUnchecked(suffix, to: rhs) + if !comparison.isZero { return comparison } + let prefix = NBK.UnsafeWords(rebasing: lhs.prefix(upTo: partition)) + return Int(bit: !prefix.allSatisfy({ $0.isZero })) + } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift index d5d72ade..854278ca 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift @@ -31,6 +31,13 @@ extension NBKFlexibleWidth { self.init(sign: Sign(sign), magnitude: magnitude) } + #warning("tests") + @inlinable public init(digit: Int, at index: Int) { + let sign = digit.isLessThanZero + let magnitude = Magnitude(digit: digit.magnitude, at: index) + self.init(sign: Sign(sign), magnitude: magnitude) + } + //=------------------------------------------------------------------------= // MARK: Initializers x Literal //=------------------------------------------------------------------------= @@ -120,7 +127,15 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @inlinable public init(digit: UInt) { - self.init(storage: Storage(elements: [digit])) + guard !digit.isZero else { self.init(); return } + self.init(unchecked: Storage(elements: [digit])) + } + + #warning("tests") + @inlinable public init(digit: UInt, at index: Int) { + guard !digit.isZero else { self.init(); return } + self.init(unchecked: Storage(repeating: UInt.zero, count: index + 1)) + self.storage.elements[index] = digit } //=------------------------------------------------------------------------= diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Protocol.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Protocol.swift index 6a0264aa..5088018d 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Protocol.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Protocol.swift @@ -22,4 +22,8 @@ public protocol IntXLOrUIntXL: NBKBinaryInteger { //=------------------------------------------------------------------------= func compared(to other: Self, at index: Int) -> Int + + func compared(to other: Self.Digit) -> Int + + func compared(to other: Self.Digit, at index: Int) -> Int } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift index 4cbb601c..d29ea689 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift @@ -237,3 +237,20 @@ extension NBKFlexibleWidth.Magnitude { } } } + +//=----------------------------------------------------------------------------= +// MARK: + Algorithms +//=----------------------------------------------------------------------------= + +extension NBKFlexibleWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Utilities x Private + //=------------------------------------------------------------------------= + + @inlinable static func withUnsafeWords(of digit: Digit, perform body: (NBK.UnsafeWords) -> T) -> T { + Swift.withUnsafePointer(to: digit) { + body(NBK.UnsafeWords(start: $0, count: Int(bit: !digit.isZero))) + } + } +} diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Comparisons.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Comparisons.swift index 88c8e954..1c48262d 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Comparisons.swift +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Comparisons.swift @@ -24,109 +24,7 @@ final class IntXLTestsOnComparisons: XCTestCase { typealias T = IntXL typealias M = UIntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testHashing() { - var union = Set() - union.insert(T(sign: .minus, magnitude: M())) - union.insert(T(sign: .minus, magnitude: M())) - union.insert(T(words:[0, 0, 0, 0] as [UInt])) - union.insert(T(words:[0, 0, 0, 0] as [UInt])) - union.insert(T(words:[1, 0, 0, 0] as [UInt])) - union.insert(T(words:[1, 0, 0, 0] as [UInt])) - union.insert(T(words:[0, 1, 0, 0] as [UInt])) - union.insert(T(words:[0, 1, 0, 0] as [UInt])) - union.insert(T(words:[0, 0, 1, 0] as [UInt])) - union.insert(T(words:[0, 0, 1, 0] as [UInt])) - union.insert(T(words:[0, 0, 0, 1] as [UInt])) - union.insert(T(words:[0, 0, 0, 1] as [UInt])) - XCTAssertEqual(union.count, 5 as Int) - } - func testComparisons() { - NBKAssertComparisons( T(0), T(0), Int(0)) - NBKAssertComparisons( T(0), -T(0), Int(0)) - NBKAssertComparisons(-T(0), T(0), Int(0)) - NBKAssertComparisons(-T(0), -T(0), Int(0)) - - NBKAssertComparisons( T(1), T(1), Int(0)) - NBKAssertComparisons( T(1), -T(1), Int(1)) - NBKAssertComparisons(-T(1), T(1), -Int(1)) - NBKAssertComparisons(-T(1), -T(1), Int(0)) - - NBKAssertComparisons( T(2), T(3), -Int(1)) - NBKAssertComparisons( T(2), -T(3), Int(1)) - NBKAssertComparisons(-T(2), T(3), -Int(1)) - NBKAssertComparisons(-T(2), -T(3), Int(1)) - - NBKAssertComparisons( T(3), T(2), Int(1)) - NBKAssertComparisons( T(3), -T(2), Int(1)) - NBKAssertComparisons(-T(3), T(2), -Int(1)) - NBKAssertComparisons(-T(3), -T(2), -Int(1)) - - NBKAssertComparisons(T(words:[0, 2, 3, 4] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), -Int(1)) - NBKAssertComparisons(T(words:[1, 0, 3, 4] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), -Int(1)) - NBKAssertComparisons(T(words:[1, 2, 0, 4] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), -Int(1)) - NBKAssertComparisons(T(words:[1, 2, 3, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), -Int(1)) - NBKAssertComparisons(T(words:[0, 2, 3, 4] as [UInt]), T(words:[0, 2, 3, 4] as [UInt]), Int(0)) - NBKAssertComparisons(T(words:[1, 0, 3, 4] as [UInt]), T(words:[1, 0, 3, 4] as [UInt]), Int(0)) - NBKAssertComparisons(T(words:[1, 2, 0, 4] as [UInt]), T(words:[1, 2, 0, 4] as [UInt]), Int(0)) - NBKAssertComparisons(T(words:[1, 2, 3, 0] as [UInt]), T(words:[1, 2, 3, 0] as [UInt]), Int(0)) - NBKAssertComparisons(T(words:[1, 2, 3, 4] as [UInt]), T(words:[0, 2, 3, 4] as [UInt]), Int(1)) - NBKAssertComparisons(T(words:[1, 2, 3, 4] as [UInt]), T(words:[1, 0, 3, 4] as [UInt]), Int(1)) - NBKAssertComparisons(T(words:[1, 2, 3, 4] as [UInt]), T(words:[1, 2, 0, 4] as [UInt]), Int(1)) - NBKAssertComparisons(T(words:[1, 2, 3, 4] as [UInt]), T(words:[1, 2, 3, 0] as [UInt]), Int(1)) - } - - func testComparisonsAtIndex() { - NBKAssertComparisonsAtIndex( T(0), T(0), Int(4), Int(0)) - NBKAssertComparisonsAtIndex( T(0), -T(0), Int(4), Int(0)) - NBKAssertComparisonsAtIndex(-T(0), T(0), Int(4), Int(0)) - NBKAssertComparisonsAtIndex(-T(0), -T(0), Int(4), Int(0)) - - NBKAssertComparisonsAtIndex( T(1), T(1), Int(4), -Int(1)) - NBKAssertComparisonsAtIndex( T(1), -T(1), Int(4), Int(1)) - NBKAssertComparisonsAtIndex(-T(1), T(1), Int(4), -Int(1)) - NBKAssertComparisonsAtIndex(-T(1), -T(1), Int(4), Int(1)) - - NBKAssertComparisonsAtIndex( T(2), T(3), Int(4), -Int(1)) - NBKAssertComparisonsAtIndex( T(2), -T(3), Int(4), Int(1)) - NBKAssertComparisonsAtIndex(-T(2), T(3), Int(4), -Int(1)) - NBKAssertComparisonsAtIndex(-T(2), -T(3), Int(4), Int(1)) - - NBKAssertComparisonsAtIndex( T(3), T(2), Int(4), -Int(1)) - NBKAssertComparisonsAtIndex( T(3), -T(2), Int(4), Int(1)) - NBKAssertComparisonsAtIndex(-T(3), T(2), Int(4), -Int(1)) - NBKAssertComparisonsAtIndex(-T(3), -T(2), Int(4), Int(1)) - - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(0), Int(0)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(1), Int(0)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(2), Int(0)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(3), Int(0)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(4), Int(0)) - - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(0), -Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(1), -Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(2), -Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(3), -Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(4), -Int(1)) - - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(0), Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(1), Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(2), Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(3), Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(4), Int(1)) - - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(0), Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(1), Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(2), Int(0)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(3), -Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(4), -Int(1)) - } - //=------------------------------------------------------------------------= // MARK: Tests //=------------------------------------------------------------------------= @@ -231,16 +129,6 @@ final class IntXLTestsOnComparisons: XCTestCase { NBKAssertSignum(T(words:[~1] as [UInt]), Int(-1)) NBKAssertSignum(T(words:[~2] as [UInt]), Int(-1)) } -} - -//*============================================================================* -// MARK: * NBK x UIntXL x Comparisons -//*============================================================================* - -final class UIntXLTestsOnComparisons: XCTestCase { - - typealias T = UIntXL - typealias M = UIntXL //=------------------------------------------------------------------------= // MARK: Tests @@ -248,6 +136,8 @@ final class UIntXLTestsOnComparisons: XCTestCase { func testHashing() { var union = Set() + union.insert(T(sign: .minus, magnitude: M())) + union.insert(T(sign: .minus, magnitude: M())) union.insert(T(words:[0, 0, 0, 0] as [UInt])) union.insert(T(words:[0, 0, 0, 0] as [UInt])) union.insert(T(words:[1, 0, 0, 0] as [UInt])) @@ -260,8 +150,28 @@ final class UIntXLTestsOnComparisons: XCTestCase { union.insert(T(words:[0, 0, 0, 1] as [UInt])) XCTAssertEqual(union.count, 5 as Int) } - - func testComparisons() { + + func testComparing() { + NBKAssertComparisons( T(0), T(0), Int(0)) + NBKAssertComparisons( T(0), -T(0), Int(0)) + NBKAssertComparisons(-T(0), T(0), Int(0)) + NBKAssertComparisons(-T(0), -T(0), Int(0)) + + NBKAssertComparisons( T(1), T(1), Int(0)) + NBKAssertComparisons( T(1), -T(1), Int(1)) + NBKAssertComparisons(-T(1), T(1), -Int(1)) + NBKAssertComparisons(-T(1), -T(1), Int(0)) + + NBKAssertComparisons( T(2), T(3), -Int(1)) + NBKAssertComparisons( T(2), -T(3), Int(1)) + NBKAssertComparisons(-T(2), T(3), -Int(1)) + NBKAssertComparisons(-T(2), -T(3), Int(1)) + + NBKAssertComparisons( T(3), T(2), Int(1)) + NBKAssertComparisons( T(3), -T(2), Int(1)) + NBKAssertComparisons(-T(3), T(2), -Int(1)) + NBKAssertComparisons(-T(3), -T(2), -Int(1)) + NBKAssertComparisons(T(words:[0, 2, 3, 4] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), -Int(1)) NBKAssertComparisons(T(words:[1, 0, 3, 4] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), -Int(1)) NBKAssertComparisons(T(words:[1, 2, 0, 4] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), -Int(1)) @@ -276,7 +186,27 @@ final class UIntXLTestsOnComparisons: XCTestCase { NBKAssertComparisons(T(words:[1, 2, 3, 4] as [UInt]), T(words:[1, 2, 3, 0] as [UInt]), Int(1)) } - func testComparisonsAtIndex() { + func testComparingAtIndex() { + NBKAssertComparisonsAtIndex( T(0), T(0), Int(4), Int(0)) + NBKAssertComparisonsAtIndex( T(0), -T(0), Int(4), Int(0)) + NBKAssertComparisonsAtIndex(-T(0), T(0), Int(4), Int(0)) + NBKAssertComparisonsAtIndex(-T(0), -T(0), Int(4), Int(0)) + + NBKAssertComparisonsAtIndex( T(1), T(1), Int(4), -Int(1)) + NBKAssertComparisonsAtIndex( T(1), -T(1), Int(4), Int(1)) + NBKAssertComparisonsAtIndex(-T(1), T(1), Int(4), -Int(1)) + NBKAssertComparisonsAtIndex(-T(1), -T(1), Int(4), Int(1)) + + NBKAssertComparisonsAtIndex( T(2), T(3), Int(4), -Int(1)) + NBKAssertComparisonsAtIndex( T(2), -T(3), Int(4), Int(1)) + NBKAssertComparisonsAtIndex(-T(2), T(3), Int(4), -Int(1)) + NBKAssertComparisonsAtIndex(-T(2), -T(3), Int(4), Int(1)) + + NBKAssertComparisonsAtIndex( T(3), T(2), Int(4), -Int(1)) + NBKAssertComparisonsAtIndex( T(3), -T(2), Int(4), Int(1)) + NBKAssertComparisonsAtIndex(-T(3), T(2), Int(4), -Int(1)) + NBKAssertComparisonsAtIndex(-T(3), -T(2), Int(4), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(0), Int(0)) NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(1), Int(0)) NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(2), Int(0)) @@ -301,6 +231,95 @@ final class UIntXLTestsOnComparisons: XCTestCase { NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(3), -Int(1)) NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(4), -Int(1)) } + + //=------------------------------------------------------------------------= + // MARK: Tests x Digit + //=------------------------------------------------------------------------= + + func testComparingByDigit() { + NBKAssertComparisonsByDigit( T(0), Int(0), Int(0)) + NBKAssertComparisonsByDigit( T(0), -Int(0), Int(0)) + NBKAssertComparisonsByDigit(-T(0), Int(0), Int(0)) + NBKAssertComparisonsByDigit(-T(0), -Int(0), Int(0)) + + NBKAssertComparisonsByDigit( T(1), Int(1), Int(0)) + NBKAssertComparisonsByDigit( T(1), -Int(1), Int(1)) + NBKAssertComparisonsByDigit(-T(1), Int(1), -Int(1)) + NBKAssertComparisonsByDigit(-T(1), -Int(1), Int(0)) + + NBKAssertComparisonsByDigit( T(2), Int(3), -Int(1)) + NBKAssertComparisonsByDigit( T(2), -Int(3), Int(1)) + NBKAssertComparisonsByDigit(-T(2), Int(3), -Int(1)) + NBKAssertComparisonsByDigit(-T(2), -Int(3), Int(1)) + + NBKAssertComparisonsByDigit( T(3), Int(2), Int(1)) + NBKAssertComparisonsByDigit( T(3), -Int(2), Int(1)) + NBKAssertComparisonsByDigit(-T(3), Int(2), -Int(1)) + NBKAssertComparisonsByDigit(-T(3), -Int(2), -Int(1)) + + NBKAssertComparisonsByDigit(T(words:[0, 0, 0, 0]), Int(1), -Int(1)) + NBKAssertComparisonsByDigit(T(words:[1, 0, 0, 0]), Int(1), Int(0)) + NBKAssertComparisonsByDigit(T(words:[2, 0, 0, 0]), Int(1), Int(1)) + + NBKAssertComparisonsByDigit(T(words:[0, 1, 0, 0]), Int(1), Int(1)) + NBKAssertComparisonsByDigit(T(words:[1, 1, 0, 0]), Int(1), Int(1)) + NBKAssertComparisonsByDigit(T(words:[2, 1, 0, 0]), Int(1), Int(1)) + } + + func testComparingByDigitAtIndex() { + NBKAssertComparisonsByDigitAtIndex( T(0), Int(0), Int(4), Int(0)) + NBKAssertComparisonsByDigitAtIndex( T(0), -Int(0), Int(4), Int(0)) + NBKAssertComparisonsByDigitAtIndex(-T(0), Int(0), Int(4), Int(0)) + NBKAssertComparisonsByDigitAtIndex(-T(0), -Int(0), Int(4), Int(0)) + + NBKAssertComparisonsByDigitAtIndex( T(1), Int(1), Int(4), -Int(1)) + NBKAssertComparisonsByDigitAtIndex( T(1), -Int(1), Int(4), Int(1)) + NBKAssertComparisonsByDigitAtIndex(-T(1), Int(1), Int(4), -Int(1)) + NBKAssertComparisonsByDigitAtIndex(-T(1), -Int(1), Int(4), Int(1)) + + NBKAssertComparisonsByDigitAtIndex( T(2), Int(3), Int(4), -Int(1)) + NBKAssertComparisonsByDigitAtIndex( T(2), -Int(3), Int(4), Int(1)) + NBKAssertComparisonsByDigitAtIndex(-T(2), Int(3), Int(4), -Int(1)) + NBKAssertComparisonsByDigitAtIndex(-T(2), -Int(3), Int(4), Int(1)) + + NBKAssertComparisonsByDigitAtIndex( T(3), Int(2), Int(4), -Int(1)) + NBKAssertComparisonsByDigitAtIndex( T(3), -Int(2), Int(4), Int(1)) + NBKAssertComparisonsByDigitAtIndex(-T(3), Int(2), Int(4), -Int(1)) + NBKAssertComparisonsByDigitAtIndex(-T(3), -Int(2), Int(4), Int(1)) + + NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), Int(4), Int(0), Int(1)) + NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), Int(4), Int(1), Int(1)) + NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), Int(4), Int(2), Int(1)) + NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), Int(4), Int(3), Int(1)) + NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), Int(4), Int(4), -Int(1)) + + NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), Int(5), Int(0), Int(1)) + NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), Int(5), Int(1), Int(1)) + NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), Int(5), Int(2), Int(1)) + NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), Int(5), Int(3), -Int(1)) + NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), Int(5), Int(4), -Int(1)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Miscellaneous + //=------------------------------------------------------------------------= + + func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { + func becauseThisCompilesSuccessfully(_ x: inout T) { + XCTAssertNotNil(x.compared(to: 0)) + XCTAssertNotNil(x.compared(to: 0, at: 0)) + } + } +} + +//*============================================================================* +// MARK: * NBK x UIntXL x Comparisons +//*============================================================================* + +final class UIntXLTestsOnComparisons: XCTestCase { + + typealias T = UIntXL + typealias M = UIntXL //=------------------------------------------------------------------------= // MARK: Tests @@ -385,6 +404,105 @@ final class UIntXLTestsOnComparisons: XCTestCase { NBKAssertSignum(T(words:[~1] as [UInt]), Int(1)) NBKAssertSignum(T(words:[~2] as [UInt]), Int(1)) } + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testHashing() { + var union = Set() + union.insert(T(words:[0, 0, 0, 0] as [UInt])) + union.insert(T(words:[0, 0, 0, 0] as [UInt])) + union.insert(T(words:[1, 0, 0, 0] as [UInt])) + union.insert(T(words:[1, 0, 0, 0] as [UInt])) + union.insert(T(words:[0, 1, 0, 0] as [UInt])) + union.insert(T(words:[0, 1, 0, 0] as [UInt])) + union.insert(T(words:[0, 0, 1, 0] as [UInt])) + union.insert(T(words:[0, 0, 1, 0] as [UInt])) + union.insert(T(words:[0, 0, 0, 1] as [UInt])) + union.insert(T(words:[0, 0, 0, 1] as [UInt])) + XCTAssertEqual(union.count, 5 as Int) + } + + func testComparing() { + NBKAssertComparisons(T(words:[0, 2, 3, 4] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), -Int(1)) + NBKAssertComparisons(T(words:[1, 0, 3, 4] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), -Int(1)) + NBKAssertComparisons(T(words:[1, 2, 0, 4] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), -Int(1)) + NBKAssertComparisons(T(words:[1, 2, 3, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), -Int(1)) + NBKAssertComparisons(T(words:[0, 2, 3, 4] as [UInt]), T(words:[0, 2, 3, 4] as [UInt]), Int(0)) + NBKAssertComparisons(T(words:[1, 0, 3, 4] as [UInt]), T(words:[1, 0, 3, 4] as [UInt]), Int(0)) + NBKAssertComparisons(T(words:[1, 2, 0, 4] as [UInt]), T(words:[1, 2, 0, 4] as [UInt]), Int(0)) + NBKAssertComparisons(T(words:[1, 2, 3, 0] as [UInt]), T(words:[1, 2, 3, 0] as [UInt]), Int(0)) + NBKAssertComparisons(T(words:[1, 2, 3, 4] as [UInt]), T(words:[0, 2, 3, 4] as [UInt]), Int(1)) + NBKAssertComparisons(T(words:[1, 2, 3, 4] as [UInt]), T(words:[1, 0, 3, 4] as [UInt]), Int(1)) + NBKAssertComparisons(T(words:[1, 2, 3, 4] as [UInt]), T(words:[1, 2, 0, 4] as [UInt]), Int(1)) + NBKAssertComparisons(T(words:[1, 2, 3, 4] as [UInt]), T(words:[1, 2, 3, 0] as [UInt]), Int(1)) + } + + func testComparingAtIndex() { + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(0), Int(0)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(1), Int(0)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(2), Int(0)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(3), Int(0)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(4), Int(0)) + + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(0), -Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(1), -Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(2), -Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(3), -Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(4), -Int(1)) + + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(0), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(1), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(2), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(3), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(4), Int(1)) + + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(0), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(1), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(2), Int(0)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(3), -Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(4), -Int(1)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Digit + //=------------------------------------------------------------------------= + + func testComparingByDigit() { + NBKAssertComparisonsByDigit(T(words:[0, 0, 0, 0]), UInt(1), -Int(1)) + NBKAssertComparisonsByDigit(T(words:[1, 0, 0, 0]), UInt(1), Int(0)) + NBKAssertComparisonsByDigit(T(words:[2, 0, 0, 0]), UInt(1), Int(1)) + + NBKAssertComparisonsByDigit(T(words:[0, 1, 0, 0]), UInt(1), Int(1)) + NBKAssertComparisonsByDigit(T(words:[1, 1, 0, 0]), UInt(1), Int(1)) + NBKAssertComparisonsByDigit(T(words:[2, 1, 0, 0]), UInt(1), Int(1)) + } + + func testComparingByDigitAtIndex() { + NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), UInt(4), Int(0), Int(1)) + NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), UInt(4), Int(1), Int(1)) + NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), UInt(4), Int(2), Int(1)) + NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), UInt(4), Int(3), Int(1)) + NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), UInt(4), Int(4), -Int(1)) + + NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), UInt(5), Int(0), Int(1)) + NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), UInt(5), Int(1), Int(1)) + NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), UInt(5), Int(2), Int(1)) + NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), UInt(5), Int(3), -Int(1)) + NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), UInt(5), Int(4), -Int(1)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Miscellaneous + //=------------------------------------------------------------------------= + + func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { + func becauseThisCompilesSuccessfully(_ x: inout T) { + XCTAssertNotNil(x.compared(to: 0)) + XCTAssertNotNil(x.compared(to: 0, at: 0)) + } + } } #endif diff --git a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Comparisons.swift b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Comparisons.swift index 17e31bbc..e2d5deb1 100644 --- a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Comparisons.swift +++ b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Comparisons.swift @@ -47,3 +47,29 @@ file: StaticString = #file, line: UInt = #line) { //=------------------------------------------= XCTAssertEqual(lhs.compared(to: rhs, at: index), signum, file: file, line: line) } + +func NBKAssertComparisonsByDigit( +_ lhs: T, _ rhs: T.Digit, _ signum: Int, +file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual(lhs == rhs, signum == 0, file: file, line: line) + XCTAssertEqual(lhs != rhs, signum != 0, file: file, line: line) + + XCTAssertEqual(lhs < rhs, signum == -1, file: file, line: line) + XCTAssertEqual(lhs <= rhs, signum != 1, file: file, line: line) + + XCTAssertEqual(lhs > rhs, signum == 1, file: file, line: line) + XCTAssertEqual(lhs >= rhs, signum != -1, file: file, line: line) + + XCTAssertEqual(lhs.compared(to: rhs), signum, file: file, line: line) +} + +func NBKAssertComparisonsByDigitAtIndex( +_ lhs: T, _ rhs: T.Digit, _ index: Int, _ signum: Int, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + if index.isZero { + NBKAssertComparisonsByDigit(lhs, rhs, signum, file: file, line: line) + } + //=------------------------------------------= + XCTAssertEqual(lhs.compared(to: rhs, at: index), signum, file: file, line: line) +} From 37ea0199fd1cb2c3999a60617d2466d39b188f10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sun, 30 Jul 2023 09:18:21 +0200 Subject: [PATCH 027/133] NBKFlexibleWidthKit: Digit. --- .../NBKFlexibleWidth+Numbers+Storage.swift | 15 +++++++++++- .../NBKFlexibleWidth+Numbers.swift | 7 ++---- ...swift => NBKFlexibleWidth+Protocols.swift} | 6 +++++ .../IntXL+Numbers.swift | 23 +++++++++++++++++-- 4 files changed, 43 insertions(+), 8 deletions(-) rename Sources/NBKFlexibleWidthKit/{NBKFlexibleWidth+Protocol.swift => NBKFlexibleWidth+Protocols.swift} (83%) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers+Storage.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers+Storage.swift index d6aec5ef..d10a2454 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers+Storage.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers+Storage.swift @@ -16,7 +16,20 @@ import NBKCoreKit extension NBKFlexibleWidth.Magnitude.Storage { //=------------------------------------------------------------------------= - // MARK: Transformations + // MARK: Initializers x Digit + //=------------------------------------------------------------------------= + + @inlinable init(digit: UInt) { + self.init(elements:[digit]) + } + + @inlinable init(digit: UInt, at index: Int) { + self.init(repeating: UInt.zero, count: index + 1) + self.elements[index] = digit + } + + //=------------------------------------------------------------------------= + // MARK: Initializers x Literal //=------------------------------------------------------------------------= @inlinable init(truncating source: StaticBigInt) { diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift index 854278ca..a57a34a4 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift @@ -31,7 +31,6 @@ extension NBKFlexibleWidth { self.init(sign: Sign(sign), magnitude: magnitude) } - #warning("tests") @inlinable public init(digit: Int, at index: Int) { let sign = digit.isLessThanZero let magnitude = Magnitude(digit: digit.magnitude, at: index) @@ -128,14 +127,12 @@ extension NBKFlexibleWidth.Magnitude { @inlinable public init(digit: UInt) { guard !digit.isZero else { self.init(); return } - self.init(unchecked: Storage(elements: [digit])) + self.init(unchecked: Storage(digit: digit)) } - #warning("tests") @inlinable public init(digit: UInt, at index: Int) { guard !digit.isZero else { self.init(); return } - self.init(unchecked: Storage(repeating: UInt.zero, count: index + 1)) - self.storage.elements[index] = digit + self.init(unchecked: Storage(digit: digit, at: index)) } //=------------------------------------------------------------------------= diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Protocol.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Protocols.swift similarity index 83% rename from Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Protocol.swift rename to Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Protocols.swift index 5088018d..c051e722 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Protocol.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Protocols.swift @@ -26,4 +26,10 @@ public protocol IntXLOrUIntXL: NBKBinaryInteger { func compared(to other: Self.Digit) -> Int func compared(to other: Self.Digit, at index: Int) -> Int + + //=------------------------------------------------------------------------= + // MARK: Details x Numbers + //=------------------------------------------------------------------------= + + init(digit: Self.Digit, at index: Int) } diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Numbers.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Numbers.swift index eba8cbe8..75aa3656 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Numbers.swift +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Numbers.swift @@ -56,6 +56,18 @@ final class IntXLTestsOnNumbers: XCTestCase { NBKAssertNumbers(from: T(digit: Int.max), default: T(words:[UInt(Int.max), 0, 0, 0] as [UInt])) } + func testFromIntAsDigitAtIndex() { + NBKAssertNumbers(from: T(digit: Int( 4), at: Int(0)), default: T(words:[ 4, 0, 0, 0] as [UInt])) + NBKAssertNumbers(from: T(digit: Int( 4), at: Int(1)), default: T(words:[ 0, 4, 0, 0] as [UInt])) + NBKAssertNumbers(from: T(digit: Int( 4), at: Int(2)), default: T(words:[ 0, 0, 4, 0] as [UInt])) + NBKAssertNumbers(from: T(digit: Int( 4), at: Int(3)), default: T(words:[ 0, 0, 0, 4] as [UInt])) + + NBKAssertNumbers(from: T(digit: Int(-4), at: Int(0)), default: T(words:[~3, ~0, ~0, ~0] as [UInt])) + NBKAssertNumbers(from: T(digit: Int(-4), at: Int(1)), default: T(words:[ 0, ~3, ~0, ~0] as [UInt])) + NBKAssertNumbers(from: T(digit: Int(-4), at: Int(2)), default: T(words:[ 0, 0, ~3, ~0] as [UInt])) + NBKAssertNumbers(from: T(digit: Int(-4), at: Int(3)), default: T(words:[ 0, 0, 0, ~3] as [UInt])) + } + //=------------------------------------------------------------------------= // MARK: Tests x Int32 //=------------------------------------------------------------------------= @@ -324,8 +336,15 @@ final class UIntXLTestsOnNumbers: XCTestCase { } func testFromUIntAsDigit() { - XCTAssertEqual(T(digit: UInt.min), T(words:[UInt.min] as [UInt])) - XCTAssertEqual(T(digit: UInt.max), T(words:[UInt.max] as [UInt])) + NBKAssertNumbers(from: T(digit: UInt.min), default: T(words:[ 0, 0, 0, 0] as [UInt])) + NBKAssertNumbers(from: T(digit: UInt.max), default: T(words:[~0, 0, 0, 0] as [UInt])) + } + + func testFromUIntAsDigitAtIndex() { + NBKAssertNumbers(from: T(digit: UInt.max, at: Int(0)), default: T(words:[~0, 0, 0, 0] as [UInt])) + NBKAssertNumbers(from: T(digit: UInt.max, at: Int(1)), default: T(words:[ 0, ~0, 0, 0] as [UInt])) + NBKAssertNumbers(from: T(digit: UInt.max, at: Int(2)), default: T(words:[ 0, 0, ~0, 0] as [UInt])) + NBKAssertNumbers(from: T(digit: UInt.max, at: Int(3)), default: T(words:[ 0, 0, 0, ~0] as [UInt])) } //=------------------------------------------------------------------------= From db66a0eafa0c6067d6d3856d429bfeab442844dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sun, 30 Jul 2023 09:24:55 +0200 Subject: [PATCH 028/133] NBKFlexibleWidthKit: Cleanup. --- Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift index d29ea689..b2b68a33 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift @@ -250,7 +250,7 @@ extension NBKFlexibleWidth.Magnitude { @inlinable static func withUnsafeWords(of digit: Digit, perform body: (NBK.UnsafeWords) -> T) -> T { Swift.withUnsafePointer(to: digit) { - body(NBK.UnsafeWords(start: $0, count: Int(bit: !digit.isZero))) + body(NBK.UnsafeWords(start: $0, count: Int(bit: !$0.pointee.isZero))) } } } From d075eaac1db056abf49d9c2aea83ebc6d8c9a539 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sun, 30 Jul 2023 18:13:54 +0200 Subject: [PATCH 029/133] NBKFlexibleWidthKit: Addition, Subtraction. --- .../NBKFlexibleWidth+Addition+Digit.swift | 16 +-- .../NBKFlexibleWidth+Addition.swift | 7 +- .../NBKFlexibleWidth+Protocols.swift | 24 +++++ .../NBKFlexibleWidth+Subtraction+Digit.swift | 16 +-- .../NBKFlexibleWidth+Subtraction.swift | 7 +- .../IntXL+Addition.swift | 61 ++++++++++++ .../IntXL+Subtraction.swift | 61 ++++++++++++ .../IntXL+Addition.swift | 95 ++++++++++++++++++ .../IntXL+Subtraction.swift | 97 +++++++++++++++++++ .../Utilities/NBKAssert+Addition.swift | 8 +- .../Utilities/NBKAssert+Subtraction.swift | 12 ++- 11 files changed, 368 insertions(+), 36 deletions(-) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift index fa47e9e0..9ad807d6 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift @@ -31,22 +31,12 @@ extension NBKFlexibleWidth { // MARK: Transformations //=------------------------------------------------------------------------= - #warning("tests") @_disfavoredOverload @inlinable public mutating func add(_ other: Int, at index: Int) { - if self.sign == Sign(other.isLessThanZero) { + if self.sign == Sign(other.isLessThanZero) { self.magnitude.add(other.magnitude, at: index) - return - } - //=--------------------------------------= - let otherMagnitude = other.magnitude as UInt - //=--------------------------------------= - if self.magnitude.compared(to: otherMagnitude, at: index) >= 0 { - self.magnitude.subtract(otherMagnitude, at: index) - } else { + } else if self.magnitude.subtractReportingOverflow(other.magnitude, at: index) { self.sign.toggle() - let magnitude = self.magnitude as Magnitude - self.magnitude = Magnitude(digit: otherMagnitude, at: index) - self.magnitude.subtract(magnitude, at: Int.zero) + self.magnitude.formTwosComplement() } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift index 1dde6f88..4f4f9b1e 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift @@ -32,7 +32,12 @@ extension NBKFlexibleWidth { //=------------------------------------------------------------------------= @inlinable public mutating func add(_ other: Self, at index: Int) { - fatalError("TODO") + if self.sign == other.sign { + self.magnitude.add(other.magnitude, at: index) + } else if self.magnitude.subtractReportingOverflow(other.magnitude, at: index) { + self.sign.toggle() + self.magnitude.formTwosComplement() + } } @inlinable public func adding(_ other: Self, at index: Int) -> Self { diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Protocols.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Protocols.swift index c051e722..566baf80 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Protocols.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Protocols.swift @@ -32,4 +32,28 @@ public protocol IntXLOrUIntXL: NBKBinaryInteger { //=------------------------------------------------------------------------= init(digit: Self.Digit, at index: Int) + + //=------------------------------------------------------------------------= + // MARK: Details x Addition + //=------------------------------------------------------------------------= + + @inlinable mutating func add(_ other: Self, at index: Int) + + @_disfavoredOverload @inlinable mutating func add(_ other: Digit, at index: Int) + + @inlinable func adding(_ other: Self, at index: Int) -> Self + + @_disfavoredOverload @inlinable func adding(_ other: Digit, at index: Int) -> Self + + //=------------------------------------------------------------------------= + // MARK: Details x Subtraction + //=------------------------------------------------------------------------= + + @inlinable mutating func subtract(_ other: Self, at index: Int) + + @_disfavoredOverload @inlinable mutating func subtract(_ other: Digit, at index: Int) + + @inlinable func subtracting(_ other: Self, at index: Int) -> Self + + @_disfavoredOverload @inlinable func subtracting(_ other: Digit, at index: Int) -> Self } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift index 069a5836..30ecc0bf 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift @@ -31,22 +31,12 @@ extension NBKFlexibleWidth { // MARK: Transformations //=------------------------------------------------------------------------= - #warning("tests") @_disfavoredOverload @inlinable public mutating func subtract(_ other: Int, at index: Int) { - if self.sign != Sign(other.isLessThanZero) { + if self.sign != Sign(other.isLessThanZero) { self.magnitude.add(other.magnitude, at: index) - return - } - //=--------------------------------------= - let otherMagnitude = other.magnitude as UInt - //=--------------------------------------= - if self.magnitude.compared(to: otherMagnitude, at: index) >= 0 { - self.magnitude.subtract(otherMagnitude, at: index) - } else { + } else if self.magnitude.subtractReportingOverflow(other.magnitude, at: index) { self.sign.toggle() - let magnitude = self.magnitude as Magnitude - self.magnitude = Magnitude(digit: otherMagnitude, at: index) - self.magnitude.subtract(magnitude, at: Int.zero) + self.magnitude.formTwosComplement() } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift index 569973ec..bcfd6235 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift @@ -32,7 +32,12 @@ extension NBKFlexibleWidth { //=------------------------------------------------------------------------= @inlinable public mutating func subtract(_ other: Self, at index: Int) { - fatalError("TODO") + if self.sign != other.sign { + self.magnitude.add(other.magnitude, at: index) + } else if self.magnitude.subtractReportingOverflow(other.magnitude, at: index) { + self.sign.toggle() + self.magnitude.formTwosComplement() + } } @inlinable public func subtracting(_ other: Self, at index: Int) -> Self { diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Addition.swift b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Addition.swift index e52193ac..643c454e 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Addition.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Addition.swift @@ -16,6 +16,67 @@ import XCTest private typealias X = [UInt64] private typealias Y = [UInt32] +//*============================================================================* +// MARK: * NBK x IntXL x Addition +//*============================================================================* + +final class IntXLBenchmarksOnAddition: XCTestCase { + + typealias T = IntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testAdd() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs += rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testAdding() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs + rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Digit + //=------------------------------------------------------------------------= + + func testAddDigit() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(Int.max) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs += rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testAddingDigit() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(Int.max) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs + rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } +} + //*============================================================================* // MARK: * NBK x UIntXL x Addition //*============================================================================* diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Subtraction.swift b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Subtraction.swift index def33fd5..114774cb 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Subtraction.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Subtraction.swift @@ -16,6 +16,67 @@ import XCTest private typealias X = [UInt64] private typealias Y = [UInt32] +//*============================================================================* +// MARK: * NBK x IntXL x Subtraction +//*============================================================================* + +final class IntXLBenchmarksOnSubtraction: XCTestCase { + + typealias T = IntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testSubtract() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs -= rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testSubtracting() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs - rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Digit + //=------------------------------------------------------------------------= + + func testSubtractDigit() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(Int.max) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs -= rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testSubtractingDigit() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(Int.max) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs - rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } +} + //*============================================================================* // MARK: * NBK x UIntXL x Subtraction //*============================================================================* diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Addition.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Addition.swift index 8aa3cdb5..ef5c51a2 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Addition.swift +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Addition.swift @@ -16,6 +16,101 @@ import XCTest private typealias X = [UInt64] private typealias Y = [UInt32] +//*============================================================================* +// MARK: * NBK x IntXL x Addition +//*============================================================================* + +final class IntXLTestsOnAddition: XCTestCase { + + typealias T = IntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testAdding() { + NBKAssertAddition(T( 1), T( 2), Int(0), T( 3)) + NBKAssertAddition(T( 1), T( 1), Int(0), T( 2)) + NBKAssertAddition(T( 1), T( 0), Int(0), T( 1)) + NBKAssertAddition(T( 1), T(-1), Int(0), T( 0)) + NBKAssertAddition(T( 1), T(-2), Int(0), T(-1)) + + NBKAssertAddition(T( 0), T( 2), Int(0), T( 2)) + NBKAssertAddition(T( 0), T( 1), Int(0), T( 1)) + NBKAssertAddition(T( 0), T( 0), Int(0), T( 0)) + NBKAssertAddition(T( 0), T(-1), Int(0), T(-1)) + NBKAssertAddition(T( 0), T(-2), Int(0), T(-2)) + + NBKAssertAddition(T(-1), T( 2), Int(0), T( 1)) + NBKAssertAddition(T(-1), T( 1), Int(0), T( 0)) + NBKAssertAddition(T(-1), T( 0), Int(0), T(-1)) + NBKAssertAddition(T(-1), T(-1), Int(0), T(-2)) + NBKAssertAddition(T(-1), T(-2), Int(0), T(-3)) + } + + func testAddingAtIndex() { + NBKAssertAddition(T(words:[ 0, 0, 0, 0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(0), T(words:[ 1, 2, 3, 0] as [UInt])) + NBKAssertAddition(T(words:[~0, 0, 0, 0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(0), T(words:[ 0, 3, 3, 0] as [UInt])) + NBKAssertAddition(T(words:[~0, ~0, 0, 0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(0), T(words:[ 0, 2, 4, 0] as [UInt])) + NBKAssertAddition(T(words:[~0, ~0, ~0, 0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(0), T(words:[ 0, 2, 3, 1] as [UInt])) + + NBKAssertAddition(T(words:[ 0, 0, 0, 0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(1), T(words:[ 0, 1, 2, 3] as [UInt])) + NBKAssertAddition(T(words:[~0, 0, 0, 0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(1), T(words:[~0, 1, 2, 3] as [UInt])) + NBKAssertAddition(T(words:[~0, ~0, 0, 0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(1), T(words:[~0, 0, 3, 3] as [UInt])) + NBKAssertAddition(T(words:[~0, ~0, ~0, 0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(1), T(words:[~0, 0, 2, 4] as [UInt])) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Digit + //=------------------------------------------------------------------------= + + func testAddingDigit() { + NBKAssertAdditionByDigit(T( 1), Int( 2), Int(0), T( 3)) + NBKAssertAdditionByDigit(T( 1), Int( 1), Int(0), T( 2)) + NBKAssertAdditionByDigit(T( 1), Int( 0), Int(0), T( 1)) + NBKAssertAdditionByDigit(T( 1), Int(-1), Int(0), T( 0)) + NBKAssertAdditionByDigit(T( 1), Int(-2), Int(0), T(-1)) + + NBKAssertAdditionByDigit(T( 0), Int( 2), Int(0), T( 2)) + NBKAssertAdditionByDigit(T( 0), Int( 1), Int(0), T( 1)) + NBKAssertAdditionByDigit(T( 0), Int( 0), Int(0), T( 0)) + NBKAssertAdditionByDigit(T( 0), Int(-1), Int(0), T(-1)) + NBKAssertAdditionByDigit(T( 0), Int(-2), Int(0), T(-2)) + + NBKAssertAdditionByDigit(T(-1), Int( 2), Int(0), T( 1)) + NBKAssertAdditionByDigit(T(-1), Int( 1), Int(0), T( 0)) + NBKAssertAdditionByDigit(T(-1), Int( 0), Int(0), T(-1)) + NBKAssertAdditionByDigit(T(-1), Int(-1), Int(0), T(-2)) + NBKAssertAdditionByDigit(T(-1), Int(-2), Int(0), T(-3)) + } + + func testAddingDigitAtIndex() { + NBKAssertAdditionByDigit(T(words:[ 0, 0, 0, 0] as [UInt]), Int(3), Int(0), T(words:[ 3, 0, 0, 0] as [UInt])) + NBKAssertAdditionByDigit(T(words:[~0, 0, 0, 0] as [UInt]), Int(3), Int(0), T(words:[ 2, 1, 0, 0] as [UInt])) + NBKAssertAdditionByDigit(T(words:[~0, ~0, 0, 0] as [UInt]), Int(3), Int(0), T(words:[ 2, 0, 1, 0] as [UInt])) + NBKAssertAdditionByDigit(T(words:[~0, ~0, ~0, 0] as [UInt]), Int(3), Int(0), T(words:[ 2, 0, 0, 1] as [UInt])) + + NBKAssertAdditionByDigit(T(words:[ 0, 0, 0, 0] as [UInt]), Int(3), Int(1), T(words:[ 0, 3, 0, 0] as [UInt])) + NBKAssertAdditionByDigit(T(words:[~0, 0, 0, 0] as [UInt]), Int(3), Int(1), T(words:[~0, 3, 0, 0] as [UInt])) + NBKAssertAdditionByDigit(T(words:[~0, ~0, 0, 0] as [UInt]), Int(3), Int(1), T(words:[~0, 2, 1, 0] as [UInt])) + NBKAssertAdditionByDigit(T(words:[~0, ~0, ~0, 0] as [UInt]), Int(3), Int(1), T(words:[~0, 2, 0, 1] as [UInt])) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Miscellaneous + //=------------------------------------------------------------------------= + + func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { + func becauseThisCompilesSuccessfully(_ x: inout T) { + XCTAssertNotNil(x += 0) + XCTAssertNotNil(x.add(0, at: 0)) + + XCTAssertNotNil(x + 0) + XCTAssertNotNil(x.adding(0, at: 0)) + } + } +} + //*============================================================================* // MARK: * NBK x UIntXL x Addition //*============================================================================* diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Subtraction.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Subtraction.swift index fe29b317..d89cacd2 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Subtraction.swift +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Subtraction.swift @@ -16,6 +16,101 @@ import XCTest private typealias X = [UInt64] private typealias Y = [UInt32] +//*============================================================================* +// MARK: * NBK x IntXL x Subtraction +//*============================================================================* + +final class IntXLTestsOnSubtraction: XCTestCase { + + typealias T = IntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testSubtracting() { + NBKAssertSubtraction(T( 1), T( 2), Int(0), T(-1)) + NBKAssertSubtraction(T( 1), T( 1), Int(0), T( 0)) + NBKAssertSubtraction(T( 1), T( 0), Int(0), T( 1)) + NBKAssertSubtraction(T( 1), T(-1), Int(0), T( 2)) + NBKAssertSubtraction(T( 1), T(-2), Int(0), T( 3)) + + NBKAssertSubtraction(T( 0), T( 2), Int(0), T(-2)) + NBKAssertSubtraction(T( 0), T( 1), Int(0), T(-1)) + NBKAssertSubtraction(T( 0), T( 0), Int(0), T( 0)) + NBKAssertSubtraction(T( 0), T(-1), Int(0), T( 1)) + NBKAssertSubtraction(T( 0), T(-2), Int(0), T( 2)) + + NBKAssertSubtraction(T(-1), T( 2), Int(0), T(-3)) + NBKAssertSubtraction(T(-1), T( 1), Int(0), T(-2)) + NBKAssertSubtraction(T(-1), T( 0), Int(0), T(-1)) + NBKAssertSubtraction(T(-1), T(-1), Int(0), T( 0)) + NBKAssertSubtraction(T(-1), T(-2), Int(0), T( 1)) + } + + func testSubtractingAtIndex() { + NBKAssertSubtraction(T(words:[~0, ~0, ~0, ~0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(0), T(words:[~1, ~2, ~3, ~0] as [UInt])) + NBKAssertSubtraction(T(words:[ 0, ~0, ~0, ~0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(0), T(words:[~0, ~3, ~3, ~0] as [UInt])) + NBKAssertSubtraction(T(words:[ 0, 0, ~0, ~0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(0), T(words:[~0, ~2, ~4, ~0] as [UInt])) + NBKAssertSubtraction(T(words:[ 0, 0, 0, ~0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(0), T(words:[~0, ~2, ~3, ~1] as [UInt])) + + NBKAssertSubtraction(T(words:[~0, ~0, ~0, ~0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(1), T(words:[~0, ~1, ~2, ~3] as [UInt])) + NBKAssertSubtraction(T(words:[ 0, ~0, ~0, ~0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(1), T(words:[ 0, ~1, ~2, ~3] as [UInt])) + NBKAssertSubtraction(T(words:[ 0, 0, ~0, ~0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(1), T(words:[ 0, ~0, ~3, ~3] as [UInt])) + NBKAssertSubtraction(T(words:[ 0, 0, 0, ~0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(1), T(words:[ 0, ~0, ~2, ~4] as [UInt])) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Digit + //=------------------------------------------------------------------------= + + func testSubtractingDigit() { + NBKAssertSubtractionByDigit(T( 1), Int( 2), Int(0), T(-1)) + NBKAssertSubtractionByDigit(T( 1), Int( 1), Int(0), T( 0)) + NBKAssertSubtractionByDigit(T( 1), Int( 0), Int(0), T( 1)) + NBKAssertSubtractionByDigit(T( 1), Int(-1), Int(0), T( 2)) + NBKAssertSubtractionByDigit(T( 1), Int(-2), Int(0), T( 3)) + + NBKAssertSubtractionByDigit(T( 0), Int( 2), Int(0), T(-2)) + NBKAssertSubtractionByDigit(T( 0), Int( 1), Int(0), T(-1)) + NBKAssertSubtractionByDigit(T( 0), Int( 0), Int(0), T( 0)) + NBKAssertSubtractionByDigit(T( 0), Int(-1), Int(0), T( 1)) + NBKAssertSubtractionByDigit(T( 0), Int(-2), Int(0), T( 2)) + + NBKAssertSubtractionByDigit(T(-1), Int( 2), Int(0), T(-3)) + NBKAssertSubtractionByDigit(T(-1), Int( 1), Int(0), T(-2)) + NBKAssertSubtractionByDigit(T(-1), Int( 0), Int(0), T(-1)) + NBKAssertSubtractionByDigit(T(-1), Int(-1), Int(0), T( 0)) + NBKAssertSubtractionByDigit(T(-1), Int(-2), Int(0), T( 1)) + } + + func testSubtractingDigitAtIndex() { + NBKAssertSubtractionByDigit(T(words:[~0, ~0, ~0, ~0] as [UInt]), Int(3), Int(0), T(words:[~3, ~0, ~0, ~0] as [UInt])) + NBKAssertSubtractionByDigit(T(words:[ 0, ~0, ~0, ~0] as [UInt]), Int(3), Int(0), T(words:[~2, ~1, ~0, ~0] as [UInt])) + NBKAssertSubtractionByDigit(T(words:[ 0, 0, ~0, ~0] as [UInt]), Int(3), Int(0), T(words:[~2, ~0, ~1, ~0] as [UInt])) + NBKAssertSubtractionByDigit(T(words:[ 0, 0, 0, ~0] as [UInt]), Int(3), Int(0), T(words:[~2, ~0, ~0, ~1] as [UInt])) + + NBKAssertSubtractionByDigit(T(words:[~0, ~0, ~0, ~0] as [UInt]), Int(3), Int(1), T(words:[~0, ~3, ~0, ~0] as [UInt])) + NBKAssertSubtractionByDigit(T(words:[ 0, ~0, ~0, ~0] as [UInt]), Int(3), Int(1), T(words:[ 0, ~3, ~0, ~0] as [UInt])) + NBKAssertSubtractionByDigit(T(words:[ 0, 0, ~0, ~0] as [UInt]), Int(3), Int(1), T(words:[ 0, ~2, ~1, ~0] as [UInt])) + NBKAssertSubtractionByDigit(T(words:[ 0, 0, 0, ~0] as [UInt]), Int(3), Int(1), T(words:[ 0, ~2, ~0, ~1] as [UInt])) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Miscellaneous + //=------------------------------------------------------------------------= + + func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { + func becauseThisCompilesSuccessfully(_ x: inout T) { + XCTAssertNotNil(x -= 0) + XCTAssertNotNil(x.subtract(0, at: 0)) + + XCTAssertNotNil(x - 0) + XCTAssertNotNil(x.subtracting(0, at: 0)) + } + } +} + //*============================================================================* // MARK: * NBK x UIntXL x Subtraction //*============================================================================* @@ -104,9 +199,11 @@ final class UIntXLTestsOnSubtraction: XCTestCase { func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { func becauseThisCompilesSuccessfully(_ x: inout T) { XCTAssertNotNil(x -= 0) + XCTAssertNotNil(x.subtract(0, at: 0)) XCTAssertNotNil(x.subtractReportingOverflow(0, at: 0)) XCTAssertNotNil(x - 0) + XCTAssertNotNil(x.subtracting(0, at: 0)) XCTAssertNotNil(x.subtractingReportingOverflow(0, at: 0)) } } diff --git a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Addition.swift b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Addition.swift index f2318c6c..5babe036 100644 --- a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Addition.swift +++ b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Addition.swift @@ -15,8 +15,8 @@ import XCTest // MARK: * NBK x Assert x Addition //*============================================================================* -func NBKAssertAddition( -_ lhs: UIntXL, _ rhs: UIntXL, _ index: Int, _ partialValue: UIntXL, +func NBKAssertAddition( +_ lhs: T, _ rhs: T, _ index: Int, _ partialValue: T, file: StaticString = #file, line: UInt = #line) { //=------------------------------------------= if index.isZero { @@ -28,8 +28,8 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual({ var x = lhs; let _ = x.add(rhs, at: index); return x }(), partialValue, file: file, line: line) } -func NBKAssertAdditionByDigit( -_ lhs: UIntXL, _ rhs: UIntXL.Digit, _ index: Int, _ partialValue: UIntXL, +func NBKAssertAdditionByDigit( +_ lhs: T, _ rhs: T.Digit, _ index: Int, _ partialValue: T, file: StaticString = #file, line: UInt = #line) { //=------------------------------------------= if index.isZero { diff --git a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Subtraction.swift b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Subtraction.swift index 3e08b85f..d83b7708 100644 --- a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Subtraction.swift +++ b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Subtraction.swift @@ -15,8 +15,8 @@ import XCTest // MARK: * NBK x Assert x Subtraction //*============================================================================* -func NBKAssertSubtraction( -_ lhs: UIntXL, _ rhs: UIntXL, _ index: Int, _ partialValue: UIntXL, _ overflow: Bool = false, +func NBKAssertSubtraction( +_ lhs: T, _ rhs: T, _ index: Int, _ partialValue: T, _ overflow: Bool = false, file: StaticString = #file, line: UInt = #line) { //=------------------------------------------= if !overflow, index.isZero { @@ -27,6 +27,8 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual({ var lhs = lhs; lhs.subtract(rhs, at: Int.zero); return lhs }(), partialValue, file: file, line: line) } //=------------------------------------------= + guard let lhs = lhs as? UIntXL, let rhs = rhs as? UIntXL, let partialValue = partialValue as? UIntXL else { return } + //=------------------------------------------= XCTAssertEqual(lhs.subtractingReportingOverflow(rhs, at: index).partialValue, partialValue, file: file, line: line) XCTAssertEqual(lhs.subtractingReportingOverflow(rhs, at: index).overflow, overflow, file: file, line: line) @@ -34,8 +36,8 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual({ var x = lhs; let o = x.subtractReportingOverflow(rhs, at: index); return o }(), overflow, file: file, line: line) } -func NBKAssertSubtractionByDigit( -_ lhs: UIntXL, _ rhs: UIntXL.Digit, _ index: Int, _ partialValue: UIntXL, _ overflow: Bool = false, +func NBKAssertSubtractionByDigit( +_ lhs: T, _ rhs: T.Digit, _ index: Int, _ partialValue: T, _ overflow: Bool = false, file: StaticString = #file, line: UInt = #line) { //=------------------------------------------= if !overflow, index.isZero { @@ -46,6 +48,8 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual({ var lhs = lhs; lhs.subtract(rhs, at: Int.zero); return lhs }(), partialValue, file: file, line: line) } //=------------------------------------------= + guard let lhs = lhs as? UIntXL, let rhs = rhs as? UIntXL.Digit, let partialValue = partialValue as? UIntXL else { return } + //=------------------------------------------= XCTAssertEqual(lhs.subtractingReportingOverflow(rhs, at: index).partialValue, partialValue, file: file, line: line) XCTAssertEqual(lhs.subtractingReportingOverflow(rhs, at: index).overflow, overflow, file: file, line: line) From ca720ff858ba9e8b471cf35bc9f6137fbd533455 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sun, 30 Jul 2023 21:22:25 +0200 Subject: [PATCH 030/133] NBKFlexibleWidthKit: Multiplication. --- ...BKFlexibleWidth+Multiplication+Digit.swift | 17 ++-- .../NBKFlexibleWidth+Multiplication.swift | 7 +- .../NBKFlexibleWidth+Protocols.swift | 12 +++ .../IntXL+Multiplication.swift | 39 ++++++++ .../IntXL+Multiplication.swift | 99 ++++++++++++++++--- .../Utilities/NBKAssert+Multiplication.swift | 8 +- 6 files changed, 153 insertions(+), 29 deletions(-) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift index 67f6a337..5c2fb038 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift @@ -31,14 +31,15 @@ extension NBKFlexibleWidth { // MARK: Transformations //=------------------------------------------------------------------------= - // TODO: see what kind of addition the algorithm intrinsically permits - @_disfavoredOverload @inlinable mutating func multiply(by multiplicand: Int, adding addend: UInt) { - fatalError("TODO") + @_disfavoredOverload @inlinable public mutating func multiply(by multiplicand: Int, adding addend: UInt) { + self.sign = self.sign ^ Sign(multiplicand.isLessThanZero) + return self.magnitude.multiply(by: multiplicand.magnitude, adding: addend) } - // TODO: see what kind of addition the algorithm intrinsically permits - @_disfavoredOverload @inlinable func multiplied(by multiplicand: Int, adding addend: UInt) -> Self { - var result = self; result.multiply(by: multiplicand, adding: addend); return result + @_disfavoredOverload @inlinable public func multiplied(by multiplicand: Int, adding addend: UInt) -> Self { + let sign = self.sign ^ Sign(multiplicand.isLessThanZero) + let magnitude = self.magnitude.multiplied(by: multiplicand.magnitude, adding: addend) + return Self(sign: sign, magnitude: magnitude) } } @@ -64,7 +65,7 @@ extension NBKFlexibleWidth.Magnitude { // MARK: Transformations //=------------------------------------------------------------------------= - @_disfavoredOverload @inlinable mutating func multiply(by multiplicand: UInt, adding addend: UInt) { + @_disfavoredOverload @inlinable public mutating func multiply(by multiplicand: UInt, adding addend: UInt) { defer { Swift.assert(self.storage.isNormal) } @@ -80,7 +81,7 @@ extension NBKFlexibleWidth.Magnitude { } } - @_disfavoredOverload @inlinable func multiplied(by multiplicand: UInt, adding addend: UInt) -> Self { + @_disfavoredOverload @inlinable public func multiplied(by multiplicand: UInt, adding addend: UInt) -> Self { var result = self; result.multiply(by: multiplicand, adding: addend); return result } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift index ad65dbb7..293b2e7f 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift @@ -32,11 +32,14 @@ extension NBKFlexibleWidth { //=------------------------------------------------------------------------= @inlinable public mutating func multiply(by multiplicand: Self) { - self = self.multiplied(by: multiplicand) + self.sign = self.sign ^ multiplicand.sign + self.magnitude.multiply(by: multiplicand.magnitude) } @inlinable public func multiplied(by multiplicand: Self) -> Self { - fatalError("TODO") + let sign = self.sign ^ Sign(multiplicand.isLessThanZero) + let magnitude = self.magnitude.multiplied(by: multiplicand.magnitude) + return Self(sign: sign, magnitude: magnitude) } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Protocols.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Protocols.swift index 566baf80..694d1cd7 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Protocols.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Protocols.swift @@ -56,4 +56,16 @@ public protocol IntXLOrUIntXL: NBKBinaryInteger { @inlinable func subtracting(_ other: Self, at index: Int) -> Self @_disfavoredOverload @inlinable func subtracting(_ other: Digit, at index: Int) -> Self + + //=------------------------------------------------------------------------= + // MARK: Details x Multiplication + //=------------------------------------------------------------------------= + + @inlinable mutating func multiply(by multiplicand: Self) + + @_disfavoredOverload @inlinable mutating func multiply(by multiplicand: Digit, adding addend: UInt) + + @inlinable func multiplied(by multiplicand: Self) -> Self + + @_disfavoredOverload @inlinable func multiplied(by multiplicand: Digit, adding addend: UInt) -> Self } diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Multiplication.swift b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Multiplication.swift index 5f04f423..f9b16bcd 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Multiplication.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Multiplication.swift @@ -16,6 +16,45 @@ import XCTest private typealias X = [UInt64] private typealias Y = [UInt32] +//*============================================================================* +// MARK: * NBK x IntXL x Multiplication +//*============================================================================* + +final class IntXLBenchmarksOnMultiplication: XCTestCase { + + typealias T = IntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testMultiplied() { + var lhs = NBK.blackHoleIdentity(T(x64:[~1, ~2, ~3, ~4] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 1, 2, 3, 4] as X)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs * rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Digit + //=------------------------------------------------------------------------= + + func testMultipliedByDigit() { + var lhs = NBK.blackHoleIdentity(T(x64:[~1, ~2, ~3, ~4] as X)) + var rhs = NBK.blackHoleIdentity(Int.max) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs * rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } +} + //*============================================================================* // MARK: * NBK x UIntXL x Multiplication //*============================================================================* diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Multiplication.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Multiplication.swift index 0e5863b4..4ad35116 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Multiplication.swift +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Multiplication.swift @@ -13,9 +13,73 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest +private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] +//*============================================================================* +// MARK: * NBK x IntXL x Multiplication +//*============================================================================* + +final class IntXLTestsOnMultiplication: XCTestCase { + + typealias T = IntXL + typealias M = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testMultiplying() { + NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as W), T(words:[2, 0, 0, 0] as W), T(words:[ 2, 4, 6, 8, 0, 0, 0, 0] as W)) + NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as W), T(words:[0, 2, 0, 0] as W), T(words:[ 0, 2, 4, 6, 8, 0, 0, 0] as W)) + NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as W), T(words:[0, 0, 2, 0] as W), T(words:[ 0, 0, 2, 4, 6, 8, 0, 0] as W)) + NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as W), T(words:[0, 0, 0, 2] as W), T(words:[ 0, 0, 0, 2, 4, 6, 8, 0] as W)) + + NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as W), -T(words:[2, 0, 0, 0] as W), T(words:[~1, ~4, ~6, ~8, ~0, ~0, ~0, ~0] as W)) + NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as W), -T(words:[0, 2, 0, 0] as W), T(words:[ 0, ~1, ~4, ~6, ~8, ~0, ~0, ~0] as W)) + NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as W), -T(words:[0, 0, 2, 0] as W), T(words:[ 0, 0, ~1, ~4, ~6, ~8, ~0, ~0] as W)) + NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as W), -T(words:[0, 0, 0, 2] as W), T(words:[ 0, 0, 0, ~1, ~4, ~6, ~8, ~0] as W)) + + NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as W), T(words:[2, 0, 0, 0] as W), T(words:[~3, ~4, ~6, ~8, ~0, ~0, ~0, ~0] as W)) + NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as W), T(words:[0, 2, 0, 0] as W), T(words:[ 0, ~3, ~4, ~6, ~8, ~0, ~0, ~0] as W)) + NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as W), T(words:[0, 0, 2, 0] as W), T(words:[ 0, 0, ~3, ~4, ~6, ~8, ~0, ~0] as W)) + NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as W), T(words:[0, 0, 0, 2] as W), T(words:[ 0, 0, 0, ~3, ~4, ~6, ~8, ~0] as W)) + + NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as W), -T(words:[2, 0, 0, 0] as W), T(words:[ 4, 4, 6, 8, 0, 0, 0, 0] as W)) + NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as W), -T(words:[0, 2, 0, 0] as W), T(words:[ 0, 4, 4, 6, 8, 0, 0, 0] as W)) + NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as W), -T(words:[0, 0, 2, 0] as W), T(words:[ 0, 0, 4, 4, 6, 8, 0, 0] as W)) + NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as W), -T(words:[0, 0, 0, 2] as W), T(words:[ 0, 0, 0, 4, 4, 6, 8, 0] as W)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Digit + //=------------------------------------------------------------------------= + + func testMultiplyingByDigit() { + NBKAssertMultiplicationByDigit(T(words:[ 1, 2, 3, 4] as W), Int(2), T(words:[ 2, 4, 6, 8, 0] as W)) + NBKAssertMultiplicationByDigit(T(words:[ 1, 2, 3, 4] as W), -Int(2), T(words:[~1, ~4, ~6, ~8, ~0] as W)) + NBKAssertMultiplicationByDigit(T(words:[~1, ~2, ~3, ~4] as W), Int(2), T(words:[~3, ~4, ~6, ~8, ~0] as W)) + NBKAssertMultiplicationByDigit(T(words:[~1, ~2, ~3, ~4] as W), -Int(2), T(words:[ 4, 4, 6, 8, 0] as W)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Miscellaneous + //=------------------------------------------------------------------------= + + func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { + func becauseThisCompilesSuccessfully(_ x: inout T) { + XCTAssertNotNil(x *= 0) + XCTAssertNotNil(x.multiply(by: 0)) + XCTAssertNotNil(x.multiply(by: 0, adding: 0)) + + XCTAssertNotNil(x * 0) + XCTAssertNotNil(x.multiplied(by: 0)) + XCTAssertNotNil(x.multiplied(by: 0, adding: 0)) + } + } +} + //*============================================================================* // MARK: * NBK x UIntXL x Multiplication //*============================================================================* @@ -30,15 +94,15 @@ final class UIntXLTestsOnMultiplication: XCTestCase { //=------------------------------------------------------------------------= func testMultiplying() { - NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as [UInt]), T(words:[2, 0, 0, 0] as [UInt]), T(words:[ 2, 4, 6, 8, 0, 0, 0, 0] as [UInt])) - NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as [UInt]), T(words:[0, 2, 0, 0] as [UInt]), T(words:[ 0, 2, 4, 6, 8, 0, 0, 0] as [UInt])) - NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as [UInt]), T(words:[0, 0, 2, 0] as [UInt]), T(words:[ 0, 0, 2, 4, 6, 8, 0, 0] as [UInt])) - NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as [UInt]), T(words:[0, 0, 0, 2] as [UInt]), T(words:[ 0, 0, 0, 2, 4, 6, 8, 0] as [UInt])) + NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as W), T(words:[2, 0, 0, 0] as W), T(words:[ 2, 4, 6, 8, 0, 0, 0, 0] as W)) + NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as W), T(words:[0, 2, 0, 0] as W), T(words:[ 0, 2, 4, 6, 8, 0, 0, 0] as W)) + NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as W), T(words:[0, 0, 2, 0] as W), T(words:[ 0, 0, 2, 4, 6, 8, 0, 0] as W)) + NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as W), T(words:[0, 0, 0, 2] as W), T(words:[ 0, 0, 0, 2, 4, 6, 8, 0] as W)) - NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as [UInt]), T(words:[2, 0, 0, 0] as [UInt]), T(words:[~3, ~4, ~6, ~8, 1, 0, 0, 0] as [UInt])) - NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as [UInt]), T(words:[0, 2, 0, 0] as [UInt]), T(words:[ 0, ~3, ~4, ~6, ~8, 1, 0, 0] as [UInt])) - NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as [UInt]), T(words:[0, 0, 2, 0] as [UInt]), T(words:[ 0, 0, ~3, ~4, ~6, ~8, 1, 0] as [UInt])) - NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as [UInt]), T(words:[0, 0, 0, 2] as [UInt]), T(words:[ 0, 0, 0, ~3, ~4, ~6, ~8, 1] as [UInt])) + NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as W), T(words:[2, 0, 0, 0] as W), T(words:[~3, ~4, ~6, ~8, 1, 0, 0, 0] as W)) + NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as W), T(words:[0, 2, 0, 0] as W), T(words:[ 0, ~3, ~4, ~6, ~8, 1, 0, 0] as W)) + NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as W), T(words:[0, 0, 2, 0] as W), T(words:[ 0, 0, ~3, ~4, ~6, ~8, 1, 0] as W)) + NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as W), T(words:[0, 0, 0, 2] as W), T(words:[ 0, 0, 0, ~3, ~4, ~6, ~8, 1] as W)) } //=------------------------------------------------------------------------= @@ -46,13 +110,13 @@ final class UIntXLTestsOnMultiplication: XCTestCase { //=------------------------------------------------------------------------= func testMultipliedByDigit() { - NBKAssertMultiplicationByDigit(T(words:[1, 2, 3, 4] as [UInt]), UInt(0), T(words:[0, 0, 0, 0, 0] as [UInt])) - NBKAssertMultiplicationByDigit(T(words:[1, 2, 3, 4] as [UInt]), UInt(1), T(words:[1, 2, 3, 4, 0] as [UInt])) - NBKAssertMultiplicationByDigit(T(words:[1, 2, 3, 4] as [UInt]), UInt(2), T(words:[2, 4, 6, 8, 0] as [UInt])) - - NBKAssertMultiplicationByDigit(T(words:[1, 2, 3, 4] as [UInt]), ~UInt(0), ~T(words:[0, 1, 1, 1, ~3] as [UInt])) - NBKAssertMultiplicationByDigit(T(words:[1, 2, 3, 4] as [UInt]), ~UInt(1), ~T(words:[1, 3, 4, 5, ~3] as [UInt])) - NBKAssertMultiplicationByDigit(T(words:[1, 2, 3, 4] as [UInt]), ~UInt(2), ~T(words:[2, 5, 7, 9, ~3] as [UInt])) + NBKAssertMultiplicationByDigit(T(words:[1, 2, 3, 4] as W), UInt(0), T(words:[ 0, 0, 0, 0, 0] as W)) + NBKAssertMultiplicationByDigit(T(words:[1, 2, 3, 4] as W), UInt(1), T(words:[ 1, 2, 3, 4, 0] as W)) + NBKAssertMultiplicationByDigit(T(words:[1, 2, 3, 4] as W), UInt(2), T(words:[ 2, 4, 6, 8, 0] as W)) + + NBKAssertMultiplicationByDigit(T(words:[1, 2, 3, 4] as W), ~UInt(0), ~T(words:[ 0, 1, 1, 1, ~3] as W)) + NBKAssertMultiplicationByDigit(T(words:[1, 2, 3, 4] as W), ~UInt(1), ~T(words:[ 1, 3, 4, 5, ~3] as W)) + NBKAssertMultiplicationByDigit(T(words:[1, 2, 3, 4] as W), ~UInt(2), ~T(words:[ 2, 5, 7, 9, ~3] as W)) } //=------------------------------------------------------------------------= @@ -62,7 +126,12 @@ final class UIntXLTestsOnMultiplication: XCTestCase { func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { func becauseThisCompilesSuccessfully(_ x: inout T) { XCTAssertNotNil(x *= 0) + XCTAssertNotNil(x.multiply(by: 0)) + XCTAssertNotNil(x.multiply(by: 0, adding: 0)) + XCTAssertNotNil(x * 0) + XCTAssertNotNil(x.multiplied(by: 0)) + XCTAssertNotNil(x.multiplied(by: 0, adding: 0)) } } } diff --git a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Multiplication.swift b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Multiplication.swift index 9c08be90..9aa6f954 100644 --- a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Multiplication.swift +++ b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Multiplication.swift @@ -15,8 +15,8 @@ import XCTest // MARK: * NBK x Assert x Multiplication //*============================================================================* -func NBKAssertMultiplication( -_ lhs: UIntXL, _ rhs: UIntXL, _ result: UIntXL, +func NBKAssertMultiplication( +_ lhs: T, _ rhs: T, _ result: T, file: StaticString = #file, line: UInt = #line) { XCTAssertEqual( lhs * rhs, result, file: file, line: line) XCTAssertEqual({ var lhs = lhs; lhs *= rhs; return lhs }(), result, file: file, line: line) @@ -25,8 +25,8 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual({ var lhs = lhs; lhs.multiply(by: rhs); return lhs }(), result, file: file, line: line) } -func NBKAssertMultiplicationByDigit( -_ lhs: UIntXL, _ rhs: UIntXL.Digit, _ result: UIntXL, +func NBKAssertMultiplicationByDigit( +_ lhs: T, _ rhs: T.Digit, _ result: T, file: StaticString = #file, line: UInt = #line) { XCTAssertEqual( lhs * rhs, result, file: file, line: line) XCTAssertEqual({ var lhs = lhs; lhs *= rhs; return lhs }(), result, file: file, line: line) From c20b88ca6266fd6ef5089dfd62a07569a946b1cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sun, 30 Jul 2023 21:47:10 +0200 Subject: [PATCH 031/133] NBKFlexibleWidthKit: Cleanup. --- .../IntXL+Addition.swift | 1 + .../IntXL+Bits.swift | 1 + .../IntXL+Comparisons.swift | 1 + .../IntXL+Division.swift | 1 + .../IntXL+Logic.swift | 1 + .../IntXL+Multiplication.swift | 1 + .../IntXL+Numbers.swift | 1 + .../IntXL+Shifts.swift | 1 + .../IntXL+Subtraction.swift | 1 + .../IntXL+Text.swift | 1 + .../IntXL+Addition.swift | 65 +-- .../NBKFlexibleWidthKitTests/IntXL+Bits.swift | 191 ++++----- .../IntXL+Comparisons.swift | 393 +++++++++--------- .../IntXL+Complements.swift | 105 ++--- .../IntXL+Division.swift | 9 +- .../IntXL+Logic.swift | 53 +-- .../IntXL+Numbers.swift | 149 +++---- .../IntXL+Shifts.swift | 1 + .../IntXL+Subtraction.swift | 95 ++--- .../NBKFlexibleWidthKitTests/IntXL+Text.swift | 1 + .../IntXL+Words.swift | 13 +- 21 files changed, 553 insertions(+), 532 deletions(-) diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Addition.swift b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Addition.swift index 643c454e..59385b99 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Addition.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Addition.swift @@ -13,6 +13,7 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest +private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Bits.swift b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Bits.swift index 0ce7f77b..c0162d3d 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Bits.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Bits.swift @@ -13,6 +13,7 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest +private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Comparisons.swift b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Comparisons.swift index 664c1dd3..f7468303 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Comparisons.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Comparisons.swift @@ -13,6 +13,7 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest +private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Division.swift b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Division.swift index 92c3b741..06aece6b 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Division.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Division.swift @@ -13,6 +13,7 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest +private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Logic.swift b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Logic.swift index dcfabed6..87953d68 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Logic.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Logic.swift @@ -13,6 +13,7 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest +private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Multiplication.swift b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Multiplication.swift index f9b16bcd..f3dcef84 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Multiplication.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Multiplication.swift @@ -13,6 +13,7 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest +private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Numbers.swift b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Numbers.swift index 472c59d3..f80987d3 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Numbers.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Numbers.swift @@ -13,6 +13,7 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest +private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Shifts.swift b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Shifts.swift index 3dc6a565..2af58592 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Shifts.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Shifts.swift @@ -13,6 +13,7 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest +private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Subtraction.swift b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Subtraction.swift index 114774cb..f5fd77ec 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Subtraction.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Subtraction.swift @@ -13,6 +13,7 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest +private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Text.swift b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Text.swift index b9cb667f..341b057e 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Text.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Text.swift @@ -13,6 +13,7 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest +private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Addition.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Addition.swift index ef5c51a2..86af78b7 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Addition.swift +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Addition.swift @@ -13,6 +13,7 @@ import NBKCoreKit @testable import NBKFlexibleWidthKit import XCTest +private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] @@ -49,15 +50,15 @@ final class IntXLTestsOnAddition: XCTestCase { } func testAddingAtIndex() { - NBKAssertAddition(T(words:[ 0, 0, 0, 0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(0), T(words:[ 1, 2, 3, 0] as [UInt])) - NBKAssertAddition(T(words:[~0, 0, 0, 0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(0), T(words:[ 0, 3, 3, 0] as [UInt])) - NBKAssertAddition(T(words:[~0, ~0, 0, 0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(0), T(words:[ 0, 2, 4, 0] as [UInt])) - NBKAssertAddition(T(words:[~0, ~0, ~0, 0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(0), T(words:[ 0, 2, 3, 1] as [UInt])) + NBKAssertAddition(T(words:[ 0, 0, 0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[ 1, 2, 3, 0] as W)) + NBKAssertAddition(T(words:[~0, 0, 0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[ 0, 3, 3, 0] as W)) + NBKAssertAddition(T(words:[~0, ~0, 0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[ 0, 2, 4, 0] as W)) + NBKAssertAddition(T(words:[~0, ~0, ~0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[ 0, 2, 3, 1] as W)) - NBKAssertAddition(T(words:[ 0, 0, 0, 0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(1), T(words:[ 0, 1, 2, 3] as [UInt])) - NBKAssertAddition(T(words:[~0, 0, 0, 0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(1), T(words:[~0, 1, 2, 3] as [UInt])) - NBKAssertAddition(T(words:[~0, ~0, 0, 0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(1), T(words:[~0, 0, 3, 3] as [UInt])) - NBKAssertAddition(T(words:[~0, ~0, ~0, 0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(1), T(words:[~0, 0, 2, 4] as [UInt])) + NBKAssertAddition(T(words:[ 0, 0, 0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[ 0, 1, 2, 3] as W)) + NBKAssertAddition(T(words:[~0, 0, 0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[~0, 1, 2, 3] as W)) + NBKAssertAddition(T(words:[~0, ~0, 0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[~0, 0, 3, 3] as W)) + NBKAssertAddition(T(words:[~0, ~0, ~0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[~0, 0, 2, 4] as W)) } //=------------------------------------------------------------------------= @@ -85,15 +86,15 @@ final class IntXLTestsOnAddition: XCTestCase { } func testAddingDigitAtIndex() { - NBKAssertAdditionByDigit(T(words:[ 0, 0, 0, 0] as [UInt]), Int(3), Int(0), T(words:[ 3, 0, 0, 0] as [UInt])) - NBKAssertAdditionByDigit(T(words:[~0, 0, 0, 0] as [UInt]), Int(3), Int(0), T(words:[ 2, 1, 0, 0] as [UInt])) - NBKAssertAdditionByDigit(T(words:[~0, ~0, 0, 0] as [UInt]), Int(3), Int(0), T(words:[ 2, 0, 1, 0] as [UInt])) - NBKAssertAdditionByDigit(T(words:[~0, ~0, ~0, 0] as [UInt]), Int(3), Int(0), T(words:[ 2, 0, 0, 1] as [UInt])) + NBKAssertAdditionByDigit(T(words:[ 0, 0, 0, 0] as W), Int(3), Int(0), T(words:[ 3, 0, 0, 0] as W)) + NBKAssertAdditionByDigit(T(words:[~0, 0, 0, 0] as W), Int(3), Int(0), T(words:[ 2, 1, 0, 0] as W)) + NBKAssertAdditionByDigit(T(words:[~0, ~0, 0, 0] as W), Int(3), Int(0), T(words:[ 2, 0, 1, 0] as W)) + NBKAssertAdditionByDigit(T(words:[~0, ~0, ~0, 0] as W), Int(3), Int(0), T(words:[ 2, 0, 0, 1] as W)) - NBKAssertAdditionByDigit(T(words:[ 0, 0, 0, 0] as [UInt]), Int(3), Int(1), T(words:[ 0, 3, 0, 0] as [UInt])) - NBKAssertAdditionByDigit(T(words:[~0, 0, 0, 0] as [UInt]), Int(3), Int(1), T(words:[~0, 3, 0, 0] as [UInt])) - NBKAssertAdditionByDigit(T(words:[~0, ~0, 0, 0] as [UInt]), Int(3), Int(1), T(words:[~0, 2, 1, 0] as [UInt])) - NBKAssertAdditionByDigit(T(words:[~0, ~0, ~0, 0] as [UInt]), Int(3), Int(1), T(words:[~0, 2, 0, 1] as [UInt])) + NBKAssertAdditionByDigit(T(words:[ 0, 0, 0, 0] as W), Int(3), Int(1), T(words:[ 0, 3, 0, 0] as W)) + NBKAssertAdditionByDigit(T(words:[~0, 0, 0, 0] as W), Int(3), Int(1), T(words:[~0, 3, 0, 0] as W)) + NBKAssertAdditionByDigit(T(words:[~0, ~0, 0, 0] as W), Int(3), Int(1), T(words:[~0, 2, 1, 0] as W)) + NBKAssertAdditionByDigit(T(words:[~0, ~0, ~0, 0] as W), Int(3), Int(1), T(words:[~0, 2, 0, 1] as W)) } //=------------------------------------------------------------------------= @@ -134,15 +135,15 @@ final class UIntXLTestsOnAddition: XCTestCase { } func testAddingAtIndex() { - NBKAssertAddition(T(words:[ 0, 0, 0, 0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(0), T(words:[ 1, 2, 3, 0] as [UInt])) - NBKAssertAddition(T(words:[~0, 0, 0, 0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(0), T(words:[ 0, 3, 3, 0] as [UInt])) - NBKAssertAddition(T(words:[~0, ~0, 0, 0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(0), T(words:[ 0, 2, 4, 0] as [UInt])) - NBKAssertAddition(T(words:[~0, ~0, ~0, 0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(0), T(words:[ 0, 2, 3, 1] as [UInt])) + NBKAssertAddition(T(words:[ 0, 0, 0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[ 1, 2, 3, 0] as W)) + NBKAssertAddition(T(words:[~0, 0, 0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[ 0, 3, 3, 0] as W)) + NBKAssertAddition(T(words:[~0, ~0, 0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[ 0, 2, 4, 0] as W)) + NBKAssertAddition(T(words:[~0, ~0, ~0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[ 0, 2, 3, 1] as W)) - NBKAssertAddition(T(words:[ 0, 0, 0, 0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(1), T(words:[ 0, 1, 2, 3] as [UInt])) - NBKAssertAddition(T(words:[~0, 0, 0, 0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(1), T(words:[~0, 1, 2, 3] as [UInt])) - NBKAssertAddition(T(words:[~0, ~0, 0, 0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(1), T(words:[~0, 0, 3, 3] as [UInt])) - NBKAssertAddition(T(words:[~0, ~0, ~0, 0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(1), T(words:[~0, 0, 2, 4] as [UInt])) + NBKAssertAddition(T(words:[ 0, 0, 0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[ 0, 1, 2, 3] as W)) + NBKAssertAddition(T(words:[~0, 0, 0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[~0, 1, 2, 3] as W)) + NBKAssertAddition(T(words:[~0, ~0, 0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[~0, 0, 3, 3] as W)) + NBKAssertAddition(T(words:[~0, ~0, ~0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[~0, 0, 2, 4] as W)) } //=------------------------------------------------------------------------= @@ -160,15 +161,15 @@ final class UIntXLTestsOnAddition: XCTestCase { } func testAddingDigitAtIndex() { - NBKAssertAdditionByDigit(T(words:[ 0, 0, 0, 0] as [UInt]), UInt(3), Int(0), T(words:[ 3, 0, 0, 0] as [UInt])) - NBKAssertAdditionByDigit(T(words:[~0, 0, 0, 0] as [UInt]), UInt(3), Int(0), T(words:[ 2, 1, 0, 0] as [UInt])) - NBKAssertAdditionByDigit(T(words:[~0, ~0, 0, 0] as [UInt]), UInt(3), Int(0), T(words:[ 2, 0, 1, 0] as [UInt])) - NBKAssertAdditionByDigit(T(words:[~0, ~0, ~0, 0] as [UInt]), UInt(3), Int(0), T(words:[ 2, 0, 0, 1] as [UInt])) + NBKAssertAdditionByDigit(T(words:[ 0, 0, 0, 0] as W), UInt(3), Int(0), T(words:[ 3, 0, 0, 0] as W)) + NBKAssertAdditionByDigit(T(words:[~0, 0, 0, 0] as W), UInt(3), Int(0), T(words:[ 2, 1, 0, 0] as W)) + NBKAssertAdditionByDigit(T(words:[~0, ~0, 0, 0] as W), UInt(3), Int(0), T(words:[ 2, 0, 1, 0] as W)) + NBKAssertAdditionByDigit(T(words:[~0, ~0, ~0, 0] as W), UInt(3), Int(0), T(words:[ 2, 0, 0, 1] as W)) - NBKAssertAdditionByDigit(T(words:[ 0, 0, 0, 0] as [UInt]), UInt(3), Int(1), T(words:[ 0, 3, 0, 0] as [UInt])) - NBKAssertAdditionByDigit(T(words:[~0, 0, 0, 0] as [UInt]), UInt(3), Int(1), T(words:[~0, 3, 0, 0] as [UInt])) - NBKAssertAdditionByDigit(T(words:[~0, ~0, 0, 0] as [UInt]), UInt(3), Int(1), T(words:[~0, 2, 1, 0] as [UInt])) - NBKAssertAdditionByDigit(T(words:[~0, ~0, ~0, 0] as [UInt]), UInt(3), Int(1), T(words:[~0, 2, 0, 1] as [UInt])) + NBKAssertAdditionByDigit(T(words:[ 0, 0, 0, 0] as W), UInt(3), Int(1), T(words:[ 0, 3, 0, 0] as W)) + NBKAssertAdditionByDigit(T(words:[~0, 0, 0, 0] as W), UInt(3), Int(1), T(words:[~0, 3, 0, 0] as W)) + NBKAssertAdditionByDigit(T(words:[~0, ~0, 0, 0] as W), UInt(3), Int(1), T(words:[~0, 2, 1, 0] as W)) + NBKAssertAdditionByDigit(T(words:[~0, ~0, ~0, 0] as W), UInt(3), Int(1), T(words:[~0, 2, 0, 1] as W)) } //=------------------------------------------------------------------------= diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Bits.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Bits.swift index a0dd1e92..eaebd520 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Bits.swift +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Bits.swift @@ -13,6 +13,7 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest +private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] @@ -35,97 +36,97 @@ final class IntXLTestsOnBits: XCTestCase { } func testBitWidth() { - XCTAssertEqual(T(words:[ 0, 0, 0, 0] as [UInt]).bitWidth, UInt.bitWidth * 1) - XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as [UInt]).bitWidth, UInt.bitWidth * 1) + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).bitWidth, UInt.bitWidth * 1) + XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).bitWidth, UInt.bitWidth * 1) - XCTAssertEqual(T(sign: .plus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as [UInt])).bitWidth, UInt.bitWidth * 4) - XCTAssertEqual(T(sign: .plus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as [UInt])).bitWidth, UInt.bitWidth * 5) - XCTAssertEqual(T(sign: .plus, magnitude: M(words:[ 1, 0, 0, ~0/2 + 1] as [UInt])).bitWidth, UInt.bitWidth * 5) + XCTAssertEqual(T(sign: .plus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as W)).bitWidth, UInt.bitWidth * 4) + XCTAssertEqual(T(sign: .plus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as W)).bitWidth, UInt.bitWidth * 5) + XCTAssertEqual(T(sign: .plus, magnitude: M(words:[ 1, 0, 0, ~0/2 + 1] as W)).bitWidth, UInt.bitWidth * 5) - XCTAssertEqual(T(sign: .minus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as [UInt])).bitWidth, UInt.bitWidth * 4) - XCTAssertEqual(T(sign: .minus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as [UInt])).bitWidth, UInt.bitWidth * 4) - XCTAssertEqual(T(sign: .minus, magnitude: M(words:[ 1, 0, 0, ~0/2 + 1] as [UInt])).bitWidth, UInt.bitWidth * 5) + XCTAssertEqual(T(sign: .minus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as W)).bitWidth, UInt.bitWidth * 4) + XCTAssertEqual(T(sign: .minus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as W)).bitWidth, UInt.bitWidth * 4) + XCTAssertEqual(T(sign: .minus, magnitude: M(words:[ 1, 0, 0, ~0/2 + 1] as W)).bitWidth, UInt.bitWidth * 5) } func testNonzeroBitCount() { XCTAssertEqual(T(sign: .minus, magnitude: M.zero).nonzeroBitCount, 0) - XCTAssertEqual(T(words:[ 0, 0, 0, 0] as [UInt]).nonzeroBitCount, 0) - XCTAssertEqual(T(words:[ 1, 1, 1, 1] as [UInt]).nonzeroBitCount, 4) - XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as [UInt]).nonzeroBitCount, UInt.bitWidth * 1) + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).nonzeroBitCount, 0) + XCTAssertEqual(T(words:[ 1, 1, 1, 1] as W).nonzeroBitCount, 4) + XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).nonzeroBitCount, UInt.bitWidth * 1) - XCTAssertEqual(T(sign: .plus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as [UInt])).nonzeroBitCount, UInt.bitWidth * 4 - 1) - XCTAssertEqual(T(sign: .plus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as [UInt])).nonzeroBitCount, UInt.bitWidth * 0 + 1) - XCTAssertEqual(T(sign: .plus, magnitude: M(words:[ 1, 0, 0, ~0/2 + 1] as [UInt])).nonzeroBitCount, UInt.bitWidth * 0 + 2) + XCTAssertEqual(T(sign: .plus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as W)).nonzeroBitCount, UInt.bitWidth * 4 - 1) + XCTAssertEqual(T(sign: .plus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as W)).nonzeroBitCount, UInt.bitWidth * 0 + 1) + XCTAssertEqual(T(sign: .plus, magnitude: M(words:[ 1, 0, 0, ~0/2 + 1] as W)).nonzeroBitCount, UInt.bitWidth * 0 + 2) - XCTAssertEqual(T(sign: .minus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as [UInt])).nonzeroBitCount, UInt.bitWidth * 0 + 2) - XCTAssertEqual(T(sign: .minus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as [UInt])).nonzeroBitCount, UInt.bitWidth * 0 + 1) - XCTAssertEqual(T(sign: .minus, magnitude: M(words:[ 1, 0, 0, ~0/2 + 1] as [UInt])).nonzeroBitCount, UInt.bitWidth * 5 - 1) + XCTAssertEqual(T(sign: .minus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as W)).nonzeroBitCount, UInt.bitWidth * 0 + 2) + XCTAssertEqual(T(sign: .minus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as W)).nonzeroBitCount, UInt.bitWidth * 0 + 1) + XCTAssertEqual(T(sign: .minus, magnitude: M(words:[ 1, 0, 0, ~0/2 + 1] as W)).nonzeroBitCount, UInt.bitWidth * 5 - 1) } func testLeadingZeroBitCount() { XCTAssertEqual(T(sign: .minus, magnitude: M.zero).leadingZeroBitCount, UInt.bitWidth * 1) - XCTAssertEqual(T(words:[ 0, 0, 0, 0] as [UInt]).leadingZeroBitCount, UInt.bitWidth * 1) - XCTAssertEqual(T(words:[ 1, 1, 1, 1] as [UInt]).leadingZeroBitCount, UInt.bitWidth * 1 - 1) - XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as [UInt]).leadingZeroBitCount, UInt.bitWidth * 0) + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).leadingZeroBitCount, UInt.bitWidth * 1) + XCTAssertEqual(T(words:[ 1, 1, 1, 1] as W).leadingZeroBitCount, UInt.bitWidth * 1 - 1) + XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).leadingZeroBitCount, UInt.bitWidth * 0) - XCTAssertEqual(T(words:[ 2, 0, 0, 0] as [UInt]).leadingZeroBitCount, UInt.bitWidth * 1 - 2) - XCTAssertEqual(T(words:[ 0, 2, 0, 0] as [UInt]).leadingZeroBitCount, UInt.bitWidth * 1 - 2) - XCTAssertEqual(T(words:[ 0, 0, 2, 0] as [UInt]).leadingZeroBitCount, UInt.bitWidth * 1 - 2) - XCTAssertEqual(T(words:[ 0, 0, 0, 2] as [UInt]).leadingZeroBitCount, UInt.bitWidth * 1 - 2) + XCTAssertEqual(T(words:[ 2, 0, 0, 0] as W).leadingZeroBitCount, UInt.bitWidth * 1 - 2) + XCTAssertEqual(T(words:[ 0, 2, 0, 0] as W).leadingZeroBitCount, UInt.bitWidth * 1 - 2) + XCTAssertEqual(T(words:[ 0, 0, 2, 0] as W).leadingZeroBitCount, UInt.bitWidth * 1 - 2) + XCTAssertEqual(T(words:[ 0, 0, 0, 2] as W).leadingZeroBitCount, UInt.bitWidth * 1 - 2) - XCTAssertEqual(T(sign: .plus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as [UInt])).leadingZeroBitCount, UInt.bitWidth * 0 + 1) - XCTAssertEqual(T(sign: .plus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as [UInt])).leadingZeroBitCount, UInt.bitWidth * 1 + 0) - XCTAssertEqual(T(sign: .plus, magnitude: M(words:[ 1, 0, 0, ~0/2 + 1] as [UInt])).leadingZeroBitCount, UInt.bitWidth * 1 + 0) + XCTAssertEqual(T(sign: .plus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as W)).leadingZeroBitCount, UInt.bitWidth * 0 + 1) + XCTAssertEqual(T(sign: .plus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as W)).leadingZeroBitCount, UInt.bitWidth * 1 + 0) + XCTAssertEqual(T(sign: .plus, magnitude: M(words:[ 1, 0, 0, ~0/2 + 1] as W)).leadingZeroBitCount, UInt.bitWidth * 1 + 0) - XCTAssertEqual(T(sign: .minus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as [UInt])).leadingZeroBitCount, UInt.bitWidth * 0 + 0) - XCTAssertEqual(T(sign: .minus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as [UInt])).leadingZeroBitCount, UInt.bitWidth * 0 + 0) - XCTAssertEqual(T(sign: .minus, magnitude: M(words:[ 1, 0, 0, ~0/2 + 1] as [UInt])).leadingZeroBitCount, UInt.bitWidth * 0 + 0) + XCTAssertEqual(T(sign: .minus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as W)).leadingZeroBitCount, UInt.bitWidth * 0 + 0) + XCTAssertEqual(T(sign: .minus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as W)).leadingZeroBitCount, UInt.bitWidth * 0 + 0) + XCTAssertEqual(T(sign: .minus, magnitude: M(words:[ 1, 0, 0, ~0/2 + 1] as W)).leadingZeroBitCount, UInt.bitWidth * 0 + 0) } func testTrailingZeroBitCount() { XCTAssertEqual(T(sign: .minus, magnitude: M.zero).trailingZeroBitCount, UInt.bitWidth * 0) - XCTAssertEqual(T(words:[ 0, 0, 0, 0] as [UInt]).trailingZeroBitCount, UInt.bitWidth * 0) - XCTAssertEqual(T(words:[ 1, 1, 1, 1] as [UInt]).trailingZeroBitCount, UInt.bitWidth * 0) - XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as [UInt]).trailingZeroBitCount, UInt.bitWidth * 0) + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).trailingZeroBitCount, UInt.bitWidth * 0) + XCTAssertEqual(T(words:[ 1, 1, 1, 1] as W).trailingZeroBitCount, UInt.bitWidth * 0) + XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).trailingZeroBitCount, UInt.bitWidth * 0) - XCTAssertEqual(T(words:[ 2, 0, 0, 0] as [UInt]).trailingZeroBitCount, UInt.bitWidth * 0 + 1) - XCTAssertEqual(T(words:[ 0, 2, 0, 0] as [UInt]).trailingZeroBitCount, UInt.bitWidth * 1 + 1) - XCTAssertEqual(T(words:[ 0, 0, 2, 0] as [UInt]).trailingZeroBitCount, UInt.bitWidth * 2 + 1) - XCTAssertEqual(T(words:[ 0, 0, 0, 2] as [UInt]).trailingZeroBitCount, UInt.bitWidth * 3 + 1) + XCTAssertEqual(T(words:[ 2, 0, 0, 0] as W).trailingZeroBitCount, UInt.bitWidth * 0 + 1) + XCTAssertEqual(T(words:[ 0, 2, 0, 0] as W).trailingZeroBitCount, UInt.bitWidth * 1 + 1) + XCTAssertEqual(T(words:[ 0, 0, 2, 0] as W).trailingZeroBitCount, UInt.bitWidth * 2 + 1) + XCTAssertEqual(T(words:[ 0, 0, 0, 2] as W).trailingZeroBitCount, UInt.bitWidth * 3 + 1) } func testMostSignificantBit() { XCTAssertEqual(T(sign: .minus, magnitude: M.zero).mostSignificantBit, false) - XCTAssertEqual(T(words:[ 0, 0, 0, 0] as [UInt]).mostSignificantBit, false) - XCTAssertEqual(T(words:[ 1, 1, 1, 1] as [UInt]).mostSignificantBit, false) - XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as [UInt]).mostSignificantBit, true ) + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).mostSignificantBit, false) + XCTAssertEqual(T(words:[ 1, 1, 1, 1] as W).mostSignificantBit, false) + XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).mostSignificantBit, true ) - XCTAssertEqual(T(words:[~0, 0, 0, 0] as [UInt]).mostSignificantBit, false) - XCTAssertEqual(T(words:[ 0, ~0, 0, 0] as [UInt]).mostSignificantBit, false) - XCTAssertEqual(T(words:[ 0, 0, ~0, 0] as [UInt]).mostSignificantBit, false) - XCTAssertEqual(T(words:[ 0, 0, 0, ~0] as [UInt]).mostSignificantBit, true ) + XCTAssertEqual(T(words:[~0, 0, 0, 0] as W).mostSignificantBit, false) + XCTAssertEqual(T(words:[ 0, ~0, 0, 0] as W).mostSignificantBit, false) + XCTAssertEqual(T(words:[ 0, 0, ~0, 0] as W).mostSignificantBit, false) + XCTAssertEqual(T(words:[ 0, 0, 0, ~0] as W).mostSignificantBit, true ) - XCTAssertEqual(T(words:[~0, 1, 0, 0] as [UInt]).mostSignificantBit, false) - XCTAssertEqual(T(words:[ 0, ~0, 1, 0] as [UInt]).mostSignificantBit, false) - XCTAssertEqual(T(words:[ 0, 0, ~0, 1] as [UInt]).mostSignificantBit, false) - XCTAssertEqual(T(words:[ 1, 0, 0, ~0] as [UInt]).mostSignificantBit, true ) + XCTAssertEqual(T(words:[~0, 1, 0, 0] as W).mostSignificantBit, false) + XCTAssertEqual(T(words:[ 0, ~0, 1, 0] as W).mostSignificantBit, false) + XCTAssertEqual(T(words:[ 0, 0, ~0, 1] as W).mostSignificantBit, false) + XCTAssertEqual(T(words:[ 1, 0, 0, ~0] as W).mostSignificantBit, true ) } func testLeastSignificantBit() { XCTAssertEqual(T(sign: .minus, magnitude: M.zero).leastSignificantBit, false) - XCTAssertEqual(T(words:[ 0, 0, 0, 0] as [UInt]).leastSignificantBit, false) - XCTAssertEqual(T(words:[ 1, 1, 1, 1] as [UInt]).leastSignificantBit, true ) - XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as [UInt]).leastSignificantBit, true ) + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).leastSignificantBit, false) + XCTAssertEqual(T(words:[ 1, 1, 1, 1] as W).leastSignificantBit, true ) + XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).leastSignificantBit, true ) - XCTAssertEqual(T(words:[~0, 0, 0, 0] as [UInt]).leastSignificantBit, true ) - XCTAssertEqual(T(words:[ 0, ~0, 0, 0] as [UInt]).leastSignificantBit, false) - XCTAssertEqual(T(words:[ 0, 0, ~0, 0] as [UInt]).leastSignificantBit, false) - XCTAssertEqual(T(words:[ 0, 0, 0, ~0] as [UInt]).leastSignificantBit, false) + XCTAssertEqual(T(words:[~0, 0, 0, 0] as W).leastSignificantBit, true ) + XCTAssertEqual(T(words:[ 0, ~0, 0, 0] as W).leastSignificantBit, false) + XCTAssertEqual(T(words:[ 0, 0, ~0, 0] as W).leastSignificantBit, false) + XCTAssertEqual(T(words:[ 0, 0, 0, ~0] as W).leastSignificantBit, false) - XCTAssertEqual(T(words:[~0, 1, 0, 0] as [UInt]).leastSignificantBit, true ) - XCTAssertEqual(T(words:[ 0, ~0, 1, 0] as [UInt]).leastSignificantBit, false) - XCTAssertEqual(T(words:[ 0, 0, ~0, 1] as [UInt]).leastSignificantBit, false) - XCTAssertEqual(T(words:[ 1, 0, 0, ~0] as [UInt]).leastSignificantBit, true ) + XCTAssertEqual(T(words:[~0, 1, 0, 0] as W).leastSignificantBit, true ) + XCTAssertEqual(T(words:[ 0, ~0, 1, 0] as W).leastSignificantBit, false) + XCTAssertEqual(T(words:[ 0, 0, ~0, 1] as W).leastSignificantBit, false) + XCTAssertEqual(T(words:[ 1, 0, 0, ~0] as W).leastSignificantBit, true ) } } @@ -148,63 +149,63 @@ final class UIntXLTestsOnBits: XCTestCase { } func testBitWidth() { - XCTAssertEqual(T(words:[ 0, 0, 0, 0] as [UInt]).bitWidth, UInt.bitWidth * 0) - XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as [UInt]).bitWidth, UInt.bitWidth * 4) + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).bitWidth, UInt.bitWidth * 0) + XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).bitWidth, UInt.bitWidth * 4) } func testNonzeroBitCount() { - XCTAssertEqual(T(words:[ 0, 0, 0, 0] as [UInt]).nonzeroBitCount, 0) - XCTAssertEqual(T(words:[ 1, 1, 1, 1] as [UInt]).nonzeroBitCount, 4) + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).nonzeroBitCount, 0) + XCTAssertEqual(T(words:[ 1, 1, 1, 1] as W).nonzeroBitCount, 4) } func testLeadingZeroBitCount() { - XCTAssertEqual(T(words:[ 0, 0, 0, 0] as [UInt]).leadingZeroBitCount, UInt.bitWidth * 0) - XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as [UInt]).leadingZeroBitCount, UInt.bitWidth * 0) + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).leadingZeroBitCount, UInt.bitWidth * 0) + XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).leadingZeroBitCount, UInt.bitWidth * 0) - XCTAssertEqual(T(words:[ 2, 0, 0, 0] as [UInt]).leadingZeroBitCount, UInt.bitWidth * 1 - 2) - XCTAssertEqual(T(words:[ 0, 2, 0, 0] as [UInt]).leadingZeroBitCount, UInt.bitWidth * 1 - 2) - XCTAssertEqual(T(words:[ 0, 0, 2, 0] as [UInt]).leadingZeroBitCount, UInt.bitWidth * 1 - 2) - XCTAssertEqual(T(words:[ 0, 0, 0, 2] as [UInt]).leadingZeroBitCount, UInt.bitWidth * 1 - 2) + XCTAssertEqual(T(words:[ 2, 0, 0, 0] as W).leadingZeroBitCount, UInt.bitWidth * 1 - 2) + XCTAssertEqual(T(words:[ 0, 2, 0, 0] as W).leadingZeroBitCount, UInt.bitWidth * 1 - 2) + XCTAssertEqual(T(words:[ 0, 0, 2, 0] as W).leadingZeroBitCount, UInt.bitWidth * 1 - 2) + XCTAssertEqual(T(words:[ 0, 0, 0, 2] as W).leadingZeroBitCount, UInt.bitWidth * 1 - 2) } func testTrailingZeroBitCount() { - XCTAssertEqual(T(words:[ 0, 0, 0, 0] as [UInt]).trailingZeroBitCount, UInt.bitWidth * 0) - XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as [UInt]).trailingZeroBitCount, UInt.bitWidth * 0) + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).trailingZeroBitCount, UInt.bitWidth * 0) + XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).trailingZeroBitCount, UInt.bitWidth * 0) - XCTAssertEqual(T(words:[ 2, 0, 0, 0] as [UInt]).trailingZeroBitCount, UInt.bitWidth * 0 + 1) - XCTAssertEqual(T(words:[ 0, 2, 0, 0] as [UInt]).trailingZeroBitCount, UInt.bitWidth * 1 + 1) - XCTAssertEqual(T(words:[ 0, 0, 2, 0] as [UInt]).trailingZeroBitCount, UInt.bitWidth * 2 + 1) - XCTAssertEqual(T(words:[ 0, 0, 0, 2] as [UInt]).trailingZeroBitCount, UInt.bitWidth * 3 + 1) + XCTAssertEqual(T(words:[ 2, 0, 0, 0] as W).trailingZeroBitCount, UInt.bitWidth * 0 + 1) + XCTAssertEqual(T(words:[ 0, 2, 0, 0] as W).trailingZeroBitCount, UInt.bitWidth * 1 + 1) + XCTAssertEqual(T(words:[ 0, 0, 2, 0] as W).trailingZeroBitCount, UInt.bitWidth * 2 + 1) + XCTAssertEqual(T(words:[ 0, 0, 0, 2] as W).trailingZeroBitCount, UInt.bitWidth * 3 + 1) } func testMostSignificantBit() { - XCTAssertEqual(T(words:[ 0, 0, 0, 0] as [UInt]).mostSignificantBit, false) - XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as [UInt]).mostSignificantBit, true ) + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).mostSignificantBit, false) + XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).mostSignificantBit, true ) - XCTAssertEqual(T(words:[~0, 0, 0, 0] as [UInt]).mostSignificantBit, true ) - XCTAssertEqual(T(words:[ 0, ~0, 0, 0] as [UInt]).mostSignificantBit, true ) - XCTAssertEqual(T(words:[ 0, 0, ~0, 0] as [UInt]).mostSignificantBit, true ) - XCTAssertEqual(T(words:[ 0, 0, 0, ~0] as [UInt]).mostSignificantBit, true ) + XCTAssertEqual(T(words:[~0, 0, 0, 0] as W).mostSignificantBit, true ) + XCTAssertEqual(T(words:[ 0, ~0, 0, 0] as W).mostSignificantBit, true ) + XCTAssertEqual(T(words:[ 0, 0, ~0, 0] as W).mostSignificantBit, true ) + XCTAssertEqual(T(words:[ 0, 0, 0, ~0] as W).mostSignificantBit, true ) - XCTAssertEqual(T(words:[~0, 1, 0, 0] as [UInt]).mostSignificantBit, false) - XCTAssertEqual(T(words:[ 0, ~0, 1, 0] as [UInt]).mostSignificantBit, false) - XCTAssertEqual(T(words:[ 0, 0, ~0, 1] as [UInt]).mostSignificantBit, false) - XCTAssertEqual(T(words:[ 1, 0, 0, ~0] as [UInt]).mostSignificantBit, true ) + XCTAssertEqual(T(words:[~0, 1, 0, 0] as W).mostSignificantBit, false) + XCTAssertEqual(T(words:[ 0, ~0, 1, 0] as W).mostSignificantBit, false) + XCTAssertEqual(T(words:[ 0, 0, ~0, 1] as W).mostSignificantBit, false) + XCTAssertEqual(T(words:[ 1, 0, 0, ~0] as W).mostSignificantBit, true ) } func testLeastSignificantBit() { - XCTAssertEqual(T(words:[ 0, 0, 0, 0] as [UInt]).leastSignificantBit, false) - XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as [UInt]).leastSignificantBit, true ) + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).leastSignificantBit, false) + XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).leastSignificantBit, true ) - XCTAssertEqual(T(words:[~0, 0, 0, 0] as [UInt]).leastSignificantBit, true ) - XCTAssertEqual(T(words:[ 0, ~0, 0, 0] as [UInt]).leastSignificantBit, false) - XCTAssertEqual(T(words:[ 0, 0, ~0, 0] as [UInt]).leastSignificantBit, false) - XCTAssertEqual(T(words:[ 0, 0, 0, ~0] as [UInt]).leastSignificantBit, false) + XCTAssertEqual(T(words:[~0, 0, 0, 0] as W).leastSignificantBit, true ) + XCTAssertEqual(T(words:[ 0, ~0, 0, 0] as W).leastSignificantBit, false) + XCTAssertEqual(T(words:[ 0, 0, ~0, 0] as W).leastSignificantBit, false) + XCTAssertEqual(T(words:[ 0, 0, 0, ~0] as W).leastSignificantBit, false) - XCTAssertEqual(T(words:[~0, 1, 0, 0] as [UInt]).leastSignificantBit, true ) - XCTAssertEqual(T(words:[ 0, ~0, 1, 0] as [UInt]).leastSignificantBit, false) - XCTAssertEqual(T(words:[ 0, 0, ~0, 1] as [UInt]).leastSignificantBit, false) - XCTAssertEqual(T(words:[ 1, 0, 0, ~0] as [UInt]).leastSignificantBit, true ) + XCTAssertEqual(T(words:[~0, 1, 0, 0] as W).leastSignificantBit, true ) + XCTAssertEqual(T(words:[ 0, ~0, 1, 0] as W).leastSignificantBit, false) + XCTAssertEqual(T(words:[ 0, 0, ~0, 1] as W).leastSignificantBit, false) + XCTAssertEqual(T(words:[ 1, 0, 0, ~0] as W).leastSignificantBit, true ) } } diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Comparisons.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Comparisons.swift index 88223a97..093fc67f 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Comparisons.swift +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Comparisons.swift @@ -13,6 +13,7 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest +private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] @@ -33,101 +34,101 @@ final class IntXLTestsOnComparisons: XCTestCase { XCTAssertTrue (T(sign: .plus, magnitude: M( )).isZero) XCTAssertTrue (T(sign: .minus, magnitude: M( )).isZero) - XCTAssertTrue (T(words:[ 0] as [UInt]).isZero) - XCTAssertFalse(T(words:[ 1] as [UInt]).isZero) - XCTAssertFalse(T(words:[ 2] as [UInt]).isZero) + XCTAssertTrue (T(words:[ 0] as W).isZero) + XCTAssertFalse(T(words:[ 1] as W).isZero) + XCTAssertFalse(T(words:[ 2] as W).isZero) - XCTAssertFalse(T(words:[~0] as [UInt]).isZero) - XCTAssertFalse(T(words:[~1] as [UInt]).isZero) - XCTAssertFalse(T(words:[~2] as [UInt]).isZero) + XCTAssertFalse(T(words:[~0] as W).isZero) + XCTAssertFalse(T(words:[~1] as W).isZero) + XCTAssertFalse(T(words:[~2] as W).isZero) } func testIsLessThanZero() { XCTAssertFalse(T(sign: .plus, magnitude: M( )).isLessThanZero) XCTAssertFalse(T(sign: .minus, magnitude: M( )).isLessThanZero) - XCTAssertFalse(T(words:[ 0] as [UInt]).isLessThanZero) - XCTAssertFalse(T(words:[ 1] as [UInt]).isLessThanZero) - XCTAssertFalse(T(words:[ 2] as [UInt]).isLessThanZero) + XCTAssertFalse(T(words:[ 0] as W).isLessThanZero) + XCTAssertFalse(T(words:[ 1] as W).isLessThanZero) + XCTAssertFalse(T(words:[ 2] as W).isLessThanZero) - XCTAssertTrue (T(words:[~0] as [UInt]).isLessThanZero) - XCTAssertTrue (T(words:[~1] as [UInt]).isLessThanZero) - XCTAssertTrue (T(words:[~2] as [UInt]).isLessThanZero) + XCTAssertTrue (T(words:[~0] as W).isLessThanZero) + XCTAssertTrue (T(words:[~1] as W).isLessThanZero) + XCTAssertTrue (T(words:[~2] as W).isLessThanZero) } func testIsMoreThanZero() { XCTAssertFalse(T(sign: .plus, magnitude: M( )).isMoreThanZero) XCTAssertFalse(T(sign: .minus, magnitude: M( )).isMoreThanZero) - XCTAssertFalse(T(words:[ 0] as [UInt]).isMoreThanZero) - XCTAssertTrue (T(words:[ 1] as [UInt]).isMoreThanZero) - XCTAssertTrue (T(words:[ 2] as [UInt]).isMoreThanZero) + XCTAssertFalse(T(words:[ 0] as W).isMoreThanZero) + XCTAssertTrue (T(words:[ 1] as W).isMoreThanZero) + XCTAssertTrue (T(words:[ 2] as W).isMoreThanZero) - XCTAssertFalse(T(words:[~0] as [UInt]).isMoreThanZero) - XCTAssertFalse(T(words:[~1] as [UInt]).isMoreThanZero) - XCTAssertFalse(T(words:[~2] as [UInt]).isMoreThanZero) + XCTAssertFalse(T(words:[~0] as W).isMoreThanZero) + XCTAssertFalse(T(words:[~1] as W).isMoreThanZero) + XCTAssertFalse(T(words:[~2] as W).isMoreThanZero) } func testIsOdd() { XCTAssertFalse(T(sign: .plus, magnitude: M( )).isOdd) XCTAssertFalse(T(sign: .minus, magnitude: M( )).isOdd) - XCTAssertFalse(T(words:[ 0] as [UInt]).isOdd) - XCTAssertTrue (T(words:[ 1] as [UInt]).isOdd) - XCTAssertFalse(T(words:[ 2] as [UInt]).isOdd) + XCTAssertFalse(T(words:[ 0] as W).isOdd) + XCTAssertTrue (T(words:[ 1] as W).isOdd) + XCTAssertFalse(T(words:[ 2] as W).isOdd) - XCTAssertTrue (T(words:[~0] as [UInt]).isOdd) - XCTAssertFalse(T(words:[~1] as [UInt]).isOdd) - XCTAssertTrue (T(words:[~2] as [UInt]).isOdd) + XCTAssertTrue (T(words:[~0] as W).isOdd) + XCTAssertFalse(T(words:[~1] as W).isOdd) + XCTAssertTrue (T(words:[~2] as W).isOdd) } func testIsEven() { XCTAssertTrue (T(sign: .plus, magnitude: M( )).isEven) XCTAssertTrue (T(sign: .minus, magnitude: M( )).isEven) - XCTAssertTrue (T(words:[ 0] as [UInt]).isEven) - XCTAssertFalse(T(words:[ 1] as [UInt]).isEven) - XCTAssertTrue (T(words:[ 2] as [UInt]).isEven) + XCTAssertTrue (T(words:[ 0] as W).isEven) + XCTAssertFalse(T(words:[ 1] as W).isEven) + XCTAssertTrue (T(words:[ 2] as W).isEven) - XCTAssertFalse(T(words:[~0] as [UInt]).isEven) - XCTAssertTrue (T(words:[~1] as [UInt]).isEven) - XCTAssertFalse(T(words:[~2] as [UInt]).isEven) + XCTAssertFalse(T(words:[~0] as W).isEven) + XCTAssertTrue (T(words:[~1] as W).isEven) + XCTAssertFalse(T(words:[~2] as W).isEven) } func testIsPowerOf2() { XCTAssertFalse(T(sign: .plus, magnitude: M( )).isPowerOf2) XCTAssertFalse(T(sign: .minus, magnitude: M( )).isPowerOf2) - XCTAssertFalse(T(words:[~3] as [UInt]).isPowerOf2) - XCTAssertFalse(T(words:[~2] as [UInt]).isPowerOf2) - XCTAssertFalse(T(words:[~1] as [UInt]).isPowerOf2) - XCTAssertFalse(T(words:[~0] as [UInt]).isPowerOf2) - XCTAssertFalse(T(words:[ 0] as [UInt]).isPowerOf2) - XCTAssertTrue (T(words:[ 1] as [UInt]).isPowerOf2) - XCTAssertTrue (T(words:[ 2] as [UInt]).isPowerOf2) - XCTAssertFalse(T(words:[ 3] as [UInt]).isPowerOf2) - - XCTAssertFalse(T(words:[ 0, 0, 0, 0] as [UInt]).isPowerOf2) - XCTAssertTrue (T(words:[ 1, 0, 0, 0] as [UInt]).isPowerOf2) - XCTAssertFalse(T(words:[ 1, 1, 0, 0] as [UInt]).isPowerOf2) - XCTAssertTrue (T(words:[ 0, 1, 0, 0] as [UInt]).isPowerOf2) - XCTAssertFalse(T(words:[ 0, 1, 1, 0] as [UInt]).isPowerOf2) - XCTAssertTrue (T(words:[ 0, 0, 1, 0] as [UInt]).isPowerOf2) - XCTAssertFalse(T(words:[ 0, 0, 1, 1] as [UInt]).isPowerOf2) - XCTAssertTrue (T(words:[ 0, 0, 0, 1] as [UInt]).isPowerOf2) + XCTAssertFalse(T(words:[~3] as W).isPowerOf2) + XCTAssertFalse(T(words:[~2] as W).isPowerOf2) + XCTAssertFalse(T(words:[~1] as W).isPowerOf2) + XCTAssertFalse(T(words:[~0] as W).isPowerOf2) + XCTAssertFalse(T(words:[ 0] as W).isPowerOf2) + XCTAssertTrue (T(words:[ 1] as W).isPowerOf2) + XCTAssertTrue (T(words:[ 2] as W).isPowerOf2) + XCTAssertFalse(T(words:[ 3] as W).isPowerOf2) + + XCTAssertFalse(T(words:[ 0, 0, 0, 0] as W).isPowerOf2) + XCTAssertTrue (T(words:[ 1, 0, 0, 0] as W).isPowerOf2) + XCTAssertFalse(T(words:[ 1, 1, 0, 0] as W).isPowerOf2) + XCTAssertTrue (T(words:[ 0, 1, 0, 0] as W).isPowerOf2) + XCTAssertFalse(T(words:[ 0, 1, 1, 0] as W).isPowerOf2) + XCTAssertTrue (T(words:[ 0, 0, 1, 0] as W).isPowerOf2) + XCTAssertFalse(T(words:[ 0, 0, 1, 1] as W).isPowerOf2) + XCTAssertTrue (T(words:[ 0, 0, 0, 1] as W).isPowerOf2) } func testSignum() { NBKAssertSignum(T(sign: .plus, magnitude: M( )), Int( 0)) NBKAssertSignum(T(sign: .minus, magnitude: M( )), Int( 0)) - NBKAssertSignum(T(words:[ 0] as [UInt]), Int( 0)) - NBKAssertSignum(T(words:[ 1] as [UInt]), Int( 1)) - NBKAssertSignum(T(words:[ 2] as [UInt]), Int( 1)) + NBKAssertSignum(T(words:[ 0] as W), Int( 0)) + NBKAssertSignum(T(words:[ 1] as W), Int( 1)) + NBKAssertSignum(T(words:[ 2] as W), Int( 1)) - NBKAssertSignum(T(words:[~0] as [UInt]), Int(-1)) - NBKAssertSignum(T(words:[~1] as [UInt]), Int(-1)) - NBKAssertSignum(T(words:[~2] as [UInt]), Int(-1)) + NBKAssertSignum(T(words:[~0] as W), Int(-1)) + NBKAssertSignum(T(words:[~1] as W), Int(-1)) + NBKAssertSignum(T(words:[~2] as W), Int(-1)) } //=------------------------------------------------------------------------= @@ -138,16 +139,16 @@ final class IntXLTestsOnComparisons: XCTestCase { var union = Set() union.insert(T(sign: .minus, magnitude: M())) union.insert(T(sign: .minus, magnitude: M())) - union.insert(T(words:[0, 0, 0, 0] as [UInt])) - union.insert(T(words:[0, 0, 0, 0] as [UInt])) - union.insert(T(words:[1, 0, 0, 0] as [UInt])) - union.insert(T(words:[1, 0, 0, 0] as [UInt])) - union.insert(T(words:[0, 1, 0, 0] as [UInt])) - union.insert(T(words:[0, 1, 0, 0] as [UInt])) - union.insert(T(words:[0, 0, 1, 0] as [UInt])) - union.insert(T(words:[0, 0, 1, 0] as [UInt])) - union.insert(T(words:[0, 0, 0, 1] as [UInt])) - union.insert(T(words:[0, 0, 0, 1] as [UInt])) + union.insert(T(words:[0, 0, 0, 0] as W)) + union.insert(T(words:[0, 0, 0, 0] as W)) + union.insert(T(words:[1, 0, 0, 0] as W)) + union.insert(T(words:[1, 0, 0, 0] as W)) + union.insert(T(words:[0, 1, 0, 0] as W)) + union.insert(T(words:[0, 1, 0, 0] as W)) + union.insert(T(words:[0, 0, 1, 0] as W)) + union.insert(T(words:[0, 0, 1, 0] as W)) + union.insert(T(words:[0, 0, 0, 1] as W)) + union.insert(T(words:[0, 0, 0, 1] as W)) XCTAssertEqual(union.count, 5 as Int) } @@ -172,18 +173,18 @@ final class IntXLTestsOnComparisons: XCTestCase { NBKAssertComparisons(-T(3), T(2), -Int(1)) NBKAssertComparisons(-T(3), -T(2), -Int(1)) - NBKAssertComparisons(T(words:[0, 2, 3, 4] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), -Int(1)) - NBKAssertComparisons(T(words:[1, 0, 3, 4] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), -Int(1)) - NBKAssertComparisons(T(words:[1, 2, 0, 4] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), -Int(1)) - NBKAssertComparisons(T(words:[1, 2, 3, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), -Int(1)) - NBKAssertComparisons(T(words:[0, 2, 3, 4] as [UInt]), T(words:[0, 2, 3, 4] as [UInt]), Int(0)) - NBKAssertComparisons(T(words:[1, 0, 3, 4] as [UInt]), T(words:[1, 0, 3, 4] as [UInt]), Int(0)) - NBKAssertComparisons(T(words:[1, 2, 0, 4] as [UInt]), T(words:[1, 2, 0, 4] as [UInt]), Int(0)) - NBKAssertComparisons(T(words:[1, 2, 3, 0] as [UInt]), T(words:[1, 2, 3, 0] as [UInt]), Int(0)) - NBKAssertComparisons(T(words:[1, 2, 3, 4] as [UInt]), T(words:[0, 2, 3, 4] as [UInt]), Int(1)) - NBKAssertComparisons(T(words:[1, 2, 3, 4] as [UInt]), T(words:[1, 0, 3, 4] as [UInt]), Int(1)) - NBKAssertComparisons(T(words:[1, 2, 3, 4] as [UInt]), T(words:[1, 2, 0, 4] as [UInt]), Int(1)) - NBKAssertComparisons(T(words:[1, 2, 3, 4] as [UInt]), T(words:[1, 2, 3, 0] as [UInt]), Int(1)) + NBKAssertComparisons(T(words:[0, 2, 3, 4] as W), T(words:[1, 2, 3, 4] as W), -Int(1)) + NBKAssertComparisons(T(words:[1, 0, 3, 4] as W), T(words:[1, 2, 3, 4] as W), -Int(1)) + NBKAssertComparisons(T(words:[1, 2, 0, 4] as W), T(words:[1, 2, 3, 4] as W), -Int(1)) + NBKAssertComparisons(T(words:[1, 2, 3, 0] as W), T(words:[1, 2, 3, 4] as W), -Int(1)) + NBKAssertComparisons(T(words:[0, 2, 3, 4] as W), T(words:[0, 2, 3, 4] as W), Int(0)) + NBKAssertComparisons(T(words:[1, 0, 3, 4] as W), T(words:[1, 0, 3, 4] as W), Int(0)) + NBKAssertComparisons(T(words:[1, 2, 0, 4] as W), T(words:[1, 2, 0, 4] as W), Int(0)) + NBKAssertComparisons(T(words:[1, 2, 3, 0] as W), T(words:[1, 2, 3, 0] as W), Int(0)) + NBKAssertComparisons(T(words:[1, 2, 3, 4] as W), T(words:[0, 2, 3, 4] as W), Int(1)) + NBKAssertComparisons(T(words:[1, 2, 3, 4] as W), T(words:[1, 0, 3, 4] as W), Int(1)) + NBKAssertComparisons(T(words:[1, 2, 3, 4] as W), T(words:[1, 2, 0, 4] as W), Int(1)) + NBKAssertComparisons(T(words:[1, 2, 3, 4] as W), T(words:[1, 2, 3, 0] as W), Int(1)) } func testComparingAtIndex() { @@ -207,29 +208,29 @@ final class IntXLTestsOnComparisons: XCTestCase { NBKAssertComparisonsAtIndex(-T(3), T(2), Int(4), -Int(1)) NBKAssertComparisonsAtIndex(-T(3), -T(2), Int(4), Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(0), Int(0)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(1), Int(0)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(2), Int(0)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(3), Int(0)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(4), Int(0)) - - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(0), -Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(1), -Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(2), -Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(3), -Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(4), -Int(1)) - - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(0), Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(1), Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(2), Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(3), Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(4), Int(1)) - - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(0), Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(1), Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(2), Int(0)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(3), -Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(4), -Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(0), Int(0)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(1), Int(0)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(2), Int(0)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(3), Int(0)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(4), Int(0)) + + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(0), -Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(1), -Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(2), -Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(3), -Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(4), -Int(1)) + + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(0), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(1), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(2), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(3), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(4), Int(1)) + + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(0), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(1), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(2), Int(0)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(3), -Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(4), -Int(1)) } //=------------------------------------------------------------------------= @@ -334,83 +335,83 @@ final class UIntXLTestsOnComparisons: XCTestCase { //=------------------------------------------------------------------------= func testIsZero() { - XCTAssertTrue (T(words:[ 0] as [UInt]).isZero) - XCTAssertFalse(T(words:[ 1] as [UInt]).isZero) - XCTAssertFalse(T(words:[ 2] as [UInt]).isZero) + XCTAssertTrue (T(words:[ 0] as W).isZero) + XCTAssertFalse(T(words:[ 1] as W).isZero) + XCTAssertFalse(T(words:[ 2] as W).isZero) - XCTAssertFalse(T(words:[~0] as [UInt]).isZero) - XCTAssertFalse(T(words:[~1] as [UInt]).isZero) - XCTAssertFalse(T(words:[~2] as [UInt]).isZero) + XCTAssertFalse(T(words:[~0] as W).isZero) + XCTAssertFalse(T(words:[~1] as W).isZero) + XCTAssertFalse(T(words:[~2] as W).isZero) } func testIsLessThanZero() { - XCTAssertFalse(T(words:[ 0] as [UInt]).isLessThanZero) - XCTAssertFalse(T(words:[ 1] as [UInt]).isLessThanZero) - XCTAssertFalse(T(words:[ 2] as [UInt]).isLessThanZero) + XCTAssertFalse(T(words:[ 0] as W).isLessThanZero) + XCTAssertFalse(T(words:[ 1] as W).isLessThanZero) + XCTAssertFalse(T(words:[ 2] as W).isLessThanZero) - XCTAssertFalse(T(words:[~0] as [UInt]).isLessThanZero) - XCTAssertFalse(T(words:[~1] as [UInt]).isLessThanZero) - XCTAssertFalse(T(words:[~2] as [UInt]).isLessThanZero) + XCTAssertFalse(T(words:[~0] as W).isLessThanZero) + XCTAssertFalse(T(words:[~1] as W).isLessThanZero) + XCTAssertFalse(T(words:[~2] as W).isLessThanZero) } func testIsMoreThanZero() { - XCTAssertFalse(T(words:[ 0] as [UInt]).isMoreThanZero) - XCTAssertTrue (T(words:[ 1] as [UInt]).isMoreThanZero) - XCTAssertTrue (T(words:[ 2] as [UInt]).isMoreThanZero) + XCTAssertFalse(T(words:[ 0] as W).isMoreThanZero) + XCTAssertTrue (T(words:[ 1] as W).isMoreThanZero) + XCTAssertTrue (T(words:[ 2] as W).isMoreThanZero) - XCTAssertTrue (T(words:[~0] as [UInt]).isMoreThanZero) - XCTAssertTrue (T(words:[~1] as [UInt]).isMoreThanZero) - XCTAssertTrue (T(words:[~2] as [UInt]).isMoreThanZero) + XCTAssertTrue (T(words:[~0] as W).isMoreThanZero) + XCTAssertTrue (T(words:[~1] as W).isMoreThanZero) + XCTAssertTrue (T(words:[~2] as W).isMoreThanZero) } func testIsOdd() { - XCTAssertFalse(T(words:[ 0] as [UInt]).isOdd) - XCTAssertTrue (T(words:[ 1] as [UInt]).isOdd) - XCTAssertFalse(T(words:[ 2] as [UInt]).isOdd) + XCTAssertFalse(T(words:[ 0] as W).isOdd) + XCTAssertTrue (T(words:[ 1] as W).isOdd) + XCTAssertFalse(T(words:[ 2] as W).isOdd) - XCTAssertTrue (T(words:[~0] as [UInt]).isOdd) - XCTAssertFalse(T(words:[~1] as [UInt]).isOdd) - XCTAssertTrue (T(words:[~2] as [UInt]).isOdd) + XCTAssertTrue (T(words:[~0] as W).isOdd) + XCTAssertFalse(T(words:[~1] as W).isOdd) + XCTAssertTrue (T(words:[~2] as W).isOdd) } func testIsEven() { - XCTAssertTrue (T(words:[ 0] as [UInt]).isEven) - XCTAssertFalse(T(words:[ 1] as [UInt]).isEven) - XCTAssertTrue (T(words:[ 2] as [UInt]).isEven) + XCTAssertTrue (T(words:[ 0] as W).isEven) + XCTAssertFalse(T(words:[ 1] as W).isEven) + XCTAssertTrue (T(words:[ 2] as W).isEven) - XCTAssertFalse(T(words:[~0] as [UInt]).isEven) - XCTAssertTrue (T(words:[~1] as [UInt]).isEven) - XCTAssertFalse(T(words:[~2] as [UInt]).isEven) + XCTAssertFalse(T(words:[~0] as W).isEven) + XCTAssertTrue (T(words:[~1] as W).isEven) + XCTAssertFalse(T(words:[~2] as W).isEven) } func testIsPowerOf2() { - XCTAssertFalse(T(words:[ 0] as [UInt]).isPowerOf2) - XCTAssertTrue (T(words:[ 1] as [UInt]).isPowerOf2) - XCTAssertTrue (T(words:[ 2] as [UInt]).isPowerOf2) - XCTAssertFalse(T(words:[ 3] as [UInt]).isPowerOf2) - XCTAssertTrue (T(words:[ 4] as [UInt]).isPowerOf2) - XCTAssertFalse(T(words:[ 5] as [UInt]).isPowerOf2) - XCTAssertFalse(T(words:[ 6] as [UInt]).isPowerOf2) - XCTAssertFalse(T(words:[ 7] as [UInt]).isPowerOf2) - - XCTAssertFalse(T(words:[ 0, 0, 0, 0] as [UInt]).isPowerOf2) - XCTAssertTrue (T(words:[ 1, 0, 0, 0] as [UInt]).isPowerOf2) - XCTAssertFalse(T(words:[ 1, 1, 0, 0] as [UInt]).isPowerOf2) - XCTAssertTrue (T(words:[ 0, 1, 0, 0] as [UInt]).isPowerOf2) - XCTAssertFalse(T(words:[ 0, 1, 1, 0] as [UInt]).isPowerOf2) - XCTAssertTrue (T(words:[ 0, 0, 1, 0] as [UInt]).isPowerOf2) - XCTAssertFalse(T(words:[ 0, 0, 1, 1] as [UInt]).isPowerOf2) - XCTAssertTrue (T(words:[ 0, 0, 0, 1] as [UInt]).isPowerOf2) + XCTAssertFalse(T(words:[ 0] as W).isPowerOf2) + XCTAssertTrue (T(words:[ 1] as W).isPowerOf2) + XCTAssertTrue (T(words:[ 2] as W).isPowerOf2) + XCTAssertFalse(T(words:[ 3] as W).isPowerOf2) + XCTAssertTrue (T(words:[ 4] as W).isPowerOf2) + XCTAssertFalse(T(words:[ 5] as W).isPowerOf2) + XCTAssertFalse(T(words:[ 6] as W).isPowerOf2) + XCTAssertFalse(T(words:[ 7] as W).isPowerOf2) + + XCTAssertFalse(T(words:[ 0, 0, 0, 0] as W).isPowerOf2) + XCTAssertTrue (T(words:[ 1, 0, 0, 0] as W).isPowerOf2) + XCTAssertFalse(T(words:[ 1, 1, 0, 0] as W).isPowerOf2) + XCTAssertTrue (T(words:[ 0, 1, 0, 0] as W).isPowerOf2) + XCTAssertFalse(T(words:[ 0, 1, 1, 0] as W).isPowerOf2) + XCTAssertTrue (T(words:[ 0, 0, 1, 0] as W).isPowerOf2) + XCTAssertFalse(T(words:[ 0, 0, 1, 1] as W).isPowerOf2) + XCTAssertTrue (T(words:[ 0, 0, 0, 1] as W).isPowerOf2) } func testSignum() { - NBKAssertSignum(T(words:[ 0] as [UInt]), Int(0)) - NBKAssertSignum(T(words:[ 1] as [UInt]), Int(1)) - NBKAssertSignum(T(words:[ 2] as [UInt]), Int(1)) + NBKAssertSignum(T(words:[ 0] as W), Int(0)) + NBKAssertSignum(T(words:[ 1] as W), Int(1)) + NBKAssertSignum(T(words:[ 2] as W), Int(1)) - NBKAssertSignum(T(words:[~0] as [UInt]), Int(1)) - NBKAssertSignum(T(words:[~1] as [UInt]), Int(1)) - NBKAssertSignum(T(words:[~2] as [UInt]), Int(1)) + NBKAssertSignum(T(words:[~0] as W), Int(1)) + NBKAssertSignum(T(words:[~1] as W), Int(1)) + NBKAssertSignum(T(words:[~2] as W), Int(1)) } //=------------------------------------------------------------------------= @@ -419,58 +420,58 @@ final class UIntXLTestsOnComparisons: XCTestCase { func testHashing() { var union = Set() - union.insert(T(words:[0, 0, 0, 0] as [UInt])) - union.insert(T(words:[0, 0, 0, 0] as [UInt])) - union.insert(T(words:[1, 0, 0, 0] as [UInt])) - union.insert(T(words:[1, 0, 0, 0] as [UInt])) - union.insert(T(words:[0, 1, 0, 0] as [UInt])) - union.insert(T(words:[0, 1, 0, 0] as [UInt])) - union.insert(T(words:[0, 0, 1, 0] as [UInt])) - union.insert(T(words:[0, 0, 1, 0] as [UInt])) - union.insert(T(words:[0, 0, 0, 1] as [UInt])) - union.insert(T(words:[0, 0, 0, 1] as [UInt])) + union.insert(T(words:[0, 0, 0, 0] as W)) + union.insert(T(words:[0, 0, 0, 0] as W)) + union.insert(T(words:[1, 0, 0, 0] as W)) + union.insert(T(words:[1, 0, 0, 0] as W)) + union.insert(T(words:[0, 1, 0, 0] as W)) + union.insert(T(words:[0, 1, 0, 0] as W)) + union.insert(T(words:[0, 0, 1, 0] as W)) + union.insert(T(words:[0, 0, 1, 0] as W)) + union.insert(T(words:[0, 0, 0, 1] as W)) + union.insert(T(words:[0, 0, 0, 1] as W)) XCTAssertEqual(union.count, 5 as Int) } func testComparing() { - NBKAssertComparisons(T(words:[0, 2, 3, 4] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), -Int(1)) - NBKAssertComparisons(T(words:[1, 0, 3, 4] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), -Int(1)) - NBKAssertComparisons(T(words:[1, 2, 0, 4] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), -Int(1)) - NBKAssertComparisons(T(words:[1, 2, 3, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), -Int(1)) - NBKAssertComparisons(T(words:[0, 2, 3, 4] as [UInt]), T(words:[0, 2, 3, 4] as [UInt]), Int(0)) - NBKAssertComparisons(T(words:[1, 0, 3, 4] as [UInt]), T(words:[1, 0, 3, 4] as [UInt]), Int(0)) - NBKAssertComparisons(T(words:[1, 2, 0, 4] as [UInt]), T(words:[1, 2, 0, 4] as [UInt]), Int(0)) - NBKAssertComparisons(T(words:[1, 2, 3, 0] as [UInt]), T(words:[1, 2, 3, 0] as [UInt]), Int(0)) - NBKAssertComparisons(T(words:[1, 2, 3, 4] as [UInt]), T(words:[0, 2, 3, 4] as [UInt]), Int(1)) - NBKAssertComparisons(T(words:[1, 2, 3, 4] as [UInt]), T(words:[1, 0, 3, 4] as [UInt]), Int(1)) - NBKAssertComparisons(T(words:[1, 2, 3, 4] as [UInt]), T(words:[1, 2, 0, 4] as [UInt]), Int(1)) - NBKAssertComparisons(T(words:[1, 2, 3, 4] as [UInt]), T(words:[1, 2, 3, 0] as [UInt]), Int(1)) + NBKAssertComparisons(T(words:[0, 2, 3, 4] as W), T(words:[1, 2, 3, 4] as W), -Int(1)) + NBKAssertComparisons(T(words:[1, 0, 3, 4] as W), T(words:[1, 2, 3, 4] as W), -Int(1)) + NBKAssertComparisons(T(words:[1, 2, 0, 4] as W), T(words:[1, 2, 3, 4] as W), -Int(1)) + NBKAssertComparisons(T(words:[1, 2, 3, 0] as W), T(words:[1, 2, 3, 4] as W), -Int(1)) + NBKAssertComparisons(T(words:[0, 2, 3, 4] as W), T(words:[0, 2, 3, 4] as W), Int(0)) + NBKAssertComparisons(T(words:[1, 0, 3, 4] as W), T(words:[1, 0, 3, 4] as W), Int(0)) + NBKAssertComparisons(T(words:[1, 2, 0, 4] as W), T(words:[1, 2, 0, 4] as W), Int(0)) + NBKAssertComparisons(T(words:[1, 2, 3, 0] as W), T(words:[1, 2, 3, 0] as W), Int(0)) + NBKAssertComparisons(T(words:[1, 2, 3, 4] as W), T(words:[0, 2, 3, 4] as W), Int(1)) + NBKAssertComparisons(T(words:[1, 2, 3, 4] as W), T(words:[1, 0, 3, 4] as W), Int(1)) + NBKAssertComparisons(T(words:[1, 2, 3, 4] as W), T(words:[1, 2, 0, 4] as W), Int(1)) + NBKAssertComparisons(T(words:[1, 2, 3, 4] as W), T(words:[1, 2, 3, 0] as W), Int(1)) } func testComparingAtIndex() { - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(0), Int(0)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(1), Int(0)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(2), Int(0)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(3), Int(0)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(4), Int(0)) - - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(0), -Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(1), -Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(2), -Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(3), -Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(4), -Int(1)) - - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(0), Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(1), Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(2), Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(3), Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[0, 0, 0, 0] as [UInt]), Int(4), Int(1)) - - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(0), Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(1), Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(2), Int(0)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(3), -Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as [UInt]), T(words:[1, 2, 3, 4] as [UInt]), Int(4), -Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(0), Int(0)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(1), Int(0)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(2), Int(0)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(3), Int(0)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(4), Int(0)) + + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(0), -Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(1), -Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(2), -Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(3), -Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(4), -Int(1)) + + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(0), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(1), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(2), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(3), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(4), Int(1)) + + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(0), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(1), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(2), Int(0)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(3), -Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(4), -Int(1)) } func testComparingByDigit() { diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Complements.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Complements.swift index c6202dca..e41a03e4 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Complements.swift +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Complements.swift @@ -13,6 +13,7 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest +private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] @@ -30,10 +31,10 @@ final class IntXLTestsOnComplements: XCTestCase { //=------------------------------------------------------------------------= func testMagnitude() { - XCTAssertEqual(T(words:[ 1, 0, 0, 0] as [UInt]).magnitude, M(words:[ 1, 0, 0, 0] as [UInt])) - XCTAssertEqual(T(words:[~0, 0, 0, 0] as [UInt]).magnitude, M(words:[~0, 0, 0, 0] as [UInt])) - XCTAssertEqual(T(words:[ 1, 1, 1, 1] as [UInt]).magnitude, M(words:[ 1, 1, 1, 1] as [UInt])) - XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as [UInt]).magnitude, M(words:[ 1, 0, 0, 0] as [UInt])) + XCTAssertEqual(T(words:[ 1, 0, 0, 0] as W).magnitude, M(words:[ 1, 0, 0, 0] as W)) + XCTAssertEqual(T(words:[~0, 0, 0, 0] as W).magnitude, M(words:[~0, 0, 0, 0] as W)) + XCTAssertEqual(T(words:[ 1, 1, 1, 1] as W).magnitude, M(words:[ 1, 1, 1, 1] as W)) + XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).magnitude, M(words:[ 1, 0, 0, 0] as W)) } //=------------------------------------------------------------------------= @@ -46,19 +47,19 @@ final class IntXLTestsOnComplements: XCTestCase { NBKAssertOnesComplement( T(0), -T(1)) NBKAssertOnesComplement( T(1), -T(2)) - NBKAssertOnesComplement(T(words:[ 0, 0, 0, 0] as [UInt]), T(words:[~0, ~0, ~0, ~0] as [UInt])) - NBKAssertOnesComplement(T(words:[ 1, 0, 0, 0] as [UInt]), T(words:[~1, ~0, ~0, ~0] as [UInt])) - NBKAssertOnesComplement(T(words:[~0, 0, 0, 0] as [UInt]), T(words:[ 0, ~0, ~0, ~0] as [UInt])) - NBKAssertOnesComplement(T(words:[ 1, 1, 1, 1] as [UInt]), T(words:[~1, ~1, ~1, ~1] as [UInt])) - NBKAssertOnesComplement(T(words:[~0, ~0, ~0, ~0] as [UInt]), T(words:[ 0, 0, 0, 0] as [UInt])) + NBKAssertOnesComplement(T(words:[ 0, 0, 0, 0] as W), T(words:[~0, ~0, ~0, ~0] as W)) + NBKAssertOnesComplement(T(words:[ 1, 0, 0, 0] as W), T(words:[~1, ~0, ~0, ~0] as W)) + NBKAssertOnesComplement(T(words:[~0, 0, 0, 0] as W), T(words:[ 0, ~0, ~0, ~0] as W)) + NBKAssertOnesComplement(T(words:[ 1, 1, 1, 1] as W), T(words:[~1, ~1, ~1, ~1] as W)) + NBKAssertOnesComplement(T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 0, 0, 0, 0] as W)) - NBKAssertOnesComplement(T(words:[~0, ~0, ~0, ~0/2 + 0, 0] as [UInt]), T(words:[ 0, 0, 0, ~0/2 + 1, ~0] as [UInt])) - NBKAssertOnesComplement(T(words:[ 0, 0, 0, ~0/2 + 1, 0] as [UInt]), T(words:[~0, ~0, ~0, ~0/2 + 0, ~0] as [UInt])) - NBKAssertOnesComplement(T(words:[ 1, 0, 0, ~0/2 + 1, 0] as [UInt]), T(words:[~1, ~0, ~0, ~0/2 + 0, ~0] as [UInt])) + NBKAssertOnesComplement(T(words:[~0, ~0, ~0, ~0/2 + 0, 0] as W), T(words:[ 0, 0, 0, ~0/2 + 1, ~0] as W)) + NBKAssertOnesComplement(T(words:[ 0, 0, 0, ~0/2 + 1, 0] as W), T(words:[~0, ~0, ~0, ~0/2 + 0, ~0] as W)) + NBKAssertOnesComplement(T(words:[ 1, 0, 0, ~0/2 + 1, 0] as W), T(words:[~1, ~0, ~0, ~0/2 + 0, ~0] as W)) - NBKAssertOnesComplement(T(words:[ 1, 0, 0, ~0/2 + 1, ~0] as [UInt]), T(words:[~1, ~0, ~0, ~0/2 + 0, 0] as [UInt])) - NBKAssertOnesComplement(T(words:[ 0, 0, 0, ~0/2 + 1, ~0] as [UInt]), T(words:[~0, ~0, ~0, ~0/2 + 0, 0] as [UInt])) - NBKAssertOnesComplement(T(words:[~0, ~0, ~0, ~0/2 + 0, ~0] as [UInt]), T(words:[ 0, 0, 0, ~0/2 + 1, 0] as [UInt])) + NBKAssertOnesComplement(T(words:[ 1, 0, 0, ~0/2 + 1, ~0] as W), T(words:[~1, ~0, ~0, ~0/2 + 0, 0] as W)) + NBKAssertOnesComplement(T(words:[ 0, 0, 0, ~0/2 + 1, ~0] as W), T(words:[~0, ~0, ~0, ~0/2 + 0, 0] as W)) + NBKAssertOnesComplement(T(words:[~0, ~0, ~0, ~0/2 + 0, ~0] as W), T(words:[ 0, 0, 0, ~0/2 + 1, 0] as W)) } //=------------------------------------------------------------------------= @@ -71,19 +72,19 @@ final class IntXLTestsOnComplements: XCTestCase { NBKAssertTwosComplement( T(0), -T(0)) NBKAssertTwosComplement( T(1), -T(1)) - NBKAssertTwosComplement(T(words:[ 0, 0, 0, 0] as [UInt]), T(words:[ 0, 0, 0, 0] as [UInt])) - NBKAssertTwosComplement(T(words:[ 1, 0, 0, 0] as [UInt]), T(words:[~0, ~0, ~0, ~0] as [UInt])) - NBKAssertTwosComplement(T(words:[~0, 0, 0, 0] as [UInt]), T(words:[ 1, ~0, ~0, ~0] as [UInt])) - NBKAssertTwosComplement(T(words:[ 1, 1, 1, 1] as [UInt]), T(words:[~0, ~1, ~1, ~1] as [UInt])) - NBKAssertTwosComplement(T(words:[~0, ~0, ~0, ~0] as [UInt]), T(words:[ 1, 0, 0, 0] as [UInt])) + NBKAssertTwosComplement(T(words:[ 0, 0, 0, 0] as W), T(words:[ 0, 0, 0, 0] as W)) + NBKAssertTwosComplement(T(words:[ 1, 0, 0, 0] as W), T(words:[~0, ~0, ~0, ~0] as W)) + NBKAssertTwosComplement(T(words:[~0, 0, 0, 0] as W), T(words:[ 1, ~0, ~0, ~0] as W)) + NBKAssertTwosComplement(T(words:[ 1, 1, 1, 1] as W), T(words:[~0, ~1, ~1, ~1] as W)) + NBKAssertTwosComplement(T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 1, 0, 0, 0] as W)) - NBKAssertTwosComplement(T(words:[~0, ~0, ~0, ~0/2 + 0, 0] as [UInt]), T(words:[ 1, 0, 0, ~0/2 + 1, ~0] as [UInt])) - NBKAssertTwosComplement(T(words:[ 0, 0, 0, ~0/2 + 1, 0] as [UInt]), T(words:[ 0, 0, 0, ~0/2 + 1, ~0] as [UInt])) - NBKAssertTwosComplement(T(words:[ 1, 0, 0, ~0/2 + 1, 0] as [UInt]), T(words:[~0, ~0, ~0, ~0/2 + 0, ~0] as [UInt])) + NBKAssertTwosComplement(T(words:[~0, ~0, ~0, ~0/2 + 0, 0] as W), T(words:[ 1, 0, 0, ~0/2 + 1, ~0] as W)) + NBKAssertTwosComplement(T(words:[ 0, 0, 0, ~0/2 + 1, 0] as W), T(words:[ 0, 0, 0, ~0/2 + 1, ~0] as W)) + NBKAssertTwosComplement(T(words:[ 1, 0, 0, ~0/2 + 1, 0] as W), T(words:[~0, ~0, ~0, ~0/2 + 0, ~0] as W)) - NBKAssertTwosComplement(T(words:[ 1, 0, 0, ~0/2 + 1, ~0] as [UInt]), T(words:[~0, ~0, ~0, ~0/2 + 0, 0] as [UInt])) - NBKAssertTwosComplement(T(words:[ 0, 0, 0, ~0/2 + 1, ~0] as [UInt]), T(words:[ 0, 0, 0, ~0/2 + 1, ~0] as [UInt]), true) - NBKAssertTwosComplement(T(words:[~0, ~0, ~0, ~0/2 + 0, ~0] as [UInt]), T(words:[ 1, 0, 0, ~0/2 + 1, 0] as [UInt])) + NBKAssertTwosComplement(T(words:[ 1, 0, 0, ~0/2 + 1, ~0] as W), T(words:[~0, ~0, ~0, ~0/2 + 0, 0] as W)) + NBKAssertTwosComplement(T(words:[ 0, 0, 0, ~0/2 + 1, ~0] as W), T(words:[ 0, 0, 0, ~0/2 + 1, ~0] as W), true) + NBKAssertTwosComplement(T(words:[~0, ~0, ~0, ~0/2 + 0, ~0] as W), T(words:[ 1, 0, 0, ~0/2 + 1, 0] as W)) } //=------------------------------------------------------------------------= @@ -112,10 +113,10 @@ final class UIntXLTestsOnComplements: XCTestCase { //=------------------------------------------------------------------------= func testMagnitude() { - XCTAssertEqual(T(words:[ 1, 0, 0, 0] as [UInt]).magnitude, M(words:[ 1, 0, 0, 0] as [UInt])) - XCTAssertEqual(T(words:[~0, 0, 0, 0] as [UInt]).magnitude, M(words:[~0, 0, 0, 0] as [UInt])) - XCTAssertEqual(T(words:[ 1, 1, 1, 1] as [UInt]).magnitude, M(words:[ 1, 1, 1, 1] as [UInt])) - XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as [UInt]).magnitude, M(words:[~0, ~0, ~0, ~0] as [UInt])) + XCTAssertEqual(T(words:[ 1, 0, 0, 0] as W).magnitude, M(words:[ 1, 0, 0, 0] as W)) + XCTAssertEqual(T(words:[~0, 0, 0, 0] as W).magnitude, M(words:[~0, 0, 0, 0] as W)) + XCTAssertEqual(T(words:[ 1, 1, 1, 1] as W).magnitude, M(words:[ 1, 1, 1, 1] as W)) + XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).magnitude, M(words:[~0, ~0, ~0, ~0] as W)) } //=------------------------------------------------------------------------= @@ -123,19 +124,19 @@ final class UIntXLTestsOnComplements: XCTestCase { //=------------------------------------------------------------------------= func testOnesComplement() { - NBKAssertOnesComplement(T(words:[ 0, 0, 0, 0] as [UInt]), T(words:[ 0, 0, 0, 0] as [UInt])) - NBKAssertOnesComplement(T(words:[ 1, 0, 0, 0] as [UInt]), T(words:[~1, 0, 0, 0] as [UInt])) - NBKAssertOnesComplement(T(words:[~0, 0, 0, 0] as [UInt]), T(words:[ 0, 0, 0, 0] as [UInt])) - NBKAssertOnesComplement(T(words:[ 1, 1, 1, 1] as [UInt]), T(words:[~1, ~1, ~1, ~1] as [UInt])) - NBKAssertOnesComplement(T(words:[~0, ~0, ~0, ~0] as [UInt]), T(words:[ 0, 0, 0, 0] as [UInt])) + NBKAssertOnesComplement(T(words:[ 0, 0, 0, 0] as W), T(words:[ 0, 0, 0, 0] as W)) + NBKAssertOnesComplement(T(words:[ 1, 0, 0, 0] as W), T(words:[~1, 0, 0, 0] as W)) + NBKAssertOnesComplement(T(words:[~0, 0, 0, 0] as W), T(words:[ 0, 0, 0, 0] as W)) + NBKAssertOnesComplement(T(words:[ 1, 1, 1, 1] as W), T(words:[~1, ~1, ~1, ~1] as W)) + NBKAssertOnesComplement(T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 0, 0, 0, 0] as W)) - NBKAssertOnesComplement(T(words:[~0, ~0, ~0, ~0/2 + 0] as [UInt]), T(words:[ 0, 0, 0, ~0/2 + 1] as [UInt])) - NBKAssertOnesComplement(T(words:[ 0, 0, 0, ~0/2 + 1] as [UInt]), T(words:[~0, ~0, ~0, ~0/2 + 0] as [UInt])) - NBKAssertOnesComplement(T(words:[ 1, 0, 0, ~0/2 + 1] as [UInt]), T(words:[~1, ~0, ~0, ~0/2 + 0] as [UInt])) + NBKAssertOnesComplement(T(words:[~0, ~0, ~0, ~0/2 + 0] as W), T(words:[ 0, 0, 0, ~0/2 + 1] as W)) + NBKAssertOnesComplement(T(words:[ 0, 0, 0, ~0/2 + 1] as W), T(words:[~0, ~0, ~0, ~0/2 + 0] as W)) + NBKAssertOnesComplement(T(words:[ 1, 0, 0, ~0/2 + 1] as W), T(words:[~1, ~0, ~0, ~0/2 + 0] as W)) - NBKAssertOnesComplement(T(words:[ 1, 0, 0, ~0/2 + 1] as [UInt]), T(words:[~1, ~0, ~0, ~0/2 + 0] as [UInt])) - NBKAssertOnesComplement(T(words:[ 0, 0, 0, ~0/2 + 1] as [UInt]), T(words:[~0, ~0, ~0, ~0/2 + 0] as [UInt])) - NBKAssertOnesComplement(T(words:[~0, ~0, ~0, ~0/2 + 0] as [UInt]), T(words:[ 0, 0, 0, ~0/2 + 1] as [UInt])) + NBKAssertOnesComplement(T(words:[ 1, 0, 0, ~0/2 + 1] as W), T(words:[~1, ~0, ~0, ~0/2 + 0] as W)) + NBKAssertOnesComplement(T(words:[ 0, 0, 0, ~0/2 + 1] as W), T(words:[~0, ~0, ~0, ~0/2 + 0] as W)) + NBKAssertOnesComplement(T(words:[~0, ~0, ~0, ~0/2 + 0] as W), T(words:[ 0, 0, 0, ~0/2 + 1] as W)) } //=------------------------------------------------------------------------= @@ -143,19 +144,19 @@ final class UIntXLTestsOnComplements: XCTestCase { //=------------------------------------------------------------------------= func testTwosComplement() { - NBKAssertTwosComplement(T(words:[ 0, 0, 0, 0] as [UInt]), T(words:[ 0, 0, 0, 0] as [UInt]), true) - NBKAssertTwosComplement(T(words:[ 1, 0, 0, 0] as [UInt]), T(words:[~0, 0, 0, 0] as [UInt])) - NBKAssertTwosComplement(T(words:[~0, 0, 0, 0] as [UInt]), T(words:[ 1, 0, 0, 0] as [UInt])) - NBKAssertTwosComplement(T(words:[ 1, 1, 1, 1] as [UInt]), T(words:[~0, ~1, ~1, ~1] as [UInt])) - NBKAssertTwosComplement(T(words:[~0, ~0, ~0, ~0] as [UInt]), T(words:[ 1, 0, 0, 0] as [UInt])) + NBKAssertTwosComplement(T(words:[ 0, 0, 0, 0] as W), T(words:[ 0, 0, 0, 0] as W), true) + NBKAssertTwosComplement(T(words:[ 1, 0, 0, 0] as W), T(words:[~0, 0, 0, 0] as W)) + NBKAssertTwosComplement(T(words:[~0, 0, 0, 0] as W), T(words:[ 1, 0, 0, 0] as W)) + NBKAssertTwosComplement(T(words:[ 1, 1, 1, 1] as W), T(words:[~0, ~1, ~1, ~1] as W)) + NBKAssertTwosComplement(T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 1, 0, 0, 0] as W)) - NBKAssertTwosComplement(T(words:[~0, ~0, ~0, ~0/2 + 0] as [UInt]), T(words:[ 1, 0, 0, ~0/2 + 1] as [UInt])) // Int256.max - NBKAssertTwosComplement(T(words:[ 0, 0, 0, ~0/2 + 1] as [UInt]), T(words:[ 0, 0, 0, ~0/2 + 1] as [UInt])) - NBKAssertTwosComplement(T(words:[ 1, 0, 0, ~0/2 + 1] as [UInt]), T(words:[~0, ~0, ~0, ~0/2 + 0] as [UInt])) + NBKAssertTwosComplement(T(words:[~0, ~0, ~0, ~0/2 + 0] as W), T(words:[ 1, 0, 0, ~0/2 + 1] as W)) + NBKAssertTwosComplement(T(words:[ 0, 0, 0, ~0/2 + 1] as W), T(words:[ 0, 0, 0, ~0/2 + 1] as W)) + NBKAssertTwosComplement(T(words:[ 1, 0, 0, ~0/2 + 1] as W), T(words:[~0, ~0, ~0, ~0/2 + 0] as W)) - NBKAssertTwosComplement(T(words:[ 1, 0, 0, ~0/2 + 1] as [UInt]), T(words:[~0, ~0, ~0, ~0/2 + 0] as [UInt])) - NBKAssertTwosComplement(T(words:[ 0, 0, 0, ~0/2 + 1] as [UInt]), T(words:[ 0, 0, 0, ~0/2 + 1] as [UInt])) // Int256.min - NBKAssertTwosComplement(T(words:[~0, ~0, ~0, ~0/2 + 0] as [UInt]), T(words:[ 1, 0, 0, ~0/2 + 1] as [UInt])) + NBKAssertTwosComplement(T(words:[ 1, 0, 0, ~0/2 + 1] as W), T(words:[~0, ~0, ~0, ~0/2 + 0] as W)) + NBKAssertTwosComplement(T(words:[ 0, 0, 0, ~0/2 + 1] as W), T(words:[ 0, 0, 0, ~0/2 + 1] as W)) + NBKAssertTwosComplement(T(words:[~0, ~0, ~0, ~0/2 + 0] as W), T(words:[ 1, 0, 0, ~0/2 + 1] as W)) } } diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Division.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Division.swift index 653604fc..74b5af45 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Division.swift +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Division.swift @@ -13,6 +13,7 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest +private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] @@ -95,10 +96,10 @@ final class UIntXLTestsOnDivision: XCTestCase { } func testDividingByDigitWithLargeDividend() { - NBKAssertDivisionByDigit(T(words:[~2, ~4, ~6, 9] as [UInt]), UInt(2), T(words:[~1, ~2, ~3, 4] as [UInt]), UInt(1)) - NBKAssertDivisionByDigit(T(words:[~3, ~6, ~9, 14] as [UInt]), UInt(3), T(words:[~1, ~2, ~3, 4] as [UInt]), UInt(2)) - NBKAssertDivisionByDigit(T(words:[~4, ~8, ~12, 19] as [UInt]), UInt(4), T(words:[~1, ~2, ~3, 4] as [UInt]), UInt(3)) - NBKAssertDivisionByDigit(T(words:[~5, ~10, ~15, 24] as [UInt]), UInt(5), T(words:[~1, ~2, ~3, 4] as [UInt]), UInt(4)) + NBKAssertDivisionByDigit(T(words:[~2, ~4, ~6, 9] as W), UInt(2), T(words:[~1, ~2, ~3, 4] as W), UInt(1)) + NBKAssertDivisionByDigit(T(words:[~3, ~6, ~9, 14] as W), UInt(3), T(words:[~1, ~2, ~3, 4] as W), UInt(2)) + NBKAssertDivisionByDigit(T(words:[~4, ~8, ~12, 19] as W), UInt(4), T(words:[~1, ~2, ~3, 4] as W), UInt(3)) + NBKAssertDivisionByDigit(T(words:[~5, ~10, ~15, 24] as W), UInt(5), T(words:[~1, ~2, ~3, 4] as W), UInt(4)) } //=------------------------------------------------------------------------= diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Logic.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Logic.swift index e923c073..b8206cda 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Logic.swift +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Logic.swift @@ -13,6 +13,7 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest +private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] @@ -29,11 +30,11 @@ final class IntXLTestsOnLogic: XCTestCase { //=------------------------------------------------------------------------= func testNot() { - NBKAssertNot(T(words:[ 0, 0, 0, 0] as [UInt]), T(words:[~0, ~0, ~0, ~0] as [UInt])) - NBKAssertNot(T(words:[~0, ~0, ~0, ~0] as [UInt]), T(words:[ 0, 0, 0, 0] as [UInt])) + NBKAssertNot(T(words:[ 0, 0, 0, 0] as W), T(words:[~0, ~0, ~0, ~0] as W)) + NBKAssertNot(T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 0, 0, 0, 0] as W)) - NBKAssertNot(T(words:[ 0, 1, 2, 3] as [UInt]), T(words:[~0, ~1, ~2, ~3] as [UInt])) - NBKAssertNot(T(words:[~0, ~1, ~2, ~3] as [UInt]), T(words:[ 0, 1, 2, 3] as [UInt])) + NBKAssertNot(T(words:[ 0, 1, 2, 3] as W), T(words:[~0, ~1, ~2, ~3] as W)) + NBKAssertNot(T(words:[~0, ~1, ~2, ~3] as W), T(words:[ 0, 1, 2, 3] as W)) } func testAnd() { @@ -62,44 +63,44 @@ final class UIntXLTestsOnLogic: XCTestCase { //=------------------------------------------------------------------------= func testNot() { - NBKAssertNot(T(words:[ 0, 0, 0, 0] as [UInt]), T(words:[ 0, 0, 0, 0] as [UInt])) - NBKAssertNot(T(words:[~0, ~0, ~0, ~0] as [UInt]), T(words:[ 0, 0, 0, 0] as [UInt])) + NBKAssertNot(T(words:[ 0, 0, 0, 0] as W), T(words:[ 0, 0, 0, 0] as W)) + NBKAssertNot(T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 0, 0, 0, 0] as W)) - NBKAssertNot(T(words:[ 0, 1, 2, 3] as [UInt]), T(words:[~0, ~1, ~2, ~3] as [UInt])) - NBKAssertNot(T(words:[~0, ~1, ~2, ~3] as [UInt]), T(words:[ 0, 1, 2, 3] as [UInt])) + NBKAssertNot(T(words:[ 0, 1, 2, 3] as W), T(words:[~0, ~1, ~2, ~3] as W)) + NBKAssertNot(T(words:[~0, ~1, ~2, ~3] as W), T(words:[ 0, 1, 2, 3] as W)) } func testAnd() { - NBKAssertAnd(T(words:[ 0, 1, 2, 3] as [UInt]), T(words:[ 0, 0, 0, 0] as [UInt]), T(words:[ 0, 0, 0, 0] as [UInt])) - NBKAssertAnd(T(words:[ 3, 2, 1, 0] as [UInt]), T(words:[ 0, 0, 0, 0] as [UInt]), T(words:[ 0, 0, 0, 0] as [UInt])) + NBKAssertAnd(T(words:[ 0, 1, 2, 3] as W), T(words:[ 0, 0, 0, 0] as W), T(words:[ 0, 0, 0, 0] as W)) + NBKAssertAnd(T(words:[ 3, 2, 1, 0] as W), T(words:[ 0, 0, 0, 0] as W), T(words:[ 0, 0, 0, 0] as W)) - NBKAssertAnd(T(words:[ 0, 1, 2, 3] as [UInt]), T(words:[~0, ~0, ~0, ~0] as [UInt]), T(words:[ 0, 1, 2, 3] as [UInt])) - NBKAssertAnd(T(words:[ 3, 2, 1, 0] as [UInt]), T(words:[~0, ~0, ~0, ~0] as [UInt]), T(words:[ 3, 2, 1, 0] as [UInt])) + NBKAssertAnd(T(words:[ 0, 1, 2, 3] as W), T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 0, 1, 2, 3] as W)) + NBKAssertAnd(T(words:[ 3, 2, 1, 0] as W), T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 3, 2, 1, 0] as W)) - NBKAssertAnd(T(words:[ 0, 1, 2, 3] as [UInt]), T(words:[ 1, 1, 1, 1] as [UInt]), T(words:[ 0, 1, 0, 1] as [UInt])) - NBKAssertAnd(T(words:[ 3, 2, 1, 0] as [UInt]), T(words:[ 1, 1, 1, 1] as [UInt]), T(words:[ 1, 0, 1, 0] as [UInt])) + NBKAssertAnd(T(words:[ 0, 1, 2, 3] as W), T(words:[ 1, 1, 1, 1] as W), T(words:[ 0, 1, 0, 1] as W)) + NBKAssertAnd(T(words:[ 3, 2, 1, 0] as W), T(words:[ 1, 1, 1, 1] as W), T(words:[ 1, 0, 1, 0] as W)) } func testOr() { - NBKAssertOr (T(words:[ 0, 1, 2, 3] as [UInt]), T(words:[ 0, 0, 0, 0] as [UInt]), T(words:[ 0, 1, 2, 3] as [UInt])) - NBKAssertOr (T(words:[ 3, 2, 1, 0] as [UInt]), T(words:[ 0, 0, 0, 0] as [UInt]), T(words:[ 3, 2, 1, 0] as [UInt])) + NBKAssertOr (T(words:[ 0, 1, 2, 3] as W), T(words:[ 0, 0, 0, 0] as W), T(words:[ 0, 1, 2, 3] as W)) + NBKAssertOr (T(words:[ 3, 2, 1, 0] as W), T(words:[ 0, 0, 0, 0] as W), T(words:[ 3, 2, 1, 0] as W)) - NBKAssertOr (T(words:[ 0, 1, 2, 3] as [UInt]), T(words:[~0, ~0, ~0, ~0] as [UInt]), T(words:[~0, ~0, ~0, ~0] as [UInt])) - NBKAssertOr (T(words:[ 3, 2, 1, 0] as [UInt]), T(words:[~0, ~0, ~0, ~0] as [UInt]), T(words:[~0, ~0, ~0, ~0] as [UInt])) + NBKAssertOr (T(words:[ 0, 1, 2, 3] as W), T(words:[~0, ~0, ~0, ~0] as W), T(words:[~0, ~0, ~0, ~0] as W)) + NBKAssertOr (T(words:[ 3, 2, 1, 0] as W), T(words:[~0, ~0, ~0, ~0] as W), T(words:[~0, ~0, ~0, ~0] as W)) - NBKAssertOr (T(words:[ 0, 1, 2, 3] as [UInt]), T(words:[ 1, 1, 1, 1] as [UInt]), T(words:[ 1, 1, 3, 3] as [UInt])) - NBKAssertOr (T(words:[ 3, 2, 1, 0] as [UInt]), T(words:[ 1, 1, 1, 1] as [UInt]), T(words:[ 3, 3, 1, 1] as [UInt])) + NBKAssertOr (T(words:[ 0, 1, 2, 3] as W), T(words:[ 1, 1, 1, 1] as W), T(words:[ 1, 1, 3, 3] as W)) + NBKAssertOr (T(words:[ 3, 2, 1, 0] as W), T(words:[ 1, 1, 1, 1] as W), T(words:[ 3, 3, 1, 1] as W)) } func testXor() { - NBKAssertXor(T(words:[ 0, 1, 2, 3] as [UInt]), T(words:[ 0, 0, 0, 0] as [UInt]), T(words:[ 0, 1, 2, 3] as [UInt])) - NBKAssertXor(T(words:[ 3, 2, 1, 0] as [UInt]), T(words:[ 0, 0, 0, 0] as [UInt]), T(words:[ 3, 2, 1, 0] as [UInt])) + NBKAssertXor(T(words:[ 0, 1, 2, 3] as W), T(words:[ 0, 0, 0, 0] as W), T(words:[ 0, 1, 2, 3] as W)) + NBKAssertXor(T(words:[ 3, 2, 1, 0] as W), T(words:[ 0, 0, 0, 0] as W), T(words:[ 3, 2, 1, 0] as W)) - NBKAssertXor(T(words:[ 0, 1, 2, 3] as [UInt]), T(words:[~0, ~0, ~0, ~0] as [UInt]), T(words:[~0, ~1, ~2, ~3] as [UInt])) - NBKAssertXor(T(words:[ 3, 2, 1, 0] as [UInt]), T(words:[~0, ~0, ~0, ~0] as [UInt]), T(words:[~3, ~2, ~1, ~0] as [UInt])) + NBKAssertXor(T(words:[ 0, 1, 2, 3] as W), T(words:[~0, ~0, ~0, ~0] as W), T(words:[~0, ~1, ~2, ~3] as W)) + NBKAssertXor(T(words:[ 3, 2, 1, 0] as W), T(words:[~0, ~0, ~0, ~0] as W), T(words:[~3, ~2, ~1, ~0] as W)) - NBKAssertXor(T(words:[ 0, 1, 2, 3] as [UInt]), T(words:[ 1, 1, 1, 1] as [UInt]), T(words:[ 1, 0, 3, 2] as [UInt])) - NBKAssertXor(T(words:[ 3, 2, 1, 0] as [UInt]), T(words:[ 1, 1, 1, 1] as [UInt]), T(words:[ 2, 3, 0, 1] as [UInt])) + NBKAssertXor(T(words:[ 0, 1, 2, 3] as W), T(words:[ 1, 1, 1, 1] as W), T(words:[ 1, 0, 3, 2] as W)) + NBKAssertXor(T(words:[ 3, 2, 1, 0] as W), T(words:[ 1, 1, 1, 1] as W), T(words:[ 2, 3, 0, 1] as W)) } } diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Numbers.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Numbers.swift index 75aa3656..ccc85674 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Numbers.swift +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Numbers.swift @@ -13,6 +13,7 @@ import NBKCoreKit @testable import NBKFlexibleWidthKit import XCTest +private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] @@ -40,32 +41,32 @@ final class IntXLTestsOnNumbers: XCTestCase { //=------------------------------------------------------------------------= func testToInt() { - NBKAssertNumbers(from: T(words:[ 1, 0, 0, 0] as [UInt]), default: Int( 1)) - NBKAssertNumbers(from: T(words:[~0, 0, 0, 0] as [UInt]), exactly: nil, clamping: Int.max, truncating: -1) - NBKAssertNumbers(from: T(words:[ 1, 1, 1, 1] as [UInt]), exactly: nil, clamping: Int.max, truncating: 1) - NBKAssertNumbers(from: T(words:[~0, ~0, ~0, ~0] as [UInt]), default: Int(-1)) + NBKAssertNumbers(from: T(words:[ 1, 0, 0, 0] as W), default: Int( 1)) + NBKAssertNumbers(from: T(words:[~0, 0, 0, 0] as W), exactly: nil, clamping: Int.max, truncating: -1) + NBKAssertNumbers(from: T(words:[ 1, 1, 1, 1] as W), exactly: nil, clamping: Int.max, truncating: 1) + NBKAssertNumbers(from: T(words:[~0, ~0, ~0, ~0] as W), default: Int(-1)) } func testFromInt() { - NBKAssertNumbers(from: Int.min, default: ~T(words:[UInt(Int.max), 0, 0, 0] as [UInt])) - NBKAssertNumbers(from: Int.max, default: T(words:[UInt(Int.max), 0, 0, 0] as [UInt])) + NBKAssertNumbers(from: Int.min, default: ~T(words:[UInt(Int.max), 0, 0, 0] as W)) + NBKAssertNumbers(from: Int.max, default: T(words:[UInt(Int.max), 0, 0, 0] as W)) } func testFromIntAsDigit() { - NBKAssertNumbers(from: T(digit: Int.min), default: ~T(words:[UInt(Int.max), 0, 0, 0] as [UInt])) - NBKAssertNumbers(from: T(digit: Int.max), default: T(words:[UInt(Int.max), 0, 0, 0] as [UInt])) + NBKAssertNumbers(from: T(digit: Int.min), default: ~T(words:[UInt(Int.max), 0, 0, 0] as W)) + NBKAssertNumbers(from: T(digit: Int.max), default: T(words:[UInt(Int.max), 0, 0, 0] as W)) } func testFromIntAsDigitAtIndex() { - NBKAssertNumbers(from: T(digit: Int( 4), at: Int(0)), default: T(words:[ 4, 0, 0, 0] as [UInt])) - NBKAssertNumbers(from: T(digit: Int( 4), at: Int(1)), default: T(words:[ 0, 4, 0, 0] as [UInt])) - NBKAssertNumbers(from: T(digit: Int( 4), at: Int(2)), default: T(words:[ 0, 0, 4, 0] as [UInt])) - NBKAssertNumbers(from: T(digit: Int( 4), at: Int(3)), default: T(words:[ 0, 0, 0, 4] as [UInt])) + NBKAssertNumbers(from: T(digit: Int( 4), at: Int(0)), default: T(words:[ 4, 0, 0, 0] as W)) + NBKAssertNumbers(from: T(digit: Int( 4), at: Int(1)), default: T(words:[ 0, 4, 0, 0] as W)) + NBKAssertNumbers(from: T(digit: Int( 4), at: Int(2)), default: T(words:[ 0, 0, 4, 0] as W)) + NBKAssertNumbers(from: T(digit: Int( 4), at: Int(3)), default: T(words:[ 0, 0, 0, 4] as W)) - NBKAssertNumbers(from: T(digit: Int(-4), at: Int(0)), default: T(words:[~3, ~0, ~0, ~0] as [UInt])) - NBKAssertNumbers(from: T(digit: Int(-4), at: Int(1)), default: T(words:[ 0, ~3, ~0, ~0] as [UInt])) - NBKAssertNumbers(from: T(digit: Int(-4), at: Int(2)), default: T(words:[ 0, 0, ~3, ~0] as [UInt])) - NBKAssertNumbers(from: T(digit: Int(-4), at: Int(3)), default: T(words:[ 0, 0, 0, ~3] as [UInt])) + NBKAssertNumbers(from: T(digit: Int(-4), at: Int(0)), default: T(words:[~3, ~0, ~0, ~0] as W)) + NBKAssertNumbers(from: T(digit: Int(-4), at: Int(1)), default: T(words:[ 0, ~3, ~0, ~0] as W)) + NBKAssertNumbers(from: T(digit: Int(-4), at: Int(2)), default: T(words:[ 0, 0, ~3, ~0] as W)) + NBKAssertNumbers(from: T(digit: Int(-4), at: Int(3)), default: T(words:[ 0, 0, 0, ~3] as W)) } //=------------------------------------------------------------------------= @@ -105,10 +106,10 @@ final class IntXLTestsOnNumbers: XCTestCase { //=------------------------------------------------------------------------= func testToUInt() { - NBKAssertNumbers(from: T(words:[ 1, 0, 0, 0] as [UInt]), default: UInt( 1)) - NBKAssertNumbers(from: T(words:[~0, 0, 0, 0] as [UInt]), default: UInt.max) - NBKAssertNumbers(from: T(words:[ 1, 1, 1, 1] as [UInt]), exactly: nil, clamping: ~0, truncating: UInt( 1)) - NBKAssertNumbers(from: T(words:[~0, ~0, ~0, ~0] as [UInt]), exactly: nil, clamping: 0, truncating: UInt.max) + NBKAssertNumbers(from: T(words:[ 1, 0, 0, 0] as W), default: UInt( 1)) + NBKAssertNumbers(from: T(words:[~0, 0, 0, 0] as W), default: UInt.max) + NBKAssertNumbers(from: T(words:[ 1, 1, 1, 1] as W), exactly: nil, clamping: ~0, truncating: UInt( 1)) + NBKAssertNumbers(from: T(words:[~0, ~0, ~0, ~0] as W), exactly: nil, clamping: 0, truncating: UInt.max) } func testFromUInt() { @@ -153,17 +154,17 @@ final class IntXLTestsOnNumbers: XCTestCase { //=------------------------------------------------------------------------= func testToSignitude() { - NBKAssertNumbers(from: T(words:[ 1, 0, 0, 0] as [UInt]), default: S(words:[ 1, 0, 0, 0] as [UInt])) - NBKAssertNumbers(from: T(words:[~0, 0, 0, 0] as [UInt]), default: S(words:[~0, 0, 0, 0] as [UInt])) - NBKAssertNumbers(from: T(words:[ 1, 1, 1, 1] as [UInt]), default: S(words:[ 1, 1, 1, 1] as [UInt])) - NBKAssertNumbers(from: T(words:[~0, ~0, ~0, ~0] as [UInt]), default: S(words:[~0, ~0, ~0, ~0] as [UInt])) + NBKAssertNumbers(from: T(words:[ 1, 0, 0, 0] as W), default: S(words:[ 1, 0, 0, 0] as W)) + NBKAssertNumbers(from: T(words:[~0, 0, 0, 0] as W), default: S(words:[~0, 0, 0, 0] as W)) + NBKAssertNumbers(from: T(words:[ 1, 1, 1, 1] as W), default: S(words:[ 1, 1, 1, 1] as W)) + NBKAssertNumbers(from: T(words:[~0, ~0, ~0, ~0] as W), default: S(words:[~0, ~0, ~0, ~0] as W)) } func testFromSignitude() { - NBKAssertNumbers(from: S(words:[ 1, 0, 0, 0] as [UInt]), default: T(words:[ 1, 0, 0, 0] as [UInt])) - NBKAssertNumbers(from: S(words:[~0, 0, 0, 0] as [UInt]), default: T(words:[~0, 0, 0, 0] as [UInt])) - NBKAssertNumbers(from: S(words:[ 1, 1, 1, 1] as [UInt]), default: T(words:[ 1, 1, 1, 1] as [UInt])) - NBKAssertNumbers(from: S(words:[~0, ~0, ~0, ~0] as [UInt]), default: T(words:[~0, ~0, ~0, ~0] as [UInt])) + NBKAssertNumbers(from: S(words:[ 1, 0, 0, 0] as W), default: T(words:[ 1, 0, 0, 0] as W)) + NBKAssertNumbers(from: S(words:[~0, 0, 0, 0] as W), default: T(words:[~0, 0, 0, 0] as W)) + NBKAssertNumbers(from: S(words:[ 1, 1, 1, 1] as W), default: T(words:[ 1, 1, 1, 1] as W)) + NBKAssertNumbers(from: S(words:[~0, ~0, ~0, ~0] as W), default: T(words:[~0, ~0, ~0, ~0] as W)) } //=------------------------------------------------------------------------= @@ -171,17 +172,17 @@ final class IntXLTestsOnNumbers: XCTestCase { //=------------------------------------------------------------------------= func testToMagnitude() { - NBKAssertNumbers(from: T(words:[ 1, 0, 0, 0] as [UInt]), default: M(words:[ 1, 0, 0, 0] as [UInt])) - NBKAssertNumbers(from: T(words:[~0, 0, 0, 0] as [UInt]), default: M(words:[~0, 0, 0, 0] as [UInt])) - NBKAssertNumbers(from: T(words:[ 1, 1, 1, 1] as [UInt]), default: M(words:[ 1, 1, 1, 1] as [UInt])) - NBKAssertNumbers(from: T(words:[~0, ~0, ~0, ~0] as [UInt]), exactly: nil, clamping: M.zero, truncating: M(UInt.max)) + NBKAssertNumbers(from: T(words:[ 1, 0, 0, 0] as W), default: M(words:[ 1, 0, 0, 0] as W)) + NBKAssertNumbers(from: T(words:[~0, 0, 0, 0] as W), default: M(words:[~0, 0, 0, 0] as W)) + NBKAssertNumbers(from: T(words:[ 1, 1, 1, 1] as W), default: M(words:[ 1, 1, 1, 1] as W)) + NBKAssertNumbers(from: T(words:[~0, ~0, ~0, ~0] as W), exactly: nil, clamping: M.zero, truncating: M(UInt.max)) } func testFromMagnitude() { - NBKAssertNumbers(from: M(words:[ 1, 0, 0, 0] as [UInt]), default: T(words:[ 1, 0, 0, 0, 0] as [UInt])) - NBKAssertNumbers(from: M(words:[~0, 0, 0, 0] as [UInt]), default: T(words:[~0, 0, 0, 0, 0] as [UInt])) - NBKAssertNumbers(from: M(words:[ 1, 1, 1, 1] as [UInt]), default: T(words:[ 1, 1, 1, 1, 0] as [UInt])) - NBKAssertNumbers(from: M(words:[~0, ~0, ~0, ~0] as [UInt]), default: T(words:[~0, ~0, ~0, ~0, 0] as [UInt])) + NBKAssertNumbers(from: M(words:[ 1, 0, 0, 0] as W), default: T(words:[ 1, 0, 0, 0, 0] as W)) + NBKAssertNumbers(from: M(words:[~0, 0, 0, 0] as W), default: T(words:[~0, 0, 0, 0, 0] as W)) + NBKAssertNumbers(from: M(words:[ 1, 1, 1, 1] as W), default: T(words:[ 1, 1, 1, 1, 0] as W)) + NBKAssertNumbers(from: M(words:[~0, ~0, ~0, ~0] as W), default: T(words:[~0, ~0, ~0, ~0, 0] as W)) } //=------------------------------------------------------------------------= @@ -241,14 +242,14 @@ final class IntXLTestsOnNumbers: XCTestCase { //=------------------------------------------------------------------------= func testFromLiteral() { - XCTAssertEqual(T(words:[ 0, 0, 0, 0] as [UInt]), 0) - XCTAssertEqual(T(words:[~0, 0, 0, 0] as [UInt]), 18446744073709551615) - XCTAssertEqual(T(words:[~0, ~0, 0, 0] as [UInt]), 340282366920938463463374607431768211455) - XCTAssertEqual(T(words:[~0, ~0, ~0, 0] as [UInt]), 6277101735386680763835789423207666416102355444464034512895) - XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as [UInt]), -1) - XCTAssertEqual(T(words:[ 1, ~0, ~0, ~0] as [UInt]), -18446744073709551615) - XCTAssertEqual(T(words:[ 1, 0, ~0, ~0] as [UInt]), -340282366920938463463374607431768211455) - XCTAssertEqual(T(words:[ 1, 0, 0, ~0] as [UInt]), -6277101735386680763835789423207666416102355444464034512895) + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W), 0) + XCTAssertEqual(T(words:[~0, 0, 0, 0] as W), 18446744073709551615) + XCTAssertEqual(T(words:[~0, ~0, 0, 0] as W), 340282366920938463463374607431768211455) + XCTAssertEqual(T(words:[~0, ~0, ~0, 0] as W), 6277101735386680763835789423207666416102355444464034512895) + XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W), -1) + XCTAssertEqual(T(words:[ 1, ~0, ~0, ~0] as W), -18446744073709551615) + XCTAssertEqual(T(words:[ 1, 0, ~0, ~0] as W), -340282366920938463463374607431768211455) + XCTAssertEqual(T(words:[ 1, 0, 0, ~0] as W), -6277101735386680763835789423207666416102355444464034512895) } } @@ -276,10 +277,10 @@ final class UIntXLTestsOnNumbers: XCTestCase { //=------------------------------------------------------------------------= func testToInt() { - NBKAssertNumbers(from: T(words:[ 1, 0, 0, 0] as [UInt]), default: Int( 1)) - NBKAssertNumbers(from: T(words:[~0, 0, 0, 0] as [UInt]), exactly: nil, clamping: Int.max, truncating: -1) - NBKAssertNumbers(from: T(words:[ 1, 1, 1, 1] as [UInt]), exactly: nil, clamping: Int.max, truncating: 1) - NBKAssertNumbers(from: T(words:[~0, ~0, ~0, ~0] as [UInt]), exactly: nil, clamping: Int.max, truncating: -1) + NBKAssertNumbers(from: T(words:[ 1, 0, 0, 0] as W), default: Int( 1)) + NBKAssertNumbers(from: T(words:[~0, 0, 0, 0] as W), exactly: nil, clamping: Int.max, truncating: -1) + NBKAssertNumbers(from: T(words:[ 1, 1, 1, 1] as W), exactly: nil, clamping: Int.max, truncating: 1) + NBKAssertNumbers(from: T(words:[~0, ~0, ~0, ~0] as W), exactly: nil, clamping: Int.max, truncating: -1) } func testFromInt() { @@ -324,10 +325,10 @@ final class UIntXLTestsOnNumbers: XCTestCase { //=------------------------------------------------------------------------= func testToUInt() { - NBKAssertNumbers(from: T(words:[ 1, 0, 0, 0] as [UInt]), default: UInt( 1)) - NBKAssertNumbers(from: T(words:[~0, 0, 0, 0] as [UInt]), default: ~UInt( 0)) - NBKAssertNumbers(from: T(words:[ 1, 1, 1, 1] as [UInt]), exactly: nil, clamping: UInt.max, truncating: 1) - NBKAssertNumbers(from: T(words:[~0, ~0, ~0, ~0] as [UInt]), exactly: nil, clamping: UInt.max, truncating: ~0) + NBKAssertNumbers(from: T(words:[ 1, 0, 0, 0] as W), default: UInt( 1)) + NBKAssertNumbers(from: T(words:[~0, 0, 0, 0] as W), default: ~UInt( 0)) + NBKAssertNumbers(from: T(words:[ 1, 1, 1, 1] as W), exactly: nil, clamping: UInt.max, truncating: 1) + NBKAssertNumbers(from: T(words:[~0, ~0, ~0, ~0] as W), exactly: nil, clamping: UInt.max, truncating: ~0) } func testFromUInt() { @@ -336,15 +337,15 @@ final class UIntXLTestsOnNumbers: XCTestCase { } func testFromUIntAsDigit() { - NBKAssertNumbers(from: T(digit: UInt.min), default: T(words:[ 0, 0, 0, 0] as [UInt])) - NBKAssertNumbers(from: T(digit: UInt.max), default: T(words:[~0, 0, 0, 0] as [UInt])) + NBKAssertNumbers(from: T(digit: UInt.min), default: T(words:[ 0, 0, 0, 0] as W)) + NBKAssertNumbers(from: T(digit: UInt.max), default: T(words:[~0, 0, 0, 0] as W)) } func testFromUIntAsDigitAtIndex() { - NBKAssertNumbers(from: T(digit: UInt.max, at: Int(0)), default: T(words:[~0, 0, 0, 0] as [UInt])) - NBKAssertNumbers(from: T(digit: UInt.max, at: Int(1)), default: T(words:[ 0, ~0, 0, 0] as [UInt])) - NBKAssertNumbers(from: T(digit: UInt.max, at: Int(2)), default: T(words:[ 0, 0, ~0, 0] as [UInt])) - NBKAssertNumbers(from: T(digit: UInt.max, at: Int(3)), default: T(words:[ 0, 0, 0, ~0] as [UInt])) + NBKAssertNumbers(from: T(digit: UInt.max, at: Int(0)), default: T(words:[~0, 0, 0, 0] as W)) + NBKAssertNumbers(from: T(digit: UInt.max, at: Int(1)), default: T(words:[ 0, ~0, 0, 0] as W)) + NBKAssertNumbers(from: T(digit: UInt.max, at: Int(2)), default: T(words:[ 0, 0, ~0, 0] as W)) + NBKAssertNumbers(from: T(digit: UInt.max, at: Int(3)), default: T(words:[ 0, 0, 0, ~0] as W)) } //=------------------------------------------------------------------------= @@ -384,17 +385,17 @@ final class UIntXLTestsOnNumbers: XCTestCase { //=------------------------------------------------------------------------= func testToSignitude() { - NBKAssertNumbers(from: T(words:[ 1, 0, 0, 0] as [UInt]), default: S(words:[ 1, 0, 0, 0, 0] as [UInt])) - NBKAssertNumbers(from: T(words:[~0, 0, 0, 0] as [UInt]), default: S(words:[~0, 0, 0, 0, 0] as [UInt])) - NBKAssertNumbers(from: T(words:[ 1, 1, 1, 1] as [UInt]), default: S(words:[ 1, 1, 1, 1, 0] as [UInt])) - NBKAssertNumbers(from: T(words:[~0, ~0, ~0, ~0] as [UInt]), default: S(words:[~0, ~0, ~0, ~0, 0] as [UInt])) + NBKAssertNumbers(from: T(words:[ 1, 0, 0, 0] as W), default: S(words:[ 1, 0, 0, 0, 0] as W)) + NBKAssertNumbers(from: T(words:[~0, 0, 0, 0] as W), default: S(words:[~0, 0, 0, 0, 0] as W)) + NBKAssertNumbers(from: T(words:[ 1, 1, 1, 1] as W), default: S(words:[ 1, 1, 1, 1, 0] as W)) + NBKAssertNumbers(from: T(words:[~0, ~0, ~0, ~0] as W), default: S(words:[~0, ~0, ~0, ~0, 0] as W)) } func testFromSignitude() { - NBKAssertNumbers(from: S(words:[ 1, 0, 0, 0] as [UInt]), default: T(words:[ 1, 0, 0, 0, 0] as [UInt])) - NBKAssertNumbers(from: S(words:[~0, 0, 0, 0] as [UInt]), default: T(words:[~0, 0, 0, 0, 0] as [UInt])) - NBKAssertNumbers(from: S(words:[ 1, 1, 1, 1] as [UInt]), default: T(words:[ 1, 1, 1, 1, 0] as [UInt])) - NBKAssertNumbers(from: S(words:[~0, ~0, ~0, ~0] as [UInt]), exactly: nil, clamping: T.zero, truncating: T(UInt.max)) + NBKAssertNumbers(from: S(words:[ 1, 0, 0, 0] as W), default: T(words:[ 1, 0, 0, 0, 0] as W)) + NBKAssertNumbers(from: S(words:[~0, 0, 0, 0] as W), default: T(words:[~0, 0, 0, 0, 0] as W)) + NBKAssertNumbers(from: S(words:[ 1, 1, 1, 1] as W), default: T(words:[ 1, 1, 1, 1, 0] as W)) + NBKAssertNumbers(from: S(words:[~0, ~0, ~0, ~0] as W), exactly: nil, clamping: T.zero, truncating: T(UInt.max)) } //=------------------------------------------------------------------------= @@ -402,17 +403,17 @@ final class UIntXLTestsOnNumbers: XCTestCase { //=------------------------------------------------------------------------= func testToMagnitude() { - NBKAssertNumbers(from: T(words:[ 1, 0, 0, 0] as [UInt]), default: M(words:[ 1, 0, 0, 0] as [UInt])) - NBKAssertNumbers(from: T(words:[~0, 0, 0, 0] as [UInt]), default: M(words:[~0, 0, 0, 0] as [UInt])) - NBKAssertNumbers(from: T(words:[ 1, 1, 1, 1] as [UInt]), default: M(words:[ 1, 1, 1, 1] as [UInt])) - NBKAssertNumbers(from: T(words:[~0, ~0, ~0, ~0] as [UInt]), default: M(words:[~0, ~0, ~0, ~0] as [UInt])) + NBKAssertNumbers(from: T(words:[ 1, 0, 0, 0] as W), default: M(words:[ 1, 0, 0, 0] as W)) + NBKAssertNumbers(from: T(words:[~0, 0, 0, 0] as W), default: M(words:[~0, 0, 0, 0] as W)) + NBKAssertNumbers(from: T(words:[ 1, 1, 1, 1] as W), default: M(words:[ 1, 1, 1, 1] as W)) + NBKAssertNumbers(from: T(words:[~0, ~0, ~0, ~0] as W), default: M(words:[~0, ~0, ~0, ~0] as W)) } func testFromMagnitude() { - NBKAssertNumbers(from: M(words:[ 1, 0, 0, 0] as [UInt]), default: T(words:[ 1, 0, 0, 0] as [UInt])) - NBKAssertNumbers(from: M(words:[~0, 0, 0, 0] as [UInt]), default: T(words:[~0, 0, 0, 0] as [UInt])) - NBKAssertNumbers(from: M(words:[ 1, 1, 1, 1] as [UInt]), default: T(words:[ 1, 1, 1, 1] as [UInt])) - NBKAssertNumbers(from: M(words:[~0, ~0, ~0, ~0] as [UInt]), default: T(words:[~0, ~0, ~0, ~0] as [UInt])) + NBKAssertNumbers(from: M(words:[ 1, 0, 0, 0] as W), default: T(words:[ 1, 0, 0, 0] as W)) + NBKAssertNumbers(from: M(words:[~0, 0, 0, 0] as W), default: T(words:[~0, 0, 0, 0] as W)) + NBKAssertNumbers(from: M(words:[ 1, 1, 1, 1] as W), default: T(words:[ 1, 1, 1, 1] as W)) + NBKAssertNumbers(from: M(words:[~0, ~0, ~0, ~0] as W), default: T(words:[~0, ~0, ~0, ~0] as W)) } //=------------------------------------------------------------------------= diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Shifts.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Shifts.swift index 16e63986..add20498 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Shifts.swift +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Shifts.swift @@ -13,6 +13,7 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest +private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Subtraction.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Subtraction.swift index d89cacd2..4f9ea9be 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Subtraction.swift +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Subtraction.swift @@ -13,6 +13,7 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest +private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] @@ -49,15 +50,15 @@ final class IntXLTestsOnSubtraction: XCTestCase { } func testSubtractingAtIndex() { - NBKAssertSubtraction(T(words:[~0, ~0, ~0, ~0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(0), T(words:[~1, ~2, ~3, ~0] as [UInt])) - NBKAssertSubtraction(T(words:[ 0, ~0, ~0, ~0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(0), T(words:[~0, ~3, ~3, ~0] as [UInt])) - NBKAssertSubtraction(T(words:[ 0, 0, ~0, ~0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(0), T(words:[~0, ~2, ~4, ~0] as [UInt])) - NBKAssertSubtraction(T(words:[ 0, 0, 0, ~0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(0), T(words:[~0, ~2, ~3, ~1] as [UInt])) + NBKAssertSubtraction(T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[~1, ~2, ~3, ~0] as W)) + NBKAssertSubtraction(T(words:[ 0, ~0, ~0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[~0, ~3, ~3, ~0] as W)) + NBKAssertSubtraction(T(words:[ 0, 0, ~0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[~0, ~2, ~4, ~0] as W)) + NBKAssertSubtraction(T(words:[ 0, 0, 0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[~0, ~2, ~3, ~1] as W)) - NBKAssertSubtraction(T(words:[~0, ~0, ~0, ~0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(1), T(words:[~0, ~1, ~2, ~3] as [UInt])) - NBKAssertSubtraction(T(words:[ 0, ~0, ~0, ~0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(1), T(words:[ 0, ~1, ~2, ~3] as [UInt])) - NBKAssertSubtraction(T(words:[ 0, 0, ~0, ~0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(1), T(words:[ 0, ~0, ~3, ~3] as [UInt])) - NBKAssertSubtraction(T(words:[ 0, 0, 0, ~0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(1), T(words:[ 0, ~0, ~2, ~4] as [UInt])) + NBKAssertSubtraction(T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[~0, ~1, ~2, ~3] as W)) + NBKAssertSubtraction(T(words:[ 0, ~0, ~0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[ 0, ~1, ~2, ~3] as W)) + NBKAssertSubtraction(T(words:[ 0, 0, ~0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[ 0, ~0, ~3, ~3] as W)) + NBKAssertSubtraction(T(words:[ 0, 0, 0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[ 0, ~0, ~2, ~4] as W)) } //=------------------------------------------------------------------------= @@ -85,15 +86,15 @@ final class IntXLTestsOnSubtraction: XCTestCase { } func testSubtractingDigitAtIndex() { - NBKAssertSubtractionByDigit(T(words:[~0, ~0, ~0, ~0] as [UInt]), Int(3), Int(0), T(words:[~3, ~0, ~0, ~0] as [UInt])) - NBKAssertSubtractionByDigit(T(words:[ 0, ~0, ~0, ~0] as [UInt]), Int(3), Int(0), T(words:[~2, ~1, ~0, ~0] as [UInt])) - NBKAssertSubtractionByDigit(T(words:[ 0, 0, ~0, ~0] as [UInt]), Int(3), Int(0), T(words:[~2, ~0, ~1, ~0] as [UInt])) - NBKAssertSubtractionByDigit(T(words:[ 0, 0, 0, ~0] as [UInt]), Int(3), Int(0), T(words:[~2, ~0, ~0, ~1] as [UInt])) + NBKAssertSubtractionByDigit(T(words:[~0, ~0, ~0, ~0] as W), Int(3), Int(0), T(words:[~3, ~0, ~0, ~0] as W)) + NBKAssertSubtractionByDigit(T(words:[ 0, ~0, ~0, ~0] as W), Int(3), Int(0), T(words:[~2, ~1, ~0, ~0] as W)) + NBKAssertSubtractionByDigit(T(words:[ 0, 0, ~0, ~0] as W), Int(3), Int(0), T(words:[~2, ~0, ~1, ~0] as W)) + NBKAssertSubtractionByDigit(T(words:[ 0, 0, 0, ~0] as W), Int(3), Int(0), T(words:[~2, ~0, ~0, ~1] as W)) - NBKAssertSubtractionByDigit(T(words:[~0, ~0, ~0, ~0] as [UInt]), Int(3), Int(1), T(words:[~0, ~3, ~0, ~0] as [UInt])) - NBKAssertSubtractionByDigit(T(words:[ 0, ~0, ~0, ~0] as [UInt]), Int(3), Int(1), T(words:[ 0, ~3, ~0, ~0] as [UInt])) - NBKAssertSubtractionByDigit(T(words:[ 0, 0, ~0, ~0] as [UInt]), Int(3), Int(1), T(words:[ 0, ~2, ~1, ~0] as [UInt])) - NBKAssertSubtractionByDigit(T(words:[ 0, 0, 0, ~0] as [UInt]), Int(3), Int(1), T(words:[ 0, ~2, ~0, ~1] as [UInt])) + NBKAssertSubtractionByDigit(T(words:[~0, ~0, ~0, ~0] as W), Int(3), Int(1), T(words:[~0, ~3, ~0, ~0] as W)) + NBKAssertSubtractionByDigit(T(words:[ 0, ~0, ~0, ~0] as W), Int(3), Int(1), T(words:[ 0, ~3, ~0, ~0] as W)) + NBKAssertSubtractionByDigit(T(words:[ 0, 0, ~0, ~0] as W), Int(3), Int(1), T(words:[ 0, ~2, ~1, ~0] as W)) + NBKAssertSubtractionByDigit(T(words:[ 0, 0, 0, ~0] as W), Int(3), Int(1), T(words:[ 0, ~2, ~0, ~1] as W)) } //=------------------------------------------------------------------------= @@ -131,28 +132,28 @@ final class UIntXLTestsOnSubtraction: XCTestCase { } func testSubtractingReportingOverflow() { - NBKAssertSubtraction(T(1), T(0), Int(0), T(words:[ 1] as [UInt])) - NBKAssertSubtraction(T(1), T(1), Int(0), T(words:[ 0] as [UInt])) - NBKAssertSubtraction(T(1), T(2), Int(0), T(words:[~0] as [UInt]), true) - NBKAssertSubtraction(T(1), T(3), Int(0), T(words:[~1] as [UInt]), true) + NBKAssertSubtraction(T(1), T(0), Int(0), T(words:[ 1] as W)) + NBKAssertSubtraction(T(1), T(1), Int(0), T(words:[ 0] as W)) + NBKAssertSubtraction(T(1), T(2), Int(0), T(words:[~0] as W), true) + NBKAssertSubtraction(T(1), T(3), Int(0), T(words:[~1] as W), true) } func testSubtractingAtIndex() { - NBKAssertSubtraction(T(words:[~0, ~0, ~0, ~0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(0), T(words:[~1, ~2, ~3, ~0] as [UInt])) - NBKAssertSubtraction(T(words:[ 0, ~0, ~0, ~0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(0), T(words:[~0, ~3, ~3, ~0] as [UInt])) - NBKAssertSubtraction(T(words:[ 0, 0, ~0, ~0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(0), T(words:[~0, ~2, ~4, ~0] as [UInt])) - NBKAssertSubtraction(T(words:[ 0, 0, 0, ~0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(0), T(words:[~0, ~2, ~3, ~1] as [UInt])) + NBKAssertSubtraction(T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[~1, ~2, ~3, ~0] as W)) + NBKAssertSubtraction(T(words:[ 0, ~0, ~0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[~0, ~3, ~3, ~0] as W)) + NBKAssertSubtraction(T(words:[ 0, 0, ~0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[~0, ~2, ~4, ~0] as W)) + NBKAssertSubtraction(T(words:[ 0, 0, 0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[~0, ~2, ~3, ~1] as W)) - NBKAssertSubtraction(T(words:[~0, ~0, ~0, ~0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(1), T(words:[~0, ~1, ~2, ~3] as [UInt])) - NBKAssertSubtraction(T(words:[ 0, ~0, ~0, ~0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(1), T(words:[ 0, ~1, ~2, ~3] as [UInt])) - NBKAssertSubtraction(T(words:[ 0, 0, ~0, ~0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(1), T(words:[ 0, ~0, ~3, ~3] as [UInt])) - NBKAssertSubtraction(T(words:[ 0, 0, 0, ~0] as [UInt]), T(words:[ 1, 2, 3, 0] as [UInt]), Int(1), T(words:[ 0, ~0, ~2, ~4] as [UInt])) + NBKAssertSubtraction(T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[~0, ~1, ~2, ~3] as W)) + NBKAssertSubtraction(T(words:[ 0, ~0, ~0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[ 0, ~1, ~2, ~3] as W)) + NBKAssertSubtraction(T(words:[ 0, 0, ~0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[ 0, ~0, ~3, ~3] as W)) + NBKAssertSubtraction(T(words:[ 0, 0, 0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[ 0, ~0, ~2, ~4] as W)) } func testSubtractingAtIndexReportingOverflow() { - NBKAssertSubtraction(T(words:[ 1, 2, 3, 0] as [UInt]), T(words:[ 4, 5, 0, 0] as [UInt]), Int(0), T(words:[~2, ~3, 2, 0] as [UInt])) - NBKAssertSubtraction(T(words:[ 1, 2, 3, 0] as [UInt]), T(words:[ 4, 5, 0, 0] as [UInt]), Int(1), T(words:[ 1, ~1, ~2, 0] as [UInt]), true) - NBKAssertSubtraction(T(words:[ 1, 2, 3, 0] as [UInt]), T(words:[ 4, 5, 0, 0] as [UInt]), Int(2), T(words:[ 1, 2, ~0, ~5] as [UInt]), true) + NBKAssertSubtraction(T(words:[ 1, 2, 3, 0] as W), T(words:[ 4, 5, 0, 0] as W), Int(0), T(words:[~2, ~3, 2, 0] as W)) + NBKAssertSubtraction(T(words:[ 1, 2, 3, 0] as W), T(words:[ 4, 5, 0, 0] as W), Int(1), T(words:[ 1, ~1, ~2, 0] as W), true) + NBKAssertSubtraction(T(words:[ 1, 2, 3, 0] as W), T(words:[ 4, 5, 0, 0] as W), Int(2), T(words:[ 1, 2, ~0, ~5] as W), true) } //=------------------------------------------------------------------------= @@ -167,29 +168,29 @@ final class UIntXLTestsOnSubtraction: XCTestCase { } func testSubtractingDigitReportingOverflow() { - NBKAssertSubtractionByDigit(T(1), UInt(0), Int(0), T(words:[ 1] as [UInt])) - NBKAssertSubtractionByDigit(T(1), UInt(1), Int(0), T(words:[ 0] as [UInt])) - NBKAssertSubtractionByDigit(T(1), UInt(2), Int(0), T(words:[~0] as [UInt]), true) - NBKAssertSubtractionByDigit(T(1), UInt(3), Int(0), T(words:[~1] as [UInt]), true) + NBKAssertSubtractionByDigit(T(1), UInt(0), Int(0), T(words:[ 1] as W)) + NBKAssertSubtractionByDigit(T(1), UInt(1), Int(0), T(words:[ 0] as W)) + NBKAssertSubtractionByDigit(T(1), UInt(2), Int(0), T(words:[~0] as W), true) + NBKAssertSubtractionByDigit(T(1), UInt(3), Int(0), T(words:[~1] as W), true) } func testSubtractingDigitAtIndex() { - NBKAssertSubtractionByDigit(T(words:[~0, ~0, ~0, ~0] as [UInt]), UInt(3), Int(0), T(words:[~3, ~0, ~0, ~0] as [UInt])) - NBKAssertSubtractionByDigit(T(words:[ 0, ~0, ~0, ~0] as [UInt]), UInt(3), Int(0), T(words:[~2, ~1, ~0, ~0] as [UInt])) - NBKAssertSubtractionByDigit(T(words:[ 0, 0, ~0, ~0] as [UInt]), UInt(3), Int(0), T(words:[~2, ~0, ~1, ~0] as [UInt])) - NBKAssertSubtractionByDigit(T(words:[ 0, 0, 0, ~0] as [UInt]), UInt(3), Int(0), T(words:[~2, ~0, ~0, ~1] as [UInt])) + NBKAssertSubtractionByDigit(T(words:[~0, ~0, ~0, ~0] as W), UInt(3), Int(0), T(words:[~3, ~0, ~0, ~0] as W)) + NBKAssertSubtractionByDigit(T(words:[ 0, ~0, ~0, ~0] as W), UInt(3), Int(0), T(words:[~2, ~1, ~0, ~0] as W)) + NBKAssertSubtractionByDigit(T(words:[ 0, 0, ~0, ~0] as W), UInt(3), Int(0), T(words:[~2, ~0, ~1, ~0] as W)) + NBKAssertSubtractionByDigit(T(words:[ 0, 0, 0, ~0] as W), UInt(3), Int(0), T(words:[~2, ~0, ~0, ~1] as W)) - NBKAssertSubtractionByDigit(T(words:[~0, ~0, ~0, ~0] as [UInt]), UInt(3), Int(1), T(words:[~0, ~3, ~0, ~0] as [UInt])) - NBKAssertSubtractionByDigit(T(words:[ 0, ~0, ~0, ~0] as [UInt]), UInt(3), Int(1), T(words:[ 0, ~3, ~0, ~0] as [UInt])) - NBKAssertSubtractionByDigit(T(words:[ 0, 0, ~0, ~0] as [UInt]), UInt(3), Int(1), T(words:[ 0, ~2, ~1, ~0] as [UInt])) - NBKAssertSubtractionByDigit(T(words:[ 0, 0, 0, ~0] as [UInt]), UInt(3), Int(1), T(words:[ 0, ~2, ~0, ~1] as [UInt])) + NBKAssertSubtractionByDigit(T(words:[~0, ~0, ~0, ~0] as W), UInt(3), Int(1), T(words:[~0, ~3, ~0, ~0] as W)) + NBKAssertSubtractionByDigit(T(words:[ 0, ~0, ~0, ~0] as W), UInt(3), Int(1), T(words:[ 0, ~3, ~0, ~0] as W)) + NBKAssertSubtractionByDigit(T(words:[ 0, 0, ~0, ~0] as W), UInt(3), Int(1), T(words:[ 0, ~2, ~1, ~0] as W)) + NBKAssertSubtractionByDigit(T(words:[ 0, 0, 0, ~0] as W), UInt(3), Int(1), T(words:[ 0, ~2, ~0, ~1] as W)) } func testSubtractingDigitAtIndexReportingOverflow() { - NBKAssertSubtractionByDigit(T(words:[ 1, 2, 3, 0] as [UInt]), UInt(5), Int(0), T(words:[~3, 1, 3, 0] as [UInt])) - NBKAssertSubtractionByDigit(T(words:[ 1, 2, 3, 0] as [UInt]), UInt(5), Int(1), T(words:[ 1, ~2, 2, 0] as [UInt])) - NBKAssertSubtractionByDigit(T(words:[ 1, 2, 3, 0] as [UInt]), UInt(5), Int(2), T(words:[ 1, 2, ~1, 0] as [UInt]), true) - NBKAssertSubtractionByDigit(T(words:[ 1, 2, 3, 0] as [UInt]), UInt(5), Int(3), T(words:[ 1, 2, 3, ~4] as [UInt]), true) + NBKAssertSubtractionByDigit(T(words:[ 1, 2, 3, 0] as W), UInt(5), Int(0), T(words:[~3, 1, 3, 0] as W)) + NBKAssertSubtractionByDigit(T(words:[ 1, 2, 3, 0] as W), UInt(5), Int(1), T(words:[ 1, ~2, 2, 0] as W)) + NBKAssertSubtractionByDigit(T(words:[ 1, 2, 3, 0] as W), UInt(5), Int(2), T(words:[ 1, 2, ~1, 0] as W), true) + NBKAssertSubtractionByDigit(T(words:[ 1, 2, 3, 0] as W), UInt(5), Int(3), T(words:[ 1, 2, 3, ~4] as W), true) } //=------------------------------------------------------------------------= diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Text.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Text.swift index dfcf1985..b73cb368 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Text.swift +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Text.swift @@ -13,6 +13,7 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest +private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Words.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Words.swift index a7457747..0a90e969 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Words.swift +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Words.swift @@ -13,6 +13,7 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest +private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] @@ -42,13 +43,13 @@ final class IntXLTestsOnWords: XCTestCase { NBKAssertWords(T(words:[1, 2, 3, 0]), [1, 2, 3 ]) NBKAssertWords(T(words:[1, 2, 3, 4]), [1, 2, 3, 4]) - NBKAssertWords(T(sign: .plus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as [UInt])), [~0, ~0, ~0, ~0/2 + 0 ] as [UInt]) // 4 - NBKAssertWords(T(sign: .plus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as [UInt])), [ 0, 0, 0, ~0/2 + 1, 0] as [UInt]) // 5 - NBKAssertWords(T(sign: .plus, magnitude: M(words:[ 1, 0, 0, ~0/2 + 1] as [UInt])), [ 1, 0, 0, ~0/2 + 1, 0] as [UInt]) // 5 + NBKAssertWords(T(sign: .plus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as W)), [~0, ~0, ~0, ~0/2 + 0 ] as W) // 4 + NBKAssertWords(T(sign: .plus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as W)), [ 0, 0, 0, ~0/2 + 1, 0] as W) // 5 + NBKAssertWords(T(sign: .plus, magnitude: M(words:[ 1, 0, 0, ~0/2 + 1] as W)), [ 1, 0, 0, ~0/2 + 1, 0] as W) // 5 - NBKAssertWords(T(sign: .minus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as [UInt])), [ 1, 0, 0, ~0/2 + 1 ] as [UInt]) // 4 - NBKAssertWords(T(sign: .minus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as [UInt])), [ 0, 0, 0, ~0/2 + 1 ] as [UInt]) // 4 - NBKAssertWords(T(sign: .minus, magnitude: M(words:[ 1, 0, 0, ~0/2 + 1] as [UInt])), [~0, ~0, ~0, ~0/2 + 0, ~0] as [UInt]) // 5 + NBKAssertWords(T(sign: .minus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as W)), [ 1, 0, 0, ~0/2 + 1 ] as W) // 4 + NBKAssertWords(T(sign: .minus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as W)), [ 0, 0, 0, ~0/2 + 1 ] as W) // 4 + NBKAssertWords(T(sign: .minus, magnitude: M(words:[ 1, 0, 0, ~0/2 + 1] as W)), [~0, ~0, ~0, ~0/2 + 0, ~0] as W) // 5 } func testWordsX64() throws { From 84abc87ed789c47b14f41a784785a122530c1ad9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Mon, 31 Jul 2023 09:43:25 +0200 Subject: [PATCH 032/133] NBKFlexibleWidthKit: Division. --- .../NBKFlexibleWidth+Division+Digit.swift | 6 +- .../NBKFlexibleWidth+Division.swift | 7 +- .../IntXL+Division.swift | 136 +++++++++++++++++ .../NBKFlexibleWidth.swift | 18 +++ .../IntXL+Division.swift | 141 +++++++++++++++++- .../NBKFlexibleWidth.swift | 18 +++ .../Utilities/NBKAssert+Division.swift | 12 +- 7 files changed, 325 insertions(+), 13 deletions(-) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.swift index a71beaf8..e7deed29 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.swift @@ -42,7 +42,11 @@ extension NBKFlexibleWidth { } @_disfavoredOverload @inlinable public func quotientAndRemainderReportingOverflow(dividingBy other: Digit) -> PVO> { - fatalError("TODO") + let otherSign = Sign(other.isLessThanZero) + let qro: PVO> = self.magnitude.quotientAndRemainderReportingOverflow(dividingBy: other.magnitude) + let quotient = Self(sign: self.sign ^ otherSign, magnitude: qro.partialValue.quotient ) + let remainder = Self.Digit.exactly(sign: self.sign, magnitude: qro.partialValue.remainder)! + return PVO(QR(quotient, remainder), qro.overflow) } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift index 0e107037..db0081a2 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift @@ -42,7 +42,10 @@ extension NBKFlexibleWidth { } @inlinable public func quotientAndRemainderReportingOverflow(dividingBy other: Self) -> PVO> { - fatalError("TODO") + let qro: PVO> = self.magnitude.quotientAndRemainderReportingOverflow(dividingBy: other.magnitude) + let quotient = Self(sign: self.sign ^ other.sign, magnitude: qro.partialValue.quotient ) + let remainder = Self(sign: self.sign, /*------*/ magnitude: qro.partialValue.remainder) + return PVO(QR(quotient, remainder), qro.overflow) } } @@ -133,7 +136,7 @@ extension NBKFlexibleWidth.Magnitude { let shift = divisor.elements.last!.leadingZeroBitCount as Int divisor.bitshiftLeft(words: Int.zero, bits: shift) let divisorLast0 = divisor.elements[divisor.elements.endIndex - 1] as UInt - assert(divisorLast0.mostSignificantBit, "divisor must be normalized") + assert(divisorLast0.mostSignificantBit) var remainderIndex = self.storage.elements.endIndex self.storage.elements.append(0) diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Division.swift b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Division.swift index 06aece6b..8e184d50 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Division.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Division.swift @@ -17,6 +17,116 @@ private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] +//*============================================================================* +// MARK: * NBK x IntXL x Division +//*============================================================================* + +final class IntXLBenchmarksOnDivision: XCTestCase { + + typealias T = IntXL + typealias M = IntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testQuotientAndRemainder() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + + for _ in 0 ..< 250_000 { + NBK.blackHole(lhs.quotientAndRemainder(dividingBy: rhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testQuotientReportingOverflow() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + + for _ in 0 ..< 250_000 { + NBK.blackHole(lhs.dividedReportingOverflow(by: rhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testRemainderReportingOverflow() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + + for _ in 0 ..< 250_000 { + NBK.blackHole(lhs.remainderReportingOverflow(dividingBy: rhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Digit + //=------------------------------------------------------------------------= + + func testQuotientAndRemainderDividingByDigit() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(Int.max) + + for _ in 0 ..< 250_000 { + NBK.blackHole(lhs.quotientAndRemainder(dividingBy: rhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testQuotientDividingByDigitReportingOverflow() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(Int.max) + + for _ in 0 ..< 250_000 { + NBK.blackHole(lhs.dividedReportingOverflow(by: rhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testRemainderDividingByDigitReportingOverflow() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(Int.max) + + for _ in 0 ..< 250_000 { + NBK.blackHole(lhs.remainderReportingOverflow(dividingBy: rhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Full Width + //=------------------------------------------------------------------------= + + func testDividingFullWidthAs256() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0/2] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0/2, ~0, ~0, ~0, ~0/4] as X)) + + for _ in 0 ..< 250_000 { + NBK.blackHole(rhs.quotientAndRemainder(dividingBy: lhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testDividingFullWidthReportingOverflowAs256() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0/2] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0/2, ~0, ~0, ~0, ~0/4] as X)) + + for _ in 0 ..< 250_000 { + NBK.blackHole(rhs.quotientAndRemainderReportingOverflow(dividingBy: lhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } +} + //*============================================================================* // MARK: * NBK x UIntXL x Division //*============================================================================* @@ -99,6 +209,32 @@ final class UIntXLBenchmarksOnDivision: XCTestCase { NBK.blackHoleInoutIdentity(&rhs) } } + + //=------------------------------------------------------------------------= + // MARK: Tests x Full Width + //=------------------------------------------------------------------------= + + func testDividingFullWidthAs256() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0, ~1, ~0, ~0, ~0] as X)) + + for _ in 0 ..< 250_000 { + NBK.blackHole(rhs.quotientAndRemainder(dividingBy: lhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testDividingFullWidthReportingOverflowAs256() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0, ~1, ~0, ~0, ~0] as X)) + + for _ in 0 ..< 250_000 { + NBK.blackHole(rhs.quotientAndRemainderReportingOverflow(dividingBy: lhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } } #endif diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth.swift index cbf880ce..fa1f957d 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth.swift @@ -11,12 +11,23 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + //*============================================================================* // MARK: * NBK x Flexible Width x Initializers x Signed //*============================================================================* extension NBKFlexibleWidth { + //=------------------------------------------------------------------------= + // MARK: Details x Numbers + //=------------------------------------------------------------------------= + + static let min256 = Self(x64:[ 0, 0, 0, 0/2 + 1] as X) + static let max256 = Self(x64:[~0, ~0, ~0, ~0/2 + 0] as X) + //=------------------------------------------------------------------------= // MARK: Details x Limbs //=------------------------------------------------------------------------= @@ -36,6 +47,13 @@ extension NBKFlexibleWidth { extension NBKFlexibleWidth.Magnitude { + //=------------------------------------------------------------------------= + // MARK: Details x Numbers + //=------------------------------------------------------------------------= + + static let min256 = Self(x64:[ 0, 0, 0, 0] as X) + static let max256 = Self(x64:[~0, ~0, ~0, ~0] as X) + //=------------------------------------------------------------------------= // MARK: Details x Limbs //=------------------------------------------------------------------------= diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Division.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Division.swift index 74b5af45..92b30677 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Division.swift +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Division.swift @@ -17,6 +17,133 @@ private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] +//*============================================================================* +// MARK: * NBK x IntXL x Division +//*============================================================================* + +final class IntXLTestsOnDivision: XCTestCase { + + typealias T = IntXL + typealias M = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testDividing() { + NBKAssertDivision( T( ), T(1), T( ), T( )) + NBKAssertDivision( T( ), T(2), T( ), T( )) + NBKAssertDivision( T(7), T(1), T(7), T( )) + NBKAssertDivision( T(7), T(2), T(3), T(1)) + + NBKAssertDivision( T(7), T(3), T(2), T(1)) + NBKAssertDivision( T(7), -T(3), -T(2), T(1)) + NBKAssertDivision(-T(7), T(3), -T(2), -T(1)) + NBKAssertDivision(-T(7), -T(3), T(2), -T(1)) + } + + func testDividingReportingOverflow() { + NBKAssertDivision( T(0), T( ), T(0), T( ), true) + NBKAssertDivision( T(1), T( ), T(1), T(1), true) + NBKAssertDivision( T(2), T( ), T(2), T(2), true) + + NBKAssertDivision(T(words:[~0, ~0, ~0, ~0/2 + 0] as W), -T(1), T(words:[1, 0, 0, ~0/2 + 1, ~0] as W), T( )) // Int256.max + NBKAssertDivision(T(words:[ 0, 0, 0, ~0/2 + 1] as W), -T(1), T(words:[0, 0, 0, ~0/2 + 1, 0] as W), T( )) // Int256.min + } + + func testDividingWithLargeDividend() { + NBKAssertDivision( T(words:[1, 2, 3, 4] as W), T(2), T(words:[0, ~0/2 + 2, 1, 2] as W), T(1)) + NBKAssertDivision( T(words:[1, 2, 3, 4] as W), -T(2), -T(words:[0, ~0/2 + 2, 1, 2] as W), T(1)) + NBKAssertDivision(-T(words:[1, 2, 3, 4] as W), T(2), -T(words:[0, ~0/2 + 2, 1, 2] as W), -T(1)) + NBKAssertDivision(-T(words:[1, 2, 3, 4] as W), -T(2), T(words:[0, ~0/2 + 2, 1, 2] as W), -T(1)) + + NBKAssertDivision( T(words:[1, 2, 3, 4] as W), T(words:[0, ~0/2 + 2, 1, 2] as W), T(2), T(1)) + NBKAssertDivision( T(words:[1, 2, 3, 4] as W), -T(words:[0, ~0/2 + 2, 1, 2] as W), -T(2), T(1)) + NBKAssertDivision(-T(words:[1, 2, 3, 4] as W), -T(words:[0, ~0/2 + 2, 1, 2] as W), T(2), -T(1)) + NBKAssertDivision(-T(words:[1, 2, 3, 4] as W), T(words:[0, ~0/2 + 2, 1, 2] as W), -T(2), -T(1)) + } + + func testDividingWithLargeDivisor() { + NBKAssertDivision(T(words:[1, 2, 3, 4 + 1 << 63] as W), T(words:[ 1, 2, 3, 4 &+ 1 << 63] as W), T(1), -T(words:[0, 0, 0, 0] as W)) + NBKAssertDivision(T(words:[1, 2, 3, 4 + 1 << 63] as W), T(words:[ 2, 3, 4, 5 &+ 1 << 63] as W), T(1), -T(words:[1, 1, 1, 1] as W)) + NBKAssertDivision(T(words:[1, 2, 3, 4 + 1 << 63] as W), T(words:[ 3, 4, 5, 6 &+ 1 << 63] as W), T(1), -T(words:[2, 2, 2, 2] as W)) + NBKAssertDivision(T(words:[1, 2, 3, 4 + 1 << 63] as W), T(words:[ 4, 5, 6, 7 &+ 1 << 63] as W), T(1), -T(words:[3, 3, 3, 3] as W)) + + NBKAssertDivision(T(words:[1, 2, 3, 4 + 1 << 63] as W), T(words:[~0, ~2, ~3, ~4 &+ 1 << 63] as W), -T(1), -T(words:[0, 0, 0, 0] as W)) + NBKAssertDivision(T(words:[1, 2, 3, 4 + 1 << 63] as W), T(words:[~1, ~3, ~4, ~5 &+ 1 << 63] as W), -T(1), -T(words:[1, 1, 1, 1] as W)) + NBKAssertDivision(T(words:[1, 2, 3, 4 + 1 << 63] as W), T(words:[~2, ~4, ~5, ~6 &+ 1 << 63] as W), -T(1), -T(words:[2, 2, 2, 2] as W)) + NBKAssertDivision(T(words:[1, 2, 3, 4 + 1 << 63] as W), T(words:[~3, ~5, ~6, ~7 &+ 1 << 63] as W), -T(1), -T(words:[3, 3, 3, 3] as W)) + } + + func testDividingLikeFullWidth() { + var dividend: T + //=--------------------------------------= + dividend = T(words:[ 06, 17, 35, 61, 61, 52, 32, 00] as W) + NBKAssertDivision(dividend, T(words:[ 1, 2, 3, 4] as W), T(words:[ 5, 6, 7, 8] as W), T(words:[ 1, 1, 1, 1] as W)) + NBKAssertDivision(dividend, T(words:[ 5, 6, 7, 8] as W), T(words:[ 1, 2, 3, 4] as W), T(words:[ 1, 1, 1, 1] as W)) + //=--------------------------------------= + dividend = T(words:[ 34, 54, 63, 62, 34, 16, 05, 00] as W) + NBKAssertDivision(dividend, T(words:[ 4, 3, 2, 1] as W), T(words:[ 9, 7, 6, 5] as W), T(words:[~1, ~1, ~0, 0] as W)) + NBKAssertDivision(dividend, T(words:[ 8, 7, 6, 5] as W), T(words:[ 4, 3, 2, 1] as W), T(words:[ 2, 2, 2, 2] as W)) + //=--------------------------------------= + dividend = T(words:[ ~1, ~0, ~0, ~0, ~0, ~0, ~0, ~0] as W) + NBKAssertDivision(dividend, T(words:[ 1, 0, 0, 0] as W), T(words:[~1, ~0, ~0, ~0] as W), T(words:[ 0, 0, 0, 0] as W)) + NBKAssertDivision(dividend, T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 2, 0, 0, 0] as W), T(words:[ 0, 0, 0, 0] as W)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Digit + //=------------------------------------------------------------------------= + + func testDividingByDigit() { + NBKAssertDivisionByDigit( T( ), Int(1), T( ), Int( )) + NBKAssertDivisionByDigit( T( ), Int(2), T( ), Int( )) + NBKAssertDivisionByDigit( T(7), Int(1), T(7), Int( )) + NBKAssertDivisionByDigit( T(7), Int(2), T(3), Int(1)) + + NBKAssertDivisionByDigit( T(7), Int(3), T(2), Int(1)) + NBKAssertDivisionByDigit( T(7), -Int(3), -T(2), Int(1)) + NBKAssertDivisionByDigit(-T(7), Int(3), -T(2), -Int(1)) + NBKAssertDivisionByDigit(-T(7), -Int(3), T(2), -Int(1)) + } + + func testDividingByDigitReportingOverflow() { + NBKAssertDivisionByDigit( T(0), Int( ), T( 0), Int( ), true) + NBKAssertDivisionByDigit( T(1), Int( ), T( 1), Int(1), true) + NBKAssertDivisionByDigit( T(2), Int( ), T( 2), Int(2), true) + + NBKAssertDivisionByDigit(T(words:[~0, ~0, ~0, ~0/2 + 0] as W), -Int(1), T(words:[1, 0, 0, ~0/2 + 1, ~0] as W), Int( )) // Int256.max + NBKAssertDivisionByDigit(T(words:[ 0, 0, 0, ~0/2 + 1] as W), -Int(1), T(words:[0, 0, 0, ~0/2 + 1, 0] as W), Int( )) // Int256.min + } + + func testDividingByDigitWithLargeDividend() { + NBKAssertDivisionByDigit( T(words:[1, 2, 3, 4] as W), Int(2), T(words:[0, ~0/2 + 2, 1, 2] as W), Int(1)) + NBKAssertDivisionByDigit( T(words:[1, 2, 3, 4] as W), -Int(2), -T(words:[0, ~0/2 + 2, 1, 2] as W), Int(1)) + NBKAssertDivisionByDigit(-T(words:[1, 2, 3, 4] as W), Int(2), -T(words:[0, ~0/2 + 2, 1, 2] as W), -Int(1)) + NBKAssertDivisionByDigit(-T(words:[1, 2, 3, 4] as W), -Int(2), T(words:[0, ~0/2 + 2, 1, 2] as W), -Int(1)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Miscellaneous + //=------------------------------------------------------------------------= + + func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { + func becauseThisCompilesSuccessfully(_ x: inout T) { + XCTAssertNotNil(x /= 0) + XCTAssertNotNil(x %= 0) + XCTAssertNotNil(x.divideReportingOverflow(by: 0)) + XCTAssertNotNil(x.formRemainderReportingOverflow(dividingBy: 0)) + + XCTAssertNotNil(x / 0) + XCTAssertNotNil(x % 0) + XCTAssertNotNil(x.dividedReportingOverflow(by: 0)) + XCTAssertNotNil(x.remainderReportingOverflow(dividingBy: 0)) + XCTAssertNotNil(x.quotientAndRemainder(dividingBy: 0)) + XCTAssertNotNil(x.quotientAndRemainderReportingOverflow(dividingBy: 0)) + } + } +} + //*============================================================================* // MARK: * NBK x UIntXL x Division //*============================================================================* @@ -71,11 +198,15 @@ final class UIntXLTestsOnDivision: XCTestCase { } func testDividingLikeFullWidth() { - NBKAssertDivision(M(x64:[06, 17, 35, 61, 61, 52, 32, 00] as X), T(x64:[1, 2, 3, 4] as X), T(x64:[5, 6, 7, 8] as X), T(x64:[ 1, 1, 1, 1] as X)) - NBKAssertDivision(M(x64:[06, 17, 35, 61, 61, 52, 32, 00] as X), T(x64:[5, 6, 7, 8] as X), T(x64:[1, 2, 3, 4] as X), T(x64:[ 1, 1, 1, 1] as X)) - - NBKAssertDivision(M(x64:[34, 54, 63, 62, 34, 16, 05, 00] as X), T(x64:[4, 3, 2, 1] as X), T(x64:[9, 7, 6, 5] as X), T(x64:[~1, ~1, ~0, 0] as X)) - NBKAssertDivision(M(x64:[34, 54, 63, 62, 34, 16, 05, 00] as X), T(x64:[8, 7, 6, 5] as X), T(x64:[4, 3, 2, 1] as X), T(x64:[ 2, 2, 2, 2] as X)) + var dividend: T + //=--------------------------------------= + dividend = T(words:[ 06, 17, 35, 61, 61, 52, 32, 00] as W) + NBKAssertDivision(dividend, T(words:[ 1, 2, 3, 4] as W), T(words:[ 5, 6, 7, 8] as W), T(words:[ 1, 1, 1, 1] as W)) + NBKAssertDivision(dividend, T(words:[ 5, 6, 7, 8] as W), T(words:[ 1, 2, 3, 4] as W), T(words:[ 1, 1, 1, 1] as W)) + //=--------------------------------------= + dividend = T(words:[ 34, 54, 63, 62, 34, 16, 05, 00] as W) + NBKAssertDivision(dividend, T(words:[ 4, 3, 2, 1] as W), T(words:[ 9, 7, 6, 5] as W), T(words:[~1, ~1, ~0, 0] as W)) + NBKAssertDivision(dividend, T(words:[ 8, 7, 6, 5] as W), T(words:[ 4, 3, 2, 1] as W), T(words:[ 2, 2, 2, 2] as W)) } //=------------------------------------------------------------------------= diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth.swift index cbf880ce..fa1f957d 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth.swift @@ -11,12 +11,23 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + //*============================================================================* // MARK: * NBK x Flexible Width x Initializers x Signed //*============================================================================* extension NBKFlexibleWidth { + //=------------------------------------------------------------------------= + // MARK: Details x Numbers + //=------------------------------------------------------------------------= + + static let min256 = Self(x64:[ 0, 0, 0, 0/2 + 1] as X) + static let max256 = Self(x64:[~0, ~0, ~0, ~0/2 + 0] as X) + //=------------------------------------------------------------------------= // MARK: Details x Limbs //=------------------------------------------------------------------------= @@ -36,6 +47,13 @@ extension NBKFlexibleWidth { extension NBKFlexibleWidth.Magnitude { + //=------------------------------------------------------------------------= + // MARK: Details x Numbers + //=------------------------------------------------------------------------= + + static let min256 = Self(x64:[ 0, 0, 0, 0] as X) + static let max256 = Self(x64:[~0, ~0, ~0, ~0] as X) + //=------------------------------------------------------------------------= // MARK: Details x Limbs //=------------------------------------------------------------------------= diff --git a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Division.swift b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Division.swift index 3e6e7644..82dbdc04 100644 --- a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Division.swift +++ b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Division.swift @@ -15,8 +15,8 @@ import XCTest // MARK: * NBK x Assert x Division //*============================================================================* -func NBKAssertDivision( -_ lhs: UIntXL, _ rhs: UIntXL, _ quotient: UIntXL, _ remainder: UIntXL, _ overflow: Bool = false, +func NBKAssertDivision( +_ lhs: T, _ rhs: T, _ quotient: T, _ remainder: T, _ overflow: Bool = false, file: StaticString = #file, line: UInt = #line) { //=------------------------------------------= XCTAssertEqual(lhs, quotient * rhs + remainder, "lhs != rhs * quotient + remainder", file: file, line: line) @@ -48,15 +48,17 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual(lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs).partialValue.remainder, remainder, file: file, line: line) XCTAssertEqual(lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs).overflow, overflow, file: file, line: line) //=------------------------------------------= + guard let lhs = lhs as? UIntXL, let rhs = rhs as? UIntXL, let quotient = quotient as? UIntXL, let remainder = remainder as? UIntXL else { return } + //=------------------------------------------= XCTAssertEqual(lhs.quotientAndRemainderReportingOverflowAsNormal(dividingBy: rhs).partialValue.quotient, quotient, file: file, line: line) XCTAssertEqual(lhs.quotientAndRemainderReportingOverflowAsNormal(dividingBy: rhs).partialValue.remainder, remainder, file: file, line: line) XCTAssertEqual(lhs.quotientAndRemainderReportingOverflowAsNormal(dividingBy: rhs).overflow, overflow, file: file, line: line) } -func NBKAssertDivisionByDigit( -_ lhs: UIntXL, _ rhs: UIntXL.Digit, _ quotient: UIntXL, _ remainder: UIntXL.Digit, _ overflow: Bool = false, +func NBKAssertDivisionByDigit( +_ lhs: T, _ rhs: T.Digit, _ quotient: T, _ remainder: T.Digit, _ overflow: Bool = false, file: StaticString = #file, line: UInt = #line) { - let extended = UIntXL(digit: remainder) + let extended = T(digit: remainder) //=------------------------------------------= XCTAssertEqual(lhs, quotient * rhs + remainder, "lhs != rhs * quotient + remainder", file: file, line: line) //=------------------------------------------= From cc7bb4e2bb7a0146297de557a918ee699d0a8d56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Mon, 31 Jul 2023 10:34:43 +0200 Subject: [PATCH 033/133] NBKFlexibleWidthKit: Text. --- .../NBKFlexibleWidthKit-Benchmarks.xctestplan | 2 + .../NBKFlexibleWidth+Protocols.swift | 2 +- .../NBKFlexibleWidth+Text+Radix.swift | 27 +- .../IntXL+Text.swift | 90 +++++++ .../NBKFlexibleWidth.swift | 2 +- .../NBKFlexibleWidthKitTests/IntXL+Text.swift | 243 +++++++++++++++++- .../NBKFlexibleWidth.swift | 2 +- .../Utilities/NBKAssert+Text.swift | 14 +- 8 files changed, 363 insertions(+), 19 deletions(-) diff --git a/.swiftpm/NBKFlexibleWidthKit-Benchmarks.xctestplan b/.swiftpm/NBKFlexibleWidthKit-Benchmarks.xctestplan index 55b3abb9..38bde86c 100644 --- a/.swiftpm/NBKFlexibleWidthKit-Benchmarks.xctestplan +++ b/.swiftpm/NBKFlexibleWidthKit-Benchmarks.xctestplan @@ -14,6 +14,8 @@ "testTargets" : [ { "skippedTests" : [ + "IntXLBenchmarksOnText\/testEncodingUsingSwiftStdlibRadix10()", + "IntXLBenchmarksOnText\/testEncodingUsingSwiftStdlibRadix16()", "UIntXLBenchmarksOnText\/testEncodingUsingSwiftStdlibRadix10()", "UIntXLBenchmarksOnText\/testEncodingUsingSwiftStdlibRadix16()" ], diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Protocols.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Protocols.swift index 694d1cd7..fe57876f 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Protocols.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Protocols.swift @@ -15,7 +15,7 @@ import NBKCoreKit // MARK: * NBK x Flexible Width x Protocol //*============================================================================* -public protocol IntXLOrUIntXL: NBKBinaryInteger { +public protocol IntXLOrUIntXL: NBKBinaryInteger, LosslessStringConvertible { //=------------------------------------------------------------------------= // MARK: Details x Comparisons diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text+Radix.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text+Radix.swift index de0cca3a..aaa1e9c3 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text+Radix.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text+Radix.swift @@ -9,7 +9,6 @@ import NBKCoreKit -// TODO: IntXL and UIntXL are similar //*============================================================================* // MARK: * NBK x Flexible Width x Text x Radix x Signed //*============================================================================* @@ -21,7 +20,17 @@ extension NBKFlexibleWidth { //=------------------------------------------------------------------------= @inlinable public init?(_ description: some StringProtocol, radix: Int = 10) { - fatalError("TODO") + var description = String(description) + + let value: Optional = description.withUTF8 { utf8 in + let (radix) = NBK.AnyRadixUIntRoot(radix) + let (sign,body) = NBK.integerComponents(utf8: utf8) + let (digits) = NBK.UnsafeUTF8(rebasing: body) + let (magnitude) = Magnitude(digits: digits, radix: radix) + return magnitude.flatMap({ Self.exactly(sign: sign, magnitude: $0) }) + } + + if let value { self = value } else { return nil } } //=------------------------------------------------------------------------= @@ -29,7 +38,13 @@ extension NBKFlexibleWidth { //=------------------------------------------------------------------------= @inlinable public func description(radix: Int = 10, uppercase: Bool = false) -> String { - fatalError("TODO") + Swift.withUnsafePointer(to: UInt8(ascii: "-")) { minus in + let radix = NBK.AnyRadixUIntRoot(radix) + let alphabet = NBK.MaxRadixAlphabetEncoder(uppercase: uppercase) + let prefix = NBK.UnsafeUTF8(start: minus, count: Int(bit: self.isLessThanZero)) + let suffix = NBK.UnsafeUTF8(start: nil, count: Int.zero) + return self.magnitude.description(radix: radix, alphabet: alphabet, prefix: prefix, suffix: suffix) + } } } @@ -72,9 +87,9 @@ extension NBKFlexibleWidth.Magnitude { } } -//*============================================================================* -// MARK: * NBK x Flexible Width x Text x Radix x Unsigned -//*============================================================================* +//=----------------------------------------------------------------------------= +// MARK: + Algorithms +//=----------------------------------------------------------------------------= extension NBKFlexibleWidth.Magnitude { diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Text.swift b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Text.swift index 341b057e..e4eb6e7a 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Text.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Text.swift @@ -17,6 +17,96 @@ private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] +//*============================================================================* +// MARK: * NBK x IntXL x Division +//*============================================================================* + +final class IntXLBenchmarksOnText: XCTestCase { + + typealias T = IntXL + + //=------------------------------------------------------------------------= + // MARK: State + //=------------------------------------------------------------------------= + + static let decoded = NBK.blackHoleIdentity(T(encoded, radix: 16)!) + static let encoded = NBK.blackHoleIdentity(String(repeating: "1", count: 64)) + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testDecodingRadix10() { + var radix = NBK.blackHoleIdentity(10) + var encoded = NBK.blackHoleIdentity(Self.encoded) + + for _ in 0 ..< 250_000 { + NBK.blackHole(T(encoded, radix: radix)!) + NBK.blackHoleInoutIdentity(&radix) + NBK.blackHoleInoutIdentity(&encoded) + } + } + + func testDecodingRadix16() { + var radix = NBK.blackHoleIdentity(16) + var encoded = NBK.blackHoleIdentity(Self.encoded) + + for _ in 0 ..< 250_000 { + NBK.blackHole(T(encoded, radix: radix)!) + NBK.blackHoleInoutIdentity(&radix) + NBK.blackHoleInoutIdentity(&encoded) + } + } + + func testEncodingRadix10() { + var radix = NBK.blackHoleIdentity(10) + var decoded = NBK.blackHoleIdentity(Self.decoded) + + for _ in 0 ..< 250_000 { + NBK.blackHole(String(decoded, radix: radix)) + NBK.blackHoleInoutIdentity(&radix) + NBK.blackHoleInoutIdentity(&decoded) + } + } + + func testEncodingRadix16() { + var radix = NBK.blackHoleIdentity(16) + var decoded = NBK.blackHoleIdentity(Self.decoded) + + for _ in 0 ..< 250_000 { + NBK.blackHole(String(decoded, radix: radix)) + NBK.blackHoleInoutIdentity(&radix) + NBK.blackHoleInoutIdentity(&decoded) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Swift Standard Library Methods + //=------------------------------------------------------------------------= + + func testEncodingUsingSwiftStdlibRadix10() { + var radix = NBK.blackHoleIdentity(10) + var decoded = NBK.blackHoleIdentity(Self.decoded) + + for _ in 0 ..< 1_000 { + NBK.blackHole(NBK.descriptionAsStdlib(decoded, radix: radix)) + NBK.blackHoleInoutIdentity(&radix) + NBK.blackHoleInoutIdentity(&decoded) + } + } + + func testEncodingUsingSwiftStdlibRadix16() { + var radix = NBK.blackHoleIdentity(16) + var decoded = NBK.blackHoleIdentity(Self.decoded) + + for _ in 0 ..< 1_000 { + NBK.blackHole(NBK.descriptionAsStdlib(decoded, radix: radix)) + NBK.blackHoleInoutIdentity(&radix) + NBK.blackHoleInoutIdentity(&decoded) + } + } +} + //*============================================================================* // MARK: * NBK x UIntXL x Division //*============================================================================* diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth.swift index fa1f957d..ccc06e1e 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth.swift @@ -25,7 +25,7 @@ extension NBKFlexibleWidth { // MARK: Details x Numbers //=------------------------------------------------------------------------= - static let min256 = Self(x64:[ 0, 0, 0, 0/2 + 1] as X) + static let min256 = Self(x64:[ 0, 0, 0, ~0/2 + 1] as X) static let max256 = Self(x64:[~0, ~0, ~0, ~0/2 + 0] as X) //=------------------------------------------------------------------------= diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Text.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Text.swift index b73cb368..b732aa61 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Text.swift +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Text.swift @@ -17,6 +17,243 @@ private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] +//*============================================================================* +// MARK: * NBK x IntXL x Text +//*============================================================================* + +final class IntXLTestsOnText: XCTestCase { + + typealias T = IntXL + + //=------------------------------------------------------------------------= + // MARK: State + //=------------------------------------------------------------------------= + + let bit256 = 256 + let min256 = T.min256 + let max256 = T.max256 + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testInitDescription() { + XCTAssertEqual(T( "10"), 10) + XCTAssertEqual(T( "+10"), 10) + XCTAssertEqual(T( "-10"), -10) + XCTAssertEqual(T( " 10"), nil) + + XCTAssertEqual(T( "0x10"), nil) + XCTAssertEqual(T("+0x10"), nil) + XCTAssertEqual(T("-0x10"), nil) + XCTAssertEqual(T(" 0x10"), nil) + } + + func testInstanceDescriptionUsesRadix10() { + XCTAssertEqual("10", T(10).description) + XCTAssertEqual("10", String(describing: T(10))) + } + + func testMetaTypeDescriptionIsSimple() { + XCTAssertEqual("IntXL", T.description) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Decode + //=------------------------------------------------------------------------= + + func testDecodingRadix02() { + NBKAssertDecodeText(min256, 02, "-1" + String(repeating: "0", count: bit256 / 1 - 1)) + NBKAssertDecodeText(max256, 02, String(repeating: "1", count: bit256 / 1 - 1)) + } + + func testDecodingRadix03() { + NBKAssertDecodeText(min256, 03, "-21221122120" + + "12222212211110210202220000022211002111211122012220" + + "12122202101121021220012201000100012101202122101020" + + "20010111121211022111102111220220201211121011101022" ) + NBKAssertDecodeText(max256, 03, "21221122120" + + "12222212211110210202220000022211002111211122012220" + + "12122202101121021220012201000100012101202122101020" + + "20010111121211022111102111220220201211121011101021" ) + } + + func testDecodingRadix04() { + NBKAssertDecodeText(min256, 04, "-2" + String(repeating: "0", count: bit256 / 2 - 1)) + NBKAssertDecodeText(max256, 04, "1" + String(repeating: "3", count: bit256 / 2 - 1)) + } + + func testDecodingRadix08() { + NBKAssertDecodeText(min256, 08, "-1" + String(repeating: "0", count: 85)) + NBKAssertDecodeText(max256, 08, String(repeating: "7", count: 85)) + } + + func testDecodingRadix10() { + NBKAssertDecodeText(min256, 10, "-57896044618658097711785492504343953926634992332820282019728792003956564819968") + NBKAssertDecodeText(max256, 10, "57896044618658097711785492504343953926634992332820282019728792003956564819967") + } + + func testDecodingRadix16() { + NBKAssertDecodeText(min256, 16, "-8" + String(repeating: "0", count: bit256 / 4 - 1)) + NBKAssertDecodeText(max256, 16, "7" + String(repeating: "f", count: bit256 / 4 - 1)) + } + + func testDecodingRadix32() { + NBKAssertDecodeText(min256, 32, "-1" + String(repeating: "0", count: 51)) + NBKAssertDecodeText(max256, 32, String(repeating: "v", count: 51)) + } + + func testDecodingRadix36() { + NBKAssertDecodeText(min256, 36, "-36ukv65j19b11mbvjyfui963v4my01krth19g3r3bk1ojlrwu8") + NBKAssertDecodeText(max256, 36, "36ukv65j19b11mbvjyfui963v4my01krth19g3r3bk1ojlrwu7") + } + + func testDecodingRadixLiteralAsNumber() { + NBKAssertDecodeText(T( 33), 36, "0x") + NBKAssertDecodeText(T( 24), 36, "0o") + NBKAssertDecodeText(T( 11), 36, "0b") + + NBKAssertDecodeText(T( 33), 36, "+0x") + NBKAssertDecodeText(T( 24), 36, "+0o") + NBKAssertDecodeText(T( 11), 36, "+0b") + + NBKAssertDecodeText(T(-33), 36, "-0x") + NBKAssertDecodeText(T(-24), 36, "-0o") + NBKAssertDecodeText(T(-11), 36, "-0b") + } + + func testDecodingRadixLiteralAsRadixReturnsNil() { + NBKAssertDecodeText(T?.none, 10, "0x10") + NBKAssertDecodeText(T?.none, 10, "0o10") + NBKAssertDecodeText(T?.none, 10, "0b10") + + NBKAssertDecodeText(T?.none, 10, "+0x10") + NBKAssertDecodeText(T?.none, 10, "+0o10") + NBKAssertDecodeText(T?.none, 10, "+0b10") + + NBKAssertDecodeText(T?.none, 10, "-0x10") + NBKAssertDecodeText(T?.none, 10, "-0o10") + NBKAssertDecodeText(T?.none, 10, "-0b10") + } + + func testDecodingStringsWithAndWithoutSign() { + NBKAssertDecodeText(T( 1234567890), 10, "1234567890") + NBKAssertDecodeText(T( 1234567890), 10, "+1234567890") + NBKAssertDecodeText(T(-1234567890), 10, "-1234567890") + } + + func testDecodingStrategyIsCaseInsensitive() { + NBKAssertDecodeText(T(0xabcdef), 16, "abcdef") + NBKAssertDecodeText(T(0xABCDEF), 16, "ABCDEF") + NBKAssertDecodeText(T(0xaBcDeF), 16, "aBcDeF") + NBKAssertDecodeText(T(0xAbCdEf), 16, "AbCdEf") + } + + func testDecodingUnalignedStringsIsOK() { + NBKAssertDecodeText(T(1), 10, "1") + NBKAssertDecodeText(T(1), 16, "1") + } + + func testDecodingPrefixingZerosHasNoEffect() { + let zero = String(repeating: "0", count: bit256) + "0" + let one = String(repeating: "0", count: bit256) + "1" + + for radix in 02 ... 36 { + NBKAssertDecodeText(T(0), radix, zero) + NBKAssertDecodeText(T(1), radix, one ) + } + } + + func testDecodingInvalidCharactersReturnsNil() { + NBKAssertDecodeText(T?.none, 16, "/") + NBKAssertDecodeText(T?.none, 16, "G") + + NBKAssertDecodeText(T?.none, 10, "/") + NBKAssertDecodeText(T?.none, 10, ":") + + NBKAssertDecodeText(T?.none, 10, String(repeating: "1", count: 19) + "/") + NBKAssertDecodeText(T?.none, 10, String(repeating: "1", count: 19) + ":") + } + + func testDecodingStringsWithoutDigitsReturnsNil() { + NBKAssertDecodeText(T?.none, 10, "") + NBKAssertDecodeText(T?.none, 10, "+") + NBKAssertDecodeText(T?.none, 10, "-") + NBKAssertDecodeText(T?.none, 10, "~") + + NBKAssertDecodeText(T?.none, 16, "") + NBKAssertDecodeText(T?.none, 16, "+") + NBKAssertDecodeText(T?.none, 16, "-") + NBKAssertDecodeText(T?.none, 16, "~") + } + + func testDecodingValuesOutsideOfRepresentableRangeReturnsNil() { + let positive = "+" + String(repeating: "1", count: bit256) + let negative = "-" + String(repeating: "1", count: bit256) + + for radix in 02 ... 36 { + XCTAssertNotNil(T(positive, radix: radix)) + XCTAssertNotNil(T(negative, radix: radix)) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Encode + //=------------------------------------------------------------------------= + + func testEncodingRadix02() { + NBKAssertEncodeText(min256, 02, false, "-1" + String(repeating: "0", count: bit256 / 1 - 1)) + NBKAssertEncodeText(max256, 02, false, String(repeating: "1", count: bit256 / 1 - 1)) + } + + func testEncodingRadix03() { + NBKAssertEncodeText(min256, 03, false,"-21221122120" + + "12222212211110210202220000022211002111211122012220" + + "12122202101121021220012201000100012101202122101020" + + "20010111121211022111102111220220201211121011101022" ) + NBKAssertEncodeText(max256, 03, false, "21221122120" + + "12222212211110210202220000022211002111211122012220" + + "12122202101121021220012201000100012101202122101020" + + "20010111121211022111102111220220201211121011101021" ) + } + + func testEncodingRadix04() { + NBKAssertEncodeText(min256, 04, false, "-2" + String(repeating: "0", count: bit256 / 2 - 1)) + NBKAssertEncodeText(max256, 04, false, "1" + String(repeating: "3", count: bit256 / 2 - 1)) + } + + func testEncodingRadix08() { + NBKAssertEncodeText(min256, 08, false, "-1" + String(repeating: "0", count: 85)) + NBKAssertEncodeText(max256, 08, false, String(repeating: "7", count: 85)) + } + + func testEncodingRadix10() { + NBKAssertEncodeText(min256, 10, false, "-57896044618658097711785492504343953926634992332820282019728792003956564819968") + NBKAssertEncodeText(max256, 10, false, "57896044618658097711785492504343953926634992332820282019728792003956564819967") + } + + func testEncodingRadix16() { + NBKAssertEncodeText(min256, 16, false, "-8" + String(repeating: "0", count: bit256 / 4 - 1)) + NBKAssertEncodeText(min256, 16, true , "-8" + String(repeating: "0", count: bit256 / 4 - 1)) + NBKAssertEncodeText(max256, 16, false, "7" + String(repeating: "f", count: bit256 / 4 - 1)) + NBKAssertEncodeText(max256, 16, true , "7" + String(repeating: "F", count: bit256 / 4 - 1)) + } + + func testEncodingRadix32() { + NBKAssertEncodeText(min256, 32, false, "-1" + String(repeating: "0", count: 51)) + NBKAssertEncodeText(min256, 32, true , "-1" + String(repeating: "0", count: 51)) + NBKAssertEncodeText(max256, 32, false, String(repeating: "v", count: 51)) + NBKAssertEncodeText(max256, 32, true , String(repeating: "V", count: 51)) + } + + func testEncodingRadix36() { + NBKAssertEncodeText(min256, 36, false, "-36ukv65j19b11mbvjyfui963v4my01krth19g3r3bk1ojlrwu8") + NBKAssertEncodeText(min256, 36, true , "-36UKV65J19B11MBVJYFUI963V4MY01KRTH19G3R3BK1OJLRWU8") + NBKAssertEncodeText(max256, 36, false, "36ukv65j19b11mbvjyfui963v4my01krth19g3r3bk1ojlrwu7") + NBKAssertEncodeText(max256, 36, true , "36UKV65J19B11MBVJYFUI963V4MY01KRTH19G3R3BK1OJLRWU7") + } +} + //*============================================================================* // MARK: * NBK x UIntXL x Text //*============================================================================* @@ -29,9 +266,9 @@ final class UIntXLTestsOnText: XCTestCase { // MARK: State //=------------------------------------------------------------------------= - let bit256 = 256 as Int - let min256 = T(x64: X(repeating: UInt64.min, count: 4)) - let max256 = T(x64: X(repeating: UInt64.max, count: 4)) + let bit256 = 256 + let min256 = T.min256 + let max256 = T.max256 //=------------------------------------------------------------------------= // MARK: Tests diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth.swift index fa1f957d..ccc06e1e 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth.swift @@ -25,7 +25,7 @@ extension NBKFlexibleWidth { // MARK: Details x Numbers //=------------------------------------------------------------------------= - static let min256 = Self(x64:[ 0, 0, 0, 0/2 + 1] as X) + static let min256 = Self(x64:[ 0, 0, 0, ~0/2 + 1] as X) static let max256 = Self(x64:[~0, ~0, ~0, ~0/2 + 0] as X) //=------------------------------------------------------------------------= diff --git a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Text.swift b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Text.swift index 094039e5..8f7b4d41 100644 --- a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Text.swift +++ b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Text.swift @@ -15,19 +15,19 @@ import XCTest // MARK: * NBK x Assert x Text //*============================================================================* -func NBKAssertDecodeText( -_ integer: UIntXL?, _ radix: Int, _ text: String, -file: StaticString = #file, line: UInt = #line) { +func NBKAssertDecodeText ( +_ integer: T?, _ radix: Int, _ text: String, +file: StaticString = #file, line: UInt = #line) where T: LosslessStringConvertible { //=------------------------------------------= if radix == 10 { - XCTAssertEqual(UIntXL(text), integer, file: file, line: line) + XCTAssertEqual(T(text), integer, file: file, line: line) } //=------------------------------------------= - XCTAssertEqual(UIntXL(text, radix: radix), integer, file: file, line: line) + XCTAssertEqual(T(text, radix: radix), integer, file: file, line: line) } -func NBKAssertEncodeText( -_ integer: UIntXL, _ radix: Int, _ uppercase: Bool, _ text: String, +func NBKAssertEncodeText( +_ integer: T, _ radix: Int, _ uppercase: Bool, _ text: String, file: StaticString = #file, line: UInt = #line) { //=------------------------------------------= if radix == 10, uppercase == false { From 254884569843cec8f5e2aae0440454cef7e55576 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Tue, 1 Aug 2023 14:48:46 +0200 Subject: [PATCH 034/133] NBKFlexibleWidthKit: Shifts. --- ...NBKFlexibleWidth+Complements+Storage.swift | 2 +- .../NBKFlexibleWidth+Protocols.swift | 36 +++++ .../NBKFlexibleWidth+Shifts.swift | 37 +++-- .../IntXL+Shifts.swift | 132 ++++++++++++++++++ .../IntXL+Shifts.swift | 118 ++++++++++++++++ .../Utilities/NBKAssert+Shifts.swift | 8 +- 6 files changed, 319 insertions(+), 14 deletions(-) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements+Storage.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements+Storage.swift index c20e9c56..ce53294f 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements+Storage.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements+Storage.swift @@ -31,7 +31,7 @@ extension NBKFlexibleWidth.Magnitude.Storage { var carry = carry for index in self.elements.indices { - carry = self.elements[index].formTwosComplementSubsequence(carry) + carry = self.elements[index].formTwosComplementSubsequence(carry) } return carry as Bool diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Protocols.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Protocols.swift index fe57876f..d97376aa 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Protocols.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Protocols.swift @@ -68,4 +68,40 @@ public protocol IntXLOrUIntXL: NBKBinaryInteger, LosslessStringConvertible { @inlinable func multiplied(by multiplicand: Self) -> Self @_disfavoredOverload @inlinable func multiplied(by multiplicand: Digit, adding addend: UInt) -> Self + + //=------------------------------------------------------------------------= + // MARK: Details x Shifts + //=------------------------------------------------------------------------= + + @inlinable mutating func bitshiftLeftSmart(by distance: Int) + + @inlinable func bitshiftedLeftSmart(by distance: Int) -> Self + + @inlinable mutating func bitshiftLeft(by distance: Int) + + @inlinable func bitshiftedLeft(by distance: Int) -> Self + + @inlinable mutating func bitshiftLeft(words: Int, bits: Int) + + @inlinable func bitshiftedLeft(words: Int, bits: Int) -> Self + + @inlinable mutating func bitshiftLeft(words: Int) + + @inlinable func bitshiftedLeft(words: Int) -> Self + + @inlinable mutating func bitshiftRightSmart(by distance: Int) + + @inlinable func bitshiftedRightSmart(by distance: Int) -> Self + + @inlinable mutating func bitshiftRight(by distance: Int) + + @inlinable func bitshiftedRight(by distance: Int) -> Self + + @inlinable mutating func bitshiftRight(words: Int, bits: Int) + + @inlinable func bitshiftedRight(words: Int, bits: Int) -> Self + + @inlinable mutating func bitshiftRight(words: Int) + + @inlinable func bitshiftedRight(words: Int) -> Self } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift index 50ad3e30..0233c2e7 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift @@ -23,7 +23,7 @@ extension NBKFlexibleWidth { //=------------------------------------------------------------------------= @inlinable public static func <<=(lhs: inout Self, rhs: some BinaryInteger) { - fatalError("TODO") + lhs.bitshiftLeftSmart(by: NBK.initOrBitCast(clamping: rhs, as: Int.self)) } @inlinable public static func <<(lhs: Self, rhs: some BinaryInteger) -> Self { @@ -35,7 +35,11 @@ extension NBKFlexibleWidth { //=------------------------------------------------------------------------= @inlinable public mutating func bitshiftLeftSmart(by distance: Int) { - fatalError("TODO") + if distance >= 0 { + self.bitshiftLeft (by: distance) + } else { + self.bitshiftRight(by: NBK.initOrBitCast(clamping: distance.magnitude, as: Int.self)) + } } @inlinable public func bitshiftedLeftSmart(by distance: Int) -> Self { @@ -54,7 +58,7 @@ extension NBKFlexibleWidth { } @inlinable public mutating func bitshiftLeft(words: Int, bits: Int) { - fatalError("TODO") + self.magnitude.bitshiftLeft(words: words, bits: bits) } @inlinable public func bitshiftedLeft(words: Int, bits: Int) -> Self { @@ -62,7 +66,7 @@ extension NBKFlexibleWidth { } @inlinable public mutating func bitshiftLeft(words: Int) { - fatalError("TODO") + self.magnitude.bitshiftLeft(words: words) } @inlinable public func bitshiftedLeft(words: Int) -> Self { @@ -81,7 +85,7 @@ extension NBKFlexibleWidth { //=------------------------------------------------------------------------= @inlinable public static func >>=(lhs: inout Self, rhs: some BinaryInteger) { - fatalError("TODO") + lhs.bitshiftRightSmart(by: NBK.initOrBitCast(clamping: rhs, as: Int.self)) } @inlinable public static func >>(lhs: Self, rhs: some BinaryInteger) -> Self { @@ -93,7 +97,11 @@ extension NBKFlexibleWidth { //=------------------------------------------------------------------------= @inlinable public mutating func bitshiftRightSmart(by distance: Int) { - fatalError("TODO") + if distance >= 0 { + self.bitshiftRight(by: distance) + } else { + self.bitshiftLeft (by: NBK.initOrBitCast(clamping: distance.magnitude, as: Int.self)) + } } @inlinable public func bitshiftedRightSmart(by distance: Int) -> Self { @@ -112,7 +120,13 @@ extension NBKFlexibleWidth { } @inlinable public mutating func bitshiftRight(words: Int, bits: Int) { - fatalError("TODO") + let minus = self.isLessThanZero + //=--------------------------------------= + self.magnitude.bitshiftRight(words: words, bits: bits) + //=--------------------------------------= + if minus, self.isZero { + self.magnitude.assign(1 as UInt) + } } @inlinable public func bitshiftedRight(words: Int, bits: Int) -> Self { @@ -120,7 +134,13 @@ extension NBKFlexibleWidth { } @inlinable public mutating func bitshiftRight(words: Int) { - fatalError("TODO") + let minus = self.isLessThanZero + //=--------------------------------------= + self.magnitude.bitshiftRight(words: words) + //=--------------------------------------= + if minus, self.isZero { + self.magnitude.assign(1 as UInt) + } } @inlinable public func bitshiftedRight(words: Int) -> Self { @@ -128,7 +148,6 @@ extension NBKFlexibleWidth { } } - //*============================================================================* // MARK: * NBK x Flexible Width x Shifts x Unsigned //*============================================================================* diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Shifts.swift b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Shifts.swift index 2af58592..affe1757 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Shifts.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Shifts.swift @@ -17,6 +17,138 @@ private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] +//*============================================================================* +// MARK: * NBK x IntXL x Shifts +//*============================================================================* + +final class IntXLBenchmarksOnShifts: XCTestCase { + + typealias T = IntXL + + //=------------------------------------------------------------------------= + // MARK: Tests x Left + //=------------------------------------------------------------------------= + + func testBitshiftingLeft() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(UInt.bitWidth * 3/2) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs << rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testBitshiftingLeftByWords() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs.bitshiftedLeft(words: rhs.words)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testBitshiftingLeftByWordsAndBits() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs.bitshiftedLeft(words: rhs.words, bits: rhs.bits)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Right + //=------------------------------------------------------------------------= + + func testBitshiftingRight() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(UInt.bitWidth * 3/2) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs >> rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testBitshiftingRightByWords() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs.bitshiftedRight(words: rhs.words)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testBitshiftingRightByWordsAndBits() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs.bitshiftedRight(words: rhs.words, bits: rhs.bits)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x In Both Directions + //=------------------------------------------------------------------------= + + func testBitshiftingInBothDirectionsInout() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(UInt.bitWidth * 3/2) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs.bitshiftLeft (by: rhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + + NBK.blackHole(lhs.bitshiftRight(by: rhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testBitshiftingInBothDirectionsByWordsInout() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs.bitshiftLeft (words: rhs.words)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + + NBK.blackHole(lhs.bitshiftRight(words: rhs.words)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testBitshiftingInBothDirectionsByWordsAndBitsInout() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs.bitshiftLeft (words: rhs.words, bits: rhs.bits)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + + NBK.blackHole(lhs.bitshiftRight(words: rhs.words, bits: rhs.bits)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } +} + //*============================================================================* // MARK: * NBK x UIntXL x Shifts //*============================================================================* diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Shifts.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Shifts.swift index add20498..27d2a156 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Shifts.swift +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Shifts.swift @@ -17,6 +17,124 @@ private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] +//*============================================================================* +// MARK: * NBK x IntXL x Shifts +//*============================================================================* + +final class IntXLTestsOnShifts: XCTestCase { + + typealias T = IntXL + + //=------------------------------------------------------------------------= + // MARK: Tests x Left + //=------------------------------------------------------------------------= + + func testBitshiftingLeftByBits() { + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 0, T(x64:[ 1, 2, 3, 4] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 1, T(x64:[ 2, 4, 6, 8] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 2, T(x64:[ 4, 8, 12, 16] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 3, T(x64:[ 8, 16, 24, 32] as X)) + } + + func testBitshiftingLeftByWords() { + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 0, T(x64:[ 1, 2, 3, 4, 0, 0, 0, 0] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 64, T(x64:[ 0, 1, 2, 3, 4, 0, 0, 0] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 128, T(x64:[ 0, 0, 1, 2, 3, 4, 0, 0] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 192, T(x64:[ 0, 0, 0, 1, 2, 3, 4, 0] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 256, T(x64:[ 0, 0, 0, 0, 1, 2, 3, 4] as X)) + } + + func testBitshiftingLeftByWordsAndBits() { + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 3, T(x64:[ 8, 16, 24, 32, 0, 0, 0, 0] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 67, T(x64:[ 0, 8, 16, 24, 32, 0, 0, 0] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 131, T(x64:[ 0, 0, 8, 16, 24, 32, 0, 0] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 195, T(x64:[ 0, 0, 0, 8, 16, 24, 32, 0] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 259, T(x64:[ 0, 0, 0, 0, 8, 16, 24, 32] as X)) + } + + func testBitshiftingLeftSuchThatWordsSplit() { + NBKAssertShiftLeft(T(x64:[~0, 0, 0, 0] as X), 1, T(x64:[~1, 1, 0, 0, 0] as X)) + NBKAssertShiftLeft(T(x64:[ 0, ~0, 0, 0] as X), 1, T(x64:[ 0, ~1, 1, 0, 0] as X)) + NBKAssertShiftLeft(T(x64:[ 0, 0, ~0, 0] as X), 1, T(x64:[ 0, 0, ~1, 1, 0] as X)) + NBKAssertShiftLeft(T(x64:[ 0, 0, 0, ~0] as X), 1, T(x64:[ 0, 0, 0, ~1, ~0] as X)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Right + //=------------------------------------------------------------------------= + + func testBitshiftingRightByBits() { + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 0, T(x64:[ 8, 16, 24, 32] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 1, T(x64:[ 4, 8, 12, 16] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 2, T(x64:[ 2, 4, 6, 8] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 3, T(x64:[ 1, 2, 3, 4] as X)) + } + + func testBitshiftingRightByWords() { + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 0, T(x64:[ 8, 16, 24, 32] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 64, T(x64:[16, 24, 32, 0] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 128, T(x64:[24, 32, 0, 0] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 192, T(x64:[32, 0, 0, 0] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 256, T(x64:[ 0, 0, 0, 0] as X)) + } + + func testBitshiftingRightByWordsAndBits() { + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 3, T(x64:[ 1, 2, 3, 4] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 67, T(x64:[ 2, 3, 4, 0] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 131, T(x64:[ 3, 4, 0, 0] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 195, T(x64:[ 4, 0, 0, 0] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 259, T(x64:[ 0, 0, 0, 0] as X)) + } + + func testBitshiftingRightSuchThatWordsSplit() { + NBKAssertShiftRight(T(x64:[0, 0, 0, 7] as X), 1, T(x64:[ 0, 0, 1 << 63, 3] as X)) + NBKAssertShiftRight(T(x64:[0, 0, 7, 0] as X), 1, T(x64:[ 0, 1 << 63, 3, 0] as X)) + NBKAssertShiftRight(T(x64:[0, 7, 0, 0] as X), 1, T(x64:[ 1 << 63, 3, 0, 0] as X)) + NBKAssertShiftRight(T(x64:[7, 0, 0, 0] as X), 1, T(x64:[ 3, 0, 0, 0] as X)) + } + + func testBitshiftingRightIsSigned() { + NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X), 0, T(x64:[ 0, 0, 0, 1 << 63] as X)) + NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X), 64, T(x64:[ 0, 0, 1 << 63, ~0] as X)) + NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X), 128, T(x64:[ 0, 1 << 63, ~0, ~0] as X)) + NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X), 192, T(x64:[ 1 << 63, ~0, ~0, ~0] as X)) + NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X), 256, T(x64:[~0, ~0, ~0, ~0] as X)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Miscellaneous + //=------------------------------------------------------------------------= + + func testBitshiftingIsSmart() { + XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) << 1, T(x64:[2, 4, 6, 8, 0] as X)) + XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) >> -1, T(x64:[2, 4, 6, 8, 0] as X)) + + XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) << 64, T(x64:[0, 1, 2, 3, 4] as X)) + XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) >> -64, T(x64:[0, 1, 2, 3, 4] as X)) + } + + func testBitshiftingRightDoesNotTrap() { + XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) >> Int.max, T.zero) + XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) << Int.min, T.zero) + } + + func testBitshiftingZeroDoesNotTrap() { + XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) << Int.min, T.zero) + XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) << Int.max, T.zero) + + XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) >> Int.min, T.zero) + XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) >> Int.max, T.zero) + } + + func testBitshiftingZeroDoesNotDoAnything() { + XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) << (UInt.bitWidth + 0), T.zero) + XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) << (UInt.bitWidth + 1), T.zero) + + XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) >> (UInt.bitWidth + 0), T.zero) + XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) >> (UInt.bitWidth + 1), T.zero) + } +} + //*============================================================================* // MARK: * NBK x UIntXL x Shifts //*============================================================================* diff --git a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Shifts.swift b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Shifts.swift index 55dfcb43..3d62ed26 100644 --- a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Shifts.swift +++ b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Shifts.swift @@ -15,8 +15,8 @@ import XCTest // MARK: * NBK x Assert x Shifts //*============================================================================* -func NBKAssertShiftLeft( -_ lhs: UIntXL, _ rhs: Int, _ result: UIntXL, +func NBKAssertShiftLeft( +_ lhs: T, _ rhs: Int, _ result: T, file: StaticString = #file, line: UInt = #line) { //=------------------------------------------= let (words, bits) = rhs.quotientAndRemainder(dividingBy: UInt.bitWidth) @@ -47,8 +47,8 @@ file: StaticString = #file, line: UInt = #line) { } } -func NBKAssertShiftRight( -_ lhs: UIntXL, _ rhs: Int, _ result: UIntXL, +func NBKAssertShiftRight( +_ lhs: T, _ rhs: Int, _ result: T, file: StaticString = #file, line: UInt = #line) { //=------------------------------------------= let (words, bits) = rhs.quotientAndRemainder(dividingBy: UInt.bitWidth) From 5e327ff382b6a6fe883955a763d87adf1b845c66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Tue, 1 Aug 2023 15:00:56 +0200 Subject: [PATCH 035/133] NBKFlexibleWidthKit: Numbers. --- .../NBKFlexibleWidth+Numbers.swift | 11 +- .../IntXL+Numbers.swift | 456 ++++++++++++++++-- .../IntXL+Numbers.swift | 91 +++- 3 files changed, 508 insertions(+), 50 deletions(-) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift index a57a34a4..2ec5dc04 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift @@ -89,11 +89,16 @@ extension NBKFlexibleWidth { //=------------------------------------------------------------------------= @inlinable public init(_ source: some BinaryFloatingPoint) { - fatalError("TODO") + guard let result = Self(exactly: source.rounded(.towardZero)) else { + preconditionFailure("\(Self.description) cannot represent \(source)") + } + + self = result } @inlinable public init?(exactly source: some BinaryFloatingPoint) { - fatalError("TODO") + guard let magnitude = Magnitude(exactly: source.magnitude) else { return nil } + self.init(sign: source.sign, magnitude: magnitude) } //=------------------------------------------------------------------------= @@ -162,7 +167,7 @@ extension NBKFlexibleWidth.Magnitude { // MARK: Initializers x Binary Integer //=------------------------------------------------------------------------= - @inlinable public init(_ source: T) where T: BinaryInteger { + @inlinable public init(_ source: some BinaryInteger) { guard let result = Self(exactly: source) else { preconditionFailure("\(Self.description) cannot represent \(source)") } diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Numbers.swift b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Numbers.swift index f80987d3..90090857 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Numbers.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Numbers.swift @@ -17,6 +17,406 @@ private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] +//*============================================================================* +// MARK: * NBK x IntXL x Numbers +//*============================================================================* + +final class IntXLBenchmarksOnNumbers: XCTestCase { + + typealias T = IntXL + typealias M = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testZero() { + for _ in 0 ..< 100_000 { + NBK.blackHole(T()) + NBK.blackHole(T.zero) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Integers + //=------------------------------------------------------------------------= + + func testToInt() { + var abc = NBK.blackHoleIdentity(T(Int.max)) + + for _ in 0 ..< 50_000 { + NBK.blackHole(Int(abc)) + NBK.blackHole(Int(exactly: abc)) + NBK.blackHole(Int(clamping: abc)) + NBK.blackHole(Int(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromInt() { + var abc = NBK.blackHoleIdentity(Int.max) + + for _ in 0 ..< 100_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHole(T(clamping: abc)) + NBK.blackHole(T(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testToUInt() { + var abc = NBK.blackHoleIdentity(T(UInt.max)) + + for _ in 0 ..< 50_000 { + NBK.blackHole(UInt(abc)) + NBK.blackHole(UInt(exactly: abc)) + NBK.blackHole(UInt(clamping: abc)) + NBK.blackHole(UInt(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromUInt() { + var abc = NBK.blackHoleIdentity(UInt.max) + + for _ in 0 ..< 100_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHole(T(clamping: abc)) + NBK.blackHole(T(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testToInt8() { + var abc = NBK.blackHoleIdentity(T(Int8.max)) + + for _ in 0 ..< 50_000 { + NBK.blackHole(Int8(abc)) + NBK.blackHole(Int8(exactly: abc)) + NBK.blackHole(Int8(clamping: abc)) + NBK.blackHole(Int8(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromInt8() { + var abc = NBK.blackHoleIdentity(Int8.max) + + for _ in 0 ..< 100_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHole(T(clamping: abc)) + NBK.blackHole(T(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testToUInt8() { + var abc = NBK.blackHoleIdentity(T(UInt8.max)) + + for _ in 0 ..< 50_000 { + NBK.blackHole(UInt8(abc)) + NBK.blackHole(UInt8(exactly: abc)) + NBK.blackHole(UInt8(clamping: abc)) + NBK.blackHole(UInt8(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromUInt8() { + var abc = NBK.blackHoleIdentity(UInt8.max) + + for _ in 0 ..< 100_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHole(T(clamping: abc)) + NBK.blackHole(T(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testToInt16() { + var abc = NBK.blackHoleIdentity(T(Int16.max)) + + for _ in 0 ..< 50_000 { + NBK.blackHole(Int16(abc)) + NBK.blackHole(Int16(exactly: abc)) + NBK.blackHole(Int16(clamping: abc)) + NBK.blackHole(Int16(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromInt16() { + var abc = NBK.blackHoleIdentity(Int16.max) + + for _ in 0 ..< 100_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHole(T(clamping: abc)) + NBK.blackHole(T(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testToUInt16() { + var abc = NBK.blackHoleIdentity(T(UInt16.max)) + + for _ in 0 ..< 50_000 { + NBK.blackHole(UInt16(abc)) + NBK.blackHole(UInt16(exactly: abc)) + NBK.blackHole(UInt16(clamping: abc)) + NBK.blackHole(UInt16(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromUInt16() { + var abc = NBK.blackHoleIdentity(UInt16.max) + + for _ in 0 ..< 100_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHole(T(clamping: abc)) + NBK.blackHole(T(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testToInt32() { + var abc = NBK.blackHoleIdentity(T(Int32.max)) + + for _ in 0 ..< 50_000 { + NBK.blackHole(Int32(abc)) + NBK.blackHole(Int32(exactly: abc)) + NBK.blackHole(Int32(clamping: abc)) + NBK.blackHole(Int32(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromInt32() { + var abc = NBK.blackHoleIdentity(Int32.max) + + for _ in 0 ..< 100_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHole(T(clamping: abc)) + NBK.blackHole(T(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testToUInt32() { + var abc = NBK.blackHoleIdentity(T(UInt32.max)) + + for _ in 0 ..< 50_000 { + NBK.blackHole(UInt32(abc)) + NBK.blackHole(UInt32(exactly: abc)) + NBK.blackHole(UInt32(clamping: abc)) + NBK.blackHole(UInt32(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromUInt32() { + var abc = NBK.blackHoleIdentity(UInt32.max) + + for _ in 0 ..< 100_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHole(T(clamping: abc)) + NBK.blackHole(T(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testToInt64() { + var abc = NBK.blackHoleIdentity(T(Int64.max)) + + for _ in 0 ..< 50_000 { + NBK.blackHole(Int64(abc)) + NBK.blackHole(Int64(exactly: abc)) + NBK.blackHole(Int64(clamping: abc)) + NBK.blackHole(Int64(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromInt64() { + var abc = NBK.blackHoleIdentity(Int64.max) + + for _ in 0 ..< 100_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHole(T(clamping: abc)) + NBK.blackHole(T(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testToUInt64() { + var abc = NBK.blackHoleIdentity(T(UInt64.max)) + + for _ in 0 ..< 50_000 { + NBK.blackHole(UInt64(abc)) + NBK.blackHole(UInt64(exactly: abc)) + NBK.blackHole(UInt64(clamping: abc)) + NBK.blackHole(UInt64(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromUInt64() { + var abc = NBK.blackHoleIdentity(UInt64.max) + + for _ in 0 ..< 100_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHole(T(clamping: abc)) + NBK.blackHole(T(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Complements + //=------------------------------------------------------------------------= + + func testToDigit() { + var abc = NBK.blackHoleIdentity(T(T.Digit.max)) + + for _ in 0 ..< 50_000 { + NBK.blackHole(T.Digit(abc)) + NBK.blackHole(T.Digit(exactly: abc)) + NBK.blackHole(T.Digit(clamping: abc)) + NBK.blackHole(T.Digit(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromDigit() { + var abc = NBK.blackHoleIdentity(T.Digit.max) + + for _ in 0 ..< 100_000 { + NBK.blackHole(T(digit: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testToMagnitude() { + var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + + for _ in 0 ..< 50_000 { + NBK.blackHole(M(abc)) + NBK.blackHole(M(exactly: abc)) + NBK.blackHole(M(clamping: abc)) + NBK.blackHole(M(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromMagnitude() { + var abc = NBK.blackHoleIdentity(M(x64:[0, 1, 2, 3] as X)) + + for _ in 0 ..< 100_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHole(T(clamping: abc)) + NBK.blackHole(T(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Float + //=------------------------------------------------------------------------= + + // TODO: brrr + func testToFloat16() { + var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + + for _ in 0 ..< 1_000 { + NBK.blackHole(Float16(abc)) + NBK.blackHole(Float16(exactly: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromFloat16() { + var abc = NBK.blackHoleIdentity(Float16(123)) + + for _ in 0 ..< 100_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + // TODO: brrr + func testToFloat32() { + var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + + for _ in 0 ..< 1_000 { + NBK.blackHole(Float32(abc)) + NBK.blackHole(Float32(exactly: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromFloat32() { + var abc = NBK.blackHoleIdentity(Float32(123)) + + for _ in 0 ..< 100_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + // TODO: brrr + func testToFloat64() { + var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + + for _ in 0 ..< 1_000 { + NBK.blackHole(Float64(abc)) + NBK.blackHole(Float64(exactly: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromFloat64() { + var abc = NBK.blackHoleIdentity(Float64(123)) + + for _ in 0 ..< 100_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Sign & Magnitude + //=------------------------------------------------------------------------= + + func testSignAndMagnitude() { + var abc = NBK.blackHoleIdentity((sign: FloatingPointSign.plus, magnitude: M(x64:[0, 1, 2, 3] as X))) + var xyz = NBK.blackHoleIdentity((sign: FloatingPointSign.minus, magnitude: M(x64:[0, 1, 2, 3] as X))) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(T.exactly (sign: abc.sign, magnitude: abc.magnitude)) + NBK.blackHole(T.clamping(sign: abc.sign, magnitude: abc.magnitude)) + NBK.blackHoleInoutIdentity(&abc) + + NBK.blackHole(T.exactly (sign: xyz.sign, magnitude: xyz.magnitude)) + NBK.blackHole(T.clamping(sign: xyz.sign, magnitude: xyz.magnitude)) + NBK.blackHoleInoutIdentity(&xyz) + } + } +} + //*============================================================================* // MARK: * NBK x UIntXL x Numbers //*============================================================================* @@ -31,7 +431,7 @@ final class UIntXLBenchmarksOnNumbers: XCTestCase { //=------------------------------------------------------------------------= func testZero() { - for _ in 0 ..< 250_000 { + for _ in 0 ..< 100_000 { NBK.blackHole(T()) NBK.blackHole(T.zero) } @@ -44,7 +444,7 @@ final class UIntXLBenchmarksOnNumbers: XCTestCase { func testToInt() { var abc = NBK.blackHoleIdentity(T(Int.max)) - for _ in 0 ..< 250_000 { + for _ in 0 ..< 50_000 { NBK.blackHole(Int(abc)) NBK.blackHole(Int(exactly: abc)) NBK.blackHole(Int(clamping: abc)) @@ -56,7 +456,7 @@ final class UIntXLBenchmarksOnNumbers: XCTestCase { func testFromInt() { var abc = NBK.blackHoleIdentity(Int.max) - for _ in 0 ..< 250_000 { + for _ in 0 ..< 100_000 { NBK.blackHole(T(abc)) NBK.blackHole(T(exactly: abc)) NBK.blackHole(T(clamping: abc)) @@ -68,7 +468,7 @@ final class UIntXLBenchmarksOnNumbers: XCTestCase { func testToUInt() { var abc = NBK.blackHoleIdentity(T(UInt.max)) - for _ in 0 ..< 250_000 { + for _ in 0 ..< 50_000 { NBK.blackHole(UInt(abc)) NBK.blackHole(UInt(exactly: abc)) NBK.blackHole(UInt(clamping: abc)) @@ -80,7 +480,7 @@ final class UIntXLBenchmarksOnNumbers: XCTestCase { func testFromUInt() { var abc = NBK.blackHoleIdentity(UInt.max) - for _ in 0 ..< 250_000 { + for _ in 0 ..< 100_000 { NBK.blackHole(T(abc)) NBK.blackHole(T(exactly: abc)) NBK.blackHole(T(clamping: abc)) @@ -92,7 +492,7 @@ final class UIntXLBenchmarksOnNumbers: XCTestCase { func testToInt8() { var abc = NBK.blackHoleIdentity(T(Int8.max)) - for _ in 0 ..< 250_000 { + for _ in 0 ..< 50_000 { NBK.blackHole(Int8(abc)) NBK.blackHole(Int8(exactly: abc)) NBK.blackHole(Int8(clamping: abc)) @@ -104,7 +504,7 @@ final class UIntXLBenchmarksOnNumbers: XCTestCase { func testFromInt8() { var abc = NBK.blackHoleIdentity(Int8.max) - for _ in 0 ..< 250_000 { + for _ in 0 ..< 100_000 { NBK.blackHole(T(abc)) NBK.blackHole(T(exactly: abc)) NBK.blackHole(T(clamping: abc)) @@ -116,7 +516,7 @@ final class UIntXLBenchmarksOnNumbers: XCTestCase { func testToUInt8() { var abc = NBK.blackHoleIdentity(T(UInt8.max)) - for _ in 0 ..< 250_000 { + for _ in 0 ..< 50_000 { NBK.blackHole(UInt8(abc)) NBK.blackHole(UInt8(exactly: abc)) NBK.blackHole(UInt8(clamping: abc)) @@ -128,7 +528,7 @@ final class UIntXLBenchmarksOnNumbers: XCTestCase { func testFromUInt8() { var abc = NBK.blackHoleIdentity(UInt8.max) - for _ in 0 ..< 250_000 { + for _ in 0 ..< 100_000 { NBK.blackHole(T(abc)) NBK.blackHole(T(exactly: abc)) NBK.blackHole(T(clamping: abc)) @@ -140,7 +540,7 @@ final class UIntXLBenchmarksOnNumbers: XCTestCase { func testToInt16() { var abc = NBK.blackHoleIdentity(T(Int16.max)) - for _ in 0 ..< 250_000 { + for _ in 0 ..< 50_000 { NBK.blackHole(Int16(abc)) NBK.blackHole(Int16(exactly: abc)) NBK.blackHole(Int16(clamping: abc)) @@ -152,7 +552,7 @@ final class UIntXLBenchmarksOnNumbers: XCTestCase { func testFromInt16() { var abc = NBK.blackHoleIdentity(Int16.max) - for _ in 0 ..< 250_000 { + for _ in 0 ..< 100_000 { NBK.blackHole(T(abc)) NBK.blackHole(T(exactly: abc)) NBK.blackHole(T(clamping: abc)) @@ -164,7 +564,7 @@ final class UIntXLBenchmarksOnNumbers: XCTestCase { func testToUInt16() { var abc = NBK.blackHoleIdentity(T(UInt16.max)) - for _ in 0 ..< 250_000 { + for _ in 0 ..< 50_000 { NBK.blackHole(UInt16(abc)) NBK.blackHole(UInt16(exactly: abc)) NBK.blackHole(UInt16(clamping: abc)) @@ -176,7 +576,7 @@ final class UIntXLBenchmarksOnNumbers: XCTestCase { func testFromUInt16() { var abc = NBK.blackHoleIdentity(UInt16.max) - for _ in 0 ..< 250_000 { + for _ in 0 ..< 100_000 { NBK.blackHole(T(abc)) NBK.blackHole(T(exactly: abc)) NBK.blackHole(T(clamping: abc)) @@ -188,7 +588,7 @@ final class UIntXLBenchmarksOnNumbers: XCTestCase { func testToInt32() { var abc = NBK.blackHoleIdentity(T(Int32.max)) - for _ in 0 ..< 250_000 { + for _ in 0 ..< 50_000 { NBK.blackHole(Int32(abc)) NBK.blackHole(Int32(exactly: abc)) NBK.blackHole(Int32(clamping: abc)) @@ -200,7 +600,7 @@ final class UIntXLBenchmarksOnNumbers: XCTestCase { func testFromInt32() { var abc = NBK.blackHoleIdentity(Int32.max) - for _ in 0 ..< 250_000 { + for _ in 0 ..< 100_000 { NBK.blackHole(T(abc)) NBK.blackHole(T(exactly: abc)) NBK.blackHole(T(clamping: abc)) @@ -212,7 +612,7 @@ final class UIntXLBenchmarksOnNumbers: XCTestCase { func testToUInt32() { var abc = NBK.blackHoleIdentity(T(UInt32.max)) - for _ in 0 ..< 250_000 { + for _ in 0 ..< 50_000 { NBK.blackHole(UInt32(abc)) NBK.blackHole(UInt32(exactly: abc)) NBK.blackHole(UInt32(clamping: abc)) @@ -224,7 +624,7 @@ final class UIntXLBenchmarksOnNumbers: XCTestCase { func testFromUInt32() { var abc = NBK.blackHoleIdentity(UInt32.max) - for _ in 0 ..< 250_000 { + for _ in 0 ..< 100_000 { NBK.blackHole(T(abc)) NBK.blackHole(T(exactly: abc)) NBK.blackHole(T(clamping: abc)) @@ -236,7 +636,7 @@ final class UIntXLBenchmarksOnNumbers: XCTestCase { func testToInt64() { var abc = NBK.blackHoleIdentity(T(Int64.max)) - for _ in 0 ..< 250_000 { + for _ in 0 ..< 50_000 { NBK.blackHole(Int64(abc)) NBK.blackHole(Int64(exactly: abc)) NBK.blackHole(Int64(clamping: abc)) @@ -248,7 +648,7 @@ final class UIntXLBenchmarksOnNumbers: XCTestCase { func testFromInt64() { var abc = NBK.blackHoleIdentity(Int64.max) - for _ in 0 ..< 250_000 { + for _ in 0 ..< 100_000 { NBK.blackHole(T(abc)) NBK.blackHole(T(exactly: abc)) NBK.blackHole(T(clamping: abc)) @@ -260,7 +660,7 @@ final class UIntXLBenchmarksOnNumbers: XCTestCase { func testToUInt64() { var abc = NBK.blackHoleIdentity(T(UInt64.max)) - for _ in 0 ..< 250_000 { + for _ in 0 ..< 50_000 { NBK.blackHole(UInt64(abc)) NBK.blackHole(UInt64(exactly: abc)) NBK.blackHole(UInt64(clamping: abc)) @@ -272,7 +672,7 @@ final class UIntXLBenchmarksOnNumbers: XCTestCase { func testFromUInt64() { var abc = NBK.blackHoleIdentity(UInt64.max) - for _ in 0 ..< 250_000 { + for _ in 0 ..< 100_000 { NBK.blackHole(T(abc)) NBK.blackHole(T(exactly: abc)) NBK.blackHole(T(clamping: abc)) @@ -288,7 +688,7 @@ final class UIntXLBenchmarksOnNumbers: XCTestCase { func testToDigit() { var abc = NBK.blackHoleIdentity(T(T.Digit.max)) - for _ in 0 ..< 250_000 { + for _ in 0 ..< 50_000 { NBK.blackHole(T.Digit(abc)) NBK.blackHole(T.Digit(exactly: abc)) NBK.blackHole(T.Digit(clamping: abc)) @@ -300,7 +700,7 @@ final class UIntXLBenchmarksOnNumbers: XCTestCase { func testFromDigit() { var abc = NBK.blackHoleIdentity(T.Digit.max) - for _ in 0 ..< 250_000 { + for _ in 0 ..< 100_000 { NBK.blackHole(T(digit: abc)) NBK.blackHoleInoutIdentity(&abc) } @@ -309,7 +709,7 @@ final class UIntXLBenchmarksOnNumbers: XCTestCase { func testToMagnitude() { var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - for _ in 0 ..< 250_000 { + for _ in 0 ..< 50_000 { NBK.blackHole(M(abc)) NBK.blackHole(M(exactly: abc)) NBK.blackHole(M(clamping: abc)) @@ -321,7 +721,7 @@ final class UIntXLBenchmarksOnNumbers: XCTestCase { func testFromMagnitude() { var abc = NBK.blackHoleIdentity(M(x64:[0, 1, 2, 3] as X)) - for _ in 0 ..< 250_000 { + for _ in 0 ..< 100_000 { NBK.blackHole(T(abc)) NBK.blackHole(T(exactly: abc)) NBK.blackHole(T(clamping: abc)) @@ -348,7 +748,7 @@ final class UIntXLBenchmarksOnNumbers: XCTestCase { func testFromFloat16() { var abc = NBK.blackHoleIdentity(Float16(123)) - for _ in 0 ..< 250_000 { + for _ in 0 ..< 100_000 { NBK.blackHole(T(abc)) NBK.blackHole(T(exactly: abc)) NBK.blackHoleInoutIdentity(&abc) @@ -369,7 +769,7 @@ final class UIntXLBenchmarksOnNumbers: XCTestCase { func testFromFloat32() { var abc = NBK.blackHoleIdentity(Float32(123)) - for _ in 0 ..< 250_000 { + for _ in 0 ..< 100_000 { NBK.blackHole(T(abc)) NBK.blackHole(T(exactly: abc)) NBK.blackHoleInoutIdentity(&abc) @@ -390,7 +790,7 @@ final class UIntXLBenchmarksOnNumbers: XCTestCase { func testFromFloat64() { var abc = NBK.blackHoleIdentity(Float64(123)) - for _ in 0 ..< 250_000 { + for _ in 0 ..< 100_000 { NBK.blackHole(T(abc)) NBK.blackHole(T(exactly: abc)) NBK.blackHoleInoutIdentity(&abc) diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Numbers.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Numbers.swift index ccc85674..525b9d62 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Numbers.swift +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Numbers.swift @@ -190,15 +190,39 @@ final class IntXLTestsOnNumbers: XCTestCase { //=------------------------------------------------------------------------= func testToFloat32() { - // TODO: (!) + XCTAssertEqual(Float32(T(-1)), Float32(-1)) + XCTAssertEqual(Float32(T( 0)), Float32( 0)) + XCTAssertEqual(Float32(T( 1)), Float32( 1)) + + XCTAssertEqual(Float32(T( Int32.min)), Float32( Int32.min)) + XCTAssertEqual(Float32(T( Int32.max)), Float32( Int32.max)) + + XCTAssertEqual(Float32(T(UInt32.min)), Float32(UInt32.min)) + XCTAssertEqual(Float32(T(UInt32.max)), Float32(UInt32.max)) } func testFromFloat32() { - // TODO: (!) + XCTAssertEqual(T(Float32( 22.0)), 22) + XCTAssertEqual(T(Float32( -22.0)), -22) + XCTAssertEqual(T(Float32( 22.5)), 22) + XCTAssertEqual(T(Float32( -22.5)), -22) + + XCTAssertEqual(T(exactly: 22.5), nil) + XCTAssertEqual(T(exactly: -22.5), nil) + + XCTAssertEqual(T(exactly: pow(2, Float32(64 * 0 - 1))), nil) + XCTAssertEqual(T(exactly: pow(2, Float32(64 * 0 - 0))), T(x64:[1, 0, 0, 0] as X)) + XCTAssertEqual(T(exactly: pow(2, Float32(64 * 1 - 1))), T(x64:[1 << 63, 0, 0, 0] as X)) + XCTAssertEqual(T(exactly: pow(2, Float32(64 * 2 - 1))), T(x64:[0, 1 << 63, 0, 0] as X)) + XCTAssertEqual(T(exactly: pow(2, Float32(64 * 2 - 0))), nil) } func testFromFloat32ValuesThatAreSpecial() { - // TODO: (!) + XCTAssertNil(T(exactly: Float32.nan)) + XCTAssertNil(T(exactly: Float32.infinity)) + XCTAssertNil(T(exactly: Float32.signalingNaN)) + XCTAssertNil(T(exactly: Float32.leastNormalMagnitude)) + XCTAssertNil(T(exactly: Float32.leastNonzeroMagnitude)) } //=------------------------------------------------------------------------= @@ -206,15 +230,41 @@ final class IntXLTestsOnNumbers: XCTestCase { //=------------------------------------------------------------------------= func testToFloat64() { - // TODO: (!) + XCTAssertEqual(Float64(T(-1)), Float64(-1)) + XCTAssertEqual(Float64(T( 0)), Float64( 0)) + XCTAssertEqual(Float64(T( 1)), Float64( 1)) + + XCTAssertEqual(Float64(T( Int64.min)), Float64( Int64.min)) + XCTAssertEqual(Float64(T( Int64.max)), Float64( Int64.max)) + + XCTAssertEqual(Float64(T(UInt64.min)), Float64(UInt64.min)) + XCTAssertEqual(Float64(T(UInt64.max)), Float64(UInt64.max)) } func testFromFloat64() { - // TODO: (!) + XCTAssertEqual(T(Float64( 22.0)), 22) + XCTAssertEqual(T(Float64( -22.0)), -22) + XCTAssertEqual(T(Float64( 22.5)), 22) + XCTAssertEqual(T(Float64( -22.5)), -22) + + XCTAssertEqual(T(exactly: 22.5), nil) + XCTAssertEqual(T(exactly: -22.5), nil) + + XCTAssertEqual(T(exactly: pow(2, Float64(64 * 0 - 1))), nil) + XCTAssertEqual(T(exactly: pow(2, Float64(64 * 0 - 0))), T(x64:[1, 0, 0, 0] as X)) + XCTAssertEqual(T(exactly: pow(2, Float64(64 * 1 - 1))), T(x64:[1 << 63, 0, 0, 0] as X)) + XCTAssertEqual(T(exactly: pow(2, Float64(64 * 2 - 1))), T(x64:[0, 1 << 63, 0, 0] as X)) + XCTAssertEqual(T(exactly: pow(2, Float64(64 * 3 - 1))), T(x64:[0, 0, 1 << 63, 0] as X)) + XCTAssertEqual(T(exactly: pow(2, Float64(64 * 4 - 2))), T(x64:[0, 0, 0, 1 << 62] as X)) + XCTAssertEqual(T(exactly: pow(2, Float64(64 * 4 - 1))), -T(x64:[0, 0, 0, 1 << 63] as X)) } func testFromFloat64ValuesThatAreSpecial() { - // TODO: (!) + XCTAssertNil(T(exactly: Float64.nan)) + XCTAssertNil(T(exactly: Float64.infinity)) + XCTAssertNil(T(exactly: Float64.signalingNaN)) + XCTAssertNil(T(exactly: Float64.leastNormalMagnitude)) + XCTAssertNil(T(exactly: Float64.leastNonzeroMagnitude)) } //=------------------------------------------------------------------------= @@ -242,14 +292,14 @@ final class IntXLTestsOnNumbers: XCTestCase { //=------------------------------------------------------------------------= func testFromLiteral() { - XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W), 0) - XCTAssertEqual(T(words:[~0, 0, 0, 0] as W), 18446744073709551615) - XCTAssertEqual(T(words:[~0, ~0, 0, 0] as W), 340282366920938463463374607431768211455) - XCTAssertEqual(T(words:[~0, ~0, ~0, 0] as W), 6277101735386680763835789423207666416102355444464034512895) - XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W), -1) - XCTAssertEqual(T(words:[ 1, ~0, ~0, ~0] as W), -18446744073709551615) - XCTAssertEqual(T(words:[ 1, 0, ~0, ~0] as W), -340282366920938463463374607431768211455) - XCTAssertEqual(T(words:[ 1, 0, 0, ~0] as W), -6277101735386680763835789423207666416102355444464034512895) + XCTAssertEqual(T(x64:[ 0, 0, 0, 0] as X), 0x0000000000000000000000000000000000000000000000000000000000000000) + XCTAssertEqual(T(x64:[~0, 0, 0, 0] as X), 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + XCTAssertEqual(T(x64:[~0, ~0, 0, 0] as X), 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + XCTAssertEqual(T(x64:[~0, ~0, ~0, 0] as X), 0x0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff) + XCTAssertEqual(T(x64:[~0, ~0, ~0, ~0] as X), -0x0000000000000000000000000000000000000000000000000000000000000001) + XCTAssertEqual(T(x64:[ 0, ~0, ~0, ~0] as X), -0x0000000000000000000000000000000000000000000000010000000000000000) + XCTAssertEqual(T(x64:[ 0, 0, ~0, ~0] as X), -0x0000000000000000000000000000000100000000000000000000000000000000) + XCTAssertEqual(T(x64:[ 0, 0, 0, ~0] as X), -0x0000000000000001000000000000000000000000000000000000000000000000) } } @@ -510,11 +560,14 @@ final class UIntXLTestsOnNumbers: XCTestCase { //=------------------------------------------------------------------------= func testFromLiteral() { - XCTAssertEqual(T(x64:[ 0, 0, 0, 0] as X), 0) - XCTAssertEqual(T(x64:[~0, 0, 0, 0] as X), 18446744073709551615) - XCTAssertEqual(T(x64:[~0, ~0, 0, 0] as X), 340282366920938463463374607431768211455) - XCTAssertEqual(T(x64:[~0, ~0, ~0, 0] as X), 6277101735386680763835789423207666416102355444464034512895) - XCTAssertEqual(T(x64:[~0, ~0, ~0, ~0] as X), 115792089237316195423570985008687907853269984665640564039457584007913129639935) + XCTAssertEqual(T(x64:[ 0, 0, 0, 0] as X), 0x0000000000000000000000000000000000000000000000000000000000000000) + XCTAssertEqual(T(x64:[~0, 0, 0, 0] as X), 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + XCTAssertEqual(T(x64:[~0, ~0, 0, 0] as X), 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + XCTAssertEqual(T(x64:[~0, ~0, ~0, 0] as X), 0x0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff) + XCTAssertEqual(T(x64:[~0, ~0, ~0, ~0] as X), 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + XCTAssertEqual(T(x64:[ 0, ~0, ~0, ~0] as X), 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + XCTAssertEqual(T(x64:[ 0, 0, ~0, ~0] as X), 0xffffffffffffffffffffffffffffffff00000000000000000000000000000000) + XCTAssertEqual(T(x64:[ 0, 0, 0, ~0] as X), 0xffffffffffffffff000000000000000000000000000000000000000000000000) XCTAssertNil(T(exactlyIntegerLiteral: -1)) } From a2c5626afc979d126c08f25bb59919fe85f6928c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Thu, 3 Aug 2023 10:54:52 +0200 Subject: [PATCH 036/133] NBKFlexibleWidth: Bits. --- .../NBKFlexibleWidth+Bits.swift | 19 +++++-------- .../NBKFlexibleWidth+Words.swift | 10 +++---- .../NBKFlexibleWidthKit/Private/Bits.swift | 27 +++++++++++++++++++ 3 files changed, 38 insertions(+), 18 deletions(-) create mode 100644 Sources/NBKFlexibleWidthKit/Private/Bits.swift diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift index 82035f4a..336f232e 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift @@ -29,22 +29,17 @@ extension NBKFlexibleWidth { /// The number of bits in ``words``. @inlinable public var bitWidth: Int { - self.magnitude.bitWidth + self.extraBitWidthInBitWidth + self.magnitude.bitWidth + self.extraBitWidth } @inlinable public var nonzeroBitCount: Int { - if !self.isLessThanZero { - return self.magnitude.nonzeroBitCount - } - - var nonzeroBitCount = self.bitWidth - nonzeroBitCount &-= self.magnitude.nonzeroBitCount - nonzeroBitCount &-= self.magnitude.trailingZeroBitCount - return nonzeroBitCount &+ 1 as Int + switch self.isLessThanZero { + case true: return NBK.nonzeroBitCount(twosComplementOf: self.magnitude.storage.elements) + self.extraBitWidth + case false: return self.magnitude.nonzeroBitCount } } @inlinable public var leadingZeroBitCount: Int { - self.isLessThanZero ? Int.zero : self.magnitude.leadingZeroBitCount + self.extraBitWidthInBitWidth + self.isLessThanZero ? Int.zero : self.magnitude.leadingZeroBitCount + self.extraBitWidth } @inlinable public var trailingZeroBitCount: Int { @@ -64,8 +59,8 @@ extension NBKFlexibleWidth { //=------------------------------------------------------------------------= /// The number of extra bits in `bitWidth` compared to `magnitude/bitWidth`. - @inlinable var extraBitWidthInBitWidth: Int { - self.wordsNeedsOneMoreWord ? UInt.bitWidth : Int.zero + @inlinable var extraBitWidth: Int { + self.storageNeedsOneMoreWord ? UInt.bitWidth : Int.zero } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift index b2b68a33..966296e6 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift @@ -25,9 +25,7 @@ extension NBKFlexibleWidth { /// @inlinable public init(words: some RandomAccessCollection) { //=--------------------------------------= - // default to zero by nil coalescing - //=--------------------------------------= - let last = words.last ?? UInt() + let last = words.last ?? UInt.zero //=--------------------------------------= self.init(sign: Sign.plus, magnitude: Magnitude(words: words)) //=--------------------------------------= @@ -49,8 +47,8 @@ extension NBKFlexibleWidth { // MARK: Utilities x Private //=------------------------------------------------------------------------= - @inlinable var wordsNeedsOneMoreWord: Bool { - guard !self.magnitude.isZero else { return true } + @inlinable var storageNeedsOneMoreWord: Bool { + guard !self.magnitude.storage.elements.isEmpty else { return true } let index = self.magnitude.storage.elements.count - 1 let comparison = self.magnitude.compared(to: UInt(bitPattern: Int.min), at: index) return comparison >= Int(bit: self.sign.bit) @@ -75,7 +73,7 @@ extension NBKFlexibleWidth { //=--------------------------------------------------------------------= @inlinable init(source: NBKFlexibleWidth) { - self.count = Int(bit: source.wordsNeedsOneMoreWord) + self.count = Int(bit: source.storageNeedsOneMoreWord) self.sign = UInt(repeating: source.isLessThanZero) self.storage = source.magnitude.storage //=----------------------------------= diff --git a/Sources/NBKFlexibleWidthKit/Private/Bits.swift b/Sources/NBKFlexibleWidthKit/Private/Bits.swift new file mode 100644 index 00000000..9cb45842 --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/Private/Bits.swift @@ -0,0 +1,27 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Bits +//*============================================================================* + +extension NBK { + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + /// Returns the nonzero bit count for the two's complement of `limbs`. + @inlinable static func nonzeroBitCount(twosComplementOf limbs: some Collection) -> Int { + guard let index = limbs.firstIndex(where:{ !$0.isZero }) else { return Int() } + return limbs.indices[index...].reduce(1 - limbs[index].trailingZeroBitCount) { $0 + limbs[$1].onesComplement().nonzeroBitCount } + } +} From f8d6bc7a2b4c81735aafae6ec6ded0b90e0eb825 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Thu, 3 Aug 2023 14:08:27 +0200 Subject: [PATCH 037/133] NBKFlexibleWidthKit: Bits, Cleanup. --- .../NBKFlexibleWidth+Bits.swift | 10 ++--- .../NBKFlexibleWidth+Comparisons.swift | 16 ++++---- .../NBKFlexibleWidth+Words.swift | 10 +++-- .../NBKFlexibleWidthKit/Private/Bits.swift | 27 +++++++++++++ .../NBKFlexibleWidthKitTests/IntXL+Bits.swift | 12 +++--- .../IntXL+Comparisons.swift | 40 ++++++++++++------- 6 files changed, 78 insertions(+), 37 deletions(-) create mode 100644 Sources/NBKFlexibleWidthKit/Private/Bits.swift diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift index 336f232e..f10eed1f 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift @@ -29,17 +29,17 @@ extension NBKFlexibleWidth { /// The number of bits in ``words``. @inlinable public var bitWidth: Int { - self.magnitude.bitWidth + self.extraBitWidth + self.magnitude.bitWidth + self.storageBitWidthNeeded } @inlinable public var nonzeroBitCount: Int { switch self.isLessThanZero { - case true: return NBK.nonzeroBitCount(twosComplementOf: self.magnitude.storage.elements) + self.extraBitWidth - case false: return self.magnitude.nonzeroBitCount } + case false: return self.magnitude.nonzeroBitCount + case true: return NBK.nonzeroBitCount(twosComplementOf: self.magnitude.storage.elements) + self.storageBitWidthNeeded } } @inlinable public var leadingZeroBitCount: Int { - self.isLessThanZero ? Int.zero : self.magnitude.leadingZeroBitCount + self.extraBitWidth + self.isLessThanZero ? Int.zero : (self.magnitude.leadingZeroBitCount + self.storageBitWidthNeeded) } @inlinable public var trailingZeroBitCount: Int { @@ -59,7 +59,7 @@ extension NBKFlexibleWidth { //=------------------------------------------------------------------------= /// The number of extra bits in `bitWidth` compared to `magnitude/bitWidth`. - @inlinable var extraBitWidth: Int { + @inlinable var storageBitWidthNeeded: Int { self.storageNeedsOneMoreWord ? UInt.bitWidth : Int.zero } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift index 2cd4b30d..8766f953 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift @@ -31,14 +31,14 @@ extension NBKFlexibleWidth { self.sign == Sign.plus && !self.isZero } - @inlinable public func signum() -> Int { - self.isZero ? 0 : self.sign == Sign.plus ? 1 : -1 - } - @inlinable public var isPowerOf2: Bool { self.sign == Sign.plus && self.magnitude.isPowerOf2 } + @inlinable public func signum() -> Int { + self.isZero ? 0 : self.sign == Sign.plus ? 1 : -1 + } + //=------------------------------------------------------------------------= // MARK: Utilities //=------------------------------------------------------------------------= @@ -121,14 +121,14 @@ extension NBKFlexibleWidth.Magnitude { !self.isZero } - @inlinable public func signum() -> Int { - Int(bit: !self.isZero) - } - @inlinable public var isPowerOf2: Bool { NBK.nonzeroBitCount(of: self.storage.elements, equals: 1) } + @inlinable public func signum() -> Int { + Int(bit: !self.isZero) + } + //=------------------------------------------------------------------------= // MARK: Utilities //=------------------------------------------------------------------------= diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift index 966296e6..a1e400d9 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift @@ -48,10 +48,12 @@ extension NBKFlexibleWidth { //=------------------------------------------------------------------------= @inlinable var storageNeedsOneMoreWord: Bool { - guard !self.magnitude.storage.elements.isEmpty else { return true } - let index = self.magnitude.storage.elements.count - 1 - let comparison = self.magnitude.compared(to: UInt(bitPattern: Int.min), at: index) - return comparison >= Int(bit: self.sign.bit) + //=--------------------------------------= + if self.magnitude.storage.elements.isEmpty { return true } + //=--------------------------------------= + switch self.sign { + case .plus : return self.magnitude.storage.elements.last!.mostSignificantBit + case .minus: return !NBK.mostSignificantBit(twosComplementOf: self.magnitude.storage.elements) } } //*========================================================================* diff --git a/Sources/NBKFlexibleWidthKit/Private/Bits.swift b/Sources/NBKFlexibleWidthKit/Private/Bits.swift new file mode 100644 index 00000000..86917892 --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/Private/Bits.swift @@ -0,0 +1,27 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Bits +//*============================================================================* + +extension NBK { + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + /// Returns the most significant bit for the two's complement of `limbs`. + @inlinable public static func mostSignificantBit(twosComplementOf limbs: some BidirectionalCollection) -> Bool { + guard let index = limbs.firstIndex(where:{ !$0.isZero }) else { return false } + return limbs.last!.twosComplementSubsequence(limbs.index(after: index) == limbs.endIndex).partialValue.mostSignificantBit + } +} diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Bits.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Bits.swift index eaebd520..d7ee82de 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Bits.swift +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Bits.swift @@ -42,14 +42,14 @@ final class IntXLTestsOnBits: XCTestCase { XCTAssertEqual(T(sign: .plus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as W)).bitWidth, UInt.bitWidth * 4) XCTAssertEqual(T(sign: .plus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as W)).bitWidth, UInt.bitWidth * 5) XCTAssertEqual(T(sign: .plus, magnitude: M(words:[ 1, 0, 0, ~0/2 + 1] as W)).bitWidth, UInt.bitWidth * 5) - + XCTAssertEqual(T(sign: .minus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as W)).bitWidth, UInt.bitWidth * 4) XCTAssertEqual(T(sign: .minus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as W)).bitWidth, UInt.bitWidth * 4) XCTAssertEqual(T(sign: .minus, magnitude: M(words:[ 1, 0, 0, ~0/2 + 1] as W)).bitWidth, UInt.bitWidth * 5) } func testNonzeroBitCount() { - XCTAssertEqual(T(sign: .minus, magnitude: M.zero).nonzeroBitCount, 0) + XCTAssertEqual(T(sign: .minus, magnitude: 0).nonzeroBitCount, 0) XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).nonzeroBitCount, 0) XCTAssertEqual(T(words:[ 1, 1, 1, 1] as W).nonzeroBitCount, 4) XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).nonzeroBitCount, UInt.bitWidth * 1) @@ -64,7 +64,7 @@ final class IntXLTestsOnBits: XCTestCase { } func testLeadingZeroBitCount() { - XCTAssertEqual(T(sign: .minus, magnitude: M.zero).leadingZeroBitCount, UInt.bitWidth * 1) + XCTAssertEqual(T(sign: .minus, magnitude: 0).leadingZeroBitCount, UInt.bitWidth * 1) XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).leadingZeroBitCount, UInt.bitWidth * 1) XCTAssertEqual(T(words:[ 1, 1, 1, 1] as W).leadingZeroBitCount, UInt.bitWidth * 1 - 1) XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).leadingZeroBitCount, UInt.bitWidth * 0) @@ -84,7 +84,7 @@ final class IntXLTestsOnBits: XCTestCase { } func testTrailingZeroBitCount() { - XCTAssertEqual(T(sign: .minus, magnitude: M.zero).trailingZeroBitCount, UInt.bitWidth * 0) + XCTAssertEqual(T(sign: .minus, magnitude: 0).trailingZeroBitCount, UInt.bitWidth * 0) XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).trailingZeroBitCount, UInt.bitWidth * 0) XCTAssertEqual(T(words:[ 1, 1, 1, 1] as W).trailingZeroBitCount, UInt.bitWidth * 0) XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).trailingZeroBitCount, UInt.bitWidth * 0) @@ -96,7 +96,7 @@ final class IntXLTestsOnBits: XCTestCase { } func testMostSignificantBit() { - XCTAssertEqual(T(sign: .minus, magnitude: M.zero).mostSignificantBit, false) + XCTAssertEqual(T(sign: .minus, magnitude: 0).mostSignificantBit, false) XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).mostSignificantBit, false) XCTAssertEqual(T(words:[ 1, 1, 1, 1] as W).mostSignificantBit, false) XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).mostSignificantBit, true ) @@ -113,7 +113,7 @@ final class IntXLTestsOnBits: XCTestCase { } func testLeastSignificantBit() { - XCTAssertEqual(T(sign: .minus, magnitude: M.zero).leastSignificantBit, false) + XCTAssertEqual(T(sign: .minus, magnitude: 0).leastSignificantBit, false) XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).leastSignificantBit, false) XCTAssertEqual(T(words:[ 1, 1, 1, 1] as W).leastSignificantBit, true ) XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).leastSignificantBit, true ) diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Comparisons.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Comparisons.swift index 093fc67f..027e2fad 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Comparisons.swift +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Comparisons.swift @@ -31,8 +31,8 @@ final class IntXLTestsOnComparisons: XCTestCase { //=------------------------------------------------------------------------= func testIsZero() { - XCTAssertTrue (T(sign: .plus, magnitude: M( )).isZero) - XCTAssertTrue (T(sign: .minus, magnitude: M( )).isZero) + XCTAssertTrue (T(sign: .plus, magnitude: 0).isZero) + XCTAssertTrue (T(sign: .minus, magnitude: 0).isZero) XCTAssertTrue (T(words:[ 0] as W).isZero) XCTAssertFalse(T(words:[ 1] as W).isZero) @@ -44,8 +44,8 @@ final class IntXLTestsOnComparisons: XCTestCase { } func testIsLessThanZero() { - XCTAssertFalse(T(sign: .plus, magnitude: M( )).isLessThanZero) - XCTAssertFalse(T(sign: .minus, magnitude: M( )).isLessThanZero) + XCTAssertFalse(T(sign: .plus, magnitude: 0).isLessThanZero) + XCTAssertFalse(T(sign: .minus, magnitude: 0).isLessThanZero) XCTAssertFalse(T(words:[ 0] as W).isLessThanZero) XCTAssertFalse(T(words:[ 1] as W).isLessThanZero) @@ -57,8 +57,8 @@ final class IntXLTestsOnComparisons: XCTestCase { } func testIsMoreThanZero() { - XCTAssertFalse(T(sign: .plus, magnitude: M( )).isMoreThanZero) - XCTAssertFalse(T(sign: .minus, magnitude: M( )).isMoreThanZero) + XCTAssertFalse(T(sign: .plus, magnitude: 0).isMoreThanZero) + XCTAssertFalse(T(sign: .minus, magnitude: 0).isMoreThanZero) XCTAssertFalse(T(words:[ 0] as W).isMoreThanZero) XCTAssertTrue (T(words:[ 1] as W).isMoreThanZero) @@ -70,8 +70,8 @@ final class IntXLTestsOnComparisons: XCTestCase { } func testIsOdd() { - XCTAssertFalse(T(sign: .plus, magnitude: M( )).isOdd) - XCTAssertFalse(T(sign: .minus, magnitude: M( )).isOdd) + XCTAssertFalse(T(sign: .plus, magnitude: 0).isOdd) + XCTAssertFalse(T(sign: .minus, magnitude: 0).isOdd) XCTAssertFalse(T(words:[ 0] as W).isOdd) XCTAssertTrue (T(words:[ 1] as W).isOdd) @@ -83,8 +83,8 @@ final class IntXLTestsOnComparisons: XCTestCase { } func testIsEven() { - XCTAssertTrue (T(sign: .plus, magnitude: M( )).isEven) - XCTAssertTrue (T(sign: .minus, magnitude: M( )).isEven) + XCTAssertTrue (T(sign: .plus, magnitude: 0).isEven) + XCTAssertTrue (T(sign: .minus, magnitude: 0).isEven) XCTAssertTrue (T(words:[ 0] as W).isEven) XCTAssertFalse(T(words:[ 1] as W).isEven) @@ -96,8 +96,8 @@ final class IntXLTestsOnComparisons: XCTestCase { } func testIsPowerOf2() { - XCTAssertFalse(T(sign: .plus, magnitude: M( )).isPowerOf2) - XCTAssertFalse(T(sign: .minus, magnitude: M( )).isPowerOf2) + XCTAssertFalse(T(sign: .plus, magnitude: 0).isPowerOf2) + XCTAssertFalse(T(sign: .minus, magnitude: 0).isPowerOf2) XCTAssertFalse(T(words:[~3] as W).isPowerOf2) XCTAssertFalse(T(words:[~2] as W).isPowerOf2) @@ -119,8 +119,8 @@ final class IntXLTestsOnComparisons: XCTestCase { } func testSignum() { - NBKAssertSignum(T(sign: .plus, magnitude: M( )), Int( 0)) - NBKAssertSignum(T(sign: .minus, magnitude: M( )), Int( 0)) + NBKAssertSignum(T(sign: .plus, magnitude: 0), Int( 0)) + NBKAssertSignum(T(sign: .minus, magnitude: 0), Int( 0)) NBKAssertSignum(T(words:[ 0] as W), Int( 0)) NBKAssertSignum(T(words:[ 1] as W), Int( 1)) @@ -313,6 +313,12 @@ final class IntXLTestsOnComparisons: XCTestCase { // MARK: Tests x Miscellaneous //=------------------------------------------------------------------------= + func testOverloadsAreUnambiguous() { + func becauseThisCompilesSuccessfully(_ x: inout T) { + XCTAssertNotNil(x.signum()) // Int + } + } + func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { func becauseThisCompilesSuccessfully(_ x: inout T) { XCTAssertNotNil(x.compared(to: 0)) @@ -507,6 +513,12 @@ final class UIntXLTestsOnComparisons: XCTestCase { // MARK: Tests x Miscellaneous //=------------------------------------------------------------------------= + func testOverloadsAreUnambiguous() { + func becauseThisCompilesSuccessfully(_ x: inout T) { + XCTAssertNotNil(x.signum()) // Int + } + } + func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { func becauseThisCompilesSuccessfully(_ x: inout T) { XCTAssertNotNil(x.compared(to: 0)) From 8628ee543ee51d2d93c96b3baa41f96e070539f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Fri, 4 Aug 2023 13:21:57 +0200 Subject: [PATCH 038/133] NBKFlexibleWidth: Cleanup. --- .../NBKFlexibleWidth+Comparisons.swift | 22 +++++++++++++------ ...NBKFlexibleWidth+Complements+Storage.swift | 14 ++++++++++++ .../NBKFlexibleWidth+Complements.swift | 15 +++---------- 3 files changed, 32 insertions(+), 19 deletions(-) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift index 8766f953..4b74883e 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift @@ -61,19 +61,28 @@ extension NBKFlexibleWidth { } @inlinable public func compared(to other: Self) -> Int { - Self.compare(self, to: other, at: Int.zero, magnitude: { lhs, rhs, _ in lhs.compared(to: rhs) }) + Self.compare(self, to: other, magnitude:{ $0.compared(to: $1) }) } @inlinable public func compared(to other: Self, at index: Int) -> Int { - Self.compare(self, to: other, at: index, magnitude: { lhs, rhs, index in lhs.compared(to: rhs, at: index) }) + Self.compare(self, to: other, magnitude:{ $0.compared(to: $1, at: index) }) } @_disfavoredOverload @inlinable public func compared(to other: Digit) -> Int { - Self.compare(self, to: other, at: Int.zero, magnitude: { lhs, rhs, _ in lhs.compared(to: rhs) }) + Self.compare(self, to: other, magnitude:{ $0.compared(to: $1) }) } @_disfavoredOverload @inlinable public func compared(to other: Digit, at index: Int) -> Int { - Self.compare(self, to: other, at: index, magnitude: { lhs, rhs, index in lhs.compared(to: rhs, at: index) }) + Self.compare(self, to: other, magnitude:{ $0.compared(to: $1, at: index) }) + } + + //=------------------------------------------------------------------------= + // MARK: Accessors x Private + //=------------------------------------------------------------------------= + + @inlinable var isTwosComplementMinValue: Bool { + guard !self.magnitude.storage.elements.isEmpty else { return false } + return self.compared(to: Int.min, at: self.magnitude.storage.elements.count - 1).isZero } } @@ -87,14 +96,13 @@ extension NBKFlexibleWidth { // MARK: Utilities x Private //=------------------------------------------------------------------------= - @inlinable static func compare(_ lhs: Self, to rhs: T, at index: Int, - magnitude: (Magnitude, T.Magnitude, Int) -> Int) -> Int where T: NBKBinaryInteger { + @inlinable static func compare(_ lhs: Self, to rhs: T, magnitude: (Magnitude, T.Magnitude) -> Int) -> Int where T: NBKBinaryInteger { //=--------------------------------------= if lhs.sign.bit != rhs.isLessThanZero { return lhs.isZero && rhs.isZero ? 0 : lhs.sign.bit ? -1 : 1 } //=--------------------------------------= - let magnitude = magnitude(lhs.magnitude, rhs.magnitude, index) + let magnitude = magnitude(lhs.magnitude, rhs.magnitude) return lhs.sign.bit ? magnitude.negated() : magnitude } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements+Storage.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements+Storage.swift index ce53294f..b8fe759d 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements+Storage.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements+Storage.swift @@ -15,6 +15,20 @@ import NBKCoreKit extension NBKFlexibleWidth.Magnitude.Storage { + //=------------------------------------------------------------------------= + // MARK: Details x One's Complement + //=------------------------------------------------------------------------= + + @inlinable public mutating func formOnesComplement() { + for index in self.elements.indices { + self.elements[index].formOnesComplement() + } + } + + @inlinable public func onesComplement() -> Self { + Self(elements: self.elements.map(~)) + } + //=------------------------------------------------------------------------= // MARK: Details x Two's Complement //=------------------------------------------------------------------------= diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements.swift index 119fbbec..1c74ea10 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements.swift @@ -68,14 +68,6 @@ extension NBKFlexibleWidth { let overflow = partialValue.negateReportingOverflow() return PVO(partialValue, overflow) } - - //=------------------------------------------------------------------------= - // MARK: Utilities x Private - //=------------------------------------------------------------------------= - - @inlinable var isTwosComplementMinValue: Bool { - !self.magnitude.isZero && self.compared(to: Int.min, at: self.magnitude.storage.elements.count - 1).isZero - } } //*============================================================================* @@ -89,13 +81,12 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @inlinable public mutating func formOnesComplement() { - for index in self.storage.elements.indices { - self.storage.elements[index].formOnesComplement() - }; self.storage.normalize() + self.storage.formOnesComplement() + self.storage.normalize() } @inlinable public func onesComplement() -> Self { - Self(storage: Storage(elements: self.storage.elements.map(~))) + Self(storage: self.storage.onesComplement()) } //=------------------------------------------------------------------------= From 91c8e50988dbaebff6a54fd2df1692548020fb3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Fri, 4 Aug 2023 16:18:58 +0200 Subject: [PATCH 039/133] NBKResizableWidthKit. --- Package.swift | 8 +- .../NBKResizableWidth+Size.swift | 53 +++++++ .../NBKResizableWidth+Text.swift | 62 ++++++++ .../NBKResizableWidth+Words.swift | 146 ++++++++++++++++++ .../NBKResizableWidth.swift | 84 ++++++++++ 5 files changed, 352 insertions(+), 1 deletion(-) create mode 100644 Sources/NBKResizableWidthKit/NBKResizableWidth+Size.swift create mode 100644 Sources/NBKResizableWidthKit/NBKResizableWidth+Text.swift create mode 100644 Sources/NBKResizableWidthKit/NBKResizableWidth+Words.swift create mode 100644 Sources/NBKResizableWidthKit/NBKResizableWidth.swift diff --git a/Package.swift b/Package.swift index ae6e027f..0500c85a 100644 --- a/Package.swift +++ b/Package.swift @@ -89,7 +89,7 @@ let package = Package( //=--------------------------------------= .target( name: "NBKFlexibleWidthKit", - dependencies: ["NBKCoreKit"]), + dependencies: ["NBKCoreKit", "NBKResizableWidthKit"]), .testTarget( name: "NBKFlexibleWidthKitBenchmarks", @@ -98,5 +98,11 @@ let package = Package( .testTarget( name: "NBKFlexibleWidthKitTests", dependencies: ["NBKFlexibleWidthKit"]), + //=--------------------------------------= + // NBK x Resizable Width Kit + //=--------------------------------------= + .target( + name: "NBKResizableWidthKit", + dependencies: ["NBKCoreKit"]), ] ) diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Size.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Size.swift new file mode 100644 index 00000000..31fd1a68 --- /dev/null +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Size.swift @@ -0,0 +1,53 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Resizable Width x Size x Unsigned +//*============================================================================* + +extension NBKResizableWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Details x Count + //=------------------------------------------------------------------------= + + @inlinable mutating func reserve(minCount: Int) { + self.storage.reserveCapacity(minCount) + } + + @inlinable mutating func resize(minCount: Int) { + self.reserve(minCount: minCount) + appending: while self.storage.count < minCount { + self.storage.append(UInt.zero) + } + } + + @inlinable mutating func resize(maxCount: Int) { + precondition(!maxCount.isMoreThanZero, "\(Self.description) must contain at least one word") + if self.storage.count > maxCount { + self.storage.removeSubrange(maxCount...) + } + } + + //=------------------------------------------------------------------------= + // MARK: Details x Normalization + //=------------------------------------------------------------------------= + + @inlinable public var isNormal: Bool { + self.storage.count == 1 || !self.last.isZero + } + + @inlinable public mutating func normalize() { + trimming: while self.storage.count > 1, self.last.isZero { + self.storage.removeLast() + } + } +} diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Text.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Text.swift new file mode 100644 index 00000000..3db77a64 --- /dev/null +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Text.swift @@ -0,0 +1,62 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Resizable Width x Text x Signed +//*============================================================================* + +extension NBKResizableWidth { + + //=------------------------------------------------------------------------= + // MARK: Details x Encode + //=------------------------------------------------------------------------= + + /// The `description` of this type. + /// + /// ``` + /// ┌───────────── → ────────────┐ + /// │ self │ description │ + /// ├───────────── → ────────────┤ + /// │ Int256.self │ "Int256" │ + /// │ UInt512.self │ "UInt512" │ + /// └───────────── → ────────────┘ + /// ``` + /// + @inlinable public static var description: String { + "IntXR" + } +} + +//*============================================================================* +// MARK: * NBK x Resizable Width x Text x Unsigned +//*============================================================================* + +extension NBKResizableWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Details x Encode + //=------------------------------------------------------------------------= + + /// The `description` of this type. + /// + /// ``` + /// ┌───────────── → ────────────┐ + /// │ self │ description │ + /// ├───────────── → ────────────┤ + /// │ Int256.self │ "Int256" │ + /// │ UInt512.self │ "UInt512" │ + /// └───────────── → ────────────┘ + /// ``` + /// + @inlinable public static var description: String { + "UIntXR" + } +} diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Words.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Words.swift new file mode 100644 index 00000000..2a1ee2d4 --- /dev/null +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Words.swift @@ -0,0 +1,146 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Resizable Width x Words x Unsigned +//*============================================================================* + +extension NBKResizableWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + @inlinable public init(words: some RandomAccessCollection) { + self.init(storage: Storage(words)) + } + + @inlinable public init(repeating word: UInt, count: Int) { + self.init(storage: Storage(repeating: word, count: count)) + } + + //=------------------------------------------------------------------------= + // MARK: Accessors + //=------------------------------------------------------------------------= + + @inlinable public var count: Int { + self.storage.count + } + + @inlinable public var words: Self { + _read { yield self } + } +} + +//=----------------------------------------------------------------------------= +// MARK: + Collection x Indices +//=----------------------------------------------------------------------------= + +extension NBKResizableWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Accessors + //=------------------------------------------------------------------------= + + @inlinable public var startIndex: Int { + self.storage.startIndex + } + + @inlinable public var lastIndex: Int { + self.storage.index(before: self.storage.endIndex) + } + + @inlinable public var endIndex: Int { + self.storage.endIndex + } + + @inlinable public var indices: Range { + self.storage.indices + } + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + @inlinable public func distance(from start: Int, to end: Int) -> Int { + end - start + } + + @inlinable public func index(after index: Int) -> Int { + index + 1 + } + + @inlinable public func formIndex(after index: inout Int) { + index += 1 + } + + @inlinable public func index(before index: Int) -> Int { + index - 1 + } + + @inlinable public func formIndex(before index: inout Int) { + index -= 1 + } + + @inlinable public func index(_ index: Int, offsetBy distance: Int) -> Int { + index + distance + } + + @inlinable public func index(_ index: Int, offsetBy distance: Int, limitedBy limit: Int) -> Int? { + let distanceLimit: Int = self.distance(from: index, to: limit) + + guard distance >= 0 + ? distance <= distanceLimit || distanceLimit < 0 + : distance >= distanceLimit || distanceLimit > 0 + else { return nil } + + return self.index(index, offsetBy: distance) as Int + } +} + +//=----------------------------------------------------------------------------= +// MARK: + Collection x Elements +//=----------------------------------------------------------------------------= + +extension NBKResizableWidth.Magnitude { + + /// The least significant word. + /// + /// - Note: This member is required by `Swift.BinaryInteger`. + /// + @inlinable public var _lowWord: UInt { + self.first + } + + /// The least significant word. + @inlinable public var first: UInt { + _read { yield self[self.startIndex] } + _modify { yield &self[self.startIndex] } + } + + /// The most significant word. + @inlinable public var last: UInt { + _read { yield self[self.lastIndex] } + _modify { yield &self[self.lastIndex] } + } + + /// The most significant word, reinterpreted as a ``Digit``. + @inlinable public var tail: Digit { + _read { yield self[self.lastIndex] } + _modify { yield &self[self.lastIndex] } + } + + /// Accesses the word at the given index, from least significant to most. + @inlinable public subscript(_ index: Int) -> UInt { + _read { yield self.storage[index] } + _modify { yield &self.storage[index] } + } +} diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth.swift new file mode 100644 index 00000000..249009b9 --- /dev/null +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth.swift @@ -0,0 +1,84 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Resizable Width +//*============================================================================* + +/// A signed, resizable-width, binary integer of at least one word. +@frozen public struct NBKResizableWidth { + + public typealias Digit = Int + + @usableFromInline typealias Storage = Array + + //=------------------------------------------------------------------------= + // MARK: State + //=------------------------------------------------------------------------= + + @usableFromInline var storage: Storage + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + @inlinable init(storage: Storage) { + self.storage = storage + precondition(!self.storage.isEmpty, "\(Self.description) must contain at least one word") + } + + @inlinable init(unchecked storage: Storage) { + self.storage = storage + Swift.assert(!self.storage.isEmpty, "\(Self.description) must contain at least one word") + } + + //*========================================================================* + // MARK: * Magnitude + //*========================================================================* + + /// An unsigned, resizable-width, binary integer of at least one word. + @frozen public struct Magnitude: MutableCollection, RandomAccessCollection, Sendable { + + public typealias Digit = UInt + + @usableFromInline typealias Storage = NBKResizableWidth.Storage + + //=--------------------------------------------------------------------= + // MARK: State + //=--------------------------------------------------------------------= + + @usableFromInline var storage: Storage + + //=--------------------------------------------------------------------= + // MARK: Initializers + //=--------------------------------------------------------------------= + + @inlinable init(storage: Storage) { + self.storage = storage + precondition(!self.storage.isEmpty, "\(Self.description) must contain at least one word") + } + + @inlinable init(unchecked storage: Storage) { + self.storage = storage + Swift.assert(!self.storage.isEmpty, "\(Self.description) must contain at least one word") + } + } +} + +//*============================================================================* +// MARK: * NBK x Resizable Width x Aliases +//*============================================================================* + +/// A signed, resizable-width, binary integer of at least one word. +public typealias IntXR = NBKResizableWidth + +/// An unsigned, resizable-width, binary integer of at least one word. +public typealias UIntXR = NBKResizableWidth.Magnitude From 53ee3a6ef6c8da066f0bf3bd7e3a60eee6835296 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Fri, 4 Aug 2023 17:39:24 +0200 Subject: [PATCH 040/133] NBKResizableWidthKit: Miscellaneous. --- .../NBKResizableWidth+Addition+Digit.swift | 57 ++++++++++++++ .../NBKResizableWidth+Addition+Void.swift | 31 ++++++++ .../NBKResizableWidth+Addition.swift | 49 ++++++++++++ .../NBKResizableWidth+Complements.swift | 71 ++++++++++++++++++ ...KResizableWidth+Multiplication+Digit.swift | 46 ++++++++++++ .../NBKResizableWidth+Multiplication.swift | 51 +++++++++++++ .../NBKResizableWidth+Size.swift | 6 +- .../NBKResizableWidth+Subtraction+Digit.swift | 75 +++++++++++++++++++ .../NBKResizableWidth+Subtraction+Void.swift | 31 ++++++++ .../NBKResizableWidth+Subtraction.swift | 49 ++++++++++++ .../NBKResizableWidth+Uninitialized.swift | 32 ++++++++ .../NBKResizableWidth+Words.swift | 2 +- 12 files changed, 496 insertions(+), 4 deletions(-) create mode 100644 Sources/NBKResizableWidthKit/NBKResizableWidth+Addition+Digit.swift create mode 100644 Sources/NBKResizableWidthKit/NBKResizableWidth+Addition+Void.swift create mode 100644 Sources/NBKResizableWidthKit/NBKResizableWidth+Addition.swift create mode 100644 Sources/NBKResizableWidthKit/NBKResizableWidth+Complements.swift create mode 100644 Sources/NBKResizableWidthKit/NBKResizableWidth+Multiplication+Digit.swift create mode 100644 Sources/NBKResizableWidthKit/NBKResizableWidth+Multiplication.swift create mode 100644 Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction+Digit.swift create mode 100644 Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction+Void.swift create mode 100644 Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction.swift create mode 100644 Sources/NBKResizableWidthKit/NBKResizableWidth+Uninitialized.swift diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition+Digit.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition+Digit.swift new file mode 100644 index 00000000..a9687d3c --- /dev/null +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition+Digit.swift @@ -0,0 +1,57 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Resizable Width x Addition x Unsigned +//*============================================================================* + +extension NBKResizableWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public mutating func add(_ other: UInt, plus addend: Bool, at index: Int) -> Bool { + var index = index, overflow = addend + self.add(other, at: &index, carrying: &overflow) + return overflow as Bool + } +} + +//=----------------------------------------------------------------------------= +// MARK: + Algorithms +//=----------------------------------------------------------------------------= + +extension NBKResizableWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable mutating func add(_ other: UInt, at index: inout Int, carrying overflow: inout Bool) { + self.addWithoutGoingBeyond(other, at: &index, carrying: &overflow) + self.add((), at: &index, carrying: &overflow) + } + + @inlinable mutating func addWithoutGoingBeyond(_ other: UInt, at index: inout Int, carrying overflow: inout Bool) { + var other = other as UInt + + if overflow { + overflow = other.addReportingOverflow(1 as UInt) + } + + if !overflow { + overflow = self.storage[index].addReportingOverflow(other) + } + + self.storage.formIndex(after: &index) + } +} diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition+Void.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition+Void.swift new file mode 100644 index 00000000..c03b731c --- /dev/null +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition+Void.swift @@ -0,0 +1,31 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Resizable Width x Addition x Unsigned x Void +//*============================================================================* +//=----------------------------------------------------------------------------= +// MARK: + Algorithms +//=----------------------------------------------------------------------------= + +extension NBKResizableWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable mutating func add(_ other: Void, at index: inout Int, carrying overflow: inout Bool) { + while overflow && index < self.storage.endIndex { + overflow = self.storage[index].addReportingOverflow(1 as UInt) + self.storage.formIndex(after: &index) + } + } +} diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition.swift new file mode 100644 index 00000000..4f6e177e --- /dev/null +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition.swift @@ -0,0 +1,49 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Resizable Width x Addition x Unsigned +//*============================================================================* + +extension NBKResizableWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public mutating func add(_ other: Self, plus addend: Bool, at index: Int) -> Bool { + var index = index, overflow = addend + self.add(other, at: &index, carrying: &overflow) + return overflow as Bool + } +} + +//=----------------------------------------------------------------------------= +// MARK: + Algorithms +//=----------------------------------------------------------------------------= + +extension NBKResizableWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Transformations x Self + //=------------------------------------------------------------------------= + + @inlinable mutating func add(_ other: Self, at index: inout Int, carrying overflow: inout Bool) { + self.addWithoutGoingBeyond(other, at: &index, carrying: &overflow) + self.add((), at: &index, carrying: &overflow) + } + + @inlinable mutating func addWithoutGoingBeyond(_ other: Self, at index: inout Int, carrying overflow: inout Bool) { + for otherIndex in other.storage.indices { // for-index-in >= for-element-in + self.addWithoutGoingBeyond(other.storage[otherIndex], at: &index, carrying: &overflow) + } + } +} diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Complements.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Complements.swift new file mode 100644 index 00000000..c2702357 --- /dev/null +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Complements.swift @@ -0,0 +1,71 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Resizable Width x Complements x Unsigned +//*============================================================================* + +extension NBKResizableWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Details x One's Complement + //=------------------------------------------------------------------------= + + @inlinable public mutating func formOnesComplement() { + for index in self.storage.indices { + self.storage[index].formOnesComplement() + } + } + + @inlinable public func onesComplement() -> Self { + Self(unchecked: self.storage.map(~)) + } + + //=------------------------------------------------------------------------= + // MARK: Details x Two's Complement + //=------------------------------------------------------------------------= + + // TODO: use NBKBinaryInteger default + @inlinable public mutating func formTwosComplement() { + _ = self.formTwosComplementReportingOverflow() + } + + // TODO: use NBKBinaryInteger default + @inlinable public func twosComplement() -> Self { + self.twosComplementReportingOverflow().partialValue + } + + @inlinable public mutating func formTwosComplementReportingOverflow() -> Bool { + self.formTwosComplementSubsequence(true) + } + + @inlinable public func twosComplementReportingOverflow() -> PVO { + var partialValue = self + let overflow = partialValue.formTwosComplementReportingOverflow() + return PVO(partialValue, overflow) + } + + @inlinable public mutating func formTwosComplementSubsequence(_ carry: Bool) -> Bool { + var carry = carry + + for index in self.storage.indices { + carry = self.storage[index].formTwosComplementSubsequence(carry) + } + + return carry as Bool + } + + @inlinable public func twosComplementSubsequence(_ carry: Bool) -> PVO { + var partialValue = self + let overflow = partialValue.formTwosComplementSubsequence(carry) + return PVO(partialValue, overflow) + } +} diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Multiplication+Digit.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Multiplication+Digit.swift new file mode 100644 index 00000000..01011fa3 --- /dev/null +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Multiplication+Digit.swift @@ -0,0 +1,46 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Resizable Width x Multiplication x Digit x Unsigned +//*============================================================================* + +extension NBKResizableWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public mutating func multiply(by other: UInt, plus addend: UInt) -> UInt { + var overflow = addend + self.multiply(by: other, carrying: &overflow) + return overflow as UInt + } +} + +//=----------------------------------------------------------------------------= +// MARK: + Algorithms +//=----------------------------------------------------------------------------= + +extension NBKResizableWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable mutating func multiply(by other: UInt, carrying overflow: inout UInt) { + for index in self.storage.indices { + var subproduct = self.storage[index].multipliedFullWidth(by: other) + overflow = UInt(bit: subproduct.low.addReportingOverflow(overflow)) &+ subproduct.high + self.storage[index] = subproduct.low as UInt + } + } +} diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Multiplication.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Multiplication.swift new file mode 100644 index 00000000..f77f89d5 --- /dev/null +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Multiplication.swift @@ -0,0 +1,51 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Resizable Width x Multiplication x Digit x Unsigned +//*============================================================================* + +extension NBKResizableWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Transformations x Self + //=------------------------------------------------------------------------= + + @inlinable public func multipliedFullWidth(by multiplicand: Self) -> Self { + self.multipliedFullWidthByNaiveMethod(by: multiplicand, adding: UInt.zero) + } + + @inlinable public func multipliedFullWidthByNaiveMethod(by multiplicand: Self, adding addend: UInt) -> Self { + Self.uninitialized(count: self.storage.count + multiplicand.storage.count) { product in + //=----------------------------------= + // de/init: pointee is trivial + //=----------------------------------= + product.update(repeating: UInt.zero) + //=----------------------------------= + var overflow = addend as UInt + for lhsIndex in self.storage.indices { + let outer = self.storage[lhsIndex] + + for rhsIndex in multiplicand.storage.indices { + let inner = multiplicand.storage[rhsIndex] + var subproduct = outer.multipliedFullWidth(by: inner) + + overflow = UInt(bit: subproduct.low.addReportingOverflow(overflow)) + overflow &+= UInt(bit: product[lhsIndex + rhsIndex].addReportingOverflow(subproduct.low)) + overflow &+= subproduct.high + } + + product[lhsIndex + multiplicand.storage.count] = overflow + overflow = UInt.zero + } + } + } +} diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Size.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Size.swift index 31fd1a68..cebfc458 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Size.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Size.swift @@ -19,18 +19,18 @@ extension NBKResizableWidth.Magnitude { // MARK: Details x Count //=------------------------------------------------------------------------= - @inlinable mutating func reserve(minCount: Int) { + @inlinable public mutating func reserve(minCount: Int) { self.storage.reserveCapacity(minCount) } - @inlinable mutating func resize(minCount: Int) { + @inlinable public mutating func resize(minCount: Int) { self.reserve(minCount: minCount) appending: while self.storage.count < minCount { self.storage.append(UInt.zero) } } - @inlinable mutating func resize(maxCount: Int) { + @inlinable public mutating func resize(maxCount: Int) { precondition(!maxCount.isMoreThanZero, "\(Self.description) must contain at least one word") if self.storage.count > maxCount { self.storage.removeSubrange(maxCount...) diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction+Digit.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction+Digit.swift new file mode 100644 index 00000000..47d08652 --- /dev/null +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction+Digit.swift @@ -0,0 +1,75 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Resizable Width x Subtraction x Unsigned +//*============================================================================* + +extension NBKResizableWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public mutating func subtract(_ other: UInt, plus addend: Bool, at index: Int) -> Bool { + var index = index, overflow = addend + self.subtract(other, at: &index, borrowing: &overflow) + return overflow as Bool + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Multiplication By UInt + //=------------------------------------------------------------------------= + + @inlinable public mutating func subtract(_ other: Self, times multiplicand: UInt, plus addend: UInt, at index: Int) -> Bool { + var index = index + var overflow = false + var last = addend as UInt + + for otherIndex in other.storage.indices { + var subproduct = other.storage[otherIndex].multipliedFullWidth(by: multiplicand) + last = UInt(bit: subproduct.low.addReportingOverflow(last)) &+ subproduct.high + self.subtractWithoutGoingBeyond(subproduct.low, at: &index, borrowing: &overflow) + } + + return self.subtract(last, plus: overflow, at: index) + } +} + +//=----------------------------------------------------------------------------= +// MARK: + Algorithms +//=----------------------------------------------------------------------------= + +extension NBKResizableWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable mutating func subtract(_ other: UInt, at index: inout Int, borrowing overflow: inout Bool) { + self.subtractWithoutGoingBeyond(other, at: &index, borrowing: &overflow) + self.subtract((), at: &index, borrowing: &overflow) + } + + @inlinable mutating func subtractWithoutGoingBeyond(_ other: UInt, at index: inout Int, borrowing overflow: inout Bool) { + var other = other as UInt + + if overflow { + overflow = other.addReportingOverflow(1 as UInt) + } + + if !overflow { + overflow = self.storage[index].subtractReportingOverflow(other) + } + + self.storage.formIndex(after: &index) + } +} diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction+Void.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction+Void.swift new file mode 100644 index 00000000..875d2966 --- /dev/null +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction+Void.swift @@ -0,0 +1,31 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Resizable Width x Subtraction x Unsigned +//*============================================================================* +//=----------------------------------------------------------------------------= +// MARK: + Algorithms +//=----------------------------------------------------------------------------= + +extension NBKResizableWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable mutating func subtract(_ other: Void, at index: inout Int, borrowing overflow: inout Bool) { + while overflow && index < self.storage.endIndex { + overflow = self.storage[index].subtractReportingOverflow(1 as UInt) + self.storage.formIndex(after: &index) + } + } +} diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction.swift new file mode 100644 index 00000000..2ef829f4 --- /dev/null +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction.swift @@ -0,0 +1,49 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Resizable Width x Subtraction x Unsigned +//*============================================================================* + +extension NBKResizableWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Transformations x Self + //=------------------------------------------------------------------------= + + @inlinable public mutating func subtract(_ other: Self, plus addend: Bool, at index: Int) -> Bool { + var index = index, overflow = addend + self.subtract(other, at: &index, borrowing: &overflow) + return overflow as Bool + } +} + +//=----------------------------------------------------------------------------= +// MARK: + Algorithms +//=----------------------------------------------------------------------------= + +extension NBKResizableWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable mutating func subtract(_ other: Self, at index: inout Int, borrowing overflow: inout Bool) { + self.subtractWithoutGoingBeyond(other, at: &index, borrowing: &overflow) + self.subtract((), at: &index, borrowing: &overflow) + } + + @inlinable mutating func subtractWithoutGoingBeyond(_ other: Self, at index: inout Int, borrowing overflow: inout Bool) { + for otherIndex in other.storage.indices { // for-index-in >= for-element-in + self.subtractWithoutGoingBeyond(other.storage[otherIndex], at: &index, borrowing: &overflow) + } + } +} diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Uninitialized.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Uninitialized.swift new file mode 100644 index 00000000..c033bfe9 --- /dev/null +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Uninitialized.swift @@ -0,0 +1,32 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Resizable Width x Uninitialized x Unsigned +//*============================================================================* + +extension NBKResizableWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + // TODO: measure (inout Self) -> Void + @inlinable static func uninitialized(count: Int, body: (NBK.UnsafeMutableWords) -> Void) -> Self { + let storage = Storage(unsafeUninitializedCapacity: count) { + storage, endIndex in + body(NBK.UnsafeMutableWords(rebasing: storage.prefix(upTo: count))) + endIndex = count as Int + } + + return Self(storage: storage) + } +} diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Words.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Words.swift index 2a1ee2d4..69110281 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Words.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Words.swift @@ -19,7 +19,7 @@ extension NBKResizableWidth.Magnitude { // MARK: Initializers //=------------------------------------------------------------------------= - @inlinable public init(words: some RandomAccessCollection) { + @inlinable public init(words: some Collection) { self.init(storage: Storage(words)) } From e519160019aa5f607ce60ae024e79beeb8ff9ef2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Fri, 4 Aug 2023 18:06:59 +0200 Subject: [PATCH 041/133] NBKResizableWidthKit: Miscellaneous. --- .../NBKResizableWidth+Logic.swift | 31 ++++ .../NBKResizableWidth+Numbers.swift | 48 ++++++ .../NBKResizableWidth+Shifts.swift | 145 ++++++++++++++++++ .../Private/Pointers.swift | 32 ++++ 4 files changed, 256 insertions(+) create mode 100644 Sources/NBKResizableWidthKit/NBKResizableWidth+Logic.swift create mode 100644 Sources/NBKResizableWidthKit/NBKResizableWidth+Numbers.swift create mode 100644 Sources/NBKResizableWidthKit/NBKResizableWidth+Shifts.swift create mode 100644 Sources/NBKResizableWidthKit/Private/Pointers.swift diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Logic.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Logic.swift new file mode 100644 index 00000000..b50f9211 --- /dev/null +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Logic.swift @@ -0,0 +1,31 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Resizable Width x Logic x Unsigned +//*============================================================================* + +extension NBKResizableWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable mutating func formInIntersection(of other: Self, each element: (UInt, UInt) -> UInt) { + self .storage.withUnsafeMutableBufferPointer { lhs in + other.storage.withUnsafeBufferPointer { rhs in + let endIndex = Swift.min(lhs.endIndex, rhs.endIndex) + let lhsIntersection = NBK.UnsafeMutableWords(rebasing: lhs.prefix(upTo: endIndex)) + let rhsIntersection = /*---*/NBK.UnsafeWords(rebasing: rhs.prefix(upTo: endIndex)) + NBK.merge(into: lhsIntersection, from: NBK.UnsafeWords(lhsIntersection), rhsIntersection, each: element) + }} + } +} diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Numbers.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Numbers.swift new file mode 100644 index 00000000..72748575 --- /dev/null +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Numbers.swift @@ -0,0 +1,48 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Numbers x Unsigned +//*============================================================================* + +extension NBKResizableWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Initializers x Digit + //=------------------------------------------------------------------------= + + @inlinable init(digit: UInt) { + self.init(unchecked:[digit]) + } + + @inlinable init(digit: UInt, at index: Int) { + self.init(repeating: UInt.zero, count: index + 1) + self.storage[index] = digit + } + + //=------------------------------------------------------------------------= + // MARK: Initializers x Literal + //=------------------------------------------------------------------------= + + @inlinable init(truncating source: StaticBigInt) { + //=--------------------------------------= + let bitWidth = source.bitWidth + let major = NBK .quotientDividingByBitWidthAssumingIsAtLeastZero(bitWidth) + let minor = NBK.remainderDividingByBitWidthAssumingIsAtLeastZero(bitWidth) + let count = major + Int(bit: !minor.isZero) + //=--------------------------------------= + self = Self.uninitialized(count: count) { storage in + for index in storage.indices { + storage[index] = source[index] + } + } + } +} diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Shifts.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Shifts.swift new file mode 100644 index 00000000..45d1a3d2 --- /dev/null +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Shifts.swift @@ -0,0 +1,145 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Resizable Width x Shifts x Unsigned +//*============================================================================* +//=----------------------------------------------------------------------------= +// MARK: + Left +//=----------------------------------------------------------------------------= + +extension NBKResizableWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Transformations x Int + //=------------------------------------------------------------------------= + + /// Performs a left shift. + /// + /// - Parameters: + /// - distance: `0 <= distance < self.bitWidth` + /// + @inlinable public mutating func bitshiftLeft(by distance: Int) { + precondition(distance >= 0, NBK.callsiteOutOfBoundsInfo()) + let major = NBK .quotientDividingByBitWidthAssumingIsAtLeastZero(distance) + let minor = NBK.remainderDividingByBitWidthAssumingIsAtLeastZero(distance) + return self.bitshiftLeft(words: major, bits: minor) + } + + /// Performs a left shift. + /// + /// - Parameters: + /// - words: `0 <= words < self.endIndex` + /// - bits: `0 <= bits  < UInt.bitWidth` + /// + @inlinable public mutating func bitshiftLeft(words: Int, bits: Int) { + //=--------------------------------------= + if bits.isZero { + return self.bitshiftLeft(words: words) + } + //=--------------------------------------= + self.bitshiftLeft(words: words, atLeastOneBit: bits) + } + + /// Performs a left shift. + /// + /// - Parameters: + /// - words: `0 <= words < self.endIndex` + /// + @inlinable public mutating func bitshiftLeft(words: Int) { + //=--------------------------------------= + if words.isZero { return } + //=--------------------------------------= + self.bitshiftLeft(atLeastOneWord: words) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Int x Private + //=------------------------------------------------------------------------= + + @inlinable mutating func bitshiftLeft(words: Int, atLeastOneBit bits: Int) { + self.storage.withUnsafeMutableBufferPointer { + NBK.bitshiftLeftAsFixedLimbsCodeBlock(&$0, environment: false, limbs: words, atLeastOneBit: bits) + } + } + + @inlinable mutating func bitshiftLeft(atLeastOneWord words: Int) { + self.storage.withUnsafeMutableBufferPointer { + NBK.bitshiftLeftAsFixedLimbsCodeBlock(&$0, environment: false, atLeastOneLimb: words) + } + } +} + +//=----------------------------------------------------------------------------= +// MARK: + Right +//=----------------------------------------------------------------------------= + +extension NBKResizableWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Transformations x Right + //=------------------------------------------------------------------------= + + /// Performs an un/signed right shift. + /// + /// - Parameters: + /// - distance: `0 <= distance < self.bitWidth` + /// + @inlinable public mutating func bitshiftRight(by distance: Int) { + precondition(distance >= 0, NBK.callsiteOutOfBoundsInfo()) + let major = NBK .quotientDividingByBitWidthAssumingIsAtLeastZero(distance) + let minor = NBK.remainderDividingByBitWidthAssumingIsAtLeastZero(distance) + return self.bitshiftRight(words: major, bits: minor) + } + + /// Performs an un/signed right shift. + /// + /// - Parameters: + /// - words: `0 <= words < self.endIndex` + /// - bits: `0 <= bits  < UInt.bitWidth` + /// + @inlinable public mutating func bitshiftRight(words: Int, bits: Int) { + //=--------------------------------------= + if bits.isZero { + return self.bitshiftRight(words: words) + } + //=--------------------------------------= + self.bitshiftRight(words: words, atLeastOneBit: bits) + } + + /// Performs an un/signed right shift. + /// + /// - Parameters: + /// - words: `0 <= words < self.endIndex` + /// + @inlinable public mutating func bitshiftRight(words: Int) { + //=--------------------------------------= + if words.isZero { return } + //=--------------------------------------= + self.bitshiftRight(atLeastOneWord: words) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Int x Private + //=------------------------------------------------------------------------= + + @inlinable mutating func bitshiftRight(words: Int, atLeastOneBit bits: Int) { + self.storage.withUnsafeMutableBufferPointer { + NBK.bitshiftRightAsFixedLimbsCodeBlock(&$0, environment: false, limbs: words, atLeastOneBit: bits) + } + } + + @inlinable mutating func bitshiftRight(atLeastOneWord words: Int) { + self.storage.withUnsafeMutableBufferPointer { + NBK.bitshiftRightAsFixedLimbsCodeBlock(&$0, environment: false, atLeastOneLimb: words) + } + } +} diff --git a/Sources/NBKResizableWidthKit/Private/Pointers.swift b/Sources/NBKResizableWidthKit/Private/Pointers.swift new file mode 100644 index 00000000..6cabcd95 --- /dev/null +++ b/Sources/NBKResizableWidthKit/Private/Pointers.swift @@ -0,0 +1,32 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Pointers +//*============================================================================* + +extension NBK { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable static func merge(into result: UnsafeMutableBufferPointer, + from x0: UnsafeBufferPointer, _ x1: UnsafeBufferPointer, each element: (T, T) -> T) { + //=--------------------------------------= + precondition(result.count == x0.count, NBK.callsiteOutOfBoundsInfo()) + precondition(result.count == x1.count, NBK.callsiteOutOfBoundsInfo()) + //=--------------------------------------= + for index in result.indices { + result[index] = element(x0[index], x1[index]) + } + } +} From 75a9f0e9b8ce4aed92f4e7e0bdd4a8574cd6c4bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sat, 5 Aug 2023 09:08:27 +0200 Subject: [PATCH 042/133] NBKFlexibleWidthKit: NBKResizableWidthKit. --- .../NBKFlexibleWidth+Addition+Digit.swift | 5 +- .../NBKFlexibleWidth+Addition+Storage.swift | 93 ----------- .../NBKFlexibleWidth+Addition.swift | 5 +- .../NBKFlexibleWidth+Bits.swift | 15 +- .../NBKFlexibleWidth+Comparisons.swift | 80 ++-------- ...NBKFlexibleWidth+Complements+Storage.swift | 53 ------- .../NBKFlexibleWidth+Complements.swift | 1 + .../NBKFlexibleWidth+Division+Digit.swift | 7 +- .../NBKFlexibleWidth+Division.swift | 25 +-- .../NBKFlexibleWidth+Logic+Storage.swift | 31 ---- .../NBKFlexibleWidth+Logic.swift | 7 +- .../NBKFlexibleWidth+Miscellaneous.swift | 10 +- ...BKFlexibleWidth+Multiplication+Digit.swift | 5 +- ...FlexibleWidth+Multiplication+Storage.swift | 80 ---------- .../NBKFlexibleWidth+Multiplication.swift | 1 + .../NBKFlexibleWidth+Numbers+Storage.swift | 48 ------ .../NBKFlexibleWidth+Numbers.swift | 1 + .../NBKFlexibleWidth+Shifts+Storage.swift | 145 ----------------- .../NBKFlexibleWidth+Shifts.swift | 19 ++- .../NBKFlexibleWidth+Storage.swift | 64 -------- .../NBKFlexibleWidth+Subtraction+Digit.swift | 1 + ...NBKFlexibleWidth+Subtraction+Storage.swift | 112 ------------- .../NBKFlexibleWidth+Subtraction.swift | 3 +- .../NBKFlexibleWidth+Text+Radix.swift | 5 +- .../NBKFlexibleWidth+Uninitialized.swift | 31 ---- .../NBKFlexibleWidth+Words.swift | 147 ++++-------------- .../NBKFlexibleWidth.swift | 28 +--- .../NBKResizableWidth+Comparisons.swift | 138 ++++++++++++++++ .../NBKResizableWidth+Complements.swift | 2 +- .../NBKResizableWidth+Logic.swift | 7 +- ...KResizableWidth+Multiplication+Digit.swift | 2 +- .../NBKResizableWidth+Numbers.swift | 9 +- .../NBKResizableWidth+Shifts.swift | 12 +- .../NBKResizableWidth+Size.swift | 15 +- .../NBKResizableWidth+Uninitialized.swift | 2 +- .../NBKResizableWidth+Words+Pointers.swift | 58 +++++++ .../NBKResizableWidth+Words.swift | 17 ++ .../NBKResizableWidth.swift | 44 +++++- .../Private/Collection.swift} | 24 +-- .../IntXL+Logic.swift | 9 ++ .../IntXL+Words.swift | 72 +++++++++ .../NBKFlexibleWidthKitTests/IntXL+Bits.swift | 10 +- .../IntXL+Complements.swift | 2 +- .../IntXL+Logic.swift | 2 +- .../IntXL+Words.swift | 19 +-- 45 files changed, 500 insertions(+), 966 deletions(-) delete mode 100644 Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Storage.swift delete mode 100644 Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements+Storage.swift delete mode 100644 Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic+Storage.swift delete mode 100644 Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Storage.swift delete mode 100644 Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers+Storage.swift delete mode 100644 Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts+Storage.swift delete mode 100644 Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Storage.swift delete mode 100644 Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Storage.swift delete mode 100644 Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Uninitialized.swift create mode 100644 Sources/NBKResizableWidthKit/NBKResizableWidth+Comparisons.swift create mode 100644 Sources/NBKResizableWidthKit/NBKResizableWidth+Words+Pointers.swift rename Sources/{NBKFlexibleWidthKit/Private/Pointers.swift => NBKResizableWidthKit/Private/Collection.swift} (53%) create mode 100644 Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Words.swift diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift index 9ad807d6..ef095562 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift @@ -8,6 +8,7 @@ //=----------------------------------------------------------------------------= import NBKCoreKit +import NBKResizableWidthKit //*============================================================================* // MARK: * NBK x Flexible Width x Addition x Digit x Signed @@ -74,9 +75,9 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= if other.isZero { return } //=--------------------------------------= - self.storage.resize(minCount: index + 1) + self.storage.resize(minCount: index + 1) let overflow = self.storage.add(other, plus: false, at: index) - if overflow { self.storage.elements.append(1) } + if overflow { self.storage.append(1) } } @_disfavoredOverload @inlinable public func adding(_ other: UInt, at index: Int) -> Self { diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Storage.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Storage.swift deleted file mode 100644 index b6166fef..00000000 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Storage.swift +++ /dev/null @@ -1,93 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Flexible Width x Addition x Unsigned x Storage -//*============================================================================* - -extension NBKFlexibleWidth.Magnitude.Storage { - - //=------------------------------------------------------------------------= - // MARK: Transformations x Self - //=------------------------------------------------------------------------= - - @inlinable mutating func add(_ other: Self, plus addend: Bool, at index: Int) -> Bool { - var index = index, overflow = addend - self.add(other, at: &index, carrying: &overflow) - return overflow as Bool - } - - //=------------------------------------------------------------------------= - // MARK: Transformations x UInt - //=------------------------------------------------------------------------= - - @inlinable mutating func add(_ other: UInt, plus addend: Bool, at index: Int) -> Bool { - var index = index, overflow = addend - self.add(other, at: &index, carrying: &overflow) - return overflow as Bool - } -} - -//=----------------------------------------------------------------------------= -// MARK: + Algorithms -//=----------------------------------------------------------------------------= - -extension NBKFlexibleWidth.Magnitude.Storage { - - //=------------------------------------------------------------------------= - // MARK: Transformations x Self - //=------------------------------------------------------------------------= - - @inlinable mutating func add(_ other: Self, at index: inout Int, carrying overflow: inout Bool) { - self.addWithoutGoingBeyond(other, at: &index, carrying: &overflow) - self.add((), at: &index, carrying: &overflow) - } - - @inlinable mutating func addWithoutGoingBeyond(_ other: Self, at index: inout Int, carrying overflow: inout Bool) { - for otherIndex in other.elements.indices { // for-index-in >= for-element-in - self.addWithoutGoingBeyond(other.elements[otherIndex], at: &index, carrying: &overflow) - } - } - - //=------------------------------------------------------------------------= - // MARK: Transformations x UInt - //=------------------------------------------------------------------------= - - @inlinable mutating func add(_ other: UInt, at index: inout Int, carrying overflow: inout Bool) { - self.addWithoutGoingBeyond(other, at: &index, carrying: &overflow) - self.add((), at: &index, carrying: &overflow) - } - - @inlinable mutating func addWithoutGoingBeyond(_ other: UInt, at index: inout Int, carrying overflow: inout Bool) { - var other = other as UInt - - if overflow { - overflow = other.addReportingOverflow(1 as UInt) - } - - if !overflow { - overflow = self.elements[index].addReportingOverflow(other) - } - - self.elements.formIndex(after: &index) - } - - //=------------------------------------------------------------------------= - // MARK: Transformations x Void - //=------------------------------------------------------------------------= - - @inlinable mutating func add(_ other: Void, at index: inout Int, carrying overflow: inout Bool) { - while overflow && index < self.elements.endIndex { - overflow = self.elements[index].addReportingOverflow(1 as UInt) - self.elements.formIndex(after: &index) - } - } -} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift index 4f4f9b1e..d6c856c2 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift @@ -8,6 +8,7 @@ //=----------------------------------------------------------------------------= import NBKCoreKit +import NBKResizableWidthKit //*============================================================================* // MARK: * NBK x Flexible Width x Addition x Signed @@ -74,9 +75,9 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= if other.isZero { return } //=--------------------------------------= - self.storage.resize(minCount: other.storage.elements.count + index) + self.storage.resize(minCount: other.storage.count + index) let overflow = self.storage.add(other.storage, plus: false, at: index) - if overflow { self.storage.elements.append(1) } + if overflow { self.storage.append(1) } } @inlinable public func adding(_ other: Self, at index: Int) -> Self { diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift index 9319ef91..e24c5ba2 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift @@ -8,6 +8,7 @@ //=----------------------------------------------------------------------------= import NBKCoreKit +import NBKResizableWidthKit //*============================================================================* // MARK: * NBK x Flexible Width x Bits x Signed @@ -35,7 +36,7 @@ extension NBKFlexibleWidth { @inlinable public var nonzeroBitCount: Int { switch self.isLessThanZero { case false: return self.magnitude.nonzeroBitCount - case true: return NBK.nonzeroBitCount(twosComplementOf: self.magnitude.storage.elements) + self.storageBitWidthNeeded } + case true: return NBK.nonzeroBitCount(twosComplementOf: self.magnitude.storage) + self.storageBitWidthNeeded } } @inlinable public var leadingZeroBitCount: Int { @@ -84,26 +85,26 @@ extension NBKFlexibleWidth.Magnitude { /// The number of bits in ``words``. @inlinable public var bitWidth: Int { - self.storage.elements.count * UInt.bitWidth + self.storage.count * UInt.bitWidth } @inlinable public var nonzeroBitCount: Int { - NBK.nonzeroBitCount(of: self.storage.elements) + NBK.nonzeroBitCount(of: self.storage) } @inlinable public var leadingZeroBitCount: Int { - self.storage.elements.last?.leadingZeroBitCount ?? Int.zero + self.storage.last.leadingZeroBitCount } @inlinable public var trailingZeroBitCount: Int { - NBK.trailingZeroBitCount(of: self.storage.elements) + NBK.trailingZeroBitCount(of: self.storage) } @inlinable public var mostSignificantBit: Bool { - self.storage.elements.last?.mostSignificantBit ?? false + self.storage.last.mostSignificantBit } @inlinable public var leastSignificantBit: Bool { - self.storage.elements.first?.leastSignificantBit ?? false + self.storage.first.leastSignificantBit } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift index 4b74883e..33687950 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift @@ -8,6 +8,7 @@ //=----------------------------------------------------------------------------= import NBKCoreKit +import NBKResizableWidthKit //*============================================================================* // MARK: * NBK x Flexible Width x Comparisons x Signed @@ -81,8 +82,7 @@ extension NBKFlexibleWidth { //=------------------------------------------------------------------------= @inlinable var isTwosComplementMinValue: Bool { - guard !self.magnitude.storage.elements.isEmpty else { return false } - return self.compared(to: Int.min, at: self.magnitude.storage.elements.count - 1).isZero + self.compared(to: Int.min, at: self.magnitude.storage.lastIndex).isZero } } @@ -118,23 +118,23 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @inlinable public var isZero: Bool { - self.storage.elements.isEmpty + self.storage.isZero } @inlinable public var isLessThanZero: Bool { - false + self.storage.isLessThanZero } @inlinable public var isMoreThanZero: Bool { - !self.isZero + self.storage.isMoreThanZero } @inlinable public var isPowerOf2: Bool { - NBK.nonzeroBitCount(of: self.storage.elements, equals: 1) + self.storage.isPowerOf2 } @inlinable public func signum() -> Int { - Int(bit: !self.isZero) + self.storage.signum() } //=------------------------------------------------------------------------= @@ -158,76 +158,18 @@ extension NBKFlexibleWidth.Magnitude { } @inlinable public func compared(to other: Self) -> Int { - self .storage.elements.withUnsafeBufferPointer { lhs in - other.storage.elements.withUnsafeBufferPointer { rhs in - Self.compareWordsUnchecked(lhs, to: rhs) - }} + self.storage.compared(to: other.storage) } @inlinable public func compared(to other: Self, at index: Int) -> Int { - self .storage.elements.withUnsafeBufferPointer { lhs in - other.storage.elements.withUnsafeBufferPointer { rhs in - Self.compareWordsUnchecked(lhs, to: rhs, at: index) - }} + self.storage.compared(to: other.storage, at: index) } @_disfavoredOverload @inlinable public func compared(to other: Digit) -> Int { - self.storage.elements.withUnsafeBufferPointer { lhs in - Self.withUnsafeWords(of: other) { rhs in - Self.compareWordsUnchecked(lhs, to: rhs) - }} + self.storage.compared(to: other) } @_disfavoredOverload @inlinable public func compared(to other: Digit, at index: Int) -> Int { - self.storage.elements.withUnsafeBufferPointer { lhs in - Self.withUnsafeWords(of: other) { rhs in - Self.compareWordsUnchecked(lhs, to: rhs, at: index) - }} - } -} - -//=----------------------------------------------------------------------------= -// MARK: + Algorithms -//=----------------------------------------------------------------------------= - -extension NBKFlexibleWidth.Magnitude { - - //=------------------------------------------------------------------------= - // MARK: Utilities x Private - //=------------------------------------------------------------------------= - - /// A three-way comparison of `lhs` against `rhs`. - /// - /// - Requires: The last element in `lhs` and `rhs` must not be zero. - /// - @inlinable static func compareWordsUnchecked(_ lhs: NBK.UnsafeWords, to rhs: NBK.UnsafeWords) -> Int { - assert(lhs.last != 0 && rhs.last != 0) - //=--------------------------------------= - if lhs.count != rhs.count { - return lhs.count < rhs.count ? -1 : 1 - } - //=--------------------------------------= - for index in lhs.indices.reversed() { - let lhsWord = lhs[index] as UInt - let rhsWord = rhs[index] as UInt - if lhsWord != rhsWord { return lhsWord < rhsWord ? -1 : 1 } - } - - return Int.zero - } - - /// A three-way comparison of `lhs` against `rhs` at `index`. - /// - /// - Requires: The last element in `lhs` and `rhs` must not be zero. - /// - @inlinable static func compareWordsUnchecked(_ lhs: NBK.UnsafeWords, to rhs: NBK.UnsafeWords, at index: Int) -> Int { - assert(lhs.last != 0 && rhs.last != 0 && index >= 0) - //=--------------------------------------= - let partition = Swift.min(index, lhs.endIndex) - let suffix = NBK.UnsafeWords(rebasing: lhs.suffix(from: partition)) - let comparison = Self.compareWordsUnchecked(suffix, to: rhs) - if !comparison.isZero { return comparison } - let prefix = NBK.UnsafeWords(rebasing: lhs.prefix(upTo: partition)) - return Int(bit: !prefix.allSatisfy({ $0.isZero })) + self.storage.compared(to: other, at: index) } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements+Storage.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements+Storage.swift deleted file mode 100644 index b8fe759d..00000000 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements+Storage.swift +++ /dev/null @@ -1,53 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Flexible Width x Complements x Unsigned x Storage -//*============================================================================* - -extension NBKFlexibleWidth.Magnitude.Storage { - - //=------------------------------------------------------------------------= - // MARK: Details x One's Complement - //=------------------------------------------------------------------------= - - @inlinable public mutating func formOnesComplement() { - for index in self.elements.indices { - self.elements[index].formOnesComplement() - } - } - - @inlinable public func onesComplement() -> Self { - Self(elements: self.elements.map(~)) - } - - //=------------------------------------------------------------------------= - // MARK: Details x Two's Complement - //=------------------------------------------------------------------------= - - @inlinable public mutating func formTwosComplement() { - _ = self.formTwosComplementReportingOverflow() - } - - @inlinable public mutating func formTwosComplementReportingOverflow() -> Bool { - self.formTwosComplementSubsequence(true) - } - - @inlinable public mutating func formTwosComplementSubsequence(_ carry: Bool) -> Bool { - var carry = carry - - for index in self.elements.indices { - carry = self.elements[index].formTwosComplementSubsequence(carry) - } - - return carry as Bool - } -} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements.swift index 1c74ea10..39ff5c27 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements.swift @@ -8,6 +8,7 @@ //=----------------------------------------------------------------------------= import NBKCoreKit +import NBKResizableWidthKit //*============================================================================* // MARK: * NBK x Flexible Width x Complements x Signed diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.swift index e7deed29..167b82ec 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.swift @@ -8,6 +8,7 @@ //=----------------------------------------------------------------------------= import NBKCoreKit +import NBKResizableWidthKit //*============================================================================* // MARK: * NBK x Flexible Width x Division x Digit x Signed @@ -98,13 +99,13 @@ extension NBKFlexibleWidth.Magnitude { } //=--------------------------------------= if other.isZero { - return NBK.bitCast(PVO(self.storage.elements.first ?? UInt.zero, true)) + return NBK.bitCast(PVO(self.storage.first, true)) } //=--------------------------------------= var remainder = UInt.zero - for index in self.storage.elements.indices.reversed() { - (self.storage.elements[index], remainder) = other.dividingFullWidth(HL(remainder, self.storage.elements[index])) + for index in self.storage.indices.reversed() { + (self.storage[index], remainder) = other.dividingFullWidth(HL(remainder, self.storage[index])) } self.storage.normalize() diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift index db0081a2..cfa116ac 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift @@ -8,6 +8,7 @@ //=----------------------------------------------------------------------------= import NBKCoreKit +import NBKResizableWidthKit //*============================================================================* // MARK: * NBK x Flexible Width x Division x Signed @@ -112,8 +113,8 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= // divisor is one word //=--------------------------------------= - if other.storage.elements.count == 1 { - let qr = self.quotientAndRemainder(dividingBy: other.storage.elements.first!) + if other.storage.count == 1 { + let qr = self.quotientAndRemainder(dividingBy: other.storage.first) self.assign(qr.remainder) return PVO(qr.quotient, false) } @@ -133,23 +134,23 @@ extension NBKFlexibleWidth.Magnitude { // shift to clamp approximation //=--------------------------------------= var divisor = other.storage - let shift = divisor.elements.last!.leadingZeroBitCount as Int + let shift = divisor.last.leadingZeroBitCount as Int divisor.bitshiftLeft(words: Int.zero, bits: shift) - let divisorLast0 = divisor.elements[divisor.elements.endIndex - 1] as UInt + let divisorLast0 = divisor[divisor.endIndex - 1] as UInt assert(divisorLast0.mostSignificantBit) - var remainderIndex = self.storage.elements.endIndex - self.storage.elements.append(0) + var remainderIndex = self.storage.endIndex + self.storage.append(0) self.storage.bitshiftLeft(words: Int.zero, bits: shift) //=--------------------------------------= // division: approximate quotient digits //=--------------------------------------= - var quotientIndex = remainderIndex - divisor.elements.endIndex as Int + var quotientIndex = remainderIndex - divisor.endIndex as Int var quotient = Storage.uninitialized(count: quotientIndex + 1) { quotient in loop: repeat { - let remainderLast0 = self.storage.elements[remainderIndex] - self.storage.elements.formIndex(before: &remainderIndex) - let remainderLast1 = self.storage.elements[remainderIndex] + let remainderLast0 = self.storage[remainderIndex] + self.storage.formIndex(before: &remainderIndex) + let remainderLast1 = self.storage[remainderIndex] //=------------------------------= var digit: UInt if divisorLast0 == remainderLast0 { @@ -160,8 +161,8 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------= if !digit.isZero { var overflow = self.storage.subtract(divisor, times: digit, plus: UInt.zero, at: quotientIndex) - while overflow { - let _ = digit.subtractReportingOverflow(1 as UInt) + decrement: while overflow { + _ = digit.subtractReportingOverflow(1 as UInt) overflow = !self.storage.add(divisor, plus: false, at: quotientIndex) } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic+Storage.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic+Storage.swift deleted file mode 100644 index 70ab3170..00000000 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic+Storage.swift +++ /dev/null @@ -1,31 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Flexible Width x Logic x Unsigned x Storage -//*============================================================================* - -extension NBKFlexibleWidth.Magnitude.Storage { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable mutating func formInIntersection(of other: Self, each element: (UInt, UInt) -> UInt) { - self .elements.withUnsafeMutableBufferPointer { lhs in - other.elements.withUnsafeBufferPointer { rhs in - let endIndex = Swift.min(lhs.endIndex, rhs.endIndex) - let lhsIntersection = NBK.UnsafeMutableWords(rebasing: lhs.prefix(upTo: endIndex)) - let rhsIntersection = /*---*/NBK.UnsafeWords(rebasing: rhs.prefix(upTo: endIndex)) - NBK.merge(into: lhsIntersection, from: NBK.UnsafeWords(lhsIntersection), rhsIntersection, each: element) - }} - } -} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift index 8802936f..99d68e8c 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift @@ -8,6 +8,7 @@ //=----------------------------------------------------------------------------= import NBKCoreKit +import NBKResizableWidthKit //*============================================================================* // MARK: * NBK x Flexible Width x Logic x Signed @@ -83,7 +84,7 @@ extension NBKFlexibleWidth.Magnitude { Swift.assert(lhs.storage.isNormal) } //=--------------------------------------= - lhs.storage.resize(maxCount: rhs.storage.elements.count) + lhs.storage.resize(maxCount: rhs.storage.count) lhs.storage.formInIntersection(of: rhs.storage, each: &) lhs.storage.normalize() } @@ -101,7 +102,7 @@ extension NBKFlexibleWidth.Magnitude { Swift.assert(lhs.storage.isNormal) } //=--------------------------------------= - lhs.storage.resize(minCount: rhs.storage.elements.count) + lhs.storage.resize(minCount: rhs.storage.count) lhs.storage.formInIntersection(of: rhs.storage, each: |) } @@ -118,7 +119,7 @@ extension NBKFlexibleWidth.Magnitude { Swift.assert(lhs.storage.isNormal) } //=--------------------------------------= - lhs.storage.resize(minCount: rhs.storage.elements.count) + lhs.storage.resize(minCount: rhs.storage.count) lhs.storage.formInIntersection(of: rhs.storage, each: ^) lhs.storage.normalize() } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Miscellaneous.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Miscellaneous.swift index de4405f0..5ec65987 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Miscellaneous.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Miscellaneous.swift @@ -8,6 +8,7 @@ //=----------------------------------------------------------------------------= import NBKCoreKit +import NBKResizableWidthKit //*============================================================================* // MARK: * NBK x Flexible Width x Miscellaneous x Unsigned @@ -20,12 +21,11 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @inlinable mutating func assignZeroValue() { - self.storage.elements.removeAll(keepingCapacity: true) + self.assign(UInt.zero) } - @inlinable mutating func assign(_ other: UInt) { - self.storage.elements.removeAll(keepingCapacity: true) - guard !other.isZero else { return } - self.storage.elements.append(other) + @inlinable mutating func assign(_ value: UInt) { + self.storage.normalize(assign: value) + Swift.assert(self.storage.isNormal) } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift index 5c2fb038..aca6dd01 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift @@ -8,6 +8,7 @@ //=----------------------------------------------------------------------------= import NBKCoreKit +import NBKResizableWidthKit //*============================================================================* // MARK: * NBK x Flexible Width x Multiplication x Digit x Signed @@ -74,10 +75,10 @@ extension NBKFlexibleWidth.Magnitude { return self.assign(addend) } //=--------------------------------------= - self.storage.reserve(minCount: self.storage.elements.count + 1) + self.storage.reserve(minCount: self.storage.count + 1) let overflow = self.storage.multiply(by: multiplicand, plus: addend) if !overflow.isZero { - self.storage.elements.append(overflow) + self.storage.append(overflow) } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Storage.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Storage.swift deleted file mode 100644 index 47e4214b..00000000 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Storage.swift +++ /dev/null @@ -1,80 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Flexible Width x Multiplication x Digit x Unsigned x Storage -//*============================================================================* - -extension NBKFlexibleWidth.Magnitude.Storage { - - //=------------------------------------------------------------------------= - // MARK: Transformations x Self - //=------------------------------------------------------------------------= - - @inlinable func multipliedFullWidth(by multiplicand: Self) -> Self { - self.multipliedFullWidthByNaiveMethod(by: multiplicand, adding: UInt.zero) - } - - @inlinable func multipliedFullWidthByNaiveMethod(by multiplicand: Self, adding addend: UInt) -> Self { - Self.uninitialized(count: self.elements.count + multiplicand.elements.count) { product in - //=----------------------------------= - // de/init: pointee is trivial - //=----------------------------------= - product.update(repeating: UInt.zero) - //=----------------------------------= - var overflow = addend as UInt - for lhsIndex in self.elements.indices { - let outer = self.elements[lhsIndex] - - for rhsIndex in multiplicand.elements.indices { - let inner = multiplicand.elements[rhsIndex] - var subproduct = outer.multipliedFullWidth(by: inner) - - overflow = UInt(bit: subproduct.low.addReportingOverflow(overflow)) - overflow &+= UInt(bit: product[lhsIndex + rhsIndex].addReportingOverflow(subproduct.low)) - overflow &+= subproduct.high - } - - product[lhsIndex + multiplicand.elements.count] = overflow - overflow = UInt.zero - } - } - } - - //=------------------------------------------------------------------------= - // MARK: Transformations x UInt - //=------------------------------------------------------------------------= - - @inlinable mutating func multiply(by other: UInt, plus addend: UInt) -> UInt { - var overflow = addend - self.multiply(by: other, carrying: &overflow) - return overflow as UInt - } -} - -//=----------------------------------------------------------------------------= -// MARK: + Algorithms -//=----------------------------------------------------------------------------= - -extension NBKFlexibleWidth.Magnitude.Storage { - - //=------------------------------------------------------------------------= - // MARK: Transformations x UInt - //=------------------------------------------------------------------------= - - @inlinable mutating func multiply(by other: UInt, carrying overflow: inout UInt) { - for index in self.elements.indices { - var subproduct = self.elements[index].multipliedFullWidth(by: other) - overflow = UInt(bit: subproduct.low.addReportingOverflow(overflow)) &+ subproduct.high - self.elements[index] = subproduct.low as UInt - } - } -} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift index 293b2e7f..b33a3ec1 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift @@ -8,6 +8,7 @@ //=----------------------------------------------------------------------------= import NBKCoreKit +import NBKResizableWidthKit //*============================================================================* // MARK: * NBK x Flexible Width x Multiplication x Signed diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers+Storage.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers+Storage.swift deleted file mode 100644 index d10a2454..00000000 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers+Storage.swift +++ /dev/null @@ -1,48 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Numbers x Unsigned x Storage -//*============================================================================* - -extension NBKFlexibleWidth.Magnitude.Storage { - - //=------------------------------------------------------------------------= - // MARK: Initializers x Digit - //=------------------------------------------------------------------------= - - @inlinable init(digit: UInt) { - self.init(elements:[digit]) - } - - @inlinable init(digit: UInt, at index: Int) { - self.init(repeating: UInt.zero, count: index + 1) - self.elements[index] = digit - } - - //=------------------------------------------------------------------------= - // MARK: Initializers x Literal - //=------------------------------------------------------------------------= - - @inlinable init(truncating source: StaticBigInt) { - //=--------------------------------------= - let bitWidth = source.bitWidth - let major = NBK .quotientDividingByBitWidthAssumingIsAtLeastZero(bitWidth) - let minor = NBK.remainderDividingByBitWidthAssumingIsAtLeastZero(bitWidth) - let count = major + Int(bit: !minor.isZero) - //=--------------------------------------= - self = Self.uninitialized(count: count) { storage in - for index in storage.indices { - storage[index] = source[index] - } - } - } -} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift index 2ec5dc04..61b10e72 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift @@ -8,6 +8,7 @@ //=----------------------------------------------------------------------------= import NBKCoreKit +import NBKResizableWidthKit //*============================================================================* // MARK: * NBK x Flexible Width x Numbers x Signed diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts+Storage.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts+Storage.swift deleted file mode 100644 index f3177d2c..00000000 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts+Storage.swift +++ /dev/null @@ -1,145 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Flexible Width x Shifts x Unsigned x Storage -//*============================================================================* -//=----------------------------------------------------------------------------= -// MARK: + Left -//=----------------------------------------------------------------------------= - -extension NBKFlexibleWidth.Magnitude.Storage { - - //=------------------------------------------------------------------------= - // MARK: Transformations x Int - //=------------------------------------------------------------------------= - - /// Performs a left shift. - /// - /// - Parameters: - /// - distance: `0 <= distance < self.bitWidth` - /// - @inlinable public mutating func bitshiftLeft(by distance: Int) { - precondition(distance >= 0, NBK.callsiteOutOfBoundsInfo()) - let major = NBK .quotientDividingByBitWidthAssumingIsAtLeastZero(distance) - let minor = NBK.remainderDividingByBitWidthAssumingIsAtLeastZero(distance) - return self.bitshiftLeft(words: major, bits: minor) - } - - /// Performs a left shift. - /// - /// - Parameters: - /// - words: `0 <= words < self.endIndex` - /// - bits: `0 <= bits  < UInt.bitWidth` - /// - @inlinable public mutating func bitshiftLeft(words: Int, bits: Int) { - //=--------------------------------------= - if bits.isZero { - return self.bitshiftLeft(words: words) - } - //=--------------------------------------= - self.bitshiftLeft(words: words, atLeastOneBit: bits) - } - - /// Performs a left shift. - /// - /// - Parameters: - /// - words: `0 <= words < self.endIndex` - /// - @inlinable public mutating func bitshiftLeft(words: Int) { - //=--------------------------------------= - if words.isZero { return } - //=--------------------------------------= - self.bitshiftLeft(atLeastOneWord: words) - } - - //=------------------------------------------------------------------------= - // MARK: Transformations x Int x Private - //=------------------------------------------------------------------------= - - @inlinable mutating func bitshiftLeft(words: Int, atLeastOneBit bits: Int) { - self.elements.withUnsafeMutableBufferPointer { - NBK.bitshiftLeftAsFixedLimbsCodeBlock(&$0, environment: false, limbs: words, atLeastOneBit: bits) - } - } - - @inlinable mutating func bitshiftLeft(atLeastOneWord words: Int) { - self.elements.withUnsafeMutableBufferPointer { - NBK.bitshiftLeftAsFixedLimbsCodeBlock(&$0, environment: false, atLeastOneLimb: words) - } - } -} - -//=----------------------------------------------------------------------------= -// MARK: + Right -//=----------------------------------------------------------------------------= - -extension NBKFlexibleWidth.Magnitude.Storage { - - //=------------------------------------------------------------------------= - // MARK: Transformations x Right - //=------------------------------------------------------------------------= - - /// Performs an un/signed right shift. - /// - /// - Parameters: - /// - distance: `0 <= distance < self.bitWidth` - /// - @inlinable public mutating func bitshiftRight(by distance: Int) { - precondition(distance >= 0, NBK.callsiteOutOfBoundsInfo()) - let major = NBK .quotientDividingByBitWidthAssumingIsAtLeastZero(distance) - let minor = NBK.remainderDividingByBitWidthAssumingIsAtLeastZero(distance) - return self.bitshiftRight(words: major, bits: minor) - } - - /// Performs an un/signed right shift. - /// - /// - Parameters: - /// - words: `0 <= words < self.endIndex` - /// - bits: `0 <= bits  < UInt.bitWidth` - /// - @inlinable public mutating func bitshiftRight(words: Int, bits: Int) { - //=--------------------------------------= - if bits.isZero { - return self.bitshiftRight(words: words) - } - //=--------------------------------------= - self.bitshiftRight(words: words, atLeastOneBit: bits) - } - - /// Performs an un/signed right shift. - /// - /// - Parameters: - /// - words: `0 <= words < self.endIndex` - /// - @inlinable public mutating func bitshiftRight(words: Int) { - //=--------------------------------------= - if words.isZero { return } - //=--------------------------------------= - self.bitshiftRight(atLeastOneWord: words) - } - - //=------------------------------------------------------------------------= - // MARK: Transformations x Int x Private - //=------------------------------------------------------------------------= - - @inlinable mutating func bitshiftRight(words: Int, atLeastOneBit bits: Int) { - self.elements.withUnsafeMutableBufferPointer { - NBK.bitshiftRightAsFixedLimbsCodeBlock(&$0, environment: false, limbs: words, atLeastOneBit: bits) - } - } - - @inlinable mutating func bitshiftRight(atLeastOneWord words: Int) { - self.elements.withUnsafeMutableBufferPointer { - NBK.bitshiftRightAsFixedLimbsCodeBlock(&$0, environment: false, atLeastOneLimb: words) - } - } -} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift index 0233c2e7..9a867ae2 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift @@ -8,6 +8,7 @@ //=----------------------------------------------------------------------------= import NBKCoreKit +import NBKResizableWidthKit //*============================================================================* // MARK: * NBK x Flexible Width x Shifts x Signed @@ -210,7 +211,7 @@ extension NBKFlexibleWidth.Magnitude { } //=--------------------------------------= let rollover = Int(bit: self.leadingZeroBitCount < bits) - self.storage.resize(minCount: self.storage.elements.count + words + rollover) + self.storage.resize(minCount: self.storage.count + words + rollover) self.storage.bitshiftLeft(words: words, atLeastOneBit: bits) } @@ -231,7 +232,7 @@ extension NBKFlexibleWidth.Magnitude { return } //=--------------------------------------= - self.storage.resize(minCount: self.storage.elements.count + words) + self.storage.resize(minCount: self.storage.count + words) self.storage.bitshiftLeft(atLeastOneWord: words) } @@ -294,13 +295,15 @@ extension NBKFlexibleWidth.Magnitude { return self.bitshiftRight(words: words) } //=--------------------------------------= - if self.storage.elements.count <= words { + let rollover = Int(bit: bits + self.leadingZeroBitCount - UInt.bitWidth >= 0) + let maxCount = self.storage.count - words - rollover + //=--------------------------------------= + if maxCount < 1 { return self.assignZeroValue() } //=--------------------------------------= - let rollover = Int(bit: bits + self.leadingZeroBitCount - UInt.bitWidth >= 0) self.storage.bitshiftRight(words: words, atLeastOneBit: bits) - self.storage.resize(maxCount: self.storage.elements.count - words - rollover) + self.storage.resize(maxCount: maxCount) } @inlinable public func bitshiftedRight(words: Int, bits: Int) -> Self { @@ -316,12 +319,12 @@ extension NBKFlexibleWidth.Magnitude { return } //=--------------------------------------= - if self.storage.elements.count <= words { + if self.storage.count <= words { return self.assignZeroValue() } //=--------------------------------------= - self.storage.bitshiftRight(atLeastOneWord: words) - self.storage.resize(maxCount: self.storage.elements.count - words) + self.storage.bitshiftRight(words: words) + self.storage.resize(maxCount: self.storage.count - words) } @inlinable public func bitshiftedRight(words: Int) -> Self { diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Storage.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Storage.swift deleted file mode 100644 index 4a7ba498..00000000 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Storage.swift +++ /dev/null @@ -1,64 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Flexible Width x Storage x Unsigned -//*============================================================================* - -extension NBKFlexibleWidth.Magnitude.Storage { - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - @inlinable init(_ elements: some Sequence) { - self.init(elements: Elements(elements)) - } - - @inlinable init(repeating element: UInt, count: Int) { - self.init(elements: Elements(repeating: element, count: count)) - } - - //=------------------------------------------------------------------------= - // MARK: Accessors - //=------------------------------------------------------------------------= - - @inlinable var isNormal: Bool { - self.elements.last != 0 as UInt - } - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable mutating func normalize() { - trimming: while self.elements.last == 0 as UInt { - self.elements.removeLast() - } - } - - @inlinable mutating func resize(maxCount: Int) { - if self.elements.count > maxCount { - self.elements.removeSubrange(maxCount...) - } - } - - @inlinable mutating func resize(minCount: Int) { - self.reserve(minCount: minCount) - appending: while self.elements.count < minCount { - self.elements.append(UInt.zero) - } - } - - @inlinable mutating func reserve(minCount: Int) { - self.elements.reserveCapacity(minCount) - } -} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift index 4bd5fc07..33881815 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift @@ -8,6 +8,7 @@ //=----------------------------------------------------------------------------= import NBKCoreKit +import NBKResizableWidthKit //*============================================================================* // MARK: * NBK x Flexible Width x Subtraction x Digit x Signed diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Storage.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Storage.swift deleted file mode 100644 index 0150b936..00000000 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Storage.swift +++ /dev/null @@ -1,112 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Flexible Width x Subtraction x Unsigned x Storage -//*============================================================================* - -extension NBKFlexibleWidth.Magnitude.Storage { - - //=------------------------------------------------------------------------= - // MARK: Transformations x Self - //=------------------------------------------------------------------------= - - @inlinable mutating func subtract(_ other: Self, plus addend: Bool, at index: Int) -> Bool { - var index = index, overflow = addend - self.subtract(other, at: &index, borrowing: &overflow) - return overflow as Bool - } - - //=------------------------------------------------------------------------= - // MARK: Transformations x UInt - //=------------------------------------------------------------------------= - - @inlinable mutating func subtract(_ other: UInt, plus addend: Bool, at index: Int) -> Bool { - var index = index, overflow = addend - self.subtract(other, at: &index, borrowing: &overflow) - return overflow as Bool - } - - //=------------------------------------------------------------------------= - // MARK: Transformations x Multiplication By UInt - //=------------------------------------------------------------------------= - - // TODO: test cases - @inlinable mutating func subtract(_ other: Self, times multiplicand: UInt, plus addend: UInt, at index: Int) -> Bool { - var index = index - var overflow = false - var last = addend as UInt - - for otherIndex in other.elements.indices { - var subproduct = other.elements[otherIndex].multipliedFullWidth(by: multiplicand) - last = UInt(bit: subproduct.low.addReportingOverflow(last)) &+ subproduct.high - self.subtractWithoutGoingBeyond(subproduct.low, at: &index, borrowing: &overflow) - } - - return self.subtract(last, plus: overflow, at: index) - } -} - -//=----------------------------------------------------------------------------= -// MARK: + Algorithms -//=----------------------------------------------------------------------------= - -extension NBKFlexibleWidth.Magnitude.Storage { - - //=------------------------------------------------------------------------= - // MARK: Transformations x Self - //=------------------------------------------------------------------------= - - @inlinable mutating func subtract(_ other: Self, at index: inout Int, borrowing overflow: inout Bool) { - self.subtractWithoutGoingBeyond(other, at: &index, borrowing: &overflow) - self.subtract((), at: &index, borrowing: &overflow) - } - - @inlinable mutating func subtractWithoutGoingBeyond(_ other: Self, at index: inout Int, borrowing overflow: inout Bool) { - for otherIndex in other.elements.indices { // for-index-in >= for-element-in - self.subtractWithoutGoingBeyond(other.elements[otherIndex], at: &index, borrowing: &overflow) - } - } - - //=------------------------------------------------------------------------= - // MARK: Transformations x UInt - //=------------------------------------------------------------------------= - - @inlinable mutating func subtract(_ other: UInt, at index: inout Int, borrowing overflow: inout Bool) { - self.subtractWithoutGoingBeyond(other, at: &index, borrowing: &overflow) - self.subtract((), at: &index, borrowing: &overflow) - } - - @inlinable mutating func subtractWithoutGoingBeyond(_ other: UInt, at index: inout Int, borrowing overflow: inout Bool) { - var other = other as UInt - - if overflow { - overflow = other.addReportingOverflow(1 as UInt) - } - - if !overflow { - overflow = self.elements[index].subtractReportingOverflow(other) - } - - self.elements.formIndex(after: &index) - } - - //=------------------------------------------------------------------------= - // MARK: Transformations x Void - //=------------------------------------------------------------------------= - - @inlinable mutating func subtract(_ other: Void, at index: inout Int, borrowing overflow: inout Bool) { - while overflow && index < self.elements.endIndex { - overflow = self.elements[index].subtractReportingOverflow(1 as UInt) - self.elements.formIndex(after: &index) - } - } -} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift index 24bf5fdd..a443026b 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift @@ -8,6 +8,7 @@ //=----------------------------------------------------------------------------= import NBKCoreKit +import NBKResizableWidthKit //*============================================================================* // MARK: * NBK x Flexible Width x Subtraction @@ -93,7 +94,7 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= if other.isZero { return false } //=--------------------------------------= - self.storage.resize(minCount: other.storage.elements.count + index) + self.storage.resize(minCount: other.storage.count + index) defer{ self.storage.normalize() } return self.storage.subtract(other.storage, plus: false, at: index) } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text+Radix.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text+Radix.swift index aaa1e9c3..11d28b03 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text+Radix.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text+Radix.swift @@ -8,6 +8,7 @@ //=----------------------------------------------------------------------------= import NBKCoreKit +import NBKResizableWidthKit //*============================================================================* // MARK: * NBK x Flexible Width x Text x Radix x Signed @@ -110,6 +111,8 @@ extension NBKFlexibleWidth.Magnitude { let division = digits.count.quotientAndRemainder(dividingBy: radix.exponent) let count = division.quotient + Int(bit: !division.remainder.isZero) //=--------------------------------------= + guard count.isMoreThanZero else { self = Self.zero; return } + //=--------------------------------------= var error = false let value = Storage.uninitialized(count: count) { storage in for index in storage.indices { @@ -162,7 +165,7 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= // with one buffer pointer specialization //=--------------------------------------= - return self.storage.elements.withUnsafeBufferPointer { buffer in + return self.storage.withContiguousStorage { buffer in let chunks = NBK.UnsafeWords(rebasing: NBK.dropLast(from: buffer, while: { $0.isZero })) return NBK.integerTextUnchecked(chunks: chunks, radix: radix, alphabet: alphabet, prefix: prefix, suffix: suffix) } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Uninitialized.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Uninitialized.swift deleted file mode 100644 index a5371b47..00000000 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Uninitialized.swift +++ /dev/null @@ -1,31 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Flexible Width x Uninitialized x Unsigned x Storage -//*============================================================================* - -extension NBKFlexibleWidth.Magnitude.Storage { - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - @inlinable static func uninitialized(count: Int, body: (NBK.UnsafeMutableWords) -> Void) -> Self { - let elements = Elements(unsafeUninitializedCapacity: count) { - elements, endIndex in - body(NBK.UnsafeMutableWords(rebasing: elements.prefix(upTo: count))) - endIndex = count as Int - } - - return Self(elements: elements) - } -} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift index fbda136e..69897b66 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift @@ -8,6 +8,7 @@ //=----------------------------------------------------------------------------= import NBKCoreKit +import NBKResizableWidthKit //*============================================================================* // MARK: * NBK x Flexible Width x Words x Signed @@ -23,16 +24,17 @@ extension NBKFlexibleWidth { /// /// - Note: An empty collection defaults to positive zero. /// - @inlinable public init(words: some RandomAccessCollection) { + @inlinable public init(words: some Collection) { + var magnitude = Magnitude.Storage(words: words) + let sign = Sign(magnitude.last.mostSignificantBit) //=--------------------------------------= - let last = words.last ?? UInt.zero + if sign.bit { + magnitude.formTwosComplement() + } //=--------------------------------------= - self.init(sign: Sign.plus, magnitude: Magnitude(words: words)) + magnitude.normalize() //=--------------------------------------= - if last.mostSignificantBit { - self.sign.toggle() - self.magnitude.formTwosComplement() - } + self.init(sign: sign, magnitude: Magnitude(unchecked: magnitude)) } //=------------------------------------------------------------------------= @@ -48,12 +50,9 @@ extension NBKFlexibleWidth { //=------------------------------------------------------------------------= @inlinable var storageNeedsOneMoreWord: Bool { - //=--------------------------------------= - if self.magnitude.storage.elements.isEmpty { return true } - //=--------------------------------------= - switch self.sign { - case .plus : return self.magnitude.storage.elements.last!.mostSignificantBit - case .minus: return !NBK.mostSignificantBit(twosComplementOf: self.magnitude.storage.elements)! } + switch self.isLessThanZero { + case false: return self.magnitude.storage.last.mostSignificantBit + case true: return !NBK.mostSignificantBit(twosComplementOf: self.magnitude.storage)! } } //*========================================================================* @@ -83,7 +82,7 @@ extension NBKFlexibleWidth { self.storage.formTwosComplement() } //=----------------------------------= - self.count += self.storage.elements.count + self.count += self.storage.count } //=--------------------------------------------------------------------= @@ -99,8 +98,8 @@ extension NBKFlexibleWidth { } @inlinable public subscript(index: Int) -> UInt { - switch index < self.storage.elements.endIndex { - case true: return self.storage.elements[index] + switch index < self.storage.endIndex { + case true: return self.storage[index] case false: return self.sign } } @@ -109,31 +108,31 @@ extension NBKFlexibleWidth { //=--------------------------------------------------------------------= @inlinable public func distance(from start: Int, to end: Int) -> Int { - self.storage.elements.distance(from: start, to: end) + self.storage.distance(from: start, to: end) } @inlinable public func index(after index: Int) -> Int { - self.storage.elements.index(after: index) + self.storage.index(after: index) } @inlinable public func formIndex(after index: inout Int) { - self.storage.elements.formIndex(after: &index) + self.storage.formIndex(after: &index) } @inlinable public func index(before index: Int) -> Int { - self.storage.elements.index(before: index) + self.storage.index(before: index) } @inlinable public func formIndex(before index: inout Int) { - self.storage.elements.formIndex(before: &index) + self.storage.formIndex(before: &index) } @inlinable public func index(_ index: Int, offsetBy distance: Int) -> Int { - self.storage.elements.index(index, offsetBy: distance) + self.storage.index(index, offsetBy: distance) } @inlinable public func index(_ index: Int, offsetBy distance: Int, limitedBy limit: Int) -> Int? { - self.storage.elements.index(index, offsetBy: distance, limitedBy: limit) + self.storage.index(index, offsetBy: distance, limitedBy: limit) } } } @@ -148,109 +147,15 @@ extension NBKFlexibleWidth.Magnitude { // MARK: Initializers //=------------------------------------------------------------------------= - @inlinable public init(words: some RandomAccessCollection) { - var storage = Storage(words) - storage.normalize() - self.init(unchecked: storage) + @inlinable public init(words: some Collection) { + self.init(storage: Storage(words: words)) } //=------------------------------------------------------------------------= // MARK: Accessors //=------------------------------------------------------------------------= - @inlinable public var words: Words { - Words(source: self) - } - - //*========================================================================* - // MARK: * Words - //*========================================================================* - - @frozen public struct Words: RandomAccessCollection { - - //=--------------------------------------------------------------------= - // MARK: State - //=--------------------------------------------------------------------= - - @usableFromInline let storage: Magnitude.Storage - - //=--------------------------------------------------------------------= - // MARK: Initializers - //=--------------------------------------------------------------------= - - @inlinable init(source: Magnitude) { - self.storage = source.storage - } - - //=--------------------------------------------------------------------= - // MARK: Accessors - //=--------------------------------------------------------------------= - - @inlinable public var count: Int { - self.storage.elements.count - } - - @inlinable public var startIndex: Int { - (0 as Int) - } - - @inlinable public var endIndex: Int { - self.count - } - - @inlinable public subscript(index: Int) -> UInt { - switch index < self.storage.elements.endIndex { - case true: return self.storage.elements[index] - case false: return UInt.zero } - } - - //=--------------------------------------------------------------------= - // MARK: Utilities - //=--------------------------------------------------------------------= - - @inlinable public func distance(from start: Int, to end: Int) -> Int { - self.storage.elements.distance(from: start, to: end) - } - - @inlinable public func index(after index: Int) -> Int { - self.storage.elements.index(after: index) - } - - @inlinable public func formIndex(after index: inout Int) { - self.storage.elements.formIndex(after: &index) - } - - @inlinable public func index(before index: Int) -> Int { - self.storage.elements.index(before: index) - } - - @inlinable public func formIndex(before index: inout Int) { - self.storage.elements.formIndex(before: &index) - } - - @inlinable public func index(_ index: Int, offsetBy distance: Int) -> Int { - self.storage.elements.index(index, offsetBy: distance) - } - - @inlinable public func index(_ index: Int, offsetBy distance: Int, limitedBy limit: Int) -> Int? { - self.storage.elements.index(index, offsetBy: distance, limitedBy: limit) - } - } -} - -//=----------------------------------------------------------------------------= -// MARK: + Algorithms -//=----------------------------------------------------------------------------= - -extension NBKFlexibleWidth.Magnitude { - - //=------------------------------------------------------------------------= - // MARK: Utilities x Private - //=------------------------------------------------------------------------= - - @inlinable static func withUnsafeWords(of digit: Digit, perform body: (NBK.UnsafeWords) -> T) -> T { - Swift.withUnsafePointer(to: digit) { - body(NBK.UnsafeWords(start: $0, count: Int(bit: !$0.pointee.isZero))) - } + @inlinable public var words: UIntXR.Words { + _read { yield self.storage.words } } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift index 100cd9af..05e63b42 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift @@ -8,6 +8,7 @@ //=----------------------------------------------------------------------------= import NBKCoreKit +import NBKResizableWidthKit //*============================================================================* // MARK: * NBK x Flexible Width @@ -53,6 +54,8 @@ import NBKCoreKit public typealias Digit = UInt + @usableFromInline typealias Storage = NBKResizableWidth.Magnitude + //=--------------------------------------------------------------------= // MARK: State //=--------------------------------------------------------------------= @@ -73,31 +76,6 @@ import NBKCoreKit self.storage = unchecked Swift.assert(self.storage.isNormal) } - - //*====================================================================* - // MARK: * Storage - //*====================================================================* - - /// A contiguous collection of machine words. - /// - /// - Note: It's methods have fixed-width semantics unless stated otherwise. - /// - @frozen @usableFromInline struct Storage: Hashable { - - @usableFromInline typealias Elements = Array - - //=----------------------------------------------------------------= - // MARK: State - //=----------------------------------------------------------------= - - @usableFromInline var elements: Elements - - //=----------------------------------------------------------------= - // MARK: Initializers - //=----------------------------------------------------------------= - - @inlinable init(elements: Elements) { self.elements = elements } - } } } diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Comparisons.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Comparisons.swift new file mode 100644 index 00000000..d16c3fff --- /dev/null +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Comparisons.swift @@ -0,0 +1,138 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Resizable Width x Comparisons x Unsigned +//*============================================================================* + +extension NBKResizableWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Accessors + //=------------------------------------------------------------------------= + + @inlinable public var isZero: Bool { + self.count == 1 && self.first.isZero + } + + @inlinable public var isLessThanZero: Bool { + false + } + + @inlinable public var isMoreThanZero: Bool { + !self.isZero + } + + @inlinable public var isPowerOf2: Bool { + NBK.nonzeroBitCount(of: self.storage, equals: 1) + } + + @inlinable public func signum() -> Int { + Int(bit: !self.isZero) + } + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + @inlinable public func hash(into hasher: inout Hasher) { + hasher.combine(self.storage) + } + + @inlinable public func compared(to other: Self) -> Int { + self .withContiguousStorage { lhs in + other.withContiguousStorage { rhs in + Self.compareWordsUnchecked(lhs, to: rhs) + }} + } + + @inlinable public func compared(to other: Self, at index: Int) -> Int { + self .withContiguousStorage { lhs in + other.withContiguousStorage { rhs in + Self.compareWordsUnchecked(lhs, to: rhs, at: index) + }} + } + + @_disfavoredOverload @inlinable public func compared(to other: Digit) -> Int { + self.withContiguousStorage { lhs in + Self.withUnsafeWords(of: other) { rhs in + Self.compareWordsUnchecked(lhs, to: rhs) + }} + } + + @_disfavoredOverload @inlinable public func compared(to other: Digit, at index: Int) -> Int { + self.withContiguousStorage { lhs in + Self.withUnsafeWords(of: other) { rhs in + Self.compareWordsUnchecked(lhs, to: rhs, at: index) + }} + } +} + +//=----------------------------------------------------------------------------= +// MARK: + Algorithms +//=----------------------------------------------------------------------------= + +extension NBKResizableWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Utilities x Private + //=------------------------------------------------------------------------= + + /// A three-way comparison of `lhs` against `rhs` at `index`. + /// + /// - Requires: The last element in `lhs` and `rhs` must not be zero. + /// + @inlinable static func compareWordsUnchecked(_ lhs: NBK.UnsafeWords, to rhs: NBK.UnsafeWords, at index: Int) -> Int { + let partition = Swift.min(index, lhs.endIndex) + let suffix = NBK.UnsafeWords(rebasing: lhs.suffix(from: partition)) + let comparison = Self.compareWordsUnchecked(suffix, to: rhs) + if !comparison.isZero { return comparison } + let prefix = NBK.UnsafeWords(rebasing: lhs.prefix(upTo: partition)) + return Int(bit: !prefix.allSatisfy({ $0.isZero })) + } + + /// A three-way comparison of `lhs` against `rhs`. + @inlinable static func compareWordsUnchecked(_ lhs: NBK.UnsafeWords, to rhs: NBK.UnsafeWords) -> Int { + let lhs = NBK.UnsafeWords(rebasing: NBK.dropLast(from: lhs, while:{ $0.isZero })) + let rhs = NBK.UnsafeWords(rebasing: NBK.dropLast(from: rhs, while:{ $0.isZero })) + return Self.compareMinTwosComplementWordsUnchecked(lhs, to: rhs) + } + + /// A three-way comparison of `lhs` against `rhs`. + /// + /// - Requires: The last element in `lhs` and `rhs` must not be zero. + /// + @inlinable static func compareMinTwosComplementWordsUnchecked(_ lhs: NBK.UnsafeWords, to rhs: NBK.UnsafeWords) -> Int { + assert(lhs.last != 0 && rhs.last != 0) + //=--------------------------------------= + if lhs.count != rhs.count { + return lhs.count < rhs.count ? -1 : 1 + } + //=--------------------------------------= + return Self.compareSameSizeWordsUnchecked(lhs, to: rhs) + } + + /// A three-way comparison of `lhs` against `rhs`. + /// + /// - Requires: The number of elements in `lhs` and `rhs` must be equal. + /// + @inlinable static func compareSameSizeWordsUnchecked(_ lhs: NBK.UnsafeWords, to rhs: NBK.UnsafeWords) -> Int { + assert(lhs.count == rhs.count) + + for index in lhs.indices.reversed() { + let lhsWord = lhs[index] as UInt + let rhsWord = rhs[index] as UInt + if lhsWord != rhsWord { return lhsWord < rhsWord ? -1 : 1 } + } + + return Int.zero + } +} diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Complements.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Complements.swift index c2702357..04392d82 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Complements.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Complements.swift @@ -26,7 +26,7 @@ extension NBKResizableWidth.Magnitude { } @inlinable public func onesComplement() -> Self { - Self(unchecked: self.storage.map(~)) + Self(unchecked: Storage(self.storage.lazy.map(~))) } //=------------------------------------------------------------------------= diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Logic.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Logic.swift index b50f9211..8b314d86 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Logic.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Logic.swift @@ -19,12 +19,13 @@ extension NBKResizableWidth.Magnitude { // MARK: Transformations //=------------------------------------------------------------------------= - @inlinable mutating func formInIntersection(of other: Self, each element: (UInt, UInt) -> UInt) { + // TODO: internal + @inlinable public mutating func formInIntersection(of other: Self, each element: (UInt, UInt) -> UInt) { self .storage.withUnsafeMutableBufferPointer { lhs in other.storage.withUnsafeBufferPointer { rhs in let endIndex = Swift.min(lhs.endIndex, rhs.endIndex) - let lhsIntersection = NBK.UnsafeMutableWords(rebasing: lhs.prefix(upTo: endIndex)) - let rhsIntersection = /*---*/NBK.UnsafeWords(rebasing: rhs.prefix(upTo: endIndex)) + let lhsIntersection = NBK.UnsafeMutableWords(rebasing: lhs.prefix(upTo: endIndex)) + let rhsIntersection = /*---*/NBK.UnsafeWords(rebasing: rhs.prefix(upTo: endIndex)) NBK.merge(into: lhsIntersection, from: NBK.UnsafeWords(lhsIntersection), rhsIntersection, each: element) }} } diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Multiplication+Digit.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Multiplication+Digit.swift index 01011fa3..e7ead09a 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Multiplication+Digit.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Multiplication+Digit.swift @@ -39,7 +39,7 @@ extension NBKResizableWidth.Magnitude { @inlinable mutating func multiply(by other: UInt, carrying overflow: inout UInt) { for index in self.storage.indices { var subproduct = self.storage[index].multipliedFullWidth(by: other) - overflow = UInt(bit: subproduct.low.addReportingOverflow(overflow)) &+ subproduct.high + overflow = UInt(bit: subproduct.low.addReportingOverflow(overflow)) &+ subproduct.high self.storage[index] = subproduct.low as UInt } } diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Numbers.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Numbers.swift index 72748575..5b1cb877 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Numbers.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Numbers.swift @@ -19,11 +19,11 @@ extension NBKResizableWidth.Magnitude { // MARK: Initializers x Digit //=------------------------------------------------------------------------= - @inlinable init(digit: UInt) { + @inlinable public init(digit: UInt) { self.init(unchecked:[digit]) } - @inlinable init(digit: UInt, at index: Int) { + @inlinable public init(digit: UInt, at index: Int) { self.init(repeating: UInt.zero, count: index + 1) self.storage[index] = digit } @@ -31,8 +31,9 @@ extension NBKResizableWidth.Magnitude { //=------------------------------------------------------------------------= // MARK: Initializers x Literal //=------------------------------------------------------------------------= - - @inlinable init(truncating source: StaticBigInt) { + + // TODO: internal + @inlinable public init(truncating source: StaticBigInt) { //=--------------------------------------= let bitWidth = source.bitWidth let major = NBK .quotientDividingByBitWidthAssumingIsAtLeastZero(bitWidth) diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Shifts.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Shifts.swift index 45d1a3d2..831eb76f 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Shifts.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Shifts.swift @@ -65,13 +65,15 @@ extension NBKResizableWidth.Magnitude { // MARK: Transformations x Int x Private //=------------------------------------------------------------------------= - @inlinable mutating func bitshiftLeft(words: Int, atLeastOneBit bits: Int) { + // TODO: internal + @inlinable public mutating func bitshiftLeft(words: Int, atLeastOneBit bits: Int) { self.storage.withUnsafeMutableBufferPointer { NBK.bitshiftLeftAsFixedLimbsCodeBlock(&$0, environment: false, limbs: words, atLeastOneBit: bits) } } - @inlinable mutating func bitshiftLeft(atLeastOneWord words: Int) { + // TODO: internal + @inlinable public mutating func bitshiftLeft(atLeastOneWord words: Int) { self.storage.withUnsafeMutableBufferPointer { NBK.bitshiftLeftAsFixedLimbsCodeBlock(&$0, environment: false, atLeastOneLimb: words) } @@ -131,13 +133,15 @@ extension NBKResizableWidth.Magnitude { // MARK: Transformations x Int x Private //=------------------------------------------------------------------------= - @inlinable mutating func bitshiftRight(words: Int, atLeastOneBit bits: Int) { + // TODO: internal + @inlinable public mutating func bitshiftRight(words: Int, atLeastOneBit bits: Int) { self.storage.withUnsafeMutableBufferPointer { NBK.bitshiftRightAsFixedLimbsCodeBlock(&$0, environment: false, limbs: words, atLeastOneBit: bits) } } - @inlinable mutating func bitshiftRight(atLeastOneWord words: Int) { + // TODO: internal + @inlinable public mutating func bitshiftRight(atLeastOneWord words: Int) { self.storage.withUnsafeMutableBufferPointer { NBK.bitshiftRightAsFixedLimbsCodeBlock(&$0, environment: false, atLeastOneLimb: words) } diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Size.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Size.swift index cebfc458..abd35271 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Size.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Size.swift @@ -16,9 +16,13 @@ import NBKCoreKit extension NBKResizableWidth.Magnitude { //=------------------------------------------------------------------------= - // MARK: Details x Count + // MARK: Details x Resize //=------------------------------------------------------------------------= + @inlinable public mutating func append(_ word: UInt) { + self.storage.append(word) + } + @inlinable public mutating func reserve(minCount: Int) { self.storage.reserveCapacity(minCount) } @@ -31,10 +35,12 @@ extension NBKResizableWidth.Magnitude { } @inlinable public mutating func resize(maxCount: Int) { - precondition(!maxCount.isMoreThanZero, "\(Self.description) must contain at least one word") + //=--------------------------------------= if self.storage.count > maxCount { self.storage.removeSubrange(maxCount...) } + //=--------------------------------------= + precondition(self.isOK, Self.callsiteInvariantsInfo()) } //=------------------------------------------------------------------------= @@ -50,4 +56,9 @@ extension NBKResizableWidth.Magnitude { self.storage.removeLast() } } + + @inlinable public mutating func normalize(assign value: UInt) { + self.storage.removeAll(keepingCapacity: true) + self.storage.append(value) + } } diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Uninitialized.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Uninitialized.swift index c033bfe9..09044713 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Uninitialized.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Uninitialized.swift @@ -20,7 +20,7 @@ extension NBKResizableWidth.Magnitude { //=------------------------------------------------------------------------= // TODO: measure (inout Self) -> Void - @inlinable static func uninitialized(count: Int, body: (NBK.UnsafeMutableWords) -> Void) -> Self { + @inlinable public static func uninitialized(count: Int, body: (NBK.UnsafeMutableWords) -> Void) -> Self { let storage = Storage(unsafeUninitializedCapacity: count) { storage, endIndex in body(NBK.UnsafeMutableWords(rebasing: storage.prefix(upTo: count))) diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Words+Pointers.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Words+Pointers.swift new file mode 100644 index 00000000..9e7f2159 --- /dev/null +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Words+Pointers.swift @@ -0,0 +1,58 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Resizable Width x Words x Pointers x Unsigned +//*============================================================================* + +extension NBKResizableWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Details x Contiguous UInt Collection + //=------------------------------------------------------------------------= + + /// Grants unsafe access to the collection's contiguous storage. + /// + /// The elements of the contiguous storage appear in the order of the collection. + /// + @inlinable public func withContiguousStorage(_ body: (NBK.UnsafeWords) throws -> T) rethrows -> T { + try self.storage.withUnsafeBufferPointer(body) + } + + /// Grants unsafe access to the collection's contiguous storage. + /// + /// The elements of the contiguous storage appear in the order of the collection. + /// + /// - Note: This member is required by `Swift.Sequence`. + /// + @inlinable public func withContiguousStorageIfAvailable(_ body: (NBK.UnsafeWords) throws -> T) rethrows -> T? { + try self.withContiguousStorage(body) + } + + /// Grants unsafe access to the collection's contiguous mutable storage. + /// + /// The elements of the contiguous mutable storage appear in the order of the collection. + /// + @inlinable public mutating func withContiguousMutableStorage(_ body: (inout NBK.UnsafeMutableWords) throws -> T) rethrows -> T { + try self.storage.withUnsafeMutableBufferPointer(body) + + } + + /// Grants unsafe access to the collection's contiguous mutable storage. + /// + /// The elements of the contiguous mutable storage appear in the order of the collection. + /// + /// - Note: This member is required by `Swift.MutableCollection`. + /// + @inlinable public mutating func withContiguousMutableStorageIfAvailable(_ body: (inout NBK.UnsafeMutableWords) throws -> T) rethrows -> T? { + try self.withContiguousMutableStorage(body) + } +} diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Words.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Words.swift index 69110281..1e24fee9 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Words.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Words.swift @@ -144,3 +144,20 @@ extension NBKResizableWidth.Magnitude { _modify { yield &self.storage[index] } } } + +//=----------------------------------------------------------------------------= +// MARK: + Algorithms +//=----------------------------------------------------------------------------= + +extension NBKResizableWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Utilities x Private + //=------------------------------------------------------------------------= + + @inlinable static func withUnsafeWords(of digit: Digit, perform body: (NBK.UnsafeWords) -> T) -> T { + Swift.withUnsafePointer(to: digit) { + body(NBK.UnsafeWords(start: $0, count: 1)) + } + } +} diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth.swift index 249009b9..623c9fe1 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth.swift @@ -18,7 +18,9 @@ import NBKCoreKit public typealias Digit = Int - @usableFromInline typealias Storage = Array + public typealias Words = Self + + @usableFromInline typealias Storage = ContiguousArray //=------------------------------------------------------------------------= // MARK: State @@ -32,12 +34,26 @@ import NBKCoreKit @inlinable init(storage: Storage) { self.storage = storage - precondition(!self.storage.isEmpty, "\(Self.description) must contain at least one word") + precondition(self.isOK, Self.callsiteInvariantsInfo()) } @inlinable init(unchecked storage: Storage) { self.storage = storage - Swift.assert(!self.storage.isEmpty, "\(Self.description) must contain at least one word") + Swift.assert(self.isOK, Self.callsiteInvariantsInfo()) + } + + //=------------------------------------------------------------------------= + // MARK: Invariants + //=------------------------------------------------------------------------= + + /// Returns whether its invariants are kept. + @inlinable var isOK: Bool { + !self.storage.isEmpty + } + + /// Returns a description of the invariants that must be kept. + @inlinable static func callsiteInvariantsInfo() -> String { + "\(Self.description) must contain at least one word" } //*========================================================================* @@ -45,10 +61,12 @@ import NBKCoreKit //*========================================================================* /// An unsigned, resizable-width, binary integer of at least one word. - @frozen public struct Magnitude: MutableCollection, RandomAccessCollection, Sendable { + @frozen public struct Magnitude: Hashable, MutableCollection, RandomAccessCollection, Sendable { public typealias Digit = UInt + public typealias Words = Self + @usableFromInline typealias Storage = NBKResizableWidth.Storage //=--------------------------------------------------------------------= @@ -63,12 +81,26 @@ import NBKCoreKit @inlinable init(storage: Storage) { self.storage = storage - precondition(!self.storage.isEmpty, "\(Self.description) must contain at least one word") + precondition(self.isOK, Self.callsiteInvariantsInfo()) } @inlinable init(unchecked storage: Storage) { self.storage = storage - Swift.assert(!self.storage.isEmpty, "\(Self.description) must contain at least one word") + Swift.assert(self.isOK, Self.callsiteInvariantsInfo()) + } + + //=--------------------------------------------------------------------= + // MARK: Invariants + //=--------------------------------------------------------------------= + + /// Returns whether its invariants are kept. + @inlinable var isOK: Bool { + !self.storage.isEmpty + } + + /// Returns a description of the invariants that must be kept. + @inlinable static func callsiteInvariantsInfo() -> String { + "\(Self.description) must contain at least one word" } } } diff --git a/Sources/NBKFlexibleWidthKit/Private/Pointers.swift b/Sources/NBKResizableWidthKit/Private/Collection.swift similarity index 53% rename from Sources/NBKFlexibleWidthKit/Private/Pointers.swift rename to Sources/NBKResizableWidthKit/Private/Collection.swift index 6cabcd95..1f4427ee 100644 --- a/Sources/NBKFlexibleWidthKit/Private/Pointers.swift +++ b/Sources/NBKResizableWidthKit/Private/Collection.swift @@ -10,23 +10,27 @@ import NBKCoreKit //*============================================================================* -// MARK: * NBK x Pointers +// MARK: * NBK x Collection //*============================================================================* extension NBK { //=------------------------------------------------------------------------= - // MARK: Transformations + // MARK: Transformations x Drop //=------------------------------------------------------------------------= - @inlinable static func merge(into result: UnsafeMutableBufferPointer, - from x0: UnsafeBufferPointer, _ x1: UnsafeBufferPointer, each element: (T, T) -> T) { - //=--------------------------------------= - precondition(result.count == x0.count, NBK.callsiteOutOfBoundsInfo()) - precondition(result.count == x1.count, NBK.callsiteOutOfBoundsInfo()) - //=--------------------------------------= - for index in result.indices { - result[index] = element(x0[index], x1[index]) + /// Drops elements that the satisfy the predicate from the end of the given `collection`. + @_transparent @usableFromInline static func dropLast( + from collection: T, while predicate: (T.Element) -> Bool) + -> T.SubSequence where T: BidirectionalCollection { + var newEndIndex = collection.endIndex + + backwards: while newEndIndex > collection.startIndex { + let newLastIndex = collection.index(before: newEndIndex) + guard predicate(collection[newLastIndex]) else { break } + newEndIndex = newLastIndex } + + return collection.prefix(upTo: newEndIndex) } } diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Logic.swift b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Logic.swift index 87953d68..c3289324 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Logic.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Logic.swift @@ -29,6 +29,15 @@ final class UIntXLBenchmarksOnLogic: XCTestCase { // MARK: Tests //=------------------------------------------------------------------------= + func testNotInout() { + var abc = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.formOnesComplement()) + NBK.blackHoleInoutIdentity(&abc) + } + } + func testNot() { var abc = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Words.swift b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Words.swift new file mode 100644 index 00000000..a3485669 --- /dev/null +++ b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Words.swift @@ -0,0 +1,72 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if !DEBUG + +import NBKCoreKit +import NBKFlexibleWidthKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x UntXL x Words +//*============================================================================* + +final class IntXLBenchmarksOnWords: XCTestCase { + + typealias T = IntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testFromWords() { + var abc = NBK.blackHoleIdentity([ 0, 0, 0, 0] as W) + var xyz = NBK.blackHoleIdentity([~0, ~0, ~0, ~0] as W) + + for _ in 0 ..< 250_000 { + NBK.blackHole(T(words: abc)) + NBK.blackHole(T(words: xyz)) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } +} + +//*============================================================================* +// MARK: * NBK x UIntXL x Words +//*============================================================================* + +final class UIntXLBenchmarksOnWords: XCTestCase { + + typealias T = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testFromWords() { + var abc = NBK.blackHoleIdentity([ 0, 0, 0, 0] as W) + var xyz = NBK.blackHoleIdentity([~0, ~0, ~0, ~0] as W) + + for _ in 0 ..< 250_000 { + NBK.blackHole(T(words: abc)) + NBK.blackHole(T(words: xyz)) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } +} + +#endif diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Bits.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Bits.swift index d7ee82de..e61dfc4b 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Bits.swift +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Bits.swift @@ -84,8 +84,8 @@ final class IntXLTestsOnBits: XCTestCase { } func testTrailingZeroBitCount() { - XCTAssertEqual(T(sign: .minus, magnitude: 0).trailingZeroBitCount, UInt.bitWidth * 0) - XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).trailingZeroBitCount, UInt.bitWidth * 0) + XCTAssertEqual(T(sign: .minus, magnitude: 0).trailingZeroBitCount, UInt.bitWidth * 1) + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).trailingZeroBitCount, UInt.bitWidth * 1) XCTAssertEqual(T(words:[ 1, 1, 1, 1] as W).trailingZeroBitCount, UInt.bitWidth * 0) XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).trailingZeroBitCount, UInt.bitWidth * 0) @@ -149,7 +149,7 @@ final class UIntXLTestsOnBits: XCTestCase { } func testBitWidth() { - XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).bitWidth, UInt.bitWidth * 0) + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).bitWidth, UInt.bitWidth * 1) XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).bitWidth, UInt.bitWidth * 4) } @@ -159,7 +159,7 @@ final class UIntXLTestsOnBits: XCTestCase { } func testLeadingZeroBitCount() { - XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).leadingZeroBitCount, UInt.bitWidth * 0) + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).leadingZeroBitCount, UInt.bitWidth * 1) XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).leadingZeroBitCount, UInt.bitWidth * 0) XCTAssertEqual(T(words:[ 2, 0, 0, 0] as W).leadingZeroBitCount, UInt.bitWidth * 1 - 2) @@ -169,7 +169,7 @@ final class UIntXLTestsOnBits: XCTestCase { } func testTrailingZeroBitCount() { - XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).trailingZeroBitCount, UInt.bitWidth * 0) + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).trailingZeroBitCount, UInt.bitWidth * 1) XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).trailingZeroBitCount, UInt.bitWidth * 0) XCTAssertEqual(T(words:[ 2, 0, 0, 0] as W).trailingZeroBitCount, UInt.bitWidth * 0 + 1) diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Complements.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Complements.swift index e41a03e4..2c052ddb 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Complements.swift +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Complements.swift @@ -124,7 +124,7 @@ final class UIntXLTestsOnComplements: XCTestCase { //=------------------------------------------------------------------------= func testOnesComplement() { - NBKAssertOnesComplement(T(words:[ 0, 0, 0, 0] as W), T(words:[ 0, 0, 0, 0] as W)) + NBKAssertOnesComplement(T(words:[ 0, 0, 0, 0] as W), T(words:[~0, 0, 0, 0] as W)) NBKAssertOnesComplement(T(words:[ 1, 0, 0, 0] as W), T(words:[~1, 0, 0, 0] as W)) NBKAssertOnesComplement(T(words:[~0, 0, 0, 0] as W), T(words:[ 0, 0, 0, 0] as W)) NBKAssertOnesComplement(T(words:[ 1, 1, 1, 1] as W), T(words:[~1, ~1, ~1, ~1] as W)) diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Logic.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Logic.swift index b8206cda..dece8d7d 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Logic.swift +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Logic.swift @@ -63,7 +63,7 @@ final class UIntXLTestsOnLogic: XCTestCase { //=------------------------------------------------------------------------= func testNot() { - NBKAssertNot(T(words:[ 0, 0, 0, 0] as W), T(words:[ 0, 0, 0, 0] as W)) + NBKAssertNot(T(words:[ 0, 0, 0, 0] as W), T(words:[~0, 0, 0, 0] as W)) NBKAssertNot(T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 0, 0, 0, 0] as W)) NBKAssertNot(T(words:[ 0, 1, 2, 3] as W), T(words:[~0, ~1, ~2, ~3] as W)) diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Words.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Words.swift index 0a90e969..35e1ca46 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Words.swift +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Words.swift @@ -31,7 +31,7 @@ final class IntXLTestsOnWords: XCTestCase { //=------------------------------------------------------------------------= func testWords() { - NBKAssertWords(T(words:[ ]), [0 ]) + NBKAssertWords(T(words:[0 ]), [0 ]) NBKAssertWords(T(words:[1 ]), [1 ]) NBKAssertWords(T(words:[1, 2 ]), [1, 2 ]) NBKAssertWords(T(words:[1, 2, 3 ]), [1, 2, 3 ]) @@ -55,7 +55,7 @@ final class IntXLTestsOnWords: XCTestCase { func testWordsX64() throws { guard MemoryLayout.size == MemoryLayout.size else { throw XCTSkip() } - NBKAssertWords(T(x64:[ ] as X), [0 ]) + NBKAssertWords(T(x64:[0 ] as X), [0 ]) NBKAssertWords(T(x64:[1 ] as X), [1 ]) NBKAssertWords(T(x64:[1, 2 ] as X), [1, 2 ]) NBKAssertWords(T(x64:[1, 2, 3 ] as X), [1, 2, 3 ]) @@ -71,7 +71,7 @@ final class IntXLTestsOnWords: XCTestCase { func testWordsX32() throws { guard MemoryLayout.size == MemoryLayout.size else { throw XCTSkip() } - NBKAssertWords(T(x32:[ ] as Y), [0 ]) + NBKAssertWords(T(x32:[0 ] as Y), [0 ]) NBKAssertWords(T(x32:[1 ] as Y), [1 ]) NBKAssertWords(T(x32:[1, 2 ] as Y), [1, 2 ]) NBKAssertWords(T(x32:[1, 2, 3 ] as Y), [1, 2, 3 ]) @@ -102,18 +102,19 @@ final class UIntXLTestsOnWords: XCTestCase { typealias T = UIntXL typealias M = UIntXL + #warning("T.exactly(words:)") //=------------------------------------------------------------------------= // MARK: Tests //=------------------------------------------------------------------------= func testWords() { - NBKAssertWords(T(words:[ ]), [ ]) + NBKAssertWords(T(words:[0 ]), [0 ]) NBKAssertWords(T(words:[1 ]), [1 ]) NBKAssertWords(T(words:[1, 2 ]), [1, 2 ]) NBKAssertWords(T(words:[1, 2, 3 ]), [1, 2, 3 ]) NBKAssertWords(T(words:[1, 2, 3, 4]), [1, 2, 3, 4]) - NBKAssertWords(T(words:[0, 0, 0, 0]), [ ]) + NBKAssertWords(T(words:[0, 0, 0, 0]), [0 ]) NBKAssertWords(T(words:[1, 0, 0, 0]), [1 ]) NBKAssertWords(T(words:[1, 2, 0, 0]), [1, 2 ]) NBKAssertWords(T(words:[1, 2, 3, 0]), [1, 2, 3 ]) @@ -123,13 +124,13 @@ final class UIntXLTestsOnWords: XCTestCase { func testWordsX64() throws { guard MemoryLayout.size == MemoryLayout.size else { throw XCTSkip() } - NBKAssertWords(T(x64:[ ] as X), [ ]) + NBKAssertWords(T(x64:[0 ] as X), [0 ]) NBKAssertWords(T(x64:[1 ] as X), [1 ]) NBKAssertWords(T(x64:[1, 2 ] as X), [1, 2 ]) NBKAssertWords(T(x64:[1, 2, 3 ] as X), [1, 2, 3 ]) NBKAssertWords(T(x64:[1, 2, 3, 4] as X), [1, 2, 3, 4]) - NBKAssertWords(T(x64:[0, 0, 0, 0] as X), [ ]) + NBKAssertWords(T(x64:[0, 0, 0, 0] as X), [0 ]) NBKAssertWords(T(x64:[1, 0, 0, 0] as X), [1 ]) NBKAssertWords(T(x64:[1, 2, 0, 0] as X), [1, 2 ]) NBKAssertWords(T(x64:[1, 2, 3, 0] as X), [1, 2, 3 ]) @@ -139,7 +140,7 @@ final class UIntXLTestsOnWords: XCTestCase { func testWordsX32() throws { guard MemoryLayout.size == MemoryLayout.size else { throw XCTSkip() } - NBKAssertWords(T(x32:[ ] as Y), [ ]) + NBKAssertWords(T(x32:[0 ] as Y), [0 ]) NBKAssertWords(T(x32:[1 ] as Y), [1 ]) NBKAssertWords(T(x32:[1, 2 ] as Y), [1, 2 ]) NBKAssertWords(T(x32:[1, 2, 3 ] as Y), [1, 2, 3 ]) @@ -149,7 +150,7 @@ final class UIntXLTestsOnWords: XCTestCase { NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6, 7 ] as Y), [1, 2, 3, 4, 5, 6, 7 ]) NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6, 7, 8] as Y), [1, 2, 3, 4, 5, 6, 7, 8]) - NBKAssertWords(T(x32:[0, 0, 0, 0, 0, 0, 0, 0] as Y), [ ]) + NBKAssertWords(T(x32:[0, 0, 0, 0, 0, 0, 0, 0] as Y), [0 ]) NBKAssertWords(T(x32:[1, 0, 0, 0, 0, 0, 0, 0] as Y), [1 ]) NBKAssertWords(T(x32:[1, 2, 0, 0, 0, 0, 0, 0] as Y), [1, 2 ]) NBKAssertWords(T(x32:[1, 2, 3, 0, 0, 0, 0, 0] as Y), [1, 2, 3 ]) From 7cf5ee9edd5b5ff53bea113b16c18cd3b21b02b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sat, 5 Aug 2023 10:16:15 +0200 Subject: [PATCH 043/133] NBKFlexibleWidthKit: Cleanup. --- .../NBKFlexibleWidth+Addition+Digit.swift | 2 +- .../NBKFlexibleWidth+Addition.swift | 2 +- .../NBKFlexibleWidth+Words.swift | 2 +- .../IntXL+Complements.swift | 299 ++++++++++++++++++ .../IntXL+Words.swift | 1 - 5 files changed, 302 insertions(+), 4 deletions(-) create mode 100644 Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Complements.swift diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift index ef095562..cdc168a5 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift @@ -77,7 +77,7 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= self.storage.resize(minCount: index + 1) let overflow = self.storage.add(other, plus: false, at: index) - if overflow { self.storage.append(1) } + if overflow { self.storage.append(1 as UInt) } } @_disfavoredOverload @inlinable public func adding(_ other: UInt, at index: Int) -> Self { diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift index d6c856c2..fa122cfc 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift @@ -77,7 +77,7 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= self.storage.resize(minCount: other.storage.count + index) let overflow = self.storage.add(other.storage, plus: false, at: index) - if overflow { self.storage.append(1) } + if overflow { self.storage.append(1 as UInt) } } @inlinable public func adding(_ other: Self, at index: Int) -> Self { diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift index 69897b66..b680839b 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift @@ -32,7 +32,7 @@ extension NBKFlexibleWidth { magnitude.formTwosComplement() } //=--------------------------------------= - magnitude.normalize() + magnitude.normalize() // TODO: consuming //=--------------------------------------= self.init(sign: sign, magnitude: Magnitude(unchecked: magnitude)) } diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Complements.swift b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Complements.swift new file mode 100644 index 00000000..0bf91a74 --- /dev/null +++ b/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Complements.swift @@ -0,0 +1,299 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if !DEBUG + +import NBKCoreKit +import NBKFlexibleWidthKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x IntXL x Complements +//*============================================================================* + +final class IntXLBenchmarksOnComplements: XCTestCase { + + typealias T = IntXL + typealias M = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests x Magnitude + //=------------------------------------------------------------------------= + + func testMagnitude() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.magnitude) + NBK.blackHole(xyz.magnitude) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x One's Complement + //=------------------------------------------------------------------------= + + func testOnesComplement() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 250_000 { + NBK.blackHole(abc.onesComplement()) + NBK.blackHole(xyz.onesComplement()) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testOnesComplementInout() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.formOnesComplement()) + NBK.blackHole(xyz.formOnesComplement()) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Two's Complement + //=------------------------------------------------------------------------= + + func testTwosComplement() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.twosComplement()) + NBK.blackHole(xyz.twosComplement()) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testTwosComplementInout() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.formTwosComplement()) + NBK.blackHole(xyz.formTwosComplement()) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testTwosComplementReportingOverflow() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.twosComplementReportingOverflow()) + NBK.blackHole(xyz.twosComplementReportingOverflow()) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testTwosComplementReportingOverflowInout() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.formTwosComplementReportingOverflow()) + NBK.blackHole(xyz.formTwosComplementReportingOverflow()) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testTwosComplementSubsequence() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.twosComplementSubsequence(true)) + NBK.blackHole(xyz.twosComplementSubsequence(true)) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testTwosComplementSubsequenceInout() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.formTwosComplementSubsequence(true)) + NBK.blackHole(xyz.formTwosComplementSubsequence(true)) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } +} + +//*============================================================================* +// MARK: * NBK x UIntXL x Complements +//*============================================================================* + +final class UIntXLBenchmarksOnComplements: XCTestCase { + + typealias T = UIntXL + typealias M = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests x Magnitude + //=------------------------------------------------------------------------= + + func testMagnitude() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.magnitude) + NBK.blackHole(xyz.magnitude) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x One's Complement + //=------------------------------------------------------------------------= + + func testOnesComplement() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 250_000 { + NBK.blackHole(abc.onesComplement()) + NBK.blackHole(xyz.onesComplement()) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testOnesComplementInout() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.formOnesComplement()) + NBK.blackHole(xyz.formOnesComplement()) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Two's Complement + //=------------------------------------------------------------------------= + + func testTwosComplement() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 250_000 { + NBK.blackHole(abc.twosComplement()) + NBK.blackHole(xyz.twosComplement()) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testTwosComplementInout() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.formTwosComplement()) + NBK.blackHole(xyz.formTwosComplement()) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testTwosComplementReportingOverflow() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 250_000 { + NBK.blackHole(abc.twosComplementReportingOverflow()) + NBK.blackHole(xyz.twosComplementReportingOverflow()) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + + func testTwosComplementReportingOverflowInout() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.formTwosComplementReportingOverflow()) + NBK.blackHole(xyz.formTwosComplementReportingOverflow()) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testTwosComplementSubsequence() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 250_000 { + NBK.blackHole(abc.twosComplementSubsequence(true)) + NBK.blackHole(xyz.twosComplementSubsequence(true)) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testTwosComplementSubsequenceInout() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.formTwosComplementSubsequence(true)) + NBK.blackHole(xyz.formTwosComplementSubsequence(true)) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } +} + +#endif diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Words.swift b/Tests/NBKFlexibleWidthKitTests/IntXL+Words.swift index 35e1ca46..ac8e89e6 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Words.swift +++ b/Tests/NBKFlexibleWidthKitTests/IntXL+Words.swift @@ -102,7 +102,6 @@ final class UIntXLTestsOnWords: XCTestCase { typealias T = UIntXL typealias M = UIntXL - #warning("T.exactly(words:)") //=------------------------------------------------------------------------= // MARK: Tests //=------------------------------------------------------------------------= From b94c7fdb0c06676cec77d4b3fe08222839f08eb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sat, 5 Aug 2023 13:37:18 +0200 Subject: [PATCH 044/133] NBKResizableWidthKit: Xcode. --- ...NBKResizableWidthKit-Benchmarks.xctestplan | 24 +++++++ .swiftpm/NBKResizableWidthKit.xctestplan | 32 +++++++++ .swiftpm/Numberick-Benchmarks.xctestplan | 7 ++ .swiftpm/Numberick.xctestplan | 7 ++ .../NBKResizableWidthKit-Benchmarks.xcscheme | 71 +++++++++++++++++++ .../xcschemes/NBKResizableWidthKit.xcscheme | 71 +++++++++++++++++++ .../xcschemes/Numberick-Benchmarks.xcscheme | 17 +++++ .../xcshareddata/xcschemes/Numberick.xcscheme | 17 +++++ Package.swift | 14 ++++ README.md | 8 +++ .../Blank.swift | 1 + Tests/NBKResizableWidthKitTests/Blank.swift | 1 + 12 files changed, 270 insertions(+) create mode 100644 .swiftpm/NBKResizableWidthKit-Benchmarks.xctestplan create mode 100644 .swiftpm/NBKResizableWidthKit.xctestplan create mode 100644 .swiftpm/xcode/xcshareddata/xcschemes/NBKResizableWidthKit-Benchmarks.xcscheme create mode 100644 .swiftpm/xcode/xcshareddata/xcschemes/NBKResizableWidthKit.xcscheme create mode 100644 Tests/NBKResizableWidthKitBenchmarks/Blank.swift create mode 100644 Tests/NBKResizableWidthKitTests/Blank.swift diff --git a/.swiftpm/NBKResizableWidthKit-Benchmarks.xctestplan b/.swiftpm/NBKResizableWidthKit-Benchmarks.xctestplan new file mode 100644 index 00000000..c2f15441 --- /dev/null +++ b/.swiftpm/NBKResizableWidthKit-Benchmarks.xctestplan @@ -0,0 +1,24 @@ +{ + "configurations" : [ + { + "id" : "2BBD9A51-D890-4B97-AED4-B9962867DF57", + "name" : "Main", + "options" : { + + } + } + ], + "defaultOptions" : { + "codeCoverage" : false + }, + "testTargets" : [ + { + "target" : { + "containerPath" : "container:", + "identifier" : "NBKResizableWidthKitBenchmarks", + "name" : "NBKResizableWidthKitBenchmarks" + } + } + ], + "version" : 1 +} diff --git a/.swiftpm/NBKResizableWidthKit.xctestplan b/.swiftpm/NBKResizableWidthKit.xctestplan new file mode 100644 index 00000000..1f0eca5f --- /dev/null +++ b/.swiftpm/NBKResizableWidthKit.xctestplan @@ -0,0 +1,32 @@ +{ + "configurations" : [ + { + "id" : "6FC9897F-2BF3-4836-8372-787CE5195F87", + "name" : "Main", + "options" : { + + } + } + ], + "defaultOptions" : { + "codeCoverage" : { + "targets" : [ + { + "containerPath" : "container:", + "identifier" : "NBKResizableWidthKit", + "name" : "NBKResizableWidthKit" + } + ] + } + }, + "testTargets" : [ + { + "target" : { + "containerPath" : "container:", + "identifier" : "NBKResizableWidthKitTests", + "name" : "NBKResizableWidthKitTests" + } + } + ], + "version" : 1 +} diff --git a/.swiftpm/Numberick-Benchmarks.xctestplan b/.swiftpm/Numberick-Benchmarks.xctestplan index fe7df235..24d1cd11 100644 --- a/.swiftpm/Numberick-Benchmarks.xctestplan +++ b/.swiftpm/Numberick-Benchmarks.xctestplan @@ -42,6 +42,13 @@ "identifier" : "NBKFlexibleWidthKitBenchmarks", "name" : "NBKFlexibleWidthKitBenchmarks" } + }, + { + "target" : { + "containerPath" : "container:", + "identifier" : "NBKResizableWidthKitBenchmarks", + "name" : "NBKResizableWidthKitBenchmarks" + } } ], "version" : 1 diff --git a/.swiftpm/Numberick.xctestplan b/.swiftpm/Numberick.xctestplan index 74306fdc..8bba5531 100644 --- a/.swiftpm/Numberick.xctestplan +++ b/.swiftpm/Numberick.xctestplan @@ -50,6 +50,13 @@ "identifier" : "NBKFlexibleWidthKitTests", "name" : "NBKFlexibleWidthKitTests" } + }, + { + "target" : { + "containerPath" : "container:", + "identifier" : "NBKResizableWidthKitTests", + "name" : "NBKResizableWidthKitTests" + } } ], "version" : 1 diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/NBKResizableWidthKit-Benchmarks.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/NBKResizableWidthKit-Benchmarks.xcscheme new file mode 100644 index 00000000..7a6e61ad --- /dev/null +++ b/.swiftpm/xcode/xcshareddata/xcschemes/NBKResizableWidthKit-Benchmarks.xcscheme @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/NBKResizableWidthKit.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/NBKResizableWidthKit.xcscheme new file mode 100644 index 00000000..065ae43d --- /dev/null +++ b/.swiftpm/xcode/xcshareddata/xcschemes/NBKResizableWidthKit.xcscheme @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/Numberick-Benchmarks.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/Numberick-Benchmarks.xcscheme index 40b57f7b..96dd3f9a 100644 --- a/.swiftpm/xcode/xcshareddata/xcschemes/Numberick-Benchmarks.xcscheme +++ b/.swiftpm/xcode/xcshareddata/xcschemes/Numberick-Benchmarks.xcscheme @@ -48,6 +48,20 @@ ReferencedContainer = "container:"> + + + + + + + + + + + + diff --git a/Tests/NBKResizableWidthKitBenchmarks/Blank.swift b/Tests/NBKResizableWidthKitBenchmarks/Blank.swift new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/Tests/NBKResizableWidthKitBenchmarks/Blank.swift @@ -0,0 +1 @@ + diff --git a/Tests/NBKResizableWidthKitTests/Blank.swift b/Tests/NBKResizableWidthKitTests/Blank.swift new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/Tests/NBKResizableWidthKitTests/Blank.swift @@ -0,0 +1 @@ + From e9054ba1904eda7edc33449b6794ca1ceeee0dbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sun, 6 Aug 2023 12:49:35 +0200 Subject: [PATCH 045/133] NBKFlexibleWidthKit: Tests & Benchmarks. --- ....swift => NBKFlexibleWidth+Addition.swift} | 8 +- ...Bits.swift => NBKFlexibleWidth+Bits.swift} | 8 +- ...ift => NBKFlexibleWidth+Comparisons.swift} | 8 +- ...ift => NBKFlexibleWidth+Complements.swift} | 8 +- ....swift => NBKFlexibleWidth+Division.swift} | 8 +- ...gic.swift => NBKFlexibleWidth+Logic.swift} | 4 +- ... => NBKFlexibleWidth+Multiplication.swift} | 8 +- ...s.swift => NBKFlexibleWidth+Numbers.swift} | 8 +- ...ts.swift => NBKFlexibleWidth+Shifts.swift} | 8 +- ...ift => NBKFlexibleWidth+Subtraction.swift} | 8 +- ...Text.swift => NBKFlexibleWidth+Text.swift} | 8 +- ...rds.swift => NBKFlexibleWidth+Words.swift} | 6 +- .../NBKFlexibleWidth.swift | 4 +- Tests/NBKFlexibleWidthKitTests/IntXL.swift | 36 ------- ....swift => NBKFlexibleWidth+Addition.swift} | 38 +++++++- ...Bits.swift => NBKFlexibleWidth+Bits.swift} | 8 +- ...ift => NBKFlexibleWidth+Comparisons.swift} | 71 +++++++++++++- ...ift => NBKFlexibleWidth+Complements.swift} | 55 ++++++++++- ....swift => NBKFlexibleWidth+Division.swift} | 93 +++++++++++++++++-- ...gic.swift => NBKFlexibleWidth+Logic.swift} | 50 +++++++++- ... => NBKFlexibleWidth+Multiplication.swift} | 32 ++++++- ...s.swift => NBKFlexibleWidth+Numbers.swift} | 49 +++++++++- ...ts.swift => NBKFlexibleWidth+Shifts.swift} | 76 ++++++++++++++- ...ift => NBKFlexibleWidth+Subtraction.swift} | 70 +++++++++++++- ...Text.swift => NBKFlexibleWidth+Text.swift} | 37 +++++++- ...rds.swift => NBKFlexibleWidth+Words.swift} | 19 +++- .../NBKFlexibleWidth.swift | 43 ++++++++- .../Utilities/NBKAssert+Addition.swift | 42 --------- .../Utilities/NBKAssert+Comparisons.swift | 75 --------------- .../Utilities/NBKAssert+Complements.swift | 59 ------------ .../Utilities/NBKAssert+Division.swift | 91 ------------------ .../Utilities/NBKAssert+Identical.swift | 29 ------ .../Utilities/NBKAssert+Logic.swift | 54 ----------- .../Utilities/NBKAssert+Multiplication.swift | 36 ------- .../Utilities/NBKAssert+Numbers.swift | 53 ----------- .../Utilities/NBKAssert+Shifts.swift | 80 ---------------- .../Utilities/NBKAssert+Subtraction.swift | 74 --------------- .../Utilities/NBKAssert+Text.swift | 41 -------- .../Utilities/NBKAssert+Words.swift | 23 ----- 39 files changed, 635 insertions(+), 793 deletions(-) rename Tests/NBKFlexibleWidthKitBenchmarks/{IntXL+Addition.swift => NBKFlexibleWidth+Addition.swift} (94%) rename Tests/NBKFlexibleWidthKitBenchmarks/{IntXL+Bits.swift => NBKFlexibleWidth+Bits.swift} (96%) rename Tests/NBKFlexibleWidthKitBenchmarks/{IntXL+Comparisons.swift => NBKFlexibleWidth+Comparisons.swift} (96%) rename Tests/NBKFlexibleWidthKitBenchmarks/{IntXL+Complements.swift => NBKFlexibleWidth+Complements.swift} (97%) rename Tests/NBKFlexibleWidthKitBenchmarks/{IntXL+Division.swift => NBKFlexibleWidth+Division.swift} (97%) rename Tests/NBKFlexibleWidthKitBenchmarks/{IntXL+Logic.swift => NBKFlexibleWidth+Logic.swift} (96%) rename Tests/NBKFlexibleWidthKitBenchmarks/{IntXL+Multiplication.swift => NBKFlexibleWidth+Multiplication.swift} (92%) rename Tests/NBKFlexibleWidthKitBenchmarks/{IntXL+Numbers.swift => NBKFlexibleWidth+Numbers.swift} (99%) rename Tests/NBKFlexibleWidthKitBenchmarks/{IntXL+Shifts.swift => NBKFlexibleWidth+Shifts.swift} (97%) rename Tests/NBKFlexibleWidthKitBenchmarks/{IntXL+Subtraction.swift => NBKFlexibleWidth+Subtraction.swift} (94%) rename Tests/NBKFlexibleWidthKitBenchmarks/{IntXL+Text.swift => NBKFlexibleWidth+Text.swift} (96%) rename Tests/NBKFlexibleWidthKitBenchmarks/{IntXL+Words.swift => NBKFlexibleWidth+Words.swift} (92%) delete mode 100644 Tests/NBKFlexibleWidthKitTests/IntXL.swift rename Tests/NBKFlexibleWidthKitTests/{IntXL+Addition.swift => NBKFlexibleWidth+Addition.swift} (83%) rename Tests/NBKFlexibleWidthKitTests/{IntXL+Bits.swift => NBKFlexibleWidth+Bits.swift} (98%) rename Tests/NBKFlexibleWidthKitTests/{IntXL+Comparisons.swift => NBKFlexibleWidth+Comparisons.swift} (90%) rename Tests/NBKFlexibleWidthKitTests/{IntXL+Complements.swift => NBKFlexibleWidth+Complements.swift} (71%) rename Tests/NBKFlexibleWidthKitTests/{IntXL+Division.swift => NBKFlexibleWidth+Division.swift} (71%) rename Tests/NBKFlexibleWidthKitTests/{IntXL+Logic.swift => NBKFlexibleWidth+Logic.swift} (65%) rename Tests/NBKFlexibleWidthKitTests/{IntXL+Multiplication.swift => NBKFlexibleWidth+Multiplication.swift} (83%) rename Tests/NBKFlexibleWidthKitTests/{IntXL+Numbers.swift => NBKFlexibleWidth+Numbers.swift} (92%) rename Tests/NBKFlexibleWidthKitTests/{IntXL+Shifts.swift => NBKFlexibleWidth+Shifts.swift} (75%) rename Tests/NBKFlexibleWidthKitTests/{IntXL+Subtraction.swift => NBKFlexibleWidth+Subtraction.swift} (71%) rename Tests/NBKFlexibleWidthKitTests/{IntXL+Text.swift => NBKFlexibleWidth+Text.swift} (91%) rename Tests/NBKFlexibleWidthKitTests/{IntXL+Words.swift => NBKFlexibleWidth+Words.swift} (91%) delete mode 100644 Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Addition.swift delete mode 100644 Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Comparisons.swift delete mode 100644 Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Complements.swift delete mode 100644 Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Division.swift delete mode 100644 Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Identical.swift delete mode 100644 Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Logic.swift delete mode 100644 Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Multiplication.swift delete mode 100644 Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Numbers.swift delete mode 100644 Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Shifts.swift delete mode 100644 Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Subtraction.swift delete mode 100644 Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Text.swift delete mode 100644 Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Words.swift diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Addition.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Addition.swift similarity index 94% rename from Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Addition.swift rename to Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Addition.swift index 59385b99..59ae2e1a 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Addition.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Addition.swift @@ -18,10 +18,10 @@ private typealias X = [UInt64] private typealias Y = [UInt32] //*============================================================================* -// MARK: * NBK x IntXL x Addition +// MARK: * NBK x Flexible Width x Addition x IntXL //*============================================================================* -final class IntXLBenchmarksOnAddition: XCTestCase { +final class NBKFlexibleWidthBenchmarksOnAdditionAsIntXL: XCTestCase { typealias T = IntXL @@ -79,10 +79,10 @@ final class IntXLBenchmarksOnAddition: XCTestCase { } //*============================================================================* -// MARK: * NBK x UIntXL x Addition +// MARK: * NBK x Flexible Width x Addition x UIntXL //*============================================================================* -final class UIntXLBenchmarksOnAddition: XCTestCase { +final class NBKFlexibleWidthBenchmarksOnAdditionAsUIntXL: XCTestCase { typealias T = UIntXL diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Bits.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Bits.swift similarity index 96% rename from Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Bits.swift rename to Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Bits.swift index d182716f..3eb6844b 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Bits.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Bits.swift @@ -18,10 +18,10 @@ private typealias X = [UInt64] private typealias Y = [UInt32] //*============================================================================* -// MARK: * NBK x UntXL x Bits +// MARK: * NBK x Flexible Width x Bits x IntXL //*============================================================================* -final class IntXLBenchmarksOnBits: XCTestCase { +final class NBKFlexibleWidthBenchmarksOnBitsAsIntXL: XCTestCase { typealias T = IntXL @@ -122,10 +122,10 @@ final class IntXLBenchmarksOnBits: XCTestCase { } //*============================================================================* -// MARK: * NBK x UIntXL x Bits +// MARK: * NBK x Flexible Width x Bits x UIntXL //*============================================================================* -final class UIntXLBenchmarksOnBits: XCTestCase { +final class NBKFlexibleWidthBenchmarksOnBitsAsUIntXL: XCTestCase { typealias T = UIntXL diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Comparisons.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Comparisons.swift similarity index 96% rename from Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Comparisons.swift rename to Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Comparisons.swift index bf6df91b..349fe8a9 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Comparisons.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Comparisons.swift @@ -18,10 +18,10 @@ private typealias X = [UInt64] private typealias Y = [UInt32] //*============================================================================* -// MARK: * NBK x IntXL x Comparisons +// MARK: * NBK x Flexible Width x Comparisons x IntXL //*============================================================================* -final class IntXLBenchmarksOnComparisons: XCTestCase { +final class NBKFlexibleWidthBenchmarksOnComparisonsAsIntXL: XCTestCase { typealias T = IntXL @@ -124,10 +124,10 @@ final class IntXLBenchmarksOnComparisons: XCTestCase { } //*============================================================================* -// MARK: * NBK x UIntXL x Comparisons +// MARK: * NBK x Flexible Width x Comparisons x UIntXL //*============================================================================* -final class UIntXLBenchmarksOnComparisons: XCTestCase { +final class NBKFlexibleWidthBenchmarksOnComparisonsAsUIntXL: XCTestCase { typealias T = UIntXL diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Complements.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Complements.swift similarity index 97% rename from Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Complements.swift rename to Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Complements.swift index 0bf91a74..f865026f 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Complements.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Complements.swift @@ -18,10 +18,10 @@ private typealias X = [UInt64] private typealias Y = [UInt32] //*============================================================================* -// MARK: * NBK x IntXL x Complements +// MARK: * NBK x Flexible Width x Complements x IntXL //*============================================================================* -final class IntXLBenchmarksOnComplements: XCTestCase { +final class NBKFlexibleWidthBenchmarksOnComplementsAsIntXL: XCTestCase { typealias T = IntXL typealias M = UIntXL @@ -157,10 +157,10 @@ final class IntXLBenchmarksOnComplements: XCTestCase { } //*============================================================================* -// MARK: * NBK x UIntXL x Complements +// MARK: * NBK x Flexible Width x Complements x UIntXL //*============================================================================* -final class UIntXLBenchmarksOnComplements: XCTestCase { +final class NBKFlexibleWidthBenchmarksOnComplementsAsUIntXL: XCTestCase { typealias T = UIntXL typealias M = UIntXL diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Division.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Division.swift similarity index 97% rename from Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Division.swift rename to Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Division.swift index 8e184d50..dd04728c 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Division.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Division.swift @@ -18,10 +18,10 @@ private typealias X = [UInt64] private typealias Y = [UInt32] //*============================================================================* -// MARK: * NBK x IntXL x Division +// MARK: * NBK x Flexible Width x Division x IntXL //*============================================================================* -final class IntXLBenchmarksOnDivision: XCTestCase { +final class NBKFlexibleWidthBenchmarksOnDivisionAsIntXL: XCTestCase { typealias T = IntXL typealias M = IntXL @@ -128,10 +128,10 @@ final class IntXLBenchmarksOnDivision: XCTestCase { } //*============================================================================* -// MARK: * NBK x UIntXL x Division +// MARK: * NBK x Flexible Width x Division x UIntXL //*============================================================================* -final class UIntXLBenchmarksOnDivision: XCTestCase { +final class NBKFlexibleWidthBenchmarksOnDivisionAsUIntXL: XCTestCase { typealias T = UIntXL typealias M = UIntXL diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Logic.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Logic.swift similarity index 96% rename from Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Logic.swift rename to Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Logic.swift index c3289324..bb90656a 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Logic.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Logic.swift @@ -18,10 +18,10 @@ private typealias X = [UInt64] private typealias Y = [UInt32] //*============================================================================* -// MARK: * NBK x UIntXL x Logic +// MARK: * NBK x Flexible Width x Logic x UIntXL //*============================================================================* -final class UIntXLBenchmarksOnLogic: XCTestCase { +final class NBKFlexibleWidthBenchmarksOnLogicAsUIntXL: XCTestCase { typealias T = UIntXL diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Multiplication.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Multiplication.swift similarity index 92% rename from Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Multiplication.swift rename to Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Multiplication.swift index f3dcef84..f8740232 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Multiplication.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Multiplication.swift @@ -18,10 +18,10 @@ private typealias X = [UInt64] private typealias Y = [UInt32] //*============================================================================* -// MARK: * NBK x IntXL x Multiplication +// MARK: * NBK x Flexible Width x Multiplication x IntXL //*============================================================================* -final class IntXLBenchmarksOnMultiplication: XCTestCase { +final class NBKFlexibleWidthBenchmarksOnMultiplicationAsIntXL: XCTestCase { typealias T = IntXL @@ -57,10 +57,10 @@ final class IntXLBenchmarksOnMultiplication: XCTestCase { } //*============================================================================* -// MARK: * NBK x UIntXL x Multiplication +// MARK: * NBK x Flexible Width x Multiplication x UIntXL //*============================================================================* -final class UIntXLBenchmarksOnMultiplication: XCTestCase { +final class NBKFlexibleWidthBenchmarksOnMultiplicationAsUIntXL: XCTestCase { typealias T = UIntXL diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Numbers.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Numbers.swift similarity index 99% rename from Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Numbers.swift rename to Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Numbers.swift index 90090857..2fb44ab7 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Numbers.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Numbers.swift @@ -18,10 +18,10 @@ private typealias X = [UInt64] private typealias Y = [UInt32] //*============================================================================* -// MARK: * NBK x IntXL x Numbers +// MARK: * NBK x Flexible Width x Numbers x IntXL //*============================================================================* -final class IntXLBenchmarksOnNumbers: XCTestCase { +final class NBKFlexibleWidthBenchmarksOnNumbersAsIntXL: XCTestCase { typealias T = IntXL typealias M = UIntXL @@ -418,10 +418,10 @@ final class IntXLBenchmarksOnNumbers: XCTestCase { } //*============================================================================* -// MARK: * NBK x UIntXL x Numbers +// MARK: * NBK x Flexible Width x Numbers x UIntXL //*============================================================================* -final class UIntXLBenchmarksOnNumbers: XCTestCase { +final class NBKFlexibleWidthBenchmarksOnNumbersAsUIntXL: XCTestCase { typealias T = UIntXL typealias M = UIntXL diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Shifts.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Shifts.swift similarity index 97% rename from Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Shifts.swift rename to Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Shifts.swift index affe1757..9e69edc1 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Shifts.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Shifts.swift @@ -18,10 +18,10 @@ private typealias X = [UInt64] private typealias Y = [UInt32] //*============================================================================* -// MARK: * NBK x IntXL x Shifts +// MARK: * NBK x Flexible Width x Shifts x IntXL //*============================================================================* -final class IntXLBenchmarksOnShifts: XCTestCase { +final class NBKFlexibleWidthBenchmarksOnShiftsAsIntXL: XCTestCase { typealias T = IntXL @@ -150,10 +150,10 @@ final class IntXLBenchmarksOnShifts: XCTestCase { } //*============================================================================* -// MARK: * NBK x UIntXL x Shifts +// MARK: * NBK x Flexible Width x Shifts x UIntXL //*============================================================================* -final class UIntXLBenchmarksOnShifts: XCTestCase { +final class NBKFlexibleWidthBenchmarksOnShiftsAsUIntXL: XCTestCase { typealias T = UIntXL diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Subtraction.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Subtraction.swift similarity index 94% rename from Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Subtraction.swift rename to Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Subtraction.swift index f5fd77ec..1c7a0733 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Subtraction.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Subtraction.swift @@ -18,10 +18,10 @@ private typealias X = [UInt64] private typealias Y = [UInt32] //*============================================================================* -// MARK: * NBK x IntXL x Subtraction +// MARK: * NBK x Flexible Width x Subtraction x IntXL //*============================================================================* -final class IntXLBenchmarksOnSubtraction: XCTestCase { +final class NBKFlexibleWidthBenchmarksOnSubtractionAsIntXL: XCTestCase { typealias T = IntXL @@ -79,10 +79,10 @@ final class IntXLBenchmarksOnSubtraction: XCTestCase { } //*============================================================================* -// MARK: * NBK x UIntXL x Subtraction +// MARK: * NBK x Flexible Width x Subtraction x UIntXL //*============================================================================* -final class UIntXLBenchmarksOnSubtraction: XCTestCase { +final class NBKFlexibleWidthBenchmarksOnSubtractionAsUIntXL: XCTestCase { typealias T = UIntXL diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Text.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Text.swift similarity index 96% rename from Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Text.swift rename to Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Text.swift index e4eb6e7a..d81211e6 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Text.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Text.swift @@ -18,10 +18,10 @@ private typealias X = [UInt64] private typealias Y = [UInt32] //*============================================================================* -// MARK: * NBK x IntXL x Division +// MARK: * NBK x Flexible Width x Division x IntXL //*============================================================================* -final class IntXLBenchmarksOnText: XCTestCase { +final class NBKFlexibleWidthBenchmarksOnTextAsIntXL: XCTestCase { typealias T = IntXL @@ -108,10 +108,10 @@ final class IntXLBenchmarksOnText: XCTestCase { } //*============================================================================* -// MARK: * NBK x UIntXL x Division +// MARK: * NBK x Flexible Width x Division x UIntXL //*============================================================================* -final class UIntXLBenchmarksOnText: XCTestCase { +final class NBKFlexibleWidthBenchmarksOnTextAsUIntXL: XCTestCase { typealias T = UIntXL diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Words.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Words.swift similarity index 92% rename from Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Words.swift rename to Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Words.swift index a3485669..1e95969c 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/IntXL+Words.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Words.swift @@ -21,7 +21,7 @@ private typealias Y = [UInt32] // MARK: * NBK x UntXL x Words //*============================================================================* -final class IntXLBenchmarksOnWords: XCTestCase { +final class NBKFlexibleWidthBenchmarksOnWordsAsIntXL: XCTestCase { typealias T = IntXL @@ -44,10 +44,10 @@ final class IntXLBenchmarksOnWords: XCTestCase { } //*============================================================================* -// MARK: * NBK x UIntXL x Words +// MARK: * NBK x Flexible Width x Words x UIntXL //*============================================================================* -final class UIntXLBenchmarksOnWords: XCTestCase { +final class NBKFlexibleWidthBenchmarksOnWordsAsUIntXL: XCTestCase { typealias T = UIntXL diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth.swift index 3a4ca196..a9861a0d 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth.swift @@ -16,7 +16,7 @@ private typealias X = [UInt64] private typealias Y = [UInt32] //*============================================================================* -// MARK: * NBK x Flexible Width x Initializers x Signed +// MARK: * NBK x Flexible Width x Initializers x IntXL //*============================================================================* extension NBKFlexibleWidth { @@ -42,7 +42,7 @@ extension NBKFlexibleWidth { } //*============================================================================* -// MARK: * NBK x Flexible Width x Initializers x Unsigned +// MARK: * NBK x Flexible Width x Initializers x UIntXL //*============================================================================* extension NBKFlexibleWidth.Magnitude { diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL.swift b/Tests/NBKFlexibleWidthKitTests/IntXL.swift deleted file mode 100644 index ab998cf2..00000000 --- a/Tests/NBKFlexibleWidthKitTests/IntXL.swift +++ /dev/null @@ -1,36 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if DEBUG - -import NBKFlexibleWidthKit -import XCTest - -//*============================================================================* -// MARK: * NBK x IntXL -//*============================================================================* - -final class IntXLTests: XCTestCase { - - typealias T = IntXL - typealias M = UIntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testSign() { - XCTAssertEqual(T(sign: .plus, magnitude: 0).sign, .plus ) - XCTAssertEqual(T(sign: .minus, magnitude: 0).sign, .minus) - XCTAssertEqual(T(sign: .plus, magnitude: 1).sign, .plus ) - XCTAssertEqual(T(sign: .minus, magnitude: 1).sign, .minus) - } -} - -#endif diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Addition.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Addition.swift similarity index 83% rename from Tests/NBKFlexibleWidthKitTests/IntXL+Addition.swift rename to Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Addition.swift index 86af78b7..2f1c5c58 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Addition.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Addition.swift @@ -18,10 +18,10 @@ private typealias X = [UInt64] private typealias Y = [UInt32] //*============================================================================* -// MARK: * NBK x IntXL x Addition +// MARK: * NBK x Flexible Width x Addition x IntXL //*============================================================================* -final class IntXLTestsOnAddition: XCTestCase { +final class NBKFlexibleWidthTestsOnAdditionAsIntXL: XCTestCase { typealias T = IntXL @@ -113,10 +113,10 @@ final class IntXLTestsOnAddition: XCTestCase { } //*============================================================================* -// MARK: * NBK x UIntXL x Addition +// MARK: * NBK x Flexible Width x Addition x UIntXL //*============================================================================* -final class UIntXLTestsOnAddition: XCTestCase { +final class NBKFlexibleWidthTestsOnAdditionAsUIntXL: XCTestCase { typealias T = UIntXL @@ -187,4 +187,34 @@ final class UIntXLTestsOnAddition: XCTestCase { } } +//*============================================================================* +// MARK: * NBK x Flexible Width x Addition x Assertions +//*============================================================================* + +private func NBKAssertAddition( +_ lhs: T, _ rhs: T, _ index: Int, _ partialValue: T, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + if index.isZero { + XCTAssertEqual( lhs + rhs, partialValue, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs += rhs; return lhs }(), partialValue, file: file, line: line) + } + //=------------------------------------------= + XCTAssertEqual(lhs.adding(rhs, at: index), partialValue, file: file, line: line) + XCTAssertEqual({ var x = lhs; let _ = x.add(rhs, at: index); return x }(), partialValue, file: file, line: line) +} + +private func NBKAssertAdditionByDigit( +_ lhs: T, _ rhs: T.Digit, _ index: Int, _ partialValue: T, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + if index.isZero { + XCTAssertEqual( lhs + rhs, partialValue, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs += rhs; return lhs }(), partialValue, file: file, line: line) + } + //=------------------------------------------= + XCTAssertEqual(lhs.adding(rhs, at: index), partialValue, file: file, line: line) + XCTAssertEqual({ var x = lhs; let _ = x.add(rhs, at: index); return x }(), partialValue, file: file, line: line) +} + #endif diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Bits.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Bits.swift similarity index 98% rename from Tests/NBKFlexibleWidthKitTests/IntXL+Bits.swift rename to Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Bits.swift index e61dfc4b..f15ef7d9 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Bits.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Bits.swift @@ -18,10 +18,10 @@ private typealias X = [UInt64] private typealias Y = [UInt32] //*============================================================================* -// MARK: * NBK x IntXL x Bits +// MARK: * NBK x Flexible Width x Bits x IntXL //*============================================================================* -final class IntXLTestsOnBits: XCTestCase { +final class NBKFlexibleWidthTestsOnBitsAsIntXL: XCTestCase { typealias T = IntXL typealias M = UIntXL @@ -131,10 +131,10 @@ final class IntXLTestsOnBits: XCTestCase { } //*============================================================================* -// MARK: * NBK x UIntXL x Bits +// MARK: * NBK x Flexible Width x Bits x UIntXL //*============================================================================* -final class UIntXLTestsOnBits: XCTestCase { +final class NBKFlexibleWidthTestsOnBitsAsUIntXL: XCTestCase { typealias T = UIntXL typealias M = UIntXL diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Comparisons.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Comparisons.swift similarity index 90% rename from Tests/NBKFlexibleWidthKitTests/IntXL+Comparisons.swift rename to Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Comparisons.swift index 027e2fad..ea88efc2 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Comparisons.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Comparisons.swift @@ -18,10 +18,10 @@ private typealias X = [UInt64] private typealias Y = [UInt32] //*============================================================================* -// MARK: * NBK x IntXL x Comparisons +// MARK: * NBK x Flexible Width x Comparisons x IntXL //*============================================================================* -final class IntXLTestsOnComparisons: XCTestCase { +final class NBKFlexibleWidthTestsOnComparisonsAsIntXL: XCTestCase { typealias T = IntXL typealias M = UIntXL @@ -328,10 +328,10 @@ final class IntXLTestsOnComparisons: XCTestCase { } //*============================================================================* -// MARK: * NBK x UIntXL x Comparisons +// MARK: * NBK x Flexible Width x Comparisons x UIntXL //*============================================================================* -final class UIntXLTestsOnComparisons: XCTestCase { +final class NBKFlexibleWidthTestsOnComparisonsAsUIntXL: XCTestCase { typealias T = UIntXL typealias M = UIntXL @@ -527,4 +527,67 @@ final class UIntXLTestsOnComparisons: XCTestCase { } } +//*============================================================================* +// MARK: * NBK x Flexible Width x Comparisons x Assertions +//*============================================================================* + +private func NBKAssertSignum( +_ operand: T, _ signum: Int, +file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual(Int(operand.signum() as Int), signum, file: file, line: line) + XCTAssertEqual(Int(operand.signum() as T ), signum, file: file, line: line) // stdlib +} + +private func NBKAssertComparisons( +_ lhs: T, _ rhs: T, _ signum: Int, +file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual(lhs == rhs, signum == 0, file: file, line: line) + XCTAssertEqual(lhs != rhs, signum != 0, file: file, line: line) + + XCTAssertEqual(lhs < rhs, signum == -1, file: file, line: line) + XCTAssertEqual(lhs <= rhs, signum != 1, file: file, line: line) + + XCTAssertEqual(lhs > rhs, signum == 1, file: file, line: line) + XCTAssertEqual(lhs >= rhs, signum != -1, file: file, line: line) + + XCTAssertEqual(lhs.compared(to: rhs), signum, file: file, line: line) +} + +private func NBKAssertComparisonsAtIndex( +_ lhs: T, _ rhs: T, _ index: Int, _ signum: Int, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + if index.isZero { + NBKAssertComparisons(lhs, rhs, signum, file: file, line: line) + } + //=------------------------------------------= + XCTAssertEqual(lhs.compared(to: rhs, at: index), signum, file: file, line: line) +} + +private func NBKAssertComparisonsByDigit( +_ lhs: T, _ rhs: T.Digit, _ signum: Int, +file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual(lhs == rhs, signum == 0, file: file, line: line) + XCTAssertEqual(lhs != rhs, signum != 0, file: file, line: line) + + XCTAssertEqual(lhs < rhs, signum == -1, file: file, line: line) + XCTAssertEqual(lhs <= rhs, signum != 1, file: file, line: line) + + XCTAssertEqual(lhs > rhs, signum == 1, file: file, line: line) + XCTAssertEqual(lhs >= rhs, signum != -1, file: file, line: line) + + XCTAssertEqual(lhs.compared(to: rhs), signum, file: file, line: line) +} + +private func NBKAssertComparisonsByDigitAtIndex( +_ lhs: T, _ rhs: T.Digit, _ index: Int, _ signum: Int, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + if index.isZero { + NBKAssertComparisonsByDigit(lhs, rhs, signum, file: file, line: line) + } + //=------------------------------------------= + XCTAssertEqual(lhs.compared(to: rhs, at: index), signum, file: file, line: line) +} + #endif diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Complements.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Complements.swift similarity index 71% rename from Tests/NBKFlexibleWidthKitTests/IntXL+Complements.swift rename to Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Complements.swift index 2c052ddb..e2fb39f2 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Complements.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Complements.swift @@ -18,10 +18,10 @@ private typealias X = [UInt64] private typealias Y = [UInt32] //*============================================================================* -// MARK: * NBK x IntXL x Complements +// MARK: * NBK x Flexible Width x Complements x IntXL //*============================================================================* -final class IntXLTestsOnComplements: XCTestCase { +final class NBKFlexibleWidthTestsOnComplementsAsIntXL: XCTestCase { typealias T = IntXL typealias M = UIntXL @@ -100,10 +100,10 @@ final class IntXLTestsOnComplements: XCTestCase { } //*============================================================================* -// MARK: * NBK x UIntXL x Complements +// MARK: * NBK x Flexible Width x Complements x UIntXL //*============================================================================* -final class UIntXLTestsOnComplements: XCTestCase { +final class NBKFlexibleWidthTestsOnComplementsAsUIntXL: XCTestCase { typealias T = UIntXL typealias M = UIntXL @@ -160,4 +160,51 @@ final class UIntXLTestsOnComplements: XCTestCase { } } +//*============================================================================* +// MARK: * NBK x Flexible Width x Complements x Assertions +//*============================================================================* + +private func NBKAssertOnesComplement( +_ integer: T, _ result: T, +file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual(integer.onesComplement(), result, file: file, line: line) + XCTAssertEqual(integer.twosComplementSubsequence(false).partialValue, result, file: file, line: line) + + XCTAssertEqual({ var x = integer; let _ = x.formOnesComplement(); return x }(), result, file: file, line: line) + XCTAssertEqual({ var x = integer; let _ = x.formTwosComplementSubsequence(false); return x }(), result, file: file, line: line) +} + +private func NBKAssertTwosComplement( +_ integer: T, _ partialValue: T, _ overflow: Bool = false, +file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual(integer.twosComplement(), partialValue, file: file, line: line) + XCTAssertEqual(integer.twosComplementReportingOverflow().partialValue, partialValue, file: file, line: line) + XCTAssertEqual(integer.twosComplementReportingOverflow().overflow, overflow, file: file, line: line) + XCTAssertEqual(integer.twosComplementSubsequence(true ).partialValue, partialValue, file: file, line: line) + XCTAssertEqual(integer.twosComplementSubsequence(true ).overflow, overflow, file: file, line: line) + + XCTAssertEqual({ var x = integer; x.formTwosComplement(); return x }(), partialValue, file: file, line: line) + XCTAssertEqual({ var x = integer; let _ = x.formTwosComplementReportingOverflow(); return x }(), partialValue, file: file, line: line) + XCTAssertEqual({ var x = integer; let o = x.formTwosComplementReportingOverflow(); return o }(), overflow, file: file, line: line) + XCTAssertEqual({ var x = integer; let _ = x.formTwosComplementSubsequence(true ); return x }(), partialValue, file: file, line: line) + XCTAssertEqual({ var x = integer; let o = x.formTwosComplementSubsequence(true ); return o }(), overflow, file: file, line: line) +} + +private func NBKAssertAdditiveInverse( +_ operand: IntXL, _ partialValue: IntXL, _ overflow: Bool = false, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + if !overflow { + NBKAssertIdentical(-operand, partialValue, file: file, line: line) + NBKAssertIdentical((operand).negated(), partialValue, file: file, line: line) + NBKAssertIdentical({ var x = operand; x.negate(); return x }(), partialValue, file: file, line: line) + } + //=------------------------------------------= + NBKAssertIdentical(operand.negatedReportingOverflow().partialValue, partialValue, file: file, line: line) + XCTAssertEqual/**/(operand.negatedReportingOverflow().overflow, overflow, file: file, line: line) + + NBKAssertIdentical({ var x = operand; let _ = x.negateReportingOverflow(); return x }(), partialValue, file: file, line: line) + XCTAssertEqual/**/({ var x = operand; let o = x.negateReportingOverflow(); return o }(), overflow, file: file, line: line) +} + #endif diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Division.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Division.swift similarity index 71% rename from Tests/NBKFlexibleWidthKitTests/IntXL+Division.swift rename to Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Division.swift index 92b30677..1664c319 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Division.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Division.swift @@ -10,7 +10,7 @@ #if DEBUG import NBKCoreKit -import NBKFlexibleWidthKit +@testable import NBKFlexibleWidthKit import XCTest private typealias W = [UInt] @@ -18,10 +18,10 @@ private typealias X = [UInt64] private typealias Y = [UInt32] //*============================================================================* -// MARK: * NBK x IntXL x Division +// MARK: * NBK x Flexible Width x Division x IntXL //*============================================================================* -final class IntXLTestsOnDivision: XCTestCase { +final class NBKFlexibleWidthTestsOnDivisionAsIntXL: XCTestCase { typealias T = IntXL typealias M = UIntXL @@ -145,10 +145,10 @@ final class IntXLTestsOnDivision: XCTestCase { } //*============================================================================* -// MARK: * NBK x UIntXL x Division +// MARK: * NBK x Flexible Width x Division x UIntXL //*============================================================================* -final class UIntXLTestsOnDivision: XCTestCase { +final class NBKFlexibleWidthTestsOnDivisionAsUIntXL: XCTestCase { typealias T = UIntXL typealias M = UIntXL @@ -255,10 +255,10 @@ final class UIntXLTestsOnDivision: XCTestCase { } //*============================================================================* -// MARK: * NBK x UIntXL x Division x Code Coverage +// MARK: * NBK x Flexible Width x Division x UIntXL x Code Coverage //*============================================================================* -final class UIntXLTestsOnDivisionCodeCoverage: XCTestCase { +final class NBKFlexibleWidthTestsOnDivisionCodeCoverageAsUIntXL: XCTestCase { typealias T = UIntXL typealias M = UIntXL @@ -284,4 +284,83 @@ final class UIntXLTestsOnDivisionCodeCoverage: XCTestCase { } } +//*============================================================================* +// MARK: * NBK x Flexible Width x Division x Assertions +//*============================================================================* + +private func NBKAssertDivision( +_ lhs: T, _ rhs: T, _ quotient: T, _ remainder: T, _ overflow: Bool = false, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + XCTAssertEqual(lhs, quotient * rhs + remainder, "lhs != rhs * quotient + remainder", file: file, line: line) + //=------------------------------------------= + if !overflow { + XCTAssertEqual(lhs / rhs, quotient, file: file, line: line) + XCTAssertEqual(lhs % rhs, remainder, file: file, line: line) + + XCTAssertEqual({ var x = lhs; x /= rhs; return x }(), quotient, file: file, line: line) + XCTAssertEqual({ var x = lhs; x %= rhs; return x }(), remainder, file: file, line: line) + + XCTAssertEqual(lhs.quotientAndRemainder(dividingBy: rhs).quotient, quotient, file: file, line: line) + XCTAssertEqual(lhs.quotientAndRemainder(dividingBy: rhs).remainder, remainder, file: file, line: line) + } + //=------------------------------------------= + XCTAssertEqual(lhs.dividedReportingOverflow(by: rhs).partialValue, quotient, file: file, line: line) + XCTAssertEqual(lhs.dividedReportingOverflow(by: rhs).overflow, overflow, file: file, line: line) + + XCTAssertEqual({ var x = lhs; let _ = x.divideReportingOverflow(by: rhs); return x }(), quotient, file: file, line: line) + XCTAssertEqual({ var x = lhs; let o = x.divideReportingOverflow(by: rhs); return o }(), overflow, file: file, line: line) + + XCTAssertEqual(lhs.remainderReportingOverflow(dividingBy: rhs).partialValue, remainder, file: file, line: line) + XCTAssertEqual(lhs.remainderReportingOverflow(dividingBy: rhs).overflow, overflow, file: file, line: line) + + XCTAssertEqual({ var x = lhs; let _ = x.formRemainderReportingOverflow(dividingBy: rhs); return x }(), remainder, file: file, line: line) + XCTAssertEqual({ var x = lhs; let o = x.formRemainderReportingOverflow(dividingBy: rhs); return o }(), overflow, file: file, line: line) + + XCTAssertEqual(lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs).partialValue.quotient, quotient, file: file, line: line) + XCTAssertEqual(lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs).partialValue.remainder, remainder, file: file, line: line) + XCTAssertEqual(lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs).overflow, overflow, file: file, line: line) + //=------------------------------------------= + guard let lhs = lhs as? UIntXL, let rhs = rhs as? UIntXL, let quotient = quotient as? UIntXL, let remainder = remainder as? UIntXL else { return } + //=------------------------------------------= + XCTAssertEqual(lhs.quotientAndRemainderReportingOverflowAsNormal(dividingBy: rhs).partialValue.quotient, quotient, file: file, line: line) + XCTAssertEqual(lhs.quotientAndRemainderReportingOverflowAsNormal(dividingBy: rhs).partialValue.remainder, remainder, file: file, line: line) + XCTAssertEqual(lhs.quotientAndRemainderReportingOverflowAsNormal(dividingBy: rhs).overflow, overflow, file: file, line: line) +} + +private func NBKAssertDivisionByDigit( +_ lhs: T, _ rhs: T.Digit, _ quotient: T, _ remainder: T.Digit, _ overflow: Bool = false, +file: StaticString = #file, line: UInt = #line) { + let extended = T(digit: remainder) + //=------------------------------------------= + XCTAssertEqual(lhs, quotient * rhs + remainder, "lhs != rhs * quotient + remainder", file: file, line: line) + //=------------------------------------------= + if !overflow { + XCTAssertEqual(lhs / rhs, quotient, file: file, line: line) + XCTAssertEqual(lhs % rhs, remainder, file: file, line: line) + + XCTAssertEqual({ var x = lhs; x /= rhs; return x }(), quotient, file: file, line: line) + XCTAssertEqual({ var x = lhs; x %= rhs; return x }(), extended, file: file, line: line) + + XCTAssertEqual(lhs.quotientAndRemainder(dividingBy: rhs).quotient, quotient, file: file, line: line) + XCTAssertEqual(lhs.quotientAndRemainder(dividingBy: rhs).remainder, remainder, file: file, line: line) + } + //=------------------------------------------= + XCTAssertEqual(lhs.dividedReportingOverflow(by: rhs).partialValue, quotient, file: file, line: line) + XCTAssertEqual(lhs.dividedReportingOverflow(by: rhs).overflow, overflow, file: file, line: line) + + XCTAssertEqual({ var x = lhs; let _ = x.divideReportingOverflow(by: rhs); return x }(), quotient, file: file, line: line) + XCTAssertEqual({ var x = lhs; let o = x.divideReportingOverflow(by: rhs); return o }(), overflow, file: file, line: line) + + XCTAssertEqual(lhs.remainderReportingOverflow(dividingBy: rhs).partialValue, remainder, file: file, line: line) + XCTAssertEqual(lhs.remainderReportingOverflow(dividingBy: rhs).overflow, overflow, file: file, line: line) + + XCTAssertEqual({ var x = lhs; let _ = x.formRemainderReportingOverflow(dividingBy: rhs); return x }(), extended, file: file, line: line) + XCTAssertEqual({ var x = lhs; let o = x.formRemainderReportingOverflow(dividingBy: rhs); return o }(), overflow, file: file, line: line) + + XCTAssertEqual(lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs).partialValue.quotient, quotient, file: file, line: line) + XCTAssertEqual(lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs).partialValue.remainder, remainder, file: file, line: line) + XCTAssertEqual(lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs).overflow, overflow, file: file, line: line) +} + #endif diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Logic.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Logic.swift similarity index 65% rename from Tests/NBKFlexibleWidthKitTests/IntXL+Logic.swift rename to Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Logic.swift index dece8d7d..d354ff87 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Logic.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Logic.swift @@ -18,10 +18,10 @@ private typealias X = [UInt64] private typealias Y = [UInt32] //*============================================================================* -// MARK: * NBK x IntXL x Logic +// MARK: * NBK x Flexible Width x Logic x IntXL //*============================================================================* -final class IntXLTestsOnLogic: XCTestCase { +final class NBKFlexibleWidthTestsOnLogicAsIntXL: XCTestCase { typealias T = IntXL @@ -51,10 +51,10 @@ final class IntXLTestsOnLogic: XCTestCase { } //*============================================================================* -// MARK: * NBK x UIntXL x Logic +// MARK: * NBK x Flexible Width x Logic x UIntXL //*============================================================================* -final class UIntXLTestsOnLogic: XCTestCase { +final class NBKFlexibleWidthTestsOnLogicAsUIntXL: XCTestCase { typealias T = UIntXL @@ -104,4 +104,46 @@ final class UIntXLTestsOnLogic: XCTestCase { } } +//*============================================================================* +// MARK: * NBK x Flexible Width x Logic x Assertions +//*============================================================================* + +private func NBKAssertNot( +_ operand: T, _ result: T, +file: StaticString = #file, line: UInt = #line) { + if operand.words.last != UInt.max { + XCTAssertEqual(~operand, result, file: file, line: line) + XCTAssertEqual(~result, operand, file: file, line: line) + } else { + XCTAssertEqual(~operand, result, file: file, line: line) + } +} + +private func NBKAssertAnd( +_ lhs: T, _ rhs: T, _ result: T, +file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual( lhs & rhs, result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs &= rhs; return lhs }(), result, file: file, line: line) + XCTAssertEqual( rhs & lhs, result, file: file, line: line) + XCTAssertEqual({ var rhs = rhs; rhs &= lhs; return rhs }(), result, file: file, line: line) +} + +private func NBKAssertOr( +_ lhs: T, _ rhs: T, _ result: T, +file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual( lhs | rhs, result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs |= rhs; return lhs }(), result, file: file, line: line) + XCTAssertEqual( rhs | lhs, result, file: file, line: line) + XCTAssertEqual({ var rhs = rhs; rhs |= lhs; return rhs }(), result, file: file, line: line) +} + +private func NBKAssertXor( +_ lhs: T, _ rhs: T, _ result: T, +file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual( lhs ^ rhs, result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs ^= rhs; return lhs }(), result, file: file, line: line) + XCTAssertEqual( rhs ^ lhs, result, file: file, line: line) + XCTAssertEqual({ var rhs = rhs; rhs ^= lhs; return rhs }(), result, file: file, line: line) +} + #endif diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Multiplication.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Multiplication.swift similarity index 83% rename from Tests/NBKFlexibleWidthKitTests/IntXL+Multiplication.swift rename to Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Multiplication.swift index 4ad35116..abac5203 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Multiplication.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Multiplication.swift @@ -18,10 +18,10 @@ private typealias X = [UInt64] private typealias Y = [UInt32] //*============================================================================* -// MARK: * NBK x IntXL x Multiplication +// MARK: * NBK x Flexible Width x Multiplication x IntXL //*============================================================================* -final class IntXLTestsOnMultiplication: XCTestCase { +final class NBKFlexibleWidthTestsOnMultiplicationAsIntXL: XCTestCase { typealias T = IntXL typealias M = UIntXL @@ -81,10 +81,10 @@ final class IntXLTestsOnMultiplication: XCTestCase { } //*============================================================================* -// MARK: * NBK x UIntXL x Multiplication +// MARK: * NBK x Flexible Width x Multiplication x UIntXL //*============================================================================* -final class UIntXLTestsOnMultiplication: XCTestCase { +final class NBKFlexibleWidthTestsOnMultiplicationAsUIntXL: XCTestCase { typealias T = UIntXL typealias M = UIntXL @@ -136,4 +136,28 @@ final class UIntXLTestsOnMultiplication: XCTestCase { } } +//*============================================================================* +// MARK: * NBK x Flexible Width x Multiplication x Assertions +//*============================================================================* + +private func NBKAssertMultiplication( +_ lhs: T, _ rhs: T, _ result: T, +file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual( lhs * rhs, result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs *= rhs; return lhs }(), result, file: file, line: line) + + XCTAssertEqual(lhs.multiplied(by: rhs), result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs.multiply(by: rhs); return lhs }(), result, file: file, line: line) +} + +private func NBKAssertMultiplicationByDigit( +_ lhs: T, _ rhs: T.Digit, _ result: T, +file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual( lhs * rhs, result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs *= rhs; return lhs }(), result, file: file, line: line) + + XCTAssertEqual(lhs.multiplied(by: rhs, adding: UInt.zero), result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs.multiply(by: rhs, adding: UInt.zero); return lhs }(), result, file: file, line: line) +} + #endif diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Numbers.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Numbers.swift similarity index 92% rename from Tests/NBKFlexibleWidthKitTests/IntXL+Numbers.swift rename to Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Numbers.swift index 7329598c..c970c7eb 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Numbers.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Numbers.swift @@ -18,10 +18,10 @@ private typealias X = [UInt64] private typealias Y = [UInt32] //*============================================================================* -// MARK: * NBK x IntXL x Numbers +// MARK: * NBK x Flexible Width x Numbers x IntXL //*============================================================================* -final class IntXLTestsOnNumbers: XCTestCase { +final class NBKFlexibleWidthTestsOnNumbersAsIntXL: XCTestCase { typealias S = IntXL typealias T = IntXL @@ -304,10 +304,10 @@ final class IntXLTestsOnNumbers: XCTestCase { } //*============================================================================* -// MARK: * NBK x UIntXL x Numbers +// MARK: * NBK x Flexible Width x Numbers x UIntXL //*============================================================================* -final class UIntXLTestsOnNumbers: XCTestCase { +final class NBKFlexibleWidthTestsOnNumbersAsUIntXL: XCTestCase { typealias S = IntXL typealias T = UIntXL @@ -573,4 +573,45 @@ final class UIntXLTestsOnNumbers: XCTestCase { } } +//*============================================================================* +// MARK: * NBK x Flexible Width x Numbers x Assertions +//*============================================================================* + +private func NBKAssertNumbers( +from value: I, default: O, +file: StaticString = #file, line: UInt = #line) { + NBKAssertNumbers(from: value, exactly: `default`, clamping: `default`, truncating: `default`, file: file, line: line) +} + +private func NBKAssertNumbers( +from value: I, default: O, exactly: O?, +file: StaticString = #file, line: UInt = #line) { + NBKAssertNumbers(from: value, exactly: exactly, clamping: `default`, truncating: `default`, file: file, line: line) +} + +private func NBKAssertNumbers( +from value: I, default: O, clamping: O, +file: StaticString = #file, line: UInt = #line) { + NBKAssertNumbers(from: value, exactly: `default`, clamping: clamping, truncating: `default`, file: file, line: line) +} + +private func NBKAssertNumbers( +from value: I, default: O, truncating: O, +file: StaticString = #file, line: UInt = #line) { + NBKAssertNumbers(from: value, exactly: `default`, clamping: `default`, truncating: truncating, file: file, line: line) +} + +private func NBKAssertNumbers( +from value: I, exactly: O?, clamping: O, truncating: O, +file: StaticString = #file, line: UInt = #line) { + //=--------------------------------------= + if let exactly = exactly { + XCTAssertEqual(O(value), exactly, file: file, line: line) + } + //=--------------------------------------= + XCTAssertEqual(O(exactly: value), exactly, file: file, line: line) + XCTAssertEqual(O(clamping: value), clamping, file: file, line: line) + XCTAssertEqual(O(truncatingIfNeeded: value), truncating, file: file, line: line) +} + #endif diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Shifts.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Shifts.swift similarity index 75% rename from Tests/NBKFlexibleWidthKitTests/IntXL+Shifts.swift rename to Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Shifts.swift index 27d2a156..fd77a3c9 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Shifts.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Shifts.swift @@ -18,10 +18,10 @@ private typealias X = [UInt64] private typealias Y = [UInt32] //*============================================================================* -// MARK: * NBK x IntXL x Shifts +// MARK: * NBK x Flexible Width x Shifts x IntXL //*============================================================================* -final class IntXLTestsOnShifts: XCTestCase { +final class NBKFlexibleWidthTestsOnShiftsAsIntXL: XCTestCase { typealias T = IntXL @@ -136,10 +136,10 @@ final class IntXLTestsOnShifts: XCTestCase { } //*============================================================================* -// MARK: * NBK x UIntXL x Shifts +// MARK: * NBK x Flexible Width x Shifts x UIntXL //*============================================================================* -final class UIntXLTestsOnShifts: XCTestCase { +final class NBKFlexibleWidthTestsOnShiftsAsUIntXL: XCTestCase { typealias T = UIntXL @@ -253,4 +253,72 @@ final class UIntXLTestsOnShifts: XCTestCase { } } +//*============================================================================* +// MARK: * NBK x Flexible Width x Shifts x Assertions +//*============================================================================* + +private func NBKAssertShiftLeft( +_ lhs: T, _ rhs: Int, _ result: T, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + let (words, bits) = rhs.quotientAndRemainder(dividingBy: UInt.bitWidth) + //=------------------------------------------= + XCTAssertEqual( lhs << rhs, result, file: file, line: line) + XCTAssertEqual( lhs >> -rhs, result, file: file, line: line) + + XCTAssertEqual({ var lhs = lhs; lhs <<= rhs; return lhs }(), result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs >>= -rhs; return lhs }(), result, file: file, line: line) + + XCTAssertEqual(lhs.bitshiftedLeftSmart(by: rhs), result, file: file, line: line) + XCTAssertEqual(lhs.bitshiftedRightSmart(by: -rhs), result, file: file, line: line) + + XCTAssertEqual({ var lhs = lhs; lhs.bitshiftLeftSmart(by: rhs); return lhs }(), result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs.bitshiftRightSmart(by: -rhs); return lhs }(), result, file: file, line: line) + //=------------------------------------------= + if 0 ..< lhs.bitWidth ~= rhs { + XCTAssertEqual(lhs.bitshiftedLeft(by: rhs), result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs.bitshiftLeft(by: rhs); return lhs }(), result, file: file, line: line) + + XCTAssertEqual(lhs.bitshiftedLeft(words: words, bits: bits), result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs.bitshiftLeft(words: words, bits: bits); return lhs }(), result, file: file, line: line) + } + //=------------------------------------------= + if 0 ..< lhs.bitWidth ~= rhs, bits.isZero { + XCTAssertEqual(lhs.bitshiftedLeft(words: words), result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs.bitshiftLeft(words: words); return lhs }(), result, file: file, line: line) + } +} + +private func NBKAssertShiftRight( +_ lhs: T, _ rhs: Int, _ result: T, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + let (words, bits) = rhs.quotientAndRemainder(dividingBy: UInt.bitWidth) + //=------------------------------------------= + XCTAssertEqual( lhs >> rhs, result, file: file, line: line) + XCTAssertEqual( lhs << -rhs, result, file: file, line: line) + + XCTAssertEqual({ var lhs = lhs; lhs >>= rhs; return lhs }(), result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs <<= -rhs; return lhs }(), result, file: file, line: line) + + XCTAssertEqual(lhs.bitshiftedRightSmart(by: rhs), result, file: file, line: line) + XCTAssertEqual(lhs.bitshiftedLeftSmart(by: -rhs), result, file: file, line: line) + + XCTAssertEqual({ var lhs = lhs; lhs.bitshiftRightSmart(by: rhs); return lhs }(), result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs.bitshiftLeftSmart(by: -rhs); return lhs }(), result, file: file, line: line) + //=------------------------------------------= + if 0 ..< lhs.bitWidth ~= rhs { + XCTAssertEqual(lhs.bitshiftedRight(by: rhs), result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs.bitshiftRight(by: rhs); return lhs }(), result, file: file, line: line) + + XCTAssertEqual(lhs.bitshiftedRight(words: words, bits: bits), result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs.bitshiftRight(words: words, bits: bits); return lhs }(), result, file: file, line: line) + } + //=------------------------------------------= + if 0 ..< lhs.bitWidth ~= rhs, bits.isZero { + XCTAssertEqual(lhs.bitshiftedRight(words: words), result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs.bitshiftRight(words: words); return lhs }(), result, file: file, line: line) + } +} + #endif diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Subtraction.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Subtraction.swift similarity index 71% rename from Tests/NBKFlexibleWidthKitTests/IntXL+Subtraction.swift rename to Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Subtraction.swift index 4f9ea9be..a3403d72 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Subtraction.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Subtraction.swift @@ -18,10 +18,10 @@ private typealias X = [UInt64] private typealias Y = [UInt32] //*============================================================================* -// MARK: * NBK x IntXL x Subtraction +// MARK: * NBK x Flexible Width x Subtraction x IntXL //*============================================================================* -final class IntXLTestsOnSubtraction: XCTestCase { +final class NBKFlexibleWidthTestsOnSubtractionAsIntXL: XCTestCase { typealias T = IntXL @@ -113,10 +113,10 @@ final class IntXLTestsOnSubtraction: XCTestCase { } //*============================================================================* -// MARK: * NBK x UIntXL x Subtraction +// MARK: * NBK x Flexible Width x Subtraction x UIntXL //*============================================================================* -final class UIntXLTestsOnSubtraction: XCTestCase { +final class NBKFlexibleWidthTestsOnSubtractionAsUIntXL: XCTestCase { typealias T = UIntXL @@ -210,4 +210,66 @@ final class UIntXLTestsOnSubtraction: XCTestCase { } } +//*============================================================================* +// MARK: * NBK x Flexible Width x Subtraction x Assertions +//*============================================================================* + +private func NBKAssertSubtraction( +_ lhs: T, _ rhs: T, _ index: Int, _ partialValue: T, _ overflow: Bool = false, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + if !overflow, index.isZero { + XCTAssertEqual( lhs - rhs, partialValue, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs -= rhs; return lhs }(), partialValue, file: file, line: line) + + XCTAssertEqual(lhs.subtracting(rhs, at: Int.zero), partialValue, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs.subtract(rhs, at: Int.zero); return lhs }(), partialValue, file: file, line: line) + } + //=------------------------------------------= + guard let lhs = lhs as? UIntXL, let rhs = rhs as? UIntXL, let partialValue = partialValue as? UIntXL else { return } + //=------------------------------------------= + if index.isZero { + XCTAssertEqual(lhs.subtractingReportingOverflow(rhs).partialValue, partialValue, file: file, line: line) + XCTAssertEqual(lhs.subtractingReportingOverflow(rhs).overflow, overflow, file: file, line: line) + + XCTAssertEqual({ var x = lhs; let _ = x.subtractReportingOverflow(rhs); return x }(), partialValue, file: file, line: line) + XCTAssertEqual({ var x = lhs; let o = x.subtractReportingOverflow(rhs); return o }(), overflow, file: file, line: line) + } + //=------------------------------------------= + XCTAssertEqual(lhs.subtractingReportingOverflow(rhs, at: index).partialValue, partialValue, file: file, line: line) + XCTAssertEqual(lhs.subtractingReportingOverflow(rhs, at: index).overflow, overflow, file: file, line: line) + + XCTAssertEqual({ var x = lhs; let _ = x.subtractReportingOverflow(rhs, at: index); return x }(), partialValue, file: file, line: line) + XCTAssertEqual({ var x = lhs; let o = x.subtractReportingOverflow(rhs, at: index); return o }(), overflow, file: file, line: line) +} + +private func NBKAssertSubtractionByDigit( +_ lhs: T, _ rhs: T.Digit, _ index: Int, _ partialValue: T, _ overflow: Bool = false, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + if !overflow, index.isZero { + XCTAssertEqual( lhs - rhs, partialValue, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs -= rhs; return lhs }(), partialValue, file: file, line: line) + + XCTAssertEqual(lhs.subtracting(rhs, at: Int.zero), partialValue, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs.subtract(rhs, at: Int.zero); return lhs }(), partialValue, file: file, line: line) + } + //=------------------------------------------= + guard let lhs = lhs as? UIntXL, let rhs = rhs as? UIntXL.Digit, let partialValue = partialValue as? UIntXL else { return } + //=------------------------------------------= + if index.isZero { + XCTAssertEqual(lhs.subtractingReportingOverflow(rhs).partialValue, partialValue, file: file, line: line) + XCTAssertEqual(lhs.subtractingReportingOverflow(rhs).overflow, overflow, file: file, line: line) + + XCTAssertEqual({ var x = lhs; let _ = x.subtractReportingOverflow(rhs); return x }(), partialValue, file: file, line: line) + XCTAssertEqual({ var x = lhs; let o = x.subtractReportingOverflow(rhs); return o }(), overflow, file: file, line: line) + } + //=------------------------------------------= + XCTAssertEqual(lhs.subtractingReportingOverflow(rhs, at: index).partialValue, partialValue, file: file, line: line) + XCTAssertEqual(lhs.subtractingReportingOverflow(rhs, at: index).overflow, overflow, file: file, line: line) + + XCTAssertEqual({ var x = lhs; let _ = x.subtractReportingOverflow(rhs, at: index); return x }(), partialValue, file: file, line: line) + XCTAssertEqual({ var x = lhs; let o = x.subtractReportingOverflow(rhs, at: index); return o }(), overflow, file: file, line: line) +} + #endif diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Text.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Text.swift similarity index 91% rename from Tests/NBKFlexibleWidthKitTests/IntXL+Text.swift rename to Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Text.swift index b732aa61..87548b84 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Text.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Text.swift @@ -18,10 +18,10 @@ private typealias X = [UInt64] private typealias Y = [UInt32] //*============================================================================* -// MARK: * NBK x IntXL x Text +// MARK: * NBK x Flexible Width x Text x IntXL //*============================================================================* -final class IntXLTestsOnText: XCTestCase { +final class NBKFlexibleWidthTestsOnTextAsIntXL: XCTestCase { typealias T = IntXL @@ -255,10 +255,10 @@ final class IntXLTestsOnText: XCTestCase { } //*============================================================================* -// MARK: * NBK x UIntXL x Text +// MARK: * NBK x Flexible Width x Text x UIntXL //*============================================================================* -final class UIntXLTestsOnText: XCTestCase { +final class NBKFlexibleWidthTestsOnTextAsUIntXL: XCTestCase { typealias T = UIntXL @@ -476,4 +476,33 @@ final class UIntXLTestsOnText: XCTestCase { } } +//*============================================================================* +// MARK: * NBK x Flexible Width x Text x Assertions +//*============================================================================* + +private func NBKAssertDecodeText ( +_ integer: T?, _ radix: Int, _ text: String, +file: StaticString = #file, line: UInt = #line) where T: LosslessStringConvertible { + //=------------------------------------------= + if radix == 10 { + XCTAssertEqual(T(text), integer, file: file, line: line) + } + //=------------------------------------------= + XCTAssertEqual(T(text, radix: radix), integer, file: file, line: line) +} + +private func NBKAssertEncodeText( +_ integer: T, _ radix: Int, _ uppercase: Bool, _ text: String, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + if radix == 10, uppercase == false { + XCTAssertEqual(String(integer), text, file: file, line: line) + XCTAssertEqual(integer.description, text, file: file, line: line) + XCTAssertEqual(integer.description(), text, file: file, line: line) + } + //=------------------------------------------= + XCTAssertEqual(String(integer, radix: radix, uppercase: uppercase), text, file: file, line: line) + XCTAssertEqual(integer.description(radix: radix, uppercase: uppercase), text, file: file, line: line) +} + #endif diff --git a/Tests/NBKFlexibleWidthKitTests/IntXL+Words.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Words.swift similarity index 91% rename from Tests/NBKFlexibleWidthKitTests/IntXL+Words.swift rename to Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Words.swift index ac8e89e6..c633268d 100644 --- a/Tests/NBKFlexibleWidthKitTests/IntXL+Words.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Words.swift @@ -18,10 +18,10 @@ private typealias X = [UInt64] private typealias Y = [UInt32] //*============================================================================* -// MARK: * NBK x IntXL x Words +// MARK: * NBK x Flexible Width x Words x IntXL //*============================================================================* -final class IntXLTestsOnWords: XCTestCase { +final class NBKFlexibleWidthTestsOnWordsAsIntXL: XCTestCase { typealias T = IntXL typealias M = UIntXL @@ -94,10 +94,10 @@ final class IntXLTestsOnWords: XCTestCase { } //*============================================================================* -// MARK: * NBK x UIntXL x Words +// MARK: * NBK x Flexible Width x Words x UIntXL //*============================================================================* -final class UIntXLTestsOnWords: XCTestCase { +final class NBKFlexibleWidthTestsOnWordsAsUIntXL: XCTestCase { typealias T = UIntXL typealias M = UIntXL @@ -161,4 +161,15 @@ final class UIntXLTestsOnWords: XCTestCase { } } +//*============================================================================* +// MARK: * NBK x Flexible Width x Words x Assertions +//*============================================================================* + +private func NBKAssertWords( +_ integer: T, _ words: [UInt], +file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual(Array(integer.words), Array(words), file: file, line: line) + XCTAssertEqual(Array(integer.words.reversed()), Array(words.reversed()), file: file, line: line) +} + #endif diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth.swift index 3a4ca196..4885de9c 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth.swift @@ -16,7 +16,46 @@ private typealias X = [UInt64] private typealias Y = [UInt32] //*============================================================================* -// MARK: * NBK x Flexible Width x Initializers x Signed +// MARK: * NBK x Flexible Width x IntXL +//*============================================================================* + +final class NBKFlexibleWidthTestsAsIntXL: XCTestCase { + + typealias T = IntXL + typealias M = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testSign() { + XCTAssertEqual(T(sign: .plus, magnitude: 0).sign, .plus ) + XCTAssertEqual(T(sign: .minus, magnitude: 0).sign, .minus) + XCTAssertEqual(T(sign: .plus, magnitude: 1).sign, .plus ) + XCTAssertEqual(T(sign: .minus, magnitude: 1).sign, .minus) + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Assertions +//*============================================================================* + +func NBKAssertIdentical(_ lhs: IntXL?, _ rhs: IntXL?, file: StaticString = #file, line: UInt = #line) { + func description(of value: IntXL?) -> String { + value.map({ "\(UnicodeScalar($0.sign.ascii))\($0.magnitude)" }) ?? "nil" + } + //=--------------------------------------= + let success: Bool = lhs?.sign == rhs?.sign && lhs?.magnitude == rhs?.magnitude + //=--------------------------------------= + if success { + XCTAssertEqual(lhs, rhs, file: file, line: line) + } + //=--------------------------------------= + XCTAssert(success, "\(description(of: lhs)) is not identical to \(description(of: rhs))", file: file, line: line) +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Initializers x IntXL //*============================================================================* extension NBKFlexibleWidth { @@ -42,7 +81,7 @@ extension NBKFlexibleWidth { } //*============================================================================* -// MARK: * NBK x Flexible Width x Initializers x Unsigned +// MARK: * NBK x Flexible Width x Initializers x UIntXL //*============================================================================* extension NBKFlexibleWidth.Magnitude { diff --git a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Addition.swift b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Addition.swift deleted file mode 100644 index 5babe036..00000000 --- a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Addition.swift +++ /dev/null @@ -1,42 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit -import NBKFlexibleWidthKit -import XCTest - -//*============================================================================* -// MARK: * NBK x Assert x Addition -//*============================================================================* - -func NBKAssertAddition( -_ lhs: T, _ rhs: T, _ index: Int, _ partialValue: T, -file: StaticString = #file, line: UInt = #line) { - //=------------------------------------------= - if index.isZero { - XCTAssertEqual( lhs + rhs, partialValue, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs += rhs; return lhs }(), partialValue, file: file, line: line) - } - //=------------------------------------------= - XCTAssertEqual(lhs.adding(rhs, at: index), partialValue, file: file, line: line) - XCTAssertEqual({ var x = lhs; let _ = x.add(rhs, at: index); return x }(), partialValue, file: file, line: line) -} - -func NBKAssertAdditionByDigit( -_ lhs: T, _ rhs: T.Digit, _ index: Int, _ partialValue: T, -file: StaticString = #file, line: UInt = #line) { - //=------------------------------------------= - if index.isZero { - XCTAssertEqual( lhs + rhs, partialValue, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs += rhs; return lhs }(), partialValue, file: file, line: line) - } - //=------------------------------------------= - XCTAssertEqual(lhs.adding(rhs, at: index), partialValue, file: file, line: line) - XCTAssertEqual({ var x = lhs; let _ = x.add(rhs, at: index); return x }(), partialValue, file: file, line: line) -} diff --git a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Comparisons.swift b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Comparisons.swift deleted file mode 100644 index e2d5deb1..00000000 --- a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Comparisons.swift +++ /dev/null @@ -1,75 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit -import NBKFlexibleWidthKit -import XCTest - -//*============================================================================* -// MARK: * NBK x Assert x Comparisons -//*============================================================================* - -func NBKAssertSignum( -_ operand: T, _ signum: Int, -file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual(Int(operand.signum() as Int), signum, file: file, line: line) - XCTAssertEqual(Int(operand.signum() as T ), signum, file: file, line: line) // stdlib -} - -func NBKAssertComparisons( -_ lhs: T, _ rhs: T, _ signum: Int, -file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual(lhs == rhs, signum == 0, file: file, line: line) - XCTAssertEqual(lhs != rhs, signum != 0, file: file, line: line) - - XCTAssertEqual(lhs < rhs, signum == -1, file: file, line: line) - XCTAssertEqual(lhs <= rhs, signum != 1, file: file, line: line) - - XCTAssertEqual(lhs > rhs, signum == 1, file: file, line: line) - XCTAssertEqual(lhs >= rhs, signum != -1, file: file, line: line) - - XCTAssertEqual(lhs.compared(to: rhs), signum, file: file, line: line) -} - -func NBKAssertComparisonsAtIndex( -_ lhs: T, _ rhs: T, _ index: Int, _ signum: Int, -file: StaticString = #file, line: UInt = #line) { - //=------------------------------------------= - if index.isZero { - NBKAssertComparisons(lhs, rhs, signum, file: file, line: line) - } - //=------------------------------------------= - XCTAssertEqual(lhs.compared(to: rhs, at: index), signum, file: file, line: line) -} - -func NBKAssertComparisonsByDigit( -_ lhs: T, _ rhs: T.Digit, _ signum: Int, -file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual(lhs == rhs, signum == 0, file: file, line: line) - XCTAssertEqual(lhs != rhs, signum != 0, file: file, line: line) - - XCTAssertEqual(lhs < rhs, signum == -1, file: file, line: line) - XCTAssertEqual(lhs <= rhs, signum != 1, file: file, line: line) - - XCTAssertEqual(lhs > rhs, signum == 1, file: file, line: line) - XCTAssertEqual(lhs >= rhs, signum != -1, file: file, line: line) - - XCTAssertEqual(lhs.compared(to: rhs), signum, file: file, line: line) -} - -func NBKAssertComparisonsByDigitAtIndex( -_ lhs: T, _ rhs: T.Digit, _ index: Int, _ signum: Int, -file: StaticString = #file, line: UInt = #line) { - //=------------------------------------------= - if index.isZero { - NBKAssertComparisonsByDigit(lhs, rhs, signum, file: file, line: line) - } - //=------------------------------------------= - XCTAssertEqual(lhs.compared(to: rhs, at: index), signum, file: file, line: line) -} diff --git a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Complements.swift b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Complements.swift deleted file mode 100644 index 9dc67515..00000000 --- a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Complements.swift +++ /dev/null @@ -1,59 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit -import NBKFlexibleWidthKit -import XCTest - -//*============================================================================* -// MARK: * NBK x Assert x Complements -//*============================================================================* - -func NBKAssertOnesComplement( -_ integer: T, _ result: T, -file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual(integer.onesComplement(), result, file: file, line: line) - XCTAssertEqual(integer.twosComplementSubsequence(false).partialValue, result, file: file, line: line) - - XCTAssertEqual({ var x = integer; let _ = x.formOnesComplement(); return x }(), result, file: file, line: line) - XCTAssertEqual({ var x = integer; let _ = x.formTwosComplementSubsequence(false); return x }(), result, file: file, line: line) -} - -func NBKAssertTwosComplement( -_ integer: T, _ partialValue: T, _ overflow: Bool = false, -file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual(integer.twosComplement(), partialValue, file: file, line: line) - XCTAssertEqual(integer.twosComplementReportingOverflow().partialValue, partialValue, file: file, line: line) - XCTAssertEqual(integer.twosComplementReportingOverflow().overflow, overflow, file: file, line: line) - XCTAssertEqual(integer.twosComplementSubsequence(true ).partialValue, partialValue, file: file, line: line) - XCTAssertEqual(integer.twosComplementSubsequence(true ).overflow, overflow, file: file, line: line) - - XCTAssertEqual({ var x = integer; x.formTwosComplement(); return x }(), partialValue, file: file, line: line) - XCTAssertEqual({ var x = integer; let _ = x.formTwosComplementReportingOverflow(); return x }(), partialValue, file: file, line: line) - XCTAssertEqual({ var x = integer; let o = x.formTwosComplementReportingOverflow(); return o }(), overflow, file: file, line: line) - XCTAssertEqual({ var x = integer; let _ = x.formTwosComplementSubsequence(true ); return x }(), partialValue, file: file, line: line) - XCTAssertEqual({ var x = integer; let o = x.formTwosComplementSubsequence(true ); return o }(), overflow, file: file, line: line) -} - -func NBKAssertAdditiveInverse( -_ operand: IntXL, _ partialValue: IntXL, _ overflow: Bool = false, -file: StaticString = #file, line: UInt = #line) { - //=------------------------------------------= - if !overflow { - NBKAssertIdentical(-operand, partialValue, file: file, line: line) - NBKAssertIdentical((operand).negated(), partialValue, file: file, line: line) - NBKAssertIdentical({ var x = operand; x.negate(); return x }(), partialValue, file: file, line: line) - } - //=------------------------------------------= - NBKAssertIdentical(operand.negatedReportingOverflow().partialValue, partialValue, file: file, line: line) - XCTAssertEqual/**/(operand.negatedReportingOverflow().overflow, overflow, file: file, line: line) - - NBKAssertIdentical({ var x = operand; let _ = x.negateReportingOverflow(); return x }(), partialValue, file: file, line: line) - XCTAssertEqual/**/({ var x = operand; let o = x.negateReportingOverflow(); return o }(), overflow, file: file, line: line) -} diff --git a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Division.swift b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Division.swift deleted file mode 100644 index 82dbdc04..00000000 --- a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Division.swift +++ /dev/null @@ -1,91 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit -@testable import NBKFlexibleWidthKit -import XCTest - -//*============================================================================* -// MARK: * NBK x Assert x Division -//*============================================================================* - -func NBKAssertDivision( -_ lhs: T, _ rhs: T, _ quotient: T, _ remainder: T, _ overflow: Bool = false, -file: StaticString = #file, line: UInt = #line) { - //=------------------------------------------= - XCTAssertEqual(lhs, quotient * rhs + remainder, "lhs != rhs * quotient + remainder", file: file, line: line) - //=------------------------------------------= - if !overflow { - XCTAssertEqual(lhs / rhs, quotient, file: file, line: line) - XCTAssertEqual(lhs % rhs, remainder, file: file, line: line) - - XCTAssertEqual({ var x = lhs; x /= rhs; return x }(), quotient, file: file, line: line) - XCTAssertEqual({ var x = lhs; x %= rhs; return x }(), remainder, file: file, line: line) - - XCTAssertEqual(lhs.quotientAndRemainder(dividingBy: rhs).quotient, quotient, file: file, line: line) - XCTAssertEqual(lhs.quotientAndRemainder(dividingBy: rhs).remainder, remainder, file: file, line: line) - } - //=------------------------------------------= - XCTAssertEqual(lhs.dividedReportingOverflow(by: rhs).partialValue, quotient, file: file, line: line) - XCTAssertEqual(lhs.dividedReportingOverflow(by: rhs).overflow, overflow, file: file, line: line) - - XCTAssertEqual({ var x = lhs; let _ = x.divideReportingOverflow(by: rhs); return x }(), quotient, file: file, line: line) - XCTAssertEqual({ var x = lhs; let o = x.divideReportingOverflow(by: rhs); return o }(), overflow, file: file, line: line) - - XCTAssertEqual(lhs.remainderReportingOverflow(dividingBy: rhs).partialValue, remainder, file: file, line: line) - XCTAssertEqual(lhs.remainderReportingOverflow(dividingBy: rhs).overflow, overflow, file: file, line: line) - - XCTAssertEqual({ var x = lhs; let _ = x.formRemainderReportingOverflow(dividingBy: rhs); return x }(), remainder, file: file, line: line) - XCTAssertEqual({ var x = lhs; let o = x.formRemainderReportingOverflow(dividingBy: rhs); return o }(), overflow, file: file, line: line) - - XCTAssertEqual(lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs).partialValue.quotient, quotient, file: file, line: line) - XCTAssertEqual(lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs).partialValue.remainder, remainder, file: file, line: line) - XCTAssertEqual(lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs).overflow, overflow, file: file, line: line) - //=------------------------------------------= - guard let lhs = lhs as? UIntXL, let rhs = rhs as? UIntXL, let quotient = quotient as? UIntXL, let remainder = remainder as? UIntXL else { return } - //=------------------------------------------= - XCTAssertEqual(lhs.quotientAndRemainderReportingOverflowAsNormal(dividingBy: rhs).partialValue.quotient, quotient, file: file, line: line) - XCTAssertEqual(lhs.quotientAndRemainderReportingOverflowAsNormal(dividingBy: rhs).partialValue.remainder, remainder, file: file, line: line) - XCTAssertEqual(lhs.quotientAndRemainderReportingOverflowAsNormal(dividingBy: rhs).overflow, overflow, file: file, line: line) -} - -func NBKAssertDivisionByDigit( -_ lhs: T, _ rhs: T.Digit, _ quotient: T, _ remainder: T.Digit, _ overflow: Bool = false, -file: StaticString = #file, line: UInt = #line) { - let extended = T(digit: remainder) - //=------------------------------------------= - XCTAssertEqual(lhs, quotient * rhs + remainder, "lhs != rhs * quotient + remainder", file: file, line: line) - //=------------------------------------------= - if !overflow { - XCTAssertEqual(lhs / rhs, quotient, file: file, line: line) - XCTAssertEqual(lhs % rhs, remainder, file: file, line: line) - - XCTAssertEqual({ var x = lhs; x /= rhs; return x }(), quotient, file: file, line: line) - XCTAssertEqual({ var x = lhs; x %= rhs; return x }(), extended, file: file, line: line) - - XCTAssertEqual(lhs.quotientAndRemainder(dividingBy: rhs).quotient, quotient, file: file, line: line) - XCTAssertEqual(lhs.quotientAndRemainder(dividingBy: rhs).remainder, remainder, file: file, line: line) - } - //=------------------------------------------= - XCTAssertEqual(lhs.dividedReportingOverflow(by: rhs).partialValue, quotient, file: file, line: line) - XCTAssertEqual(lhs.dividedReportingOverflow(by: rhs).overflow, overflow, file: file, line: line) - - XCTAssertEqual({ var x = lhs; let _ = x.divideReportingOverflow(by: rhs); return x }(), quotient, file: file, line: line) - XCTAssertEqual({ var x = lhs; let o = x.divideReportingOverflow(by: rhs); return o }(), overflow, file: file, line: line) - - XCTAssertEqual(lhs.remainderReportingOverflow(dividingBy: rhs).partialValue, remainder, file: file, line: line) - XCTAssertEqual(lhs.remainderReportingOverflow(dividingBy: rhs).overflow, overflow, file: file, line: line) - - XCTAssertEqual({ var x = lhs; let _ = x.formRemainderReportingOverflow(dividingBy: rhs); return x }(), extended, file: file, line: line) - XCTAssertEqual({ var x = lhs; let o = x.formRemainderReportingOverflow(dividingBy: rhs); return o }(), overflow, file: file, line: line) - - XCTAssertEqual(lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs).partialValue.quotient, quotient, file: file, line: line) - XCTAssertEqual(lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs).partialValue.remainder, remainder, file: file, line: line) - XCTAssertEqual(lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs).overflow, overflow, file: file, line: line) -} diff --git a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Identical.swift b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Identical.swift deleted file mode 100644 index de85cefc..00000000 --- a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Identical.swift +++ /dev/null @@ -1,29 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKFlexibleWidthKit -import XCTest - -//*============================================================================* -// MARK: * NBK x Assert x Identical -//*============================================================================* - -func NBKAssertIdentical(_ lhs: IntXL?, _ rhs: IntXL?, file: StaticString = #file, line: UInt = #line) { - func description(of value: IntXL?) -> String { - value.map({ "\(UnicodeScalar($0.sign.ascii))\($0.magnitude)" }) ?? "nil" - } - //=--------------------------------------= - let success: Bool = lhs?.sign == rhs?.sign && lhs?.magnitude == rhs?.magnitude - //=--------------------------------------= - if success { - XCTAssertEqual(lhs, rhs, file: file, line: line) - } - //=--------------------------------------= - XCTAssert(success, "\(description(of: lhs)) is not identical to \(description(of: rhs))", file: file, line: line) -} diff --git a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Logic.swift b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Logic.swift deleted file mode 100644 index 1bf9eef1..00000000 --- a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Logic.swift +++ /dev/null @@ -1,54 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit -import NBKFlexibleWidthKit -import XCTest - -//*============================================================================* -// MARK: * NBK x Assert x Logic -//*============================================================================* - -func NBKAssertNot( -_ operand: T, _ result: T, -file: StaticString = #file, line: UInt = #line) { - if operand.words.last != UInt.max { - XCTAssertEqual(~operand, result, file: file, line: line) - XCTAssertEqual(~result, operand, file: file, line: line) - } else { - XCTAssertEqual(~operand, result, file: file, line: line) - } -} - -func NBKAssertAnd( -_ lhs: T, _ rhs: T, _ result: T, -file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual( lhs & rhs, result, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs &= rhs; return lhs }(), result, file: file, line: line) - XCTAssertEqual( rhs & lhs, result, file: file, line: line) - XCTAssertEqual({ var rhs = rhs; rhs &= lhs; return rhs }(), result, file: file, line: line) -} - -func NBKAssertOr( -_ lhs: T, _ rhs: T, _ result: T, -file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual( lhs | rhs, result, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs |= rhs; return lhs }(), result, file: file, line: line) - XCTAssertEqual( rhs | lhs, result, file: file, line: line) - XCTAssertEqual({ var rhs = rhs; rhs |= lhs; return rhs }(), result, file: file, line: line) -} - -func NBKAssertXor( -_ lhs: T, _ rhs: T, _ result: T, -file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual( lhs ^ rhs, result, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs ^= rhs; return lhs }(), result, file: file, line: line) - XCTAssertEqual( rhs ^ lhs, result, file: file, line: line) - XCTAssertEqual({ var rhs = rhs; rhs ^= lhs; return rhs }(), result, file: file, line: line) -} diff --git a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Multiplication.swift b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Multiplication.swift deleted file mode 100644 index 9aa6f954..00000000 --- a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Multiplication.swift +++ /dev/null @@ -1,36 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit -@testable import NBKFlexibleWidthKit -import XCTest - -//*============================================================================* -// MARK: * NBK x Assert x Multiplication -//*============================================================================* - -func NBKAssertMultiplication( -_ lhs: T, _ rhs: T, _ result: T, -file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual( lhs * rhs, result, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs *= rhs; return lhs }(), result, file: file, line: line) - - XCTAssertEqual(lhs.multiplied(by: rhs), result, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs.multiply(by: rhs); return lhs }(), result, file: file, line: line) -} - -func NBKAssertMultiplicationByDigit( -_ lhs: T, _ rhs: T.Digit, _ result: T, -file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual( lhs * rhs, result, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs *= rhs; return lhs }(), result, file: file, line: line) - - XCTAssertEqual(lhs.multiplied(by: rhs, adding: UInt.zero), result, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs.multiply(by: rhs, adding: UInt.zero); return lhs }(), result, file: file, line: line) -} diff --git a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Numbers.swift b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Numbers.swift deleted file mode 100644 index 55a20dd3..00000000 --- a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Numbers.swift +++ /dev/null @@ -1,53 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit -import NBKFlexibleWidthKit -import XCTest - -//*============================================================================* -// MARK: * NBK x Assert x Numbers -//*============================================================================* - -func NBKAssertNumbers( -from value: I, default: O, -file: StaticString = #file, line: UInt = #line) { - NBKAssertNumbers(from: value, exactly: `default`, clamping: `default`, truncating: `default`, file: file, line: line) -} - -func NBKAssertNumbers( -from value: I, default: O, exactly: O?, -file: StaticString = #file, line: UInt = #line) { - NBKAssertNumbers(from: value, exactly: exactly, clamping: `default`, truncating: `default`, file: file, line: line) -} - -func NBKAssertNumbers( -from value: I, default: O, clamping: O, -file: StaticString = #file, line: UInt = #line) { - NBKAssertNumbers(from: value, exactly: `default`, clamping: clamping, truncating: `default`, file: file, line: line) -} - -func NBKAssertNumbers( -from value: I, default: O, truncating: O, -file: StaticString = #file, line: UInt = #line) { - NBKAssertNumbers(from: value, exactly: `default`, clamping: `default`, truncating: truncating, file: file, line: line) -} - -func NBKAssertNumbers( -from value: I, exactly: O?, clamping: O, truncating: O, -file: StaticString = #file, line: UInt = #line) { - //=--------------------------------------= - if let exactly = exactly { - XCTAssertEqual(O(value), exactly, file: file, line: line) - } - //=--------------------------------------= - XCTAssertEqual(O(exactly: value), exactly, file: file, line: line) - XCTAssertEqual(O(clamping: value), clamping, file: file, line: line) - XCTAssertEqual(O(truncatingIfNeeded: value), truncating, file: file, line: line) -} diff --git a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Shifts.swift b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Shifts.swift deleted file mode 100644 index 3d62ed26..00000000 --- a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Shifts.swift +++ /dev/null @@ -1,80 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit -import NBKFlexibleWidthKit -import XCTest - -//*============================================================================* -// MARK: * NBK x Assert x Shifts -//*============================================================================* - -func NBKAssertShiftLeft( -_ lhs: T, _ rhs: Int, _ result: T, -file: StaticString = #file, line: UInt = #line) { - //=------------------------------------------= - let (words, bits) = rhs.quotientAndRemainder(dividingBy: UInt.bitWidth) - //=------------------------------------------= - XCTAssertEqual( lhs << rhs, result, file: file, line: line) - XCTAssertEqual( lhs >> -rhs, result, file: file, line: line) - - XCTAssertEqual({ var lhs = lhs; lhs <<= rhs; return lhs }(), result, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs >>= -rhs; return lhs }(), result, file: file, line: line) - - XCTAssertEqual(lhs.bitshiftedLeftSmart(by: rhs), result, file: file, line: line) - XCTAssertEqual(lhs.bitshiftedRightSmart(by: -rhs), result, file: file, line: line) - - XCTAssertEqual({ var lhs = lhs; lhs.bitshiftLeftSmart(by: rhs); return lhs }(), result, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs.bitshiftRightSmart(by: -rhs); return lhs }(), result, file: file, line: line) - //=------------------------------------------= - if 0 ..< lhs.bitWidth ~= rhs { - XCTAssertEqual(lhs.bitshiftedLeft(by: rhs), result, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs.bitshiftLeft(by: rhs); return lhs }(), result, file: file, line: line) - - XCTAssertEqual(lhs.bitshiftedLeft(words: words, bits: bits), result, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs.bitshiftLeft(words: words, bits: bits); return lhs }(), result, file: file, line: line) - } - //=------------------------------------------= - if 0 ..< lhs.bitWidth ~= rhs, bits.isZero { - XCTAssertEqual(lhs.bitshiftedLeft(words: words), result, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs.bitshiftLeft(words: words); return lhs }(), result, file: file, line: line) - } -} - -func NBKAssertShiftRight( -_ lhs: T, _ rhs: Int, _ result: T, -file: StaticString = #file, line: UInt = #line) { - //=------------------------------------------= - let (words, bits) = rhs.quotientAndRemainder(dividingBy: UInt.bitWidth) - //=------------------------------------------= - XCTAssertEqual( lhs >> rhs, result, file: file, line: line) - XCTAssertEqual( lhs << -rhs, result, file: file, line: line) - - XCTAssertEqual({ var lhs = lhs; lhs >>= rhs; return lhs }(), result, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs <<= -rhs; return lhs }(), result, file: file, line: line) - - XCTAssertEqual(lhs.bitshiftedRightSmart(by: rhs), result, file: file, line: line) - XCTAssertEqual(lhs.bitshiftedLeftSmart(by: -rhs), result, file: file, line: line) - - XCTAssertEqual({ var lhs = lhs; lhs.bitshiftRightSmart(by: rhs); return lhs }(), result, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs.bitshiftLeftSmart(by: -rhs); return lhs }(), result, file: file, line: line) - //=------------------------------------------= - if 0 ..< lhs.bitWidth ~= rhs { - XCTAssertEqual(lhs.bitshiftedRight(by: rhs), result, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs.bitshiftRight(by: rhs); return lhs }(), result, file: file, line: line) - - XCTAssertEqual(lhs.bitshiftedRight(words: words, bits: bits), result, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs.bitshiftRight(words: words, bits: bits); return lhs }(), result, file: file, line: line) - } - //=------------------------------------------= - if 0 ..< lhs.bitWidth ~= rhs, bits.isZero { - XCTAssertEqual(lhs.bitshiftedRight(words: words), result, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs.bitshiftRight(words: words); return lhs }(), result, file: file, line: line) - } -} diff --git a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Subtraction.swift b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Subtraction.swift deleted file mode 100644 index e28f5af0..00000000 --- a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Subtraction.swift +++ /dev/null @@ -1,74 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit -import NBKFlexibleWidthKit -import XCTest - -//*============================================================================* -// MARK: * NBK x Assert x Subtraction -//*============================================================================* - -func NBKAssertSubtraction( -_ lhs: T, _ rhs: T, _ index: Int, _ partialValue: T, _ overflow: Bool = false, -file: StaticString = #file, line: UInt = #line) { - //=------------------------------------------= - if !overflow, index.isZero { - XCTAssertEqual( lhs - rhs, partialValue, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs -= rhs; return lhs }(), partialValue, file: file, line: line) - - XCTAssertEqual(lhs.subtracting(rhs, at: Int.zero), partialValue, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs.subtract(rhs, at: Int.zero); return lhs }(), partialValue, file: file, line: line) - } - //=------------------------------------------= - guard let lhs = lhs as? UIntXL, let rhs = rhs as? UIntXL, let partialValue = partialValue as? UIntXL else { return } - //=------------------------------------------= - if index.isZero { - XCTAssertEqual(lhs.subtractingReportingOverflow(rhs).partialValue, partialValue, file: file, line: line) - XCTAssertEqual(lhs.subtractingReportingOverflow(rhs).overflow, overflow, file: file, line: line) - - XCTAssertEqual({ var x = lhs; let _ = x.subtractReportingOverflow(rhs); return x }(), partialValue, file: file, line: line) - XCTAssertEqual({ var x = lhs; let o = x.subtractReportingOverflow(rhs); return o }(), overflow, file: file, line: line) - } - //=------------------------------------------= - XCTAssertEqual(lhs.subtractingReportingOverflow(rhs, at: index).partialValue, partialValue, file: file, line: line) - XCTAssertEqual(lhs.subtractingReportingOverflow(rhs, at: index).overflow, overflow, file: file, line: line) - - XCTAssertEqual({ var x = lhs; let _ = x.subtractReportingOverflow(rhs, at: index); return x }(), partialValue, file: file, line: line) - XCTAssertEqual({ var x = lhs; let o = x.subtractReportingOverflow(rhs, at: index); return o }(), overflow, file: file, line: line) -} - -func NBKAssertSubtractionByDigit( -_ lhs: T, _ rhs: T.Digit, _ index: Int, _ partialValue: T, _ overflow: Bool = false, -file: StaticString = #file, line: UInt = #line) { - //=------------------------------------------= - if !overflow, index.isZero { - XCTAssertEqual( lhs - rhs, partialValue, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs -= rhs; return lhs }(), partialValue, file: file, line: line) - - XCTAssertEqual(lhs.subtracting(rhs, at: Int.zero), partialValue, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs.subtract(rhs, at: Int.zero); return lhs }(), partialValue, file: file, line: line) - } - //=------------------------------------------= - guard let lhs = lhs as? UIntXL, let rhs = rhs as? UIntXL.Digit, let partialValue = partialValue as? UIntXL else { return } - //=------------------------------------------= - if index.isZero { - XCTAssertEqual(lhs.subtractingReportingOverflow(rhs).partialValue, partialValue, file: file, line: line) - XCTAssertEqual(lhs.subtractingReportingOverflow(rhs).overflow, overflow, file: file, line: line) - - XCTAssertEqual({ var x = lhs; let _ = x.subtractReportingOverflow(rhs); return x }(), partialValue, file: file, line: line) - XCTAssertEqual({ var x = lhs; let o = x.subtractReportingOverflow(rhs); return o }(), overflow, file: file, line: line) - } - //=------------------------------------------= - XCTAssertEqual(lhs.subtractingReportingOverflow(rhs, at: index).partialValue, partialValue, file: file, line: line) - XCTAssertEqual(lhs.subtractingReportingOverflow(rhs, at: index).overflow, overflow, file: file, line: line) - - XCTAssertEqual({ var x = lhs; let _ = x.subtractReportingOverflow(rhs, at: index); return x }(), partialValue, file: file, line: line) - XCTAssertEqual({ var x = lhs; let o = x.subtractReportingOverflow(rhs, at: index); return o }(), overflow, file: file, line: line) -} diff --git a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Text.swift b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Text.swift deleted file mode 100644 index 8f7b4d41..00000000 --- a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Text.swift +++ /dev/null @@ -1,41 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit -import NBKFlexibleWidthKit -import XCTest - -//*============================================================================* -// MARK: * NBK x Assert x Text -//*============================================================================* - -func NBKAssertDecodeText ( -_ integer: T?, _ radix: Int, _ text: String, -file: StaticString = #file, line: UInt = #line) where T: LosslessStringConvertible { - //=------------------------------------------= - if radix == 10 { - XCTAssertEqual(T(text), integer, file: file, line: line) - } - //=------------------------------------------= - XCTAssertEqual(T(text, radix: radix), integer, file: file, line: line) -} - -func NBKAssertEncodeText( -_ integer: T, _ radix: Int, _ uppercase: Bool, _ text: String, -file: StaticString = #file, line: UInt = #line) { - //=------------------------------------------= - if radix == 10, uppercase == false { - XCTAssertEqual(String(integer), text, file: file, line: line) - XCTAssertEqual(integer.description, text, file: file, line: line) - XCTAssertEqual(integer.description(), text, file: file, line: line) - } - //=------------------------------------------= - XCTAssertEqual(String(integer, radix: radix, uppercase: uppercase), text, file: file, line: line) - XCTAssertEqual(integer.description(radix: radix, uppercase: uppercase), text, file: file, line: line) -} diff --git a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Words.swift b/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Words.swift deleted file mode 100644 index 0ab79c70..00000000 --- a/Tests/NBKFlexibleWidthKitTests/Utilities/NBKAssert+Words.swift +++ /dev/null @@ -1,23 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit -import NBKFlexibleWidthKit -import XCTest - -//*============================================================================* -// MARK: * NBK x Assert x Words -//*============================================================================* - -func NBKAssertWords( -_ integer: T, _ words: [UInt], -file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual(Array(integer.words), Array(words), file: file, line: line) - XCTAssertEqual(Array(integer.words.reversed()), Array(words.reversed()), file: file, line: line) -} From c6cef2fa6b847cfb690bb01322f92e4436c59c6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sun, 6 Aug 2023 14:54:12 +0200 Subject: [PATCH 046/133] NBKResizableWidthKit: TODOs. --- .swiftpm/Numberick.xctestplan | 5 ++ .../NBKFlexibleWidth+Bits.swift | 14 ++-- .../NBKFlexibleWidth+Numbers.swift | 2 +- .../NBKFlexibleWidth+Protocols.swift | 12 ++-- .../NBKResizableWidth+Addition+Digit.swift | 14 +++- .../NBKResizableWidth+Addition.swift | 12 ++++ .../NBKResizableWidth+Bits.swift | 53 +++++++++++++++ .../NBKResizableWidth+Division+Digit.swift | 57 ++++++++++++++++ .../NBKResizableWidth+Division.swift | 68 +++++++++++++++++++ .../NBKResizableWidth+Logic.swift | 51 ++++++++++++++ ...KResizableWidth+Multiplication+Digit.swift | 14 +++- .../NBKResizableWidth+Multiplication.swift | 14 +++- .../NBKResizableWidth+Numbers.swift | 46 ++++++++++++- .../NBKResizableWidth+Protocols.swift | 17 +++++ .../NBKResizableWidth+Shifts.swift | 26 ++++++- .../NBKResizableWidth+Subtraction+Digit.swift | 22 +++++- .../NBKResizableWidth+Subtraction.swift | 22 +++++- .../NBKResizableWidth+Text+Radix.swift | 31 +++++++++ .../NBKResizableWidth+Text.swift | 44 ++++++++++++ .../NBKResizableWidth.swift | 2 +- 20 files changed, 502 insertions(+), 24 deletions(-) create mode 100644 Sources/NBKResizableWidthKit/NBKResizableWidth+Bits.swift create mode 100644 Sources/NBKResizableWidthKit/NBKResizableWidth+Division+Digit.swift create mode 100644 Sources/NBKResizableWidthKit/NBKResizableWidth+Division.swift create mode 100644 Sources/NBKResizableWidthKit/NBKResizableWidth+Protocols.swift create mode 100644 Sources/NBKResizableWidthKit/NBKResizableWidth+Text+Radix.swift diff --git a/.swiftpm/Numberick.xctestplan b/.swiftpm/Numberick.xctestplan index 8bba5531..a8c7369c 100644 --- a/.swiftpm/Numberick.xctestplan +++ b/.swiftpm/Numberick.xctestplan @@ -25,6 +25,11 @@ "containerPath" : "container:", "identifier" : "NBKFlexibleWidthKit", "name" : "NBKFlexibleWidthKit" + }, + { + "containerPath" : "container:", + "identifier" : "NBKResizableWidthKit", + "name" : "NBKResizableWidthKit" } ] } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift index e24c5ba2..f408209c 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift @@ -28,7 +28,6 @@ extension NBKFlexibleWidth { // MARK: Accessors //=------------------------------------------------------------------------= - /// The number of bits in ``words``. @inlinable public var bitWidth: Int { self.magnitude.bitWidth + self.storageBitWidthNeeded } @@ -83,28 +82,27 @@ extension NBKFlexibleWidth.Magnitude { // MARK: Accessors //=------------------------------------------------------------------------= - /// The number of bits in ``words``. @inlinable public var bitWidth: Int { - self.storage.count * UInt.bitWidth + self.storage.bitWidth } @inlinable public var nonzeroBitCount: Int { - NBK.nonzeroBitCount(of: self.storage) + self.storage.nonzeroBitCount } @inlinable public var leadingZeroBitCount: Int { - self.storage.last.leadingZeroBitCount + self.storage.leadingZeroBitCount } @inlinable public var trailingZeroBitCount: Int { - NBK.trailingZeroBitCount(of: self.storage) + self.storage.trailingZeroBitCount } @inlinable public var mostSignificantBit: Bool { - self.storage.last.mostSignificantBit + self.storage.mostSignificantBit } @inlinable public var leastSignificantBit: Bool { - self.storage.first.leastSignificantBit + self.storage.leastSignificantBit } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift index 61b10e72..12cc2b26 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift @@ -161,7 +161,7 @@ extension NBKFlexibleWidth.Magnitude { } @inlinable init(truncatingIntegerLiteral source: StaticBigInt) { - self.init(storage: Storage(truncating: source)) + self.init(storage: Storage(truncatingIntegerLiteral: source)) } //=------------------------------------------------------------------------= diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Protocols.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Protocols.swift index d97376aa..1780b34c 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Protocols.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Protocols.swift @@ -12,7 +12,7 @@ import NBKCoreKit // TODO: consider a public NBKCoreKit/NBKFlexibleWidthInteger protocol // TODO: consider a primary associated type similar to NBKCoreKit/NBKCoreInteger //*============================================================================* -// MARK: * NBK x Flexible Width x Protocol +// MARK: * NBK x Flexible Width x IntXL or UIntXL //*============================================================================* public protocol IntXLOrUIntXL: NBKBinaryInteger, LosslessStringConvertible { @@ -21,17 +21,15 @@ public protocol IntXLOrUIntXL: NBKBinaryInteger, LosslessStringConvertible { // MARK: Details x Comparisons //=------------------------------------------------------------------------= - func compared(to other: Self, at index: Int) -> Int - - func compared(to other: Self.Digit) -> Int - - func compared(to other: Self.Digit, at index: Int) -> Int + func compared(to other: Self, at index: Int) -> Int + + func compared(to other: Digit, at index: Int) -> Int //=------------------------------------------------------------------------= // MARK: Details x Numbers //=------------------------------------------------------------------------= - init(digit: Self.Digit, at index: Int) + init(digit: Digit, at index: Int) //=------------------------------------------------------------------------= // MARK: Details x Addition diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition+Digit.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition+Digit.swift index a9687d3c..a2905f6b 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition+Digit.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition+Digit.swift @@ -19,7 +19,19 @@ extension NBKResizableWidth.Magnitude { // MARK: Transformations //=------------------------------------------------------------------------= - @inlinable public mutating func add(_ other: UInt, plus addend: Bool, at index: Int) -> Bool { + @_disfavoredOverload @inlinable public static func +=(lhs: inout Self, rhs: UInt) { + fatalError("TODO") + } + + @_disfavoredOverload @inlinable public static func +(lhs: Self, rhs: UInt) -> Self { + fatalError("TODO") + } + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @_disfavoredOverload @inlinable public mutating func add(_ other: UInt, plus addend: Bool, at index: Int) -> Bool { var index = index, overflow = addend self.add(other, at: &index, carrying: &overflow) return overflow as Bool diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition.swift index 4f6e177e..ba02b0c2 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition.swift @@ -19,6 +19,18 @@ extension NBKResizableWidth.Magnitude { // MARK: Transformations //=------------------------------------------------------------------------= + @inlinable public static func +=(lhs: inout Self, rhs: Self) { + fatalError("TODO") + } + + @inlinable public static func +(lhs: Self, rhs: Self) -> Self { + fatalError("TODO") + } + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + @inlinable public mutating func add(_ other: Self, plus addend: Bool, at index: Int) -> Bool { var index = index, overflow = addend self.add(other, at: &index, carrying: &overflow) diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Bits.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Bits.swift new file mode 100644 index 00000000..ce913b42 --- /dev/null +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Bits.swift @@ -0,0 +1,53 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Resizable Width x Bits x Unsigned +//*============================================================================* + +extension NBKResizableWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + @inlinable public init(bit: Bool) { + self.init(digit: Digit(bit: bit)) + } + + //=------------------------------------------------------------------------= + // MARK: Accessors + //=------------------------------------------------------------------------= + + @inlinable public var bitWidth: Int { + self.storage.count * UInt.bitWidth + } + + @inlinable public var nonzeroBitCount: Int { + NBK.nonzeroBitCount(of: self.storage) + } + + @inlinable public var leadingZeroBitCount: Int { + self.last.leadingZeroBitCount + } + + @inlinable public var trailingZeroBitCount: Int { + NBK.trailingZeroBitCount(of: self.storage) + } + + @inlinable public var mostSignificantBit: Bool { + self.last.mostSignificantBit + } + + @inlinable public var leastSignificantBit: Bool { + self.first.leastSignificantBit + } +} diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Division+Digit.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Division+Digit.swift new file mode 100644 index 00000000..a13eb4eb --- /dev/null +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Division+Digit.swift @@ -0,0 +1,57 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Resizable Width x Division x Digit x Unsigned +//*============================================================================* + +extension NBKResizableWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @_disfavoredOverload @inlinable public mutating func divideReportingOverflow(by other: Digit) -> Bool { + let pvo: PVO = self.dividedReportingOverflow(by: other) + self = pvo.partialValue + return pvo.overflow as Bool + } + + @_disfavoredOverload @inlinable public func dividedReportingOverflow(by other: Digit) -> PVO { + let qro: PVO> = self.quotientAndRemainderReportingOverflow(dividingBy: other) + return PVO(qro.partialValue.quotient, qro.overflow) + } + + @_disfavoredOverload @inlinable public mutating func formRemainderReportingOverflow(dividingBy other: Digit) -> Bool { + let pvo: PVO = self.remainderReportingOverflow(dividingBy: other) + self = Self(digit: pvo.partialValue) + return pvo.overflow as Bool + } + + @_disfavoredOverload @inlinable public func remainderReportingOverflow(dividingBy other: Digit) -> PVO { + let qro: PVO> = self.quotientAndRemainderReportingOverflow(dividingBy: other) + return PVO(qro.partialValue.remainder, qro.overflow) + } + + @_disfavoredOverload @inlinable public func quotientAndRemainderReportingOverflow(dividingBy other: Digit) -> PVO> { + var quotient = self + let remainder = quotient.formQuotientWithRemainderReportingOverflow(dividingBy: other) + return PVO(QR(quotient, remainder.partialValue), remainder.overflow) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Private + //=------------------------------------------------------------------------= + + @_disfavoredOverload @inlinable mutating func formQuotientWithRemainderReportingOverflow(dividingBy other: Digit) -> PVO { + fatalError("TODO") + } +} diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Division.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Division.swift new file mode 100644 index 00000000..5fe3a91d --- /dev/null +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Division.swift @@ -0,0 +1,68 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Resizable Width x Division x Unsigned +//*============================================================================* + +extension NBKResizableWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public mutating func divideReportingOverflow(by other: Self) -> Bool { + let pvo: PVO = self.dividedReportingOverflow(by: other) + self = pvo.partialValue + return pvo.overflow as Bool + } + + @inlinable public func dividedReportingOverflow(by other: Self) -> PVO { + let qro: PVO> = self.quotientAndRemainderReportingOverflow(dividingBy: other) + return PVO(qro.partialValue.quotient, qro.overflow) + } + + @inlinable public mutating func formRemainderReportingOverflow(dividingBy other: Self) -> Bool { + let pvo: PVO = self.remainderReportingOverflow(dividingBy: other) + self = pvo.partialValue + return pvo.overflow as Bool + } + + @inlinable public func remainderReportingOverflow(dividingBy other: Self) -> PVO { + let qro: PVO> = self.quotientAndRemainderReportingOverflow(dividingBy: other) + return PVO(qro.partialValue.remainder, qro.overflow) + } + + @inlinable public func quotientAndRemainderReportingOverflow(dividingBy other: Self) -> PVO> { + self.quotientAndRemainderReportingOverflowAsNormal(dividingBy: other) + } +} + +//=----------------------------------------------------------------------------= +// MARK: + Normal +//=----------------------------------------------------------------------------= + +extension NBKResizableWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Transformations x Private + //=------------------------------------------------------------------------= + + @inlinable func quotientAndRemainderReportingOverflowAsNormal(dividingBy other: Self) -> PVO> { + var (remainder) = self + let (quotient, overflow) = remainder.formRemainderWithQuotientReportingOverflowAsNormal(dividingBy: other) + return PVO(QR(quotient, remainder), overflow) + } + + @inlinable mutating func formRemainderWithQuotientReportingOverflowAsNormal(dividingBy other: Self) -> PVO { + fatalError("TODO") + } +} diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Logic.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Logic.swift index 8b314d86..31dca807 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Logic.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Logic.swift @@ -13,6 +13,57 @@ import NBKCoreKit // MARK: * NBK x Resizable Width x Logic x Unsigned //*============================================================================* +extension NBKResizableWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Transformations x NOT + //=------------------------------------------------------------------------= + + @inlinable public static prefix func ~(x: Self) -> Self { + x.onesComplement() + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x AND + //=------------------------------------------------------------------------= + + @inlinable public static func &=(lhs: inout Self, rhs: Self) { + fatalError("TODO") + } + + @inlinable public static func &(lhs: Self, rhs: Self) -> Self { + var lhs = lhs; lhs &= rhs; return lhs + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x OR + //=------------------------------------------------------------------------= + + @inlinable public static func |=(lhs: inout Self, rhs: Self) { + fatalError("TODO") + } + + @inlinable public static func |(lhs: Self, rhs: Self) -> Self { + var lhs = lhs; lhs |= rhs; return lhs + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x XOR + //=------------------------------------------------------------------------= + + @inlinable public static func ^=(lhs: inout Self, rhs: Self) { + fatalError("TODO") + } + + @inlinable public static func ^(lhs: Self, rhs: Self) -> Self { + var lhs = lhs; lhs ^= rhs; return lhs + } +} + +//=----------------------------------------------------------------------------= +// MARK: + Algorithms +//=----------------------------------------------------------------------------= + extension NBKResizableWidth.Magnitude { //=------------------------------------------------------------------------= diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Multiplication+Digit.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Multiplication+Digit.swift index e7ead09a..8a6c93e9 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Multiplication+Digit.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Multiplication+Digit.swift @@ -19,7 +19,19 @@ extension NBKResizableWidth.Magnitude { // MARK: Transformations //=------------------------------------------------------------------------= - @inlinable public mutating func multiply(by other: UInt, plus addend: UInt) -> UInt { + @_disfavoredOverload @inlinable public static func *=(lhs: inout Self, rhs: UInt) { + fatalError("TODO") + } + + @_disfavoredOverload @inlinable public static func *(lhs: Self, rhs: UInt) -> Self { + fatalError("TODO") + } + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @_disfavoredOverload @inlinable public mutating func multiply(by other: UInt, plus addend: UInt) -> UInt { var overflow = addend self.multiply(by: other, carrying: &overflow) return overflow as UInt diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Multiplication.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Multiplication.swift index f77f89d5..73c0a51c 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Multiplication.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Multiplication.swift @@ -16,7 +16,19 @@ import NBKCoreKit extension NBKResizableWidth.Magnitude { //=------------------------------------------------------------------------= - // MARK: Transformations x Self + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public static func *=(lhs: inout Self, rhs: Self) { + fatalError("TODO") + } + + @inlinable public static func *(lhs: Self, rhs: Self) -> Self { + fatalError("TODO") + } + + //=------------------------------------------------------------------------= + // MARK: Transformations //=------------------------------------------------------------------------= @inlinable public func multipliedFullWidth(by multiplicand: Self) -> Self { diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Numbers.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Numbers.swift index 5b1cb877..97764f35 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Numbers.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Numbers.swift @@ -32,8 +32,20 @@ extension NBKResizableWidth.Magnitude { // MARK: Initializers x Literal //=------------------------------------------------------------------------= + @inlinable public init(integerLiteral source: StaticBigInt) { + fatalError("TODO") + } + + // TODO: internal + @inlinable public init?(exactlyIntegerLiteral source: StaticBigInt) { + //=--------------------------------------= + if source.signum() == -1 { return nil } + //=--------------------------------------= + self.init(truncatingIntegerLiteral: source) + } + // TODO: internal - @inlinable public init(truncating source: StaticBigInt) { + @inlinable public init(truncatingIntegerLiteral source: StaticBigInt) { //=--------------------------------------= let bitWidth = source.bitWidth let major = NBK .quotientDividingByBitWidthAssumingIsAtLeastZero(bitWidth) @@ -46,4 +58,36 @@ extension NBKResizableWidth.Magnitude { } } } + + //=------------------------------------------------------------------------= + // MARK: Initializers x Binary Integer + //=------------------------------------------------------------------------= + + @inlinable public init(_ source: some BinaryInteger) { + fatalError("TODO") + } + + @inlinable public init?(exactly source: some BinaryInteger) { + fatalError("TODO") + } + + @inlinable public init(clamping source: some BinaryInteger) { + fatalError("TODO") + } + + @inlinable public init(truncatingIfNeeded source: some BinaryInteger) { + fatalError("TODO") + } + + //=------------------------------------------------------------------------= + // MARK: Initializers x Binary Floating Point + //=------------------------------------------------------------------------= + + @inlinable public init(_ source: some BinaryFloatingPoint) { + fatalError("TODO") + } + + @inlinable public init?(exactly source: some BinaryFloatingPoint) { + fatalError("TODO") + } } diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Protocols.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Protocols.swift new file mode 100644 index 00000000..0aee5fe2 --- /dev/null +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Protocols.swift @@ -0,0 +1,17 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Resizable Width x IntXR or UIntXR +//*============================================================================* + +public protocol IntXROrUIntXR: NBKBinaryInteger, LosslessStringConvertible, MutableCollection, +RandomAccessCollection where Element == UInt, Index == Int, Indices == Range { } diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Shifts.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Shifts.swift index 831eb76f..443beac9 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Shifts.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Shifts.swift @@ -18,6 +18,18 @@ import NBKCoreKit extension NBKResizableWidth.Magnitude { + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public static func <<=(lhs: inout Self, rhs: some BinaryInteger) { + fatalError("TODO") + } + + @inlinable public static func <<(lhs: Self, rhs: some BinaryInteger) -> Self { + var lhs = lhs; lhs <<= rhs; return lhs + } + //=------------------------------------------------------------------------= // MARK: Transformations x Int //=------------------------------------------------------------------------= @@ -87,7 +99,19 @@ extension NBKResizableWidth.Magnitude { extension NBKResizableWidth.Magnitude { //=------------------------------------------------------------------------= - // MARK: Transformations x Right + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public static func >>=(lhs: inout Self, rhs: some BinaryInteger) { + fatalError("TODO") + } + + @inlinable public static func >>(lhs: Self, rhs: some BinaryInteger) -> Self { + var lhs = lhs; lhs >>= rhs; return lhs + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Int //=------------------------------------------------------------------------= /// Performs an un/signed right shift. diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction+Digit.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction+Digit.swift index 47d08652..0dccac8f 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction+Digit.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction+Digit.swift @@ -19,7 +19,27 @@ extension NBKResizableWidth.Magnitude { // MARK: Transformations //=------------------------------------------------------------------------= - @inlinable public mutating func subtract(_ other: UInt, plus addend: Bool, at index: Int) -> Bool { + @_disfavoredOverload @inlinable public static func -=(lhs: inout Self, rhs: UInt) { + fatalError("TODO") + } + + @_disfavoredOverload @inlinable public static func -(lhs: Self, rhs: UInt) -> Self { + fatalError("TODO") + } + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @_disfavoredOverload @inlinable public mutating func subtractReportingOverflow(_ other: UInt) -> Bool { + fatalError("TODO") + } + + @_disfavoredOverload @inlinable public func subtractingReportingOverflow(_ other: UInt) -> PVO { + fatalError("TODO") + } + + @_disfavoredOverload @inlinable public mutating func subtract(_ other: UInt, plus addend: Bool, at index: Int) -> Bool { var index = index, overflow = addend self.subtract(other, at: &index, borrowing: &overflow) return overflow as Bool diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction.swift index 2ef829f4..edd34902 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction.swift @@ -16,8 +16,28 @@ import NBKCoreKit extension NBKResizableWidth.Magnitude { //=------------------------------------------------------------------------= - // MARK: Transformations x Self + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public static func -=(lhs: inout Self, rhs: Self) { + fatalError("TODO") + } + + @inlinable public static func -(lhs: Self, rhs: Self) -> Self { + fatalError("TODO") + } + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public mutating func subtractReportingOverflow(_ other: Self) -> Bool { + fatalError("TODO") + } + + @inlinable public func subtractingReportingOverflow(_ other: Self) -> PVO { + fatalError("TODO") + } @inlinable public mutating func subtract(_ other: Self, plus addend: Bool, at index: Int) -> Bool { var index = index, overflow = addend diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Text+Radix.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Text+Radix.swift new file mode 100644 index 00000000..fc711b07 --- /dev/null +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Text+Radix.swift @@ -0,0 +1,31 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +//*============================================================================* +// MARK: * NBK x Resizable Width x Text x Radix +//*============================================================================* + +extension NBKResizableWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Details x Decode + //=------------------------------------------------------------------------= + + @inlinable public init?(_ description: some StringProtocol, radix: Int) { + fatalError("TODO") + } + + //=------------------------------------------------------------------------= + // MARK: Details x Encode + //=------------------------------------------------------------------------= + + @inlinable public func description(radix: Int = 10, uppercase: Bool = false) -> String { + fatalError("TODO") + } +} diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Text.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Text.swift index 3db77a64..8a172873 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Text.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Text.swift @@ -41,6 +41,50 @@ extension NBKResizableWidth { extension NBKResizableWidth.Magnitude { + //=------------------------------------------------------------------------= + // MARK: Details x Decode + //=------------------------------------------------------------------------= + + /// Creates a new instance from the given `description`. + /// + /// The `description` may contain a plus or minus sign (+ or -), followed + /// by one or more numeric digits (0-9). If the description uses an invalid + /// format, or its value cannot be represented, the result is nil. + /// + /// ``` + /// ┌──────────── → ─────────────┐ + /// │ description │ self │ + /// ├──────────── → ─────────────┤ + /// │ "123" │ Int256( 123) │ + /// │ "+123" │ Int256( 123) │ + /// │ "-123" │ Int256(-123) │ + /// │ "~123" │ nil │ + /// └──────────── → ─────────────┘ + /// ``` + /// + /// - Note: This member is required by `Swift.LosslessStringConvertible`. + /// + @inlinable public init?(_ description: String) { + self.init(description, radix: 10) + } + + /// The `description` of this value. + /// + /// ``` + /// ┌───────────── → ────────────┐ + /// │ self │ description │ + /// ├───────────── → ────────────┤ + /// │ Int256( 123) │ "123" │ + /// │ Int256(-123) │ "-123" │ + /// └───────────── → ────────────┘ + /// ``` + /// + /// - Note: This member is required by `Swift.CustomStringConvertible`. + /// + @inlinable public var description: String { + self.description(radix: 10, uppercase: false) + } + //=------------------------------------------------------------------------= // MARK: Details x Encode //=------------------------------------------------------------------------= diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth.swift index 623c9fe1..74c69264 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth.swift @@ -61,7 +61,7 @@ import NBKCoreKit //*========================================================================* /// An unsigned, resizable-width, binary integer of at least one word. - @frozen public struct Magnitude: Hashable, MutableCollection, RandomAccessCollection, Sendable { + @frozen public struct Magnitude: NBKUnsignedInteger, IntXROrUIntXR { public typealias Digit = UInt From c98e72d4cfad85de7232af58324a49ddf2fabd00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sun, 6 Aug 2023 15:51:14 +0200 Subject: [PATCH 047/133] NBKResizableWidthKit: Words. --- .../NBKResizableWidth+Numbers.swift | 6 +- .../NBKResizableWidth+Protocols.swift | 25 ++- .../NBKResizableWidth+Subtraction+Digit.swift | 18 -- .../NBKResizableWidth+Subtraction.swift | 18 ++ .../NBKResizableWidth+Words+Pointers.swift | 1 - .../Blank.swift | 1 - .../NBKResizableWidth.swift | 42 +++++ Tests/NBKResizableWidthKitTests/Blank.swift | 1 - .../NBKResizableWidth+Words.swift | 176 ++++++++++++++++++ .../NBKResizableWidth.swift | 42 +++++ 10 files changed, 307 insertions(+), 23 deletions(-) delete mode 100644 Tests/NBKResizableWidthKitBenchmarks/Blank.swift create mode 100644 Tests/NBKResizableWidthKitBenchmarks/NBKResizableWidth.swift delete mode 100644 Tests/NBKResizableWidthKitTests/Blank.swift create mode 100644 Tests/NBKResizableWidthKitTests/NBKResizableWidth+Words.swift create mode 100644 Tests/NBKResizableWidthKitTests/NBKResizableWidth.swift diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Numbers.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Numbers.swift index 97764f35..514ed928 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Numbers.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Numbers.swift @@ -33,7 +33,11 @@ extension NBKResizableWidth.Magnitude { //=------------------------------------------------------------------------= @inlinable public init(integerLiteral source: StaticBigInt) { - fatalError("TODO") + guard let value = Self(exactlyIntegerLiteral: source) else { + preconditionFailure("\(Self.description) cannot represent \(source)") + } + + self = value } // TODO: internal diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Protocols.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Protocols.swift index 0aee5fe2..938e823c 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Protocols.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Protocols.swift @@ -14,4 +14,27 @@ import NBKCoreKit //*============================================================================* public protocol IntXROrUIntXR: NBKBinaryInteger, LosslessStringConvertible, MutableCollection, -RandomAccessCollection where Element == UInt, Index == Int, Indices == Range { } +RandomAccessCollection where Element == UInt, Index == Int, Indices == Range { + + //=------------------------------------------------------------------------= + // MARK: Details x Words + //=------------------------------------------------------------------------= + + @inlinable var first: UInt { get set } + + @inlinable var last: UInt { get set } + + @inlinable var tail: Digit { get set } + + //=------------------------------------------------------------------------= + // MARK: Details x Words x Pointers + //=------------------------------------------------------------------------= + + @inlinable func withContiguousStorage(_ body: (NBK.UnsafeWords) throws -> T) rethrows -> T + + @inlinable func withContiguousStorageIfAvailable(_ body: (NBK.UnsafeWords) throws -> T) rethrows -> T? + + @inlinable mutating func withContiguousMutableStorage(_ body: (inout NBK.UnsafeMutableWords) throws -> T) rethrows -> T + + @inlinable mutating func withContiguousMutableStorageIfAvailable(_ body: (inout NBK.UnsafeMutableWords) throws -> T) rethrows -> T? +} diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction+Digit.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction+Digit.swift index 0dccac8f..4bf314da 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction+Digit.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction+Digit.swift @@ -44,24 +44,6 @@ extension NBKResizableWidth.Magnitude { self.subtract(other, at: &index, borrowing: &overflow) return overflow as Bool } - - //=------------------------------------------------------------------------= - // MARK: Transformations x Multiplication By UInt - //=------------------------------------------------------------------------= - - @inlinable public mutating func subtract(_ other: Self, times multiplicand: UInt, plus addend: UInt, at index: Int) -> Bool { - var index = index - var overflow = false - var last = addend as UInt - - for otherIndex in other.storage.indices { - var subproduct = other.storage[otherIndex].multipliedFullWidth(by: multiplicand) - last = UInt(bit: subproduct.low.addReportingOverflow(last)) &+ subproduct.high - self.subtractWithoutGoingBeyond(subproduct.low, at: &index, borrowing: &overflow) - } - - return self.subtract(last, plus: overflow, at: index) - } } //=----------------------------------------------------------------------------= diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction.swift index edd34902..10631599 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction.swift @@ -44,6 +44,24 @@ extension NBKResizableWidth.Magnitude { self.subtract(other, at: &index, borrowing: &overflow) return overflow as Bool } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Product + //=------------------------------------------------------------------------= + + @inlinable public mutating func subtract(_ other: Self, times multiplicand: UInt, plus addend: UInt, at index: Int) -> Bool { + var index = index + var overflow = false + var last = addend as UInt + + for otherIndex in other.storage.indices { + var subproduct = other.storage[otherIndex].multipliedFullWidth(by: multiplicand) + last = UInt(bit: subproduct.low.addReportingOverflow(last)) &+ subproduct.high + self.subtractWithoutGoingBeyond(subproduct.low, at: &index, borrowing: &overflow) + } + + return self.subtract(last, plus: overflow, at: index) + } } //=----------------------------------------------------------------------------= diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Words+Pointers.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Words+Pointers.swift index 9e7f2159..4c5b65f7 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Words+Pointers.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Words+Pointers.swift @@ -43,7 +43,6 @@ extension NBKResizableWidth.Magnitude { /// @inlinable public mutating func withContiguousMutableStorage(_ body: (inout NBK.UnsafeMutableWords) throws -> T) rethrows -> T { try self.storage.withUnsafeMutableBufferPointer(body) - } /// Grants unsafe access to the collection's contiguous mutable storage. diff --git a/Tests/NBKResizableWidthKitBenchmarks/Blank.swift b/Tests/NBKResizableWidthKitBenchmarks/Blank.swift deleted file mode 100644 index 8b137891..00000000 --- a/Tests/NBKResizableWidthKitBenchmarks/Blank.swift +++ /dev/null @@ -1 +0,0 @@ - diff --git a/Tests/NBKResizableWidthKitBenchmarks/NBKResizableWidth.swift b/Tests/NBKResizableWidthKitBenchmarks/NBKResizableWidth.swift new file mode 100644 index 00000000..96c46b87 --- /dev/null +++ b/Tests/NBKResizableWidthKitBenchmarks/NBKResizableWidth.swift @@ -0,0 +1,42 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit +import NBKResizableWidthKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Resizable Width x Initializers x UIntXR +//*============================================================================* + +extension NBKResizableWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Details x Numbers + //=------------------------------------------------------------------------= + + static let min256 = Self(x64:[ 0, 0, 0, 0] as X) + static let max256 = Self(x64:[~0, ~0, ~0, ~0] as X) + + //=------------------------------------------------------------------------= + // MARK: Details x Limbs + //=------------------------------------------------------------------------= + + init(x32: [UInt32]) { + self.init(words: NBK.limbs(x32, as: [UInt].self)) + } + + init(x64: [UInt64]) { + self.init(words: NBK.limbs(x64, as: [UInt].self)) + } +} diff --git a/Tests/NBKResizableWidthKitTests/Blank.swift b/Tests/NBKResizableWidthKitTests/Blank.swift deleted file mode 100644 index 8b137891..00000000 --- a/Tests/NBKResizableWidthKitTests/Blank.swift +++ /dev/null @@ -1 +0,0 @@ - diff --git a/Tests/NBKResizableWidthKitTests/NBKResizableWidth+Words.swift b/Tests/NBKResizableWidthKitTests/NBKResizableWidth+Words.swift new file mode 100644 index 00000000..1ba9b39c --- /dev/null +++ b/Tests/NBKResizableWidthKitTests/NBKResizableWidth+Words.swift @@ -0,0 +1,176 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +import NBKResizableWidthKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Resizable Width x Words x UIntXR +//*============================================================================* + +final class NBKResizableWidthTestsOnWordsAsUIntXR: XCTestCase { + + typealias T = UIntXR + typealias M = UIntXR + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testWords() { + NBKAssertWords(T(words:[0 ]), [0 ]) + NBKAssertWords(T(words:[1 ]), [1 ]) + NBKAssertWords(T(words:[1, 2 ]), [1, 2 ]) + NBKAssertWords(T(words:[1, 2, 3 ]), [1, 2, 3 ]) + NBKAssertWords(T(words:[1, 2, 3, 4]), [1, 2, 3, 4]) + + NBKAssertWords(T(words:[0, 0, 0, 0]), [0, 0, 0, 0]) + NBKAssertWords(T(words:[1, 0, 0, 0]), [1, 0, 0, 0]) + NBKAssertWords(T(words:[1, 2, 0, 0]), [1, 2, 0, 0]) + NBKAssertWords(T(words:[1, 2, 3, 0]), [1, 2, 3, 0]) + NBKAssertWords(T(words:[1, 2, 3, 4]), [1, 2, 3, 4]) + } + + func testWordsX64() throws { + guard MemoryLayout.size == MemoryLayout.size else { throw XCTSkip() } + + NBKAssertWords(T(x64:[0 ] as X), [0 ]) + NBKAssertWords(T(x64:[1 ] as X), [1 ]) + NBKAssertWords(T(x64:[1, 2 ] as X), [1, 2 ]) + NBKAssertWords(T(x64:[1, 2, 3 ] as X), [1, 2, 3 ]) + NBKAssertWords(T(x64:[1, 2, 3, 4] as X), [1, 2, 3, 4]) + + NBKAssertWords(T(x64:[0, 0, 0, 0] as X), [0, 0, 0, 0]) + NBKAssertWords(T(x64:[1, 0, 0, 0] as X), [1, 0, 0, 0]) + NBKAssertWords(T(x64:[1, 2, 0, 0] as X), [1, 2, 0, 0]) + NBKAssertWords(T(x64:[1, 2, 3, 0] as X), [1, 2, 3, 0]) + NBKAssertWords(T(x64:[1, 2, 3, 4] as X), [1, 2, 3, 4]) + } + + func testWordsX32() throws { + guard MemoryLayout.size == MemoryLayout.size else { throw XCTSkip() } + + NBKAssertWords(T(x32:[0 ] as Y), [0 ]) + NBKAssertWords(T(x32:[1 ] as Y), [1 ]) + NBKAssertWords(T(x32:[1, 2 ] as Y), [1, 2 ]) + NBKAssertWords(T(x32:[1, 2, 3 ] as Y), [1, 2, 3 ]) + NBKAssertWords(T(x32:[1, 2, 3, 4 ] as Y), [1, 2, 3, 4 ]) + NBKAssertWords(T(x32:[1, 2, 3, 4, 5 ] as Y), [1, 2, 3, 4, 5 ]) + NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6 ] as Y), [1, 2, 3, 4, 5, 6 ]) + NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6, 7 ] as Y), [1, 2, 3, 4, 5, 6, 7 ]) + NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6, 7, 8] as Y), [1, 2, 3, 4, 5, 6, 7, 8]) + + NBKAssertWords(T(x32:[0, 0, 0, 0, 0, 0, 0, 0] as Y), [0, 0, 0, 0, 0, 0, 0, 0]) + NBKAssertWords(T(x32:[1, 0, 0, 0, 0, 0, 0, 0] as Y), [1, 0, 0, 0, 0, 0, 0, 0]) + NBKAssertWords(T(x32:[1, 2, 0, 0, 0, 0, 0, 0] as Y), [1, 2, 0, 0, 0, 0, 0, 0]) + NBKAssertWords(T(x32:[1, 2, 3, 0, 0, 0, 0, 0] as Y), [1, 2, 3, 0, 0, 0, 0, 0]) + NBKAssertWords(T(x32:[1, 2, 3, 4, 0, 0, 0, 0] as Y), [1, 2, 3, 4, 0, 0, 0, 0]) + NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 0, 0, 0] as Y), [1, 2, 3, 4, 5, 0, 0, 0]) + NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6, 0, 0] as Y), [1, 2, 3, 4, 5, 6, 0, 0]) + NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6, 7, 0] as Y), [1, 2, 3, 4, 5, 6, 7, 0]) + NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6, 7, 8] as Y), [1, 2, 3, 4, 5, 6, 7, 8]) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Indices + //=------------------------------------------------------------------------= + + func testIndexOffsetByLimitedBy() { + NBKAssertIndexOffsetByLimitedBy(T.zero, 1, 2, 2, nil) + NBKAssertIndexOffsetByLimitedBy(T.zero, 1, 1, 2, 2) + NBKAssertIndexOffsetByLimitedBy(T.zero, 1, 0, 2, 1) + NBKAssertIndexOffsetByLimitedBy(T.zero, 1, -1, 2, 0) + NBKAssertIndexOffsetByLimitedBy(T.zero, 1, -2, 2, -1) + + NBKAssertIndexOffsetByLimitedBy(T.zero, 2, 2, 2, nil) + NBKAssertIndexOffsetByLimitedBy(T.zero, 2, 1, 2, nil) + NBKAssertIndexOffsetByLimitedBy(T.zero, 2, 0, 2, 2) + NBKAssertIndexOffsetByLimitedBy(T.zero, 2, -1, 2, nil) + NBKAssertIndexOffsetByLimitedBy(T.zero, 2, -2, 2, nil) + + NBKAssertIndexOffsetByLimitedBy(T.zero, 3, 2, 2, 5) + NBKAssertIndexOffsetByLimitedBy(T.zero, 3, 1, 2, 4) + NBKAssertIndexOffsetByLimitedBy(T.zero, 3, 0, 2, 3) + NBKAssertIndexOffsetByLimitedBy(T.zero, 3, -1, 2, 2) + NBKAssertIndexOffsetByLimitedBy(T.zero, 3, -2, 2, nil) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Elements + //=------------------------------------------------------------------------= + + func testFirstLastTail() { + NBKAssertFirstLastTail( T(words:[1, 2, 3, 4]), first: 1, last: 4, tail: 4) + NBKAssertFirstLastTail(~T(words:[1, 2, 3, 4]), first: ~1, last: ~4, tail: ~4) + } +} + +//*============================================================================* +// MARK: * NBK x Resizable Width x Words x Assertions +//*============================================================================* + +private func NBKAssertWords( +_ integer: T, _ words: [UInt], +file: StaticString = #file, line: UInt = #line) { + var integer: T = integer + var generic: some RandomAccessCollection & MutableCollection = integer + + XCTAssertEqual(Array(integer.words), Array(words), file: file, line: line) + XCTAssertEqual(Array(integer.words.reversed()), Array(words.reversed()), file: file, line: line) + + XCTAssertEqual(integer.withContiguousStorage({ Array($0) }), words, file: file, line: line) + XCTAssertEqual(integer.withContiguousMutableStorage({ Array($0) }), words, file: file, line: line) + + XCTAssertEqual(integer.withContiguousStorageIfAvailable({ Array($0) }), words, file: file, line: line) + XCTAssertEqual(integer.withContiguousMutableStorageIfAvailable({ Array($0) }), words, file: file, line: line) + + XCTAssertEqual(generic.withContiguousStorageIfAvailable({ Array($0) }), words, file: file, line: line) + XCTAssertEqual(generic.withContiguousMutableStorageIfAvailable({ Array($0) }), words, file: file, line: line) +} + +//=----------------------------------------------------------------------------= +// MARK: + Indices +//=----------------------------------------------------------------------------= + +private func NBKAssertIndexOffsetByLimitedBy( +_ integer: T, _ index: Int, _ distance: Int, _ limit: Int, _ expectation: Int?, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + let wordsIndex = /*-*/(integer).index(index, offsetBy: distance, limitedBy: limit) + let arrayIndex = Array(integer).index(index, offsetBy: distance, limitedBy: limit) + //=------------------------------------------= + XCTAssertEqual(wordsIndex, expectation, file: file, line: line) + XCTAssertEqual(arrayIndex, expectation, file: file, line: line) +} + +//=----------------------------------------------------------------------------= +// MARK: + Elements +//=----------------------------------------------------------------------------= + +private func NBKAssertFirstLastTail( +_ integer: T, first: UInt, last: UInt, tail: T.Digit, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + XCTAssertEqual(integer.first, first, file: file, line: line) + XCTAssertEqual(integer.last, last, file: file, line: line) + XCTAssertEqual(integer.tail, tail, file: file, line: line) + //=------------------------------------------= + XCTAssertEqual({ var x = T.zero; x.first = first; return x.first }(), first, file: file, line: line) + XCTAssertEqual({ var x = T.zero; x.last = last; return x.last }(), last, file: file, line: line) + XCTAssertEqual({ var x = T.zero; x.tail = tail; return x.tail }(), tail, file: file, line: line) +} + +#endif diff --git a/Tests/NBKResizableWidthKitTests/NBKResizableWidth.swift b/Tests/NBKResizableWidthKitTests/NBKResizableWidth.swift new file mode 100644 index 00000000..96c46b87 --- /dev/null +++ b/Tests/NBKResizableWidthKitTests/NBKResizableWidth.swift @@ -0,0 +1,42 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit +import NBKResizableWidthKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Resizable Width x Initializers x UIntXR +//*============================================================================* + +extension NBKResizableWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Details x Numbers + //=------------------------------------------------------------------------= + + static let min256 = Self(x64:[ 0, 0, 0, 0] as X) + static let max256 = Self(x64:[~0, ~0, ~0, ~0] as X) + + //=------------------------------------------------------------------------= + // MARK: Details x Limbs + //=------------------------------------------------------------------------= + + init(x32: [UInt32]) { + self.init(words: NBK.limbs(x32, as: [UInt].self)) + } + + init(x64: [UInt64]) { + self.init(words: NBK.limbs(x64, as: [UInt].self)) + } +} From 233e9f2ac5d98bec3dc4f96fcd31aa3e0ff7a2dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sun, 6 Aug 2023 17:13:11 +0200 Subject: [PATCH 048/133] NBKResizableWidthKit: Bits. --- .../NBKFlexibleWidth+Bits.swift | 2 +- .../NBKResizableWidth+Bits.swift | 2 +- .../NBKResizableWidth+Comparisons.swift | 12 ++ .../Private/NBK+Bits.swift | 37 ++++++ .../{Pointers.swift => NBK+Pointers.swift} | 0 .../NBKFlexibleWidth+Words.swift | 2 +- .../NBKResizableWidth+Bits.swift | 124 ++++++++++++++++++ .../NBKResizableWidth+Words.swift | 46 +++++++ .../NBKResizableWidth+Bits.swift | 99 ++++++++++++++ 9 files changed, 321 insertions(+), 3 deletions(-) create mode 100644 Sources/NBKResizableWidthKit/Private/NBK+Bits.swift rename Sources/NBKResizableWidthKit/Private/{Pointers.swift => NBK+Pointers.swift} (100%) create mode 100644 Tests/NBKResizableWidthKitBenchmarks/NBKResizableWidth+Bits.swift create mode 100644 Tests/NBKResizableWidthKitBenchmarks/NBKResizableWidth+Words.swift create mode 100644 Tests/NBKResizableWidthKitTests/NBKResizableWidth+Bits.swift diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift index f408209c..1161a608 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift @@ -91,7 +91,7 @@ extension NBKFlexibleWidth.Magnitude { } @inlinable public var leadingZeroBitCount: Int { - self.storage.leadingZeroBitCount + self.storage.last.leadingZeroBitCount } @inlinable public var trailingZeroBitCount: Int { diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Bits.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Bits.swift index ce913b42..1d472b6e 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Bits.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Bits.swift @@ -36,7 +36,7 @@ extension NBKResizableWidth.Magnitude { } @inlinable public var leadingZeroBitCount: Int { - self.last.leadingZeroBitCount + NBK.leadingZeroBitCount(of: self.storage) } @inlinable public var trailingZeroBitCount: Int { diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Comparisons.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Comparisons.swift index aad12f15..7f7c0128 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Comparisons.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Comparisons.swift @@ -47,6 +47,18 @@ extension NBKResizableWidth.Magnitude { hasher.combine(self.storage) } + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + @inlinable public static func ==(lhs: Self, rhs: Self) -> Bool { + lhs.compared(to: rhs) == 0 + } + + @inlinable public static func <(lhs: Self, rhs: Self) -> Bool { + lhs.compared(to: rhs) == -1 + } + @inlinable public func compared(to other: Self) -> Int { self .withContiguousStorage { lhs in other.withContiguousStorage { rhs in diff --git a/Sources/NBKResizableWidthKit/Private/NBK+Bits.swift b/Sources/NBKResizableWidthKit/Private/NBK+Bits.swift new file mode 100644 index 00000000..7f641430 --- /dev/null +++ b/Sources/NBKResizableWidthKit/Private/NBK+Bits.swift @@ -0,0 +1,37 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Bits +//*============================================================================* + +extension NBK { + + //=------------------------------------------------------------------------= + // MARK: Details + //=------------------------------------------------------------------------= + + /// Returns the leading zero bit count of `limbs`. + /// + /// - Note: The leading zero bit count is zero when `limbs` is empty. + /// + @inlinable public static func leadingZeroBitCount(of limbs: some BidirectionalCollection) -> Int { + var index = limbs.endIndex + var element = T.zero + + while index > limbs.startIndex, element.isZero { + limbs.formIndex(before: &index) + element = limbs[index] + } + + return limbs.distance(from: index, to: limbs.endIndex) * T.bitWidth - T.bitWidth + element.leadingZeroBitCount + } +} diff --git a/Sources/NBKResizableWidthKit/Private/Pointers.swift b/Sources/NBKResizableWidthKit/Private/NBK+Pointers.swift similarity index 100% rename from Sources/NBKResizableWidthKit/Private/Pointers.swift rename to Sources/NBKResizableWidthKit/Private/NBK+Pointers.swift diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Words.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Words.swift index 1e95969c..d9234536 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Words.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Words.swift @@ -18,7 +18,7 @@ private typealias X = [UInt64] private typealias Y = [UInt32] //*============================================================================* -// MARK: * NBK x UntXL x Words +// MARK: * NBK x Flexible Width x Words x IntXL //*============================================================================* final class NBKFlexibleWidthBenchmarksOnWordsAsIntXL: XCTestCase { diff --git a/Tests/NBKResizableWidthKitBenchmarks/NBKResizableWidth+Bits.swift b/Tests/NBKResizableWidthKitBenchmarks/NBKResizableWidth+Bits.swift new file mode 100644 index 00000000..a3a8c7d2 --- /dev/null +++ b/Tests/NBKResizableWidthKitBenchmarks/NBKResizableWidth+Bits.swift @@ -0,0 +1,124 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if !DEBUG + +import NBKCoreKit +import NBKResizableWidthKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Resizable Width x Bits x UIntXR +//*============================================================================* + +final class NBKResizableWidthBenchmarksOnBitsAsUIntXR: XCTestCase { + + typealias T = UIntXR + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testInitBit() { + var abc = NBK.blackHoleIdentity(true ) + var xyz = NBK.blackHoleIdentity(false) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(T(bit: abc)) + NBK.blackHole(T(bit: xyz)) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testBitWidth() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.bitWidth) + NBK.blackHole(xyz.bitWidth) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testNonzeroBitCount() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.nonzeroBitCount) + NBK.blackHole(xyz.nonzeroBitCount) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testLeadingZeroBitCount() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.leadingZeroBitCount) + NBK.blackHole(xyz.leadingZeroBitCount) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testTrailingZeroBitCount() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.trailingZeroBitCount) + NBK.blackHole(xyz.trailingZeroBitCount) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testMostSignificantBit() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.mostSignificantBit) + NBK.blackHole(xyz.mostSignificantBit) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testLeastSignificantBit() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.leastSignificantBit) + NBK.blackHole(xyz.leastSignificantBit) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } +} + +#endif diff --git a/Tests/NBKResizableWidthKitBenchmarks/NBKResizableWidth+Words.swift b/Tests/NBKResizableWidthKitBenchmarks/NBKResizableWidth+Words.swift new file mode 100644 index 00000000..9461d00d --- /dev/null +++ b/Tests/NBKResizableWidthKitBenchmarks/NBKResizableWidth+Words.swift @@ -0,0 +1,46 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if !DEBUG + +import NBKCoreKit +import NBKResizableWidthKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Resizable Width x Words x UIntXR +//*============================================================================* + +final class NBKResizableWidthBenchmarksOnWordsAsUIntXR: XCTestCase { + + typealias T = UIntXR + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testFromWords() { + var abc = NBK.blackHoleIdentity([ 0, 0, 0, 0] as W) + var xyz = NBK.blackHoleIdentity([~0, ~0, ~0, ~0] as W) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(T(words: abc)) + NBK.blackHole(T(words: xyz)) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } +} + +#endif diff --git a/Tests/NBKResizableWidthKitTests/NBKResizableWidth+Bits.swift b/Tests/NBKResizableWidthKitTests/NBKResizableWidth+Bits.swift new file mode 100644 index 00000000..790ff3ca --- /dev/null +++ b/Tests/NBKResizableWidthKitTests/NBKResizableWidth+Bits.swift @@ -0,0 +1,99 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +import NBKResizableWidthKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Resizable Width x Bits x UIntXR +//*============================================================================* + +final class NBKResizableWidthTestsOnBitsAsUIntXR: XCTestCase { + + typealias T = UIntXR + typealias M = UIntXR + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testInitBit() { + XCTAssertEqual(T(bit: false), T( )) + XCTAssertEqual(T(bit: true ), T(1)) + } + + func testBitWidth() { + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).bitWidth, UInt.bitWidth * 4) + XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).bitWidth, UInt.bitWidth * 4) + } + + func testNonzeroBitCount() { + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).nonzeroBitCount, 0) + XCTAssertEqual(T(words:[ 1, 1, 1, 1] as W).nonzeroBitCount, 4) + } + + func testLeadingZeroBitCount() { + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).leadingZeroBitCount, UInt.bitWidth * 4) + XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).leadingZeroBitCount, UInt.bitWidth * 0) + + XCTAssertEqual(T(words:[ 2, 0, 0, 0] as W).leadingZeroBitCount, UInt.bitWidth * 4 - 2) + XCTAssertEqual(T(words:[ 0, 2, 0, 0] as W).leadingZeroBitCount, UInt.bitWidth * 3 - 2) + XCTAssertEqual(T(words:[ 0, 0, 2, 0] as W).leadingZeroBitCount, UInt.bitWidth * 2 - 2) + XCTAssertEqual(T(words:[ 0, 0, 0, 2] as W).leadingZeroBitCount, UInt.bitWidth * 1 - 2) + } + + func testTrailingZeroBitCount() { + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).trailingZeroBitCount, UInt.bitWidth * 4) + XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).trailingZeroBitCount, UInt.bitWidth * 0) + + XCTAssertEqual(T(words:[ 2, 0, 0, 0] as W).trailingZeroBitCount, UInt.bitWidth * 0 + 1) + XCTAssertEqual(T(words:[ 0, 2, 0, 0] as W).trailingZeroBitCount, UInt.bitWidth * 1 + 1) + XCTAssertEqual(T(words:[ 0, 0, 2, 0] as W).trailingZeroBitCount, UInt.bitWidth * 2 + 1) + XCTAssertEqual(T(words:[ 0, 0, 0, 2] as W).trailingZeroBitCount, UInt.bitWidth * 3 + 1) + } + + func testMostSignificantBit() { + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).mostSignificantBit, false) + XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).mostSignificantBit, true ) + + XCTAssertEqual(T(words:[~0, 0, 0, 0] as W).mostSignificantBit, false) + XCTAssertEqual(T(words:[ 0, ~0, 0, 0] as W).mostSignificantBit, false) + XCTAssertEqual(T(words:[ 0, 0, ~0, 0] as W).mostSignificantBit, false) + XCTAssertEqual(T(words:[ 0, 0, 0, ~0] as W).mostSignificantBit, true ) + + XCTAssertEqual(T(words:[~0, 1, 0, 0] as W).mostSignificantBit, false) + XCTAssertEqual(T(words:[ 0, ~0, 1, 0] as W).mostSignificantBit, false) + XCTAssertEqual(T(words:[ 0, 0, ~0, 1] as W).mostSignificantBit, false) + XCTAssertEqual(T(words:[ 1, 0, 0, ~0] as W).mostSignificantBit, true ) + } + + func testLeastSignificantBit() { + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).leastSignificantBit, false) + XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).leastSignificantBit, true ) + + XCTAssertEqual(T(words:[~0, 0, 0, 0] as W).leastSignificantBit, true ) + XCTAssertEqual(T(words:[ 0, ~0, 0, 0] as W).leastSignificantBit, false) + XCTAssertEqual(T(words:[ 0, 0, ~0, 0] as W).leastSignificantBit, false) + XCTAssertEqual(T(words:[ 0, 0, 0, ~0] as W).leastSignificantBit, false) + + XCTAssertEqual(T(words:[~0, 1, 0, 0] as W).leastSignificantBit, true ) + XCTAssertEqual(T(words:[ 0, ~0, 1, 0] as W).leastSignificantBit, false) + XCTAssertEqual(T(words:[ 0, 0, ~0, 1] as W).leastSignificantBit, false) + XCTAssertEqual(T(words:[ 1, 0, 0, ~0] as W).leastSignificantBit, true ) + } +} + +#endif From f73c2e0d99aa0fa2bed82c5eac8d6e03a5bbae44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sun, 6 Aug 2023 18:41:27 +0200 Subject: [PATCH 049/133] NBKResizableWidthKit: Comparisons. --- .../NBKFlexibleWidth+Comparisons.swift | 4 +- .../NBKResizableWidth+Comparisons.swift | 2 +- .../NBKResizableWidth+Numbers.swift | 13 +- .../NBKResizableWidth+Protocols.swift | 8 + .../NBKCoreInteger+Comparisons.swift | 6 +- .../NBKFlexibleWidth+Comparisons.swift | 4 +- .../NBKResizableWidth+Comparisons.swift | 126 ++++++++ .../NBKResizableWidth+Comparisons.swift | 284 ++++++++++++++++++ 8 files changed, 435 insertions(+), 12 deletions(-) create mode 100644 Tests/NBKResizableWidthKitBenchmarks/NBKResizableWidth+Comparisons.swift create mode 100644 Tests/NBKResizableWidthKitTests/NBKResizableWidth+Comparisons.swift diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift index 33687950..551239cf 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift @@ -54,7 +54,7 @@ extension NBKFlexibleWidth { //=------------------------------------------------------------------------= @inlinable public static func ==(lhs: Self, rhs: Self) -> Bool { - lhs.compared(to: rhs) == 0 + lhs.compared(to: rhs).isZero } @inlinable public static func <(lhs: Self, rhs: Self) -> Bool { @@ -150,7 +150,7 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @inlinable public static func ==(lhs: Self, rhs: Self) -> Bool { - lhs.compared(to: rhs) == 0 + lhs.compared(to: rhs).isZero } @inlinable public static func <(lhs: Self, rhs: Self) -> Bool { diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Comparisons.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Comparisons.swift index 7f7c0128..d6cf10c6 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Comparisons.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Comparisons.swift @@ -52,7 +52,7 @@ extension NBKResizableWidth.Magnitude { //=------------------------------------------------------------------------= @inlinable public static func ==(lhs: Self, rhs: Self) -> Bool { - lhs.compared(to: rhs) == 0 + lhs.compared(to: rhs).isZero } @inlinable public static func <(lhs: Self, rhs: Self) -> Bool { diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Numbers.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Numbers.swift index 514ed928..e8967465 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Numbers.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Numbers.swift @@ -68,19 +68,24 @@ extension NBKResizableWidth.Magnitude { //=------------------------------------------------------------------------= @inlinable public init(_ source: some BinaryInteger) { - fatalError("TODO") + guard let result = Self(exactly: source) else { + preconditionFailure("\(Self.description) cannot represent \(source)") + } + + self = result } @inlinable public init?(exactly source: some BinaryInteger) { - fatalError("TODO") + guard source.signum() >= 0 else { return nil } + self.init(words: source.words) } @inlinable public init(clamping source: some BinaryInteger) { - fatalError("TODO") + self = Self(exactly: source) ?? (0 as Self) } @inlinable public init(truncatingIfNeeded source: some BinaryInteger) { - fatalError("TODO") + self.init(words: source.words) } //=------------------------------------------------------------------------= diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Protocols.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Protocols.swift index 938e823c..90cfdb3f 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Protocols.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Protocols.swift @@ -16,6 +16,14 @@ import NBKCoreKit public protocol IntXROrUIntXR: NBKBinaryInteger, LosslessStringConvertible, MutableCollection, RandomAccessCollection where Element == UInt, Index == Int, Indices == Range { + //=------------------------------------------------------------------------= + // MARK: Details x Comparisons + //=------------------------------------------------------------------------= + + func compared(to other: Self, at index: Int) -> Int + + func compared(to other: Digit, at index: Int) -> Int + //=------------------------------------------------------------------------= // MARK: Details x Words //=------------------------------------------------------------------------= diff --git a/Tests/NBKCoreKitTests/NBKCoreInteger+Comparisons.swift b/Tests/NBKCoreKitTests/NBKCoreInteger+Comparisons.swift index 974240d6..06986b85 100644 --- a/Tests/NBKCoreKitTests/NBKCoreInteger+Comparisons.swift +++ b/Tests/NBKCoreKitTests/NBKCoreInteger+Comparisons.swift @@ -213,9 +213,9 @@ final class NBKCoreIntegerTestsOnComparisons: XCTestCase { func testOverloadsAreUnambiguousWhenUsingSignum() { func becauseThisCompilesSuccessfully(_ x: inout some NBKCoreInteger, _ s: inout Int, _ u: inout UInt) { - XCTAssertNotNil(x.signum()) // Int - XCTAssertNotNil(s.signum()) // Int - XCTAssertNotNil(u.signum()) // UInt, stdlib + XCTAssertNotNil(x.signum()) + XCTAssertNotNil(s.signum()) + XCTAssertNotNil(u.signum()) } } } diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Comparisons.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Comparisons.swift index ea88efc2..a6a9845b 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Comparisons.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Comparisons.swift @@ -315,7 +315,7 @@ final class NBKFlexibleWidthTestsOnComparisonsAsIntXL: XCTestCase { func testOverloadsAreUnambiguous() { func becauseThisCompilesSuccessfully(_ x: inout T) { - XCTAssertNotNil(x.signum()) // Int + XCTAssertNotNil(x.signum()) } } @@ -515,7 +515,7 @@ final class NBKFlexibleWidthTestsOnComparisonsAsUIntXL: XCTestCase { func testOverloadsAreUnambiguous() { func becauseThisCompilesSuccessfully(_ x: inout T) { - XCTAssertNotNil(x.signum()) // Int + XCTAssertNotNil(x.signum()) } } diff --git a/Tests/NBKResizableWidthKitBenchmarks/NBKResizableWidth+Comparisons.swift b/Tests/NBKResizableWidthKitBenchmarks/NBKResizableWidth+Comparisons.swift new file mode 100644 index 00000000..2152f860 --- /dev/null +++ b/Tests/NBKResizableWidthKitBenchmarks/NBKResizableWidth+Comparisons.swift @@ -0,0 +1,126 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if !DEBUG + +import NBKCoreKit +import NBKResizableWidthKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Resizable Width x Comparisons x UIntXR +//*============================================================================* + +final class NBKResizableWidthBenchmarksOnComparisonsAsUIntXR: XCTestCase { + + typealias T = UIntXR + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testIsZero() { + var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.isZero) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testIsLessThanZero() { + var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.isLessThanZero) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testIsMoreThanZero() { + var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.isMoreThanZero) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testIsPowerOf2() { + var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.isPowerOf2) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testSignum() { + var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.signum()) + NBK.blackHoleInoutIdentity(&abc) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testIsEqualTo() { + var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs == rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testIsLessThan() { + var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs < rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testComparedTo() { + var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs.compared(to: rhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testComparedToDigit() { + var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + var rhs = NBK.blackHoleIdentity(UInt.max) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs.compared(to: rhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } +} + +#endif diff --git a/Tests/NBKResizableWidthKitTests/NBKResizableWidth+Comparisons.swift b/Tests/NBKResizableWidthKitTests/NBKResizableWidth+Comparisons.swift new file mode 100644 index 00000000..49ce4961 --- /dev/null +++ b/Tests/NBKResizableWidthKitTests/NBKResizableWidth+Comparisons.swift @@ -0,0 +1,284 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +import NBKResizableWidthKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Resizable Width x Comparisons x UIntXR +//*============================================================================* + +final class NBKResizableWidthTestsOnComparisonsAsUIntXR: XCTestCase { + + typealias T = UIntXR + typealias M = UIntXR + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testIsZero() { + XCTAssertTrue (T(words:[ 0] as W).isZero) + XCTAssertFalse(T(words:[ 1] as W).isZero) + XCTAssertFalse(T(words:[ 2] as W).isZero) + + XCTAssertFalse(T(words:[~0] as W).isZero) + XCTAssertFalse(T(words:[~1] as W).isZero) + XCTAssertFalse(T(words:[~2] as W).isZero) + } + + func testIsLessThanZero() { + XCTAssertFalse(T(words:[ 0] as W).isLessThanZero) + XCTAssertFalse(T(words:[ 1] as W).isLessThanZero) + XCTAssertFalse(T(words:[ 2] as W).isLessThanZero) + + XCTAssertFalse(T(words:[~0] as W).isLessThanZero) + XCTAssertFalse(T(words:[~1] as W).isLessThanZero) + XCTAssertFalse(T(words:[~2] as W).isLessThanZero) + } + + func testIsMoreThanZero() { + XCTAssertFalse(T(words:[ 0] as W).isMoreThanZero) + XCTAssertTrue (T(words:[ 1] as W).isMoreThanZero) + XCTAssertTrue (T(words:[ 2] as W).isMoreThanZero) + + XCTAssertTrue (T(words:[~0] as W).isMoreThanZero) + XCTAssertTrue (T(words:[~1] as W).isMoreThanZero) + XCTAssertTrue (T(words:[~2] as W).isMoreThanZero) + } + + func testIsOdd() { + XCTAssertFalse(T(words:[ 0] as W).isOdd) + XCTAssertTrue (T(words:[ 1] as W).isOdd) + XCTAssertFalse(T(words:[ 2] as W).isOdd) + + XCTAssertTrue (T(words:[~0] as W).isOdd) + XCTAssertFalse(T(words:[~1] as W).isOdd) + XCTAssertTrue (T(words:[~2] as W).isOdd) + } + + func testIsEven() { + XCTAssertTrue (T(words:[ 0] as W).isEven) + XCTAssertFalse(T(words:[ 1] as W).isEven) + XCTAssertTrue (T(words:[ 2] as W).isEven) + + XCTAssertFalse(T(words:[~0] as W).isEven) + XCTAssertTrue (T(words:[~1] as W).isEven) + XCTAssertFalse(T(words:[~2] as W).isEven) + } + + func testIsPowerOf2() { + XCTAssertFalse(T(words:[ 0] as W).isPowerOf2) + XCTAssertTrue (T(words:[ 1] as W).isPowerOf2) + XCTAssertTrue (T(words:[ 2] as W).isPowerOf2) + XCTAssertFalse(T(words:[ 3] as W).isPowerOf2) + XCTAssertTrue (T(words:[ 4] as W).isPowerOf2) + XCTAssertFalse(T(words:[ 5] as W).isPowerOf2) + XCTAssertFalse(T(words:[ 6] as W).isPowerOf2) + XCTAssertFalse(T(words:[ 7] as W).isPowerOf2) + + XCTAssertFalse(T(words:[ 0, 0, 0, 0] as W).isPowerOf2) + XCTAssertTrue (T(words:[ 1, 0, 0, 0] as W).isPowerOf2) + XCTAssertFalse(T(words:[ 1, 1, 0, 0] as W).isPowerOf2) + XCTAssertTrue (T(words:[ 0, 1, 0, 0] as W).isPowerOf2) + XCTAssertFalse(T(words:[ 0, 1, 1, 0] as W).isPowerOf2) + XCTAssertTrue (T(words:[ 0, 0, 1, 0] as W).isPowerOf2) + XCTAssertFalse(T(words:[ 0, 0, 1, 1] as W).isPowerOf2) + XCTAssertTrue (T(words:[ 0, 0, 0, 1] as W).isPowerOf2) + } + + func testSignum() { + NBKAssertSignum(T(words:[ 0] as W), Int(0)) + NBKAssertSignum(T(words:[ 1] as W), Int(1)) + NBKAssertSignum(T(words:[ 2] as W), Int(1)) + + NBKAssertSignum(T(words:[~0] as W), Int(1)) + NBKAssertSignum(T(words:[~1] as W), Int(1)) + NBKAssertSignum(T(words:[~2] as W), Int(1)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testHashing() { + var union = Set() + union.insert(T(words:[0, 0, 0, 0] as W)) + union.insert(T(words:[0, 0, 0, 0] as W)) + union.insert(T(words:[1, 0, 0, 0] as W)) + union.insert(T(words:[1, 0, 0, 0] as W)) + union.insert(T(words:[0, 1, 0, 0] as W)) + union.insert(T(words:[0, 1, 0, 0] as W)) + union.insert(T(words:[0, 0, 1, 0] as W)) + union.insert(T(words:[0, 0, 1, 0] as W)) + union.insert(T(words:[0, 0, 0, 1] as W)) + union.insert(T(words:[0, 0, 0, 1] as W)) + XCTAssertEqual(union.count, 5 as Int) + } + + func testComparing() { + NBKAssertComparisons(T(words:[0, 2, 3, 4] as W), T(words:[1, 2, 3, 4] as W), -Int(1)) + NBKAssertComparisons(T(words:[1, 0, 3, 4] as W), T(words:[1, 2, 3, 4] as W), -Int(1)) + NBKAssertComparisons(T(words:[1, 2, 0, 4] as W), T(words:[1, 2, 3, 4] as W), -Int(1)) + NBKAssertComparisons(T(words:[1, 2, 3, 0] as W), T(words:[1, 2, 3, 4] as W), -Int(1)) + NBKAssertComparisons(T(words:[0, 2, 3, 4] as W), T(words:[0, 2, 3, 4] as W), Int(0)) + NBKAssertComparisons(T(words:[1, 0, 3, 4] as W), T(words:[1, 0, 3, 4] as W), Int(0)) + NBKAssertComparisons(T(words:[1, 2, 0, 4] as W), T(words:[1, 2, 0, 4] as W), Int(0)) + NBKAssertComparisons(T(words:[1, 2, 3, 0] as W), T(words:[1, 2, 3, 0] as W), Int(0)) + NBKAssertComparisons(T(words:[1, 2, 3, 4] as W), T(words:[0, 2, 3, 4] as W), Int(1)) + NBKAssertComparisons(T(words:[1, 2, 3, 4] as W), T(words:[1, 0, 3, 4] as W), Int(1)) + NBKAssertComparisons(T(words:[1, 2, 3, 4] as W), T(words:[1, 2, 0, 4] as W), Int(1)) + NBKAssertComparisons(T(words:[1, 2, 3, 4] as W), T(words:[1, 2, 3, 0] as W), Int(1)) + } + + func testComparingAtIndex() { + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(0), Int(0)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(1), Int(0)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(2), Int(0)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(3), Int(0)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(4), Int(0)) + + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(0), -Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(1), -Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(2), -Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(3), -Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(4), -Int(1)) + + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(0), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(1), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(2), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(3), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(4), Int(1)) + + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(0), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(1), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(2), Int(0)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(3), -Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(4), -Int(1)) + } + + func testComparingByDigit() { + NBKAssertComparisonsByDigit(T(0), UInt(0), Int(0)) + NBKAssertComparisonsByDigit(T(1), UInt(1), Int(0)) + NBKAssertComparisonsByDigit(T(2), UInt(3), -Int(1)) + NBKAssertComparisonsByDigit(T(3), UInt(2), Int(1)) + + NBKAssertComparisonsByDigit(T(words:[0, 0, 0, 0]), UInt(1), -Int(1)) + NBKAssertComparisonsByDigit(T(words:[1, 0, 0, 0]), UInt(1), Int(0)) + NBKAssertComparisonsByDigit(T(words:[2, 0, 0, 0]), UInt(1), Int(1)) + + NBKAssertComparisonsByDigit(T(words:[0, 1, 0, 0]), UInt(1), Int(1)) + NBKAssertComparisonsByDigit(T(words:[1, 1, 0, 0]), UInt(1), Int(1)) + NBKAssertComparisonsByDigit(T(words:[2, 1, 0, 0]), UInt(1), Int(1)) + } + + func testComparingByDigitAtIndex() { + NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), UInt(4), Int(0), Int(1)) + NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), UInt(4), Int(1), Int(1)) + NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), UInt(4), Int(2), Int(1)) + NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), UInt(4), Int(3), Int(1)) + NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), UInt(4), Int(4), -Int(1)) + + NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), UInt(5), Int(0), Int(1)) + NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), UInt(5), Int(1), Int(1)) + NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), UInt(5), Int(2), Int(1)) + NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), UInt(5), Int(3), -Int(1)) + NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), UInt(5), Int(4), -Int(1)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Miscellaneous + //=------------------------------------------------------------------------= + + func testOverloadsAreUnambiguous() { + func becauseThisCompilesSuccessfully(_ x: inout T) { + XCTAssertNotNil(x.signum()) + } + } + + func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { + func becauseThisCompilesSuccessfully(_ x: inout T) { + XCTAssertNotNil(x.compared(to: 0)) + XCTAssertNotNil(x.compared(to: 0, at: 0)) + } + } +} + +//*============================================================================* +// MARK: * NBK x Resizable Width x Comparisons x Assertions +//*============================================================================* + +private func NBKAssertSignum( +_ operand: T, _ signum: Int, +file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual(Int(operand.signum() as Int), signum, file: file, line: line) + // TODO: stdlib implementation requires subtraction + // XCTAssertEqual(Int(operand.signum() as T ), signum, file: file, line: line) // stdlib +} + +private func NBKAssertComparisons( +_ lhs: T, _ rhs: T, _ signum: Int, +file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual(lhs == rhs, signum == 0, file: file, line: line) + XCTAssertEqual(lhs != rhs, signum != 0, file: file, line: line) + + XCTAssertEqual(lhs < rhs, signum == -1, file: file, line: line) + XCTAssertEqual(lhs <= rhs, signum != 1, file: file, line: line) + + XCTAssertEqual(lhs > rhs, signum == 1, file: file, line: line) + XCTAssertEqual(lhs >= rhs, signum != -1, file: file, line: line) + + XCTAssertEqual(lhs.compared(to: rhs), signum, file: file, line: line) +} + +private func NBKAssertComparisonsAtIndex( +_ lhs: T, _ rhs: T, _ index: Int, _ signum: Int, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + if index.isZero { + NBKAssertComparisons(lhs, rhs, signum, file: file, line: line) + } + //=------------------------------------------= + XCTAssertEqual(lhs.compared(to: rhs, at: index), signum, file: file, line: line) +} + +private func NBKAssertComparisonsByDigit( +_ lhs: T, _ rhs: T.Digit, _ signum: Int, +file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual(lhs == rhs, signum == 0, file: file, line: line) + XCTAssertEqual(lhs != rhs, signum != 0, file: file, line: line) + + XCTAssertEqual(lhs < rhs, signum == -1, file: file, line: line) + XCTAssertEqual(lhs <= rhs, signum != 1, file: file, line: line) + + XCTAssertEqual(lhs > rhs, signum == 1, file: file, line: line) + XCTAssertEqual(lhs >= rhs, signum != -1, file: file, line: line) + + XCTAssertEqual(lhs.compared(to: rhs), signum, file: file, line: line) +} + +private func NBKAssertComparisonsByDigitAtIndex( +_ lhs: T, _ rhs: T.Digit, _ index: Int, _ signum: Int, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + if index.isZero { + NBKAssertComparisonsByDigit(lhs, rhs, signum, file: file, line: line) + } + //=------------------------------------------= + XCTAssertEqual(lhs.compared(to: rhs, at: index), signum, file: file, line: line) +} + +#endif From ac349fc13dc062a84b17fdad6892aaaf67911b7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Mon, 7 Aug 2023 04:01:06 +0200 Subject: [PATCH 050/133] NBKResizableWidthKit: Logic. --- .../NBKFlexibleWidth+Logic.swift | 24 +--- ...BKFlexibleWidth+Multiplication+Digit.swift | 2 +- .../NBKFlexibleWidth+Protocols.swift | 6 + .../NBKFlexibleWidth+Size.swift | 41 ++++++ .../NBKResizableWidth+Complements.swift | 10 -- .../NBKResizableWidth+Logic.swift | 35 +++-- .../NBKResizableWidth+Numbers.swift | 12 ++ .../NBKResizableWidth+Protocols.swift | 12 ++ .../NBKResizableWidth+Size.swift | 10 +- .../Private/NBK+Pointers.swift | 32 ----- .../NBKResizableWidth+Logic.swift | 117 ++++++++++++++++ .../NBKResizableWidth+Logic.swift | 131 ++++++++++++++++++ 12 files changed, 354 insertions(+), 78 deletions(-) create mode 100644 Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Size.swift delete mode 100644 Sources/NBKResizableWidthKit/Private/NBK+Pointers.swift create mode 100644 Tests/NBKResizableWidthKitBenchmarks/NBKResizableWidth+Logic.swift create mode 100644 Tests/NBKResizableWidthKitTests/NBKResizableWidth+Logic.swift diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift index 99d68e8c..29caa943 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift @@ -80,13 +80,9 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @inlinable public static func &=(lhs: inout Self, rhs: Self) { - defer { - Swift.assert(lhs.storage.isNormal) - } - //=--------------------------------------= - lhs.storage.resize(maxCount: rhs.storage.count) - lhs.storage.formInIntersection(of: rhs.storage, each: &) + lhs.storage.downsizeThenFormInIntersection(of: rhs.storage, each: &) lhs.storage.normalize() + Swift.assert(lhs.storage.isNormal) } @inlinable public static func &(lhs: Self, rhs: Self) -> Self { @@ -98,12 +94,8 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @inlinable public static func |=(lhs: inout Self, rhs: Self) { - defer { - Swift.assert(lhs.storage.isNormal) - } - //=--------------------------------------= - lhs.storage.resize(minCount: rhs.storage.count) - lhs.storage.formInIntersection(of: rhs.storage, each: |) + lhs.storage |= rhs.storage + Swift.assert(lhs.storage.isNormal) } @inlinable public static func |(lhs: Self, rhs: Self) -> Self { @@ -115,13 +107,9 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @inlinable public static func ^=(lhs: inout Self, rhs: Self) { - defer { - Swift.assert(lhs.storage.isNormal) - } - //=--------------------------------------= - lhs.storage.resize(minCount: rhs.storage.count) - lhs.storage.formInIntersection(of: rhs.storage, each: ^) + lhs.storage ^= rhs.storage lhs.storage.normalize() + Swift.assert(lhs.storage.isNormal) } @inlinable public static func ^(lhs: Self, rhs: Self) -> Self { diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift index aca6dd01..bb95f37a 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift @@ -75,7 +75,7 @@ extension NBKFlexibleWidth.Magnitude { return self.assign(addend) } //=--------------------------------------= - self.storage.reserve(minCount: self.storage.count + 1) + self.storage.reserveCapacity(self.storage.count + 1) let overflow = self.storage.multiply(by: multiplicand, plus: addend) if !overflow.isZero { self.storage.append(overflow) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Protocols.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Protocols.swift index 1780b34c..d05f2f2f 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Protocols.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Protocols.swift @@ -17,6 +17,12 @@ import NBKCoreKit public protocol IntXLOrUIntXL: NBKBinaryInteger, LosslessStringConvertible { + //=------------------------------------------------------------------------= + // MARK: Details x Size + //=------------------------------------------------------------------------= + + @inlinable mutating func reserveCapacity(_ minCapacity: Int) + //=------------------------------------------------------------------------= // MARK: Details x Comparisons //=------------------------------------------------------------------------= diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Size.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Size.swift new file mode 100644 index 00000000..b6d86c8d --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Size.swift @@ -0,0 +1,41 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit +import NBKResizableWidthKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x Size x Signed +//*============================================================================* + +extension NBKFlexibleWidth { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public mutating func reserveCapacity(_ minCapacity: Int) { + self.magnitude.reserveCapacity(minCapacity + 1) + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Size x Unsigned +//*============================================================================* + +extension NBKFlexibleWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public mutating func reserveCapacity(_ minCapacity: Int) { + self.storage.reserveCapacity(minCapacity) + } +} diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Complements.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Complements.swift index 04392d82..0ff74a50 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Complements.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Complements.swift @@ -33,16 +33,6 @@ extension NBKResizableWidth.Magnitude { // MARK: Details x Two's Complement //=------------------------------------------------------------------------= - // TODO: use NBKBinaryInteger default - @inlinable public mutating func formTwosComplement() { - _ = self.formTwosComplementReportingOverflow() - } - - // TODO: use NBKBinaryInteger default - @inlinable public func twosComplement() -> Self { - self.twosComplementReportingOverflow().partialValue - } - @inlinable public mutating func formTwosComplementReportingOverflow() -> Bool { self.formTwosComplementSubsequence(true) } diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Logic.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Logic.swift index 31dca807..c83dd22a 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Logic.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Logic.swift @@ -28,7 +28,7 @@ extension NBKResizableWidth.Magnitude { //=------------------------------------------------------------------------= @inlinable public static func &=(lhs: inout Self, rhs: Self) { - fatalError("TODO") + lhs.upsizeThenFormInIntersection(of: rhs, each: &) } @inlinable public static func &(lhs: Self, rhs: Self) -> Self { @@ -40,7 +40,7 @@ extension NBKResizableWidth.Magnitude { //=------------------------------------------------------------------------= @inlinable public static func |=(lhs: inout Self, rhs: Self) { - fatalError("TODO") + lhs.upsizeThenFormInIntersection(of: rhs, each: |) } @inlinable public static func |(lhs: Self, rhs: Self) -> Self { @@ -52,7 +52,7 @@ extension NBKResizableWidth.Magnitude { //=------------------------------------------------------------------------= @inlinable public static func ^=(lhs: inout Self, rhs: Self) { - fatalError("TODO") + lhs.upsizeThenFormInIntersection(of: rhs, each: ^) } @inlinable public static func ^(lhs: Self, rhs: Self) -> Self { @@ -70,14 +70,25 @@ extension NBKResizableWidth.Magnitude { // MARK: Transformations //=------------------------------------------------------------------------= - // TODO: internal - @inlinable public mutating func formInIntersection(of other: Self, each element: (UInt, UInt) -> UInt) { - self .storage.withUnsafeMutableBufferPointer { lhs in - other.storage.withUnsafeBufferPointer { rhs in - let endIndex = Swift.min(lhs.endIndex, rhs.endIndex) - let lhsIntersection = NBK.UnsafeMutableWords(rebasing: lhs.prefix(upTo: endIndex)) - let rhsIntersection = /*---*/NBK.UnsafeWords(rebasing: rhs.prefix(upTo: endIndex)) - NBK.merge(into: lhsIntersection, from: NBK.UnsafeWords(lhsIntersection), rhsIntersection, each: element) - }} + @inlinable public mutating func upsizeThenFormInIntersection(of other: Self, each element: (UInt, UInt) -> UInt) { + self.resize(minCount: other.storage.count) + self.withContiguousMutableStorage { lhs in + other.withContiguousStorage { rhs in + for index in rhs.indices { + lhs[index] = element(lhs[index], rhs[index]) + } + } + } + } + + @inlinable public mutating func downsizeThenFormInIntersection(of other: Self, each element: (UInt, UInt) -> UInt) { + self.resize(maxCount: other.storage.count) + self.withContiguousMutableStorage { lhs in + other.withContiguousStorage { rhs in + for index in lhs.indices { + lhs[index] = element(lhs[index], rhs[index]) + } + } + } } } diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Numbers.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Numbers.swift index e8967465..2ed95db9 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Numbers.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Numbers.swift @@ -99,4 +99,16 @@ extension NBKResizableWidth.Magnitude { @inlinable public init?(exactly source: some BinaryFloatingPoint) { fatalError("TODO") } + + //=------------------------------------------------------------------------= + // MARK: Initializers x Sign & Magnitude + //=------------------------------------------------------------------------= + + @inlinable public static func exactly(sign: FloatingPointSign, magnitude: Magnitude) -> Self? { + if sign == FloatingPointSign.plus || magnitude.isZero { return magnitude } else { return nil } + } + + @inlinable public static func clamping(sign: FloatingPointSign, magnitude: Magnitude) -> Self { + if sign == FloatingPointSign.plus { return magnitude } else { return Self.zero } + } } diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Protocols.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Protocols.swift index 90cfdb3f..27f7e627 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Protocols.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Protocols.swift @@ -16,6 +16,18 @@ import NBKCoreKit public protocol IntXROrUIntXR: NBKBinaryInteger, LosslessStringConvertible, MutableCollection, RandomAccessCollection where Element == UInt, Index == Int, Indices == Range { + //=------------------------------------------------------------------------= + // MARK: Details x Size + //=------------------------------------------------------------------------= + + @inlinable mutating func append(_ word: UInt) + + @inlinable mutating func resize(minCount: Int) + + @inlinable mutating func resize(maxCount: Int) + + @inlinable mutating func reserveCapacity(_ minCapacity: Int) + //=------------------------------------------------------------------------= // MARK: Details x Comparisons //=------------------------------------------------------------------------= diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Size.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Size.swift index abd35271..8bac6c49 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Size.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Size.swift @@ -23,12 +23,8 @@ extension NBKResizableWidth.Magnitude { self.storage.append(word) } - @inlinable public mutating func reserve(minCount: Int) { - self.storage.reserveCapacity(minCount) - } - @inlinable public mutating func resize(minCount: Int) { - self.reserve(minCount: minCount) + self.reserveCapacity(minCount) appending: while self.storage.count < minCount { self.storage.append(UInt.zero) } @@ -43,6 +39,10 @@ extension NBKResizableWidth.Magnitude { precondition(self.isOK, Self.callsiteInvariantsInfo()) } + @inlinable public mutating func reserveCapacity(_ minCapacity: Int) { + self.storage.reserveCapacity(minCapacity) + } + //=------------------------------------------------------------------------= // MARK: Details x Normalization //=------------------------------------------------------------------------= diff --git a/Sources/NBKResizableWidthKit/Private/NBK+Pointers.swift b/Sources/NBKResizableWidthKit/Private/NBK+Pointers.swift deleted file mode 100644 index 6cabcd95..00000000 --- a/Sources/NBKResizableWidthKit/Private/NBK+Pointers.swift +++ /dev/null @@ -1,32 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Pointers -//*============================================================================* - -extension NBK { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable static func merge(into result: UnsafeMutableBufferPointer, - from x0: UnsafeBufferPointer, _ x1: UnsafeBufferPointer, each element: (T, T) -> T) { - //=--------------------------------------= - precondition(result.count == x0.count, NBK.callsiteOutOfBoundsInfo()) - precondition(result.count == x1.count, NBK.callsiteOutOfBoundsInfo()) - //=--------------------------------------= - for index in result.indices { - result[index] = element(x0[index], x1[index]) - } - } -} diff --git a/Tests/NBKResizableWidthKitBenchmarks/NBKResizableWidth+Logic.swift b/Tests/NBKResizableWidthKitBenchmarks/NBKResizableWidth+Logic.swift new file mode 100644 index 00000000..c84d3acd --- /dev/null +++ b/Tests/NBKResizableWidthKitBenchmarks/NBKResizableWidth+Logic.swift @@ -0,0 +1,117 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if !DEBUG + +import NBKCoreKit +import NBKResizableWidthKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Resizable Width x Logic x UIntXR +//*============================================================================* + +final class NBKResizableWidthBenchmarksOnLogicAsUIntXR: XCTestCase { + + typealias T = UIntXR + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testNotInout() { + var abc = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.formOnesComplement()) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testNot() { + var abc = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(~abc) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testAndInout() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs &= rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testAnd() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs & rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testOrInout() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs |= rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testOr() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs | rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testXorInout() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs ^= rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testXor() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs ^ rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } +} + +#endif diff --git a/Tests/NBKResizableWidthKitTests/NBKResizableWidth+Logic.swift b/Tests/NBKResizableWidthKitTests/NBKResizableWidth+Logic.swift new file mode 100644 index 00000000..40bf33ca --- /dev/null +++ b/Tests/NBKResizableWidthKitTests/NBKResizableWidth+Logic.swift @@ -0,0 +1,131 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +import NBKResizableWidthKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Resizable Width x Logic x UIntXR +//*============================================================================* + +final class NBKResizableWidthTestsOnLogicAsUIntXR: XCTestCase { + + typealias T = UIntXR + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testNot() { + NBKAssertNot(T(words:[ 0, 0, 0, 0] as W), T(words:[~0, ~0, ~0, ~0] as W)) + NBKAssertNot(T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 0, 0, 0, 0] as W)) + + NBKAssertNot(T(words:[ 0, 1, 2, 3] as W), T(words:[~0, ~1, ~2, ~3] as W)) + NBKAssertNot(T(words:[~0, ~1, ~2, ~3] as W), T(words:[ 0, 1, 2, 3] as W)) + } + + func testAnd() { + NBKAssertAnd(T(words:[ 0, 1, 2, 3] as W), T(words:[ 0, 0, 0, 0] as W), T(words:[ 0, 0, 0, 0] as W)) + NBKAssertAnd(T(words:[ 3, 2, 1, 0] as W), T(words:[ 0, 0, 0, 0] as W), T(words:[ 0, 0, 0, 0] as W)) + + NBKAssertAnd(T(words:[ 0, 1, 2, 3] as W), T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 0, 1, 2, 3] as W)) + NBKAssertAnd(T(words:[ 3, 2, 1, 0] as W), T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 3, 2, 1, 0] as W)) + + NBKAssertAnd(T(words:[ 0, 1, 2, 3] as W), T(words:[ 1, 1, 1, 1] as W), T(words:[ 0, 1, 0, 1] as W)) + NBKAssertAnd(T(words:[ 3, 2, 1, 0] as W), T(words:[ 1, 1, 1, 1] as W), T(words:[ 1, 0, 1, 0] as W)) + } + + func testOr() { + NBKAssertOr (T(words:[ 0, 1, 2, 3] as W), T(words:[ 0, 0, 0, 0] as W), T(words:[ 0, 1, 2, 3] as W)) + NBKAssertOr (T(words:[ 3, 2, 1, 0] as W), T(words:[ 0, 0, 0, 0] as W), T(words:[ 3, 2, 1, 0] as W)) + + NBKAssertOr (T(words:[ 0, 1, 2, 3] as W), T(words:[~0, ~0, ~0, ~0] as W), T(words:[~0, ~0, ~0, ~0] as W)) + NBKAssertOr (T(words:[ 3, 2, 1, 0] as W), T(words:[~0, ~0, ~0, ~0] as W), T(words:[~0, ~0, ~0, ~0] as W)) + + NBKAssertOr (T(words:[ 0, 1, 2, 3] as W), T(words:[ 1, 1, 1, 1] as W), T(words:[ 1, 1, 3, 3] as W)) + NBKAssertOr (T(words:[ 3, 2, 1, 0] as W), T(words:[ 1, 1, 1, 1] as W), T(words:[ 3, 3, 1, 1] as W)) + } + + func testXor() { + NBKAssertXor(T(words:[ 0, 1, 2, 3] as W), T(words:[ 0, 0, 0, 0] as W), T(words:[ 0, 1, 2, 3] as W)) + NBKAssertXor(T(words:[ 3, 2, 1, 0] as W), T(words:[ 0, 0, 0, 0] as W), T(words:[ 3, 2, 1, 0] as W)) + + NBKAssertXor(T(words:[ 0, 1, 2, 3] as W), T(words:[~0, ~0, ~0, ~0] as W), T(words:[~0, ~1, ~2, ~3] as W)) + NBKAssertXor(T(words:[ 3, 2, 1, 0] as W), T(words:[~0, ~0, ~0, ~0] as W), T(words:[~3, ~2, ~1, ~0] as W)) + + NBKAssertXor(T(words:[ 0, 1, 2, 3] as W), T(words:[ 1, 1, 1, 1] as W), T(words:[ 1, 0, 3, 2] as W)) + NBKAssertXor(T(words:[ 3, 2, 1, 0] as W), T(words:[ 1, 1, 1, 1] as W), T(words:[ 2, 3, 0, 1] as W)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Miscellaneous + //=------------------------------------------------------------------------= + + func testOperationsHaveUpsizingSemantics() { + NBKAssertAnd(T(words:[0 ] as W), T(words:[0, 0] as W), T(words:[0, 0] as W)) + NBKAssertAnd(T(words:[0, 0] as W), T(words:[0 ] as W), T(words:[0, 0] as W)) + + NBKAssertOr (T(words:[0 ] as W), T(words:[0, 0] as W), T(words:[0, 0] as W)) + NBKAssertOr (T(words:[0, 0] as W), T(words:[0 ] as W), T(words:[0, 0] as W)) + + NBKAssertXor(T(words:[0 ] as W), T(words:[0, 0] as W), T(words:[0, 0] as W)) + NBKAssertXor(T(words:[0, 0] as W), T(words:[0 ] as W), T(words:[0, 0] as W)) + } +} + +//*============================================================================* +// MARK: * NBK x Resizable Width x Logic x Assertions +//*============================================================================* + +private func NBKAssertNot( +_ operand: T, _ result: T, +file: StaticString = #file, line: UInt = #line) { + if operand.words.last != UInt.max { + XCTAssertEqual(~operand, result, file: file, line: line) + XCTAssertEqual(~result, operand, file: file, line: line) + } else { + XCTAssertEqual(~operand, result, file: file, line: line) + } +} + +private func NBKAssertAnd( +_ lhs: T, _ rhs: T, _ result: T, +file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual( lhs & rhs, result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs &= rhs; return lhs }(), result, file: file, line: line) + XCTAssertEqual( rhs & lhs, result, file: file, line: line) + XCTAssertEqual({ var rhs = rhs; rhs &= lhs; return rhs }(), result, file: file, line: line) +} + +private func NBKAssertOr( +_ lhs: T, _ rhs: T, _ result: T, +file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual( lhs | rhs, result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs |= rhs; return lhs }(), result, file: file, line: line) + XCTAssertEqual( rhs | lhs, result, file: file, line: line) + XCTAssertEqual({ var rhs = rhs; rhs |= lhs; return rhs }(), result, file: file, line: line) +} + +private func NBKAssertXor( +_ lhs: T, _ rhs: T, _ result: T, +file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual( lhs ^ rhs, result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs ^= rhs; return lhs }(), result, file: file, line: line) + XCTAssertEqual( rhs ^ lhs, result, file: file, line: line) + XCTAssertEqual({ var rhs = rhs; rhs ^= lhs; return rhs }(), result, file: file, line: line) +} + +#endif From 84579fa55cf9f1385592ff3a4f1b62aa39785cb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Mon, 7 Aug 2023 04:24:53 +0200 Subject: [PATCH 051/133] NBKResizableWidthKit: Shifts. --- .../NBKFlexibleWidth+Shifts.swift | 128 +++++++---- .../NBKResizableWidth+Miscellaneous.swift | 29 +++ .../NBKResizableWidth+Protocols.swift | 36 +++ .../NBKResizableWidth+Shifts.swift | 152 +++++++++++-- .../NBKResizableWidth+Shifts.swift | 152 +++++++++++++ .../NBKResizableWidth+Shifts.swift | 206 ++++++++++++++++++ 6 files changed, 650 insertions(+), 53 deletions(-) create mode 100644 Sources/NBKResizableWidthKit/NBKResizableWidth+Miscellaneous.swift create mode 100644 Tests/NBKResizableWidthKitBenchmarks/NBKResizableWidth+Shifts.swift create mode 100644 Tests/NBKResizableWidthKitTests/NBKResizableWidth+Shifts.swift diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift index 9a867ae2..1bd48593 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift @@ -198,21 +198,12 @@ extension NBKFlexibleWidth.Magnitude { } @inlinable public mutating func bitshiftLeft(words: Int, bits: Int) { - defer { - Swift.assert(self.storage.isNormal) - } //=--------------------------------------= if bits.isZero { return self.bitshiftLeft(words: words) } //=--------------------------------------= - if self.isZero { - return - } - //=--------------------------------------= - let rollover = Int(bit: self.leadingZeroBitCount < bits) - self.storage.resize(minCount: self.storage.count + words + rollover) - self.storage.bitshiftLeft(words: words, atLeastOneBit: bits) + self.bitshiftLeft(words: words, atLeastOneBit: bits) } @inlinable public func bitshiftedLeft(words: Int, bits: Int) -> Self { @@ -220,24 +211,58 @@ extension NBKFlexibleWidth.Magnitude { } @inlinable public mutating func bitshiftLeft(words: Int) { + //=--------------------------------------= + if words.isZero { return } + //=--------------------------------------= + self.bitshiftLeft(atLeastOneWord: words) + } + + @inlinable public func bitshiftedLeft(words: Int) -> Self { + var result = self; result.bitshiftLeft(words: words); return result + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Int x Private + //=------------------------------------------------------------------------= + + /// Performs a left shift. + /// + /// - Parameters: + /// - words: `0 <= words < self.endIndex` + /// - bits: `1 <= bits  < UInt.bitWidth` + /// + @inlinable mutating func bitshiftLeft(words: Int, atLeastOneBit bits: Int) { defer { Swift.assert(self.storage.isNormal) } //=--------------------------------------= - if words.isZero { - return - } - //=--------------------------------------= if self.isZero { return } //=--------------------------------------= - self.storage.resize(minCount: self.storage.count + words) - self.storage.bitshiftLeft(atLeastOneWord: words) + let rollover = Int(bit: self.leadingZeroBitCount < bits) + self.storage.resize(minCount: self.storage.count + words + rollover) + self.storage.withContiguousMutableStorage { + NBK.bitshiftLeftAsFixedLimbsCodeBlock(&$0, environment: false, limbs: words, atLeastOneBit: bits) + } } - @inlinable public func bitshiftedLeft(words: Int) -> Self { - var result = self; result.bitshiftLeft(words: words); return result + /// Performs a left shift. + /// + /// - Parameters: + /// - words: `1 <= words < self.endIndex` + /// + @inlinable mutating func bitshiftLeft(atLeastOneWord words: Int) { + defer { + Swift.assert(self.storage.isNormal) + } + //=--------------------------------------= + if self.isZero { return } + //=--------------------------------------= + self.storage.resize(minCount: self.storage.count + words) + self.storage.withContiguousMutableStorage { + NBK.bitshiftLeftAsFixedLimbsCodeBlock(&$0, environment: false, atLeastOneLimb: words) + } } } @@ -287,23 +312,12 @@ extension NBKFlexibleWidth.Magnitude { } @inlinable public mutating func bitshiftRight(words: Int, bits: Int) { - defer { - Swift.assert(self.storage.isNormal) - } //=--------------------------------------= if bits.isZero { return self.bitshiftRight(words: words) } //=--------------------------------------= - let rollover = Int(bit: bits + self.leadingZeroBitCount - UInt.bitWidth >= 0) - let maxCount = self.storage.count - words - rollover - //=--------------------------------------= - if maxCount < 1 { - return self.assignZeroValue() - } - //=--------------------------------------= - self.storage.bitshiftRight(words: words, atLeastOneBit: bits) - self.storage.resize(maxCount: maxCount) + self.bitshiftRight(words: words, atLeastOneBit: bits) } @inlinable public func bitshiftedRight(words: Int, bits: Int) -> Self { @@ -311,23 +325,63 @@ extension NBKFlexibleWidth.Magnitude { } @inlinable public mutating func bitshiftRight(words: Int) { + //=--------------------------------------= + if words.isZero { return } + //=--------------------------------------= + self.bitshiftRight(atLeastOneWord: words) + } + + @inlinable public func bitshiftedRight(words: Int) -> Self { + var result = self; result.bitshiftRight(words: words); return result + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Int x Private + //=------------------------------------------------------------------------= + + /// Performs an un/signed right shift. + /// + /// - Parameters: + /// - words: `1 <= words < self.endIndex` + /// - bits: `0 <= bits  < UInt.bitWidth` + /// + @inlinable mutating func bitshiftRight(words: Int, atLeastOneBit bits: Int) { defer { Swift.assert(self.storage.isNormal) } //=--------------------------------------= - if words.isZero { - return + let rollover = Int(bit: 0 <= bits + self.leadingZeroBitCount - UInt.bitWidth) + let maxCount = self.storage.count - words - rollover + //=--------------------------------------= + if maxCount <= 0 { + return self.assignZeroValue() + } + //=--------------------------------------= + self.storage.withContiguousMutableStorage { + NBK.bitshiftRightAsFixedLimbsCodeBlock(&$0, environment: false, limbs: words, atLeastOneBit: bits) + } + + self.storage.resize(maxCount: maxCount) + } + + /// Performs an un/signed right shift. + /// + /// - Parameters: + /// - words: `1 <= words < self.endIndex` + /// + @inlinable mutating func bitshiftRight(atLeastOneWord words: Int) { + defer { + Swift.assert(self.storage.isNormal) } //=--------------------------------------= if self.storage.count <= words { return self.assignZeroValue() } //=--------------------------------------= - self.storage.bitshiftRight(words: words) + self.storage.withContiguousMutableStorage { + NBK.bitshiftRightAsFixedLimbsCodeBlock(&$0, environment: false, atLeastOneLimb: words) + } + self.storage.resize(maxCount: self.storage.count - words) } - - @inlinable public func bitshiftedRight(words: Int) -> Self { - var result = self; result.bitshiftRight(words: words); return result - } } diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Miscellaneous.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Miscellaneous.swift new file mode 100644 index 00000000..15cb0978 --- /dev/null +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Miscellaneous.swift @@ -0,0 +1,29 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Resizable Width x Miscellaneous x Unsigned +//*============================================================================* + +extension NBKResizableWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public mutating func assignZeroValue() { + self.assign(repeating: false) + } + + @inlinable public mutating func assign(repeating bit: Bool) { + self.withContiguousMutableStorage({ $0.update(repeating: UInt(repeating: bit)) }) + } +} diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Protocols.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Protocols.swift index 27f7e627..ffd8ce0a 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Protocols.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Protocols.swift @@ -36,6 +36,42 @@ RandomAccessCollection where Element == UInt, Index == Int, Indices == Range Int + //=------------------------------------------------------------------------= + // MARK: Details x Shifts + //=------------------------------------------------------------------------= + + @inlinable mutating func bitshiftLeftSmart(by distance: Int) + + @inlinable func bitshiftedLeftSmart(by distance: Int) -> Self + + @inlinable mutating func bitshiftLeft(by distance: Int) + + @inlinable func bitshiftedLeft(by distance: Int) -> Self + + @inlinable mutating func bitshiftLeft(words: Int, bits: Int) + + @inlinable func bitshiftedLeft(words: Int, bits: Int) -> Self + + @inlinable mutating func bitshiftLeft(words: Int) + + @inlinable func bitshiftedLeft(words: Int) -> Self + + @inlinable mutating func bitshiftRightSmart(by distance: Int) + + @inlinable func bitshiftedRightSmart(by distance: Int) -> Self + + @inlinable mutating func bitshiftRight(by distance: Int) + + @inlinable func bitshiftedRight(by distance: Int) -> Self + + @inlinable mutating func bitshiftRight(words: Int, bits: Int) + + @inlinable func bitshiftedRight(words: Int, bits: Int) -> Self + + @inlinable mutating func bitshiftRight(words: Int) + + @inlinable func bitshiftedRight(words: Int) -> Self + //=------------------------------------------------------------------------= // MARK: Details x Words //=------------------------------------------------------------------------= diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Shifts.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Shifts.swift index 443beac9..24aa628e 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Shifts.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Shifts.swift @@ -23,7 +23,7 @@ extension NBKResizableWidth.Magnitude { //=------------------------------------------------------------------------= @inlinable public static func <<=(lhs: inout Self, rhs: some BinaryInteger) { - fatalError("TODO") + lhs.bitshiftLeftSmart(by: NBK.initOrBitCast(clamping: rhs, as: Int.self)) } @inlinable public static func <<(lhs: Self, rhs: some BinaryInteger) -> Self { @@ -34,6 +34,29 @@ extension NBKResizableWidth.Magnitude { // MARK: Transformations x Int //=------------------------------------------------------------------------= + /// Performs a smart left shift. + /// + /// - Parameters: + /// - distance: `Int.min <= distance <= Int.max` + /// + @inlinable public mutating func bitshiftLeftSmart(by distance: Int) { + let size = distance.magnitude as UInt + switch (distance >= 0, size < UInt(bitPattern: self.bitWidth)) { + case (true, true ): self.bitshiftLeft (by: Int(bitPattern: size)) + case (true, false): self.assign(repeating: false) + case (false, true ): self.bitshiftRight(by: Int(bitPattern: size)) + case (false, false): self.assign(repeating: self.isLessThanZero) } + } + + /// Performs a smart left shift. + /// + /// - Parameters: + /// - distance: `Int.min <= distance <= Int.max` + /// + @inlinable public func bitshiftedLeftSmart(by distance: Int) -> Self { + var result = self; result.bitshiftLeftSmart(by: distance); return result + } + /// Performs a left shift. /// /// - Parameters: @@ -46,6 +69,15 @@ extension NBKResizableWidth.Magnitude { return self.bitshiftLeft(words: major, bits: minor) } + /// Performs a left shift. + /// + /// - Parameters: + /// - distance: `0 <= distance < self.bitWidth` + /// + @inlinable public func bitshiftedLeft(by distance: Int) -> Self { + var result = self; result.bitshiftLeft(by: distance); return result + } + /// Performs a left shift. /// /// - Parameters: @@ -60,6 +92,16 @@ extension NBKResizableWidth.Magnitude { //=--------------------------------------= self.bitshiftLeft(words: words, atLeastOneBit: bits) } + + /// Performs a left shift. + /// + /// - Parameters: + /// - words: `0 <= words < self.endIndex` + /// - bits: `0 <= bits  < UInt.bitWidth` + /// + @inlinable public func bitshiftedLeft(words: Int, bits: Int) -> Self { + var result = self; result.bitshiftLeft(words: words, bits: bits); return result + } /// Performs a left shift. /// @@ -73,20 +115,38 @@ extension NBKResizableWidth.Magnitude { self.bitshiftLeft(atLeastOneWord: words) } + /// Performs a left shift. + /// + /// - Parameters: + /// - words: `0 <= words < self.endIndex` + /// + @inlinable public func bitshiftedLeft(words: Int) -> Self { + var result = self; result.bitshiftLeft(words: words); return result + } + //=------------------------------------------------------------------------= // MARK: Transformations x Int x Private //=------------------------------------------------------------------------= - - // TODO: internal - @inlinable public mutating func bitshiftLeft(words: Int, atLeastOneBit bits: Int) { - self.storage.withUnsafeMutableBufferPointer { + + /// Performs a left shift. + /// + /// - Parameters: + /// - words: `0 <= words < self.endIndex` + /// - bits: `1 <= bits  < UInt.bitWidth` + /// + @inlinable mutating func bitshiftLeft(words: Int, atLeastOneBit bits: Int) { + self.withContiguousMutableStorage { NBK.bitshiftLeftAsFixedLimbsCodeBlock(&$0, environment: false, limbs: words, atLeastOneBit: bits) } } - - // TODO: internal - @inlinable public mutating func bitshiftLeft(atLeastOneWord words: Int) { - self.storage.withUnsafeMutableBufferPointer { + + /// Performs a left shift. + /// + /// - Parameters: + /// - words: `1 <= words < self.endIndex` + /// + @inlinable mutating func bitshiftLeft(atLeastOneWord words: Int) { + self.withContiguousMutableStorage { NBK.bitshiftLeftAsFixedLimbsCodeBlock(&$0, environment: false, atLeastOneLimb: words) } } @@ -103,7 +163,7 @@ extension NBKResizableWidth.Magnitude { //=------------------------------------------------------------------------= @inlinable public static func >>=(lhs: inout Self, rhs: some BinaryInteger) { - fatalError("TODO") + lhs.bitshiftRightSmart(by: NBK.initOrBitCast(clamping: rhs, as: Int.self)) } @inlinable public static func >>(lhs: Self, rhs: some BinaryInteger) -> Self { @@ -114,6 +174,29 @@ extension NBKResizableWidth.Magnitude { // MARK: Transformations x Int //=------------------------------------------------------------------------= + /// Performs an un/signed, smart, right shift. + /// + /// - Parameters: + /// - distance: `Int.min <= distance <= Int.max` + /// + @inlinable public mutating func bitshiftRightSmart(by distance: Int) { + let size = distance.magnitude as UInt + switch (distance >= 0, size < UInt(bitPattern: self.bitWidth)) { + case (true, true ): self.bitshiftRight(by: Int(bitPattern: size)) + case (true, false): self.assign(repeating: self.isLessThanZero) + case (false, true ): self.bitshiftLeft (by: Int(bitPattern: size)) + case (false, false): self.assign(repeating: false) } + } + + /// Performs an un/signed, smart, right shift. + /// + /// - Parameters: + /// - distance: `Int.min <= distance <= Int.max` + /// + @inlinable public func bitshiftedRightSmart(by distance: Int) -> Self { + var result = self; result.bitshiftRightSmart(by: distance); return result + } + /// Performs an un/signed right shift. /// /// - Parameters: @@ -126,6 +209,15 @@ extension NBKResizableWidth.Magnitude { return self.bitshiftRight(words: major, bits: minor) } + /// Performs an un/signed right shift. + /// + /// - Parameters: + /// - distance: `0 <= distance < self.bitWidth` + /// + @inlinable public func bitshiftedRight(by distance: Int) -> Self { + var result = self; result.bitshiftRight(by: distance); return result + } + /// Performs an un/signed right shift. /// /// - Parameters: @@ -140,6 +232,16 @@ extension NBKResizableWidth.Magnitude { //=--------------------------------------= self.bitshiftRight(words: words, atLeastOneBit: bits) } + + /// Performs an un/signed right shift. + /// + /// - Parameters: + /// - words: `0 <= words < self.endIndex` + /// - bits: `0 <= bits  < UInt.bitWidth` + /// + @inlinable public func bitshiftedRight(words: Int, bits: Int) -> Self { + var result = self; result.bitshiftRight(words: words, bits: bits); return result + } /// Performs an un/signed right shift. /// @@ -153,20 +255,38 @@ extension NBKResizableWidth.Magnitude { self.bitshiftRight(atLeastOneWord: words) } + /// Performs an un/signed right shift. + /// + /// - Parameters: + /// - words: `0 <= words < self.endIndex` + /// + @inlinable public func bitshiftedRight(words: Int) -> Self { + var result = self; result.bitshiftRight(words: words); return result + } + //=------------------------------------------------------------------------= // MARK: Transformations x Int x Private //=------------------------------------------------------------------------= - // TODO: internal - @inlinable public mutating func bitshiftRight(words: Int, atLeastOneBit bits: Int) { - self.storage.withUnsafeMutableBufferPointer { + /// Performs an un/signed right shift. + /// + /// - Parameters: + /// - words: `1 <= words < self.endIndex` + /// - bits: `0 <= bits  < UInt.bitWidth` + /// + @inlinable mutating func bitshiftRight(words: Int, atLeastOneBit bits: Int) { + self.withContiguousMutableStorage { NBK.bitshiftRightAsFixedLimbsCodeBlock(&$0, environment: false, limbs: words, atLeastOneBit: bits) } } - // TODO: internal - @inlinable public mutating func bitshiftRight(atLeastOneWord words: Int) { - self.storage.withUnsafeMutableBufferPointer { + /// Performs an un/signed right shift. + /// + /// - Parameters: + /// - words: `1 <= words < self.endIndex` + /// + @inlinable mutating func bitshiftRight(atLeastOneWord words: Int) { + self.withContiguousMutableStorage { NBK.bitshiftRightAsFixedLimbsCodeBlock(&$0, environment: false, atLeastOneLimb: words) } } diff --git a/Tests/NBKResizableWidthKitBenchmarks/NBKResizableWidth+Shifts.swift b/Tests/NBKResizableWidthKitBenchmarks/NBKResizableWidth+Shifts.swift new file mode 100644 index 00000000..c745d9be --- /dev/null +++ b/Tests/NBKResizableWidthKitBenchmarks/NBKResizableWidth+Shifts.swift @@ -0,0 +1,152 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if !DEBUG + +import NBKCoreKit +import NBKResizableWidthKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Resizable Width x Shifts x UIntXR +//*============================================================================* + +final class NBKResizableWidthBenchmarksOnShiftsAsUIntXR: XCTestCase { + + typealias T = UIntXR + + //=------------------------------------------------------------------------= + // MARK: Tests x Left + //=------------------------------------------------------------------------= + + func testBitshiftingLeft() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(UInt.bitWidth * 3/2) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs << rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testBitshiftingLeftByWords() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs.bitshiftedLeft(words: rhs.words)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testBitshiftingLeftByWordsAndBits() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs.bitshiftedLeft(words: rhs.words, bits: rhs.bits)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Right + //=------------------------------------------------------------------------= + + func testBitshiftingRight() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(UInt.bitWidth * 3/2) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs >> rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testBitshiftingRightByWords() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs.bitshiftedRight(words: rhs.words)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testBitshiftingRightByWordsAndBits() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs.bitshiftedRight(words: rhs.words, bits: rhs.bits)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x In Both Directions + //=------------------------------------------------------------------------= + + func testBitshiftingInBothDirectionsInout() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(UInt.bitWidth * 3/2) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs.bitshiftLeft (by: rhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + + NBK.blackHole(lhs.bitshiftRight(by: rhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testBitshiftingInBothDirectionsByWordsInout() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs.bitshiftLeft (words: rhs.words)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + + NBK.blackHole(lhs.bitshiftRight(words: rhs.words)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testBitshiftingInBothDirectionsByWordsAndBitsInout() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs.bitshiftLeft (words: rhs.words, bits: rhs.bits)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + + NBK.blackHole(lhs.bitshiftRight(words: rhs.words, bits: rhs.bits)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } +} + +#endif diff --git a/Tests/NBKResizableWidthKitTests/NBKResizableWidth+Shifts.swift b/Tests/NBKResizableWidthKitTests/NBKResizableWidth+Shifts.swift new file mode 100644 index 00000000..a4a64ab7 --- /dev/null +++ b/Tests/NBKResizableWidthKitTests/NBKResizableWidth+Shifts.swift @@ -0,0 +1,206 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +import NBKResizableWidthKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Resizable Width x Shifts x UIntXR +//*============================================================================* + +final class NBKResizableWidthTestsOnShiftsAsUIntXR: XCTestCase { + + typealias T = UIntXR + + //=------------------------------------------------------------------------= + // MARK: Tests x Left + //=------------------------------------------------------------------------= + + func testBitshiftingLeftByBits() { + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 0, T(x64:[ 1, 2, 3, 4] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 1, T(x64:[ 2, 4, 6, 8] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 2, T(x64:[ 4, 8, 12, 16] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 3, T(x64:[ 8, 16, 24, 32] as X)) + } + + func testBitshiftingLeftByWords() { + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 0, T(x64:[ 1, 2, 3, 4] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 64, T(x64:[ 0, 1, 2, 3] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 128, T(x64:[ 0, 0, 1, 2] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 192, T(x64:[ 0, 0, 0, 1] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 256, T(x64:[ 0, 0, 0, 0] as X)) + } + + func testBitshiftingLeftByWordsAndBits() { + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 3, T(x64:[ 8, 16, 24, 32] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 67, T(x64:[ 0, 8, 16, 24] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 131, T(x64:[ 0, 0, 8, 16] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 195, T(x64:[ 0, 0, 0, 8] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 259, T(x64:[ 0, 0, 0, 0] as X)) + } + + func testBitshiftingLeftSuchThatWordsSplit() { + NBKAssertShiftLeft(T(x64:[~0, 0, 0, 0] as X), 1, T(x64:[~1, 1, 0, 0] as X)) + NBKAssertShiftLeft(T(x64:[ 0, ~0, 0, 0] as X), 1, T(x64:[ 0, ~1, 1, 0] as X)) + NBKAssertShiftLeft(T(x64:[ 0, 0, ~0, 0] as X), 1, T(x64:[ 0, 0, ~1, 1] as X)) + NBKAssertShiftLeft(T(x64:[ 0, 0, 0, ~0] as X), 1, T(x64:[ 0, 0, 0, ~1] as X)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Right + //=------------------------------------------------------------------------= + + func testBitshiftingRightByBits() { + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 0, T(x64:[ 8, 16, 24, 32] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 1, T(x64:[ 4, 8, 12, 16] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 2, T(x64:[ 2, 4, 6, 8] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 3, T(x64:[ 1, 2, 3, 4] as X)) + } + + func testBitshiftingRightByWords() { + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 0, T(x64:[ 8, 16, 24, 32] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 64, T(x64:[16, 24, 32, 0] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 128, T(x64:[24, 32, 0, 0] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 192, T(x64:[32, 0, 0, 0] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 256, T(x64:[ 0, 0, 0, 0] as X)) + } + + func testBitshiftingRightByWordsAndBits() { + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 3, T(x64:[ 1, 2, 3, 4] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 67, T(x64:[ 2, 3, 4, 0] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 131, T(x64:[ 3, 4, 0, 0] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 195, T(x64:[ 4, 0, 0, 0] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 259, T(x64:[ 0, 0, 0, 0] as X)) + } + + func testBitshiftingRightSuchThatWordsSplit() { + NBKAssertShiftRight(T(x64:[0, 0, 0, 7] as X), 1, T(x64:[ 0, 0, 1 << 63, 3] as X)) + NBKAssertShiftRight(T(x64:[0, 0, 7, 0] as X), 1, T(x64:[ 0, 1 << 63, 3, 0] as X)) + NBKAssertShiftRight(T(x64:[0, 7, 0, 0] as X), 1, T(x64:[ 1 << 63, 3, 0, 0] as X)) + NBKAssertShiftRight(T(x64:[7, 0, 0, 0] as X), 1, T(x64:[ 3, 0, 0, 0] as X)) + } + + func testBitshiftingRightIsUnsigned() { + NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X), 0, T(x64:[0, 0, 0, 1 << 63] as X)) + NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X), 64, T(x64:[0, 0, 1 << 63, 0] as X)) + NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X), 128, T(x64:[0, 1 << 63, 0, 0] as X)) + NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X), 192, T(x64:[1 << 63, 0, 0, 0] as X)) + NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X), 256, T(x64:[0, 0, 0, 0] as X)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Miscellaneous + //=------------------------------------------------------------------------= + + func testBitshiftingIsSmart() { + XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) << 1, T(x64:[2, 4, 6, 8] as X)) + XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) >> -1, T(x64:[2, 4, 6, 8] as X)) + + XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) << 64, T(x64:[0, 1, 2, 3] as X)) + XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) >> -64, T(x64:[0, 1, 2, 3] as X)) + } + + func testBitshiftingRightDoesNotTrap() { + XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) >> Int.max, T.zero) + XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) << Int.min, T.zero) + } + + func testBitshiftingZeroDoesNotTrap() { + XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) << Int.min, T.zero) + XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) << Int.max, T.zero) + + XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) >> Int.min, T.zero) + XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) >> Int.max, T.zero) + } + + func testBitshiftingZeroDoesNotDoAnything() { + XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) << (UInt.bitWidth + 0), T.zero) + XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) << (UInt.bitWidth + 1), T.zero) + + XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) >> (UInt.bitWidth + 0), T.zero) + XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) >> (UInt.bitWidth + 1), T.zero) + } +} + +//*============================================================================* +// MARK: * NBK x Resizable Width x Shifts x Assertions +//*============================================================================* + +private func NBKAssertShiftLeft( +_ lhs: T, _ rhs: Int, _ result: T, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + let (words, bits) = rhs.quotientAndRemainder(dividingBy: UInt.bitWidth) + //=------------------------------------------= + XCTAssertEqual( lhs << rhs, result, file: file, line: line) + XCTAssertEqual( lhs >> -rhs, result, file: file, line: line) + + XCTAssertEqual({ var lhs = lhs; lhs <<= rhs; return lhs }(), result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs >>= -rhs; return lhs }(), result, file: file, line: line) + + XCTAssertEqual(lhs.bitshiftedLeftSmart(by: rhs), result, file: file, line: line) + XCTAssertEqual(lhs.bitshiftedRightSmart(by: -rhs), result, file: file, line: line) + + XCTAssertEqual({ var lhs = lhs; lhs.bitshiftLeftSmart(by: rhs); return lhs }(), result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs.bitshiftRightSmart(by: -rhs); return lhs }(), result, file: file, line: line) + //=------------------------------------------= + if 0 ..< lhs.bitWidth ~= rhs { + XCTAssertEqual(lhs.bitshiftedLeft(by: rhs), result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs.bitshiftLeft(by: rhs); return lhs }(), result, file: file, line: line) + + XCTAssertEqual(lhs.bitshiftedLeft(words: words, bits: bits), result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs.bitshiftLeft(words: words, bits: bits); return lhs }(), result, file: file, line: line) + } + //=------------------------------------------= + if 0 ..< lhs.bitWidth ~= rhs, bits.isZero { + XCTAssertEqual(lhs.bitshiftedLeft(words: words), result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs.bitshiftLeft(words: words); return lhs }(), result, file: file, line: line) + } +} + +private func NBKAssertShiftRight( +_ lhs: T, _ rhs: Int, _ result: T, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + let (words, bits) = rhs.quotientAndRemainder(dividingBy: UInt.bitWidth) + //=------------------------------------------= + XCTAssertEqual( lhs >> rhs, result, file: file, line: line) + XCTAssertEqual( lhs << -rhs, result, file: file, line: line) + + XCTAssertEqual({ var lhs = lhs; lhs >>= rhs; return lhs }(), result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs <<= -rhs; return lhs }(), result, file: file, line: line) + + XCTAssertEqual(lhs.bitshiftedRightSmart(by: rhs), result, file: file, line: line) + XCTAssertEqual(lhs.bitshiftedLeftSmart(by: -rhs), result, file: file, line: line) + + XCTAssertEqual({ var lhs = lhs; lhs.bitshiftRightSmart(by: rhs); return lhs }(), result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs.bitshiftLeftSmart(by: -rhs); return lhs }(), result, file: file, line: line) + //=------------------------------------------= + if 0 ..< lhs.bitWidth ~= rhs { + XCTAssertEqual(lhs.bitshiftedRight(by: rhs), result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs.bitshiftRight(by: rhs); return lhs }(), result, file: file, line: line) + + XCTAssertEqual(lhs.bitshiftedRight(words: words, bits: bits), result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs.bitshiftRight(words: words, bits: bits); return lhs }(), result, file: file, line: line) + } + //=------------------------------------------= + if 0 ..< lhs.bitWidth ~= rhs, bits.isZero { + XCTAssertEqual(lhs.bitshiftedRight(words: words), result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs.bitshiftRight(words: words); return lhs }(), result, file: file, line: line) + } +} + +#endif From 5902b73c1d161925954ba1925523251be4f723e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Mon, 7 Aug 2023 19:20:56 +0200 Subject: [PATCH 052/133] Update. --- .../NBKFlexibleWidth+Division.swift | 4 +- .../NBKFlexibleWidth+Miscellaneous.swift | 31 ----------- ...BKFlexibleWidth+Multiplication+Digit.swift | 2 +- .../NBKFlexibleWidth+Protocols.swift | 8 +++ .../NBKFlexibleWidth+Shifts.swift | 8 +-- .../NBKFlexibleWidth+Update.swift | 51 +++++++++++++++++++ .../NBKResizableWidth+Protocols.swift | 10 ++++ .../NBKResizableWidth+Shifts.swift | 8 +-- .../NBKResizableWidth+Size.swift | 5 +- ...s.swift => NBKResizableWidth+Update.swift} | 12 +++-- 10 files changed, 90 insertions(+), 49 deletions(-) delete mode 100644 Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Miscellaneous.swift create mode 100644 Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Update.swift rename Sources/NBKResizableWidthKit/{NBKResizableWidth+Miscellaneous.swift => NBKResizableWidth+Update.swift} (76%) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift index cfa116ac..b0ecb52e 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift @@ -115,7 +115,7 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= if other.storage.count == 1 { let qr = self.quotientAndRemainder(dividingBy: other.storage.first) - self.assign(qr.remainder) + self.update(qr.remainder) return PVO(qr.quotient, false) } //=--------------------------------------= @@ -124,7 +124,7 @@ extension NBKFlexibleWidth.Magnitude { let comparison = other.compared(to: self) if comparison >= 0 { if comparison.isZero { - self.assign(UInt.zero) + self.update(UInt.zero) return PVO(001, false) } else { return PVO(000, false) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Miscellaneous.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Miscellaneous.swift deleted file mode 100644 index 5ec65987..00000000 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Miscellaneous.swift +++ /dev/null @@ -1,31 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit -import NBKResizableWidthKit - -//*============================================================================* -// MARK: * NBK x Flexible Width x Miscellaneous x Unsigned -//*============================================================================* - -extension NBKFlexibleWidth.Magnitude { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable mutating func assignZeroValue() { - self.assign(UInt.zero) - } - - @inlinable mutating func assign(_ value: UInt) { - self.storage.normalize(assign: value) - Swift.assert(self.storage.isNormal) - } -} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift index bb95f37a..fae03528 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift @@ -72,7 +72,7 @@ extension NBKFlexibleWidth.Magnitude { } //=--------------------------------------= if multiplicand.isZero { - return self.assign(addend) + return self.update(addend) } //=--------------------------------------= self.storage.reserveCapacity(self.storage.count + 1) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Protocols.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Protocols.swift index d05f2f2f..5c035dee 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Protocols.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Protocols.swift @@ -108,4 +108,12 @@ public protocol IntXLOrUIntXL: NBKBinaryInteger, LosslessStringConvertible { @inlinable mutating func bitshiftRight(words: Int) @inlinable func bitshiftedRight(words: Int) -> Self + + //=------------------------------------------------------------------------= + // MARK: Details x Update + //=------------------------------------------------------------------------= + + @inlinable mutating func updateZeroValue() + + @inlinable mutating func update(_ value: Digit) } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift index 1bd48593..32a4f0e2 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift @@ -126,7 +126,7 @@ extension NBKFlexibleWidth { self.magnitude.bitshiftRight(words: words, bits: bits) //=--------------------------------------= if minus, self.isZero { - self.magnitude.assign(1 as UInt) + self.magnitude.update(1 as UInt) } } @@ -140,7 +140,7 @@ extension NBKFlexibleWidth { self.magnitude.bitshiftRight(words: words) //=--------------------------------------= if minus, self.isZero { - self.magnitude.assign(1 as UInt) + self.magnitude.update(1 as UInt) } } @@ -354,7 +354,7 @@ extension NBKFlexibleWidth.Magnitude { let maxCount = self.storage.count - words - rollover //=--------------------------------------= if maxCount <= 0 { - return self.assignZeroValue() + return self.updateZeroValue() } //=--------------------------------------= self.storage.withContiguousMutableStorage { @@ -375,7 +375,7 @@ extension NBKFlexibleWidth.Magnitude { } //=--------------------------------------= if self.storage.count <= words { - return self.assignZeroValue() + return self.updateZeroValue() } //=--------------------------------------= self.storage.withContiguousMutableStorage { diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Update.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Update.swift new file mode 100644 index 00000000..f68992f1 --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Update.swift @@ -0,0 +1,51 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit +import NBKResizableWidthKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x Miscellaneous x Signed +//*============================================================================* + +extension NBKFlexibleWidth { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public mutating func updateZeroValue() { + self.sign = Sign.plus + self.magnitude.updateZeroValue() + } + + @inlinable public mutating func update(_ value: Digit) { + self.sign = Sign(value.isLessThanZero) + self.magnitude.update(value.magnitude) + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Miscellaneous x Unsigned +//*============================================================================* + +extension NBKFlexibleWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public mutating func updateZeroValue() { + self.update(UInt.zero) + } + + @inlinable public mutating func update(_ value: Digit) { + self.storage.normalize(update: value) + } +} diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Protocols.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Protocols.swift index ffd8ce0a..87882350 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Protocols.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Protocols.swift @@ -72,6 +72,16 @@ RandomAccessCollection where Element == UInt, Index == Int, Indices == Range Self + //=------------------------------------------------------------------------= + // MARK: Details x Update + //=------------------------------------------------------------------------= + + @inlinable mutating func updateZeroValue() + + @inlinable mutating func update(repeating bit: Bool) + + @inlinable mutating func update(repeating word: UInt) + //=------------------------------------------------------------------------= // MARK: Details x Words //=------------------------------------------------------------------------= diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Shifts.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Shifts.swift index 24aa628e..e439dd9c 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Shifts.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Shifts.swift @@ -43,9 +43,9 @@ extension NBKResizableWidth.Magnitude { let size = distance.magnitude as UInt switch (distance >= 0, size < UInt(bitPattern: self.bitWidth)) { case (true, true ): self.bitshiftLeft (by: Int(bitPattern: size)) - case (true, false): self.assign(repeating: false) + case (true, false): self.update(repeating: false) case (false, true ): self.bitshiftRight(by: Int(bitPattern: size)) - case (false, false): self.assign(repeating: self.isLessThanZero) } + case (false, false): self.update(repeating: self.isLessThanZero) } } /// Performs a smart left shift. @@ -183,9 +183,9 @@ extension NBKResizableWidth.Magnitude { let size = distance.magnitude as UInt switch (distance >= 0, size < UInt(bitPattern: self.bitWidth)) { case (true, true ): self.bitshiftRight(by: Int(bitPattern: size)) - case (true, false): self.assign(repeating: self.isLessThanZero) + case (true, false): self.update(repeating: self.isLessThanZero) case (false, true ): self.bitshiftLeft (by: Int(bitPattern: size)) - case (false, false): self.assign(repeating: false) } + case (false, false): self.update(repeating: false) } } /// Performs an un/signed, smart, right shift. diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Size.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Size.swift index 8bac6c49..8354dcc0 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Size.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Size.swift @@ -57,8 +57,7 @@ extension NBKResizableWidth.Magnitude { } } - @inlinable public mutating func normalize(assign value: UInt) { - self.storage.removeAll(keepingCapacity: true) - self.storage.append(value) + @inlinable public mutating func normalize(update value: UInt) { + self.storage.replaceSubrange(self.storage.indices, with: CollectionOfOne(value)) } } diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Miscellaneous.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Update.swift similarity index 76% rename from Sources/NBKResizableWidthKit/NBKResizableWidth+Miscellaneous.swift rename to Sources/NBKResizableWidthKit/NBKResizableWidth+Update.swift index 15cb0978..4d8f869e 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Miscellaneous.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Update.swift @@ -19,11 +19,15 @@ extension NBKResizableWidth.Magnitude { // MARK: Transformations //=------------------------------------------------------------------------= - @inlinable public mutating func assignZeroValue() { - self.assign(repeating: false) + @inlinable public mutating func updateZeroValue() { + self.update(repeating: false) } - @inlinable public mutating func assign(repeating bit: Bool) { - self.withContiguousMutableStorage({ $0.update(repeating: UInt(repeating: bit)) }) + @inlinable public mutating func update(repeating bit: Bool) { + self.update(repeating: UInt(repeating: bit)) + } + + @inlinable public mutating func update(repeating word: UInt) { + self.withContiguousMutableStorage({ $0.update(repeating: word) }) } } From 76902f19bc5f9741dad90d061fe2c81915c4f64e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Wed, 9 Aug 2023 12:00:40 +0200 Subject: [PATCH 053/133] NBKResizableWidthKit: Addition. --- .../NBKFlexibleWidth+Words.swift | 8 +- .../NBKResizableWidth+Addition+Digit.swift | 36 +--- .../NBKResizableWidth+Addition+Void.swift | 31 --- .../NBKResizableWidth+Addition.swift | 28 +-- .../Private/NBK+Addition.swift | 190 ++++++++++++++++++ .../NBKResizableWidthKit/Private/NBK.swift | 20 ++ 6 files changed, 218 insertions(+), 95 deletions(-) delete mode 100644 Sources/NBKResizableWidthKit/NBKResizableWidth+Addition+Void.swift create mode 100644 Sources/NBKResizableWidthKit/Private/NBK+Addition.swift create mode 100644 Sources/NBKResizableWidthKit/Private/NBK.swift diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift index b680839b..f5d15ca4 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift @@ -51,8 +51,8 @@ extension NBKFlexibleWidth { @inlinable var storageNeedsOneMoreWord: Bool { switch self.isLessThanZero { - case false: return self.magnitude.storage.last.mostSignificantBit - case true: return !NBK.mostSignificantBit(twosComplementOf: self.magnitude.storage)! } + case true: return !NBK.mostSignificantBit(twosComplementOf: self.magnitude.storage)! + case false: return self.magnitude.storage.last.mostSignificantBit } } //*========================================================================* @@ -74,8 +74,8 @@ extension NBKFlexibleWidth { //=--------------------------------------------------------------------= @inlinable init(source: NBKFlexibleWidth) { - self.count = Int(bit: source.storageNeedsOneMoreWord) - self.sign = UInt(repeating: source.isLessThanZero) + self.count = Int(bit: source.storageNeedsOneMoreWord) + self.sign = UInt(repeating: source.isLessThanZero) self.storage = source.magnitude.storage //=----------------------------------= if !self.sign.isZero { diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition+Digit.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition+Digit.swift index a2905f6b..a46acee6 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition+Digit.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition+Digit.swift @@ -31,39 +31,7 @@ extension NBKResizableWidth.Magnitude { // MARK: Transformations //=------------------------------------------------------------------------= - @_disfavoredOverload @inlinable public mutating func add(_ other: UInt, plus addend: Bool, at index: Int) -> Bool { - var index = index, overflow = addend - self.add(other, at: &index, carrying: &overflow) - return overflow as Bool - } -} - -//=----------------------------------------------------------------------------= -// MARK: + Algorithms -//=----------------------------------------------------------------------------= - -extension NBKResizableWidth.Magnitude { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable mutating func add(_ other: UInt, at index: inout Int, carrying overflow: inout Bool) { - self.addWithoutGoingBeyond(other, at: &index, carrying: &overflow) - self.add((), at: &index, carrying: &overflow) - } - - @inlinable mutating func addWithoutGoingBeyond(_ other: UInt, at index: inout Int, carrying overflow: inout Bool) { - var other = other as UInt - - if overflow { - overflow = other.addReportingOverflow(1 as UInt) - } - - if !overflow { - overflow = self.storage[index].addReportingOverflow(other) - } - - self.storage.formIndex(after: &index) + @_disfavoredOverload @inlinable public mutating func add(_ other: UInt, plus carry: Bool, at index: Int) -> Bool { + NBK.incrementAsUnsigned(&self, by: other, plus: carry, at: index).overflow } } diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition+Void.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition+Void.swift deleted file mode 100644 index c03b731c..00000000 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition+Void.swift +++ /dev/null @@ -1,31 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Resizable Width x Addition x Unsigned x Void -//*============================================================================* -//=----------------------------------------------------------------------------= -// MARK: + Algorithms -//=----------------------------------------------------------------------------= - -extension NBKResizableWidth.Magnitude { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable mutating func add(_ other: Void, at index: inout Int, carrying overflow: inout Bool) { - while overflow && index < self.storage.endIndex { - overflow = self.storage[index].addReportingOverflow(1 as UInt) - self.storage.formIndex(after: &index) - } - } -} diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition.swift index ba02b0c2..240cb122 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition.swift @@ -31,31 +31,7 @@ extension NBKResizableWidth.Magnitude { // MARK: Transformations //=------------------------------------------------------------------------= - @inlinable public mutating func add(_ other: Self, plus addend: Bool, at index: Int) -> Bool { - var index = index, overflow = addend - self.add(other, at: &index, carrying: &overflow) - return overflow as Bool - } -} - -//=----------------------------------------------------------------------------= -// MARK: + Algorithms -//=----------------------------------------------------------------------------= - -extension NBKResizableWidth.Magnitude { - - //=------------------------------------------------------------------------= - // MARK: Transformations x Self - //=------------------------------------------------------------------------= - - @inlinable mutating func add(_ other: Self, at index: inout Int, carrying overflow: inout Bool) { - self.addWithoutGoingBeyond(other, at: &index, carrying: &overflow) - self.add((), at: &index, carrying: &overflow) - } - - @inlinable mutating func addWithoutGoingBeyond(_ other: Self, at index: inout Int, carrying overflow: inout Bool) { - for otherIndex in other.storage.indices { // for-index-in >= for-element-in - self.addWithoutGoingBeyond(other.storage[otherIndex], at: &index, carrying: &overflow) - } + @inlinable public mutating func add(_ other: Self, plus carry: Bool, at index: Int) -> Bool { + NBK.incrementAsUnsigned(&self, by: other, plus: carry, at: index).overflow } } diff --git a/Sources/NBKResizableWidthKit/Private/NBK+Addition.swift b/Sources/NBKResizableWidthKit/Private/NBK+Addition.swift new file mode 100644 index 00000000..e0e3e617 --- /dev/null +++ b/Sources/NBKResizableWidthKit/Private/NBK+Addition.swift @@ -0,0 +1,190 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Addition +//*============================================================================* + +extension NBK { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @_transparent public static func incrementAsUnsigned( + _ limbs: inout T, by addend: T, plus overflow: Bool, at index: T.Index) -> IO + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + var index: T.Index = index, overflow: Bool = overflow + NBK.incrementAsUnsigned(&limbs, by: addend, at: &index, carrying: &overflow) + return IO(index: index as T.Index, overflow: overflow as Bool) + } + + @_transparent public static func incrementWithoutGoingBeyondAsUnsigned( + _ limbs: inout T, by addend: T, plus overflow: Bool, at index: T.Index) -> IO + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + var index: T.Index = index, overflow: Bool = overflow + NBK.incrementAsUnsigned(&limbs, by: addend, at: &index, carrying: &overflow) + return IO(index: index as T.Index, overflow: overflow as Bool) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Inout + //=------------------------------------------------------------------------= + + @inlinable public static func incrementAsUnsigned( + _ limbs: inout T, by addend: T, at index: inout T.Index, carrying overflow: inout Bool) + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + NBK.incrementWithoutGoingBeyondAsUnsigned(&limbs, by: addend, at: &index, carrying: &overflow) + NBK.incrementAsUnsigned(&limbs, by: Void(), at: &index, carrying: &overflow) + } + + @inlinable public static func incrementWithoutGoingBeyondAsUnsigned( + _ limbs: inout T, by addend: T, at index: inout T.Index, carrying overflow: inout Bool) + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + for addendIndex in addend.indices { // for-index-in >= for-element-in + NBK.incrementWithoutGoingBeyondAsUnsigned(&limbs, by: addend[addendIndex], at: &index, carrying: &overflow) + } + } +} + +//*============================================================================* +// MARK: * NBK x Addition x Digit +//*============================================================================* + +extension NBK { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @_transparent public static func incrementAsUnsigned( + _ limbs: inout T, by addend: T.Element, at index: T.Index) -> IO + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + let (index, overflow) = NBK.incrementWithoutGoingBeyondAsUnsigned(&limbs, by: addend, at: index) + return NBK.incrementAsUnsigned(&limbs, by: overflow, at: index) as IO + } + + @_transparent public static func incrementWithoutGoingBeyondAsUnsigned( + _ limbs: inout T, by addend: T.Element, at index: T.Index) -> IO + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + let overflow = limbs[index].addReportingOverflow(addend) + return IO(limbs.index(after: index), overflow) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Inout + //=------------------------------------------------------------------------= + + @inlinable public static func incrementAsUnsigned( + _ limbs: inout T, by addend: T.Element, at index: inout T.Index) -> Bool + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + var overflow = NBK.incrementWithoutGoingBeyondAsUnsigned(&limbs, by: addend, at: &index) + NBK.incrementAsUnsigned(&limbs, by: Void(), at: &index, carrying: &overflow) + return overflow as Bool + } + + @inlinable public static func incrementWithoutGoingBeyondAsUnsigned( + _ limbs: inout T, by addend: T.Element, at index: inout T.Index) -> Bool + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + //=--------------------------------------= + defer { + limbs.formIndex(after: &index) + } + //=--------------------------------------= + return limbs[index].addReportingOverflow(addend) + } +} + +//*============================================================================* +// MARK: * NBK x Addition x Digit x Carry +//*============================================================================* + +extension NBK { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @_transparent public static func incrementAsUnsigned( + _ limbs: inout T, by addend: T.Element, plus overflow: Bool, at index: T.Index) -> IO + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + var index: T.Index = index, overflow: Bool = overflow + NBK.incrementAsUnsigned(&limbs, by: addend, at: &index, carrying: &overflow) + return IO(index: index as T.Index, overflow: overflow as Bool) + } + + @_transparent public static func incrementWithoutGoingBeyondAsUnsigned( + _ limbs: inout T, by addend: T.Element, plus overflow: Bool, at index: T.Index) -> IO + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + var index: T.Index = index, overflow: Bool = overflow + NBK.incrementWithoutGoingBeyondAsUnsigned(&limbs, by: addend, at: &index, carrying: &overflow) + return IO(index: index as T.Index, overflow: overflow as Bool) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Inout + //=------------------------------------------------------------------------= + + @inlinable public static func incrementAsUnsigned( + _ limbs: inout T, by addend: T.Element, at index: inout T.Index, carrying overflow: inout Bool) + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + NBK.incrementWithoutGoingBeyondAsUnsigned(&limbs, by: addend, at: &index, carrying: &overflow) + NBK.incrementAsUnsigned(&limbs, by: Void(), at: &index, carrying: &overflow) + } + + @inlinable public static func incrementWithoutGoingBeyondAsUnsigned( + _ limbs: inout T, by addend: T.Element, at index: inout T.Index, carrying overflow: inout Bool) + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + var addend: T.Element = addend + + if overflow { + overflow = addend.addReportingOverflow(1 as T.Element.Digit) + } + + if !overflow { + overflow = limbs[index].addReportingOverflow(addend) + } + + limbs.formIndex(after: &index) + } +} + +//*============================================================================* +// MARK: * NBK x Addition x Bool +//*============================================================================* + +extension NBK { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @_transparent public static func incrementAsUnsigned( + _ limbs: inout T, by addend: Bool, at index: T.Index) -> IO + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + var index: T.Index = index, overflow: Bool = addend + NBK.incrementAsUnsigned(&limbs, by: Void(), at: &index, carrying: &overflow) + return IO(index: index as T.Index, overflow: overflow as Bool) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Inout + //=------------------------------------------------------------------------= + + @inlinable public static func incrementAsUnsigned( + _ limbs: inout T, by addend: Void, at index: inout T.Index, carrying overflow: inout Bool) + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + while overflow && index < limbs.endIndex { + overflow = limbs[index].addReportingOverflow(1 as T.Element.Digit) + limbs.formIndex(after: &index) + } + } +} diff --git a/Sources/NBKResizableWidthKit/Private/NBK.swift b/Sources/NBKResizableWidthKit/Private/NBK.swift new file mode 100644 index 00000000..52034f6a --- /dev/null +++ b/Sources/NBKResizableWidthKit/Private/NBK.swift @@ -0,0 +1,20 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK +//*============================================================================* + +extension NBK { + + /// An index and an overflow indicator. + public typealias IO = (index: I, overflow: Bool) +} From 4979953c35ec2f961e7f5ea4778dc3d0d8dae3ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Wed, 9 Aug 2023 14:42:06 +0200 Subject: [PATCH 054/133] NBKResizableWidthKit: Subtraction. --- .../NBKResizableWidth+Subtraction+Digit.swift | 36 +--- .../NBKResizableWidth+Subtraction+Void.swift | 31 --- .../NBKResizableWidth+Subtraction.swift | 31 +-- .../Private/NBK+Addition.swift | 30 ++- .../Private/NBK+Subtraction.swift | 186 ++++++++++++++++++ 5 files changed, 205 insertions(+), 109 deletions(-) delete mode 100644 Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction+Void.swift create mode 100644 Sources/NBKResizableWidthKit/Private/NBK+Subtraction.swift diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction+Digit.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction+Digit.swift index 4bf314da..6533447c 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction+Digit.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction+Digit.swift @@ -39,39 +39,7 @@ extension NBKResizableWidth.Magnitude { fatalError("TODO") } - @_disfavoredOverload @inlinable public mutating func subtract(_ other: UInt, plus addend: Bool, at index: Int) -> Bool { - var index = index, overflow = addend - self.subtract(other, at: &index, borrowing: &overflow) - return overflow as Bool - } -} - -//=----------------------------------------------------------------------------= -// MARK: + Algorithms -//=----------------------------------------------------------------------------= - -extension NBKResizableWidth.Magnitude { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable mutating func subtract(_ other: UInt, at index: inout Int, borrowing overflow: inout Bool) { - self.subtractWithoutGoingBeyond(other, at: &index, borrowing: &overflow) - self.subtract((), at: &index, borrowing: &overflow) - } - - @inlinable mutating func subtractWithoutGoingBeyond(_ other: UInt, at index: inout Int, borrowing overflow: inout Bool) { - var other = other as UInt - - if overflow { - overflow = other.addReportingOverflow(1 as UInt) - } - - if !overflow { - overflow = self.storage[index].subtractReportingOverflow(other) - } - - self.storage.formIndex(after: &index) + @_disfavoredOverload @inlinable public mutating func subtract(_ other: UInt, plus subtrahend: Bool, at index: Int) -> Bool { + NBK.decrementAsUnsigned(&self, by: other, plus: subtrahend, at: index).overflow } } diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction+Void.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction+Void.swift deleted file mode 100644 index 875d2966..00000000 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction+Void.swift +++ /dev/null @@ -1,31 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Resizable Width x Subtraction x Unsigned -//*============================================================================* -//=----------------------------------------------------------------------------= -// MARK: + Algorithms -//=----------------------------------------------------------------------------= - -extension NBKResizableWidth.Magnitude { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable mutating func subtract(_ other: Void, at index: inout Int, borrowing overflow: inout Bool) { - while overflow && index < self.storage.endIndex { - overflow = self.storage[index].subtractReportingOverflow(1 as UInt) - self.storage.formIndex(after: &index) - } - } -} diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction.swift index 10631599..07410f6b 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction.swift @@ -39,12 +39,11 @@ extension NBKResizableWidth.Magnitude { fatalError("TODO") } - @inlinable public mutating func subtract(_ other: Self, plus addend: Bool, at index: Int) -> Bool { - var index = index, overflow = addend - self.subtract(other, at: &index, borrowing: &overflow) - return overflow as Bool + @inlinable public mutating func subtract(_ other: Self, plus subtrahend: Bool, at index: Int) -> Bool { + NBK.decrementAsUnsigned(&self, by: other, plus: subtrahend, at: index).overflow } + // TODO: NBK algorithm //=------------------------------------------------------------------------= // MARK: Transformations x Product //=------------------------------------------------------------------------= @@ -57,31 +56,9 @@ extension NBKResizableWidth.Magnitude { for otherIndex in other.storage.indices { var subproduct = other.storage[otherIndex].multipliedFullWidth(by: multiplicand) last = UInt(bit: subproduct.low.addReportingOverflow(last)) &+ subproduct.high - self.subtractWithoutGoingBeyond(subproduct.low, at: &index, borrowing: &overflow) + NBK.decrementAsUnsignedInIntersection(&self, by: subproduct.low, at: &index, borrowing: &overflow) } return self.subtract(last, plus: overflow, at: index) } } - -//=----------------------------------------------------------------------------= -// MARK: + Algorithms -//=----------------------------------------------------------------------------= - -extension NBKResizableWidth.Magnitude { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable mutating func subtract(_ other: Self, at index: inout Int, borrowing overflow: inout Bool) { - self.subtractWithoutGoingBeyond(other, at: &index, borrowing: &overflow) - self.subtract((), at: &index, borrowing: &overflow) - } - - @inlinable mutating func subtractWithoutGoingBeyond(_ other: Self, at index: inout Int, borrowing overflow: inout Bool) { - for otherIndex in other.storage.indices { // for-index-in >= for-element-in - self.subtractWithoutGoingBeyond(other.storage[otherIndex], at: &index, borrowing: &overflow) - } - } -} diff --git a/Sources/NBKResizableWidthKit/Private/NBK+Addition.swift b/Sources/NBKResizableWidthKit/Private/NBK+Addition.swift index e0e3e617..7637b56c 100644 --- a/Sources/NBKResizableWidthKit/Private/NBK+Addition.swift +++ b/Sources/NBKResizableWidthKit/Private/NBK+Addition.swift @@ -27,7 +27,7 @@ extension NBK { return IO(index: index as T.Index, overflow: overflow as Bool) } - @_transparent public static func incrementWithoutGoingBeyondAsUnsigned( + @_transparent public static func incrementAsUnsignedInIntersection( _ limbs: inout T, by addend: T, plus overflow: Bool, at index: T.Index) -> IO where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { var index: T.Index = index, overflow: Bool = overflow @@ -42,15 +42,15 @@ extension NBK { @inlinable public static func incrementAsUnsigned( _ limbs: inout T, by addend: T, at index: inout T.Index, carrying overflow: inout Bool) where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - NBK.incrementWithoutGoingBeyondAsUnsigned(&limbs, by: addend, at: &index, carrying: &overflow) + NBK.incrementAsUnsignedInIntersection(&limbs, by: addend, at: &index, carrying: &overflow) NBK.incrementAsUnsigned(&limbs, by: Void(), at: &index, carrying: &overflow) } - @inlinable public static func incrementWithoutGoingBeyondAsUnsigned( + @inlinable public static func incrementAsUnsignedInIntersection( _ limbs: inout T, by addend: T, at index: inout T.Index, carrying overflow: inout Bool) where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { for addendIndex in addend.indices { // for-index-in >= for-element-in - NBK.incrementWithoutGoingBeyondAsUnsigned(&limbs, by: addend[addendIndex], at: &index, carrying: &overflow) + NBK.incrementAsUnsignedInIntersection(&limbs, by: addend[addendIndex], at: &index, carrying: &overflow) } } } @@ -68,11 +68,11 @@ extension NBK { @_transparent public static func incrementAsUnsigned( _ limbs: inout T, by addend: T.Element, at index: T.Index) -> IO where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - let (index, overflow) = NBK.incrementWithoutGoingBeyondAsUnsigned(&limbs, by: addend, at: index) + let (index, overflow) = NBK.incrementAsUnsignedInIntersection(&limbs, by: addend, at: index) return NBK.incrementAsUnsigned(&limbs, by: overflow, at: index) as IO } - @_transparent public static func incrementWithoutGoingBeyondAsUnsigned( + @_transparent public static func incrementAsUnsignedInIntersection( _ limbs: inout T, by addend: T.Element, at index: T.Index) -> IO where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { let overflow = limbs[index].addReportingOverflow(addend) @@ -86,19 +86,15 @@ extension NBK { @inlinable public static func incrementAsUnsigned( _ limbs: inout T, by addend: T.Element, at index: inout T.Index) -> Bool where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - var overflow = NBK.incrementWithoutGoingBeyondAsUnsigned(&limbs, by: addend, at: &index) + var overflow = NBK.incrementAsUnsignedInIntersection(&limbs, by: addend, at: &index) NBK.incrementAsUnsigned(&limbs, by: Void(), at: &index, carrying: &overflow) return overflow as Bool } - @inlinable public static func incrementWithoutGoingBeyondAsUnsigned( + @inlinable public static func incrementAsUnsignedInIntersection( _ limbs: inout T, by addend: T.Element, at index: inout T.Index) -> Bool where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - //=--------------------------------------= - defer { - limbs.formIndex(after: &index) - } - //=--------------------------------------= + defer{ limbs.formIndex(after: &index) } return limbs[index].addReportingOverflow(addend) } } @@ -121,11 +117,11 @@ extension NBK { return IO(index: index as T.Index, overflow: overflow as Bool) } - @_transparent public static func incrementWithoutGoingBeyondAsUnsigned( + @_transparent public static func incrementAsUnsignedInIntersection( _ limbs: inout T, by addend: T.Element, plus overflow: Bool, at index: T.Index) -> IO where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { var index: T.Index = index, overflow: Bool = overflow - NBK.incrementWithoutGoingBeyondAsUnsigned(&limbs, by: addend, at: &index, carrying: &overflow) + NBK.incrementAsUnsignedInIntersection(&limbs, by: addend, at: &index, carrying: &overflow) return IO(index: index as T.Index, overflow: overflow as Bool) } @@ -136,11 +132,11 @@ extension NBK { @inlinable public static func incrementAsUnsigned( _ limbs: inout T, by addend: T.Element, at index: inout T.Index, carrying overflow: inout Bool) where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - NBK.incrementWithoutGoingBeyondAsUnsigned(&limbs, by: addend, at: &index, carrying: &overflow) + NBK.incrementAsUnsignedInIntersection(&limbs, by: addend, at: &index, carrying: &overflow) NBK.incrementAsUnsigned(&limbs, by: Void(), at: &index, carrying: &overflow) } - @inlinable public static func incrementWithoutGoingBeyondAsUnsigned( + @inlinable public static func incrementAsUnsignedInIntersection( _ limbs: inout T, by addend: T.Element, at index: inout T.Index, carrying overflow: inout Bool) where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { var addend: T.Element = addend diff --git a/Sources/NBKResizableWidthKit/Private/NBK+Subtraction.swift b/Sources/NBKResizableWidthKit/Private/NBK+Subtraction.swift new file mode 100644 index 00000000..418f6b0a --- /dev/null +++ b/Sources/NBKResizableWidthKit/Private/NBK+Subtraction.swift @@ -0,0 +1,186 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Subtraction +//*============================================================================* + +extension NBK { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @_transparent public static func decrementAsUnsigned( + _ limbs: inout T, by subtrahend: T, plus overflow: Bool, at index: T.Index) -> IO + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + var index: T.Index = index, overflow: Bool = overflow + NBK.decrementAsUnsigned(&limbs, by: subtrahend, at: &index, borrowing: &overflow) + return IO(index: index as T.Index, overflow: overflow as Bool) + } + + @_transparent public static func decrementAsUnsignedInIntersection( + _ limbs: inout T, by subtrahend: T, plus overflow: Bool, at index: T.Index) -> IO + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + var index: T.Index = index, overflow: Bool = overflow + NBK.decrementAsUnsigned(&limbs, by: subtrahend, at: &index, borrowing: &overflow) + return IO(index: index as T.Index, overflow: overflow as Bool) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Inout + //=------------------------------------------------------------------------= + + @inlinable public static func decrementAsUnsigned( + _ limbs: inout T, by subtrahend: T, at index: inout T.Index, borrowing overflow: inout Bool) + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + NBK.decrementAsUnsignedInIntersection(&limbs, by: subtrahend, at: &index, borrowing: &overflow) + NBK.decrementAsUnsigned(&limbs, by: Void(), at: &index, borrowing: &overflow) + } + + @inlinable public static func decrementAsUnsignedInIntersection( + _ limbs: inout T, by subtrahend: T, at index: inout T.Index, borrowing overflow: inout Bool) + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + for subtrahendIndex in subtrahend.indices { // for-index-in >= for-element-in + NBK.decrementAsUnsignedInIntersection(&limbs, by: subtrahend[subtrahendIndex], at: &index, borrowing: &overflow) + } + } +} + +//*============================================================================* +// MARK: * NBK x Subtraction x Digit +//*============================================================================* + +extension NBK { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @_transparent public static func decrementAsUnsigned( + _ limbs: inout T, by subtrahend: T.Element, at index: T.Index) -> IO + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + let (index, overflow) = NBK.decrementAsUnsignedInIntersection(&limbs, by: subtrahend, at: index) + return NBK.decrementAsUnsigned(&limbs, by: overflow, at: index) as IO + } + + @_transparent public static func decrementAsUnsignedInIntersection( + _ limbs: inout T, by subtrahend: T.Element, at index: T.Index) -> IO + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + let overflow = limbs[index].addReportingOverflow(subtrahend) + return IO(limbs.index(after: index), overflow) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Inout + //=------------------------------------------------------------------------= + + @inlinable public static func decrementAsUnsigned( + _ limbs: inout T, by subtrahend: T.Element, at index: inout T.Index) -> Bool + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + var overflow = NBK.decrementAsUnsignedInIntersection(&limbs, by: subtrahend, at: &index) + NBK.decrementAsUnsigned(&limbs, by: Void(), at: &index, borrowing: &overflow) + return overflow as Bool + } + + @inlinable public static func decrementAsUnsignedInIntersection( + _ limbs: inout T, by subtrahend: T.Element, at index: inout T.Index) -> Bool + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + defer{ limbs.formIndex(after: &index) } + return limbs[index].addReportingOverflow(subtrahend) + } +} + +//*============================================================================* +// MARK: * NBK x Subtraction x Digit x Carry +//*============================================================================* + +extension NBK { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @_transparent public static func decrementAsUnsigned( + _ limbs: inout T, by subtrahend: T.Element, plus overflow: Bool, at index: T.Index) -> IO + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + var index: T.Index = index, overflow: Bool = overflow + NBK.decrementAsUnsigned(&limbs, by: subtrahend, at: &index, borrowing: &overflow) + return IO(index: index as T.Index, overflow: overflow as Bool) + } + + @_transparent public static func decrementAsUnsignedInIntersection( + _ limbs: inout T, by subtrahend: T.Element, plus overflow: Bool, at index: T.Index) -> IO + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + var index: T.Index = index, overflow: Bool = overflow + NBK.decrementAsUnsignedInIntersection(&limbs, by: subtrahend, at: &index, borrowing: &overflow) + return IO(index: index as T.Index, overflow: overflow as Bool) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Inout + //=------------------------------------------------------------------------= + + @inlinable public static func decrementAsUnsigned( + _ limbs: inout T, by subtrahend: T.Element, at index: inout T.Index, borrowing overflow: inout Bool) + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + NBK.decrementAsUnsignedInIntersection(&limbs, by: subtrahend, at: &index, borrowing: &overflow) + NBK.decrementAsUnsigned(&limbs, by: Void(), at: &index, borrowing: &overflow) + } + + @inlinable public static func decrementAsUnsignedInIntersection( + _ limbs: inout T, by subtrahend: T.Element, at index: inout T.Index, borrowing overflow: inout Bool) + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + var subtrahend: T.Element = subtrahend + + if overflow { + overflow = subtrahend.addReportingOverflow(1 as T.Element.Digit) + } + + if !overflow { + overflow = limbs[index].subtractReportingOverflow(subtrahend) + } + + limbs.formIndex(after: &index) + } +} + +//*============================================================================* +// MARK: * NBK x Subtraction x Bool +//*============================================================================* + +extension NBK { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @_transparent public static func decrementAsUnsigned( + _ limbs: inout T, by subtrahend: Bool, at index: T.Index) -> IO + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + var index: T.Index = index, overflow: Bool = subtrahend + NBK.decrementAsUnsigned(&limbs, by: Void(), at: &index, borrowing: &overflow) + return IO(index: index as T.Index, overflow: overflow as Bool) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Inout + //=------------------------------------------------------------------------= + + @inlinable public static func decrementAsUnsigned( + _ limbs: inout T, by subtrahend: Void, at index: inout T.Index, borrowing overflow: inout Bool) + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + while overflow && index < limbs.endIndex { + overflow = limbs[index].subtractReportingOverflow(1 as T.Element.Digit) + limbs.formIndex(after: &index) + } + } +} From 38f0aaa840bac7143a2ff5d09196e4758f1cf13d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Wed, 9 Aug 2023 15:25:31 +0200 Subject: [PATCH 055/133] NBKResizableWidthKit: Subtraction. --- .../NBKResizableWidth+Addition+Digit.swift | 1 + .../NBKResizableWidth+Addition.swift | 1 + .../NBKResizableWidth+Subtraction+Digit.swift | 5 +++ .../NBKResizableWidth+Subtraction.swift | 25 ++++-------- .../Private/NBK+Subtraction.swift | 39 +++++++++++++++++++ 5 files changed, 54 insertions(+), 17 deletions(-) diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition+Digit.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition+Digit.swift index a46acee6..9901cf98 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition+Digit.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition+Digit.swift @@ -31,6 +31,7 @@ extension NBKResizableWidth.Magnitude { // MARK: Transformations //=------------------------------------------------------------------------= + // TODO: rename @_disfavoredOverload @inlinable public mutating func add(_ other: UInt, plus carry: Bool, at index: Int) -> Bool { NBK.incrementAsUnsigned(&self, by: other, plus: carry, at: index).overflow } diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition.swift index 240cb122..8e5e9396 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition.swift @@ -31,6 +31,7 @@ extension NBKResizableWidth.Magnitude { // MARK: Transformations //=------------------------------------------------------------------------= + // TODO: rename @inlinable public mutating func add(_ other: Self, plus carry: Bool, at index: Int) -> Bool { NBK.incrementAsUnsigned(&self, by: other, plus: carry, at: index).overflow } diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction+Digit.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction+Digit.swift index 6533447c..cf7bb8bf 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction+Digit.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction+Digit.swift @@ -39,6 +39,11 @@ extension NBKResizableWidth.Magnitude { fatalError("TODO") } + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + // TODO: rename @_disfavoredOverload @inlinable public mutating func subtract(_ other: UInt, plus subtrahend: Bool, at index: Int) -> Bool { NBK.decrementAsUnsigned(&self, by: other, plus: subtrahend, at: index).overflow } diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction.swift index 07410f6b..ea9774cf 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction.swift @@ -39,26 +39,17 @@ extension NBKResizableWidth.Magnitude { fatalError("TODO") } + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + // TODO: rename @inlinable public mutating func subtract(_ other: Self, plus subtrahend: Bool, at index: Int) -> Bool { NBK.decrementAsUnsigned(&self, by: other, plus: subtrahend, at: index).overflow } - // TODO: NBK algorithm - //=------------------------------------------------------------------------= - // MARK: Transformations x Product - //=------------------------------------------------------------------------= - - @inlinable public mutating func subtract(_ other: Self, times multiplicand: UInt, plus addend: UInt, at index: Int) -> Bool { - var index = index - var overflow = false - var last = addend as UInt - - for otherIndex in other.storage.indices { - var subproduct = other.storage[otherIndex].multipliedFullWidth(by: multiplicand) - last = UInt(bit: subproduct.low.addReportingOverflow(last)) &+ subproduct.high - NBK.decrementAsUnsignedInIntersection(&self, by: subproduct.low, at: &index, borrowing: &overflow) - } - - return self.subtract(last, plus: overflow, at: index) + // TODO: rename + @inlinable public mutating func subtract(_ other: Self, times multiplicand: UInt, plus subtrahend: UInt, at index: Int) -> Bool { + NBK.decrementAsUnsigned(&self, by: other, times: multiplicand, plus: subtrahend, and: false, at: index).overflow } } diff --git a/Sources/NBKResizableWidthKit/Private/NBK+Subtraction.swift b/Sources/NBKResizableWidthKit/Private/NBK+Subtraction.swift index 418f6b0a..76fc6fbb 100644 --- a/Sources/NBKResizableWidthKit/Private/NBK+Subtraction.swift +++ b/Sources/NBKResizableWidthKit/Private/NBK+Subtraction.swift @@ -184,3 +184,42 @@ extension NBK { } } } + +//*============================================================================* +// MARK: * NBK x Subtraction x Product +//*============================================================================* + +extension NBK { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @_transparent public static func decrementAsUnsigned( + _ limbs: inout T, by other: T, times multiplicand: T.Element, plus subtrahend: T.Element, + and overflow: Bool, at index: T.Index) -> IO + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + var index: T.Index = index, overflow: Bool = overflow + NBK.decrementAsUnsigned(&limbs, by: other, times: multiplicand, plus: subtrahend, at: &index, borrowing: &overflow) + return IO(index: index as T.Index, overflow: overflow as Bool) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Inout + //=------------------------------------------------------------------------= + + @inlinable public static func decrementAsUnsigned( + _ limbs: inout T, by other: T, times multiplicand: T.Element, plus subtrahend: T.Element, + at index: inout T.Index, borrowing overflow: inout Bool) + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + var last: T.Element = subtrahend + + for otherIndex in other.indices { + var subproduct = other[otherIndex].multipliedFullWidth(by: multiplicand) + last = T.Element(bit: subproduct.low.addReportingOverflow(last)) &+ subproduct.high + NBK.decrementAsUnsignedInIntersection(&limbs, by: subproduct.low, at: &index, borrowing: &overflow) + } + + NBK.decrementAsUnsigned(&limbs, by: last, at: &index, borrowing: &overflow) + } +} From c65165e9d5cfea8dc0652ae098073256a5d475d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Wed, 9 Aug 2023 16:52:34 +0200 Subject: [PATCH 056/133] NBKResizableWidthKit: Division. --- .../NBKFlexibleWidth+Division+Digit.swift | 20 ++-------- .../NBKResizableWidth+Division+Digit.swift | 4 +- .../NBKResizableWidth+Uninitialized.swift | 10 +---- .../Private/NBK+Division.swift | 38 +++++++++++++++++++ 4 files changed, 45 insertions(+), 27 deletions(-) create mode 100644 Sources/NBKResizableWidthKit/Private/NBK+Division.swift diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.swift index 38a6c845..e1e5d857 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.swift @@ -93,22 +93,8 @@ extension NBKFlexibleWidth.Magnitude { // MARK: Transformations x Private //=------------------------------------------------------------------------= - @_disfavoredOverload @inlinable mutating func formQuotientWithRemainderReportingOverflow(dividingBy other: Digit) -> PVO { - defer { - Swift.assert(self.storage.isNormal) - } - //=--------------------------------------= - if other.isZero { - return NBK.bitCast(PVO(self.storage.first, true)) - } - //=--------------------------------------= - var remainder = UInt.zero - - for index in self.storage.indices.reversed() { - (self.storage[index], remainder) = other.dividingFullWidth(HL(remainder, self.storage[index])) - } - - self.storage.normalize() - return PVO(remainder, false) + @_disfavoredOverload @inlinable public mutating func formQuotientWithRemainderReportingOverflow(dividingBy other: Digit) -> PVO { + defer{ self.storage.normalize() } + return self.storage.formQuotientWithRemainderReportingOverflow(dividingBy: other) } } diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Division+Digit.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Division+Digit.swift index a13eb4eb..d0db3680 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Division+Digit.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Division+Digit.swift @@ -51,7 +51,7 @@ extension NBKResizableWidth.Magnitude { // MARK: Transformations x Private //=------------------------------------------------------------------------= - @_disfavoredOverload @inlinable mutating func formQuotientWithRemainderReportingOverflow(dividingBy other: Digit) -> PVO { - fatalError("TODO") + @_disfavoredOverload @inlinable public mutating func formQuotientWithRemainderReportingOverflow(dividingBy other: Digit) -> PVO { + NBK.formQuotientWithRemainderReportingOverflowAsUnsigned(&self.storage, dividingBy: other) } } diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Uninitialized.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Uninitialized.swift index 09044713..c9194067 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Uninitialized.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Uninitialized.swift @@ -20,13 +20,7 @@ extension NBKResizableWidth.Magnitude { //=------------------------------------------------------------------------= // TODO: measure (inout Self) -> Void - @inlinable public static func uninitialized(count: Int, body: (NBK.UnsafeMutableWords) -> Void) -> Self { - let storage = Storage(unsafeUninitializedCapacity: count) { - storage, endIndex in - body(NBK.UnsafeMutableWords(rebasing: storage.prefix(upTo: count))) - endIndex = count as Int - } - - return Self(storage: storage) + @inlinable public static func uninitialized(count: Int, body: (inout NBK.UnsafeMutableWords) -> Void) -> Self { + Self(storage: Storage(unsafeUninitializedCapacity: count) { body(&$0); $1 = count }) } } diff --git a/Sources/NBKResizableWidthKit/Private/NBK+Division.swift b/Sources/NBKResizableWidthKit/Private/NBK+Division.swift new file mode 100644 index 00000000..c4d94d07 --- /dev/null +++ b/Sources/NBKResizableWidthKit/Private/NBK+Division.swift @@ -0,0 +1,38 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Division x Digit +//*============================================================================* + +extension NBK { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public static func formQuotientWithRemainderReportingOverflowAsUnsigned( + _ limbs: inout T, dividingBy divisor: T.Element) -> PVO + where T: BidirectionalCollection & MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + //=--------------------------------------= + if divisor.isZero { + return PVO(limbs[limbs.startIndex], true) + } + //=--------------------------------------= + var remainder = T.Element.zero + + for index in limbs.indices.reversed() { + (limbs[index], remainder) = divisor.dividingFullWidth(HL(remainder, limbs[index])) + } + + return PVO(remainder, false) + } +} From ef23ebbe06dbaa717466df9f58ffd0f052ab15e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Thu, 10 Aug 2023 18:20:26 +0200 Subject: [PATCH 057/133] NBKResizableWidthKit: Cleanup. --- .../NBKResizableWidth+Addition+Digit.swift | 2 +- .../NBKResizableWidth+Addition.swift | 2 +- .../NBKResizableWidth+Subtraction+Digit.swift | 2 +- .../NBKResizableWidth+Subtraction.swift | 4 +- .../Private/NBK+Addition.swift | 56 ++++++++-------- .../Private/NBK+Subtraction.swift | 66 +++++++++---------- 6 files changed, 66 insertions(+), 66 deletions(-) diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition+Digit.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition+Digit.swift index 9901cf98..9e6ad9e1 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition+Digit.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition+Digit.swift @@ -33,6 +33,6 @@ extension NBKResizableWidth.Magnitude { // TODO: rename @_disfavoredOverload @inlinable public mutating func add(_ other: UInt, plus carry: Bool, at index: Int) -> Bool { - NBK.incrementAsUnsigned(&self, by: other, plus: carry, at: index).overflow + NBK.incrementUnsignedInteger(&self, by: other, plus: carry, at: index).overflow } } diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition.swift index 8e5e9396..a6f017db 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition.swift @@ -33,6 +33,6 @@ extension NBKResizableWidth.Magnitude { // TODO: rename @inlinable public mutating func add(_ other: Self, plus carry: Bool, at index: Int) -> Bool { - NBK.incrementAsUnsigned(&self, by: other, plus: carry, at: index).overflow + NBK.incrementUnsignedInteger(&self, by: other, plus: carry, at: index).overflow } } diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction+Digit.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction+Digit.swift index cf7bb8bf..69363320 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction+Digit.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction+Digit.swift @@ -45,6 +45,6 @@ extension NBKResizableWidth.Magnitude { // TODO: rename @_disfavoredOverload @inlinable public mutating func subtract(_ other: UInt, plus subtrahend: Bool, at index: Int) -> Bool { - NBK.decrementAsUnsigned(&self, by: other, plus: subtrahend, at: index).overflow + NBK.decrementUnsignedInteger(&self, by: other, plus: subtrahend, at: index).overflow } } diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction.swift index ea9774cf..c8cb3489 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction.swift @@ -45,11 +45,11 @@ extension NBKResizableWidth.Magnitude { // TODO: rename @inlinable public mutating func subtract(_ other: Self, plus subtrahend: Bool, at index: Int) -> Bool { - NBK.decrementAsUnsigned(&self, by: other, plus: subtrahend, at: index).overflow + NBK.decrementUnsignedInteger(&self, by: other, plus: subtrahend, at: index).overflow } // TODO: rename @inlinable public mutating func subtract(_ other: Self, times multiplicand: UInt, plus subtrahend: UInt, at index: Int) -> Bool { - NBK.decrementAsUnsigned(&self, by: other, times: multiplicand, plus: subtrahend, and: false, at: index).overflow + NBK.decrementUnsignedInteger(&self, by: other, times: multiplicand, plus: subtrahend, and: false, at: index).overflow } } diff --git a/Sources/NBKResizableWidthKit/Private/NBK+Addition.swift b/Sources/NBKResizableWidthKit/Private/NBK+Addition.swift index 7637b56c..88d5e0a8 100644 --- a/Sources/NBKResizableWidthKit/Private/NBK+Addition.swift +++ b/Sources/NBKResizableWidthKit/Private/NBK+Addition.swift @@ -19,19 +19,19 @@ extension NBK { // MARK: Transformations //=------------------------------------------------------------------------= - @_transparent public static func incrementAsUnsigned( + @_transparent public static func incrementUnsignedInteger( _ limbs: inout T, by addend: T, plus overflow: Bool, at index: T.Index) -> IO where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { var index: T.Index = index, overflow: Bool = overflow - NBK.incrementAsUnsigned(&limbs, by: addend, at: &index, carrying: &overflow) + NBK.incrementUnsignedInteger(&limbs, by: addend, at: &index, carrying: &overflow) return IO(index: index as T.Index, overflow: overflow as Bool) } - @_transparent public static func incrementAsUnsignedInIntersection( + @_transparent public static func incrementUnsignedIntegerInIntersection( _ limbs: inout T, by addend: T, plus overflow: Bool, at index: T.Index) -> IO where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { var index: T.Index = index, overflow: Bool = overflow - NBK.incrementAsUnsigned(&limbs, by: addend, at: &index, carrying: &overflow) + NBK.incrementUnsignedInteger(&limbs, by: addend, at: &index, carrying: &overflow) return IO(index: index as T.Index, overflow: overflow as Bool) } @@ -39,18 +39,18 @@ extension NBK { // MARK: Transformations x Inout //=------------------------------------------------------------------------= - @inlinable public static func incrementAsUnsigned( + @inlinable public static func incrementUnsignedInteger( _ limbs: inout T, by addend: T, at index: inout T.Index, carrying overflow: inout Bool) where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - NBK.incrementAsUnsignedInIntersection(&limbs, by: addend, at: &index, carrying: &overflow) - NBK.incrementAsUnsigned(&limbs, by: Void(), at: &index, carrying: &overflow) + NBK.incrementUnsignedIntegerInIntersection(&limbs, by: addend, at: &index, carrying: &overflow) + NBK.incrementUnsignedInteger(&limbs, by: Void(), at: &index, carrying: &overflow) } - @inlinable public static func incrementAsUnsignedInIntersection( + @inlinable public static func incrementUnsignedIntegerInIntersection( _ limbs: inout T, by addend: T, at index: inout T.Index, carrying overflow: inout Bool) where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { for addendIndex in addend.indices { // for-index-in >= for-element-in - NBK.incrementAsUnsignedInIntersection(&limbs, by: addend[addendIndex], at: &index, carrying: &overflow) + NBK.incrementUnsignedIntegerInIntersection(&limbs, by: addend[addendIndex], at: &index, carrying: &overflow) } } } @@ -65,14 +65,14 @@ extension NBK { // MARK: Transformations //=------------------------------------------------------------------------= - @_transparent public static func incrementAsUnsigned( + @_transparent public static func incrementUnsignedInteger( _ limbs: inout T, by addend: T.Element, at index: T.Index) -> IO where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - let (index, overflow) = NBK.incrementAsUnsignedInIntersection(&limbs, by: addend, at: index) - return NBK.incrementAsUnsigned(&limbs, by: overflow, at: index) as IO + let (index, overflow) = NBK.incrementUnsignedIntegerInIntersection(&limbs, by: addend, at: index) + return NBK.incrementUnsignedInteger(&limbs, by: overflow, at: index) as IO } - @_transparent public static func incrementAsUnsignedInIntersection( + @_transparent public static func incrementUnsignedIntegerInIntersection( _ limbs: inout T, by addend: T.Element, at index: T.Index) -> IO where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { let overflow = limbs[index].addReportingOverflow(addend) @@ -83,15 +83,15 @@ extension NBK { // MARK: Transformations x Inout //=------------------------------------------------------------------------= - @inlinable public static func incrementAsUnsigned( + @inlinable public static func incrementUnsignedInteger( _ limbs: inout T, by addend: T.Element, at index: inout T.Index) -> Bool where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - var overflow = NBK.incrementAsUnsignedInIntersection(&limbs, by: addend, at: &index) - NBK.incrementAsUnsigned(&limbs, by: Void(), at: &index, carrying: &overflow) + var overflow = NBK.incrementUnsignedIntegerInIntersection(&limbs, by: addend, at: &index) + NBK.incrementUnsignedInteger(&limbs, by: Void(), at: &index, carrying: &overflow) return overflow as Bool } - @inlinable public static func incrementAsUnsignedInIntersection( + @inlinable public static func incrementUnsignedIntegerInIntersection( _ limbs: inout T, by addend: T.Element, at index: inout T.Index) -> Bool where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { defer{ limbs.formIndex(after: &index) } @@ -109,19 +109,19 @@ extension NBK { // MARK: Transformations //=------------------------------------------------------------------------= - @_transparent public static func incrementAsUnsigned( + @_transparent public static func incrementUnsignedInteger( _ limbs: inout T, by addend: T.Element, plus overflow: Bool, at index: T.Index) -> IO where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { var index: T.Index = index, overflow: Bool = overflow - NBK.incrementAsUnsigned(&limbs, by: addend, at: &index, carrying: &overflow) + NBK.incrementUnsignedInteger(&limbs, by: addend, at: &index, carrying: &overflow) return IO(index: index as T.Index, overflow: overflow as Bool) } - @_transparent public static func incrementAsUnsignedInIntersection( + @_transparent public static func incrementUnsignedIntegerInIntersection( _ limbs: inout T, by addend: T.Element, plus overflow: Bool, at index: T.Index) -> IO where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { var index: T.Index = index, overflow: Bool = overflow - NBK.incrementAsUnsignedInIntersection(&limbs, by: addend, at: &index, carrying: &overflow) + NBK.incrementUnsignedIntegerInIntersection(&limbs, by: addend, at: &index, carrying: &overflow) return IO(index: index as T.Index, overflow: overflow as Bool) } @@ -129,14 +129,14 @@ extension NBK { // MARK: Transformations x Inout //=------------------------------------------------------------------------= - @inlinable public static func incrementAsUnsigned( + @inlinable public static func incrementUnsignedInteger( _ limbs: inout T, by addend: T.Element, at index: inout T.Index, carrying overflow: inout Bool) where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - NBK.incrementAsUnsignedInIntersection(&limbs, by: addend, at: &index, carrying: &overflow) - NBK.incrementAsUnsigned(&limbs, by: Void(), at: &index, carrying: &overflow) + NBK.incrementUnsignedIntegerInIntersection(&limbs, by: addend, at: &index, carrying: &overflow) + NBK.incrementUnsignedInteger(&limbs, by: Void(), at: &index, carrying: &overflow) } - @inlinable public static func incrementAsUnsignedInIntersection( + @inlinable public static func incrementUnsignedIntegerInIntersection( _ limbs: inout T, by addend: T.Element, at index: inout T.Index, carrying overflow: inout Bool) where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { var addend: T.Element = addend @@ -163,11 +163,11 @@ extension NBK { // MARK: Transformations //=------------------------------------------------------------------------= - @_transparent public static func incrementAsUnsigned( + @_transparent public static func incrementUnsignedInteger( _ limbs: inout T, by addend: Bool, at index: T.Index) -> IO where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { var index: T.Index = index, overflow: Bool = addend - NBK.incrementAsUnsigned(&limbs, by: Void(), at: &index, carrying: &overflow) + NBK.incrementUnsignedInteger(&limbs, by: Void(), at: &index, carrying: &overflow) return IO(index: index as T.Index, overflow: overflow as Bool) } @@ -175,7 +175,7 @@ extension NBK { // MARK: Transformations x Inout //=------------------------------------------------------------------------= - @inlinable public static func incrementAsUnsigned( + @inlinable public static func incrementUnsignedInteger( _ limbs: inout T, by addend: Void, at index: inout T.Index, carrying overflow: inout Bool) where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { while overflow && index < limbs.endIndex { diff --git a/Sources/NBKResizableWidthKit/Private/NBK+Subtraction.swift b/Sources/NBKResizableWidthKit/Private/NBK+Subtraction.swift index 76fc6fbb..a94c7c3f 100644 --- a/Sources/NBKResizableWidthKit/Private/NBK+Subtraction.swift +++ b/Sources/NBKResizableWidthKit/Private/NBK+Subtraction.swift @@ -19,19 +19,19 @@ extension NBK { // MARK: Transformations //=------------------------------------------------------------------------= - @_transparent public static func decrementAsUnsigned( + @_transparent public static func decrementUnsignedInteger( _ limbs: inout T, by subtrahend: T, plus overflow: Bool, at index: T.Index) -> IO where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { var index: T.Index = index, overflow: Bool = overflow - NBK.decrementAsUnsigned(&limbs, by: subtrahend, at: &index, borrowing: &overflow) + NBK.decrementUnsignedInteger(&limbs, by: subtrahend, at: &index, borrowing: &overflow) return IO(index: index as T.Index, overflow: overflow as Bool) } - @_transparent public static func decrementAsUnsignedInIntersection( + @_transparent public static func decrementUnsignedIntegerInIntersection( _ limbs: inout T, by subtrahend: T, plus overflow: Bool, at index: T.Index) -> IO where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { var index: T.Index = index, overflow: Bool = overflow - NBK.decrementAsUnsigned(&limbs, by: subtrahend, at: &index, borrowing: &overflow) + NBK.decrementUnsignedInteger(&limbs, by: subtrahend, at: &index, borrowing: &overflow) return IO(index: index as T.Index, overflow: overflow as Bool) } @@ -39,18 +39,18 @@ extension NBK { // MARK: Transformations x Inout //=------------------------------------------------------------------------= - @inlinable public static func decrementAsUnsigned( + @inlinable public static func decrementUnsignedInteger( _ limbs: inout T, by subtrahend: T, at index: inout T.Index, borrowing overflow: inout Bool) where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - NBK.decrementAsUnsignedInIntersection(&limbs, by: subtrahend, at: &index, borrowing: &overflow) - NBK.decrementAsUnsigned(&limbs, by: Void(), at: &index, borrowing: &overflow) + NBK.decrementUnsignedIntegerInIntersection(&limbs, by: subtrahend, at: &index, borrowing: &overflow) + NBK.decrementUnsignedInteger(&limbs, by: Void(), at: &index, borrowing: &overflow) } - @inlinable public static func decrementAsUnsignedInIntersection( + @inlinable public static func decrementUnsignedIntegerInIntersection( _ limbs: inout T, by subtrahend: T, at index: inout T.Index, borrowing overflow: inout Bool) where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { for subtrahendIndex in subtrahend.indices { // for-index-in >= for-element-in - NBK.decrementAsUnsignedInIntersection(&limbs, by: subtrahend[subtrahendIndex], at: &index, borrowing: &overflow) + NBK.decrementUnsignedIntegerInIntersection(&limbs, by: subtrahend[subtrahendIndex], at: &index, borrowing: &overflow) } } } @@ -65,14 +65,14 @@ extension NBK { // MARK: Transformations //=------------------------------------------------------------------------= - @_transparent public static func decrementAsUnsigned( + @_transparent public static func decrementUnsignedInteger( _ limbs: inout T, by subtrahend: T.Element, at index: T.Index) -> IO where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - let (index, overflow) = NBK.decrementAsUnsignedInIntersection(&limbs, by: subtrahend, at: index) - return NBK.decrementAsUnsigned(&limbs, by: overflow, at: index) as IO + let (index, overflow) = NBK.decrementUnsignedIntegerInIntersection(&limbs, by: subtrahend, at: index) + return NBK.decrementUnsignedInteger(&limbs, by: overflow, at: index) as IO } - @_transparent public static func decrementAsUnsignedInIntersection( + @_transparent public static func decrementUnsignedIntegerInIntersection( _ limbs: inout T, by subtrahend: T.Element, at index: T.Index) -> IO where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { let overflow = limbs[index].addReportingOverflow(subtrahend) @@ -83,15 +83,15 @@ extension NBK { // MARK: Transformations x Inout //=------------------------------------------------------------------------= - @inlinable public static func decrementAsUnsigned( + @inlinable public static func decrementUnsignedInteger( _ limbs: inout T, by subtrahend: T.Element, at index: inout T.Index) -> Bool where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - var overflow = NBK.decrementAsUnsignedInIntersection(&limbs, by: subtrahend, at: &index) - NBK.decrementAsUnsigned(&limbs, by: Void(), at: &index, borrowing: &overflow) + var overflow = NBK.decrementUnsignedIntegerInIntersection(&limbs, by: subtrahend, at: &index) + NBK.decrementUnsignedInteger(&limbs, by: Void(), at: &index, borrowing: &overflow) return overflow as Bool } - @inlinable public static func decrementAsUnsignedInIntersection( + @inlinable public static func decrementUnsignedIntegerInIntersection( _ limbs: inout T, by subtrahend: T.Element, at index: inout T.Index) -> Bool where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { defer{ limbs.formIndex(after: &index) } @@ -109,19 +109,19 @@ extension NBK { // MARK: Transformations //=------------------------------------------------------------------------= - @_transparent public static func decrementAsUnsigned( + @_transparent public static func decrementUnsignedInteger( _ limbs: inout T, by subtrahend: T.Element, plus overflow: Bool, at index: T.Index) -> IO where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { var index: T.Index = index, overflow: Bool = overflow - NBK.decrementAsUnsigned(&limbs, by: subtrahend, at: &index, borrowing: &overflow) + NBK.decrementUnsignedInteger(&limbs, by: subtrahend, at: &index, borrowing: &overflow) return IO(index: index as T.Index, overflow: overflow as Bool) } - @_transparent public static func decrementAsUnsignedInIntersection( + @_transparent public static func decrementUnsignedIntegerInIntersection( _ limbs: inout T, by subtrahend: T.Element, plus overflow: Bool, at index: T.Index) -> IO where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { var index: T.Index = index, overflow: Bool = overflow - NBK.decrementAsUnsignedInIntersection(&limbs, by: subtrahend, at: &index, borrowing: &overflow) + NBK.decrementUnsignedIntegerInIntersection(&limbs, by: subtrahend, at: &index, borrowing: &overflow) return IO(index: index as T.Index, overflow: overflow as Bool) } @@ -129,14 +129,14 @@ extension NBK { // MARK: Transformations x Inout //=------------------------------------------------------------------------= - @inlinable public static func decrementAsUnsigned( + @inlinable public static func decrementUnsignedInteger( _ limbs: inout T, by subtrahend: T.Element, at index: inout T.Index, borrowing overflow: inout Bool) where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - NBK.decrementAsUnsignedInIntersection(&limbs, by: subtrahend, at: &index, borrowing: &overflow) - NBK.decrementAsUnsigned(&limbs, by: Void(), at: &index, borrowing: &overflow) + NBK.decrementUnsignedIntegerInIntersection(&limbs, by: subtrahend, at: &index, borrowing: &overflow) + NBK.decrementUnsignedInteger(&limbs, by: Void(), at: &index, borrowing: &overflow) } - @inlinable public static func decrementAsUnsignedInIntersection( + @inlinable public static func decrementUnsignedIntegerInIntersection( _ limbs: inout T, by subtrahend: T.Element, at index: inout T.Index, borrowing overflow: inout Bool) where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { var subtrahend: T.Element = subtrahend @@ -163,11 +163,11 @@ extension NBK { // MARK: Transformations //=------------------------------------------------------------------------= - @_transparent public static func decrementAsUnsigned( + @_transparent public static func decrementUnsignedInteger( _ limbs: inout T, by subtrahend: Bool, at index: T.Index) -> IO where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { var index: T.Index = index, overflow: Bool = subtrahend - NBK.decrementAsUnsigned(&limbs, by: Void(), at: &index, borrowing: &overflow) + NBK.decrementUnsignedInteger(&limbs, by: Void(), at: &index, borrowing: &overflow) return IO(index: index as T.Index, overflow: overflow as Bool) } @@ -175,7 +175,7 @@ extension NBK { // MARK: Transformations x Inout //=------------------------------------------------------------------------= - @inlinable public static func decrementAsUnsigned( + @inlinable public static func decrementUnsignedInteger( _ limbs: inout T, by subtrahend: Void, at index: inout T.Index, borrowing overflow: inout Bool) where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { while overflow && index < limbs.endIndex { @@ -195,12 +195,12 @@ extension NBK { // MARK: Transformations //=------------------------------------------------------------------------= - @_transparent public static func decrementAsUnsigned( + @_transparent public static func decrementUnsignedInteger( _ limbs: inout T, by other: T, times multiplicand: T.Element, plus subtrahend: T.Element, and overflow: Bool, at index: T.Index) -> IO where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { var index: T.Index = index, overflow: Bool = overflow - NBK.decrementAsUnsigned(&limbs, by: other, times: multiplicand, plus: subtrahend, at: &index, borrowing: &overflow) + NBK.decrementUnsignedInteger(&limbs, by: other, times: multiplicand, plus: subtrahend, at: &index, borrowing: &overflow) return IO(index: index as T.Index, overflow: overflow as Bool) } @@ -208,7 +208,7 @@ extension NBK { // MARK: Transformations x Inout //=------------------------------------------------------------------------= - @inlinable public static func decrementAsUnsigned( + @inlinable public static func decrementUnsignedInteger( _ limbs: inout T, by other: T, times multiplicand: T.Element, plus subtrahend: T.Element, at index: inout T.Index, borrowing overflow: inout Bool) where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { @@ -217,9 +217,9 @@ extension NBK { for otherIndex in other.indices { var subproduct = other[otherIndex].multipliedFullWidth(by: multiplicand) last = T.Element(bit: subproduct.low.addReportingOverflow(last)) &+ subproduct.high - NBK.decrementAsUnsignedInIntersection(&limbs, by: subproduct.low, at: &index, borrowing: &overflow) + NBK.decrementUnsignedIntegerInIntersection(&limbs, by: subproduct.low, at: &index, borrowing: &overflow) } - NBK.decrementAsUnsigned(&limbs, by: last, at: &index, borrowing: &overflow) + NBK.decrementUnsignedInteger(&limbs, by: last, at: &index, borrowing: &overflow) } } From 830a85617437f1709db4857f4adc362ffe79d759 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Fri, 11 Aug 2023 08:59:29 +0200 Subject: [PATCH 058/133] NBKResizableWidthKit: Addition, Subtraction. --- .../NBKResizableWidth+Addition+Digit.swift | 2 +- .../NBKResizableWidth+Addition.swift | 2 +- .../NBKResizableWidth+Subtraction+Digit.swift | 2 +- .../NBKResizableWidth+Subtraction.swift | 4 +- .../Private/NBK+Addition.swift | 186 ----------- .../Private/NBK+Limbs+Addition.swift | 266 +++++++++++++++ .../Private/NBK+Limbs+Subtraction.swift | 316 ++++++++++++++++++ .../Private/NBK+Subtraction.swift | 225 ------------- .../Private/NBK+Limbs+Addition.swift | 142 ++++++++ .../Private/NBK+Limbs+Subtraction.swift | 142 ++++++++ 10 files changed, 871 insertions(+), 416 deletions(-) delete mode 100644 Sources/NBKResizableWidthKit/Private/NBK+Addition.swift create mode 100644 Sources/NBKResizableWidthKit/Private/NBK+Limbs+Addition.swift create mode 100644 Sources/NBKResizableWidthKit/Private/NBK+Limbs+Subtraction.swift delete mode 100644 Sources/NBKResizableWidthKit/Private/NBK+Subtraction.swift create mode 100644 Tests/NBKResizableWidthKitTests/Private/NBK+Limbs+Addition.swift create mode 100644 Tests/NBKResizableWidthKitTests/Private/NBK+Limbs+Subtraction.swift diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition+Digit.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition+Digit.swift index 9e6ad9e1..6c53965a 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition+Digit.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition+Digit.swift @@ -33,6 +33,6 @@ extension NBKResizableWidth.Magnitude { // TODO: rename @_disfavoredOverload @inlinable public mutating func add(_ other: UInt, plus carry: Bool, at index: Int) -> Bool { - NBK.incrementUnsignedInteger(&self, by: other, plus: carry, at: index).overflow + NBK.incrementSufficientUnsignedInteger(&self, by: other, at: index, carrying: carry).overflow } } diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition.swift index a6f017db..6686bbc9 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition.swift @@ -33,6 +33,6 @@ extension NBKResizableWidth.Magnitude { // TODO: rename @inlinable public mutating func add(_ other: Self, plus carry: Bool, at index: Int) -> Bool { - NBK.incrementUnsignedInteger(&self, by: other, plus: carry, at: index).overflow + NBK.incrementSufficientUnsignedInteger(&self, by: other, at: index, carrying: carry).overflow } } diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction+Digit.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction+Digit.swift index 69363320..daa6d855 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction+Digit.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction+Digit.swift @@ -45,6 +45,6 @@ extension NBKResizableWidth.Magnitude { // TODO: rename @_disfavoredOverload @inlinable public mutating func subtract(_ other: UInt, plus subtrahend: Bool, at index: Int) -> Bool { - NBK.decrementUnsignedInteger(&self, by: other, plus: subtrahend, at: index).overflow + NBK.decrementSufficientUnsignedInteger(&self, by: other, at: index, borrowing: subtrahend).overflow } } diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction.swift index c8cb3489..0de611a6 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction.swift @@ -45,11 +45,11 @@ extension NBKResizableWidth.Magnitude { // TODO: rename @inlinable public mutating func subtract(_ other: Self, plus subtrahend: Bool, at index: Int) -> Bool { - NBK.decrementUnsignedInteger(&self, by: other, plus: subtrahend, at: index).overflow + NBK.decrementSufficientUnsignedInteger(&self, by: other, at: index, borrowing: subtrahend).overflow } // TODO: rename @inlinable public mutating func subtract(_ other: Self, times multiplicand: UInt, plus subtrahend: UInt, at index: Int) -> Bool { - NBK.decrementUnsignedInteger(&self, by: other, times: multiplicand, plus: subtrahend, and: false, at: index).overflow + NBK.decrementSufficientUnsignedInteger(&self, by: other, times: multiplicand, plus: subtrahend, at: index, borrowing: false).overflow } } diff --git a/Sources/NBKResizableWidthKit/Private/NBK+Addition.swift b/Sources/NBKResizableWidthKit/Private/NBK+Addition.swift deleted file mode 100644 index 88d5e0a8..00000000 --- a/Sources/NBKResizableWidthKit/Private/NBK+Addition.swift +++ /dev/null @@ -1,186 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Addition -//*============================================================================* - -extension NBK { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @_transparent public static func incrementUnsignedInteger( - _ limbs: inout T, by addend: T, plus overflow: Bool, at index: T.Index) -> IO - where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - var index: T.Index = index, overflow: Bool = overflow - NBK.incrementUnsignedInteger(&limbs, by: addend, at: &index, carrying: &overflow) - return IO(index: index as T.Index, overflow: overflow as Bool) - } - - @_transparent public static func incrementUnsignedIntegerInIntersection( - _ limbs: inout T, by addend: T, plus overflow: Bool, at index: T.Index) -> IO - where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - var index: T.Index = index, overflow: Bool = overflow - NBK.incrementUnsignedInteger(&limbs, by: addend, at: &index, carrying: &overflow) - return IO(index: index as T.Index, overflow: overflow as Bool) - } - - //=------------------------------------------------------------------------= - // MARK: Transformations x Inout - //=------------------------------------------------------------------------= - - @inlinable public static func incrementUnsignedInteger( - _ limbs: inout T, by addend: T, at index: inout T.Index, carrying overflow: inout Bool) - where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - NBK.incrementUnsignedIntegerInIntersection(&limbs, by: addend, at: &index, carrying: &overflow) - NBK.incrementUnsignedInteger(&limbs, by: Void(), at: &index, carrying: &overflow) - } - - @inlinable public static func incrementUnsignedIntegerInIntersection( - _ limbs: inout T, by addend: T, at index: inout T.Index, carrying overflow: inout Bool) - where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - for addendIndex in addend.indices { // for-index-in >= for-element-in - NBK.incrementUnsignedIntegerInIntersection(&limbs, by: addend[addendIndex], at: &index, carrying: &overflow) - } - } -} - -//*============================================================================* -// MARK: * NBK x Addition x Digit -//*============================================================================* - -extension NBK { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @_transparent public static func incrementUnsignedInteger( - _ limbs: inout T, by addend: T.Element, at index: T.Index) -> IO - where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - let (index, overflow) = NBK.incrementUnsignedIntegerInIntersection(&limbs, by: addend, at: index) - return NBK.incrementUnsignedInteger(&limbs, by: overflow, at: index) as IO - } - - @_transparent public static func incrementUnsignedIntegerInIntersection( - _ limbs: inout T, by addend: T.Element, at index: T.Index) -> IO - where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - let overflow = limbs[index].addReportingOverflow(addend) - return IO(limbs.index(after: index), overflow) - } - - //=------------------------------------------------------------------------= - // MARK: Transformations x Inout - //=------------------------------------------------------------------------= - - @inlinable public static func incrementUnsignedInteger( - _ limbs: inout T, by addend: T.Element, at index: inout T.Index) -> Bool - where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - var overflow = NBK.incrementUnsignedIntegerInIntersection(&limbs, by: addend, at: &index) - NBK.incrementUnsignedInteger(&limbs, by: Void(), at: &index, carrying: &overflow) - return overflow as Bool - } - - @inlinable public static func incrementUnsignedIntegerInIntersection( - _ limbs: inout T, by addend: T.Element, at index: inout T.Index) -> Bool - where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - defer{ limbs.formIndex(after: &index) } - return limbs[index].addReportingOverflow(addend) - } -} - -//*============================================================================* -// MARK: * NBK x Addition x Digit x Carry -//*============================================================================* - -extension NBK { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @_transparent public static func incrementUnsignedInteger( - _ limbs: inout T, by addend: T.Element, plus overflow: Bool, at index: T.Index) -> IO - where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - var index: T.Index = index, overflow: Bool = overflow - NBK.incrementUnsignedInteger(&limbs, by: addend, at: &index, carrying: &overflow) - return IO(index: index as T.Index, overflow: overflow as Bool) - } - - @_transparent public static func incrementUnsignedIntegerInIntersection( - _ limbs: inout T, by addend: T.Element, plus overflow: Bool, at index: T.Index) -> IO - where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - var index: T.Index = index, overflow: Bool = overflow - NBK.incrementUnsignedIntegerInIntersection(&limbs, by: addend, at: &index, carrying: &overflow) - return IO(index: index as T.Index, overflow: overflow as Bool) - } - - //=------------------------------------------------------------------------= - // MARK: Transformations x Inout - //=------------------------------------------------------------------------= - - @inlinable public static func incrementUnsignedInteger( - _ limbs: inout T, by addend: T.Element, at index: inout T.Index, carrying overflow: inout Bool) - where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - NBK.incrementUnsignedIntegerInIntersection(&limbs, by: addend, at: &index, carrying: &overflow) - NBK.incrementUnsignedInteger(&limbs, by: Void(), at: &index, carrying: &overflow) - } - - @inlinable public static func incrementUnsignedIntegerInIntersection( - _ limbs: inout T, by addend: T.Element, at index: inout T.Index, carrying overflow: inout Bool) - where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - var addend: T.Element = addend - - if overflow { - overflow = addend.addReportingOverflow(1 as T.Element.Digit) - } - - if !overflow { - overflow = limbs[index].addReportingOverflow(addend) - } - - limbs.formIndex(after: &index) - } -} - -//*============================================================================* -// MARK: * NBK x Addition x Bool -//*============================================================================* - -extension NBK { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @_transparent public static func incrementUnsignedInteger( - _ limbs: inout T, by addend: Bool, at index: T.Index) -> IO - where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - var index: T.Index = index, overflow: Bool = addend - NBK.incrementUnsignedInteger(&limbs, by: Void(), at: &index, carrying: &overflow) - return IO(index: index as T.Index, overflow: overflow as Bool) - } - - //=------------------------------------------------------------------------= - // MARK: Transformations x Inout - //=------------------------------------------------------------------------= - - @inlinable public static func incrementUnsignedInteger( - _ limbs: inout T, by addend: Void, at index: inout T.Index, carrying overflow: inout Bool) - where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - while overflow && index < limbs.endIndex { - overflow = limbs[index].addReportingOverflow(1 as T.Element.Digit) - limbs.formIndex(after: &index) - } - } -} diff --git a/Sources/NBKResizableWidthKit/Private/NBK+Limbs+Addition.swift b/Sources/NBKResizableWidthKit/Private/NBK+Limbs+Addition.swift new file mode 100644 index 00000000..0e65b7c5 --- /dev/null +++ b/Sources/NBKResizableWidthKit/Private/NBK+Limbs+Addition.swift @@ -0,0 +1,266 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Limbs x Addition +//*============================================================================* + +extension NBK { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + /// Increments `limbs` by the sum of `addend` and `overflow` at `index`. + /// + /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// + /// - Returns: An overflow indicator and its index in `limbs`. + /// + @_transparent public static func incrementSufficientUnsignedInteger( + _ limbs: inout T, by addend: T, at index: T.Index, carrying overflow: Bool) -> IO + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + var index: T.Index = index, overflow: Bool = overflow + NBK.incrementSufficientUnsignedInteger(&limbs, by: addend, at: &index, carrying: &overflow) + return IO(index: index as T.Index, overflow: overflow as Bool) + } + + /// Partially increments `limbs` by the sum of `addend` and `overflow` at `index`. + /// + /// - This operation does not continue beyond the operand intersection. + /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// + /// - Returns: An overflow indicator and its index in `limbs`. + /// + @_transparent public static func incrementSufficientUnsignedIntegerInIntersection( + _ limbs: inout T, by addend: T, at index: T.Index, carrying overflow: Bool) -> IO + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + var index: T.Index = index, overflow: Bool = overflow + NBK.incrementSufficientUnsignedInteger(&limbs, by: addend, at: &index, carrying: &overflow) + return IO(index: index as T.Index, overflow: overflow as Bool) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Inout + //=------------------------------------------------------------------------= + + /// Increments `limbs` by the sum of `addend` and `overflow` at `index`. + /// + /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// + @inlinable public static func incrementSufficientUnsignedInteger( + _ limbs: inout T, by addend: T, at index: inout T.Index, carrying overflow: inout Bool) + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + NBK.incrementSufficientUnsignedIntegerInIntersection(&limbs, by: addend, at: &index, carrying: &overflow) + NBK.incrementSufficientUnsignedInteger(&limbs, by: Void(), at: &index, carrying: &overflow) + } + + /// Partially increments `limbs` by the sum of `addend` and `overflow` at `index`. + /// + /// - This operation does not continue beyond the operand intersection. + /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// + @inlinable public static func incrementSufficientUnsignedIntegerInIntersection( + _ limbs: inout T, by addend: T, at index: inout T.Index, carrying overflow: inout Bool) + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + for addendIndex in addend.indices { // for-index-in >= for-element-in + NBK.incrementSufficientUnsignedIntegerInIntersection(&limbs, by: addend[addendIndex], at: &index, carrying: &overflow) + } + } +} + +//*============================================================================* +// MARK: * NBK x Limbs x Addition x Digit +//*============================================================================* + +extension NBK { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + /// Increments `limbs` by `addend` at `index`. + /// + /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// + /// - Returns: An overflow indicator and its index in `limbs`. + /// + @_transparent public static func incrementSufficientUnsignedInteger( + _ limbs: inout T, by addend: T.Element, at index: T.Index) -> IO + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + let (index, overflow) = NBK.incrementSufficientUnsignedIntegerInIntersection(&limbs, by: addend, at: index) + return NBK.incrementSufficientUnsignedInteger(&limbs, by: Void(), at: index, carrying: overflow) as IO + } + + /// Partially increments `limbs` by `addend` at `index`. + /// + /// - This operation does not continue beyond the operand intersection. + /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// + /// - Returns: An overflow indicator and its index in `limbs`. + /// + @_transparent public static func incrementSufficientUnsignedIntegerInIntersection( + _ limbs: inout T, by addend: T.Element, at index: T.Index) -> IO + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + let overflow = limbs[index].addReportingOverflow(addend) + return IO(limbs.index(after: index), overflow) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Inout + //=------------------------------------------------------------------------= + + /// Increments `limbs` by `addend` at `index`. + /// + /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// + /// - Returns: An overflow indicator. + /// + @inlinable public static func incrementSufficientUnsignedInteger( + _ limbs: inout T, by addend: T.Element, at index: inout T.Index) -> Bool + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + var overflow = NBK.incrementSufficientUnsignedIntegerInIntersection(&limbs, by: addend, at: &index) + NBK.incrementSufficientUnsignedInteger(&limbs, by: Void(), at: &index, carrying: &overflow) + return overflow as Bool + } + + /// Partially increments `limbs` by `addend` at `index`. + /// + /// - This operation does not continue beyond the operand intersection. + /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// + /// - Returns: An overflow indicator. + /// + @inlinable public static func incrementSufficientUnsignedIntegerInIntersection( + _ limbs: inout T, by addend: T.Element, at index: inout T.Index) -> Bool + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + defer{ limbs.formIndex(after: &index) } + return limbs[index].addReportingOverflow(addend) + } +} + +//*============================================================================* +// MARK: * NBK x Limbs x Addition x Digit x Carry +//*============================================================================* + +extension NBK { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + /// Increments `limbs` by the sum of `addend` and `overflow` at `index`. + /// + /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// + /// - Returns: An overflow indicator and its index in `limbs`. + /// + @_transparent public static func incrementSufficientUnsignedInteger( + _ limbs: inout T, by addend: T.Element, at index: T.Index, carrying overflow: Bool) -> IO + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + var index: T.Index = index, overflow: Bool = overflow + NBK.incrementSufficientUnsignedInteger(&limbs, by: addend, at: &index, carrying: &overflow) + return IO(index: index as T.Index, overflow: overflow as Bool) + } + + /// Partially increments `limbs` by the sum of `addend` and `overflow` at `index`. + /// + /// - This operation does not continue beyond the operand intersection. + /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// + /// - Returns: An overflow indicator and its index in `limbs`. + /// + @_transparent public static func incrementSufficientUnsignedIntegerInIntersection( + _ limbs: inout T, by addend: T.Element, at index: T.Index, carrying overflow: Bool) -> IO + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + var index: T.Index = index, overflow: Bool = overflow + NBK.incrementSufficientUnsignedIntegerInIntersection(&limbs, by: addend, at: &index, carrying: &overflow) + return IO(index: index as T.Index, overflow: overflow as Bool) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Inout + //=------------------------------------------------------------------------= + + /// Increments `limbs` by the sum of `addend` and `overflow` at `index`. + /// + /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// + @inlinable public static func incrementSufficientUnsignedInteger( + _ limbs: inout T, by addend: T.Element, at index: inout T.Index, carrying overflow: inout Bool) + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + NBK.incrementSufficientUnsignedIntegerInIntersection(&limbs, by: addend, at: &index, carrying: &overflow) + NBK.incrementSufficientUnsignedInteger(&limbs, by: Void(), at: &index, carrying: &overflow) + } + + /// Partially increments `limbs` by the sum of `addend` and `overflow` at `index`. + /// + /// - This operation does not continue beyond the operand intersection. + /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// + @inlinable public static func incrementSufficientUnsignedIntegerInIntersection( + _ limbs: inout T, by addend: T.Element, at index: inout T.Index, carrying overflow: inout Bool) + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + var addend: T.Element = addend + + if overflow { + overflow = addend.addReportingOverflow(1 as T.Element.Digit) + } + + if !overflow { + overflow = limbs[index].addReportingOverflow(addend) + } + + limbs.formIndex(after: &index) + } +} + +//*============================================================================* +// MARK: * NBK x Limbs x Addition x Void +//*============================================================================* + +extension NBK { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + /// Increments `limbs` by the sum of `addend` and `overflow` at `index`. + /// + /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// + /// - Returns: An overflow indicator and its index in `limbs`. + /// + @_transparent public static func incrementSufficientUnsignedInteger( + _ limbs: inout T, by addend: Void, at index: T.Index, carrying overflow: Bool) -> IO + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + var index: T.Index = index, overflow: Bool = overflow + NBK.incrementSufficientUnsignedInteger(&limbs, by: addend, at: &index, carrying: &overflow) + return IO(index: index as T.Index, overflow: overflow as Bool) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Inout + //=------------------------------------------------------------------------= + + /// Increments `limbs` by the sum of `addend` and `overflow` at `index`. + /// + /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// + @inlinable public static func incrementSufficientUnsignedInteger( + _ limbs: inout T, by addend: Void, at index: inout T.Index, carrying overflow: inout Bool) + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + while overflow && index < limbs.endIndex { + overflow = limbs[index].addReportingOverflow(1 as T.Element.Digit) + limbs.formIndex(after: &index) + } + } +} diff --git a/Sources/NBKResizableWidthKit/Private/NBK+Limbs+Subtraction.swift b/Sources/NBKResizableWidthKit/Private/NBK+Limbs+Subtraction.swift new file mode 100644 index 00000000..61abebbc --- /dev/null +++ b/Sources/NBKResizableWidthKit/Private/NBK+Limbs+Subtraction.swift @@ -0,0 +1,316 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Limbs x Subtraction +//*============================================================================* + +extension NBK { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + /// Decrements `limbs` by the sum of `subtrahend` and `overflow` at `index`. + /// + /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// + /// - Returns: An overflow indicator and its index in `limbs`. + /// + @_transparent public static func decrementSufficientUnsignedInteger( + _ limbs: inout T, by subtrahend: T, at index: T.Index, borrowing overflow: Bool) -> IO + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + var index: T.Index = index, overflow: Bool = overflow + NBK.decrementSufficientUnsignedInteger(&limbs, by: subtrahend, at: &index, borrowing: &overflow) + return IO(index: index as T.Index, overflow: overflow as Bool) + } + + /// Partially decrements `limbs` by the sum of `subtrahend` and `overflow` at `index`. + /// + /// - This operation does not continue beyond the operand intersection. + /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// + /// - Returns: An overflow indicator and its index in `limbs`. + /// + @_transparent public static func decrementSufficientUnsignedIntegerInIntersection( + _ limbs: inout T, by subtrahend: T, at index: T.Index, borrowing overflow: Bool) -> IO + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + var index: T.Index = index, overflow: Bool = overflow + NBK.decrementSufficientUnsignedInteger(&limbs, by: subtrahend, at: &index, borrowing: &overflow) + return IO(index: index as T.Index, overflow: overflow as Bool) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Inout + //=------------------------------------------------------------------------= + + /// Decrements `limbs` by the sum of `subtrahend` and `overflow` at `index`. + /// + /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// + @inlinable public static func decrementSufficientUnsignedInteger( + _ limbs: inout T, by subtrahend: T, at index: inout T.Index, borrowing overflow: inout Bool) + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + NBK.decrementSufficientUnsignedIntegerInIntersection(&limbs, by: subtrahend, at: &index, borrowing: &overflow) + NBK.decrementSufficientUnsignedInteger(&limbs, by: Void(), at: &index, borrowing: &overflow) + } + + /// Partially decrements `limbs` by the sum of `subtrahend` and `overflow` at `index`. + /// + /// - This operation does not continue beyond the operand intersection. + /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// + @inlinable public static func decrementSufficientUnsignedIntegerInIntersection( + _ limbs: inout T, by subtrahend: T, at index: inout T.Index, borrowing overflow: inout Bool) + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + for subtrahendIndex in subtrahend.indices { // for-index-in >= for-element-in + NBK.decrementSufficientUnsignedIntegerInIntersection(&limbs, by: subtrahend[subtrahendIndex], at: &index, borrowing: &overflow) + } + } +} + +//*============================================================================* +// MARK: * NBK x Limbs x Subtraction x Digit +//*============================================================================* + +extension NBK { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + /// Decrements `limbs` by `subtrahend` at `index`. + /// + /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// + /// - Returns: An overflow indicator and its index in `limbs`. + /// + @_transparent public static func decrementSufficientUnsignedInteger( + _ limbs: inout T, by subtrahend: T.Element, at index: T.Index) -> IO + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + let (index, overflow) = NBK.decrementSufficientUnsignedIntegerInIntersection(&limbs, by: subtrahend, at: index) + return NBK.decrementSufficientUnsignedInteger(&limbs, by: Void(), at: index, borrowing: overflow) as IO + } + + /// Partially decrements `limbs` by `subtrahend` at `index`. + /// + /// - This operation does not continue beyond the operand intersection. + /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// + /// - Returns: An overflow indicator and its index in `limbs`. + /// + @_transparent public static func decrementSufficientUnsignedIntegerInIntersection( + _ limbs: inout T, by subtrahend: T.Element, at index: T.Index) -> IO + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + let overflow = limbs[index].subtractReportingOverflow(subtrahend) + return IO(limbs.index(after: index), overflow) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Inout + //=------------------------------------------------------------------------= + + /// Decrements `limbs` by `subtrahend` at `index`. + /// + /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// + /// - Returns: An overflow indicator. + /// + @inlinable public static func decrementSufficientUnsignedInteger( + _ limbs: inout T, by subtrahend: T.Element, at index: inout T.Index) -> Bool + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + var overflow = NBK.decrementSufficientUnsignedIntegerInIntersection(&limbs, by: subtrahend, at: &index) + NBK.decrementSufficientUnsignedInteger(&limbs, by: Void(), at: &index, borrowing: &overflow) + return overflow as Bool + } + + /// Partially decrements `limbs` by `subtrahend` at `index`. + /// + /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// + /// - Returns: An overflow indicator. + /// + @inlinable public static func decrementSufficientUnsignedIntegerInIntersection( + _ limbs: inout T, by subtrahend: T.Element, at index: inout T.Index) -> Bool + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + defer{ limbs.formIndex(after: &index) } + return limbs[index].subtractReportingOverflow(subtrahend) + } +} + +//*============================================================================* +// MARK: * NBK x Limbs x Subtraction x Digit x Carry +//*============================================================================* + +extension NBK { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + /// Decrements `limbs` by the sum of `subtrahend` and `overflow` at `index`. + /// + /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// + /// - Returns: An overflow indicator and its index in `limbs`. + /// + @_transparent public static func decrementSufficientUnsignedInteger( + _ limbs: inout T, by subtrahend: T.Element, at index: T.Index, borrowing overflow: Bool) -> IO + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + var index: T.Index = index, overflow: Bool = overflow + NBK.decrementSufficientUnsignedInteger(&limbs, by: subtrahend, at: &index, borrowing: &overflow) + return IO(index: index as T.Index, overflow: overflow as Bool) + } + + /// Partially decrements `limbs` by the sum of `subtrahend` and `overflow` at `index`. + /// + /// - This operation does not continue beyond the operand intersection. + /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// + /// - Returns: An overflow indicator and its index in `limbs`. + /// + @_transparent public static func decrementSufficientUnsignedIntegerInIntersection( + _ limbs: inout T, by subtrahend: T.Element, at index: T.Index, borrowing overflow: Bool) -> IO + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + var index: T.Index = index, overflow: Bool = overflow + NBK.decrementSufficientUnsignedIntegerInIntersection(&limbs, by: subtrahend, at: &index, borrowing: &overflow) + return IO(index: index as T.Index, overflow: overflow as Bool) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Inout + //=------------------------------------------------------------------------= + + /// Decrements `limbs` by the sum of `subtrahend` and `overflow` at `index`. + /// + /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// + @inlinable public static func decrementSufficientUnsignedInteger( + _ limbs: inout T, by subtrahend: T.Element, at index: inout T.Index, borrowing overflow: inout Bool) + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + NBK.decrementSufficientUnsignedIntegerInIntersection(&limbs, by: subtrahend, at: &index, borrowing: &overflow) + NBK.decrementSufficientUnsignedInteger(&limbs, by: Void(), at: &index, borrowing: &overflow) + } + + /// Partially decrements `limbs` by the sum of `subtrahend` and `overflow` at `index`. + /// + /// - This operation does not continue beyond the operand intersection. + /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// + @inlinable public static func decrementSufficientUnsignedIntegerInIntersection( + _ limbs: inout T, by subtrahend: T.Element, at index: inout T.Index, borrowing overflow: inout Bool) + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + var subtrahend: T.Element = subtrahend + + if overflow { + overflow = subtrahend.addReportingOverflow(1 as T.Element.Digit) + } + + if !overflow { + overflow = limbs[index].subtractReportingOverflow(subtrahend) + } + + limbs.formIndex(after: &index) + } +} + +//*============================================================================* +// MARK: * NBK x Limbs x Subtraction x Void +//*============================================================================* + +extension NBK { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + /// Decrements `limbs` by the sum of `subtrahend` and `overflow` at `index`. + /// + /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// + /// - Returns: An overflow indicator and its index in `limbs`. + /// + @_transparent public static func decrementSufficientUnsignedInteger( + _ limbs: inout T, by subtrahend: Void, at index: T.Index, borrowing overflow: Bool) -> IO + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + var index: T.Index = index, overflow: Bool = overflow + NBK.decrementSufficientUnsignedInteger(&limbs, by: Void(), at: &index, borrowing: &overflow) + return IO(index: index as T.Index, overflow: overflow as Bool) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Inout + //=------------------------------------------------------------------------= + + /// Decrements `limbs` by the sum of `subtrahend` and `overflow` at `index`. + /// + /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// + @inlinable public static func decrementSufficientUnsignedInteger( + _ limbs: inout T, by subtrahend: Void, at index: inout T.Index, borrowing overflow: inout Bool) + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + while overflow && index < limbs.endIndex { + overflow = limbs[index].subtractReportingOverflow(1 as T.Element.Digit) + limbs.formIndex(after: &index) + } + } +} + +//*============================================================================* +// MARK: * NBK x Limbs x Subtraction x Product +//*============================================================================* + +extension NBK { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + /// Decrements `limbs` by the sum of the `subtrahend`, the `overflow`, and + /// the product of `other` and `multiplicand` at `index`. + /// + /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// + /// - Returns: An overflow indicator and its index in `limbs`. + /// + @_transparent public static func decrementSufficientUnsignedInteger( + _ limbs: inout T, by other: T, times multiplicand: T.Element, plus subtrahend: T.Element, + at index: T.Index, borrowing overflow: Bool) -> IO + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + var index: T.Index = index, overflow: Bool = overflow + NBK.decrementSufficientUnsignedInteger(&limbs, by: other, times: multiplicand, plus: subtrahend, at: &index, borrowing: &overflow) + return IO(index: index as T.Index, overflow: overflow as Bool) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Inout + //=------------------------------------------------------------------------= + + /// Decrements `limbs` by the sum of the `subtrahend`, the `overflow`, and + /// the product of `other` and `multiplicand` at `index`. + /// + /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// + @inlinable public static func decrementSufficientUnsignedInteger( + _ limbs: inout T, by other: T, times multiplicand: T.Element, plus subtrahend: T.Element, + at index: inout T.Index, borrowing overflow: inout Bool) + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + var last: T.Element = subtrahend + + for otherIndex in other.indices { + var subproduct = other[otherIndex].multipliedFullWidth(by: multiplicand) + last = T.Element(bit: subproduct.low.addReportingOverflow(last)) &+ subproduct.high + NBK.decrementSufficientUnsignedIntegerInIntersection(&limbs, by: subproduct.low, at: &index, borrowing: &overflow) + } + + NBK.decrementSufficientUnsignedInteger(&limbs, by: last, at: &index, borrowing: &overflow) + } +} diff --git a/Sources/NBKResizableWidthKit/Private/NBK+Subtraction.swift b/Sources/NBKResizableWidthKit/Private/NBK+Subtraction.swift deleted file mode 100644 index a94c7c3f..00000000 --- a/Sources/NBKResizableWidthKit/Private/NBK+Subtraction.swift +++ /dev/null @@ -1,225 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Subtraction -//*============================================================================* - -extension NBK { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @_transparent public static func decrementUnsignedInteger( - _ limbs: inout T, by subtrahend: T, plus overflow: Bool, at index: T.Index) -> IO - where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - var index: T.Index = index, overflow: Bool = overflow - NBK.decrementUnsignedInteger(&limbs, by: subtrahend, at: &index, borrowing: &overflow) - return IO(index: index as T.Index, overflow: overflow as Bool) - } - - @_transparent public static func decrementUnsignedIntegerInIntersection( - _ limbs: inout T, by subtrahend: T, plus overflow: Bool, at index: T.Index) -> IO - where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - var index: T.Index = index, overflow: Bool = overflow - NBK.decrementUnsignedInteger(&limbs, by: subtrahend, at: &index, borrowing: &overflow) - return IO(index: index as T.Index, overflow: overflow as Bool) - } - - //=------------------------------------------------------------------------= - // MARK: Transformations x Inout - //=------------------------------------------------------------------------= - - @inlinable public static func decrementUnsignedInteger( - _ limbs: inout T, by subtrahend: T, at index: inout T.Index, borrowing overflow: inout Bool) - where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - NBK.decrementUnsignedIntegerInIntersection(&limbs, by: subtrahend, at: &index, borrowing: &overflow) - NBK.decrementUnsignedInteger(&limbs, by: Void(), at: &index, borrowing: &overflow) - } - - @inlinable public static func decrementUnsignedIntegerInIntersection( - _ limbs: inout T, by subtrahend: T, at index: inout T.Index, borrowing overflow: inout Bool) - where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - for subtrahendIndex in subtrahend.indices { // for-index-in >= for-element-in - NBK.decrementUnsignedIntegerInIntersection(&limbs, by: subtrahend[subtrahendIndex], at: &index, borrowing: &overflow) - } - } -} - -//*============================================================================* -// MARK: * NBK x Subtraction x Digit -//*============================================================================* - -extension NBK { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @_transparent public static func decrementUnsignedInteger( - _ limbs: inout T, by subtrahend: T.Element, at index: T.Index) -> IO - where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - let (index, overflow) = NBK.decrementUnsignedIntegerInIntersection(&limbs, by: subtrahend, at: index) - return NBK.decrementUnsignedInteger(&limbs, by: overflow, at: index) as IO - } - - @_transparent public static func decrementUnsignedIntegerInIntersection( - _ limbs: inout T, by subtrahend: T.Element, at index: T.Index) -> IO - where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - let overflow = limbs[index].addReportingOverflow(subtrahend) - return IO(limbs.index(after: index), overflow) - } - - //=------------------------------------------------------------------------= - // MARK: Transformations x Inout - //=------------------------------------------------------------------------= - - @inlinable public static func decrementUnsignedInteger( - _ limbs: inout T, by subtrahend: T.Element, at index: inout T.Index) -> Bool - where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - var overflow = NBK.decrementUnsignedIntegerInIntersection(&limbs, by: subtrahend, at: &index) - NBK.decrementUnsignedInteger(&limbs, by: Void(), at: &index, borrowing: &overflow) - return overflow as Bool - } - - @inlinable public static func decrementUnsignedIntegerInIntersection( - _ limbs: inout T, by subtrahend: T.Element, at index: inout T.Index) -> Bool - where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - defer{ limbs.formIndex(after: &index) } - return limbs[index].addReportingOverflow(subtrahend) - } -} - -//*============================================================================* -// MARK: * NBK x Subtraction x Digit x Carry -//*============================================================================* - -extension NBK { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @_transparent public static func decrementUnsignedInteger( - _ limbs: inout T, by subtrahend: T.Element, plus overflow: Bool, at index: T.Index) -> IO - where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - var index: T.Index = index, overflow: Bool = overflow - NBK.decrementUnsignedInteger(&limbs, by: subtrahend, at: &index, borrowing: &overflow) - return IO(index: index as T.Index, overflow: overflow as Bool) - } - - @_transparent public static func decrementUnsignedIntegerInIntersection( - _ limbs: inout T, by subtrahend: T.Element, plus overflow: Bool, at index: T.Index) -> IO - where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - var index: T.Index = index, overflow: Bool = overflow - NBK.decrementUnsignedIntegerInIntersection(&limbs, by: subtrahend, at: &index, borrowing: &overflow) - return IO(index: index as T.Index, overflow: overflow as Bool) - } - - //=------------------------------------------------------------------------= - // MARK: Transformations x Inout - //=------------------------------------------------------------------------= - - @inlinable public static func decrementUnsignedInteger( - _ limbs: inout T, by subtrahend: T.Element, at index: inout T.Index, borrowing overflow: inout Bool) - where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - NBK.decrementUnsignedIntegerInIntersection(&limbs, by: subtrahend, at: &index, borrowing: &overflow) - NBK.decrementUnsignedInteger(&limbs, by: Void(), at: &index, borrowing: &overflow) - } - - @inlinable public static func decrementUnsignedIntegerInIntersection( - _ limbs: inout T, by subtrahend: T.Element, at index: inout T.Index, borrowing overflow: inout Bool) - where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - var subtrahend: T.Element = subtrahend - - if overflow { - overflow = subtrahend.addReportingOverflow(1 as T.Element.Digit) - } - - if !overflow { - overflow = limbs[index].subtractReportingOverflow(subtrahend) - } - - limbs.formIndex(after: &index) - } -} - -//*============================================================================* -// MARK: * NBK x Subtraction x Bool -//*============================================================================* - -extension NBK { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @_transparent public static func decrementUnsignedInteger( - _ limbs: inout T, by subtrahend: Bool, at index: T.Index) -> IO - where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - var index: T.Index = index, overflow: Bool = subtrahend - NBK.decrementUnsignedInteger(&limbs, by: Void(), at: &index, borrowing: &overflow) - return IO(index: index as T.Index, overflow: overflow as Bool) - } - - //=------------------------------------------------------------------------= - // MARK: Transformations x Inout - //=------------------------------------------------------------------------= - - @inlinable public static func decrementUnsignedInteger( - _ limbs: inout T, by subtrahend: Void, at index: inout T.Index, borrowing overflow: inout Bool) - where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - while overflow && index < limbs.endIndex { - overflow = limbs[index].subtractReportingOverflow(1 as T.Element.Digit) - limbs.formIndex(after: &index) - } - } -} - -//*============================================================================* -// MARK: * NBK x Subtraction x Product -//*============================================================================* - -extension NBK { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @_transparent public static func decrementUnsignedInteger( - _ limbs: inout T, by other: T, times multiplicand: T.Element, plus subtrahend: T.Element, - and overflow: Bool, at index: T.Index) -> IO - where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - var index: T.Index = index, overflow: Bool = overflow - NBK.decrementUnsignedInteger(&limbs, by: other, times: multiplicand, plus: subtrahend, at: &index, borrowing: &overflow) - return IO(index: index as T.Index, overflow: overflow as Bool) - } - - //=------------------------------------------------------------------------= - // MARK: Transformations x Inout - //=------------------------------------------------------------------------= - - @inlinable public static func decrementUnsignedInteger( - _ limbs: inout T, by other: T, times multiplicand: T.Element, plus subtrahend: T.Element, - at index: inout T.Index, borrowing overflow: inout Bool) - where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - var last: T.Element = subtrahend - - for otherIndex in other.indices { - var subproduct = other[otherIndex].multipliedFullWidth(by: multiplicand) - last = T.Element(bit: subproduct.low.addReportingOverflow(last)) &+ subproduct.high - NBK.decrementUnsignedIntegerInIntersection(&limbs, by: subproduct.low, at: &index, borrowing: &overflow) - } - - NBK.decrementUnsignedInteger(&limbs, by: last, at: &index, borrowing: &overflow) - } -} diff --git a/Tests/NBKResizableWidthKitTests/Private/NBK+Limbs+Addition.swift b/Tests/NBKResizableWidthKitTests/Private/NBK+Limbs+Addition.swift new file mode 100644 index 00000000..314e51a8 --- /dev/null +++ b/Tests/NBKResizableWidthKitTests/Private/NBK+Limbs+Addition.swift @@ -0,0 +1,142 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Limbs x Addition x Unsigned +//*============================================================================* + +final class NBKTestsOnLimbsByAdditionAsUnsigned: XCTestCase { + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testAddingAtIndex() { + NBKAssertAdditionAtIndex([~0, ~1, ~2, ~3] as W, [3, 0, 0, 0] as W, Int(0), [ 2, ~0, ~2, ~3] as W) + NBKAssertAdditionAtIndex([~0, ~1, ~2, ~3] as W, [0, 3, 0, 0] as W, Int(0), [~0, 1, ~1, ~3] as W) + NBKAssertAdditionAtIndex([~0, ~1, ~2, ~3] as W, [0, 0, 3, 0] as W, Int(0), [~0, ~1, 0, ~2] as W) + NBKAssertAdditionAtIndex([~0, ~1, ~2, ~3] as W, [0, 0, 0, 3] as W, Int(0), [~0, ~1, ~2, ~0] as W) + + NBKAssertAdditionAtIndex([~0, ~1, ~2, ~3] as W, [0, 0, 0, 3] as W, Int(0), [~0, ~1, ~2, ~0] as W) + NBKAssertAdditionAtIndex([~0, ~1, ~2, ~3] as W, [0, 0, 3 ] as W, Int(1), [~0, ~1, ~2, ~0] as W) + NBKAssertAdditionAtIndex([~0, ~1, ~2, ~3] as W, [0, 3 ] as W, Int(2), [~0, ~1, ~2, ~0] as W) + NBKAssertAdditionAtIndex([~0, ~1, ~2, ~3] as W, [3 ] as W, Int(3), [~0, ~1, ~2, ~0] as W) + } + + func testAddingAtIndexReportingOverflow() { + NBKAssertAdditionAtIndex([~0, ~0, ~0, ~0] as W, [0, 0, 0, 0] as W, Int(0), [~0, ~0, ~0, ~0] as W) + NBKAssertAdditionAtIndex([~0, ~0, ~0, ~0] as W, [1, 0, 0, 0] as W, Int(0), [ 0, 0, 0, 0] as W, true) + + NBKAssertAdditionAtIndex([~3, ~2, ~1, ~0] as W, [4, 0, 0, 0] as W, Int(0), [ 0, ~1, ~1, ~0] as W) + NBKAssertAdditionAtIndex([~3, ~2, ~1, ~0] as W, [4, 0, 0 ] as W, Int(1), [~3, 1, ~0, ~0] as W) + NBKAssertAdditionAtIndex([~3, ~2, ~1, ~0] as W, [4, 0 ] as W, Int(2), [~3, ~2, 2, 0] as W, true) + NBKAssertAdditionAtIndex([~3, ~2, ~1, ~0] as W, [4 ] as W, Int(3), [~3, ~2, ~1, 3] as W, true) + + NBKAssertAdditionAtIndex([~3, ~2, ~1, ~0] as W, [4, 0, 0, 0] as W, Int(0), [ 0, ~1, ~1, ~0] as W) + NBKAssertAdditionAtIndex([~3, ~2, ~1, ~0] as W, [0, 4, 0, 0] as W, Int(0), [~3, 1, ~0, ~0] as W) + NBKAssertAdditionAtIndex([~3, ~2, ~1, ~0] as W, [0, 0, 4, 0] as W, Int(0), [~3, ~2, 2, 0] as W, true) + NBKAssertAdditionAtIndex([~3, ~2, ~1, ~0] as W, [0, 0, 0, 4] as W, Int(0), [~3, ~2, ~1, 3] as W, true) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Digit + //=------------------------------------------------------------------------= + + func testAddingDigitAtIndex() { + NBKAssertAdditionByDigitAtIndex([ 0, 0, 0, 0] as W, UInt(3), Int(0), [ 3, 0, 0, 0] as W) + NBKAssertAdditionByDigitAtIndex([~0, 0, 0, 0] as W, UInt(3), Int(0), [ 2, 1, 0, 0] as W) + NBKAssertAdditionByDigitAtIndex([~0, ~0, 0, 0] as W, UInt(3), Int(0), [ 2, 0, 1, 0] as W) + NBKAssertAdditionByDigitAtIndex([~0, ~0, ~0, 0] as W, UInt(3), Int(0), [ 2, 0, 0, 1] as W) + + NBKAssertAdditionByDigitAtIndex([ 0, 0, 0, 0] as W, UInt(3), Int(1), [ 0, 3, 0, 0] as W) + NBKAssertAdditionByDigitAtIndex([~0, 0, 0, 0] as W, UInt(3), Int(1), [~0, 3, 0, 0] as W) + NBKAssertAdditionByDigitAtIndex([~0, ~0, 0, 0] as W, UInt(3), Int(1), [~0, 2, 1, 0] as W) + NBKAssertAdditionByDigitAtIndex([~0, ~0, ~0, 0] as W, UInt(3), Int(1), [~0, 2, 0, 1] as W) + } + + func testAddingDigitAtIndexReportingOverflow() { + NBKAssertAdditionByDigitAtIndex([~0, ~0, ~0, ~0] as W, UInt(0), Int(0), [~0, ~0, ~0, ~0] as W) + NBKAssertAdditionByDigitAtIndex([~0, ~0, ~0, ~0] as W, UInt(1), Int(0), [ 0, 0, 0, 0] as W, true) + + NBKAssertAdditionByDigitAtIndex([~3, ~2, ~1, ~0] as W, UInt(4), Int(0), [ 0, ~1, ~1, ~0] as W) + NBKAssertAdditionByDigitAtIndex([~3, ~2, ~1, ~0] as W, UInt(4), Int(1), [~3, 1, ~0, ~0] as W) + NBKAssertAdditionByDigitAtIndex([~3, ~2, ~1, ~0] as W, UInt(4), Int(2), [~3, ~2, 2, 0] as W, true) + NBKAssertAdditionByDigitAtIndex([~3, ~2, ~1, ~0] as W, UInt(4), Int(3), [~3, ~2, ~1, 3] as W, true) + } +} + +//*============================================================================* +// MARK: * NBK x Limbs x Addition x Assertions +//*============================================================================* + +private func NBKAssertAdditionAtIndex( +_ lhs: [UInt], _ rhs: [UInt], _ index: Int, _ product: [UInt], _ overflow: Bool = false, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + brr: do { + var lhs = lhs + let max = NBK.incrementSufficientUnsignedInteger(&lhs, by: rhs, at: index, carrying: false) + XCTAssertEqual(lhs, product, file: file, line: line) + XCTAssertEqual(max.overflow, overflow, file: file, line: line) + } + + brr: do { + var lhs = lhs + let min = NBK.incrementSufficientUnsignedIntegerInIntersection(&lhs, by: rhs, at: index, carrying: false) + let max = NBK.incrementSufficientUnsignedInteger(&lhs, by: Void(), at: min.index, carrying: min.overflow) + XCTAssertEqual(lhs, product, file: file, line: line) + XCTAssertEqual(max.overflow, overflow, file: file, line: line) + } +} + +private func NBKAssertAdditionByDigitAtIndex( +_ lhs: [UInt], _ rhs: UInt, _ index: Int, _ product: [UInt], _ overflow: Bool = false, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + brr: do { + var lhs = lhs + let max = NBK.incrementSufficientUnsignedInteger(&lhs, by: rhs, at: index) + XCTAssertEqual(lhs, product, file: file, line: line) + XCTAssertEqual(max.overflow, overflow, file: file, line: line) + } + + brr: do { + var lhs = lhs + let min = NBK.incrementSufficientUnsignedIntegerInIntersection(&lhs, by: rhs, at: index) + let max = NBK.incrementSufficientUnsignedInteger(&lhs, by: Void(), at: min.index, carrying: min.overflow) + XCTAssertEqual(lhs, product, file: file, line: line) + XCTAssertEqual(max.overflow, overflow, file: file, line: line) + } + //=------------------------------------------= + brr: do { + var lhs = lhs + let max = NBK.incrementSufficientUnsignedInteger(&lhs, by: rhs, at: index, carrying: false) + XCTAssertEqual(lhs, product, file: file, line: line) + XCTAssertEqual(max.overflow, overflow, file: file, line: line) + } + + brr: do { + var lhs = lhs + let min = NBK.incrementSufficientUnsignedIntegerInIntersection(&lhs, by: rhs, at: index, carrying: false) + let max = NBK.incrementSufficientUnsignedInteger(&lhs, by: Void(), at: min.index, carrying: min.overflow) + XCTAssertEqual(lhs, product, file: file, line: line) + XCTAssertEqual(max.overflow, overflow, file: file, line: line) + } +} + +#endif diff --git a/Tests/NBKResizableWidthKitTests/Private/NBK+Limbs+Subtraction.swift b/Tests/NBKResizableWidthKitTests/Private/NBK+Limbs+Subtraction.swift new file mode 100644 index 00000000..ba8ac091 --- /dev/null +++ b/Tests/NBKResizableWidthKitTests/Private/NBK+Limbs+Subtraction.swift @@ -0,0 +1,142 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Limbs x Subtraction x Unsigned +//*============================================================================* + +final class NBKTestsOnLimbsBySubtractionAsUnsigned: XCTestCase { + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testSubtractingAtIndex() { + NBKAssertSubtractionAtIndex([ 0, 1, 2, 3] as W, [3, 0, 0, 0] as W, Int(0), [~2, 0, 2, 3] as W) + NBKAssertSubtractionAtIndex([ 0, 1, 2, 3] as W, [0, 3, 0, 0] as W, Int(0), [ 0, ~1, 1, 3] as W) + NBKAssertSubtractionAtIndex([ 0, 1, 2, 3] as W, [0, 0, 3, 0] as W, Int(0), [ 0, 1, ~0, 2] as W) + NBKAssertSubtractionAtIndex([ 0, 1, 2, 3] as W, [0, 0, 0, 3] as W, Int(0), [ 0, 1, 2, 0] as W) + + NBKAssertSubtractionAtIndex([ 0, 1, 2, 3] as W, [0, 0, 0, 3] as W, Int(0), [ 0, 1, 2, 0] as W) + NBKAssertSubtractionAtIndex([ 0, 1, 2, 3] as W, [0, 0, 3 ] as W, Int(1), [ 0, 1, 2, 0] as W) + NBKAssertSubtractionAtIndex([ 0, 1, 2, 3] as W, [0, 3 ] as W, Int(2), [ 0, 1, 2, 0] as W) + NBKAssertSubtractionAtIndex([ 0, 1, 2, 3] as W, [3 ] as W, Int(3), [ 0, 1, 2, 0] as W) + } + + func testSubtractingAtIndexReportingOverflow() { + NBKAssertSubtractionAtIndex([ 0, 0, 0, 0] as W, [0, 0, 0, 0] as W, Int(0), [ 0, 0, 0, 0] as W) + NBKAssertSubtractionAtIndex([ 0, 0, 0, 0] as W, [1, 0, 0, 0] as W, Int(0), [~0, ~0, ~0, ~0] as W, true) + + NBKAssertSubtractionAtIndex([ 3, 2, 1, 0] as W, [4, 0, 0, 0] as W, Int(0), [~0, 1, 1, 0] as W) + NBKAssertSubtractionAtIndex([ 3, 2, 1, 0] as W, [4, 0, 0 ] as W, Int(1), [ 3, ~1, 0, 0] as W) + NBKAssertSubtractionAtIndex([ 3, 2, 1, 0] as W, [4, 0 ] as W, Int(2), [ 3, 2, ~2, ~0] as W, true) + NBKAssertSubtractionAtIndex([ 3, 2, 1, 0] as W, [4 ] as W, Int(3), [ 3, 2, 1, ~3] as W, true) + + NBKAssertSubtractionAtIndex([ 3, 2, 1, 0] as W, [4, 0, 0, 0] as W, Int(0), [~0, 1, 1, 0] as W) + NBKAssertSubtractionAtIndex([ 3, 2, 1, 0] as W, [0, 4, 0, 0] as W, Int(0), [ 3, ~1, 0, 0] as W) + NBKAssertSubtractionAtIndex([ 3, 2, 1, 0] as W, [0, 0, 4, 0] as W, Int(0), [ 3, 2, ~2, ~0] as W, true) + NBKAssertSubtractionAtIndex([ 3, 2, 1, 0] as W, [0, 0, 0, 4] as W, Int(0), [ 3, 2, 1, ~3] as W, true) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Digit + //=------------------------------------------------------------------------= + + func testSubtractingDigitAtIndex() { + NBKAssertSubtractionByDigitAtIndex([~0, ~0, ~0, ~0] as W, UInt(3), Int(0), [~3, ~0, ~0, ~0] as W) + NBKAssertSubtractionByDigitAtIndex([ 0, ~0, ~0, ~0] as W, UInt(3), Int(0), [~2, ~1, ~0, ~0] as W) + NBKAssertSubtractionByDigitAtIndex([ 0, 0, ~0, ~0] as W, UInt(3), Int(0), [~2, ~0, ~1, ~0] as W) + NBKAssertSubtractionByDigitAtIndex([ 0, 0, 0, ~0] as W, UInt(3), Int(0), [~2, ~0, ~0, ~1] as W) + + NBKAssertSubtractionByDigitAtIndex([~0, ~0, ~0, ~0] as W, UInt(3), Int(1), [~0, ~3, ~0, ~0] as W) + NBKAssertSubtractionByDigitAtIndex([ 0, ~0, ~0, ~0] as W, UInt(3), Int(1), [ 0, ~3, ~0, ~0] as W) + NBKAssertSubtractionByDigitAtIndex([ 0, 0, ~0, ~0] as W, UInt(3), Int(1), [ 0, ~2, ~1, ~0] as W) + NBKAssertSubtractionByDigitAtIndex([ 0, 0, 0, ~0] as W, UInt(3), Int(1), [ 0, ~2, ~0, ~1] as W) + } + + func testSubtractingDigitAtIndexReportingOverflow() { + NBKAssertSubtractionByDigitAtIndex([ 0, 0, 0, 0] as W, UInt(0), Int(0), [ 0, 0, 0, 0] as W) + NBKAssertSubtractionByDigitAtIndex([ 0, 0, 0, 0] as W, UInt(1), Int(0), [~0, ~0, ~0, ~0] as W, true) + + NBKAssertSubtractionByDigitAtIndex([ 3, 2, 1, 0] as W, UInt(4), Int(0), [~0, 1, 1, 0] as W) + NBKAssertSubtractionByDigitAtIndex([ 3, 2, 1, 0] as W, UInt(4), Int(1), [ 3, ~1, 0, 0] as W) + NBKAssertSubtractionByDigitAtIndex([ 3, 2, 1, 0] as W, UInt(4), Int(2), [ 3, 2, ~2, ~0] as W, true) + NBKAssertSubtractionByDigitAtIndex([ 3, 2, 1, 0] as W, UInt(4), Int(3), [ 3, 2, 1, ~3] as W, true) + } +} + +//*============================================================================* +// MARK: * NBK x Limbs x Subtraction x Assertions +//*============================================================================* + +private func NBKAssertSubtractionAtIndex( +_ lhs: [UInt], _ rhs: [UInt], _ index: Int, _ product: [UInt], _ overflow: Bool = false, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + brr: do { + var lhs = lhs + let max = NBK.decrementSufficientUnsignedInteger(&lhs, by: rhs, at: index, borrowing: false) + XCTAssertEqual(lhs, product, file: file, line: line) + XCTAssertEqual(max.overflow, overflow, file: file, line: line) + } + + brr: do { + var lhs = lhs + let min = NBK.decrementSufficientUnsignedIntegerInIntersection(&lhs, by: rhs, at: index, borrowing: false) + let max = NBK.decrementSufficientUnsignedInteger(&lhs, by: Void(), at: min.index, borrowing: min.overflow) + XCTAssertEqual(lhs, product, file: file, line: line) + XCTAssertEqual(max.overflow, overflow, file: file, line: line) + } +} + +private func NBKAssertSubtractionByDigitAtIndex( +_ lhs: [UInt], _ rhs: UInt, _ index: Int, _ product: [UInt], _ overflow: Bool = false, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + brr: do { + var lhs = lhs + let max = NBK.decrementSufficientUnsignedInteger(&lhs, by: rhs, at: index) + XCTAssertEqual(lhs, product, file: file, line: line) + XCTAssertEqual(max.overflow, overflow, file: file, line: line) + } + + brr: do { + var lhs = lhs + let min = NBK.decrementSufficientUnsignedIntegerInIntersection(&lhs, by: rhs, at: index) + let max = NBK.decrementSufficientUnsignedInteger(&lhs, by: Void(), at: min.index, borrowing: min.overflow) + XCTAssertEqual(lhs, product, file: file, line: line) + XCTAssertEqual(max.overflow, overflow, file: file, line: line) + } + //=------------------------------------------= + brr: do { + var lhs = lhs + let max = NBK.decrementSufficientUnsignedInteger(&lhs, by: rhs, at: index, borrowing: false) + XCTAssertEqual(lhs, product, file: file, line: line) + XCTAssertEqual(max.overflow, overflow, file: file, line: line) + } + + brr: do { + var lhs = lhs + let min = NBK.decrementSufficientUnsignedIntegerInIntersection(&lhs, by: rhs, at: index, borrowing: false) + let max = NBK.decrementSufficientUnsignedInteger(&lhs, by: Void(), at: min.index, borrowing: min.overflow) + XCTAssertEqual(lhs, product, file: file, line: line) + XCTAssertEqual(max.overflow, overflow, file: file, line: line) + } +} + +#endif From dcceac44a3716e880be2c3b0e7d0380ddb7128ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Fri, 11 Aug 2023 09:38:59 +0200 Subject: [PATCH 059/133] NBKResizableWidthKit: Addition, Subtraction. --- .../NBKFlexibleWidth+Division.swift | 2 +- .../NBKResizableWidth+Addition+Digit.swift | 2 +- .../NBKResizableWidth+Addition.swift | 2 +- .../NBKResizableWidth+Subtraction+Digit.swift | 4 +- .../NBKResizableWidth+Subtraction.swift | 8 +- .../Private/NBK+Limbs+Addition.swift | 244 ++++++++-------- .../Private/NBK+Limbs+Subtraction.swift | 261 +++++++++--------- .../Private/NBK+Limbs+Addition.swift | 16 +- .../Private/NBK+Limbs+Subtraction.swift | 16 +- 9 files changed, 294 insertions(+), 261 deletions(-) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift index 99248680..0ed355eb 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift @@ -160,7 +160,7 @@ extension NBKFlexibleWidth.Magnitude { } //=------------------------------= if !digit.isZero { - var overflow = self.storage.subtract(divisor, times: digit, plus: UInt.zero, at: quotientIndex) + var overflow = self.storage.subtract(divisor, times: digit, plus: UInt.zero, plus: false, at: quotientIndex) decrement: while overflow { _ = digit.subtractReportingOverflow(1 as UInt) overflow = !self.storage.add(divisor, plus: false, at: quotientIndex) diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition+Digit.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition+Digit.swift index 6c53965a..a7d952e0 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition+Digit.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition+Digit.swift @@ -33,6 +33,6 @@ extension NBKResizableWidth.Magnitude { // TODO: rename @_disfavoredOverload @inlinable public mutating func add(_ other: UInt, plus carry: Bool, at index: Int) -> Bool { - NBK.incrementSufficientUnsignedInteger(&self, by: other, at: index, carrying: carry).overflow + NBK.incrementSufficientUnsignedInteger(&self, by: other, plus: carry, at: index).overflow } } diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition.swift index 6686bbc9..03e448e9 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition.swift @@ -33,6 +33,6 @@ extension NBKResizableWidth.Magnitude { // TODO: rename @inlinable public mutating func add(_ other: Self, plus carry: Bool, at index: Int) -> Bool { - NBK.incrementSufficientUnsignedInteger(&self, by: other, at: index, carrying: carry).overflow + NBK.incrementSufficientUnsignedInteger(&self, by: other, plus: carry, at: index).overflow } } diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction+Digit.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction+Digit.swift index daa6d855..9744ffc9 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction+Digit.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction+Digit.swift @@ -44,7 +44,7 @@ extension NBKResizableWidth.Magnitude { //=------------------------------------------------------------------------= // TODO: rename - @_disfavoredOverload @inlinable public mutating func subtract(_ other: UInt, plus subtrahend: Bool, at index: Int) -> Bool { - NBK.decrementSufficientUnsignedInteger(&self, by: other, at: index, borrowing: subtrahend).overflow + @_disfavoredOverload @inlinable public mutating func subtract(_ other: UInt, plus borrow: Bool, at index: Int) -> Bool { + NBK.decrementSufficientUnsignedInteger(&self, by: other, plus: borrow, at: index).overflow } } diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction.swift b/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction.swift index 0de611a6..45d64738 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction.swift +++ b/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction.swift @@ -44,12 +44,12 @@ extension NBKResizableWidth.Magnitude { //=------------------------------------------------------------------------= // TODO: rename - @inlinable public mutating func subtract(_ other: Self, plus subtrahend: Bool, at index: Int) -> Bool { - NBK.decrementSufficientUnsignedInteger(&self, by: other, at: index, borrowing: subtrahend).overflow + @inlinable public mutating func subtract(_ other: Self, plus borrow: Bool, at index: Int) -> Bool { + NBK.decrementSufficientUnsignedInteger(&self, by: other, plus: borrow, at: index).overflow } // TODO: rename - @inlinable public mutating func subtract(_ other: Self, times multiplicand: UInt, plus subtrahend: UInt, at index: Int) -> Bool { - NBK.decrementSufficientUnsignedInteger(&self, by: other, times: multiplicand, plus: subtrahend, at: index, borrowing: false).overflow + @inlinable public mutating func subtract(_ other: Self, times multiplicand: UInt, plus subtrahend: UInt, plus borrow: Bool, at index: Int) -> Bool { + NBK.decrementSufficientUnsignedInteger(&self, by: other, times: multiplicand, plus: subtrahend, plus: borrow, at: index).overflow } } diff --git a/Sources/NBKResizableWidthKit/Private/NBK+Limbs+Addition.swift b/Sources/NBKResizableWidthKit/Private/NBK+Limbs+Addition.swift index 0e65b7c5..f97a1fb6 100644 --- a/Sources/NBKResizableWidthKit/Private/NBK+Limbs+Addition.swift +++ b/Sources/NBKResizableWidthKit/Private/NBK+Limbs+Addition.swift @@ -9,8 +9,10 @@ import NBKCoreKit +//=----------------------------------------------------------------------------= +// TODO: see whether consuming arguments removes need for inout versions in 5.9 //*============================================================================* -// MARK: * NBK x Limbs x Addition +// MARK: * NBK x Limbs x Addition x Limbs //*============================================================================* extension NBK { @@ -19,60 +21,64 @@ extension NBK { // MARK: Transformations //=------------------------------------------------------------------------= - /// Increments `limbs` by the sum of `addend` and `overflow` at `index`. + /// Increments `pointee` by the sum of `limbs` and `bit` at `index`. /// - /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// - This operation must not overflow the `pointee` subsequence by more than one bit. /// - /// - Returns: An overflow indicator and its index in `limbs`. + /// - Returns: An overflow indicator and its index in `pointee`. /// - @_transparent public static func incrementSufficientUnsignedInteger( - _ limbs: inout T, by addend: T, at index: T.Index, carrying overflow: Bool) -> IO - where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - var index: T.Index = index, overflow: Bool = overflow - NBK.incrementSufficientUnsignedInteger(&limbs, by: addend, at: &index, carrying: &overflow) - return IO(index: index as T.Index, overflow: overflow as Bool) + @inlinable public static func incrementSufficientUnsignedInteger( + _ pointee: inout T, by limbs: T, plus bit: Bool, at index: T.Index) -> IO + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + var index: T.Index = index, bit: Bool = bit + NBK.incrementSufficientUnsignedInteger(&pointee, by: limbs, plus: &bit, at: &index) + return IO(index: index as T.Index, overflow: bit as Bool) } - /// Partially increments `limbs` by the sum of `addend` and `overflow` at `index`. + /// Partially increments `pointee` by the sum of `digit` and `bit` at `index`. /// /// - This operation does not continue beyond the operand intersection. - /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// - This operation must not overflow the `pointee` subsequence by more than one bit. /// - /// - Returns: An overflow indicator and its index in `limbs`. + /// - Returns: An overflow indicator and its index in `pointee`. /// - @_transparent public static func incrementSufficientUnsignedIntegerInIntersection( - _ limbs: inout T, by addend: T, at index: T.Index, carrying overflow: Bool) -> IO - where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - var index: T.Index = index, overflow: Bool = overflow - NBK.incrementSufficientUnsignedInteger(&limbs, by: addend, at: &index, carrying: &overflow) - return IO(index: index as T.Index, overflow: overflow as Bool) + @inlinable public static func incrementSufficientUnsignedIntegerInIntersection( + _ pointee: inout T, by limbs: T, plus bit: Bool, at index: T.Index) -> IO + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + var index: T.Index = index, bit: Bool = bit + NBK.incrementSufficientUnsignedIntegerInIntersection(&pointee, by: limbs, plus: &bit, at: &index) + return IO(index: index as T.Index, overflow: bit as Bool) } //=------------------------------------------------------------------------= // MARK: Transformations x Inout //=------------------------------------------------------------------------= - /// Increments `limbs` by the sum of `addend` and `overflow` at `index`. + /// Increments `pointee` by the sum of `limbs` and `bit` at `index`. /// - /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// - This operation must not overflow the `pointee` subsequence by more than one bit. + /// + /// - Returns: An overflow indicator and its index in `pointee`. /// @inlinable public static func incrementSufficientUnsignedInteger( - _ limbs: inout T, by addend: T, at index: inout T.Index, carrying overflow: inout Bool) - where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - NBK.incrementSufficientUnsignedIntegerInIntersection(&limbs, by: addend, at: &index, carrying: &overflow) - NBK.incrementSufficientUnsignedInteger(&limbs, by: Void(), at: &index, carrying: &overflow) + _ pointee: inout T, by limbs: T, plus bit: inout Bool, at index: inout T.Index) + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + NBK.incrementSufficientUnsignedIntegerInIntersection(&pointee, by: limbs, plus: &bit, at: &index) + NBK.incrementSufficientUnsignedInteger(&pointee, by: &bit, at: &index) } - /// Partially increments `limbs` by the sum of `addend` and `overflow` at `index`. + /// Partially increments `pointee` by the sum of `digit` and `bit` at `index`. /// /// - This operation does not continue beyond the operand intersection. - /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// - This operation must not overflow the `pointee` subsequence by more than one bit. + /// + /// - Returns: An overflow indicator and its index in `pointee`. /// @inlinable public static func incrementSufficientUnsignedIntegerInIntersection( - _ limbs: inout T, by addend: T, at index: inout T.Index, carrying overflow: inout Bool) - where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - for addendIndex in addend.indices { // for-index-in >= for-element-in - NBK.incrementSufficientUnsignedIntegerInIntersection(&limbs, by: addend[addendIndex], at: &index, carrying: &overflow) + _ pointee: inout T, by limbs: T, plus bit: inout Bool, at index: inout T.Index) + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + for limbsIndex in limbs.indices { + NBK.incrementSufficientUnsignedIntegerInIntersection(&pointee, by: limbs[limbsIndex], plus: &bit, at: &index) } } } @@ -87,68 +93,70 @@ extension NBK { // MARK: Transformations //=------------------------------------------------------------------------= - /// Increments `limbs` by `addend` at `index`. + /// Increments `pointee` by `digit` at `index`. /// - /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// - This operation must not overflow the `pointee` subsequence by more than one bit. /// - /// - Returns: An overflow indicator and its index in `limbs`. + /// - Returns: An overflow indicator and its index in `pointee`. /// - @_transparent public static func incrementSufficientUnsignedInteger( - _ limbs: inout T, by addend: T.Element, at index: T.Index) -> IO - where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - let (index, overflow) = NBK.incrementSufficientUnsignedIntegerInIntersection(&limbs, by: addend, at: index) - return NBK.incrementSufficientUnsignedInteger(&limbs, by: Void(), at: index, carrying: overflow) as IO + @_transparent @discardableResult public static func incrementSufficientUnsignedInteger( + _ pointee: inout T, by digit: T.Element, at index: T.Index) -> IO + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + var index: T.Index = index, bit: Bool + bit = NBK.incrementSufficientUnsignedInteger(&pointee, by: digit, at: &index) + return IO(index as T.Index, overflow: bit as Bool) } - /// Partially increments `limbs` by `addend` at `index`. + /// Partially increments `pointee` by `digit` at `index`. /// /// - This operation does not continue beyond the operand intersection. - /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// - This operation must not overflow the `pointee` subsequence by more than one bit. /// - /// - Returns: An overflow indicator and its index in `limbs`. + /// - Returns: An overflow indicator and its index in `pointee`. /// - @_transparent public static func incrementSufficientUnsignedIntegerInIntersection( - _ limbs: inout T, by addend: T.Element, at index: T.Index) -> IO - where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - let overflow = limbs[index].addReportingOverflow(addend) - return IO(limbs.index(after: index), overflow) + @_transparent @discardableResult public static func incrementSufficientUnsignedIntegerInIntersection( + _ pointee: inout T, by digit: T.Element, at index: T.Index) -> IO + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + var index: T.Index = index, bit: Bool + bit = NBK.incrementSufficientUnsignedIntegerInIntersection(&pointee, by: digit, at: &index) + return IO(index as T.Index, overflow: bit as Bool) } //=------------------------------------------------------------------------= // MARK: Transformations x Inout //=------------------------------------------------------------------------= - /// Increments `limbs` by `addend` at `index`. + /// Increments `pointee` by `digit` at `index`. /// - /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// - This operation must not overflow the `pointee` subsequence by more than one bit. /// - /// - Returns: An overflow indicator. + /// - Returns: An overflow indicator and its index in `pointee`. /// @inlinable public static func incrementSufficientUnsignedInteger( - _ limbs: inout T, by addend: T.Element, at index: inout T.Index) -> Bool - where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - var overflow = NBK.incrementSufficientUnsignedIntegerInIntersection(&limbs, by: addend, at: &index) - NBK.incrementSufficientUnsignedInteger(&limbs, by: Void(), at: &index, carrying: &overflow) - return overflow as Bool + _ pointee: inout T, by digit: T.Element, at index: inout T.Index) -> Bool + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + var bit = NBK.incrementSufficientUnsignedIntegerInIntersection(&pointee, by: digit, at: &index) + NBK.incrementSufficientUnsignedInteger(&pointee, by: &bit, at: &index) + return bit as Bool } - /// Partially increments `limbs` by `addend` at `index`. + /// Partially increments `pointee` by `digit` at `index`. /// /// - This operation does not continue beyond the operand intersection. - /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// - This operation must not overflow the `pointee` subsequence by more than one bit. /// - /// - Returns: An overflow indicator. + /// - Returns: An overflow indicator and its index in `pointee`. /// @inlinable public static func incrementSufficientUnsignedIntegerInIntersection( - _ limbs: inout T, by addend: T.Element, at index: inout T.Index) -> Bool - where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - defer{ limbs.formIndex(after: &index) } - return limbs[index].addReportingOverflow(addend) + _ pointee: inout T, by digit: T.Element, at index: inout T.Index) -> Bool + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + defer{ pointee.formIndex(after: &index) } + return pointee[index].addReportingOverflow(digit) } } //*============================================================================* -// MARK: * NBK x Limbs x Addition x Digit x Carry +// MARK: * NBK x Limbs x Addition x Digit + Bit //*============================================================================* extension NBK { @@ -157,74 +165,78 @@ extension NBK { // MARK: Transformations //=------------------------------------------------------------------------= - /// Increments `limbs` by the sum of `addend` and `overflow` at `index`. + /// Increments `pointee` by the sum of `digit` and `bit` at `index`. /// - /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// - This operation must not overflow the `pointee` subsequence by more than one bit. /// - /// - Returns: An overflow indicator and its index in `limbs`. + /// - Returns: An overflow indicator and its index in `pointee`. /// - @_transparent public static func incrementSufficientUnsignedInteger( - _ limbs: inout T, by addend: T.Element, at index: T.Index, carrying overflow: Bool) -> IO - where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - var index: T.Index = index, overflow: Bool = overflow - NBK.incrementSufficientUnsignedInteger(&limbs, by: addend, at: &index, carrying: &overflow) - return IO(index: index as T.Index, overflow: overflow as Bool) + @_transparent @discardableResult public static func incrementSufficientUnsignedInteger( + _ pointee: inout T, by digit: T.Element, plus bit: Bool, at index: T.Index) -> IO + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + var index: T.Index = index, bit: Bool = bit + NBK.incrementSufficientUnsignedInteger(&pointee, by: digit, plus: &bit, at: &index) + return IO(index: index as T.Index, overflow: bit as Bool) } - /// Partially increments `limbs` by the sum of `addend` and `overflow` at `index`. + /// Partially increments `pointee` by the sum of `digit` and `bit` at `index`. /// /// - This operation does not continue beyond the operand intersection. - /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// - This operation must not overflow the `pointee` subsequence by more than one bit. /// - /// - Returns: An overflow indicator and its index in `limbs`. + /// - Returns: An overflow indicator and its index in `pointee`. /// - @_transparent public static func incrementSufficientUnsignedIntegerInIntersection( - _ limbs: inout T, by addend: T.Element, at index: T.Index, carrying overflow: Bool) -> IO - where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - var index: T.Index = index, overflow: Bool = overflow - NBK.incrementSufficientUnsignedIntegerInIntersection(&limbs, by: addend, at: &index, carrying: &overflow) - return IO(index: index as T.Index, overflow: overflow as Bool) + @_transparent @discardableResult public static func incrementSufficientUnsignedIntegerInIntersection( + _ pointee: inout T, by digit: T.Element, plus bit: Bool, at index: T.Index) -> IO + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + var index: T.Index = index, bit: Bool = bit, digit: T.Element = digit + NBK.incrementSufficientUnsignedIntegerInIntersection(&pointee, by: digit, plus: &bit, at: &index) + return IO(index: index as T.Index, overflow: bit as Bool) } //=------------------------------------------------------------------------= // MARK: Transformations x Inout //=------------------------------------------------------------------------= - /// Increments `limbs` by the sum of `addend` and `overflow` at `index`. + /// Increments `pointee` by the sum of `digit` and `bit` at `index`. /// - /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// - This operation must not overflow the `pointee` subsequence by more than one bit. + /// + /// - Returns: An overflow indicator and its index in `pointee`. /// @inlinable public static func incrementSufficientUnsignedInteger( - _ limbs: inout T, by addend: T.Element, at index: inout T.Index, carrying overflow: inout Bool) - where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - NBK.incrementSufficientUnsignedIntegerInIntersection(&limbs, by: addend, at: &index, carrying: &overflow) - NBK.incrementSufficientUnsignedInteger(&limbs, by: Void(), at: &index, carrying: &overflow) + _ pointee: inout T, by digit: T.Element, plus bit: inout Bool, at index: inout T.Index) + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + NBK.incrementSufficientUnsignedIntegerInIntersection(&pointee, by: digit, plus: &bit, at: &index) + NBK.incrementSufficientUnsignedInteger(&pointee, by: &bit, at: &index) } - /// Partially increments `limbs` by the sum of `addend` and `overflow` at `index`. + /// Partially increments `pointee` by the sum of `digit` and `bit` at `index`. /// /// - This operation does not continue beyond the operand intersection. - /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// - This operation must not overflow the `pointee` subsequence by more than one bit. + /// + /// - Returns: An overflow indicator and its index in `pointee`. /// @inlinable public static func incrementSufficientUnsignedIntegerInIntersection( - _ limbs: inout T, by addend: T.Element, at index: inout T.Index, carrying overflow: inout Bool) - where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - var addend: T.Element = addend + _ pointee: inout T, by digit: T.Element, plus bit: inout Bool, at index: inout T.Index) + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + var digit: T.Element = digit - if overflow { - overflow = addend.addReportingOverflow(1 as T.Element.Digit) + if bit { + bit = digit.addReportingOverflow(1 as T.Element.Digit) } - if !overflow { - overflow = limbs[index].addReportingOverflow(addend) + if !bit { + bit = pointee[index].addReportingOverflow(digit) } - limbs.formIndex(after: &index) + pointee.formIndex(after: &index) } } //*============================================================================* -// MARK: * NBK x Limbs x Addition x Void +// MARK: * NBK x Limbs x Addition x Bit //*============================================================================* extension NBK { @@ -233,34 +245,36 @@ extension NBK { // MARK: Transformations //=------------------------------------------------------------------------= - /// Increments `limbs` by the sum of `addend` and `overflow` at `index`. + /// Increments `pointee` by `bit` at `index`. /// - /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// - This operation must not overflow the `pointee` subsequence by more than one bit. /// - /// - Returns: An overflow indicator and its index in `limbs`. + /// - Returns: An overflow indicator and its index in `pointee`. /// - @_transparent public static func incrementSufficientUnsignedInteger( - _ limbs: inout T, by addend: Void, at index: T.Index, carrying overflow: Bool) -> IO - where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - var index: T.Index = index, overflow: Bool = overflow - NBK.incrementSufficientUnsignedInteger(&limbs, by: addend, at: &index, carrying: &overflow) - return IO(index: index as T.Index, overflow: overflow as Bool) + @_transparent @discardableResult public static func incrementSufficientUnsignedInteger( + _ pointee: inout T, by bit: Bool, at index: T.Index) -> IO + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + var index: T.Index = index, bit: Bool = bit + NBK.incrementSufficientUnsignedInteger(&pointee, by: &bit, at: &index) + return IO(index: index as T.Index, overflow: bit as Bool) } //=------------------------------------------------------------------------= - // MARK: Transformations x Inout + // MARK: Transformationsx x Inout //=------------------------------------------------------------------------= - /// Increments `limbs` by the sum of `addend` and `overflow` at `index`. + /// Increments `pointee` by `bit` at `index`. + /// + /// - This operation must not overflow the `pointee` subsequence by more than one bit. /// - /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// - Returns: An overflow indicator and its index in `pointee`. /// @inlinable public static func incrementSufficientUnsignedInteger( - _ limbs: inout T, by addend: Void, at index: inout T.Index, carrying overflow: inout Bool) - where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - while overflow && index < limbs.endIndex { - overflow = limbs[index].addReportingOverflow(1 as T.Element.Digit) - limbs.formIndex(after: &index) + _ pointee: inout T, by bit: inout Bool, at index: inout T.Index) + where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { + while bit && index < pointee.endIndex { + bit = pointee[index].addReportingOverflow(1 as T.Element.Digit) + pointee.formIndex(after: &index) } } } diff --git a/Sources/NBKResizableWidthKit/Private/NBK+Limbs+Subtraction.swift b/Sources/NBKResizableWidthKit/Private/NBK+Limbs+Subtraction.swift index 61abebbc..66b43ef1 100644 --- a/Sources/NBKResizableWidthKit/Private/NBK+Limbs+Subtraction.swift +++ b/Sources/NBKResizableWidthKit/Private/NBK+Limbs+Subtraction.swift @@ -9,70 +9,76 @@ import NBKCoreKit +//=----------------------------------------------------------------------------= +// TODO: see whether consuming arguments removes need for inout versions in 5.9 //*============================================================================* -// MARK: * NBK x Limbs x Subtraction +// MARK: * NBK x Limbs x Subtraction x Limbs + Bit //*============================================================================* extension NBK { - + //=------------------------------------------------------------------------= // MARK: Transformations //=------------------------------------------------------------------------= - /// Decrements `limbs` by the sum of `subtrahend` and `overflow` at `index`. + /// Decrements `pointee` by the sum of `limbs` and `bit` at `index`. /// - /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// - This operation must not overflow the `pointee` subsequence by more than one bit. /// - /// - Returns: An overflow indicator and its index in `limbs`. + /// - Returns: An overflow indicator and its index in `pointee`. /// - @_transparent public static func decrementSufficientUnsignedInteger( - _ limbs: inout T, by subtrahend: T, at index: T.Index, borrowing overflow: Bool) -> IO + @_transparent @discardableResult public static func decrementSufficientUnsignedInteger( + _ pointee: inout T, by limbs: T, plus bit: Bool, at index: T.Index) -> IO where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - var index: T.Index = index, overflow: Bool = overflow - NBK.decrementSufficientUnsignedInteger(&limbs, by: subtrahend, at: &index, borrowing: &overflow) - return IO(index: index as T.Index, overflow: overflow as Bool) + var index: T.Index = index, bit: Bool = bit + NBK.decrementSufficientUnsignedInteger(&pointee, by: limbs, plus: &bit, at: &index) + return IO(index: index as T.Index, overflow: bit as Bool) } - /// Partially decrements `limbs` by the sum of `subtrahend` and `overflow` at `index`. + /// Partially decrements `pointee` by the sum of `limbs` and `bit` at `index`. /// /// - This operation does not continue beyond the operand intersection. - /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// - This operation must not overflow the `pointee` subsequence by more than one bit. /// - /// - Returns: An overflow indicator and its index in `limbs`. + /// - Returns: An overflow indicator and its index in `pointee`. /// - @_transparent public static func decrementSufficientUnsignedIntegerInIntersection( - _ limbs: inout T, by subtrahend: T, at index: T.Index, borrowing overflow: Bool) -> IO + @_transparent @discardableResult public static func decrementSufficientUnsignedIntegerInIntersection( + _ pointee: inout T, by limbs: T, plus bit: Bool, at index: T.Index) -> IO where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - var index: T.Index = index, overflow: Bool = overflow - NBK.decrementSufficientUnsignedInteger(&limbs, by: subtrahend, at: &index, borrowing: &overflow) - return IO(index: index as T.Index, overflow: overflow as Bool) + var index: T.Index = index, bit: Bool = bit + NBK.decrementSufficientUnsignedIntegerInIntersection(&pointee, by: limbs, plus: &bit, at: &index) + return IO(index: index as T.Index, overflow: bit as Bool) } //=------------------------------------------------------------------------= // MARK: Transformations x Inout //=------------------------------------------------------------------------= - /// Decrements `limbs` by the sum of `subtrahend` and `overflow` at `index`. + /// Decrements `pointee` by the sum of `limbs` and `bit` at `index`. + /// + /// - This operation must not overflow the `pointee` subsequence by more than one bit. /// - /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// - Returns: An overflow indicator and its index in `pointee`. /// @inlinable public static func decrementSufficientUnsignedInteger( - _ limbs: inout T, by subtrahend: T, at index: inout T.Index, borrowing overflow: inout Bool) + _ pointee: inout T, by limbs: T, plus bit: inout Bool, at index: inout T.Index) where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - NBK.decrementSufficientUnsignedIntegerInIntersection(&limbs, by: subtrahend, at: &index, borrowing: &overflow) - NBK.decrementSufficientUnsignedInteger(&limbs, by: Void(), at: &index, borrowing: &overflow) + NBK.decrementSufficientUnsignedIntegerInIntersection(&pointee, by: limbs, plus: &bit, at: &index) + NBK.decrementSufficientUnsignedInteger(&pointee, by: &bit, at: &index) } - /// Partially decrements `limbs` by the sum of `subtrahend` and `overflow` at `index`. + /// Partially decrements `pointee` by the sum of `limbs` and `bit` at `index`. /// /// - This operation does not continue beyond the operand intersection. - /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// - This operation must not overflow the `pointee` subsequence by more than one bit. + /// + /// - Returns: An overflow indicator and its index in `pointee`. /// @inlinable public static func decrementSufficientUnsignedIntegerInIntersection( - _ limbs: inout T, by subtrahend: T, at index: inout T.Index, borrowing overflow: inout Bool) + _ pointee: inout T, by limbs: T, plus bit: inout Bool, at index: inout T.Index) where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - for subtrahendIndex in subtrahend.indices { // for-index-in >= for-element-in - NBK.decrementSufficientUnsignedIntegerInIntersection(&limbs, by: subtrahend[subtrahendIndex], at: &index, borrowing: &overflow) + for limbsIndex in limbs.indices { + NBK.decrementSufficientUnsignedIntegerInIntersection(&pointee, by: limbs[limbsIndex], plus: &bit, at: &index) } } } @@ -82,72 +88,75 @@ extension NBK { //*============================================================================* extension NBK { - + //=------------------------------------------------------------------------= // MARK: Transformations //=------------------------------------------------------------------------= - /// Decrements `limbs` by `subtrahend` at `index`. + /// Decrements `pointee` by `digit` at `index`. /// - /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// - This operation must not overflow the `pointee` subsequence by more than one bit. /// - /// - Returns: An overflow indicator and its index in `limbs`. + /// - Returns: An overflow indicator and its index in `pointee`. /// - @_transparent public static func decrementSufficientUnsignedInteger( - _ limbs: inout T, by subtrahend: T.Element, at index: T.Index) -> IO + @_transparent @discardableResult public static func decrementSufficientUnsignedInteger( + _ pointee: inout T, by digit: T.Element, at index: T.Index) -> IO where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - let (index, overflow) = NBK.decrementSufficientUnsignedIntegerInIntersection(&limbs, by: subtrahend, at: index) - return NBK.decrementSufficientUnsignedInteger(&limbs, by: Void(), at: index, borrowing: overflow) as IO + var index: T.Index = index, bit: Bool + bit = NBK.decrementSufficientUnsignedInteger(&pointee, by: digit, at: &index) + return IO(index as T.Index, overflow: bit as Bool) } - /// Partially decrements `limbs` by `subtrahend` at `index`. + /// Partially decrements `pointee` by `digit` at `index`. /// /// - This operation does not continue beyond the operand intersection. - /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// - This operation must not overflow the `pointee` subsequence by more than one bit. /// - /// - Returns: An overflow indicator and its index in `limbs`. + /// - Returns: An overflow indicator and its index in `pointee`. /// - @_transparent public static func decrementSufficientUnsignedIntegerInIntersection( - _ limbs: inout T, by subtrahend: T.Element, at index: T.Index) -> IO + @_transparent @discardableResult public static func decrementSufficientUnsignedIntegerInIntersection( + _ pointee: inout T, by digit: T.Element, at index: T.Index) -> IO where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - let overflow = limbs[index].subtractReportingOverflow(subtrahend) - return IO(limbs.index(after: index), overflow) + var index: T.Index = index, bit: Bool + bit = NBK.decrementSufficientUnsignedIntegerInIntersection(&pointee, by: digit, at: &index) + return IO(index as T.Index, overflow: bit as Bool) } //=------------------------------------------------------------------------= // MARK: Transformations x Inout //=------------------------------------------------------------------------= - /// Decrements `limbs` by `subtrahend` at `index`. + /// Decrements `pointee` by `digit` at `index`. /// - /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// - This operation must not overflow the `pointee` subsequence by more than one bit. /// - /// - Returns: An overflow indicator. + /// - Returns: An overflow indicator and its index in `pointee`. /// @inlinable public static func decrementSufficientUnsignedInteger( - _ limbs: inout T, by subtrahend: T.Element, at index: inout T.Index) -> Bool + _ pointee: inout T, by digit: T.Element, at index: inout T.Index) -> Bool where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - var overflow = NBK.decrementSufficientUnsignedIntegerInIntersection(&limbs, by: subtrahend, at: &index) - NBK.decrementSufficientUnsignedInteger(&limbs, by: Void(), at: &index, borrowing: &overflow) - return overflow as Bool + var bit = NBK.decrementSufficientUnsignedIntegerInIntersection(&pointee, by: digit, at: &index) + NBK.decrementSufficientUnsignedInteger(&pointee, by: &bit, at: &index) + return bit as Bool } - /// Partially decrements `limbs` by `subtrahend` at `index`. + /// Partially decrements `pointee` by `digit` at `index`. /// - /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// - This operation does not continue beyond the operand intersection. + /// - This operation must not overflow the `pointee` subsequence by more than one bit. /// - /// - Returns: An overflow indicator. + /// - Returns: An overflow indicator and its index in `pointee`. /// @inlinable public static func decrementSufficientUnsignedIntegerInIntersection( - _ limbs: inout T, by subtrahend: T.Element, at index: inout T.Index) -> Bool + _ pointee: inout T, by digit: T.Element, at index: inout T.Index) -> Bool where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - defer{ limbs.formIndex(after: &index) } - return limbs[index].subtractReportingOverflow(subtrahend) + defer{ pointee.formIndex(after: &index) } + return pointee[index].subtractReportingOverflow(digit) } } //*============================================================================* -// MARK: * NBK x Limbs x Subtraction x Digit x Carry +// MARK: * NBK x Limbs x Subtraction x Digit + Bit //*============================================================================* extension NBK { @@ -156,74 +165,78 @@ extension NBK { // MARK: Transformations //=------------------------------------------------------------------------= - /// Decrements `limbs` by the sum of `subtrahend` and `overflow` at `index`. + /// Decrements `pointee` by the sum of `digit` and `bit` at `index`. /// - /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// - This operation must not overflow the `pointee` subsequence by more than one bit. /// - /// - Returns: An overflow indicator and its index in `limbs`. + /// - Returns: An overflow indicator and its index in `pointee`. /// - @_transparent public static func decrementSufficientUnsignedInteger( - _ limbs: inout T, by subtrahend: T.Element, at index: T.Index, borrowing overflow: Bool) -> IO + @_transparent @discardableResult public static func decrementSufficientUnsignedInteger( + _ pointee: inout T, by digit: T.Element, plus bit: Bool, at index: T.Index) -> IO where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - var index: T.Index = index, overflow: Bool = overflow - NBK.decrementSufficientUnsignedInteger(&limbs, by: subtrahend, at: &index, borrowing: &overflow) - return IO(index: index as T.Index, overflow: overflow as Bool) + var index: T.Index = index, bit: Bool = bit + NBK.decrementSufficientUnsignedInteger(&pointee, by: digit, plus: &bit, at: &index) + return IO(index: index as T.Index, overflow: bit as Bool) } - /// Partially decrements `limbs` by the sum of `subtrahend` and `overflow` at `index`. + /// Partially decrements `pointee` by the sum of `digit` and `bit` at `index`. /// /// - This operation does not continue beyond the operand intersection. - /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// - This operation must not overflow the `pointee` subsequence by more than one bit. /// - /// - Returns: An overflow indicator and its index in `limbs`. + /// - Returns: An overflow indicator and its index in `pointee`. /// - @_transparent public static func decrementSufficientUnsignedIntegerInIntersection( - _ limbs: inout T, by subtrahend: T.Element, at index: T.Index, borrowing overflow: Bool) -> IO + @_transparent @discardableResult public static func decrementSufficientUnsignedIntegerInIntersection( + _ pointee: inout T, by digit: T.Element, plus bit: Bool, at index: T.Index) -> IO where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - var index: T.Index = index, overflow: Bool = overflow - NBK.decrementSufficientUnsignedIntegerInIntersection(&limbs, by: subtrahend, at: &index, borrowing: &overflow) - return IO(index: index as T.Index, overflow: overflow as Bool) + var index: T.Index = index, bit: Bool = bit + NBK.decrementSufficientUnsignedIntegerInIntersection(&pointee, by: digit, plus: &bit, at: &index) + return IO(index: index as T.Index, overflow: bit as Bool) } //=------------------------------------------------------------------------= // MARK: Transformations x Inout //=------------------------------------------------------------------------= - /// Decrements `limbs` by the sum of `subtrahend` and `overflow` at `index`. + /// Decrements `pointee` by the sum of `digit` and `bit` at `index`. + /// + /// - This operation must not overflow the `pointee` subsequence by more than one bit. /// - /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// - Returns: An overflow indicator and its index in `pointee`. /// @inlinable public static func decrementSufficientUnsignedInteger( - _ limbs: inout T, by subtrahend: T.Element, at index: inout T.Index, borrowing overflow: inout Bool) + _ pointee: inout T, by digit: T.Element, plus bit: inout Bool, at index: inout T.Index) where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - NBK.decrementSufficientUnsignedIntegerInIntersection(&limbs, by: subtrahend, at: &index, borrowing: &overflow) - NBK.decrementSufficientUnsignedInteger(&limbs, by: Void(), at: &index, borrowing: &overflow) + NBK.decrementSufficientUnsignedIntegerInIntersection(&pointee, by: digit, plus: &bit, at: &index) + NBK.decrementSufficientUnsignedInteger(&pointee, by: &bit, at: &index) } - /// Partially decrements `limbs` by the sum of `subtrahend` and `overflow` at `index`. + /// Partially decrements `pointee` by the sum of `digit` and `bit` at `index`. /// /// - This operation does not continue beyond the operand intersection. - /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// - This operation must not overflow the `pointee` subsequence by more than one bit. + /// + /// - Returns: An overflow indicator and its index in `pointee`. /// @inlinable public static func decrementSufficientUnsignedIntegerInIntersection( - _ limbs: inout T, by subtrahend: T.Element, at index: inout T.Index, borrowing overflow: inout Bool) + _ pointee: inout T, by digit: T.Element, plus bit: inout Bool, at index: inout T.Index) where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - var subtrahend: T.Element = subtrahend - - if overflow { - overflow = subtrahend.addReportingOverflow(1 as T.Element.Digit) + var digit: T.Element = digit + + if bit { + bit = digit.addReportingOverflow(1 as T.Element.Digit) } - if !overflow { - overflow = limbs[index].subtractReportingOverflow(subtrahend) + if !bit { + bit = pointee[index].subtractReportingOverflow(digit) } - limbs.formIndex(after: &index) + pointee.formIndex(after: &index) } } //*============================================================================* -// MARK: * NBK x Limbs x Subtraction x Void +// MARK: * NBK x Limbs x Subtraction x Bit //*============================================================================* extension NBK { @@ -232,40 +245,42 @@ extension NBK { // MARK: Transformations //=------------------------------------------------------------------------= - /// Decrements `limbs` by the sum of `subtrahend` and `overflow` at `index`. + /// Decrements `pointee` by `bit` at `index`. /// - /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// - This operation must not overflow the `pointee` subsequence by more than one bit. /// - /// - Returns: An overflow indicator and its index in `limbs`. + /// - Returns: An overflow indicator and its index in `pointee`. /// - @_transparent public static func decrementSufficientUnsignedInteger( - _ limbs: inout T, by subtrahend: Void, at index: T.Index, borrowing overflow: Bool) -> IO + @_transparent @discardableResult public static func decrementSufficientUnsignedInteger( + _ pointee: inout T, by bit: Bool, at index: T.Index) -> IO where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - var index: T.Index = index, overflow: Bool = overflow - NBK.decrementSufficientUnsignedInteger(&limbs, by: Void(), at: &index, borrowing: &overflow) - return IO(index: index as T.Index, overflow: overflow as Bool) + var index: T.Index = index, bit: Bool = bit + NBK.decrementSufficientUnsignedInteger(&pointee, by: &bit, at: &index) + return IO(index: index as T.Index, overflow: bit as Bool) } //=------------------------------------------------------------------------= // MARK: Transformations x Inout //=------------------------------------------------------------------------= - /// Decrements `limbs` by the sum of `subtrahend` and `overflow` at `index`. + /// Decrements `pointee` by `bit` at `index`. + /// + /// - This operation must not overflow the `pointee` subsequence by more than one bit. /// - /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// - Returns: An overflow indicator and its index in `pointee`. /// @inlinable public static func decrementSufficientUnsignedInteger( - _ limbs: inout T, by subtrahend: Void, at index: inout T.Index, borrowing overflow: inout Bool) + _ pointee: inout T, by bit: inout Bool, at index: inout T.Index) where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - while overflow && index < limbs.endIndex { - overflow = limbs[index].subtractReportingOverflow(1 as T.Element.Digit) - limbs.formIndex(after: &index) + while bit && index < pointee.endIndex { + bit = pointee[index].subtractReportingOverflow(1 as T.Element.Digit) + pointee.formIndex(after: &index) } } } //*============================================================================* -// MARK: * NBK x Limbs x Subtraction x Product +// MARK: * NBK x Limbs x Subtraction x Limbs × Digit + Digit + Bit //*============================================================================* extension NBK { @@ -274,43 +289,43 @@ extension NBK { // MARK: Transformations //=------------------------------------------------------------------------= - /// Decrements `limbs` by the sum of the `subtrahend`, the `overflow`, and - /// the product of `other` and `multiplicand` at `index`. + /// Decrements `pointee` by the product of `limbs` and `multiplicand` at `index`, + /// and the sum of `subtrahend` and `bit` at `index`. /// - /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// - This operation must not overflow the `pointee` subsequence by more than one bit. /// - /// - Returns: An overflow indicator and its index in `limbs`. + /// - Returns: An overflow indicator and its index in `pointee`. /// - @_transparent public static func decrementSufficientUnsignedInteger( - _ limbs: inout T, by other: T, times multiplicand: T.Element, plus subtrahend: T.Element, - at index: T.Index, borrowing overflow: Bool) -> IO + @_transparent @discardableResult public static func decrementSufficientUnsignedInteger( + _ pointee: inout T, by limbs: T, times multiplicand: T.Element, plus subtrahend: T.Element, plus bit: Bool, at index: T.Index) -> IO where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { - var index: T.Index = index, overflow: Bool = overflow - NBK.decrementSufficientUnsignedInteger(&limbs, by: other, times: multiplicand, plus: subtrahend, at: &index, borrowing: &overflow) - return IO(index: index as T.Index, overflow: overflow as Bool) + var index: T.Index = index, bit: Bool = bit + NBK.decrementSufficientUnsignedInteger(&pointee, by: limbs, times: multiplicand, plus: subtrahend, plus: &bit, at: &index) + return IO(index: index as T.Index, overflow: bit as Bool) } //=------------------------------------------------------------------------= // MARK: Transformations x Inout //=------------------------------------------------------------------------= - /// Decrements `limbs` by the sum of the `subtrahend`, the `overflow`, and - /// the product of `other` and `multiplicand` at `index`. + /// Decrements `pointee` by the product of `limbs` and `multiplicand` at `index`, + /// and the sum of `subtrahend` and `bit` at `index`. + /// + /// - This operation must not overflow the `pointee` subsequence by more than one bit. /// - /// - This operation must not overflow the `limbs` subsequence by more than one bit. + /// - Returns: An overflow indicator and its index in `pointee`. /// @inlinable public static func decrementSufficientUnsignedInteger( - _ limbs: inout T, by other: T, times multiplicand: T.Element, plus subtrahend: T.Element, - at index: inout T.Index, borrowing overflow: inout Bool) + _ pointee: inout T, by limbs: T, times multiplicand: T.Element, plus subtrahend: T.Element, plus bit: inout Bool, at index: inout T.Index) where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { var last: T.Element = subtrahend - for otherIndex in other.indices { - var subproduct = other[otherIndex].multipliedFullWidth(by: multiplicand) + for limbsIndex in limbs.indices { + var subproduct = limbs[limbsIndex].multipliedFullWidth(by: multiplicand) last = T.Element(bit: subproduct.low.addReportingOverflow(last)) &+ subproduct.high - NBK.decrementSufficientUnsignedIntegerInIntersection(&limbs, by: subproduct.low, at: &index, borrowing: &overflow) + NBK.decrementSufficientUnsignedIntegerInIntersection(&pointee, by: subproduct.low, plus: &bit, at: &index) } - NBK.decrementSufficientUnsignedInteger(&limbs, by: last, at: &index, borrowing: &overflow) + NBK.decrementSufficientUnsignedInteger(&pointee, by: last, plus: &bit, at: &index) } } diff --git a/Tests/NBKResizableWidthKitTests/Private/NBK+Limbs+Addition.swift b/Tests/NBKResizableWidthKitTests/Private/NBK+Limbs+Addition.swift index 314e51a8..8b61451b 100644 --- a/Tests/NBKResizableWidthKitTests/Private/NBK+Limbs+Addition.swift +++ b/Tests/NBKResizableWidthKitTests/Private/NBK+Limbs+Addition.swift @@ -84,26 +84,28 @@ final class NBKTestsOnLimbsByAdditionAsUnsigned: XCTestCase { // MARK: * NBK x Limbs x Addition x Assertions //*============================================================================* +// TODO: with initial bit set private func NBKAssertAdditionAtIndex( _ lhs: [UInt], _ rhs: [UInt], _ index: Int, _ product: [UInt], _ overflow: Bool = false, file: StaticString = #file, line: UInt = #line) { //=------------------------------------------= brr: do { var lhs = lhs - let max = NBK.incrementSufficientUnsignedInteger(&lhs, by: rhs, at: index, carrying: false) + let max = NBK.incrementSufficientUnsignedInteger(&lhs, by: rhs, plus: false, at: index) XCTAssertEqual(lhs, product, file: file, line: line) XCTAssertEqual(max.overflow, overflow, file: file, line: line) } brr: do { var lhs = lhs - let min = NBK.incrementSufficientUnsignedIntegerInIntersection(&lhs, by: rhs, at: index, carrying: false) - let max = NBK.incrementSufficientUnsignedInteger(&lhs, by: Void(), at: min.index, carrying: min.overflow) + let min = NBK.incrementSufficientUnsignedIntegerInIntersection(&lhs, by: rhs, plus: false, at: index) + let max = NBK.incrementSufficientUnsignedInteger(&lhs, by: min.overflow, at: min.index) XCTAssertEqual(lhs, product, file: file, line: line) XCTAssertEqual(max.overflow, overflow, file: file, line: line) } } +// TODO: with initial bit set private func NBKAssertAdditionByDigitAtIndex( _ lhs: [UInt], _ rhs: UInt, _ index: Int, _ product: [UInt], _ overflow: Bool = false, file: StaticString = #file, line: UInt = #line) { @@ -118,22 +120,22 @@ file: StaticString = #file, line: UInt = #line) { brr: do { var lhs = lhs let min = NBK.incrementSufficientUnsignedIntegerInIntersection(&lhs, by: rhs, at: index) - let max = NBK.incrementSufficientUnsignedInteger(&lhs, by: Void(), at: min.index, carrying: min.overflow) + let max = NBK.incrementSufficientUnsignedInteger(&lhs, by: min.overflow, at: min.index) XCTAssertEqual(lhs, product, file: file, line: line) XCTAssertEqual(max.overflow, overflow, file: file, line: line) } //=------------------------------------------= brr: do { var lhs = lhs - let max = NBK.incrementSufficientUnsignedInteger(&lhs, by: rhs, at: index, carrying: false) + let max = NBK.incrementSufficientUnsignedInteger(&lhs, by: rhs, plus: false, at: index) XCTAssertEqual(lhs, product, file: file, line: line) XCTAssertEqual(max.overflow, overflow, file: file, line: line) } brr: do { var lhs = lhs - let min = NBK.incrementSufficientUnsignedIntegerInIntersection(&lhs, by: rhs, at: index, carrying: false) - let max = NBK.incrementSufficientUnsignedInteger(&lhs, by: Void(), at: min.index, carrying: min.overflow) + let min = NBK.incrementSufficientUnsignedIntegerInIntersection(&lhs, by: rhs, plus: false, at: index) + let max = NBK.incrementSufficientUnsignedInteger(&lhs, by: min.overflow, at: min.index) XCTAssertEqual(lhs, product, file: file, line: line) XCTAssertEqual(max.overflow, overflow, file: file, line: line) } diff --git a/Tests/NBKResizableWidthKitTests/Private/NBK+Limbs+Subtraction.swift b/Tests/NBKResizableWidthKitTests/Private/NBK+Limbs+Subtraction.swift index ba8ac091..2e0a508f 100644 --- a/Tests/NBKResizableWidthKitTests/Private/NBK+Limbs+Subtraction.swift +++ b/Tests/NBKResizableWidthKitTests/Private/NBK+Limbs+Subtraction.swift @@ -84,26 +84,28 @@ final class NBKTestsOnLimbsBySubtractionAsUnsigned: XCTestCase { // MARK: * NBK x Limbs x Subtraction x Assertions //*============================================================================* +// TODO: with initial bit set private func NBKAssertSubtractionAtIndex( _ lhs: [UInt], _ rhs: [UInt], _ index: Int, _ product: [UInt], _ overflow: Bool = false, file: StaticString = #file, line: UInt = #line) { //=------------------------------------------= brr: do { var lhs = lhs - let max = NBK.decrementSufficientUnsignedInteger(&lhs, by: rhs, at: index, borrowing: false) + let max = NBK.decrementSufficientUnsignedInteger(&lhs, by: rhs, plus: false, at: index) XCTAssertEqual(lhs, product, file: file, line: line) XCTAssertEqual(max.overflow, overflow, file: file, line: line) } brr: do { var lhs = lhs - let min = NBK.decrementSufficientUnsignedIntegerInIntersection(&lhs, by: rhs, at: index, borrowing: false) - let max = NBK.decrementSufficientUnsignedInteger(&lhs, by: Void(), at: min.index, borrowing: min.overflow) + let min = NBK.decrementSufficientUnsignedIntegerInIntersection(&lhs, by: rhs, plus: false, at: index) + let max = NBK.decrementSufficientUnsignedInteger(&lhs, by: min.overflow, at: min.index) XCTAssertEqual(lhs, product, file: file, line: line) XCTAssertEqual(max.overflow, overflow, file: file, line: line) } } +// TODO: with initial bit set private func NBKAssertSubtractionByDigitAtIndex( _ lhs: [UInt], _ rhs: UInt, _ index: Int, _ product: [UInt], _ overflow: Bool = false, file: StaticString = #file, line: UInt = #line) { @@ -118,22 +120,22 @@ file: StaticString = #file, line: UInt = #line) { brr: do { var lhs = lhs let min = NBK.decrementSufficientUnsignedIntegerInIntersection(&lhs, by: rhs, at: index) - let max = NBK.decrementSufficientUnsignedInteger(&lhs, by: Void(), at: min.index, borrowing: min.overflow) + let max = NBK.decrementSufficientUnsignedInteger(&lhs, by: min.overflow, at: min.index) XCTAssertEqual(lhs, product, file: file, line: line) XCTAssertEqual(max.overflow, overflow, file: file, line: line) } //=------------------------------------------= brr: do { var lhs = lhs - let max = NBK.decrementSufficientUnsignedInteger(&lhs, by: rhs, at: index, borrowing: false) + let max = NBK.decrementSufficientUnsignedInteger(&lhs, by: rhs, plus: false, at: index) XCTAssertEqual(lhs, product, file: file, line: line) XCTAssertEqual(max.overflow, overflow, file: file, line: line) } brr: do { var lhs = lhs - let min = NBK.decrementSufficientUnsignedIntegerInIntersection(&lhs, by: rhs, at: index, borrowing: false) - let max = NBK.decrementSufficientUnsignedInteger(&lhs, by: Void(), at: min.index, borrowing: min.overflow) + let min = NBK.decrementSufficientUnsignedIntegerInIntersection(&lhs, by: rhs, plus: false, at: index) + let max = NBK.decrementSufficientUnsignedInteger(&lhs, by: min.overflow, at: min.index) XCTAssertEqual(lhs, product, file: file, line: line) XCTAssertEqual(max.overflow, overflow, file: file, line: line) } From 371b7df7f67a24da25fecda648b8f2a719d5fa75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Mon, 11 Sep 2023 08:32:26 +0200 Subject: [PATCH 060/133] [NBKFlexibleWidthKit] Cleanup. --- .../xcschemes/NBKFlexibleWidthKit.xcscheme | 71 +++++++++ .../NBKFlexibleWidth+Addition.swift | 2 +- .../NBKFlexibleWidth+Bits.swift | 9 +- .../NBKFlexibleWidth+Literals.swift | 6 +- .../NBKFlexibleWidth.swift | 8 +- .../NBKFlexibleWidth+Division.swift | 13 +- .../NBKFlexibleWidth+Literals.swift | 140 +++++++++++++----- .../NBKFlexibleWidth+Text.swift | 4 +- .../NBKFlexibleWidth.swift | 8 +- .../NBKResizableWidth.swift | 4 +- .../NBKResizableWidth.swift | 4 +- 11 files changed, 205 insertions(+), 64 deletions(-) create mode 100644 .swiftpm/xcode/xcshareddata/xcschemes/NBKFlexibleWidthKit.xcscheme diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/NBKFlexibleWidthKit.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/NBKFlexibleWidthKit.xcscheme new file mode 100644 index 00000000..c72f5e4d --- /dev/null +++ b/.swiftpm/xcode/xcshareddata/xcschemes/NBKFlexibleWidthKit.xcscheme @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift index fa122cfc..c0e35557 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift @@ -75,7 +75,7 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= if other.isZero { return } //=--------------------------------------= - self.storage.resize(minCount: other.storage.count + index) + self.storage.resize(minCount: other.storage.count + index) let overflow = self.storage.add(other.storage, plus: false, at: index) if overflow { self.storage.append(1 as UInt) } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift index 1161a608..c024126e 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift @@ -33,9 +33,12 @@ extension NBKFlexibleWidth { } @inlinable public var nonzeroBitCount: Int { - switch self.isLessThanZero { - case false: return self.magnitude.nonzeroBitCount - case true: return NBK.nonzeroBitCount(twosComplementOf: self.magnitude.storage) + self.storageBitWidthNeeded } + if self.isLessThanZero { + let s = NBK.nonzeroBitCount(twosComplementOf: self.magnitude.storage) + return s + self.storageBitWidthNeeded + } else { + return self.magnitude.nonzeroBitCount + } } @inlinable public var leadingZeroBitCount: Int { diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Literals.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Literals.swift index c050ff29..8a5fe4ac 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Literals.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Literals.swift @@ -149,14 +149,12 @@ extension NBKFlexibleWidth.Magnitude { } @inlinable init?(exactlyStringLiteral source: StaticString) { - let value: Optional = source.withUTF8Buffer { utf8 in + if let value: Self = source.withUTF8Buffer({ utf8 in let components = NBK.makeIntegerComponentsByDecodingRadix(utf8: utf8) let radix = NBK.AnyRadixSolution(components.radix) let digits = NBK.UnsafeUTF8(rebasing: components.body ) guard let magnitude = Magnitude(digits: digits, radix: radix) else { return nil } return Self(sign: components.sign, magnitude: magnitude) - } - - if let value { self = value } else { return nil } + }){ self = value } else { return nil } } } diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth.swift index 4502ffa6..e2a353aa 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth.swift @@ -33,11 +33,11 @@ extension NBKFlexibleWidth { //=------------------------------------------------------------------------= init(x32: [UInt32]) { - self.init(words: NBKChunkedInt(x32, as: UInt.self)) + self.init(words: NBKChunkedInt(x32)) } init(x64: [UInt64]) { - self.init(words: NBKChunkedInt(x64, as: UInt.self)) + self.init(words: NBKChunkedInt(x64)) } } @@ -59,10 +59,10 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= init(x32: [UInt32]) { - self.init(words: NBKChunkedInt(x32, as: UInt.self)) + self.init(words: NBKChunkedInt(x32)) } init(x64: [UInt64]) { - self.init(words: NBKChunkedInt(x64, as: UInt.self)) + self.init(words: NBKChunkedInt(x64)) } } diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Division.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Division.swift index 1664c319..84645c5f 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Division.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Division.swift @@ -292,7 +292,7 @@ private func NBKAssertDivision( _ lhs: T, _ rhs: T, _ quotient: T, _ remainder: T, _ overflow: Bool = false, file: StaticString = #file, line: UInt = #line) { //=------------------------------------------= - XCTAssertEqual(lhs, quotient * rhs + remainder, "lhs != rhs * quotient + remainder", file: file, line: line) + XCTAssertEqual(lhs, quotient * rhs + remainder, "dividend != divisor * quotient + remainder", file: file, line: line) //=------------------------------------------= if !overflow { XCTAssertEqual(lhs / rhs, quotient, file: file, line: line) @@ -321,7 +321,12 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual(lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs).partialValue.remainder, remainder, file: file, line: line) XCTAssertEqual(lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs).overflow, overflow, file: file, line: line) //=------------------------------------------= - guard let lhs = lhs as? UIntXL, let rhs = rhs as? UIntXL, let quotient = quotient as? UIntXL, let remainder = remainder as? UIntXL else { return } + guard + let lhs = lhs as? UIntXL, + let rhs = rhs as? UIntXL, + let quotient = quotient as? UIntXL, + let remainder = remainder as? UIntXL + else { return } //=------------------------------------------= XCTAssertEqual(lhs.quotientAndRemainderReportingOverflowAsNormal(dividingBy: rhs).partialValue.quotient, quotient, file: file, line: line) XCTAssertEqual(lhs.quotientAndRemainderReportingOverflowAsNormal(dividingBy: rhs).partialValue.remainder, remainder, file: file, line: line) @@ -333,7 +338,7 @@ _ lhs: T, _ rhs: T.Digit, _ quotient: T, _ remainder: T.Digit, _ overflow: Bool file: StaticString = #file, line: UInt = #line) { let extended = T(digit: remainder) //=------------------------------------------= - XCTAssertEqual(lhs, quotient * rhs + remainder, "lhs != rhs * quotient + remainder", file: file, line: line) + XCTAssertEqual(lhs, quotient * rhs + remainder, "dividend != divisor * quotient + remainder", file: file, line: line) //=------------------------------------------= if !overflow { XCTAssertEqual(lhs / rhs, quotient, file: file, line: line) @@ -357,7 +362,7 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual({ var x = lhs; let _ = x.formRemainderReportingOverflow(dividingBy: rhs); return x }(), extended, file: file, line: line) XCTAssertEqual({ var x = lhs; let o = x.formRemainderReportingOverflow(dividingBy: rhs); return o }(), overflow, file: file, line: line) - + XCTAssertEqual(lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs).partialValue.quotient, quotient, file: file, line: line) XCTAssertEqual(lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs).partialValue.remainder, remainder, file: file, line: line) XCTAssertEqual(lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs).overflow, overflow, file: file, line: line) diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Literals.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Literals.swift index ef673d7e..b850125c 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Literals.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Literals.swift @@ -30,30 +30,67 @@ final class NBKFlexibleWidthTestsOnLiteralsAsIntXL: XCTestCase { //=------------------------------------------------------------------------= func testFromIntegerLiteral() { + XCTAssertEqual(T(x64:[ 10, 0, 0, 0] as X), (10)) + XCTAssertEqual(T(x64:[ 02, 0, 0, 0] as X), (0b10)) + XCTAssertEqual(T(x64:[ 08, 0, 0, 0] as X), (0o10)) + XCTAssertEqual(T(x64:[ 16, 0, 0, 0] as X), (0x10)) + XCTAssertEqual(T(x64:[ 16, 0, 0, 0] as X), (0x10)) + XCTAssertEqual(T(x64:[ ~9, ~0, ~0, ~0] as X), (-10)) + XCTAssertEqual(T(x64:[ ~1, ~0, ~0, ~0] as X), (-0b10)) + XCTAssertEqual(T(x64:[ ~7, ~0, ~0, ~0] as X), (-0o10)) + XCTAssertEqual(T(x64:[~15, ~0, ~0, ~0] as X), (-0x10)) #if SBI && swift(>=5.8) - XCTAssertEqual(T(x64:[ 0, 0, 0, 0] as X), 0x0000000000000000000000000000000000000000000000000000000000000000) - XCTAssertEqual(T(x64:[~0, 0, 0, 0] as X), 0x000000000000000000000000000000000000000000000000ffffffffffffffff) - XCTAssertEqual(T(x64:[~0, ~0, 0, 0] as X), 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) - XCTAssertEqual(T(x64:[~0, ~0, ~0, 0] as X), 0x0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff) - XCTAssertEqual(T(x64:[~0, ~0, ~0, ~0] as X), -0x0000000000000000000000000000000000000000000000000000000000000001) - XCTAssertEqual(T(x64:[ 0, ~0, ~0, ~0] as X), -0x0000000000000000000000000000000000000000000000010000000000000000) - XCTAssertEqual(T(x64:[ 0, 0, ~0, ~0] as X), -0x0000000000000000000000000000000100000000000000000000000000000000) - XCTAssertEqual(T(x64:[ 0, 0, 0, ~0] as X), -0x0000000000000001000000000000000000000000000000000000000000000000) + XCTAssertEqual(T(x64:[ 0, 0, 0, 0] as X), (0x000000000000000000000000000000000000000000000000000000000000000000000000000000)) + XCTAssertEqual(T(x64:[ ~0, 0, 0, 0] as X), (0x00000000000000000000000000000000000000000000000000000000000000ffffffffffffffff)) + XCTAssertEqual(T(x64:[ ~0, ~0, 0, 0] as X), (0x0000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffff)) + XCTAssertEqual(T(x64:[ ~0, ~0, ~0, 0] as X), (0x000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff)) + XCTAssertEqual(T(x64:[ ~0, ~0, ~0, ~0] as X), (-0x000000000000000000000000000000000000000000000000000000000000000000000000000001)) + XCTAssertEqual(T(x64:[ 0, ~0, ~0, ~0] as X), (-0x000000000000000000000000000000000000000000000000000000000000010000000000000000)) + XCTAssertEqual(T(x64:[ 0, 0, ~0, ~0] as X), (-0x000000000000000000000000000000000000000000000100000000000000000000000000000000)) + XCTAssertEqual(T(x64:[ 0, 0, 0, ~0] as X), (-0x000000000000000000000000000001000000000000000000000000000000000000000000000000)) + + XCTAssertEqual(T(x64:[ 0, 0, 0, 0] as X), (00000000000000000000000000000000000000000000000000000000000000000000000000000000)) + XCTAssertEqual(T(x64:[ ~0, 0, 0, 0] as X), (00000000000000000000000000000000000000000000000000000000000018446744073709551615)) + XCTAssertEqual(T(x64:[ ~0, ~0, 0, 0] as X), (00000000000000000000000000000000000000000340282366920938463463374607431768211455)) + XCTAssertEqual(T(x64:[ ~0, ~0, ~0, 0] as X), (00000000000000000000006277101735386680763835789423207666416102355444464034512895)) + XCTAssertEqual(T(x64:[ ~0, ~0, ~0, ~0] as X), (-00000000000000000000000000000000000000000000000000000000000000000000000000000001)) + XCTAssertEqual(T(x64:[ 0, ~0, ~0, ~0] as X), (-00000000000000000000000000000000000000000000000000000000000018446744073709551616)) + XCTAssertEqual(T(x64:[ 0, 0, ~0, ~0] as X), (-00000000000000000000000000000000000000000340282366920938463463374607431768211456)) + XCTAssertEqual(T(x64:[ 0, 0, 0, ~0] as X), (-00000000000000000000006277101735386680763835789423207666416102355444464034512896)) #else - XCTAssertEqual(T(integerLiteral: Int.max), T(x64: [UInt64(Int.max), 0, 0, 0] as X)) - XCTAssertEqual(T(integerLiteral: Int.min), ~T(x64: [UInt64(Int.max), 0, 0, 0] as X)) + XCTAssertEqual(T(integerLiteral: Int.max), T(x64:[UInt64(Int.max), 0, 0, 0] as X)) + XCTAssertEqual(T(integerLiteral: Int.min), ~T(x64:[UInt64(Int.max), 0, 0, 0] as X)) #endif } func testFromStringLiteral() { - XCTAssertEqual(T(x64:[ 0, 0, 0, 0] as X), "0x0000000000000000000000000000000000000000000000000000000000000000") - XCTAssertEqual(T(x64:[~0, 0, 0, 0] as X), "0x000000000000000000000000000000000000000000000000ffffffffffffffff") - XCTAssertEqual(T(x64:[~0, ~0, 0, 0] as X), "0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff") - XCTAssertEqual(T(x64:[~0, ~0, ~0, 0] as X), "0x0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff") - XCTAssertEqual(T(x64:[~0, ~0, ~0, ~0] as X), "-0x0000000000000000000000000000000000000000000000000000000000000001") - XCTAssertEqual(T(x64:[ 0, ~0, ~0, ~0] as X), "-0x0000000000000000000000000000000000000000000000010000000000000000") - XCTAssertEqual(T(x64:[ 0, 0, ~0, ~0] as X), "-0x0000000000000000000000000000000100000000000000000000000000000000") - XCTAssertEqual(T(x64:[ 0, 0, 0, ~0] as X), "-0x0000000000000001000000000000000000000000000000000000000000000000") + XCTAssertEqual(T(x64:[ 10, 0, 0, 0] as X), "10") + XCTAssertEqual(T(x64:[ 02, 0, 0, 0] as X), "0b10") + XCTAssertEqual(T(x64:[ 08, 0, 0, 0] as X), "0o10") + XCTAssertEqual(T(x64:[ 16, 0, 0, 0] as X), "0x10") + XCTAssertEqual(T(x64:[ 16, 0, 0, 0] as X), "0x10") + XCTAssertEqual(T(x64:[ ~9, ~0, ~0, ~0] as X), "-10") + XCTAssertEqual(T(x64:[ ~1, ~0, ~0, ~0] as X), "-0b10") + XCTAssertEqual(T(x64:[ ~7, ~0, ~0, ~0] as X), "-0o10") + XCTAssertEqual(T(x64:[~15, ~0, ~0, ~0] as X), "-0x10") + + XCTAssertEqual(T(x64:[ 0, 0, 0, 0] as X), "0x000000000000000000000000000000000000000000000000000000000000000000000000000000") + XCTAssertEqual(T(x64:[ ~0, 0, 0, 0] as X), "0x00000000000000000000000000000000000000000000000000000000000000ffffffffffffffff") + XCTAssertEqual(T(x64:[ ~0, ~0, 0, 0] as X), "0x0000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffff") + XCTAssertEqual(T(x64:[ ~0, ~0, ~0, 0] as X), "0x000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff") + XCTAssertEqual(T(x64:[ ~0, ~0, ~0, ~0] as X), "-0x000000000000000000000000000000000000000000000000000000000000000000000000000001") + XCTAssertEqual(T(x64:[ 0, ~0, ~0, ~0] as X), "-0x000000000000000000000000000000000000000000000000000000000000010000000000000000") + XCTAssertEqual(T(x64:[ 0, 0, ~0, ~0] as X), "-0x000000000000000000000000000000000000000000000100000000000000000000000000000000") + XCTAssertEqual(T(x64:[ 0, 0, 0, ~0] as X), "-0x000000000000000000000000000001000000000000000000000000000000000000000000000000") + + XCTAssertEqual(T(x64:[ 0, 0, 0, 0] as X), "00000000000000000000000000000000000000000000000000000000000000000000000000000000") + XCTAssertEqual(T(x64:[ ~0, 0, 0, 0] as X), "00000000000000000000000000000000000000000000000000000000000018446744073709551615") + XCTAssertEqual(T(x64:[ ~0, ~0, 0, 0] as X), "00000000000000000000000000000000000000000340282366920938463463374607431768211455") + XCTAssertEqual(T(x64:[ ~0, ~0, ~0, 0] as X), "00000000000000000000006277101735386680763835789423207666416102355444464034512895") + XCTAssertEqual(T(x64:[ ~0, ~0, ~0, ~0] as X), "-00000000000000000000000000000000000000000000000000000000000000000000000000000001") + XCTAssertEqual(T(x64:[ 0, ~0, ~0, ~0] as X), "-00000000000000000000000000000000000000000000000000000000000018446744073709551616") + XCTAssertEqual(T(x64:[ 0, 0, ~0, ~0] as X), "-00000000000000000000000000000000000000000340282366920938463463374607431768211456") + XCTAssertEqual(T(x64:[ 0, 0, 0, ~0] as X), "-00000000000000000000006277101735386680763835789423207666416102355444464034512896") } } @@ -70,34 +107,61 @@ final class NBKFlexibleWidthTestsOnLiteralsAsUIntXL: XCTestCase { //=------------------------------------------------------------------------= func testFromIntegerLiteral() { + XCTAssertEqual(T(x64:[ 10, 0, 0, 0] as X), (10)) + XCTAssertEqual(T(x64:[ 02, 0, 0, 0] as X), (0b10)) + XCTAssertEqual(T(x64:[ 08, 0, 0, 0] as X), (0o10)) + XCTAssertEqual(T(x64:[ 16, 0, 0, 0] as X), (0x10)) #if SBI && swift(>=5.8) - XCTAssertEqual(T(x64:[ 0, 0, 0, 0] as X), 0x0000000000000000000000000000000000000000000000000000000000000000) - XCTAssertEqual(T(x64:[~0, 0, 0, 0] as X), 0x000000000000000000000000000000000000000000000000ffffffffffffffff) - XCTAssertEqual(T(x64:[~0, ~0, 0, 0] as X), 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) - XCTAssertEqual(T(x64:[~0, ~0, ~0, 0] as X), 0x0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff) - XCTAssertEqual(T(x64:[~0, ~0, ~0, ~0] as X), 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) - XCTAssertEqual(T(x64:[ 0, ~0, ~0, ~0] as X), 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) - XCTAssertEqual(T(x64:[ 0, 0, ~0, ~0] as X), 0xffffffffffffffffffffffffffffffff00000000000000000000000000000000) - XCTAssertEqual(T(x64:[ 0, 0, 0, ~0] as X), 0xffffffffffffffff000000000000000000000000000000000000000000000000) + XCTAssertEqual(T(x64:[ 0, 0, 0, 0] as X), (0x000000000000000000000000000000000000000000000000000000000000000000000000000000)) + XCTAssertEqual(T(x64:[ ~0, 0, 0, 0] as X), (0x00000000000000000000000000000000000000000000000000000000000000ffffffffffffffff)) + XCTAssertEqual(T(x64:[ ~0, ~0, 0, 0] as X), (0x0000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffff)) + XCTAssertEqual(T(x64:[ ~0, ~0, ~0, 0] as X), (0x000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff)) + XCTAssertEqual(T(x64:[ ~0, ~0, ~0, ~0] as X), (0x00000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)) + XCTAssertEqual(T(x64:[ 0, ~0, ~0, ~0] as X), (0x00000000000000ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000)) + XCTAssertEqual(T(x64:[ 0, 0, ~0, ~0] as X), (0x00000000000000ffffffffffffffffffffffffffffffff00000000000000000000000000000000)) + XCTAssertEqual(T(x64:[ 0, 0, 0, ~0] as X), (0x00000000000000ffffffffffffffff000000000000000000000000000000000000000000000000)) + XCTAssertEqual(T(exactlyIntegerLiteral: (-0x000000000000000000000000000000000000000000000000000000000000000000000000000001)), nil) - XCTAssertNil(T(exactlyIntegerLiteral: -1)) + XCTAssertEqual(T(x64:[ 0, 0, 0, 0] as X), (00000000000000000000000000000000000000000000000000000000000000000000000000000000)) + XCTAssertEqual(T(x64:[ ~0, 0, 0, 0] as X), (00000000000000000000000000000000000000000000000000000000000018446744073709551615)) + XCTAssertEqual(T(x64:[ ~0, ~0, 0, 0] as X), (00000000000000000000000000000000000000000340282366920938463463374607431768211455)) + XCTAssertEqual(T(x64:[ ~0, ~0, ~0, 0] as X), (00000000000000000000006277101735386680763835789423207666416102355444464034512895)) + XCTAssertEqual(T(x64:[ ~0, ~0, ~0, ~0] as X), (00115792089237316195423570985008687907853269984665640564039457584007913129639935)) + XCTAssertEqual(T(x64:[ 0, ~0, ~0, ~0] as X), (00115792089237316195423570985008687907853269984665640564039439137263839420088320)) + XCTAssertEqual(T(x64:[ 0, 0, ~0, ~0] as X), (00115792089237316195423570985008687907852929702298719625575994209400481361428480)) + XCTAssertEqual(T(x64:[ 0, 0, 0, ~0] as X), (00115792089237316195417293883273301227089434195242432897623355228563449095127040)) + XCTAssertEqual(T(exactlyIntegerLiteral: (-00000000000000000000000000000000000000000000000000000000000000000000000000000001)), nil) #else - XCTAssertEqual(T(integerLiteral: UInt.max), T(x64: [UInt64(UInt.max), 0, 0, 0] as X)) - XCTAssertEqual(T(integerLiteral: UInt.min), T(x64: [UInt64(UInt.min), 0, 0, 0] as X)) + XCTAssertEqual(T(integerLiteral: UInt.max), T(x64:[UInt64(UInt.max), 0, 0, 0] as X)) + XCTAssertEqual(T(integerLiteral: UInt.min), T(x64:[UInt64(UInt.min), 0, 0, 0] as X)) #endif } func testFromStringLiteral() { - XCTAssertEqual(T(x64:[ 0, 0, 0, 0] as X), "0x0000000000000000000000000000000000000000000000000000000000000000") - XCTAssertEqual(T(x64:[~0, 0, 0, 0] as X), "0x000000000000000000000000000000000000000000000000ffffffffffffffff") - XCTAssertEqual(T(x64:[~0, ~0, 0, 0] as X), "0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff") - XCTAssertEqual(T(x64:[~0, ~0, ~0, 0] as X), "0x0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff") - XCTAssertEqual(T(x64:[~0, ~0, ~0, ~0] as X), "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") - XCTAssertEqual(T(x64:[ 0, ~0, ~0, ~0] as X), "0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000") - XCTAssertEqual(T(x64:[ 0, 0, ~0, ~0] as X), "0xffffffffffffffffffffffffffffffff00000000000000000000000000000000") - XCTAssertEqual(T(x64:[ 0, 0, 0, ~0] as X), "0xffffffffffffffff000000000000000000000000000000000000000000000000") + XCTAssertEqual(T(x64:[ 10, 0, 0, 0] as X), "10") + XCTAssertEqual(T(x64:[ 02, 0, 0, 0] as X), "0b10") + XCTAssertEqual(T(x64:[ 08, 0, 0, 0] as X), "0o10") + XCTAssertEqual(T(x64:[ 16, 0, 0, 0] as X), "0x10") + + XCTAssertEqual(T(x64:[ 0, 0, 0, 0] as X), "0x000000000000000000000000000000000000000000000000000000000000000000000000000000") + XCTAssertEqual(T(x64:[ ~0, 0, 0, 0] as X), "0x00000000000000000000000000000000000000000000000000000000000000ffffffffffffffff") + XCTAssertEqual(T(x64:[ ~0, ~0, 0, 0] as X), "0x0000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffff") + XCTAssertEqual(T(x64:[ ~0, ~0, ~0, 0] as X), "0x000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff") + XCTAssertEqual(T(x64:[ ~0, ~0, ~0, ~0] as X), "0x00000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") + XCTAssertEqual(T(x64:[ 0, ~0, ~0, ~0] as X), "0x00000000000000ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000") + XCTAssertEqual(T(x64:[ 0, 0, ~0, ~0] as X), "0x00000000000000ffffffffffffffffffffffffffffffff00000000000000000000000000000000") + XCTAssertEqual(T(x64:[ 0, 0, 0, ~0] as X), "0x00000000000000ffffffffffffffff000000000000000000000000000000000000000000000000") + XCTAssertEqual(T(exactlyStringLiteral: "-0x000000000000000000000000000000000000000000000000000000000000000000000000000001"), nil) - XCTAssertNil(T(exactlyStringLiteral: "-1")) + XCTAssertEqual(T(x64:[ 0, 0, 0, 0] as X), "00000000000000000000000000000000000000000000000000000000000000000000000000000000") + XCTAssertEqual(T(x64:[ ~0, 0, 0, 0] as X), "00000000000000000000000000000000000000000000000000000000000018446744073709551615") + XCTAssertEqual(T(x64:[ ~0, ~0, 0, 0] as X), "00000000000000000000000000000000000000000340282366920938463463374607431768211455") + XCTAssertEqual(T(x64:[ ~0, ~0, ~0, 0] as X), "00000000000000000000006277101735386680763835789423207666416102355444464034512895") + XCTAssertEqual(T(x64:[ ~0, ~0, ~0, ~0] as X), "00115792089237316195423570985008687907853269984665640564039457584007913129639935") + XCTAssertEqual(T(x64:[ 0, ~0, ~0, ~0] as X), "00115792089237316195423570985008687907853269984665640564039439137263839420088320") + XCTAssertEqual(T(x64:[ 0, 0, ~0, ~0] as X), "00115792089237316195423570985008687907852929702298719625575994209400481361428480") + XCTAssertEqual(T(x64:[ 0, 0, 0, ~0] as X), "00115792089237316195417293883273301227089434195242432897623355228563449095127040") + XCTAssertEqual(T(exactlyStringLiteral: "-00000000000000000000000000000000000000000000000000000000000000000000000000000001"), nil) } } diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Text.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Text.swift index a4044c91..54151935 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Text.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Text.swift @@ -37,7 +37,7 @@ final class NBKFlexibleWidthTestsOnTextAsIntXL: XCTestCase { // MARK: Tests //=------------------------------------------------------------------------= - func testInitDescription() { + func testFromDescription() { NBKAssertFromDescription(T?( 10), "10") NBKAssertFromDescription(T?( 10), "+10") NBKAssertFromDescription(T?(-10), "-10") @@ -273,7 +273,7 @@ final class NBKFlexibleWidthTestsOnTextAsUIntXL: XCTestCase { // MARK: Tests //=------------------------------------------------------------------------= - func testInitDescription() { + func testFromDescription() { NBKAssertFromDescription(T?( 10), "10") NBKAssertFromDescription(T?( 10), "+10") NBKAssertFromDescription(T?(nil), "-10") diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth.swift index c682e17e..40448815 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth.swift @@ -72,11 +72,11 @@ extension NBKFlexibleWidth { //=------------------------------------------------------------------------= init(x32: [UInt32]) { - self.init(words: NBKChunkedInt(x32, as: UInt.self)) + self.init(words: NBKChunkedInt(x32)) } init(x64: [UInt64]) { - self.init(words: NBKChunkedInt(x64, as: UInt.self)) + self.init(words: NBKChunkedInt(x64)) } } @@ -98,10 +98,10 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= init(x32: [UInt32]) { - self.init(words: NBKChunkedInt(x32, as: UInt.self)) + self.init(words: NBKChunkedInt(x32)) } init(x64: [UInt64]) { - self.init(words: NBKChunkedInt(x64, as: UInt.self)) + self.init(words: NBKChunkedInt(x64)) } } diff --git a/Tests/NBKResizableWidthKitBenchmarks/NBKResizableWidth.swift b/Tests/NBKResizableWidthKitBenchmarks/NBKResizableWidth.swift index ffcdff9a..3c57b0b3 100644 --- a/Tests/NBKResizableWidthKitBenchmarks/NBKResizableWidth.swift +++ b/Tests/NBKResizableWidthKitBenchmarks/NBKResizableWidth.swift @@ -33,10 +33,10 @@ extension NBKResizableWidth.Magnitude { //=------------------------------------------------------------------------= init(x32: [UInt32]) { - self.init(words: NBKChunkedInt(x32, as: UInt.self)) + self.init(words: NBKChunkedInt(x32)) } init(x64: [UInt64]) { - self.init(words: NBKChunkedInt(x64, as: UInt.self)) + self.init(words: NBKChunkedInt(x64)) } } diff --git a/Tests/NBKResizableWidthKitTests/NBKResizableWidth.swift b/Tests/NBKResizableWidthKitTests/NBKResizableWidth.swift index ffcdff9a..3c57b0b3 100644 --- a/Tests/NBKResizableWidthKitTests/NBKResizableWidth.swift +++ b/Tests/NBKResizableWidthKitTests/NBKResizableWidth.swift @@ -33,10 +33,10 @@ extension NBKResizableWidth.Magnitude { //=------------------------------------------------------------------------= init(x32: [UInt32]) { - self.init(words: NBKChunkedInt(x32, as: UInt.self)) + self.init(words: NBKChunkedInt(x32)) } init(x64: [UInt64]) { - self.init(words: NBKChunkedInt(x64, as: UInt.self)) + self.init(words: NBKChunkedInt(x64)) } } From 7740703f495f7a9f8c72a15442bc635a8a5de010 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Mon, 11 Sep 2023 09:11:01 +0200 Subject: [PATCH 061/133] [NBKFlexibleWidthKit] Dropped NBKResizableWidthKit (#33) (#46). --- ...NBKResizableWidthKit-Benchmarks.xctestplan | 24 -- .swiftpm/NBKResizableWidthKit.xctestplan | 32 -- .swiftpm/Numberick-Benchmarks.xctestplan | 7 - .swiftpm/Numberick.xctestplan | 12 - .../xcschemes/Numberick-Benchmarks.xcscheme | 3 - .../xcshareddata/xcschemes/Numberick.xcscheme | 3 - Package.swift | 22 +- README.md | 8 - .../NBKFlexibleWidth+Addition+Digit.swift | 1 - .../NBKFlexibleWidth+Addition.swift | 1 - .../NBKFlexibleWidth+Bits.swift | 1 - .../NBKFlexibleWidth+Comparisons.swift | 1 - .../NBKFlexibleWidth+Complements.swift | 1 - .../NBKFlexibleWidth+Division+Digit.swift | 1 - .../NBKFlexibleWidth+Division.swift | 1 - .../NBKFlexibleWidth+Logic.swift | 1 - ...BKFlexibleWidth+Multiplication+Digit.swift | 1 - .../NBKFlexibleWidth+Multiplication.swift | 1 - .../NBKFlexibleWidth+Numbers.swift | 1 - .../NBKFlexibleWidth+Shifts.swift | 1 - .../NBKFlexibleWidth+Size.swift | 1 - .../NBKFlexibleWidth+Subtraction+Digit.swift | 1 - .../NBKFlexibleWidth+Subtraction.swift | 1 - .../NBKFlexibleWidth+Text.swift | 1 - .../NBKFlexibleWidth+Update.swift | 1 - .../NBKFlexibleWidth+Words.swift | 1 - .../NBKFlexibleWidth.swift | 1 - .../NBKResizableWidth+Addition+Digit.swift | 0 .../NBKResizableWidth+Addition.swift | 0 .../NBKResizableWidth+Bits.swift | 0 .../NBKResizableWidth+Comparisons.swift | 0 .../NBKResizableWidth+Complements.swift | 0 .../NBKResizableWidth+Division+Digit.swift | 0 .../NBKResizableWidth+Division.swift | 0 .../NBKResizableWidth+Literals.swift | 0 .../NBKResizableWidth+Logic.swift | 0 ...KResizableWidth+Multiplication+Digit.swift | 0 .../NBKResizableWidth+Multiplication.swift | 0 .../NBKResizableWidth+Numbers.swift | 0 .../NBKResizableWidth+Protocols.swift | 0 .../NBKResizableWidth+Shifts.swift | 0 .../NBKResizableWidth+Size.swift | 0 .../NBKResizableWidth+Subtraction+Digit.swift | 0 .../NBKResizableWidth+Subtraction.swift | 0 .../NBKResizableWidth+Text.swift | 2 + .../NBKResizableWidth+Uninitialized.swift | 0 .../NBKResizableWidth+Update.swift | 0 .../NBKResizableWidth+Words+Pointers.swift | 0 .../NBKResizableWidth+Words.swift | 0 .../NBKResizableWidth.swift | 0 .../NBKResizableWidth+Bits.swift | 124 -------- .../NBKResizableWidth+Comparisons.swift | 150 --------- .../NBKResizableWidth+Logic.swift | 117 -------- .../NBKResizableWidth+Shifts.swift | 152 ---------- .../NBKResizableWidth+Words.swift | 46 --- .../NBKResizableWidth.swift | 42 --- .../NBKResizableWidth+Bits.swift | 99 ------ .../NBKResizableWidth+Comparisons.swift | 284 ------------------ .../NBKResizableWidth+Logic.swift | 131 -------- .../NBKResizableWidth+Shifts.swift | 206 ------------- .../NBKResizableWidth+Words.swift | 176 ----------- .../NBKResizableWidth.swift | 42 --- 62 files changed, 3 insertions(+), 1698 deletions(-) delete mode 100644 .swiftpm/NBKResizableWidthKit-Benchmarks.xctestplan delete mode 100644 .swiftpm/NBKResizableWidthKit.xctestplan rename Sources/{ => NBKFlexibleWidthKit}/NBKResizableWidthKit/NBKResizableWidth+Addition+Digit.swift (100%) rename Sources/{ => NBKFlexibleWidthKit}/NBKResizableWidthKit/NBKResizableWidth+Addition.swift (100%) rename Sources/{ => NBKFlexibleWidthKit}/NBKResizableWidthKit/NBKResizableWidth+Bits.swift (100%) rename Sources/{ => NBKFlexibleWidthKit}/NBKResizableWidthKit/NBKResizableWidth+Comparisons.swift (100%) rename Sources/{ => NBKFlexibleWidthKit}/NBKResizableWidthKit/NBKResizableWidth+Complements.swift (100%) rename Sources/{ => NBKFlexibleWidthKit}/NBKResizableWidthKit/NBKResizableWidth+Division+Digit.swift (100%) rename Sources/{ => NBKFlexibleWidthKit}/NBKResizableWidthKit/NBKResizableWidth+Division.swift (100%) rename Sources/{ => NBKFlexibleWidthKit}/NBKResizableWidthKit/NBKResizableWidth+Literals.swift (100%) rename Sources/{ => NBKFlexibleWidthKit}/NBKResizableWidthKit/NBKResizableWidth+Logic.swift (100%) rename Sources/{ => NBKFlexibleWidthKit}/NBKResizableWidthKit/NBKResizableWidth+Multiplication+Digit.swift (100%) rename Sources/{ => NBKFlexibleWidthKit}/NBKResizableWidthKit/NBKResizableWidth+Multiplication.swift (100%) rename Sources/{ => NBKFlexibleWidthKit}/NBKResizableWidthKit/NBKResizableWidth+Numbers.swift (100%) rename Sources/{ => NBKFlexibleWidthKit}/NBKResizableWidthKit/NBKResizableWidth+Protocols.swift (100%) rename Sources/{ => NBKFlexibleWidthKit}/NBKResizableWidthKit/NBKResizableWidth+Shifts.swift (100%) rename Sources/{ => NBKFlexibleWidthKit}/NBKResizableWidthKit/NBKResizableWidth+Size.swift (100%) rename Sources/{ => NBKFlexibleWidthKit}/NBKResizableWidthKit/NBKResizableWidth+Subtraction+Digit.swift (100%) rename Sources/{ => NBKFlexibleWidthKit}/NBKResizableWidthKit/NBKResizableWidth+Subtraction.swift (100%) rename Sources/{ => NBKFlexibleWidthKit}/NBKResizableWidthKit/NBKResizableWidth+Text.swift (98%) rename Sources/{ => NBKFlexibleWidthKit}/NBKResizableWidthKit/NBKResizableWidth+Uninitialized.swift (100%) rename Sources/{ => NBKFlexibleWidthKit}/NBKResizableWidthKit/NBKResizableWidth+Update.swift (100%) rename Sources/{ => NBKFlexibleWidthKit}/NBKResizableWidthKit/NBKResizableWidth+Words+Pointers.swift (100%) rename Sources/{ => NBKFlexibleWidthKit}/NBKResizableWidthKit/NBKResizableWidth+Words.swift (100%) rename Sources/{ => NBKFlexibleWidthKit}/NBKResizableWidthKit/NBKResizableWidth.swift (100%) delete mode 100644 Tests/NBKResizableWidthKitBenchmarks/NBKResizableWidth+Bits.swift delete mode 100644 Tests/NBKResizableWidthKitBenchmarks/NBKResizableWidth+Comparisons.swift delete mode 100644 Tests/NBKResizableWidthKitBenchmarks/NBKResizableWidth+Logic.swift delete mode 100644 Tests/NBKResizableWidthKitBenchmarks/NBKResizableWidth+Shifts.swift delete mode 100644 Tests/NBKResizableWidthKitBenchmarks/NBKResizableWidth+Words.swift delete mode 100644 Tests/NBKResizableWidthKitBenchmarks/NBKResizableWidth.swift delete mode 100644 Tests/NBKResizableWidthKitTests/NBKResizableWidth+Bits.swift delete mode 100644 Tests/NBKResizableWidthKitTests/NBKResizableWidth+Comparisons.swift delete mode 100644 Tests/NBKResizableWidthKitTests/NBKResizableWidth+Logic.swift delete mode 100644 Tests/NBKResizableWidthKitTests/NBKResizableWidth+Shifts.swift delete mode 100644 Tests/NBKResizableWidthKitTests/NBKResizableWidth+Words.swift delete mode 100644 Tests/NBKResizableWidthKitTests/NBKResizableWidth.swift diff --git a/.swiftpm/NBKResizableWidthKit-Benchmarks.xctestplan b/.swiftpm/NBKResizableWidthKit-Benchmarks.xctestplan deleted file mode 100644 index c2f15441..00000000 --- a/.swiftpm/NBKResizableWidthKit-Benchmarks.xctestplan +++ /dev/null @@ -1,24 +0,0 @@ -{ - "configurations" : [ - { - "id" : "2BBD9A51-D890-4B97-AED4-B9962867DF57", - "name" : "Main", - "options" : { - - } - } - ], - "defaultOptions" : { - "codeCoverage" : false - }, - "testTargets" : [ - { - "target" : { - "containerPath" : "container:", - "identifier" : "NBKResizableWidthKitBenchmarks", - "name" : "NBKResizableWidthKitBenchmarks" - } - } - ], - "version" : 1 -} diff --git a/.swiftpm/NBKResizableWidthKit.xctestplan b/.swiftpm/NBKResizableWidthKit.xctestplan deleted file mode 100644 index 1f0eca5f..00000000 --- a/.swiftpm/NBKResizableWidthKit.xctestplan +++ /dev/null @@ -1,32 +0,0 @@ -{ - "configurations" : [ - { - "id" : "6FC9897F-2BF3-4836-8372-787CE5195F87", - "name" : "Main", - "options" : { - - } - } - ], - "defaultOptions" : { - "codeCoverage" : { - "targets" : [ - { - "containerPath" : "container:", - "identifier" : "NBKResizableWidthKit", - "name" : "NBKResizableWidthKit" - } - ] - } - }, - "testTargets" : [ - { - "target" : { - "containerPath" : "container:", - "identifier" : "NBKResizableWidthKitTests", - "name" : "NBKResizableWidthKitTests" - } - } - ], - "version" : 1 -} diff --git a/.swiftpm/Numberick-Benchmarks.xctestplan b/.swiftpm/Numberick-Benchmarks.xctestplan index 36ca600d..b7a219a1 100644 --- a/.swiftpm/Numberick-Benchmarks.xctestplan +++ b/.swiftpm/Numberick-Benchmarks.xctestplan @@ -42,13 +42,6 @@ "identifier" : "NBKFlexibleWidthKitBenchmarks", "name" : "NBKFlexibleWidthKitBenchmarks" } - }, - { - "target" : { - "containerPath" : "container:", - "identifier" : "NBKResizableWidthKitBenchmarks", - "name" : "NBKResizableWidthKitBenchmarks" - } } ], "version" : 1 diff --git a/.swiftpm/Numberick.xctestplan b/.swiftpm/Numberick.xctestplan index a8c7369c..74306fdc 100644 --- a/.swiftpm/Numberick.xctestplan +++ b/.swiftpm/Numberick.xctestplan @@ -25,11 +25,6 @@ "containerPath" : "container:", "identifier" : "NBKFlexibleWidthKit", "name" : "NBKFlexibleWidthKit" - }, - { - "containerPath" : "container:", - "identifier" : "NBKResizableWidthKit", - "name" : "NBKResizableWidthKit" } ] } @@ -55,13 +50,6 @@ "identifier" : "NBKFlexibleWidthKitTests", "name" : "NBKFlexibleWidthKitTests" } - }, - { - "target" : { - "containerPath" : "container:", - "identifier" : "NBKResizableWidthKitTests", - "name" : "NBKResizableWidthKitTests" - } } ], "version" : 1 diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/Numberick-Benchmarks.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/Numberick-Benchmarks.xcscheme index d829dc1f..8cf9cef5 100644 --- a/.swiftpm/xcode/xcshareddata/xcschemes/Numberick-Benchmarks.xcscheme +++ b/.swiftpm/xcode/xcshareddata/xcschemes/Numberick-Benchmarks.xcscheme @@ -38,9 +38,6 @@ - - diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/Numberick.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/Numberick.xcscheme index e28d3bac..7e8b10d0 100644 --- a/.swiftpm/xcode/xcshareddata/xcschemes/Numberick.xcscheme +++ b/.swiftpm/xcode/xcshareddata/xcschemes/Numberick.xcscheme @@ -76,9 +76,6 @@ - - diff --git a/Package.swift b/Package.swift index 444aa103..ca59bbb2 100644 --- a/Package.swift +++ b/Package.swift @@ -54,12 +54,6 @@ var package = Package( .library( name: "NBKFlexibleWidthKit", targets: ["NBKFlexibleWidthKit"]), - //=--------------------------------------= - // NBK x Resizable Width Kit - //=--------------------------------------= - .library( - name: "NBKResizableWidthKit", - targets: ["NBKResizableWidthKit"]), ], targets: [ //=--------------------------------------= @@ -101,7 +95,7 @@ var package = Package( //=--------------------------------------= .target( name: "NBKFlexibleWidthKit", - dependencies: ["NBKCoreKit", "NBKResizableWidthKit"]), + dependencies: ["NBKCoreKit"]), .testTarget( name: "NBKFlexibleWidthKitBenchmarks", @@ -110,20 +104,6 @@ var package = Package( .testTarget( name: "NBKFlexibleWidthKitTests", dependencies: ["NBKFlexibleWidthKit"]), - //=--------------------------------------= - // NBK x Resizable Width Kit - //=--------------------------------------= - .target( - name: "NBKResizableWidthKit", - dependencies: ["NBKCoreKit"]), - - .testTarget( - name: "NBKResizableWidthKitBenchmarks", - dependencies: ["NBKResizableWidthKit"]), - - .testTarget( - name: "NBKResizableWidthKitTests", - dependencies: ["NBKResizableWidthKit"]), ] ) diff --git a/README.md b/README.md index 7ca90095..859af472 100644 --- a/README.md +++ b/README.md @@ -105,10 +105,6 @@ Int256(5) % Int(5), UInt256(5) % UInt(5) 👨‍💻🛠️🚧🧱🧱🏗️🧱🧱🚧⏳ -## [NBKResizableWidthKit][RES/D] ([Sources][RES/S], [Tests][RES/T], [Benchmarks][RES/B]) - -👨‍💻🛠️🚧🧱🧱🏗️🧱🧱🚧⏳ - ## Acknowledgements This project is inspired by [**Int128**][Apple/Int128] and [**DoubleWidth**][Apple/DoubleWidth] by Apple. @@ -118,22 +114,18 @@ This project is inspired by [**Int128**][Apple/Int128] and [**DoubleWidth**][App [NBK/D]: https://oscbyspro.github.io/Numberick/documentation/numberick [DBL/D]: https://oscbyspro.github.io/Numberick/documentation/numberick/nbkdoublewidth [FLX/D]: https://oscbyspro.github.io/Numberick/documentation/numberick/nbkflexiblewidth -[RES/D]: https://oscbyspro.github.io/Numberick/documentation/numberick/nbkresizablewidth [COR/S]: Sources/NBKCoreKit [DBL/S]: Sources/NBKDoubleWidthKit [FLX/S]: Sources/NBKFlexibleWidthKit -[RES/S]: Sources/NBKResizableWidthKit [COR/T]: Tests/NBKCoreKitTests [DBL/T]: Tests/NBKDoubleWidthKitTests [FLX/T]: Tests/NBKFlexibleWidthKitTests -[RES/T]: Tests/NBKResizableWidthKitTests [COR/B]: Tests/NBKCoreKitBenchmarks [DBL/B]: Tests/NBKDoubleWidthKitBenchmarks [FLX/B]: Tests/NBKFlexibleWidthKitBenchmarks -[RES/B]: Tests/NBKResizableWidthKitBenchmarks diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift index cdc168a5..4b66a975 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift @@ -8,7 +8,6 @@ //=----------------------------------------------------------------------------= import NBKCoreKit -import NBKResizableWidthKit //*============================================================================* // MARK: * NBK x Flexible Width x Addition x Digit x Signed diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift index c0e35557..e61d899b 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift @@ -8,7 +8,6 @@ //=----------------------------------------------------------------------------= import NBKCoreKit -import NBKResizableWidthKit //*============================================================================* // MARK: * NBK x Flexible Width x Addition x Signed diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift index c024126e..2a021653 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift @@ -8,7 +8,6 @@ //=----------------------------------------------------------------------------= import NBKCoreKit -import NBKResizableWidthKit //*============================================================================* // MARK: * NBK x Flexible Width x Bits x Signed diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift index 551239cf..def8ce40 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift @@ -8,7 +8,6 @@ //=----------------------------------------------------------------------------= import NBKCoreKit -import NBKResizableWidthKit //*============================================================================* // MARK: * NBK x Flexible Width x Comparisons x Signed diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements.swift index 39ff5c27..1c74ea10 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements.swift @@ -8,7 +8,6 @@ //=----------------------------------------------------------------------------= import NBKCoreKit -import NBKResizableWidthKit //*============================================================================* // MARK: * NBK x Flexible Width x Complements x Signed diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.swift index e1e5d857..66f7e7b9 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.swift @@ -8,7 +8,6 @@ //=----------------------------------------------------------------------------= import NBKCoreKit -import NBKResizableWidthKit //*============================================================================* // MARK: * NBK x Flexible Width x Division x Digit x Signed diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift index 0ed355eb..f514fb7e 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift @@ -8,7 +8,6 @@ //=----------------------------------------------------------------------------= import NBKCoreKit -import NBKResizableWidthKit //*============================================================================* // MARK: * NBK x Flexible Width x Division x Signed diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift index 29caa943..3d70f1f5 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift @@ -8,7 +8,6 @@ //=----------------------------------------------------------------------------= import NBKCoreKit -import NBKResizableWidthKit //*============================================================================* // MARK: * NBK x Flexible Width x Logic x Signed diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift index 0486f3df..1d6e3038 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift @@ -8,7 +8,6 @@ //=----------------------------------------------------------------------------= import NBKCoreKit -import NBKResizableWidthKit //*============================================================================* // MARK: * NBK x Flexible Width x Multiplication x Digit x Signed diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift index 8fde35ce..fd0f5b21 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift @@ -8,7 +8,6 @@ //=----------------------------------------------------------------------------= import NBKCoreKit -import NBKResizableWidthKit //*============================================================================* // MARK: * NBK x Flexible Width x Multiplication x Signed diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift index ddff8df9..a50ff1f9 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift @@ -8,7 +8,6 @@ //=----------------------------------------------------------------------------= import NBKCoreKit -import NBKResizableWidthKit //*============================================================================* // MARK: * NBK x Flexible Width x Numbers x Signed diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift index 32a4f0e2..e60b8bb5 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift @@ -8,7 +8,6 @@ //=----------------------------------------------------------------------------= import NBKCoreKit -import NBKResizableWidthKit //*============================================================================* // MARK: * NBK x Flexible Width x Shifts x Signed diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Size.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Size.swift index b6d86c8d..c4b3bb2e 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Size.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Size.swift @@ -8,7 +8,6 @@ //=----------------------------------------------------------------------------= import NBKCoreKit -import NBKResizableWidthKit //*============================================================================* // MARK: * NBK x Flexible Width x Size x Signed diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift index 33881815..4bd5fc07 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift @@ -8,7 +8,6 @@ //=----------------------------------------------------------------------------= import NBKCoreKit -import NBKResizableWidthKit //*============================================================================* // MARK: * NBK x Flexible Width x Subtraction x Digit x Signed diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift index a443026b..b1acf0e8 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift @@ -8,7 +8,6 @@ //=----------------------------------------------------------------------------= import NBKCoreKit -import NBKResizableWidthKit //*============================================================================* // MARK: * NBK x Flexible Width x Subtraction diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text.swift index 9e5a8276..ca58a24e 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text.swift @@ -8,7 +8,6 @@ //=----------------------------------------------------------------------------= import NBKCoreKit -import NBKResizableWidthKit //*============================================================================* // MARK: * NBK x Flexible Width x Text x Signed diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Update.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Update.swift index f68992f1..60c180d8 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Update.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Update.swift @@ -8,7 +8,6 @@ //=----------------------------------------------------------------------------= import NBKCoreKit -import NBKResizableWidthKit //*============================================================================* // MARK: * NBK x Flexible Width x Miscellaneous x Signed diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift index f5d15ca4..cf177d24 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift @@ -8,7 +8,6 @@ //=----------------------------------------------------------------------------= import NBKCoreKit -import NBKResizableWidthKit //*============================================================================* // MARK: * NBK x Flexible Width x Words x Signed diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift index 95d59d74..adaf47ca 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift @@ -8,7 +8,6 @@ //=----------------------------------------------------------------------------= import NBKCoreKit -import NBKResizableWidthKit //*============================================================================* // MARK: * NBK x Flexible Width diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Addition+Digit.swift similarity index 100% rename from Sources/NBKResizableWidthKit/NBKResizableWidth+Addition+Digit.swift rename to Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Addition+Digit.swift diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Addition.swift b/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Addition.swift similarity index 100% rename from Sources/NBKResizableWidthKit/NBKResizableWidth+Addition.swift rename to Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Addition.swift diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Bits.swift b/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Bits.swift similarity index 100% rename from Sources/NBKResizableWidthKit/NBKResizableWidth+Bits.swift rename to Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Bits.swift diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Comparisons.swift b/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Comparisons.swift similarity index 100% rename from Sources/NBKResizableWidthKit/NBKResizableWidth+Comparisons.swift rename to Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Comparisons.swift diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Complements.swift b/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Complements.swift similarity index 100% rename from Sources/NBKResizableWidthKit/NBKResizableWidth+Complements.swift rename to Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Complements.swift diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Division+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Division+Digit.swift similarity index 100% rename from Sources/NBKResizableWidthKit/NBKResizableWidth+Division+Digit.swift rename to Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Division+Digit.swift diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Division.swift b/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Division.swift similarity index 100% rename from Sources/NBKResizableWidthKit/NBKResizableWidth+Division.swift rename to Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Division.swift diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Literals.swift b/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Literals.swift similarity index 100% rename from Sources/NBKResizableWidthKit/NBKResizableWidth+Literals.swift rename to Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Literals.swift diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Logic.swift b/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Logic.swift similarity index 100% rename from Sources/NBKResizableWidthKit/NBKResizableWidth+Logic.swift rename to Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Logic.swift diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Multiplication+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Multiplication+Digit.swift similarity index 100% rename from Sources/NBKResizableWidthKit/NBKResizableWidth+Multiplication+Digit.swift rename to Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Multiplication+Digit.swift diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Multiplication.swift b/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Multiplication.swift similarity index 100% rename from Sources/NBKResizableWidthKit/NBKResizableWidth+Multiplication.swift rename to Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Multiplication.swift diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Numbers.swift b/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Numbers.swift similarity index 100% rename from Sources/NBKResizableWidthKit/NBKResizableWidth+Numbers.swift rename to Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Numbers.swift diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Protocols.swift b/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Protocols.swift similarity index 100% rename from Sources/NBKResizableWidthKit/NBKResizableWidth+Protocols.swift rename to Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Protocols.swift diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Shifts.swift b/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Shifts.swift similarity index 100% rename from Sources/NBKResizableWidthKit/NBKResizableWidth+Shifts.swift rename to Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Shifts.swift diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Size.swift b/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Size.swift similarity index 100% rename from Sources/NBKResizableWidthKit/NBKResizableWidth+Size.swift rename to Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Size.swift diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Subtraction+Digit.swift similarity index 100% rename from Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction+Digit.swift rename to Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Subtraction+Digit.swift diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction.swift b/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Subtraction.swift similarity index 100% rename from Sources/NBKResizableWidthKit/NBKResizableWidth+Subtraction.swift rename to Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Subtraction.swift diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Text.swift b/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Text.swift similarity index 98% rename from Sources/NBKResizableWidthKit/NBKResizableWidth+Text.swift rename to Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Text.swift index f729c255..2f986d6b 100644 --- a/Sources/NBKResizableWidthKit/NBKResizableWidth+Text.swift +++ b/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Text.swift @@ -7,6 +7,8 @@ // See http://www.apache.org/licenses/LICENSE-2.0 for license information. //=----------------------------------------------------------------------------= +import NBKCoreKit + //*============================================================================* // MARK: * NBK x Resizable Width x Text //*============================================================================* diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Uninitialized.swift b/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Uninitialized.swift similarity index 100% rename from Sources/NBKResizableWidthKit/NBKResizableWidth+Uninitialized.swift rename to Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Uninitialized.swift diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Update.swift b/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Update.swift similarity index 100% rename from Sources/NBKResizableWidthKit/NBKResizableWidth+Update.swift rename to Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Update.swift diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Words+Pointers.swift b/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Words+Pointers.swift similarity index 100% rename from Sources/NBKResizableWidthKit/NBKResizableWidth+Words+Pointers.swift rename to Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Words+Pointers.swift diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth+Words.swift b/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Words.swift similarity index 100% rename from Sources/NBKResizableWidthKit/NBKResizableWidth+Words.swift rename to Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Words.swift diff --git a/Sources/NBKResizableWidthKit/NBKResizableWidth.swift b/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth.swift similarity index 100% rename from Sources/NBKResizableWidthKit/NBKResizableWidth.swift rename to Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth.swift diff --git a/Tests/NBKResizableWidthKitBenchmarks/NBKResizableWidth+Bits.swift b/Tests/NBKResizableWidthKitBenchmarks/NBKResizableWidth+Bits.swift deleted file mode 100644 index a3a8c7d2..00000000 --- a/Tests/NBKResizableWidthKitBenchmarks/NBKResizableWidth+Bits.swift +++ /dev/null @@ -1,124 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if !DEBUG - -import NBKCoreKit -import NBKResizableWidthKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Resizable Width x Bits x UIntXR -//*============================================================================* - -final class NBKResizableWidthBenchmarksOnBitsAsUIntXR: XCTestCase { - - typealias T = UIntXR - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testInitBit() { - var abc = NBK.blackHoleIdentity(true ) - var xyz = NBK.blackHoleIdentity(false) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(T(bit: abc)) - NBK.blackHole(T(bit: xyz)) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - func testBitWidth() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.bitWidth) - NBK.blackHole(xyz.bitWidth) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - func testNonzeroBitCount() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.nonzeroBitCount) - NBK.blackHole(xyz.nonzeroBitCount) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - func testLeadingZeroBitCount() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.leadingZeroBitCount) - NBK.blackHole(xyz.leadingZeroBitCount) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - func testTrailingZeroBitCount() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.trailingZeroBitCount) - NBK.blackHole(xyz.trailingZeroBitCount) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - func testMostSignificantBit() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.mostSignificantBit) - NBK.blackHole(xyz.mostSignificantBit) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - func testLeastSignificantBit() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.leastSignificantBit) - NBK.blackHole(xyz.leastSignificantBit) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } -} - -#endif diff --git a/Tests/NBKResizableWidthKitBenchmarks/NBKResizableWidth+Comparisons.swift b/Tests/NBKResizableWidthKitBenchmarks/NBKResizableWidth+Comparisons.swift deleted file mode 100644 index 81233d5b..00000000 --- a/Tests/NBKResizableWidthKitBenchmarks/NBKResizableWidth+Comparisons.swift +++ /dev/null @@ -1,150 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if !DEBUG - -import NBKCoreKit -import NBKResizableWidthKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Resizable Width x Comparisons x UIntXR -//*============================================================================* - -final class NBKResizableWidthBenchmarksOnComparisonsAsUIntXR: XCTestCase { - - typealias T = UIntXR - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testIsZero() { - var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.isZero) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testIsLessThanZero() { - var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.isLessThanZero) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testIsMoreThanZero() { - var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.isMoreThanZero) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testIsPowerOf2() { - var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.isPowerOf2) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testSignum() { - var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.signum()) - NBK.blackHoleInoutIdentity(&abc) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testIsEqualTo() { - var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(lhs == rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testIsLessThan() { - var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(lhs < rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testComparedTo() { - var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(lhs.compared(to: rhs)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testComparedToAtIndex() { - var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[1, 2, 3, 0] as X)) - let xyz = NBK.blackHoleIdentity(1 as Int) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(lhs.compared(to: rhs, at: xyz)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testComparedToDigit() { - var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - var rhs = NBK.blackHoleIdentity(UInt.max) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(lhs.compared(to: rhs)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testComparedToDigitAtIndex() { - var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - var rhs = NBK.blackHoleIdentity(UInt( 3)) - let xyz = NBK.blackHoleIdentity(3 as Int) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(lhs.compared(to: rhs, at: xyz)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } -} - -#endif diff --git a/Tests/NBKResizableWidthKitBenchmarks/NBKResizableWidth+Logic.swift b/Tests/NBKResizableWidthKitBenchmarks/NBKResizableWidth+Logic.swift deleted file mode 100644 index c84d3acd..00000000 --- a/Tests/NBKResizableWidthKitBenchmarks/NBKResizableWidth+Logic.swift +++ /dev/null @@ -1,117 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if !DEBUG - -import NBKCoreKit -import NBKResizableWidthKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Resizable Width x Logic x UIntXR -//*============================================================================* - -final class NBKResizableWidthBenchmarksOnLogicAsUIntXR: XCTestCase { - - typealias T = UIntXR - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testNotInout() { - var abc = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.formOnesComplement()) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testNot() { - var abc = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(~abc) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testAndInout() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(lhs &= rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testAnd() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs & rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testOrInout() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(lhs |= rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testOr() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs | rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testXorInout() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(lhs ^= rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testXor() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs ^ rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } -} - -#endif diff --git a/Tests/NBKResizableWidthKitBenchmarks/NBKResizableWidth+Shifts.swift b/Tests/NBKResizableWidthKitBenchmarks/NBKResizableWidth+Shifts.swift deleted file mode 100644 index c745d9be..00000000 --- a/Tests/NBKResizableWidthKitBenchmarks/NBKResizableWidth+Shifts.swift +++ /dev/null @@ -1,152 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if !DEBUG - -import NBKCoreKit -import NBKResizableWidthKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Resizable Width x Shifts x UIntXR -//*============================================================================* - -final class NBKResizableWidthBenchmarksOnShiftsAsUIntXR: XCTestCase { - - typealias T = UIntXR - - //=------------------------------------------------------------------------= - // MARK: Tests x Left - //=------------------------------------------------------------------------= - - func testBitshiftingLeft() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(UInt.bitWidth * 3/2) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs << rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testBitshiftingLeftByWords() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs.bitshiftedLeft(words: rhs.words)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testBitshiftingLeftByWordsAndBits() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs.bitshiftedLeft(words: rhs.words, bits: rhs.bits)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Right - //=------------------------------------------------------------------------= - - func testBitshiftingRight() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(UInt.bitWidth * 3/2) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs >> rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testBitshiftingRightByWords() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs.bitshiftedRight(words: rhs.words)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testBitshiftingRightByWordsAndBits() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs.bitshiftedRight(words: rhs.words, bits: rhs.bits)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x In Both Directions - //=------------------------------------------------------------------------= - - func testBitshiftingInBothDirectionsInout() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(UInt.bitWidth * 3/2) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs.bitshiftLeft (by: rhs)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - - NBK.blackHole(lhs.bitshiftRight(by: rhs)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testBitshiftingInBothDirectionsByWordsInout() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs.bitshiftLeft (words: rhs.words)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - - NBK.blackHole(lhs.bitshiftRight(words: rhs.words)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testBitshiftingInBothDirectionsByWordsAndBitsInout() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs.bitshiftLeft (words: rhs.words, bits: rhs.bits)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - - NBK.blackHole(lhs.bitshiftRight(words: rhs.words, bits: rhs.bits)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } -} - -#endif diff --git a/Tests/NBKResizableWidthKitBenchmarks/NBKResizableWidth+Words.swift b/Tests/NBKResizableWidthKitBenchmarks/NBKResizableWidth+Words.swift deleted file mode 100644 index 9461d00d..00000000 --- a/Tests/NBKResizableWidthKitBenchmarks/NBKResizableWidth+Words.swift +++ /dev/null @@ -1,46 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if !DEBUG - -import NBKCoreKit -import NBKResizableWidthKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Resizable Width x Words x UIntXR -//*============================================================================* - -final class NBKResizableWidthBenchmarksOnWordsAsUIntXR: XCTestCase { - - typealias T = UIntXR - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testFromWords() { - var abc = NBK.blackHoleIdentity([ 0, 0, 0, 0] as W) - var xyz = NBK.blackHoleIdentity([~0, ~0, ~0, ~0] as W) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(T(words: abc)) - NBK.blackHole(T(words: xyz)) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } -} - -#endif diff --git a/Tests/NBKResizableWidthKitBenchmarks/NBKResizableWidth.swift b/Tests/NBKResizableWidthKitBenchmarks/NBKResizableWidth.swift deleted file mode 100644 index 3c57b0b3..00000000 --- a/Tests/NBKResizableWidthKitBenchmarks/NBKResizableWidth.swift +++ /dev/null @@ -1,42 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit -import NBKResizableWidthKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Resizable Width x Initializers x UIntXR -//*============================================================================* - -extension NBKResizableWidth.Magnitude { - - //=------------------------------------------------------------------------= - // MARK: Details x Numbers - //=------------------------------------------------------------------------= - - static let min256 = Self(x64:[ 0, 0, 0, 0] as X) - static let max256 = Self(x64:[~0, ~0, ~0, ~0] as X) - - //=------------------------------------------------------------------------= - // MARK: Details x Limbs - //=------------------------------------------------------------------------= - - init(x32: [UInt32]) { - self.init(words: NBKChunkedInt(x32)) - } - - init(x64: [UInt64]) { - self.init(words: NBKChunkedInt(x64)) - } -} diff --git a/Tests/NBKResizableWidthKitTests/NBKResizableWidth+Bits.swift b/Tests/NBKResizableWidthKitTests/NBKResizableWidth+Bits.swift deleted file mode 100644 index 790ff3ca..00000000 --- a/Tests/NBKResizableWidthKitTests/NBKResizableWidth+Bits.swift +++ /dev/null @@ -1,99 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if DEBUG - -import NBKCoreKit -import NBKResizableWidthKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Resizable Width x Bits x UIntXR -//*============================================================================* - -final class NBKResizableWidthTestsOnBitsAsUIntXR: XCTestCase { - - typealias T = UIntXR - typealias M = UIntXR - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testInitBit() { - XCTAssertEqual(T(bit: false), T( )) - XCTAssertEqual(T(bit: true ), T(1)) - } - - func testBitWidth() { - XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).bitWidth, UInt.bitWidth * 4) - XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).bitWidth, UInt.bitWidth * 4) - } - - func testNonzeroBitCount() { - XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).nonzeroBitCount, 0) - XCTAssertEqual(T(words:[ 1, 1, 1, 1] as W).nonzeroBitCount, 4) - } - - func testLeadingZeroBitCount() { - XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).leadingZeroBitCount, UInt.bitWidth * 4) - XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).leadingZeroBitCount, UInt.bitWidth * 0) - - XCTAssertEqual(T(words:[ 2, 0, 0, 0] as W).leadingZeroBitCount, UInt.bitWidth * 4 - 2) - XCTAssertEqual(T(words:[ 0, 2, 0, 0] as W).leadingZeroBitCount, UInt.bitWidth * 3 - 2) - XCTAssertEqual(T(words:[ 0, 0, 2, 0] as W).leadingZeroBitCount, UInt.bitWidth * 2 - 2) - XCTAssertEqual(T(words:[ 0, 0, 0, 2] as W).leadingZeroBitCount, UInt.bitWidth * 1 - 2) - } - - func testTrailingZeroBitCount() { - XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).trailingZeroBitCount, UInt.bitWidth * 4) - XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).trailingZeroBitCount, UInt.bitWidth * 0) - - XCTAssertEqual(T(words:[ 2, 0, 0, 0] as W).trailingZeroBitCount, UInt.bitWidth * 0 + 1) - XCTAssertEqual(T(words:[ 0, 2, 0, 0] as W).trailingZeroBitCount, UInt.bitWidth * 1 + 1) - XCTAssertEqual(T(words:[ 0, 0, 2, 0] as W).trailingZeroBitCount, UInt.bitWidth * 2 + 1) - XCTAssertEqual(T(words:[ 0, 0, 0, 2] as W).trailingZeroBitCount, UInt.bitWidth * 3 + 1) - } - - func testMostSignificantBit() { - XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).mostSignificantBit, false) - XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).mostSignificantBit, true ) - - XCTAssertEqual(T(words:[~0, 0, 0, 0] as W).mostSignificantBit, false) - XCTAssertEqual(T(words:[ 0, ~0, 0, 0] as W).mostSignificantBit, false) - XCTAssertEqual(T(words:[ 0, 0, ~0, 0] as W).mostSignificantBit, false) - XCTAssertEqual(T(words:[ 0, 0, 0, ~0] as W).mostSignificantBit, true ) - - XCTAssertEqual(T(words:[~0, 1, 0, 0] as W).mostSignificantBit, false) - XCTAssertEqual(T(words:[ 0, ~0, 1, 0] as W).mostSignificantBit, false) - XCTAssertEqual(T(words:[ 0, 0, ~0, 1] as W).mostSignificantBit, false) - XCTAssertEqual(T(words:[ 1, 0, 0, ~0] as W).mostSignificantBit, true ) - } - - func testLeastSignificantBit() { - XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).leastSignificantBit, false) - XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).leastSignificantBit, true ) - - XCTAssertEqual(T(words:[~0, 0, 0, 0] as W).leastSignificantBit, true ) - XCTAssertEqual(T(words:[ 0, ~0, 0, 0] as W).leastSignificantBit, false) - XCTAssertEqual(T(words:[ 0, 0, ~0, 0] as W).leastSignificantBit, false) - XCTAssertEqual(T(words:[ 0, 0, 0, ~0] as W).leastSignificantBit, false) - - XCTAssertEqual(T(words:[~0, 1, 0, 0] as W).leastSignificantBit, true ) - XCTAssertEqual(T(words:[ 0, ~0, 1, 0] as W).leastSignificantBit, false) - XCTAssertEqual(T(words:[ 0, 0, ~0, 1] as W).leastSignificantBit, false) - XCTAssertEqual(T(words:[ 1, 0, 0, ~0] as W).leastSignificantBit, true ) - } -} - -#endif diff --git a/Tests/NBKResizableWidthKitTests/NBKResizableWidth+Comparisons.swift b/Tests/NBKResizableWidthKitTests/NBKResizableWidth+Comparisons.swift deleted file mode 100644 index 49ce4961..00000000 --- a/Tests/NBKResizableWidthKitTests/NBKResizableWidth+Comparisons.swift +++ /dev/null @@ -1,284 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if DEBUG - -import NBKCoreKit -import NBKResizableWidthKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Resizable Width x Comparisons x UIntXR -//*============================================================================* - -final class NBKResizableWidthTestsOnComparisonsAsUIntXR: XCTestCase { - - typealias T = UIntXR - typealias M = UIntXR - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testIsZero() { - XCTAssertTrue (T(words:[ 0] as W).isZero) - XCTAssertFalse(T(words:[ 1] as W).isZero) - XCTAssertFalse(T(words:[ 2] as W).isZero) - - XCTAssertFalse(T(words:[~0] as W).isZero) - XCTAssertFalse(T(words:[~1] as W).isZero) - XCTAssertFalse(T(words:[~2] as W).isZero) - } - - func testIsLessThanZero() { - XCTAssertFalse(T(words:[ 0] as W).isLessThanZero) - XCTAssertFalse(T(words:[ 1] as W).isLessThanZero) - XCTAssertFalse(T(words:[ 2] as W).isLessThanZero) - - XCTAssertFalse(T(words:[~0] as W).isLessThanZero) - XCTAssertFalse(T(words:[~1] as W).isLessThanZero) - XCTAssertFalse(T(words:[~2] as W).isLessThanZero) - } - - func testIsMoreThanZero() { - XCTAssertFalse(T(words:[ 0] as W).isMoreThanZero) - XCTAssertTrue (T(words:[ 1] as W).isMoreThanZero) - XCTAssertTrue (T(words:[ 2] as W).isMoreThanZero) - - XCTAssertTrue (T(words:[~0] as W).isMoreThanZero) - XCTAssertTrue (T(words:[~1] as W).isMoreThanZero) - XCTAssertTrue (T(words:[~2] as W).isMoreThanZero) - } - - func testIsOdd() { - XCTAssertFalse(T(words:[ 0] as W).isOdd) - XCTAssertTrue (T(words:[ 1] as W).isOdd) - XCTAssertFalse(T(words:[ 2] as W).isOdd) - - XCTAssertTrue (T(words:[~0] as W).isOdd) - XCTAssertFalse(T(words:[~1] as W).isOdd) - XCTAssertTrue (T(words:[~2] as W).isOdd) - } - - func testIsEven() { - XCTAssertTrue (T(words:[ 0] as W).isEven) - XCTAssertFalse(T(words:[ 1] as W).isEven) - XCTAssertTrue (T(words:[ 2] as W).isEven) - - XCTAssertFalse(T(words:[~0] as W).isEven) - XCTAssertTrue (T(words:[~1] as W).isEven) - XCTAssertFalse(T(words:[~2] as W).isEven) - } - - func testIsPowerOf2() { - XCTAssertFalse(T(words:[ 0] as W).isPowerOf2) - XCTAssertTrue (T(words:[ 1] as W).isPowerOf2) - XCTAssertTrue (T(words:[ 2] as W).isPowerOf2) - XCTAssertFalse(T(words:[ 3] as W).isPowerOf2) - XCTAssertTrue (T(words:[ 4] as W).isPowerOf2) - XCTAssertFalse(T(words:[ 5] as W).isPowerOf2) - XCTAssertFalse(T(words:[ 6] as W).isPowerOf2) - XCTAssertFalse(T(words:[ 7] as W).isPowerOf2) - - XCTAssertFalse(T(words:[ 0, 0, 0, 0] as W).isPowerOf2) - XCTAssertTrue (T(words:[ 1, 0, 0, 0] as W).isPowerOf2) - XCTAssertFalse(T(words:[ 1, 1, 0, 0] as W).isPowerOf2) - XCTAssertTrue (T(words:[ 0, 1, 0, 0] as W).isPowerOf2) - XCTAssertFalse(T(words:[ 0, 1, 1, 0] as W).isPowerOf2) - XCTAssertTrue (T(words:[ 0, 0, 1, 0] as W).isPowerOf2) - XCTAssertFalse(T(words:[ 0, 0, 1, 1] as W).isPowerOf2) - XCTAssertTrue (T(words:[ 0, 0, 0, 1] as W).isPowerOf2) - } - - func testSignum() { - NBKAssertSignum(T(words:[ 0] as W), Int(0)) - NBKAssertSignum(T(words:[ 1] as W), Int(1)) - NBKAssertSignum(T(words:[ 2] as W), Int(1)) - - NBKAssertSignum(T(words:[~0] as W), Int(1)) - NBKAssertSignum(T(words:[~1] as W), Int(1)) - NBKAssertSignum(T(words:[~2] as W), Int(1)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testHashing() { - var union = Set() - union.insert(T(words:[0, 0, 0, 0] as W)) - union.insert(T(words:[0, 0, 0, 0] as W)) - union.insert(T(words:[1, 0, 0, 0] as W)) - union.insert(T(words:[1, 0, 0, 0] as W)) - union.insert(T(words:[0, 1, 0, 0] as W)) - union.insert(T(words:[0, 1, 0, 0] as W)) - union.insert(T(words:[0, 0, 1, 0] as W)) - union.insert(T(words:[0, 0, 1, 0] as W)) - union.insert(T(words:[0, 0, 0, 1] as W)) - union.insert(T(words:[0, 0, 0, 1] as W)) - XCTAssertEqual(union.count, 5 as Int) - } - - func testComparing() { - NBKAssertComparisons(T(words:[0, 2, 3, 4] as W), T(words:[1, 2, 3, 4] as W), -Int(1)) - NBKAssertComparisons(T(words:[1, 0, 3, 4] as W), T(words:[1, 2, 3, 4] as W), -Int(1)) - NBKAssertComparisons(T(words:[1, 2, 0, 4] as W), T(words:[1, 2, 3, 4] as W), -Int(1)) - NBKAssertComparisons(T(words:[1, 2, 3, 0] as W), T(words:[1, 2, 3, 4] as W), -Int(1)) - NBKAssertComparisons(T(words:[0, 2, 3, 4] as W), T(words:[0, 2, 3, 4] as W), Int(0)) - NBKAssertComparisons(T(words:[1, 0, 3, 4] as W), T(words:[1, 0, 3, 4] as W), Int(0)) - NBKAssertComparisons(T(words:[1, 2, 0, 4] as W), T(words:[1, 2, 0, 4] as W), Int(0)) - NBKAssertComparisons(T(words:[1, 2, 3, 0] as W), T(words:[1, 2, 3, 0] as W), Int(0)) - NBKAssertComparisons(T(words:[1, 2, 3, 4] as W), T(words:[0, 2, 3, 4] as W), Int(1)) - NBKAssertComparisons(T(words:[1, 2, 3, 4] as W), T(words:[1, 0, 3, 4] as W), Int(1)) - NBKAssertComparisons(T(words:[1, 2, 3, 4] as W), T(words:[1, 2, 0, 4] as W), Int(1)) - NBKAssertComparisons(T(words:[1, 2, 3, 4] as W), T(words:[1, 2, 3, 0] as W), Int(1)) - } - - func testComparingAtIndex() { - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(0), Int(0)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(1), Int(0)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(2), Int(0)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(3), Int(0)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(4), Int(0)) - - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(0), -Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(1), -Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(2), -Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(3), -Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(4), -Int(1)) - - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(0), Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(1), Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(2), Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(3), Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(4), Int(1)) - - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(0), Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(1), Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(2), Int(0)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(3), -Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(4), -Int(1)) - } - - func testComparingByDigit() { - NBKAssertComparisonsByDigit(T(0), UInt(0), Int(0)) - NBKAssertComparisonsByDigit(T(1), UInt(1), Int(0)) - NBKAssertComparisonsByDigit(T(2), UInt(3), -Int(1)) - NBKAssertComparisonsByDigit(T(3), UInt(2), Int(1)) - - NBKAssertComparisonsByDigit(T(words:[0, 0, 0, 0]), UInt(1), -Int(1)) - NBKAssertComparisonsByDigit(T(words:[1, 0, 0, 0]), UInt(1), Int(0)) - NBKAssertComparisonsByDigit(T(words:[2, 0, 0, 0]), UInt(1), Int(1)) - - NBKAssertComparisonsByDigit(T(words:[0, 1, 0, 0]), UInt(1), Int(1)) - NBKAssertComparisonsByDigit(T(words:[1, 1, 0, 0]), UInt(1), Int(1)) - NBKAssertComparisonsByDigit(T(words:[2, 1, 0, 0]), UInt(1), Int(1)) - } - - func testComparingByDigitAtIndex() { - NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), UInt(4), Int(0), Int(1)) - NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), UInt(4), Int(1), Int(1)) - NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), UInt(4), Int(2), Int(1)) - NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), UInt(4), Int(3), Int(1)) - NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), UInt(4), Int(4), -Int(1)) - - NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), UInt(5), Int(0), Int(1)) - NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), UInt(5), Int(1), Int(1)) - NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), UInt(5), Int(2), Int(1)) - NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), UInt(5), Int(3), -Int(1)) - NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), UInt(5), Int(4), -Int(1)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Miscellaneous - //=------------------------------------------------------------------------= - - func testOverloadsAreUnambiguous() { - func becauseThisCompilesSuccessfully(_ x: inout T) { - XCTAssertNotNil(x.signum()) - } - } - - func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { - func becauseThisCompilesSuccessfully(_ x: inout T) { - XCTAssertNotNil(x.compared(to: 0)) - XCTAssertNotNil(x.compared(to: 0, at: 0)) - } - } -} - -//*============================================================================* -// MARK: * NBK x Resizable Width x Comparisons x Assertions -//*============================================================================* - -private func NBKAssertSignum( -_ operand: T, _ signum: Int, -file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual(Int(operand.signum() as Int), signum, file: file, line: line) - // TODO: stdlib implementation requires subtraction - // XCTAssertEqual(Int(operand.signum() as T ), signum, file: file, line: line) // stdlib -} - -private func NBKAssertComparisons( -_ lhs: T, _ rhs: T, _ signum: Int, -file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual(lhs == rhs, signum == 0, file: file, line: line) - XCTAssertEqual(lhs != rhs, signum != 0, file: file, line: line) - - XCTAssertEqual(lhs < rhs, signum == -1, file: file, line: line) - XCTAssertEqual(lhs <= rhs, signum != 1, file: file, line: line) - - XCTAssertEqual(lhs > rhs, signum == 1, file: file, line: line) - XCTAssertEqual(lhs >= rhs, signum != -1, file: file, line: line) - - XCTAssertEqual(lhs.compared(to: rhs), signum, file: file, line: line) -} - -private func NBKAssertComparisonsAtIndex( -_ lhs: T, _ rhs: T, _ index: Int, _ signum: Int, -file: StaticString = #file, line: UInt = #line) { - //=------------------------------------------= - if index.isZero { - NBKAssertComparisons(lhs, rhs, signum, file: file, line: line) - } - //=------------------------------------------= - XCTAssertEqual(lhs.compared(to: rhs, at: index), signum, file: file, line: line) -} - -private func NBKAssertComparisonsByDigit( -_ lhs: T, _ rhs: T.Digit, _ signum: Int, -file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual(lhs == rhs, signum == 0, file: file, line: line) - XCTAssertEqual(lhs != rhs, signum != 0, file: file, line: line) - - XCTAssertEqual(lhs < rhs, signum == -1, file: file, line: line) - XCTAssertEqual(lhs <= rhs, signum != 1, file: file, line: line) - - XCTAssertEqual(lhs > rhs, signum == 1, file: file, line: line) - XCTAssertEqual(lhs >= rhs, signum != -1, file: file, line: line) - - XCTAssertEqual(lhs.compared(to: rhs), signum, file: file, line: line) -} - -private func NBKAssertComparisonsByDigitAtIndex( -_ lhs: T, _ rhs: T.Digit, _ index: Int, _ signum: Int, -file: StaticString = #file, line: UInt = #line) { - //=------------------------------------------= - if index.isZero { - NBKAssertComparisonsByDigit(lhs, rhs, signum, file: file, line: line) - } - //=------------------------------------------= - XCTAssertEqual(lhs.compared(to: rhs, at: index), signum, file: file, line: line) -} - -#endif diff --git a/Tests/NBKResizableWidthKitTests/NBKResizableWidth+Logic.swift b/Tests/NBKResizableWidthKitTests/NBKResizableWidth+Logic.swift deleted file mode 100644 index 40bf33ca..00000000 --- a/Tests/NBKResizableWidthKitTests/NBKResizableWidth+Logic.swift +++ /dev/null @@ -1,131 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if DEBUG - -import NBKCoreKit -import NBKResizableWidthKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Resizable Width x Logic x UIntXR -//*============================================================================* - -final class NBKResizableWidthTestsOnLogicAsUIntXR: XCTestCase { - - typealias T = UIntXR - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testNot() { - NBKAssertNot(T(words:[ 0, 0, 0, 0] as W), T(words:[~0, ~0, ~0, ~0] as W)) - NBKAssertNot(T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 0, 0, 0, 0] as W)) - - NBKAssertNot(T(words:[ 0, 1, 2, 3] as W), T(words:[~0, ~1, ~2, ~3] as W)) - NBKAssertNot(T(words:[~0, ~1, ~2, ~3] as W), T(words:[ 0, 1, 2, 3] as W)) - } - - func testAnd() { - NBKAssertAnd(T(words:[ 0, 1, 2, 3] as W), T(words:[ 0, 0, 0, 0] as W), T(words:[ 0, 0, 0, 0] as W)) - NBKAssertAnd(T(words:[ 3, 2, 1, 0] as W), T(words:[ 0, 0, 0, 0] as W), T(words:[ 0, 0, 0, 0] as W)) - - NBKAssertAnd(T(words:[ 0, 1, 2, 3] as W), T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 0, 1, 2, 3] as W)) - NBKAssertAnd(T(words:[ 3, 2, 1, 0] as W), T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 3, 2, 1, 0] as W)) - - NBKAssertAnd(T(words:[ 0, 1, 2, 3] as W), T(words:[ 1, 1, 1, 1] as W), T(words:[ 0, 1, 0, 1] as W)) - NBKAssertAnd(T(words:[ 3, 2, 1, 0] as W), T(words:[ 1, 1, 1, 1] as W), T(words:[ 1, 0, 1, 0] as W)) - } - - func testOr() { - NBKAssertOr (T(words:[ 0, 1, 2, 3] as W), T(words:[ 0, 0, 0, 0] as W), T(words:[ 0, 1, 2, 3] as W)) - NBKAssertOr (T(words:[ 3, 2, 1, 0] as W), T(words:[ 0, 0, 0, 0] as W), T(words:[ 3, 2, 1, 0] as W)) - - NBKAssertOr (T(words:[ 0, 1, 2, 3] as W), T(words:[~0, ~0, ~0, ~0] as W), T(words:[~0, ~0, ~0, ~0] as W)) - NBKAssertOr (T(words:[ 3, 2, 1, 0] as W), T(words:[~0, ~0, ~0, ~0] as W), T(words:[~0, ~0, ~0, ~0] as W)) - - NBKAssertOr (T(words:[ 0, 1, 2, 3] as W), T(words:[ 1, 1, 1, 1] as W), T(words:[ 1, 1, 3, 3] as W)) - NBKAssertOr (T(words:[ 3, 2, 1, 0] as W), T(words:[ 1, 1, 1, 1] as W), T(words:[ 3, 3, 1, 1] as W)) - } - - func testXor() { - NBKAssertXor(T(words:[ 0, 1, 2, 3] as W), T(words:[ 0, 0, 0, 0] as W), T(words:[ 0, 1, 2, 3] as W)) - NBKAssertXor(T(words:[ 3, 2, 1, 0] as W), T(words:[ 0, 0, 0, 0] as W), T(words:[ 3, 2, 1, 0] as W)) - - NBKAssertXor(T(words:[ 0, 1, 2, 3] as W), T(words:[~0, ~0, ~0, ~0] as W), T(words:[~0, ~1, ~2, ~3] as W)) - NBKAssertXor(T(words:[ 3, 2, 1, 0] as W), T(words:[~0, ~0, ~0, ~0] as W), T(words:[~3, ~2, ~1, ~0] as W)) - - NBKAssertXor(T(words:[ 0, 1, 2, 3] as W), T(words:[ 1, 1, 1, 1] as W), T(words:[ 1, 0, 3, 2] as W)) - NBKAssertXor(T(words:[ 3, 2, 1, 0] as W), T(words:[ 1, 1, 1, 1] as W), T(words:[ 2, 3, 0, 1] as W)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Miscellaneous - //=------------------------------------------------------------------------= - - func testOperationsHaveUpsizingSemantics() { - NBKAssertAnd(T(words:[0 ] as W), T(words:[0, 0] as W), T(words:[0, 0] as W)) - NBKAssertAnd(T(words:[0, 0] as W), T(words:[0 ] as W), T(words:[0, 0] as W)) - - NBKAssertOr (T(words:[0 ] as W), T(words:[0, 0] as W), T(words:[0, 0] as W)) - NBKAssertOr (T(words:[0, 0] as W), T(words:[0 ] as W), T(words:[0, 0] as W)) - - NBKAssertXor(T(words:[0 ] as W), T(words:[0, 0] as W), T(words:[0, 0] as W)) - NBKAssertXor(T(words:[0, 0] as W), T(words:[0 ] as W), T(words:[0, 0] as W)) - } -} - -//*============================================================================* -// MARK: * NBK x Resizable Width x Logic x Assertions -//*============================================================================* - -private func NBKAssertNot( -_ operand: T, _ result: T, -file: StaticString = #file, line: UInt = #line) { - if operand.words.last != UInt.max { - XCTAssertEqual(~operand, result, file: file, line: line) - XCTAssertEqual(~result, operand, file: file, line: line) - } else { - XCTAssertEqual(~operand, result, file: file, line: line) - } -} - -private func NBKAssertAnd( -_ lhs: T, _ rhs: T, _ result: T, -file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual( lhs & rhs, result, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs &= rhs; return lhs }(), result, file: file, line: line) - XCTAssertEqual( rhs & lhs, result, file: file, line: line) - XCTAssertEqual({ var rhs = rhs; rhs &= lhs; return rhs }(), result, file: file, line: line) -} - -private func NBKAssertOr( -_ lhs: T, _ rhs: T, _ result: T, -file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual( lhs | rhs, result, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs |= rhs; return lhs }(), result, file: file, line: line) - XCTAssertEqual( rhs | lhs, result, file: file, line: line) - XCTAssertEqual({ var rhs = rhs; rhs |= lhs; return rhs }(), result, file: file, line: line) -} - -private func NBKAssertXor( -_ lhs: T, _ rhs: T, _ result: T, -file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual( lhs ^ rhs, result, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs ^= rhs; return lhs }(), result, file: file, line: line) - XCTAssertEqual( rhs ^ lhs, result, file: file, line: line) - XCTAssertEqual({ var rhs = rhs; rhs ^= lhs; return rhs }(), result, file: file, line: line) -} - -#endif diff --git a/Tests/NBKResizableWidthKitTests/NBKResizableWidth+Shifts.swift b/Tests/NBKResizableWidthKitTests/NBKResizableWidth+Shifts.swift deleted file mode 100644 index a4a64ab7..00000000 --- a/Tests/NBKResizableWidthKitTests/NBKResizableWidth+Shifts.swift +++ /dev/null @@ -1,206 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if DEBUG - -import NBKCoreKit -import NBKResizableWidthKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Resizable Width x Shifts x UIntXR -//*============================================================================* - -final class NBKResizableWidthTestsOnShiftsAsUIntXR: XCTestCase { - - typealias T = UIntXR - - //=------------------------------------------------------------------------= - // MARK: Tests x Left - //=------------------------------------------------------------------------= - - func testBitshiftingLeftByBits() { - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 0, T(x64:[ 1, 2, 3, 4] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 1, T(x64:[ 2, 4, 6, 8] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 2, T(x64:[ 4, 8, 12, 16] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 3, T(x64:[ 8, 16, 24, 32] as X)) - } - - func testBitshiftingLeftByWords() { - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 0, T(x64:[ 1, 2, 3, 4] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 64, T(x64:[ 0, 1, 2, 3] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 128, T(x64:[ 0, 0, 1, 2] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 192, T(x64:[ 0, 0, 0, 1] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 256, T(x64:[ 0, 0, 0, 0] as X)) - } - - func testBitshiftingLeftByWordsAndBits() { - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 3, T(x64:[ 8, 16, 24, 32] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 67, T(x64:[ 0, 8, 16, 24] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 131, T(x64:[ 0, 0, 8, 16] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 195, T(x64:[ 0, 0, 0, 8] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 259, T(x64:[ 0, 0, 0, 0] as X)) - } - - func testBitshiftingLeftSuchThatWordsSplit() { - NBKAssertShiftLeft(T(x64:[~0, 0, 0, 0] as X), 1, T(x64:[~1, 1, 0, 0] as X)) - NBKAssertShiftLeft(T(x64:[ 0, ~0, 0, 0] as X), 1, T(x64:[ 0, ~1, 1, 0] as X)) - NBKAssertShiftLeft(T(x64:[ 0, 0, ~0, 0] as X), 1, T(x64:[ 0, 0, ~1, 1] as X)) - NBKAssertShiftLeft(T(x64:[ 0, 0, 0, ~0] as X), 1, T(x64:[ 0, 0, 0, ~1] as X)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Right - //=------------------------------------------------------------------------= - - func testBitshiftingRightByBits() { - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 0, T(x64:[ 8, 16, 24, 32] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 1, T(x64:[ 4, 8, 12, 16] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 2, T(x64:[ 2, 4, 6, 8] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 3, T(x64:[ 1, 2, 3, 4] as X)) - } - - func testBitshiftingRightByWords() { - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 0, T(x64:[ 8, 16, 24, 32] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 64, T(x64:[16, 24, 32, 0] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 128, T(x64:[24, 32, 0, 0] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 192, T(x64:[32, 0, 0, 0] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 256, T(x64:[ 0, 0, 0, 0] as X)) - } - - func testBitshiftingRightByWordsAndBits() { - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 3, T(x64:[ 1, 2, 3, 4] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 67, T(x64:[ 2, 3, 4, 0] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 131, T(x64:[ 3, 4, 0, 0] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 195, T(x64:[ 4, 0, 0, 0] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 259, T(x64:[ 0, 0, 0, 0] as X)) - } - - func testBitshiftingRightSuchThatWordsSplit() { - NBKAssertShiftRight(T(x64:[0, 0, 0, 7] as X), 1, T(x64:[ 0, 0, 1 << 63, 3] as X)) - NBKAssertShiftRight(T(x64:[0, 0, 7, 0] as X), 1, T(x64:[ 0, 1 << 63, 3, 0] as X)) - NBKAssertShiftRight(T(x64:[0, 7, 0, 0] as X), 1, T(x64:[ 1 << 63, 3, 0, 0] as X)) - NBKAssertShiftRight(T(x64:[7, 0, 0, 0] as X), 1, T(x64:[ 3, 0, 0, 0] as X)) - } - - func testBitshiftingRightIsUnsigned() { - NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X), 0, T(x64:[0, 0, 0, 1 << 63] as X)) - NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X), 64, T(x64:[0, 0, 1 << 63, 0] as X)) - NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X), 128, T(x64:[0, 1 << 63, 0, 0] as X)) - NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X), 192, T(x64:[1 << 63, 0, 0, 0] as X)) - NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X), 256, T(x64:[0, 0, 0, 0] as X)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Miscellaneous - //=------------------------------------------------------------------------= - - func testBitshiftingIsSmart() { - XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) << 1, T(x64:[2, 4, 6, 8] as X)) - XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) >> -1, T(x64:[2, 4, 6, 8] as X)) - - XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) << 64, T(x64:[0, 1, 2, 3] as X)) - XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) >> -64, T(x64:[0, 1, 2, 3] as X)) - } - - func testBitshiftingRightDoesNotTrap() { - XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) >> Int.max, T.zero) - XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) << Int.min, T.zero) - } - - func testBitshiftingZeroDoesNotTrap() { - XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) << Int.min, T.zero) - XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) << Int.max, T.zero) - - XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) >> Int.min, T.zero) - XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) >> Int.max, T.zero) - } - - func testBitshiftingZeroDoesNotDoAnything() { - XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) << (UInt.bitWidth + 0), T.zero) - XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) << (UInt.bitWidth + 1), T.zero) - - XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) >> (UInt.bitWidth + 0), T.zero) - XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) >> (UInt.bitWidth + 1), T.zero) - } -} - -//*============================================================================* -// MARK: * NBK x Resizable Width x Shifts x Assertions -//*============================================================================* - -private func NBKAssertShiftLeft( -_ lhs: T, _ rhs: Int, _ result: T, -file: StaticString = #file, line: UInt = #line) { - //=------------------------------------------= - let (words, bits) = rhs.quotientAndRemainder(dividingBy: UInt.bitWidth) - //=------------------------------------------= - XCTAssertEqual( lhs << rhs, result, file: file, line: line) - XCTAssertEqual( lhs >> -rhs, result, file: file, line: line) - - XCTAssertEqual({ var lhs = lhs; lhs <<= rhs; return lhs }(), result, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs >>= -rhs; return lhs }(), result, file: file, line: line) - - XCTAssertEqual(lhs.bitshiftedLeftSmart(by: rhs), result, file: file, line: line) - XCTAssertEqual(lhs.bitshiftedRightSmart(by: -rhs), result, file: file, line: line) - - XCTAssertEqual({ var lhs = lhs; lhs.bitshiftLeftSmart(by: rhs); return lhs }(), result, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs.bitshiftRightSmart(by: -rhs); return lhs }(), result, file: file, line: line) - //=------------------------------------------= - if 0 ..< lhs.bitWidth ~= rhs { - XCTAssertEqual(lhs.bitshiftedLeft(by: rhs), result, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs.bitshiftLeft(by: rhs); return lhs }(), result, file: file, line: line) - - XCTAssertEqual(lhs.bitshiftedLeft(words: words, bits: bits), result, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs.bitshiftLeft(words: words, bits: bits); return lhs }(), result, file: file, line: line) - } - //=------------------------------------------= - if 0 ..< lhs.bitWidth ~= rhs, bits.isZero { - XCTAssertEqual(lhs.bitshiftedLeft(words: words), result, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs.bitshiftLeft(words: words); return lhs }(), result, file: file, line: line) - } -} - -private func NBKAssertShiftRight( -_ lhs: T, _ rhs: Int, _ result: T, -file: StaticString = #file, line: UInt = #line) { - //=------------------------------------------= - let (words, bits) = rhs.quotientAndRemainder(dividingBy: UInt.bitWidth) - //=------------------------------------------= - XCTAssertEqual( lhs >> rhs, result, file: file, line: line) - XCTAssertEqual( lhs << -rhs, result, file: file, line: line) - - XCTAssertEqual({ var lhs = lhs; lhs >>= rhs; return lhs }(), result, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs <<= -rhs; return lhs }(), result, file: file, line: line) - - XCTAssertEqual(lhs.bitshiftedRightSmart(by: rhs), result, file: file, line: line) - XCTAssertEqual(lhs.bitshiftedLeftSmart(by: -rhs), result, file: file, line: line) - - XCTAssertEqual({ var lhs = lhs; lhs.bitshiftRightSmart(by: rhs); return lhs }(), result, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs.bitshiftLeftSmart(by: -rhs); return lhs }(), result, file: file, line: line) - //=------------------------------------------= - if 0 ..< lhs.bitWidth ~= rhs { - XCTAssertEqual(lhs.bitshiftedRight(by: rhs), result, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs.bitshiftRight(by: rhs); return lhs }(), result, file: file, line: line) - - XCTAssertEqual(lhs.bitshiftedRight(words: words, bits: bits), result, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs.bitshiftRight(words: words, bits: bits); return lhs }(), result, file: file, line: line) - } - //=------------------------------------------= - if 0 ..< lhs.bitWidth ~= rhs, bits.isZero { - XCTAssertEqual(lhs.bitshiftedRight(words: words), result, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs.bitshiftRight(words: words); return lhs }(), result, file: file, line: line) - } -} - -#endif diff --git a/Tests/NBKResizableWidthKitTests/NBKResizableWidth+Words.swift b/Tests/NBKResizableWidthKitTests/NBKResizableWidth+Words.swift deleted file mode 100644 index 1ba9b39c..00000000 --- a/Tests/NBKResizableWidthKitTests/NBKResizableWidth+Words.swift +++ /dev/null @@ -1,176 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if DEBUG - -import NBKCoreKit -import NBKResizableWidthKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Resizable Width x Words x UIntXR -//*============================================================================* - -final class NBKResizableWidthTestsOnWordsAsUIntXR: XCTestCase { - - typealias T = UIntXR - typealias M = UIntXR - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testWords() { - NBKAssertWords(T(words:[0 ]), [0 ]) - NBKAssertWords(T(words:[1 ]), [1 ]) - NBKAssertWords(T(words:[1, 2 ]), [1, 2 ]) - NBKAssertWords(T(words:[1, 2, 3 ]), [1, 2, 3 ]) - NBKAssertWords(T(words:[1, 2, 3, 4]), [1, 2, 3, 4]) - - NBKAssertWords(T(words:[0, 0, 0, 0]), [0, 0, 0, 0]) - NBKAssertWords(T(words:[1, 0, 0, 0]), [1, 0, 0, 0]) - NBKAssertWords(T(words:[1, 2, 0, 0]), [1, 2, 0, 0]) - NBKAssertWords(T(words:[1, 2, 3, 0]), [1, 2, 3, 0]) - NBKAssertWords(T(words:[1, 2, 3, 4]), [1, 2, 3, 4]) - } - - func testWordsX64() throws { - guard MemoryLayout.size == MemoryLayout.size else { throw XCTSkip() } - - NBKAssertWords(T(x64:[0 ] as X), [0 ]) - NBKAssertWords(T(x64:[1 ] as X), [1 ]) - NBKAssertWords(T(x64:[1, 2 ] as X), [1, 2 ]) - NBKAssertWords(T(x64:[1, 2, 3 ] as X), [1, 2, 3 ]) - NBKAssertWords(T(x64:[1, 2, 3, 4] as X), [1, 2, 3, 4]) - - NBKAssertWords(T(x64:[0, 0, 0, 0] as X), [0, 0, 0, 0]) - NBKAssertWords(T(x64:[1, 0, 0, 0] as X), [1, 0, 0, 0]) - NBKAssertWords(T(x64:[1, 2, 0, 0] as X), [1, 2, 0, 0]) - NBKAssertWords(T(x64:[1, 2, 3, 0] as X), [1, 2, 3, 0]) - NBKAssertWords(T(x64:[1, 2, 3, 4] as X), [1, 2, 3, 4]) - } - - func testWordsX32() throws { - guard MemoryLayout.size == MemoryLayout.size else { throw XCTSkip() } - - NBKAssertWords(T(x32:[0 ] as Y), [0 ]) - NBKAssertWords(T(x32:[1 ] as Y), [1 ]) - NBKAssertWords(T(x32:[1, 2 ] as Y), [1, 2 ]) - NBKAssertWords(T(x32:[1, 2, 3 ] as Y), [1, 2, 3 ]) - NBKAssertWords(T(x32:[1, 2, 3, 4 ] as Y), [1, 2, 3, 4 ]) - NBKAssertWords(T(x32:[1, 2, 3, 4, 5 ] as Y), [1, 2, 3, 4, 5 ]) - NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6 ] as Y), [1, 2, 3, 4, 5, 6 ]) - NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6, 7 ] as Y), [1, 2, 3, 4, 5, 6, 7 ]) - NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6, 7, 8] as Y), [1, 2, 3, 4, 5, 6, 7, 8]) - - NBKAssertWords(T(x32:[0, 0, 0, 0, 0, 0, 0, 0] as Y), [0, 0, 0, 0, 0, 0, 0, 0]) - NBKAssertWords(T(x32:[1, 0, 0, 0, 0, 0, 0, 0] as Y), [1, 0, 0, 0, 0, 0, 0, 0]) - NBKAssertWords(T(x32:[1, 2, 0, 0, 0, 0, 0, 0] as Y), [1, 2, 0, 0, 0, 0, 0, 0]) - NBKAssertWords(T(x32:[1, 2, 3, 0, 0, 0, 0, 0] as Y), [1, 2, 3, 0, 0, 0, 0, 0]) - NBKAssertWords(T(x32:[1, 2, 3, 4, 0, 0, 0, 0] as Y), [1, 2, 3, 4, 0, 0, 0, 0]) - NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 0, 0, 0] as Y), [1, 2, 3, 4, 5, 0, 0, 0]) - NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6, 0, 0] as Y), [1, 2, 3, 4, 5, 6, 0, 0]) - NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6, 7, 0] as Y), [1, 2, 3, 4, 5, 6, 7, 0]) - NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6, 7, 8] as Y), [1, 2, 3, 4, 5, 6, 7, 8]) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Indices - //=------------------------------------------------------------------------= - - func testIndexOffsetByLimitedBy() { - NBKAssertIndexOffsetByLimitedBy(T.zero, 1, 2, 2, nil) - NBKAssertIndexOffsetByLimitedBy(T.zero, 1, 1, 2, 2) - NBKAssertIndexOffsetByLimitedBy(T.zero, 1, 0, 2, 1) - NBKAssertIndexOffsetByLimitedBy(T.zero, 1, -1, 2, 0) - NBKAssertIndexOffsetByLimitedBy(T.zero, 1, -2, 2, -1) - - NBKAssertIndexOffsetByLimitedBy(T.zero, 2, 2, 2, nil) - NBKAssertIndexOffsetByLimitedBy(T.zero, 2, 1, 2, nil) - NBKAssertIndexOffsetByLimitedBy(T.zero, 2, 0, 2, 2) - NBKAssertIndexOffsetByLimitedBy(T.zero, 2, -1, 2, nil) - NBKAssertIndexOffsetByLimitedBy(T.zero, 2, -2, 2, nil) - - NBKAssertIndexOffsetByLimitedBy(T.zero, 3, 2, 2, 5) - NBKAssertIndexOffsetByLimitedBy(T.zero, 3, 1, 2, 4) - NBKAssertIndexOffsetByLimitedBy(T.zero, 3, 0, 2, 3) - NBKAssertIndexOffsetByLimitedBy(T.zero, 3, -1, 2, 2) - NBKAssertIndexOffsetByLimitedBy(T.zero, 3, -2, 2, nil) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Elements - //=------------------------------------------------------------------------= - - func testFirstLastTail() { - NBKAssertFirstLastTail( T(words:[1, 2, 3, 4]), first: 1, last: 4, tail: 4) - NBKAssertFirstLastTail(~T(words:[1, 2, 3, 4]), first: ~1, last: ~4, tail: ~4) - } -} - -//*============================================================================* -// MARK: * NBK x Resizable Width x Words x Assertions -//*============================================================================* - -private func NBKAssertWords( -_ integer: T, _ words: [UInt], -file: StaticString = #file, line: UInt = #line) { - var integer: T = integer - var generic: some RandomAccessCollection & MutableCollection = integer - - XCTAssertEqual(Array(integer.words), Array(words), file: file, line: line) - XCTAssertEqual(Array(integer.words.reversed()), Array(words.reversed()), file: file, line: line) - - XCTAssertEqual(integer.withContiguousStorage({ Array($0) }), words, file: file, line: line) - XCTAssertEqual(integer.withContiguousMutableStorage({ Array($0) }), words, file: file, line: line) - - XCTAssertEqual(integer.withContiguousStorageIfAvailable({ Array($0) }), words, file: file, line: line) - XCTAssertEqual(integer.withContiguousMutableStorageIfAvailable({ Array($0) }), words, file: file, line: line) - - XCTAssertEqual(generic.withContiguousStorageIfAvailable({ Array($0) }), words, file: file, line: line) - XCTAssertEqual(generic.withContiguousMutableStorageIfAvailable({ Array($0) }), words, file: file, line: line) -} - -//=----------------------------------------------------------------------------= -// MARK: + Indices -//=----------------------------------------------------------------------------= - -private func NBKAssertIndexOffsetByLimitedBy( -_ integer: T, _ index: Int, _ distance: Int, _ limit: Int, _ expectation: Int?, -file: StaticString = #file, line: UInt = #line) { - //=------------------------------------------= - let wordsIndex = /*-*/(integer).index(index, offsetBy: distance, limitedBy: limit) - let arrayIndex = Array(integer).index(index, offsetBy: distance, limitedBy: limit) - //=------------------------------------------= - XCTAssertEqual(wordsIndex, expectation, file: file, line: line) - XCTAssertEqual(arrayIndex, expectation, file: file, line: line) -} - -//=----------------------------------------------------------------------------= -// MARK: + Elements -//=----------------------------------------------------------------------------= - -private func NBKAssertFirstLastTail( -_ integer: T, first: UInt, last: UInt, tail: T.Digit, -file: StaticString = #file, line: UInt = #line) { - //=------------------------------------------= - XCTAssertEqual(integer.first, first, file: file, line: line) - XCTAssertEqual(integer.last, last, file: file, line: line) - XCTAssertEqual(integer.tail, tail, file: file, line: line) - //=------------------------------------------= - XCTAssertEqual({ var x = T.zero; x.first = first; return x.first }(), first, file: file, line: line) - XCTAssertEqual({ var x = T.zero; x.last = last; return x.last }(), last, file: file, line: line) - XCTAssertEqual({ var x = T.zero; x.tail = tail; return x.tail }(), tail, file: file, line: line) -} - -#endif diff --git a/Tests/NBKResizableWidthKitTests/NBKResizableWidth.swift b/Tests/NBKResizableWidthKitTests/NBKResizableWidth.swift deleted file mode 100644 index 3c57b0b3..00000000 --- a/Tests/NBKResizableWidthKitTests/NBKResizableWidth.swift +++ /dev/null @@ -1,42 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit -import NBKResizableWidthKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Resizable Width x Initializers x UIntXR -//*============================================================================* - -extension NBKResizableWidth.Magnitude { - - //=------------------------------------------------------------------------= - // MARK: Details x Numbers - //=------------------------------------------------------------------------= - - static let min256 = Self(x64:[ 0, 0, 0, 0] as X) - static let max256 = Self(x64:[~0, ~0, ~0, ~0] as X) - - //=------------------------------------------------------------------------= - // MARK: Details x Limbs - //=------------------------------------------------------------------------= - - init(x32: [UInt32]) { - self.init(words: NBKChunkedInt(x32)) - } - - init(x64: [UInt64]) { - self.init(words: NBKChunkedInt(x64)) - } -} From 39468ce416152c8b7bd0d52faff03709f26e330a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Mon, 11 Sep 2023 17:01:15 +0200 Subject: [PATCH 062/133] [NBKFlexibleWidthKit] Dropped NBKResizableWidth. --- .../xcshareddata/xcschemes/Numberick.xcscheme | 14 + .../NBKFlexibleWidth+Addition+Digit.swift | 15 + .../NBKFlexibleWidth+Addition.swift | 17 +- .../NBKFlexibleWidth+Bits.swift | 14 +- .../NBKFlexibleWidth+Comparisons.swift | 36 ++- .../NBKFlexibleWidth+Complements.swift | 61 ++++ ...ized.swift => NBKFlexibleWidth+Data.swift} | 12 +- .../NBKFlexibleWidth+Division+Digit.swift | 2 +- .../NBKFlexibleWidth+Division.swift | 18 +- .../NBKFlexibleWidth+Literals.swift | 8 +- .../NBKFlexibleWidth+Logic.swift | 42 ++- ...BKFlexibleWidth+Multiplication+Digit.swift | 17 +- .../NBKFlexibleWidth+Multiplication.swift | 41 +++ .../NBKFlexibleWidth+Numbers.swift | 8 +- .../NBKFlexibleWidth+Shifts.swift | 185 +++++++++-- .../NBKFlexibleWidth+Size.swift | 49 +++ .../NBKFlexibleWidth+Subtraction+Digit.swift | 15 + .../NBKFlexibleWidth+Subtraction.swift | 23 +- .../NBKFlexibleWidth+Text.swift | 4 +- .../NBKFlexibleWidth+Update.swift | 27 +- ... => NBKFlexibleWidth+Words+Pointers.swift} | 22 +- .../NBKFlexibleWidth+Words.swift | 55 +++- .../NBKFlexibleWidth.swift | 54 +++- .../NBKResizableWidth+Addition+Digit.swift | 38 --- .../NBKResizableWidth+Addition.swift | 38 --- .../NBKResizableWidth+Bits.swift | 53 ---- .../NBKResizableWidth+Comparisons.swift | 89 ------ .../NBKResizableWidth+Complements.swift | 61 ---- .../NBKResizableWidth+Division+Digit.swift | 57 ---- .../NBKResizableWidth+Division.swift | 68 ---- .../NBKResizableWidth+Literals.swift | 94 ------ .../NBKResizableWidth+Logic.swift | 94 ------ ...KResizableWidth+Multiplication+Digit.swift | 37 --- .../NBKResizableWidth+Multiplication.swift | 63 ---- .../NBKResizableWidth+Numbers.swift | 75 ----- .../NBKResizableWidth+Protocols.swift | 107 ------- .../NBKResizableWidth+Shifts.swift | 293 ------------------ .../NBKResizableWidth+Size.swift | 63 ---- .../NBKResizableWidth+Subtraction+Digit.swift | 50 --- .../NBKResizableWidth+Subtraction.swift | 55 ---- .../NBKResizableWidth+Update.swift | 33 -- .../NBKResizableWidth+Words+Pointers.swift | 57 ---- .../NBKResizableWidth+Words.swift | 146 --------- .../NBKResizableWidth.swift | 154 --------- 44 files changed, 637 insertions(+), 1827 deletions(-) rename Sources/NBKFlexibleWidthKit/{NBKResizableWidthKit/NBKResizableWidth+Uninitialized.swift => NBKFlexibleWidth+Data.swift} (64%) rename Sources/NBKFlexibleWidthKit/{NBKResizableWidthKit/NBKResizableWidth+Text.swift => NBKFlexibleWidth+Words+Pointers.swift} (53%) delete mode 100644 Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Addition+Digit.swift delete mode 100644 Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Addition.swift delete mode 100644 Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Bits.swift delete mode 100644 Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Comparisons.swift delete mode 100644 Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Complements.swift delete mode 100644 Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Division+Digit.swift delete mode 100644 Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Division.swift delete mode 100644 Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Literals.swift delete mode 100644 Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Logic.swift delete mode 100644 Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Multiplication+Digit.swift delete mode 100644 Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Multiplication.swift delete mode 100644 Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Numbers.swift delete mode 100644 Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Protocols.swift delete mode 100644 Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Shifts.swift delete mode 100644 Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Size.swift delete mode 100644 Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Subtraction+Digit.swift delete mode 100644 Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Subtraction.swift delete mode 100644 Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Update.swift delete mode 100644 Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Words+Pointers.swift delete mode 100644 Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Words.swift delete mode 100644 Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth.swift diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/Numberick.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/Numberick.xcscheme index 7e8b10d0..3e0bbfe8 100644 --- a/.swiftpm/xcode/xcshareddata/xcschemes/Numberick.xcscheme +++ b/.swiftpm/xcode/xcshareddata/xcschemes/Numberick.xcscheme @@ -48,6 +48,20 @@ ReferencedContainer = "container:"> + + + + Bool { + NBK.incrementSufficientUnsignedInteger(&self.elements, by: other, plus: carry, at: index).overflow + } +} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift index e61d899b..6fbce02b 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift @@ -74,7 +74,7 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= if other.isZero { return } //=--------------------------------------= - self.storage.resize(minCount: other.storage.count + index) + self.storage.resize(minCount: other.storage.elements.count + index) let overflow = self.storage.add(other.storage, plus: false, at: index) if overflow { self.storage.append(1 as UInt) } } @@ -83,3 +83,18 @@ extension NBKFlexibleWidth.Magnitude { var result = self; result.add(other, at: index); return result } } + +//*============================================================================* +// MARK: * NBK x Flexible Width x Addition x Unsigned x Storage +//*============================================================================* + +extension NBKFlexibleWidth.Magnitude.Storage { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable mutating func add(_ other: Self, plus carry: Bool, at index: Int) -> Bool { + NBK.incrementSufficientUnsignedInteger(&self.elements, by: other.elements, plus: carry, at: index).overflow + } +} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift index 2a021653..514adb80 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift @@ -33,7 +33,7 @@ extension NBKFlexibleWidth { @inlinable public var nonzeroBitCount: Int { if self.isLessThanZero { - let s = NBK.nonzeroBitCount(twosComplementOf: self.magnitude.storage) + let s = self.magnitude.storage.elements.withUnsafeBufferPointer(NBK.nonzeroBitCount(twosComplementOf:)) return s + self.storageBitWidthNeeded } else { return self.magnitude.nonzeroBitCount @@ -85,26 +85,26 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @inlinable public var bitWidth: Int { - self.storage.bitWidth + self.storage.elements.count * UInt.bitWidth } @inlinable public var nonzeroBitCount: Int { - self.storage.nonzeroBitCount + self.storage.elements.withUnsafeBufferPointer(NBK.nonzeroBitCount(of:)) } @inlinable public var leadingZeroBitCount: Int { - self.storage.last.leadingZeroBitCount + self.storage.elements.withUnsafeBufferPointer(NBK.leadingZeroBitCount(of:)) } @inlinable public var trailingZeroBitCount: Int { - self.storage.trailingZeroBitCount + self.storage.elements.withUnsafeBufferPointer(NBK.trailingZeroBitCount(of:)) } @inlinable public var mostSignificantBit: Bool { - self.storage.mostSignificantBit + self.storage.elements.last!.mostSignificantBit } @inlinable public var leastSignificantBit: Bool { - self.storage.leastSignificantBit + self.storage.elements.first!.leastSignificantBit } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift index def8ce40..f4bb0390 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift @@ -81,7 +81,7 @@ extension NBKFlexibleWidth { //=------------------------------------------------------------------------= @inlinable var isTwosComplementMinValue: Bool { - self.compared(to: Int.min, at: self.magnitude.storage.lastIndex).isZero + self.compared(to: Int.min, at: self.magnitude.storage.elements.count - 1).isZero } } @@ -115,25 +115,25 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= // MARK: Accessors //=------------------------------------------------------------------------= - + @inlinable public var isZero: Bool { - self.storage.isZero + self.storage.elements.count == 1 && self.storage.elements.first!.isZero } @inlinable public var isLessThanZero: Bool { - self.storage.isLessThanZero + false } @inlinable public var isMoreThanZero: Bool { - self.storage.isMoreThanZero + !self.isZero } @inlinable public var isPowerOf2: Bool { - self.storage.isPowerOf2 + self.storage.elements.withUnsafeBufferPointer({ NBK.nonzeroBitCount(of: $0, equals: 1) }) } @inlinable public func signum() -> Int { - self.storage.signum() + Int(bit: !self.isZero) } //=------------------------------------------------------------------------= @@ -141,7 +141,7 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @inlinable public func hash(into hasher: inout Hasher) { - hasher.combine(self.storage) + hasher.combine(self.storage.elements) } //=------------------------------------------------------------------------= @@ -157,18 +157,30 @@ extension NBKFlexibleWidth.Magnitude { } @inlinable public func compared(to other: Self) -> Int { - self.storage.compared(to: other.storage) + self .storage.elements.withUnsafeBufferPointer { lhs in + other.storage.elements.withUnsafeBufferPointer { rhs in + NBK.compareLenientUnsignedInteger(lhs, to: rhs) + }} } @inlinable public func compared(to other: Self, at index: Int) -> Int { - self.storage.compared(to: other.storage, at: index) + self .storage.elements.withUnsafeBufferPointer { lhs in + other.storage.elements.withUnsafeBufferPointer { rhs in + NBK.compareLenientUnsignedInteger(lhs, to: rhs, at: index) + }} } @_disfavoredOverload @inlinable public func compared(to other: Digit) -> Int { - self.storage.compared(to: other) + self.storage.elements.withUnsafeBufferPointer { lhs in + NBK .withUnsafeWords(of: other) { rhs in + NBK.compareLenientUnsignedInteger(lhs, to: rhs) + }} } @_disfavoredOverload @inlinable public func compared(to other: Digit, at index: Int) -> Int { - self.storage.compared(to: other, at: index) + self.storage.elements.withUnsafeBufferPointer { lhs in + NBK .withUnsafeWords(of: other) { rhs in + NBK.compareLenientUnsignedInteger(lhs, to: rhs, at: index) + }} } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements.swift index 1c74ea10..3ac70215 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements.swift @@ -115,3 +115,64 @@ extension NBKFlexibleWidth.Magnitude { return PVO(partialValue, overflow) } } + +//*============================================================================* +// MARK: * NBK x Flexible Width x Complements x Unsigned x Storage +//*============================================================================* + +extension NBKFlexibleWidth.Magnitude.Storage { + + //=------------------------------------------------------------------------= + // MARK: Details x One's Complement + //=------------------------------------------------------------------------= + + @inlinable mutating func formOnesComplement() { + for index in self.elements.indices { + self.elements[index].formOnesComplement() + } + } + + @inlinable func onesComplement() -> Self { + Self(unchecked: Elements(self.elements.lazy.map(~))) + } + + //=------------------------------------------------------------------------= + // MARK: Details x Two's Complement + //=------------------------------------------------------------------------= + + @inlinable mutating func formTwosComplement() { + _ = self.formTwosComplementSubsequence(true) + } + + @inlinable func twosComplementw() -> Self { + var partialValue = self + partialValue.formTwosComplement() + return partialValue as Self + } + + @inlinable mutating func formTwosComplementReportingOverflow() -> Bool { + self.formTwosComplementSubsequence(true) + } + + @inlinable func twosComplementReportingOverflow() -> PVO { + var partialValue = self + let overflow = partialValue.formTwosComplementReportingOverflow() + return PVO(partialValue, overflow) + } + + @inlinable mutating func formTwosComplementSubsequence(_ carry: Bool) -> Bool { + var carry = carry + + for index in self.elements.indices { + carry = self.elements[index].formTwosComplementSubsequence(carry) + } + + return carry as Bool + } + + @inlinable func twosComplementSubsequence(_ carry: Bool) -> PVO { + var partialValue = self + let overflow = partialValue.formTwosComplementSubsequence(carry) + return PVO(partialValue, overflow) + } +} diff --git a/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Uninitialized.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Data.swift similarity index 64% rename from Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Uninitialized.swift rename to Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Data.swift index c9194067..d27f905e 100644 --- a/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Uninitialized.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Data.swift @@ -10,17 +10,17 @@ import NBKCoreKit //*============================================================================* -// MARK: * NBK x Resizable Width x Uninitialized x Unsigned +// MARK: * NBK x Double Width x Data x Unsigned x Storage //*============================================================================* -extension NBKResizableWidth.Magnitude { +extension NBKFlexibleWidth.Magnitude.Storage { //=------------------------------------------------------------------------= - // MARK: Initializers + // MARK: Initializers x Private //=------------------------------------------------------------------------= - // TODO: measure (inout Self) -> Void - @inlinable public static func uninitialized(count: Int, body: (inout NBK.UnsafeMutableWords) -> Void) -> Self { - Self(storage: Storage(unsafeUninitializedCapacity: count) { body(&$0); $1 = count }) + /// Creates a new instance with unsafe access to its uninitialized memory. + @inlinable static func uninitialized(count: Int, body: (inout NBK.UnsafeMutableWords) -> Void) -> Self { + Self(elements: Elements(unsafeUninitializedCapacity: count) { body(&$0); $1 = count }) } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.swift index 66f7e7b9..c2848961 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.swift @@ -94,6 +94,6 @@ extension NBKFlexibleWidth.Magnitude { @_disfavoredOverload @inlinable public mutating func formQuotientWithRemainderReportingOverflow(dividingBy other: Digit) -> PVO { defer{ self.storage.normalize() } - return self.storage.formQuotientWithRemainderReportingOverflow(dividingBy: other) + return NBK.formQuotientWithRemainderReportingOverflowAsLenientUnsignedInteger(of: &self.storage.elements, dividingBy: other) } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift index f514fb7e..a42ddacc 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift @@ -112,8 +112,8 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= // divisor is one word //=--------------------------------------= - if other.storage.count == 1 { - let qr = self.quotientAndRemainder(dividingBy: other.storage.first) + if other.storage.elements.count == 1 { + let qr = self.quotientAndRemainder(dividingBy: other.storage.elements.first!) self.update(qr.remainder) return PVO(qr.quotient, false) } @@ -133,23 +133,23 @@ extension NBKFlexibleWidth.Magnitude { // shift to clamp approximation //=--------------------------------------= var divisor = other.storage - let shift = divisor.last.leadingZeroBitCount as Int + let shift = divisor.elements.last!.leadingZeroBitCount as Int divisor.bitshiftLeft(words: Int.zero, bits: shift) - let divisorLast0 = divisor[divisor.endIndex - 1] as UInt + let divisorLast0 = divisor.elements[divisor.elements.endIndex - 1] as UInt assert(divisorLast0.mostSignificantBit) - var remainderIndex = self.storage.endIndex + var remainderIndex = self.storage.elements.endIndex self.storage.append(0) self.storage.bitshiftLeft(words: Int.zero, bits: shift) //=--------------------------------------= // division: approximate quotient digits //=--------------------------------------= - var quotientIndex = remainderIndex - divisor.endIndex as Int + var quotientIndex = remainderIndex - divisor.elements.endIndex as Int var quotient = Storage.uninitialized(count: quotientIndex + 1) { quotient in loop: repeat { - let remainderLast0 = self.storage[remainderIndex] - self.storage.formIndex(before: &remainderIndex) - let remainderLast1 = self.storage[remainderIndex] + let remainderLast0 = self.storage.elements[remainderIndex] + self.storage.elements.formIndex(before: &remainderIndex) + let remainderLast1 = self.storage.elements[remainderIndex] //=------------------------------= var digit: UInt if divisorLast0 == remainderLast0 { diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Literals.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Literals.swift index 8a5fe4ac..3698c39a 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Literals.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Literals.swift @@ -69,15 +69,13 @@ extension NBKFlexibleWidth { } @inlinable init?(exactlyStringLiteral source: StaticString) { - let value: Optional = source.withUTF8Buffer { utf8 in + if let value: Self = source.withUTF8Buffer({ utf8 in let components = NBK.makeIntegerComponentsByDecodingRadix(utf8: utf8) let radix = NBK.AnyRadixSolution(components.radix) let digits = NBK.UnsafeUTF8(rebasing: components.body ) guard let magnitude = Magnitude(digits: digits, radix: radix) else { return nil } return Self(sign: components.sign, magnitude: magnitude) - } - - if let value { self = value } else { return nil } + }){ self = value } else { return nil } } } @@ -149,7 +147,7 @@ extension NBKFlexibleWidth.Magnitude { } @inlinable init?(exactlyStringLiteral source: StaticString) { - if let value: Self = source.withUTF8Buffer({ utf8 in + if let value: Self = source.withUTF8Buffer({ utf8 in let components = NBK.makeIntegerComponentsByDecodingRadix(utf8: utf8) let radix = NBK.AnyRadixSolution(components.radix) let digits = NBK.UnsafeUTF8(rebasing: components.body ) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift index 3d70f1f5..bb73e7db 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift @@ -79,7 +79,7 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @inlinable public static func &=(lhs: inout Self, rhs: Self) { - lhs.storage.downsizeThenFormInIntersection(of: rhs.storage, each: &) + lhs.storage.downsizeThenFormInIntersection(with: rhs.storage, each: &) lhs.storage.normalize() Swift.assert(lhs.storage.isNormal) } @@ -93,7 +93,7 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @inlinable public static func |=(lhs: inout Self, rhs: Self) { - lhs.storage |= rhs.storage + lhs.storage.upsizeThenFormInIntersection(with: rhs.storage, each: |) Swift.assert(lhs.storage.isNormal) } @@ -106,7 +106,7 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @inlinable public static func ^=(lhs: inout Self, rhs: Self) { - lhs.storage ^= rhs.storage + lhs.storage.upsizeThenFormInIntersection(with: rhs.storage, each: ^) lhs.storage.normalize() Swift.assert(lhs.storage.isNormal) } @@ -115,3 +115,39 @@ extension NBKFlexibleWidth.Magnitude { var lhs = lhs; lhs ^= rhs; return lhs } } + +//*============================================================================* +// MARK: * NBK x Flexible Width x Logic x Unsigned x Storage +//*============================================================================* +//=----------------------------------------------------------------------------= +// MARK: + Algorithms +//=----------------------------------------------------------------------------= + +extension NBKFlexibleWidth.Magnitude.Storage { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable mutating func upsizeThenFormInIntersection(with other: Self, each element: (UInt, UInt) -> UInt) { + self.resize(minCount: other.elements.count) + self.withUnsafeMutableBufferPointer { lhs in + other.withUnsafeBufferPointer { rhs in + for index in rhs.indices { + lhs[index] = element(lhs[index], rhs[index]) + } + } + } + } + + @inlinable mutating func downsizeThenFormInIntersection(with other: Self, each element: (UInt, UInt) -> UInt) { + self.resize(maxCount: other.elements.count) + self.withUnsafeMutableBufferPointer { lhs in + other.withUnsafeBufferPointer { rhs in + for index in lhs.indices { + lhs[index] = element(lhs[index], rhs[index]) + } + } + } + } +} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift index 1d6e3038..4a8c5a15 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift @@ -60,7 +60,7 @@ extension NBKFlexibleWidth.Magnitude { return self.update(addend) } //=--------------------------------------= - self.storage.reserveCapacity(self.storage.count + 1) + self.storage.reserveCapacity(self.storage.elements.count + 1) let overflow = self.storage.multiply(by: multiplicand, add: addend) if !overflow.isZero { self.storage.append(overflow) @@ -71,3 +71,18 @@ extension NBKFlexibleWidth.Magnitude { var result = self; result.multiply(by: multiplicand, add: addend); return result } } + +//*============================================================================* +// MARK: * NBK x Resizable Width x Multiplication x Digit x Unsigned +//*============================================================================* + +extension NBKFlexibleWidth.Magnitude.Storage { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @_disfavoredOverload @inlinable mutating func multiply(by other: UInt, add addend: UInt) -> UInt { + NBK.multiplyFullWidthLenientUnsignedInteger(&self.elements, by: other, add: addend) + } +} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift index fd0f5b21..9105df3d 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift @@ -47,3 +47,44 @@ extension NBKFlexibleWidth.Magnitude { Self(storage: lhs.storage.multipliedFullWidth(by: rhs.storage)) } } + +//*============================================================================* +// MARK: * NBK x Resizable Width x Multiplication x Unsigned +//*============================================================================* + +extension NBKFlexibleWidth.Magnitude.Storage { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable func multipliedFullWidth(by multiplicand: Self) -> Self { + self.multipliedFullWidthByNaiveMethod(by: multiplicand, adding: UInt.zero) + } + + @inlinable func multipliedFullWidthByNaiveMethod(by multiplicand: Self, adding addend: UInt) -> Self { + Self.uninitialized(count: self.elements.count + multiplicand.elements.count) { product in + //=----------------------------------= + // de/init: pointee is trivial + //=----------------------------------= + product.update(repeating: UInt.zero) + //=----------------------------------= + var overflow = addend as UInt + for lhsIndex in self.elements.indices { + let outer = self.elements[lhsIndex] + + for rhsIndex in multiplicand.elements.indices { + let inner = multiplicand.elements[rhsIndex] + var subproduct = outer.multipliedFullWidth(by: inner) + + overflow = UInt(bit: subproduct.low.addReportingOverflow(overflow)) + overflow &+= UInt(bit: product[lhsIndex + rhsIndex].addReportingOverflow(subproduct.low)) + overflow &+= subproduct.high + } + + product[lhsIndex + multiplicand.elements.count] = overflow + overflow = UInt.zero + } + } + } +} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift index a50ff1f9..31347a0e 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift @@ -104,11 +104,15 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @inlinable public init(digit: UInt) { - self.init(unchecked: Storage(digit: digit)) + let storage = Storage(unchecked: [digit]) + self.init(unchecked: storage) } @inlinable public init(digit: UInt, at index: Int) { - self.init(unchecked: Storage(digit: digit, at: index)) + var storage = Storage(repeating: 0 as UInt, count: index + 1) + storage.elements[index] = digit + storage.normalize() + self.init(unchecked: storage) } //=------------------------------------------------------------------------= diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift index e60b8bb5..1dc94523 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift @@ -235,15 +235,11 @@ extension NBKFlexibleWidth.Magnitude { Swift.assert(self.storage.isNormal) } //=--------------------------------------= - if self.isZero { - return - } + if self.isZero { return } //=--------------------------------------= let rollover = Int(bit: self.leadingZeroBitCount < bits) - self.storage.resize(minCount: self.storage.count + words + rollover) - self.storage.withContiguousMutableStorage { - NBK.bitshiftLeftAsFixedLimbsCodeBlock(&$0, environment: false, limbs: words, atLeastOneBit: bits) - } + self.storage.resize(minCount: self.storage.elements.count + words + rollover) + self.storage.bitshiftLeft(words: words, atLeastOneBit: bits) } /// Performs a left shift. @@ -258,10 +254,8 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= if self.isZero { return } //=--------------------------------------= - self.storage.resize(minCount: self.storage.count + words) - self.storage.withContiguousMutableStorage { - NBK.bitshiftLeftAsFixedLimbsCodeBlock(&$0, environment: false, atLeastOneLimb: words) - } + self.storage.resize(minCount: self.storage.elements.count + words) + self.storage.bitshiftLeft(atLeastOneWord: words) } } @@ -350,16 +344,13 @@ extension NBKFlexibleWidth.Magnitude { } //=--------------------------------------= let rollover = Int(bit: 0 <= bits + self.leadingZeroBitCount - UInt.bitWidth) - let maxCount = self.storage.count - words - rollover + let maxCount = self.storage.elements.count - words - rollover //=--------------------------------------= if maxCount <= 0 { return self.updateZeroValue() } //=--------------------------------------= - self.storage.withContiguousMutableStorage { - NBK.bitshiftRightAsFixedLimbsCodeBlock(&$0, environment: false, limbs: words, atLeastOneBit: bits) - } - + self.storage.bitshiftRight(words: words, atLeastOneBit: bits) self.storage.resize(maxCount: maxCount) } @@ -373,14 +364,168 @@ extension NBKFlexibleWidth.Magnitude { Swift.assert(self.storage.isNormal) } //=--------------------------------------= - if self.storage.count <= words { + if self.storage.elements.count <= words { return self.updateZeroValue() } //=--------------------------------------= - self.storage.withContiguousMutableStorage { - NBK.bitshiftRightAsFixedLimbsCodeBlock(&$0, environment: false, atLeastOneLimb: words) + self.storage.bitshiftRight(atLeastOneWord: words) + self.storage.resize(maxCount: self.storage.elements.count - words) + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Shifts x Unsigned x Storage +//*============================================================================* +//=----------------------------------------------------------------------------= +// MARK: + Left +//=----------------------------------------------------------------------------= + +extension NBKFlexibleWidth.Magnitude.Storage { + + //=------------------------------------------------------------------------= + // MARK: Transformations x Int + //=------------------------------------------------------------------------= + + /// Performs a left shift. + /// + /// - Parameters: + /// - distance: `0 <= distance < self.bitWidth` + /// + @inlinable mutating func bitshiftLeft(by distance: Int) { + precondition(distance >= 0, NBK.callsiteOutOfBoundsInfo()) + let major = NBK .quotientDividingByBitWidthAssumingIsAtLeastZero(distance) + let minor = NBK.remainderDividingByBitWidthAssumingIsAtLeastZero(distance) + return self.bitshiftLeft(words: major, bits: minor) + } + + /// Performs a left shift. + /// + /// - Parameters: + /// - words: `0 <= words < self.endIndex` + /// - bits: `0 <= bits  < UInt.bitWidth` + /// + @inlinable mutating func bitshiftLeft(words: Int, bits: Int) { + //=--------------------------------------= + if bits.isZero { + return self.bitshiftLeft(words: words) + } + //=--------------------------------------= + self.bitshiftLeft(words: words, atLeastOneBit: bits) + } + + /// Performs a left shift. + /// + /// - Parameters: + /// - words: `0 <= words < self.endIndex` + /// + @inlinable mutating func bitshiftLeft(words: Int) { + //=--------------------------------------= + if words.isZero { return } + //=--------------------------------------= + self.bitshiftLeft(atLeastOneWord: words) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Int x Private + //=------------------------------------------------------------------------= + + /// Performs a left shift. + /// + /// - Parameters: + /// - words: `0 <= words < self.endIndex` + /// - bits: `1 <= bits  < UInt.bitWidth` + /// + @inlinable mutating func bitshiftLeft(words: Int, atLeastOneBit bits: Int) { + self.withUnsafeMutableBufferPointer { + NBK.bitshiftLeftAsFixedLimbsCodeBlock(&$0, environment: false, limbs: words, atLeastOneBit: bits) + } + } + + /// Performs a left shift. + /// + /// - Parameters: + /// - words: `1 <= words < self.endIndex` + /// + @inlinable mutating func bitshiftLeft(atLeastOneWord words: Int) { + self.withUnsafeMutableBufferPointer { + NBK.bitshiftLeftAsFixedLimbsCodeBlock(&$0, environment: false, atLeastOneLimb: words) + } + } +} + +//=----------------------------------------------------------------------------= +// MARK: + Right +//=----------------------------------------------------------------------------= + +extension NBKFlexibleWidth.Magnitude.Storage { + + //=------------------------------------------------------------------------= + // MARK: Transformations x Int + //=------------------------------------------------------------------------= + + /// Performs an un/signed right shift. + /// + /// - Parameters: + /// - distance: `0 <= distance < self.bitWidth` + /// + @inlinable mutating func bitshiftRight(by distance: Int) { + precondition(distance >= 0, NBK.callsiteOutOfBoundsInfo()) + let major = NBK .quotientDividingByBitWidthAssumingIsAtLeastZero(distance) + let minor = NBK.remainderDividingByBitWidthAssumingIsAtLeastZero(distance) + return self.bitshiftRight(words: major, bits: minor) + } + + /// Performs an un/signed right shift. + /// + /// - Parameters: + /// - words: `0 <= words < self.endIndex` + /// - bits: `0 <= bits  < UInt.bitWidth` + /// + @inlinable mutating func bitshiftRight(words: Int, bits: Int) { + //=--------------------------------------= + if bits.isZero { + return self.bitshiftRight(words: words) } + //=--------------------------------------= + self.bitshiftRight(words: words, atLeastOneBit: bits) + } - self.storage.resize(maxCount: self.storage.count - words) + /// Performs an un/signed right shift. + /// + /// - Parameters: + /// - words: `0 <= words < self.endIndex` + /// + @inlinable mutating func bitshiftRight(words: Int) { + //=--------------------------------------= + if words.isZero { return } + //=--------------------------------------= + self.bitshiftRight(atLeastOneWord: words) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Int x Private + //=------------------------------------------------------------------------= + + /// Performs an un/signed right shift. + /// + /// - Parameters: + /// - words: `1 <= words < self.endIndex` + /// - bits: `0 <= bits  < UInt.bitWidth` + /// + @inlinable mutating func bitshiftRight(words: Int, atLeastOneBit bits: Int) { + self.withUnsafeMutableBufferPointer { + NBK.bitshiftRightAsFixedLimbsCodeBlock(&$0, environment: false, limbs: words, atLeastOneBit: bits) + } + } + + /// Performs an un/signed right shift. + /// + /// - Parameters: + /// - words: `1 <= words < self.endIndex` + /// + @inlinable mutating func bitshiftRight(atLeastOneWord words: Int) { + self.withUnsafeMutableBufferPointer { + NBK.bitshiftRightAsFixedLimbsCodeBlock(&$0, environment: false, atLeastOneLimb: words) + } } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Size.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Size.swift index c4b3bb2e..431e2016 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Size.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Size.swift @@ -38,3 +38,52 @@ extension NBKFlexibleWidth.Magnitude { self.storage.reserveCapacity(minCapacity) } } + +//*============================================================================* +// MARK: * NBK x Flexible Width x Size x Unsigned x Storage +//*============================================================================* + +extension NBKFlexibleWidth.Magnitude.Storage { + + //=------------------------------------------------------------------------= + // MARK: Details x Resize + //=------------------------------------------------------------------------= + + @inlinable mutating func append(_ word: UInt) { + self.elements.append(word) + } + + @inlinable mutating func resize(minCount: Int) { + self.reserveCapacity(minCount) + appending: while self.elements.count < minCount { + self.elements.append(UInt.zero) + } + } + + @inlinable mutating func resize(maxCount: Int) { + //=--------------------------------------= + if self.elements.count > maxCount { + self.elements.removeSubrange(maxCount...) + } + //=--------------------------------------= + precondition(self.isOK, Self.invariantsInfo()) + } + + @inlinable mutating func reserveCapacity(_ minCapacity: Int) { + self.elements.reserveCapacity(minCapacity) + } + + //=------------------------------------------------------------------------= + // MARK: Details x Normalization + //=------------------------------------------------------------------------= + + @inlinable mutating func normalize() { + trimming: while self.elements.count > 1, self.elements.last!.isZero { + self.elements.removeLast() + } + } + + @inlinable mutating func normalize(update value: UInt) { + self.elements.replaceSubrange(self.elements.indices, with: CollectionOfOne(value)) + } +} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift index 4bd5fc07..af500992 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift @@ -104,3 +104,18 @@ extension NBKFlexibleWidth.Magnitude { return PVO(partialValue, overflow) } } + +//*============================================================================* +// MARK: * NBK x Flexible Width x Subtraction x Digit x Unsigned x Storage +//*============================================================================* + +extension NBKFlexibleWidth.Magnitude.Storage { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @_disfavoredOverload @inlinable mutating func subtract(_ other: UInt, plus borrow: Bool, at index: Int) -> Bool { + NBK.decrementSufficientUnsignedInteger(&self.elements, by: other, plus: borrow, at: index).overflow + } +} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift index b1acf0e8..e642e2f6 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift @@ -93,7 +93,7 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= if other.isZero { return false } //=--------------------------------------= - self.storage.resize(minCount: other.storage.count + index) + self.storage.resize(minCount: other.storage.elements.count + index) defer{ self.storage.normalize() } return self.storage.subtract(other.storage, plus: false, at: index) } @@ -104,3 +104,24 @@ extension NBKFlexibleWidth.Magnitude { return PVO(partialValue, overflow) } } + +//*============================================================================* +// MARK: * NBK x Flexible Width x Subtraction x Unsigned x Storage +//*============================================================================* + +extension NBKFlexibleWidth.Magnitude.Storage { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable mutating func subtract(_ other: Self, plus borrow: Bool, at index: Int) -> Bool { + NBK.decrementSufficientUnsignedInteger(&self.elements, by: other.elements, plus: borrow, at: index).overflow + } + + @inlinable mutating func subtract(_ other: Self, times multiplicand: UInt, + plus subtrahend: UInt, plus borrow: Bool, at index: Int) -> Bool { + NBK.decrementSufficientUnsignedInteger(&self.elements, by: other .elements, + times: multiplicand, plus: subtrahend, plus: borrow, at: index).overflow + } +} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text.swift index ca58a24e..c9768c0f 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text.swift @@ -138,7 +138,7 @@ extension NBKFlexibleWidth.Magnitude { forwards: if !alignment.isZero { let chunk = NBK.UnsafeUTF8(rebasing: NBK.removePrefix(from: &digits, count: alignment)) guard let word = NBK.truncating(digits: chunk, radix: radix.base, as: UInt.self) else { return nil } - self.storage.first = word + self.storage.elements[self.storage.elements.startIndex] = word } forwards: while !digits.isEmpty { @@ -170,7 +170,7 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= // with one buffer pointer specialization //=--------------------------------------= - self.storage.withContiguousStorage { words in + self.storage.withUnsafeBufferPointer { words in let chunks = NBKTwinHeaded(words) let radix = NBK.AnyRadixSolution(radix) return NBK.integerTextUnchecked(chunks: chunks, radix: radix, alphabet: alphabet, prefix: prefix, suffix: suffix) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Update.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Update.swift index 60c180d8..3f2ba4ef 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Update.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Update.swift @@ -10,7 +10,7 @@ import NBKCoreKit //*============================================================================* -// MARK: * NBK x Flexible Width x Miscellaneous x Signed +// MARK: * NBK x Flexible Width x Update x Signed //*============================================================================* extension NBKFlexibleWidth { @@ -31,7 +31,7 @@ extension NBKFlexibleWidth { } //*============================================================================* -// MARK: * NBK x Flexible Width x Miscellaneous x Unsigned +// MARK: * NBK x Flexible Width x Update x Unsigned //*============================================================================* extension NBKFlexibleWidth.Magnitude { @@ -48,3 +48,26 @@ extension NBKFlexibleWidth.Magnitude { self.storage.normalize(update: value) } } + +//*============================================================================* +// MARK: * NBK x Flexible Width x Update x Unsigned x Storage +//*============================================================================* + +extension NBKFlexibleWidth.Magnitude.Storage { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable mutating func updateZeroValue() { + self.update(repeating: false) + } + + @inlinable mutating func update(repeating bit: Bool) { + self.update(repeating: UInt(repeating: bit)) + } + + @inlinable mutating func update(repeating word: UInt) { + self.withUnsafeMutableBufferPointer({ $0.update(repeating: word) }) + } +} diff --git a/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Text.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words+Pointers.swift similarity index 53% rename from Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Text.swift rename to Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words+Pointers.swift index 2f986d6b..9aab0d6c 100644 --- a/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Text.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words+Pointers.swift @@ -10,24 +10,24 @@ import NBKCoreKit //*============================================================================* -// MARK: * NBK x Resizable Width x Text +// MARK: * NBK x Flexible Width x Words x Pointers x Unsigned x Storage //*============================================================================* -extension NBKResizableWidth.Magnitude { +extension NBKFlexibleWidth.Magnitude.Storage { //=------------------------------------------------------------------------= - // MARK: Details x Decode + // MARK: Details x Contiguous UInt Collection //=------------------------------------------------------------------------= - @inlinable public init?(_ description: some StringProtocol, radix: Int) { - fatalError("TODO") + /// Grants unsafe access to the collection's contiguous storage. + @inlinable func withUnsafeBufferPointer( + _ body: (NBK.UnsafeWords) throws -> T) rethrows -> T { + try self.elements.withUnsafeBufferPointer(body) } - //=------------------------------------------------------------------------= - // MARK: Details x Encode - //=------------------------------------------------------------------------= - - @inlinable public func description(radix: Int = 10, uppercase: Bool = false) -> String { - fatalError("TODO") + /// Grants unsafe access to the collection's contiguous mutable storage. + @inlinable mutating func withUnsafeMutableBufferPointer( + _ body: (inout NBK.UnsafeMutableWords) throws -> T) rethrows -> T { + try self.elements.withUnsafeMutableBufferPointer(body) } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift index cf177d24..be0a597f 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift @@ -25,7 +25,7 @@ extension NBKFlexibleWidth { /// @inlinable public init(words: some Collection) { var magnitude = Magnitude.Storage(words: words) - let sign = Sign(magnitude.last.mostSignificantBit) + let sign = Sign(magnitude.elements.last!.mostSignificantBit) //=--------------------------------------= if sign.bit { magnitude.formTwosComplement() @@ -49,11 +49,14 @@ extension NBKFlexibleWidth { //=------------------------------------------------------------------------= @inlinable var storageNeedsOneMoreWord: Bool { - switch self.isLessThanZero { - case true: return !NBK.mostSignificantBit(twosComplementOf: self.magnitude.storage)! - case false: return self.magnitude.storage.last.mostSignificantBit } + if self.isLessThanZero { + return !self.magnitude.storage.withUnsafeBufferPointer({ NBK.mostSignificantBit(twosComplementOf: $0)! }) + } else { + return self.magnitude.storage.elements.last!.mostSignificantBit + } } + #warning("IntXL and UIntXL can share Words") //*========================================================================* // MARK: * Words //*========================================================================* @@ -81,7 +84,7 @@ extension NBKFlexibleWidth { self.storage.formTwosComplement() } //=----------------------------------= - self.count += self.storage.count + self.count += self.storage.elements.count } //=--------------------------------------------------------------------= @@ -97,8 +100,8 @@ extension NBKFlexibleWidth { } @inlinable public subscript(index: Int) -> UInt { - switch index < self.storage.endIndex { - case true: return self.storage[index] + switch index < self.storage.elements.endIndex { + case true: return self.storage.elements[index] case false: return self.sign } } @@ -107,31 +110,31 @@ extension NBKFlexibleWidth { //=--------------------------------------------------------------------= @inlinable public func distance(from start: Int, to end: Int) -> Int { - self.storage.distance(from: start, to: end) + self.storage.elements.distance(from: start, to: end) } @inlinable public func index(after index: Int) -> Int { - self.storage.index(after: index) + self.storage.elements.index(after: index) } @inlinable public func formIndex(after index: inout Int) { - self.storage.formIndex(after: &index) + self.storage.elements.formIndex(after: &index) } @inlinable public func index(before index: Int) -> Int { - self.storage.index(before: index) + self.storage.elements.index(before: index) } @inlinable public func formIndex(before index: inout Int) { - self.storage.formIndex(before: &index) + self.storage.elements.formIndex(before: &index) } @inlinable public func index(_ index: Int, offsetBy distance: Int) -> Int { - self.storage.index(index, offsetBy: distance) + self.storage.elements.index(index, offsetBy: distance) } @inlinable public func index(_ index: Int, offsetBy distance: Int, limitedBy limit: Int) -> Int? { - self.storage.index(index, offsetBy: distance, limitedBy: limit) + self.storage.elements.index(index, offsetBy: distance, limitedBy: limit) } } } @@ -154,7 +157,27 @@ extension NBKFlexibleWidth.Magnitude { // MARK: Accessors //=------------------------------------------------------------------------= - @inlinable public var words: UIntXR.Words { - _read { yield self.storage.words } + // TODO: do not expose the actual type + @inlinable public var words: ContiguousArray { + _read { yield self.storage.elements } + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Words x Unsigned x Storage +//*============================================================================* + +extension NBKFlexibleWidth.Magnitude.Storage { + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + @inlinable init(words: some Collection) { + self.init(elements: Elements(words)) + } + + @inlinable init(repeating word: UInt, count: Int) { + self.init(elements: Elements(repeating: word, count: count)) } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift index adaf47ca..d00d2f37 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift @@ -71,9 +71,7 @@ import NBKCoreKit @frozen public struct Magnitude: NBKUnsignedInteger, IntXLOrUIntXL { public typealias Digit = UInt - - @usableFromInline typealias Storage = NBKResizableWidth.Magnitude - + //=--------------------------------------------------------------------= // MARK: State //=--------------------------------------------------------------------= @@ -113,6 +111,56 @@ import NBKCoreKit @inlinable public static var description: String { "UIntXL" } + + #warning("TODO: check uses of elements, first!, last!, count, lastIndex") + //*====================================================================* + // MARK: * Storage + //*====================================================================* + + /// An unsigned, resizable, collection of at least one word. + /// + /// Its operations have fixed-width semantics unless stated otherwise. + /// + @frozen @usableFromInline struct Storage { + + @usableFromInline typealias Elements = ContiguousArray + + //=----------------------------------------------------------------= + // MARK: State + //=----------------------------------------------------------------= + + @usableFromInline var elements: ContiguousArray + + //=----------------------------------------------------------------= + // MARK: Initializers + //=----------------------------------------------------------------= + + @inlinable init(elements: Elements) { + self.elements = elements + precondition(self.isOK, Self.invariantsInfo()) + } + + @inlinable init(unchecked elements: Elements) { + self.elements = elements + Swift.assert(self.isOK, Self.invariantsInfo()) + } + + //=----------------------------------------------------------------= + // MARK: Utilities + //=----------------------------------------------------------------= + + @inlinable var isOK: Bool { + !self.elements.isEmpty + } + + @inlinable var isNormal: Bool { + self.elements.count == 1 || !self.elements.last!.isZero + } + + @inlinable static func invariantsInfo() -> String { + "UIntXL must contain at least one element" + } + } } } diff --git a/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Addition+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Addition+Digit.swift deleted file mode 100644 index a7d952e0..00000000 --- a/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Addition+Digit.swift +++ /dev/null @@ -1,38 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Resizable Width x Addition x Unsigned -//*============================================================================* - -extension NBKResizableWidth.Magnitude { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @_disfavoredOverload @inlinable public static func +=(lhs: inout Self, rhs: UInt) { - fatalError("TODO") - } - - @_disfavoredOverload @inlinable public static func +(lhs: Self, rhs: UInt) -> Self { - fatalError("TODO") - } - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - // TODO: rename - @_disfavoredOverload @inlinable public mutating func add(_ other: UInt, plus carry: Bool, at index: Int) -> Bool { - NBK.incrementSufficientUnsignedInteger(&self, by: other, plus: carry, at: index).overflow - } -} diff --git a/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Addition.swift b/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Addition.swift deleted file mode 100644 index 03e448e9..00000000 --- a/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Addition.swift +++ /dev/null @@ -1,38 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Resizable Width x Addition x Unsigned -//*============================================================================* - -extension NBKResizableWidth.Magnitude { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable public static func +=(lhs: inout Self, rhs: Self) { - fatalError("TODO") - } - - @inlinable public static func +(lhs: Self, rhs: Self) -> Self { - fatalError("TODO") - } - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - // TODO: rename - @inlinable public mutating func add(_ other: Self, plus carry: Bool, at index: Int) -> Bool { - NBK.incrementSufficientUnsignedInteger(&self, by: other, plus: carry, at: index).overflow - } -} diff --git a/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Bits.swift b/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Bits.swift deleted file mode 100644 index 1d472b6e..00000000 --- a/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Bits.swift +++ /dev/null @@ -1,53 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Resizable Width x Bits x Unsigned -//*============================================================================* - -extension NBKResizableWidth.Magnitude { - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - @inlinable public init(bit: Bool) { - self.init(digit: Digit(bit: bit)) - } - - //=------------------------------------------------------------------------= - // MARK: Accessors - //=------------------------------------------------------------------------= - - @inlinable public var bitWidth: Int { - self.storage.count * UInt.bitWidth - } - - @inlinable public var nonzeroBitCount: Int { - NBK.nonzeroBitCount(of: self.storage) - } - - @inlinable public var leadingZeroBitCount: Int { - NBK.leadingZeroBitCount(of: self.storage) - } - - @inlinable public var trailingZeroBitCount: Int { - NBK.trailingZeroBitCount(of: self.storage) - } - - @inlinable public var mostSignificantBit: Bool { - self.last.mostSignificantBit - } - - @inlinable public var leastSignificantBit: Bool { - self.first.leastSignificantBit - } -} diff --git a/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Comparisons.swift b/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Comparisons.swift deleted file mode 100644 index 3b1095b1..00000000 --- a/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Comparisons.swift +++ /dev/null @@ -1,89 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Resizable Width x Comparisons x Unsigned -//*============================================================================* - -extension NBKResizableWidth.Magnitude { - - //=------------------------------------------------------------------------= - // MARK: Accessors - //=------------------------------------------------------------------------= - - @inlinable public var isZero: Bool { - self.count == 1 && self.first.isZero - } - - @inlinable public var isLessThanZero: Bool { - false - } - - @inlinable public var isMoreThanZero: Bool { - !self.isZero - } - - @inlinable public var isPowerOf2: Bool { - NBK.nonzeroBitCount(of: self.storage, equals: 1) - } - - @inlinable public func signum() -> Int { - Int(bit: !self.isZero) - } - - //=------------------------------------------------------------------------= - // MARK: Utilities - //=------------------------------------------------------------------------= - - @inlinable public func hash(into hasher: inout Hasher) { - hasher.combine(self.storage) - } - - //=------------------------------------------------------------------------= - // MARK: Utilities - //=------------------------------------------------------------------------= - - @inlinable public static func ==(lhs: Self, rhs: Self) -> Bool { - lhs.compared(to: rhs).isZero - } - - @inlinable public static func <(lhs: Self, rhs: Self) -> Bool { - lhs.compared(to: rhs) == -1 - } - - @inlinable public func compared(to other: Self) -> Int { - self .withContiguousStorage { lhs in - other.withContiguousStorage { rhs in - NBK.compareLenientUnsignedInteger(lhs, to: rhs) - }} - } - - @inlinable public func compared(to other: Self, at index: Int) -> Int { - self .withContiguousStorage { lhs in - other.withContiguousStorage { rhs in - NBK.compareLenientUnsignedInteger(lhs, to: rhs, at: index) - }} - } - - @_disfavoredOverload @inlinable public func compared(to other: Digit) -> Int { - self.withContiguousStorage { lhs in - NBK .withUnsafeWords(of: other) { rhs in - NBK.compareLenientUnsignedInteger(lhs, to: rhs) - }} - } - - @_disfavoredOverload @inlinable public func compared(to other: Digit, at index: Int) -> Int { - self.withContiguousStorage { lhs in - NBK .withUnsafeWords(of: other) { rhs in - NBK.compareLenientUnsignedInteger(lhs, to: rhs, at: index) - }} - } -} diff --git a/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Complements.swift b/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Complements.swift deleted file mode 100644 index 0ff74a50..00000000 --- a/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Complements.swift +++ /dev/null @@ -1,61 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Resizable Width x Complements x Unsigned -//*============================================================================* - -extension NBKResizableWidth.Magnitude { - - //=------------------------------------------------------------------------= - // MARK: Details x One's Complement - //=------------------------------------------------------------------------= - - @inlinable public mutating func formOnesComplement() { - for index in self.storage.indices { - self.storage[index].formOnesComplement() - } - } - - @inlinable public func onesComplement() -> Self { - Self(unchecked: Storage(self.storage.lazy.map(~))) - } - - //=------------------------------------------------------------------------= - // MARK: Details x Two's Complement - //=------------------------------------------------------------------------= - - @inlinable public mutating func formTwosComplementReportingOverflow() -> Bool { - self.formTwosComplementSubsequence(true) - } - - @inlinable public func twosComplementReportingOverflow() -> PVO { - var partialValue = self - let overflow = partialValue.formTwosComplementReportingOverflow() - return PVO(partialValue, overflow) - } - - @inlinable public mutating func formTwosComplementSubsequence(_ carry: Bool) -> Bool { - var carry = carry - - for index in self.storage.indices { - carry = self.storage[index].formTwosComplementSubsequence(carry) - } - - return carry as Bool - } - - @inlinable public func twosComplementSubsequence(_ carry: Bool) -> PVO { - var partialValue = self - let overflow = partialValue.formTwosComplementSubsequence(carry) - return PVO(partialValue, overflow) - } -} diff --git a/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Division+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Division+Digit.swift deleted file mode 100644 index c22adaef..00000000 --- a/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Division+Digit.swift +++ /dev/null @@ -1,57 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Resizable Width x Division x Digit x Unsigned -//*============================================================================* - -extension NBKResizableWidth.Magnitude { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @_disfavoredOverload @inlinable public mutating func divideReportingOverflow(by other: Digit) -> Bool { - let pvo: PVO = self.dividedReportingOverflow(by: other) - self = pvo.partialValue - return pvo.overflow as Bool - } - - @_disfavoredOverload @inlinable public func dividedReportingOverflow(by other: Digit) -> PVO { - let qro: PVO> = self.quotientAndRemainderReportingOverflow(dividingBy: other) - return PVO(qro.partialValue.quotient, qro.overflow) - } - - @_disfavoredOverload @inlinable public mutating func formRemainderReportingOverflow(dividingBy other: Digit) -> Bool { - let pvo: PVO = self.remainderReportingOverflow(dividingBy: other) - self = Self(digit: pvo.partialValue) - return pvo.overflow as Bool - } - - @_disfavoredOverload @inlinable public func remainderReportingOverflow(dividingBy other: Digit) -> PVO { - let qro: PVO> = self.quotientAndRemainderReportingOverflow(dividingBy: other) - return PVO(qro.partialValue.remainder, qro.overflow) - } - - @_disfavoredOverload @inlinable public func quotientAndRemainderReportingOverflow(dividingBy other: Digit) -> PVO> { - var quotient = self - let remainder = quotient.formQuotientWithRemainderReportingOverflow(dividingBy: other) - return PVO(QR(quotient, remainder.partialValue), remainder.overflow) - } - - //=------------------------------------------------------------------------= - // MARK: Transformations x Private - //=------------------------------------------------------------------------= - - @_disfavoredOverload @inlinable public mutating func formQuotientWithRemainderReportingOverflow(dividingBy other: Digit) -> PVO { - NBK.formQuotientWithRemainderReportingOverflowAsLenientUnsignedInteger(of: &self.storage, dividingBy: other) - } -} diff --git a/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Division.swift b/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Division.swift deleted file mode 100644 index 5fe3a91d..00000000 --- a/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Division.swift +++ /dev/null @@ -1,68 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Resizable Width x Division x Unsigned -//*============================================================================* - -extension NBKResizableWidth.Magnitude { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable public mutating func divideReportingOverflow(by other: Self) -> Bool { - let pvo: PVO = self.dividedReportingOverflow(by: other) - self = pvo.partialValue - return pvo.overflow as Bool - } - - @inlinable public func dividedReportingOverflow(by other: Self) -> PVO { - let qro: PVO> = self.quotientAndRemainderReportingOverflow(dividingBy: other) - return PVO(qro.partialValue.quotient, qro.overflow) - } - - @inlinable public mutating func formRemainderReportingOverflow(dividingBy other: Self) -> Bool { - let pvo: PVO = self.remainderReportingOverflow(dividingBy: other) - self = pvo.partialValue - return pvo.overflow as Bool - } - - @inlinable public func remainderReportingOverflow(dividingBy other: Self) -> PVO { - let qro: PVO> = self.quotientAndRemainderReportingOverflow(dividingBy: other) - return PVO(qro.partialValue.remainder, qro.overflow) - } - - @inlinable public func quotientAndRemainderReportingOverflow(dividingBy other: Self) -> PVO> { - self.quotientAndRemainderReportingOverflowAsNormal(dividingBy: other) - } -} - -//=----------------------------------------------------------------------------= -// MARK: + Normal -//=----------------------------------------------------------------------------= - -extension NBKResizableWidth.Magnitude { - - //=------------------------------------------------------------------------= - // MARK: Transformations x Private - //=------------------------------------------------------------------------= - - @inlinable func quotientAndRemainderReportingOverflowAsNormal(dividingBy other: Self) -> PVO> { - var (remainder) = self - let (quotient, overflow) = remainder.formRemainderWithQuotientReportingOverflowAsNormal(dividingBy: other) - return PVO(QR(quotient, remainder), overflow) - } - - @inlinable mutating func formRemainderWithQuotientReportingOverflowAsNormal(dividingBy other: Self) -> PVO { - fatalError("TODO") - } -} diff --git a/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Literals.swift b/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Literals.swift deleted file mode 100644 index f35fcaf1..00000000 --- a/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Literals.swift +++ /dev/null @@ -1,94 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Resizable Width x Literals x Unsigned -//*============================================================================* - -extension NBKResizableWidth.Magnitude { - - //=-------------------------------------------------------------------------= - // MARK: Details x Integer Literal Type - //=-------------------------------------------------------------------------= - #if SBI && swift(>=5.8) - - @inlinable public init(integerLiteral source: StaticBigInt) { - guard let value = Self(exactlyIntegerLiteral: source) else { - preconditionFailure("\(Self.description) cannot represent \(source)") - } - - self = value - } - - // TODO: internal - @inlinable public init?(exactlyIntegerLiteral source: StaticBigInt) { - //=--------------------------------------= - if source.signum() == -1 { return nil } - //=--------------------------------------= - self.init(truncatingIntegerLiteral: source) - } - - // TODO: internal - @inlinable public init(truncatingIntegerLiteral source: StaticBigInt) { - //=--------------------------------------= - let bitWidth = source.bitWidth - let major = NBK .quotientDividingByBitWidthAssumingIsAtLeastZero(bitWidth) - let minor = NBK.remainderDividingByBitWidthAssumingIsAtLeastZero(bitWidth) - let count = major + Int(bit: !minor.isZero) - //=--------------------------------------= - self = Self.uninitialized(count: count) { storage in - for index in storage.indices { - storage[index] = source[index] - } - } - } - - #else - - @inlinable public init(integerLiteral source: Digit.IntegerLiteralType) { - self.init(digit: Digit(integerLiteral: source)) - } - - #endif - //=------------------------------------------------------------------------= - // MARK: Details x String Literal Type - //=------------------------------------------------------------------------= - - /// Creates a new instance from the given string literal. - /// - /// The string literal may contain a plus or minus sign (+ or -), followed by - /// an optional radix indicator (0b, 0o or 0x), then one or more numeric digits - /// (0-9) or letters (a-z or A-Z). If the string literal uses an invalid format, - /// or its value cannot be represented, a runtime error may occur. - /// - /// ``` - /// ┌───────── → ─────────────┐ - /// │ literal │ self │ - /// ├───────── → ─────────────┤ - /// │ "123" │ Int256( 123) │ - /// │ "+0x123" │ Int256( 291) │ - /// │ "-0x123" │ Int256(-291) │ - /// │ "~OX123" │ error │ - /// └───────── → ─────────────┘ - /// ``` - /// - /// - Note: The decoding strategy is case insensitive. - /// - @inlinable public init(stringLiteral source: StaticString) { - if let value = Self(exactlyStringLiteral: source) { self = value } else { - preconditionFailure("\(Self.description) cannot represent \(source)") - } - } - - @inlinable init?(exactlyStringLiteral source: StaticString) { - fatalError("TODO") - } -} diff --git a/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Logic.swift b/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Logic.swift deleted file mode 100644 index c83dd22a..00000000 --- a/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Logic.swift +++ /dev/null @@ -1,94 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Resizable Width x Logic x Unsigned -//*============================================================================* - -extension NBKResizableWidth.Magnitude { - - //=------------------------------------------------------------------------= - // MARK: Transformations x NOT - //=------------------------------------------------------------------------= - - @inlinable public static prefix func ~(x: Self) -> Self { - x.onesComplement() - } - - //=------------------------------------------------------------------------= - // MARK: Transformations x AND - //=------------------------------------------------------------------------= - - @inlinable public static func &=(lhs: inout Self, rhs: Self) { - lhs.upsizeThenFormInIntersection(of: rhs, each: &) - } - - @inlinable public static func &(lhs: Self, rhs: Self) -> Self { - var lhs = lhs; lhs &= rhs; return lhs - } - - //=------------------------------------------------------------------------= - // MARK: Transformations x OR - //=------------------------------------------------------------------------= - - @inlinable public static func |=(lhs: inout Self, rhs: Self) { - lhs.upsizeThenFormInIntersection(of: rhs, each: |) - } - - @inlinable public static func |(lhs: Self, rhs: Self) -> Self { - var lhs = lhs; lhs |= rhs; return lhs - } - - //=------------------------------------------------------------------------= - // MARK: Transformations x XOR - //=------------------------------------------------------------------------= - - @inlinable public static func ^=(lhs: inout Self, rhs: Self) { - lhs.upsizeThenFormInIntersection(of: rhs, each: ^) - } - - @inlinable public static func ^(lhs: Self, rhs: Self) -> Self { - var lhs = lhs; lhs ^= rhs; return lhs - } -} - -//=----------------------------------------------------------------------------= -// MARK: + Algorithms -//=----------------------------------------------------------------------------= - -extension NBKResizableWidth.Magnitude { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable public mutating func upsizeThenFormInIntersection(of other: Self, each element: (UInt, UInt) -> UInt) { - self.resize(minCount: other.storage.count) - self.withContiguousMutableStorage { lhs in - other.withContiguousStorage { rhs in - for index in rhs.indices { - lhs[index] = element(lhs[index], rhs[index]) - } - } - } - } - - @inlinable public mutating func downsizeThenFormInIntersection(of other: Self, each element: (UInt, UInt) -> UInt) { - self.resize(maxCount: other.storage.count) - self.withContiguousMutableStorage { lhs in - other.withContiguousStorage { rhs in - for index in lhs.indices { - lhs[index] = element(lhs[index], rhs[index]) - } - } - } - } -} diff --git a/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Multiplication+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Multiplication+Digit.swift deleted file mode 100644 index 697a782f..00000000 --- a/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Multiplication+Digit.swift +++ /dev/null @@ -1,37 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Resizable Width x Multiplication x Digit x Unsigned -//*============================================================================* - -extension NBKResizableWidth.Magnitude { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @_disfavoredOverload @inlinable public static func *=(lhs: inout Self, rhs: UInt) { - fatalError("TODO") - } - - @_disfavoredOverload @inlinable public static func *(lhs: Self, rhs: UInt) -> Self { - fatalError("TODO") - } - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @_disfavoredOverload @inlinable public mutating func multiply(by other: UInt, add addend: UInt) -> UInt { - NBK.multiplyFullWidthLenientUnsignedInteger(&self, by: other, add: addend) - } -} diff --git a/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Multiplication.swift b/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Multiplication.swift deleted file mode 100644 index 73c0a51c..00000000 --- a/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Multiplication.swift +++ /dev/null @@ -1,63 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Resizable Width x Multiplication x Digit x Unsigned -//*============================================================================* - -extension NBKResizableWidth.Magnitude { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable public static func *=(lhs: inout Self, rhs: Self) { - fatalError("TODO") - } - - @inlinable public static func *(lhs: Self, rhs: Self) -> Self { - fatalError("TODO") - } - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable public func multipliedFullWidth(by multiplicand: Self) -> Self { - self.multipliedFullWidthByNaiveMethod(by: multiplicand, adding: UInt.zero) - } - - @inlinable public func multipliedFullWidthByNaiveMethod(by multiplicand: Self, adding addend: UInt) -> Self { - Self.uninitialized(count: self.storage.count + multiplicand.storage.count) { product in - //=----------------------------------= - // de/init: pointee is trivial - //=----------------------------------= - product.update(repeating: UInt.zero) - //=----------------------------------= - var overflow = addend as UInt - for lhsIndex in self.storage.indices { - let outer = self.storage[lhsIndex] - - for rhsIndex in multiplicand.storage.indices { - let inner = multiplicand.storage[rhsIndex] - var subproduct = outer.multipliedFullWidth(by: inner) - - overflow = UInt(bit: subproduct.low.addReportingOverflow(overflow)) - overflow &+= UInt(bit: product[lhsIndex + rhsIndex].addReportingOverflow(subproduct.low)) - overflow &+= subproduct.high - } - - product[lhsIndex + multiplicand.storage.count] = overflow - overflow = UInt.zero - } - } - } -} diff --git a/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Numbers.swift b/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Numbers.swift deleted file mode 100644 index 664add51..00000000 --- a/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Numbers.swift +++ /dev/null @@ -1,75 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Numbers x Unsigned -//*============================================================================* - -extension NBKResizableWidth.Magnitude { - - //=------------------------------------------------------------------------= - // MARK: Initializers x Digit - //=------------------------------------------------------------------------= - - @inlinable public init(digit: UInt) { - self.init(unchecked:[digit]) - } - - @inlinable public init(digit: UInt, at index: Int) { - self.init(repeating: UInt.zero, count: index + 1) - self.storage[index] = digit - } - - //=------------------------------------------------------------------------= - // MARK: Initializers x Binary Integer - //=------------------------------------------------------------------------= - - @inlinable public init(_ source: some BinaryInteger) { - guard let result = Self(exactly: source) else { - preconditionFailure("\(Self.description) cannot represent \(source)") - } - - self = result - } - - @inlinable public init?(exactly source: some BinaryInteger) { - guard source.signum() >= 0 else { return nil } - self.init(words: source.words) - } - - @inlinable public init(clamping source: some BinaryInteger) { - self = Self(exactly: source) ?? (0 as Self) - } - - @inlinable public init(truncatingIfNeeded source: some BinaryInteger) { - self.init(words: source.words) - } - - //=------------------------------------------------------------------------= - // MARK: Initializers x Binary Floating Point - //=------------------------------------------------------------------------= - - @inlinable public init(_ source: some BinaryFloatingPoint) { - fatalError("TODO") - } - - @inlinable public init?(exactly source: some BinaryFloatingPoint) { - fatalError("TODO") - } - - //=------------------------------------------------------------------------= - // MARK: Initializers x Sign & Magnitude - //=------------------------------------------------------------------------= - - @inlinable public init?(sign: FloatingPointSign, magnitude: Magnitude) { - if sign == FloatingPointSign.plus || magnitude.isZero { self = magnitude } else { return nil } - } -} diff --git a/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Protocols.swift b/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Protocols.swift deleted file mode 100644 index f123f242..00000000 --- a/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Protocols.swift +++ /dev/null @@ -1,107 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Resizable Width x IntXR or UIntXR -//*============================================================================* - -public protocol IntXROrUIntXR: NBKBinaryInteger, ExpressibleByStringLiteral, -MutableCollection, RandomAccessCollection where Magnitude == UIntXR, Element == UInt, -Index == Int, Indices == Range { - - //=------------------------------------------------------------------------= - // MARK: Details x Size - //=------------------------------------------------------------------------= - - @inlinable mutating func append(_ word: UInt) - - @inlinable mutating func resize(minCount: Int) - - @inlinable mutating func resize(maxCount: Int) - - @inlinable mutating func reserveCapacity(_ minCapacity: Int) - - //=------------------------------------------------------------------------= - // MARK: Details x Comparisons - //=------------------------------------------------------------------------= - - func compared(to other: Self, at index: Int) -> Int - - func compared(to other: Digit, at index: Int) -> Int - - //=------------------------------------------------------------------------= - // MARK: Details x Shifts - //=------------------------------------------------------------------------= - - @inlinable mutating func bitshiftLeftSmart(by distance: Int) - - @inlinable func bitshiftedLeftSmart(by distance: Int) -> Self - - @inlinable mutating func bitshiftLeft(by distance: Int) - - @inlinable func bitshiftedLeft(by distance: Int) -> Self - - @inlinable mutating func bitshiftLeft(words: Int, bits: Int) - - @inlinable func bitshiftedLeft(words: Int, bits: Int) -> Self - - @inlinable mutating func bitshiftLeft(words: Int) - - @inlinable func bitshiftedLeft(words: Int) -> Self - - @inlinable mutating func bitshiftRightSmart(by distance: Int) - - @inlinable func bitshiftedRightSmart(by distance: Int) -> Self - - @inlinable mutating func bitshiftRight(by distance: Int) - - @inlinable func bitshiftedRight(by distance: Int) -> Self - - @inlinable mutating func bitshiftRight(words: Int, bits: Int) - - @inlinable func bitshiftedRight(words: Int, bits: Int) -> Self - - @inlinable mutating func bitshiftRight(words: Int) - - @inlinable func bitshiftedRight(words: Int) -> Self - - //=------------------------------------------------------------------------= - // MARK: Details x Update - //=------------------------------------------------------------------------= - - @inlinable mutating func updateZeroValue() - - @inlinable mutating func update(repeating bit: Bool) - - @inlinable mutating func update(repeating word: UInt) - - //=------------------------------------------------------------------------= - // MARK: Details x Words - //=------------------------------------------------------------------------= - - @inlinable var first: UInt { get set } - - @inlinable var last: UInt { get set } - - @inlinable var tail: Digit { get set } - - //=------------------------------------------------------------------------= - // MARK: Details x Words x Pointers - //=------------------------------------------------------------------------= - - @inlinable func withContiguousStorage(_ body: (NBK.UnsafeWords) throws -> T) rethrows -> T - - @inlinable func withContiguousStorageIfAvailable(_ body: (NBK.UnsafeWords) throws -> T) rethrows -> T? - - @inlinable mutating func withContiguousMutableStorage(_ body: (inout NBK.UnsafeMutableWords) throws -> T) rethrows -> T - - @inlinable mutating func withContiguousMutableStorageIfAvailable(_ body: (inout NBK.UnsafeMutableWords) throws -> T) rethrows -> T? -} diff --git a/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Shifts.swift b/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Shifts.swift deleted file mode 100644 index e439dd9c..00000000 --- a/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Shifts.swift +++ /dev/null @@ -1,293 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Resizable Width x Shifts x Unsigned -//*============================================================================* -//=----------------------------------------------------------------------------= -// MARK: + Left -//=----------------------------------------------------------------------------= - -extension NBKResizableWidth.Magnitude { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable public static func <<=(lhs: inout Self, rhs: some BinaryInteger) { - lhs.bitshiftLeftSmart(by: NBK.initOrBitCast(clamping: rhs, as: Int.self)) - } - - @inlinable public static func <<(lhs: Self, rhs: some BinaryInteger) -> Self { - var lhs = lhs; lhs <<= rhs; return lhs - } - - //=------------------------------------------------------------------------= - // MARK: Transformations x Int - //=------------------------------------------------------------------------= - - /// Performs a smart left shift. - /// - /// - Parameters: - /// - distance: `Int.min <= distance <= Int.max` - /// - @inlinable public mutating func bitshiftLeftSmart(by distance: Int) { - let size = distance.magnitude as UInt - switch (distance >= 0, size < UInt(bitPattern: self.bitWidth)) { - case (true, true ): self.bitshiftLeft (by: Int(bitPattern: size)) - case (true, false): self.update(repeating: false) - case (false, true ): self.bitshiftRight(by: Int(bitPattern: size)) - case (false, false): self.update(repeating: self.isLessThanZero) } - } - - /// Performs a smart left shift. - /// - /// - Parameters: - /// - distance: `Int.min <= distance <= Int.max` - /// - @inlinable public func bitshiftedLeftSmart(by distance: Int) -> Self { - var result = self; result.bitshiftLeftSmart(by: distance); return result - } - - /// Performs a left shift. - /// - /// - Parameters: - /// - distance: `0 <= distance < self.bitWidth` - /// - @inlinable public mutating func bitshiftLeft(by distance: Int) { - precondition(distance >= 0, NBK.callsiteOutOfBoundsInfo()) - let major = NBK .quotientDividingByBitWidthAssumingIsAtLeastZero(distance) - let minor = NBK.remainderDividingByBitWidthAssumingIsAtLeastZero(distance) - return self.bitshiftLeft(words: major, bits: minor) - } - - /// Performs a left shift. - /// - /// - Parameters: - /// - distance: `0 <= distance < self.bitWidth` - /// - @inlinable public func bitshiftedLeft(by distance: Int) -> Self { - var result = self; result.bitshiftLeft(by: distance); return result - } - - /// Performs a left shift. - /// - /// - Parameters: - /// - words: `0 <= words < self.endIndex` - /// - bits: `0 <= bits  < UInt.bitWidth` - /// - @inlinable public mutating func bitshiftLeft(words: Int, bits: Int) { - //=--------------------------------------= - if bits.isZero { - return self.bitshiftLeft(words: words) - } - //=--------------------------------------= - self.bitshiftLeft(words: words, atLeastOneBit: bits) - } - - /// Performs a left shift. - /// - /// - Parameters: - /// - words: `0 <= words < self.endIndex` - /// - bits: `0 <= bits  < UInt.bitWidth` - /// - @inlinable public func bitshiftedLeft(words: Int, bits: Int) -> Self { - var result = self; result.bitshiftLeft(words: words, bits: bits); return result - } - - /// Performs a left shift. - /// - /// - Parameters: - /// - words: `0 <= words < self.endIndex` - /// - @inlinable public mutating func bitshiftLeft(words: Int) { - //=--------------------------------------= - if words.isZero { return } - //=--------------------------------------= - self.bitshiftLeft(atLeastOneWord: words) - } - - /// Performs a left shift. - /// - /// - Parameters: - /// - words: `0 <= words < self.endIndex` - /// - @inlinable public func bitshiftedLeft(words: Int) -> Self { - var result = self; result.bitshiftLeft(words: words); return result - } - - //=------------------------------------------------------------------------= - // MARK: Transformations x Int x Private - //=------------------------------------------------------------------------= - - /// Performs a left shift. - /// - /// - Parameters: - /// - words: `0 <= words < self.endIndex` - /// - bits: `1 <= bits  < UInt.bitWidth` - /// - @inlinable mutating func bitshiftLeft(words: Int, atLeastOneBit bits: Int) { - self.withContiguousMutableStorage { - NBK.bitshiftLeftAsFixedLimbsCodeBlock(&$0, environment: false, limbs: words, atLeastOneBit: bits) - } - } - - /// Performs a left shift. - /// - /// - Parameters: - /// - words: `1 <= words < self.endIndex` - /// - @inlinable mutating func bitshiftLeft(atLeastOneWord words: Int) { - self.withContiguousMutableStorage { - NBK.bitshiftLeftAsFixedLimbsCodeBlock(&$0, environment: false, atLeastOneLimb: words) - } - } -} - -//=----------------------------------------------------------------------------= -// MARK: + Right -//=----------------------------------------------------------------------------= - -extension NBKResizableWidth.Magnitude { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable public static func >>=(lhs: inout Self, rhs: some BinaryInteger) { - lhs.bitshiftRightSmart(by: NBK.initOrBitCast(clamping: rhs, as: Int.self)) - } - - @inlinable public static func >>(lhs: Self, rhs: some BinaryInteger) -> Self { - var lhs = lhs; lhs >>= rhs; return lhs - } - - //=------------------------------------------------------------------------= - // MARK: Transformations x Int - //=------------------------------------------------------------------------= - - /// Performs an un/signed, smart, right shift. - /// - /// - Parameters: - /// - distance: `Int.min <= distance <= Int.max` - /// - @inlinable public mutating func bitshiftRightSmart(by distance: Int) { - let size = distance.magnitude as UInt - switch (distance >= 0, size < UInt(bitPattern: self.bitWidth)) { - case (true, true ): self.bitshiftRight(by: Int(bitPattern: size)) - case (true, false): self.update(repeating: self.isLessThanZero) - case (false, true ): self.bitshiftLeft (by: Int(bitPattern: size)) - case (false, false): self.update(repeating: false) } - } - - /// Performs an un/signed, smart, right shift. - /// - /// - Parameters: - /// - distance: `Int.min <= distance <= Int.max` - /// - @inlinable public func bitshiftedRightSmart(by distance: Int) -> Self { - var result = self; result.bitshiftRightSmart(by: distance); return result - } - - /// Performs an un/signed right shift. - /// - /// - Parameters: - /// - distance: `0 <= distance < self.bitWidth` - /// - @inlinable public mutating func bitshiftRight(by distance: Int) { - precondition(distance >= 0, NBK.callsiteOutOfBoundsInfo()) - let major = NBK .quotientDividingByBitWidthAssumingIsAtLeastZero(distance) - let minor = NBK.remainderDividingByBitWidthAssumingIsAtLeastZero(distance) - return self.bitshiftRight(words: major, bits: minor) - } - - /// Performs an un/signed right shift. - /// - /// - Parameters: - /// - distance: `0 <= distance < self.bitWidth` - /// - @inlinable public func bitshiftedRight(by distance: Int) -> Self { - var result = self; result.bitshiftRight(by: distance); return result - } - - /// Performs an un/signed right shift. - /// - /// - Parameters: - /// - words: `0 <= words < self.endIndex` - /// - bits: `0 <= bits  < UInt.bitWidth` - /// - @inlinable public mutating func bitshiftRight(words: Int, bits: Int) { - //=--------------------------------------= - if bits.isZero { - return self.bitshiftRight(words: words) - } - //=--------------------------------------= - self.bitshiftRight(words: words, atLeastOneBit: bits) - } - - /// Performs an un/signed right shift. - /// - /// - Parameters: - /// - words: `0 <= words < self.endIndex` - /// - bits: `0 <= bits  < UInt.bitWidth` - /// - @inlinable public func bitshiftedRight(words: Int, bits: Int) -> Self { - var result = self; result.bitshiftRight(words: words, bits: bits); return result - } - - /// Performs an un/signed right shift. - /// - /// - Parameters: - /// - words: `0 <= words < self.endIndex` - /// - @inlinable public mutating func bitshiftRight(words: Int) { - //=--------------------------------------= - if words.isZero { return } - //=--------------------------------------= - self.bitshiftRight(atLeastOneWord: words) - } - - /// Performs an un/signed right shift. - /// - /// - Parameters: - /// - words: `0 <= words < self.endIndex` - /// - @inlinable public func bitshiftedRight(words: Int) -> Self { - var result = self; result.bitshiftRight(words: words); return result - } - - //=------------------------------------------------------------------------= - // MARK: Transformations x Int x Private - //=------------------------------------------------------------------------= - - /// Performs an un/signed right shift. - /// - /// - Parameters: - /// - words: `1 <= words < self.endIndex` - /// - bits: `0 <= bits  < UInt.bitWidth` - /// - @inlinable mutating func bitshiftRight(words: Int, atLeastOneBit bits: Int) { - self.withContiguousMutableStorage { - NBK.bitshiftRightAsFixedLimbsCodeBlock(&$0, environment: false, limbs: words, atLeastOneBit: bits) - } - } - - /// Performs an un/signed right shift. - /// - /// - Parameters: - /// - words: `1 <= words < self.endIndex` - /// - @inlinable mutating func bitshiftRight(atLeastOneWord words: Int) { - self.withContiguousMutableStorage { - NBK.bitshiftRightAsFixedLimbsCodeBlock(&$0, environment: false, atLeastOneLimb: words) - } - } -} diff --git a/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Size.swift b/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Size.swift deleted file mode 100644 index 8354dcc0..00000000 --- a/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Size.swift +++ /dev/null @@ -1,63 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Resizable Width x Size x Unsigned -//*============================================================================* - -extension NBKResizableWidth.Magnitude { - - //=------------------------------------------------------------------------= - // MARK: Details x Resize - //=------------------------------------------------------------------------= - - @inlinable public mutating func append(_ word: UInt) { - self.storage.append(word) - } - - @inlinable public mutating func resize(minCount: Int) { - self.reserveCapacity(minCount) - appending: while self.storage.count < minCount { - self.storage.append(UInt.zero) - } - } - - @inlinable public mutating func resize(maxCount: Int) { - //=--------------------------------------= - if self.storage.count > maxCount { - self.storage.removeSubrange(maxCount...) - } - //=--------------------------------------= - precondition(self.isOK, Self.callsiteInvariantsInfo()) - } - - @inlinable public mutating func reserveCapacity(_ minCapacity: Int) { - self.storage.reserveCapacity(minCapacity) - } - - //=------------------------------------------------------------------------= - // MARK: Details x Normalization - //=------------------------------------------------------------------------= - - @inlinable public var isNormal: Bool { - self.storage.count == 1 || !self.last.isZero - } - - @inlinable public mutating func normalize() { - trimming: while self.storage.count > 1, self.last.isZero { - self.storage.removeLast() - } - } - - @inlinable public mutating func normalize(update value: UInt) { - self.storage.replaceSubrange(self.storage.indices, with: CollectionOfOne(value)) - } -} diff --git a/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Subtraction+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Subtraction+Digit.swift deleted file mode 100644 index 9744ffc9..00000000 --- a/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Subtraction+Digit.swift +++ /dev/null @@ -1,50 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Resizable Width x Subtraction x Unsigned -//*============================================================================* - -extension NBKResizableWidth.Magnitude { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @_disfavoredOverload @inlinable public static func -=(lhs: inout Self, rhs: UInt) { - fatalError("TODO") - } - - @_disfavoredOverload @inlinable public static func -(lhs: Self, rhs: UInt) -> Self { - fatalError("TODO") - } - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @_disfavoredOverload @inlinable public mutating func subtractReportingOverflow(_ other: UInt) -> Bool { - fatalError("TODO") - } - - @_disfavoredOverload @inlinable public func subtractingReportingOverflow(_ other: UInt) -> PVO { - fatalError("TODO") - } - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - // TODO: rename - @_disfavoredOverload @inlinable public mutating func subtract(_ other: UInt, plus borrow: Bool, at index: Int) -> Bool { - NBK.decrementSufficientUnsignedInteger(&self, by: other, plus: borrow, at: index).overflow - } -} diff --git a/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Subtraction.swift b/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Subtraction.swift deleted file mode 100644 index 45d64738..00000000 --- a/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Subtraction.swift +++ /dev/null @@ -1,55 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Resizable Width x Subtraction x Unsigned -//*============================================================================* - -extension NBKResizableWidth.Magnitude { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable public static func -=(lhs: inout Self, rhs: Self) { - fatalError("TODO") - } - - @inlinable public static func -(lhs: Self, rhs: Self) -> Self { - fatalError("TODO") - } - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable public mutating func subtractReportingOverflow(_ other: Self) -> Bool { - fatalError("TODO") - } - - @inlinable public func subtractingReportingOverflow(_ other: Self) -> PVO { - fatalError("TODO") - } - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - // TODO: rename - @inlinable public mutating func subtract(_ other: Self, plus borrow: Bool, at index: Int) -> Bool { - NBK.decrementSufficientUnsignedInteger(&self, by: other, plus: borrow, at: index).overflow - } - - // TODO: rename - @inlinable public mutating func subtract(_ other: Self, times multiplicand: UInt, plus subtrahend: UInt, plus borrow: Bool, at index: Int) -> Bool { - NBK.decrementSufficientUnsignedInteger(&self, by: other, times: multiplicand, plus: subtrahend, plus: borrow, at: index).overflow - } -} diff --git a/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Update.swift b/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Update.swift deleted file mode 100644 index 4d8f869e..00000000 --- a/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Update.swift +++ /dev/null @@ -1,33 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Resizable Width x Miscellaneous x Unsigned -//*============================================================================* - -extension NBKResizableWidth.Magnitude { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable public mutating func updateZeroValue() { - self.update(repeating: false) - } - - @inlinable public mutating func update(repeating bit: Bool) { - self.update(repeating: UInt(repeating: bit)) - } - - @inlinable public mutating func update(repeating word: UInt) { - self.withContiguousMutableStorage({ $0.update(repeating: word) }) - } -} diff --git a/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Words+Pointers.swift b/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Words+Pointers.swift deleted file mode 100644 index 4c5b65f7..00000000 --- a/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Words+Pointers.swift +++ /dev/null @@ -1,57 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Resizable Width x Words x Pointers x Unsigned -//*============================================================================* - -extension NBKResizableWidth.Magnitude { - - //=------------------------------------------------------------------------= - // MARK: Details x Contiguous UInt Collection - //=------------------------------------------------------------------------= - - /// Grants unsafe access to the collection's contiguous storage. - /// - /// The elements of the contiguous storage appear in the order of the collection. - /// - @inlinable public func withContiguousStorage(_ body: (NBK.UnsafeWords) throws -> T) rethrows -> T { - try self.storage.withUnsafeBufferPointer(body) - } - - /// Grants unsafe access to the collection's contiguous storage. - /// - /// The elements of the contiguous storage appear in the order of the collection. - /// - /// - Note: This member is required by `Swift.Sequence`. - /// - @inlinable public func withContiguousStorageIfAvailable(_ body: (NBK.UnsafeWords) throws -> T) rethrows -> T? { - try self.withContiguousStorage(body) - } - - /// Grants unsafe access to the collection's contiguous mutable storage. - /// - /// The elements of the contiguous mutable storage appear in the order of the collection. - /// - @inlinable public mutating func withContiguousMutableStorage(_ body: (inout NBK.UnsafeMutableWords) throws -> T) rethrows -> T { - try self.storage.withUnsafeMutableBufferPointer(body) - } - - /// Grants unsafe access to the collection's contiguous mutable storage. - /// - /// The elements of the contiguous mutable storage appear in the order of the collection. - /// - /// - Note: This member is required by `Swift.MutableCollection`. - /// - @inlinable public mutating func withContiguousMutableStorageIfAvailable(_ body: (inout NBK.UnsafeMutableWords) throws -> T) rethrows -> T? { - try self.withContiguousMutableStorage(body) - } -} diff --git a/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Words.swift b/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Words.swift deleted file mode 100644 index 69110281..00000000 --- a/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth+Words.swift +++ /dev/null @@ -1,146 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Resizable Width x Words x Unsigned -//*============================================================================* - -extension NBKResizableWidth.Magnitude { - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - @inlinable public init(words: some Collection) { - self.init(storage: Storage(words)) - } - - @inlinable public init(repeating word: UInt, count: Int) { - self.init(storage: Storage(repeating: word, count: count)) - } - - //=------------------------------------------------------------------------= - // MARK: Accessors - //=------------------------------------------------------------------------= - - @inlinable public var count: Int { - self.storage.count - } - - @inlinable public var words: Self { - _read { yield self } - } -} - -//=----------------------------------------------------------------------------= -// MARK: + Collection x Indices -//=----------------------------------------------------------------------------= - -extension NBKResizableWidth.Magnitude { - - //=------------------------------------------------------------------------= - // MARK: Accessors - //=------------------------------------------------------------------------= - - @inlinable public var startIndex: Int { - self.storage.startIndex - } - - @inlinable public var lastIndex: Int { - self.storage.index(before: self.storage.endIndex) - } - - @inlinable public var endIndex: Int { - self.storage.endIndex - } - - @inlinable public var indices: Range { - self.storage.indices - } - - //=------------------------------------------------------------------------= - // MARK: Utilities - //=------------------------------------------------------------------------= - - @inlinable public func distance(from start: Int, to end: Int) -> Int { - end - start - } - - @inlinable public func index(after index: Int) -> Int { - index + 1 - } - - @inlinable public func formIndex(after index: inout Int) { - index += 1 - } - - @inlinable public func index(before index: Int) -> Int { - index - 1 - } - - @inlinable public func formIndex(before index: inout Int) { - index -= 1 - } - - @inlinable public func index(_ index: Int, offsetBy distance: Int) -> Int { - index + distance - } - - @inlinable public func index(_ index: Int, offsetBy distance: Int, limitedBy limit: Int) -> Int? { - let distanceLimit: Int = self.distance(from: index, to: limit) - - guard distance >= 0 - ? distance <= distanceLimit || distanceLimit < 0 - : distance >= distanceLimit || distanceLimit > 0 - else { return nil } - - return self.index(index, offsetBy: distance) as Int - } -} - -//=----------------------------------------------------------------------------= -// MARK: + Collection x Elements -//=----------------------------------------------------------------------------= - -extension NBKResizableWidth.Magnitude { - - /// The least significant word. - /// - /// - Note: This member is required by `Swift.BinaryInteger`. - /// - @inlinable public var _lowWord: UInt { - self.first - } - - /// The least significant word. - @inlinable public var first: UInt { - _read { yield self[self.startIndex] } - _modify { yield &self[self.startIndex] } - } - - /// The most significant word. - @inlinable public var last: UInt { - _read { yield self[self.lastIndex] } - _modify { yield &self[self.lastIndex] } - } - - /// The most significant word, reinterpreted as a ``Digit``. - @inlinable public var tail: Digit { - _read { yield self[self.lastIndex] } - _modify { yield &self[self.lastIndex] } - } - - /// Accesses the word at the given index, from least significant to most. - @inlinable public subscript(_ index: Int) -> UInt { - _read { yield self.storage[index] } - _modify { yield &self.storage[index] } - } -} diff --git a/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth.swift b/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth.swift deleted file mode 100644 index 996f252d..00000000 --- a/Sources/NBKFlexibleWidthKit/NBKResizableWidthKit/NBKResizableWidth.swift +++ /dev/null @@ -1,154 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Resizable Width -//*============================================================================* - -/// A signed, resizable-width, binary integer of at least one word. -@frozen public struct NBKResizableWidth { - - public typealias Digit = Int - - public typealias Words = Self - - @usableFromInline typealias Storage = ContiguousArray - - //=------------------------------------------------------------------------= - // MARK: State - //=------------------------------------------------------------------------= - - @usableFromInline var storage: Storage - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - @inlinable init(storage: Storage) { - self.storage = storage - precondition(self.isOK, Self.callsiteInvariantsInfo()) - } - - @inlinable init(unchecked storage: Storage) { - self.storage = storage - Swift.assert(self.isOK, Self.callsiteInvariantsInfo()) - } - - //=------------------------------------------------------------------------= - // MARK: Invariants - //=------------------------------------------------------------------------= - - /// Returns whether its invariants are kept. - @inlinable var isOK: Bool { - !self.storage.isEmpty - } - - /// Returns a description of the invariants that must be kept. - @inlinable static func callsiteInvariantsInfo() -> String { - "\(Self.description) must contain at least one word" - } - - //=------------------------------------------------------------------------= - // MARK: Utilities - //=------------------------------------------------------------------------= - - /// A `description` of this type. - /// - /// ``` - /// ┌──────────────────────────── → ────────────┐ - /// │ type │ description │ - /// ├──────────────────────────── → ────────────┤ - /// │ NBKResizableWidth │ "IntXR" │ - /// │ NBKResizableWidth.Magnitude │ "UIntXR" │ - /// └──────────────────────────── → ────────────┘ - /// ``` - /// - @inlinable public static var description: String { - "IntXR" - } - - //*========================================================================* - // MARK: * Magnitude - //*========================================================================* - - /// An unsigned, resizable-width, binary integer of at least one word. - @frozen public struct Magnitude: NBKUnsignedInteger, IntXROrUIntXR { - - public typealias Digit = UInt - - public typealias Words = Self - - @usableFromInline typealias Storage = NBKResizableWidth.Storage - - //=--------------------------------------------------------------------= - // MARK: State - //=--------------------------------------------------------------------= - - @usableFromInline var storage: Storage - - //=--------------------------------------------------------------------= - // MARK: Initializers - //=--------------------------------------------------------------------= - - @inlinable init(storage: Storage) { - self.storage = storage - precondition(self.isOK, Self.callsiteInvariantsInfo()) - } - - @inlinable init(unchecked storage: Storage) { - self.storage = storage - Swift.assert(self.isOK, Self.callsiteInvariantsInfo()) - } - - //=--------------------------------------------------------------------= - // MARK: Invariants - //=--------------------------------------------------------------------= - - /// Returns whether its invariants are kept. - @inlinable var isOK: Bool { - !self.storage.isEmpty - } - - /// Returns a description of the invariants that must be kept. - @inlinable static func callsiteInvariantsInfo() -> String { - "\(Self.description) must contain at least one word" - } - - //=--------------------------------------------------------------------= - // MARK: Utilities - //=--------------------------------------------------------------------= - - /// A `description` of this type. - /// - /// ``` - /// ┌──────────────────────────── → ────────────┐ - /// │ type │ description │ - /// ├──────────────────────────── → ────────────┤ - /// │ NBKResizableWidth │ "IntXR" │ - /// │ NBKResizableWidth.Magnitude │ "UIntXR" │ - /// └──────────────────────────── → ────────────┘ - /// ``` - /// - @inlinable public static var description: String { - "UIntXR" - } - } -} - -//*============================================================================* -// MARK: * NBK x Resizable Width x Aliases -//*============================================================================* - -/// A signed, resizable-width, binary integer of at least one word. -public typealias IntXR = NBKResizableWidth - -/// An unsigned, resizable-width, binary integer of at least one word. -public typealias UIntXR = NBKResizableWidth.Magnitude From 20c9b0f672356c789adf2c4e3d63b8d6ac1e6f82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Tue, 12 Sep 2023 15:27:51 +0200 Subject: [PATCH 063/133] Start of 2's complement rework (#44). --- .../NBKFlexibleWidthKit-Benchmarks.xctestplan | 6 - ...NBKTwosComplementKit-Benchmarks.xctestplan | 24 ++ .swiftpm/NBKTwosComplementKit.xctestplan | 32 ++ .../NBKTwosComplementKit-Benchmarks.xcscheme | 46 +++ ...xcscheme => NBKTwosComplementKit.xcscheme} | 26 +- Package.swift | 20 + .../IntXL+Addition+Digit.swift | 76 ++++ .../NBKTwosComplementKit/IntXL+Addition.swift | 76 ++++ Sources/NBKTwosComplementKit/IntXL+Bits.swift | 96 +++++ .../IntXL+Comparisons.swift | 156 +++++++ .../IntXL+Complements.swift | 122 ++++++ .../IntXL+Division+Digit.swift | 94 +++++ .../NBKTwosComplementKit/IntXL+Division.swift | 105 +++++ .../NBKTwosComplementKit/IntXL+Literals.swift | 120 ++++++ .../NBKTwosComplementKit/IntXL+Logic.swift | 112 +++++ .../IntXL+Multiplication+Digit.swift | 62 +++ .../IntXL+Multiplication.swift | 48 +++ .../NBKTwosComplementKit/IntXL+Numbers.swift | 170 ++++++++ .../NBKTwosComplementKit/IntXL+Shifts.swift | 388 ++++++++++++++++++ .../NBKTwosComplementKit/IntXL+Storage.swift | 100 +++++ .../IntXL+Subtraction+Digit.swift | 93 +++++ .../IntXL+Subtraction.swift | 93 +++++ Sources/NBKTwosComplementKit/IntXL+Text.swift | 173 ++++++++ .../NBKTwosComplementKit/IntXL+Words.swift | 70 ++++ Sources/NBKTwosComplementKit/IntXL.swift | 126 ++++++ .../Blank.swift | 1 + .../IntXL+Words.swift | 167 ++++++++ Tests/NBKTwosComplementKitTests/IntXL.swift | 68 +++ 28 files changed, 2651 insertions(+), 19 deletions(-) create mode 100644 .swiftpm/NBKTwosComplementKit-Benchmarks.xctestplan create mode 100644 .swiftpm/NBKTwosComplementKit.xctestplan create mode 100644 .swiftpm/xcode/xcshareddata/xcschemes/NBKTwosComplementKit-Benchmarks.xcscheme rename .swiftpm/xcode/xcshareddata/xcschemes/{NBKResizableWidthKit-Benchmarks.xcscheme => NBKTwosComplementKit.xcscheme} (72%) create mode 100644 Sources/NBKTwosComplementKit/IntXL+Addition+Digit.swift create mode 100644 Sources/NBKTwosComplementKit/IntXL+Addition.swift create mode 100644 Sources/NBKTwosComplementKit/IntXL+Bits.swift create mode 100644 Sources/NBKTwosComplementKit/IntXL+Comparisons.swift create mode 100644 Sources/NBKTwosComplementKit/IntXL+Complements.swift create mode 100644 Sources/NBKTwosComplementKit/IntXL+Division+Digit.swift create mode 100644 Sources/NBKTwosComplementKit/IntXL+Division.swift create mode 100644 Sources/NBKTwosComplementKit/IntXL+Literals.swift create mode 100644 Sources/NBKTwosComplementKit/IntXL+Logic.swift create mode 100644 Sources/NBKTwosComplementKit/IntXL+Multiplication+Digit.swift create mode 100644 Sources/NBKTwosComplementKit/IntXL+Multiplication.swift create mode 100644 Sources/NBKTwosComplementKit/IntXL+Numbers.swift create mode 100644 Sources/NBKTwosComplementKit/IntXL+Shifts.swift create mode 100644 Sources/NBKTwosComplementKit/IntXL+Storage.swift create mode 100644 Sources/NBKTwosComplementKit/IntXL+Subtraction+Digit.swift create mode 100644 Sources/NBKTwosComplementKit/IntXL+Subtraction.swift create mode 100644 Sources/NBKTwosComplementKit/IntXL+Text.swift create mode 100644 Sources/NBKTwosComplementKit/IntXL+Words.swift create mode 100644 Sources/NBKTwosComplementKit/IntXL.swift create mode 100644 Tests/NBKTwosComplementKitBenchmarks/Blank.swift create mode 100644 Tests/NBKTwosComplementKitTests/IntXL+Words.swift create mode 100644 Tests/NBKTwosComplementKitTests/IntXL.swift diff --git a/.swiftpm/NBKFlexibleWidthKit-Benchmarks.xctestplan b/.swiftpm/NBKFlexibleWidthKit-Benchmarks.xctestplan index 0afb521f..44560b00 100644 --- a/.swiftpm/NBKFlexibleWidthKit-Benchmarks.xctestplan +++ b/.swiftpm/NBKFlexibleWidthKit-Benchmarks.xctestplan @@ -13,12 +13,6 @@ }, "testTargets" : [ { - "skippedTests" : [ - "NBKFlexibleWidthBenchmarksOnTextAsIntXL\/testEncodingUsingSwiftStdlibRadix10()", - "NBKFlexibleWidthBenchmarksOnTextAsIntXL\/testEncodingUsingSwiftStdlibRadix16()", - "NBKFlexibleWidthBenchmarksOnTextAsUIntXL\/testEncodingUsingSwiftStdlibRadix10()", - "NBKFlexibleWidthBenchmarksOnTextAsUIntXL\/testEncodingUsingSwiftStdlibRadix16()" - ], "target" : { "containerPath" : "container:", "identifier" : "NBKFlexibleWidthKitBenchmarks", diff --git a/.swiftpm/NBKTwosComplementKit-Benchmarks.xctestplan b/.swiftpm/NBKTwosComplementKit-Benchmarks.xctestplan new file mode 100644 index 00000000..e55e22be --- /dev/null +++ b/.swiftpm/NBKTwosComplementKit-Benchmarks.xctestplan @@ -0,0 +1,24 @@ +{ + "configurations" : [ + { + "id" : "2BBD9A51-D890-4B97-AED4-B9962867DF57", + "name" : "Main", + "options" : { + + } + } + ], + "defaultOptions" : { + "codeCoverage" : false + }, + "testTargets" : [ + { + "target" : { + "containerPath" : "container:", + "identifier" : "NBKTwosComplementKitBenchmarks", + "name" : "NBKTwosComplementKitBenchmarks" + } + } + ], + "version" : 1 +} diff --git a/.swiftpm/NBKTwosComplementKit.xctestplan b/.swiftpm/NBKTwosComplementKit.xctestplan new file mode 100644 index 00000000..97aec1c5 --- /dev/null +++ b/.swiftpm/NBKTwosComplementKit.xctestplan @@ -0,0 +1,32 @@ +{ + "configurations" : [ + { + "id" : "6FC9897F-2BF3-4836-8372-787CE5195F87", + "name" : "Main", + "options" : { + + } + } + ], + "defaultOptions" : { + "codeCoverage" : { + "targets" : [ + { + "containerPath" : "container:", + "identifier" : "NBKTwosComplementKit", + "name" : "NBKTwosComplementKit" + } + ] + } + }, + "testTargets" : [ + { + "target" : { + "containerPath" : "container:", + "identifier" : "NBKTwosComplementKitTests", + "name" : "NBKTwosComplementKitTests" + } + } + ], + "version" : 1 +} diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/NBKTwosComplementKit-Benchmarks.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/NBKTwosComplementKit-Benchmarks.xcscheme new file mode 100644 index 00000000..e22fac90 --- /dev/null +++ b/.swiftpm/xcode/xcshareddata/xcschemes/NBKTwosComplementKit-Benchmarks.xcscheme @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/NBKResizableWidthKit-Benchmarks.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/NBKTwosComplementKit.xcscheme similarity index 72% rename from .swiftpm/xcode/xcshareddata/xcschemes/NBKResizableWidthKit-Benchmarks.xcscheme rename to .swiftpm/xcode/xcshareddata/xcschemes/NBKTwosComplementKit.xcscheme index 7a6e61ad..6e7e3288 100644 --- a/.swiftpm/xcode/xcshareddata/xcschemes/NBKResizableWidthKit-Benchmarks.xcscheme +++ b/.swiftpm/xcode/xcshareddata/xcschemes/NBKTwosComplementKit.xcscheme @@ -14,28 +14,28 @@ buildForAnalyzing = "YES"> + buildConfiguration = "Debug"> Self { + lhs.adding(rhs, at: Int.zero) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @_disfavoredOverload @inlinable public mutating func add(_ other: Int, at index: Int) { + fatalError("TODO") + } + + @_disfavoredOverload @inlinable public func adding(_ other: Int, at index: Int) -> Self { + var result = self + result.add(other, at: index) + return result as Self + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Addition x Digit x UIntXL +//*============================================================================* + +extension UIntXL { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @_disfavoredOverload @inlinable public static func +=(lhs: inout Self, rhs: UInt) { + lhs.add(rhs, at: Int.zero) + } + + @_disfavoredOverload @inlinable public static func +(lhs: Self, rhs: UInt) -> Self { + lhs.adding(rhs, at: Int.zero) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @_disfavoredOverload @inlinable public mutating func add(_ other: UInt, at index: Int) { + fatalError("TODO") + } + + @_disfavoredOverload @inlinable public func adding(_ other: UInt, at index: Int) -> Self { + var result = self + result.add(other, at: index) + return result as Self + } +} diff --git a/Sources/NBKTwosComplementKit/IntXL+Addition.swift b/Sources/NBKTwosComplementKit/IntXL+Addition.swift new file mode 100644 index 00000000..15366da3 --- /dev/null +++ b/Sources/NBKTwosComplementKit/IntXL+Addition.swift @@ -0,0 +1,76 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x Addition x IntXL +//*============================================================================* + +extension IntXL { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public static func +=(lhs: inout Self, rhs: Self) { + lhs.add(rhs, at: Int.zero) + } + + @inlinable public static func +(lhs: Self, rhs: Self) -> Self { + lhs.adding(rhs, at: Int.zero) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public mutating func add(_ other: Self, at index: Int) { + fatalError("TODO") + } + + @inlinable public func adding(_ other: Self, at index: Int) -> Self { + var result = self + result.add(other, at: index) + return result as Self + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Addition x UIntXL +//*============================================================================* + +extension UIntXL { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public static func +=(lhs: inout Self, rhs: Self) { + lhs.add(rhs, at: Int.zero) + } + + @inlinable public static func +(lhs: Self, rhs: Self) -> Self { + lhs.adding(rhs, at: Int.zero) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public mutating func add(_ other: Self, at index: Int) { + fatalError("TODO") + } + + @inlinable public func adding(_ other: Self, at index: Int) -> Self { + var result = self + result.add(other, at: index) + return result as Self + } +} diff --git a/Sources/NBKTwosComplementKit/IntXL+Bits.swift b/Sources/NBKTwosComplementKit/IntXL+Bits.swift new file mode 100644 index 00000000..0543caf7 --- /dev/null +++ b/Sources/NBKTwosComplementKit/IntXL+Bits.swift @@ -0,0 +1,96 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x Bits x IntXL +//*============================================================================* + +extension IntXL { + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + @inlinable public init(bit: Bool) { + self.init(digit: Digit(bit: bit)) + } + + //=------------------------------------------------------------------------= + // MARK: Accessors + //=------------------------------------------------------------------------= + + @inlinable public var bitWidth: Int { + fatalError("TODO") + } + + @inlinable public var nonzeroBitCount: Int { + fatalError("TODO") + } + + @inlinable public var leadingZeroBitCount: Int { + fatalError("TODO") + } + + @inlinable public var trailingZeroBitCount: Int { + fatalError("TODO") + } + + @inlinable public var mostSignificantBit: Bool { + fatalError("TODO") + } + + @inlinable public var leastSignificantBit: Bool { + fatalError("TODO") + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Bits x UIntXL +//*============================================================================* + +extension UIntXL { + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + @inlinable public init(bit: Bool) { + self.init(digit: Digit(bit: bit)) + } + + //=------------------------------------------------------------------------= + // MARK: Accessors + //=------------------------------------------------------------------------= + + @inlinable public var bitWidth: Int { + fatalError("TODO") + } + + @inlinable public var nonzeroBitCount: Int { + fatalError("TODO") + } + + @inlinable public var leadingZeroBitCount: Int { + fatalError("TODO") + } + + @inlinable public var trailingZeroBitCount: Int { + fatalError("TODO") + } + + @inlinable public var mostSignificantBit: Bool { + fatalError("TODO") + } + + @inlinable public var leastSignificantBit: Bool { + fatalError("TODO") + } +} diff --git a/Sources/NBKTwosComplementKit/IntXL+Comparisons.swift b/Sources/NBKTwosComplementKit/IntXL+Comparisons.swift new file mode 100644 index 00000000..8885e076 --- /dev/null +++ b/Sources/NBKTwosComplementKit/IntXL+Comparisons.swift @@ -0,0 +1,156 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x Comparisons x IntXL +//*============================================================================* + +extension IntXL { + + //=------------------------------------------------------------------------= + // MARK: Accessors + //=------------------------------------------------------------------------= + + @inlinable public var isZero: Bool { + fatalError("TODO") + } + + @inlinable public var isLessThanZero: Bool { + fatalError("TODO") + } + + @inlinable public var isMoreThanZero: Bool { + fatalError("TODO") + } + + @inlinable public var isPowerOf2: Bool { + fatalError("TODO") + } + + @inlinable public func signum() -> Int { + fatalError("TODO") + } + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + @inlinable public func hash(into hasher: inout Hasher) { + hasher.combine(self.storage) + } + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + @inlinable public static func ==(lhs: Self, rhs: Self) -> Bool { + lhs.compared(to: rhs).isZero + } + + @inlinable public static func <(lhs: Self, rhs: Self) -> Bool { + lhs.compared(to: rhs) == -1 + } + + @inlinable public func compared(to other: Self) -> Int { + fatalError("TODO") + } + + @inlinable public func compared(to other: Self, at index: Int) -> Int { + fatalError("TODO") + } + + @_disfavoredOverload @inlinable public func compared(to other: Digit) -> Int { + fatalError("TODO") + } + + @_disfavoredOverload @inlinable public func compared(to other: Digit, at index: Int) -> Int { + fatalError("TODO") + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Comparisons x Unsigned +//*============================================================================* + +extension UIntXL { + + //=------------------------------------------------------------------------= + // MARK: Accessors + //=------------------------------------------------------------------------= + + @inlinable public var isZero: Bool { + self.storage.count == 1 && self.storage.first!.isZero + } + + @inlinable public var isLessThanZero: Bool { + false + } + + @inlinable public var isMoreThanZero: Bool { + !self.isZero + } + + @inlinable public var isPowerOf2: Bool { + self.storage.withUnsafeBufferPointer({ NBK.nonzeroBitCount(of: $0, equals: 1) }) + } + + @inlinable public func signum() -> Int { + Int(bit: !self.isZero) + } + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + @inlinable public func hash(into hasher: inout Hasher) { + hasher.combine(self.storage) + } + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + @inlinable public static func ==(lhs: Self, rhs: Self) -> Bool { + lhs.compared(to: rhs).isZero + } + + @inlinable public static func <(lhs: Self, rhs: Self) -> Bool { + lhs.compared(to: rhs) == -1 + } + + @inlinable public func compared(to other: Self) -> Int { + self .storage.withUnsafeBufferPointer { lhs in + other.storage.withUnsafeBufferPointer { rhs in + NBK.compareLenientUnsignedInteger(lhs, to: rhs) + }} + } + + @inlinable public func compared(to other: Self, at index: Int) -> Int { + self .storage.withUnsafeBufferPointer { lhs in + other.storage.withUnsafeBufferPointer { rhs in + NBK.compareLenientUnsignedInteger(lhs, to: rhs, at: index) + }} + } + + @_disfavoredOverload @inlinable public func compared(to other: Digit) -> Int { + self.storage.withUnsafeBufferPointer { lhs in + NBK .withUnsafeWords(of: other) { rhs in + NBK.compareLenientUnsignedInteger(lhs, to: rhs) + }} + } + + @_disfavoredOverload @inlinable public func compared(to other: Digit, at index: Int) -> Int { + self.storage.withUnsafeBufferPointer { lhs in + NBK .withUnsafeWords(of: other) { rhs in + NBK.compareLenientUnsignedInteger(lhs, to: rhs, at: index) + }} + } +} diff --git a/Sources/NBKTwosComplementKit/IntXL+Complements.swift b/Sources/NBKTwosComplementKit/IntXL+Complements.swift new file mode 100644 index 00000000..53c4fa5a --- /dev/null +++ b/Sources/NBKTwosComplementKit/IntXL+Complements.swift @@ -0,0 +1,122 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x Complements x IntXL +//*============================================================================* + +extension IntXL { + + //=------------------------------------------------------------------------= + // MARK: Details x Magnitude + //=------------------------------------------------------------------------= + + @inlinable public var magnitude: UIntXL { + fatalError("TODO") + } + + //=------------------------------------------------------------------------= + // MARK: Details x Two's Complement + //=------------------------------------------------------------------------= + + @inlinable public mutating func formOnesComplement() { + fatalError("TODO") + } + + @inlinable public func onesComplement() -> Self { + var result = self + result.formOnesComplement() + return result as Self + } + + //=------------------------------------------------------------------------= + // MARK: Details x Two's Complement + //=------------------------------------------------------------------------= + + @inlinable public mutating func formTwosComplementReportingOverflow() -> Bool { + fatalError("TODO") + } + + @inlinable public func twosComplementReportingOverflow() -> PVO { + var partialValue = self + let overflow = partialValue.formTwosComplementReportingOverflow() + return PVO(partialValue, overflow) + } + + @inlinable public mutating func formTwosComplementSubsequence(_ carry: Bool) -> Bool { + switch carry { + case true : return self.formTwosComplementReportingOverflow() + case false: self.formOnesComplement(); return false } + } + + @inlinable public func twosComplementSubsequence(_ carry: Bool) -> PVO { + var partialValue = self + let overflow = partialValue.formTwosComplementSubsequence(carry) + return PVO(partialValue, overflow) + } + + //=------------------------------------------------------------------------= + // MARK: Details x Additive Inverse + //=------------------------------------------------------------------------= + + @inlinable public mutating func negateReportingOverflow() -> Bool { + fatalError("TODO") + } + + @inlinable public func negatedReportingOverflow() -> PVO { + var partialValue = self + let overflow = partialValue.negateReportingOverflow() + return PVO(partialValue, overflow) + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Complements x UIntXL +//*============================================================================* + +extension UIntXL { + + //=------------------------------------------------------------------------= + // MARK: Details x One's Complement + //=------------------------------------------------------------------------= + + @inlinable public mutating func formOnesComplement() { + fatalError("TODO") + } + + @inlinable public func onesComplement() -> Self { + fatalError("TODO") + } + + //=------------------------------------------------------------------------= + // MARK: Details x Two's Complement + //=------------------------------------------------------------------------= + + @inlinable public mutating func formTwosComplementReportingOverflow() -> Bool { + fatalError("TODO") + } + + @inlinable public func twosComplementReportingOverflow() -> PVO { + var partialValue = self + let overflow = partialValue.formTwosComplementReportingOverflow() + return PVO(partialValue, overflow) + } + + @inlinable public mutating func formTwosComplementSubsequence(_ carry: Bool) -> Bool { + fatalError("TODO") + } + + @inlinable public func twosComplementSubsequence(_ carry: Bool) -> PVO { + var partialValue = self + let overflow = partialValue.formTwosComplementSubsequence(carry) + return PVO(partialValue, overflow) + } +} diff --git a/Sources/NBKTwosComplementKit/IntXL+Division+Digit.swift b/Sources/NBKTwosComplementKit/IntXL+Division+Digit.swift new file mode 100644 index 00000000..f85de0dc --- /dev/null +++ b/Sources/NBKTwosComplementKit/IntXL+Division+Digit.swift @@ -0,0 +1,94 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x Division x Digit x IntXL +//*============================================================================* + +extension IntXL { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @_disfavoredOverload @inlinable public mutating func divideReportingOverflow(by other: Digit) -> Bool { + let pvo: PVO = self.dividedReportingOverflow(by: other) + self = pvo.partialValue + return pvo.overflow as Bool + } + + @_disfavoredOverload @inlinable public func dividedReportingOverflow(by other: Digit) -> PVO { + let qro: PVO> = self.quotientAndRemainderReportingOverflow(dividingBy: other) + return PVO(qro.partialValue.quotient, qro.overflow) + } + + @_disfavoredOverload @inlinable public mutating func formRemainderReportingOverflow(dividingBy other: Digit) -> Bool { + let pvo: PVO = self.remainderReportingOverflow(dividingBy: other) + self = Self(digit: pvo.partialValue) + return pvo.overflow as Bool + } + + @_disfavoredOverload @inlinable public func remainderReportingOverflow(dividingBy other: Digit) -> PVO { + let qro: PVO> = self.quotientAndRemainderReportingOverflow(dividingBy: other) + return PVO(qro.partialValue.remainder, qro.overflow) + } + + @_disfavoredOverload @inlinable public func quotientAndRemainderReportingOverflow(dividingBy other: Digit) -> PVO> { + fatalError("TODO") + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Division x Digit x UIntXL +//*============================================================================* + +extension UIntXL { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @_disfavoredOverload @inlinable public mutating func divideReportingOverflow(by other: Digit) -> Bool { + let pvo: PVO = self.dividedReportingOverflow(by: other) + self = pvo.partialValue + return pvo.overflow as Bool + } + + @_disfavoredOverload @inlinable public func dividedReportingOverflow(by other: Digit) -> PVO { + let qro: PVO> = self.quotientAndRemainderReportingOverflow(dividingBy: other) + return PVO(qro.partialValue.quotient, qro.overflow) + } + + @_disfavoredOverload @inlinable public mutating func formRemainderReportingOverflow(dividingBy other: Digit) -> Bool { + let pvo: PVO = self.remainderReportingOverflow(dividingBy: other) + self = Self(digit: pvo.partialValue) + return pvo.overflow as Bool + } + + @_disfavoredOverload @inlinable public func remainderReportingOverflow(dividingBy other: Digit) -> PVO { + let qro: PVO> = self.quotientAndRemainderReportingOverflow(dividingBy: other) + return PVO(qro.partialValue.remainder, qro.overflow) + } + + @_disfavoredOverload @inlinable public func quotientAndRemainderReportingOverflow(dividingBy other: Digit) -> PVO> { + var quotient = self + let remainder = quotient.formQuotientWithRemainderReportingOverflow(dividingBy: other) + return PVO(QR(quotient, remainder.partialValue), remainder.overflow) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Private + //=------------------------------------------------------------------------= + + @_disfavoredOverload @inlinable public mutating func formQuotientWithRemainderReportingOverflow(dividingBy other: Digit) -> PVO { + fatalError("TODO") + } +} diff --git a/Sources/NBKTwosComplementKit/IntXL+Division.swift b/Sources/NBKTwosComplementKit/IntXL+Division.swift new file mode 100644 index 00000000..5068f5df --- /dev/null +++ b/Sources/NBKTwosComplementKit/IntXL+Division.swift @@ -0,0 +1,105 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x Division x IntXL +//*============================================================================* + +extension IntXL { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public mutating func divideReportingOverflow(by other: Self) -> Bool { + let pvo: PVO = self.dividedReportingOverflow(by: other) + self = pvo.partialValue + return pvo.overflow as Bool + } + + @inlinable public func dividedReportingOverflow(by other: Self) -> PVO { + let qro: PVO> = self.quotientAndRemainderReportingOverflow(dividingBy: other) + return PVO(qro.partialValue.quotient, qro.overflow) + } + + @inlinable public mutating func formRemainderReportingOverflow(dividingBy other: Self) -> Bool { + let pvo: PVO = self.remainderReportingOverflow(dividingBy: other) + self = pvo.partialValue + return pvo.overflow as Bool + } + + @inlinable public func remainderReportingOverflow(dividingBy other: Self) -> PVO { + let qro: PVO> = self.quotientAndRemainderReportingOverflow(dividingBy: other) + return PVO(qro.partialValue.remainder, qro.overflow) + } + + @inlinable public func quotientAndRemainderReportingOverflow(dividingBy other: Self) -> PVO> { + fatalError("TODO") + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Division x UIntXL +//*============================================================================* + +extension UIntXL { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public mutating func divideReportingOverflow(by other: Self) -> Bool { + let pvo: PVO = self.dividedReportingOverflow(by: other) + self = pvo.partialValue + return pvo.overflow as Bool + } + + @inlinable public func dividedReportingOverflow(by other: Self) -> PVO { + let qro: PVO> = self.quotientAndRemainderReportingOverflow(dividingBy: other) + return PVO(qro.partialValue.quotient, qro.overflow) + } + + @inlinable public mutating func formRemainderReportingOverflow(dividingBy other: Self) -> Bool { + let pvo: PVO = self.remainderReportingOverflow(dividingBy: other) + self = pvo.partialValue + return pvo.overflow as Bool + } + + @inlinable public func remainderReportingOverflow(dividingBy other: Self) -> PVO { + let qro: PVO> = self.quotientAndRemainderReportingOverflow(dividingBy: other) + return PVO(qro.partialValue.remainder, qro.overflow) + } + + @inlinable public func quotientAndRemainderReportingOverflow(dividingBy other: Self) -> PVO> { + self.quotientAndRemainderReportingOverflowAsNormal(dividingBy: other) + } +} + +//=----------------------------------------------------------------------------= +// MARK: + Normal +//=----------------------------------------------------------------------------= + +extension UIntXL { + + //=------------------------------------------------------------------------= + // MARK: Transformations x Private + //=------------------------------------------------------------------------= + + @inlinable func quotientAndRemainderReportingOverflowAsNormal(dividingBy other: Self) -> PVO> { + var (remainder) = self + let (quotient, overflow) = remainder.formRemainderWithQuotientReportingOverflowAsNormal(dividingBy: other) + return PVO(QR(quotient, remainder), overflow) + } + + @inlinable mutating func formRemainderWithQuotientReportingOverflowAsNormal(dividingBy other: Self) -> PVO { + fatalError("TODO") + } +} diff --git a/Sources/NBKTwosComplementKit/IntXL+Literals.swift b/Sources/NBKTwosComplementKit/IntXL+Literals.swift new file mode 100644 index 00000000..6279d68b --- /dev/null +++ b/Sources/NBKTwosComplementKit/IntXL+Literals.swift @@ -0,0 +1,120 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x Literals x IntXL +//*============================================================================* + +extension IntXL { + + //=-------------------------------------------------------------------------= + // MARK: Details x Integer Literal Type + //=-------------------------------------------------------------------------= + + @inlinable public init(integerLiteral source: Digit) { + self.init(digit: source) + } + + //=------------------------------------------------------------------------= + // MARK: Details x String Literal Type + //=------------------------------------------------------------------------= + + /// Creates a new instance from the given string literal. + /// + /// The string literal may contain a plus or minus sign (+ or -), followed by + /// an optional radix indicator (0b, 0o or 0x), then one or more numeric digits + /// (0-9) or letters (a-z or A-Z). If the string literal uses an invalid format, + /// or its value cannot be represented, a runtime error may occur. + /// + /// ``` + /// ┌───────── → ─────────────┐ + /// │ literal │ self │ + /// ├───────── → ─────────────┤ + /// │ "123" │ Int256( 123) │ + /// │ "+0x123" │ Int256( 291) │ + /// │ "-0x123" │ Int256(-291) │ + /// │ "~OX123" │ error │ + /// └───────── → ─────────────┘ + /// ``` + /// + /// - Note: The decoding strategy is case insensitive. + /// + @inlinable public init(stringLiteral source: StaticString) { + if let value = Self(exactlyStringLiteral: source) { self = value } else { + preconditionFailure("\(Self.description) cannot represent \(source)") + } + } + + @inlinable init?(exactlyStringLiteral source: StaticString) { + if let value: Self = source.withUTF8Buffer({ utf8 in + let components = NBK.makeIntegerComponentsByDecodingRadix(utf8: utf8) + let radix = NBK.AnyRadixSolution(components.radix) + let digits = NBK.UnsafeUTF8(rebasing: components.body ) + guard let magnitude = Magnitude(digits: digits, radix: radix) else { return nil } + return Self(sign: components.sign, magnitude: magnitude) + }){ self = value } else { return nil } + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Literals x Unsigned +//*============================================================================* + +extension UIntXL { + + //=-------------------------------------------------------------------------= + // MARK: Details x Integer Literal Type + //=-------------------------------------------------------------------------= + + @inlinable public init(integerLiteral source: Digit) { + self.init(digit: source) + } + + //=------------------------------------------------------------------------= + // MARK: Details x String Literal Type + //=------------------------------------------------------------------------= + + /// Creates a new instance from the given string literal. + /// + /// The string literal may contain a plus or minus sign (+ or -), followed by + /// an optional radix indicator (0b, 0o or 0x), then one or more numeric digits + /// (0-9) or letters (a-z or A-Z). If the string literal uses an invalid format, + /// or its value cannot be represented, a runtime error may occur. + /// + /// ``` + /// ┌───────── → ─────────────┐ + /// │ literal │ self │ + /// ├───────── → ─────────────┤ + /// │ "123" │ Int256( 123) │ + /// │ "+0x123" │ Int256( 291) │ + /// │ "-0x123" │ Int256(-291) │ + /// │ "~OX123" │ error │ + /// └───────── → ─────────────┘ + /// ``` + /// + /// - Note: The decoding strategy is case insensitive. + /// + @inlinable public init(stringLiteral source: StaticString) { + if let value = Self(exactlyStringLiteral: source) { self = value } else { + preconditionFailure("\(Self.description) cannot represent \(source)") + } + } + + @inlinable init?(exactlyStringLiteral source: StaticString) { + if let value: Self = source.withUTF8Buffer({ utf8 in + let components = NBK.makeIntegerComponentsByDecodingRadix(utf8: utf8) + let radix = NBK.AnyRadixSolution(components.radix) + let digits = NBK.UnsafeUTF8(rebasing: components.body ) + guard let magnitude = Magnitude(digits: digits, radix: radix) else { return nil } + return Self(sign: components.sign, magnitude: magnitude) + }){ self = value } else { return nil } + } +} diff --git a/Sources/NBKTwosComplementKit/IntXL+Logic.swift b/Sources/NBKTwosComplementKit/IntXL+Logic.swift new file mode 100644 index 00000000..b938fdbe --- /dev/null +++ b/Sources/NBKTwosComplementKit/IntXL+Logic.swift @@ -0,0 +1,112 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x Logic x IntXL +//*============================================================================* + +extension IntXL { + + //=------------------------------------------------------------------------= + // MARK: Transformations x NOT + //=------------------------------------------------------------------------= + + @inlinable public static prefix func ~(x: Self) -> Self { + x.onesComplement() + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x AND + //=------------------------------------------------------------------------= + + @inlinable public static func &=(lhs: inout Self, rhs: Self) { + fatalError("TODO") + } + + @inlinable public static func &(lhs: Self, rhs: Self) -> Self { + var lhs = lhs; lhs &= rhs; return lhs + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x OR + //=------------------------------------------------------------------------= + + @inlinable public static func |=(lhs: inout Self, rhs: Self) { + fatalError("TODO") + } + + @inlinable public static func |(lhs: Self, rhs: Self) -> Self { + var lhs = lhs; lhs |= rhs; return lhs + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x XOR + //=------------------------------------------------------------------------= + + @inlinable public static func ^=(lhs: inout Self, rhs: Self) { + fatalError("TODO") + } + + @inlinable public static func ^(lhs: Self, rhs: Self) -> Self { + var lhs = lhs; lhs ^= rhs; return lhs + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Logic x UIntXL +//*============================================================================* + +extension UIntXL { + + //=------------------------------------------------------------------------= + // MARK: Transformations x NOT + //=------------------------------------------------------------------------= + + @inlinable public static prefix func ~(x: Self) -> Self { + x.onesComplement() + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x AND + //=------------------------------------------------------------------------= + + @inlinable public static func &=(lhs: inout Self, rhs: Self) { + fatalError("TODO") + } + + @inlinable public static func &(lhs: Self, rhs: Self) -> Self { + var lhs = lhs; lhs &= rhs; return lhs + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x OR + //=------------------------------------------------------------------------= + + @inlinable public static func |=(lhs: inout Self, rhs: Self) { + fatalError("TODO") + } + + @inlinable public static func |(lhs: Self, rhs: Self) -> Self { + var lhs = lhs; lhs |= rhs; return lhs + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x XOR + //=------------------------------------------------------------------------= + + @inlinable public static func ^=(lhs: inout Self, rhs: Self) { + fatalError("TODO") + } + + @inlinable public static func ^(lhs: Self, rhs: Self) -> Self { + var lhs = lhs; lhs ^= rhs; return lhs + } +} diff --git a/Sources/NBKTwosComplementKit/IntXL+Multiplication+Digit.swift b/Sources/NBKTwosComplementKit/IntXL+Multiplication+Digit.swift new file mode 100644 index 00000000..8c035d32 --- /dev/null +++ b/Sources/NBKTwosComplementKit/IntXL+Multiplication+Digit.swift @@ -0,0 +1,62 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x Multiplication x Digit x IntXL +//*============================================================================* + +extension IntXL { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @_disfavoredOverload @inlinable public static func *=(lhs: inout Self, rhs: Int) { + fatalError("TODO") + } + + @_disfavoredOverload @inlinable public static func *(lhs: Self, rhs: Int) -> Self { + fatalError("TODO") + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Multiplication x Digit x UIntXL +//*============================================================================* + +extension UIntXL { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @_disfavoredOverload @inlinable public static func *=(lhs: inout Self, rhs: UInt) { + lhs.multiply(by: rhs, add: UInt.zero) + } + + @_disfavoredOverload @inlinable public static func *(lhs: Self, rhs: UInt) -> Self { + lhs.multiplied(by: rhs, adding: UInt.zero) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @_disfavoredOverload @inlinable public mutating func multiply(by multiplicand: UInt, add addend: UInt) { + fatalError("TODO") + } + + @_disfavoredOverload @inlinable public func multiplied(by multiplicand: UInt, adding addend: UInt) -> Self { + var result = self + result.multiply(by: multiplicand, add: addend) + return result as Self + } +} diff --git a/Sources/NBKTwosComplementKit/IntXL+Multiplication.swift b/Sources/NBKTwosComplementKit/IntXL+Multiplication.swift new file mode 100644 index 00000000..4dd0b591 --- /dev/null +++ b/Sources/NBKTwosComplementKit/IntXL+Multiplication.swift @@ -0,0 +1,48 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x Multiplication x IntXL +//*============================================================================* + +extension IntXL { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public static func *=(lhs: inout Self, rhs: Self) { + fatalError("TODO") + } + + @inlinable public static func *(lhs: Self, rhs: Self) -> Self { + fatalError("TODO") + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Multiplication x UIntXL +//*============================================================================* + +extension UIntXL { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public static func *=(lhs: inout Self, rhs: Self) { + fatalError("TODO") + } + + @inlinable public static func *(lhs: Self, rhs: Self) -> Self { + fatalError("TODO") + } +} diff --git a/Sources/NBKTwosComplementKit/IntXL+Numbers.swift b/Sources/NBKTwosComplementKit/IntXL+Numbers.swift new file mode 100644 index 00000000..be01b8d3 --- /dev/null +++ b/Sources/NBKTwosComplementKit/IntXL+Numbers.swift @@ -0,0 +1,170 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x Numbers x IntXL +//*============================================================================* + +extension IntXL { + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + public static let zero = Self(0) + + //=------------------------------------------------------------------------= + // MARK: Initializers x Digit + //=------------------------------------------------------------------------= + + @inlinable public init(digit: Int) { + self.init(unchecked: [UInt(bitPattern: digit)]) + } + + //=------------------------------------------------------------------------= + // MARK: Initializers x Binary Integer + //=------------------------------------------------------------------------= + + @inlinable public init(_ source: some BinaryInteger) { + //=--------------------------------------= + // Magnitude + //=--------------------------------------= + if let source = source as? Magnitude { + self.init(sign: FloatingPointSign.plus, magnitude: source) + //=--------------------------------------= + // some BinaryInteger + //=--------------------------------------= + } else { + let sign = FloatingPointSign(source < 0) + let magnitude = Magnitude(source.magnitude) + self.init(sign: sign, magnitude: magnitude) + } + } + + @inlinable public init?(exactly source: some BinaryInteger) { + self.init(source) + } + + @inlinable public init(clamping source: some BinaryInteger) { + self.init(source) + } + + @inlinable public init(truncatingIfNeeded source: some BinaryInteger) { + self.init(source) + } + + //=------------------------------------------------------------------------= + // MARK: Initializers x Binary Floating Point + //=------------------------------------------------------------------------= + + @inlinable public init(_ source: some BinaryFloatingPoint) { + guard let result = Self(exactly: source.rounded(.towardZero)) else { + preconditionFailure("\(Self.description) cannot represent \(source)") + } + + self = result + } + + @inlinable public init?(exactly source: some BinaryFloatingPoint) { + guard let magnitude = Magnitude(exactly: source.magnitude) else { return nil } + self.init(sign: source.sign, magnitude: magnitude) + } + + //=------------------------------------------------------------------------= + // MARK: Initializers x Sign & Magnitude + //=------------------------------------------------------------------------= + + @inlinable public init(sign: FloatingPointSign, magnitude: Magnitude) { + fatalError("TODO") + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Numbers x UIntXL +//*============================================================================* + +extension UIntXL { + + //=------------------------------------------------------------------------= + // MARK: Constants + //=------------------------------------------------------------------------= + + public static let zero = Self(0) + + //=------------------------------------------------------------------------= + // MARK: Initializers x Digit + //=------------------------------------------------------------------------= + + @inlinable public init(digit: UInt) { + self.init(unchecked: [digit]) + } + + //=------------------------------------------------------------------------= + // MARK: Initializers x Binary Integer + //=------------------------------------------------------------------------= + + @inlinable public init(_ source: some BinaryInteger) { + guard let result = Self(exactly: source) else { + preconditionFailure("\(Self.description) cannot represent \(source)") + } + + self = result + } + + @inlinable public init?(exactly source: some BinaryInteger) { + guard source.signum() >= 0 else { return nil } + self.init(words: source.words) + } + + @inlinable public init(clamping source: some BinaryInteger) { + self = Self(exactly: source) ?? (0 as Self) + } + + @inlinable public init(truncatingIfNeeded source: some BinaryInteger) { + self.init(words: source.words) + } + + //=------------------------------------------------------------------------= + // MARK: Initializers x Binary Floating Point + //=------------------------------------------------------------------------= + + @inlinable public init(_ source: some BinaryFloatingPoint) { + guard let value = Self(exactly: source.rounded(.towardZero)) else { + preconditionFailure("\(Self.description) cannot represent \(source)") + } + + self = value + } + + @inlinable public init?(exactly source: some BinaryFloatingPoint) { + if source.sign == .minus { return nil } + //=--------------------------------------= + if source.isZero { self.init(); return } + guard source.isFinite else { return nil } + let value = source.rounded(.towardZero) + guard value == source else { return nil } + //=--------------------------------------= + let exponent = Int(source.exponent) + let ratio = exponent.quotientAndRemainder(dividingBy: UInt.bitWidth) + //=--------------------------------------= + self.init(exactly: source.significandBitPattern) + self >>= type(of: source).significandBitCount - exponent + self.add(UInt(1) << ratio.remainder, at: ratio.quotient) + } + + //=------------------------------------------------------------------------= + // MARK: Initializers x Sign & Magnitude + //=------------------------------------------------------------------------= + + @inlinable public init?(sign: FloatingPointSign, magnitude: Magnitude) { + if sign == FloatingPointSign.plus || magnitude.isZero { self = magnitude } else { return nil } + } +} diff --git a/Sources/NBKTwosComplementKit/IntXL+Shifts.swift b/Sources/NBKTwosComplementKit/IntXL+Shifts.swift new file mode 100644 index 00000000..6ead1415 --- /dev/null +++ b/Sources/NBKTwosComplementKit/IntXL+Shifts.swift @@ -0,0 +1,388 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x Shifts x IntXL +//*============================================================================* +//=----------------------------------------------------------------------------= +// MARK: + Left +//=----------------------------------------------------------------------------= + +extension IntXL { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public static func <<=(lhs: inout Self, rhs: some BinaryInteger) { + lhs.bitshiftLeftSmart(by: NBK.initOrBitCast(clamping: rhs, as: Int.self)) + } + + @inlinable public static func <<(lhs: Self, rhs: some BinaryInteger) -> Self { + var lhs = lhs; lhs <<= rhs; return lhs + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Int + //=------------------------------------------------------------------------= + + @inlinable public mutating func bitshiftLeftSmart(by distance: Int) { + if distance >= 0 { + self.bitshiftLeft (by: distance) + } else { + self.bitshiftRight(by: Int(clamping: distance.magnitude)) + } + } + + @inlinable public func bitshiftedLeftSmart(by distance: Int) -> Self { + var result = self; result.bitshiftLeftSmart(by: distance); return result + } + + @inlinable public mutating func bitshiftLeft(by distance: Int) { + precondition(distance >= 0, NBK.callsiteOutOfBoundsInfo()) + let major = NBK .quotientDividingByBitWidthAssumingIsAtLeastZero(distance) + let minor = NBK.remainderDividingByBitWidthAssumingIsAtLeastZero(distance) + return self.bitshiftLeft(words: major, bits: minor) + } + + @inlinable public func bitshiftedLeft(by distance: Int) -> Self { + var result = self; result.bitshiftLeft(by: distance); return result + } + + @inlinable public mutating func bitshiftLeft(words: Int, bits: Int) { + //=--------------------------------------= + if bits.isZero { + return self.bitshiftRight(words: words) + } + //=--------------------------------------= + self.bitshiftLeft(words: words, atLeastOneBit: bits) + } + + @inlinable public func bitshiftedLeft(words: Int, bits: Int) -> Self { + var result = self; result.bitshiftLeft(words: words, bits: bits); return result + } + + @inlinable public mutating func bitshiftLeft(words: Int) { + //=--------------------------------------= + if words.isZero { return } + //=--------------------------------------= + self.bitshiftLeft(atLeastOneWord: words) + } + + @inlinable public func bitshiftedLeft(words: Int) -> Self { + var result = self; result.bitshiftLeft(words: words); return result + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Int x Private + //=------------------------------------------------------------------------= + + /// Performs a left shift. + /// + /// - Parameters: + /// - words: `0 <= words < self.endIndex` + /// - bits: `1 <= bits  < UInt.bitWidth` + /// + @inlinable mutating func bitshiftLeft(words: Int, atLeastOneBit bits: Int) { + fatalError("TODO") + } + + /// Performs a left shift. + /// + /// - Parameters: + /// - words: `1 <= words < self.endIndex` + /// + @inlinable mutating func bitshiftLeft(atLeastOneWord words: Int) { + fatalError("TODO") + } +} + +//=----------------------------------------------------------------------------= +// MARK: + Right +//=----------------------------------------------------------------------------= + +extension IntXL { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public static func >>=(lhs: inout Self, rhs: some BinaryInteger) { + lhs.bitshiftRightSmart(by: NBK.initOrBitCast(clamping: rhs, as: Int.self)) + } + + @inlinable public static func >>(lhs: Self, rhs: some BinaryInteger) -> Self { + var lhs = lhs; lhs >>= rhs; return lhs + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Int + //=------------------------------------------------------------------------= + + @inlinable public mutating func bitshiftRightSmart(by distance: Int) { + if distance >= 0 { + self.bitshiftRight(by: distance) + } else { + self.bitshiftLeft(by: Int(clamping: distance.magnitude)) + } + } + + @inlinable public func bitshiftedRightSmart(by distance: Int) -> Self { + var result = self; result.bitshiftRightSmart(by: distance); return result + } + + @inlinable public mutating func bitshiftRight(by distance: Int) { + precondition(distance >= 0, NBK.callsiteOutOfBoundsInfo()) + let major = NBK .quotientDividingByBitWidthAssumingIsAtLeastZero(distance) + let minor = NBK.remainderDividingByBitWidthAssumingIsAtLeastZero(distance) + return self.bitshiftRight(words: major, bits: minor) + } + + @inlinable public func bitshiftedRight(by distance: Int) -> Self { + var result = self; result.bitshiftRight(by: distance); return result + } + + @inlinable public mutating func bitshiftRight(words: Int, bits: Int) { + //=--------------------------------------= + if bits.isZero { + return self.bitshiftRight(words: words) + } + //=--------------------------------------= + self.bitshiftRight(words: words, atLeastOneBit: bits) + } + + @inlinable public func bitshiftedRight(words: Int, bits: Int) -> Self { + var result = self; result.bitshiftRight(words: words, bits: bits); return result + } + + @inlinable public mutating func bitshiftRight(words: Int) { + //=--------------------------------------= + if words.isZero { return } + //=--------------------------------------= + self.bitshiftRight(atLeastOneWord: words) + } + + @inlinable public func bitshiftedRight(words: Int) -> Self { + var result = self; result.bitshiftRight(words: words); return result + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Int x Private + //=------------------------------------------------------------------------= + + /// Performs an signed right shift. + /// + /// - Parameters: + /// - words: `1 <= words < self.endIndex` + /// - bits: `0 <= bits  < UInt.bitWidth` + /// + @inlinable mutating func bitshiftRight(words: Int, atLeastOneBit bits: Int) { + fatalError("TODO") + } + + /// Performs an signed right shift. + /// + /// - Parameters: + /// - words: `1 <= words < self.endIndex` + /// + @inlinable mutating func bitshiftRight(atLeastOneWord words: Int) { + fatalError("TODO") + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Shifts x UIntXL +//*============================================================================* +//=----------------------------------------------------------------------------= +// MARK: + Left +//=----------------------------------------------------------------------------= + +extension UIntXL { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public static func <<=(lhs: inout Self, rhs: some BinaryInteger) { + lhs.bitshiftLeftSmart(by: NBK.initOrBitCast(clamping: rhs, as: Int.self)) + } + + @inlinable public static func <<(lhs: Self, rhs: some BinaryInteger) -> Self { + var lhs = lhs; lhs <<= rhs; return lhs + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Int + //=------------------------------------------------------------------------= + + @inlinable public mutating func bitshiftLeftSmart(by distance: Int) { + if distance >= 0 { + self.bitshiftLeft (by: distance) + } else { + self.bitshiftRight(by: Int(clamping: distance.magnitude)) + } + } + + @inlinable public func bitshiftedLeftSmart(by distance: Int) -> Self { + var result = self; result.bitshiftLeftSmart(by: distance); return result + } + + @inlinable public mutating func bitshiftLeft(by distance: Int) { + precondition(distance >= 0, NBK.callsiteOutOfBoundsInfo()) + let major = NBK .quotientDividingByBitWidthAssumingIsAtLeastZero(distance) + let minor = NBK.remainderDividingByBitWidthAssumingIsAtLeastZero(distance) + return self.bitshiftLeft(words: major, bits: minor) + } + + @inlinable public func bitshiftedLeft(by distance: Int) -> Self { + var result = self; result.bitshiftLeft(by: distance); return result + } + + @inlinable public mutating func bitshiftLeft(words: Int, bits: Int) { + //=--------------------------------------= + if bits.isZero { + return self.bitshiftRight(words: words) + } + //=--------------------------------------= + self.bitshiftLeft(words: words, atLeastOneBit: bits) + } + + @inlinable public func bitshiftedLeft(words: Int, bits: Int) -> Self { + var result = self; result.bitshiftLeft(words: words, bits: bits); return result + } + + @inlinable public mutating func bitshiftLeft(words: Int) { + //=--------------------------------------= + if words.isZero { return } + //=--------------------------------------= + self.bitshiftLeft(atLeastOneWord: words) + } + + @inlinable public func bitshiftedLeft(words: Int) -> Self { + var result = self; result.bitshiftLeft(words: words); return result + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Int x Private + //=------------------------------------------------------------------------= + + /// Performs a left shift. + /// + /// - Parameters: + /// - words: `0 <= words < self.endIndex` + /// - bits: `1 <= bits  < UInt.bitWidth` + /// + @inlinable mutating func bitshiftLeft(words: Int, atLeastOneBit bits: Int) { + fatalError("TODO") + } + + /// Performs a left shift. + /// + /// - Parameters: + /// - words: `1 <= words < self.endIndex` + /// + @inlinable mutating func bitshiftLeft(atLeastOneWord words: Int) { + fatalError("TODO") + } +} + +//=----------------------------------------------------------------------------= +// MARK: + Right +//=----------------------------------------------------------------------------= + +extension UIntXL { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public static func >>=(lhs: inout Self, rhs: some BinaryInteger) { + lhs.bitshiftRightSmart(by: NBK.initOrBitCast(clamping: rhs, as: Int.self)) + } + + @inlinable public static func >>(lhs: Self, rhs: some BinaryInteger) -> Self { + var lhs = lhs; lhs >>= rhs; return lhs + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Int + //=------------------------------------------------------------------------= + + @inlinable public mutating func bitshiftRightSmart(by distance: Int) { + if distance >= 0 { + self.bitshiftRight(by: distance) + } else { + self.bitshiftLeft(by: Int(clamping: distance.magnitude)) + } + } + + @inlinable public func bitshiftedRightSmart(by distance: Int) -> Self { + var result = self; result.bitshiftRightSmart(by: distance); return result + } + + @inlinable public mutating func bitshiftRight(by distance: Int) { + precondition(distance >= 0, NBK.callsiteOutOfBoundsInfo()) + let major = NBK .quotientDividingByBitWidthAssumingIsAtLeastZero(distance) + let minor = NBK.remainderDividingByBitWidthAssumingIsAtLeastZero(distance) + return self.bitshiftRight(words: major, bits: minor) + } + + @inlinable public func bitshiftedRight(by distance: Int) -> Self { + var result = self; result.bitshiftRight(by: distance); return result + } + + @inlinable public mutating func bitshiftRight(words: Int, bits: Int) { + //=--------------------------------------= + if bits.isZero { + return self.bitshiftRight(words: words) + } + //=--------------------------------------= + self.bitshiftRight(words: words, atLeastOneBit: bits) + } + + @inlinable public func bitshiftedRight(words: Int, bits: Int) -> Self { + var result = self; result.bitshiftRight(words: words, bits: bits); return result + } + + @inlinable public mutating func bitshiftRight(words: Int) { + //=--------------------------------------= + if words.isZero { return } + //=--------------------------------------= + self.bitshiftRight(atLeastOneWord: words) + } + + @inlinable public func bitshiftedRight(words: Int) -> Self { + var result = self; result.bitshiftRight(words: words); return result + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Int x Private + //=------------------------------------------------------------------------= + + /// Performs an unsigned right shift. + /// + /// - Parameters: + /// - words: `1 <= words < self.endIndex` + /// - bits: `0 <= bits  < UInt.bitWidth` + /// + @inlinable mutating func bitshiftRight(words: Int, atLeastOneBit bits: Int) { + fatalError("TODO") + } + + /// Performs an unsigned right shift. + /// + /// - Parameters: + /// - words: `1 <= words < self.endIndex` + /// + @inlinable mutating func bitshiftRight(atLeastOneWord words: Int) { + fatalError("TODO") + } +} diff --git a/Sources/NBKTwosComplementKit/IntXL+Storage.swift b/Sources/NBKTwosComplementKit/IntXL+Storage.swift new file mode 100644 index 00000000..2fb0c34a --- /dev/null +++ b/Sources/NBKTwosComplementKit/IntXL+Storage.swift @@ -0,0 +1,100 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x Storage x IntXL +//*============================================================================* + +extension IntXL { + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + @inlinable var isNormal: Bool { + if self.storage.count == 1 { return true } + + let tail = Int(bitPattern: self.storage[self.storage.count - 1]) + let head = Int(bitPattern: self.storage[self.storage.count - 2]) + + let sign = tail >> Int.bitWidth + + return !(sign == tail && sign == head >> Int.bitWidth) + } + + @inlinable mutating func normalize() { + Swift.assert(!self.storage.isEmpty) + //=--------------------------------------= + var position = self.storage.index(before: self.storage.endIndex) + let mostSignificantBit = self.storage[position].mostSignificantBit + let sign = UInt(repeating: mostSignificantBit) + //=--------------------------------------= + // TODO: measure combined loop conditions + //=--------------------------------------= + backwards: while position > self.storage.startIndex { + if self.storage[position] != sign { return } + self.storage.formIndex(before: &position) + if self.storage[position].mostSignificantBit != mostSignificantBit { return } + self.storage.removeLast() + } + } + + @inlinable mutating func normalize(appending word: UInt) { + Swift.assert(!self.storage.isEmpty) + //=--------------------------------------= + var position = self.storage.index(before: self.storage.endIndex) + let mostSignificantBit = self.storage[position].mostSignificantBit + let sign = UInt(repeating: mostSignificantBit) + //=--------------------------------------= + if word != sign { + return self.storage.append(word) + } + //=--------------------------------------= + // TODO: measure combined loop conditions + //=--------------------------------------= + backwards: while position > self.storage.startIndex { + if self.storage[position] != sign { return } + self.storage.formIndex(before: &position) + if self.storage[position].mostSignificantBit != mostSignificantBit { return } + self.storage.removeLast() + } + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Storage x UIntXL +//*============================================================================* + +extension UIntXL { + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + @inlinable var isNormal: Bool { + self.storage.count == 1 || !self.storage.last!.isZero + } + + @inlinable mutating func normalize() { + Swift.assert(!self.storage.isEmpty) + //=--------------------------------------= + var position = self.storage.index(before: self.storage.endIndex) + let sign = UInt(repeating: false) + //=--------------------------------------= + // TODO: measure combined loop conditions + //=--------------------------------------= + backwards: while position > self.storage.startIndex { + if self.storage[position] != sign { return } + self.storage.formIndex(before: &position) + self.storage.removeLast() + } + } +} diff --git a/Sources/NBKTwosComplementKit/IntXL+Subtraction+Digit.swift b/Sources/NBKTwosComplementKit/IntXL+Subtraction+Digit.swift new file mode 100644 index 00000000..85e5db27 --- /dev/null +++ b/Sources/NBKTwosComplementKit/IntXL+Subtraction+Digit.swift @@ -0,0 +1,93 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x Subtraction x Digit x IntXL +//*============================================================================* + +extension IntXL { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @_disfavoredOverload @inlinable public static func -=(lhs: inout Self, rhs: Int) { + lhs.subtract(rhs, at: Int.zero) + } + + @_disfavoredOverload @inlinable public static func -(lhs: Self, rhs: Int) -> Self { + lhs.subtracting(rhs, at: Int.zero) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @_disfavoredOverload @inlinable public mutating func subtract(_ other: Int, at index: Int) { + fatalError("TODO") + } + + @_disfavoredOverload @inlinable public func subtracting(_ other: Int, at index: Int) -> Self { + var result = self; result.subtract(other, at: index); return result + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Subtraction x Digit x UIntXL +//*============================================================================* + +extension UIntXL { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @_disfavoredOverload @inlinable public static func -=(lhs: inout Self, rhs: UInt) { + lhs.subtract(rhs, at: Int.zero) + } + + @_disfavoredOverload @inlinable public static func -(lhs: Self, rhs: UInt) -> Self { + lhs.subtracting(rhs, at: Int.zero) + } + + @_disfavoredOverload @inlinable public mutating func subtractReportingOverflow(_ other: UInt) -> Bool { + self.subtractReportingOverflow(other, at: Int.zero) + } + + @_disfavoredOverload @inlinable public func subtractingReportingOverflow(_ other: UInt) -> PVO { + self.subtractingReportingOverflow(other, at: Int.zero) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @_disfavoredOverload @inlinable public mutating func subtract(_ other: UInt, at index: Int) { + let overflow: Bool = self.subtractReportingOverflow(other, at: index) + precondition(!overflow, NBK.callsiteOverflowInfo()) + } + + @_disfavoredOverload @inlinable public func subtracting(_ other: UInt, at index: Int) -> Self { + let pvo: PVO = self.subtractingReportingOverflow(other, at: index) + precondition(!pvo.overflow, NBK.callsiteOverflowInfo()) + return pvo.partialValue as Self + } + + @_disfavoredOverload @inlinable public mutating func subtractReportingOverflow(_ other: UInt, at index: Int) -> Bool { + fatalError("TODO") + } + + @_disfavoredOverload @inlinable public func subtractingReportingOverflow(_ other: UInt, at index: Int) -> PVO { + var partialValue = self + let overflow: Bool = partialValue.subtractReportingOverflow(other, at: index) + return PVO(partialValue, overflow) + } +} diff --git a/Sources/NBKTwosComplementKit/IntXL+Subtraction.swift b/Sources/NBKTwosComplementKit/IntXL+Subtraction.swift new file mode 100644 index 00000000..90256986 --- /dev/null +++ b/Sources/NBKTwosComplementKit/IntXL+Subtraction.swift @@ -0,0 +1,93 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x Subtraction x IntXL +//*============================================================================* + +extension IntXL { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public static func -=(lhs: inout Self, rhs: Self) { + lhs.subtract(rhs, at: Int.zero) + } + + @inlinable public static func -(lhs: Self, rhs: Self) -> Self { + lhs.subtracting(rhs, at: Int.zero) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public mutating func subtract(_ other: Self, at index: Int) { + fatalError("TODO") + } + + @inlinable public func subtracting(_ other: Self, at index: Int) -> Self { + var result = self; result.subtract(other, at: index); return result + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Subtraction x UIntXL +//*============================================================================* + +extension UIntXL { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public static func -=(lhs: inout Self, rhs: Self) { + lhs.subtract(rhs, at: Int.zero) + } + + @inlinable public static func -(lhs: Self, rhs: Self) -> Self { + lhs.subtracting(rhs, at: Int.zero) + } + + @inlinable public mutating func subtractReportingOverflow(_ other: Self) -> Bool { + self.subtractReportingOverflow(other, at: Int.zero) + } + + @inlinable public func subtractingReportingOverflow(_ other: Self) -> PVO { + self.subtractingReportingOverflow(other, at: Int.zero) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public mutating func subtract(_ other: Self, at index: Int) { + let overflow: Bool = self.subtractReportingOverflow(other, at: index) + precondition(!overflow, NBK.callsiteOverflowInfo()) + } + + @inlinable public func subtracting(_ other: Self, at index: Int) -> Self { + let pvo: PVO = self.subtractingReportingOverflow(other, at: index) + precondition(!pvo.overflow, NBK.callsiteOverflowInfo()) + return pvo.partialValue as Self + } + + @inlinable public mutating func subtractReportingOverflow(_ other: Self, at index: Int) -> Bool { + fatalError("TODO") + } + + @inlinable public func subtractingReportingOverflow(_ other: Self, at index: Int) -> PVO { + var partialValue = self + let overflow: Bool = partialValue.subtractReportingOverflow(other, at: index) + return PVO(partialValue, overflow) + } +} diff --git a/Sources/NBKTwosComplementKit/IntXL+Text.swift b/Sources/NBKTwosComplementKit/IntXL+Text.swift new file mode 100644 index 00000000..b023929c --- /dev/null +++ b/Sources/NBKTwosComplementKit/IntXL+Text.swift @@ -0,0 +1,173 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x Text x IntXL +//*============================================================================* + +extension IntXL { + + //=------------------------------------------------------------------------= + // MARK: Details x Decode + //=------------------------------------------------------------------------= + + @inlinable public init?(_ description: some StringProtocol, radix: Int = 10) { + var description = String(description) + if let value: Self = description.withUTF8({ utf8 in + + let radix = NBK.AnyRadixSolution(radix) + let components = NBK.makeIntegerComponents(utf8: utf8) + let digits = NBK.UnsafeUTF8(rebasing: components.body) + guard let magnitude = Magnitude(digits: digits, radix: radix) else { return nil } + return Self(sign: components.sign, magnitude: magnitude) + + }){ self = value } else { return nil } + } + + //=------------------------------------------------------------------------= + // MARK: Details x Encode + //=------------------------------------------------------------------------= + + @inlinable public func description(radix: Int = 10, uppercase: Bool = false) -> String { + Swift.withUnsafePointer(to: UInt8(ascii: "-")) { minus in + let radix = NBK.AnyRadixSolution(radix) + let alphabet = NBK.MaxRadixAlphabetEncoder(uppercase: uppercase) + let prefix = NBK.UnsafeUTF8(start: minus, count: Int(bit: self.isLessThanZero)) + let suffix = NBK.UnsafeUTF8(start: nil, count: Int.zero) + return self.magnitude.description(radix: radix, alphabet: alphabet, prefix: prefix, suffix: suffix) + } + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Text x UIntXL +//*============================================================================* + +extension UIntXL { + + //=------------------------------------------------------------------------= + // MARK: Details x Decode + //=------------------------------------------------------------------------= + + @inlinable public init?(_ description: some StringProtocol, radix: Int = 10) { + var description = String(description) + if let value: Self = description.withUTF8({ utf8 in + + let radix = NBK.AnyRadixSolution(radix) + let components = NBK.makeIntegerComponents(utf8: utf8) + let digits = NBK.UnsafeUTF8(rebasing: components.body) + guard let magnitude = Magnitude(digits: digits, radix: radix) else { return nil } + return Self(sign: components.sign, magnitude: magnitude) + + }){ self = value } else { return nil } + } + + //=------------------------------------------------------------------------= + // MARK: Details x Encode + //=------------------------------------------------------------------------= + + @inlinable public func description(radix: Int = 10, uppercase: Bool = false) -> String { + Swift.withUnsafePointer(to: UInt8(ascii: "-")) { minus in + let radix = NBK.AnyRadixSolution(radix) + let alphabet = NBK.MaxRadixAlphabetEncoder(uppercase: uppercase) + let prefix = NBK.UnsafeUTF8(start: minus, count: Int(bit: self.isLessThanZero)) + let suffix = NBK.UnsafeUTF8(start: nil, count: Int.zero) + return self.magnitude.description(radix: radix, alphabet: alphabet, prefix: prefix, suffix: suffix) + } + } +} + +//=----------------------------------------------------------------------------= +// MARK: + Algorithms +//=----------------------------------------------------------------------------= + +extension UIntXL { + + //=------------------------------------------------------------------------= + // MARK: Details x Decode x Private + //=------------------------------------------------------------------------= + + @inlinable init?(digits: NBK.UnsafeUTF8, radix: NBK.AnyRadixSolution) { + if radix.power.isZero { + self.init(digits: digits, radix: NBK .PerfectRadixSolution(radix)!) + } else { + self.init(digits: digits, radix: NBK.ImperfectRadixSolution(radix)!) + } + } + + @inlinable init?(digits: NBK.UnsafeUTF8, radix: NBK.PerfectRadixSolution) { + fatalError("TODO") + } + + @inlinable init?(digits: NBK.UnsafeUTF8, radix: NBK.ImperfectRadixSolution) { + fatalError("TODO") + } + + //=------------------------------------------------------------------------= + // MARK: Details x Encode x Private + //=------------------------------------------------------------------------= + // NOTE: Both branches specialize NBKTwinHeaded>. + //=------------------------------------------------------------------------= + + @inlinable func description( + radix: NBK.AnyRadixSolution, alphabet: NBK.MaxRadixAlphabetEncoder, + prefix: NBK.UnsafeUTF8, suffix: NBK.UnsafeUTF8) -> String { + if radix.power.isZero { + return self.description(radix: NBK .PerfectRadixSolution(radix)!, alphabet: alphabet, prefix: prefix, suffix: suffix) + } else { + return self.description(radix: NBK.ImperfectRadixSolution(radix)!, alphabet: alphabet, prefix: prefix, suffix: suffix) + } + } + + @inlinable func description( + radix: NBK.PerfectRadixSolution, alphabet: NBK.MaxRadixAlphabetEncoder, + prefix: NBK.UnsafeUTF8, suffix: NBK.UnsafeUTF8) -> String { + //=--------------------------------------= + // with one buffer pointer specialization + //=--------------------------------------= + self.storage.withUnsafeBufferPointer { words in + let chunks = NBKTwinHeaded(words) + let radix = NBK.AnyRadixSolution(radix) + return NBK.integerTextUnchecked(chunks: chunks, radix: radix, alphabet: alphabet, prefix: prefix, suffix: suffix) + } + } + + @inlinable func description( + radix: NBK.ImperfectRadixSolution, alphabet: NBK.MaxRadixAlphabetEncoder, + prefix: NBK.UnsafeUTF8, suffix: NBK.UnsafeUTF8) -> String { + //=--------------------------------------= + // with one buffer pointer specialization + //=--------------------------------------= + let capacity: Int = radix.divisibilityByPowerUpperBound(self) + return Swift.withUnsafeTemporaryAllocation(of: UInt.self, capacity: capacity) { buffer in + //=----------------------------------= + var magnitude: Magnitude = self + let start = buffer.baseAddress! + var position = start as UnsafeMutablePointer + //=----------------------------------= + // pointee: initialization + //=----------------------------------= + rebasing: repeat { + position.initialize(to: magnitude.formQuotientWithRemainderReportingOverflow(dividingBy: radix.power).partialValue) + position = position.successor() + } while !magnitude.isZero + //=----------------------------------= + // pointee: deferred deinitialization + //=----------------------------------= + let count = start.distance(to: position) + defer { start.deinitialize(count: count) } + //=----------------------------------= + let radix = NBK.AnyRadixSolution(radix) + let chunks = NBKTwinHeaded(UnsafeBufferPointer( start: start, count: count)) + return NBK.integerTextUnchecked(chunks: chunks, radix: radix, alphabet: alphabet, prefix: prefix, suffix: suffix) + } + } +} diff --git a/Sources/NBKTwosComplementKit/IntXL+Words.swift b/Sources/NBKTwosComplementKit/IntXL+Words.swift new file mode 100644 index 00000000..7ec22012 --- /dev/null +++ b/Sources/NBKTwosComplementKit/IntXL+Words.swift @@ -0,0 +1,70 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +//*============================================================================* +// MARK: * NBK x Flexible Width x Words x IntXL +//*============================================================================* + +extension IntXL { + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + @inlinable public init(words: some Sequence) { + self.init(Storage(words)) + } + + //=------------------------------------------------------------------------= + // MARK: Accessors + //=------------------------------------------------------------------------= + + @inlinable public var words: ContiguousArray { + self.storage + } + + @inlinable public subscript(index: Int) -> UInt { + if index < self.storage.endIndex { + return self.storage[index] + } else { + return UInt(bitPattern: Int(bitPattern: self.storage.last!) >> Int.bitWidth) + } + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Words x UIntXL +//*============================================================================* + +extension UIntXL { + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + @inlinable public init(words: some Sequence) { + self.init(Storage(words)) + } + + //=------------------------------------------------------------------------= + // MARK: Accessors + //=------------------------------------------------------------------------= + + @inlinable public var words: ContiguousArray { + self.storage + } + + @inlinable public subscript(index: Int) -> UInt { + if index < self.storage.endIndex { + return self.storage[index] + } else { + return 0000000000000000000 + } + } +} diff --git a/Sources/NBKTwosComplementKit/IntXL.swift b/Sources/NBKTwosComplementKit/IntXL.swift new file mode 100644 index 00000000..5bcd09be --- /dev/null +++ b/Sources/NBKTwosComplementKit/IntXL.swift @@ -0,0 +1,126 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x IntXL +//*============================================================================* + +/// A signed, flexible-width, binary integer. +@frozen public struct IntXL: IntXLOrUIntXL, NBKSignedInteger { + + public typealias Digit = Int + + @usableFromInline typealias Storage = ContiguousArray + + //=------------------------------------------------------------------------= + // MARK: State + //=------------------------------------------------------------------------= + + /// The integer's underlying storage. + /// + /// It must be normal and nonempty the start and end of each integer access. + /// + @usableFromInline var storage: Storage + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + @inlinable init(_ storage: Storage) { + self.storage = storage + precondition(!self.storage.isEmpty) + self.normalize() + } + + @inlinable init(unchecked storage: Storage) { + self.storage = storage + } + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + /// A `description` of this type. + /// + /// ``` + /// ┌─────────────────────────── → ────────────┐ + /// │ type │ description │ + /// ├─────────────────────────── → ────────────┤ + /// │ NBKFlexibleWidth │ "IntXL" │ + /// │ NBKFlexibleWidth.Magnitude │ "UIntXL" │ + /// └─────────────────────────── → ────────────┘ + /// ``` + /// + @inlinable public static var description: String { + "IntXL" + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x UIntXL +//*============================================================================* + +/// An unsigned, flexible-width, binary integer. +@frozen public struct UIntXL: IntXLOrUIntXL, NBKUnsignedInteger { + + public typealias Digit = UInt + + @usableFromInline typealias Storage = ContiguousArray + + //=------------------------------------------------------------------------= + // MARK: State + //=------------------------------------------------------------------------= + + /// The integer's underlying storage. + /// + /// It must be normal and nonempty the start and end of each integer access. + /// + @usableFromInline var storage: Storage + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + @inlinable init(_ storage: Storage) { + self.storage = storage + precondition(!self.storage.isEmpty) + self.normalize() + } + + @inlinable init(unchecked storage: Storage) { + self.storage = storage + } + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + /// A `description` of this type. + /// + /// ``` + /// ┌─────────────────────────── → ────────────┐ + /// │ type │ description │ + /// ├─────────────────────────── → ────────────┤ + /// │ NBKFlexibleWidth │ "IntXL" │ + /// │ NBKFlexibleWidth.Magnitude │ "UIntXL" │ + /// └─────────────────────────── → ────────────┘ + /// ``` + /// + @inlinable public static var description: String { + "UIntXL" + } +} + +//*============================================================================* +// MARK: * NBK x IntXL or UIntXL +//*============================================================================* + +public protocol IntXLOrUIntXL: NBKBinaryInteger, ExpressibleByStringLiteral where Magnitude == UIntXL { } diff --git a/Tests/NBKTwosComplementKitBenchmarks/Blank.swift b/Tests/NBKTwosComplementKitBenchmarks/Blank.swift new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/Tests/NBKTwosComplementKitBenchmarks/Blank.swift @@ -0,0 +1 @@ + diff --git a/Tests/NBKTwosComplementKitTests/IntXL+Words.swift b/Tests/NBKTwosComplementKitTests/IntXL+Words.swift new file mode 100644 index 00000000..587010a6 --- /dev/null +++ b/Tests/NBKTwosComplementKitTests/IntXL+Words.swift @@ -0,0 +1,167 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +import NBKTwosComplementKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Flexible Width x Words x IntXL +//*============================================================================* + +final class NBKFlexibleWidthTestsOnWordsAsIntXL: XCTestCase { + + typealias T = IntXL + typealias M = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testWords() { + NBKAssertWords(T(words:[0 ]), [0 ]) + NBKAssertWords(T(words:[1 ]), [1 ]) + NBKAssertWords(T(words:[1, 2 ]), [1, 2 ]) + NBKAssertWords(T(words:[1, 2, 3 ]), [1, 2, 3 ]) + NBKAssertWords(T(words:[1, 2, 3, 4]), [1, 2, 3, 4]) + + NBKAssertWords(T(words:[0, 0, 0, 0]), [0 ]) + NBKAssertWords(T(words:[1, 0, 0, 0]), [1 ]) + NBKAssertWords(T(words:[1, 2, 0, 0]), [1, 2 ]) + NBKAssertWords(T(words:[1, 2, 3, 0]), [1, 2, 3 ]) + NBKAssertWords(T(words:[1, 2, 3, 4]), [1, 2, 3, 4]) + } + + func testWordsX64() throws { + guard MemoryLayout.size == MemoryLayout.size else { throw XCTSkip() } + + NBKAssertWords(T(x64:[0 ] as X), [0 ]) + NBKAssertWords(T(x64:[1 ] as X), [1 ]) + NBKAssertWords(T(x64:[1, 2 ] as X), [1, 2 ]) + NBKAssertWords(T(x64:[1, 2, 3 ] as X), [1, 2, 3 ]) + NBKAssertWords(T(x64:[1, 2, 3, 4] as X), [1, 2, 3, 4]) + + NBKAssertWords(T(x64:[0, 0, 0, 0] as X), [0 ]) + NBKAssertWords(T(x64:[1, 0, 0, 0] as X), [1 ]) + NBKAssertWords(T(x64:[1, 2, 0, 0] as X), [1, 2 ]) + NBKAssertWords(T(x64:[1, 2, 3, 0] as X), [1, 2, 3 ]) + NBKAssertWords(T(x64:[1, 2, 3, 4] as X), [1, 2, 3, 4]) + } + + func testWordsX32() throws { + guard MemoryLayout.size == MemoryLayout.size else { throw XCTSkip() } + + NBKAssertWords(T(x32:[0 ] as Y), [0 ]) + NBKAssertWords(T(x32:[1 ] as Y), [1 ]) + NBKAssertWords(T(x32:[1, 2 ] as Y), [1, 2 ]) + NBKAssertWords(T(x32:[1, 2, 3 ] as Y), [1, 2, 3 ]) + NBKAssertWords(T(x32:[1, 2, 3, 4 ] as Y), [1, 2, 3, 4 ]) + NBKAssertWords(T(x32:[1, 2, 3, 4, 5 ] as Y), [1, 2, 3, 4, 5 ]) + NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6 ] as Y), [1, 2, 3, 4, 5, 6 ]) + NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6, 7 ] as Y), [1, 2, 3, 4, 5, 6, 7 ]) + NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6, 7, 8] as Y), [1, 2, 3, 4, 5, 6, 7, 8]) + + NBKAssertWords(T(x32:[0, 0, 0, 0, 0, 0, 0, 0] as Y), [0 ]) + NBKAssertWords(T(x32:[1, 0, 0, 0, 0, 0, 0, 0] as Y), [1 ]) + NBKAssertWords(T(x32:[1, 2, 0, 0, 0, 0, 0, 0] as Y), [1, 2 ]) + NBKAssertWords(T(x32:[1, 2, 3, 0, 0, 0, 0, 0] as Y), [1, 2, 3 ]) + NBKAssertWords(T(x32:[1, 2, 3, 4, 0, 0, 0, 0] as Y), [1, 2, 3, 4 ]) + NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 0, 0, 0] as Y), [1, 2, 3, 4, 5 ]) + NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6, 0, 0] as Y), [1, 2, 3, 4, 5, 6 ]) + NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6, 7, 0] as Y), [1, 2, 3, 4, 5, 6, 7 ]) + NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6, 7, 8] as Y), [1, 2, 3, 4, 5, 6, 7, 8]) + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Words x UIntXL +//*============================================================================* + +final class NBKFlexibleWidthTestsOnWordsAsUIntXL: XCTestCase { + + typealias T = UIntXL + typealias M = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testWords() { + NBKAssertWords(T(words:[0 ]), [0 ]) + NBKAssertWords(T(words:[1 ]), [1 ]) + NBKAssertWords(T(words:[1, 2 ]), [1, 2 ]) + NBKAssertWords(T(words:[1, 2, 3 ]), [1, 2, 3 ]) + NBKAssertWords(T(words:[1, 2, 3, 4]), [1, 2, 3, 4]) + + NBKAssertWords(T(words:[0, 0, 0, 0]), [0 ]) + NBKAssertWords(T(words:[1, 0, 0, 0]), [1 ]) + NBKAssertWords(T(words:[1, 2, 0, 0]), [1, 2 ]) + NBKAssertWords(T(words:[1, 2, 3, 0]), [1, 2, 3 ]) + NBKAssertWords(T(words:[1, 2, 3, 4]), [1, 2, 3, 4]) + } + + func testWordsX64() throws { + guard MemoryLayout.size == MemoryLayout.size else { throw XCTSkip() } + + NBKAssertWords(T(x64:[0 ] as X), [0 ]) + NBKAssertWords(T(x64:[1 ] as X), [1 ]) + NBKAssertWords(T(x64:[1, 2 ] as X), [1, 2 ]) + NBKAssertWords(T(x64:[1, 2, 3 ] as X), [1, 2, 3 ]) + NBKAssertWords(T(x64:[1, 2, 3, 4] as X), [1, 2, 3, 4]) + + NBKAssertWords(T(x64:[0, 0, 0, 0] as X), [0 ]) + NBKAssertWords(T(x64:[1, 0, 0, 0] as X), [1 ]) + NBKAssertWords(T(x64:[1, 2, 0, 0] as X), [1, 2 ]) + NBKAssertWords(T(x64:[1, 2, 3, 0] as X), [1, 2, 3 ]) + NBKAssertWords(T(x64:[1, 2, 3, 4] as X), [1, 2, 3, 4]) + } + + func testWordsX32() throws { + guard MemoryLayout.size == MemoryLayout.size else { throw XCTSkip() } + + NBKAssertWords(T(x32:[0 ] as Y), [0 ]) + NBKAssertWords(T(x32:[1 ] as Y), [1 ]) + NBKAssertWords(T(x32:[1, 2 ] as Y), [1, 2 ]) + NBKAssertWords(T(x32:[1, 2, 3 ] as Y), [1, 2, 3 ]) + NBKAssertWords(T(x32:[1, 2, 3, 4 ] as Y), [1, 2, 3, 4 ]) + NBKAssertWords(T(x32:[1, 2, 3, 4, 5 ] as Y), [1, 2, 3, 4, 5 ]) + NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6 ] as Y), [1, 2, 3, 4, 5, 6 ]) + NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6, 7 ] as Y), [1, 2, 3, 4, 5, 6, 7 ]) + NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6, 7, 8] as Y), [1, 2, 3, 4, 5, 6, 7, 8]) + + NBKAssertWords(T(x32:[0, 0, 0, 0, 0, 0, 0, 0] as Y), [0 ]) + NBKAssertWords(T(x32:[1, 0, 0, 0, 0, 0, 0, 0] as Y), [1 ]) + NBKAssertWords(T(x32:[1, 2, 0, 0, 0, 0, 0, 0] as Y), [1, 2 ]) + NBKAssertWords(T(x32:[1, 2, 3, 0, 0, 0, 0, 0] as Y), [1, 2, 3 ]) + NBKAssertWords(T(x32:[1, 2, 3, 4, 0, 0, 0, 0] as Y), [1, 2, 3, 4 ]) + NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 0, 0, 0] as Y), [1, 2, 3, 4, 5 ]) + NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6, 0, 0] as Y), [1, 2, 3, 4, 5, 6 ]) + NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6, 7, 0] as Y), [1, 2, 3, 4, 5, 6, 7 ]) + NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6, 7, 8] as Y), [1, 2, 3, 4, 5, 6, 7, 8]) + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Words x Assertions +//*============================================================================* + +private func NBKAssertWords( +_ integer: T, _ words: [UInt], +file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual(Array(integer.words), Array(words), file: file, line: line) + XCTAssertEqual(Array(integer.words.reversed()), Array(words.reversed()), file: file, line: line) +} + +#endif diff --git a/Tests/NBKTwosComplementKitTests/IntXL.swift b/Tests/NBKTwosComplementKitTests/IntXL.swift new file mode 100644 index 00000000..c1cb189f --- /dev/null +++ b/Tests/NBKTwosComplementKitTests/IntXL.swift @@ -0,0 +1,68 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit +import NBKTwosComplementKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Flexible Width x IntXL +//*============================================================================* + +extension IntXL { + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + static let min256 = Self(x64:[ 0, 0, 0, ~0/2 + 1] as X) + static let max256 = Self(x64:[~0, ~0, ~0, ~0/2 + 0] as X) + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + init(x32: [UInt32]) { + self.init(words: NBKChunkedInt(x32)) + } + + init(x64: [UInt64]) { + self.init(words: NBKChunkedInt(x64)) + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x UIntXL +//*============================================================================* + +extension UIntXL { + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + static let min256 = Self(x64:[ 0, 0, 0, 0] as X) + static let max256 = Self(x64:[~0, ~0, ~0, ~0] as X) + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + init(x32: [UInt32]) { + self.init(words: NBKChunkedInt(x32)) + } + + init(x64: [UInt64]) { + self.init(words: NBKChunkedInt(x64)) + } +} From 8abe19ca1a871b7197a4801717be1ab1299112c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Wed, 13 Sep 2023 08:45:50 +0200 Subject: [PATCH 064/133] [2's rework] Day 2 (#44). --- .../NBKFlexibleWidth+Words.swift | 2 +- .../NBKFlexibleWidth.swift | 2 +- .../IntXL+Addition+Digit.swift | 27 +- .../NBKTwosComplementKit/IntXL+Addition.swift | 23 +- Sources/NBKTwosComplementKit/IntXL+Bits.swift | 66 +- .../IntXL+Comparisons.swift | 67 +- .../IntXL+Complements.swift | 109 +- .../IntXL+Division+Digit.swift | 40 +- .../NBKTwosComplementKit/IntXL+Division.swift | 37 +- .../NBKTwosComplementKit/IntXL+Logic.swift | 100 +- .../IntXL+Multiplication+Digit.swift | 45 +- .../NBKTwosComplementKit/IntXL+Numbers.swift | 71 +- .../NBKTwosComplementKit/IntXL+Shifts.swift | 230 +-- .../NBKTwosComplementKit/IntXL+Storage.swift | 121 +- .../IntXL+Subtraction+Digit.swift | 47 +- .../IntXL+Subtraction.swift | 41 +- Sources/NBKTwosComplementKit/IntXL+Text.swift | 79 +- .../NBKTwosComplementKit/IntXL+Update.swift | 29 + .../IntXL+Words+Pointers.swift | 34 + .../NBKTwosComplementKit/IntXL+Words.swift | 45 +- Sources/NBKTwosComplementKit/IntXL.swift | 250 ++- .../IntXL+Bits.swift | 212 +++ .../IntXL+Logic.swift | 170 ++ .../IntXL+Shifts.swift | 324 ++++ .../IntXL+Text.swift | 1435 +++++++++++++++++ .../IntXL+Words.swift | 8 + 26 files changed, 2995 insertions(+), 619 deletions(-) create mode 100644 Sources/NBKTwosComplementKit/IntXL+Update.swift create mode 100644 Sources/NBKTwosComplementKit/IntXL+Words+Pointers.swift create mode 100644 Tests/NBKTwosComplementKitTests/IntXL+Bits.swift create mode 100644 Tests/NBKTwosComplementKitTests/IntXL+Logic.swift create mode 100644 Tests/NBKTwosComplementKitTests/IntXL+Shifts.swift create mode 100644 Tests/NBKTwosComplementKitTests/IntXL+Text.swift diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift index be0a597f..f4efc167 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift @@ -56,7 +56,7 @@ extension NBKFlexibleWidth { } } - #warning("IntXL and UIntXL can share Words") + // #warning("IntXL and UIntXL can share Words") //*========================================================================* // MARK: * Words //*========================================================================* diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift index d00d2f37..f21bf562 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift @@ -112,7 +112,7 @@ import NBKCoreKit "UIntXL" } - #warning("TODO: check uses of elements, first!, last!, count, lastIndex") + // #warning("check uses of elements, first!, last!, count, lastIndex") //*====================================================================* // MARK: * Storage //*====================================================================* diff --git a/Sources/NBKTwosComplementKit/IntXL+Addition+Digit.swift b/Sources/NBKTwosComplementKit/IntXL+Addition+Digit.swift index 7aa737f2..fd800ad4 100644 --- a/Sources/NBKTwosComplementKit/IntXL+Addition+Digit.swift +++ b/Sources/NBKTwosComplementKit/IntXL+Addition+Digit.swift @@ -10,22 +10,29 @@ import NBKCoreKit //*============================================================================* -// MARK: * NBK x Flexible Width x Addition x Digit x IntXL +// MARK: * NBK x Flexible Width x Addition x Digit //*============================================================================* -extension IntXL { +extension IntXLOrUIntXL { //=------------------------------------------------------------------------= // MARK: Transformations //=------------------------------------------------------------------------= - @_disfavoredOverload @inlinable public static func +=(lhs: inout Self, rhs: Int) { + @_disfavoredOverload @inlinable public static func +=(lhs: inout Self, rhs: Digit) { lhs.add(rhs, at: Int.zero) } - @_disfavoredOverload @inlinable public static func +(lhs: Self, rhs: Int) -> Self { + @_disfavoredOverload @inlinable public static func +(lhs: Self, rhs: Digit) -> Self { lhs.adding(rhs, at: Int.zero) } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Addition x Digit x IntXL +//*============================================================================* + +extension IntXL { //=------------------------------------------------------------------------= // MARK: Transformations @@ -52,18 +59,6 @@ extension UIntXL { // MARK: Transformations //=------------------------------------------------------------------------= - @_disfavoredOverload @inlinable public static func +=(lhs: inout Self, rhs: UInt) { - lhs.add(rhs, at: Int.zero) - } - - @_disfavoredOverload @inlinable public static func +(lhs: Self, rhs: UInt) -> Self { - lhs.adding(rhs, at: Int.zero) - } - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - @_disfavoredOverload @inlinable public mutating func add(_ other: UInt, at index: Int) { fatalError("TODO") } diff --git a/Sources/NBKTwosComplementKit/IntXL+Addition.swift b/Sources/NBKTwosComplementKit/IntXL+Addition.swift index 15366da3..064d9dbe 100644 --- a/Sources/NBKTwosComplementKit/IntXL+Addition.swift +++ b/Sources/NBKTwosComplementKit/IntXL+Addition.swift @@ -10,10 +10,10 @@ import NBKCoreKit //*============================================================================* -// MARK: * NBK x Flexible Width x Addition x IntXL +// MARK: * NBK x Flexible Width x Addition //*============================================================================* -extension IntXL { +extension IntXLOrUIntXL { //=------------------------------------------------------------------------= // MARK: Transformations @@ -26,6 +26,13 @@ extension IntXL { @inlinable public static func +(lhs: Self, rhs: Self) -> Self { lhs.adding(rhs, at: Int.zero) } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Addition x IntXL +//*============================================================================* + +extension IntXL { //=------------------------------------------------------------------------= // MARK: Transformations @@ -52,18 +59,6 @@ extension UIntXL { // MARK: Transformations //=------------------------------------------------------------------------= - @inlinable public static func +=(lhs: inout Self, rhs: Self) { - lhs.add(rhs, at: Int.zero) - } - - @inlinable public static func +(lhs: Self, rhs: Self) -> Self { - lhs.adding(rhs, at: Int.zero) - } - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - @inlinable public mutating func add(_ other: Self, at index: Int) { fatalError("TODO") } diff --git a/Sources/NBKTwosComplementKit/IntXL+Bits.swift b/Sources/NBKTwosComplementKit/IntXL+Bits.swift index 0543caf7..25a706aa 100644 --- a/Sources/NBKTwosComplementKit/IntXL+Bits.swift +++ b/Sources/NBKTwosComplementKit/IntXL+Bits.swift @@ -10,10 +10,10 @@ import NBKCoreKit //*============================================================================* -// MARK: * NBK x Flexible Width x Bits x IntXL +// MARK: * NBK x Flexible Width x Bits //*============================================================================* -extension IntXL { +extension PrivateIntXLOrUIntXL { //=------------------------------------------------------------------------= // MARK: Initializers @@ -24,73 +24,43 @@ extension IntXL { } //=------------------------------------------------------------------------= - // MARK: Accessors + // MARK: Utilities //=------------------------------------------------------------------------= @inlinable public var bitWidth: Int { - fatalError("TODO") + self.storage.elements.count * UInt.bitWidth } - + @inlinable public var nonzeroBitCount: Int { - fatalError("TODO") + self.withUnsafeBufferPointer(NBK.nonzeroBitCount(of:)) } @inlinable public var leadingZeroBitCount: Int { - fatalError("TODO") + self.storage.last.leadingZeroBitCount } @inlinable public var trailingZeroBitCount: Int { - fatalError("TODO") + self.withUnsafeBufferPointer(NBK.trailingZeroBitCount(of:)) } @inlinable public var mostSignificantBit: Bool { - fatalError("TODO") + self.storage.last.mostSignificantBit } @inlinable public var leastSignificantBit: Bool { - fatalError("TODO") - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Bits x UIntXL -//*============================================================================* - -extension UIntXL { - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - @inlinable public init(bit: Bool) { - self.init(digit: Digit(bit: bit)) + self.storage.first.leastSignificantBit } //=------------------------------------------------------------------------= - // MARK: Accessors + // MARK: Utilities x Private //=------------------------------------------------------------------------= - @inlinable public var bitWidth: Int { - fatalError("TODO") - } - - @inlinable public var nonzeroBitCount: Int { - fatalError("TODO") - } - - @inlinable public var leadingZeroBitCount: Int { - fatalError("TODO") - } - - @inlinable public var trailingZeroBitCount: Int { - fatalError("TODO") - } - - @inlinable public var mostSignificantBit: Bool { - fatalError("TODO") - } - - @inlinable public var leastSignificantBit: Bool { - fatalError("TODO") + @inlinable func leadingBitCount(_ bit: Bool) -> Int { + var last = self.storage.last + if bit { + last.formOnesComplement() + } + + return last.leadingZeroBitCount } } diff --git a/Sources/NBKTwosComplementKit/IntXL+Comparisons.swift b/Sources/NBKTwosComplementKit/IntXL+Comparisons.swift index 8885e076..be9f8278 100644 --- a/Sources/NBKTwosComplementKit/IntXL+Comparisons.swift +++ b/Sources/NBKTwosComplementKit/IntXL+Comparisons.swift @@ -20,23 +20,23 @@ extension IntXL { //=------------------------------------------------------------------------= @inlinable public var isZero: Bool { - fatalError("TODO") + self.storage.elements.count == 1 && self.storage.first.isZero } @inlinable public var isLessThanZero: Bool { - fatalError("TODO") + self.storage.last.mostSignificantBit } @inlinable public var isMoreThanZero: Bool { - fatalError("TODO") + !self.isLessThanZero && !self.isZero } @inlinable public var isPowerOf2: Bool { - fatalError("TODO") + !self.isLessThanZero && self.withUnsafeBufferPointer({ NBK.nonzeroBitCount(of: $0, equals: 1) }) } @inlinable public func signum() -> Int { - fatalError("TODO") + self.isLessThanZero ? -1 : self.isZero ? 0 : 1 } //=------------------------------------------------------------------------= @@ -44,7 +44,7 @@ extension IntXL { //=------------------------------------------------------------------------= @inlinable public func hash(into hasher: inout Hasher) { - hasher.combine(self.storage) + hasher.combine(self.storage.elements) } //=------------------------------------------------------------------------= @@ -60,24 +60,36 @@ extension IntXL { } @inlinable public func compared(to other: Self) -> Int { - fatalError("TODO") + self .withUnsafeBufferPointer { lhs in + other.withUnsafeBufferPointer { rhs in + NBK.compareStrictSignedInteger(lhs, to: rhs) + }} } @inlinable public func compared(to other: Self, at index: Int) -> Int { - fatalError("TODO") + self .withUnsafeBufferPointer { lhs in + other.withUnsafeBufferPointer { rhs in + NBK.compareStrictSignedInteger(lhs, to: rhs, at: index) + }} } @_disfavoredOverload @inlinable public func compared(to other: Digit) -> Int { - fatalError("TODO") + self.withUnsafeBufferPointer { lhs in + NBK .withUnsafeWords(of: other) { rhs in + NBK.compareStrictSignedInteger(lhs, to: rhs) + }} } @_disfavoredOverload @inlinable public func compared(to other: Digit, at index: Int) -> Int { - fatalError("TODO") + self.withUnsafeBufferPointer { lhs in + NBK .withUnsafeWords(of: other) { rhs in + NBK.compareStrictSignedInteger(lhs, to: rhs, at: index) + }} } } //*============================================================================* -// MARK: * NBK x Flexible Width x Comparisons x Unsigned +// MARK: * NBK x Flexible Width x Comparisons x UIntXL //*============================================================================* extension UIntXL { @@ -87,7 +99,7 @@ extension UIntXL { //=------------------------------------------------------------------------= @inlinable public var isZero: Bool { - self.storage.count == 1 && self.storage.first!.isZero + self.storage.elements.count == 1 && self.storage.first.isZero } @inlinable public var isLessThanZero: Bool { @@ -99,7 +111,7 @@ extension UIntXL { } @inlinable public var isPowerOf2: Bool { - self.storage.withUnsafeBufferPointer({ NBK.nonzeroBitCount(of: $0, equals: 1) }) + self.withUnsafeBufferPointer({ NBK.nonzeroBitCount(of: $0, equals: 1) }) } @inlinable public func signum() -> Int { @@ -111,7 +123,7 @@ extension UIntXL { //=------------------------------------------------------------------------= @inlinable public func hash(into hasher: inout Hasher) { - hasher.combine(self.storage) + hasher.combine(self.storage.elements) } //=------------------------------------------------------------------------= @@ -127,30 +139,45 @@ extension UIntXL { } @inlinable public func compared(to other: Self) -> Int { - self .storage.withUnsafeBufferPointer { lhs in - other.storage.withUnsafeBufferPointer { rhs in + self .withUnsafeBufferPointer { lhs in + other.withUnsafeBufferPointer { rhs in NBK.compareLenientUnsignedInteger(lhs, to: rhs) }} } @inlinable public func compared(to other: Self, at index: Int) -> Int { - self .storage.withUnsafeBufferPointer { lhs in - other.storage.withUnsafeBufferPointer { rhs in + self .withUnsafeBufferPointer { lhs in + other.withUnsafeBufferPointer { rhs in NBK.compareLenientUnsignedInteger(lhs, to: rhs, at: index) }} } @_disfavoredOverload @inlinable public func compared(to other: Digit) -> Int { - self.storage.withUnsafeBufferPointer { lhs in + self.withUnsafeBufferPointer { lhs in NBK .withUnsafeWords(of: other) { rhs in NBK.compareLenientUnsignedInteger(lhs, to: rhs) }} } @_disfavoredOverload @inlinable public func compared(to other: Digit, at index: Int) -> Int { - self.storage.withUnsafeBufferPointer { lhs in + self.withUnsafeBufferPointer { lhs in NBK .withUnsafeWords(of: other) { rhs in NBK.compareLenientUnsignedInteger(lhs, to: rhs, at: index) }} } } + +//*============================================================================* +// MARK: * NBK x Flexible Width x Comparisons x Storage +//*============================================================================* + +extension StorageXL { + + //=------------------------------------------------------------------------= + // MARK: Accessors + //=------------------------------------------------------------------------= + + @inlinable func isLessThanZero(isSigned: Bool) -> Bool { + isSigned && self.last.mostSignificantBit + } +} diff --git a/Sources/NBKTwosComplementKit/IntXL+Complements.swift b/Sources/NBKTwosComplementKit/IntXL+Complements.swift index 53c4fa5a..c0c676b9 100644 --- a/Sources/NBKTwosComplementKit/IntXL+Complements.swift +++ b/Sources/NBKTwosComplementKit/IntXL+Complements.swift @@ -10,39 +10,42 @@ import NBKCoreKit //*============================================================================* -// MARK: * NBK x Flexible Width x Complements x IntXL +// MARK: * NBK x Flexible Width x Complements //*============================================================================* -extension IntXL { +extension PrivateIntXLOrUIntXL { //=------------------------------------------------------------------------= - // MARK: Details x Magnitude + // MARK: Details x One's Complement //=------------------------------------------------------------------------= - @inlinable public var magnitude: UIntXL { - fatalError("TODO") + @inlinable public mutating func formOnesComplement() { + self.storage.formOnesComplement() + Self.normalize(&self.storage) + } + + @inlinable public func onesComplement() -> Self { + Self(normalizing: self.storage.onesComplement()) } //=------------------------------------------------------------------------= // MARK: Details x Two's Complement //=------------------------------------------------------------------------= - @inlinable public mutating func formOnesComplement() { - fatalError("TODO") + @inlinable public mutating func formTwosComplement() { + defer{ Self.normalize(&self.storage) } + return self.storage.formTwosComplement() } - @inlinable public func onesComplement() -> Self { + @inlinable public func twosComplement() -> Self { var result = self - result.formOnesComplement() + result.formTwosComplement() return result as Self } - //=------------------------------------------------------------------------= - // MARK: Details x Two's Complement - //=------------------------------------------------------------------------= - @inlinable public mutating func formTwosComplementReportingOverflow() -> Bool { - fatalError("TODO") + defer{ Self.normalize(&self.storage) } + return self.storage.formTwosComplementReportingOverflow(as: Digit.self) } @inlinable public func twosComplementReportingOverflow() -> PVO { @@ -52,9 +55,8 @@ extension IntXL { } @inlinable public mutating func formTwosComplementSubsequence(_ carry: Bool) -> Bool { - switch carry { - case true : return self.formTwosComplementReportingOverflow() - case false: self.formOnesComplement(); return false } + defer{ Self.normalize(&self.storage) } + return self.storage.formTwosComplementSubsequence(carry, as: Digit.self) } @inlinable public func twosComplementSubsequence(_ carry: Bool) -> PVO { @@ -62,61 +64,82 @@ extension IntXL { let overflow = partialValue.formTwosComplementSubsequence(carry) return PVO(partialValue, overflow) } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Complements x IntXL +//*============================================================================* + +extension IntXL { + + //=------------------------------------------------------------------------= + // MARK: Details x Magnitude + //=------------------------------------------------------------------------= + + @inlinable public var magnitude: Magnitude { + let isLessThanZero = self.isLessThanZero + var storage = self.storage + if isLessThanZero { + storage.formTwosComplement() + } + + Magnitude.normalize(&storage) + return Magnitude(unchecked: storage) + } //=------------------------------------------------------------------------= // MARK: Details x Additive Inverse //=------------------------------------------------------------------------= @inlinable public mutating func negateReportingOverflow() -> Bool { - fatalError("TODO") + self.formTwosComplement(); return false } - + @inlinable public func negatedReportingOverflow() -> PVO { - var partialValue = self - let overflow = partialValue.negateReportingOverflow() - return PVO(partialValue, overflow) + PVO(self.twosComplement(), false) } } //*============================================================================* -// MARK: * NBK x Flexible Width x Complements x UIntXL +// MARK: * NBK x Flexible Width x Complements x Storage //*============================================================================* -extension UIntXL { +extension StorageXL { //=------------------------------------------------------------------------= // MARK: Details x One's Complement //=------------------------------------------------------------------------= - @inlinable public mutating func formOnesComplement() { - fatalError("TODO") + @inlinable mutating func formOnesComplement() { + for index in self.elements.indices { + self.elements[index].formOnesComplement() + } } - - @inlinable public func onesComplement() -> Self { - fatalError("TODO") + + @inlinable func onesComplement() -> Self { + Self(unchecked: Elements(self.elements.lazy.map(~))) } //=------------------------------------------------------------------------= // MARK: Details x Two's Complement //=------------------------------------------------------------------------= - @inlinable public mutating func formTwosComplementReportingOverflow() -> Bool { - fatalError("TODO") + @inlinable mutating func formTwosComplement() { + _ = self.formTwosComplementSubsequence(true, as: UInt.self) } - @inlinable public func twosComplementReportingOverflow() -> PVO { - var partialValue = self - let overflow = partialValue.formTwosComplementReportingOverflow() - return PVO(partialValue, overflow) + @inlinable mutating func formTwosComplementReportingOverflow(as digit: T.Type) -> Bool where T: NBKCoreInteger { + self.formTwosComplementSubsequence(true, as: T.self) } - @inlinable public mutating func formTwosComplementSubsequence(_ carry: Bool) -> Bool { - fatalError("TODO") - } - - @inlinable public func twosComplementSubsequence(_ carry: Bool) -> PVO { - var partialValue = self - let overflow = partialValue.formTwosComplementSubsequence(carry) - return PVO(partialValue, overflow) + @inlinable mutating func formTwosComplementSubsequence(_ carry: Bool, as digit: T.Type) -> Bool where T: NBKCoreInteger { + var carry = carry + let lastIndex = self.elements.index(before: self.elements.endIndex) + + for index in self.elements.startIndex ..< lastIndex { + carry = self.elements[index].formTwosComplementSubsequence(carry) + } + + return self[lastIndex,as: T.self].formTwosComplementSubsequence(carry) } } diff --git a/Sources/NBKTwosComplementKit/IntXL+Division+Digit.swift b/Sources/NBKTwosComplementKit/IntXL+Division+Digit.swift index f85de0dc..76c28a2b 100644 --- a/Sources/NBKTwosComplementKit/IntXL+Division+Digit.swift +++ b/Sources/NBKTwosComplementKit/IntXL+Division+Digit.swift @@ -10,10 +10,10 @@ import NBKCoreKit //*============================================================================* -// MARK: * NBK x Flexible Width x Division x Digit x IntXL +// MARK: * NBK x Flexible Width x Division x Digit //*============================================================================* -extension IntXL { +extension IntXLOrUIntXL { //=------------------------------------------------------------------------= // MARK: Transformations @@ -40,6 +40,17 @@ extension IntXL { let qro: PVO> = self.quotientAndRemainderReportingOverflow(dividingBy: other) return PVO(qro.partialValue.remainder, qro.overflow) } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Division x Digit x IntXL +//*============================================================================* + +extension IntXL { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= @_disfavoredOverload @inlinable public func quotientAndRemainderReportingOverflow(dividingBy other: Digit) -> PVO> { fatalError("TODO") @@ -56,28 +67,6 @@ extension UIntXL { // MARK: Transformations //=------------------------------------------------------------------------= - @_disfavoredOverload @inlinable public mutating func divideReportingOverflow(by other: Digit) -> Bool { - let pvo: PVO = self.dividedReportingOverflow(by: other) - self = pvo.partialValue - return pvo.overflow as Bool - } - - @_disfavoredOverload @inlinable public func dividedReportingOverflow(by other: Digit) -> PVO { - let qro: PVO> = self.quotientAndRemainderReportingOverflow(dividingBy: other) - return PVO(qro.partialValue.quotient, qro.overflow) - } - - @_disfavoredOverload @inlinable public mutating func formRemainderReportingOverflow(dividingBy other: Digit) -> Bool { - let pvo: PVO = self.remainderReportingOverflow(dividingBy: other) - self = Self(digit: pvo.partialValue) - return pvo.overflow as Bool - } - - @_disfavoredOverload @inlinable public func remainderReportingOverflow(dividingBy other: Digit) -> PVO { - let qro: PVO> = self.quotientAndRemainderReportingOverflow(dividingBy: other) - return PVO(qro.partialValue.remainder, qro.overflow) - } - @_disfavoredOverload @inlinable public func quotientAndRemainderReportingOverflow(dividingBy other: Digit) -> PVO> { var quotient = self let remainder = quotient.formQuotientWithRemainderReportingOverflow(dividingBy: other) @@ -89,6 +78,7 @@ extension UIntXL { //=------------------------------------------------------------------------= @_disfavoredOverload @inlinable public mutating func formQuotientWithRemainderReportingOverflow(dividingBy other: Digit) -> PVO { - fatalError("TODO") + defer{ Self.normalize(&self.storage) } + return NBK.formQuotientWithRemainderReportingOverflowAsLenientUnsignedInteger(of: &self.storage.elements, dividingBy: other) } } diff --git a/Sources/NBKTwosComplementKit/IntXL+Division.swift b/Sources/NBKTwosComplementKit/IntXL+Division.swift index 5068f5df..45ea6056 100644 --- a/Sources/NBKTwosComplementKit/IntXL+Division.swift +++ b/Sources/NBKTwosComplementKit/IntXL+Division.swift @@ -10,10 +10,10 @@ import NBKCoreKit //*============================================================================* -// MARK: * NBK x Flexible Width x Division x IntXL +// MARK: * NBK x Flexible Width x Division //*============================================================================* -extension IntXL { +extension IntXLOrUIntXL { //=------------------------------------------------------------------------= // MARK: Transformations @@ -40,6 +40,17 @@ extension IntXL { let qro: PVO> = self.quotientAndRemainderReportingOverflow(dividingBy: other) return PVO(qro.partialValue.remainder, qro.overflow) } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Division x IntXL +//*============================================================================* + +extension IntXL { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= @inlinable public func quotientAndRemainderReportingOverflow(dividingBy other: Self) -> PVO> { fatalError("TODO") @@ -56,28 +67,6 @@ extension UIntXL { // MARK: Transformations //=------------------------------------------------------------------------= - @inlinable public mutating func divideReportingOverflow(by other: Self) -> Bool { - let pvo: PVO = self.dividedReportingOverflow(by: other) - self = pvo.partialValue - return pvo.overflow as Bool - } - - @inlinable public func dividedReportingOverflow(by other: Self) -> PVO { - let qro: PVO> = self.quotientAndRemainderReportingOverflow(dividingBy: other) - return PVO(qro.partialValue.quotient, qro.overflow) - } - - @inlinable public mutating func formRemainderReportingOverflow(dividingBy other: Self) -> Bool { - let pvo: PVO = self.remainderReportingOverflow(dividingBy: other) - self = pvo.partialValue - return pvo.overflow as Bool - } - - @inlinable public func remainderReportingOverflow(dividingBy other: Self) -> PVO { - let qro: PVO> = self.quotientAndRemainderReportingOverflow(dividingBy: other) - return PVO(qro.partialValue.remainder, qro.overflow) - } - @inlinable public func quotientAndRemainderReportingOverflow(dividingBy other: Self) -> PVO> { self.quotientAndRemainderReportingOverflowAsNormal(dividingBy: other) } diff --git a/Sources/NBKTwosComplementKit/IntXL+Logic.swift b/Sources/NBKTwosComplementKit/IntXL+Logic.swift index b938fdbe..e0b38c8e 100644 --- a/Sources/NBKTwosComplementKit/IntXL+Logic.swift +++ b/Sources/NBKTwosComplementKit/IntXL+Logic.swift @@ -10,10 +10,10 @@ import NBKCoreKit //*============================================================================* -// MARK: * NBK x Flexible Width x Logic x IntXL +// MARK: * NBK x Flexible Width x Logic //*============================================================================* -extension IntXL { +extension IntXLOrUIntXL { //=------------------------------------------------------------------------= // MARK: Transformations x NOT @@ -22,17 +22,20 @@ extension IntXL { @inlinable public static prefix func ~(x: Self) -> Self { x.onesComplement() } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Logic x IntXL +//*============================================================================* + +extension IntXL { //=------------------------------------------------------------------------= // MARK: Transformations x AND //=------------------------------------------------------------------------= @inlinable public static func &=(lhs: inout Self, rhs: Self) { - fatalError("TODO") - } - - @inlinable public static func &(lhs: Self, rhs: Self) -> Self { - var lhs = lhs; lhs &= rhs; return lhs + lhs.upsizeThenFormInIntersection(extending: rhs, each: &) } //=------------------------------------------------------------------------= @@ -40,11 +43,7 @@ extension IntXL { //=------------------------------------------------------------------------= @inlinable public static func |=(lhs: inout Self, rhs: Self) { - fatalError("TODO") - } - - @inlinable public static func |(lhs: Self, rhs: Self) -> Self { - var lhs = lhs; lhs |= rhs; return lhs + lhs.upsizeThenFormInIntersection(extending: rhs, each: |) } //=------------------------------------------------------------------------= @@ -52,11 +51,24 @@ extension IntXL { //=------------------------------------------------------------------------= @inlinable public static func ^=(lhs: inout Self, rhs: Self) { - fatalError("TODO") + lhs.upsizeThenFormInIntersection(extending: rhs, each: ^) } - @inlinable public static func ^(lhs: Self, rhs: Self) -> Self { - var lhs = lhs; lhs ^= rhs; return lhs + //=------------------------------------------------------------------------= + // MARK: Transformations x Private + //=------------------------------------------------------------------------= + + @inlinable mutating func upsizeThenFormInIntersection(extending other: Self, each element: (UInt, UInt) -> UInt) { + let lhsSign = UInt(repeating: self.isLessThanZero) + self.storage.resize(minCount: other.storage.elements.count, appending: lhsSign) + self.withUnsafeMutableBufferPointer { lhs in + other.withUnsafeBufferPointer { rhs in + let rhsSign = UInt(repeating: rhs.last!.mostSignificantBit) + for index in lhs.indices { + lhs[index] = element(lhs[index], index < rhs.endIndex ? rhs[index] : rhsSign) + } + } + } } } @@ -66,24 +78,13 @@ extension IntXL { extension UIntXL { - //=------------------------------------------------------------------------= - // MARK: Transformations x NOT - //=------------------------------------------------------------------------= - - @inlinable public static prefix func ~(x: Self) -> Self { - x.onesComplement() - } - //=------------------------------------------------------------------------= // MARK: Transformations x AND //=------------------------------------------------------------------------= @inlinable public static func &=(lhs: inout Self, rhs: Self) { - fatalError("TODO") - } - - @inlinable public static func &(lhs: Self, rhs: Self) -> Self { - var lhs = lhs; lhs &= rhs; return lhs + lhs.storage.downsizeThenFormInIntersection(with: rhs.storage, each: &) + Self.normalize(&lhs.storage) } //=------------------------------------------------------------------------= @@ -91,11 +92,8 @@ extension UIntXL { //=------------------------------------------------------------------------= @inlinable public static func |=(lhs: inout Self, rhs: Self) { - fatalError("TODO") - } - - @inlinable public static func |(lhs: Self, rhs: Self) -> Self { - var lhs = lhs; lhs |= rhs; return lhs + lhs.storage.upsizeThenFormInIntersection(with: rhs.storage, appending: 0 as UInt, each: |) + Swift.assert(Self.isNormal(lhs.storage)) } //=------------------------------------------------------------------------= @@ -103,10 +101,40 @@ extension UIntXL { //=------------------------------------------------------------------------= @inlinable public static func ^=(lhs: inout Self, rhs: Self) { - fatalError("TODO") + lhs.storage.upsizeThenFormInIntersection(with: rhs.storage, appending: 0 as UInt, each: ^) + Swift.assert(Self.isNormal(lhs.storage)) + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Logic x Storage +//*============================================================================* + +extension StorageXL { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable mutating func upsizeThenFormInIntersection(with other: Self, appending word: UInt, each element: (UInt, UInt) -> UInt) { + self.resize(minCount: other.elements.count, appending: word) + self.elements.withUnsafeMutableBufferPointer { lhs in + other.elements.withUnsafeBufferPointer { rhs in + for index in rhs.indices { + lhs[index] = element(lhs[index], rhs[index]) + } + } + } } - @inlinable public static func ^(lhs: Self, rhs: Self) -> Self { - var lhs = lhs; lhs ^= rhs; return lhs + @inlinable mutating func downsizeThenFormInIntersection(with other: Self, each element: (UInt, UInt) -> UInt) { + self.resize(maxCount: other.elements.count) + self.elements.withUnsafeMutableBufferPointer { lhs in + other.elements.withUnsafeBufferPointer { rhs in + for index in lhs.indices { + lhs[index] = element(lhs[index], rhs[index]) + } + } + } } } diff --git a/Sources/NBKTwosComplementKit/IntXL+Multiplication+Digit.swift b/Sources/NBKTwosComplementKit/IntXL+Multiplication+Digit.swift index 8c035d32..a57f3517 100644 --- a/Sources/NBKTwosComplementKit/IntXL+Multiplication+Digit.swift +++ b/Sources/NBKTwosComplementKit/IntXL+Multiplication+Digit.swift @@ -19,11 +19,11 @@ extension IntXL { // MARK: Transformations //=------------------------------------------------------------------------= - @_disfavoredOverload @inlinable public static func *=(lhs: inout Self, rhs: Int) { + @_disfavoredOverload @inlinable public static func *=(lhs: inout Self, rhs: Digit) { fatalError("TODO") } - @_disfavoredOverload @inlinable public static func *(lhs: Self, rhs: Int) -> Self { + @_disfavoredOverload @inlinable public static func *(lhs: Self, rhs: Digit) -> Self { fatalError("TODO") } } @@ -38,25 +38,52 @@ extension UIntXL { // MARK: Transformations //=------------------------------------------------------------------------= - @_disfavoredOverload @inlinable public static func *=(lhs: inout Self, rhs: UInt) { - lhs.multiply(by: rhs, add: UInt.zero) + @_disfavoredOverload @inlinable public static func *=(lhs: inout Self, rhs: Digit) { + lhs.multiply(by: rhs, add: 0 as Digit) } - @_disfavoredOverload @inlinable public static func *(lhs: Self, rhs: UInt) -> Self { - lhs.multiplied(by: rhs, adding: UInt.zero) + @_disfavoredOverload @inlinable public static func *(lhs: Self, rhs: Digit) -> Self { + lhs.multiplied(by: rhs, adding: 0 as Digit) } //=------------------------------------------------------------------------= // MARK: Transformations //=------------------------------------------------------------------------= - @_disfavoredOverload @inlinable public mutating func multiply(by multiplicand: UInt, add addend: UInt) { - fatalError("TODO") + @_disfavoredOverload @inlinable public mutating func multiply(by multiplicand: Digit, add addend: Digit) { + defer { + Swift.assert(Self.isNormal(self.storage)) + } + //=--------------------------------------= + if multiplicand.isZero { + return self.update(addend) + } + //=--------------------------------------= + self.storage.reserveCapacity(self.storage.elements.count + 1) + let overflow = self.storage.multiplyAsUnsigned(by: multiplicand, add: addend) + if !overflow.isZero { + self.storage.append(overflow) + } } - @_disfavoredOverload @inlinable public func multiplied(by multiplicand: UInt, adding addend: UInt) -> Self { + @_disfavoredOverload @inlinable public func multiplied(by multiplicand: Digit, adding addend: Digit) -> Self { var result = self result.multiply(by: multiplicand, add: addend) return result as Self } } + +//*============================================================================* +// MARK: * NBK x Flexible Width x Multiplication x Digit x Storage +//*============================================================================* + +extension StorageXL { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @_disfavoredOverload @inlinable mutating func multiplyAsUnsigned(by other: UInt, add addend: UInt) -> UInt { + NBK.multiplyFullWidthLenientUnsignedInteger(&self.elements, by: other, add: addend) + } +} diff --git a/Sources/NBKTwosComplementKit/IntXL+Numbers.swift b/Sources/NBKTwosComplementKit/IntXL+Numbers.swift index be01b8d3..a42e8c3a 100644 --- a/Sources/NBKTwosComplementKit/IntXL+Numbers.swift +++ b/Sources/NBKTwosComplementKit/IntXL+Numbers.swift @@ -10,43 +10,46 @@ import NBKCoreKit //*============================================================================* -// MARK: * NBK x Flexible Width x Numbers x IntXL +// MARK: * NBK x Flexible Width x Numbers //*============================================================================* -extension IntXL { +extension PrivateIntXLOrUIntXL { //=------------------------------------------------------------------------= // MARK: Initializers //=------------------------------------------------------------------------= - public static let zero = Self(0) + @inlinable public init(digit: Digit) { + self.init(unchecked: Storage(unchecked: [UInt(bitPattern: digit)])) + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Numbers x IntXL +//*============================================================================* + +extension IntXL { //=------------------------------------------------------------------------= - // MARK: Initializers x Digit + // MARK: Initializers //=------------------------------------------------------------------------= - @inlinable public init(digit: Int) { - self.init(unchecked: [UInt(bitPattern: digit)]) - } + public static let zero = Self(0) //=------------------------------------------------------------------------= // MARK: Initializers x Binary Integer //=------------------------------------------------------------------------= - @inlinable public init(_ source: some BinaryInteger) { - //=--------------------------------------= - // Magnitude - //=--------------------------------------= - if let source = source as? Magnitude { - self.init(sign: FloatingPointSign.plus, magnitude: source) - //=--------------------------------------= - // some BinaryInteger - //=--------------------------------------= + @inlinable public init(_ source: T) where T: BinaryInteger { + var storage = Storage(nonemptying: Elements(source.words)) + + if !T.isSigned, storage.last.mostSignificantBit { + storage.append(0 as UInt) } else { - let sign = FloatingPointSign(source < 0) - let magnitude = Magnitude(source.magnitude) - self.init(sign: sign, magnitude: magnitude) + Self.normalize(&storage) } + + self.init(unchecked: storage) } @inlinable public init?(exactly source: some BinaryInteger) { @@ -66,11 +69,9 @@ extension IntXL { //=------------------------------------------------------------------------= @inlinable public init(_ source: some BinaryFloatingPoint) { - guard let result = Self(exactly: source.rounded(.towardZero)) else { + if let value = Self(exactly: source.rounded(.towardZero)) { self = value } else { preconditionFailure("\(Self.description) cannot represent \(source)") } - - self = result } @inlinable public init?(exactly source: some BinaryFloatingPoint) { @@ -83,7 +84,15 @@ extension IntXL { //=------------------------------------------------------------------------= @inlinable public init(sign: FloatingPointSign, magnitude: Magnitude) { - fatalError("TODO") + var storage = magnitude.storage as Storage + var isLessThanZero = (sign == FloatingPointSign.minus) + + if isLessThanZero { + isLessThanZero = !storage.formTwosComplementReportingOverflow(as: UInt.self) + } + + Self.normalize(&storage, appending: UInt(repeating: isLessThanZero)) + self.init(unchecked: storage) } } @@ -99,24 +108,14 @@ extension UIntXL { public static let zero = Self(0) - //=------------------------------------------------------------------------= - // MARK: Initializers x Digit - //=------------------------------------------------------------------------= - - @inlinable public init(digit: UInt) { - self.init(unchecked: [digit]) - } - //=------------------------------------------------------------------------= // MARK: Initializers x Binary Integer //=------------------------------------------------------------------------= @inlinable public init(_ source: some BinaryInteger) { - guard let result = Self(exactly: source) else { + if let value = Self(exactly: source) { self = value } else { preconditionFailure("\(Self.description) cannot represent \(source)") } - - self = result } @inlinable public init?(exactly source: some BinaryInteger) { @@ -137,11 +136,9 @@ extension UIntXL { //=------------------------------------------------------------------------= @inlinable public init(_ source: some BinaryFloatingPoint) { - guard let value = Self(exactly: source.rounded(.towardZero)) else { + if let value = Self(exactly: source.rounded(.towardZero)) { self = value } else { preconditionFailure("\(Self.description) cannot represent \(source)") } - - self = value } @inlinable public init?(exactly source: some BinaryFloatingPoint) { diff --git a/Sources/NBKTwosComplementKit/IntXL+Shifts.swift b/Sources/NBKTwosComplementKit/IntXL+Shifts.swift index 6ead1415..860b6692 100644 --- a/Sources/NBKTwosComplementKit/IntXL+Shifts.swift +++ b/Sources/NBKTwosComplementKit/IntXL+Shifts.swift @@ -10,13 +10,13 @@ import NBKCoreKit //*============================================================================* -// MARK: * NBK x Flexible Width x Shifts x IntXL +// MARK: * NBK x Flexible Width x Shifts //*============================================================================* //=----------------------------------------------------------------------------= // MARK: + Left //=----------------------------------------------------------------------------= -extension IntXL { +extension PrivateIntXLOrUIntXL { //=------------------------------------------------------------------------= // MARK: Transformations @@ -60,7 +60,7 @@ extension IntXL { @inlinable public mutating func bitshiftLeft(words: Int, bits: Int) { //=--------------------------------------= if bits.isZero { - return self.bitshiftRight(words: words) + return self.bitshiftLeft(words: words) } //=--------------------------------------= self.bitshiftLeft(words: words, atLeastOneBit: bits) @@ -84,24 +84,39 @@ extension IntXL { //=------------------------------------------------------------------------= // MARK: Transformations x Int x Private //=------------------------------------------------------------------------= - + /// Performs a left shift. /// /// - Parameters: - /// - words: `0 <= words < self.endIndex` + /// - words: `0 <= words` /// - bits: `1 <= bits  < UInt.bitWidth` /// @inlinable mutating func bitshiftLeft(words: Int, atLeastOneBit bits: Int) { - fatalError("TODO") + defer { + Swift.assert(Self.isNormal(self.storage)) + } + //=--------------------------------------= + if self.isZero { return } + //=--------------------------------------= + let rollover = Int(bit: self.leadingBitCount(self.isLessThanZero) < bits) + self.storage.resize(minCount: self.storage.elements.count + words + rollover, appending: 0 as UInt) + self.storage.bitshiftLeft(words: words, atLeastOneBit: bits) } /// Performs a left shift. /// /// - Parameters: - /// - words: `1 <= words < self.endIndex` + /// - words: `1 <= words` /// @inlinable mutating func bitshiftLeft(atLeastOneWord words: Int) { - fatalError("TODO") + defer { + Swift.assert(Self.isNormal(self.storage)) + } + //=--------------------------------------= + if self.isZero { return } + //=--------------------------------------= + self.storage.resize(minCount: self.storage.elements.count + words, appending: 0 as UInt) + self.storage.bitshiftLeft(atLeastOneWord: words) } } @@ -109,7 +124,7 @@ extension IntXL { // MARK: + Right //=----------------------------------------------------------------------------= -extension IntXL { +extension PrivateIntXLOrUIntXL { //=------------------------------------------------------------------------= // MARK: Transformations @@ -178,102 +193,56 @@ extension IntXL { // MARK: Transformations x Int x Private //=------------------------------------------------------------------------= - /// Performs an signed right shift. + /// Performs an un/signed right shift. /// /// - Parameters: - /// - words: `1 <= words < self.endIndex` + /// - words: `1 <= words` /// - bits: `0 <= bits  < UInt.bitWidth` /// @inlinable mutating func bitshiftRight(words: Int, atLeastOneBit bits: Int) { - fatalError("TODO") + defer { + Swift.assert(Self.isNormal(self.storage)) + } + //=--------------------------------------= + let rollover = Int(bit: 0 <= bits + self.leadingZeroBitCount - UInt.bitWidth) + let maxCount = self.storage.elements.count - words - rollover + //=--------------------------------------= + if maxCount <= 0 { + return self.update(Digit(repeating: self.isLessThanZero)) + } + //=--------------------------------------= + self.storage.bitshiftRight(isSigned: Self.isSigned, words: words, atLeastOneBit: bits) + self.storage.resize(maxCount: maxCount) } - /// Performs an signed right shift. + /// Performs an un/signed right shift. /// /// - Parameters: - /// - words: `1 <= words < self.endIndex` + /// - words: `1 <= words` /// @inlinable mutating func bitshiftRight(atLeastOneWord words: Int) { - fatalError("TODO") + defer { + Swift.assert(Self.isNormal(self.storage)) + } + //=--------------------------------------= + if self.storage.elements.count <= words { + return self.update(Digit(repeating: self.isLessThanZero)) + } + //=--------------------------------------= + self.storage.bitshiftRight(isSigned: Self.isSigned, atLeastOneWord: words) + self.storage.resize(maxCount: self.storage.elements.count - words) } } //*============================================================================* -// MARK: * NBK x Flexible Width x Shifts x UIntXL +// MARK: * NBK x Flexible Width x Shifts x Storage //*============================================================================* //=----------------------------------------------------------------------------= // MARK: + Left //=----------------------------------------------------------------------------= -extension UIntXL { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable public static func <<=(lhs: inout Self, rhs: some BinaryInteger) { - lhs.bitshiftLeftSmart(by: NBK.initOrBitCast(clamping: rhs, as: Int.self)) - } - - @inlinable public static func <<(lhs: Self, rhs: some BinaryInteger) -> Self { - var lhs = lhs; lhs <<= rhs; return lhs - } - - //=------------------------------------------------------------------------= - // MARK: Transformations x Int - //=------------------------------------------------------------------------= - - @inlinable public mutating func bitshiftLeftSmart(by distance: Int) { - if distance >= 0 { - self.bitshiftLeft (by: distance) - } else { - self.bitshiftRight(by: Int(clamping: distance.magnitude)) - } - } - - @inlinable public func bitshiftedLeftSmart(by distance: Int) -> Self { - var result = self; result.bitshiftLeftSmart(by: distance); return result - } - - @inlinable public mutating func bitshiftLeft(by distance: Int) { - precondition(distance >= 0, NBK.callsiteOutOfBoundsInfo()) - let major = NBK .quotientDividingByBitWidthAssumingIsAtLeastZero(distance) - let minor = NBK.remainderDividingByBitWidthAssumingIsAtLeastZero(distance) - return self.bitshiftLeft(words: major, bits: minor) - } - - @inlinable public func bitshiftedLeft(by distance: Int) -> Self { - var result = self; result.bitshiftLeft(by: distance); return result - } - - @inlinable public mutating func bitshiftLeft(words: Int, bits: Int) { - //=--------------------------------------= - if bits.isZero { - return self.bitshiftRight(words: words) - } - //=--------------------------------------= - self.bitshiftLeft(words: words, atLeastOneBit: bits) - } - - @inlinable public func bitshiftedLeft(words: Int, bits: Int) -> Self { - var result = self; result.bitshiftLeft(words: words, bits: bits); return result - } - - @inlinable public mutating func bitshiftLeft(words: Int) { - //=--------------------------------------= - if words.isZero { return } - //=--------------------------------------= - self.bitshiftLeft(atLeastOneWord: words) - } - - @inlinable public func bitshiftedLeft(words: Int) -> Self { - var result = self; result.bitshiftLeft(words: words); return result - } - - //=------------------------------------------------------------------------= - // MARK: Transformations x Int x Private - //=------------------------------------------------------------------------= - +extension StorageXL { + /// Performs a left shift. /// /// - Parameters: @@ -281,7 +250,9 @@ extension UIntXL { /// - bits: `1 <= bits  < UInt.bitWidth` /// @inlinable mutating func bitshiftLeft(words: Int, atLeastOneBit bits: Int) { - fatalError("TODO") + self.elements.withUnsafeMutableBufferPointer { + NBK.bitshiftLeftAsFixedLimbsCodeBlock(&$0, environment: false, limbs: words, atLeastOneBit: bits) + } } /// Performs a left shift. @@ -290,7 +261,9 @@ extension UIntXL { /// - words: `1 <= words < self.endIndex` /// @inlinable mutating func bitshiftLeft(atLeastOneWord words: Int) { - fatalError("TODO") + self.elements.withUnsafeMutableBufferPointer { + NBK.bitshiftLeftAsFixedLimbsCodeBlock(&$0, environment: false, atLeastOneLimb: words) + } } } @@ -298,91 +271,34 @@ extension UIntXL { // MARK: + Right //=----------------------------------------------------------------------------= -extension UIntXL { +extension StorageXL { //=------------------------------------------------------------------------= // MARK: Transformations //=------------------------------------------------------------------------= - - @inlinable public static func >>=(lhs: inout Self, rhs: some BinaryInteger) { - lhs.bitshiftRightSmart(by: NBK.initOrBitCast(clamping: rhs, as: Int.self)) - } - @inlinable public static func >>(lhs: Self, rhs: some BinaryInteger) -> Self { - var lhs = lhs; lhs >>= rhs; return lhs - } - - //=------------------------------------------------------------------------= - // MARK: Transformations x Int - //=------------------------------------------------------------------------= - - @inlinable public mutating func bitshiftRightSmart(by distance: Int) { - if distance >= 0 { - self.bitshiftRight(by: distance) - } else { - self.bitshiftLeft(by: Int(clamping: distance.magnitude)) - } - } - - @inlinable public func bitshiftedRightSmart(by distance: Int) -> Self { - var result = self; result.bitshiftRightSmart(by: distance); return result - } - - @inlinable public mutating func bitshiftRight(by distance: Int) { - precondition(distance >= 0, NBK.callsiteOutOfBoundsInfo()) - let major = NBK .quotientDividingByBitWidthAssumingIsAtLeastZero(distance) - let minor = NBK.remainderDividingByBitWidthAssumingIsAtLeastZero(distance) - return self.bitshiftRight(words: major, bits: minor) - } - - @inlinable public func bitshiftedRight(by distance: Int) -> Self { - var result = self; result.bitshiftRight(by: distance); return result - } - - @inlinable public mutating func bitshiftRight(words: Int, bits: Int) { - //=--------------------------------------= - if bits.isZero { - return self.bitshiftRight(words: words) - } - //=--------------------------------------= - self.bitshiftRight(words: words, atLeastOneBit: bits) - } - - @inlinable public func bitshiftedRight(words: Int, bits: Int) -> Self { - var result = self; result.bitshiftRight(words: words, bits: bits); return result - } - - @inlinable public mutating func bitshiftRight(words: Int) { - //=--------------------------------------= - if words.isZero { return } - //=--------------------------------------= - self.bitshiftRight(atLeastOneWord: words) - } - - @inlinable public func bitshiftedRight(words: Int) -> Self { - var result = self; result.bitshiftRight(words: words); return result - } - - //=------------------------------------------------------------------------= - // MARK: Transformations x Int x Private - //=------------------------------------------------------------------------= - - /// Performs an unsigned right shift. + /// Performs an un/signed right shift. /// /// - Parameters: /// - words: `1 <= words < self.endIndex` /// - bits: `0 <= bits  < UInt.bitWidth` /// - @inlinable mutating func bitshiftRight(words: Int, atLeastOneBit bits: Int) { - fatalError("TODO") + @inlinable mutating func bitshiftRight(isSigned: Bool, words: Int, atLeastOneBit bits: Int) { + let environment = isSigned && self.last.mostSignificantBit + self.elements.withUnsafeMutableBufferPointer { + NBK.bitshiftRightAsFixedLimbsCodeBlock(&$0, environment: environment, limbs: words, atLeastOneBit: bits) + } } - /// Performs an unsigned right shift. + /// Performs an un/signed right shift. /// /// - Parameters: /// - words: `1 <= words < self.endIndex` /// - @inlinable mutating func bitshiftRight(atLeastOneWord words: Int) { - fatalError("TODO") + @inlinable mutating func bitshiftRight(isSigned: Bool, atLeastOneWord words: Int) { + let environment = isSigned && self.last.mostSignificantBit + self.elements.withUnsafeMutableBufferPointer { + NBK.bitshiftRightAsFixedLimbsCodeBlock(&$0, environment: environment, atLeastOneLimb: words) + } } } diff --git a/Sources/NBKTwosComplementKit/IntXL+Storage.swift b/Sources/NBKTwosComplementKit/IntXL+Storage.swift index 2fb0c34a..facfd703 100644 --- a/Sources/NBKTwosComplementKit/IntXL+Storage.swift +++ b/Sources/NBKTwosComplementKit/IntXL+Storage.swift @@ -9,6 +9,21 @@ import NBKCoreKit +//*============================================================================* +// MARK: * NBK x Flexible Width x Storage +//*============================================================================* + +extension PrivateIntXLOrUIntXL { + + //=------------------------------------------------------------------------= + // MARK: Details x Normalization + //=------------------------------------------------------------------------= + + @inlinable static func normalize(_ storage: inout Storage, update value: Digit) { + storage.elements.replaceSubrange(storage.elements.indices, with: CollectionOfOne(UInt(bitPattern: value))) + } +} + //*============================================================================* // MARK: * NBK x Flexible Width x Storage x IntXL //*============================================================================* @@ -16,55 +31,55 @@ import NBKCoreKit extension IntXL { //=------------------------------------------------------------------------= - // MARK: Utilities + // MARK: Details x Normalization //=------------------------------------------------------------------------= - @inlinable var isNormal: Bool { - if self.storage.count == 1 { return true } + @inlinable static func isNormal(_ storage: Storage) -> Bool { + if storage.elements.count == 1 { return true } - let tail = Int(bitPattern: self.storage[self.storage.count - 1]) - let head = Int(bitPattern: self.storage[self.storage.count - 2]) + let tail = Int(bitPattern: storage.elements[storage.elements.count - 1]) + let head = Int(bitPattern: storage.elements[storage.elements.count - 2]) let sign = tail >> Int.bitWidth return !(sign == tail && sign == head >> Int.bitWidth) } - @inlinable mutating func normalize() { - Swift.assert(!self.storage.isEmpty) + @inlinable static func normalize(_ storage: inout Storage) { + Swift.assert(!storage.elements.isEmpty) //=--------------------------------------= - var position = self.storage.index(before: self.storage.endIndex) - let mostSignificantBit = self.storage[position].mostSignificantBit + var position = storage.elements.index(before: storage.elements.endIndex) + let mostSignificantBit = storage.elements[position].mostSignificantBit let sign = UInt(repeating: mostSignificantBit) //=--------------------------------------= // TODO: measure combined loop conditions //=--------------------------------------= - backwards: while position > self.storage.startIndex { - if self.storage[position] != sign { return } - self.storage.formIndex(before: &position) - if self.storage[position].mostSignificantBit != mostSignificantBit { return } - self.storage.removeLast() + backwards: while position > storage.elements.startIndex { + if storage.elements[position] != sign { return } + storage.elements.formIndex(before: &position) + if storage.elements[position].mostSignificantBit != mostSignificantBit { return } + storage.elements.removeLast() } } - @inlinable mutating func normalize(appending word: UInt) { - Swift.assert(!self.storage.isEmpty) + @inlinable static func normalize(_ storage: inout Storage, appending word: UInt) { + Swift.assert(!storage.elements.isEmpty) //=--------------------------------------= - var position = self.storage.index(before: self.storage.endIndex) - let mostSignificantBit = self.storage[position].mostSignificantBit + var position = storage.elements.index(before: storage.elements.endIndex) + let mostSignificantBit = storage.elements[position].mostSignificantBit let sign = UInt(repeating: mostSignificantBit) //=--------------------------------------= if word != sign { - return self.storage.append(word) + return storage.elements.append(word) } //=--------------------------------------= // TODO: measure combined loop conditions //=--------------------------------------= - backwards: while position > self.storage.startIndex { - if self.storage[position] != sign { return } - self.storage.formIndex(before: &position) - if self.storage[position].mostSignificantBit != mostSignificantBit { return } - self.storage.removeLast() + backwards: while position > storage.elements.startIndex { + if storage.elements[position] != sign { return } + storage.elements.formIndex(before: &position) + if storage.elements[position].mostSignificantBit != mostSignificantBit { return } + storage.elements.removeLast() } } } @@ -76,25 +91,63 @@ extension IntXL { extension UIntXL { //=------------------------------------------------------------------------= - // MARK: Utilities + // MARK: Details x Normalization //=------------------------------------------------------------------------= - @inlinable var isNormal: Bool { - self.storage.count == 1 || !self.storage.last!.isZero + @inlinable static func isNormal(_ storage: Storage) -> Bool { + storage.elements.count == 1 || !storage.elements.last!.isZero } - @inlinable mutating func normalize() { - Swift.assert(!self.storage.isEmpty) + @inlinable static func normalize(_ storage: inout Storage) { + Swift.assert(!storage.elements.isEmpty) //=--------------------------------------= - var position = self.storage.index(before: self.storage.endIndex) + var position = storage.elements.index(before: storage.elements.endIndex) let sign = UInt(repeating: false) //=--------------------------------------= // TODO: measure combined loop conditions //=--------------------------------------= - backwards: while position > self.storage.startIndex { - if self.storage[position] != sign { return } - self.storage.formIndex(before: &position) - self.storage.removeLast() + backwards: while position > storage.elements.startIndex { + if storage.elements[position] != sign { return } + storage.elements.formIndex(before: &position) + storage.elements.removeLast() + } + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Storage x StorageXL +//*============================================================================* + +extension StorageXL { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable mutating func reserveCapacity(_ minCapacity: Int) { + self.elements.reserveCapacity(minCapacity) + } + + @inlinable mutating func append(_ word: UInt) { + self.elements.append(word) + } + + @inlinable mutating func resize(maxCount: Int) { + precondition(maxCount.isMoreThanZero) + if self.elements.count > maxCount { + self.elements.removeSubrange(maxCount...) } } + + @inlinable mutating func resize(minCount: Int, appending word: UInt) { + self.reserveCapacity(minCount) + appending: while self.elements.count < minCount { + self.elements.append(word) + } + } + + @inlinable mutating func resize(minCount: Int, isSigned: Bool) { + let isLessThanZero = self.isLessThanZero(isSigned: isSigned) + self.resize(minCount: minCount, appending: UInt(repeating: isLessThanZero)) + } } diff --git a/Sources/NBKTwosComplementKit/IntXL+Subtraction+Digit.swift b/Sources/NBKTwosComplementKit/IntXL+Subtraction+Digit.swift index 85e5db27..14f24f5d 100644 --- a/Sources/NBKTwosComplementKit/IntXL+Subtraction+Digit.swift +++ b/Sources/NBKTwosComplementKit/IntXL+Subtraction+Digit.swift @@ -10,22 +10,29 @@ import NBKCoreKit //*============================================================================* -// MARK: * NBK x Flexible Width x Subtraction x Digit x IntXL +// MARK: * NBK x Flexible Width x Subtraction x Digit //*============================================================================* -extension IntXL { +extension IntXLOrUIntXL { //=------------------------------------------------------------------------= // MARK: Transformations //=------------------------------------------------------------------------= - @_disfavoredOverload @inlinable public static func -=(lhs: inout Self, rhs: Int) { + @_disfavoredOverload @inlinable public static func -=(lhs: inout Self, rhs: Digit) { lhs.subtract(rhs, at: Int.zero) } - @_disfavoredOverload @inlinable public static func -(lhs: Self, rhs: Int) -> Self { + @_disfavoredOverload @inlinable public static func -(lhs: Self, rhs: Digit) -> Self { lhs.subtracting(rhs, at: Int.zero) } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Subtraction x Digit x IntXL +//*============================================================================* + +extension IntXL { //=------------------------------------------------------------------------= // MARK: Transformations @@ -50,26 +57,6 @@ extension UIntXL { // MARK: Transformations //=------------------------------------------------------------------------= - @_disfavoredOverload @inlinable public static func -=(lhs: inout Self, rhs: UInt) { - lhs.subtract(rhs, at: Int.zero) - } - - @_disfavoredOverload @inlinable public static func -(lhs: Self, rhs: UInt) -> Self { - lhs.subtracting(rhs, at: Int.zero) - } - - @_disfavoredOverload @inlinable public mutating func subtractReportingOverflow(_ other: UInt) -> Bool { - self.subtractReportingOverflow(other, at: Int.zero) - } - - @_disfavoredOverload @inlinable public func subtractingReportingOverflow(_ other: UInt) -> PVO { - self.subtractingReportingOverflow(other, at: Int.zero) - } - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - @_disfavoredOverload @inlinable public mutating func subtract(_ other: UInt, at index: Int) { let overflow: Bool = self.subtractReportingOverflow(other, at: index) precondition(!overflow, NBK.callsiteOverflowInfo()) @@ -81,6 +68,18 @@ extension UIntXL { return pvo.partialValue as Self } + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @_disfavoredOverload @inlinable public mutating func subtractReportingOverflow(_ other: UInt) -> Bool { + self.subtractReportingOverflow(other, at: Int.zero) + } + + @_disfavoredOverload @inlinable public func subtractingReportingOverflow(_ other: UInt) -> PVO { + self.subtractingReportingOverflow(other, at: Int.zero) + } + @_disfavoredOverload @inlinable public mutating func subtractReportingOverflow(_ other: UInt, at index: Int) -> Bool { fatalError("TODO") } diff --git a/Sources/NBKTwosComplementKit/IntXL+Subtraction.swift b/Sources/NBKTwosComplementKit/IntXL+Subtraction.swift index 90256986..65632d9a 100644 --- a/Sources/NBKTwosComplementKit/IntXL+Subtraction.swift +++ b/Sources/NBKTwosComplementKit/IntXL+Subtraction.swift @@ -10,10 +10,10 @@ import NBKCoreKit //*============================================================================* -// MARK: * NBK x Flexible Width x Subtraction x IntXL +// MARK: * NBK x Flexible Width x Subtraction //*============================================================================* -extension IntXL { +extension IntXLOrUIntXL { //=------------------------------------------------------------------------= // MARK: Transformations @@ -26,6 +26,13 @@ extension IntXL { @inlinable public static func -(lhs: Self, rhs: Self) -> Self { lhs.subtracting(rhs, at: Int.zero) } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Subtraction x IntXL +//*============================================================================* + +extension IntXL { //=------------------------------------------------------------------------= // MARK: Transformations @@ -50,14 +57,21 @@ extension UIntXL { // MARK: Transformations //=------------------------------------------------------------------------= - @inlinable public static func -=(lhs: inout Self, rhs: Self) { - lhs.subtract(rhs, at: Int.zero) + @inlinable public mutating func subtract(_ other: Self, at index: Int) { + let overflow: Bool = self.subtractReportingOverflow(other, at: index) + precondition(!overflow, NBK.callsiteOverflowInfo()) } - @inlinable public static func -(lhs: Self, rhs: Self) -> Self { - lhs.subtracting(rhs, at: Int.zero) + @inlinable public func subtracting(_ other: Self, at index: Int) -> Self { + let pvo: PVO = self.subtractingReportingOverflow(other, at: index) + precondition(!pvo.overflow, NBK.callsiteOverflowInfo()) + return pvo.partialValue as Self } + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + @inlinable public mutating func subtractReportingOverflow(_ other: Self) -> Bool { self.subtractReportingOverflow(other, at: Int.zero) } @@ -66,21 +80,6 @@ extension UIntXL { self.subtractingReportingOverflow(other, at: Int.zero) } - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable public mutating func subtract(_ other: Self, at index: Int) { - let overflow: Bool = self.subtractReportingOverflow(other, at: index) - precondition(!overflow, NBK.callsiteOverflowInfo()) - } - - @inlinable public func subtracting(_ other: Self, at index: Int) -> Self { - let pvo: PVO = self.subtractingReportingOverflow(other, at: index) - precondition(!pvo.overflow, NBK.callsiteOverflowInfo()) - return pvo.partialValue as Self - } - @inlinable public mutating func subtractReportingOverflow(_ other: Self, at index: Int) -> Bool { fatalError("TODO") } diff --git a/Sources/NBKTwosComplementKit/IntXL+Text.swift b/Sources/NBKTwosComplementKit/IntXL+Text.swift index b023929c..40463688 100644 --- a/Sources/NBKTwosComplementKit/IntXL+Text.swift +++ b/Sources/NBKTwosComplementKit/IntXL+Text.swift @@ -10,48 +10,10 @@ import NBKCoreKit //*============================================================================* -// MARK: * NBK x Flexible Width x Text x IntXL +// MARK: * NBK x Flexible Width x Text //*============================================================================* -extension IntXL { - - //=------------------------------------------------------------------------= - // MARK: Details x Decode - //=------------------------------------------------------------------------= - - @inlinable public init?(_ description: some StringProtocol, radix: Int = 10) { - var description = String(description) - if let value: Self = description.withUTF8({ utf8 in - - let radix = NBK.AnyRadixSolution(radix) - let components = NBK.makeIntegerComponents(utf8: utf8) - let digits = NBK.UnsafeUTF8(rebasing: components.body) - guard let magnitude = Magnitude(digits: digits, radix: radix) else { return nil } - return Self(sign: components.sign, magnitude: magnitude) - - }){ self = value } else { return nil } - } - - //=------------------------------------------------------------------------= - // MARK: Details x Encode - //=------------------------------------------------------------------------= - - @inlinable public func description(radix: Int = 10, uppercase: Bool = false) -> String { - Swift.withUnsafePointer(to: UInt8(ascii: "-")) { minus in - let radix = NBK.AnyRadixSolution(radix) - let alphabet = NBK.MaxRadixAlphabetEncoder(uppercase: uppercase) - let prefix = NBK.UnsafeUTF8(start: minus, count: Int(bit: self.isLessThanZero)) - let suffix = NBK.UnsafeUTF8(start: nil, count: Int.zero) - return self.magnitude.description(radix: radix, alphabet: alphabet, prefix: prefix, suffix: suffix) - } - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Text x UIntXL -//*============================================================================* - -extension UIntXL { +extension IntXLOrUIntXL { //=------------------------------------------------------------------------= // MARK: Details x Decode @@ -104,11 +66,42 @@ extension UIntXL { } @inlinable init?(digits: NBK.UnsafeUTF8, radix: NBK.PerfectRadixSolution) { - fatalError("TODO") + guard !digits.isEmpty else { return nil } + //=--------------------------------------= + var digits = digits.drop(while:{ $0 == 48 }) + let division = digits.count.quotientAndRemainder(dividingBy: radix.exponent) + let count = division.quotient + Int(bit: !division.remainder.isZero) + //=--------------------------------------= + var elements = Elements(repeating: 0, count: count) + + backwards: for index in elements.indices { + let chunk = NBK.UnsafeUTF8(rebasing: NBK.removeSuffix(from: &digits, maxLength: radix.exponent)) + guard let word = NBK.truncating(digits: chunk, radix: radix.base, as: UInt.self) else { return nil } + elements[index] = word + } + + self.init(unchecked: Storage(nonemptying: elements)) } @inlinable init?(digits: NBK.UnsafeUTF8, radix: NBK.ImperfectRadixSolution) { - fatalError("TODO") + guard !digits.isEmpty else { return nil } + //=--------------------------------------= + var digits = digits.drop(while:{ $0 == 48 }) + let remainder = digits.count % radix.exponent + //=--------------------------------------= + self.init() + + forwards: if !remainder.isZero { + let chunk = NBK.UnsafeUTF8(rebasing: NBK.removePrefix(from: &digits, count: remainder)) + guard let word = NBK.truncating(digits: chunk, radix: radix.base, as: UInt.self) else { return nil } + self.storage.first = word + } + + forwards: while !digits.isEmpty { + let chunk = NBK.UnsafeUTF8(rebasing: NBK.removePrefix(from: &digits, count: radix.exponent)) + guard let word = NBK.truncating(digits: chunk, radix: radix.base, as: UInt.self) else { return nil } + self.multiply(by: radix.power, add: word) + } } //=------------------------------------------------------------------------= @@ -133,7 +126,7 @@ extension UIntXL { //=--------------------------------------= // with one buffer pointer specialization //=--------------------------------------= - self.storage.withUnsafeBufferPointer { words in + self.withUnsafeBufferPointer { words in let chunks = NBKTwinHeaded(words) let radix = NBK.AnyRadixSolution(radix) return NBK.integerTextUnchecked(chunks: chunks, radix: radix, alphabet: alphabet, prefix: prefix, suffix: suffix) diff --git a/Sources/NBKTwosComplementKit/IntXL+Update.swift b/Sources/NBKTwosComplementKit/IntXL+Update.swift new file mode 100644 index 00000000..7e047a4e --- /dev/null +++ b/Sources/NBKTwosComplementKit/IntXL+Update.swift @@ -0,0 +1,29 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x Update +//*============================================================================* + +extension PrivateIntXLOrUIntXL { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public mutating func updateZeroValue() { + self.update(0 as Digit) + } + + @inlinable public mutating func update(_ value: Digit) { + Self.normalize(&self.storage, update: value) + } +} diff --git a/Sources/NBKTwosComplementKit/IntXL+Words+Pointers.swift b/Sources/NBKTwosComplementKit/IntXL+Words+Pointers.swift new file mode 100644 index 00000000..6c6bdce6 --- /dev/null +++ b/Sources/NBKTwosComplementKit/IntXL+Words+Pointers.swift @@ -0,0 +1,34 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x Words x Pointers +//*============================================================================* + +extension PrivateIntXLOrUIntXL { + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + /// Grants unsafe access to the collection's contiguous storage. + @inlinable public func withUnsafeBufferPointer( + _ body:(UnsafeBufferPointer) throws -> T) rethrows -> T { + try self.storage.elements.withUnsafeBufferPointer(body) + } + + /// Grants unsafe access to the collection's contiguous mutable storage. + @inlinable public mutating func withUnsafeMutableBufferPointer( + _ body:(inout UnsafeMutableBufferPointer) throws -> T) rethrows -> T { + defer{ Self.normalize(&self.storage) } + return try self.storage.elements.withUnsafeMutableBufferPointer(body) + } +} diff --git a/Sources/NBKTwosComplementKit/IntXL+Words.swift b/Sources/NBKTwosComplementKit/IntXL+Words.swift index 7ec22012..b8df9826 100644 --- a/Sources/NBKTwosComplementKit/IntXL+Words.swift +++ b/Sources/NBKTwosComplementKit/IntXL+Words.swift @@ -7,18 +7,20 @@ // See http://www.apache.org/licenses/LICENSE-2.0 for license information. //=----------------------------------------------------------------------------= +import NBKCoreKit + //*============================================================================* -// MARK: * NBK x Flexible Width x Words x IntXL +// MARK: * NBK x Flexible Width x Words //*============================================================================* -extension IntXL { +extension PrivateIntXLOrUIntXL { //=------------------------------------------------------------------------= // MARK: Initializers //=------------------------------------------------------------------------= @inlinable public init(words: some Sequence) { - self.init(Storage(words)) + self.init(normalizing: Storage(nonemptying: Elements(words))) } //=------------------------------------------------------------------------= @@ -26,45 +28,40 @@ extension IntXL { //=------------------------------------------------------------------------= @inlinable public var words: ContiguousArray { - self.storage + self.storage.elements // TODO: make opaque } @inlinable public subscript(index: Int) -> UInt { - if index < self.storage.endIndex { - return self.storage[index] + if index < self.storage.elements.endIndex { + return self.storage.elements[index] } else { - return UInt(bitPattern: Int(bitPattern: self.storage.last!) >> Int.bitWidth) + return UInt(bitPattern: Digit(bitPattern: self.storage.last) >> Digit.bitWidth) } } } //*============================================================================* -// MARK: * NBK x Flexible Width x Words x UIntXL +// MARK: * NBK x Flexible Width x Words x Storage //*============================================================================* -extension UIntXL { +extension NBKFlexibleWidth.Storage { //=------------------------------------------------------------------------= - // MARK: Initializers + // MARK: Accessors //=------------------------------------------------------------------------= - @inlinable public init(words: some Sequence) { - self.init(Storage(words)) + @inlinable var first: UInt { + get { self.elements[self.elements.startIndex] } + set { self.elements[self.elements.startIndex] = newValue } } - //=------------------------------------------------------------------------= - // MARK: Accessors - //=------------------------------------------------------------------------= - - @inlinable public var words: ContiguousArray { - self.storage + @inlinable var last: UInt { + get { self.elements[self.elements.index(before: self.elements.endIndex)] } + set { self.elements[self.elements.index(before: self.elements.endIndex)] = newValue } } - @inlinable public subscript(index: Int) -> UInt { - if index < self.storage.endIndex { - return self.storage[index] - } else { - return 0000000000000000000 - } + @inlinable subscript(_ index: Int, as type: T.Type) -> T where T: NBKCoreInteger { + get { T.init(bitPattern: self.elements[index]) } + set { self.elements[index] = UInt(bitPattern: newValue) } } } diff --git a/Sources/NBKTwosComplementKit/IntXL.swift b/Sources/NBKTwosComplementKit/IntXL.swift index 5bcd09be..0e32513b 100644 --- a/Sources/NBKTwosComplementKit/IntXL.swift +++ b/Sources/NBKTwosComplementKit/IntXL.swift @@ -14,19 +14,21 @@ import NBKCoreKit //*============================================================================* /// A signed, flexible-width, binary integer. -@frozen public struct IntXL: IntXLOrUIntXL, NBKSignedInteger { +@frozen public struct NBKFlexibleWidth: PrivateIntXLOrUIntXL, NBKSignedInteger { public typealias Digit = Int - @usableFromInline typealias Storage = ContiguousArray + public typealias Words = ContiguousArray + @usableFromInline typealias Elements = ContiguousArray + //=------------------------------------------------------------------------= // MARK: State //=------------------------------------------------------------------------= /// The integer's underlying storage. /// - /// It must be normal and nonempty the start and end of each integer access. + /// It must be `normal` and `nonempty` at the start and end of each access. /// @usableFromInline var storage: Storage @@ -36,68 +38,203 @@ import NBKCoreKit @inlinable init(_ storage: Storage) { self.storage = storage - precondition(!self.storage.isEmpty) - self.normalize() + precondition(Self.isNormal(self.storage)) } @inlinable init(unchecked storage: Storage) { self.storage = storage + Swift.assert(Self.isNormal(self.storage)) } - //=------------------------------------------------------------------------= - // MARK: Utilities - //=------------------------------------------------------------------------= + @inlinable init(normalizing storage: Storage) { + self.storage = storage + Self.normalize(&self.storage) + } - /// A `description` of this type. + //*========================================================================* + // MARK: * Magnitude + //*========================================================================* + + /// An unsigned, flexible-width, binary integer. + @frozen public struct Magnitude: PrivateIntXLOrUIntXL, NBKUnsignedInteger { + + public typealias Digit = UInt + + public typealias Words = NBKFlexibleWidth.Words + + @usableFromInline typealias Storage = NBKFlexibleWidth.Storage + + @usableFromInline typealias Elements = NBKFlexibleWidth.Elements + + //=--------------------------------------------------------------------= + // MARK: State + //=--------------------------------------------------------------------= + + /// The integer's underlying storage. + /// + /// It must be `normal` and `nonempty` at the start and end of each access. + /// + @usableFromInline var storage: Storage + + //=--------------------------------------------------------------------= + // MARK: Initializers + //=--------------------------------------------------------------------= + + @inlinable init(_ storage: Storage) { + self.storage = storage + precondition(Self.isNormal(self.storage)) + } + + @inlinable init(unchecked storage: Storage) { + self.storage = storage + Swift.assert(Self.isNormal(self.storage)) + } + + @inlinable init(normalizing storage: Storage) { + self.storage = storage + Self.normalize(&self.storage) + } + } + + //*============================================================================* + // MARK: * Storage + //*============================================================================* + + /// IntXL's and UIntXL's underlying storage. /// - /// ``` - /// ┌─────────────────────────── → ────────────┐ - /// │ type │ description │ - /// ├─────────────────────────── → ────────────┤ - /// │ NBKFlexibleWidth │ "IntXL" │ - /// │ NBKFlexibleWidth.Magnitude │ "UIntXL" │ - /// └─────────────────────────── → ────────────┘ - /// ``` + /// It has fixed-width semantics unless stated otherwise. /// - @inlinable public static var description: String { - "IntXL" + @frozen @usableFromInline struct Storage { + + @usableFromInline typealias Elements = NBKFlexibleWidth.Elements + + //=------------------------------------------------------------------------= + // MARK: State + //=------------------------------------------------------------------------= + + /// The integer's underlying storage. + /// + /// It must be `nonempty` at the start and end of each access. + /// + @usableFromInline var elements: Elements + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + @inlinable init(_ elements: Elements) { + self.elements = elements + precondition(!self.elements.isEmpty) + } + + @inlinable init(unchecked elements: Elements) { + self.elements = elements + Swift.assert(!self.elements.isEmpty) + } + + @inlinable init(nonemptying elements: Elements) { + self.elements = elements + if self.elements.isEmpty { + self.elements.append(0) + } + } } } //*============================================================================* -// MARK: * NBK x Flexible Width x UIntXL +// MARK: * NBK x Flexible Width x Aliases //*============================================================================* -/// An unsigned, flexible-width, binary integer. -@frozen public struct UIntXL: IntXLOrUIntXL, NBKUnsignedInteger { +/// A signed, flexible-width, integer. +public typealias IntXL = NBKFlexibleWidth + +/// An unsigned, flexible-width, integer. +public typealias UIntXL = NBKFlexibleWidth.Magnitude + +/// IntXL's and UIntXL's underlying storage. +@usableFromInline typealias StorageXL = NBKFlexibleWidth.Storage + +//*============================================================================* +// MARK: * NBK x Flexible Width x Protocol +//*============================================================================* + +public protocol IntXLOrUIntXL: NBKBinaryInteger, ExpressibleByStringLiteral where +Digit: NBKCoreInteger, Magnitude == UIntXL { + + //=------------------------------------------------------------------------= + // MARK: Details x Addition + //=------------------------------------------------------------------------= + + @inlinable mutating func add(_ other: Self, at index: Int) - public typealias Digit = UInt + @inlinable func adding(_ other: Self, at index: Int) -> Self - @usableFromInline typealias Storage = ContiguousArray + @_disfavoredOverload @inlinable mutating func add(_ other: Digit, at index: Int) + + @_disfavoredOverload @inlinable func adding(_ other: Digit, at index: Int) -> Self //=------------------------------------------------------------------------= - // MARK: State + // MARK: Details x Subtraction //=------------------------------------------------------------------------= - /// The integer's underlying storage. - /// - /// It must be normal and nonempty the start and end of each integer access. - /// - @usableFromInline var storage: Storage + @inlinable mutating func subtract(_ other: Self, at index: Int) + + @inlinable func subtracting(_ other: Self, at index: Int) -> Self + + @_disfavoredOverload @inlinable mutating func subtract(_ other: Digit, at index: Int) + + @_disfavoredOverload @inlinable func subtracting(_ other: Digit, at index: Int) -> Self //=------------------------------------------------------------------------= - // MARK: Initializers + // MARK: Details x Shifts //=------------------------------------------------------------------------= - @inlinable init(_ storage: Storage) { - self.storage = storage - precondition(!self.storage.isEmpty) - self.normalize() - } + @inlinable mutating func bitshiftLeftSmart(by distance: Int) - @inlinable init(unchecked storage: Storage) { - self.storage = storage - } + @inlinable func bitshiftedLeftSmart(by distance: Int) -> Self + + @inlinable mutating func bitshiftLeft(by distance: Int) + + @inlinable func bitshiftedLeft(by distance: Int) -> Self + + @inlinable mutating func bitshiftLeft(words: Int, bits: Int) + + @inlinable func bitshiftedLeft(words: Int, bits: Int) -> Self + + @inlinable mutating func bitshiftLeft(words: Int) + + @inlinable func bitshiftedLeft(words: Int) -> Self + + @inlinable mutating func bitshiftRightSmart(by distance: Int) + + @inlinable func bitshiftedRightSmart(by distance: Int) -> Self + + @inlinable mutating func bitshiftRight(by distance: Int) + + @inlinable func bitshiftedRight(by distance: Int) -> Self + + @inlinable mutating func bitshiftRight(words: Int, bits: Int) + + @inlinable func bitshiftedRight(words: Int, bits: Int) -> Self + + @inlinable mutating func bitshiftRight(words: Int) + + @inlinable func bitshiftedRight(words: Int) -> Self + + //=------------------------------------------------------------------------= + // MARK: Details x Update + //=------------------------------------------------------------------------= + + @inlinable mutating func updateZeroValue() + + @inlinable mutating func update(_ value: Digit) +} + +//=----------------------------------------------------------------------------= +// MARK: + Details +//=----------------------------------------------------------------------------= + +extension IntXLOrUIntXL { //=------------------------------------------------------------------------= // MARK: Utilities @@ -115,12 +252,41 @@ import NBKCoreKit /// ``` /// @inlinable public static var description: String { - "UIntXL" + self.isSigned ? "IntXL" : "UIntXL" } } //*============================================================================* -// MARK: * NBK x IntXL or UIntXL +// MARK: * NBK x Flexible Width x Protocol x Private //*============================================================================* -public protocol IntXLOrUIntXL: NBKBinaryInteger, ExpressibleByStringLiteral where Magnitude == UIntXL { } +@usableFromInline protocol PrivateIntXLOrUIntXL: IntXLOrUIntXL where Words == NBKFlexibleWidth.Words { + + typealias Storage = NBKFlexibleWidth.Storage + + typealias Elements = NBKFlexibleWidth.Elements + + //=------------------------------------------------------------------------= + // MARK: State + //=------------------------------------------------------------------------= + + @inlinable var storage: Storage { get set } + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + @inlinable init(_ storage: Storage) + + @inlinable init(unchecked storage: Storage) + + @inlinable init(normalizing storage: Storage) + + //=------------------------------------------------------------------------= + // MARK: Details x Storage + //=------------------------------------------------------------------------= + + @inlinable static func isNormal(_ storage: Storage) -> Bool + + @inlinable static func normalize(_ storage: inout Storage) +} diff --git a/Tests/NBKTwosComplementKitTests/IntXL+Bits.swift b/Tests/NBKTwosComplementKitTests/IntXL+Bits.swift new file mode 100644 index 00000000..230b38b2 --- /dev/null +++ b/Tests/NBKTwosComplementKitTests/IntXL+Bits.swift @@ -0,0 +1,212 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +import NBKTwosComplementKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Flexible Width x Bits x IntXL +//*============================================================================* + +final class NBKFlexibleWidthTestsOnBitsAsIntXL: XCTestCase { + + typealias T = IntXL + typealias M = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testInitBit() { + XCTAssertEqual(T(bit: false), T( )) + XCTAssertEqual(T(bit: true ), T(1)) + } + + func testBitWidth() { + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).bitWidth, UInt.bitWidth * 1) + XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).bitWidth, UInt.bitWidth * 1) + + XCTAssertEqual(T(sign: .plus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as W)).bitWidth, UInt.bitWidth * 4) + XCTAssertEqual(T(sign: .plus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as W)).bitWidth, UInt.bitWidth * 5) + XCTAssertEqual(T(sign: .plus, magnitude: M(words:[ 1, 0, 0, ~0/2 + 1] as W)).bitWidth, UInt.bitWidth * 5) + + XCTAssertEqual(T(sign: .minus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as W)).bitWidth, UInt.bitWidth * 4) + XCTAssertEqual(T(sign: .minus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as W)).bitWidth, UInt.bitWidth * 4) + XCTAssertEqual(T(sign: .minus, magnitude: M(words:[ 1, 0, 0, ~0/2 + 1] as W)).bitWidth, UInt.bitWidth * 5) + } + + func testNonzeroBitCount() { + XCTAssertEqual(T(sign: .minus, magnitude: 0).nonzeroBitCount, 0) + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).nonzeroBitCount, 0) + XCTAssertEqual(T(words:[ 1, 1, 1, 1] as W).nonzeroBitCount, 4) + XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).nonzeroBitCount, UInt.bitWidth * 1) + + XCTAssertEqual(T(sign: .plus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as W)).nonzeroBitCount, UInt.bitWidth * 4 - 1) + XCTAssertEqual(T(sign: .plus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as W)).nonzeroBitCount, UInt.bitWidth * 0 + 1) + XCTAssertEqual(T(sign: .plus, magnitude: M(words:[ 1, 0, 0, ~0/2 + 1] as W)).nonzeroBitCount, UInt.bitWidth * 0 + 2) + + XCTAssertEqual(T(sign: .minus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as W)).nonzeroBitCount, UInt.bitWidth * 0 + 2) + XCTAssertEqual(T(sign: .minus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as W)).nonzeroBitCount, UInt.bitWidth * 0 + 1) + XCTAssertEqual(T(sign: .minus, magnitude: M(words:[ 1, 0, 0, ~0/2 + 1] as W)).nonzeroBitCount, UInt.bitWidth * 5 - 1) + } + + func testLeadingZeroBitCount() { + XCTAssertEqual(T(sign: .minus, magnitude: 0).leadingZeroBitCount, UInt.bitWidth * 1) + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).leadingZeroBitCount, UInt.bitWidth * 1) + XCTAssertEqual(T(words:[ 1, 1, 1, 1] as W).leadingZeroBitCount, UInt.bitWidth * 1 - 1) + XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).leadingZeroBitCount, UInt.bitWidth * 0) + + XCTAssertEqual(T(words:[ 2, 0, 0, 0] as W).leadingZeroBitCount, UInt.bitWidth * 1 - 2) + XCTAssertEqual(T(words:[ 0, 2, 0, 0] as W).leadingZeroBitCount, UInt.bitWidth * 1 - 2) + XCTAssertEqual(T(words:[ 0, 0, 2, 0] as W).leadingZeroBitCount, UInt.bitWidth * 1 - 2) + XCTAssertEqual(T(words:[ 0, 0, 0, 2] as W).leadingZeroBitCount, UInt.bitWidth * 1 - 2) + + XCTAssertEqual(T(sign: .plus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as W)).leadingZeroBitCount, UInt.bitWidth * 0 + 1) + XCTAssertEqual(T(sign: .plus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as W)).leadingZeroBitCount, UInt.bitWidth * 1 + 0) + XCTAssertEqual(T(sign: .plus, magnitude: M(words:[ 1, 0, 0, ~0/2 + 1] as W)).leadingZeroBitCount, UInt.bitWidth * 1 + 0) + + XCTAssertEqual(T(sign: .minus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as W)).leadingZeroBitCount, UInt.bitWidth * 0 + 0) + XCTAssertEqual(T(sign: .minus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as W)).leadingZeroBitCount, UInt.bitWidth * 0 + 0) + XCTAssertEqual(T(sign: .minus, magnitude: M(words:[ 1, 0, 0, ~0/2 + 1] as W)).leadingZeroBitCount, UInt.bitWidth * 0 + 0) + } + + func testTrailingZeroBitCount() { + XCTAssertEqual(T(sign: .minus, magnitude: 0).trailingZeroBitCount, UInt.bitWidth * 1) + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).trailingZeroBitCount, UInt.bitWidth * 1) + XCTAssertEqual(T(words:[ 1, 1, 1, 1] as W).trailingZeroBitCount, UInt.bitWidth * 0) + XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).trailingZeroBitCount, UInt.bitWidth * 0) + + XCTAssertEqual(T(words:[ 2, 0, 0, 0] as W).trailingZeroBitCount, UInt.bitWidth * 0 + 1) + XCTAssertEqual(T(words:[ 0, 2, 0, 0] as W).trailingZeroBitCount, UInt.bitWidth * 1 + 1) + XCTAssertEqual(T(words:[ 0, 0, 2, 0] as W).trailingZeroBitCount, UInt.bitWidth * 2 + 1) + XCTAssertEqual(T(words:[ 0, 0, 0, 2] as W).trailingZeroBitCount, UInt.bitWidth * 3 + 1) + } + + func testMostSignificantBit() { + XCTAssertEqual(T(sign: .minus, magnitude: 0).mostSignificantBit, false) + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).mostSignificantBit, false) + XCTAssertEqual(T(words:[ 1, 1, 1, 1] as W).mostSignificantBit, false) + XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).mostSignificantBit, true ) + + XCTAssertEqual(T(words:[~0, 0, 0, 0] as W).mostSignificantBit, false) + XCTAssertEqual(T(words:[ 0, ~0, 0, 0] as W).mostSignificantBit, false) + XCTAssertEqual(T(words:[ 0, 0, ~0, 0] as W).mostSignificantBit, false) + XCTAssertEqual(T(words:[ 0, 0, 0, ~0] as W).mostSignificantBit, true ) + + XCTAssertEqual(T(words:[~0, 1, 0, 0] as W).mostSignificantBit, false) + XCTAssertEqual(T(words:[ 0, ~0, 1, 0] as W).mostSignificantBit, false) + XCTAssertEqual(T(words:[ 0, 0, ~0, 1] as W).mostSignificantBit, false) + XCTAssertEqual(T(words:[ 1, 0, 0, ~0] as W).mostSignificantBit, true ) + } + + func testLeastSignificantBit() { + XCTAssertEqual(T(sign: .minus, magnitude: 0).leastSignificantBit, false) + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).leastSignificantBit, false) + XCTAssertEqual(T(words:[ 1, 1, 1, 1] as W).leastSignificantBit, true ) + XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).leastSignificantBit, true ) + + XCTAssertEqual(T(words:[~0, 0, 0, 0] as W).leastSignificantBit, true ) + XCTAssertEqual(T(words:[ 0, ~0, 0, 0] as W).leastSignificantBit, false) + XCTAssertEqual(T(words:[ 0, 0, ~0, 0] as W).leastSignificantBit, false) + XCTAssertEqual(T(words:[ 0, 0, 0, ~0] as W).leastSignificantBit, false) + + XCTAssertEqual(T(words:[~0, 1, 0, 0] as W).leastSignificantBit, true ) + XCTAssertEqual(T(words:[ 0, ~0, 1, 0] as W).leastSignificantBit, false) + XCTAssertEqual(T(words:[ 0, 0, ~0, 1] as W).leastSignificantBit, false) + XCTAssertEqual(T(words:[ 1, 0, 0, ~0] as W).leastSignificantBit, true ) + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Bits x UIntXL +//*============================================================================* + +final class NBKFlexibleWidthTestsOnBitsAsUIntXL: XCTestCase { + + typealias T = UIntXL + typealias M = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testInitBit() { + XCTAssertEqual(T(bit: false), T( )) + XCTAssertEqual(T(bit: true ), T(1)) + } + + func testBitWidth() { + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).bitWidth, UInt.bitWidth * 1) + XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).bitWidth, UInt.bitWidth * 4) + } + + func testNonzeroBitCount() { + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).nonzeroBitCount, 0) + XCTAssertEqual(T(words:[ 1, 1, 1, 1] as W).nonzeroBitCount, 4) + } + + func testLeadingZeroBitCount() { + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).leadingZeroBitCount, UInt.bitWidth * 1) + XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).leadingZeroBitCount, UInt.bitWidth * 0) + + XCTAssertEqual(T(words:[ 2, 0, 0, 0] as W).leadingZeroBitCount, UInt.bitWidth * 1 - 2) + XCTAssertEqual(T(words:[ 0, 2, 0, 0] as W).leadingZeroBitCount, UInt.bitWidth * 1 - 2) + XCTAssertEqual(T(words:[ 0, 0, 2, 0] as W).leadingZeroBitCount, UInt.bitWidth * 1 - 2) + XCTAssertEqual(T(words:[ 0, 0, 0, 2] as W).leadingZeroBitCount, UInt.bitWidth * 1 - 2) + } + + func testTrailingZeroBitCount() { + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).trailingZeroBitCount, UInt.bitWidth * 1) + XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).trailingZeroBitCount, UInt.bitWidth * 0) + + XCTAssertEqual(T(words:[ 2, 0, 0, 0] as W).trailingZeroBitCount, UInt.bitWidth * 0 + 1) + XCTAssertEqual(T(words:[ 0, 2, 0, 0] as W).trailingZeroBitCount, UInt.bitWidth * 1 + 1) + XCTAssertEqual(T(words:[ 0, 0, 2, 0] as W).trailingZeroBitCount, UInt.bitWidth * 2 + 1) + XCTAssertEqual(T(words:[ 0, 0, 0, 2] as W).trailingZeroBitCount, UInt.bitWidth * 3 + 1) + } + + func testMostSignificantBit() { + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).mostSignificantBit, false) + XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).mostSignificantBit, true ) + + XCTAssertEqual(T(words:[~0, 0, 0, 0] as W).mostSignificantBit, true ) + XCTAssertEqual(T(words:[ 0, ~0, 0, 0] as W).mostSignificantBit, true ) + XCTAssertEqual(T(words:[ 0, 0, ~0, 0] as W).mostSignificantBit, true ) + XCTAssertEqual(T(words:[ 0, 0, 0, ~0] as W).mostSignificantBit, true ) + + XCTAssertEqual(T(words:[~0, 1, 0, 0] as W).mostSignificantBit, false) + XCTAssertEqual(T(words:[ 0, ~0, 1, 0] as W).mostSignificantBit, false) + XCTAssertEqual(T(words:[ 0, 0, ~0, 1] as W).mostSignificantBit, false) + XCTAssertEqual(T(words:[ 1, 0, 0, ~0] as W).mostSignificantBit, true ) + } + + func testLeastSignificantBit() { + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).leastSignificantBit, false) + XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).leastSignificantBit, true ) + + XCTAssertEqual(T(words:[~0, 0, 0, 0] as W).leastSignificantBit, true ) + XCTAssertEqual(T(words:[ 0, ~0, 0, 0] as W).leastSignificantBit, false) + XCTAssertEqual(T(words:[ 0, 0, ~0, 0] as W).leastSignificantBit, false) + XCTAssertEqual(T(words:[ 0, 0, 0, ~0] as W).leastSignificantBit, false) + + XCTAssertEqual(T(words:[~0, 1, 0, 0] as W).leastSignificantBit, true ) + XCTAssertEqual(T(words:[ 0, ~0, 1, 0] as W).leastSignificantBit, false) + XCTAssertEqual(T(words:[ 0, 0, ~0, 1] as W).leastSignificantBit, false) + XCTAssertEqual(T(words:[ 1, 0, 0, ~0] as W).leastSignificantBit, true ) + } +} + +#endif diff --git a/Tests/NBKTwosComplementKitTests/IntXL+Logic.swift b/Tests/NBKTwosComplementKitTests/IntXL+Logic.swift new file mode 100644 index 00000000..5a70aa71 --- /dev/null +++ b/Tests/NBKTwosComplementKitTests/IntXL+Logic.swift @@ -0,0 +1,170 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +import NBKTwosComplementKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Flexible Width x Logic x IntXL +//*============================================================================* + +final class NBKFlexibleWidthTestsOnLogicAsIntXL: XCTestCase { + + typealias T = IntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testNot() { + NBKAssertNot(T(words:[ 0, 0, 0, 0] as W), T(words:[~0, ~0, ~0, ~0] as W)) + NBKAssertNot(T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 0, 0, 0, 0] as W)) + + NBKAssertNot(T(words:[ 0, 1, 2, 3] as W), T(words:[~0, ~1, ~2, ~3] as W)) + NBKAssertNot(T(words:[~0, ~1, ~2, ~3] as W), T(words:[ 0, 1, 2, 3] as W)) + } + + func testAnd() { + NBKAssertAnd(T(words:[ 0, 1, 2, 3] as W), T(words:[ 0, 0, 0, 0] as W), T(words:[ 0, 0, 0, 0] as W)) + NBKAssertAnd(T(words:[ 3, 2, 1, 0] as W), T(words:[ 0, 0, 0, 0] as W), T(words:[ 0, 0, 0, 0] as W)) + + NBKAssertAnd(T(words:[ 0, 1, 2, 3] as W), T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 0, 1, 2, 3] as W)) + NBKAssertAnd(T(words:[ 3, 2, 1, 0] as W), T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 3, 2, 1, 0] as W)) + + NBKAssertAnd(T(words:[ 0, 1, 2, 3] as W), T(words:[ 1, 1, 1, 1] as W), T(words:[ 0, 1, 0, 1] as W)) + NBKAssertAnd(T(words:[ 3, 2, 1, 0] as W), T(words:[ 1, 1, 1, 1] as W), T(words:[ 1, 0, 1, 0] as W)) + } + + func testOr() { + NBKAssertOr (T(words:[ 0, 1, 2, 3] as W), T(words:[ 0, 0, 0, 0] as W), T(words:[ 0, 1, 2, 3] as W)) + NBKAssertOr (T(words:[ 3, 2, 1, 0] as W), T(words:[ 0, 0, 0, 0] as W), T(words:[ 3, 2, 1, 0] as W)) + + NBKAssertOr (T(words:[ 0, 1, 2, 3] as W), T(words:[~0, ~0, ~0, ~0] as W), T(words:[~0, ~0, ~0, ~0] as W)) + NBKAssertOr (T(words:[ 3, 2, 1, 0] as W), T(words:[~0, ~0, ~0, ~0] as W), T(words:[~0, ~0, ~0, ~0] as W)) + + NBKAssertOr (T(words:[ 0, 1, 2, 3] as W), T(words:[ 1, 1, 1, 1] as W), T(words:[ 1, 1, 3, 3] as W)) + NBKAssertOr (T(words:[ 3, 2, 1, 0] as W), T(words:[ 1, 1, 1, 1] as W), T(words:[ 3, 3, 1, 1] as W)) + } + + func testXor() { + NBKAssertXor(T(words:[ 0, 1, 2, 3] as W), T(words:[ 0, 0, 0, 0] as W), T(words:[ 0, 1, 2, 3] as W)) + NBKAssertXor(T(words:[ 3, 2, 1, 0] as W), T(words:[ 0, 0, 0, 0] as W), T(words:[ 3, 2, 1, 0] as W)) + + NBKAssertXor(T(words:[ 0, 1, 2, 3] as W), T(words:[~0, ~0, ~0, ~0] as W), T(words:[~0, ~1, ~2, ~3] as W)) + NBKAssertXor(T(words:[ 3, 2, 1, 0] as W), T(words:[~0, ~0, ~0, ~0] as W), T(words:[~3, ~2, ~1, ~0] as W)) + + NBKAssertXor(T(words:[ 0, 1, 2, 3] as W), T(words:[ 1, 1, 1, 1] as W), T(words:[ 1, 0, 3, 2] as W)) + NBKAssertXor(T(words:[ 3, 2, 1, 0] as W), T(words:[ 1, 1, 1, 1] as W), T(words:[ 2, 3, 0, 1] as W)) + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Logic x UIntXL +//*============================================================================* + +final class NBKFlexibleWidthTestsOnLogicAsUIntXL: XCTestCase { + + typealias T = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testNot() { + NBKAssertNot(T(words:[ 0, 0, 0, 0] as W), T(words:[~0, 0, 0, 0] as W)) + NBKAssertNot(T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 0, 0, 0, 0] as W)) + + NBKAssertNot(T(words:[ 0, 1, 2, 3] as W), T(words:[~0, ~1, ~2, ~3] as W)) + NBKAssertNot(T(words:[~0, ~1, ~2, ~3] as W), T(words:[ 0, 1, 2, 3] as W)) + } + + func testAnd() { + NBKAssertAnd(T(words:[ 0, 1, 2, 3] as W), T(words:[ 0, 0, 0, 0] as W), T(words:[ 0, 0, 0, 0] as W)) + NBKAssertAnd(T(words:[ 3, 2, 1, 0] as W), T(words:[ 0, 0, 0, 0] as W), T(words:[ 0, 0, 0, 0] as W)) + + NBKAssertAnd(T(words:[ 0, 1, 2, 3] as W), T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 0, 1, 2, 3] as W)) + NBKAssertAnd(T(words:[ 3, 2, 1, 0] as W), T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 3, 2, 1, 0] as W)) + + NBKAssertAnd(T(words:[ 0, 1, 2, 3] as W), T(words:[ 1, 1, 1, 1] as W), T(words:[ 0, 1, 0, 1] as W)) + NBKAssertAnd(T(words:[ 3, 2, 1, 0] as W), T(words:[ 1, 1, 1, 1] as W), T(words:[ 1, 0, 1, 0] as W)) + } + + func testOr() { + NBKAssertOr (T(words:[ 0, 1, 2, 3] as W), T(words:[ 0, 0, 0, 0] as W), T(words:[ 0, 1, 2, 3] as W)) + NBKAssertOr (T(words:[ 3, 2, 1, 0] as W), T(words:[ 0, 0, 0, 0] as W), T(words:[ 3, 2, 1, 0] as W)) + + NBKAssertOr (T(words:[ 0, 1, 2, 3] as W), T(words:[~0, ~0, ~0, ~0] as W), T(words:[~0, ~0, ~0, ~0] as W)) + NBKAssertOr (T(words:[ 3, 2, 1, 0] as W), T(words:[~0, ~0, ~0, ~0] as W), T(words:[~0, ~0, ~0, ~0] as W)) + + NBKAssertOr (T(words:[ 0, 1, 2, 3] as W), T(words:[ 1, 1, 1, 1] as W), T(words:[ 1, 1, 3, 3] as W)) + NBKAssertOr (T(words:[ 3, 2, 1, 0] as W), T(words:[ 1, 1, 1, 1] as W), T(words:[ 3, 3, 1, 1] as W)) + } + + func testXor() { + NBKAssertXor(T(words:[ 0, 1, 2, 3] as W), T(words:[ 0, 0, 0, 0] as W), T(words:[ 0, 1, 2, 3] as W)) + NBKAssertXor(T(words:[ 3, 2, 1, 0] as W), T(words:[ 0, 0, 0, 0] as W), T(words:[ 3, 2, 1, 0] as W)) + + NBKAssertXor(T(words:[ 0, 1, 2, 3] as W), T(words:[~0, ~0, ~0, ~0] as W), T(words:[~0, ~1, ~2, ~3] as W)) + NBKAssertXor(T(words:[ 3, 2, 1, 0] as W), T(words:[~0, ~0, ~0, ~0] as W), T(words:[~3, ~2, ~1, ~0] as W)) + + NBKAssertXor(T(words:[ 0, 1, 2, 3] as W), T(words:[ 1, 1, 1, 1] as W), T(words:[ 1, 0, 3, 2] as W)) + NBKAssertXor(T(words:[ 3, 2, 1, 0] as W), T(words:[ 1, 1, 1, 1] as W), T(words:[ 2, 3, 0, 1] as W)) + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Logic x Assertions +//*============================================================================* + +private func NBKAssertNot( +_ operand: T, _ result: T, +file: StaticString = #file, line: UInt = #line) { + if operand.words.last != UInt.max { + XCTAssertEqual(~operand, result, file: file, line: line) + XCTAssertEqual(~result, operand, file: file, line: line) + } else { + XCTAssertEqual(~operand, result, file: file, line: line) + } +} + +private func NBKAssertAnd( +_ lhs: T, _ rhs: T, _ result: T, +file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual( lhs & rhs, result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs &= rhs; return lhs }(), result, file: file, line: line) + XCTAssertEqual( rhs & lhs, result, file: file, line: line) + XCTAssertEqual({ var rhs = rhs; rhs &= lhs; return rhs }(), result, file: file, line: line) +} + +private func NBKAssertOr( +_ lhs: T, _ rhs: T, _ result: T, +file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual( lhs | rhs, result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs |= rhs; return lhs }(), result, file: file, line: line) + XCTAssertEqual( rhs | lhs, result, file: file, line: line) + XCTAssertEqual({ var rhs = rhs; rhs |= lhs; return rhs }(), result, file: file, line: line) +} + +private func NBKAssertXor( +_ lhs: T, _ rhs: T, _ result: T, +file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual( lhs ^ rhs, result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs ^= rhs; return lhs }(), result, file: file, line: line) + XCTAssertEqual( rhs ^ lhs, result, file: file, line: line) + XCTAssertEqual({ var rhs = rhs; rhs ^= lhs; return rhs }(), result, file: file, line: line) +} + +#endif diff --git a/Tests/NBKTwosComplementKitTests/IntXL+Shifts.swift b/Tests/NBKTwosComplementKitTests/IntXL+Shifts.swift new file mode 100644 index 00000000..f8c731e6 --- /dev/null +++ b/Tests/NBKTwosComplementKitTests/IntXL+Shifts.swift @@ -0,0 +1,324 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +import NBKTwosComplementKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Flexible Width x Shifts x IntXL +//*============================================================================* + +final class NBKFlexibleWidthTestsOnShiftsAsIntXL: XCTestCase { + + typealias T = IntXL + + //=------------------------------------------------------------------------= + // MARK: Tests x Left + //=------------------------------------------------------------------------= + + func testBitshiftingLeftByBits() { + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 0, T(x64:[ 1, 2, 3, 4] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 1, T(x64:[ 2, 4, 6, 8] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 2, T(x64:[ 4, 8, 12, 16] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 3, T(x64:[ 8, 16, 24, 32] as X)) + } + + func testBitshiftingLeftByWords() { + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 0, T(x64:[ 1, 2, 3, 4, 0, 0, 0, 0] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 64, T(x64:[ 0, 1, 2, 3, 4, 0, 0, 0] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 128, T(x64:[ 0, 0, 1, 2, 3, 4, 0, 0] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 192, T(x64:[ 0, 0, 0, 1, 2, 3, 4, 0] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 256, T(x64:[ 0, 0, 0, 0, 1, 2, 3, 4] as X)) + } + + func testBitshiftingLeftByWordsAndBits() { + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 3, T(x64:[ 8, 16, 24, 32, 0, 0, 0, 0] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 67, T(x64:[ 0, 8, 16, 24, 32, 0, 0, 0] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 131, T(x64:[ 0, 0, 8, 16, 24, 32, 0, 0] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 195, T(x64:[ 0, 0, 0, 8, 16, 24, 32, 0] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 259, T(x64:[ 0, 0, 0, 0, 8, 16, 24, 32] as X)) + } + + func testBitshiftingLeftSuchThatWordsSplit() { + NBKAssertShiftLeft(T(x64:[~0, 0, 0, 0] as X), 1, T(x64:[~1, 1, 0, 0, 0] as X)) + NBKAssertShiftLeft(T(x64:[ 0, ~0, 0, 0] as X), 1, T(x64:[ 0, ~1, 1, 0, 0] as X)) + NBKAssertShiftLeft(T(x64:[ 0, 0, ~0, 0] as X), 1, T(x64:[ 0, 0, ~1, 1, 0] as X)) + NBKAssertShiftLeft(T(x64:[ 0, 0, 0, ~0] as X), 1, T(x64:[ 0, 0, 0, ~1, ~0] as X)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Right + //=------------------------------------------------------------------------= + + func testBitshiftingRightByBits() { + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 0, T(x64:[ 8, 16, 24, 32] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 1, T(x64:[ 4, 8, 12, 16] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 2, T(x64:[ 2, 4, 6, 8] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 3, T(x64:[ 1, 2, 3, 4] as X)) + } + + func testBitshiftingRightByWords() { + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 0, T(x64:[ 8, 16, 24, 32] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 64, T(x64:[16, 24, 32, 0] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 128, T(x64:[24, 32, 0, 0] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 192, T(x64:[32, 0, 0, 0] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 256, T(x64:[ 0, 0, 0, 0] as X)) + } + + func testBitshiftingRightByWordsAndBits() { + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 3, T(x64:[ 1, 2, 3, 4] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 67, T(x64:[ 2, 3, 4, 0] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 131, T(x64:[ 3, 4, 0, 0] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 195, T(x64:[ 4, 0, 0, 0] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 259, T(x64:[ 0, 0, 0, 0] as X)) + } + + func testBitshiftingRightSuchThatWordsSplit() { + NBKAssertShiftRight(T(x64:[0, 0, 0, 7] as X), 1, T(x64:[ 0, 0, 1 << 63, 3] as X)) + NBKAssertShiftRight(T(x64:[0, 0, 7, 0] as X), 1, T(x64:[ 0, 1 << 63, 3, 0] as X)) + NBKAssertShiftRight(T(x64:[0, 7, 0, 0] as X), 1, T(x64:[ 1 << 63, 3, 0, 0] as X)) + NBKAssertShiftRight(T(x64:[7, 0, 0, 0] as X), 1, T(x64:[ 3, 0, 0, 0] as X)) + } + + func testBitshiftingRightIsSigned() { + NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X), 0, T(x64:[ 0, 0, 0, 1 << 63] as X)) + NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X), 64, T(x64:[ 0, 0, 1 << 63, ~0] as X)) + NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X), 128, T(x64:[ 0, 1 << 63, ~0, ~0] as X)) + NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X), 192, T(x64:[ 1 << 63, ~0, ~0, ~0] as X)) + NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X), 256, T(x64:[~0, ~0, ~0, ~0] as X)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Miscellaneous + //=------------------------------------------------------------------------= + + func testBitshiftingIsSmart() { + XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) << 1, T(x64:[2, 4, 6, 8, 0] as X)) + XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) >> -1, T(x64:[2, 4, 6, 8, 0] as X)) + + XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) << 64, T(x64:[0, 1, 2, 3, 4] as X)) + XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) >> -64, T(x64:[0, 1, 2, 3, 4] as X)) + } + + func testBitshiftingRightDoesNotTrap() { + XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) >> Int.max, T.zero) + XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) << Int.min, T.zero) + } + + func testBitshiftingZeroDoesNotTrap() { + XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) << Int.min, T.zero) + XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) << Int.max, T.zero) + + XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) >> Int.min, T.zero) + XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) >> Int.max, T.zero) + } + + func testBitshiftingZeroDoesNotDoAnything() { + XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) << (UInt.bitWidth + 0), T.zero) + XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) << (UInt.bitWidth + 1), T.zero) + + XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) >> (UInt.bitWidth + 0), T.zero) + XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) >> (UInt.bitWidth + 1), T.zero) + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Shifts x UIntXL +//*============================================================================* + +final class NBKFlexibleWidthTestsOnShiftsAsUIntXL: XCTestCase { + + typealias T = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests x Left + //=------------------------------------------------------------------------= + + func testBitshiftingLeftByBits() { + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 0, T(x64:[ 1, 2, 3, 4] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 1, T(x64:[ 2, 4, 6, 8] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 2, T(x64:[ 4, 8, 12, 16] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 3, T(x64:[ 8, 16, 24, 32] as X)) + } + + func testBitshiftingLeftByWords() { + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 0, T(x64:[ 1, 2, 3, 4, 0, 0, 0, 0] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 64, T(x64:[ 0, 1, 2, 3, 4, 0, 0, 0] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 128, T(x64:[ 0, 0, 1, 2, 3, 4, 0, 0] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 192, T(x64:[ 0, 0, 0, 1, 2, 3, 4, 0] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 256, T(x64:[ 0, 0, 0, 0, 1, 2, 3, 4] as X)) + } + + func testBitshiftingLeftByWordsAndBits() { + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 3, T(x64:[ 8, 16, 24, 32, 0, 0, 0, 0] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 67, T(x64:[ 0, 8, 16, 24, 32, 0, 0, 0] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 131, T(x64:[ 0, 0, 8, 16, 24, 32, 0, 0] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 195, T(x64:[ 0, 0, 0, 8, 16, 24, 32, 0] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 259, T(x64:[ 0, 0, 0, 0, 8, 16, 24, 32] as X)) + } + + func testBitshiftingLeftSuchThatWordsSplit() { + NBKAssertShiftLeft(T(x64:[~0, 0, 0, 0] as X), 1, T(x64:[~1, 1, 0, 0, 0] as X)) + NBKAssertShiftLeft(T(x64:[ 0, ~0, 0, 0] as X), 1, T(x64:[ 0, ~1, 1, 0, 0] as X)) + NBKAssertShiftLeft(T(x64:[ 0, 0, ~0, 0] as X), 1, T(x64:[ 0, 0, ~1, 1, 0] as X)) + NBKAssertShiftLeft(T(x64:[ 0, 0, 0, ~0] as X), 1, T(x64:[ 0, 0, 0, ~1, 1] as X)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Right + //=------------------------------------------------------------------------= + + func testBitshiftingRightByBits() { + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 0, T(x64:[ 8, 16, 24, 32] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 1, T(x64:[ 4, 8, 12, 16] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 2, T(x64:[ 2, 4, 6, 8] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 3, T(x64:[ 1, 2, 3, 4] as X)) + } + + func testBitshiftingRightByWords() { + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 0, T(x64:[ 8, 16, 24, 32] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 64, T(x64:[16, 24, 32, 0] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 128, T(x64:[24, 32, 0, 0] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 192, T(x64:[32, 0, 0, 0] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 256, T(x64:[ 0, 0, 0, 0] as X)) + } + + func testBitshiftingRightByWordsAndBits() { + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 3, T(x64:[ 1, 2, 3, 4] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 67, T(x64:[ 2, 3, 4, 0] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 131, T(x64:[ 3, 4, 0, 0] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 195, T(x64:[ 4, 0, 0, 0] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 259, T(x64:[ 0, 0, 0, 0] as X)) + } + + func testBitshiftingRightSuchThatWordsSplit() { + NBKAssertShiftRight(T(x64:[0, 0, 0, 7] as X), 1, T(x64:[ 0, 0, 1 << 63, 3] as X)) + NBKAssertShiftRight(T(x64:[0, 0, 7, 0] as X), 1, T(x64:[ 0, 1 << 63, 3, 0] as X)) + NBKAssertShiftRight(T(x64:[0, 7, 0, 0] as X), 1, T(x64:[ 1 << 63, 3, 0, 0] as X)) + NBKAssertShiftRight(T(x64:[7, 0, 0, 0] as X), 1, T(x64:[ 3, 0, 0, 0] as X)) + } + + func testBitshiftingRightIsUnsigned() { + NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X), 0, T(x64:[0, 0, 0, 1 << 63] as X)) + NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X), 64, T(x64:[0, 0, 1 << 63, 0] as X)) + NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X), 128, T(x64:[0, 1 << 63, 0, 0] as X)) + NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X), 192, T(x64:[1 << 63, 0, 0, 0] as X)) + NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X), 256, T(x64:[0, 0, 0, 0] as X)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Miscellaneous + //=------------------------------------------------------------------------= + + func testBitshiftingIsSmart() { + XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) << 1, T(x64:[2, 4, 6, 8, 0] as X)) + XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) >> -1, T(x64:[2, 4, 6, 8, 0] as X)) + + XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) << 64, T(x64:[0, 1, 2, 3, 4] as X)) + XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) >> -64, T(x64:[0, 1, 2, 3, 4] as X)) + } + + func testBitshiftingRightDoesNotTrap() { + XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) >> Int.max, T.zero) + XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) << Int.min, T.zero) + } + + func testBitshiftingZeroDoesNotTrap() { + XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) << Int.min, T.zero) + XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) << Int.max, T.zero) + + XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) >> Int.min, T.zero) + XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) >> Int.max, T.zero) + } + + func testBitshiftingZeroDoesNotDoAnything() { + XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) << (UInt.bitWidth + 0), T.zero) + XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) << (UInt.bitWidth + 1), T.zero) + + XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) >> (UInt.bitWidth + 0), T.zero) + XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) >> (UInt.bitWidth + 1), T.zero) + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Shifts x Assertions +//*============================================================================* + +private func NBKAssertShiftLeft( +_ lhs: T, _ rhs: Int, _ result: T, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + let (words, bits) = rhs.quotientAndRemainder(dividingBy: UInt.bitWidth) + //=------------------------------------------= + XCTAssertEqual( lhs << rhs, result, file: file, line: line) + XCTAssertEqual( lhs >> -rhs, result, file: file, line: line) + + XCTAssertEqual({ var lhs = lhs; lhs <<= rhs; return lhs }(), result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs >>= -rhs; return lhs }(), result, file: file, line: line) + + XCTAssertEqual(lhs.bitshiftedLeftSmart(by: rhs), result, file: file, line: line) + XCTAssertEqual(lhs.bitshiftedRightSmart(by: -rhs), result, file: file, line: line) + + XCTAssertEqual({ var lhs = lhs; lhs.bitshiftLeftSmart(by: rhs); return lhs }(), result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs.bitshiftRightSmart(by: -rhs); return lhs }(), result, file: file, line: line) + //=------------------------------------------= + if 0 ..< lhs.bitWidth ~= rhs { + XCTAssertEqual(lhs.bitshiftedLeft(by: rhs), result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs.bitshiftLeft(by: rhs); return lhs }(), result, file: file, line: line) + + XCTAssertEqual(lhs.bitshiftedLeft(words: words, bits: bits), result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs.bitshiftLeft(words: words, bits: bits); return lhs }(), result, file: file, line: line) + } + //=------------------------------------------= + if 0 ..< lhs.bitWidth ~= rhs, bits.isZero { + XCTAssertEqual(lhs.bitshiftedLeft(words: words), result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs.bitshiftLeft(words: words); return lhs }(), result, file: file, line: line) + } +} + +private func NBKAssertShiftRight( +_ lhs: T, _ rhs: Int, _ result: T, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + let (words, bits) = rhs.quotientAndRemainder(dividingBy: UInt.bitWidth) + //=------------------------------------------= + XCTAssertEqual( lhs >> rhs, result, file: file, line: line) + XCTAssertEqual( lhs << -rhs, result, file: file, line: line) + + XCTAssertEqual({ var lhs = lhs; lhs >>= rhs; return lhs }(), result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs <<= -rhs; return lhs }(), result, file: file, line: line) + + XCTAssertEqual(lhs.bitshiftedRightSmart(by: rhs), result, file: file, line: line) + XCTAssertEqual(lhs.bitshiftedLeftSmart(by: -rhs), result, file: file, line: line) + + XCTAssertEqual({ var lhs = lhs; lhs.bitshiftRightSmart(by: rhs); return lhs }(), result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs.bitshiftLeftSmart(by: -rhs); return lhs }(), result, file: file, line: line) + //=------------------------------------------= + if 0 ..< lhs.bitWidth ~= rhs { + XCTAssertEqual(lhs.bitshiftedRight(by: rhs), result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs.bitshiftRight(by: rhs); return lhs }(), result, file: file, line: line) + + XCTAssertEqual(lhs.bitshiftedRight(words: words, bits: bits), result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs.bitshiftRight(words: words, bits: bits); return lhs }(), result, file: file, line: line) + } + //=------------------------------------------= + if 0 ..< lhs.bitWidth ~= rhs, bits.isZero { + XCTAssertEqual(lhs.bitshiftedRight(words: words), result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs.bitshiftRight(words: words); return lhs }(), result, file: file, line: line) + } +} + +#endif diff --git a/Tests/NBKTwosComplementKitTests/IntXL+Text.swift b/Tests/NBKTwosComplementKitTests/IntXL+Text.swift new file mode 100644 index 00000000..e998f0d1 --- /dev/null +++ b/Tests/NBKTwosComplementKitTests/IntXL+Text.swift @@ -0,0 +1,1435 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +import NBKTwosComplementKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Flexible Width x Text x IntXL +//*============================================================================* + +final class NBKFlexibleWidthTestsOnTextAsIntXL: XCTestCase { + + typealias T = IntXL + + //=------------------------------------------------------------------------= + // MARK: State + //=------------------------------------------------------------------------= + + let bit256 = 256 + let min256 = T.min256 + let max256 = T.max256 + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testFromDescription() { + NBKAssertFromDescription(T?( 10), "10") + NBKAssertFromDescription(T?( 10), "+10") + NBKAssertFromDescription(T?(-10), "-10") + NBKAssertFromDescription(T?(nil), " 10") + NBKAssertFromDescription(T?(nil), "0x10") + NBKAssertFromDescription(T?(nil), "+0x10") + NBKAssertFromDescription(T?(nil), "-0x10") + NBKAssertFromDescription(T?(nil), " 0x10") + } + + func testInstanceDescriptionUsesRadix10() { + XCTAssertEqual("10", T(10).description) + XCTAssertEqual("10", String(describing: T(10))) + } + + func testMetaTypeDescriptionIsSimple() { + XCTAssertEqual("IntXL", T.description) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Decode + //=------------------------------------------------------------------------= + + func testDecodingRadix02() { + NBKAssertDecodeText(min256, 02, "-1" + String(repeating: "0", count: bit256 / 1 - 1)) + NBKAssertDecodeText(max256, 02, String(repeating: "1", count: bit256 / 1 - 1)) + } + + func testDecodingRadix03() { + NBKAssertDecodeText(min256, 03, "-21221122120" + + "12222212211110210202220000022211002111211122012220" + + "12122202101121021220012201000100012101202122101020" + + "20010111121211022111102111220220201211121011101022" ) + NBKAssertDecodeText(max256, 03, "21221122120" + + "12222212211110210202220000022211002111211122012220" + + "12122202101121021220012201000100012101202122101020" + + "20010111121211022111102111220220201211121011101021" ) + } + + func testDecodingRadix04() { + NBKAssertDecodeText(min256, 04, "-2" + String(repeating: "0", count: bit256 / 2 - 1)) + NBKAssertDecodeText(max256, 04, "1" + String(repeating: "3", count: bit256 / 2 - 1)) + } + + func testDecodingRadix08() { + NBKAssertDecodeText(min256, 08, "-1" + String(repeating: "0", count: 85)) + NBKAssertDecodeText(max256, 08, String(repeating: "7", count: 85)) + } + + func testDecodingRadix10() { + NBKAssertDecodeText(min256, 10, "-57896044618658097711785492504343953926634992332820282019728792003956564819968") + NBKAssertDecodeText(max256, 10, "57896044618658097711785492504343953926634992332820282019728792003956564819967") + } + + func testDecodingRadix16() { + NBKAssertDecodeText(min256, 16, "-8" + String(repeating: "0", count: bit256 / 4 - 1)) + NBKAssertDecodeText(max256, 16, "7" + String(repeating: "f", count: bit256 / 4 - 1)) + } + + func testDecodingRadix32() { + NBKAssertDecodeText(min256, 32, "-1" + String(repeating: "0", count: 51)) + NBKAssertDecodeText(max256, 32, String(repeating: "v", count: 51)) + } + + func testDecodingRadix36() { + NBKAssertDecodeText(min256, 36, "-36ukv65j19b11mbvjyfui963v4my01krth19g3r3bk1ojlrwu8") + NBKAssertDecodeText(max256, 36, "36ukv65j19b11mbvjyfui963v4my01krth19g3r3bk1ojlrwu7") + } + + func testDecodingRadixLiteralAsNumber() { + NBKAssertDecodeText(T( 33), 36, "0x") + NBKAssertDecodeText(T( 24), 36, "0o") + NBKAssertDecodeText(T( 11), 36, "0b") + + NBKAssertDecodeText(T( 33), 36, "+0x") + NBKAssertDecodeText(T( 24), 36, "+0o") + NBKAssertDecodeText(T( 11), 36, "+0b") + + NBKAssertDecodeText(T(-33), 36, "-0x") + NBKAssertDecodeText(T(-24), 36, "-0o") + NBKAssertDecodeText(T(-11), 36, "-0b") + } + + func testDecodingRadixLiteralAsRadixReturnsNil() { + NBKAssertDecodeText(T?.none, 10, "0x10") + NBKAssertDecodeText(T?.none, 10, "0o10") + NBKAssertDecodeText(T?.none, 10, "0b10") + + NBKAssertDecodeText(T?.none, 10, "+0x10") + NBKAssertDecodeText(T?.none, 10, "+0o10") + NBKAssertDecodeText(T?.none, 10, "+0b10") + + NBKAssertDecodeText(T?.none, 10, "-0x10") + NBKAssertDecodeText(T?.none, 10, "-0o10") + NBKAssertDecodeText(T?.none, 10, "-0b10") + } + + func testDecodingStringsWithAndWithoutSign() { + NBKAssertDecodeText(T( 1234567890), 10, "1234567890") + NBKAssertDecodeText(T( 1234567890), 10, "+1234567890") + NBKAssertDecodeText(T(-1234567890), 10, "-1234567890") + } + + func testDecodingStrategyIsCaseInsensitive() { + NBKAssertDecodeText(T(0xabcdef), 16, "abcdef") + NBKAssertDecodeText(T(0xABCDEF), 16, "ABCDEF") + NBKAssertDecodeText(T(0xaBcDeF), 16, "aBcDeF") + NBKAssertDecodeText(T(0xAbCdEf), 16, "AbCdEf") + } + + func testDecodingUnalignedStringsIsOK() { + NBKAssertDecodeText(T(1), 10, "1") + NBKAssertDecodeText(T(1), 16, "1") + } + + func testDecodingPrefixingZerosHasNoEffect() { + let zero = String(repeating: "0", count: bit256) + "0" + let one = String(repeating: "0", count: bit256) + "1" + + for radix in 02 ... 36 { + NBKAssertDecodeText(T(0), radix, zero) + NBKAssertDecodeText(T(1), radix, one ) + } + } + + func testDecodingInvalidCharactersReturnsNil() { + NBKAssertDecodeText(T?.none, 16, "/") + NBKAssertDecodeText(T?.none, 16, "G") + + NBKAssertDecodeText(T?.none, 10, "/") + NBKAssertDecodeText(T?.none, 10, ":") + + NBKAssertDecodeText(T?.none, 10, String(repeating: "1", count: 19) + "/") + NBKAssertDecodeText(T?.none, 10, String(repeating: "1", count: 19) + ":") + } + + func testDecodingStringsWithoutDigitsReturnsNil() { + NBKAssertDecodeText(T?.none, 10, "") + NBKAssertDecodeText(T?.none, 10, "+") + NBKAssertDecodeText(T?.none, 10, "-") + NBKAssertDecodeText(T?.none, 10, "~") + + NBKAssertDecodeText(T?.none, 16, "") + NBKAssertDecodeText(T?.none, 16, "+") + NBKAssertDecodeText(T?.none, 16, "-") + NBKAssertDecodeText(T?.none, 16, "~") + } + + func testDecodingValuesOutsideOfRepresentableRangeReturnsNil() { + let positive = "+" + String(repeating: "1", count: bit256) + let negative = "-" + String(repeating: "1", count: bit256) + + for radix in 02 ... 36 { + XCTAssertNotNil(T(positive, radix: radix)) + XCTAssertNotNil(T(negative, radix: radix)) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Encode + //=------------------------------------------------------------------------= + + func testEncodingRadix02() { + NBKAssertEncodeText(min256, 02, false, "-1" + String(repeating: "0", count: bit256 / 1 - 1)) + NBKAssertEncodeText(max256, 02, false, String(repeating: "1", count: bit256 / 1 - 1)) + } + + func testEncodingRadix03() { + NBKAssertEncodeText(min256, 03, false,"-21221122120" + + "12222212211110210202220000022211002111211122012220" + + "12122202101121021220012201000100012101202122101020" + + "20010111121211022111102111220220201211121011101022" ) + NBKAssertEncodeText(max256, 03, false, "21221122120" + + "12222212211110210202220000022211002111211122012220" + + "12122202101121021220012201000100012101202122101020" + + "20010111121211022111102111220220201211121011101021" ) + } + + func testEncodingRadix04() { + NBKAssertEncodeText(min256, 04, false, "-2" + String(repeating: "0", count: bit256 / 2 - 1)) + NBKAssertEncodeText(max256, 04, false, "1" + String(repeating: "3", count: bit256 / 2 - 1)) + } + + func testEncodingRadix08() { + NBKAssertEncodeText(min256, 08, false, "-1" + String(repeating: "0", count: 85)) + NBKAssertEncodeText(max256, 08, false, String(repeating: "7", count: 85)) + } + + func testEncodingRadix10() { + NBKAssertEncodeText(min256, 10, false, "-57896044618658097711785492504343953926634992332820282019728792003956564819968") + NBKAssertEncodeText(max256, 10, false, "57896044618658097711785492504343953926634992332820282019728792003956564819967") + } + + func testEncodingRadix16() { + NBKAssertEncodeText(min256, 16, false, "-8" + String(repeating: "0", count: bit256 / 4 - 1)) + NBKAssertEncodeText(min256, 16, true , "-8" + String(repeating: "0", count: bit256 / 4 - 1)) + NBKAssertEncodeText(max256, 16, false, "7" + String(repeating: "f", count: bit256 / 4 - 1)) + NBKAssertEncodeText(max256, 16, true , "7" + String(repeating: "F", count: bit256 / 4 - 1)) + } + + func testEncodingRadix32() { + NBKAssertEncodeText(min256, 32, false, "-1" + String(repeating: "0", count: 51)) + NBKAssertEncodeText(min256, 32, true , "-1" + String(repeating: "0", count: 51)) + NBKAssertEncodeText(max256, 32, false, String(repeating: "v", count: 51)) + NBKAssertEncodeText(max256, 32, true , String(repeating: "V", count: 51)) + } + + func testEncodingRadix36() { + NBKAssertEncodeText(min256, 36, false, "-36ukv65j19b11mbvjyfui963v4my01krth19g3r3bk1ojlrwu8") + NBKAssertEncodeText(min256, 36, true , "-36UKV65J19B11MBVJYFUI963V4MY01KRTH19G3R3BK1OJLRWU8") + NBKAssertEncodeText(max256, 36, false, "36ukv65j19b11mbvjyfui963v4my01krth19g3r3bk1ojlrwu7") + NBKAssertEncodeText(max256, 36, true , "36UKV65J19B11MBVJYFUI963V4MY01KRTH19G3R3BK1OJLRWU7") + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Text x UIntXL +//*============================================================================* + +final class NBKFlexibleWidthTestsOnTextAsUIntXL: XCTestCase { + + typealias T = UIntXL + + //=------------------------------------------------------------------------= + // MARK: State + //=------------------------------------------------------------------------= + + let bit256 = 256 + let min256 = T.min256 + let max256 = T.max256 + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testFromDescription() { + NBKAssertFromDescription(T?( 10), "10") + NBKAssertFromDescription(T?( 10), "+10") + NBKAssertFromDescription(T?(nil), "-10") + NBKAssertFromDescription(T?(nil), " 10") + NBKAssertFromDescription(T?(nil), "0x10") + NBKAssertFromDescription(T?(nil), "+0x10") + NBKAssertFromDescription(T?(nil), "-0x10") + NBKAssertFromDescription(T?(nil), " 0x10") + } + + func testInstanceDescriptionUsesRadix10() { + XCTAssertEqual("10", T(10).description) + XCTAssertEqual("10", String(describing: T(10))) + } + + func testMetaTypeDescriptionIsSimple() { + XCTAssertEqual("UIntXL", T.description) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Decode + //=------------------------------------------------------------------------= + + func testDecodingRadix02() { + NBKAssertDecodeText(min256, 02, "0") + NBKAssertDecodeText(max256, 02, String(repeating: "1", count: bit256 / 1)) + } + + func testDecodingRadix03() { + NBKAssertDecodeText(min256, 03, "0" ) + NBKAssertDecodeText(max256, 03, "120220022011" + + "02222202122221121112210000122122012000200021102211" + + "02022111210012120210102102000200101210112021202111" + + "10021000020122121222212000211211110200012022202120" ) + } + + func testDecodingRadix04() { + NBKAssertDecodeText(min256, 04, "0") + NBKAssertDecodeText(max256, 04, String(repeating: "3", count: bit256 / 2)) + } + + func testDecodingRadix08() { + NBKAssertDecodeText(min256, 08, "0") + NBKAssertDecodeText(max256, 08, "1" + String(repeating: "7", count: 85)) + } + + func testDecodingRadix10() { + NBKAssertDecodeText(min256, 10, "0") + NBKAssertDecodeText(max256, 10, "115792089237316195423570985008687907853269984665640564039457584007913129639935") + } + + func testDecodingRadix16() { + NBKAssertDecodeText(min256, 16, "0") + NBKAssertDecodeText(max256, 16, String(repeating: "f", count: bit256 / 4)) + } + + func testDecodingRadix32() { + NBKAssertDecodeText(min256, 32, "0") + NBKAssertDecodeText(max256, 32, "1" + String(repeating: "v", count: 51)) + } + + func testDecodingRadix36() { + NBKAssertDecodeText(min256, 36, "0") + NBKAssertDecodeText(max256, 36, "6dp5qcb22im238nr3wvp0ic7q99w035jmy2iw7i6n43d37jtof") + } + + func testDecodingRadixLiteralAsNumber() { + NBKAssertDecodeText(T(33), 36, "0x") + NBKAssertDecodeText(T(24), 36, "0o") + NBKAssertDecodeText(T(11), 36, "0b") + + NBKAssertDecodeText(T(33), 36, "+0x") + NBKAssertDecodeText(T(24), 36, "+0o") + NBKAssertDecodeText(T(11), 36, "+0b") + } + + func testDecodingRadixLiteralAsRadixReturnsNil() { + NBKAssertDecodeText(T?.none, 10, "0x10") + NBKAssertDecodeText(T?.none, 10, "0o10") + NBKAssertDecodeText(T?.none, 10, "0b10") + + NBKAssertDecodeText(T?.none, 10, "+0x10") + NBKAssertDecodeText(T?.none, 10, "+0o10") + NBKAssertDecodeText(T?.none, 10, "+0b10") + } + + func testDecodingStringsWithAndWithoutSign() { + NBKAssertDecodeText(T(1234567890), 10, "1234567890") + NBKAssertDecodeText(T(1234567890), 10, "+1234567890") + } + + func testDecodingStrategyIsCaseInsensitive() { + NBKAssertDecodeText(T(0xabcdef), 16, "abcdef") + NBKAssertDecodeText(T(0xABCDEF), 16, "ABCDEF") + NBKAssertDecodeText(T(0xaBcDeF), 16, "aBcDeF") + NBKAssertDecodeText(T(0xAbCdEf), 16, "AbCdEf") + } + + func testDecodingUnalignedStringsIsOK() { + NBKAssertDecodeText(T(1), 10, "1") + NBKAssertDecodeText(T(1), 16, "1") + } + + func testDecodingPrefixingZerosHasNoEffect() { + let zero = String(repeating: "0", count: bit256) + "0" + let one = String(repeating: "0", count: bit256) + "1" + + for radix in 02 ... 36 { + NBKAssertDecodeText(T(0), radix, zero) + NBKAssertDecodeText(T(1), radix, one ) + } + } + + func testDecodingInvalidCharactersReturnsNil() { + NBKAssertDecodeText(T?.none, 16, "/") + NBKAssertDecodeText(T?.none, 16, "G") + + NBKAssertDecodeText(T?.none, 10, "/") + NBKAssertDecodeText(T?.none, 10, ":") + + NBKAssertDecodeText(T?.none, 10, String(repeating: "1", count: 19) + "/") + NBKAssertDecodeText(T?.none, 10, String(repeating: "1", count: 19) + ":") + } + + func testDecodingStringsWithoutDigitsReturnsNil() { + NBKAssertDecodeText(T?.none, 10, "") + NBKAssertDecodeText(T?.none, 10, "+") + NBKAssertDecodeText(T?.none, 10, "-") + NBKAssertDecodeText(T?.none, 10, "~") + + NBKAssertDecodeText(T?.none, 16, "") + NBKAssertDecodeText(T?.none, 16, "+") + NBKAssertDecodeText(T?.none, 16, "-") + NBKAssertDecodeText(T?.none, 16, "~") + } + + func testDecodingValuesOutsideOfRepresentableRangeReturnsNil() { + let positive = "+" + String(repeating: "1", count: bit256 + 1) + let negative = "-" + String(repeating: "1", count: 1) + + for radix in 02 ... 36 { + XCTAssertNotNil(T(positive, radix: radix)) + NBKAssertDecodeText(T?.none, radix, negative) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Encode + //=------------------------------------------------------------------------= + + func testEncodingRadix02() { + NBKAssertEncodeText(min256, 02, false, "0") + NBKAssertEncodeText(max256, 02, false, String(repeating: "1", count: bit256 / 1)) + } + + func testEncodingRadix03() { + NBKAssertEncodeText(min256, 03, false, "0" ) + NBKAssertEncodeText(max256, 03, false,"120220022011" + + "02222202122221121112210000122122012000200021102211" + + "02022111210012120210102102000200101210112021202111" + + "10021000020122121222212000211211110200012022202120" ) + } + + func testEncodingRadix04() { + NBKAssertEncodeText(min256, 04, false, "0") + NBKAssertEncodeText(max256, 04, false, String(repeating: "3", count: bit256 / 2)) + } + + func testEncodingRadix08() { + NBKAssertEncodeText(min256, 08, false, "0") + NBKAssertEncodeText(max256, 08, false, "1" + String(repeating: "7", count: 85)) + } + + func testEncodingRadix10() { + NBKAssertEncodeText(min256, 10, false, "0") + NBKAssertEncodeText(max256, 10, false, "115792089237316195423570985008687907853269984665640564039457584007913129639935") + } + + func testEncodingRadix16() { + NBKAssertEncodeText(min256, 16, false, "0") + NBKAssertEncodeText(min256, 16, true , "0") + NBKAssertEncodeText(max256, 16, false, String(repeating: "f", count: bit256 / 4)) + NBKAssertEncodeText(max256, 16, true , String(repeating: "F", count: bit256 / 4)) + } + + func testEncodingRadix32() { + NBKAssertEncodeText(min256, 32, false, "0") + NBKAssertEncodeText(min256, 32, true , "0") + NBKAssertEncodeText(max256, 32, false, "1" + String(repeating: "v", count: 51)) + NBKAssertEncodeText(max256, 32, true , "1" + String(repeating: "V", count: 51)) + } + + func testEncodingRadix36() { + NBKAssertEncodeText(min256, 36, false, "0") + NBKAssertEncodeText(min256, 36, true , "0") + NBKAssertEncodeText(max256, 36, false, "6dp5qcb22im238nr3wvp0ic7q99w035jmy2iw7i6n43d37jtof") + NBKAssertEncodeText(max256, 36, true , "6DP5QCB22IM238NR3WVP0IC7Q99W035JMY2IW7I6N43D37JTOF") + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Text x For Each Radix x UIntXL +//*============================================================================* + +final class NBKFlexibleWidthTestsOnTextForEachRadixAsUIntXL: XCTestCase { + + typealias T = UIntXL + + //=------------------------------------------------------------------------= + // MARK: State + //=------------------------------------------------------------------------= + + var radix: Int = 10 + var x64 = (UInt64(), UInt64(), UInt64(), UInt64()) + var txt = (String()) + + //=------------------------------------------------------------------------= + // MARK: Set Up, Tear Down + //=------------------------------------------------------------------------= + + override func setUp() { + self.radix = 10 + self.x64.0 = UInt64() + self.x64.1 = UInt64() + self.x64.2 = UInt64() + self.x64.3 = UInt64() + self.txt = String() + } + + override func tearDown() { + let decoded = T(x64: [x64.0, x64.1, x64.2, x64.3]) + var encoded = String(self.txt.drop{ $0 == "0" }) + if encoded.isEmpty { + encoded.append(contentsOf: self.txt.suffix(1)) + } + + NBKAssertDecodeText(decoded, self.radix, txt) + NBKAssertDecodeText(decoded, self.radix, encoded) + NBKAssertEncodeText(decoded, self.radix, true, encoded.uppercased()) + NBKAssertEncodeText(decoded, self.radix, false, encoded.lowercased()) + } + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testRadix02Top() { + self.radix = 02 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 1111111111111110111111011111110011111011111110101111100111111000\ + 1111011111110110111101011111010011110011111100101111000111110000\ + 1110111111101110111011011110110011101011111010101110100111101000\ + 1110011111100110111001011110010011100011111000101110000111100000 + """ + } + + func testRadix02Bottom() { + self.radix = 02 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0001111100011110000111010001110000011011000110100001100100011000\ + 0001011100010110000101010001010000010011000100100001000100010000\ + 0000111100001110000011010000110000001011000010100000100100001000\ + 0000011100000110000001010000010000000011000000100000000100000000 + """ + } + + //=----( 03 )--------------------------------------------------------------= + + func testRadix03Top() { + self.radix = 03 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000000000000000000000000000001202200212221120001222202211110211\ + 2122212010220102122202121101120111112200201101101222110200202110\ + 0220201022101000210101202220120002101202101120201012012212012002 + """ + } + + func testRadix03Bottom() { + self.radix = 03 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0000000000000000000000000000000012210112211101210122010202201212\ + 2200112221212101221211222010022020100210220200100011100100222021\ + 2000121220012212111000111110212212201000011111112211120210102101 + """ + } + + //=----( 04 )--------------------------------------------------------------= + + func testRadix04Top() { + self.radix = 04 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 3333333233313330332333223321332033133312331133103303330233013300\ + 3233323232313230322332223221322032133212321132103203320232013200 + """ + } + + func testRadix04Bottom() { + self.radix = 04 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0133013201310130012301220121012001130112011101100103010201010100\ + 0033003200310030002300220021002000130012001100100003000200010000 + """ + } + + //=----( 05 )--------------------------------------------------------------= + + func testRadix05Top() { + self.radix = 05 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000000000000000012224200130200441041444042343242340402322434230\ + 2203100014323101131021202442142123441124102101232423332422334024 + """ + } + + func testRadix05Bottom() { + self.radix = 05 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0000000000000000000424043311031102404011202312202132022104340041\ + 4431003121344314114341012313341313423214420311244321214230031301 + """ + } + + //=----( 06 )--------------------------------------------------------------= + + func testRadix06Top() { + self.radix = 06 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000000000000000000000000000102141010531040333210533123011525130\ + 3433311132532415235332533224344010103324220312020213104050423132 + """ + } + + func testRadix06Bottom() { + self.radix = 06 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0000000000000000000000000000004353050531332542114015530141512113\ + 1210015440102001011522210020211244125255022541512055450000200144 + """ + } + + //=----( 07 )--------------------------------------------------------------= + + func testRadix07Top() { + self.radix = 07 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000000000000000000000000000000000001305333621612661215031353503\ + 1603616341660421351201115002605631306624232666655230226263060363 + """ + } + + func testRadix07Bottom() { + self.radix = 07 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0000000000000000000000000000000000000114142063044505436351120634\ + 3333263503132100565010106005630324255134635601621240633030645403 + """ + } + + //=----( 08 )--------------------------------------------------------------= + + func testRadix08Top() { + self.radix = 08 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000000000000000000000000000000000000000001777767737637376574770\ + 7577336575171762743703577356675472765351721637467136234370560740 + """ + } + + func testRadix08Bottom() { + self.radix = 08 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0000000000000000000000000000000000000000000174360721603306414430\ + 0561302505011422042100170340641402605011020034060120200300400400 + """ + } + + //=----( 09 )--------------------------------------------------------------= + + func testRadix09Top() { + self.radix = 09 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000000000000000000000000000000000000000000000052625846058684424\ + 7876381258254151448064135842067326638330711686502352346635185162 + """ + } + + func testRadix09Bottom() { + self.radix = 09 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0000000000000000000000000000000000000000000000005715741718122655\ + 8048777185486326632382030431086760556185430443785630144484523371 + """ + } + + //=----( 10 )--------------------------------------------------------------= + + func testRadix10Top() { + self.radix = 10 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000000000000000000000000000000000000000000000000011579030850545\ + 5567723526024286119531261069242336003260839703036409543150199264 + """ + } + + func testRadix10Bottom() { + self.radix = 10 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0000000000000000000000000000000000000000000000000001407490462640\ + 1341155369551180448584754667373453244490859944217516317499064576 + """ + } + + //=----( 11 )--------------------------------------------------------------= + + func testRadix11Top() { + self.radix = 11 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000000000000000000000000000000000000000000000000000010019774172\ + 675069499548a05a7794803603a4157366204225264092700a8157a30a948720 + """ + } + + func testRadix11Bottom() { + self.radix = 11 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0000000000000000000000000000000000000000000000000000001380227a9a\ + 3a453071005401517000a3500756239a46834284766655651370a28295109a06 + """ + } + + //=----( 12 )--------------------------------------------------------------= + + func testRadix12Top() { + self.radix = 12 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000000000000000000000000000000000000000000000000000000029231468\ + 41b6624b4657b76b759711256462675490811529026b8b03507956b900591aa8 + """ + } + + func testRadix12Bottom() { + self.radix = 12 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 000000000000000000000000000000000000000000000000000000000404b13b\ + 22595a847521b8ab337490660a0b7439b1495399a8b2918a9521301732309054 + """ + } + + //=----( 13 )--------------------------------------------------------------= + + func testRadix13Top() { + self.radix = 13 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000000000000000000000000000000000000000000000000000000000178a92\ + 980701228a277594134c94bb7165a938c70c03a705750115a339820831351c78 + """ + } + + func testRadix13Bottom() { + self.radix = 13 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 00000000000000000000000000000000000000000000000000000000000268a5\ + 1c5770b549c51487a17526804a0a14c0c44bbc981573456a275580297a4a7834 + """ + } + + //=----( 14 )--------------------------------------------------------------= + + func testRadix14Top() { + self.radix = 14 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000000000000000000000000000000000000000000000000000000000001c38\ + 14cbd353812dca285cc376972998797340345da539017abd8236000c88ca00da + """ + } + + func testRadix14Bottom() { + self.radix = 14 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0000000000000000000000000000000000000000000000000000000000000329\ + 76a45325cd6dda6ac91cb8c9bccbbc61488833c2225a774c2da97ab4d4565d3a + """ + } + + //=----( 15 )--------------------------------------------------------------= + + func testRadix15Top() { + self.radix = 15 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000000000000000000000000000000000000000000000000000000000000042\ + 314e1223518107b1362e160a5ad29226b4e3e2d35ea57996aaa3242db02966ae + """ + } + + func testRadix15Bottom() { + self.radix = 15 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0000000000000000000000000000000000000000000000000000000000000007\ + 864d3605e05bd91d94b651ccc4e3078d6edc902745e03953a310b0de5c602701 + """ + } + + //=----( 16 )--------------------------------------------------------------= + + func testRadix16Top() { + self.radix = 16 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e0 + """ + } + + func testRadix16Bottom() { + self.radix = 16 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100 + """ + } + + //=----( 17 )--------------------------------------------------------------= + + func testRadix17Top() { + self.radix = 17 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 05g7d81gc01cdbf42565444eaa12342c35gd9f66bbg36c8d8841baa7a8faab0e + """ + } + + func testRadix17Bottom() { + self.radix = 17 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 00c5b2gcge3c140g4d527274dgd5cg7g58babg3e21bg76739a559151527ce653 + """ + } + + //=----( 18 )--------------------------------------------------------------= + + func testRadix18Top() { + self.radix = 18 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0031fhf5dce9fgc12bg164e9h35028896f83ddhh8be5286c3e9h17360bg1bg32 + """ + } + + func testRadix18Bottom() { + self.radix = 18 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0006e51f0da7284a3bb14747c33cgb1hfa3120c549aec7hh58g39hg075a02c3a + """ + } + + //=----( 19 )--------------------------------------------------------------= + + func testRadix19Top() { + self.radix = 19 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 000237ibab6cg652id30fgh76hdai93dhfh7dhagfdc5eb7f782c55d551ed74g6 + """ + } + + func testRadix19Bottom() { + self.radix = 19 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 000050cae6cb5210060eg1g2iicc8e689a04g25829g2f5bc8c84ea4a8a1348f4 + """ + } + + //=----( 20 )--------------------------------------------------------------= + + func testRadix20Top() { + self.radix = 20 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 000020392d6ac9d1jd12d3a88c61i7ba748483ai05hf66c6a7g42977fbe8ei34 + """ + } + + func testRadix20Bottom() { + self.radix = 20 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 000004hd5e33e5189jajhc248c2a513ae74fba267d1b3d1743i8ebgb30i9318g + """ + } + + //=----( 21 )--------------------------------------------------------------= + + func testRadix21Top() { + self.radix = 21 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000027gdj7593kjg0f1c5cga4aca1e1d5f08h72cebhcbc1c6cek06cf13eaddh + """ + } + + func testRadix21Bottom() { + self.radix = 21 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0000006124cec92463a07f87dgg069g06715hcg4j03fha2f1gafce80g895g09a + """ + } + + //=----( 22 )--------------------------------------------------------------= + + func testRadix22Top() { + self.radix = 22 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000003b5jk54f19beiidebchgec3ffc28aggdd74h75ijdc00i4ea0ji14954c0 + """ + } + + func testRadix22Bottom() { + self.radix = 22 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 000000098djlg8ll6ge66j798kd129gf43e7c6586a31h5a25adg2l78kj3a82b6 + """ + } + + //=----( 23 )--------------------------------------------------------------= + + func testRadix23Top() { + self.radix = 23 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 000000069a79baglcjbdblbk5111bb46b66g2b7a2f596763kmm7c3hbl336kl14 + """ + } + + func testRadix23Bottom() { + self.radix = 23 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 00000000hl580j6lii99g9c5137ji22ab5i41mba3lh6091cakd4h6llil689h12 + """ + } + + //=----( 24 )--------------------------------------------------------------= + + func testRadix24Top() { + self.radix = 24 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 00000000e4eikjgk76jj7i2fbn6ihk3ngef39fb00gjl3086em4k7g3ag5647hh8 + """ + } + + func testRadix24Bottom() { + self.radix = 24 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 000000001h9gbi9kc8ig99kj5lil4in9d6e81la5d0h872fff899ebj57j88732g + """ + } + + //=----( 25 )--------------------------------------------------------------= + + func testRadix25Top() { + self.radix = 25 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 000000001cea1fa4l49o4dnedkkdcnmfc3509hg185baem9bdo6e5b1dediecike + """ + } + + func testRadix25Bottom() { + self.radix = 25 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0000000004e4i6362kk6ad7abh2b4j0log0gbjn96nl1d8j88mh9m36enbbmf381 + """ + } + + //=----( 26 )--------------------------------------------------------------= + + func testRadix26Top() { + self.radix = 26 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000000004dd8f12of8578gn3cho4kjg1nm4ck49ihk7nahjpeie4d78426fjja8 + """ + } + + func testRadix26Bottom() { + self.radix = 26 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0000000000e7a4822n1867n87cpm330nai4o7gj05b5j013bb0in29cncoodh584 + """ + } + + //=----( 27 )--------------------------------------------------------------= + + func testRadix27Top() { + self.radix = 27 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000000000fo7qe0hopd7gqfbj7q7m4jdh2445pb279oj8a0lakof2akafj55n52 + """ + } + + func testRadix27Bottom() { + self.radix = 27 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 00000000001p4pcg5j6ogq1hng5neo9oj2bk10d12on0go5nd0dcnnj04demflba + """ + } + + //=----( 28 )--------------------------------------------------------------= + + func testRadix28Top() { + self.radix = 28 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 000000000028lp360pqr9fgjmgalj15e5kknmk8pd61irgj23bbe6nbafahp3e6o + """ + } + + func testRadix28Bottom() { + self.radix = 28 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 000000000007odiqi7ipkbell34qeml609e642lhrao5n03422ik497coam17kmo + """ + } + + //=----( 29 )--------------------------------------------------------------= + + func testRadix29Top() { + self.radix = 29 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 00000000000acrhqlapaaob766is1eng6erp522m0f5opigage3d3j4k7f9n8ff2 + """ + } + + func testRadix29Bottom() { + self.radix = 29 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0000000000017nr4pcg1heg13dh8cgggmn4q34frqm65gn8ec0j45591bmqfhffb + """ + } + + //=----( 30 )--------------------------------------------------------------= + + func testRadix30Top() { + self.radix = 30 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 000000000001nmr6nq4fe87dse4p4i0ama7co4moqch8081liop9spg2kl9rn95e + """ + } + + func testRadix30Bottom() { + self.radix = 30 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0000000000006g1ldfsednredtimcop3b5l3q70e4kitjnhrn4eql74ecaf5j1mg + """ + } + + //=----( 31 )--------------------------------------------------------------= + + func testRadix31Top() { + self.radix = 31 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 000000000000a30ts5ohp5e917o3nehp8urue2rb4e97icid1me5tcmpil25fi6m + """ + } + + func testRadix31Bottom() { + self.radix = 31 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 000000000000171hhf8063e3r4a99sra00a157pihstia75dmk5kfae5nnn9ab6l + """ + } + + //=----( 32 )--------------------------------------------------------------= + + func testRadix32Top() { + self.radix = 32 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000000000001vvuvnufnunpv3rvdtfkufpf3s7ftrmupqvat7kefpn5sjhu5of0 + """ + } + + func testRadix32Bottom() { + self.radix = 32 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 00000000000007ou3ke1m6gp30bhc58k2c91240f1o6go2oa1440e1g50g1g4080 + """ + } + + //=----( 33 )--------------------------------------------------------------= + + func testRadix33Top() { + self.radix = 33 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000000000000dodf9g17rn5pvw3et1k184sgnb11u6u7uhk2n9b3bhtfwrh14fb + """ + } + + func testRadix33Bottom() { + self.radix = 33 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 00000000000001m3p6weqc5jk0wsb37sv08ileepww3jad5cr0cfhd0g1aq8in3s + """ + } + + //=----( 34 )--------------------------------------------------------------= + + func testRadix34Top() { + self.radix = 34 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 00000000000003304fs1ae3ixjsrahw1k6lt33dlup2jc54b1p3xxaghpss3swhe + """ + } + + func testRadix34Bottom() { + self.radix = 34 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 00000000000000cpwunuqgcm028uqxuqmjst7gk65egpsowcgixwuci6x899aa2k + """ + } + + //=----( 35 )--------------------------------------------------------------= + + func testRadix35Top() { + self.radix = 35 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 00000000000000pcyhqj7yk3vq8j4l4vfa7wes91wah4p1y3op2k48s4pv0y189o + """ + } + + func testRadix35Bottom() { + self.radix = 35 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0000000000000032wujn2mg481jyhidxmv5271ucr21qfj9jdvqm429mwneu6b2v + """ + } + + //=----( 36 )--------------------------------------------------------------= + + func testRadix36Top() { + self.radix = 36 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 000000000000006dp15j43ld5l8i7wvimlj7kxgbfxkxkgmo66lge382296ouqjk + """ + } + + func testRadix36Bottom() { + self.radix = 36 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 000000000000000rx55jlhq7obx1pvd9861yo6c11bed0cd8s8wz2hpvczt00c1s + """ + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Text x Assertions +//*============================================================================* + +private func NBKAssertFromDescription( +_ integer: T?, _ description: String, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + XCTAssertEqual(T(description), integer, file: file, line: line) + XCTAssertEqual(T(description, radix: 10), integer, file: file, line: line) +} + +private func NBKAssertDecodeText ( +_ integer: T?, _ radix: Int, _ text: String, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + if radix == 10 { + XCTAssertEqual(T(text), integer, file: file, line: line) + } + //=------------------------------------------= + XCTAssertEqual(T(text, radix: radix), integer, file: file, line: line) +} + +private func NBKAssertEncodeText( +_ integer: T, _ radix: Int, _ uppercase: Bool, _ text: String, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + if radix == 10, uppercase == false { + XCTAssertEqual(String(integer), text, file: file, line: line) + XCTAssertEqual(integer.description, text, file: file, line: line) + + #warning("TODO: requires division or issue #80") + // XCTAssertEqual(integer.description(), text, file: file, line: line) + } + //=------------------------------------------= + XCTAssertEqual(String(integer, radix: radix, uppercase: uppercase), text, file: file, line: line) + XCTAssertEqual(integer.description(radix: radix, uppercase: uppercase), text, file: file, line: line) +} + +#endif diff --git a/Tests/NBKTwosComplementKitTests/IntXL+Words.swift b/Tests/NBKTwosComplementKitTests/IntXL+Words.swift index 587010a6..0ca40164 100644 --- a/Tests/NBKTwosComplementKitTests/IntXL+Words.swift +++ b/Tests/NBKTwosComplementKitTests/IntXL+Words.swift @@ -42,6 +42,14 @@ final class NBKFlexibleWidthTestsOnWordsAsIntXL: XCTestCase { NBKAssertWords(T(words:[1, 2, 0, 0]), [1, 2 ]) NBKAssertWords(T(words:[1, 2, 3, 0]), [1, 2, 3 ]) NBKAssertWords(T(words:[1, 2, 3, 4]), [1, 2, 3, 4]) + + NBKAssertWords(T(sign: .plus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as W)), [~0, ~0, ~0, ~0/2 + 0 ] as W) // 4 + NBKAssertWords(T(sign: .plus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as W)), [ 0, 0, 0, ~0/2 + 1, 0] as W) // 5 + NBKAssertWords(T(sign: .plus, magnitude: M(words:[ 1, 0, 0, ~0/2 + 1] as W)), [ 1, 0, 0, ~0/2 + 1, 0] as W) // 5 + + NBKAssertWords(T(sign: .minus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as W)), [ 1, 0, 0, ~0/2 + 1 ] as W) // 4 + NBKAssertWords(T(sign: .minus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as W)), [ 0, 0, 0, ~0/2 + 1 ] as W) // 4 + NBKAssertWords(T(sign: .minus, magnitude: M(words:[ 1, 0, 0, ~0/2 + 1] as W)), [~0, ~0, ~0, ~0/2 + 0, ~0] as W) // 5 } func testWordsX64() throws { From 5bcf82546b2f7099d116387893a7b75c6e087486 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Thu, 14 Sep 2023 11:17:11 +0200 Subject: [PATCH 065/133] [2's rework] Day 3 (#44). --- .../IntXL+Addition+Digit.swift | 52 +- .../NBKTwosComplementKit/IntXL+Addition.swift | 64 +- .../IntXL+Comparisons.swift | 14 +- .../IntXL+Complements.swift | 32 +- Sources/NBKTwosComplementKit/IntXL+Data.swift | 26 + .../IntXL+Division+Digit.swift | 2 +- .../NBKTwosComplementKit/IntXL+Literals.swift | 59 +- .../NBKTwosComplementKit/IntXL+Logic.swift | 62 +- .../IntXL+Multiplication+Digit.swift | 26 +- .../IntXL+Multiplication.swift | 59 +- .../NBKTwosComplementKit/IntXL+Numbers.swift | 12 +- .../NBKTwosComplementKit/IntXL+Shifts.swift | 24 +- .../IntXL+Storage+Normalization.swift | 123 ++++ .../IntXL+Storage+Size.swift | 47 ++ .../NBKTwosComplementKit/IntXL+Storage.swift | 218 +++---- .../IntXL+Subtraction+Digit.swift | 50 +- .../IntXL+Subtraction.swift | 70 ++- Sources/NBKTwosComplementKit/IntXL+Text.swift | 20 +- .../NBKTwosComplementKit/IntXL+Update.swift | 4 +- .../IntXL+Words+Pointers.swift | 2 +- .../NBKTwosComplementKit/IntXL+Words.swift | 12 +- Sources/NBKTwosComplementKit/IntXL.swift | 186 +----- .../NBKTwosComplementKit/IntXLOrUIntXL.swift | 121 ++++ .../IntXLOrUIntXLStorage.swift | 66 ++ .../IntXL+Addition.swift | 220 +++++++ .../IntXL+Comparisons.swift | 593 ++++++++++++++++++ .../IntXL+Multiplication.swift | 172 +++++ .../IntXL+Subtraction.swift | 275 ++++++++ 28 files changed, 2151 insertions(+), 460 deletions(-) create mode 100644 Sources/NBKTwosComplementKit/IntXL+Data.swift create mode 100644 Sources/NBKTwosComplementKit/IntXL+Storage+Normalization.swift create mode 100644 Sources/NBKTwosComplementKit/IntXL+Storage+Size.swift create mode 100644 Sources/NBKTwosComplementKit/IntXLOrUIntXL.swift create mode 100644 Sources/NBKTwosComplementKit/IntXLOrUIntXLStorage.swift create mode 100644 Tests/NBKTwosComplementKitTests/IntXL+Addition.swift create mode 100644 Tests/NBKTwosComplementKitTests/IntXL+Comparisons.swift create mode 100644 Tests/NBKTwosComplementKitTests/IntXL+Multiplication.swift create mode 100644 Tests/NBKTwosComplementKitTests/IntXL+Subtraction.swift diff --git a/Sources/NBKTwosComplementKit/IntXL+Addition+Digit.swift b/Sources/NBKTwosComplementKit/IntXL+Addition+Digit.swift index fd800ad4..ed8e2bf0 100644 --- a/Sources/NBKTwosComplementKit/IntXL+Addition+Digit.swift +++ b/Sources/NBKTwosComplementKit/IntXL+Addition+Digit.swift @@ -38,11 +38,32 @@ extension IntXL { // MARK: Transformations //=------------------------------------------------------------------------= - @_disfavoredOverload @inlinable public mutating func add(_ other: Int, at index: Int) { - fatalError("TODO") + @_disfavoredOverload @inlinable public mutating func add(_ other: Digit, at index: Int) { + if other.isZero { return } + //=--------------------------------------= + let lhsIsLessThanZero = self .isLessThanZero + let rhsIsLessThanZero = other.isLessThanZero + let lhsSign = UInt(repeating: lhsIsLessThanZero) + let rhsSign = UInt(repeating: rhsIsLessThanZero) + //=--------------------------------------= + self.storage.resize(minCount: index + 1) + var carry = self.storage.elements[index].addReportingOverflow(UInt(bitPattern: other)) + var index = self.storage.elements.index(after: index) + //=-------------------------------------= + if carry != rhsIsLessThanZero { + let predicate = carry + let increment = UInt(bitPattern: carry ? 1 : -1) + + while index != self.storage.elements.endIndex && carry == predicate { + carry = self.storage.elements[index].addReportingOverflow(increment) + self.storage.elements.formIndex(after: &index) + } + } + //=--------------------------------------= + self.storage.normalize(appending: lhsSign &+ rhsSign &+ UInt(bit: carry)) } - @_disfavoredOverload @inlinable public func adding(_ other: Int, at index: Int) -> Self { + @_disfavoredOverload @inlinable public func adding(_ other: Digit, at index: Int) -> Self { var result = self result.add(other, at: index) return result as Self @@ -60,7 +81,15 @@ extension UIntXL { //=------------------------------------------------------------------------= @_disfavoredOverload @inlinable public mutating func add(_ other: UInt, at index: Int) { - fatalError("TODO") + defer { + Swift.assert(self.storage.isNormal) + } + //=--------------------------------------= + if other.isZero { return } + //=--------------------------------------= + self.storage.resize(minCount: index + 1) + let overflow = self.storage.add(other, plus: false, at: index) + if overflow { self.storage.append(1 as UInt) } } @_disfavoredOverload @inlinable public func adding(_ other: UInt, at index: Int) -> Self { @@ -69,3 +98,18 @@ extension UIntXL { return result as Self } } + +//*============================================================================* +// MARK: * NBK x Flexible Width x Addition x Digit x UIntXL x Storage +//*============================================================================* + +extension UIntXL.Storage { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @_disfavoredOverload @inlinable mutating func add(_ other: UInt, plus carry: Bool, at index: Int) -> Bool { + NBK.incrementSufficientUnsignedInteger(&self.elements, by: other, plus: carry, at: index).overflow + } +} diff --git a/Sources/NBKTwosComplementKit/IntXL+Addition.swift b/Sources/NBKTwosComplementKit/IntXL+Addition.swift index 064d9dbe..6122feea 100644 --- a/Sources/NBKTwosComplementKit/IntXL+Addition.swift +++ b/Sources/NBKTwosComplementKit/IntXL+Addition.swift @@ -39,7 +39,44 @@ extension IntXL { //=------------------------------------------------------------------------= @inlinable public mutating func add(_ other: Self, at index: Int) { - fatalError("TODO") + //=--------------------------------------= + if other.isZero { return } + //=--------------------------------------= + let lhsIsLessThanZero = self .isLessThanZero + let rhsIsLessThanZero = other.isLessThanZero + let lhsSign = UInt(repeating: lhsIsLessThanZero) + let rhsSign = UInt(repeating: rhsIsLessThanZero) + //=--------------------------------------= + self.storage.resize(minCount: other.storage.elements.count + index) + //=--------------------------------------= + var carry = false + var lhsIndex = index + var rhsIndex = other.storage.elements.startIndex + //=----------------------------------= + while rhsIndex < other.storage.elements.endIndex { + var lhsElement = self .storage.elements[lhsIndex] + let rhsElement = other.storage.elements[rhsIndex] + + let a = lhsElement.addReportingOverflow(rhsElement) + let b = lhsElement.addReportingOverflow(UInt(bit: carry)) + carry = a || b + + self .storage.elements[lhsIndex] = lhsElement + self .storage.elements.formIndex(after: &lhsIndex) + other.storage.elements.formIndex(after: &rhsIndex) + } + //=--------------------------------------= + if carry != rhsIsLessThanZero { + let predicate = carry + let increment = UInt(bitPattern: carry ? 1 : -1) + + while lhsIndex < self.storage.elements.endIndex && carry == predicate { + carry = self.storage.elements[lhsIndex].addReportingOverflow(increment) + self.storage.elements.formIndex(after: &lhsIndex) + } + } + //=--------------------------------------= + self.storage.normalize(appending: lhsSign &+ rhsSign &+ UInt(bit: carry)) } @inlinable public func adding(_ other: Self, at index: Int) -> Self { @@ -60,7 +97,15 @@ extension UIntXL { //=------------------------------------------------------------------------= @inlinable public mutating func add(_ other: Self, at index: Int) { - fatalError("TODO") + defer { + Swift.assert(self.storage.isNormal) + } + //=--------------------------------------= + if other.isZero { return } + //=--------------------------------------= + self.storage.resize(minCount: other.storage.elements.count + index) + let overflow = self.storage.add(other.storage, plus: false, at: index) + if overflow { self.storage.append(1 as UInt) } } @inlinable public func adding(_ other: Self, at index: Int) -> Self { @@ -69,3 +114,18 @@ extension UIntXL { return result as Self } } + +//*============================================================================* +// MARK: * NBK x Flexible Width x Addition x UIntXL x Storage +//*============================================================================* + +extension UIntXL.Storage { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable mutating func add(_ other: Self, plus carry: Bool, at index: Int) -> Bool { + NBK.incrementSufficientUnsignedInteger(&self.elements, by: other.elements, plus: carry, at: index).overflow + } +} diff --git a/Sources/NBKTwosComplementKit/IntXL+Comparisons.swift b/Sources/NBKTwosComplementKit/IntXL+Comparisons.swift index be9f8278..9142e6d5 100644 --- a/Sources/NBKTwosComplementKit/IntXL+Comparisons.swift +++ b/Sources/NBKTwosComplementKit/IntXL+Comparisons.swift @@ -171,13 +171,21 @@ extension UIntXL { // MARK: * NBK x Flexible Width x Comparisons x Storage //*============================================================================* -extension StorageXL { +extension PrivateIntXLOrUIntXLStorage { //=------------------------------------------------------------------------= // MARK: Accessors //=------------------------------------------------------------------------= - @inlinable func isLessThanZero(isSigned: Bool) -> Bool { - isSigned && self.last.mostSignificantBit + @inlinable static var isSigned: Bool { + Digit.isSigned + } + + //=------------------------------------------------------------------------= + // MARK: Accessors + //=------------------------------------------------------------------------= + + @inlinable public var isLessThanZero: Bool { + Self.isSigned && self.last.mostSignificantBit } } diff --git a/Sources/NBKTwosComplementKit/IntXL+Complements.swift b/Sources/NBKTwosComplementKit/IntXL+Complements.swift index c0c676b9..181bf19b 100644 --- a/Sources/NBKTwosComplementKit/IntXL+Complements.swift +++ b/Sources/NBKTwosComplementKit/IntXL+Complements.swift @@ -21,7 +21,7 @@ extension PrivateIntXLOrUIntXL { @inlinable public mutating func formOnesComplement() { self.storage.formOnesComplement() - Self.normalize(&self.storage) + self.storage.normalize() } @inlinable public func onesComplement() -> Self { @@ -33,7 +33,7 @@ extension PrivateIntXLOrUIntXL { //=------------------------------------------------------------------------= @inlinable public mutating func formTwosComplement() { - defer{ Self.normalize(&self.storage) } + defer{ self.storage.normalize() } return self.storage.formTwosComplement() } @@ -44,8 +44,8 @@ extension PrivateIntXLOrUIntXL { } @inlinable public mutating func formTwosComplementReportingOverflow() -> Bool { - defer{ Self.normalize(&self.storage) } - return self.storage.formTwosComplementReportingOverflow(as: Digit.self) + defer{ self.storage.normalize() } + return self.storage.formTwosComplementReportingOverflow() } @inlinable public func twosComplementReportingOverflow() -> PVO { @@ -55,8 +55,8 @@ extension PrivateIntXLOrUIntXL { } @inlinable public mutating func formTwosComplementSubsequence(_ carry: Bool) -> Bool { - defer{ Self.normalize(&self.storage) } - return self.storage.formTwosComplementSubsequence(carry, as: Digit.self) + defer{ self.storage.normalize() } + return self.storage.formTwosComplementSubsequence(carry) } @inlinable public func twosComplementSubsequence(_ carry: Bool) -> PVO { @@ -78,13 +78,12 @@ extension IntXL { @inlinable public var magnitude: Magnitude { let isLessThanZero = self.isLessThanZero - var storage = self.storage + var storage = Magnitude.Storage(bitPattern: self.storage) if isLessThanZero { storage.formTwosComplement() } - Magnitude.normalize(&storage) - return Magnitude(unchecked: storage) + return Magnitude(normalizing: storage) } //=------------------------------------------------------------------------= @@ -104,7 +103,7 @@ extension IntXL { // MARK: * NBK x Flexible Width x Complements x Storage //*============================================================================* -extension StorageXL { +extension PrivateIntXLOrUIntXLStorage { //=------------------------------------------------------------------------= // MARK: Details x One's Complement @@ -125,21 +124,20 @@ extension StorageXL { //=------------------------------------------------------------------------= @inlinable mutating func formTwosComplement() { - _ = self.formTwosComplementSubsequence(true, as: UInt.self) + _ = self.formTwosComplementSubsequence(true) } - @inlinable mutating func formTwosComplementReportingOverflow(as digit: T.Type) -> Bool where T: NBKCoreInteger { - self.formTwosComplementSubsequence(true, as: T.self) + @inlinable mutating func formTwosComplementReportingOverflow() -> Bool { + self.formTwosComplementSubsequence(true) } - @inlinable mutating func formTwosComplementSubsequence(_ carry: Bool, as digit: T.Type) -> Bool where T: NBKCoreInteger { + @inlinable mutating func formTwosComplementSubsequence(_ carry: Bool) -> Bool { var carry = carry - let lastIndex = self.elements.index(before: self.elements.endIndex) - for index in self.elements.startIndex ..< lastIndex { + for index in self.elements.indices.dropLast() { carry = self.elements[index].formTwosComplementSubsequence(carry) } - return self[lastIndex,as: T.self].formTwosComplementSubsequence(carry) + return self.tail.formTwosComplementSubsequence(carry) } } diff --git a/Sources/NBKTwosComplementKit/IntXL+Data.swift b/Sources/NBKTwosComplementKit/IntXL+Data.swift new file mode 100644 index 00000000..d6561014 --- /dev/null +++ b/Sources/NBKTwosComplementKit/IntXL+Data.swift @@ -0,0 +1,26 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x Data x Storage +//*============================================================================* + +extension PrivateIntXLOrUIntXLStorage { + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + /// Creates a new instance with unsafe access to its uninitialized memory. + @inlinable static func uninitialized(count: Int, body: (inout NBK.UnsafeMutableWords) -> Void) -> Self { + Self(Elements(unsafeUninitializedCapacity: count) { body(&$0); $1 = count }) + } +} diff --git a/Sources/NBKTwosComplementKit/IntXL+Division+Digit.swift b/Sources/NBKTwosComplementKit/IntXL+Division+Digit.swift index 76c28a2b..45e8c6b3 100644 --- a/Sources/NBKTwosComplementKit/IntXL+Division+Digit.swift +++ b/Sources/NBKTwosComplementKit/IntXL+Division+Digit.swift @@ -78,7 +78,7 @@ extension UIntXL { //=------------------------------------------------------------------------= @_disfavoredOverload @inlinable public mutating func formQuotientWithRemainderReportingOverflow(dividingBy other: Digit) -> PVO { - defer{ Self.normalize(&self.storage) } + defer{ self.storage.normalize() } return NBK.formQuotientWithRemainderReportingOverflowAsLenientUnsignedInteger(of: &self.storage.elements, dividingBy: other) } } diff --git a/Sources/NBKTwosComplementKit/IntXL+Literals.swift b/Sources/NBKTwosComplementKit/IntXL+Literals.swift index 6279d68b..102d7612 100644 --- a/Sources/NBKTwosComplementKit/IntXL+Literals.swift +++ b/Sources/NBKTwosComplementKit/IntXL+Literals.swift @@ -10,65 +10,10 @@ import NBKCoreKit //*============================================================================* -// MARK: * NBK x Flexible Width x Literals x IntXL +// MARK: * NBK x Flexible Width x Literals //*============================================================================* -extension IntXL { - - //=-------------------------------------------------------------------------= - // MARK: Details x Integer Literal Type - //=-------------------------------------------------------------------------= - - @inlinable public init(integerLiteral source: Digit) { - self.init(digit: source) - } - - //=------------------------------------------------------------------------= - // MARK: Details x String Literal Type - //=------------------------------------------------------------------------= - - /// Creates a new instance from the given string literal. - /// - /// The string literal may contain a plus or minus sign (+ or -), followed by - /// an optional radix indicator (0b, 0o or 0x), then one or more numeric digits - /// (0-9) or letters (a-z or A-Z). If the string literal uses an invalid format, - /// or its value cannot be represented, a runtime error may occur. - /// - /// ``` - /// ┌───────── → ─────────────┐ - /// │ literal │ self │ - /// ├───────── → ─────────────┤ - /// │ "123" │ Int256( 123) │ - /// │ "+0x123" │ Int256( 291) │ - /// │ "-0x123" │ Int256(-291) │ - /// │ "~OX123" │ error │ - /// └───────── → ─────────────┘ - /// ``` - /// - /// - Note: The decoding strategy is case insensitive. - /// - @inlinable public init(stringLiteral source: StaticString) { - if let value = Self(exactlyStringLiteral: source) { self = value } else { - preconditionFailure("\(Self.description) cannot represent \(source)") - } - } - - @inlinable init?(exactlyStringLiteral source: StaticString) { - if let value: Self = source.withUTF8Buffer({ utf8 in - let components = NBK.makeIntegerComponentsByDecodingRadix(utf8: utf8) - let radix = NBK.AnyRadixSolution(components.radix) - let digits = NBK.UnsafeUTF8(rebasing: components.body ) - guard let magnitude = Magnitude(digits: digits, radix: radix) else { return nil } - return Self(sign: components.sign, magnitude: magnitude) - }){ self = value } else { return nil } - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Literals x Unsigned -//*============================================================================* - -extension UIntXL { +extension IntXLOrUIntXL { //=-------------------------------------------------------------------------= // MARK: Details x Integer Literal Type diff --git a/Sources/NBKTwosComplementKit/IntXL+Logic.swift b/Sources/NBKTwosComplementKit/IntXL+Logic.swift index e0b38c8e..e60f5eb5 100644 --- a/Sources/NBKTwosComplementKit/IntXL+Logic.swift +++ b/Sources/NBKTwosComplementKit/IntXL+Logic.swift @@ -35,7 +35,8 @@ extension IntXL { //=------------------------------------------------------------------------= @inlinable public static func &=(lhs: inout Self, rhs: Self) { - lhs.upsizeThenFormInIntersection(extending: rhs, each: &) + lhs.storage.upsizeThenFormInIntersection(extending: rhs.storage, each: &) + lhs.storage.normalize() } //=------------------------------------------------------------------------= @@ -43,7 +44,8 @@ extension IntXL { //=------------------------------------------------------------------------= @inlinable public static func |=(lhs: inout Self, rhs: Self) { - lhs.upsizeThenFormInIntersection(extending: rhs, each: |) + lhs.storage.upsizeThenFormInIntersection(extending: rhs.storage, each: |) + lhs.storage.normalize() } //=------------------------------------------------------------------------= @@ -51,24 +53,8 @@ extension IntXL { //=------------------------------------------------------------------------= @inlinable public static func ^=(lhs: inout Self, rhs: Self) { - lhs.upsizeThenFormInIntersection(extending: rhs, each: ^) - } - - //=------------------------------------------------------------------------= - // MARK: Transformations x Private - //=------------------------------------------------------------------------= - - @inlinable mutating func upsizeThenFormInIntersection(extending other: Self, each element: (UInt, UInt) -> UInt) { - let lhsSign = UInt(repeating: self.isLessThanZero) - self.storage.resize(minCount: other.storage.elements.count, appending: lhsSign) - self.withUnsafeMutableBufferPointer { lhs in - other.withUnsafeBufferPointer { rhs in - let rhsSign = UInt(repeating: rhs.last!.mostSignificantBit) - for index in lhs.indices { - lhs[index] = element(lhs[index], index < rhs.endIndex ? rhs[index] : rhsSign) - } - } - } + lhs.storage.upsizeThenFormInIntersection(extending: rhs.storage, each: ^) + lhs.storage.normalize() } } @@ -84,7 +70,7 @@ extension UIntXL { @inlinable public static func &=(lhs: inout Self, rhs: Self) { lhs.storage.downsizeThenFormInIntersection(with: rhs.storage, each: &) - Self.normalize(&lhs.storage) + lhs.storage.normalize() } //=------------------------------------------------------------------------= @@ -92,8 +78,8 @@ extension UIntXL { //=------------------------------------------------------------------------= @inlinable public static func |=(lhs: inout Self, rhs: Self) { - lhs.storage.upsizeThenFormInIntersection(with: rhs.storage, appending: 0 as UInt, each: |) - Swift.assert(Self.isNormal(lhs.storage)) + lhs.storage.upsizeThenFormInIntersection(with: rhs.storage, each: |) + Swift.assert(lhs.storage.isNormal) } //=------------------------------------------------------------------------= @@ -101,8 +87,8 @@ extension UIntXL { //=------------------------------------------------------------------------= @inlinable public static func ^=(lhs: inout Self, rhs: Self) { - lhs.storage.upsizeThenFormInIntersection(with: rhs.storage, appending: 0 as UInt, each: ^) - Swift.assert(Self.isNormal(lhs.storage)) + lhs.storage.upsizeThenFormInIntersection(with: rhs.storage, each: ^) + Swift.assert(lhs.storage.isNormal) } } @@ -110,31 +96,43 @@ extension UIntXL { // MARK: * NBK x Flexible Width x Logic x Storage //*============================================================================* -extension StorageXL { +extension PrivateIntXLOrUIntXLStorage { //=------------------------------------------------------------------------= // MARK: Transformations //=------------------------------------------------------------------------= - @inlinable mutating func upsizeThenFormInIntersection(with other: Self, appending word: UInt, each element: (UInt, UInt) -> UInt) { - self.resize(minCount: other.elements.count, appending: word) + @inlinable mutating func downsizeThenFormInIntersection(with other: Self, each element: (UInt, UInt) -> UInt) { + self.resize(maxCount: other.elements.count) self.elements.withUnsafeMutableBufferPointer { lhs in other.elements.withUnsafeBufferPointer { rhs in - for index in rhs.indices { + for index in lhs.indices { lhs[index] = element(lhs[index], rhs[index]) } } } } - @inlinable mutating func downsizeThenFormInIntersection(with other: Self, each element: (UInt, UInt) -> UInt) { - self.resize(maxCount: other.elements.count) + @inlinable mutating func upsizeThenFormInIntersection(with other: Self, each element: (UInt, UInt) -> UInt) { + self.resize(minCount: other.elements.count) self.elements.withUnsafeMutableBufferPointer { lhs in other.elements.withUnsafeBufferPointer { rhs in - for index in lhs.indices { + for index in rhs.indices { lhs[index] = element(lhs[index], rhs[index]) } } } } + + @inlinable mutating func upsizeThenFormInIntersection(extending other: Self, each element: (UInt, UInt) -> UInt) { + self.resize(minCount: other.elements.count) + self.elements.withUnsafeMutableBufferPointer { lhs in + other.elements.withUnsafeBufferPointer { rhs in + let rhsSign = UInt(repeating: Self.isSigned && rhs.last!.mostSignificantBit) + for index in lhs.indices { + lhs[index] = element(lhs[index], index < rhs.endIndex ? rhs[index] : rhsSign) + } + } + } + } } diff --git a/Sources/NBKTwosComplementKit/IntXL+Multiplication+Digit.swift b/Sources/NBKTwosComplementKit/IntXL+Multiplication+Digit.swift index a57f3517..2fc78880 100644 --- a/Sources/NBKTwosComplementKit/IntXL+Multiplication+Digit.swift +++ b/Sources/NBKTwosComplementKit/IntXL+Multiplication+Digit.swift @@ -20,11 +20,21 @@ extension IntXL { //=------------------------------------------------------------------------= @_disfavoredOverload @inlinable public static func *=(lhs: inout Self, rhs: Digit) { - fatalError("TODO") + lhs = lhs * rhs } @_disfavoredOverload @inlinable public static func *(lhs: Self, rhs: Digit) -> Self { - fatalError("TODO") + let lhsIsLessThanZero: Bool = lhs.isLessThanZero + let rhsIsLessThanZero: Bool = rhs.isLessThanZero + var minus = lhsIsLessThanZero != rhsIsLessThanZero + //=--------------------------------------= + var product = lhs.magnitude * rhs.magnitude + //=--------------------------------------= + if minus { + minus = product.storage.formTwosComplementSubsequence(minus) + } + //=--------------------------------------= + return Self(normalizing: Storage(bitPattern: product.storage)) } } @@ -52,15 +62,15 @@ extension UIntXL { @_disfavoredOverload @inlinable public mutating func multiply(by multiplicand: Digit, add addend: Digit) { defer { - Swift.assert(Self.isNormal(self.storage)) + Swift.assert(self.storage.isNormal) } //=--------------------------------------= if multiplicand.isZero { return self.update(addend) } //=--------------------------------------= - self.storage.reserveCapacity(self.storage.elements.count + 1) - let overflow = self.storage.multiplyAsUnsigned(by: multiplicand, add: addend) + self.storage.reserveCapacity(self.storage.elements.count + 1) + let overflow = self.storage.multiply(by: multiplicand, add: addend) if !overflow.isZero { self.storage.append(overflow) } @@ -74,16 +84,16 @@ extension UIntXL { } //*============================================================================* -// MARK: * NBK x Flexible Width x Multiplication x Digit x Storage +// MARK: * NBK x Flexible Width x Multiplication x Digit x UIntXL x Storage //*============================================================================* -extension StorageXL { +extension UIntXL.Storage { //=------------------------------------------------------------------------= // MARK: Transformations //=------------------------------------------------------------------------= - @_disfavoredOverload @inlinable mutating func multiplyAsUnsigned(by other: UInt, add addend: UInt) -> UInt { + @_disfavoredOverload @inlinable mutating func multiply(by other: UInt, add addend: UInt) -> UInt { NBK.multiplyFullWidthLenientUnsignedInteger(&self.elements, by: other, add: addend) } } diff --git a/Sources/NBKTwosComplementKit/IntXL+Multiplication.swift b/Sources/NBKTwosComplementKit/IntXL+Multiplication.swift index 4dd0b591..d62e5136 100644 --- a/Sources/NBKTwosComplementKit/IntXL+Multiplication.swift +++ b/Sources/NBKTwosComplementKit/IntXL+Multiplication.swift @@ -20,11 +20,21 @@ extension IntXL { //=------------------------------------------------------------------------= @inlinable public static func *=(lhs: inout Self, rhs: Self) { - fatalError("TODO") + lhs = lhs * rhs } @inlinable public static func *(lhs: Self, rhs: Self) -> Self { - fatalError("TODO") + let lhsIsLessThanZero: Bool = lhs.isLessThanZero + let rhsIsLessThanZero: Bool = rhs.isLessThanZero + var minus = lhsIsLessThanZero != rhsIsLessThanZero + //=--------------------------------------= + var product = lhs.magnitude * rhs.magnitude + //=--------------------------------------= + if minus { + minus = product.storage.formTwosComplementSubsequence(minus) + } + //=--------------------------------------= + return Self(normalizing: Storage(bitPattern: product.storage)) } } @@ -39,10 +49,51 @@ extension UIntXL { //=------------------------------------------------------------------------= @inlinable public static func *=(lhs: inout Self, rhs: Self) { - fatalError("TODO") + lhs = lhs * rhs } @inlinable public static func *(lhs: Self, rhs: Self) -> Self { - fatalError("TODO") + Self(normalizing: lhs.storage.multipliedFullWidth(by: rhs.storage)) + } +} + +//*============================================================================* +// MARK: * NBK x Resizable Width x Multiplication x UIntXL x Storage +//*============================================================================* + +extension UIntXL.Storage { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable func multipliedFullWidth(by multiplicand: Self) -> Self { + self.multipliedFullWidthByNaiveMethod(by: multiplicand, adding: UInt.zero) + } + + @inlinable func multipliedFullWidthByNaiveMethod(by multiplicand: Self, adding addend: UInt) -> Self { + Self.uninitialized(count: self.elements.count + multiplicand.elements.count) { product in + //=----------------------------------= + // de/init: pointee is trivial + //=----------------------------------= + product.initialize(repeating: UInt.zero) + //=----------------------------------= + var overflow = addend as UInt + for lhsIndex in self.elements.indices { + let outer = self.elements[lhsIndex] + + for rhsIndex in multiplicand.elements.indices { + let inner = multiplicand.elements[rhsIndex] + var subproduct = outer.multipliedFullWidth(by: inner) + + overflow = UInt(bit: subproduct.low.addReportingOverflow(overflow)) + overflow &+= UInt(bit: product[lhsIndex + rhsIndex].addReportingOverflow(subproduct.low)) + overflow &+= subproduct.high + } + + product[lhsIndex + multiplicand.elements.count] = overflow + overflow = UInt.zero + } + } } } diff --git a/Sources/NBKTwosComplementKit/IntXL+Numbers.swift b/Sources/NBKTwosComplementKit/IntXL+Numbers.swift index a42e8c3a..c7631aca 100644 --- a/Sources/NBKTwosComplementKit/IntXL+Numbers.swift +++ b/Sources/NBKTwosComplementKit/IntXL+Numbers.swift @@ -46,7 +46,7 @@ extension IntXL { if !T.isSigned, storage.last.mostSignificantBit { storage.append(0 as UInt) } else { - Self.normalize(&storage) + storage.normalize() } self.init(unchecked: storage) @@ -84,15 +84,15 @@ extension IntXL { //=------------------------------------------------------------------------= @inlinable public init(sign: FloatingPointSign, magnitude: Magnitude) { - var storage = magnitude.storage as Storage + var unsigned = magnitude.storage as Magnitude.Storage var isLessThanZero = (sign == FloatingPointSign.minus) - if isLessThanZero { - isLessThanZero = !storage.formTwosComplementReportingOverflow(as: UInt.self) + isLessThanZero = !unsigned.formTwosComplementReportingOverflow() } - Self.normalize(&storage, appending: UInt(repeating: isLessThanZero)) - self.init(unchecked: storage) + var signed = Storage(bitPattern: unsigned) + signed.normalize(appending: UInt(repeating: isLessThanZero)) + self.init(unchecked: signed) } } diff --git a/Sources/NBKTwosComplementKit/IntXL+Shifts.swift b/Sources/NBKTwosComplementKit/IntXL+Shifts.swift index 860b6692..ef57d110 100644 --- a/Sources/NBKTwosComplementKit/IntXL+Shifts.swift +++ b/Sources/NBKTwosComplementKit/IntXL+Shifts.swift @@ -93,7 +93,7 @@ extension PrivateIntXLOrUIntXL { /// @inlinable mutating func bitshiftLeft(words: Int, atLeastOneBit bits: Int) { defer { - Swift.assert(Self.isNormal(self.storage)) + Swift.assert(self.storage.isNormal) } //=--------------------------------------= if self.isZero { return } @@ -110,7 +110,7 @@ extension PrivateIntXLOrUIntXL { /// @inlinable mutating func bitshiftLeft(atLeastOneWord words: Int) { defer { - Swift.assert(Self.isNormal(self.storage)) + Swift.assert(self.storage.isNormal) } //=--------------------------------------= if self.isZero { return } @@ -201,7 +201,7 @@ extension PrivateIntXLOrUIntXL { /// @inlinable mutating func bitshiftRight(words: Int, atLeastOneBit bits: Int) { defer { - Swift.assert(Self.isNormal(self.storage)) + Swift.assert(self.storage.isNormal) } //=--------------------------------------= let rollover = Int(bit: 0 <= bits + self.leadingZeroBitCount - UInt.bitWidth) @@ -211,7 +211,7 @@ extension PrivateIntXLOrUIntXL { return self.update(Digit(repeating: self.isLessThanZero)) } //=--------------------------------------= - self.storage.bitshiftRight(isSigned: Self.isSigned, words: words, atLeastOneBit: bits) + self.storage.bitshiftRight(words: words, atLeastOneBit: bits) self.storage.resize(maxCount: maxCount) } @@ -222,14 +222,14 @@ extension PrivateIntXLOrUIntXL { /// @inlinable mutating func bitshiftRight(atLeastOneWord words: Int) { defer { - Swift.assert(Self.isNormal(self.storage)) + Swift.assert(self.storage.isNormal) } //=--------------------------------------= if self.storage.elements.count <= words { return self.update(Digit(repeating: self.isLessThanZero)) } //=--------------------------------------= - self.storage.bitshiftRight(isSigned: Self.isSigned, atLeastOneWord: words) + self.storage.bitshiftRight(atLeastOneWord: words) self.storage.resize(maxCount: self.storage.elements.count - words) } } @@ -241,7 +241,7 @@ extension PrivateIntXLOrUIntXL { // MARK: + Left //=----------------------------------------------------------------------------= -extension StorageXL { +extension PrivateIntXLOrUIntXLStorage { /// Performs a left shift. /// @@ -271,7 +271,7 @@ extension StorageXL { // MARK: + Right //=----------------------------------------------------------------------------= -extension StorageXL { +extension PrivateIntXLOrUIntXLStorage { //=------------------------------------------------------------------------= // MARK: Transformations @@ -283,8 +283,8 @@ extension StorageXL { /// - words: `1 <= words < self.endIndex` /// - bits: `0 <= bits  < UInt.bitWidth` /// - @inlinable mutating func bitshiftRight(isSigned: Bool, words: Int, atLeastOneBit bits: Int) { - let environment = isSigned && self.last.mostSignificantBit + @inlinable mutating func bitshiftRight(words: Int, atLeastOneBit bits: Int) { + let environment = self.isLessThanZero as Bool self.elements.withUnsafeMutableBufferPointer { NBK.bitshiftRightAsFixedLimbsCodeBlock(&$0, environment: environment, limbs: words, atLeastOneBit: bits) } @@ -295,8 +295,8 @@ extension StorageXL { /// - Parameters: /// - words: `1 <= words < self.endIndex` /// - @inlinable mutating func bitshiftRight(isSigned: Bool, atLeastOneWord words: Int) { - let environment = isSigned && self.last.mostSignificantBit + @inlinable mutating func bitshiftRight(atLeastOneWord words: Int) { + let environment = self.isLessThanZero as Bool self.elements.withUnsafeMutableBufferPointer { NBK.bitshiftRightAsFixedLimbsCodeBlock(&$0, environment: environment, atLeastOneLimb: words) } diff --git a/Sources/NBKTwosComplementKit/IntXL+Storage+Normalization.swift b/Sources/NBKTwosComplementKit/IntXL+Storage+Normalization.swift new file mode 100644 index 00000000..eccbd403 --- /dev/null +++ b/Sources/NBKTwosComplementKit/IntXL+Storage+Normalization.swift @@ -0,0 +1,123 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x Storage x Normalization +//*============================================================================* + +extension PrivateIntXLOrUIntXLStorage { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable mutating func normalize(update value: Digit) { + self.elements.replaceSubrange(self.elements.indices, with: CollectionOfOne(UInt(bitPattern: value))) + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Storage x Normalization x IntXL +//*============================================================================* + +extension IntXL.Storage { + + //=------------------------------------------------------------------------= + // MARK: Accessors + //=------------------------------------------------------------------------= + + @inlinable var isNormal: Bool { + if self.elements.count == 1 { return true } + + let tail = Int(bitPattern: self.elements[self.elements.count - 1]) + let head = Int(bitPattern: self.elements[self.elements.count - 2]) + + let sign = tail >> Int.bitWidth + + return !(sign == tail && sign == head >> Int.bitWidth) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable mutating func normalize() { + Swift.assert(!self.elements.isEmpty) + //=--------------------------------------= + var position = self.elements.index(before: self.elements.endIndex) + let mostSignificantBit = self.elements[position].mostSignificantBit + let sign = UInt(repeating: mostSignificantBit) + //=--------------------------------------= + // TODO: measure combined loop conditions + //=--------------------------------------= + backwards: while position > self.elements.startIndex { + if self.elements[position] != sign { return } + self.elements.formIndex(before: &position) + if self.elements[position].mostSignificantBit != mostSignificantBit { return } + self.elements.removeLast() + } + } + + @inlinable mutating func normalize(appending element: UInt) { + Swift.assert(!self.elements.isEmpty) + //=--------------------------------------= + var position = self.elements.index(before: self.elements.endIndex) + let mostSignificantBit = self.elements[position].mostSignificantBit + let sign = UInt(repeating: mostSignificantBit) + //=--------------------------------------= + if element != sign { + return self.elements.append(element) + } + //=--------------------------------------= + // TODO: measure combined loop conditions + //=--------------------------------------= + backwards: while position > self.elements.startIndex { + if self.elements[position] != sign { return } + self.elements.formIndex(before: &position) + if self.elements[position].mostSignificantBit != mostSignificantBit { return } + self.elements.removeLast() + } + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Storage x Normalization x UIntXL +//*============================================================================* + +extension UIntXL.Storage { + + //=------------------------------------------------------------------------= + // MARK: Accessors + //=------------------------------------------------------------------------= + + @inlinable var isNormal: Bool { + self.elements.count == 1 || !self.elements.last!.isZero + } + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable mutating func normalize() { + Swift.assert(!self.elements.isEmpty) + //=--------------------------------------= + var position = self.elements.index(before: self.elements.endIndex) + let sign = UInt(repeating: false) + //=--------------------------------------= + // TODO: measure combined loop conditions + //=--------------------------------------= + backwards: while position > self.elements.startIndex { + if self.elements[position] != sign { return } + self.elements.formIndex(before: &position) + self.elements.removeLast() + } + } +} diff --git a/Sources/NBKTwosComplementKit/IntXL+Storage+Size.swift b/Sources/NBKTwosComplementKit/IntXL+Storage+Size.swift new file mode 100644 index 00000000..0f0318b3 --- /dev/null +++ b/Sources/NBKTwosComplementKit/IntXL+Storage+Size.swift @@ -0,0 +1,47 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x Storage x Size +//*============================================================================* + +extension PrivateIntXLOrUIntXLStorage { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable mutating func append(_ word: UInt) { + self.elements.append(word) + } + + @inlinable mutating func resize(maxCount: Int) { + precondition(maxCount.isMoreThanZero) + if self.elements.count > maxCount { + self.elements.removeSubrange(maxCount...) + } + } + + @inlinable mutating func resize(minCount: Int, appending element: UInt) { + self.reserveCapacity(minCount) + appending: while self.elements.count < minCount { + self.elements.append(element) + } + } + + @inlinable mutating func resize(minCount: Int) { + self.resize(minCount: minCount, appending: UInt(repeating: self.isLessThanZero)) + } + + @inlinable mutating func reserveCapacity(_ minCapacity: Int) { + self.elements.reserveCapacity(minCapacity) + } +} diff --git a/Sources/NBKTwosComplementKit/IntXL+Storage.swift b/Sources/NBKTwosComplementKit/IntXL+Storage.swift index facfd703..5f14e280 100644 --- a/Sources/NBKTwosComplementKit/IntXL+Storage.swift +++ b/Sources/NBKTwosComplementKit/IntXL+Storage.swift @@ -9,20 +9,6 @@ import NBKCoreKit -//*============================================================================* -// MARK: * NBK x Flexible Width x Storage -//*============================================================================* - -extension PrivateIntXLOrUIntXL { - - //=------------------------------------------------------------------------= - // MARK: Details x Normalization - //=------------------------------------------------------------------------= - - @inlinable static func normalize(_ storage: inout Storage, update value: Digit) { - storage.elements.replaceSubrange(storage.elements.indices, with: CollectionOfOne(UInt(bitPattern: value))) - } -} //*============================================================================* // MARK: * NBK x Flexible Width x Storage x IntXL @@ -30,56 +16,61 @@ extension PrivateIntXLOrUIntXL { extension IntXL { - //=------------------------------------------------------------------------= - // MARK: Details x Normalization - //=------------------------------------------------------------------------= - - @inlinable static func isNormal(_ storage: Storage) -> Bool { - if storage.elements.count == 1 { return true } + //*========================================================================* + // MARK: * Storage + //*========================================================================* + + /// IntXL's and UIntXL's underlying storage. + /// + /// It has fixed-width semantics unless stated otherwise. + /// + @frozen @usableFromInline struct Storage: PrivateIntXLOrUIntXLStorage { - let tail = Int(bitPattern: storage.elements[storage.elements.count - 1]) - let head = Int(bitPattern: storage.elements[storage.elements.count - 2]) + @usableFromInline typealias Digit = IntXL.Digit - let sign = tail >> Int.bitWidth + @usableFromInline typealias Elements = NBKFlexibleWidth.Elements + + //=--------------------------------------------------------------------= + // MARK: State + //=--------------------------------------------------------------------= - return !(sign == tail && sign == head >> Int.bitWidth) - } - - @inlinable static func normalize(_ storage: inout Storage) { - Swift.assert(!storage.elements.isEmpty) - //=--------------------------------------= - var position = storage.elements.index(before: storage.elements.endIndex) - let mostSignificantBit = storage.elements[position].mostSignificantBit - let sign = UInt(repeating: mostSignificantBit) - //=--------------------------------------= - // TODO: measure combined loop conditions - //=--------------------------------------= - backwards: while position > storage.elements.startIndex { - if storage.elements[position] != sign { return } - storage.elements.formIndex(before: &position) - if storage.elements[position].mostSignificantBit != mostSignificantBit { return } - storage.elements.removeLast() + /// A collection of unsigned integers. + /// + /// It must be `nonempty` at the start and end of each access. + /// + @usableFromInline var elements: Elements + + //=--------------------------------------------------------------------= + // MARK: Initializers + //=--------------------------------------------------------------------= + + @inlinable init(_ elements: Elements) { + self.elements = elements + precondition(!self.elements.isEmpty) } - } - - @inlinable static func normalize(_ storage: inout Storage, appending word: UInt) { - Swift.assert(!storage.elements.isEmpty) - //=--------------------------------------= - var position = storage.elements.index(before: storage.elements.endIndex) - let mostSignificantBit = storage.elements[position].mostSignificantBit - let sign = UInt(repeating: mostSignificantBit) - //=--------------------------------------= - if word != sign { - return storage.elements.append(word) + + @inlinable init(unchecked elements: Elements) { + self.elements = elements + Swift.assert(!self.elements.isEmpty) } - //=--------------------------------------= - // TODO: measure combined loop conditions - //=--------------------------------------= - backwards: while position > storage.elements.startIndex { - if storage.elements[position] != sign { return } - storage.elements.formIndex(before: &position) - if storage.elements[position].mostSignificantBit != mostSignificantBit { return } - storage.elements.removeLast() + + @inlinable init(nonemptying elements: Elements) { + self.elements = elements + if self.elements.isEmpty { + self.elements.append(0) + } + } + + //=--------------------------------------------------------------------= + // MARK: Details x Bit Pattern + //=--------------------------------------------------------------------= + + @inlinable init(bitPattern: UIntXL.Storage) { + self.init(unchecked: bitPattern.elements) + } + + @inlinable var bitPattern: UIntXL.Storage { + UIntXL.Storage(unchecked: self.elements) } } } @@ -90,64 +81,61 @@ extension IntXL { extension UIntXL { - //=------------------------------------------------------------------------= - // MARK: Details x Normalization - //=------------------------------------------------------------------------= - - @inlinable static func isNormal(_ storage: Storage) -> Bool { - storage.elements.count == 1 || !storage.elements.last!.isZero - } - - @inlinable static func normalize(_ storage: inout Storage) { - Swift.assert(!storage.elements.isEmpty) - //=--------------------------------------= - var position = storage.elements.index(before: storage.elements.endIndex) - let sign = UInt(repeating: false) - //=--------------------------------------= - // TODO: measure combined loop conditions - //=--------------------------------------= - backwards: while position > storage.elements.startIndex { - if storage.elements[position] != sign { return } - storage.elements.formIndex(before: &position) - storage.elements.removeLast() - } - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Storage x StorageXL -//*============================================================================* + //*========================================================================* + // MARK: * Storage + //*========================================================================* -extension StorageXL { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable mutating func reserveCapacity(_ minCapacity: Int) { - self.elements.reserveCapacity(minCapacity) - } - - @inlinable mutating func append(_ word: UInt) { - self.elements.append(word) - } - - @inlinable mutating func resize(maxCount: Int) { - precondition(maxCount.isMoreThanZero) - if self.elements.count > maxCount { - self.elements.removeSubrange(maxCount...) + /// IntXL's and UIntXL's underlying storage. + /// + /// It has fixed-width semantics unless stated otherwise. + /// + @frozen @usableFromInline struct Storage: PrivateIntXLOrUIntXLStorage { + + @usableFromInline typealias Digit = UIntXL.Digit + + @usableFromInline typealias Elements = NBKFlexibleWidth.Elements + + //=--------------------------------------------------------------------= + // MARK: State + //=--------------------------------------------------------------------= + + /// A collection of unsigned integers. + /// + /// It must be `nonempty` at the start and end of each access. + /// + @usableFromInline var elements: Elements + + //=--------------------------------------------------------------------= + // MARK: Initializers + //=--------------------------------------------------------------------= + + @inlinable init(_ elements: Elements) { + self.elements = elements + precondition(!self.elements.isEmpty) } - } - - @inlinable mutating func resize(minCount: Int, appending word: UInt) { - self.reserveCapacity(minCount) - appending: while self.elements.count < minCount { - self.elements.append(word) + + @inlinable init(unchecked elements: Elements) { + self.elements = elements + Swift.assert(!self.elements.isEmpty) + } + + @inlinable init(nonemptying elements: Elements) { + self.elements = elements + if self.elements.isEmpty { + self.elements.append(0) + } + } + + //=--------------------------------------------------------------------= + // MARK: Details x Bit Pattern + //=--------------------------------------------------------------------= + + @inlinable init(bitPattern: UIntXL.Storage) { + self = bitPattern + } + + @inlinable var bitPattern: UIntXL.Storage { + self } - } - - @inlinable mutating func resize(minCount: Int, isSigned: Bool) { - let isLessThanZero = self.isLessThanZero(isSigned: isSigned) - self.resize(minCount: minCount, appending: UInt(repeating: isLessThanZero)) } } diff --git a/Sources/NBKTwosComplementKit/IntXL+Subtraction+Digit.swift b/Sources/NBKTwosComplementKit/IntXL+Subtraction+Digit.swift index 14f24f5d..00055590 100644 --- a/Sources/NBKTwosComplementKit/IntXL+Subtraction+Digit.swift +++ b/Sources/NBKTwosComplementKit/IntXL+Subtraction+Digit.swift @@ -39,7 +39,30 @@ extension IntXL { //=------------------------------------------------------------------------= @_disfavoredOverload @inlinable public mutating func subtract(_ other: Int, at index: Int) { - fatalError("TODO") + //=--------------------------------------= + if other.isZero { return } + //=--------------------------------------= + let lhsIsLessThanZero = self .isLessThanZero + let rhsIsLessThanZero = other.isLessThanZero + let lhsSign = UInt(repeating: lhsIsLessThanZero) + let rhsSign = UInt(repeating: rhsIsLessThanZero) + //=--------------------------------------= + self.storage.resize(minCount: index + 1) + //=--------------------------------------= + var borrow = self.storage.elements[index].subtractReportingOverflow(UInt(bitPattern: other)) + var index = self.storage.elements.index(after: index) + //=--------------------------------------= + if borrow != rhsIsLessThanZero { + let predicate = borrow + let decrement = UInt(bitPattern: borrow ? 1 : -1) + + while index != self.storage.elements.endIndex && borrow == predicate { + borrow = self.storage.elements[index].subtractReportingOverflow(decrement) + self.storage.elements.formIndex(after: &index) + } + } + //=--------------------------------------= + self.storage.normalize(appending: lhsSign &- rhsSign &- UInt(bit: borrow)) } @_disfavoredOverload @inlinable public func subtracting(_ other: Int, at index: Int) -> Self { @@ -81,7 +104,15 @@ extension UIntXL { } @_disfavoredOverload @inlinable public mutating func subtractReportingOverflow(_ other: UInt, at index: Int) -> Bool { - fatalError("TODO") + defer { + Swift.assert(self.storage.isNormal) + } + //=--------------------------------------= + if other.isZero { return false } + //=--------------------------------------= + self.storage.resize(minCount: index + 1) + defer{ self.storage.normalize() } + return self.storage.subtract(other, plus: false, at: index) } @_disfavoredOverload @inlinable public func subtractingReportingOverflow(_ other: UInt, at index: Int) -> PVO { @@ -90,3 +121,18 @@ extension UIntXL { return PVO(partialValue, overflow) } } + +//*============================================================================* +// MARK: * NBK x Flexible Width x Subtraction x Digit x UIntXL x Storage +//*============================================================================* + +extension UIntXL.Storage { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @_disfavoredOverload @inlinable mutating func subtract(_ other: UInt, plus borrow: Bool, at index: Int) -> Bool { + NBK.decrementSufficientUnsignedInteger(&self.elements, by: other, plus: borrow, at: index).overflow + } +} diff --git a/Sources/NBKTwosComplementKit/IntXL+Subtraction.swift b/Sources/NBKTwosComplementKit/IntXL+Subtraction.swift index 65632d9a..7a7c5f15 100644 --- a/Sources/NBKTwosComplementKit/IntXL+Subtraction.swift +++ b/Sources/NBKTwosComplementKit/IntXL+Subtraction.swift @@ -39,7 +39,44 @@ extension IntXL { //=------------------------------------------------------------------------= @inlinable public mutating func subtract(_ other: Self, at index: Int) { - fatalError("TODO") + //=--------------------------------------= + if other.isZero { return } + //=--------------------------------------= + let lhsIsLessThanZero = self .isLessThanZero + let rhsIsLessThanZero = other.isLessThanZero + let lhsSign = UInt(repeating: lhsIsLessThanZero) + let rhsSign = UInt(repeating: rhsIsLessThanZero) + //=--------------------------------------= + self.storage.resize(minCount: other.storage.elements.count + index) + //=--------------------------------------= + var borrow = false + var lhsIndex = index + var rhsIndex = other.storage.elements.startIndex + //=--------------------------------------= + while rhsIndex != other.storage.elements.endIndex { + var lhsElement = self .storage.elements[lhsIndex] + let rhsElement = other.storage.elements[rhsIndex] + + let a = lhsElement.subtractReportingOverflow(rhsElement) + let b = lhsElement.subtractReportingOverflow(UInt(bit: borrow)) + borrow = a || b + + self .storage.elements[lhsIndex] = lhsElement + self .storage.elements.formIndex(after: &lhsIndex) + other.storage.elements.formIndex(after: &rhsIndex) + } + //=--------------------------------------= + if borrow != rhsIsLessThanZero { + let predicate = borrow + let decrement = UInt(bitPattern: borrow ? 1 : -1) + + while lhsIndex != self.storage.elements.endIndex && borrow == predicate { + borrow = self.storage.elements[lhsIndex].subtractReportingOverflow(decrement) + self.storage.elements.formIndex(after: &lhsIndex) + } + } + //=--------------------------------------= + self.storage.normalize(appending: lhsSign &- rhsSign &- UInt(bit: borrow)) } @inlinable public func subtracting(_ other: Self, at index: Int) -> Self { @@ -81,7 +118,15 @@ extension UIntXL { } @inlinable public mutating func subtractReportingOverflow(_ other: Self, at index: Int) -> Bool { - fatalError("TODO") + defer { + Swift.assert(self.storage.isNormal) + } + //=--------------------------------------= + if other.isZero { return false } + //=--------------------------------------= + self.storage.resize(minCount: other.storage.elements.count + index) + defer{ self.storage.normalize() } + return self.storage.subtract(other.storage, plus: false, at: index) } @inlinable public func subtractingReportingOverflow(_ other: Self, at index: Int) -> PVO { @@ -90,3 +135,24 @@ extension UIntXL { return PVO(partialValue, overflow) } } + +//*============================================================================* +// MARK: * NBK x Flexible Width x Subtraction x UIntXL x Storage +//*============================================================================* + +extension UIntXL.Storage { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable mutating func subtract(_ other: Self, plus borrow: Bool, at index: Int) -> Bool { + NBK.decrementSufficientUnsignedInteger(&self.elements, by: other.elements, plus: borrow, at: index).overflow + } + + @inlinable mutating func subtract(_ other: Self, times multiplicand: UInt, + plus subtrahend: UInt, plus borrow: Bool, at index: Int) -> Bool { + NBK.decrementSufficientUnsignedInteger(&self.elements, by: other .elements, + times: multiplicand, plus: subtrahend, plus: borrow, at: index).overflow + } +} diff --git a/Sources/NBKTwosComplementKit/IntXL+Text.swift b/Sources/NBKTwosComplementKit/IntXL+Text.swift index 40463688..f4d37657 100644 --- a/Sources/NBKTwosComplementKit/IntXL+Text.swift +++ b/Sources/NBKTwosComplementKit/IntXL+Text.swift @@ -22,13 +22,11 @@ extension IntXLOrUIntXL { @inlinable public init?(_ description: some StringProtocol, radix: Int = 10) { var description = String(description) if let value: Self = description.withUTF8({ utf8 in - let radix = NBK.AnyRadixSolution(radix) let components = NBK.makeIntegerComponents(utf8: utf8) let digits = NBK.UnsafeUTF8(rebasing: components.body) guard let magnitude = Magnitude(digits: digits, radix: radix) else { return nil } return Self(sign: components.sign, magnitude: magnitude) - }){ self = value } else { return nil } } @@ -57,12 +55,10 @@ extension UIntXL { // MARK: Details x Decode x Private //=------------------------------------------------------------------------= - @inlinable init?(digits: NBK.UnsafeUTF8, radix: NBK.AnyRadixSolution) { - if radix.power.isZero { - self.init(digits: digits, radix: NBK .PerfectRadixSolution(radix)!) - } else { - self.init(digits: digits, radix: NBK.ImperfectRadixSolution(radix)!) - } + @inlinable init?(digits: NBK.UnsafeUTF8, radix: NBK.AnyRadixSolution) { + switch radix.power.isZero { + case true: self.init(digits: digits, radix: NBK .PerfectRadixSolution(radix)!) + case false: self.init(digits: digits, radix: NBK.ImperfectRadixSolution(radix)!) } } @inlinable init?(digits: NBK.UnsafeUTF8, radix: NBK.PerfectRadixSolution) { @@ -113,11 +109,9 @@ extension UIntXL { @inlinable func description( radix: NBK.AnyRadixSolution, alphabet: NBK.MaxRadixAlphabetEncoder, prefix: NBK.UnsafeUTF8, suffix: NBK.UnsafeUTF8) -> String { - if radix.power.isZero { - return self.description(radix: NBK .PerfectRadixSolution(radix)!, alphabet: alphabet, prefix: prefix, suffix: suffix) - } else { - return self.description(radix: NBK.ImperfectRadixSolution(radix)!, alphabet: alphabet, prefix: prefix, suffix: suffix) - } + switch radix.power.isZero { + case true: return self.description(radix: NBK .PerfectRadixSolution(radix)!, alphabet: alphabet, prefix: prefix, suffix: suffix) + case false: return self.description(radix: NBK.ImperfectRadixSolution(radix)!, alphabet: alphabet, prefix: prefix, suffix: suffix) } } @inlinable func description( diff --git a/Sources/NBKTwosComplementKit/IntXL+Update.swift b/Sources/NBKTwosComplementKit/IntXL+Update.swift index 7e047a4e..67395bbc 100644 --- a/Sources/NBKTwosComplementKit/IntXL+Update.swift +++ b/Sources/NBKTwosComplementKit/IntXL+Update.swift @@ -23,7 +23,7 @@ extension PrivateIntXLOrUIntXL { self.update(0 as Digit) } - @inlinable public mutating func update(_ value: Digit) { - Self.normalize(&self.storage, update: value) + @inlinable public mutating func update(_ value: Digit) { + self.storage.normalize(update: value) } } diff --git a/Sources/NBKTwosComplementKit/IntXL+Words+Pointers.swift b/Sources/NBKTwosComplementKit/IntXL+Words+Pointers.swift index 6c6bdce6..d794ccd6 100644 --- a/Sources/NBKTwosComplementKit/IntXL+Words+Pointers.swift +++ b/Sources/NBKTwosComplementKit/IntXL+Words+Pointers.swift @@ -28,7 +28,7 @@ extension PrivateIntXLOrUIntXL { /// Grants unsafe access to the collection's contiguous mutable storage. @inlinable public mutating func withUnsafeMutableBufferPointer( _ body:(inout UnsafeMutableBufferPointer) throws -> T) rethrows -> T { - defer{ Self.normalize(&self.storage) } + defer{ self.storage.normalize() } return try self.storage.elements.withUnsafeMutableBufferPointer(body) } } diff --git a/Sources/NBKTwosComplementKit/IntXL+Words.swift b/Sources/NBKTwosComplementKit/IntXL+Words.swift index b8df9826..9e8acab7 100644 --- a/Sources/NBKTwosComplementKit/IntXL+Words.swift +++ b/Sources/NBKTwosComplementKit/IntXL+Words.swift @@ -44,24 +44,24 @@ extension PrivateIntXLOrUIntXL { // MARK: * NBK x Flexible Width x Words x Storage //*============================================================================* -extension NBKFlexibleWidth.Storage { +extension PrivateIntXLOrUIntXLStorage { //=------------------------------------------------------------------------= // MARK: Accessors //=------------------------------------------------------------------------= @inlinable var first: UInt { - get { self.elements[self.elements.startIndex] } + get { self.elements[self.elements.startIndex] } set { self.elements[self.elements.startIndex] = newValue } } @inlinable var last: UInt { - get { self.elements[self.elements.index(before: self.elements.endIndex)] } + get { self.elements[self.elements.index(before: self.elements.endIndex)] } set { self.elements[self.elements.index(before: self.elements.endIndex)] = newValue } } - @inlinable subscript(_ index: Int, as type: T.Type) -> T where T: NBKCoreInteger { - get { T.init(bitPattern: self.elements[index]) } - set { self.elements[index] = UInt(bitPattern: newValue) } + @inlinable var tail: Digit { + get { Digit(bitPattern: self.last) } + set { self.last = UInt(bitPattern: newValue) } } } diff --git a/Sources/NBKTwosComplementKit/IntXL.swift b/Sources/NBKTwosComplementKit/IntXL.swift index 0e32513b..1d6e2d86 100644 --- a/Sources/NBKTwosComplementKit/IntXL.swift +++ b/Sources/NBKTwosComplementKit/IntXL.swift @@ -10,7 +10,7 @@ import NBKCoreKit //*============================================================================* -// MARK: * NBK x Flexible Width x IntXL +// MARK: * NBK x Flexible Width //*============================================================================* /// A signed, flexible-width, binary integer. @@ -38,17 +38,17 @@ import NBKCoreKit @inlinable init(_ storage: Storage) { self.storage = storage - precondition(Self.isNormal(self.storage)) + precondition(self.storage.isNormal) } @inlinable init(unchecked storage: Storage) { self.storage = storage - Swift.assert(Self.isNormal(self.storage)) + Swift.assert(self.storage.isNormal) } @inlinable init(normalizing storage: Storage) { self.storage = storage - Self.normalize(&self.storage) + self.storage.normalize() } //*========================================================================* @@ -61,8 +61,6 @@ import NBKCoreKit public typealias Digit = UInt public typealias Words = NBKFlexibleWidth.Words - - @usableFromInline typealias Storage = NBKFlexibleWidth.Storage @usableFromInline typealias Elements = NBKFlexibleWidth.Elements @@ -82,154 +80,21 @@ import NBKCoreKit @inlinable init(_ storage: Storage) { self.storage = storage - precondition(Self.isNormal(self.storage)) + precondition(self.storage.isNormal) } @inlinable init(unchecked storage: Storage) { self.storage = storage - Swift.assert(Self.isNormal(self.storage)) + Swift.assert(self.storage.isNormal) } @inlinable init(normalizing storage: Storage) { self.storage = storage - Self.normalize(&self.storage) - } - } - - //*============================================================================* - // MARK: * Storage - //*============================================================================* - - /// IntXL's and UIntXL's underlying storage. - /// - /// It has fixed-width semantics unless stated otherwise. - /// - @frozen @usableFromInline struct Storage { - - @usableFromInline typealias Elements = NBKFlexibleWidth.Elements - - //=------------------------------------------------------------------------= - // MARK: State - //=------------------------------------------------------------------------= - - /// The integer's underlying storage. - /// - /// It must be `nonempty` at the start and end of each access. - /// - @usableFromInline var elements: Elements - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - @inlinable init(_ elements: Elements) { - self.elements = elements - precondition(!self.elements.isEmpty) - } - - @inlinable init(unchecked elements: Elements) { - self.elements = elements - Swift.assert(!self.elements.isEmpty) - } - - @inlinable init(nonemptying elements: Elements) { - self.elements = elements - if self.elements.isEmpty { - self.elements.append(0) - } + self.storage.normalize() } } } -//*============================================================================* -// MARK: * NBK x Flexible Width x Aliases -//*============================================================================* - -/// A signed, flexible-width, integer. -public typealias IntXL = NBKFlexibleWidth - -/// An unsigned, flexible-width, integer. -public typealias UIntXL = NBKFlexibleWidth.Magnitude - -/// IntXL's and UIntXL's underlying storage. -@usableFromInline typealias StorageXL = NBKFlexibleWidth.Storage - -//*============================================================================* -// MARK: * NBK x Flexible Width x Protocol -//*============================================================================* - -public protocol IntXLOrUIntXL: NBKBinaryInteger, ExpressibleByStringLiteral where -Digit: NBKCoreInteger, Magnitude == UIntXL { - - //=------------------------------------------------------------------------= - // MARK: Details x Addition - //=------------------------------------------------------------------------= - - @inlinable mutating func add(_ other: Self, at index: Int) - - @inlinable func adding(_ other: Self, at index: Int) -> Self - - @_disfavoredOverload @inlinable mutating func add(_ other: Digit, at index: Int) - - @_disfavoredOverload @inlinable func adding(_ other: Digit, at index: Int) -> Self - - //=------------------------------------------------------------------------= - // MARK: Details x Subtraction - //=------------------------------------------------------------------------= - - @inlinable mutating func subtract(_ other: Self, at index: Int) - - @inlinable func subtracting(_ other: Self, at index: Int) -> Self - - @_disfavoredOverload @inlinable mutating func subtract(_ other: Digit, at index: Int) - - @_disfavoredOverload @inlinable func subtracting(_ other: Digit, at index: Int) -> Self - - //=------------------------------------------------------------------------= - // MARK: Details x Shifts - //=------------------------------------------------------------------------= - - @inlinable mutating func bitshiftLeftSmart(by distance: Int) - - @inlinable func bitshiftedLeftSmart(by distance: Int) -> Self - - @inlinable mutating func bitshiftLeft(by distance: Int) - - @inlinable func bitshiftedLeft(by distance: Int) -> Self - - @inlinable mutating func bitshiftLeft(words: Int, bits: Int) - - @inlinable func bitshiftedLeft(words: Int, bits: Int) -> Self - - @inlinable mutating func bitshiftLeft(words: Int) - - @inlinable func bitshiftedLeft(words: Int) -> Self - - @inlinable mutating func bitshiftRightSmart(by distance: Int) - - @inlinable func bitshiftedRightSmart(by distance: Int) -> Self - - @inlinable mutating func bitshiftRight(by distance: Int) - - @inlinable func bitshiftedRight(by distance: Int) -> Self - - @inlinable mutating func bitshiftRight(words: Int, bits: Int) - - @inlinable func bitshiftedRight(words: Int, bits: Int) -> Self - - @inlinable mutating func bitshiftRight(words: Int) - - @inlinable func bitshiftedRight(words: Int) -> Self - - //=------------------------------------------------------------------------= - // MARK: Details x Update - //=------------------------------------------------------------------------= - - @inlinable mutating func updateZeroValue() - - @inlinable mutating func update(_ value: Digit) -} - //=----------------------------------------------------------------------------= // MARK: + Details //=----------------------------------------------------------------------------= @@ -257,36 +122,11 @@ extension IntXLOrUIntXL { } //*============================================================================* -// MARK: * NBK x Flexible Width x Protocol x Private +// MARK: * NBK x Flexible Width x Aliases //*============================================================================* -@usableFromInline protocol PrivateIntXLOrUIntXL: IntXLOrUIntXL where Words == NBKFlexibleWidth.Words { - - typealias Storage = NBKFlexibleWidth.Storage - - typealias Elements = NBKFlexibleWidth.Elements - - //=------------------------------------------------------------------------= - // MARK: State - //=------------------------------------------------------------------------= - - @inlinable var storage: Storage { get set } - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - @inlinable init(_ storage: Storage) - - @inlinable init(unchecked storage: Storage) - - @inlinable init(normalizing storage: Storage) - - //=------------------------------------------------------------------------= - // MARK: Details x Storage - //=------------------------------------------------------------------------= - - @inlinable static func isNormal(_ storage: Storage) -> Bool - - @inlinable static func normalize(_ storage: inout Storage) -} +/// A signed, flexible-width, integer. +public typealias IntXL = NBKFlexibleWidth + +/// An unsigned, flexible-width, integer. +public typealias UIntXL = NBKFlexibleWidth.Magnitude diff --git a/Sources/NBKTwosComplementKit/IntXLOrUIntXL.swift b/Sources/NBKTwosComplementKit/IntXLOrUIntXL.swift new file mode 100644 index 00000000..a24fbf2e --- /dev/null +++ b/Sources/NBKTwosComplementKit/IntXLOrUIntXL.swift @@ -0,0 +1,121 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x IntXL or UIntXL +//*============================================================================* + +public protocol IntXLOrUIntXL: NBKBinaryInteger, ExpressibleByStringLiteral where +Digit: NBKCoreInteger, Magnitude == UIntXL { + + //=------------------------------------------------------------------------= + // MARK: Details x Comparisons + //=------------------------------------------------------------------------= + + func compared(to other: Self, at index: Int) -> Int + + func compared(to other: Digit, at index: Int) -> Int + + //=------------------------------------------------------------------------= + // MARK: Details x Addition + //=------------------------------------------------------------------------= + + @inlinable mutating func add(_ other: Self, at index: Int) + + @inlinable func adding(_ other: Self, at index: Int) -> Self + + @_disfavoredOverload @inlinable mutating func add(_ other: Digit, at index: Int) + + @_disfavoredOverload @inlinable func adding(_ other: Digit, at index: Int) -> Self + + //=------------------------------------------------------------------------= + // MARK: Details x Subtraction + //=------------------------------------------------------------------------= + + @inlinable mutating func subtract(_ other: Self, at index: Int) + + @inlinable func subtracting(_ other: Self, at index: Int) -> Self + + @_disfavoredOverload @inlinable mutating func subtract(_ other: Digit, at index: Int) + + @_disfavoredOverload @inlinable func subtracting(_ other: Digit, at index: Int) -> Self + + //=------------------------------------------------------------------------= + // MARK: Details x Shifts + //=------------------------------------------------------------------------= + + @inlinable mutating func bitshiftLeftSmart(by distance: Int) + + @inlinable func bitshiftedLeftSmart(by distance: Int) -> Self + + @inlinable mutating func bitshiftLeft(by distance: Int) + + @inlinable func bitshiftedLeft(by distance: Int) -> Self + + @inlinable mutating func bitshiftLeft(words: Int, bits: Int) + + @inlinable func bitshiftedLeft(words: Int, bits: Int) -> Self + + @inlinable mutating func bitshiftLeft(words: Int) + + @inlinable func bitshiftedLeft(words: Int) -> Self + + @inlinable mutating func bitshiftRightSmart(by distance: Int) + + @inlinable func bitshiftedRightSmart(by distance: Int) -> Self + + @inlinable mutating func bitshiftRight(by distance: Int) + + @inlinable func bitshiftedRight(by distance: Int) -> Self + + @inlinable mutating func bitshiftRight(words: Int, bits: Int) + + @inlinable func bitshiftedRight(words: Int, bits: Int) -> Self + + @inlinable mutating func bitshiftRight(words: Int) + + @inlinable func bitshiftedRight(words: Int) -> Self + + //=------------------------------------------------------------------------= + // MARK: Details x Update + //=------------------------------------------------------------------------= + + @inlinable mutating func updateZeroValue() + + @inlinable mutating func update(_ value: Digit) +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x IntXL or UIntXL x Private +//*============================================================================* + +@usableFromInline protocol PrivateIntXLOrUIntXL: IntXLOrUIntXL where Words == NBKFlexibleWidth.Words { + + typealias Elements = NBKFlexibleWidth.Elements + + associatedtype Storage: PrivateIntXLOrUIntXLStorage where Storage.Digit == Digit + + //=------------------------------------------------------------------------= + // MARK: State + //=------------------------------------------------------------------------= + + @inlinable var storage: Storage { get set } + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + @inlinable init(_ storage: Storage) + + @inlinable init(unchecked storage: Storage) + + @inlinable init(normalizing storage: Storage) +} diff --git a/Sources/NBKTwosComplementKit/IntXLOrUIntXLStorage.swift b/Sources/NBKTwosComplementKit/IntXLOrUIntXLStorage.swift new file mode 100644 index 00000000..6873d80e --- /dev/null +++ b/Sources/NBKTwosComplementKit/IntXLOrUIntXLStorage.swift @@ -0,0 +1,66 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x IntXL or UIntXL x Storage +//*============================================================================* + +@usableFromInline protocol IntXLOrUIntXLStorage: NBKBitPatternConvertible where BitPattern == UIntXL.Storage { + + associatedtype Digit: NBKCoreInteger + + //=------------------------------------------------------------------------= + // MARK: Details x Normalization + //=------------------------------------------------------------------------= + + @inlinable var isNormal: Bool { get } + + @inlinable mutating func normalize() + + @inlinable mutating func normalize(update value: Digit) + + //=------------------------------------------------------------------------= + // MARK: Details x Size + //=------------------------------------------------------------------------= + + @inlinable mutating func resize(minCount: Int) + + @inlinable mutating func resize(maxCount: Int) +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x IntXL or UIntXL x Storage x Private +//*============================================================================* + +@usableFromInline protocol PrivateIntXLOrUIntXLStorage: IntXLOrUIntXLStorage { + + typealias Elements = NBKFlexibleWidth.Elements + + //=------------------------------------------------------------------------= + // MARK: State + //=------------------------------------------------------------------------= + + /// A collection of unsigned integers. + /// + /// It must be `nonempty` at the start and end of each access. + /// + @inlinable var elements: Elements { get set } + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + @inlinable init(_ elements: Elements) + + @inlinable init(unchecked elements: Elements) + + @inlinable init(nonemptying elements: Elements) +} diff --git a/Tests/NBKTwosComplementKitTests/IntXL+Addition.swift b/Tests/NBKTwosComplementKitTests/IntXL+Addition.swift new file mode 100644 index 00000000..b8e6c977 --- /dev/null +++ b/Tests/NBKTwosComplementKitTests/IntXL+Addition.swift @@ -0,0 +1,220 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +import NBKTwosComplementKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Flexible Width x Addition x IntXL +//*============================================================================* + +final class NBKFlexibleWidthTestsOnAdditionAsIntXL: XCTestCase { + + typealias T = IntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testAdding() { + NBKAssertAddition(T( 1), T( 2), Int(0), T( 3)) + NBKAssertAddition(T( 1), T( 1), Int(0), T( 2)) + NBKAssertAddition(T( 1), T( 0), Int(0), T( 1)) + NBKAssertAddition(T( 1), T(-1), Int(0), T( 0)) + NBKAssertAddition(T( 1), T(-2), Int(0), T(-1)) + + NBKAssertAddition(T( 0), T( 2), Int(0), T( 2)) + NBKAssertAddition(T( 0), T( 1), Int(0), T( 1)) + NBKAssertAddition(T( 0), T( 0), Int(0), T( 0)) + NBKAssertAddition(T( 0), T(-1), Int(0), T(-1)) + NBKAssertAddition(T( 0), T(-2), Int(0), T(-2)) + + NBKAssertAddition(T(-1), T( 2), Int(0), T( 1)) + NBKAssertAddition(T(-1), T( 1), Int(0), T( 0)) + NBKAssertAddition(T(-1), T( 0), Int(0), T(-1)) + NBKAssertAddition(T(-1), T(-1), Int(0), T(-2)) + NBKAssertAddition(T(-1), T(-2), Int(0), T(-3)) + } + + func testAddingAtIndex() { + NBKAssertAddition(T(words:[ 0, 0, 0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[ 1, 2, 3, 0] as W)) + NBKAssertAddition(T(words:[~0, 0, 0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[ 0, 3, 3, 0] as W)) + NBKAssertAddition(T(words:[~0, ~0, 0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[ 0, 2, 4, 0] as W)) + NBKAssertAddition(T(words:[~0, ~0, ~0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[ 0, 2, 3, 1] as W)) + + NBKAssertAddition(T(words:[ 0, 0, 0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[ 0, 1, 2, 3] as W)) + NBKAssertAddition(T(words:[~0, 0, 0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[~0, 1, 2, 3] as W)) + NBKAssertAddition(T(words:[~0, ~0, 0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[~0, 0, 3, 3] as W)) + NBKAssertAddition(T(words:[~0, ~0, ~0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[~0, 0, 2, 4] as W)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Digit + //=------------------------------------------------------------------------= + + func testAddingDigit() { + NBKAssertAdditionByDigit(T( 1), Int( 2), Int(0), T( 3)) + NBKAssertAdditionByDigit(T( 1), Int( 1), Int(0), T( 2)) + NBKAssertAdditionByDigit(T( 1), Int( 0), Int(0), T( 1)) + NBKAssertAdditionByDigit(T( 1), Int(-1), Int(0), T( 0)) + NBKAssertAdditionByDigit(T( 1), Int(-2), Int(0), T(-1)) + + NBKAssertAdditionByDigit(T( 0), Int( 2), Int(0), T( 2)) + NBKAssertAdditionByDigit(T( 0), Int( 1), Int(0), T( 1)) + NBKAssertAdditionByDigit(T( 0), Int( 0), Int(0), T( 0)) + NBKAssertAdditionByDigit(T( 0), Int(-1), Int(0), T(-1)) + NBKAssertAdditionByDigit(T( 0), Int(-2), Int(0), T(-2)) + + NBKAssertAdditionByDigit(T(-1), Int( 2), Int(0), T( 1)) + NBKAssertAdditionByDigit(T(-1), Int( 1), Int(0), T( 0)) + NBKAssertAdditionByDigit(T(-1), Int( 0), Int(0), T(-1)) + NBKAssertAdditionByDigit(T(-1), Int(-1), Int(0), T(-2)) + NBKAssertAdditionByDigit(T(-1), Int(-2), Int(0), T(-3)) + } + + func testAddingDigitAtIndex() { + NBKAssertAdditionByDigit(T(words:[ 0, 0, 0, 0] as W), Int(3), Int(0), T(words:[ 3, 0, 0, 0] as W)) + NBKAssertAdditionByDigit(T(words:[~0, 0, 0, 0] as W), Int(3), Int(0), T(words:[ 2, 1, 0, 0] as W)) + NBKAssertAdditionByDigit(T(words:[~0, ~0, 0, 0] as W), Int(3), Int(0), T(words:[ 2, 0, 1, 0] as W)) + NBKAssertAdditionByDigit(T(words:[~0, ~0, ~0, 0] as W), Int(3), Int(0), T(words:[ 2, 0, 0, 1] as W)) + + NBKAssertAdditionByDigit(T(words:[ 0, 0, 0, 0] as W), Int(3), Int(1), T(words:[ 0, 3, 0, 0] as W)) + NBKAssertAdditionByDigit(T(words:[~0, 0, 0, 0] as W), Int(3), Int(1), T(words:[~0, 3, 0, 0] as W)) + NBKAssertAdditionByDigit(T(words:[~0, ~0, 0, 0] as W), Int(3), Int(1), T(words:[~0, 2, 1, 0] as W)) + NBKAssertAdditionByDigit(T(words:[~0, ~0, ~0, 0] as W), Int(3), Int(1), T(words:[~0, 2, 0, 1] as W)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Miscellaneous + //=------------------------------------------------------------------------= + + func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { + func becauseThisCompilesSuccessfully(_ x: inout T) { + XCTAssertNotNil(x += 0) + XCTAssertNotNil(x.add(0, at: 0)) + + XCTAssertNotNil(x + 0) + XCTAssertNotNil(x.adding(0, at: 0)) + } + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Addition x UIntXL +//*============================================================================* + +final class NBKFlexibleWidthTestsOnAdditionAsUIntXL: XCTestCase { + + typealias T = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testAdding() { + NBKAssertAddition(T(0), T(0), Int(0), T(0)) + NBKAssertAddition(T(0), T(1), Int(0), T(1)) + NBKAssertAddition(T(0), T(2), Int(0), T(2)) + + NBKAssertAddition(T(1), T(0), Int(0), T(1)) + NBKAssertAddition(T(1), T(1), Int(0), T(2)) + NBKAssertAddition(T(1), T(2), Int(0), T(3)) + } + + func testAddingAtIndex() { + NBKAssertAddition(T(words:[ 0, 0, 0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[ 1, 2, 3, 0] as W)) + NBKAssertAddition(T(words:[~0, 0, 0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[ 0, 3, 3, 0] as W)) + NBKAssertAddition(T(words:[~0, ~0, 0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[ 0, 2, 4, 0] as W)) + NBKAssertAddition(T(words:[~0, ~0, ~0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[ 0, 2, 3, 1] as W)) + + NBKAssertAddition(T(words:[ 0, 0, 0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[ 0, 1, 2, 3] as W)) + NBKAssertAddition(T(words:[~0, 0, 0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[~0, 1, 2, 3] as W)) + NBKAssertAddition(T(words:[~0, ~0, 0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[~0, 0, 3, 3] as W)) + NBKAssertAddition(T(words:[~0, ~0, ~0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[~0, 0, 2, 4] as W)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Digit + //=------------------------------------------------------------------------= + + func testAddingDigit() { + NBKAssertAdditionByDigit(T(0), UInt(0), Int(0), T(0)) + NBKAssertAdditionByDigit(T(0), UInt(1), Int(0), T(1)) + NBKAssertAdditionByDigit(T(0), UInt(2), Int(0), T(2)) + + NBKAssertAdditionByDigit(T(1), UInt(0), Int(0), T(1)) + NBKAssertAdditionByDigit(T(1), UInt(1), Int(0), T(2)) + NBKAssertAdditionByDigit(T(1), UInt(2), Int(0), T(3)) + } + + func testAddingDigitAtIndex() { + NBKAssertAdditionByDigit(T(words:[ 0, 0, 0, 0] as W), UInt(3), Int(0), T(words:[ 3, 0, 0, 0] as W)) + NBKAssertAdditionByDigit(T(words:[~0, 0, 0, 0] as W), UInt(3), Int(0), T(words:[ 2, 1, 0, 0] as W)) + NBKAssertAdditionByDigit(T(words:[~0, ~0, 0, 0] as W), UInt(3), Int(0), T(words:[ 2, 0, 1, 0] as W)) + NBKAssertAdditionByDigit(T(words:[~0, ~0, ~0, 0] as W), UInt(3), Int(0), T(words:[ 2, 0, 0, 1] as W)) + + NBKAssertAdditionByDigit(T(words:[ 0, 0, 0, 0] as W), UInt(3), Int(1), T(words:[ 0, 3, 0, 0] as W)) + NBKAssertAdditionByDigit(T(words:[~0, 0, 0, 0] as W), UInt(3), Int(1), T(words:[~0, 3, 0, 0] as W)) + NBKAssertAdditionByDigit(T(words:[~0, ~0, 0, 0] as W), UInt(3), Int(1), T(words:[~0, 2, 1, 0] as W)) + NBKAssertAdditionByDigit(T(words:[~0, ~0, ~0, 0] as W), UInt(3), Int(1), T(words:[~0, 2, 0, 1] as W)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Miscellaneous + //=------------------------------------------------------------------------= + + func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { + func becauseThisCompilesSuccessfully(_ x: inout T) { + XCTAssertNotNil(x += 0) + XCTAssertNotNil(x.add(0, at: 0)) + + XCTAssertNotNil(x + 0) + XCTAssertNotNil(x.adding(0, at: 0)) + } + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Addition x Assertions +//*============================================================================* + +private func NBKAssertAddition( +_ lhs: T, _ rhs: T, _ index: Int, _ partialValue: T, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + if index.isZero { + XCTAssertEqual( lhs + rhs, partialValue, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs += rhs; return lhs }(), partialValue, file: file, line: line) + } + //=------------------------------------------= + XCTAssertEqual(lhs.adding(rhs, at: index), partialValue, file: file, line: line) + XCTAssertEqual({ var x = lhs; let _ = x.add(rhs, at: index); return x }(), partialValue, file: file, line: line) +} + +private func NBKAssertAdditionByDigit( +_ lhs: T, _ rhs: T.Digit, _ index: Int, _ partialValue: T, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + if index.isZero { + XCTAssertEqual( lhs + rhs, partialValue, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs += rhs; return lhs }(), partialValue, file: file, line: line) + } + //=------------------------------------------= + XCTAssertEqual(lhs.adding(rhs, at: index), partialValue, file: file, line: line) + XCTAssertEqual({ var x = lhs; let _ = x.add(rhs, at: index); return x }(), partialValue, file: file, line: line) +} + +#endif diff --git a/Tests/NBKTwosComplementKitTests/IntXL+Comparisons.swift b/Tests/NBKTwosComplementKitTests/IntXL+Comparisons.swift new file mode 100644 index 00000000..aa023308 --- /dev/null +++ b/Tests/NBKTwosComplementKitTests/IntXL+Comparisons.swift @@ -0,0 +1,593 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +import NBKTwosComplementKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Flexible Width x Comparisons x IntXL +//*============================================================================* + +final class NBKFlexibleWidthTestsOnComparisonsAsIntXL: XCTestCase { + + typealias T = IntXL + typealias M = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testIsZero() { + XCTAssertTrue (T(sign: .plus, magnitude: 0).isZero) + XCTAssertTrue (T(sign: .minus, magnitude: 0).isZero) + + XCTAssertTrue (T(words:[ 0] as W).isZero) + XCTAssertFalse(T(words:[ 1] as W).isZero) + XCTAssertFalse(T(words:[ 2] as W).isZero) + + XCTAssertFalse(T(words:[~0] as W).isZero) + XCTAssertFalse(T(words:[~1] as W).isZero) + XCTAssertFalse(T(words:[~2] as W).isZero) + } + + func testIsLessThanZero() { + XCTAssertFalse(T(sign: .plus, magnitude: 0).isLessThanZero) + XCTAssertFalse(T(sign: .minus, magnitude: 0).isLessThanZero) + + XCTAssertFalse(T(words:[ 0] as W).isLessThanZero) + XCTAssertFalse(T(words:[ 1] as W).isLessThanZero) + XCTAssertFalse(T(words:[ 2] as W).isLessThanZero) + + XCTAssertTrue (T(words:[~0] as W).isLessThanZero) + XCTAssertTrue (T(words:[~1] as W).isLessThanZero) + XCTAssertTrue (T(words:[~2] as W).isLessThanZero) + } + + func testIsMoreThanZero() { + XCTAssertFalse(T(sign: .plus, magnitude: 0).isMoreThanZero) + XCTAssertFalse(T(sign: .minus, magnitude: 0).isMoreThanZero) + + XCTAssertFalse(T(words:[ 0] as W).isMoreThanZero) + XCTAssertTrue (T(words:[ 1] as W).isMoreThanZero) + XCTAssertTrue (T(words:[ 2] as W).isMoreThanZero) + + XCTAssertFalse(T(words:[~0] as W).isMoreThanZero) + XCTAssertFalse(T(words:[~1] as W).isMoreThanZero) + XCTAssertFalse(T(words:[~2] as W).isMoreThanZero) + } + + func testIsOdd() { + XCTAssertFalse(T(sign: .plus, magnitude: 0).isOdd) + XCTAssertFalse(T(sign: .minus, magnitude: 0).isOdd) + + XCTAssertFalse(T(words:[ 0] as W).isOdd) + XCTAssertTrue (T(words:[ 1] as W).isOdd) + XCTAssertFalse(T(words:[ 2] as W).isOdd) + + XCTAssertTrue (T(words:[~0] as W).isOdd) + XCTAssertFalse(T(words:[~1] as W).isOdd) + XCTAssertTrue (T(words:[~2] as W).isOdd) + } + + func testIsEven() { + XCTAssertTrue (T(sign: .plus, magnitude: 0).isEven) + XCTAssertTrue (T(sign: .minus, magnitude: 0).isEven) + + XCTAssertTrue (T(words:[ 0] as W).isEven) + XCTAssertFalse(T(words:[ 1] as W).isEven) + XCTAssertTrue (T(words:[ 2] as W).isEven) + + XCTAssertFalse(T(words:[~0] as W).isEven) + XCTAssertTrue (T(words:[~1] as W).isEven) + XCTAssertFalse(T(words:[~2] as W).isEven) + } + + func testIsPowerOf2() { + XCTAssertFalse(T(sign: .plus, magnitude: 0).isPowerOf2) + XCTAssertFalse(T(sign: .minus, magnitude: 0).isPowerOf2) + + XCTAssertFalse(T(words:[~3] as W).isPowerOf2) + XCTAssertFalse(T(words:[~2] as W).isPowerOf2) + XCTAssertFalse(T(words:[~1] as W).isPowerOf2) + XCTAssertFalse(T(words:[~0] as W).isPowerOf2) + XCTAssertFalse(T(words:[ 0] as W).isPowerOf2) + XCTAssertTrue (T(words:[ 1] as W).isPowerOf2) + XCTAssertTrue (T(words:[ 2] as W).isPowerOf2) + XCTAssertFalse(T(words:[ 3] as W).isPowerOf2) + + XCTAssertFalse(T(words:[ 0, 0, 0, 0] as W).isPowerOf2) + XCTAssertTrue (T(words:[ 1, 0, 0, 0] as W).isPowerOf2) + XCTAssertFalse(T(words:[ 1, 1, 0, 0] as W).isPowerOf2) + XCTAssertTrue (T(words:[ 0, 1, 0, 0] as W).isPowerOf2) + XCTAssertFalse(T(words:[ 0, 1, 1, 0] as W).isPowerOf2) + XCTAssertTrue (T(words:[ 0, 0, 1, 0] as W).isPowerOf2) + XCTAssertFalse(T(words:[ 0, 0, 1, 1] as W).isPowerOf2) + XCTAssertTrue (T(words:[ 0, 0, 0, 1] as W).isPowerOf2) + } + + func testSignum() { + NBKAssertSignum(T(sign: .plus, magnitude: 0), Int( 0)) + NBKAssertSignum(T(sign: .minus, magnitude: 0), Int( 0)) + + NBKAssertSignum(T(words:[ 0] as W), Int( 0)) + NBKAssertSignum(T(words:[ 1] as W), Int( 1)) + NBKAssertSignum(T(words:[ 2] as W), Int( 1)) + + NBKAssertSignum(T(words:[~0] as W), Int(-1)) + NBKAssertSignum(T(words:[~1] as W), Int(-1)) + NBKAssertSignum(T(words:[~2] as W), Int(-1)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testHashing() { + var union = Set() + union.insert(T(sign: .minus, magnitude: M())) + union.insert(T(sign: .minus, magnitude: M())) + union.insert(T(words:[0, 0, 0, 0] as W)) + union.insert(T(words:[0, 0, 0, 0] as W)) + union.insert(T(words:[1, 0, 0, 0] as W)) + union.insert(T(words:[1, 0, 0, 0] as W)) + union.insert(T(words:[0, 1, 0, 0] as W)) + union.insert(T(words:[0, 1, 0, 0] as W)) + union.insert(T(words:[0, 0, 1, 0] as W)) + union.insert(T(words:[0, 0, 1, 0] as W)) + union.insert(T(words:[0, 0, 0, 1] as W)) + union.insert(T(words:[0, 0, 0, 1] as W)) + XCTAssertEqual(union.count, 5 as Int) + } + + func testComparing() { + NBKAssertComparisons( T(0), T(0), Int(0)) + NBKAssertComparisons( T(0), -T(0), Int(0)) + NBKAssertComparisons(-T(0), T(0), Int(0)) + NBKAssertComparisons(-T(0), -T(0), Int(0)) + + NBKAssertComparisons( T(1), T(1), Int(0)) + NBKAssertComparisons( T(1), -T(1), Int(1)) + NBKAssertComparisons(-T(1), T(1), -Int(1)) + NBKAssertComparisons(-T(1), -T(1), Int(0)) + + NBKAssertComparisons( T(2), T(3), -Int(1)) + NBKAssertComparisons( T(2), -T(3), Int(1)) + NBKAssertComparisons(-T(2), T(3), -Int(1)) + NBKAssertComparisons(-T(2), -T(3), Int(1)) + + NBKAssertComparisons( T(3), T(2), Int(1)) + NBKAssertComparisons( T(3), -T(2), Int(1)) + NBKAssertComparisons(-T(3), T(2), -Int(1)) + NBKAssertComparisons(-T(3), -T(2), -Int(1)) + + NBKAssertComparisons(T(words:[0, 2, 3, 4] as W), T(words:[1, 2, 3, 4] as W), -Int(1)) + NBKAssertComparisons(T(words:[1, 0, 3, 4] as W), T(words:[1, 2, 3, 4] as W), -Int(1)) + NBKAssertComparisons(T(words:[1, 2, 0, 4] as W), T(words:[1, 2, 3, 4] as W), -Int(1)) + NBKAssertComparisons(T(words:[1, 2, 3, 0] as W), T(words:[1, 2, 3, 4] as W), -Int(1)) + NBKAssertComparisons(T(words:[0, 2, 3, 4] as W), T(words:[0, 2, 3, 4] as W), Int(0)) + NBKAssertComparisons(T(words:[1, 0, 3, 4] as W), T(words:[1, 0, 3, 4] as W), Int(0)) + NBKAssertComparisons(T(words:[1, 2, 0, 4] as W), T(words:[1, 2, 0, 4] as W), Int(0)) + NBKAssertComparisons(T(words:[1, 2, 3, 0] as W), T(words:[1, 2, 3, 0] as W), Int(0)) + NBKAssertComparisons(T(words:[1, 2, 3, 4] as W), T(words:[0, 2, 3, 4] as W), Int(1)) + NBKAssertComparisons(T(words:[1, 2, 3, 4] as W), T(words:[1, 0, 3, 4] as W), Int(1)) + NBKAssertComparisons(T(words:[1, 2, 3, 4] as W), T(words:[1, 2, 0, 4] as W), Int(1)) + NBKAssertComparisons(T(words:[1, 2, 3, 4] as W), T(words:[1, 2, 3, 0] as W), Int(1)) + } + + func testComparingAtIndex() { + NBKAssertComparisonsAtIndex( T(0), T(0), Int(4), Int(0)) + NBKAssertComparisonsAtIndex( T(0), -T(0), Int(4), Int(0)) + NBKAssertComparisonsAtIndex(-T(0), T(0), Int(4), Int(0)) + NBKAssertComparisonsAtIndex(-T(0), -T(0), Int(4), Int(0)) + + NBKAssertComparisonsAtIndex( T(1), T(1), Int(4), -Int(1)) + NBKAssertComparisonsAtIndex( T(1), -T(1), Int(4), Int(1)) + NBKAssertComparisonsAtIndex(-T(1), T(1), Int(4), -Int(1)) + NBKAssertComparisonsAtIndex(-T(1), -T(1), Int(4), Int(1)) + + NBKAssertComparisonsAtIndex( T(2), T(3), Int(4), -Int(1)) + NBKAssertComparisonsAtIndex( T(2), -T(3), Int(4), Int(1)) + NBKAssertComparisonsAtIndex(-T(2), T(3), Int(4), -Int(1)) + NBKAssertComparisonsAtIndex(-T(2), -T(3), Int(4), Int(1)) + + NBKAssertComparisonsAtIndex( T(3), T(2), Int(4), -Int(1)) + NBKAssertComparisonsAtIndex( T(3), -T(2), Int(4), Int(1)) + NBKAssertComparisonsAtIndex(-T(3), T(2), Int(4), -Int(1)) + NBKAssertComparisonsAtIndex(-T(3), -T(2), Int(4), Int(1)) + + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(0), Int(0)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(1), Int(0)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(2), Int(0)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(3), Int(0)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(4), Int(0)) + + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(0), -Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(1), -Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(2), -Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(3), -Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(4), -Int(1)) + + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(0), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(1), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(2), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(3), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(4), Int(1)) + + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(0), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(1), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(2), Int(0)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(3), -Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(4), -Int(1)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Digit + //=------------------------------------------------------------------------= + + func testComparingByDigit() { + NBKAssertComparisonsByDigit( T(0), Int(0), Int(0)) + NBKAssertComparisonsByDigit( T(0), -Int(0), Int(0)) + NBKAssertComparisonsByDigit(-T(0), Int(0), Int(0)) + NBKAssertComparisonsByDigit(-T(0), -Int(0), Int(0)) + + NBKAssertComparisonsByDigit( T(1), Int(1), Int(0)) + NBKAssertComparisonsByDigit( T(1), -Int(1), Int(1)) + NBKAssertComparisonsByDigit(-T(1), Int(1), -Int(1)) + NBKAssertComparisonsByDigit(-T(1), -Int(1), Int(0)) + + NBKAssertComparisonsByDigit( T(2), Int(3), -Int(1)) + NBKAssertComparisonsByDigit( T(2), -Int(3), Int(1)) + NBKAssertComparisonsByDigit(-T(2), Int(3), -Int(1)) + NBKAssertComparisonsByDigit(-T(2), -Int(3), Int(1)) + + NBKAssertComparisonsByDigit( T(3), Int(2), Int(1)) + NBKAssertComparisonsByDigit( T(3), -Int(2), Int(1)) + NBKAssertComparisonsByDigit(-T(3), Int(2), -Int(1)) + NBKAssertComparisonsByDigit(-T(3), -Int(2), -Int(1)) + + NBKAssertComparisonsByDigit( T(words:[0, 0, 0, 0]), Int(1), -Int(1)) + NBKAssertComparisonsByDigit( T(words:[1, 0, 0, 0]), Int(1), Int(0)) + NBKAssertComparisonsByDigit( T(words:[2, 0, 0, 0]), Int(1), Int(1)) + + NBKAssertComparisonsByDigit( T(words:[0, 1, 0, 0]), Int(1), Int(1)) + NBKAssertComparisonsByDigit( T(words:[1, 1, 0, 0]), Int(1), Int(1)) + NBKAssertComparisonsByDigit( T(words:[2, 1, 0, 0]), Int(1), Int(1)) + + NBKAssertComparisonsByDigit(~T(words:[0, 0, 0, 0]), ~Int(1), Int(1)) + NBKAssertComparisonsByDigit(~T(words:[1, 0, 0, 0]), ~Int(1), Int(0)) + NBKAssertComparisonsByDigit(~T(words:[2, 0, 0, 0]), ~Int(1), -Int(1)) + + NBKAssertComparisonsByDigit(~T(words:[0, 1, 0, 0]), ~Int(1), -Int(1)) + NBKAssertComparisonsByDigit(~T(words:[1, 1, 0, 0]), ~Int(1), -Int(1)) + NBKAssertComparisonsByDigit(~T(words:[2, 1, 0, 0]), ~Int(1), -Int(1)) + } + + func testComparingByDigitAtIndex() { + NBKAssertComparisonsByDigitAtIndex( T(0), Int(0), Int(4), Int(0)) + NBKAssertComparisonsByDigitAtIndex( T(0), -Int(0), Int(4), Int(0)) + NBKAssertComparisonsByDigitAtIndex(-T(0), Int(0), Int(4), Int(0)) + NBKAssertComparisonsByDigitAtIndex(-T(0), -Int(0), Int(4), Int(0)) + + NBKAssertComparisonsByDigitAtIndex( T(1), Int(1), Int(4), -Int(1)) + NBKAssertComparisonsByDigitAtIndex( T(1), -Int(1), Int(4), Int(1)) + NBKAssertComparisonsByDigitAtIndex(-T(1), Int(1), Int(4), -Int(1)) + NBKAssertComparisonsByDigitAtIndex(-T(1), -Int(1), Int(4), Int(1)) + + NBKAssertComparisonsByDigitAtIndex( T(2), Int(3), Int(4), -Int(1)) + NBKAssertComparisonsByDigitAtIndex( T(2), -Int(3), Int(4), Int(1)) + NBKAssertComparisonsByDigitAtIndex(-T(2), Int(3), Int(4), -Int(1)) + NBKAssertComparisonsByDigitAtIndex(-T(2), -Int(3), Int(4), Int(1)) + + NBKAssertComparisonsByDigitAtIndex( T(3), Int(2), Int(4), -Int(1)) + NBKAssertComparisonsByDigitAtIndex( T(3), -Int(2), Int(4), Int(1)) + NBKAssertComparisonsByDigitAtIndex(-T(3), Int(2), Int(4), -Int(1)) + NBKAssertComparisonsByDigitAtIndex(-T(3), -Int(2), Int(4), Int(1)) + + NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), Int(4), Int(0), Int(1)) + NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), Int(4), Int(1), Int(1)) + NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), Int(4), Int(2), Int(1)) + NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), Int(4), Int(3), Int(1)) + NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), Int(4), Int(4), -Int(1)) + + NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), Int(5), Int(0), Int(1)) + NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), Int(5), Int(1), Int(1)) + NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), Int(5), Int(2), Int(1)) + NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), Int(5), Int(3), -Int(1)) + NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), Int(5), Int(4), -Int(1)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Miscellaneous + //=------------------------------------------------------------------------= + + func testOverloadsAreUnambiguous() { + func becauseThisCompilesSuccessfully(_ x: inout T) { + XCTAssertNotNil(x.signum()) + } + } + + func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { + func becauseThisCompilesSuccessfully(_ x: inout T) { + XCTAssertNotNil(x.compared(to: 0)) + XCTAssertNotNil(x.compared(to: 0, at: 0)) + } + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Comparisons x UIntXL +//*============================================================================* + +final class NBKFlexibleWidthTestsOnComparisonsAsUIntXL: XCTestCase { + + typealias T = UIntXL + typealias M = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testIsZero() { + XCTAssertTrue (T(words:[ 0] as W).isZero) + XCTAssertFalse(T(words:[ 1] as W).isZero) + XCTAssertFalse(T(words:[ 2] as W).isZero) + + XCTAssertFalse(T(words:[~0] as W).isZero) + XCTAssertFalse(T(words:[~1] as W).isZero) + XCTAssertFalse(T(words:[~2] as W).isZero) + } + + func testIsLessThanZero() { + XCTAssertFalse(T(words:[ 0] as W).isLessThanZero) + XCTAssertFalse(T(words:[ 1] as W).isLessThanZero) + XCTAssertFalse(T(words:[ 2] as W).isLessThanZero) + + XCTAssertFalse(T(words:[~0] as W).isLessThanZero) + XCTAssertFalse(T(words:[~1] as W).isLessThanZero) + XCTAssertFalse(T(words:[~2] as W).isLessThanZero) + } + + func testIsMoreThanZero() { + XCTAssertFalse(T(words:[ 0] as W).isMoreThanZero) + XCTAssertTrue (T(words:[ 1] as W).isMoreThanZero) + XCTAssertTrue (T(words:[ 2] as W).isMoreThanZero) + + XCTAssertTrue (T(words:[~0] as W).isMoreThanZero) + XCTAssertTrue (T(words:[~1] as W).isMoreThanZero) + XCTAssertTrue (T(words:[~2] as W).isMoreThanZero) + } + + func testIsOdd() { + XCTAssertFalse(T(words:[ 0] as W).isOdd) + XCTAssertTrue (T(words:[ 1] as W).isOdd) + XCTAssertFalse(T(words:[ 2] as W).isOdd) + + XCTAssertTrue (T(words:[~0] as W).isOdd) + XCTAssertFalse(T(words:[~1] as W).isOdd) + XCTAssertTrue (T(words:[~2] as W).isOdd) + } + + func testIsEven() { + XCTAssertTrue (T(words:[ 0] as W).isEven) + XCTAssertFalse(T(words:[ 1] as W).isEven) + XCTAssertTrue (T(words:[ 2] as W).isEven) + + XCTAssertFalse(T(words:[~0] as W).isEven) + XCTAssertTrue (T(words:[~1] as W).isEven) + XCTAssertFalse(T(words:[~2] as W).isEven) + } + + func testIsPowerOf2() { + XCTAssertFalse(T(words:[ 0] as W).isPowerOf2) + XCTAssertTrue (T(words:[ 1] as W).isPowerOf2) + XCTAssertTrue (T(words:[ 2] as W).isPowerOf2) + XCTAssertFalse(T(words:[ 3] as W).isPowerOf2) + XCTAssertTrue (T(words:[ 4] as W).isPowerOf2) + XCTAssertFalse(T(words:[ 5] as W).isPowerOf2) + XCTAssertFalse(T(words:[ 6] as W).isPowerOf2) + XCTAssertFalse(T(words:[ 7] as W).isPowerOf2) + + XCTAssertFalse(T(words:[ 0, 0, 0, 0] as W).isPowerOf2) + XCTAssertTrue (T(words:[ 1, 0, 0, 0] as W).isPowerOf2) + XCTAssertFalse(T(words:[ 1, 1, 0, 0] as W).isPowerOf2) + XCTAssertTrue (T(words:[ 0, 1, 0, 0] as W).isPowerOf2) + XCTAssertFalse(T(words:[ 0, 1, 1, 0] as W).isPowerOf2) + XCTAssertTrue (T(words:[ 0, 0, 1, 0] as W).isPowerOf2) + XCTAssertFalse(T(words:[ 0, 0, 1, 1] as W).isPowerOf2) + XCTAssertTrue (T(words:[ 0, 0, 0, 1] as W).isPowerOf2) + } + + func testSignum() { + NBKAssertSignum(T(words:[ 0] as W), Int(0)) + NBKAssertSignum(T(words:[ 1] as W), Int(1)) + NBKAssertSignum(T(words:[ 2] as W), Int(1)) + + NBKAssertSignum(T(words:[~0] as W), Int(1)) + NBKAssertSignum(T(words:[~1] as W), Int(1)) + NBKAssertSignum(T(words:[~2] as W), Int(1)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testHashing() { + var union = Set() + union.insert(T(words:[0, 0, 0, 0] as W)) + union.insert(T(words:[0, 0, 0, 0] as W)) + union.insert(T(words:[1, 0, 0, 0] as W)) + union.insert(T(words:[1, 0, 0, 0] as W)) + union.insert(T(words:[0, 1, 0, 0] as W)) + union.insert(T(words:[0, 1, 0, 0] as W)) + union.insert(T(words:[0, 0, 1, 0] as W)) + union.insert(T(words:[0, 0, 1, 0] as W)) + union.insert(T(words:[0, 0, 0, 1] as W)) + union.insert(T(words:[0, 0, 0, 1] as W)) + XCTAssertEqual(union.count, 5 as Int) + } + + func testComparing() { + NBKAssertComparisons(T(words:[0, 2, 3, 4] as W), T(words:[1, 2, 3, 4] as W), -Int(1)) + NBKAssertComparisons(T(words:[1, 0, 3, 4] as W), T(words:[1, 2, 3, 4] as W), -Int(1)) + NBKAssertComparisons(T(words:[1, 2, 0, 4] as W), T(words:[1, 2, 3, 4] as W), -Int(1)) + NBKAssertComparisons(T(words:[1, 2, 3, 0] as W), T(words:[1, 2, 3, 4] as W), -Int(1)) + NBKAssertComparisons(T(words:[0, 2, 3, 4] as W), T(words:[0, 2, 3, 4] as W), Int(0)) + NBKAssertComparisons(T(words:[1, 0, 3, 4] as W), T(words:[1, 0, 3, 4] as W), Int(0)) + NBKAssertComparisons(T(words:[1, 2, 0, 4] as W), T(words:[1, 2, 0, 4] as W), Int(0)) + NBKAssertComparisons(T(words:[1, 2, 3, 0] as W), T(words:[1, 2, 3, 0] as W), Int(0)) + NBKAssertComparisons(T(words:[1, 2, 3, 4] as W), T(words:[0, 2, 3, 4] as W), Int(1)) + NBKAssertComparisons(T(words:[1, 2, 3, 4] as W), T(words:[1, 0, 3, 4] as W), Int(1)) + NBKAssertComparisons(T(words:[1, 2, 3, 4] as W), T(words:[1, 2, 0, 4] as W), Int(1)) + NBKAssertComparisons(T(words:[1, 2, 3, 4] as W), T(words:[1, 2, 3, 0] as W), Int(1)) + } + + func testComparingAtIndex() { + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(0), Int(0)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(1), Int(0)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(2), Int(0)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(3), Int(0)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(4), Int(0)) + + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(0), -Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(1), -Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(2), -Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(3), -Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(4), -Int(1)) + + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(0), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(1), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(2), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(3), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(4), Int(1)) + + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(0), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(1), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(2), Int(0)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(3), -Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(4), -Int(1)) + } + + func testComparingByDigit() { + NBKAssertComparisonsByDigit(T(0), UInt(0), Int(0)) + NBKAssertComparisonsByDigit(T(1), UInt(1), Int(0)) + NBKAssertComparisonsByDigit(T(2), UInt(3), -Int(1)) + NBKAssertComparisonsByDigit(T(3), UInt(2), Int(1)) + + NBKAssertComparisonsByDigit(T(words:[0, 0, 0, 0]), UInt(1), -Int(1)) + NBKAssertComparisonsByDigit(T(words:[1, 0, 0, 0]), UInt(1), Int(0)) + NBKAssertComparisonsByDigit(T(words:[2, 0, 0, 0]), UInt(1), Int(1)) + + NBKAssertComparisonsByDigit(T(words:[0, 1, 0, 0]), UInt(1), Int(1)) + NBKAssertComparisonsByDigit(T(words:[1, 1, 0, 0]), UInt(1), Int(1)) + NBKAssertComparisonsByDigit(T(words:[2, 1, 0, 0]), UInt(1), Int(1)) + } + + func testComparingByDigitAtIndex() { + NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), UInt(4), Int(0), Int(1)) + NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), UInt(4), Int(1), Int(1)) + NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), UInt(4), Int(2), Int(1)) + NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), UInt(4), Int(3), Int(1)) + NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), UInt(4), Int(4), -Int(1)) + + NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), UInt(5), Int(0), Int(1)) + NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), UInt(5), Int(1), Int(1)) + NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), UInt(5), Int(2), Int(1)) + NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), UInt(5), Int(3), -Int(1)) + NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), UInt(5), Int(4), -Int(1)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Miscellaneous + //=------------------------------------------------------------------------= + + func testOverloadsAreUnambiguous() { + func becauseThisCompilesSuccessfully(_ x: inout T) { + XCTAssertNotNil(x.signum()) + } + } + + func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { + func becauseThisCompilesSuccessfully(_ x: inout T) { + XCTAssertNotNil(x.compared(to: 0)) + XCTAssertNotNil(x.compared(to: 0, at: 0)) + } + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Comparisons x Assertions +//*============================================================================* + +private func NBKAssertSignum( +_ operand: T, _ signum: Int, +file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual(Int(operand.signum() as Int), signum, file: file, line: line) + XCTAssertEqual(Int(operand.signum() as T ), signum, file: file, line: line) // stdlib +} + +private func NBKAssertComparisons( +_ lhs: T, _ rhs: T, _ signum: Int, +file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual(lhs == rhs, signum == 0, file: file, line: line) + XCTAssertEqual(lhs != rhs, signum != 0, file: file, line: line) + + XCTAssertEqual(lhs < rhs, signum == -1, file: file, line: line) + XCTAssertEqual(lhs <= rhs, signum != 1, file: file, line: line) + + XCTAssertEqual(lhs > rhs, signum == 1, file: file, line: line) + XCTAssertEqual(lhs >= rhs, signum != -1, file: file, line: line) + + XCTAssertEqual(lhs.compared(to: rhs), signum, file: file, line: line) +} + +private func NBKAssertComparisonsAtIndex( +_ lhs: T, _ rhs: T, _ index: Int, _ signum: Int, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + if index.isZero { + NBKAssertComparisons(lhs, rhs, signum, file: file, line: line) + } + //=------------------------------------------= + XCTAssertEqual(lhs.compared(to: rhs, at: index), signum, file: file, line: line) +} + +private func NBKAssertComparisonsByDigit( +_ lhs: T, _ rhs: T.Digit, _ signum: Int, +file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual(lhs == rhs, signum == 0, file: file, line: line) + XCTAssertEqual(lhs != rhs, signum != 0, file: file, line: line) + + XCTAssertEqual(lhs < rhs, signum == -1, file: file, line: line) + XCTAssertEqual(lhs <= rhs, signum != 1, file: file, line: line) + + XCTAssertEqual(lhs > rhs, signum == 1, file: file, line: line) + XCTAssertEqual(lhs >= rhs, signum != -1, file: file, line: line) + + XCTAssertEqual(lhs.compared(to: rhs), signum, file: file, line: line) +} + +private func NBKAssertComparisonsByDigitAtIndex( +_ lhs: T, _ rhs: T.Digit, _ index: Int, _ signum: Int, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + if index.isZero { + NBKAssertComparisonsByDigit(lhs, rhs, signum, file: file, line: line) + } + //=------------------------------------------= + XCTAssertEqual(lhs.compared(to: rhs, at: index), signum, file: file, line: line) +} + +#endif diff --git a/Tests/NBKTwosComplementKitTests/IntXL+Multiplication.swift b/Tests/NBKTwosComplementKitTests/IntXL+Multiplication.swift new file mode 100644 index 00000000..5b0ef5e8 --- /dev/null +++ b/Tests/NBKTwosComplementKitTests/IntXL+Multiplication.swift @@ -0,0 +1,172 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +import NBKTwosComplementKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Flexible Width x Multiplication x IntXL +//*============================================================================* + +final class NBKFlexibleWidthTestsOnMultiplicationAsIntXL: XCTestCase { + + typealias T = IntXL + typealias M = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testMultiplying() { + NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as W), T(words:[2, 0, 0, 0] as W), T(words:[ 2, 4, 6, 8, 0, 0, 0, 0] as W)) + NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as W), T(words:[0, 2, 0, 0] as W), T(words:[ 0, 2, 4, 6, 8, 0, 0, 0] as W)) + NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as W), T(words:[0, 0, 2, 0] as W), T(words:[ 0, 0, 2, 4, 6, 8, 0, 0] as W)) + NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as W), T(words:[0, 0, 0, 2] as W), T(words:[ 0, 0, 0, 2, 4, 6, 8, 0] as W)) + + NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as W), -T(words:[2, 0, 0, 0] as W), T(words:[~1, ~4, ~6, ~8, ~0, ~0, ~0, ~0] as W)) + NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as W), -T(words:[0, 2, 0, 0] as W), T(words:[ 0, ~1, ~4, ~6, ~8, ~0, ~0, ~0] as W)) + NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as W), -T(words:[0, 0, 2, 0] as W), T(words:[ 0, 0, ~1, ~4, ~6, ~8, ~0, ~0] as W)) + NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as W), -T(words:[0, 0, 0, 2] as W), T(words:[ 0, 0, 0, ~1, ~4, ~6, ~8, ~0] as W)) + + NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as W), T(words:[2, 0, 0, 0] as W), T(words:[~3, ~4, ~6, ~8, ~0, ~0, ~0, ~0] as W)) + NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as W), T(words:[0, 2, 0, 0] as W), T(words:[ 0, ~3, ~4, ~6, ~8, ~0, ~0, ~0] as W)) + NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as W), T(words:[0, 0, 2, 0] as W), T(words:[ 0, 0, ~3, ~4, ~6, ~8, ~0, ~0] as W)) + NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as W), T(words:[0, 0, 0, 2] as W), T(words:[ 0, 0, 0, ~3, ~4, ~6, ~8, ~0] as W)) + + NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as W), -T(words:[2, 0, 0, 0] as W), T(words:[ 4, 4, 6, 8, 0, 0, 0, 0] as W)) + NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as W), -T(words:[0, 2, 0, 0] as W), T(words:[ 0, 4, 4, 6, 8, 0, 0, 0] as W)) + NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as W), -T(words:[0, 0, 2, 0] as W), T(words:[ 0, 0, 4, 4, 6, 8, 0, 0] as W)) + NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as W), -T(words:[0, 0, 0, 2] as W), T(words:[ 0, 0, 0, 4, 4, 6, 8, 0] as W)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Digit + //=------------------------------------------------------------------------= + + func testMultiplyingByDigit() { + NBKAssertMultiplicationByDigit(T(words:[ 1, 2, 3, 4] as W), Int(2), T(words:[ 2, 4, 6, 8, 0] as W)) + NBKAssertMultiplicationByDigit(T(words:[ 1, 2, 3, 4] as W), -Int(2), T(words:[~1, ~4, ~6, ~8, ~0] as W)) + NBKAssertMultiplicationByDigit(T(words:[~1, ~2, ~3, ~4] as W), Int(2), T(words:[~3, ~4, ~6, ~8, ~0] as W)) + NBKAssertMultiplicationByDigit(T(words:[~1, ~2, ~3, ~4] as W), -Int(2), T(words:[ 4, 4, 6, 8, 0] as W)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Miscellaneous + //=------------------------------------------------------------------------= + + func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { + func becauseThisCompilesSuccessfully(_ x: inout T) { + XCTAssertNotNil(x *= 0) + XCTAssertNotNil(x * 0) + } + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Multiplication x UIntXL +//*============================================================================* + +final class NBKFlexibleWidthTestsOnMultiplicationAsUIntXL: XCTestCase { + + typealias T = UIntXL + typealias M = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testMultiplying() { + NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as W), T(words:[2, 0, 0, 0] as W), T(words:[ 2, 4, 6, 8, 0, 0, 0, 0] as W)) + NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as W), T(words:[0, 2, 0, 0] as W), T(words:[ 0, 2, 4, 6, 8, 0, 0, 0] as W)) + NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as W), T(words:[0, 0, 2, 0] as W), T(words:[ 0, 0, 2, 4, 6, 8, 0, 0] as W)) + NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as W), T(words:[0, 0, 0, 2] as W), T(words:[ 0, 0, 0, 2, 4, 6, 8, 0] as W)) + + NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as W), T(words:[2, 0, 0, 0] as W), T(words:[~3, ~4, ~6, ~8, 1, 0, 0, 0] as W)) + NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as W), T(words:[0, 2, 0, 0] as W), T(words:[ 0, ~3, ~4, ~6, ~8, 1, 0, 0] as W)) + NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as W), T(words:[0, 0, 2, 0] as W), T(words:[ 0, 0, ~3, ~4, ~6, ~8, 1, 0] as W)) + NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as W), T(words:[0, 0, 0, 2] as W), T(words:[ 0, 0, 0, ~3, ~4, ~6, ~8, 1] as W)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Digit + //=------------------------------------------------------------------------= + + func testMultipliedByDigit() { + NBKAssertMultiplicationByDigit(T(words:[1, 2, 3, 4] as W), UInt(0), T(words:[ 0, 0, 0, 0, 0] as W)) + NBKAssertMultiplicationByDigit(T(words:[1, 2, 3, 4] as W), UInt(1), T(words:[ 1, 2, 3, 4, 0] as W)) + NBKAssertMultiplicationByDigit(T(words:[1, 2, 3, 4] as W), UInt(2), T(words:[ 2, 4, 6, 8, 0] as W)) + + NBKAssertMultiplicationByDigit(T(words:[1, 2, 3, 4] as W), ~UInt(0), ~T(words:[ 0, 1, 1, 1, ~3] as W)) + NBKAssertMultiplicationByDigit(T(words:[1, 2, 3, 4] as W), ~UInt(1), ~T(words:[ 1, 3, 4, 5, ~3] as W)) + NBKAssertMultiplicationByDigit(T(words:[1, 2, 3, 4] as W), ~UInt(2), ~T(words:[ 2, 5, 7, 9, ~3] as W)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Digit x Addition + //=------------------------------------------------------------------------= + + func testMultiplicationByDigitWithAddition() { + NBKAssertMultiplicationByDigitWithAddition(T(words:[~0, ~0, ~0, ~0] as W), 0, 0, T(words:[ 0, 0, 0, 0, 0] as W)) + NBKAssertMultiplicationByDigitWithAddition(T(words:[~0, ~0, ~0, ~0] as W), 0, ~0, T(words:[~0, 0, 0, 0, 0] as W)) + NBKAssertMultiplicationByDigitWithAddition(T(words:[~0, ~0, ~0, ~0] as W), ~0, 0, T(words:[ 1, ~0, ~0, ~0, ~1] as W)) + NBKAssertMultiplicationByDigitWithAddition(T(words:[~0, ~0, ~0, ~0] as W), ~0, ~0, T(words:[ 0, 0, 0, 0, ~0] as W)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Miscellaneous + //=------------------------------------------------------------------------= + + func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { + func becauseThisCompilesSuccessfully(_ x: inout T) { + XCTAssertNotNil(x *= 0) + XCTAssertNotNil(x.multiply(by: 0, add: 0)) + + XCTAssertNotNil(x * 0) + XCTAssertNotNil(x.multiplied(by: 0, adding: 0)) + } + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Multiplication x Assertions +//*============================================================================* + +private func NBKAssertMultiplication( +_ lhs: T, _ rhs: T, _ result: T, +file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual( lhs * rhs, result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs *= rhs; return lhs }(), result, file: file, line: line) +} + +private func NBKAssertMultiplicationByDigit( +_ lhs: T, _ rhs: T.Digit, _ result: T, +file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual( lhs * rhs, result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs *= rhs; return lhs }(), result, file: file, line: line) +} + +//=----------------------------------------------------------------------------= +// MARK: + Unsigned +//=----------------------------------------------------------------------------= + +private func NBKAssertMultiplicationByDigitWithAddition( +_ lhs: UIntXL, _ rhs: UInt, _ carry: UInt, _ product: UIntXL, +file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual(lhs.multiplied(by: rhs, adding: carry), product, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs.multiply(by: rhs, add: carry); return lhs }(), product, file: file, line: line) +} + +#endif diff --git a/Tests/NBKTwosComplementKitTests/IntXL+Subtraction.swift b/Tests/NBKTwosComplementKitTests/IntXL+Subtraction.swift new file mode 100644 index 00000000..c8e4ac13 --- /dev/null +++ b/Tests/NBKTwosComplementKitTests/IntXL+Subtraction.swift @@ -0,0 +1,275 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +import NBKTwosComplementKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Flexible Width x Subtraction x IntXL +//*============================================================================* + +final class NBKFlexibleWidthTestsOnSubtractionAsIntXL: XCTestCase { + + typealias T = IntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testSubtracting() { + NBKAssertSubtraction(T( 1), T( 2), Int(0), T(-1)) + NBKAssertSubtraction(T( 1), T( 1), Int(0), T( 0)) + NBKAssertSubtraction(T( 1), T( 0), Int(0), T( 1)) + NBKAssertSubtraction(T( 1), T(-1), Int(0), T( 2)) + NBKAssertSubtraction(T( 1), T(-2), Int(0), T( 3)) + + NBKAssertSubtraction(T( 0), T( 2), Int(0), T(-2)) + NBKAssertSubtraction(T( 0), T( 1), Int(0), T(-1)) + NBKAssertSubtraction(T( 0), T( 0), Int(0), T( 0)) + NBKAssertSubtraction(T( 0), T(-1), Int(0), T( 1)) + NBKAssertSubtraction(T( 0), T(-2), Int(0), T( 2)) + + NBKAssertSubtraction(T(-1), T( 2), Int(0), T(-3)) + NBKAssertSubtraction(T(-1), T( 1), Int(0), T(-2)) + NBKAssertSubtraction(T(-1), T( 0), Int(0), T(-1)) + NBKAssertSubtraction(T(-1), T(-1), Int(0), T( 0)) + NBKAssertSubtraction(T(-1), T(-2), Int(0), T( 1)) + } + + func testSubtractingAtIndex() { + NBKAssertSubtraction(T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[~1, ~2, ~3, ~0] as W)) + NBKAssertSubtraction(T(words:[ 0, ~0, ~0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[~0, ~3, ~3, ~0] as W)) + NBKAssertSubtraction(T(words:[ 0, 0, ~0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[~0, ~2, ~4, ~0] as W)) + NBKAssertSubtraction(T(words:[ 0, 0, 0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[~0, ~2, ~3, ~1] as W)) + + NBKAssertSubtraction(T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[~0, ~1, ~2, ~3] as W)) + NBKAssertSubtraction(T(words:[ 0, ~0, ~0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[ 0, ~1, ~2, ~3] as W)) + NBKAssertSubtraction(T(words:[ 0, 0, ~0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[ 0, ~0, ~3, ~3] as W)) + NBKAssertSubtraction(T(words:[ 0, 0, 0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[ 0, ~0, ~2, ~4] as W)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Digit + //=------------------------------------------------------------------------= + + func testSubtractingDigit() { + NBKAssertSubtractionByDigit(T( 1), Int( 2), Int(0), T(-1)) + NBKAssertSubtractionByDigit(T( 1), Int( 1), Int(0), T( 0)) + NBKAssertSubtractionByDigit(T( 1), Int( 0), Int(0), T( 1)) + NBKAssertSubtractionByDigit(T( 1), Int(-1), Int(0), T( 2)) + NBKAssertSubtractionByDigit(T( 1), Int(-2), Int(0), T( 3)) + + NBKAssertSubtractionByDigit(T( 0), Int( 2), Int(0), T(-2)) + NBKAssertSubtractionByDigit(T( 0), Int( 1), Int(0), T(-1)) + NBKAssertSubtractionByDigit(T( 0), Int( 0), Int(0), T( 0)) + NBKAssertSubtractionByDigit(T( 0), Int(-1), Int(0), T( 1)) + NBKAssertSubtractionByDigit(T( 0), Int(-2), Int(0), T( 2)) + + NBKAssertSubtractionByDigit(T(-1), Int( 2), Int(0), T(-3)) + NBKAssertSubtractionByDigit(T(-1), Int( 1), Int(0), T(-2)) + NBKAssertSubtractionByDigit(T(-1), Int( 0), Int(0), T(-1)) + NBKAssertSubtractionByDigit(T(-1), Int(-1), Int(0), T( 0)) + NBKAssertSubtractionByDigit(T(-1), Int(-2), Int(0), T( 1)) + } + + func testSubtractingDigitAtIndex() { + NBKAssertSubtractionByDigit(T(words:[~0, ~0, ~0, ~0] as W), Int(3), Int(0), T(words:[~3, ~0, ~0, ~0] as W)) + NBKAssertSubtractionByDigit(T(words:[ 0, ~0, ~0, ~0] as W), Int(3), Int(0), T(words:[~2, ~1, ~0, ~0] as W)) + NBKAssertSubtractionByDigit(T(words:[ 0, 0, ~0, ~0] as W), Int(3), Int(0), T(words:[~2, ~0, ~1, ~0] as W)) + NBKAssertSubtractionByDigit(T(words:[ 0, 0, 0, ~0] as W), Int(3), Int(0), T(words:[~2, ~0, ~0, ~1] as W)) + + NBKAssertSubtractionByDigit(T(words:[~0, ~0, ~0, ~0] as W), Int(3), Int(1), T(words:[~0, ~3, ~0, ~0] as W)) + NBKAssertSubtractionByDigit(T(words:[ 0, ~0, ~0, ~0] as W), Int(3), Int(1), T(words:[ 0, ~3, ~0, ~0] as W)) + NBKAssertSubtractionByDigit(T(words:[ 0, 0, ~0, ~0] as W), Int(3), Int(1), T(words:[ 0, ~2, ~1, ~0] as W)) + NBKAssertSubtractionByDigit(T(words:[ 0, 0, 0, ~0] as W), Int(3), Int(1), T(words:[ 0, ~2, ~0, ~1] as W)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Miscellaneous + //=------------------------------------------------------------------------= + + func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { + func becauseThisCompilesSuccessfully(_ x: inout T) { + XCTAssertNotNil(x -= 0) + XCTAssertNotNil(x.subtract(0, at: 0)) + + XCTAssertNotNil(x - 0) + XCTAssertNotNil(x.subtracting(0, at: 0)) + } + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Subtraction x UIntXL +//*============================================================================* + +final class NBKFlexibleWidthTestsOnSubtractionAsUIntXL: XCTestCase { + + typealias T = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testSubtracting() { + NBKAssertSubtraction(T(3), T(0), Int(0), T(3)) + NBKAssertSubtraction(T(3), T(1), Int(0), T(2)) + NBKAssertSubtraction(T(3), T(2), Int(0), T(1)) + NBKAssertSubtraction(T(3), T(3), Int(0), T(0)) + } + + func testSubtractingReportingOverflow() { + NBKAssertSubtraction(T(1), T(0), Int(0), T(words:[ 1] as W)) + NBKAssertSubtraction(T(1), T(1), Int(0), T(words:[ 0] as W)) + NBKAssertSubtraction(T(1), T(2), Int(0), T(words:[~0] as W), true) + NBKAssertSubtraction(T(1), T(3), Int(0), T(words:[~1] as W), true) + } + + func testSubtractingAtIndex() { + NBKAssertSubtraction(T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[~1, ~2, ~3, ~0] as W)) + NBKAssertSubtraction(T(words:[ 0, ~0, ~0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[~0, ~3, ~3, ~0] as W)) + NBKAssertSubtraction(T(words:[ 0, 0, ~0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[~0, ~2, ~4, ~0] as W)) + NBKAssertSubtraction(T(words:[ 0, 0, 0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[~0, ~2, ~3, ~1] as W)) + + NBKAssertSubtraction(T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[~0, ~1, ~2, ~3] as W)) + NBKAssertSubtraction(T(words:[ 0, ~0, ~0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[ 0, ~1, ~2, ~3] as W)) + NBKAssertSubtraction(T(words:[ 0, 0, ~0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[ 0, ~0, ~3, ~3] as W)) + NBKAssertSubtraction(T(words:[ 0, 0, 0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[ 0, ~0, ~2, ~4] as W)) + } + + func testSubtractingAtIndexReportingOverflow() { + NBKAssertSubtraction(T(words:[ 1, 2, 3, 0] as W), T(words:[ 4, 5, 0, 0] as W), Int(0), T(words:[~2, ~3, 2, 0] as W)) + NBKAssertSubtraction(T(words:[ 1, 2, 3, 0] as W), T(words:[ 4, 5, 0, 0] as W), Int(1), T(words:[ 1, ~1, ~2, 0] as W), true) + NBKAssertSubtraction(T(words:[ 1, 2, 3, 0] as W), T(words:[ 4, 5, 0, 0] as W), Int(2), T(words:[ 1, 2, ~0, ~5] as W), true) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Digit + //=------------------------------------------------------------------------= + + func testSubtractingDigit() { + NBKAssertSubtractionByDigit(T(3), UInt(0), Int(0), T(3)) + NBKAssertSubtractionByDigit(T(3), UInt(1), Int(0), T(2)) + NBKAssertSubtractionByDigit(T(3), UInt(2), Int(0), T(1)) + NBKAssertSubtractionByDigit(T(3), UInt(3), Int(0), T(0)) + } + + func testSubtractingDigitReportingOverflow() { + NBKAssertSubtractionByDigit(T(1), UInt(0), Int(0), T(words:[ 1] as W)) + NBKAssertSubtractionByDigit(T(1), UInt(1), Int(0), T(words:[ 0] as W)) + NBKAssertSubtractionByDigit(T(1), UInt(2), Int(0), T(words:[~0] as W), true) + NBKAssertSubtractionByDigit(T(1), UInt(3), Int(0), T(words:[~1] as W), true) + } + + func testSubtractingDigitAtIndex() { + NBKAssertSubtractionByDigit(T(words:[~0, ~0, ~0, ~0] as W), UInt(3), Int(0), T(words:[~3, ~0, ~0, ~0] as W)) + NBKAssertSubtractionByDigit(T(words:[ 0, ~0, ~0, ~0] as W), UInt(3), Int(0), T(words:[~2, ~1, ~0, ~0] as W)) + NBKAssertSubtractionByDigit(T(words:[ 0, 0, ~0, ~0] as W), UInt(3), Int(0), T(words:[~2, ~0, ~1, ~0] as W)) + NBKAssertSubtractionByDigit(T(words:[ 0, 0, 0, ~0] as W), UInt(3), Int(0), T(words:[~2, ~0, ~0, ~1] as W)) + + NBKAssertSubtractionByDigit(T(words:[~0, ~0, ~0, ~0] as W), UInt(3), Int(1), T(words:[~0, ~3, ~0, ~0] as W)) + NBKAssertSubtractionByDigit(T(words:[ 0, ~0, ~0, ~0] as W), UInt(3), Int(1), T(words:[ 0, ~3, ~0, ~0] as W)) + NBKAssertSubtractionByDigit(T(words:[ 0, 0, ~0, ~0] as W), UInt(3), Int(1), T(words:[ 0, ~2, ~1, ~0] as W)) + NBKAssertSubtractionByDigit(T(words:[ 0, 0, 0, ~0] as W), UInt(3), Int(1), T(words:[ 0, ~2, ~0, ~1] as W)) + } + + func testSubtractingDigitAtIndexReportingOverflow() { + NBKAssertSubtractionByDigit(T(words:[ 1, 2, 3, 0] as W), UInt(5), Int(0), T(words:[~3, 1, 3, 0] as W)) + NBKAssertSubtractionByDigit(T(words:[ 1, 2, 3, 0] as W), UInt(5), Int(1), T(words:[ 1, ~2, 2, 0] as W)) + NBKAssertSubtractionByDigit(T(words:[ 1, 2, 3, 0] as W), UInt(5), Int(2), T(words:[ 1, 2, ~1, 0] as W), true) + NBKAssertSubtractionByDigit(T(words:[ 1, 2, 3, 0] as W), UInt(5), Int(3), T(words:[ 1, 2, 3, ~4] as W), true) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Miscellaneous + //=------------------------------------------------------------------------= + + func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { + func becauseThisCompilesSuccessfully(_ x: inout T) { + XCTAssertNotNil(x -= 0) + XCTAssertNotNil(x.subtract(0, at: 0)) + XCTAssertNotNil(x.subtractReportingOverflow(0, at: 0)) + + XCTAssertNotNil(x - 0) + XCTAssertNotNil(x.subtracting(0, at: 0)) + XCTAssertNotNil(x.subtractingReportingOverflow(0, at: 0)) + } + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Subtraction x Assertions +//*============================================================================* + +private func NBKAssertSubtraction( +_ lhs: T, _ rhs: T, _ index: Int, _ partialValue: T, _ overflow: Bool = false, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + if !overflow, index.isZero { + XCTAssertEqual( lhs - rhs, partialValue, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs -= rhs; return lhs }(), partialValue, file: file, line: line) + + XCTAssertEqual(lhs.subtracting(rhs, at: Int.zero), partialValue, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs.subtract(rhs, at: Int.zero); return lhs }(), partialValue, file: file, line: line) + } + //=------------------------------------------= + guard let lhs = lhs as? UIntXL, let rhs = rhs as? UIntXL, let partialValue = partialValue as? UIntXL else { return } + //=------------------------------------------= + if index.isZero { + XCTAssertEqual(lhs.subtractingReportingOverflow(rhs).partialValue, partialValue, file: file, line: line) + XCTAssertEqual(lhs.subtractingReportingOverflow(rhs).overflow, overflow, file: file, line: line) + + XCTAssertEqual({ var x = lhs; let _ = x.subtractReportingOverflow(rhs); return x }(), partialValue, file: file, line: line) + XCTAssertEqual({ var x = lhs; let o = x.subtractReportingOverflow(rhs); return o }(), overflow, file: file, line: line) + } + //=------------------------------------------= + XCTAssertEqual(lhs.subtractingReportingOverflow(rhs, at: index).partialValue, partialValue, file: file, line: line) + XCTAssertEqual(lhs.subtractingReportingOverflow(rhs, at: index).overflow, overflow, file: file, line: line) + + XCTAssertEqual({ var x = lhs; let _ = x.subtractReportingOverflow(rhs, at: index); return x }(), partialValue, file: file, line: line) + XCTAssertEqual({ var x = lhs; let o = x.subtractReportingOverflow(rhs, at: index); return o }(), overflow, file: file, line: line) +} + +private func NBKAssertSubtractionByDigit( +_ lhs: T, _ rhs: T.Digit, _ index: Int, _ partialValue: T, _ overflow: Bool = false, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + if !overflow, index.isZero { + XCTAssertEqual( lhs - rhs, partialValue, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs -= rhs; return lhs }(), partialValue, file: file, line: line) + + XCTAssertEqual(lhs.subtracting(rhs, at: Int.zero), partialValue, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs.subtract(rhs, at: Int.zero); return lhs }(), partialValue, file: file, line: line) + } + //=------------------------------------------= + guard let lhs = lhs as? UIntXL, let rhs = rhs as? UIntXL.Digit, let partialValue = partialValue as? UIntXL else { return } + //=------------------------------------------= + if index.isZero { + XCTAssertEqual(lhs.subtractingReportingOverflow(rhs).partialValue, partialValue, file: file, line: line) + XCTAssertEqual(lhs.subtractingReportingOverflow(rhs).overflow, overflow, file: file, line: line) + + XCTAssertEqual({ var x = lhs; let _ = x.subtractReportingOverflow(rhs); return x }(), partialValue, file: file, line: line) + XCTAssertEqual({ var x = lhs; let o = x.subtractReportingOverflow(rhs); return o }(), overflow, file: file, line: line) + } + //=------------------------------------------= + XCTAssertEqual(lhs.subtractingReportingOverflow(rhs, at: index).partialValue, partialValue, file: file, line: line) + XCTAssertEqual(lhs.subtractingReportingOverflow(rhs, at: index).overflow, overflow, file: file, line: line) + + XCTAssertEqual({ var x = lhs; let _ = x.subtractReportingOverflow(rhs, at: index); return x }(), partialValue, file: file, line: line) + XCTAssertEqual({ var x = lhs; let o = x.subtractReportingOverflow(rhs, at: index); return o }(), overflow, file: file, line: line) +} + +#endif From d0756c2c8e0561005f2b801338fd1290038b68ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Thu, 14 Sep 2023 12:06:45 +0200 Subject: [PATCH 066/133] [2's rework] Day 3 (#44). --- .swiftpm/Numberick-Benchmarks.xctestplan | 7 + .swiftpm/Numberick.xctestplan | 7 + .../NBKTwosComplementKit-Benchmarks.xcscheme | 25 + .../xcschemes/Numberick-Benchmarks.xcscheme | 3 + .../xcshareddata/xcschemes/Numberick.xcscheme | 3 + .../NBKTwosComplementKit/IntXL+Division.swift | 94 -- .../NBKTwosComplementKit/IntXLOrUIntXL.swift | 6 + ... => NBKFlexibleWidth+Addition+Digit.swift} | 0 ....swift => NBKFlexibleWidth+Addition.swift} | 0 ...Bits.swift => NBKFlexibleWidth+Bits.swift} | 0 ...ift => NBKFlexibleWidth+Comparisons.swift} | 0 ...ift => NBKFlexibleWidth+Complements.swift} | 18 +- ...Data.swift => NBKFlexibleWidth+Data.swift} | 16 + ... => NBKFlexibleWidth+Division+Digit.swift} | 9 +- .../NBKFlexibleWidth+Division.swift | 174 ++++ ....swift => NBKFlexibleWidth+Literals.swift} | 29 +- ...gic.swift => NBKFlexibleWidth+Logic.swift} | 0 ...KFlexibleWidth+Multiplication+Digit.swift} | 0 ... => NBKFlexibleWidth+Multiplication.swift} | 0 ...s.swift => NBKFlexibleWidth+Numbers.swift} | 7 + ...ts.swift => NBKFlexibleWidth+Shifts.swift} | 90 ++ ...FlexibleWidth+Storage+Normalization.swift} | 0 ...ft => NBKFlexibleWidth+Storage+Size.swift} | 0 ...e.swift => NBKFlexibleWidth+Storage.swift} | 0 ... NBKFlexibleWidth+Subtraction+Digit.swift} | 0 ...ift => NBKFlexibleWidth+Subtraction.swift} | 0 ...Text.swift => NBKFlexibleWidth+Text.swift} | 0 ...te.swift => NBKFlexibleWidth+Update.swift} | 0 ... => NBKFlexibleWidth+Words+Pointers.swift} | 0 ...rds.swift => NBKFlexibleWidth+Words.swift} | 0 .../{IntXL.swift => NBKFlexibleWidth.swift} | 0 .../NBKFlexibleWidth+Text.swift | 11 +- .../Blank.swift | 1 - .../NBKFlexibleWidth+Addition.swift | 142 +++ .../NBKFlexibleWidth+Bits.swift | 228 +++++ .../NBKFlexibleWidth+Comparisons.swift | 280 ++++++ .../NBKFlexibleWidth+Complements.swift | 299 +++++++ .../NBKFlexibleWidth+Division.swift | 240 ++++++ .../NBKFlexibleWidth+Logic.swift | 117 +++ .../NBKFlexibleWidth+Multiplication.swift | 98 +++ .../NBKFlexibleWidth+Numbers.swift | 816 ++++++++++++++++++ .../NBKFlexibleWidth+Shifts.swift | 284 ++++++ .../NBKFlexibleWidth+Subtraction.swift | 142 +++ .../NBKFlexibleWidth+Text.swift | 200 +++++ .../NBKFlexibleWidth+Words.swift | 72 ++ .../NBKFlexibleWidth.swift | 68 ++ ....swift => NBKFlexibleWidth+Addition.swift} | 0 ...Bits.swift => NBKFlexibleWidth+Bits.swift} | 0 ...ift => NBKFlexibleWidth+Comparisons.swift} | 0 .../NBKFlexibleWidth+Complements.swift | 210 +++++ .../NBKFlexibleWidth+Division.swift | 371 ++++++++ .../NBKFlexibleWidth+Literals.swift | 168 ++++ ...gic.swift => NBKFlexibleWidth+Logic.swift} | 0 ... => NBKFlexibleWidth+Multiplication.swift} | 0 .../NBKFlexibleWidth+Numbers.swift | 573 ++++++++++++ ...ts.swift => NBKFlexibleWidth+Shifts.swift} | 0 ...ift => NBKFlexibleWidth+Subtraction.swift} | 0 ...Text.swift => NBKFlexibleWidth+Text.swift} | 0 ...rds.swift => NBKFlexibleWidth+Words.swift} | 0 .../{IntXL.swift => NBKFlexibleWidth.swift} | 0 60 files changed, 4702 insertions(+), 106 deletions(-) delete mode 100644 Sources/NBKTwosComplementKit/IntXL+Division.swift rename Sources/NBKTwosComplementKit/{IntXL+Addition+Digit.swift => NBKFlexibleWidth+Addition+Digit.swift} (100%) rename Sources/NBKTwosComplementKit/{IntXL+Addition.swift => NBKFlexibleWidth+Addition.swift} (100%) rename Sources/NBKTwosComplementKit/{IntXL+Bits.swift => NBKFlexibleWidth+Bits.swift} (100%) rename Sources/NBKTwosComplementKit/{IntXL+Comparisons.swift => NBKFlexibleWidth+Comparisons.swift} (100%) rename Sources/NBKTwosComplementKit/{IntXL+Complements.swift => NBKFlexibleWidth+Complements.swift} (91%) rename Sources/NBKTwosComplementKit/{IntXL+Data.swift => NBKFlexibleWidth+Data.swift} (62%) rename Sources/NBKTwosComplementKit/{IntXL+Division+Digit.swift => NBKFlexibleWidth+Division+Digit.swift} (88%) create mode 100644 Sources/NBKTwosComplementKit/NBKFlexibleWidth+Division.swift rename Sources/NBKTwosComplementKit/{IntXL+Literals.swift => NBKFlexibleWidth+Literals.swift} (72%) rename Sources/NBKTwosComplementKit/{IntXL+Logic.swift => NBKFlexibleWidth+Logic.swift} (100%) rename Sources/NBKTwosComplementKit/{IntXL+Multiplication+Digit.swift => NBKFlexibleWidth+Multiplication+Digit.swift} (100%) rename Sources/NBKTwosComplementKit/{IntXL+Multiplication.swift => NBKFlexibleWidth+Multiplication.swift} (100%) rename Sources/NBKTwosComplementKit/{IntXL+Numbers.swift => NBKFlexibleWidth+Numbers.swift} (95%) rename Sources/NBKTwosComplementKit/{IntXL+Shifts.swift => NBKFlexibleWidth+Shifts.swift} (78%) rename Sources/NBKTwosComplementKit/{IntXL+Storage+Normalization.swift => NBKFlexibleWidth+Storage+Normalization.swift} (100%) rename Sources/NBKTwosComplementKit/{IntXL+Storage+Size.swift => NBKFlexibleWidth+Storage+Size.swift} (100%) rename Sources/NBKTwosComplementKit/{IntXL+Storage.swift => NBKFlexibleWidth+Storage.swift} (100%) rename Sources/NBKTwosComplementKit/{IntXL+Subtraction+Digit.swift => NBKFlexibleWidth+Subtraction+Digit.swift} (100%) rename Sources/NBKTwosComplementKit/{IntXL+Subtraction.swift => NBKFlexibleWidth+Subtraction.swift} (100%) rename Sources/NBKTwosComplementKit/{IntXL+Text.swift => NBKFlexibleWidth+Text.swift} (100%) rename Sources/NBKTwosComplementKit/{IntXL+Update.swift => NBKFlexibleWidth+Update.swift} (100%) rename Sources/NBKTwosComplementKit/{IntXL+Words+Pointers.swift => NBKFlexibleWidth+Words+Pointers.swift} (100%) rename Sources/NBKTwosComplementKit/{IntXL+Words.swift => NBKFlexibleWidth+Words.swift} (100%) rename Sources/NBKTwosComplementKit/{IntXL.swift => NBKFlexibleWidth.swift} (100%) delete mode 100644 Tests/NBKTwosComplementKitBenchmarks/Blank.swift create mode 100644 Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Addition.swift create mode 100644 Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Bits.swift create mode 100644 Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Comparisons.swift create mode 100644 Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Complements.swift create mode 100644 Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Division.swift create mode 100644 Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Logic.swift create mode 100644 Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Multiplication.swift create mode 100644 Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Numbers.swift create mode 100644 Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Shifts.swift create mode 100644 Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Subtraction.swift create mode 100644 Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Text.swift create mode 100644 Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Words.swift create mode 100644 Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth.swift rename Tests/NBKTwosComplementKitTests/{IntXL+Addition.swift => NBKFlexibleWidth+Addition.swift} (100%) rename Tests/NBKTwosComplementKitTests/{IntXL+Bits.swift => NBKFlexibleWidth+Bits.swift} (100%) rename Tests/NBKTwosComplementKitTests/{IntXL+Comparisons.swift => NBKFlexibleWidth+Comparisons.swift} (100%) create mode 100644 Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Complements.swift create mode 100644 Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Division.swift create mode 100644 Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Literals.swift rename Tests/NBKTwosComplementKitTests/{IntXL+Logic.swift => NBKFlexibleWidth+Logic.swift} (100%) rename Tests/NBKTwosComplementKitTests/{IntXL+Multiplication.swift => NBKFlexibleWidth+Multiplication.swift} (100%) create mode 100644 Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Numbers.swift rename Tests/NBKTwosComplementKitTests/{IntXL+Shifts.swift => NBKFlexibleWidth+Shifts.swift} (100%) rename Tests/NBKTwosComplementKitTests/{IntXL+Subtraction.swift => NBKFlexibleWidth+Subtraction.swift} (100%) rename Tests/NBKTwosComplementKitTests/{IntXL+Text.swift => NBKFlexibleWidth+Text.swift} (100%) rename Tests/NBKTwosComplementKitTests/{IntXL+Words.swift => NBKFlexibleWidth+Words.swift} (100%) rename Tests/NBKTwosComplementKitTests/{IntXL.swift => NBKFlexibleWidth.swift} (100%) diff --git a/.swiftpm/Numberick-Benchmarks.xctestplan b/.swiftpm/Numberick-Benchmarks.xctestplan index b7a219a1..40ff8ef4 100644 --- a/.swiftpm/Numberick-Benchmarks.xctestplan +++ b/.swiftpm/Numberick-Benchmarks.xctestplan @@ -42,6 +42,13 @@ "identifier" : "NBKFlexibleWidthKitBenchmarks", "name" : "NBKFlexibleWidthKitBenchmarks" } + }, + { + "target" : { + "containerPath" : "container:", + "identifier" : "NBKTwosComplementKitBenchmarks", + "name" : "NBKTwosComplementKitBenchmarks" + } } ], "version" : 1 diff --git a/.swiftpm/Numberick.xctestplan b/.swiftpm/Numberick.xctestplan index 74306fdc..5116b0ed 100644 --- a/.swiftpm/Numberick.xctestplan +++ b/.swiftpm/Numberick.xctestplan @@ -50,6 +50,13 @@ "identifier" : "NBKFlexibleWidthKitTests", "name" : "NBKFlexibleWidthKitTests" } + }, + { + "target" : { + "containerPath" : "container:", + "identifier" : "NBKTwosComplementKitTests", + "name" : "NBKTwosComplementKitTests" + } } ], "version" : 1 diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/NBKTwosComplementKit-Benchmarks.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/NBKTwosComplementKit-Benchmarks.xcscheme index e22fac90..dd6ad91a 100644 --- a/.swiftpm/xcode/xcshareddata/xcschemes/NBKTwosComplementKit-Benchmarks.xcscheme +++ b/.swiftpm/xcode/xcshareddata/xcschemes/NBKTwosComplementKit-Benchmarks.xcscheme @@ -5,6 +5,22 @@ + + + + + + + + + + diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/Numberick-Benchmarks.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/Numberick-Benchmarks.xcscheme index 8cf9cef5..bf798a13 100644 --- a/.swiftpm/xcode/xcshareddata/xcschemes/Numberick-Benchmarks.xcscheme +++ b/.swiftpm/xcode/xcshareddata/xcschemes/Numberick-Benchmarks.xcscheme @@ -41,6 +41,9 @@ + + + + Bool { - let pvo: PVO = self.dividedReportingOverflow(by: other) - self = pvo.partialValue - return pvo.overflow as Bool - } - - @inlinable public func dividedReportingOverflow(by other: Self) -> PVO { - let qro: PVO> = self.quotientAndRemainderReportingOverflow(dividingBy: other) - return PVO(qro.partialValue.quotient, qro.overflow) - } - - @inlinable public mutating func formRemainderReportingOverflow(dividingBy other: Self) -> Bool { - let pvo: PVO = self.remainderReportingOverflow(dividingBy: other) - self = pvo.partialValue - return pvo.overflow as Bool - } - - @inlinable public func remainderReportingOverflow(dividingBy other: Self) -> PVO { - let qro: PVO> = self.quotientAndRemainderReportingOverflow(dividingBy: other) - return PVO(qro.partialValue.remainder, qro.overflow) - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Division x IntXL -//*============================================================================* - -extension IntXL { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable public func quotientAndRemainderReportingOverflow(dividingBy other: Self) -> PVO> { - fatalError("TODO") - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Division x UIntXL -//*============================================================================* - -extension UIntXL { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable public func quotientAndRemainderReportingOverflow(dividingBy other: Self) -> PVO> { - self.quotientAndRemainderReportingOverflowAsNormal(dividingBy: other) - } -} - -//=----------------------------------------------------------------------------= -// MARK: + Normal -//=----------------------------------------------------------------------------= - -extension UIntXL { - - //=------------------------------------------------------------------------= - // MARK: Transformations x Private - //=------------------------------------------------------------------------= - - @inlinable func quotientAndRemainderReportingOverflowAsNormal(dividingBy other: Self) -> PVO> { - var (remainder) = self - let (quotient, overflow) = remainder.formRemainderWithQuotientReportingOverflowAsNormal(dividingBy: other) - return PVO(QR(quotient, remainder), overflow) - } - - @inlinable mutating func formRemainderWithQuotientReportingOverflowAsNormal(dividingBy other: Self) -> PVO { - fatalError("TODO") - } -} diff --git a/Sources/NBKTwosComplementKit/IntXLOrUIntXL.swift b/Sources/NBKTwosComplementKit/IntXLOrUIntXL.swift index a24fbf2e..4b540ef6 100644 --- a/Sources/NBKTwosComplementKit/IntXLOrUIntXL.swift +++ b/Sources/NBKTwosComplementKit/IntXLOrUIntXL.swift @@ -24,6 +24,12 @@ Digit: NBKCoreInteger, Magnitude == UIntXL { func compared(to other: Digit, at index: Int) -> Int + //=------------------------------------------------------------------------= + // MARK: Details x Numbers + //=------------------------------------------------------------------------= + + init(digit: Digit, at index: Int) + //=------------------------------------------------------------------------= // MARK: Details x Addition //=------------------------------------------------------------------------= diff --git a/Sources/NBKTwosComplementKit/IntXL+Addition+Digit.swift b/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Addition+Digit.swift similarity index 100% rename from Sources/NBKTwosComplementKit/IntXL+Addition+Digit.swift rename to Sources/NBKTwosComplementKit/NBKFlexibleWidth+Addition+Digit.swift diff --git a/Sources/NBKTwosComplementKit/IntXL+Addition.swift b/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Addition.swift similarity index 100% rename from Sources/NBKTwosComplementKit/IntXL+Addition.swift rename to Sources/NBKTwosComplementKit/NBKFlexibleWidth+Addition.swift diff --git a/Sources/NBKTwosComplementKit/IntXL+Bits.swift b/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Bits.swift similarity index 100% rename from Sources/NBKTwosComplementKit/IntXL+Bits.swift rename to Sources/NBKTwosComplementKit/NBKFlexibleWidth+Bits.swift diff --git a/Sources/NBKTwosComplementKit/IntXL+Comparisons.swift b/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Comparisons.swift similarity index 100% rename from Sources/NBKTwosComplementKit/IntXL+Comparisons.swift rename to Sources/NBKTwosComplementKit/NBKFlexibleWidth+Comparisons.swift diff --git a/Sources/NBKTwosComplementKit/IntXL+Complements.swift b/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Complements.swift similarity index 91% rename from Sources/NBKTwosComplementKit/IntXL+Complements.swift rename to Sources/NBKTwosComplementKit/NBKFlexibleWidth+Complements.swift index 181bf19b..897d6829 100644 --- a/Sources/NBKTwosComplementKit/IntXL+Complements.swift +++ b/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Complements.swift @@ -21,7 +21,10 @@ extension PrivateIntXLOrUIntXL { @inlinable public mutating func formOnesComplement() { self.storage.formOnesComplement() - self.storage.normalize() + + if !Self.isSigned { + self.storage.normalize() + } } @inlinable public func onesComplement() -> Self { @@ -91,11 +94,20 @@ extension IntXL { //=------------------------------------------------------------------------= @inlinable public mutating func negateReportingOverflow() -> Bool { - self.formTwosComplement(); return false + let isTwosComplementMinValue = self.storage.formTwosComplementReportingOverflow() + if isTwosComplementMinValue { + self.storage.append(0 as UInt) + } else { + self.storage.normalize() + } + + return false as Bool } @inlinable public func negatedReportingOverflow() -> PVO { - PVO(self.twosComplement(), false) + var partialValue = self + let overflow = partialValue.negateReportingOverflow() + return PVO(partialValue, overflow) } } diff --git a/Sources/NBKTwosComplementKit/IntXL+Data.swift b/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Data.swift similarity index 62% rename from Sources/NBKTwosComplementKit/IntXL+Data.swift rename to Sources/NBKTwosComplementKit/NBKFlexibleWidth+Data.swift index d6561014..b4e4f79c 100644 --- a/Sources/NBKTwosComplementKit/IntXL+Data.swift +++ b/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Data.swift @@ -9,6 +9,22 @@ import NBKCoreKit +//*============================================================================* +// MARK: * NBK x Flexible Width x Data +//*============================================================================* + +extension PrivateIntXLOrUIntXL { + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + /// Creates a new instance with unsafe access to its uninitialized memory. + @inlinable static func uninitialized(count: Int, body: (inout NBK.UnsafeMutableWords) -> Void) -> Self { + Self(normalizing: Storage.uninitialized(count: count, body: body)) + } +} + //*============================================================================* // MARK: * NBK x Flexible Width x Data x Storage //*============================================================================* diff --git a/Sources/NBKTwosComplementKit/IntXL+Division+Digit.swift b/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Division+Digit.swift similarity index 88% rename from Sources/NBKTwosComplementKit/IntXL+Division+Digit.swift rename to Sources/NBKTwosComplementKit/NBKFlexibleWidth+Division+Digit.swift index 45e8c6b3..1f3c0aa3 100644 --- a/Sources/NBKTwosComplementKit/IntXL+Division+Digit.swift +++ b/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Division+Digit.swift @@ -53,7 +53,14 @@ extension IntXL { //=------------------------------------------------------------------------= @_disfavoredOverload @inlinable public func quotientAndRemainderReportingOverflow(dividingBy other: Digit) -> PVO> { - fatalError("TODO") + let lhsSign = FloatingPointSign(self .isLessThanZero) + let rhsSign = FloatingPointSign(other.isLessThanZero) + + let qro: PVO> = self.magnitude.quotientAndRemainderReportingOverflow(dividingBy: other.magnitude) + + let quotient = Self(sign: rhsSign ^ lhsSign, magnitude: qro.partialValue.quotient ) + let remainder = Self.Digit.init(sign: lhsSign, magnitude: qro.partialValue.remainder)! + return PVO(QR(quotient, remainder), qro.overflow) } } diff --git a/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Division.swift b/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Division.swift new file mode 100644 index 00000000..879663c0 --- /dev/null +++ b/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Division.swift @@ -0,0 +1,174 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x Division +//*============================================================================* + +extension IntXLOrUIntXL { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public mutating func divideReportingOverflow(by other: Self) -> Bool { + let pvo: PVO = self.dividedReportingOverflow(by: other) + self = pvo.partialValue + return pvo.overflow as Bool + } + + @inlinable public func dividedReportingOverflow(by other: Self) -> PVO { + let qro: PVO> = self.quotientAndRemainderReportingOverflow(dividingBy: other) + return PVO(qro.partialValue.quotient, qro.overflow) + } + + @inlinable public mutating func formRemainderReportingOverflow(dividingBy other: Self) -> Bool { + let pvo: PVO = self.remainderReportingOverflow(dividingBy: other) + self = pvo.partialValue + return pvo.overflow as Bool + } + + @inlinable public func remainderReportingOverflow(dividingBy other: Self) -> PVO { + let qro: PVO> = self.quotientAndRemainderReportingOverflow(dividingBy: other) + return PVO(qro.partialValue.remainder, qro.overflow) + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Division x IntXL +//*============================================================================* + +extension IntXL { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public func quotientAndRemainderReportingOverflow(dividingBy other: Self) -> PVO> { + let lhsSign = FloatingPointSign(self .isLessThanZero) + let rhsSign = FloatingPointSign(other.isLessThanZero) + + let qro: PVO> = self.magnitude.quotientAndRemainderReportingOverflow(dividingBy: other.magnitude) + + let quotient = Self(sign: rhsSign ^ lhsSign, magnitude: qro.partialValue.quotient ) + let remainder = Self(sign: /*---*/ lhsSign, magnitude: qro.partialValue.remainder) + return PVO(QR(quotient, remainder), qro.overflow) + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Division x UIntXL +//*============================================================================* + +extension UIntXL { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public func quotientAndRemainderReportingOverflow(dividingBy other: Self) -> PVO> { + self.quotientAndRemainderReportingOverflowAsNormal(dividingBy: other) + } +} + +//=----------------------------------------------------------------------------= +// MARK: + Normal +//=----------------------------------------------------------------------------= + +extension UIntXL { + + //=------------------------------------------------------------------------= + // MARK: Transformations x Private + //=------------------------------------------------------------------------= + + @inlinable func quotientAndRemainderReportingOverflowAsNormal(dividingBy other: Self) -> PVO> { + var (remainder) = self + let (quotient, overflow) = remainder.formRemainderWithQuotientReportingOverflowAsNormal(dividingBy: other) + return PVO(QR(quotient, remainder), overflow) + } + + @inlinable mutating func formRemainderWithQuotientReportingOverflowAsNormal(dividingBy other: Self) -> PVO { + //=--------------------------------------= + // divisor is zero + //=--------------------------------------= + if other.isZero { + return PVO(self, true) + } + //=--------------------------------------= + // divisor is one word + //=--------------------------------------= + if other.storage.elements.count == 1 { + let qr = self.quotientAndRemainder(dividingBy: other.storage.elements.first!) + self.update(qr.remainder) + return PVO(qr.quotient, false) + } + //=--------------------------------------= + // divisor is greater than or equal + //=--------------------------------------= + let comparison = other.compared(to: self) + if comparison >= 0 { + if comparison.isZero { + self.updateZeroValue() + return PVO(001, false) + } else { + return PVO(000, false) + } + } + //=--------------------------------------= + // shift to clamp approximation + //=--------------------------------------= + var divisor = other.storage + let shift = divisor.elements.last!.leadingZeroBitCount as Int + divisor.bitshiftLeft(words: Int.zero, bits: shift) + let divisorLast0 = divisor.elements[divisor.elements.endIndex - 1] as UInt + assert(divisorLast0.mostSignificantBit) + + var remainderIndex = self.storage.elements.endIndex + self.storage.append(0) + self.storage.bitshiftLeft(words: Int.zero, bits: shift) + //=--------------------------------------= + // division: approximate quotient digits + //=--------------------------------------= + var quotientIndex = remainderIndex - divisor.elements.endIndex as Int + var quotient = Storage.uninitialized(count: quotientIndex + 1) { quotient in + loop: repeat { + let remainderLast0 = self.storage.elements[remainderIndex] + self.storage.elements.formIndex(before: &remainderIndex) + let remainderLast1 = self.storage.elements[remainderIndex] + //=------------------------------= + var digit: UInt + if divisorLast0 == remainderLast0 { + digit = UInt.max + } else { + digit = divisorLast0.dividingFullWidth(HL(remainderLast0, remainderLast1)).quotient + } + //=------------------------------= + if !digit.isZero { + var overflow = self.storage.subtract(divisor, times: digit, plus: UInt.zero, plus: false, at: quotientIndex) + decrement: while overflow { + _ = digit.subtractReportingOverflow(1 as UInt) + overflow = !self.storage.add(divisor, plus: false, at: quotientIndex) + } + } + //=------------------------------= + quotient[quotientIndex] = digit + quotient.formIndex(before: "ientIndex) + } while quotientIndex >= quotient.startIndex + } + //=--------------------------------------= + // undo shift before division + //=--------------------------------------= + quotient.normalize() + self.storage.bitshiftRight(words: Int.zero, bits: shift) + self.storage.normalize() + return PVO(Self(unchecked: quotient), false) + } +} diff --git a/Sources/NBKTwosComplementKit/IntXL+Literals.swift b/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Literals.swift similarity index 72% rename from Sources/NBKTwosComplementKit/IntXL+Literals.swift rename to Sources/NBKTwosComplementKit/NBKFlexibleWidth+Literals.swift index 102d7612..b7b585f5 100644 --- a/Sources/NBKTwosComplementKit/IntXL+Literals.swift +++ b/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Literals.swift @@ -13,15 +13,42 @@ import NBKCoreKit // MARK: * NBK x Flexible Width x Literals //*============================================================================* -extension IntXLOrUIntXL { +extension PrivateIntXLOrUIntXL { //=-------------------------------------------------------------------------= // MARK: Details x Integer Literal Type //=-------------------------------------------------------------------------= + + #if SBI && swift(>=5.8) + + @inlinable public init(integerLiteral source: StaticBigInt) { + if let value = Self(exactlyIntegerLiteral: source) { self = value } else { + preconditionFailure("\(Self.description) cannot represent \(source)") + } + } + @inlinable public init?(exactlyIntegerLiteral source: StaticBigInt) { + guard Self.isSigned || source.signum() >= 0 as Int else { return nil } + //=--------------------------------------= + let bitWidth = Swift.max(1, source.bitWidth - Int(bit: !Self.isSigned)) + let major = NBK .quotientDividingByBitWidthAssumingIsAtLeastZero(bitWidth) + let minor = NBK.remainderDividingByBitWidthAssumingIsAtLeastZero(bitWidth) + let count = major &+ Int(bit: minor.isMoreThanZero) + //=--------------------------------------= + self = Self.uninitialized(count: count) { words in + for index in words.indices { + words.baseAddress!.advanced(by: index).initialize(to: source[index]) + } + } + } + + #else + @inlinable public init(integerLiteral source: Digit) { self.init(digit: source) } + + #endif //=------------------------------------------------------------------------= // MARK: Details x String Literal Type diff --git a/Sources/NBKTwosComplementKit/IntXL+Logic.swift b/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Logic.swift similarity index 100% rename from Sources/NBKTwosComplementKit/IntXL+Logic.swift rename to Sources/NBKTwosComplementKit/NBKFlexibleWidth+Logic.swift diff --git a/Sources/NBKTwosComplementKit/IntXL+Multiplication+Digit.swift b/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Multiplication+Digit.swift similarity index 100% rename from Sources/NBKTwosComplementKit/IntXL+Multiplication+Digit.swift rename to Sources/NBKTwosComplementKit/NBKFlexibleWidth+Multiplication+Digit.swift diff --git a/Sources/NBKTwosComplementKit/IntXL+Multiplication.swift b/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Multiplication.swift similarity index 100% rename from Sources/NBKTwosComplementKit/IntXL+Multiplication.swift rename to Sources/NBKTwosComplementKit/NBKFlexibleWidth+Multiplication.swift diff --git a/Sources/NBKTwosComplementKit/IntXL+Numbers.swift b/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Numbers.swift similarity index 95% rename from Sources/NBKTwosComplementKit/IntXL+Numbers.swift rename to Sources/NBKTwosComplementKit/NBKFlexibleWidth+Numbers.swift index c7631aca..78df84a1 100644 --- a/Sources/NBKTwosComplementKit/IntXL+Numbers.swift +++ b/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Numbers.swift @@ -22,6 +22,13 @@ extension PrivateIntXLOrUIntXL { @inlinable public init(digit: Digit) { self.init(unchecked: Storage(unchecked: [UInt(bitPattern: digit)])) } + + @inlinable public init(digit: Digit, at index: Int) { + var storage = Storage(unchecked: Elements(repeating: 0 as UInt, count: index + 1)) + storage.elements[index] = UInt(bitPattern: digit) + storage.normalize() + self.init(unchecked: storage) + } } //*============================================================================* diff --git a/Sources/NBKTwosComplementKit/IntXL+Shifts.swift b/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Shifts.swift similarity index 78% rename from Sources/NBKTwosComplementKit/IntXL+Shifts.swift rename to Sources/NBKTwosComplementKit/NBKFlexibleWidth+Shifts.swift index ef57d110..e0f3dbca 100644 --- a/Sources/NBKTwosComplementKit/IntXL+Shifts.swift +++ b/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Shifts.swift @@ -242,6 +242,53 @@ extension PrivateIntXLOrUIntXL { //=----------------------------------------------------------------------------= extension PrivateIntXLOrUIntXLStorage { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + /// Performs a left shift. + /// + /// - Parameters: + /// - distance: `0 <= distance < self.bitWidth` + /// + @inlinable mutating func bitshiftLeft(by distance: Int) { + precondition(distance >= 0, NBK.callsiteOutOfBoundsInfo()) + let major = NBK .quotientDividingByBitWidthAssumingIsAtLeastZero(distance) + let minor = NBK.remainderDividingByBitWidthAssumingIsAtLeastZero(distance) + return self.bitshiftLeft(words: major, bits: minor) + } + + /// Performs a left shift. + /// + /// - Parameters: + /// - words: `0 <= words < self.endIndex` + /// - bits: `0 <= bits  < UInt.bitWidth` + /// + @inlinable mutating func bitshiftLeft(words: Int, bits: Int) { + //=--------------------------------------= + if bits.isZero { + return self.bitshiftLeft(words: words) + } + //=--------------------------------------= + self.bitshiftLeft(words: words, atLeastOneBit: bits) + } + + /// Performs a left shift. + /// + /// - Parameters: + /// - words: `0 <= words < self.endIndex` + /// + @inlinable mutating func bitshiftLeft(words: Int) { + //=--------------------------------------= + if words.isZero { return } + //=--------------------------------------= + self.bitshiftLeft(atLeastOneWord: words) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= /// Performs a left shift. /// @@ -273,6 +320,49 @@ extension PrivateIntXLOrUIntXLStorage { extension PrivateIntXLOrUIntXLStorage { + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + /// Performs an un/signed right shift. + /// + /// - Parameters: + /// - distance: `0 <= distance < self.bitWidth` + /// + @inlinable mutating func bitshiftRight(by distance: Int) { + precondition(distance >= 0, NBK.callsiteOutOfBoundsInfo()) + let major = NBK .quotientDividingByBitWidthAssumingIsAtLeastZero(distance) + let minor = NBK.remainderDividingByBitWidthAssumingIsAtLeastZero(distance) + return self.bitshiftRight(words: major, bits: minor) + } + + /// Performs an un/signed right shift. + /// + /// - Parameters: + /// - words: `0 <= words < self.endIndex` + /// - bits: `0 <= bits  < UInt.bitWidth` + /// + @inlinable mutating func bitshiftRight(words: Int, bits: Int) { + //=--------------------------------------= + if bits.isZero { + return self.bitshiftRight(words: words) + } + //=--------------------------------------= + self.bitshiftRight(words: words, atLeastOneBit: bits) + } + + /// Performs an un/signed right shift. + /// + /// - Parameters: + /// - words: `0 <= words < self.endIndex` + /// + @inlinable mutating func bitshiftRight(words: Int) { + //=--------------------------------------= + if words.isZero { return } + //=--------------------------------------= + self.bitshiftRight(atLeastOneWord: words) + } + //=------------------------------------------------------------------------= // MARK: Transformations //=------------------------------------------------------------------------= diff --git a/Sources/NBKTwosComplementKit/IntXL+Storage+Normalization.swift b/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Storage+Normalization.swift similarity index 100% rename from Sources/NBKTwosComplementKit/IntXL+Storage+Normalization.swift rename to Sources/NBKTwosComplementKit/NBKFlexibleWidth+Storage+Normalization.swift diff --git a/Sources/NBKTwosComplementKit/IntXL+Storage+Size.swift b/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Storage+Size.swift similarity index 100% rename from Sources/NBKTwosComplementKit/IntXL+Storage+Size.swift rename to Sources/NBKTwosComplementKit/NBKFlexibleWidth+Storage+Size.swift diff --git a/Sources/NBKTwosComplementKit/IntXL+Storage.swift b/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Storage.swift similarity index 100% rename from Sources/NBKTwosComplementKit/IntXL+Storage.swift rename to Sources/NBKTwosComplementKit/NBKFlexibleWidth+Storage.swift diff --git a/Sources/NBKTwosComplementKit/IntXL+Subtraction+Digit.swift b/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Subtraction+Digit.swift similarity index 100% rename from Sources/NBKTwosComplementKit/IntXL+Subtraction+Digit.swift rename to Sources/NBKTwosComplementKit/NBKFlexibleWidth+Subtraction+Digit.swift diff --git a/Sources/NBKTwosComplementKit/IntXL+Subtraction.swift b/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Subtraction.swift similarity index 100% rename from Sources/NBKTwosComplementKit/IntXL+Subtraction.swift rename to Sources/NBKTwosComplementKit/NBKFlexibleWidth+Subtraction.swift diff --git a/Sources/NBKTwosComplementKit/IntXL+Text.swift b/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Text.swift similarity index 100% rename from Sources/NBKTwosComplementKit/IntXL+Text.swift rename to Sources/NBKTwosComplementKit/NBKFlexibleWidth+Text.swift diff --git a/Sources/NBKTwosComplementKit/IntXL+Update.swift b/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Update.swift similarity index 100% rename from Sources/NBKTwosComplementKit/IntXL+Update.swift rename to Sources/NBKTwosComplementKit/NBKFlexibleWidth+Update.swift diff --git a/Sources/NBKTwosComplementKit/IntXL+Words+Pointers.swift b/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Words+Pointers.swift similarity index 100% rename from Sources/NBKTwosComplementKit/IntXL+Words+Pointers.swift rename to Sources/NBKTwosComplementKit/NBKFlexibleWidth+Words+Pointers.swift diff --git a/Sources/NBKTwosComplementKit/IntXL+Words.swift b/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Words.swift similarity index 100% rename from Sources/NBKTwosComplementKit/IntXL+Words.swift rename to Sources/NBKTwosComplementKit/NBKFlexibleWidth+Words.swift diff --git a/Sources/NBKTwosComplementKit/IntXL.swift b/Sources/NBKTwosComplementKit/NBKFlexibleWidth.swift similarity index 100% rename from Sources/NBKTwosComplementKit/IntXL.swift rename to Sources/NBKTwosComplementKit/NBKFlexibleWidth.swift diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Text.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Text.swift index 54151935..0c914b2e 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Text.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Text.swift @@ -491,10 +491,10 @@ _ integer: T?, _ radix: Int, _ text: String, file: StaticString = #file, line: UInt = #line) { //=------------------------------------------= if radix == 10 { - XCTAssertEqual(T(text), integer, file: file, line: line) + XCTAssertEqual(T.init(text), integer, file: file, line: line) } //=------------------------------------------= - XCTAssertEqual(T(text, radix: radix), integer, file: file, line: line) + XCTAssertEqual(T.init(text, radix: radix), integer, file: file, line: line) } private func NBKAssertEncodeText( @@ -502,12 +502,11 @@ _ integer: T, _ radix: Int, _ uppercase: Bool, _ text: String, file: StaticString = #file, line: UInt = #line) { //=------------------------------------------= if radix == 10, uppercase == false { - XCTAssertEqual(String(integer), text, file: file, line: line) - XCTAssertEqual(integer.description, text, file: file, line: line) - XCTAssertEqual(integer.description(), text, file: file, line: line) + XCTAssertEqual(String.init(integer), text, file: file, line: line) + XCTAssertEqual(integer.description, text, file: file, line: line) } //=------------------------------------------= - XCTAssertEqual(String(integer, radix: radix, uppercase: uppercase), text, file: file, line: line) + XCTAssertEqual(String.init(integer,radix: radix, uppercase: uppercase), text, file: file, line: line) XCTAssertEqual(integer.description(radix: radix, uppercase: uppercase), text, file: file, line: line) } diff --git a/Tests/NBKTwosComplementKitBenchmarks/Blank.swift b/Tests/NBKTwosComplementKitBenchmarks/Blank.swift deleted file mode 100644 index 8b137891..00000000 --- a/Tests/NBKTwosComplementKitBenchmarks/Blank.swift +++ /dev/null @@ -1 +0,0 @@ - diff --git a/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Addition.swift b/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Addition.swift new file mode 100644 index 00000000..2c6bef74 --- /dev/null +++ b/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Addition.swift @@ -0,0 +1,142 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if !DEBUG + +import NBKCoreKit +import NBKTwosComplementKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Flexible Width x Addition x IntXL +//*============================================================================* + +final class NBKFlexibleWidthBenchmarksOnAdditionAsIntXL: XCTestCase { + + typealias T = IntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testAdd() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs += rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testAdding() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs + rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Digit + //=------------------------------------------------------------------------= + + func testAddDigit() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(Int.max) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs += rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testAddingDigit() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(Int.max) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs + rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Addition x UIntXL +//*============================================================================* + +final class NBKFlexibleWidthBenchmarksOnAdditionAsUIntXL: XCTestCase { + + typealias T = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testAdd() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs += rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testAdding() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs + rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Digit + //=------------------------------------------------------------------------= + + func testAddDigit() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(UInt.max) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs += rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testAddingDigit() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(UInt.max) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs + rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } +} + +#endif diff --git a/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Bits.swift b/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Bits.swift new file mode 100644 index 00000000..c14ca2c0 --- /dev/null +++ b/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Bits.swift @@ -0,0 +1,228 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if !DEBUG + +import NBKCoreKit +import NBKTwosComplementKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Flexible Width x Bits x IntXL +//*============================================================================* + +final class NBKFlexibleWidthBenchmarksOnBitsAsIntXL: XCTestCase { + + typealias T = IntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testInitBit() { + var abc = NBK.blackHoleIdentity(true ) + var xyz = NBK.blackHoleIdentity(false) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(T(bit: abc)) + NBK.blackHole(T(bit: xyz)) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testBitWidth() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.bitWidth) + NBK.blackHole(xyz.bitWidth) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testNonzeroBitCount() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.nonzeroBitCount) + NBK.blackHole(xyz.nonzeroBitCount) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testLeadingZeroBitCount() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.leadingZeroBitCount) + NBK.blackHole(xyz.leadingZeroBitCount) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testTrailingZeroBitCount() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.trailingZeroBitCount) + NBK.blackHole(xyz.trailingZeroBitCount) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testMostSignificantBit() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.mostSignificantBit) + NBK.blackHole(xyz.mostSignificantBit) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testLeastSignificantBit() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.leastSignificantBit) + NBK.blackHole(xyz.leastSignificantBit) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Bits x UIntXL +//*============================================================================* + +final class NBKFlexibleWidthBenchmarksOnBitsAsUIntXL: XCTestCase { + + typealias T = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testInitBit() { + var abc = NBK.blackHoleIdentity(true ) + var xyz = NBK.blackHoleIdentity(false) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(T(bit: abc)) + NBK.blackHole(T(bit: xyz)) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testBitWidth() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.bitWidth) + NBK.blackHole(xyz.bitWidth) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testNonzeroBitCount() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.nonzeroBitCount) + NBK.blackHole(xyz.nonzeroBitCount) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testLeadingZeroBitCount() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.leadingZeroBitCount) + NBK.blackHole(xyz.leadingZeroBitCount) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testTrailingZeroBitCount() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.trailingZeroBitCount) + NBK.blackHole(xyz.trailingZeroBitCount) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testMostSignificantBit() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.mostSignificantBit) + NBK.blackHole(xyz.mostSignificantBit) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testLeastSignificantBit() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.leastSignificantBit) + NBK.blackHole(xyz.leastSignificantBit) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } +} + +#endif diff --git a/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Comparisons.swift b/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Comparisons.swift new file mode 100644 index 00000000..5a2ebee2 --- /dev/null +++ b/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Comparisons.swift @@ -0,0 +1,280 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if !DEBUG + +import NBKCoreKit +import NBKTwosComplementKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Flexible Width x Comparisons x IntXL +//*============================================================================* + +final class NBKFlexibleWidthBenchmarksOnComparisonsAsIntXL: XCTestCase { + + typealias T = IntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testIsZero() { + var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.isZero) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testIsLessThanZero() { + var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.isLessThanZero) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testIsMoreThanZero() { + var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.isMoreThanZero) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testIsPowerOf2() { + var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.isPowerOf2) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testSignum() { + var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.signum()) + NBK.blackHoleInoutIdentity(&abc) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testIsEqualTo() { + var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs == rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testIsLessThan() { + var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs < rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testComparedTo() { + var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs.compared(to: rhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testComparedToAtIndex() { + var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[1, 2, 3, 0] as X)) + let xyz = NBK.blackHoleIdentity(1 as Int) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs.compared(to: rhs, at: xyz)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testComparedToDigit() { + var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + var rhs = NBK.blackHoleIdentity(Int.max) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs.compared(to: rhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testComparedToDigitAtIndex() { + var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + var rhs = NBK.blackHoleIdentity(3 as Int) + let xyz = NBK.blackHoleIdentity(3 as Int) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs.compared(to: rhs, at: xyz)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Comparisons x UIntXL +//*============================================================================* + +final class NBKFlexibleWidthBenchmarksOnComparisonsAsUIntXL: XCTestCase { + + typealias T = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testIsZero() { + var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.isZero) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testIsLessThanZero() { + var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.isLessThanZero) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testIsMoreThanZero() { + var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.isMoreThanZero) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testIsPowerOf2() { + var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.isPowerOf2) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testSignum() { + var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.signum()) + NBK.blackHoleInoutIdentity(&abc) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testIsEqualTo() { + var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs == rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testIsLessThan() { + var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs < rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testComparedTo() { + var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs.compared(to: rhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testComparedToAtIndex() { + var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[1, 2, 3, 0] as X)) + let xyz = NBK.blackHoleIdentity(1 as Int) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs.compared(to: rhs, at: xyz)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testComparedToDigit() { + var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + var rhs = NBK.blackHoleIdentity(UInt.max) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs.compared(to: rhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testComparedToDigitAtIndex() { + var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + var rhs = NBK.blackHoleIdentity(UInt( 3)) + let xyz = NBK.blackHoleIdentity(3 as Int) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs.compared(to: rhs, at: xyz)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } +} + +#endif diff --git a/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Complements.swift b/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Complements.swift new file mode 100644 index 00000000..50ff85d5 --- /dev/null +++ b/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Complements.swift @@ -0,0 +1,299 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if !DEBUG + +import NBKCoreKit +import NBKTwosComplementKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Flexible Width x Complements x IntXL +//*============================================================================* + +final class NBKFlexibleWidthBenchmarksOnComplementsAsIntXL: XCTestCase { + + typealias T = IntXL + typealias M = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests x Magnitude + //=------------------------------------------------------------------------= + + func testMagnitude() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.magnitude) + NBK.blackHole(xyz.magnitude) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x One's Complement + //=------------------------------------------------------------------------= + + func testOnesComplement() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 250_000 { + NBK.blackHole(abc.onesComplement()) + NBK.blackHole(xyz.onesComplement()) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testOnesComplementInout() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.formOnesComplement()) + NBK.blackHole(xyz.formOnesComplement()) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Two's Complement + //=------------------------------------------------------------------------= + + func testTwosComplement() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.twosComplement()) + NBK.blackHole(xyz.twosComplement()) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testTwosComplementInout() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.formTwosComplement()) + NBK.blackHole(xyz.formTwosComplement()) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testTwosComplementReportingOverflow() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.twosComplementReportingOverflow()) + NBK.blackHole(xyz.twosComplementReportingOverflow()) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testTwosComplementReportingOverflowInout() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.formTwosComplementReportingOverflow()) + NBK.blackHole(xyz.formTwosComplementReportingOverflow()) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testTwosComplementSubsequence() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.twosComplementSubsequence(true)) + NBK.blackHole(xyz.twosComplementSubsequence(true)) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testTwosComplementSubsequenceInout() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.formTwosComplementSubsequence(true)) + NBK.blackHole(xyz.formTwosComplementSubsequence(true)) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Complements x UIntXL +//*============================================================================* + +final class NBKFlexibleWidthBenchmarksOnComplementsAsUIntXL: XCTestCase { + + typealias T = UIntXL + typealias M = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests x Magnitude + //=------------------------------------------------------------------------= + + func testMagnitude() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.magnitude) + NBK.blackHole(xyz.magnitude) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x One's Complement + //=------------------------------------------------------------------------= + + func testOnesComplement() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 250_000 { + NBK.blackHole(abc.onesComplement()) + NBK.blackHole(xyz.onesComplement()) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testOnesComplementInout() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.formOnesComplement()) + NBK.blackHole(xyz.formOnesComplement()) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Two's Complement + //=------------------------------------------------------------------------= + + func testTwosComplement() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 250_000 { + NBK.blackHole(abc.twosComplement()) + NBK.blackHole(xyz.twosComplement()) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testTwosComplementInout() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.formTwosComplement()) + NBK.blackHole(xyz.formTwosComplement()) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testTwosComplementReportingOverflow() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 250_000 { + NBK.blackHole(abc.twosComplementReportingOverflow()) + NBK.blackHole(xyz.twosComplementReportingOverflow()) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + + func testTwosComplementReportingOverflowInout() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.formTwosComplementReportingOverflow()) + NBK.blackHole(xyz.formTwosComplementReportingOverflow()) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testTwosComplementSubsequence() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 250_000 { + NBK.blackHole(abc.twosComplementSubsequence(true)) + NBK.blackHole(xyz.twosComplementSubsequence(true)) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testTwosComplementSubsequenceInout() { + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.formTwosComplementSubsequence(true)) + NBK.blackHole(xyz.formTwosComplementSubsequence(true)) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } +} + +#endif diff --git a/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Division.swift b/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Division.swift new file mode 100644 index 00000000..c2ac9176 --- /dev/null +++ b/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Division.swift @@ -0,0 +1,240 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if !DEBUG + +import NBKCoreKit +import NBKTwosComplementKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Flexible Width x Division x IntXL +//*============================================================================* + +final class NBKFlexibleWidthBenchmarksOnDivisionAsIntXL: XCTestCase { + + typealias T = IntXL + typealias M = IntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testQuotientAndRemainder() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + + for _ in 0 ..< 250_000 { + NBK.blackHole(lhs.quotientAndRemainder(dividingBy: rhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testQuotientReportingOverflow() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + + for _ in 0 ..< 250_000 { + NBK.blackHole(lhs.dividedReportingOverflow(by: rhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testRemainderReportingOverflow() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + + for _ in 0 ..< 250_000 { + NBK.blackHole(lhs.remainderReportingOverflow(dividingBy: rhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Digit + //=------------------------------------------------------------------------= + + func testQuotientAndRemainderDividingByDigit() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(Int.max) + + for _ in 0 ..< 250_000 { + NBK.blackHole(lhs.quotientAndRemainder(dividingBy: rhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testQuotientDividingByDigitReportingOverflow() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(Int.max) + + for _ in 0 ..< 250_000 { + NBK.blackHole(lhs.dividedReportingOverflow(by: rhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testRemainderDividingByDigitReportingOverflow() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(Int.max) + + for _ in 0 ..< 250_000 { + NBK.blackHole(lhs.remainderReportingOverflow(dividingBy: rhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Full Width + //=------------------------------------------------------------------------= + + func testDividingFullWidthAs256() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0/2] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0/2, ~0, ~0, ~0, ~0/4] as X)) + + for _ in 0 ..< 250_000 { + NBK.blackHole(rhs.quotientAndRemainder(dividingBy: lhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testDividingFullWidthReportingOverflowAs256() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0/2] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0/2, ~0, ~0, ~0, ~0/4] as X)) + + for _ in 0 ..< 250_000 { + NBK.blackHole(rhs.quotientAndRemainderReportingOverflow(dividingBy: lhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Division x UIntXL +//*============================================================================* + +final class NBKFlexibleWidthBenchmarksOnDivisionAsUIntXL: XCTestCase { + + typealias T = UIntXL + typealias M = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testQuotientAndRemainder() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + + for _ in 0 ..< 250_000 { + NBK.blackHole(lhs.quotientAndRemainder(dividingBy: rhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testQuotientReportingOverflow() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + + for _ in 0 ..< 250_000 { + NBK.blackHole(lhs.dividedReportingOverflow(by: rhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testRemainderReportingOverflow() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + + for _ in 0 ..< 250_000 { + NBK.blackHole(lhs.remainderReportingOverflow(dividingBy: rhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Digit + //=------------------------------------------------------------------------= + + func testQuotientAndRemainderDividingByDigit() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(UInt.max) + + for _ in 0 ..< 250_000 { + NBK.blackHole(lhs.quotientAndRemainder(dividingBy: rhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testQuotientDividingByDigitReportingOverflow() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(UInt.max) + + for _ in 0 ..< 250_000 { + NBK.blackHole(lhs.dividedReportingOverflow(by: rhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testRemainderDividingByDigitReportingOverflow() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(UInt.max) + + for _ in 0 ..< 250_000 { + NBK.blackHole(lhs.remainderReportingOverflow(dividingBy: rhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Full Width + //=------------------------------------------------------------------------= + + func testDividingFullWidthAs256() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0, ~1, ~0, ~0, ~0] as X)) + + for _ in 0 ..< 250_000 { + NBK.blackHole(rhs.quotientAndRemainder(dividingBy: lhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testDividingFullWidthReportingOverflowAs256() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0, ~1, ~0, ~0, ~0] as X)) + + for _ in 0 ..< 250_000 { + NBK.blackHole(rhs.quotientAndRemainderReportingOverflow(dividingBy: lhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } +} + +#endif diff --git a/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Logic.swift b/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Logic.swift new file mode 100644 index 00000000..d8148416 --- /dev/null +++ b/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Logic.swift @@ -0,0 +1,117 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if !DEBUG + +import NBKCoreKit +import NBKTwosComplementKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Flexible Width x Logic x UIntXL +//*============================================================================* + +final class NBKFlexibleWidthBenchmarksOnLogicAsUIntXL: XCTestCase { + + typealias T = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testNotInout() { + var abc = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.formOnesComplement()) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testNot() { + var abc = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(~abc) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testAndInout() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs &= rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testAnd() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs & rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testOrInout() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs |= rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testOr() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs | rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testXorInout() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs ^= rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testXor() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs ^ rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } +} + +#endif diff --git a/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Multiplication.swift b/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Multiplication.swift new file mode 100644 index 00000000..b714330b --- /dev/null +++ b/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Multiplication.swift @@ -0,0 +1,98 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if !DEBUG + +import NBKCoreKit +import NBKTwosComplementKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Flexible Width x Multiplication x IntXL +//*============================================================================* + +final class NBKFlexibleWidthBenchmarksOnMultiplicationAsIntXL: XCTestCase { + + typealias T = IntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testMultiplied() { + var lhs = NBK.blackHoleIdentity(T(x64:[~1, ~2, ~3, ~4] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 1, 2, 3, 4] as X)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs * rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Digit + //=------------------------------------------------------------------------= + + func testMultipliedByDigit() { + var lhs = NBK.blackHoleIdentity(T(x64:[~1, ~2, ~3, ~4] as X)) + var rhs = NBK.blackHoleIdentity(Int.max) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs * rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Multiplication x UIntXL +//*============================================================================* + +final class NBKFlexibleWidthBenchmarksOnMultiplicationAsUIntXL: XCTestCase { + + typealias T = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testMultiplied() { + var lhs = NBK.blackHoleIdentity(T(x64:[~1, ~2, ~3, ~4] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 1, 2, 3, 4] as X)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs * rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Digit + //=------------------------------------------------------------------------= + + func testMultipliedByDigit() { + var lhs = NBK.blackHoleIdentity(T(x64:[~1, ~2, ~3, ~4] as X)) + var rhs = NBK.blackHoleIdentity(UInt.max) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs * rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } +} + +#endif diff --git a/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Numbers.swift b/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Numbers.swift new file mode 100644 index 00000000..afbbc6a4 --- /dev/null +++ b/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Numbers.swift @@ -0,0 +1,816 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if !DEBUG + +import NBKCoreKit +import NBKTwosComplementKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Flexible Width x Numbers x IntXL +//*============================================================================* + +final class NBKFlexibleWidthBenchmarksOnNumbersAsIntXL: XCTestCase { + + typealias T = IntXL + typealias M = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testZero() { + for _ in 0 ..< 100_000 { + NBK.blackHole(T()) + NBK.blackHole(T.zero) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Integers + //=------------------------------------------------------------------------= + + func testToInt() { + var abc = NBK.blackHoleIdentity(T(Int.max)) + + for _ in 0 ..< 50_000 { + NBK.blackHole(Int(abc)) + NBK.blackHole(Int(exactly: abc)) + NBK.blackHole(Int(clamping: abc)) + NBK.blackHole(Int(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromInt() { + var abc = NBK.blackHoleIdentity(Int.max) + + for _ in 0 ..< 100_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHole(T(clamping: abc)) + NBK.blackHole(T(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testToUInt() { + var abc = NBK.blackHoleIdentity(T(UInt.max)) + + for _ in 0 ..< 50_000 { + NBK.blackHole(UInt(abc)) + NBK.blackHole(UInt(exactly: abc)) + NBK.blackHole(UInt(clamping: abc)) + NBK.blackHole(UInt(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromUInt() { + var abc = NBK.blackHoleIdentity(UInt.max) + + for _ in 0 ..< 100_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHole(T(clamping: abc)) + NBK.blackHole(T(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testToInt8() { + var abc = NBK.blackHoleIdentity(T(Int8.max)) + + for _ in 0 ..< 50_000 { + NBK.blackHole(Int8(abc)) + NBK.blackHole(Int8(exactly: abc)) + NBK.blackHole(Int8(clamping: abc)) + NBK.blackHole(Int8(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromInt8() { + var abc = NBK.blackHoleIdentity(Int8.max) + + for _ in 0 ..< 100_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHole(T(clamping: abc)) + NBK.blackHole(T(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testToUInt8() { + var abc = NBK.blackHoleIdentity(T(UInt8.max)) + + for _ in 0 ..< 50_000 { + NBK.blackHole(UInt8(abc)) + NBK.blackHole(UInt8(exactly: abc)) + NBK.blackHole(UInt8(clamping: abc)) + NBK.blackHole(UInt8(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromUInt8() { + var abc = NBK.blackHoleIdentity(UInt8.max) + + for _ in 0 ..< 100_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHole(T(clamping: abc)) + NBK.blackHole(T(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testToInt16() { + var abc = NBK.blackHoleIdentity(T(Int16.max)) + + for _ in 0 ..< 50_000 { + NBK.blackHole(Int16(abc)) + NBK.blackHole(Int16(exactly: abc)) + NBK.blackHole(Int16(clamping: abc)) + NBK.blackHole(Int16(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromInt16() { + var abc = NBK.blackHoleIdentity(Int16.max) + + for _ in 0 ..< 100_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHole(T(clamping: abc)) + NBK.blackHole(T(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testToUInt16() { + var abc = NBK.blackHoleIdentity(T(UInt16.max)) + + for _ in 0 ..< 50_000 { + NBK.blackHole(UInt16(abc)) + NBK.blackHole(UInt16(exactly: abc)) + NBK.blackHole(UInt16(clamping: abc)) + NBK.blackHole(UInt16(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromUInt16() { + var abc = NBK.blackHoleIdentity(UInt16.max) + + for _ in 0 ..< 100_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHole(T(clamping: abc)) + NBK.blackHole(T(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testToInt32() { + var abc = NBK.blackHoleIdentity(T(Int32.max)) + + for _ in 0 ..< 50_000 { + NBK.blackHole(Int32(abc)) + NBK.blackHole(Int32(exactly: abc)) + NBK.blackHole(Int32(clamping: abc)) + NBK.blackHole(Int32(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromInt32() { + var abc = NBK.blackHoleIdentity(Int32.max) + + for _ in 0 ..< 100_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHole(T(clamping: abc)) + NBK.blackHole(T(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testToUInt32() { + var abc = NBK.blackHoleIdentity(T(UInt32.max)) + + for _ in 0 ..< 50_000 { + NBK.blackHole(UInt32(abc)) + NBK.blackHole(UInt32(exactly: abc)) + NBK.blackHole(UInt32(clamping: abc)) + NBK.blackHole(UInt32(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromUInt32() { + var abc = NBK.blackHoleIdentity(UInt32.max) + + for _ in 0 ..< 100_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHole(T(clamping: abc)) + NBK.blackHole(T(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testToInt64() { + var abc = NBK.blackHoleIdentity(T(Int64.max)) + + for _ in 0 ..< 50_000 { + NBK.blackHole(Int64(abc)) + NBK.blackHole(Int64(exactly: abc)) + NBK.blackHole(Int64(clamping: abc)) + NBK.blackHole(Int64(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromInt64() { + var abc = NBK.blackHoleIdentity(Int64.max) + + for _ in 0 ..< 100_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHole(T(clamping: abc)) + NBK.blackHole(T(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testToUInt64() { + var abc = NBK.blackHoleIdentity(T(UInt64.max)) + + for _ in 0 ..< 50_000 { + NBK.blackHole(UInt64(abc)) + NBK.blackHole(UInt64(exactly: abc)) + NBK.blackHole(UInt64(clamping: abc)) + NBK.blackHole(UInt64(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromUInt64() { + var abc = NBK.blackHoleIdentity(UInt64.max) + + for _ in 0 ..< 100_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHole(T(clamping: abc)) + NBK.blackHole(T(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Complements + //=------------------------------------------------------------------------= + + func testToDigit() { + var abc = NBK.blackHoleIdentity(T(T.Digit.max)) + + for _ in 0 ..< 50_000 { + NBK.blackHole(T.Digit(abc)) + NBK.blackHole(T.Digit(exactly: abc)) + NBK.blackHole(T.Digit(clamping: abc)) + NBK.blackHole(T.Digit(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromDigit() { + var abc = NBK.blackHoleIdentity(T.Digit.max) + + for _ in 0 ..< 100_000 { + NBK.blackHole(T(digit: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testToMagnitude() { + var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + + for _ in 0 ..< 50_000 { + NBK.blackHole(M(abc)) + NBK.blackHole(M(exactly: abc)) + NBK.blackHole(M(clamping: abc)) + NBK.blackHole(M(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromMagnitude() { + var abc = NBK.blackHoleIdentity(M(x64:[0, 1, 2, 3] as X)) + + for _ in 0 ..< 100_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHole(T(clamping: abc)) + NBK.blackHole(T(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Float + //=------------------------------------------------------------------------= + + // TODO: brrr + func testToFloat16() { + var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + + for _ in 0 ..< 1_000 { + NBK.blackHole(Float16(abc)) + NBK.blackHole(Float16(exactly: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromFloat16() { + var abc = NBK.blackHoleIdentity(Float16(123)) + + for _ in 0 ..< 100_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + // TODO: brrr + func testToFloat32() { + var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + + for _ in 0 ..< 1_000 { + NBK.blackHole(Float32(abc)) + NBK.blackHole(Float32(exactly: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromFloat32() { + var abc = NBK.blackHoleIdentity(Float32(123)) + + for _ in 0 ..< 100_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + // TODO: brrr + func testToFloat64() { + var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + + for _ in 0 ..< 1_000 { + NBK.blackHole(Float64(abc)) + NBK.blackHole(Float64(exactly: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromFloat64() { + var abc = NBK.blackHoleIdentity(Float64(123)) + + for _ in 0 ..< 100_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Sign & Magnitude + //=------------------------------------------------------------------------= + + func testSignAndMagnitude() { + var abc = NBK.blackHoleIdentity((sign: FloatingPointSign.plus, magnitude: M(x64:[0, 1, 2, 3] as X))) + var xyz = NBK.blackHoleIdentity((sign: FloatingPointSign.minus, magnitude: M(x64:[0, 1, 2, 3] as X))) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(T(sign: abc.sign, magnitude: abc.magnitude)) + NBK.blackHoleInoutIdentity(&abc) + + NBK.blackHole(T(sign: xyz.sign, magnitude: xyz.magnitude)) + NBK.blackHoleInoutIdentity(&xyz) + } + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Numbers x UIntXL +//*============================================================================* + +final class NBKFlexibleWidthBenchmarksOnNumbersAsUIntXL: XCTestCase { + + typealias T = UIntXL + typealias M = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testZero() { + for _ in 0 ..< 100_000 { + NBK.blackHole(T()) + NBK.blackHole(T.zero) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Integers + //=------------------------------------------------------------------------= + + func testToInt() { + var abc = NBK.blackHoleIdentity(T(Int.max)) + + for _ in 0 ..< 50_000 { + NBK.blackHole(Int(abc)) + NBK.blackHole(Int(exactly: abc)) + NBK.blackHole(Int(clamping: abc)) + NBK.blackHole(Int(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromInt() { + var abc = NBK.blackHoleIdentity(Int.max) + + for _ in 0 ..< 100_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHole(T(clamping: abc)) + NBK.blackHole(T(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testToUInt() { + var abc = NBK.blackHoleIdentity(T(UInt.max)) + + for _ in 0 ..< 50_000 { + NBK.blackHole(UInt(abc)) + NBK.blackHole(UInt(exactly: abc)) + NBK.blackHole(UInt(clamping: abc)) + NBK.blackHole(UInt(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromUInt() { + var abc = NBK.blackHoleIdentity(UInt.max) + + for _ in 0 ..< 100_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHole(T(clamping: abc)) + NBK.blackHole(T(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testToInt8() { + var abc = NBK.blackHoleIdentity(T(Int8.max)) + + for _ in 0 ..< 50_000 { + NBK.blackHole(Int8(abc)) + NBK.blackHole(Int8(exactly: abc)) + NBK.blackHole(Int8(clamping: abc)) + NBK.blackHole(Int8(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromInt8() { + var abc = NBK.blackHoleIdentity(Int8.max) + + for _ in 0 ..< 100_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHole(T(clamping: abc)) + NBK.blackHole(T(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testToUInt8() { + var abc = NBK.blackHoleIdentity(T(UInt8.max)) + + for _ in 0 ..< 50_000 { + NBK.blackHole(UInt8(abc)) + NBK.blackHole(UInt8(exactly: abc)) + NBK.blackHole(UInt8(clamping: abc)) + NBK.blackHole(UInt8(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromUInt8() { + var abc = NBK.blackHoleIdentity(UInt8.max) + + for _ in 0 ..< 100_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHole(T(clamping: abc)) + NBK.blackHole(T(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testToInt16() { + var abc = NBK.blackHoleIdentity(T(Int16.max)) + + for _ in 0 ..< 50_000 { + NBK.blackHole(Int16(abc)) + NBK.blackHole(Int16(exactly: abc)) + NBK.blackHole(Int16(clamping: abc)) + NBK.blackHole(Int16(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromInt16() { + var abc = NBK.blackHoleIdentity(Int16.max) + + for _ in 0 ..< 100_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHole(T(clamping: abc)) + NBK.blackHole(T(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testToUInt16() { + var abc = NBK.blackHoleIdentity(T(UInt16.max)) + + for _ in 0 ..< 50_000 { + NBK.blackHole(UInt16(abc)) + NBK.blackHole(UInt16(exactly: abc)) + NBK.blackHole(UInt16(clamping: abc)) + NBK.blackHole(UInt16(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromUInt16() { + var abc = NBK.blackHoleIdentity(UInt16.max) + + for _ in 0 ..< 100_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHole(T(clamping: abc)) + NBK.blackHole(T(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testToInt32() { + var abc = NBK.blackHoleIdentity(T(Int32.max)) + + for _ in 0 ..< 50_000 { + NBK.blackHole(Int32(abc)) + NBK.blackHole(Int32(exactly: abc)) + NBK.blackHole(Int32(clamping: abc)) + NBK.blackHole(Int32(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromInt32() { + var abc = NBK.blackHoleIdentity(Int32.max) + + for _ in 0 ..< 100_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHole(T(clamping: abc)) + NBK.blackHole(T(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testToUInt32() { + var abc = NBK.blackHoleIdentity(T(UInt32.max)) + + for _ in 0 ..< 50_000 { + NBK.blackHole(UInt32(abc)) + NBK.blackHole(UInt32(exactly: abc)) + NBK.blackHole(UInt32(clamping: abc)) + NBK.blackHole(UInt32(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromUInt32() { + var abc = NBK.blackHoleIdentity(UInt32.max) + + for _ in 0 ..< 100_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHole(T(clamping: abc)) + NBK.blackHole(T(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testToInt64() { + var abc = NBK.blackHoleIdentity(T(Int64.max)) + + for _ in 0 ..< 50_000 { + NBK.blackHole(Int64(abc)) + NBK.blackHole(Int64(exactly: abc)) + NBK.blackHole(Int64(clamping: abc)) + NBK.blackHole(Int64(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromInt64() { + var abc = NBK.blackHoleIdentity(Int64.max) + + for _ in 0 ..< 100_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHole(T(clamping: abc)) + NBK.blackHole(T(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testToUInt64() { + var abc = NBK.blackHoleIdentity(T(UInt64.max)) + + for _ in 0 ..< 50_000 { + NBK.blackHole(UInt64(abc)) + NBK.blackHole(UInt64(exactly: abc)) + NBK.blackHole(UInt64(clamping: abc)) + NBK.blackHole(UInt64(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromUInt64() { + var abc = NBK.blackHoleIdentity(UInt64.max) + + for _ in 0 ..< 100_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHole(T(clamping: abc)) + NBK.blackHole(T(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Complements + //=------------------------------------------------------------------------= + + func testToDigit() { + var abc = NBK.blackHoleIdentity(T(T.Digit.max)) + + for _ in 0 ..< 50_000 { + NBK.blackHole(T.Digit(abc)) + NBK.blackHole(T.Digit(exactly: abc)) + NBK.blackHole(T.Digit(clamping: abc)) + NBK.blackHole(T.Digit(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromDigit() { + var abc = NBK.blackHoleIdentity(T.Digit.max) + + for _ in 0 ..< 100_000 { + NBK.blackHole(T(digit: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testToMagnitude() { + var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + + for _ in 0 ..< 50_000 { + NBK.blackHole(M(abc)) + NBK.blackHole(M(exactly: abc)) + NBK.blackHole(M(clamping: abc)) + NBK.blackHole(M(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromMagnitude() { + var abc = NBK.blackHoleIdentity(M(x64:[0, 1, 2, 3] as X)) + + for _ in 0 ..< 100_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHole(T(clamping: abc)) + NBK.blackHole(T(truncatingIfNeeded: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Float + //=------------------------------------------------------------------------= + + // TODO: brrr + func testToFloat16() { + var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + + for _ in 0 ..< 1_000 { + NBK.blackHole(Float16(abc)) + NBK.blackHole(Float16(exactly: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromFloat16() { + var abc = NBK.blackHoleIdentity(Float16(123)) + + for _ in 0 ..< 100_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + // TODO: brrr + func testToFloat32() { + var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + + for _ in 0 ..< 1_000 { + NBK.blackHole(Float32(abc)) + NBK.blackHole(Float32(exactly: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromFloat32() { + var abc = NBK.blackHoleIdentity(Float32(123)) + + for _ in 0 ..< 100_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + // TODO: brrr + func testToFloat64() { + var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + + for _ in 0 ..< 1_000 { + NBK.blackHole(Float64(abc)) + NBK.blackHole(Float64(exactly: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testFromFloat64() { + var abc = NBK.blackHoleIdentity(Float64(123)) + + for _ in 0 ..< 100_000 { + NBK.blackHole(T(abc)) + NBK.blackHole(T(exactly: abc)) + NBK.blackHoleInoutIdentity(&abc) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Sign & Magnitude + //=------------------------------------------------------------------------= + + func testSignAndMagnitude() { + var abc = NBK.blackHoleIdentity((sign: FloatingPointSign.plus, magnitude: M(x64:[0, 1, 2, 3] as X))) + var xyz = NBK.blackHoleIdentity((sign: FloatingPointSign.minus, magnitude: M(x64:[0, 1, 2, 3] as X))) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(T(sign: abc.sign, magnitude: abc.magnitude)) + NBK.blackHoleInoutIdentity(&abc) + + NBK.blackHole(T(sign: xyz.sign, magnitude: xyz.magnitude)) + NBK.blackHoleInoutIdentity(&xyz) + } + } +} + +#endif diff --git a/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Shifts.swift b/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Shifts.swift new file mode 100644 index 00000000..819314c7 --- /dev/null +++ b/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Shifts.swift @@ -0,0 +1,284 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if !DEBUG + +import NBKCoreKit +import NBKTwosComplementKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Flexible Width x Shifts x IntXL +//*============================================================================* + +final class NBKFlexibleWidthBenchmarksOnShiftsAsIntXL: XCTestCase { + + typealias T = IntXL + + //=------------------------------------------------------------------------= + // MARK: Tests x Left + //=------------------------------------------------------------------------= + + func testBitshiftingLeft() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(UInt.bitWidth * 3/2) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs << rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testBitshiftingLeftByWords() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs.bitshiftedLeft(words: rhs.words)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testBitshiftingLeftByWordsAndBits() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs.bitshiftedLeft(words: rhs.words, bits: rhs.bits)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Right + //=------------------------------------------------------------------------= + + func testBitshiftingRight() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(UInt.bitWidth * 3/2) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs >> rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testBitshiftingRightByWords() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs.bitshiftedRight(words: rhs.words)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testBitshiftingRightByWordsAndBits() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs.bitshiftedRight(words: rhs.words, bits: rhs.bits)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x In Both Directions + //=------------------------------------------------------------------------= + + func testBitshiftingInBothDirectionsInout() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(UInt.bitWidth * 3/2) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs.bitshiftLeft (by: rhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + + NBK.blackHole(lhs.bitshiftRight(by: rhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testBitshiftingInBothDirectionsByWordsInout() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs.bitshiftLeft (words: rhs.words)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + + NBK.blackHole(lhs.bitshiftRight(words: rhs.words)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testBitshiftingInBothDirectionsByWordsAndBitsInout() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs.bitshiftLeft (words: rhs.words, bits: rhs.bits)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + + NBK.blackHole(lhs.bitshiftRight(words: rhs.words, bits: rhs.bits)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Shifts x UIntXL +//*============================================================================* + +final class NBKFlexibleWidthBenchmarksOnShiftsAsUIntXL: XCTestCase { + + typealias T = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests x Left + //=------------------------------------------------------------------------= + + func testBitshiftingLeft() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(UInt.bitWidth * 3/2) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs << rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testBitshiftingLeftByWords() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs.bitshiftedLeft(words: rhs.words)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testBitshiftingLeftByWordsAndBits() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs.bitshiftedLeft(words: rhs.words, bits: rhs.bits)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Right + //=------------------------------------------------------------------------= + + func testBitshiftingRight() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(UInt.bitWidth * 3/2) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs >> rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testBitshiftingRightByWords() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs.bitshiftedRight(words: rhs.words)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testBitshiftingRightByWordsAndBits() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs.bitshiftedRight(words: rhs.words, bits: rhs.bits)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x In Both Directions + //=------------------------------------------------------------------------= + + func testBitshiftingInBothDirectionsInout() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(UInt.bitWidth * 3/2) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs.bitshiftLeft (by: rhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + + NBK.blackHole(lhs.bitshiftRight(by: rhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testBitshiftingInBothDirectionsByWordsInout() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs.bitshiftLeft (words: rhs.words)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + + NBK.blackHole(lhs.bitshiftRight(words: rhs.words)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testBitshiftingInBothDirectionsByWordsAndBitsInout() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs.bitshiftLeft (words: rhs.words, bits: rhs.bits)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + + NBK.blackHole(lhs.bitshiftRight(words: rhs.words, bits: rhs.bits)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } +} + +#endif diff --git a/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Subtraction.swift b/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Subtraction.swift new file mode 100644 index 00000000..2a789654 --- /dev/null +++ b/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Subtraction.swift @@ -0,0 +1,142 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if !DEBUG + +import NBKCoreKit +import NBKTwosComplementKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Flexible Width x Subtraction x IntXL +//*============================================================================* + +final class NBKFlexibleWidthBenchmarksOnSubtractionAsIntXL: XCTestCase { + + typealias T = IntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testSubtract() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs -= rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testSubtracting() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs - rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Digit + //=------------------------------------------------------------------------= + + func testSubtractDigit() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(Int.max) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs -= rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testSubtractingDigit() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(Int.max) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs - rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Subtraction x UIntXL +//*============================================================================* + +final class NBKFlexibleWidthBenchmarksOnSubtractionAsUIntXL: XCTestCase { + + typealias T = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testSubtract() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs -= rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testSubtracting() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs - rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Digit + //=------------------------------------------------------------------------= + + func testSubtractDigit() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(UInt.max) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs -= rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testSubtractingDigit() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var rhs = NBK.blackHoleIdentity(UInt.max) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs - rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } +} + +#endif diff --git a/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Text.swift b/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Text.swift new file mode 100644 index 00000000..7d8b0a36 --- /dev/null +++ b/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Text.swift @@ -0,0 +1,200 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if !DEBUG + +import NBKCoreKit +import NBKTwosComplementKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Flexible Width x Text x IntXL +//*============================================================================* + +final class NBKFlexibleWidthBenchmarksOnTextAsIntXL: XCTestCase { + + typealias T = IntXL + + //=------------------------------------------------------------------------= + // MARK: State + //=------------------------------------------------------------------------= + + static let decoded = NBK.blackHoleIdentity(T(encoded, radix: 16)!) + static let encoded = NBK.blackHoleIdentity(String(repeating: "1", count: 64)) + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testDecodingRadix10() { + var radix = NBK.blackHoleIdentity(10) + var encoded = NBK.blackHoleIdentity(Self.encoded) + + for _ in 0 ..< 250_000 { + NBK.blackHole(T(encoded, radix: radix)!) + NBK.blackHoleInoutIdentity(&radix) + NBK.blackHoleInoutIdentity(&encoded) + } + } + + func testDecodingRadix16() { + var radix = NBK.blackHoleIdentity(16) + var encoded = NBK.blackHoleIdentity(Self.encoded) + + for _ in 0 ..< 250_000 { + NBK.blackHole(T(encoded, radix: radix)!) + NBK.blackHoleInoutIdentity(&radix) + NBK.blackHoleInoutIdentity(&encoded) + } + } + + func testEncodingRadix10() { + var radix = NBK.blackHoleIdentity(10) + var decoded = NBK.blackHoleIdentity(Self.decoded) + + for _ in 0 ..< 250_000 { + NBK.blackHole(String(decoded, radix: radix)) + NBK.blackHoleInoutIdentity(&radix) + NBK.blackHoleInoutIdentity(&decoded) + } + } + + func testEncodingRadix16() { + var radix = NBK.blackHoleIdentity(16) + var decoded = NBK.blackHoleIdentity(Self.decoded) + + for _ in 0 ..< 250_000 { + NBK.blackHole(String(decoded, radix: radix)) + NBK.blackHoleInoutIdentity(&radix) + NBK.blackHoleInoutIdentity(&decoded) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Swift Standard Library Methods + //=------------------------------------------------------------------------= + + func testEncodingUsingSwiftStdlibRadix10() { + var radix = NBK.blackHoleIdentity(10) + var decoded = NBK.blackHoleIdentity(Self.decoded) + + for _ in 0 ..< 1_000 { + NBK.blackHole(NBK.descriptionAsStdlib(decoded, radix: radix)) + NBK.blackHoleInoutIdentity(&radix) + NBK.blackHoleInoutIdentity(&decoded) + } + } + + func testEncodingUsingSwiftStdlibRadix16() { + var radix = NBK.blackHoleIdentity(16) + var decoded = NBK.blackHoleIdentity(Self.decoded) + + for _ in 0 ..< 1_000 { + NBK.blackHole(NBK.descriptionAsStdlib(decoded, radix: radix)) + NBK.blackHoleInoutIdentity(&radix) + NBK.blackHoleInoutIdentity(&decoded) + } + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Text x UIntXL +//*============================================================================* + +final class NBKFlexibleWidthBenchmarksOnTextAsUIntXL: XCTestCase { + + typealias T = UIntXL + + //=------------------------------------------------------------------------= + // MARK: State + //=------------------------------------------------------------------------= + + static let decoded = NBK.blackHoleIdentity(T(encoded, radix: 16)!) + static let encoded = NBK.blackHoleIdentity(String(repeating: "1", count: 64)) + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testDecodingRadix10() { + var radix = NBK.blackHoleIdentity(10) + var encoded = NBK.blackHoleIdentity(Self.encoded) + + for _ in 0 ..< 250_000 { + NBK.blackHole(T(encoded, radix: radix)!) + NBK.blackHoleInoutIdentity(&radix) + NBK.blackHoleInoutIdentity(&encoded) + } + } + + func testDecodingRadix16() { + var radix = NBK.blackHoleIdentity(16) + var encoded = NBK.blackHoleIdentity(Self.encoded) + + for _ in 0 ..< 250_000 { + NBK.blackHole(T(encoded, radix: radix)!) + NBK.blackHoleInoutIdentity(&radix) + NBK.blackHoleInoutIdentity(&encoded) + } + } + + func testEncodingRadix10() { + var radix = NBK.blackHoleIdentity(10) + var decoded = NBK.blackHoleIdentity(Self.decoded) + + for _ in 0 ..< 250_000 { + NBK.blackHole(String(decoded, radix: radix)) + NBK.blackHoleInoutIdentity(&radix) + NBK.blackHoleInoutIdentity(&decoded) + } + } + + func testEncodingRadix16() { + var radix = NBK.blackHoleIdentity(16) + var decoded = NBK.blackHoleIdentity(Self.decoded) + + for _ in 0 ..< 250_000 { + NBK.blackHole(String(decoded, radix: radix)) + NBK.blackHoleInoutIdentity(&radix) + NBK.blackHoleInoutIdentity(&decoded) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Swift Standard Library Methods + //=------------------------------------------------------------------------= + + func testEncodingUsingSwiftStdlibRadix10() { + var radix = NBK.blackHoleIdentity(10) + var decoded = NBK.blackHoleIdentity(Self.decoded) + + for _ in 0 ..< 1_000 { + NBK.blackHole(NBK.descriptionAsStdlib(decoded, radix: radix)) + NBK.blackHoleInoutIdentity(&radix) + NBK.blackHoleInoutIdentity(&decoded) + } + } + + func testEncodingUsingSwiftStdlibRadix16() { + var radix = NBK.blackHoleIdentity(16) + var decoded = NBK.blackHoleIdentity(Self.decoded) + + for _ in 0 ..< 1_000 { + NBK.blackHole(NBK.descriptionAsStdlib(decoded, radix: radix)) + NBK.blackHoleInoutIdentity(&radix) + NBK.blackHoleInoutIdentity(&decoded) + } + } +} + +#endif diff --git a/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Words.swift b/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Words.swift new file mode 100644 index 00000000..faacb817 --- /dev/null +++ b/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Words.swift @@ -0,0 +1,72 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if !DEBUG + +import NBKCoreKit +import NBKTwosComplementKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Flexible Width x Words x IntXL +//*============================================================================* + +final class NBKFlexibleWidthBenchmarksOnWordsAsIntXL: XCTestCase { + + typealias T = IntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testFromWords() { + var abc = NBK.blackHoleIdentity([ 0, 0, 0, 0] as W) + var xyz = NBK.blackHoleIdentity([~0, ~0, ~0, ~0] as W) + + for _ in 0 ..< 250_000 { + NBK.blackHole(T(words: abc)) + NBK.blackHole(T(words: xyz)) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Words x UIntXL +//*============================================================================* + +final class NBKFlexibleWidthBenchmarksOnWordsAsUIntXL: XCTestCase { + + typealias T = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testFromWords() { + var abc = NBK.blackHoleIdentity([ 0, 0, 0, 0] as W) + var xyz = NBK.blackHoleIdentity([~0, ~0, ~0, ~0] as W) + + for _ in 0 ..< 250_000 { + NBK.blackHole(T(words: abc)) + NBK.blackHole(T(words: xyz)) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } +} + +#endif diff --git a/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth.swift b/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth.swift new file mode 100644 index 00000000..e8959f9b --- /dev/null +++ b/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth.swift @@ -0,0 +1,68 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit +import NBKTwosComplementKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Flexible Width x Initializers x IntXL +//*============================================================================* + +extension NBKFlexibleWidth { + + //=------------------------------------------------------------------------= + // MARK: Details x Numbers + //=------------------------------------------------------------------------= + + static let min256 = Self(x64:[ 0, 0, 0, ~0/2 + 1] as X) + static let max256 = Self(x64:[~0, ~0, ~0, ~0/2 + 0] as X) + + //=------------------------------------------------------------------------= + // MARK: Details x Limbs + //=------------------------------------------------------------------------= + + init(x32: [UInt32]) { + self.init(words: NBKChunkedInt(x32)) + } + + init(x64: [UInt64]) { + self.init(words: NBKChunkedInt(x64)) + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Initializers x UIntXL +//*============================================================================* + +extension NBKFlexibleWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Details x Numbers + //=------------------------------------------------------------------------= + + static let min256 = Self(x64:[ 0, 0, 0, 0] as X) + static let max256 = Self(x64:[~0, ~0, ~0, ~0] as X) + + //=------------------------------------------------------------------------= + // MARK: Details x Limbs + //=------------------------------------------------------------------------= + + init(x32: [UInt32]) { + self.init(words: NBKChunkedInt(x32)) + } + + init(x64: [UInt64]) { + self.init(words: NBKChunkedInt(x64)) + } +} diff --git a/Tests/NBKTwosComplementKitTests/IntXL+Addition.swift b/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Addition.swift similarity index 100% rename from Tests/NBKTwosComplementKitTests/IntXL+Addition.swift rename to Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Addition.swift diff --git a/Tests/NBKTwosComplementKitTests/IntXL+Bits.swift b/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Bits.swift similarity index 100% rename from Tests/NBKTwosComplementKitTests/IntXL+Bits.swift rename to Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Bits.swift diff --git a/Tests/NBKTwosComplementKitTests/IntXL+Comparisons.swift b/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Comparisons.swift similarity index 100% rename from Tests/NBKTwosComplementKitTests/IntXL+Comparisons.swift rename to Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Comparisons.swift diff --git a/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Complements.swift b/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Complements.swift new file mode 100644 index 00000000..bc84b34b --- /dev/null +++ b/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Complements.swift @@ -0,0 +1,210 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +import NBKTwosComplementKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Flexible Width x Complements x IntXL +//*============================================================================* + +final class NBKFlexibleWidthTestsOnComplementsAsIntXL: XCTestCase { + + typealias T = IntXL + typealias M = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests x Magnitude + //=------------------------------------------------------------------------= + + func testMagnitude() { + XCTAssertEqual(T(words:[ 1, 0, 0, 0] as W).magnitude, M(words:[ 1, 0, 0, 0] as W)) + XCTAssertEqual(T(words:[~0, 0, 0, 0] as W).magnitude, M(words:[~0, 0, 0, 0] as W)) + XCTAssertEqual(T(words:[ 1, 1, 1, 1] as W).magnitude, M(words:[ 1, 1, 1, 1] as W)) + XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).magnitude, M(words:[ 1, 0, 0, 0] as W)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x One's Complement + //=------------------------------------------------------------------------= + + func testOnesComplement() { + NBKAssertOnesComplement(-T(1), T(0)) + NBKAssertOnesComplement(-T(0), -T(1)) + NBKAssertOnesComplement( T(0), -T(1)) + NBKAssertOnesComplement( T(1), -T(2)) + + NBKAssertOnesComplement(T(words:[ 0, 0, 0, 0] as W), T(words:[~0, ~0, ~0, ~0] as W)) + NBKAssertOnesComplement(T(words:[ 1, 0, 0, 0] as W), T(words:[~1, ~0, ~0, ~0] as W)) + NBKAssertOnesComplement(T(words:[~0, 0, 0, 0] as W), T(words:[ 0, ~0, ~0, ~0] as W)) + NBKAssertOnesComplement(T(words:[ 1, 1, 1, 1] as W), T(words:[~1, ~1, ~1, ~1] as W)) + NBKAssertOnesComplement(T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 0, 0, 0, 0] as W)) + + NBKAssertOnesComplement(T(words:[~0, ~0, ~0, ~0/2 + 0, 0] as W), T(words:[ 0, 0, 0, ~0/2 + 1, ~0] as W)) + NBKAssertOnesComplement(T(words:[ 0, 0, 0, ~0/2 + 1, 0] as W), T(words:[~0, ~0, ~0, ~0/2 + 0, ~0] as W)) + NBKAssertOnesComplement(T(words:[ 1, 0, 0, ~0/2 + 1, 0] as W), T(words:[~1, ~0, ~0, ~0/2 + 0, ~0] as W)) + + NBKAssertOnesComplement(T(words:[ 1, 0, 0, ~0/2 + 1, ~0] as W), T(words:[~1, ~0, ~0, ~0/2 + 0, 0] as W)) + NBKAssertOnesComplement(T(words:[ 0, 0, 0, ~0/2 + 1, ~0] as W), T(words:[~0, ~0, ~0, ~0/2 + 0, 0] as W)) + NBKAssertOnesComplement(T(words:[~0, ~0, ~0, ~0/2 + 0, ~0] as W), T(words:[ 0, 0, 0, ~0/2 + 1, 0] as W)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Two's Complement + //=------------------------------------------------------------------------= + + func testTwosComplement() { + NBKAssertTwosComplement(-T(1), T(1)) + NBKAssertTwosComplement(-T(0), T(0)) + NBKAssertTwosComplement( T(0), -T(0)) + NBKAssertTwosComplement( T(1), -T(1)) + + NBKAssertTwosComplement(T(words:[ 0, 0, 0, 0] as W), T(words:[ 0, 0, 0, 0] as W)) + NBKAssertTwosComplement(T(words:[ 1, 0, 0, 0] as W), T(words:[~0, ~0, ~0, ~0] as W)) + NBKAssertTwosComplement(T(words:[~0, 0, 0, 0] as W), T(words:[ 1, ~0, ~0, ~0] as W)) + NBKAssertTwosComplement(T(words:[ 1, 1, 1, 1] as W), T(words:[~0, ~1, ~1, ~1] as W)) + NBKAssertTwosComplement(T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 1, 0, 0, 0] as W)) + + NBKAssertTwosComplement(T(words:[~0, ~0, ~0, ~0/2 + 0, 0] as W), T(words:[ 1, 0, 0, ~0/2 + 1, ~0] as W)) + NBKAssertTwosComplement(T(words:[ 0, 0, 0, ~0/2 + 1, 0] as W), T(words:[ 0, 0, 0, ~0/2 + 1, ~0] as W)) + NBKAssertTwosComplement(T(words:[ 1, 0, 0, ~0/2 + 1, 0] as W), T(words:[~0, ~0, ~0, ~0/2 + 0, ~0] as W)) + + NBKAssertTwosComplement(T(words:[ 1, 0, 0, ~0/2 + 1, ~0] as W), T(words:[~0, ~0, ~0, ~0/2 + 0, 0] as W)) + NBKAssertTwosComplement(T(words:[ 0, 0, 0, ~0/2 + 1, ~0] as W), T(words:[ 0, 0, 0, ~0/2 + 1, ~0] as W), true) + NBKAssertTwosComplement(T(words:[~0, ~0, ~0, ~0/2 + 0, ~0] as W), T(words:[ 1, 0, 0, ~0/2 + 1, 0] as W)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Additive Inverse + //=------------------------------------------------------------------------= + + func testAdditiveInverse() { + NBKAssertAdditiveInverse(T(sign: .plus, magnitude: M( )), T(sign: .minus, magnitude: M( ))) + NBKAssertAdditiveInverse(T(sign: .minus, magnitude: M( )), T(sign: .plus, magnitude: M( ))) + NBKAssertAdditiveInverse(T(sign: .plus, magnitude: M(1)), T(sign: .minus, magnitude: M(1))) + NBKAssertAdditiveInverse(T(sign: .minus, magnitude: M(1)), T(sign: .plus, magnitude: M(1))) + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Complements x UIntXL +//*============================================================================* + +final class NBKFlexibleWidthTestsOnComplementsAsUIntXL: XCTestCase { + + typealias T = UIntXL + typealias M = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests x Magnitude + //=------------------------------------------------------------------------= + + func testMagnitude() { + XCTAssertEqual(T(words:[ 1, 0, 0, 0] as W).magnitude, M(words:[ 1, 0, 0, 0] as W)) + XCTAssertEqual(T(words:[~0, 0, 0, 0] as W).magnitude, M(words:[~0, 0, 0, 0] as W)) + XCTAssertEqual(T(words:[ 1, 1, 1, 1] as W).magnitude, M(words:[ 1, 1, 1, 1] as W)) + XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).magnitude, M(words:[~0, ~0, ~0, ~0] as W)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x One's Complement + //=------------------------------------------------------------------------= + + func testOnesComplement() { + NBKAssertOnesComplement(T(words:[ 0, 0, 0, 0] as W), T(words:[~0, 0, 0, 0] as W)) + NBKAssertOnesComplement(T(words:[ 1, 0, 0, 0] as W), T(words:[~1, 0, 0, 0] as W)) + NBKAssertOnesComplement(T(words:[~0, 0, 0, 0] as W), T(words:[ 0, 0, 0, 0] as W)) + NBKAssertOnesComplement(T(words:[ 1, 1, 1, 1] as W), T(words:[~1, ~1, ~1, ~1] as W)) + NBKAssertOnesComplement(T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 0, 0, 0, 0] as W)) + + NBKAssertOnesComplement(T(words:[~0, ~0, ~0, ~0/2 + 0] as W), T(words:[ 0, 0, 0, ~0/2 + 1] as W)) + NBKAssertOnesComplement(T(words:[ 0, 0, 0, ~0/2 + 1] as W), T(words:[~0, ~0, ~0, ~0/2 + 0] as W)) + NBKAssertOnesComplement(T(words:[ 1, 0, 0, ~0/2 + 1] as W), T(words:[~1, ~0, ~0, ~0/2 + 0] as W)) + + NBKAssertOnesComplement(T(words:[ 1, 0, 0, ~0/2 + 1] as W), T(words:[~1, ~0, ~0, ~0/2 + 0] as W)) + NBKAssertOnesComplement(T(words:[ 0, 0, 0, ~0/2 + 1] as W), T(words:[~0, ~0, ~0, ~0/2 + 0] as W)) + NBKAssertOnesComplement(T(words:[~0, ~0, ~0, ~0/2 + 0] as W), T(words:[ 0, 0, 0, ~0/2 + 1] as W)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Two's Complement + //=------------------------------------------------------------------------= + + func testTwosComplement() { + NBKAssertTwosComplement(T(words:[ 0, 0, 0, 0] as W), T(words:[ 0, 0, 0, 0] as W), true) + NBKAssertTwosComplement(T(words:[ 1, 0, 0, 0] as W), T(words:[~0, 0, 0, 0] as W)) + NBKAssertTwosComplement(T(words:[~0, 0, 0, 0] as W), T(words:[ 1, 0, 0, 0] as W)) + NBKAssertTwosComplement(T(words:[ 1, 1, 1, 1] as W), T(words:[~0, ~1, ~1, ~1] as W)) + NBKAssertTwosComplement(T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 1, 0, 0, 0] as W)) + + NBKAssertTwosComplement(T(words:[~0, ~0, ~0, ~0/2 + 0] as W), T(words:[ 1, 0, 0, ~0/2 + 1] as W)) + NBKAssertTwosComplement(T(words:[ 0, 0, 0, ~0/2 + 1] as W), T(words:[ 0, 0, 0, ~0/2 + 1] as W)) + NBKAssertTwosComplement(T(words:[ 1, 0, 0, ~0/2 + 1] as W), T(words:[~0, ~0, ~0, ~0/2 + 0] as W)) + + NBKAssertTwosComplement(T(words:[ 1, 0, 0, ~0/2 + 1] as W), T(words:[~0, ~0, ~0, ~0/2 + 0] as W)) + NBKAssertTwosComplement(T(words:[ 0, 0, 0, ~0/2 + 1] as W), T(words:[ 0, 0, 0, ~0/2 + 1] as W)) + NBKAssertTwosComplement(T(words:[~0, ~0, ~0, ~0/2 + 0] as W), T(words:[ 1, 0, 0, ~0/2 + 1] as W)) + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Complements x Assertions +//*============================================================================* + +private func NBKAssertOnesComplement( +_ integer: T, _ result: T, +file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual(integer.onesComplement(), result, file: file, line: line) + XCTAssertEqual(integer.twosComplementSubsequence(false).partialValue, result, file: file, line: line) + + XCTAssertEqual({ var x = integer; let _ = x.formOnesComplement(); return x }(), result, file: file, line: line) + XCTAssertEqual({ var x = integer; let _ = x.formTwosComplementSubsequence(false); return x }(), result, file: file, line: line) +} + +private func NBKAssertTwosComplement( +_ integer: T, _ partialValue: T, _ overflow: Bool = false, +file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual(integer.twosComplement(), partialValue, file: file, line: line) + XCTAssertEqual(integer.twosComplementReportingOverflow().partialValue, partialValue, file: file, line: line) + XCTAssertEqual(integer.twosComplementReportingOverflow().overflow, overflow, file: file, line: line) + XCTAssertEqual(integer.twosComplementSubsequence(true ).partialValue, partialValue, file: file, line: line) + XCTAssertEqual(integer.twosComplementSubsequence(true ).overflow, overflow, file: file, line: line) + + XCTAssertEqual({ var x = integer; x.formTwosComplement(); return x }(), partialValue, file: file, line: line) + XCTAssertEqual({ var x = integer; let _ = x.formTwosComplementReportingOverflow(); return x }(), partialValue, file: file, line: line) + XCTAssertEqual({ var x = integer; let o = x.formTwosComplementReportingOverflow(); return o }(), overflow, file: file, line: line) + XCTAssertEqual({ var x = integer; let _ = x.formTwosComplementSubsequence(true ); return x }(), partialValue, file: file, line: line) + XCTAssertEqual({ var x = integer; let o = x.formTwosComplementSubsequence(true ); return o }(), overflow, file: file, line: line) +} + +private func NBKAssertAdditiveInverse( +_ operand: IntXL, _ partialValue: IntXL, _ overflow: Bool = false, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + if !overflow { + XCTAssertEqual(-operand, partialValue, file: file, line: line) + XCTAssertEqual((operand).negated(), partialValue, file: file, line: line) + XCTAssertEqual({ var x = operand; x.negate(); return x }(), partialValue, file: file, line: line) + } + //=------------------------------------------= + XCTAssertEqual(operand.negatedReportingOverflow().partialValue, partialValue, file: file, line: line) + XCTAssertEqual(operand.negatedReportingOverflow().overflow, overflow, file: file, line: line) + + XCTAssertEqual({ var x = operand; let _ = x.negateReportingOverflow(); return x }(), partialValue, file: file, line: line) + XCTAssertEqual({ var x = operand; let o = x.negateReportingOverflow(); return o }(), overflow, file: file, line: line) +} + +#endif diff --git a/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Division.swift b/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Division.swift new file mode 100644 index 00000000..22ec78f8 --- /dev/null +++ b/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Division.swift @@ -0,0 +1,371 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +@testable import NBKTwosComplementKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Flexible Width x Division x IntXL +//*============================================================================* + +final class NBKFlexibleWidthTestsOnDivisionAsIntXL: XCTestCase { + + typealias T = IntXL + typealias M = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testDividing() { + NBKAssertDivision( T( ), T(1), T( ), T( )) + NBKAssertDivision( T( ), T(2), T( ), T( )) + NBKAssertDivision( T(7), T(1), T(7), T( )) + NBKAssertDivision( T(7), T(2), T(3), T(1)) + + NBKAssertDivision( T(7), T(3), T(2), T(1)) + NBKAssertDivision( T(7), -T(3), -T(2), T(1)) + NBKAssertDivision(-T(7), T(3), -T(2), -T(1)) + NBKAssertDivision(-T(7), -T(3), T(2), -T(1)) + } + + func testDividingReportingOverflow() { + NBKAssertDivision( T(0), T( ), T(0), T( ), true) + NBKAssertDivision( T(1), T( ), T(1), T(1), true) + NBKAssertDivision( T(2), T( ), T(2), T(2), true) + + NBKAssertDivision(T(words:[~0, ~0, ~0, ~0/2 + 0] as W), -T(1), T(words:[1, 0, 0, ~0/2 + 1, ~0] as W), T( )) // Int256.max + NBKAssertDivision(T(words:[ 0, 0, 0, ~0/2 + 1] as W), -T(1), T(words:[0, 0, 0, ~0/2 + 1, 0] as W), T( )) // Int256.min + } + + func testDividingWithLargeDividend() { + NBKAssertDivision( T(words:[1, 2, 3, 4] as W), T(2), T(words:[0, ~0/2 + 2, 1, 2] as W), T(1)) + NBKAssertDivision( T(words:[1, 2, 3, 4] as W), -T(2), -T(words:[0, ~0/2 + 2, 1, 2] as W), T(1)) + NBKAssertDivision(-T(words:[1, 2, 3, 4] as W), T(2), -T(words:[0, ~0/2 + 2, 1, 2] as W), -T(1)) + NBKAssertDivision(-T(words:[1, 2, 3, 4] as W), -T(2), T(words:[0, ~0/2 + 2, 1, 2] as W), -T(1)) + + NBKAssertDivision( T(words:[1, 2, 3, 4] as W), T(words:[0, ~0/2 + 2, 1, 2] as W), T(2), T(1)) + NBKAssertDivision( T(words:[1, 2, 3, 4] as W), -T(words:[0, ~0/2 + 2, 1, 2] as W), -T(2), T(1)) + NBKAssertDivision(-T(words:[1, 2, 3, 4] as W), -T(words:[0, ~0/2 + 2, 1, 2] as W), T(2), -T(1)) + NBKAssertDivision(-T(words:[1, 2, 3, 4] as W), T(words:[0, ~0/2 + 2, 1, 2] as W), -T(2), -T(1)) + } + + func testDividingWithLargeDivisor() { + NBKAssertDivision(T(words:[1, 2, 3, 4 + 1 << 63] as W), T(words:[ 1, 2, 3, 4 &+ 1 << 63] as W), T(1), -T(words:[0, 0, 0, 0] as W)) + NBKAssertDivision(T(words:[1, 2, 3, 4 + 1 << 63] as W), T(words:[ 2, 3, 4, 5 &+ 1 << 63] as W), T(1), -T(words:[1, 1, 1, 1] as W)) + NBKAssertDivision(T(words:[1, 2, 3, 4 + 1 << 63] as W), T(words:[ 3, 4, 5, 6 &+ 1 << 63] as W), T(1), -T(words:[2, 2, 2, 2] as W)) + NBKAssertDivision(T(words:[1, 2, 3, 4 + 1 << 63] as W), T(words:[ 4, 5, 6, 7 &+ 1 << 63] as W), T(1), -T(words:[3, 3, 3, 3] as W)) + + NBKAssertDivision(T(words:[1, 2, 3, 4 + 1 << 63] as W), T(words:[~0, ~2, ~3, ~4 &+ 1 << 63] as W), -T(1), -T(words:[0, 0, 0, 0] as W)) + NBKAssertDivision(T(words:[1, 2, 3, 4 + 1 << 63] as W), T(words:[~1, ~3, ~4, ~5 &+ 1 << 63] as W), -T(1), -T(words:[1, 1, 1, 1] as W)) + NBKAssertDivision(T(words:[1, 2, 3, 4 + 1 << 63] as W), T(words:[~2, ~4, ~5, ~6 &+ 1 << 63] as W), -T(1), -T(words:[2, 2, 2, 2] as W)) + NBKAssertDivision(T(words:[1, 2, 3, 4 + 1 << 63] as W), T(words:[~3, ~5, ~6, ~7 &+ 1 << 63] as W), -T(1), -T(words:[3, 3, 3, 3] as W)) + } + + func testDividingLikeFullWidth() { + var dividend: T + //=--------------------------------------= + dividend = T(words:[ 06, 17, 35, 61, 61, 52, 32, 00] as W) + NBKAssertDivision(dividend, T(words:[ 1, 2, 3, 4] as W), T(words:[ 5, 6, 7, 8] as W), T(words:[ 1, 1, 1, 1] as W)) + NBKAssertDivision(dividend, T(words:[ 5, 6, 7, 8] as W), T(words:[ 1, 2, 3, 4] as W), T(words:[ 1, 1, 1, 1] as W)) + //=--------------------------------------= + dividend = T(words:[ 34, 54, 63, 62, 34, 16, 05, 00] as W) + NBKAssertDivision(dividend, T(words:[ 4, 3, 2, 1] as W), T(words:[ 9, 7, 6, 5] as W), T(words:[~1, ~1, ~0, 0] as W)) + NBKAssertDivision(dividend, T(words:[ 8, 7, 6, 5] as W), T(words:[ 4, 3, 2, 1] as W), T(words:[ 2, 2, 2, 2] as W)) + //=--------------------------------------= + dividend = T(words:[ ~1, ~0, ~0, ~0, ~0, ~0, ~0, ~0] as W) + NBKAssertDivision(dividend, T(words:[ 1, 0, 0, 0] as W), T(words:[~1, ~0, ~0, ~0] as W), T(words:[ 0, 0, 0, 0] as W)) + NBKAssertDivision(dividend, T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 2, 0, 0, 0] as W), T(words:[ 0, 0, 0, 0] as W)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Digit + //=------------------------------------------------------------------------= + + func testDividingByDigit() { + NBKAssertDivisionByDigit( T( ), Int(1), T( ), Int( )) + NBKAssertDivisionByDigit( T( ), Int(2), T( ), Int( )) + NBKAssertDivisionByDigit( T(7), Int(1), T(7), Int( )) + NBKAssertDivisionByDigit( T(7), Int(2), T(3), Int(1)) + + NBKAssertDivisionByDigit( T(7), Int(3), T(2), Int(1)) + NBKAssertDivisionByDigit( T(7), -Int(3), -T(2), Int(1)) + NBKAssertDivisionByDigit(-T(7), Int(3), -T(2), -Int(1)) + NBKAssertDivisionByDigit(-T(7), -Int(3), T(2), -Int(1)) + } + + func testDividingByDigitReportingOverflow() { + NBKAssertDivisionByDigit( T(0), Int( ), T( 0), Int( ), true) + NBKAssertDivisionByDigit( T(1), Int( ), T( 1), Int(1), true) + NBKAssertDivisionByDigit( T(2), Int( ), T( 2), Int(2), true) + + NBKAssertDivisionByDigit(T(words:[~0, ~0, ~0, ~0/2 + 0] as W), -Int(1), T(words:[1, 0, 0, ~0/2 + 1, ~0] as W), Int( )) // Int256.max + NBKAssertDivisionByDigit(T(words:[ 0, 0, 0, ~0/2 + 1] as W), -Int(1), T(words:[0, 0, 0, ~0/2 + 1, 0] as W), Int( )) // Int256.min + } + + func testDividingByDigitWithLargeDividend() { + NBKAssertDivisionByDigit( T(words:[1, 2, 3, 4] as W), Int(2), T(words:[0, ~0/2 + 2, 1, 2] as W), Int(1)) + NBKAssertDivisionByDigit( T(words:[1, 2, 3, 4] as W), -Int(2), -T(words:[0, ~0/2 + 2, 1, 2] as W), Int(1)) + NBKAssertDivisionByDigit(-T(words:[1, 2, 3, 4] as W), Int(2), -T(words:[0, ~0/2 + 2, 1, 2] as W), -Int(1)) + NBKAssertDivisionByDigit(-T(words:[1, 2, 3, 4] as W), -Int(2), T(words:[0, ~0/2 + 2, 1, 2] as W), -Int(1)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Miscellaneous + //=------------------------------------------------------------------------= + + func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { + func becauseThisCompilesSuccessfully(_ x: inout T) { + XCTAssertNotNil(x /= 0) + XCTAssertNotNil(x %= 0) + XCTAssertNotNil(x.divideReportingOverflow(by: 0)) + XCTAssertNotNil(x.formRemainderReportingOverflow(dividingBy: 0)) + + XCTAssertNotNil(x / 0) + XCTAssertNotNil(x % 0) + XCTAssertNotNil(x.dividedReportingOverflow(by: 0)) + XCTAssertNotNil(x.remainderReportingOverflow(dividingBy: 0)) + XCTAssertNotNil(x.quotientAndRemainder(dividingBy: 0)) + XCTAssertNotNil(x.quotientAndRemainderReportingOverflow(dividingBy: 0)) + } + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Division x UIntXL +//*============================================================================* + +final class NBKFlexibleWidthTestsOnDivisionAsUIntXL: XCTestCase { + + typealias T = UIntXL + typealias M = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testDividing() { + NBKAssertDivision(T( ), T(1), T( ), T( )) + NBKAssertDivision(T( ), T(2), T( ), T( )) + NBKAssertDivision(T(7), T(1), T(7), T( )) + NBKAssertDivision(T(7), T(2), T(3), T(1)) + } + + func testDividingReportingOverflow() { + NBKAssertDivision(T( ), T( ), T( ), T( ), true) + NBKAssertDivision(T(1), T( ), T(1), T(1), true) + NBKAssertDivision(T(2), T( ), T(2), T(2), true) + } + + func testDividingWithLargeDividend() { + NBKAssertDivision(T(x64:[~2, ~4, ~6, 9] as X), T(2), T(x64:[~1, ~2, ~3, 4] as X), T(1)) + NBKAssertDivision(T(x64:[~3, ~6, ~9, 14] as X), T(3), T(x64:[~1, ~2, ~3, 4] as X), T(2)) + NBKAssertDivision(T(x64:[~4, ~8, ~12, 19] as X), T(4), T(x64:[~1, ~2, ~3, 4] as X), T(3)) + NBKAssertDivision(T(x64:[~5, ~10, ~15, 24] as X), T(5), T(x64:[~1, ~2, ~3, 4] as X), T(4)) + + NBKAssertDivision(T(x64:[~2, ~4, ~6, 9] as X), T(x64:[~1, ~2, ~3, 4] as X), T(2), T(1)) + NBKAssertDivision(T(x64:[~3, ~6, ~9, 14] as X), T(x64:[~1, ~2, ~3, 4] as X), T(3), T(2)) + NBKAssertDivision(T(x64:[~4, ~8, ~12, 19] as X), T(x64:[~1, ~2, ~3, 4] as X), T(4), T(3)) + NBKAssertDivision(T(x64:[~5, ~10, ~15, 24] as X), T(x64:[~1, ~2, ~3, 4] as X), T(5), T(4)) + } + + func testDividingWithLargeDivisor() { + NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X), T(x64:[ 3, 4, 5, 6 &+ 1 << 63] as X), T(0), T(x64:[1, 2, 3, 4 + 1 << 63] as X)) + NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X), T(x64:[ 2, 3, 4, 5 &+ 1 << 63] as X), T(0), T(x64:[1, 2, 3, 4 + 1 << 63] as X)) + + NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X), T(x64:[ 1, 2, 3, 4 &+ 1 << 63] as X), T(1), T(x64:[0, 0, 0, 0] as X)) + NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X), T(x64:[ 0, 1, 2, 3 &+ 1 << 63] as X), T(1), T(x64:[1, 1, 1, 1] as X)) + NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X), T(x64:[~0, ~0, 0, 2 &+ 1 << 63] as X), T(1), T(x64:[2, 2, 2, 2] as X)) + NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X), T(x64:[~1, ~1, ~0, 0 &+ 1 << 63] as X), T(1), T(x64:[3, 3, 3, 3] as X)) + + NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X), T(x64:[~2, ~2, ~1, ~0 &+ 1 << 63] as X), T(1), T(x64:[4, 4, 4, 4] as X)) + NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X), T(x64:[~3, ~3, ~2, ~1 &+ 1 << 63] as X), T(1), T(x64:[5, 5, 5, 5] as X)) + NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X), T(x64:[~4, ~4, ~3, ~2 &+ 1 << 63] as X), T(1), T(x64:[6, 6, 6, 6] as X)) + NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X), T(x64:[~5, ~5, ~4, ~3 &+ 1 << 63] as X), T(1), T(x64:[7, 7, 7, 7] as X)) + } + + func testDividingLikeFullWidth() { + var dividend: T + //=--------------------------------------= + dividend = T(words:[ 06, 17, 35, 61, 61, 52, 32, 00] as W) + NBKAssertDivision(dividend, T(words:[ 1, 2, 3, 4] as W), T(words:[ 5, 6, 7, 8] as W), T(words:[ 1, 1, 1, 1] as W)) + NBKAssertDivision(dividend, T(words:[ 5, 6, 7, 8] as W), T(words:[ 1, 2, 3, 4] as W), T(words:[ 1, 1, 1, 1] as W)) + //=--------------------------------------= + dividend = T(words:[ 34, 54, 63, 62, 34, 16, 05, 00] as W) + NBKAssertDivision(dividend, T(words:[ 4, 3, 2, 1] as W), T(words:[ 9, 7, 6, 5] as W), T(words:[~1, ~1, ~0, 0] as W)) + NBKAssertDivision(dividend, T(words:[ 8, 7, 6, 5] as W), T(words:[ 4, 3, 2, 1] as W), T(words:[ 2, 2, 2, 2] as W)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Digit + //=------------------------------------------------------------------------= + + func testDividingByDigit() { + NBKAssertDivisionByDigit(T( ), UInt(1), T( ), UInt( )) + NBKAssertDivisionByDigit(T( ), UInt(2), T( ), UInt( )) + NBKAssertDivisionByDigit(T(7), UInt(1), T(7), UInt( )) + NBKAssertDivisionByDigit(T(7), UInt(2), T(3), UInt(1)) + } + + func testDividingByDigitReportingOverflow() { + NBKAssertDivisionByDigit(T( ), UInt( ), T( ), UInt( ), true) + NBKAssertDivisionByDigit(T(1), UInt( ), T(1), UInt(1), true) + NBKAssertDivisionByDigit(T(2), UInt( ), T(2), UInt(2), true) + } + + func testDividingByDigitWithLargeDividend() { + NBKAssertDivisionByDigit(T(words:[~2, ~4, ~6, 9] as W), UInt(2), T(words:[~1, ~2, ~3, 4] as W), UInt(1)) + NBKAssertDivisionByDigit(T(words:[~3, ~6, ~9, 14] as W), UInt(3), T(words:[~1, ~2, ~3, 4] as W), UInt(2)) + NBKAssertDivisionByDigit(T(words:[~4, ~8, ~12, 19] as W), UInt(4), T(words:[~1, ~2, ~3, 4] as W), UInt(3)) + NBKAssertDivisionByDigit(T(words:[~5, ~10, ~15, 24] as W), UInt(5), T(words:[~1, ~2, ~3, 4] as W), UInt(4)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Miscellaneous + //=------------------------------------------------------------------------= + + func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { + func becauseThisCompilesSuccessfully(_ x: inout T) { + XCTAssertNotNil(x /= 0) + XCTAssertNotNil(x %= 0) + XCTAssertNotNil(x.divideReportingOverflow(by: 0)) + XCTAssertNotNil(x.formRemainderReportingOverflow(dividingBy: 0)) + + XCTAssertNotNil(x / 0) + XCTAssertNotNil(x % 0) + XCTAssertNotNil(x.dividedReportingOverflow(by: 0)) + XCTAssertNotNil(x.remainderReportingOverflow(dividingBy: 0)) + XCTAssertNotNil(x.quotientAndRemainder(dividingBy: 0)) + XCTAssertNotNil(x.quotientAndRemainderReportingOverflow(dividingBy: 0)) + } + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Division x UIntXL x Code Coverage +//*============================================================================* + +final class NBKFlexibleWidthTestsOnDivisionCodeCoverageAsUIntXL: XCTestCase { + + typealias T = UIntXL + typealias M = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testDividingFullWidth3212MSBAsUInt256() { + var dividend: T, divisor: T, quotient: T, remainder: T + //=--------------------------------------= + dividend = T(x64:[ 0, 0, 0, 0, 0, ~0, ~0, ~0] as X) + divisor = T(x64:[~0, ~0, ~0, ~0, 0, 0, 0, 0] as X) + quotient = T(x64:[ 0, ~0, ~0, ~0, 0, 0, 0, 0] as X) + remainder = T(x64:[ 0, ~0, ~0, ~0, 0, 0, 0, 0] as X) + NBKAssertDivision(dividend, divisor, quotient, remainder) + //=--------------------------------------= + dividend = T(x64:[~0, ~0, ~0, ~0, 0, ~0, ~0, ~0] as X) + divisor = T(x64:[~0, ~0, ~0, ~0, 0, 0, 0, 0] as X) + quotient = T(x64:[ 1, ~0, ~0, ~0, 0, 0, 0, 0] as X) + remainder = T(x64:[ 0, ~0, ~0, ~0, 0, 0, 0, 0] as X) + NBKAssertDivision(dividend, divisor, quotient, remainder) + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Division x Assertions +//*============================================================================* + +private func NBKAssertDivision( +_ lhs: T, _ rhs: T, _ quotient: T, _ remainder: T, _ overflow: Bool = false, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + XCTAssertEqual(lhs, quotient * rhs + remainder, "dividend != divisor * quotient + remainder", file: file, line: line) + //=------------------------------------------= + if !overflow { + XCTAssertEqual(lhs / rhs, quotient, file: file, line: line) + XCTAssertEqual(lhs % rhs, remainder, file: file, line: line) + + XCTAssertEqual({ var x = lhs; x /= rhs; return x }(), quotient, file: file, line: line) + XCTAssertEqual({ var x = lhs; x %= rhs; return x }(), remainder, file: file, line: line) + + XCTAssertEqual(lhs.quotientAndRemainder(dividingBy: rhs).quotient, quotient, file: file, line: line) + XCTAssertEqual(lhs.quotientAndRemainder(dividingBy: rhs).remainder, remainder, file: file, line: line) + } + //=------------------------------------------= + XCTAssertEqual(lhs.dividedReportingOverflow(by: rhs).partialValue, quotient, file: file, line: line) + XCTAssertEqual(lhs.dividedReportingOverflow(by: rhs).overflow, overflow, file: file, line: line) + + XCTAssertEqual({ var x = lhs; let _ = x.divideReportingOverflow(by: rhs); return x }(), quotient, file: file, line: line) + XCTAssertEqual({ var x = lhs; let o = x.divideReportingOverflow(by: rhs); return o }(), overflow, file: file, line: line) + + XCTAssertEqual(lhs.remainderReportingOverflow(dividingBy: rhs).partialValue, remainder, file: file, line: line) + XCTAssertEqual(lhs.remainderReportingOverflow(dividingBy: rhs).overflow, overflow, file: file, line: line) + + XCTAssertEqual({ var x = lhs; let _ = x.formRemainderReportingOverflow(dividingBy: rhs); return x }(), remainder, file: file, line: line) + XCTAssertEqual({ var x = lhs; let o = x.formRemainderReportingOverflow(dividingBy: rhs); return o }(), overflow, file: file, line: line) + + XCTAssertEqual(lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs).partialValue.quotient, quotient, file: file, line: line) + XCTAssertEqual(lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs).partialValue.remainder, remainder, file: file, line: line) + XCTAssertEqual(lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs).overflow, overflow, file: file, line: line) + //=------------------------------------------= + guard + let lhs = lhs as? UIntXL, + let rhs = rhs as? UIntXL, + let quotient = quotient as? UIntXL, + let remainder = remainder as? UIntXL + else { return } + //=------------------------------------------= + XCTAssertEqual(lhs.quotientAndRemainderReportingOverflowAsNormal(dividingBy: rhs).partialValue.quotient, quotient, file: file, line: line) + XCTAssertEqual(lhs.quotientAndRemainderReportingOverflowAsNormal(dividingBy: rhs).partialValue.remainder, remainder, file: file, line: line) + XCTAssertEqual(lhs.quotientAndRemainderReportingOverflowAsNormal(dividingBy: rhs).overflow, overflow, file: file, line: line) +} + +private func NBKAssertDivisionByDigit( +_ lhs: T, _ rhs: T.Digit, _ quotient: T, _ remainder: T.Digit, _ overflow: Bool = false, +file: StaticString = #file, line: UInt = #line) { + let extended = T(digit: remainder) + //=------------------------------------------= + XCTAssertEqual(lhs, quotient * rhs + remainder, "dividend != divisor * quotient + remainder", file: file, line: line) + //=------------------------------------------= + if !overflow { + XCTAssertEqual(lhs / rhs, quotient, file: file, line: line) + XCTAssertEqual(lhs % rhs, remainder, file: file, line: line) + + XCTAssertEqual({ var x = lhs; x /= rhs; return x }(), quotient, file: file, line: line) + XCTAssertEqual({ var x = lhs; x %= rhs; return x }(), extended, file: file, line: line) + + XCTAssertEqual(lhs.quotientAndRemainder(dividingBy: rhs).quotient, quotient, file: file, line: line) + XCTAssertEqual(lhs.quotientAndRemainder(dividingBy: rhs).remainder, remainder, file: file, line: line) + } + //=------------------------------------------= + XCTAssertEqual(lhs.dividedReportingOverflow(by: rhs).partialValue, quotient, file: file, line: line) + XCTAssertEqual(lhs.dividedReportingOverflow(by: rhs).overflow, overflow, file: file, line: line) + + XCTAssertEqual({ var x = lhs; let _ = x.divideReportingOverflow(by: rhs); return x }(), quotient, file: file, line: line) + XCTAssertEqual({ var x = lhs; let o = x.divideReportingOverflow(by: rhs); return o }(), overflow, file: file, line: line) + + XCTAssertEqual(lhs.remainderReportingOverflow(dividingBy: rhs).partialValue, remainder, file: file, line: line) + XCTAssertEqual(lhs.remainderReportingOverflow(dividingBy: rhs).overflow, overflow, file: file, line: line) + + XCTAssertEqual({ var x = lhs; let _ = x.formRemainderReportingOverflow(dividingBy: rhs); return x }(), extended, file: file, line: line) + XCTAssertEqual({ var x = lhs; let o = x.formRemainderReportingOverflow(dividingBy: rhs); return o }(), overflow, file: file, line: line) + + XCTAssertEqual(lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs).partialValue.quotient, quotient, file: file, line: line) + XCTAssertEqual(lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs).partialValue.remainder, remainder, file: file, line: line) + XCTAssertEqual(lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs).overflow, overflow, file: file, line: line) +} + +#endif diff --git a/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Literals.swift b/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Literals.swift new file mode 100644 index 00000000..b07b6a97 --- /dev/null +++ b/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Literals.swift @@ -0,0 +1,168 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +@testable import NBKTwosComplementKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Flexible Width x Literals x IntXL +//*============================================================================* + +final class NBKFlexibleWidthTestsOnLiteralsAsIntXL: XCTestCase { + + typealias T = IntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testFromIntegerLiteral() { + XCTAssertEqual(T(x64:[ 10, 0, 0, 0] as X), (10)) + XCTAssertEqual(T(x64:[ 02, 0, 0, 0] as X), (0b10)) + XCTAssertEqual(T(x64:[ 08, 0, 0, 0] as X), (0o10)) + XCTAssertEqual(T(x64:[ 16, 0, 0, 0] as X), (0x10)) + XCTAssertEqual(T(x64:[ 16, 0, 0, 0] as X), (0x10)) + XCTAssertEqual(T(x64:[ ~9, ~0, ~0, ~0] as X), (-10)) + XCTAssertEqual(T(x64:[ ~1, ~0, ~0, ~0] as X), (-0b10)) + XCTAssertEqual(T(x64:[ ~7, ~0, ~0, ~0] as X), (-0o10)) + XCTAssertEqual(T(x64:[~15, ~0, ~0, ~0] as X), (-0x10)) + #if SBI && swift(>=5.8) + XCTAssertEqual(T(x64:[ 0, 0, 0, 0] as X), (0x000000000000000000000000000000000000000000000000000000000000000000000000000000)) + XCTAssertEqual(T(x64:[ ~0, 0, 0, 0] as X), (0x00000000000000000000000000000000000000000000000000000000000000ffffffffffffffff)) + XCTAssertEqual(T(x64:[ ~0, ~0, 0, 0] as X), (0x0000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffff)) + XCTAssertEqual(T(x64:[ ~0, ~0, ~0, 0] as X), (0x000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff)) + XCTAssertEqual(T(x64:[ ~0, ~0, ~0, ~0] as X), (-0x000000000000000000000000000000000000000000000000000000000000000000000000000001)) + XCTAssertEqual(T(x64:[ 0, ~0, ~0, ~0] as X), (-0x000000000000000000000000000000000000000000000000000000000000010000000000000000)) + XCTAssertEqual(T(x64:[ 0, 0, ~0, ~0] as X), (-0x000000000000000000000000000000000000000000000100000000000000000000000000000000)) + XCTAssertEqual(T(x64:[ 0, 0, 0, ~0] as X), (-0x000000000000000000000000000001000000000000000000000000000000000000000000000000)) + + XCTAssertEqual(T(x64:[ 0, 0, 0, 0] as X), (00000000000000000000000000000000000000000000000000000000000000000000000000000000)) + XCTAssertEqual(T(x64:[ ~0, 0, 0, 0] as X), (00000000000000000000000000000000000000000000000000000000000018446744073709551615)) + XCTAssertEqual(T(x64:[ ~0, ~0, 0, 0] as X), (00000000000000000000000000000000000000000340282366920938463463374607431768211455)) + XCTAssertEqual(T(x64:[ ~0, ~0, ~0, 0] as X), (00000000000000000000006277101735386680763835789423207666416102355444464034512895)) + XCTAssertEqual(T(x64:[ ~0, ~0, ~0, ~0] as X), (-00000000000000000000000000000000000000000000000000000000000000000000000000000001)) + XCTAssertEqual(T(x64:[ 0, ~0, ~0, ~0] as X), (-00000000000000000000000000000000000000000000000000000000000018446744073709551616)) + XCTAssertEqual(T(x64:[ 0, 0, ~0, ~0] as X), (-00000000000000000000000000000000000000000340282366920938463463374607431768211456)) + XCTAssertEqual(T(x64:[ 0, 0, 0, ~0] as X), (-00000000000000000000006277101735386680763835789423207666416102355444464034512896)) + #else + XCTAssertEqual(T(integerLiteral: Int.max), T(x64:[UInt64(Int.max), 0, 0, 0] as X)) + XCTAssertEqual(T(integerLiteral: Int.min), ~T(x64:[UInt64(Int.max), 0, 0, 0] as X)) + #endif + } + + func testFromStringLiteral() { + XCTAssertEqual(T(x64:[ 10, 0, 0, 0] as X), "10") + XCTAssertEqual(T(x64:[ 02, 0, 0, 0] as X), "0b10") + XCTAssertEqual(T(x64:[ 08, 0, 0, 0] as X), "0o10") + XCTAssertEqual(T(x64:[ 16, 0, 0, 0] as X), "0x10") + XCTAssertEqual(T(x64:[ 16, 0, 0, 0] as X), "0x10") + XCTAssertEqual(T(x64:[ ~9, ~0, ~0, ~0] as X), "-10") + XCTAssertEqual(T(x64:[ ~1, ~0, ~0, ~0] as X), "-0b10") + XCTAssertEqual(T(x64:[ ~7, ~0, ~0, ~0] as X), "-0o10") + XCTAssertEqual(T(x64:[~15, ~0, ~0, ~0] as X), "-0x10") + + XCTAssertEqual(T(x64:[ 0, 0, 0, 0] as X), "0x000000000000000000000000000000000000000000000000000000000000000000000000000000") + XCTAssertEqual(T(x64:[ ~0, 0, 0, 0] as X), "0x00000000000000000000000000000000000000000000000000000000000000ffffffffffffffff") + XCTAssertEqual(T(x64:[ ~0, ~0, 0, 0] as X), "0x0000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffff") + XCTAssertEqual(T(x64:[ ~0, ~0, ~0, 0] as X), "0x000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff") + XCTAssertEqual(T(x64:[ ~0, ~0, ~0, ~0] as X), "-0x000000000000000000000000000000000000000000000000000000000000000000000000000001") + XCTAssertEqual(T(x64:[ 0, ~0, ~0, ~0] as X), "-0x000000000000000000000000000000000000000000000000000000000000010000000000000000") + XCTAssertEqual(T(x64:[ 0, 0, ~0, ~0] as X), "-0x000000000000000000000000000000000000000000000100000000000000000000000000000000") + XCTAssertEqual(T(x64:[ 0, 0, 0, ~0] as X), "-0x000000000000000000000000000001000000000000000000000000000000000000000000000000") + + XCTAssertEqual(T(x64:[ 0, 0, 0, 0] as X), "00000000000000000000000000000000000000000000000000000000000000000000000000000000") + XCTAssertEqual(T(x64:[ ~0, 0, 0, 0] as X), "00000000000000000000000000000000000000000000000000000000000018446744073709551615") + XCTAssertEqual(T(x64:[ ~0, ~0, 0, 0] as X), "00000000000000000000000000000000000000000340282366920938463463374607431768211455") + XCTAssertEqual(T(x64:[ ~0, ~0, ~0, 0] as X), "00000000000000000000006277101735386680763835789423207666416102355444464034512895") + XCTAssertEqual(T(x64:[ ~0, ~0, ~0, ~0] as X), "-00000000000000000000000000000000000000000000000000000000000000000000000000000001") + XCTAssertEqual(T(x64:[ 0, ~0, ~0, ~0] as X), "-00000000000000000000000000000000000000000000000000000000000018446744073709551616") + XCTAssertEqual(T(x64:[ 0, 0, ~0, ~0] as X), "-00000000000000000000000000000000000000000340282366920938463463374607431768211456") + XCTAssertEqual(T(x64:[ 0, 0, 0, ~0] as X), "-00000000000000000000006277101735386680763835789423207666416102355444464034512896") + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Literals x UIntXL +//*============================================================================* + +final class NBKFlexibleWidthTestsOnLiteralsAsUIntXL: XCTestCase { + + typealias T = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testFromIntegerLiteral() { + XCTAssertEqual(T(x64:[ 10, 0, 0, 0] as X), (10)) + XCTAssertEqual(T(x64:[ 02, 0, 0, 0] as X), (0b10)) + XCTAssertEqual(T(x64:[ 08, 0, 0, 0] as X), (0o10)) + XCTAssertEqual(T(x64:[ 16, 0, 0, 0] as X), (0x10)) + #if SBI && swift(>=5.8) + XCTAssertEqual(T(x64:[ 0, 0, 0, 0] as X), (0x000000000000000000000000000000000000000000000000000000000000000000000000000000)) + XCTAssertEqual(T(x64:[ ~0, 0, 0, 0] as X), (0x00000000000000000000000000000000000000000000000000000000000000ffffffffffffffff)) + XCTAssertEqual(T(x64:[ ~0, ~0, 0, 0] as X), (0x0000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffff)) + XCTAssertEqual(T(x64:[ ~0, ~0, ~0, 0] as X), (0x000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff)) + XCTAssertEqual(T(x64:[ ~0, ~0, ~0, ~0] as X), (0x00000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)) + XCTAssertEqual(T(x64:[ 0, ~0, ~0, ~0] as X), (0x00000000000000ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000)) + XCTAssertEqual(T(x64:[ 0, 0, ~0, ~0] as X), (0x00000000000000ffffffffffffffffffffffffffffffff00000000000000000000000000000000)) + XCTAssertEqual(T(x64:[ 0, 0, 0, ~0] as X), (0x00000000000000ffffffffffffffff000000000000000000000000000000000000000000000000)) + XCTAssertEqual(T(exactlyIntegerLiteral: (-0x000000000000000000000000000000000000000000000000000000000000000000000000000001)), nil) + + XCTAssertEqual(T(x64:[ 0, 0, 0, 0] as X), (00000000000000000000000000000000000000000000000000000000000000000000000000000000)) + XCTAssertEqual(T(x64:[ ~0, 0, 0, 0] as X), (00000000000000000000000000000000000000000000000000000000000018446744073709551615)) + XCTAssertEqual(T(x64:[ ~0, ~0, 0, 0] as X), (00000000000000000000000000000000000000000340282366920938463463374607431768211455)) + XCTAssertEqual(T(x64:[ ~0, ~0, ~0, 0] as X), (00000000000000000000006277101735386680763835789423207666416102355444464034512895)) + XCTAssertEqual(T(x64:[ ~0, ~0, ~0, ~0] as X), (00115792089237316195423570985008687907853269984665640564039457584007913129639935)) + XCTAssertEqual(T(x64:[ 0, ~0, ~0, ~0] as X), (00115792089237316195423570985008687907853269984665640564039439137263839420088320)) + XCTAssertEqual(T(x64:[ 0, 0, ~0, ~0] as X), (00115792089237316195423570985008687907852929702298719625575994209400481361428480)) + XCTAssertEqual(T(x64:[ 0, 0, 0, ~0] as X), (00115792089237316195417293883273301227089434195242432897623355228563449095127040)) + XCTAssertEqual(T(exactlyIntegerLiteral: (-00000000000000000000000000000000000000000000000000000000000000000000000000000001)), nil) + #else + XCTAssertEqual(T(integerLiteral: UInt.max), T(x64:[UInt64(UInt.max), 0, 0, 0] as X)) + XCTAssertEqual(T(integerLiteral: UInt.min), T(x64:[UInt64(UInt.min), 0, 0, 0] as X)) + #endif + } + + func testFromStringLiteral() { + XCTAssertEqual(T(x64:[ 10, 0, 0, 0] as X), "10") + XCTAssertEqual(T(x64:[ 02, 0, 0, 0] as X), "0b10") + XCTAssertEqual(T(x64:[ 08, 0, 0, 0] as X), "0o10") + XCTAssertEqual(T(x64:[ 16, 0, 0, 0] as X), "0x10") + + XCTAssertEqual(T(x64:[ 0, 0, 0, 0] as X), "0x000000000000000000000000000000000000000000000000000000000000000000000000000000") + XCTAssertEqual(T(x64:[ ~0, 0, 0, 0] as X), "0x00000000000000000000000000000000000000000000000000000000000000ffffffffffffffff") + XCTAssertEqual(T(x64:[ ~0, ~0, 0, 0] as X), "0x0000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffff") + XCTAssertEqual(T(x64:[ ~0, ~0, ~0, 0] as X), "0x000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff") + XCTAssertEqual(T(x64:[ ~0, ~0, ~0, ~0] as X), "0x00000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") + XCTAssertEqual(T(x64:[ 0, ~0, ~0, ~0] as X), "0x00000000000000ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000") + XCTAssertEqual(T(x64:[ 0, 0, ~0, ~0] as X), "0x00000000000000ffffffffffffffffffffffffffffffff00000000000000000000000000000000") + XCTAssertEqual(T(x64:[ 0, 0, 0, ~0] as X), "0x00000000000000ffffffffffffffff000000000000000000000000000000000000000000000000") + XCTAssertEqual(T(exactlyStringLiteral: "-0x000000000000000000000000000000000000000000000000000000000000000000000000000001"), nil) + + XCTAssertEqual(T(x64:[ 0, 0, 0, 0] as X), "00000000000000000000000000000000000000000000000000000000000000000000000000000000") + XCTAssertEqual(T(x64:[ ~0, 0, 0, 0] as X), "00000000000000000000000000000000000000000000000000000000000018446744073709551615") + XCTAssertEqual(T(x64:[ ~0, ~0, 0, 0] as X), "00000000000000000000000000000000000000000340282366920938463463374607431768211455") + XCTAssertEqual(T(x64:[ ~0, ~0, ~0, 0] as X), "00000000000000000000006277101735386680763835789423207666416102355444464034512895") + XCTAssertEqual(T(x64:[ ~0, ~0, ~0, ~0] as X), "00115792089237316195423570985008687907853269984665640564039457584007913129639935") + XCTAssertEqual(T(x64:[ 0, ~0, ~0, ~0] as X), "00115792089237316195423570985008687907853269984665640564039439137263839420088320") + XCTAssertEqual(T(x64:[ 0, 0, ~0, ~0] as X), "00115792089237316195423570985008687907852929702298719625575994209400481361428480") + XCTAssertEqual(T(x64:[ 0, 0, 0, ~0] as X), "00115792089237316195417293883273301227089434195242432897623355228563449095127040") + XCTAssertEqual(T(exactlyStringLiteral: "-00000000000000000000000000000000000000000000000000000000000000000000000000000001"), nil) + } +} + +#endif diff --git a/Tests/NBKTwosComplementKitTests/IntXL+Logic.swift b/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Logic.swift similarity index 100% rename from Tests/NBKTwosComplementKitTests/IntXL+Logic.swift rename to Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Logic.swift diff --git a/Tests/NBKTwosComplementKitTests/IntXL+Multiplication.swift b/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Multiplication.swift similarity index 100% rename from Tests/NBKTwosComplementKitTests/IntXL+Multiplication.swift rename to Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Multiplication.swift diff --git a/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Numbers.swift b/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Numbers.swift new file mode 100644 index 00000000..0ed7ac35 --- /dev/null +++ b/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Numbers.swift @@ -0,0 +1,573 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +import NBKTwosComplementKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Flexible Width x Numbers x IntXL +//*============================================================================* + +final class NBKFlexibleWidthTestsOnNumbersAsIntXL: XCTestCase { + + typealias S = IntXL + typealias T = IntXL + typealias M = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testZero() { + XCTAssertEqual(T( 0), T(words:[0])) + XCTAssertEqual(T.zero, T(words:[0])) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Int + //=------------------------------------------------------------------------= + + func testToInt() { + NBKAssertNumbers(from: T(words:[ 1, 0, 0, 0] as W), default: Int( 1)) + NBKAssertNumbers(from: T(words:[~0, 0, 0, 0] as W), exactly: nil, clamping: Int.max, truncating: -1) + NBKAssertNumbers(from: T(words:[ 1, 1, 1, 1] as W), exactly: nil, clamping: Int.max, truncating: 1) + NBKAssertNumbers(from: T(words:[~0, ~0, ~0, ~0] as W), default: Int(-1)) + } + + func testFromInt() { + NBKAssertNumbers(from: Int.min, default: ~T(words:[UInt(Int.max), 0, 0, 0] as W)) + NBKAssertNumbers(from: Int.max, default: T(words:[UInt(Int.max), 0, 0, 0] as W)) + } + + func testFromIntAsDigit() { + NBKAssertNumbers(from: T(digit: Int.min), default: ~T(words:[UInt(Int.max), 0, 0, 0] as W)) + NBKAssertNumbers(from: T(digit: Int.max), default: T(words:[UInt(Int.max), 0, 0, 0] as W)) + } + + func testFromIntAsDigitAtIndex() { + NBKAssertNumbers(from: T(digit: Int( 4), at: Int(0)), default: T(words:[ 4, 0, 0, 0] as W)) + NBKAssertNumbers(from: T(digit: Int( 4), at: Int(1)), default: T(words:[ 0, 4, 0, 0] as W)) + NBKAssertNumbers(from: T(digit: Int( 4), at: Int(2)), default: T(words:[ 0, 0, 4, 0] as W)) + NBKAssertNumbers(from: T(digit: Int( 4), at: Int(3)), default: T(words:[ 0, 0, 0, 4] as W)) + + NBKAssertNumbers(from: T(digit: Int(-4), at: Int(0)), default: T(words:[~3, ~0, ~0, ~0] as W)) + NBKAssertNumbers(from: T(digit: Int(-4), at: Int(1)), default: T(words:[ 0, ~3, ~0, ~0] as W)) + NBKAssertNumbers(from: T(digit: Int(-4), at: Int(2)), default: T(words:[ 0, 0, ~3, ~0] as W)) + NBKAssertNumbers(from: T(digit: Int(-4), at: Int(3)), default: T(words:[ 0, 0, 0, ~3] as W)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Int32 + //=------------------------------------------------------------------------= + + func testToInt32() { + NBKAssertNumbers(from: T(x32:[ 1, 0, 0, 0] as Y), default: Int32( 1)) + NBKAssertNumbers(from: T(x32:[~0, 0, 0, 0] as Y), exactly: nil, clamping: Int32.max, truncating: -1) + NBKAssertNumbers(from: T(x32:[ 1, 1, 1, 1] as Y), exactly: nil, clamping: Int32.max, truncating: 1) + NBKAssertNumbers(from: T(x32:[~0, ~0, ~0, ~0] as Y), default: Int32(-1)) + } + + func testFromInt32() { + NBKAssertNumbers(from: Int32.min, default: T(words: Int32.min.words)) + NBKAssertNumbers(from: Int32.max, default: T(words: Int32.max.words)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Int64 + //=------------------------------------------------------------------------= + + func testToInt64() { + NBKAssertNumbers(from: T(x64:[ 1, 0, 0, 0] as X), default: Int64( 1)) + NBKAssertNumbers(from: T(x64:[~0, 0, 0, 0] as X), exactly: nil, clamping: Int64.max, truncating: -1) + NBKAssertNumbers(from: T(x64:[ 1, 1, 1, 1] as X), exactly: nil, clamping: Int64.max, truncating: 1) + NBKAssertNumbers(from: T(x64:[~0, ~0, ~0, ~0] as X), default: Int64(-1)) + } + + func testFromInt64() { + NBKAssertNumbers(from: Int64.min, default: T(words: Int64.min.words)) + NBKAssertNumbers(from: Int64.max, default: T(words: Int64.max.words)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x UInt + //=------------------------------------------------------------------------= + + func testToUInt() { + NBKAssertNumbers(from: T(words:[ 1, 0, 0, 0] as W), default: UInt( 1)) + NBKAssertNumbers(from: T(words:[~0, 0, 0, 0] as W), default: UInt.max) + NBKAssertNumbers(from: T(words:[ 1, 1, 1, 1] as W), exactly: nil, clamping: ~0, truncating: UInt( 1)) + NBKAssertNumbers(from: T(words:[~0, ~0, ~0, ~0] as W), exactly: nil, clamping: 0, truncating: UInt.max) + } + + func testFromUInt() { + NBKAssertNumbers(from: UInt.min, default: T(sign: .plus, magnitude: M(words: UInt.min.words))) + NBKAssertNumbers(from: UInt.max, default: T(sign: .plus, magnitude: M(words: UInt.max.words))) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x UInt32 + //=------------------------------------------------------------------------= + + func testToUInt32() { + NBKAssertNumbers(from: T(x32:[ 1, 0, 0, 0] as Y), default: UInt32( 1)) + NBKAssertNumbers(from: T(x32:[~0, 0, 0, 0] as Y), default: UInt32.max) + NBKAssertNumbers(from: T(x32:[ 1, 1, 1, 1] as Y), exactly: nil, clamping: ~0, truncating: UInt32( 1)) + NBKAssertNumbers(from: T(x32:[~0, ~0, ~0, ~0] as Y), exactly: nil, clamping: 0, truncating: UInt32.max) + } + + func testFromUInt32() { + NBKAssertNumbers(from: UInt32.min, default: T(sign: .plus, magnitude: M(words: UInt32.min.words))) + NBKAssertNumbers(from: UInt32.max, default: T(sign: .plus, magnitude: M(words: UInt32.max.words))) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x UInt64 + //=------------------------------------------------------------------------= + + func testToUInt64() { + NBKAssertNumbers(from: T(x64:[ 1, 0, 0, 0] as X), default: UInt64( 1)) + NBKAssertNumbers(from: T(x64:[~0, 0, 0, 0] as X), default: UInt64.max) + NBKAssertNumbers(from: T(x64:[ 1, 1, 1, 1] as X), exactly: nil, clamping: ~0, truncating: UInt64( 1)) + NBKAssertNumbers(from: T(x64:[~0, ~0, ~0, ~0] as X), exactly: nil, clamping: 0, truncating: UInt64.max) + } + + func testFromUInt64() { + NBKAssertNumbers(from: UInt64.min, default: T(sign: .plus, magnitude: M(words: UInt64.min.words))) + NBKAssertNumbers(from: UInt64.max, default: T(sign: .plus, magnitude: M(words: UInt64.max.words))) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Signitude + //=------------------------------------------------------------------------= + + func testToSignitude() { + NBKAssertNumbers(from: T(words:[ 1, 0, 0, 0] as W), default: S(words:[ 1, 0, 0, 0] as W)) + NBKAssertNumbers(from: T(words:[~0, 0, 0, 0] as W), default: S(words:[~0, 0, 0, 0] as W)) + NBKAssertNumbers(from: T(words:[ 1, 1, 1, 1] as W), default: S(words:[ 1, 1, 1, 1] as W)) + NBKAssertNumbers(from: T(words:[~0, ~0, ~0, ~0] as W), default: S(words:[~0, ~0, ~0, ~0] as W)) + } + + func testFromSignitude() { + NBKAssertNumbers(from: S(words:[ 1, 0, 0, 0] as W), default: T(words:[ 1, 0, 0, 0] as W)) + NBKAssertNumbers(from: S(words:[~0, 0, 0, 0] as W), default: T(words:[~0, 0, 0, 0] as W)) + NBKAssertNumbers(from: S(words:[ 1, 1, 1, 1] as W), default: T(words:[ 1, 1, 1, 1] as W)) + NBKAssertNumbers(from: S(words:[~0, ~0, ~0, ~0] as W), default: T(words:[~0, ~0, ~0, ~0] as W)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Magnitude + //=------------------------------------------------------------------------= + + func testToMagnitude() { + NBKAssertNumbers(from: T(words:[ 1, 0, 0, 0] as W), default: M(words:[ 1, 0, 0, 0] as W)) + NBKAssertNumbers(from: T(words:[~0, 0, 0, 0] as W), default: M(words:[~0, 0, 0, 0] as W)) + NBKAssertNumbers(from: T(words:[ 1, 1, 1, 1] as W), default: M(words:[ 1, 1, 1, 1] as W)) + NBKAssertNumbers(from: T(words:[~0, ~0, ~0, ~0] as W), exactly: nil, clamping: M.zero, truncating: M(UInt.max)) + } + + func testFromMagnitude() { + NBKAssertNumbers(from: M(words:[ 1, 0, 0, 0] as W), default: T(words:[ 1, 0, 0, 0, 0] as W)) + NBKAssertNumbers(from: M(words:[~0, 0, 0, 0] as W), default: T(words:[~0, 0, 0, 0, 0] as W)) + NBKAssertNumbers(from: M(words:[ 1, 1, 1, 1] as W), default: T(words:[ 1, 1, 1, 1, 0] as W)) + NBKAssertNumbers(from: M(words:[~0, ~0, ~0, ~0] as W), default: T(words:[~0, ~0, ~0, ~0, 0] as W)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Float32 + //=------------------------------------------------------------------------= + + func testToFloat32() { + XCTAssertEqual(Float32(T(-1)), Float32(-1)) + XCTAssertEqual(Float32(T( 0)), Float32( 0)) + XCTAssertEqual(Float32(T( 1)), Float32( 1)) + + XCTAssertEqual(Float32(T( Int32.min)), Float32( Int32.min)) + XCTAssertEqual(Float32(T( Int32.max)), Float32( Int32.max)) + + XCTAssertEqual(Float32(T(UInt32.min)), Float32(UInt32.min)) + XCTAssertEqual(Float32(T(UInt32.max)), Float32(UInt32.max)) + } + + func testFromFloat32() { + XCTAssertEqual(T(Float32( 22.0)), 22) + XCTAssertEqual(T(Float32( -22.0)), -22) + XCTAssertEqual(T(Float32( 22.5)), 22) + XCTAssertEqual(T(Float32( -22.5)), -22) + + XCTAssertEqual(T(exactly: 22.5), nil) + XCTAssertEqual(T(exactly: -22.5), nil) + + XCTAssertEqual(T(exactly: pow(2, Float32(64 * 0 - 1))), nil) + XCTAssertEqual(T(exactly: pow(2, Float32(64 * 0 - 0))), T(x64:[1, 0, 0, 0] as X)) + XCTAssertEqual(T(exactly: pow(2, Float32(64 * 1 - 1))), T(x64:[1 << 63, 0, 0, 0] as X)) + XCTAssertEqual(T(exactly: pow(2, Float32(64 * 2 - 1))), T(x64:[0, 1 << 63, 0, 0] as X)) + XCTAssertEqual(T(exactly: pow(2, Float32(64 * 2 - 0))), nil) + } + + func testFromFloat32ValuesThatAreSpecial() { + XCTAssertNil(T(exactly: Float32.nan)) + XCTAssertNil(T(exactly: Float32.infinity)) + XCTAssertNil(T(exactly: Float32.signalingNaN)) + XCTAssertNil(T(exactly: Float32.leastNormalMagnitude)) + XCTAssertNil(T(exactly: Float32.leastNonzeroMagnitude)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Float64 + //=------------------------------------------------------------------------= + + func testToFloat64() { + XCTAssertEqual(Float64(T(-1)), Float64(-1)) + XCTAssertEqual(Float64(T( 0)), Float64( 0)) + XCTAssertEqual(Float64(T( 1)), Float64( 1)) + + XCTAssertEqual(Float64(T( Int64.min)), Float64( Int64.min)) + XCTAssertEqual(Float64(T( Int64.max)), Float64( Int64.max)) + + XCTAssertEqual(Float64(T(UInt64.min)), Float64(UInt64.min)) + XCTAssertEqual(Float64(T(UInt64.max)), Float64(UInt64.max)) + } + + func testFromFloat64() { + XCTAssertEqual(T(Float64( 22.0)), 22) + XCTAssertEqual(T(Float64( -22.0)), -22) + XCTAssertEqual(T(Float64( 22.5)), 22) + XCTAssertEqual(T(Float64( -22.5)), -22) + + XCTAssertEqual(T(exactly: 22.5), nil) + XCTAssertEqual(T(exactly: -22.5), nil) + + XCTAssertEqual(T(exactly: pow(2, Float64(64 * 0 - 1))), nil) + XCTAssertEqual(T(exactly: pow(2, Float64(64 * 0 - 0))), T(x64:[1, 0, 0, 0] as X)) + XCTAssertEqual(T(exactly: pow(2, Float64(64 * 1 - 1))), T(x64:[1 << 63, 0, 0, 0] as X)) + XCTAssertEqual(T(exactly: pow(2, Float64(64 * 2 - 1))), T(x64:[0, 1 << 63, 0, 0] as X)) + XCTAssertEqual(T(exactly: pow(2, Float64(64 * 3 - 1))), T(x64:[0, 0, 1 << 63, 0] as X)) + XCTAssertEqual(T(exactly: pow(2, Float64(64 * 4 - 2))), T(x64:[0, 0, 0, 1 << 62] as X)) + XCTAssertEqual(T(exactly: pow(2, Float64(64 * 4 - 1))), -T(x64:[0, 0, 0, 1 << 63] as X)) + } + + func testFromFloat64ValuesThatAreSpecial() { + XCTAssertNil(T(exactly: Float64.nan)) + XCTAssertNil(T(exactly: Float64.infinity)) + XCTAssertNil(T(exactly: Float64.signalingNaN)) + XCTAssertNil(T(exactly: Float64.leastNormalMagnitude)) + XCTAssertNil(T(exactly: Float64.leastNonzeroMagnitude)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Sign & Magnitude + //=------------------------------------------------------------------------= + + func testsFromSignAndMagnitude() { + XCTAssertEqual(T(sign: .plus, magnitude: M(1)), T(1)) + XCTAssertEqual(T(sign: .minus, magnitude: M(1)), -T(1)) + } + + func testsFromSignAndMagnitudeAsPlusMinusZero() { + XCTAssertEqual(T(sign: .plus, magnitude: M( )), T( )) + XCTAssertEqual(T(sign: .minus, magnitude: M( )), -T( )) + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Numbers x UIntXL +//*============================================================================* + +final class NBKFlexibleWidthTestsOnNumbersAsUIntXL: XCTestCase { + + typealias S = IntXL + typealias T = UIntXL + typealias M = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testZero() { + XCTAssertEqual(T( 0), T(words:[0])) + XCTAssertEqual(T.zero, T(words:[0])) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Int + //=------------------------------------------------------------------------= + + func testToInt() { + NBKAssertNumbers(from: T(words:[ 1, 0, 0, 0] as W), default: Int( 1)) + NBKAssertNumbers(from: T(words:[~0, 0, 0, 0] as W), exactly: nil, clamping: Int.max, truncating: -1) + NBKAssertNumbers(from: T(words:[ 1, 1, 1, 1] as W), exactly: nil, clamping: Int.max, truncating: 1) + NBKAssertNumbers(from: T(words:[~0, ~0, ~0, ~0] as W), exactly: nil, clamping: Int.max, truncating: -1) + } + + func testFromInt() { + NBKAssertNumbers(from: Int.min, exactly: nil, clamping: 0, truncating: T(words: Int.min.words)) + NBKAssertNumbers(from: Int.max, default: /*-------------------------*/ T(words: Int.max.words)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Int32 + //=------------------------------------------------------------------------= + + func testToInt32() { + NBKAssertNumbers(from: T(x32:[ 1, 0, 0, 0] as Y), default: Int32( 1)) + NBKAssertNumbers(from: T(x32:[~0, 0, 0, 0] as Y), exactly: nil, clamping: Int32.max, truncating: -1) + NBKAssertNumbers(from: T(x32:[ 1, 1, 1, 1] as Y), exactly: nil, clamping: Int32.max, truncating: 1) + NBKAssertNumbers(from: T(x32:[~0, ~0, ~0, ~0] as Y), exactly: nil, clamping: Int32.max, truncating: -1) + } + + func testFromInt32() { + NBKAssertNumbers(from: Int32.min, exactly: nil, clamping: 0, truncating: T(words: Int32.min.words)) + NBKAssertNumbers(from: Int32.max, default: /*-------------------------*/ T(words: Int32.max.words)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Int64 + //=------------------------------------------------------------------------= + + func testToInt64() { + NBKAssertNumbers(from: T(x64:[ 1, 0, 0, 0] as X), default: Int64( 1)) + NBKAssertNumbers(from: T(x64:[~0, 0, 0, 0] as X), exactly: nil, clamping: Int64.max, truncating: -1) + NBKAssertNumbers(from: T(x64:[ 1, 1, 1, 1] as X), exactly: nil, clamping: Int64.max, truncating: 1) + NBKAssertNumbers(from: T(x64:[~0, ~0, ~0, ~0] as X), exactly: nil, clamping: Int64.max, truncating: -1) + } + + func testFromInt64() { + NBKAssertNumbers(from: Int64.min, exactly: nil, clamping: 0, truncating: T(words: Int64.min.words)) + NBKAssertNumbers(from: Int64.max, default: /*-------------------------*/ T(words: Int64.max.words)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x UInt + //=------------------------------------------------------------------------= + + func testToUInt() { + NBKAssertNumbers(from: T(words:[ 1, 0, 0, 0] as W), default: UInt( 1)) + NBKAssertNumbers(from: T(words:[~0, 0, 0, 0] as W), default: ~UInt( 0)) + NBKAssertNumbers(from: T(words:[ 1, 1, 1, 1] as W), exactly: nil, clamping: UInt.max, truncating: 1) + NBKAssertNumbers(from: T(words:[~0, ~0, ~0, ~0] as W), exactly: nil, clamping: UInt.max, truncating: ~0) + } + + func testFromUInt() { + NBKAssertNumbers(from: UInt.min, default: T(words: UInt.min.words)) + NBKAssertNumbers(from: UInt.max, default: T(words: UInt.max.words)) + } + + func testFromUIntAsDigit() { + NBKAssertNumbers(from: T(digit: UInt.min), default: T(words:[ 0, 0, 0, 0] as W)) + NBKAssertNumbers(from: T(digit: UInt.max), default: T(words:[~0, 0, 0, 0] as W)) + } + + func testFromUIntAsDigitAtIndex() { + NBKAssertNumbers(from: T(digit: UInt.max, at: Int(0)), default: T(words:[~0, 0, 0, 0] as W)) + NBKAssertNumbers(from: T(digit: UInt.max, at: Int(1)), default: T(words:[ 0, ~0, 0, 0] as W)) + NBKAssertNumbers(from: T(digit: UInt.max, at: Int(2)), default: T(words:[ 0, 0, ~0, 0] as W)) + NBKAssertNumbers(from: T(digit: UInt.max, at: Int(3)), default: T(words:[ 0, 0, 0, ~0] as W)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x UInt32 + //=------------------------------------------------------------------------= + + func testToUInt32() { + NBKAssertNumbers(from: T(x32:[ 1, 0, 0, 0] as Y), default: UInt32( 1)) + NBKAssertNumbers(from: T(x32:[~0, 0, 0, 0] as Y), default: ~UInt32( 0)) + NBKAssertNumbers(from: T(x32:[ 1, 1, 1, 1] as Y), exactly: nil, clamping: UInt32.max, truncating: 1) + NBKAssertNumbers(from: T(x32:[~0, ~0, ~0, ~0] as Y), exactly: nil, clamping: UInt32.max, truncating: ~0) + } + + func testFromUInt32() { + NBKAssertNumbers(from: UInt32.min, default: T(words: UInt32.min.words)) + NBKAssertNumbers(from: UInt32.max, default: T(words: UInt32.max.words)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x UInt64 + //=------------------------------------------------------------------------= + + func testToUInt64() { + NBKAssertNumbers(from: T(x64:[ 1, 0, 0, 0] as X), default: UInt64( 1)) + NBKAssertNumbers(from: T(x64:[~0, 0, 0, 0] as X), default: ~UInt64( 0)) + NBKAssertNumbers(from: T(x64:[ 1, 1, 1, 1] as X), exactly: nil, clamping: UInt64.max, truncating: 1) + NBKAssertNumbers(from: T(x64:[~0, ~0, ~0, ~0] as X), exactly: nil, clamping: UInt64.max, truncating: ~0) + } + + func testFromUInt64() { + NBKAssertNumbers(from: UInt64.min, default: T(words: UInt64.min.words)) + NBKAssertNumbers(from: UInt64.max, default: T(words: UInt64.max.words)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Signitude + //=------------------------------------------------------------------------= + + func testToSignitude() { + NBKAssertNumbers(from: T(words:[ 1, 0, 0, 0] as W), default: S(words:[ 1, 0, 0, 0, 0] as W)) + NBKAssertNumbers(from: T(words:[~0, 0, 0, 0] as W), default: S(words:[~0, 0, 0, 0, 0] as W)) + NBKAssertNumbers(from: T(words:[ 1, 1, 1, 1] as W), default: S(words:[ 1, 1, 1, 1, 0] as W)) + NBKAssertNumbers(from: T(words:[~0, ~0, ~0, ~0] as W), default: S(words:[~0, ~0, ~0, ~0, 0] as W)) + } + + func testFromSignitude() { + NBKAssertNumbers(from: S(words:[ 1, 0, 0, 0] as W), default: T(words:[ 1, 0, 0, 0, 0] as W)) + NBKAssertNumbers(from: S(words:[~0, 0, 0, 0] as W), default: T(words:[~0, 0, 0, 0, 0] as W)) + NBKAssertNumbers(from: S(words:[ 1, 1, 1, 1] as W), default: T(words:[ 1, 1, 1, 1, 0] as W)) + NBKAssertNumbers(from: S(words:[~0, ~0, ~0, ~0] as W), exactly: nil, clamping: T.zero, truncating: T(UInt.max)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Magnitude + //=------------------------------------------------------------------------= + + func testToMagnitude() { + NBKAssertNumbers(from: T(words:[ 1, 0, 0, 0] as W), default: M(words:[ 1, 0, 0, 0] as W)) + NBKAssertNumbers(from: T(words:[~0, 0, 0, 0] as W), default: M(words:[~0, 0, 0, 0] as W)) + NBKAssertNumbers(from: T(words:[ 1, 1, 1, 1] as W), default: M(words:[ 1, 1, 1, 1] as W)) + NBKAssertNumbers(from: T(words:[~0, ~0, ~0, ~0] as W), default: M(words:[~0, ~0, ~0, ~0] as W)) + } + + func testFromMagnitude() { + NBKAssertNumbers(from: M(words:[ 1, 0, 0, 0] as W), default: T(words:[ 1, 0, 0, 0] as W)) + NBKAssertNumbers(from: M(words:[~0, 0, 0, 0] as W), default: T(words:[~0, 0, 0, 0] as W)) + NBKAssertNumbers(from: M(words:[ 1, 1, 1, 1] as W), default: T(words:[ 1, 1, 1, 1] as W)) + NBKAssertNumbers(from: M(words:[~0, ~0, ~0, ~0] as W), default: T(words:[~0, ~0, ~0, ~0] as W)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Float32 + //=------------------------------------------------------------------------= + + func testToFloat32() { + XCTAssertEqual(Float32(T(0)), Float32(0)) + XCTAssertEqual(Float32(T(1)), Float32(1)) + + XCTAssertEqual(Float32(T(UInt32.min)), Float32(UInt32.min)) + XCTAssertEqual(Float32(T(UInt32.max)), Float32(UInt32.max)) + } + + func testFromFloat32() { + XCTAssertEqual(T(Float32( 22.0)), 22) + XCTAssertEqual(T(Float32( 22.5)), 22) + + XCTAssertEqual(T(exactly: 22.5), nil) + XCTAssertEqual(T(exactly: -22.5), nil) + + XCTAssertEqual(T(exactly: pow(2, Float32(64 * 0 - 1))), nil) + XCTAssertEqual(T(exactly: pow(2, Float32(64 * 0 - 0))), T(x64:[1, 0, 0, 0] as X)) + XCTAssertEqual(T(exactly: pow(2, Float32(64 * 1 - 1))), T(x64:[1 << 63, 0, 0, 0] as X)) + XCTAssertEqual(T(exactly: pow(2, Float32(64 * 2 - 1))), T(x64:[0, 1 << 63, 0, 0] as X)) + XCTAssertEqual(T(exactly: pow(2, Float32(64 * 2 - 0))), nil) + } + + func testFromFloat32ValuesThatAreSpecial() { + XCTAssertNil(T(exactly: Float32.nan)) + XCTAssertNil(T(exactly: Float32.infinity)) + XCTAssertNil(T(exactly: Float32.signalingNaN)) + XCTAssertNil(T(exactly: Float32.leastNormalMagnitude)) + XCTAssertNil(T(exactly: Float32.leastNonzeroMagnitude)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Float64 + //=------------------------------------------------------------------------= + + func testToFloat64() { + XCTAssertEqual(Float64(T(0)), Float64(0)) + XCTAssertEqual(Float64(T(1)), Float64(1)) + + XCTAssertEqual(Float64(T(UInt64.min)), Float64(UInt64.min)) + XCTAssertEqual(Float64(T(UInt64.max)), Float64(UInt64.max)) + } + + func testFromFloat64() { + XCTAssertEqual(T(Float64( 22.0)), 22) + XCTAssertEqual(T(Float64( 22.5)), 22) + + XCTAssertEqual(T(exactly: 22.5), nil) + XCTAssertEqual(T(exactly: -22.5), nil) + + XCTAssertEqual(T(exactly: pow(2, Float64(64 * 0 - 1))), nil) + XCTAssertEqual(T(exactly: pow(2, Float64(64 * 0 - 0))), T(x64:[1, 0, 0, 0] as X)) + XCTAssertEqual(T(exactly: pow(2, Float64(64 * 1 - 1))), T(x64:[1 << 63, 0, 0, 0] as X)) + XCTAssertEqual(T(exactly: pow(2, Float64(64 * 2 - 1))), T(x64:[0, 1 << 63, 0, 0] as X)) + XCTAssertEqual(T(exactly: pow(2, Float64(64 * 3 - 1))), T(x64:[0, 0, 1 << 63, 0] as X)) + XCTAssertEqual(T(exactly: pow(2, Float64(64 * 4 - 1))), T(x64:[0, 0, 0, 1 << 63] as X)) + } + + func testFromFloat64ValuesThatAreSpecial() { + XCTAssertNil(T(exactly: Float64.nan)) + XCTAssertNil(T(exactly: Float64.infinity)) + XCTAssertNil(T(exactly: Float64.signalingNaN)) + XCTAssertNil(T(exactly: Float64.leastNormalMagnitude)) + XCTAssertNil(T(exactly: Float64.leastNonzeroMagnitude)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Sign & Magnitude + //=------------------------------------------------------------------------= + + func testsFromSignAndMagnitude() { + XCTAssertEqual(T(sign: .plus, magnitude: M( 1)), T( 1)) + XCTAssertEqual(T(sign: .minus, magnitude: M( 1)), nil) + } + + func testsFromSignAndMagnitudeAsPlusMinusZero() { + XCTAssertEqual(T(sign: .plus, magnitude: M( )), T( )) + XCTAssertEqual(T(sign: .minus, magnitude: M( )), T( )) + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Numbers x Assertions +//*============================================================================* + +private func NBKAssertNumbers( +from value: I, default: O, +file: StaticString = #file, line: UInt = #line) { + NBKAssertNumbers(from: value, exactly: `default`, clamping: `default`, truncating: `default`, file: file, line: line) +} + +private func NBKAssertNumbers( +from value: I, default: O, exactly: O?, +file: StaticString = #file, line: UInt = #line) { + NBKAssertNumbers(from: value, exactly: exactly, clamping: `default`, truncating: `default`, file: file, line: line) +} + +private func NBKAssertNumbers( +from value: I, default: O, clamping: O, +file: StaticString = #file, line: UInt = #line) { + NBKAssertNumbers(from: value, exactly: `default`, clamping: clamping, truncating: `default`, file: file, line: line) +} + +private func NBKAssertNumbers( +from value: I, default: O, truncating: O, +file: StaticString = #file, line: UInt = #line) { + NBKAssertNumbers(from: value, exactly: `default`, clamping: `default`, truncating: truncating, file: file, line: line) +} + +private func NBKAssertNumbers( +from value: I, exactly: O?, clamping: O, truncating: O, +file: StaticString = #file, line: UInt = #line) { + //=--------------------------------------= + if let exactly = exactly { + XCTAssertEqual(O(value), exactly, file: file, line: line) + } + //=--------------------------------------= + XCTAssertEqual(O(exactly: value), exactly, file: file, line: line) + XCTAssertEqual(O(clamping: value), clamping, file: file, line: line) + XCTAssertEqual(O(truncatingIfNeeded: value), truncating, file: file, line: line) +} + +#endif diff --git a/Tests/NBKTwosComplementKitTests/IntXL+Shifts.swift b/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Shifts.swift similarity index 100% rename from Tests/NBKTwosComplementKitTests/IntXL+Shifts.swift rename to Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Shifts.swift diff --git a/Tests/NBKTwosComplementKitTests/IntXL+Subtraction.swift b/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Subtraction.swift similarity index 100% rename from Tests/NBKTwosComplementKitTests/IntXL+Subtraction.swift rename to Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Subtraction.swift diff --git a/Tests/NBKTwosComplementKitTests/IntXL+Text.swift b/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Text.swift similarity index 100% rename from Tests/NBKTwosComplementKitTests/IntXL+Text.swift rename to Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Text.swift diff --git a/Tests/NBKTwosComplementKitTests/IntXL+Words.swift b/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Words.swift similarity index 100% rename from Tests/NBKTwosComplementKitTests/IntXL+Words.swift rename to Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Words.swift diff --git a/Tests/NBKTwosComplementKitTests/IntXL.swift b/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth.swift similarity index 100% rename from Tests/NBKTwosComplementKitTests/IntXL.swift rename to Tests/NBKTwosComplementKitTests/NBKFlexibleWidth.swift From be5be3ad13e126de39ef91460d8c3e4c93fafd95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Thu, 14 Sep 2023 16:54:03 +0200 Subject: [PATCH 067/133] No flexible in-memory 2's complement (#44). --- ...NBKTwosComplementKit-Benchmarks.xctestplan | 24 - .swiftpm/NBKTwosComplementKit.xctestplan | 32 - .swiftpm/Numberick-Benchmarks.xctestplan | 7 - .swiftpm/Numberick.xctestplan | 7 - .../xcschemes/Numberick-Benchmarks.xcscheme | 3 - .../xcshareddata/xcschemes/Numberick.xcscheme | 3 - Package.swift | 20 - .../NBKTwosComplementKit/IntXLOrUIntXL.swift | 127 -- .../IntXLOrUIntXLStorage.swift | 66 - .../NBKFlexibleWidth+Addition+Digit.swift | 115 -- .../NBKFlexibleWidth+Addition.swift | 131 -- .../NBKFlexibleWidth+Bits.swift | 66 - .../NBKFlexibleWidth+Comparisons.swift | 191 --- .../NBKFlexibleWidth+Complements.swift | 155 -- .../NBKFlexibleWidth+Data.swift | 42 - .../NBKFlexibleWidth+Division+Digit.swift | 91 -- .../NBKFlexibleWidth+Division.swift | 174 -- .../NBKFlexibleWidth+Literals.swift | 92 -- .../NBKFlexibleWidth+Logic.swift | 138 -- ...BKFlexibleWidth+Multiplication+Digit.swift | 99 -- .../NBKFlexibleWidth+Multiplication.swift | 99 -- .../NBKFlexibleWidth+Numbers.swift | 174 -- .../NBKFlexibleWidth+Shifts.swift | 394 ----- ...KFlexibleWidth+Storage+Normalization.swift | 123 -- .../NBKFlexibleWidth+Storage+Size.swift | 47 - .../NBKFlexibleWidth+Storage.swift | 141 -- .../NBKFlexibleWidth+Subtraction+Digit.swift | 138 -- .../NBKFlexibleWidth+Subtraction.swift | 158 -- .../NBKFlexibleWidth+Text.swift | 160 -- .../NBKFlexibleWidth+Update.swift | 29 - .../NBKFlexibleWidth+Words+Pointers.swift | 34 - .../NBKFlexibleWidth+Words.swift | 67 - .../NBKFlexibleWidth.swift | 132 -- .../NBKFlexibleWidth+Text.swift | 923 ++++++++++- .../NBKFlexibleWidth+Addition.swift | 142 -- .../NBKFlexibleWidth+Bits.swift | 228 --- .../NBKFlexibleWidth+Comparisons.swift | 280 ---- .../NBKFlexibleWidth+Complements.swift | 299 ---- .../NBKFlexibleWidth+Division.swift | 240 --- .../NBKFlexibleWidth+Logic.swift | 117 -- .../NBKFlexibleWidth+Multiplication.swift | 98 -- .../NBKFlexibleWidth+Numbers.swift | 816 ---------- .../NBKFlexibleWidth+Shifts.swift | 284 ---- .../NBKFlexibleWidth+Subtraction.swift | 142 -- .../NBKFlexibleWidth+Text.swift | 200 --- .../NBKFlexibleWidth+Words.swift | 72 - .../NBKFlexibleWidth.swift | 68 - .../NBKFlexibleWidth+Addition.swift | 220 --- .../NBKFlexibleWidth+Bits.swift | 212 --- .../NBKFlexibleWidth+Comparisons.swift | 593 ------- .../NBKFlexibleWidth+Complements.swift | 210 --- .../NBKFlexibleWidth+Division.swift | 371 ----- .../NBKFlexibleWidth+Literals.swift | 168 -- .../NBKFlexibleWidth+Logic.swift | 170 -- .../NBKFlexibleWidth+Multiplication.swift | 172 -- .../NBKFlexibleWidth+Numbers.swift | 573 ------- .../NBKFlexibleWidth+Shifts.swift | 324 ---- .../NBKFlexibleWidth+Subtraction.swift | 275 ---- .../NBKFlexibleWidth+Text.swift | 1432 ----------------- .../NBKFlexibleWidth+Words.swift | 175 -- .../NBKFlexibleWidth.swift | 68 - 61 files changed, 921 insertions(+), 11230 deletions(-) delete mode 100644 .swiftpm/NBKTwosComplementKit-Benchmarks.xctestplan delete mode 100644 .swiftpm/NBKTwosComplementKit.xctestplan delete mode 100644 Sources/NBKTwosComplementKit/IntXLOrUIntXL.swift delete mode 100644 Sources/NBKTwosComplementKit/IntXLOrUIntXLStorage.swift delete mode 100644 Sources/NBKTwosComplementKit/NBKFlexibleWidth+Addition+Digit.swift delete mode 100644 Sources/NBKTwosComplementKit/NBKFlexibleWidth+Addition.swift delete mode 100644 Sources/NBKTwosComplementKit/NBKFlexibleWidth+Bits.swift delete mode 100644 Sources/NBKTwosComplementKit/NBKFlexibleWidth+Comparisons.swift delete mode 100644 Sources/NBKTwosComplementKit/NBKFlexibleWidth+Complements.swift delete mode 100644 Sources/NBKTwosComplementKit/NBKFlexibleWidth+Data.swift delete mode 100644 Sources/NBKTwosComplementKit/NBKFlexibleWidth+Division+Digit.swift delete mode 100644 Sources/NBKTwosComplementKit/NBKFlexibleWidth+Division.swift delete mode 100644 Sources/NBKTwosComplementKit/NBKFlexibleWidth+Literals.swift delete mode 100644 Sources/NBKTwosComplementKit/NBKFlexibleWidth+Logic.swift delete mode 100644 Sources/NBKTwosComplementKit/NBKFlexibleWidth+Multiplication+Digit.swift delete mode 100644 Sources/NBKTwosComplementKit/NBKFlexibleWidth+Multiplication.swift delete mode 100644 Sources/NBKTwosComplementKit/NBKFlexibleWidth+Numbers.swift delete mode 100644 Sources/NBKTwosComplementKit/NBKFlexibleWidth+Shifts.swift delete mode 100644 Sources/NBKTwosComplementKit/NBKFlexibleWidth+Storage+Normalization.swift delete mode 100644 Sources/NBKTwosComplementKit/NBKFlexibleWidth+Storage+Size.swift delete mode 100644 Sources/NBKTwosComplementKit/NBKFlexibleWidth+Storage.swift delete mode 100644 Sources/NBKTwosComplementKit/NBKFlexibleWidth+Subtraction+Digit.swift delete mode 100644 Sources/NBKTwosComplementKit/NBKFlexibleWidth+Subtraction.swift delete mode 100644 Sources/NBKTwosComplementKit/NBKFlexibleWidth+Text.swift delete mode 100644 Sources/NBKTwosComplementKit/NBKFlexibleWidth+Update.swift delete mode 100644 Sources/NBKTwosComplementKit/NBKFlexibleWidth+Words+Pointers.swift delete mode 100644 Sources/NBKTwosComplementKit/NBKFlexibleWidth+Words.swift delete mode 100644 Sources/NBKTwosComplementKit/NBKFlexibleWidth.swift delete mode 100644 Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Addition.swift delete mode 100644 Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Bits.swift delete mode 100644 Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Comparisons.swift delete mode 100644 Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Complements.swift delete mode 100644 Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Division.swift delete mode 100644 Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Logic.swift delete mode 100644 Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Multiplication.swift delete mode 100644 Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Numbers.swift delete mode 100644 Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Shifts.swift delete mode 100644 Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Subtraction.swift delete mode 100644 Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Text.swift delete mode 100644 Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Words.swift delete mode 100644 Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth.swift delete mode 100644 Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Addition.swift delete mode 100644 Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Bits.swift delete mode 100644 Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Comparisons.swift delete mode 100644 Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Complements.swift delete mode 100644 Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Division.swift delete mode 100644 Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Literals.swift delete mode 100644 Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Logic.swift delete mode 100644 Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Multiplication.swift delete mode 100644 Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Numbers.swift delete mode 100644 Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Shifts.swift delete mode 100644 Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Subtraction.swift delete mode 100644 Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Text.swift delete mode 100644 Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Words.swift delete mode 100644 Tests/NBKTwosComplementKitTests/NBKFlexibleWidth.swift diff --git a/.swiftpm/NBKTwosComplementKit-Benchmarks.xctestplan b/.swiftpm/NBKTwosComplementKit-Benchmarks.xctestplan deleted file mode 100644 index e55e22be..00000000 --- a/.swiftpm/NBKTwosComplementKit-Benchmarks.xctestplan +++ /dev/null @@ -1,24 +0,0 @@ -{ - "configurations" : [ - { - "id" : "2BBD9A51-D890-4B97-AED4-B9962867DF57", - "name" : "Main", - "options" : { - - } - } - ], - "defaultOptions" : { - "codeCoverage" : false - }, - "testTargets" : [ - { - "target" : { - "containerPath" : "container:", - "identifier" : "NBKTwosComplementKitBenchmarks", - "name" : "NBKTwosComplementKitBenchmarks" - } - } - ], - "version" : 1 -} diff --git a/.swiftpm/NBKTwosComplementKit.xctestplan b/.swiftpm/NBKTwosComplementKit.xctestplan deleted file mode 100644 index 97aec1c5..00000000 --- a/.swiftpm/NBKTwosComplementKit.xctestplan +++ /dev/null @@ -1,32 +0,0 @@ -{ - "configurations" : [ - { - "id" : "6FC9897F-2BF3-4836-8372-787CE5195F87", - "name" : "Main", - "options" : { - - } - } - ], - "defaultOptions" : { - "codeCoverage" : { - "targets" : [ - { - "containerPath" : "container:", - "identifier" : "NBKTwosComplementKit", - "name" : "NBKTwosComplementKit" - } - ] - } - }, - "testTargets" : [ - { - "target" : { - "containerPath" : "container:", - "identifier" : "NBKTwosComplementKitTests", - "name" : "NBKTwosComplementKitTests" - } - } - ], - "version" : 1 -} diff --git a/.swiftpm/Numberick-Benchmarks.xctestplan b/.swiftpm/Numberick-Benchmarks.xctestplan index 40ff8ef4..b7a219a1 100644 --- a/.swiftpm/Numberick-Benchmarks.xctestplan +++ b/.swiftpm/Numberick-Benchmarks.xctestplan @@ -42,13 +42,6 @@ "identifier" : "NBKFlexibleWidthKitBenchmarks", "name" : "NBKFlexibleWidthKitBenchmarks" } - }, - { - "target" : { - "containerPath" : "container:", - "identifier" : "NBKTwosComplementKitBenchmarks", - "name" : "NBKTwosComplementKitBenchmarks" - } } ], "version" : 1 diff --git a/.swiftpm/Numberick.xctestplan b/.swiftpm/Numberick.xctestplan index 5116b0ed..74306fdc 100644 --- a/.swiftpm/Numberick.xctestplan +++ b/.swiftpm/Numberick.xctestplan @@ -50,13 +50,6 @@ "identifier" : "NBKFlexibleWidthKitTests", "name" : "NBKFlexibleWidthKitTests" } - }, - { - "target" : { - "containerPath" : "container:", - "identifier" : "NBKTwosComplementKitTests", - "name" : "NBKTwosComplementKitTests" - } } ], "version" : 1 diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/Numberick-Benchmarks.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/Numberick-Benchmarks.xcscheme index bf798a13..8cf9cef5 100644 --- a/.swiftpm/xcode/xcshareddata/xcschemes/Numberick-Benchmarks.xcscheme +++ b/.swiftpm/xcode/xcshareddata/xcschemes/Numberick-Benchmarks.xcscheme @@ -41,9 +41,6 @@ - - - - , Magnitude == UIntXL { - - //=------------------------------------------------------------------------= - // MARK: Details x Comparisons - //=------------------------------------------------------------------------= - - func compared(to other: Self, at index: Int) -> Int - - func compared(to other: Digit, at index: Int) -> Int - - //=------------------------------------------------------------------------= - // MARK: Details x Numbers - //=------------------------------------------------------------------------= - - init(digit: Digit, at index: Int) - - //=------------------------------------------------------------------------= - // MARK: Details x Addition - //=------------------------------------------------------------------------= - - @inlinable mutating func add(_ other: Self, at index: Int) - - @inlinable func adding(_ other: Self, at index: Int) -> Self - - @_disfavoredOverload @inlinable mutating func add(_ other: Digit, at index: Int) - - @_disfavoredOverload @inlinable func adding(_ other: Digit, at index: Int) -> Self - - //=------------------------------------------------------------------------= - // MARK: Details x Subtraction - //=------------------------------------------------------------------------= - - @inlinable mutating func subtract(_ other: Self, at index: Int) - - @inlinable func subtracting(_ other: Self, at index: Int) -> Self - - @_disfavoredOverload @inlinable mutating func subtract(_ other: Digit, at index: Int) - - @_disfavoredOverload @inlinable func subtracting(_ other: Digit, at index: Int) -> Self - - //=------------------------------------------------------------------------= - // MARK: Details x Shifts - //=------------------------------------------------------------------------= - - @inlinable mutating func bitshiftLeftSmart(by distance: Int) - - @inlinable func bitshiftedLeftSmart(by distance: Int) -> Self - - @inlinable mutating func bitshiftLeft(by distance: Int) - - @inlinable func bitshiftedLeft(by distance: Int) -> Self - - @inlinable mutating func bitshiftLeft(words: Int, bits: Int) - - @inlinable func bitshiftedLeft(words: Int, bits: Int) -> Self - - @inlinable mutating func bitshiftLeft(words: Int) - - @inlinable func bitshiftedLeft(words: Int) -> Self - - @inlinable mutating func bitshiftRightSmart(by distance: Int) - - @inlinable func bitshiftedRightSmart(by distance: Int) -> Self - - @inlinable mutating func bitshiftRight(by distance: Int) - - @inlinable func bitshiftedRight(by distance: Int) -> Self - - @inlinable mutating func bitshiftRight(words: Int, bits: Int) - - @inlinable func bitshiftedRight(words: Int, bits: Int) -> Self - - @inlinable mutating func bitshiftRight(words: Int) - - @inlinable func bitshiftedRight(words: Int) -> Self - - //=------------------------------------------------------------------------= - // MARK: Details x Update - //=------------------------------------------------------------------------= - - @inlinable mutating func updateZeroValue() - - @inlinable mutating func update(_ value: Digit) -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x IntXL or UIntXL x Private -//*============================================================================* - -@usableFromInline protocol PrivateIntXLOrUIntXL: IntXLOrUIntXL where Words == NBKFlexibleWidth.Words { - - typealias Elements = NBKFlexibleWidth.Elements - - associatedtype Storage: PrivateIntXLOrUIntXLStorage where Storage.Digit == Digit - - //=------------------------------------------------------------------------= - // MARK: State - //=------------------------------------------------------------------------= - - @inlinable var storage: Storage { get set } - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - @inlinable init(_ storage: Storage) - - @inlinable init(unchecked storage: Storage) - - @inlinable init(normalizing storage: Storage) -} diff --git a/Sources/NBKTwosComplementKit/IntXLOrUIntXLStorage.swift b/Sources/NBKTwosComplementKit/IntXLOrUIntXLStorage.swift deleted file mode 100644 index 6873d80e..00000000 --- a/Sources/NBKTwosComplementKit/IntXLOrUIntXLStorage.swift +++ /dev/null @@ -1,66 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Flexible Width x IntXL or UIntXL x Storage -//*============================================================================* - -@usableFromInline protocol IntXLOrUIntXLStorage: NBKBitPatternConvertible where BitPattern == UIntXL.Storage { - - associatedtype Digit: NBKCoreInteger - - //=------------------------------------------------------------------------= - // MARK: Details x Normalization - //=------------------------------------------------------------------------= - - @inlinable var isNormal: Bool { get } - - @inlinable mutating func normalize() - - @inlinable mutating func normalize(update value: Digit) - - //=------------------------------------------------------------------------= - // MARK: Details x Size - //=------------------------------------------------------------------------= - - @inlinable mutating func resize(minCount: Int) - - @inlinable mutating func resize(maxCount: Int) -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x IntXL or UIntXL x Storage x Private -//*============================================================================* - -@usableFromInline protocol PrivateIntXLOrUIntXLStorage: IntXLOrUIntXLStorage { - - typealias Elements = NBKFlexibleWidth.Elements - - //=------------------------------------------------------------------------= - // MARK: State - //=------------------------------------------------------------------------= - - /// A collection of unsigned integers. - /// - /// It must be `nonempty` at the start and end of each access. - /// - @inlinable var elements: Elements { get set } - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - @inlinable init(_ elements: Elements) - - @inlinable init(unchecked elements: Elements) - - @inlinable init(nonemptying elements: Elements) -} diff --git a/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Addition+Digit.swift b/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Addition+Digit.swift deleted file mode 100644 index ed8e2bf0..00000000 --- a/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Addition+Digit.swift +++ /dev/null @@ -1,115 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Flexible Width x Addition x Digit -//*============================================================================* - -extension IntXLOrUIntXL { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @_disfavoredOverload @inlinable public static func +=(lhs: inout Self, rhs: Digit) { - lhs.add(rhs, at: Int.zero) - } - - @_disfavoredOverload @inlinable public static func +(lhs: Self, rhs: Digit) -> Self { - lhs.adding(rhs, at: Int.zero) - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Addition x Digit x IntXL -//*============================================================================* - -extension IntXL { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @_disfavoredOverload @inlinable public mutating func add(_ other: Digit, at index: Int) { - if other.isZero { return } - //=--------------------------------------= - let lhsIsLessThanZero = self .isLessThanZero - let rhsIsLessThanZero = other.isLessThanZero - let lhsSign = UInt(repeating: lhsIsLessThanZero) - let rhsSign = UInt(repeating: rhsIsLessThanZero) - //=--------------------------------------= - self.storage.resize(minCount: index + 1) - var carry = self.storage.elements[index].addReportingOverflow(UInt(bitPattern: other)) - var index = self.storage.elements.index(after: index) - //=-------------------------------------= - if carry != rhsIsLessThanZero { - let predicate = carry - let increment = UInt(bitPattern: carry ? 1 : -1) - - while index != self.storage.elements.endIndex && carry == predicate { - carry = self.storage.elements[index].addReportingOverflow(increment) - self.storage.elements.formIndex(after: &index) - } - } - //=--------------------------------------= - self.storage.normalize(appending: lhsSign &+ rhsSign &+ UInt(bit: carry)) - } - - @_disfavoredOverload @inlinable public func adding(_ other: Digit, at index: Int) -> Self { - var result = self - result.add(other, at: index) - return result as Self - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Addition x Digit x UIntXL -//*============================================================================* - -extension UIntXL { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @_disfavoredOverload @inlinable public mutating func add(_ other: UInt, at index: Int) { - defer { - Swift.assert(self.storage.isNormal) - } - //=--------------------------------------= - if other.isZero { return } - //=--------------------------------------= - self.storage.resize(minCount: index + 1) - let overflow = self.storage.add(other, plus: false, at: index) - if overflow { self.storage.append(1 as UInt) } - } - - @_disfavoredOverload @inlinable public func adding(_ other: UInt, at index: Int) -> Self { - var result = self - result.add(other, at: index) - return result as Self - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Addition x Digit x UIntXL x Storage -//*============================================================================* - -extension UIntXL.Storage { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @_disfavoredOverload @inlinable mutating func add(_ other: UInt, plus carry: Bool, at index: Int) -> Bool { - NBK.incrementSufficientUnsignedInteger(&self.elements, by: other, plus: carry, at: index).overflow - } -} diff --git a/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Addition.swift b/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Addition.swift deleted file mode 100644 index 6122feea..00000000 --- a/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Addition.swift +++ /dev/null @@ -1,131 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Flexible Width x Addition -//*============================================================================* - -extension IntXLOrUIntXL { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable public static func +=(lhs: inout Self, rhs: Self) { - lhs.add(rhs, at: Int.zero) - } - - @inlinable public static func +(lhs: Self, rhs: Self) -> Self { - lhs.adding(rhs, at: Int.zero) - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Addition x IntXL -//*============================================================================* - -extension IntXL { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable public mutating func add(_ other: Self, at index: Int) { - //=--------------------------------------= - if other.isZero { return } - //=--------------------------------------= - let lhsIsLessThanZero = self .isLessThanZero - let rhsIsLessThanZero = other.isLessThanZero - let lhsSign = UInt(repeating: lhsIsLessThanZero) - let rhsSign = UInt(repeating: rhsIsLessThanZero) - //=--------------------------------------= - self.storage.resize(minCount: other.storage.elements.count + index) - //=--------------------------------------= - var carry = false - var lhsIndex = index - var rhsIndex = other.storage.elements.startIndex - //=----------------------------------= - while rhsIndex < other.storage.elements.endIndex { - var lhsElement = self .storage.elements[lhsIndex] - let rhsElement = other.storage.elements[rhsIndex] - - let a = lhsElement.addReportingOverflow(rhsElement) - let b = lhsElement.addReportingOverflow(UInt(bit: carry)) - carry = a || b - - self .storage.elements[lhsIndex] = lhsElement - self .storage.elements.formIndex(after: &lhsIndex) - other.storage.elements.formIndex(after: &rhsIndex) - } - //=--------------------------------------= - if carry != rhsIsLessThanZero { - let predicate = carry - let increment = UInt(bitPattern: carry ? 1 : -1) - - while lhsIndex < self.storage.elements.endIndex && carry == predicate { - carry = self.storage.elements[lhsIndex].addReportingOverflow(increment) - self.storage.elements.formIndex(after: &lhsIndex) - } - } - //=--------------------------------------= - self.storage.normalize(appending: lhsSign &+ rhsSign &+ UInt(bit: carry)) - } - - @inlinable public func adding(_ other: Self, at index: Int) -> Self { - var result = self - result.add(other, at: index) - return result as Self - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Addition x UIntXL -//*============================================================================* - -extension UIntXL { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable public mutating func add(_ other: Self, at index: Int) { - defer { - Swift.assert(self.storage.isNormal) - } - //=--------------------------------------= - if other.isZero { return } - //=--------------------------------------= - self.storage.resize(minCount: other.storage.elements.count + index) - let overflow = self.storage.add(other.storage, plus: false, at: index) - if overflow { self.storage.append(1 as UInt) } - } - - @inlinable public func adding(_ other: Self, at index: Int) -> Self { - var result = self - result.add(other, at: index) - return result as Self - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Addition x UIntXL x Storage -//*============================================================================* - -extension UIntXL.Storage { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable mutating func add(_ other: Self, plus carry: Bool, at index: Int) -> Bool { - NBK.incrementSufficientUnsignedInteger(&self.elements, by: other.elements, plus: carry, at: index).overflow - } -} diff --git a/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Bits.swift b/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Bits.swift deleted file mode 100644 index 25a706aa..00000000 --- a/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Bits.swift +++ /dev/null @@ -1,66 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Flexible Width x Bits -//*============================================================================* - -extension PrivateIntXLOrUIntXL { - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - @inlinable public init(bit: Bool) { - self.init(digit: Digit(bit: bit)) - } - - //=------------------------------------------------------------------------= - // MARK: Utilities - //=------------------------------------------------------------------------= - - @inlinable public var bitWidth: Int { - self.storage.elements.count * UInt.bitWidth - } - - @inlinable public var nonzeroBitCount: Int { - self.withUnsafeBufferPointer(NBK.nonzeroBitCount(of:)) - } - - @inlinable public var leadingZeroBitCount: Int { - self.storage.last.leadingZeroBitCount - } - - @inlinable public var trailingZeroBitCount: Int { - self.withUnsafeBufferPointer(NBK.trailingZeroBitCount(of:)) - } - - @inlinable public var mostSignificantBit: Bool { - self.storage.last.mostSignificantBit - } - - @inlinable public var leastSignificantBit: Bool { - self.storage.first.leastSignificantBit - } - - //=------------------------------------------------------------------------= - // MARK: Utilities x Private - //=------------------------------------------------------------------------= - - @inlinable func leadingBitCount(_ bit: Bool) -> Int { - var last = self.storage.last - if bit { - last.formOnesComplement() - } - - return last.leadingZeroBitCount - } -} diff --git a/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Comparisons.swift b/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Comparisons.swift deleted file mode 100644 index 9142e6d5..00000000 --- a/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Comparisons.swift +++ /dev/null @@ -1,191 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Flexible Width x Comparisons x IntXL -//*============================================================================* - -extension IntXL { - - //=------------------------------------------------------------------------= - // MARK: Accessors - //=------------------------------------------------------------------------= - - @inlinable public var isZero: Bool { - self.storage.elements.count == 1 && self.storage.first.isZero - } - - @inlinable public var isLessThanZero: Bool { - self.storage.last.mostSignificantBit - } - - @inlinable public var isMoreThanZero: Bool { - !self.isLessThanZero && !self.isZero - } - - @inlinable public var isPowerOf2: Bool { - !self.isLessThanZero && self.withUnsafeBufferPointer({ NBK.nonzeroBitCount(of: $0, equals: 1) }) - } - - @inlinable public func signum() -> Int { - self.isLessThanZero ? -1 : self.isZero ? 0 : 1 - } - - //=------------------------------------------------------------------------= - // MARK: Utilities - //=------------------------------------------------------------------------= - - @inlinable public func hash(into hasher: inout Hasher) { - hasher.combine(self.storage.elements) - } - - //=------------------------------------------------------------------------= - // MARK: Utilities - //=------------------------------------------------------------------------= - - @inlinable public static func ==(lhs: Self, rhs: Self) -> Bool { - lhs.compared(to: rhs).isZero - } - - @inlinable public static func <(lhs: Self, rhs: Self) -> Bool { - lhs.compared(to: rhs) == -1 - } - - @inlinable public func compared(to other: Self) -> Int { - self .withUnsafeBufferPointer { lhs in - other.withUnsafeBufferPointer { rhs in - NBK.compareStrictSignedInteger(lhs, to: rhs) - }} - } - - @inlinable public func compared(to other: Self, at index: Int) -> Int { - self .withUnsafeBufferPointer { lhs in - other.withUnsafeBufferPointer { rhs in - NBK.compareStrictSignedInteger(lhs, to: rhs, at: index) - }} - } - - @_disfavoredOverload @inlinable public func compared(to other: Digit) -> Int { - self.withUnsafeBufferPointer { lhs in - NBK .withUnsafeWords(of: other) { rhs in - NBK.compareStrictSignedInteger(lhs, to: rhs) - }} - } - - @_disfavoredOverload @inlinable public func compared(to other: Digit, at index: Int) -> Int { - self.withUnsafeBufferPointer { lhs in - NBK .withUnsafeWords(of: other) { rhs in - NBK.compareStrictSignedInteger(lhs, to: rhs, at: index) - }} - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Comparisons x UIntXL -//*============================================================================* - -extension UIntXL { - - //=------------------------------------------------------------------------= - // MARK: Accessors - //=------------------------------------------------------------------------= - - @inlinable public var isZero: Bool { - self.storage.elements.count == 1 && self.storage.first.isZero - } - - @inlinable public var isLessThanZero: Bool { - false - } - - @inlinable public var isMoreThanZero: Bool { - !self.isZero - } - - @inlinable public var isPowerOf2: Bool { - self.withUnsafeBufferPointer({ NBK.nonzeroBitCount(of: $0, equals: 1) }) - } - - @inlinable public func signum() -> Int { - Int(bit: !self.isZero) - } - - //=------------------------------------------------------------------------= - // MARK: Utilities - //=------------------------------------------------------------------------= - - @inlinable public func hash(into hasher: inout Hasher) { - hasher.combine(self.storage.elements) - } - - //=------------------------------------------------------------------------= - // MARK: Utilities - //=------------------------------------------------------------------------= - - @inlinable public static func ==(lhs: Self, rhs: Self) -> Bool { - lhs.compared(to: rhs).isZero - } - - @inlinable public static func <(lhs: Self, rhs: Self) -> Bool { - lhs.compared(to: rhs) == -1 - } - - @inlinable public func compared(to other: Self) -> Int { - self .withUnsafeBufferPointer { lhs in - other.withUnsafeBufferPointer { rhs in - NBK.compareLenientUnsignedInteger(lhs, to: rhs) - }} - } - - @inlinable public func compared(to other: Self, at index: Int) -> Int { - self .withUnsafeBufferPointer { lhs in - other.withUnsafeBufferPointer { rhs in - NBK.compareLenientUnsignedInteger(lhs, to: rhs, at: index) - }} - } - - @_disfavoredOverload @inlinable public func compared(to other: Digit) -> Int { - self.withUnsafeBufferPointer { lhs in - NBK .withUnsafeWords(of: other) { rhs in - NBK.compareLenientUnsignedInteger(lhs, to: rhs) - }} - } - - @_disfavoredOverload @inlinable public func compared(to other: Digit, at index: Int) -> Int { - self.withUnsafeBufferPointer { lhs in - NBK .withUnsafeWords(of: other) { rhs in - NBK.compareLenientUnsignedInteger(lhs, to: rhs, at: index) - }} - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Comparisons x Storage -//*============================================================================* - -extension PrivateIntXLOrUIntXLStorage { - - //=------------------------------------------------------------------------= - // MARK: Accessors - //=------------------------------------------------------------------------= - - @inlinable static var isSigned: Bool { - Digit.isSigned - } - - //=------------------------------------------------------------------------= - // MARK: Accessors - //=------------------------------------------------------------------------= - - @inlinable public var isLessThanZero: Bool { - Self.isSigned && self.last.mostSignificantBit - } -} diff --git a/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Complements.swift b/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Complements.swift deleted file mode 100644 index 897d6829..00000000 --- a/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Complements.swift +++ /dev/null @@ -1,155 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Flexible Width x Complements -//*============================================================================* - -extension PrivateIntXLOrUIntXL { - - //=------------------------------------------------------------------------= - // MARK: Details x One's Complement - //=------------------------------------------------------------------------= - - @inlinable public mutating func formOnesComplement() { - self.storage.formOnesComplement() - - if !Self.isSigned { - self.storage.normalize() - } - } - - @inlinable public func onesComplement() -> Self { - Self(normalizing: self.storage.onesComplement()) - } - - //=------------------------------------------------------------------------= - // MARK: Details x Two's Complement - //=------------------------------------------------------------------------= - - @inlinable public mutating func formTwosComplement() { - defer{ self.storage.normalize() } - return self.storage.formTwosComplement() - } - - @inlinable public func twosComplement() -> Self { - var result = self - result.formTwosComplement() - return result as Self - } - - @inlinable public mutating func formTwosComplementReportingOverflow() -> Bool { - defer{ self.storage.normalize() } - return self.storage.formTwosComplementReportingOverflow() - } - - @inlinable public func twosComplementReportingOverflow() -> PVO { - var partialValue = self - let overflow = partialValue.formTwosComplementReportingOverflow() - return PVO(partialValue, overflow) - } - - @inlinable public mutating func formTwosComplementSubsequence(_ carry: Bool) -> Bool { - defer{ self.storage.normalize() } - return self.storage.formTwosComplementSubsequence(carry) - } - - @inlinable public func twosComplementSubsequence(_ carry: Bool) -> PVO { - var partialValue = self - let overflow = partialValue.formTwosComplementSubsequence(carry) - return PVO(partialValue, overflow) - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Complements x IntXL -//*============================================================================* - -extension IntXL { - - //=------------------------------------------------------------------------= - // MARK: Details x Magnitude - //=------------------------------------------------------------------------= - - @inlinable public var magnitude: Magnitude { - let isLessThanZero = self.isLessThanZero - var storage = Magnitude.Storage(bitPattern: self.storage) - if isLessThanZero { - storage.formTwosComplement() - } - - return Magnitude(normalizing: storage) - } - - //=------------------------------------------------------------------------= - // MARK: Details x Additive Inverse - //=------------------------------------------------------------------------= - - @inlinable public mutating func negateReportingOverflow() -> Bool { - let isTwosComplementMinValue = self.storage.formTwosComplementReportingOverflow() - if isTwosComplementMinValue { - self.storage.append(0 as UInt) - } else { - self.storage.normalize() - } - - return false as Bool - } - - @inlinable public func negatedReportingOverflow() -> PVO { - var partialValue = self - let overflow = partialValue.negateReportingOverflow() - return PVO(partialValue, overflow) - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Complements x Storage -//*============================================================================* - -extension PrivateIntXLOrUIntXLStorage { - - //=------------------------------------------------------------------------= - // MARK: Details x One's Complement - //=------------------------------------------------------------------------= - - @inlinable mutating func formOnesComplement() { - for index in self.elements.indices { - self.elements[index].formOnesComplement() - } - } - - @inlinable func onesComplement() -> Self { - Self(unchecked: Elements(self.elements.lazy.map(~))) - } - - //=------------------------------------------------------------------------= - // MARK: Details x Two's Complement - //=------------------------------------------------------------------------= - - @inlinable mutating func formTwosComplement() { - _ = self.formTwosComplementSubsequence(true) - } - - @inlinable mutating func formTwosComplementReportingOverflow() -> Bool { - self.formTwosComplementSubsequence(true) - } - - @inlinable mutating func formTwosComplementSubsequence(_ carry: Bool) -> Bool { - var carry = carry - - for index in self.elements.indices.dropLast() { - carry = self.elements[index].formTwosComplementSubsequence(carry) - } - - return self.tail.formTwosComplementSubsequence(carry) - } -} diff --git a/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Data.swift b/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Data.swift deleted file mode 100644 index b4e4f79c..00000000 --- a/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Data.swift +++ /dev/null @@ -1,42 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Flexible Width x Data -//*============================================================================* - -extension PrivateIntXLOrUIntXL { - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - /// Creates a new instance with unsafe access to its uninitialized memory. - @inlinable static func uninitialized(count: Int, body: (inout NBK.UnsafeMutableWords) -> Void) -> Self { - Self(normalizing: Storage.uninitialized(count: count, body: body)) - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Data x Storage -//*============================================================================* - -extension PrivateIntXLOrUIntXLStorage { - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - /// Creates a new instance with unsafe access to its uninitialized memory. - @inlinable static func uninitialized(count: Int, body: (inout NBK.UnsafeMutableWords) -> Void) -> Self { - Self(Elements(unsafeUninitializedCapacity: count) { body(&$0); $1 = count }) - } -} diff --git a/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Division+Digit.swift b/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Division+Digit.swift deleted file mode 100644 index 1f3c0aa3..00000000 --- a/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Division+Digit.swift +++ /dev/null @@ -1,91 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Flexible Width x Division x Digit -//*============================================================================* - -extension IntXLOrUIntXL { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @_disfavoredOverload @inlinable public mutating func divideReportingOverflow(by other: Digit) -> Bool { - let pvo: PVO = self.dividedReportingOverflow(by: other) - self = pvo.partialValue - return pvo.overflow as Bool - } - - @_disfavoredOverload @inlinable public func dividedReportingOverflow(by other: Digit) -> PVO { - let qro: PVO> = self.quotientAndRemainderReportingOverflow(dividingBy: other) - return PVO(qro.partialValue.quotient, qro.overflow) - } - - @_disfavoredOverload @inlinable public mutating func formRemainderReportingOverflow(dividingBy other: Digit) -> Bool { - let pvo: PVO = self.remainderReportingOverflow(dividingBy: other) - self = Self(digit: pvo.partialValue) - return pvo.overflow as Bool - } - - @_disfavoredOverload @inlinable public func remainderReportingOverflow(dividingBy other: Digit) -> PVO { - let qro: PVO> = self.quotientAndRemainderReportingOverflow(dividingBy: other) - return PVO(qro.partialValue.remainder, qro.overflow) - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Division x Digit x IntXL -//*============================================================================* - -extension IntXL { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @_disfavoredOverload @inlinable public func quotientAndRemainderReportingOverflow(dividingBy other: Digit) -> PVO> { - let lhsSign = FloatingPointSign(self .isLessThanZero) - let rhsSign = FloatingPointSign(other.isLessThanZero) - - let qro: PVO> = self.magnitude.quotientAndRemainderReportingOverflow(dividingBy: other.magnitude) - - let quotient = Self(sign: rhsSign ^ lhsSign, magnitude: qro.partialValue.quotient ) - let remainder = Self.Digit.init(sign: lhsSign, magnitude: qro.partialValue.remainder)! - return PVO(QR(quotient, remainder), qro.overflow) - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Division x Digit x UIntXL -//*============================================================================* - -extension UIntXL { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @_disfavoredOverload @inlinable public func quotientAndRemainderReportingOverflow(dividingBy other: Digit) -> PVO> { - var quotient = self - let remainder = quotient.formQuotientWithRemainderReportingOverflow(dividingBy: other) - return PVO(QR(quotient, remainder.partialValue), remainder.overflow) - } - - //=------------------------------------------------------------------------= - // MARK: Transformations x Private - //=------------------------------------------------------------------------= - - @_disfavoredOverload @inlinable public mutating func formQuotientWithRemainderReportingOverflow(dividingBy other: Digit) -> PVO { - defer{ self.storage.normalize() } - return NBK.formQuotientWithRemainderReportingOverflowAsLenientUnsignedInteger(of: &self.storage.elements, dividingBy: other) - } -} diff --git a/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Division.swift b/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Division.swift deleted file mode 100644 index 879663c0..00000000 --- a/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Division.swift +++ /dev/null @@ -1,174 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Flexible Width x Division -//*============================================================================* - -extension IntXLOrUIntXL { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable public mutating func divideReportingOverflow(by other: Self) -> Bool { - let pvo: PVO = self.dividedReportingOverflow(by: other) - self = pvo.partialValue - return pvo.overflow as Bool - } - - @inlinable public func dividedReportingOverflow(by other: Self) -> PVO { - let qro: PVO> = self.quotientAndRemainderReportingOverflow(dividingBy: other) - return PVO(qro.partialValue.quotient, qro.overflow) - } - - @inlinable public mutating func formRemainderReportingOverflow(dividingBy other: Self) -> Bool { - let pvo: PVO = self.remainderReportingOverflow(dividingBy: other) - self = pvo.partialValue - return pvo.overflow as Bool - } - - @inlinable public func remainderReportingOverflow(dividingBy other: Self) -> PVO { - let qro: PVO> = self.quotientAndRemainderReportingOverflow(dividingBy: other) - return PVO(qro.partialValue.remainder, qro.overflow) - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Division x IntXL -//*============================================================================* - -extension IntXL { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable public func quotientAndRemainderReportingOverflow(dividingBy other: Self) -> PVO> { - let lhsSign = FloatingPointSign(self .isLessThanZero) - let rhsSign = FloatingPointSign(other.isLessThanZero) - - let qro: PVO> = self.magnitude.quotientAndRemainderReportingOverflow(dividingBy: other.magnitude) - - let quotient = Self(sign: rhsSign ^ lhsSign, magnitude: qro.partialValue.quotient ) - let remainder = Self(sign: /*---*/ lhsSign, magnitude: qro.partialValue.remainder) - return PVO(QR(quotient, remainder), qro.overflow) - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Division x UIntXL -//*============================================================================* - -extension UIntXL { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable public func quotientAndRemainderReportingOverflow(dividingBy other: Self) -> PVO> { - self.quotientAndRemainderReportingOverflowAsNormal(dividingBy: other) - } -} - -//=----------------------------------------------------------------------------= -// MARK: + Normal -//=----------------------------------------------------------------------------= - -extension UIntXL { - - //=------------------------------------------------------------------------= - // MARK: Transformations x Private - //=------------------------------------------------------------------------= - - @inlinable func quotientAndRemainderReportingOverflowAsNormal(dividingBy other: Self) -> PVO> { - var (remainder) = self - let (quotient, overflow) = remainder.formRemainderWithQuotientReportingOverflowAsNormal(dividingBy: other) - return PVO(QR(quotient, remainder), overflow) - } - - @inlinable mutating func formRemainderWithQuotientReportingOverflowAsNormal(dividingBy other: Self) -> PVO { - //=--------------------------------------= - // divisor is zero - //=--------------------------------------= - if other.isZero { - return PVO(self, true) - } - //=--------------------------------------= - // divisor is one word - //=--------------------------------------= - if other.storage.elements.count == 1 { - let qr = self.quotientAndRemainder(dividingBy: other.storage.elements.first!) - self.update(qr.remainder) - return PVO(qr.quotient, false) - } - //=--------------------------------------= - // divisor is greater than or equal - //=--------------------------------------= - let comparison = other.compared(to: self) - if comparison >= 0 { - if comparison.isZero { - self.updateZeroValue() - return PVO(001, false) - } else { - return PVO(000, false) - } - } - //=--------------------------------------= - // shift to clamp approximation - //=--------------------------------------= - var divisor = other.storage - let shift = divisor.elements.last!.leadingZeroBitCount as Int - divisor.bitshiftLeft(words: Int.zero, bits: shift) - let divisorLast0 = divisor.elements[divisor.elements.endIndex - 1] as UInt - assert(divisorLast0.mostSignificantBit) - - var remainderIndex = self.storage.elements.endIndex - self.storage.append(0) - self.storage.bitshiftLeft(words: Int.zero, bits: shift) - //=--------------------------------------= - // division: approximate quotient digits - //=--------------------------------------= - var quotientIndex = remainderIndex - divisor.elements.endIndex as Int - var quotient = Storage.uninitialized(count: quotientIndex + 1) { quotient in - loop: repeat { - let remainderLast0 = self.storage.elements[remainderIndex] - self.storage.elements.formIndex(before: &remainderIndex) - let remainderLast1 = self.storage.elements[remainderIndex] - //=------------------------------= - var digit: UInt - if divisorLast0 == remainderLast0 { - digit = UInt.max - } else { - digit = divisorLast0.dividingFullWidth(HL(remainderLast0, remainderLast1)).quotient - } - //=------------------------------= - if !digit.isZero { - var overflow = self.storage.subtract(divisor, times: digit, plus: UInt.zero, plus: false, at: quotientIndex) - decrement: while overflow { - _ = digit.subtractReportingOverflow(1 as UInt) - overflow = !self.storage.add(divisor, plus: false, at: quotientIndex) - } - } - //=------------------------------= - quotient[quotientIndex] = digit - quotient.formIndex(before: "ientIndex) - } while quotientIndex >= quotient.startIndex - } - //=--------------------------------------= - // undo shift before division - //=--------------------------------------= - quotient.normalize() - self.storage.bitshiftRight(words: Int.zero, bits: shift) - self.storage.normalize() - return PVO(Self(unchecked: quotient), false) - } -} diff --git a/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Literals.swift b/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Literals.swift deleted file mode 100644 index b7b585f5..00000000 --- a/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Literals.swift +++ /dev/null @@ -1,92 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Flexible Width x Literals -//*============================================================================* - -extension PrivateIntXLOrUIntXL { - - //=-------------------------------------------------------------------------= - // MARK: Details x Integer Literal Type - //=-------------------------------------------------------------------------= - - #if SBI && swift(>=5.8) - - @inlinable public init(integerLiteral source: StaticBigInt) { - if let value = Self(exactlyIntegerLiteral: source) { self = value } else { - preconditionFailure("\(Self.description) cannot represent \(source)") - } - } - - @inlinable public init?(exactlyIntegerLiteral source: StaticBigInt) { - guard Self.isSigned || source.signum() >= 0 as Int else { return nil } - //=--------------------------------------= - let bitWidth = Swift.max(1, source.bitWidth - Int(bit: !Self.isSigned)) - let major = NBK .quotientDividingByBitWidthAssumingIsAtLeastZero(bitWidth) - let minor = NBK.remainderDividingByBitWidthAssumingIsAtLeastZero(bitWidth) - let count = major &+ Int(bit: minor.isMoreThanZero) - //=--------------------------------------= - self = Self.uninitialized(count: count) { words in - for index in words.indices { - words.baseAddress!.advanced(by: index).initialize(to: source[index]) - } - } - } - - #else - - @inlinable public init(integerLiteral source: Digit) { - self.init(digit: source) - } - - #endif - - //=------------------------------------------------------------------------= - // MARK: Details x String Literal Type - //=------------------------------------------------------------------------= - - /// Creates a new instance from the given string literal. - /// - /// The string literal may contain a plus or minus sign (+ or -), followed by - /// an optional radix indicator (0b, 0o or 0x), then one or more numeric digits - /// (0-9) or letters (a-z or A-Z). If the string literal uses an invalid format, - /// or its value cannot be represented, a runtime error may occur. - /// - /// ``` - /// ┌───────── → ─────────────┐ - /// │ literal │ self │ - /// ├───────── → ─────────────┤ - /// │ "123" │ Int256( 123) │ - /// │ "+0x123" │ Int256( 291) │ - /// │ "-0x123" │ Int256(-291) │ - /// │ "~OX123" │ error │ - /// └───────── → ─────────────┘ - /// ``` - /// - /// - Note: The decoding strategy is case insensitive. - /// - @inlinable public init(stringLiteral source: StaticString) { - if let value = Self(exactlyStringLiteral: source) { self = value } else { - preconditionFailure("\(Self.description) cannot represent \(source)") - } - } - - @inlinable init?(exactlyStringLiteral source: StaticString) { - if let value: Self = source.withUTF8Buffer({ utf8 in - let components = NBK.makeIntegerComponentsByDecodingRadix(utf8: utf8) - let radix = NBK.AnyRadixSolution(components.radix) - let digits = NBK.UnsafeUTF8(rebasing: components.body ) - guard let magnitude = Magnitude(digits: digits, radix: radix) else { return nil } - return Self(sign: components.sign, magnitude: magnitude) - }){ self = value } else { return nil } - } -} diff --git a/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Logic.swift b/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Logic.swift deleted file mode 100644 index e60f5eb5..00000000 --- a/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Logic.swift +++ /dev/null @@ -1,138 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Flexible Width x Logic -//*============================================================================* - -extension IntXLOrUIntXL { - - //=------------------------------------------------------------------------= - // MARK: Transformations x NOT - //=------------------------------------------------------------------------= - - @inlinable public static prefix func ~(x: Self) -> Self { - x.onesComplement() - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Logic x IntXL -//*============================================================================* - -extension IntXL { - - //=------------------------------------------------------------------------= - // MARK: Transformations x AND - //=------------------------------------------------------------------------= - - @inlinable public static func &=(lhs: inout Self, rhs: Self) { - lhs.storage.upsizeThenFormInIntersection(extending: rhs.storage, each: &) - lhs.storage.normalize() - } - - //=------------------------------------------------------------------------= - // MARK: Transformations x OR - //=------------------------------------------------------------------------= - - @inlinable public static func |=(lhs: inout Self, rhs: Self) { - lhs.storage.upsizeThenFormInIntersection(extending: rhs.storage, each: |) - lhs.storage.normalize() - } - - //=------------------------------------------------------------------------= - // MARK: Transformations x XOR - //=------------------------------------------------------------------------= - - @inlinable public static func ^=(lhs: inout Self, rhs: Self) { - lhs.storage.upsizeThenFormInIntersection(extending: rhs.storage, each: ^) - lhs.storage.normalize() - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Logic x UIntXL -//*============================================================================* - -extension UIntXL { - - //=------------------------------------------------------------------------= - // MARK: Transformations x AND - //=------------------------------------------------------------------------= - - @inlinable public static func &=(lhs: inout Self, rhs: Self) { - lhs.storage.downsizeThenFormInIntersection(with: rhs.storage, each: &) - lhs.storage.normalize() - } - - //=------------------------------------------------------------------------= - // MARK: Transformations x OR - //=------------------------------------------------------------------------= - - @inlinable public static func |=(lhs: inout Self, rhs: Self) { - lhs.storage.upsizeThenFormInIntersection(with: rhs.storage, each: |) - Swift.assert(lhs.storage.isNormal) - } - - //=------------------------------------------------------------------------= - // MARK: Transformations x XOR - //=------------------------------------------------------------------------= - - @inlinable public static func ^=(lhs: inout Self, rhs: Self) { - lhs.storage.upsizeThenFormInIntersection(with: rhs.storage, each: ^) - Swift.assert(lhs.storage.isNormal) - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Logic x Storage -//*============================================================================* - -extension PrivateIntXLOrUIntXLStorage { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable mutating func downsizeThenFormInIntersection(with other: Self, each element: (UInt, UInt) -> UInt) { - self.resize(maxCount: other.elements.count) - self.elements.withUnsafeMutableBufferPointer { lhs in - other.elements.withUnsafeBufferPointer { rhs in - for index in lhs.indices { - lhs[index] = element(lhs[index], rhs[index]) - } - } - } - } - - @inlinable mutating func upsizeThenFormInIntersection(with other: Self, each element: (UInt, UInt) -> UInt) { - self.resize(minCount: other.elements.count) - self.elements.withUnsafeMutableBufferPointer { lhs in - other.elements.withUnsafeBufferPointer { rhs in - for index in rhs.indices { - lhs[index] = element(lhs[index], rhs[index]) - } - } - } - } - - @inlinable mutating func upsizeThenFormInIntersection(extending other: Self, each element: (UInt, UInt) -> UInt) { - self.resize(minCount: other.elements.count) - self.elements.withUnsafeMutableBufferPointer { lhs in - other.elements.withUnsafeBufferPointer { rhs in - let rhsSign = UInt(repeating: Self.isSigned && rhs.last!.mostSignificantBit) - for index in lhs.indices { - lhs[index] = element(lhs[index], index < rhs.endIndex ? rhs[index] : rhsSign) - } - } - } - } -} diff --git a/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Multiplication+Digit.swift b/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Multiplication+Digit.swift deleted file mode 100644 index 2fc78880..00000000 --- a/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Multiplication+Digit.swift +++ /dev/null @@ -1,99 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Flexible Width x Multiplication x Digit x IntXL -//*============================================================================* - -extension IntXL { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @_disfavoredOverload @inlinable public static func *=(lhs: inout Self, rhs: Digit) { - lhs = lhs * rhs - } - - @_disfavoredOverload @inlinable public static func *(lhs: Self, rhs: Digit) -> Self { - let lhsIsLessThanZero: Bool = lhs.isLessThanZero - let rhsIsLessThanZero: Bool = rhs.isLessThanZero - var minus = lhsIsLessThanZero != rhsIsLessThanZero - //=--------------------------------------= - var product = lhs.magnitude * rhs.magnitude - //=--------------------------------------= - if minus { - minus = product.storage.formTwosComplementSubsequence(minus) - } - //=--------------------------------------= - return Self(normalizing: Storage(bitPattern: product.storage)) - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Multiplication x Digit x UIntXL -//*============================================================================* - -extension UIntXL { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @_disfavoredOverload @inlinable public static func *=(lhs: inout Self, rhs: Digit) { - lhs.multiply(by: rhs, add: 0 as Digit) - } - - @_disfavoredOverload @inlinable public static func *(lhs: Self, rhs: Digit) -> Self { - lhs.multiplied(by: rhs, adding: 0 as Digit) - } - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @_disfavoredOverload @inlinable public mutating func multiply(by multiplicand: Digit, add addend: Digit) { - defer { - Swift.assert(self.storage.isNormal) - } - //=--------------------------------------= - if multiplicand.isZero { - return self.update(addend) - } - //=--------------------------------------= - self.storage.reserveCapacity(self.storage.elements.count + 1) - let overflow = self.storage.multiply(by: multiplicand, add: addend) - if !overflow.isZero { - self.storage.append(overflow) - } - } - - @_disfavoredOverload @inlinable public func multiplied(by multiplicand: Digit, adding addend: Digit) -> Self { - var result = self - result.multiply(by: multiplicand, add: addend) - return result as Self - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Multiplication x Digit x UIntXL x Storage -//*============================================================================* - -extension UIntXL.Storage { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @_disfavoredOverload @inlinable mutating func multiply(by other: UInt, add addend: UInt) -> UInt { - NBK.multiplyFullWidthLenientUnsignedInteger(&self.elements, by: other, add: addend) - } -} diff --git a/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Multiplication.swift b/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Multiplication.swift deleted file mode 100644 index d62e5136..00000000 --- a/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Multiplication.swift +++ /dev/null @@ -1,99 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Flexible Width x Multiplication x IntXL -//*============================================================================* - -extension IntXL { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable public static func *=(lhs: inout Self, rhs: Self) { - lhs = lhs * rhs - } - - @inlinable public static func *(lhs: Self, rhs: Self) -> Self { - let lhsIsLessThanZero: Bool = lhs.isLessThanZero - let rhsIsLessThanZero: Bool = rhs.isLessThanZero - var minus = lhsIsLessThanZero != rhsIsLessThanZero - //=--------------------------------------= - var product = lhs.magnitude * rhs.magnitude - //=--------------------------------------= - if minus { - minus = product.storage.formTwosComplementSubsequence(minus) - } - //=--------------------------------------= - return Self(normalizing: Storage(bitPattern: product.storage)) - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Multiplication x UIntXL -//*============================================================================* - -extension UIntXL { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable public static func *=(lhs: inout Self, rhs: Self) { - lhs = lhs * rhs - } - - @inlinable public static func *(lhs: Self, rhs: Self) -> Self { - Self(normalizing: lhs.storage.multipliedFullWidth(by: rhs.storage)) - } -} - -//*============================================================================* -// MARK: * NBK x Resizable Width x Multiplication x UIntXL x Storage -//*============================================================================* - -extension UIntXL.Storage { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable func multipliedFullWidth(by multiplicand: Self) -> Self { - self.multipliedFullWidthByNaiveMethod(by: multiplicand, adding: UInt.zero) - } - - @inlinable func multipliedFullWidthByNaiveMethod(by multiplicand: Self, adding addend: UInt) -> Self { - Self.uninitialized(count: self.elements.count + multiplicand.elements.count) { product in - //=----------------------------------= - // de/init: pointee is trivial - //=----------------------------------= - product.initialize(repeating: UInt.zero) - //=----------------------------------= - var overflow = addend as UInt - for lhsIndex in self.elements.indices { - let outer = self.elements[lhsIndex] - - for rhsIndex in multiplicand.elements.indices { - let inner = multiplicand.elements[rhsIndex] - var subproduct = outer.multipliedFullWidth(by: inner) - - overflow = UInt(bit: subproduct.low.addReportingOverflow(overflow)) - overflow &+= UInt(bit: product[lhsIndex + rhsIndex].addReportingOverflow(subproduct.low)) - overflow &+= subproduct.high - } - - product[lhsIndex + multiplicand.elements.count] = overflow - overflow = UInt.zero - } - } - } -} diff --git a/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Numbers.swift b/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Numbers.swift deleted file mode 100644 index 78df84a1..00000000 --- a/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Numbers.swift +++ /dev/null @@ -1,174 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Flexible Width x Numbers -//*============================================================================* - -extension PrivateIntXLOrUIntXL { - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - @inlinable public init(digit: Digit) { - self.init(unchecked: Storage(unchecked: [UInt(bitPattern: digit)])) - } - - @inlinable public init(digit: Digit, at index: Int) { - var storage = Storage(unchecked: Elements(repeating: 0 as UInt, count: index + 1)) - storage.elements[index] = UInt(bitPattern: digit) - storage.normalize() - self.init(unchecked: storage) - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Numbers x IntXL -//*============================================================================* - -extension IntXL { - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - public static let zero = Self(0) - - //=------------------------------------------------------------------------= - // MARK: Initializers x Binary Integer - //=------------------------------------------------------------------------= - - @inlinable public init(_ source: T) where T: BinaryInteger { - var storage = Storage(nonemptying: Elements(source.words)) - - if !T.isSigned, storage.last.mostSignificantBit { - storage.append(0 as UInt) - } else { - storage.normalize() - } - - self.init(unchecked: storage) - } - - @inlinable public init?(exactly source: some BinaryInteger) { - self.init(source) - } - - @inlinable public init(clamping source: some BinaryInteger) { - self.init(source) - } - - @inlinable public init(truncatingIfNeeded source: some BinaryInteger) { - self.init(source) - } - - //=------------------------------------------------------------------------= - // MARK: Initializers x Binary Floating Point - //=------------------------------------------------------------------------= - - @inlinable public init(_ source: some BinaryFloatingPoint) { - if let value = Self(exactly: source.rounded(.towardZero)) { self = value } else { - preconditionFailure("\(Self.description) cannot represent \(source)") - } - } - - @inlinable public init?(exactly source: some BinaryFloatingPoint) { - guard let magnitude = Magnitude(exactly: source.magnitude) else { return nil } - self.init(sign: source.sign, magnitude: magnitude) - } - - //=------------------------------------------------------------------------= - // MARK: Initializers x Sign & Magnitude - //=------------------------------------------------------------------------= - - @inlinable public init(sign: FloatingPointSign, magnitude: Magnitude) { - var unsigned = magnitude.storage as Magnitude.Storage - var isLessThanZero = (sign == FloatingPointSign.minus) - if isLessThanZero { - isLessThanZero = !unsigned.formTwosComplementReportingOverflow() - } - - var signed = Storage(bitPattern: unsigned) - signed.normalize(appending: UInt(repeating: isLessThanZero)) - self.init(unchecked: signed) - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Numbers x UIntXL -//*============================================================================* - -extension UIntXL { - - //=------------------------------------------------------------------------= - // MARK: Constants - //=------------------------------------------------------------------------= - - public static let zero = Self(0) - - //=------------------------------------------------------------------------= - // MARK: Initializers x Binary Integer - //=------------------------------------------------------------------------= - - @inlinable public init(_ source: some BinaryInteger) { - if let value = Self(exactly: source) { self = value } else { - preconditionFailure("\(Self.description) cannot represent \(source)") - } - } - - @inlinable public init?(exactly source: some BinaryInteger) { - guard source.signum() >= 0 else { return nil } - self.init(words: source.words) - } - - @inlinable public init(clamping source: some BinaryInteger) { - self = Self(exactly: source) ?? (0 as Self) - } - - @inlinable public init(truncatingIfNeeded source: some BinaryInteger) { - self.init(words: source.words) - } - - //=------------------------------------------------------------------------= - // MARK: Initializers x Binary Floating Point - //=------------------------------------------------------------------------= - - @inlinable public init(_ source: some BinaryFloatingPoint) { - if let value = Self(exactly: source.rounded(.towardZero)) { self = value } else { - preconditionFailure("\(Self.description) cannot represent \(source)") - } - } - - @inlinable public init?(exactly source: some BinaryFloatingPoint) { - if source.sign == .minus { return nil } - //=--------------------------------------= - if source.isZero { self.init(); return } - guard source.isFinite else { return nil } - let value = source.rounded(.towardZero) - guard value == source else { return nil } - //=--------------------------------------= - let exponent = Int(source.exponent) - let ratio = exponent.quotientAndRemainder(dividingBy: UInt.bitWidth) - //=--------------------------------------= - self.init(exactly: source.significandBitPattern) - self >>= type(of: source).significandBitCount - exponent - self.add(UInt(1) << ratio.remainder, at: ratio.quotient) - } - - //=------------------------------------------------------------------------= - // MARK: Initializers x Sign & Magnitude - //=------------------------------------------------------------------------= - - @inlinable public init?(sign: FloatingPointSign, magnitude: Magnitude) { - if sign == FloatingPointSign.plus || magnitude.isZero { self = magnitude } else { return nil } - } -} diff --git a/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Shifts.swift b/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Shifts.swift deleted file mode 100644 index e0f3dbca..00000000 --- a/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Shifts.swift +++ /dev/null @@ -1,394 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Flexible Width x Shifts -//*============================================================================* -//=----------------------------------------------------------------------------= -// MARK: + Left -//=----------------------------------------------------------------------------= - -extension PrivateIntXLOrUIntXL { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable public static func <<=(lhs: inout Self, rhs: some BinaryInteger) { - lhs.bitshiftLeftSmart(by: NBK.initOrBitCast(clamping: rhs, as: Int.self)) - } - - @inlinable public static func <<(lhs: Self, rhs: some BinaryInteger) -> Self { - var lhs = lhs; lhs <<= rhs; return lhs - } - - //=------------------------------------------------------------------------= - // MARK: Transformations x Int - //=------------------------------------------------------------------------= - - @inlinable public mutating func bitshiftLeftSmart(by distance: Int) { - if distance >= 0 { - self.bitshiftLeft (by: distance) - } else { - self.bitshiftRight(by: Int(clamping: distance.magnitude)) - } - } - - @inlinable public func bitshiftedLeftSmart(by distance: Int) -> Self { - var result = self; result.bitshiftLeftSmart(by: distance); return result - } - - @inlinable public mutating func bitshiftLeft(by distance: Int) { - precondition(distance >= 0, NBK.callsiteOutOfBoundsInfo()) - let major = NBK .quotientDividingByBitWidthAssumingIsAtLeastZero(distance) - let minor = NBK.remainderDividingByBitWidthAssumingIsAtLeastZero(distance) - return self.bitshiftLeft(words: major, bits: minor) - } - - @inlinable public func bitshiftedLeft(by distance: Int) -> Self { - var result = self; result.bitshiftLeft(by: distance); return result - } - - @inlinable public mutating func bitshiftLeft(words: Int, bits: Int) { - //=--------------------------------------= - if bits.isZero { - return self.bitshiftLeft(words: words) - } - //=--------------------------------------= - self.bitshiftLeft(words: words, atLeastOneBit: bits) - } - - @inlinable public func bitshiftedLeft(words: Int, bits: Int) -> Self { - var result = self; result.bitshiftLeft(words: words, bits: bits); return result - } - - @inlinable public mutating func bitshiftLeft(words: Int) { - //=--------------------------------------= - if words.isZero { return } - //=--------------------------------------= - self.bitshiftLeft(atLeastOneWord: words) - } - - @inlinable public func bitshiftedLeft(words: Int) -> Self { - var result = self; result.bitshiftLeft(words: words); return result - } - - //=------------------------------------------------------------------------= - // MARK: Transformations x Int x Private - //=------------------------------------------------------------------------= - - /// Performs a left shift. - /// - /// - Parameters: - /// - words: `0 <= words` - /// - bits: `1 <= bits  < UInt.bitWidth` - /// - @inlinable mutating func bitshiftLeft(words: Int, atLeastOneBit bits: Int) { - defer { - Swift.assert(self.storage.isNormal) - } - //=--------------------------------------= - if self.isZero { return } - //=--------------------------------------= - let rollover = Int(bit: self.leadingBitCount(self.isLessThanZero) < bits) - self.storage.resize(minCount: self.storage.elements.count + words + rollover, appending: 0 as UInt) - self.storage.bitshiftLeft(words: words, atLeastOneBit: bits) - } - - /// Performs a left shift. - /// - /// - Parameters: - /// - words: `1 <= words` - /// - @inlinable mutating func bitshiftLeft(atLeastOneWord words: Int) { - defer { - Swift.assert(self.storage.isNormal) - } - //=--------------------------------------= - if self.isZero { return } - //=--------------------------------------= - self.storage.resize(minCount: self.storage.elements.count + words, appending: 0 as UInt) - self.storage.bitshiftLeft(atLeastOneWord: words) - } -} - -//=----------------------------------------------------------------------------= -// MARK: + Right -//=----------------------------------------------------------------------------= - -extension PrivateIntXLOrUIntXL { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable public static func >>=(lhs: inout Self, rhs: some BinaryInteger) { - lhs.bitshiftRightSmart(by: NBK.initOrBitCast(clamping: rhs, as: Int.self)) - } - - @inlinable public static func >>(lhs: Self, rhs: some BinaryInteger) -> Self { - var lhs = lhs; lhs >>= rhs; return lhs - } - - //=------------------------------------------------------------------------= - // MARK: Transformations x Int - //=------------------------------------------------------------------------= - - @inlinable public mutating func bitshiftRightSmart(by distance: Int) { - if distance >= 0 { - self.bitshiftRight(by: distance) - } else { - self.bitshiftLeft(by: Int(clamping: distance.magnitude)) - } - } - - @inlinable public func bitshiftedRightSmart(by distance: Int) -> Self { - var result = self; result.bitshiftRightSmart(by: distance); return result - } - - @inlinable public mutating func bitshiftRight(by distance: Int) { - precondition(distance >= 0, NBK.callsiteOutOfBoundsInfo()) - let major = NBK .quotientDividingByBitWidthAssumingIsAtLeastZero(distance) - let minor = NBK.remainderDividingByBitWidthAssumingIsAtLeastZero(distance) - return self.bitshiftRight(words: major, bits: minor) - } - - @inlinable public func bitshiftedRight(by distance: Int) -> Self { - var result = self; result.bitshiftRight(by: distance); return result - } - - @inlinable public mutating func bitshiftRight(words: Int, bits: Int) { - //=--------------------------------------= - if bits.isZero { - return self.bitshiftRight(words: words) - } - //=--------------------------------------= - self.bitshiftRight(words: words, atLeastOneBit: bits) - } - - @inlinable public func bitshiftedRight(words: Int, bits: Int) -> Self { - var result = self; result.bitshiftRight(words: words, bits: bits); return result - } - - @inlinable public mutating func bitshiftRight(words: Int) { - //=--------------------------------------= - if words.isZero { return } - //=--------------------------------------= - self.bitshiftRight(atLeastOneWord: words) - } - - @inlinable public func bitshiftedRight(words: Int) -> Self { - var result = self; result.bitshiftRight(words: words); return result - } - - //=------------------------------------------------------------------------= - // MARK: Transformations x Int x Private - //=------------------------------------------------------------------------= - - /// Performs an un/signed right shift. - /// - /// - Parameters: - /// - words: `1 <= words` - /// - bits: `0 <= bits  < UInt.bitWidth` - /// - @inlinable mutating func bitshiftRight(words: Int, atLeastOneBit bits: Int) { - defer { - Swift.assert(self.storage.isNormal) - } - //=--------------------------------------= - let rollover = Int(bit: 0 <= bits + self.leadingZeroBitCount - UInt.bitWidth) - let maxCount = self.storage.elements.count - words - rollover - //=--------------------------------------= - if maxCount <= 0 { - return self.update(Digit(repeating: self.isLessThanZero)) - } - //=--------------------------------------= - self.storage.bitshiftRight(words: words, atLeastOneBit: bits) - self.storage.resize(maxCount: maxCount) - } - - /// Performs an un/signed right shift. - /// - /// - Parameters: - /// - words: `1 <= words` - /// - @inlinable mutating func bitshiftRight(atLeastOneWord words: Int) { - defer { - Swift.assert(self.storage.isNormal) - } - //=--------------------------------------= - if self.storage.elements.count <= words { - return self.update(Digit(repeating: self.isLessThanZero)) - } - //=--------------------------------------= - self.storage.bitshiftRight(atLeastOneWord: words) - self.storage.resize(maxCount: self.storage.elements.count - words) - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Shifts x Storage -//*============================================================================* -//=----------------------------------------------------------------------------= -// MARK: + Left -//=----------------------------------------------------------------------------= - -extension PrivateIntXLOrUIntXLStorage { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - /// Performs a left shift. - /// - /// - Parameters: - /// - distance: `0 <= distance < self.bitWidth` - /// - @inlinable mutating func bitshiftLeft(by distance: Int) { - precondition(distance >= 0, NBK.callsiteOutOfBoundsInfo()) - let major = NBK .quotientDividingByBitWidthAssumingIsAtLeastZero(distance) - let minor = NBK.remainderDividingByBitWidthAssumingIsAtLeastZero(distance) - return self.bitshiftLeft(words: major, bits: minor) - } - - /// Performs a left shift. - /// - /// - Parameters: - /// - words: `0 <= words < self.endIndex` - /// - bits: `0 <= bits  < UInt.bitWidth` - /// - @inlinable mutating func bitshiftLeft(words: Int, bits: Int) { - //=--------------------------------------= - if bits.isZero { - return self.bitshiftLeft(words: words) - } - //=--------------------------------------= - self.bitshiftLeft(words: words, atLeastOneBit: bits) - } - - /// Performs a left shift. - /// - /// - Parameters: - /// - words: `0 <= words < self.endIndex` - /// - @inlinable mutating func bitshiftLeft(words: Int) { - //=--------------------------------------= - if words.isZero { return } - //=--------------------------------------= - self.bitshiftLeft(atLeastOneWord: words) - } - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - /// Performs a left shift. - /// - /// - Parameters: - /// - words: `0 <= words < self.endIndex` - /// - bits: `1 <= bits  < UInt.bitWidth` - /// - @inlinable mutating func bitshiftLeft(words: Int, atLeastOneBit bits: Int) { - self.elements.withUnsafeMutableBufferPointer { - NBK.bitshiftLeftAsFixedLimbsCodeBlock(&$0, environment: false, limbs: words, atLeastOneBit: bits) - } - } - - /// Performs a left shift. - /// - /// - Parameters: - /// - words: `1 <= words < self.endIndex` - /// - @inlinable mutating func bitshiftLeft(atLeastOneWord words: Int) { - self.elements.withUnsafeMutableBufferPointer { - NBK.bitshiftLeftAsFixedLimbsCodeBlock(&$0, environment: false, atLeastOneLimb: words) - } - } -} - -//=----------------------------------------------------------------------------= -// MARK: + Right -//=----------------------------------------------------------------------------= - -extension PrivateIntXLOrUIntXLStorage { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - /// Performs an un/signed right shift. - /// - /// - Parameters: - /// - distance: `0 <= distance < self.bitWidth` - /// - @inlinable mutating func bitshiftRight(by distance: Int) { - precondition(distance >= 0, NBK.callsiteOutOfBoundsInfo()) - let major = NBK .quotientDividingByBitWidthAssumingIsAtLeastZero(distance) - let minor = NBK.remainderDividingByBitWidthAssumingIsAtLeastZero(distance) - return self.bitshiftRight(words: major, bits: minor) - } - - /// Performs an un/signed right shift. - /// - /// - Parameters: - /// - words: `0 <= words < self.endIndex` - /// - bits: `0 <= bits  < UInt.bitWidth` - /// - @inlinable mutating func bitshiftRight(words: Int, bits: Int) { - //=--------------------------------------= - if bits.isZero { - return self.bitshiftRight(words: words) - } - //=--------------------------------------= - self.bitshiftRight(words: words, atLeastOneBit: bits) - } - - /// Performs an un/signed right shift. - /// - /// - Parameters: - /// - words: `0 <= words < self.endIndex` - /// - @inlinable mutating func bitshiftRight(words: Int) { - //=--------------------------------------= - if words.isZero { return } - //=--------------------------------------= - self.bitshiftRight(atLeastOneWord: words) - } - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - /// Performs an un/signed right shift. - /// - /// - Parameters: - /// - words: `1 <= words < self.endIndex` - /// - bits: `0 <= bits  < UInt.bitWidth` - /// - @inlinable mutating func bitshiftRight(words: Int, atLeastOneBit bits: Int) { - let environment = self.isLessThanZero as Bool - self.elements.withUnsafeMutableBufferPointer { - NBK.bitshiftRightAsFixedLimbsCodeBlock(&$0, environment: environment, limbs: words, atLeastOneBit: bits) - } - } - - /// Performs an un/signed right shift. - /// - /// - Parameters: - /// - words: `1 <= words < self.endIndex` - /// - @inlinable mutating func bitshiftRight(atLeastOneWord words: Int) { - let environment = self.isLessThanZero as Bool - self.elements.withUnsafeMutableBufferPointer { - NBK.bitshiftRightAsFixedLimbsCodeBlock(&$0, environment: environment, atLeastOneLimb: words) - } - } -} diff --git a/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Storage+Normalization.swift b/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Storage+Normalization.swift deleted file mode 100644 index eccbd403..00000000 --- a/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Storage+Normalization.swift +++ /dev/null @@ -1,123 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Flexible Width x Storage x Normalization -//*============================================================================* - -extension PrivateIntXLOrUIntXLStorage { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable mutating func normalize(update value: Digit) { - self.elements.replaceSubrange(self.elements.indices, with: CollectionOfOne(UInt(bitPattern: value))) - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Storage x Normalization x IntXL -//*============================================================================* - -extension IntXL.Storage { - - //=------------------------------------------------------------------------= - // MARK: Accessors - //=------------------------------------------------------------------------= - - @inlinable var isNormal: Bool { - if self.elements.count == 1 { return true } - - let tail = Int(bitPattern: self.elements[self.elements.count - 1]) - let head = Int(bitPattern: self.elements[self.elements.count - 2]) - - let sign = tail >> Int.bitWidth - - return !(sign == tail && sign == head >> Int.bitWidth) - } - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable mutating func normalize() { - Swift.assert(!self.elements.isEmpty) - //=--------------------------------------= - var position = self.elements.index(before: self.elements.endIndex) - let mostSignificantBit = self.elements[position].mostSignificantBit - let sign = UInt(repeating: mostSignificantBit) - //=--------------------------------------= - // TODO: measure combined loop conditions - //=--------------------------------------= - backwards: while position > self.elements.startIndex { - if self.elements[position] != sign { return } - self.elements.formIndex(before: &position) - if self.elements[position].mostSignificantBit != mostSignificantBit { return } - self.elements.removeLast() - } - } - - @inlinable mutating func normalize(appending element: UInt) { - Swift.assert(!self.elements.isEmpty) - //=--------------------------------------= - var position = self.elements.index(before: self.elements.endIndex) - let mostSignificantBit = self.elements[position].mostSignificantBit - let sign = UInt(repeating: mostSignificantBit) - //=--------------------------------------= - if element != sign { - return self.elements.append(element) - } - //=--------------------------------------= - // TODO: measure combined loop conditions - //=--------------------------------------= - backwards: while position > self.elements.startIndex { - if self.elements[position] != sign { return } - self.elements.formIndex(before: &position) - if self.elements[position].mostSignificantBit != mostSignificantBit { return } - self.elements.removeLast() - } - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Storage x Normalization x UIntXL -//*============================================================================* - -extension UIntXL.Storage { - - //=------------------------------------------------------------------------= - // MARK: Accessors - //=------------------------------------------------------------------------= - - @inlinable var isNormal: Bool { - self.elements.count == 1 || !self.elements.last!.isZero - } - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable mutating func normalize() { - Swift.assert(!self.elements.isEmpty) - //=--------------------------------------= - var position = self.elements.index(before: self.elements.endIndex) - let sign = UInt(repeating: false) - //=--------------------------------------= - // TODO: measure combined loop conditions - //=--------------------------------------= - backwards: while position > self.elements.startIndex { - if self.elements[position] != sign { return } - self.elements.formIndex(before: &position) - self.elements.removeLast() - } - } -} diff --git a/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Storage+Size.swift b/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Storage+Size.swift deleted file mode 100644 index 0f0318b3..00000000 --- a/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Storage+Size.swift +++ /dev/null @@ -1,47 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Flexible Width x Storage x Size -//*============================================================================* - -extension PrivateIntXLOrUIntXLStorage { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable mutating func append(_ word: UInt) { - self.elements.append(word) - } - - @inlinable mutating func resize(maxCount: Int) { - precondition(maxCount.isMoreThanZero) - if self.elements.count > maxCount { - self.elements.removeSubrange(maxCount...) - } - } - - @inlinable mutating func resize(minCount: Int, appending element: UInt) { - self.reserveCapacity(minCount) - appending: while self.elements.count < minCount { - self.elements.append(element) - } - } - - @inlinable mutating func resize(minCount: Int) { - self.resize(minCount: minCount, appending: UInt(repeating: self.isLessThanZero)) - } - - @inlinable mutating func reserveCapacity(_ minCapacity: Int) { - self.elements.reserveCapacity(minCapacity) - } -} diff --git a/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Storage.swift b/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Storage.swift deleted file mode 100644 index 5f14e280..00000000 --- a/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Storage.swift +++ /dev/null @@ -1,141 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - - -//*============================================================================* -// MARK: * NBK x Flexible Width x Storage x IntXL -//*============================================================================* - -extension IntXL { - - //*========================================================================* - // MARK: * Storage - //*========================================================================* - - /// IntXL's and UIntXL's underlying storage. - /// - /// It has fixed-width semantics unless stated otherwise. - /// - @frozen @usableFromInline struct Storage: PrivateIntXLOrUIntXLStorage { - - @usableFromInline typealias Digit = IntXL.Digit - - @usableFromInline typealias Elements = NBKFlexibleWidth.Elements - - //=--------------------------------------------------------------------= - // MARK: State - //=--------------------------------------------------------------------= - - /// A collection of unsigned integers. - /// - /// It must be `nonempty` at the start and end of each access. - /// - @usableFromInline var elements: Elements - - //=--------------------------------------------------------------------= - // MARK: Initializers - //=--------------------------------------------------------------------= - - @inlinable init(_ elements: Elements) { - self.elements = elements - precondition(!self.elements.isEmpty) - } - - @inlinable init(unchecked elements: Elements) { - self.elements = elements - Swift.assert(!self.elements.isEmpty) - } - - @inlinable init(nonemptying elements: Elements) { - self.elements = elements - if self.elements.isEmpty { - self.elements.append(0) - } - } - - //=--------------------------------------------------------------------= - // MARK: Details x Bit Pattern - //=--------------------------------------------------------------------= - - @inlinable init(bitPattern: UIntXL.Storage) { - self.init(unchecked: bitPattern.elements) - } - - @inlinable var bitPattern: UIntXL.Storage { - UIntXL.Storage(unchecked: self.elements) - } - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Storage x UIntXL -//*============================================================================* - -extension UIntXL { - - //*========================================================================* - // MARK: * Storage - //*========================================================================* - - /// IntXL's and UIntXL's underlying storage. - /// - /// It has fixed-width semantics unless stated otherwise. - /// - @frozen @usableFromInline struct Storage: PrivateIntXLOrUIntXLStorage { - - @usableFromInline typealias Digit = UIntXL.Digit - - @usableFromInline typealias Elements = NBKFlexibleWidth.Elements - - //=--------------------------------------------------------------------= - // MARK: State - //=--------------------------------------------------------------------= - - /// A collection of unsigned integers. - /// - /// It must be `nonempty` at the start and end of each access. - /// - @usableFromInline var elements: Elements - - //=--------------------------------------------------------------------= - // MARK: Initializers - //=--------------------------------------------------------------------= - - @inlinable init(_ elements: Elements) { - self.elements = elements - precondition(!self.elements.isEmpty) - } - - @inlinable init(unchecked elements: Elements) { - self.elements = elements - Swift.assert(!self.elements.isEmpty) - } - - @inlinable init(nonemptying elements: Elements) { - self.elements = elements - if self.elements.isEmpty { - self.elements.append(0) - } - } - - //=--------------------------------------------------------------------= - // MARK: Details x Bit Pattern - //=--------------------------------------------------------------------= - - @inlinable init(bitPattern: UIntXL.Storage) { - self = bitPattern - } - - @inlinable var bitPattern: UIntXL.Storage { - self - } - } -} diff --git a/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Subtraction+Digit.swift b/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Subtraction+Digit.swift deleted file mode 100644 index 00055590..00000000 --- a/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Subtraction+Digit.swift +++ /dev/null @@ -1,138 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Flexible Width x Subtraction x Digit -//*============================================================================* - -extension IntXLOrUIntXL { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @_disfavoredOverload @inlinable public static func -=(lhs: inout Self, rhs: Digit) { - lhs.subtract(rhs, at: Int.zero) - } - - @_disfavoredOverload @inlinable public static func -(lhs: Self, rhs: Digit) -> Self { - lhs.subtracting(rhs, at: Int.zero) - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Subtraction x Digit x IntXL -//*============================================================================* - -extension IntXL { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @_disfavoredOverload @inlinable public mutating func subtract(_ other: Int, at index: Int) { - //=--------------------------------------= - if other.isZero { return } - //=--------------------------------------= - let lhsIsLessThanZero = self .isLessThanZero - let rhsIsLessThanZero = other.isLessThanZero - let lhsSign = UInt(repeating: lhsIsLessThanZero) - let rhsSign = UInt(repeating: rhsIsLessThanZero) - //=--------------------------------------= - self.storage.resize(minCount: index + 1) - //=--------------------------------------= - var borrow = self.storage.elements[index].subtractReportingOverflow(UInt(bitPattern: other)) - var index = self.storage.elements.index(after: index) - //=--------------------------------------= - if borrow != rhsIsLessThanZero { - let predicate = borrow - let decrement = UInt(bitPattern: borrow ? 1 : -1) - - while index != self.storage.elements.endIndex && borrow == predicate { - borrow = self.storage.elements[index].subtractReportingOverflow(decrement) - self.storage.elements.formIndex(after: &index) - } - } - //=--------------------------------------= - self.storage.normalize(appending: lhsSign &- rhsSign &- UInt(bit: borrow)) - } - - @_disfavoredOverload @inlinable public func subtracting(_ other: Int, at index: Int) -> Self { - var result = self; result.subtract(other, at: index); return result - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Subtraction x Digit x UIntXL -//*============================================================================* - -extension UIntXL { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @_disfavoredOverload @inlinable public mutating func subtract(_ other: UInt, at index: Int) { - let overflow: Bool = self.subtractReportingOverflow(other, at: index) - precondition(!overflow, NBK.callsiteOverflowInfo()) - } - - @_disfavoredOverload @inlinable public func subtracting(_ other: UInt, at index: Int) -> Self { - let pvo: PVO = self.subtractingReportingOverflow(other, at: index) - precondition(!pvo.overflow, NBK.callsiteOverflowInfo()) - return pvo.partialValue as Self - } - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @_disfavoredOverload @inlinable public mutating func subtractReportingOverflow(_ other: UInt) -> Bool { - self.subtractReportingOverflow(other, at: Int.zero) - } - - @_disfavoredOverload @inlinable public func subtractingReportingOverflow(_ other: UInt) -> PVO { - self.subtractingReportingOverflow(other, at: Int.zero) - } - - @_disfavoredOverload @inlinable public mutating func subtractReportingOverflow(_ other: UInt, at index: Int) -> Bool { - defer { - Swift.assert(self.storage.isNormal) - } - //=--------------------------------------= - if other.isZero { return false } - //=--------------------------------------= - self.storage.resize(minCount: index + 1) - defer{ self.storage.normalize() } - return self.storage.subtract(other, plus: false, at: index) - } - - @_disfavoredOverload @inlinable public func subtractingReportingOverflow(_ other: UInt, at index: Int) -> PVO { - var partialValue = self - let overflow: Bool = partialValue.subtractReportingOverflow(other, at: index) - return PVO(partialValue, overflow) - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Subtraction x Digit x UIntXL x Storage -//*============================================================================* - -extension UIntXL.Storage { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @_disfavoredOverload @inlinable mutating func subtract(_ other: UInt, plus borrow: Bool, at index: Int) -> Bool { - NBK.decrementSufficientUnsignedInteger(&self.elements, by: other, plus: borrow, at: index).overflow - } -} diff --git a/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Subtraction.swift b/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Subtraction.swift deleted file mode 100644 index 7a7c5f15..00000000 --- a/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Subtraction.swift +++ /dev/null @@ -1,158 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Flexible Width x Subtraction -//*============================================================================* - -extension IntXLOrUIntXL { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable public static func -=(lhs: inout Self, rhs: Self) { - lhs.subtract(rhs, at: Int.zero) - } - - @inlinable public static func -(lhs: Self, rhs: Self) -> Self { - lhs.subtracting(rhs, at: Int.zero) - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Subtraction x IntXL -//*============================================================================* - -extension IntXL { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable public mutating func subtract(_ other: Self, at index: Int) { - //=--------------------------------------= - if other.isZero { return } - //=--------------------------------------= - let lhsIsLessThanZero = self .isLessThanZero - let rhsIsLessThanZero = other.isLessThanZero - let lhsSign = UInt(repeating: lhsIsLessThanZero) - let rhsSign = UInt(repeating: rhsIsLessThanZero) - //=--------------------------------------= - self.storage.resize(minCount: other.storage.elements.count + index) - //=--------------------------------------= - var borrow = false - var lhsIndex = index - var rhsIndex = other.storage.elements.startIndex - //=--------------------------------------= - while rhsIndex != other.storage.elements.endIndex { - var lhsElement = self .storage.elements[lhsIndex] - let rhsElement = other.storage.elements[rhsIndex] - - let a = lhsElement.subtractReportingOverflow(rhsElement) - let b = lhsElement.subtractReportingOverflow(UInt(bit: borrow)) - borrow = a || b - - self .storage.elements[lhsIndex] = lhsElement - self .storage.elements.formIndex(after: &lhsIndex) - other.storage.elements.formIndex(after: &rhsIndex) - } - //=--------------------------------------= - if borrow != rhsIsLessThanZero { - let predicate = borrow - let decrement = UInt(bitPattern: borrow ? 1 : -1) - - while lhsIndex != self.storage.elements.endIndex && borrow == predicate { - borrow = self.storage.elements[lhsIndex].subtractReportingOverflow(decrement) - self.storage.elements.formIndex(after: &lhsIndex) - } - } - //=--------------------------------------= - self.storage.normalize(appending: lhsSign &- rhsSign &- UInt(bit: borrow)) - } - - @inlinable public func subtracting(_ other: Self, at index: Int) -> Self { - var result = self; result.subtract(other, at: index); return result - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Subtraction x UIntXL -//*============================================================================* - -extension UIntXL { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable public mutating func subtract(_ other: Self, at index: Int) { - let overflow: Bool = self.subtractReportingOverflow(other, at: index) - precondition(!overflow, NBK.callsiteOverflowInfo()) - } - - @inlinable public func subtracting(_ other: Self, at index: Int) -> Self { - let pvo: PVO = self.subtractingReportingOverflow(other, at: index) - precondition(!pvo.overflow, NBK.callsiteOverflowInfo()) - return pvo.partialValue as Self - } - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable public mutating func subtractReportingOverflow(_ other: Self) -> Bool { - self.subtractReportingOverflow(other, at: Int.zero) - } - - @inlinable public func subtractingReportingOverflow(_ other: Self) -> PVO { - self.subtractingReportingOverflow(other, at: Int.zero) - } - - @inlinable public mutating func subtractReportingOverflow(_ other: Self, at index: Int) -> Bool { - defer { - Swift.assert(self.storage.isNormal) - } - //=--------------------------------------= - if other.isZero { return false } - //=--------------------------------------= - self.storage.resize(minCount: other.storage.elements.count + index) - defer{ self.storage.normalize() } - return self.storage.subtract(other.storage, plus: false, at: index) - } - - @inlinable public func subtractingReportingOverflow(_ other: Self, at index: Int) -> PVO { - var partialValue = self - let overflow: Bool = partialValue.subtractReportingOverflow(other, at: index) - return PVO(partialValue, overflow) - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Subtraction x UIntXL x Storage -//*============================================================================* - -extension UIntXL.Storage { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable mutating func subtract(_ other: Self, plus borrow: Bool, at index: Int) -> Bool { - NBK.decrementSufficientUnsignedInteger(&self.elements, by: other.elements, plus: borrow, at: index).overflow - } - - @inlinable mutating func subtract(_ other: Self, times multiplicand: UInt, - plus subtrahend: UInt, plus borrow: Bool, at index: Int) -> Bool { - NBK.decrementSufficientUnsignedInteger(&self.elements, by: other .elements, - times: multiplicand, plus: subtrahend, plus: borrow, at: index).overflow - } -} diff --git a/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Text.swift b/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Text.swift deleted file mode 100644 index f4d37657..00000000 --- a/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Text.swift +++ /dev/null @@ -1,160 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Flexible Width x Text -//*============================================================================* - -extension IntXLOrUIntXL { - - //=------------------------------------------------------------------------= - // MARK: Details x Decode - //=------------------------------------------------------------------------= - - @inlinable public init?(_ description: some StringProtocol, radix: Int = 10) { - var description = String(description) - if let value: Self = description.withUTF8({ utf8 in - let radix = NBK.AnyRadixSolution(radix) - let components = NBK.makeIntegerComponents(utf8: utf8) - let digits = NBK.UnsafeUTF8(rebasing: components.body) - guard let magnitude = Magnitude(digits: digits, radix: radix) else { return nil } - return Self(sign: components.sign, magnitude: magnitude) - }){ self = value } else { return nil } - } - - //=------------------------------------------------------------------------= - // MARK: Details x Encode - //=------------------------------------------------------------------------= - - @inlinable public func description(radix: Int = 10, uppercase: Bool = false) -> String { - Swift.withUnsafePointer(to: UInt8(ascii: "-")) { minus in - let radix = NBK.AnyRadixSolution(radix) - let alphabet = NBK.MaxRadixAlphabetEncoder(uppercase: uppercase) - let prefix = NBK.UnsafeUTF8(start: minus, count: Int(bit: self.isLessThanZero)) - let suffix = NBK.UnsafeUTF8(start: nil, count: Int.zero) - return self.magnitude.description(radix: radix, alphabet: alphabet, prefix: prefix, suffix: suffix) - } - } -} - -//=----------------------------------------------------------------------------= -// MARK: + Algorithms -//=----------------------------------------------------------------------------= - -extension UIntXL { - - //=------------------------------------------------------------------------= - // MARK: Details x Decode x Private - //=------------------------------------------------------------------------= - - @inlinable init?(digits: NBK.UnsafeUTF8, radix: NBK.AnyRadixSolution) { - switch radix.power.isZero { - case true: self.init(digits: digits, radix: NBK .PerfectRadixSolution(radix)!) - case false: self.init(digits: digits, radix: NBK.ImperfectRadixSolution(radix)!) } - } - - @inlinable init?(digits: NBK.UnsafeUTF8, radix: NBK.PerfectRadixSolution) { - guard !digits.isEmpty else { return nil } - //=--------------------------------------= - var digits = digits.drop(while:{ $0 == 48 }) - let division = digits.count.quotientAndRemainder(dividingBy: radix.exponent) - let count = division.quotient + Int(bit: !division.remainder.isZero) - //=--------------------------------------= - var elements = Elements(repeating: 0, count: count) - - backwards: for index in elements.indices { - let chunk = NBK.UnsafeUTF8(rebasing: NBK.removeSuffix(from: &digits, maxLength: radix.exponent)) - guard let word = NBK.truncating(digits: chunk, radix: radix.base, as: UInt.self) else { return nil } - elements[index] = word - } - - self.init(unchecked: Storage(nonemptying: elements)) - } - - @inlinable init?(digits: NBK.UnsafeUTF8, radix: NBK.ImperfectRadixSolution) { - guard !digits.isEmpty else { return nil } - //=--------------------------------------= - var digits = digits.drop(while:{ $0 == 48 }) - let remainder = digits.count % radix.exponent - //=--------------------------------------= - self.init() - - forwards: if !remainder.isZero { - let chunk = NBK.UnsafeUTF8(rebasing: NBK.removePrefix(from: &digits, count: remainder)) - guard let word = NBK.truncating(digits: chunk, radix: radix.base, as: UInt.self) else { return nil } - self.storage.first = word - } - - forwards: while !digits.isEmpty { - let chunk = NBK.UnsafeUTF8(rebasing: NBK.removePrefix(from: &digits, count: radix.exponent)) - guard let word = NBK.truncating(digits: chunk, radix: radix.base, as: UInt.self) else { return nil } - self.multiply(by: radix.power, add: word) - } - } - - //=------------------------------------------------------------------------= - // MARK: Details x Encode x Private - //=------------------------------------------------------------------------= - // NOTE: Both branches specialize NBKTwinHeaded>. - //=------------------------------------------------------------------------= - - @inlinable func description( - radix: NBK.AnyRadixSolution, alphabet: NBK.MaxRadixAlphabetEncoder, - prefix: NBK.UnsafeUTF8, suffix: NBK.UnsafeUTF8) -> String { - switch radix.power.isZero { - case true: return self.description(radix: NBK .PerfectRadixSolution(radix)!, alphabet: alphabet, prefix: prefix, suffix: suffix) - case false: return self.description(radix: NBK.ImperfectRadixSolution(radix)!, alphabet: alphabet, prefix: prefix, suffix: suffix) } - } - - @inlinable func description( - radix: NBK.PerfectRadixSolution, alphabet: NBK.MaxRadixAlphabetEncoder, - prefix: NBK.UnsafeUTF8, suffix: NBK.UnsafeUTF8) -> String { - //=--------------------------------------= - // with one buffer pointer specialization - //=--------------------------------------= - self.withUnsafeBufferPointer { words in - let chunks = NBKTwinHeaded(words) - let radix = NBK.AnyRadixSolution(radix) - return NBK.integerTextUnchecked(chunks: chunks, radix: radix, alphabet: alphabet, prefix: prefix, suffix: suffix) - } - } - - @inlinable func description( - radix: NBK.ImperfectRadixSolution, alphabet: NBK.MaxRadixAlphabetEncoder, - prefix: NBK.UnsafeUTF8, suffix: NBK.UnsafeUTF8) -> String { - //=--------------------------------------= - // with one buffer pointer specialization - //=--------------------------------------= - let capacity: Int = radix.divisibilityByPowerUpperBound(self) - return Swift.withUnsafeTemporaryAllocation(of: UInt.self, capacity: capacity) { buffer in - //=----------------------------------= - var magnitude: Magnitude = self - let start = buffer.baseAddress! - var position = start as UnsafeMutablePointer - //=----------------------------------= - // pointee: initialization - //=----------------------------------= - rebasing: repeat { - position.initialize(to: magnitude.formQuotientWithRemainderReportingOverflow(dividingBy: radix.power).partialValue) - position = position.successor() - } while !magnitude.isZero - //=----------------------------------= - // pointee: deferred deinitialization - //=----------------------------------= - let count = start.distance(to: position) - defer { start.deinitialize(count: count) } - //=----------------------------------= - let radix = NBK.AnyRadixSolution(radix) - let chunks = NBKTwinHeaded(UnsafeBufferPointer( start: start, count: count)) - return NBK.integerTextUnchecked(chunks: chunks, radix: radix, alphabet: alphabet, prefix: prefix, suffix: suffix) - } - } -} diff --git a/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Update.swift b/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Update.swift deleted file mode 100644 index 67395bbc..00000000 --- a/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Update.swift +++ /dev/null @@ -1,29 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Flexible Width x Update -//*============================================================================* - -extension PrivateIntXLOrUIntXL { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable public mutating func updateZeroValue() { - self.update(0 as Digit) - } - - @inlinable public mutating func update(_ value: Digit) { - self.storage.normalize(update: value) - } -} diff --git a/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Words+Pointers.swift b/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Words+Pointers.swift deleted file mode 100644 index d794ccd6..00000000 --- a/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Words+Pointers.swift +++ /dev/null @@ -1,34 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Flexible Width x Words x Pointers -//*============================================================================* - -extension PrivateIntXLOrUIntXL { - - //=------------------------------------------------------------------------= - // MARK: Utilities - //=------------------------------------------------------------------------= - - /// Grants unsafe access to the collection's contiguous storage. - @inlinable public func withUnsafeBufferPointer( - _ body:(UnsafeBufferPointer) throws -> T) rethrows -> T { - try self.storage.elements.withUnsafeBufferPointer(body) - } - - /// Grants unsafe access to the collection's contiguous mutable storage. - @inlinable public mutating func withUnsafeMutableBufferPointer( - _ body:(inout UnsafeMutableBufferPointer) throws -> T) rethrows -> T { - defer{ self.storage.normalize() } - return try self.storage.elements.withUnsafeMutableBufferPointer(body) - } -} diff --git a/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Words.swift b/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Words.swift deleted file mode 100644 index 9e8acab7..00000000 --- a/Sources/NBKTwosComplementKit/NBKFlexibleWidth+Words.swift +++ /dev/null @@ -1,67 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Flexible Width x Words -//*============================================================================* - -extension PrivateIntXLOrUIntXL { - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - @inlinable public init(words: some Sequence) { - self.init(normalizing: Storage(nonemptying: Elements(words))) - } - - //=------------------------------------------------------------------------= - // MARK: Accessors - //=------------------------------------------------------------------------= - - @inlinable public var words: ContiguousArray { - self.storage.elements // TODO: make opaque - } - - @inlinable public subscript(index: Int) -> UInt { - if index < self.storage.elements.endIndex { - return self.storage.elements[index] - } else { - return UInt(bitPattern: Digit(bitPattern: self.storage.last) >> Digit.bitWidth) - } - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Words x Storage -//*============================================================================* - -extension PrivateIntXLOrUIntXLStorage { - - //=------------------------------------------------------------------------= - // MARK: Accessors - //=------------------------------------------------------------------------= - - @inlinable var first: UInt { - get { self.elements[self.elements.startIndex] } - set { self.elements[self.elements.startIndex] = newValue } - } - - @inlinable var last: UInt { - get { self.elements[self.elements.index(before: self.elements.endIndex)] } - set { self.elements[self.elements.index(before: self.elements.endIndex)] = newValue } - } - - @inlinable var tail: Digit { - get { Digit(bitPattern: self.last) } - set { self.last = UInt(bitPattern: newValue) } - } -} diff --git a/Sources/NBKTwosComplementKit/NBKFlexibleWidth.swift b/Sources/NBKTwosComplementKit/NBKFlexibleWidth.swift deleted file mode 100644 index 1d6e2d86..00000000 --- a/Sources/NBKTwosComplementKit/NBKFlexibleWidth.swift +++ /dev/null @@ -1,132 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Flexible Width -//*============================================================================* - -/// A signed, flexible-width, binary integer. -@frozen public struct NBKFlexibleWidth: PrivateIntXLOrUIntXL, NBKSignedInteger { - - public typealias Digit = Int - - public typealias Words = ContiguousArray - - @usableFromInline typealias Elements = ContiguousArray - - //=------------------------------------------------------------------------= - // MARK: State - //=------------------------------------------------------------------------= - - /// The integer's underlying storage. - /// - /// It must be `normal` and `nonempty` at the start and end of each access. - /// - @usableFromInline var storage: Storage - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - @inlinable init(_ storage: Storage) { - self.storage = storage - precondition(self.storage.isNormal) - } - - @inlinable init(unchecked storage: Storage) { - self.storage = storage - Swift.assert(self.storage.isNormal) - } - - @inlinable init(normalizing storage: Storage) { - self.storage = storage - self.storage.normalize() - } - - //*========================================================================* - // MARK: * Magnitude - //*========================================================================* - - /// An unsigned, flexible-width, binary integer. - @frozen public struct Magnitude: PrivateIntXLOrUIntXL, NBKUnsignedInteger { - - public typealias Digit = UInt - - public typealias Words = NBKFlexibleWidth.Words - - @usableFromInline typealias Elements = NBKFlexibleWidth.Elements - - //=--------------------------------------------------------------------= - // MARK: State - //=--------------------------------------------------------------------= - - /// The integer's underlying storage. - /// - /// It must be `normal` and `nonempty` at the start and end of each access. - /// - @usableFromInline var storage: Storage - - //=--------------------------------------------------------------------= - // MARK: Initializers - //=--------------------------------------------------------------------= - - @inlinable init(_ storage: Storage) { - self.storage = storage - precondition(self.storage.isNormal) - } - - @inlinable init(unchecked storage: Storage) { - self.storage = storage - Swift.assert(self.storage.isNormal) - } - - @inlinable init(normalizing storage: Storage) { - self.storage = storage - self.storage.normalize() - } - } -} - -//=----------------------------------------------------------------------------= -// MARK: + Details -//=----------------------------------------------------------------------------= - -extension IntXLOrUIntXL { - - //=------------------------------------------------------------------------= - // MARK: Utilities - //=------------------------------------------------------------------------= - - /// A `description` of this type. - /// - /// ``` - /// ┌─────────────────────────── → ────────────┐ - /// │ type │ description │ - /// ├─────────────────────────── → ────────────┤ - /// │ NBKFlexibleWidth │ "IntXL" │ - /// │ NBKFlexibleWidth.Magnitude │ "UIntXL" │ - /// └─────────────────────────── → ────────────┘ - /// ``` - /// - @inlinable public static var description: String { - self.isSigned ? "IntXL" : "UIntXL" - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Aliases -//*============================================================================* - -/// A signed, flexible-width, integer. -public typealias IntXL = NBKFlexibleWidth - -/// An unsigned, flexible-width, integer. -public typealias UIntXL = NBKFlexibleWidth.Magnitude diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Text.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Text.swift index 0c914b2e..08bb37b1 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Text.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Text.swift @@ -474,6 +474,925 @@ final class NBKFlexibleWidthTestsOnTextAsUIntXL: XCTestCase { } } +//*============================================================================* +// MARK: * NBK x Flexible Width x Text x For Each Radix x UIntXL +//*============================================================================* + +final class NBKFlexibleWidthTestsOnTextForEachRadixAsUIntXL: XCTestCase { + + typealias T = UIntXL + + //=------------------------------------------------------------------------= + // MARK: State + //=------------------------------------------------------------------------= + + var radix: Int = 10 + var x64 = (UInt64(), UInt64(), UInt64(), UInt64()) + var txt = (String()) + + //=------------------------------------------------------------------------= + // MARK: Set Up, Tear Down + //=------------------------------------------------------------------------= + + override func setUp() { + self.radix = 10 + self.x64.0 = UInt64() + self.x64.1 = UInt64() + self.x64.2 = UInt64() + self.x64.3 = UInt64() + self.txt = String() + } + + override func tearDown() { + let decoded = T(x64: [x64.0, x64.1, x64.2, x64.3]) + var encoded = String(self.txt.drop{ $0 == "0" }) + if encoded.isEmpty { + encoded.append(contentsOf: self.txt.suffix(1)) + } + + NBKAssertDecodeText(decoded, self.radix, txt) + NBKAssertDecodeText(decoded, self.radix, encoded) + NBKAssertEncodeText(decoded, self.radix, true, encoded.uppercased()) + NBKAssertEncodeText(decoded, self.radix, false, encoded.lowercased()) + } + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testRadix02Top() { + self.radix = 02 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 1111111111111110111111011111110011111011111110101111100111111000\ + 1111011111110110111101011111010011110011111100101111000111110000\ + 1110111111101110111011011110110011101011111010101110100111101000\ + 1110011111100110111001011110010011100011111000101110000111100000 + """ + } + + func testRadix02Bottom() { + self.radix = 02 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0001111100011110000111010001110000011011000110100001100100011000\ + 0001011100010110000101010001010000010011000100100001000100010000\ + 0000111100001110000011010000110000001011000010100000100100001000\ + 0000011100000110000001010000010000000011000000100000000100000000 + """ + } + + //=----( 03 )--------------------------------------------------------------= + + func testRadix03Top() { + self.radix = 03 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000000000000000000000000000001202200212221120001222202211110211\ + 2122212010220102122202121101120111112200201101101222110200202110\ + 0220201022101000210101202220120002101202101120201012012212012002 + """ + } + + func testRadix03Bottom() { + self.radix = 03 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0000000000000000000000000000000012210112211101210122010202201212\ + 2200112221212101221211222010022020100210220200100011100100222021\ + 2000121220012212111000111110212212201000011111112211120210102101 + """ + } + + //=----( 04 )--------------------------------------------------------------= + + func testRadix04Top() { + self.radix = 04 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 3333333233313330332333223321332033133312331133103303330233013300\ + 3233323232313230322332223221322032133212321132103203320232013200 + """ + } + + func testRadix04Bottom() { + self.radix = 04 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0133013201310130012301220121012001130112011101100103010201010100\ + 0033003200310030002300220021002000130012001100100003000200010000 + """ + } + + //=----( 05 )--------------------------------------------------------------= + + func testRadix05Top() { + self.radix = 05 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000000000000000012224200130200441041444042343242340402322434230\ + 2203100014323101131021202442142123441124102101232423332422334024 + """ + } + + func testRadix05Bottom() { + self.radix = 05 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0000000000000000000424043311031102404011202312202132022104340041\ + 4431003121344314114341012313341313423214420311244321214230031301 + """ + } + + //=----( 06 )--------------------------------------------------------------= + + func testRadix06Top() { + self.radix = 06 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000000000000000000000000000102141010531040333210533123011525130\ + 3433311132532415235332533224344010103324220312020213104050423132 + """ + } + + func testRadix06Bottom() { + self.radix = 06 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0000000000000000000000000000004353050531332542114015530141512113\ + 1210015440102001011522210020211244125255022541512055450000200144 + """ + } + + //=----( 07 )--------------------------------------------------------------= + + func testRadix07Top() { + self.radix = 07 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000000000000000000000000000000000001305333621612661215031353503\ + 1603616341660421351201115002605631306624232666655230226263060363 + """ + } + + func testRadix07Bottom() { + self.radix = 07 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0000000000000000000000000000000000000114142063044505436351120634\ + 3333263503132100565010106005630324255134635601621240633030645403 + """ + } + + //=----( 08 )--------------------------------------------------------------= + + func testRadix08Top() { + self.radix = 08 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000000000000000000000000000000000000000001777767737637376574770\ + 7577336575171762743703577356675472765351721637467136234370560740 + """ + } + + func testRadix08Bottom() { + self.radix = 08 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0000000000000000000000000000000000000000000174360721603306414430\ + 0561302505011422042100170340641402605011020034060120200300400400 + """ + } + + //=----( 09 )--------------------------------------------------------------= + + func testRadix09Top() { + self.radix = 09 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000000000000000000000000000000000000000000000052625846058684424\ + 7876381258254151448064135842067326638330711686502352346635185162 + """ + } + + func testRadix09Bottom() { + self.radix = 09 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0000000000000000000000000000000000000000000000005715741718122655\ + 8048777185486326632382030431086760556185430443785630144484523371 + """ + } + + //=----( 10 )--------------------------------------------------------------= + + func testRadix10Top() { + self.radix = 10 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000000000000000000000000000000000000000000000000011579030850545\ + 5567723526024286119531261069242336003260839703036409543150199264 + """ + } + + func testRadix10Bottom() { + self.radix = 10 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0000000000000000000000000000000000000000000000000001407490462640\ + 1341155369551180448584754667373453244490859944217516317499064576 + """ + } + + //=----( 11 )--------------------------------------------------------------= + + func testRadix11Top() { + self.radix = 11 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000000000000000000000000000000000000000000000000000010019774172\ + 675069499548a05a7794803603a4157366204225264092700a8157a30a948720 + """ + } + + func testRadix11Bottom() { + self.radix = 11 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0000000000000000000000000000000000000000000000000000001380227a9a\ + 3a453071005401517000a3500756239a46834284766655651370a28295109a06 + """ + } + + //=----( 12 )--------------------------------------------------------------= + + func testRadix12Top() { + self.radix = 12 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000000000000000000000000000000000000000000000000000000029231468\ + 41b6624b4657b76b759711256462675490811529026b8b03507956b900591aa8 + """ + } + + func testRadix12Bottom() { + self.radix = 12 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 000000000000000000000000000000000000000000000000000000000404b13b\ + 22595a847521b8ab337490660a0b7439b1495399a8b2918a9521301732309054 + """ + } + + //=----( 13 )--------------------------------------------------------------= + + func testRadix13Top() { + self.radix = 13 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000000000000000000000000000000000000000000000000000000000178a92\ + 980701228a277594134c94bb7165a938c70c03a705750115a339820831351c78 + """ + } + + func testRadix13Bottom() { + self.radix = 13 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 00000000000000000000000000000000000000000000000000000000000268a5\ + 1c5770b549c51487a17526804a0a14c0c44bbc981573456a275580297a4a7834 + """ + } + + //=----( 14 )--------------------------------------------------------------= + + func testRadix14Top() { + self.radix = 14 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000000000000000000000000000000000000000000000000000000000001c38\ + 14cbd353812dca285cc376972998797340345da539017abd8236000c88ca00da + """ + } + + func testRadix14Bottom() { + self.radix = 14 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0000000000000000000000000000000000000000000000000000000000000329\ + 76a45325cd6dda6ac91cb8c9bccbbc61488833c2225a774c2da97ab4d4565d3a + """ + } + + //=----( 15 )--------------------------------------------------------------= + + func testRadix15Top() { + self.radix = 15 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000000000000000000000000000000000000000000000000000000000000042\ + 314e1223518107b1362e160a5ad29226b4e3e2d35ea57996aaa3242db02966ae + """ + } + + func testRadix15Bottom() { + self.radix = 15 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0000000000000000000000000000000000000000000000000000000000000007\ + 864d3605e05bd91d94b651ccc4e3078d6edc902745e03953a310b0de5c602701 + """ + } + + //=----( 16 )--------------------------------------------------------------= + + func testRadix16Top() { + self.radix = 16 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e0 + """ + } + + func testRadix16Bottom() { + self.radix = 16 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100 + """ + } + + //=----( 17 )--------------------------------------------------------------= + + func testRadix17Top() { + self.radix = 17 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 05g7d81gc01cdbf42565444eaa12342c35gd9f66bbg36c8d8841baa7a8faab0e + """ + } + + func testRadix17Bottom() { + self.radix = 17 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 00c5b2gcge3c140g4d527274dgd5cg7g58babg3e21bg76739a559151527ce653 + """ + } + + //=----( 18 )--------------------------------------------------------------= + + func testRadix18Top() { + self.radix = 18 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0031fhf5dce9fgc12bg164e9h35028896f83ddhh8be5286c3e9h17360bg1bg32 + """ + } + + func testRadix18Bottom() { + self.radix = 18 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0006e51f0da7284a3bb14747c33cgb1hfa3120c549aec7hh58g39hg075a02c3a + """ + } + + //=----( 19 )--------------------------------------------------------------= + + func testRadix19Top() { + self.radix = 19 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 000237ibab6cg652id30fgh76hdai93dhfh7dhagfdc5eb7f782c55d551ed74g6 + """ + } + + func testRadix19Bottom() { + self.radix = 19 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 000050cae6cb5210060eg1g2iicc8e689a04g25829g2f5bc8c84ea4a8a1348f4 + """ + } + + //=----( 20 )--------------------------------------------------------------= + + func testRadix20Top() { + self.radix = 20 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 000020392d6ac9d1jd12d3a88c61i7ba748483ai05hf66c6a7g42977fbe8ei34 + """ + } + + func testRadix20Bottom() { + self.radix = 20 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 000004hd5e33e5189jajhc248c2a513ae74fba267d1b3d1743i8ebgb30i9318g + """ + } + + //=----( 21 )--------------------------------------------------------------= + + func testRadix21Top() { + self.radix = 21 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000027gdj7593kjg0f1c5cga4aca1e1d5f08h72cebhcbc1c6cek06cf13eaddh + """ + } + + func testRadix21Bottom() { + self.radix = 21 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0000006124cec92463a07f87dgg069g06715hcg4j03fha2f1gafce80g895g09a + """ + } + + //=----( 22 )--------------------------------------------------------------= + + func testRadix22Top() { + self.radix = 22 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000003b5jk54f19beiidebchgec3ffc28aggdd74h75ijdc00i4ea0ji14954c0 + """ + } + + func testRadix22Bottom() { + self.radix = 22 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 000000098djlg8ll6ge66j798kd129gf43e7c6586a31h5a25adg2l78kj3a82b6 + """ + } + + //=----( 23 )--------------------------------------------------------------= + + func testRadix23Top() { + self.radix = 23 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 000000069a79baglcjbdblbk5111bb46b66g2b7a2f596763kmm7c3hbl336kl14 + """ + } + + func testRadix23Bottom() { + self.radix = 23 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 00000000hl580j6lii99g9c5137ji22ab5i41mba3lh6091cakd4h6llil689h12 + """ + } + + //=----( 24 )--------------------------------------------------------------= + + func testRadix24Top() { + self.radix = 24 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 00000000e4eikjgk76jj7i2fbn6ihk3ngef39fb00gjl3086em4k7g3ag5647hh8 + """ + } + + func testRadix24Bottom() { + self.radix = 24 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 000000001h9gbi9kc8ig99kj5lil4in9d6e81la5d0h872fff899ebj57j88732g + """ + } + + //=----( 25 )--------------------------------------------------------------= + + func testRadix25Top() { + self.radix = 25 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 000000001cea1fa4l49o4dnedkkdcnmfc3509hg185baem9bdo6e5b1dediecike + """ + } + + func testRadix25Bottom() { + self.radix = 25 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0000000004e4i6362kk6ad7abh2b4j0log0gbjn96nl1d8j88mh9m36enbbmf381 + """ + } + + //=----( 26 )--------------------------------------------------------------= + + func testRadix26Top() { + self.radix = 26 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000000004dd8f12of8578gn3cho4kjg1nm4ck49ihk7nahjpeie4d78426fjja8 + """ + } + + func testRadix26Bottom() { + self.radix = 26 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0000000000e7a4822n1867n87cpm330nai4o7gj05b5j013bb0in29cncoodh584 + """ + } + + //=----( 27 )--------------------------------------------------------------= + + func testRadix27Top() { + self.radix = 27 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000000000fo7qe0hopd7gqfbj7q7m4jdh2445pb279oj8a0lakof2akafj55n52 + """ + } + + func testRadix27Bottom() { + self.radix = 27 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 00000000001p4pcg5j6ogq1hng5neo9oj2bk10d12on0go5nd0dcnnj04demflba + """ + } + + //=----( 28 )--------------------------------------------------------------= + + func testRadix28Top() { + self.radix = 28 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 000000000028lp360pqr9fgjmgalj15e5kknmk8pd61irgj23bbe6nbafahp3e6o + """ + } + + func testRadix28Bottom() { + self.radix = 28 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 000000000007odiqi7ipkbell34qeml609e642lhrao5n03422ik497coam17kmo + """ + } + + //=----( 29 )--------------------------------------------------------------= + + func testRadix29Top() { + self.radix = 29 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 00000000000acrhqlapaaob766is1eng6erp522m0f5opigage3d3j4k7f9n8ff2 + """ + } + + func testRadix29Bottom() { + self.radix = 29 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0000000000017nr4pcg1heg13dh8cgggmn4q34frqm65gn8ec0j45591bmqfhffb + """ + } + + //=----( 30 )--------------------------------------------------------------= + + func testRadix30Top() { + self.radix = 30 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 000000000001nmr6nq4fe87dse4p4i0ama7co4moqch8081liop9spg2kl9rn95e + """ + } + + func testRadix30Bottom() { + self.radix = 30 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0000000000006g1ldfsednredtimcop3b5l3q70e4kitjnhrn4eql74ecaf5j1mg + """ + } + + //=----( 31 )--------------------------------------------------------------= + + func testRadix31Top() { + self.radix = 31 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 000000000000a30ts5ohp5e917o3nehp8urue2rb4e97icid1me5tcmpil25fi6m + """ + } + + func testRadix31Bottom() { + self.radix = 31 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 000000000000171hhf8063e3r4a99sra00a157pihstia75dmk5kfae5nnn9ab6l + """ + } + + //=----( 32 )--------------------------------------------------------------= + + func testRadix32Top() { + self.radix = 32 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000000000001vvuvnufnunpv3rvdtfkufpf3s7ftrmupqvat7kefpn5sjhu5of0 + """ + } + + func testRadix32Bottom() { + self.radix = 32 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 00000000000007ou3ke1m6gp30bhc58k2c91240f1o6go2oa1440e1g50g1g4080 + """ + } + + //=----( 33 )--------------------------------------------------------------= + + func testRadix33Top() { + self.radix = 33 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000000000000dodf9g17rn5pvw3et1k184sgnb11u6u7uhk2n9b3bhtfwrh14fb + """ + } + + func testRadix33Bottom() { + self.radix = 33 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 00000000000001m3p6weqc5jk0wsb37sv08ileepww3jad5cr0cfhd0g1aq8in3s + """ + } + + //=----( 34 )--------------------------------------------------------------= + + func testRadix34Top() { + self.radix = 34 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 00000000000003304fs1ae3ixjsrahw1k6lt33dlup2jc54b1p3xxaghpss3swhe + """ + } + + func testRadix34Bottom() { + self.radix = 34 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 00000000000000cpwunuqgcm028uqxuqmjst7gk65egpsowcgixwuci6x899aa2k + """ + } + + //=----( 35 )--------------------------------------------------------------= + + func testRadix35Top() { + self.radix = 35 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 00000000000000pcyhqj7yk3vq8j4l4vfa7wes91wah4p1y3op2k48s4pv0y189o + """ + } + + func testRadix35Bottom() { + self.radix = 35 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0000000000000032wujn2mg481jyhidxmv5271ucr21qfj9jdvqm429mwneu6b2v + """ + } + + //=----( 36 )--------------------------------------------------------------= + + func testRadix36Top() { + self.radix = 36 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 000000000000006dp15j43ld5l8i7wvimlj7kxgbfxkxkgmo66lge382296ouqjk + """ + } + + func testRadix36Bottom() { + self.radix = 36 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 000000000000000rx55jlhq7obx1pvd9861yo6c11bed0cd8s8wz2hpvczt00c1s + """ + } +} + //*============================================================================* // MARK: * NBK x Flexible Width x Text x Assertions //*============================================================================* @@ -482,8 +1401,8 @@ private func NBKAssertFromDescription( _ integer: T?, _ description: String, file: StaticString = #file, line: UInt = #line) { //=------------------------------------------= - XCTAssertEqual(T(description), integer, file: file, line: line) - XCTAssertEqual(T(description, radix: 10), integer, file: file, line: line) + XCTAssertEqual(T.init(description), integer, file: file, line: line) + XCTAssertEqual(T.init(description, radix: 10), integer, file: file, line: line) } private func NBKAssertDecodeText ( diff --git a/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Addition.swift b/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Addition.swift deleted file mode 100644 index 2c6bef74..00000000 --- a/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Addition.swift +++ /dev/null @@ -1,142 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if !DEBUG - -import NBKCoreKit -import NBKTwosComplementKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Flexible Width x Addition x IntXL -//*============================================================================* - -final class NBKFlexibleWidthBenchmarksOnAdditionAsIntXL: XCTestCase { - - typealias T = IntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testAdd() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(lhs += rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testAdding() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs + rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Digit - //=------------------------------------------------------------------------= - - func testAddDigit() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(Int.max) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(lhs += rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testAddingDigit() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(Int.max) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs + rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Addition x UIntXL -//*============================================================================* - -final class NBKFlexibleWidthBenchmarksOnAdditionAsUIntXL: XCTestCase { - - typealias T = UIntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testAdd() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(lhs += rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testAdding() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs + rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Digit - //=------------------------------------------------------------------------= - - func testAddDigit() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(UInt.max) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(lhs += rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testAddingDigit() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(UInt.max) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs + rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } -} - -#endif diff --git a/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Bits.swift b/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Bits.swift deleted file mode 100644 index c14ca2c0..00000000 --- a/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Bits.swift +++ /dev/null @@ -1,228 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if !DEBUG - -import NBKCoreKit -import NBKTwosComplementKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Flexible Width x Bits x IntXL -//*============================================================================* - -final class NBKFlexibleWidthBenchmarksOnBitsAsIntXL: XCTestCase { - - typealias T = IntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testInitBit() { - var abc = NBK.blackHoleIdentity(true ) - var xyz = NBK.blackHoleIdentity(false) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(T(bit: abc)) - NBK.blackHole(T(bit: xyz)) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - func testBitWidth() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.bitWidth) - NBK.blackHole(xyz.bitWidth) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - func testNonzeroBitCount() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.nonzeroBitCount) - NBK.blackHole(xyz.nonzeroBitCount) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - func testLeadingZeroBitCount() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.leadingZeroBitCount) - NBK.blackHole(xyz.leadingZeroBitCount) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - func testTrailingZeroBitCount() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.trailingZeroBitCount) - NBK.blackHole(xyz.trailingZeroBitCount) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - func testMostSignificantBit() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.mostSignificantBit) - NBK.blackHole(xyz.mostSignificantBit) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - func testLeastSignificantBit() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.leastSignificantBit) - NBK.blackHole(xyz.leastSignificantBit) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Bits x UIntXL -//*============================================================================* - -final class NBKFlexibleWidthBenchmarksOnBitsAsUIntXL: XCTestCase { - - typealias T = UIntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testInitBit() { - var abc = NBK.blackHoleIdentity(true ) - var xyz = NBK.blackHoleIdentity(false) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(T(bit: abc)) - NBK.blackHole(T(bit: xyz)) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - func testBitWidth() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.bitWidth) - NBK.blackHole(xyz.bitWidth) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - func testNonzeroBitCount() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.nonzeroBitCount) - NBK.blackHole(xyz.nonzeroBitCount) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - func testLeadingZeroBitCount() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.leadingZeroBitCount) - NBK.blackHole(xyz.leadingZeroBitCount) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - func testTrailingZeroBitCount() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.trailingZeroBitCount) - NBK.blackHole(xyz.trailingZeroBitCount) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - func testMostSignificantBit() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.mostSignificantBit) - NBK.blackHole(xyz.mostSignificantBit) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - func testLeastSignificantBit() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.leastSignificantBit) - NBK.blackHole(xyz.leastSignificantBit) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } -} - -#endif diff --git a/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Comparisons.swift b/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Comparisons.swift deleted file mode 100644 index 5a2ebee2..00000000 --- a/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Comparisons.swift +++ /dev/null @@ -1,280 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if !DEBUG - -import NBKCoreKit -import NBKTwosComplementKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Flexible Width x Comparisons x IntXL -//*============================================================================* - -final class NBKFlexibleWidthBenchmarksOnComparisonsAsIntXL: XCTestCase { - - typealias T = IntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testIsZero() { - var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.isZero) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testIsLessThanZero() { - var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.isLessThanZero) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testIsMoreThanZero() { - var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.isMoreThanZero) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testIsPowerOf2() { - var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.isPowerOf2) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testSignum() { - var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.signum()) - NBK.blackHoleInoutIdentity(&abc) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testIsEqualTo() { - var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(lhs == rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testIsLessThan() { - var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(lhs < rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testComparedTo() { - var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(lhs.compared(to: rhs)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testComparedToAtIndex() { - var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[1, 2, 3, 0] as X)) - let xyz = NBK.blackHoleIdentity(1 as Int) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(lhs.compared(to: rhs, at: xyz)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testComparedToDigit() { - var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - var rhs = NBK.blackHoleIdentity(Int.max) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(lhs.compared(to: rhs)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testComparedToDigitAtIndex() { - var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - var rhs = NBK.blackHoleIdentity(3 as Int) - let xyz = NBK.blackHoleIdentity(3 as Int) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(lhs.compared(to: rhs, at: xyz)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Comparisons x UIntXL -//*============================================================================* - -final class NBKFlexibleWidthBenchmarksOnComparisonsAsUIntXL: XCTestCase { - - typealias T = UIntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testIsZero() { - var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.isZero) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testIsLessThanZero() { - var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.isLessThanZero) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testIsMoreThanZero() { - var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.isMoreThanZero) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testIsPowerOf2() { - var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.isPowerOf2) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testSignum() { - var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.signum()) - NBK.blackHoleInoutIdentity(&abc) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testIsEqualTo() { - var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(lhs == rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testIsLessThan() { - var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(lhs < rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testComparedTo() { - var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(lhs.compared(to: rhs)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testComparedToAtIndex() { - var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[1, 2, 3, 0] as X)) - let xyz = NBK.blackHoleIdentity(1 as Int) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(lhs.compared(to: rhs, at: xyz)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testComparedToDigit() { - var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - var rhs = NBK.blackHoleIdentity(UInt.max) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(lhs.compared(to: rhs)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testComparedToDigitAtIndex() { - var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - var rhs = NBK.blackHoleIdentity(UInt( 3)) - let xyz = NBK.blackHoleIdentity(3 as Int) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(lhs.compared(to: rhs, at: xyz)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } -} - -#endif diff --git a/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Complements.swift b/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Complements.swift deleted file mode 100644 index 50ff85d5..00000000 --- a/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Complements.swift +++ /dev/null @@ -1,299 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if !DEBUG - -import NBKCoreKit -import NBKTwosComplementKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Flexible Width x Complements x IntXL -//*============================================================================* - -final class NBKFlexibleWidthBenchmarksOnComplementsAsIntXL: XCTestCase { - - typealias T = IntXL - typealias M = UIntXL - - //=------------------------------------------------------------------------= - // MARK: Tests x Magnitude - //=------------------------------------------------------------------------= - - func testMagnitude() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.magnitude) - NBK.blackHole(xyz.magnitude) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x One's Complement - //=------------------------------------------------------------------------= - - func testOnesComplement() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) - - for _ in 0 ..< 250_000 { - NBK.blackHole(abc.onesComplement()) - NBK.blackHole(xyz.onesComplement()) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - func testOnesComplementInout() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.formOnesComplement()) - NBK.blackHole(xyz.formOnesComplement()) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Two's Complement - //=------------------------------------------------------------------------= - - func testTwosComplement() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.twosComplement()) - NBK.blackHole(xyz.twosComplement()) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - func testTwosComplementInout() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.formTwosComplement()) - NBK.blackHole(xyz.formTwosComplement()) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - func testTwosComplementReportingOverflow() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.twosComplementReportingOverflow()) - NBK.blackHole(xyz.twosComplementReportingOverflow()) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - func testTwosComplementReportingOverflowInout() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.formTwosComplementReportingOverflow()) - NBK.blackHole(xyz.formTwosComplementReportingOverflow()) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - func testTwosComplementSubsequence() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.twosComplementSubsequence(true)) - NBK.blackHole(xyz.twosComplementSubsequence(true)) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - func testTwosComplementSubsequenceInout() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.formTwosComplementSubsequence(true)) - NBK.blackHole(xyz.formTwosComplementSubsequence(true)) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Complements x UIntXL -//*============================================================================* - -final class NBKFlexibleWidthBenchmarksOnComplementsAsUIntXL: XCTestCase { - - typealias T = UIntXL - typealias M = UIntXL - - //=------------------------------------------------------------------------= - // MARK: Tests x Magnitude - //=------------------------------------------------------------------------= - - func testMagnitude() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.magnitude) - NBK.blackHole(xyz.magnitude) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x One's Complement - //=------------------------------------------------------------------------= - - func testOnesComplement() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) - - for _ in 0 ..< 250_000 { - NBK.blackHole(abc.onesComplement()) - NBK.blackHole(xyz.onesComplement()) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - func testOnesComplementInout() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.formOnesComplement()) - NBK.blackHole(xyz.formOnesComplement()) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Two's Complement - //=------------------------------------------------------------------------= - - func testTwosComplement() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) - - for _ in 0 ..< 250_000 { - NBK.blackHole(abc.twosComplement()) - NBK.blackHole(xyz.twosComplement()) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - func testTwosComplementInout() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.formTwosComplement()) - NBK.blackHole(xyz.formTwosComplement()) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - func testTwosComplementReportingOverflow() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) - - for _ in 0 ..< 250_000 { - NBK.blackHole(abc.twosComplementReportingOverflow()) - NBK.blackHole(xyz.twosComplementReportingOverflow()) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - - func testTwosComplementReportingOverflowInout() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.formTwosComplementReportingOverflow()) - NBK.blackHole(xyz.formTwosComplementReportingOverflow()) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - func testTwosComplementSubsequence() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) - - for _ in 0 ..< 250_000 { - NBK.blackHole(abc.twosComplementSubsequence(true)) - NBK.blackHole(xyz.twosComplementSubsequence(true)) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - func testTwosComplementSubsequenceInout() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.formTwosComplementSubsequence(true)) - NBK.blackHole(xyz.formTwosComplementSubsequence(true)) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } -} - -#endif diff --git a/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Division.swift b/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Division.swift deleted file mode 100644 index c2ac9176..00000000 --- a/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Division.swift +++ /dev/null @@ -1,240 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if !DEBUG - -import NBKCoreKit -import NBKTwosComplementKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Flexible Width x Division x IntXL -//*============================================================================* - -final class NBKFlexibleWidthBenchmarksOnDivisionAsIntXL: XCTestCase { - - typealias T = IntXL - typealias M = IntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testQuotientAndRemainder() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) - - for _ in 0 ..< 250_000 { - NBK.blackHole(lhs.quotientAndRemainder(dividingBy: rhs)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testQuotientReportingOverflow() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) - - for _ in 0 ..< 250_000 { - NBK.blackHole(lhs.dividedReportingOverflow(by: rhs)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testRemainderReportingOverflow() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) - - for _ in 0 ..< 250_000 { - NBK.blackHole(lhs.remainderReportingOverflow(dividingBy: rhs)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Digit - //=------------------------------------------------------------------------= - - func testQuotientAndRemainderDividingByDigit() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(Int.max) - - for _ in 0 ..< 250_000 { - NBK.blackHole(lhs.quotientAndRemainder(dividingBy: rhs)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testQuotientDividingByDigitReportingOverflow() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(Int.max) - - for _ in 0 ..< 250_000 { - NBK.blackHole(lhs.dividedReportingOverflow(by: rhs)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testRemainderDividingByDigitReportingOverflow() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(Int.max) - - for _ in 0 ..< 250_000 { - NBK.blackHole(lhs.remainderReportingOverflow(dividingBy: rhs)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Full Width - //=------------------------------------------------------------------------= - - func testDividingFullWidthAs256() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0/2] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0/2, ~0, ~0, ~0, ~0/4] as X)) - - for _ in 0 ..< 250_000 { - NBK.blackHole(rhs.quotientAndRemainder(dividingBy: lhs)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testDividingFullWidthReportingOverflowAs256() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0/2] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0/2, ~0, ~0, ~0, ~0/4] as X)) - - for _ in 0 ..< 250_000 { - NBK.blackHole(rhs.quotientAndRemainderReportingOverflow(dividingBy: lhs)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Division x UIntXL -//*============================================================================* - -final class NBKFlexibleWidthBenchmarksOnDivisionAsUIntXL: XCTestCase { - - typealias T = UIntXL - typealias M = UIntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testQuotientAndRemainder() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) - - for _ in 0 ..< 250_000 { - NBK.blackHole(lhs.quotientAndRemainder(dividingBy: rhs)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testQuotientReportingOverflow() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) - - for _ in 0 ..< 250_000 { - NBK.blackHole(lhs.dividedReportingOverflow(by: rhs)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testRemainderReportingOverflow() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) - - for _ in 0 ..< 250_000 { - NBK.blackHole(lhs.remainderReportingOverflow(dividingBy: rhs)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Digit - //=------------------------------------------------------------------------= - - func testQuotientAndRemainderDividingByDigit() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(UInt.max) - - for _ in 0 ..< 250_000 { - NBK.blackHole(lhs.quotientAndRemainder(dividingBy: rhs)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testQuotientDividingByDigitReportingOverflow() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(UInt.max) - - for _ in 0 ..< 250_000 { - NBK.blackHole(lhs.dividedReportingOverflow(by: rhs)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testRemainderDividingByDigitReportingOverflow() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(UInt.max) - - for _ in 0 ..< 250_000 { - NBK.blackHole(lhs.remainderReportingOverflow(dividingBy: rhs)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Full Width - //=------------------------------------------------------------------------= - - func testDividingFullWidthAs256() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0, ~1, ~0, ~0, ~0] as X)) - - for _ in 0 ..< 250_000 { - NBK.blackHole(rhs.quotientAndRemainder(dividingBy: lhs)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testDividingFullWidthReportingOverflowAs256() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0, ~1, ~0, ~0, ~0] as X)) - - for _ in 0 ..< 250_000 { - NBK.blackHole(rhs.quotientAndRemainderReportingOverflow(dividingBy: lhs)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } -} - -#endif diff --git a/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Logic.swift b/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Logic.swift deleted file mode 100644 index d8148416..00000000 --- a/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Logic.swift +++ /dev/null @@ -1,117 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if !DEBUG - -import NBKCoreKit -import NBKTwosComplementKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Flexible Width x Logic x UIntXL -//*============================================================================* - -final class NBKFlexibleWidthBenchmarksOnLogicAsUIntXL: XCTestCase { - - typealias T = UIntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testNotInout() { - var abc = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.formOnesComplement()) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testNot() { - var abc = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(~abc) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testAndInout() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(lhs &= rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testAnd() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs & rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testOrInout() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(lhs |= rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testOr() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs | rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testXorInout() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(lhs ^= rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testXor() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs ^ rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } -} - -#endif diff --git a/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Multiplication.swift b/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Multiplication.swift deleted file mode 100644 index b714330b..00000000 --- a/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Multiplication.swift +++ /dev/null @@ -1,98 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if !DEBUG - -import NBKCoreKit -import NBKTwosComplementKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Flexible Width x Multiplication x IntXL -//*============================================================================* - -final class NBKFlexibleWidthBenchmarksOnMultiplicationAsIntXL: XCTestCase { - - typealias T = IntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testMultiplied() { - var lhs = NBK.blackHoleIdentity(T(x64:[~1, ~2, ~3, ~4] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[ 1, 2, 3, 4] as X)) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs * rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Digit - //=------------------------------------------------------------------------= - - func testMultipliedByDigit() { - var lhs = NBK.blackHoleIdentity(T(x64:[~1, ~2, ~3, ~4] as X)) - var rhs = NBK.blackHoleIdentity(Int.max) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs * rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Multiplication x UIntXL -//*============================================================================* - -final class NBKFlexibleWidthBenchmarksOnMultiplicationAsUIntXL: XCTestCase { - - typealias T = UIntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testMultiplied() { - var lhs = NBK.blackHoleIdentity(T(x64:[~1, ~2, ~3, ~4] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[ 1, 2, 3, 4] as X)) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs * rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Digit - //=------------------------------------------------------------------------= - - func testMultipliedByDigit() { - var lhs = NBK.blackHoleIdentity(T(x64:[~1, ~2, ~3, ~4] as X)) - var rhs = NBK.blackHoleIdentity(UInt.max) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs * rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } -} - -#endif diff --git a/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Numbers.swift b/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Numbers.swift deleted file mode 100644 index afbbc6a4..00000000 --- a/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Numbers.swift +++ /dev/null @@ -1,816 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if !DEBUG - -import NBKCoreKit -import NBKTwosComplementKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Flexible Width x Numbers x IntXL -//*============================================================================* - -final class NBKFlexibleWidthBenchmarksOnNumbersAsIntXL: XCTestCase { - - typealias T = IntXL - typealias M = UIntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testZero() { - for _ in 0 ..< 100_000 { - NBK.blackHole(T()) - NBK.blackHole(T.zero) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Integers - //=------------------------------------------------------------------------= - - func testToInt() { - var abc = NBK.blackHoleIdentity(T(Int.max)) - - for _ in 0 ..< 50_000 { - NBK.blackHole(Int(abc)) - NBK.blackHole(Int(exactly: abc)) - NBK.blackHole(Int(clamping: abc)) - NBK.blackHole(Int(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testFromInt() { - var abc = NBK.blackHoleIdentity(Int.max) - - for _ in 0 ..< 100_000 { - NBK.blackHole(T(abc)) - NBK.blackHole(T(exactly: abc)) - NBK.blackHole(T(clamping: abc)) - NBK.blackHole(T(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testToUInt() { - var abc = NBK.blackHoleIdentity(T(UInt.max)) - - for _ in 0 ..< 50_000 { - NBK.blackHole(UInt(abc)) - NBK.blackHole(UInt(exactly: abc)) - NBK.blackHole(UInt(clamping: abc)) - NBK.blackHole(UInt(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testFromUInt() { - var abc = NBK.blackHoleIdentity(UInt.max) - - for _ in 0 ..< 100_000 { - NBK.blackHole(T(abc)) - NBK.blackHole(T(exactly: abc)) - NBK.blackHole(T(clamping: abc)) - NBK.blackHole(T(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testToInt8() { - var abc = NBK.blackHoleIdentity(T(Int8.max)) - - for _ in 0 ..< 50_000 { - NBK.blackHole(Int8(abc)) - NBK.blackHole(Int8(exactly: abc)) - NBK.blackHole(Int8(clamping: abc)) - NBK.blackHole(Int8(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testFromInt8() { - var abc = NBK.blackHoleIdentity(Int8.max) - - for _ in 0 ..< 100_000 { - NBK.blackHole(T(abc)) - NBK.blackHole(T(exactly: abc)) - NBK.blackHole(T(clamping: abc)) - NBK.blackHole(T(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testToUInt8() { - var abc = NBK.blackHoleIdentity(T(UInt8.max)) - - for _ in 0 ..< 50_000 { - NBK.blackHole(UInt8(abc)) - NBK.blackHole(UInt8(exactly: abc)) - NBK.blackHole(UInt8(clamping: abc)) - NBK.blackHole(UInt8(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testFromUInt8() { - var abc = NBK.blackHoleIdentity(UInt8.max) - - for _ in 0 ..< 100_000 { - NBK.blackHole(T(abc)) - NBK.blackHole(T(exactly: abc)) - NBK.blackHole(T(clamping: abc)) - NBK.blackHole(T(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testToInt16() { - var abc = NBK.blackHoleIdentity(T(Int16.max)) - - for _ in 0 ..< 50_000 { - NBK.blackHole(Int16(abc)) - NBK.blackHole(Int16(exactly: abc)) - NBK.blackHole(Int16(clamping: abc)) - NBK.blackHole(Int16(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testFromInt16() { - var abc = NBK.blackHoleIdentity(Int16.max) - - for _ in 0 ..< 100_000 { - NBK.blackHole(T(abc)) - NBK.blackHole(T(exactly: abc)) - NBK.blackHole(T(clamping: abc)) - NBK.blackHole(T(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testToUInt16() { - var abc = NBK.blackHoleIdentity(T(UInt16.max)) - - for _ in 0 ..< 50_000 { - NBK.blackHole(UInt16(abc)) - NBK.blackHole(UInt16(exactly: abc)) - NBK.blackHole(UInt16(clamping: abc)) - NBK.blackHole(UInt16(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testFromUInt16() { - var abc = NBK.blackHoleIdentity(UInt16.max) - - for _ in 0 ..< 100_000 { - NBK.blackHole(T(abc)) - NBK.blackHole(T(exactly: abc)) - NBK.blackHole(T(clamping: abc)) - NBK.blackHole(T(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testToInt32() { - var abc = NBK.blackHoleIdentity(T(Int32.max)) - - for _ in 0 ..< 50_000 { - NBK.blackHole(Int32(abc)) - NBK.blackHole(Int32(exactly: abc)) - NBK.blackHole(Int32(clamping: abc)) - NBK.blackHole(Int32(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testFromInt32() { - var abc = NBK.blackHoleIdentity(Int32.max) - - for _ in 0 ..< 100_000 { - NBK.blackHole(T(abc)) - NBK.blackHole(T(exactly: abc)) - NBK.blackHole(T(clamping: abc)) - NBK.blackHole(T(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testToUInt32() { - var abc = NBK.blackHoleIdentity(T(UInt32.max)) - - for _ in 0 ..< 50_000 { - NBK.blackHole(UInt32(abc)) - NBK.blackHole(UInt32(exactly: abc)) - NBK.blackHole(UInt32(clamping: abc)) - NBK.blackHole(UInt32(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testFromUInt32() { - var abc = NBK.blackHoleIdentity(UInt32.max) - - for _ in 0 ..< 100_000 { - NBK.blackHole(T(abc)) - NBK.blackHole(T(exactly: abc)) - NBK.blackHole(T(clamping: abc)) - NBK.blackHole(T(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testToInt64() { - var abc = NBK.blackHoleIdentity(T(Int64.max)) - - for _ in 0 ..< 50_000 { - NBK.blackHole(Int64(abc)) - NBK.blackHole(Int64(exactly: abc)) - NBK.blackHole(Int64(clamping: abc)) - NBK.blackHole(Int64(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testFromInt64() { - var abc = NBK.blackHoleIdentity(Int64.max) - - for _ in 0 ..< 100_000 { - NBK.blackHole(T(abc)) - NBK.blackHole(T(exactly: abc)) - NBK.blackHole(T(clamping: abc)) - NBK.blackHole(T(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testToUInt64() { - var abc = NBK.blackHoleIdentity(T(UInt64.max)) - - for _ in 0 ..< 50_000 { - NBK.blackHole(UInt64(abc)) - NBK.blackHole(UInt64(exactly: abc)) - NBK.blackHole(UInt64(clamping: abc)) - NBK.blackHole(UInt64(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testFromUInt64() { - var abc = NBK.blackHoleIdentity(UInt64.max) - - for _ in 0 ..< 100_000 { - NBK.blackHole(T(abc)) - NBK.blackHole(T(exactly: abc)) - NBK.blackHole(T(clamping: abc)) - NBK.blackHole(T(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Complements - //=------------------------------------------------------------------------= - - func testToDigit() { - var abc = NBK.blackHoleIdentity(T(T.Digit.max)) - - for _ in 0 ..< 50_000 { - NBK.blackHole(T.Digit(abc)) - NBK.blackHole(T.Digit(exactly: abc)) - NBK.blackHole(T.Digit(clamping: abc)) - NBK.blackHole(T.Digit(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testFromDigit() { - var abc = NBK.blackHoleIdentity(T.Digit.max) - - for _ in 0 ..< 100_000 { - NBK.blackHole(T(digit: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testToMagnitude() { - var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - - for _ in 0 ..< 50_000 { - NBK.blackHole(M(abc)) - NBK.blackHole(M(exactly: abc)) - NBK.blackHole(M(clamping: abc)) - NBK.blackHole(M(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testFromMagnitude() { - var abc = NBK.blackHoleIdentity(M(x64:[0, 1, 2, 3] as X)) - - for _ in 0 ..< 100_000 { - NBK.blackHole(T(abc)) - NBK.blackHole(T(exactly: abc)) - NBK.blackHole(T(clamping: abc)) - NBK.blackHole(T(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Float - //=------------------------------------------------------------------------= - - // TODO: brrr - func testToFloat16() { - var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - - for _ in 0 ..< 1_000 { - NBK.blackHole(Float16(abc)) - NBK.blackHole(Float16(exactly: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testFromFloat16() { - var abc = NBK.blackHoleIdentity(Float16(123)) - - for _ in 0 ..< 100_000 { - NBK.blackHole(T(abc)) - NBK.blackHole(T(exactly: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - // TODO: brrr - func testToFloat32() { - var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - - for _ in 0 ..< 1_000 { - NBK.blackHole(Float32(abc)) - NBK.blackHole(Float32(exactly: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testFromFloat32() { - var abc = NBK.blackHoleIdentity(Float32(123)) - - for _ in 0 ..< 100_000 { - NBK.blackHole(T(abc)) - NBK.blackHole(T(exactly: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - // TODO: brrr - func testToFloat64() { - var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - - for _ in 0 ..< 1_000 { - NBK.blackHole(Float64(abc)) - NBK.blackHole(Float64(exactly: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testFromFloat64() { - var abc = NBK.blackHoleIdentity(Float64(123)) - - for _ in 0 ..< 100_000 { - NBK.blackHole(T(abc)) - NBK.blackHole(T(exactly: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Sign & Magnitude - //=------------------------------------------------------------------------= - - func testSignAndMagnitude() { - var abc = NBK.blackHoleIdentity((sign: FloatingPointSign.plus, magnitude: M(x64:[0, 1, 2, 3] as X))) - var xyz = NBK.blackHoleIdentity((sign: FloatingPointSign.minus, magnitude: M(x64:[0, 1, 2, 3] as X))) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(T(sign: abc.sign, magnitude: abc.magnitude)) - NBK.blackHoleInoutIdentity(&abc) - - NBK.blackHole(T(sign: xyz.sign, magnitude: xyz.magnitude)) - NBK.blackHoleInoutIdentity(&xyz) - } - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Numbers x UIntXL -//*============================================================================* - -final class NBKFlexibleWidthBenchmarksOnNumbersAsUIntXL: XCTestCase { - - typealias T = UIntXL - typealias M = UIntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testZero() { - for _ in 0 ..< 100_000 { - NBK.blackHole(T()) - NBK.blackHole(T.zero) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Integers - //=------------------------------------------------------------------------= - - func testToInt() { - var abc = NBK.blackHoleIdentity(T(Int.max)) - - for _ in 0 ..< 50_000 { - NBK.blackHole(Int(abc)) - NBK.blackHole(Int(exactly: abc)) - NBK.blackHole(Int(clamping: abc)) - NBK.blackHole(Int(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testFromInt() { - var abc = NBK.blackHoleIdentity(Int.max) - - for _ in 0 ..< 100_000 { - NBK.blackHole(T(abc)) - NBK.blackHole(T(exactly: abc)) - NBK.blackHole(T(clamping: abc)) - NBK.blackHole(T(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testToUInt() { - var abc = NBK.blackHoleIdentity(T(UInt.max)) - - for _ in 0 ..< 50_000 { - NBK.blackHole(UInt(abc)) - NBK.blackHole(UInt(exactly: abc)) - NBK.blackHole(UInt(clamping: abc)) - NBK.blackHole(UInt(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testFromUInt() { - var abc = NBK.blackHoleIdentity(UInt.max) - - for _ in 0 ..< 100_000 { - NBK.blackHole(T(abc)) - NBK.blackHole(T(exactly: abc)) - NBK.blackHole(T(clamping: abc)) - NBK.blackHole(T(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testToInt8() { - var abc = NBK.blackHoleIdentity(T(Int8.max)) - - for _ in 0 ..< 50_000 { - NBK.blackHole(Int8(abc)) - NBK.blackHole(Int8(exactly: abc)) - NBK.blackHole(Int8(clamping: abc)) - NBK.blackHole(Int8(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testFromInt8() { - var abc = NBK.blackHoleIdentity(Int8.max) - - for _ in 0 ..< 100_000 { - NBK.blackHole(T(abc)) - NBK.blackHole(T(exactly: abc)) - NBK.blackHole(T(clamping: abc)) - NBK.blackHole(T(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testToUInt8() { - var abc = NBK.blackHoleIdentity(T(UInt8.max)) - - for _ in 0 ..< 50_000 { - NBK.blackHole(UInt8(abc)) - NBK.blackHole(UInt8(exactly: abc)) - NBK.blackHole(UInt8(clamping: abc)) - NBK.blackHole(UInt8(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testFromUInt8() { - var abc = NBK.blackHoleIdentity(UInt8.max) - - for _ in 0 ..< 100_000 { - NBK.blackHole(T(abc)) - NBK.blackHole(T(exactly: abc)) - NBK.blackHole(T(clamping: abc)) - NBK.blackHole(T(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testToInt16() { - var abc = NBK.blackHoleIdentity(T(Int16.max)) - - for _ in 0 ..< 50_000 { - NBK.blackHole(Int16(abc)) - NBK.blackHole(Int16(exactly: abc)) - NBK.blackHole(Int16(clamping: abc)) - NBK.blackHole(Int16(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testFromInt16() { - var abc = NBK.blackHoleIdentity(Int16.max) - - for _ in 0 ..< 100_000 { - NBK.blackHole(T(abc)) - NBK.blackHole(T(exactly: abc)) - NBK.blackHole(T(clamping: abc)) - NBK.blackHole(T(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testToUInt16() { - var abc = NBK.blackHoleIdentity(T(UInt16.max)) - - for _ in 0 ..< 50_000 { - NBK.blackHole(UInt16(abc)) - NBK.blackHole(UInt16(exactly: abc)) - NBK.blackHole(UInt16(clamping: abc)) - NBK.blackHole(UInt16(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testFromUInt16() { - var abc = NBK.blackHoleIdentity(UInt16.max) - - for _ in 0 ..< 100_000 { - NBK.blackHole(T(abc)) - NBK.blackHole(T(exactly: abc)) - NBK.blackHole(T(clamping: abc)) - NBK.blackHole(T(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testToInt32() { - var abc = NBK.blackHoleIdentity(T(Int32.max)) - - for _ in 0 ..< 50_000 { - NBK.blackHole(Int32(abc)) - NBK.blackHole(Int32(exactly: abc)) - NBK.blackHole(Int32(clamping: abc)) - NBK.blackHole(Int32(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testFromInt32() { - var abc = NBK.blackHoleIdentity(Int32.max) - - for _ in 0 ..< 100_000 { - NBK.blackHole(T(abc)) - NBK.blackHole(T(exactly: abc)) - NBK.blackHole(T(clamping: abc)) - NBK.blackHole(T(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testToUInt32() { - var abc = NBK.blackHoleIdentity(T(UInt32.max)) - - for _ in 0 ..< 50_000 { - NBK.blackHole(UInt32(abc)) - NBK.blackHole(UInt32(exactly: abc)) - NBK.blackHole(UInt32(clamping: abc)) - NBK.blackHole(UInt32(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testFromUInt32() { - var abc = NBK.blackHoleIdentity(UInt32.max) - - for _ in 0 ..< 100_000 { - NBK.blackHole(T(abc)) - NBK.blackHole(T(exactly: abc)) - NBK.blackHole(T(clamping: abc)) - NBK.blackHole(T(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testToInt64() { - var abc = NBK.blackHoleIdentity(T(Int64.max)) - - for _ in 0 ..< 50_000 { - NBK.blackHole(Int64(abc)) - NBK.blackHole(Int64(exactly: abc)) - NBK.blackHole(Int64(clamping: abc)) - NBK.blackHole(Int64(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testFromInt64() { - var abc = NBK.blackHoleIdentity(Int64.max) - - for _ in 0 ..< 100_000 { - NBK.blackHole(T(abc)) - NBK.blackHole(T(exactly: abc)) - NBK.blackHole(T(clamping: abc)) - NBK.blackHole(T(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testToUInt64() { - var abc = NBK.blackHoleIdentity(T(UInt64.max)) - - for _ in 0 ..< 50_000 { - NBK.blackHole(UInt64(abc)) - NBK.blackHole(UInt64(exactly: abc)) - NBK.blackHole(UInt64(clamping: abc)) - NBK.blackHole(UInt64(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testFromUInt64() { - var abc = NBK.blackHoleIdentity(UInt64.max) - - for _ in 0 ..< 100_000 { - NBK.blackHole(T(abc)) - NBK.blackHole(T(exactly: abc)) - NBK.blackHole(T(clamping: abc)) - NBK.blackHole(T(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Complements - //=------------------------------------------------------------------------= - - func testToDigit() { - var abc = NBK.blackHoleIdentity(T(T.Digit.max)) - - for _ in 0 ..< 50_000 { - NBK.blackHole(T.Digit(abc)) - NBK.blackHole(T.Digit(exactly: abc)) - NBK.blackHole(T.Digit(clamping: abc)) - NBK.blackHole(T.Digit(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testFromDigit() { - var abc = NBK.blackHoleIdentity(T.Digit.max) - - for _ in 0 ..< 100_000 { - NBK.blackHole(T(digit: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testToMagnitude() { - var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - - for _ in 0 ..< 50_000 { - NBK.blackHole(M(abc)) - NBK.blackHole(M(exactly: abc)) - NBK.blackHole(M(clamping: abc)) - NBK.blackHole(M(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testFromMagnitude() { - var abc = NBK.blackHoleIdentity(M(x64:[0, 1, 2, 3] as X)) - - for _ in 0 ..< 100_000 { - NBK.blackHole(T(abc)) - NBK.blackHole(T(exactly: abc)) - NBK.blackHole(T(clamping: abc)) - NBK.blackHole(T(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Float - //=------------------------------------------------------------------------= - - // TODO: brrr - func testToFloat16() { - var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - - for _ in 0 ..< 1_000 { - NBK.blackHole(Float16(abc)) - NBK.blackHole(Float16(exactly: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testFromFloat16() { - var abc = NBK.blackHoleIdentity(Float16(123)) - - for _ in 0 ..< 100_000 { - NBK.blackHole(T(abc)) - NBK.blackHole(T(exactly: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - // TODO: brrr - func testToFloat32() { - var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - - for _ in 0 ..< 1_000 { - NBK.blackHole(Float32(abc)) - NBK.blackHole(Float32(exactly: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testFromFloat32() { - var abc = NBK.blackHoleIdentity(Float32(123)) - - for _ in 0 ..< 100_000 { - NBK.blackHole(T(abc)) - NBK.blackHole(T(exactly: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - // TODO: brrr - func testToFloat64() { - var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - - for _ in 0 ..< 1_000 { - NBK.blackHole(Float64(abc)) - NBK.blackHole(Float64(exactly: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testFromFloat64() { - var abc = NBK.blackHoleIdentity(Float64(123)) - - for _ in 0 ..< 100_000 { - NBK.blackHole(T(abc)) - NBK.blackHole(T(exactly: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Sign & Magnitude - //=------------------------------------------------------------------------= - - func testSignAndMagnitude() { - var abc = NBK.blackHoleIdentity((sign: FloatingPointSign.plus, magnitude: M(x64:[0, 1, 2, 3] as X))) - var xyz = NBK.blackHoleIdentity((sign: FloatingPointSign.minus, magnitude: M(x64:[0, 1, 2, 3] as X))) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(T(sign: abc.sign, magnitude: abc.magnitude)) - NBK.blackHoleInoutIdentity(&abc) - - NBK.blackHole(T(sign: xyz.sign, magnitude: xyz.magnitude)) - NBK.blackHoleInoutIdentity(&xyz) - } - } -} - -#endif diff --git a/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Shifts.swift b/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Shifts.swift deleted file mode 100644 index 819314c7..00000000 --- a/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Shifts.swift +++ /dev/null @@ -1,284 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if !DEBUG - -import NBKCoreKit -import NBKTwosComplementKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Flexible Width x Shifts x IntXL -//*============================================================================* - -final class NBKFlexibleWidthBenchmarksOnShiftsAsIntXL: XCTestCase { - - typealias T = IntXL - - //=------------------------------------------------------------------------= - // MARK: Tests x Left - //=------------------------------------------------------------------------= - - func testBitshiftingLeft() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(UInt.bitWidth * 3/2) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs << rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testBitshiftingLeftByWords() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs.bitshiftedLeft(words: rhs.words)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testBitshiftingLeftByWordsAndBits() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs.bitshiftedLeft(words: rhs.words, bits: rhs.bits)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Right - //=------------------------------------------------------------------------= - - func testBitshiftingRight() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(UInt.bitWidth * 3/2) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs >> rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testBitshiftingRightByWords() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs.bitshiftedRight(words: rhs.words)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testBitshiftingRightByWordsAndBits() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs.bitshiftedRight(words: rhs.words, bits: rhs.bits)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x In Both Directions - //=------------------------------------------------------------------------= - - func testBitshiftingInBothDirectionsInout() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(UInt.bitWidth * 3/2) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs.bitshiftLeft (by: rhs)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - - NBK.blackHole(lhs.bitshiftRight(by: rhs)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testBitshiftingInBothDirectionsByWordsInout() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs.bitshiftLeft (words: rhs.words)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - - NBK.blackHole(lhs.bitshiftRight(words: rhs.words)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testBitshiftingInBothDirectionsByWordsAndBitsInout() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs.bitshiftLeft (words: rhs.words, bits: rhs.bits)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - - NBK.blackHole(lhs.bitshiftRight(words: rhs.words, bits: rhs.bits)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Shifts x UIntXL -//*============================================================================* - -final class NBKFlexibleWidthBenchmarksOnShiftsAsUIntXL: XCTestCase { - - typealias T = UIntXL - - //=------------------------------------------------------------------------= - // MARK: Tests x Left - //=------------------------------------------------------------------------= - - func testBitshiftingLeft() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(UInt.bitWidth * 3/2) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs << rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testBitshiftingLeftByWords() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs.bitshiftedLeft(words: rhs.words)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testBitshiftingLeftByWordsAndBits() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs.bitshiftedLeft(words: rhs.words, bits: rhs.bits)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Right - //=------------------------------------------------------------------------= - - func testBitshiftingRight() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(UInt.bitWidth * 3/2) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs >> rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testBitshiftingRightByWords() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs.bitshiftedRight(words: rhs.words)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testBitshiftingRightByWordsAndBits() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs.bitshiftedRight(words: rhs.words, bits: rhs.bits)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x In Both Directions - //=------------------------------------------------------------------------= - - func testBitshiftingInBothDirectionsInout() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(UInt.bitWidth * 3/2) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs.bitshiftLeft (by: rhs)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - - NBK.blackHole(lhs.bitshiftRight(by: rhs)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testBitshiftingInBothDirectionsByWordsInout() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs.bitshiftLeft (words: rhs.words)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - - NBK.blackHole(lhs.bitshiftRight(words: rhs.words)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testBitshiftingInBothDirectionsByWordsAndBitsInout() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs.bitshiftLeft (words: rhs.words, bits: rhs.bits)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - - NBK.blackHole(lhs.bitshiftRight(words: rhs.words, bits: rhs.bits)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } -} - -#endif diff --git a/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Subtraction.swift b/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Subtraction.swift deleted file mode 100644 index 2a789654..00000000 --- a/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Subtraction.swift +++ /dev/null @@ -1,142 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if !DEBUG - -import NBKCoreKit -import NBKTwosComplementKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Flexible Width x Subtraction x IntXL -//*============================================================================* - -final class NBKFlexibleWidthBenchmarksOnSubtractionAsIntXL: XCTestCase { - - typealias T = IntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testSubtract() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(lhs -= rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testSubtracting() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs - rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Digit - //=------------------------------------------------------------------------= - - func testSubtractDigit() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(Int.max) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(lhs -= rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testSubtractingDigit() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(Int.max) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs - rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Subtraction x UIntXL -//*============================================================================* - -final class NBKFlexibleWidthBenchmarksOnSubtractionAsUIntXL: XCTestCase { - - typealias T = UIntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testSubtract() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(lhs -= rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testSubtracting() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs - rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Digit - //=------------------------------------------------------------------------= - - func testSubtractDigit() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(UInt.max) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(lhs -= rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testSubtractingDigit() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(UInt.max) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs - rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } -} - -#endif diff --git a/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Text.swift b/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Text.swift deleted file mode 100644 index 7d8b0a36..00000000 --- a/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Text.swift +++ /dev/null @@ -1,200 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if !DEBUG - -import NBKCoreKit -import NBKTwosComplementKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Flexible Width x Text x IntXL -//*============================================================================* - -final class NBKFlexibleWidthBenchmarksOnTextAsIntXL: XCTestCase { - - typealias T = IntXL - - //=------------------------------------------------------------------------= - // MARK: State - //=------------------------------------------------------------------------= - - static let decoded = NBK.blackHoleIdentity(T(encoded, radix: 16)!) - static let encoded = NBK.blackHoleIdentity(String(repeating: "1", count: 64)) - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testDecodingRadix10() { - var radix = NBK.blackHoleIdentity(10) - var encoded = NBK.blackHoleIdentity(Self.encoded) - - for _ in 0 ..< 250_000 { - NBK.blackHole(T(encoded, radix: radix)!) - NBK.blackHoleInoutIdentity(&radix) - NBK.blackHoleInoutIdentity(&encoded) - } - } - - func testDecodingRadix16() { - var radix = NBK.blackHoleIdentity(16) - var encoded = NBK.blackHoleIdentity(Self.encoded) - - for _ in 0 ..< 250_000 { - NBK.blackHole(T(encoded, radix: radix)!) - NBK.blackHoleInoutIdentity(&radix) - NBK.blackHoleInoutIdentity(&encoded) - } - } - - func testEncodingRadix10() { - var radix = NBK.blackHoleIdentity(10) - var decoded = NBK.blackHoleIdentity(Self.decoded) - - for _ in 0 ..< 250_000 { - NBK.blackHole(String(decoded, radix: radix)) - NBK.blackHoleInoutIdentity(&radix) - NBK.blackHoleInoutIdentity(&decoded) - } - } - - func testEncodingRadix16() { - var radix = NBK.blackHoleIdentity(16) - var decoded = NBK.blackHoleIdentity(Self.decoded) - - for _ in 0 ..< 250_000 { - NBK.blackHole(String(decoded, radix: radix)) - NBK.blackHoleInoutIdentity(&radix) - NBK.blackHoleInoutIdentity(&decoded) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Swift Standard Library Methods - //=------------------------------------------------------------------------= - - func testEncodingUsingSwiftStdlibRadix10() { - var radix = NBK.blackHoleIdentity(10) - var decoded = NBK.blackHoleIdentity(Self.decoded) - - for _ in 0 ..< 1_000 { - NBK.blackHole(NBK.descriptionAsStdlib(decoded, radix: radix)) - NBK.blackHoleInoutIdentity(&radix) - NBK.blackHoleInoutIdentity(&decoded) - } - } - - func testEncodingUsingSwiftStdlibRadix16() { - var radix = NBK.blackHoleIdentity(16) - var decoded = NBK.blackHoleIdentity(Self.decoded) - - for _ in 0 ..< 1_000 { - NBK.blackHole(NBK.descriptionAsStdlib(decoded, radix: radix)) - NBK.blackHoleInoutIdentity(&radix) - NBK.blackHoleInoutIdentity(&decoded) - } - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Text x UIntXL -//*============================================================================* - -final class NBKFlexibleWidthBenchmarksOnTextAsUIntXL: XCTestCase { - - typealias T = UIntXL - - //=------------------------------------------------------------------------= - // MARK: State - //=------------------------------------------------------------------------= - - static let decoded = NBK.blackHoleIdentity(T(encoded, radix: 16)!) - static let encoded = NBK.blackHoleIdentity(String(repeating: "1", count: 64)) - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testDecodingRadix10() { - var radix = NBK.blackHoleIdentity(10) - var encoded = NBK.blackHoleIdentity(Self.encoded) - - for _ in 0 ..< 250_000 { - NBK.blackHole(T(encoded, radix: radix)!) - NBK.blackHoleInoutIdentity(&radix) - NBK.blackHoleInoutIdentity(&encoded) - } - } - - func testDecodingRadix16() { - var radix = NBK.blackHoleIdentity(16) - var encoded = NBK.blackHoleIdentity(Self.encoded) - - for _ in 0 ..< 250_000 { - NBK.blackHole(T(encoded, radix: radix)!) - NBK.blackHoleInoutIdentity(&radix) - NBK.blackHoleInoutIdentity(&encoded) - } - } - - func testEncodingRadix10() { - var radix = NBK.blackHoleIdentity(10) - var decoded = NBK.blackHoleIdentity(Self.decoded) - - for _ in 0 ..< 250_000 { - NBK.blackHole(String(decoded, radix: radix)) - NBK.blackHoleInoutIdentity(&radix) - NBK.blackHoleInoutIdentity(&decoded) - } - } - - func testEncodingRadix16() { - var radix = NBK.blackHoleIdentity(16) - var decoded = NBK.blackHoleIdentity(Self.decoded) - - for _ in 0 ..< 250_000 { - NBK.blackHole(String(decoded, radix: radix)) - NBK.blackHoleInoutIdentity(&radix) - NBK.blackHoleInoutIdentity(&decoded) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Swift Standard Library Methods - //=------------------------------------------------------------------------= - - func testEncodingUsingSwiftStdlibRadix10() { - var radix = NBK.blackHoleIdentity(10) - var decoded = NBK.blackHoleIdentity(Self.decoded) - - for _ in 0 ..< 1_000 { - NBK.blackHole(NBK.descriptionAsStdlib(decoded, radix: radix)) - NBK.blackHoleInoutIdentity(&radix) - NBK.blackHoleInoutIdentity(&decoded) - } - } - - func testEncodingUsingSwiftStdlibRadix16() { - var radix = NBK.blackHoleIdentity(16) - var decoded = NBK.blackHoleIdentity(Self.decoded) - - for _ in 0 ..< 1_000 { - NBK.blackHole(NBK.descriptionAsStdlib(decoded, radix: radix)) - NBK.blackHoleInoutIdentity(&radix) - NBK.blackHoleInoutIdentity(&decoded) - } - } -} - -#endif diff --git a/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Words.swift b/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Words.swift deleted file mode 100644 index faacb817..00000000 --- a/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth+Words.swift +++ /dev/null @@ -1,72 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if !DEBUG - -import NBKCoreKit -import NBKTwosComplementKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Flexible Width x Words x IntXL -//*============================================================================* - -final class NBKFlexibleWidthBenchmarksOnWordsAsIntXL: XCTestCase { - - typealias T = IntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testFromWords() { - var abc = NBK.blackHoleIdentity([ 0, 0, 0, 0] as W) - var xyz = NBK.blackHoleIdentity([~0, ~0, ~0, ~0] as W) - - for _ in 0 ..< 250_000 { - NBK.blackHole(T(words: abc)) - NBK.blackHole(T(words: xyz)) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Words x UIntXL -//*============================================================================* - -final class NBKFlexibleWidthBenchmarksOnWordsAsUIntXL: XCTestCase { - - typealias T = UIntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testFromWords() { - var abc = NBK.blackHoleIdentity([ 0, 0, 0, 0] as W) - var xyz = NBK.blackHoleIdentity([~0, ~0, ~0, ~0] as W) - - for _ in 0 ..< 250_000 { - NBK.blackHole(T(words: abc)) - NBK.blackHole(T(words: xyz)) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } -} - -#endif diff --git a/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth.swift b/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth.swift deleted file mode 100644 index e8959f9b..00000000 --- a/Tests/NBKTwosComplementKitBenchmarks/NBKFlexibleWidth.swift +++ /dev/null @@ -1,68 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit -import NBKTwosComplementKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Flexible Width x Initializers x IntXL -//*============================================================================* - -extension NBKFlexibleWidth { - - //=------------------------------------------------------------------------= - // MARK: Details x Numbers - //=------------------------------------------------------------------------= - - static let min256 = Self(x64:[ 0, 0, 0, ~0/2 + 1] as X) - static let max256 = Self(x64:[~0, ~0, ~0, ~0/2 + 0] as X) - - //=------------------------------------------------------------------------= - // MARK: Details x Limbs - //=------------------------------------------------------------------------= - - init(x32: [UInt32]) { - self.init(words: NBKChunkedInt(x32)) - } - - init(x64: [UInt64]) { - self.init(words: NBKChunkedInt(x64)) - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Initializers x UIntXL -//*============================================================================* - -extension NBKFlexibleWidth.Magnitude { - - //=------------------------------------------------------------------------= - // MARK: Details x Numbers - //=------------------------------------------------------------------------= - - static let min256 = Self(x64:[ 0, 0, 0, 0] as X) - static let max256 = Self(x64:[~0, ~0, ~0, ~0] as X) - - //=------------------------------------------------------------------------= - // MARK: Details x Limbs - //=------------------------------------------------------------------------= - - init(x32: [UInt32]) { - self.init(words: NBKChunkedInt(x32)) - } - - init(x64: [UInt64]) { - self.init(words: NBKChunkedInt(x64)) - } -} diff --git a/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Addition.swift b/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Addition.swift deleted file mode 100644 index b8e6c977..00000000 --- a/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Addition.swift +++ /dev/null @@ -1,220 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if DEBUG - -import NBKCoreKit -import NBKTwosComplementKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Flexible Width x Addition x IntXL -//*============================================================================* - -final class NBKFlexibleWidthTestsOnAdditionAsIntXL: XCTestCase { - - typealias T = IntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testAdding() { - NBKAssertAddition(T( 1), T( 2), Int(0), T( 3)) - NBKAssertAddition(T( 1), T( 1), Int(0), T( 2)) - NBKAssertAddition(T( 1), T( 0), Int(0), T( 1)) - NBKAssertAddition(T( 1), T(-1), Int(0), T( 0)) - NBKAssertAddition(T( 1), T(-2), Int(0), T(-1)) - - NBKAssertAddition(T( 0), T( 2), Int(0), T( 2)) - NBKAssertAddition(T( 0), T( 1), Int(0), T( 1)) - NBKAssertAddition(T( 0), T( 0), Int(0), T( 0)) - NBKAssertAddition(T( 0), T(-1), Int(0), T(-1)) - NBKAssertAddition(T( 0), T(-2), Int(0), T(-2)) - - NBKAssertAddition(T(-1), T( 2), Int(0), T( 1)) - NBKAssertAddition(T(-1), T( 1), Int(0), T( 0)) - NBKAssertAddition(T(-1), T( 0), Int(0), T(-1)) - NBKAssertAddition(T(-1), T(-1), Int(0), T(-2)) - NBKAssertAddition(T(-1), T(-2), Int(0), T(-3)) - } - - func testAddingAtIndex() { - NBKAssertAddition(T(words:[ 0, 0, 0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[ 1, 2, 3, 0] as W)) - NBKAssertAddition(T(words:[~0, 0, 0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[ 0, 3, 3, 0] as W)) - NBKAssertAddition(T(words:[~0, ~0, 0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[ 0, 2, 4, 0] as W)) - NBKAssertAddition(T(words:[~0, ~0, ~0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[ 0, 2, 3, 1] as W)) - - NBKAssertAddition(T(words:[ 0, 0, 0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[ 0, 1, 2, 3] as W)) - NBKAssertAddition(T(words:[~0, 0, 0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[~0, 1, 2, 3] as W)) - NBKAssertAddition(T(words:[~0, ~0, 0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[~0, 0, 3, 3] as W)) - NBKAssertAddition(T(words:[~0, ~0, ~0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[~0, 0, 2, 4] as W)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Digit - //=------------------------------------------------------------------------= - - func testAddingDigit() { - NBKAssertAdditionByDigit(T( 1), Int( 2), Int(0), T( 3)) - NBKAssertAdditionByDigit(T( 1), Int( 1), Int(0), T( 2)) - NBKAssertAdditionByDigit(T( 1), Int( 0), Int(0), T( 1)) - NBKAssertAdditionByDigit(T( 1), Int(-1), Int(0), T( 0)) - NBKAssertAdditionByDigit(T( 1), Int(-2), Int(0), T(-1)) - - NBKAssertAdditionByDigit(T( 0), Int( 2), Int(0), T( 2)) - NBKAssertAdditionByDigit(T( 0), Int( 1), Int(0), T( 1)) - NBKAssertAdditionByDigit(T( 0), Int( 0), Int(0), T( 0)) - NBKAssertAdditionByDigit(T( 0), Int(-1), Int(0), T(-1)) - NBKAssertAdditionByDigit(T( 0), Int(-2), Int(0), T(-2)) - - NBKAssertAdditionByDigit(T(-1), Int( 2), Int(0), T( 1)) - NBKAssertAdditionByDigit(T(-1), Int( 1), Int(0), T( 0)) - NBKAssertAdditionByDigit(T(-1), Int( 0), Int(0), T(-1)) - NBKAssertAdditionByDigit(T(-1), Int(-1), Int(0), T(-2)) - NBKAssertAdditionByDigit(T(-1), Int(-2), Int(0), T(-3)) - } - - func testAddingDigitAtIndex() { - NBKAssertAdditionByDigit(T(words:[ 0, 0, 0, 0] as W), Int(3), Int(0), T(words:[ 3, 0, 0, 0] as W)) - NBKAssertAdditionByDigit(T(words:[~0, 0, 0, 0] as W), Int(3), Int(0), T(words:[ 2, 1, 0, 0] as W)) - NBKAssertAdditionByDigit(T(words:[~0, ~0, 0, 0] as W), Int(3), Int(0), T(words:[ 2, 0, 1, 0] as W)) - NBKAssertAdditionByDigit(T(words:[~0, ~0, ~0, 0] as W), Int(3), Int(0), T(words:[ 2, 0, 0, 1] as W)) - - NBKAssertAdditionByDigit(T(words:[ 0, 0, 0, 0] as W), Int(3), Int(1), T(words:[ 0, 3, 0, 0] as W)) - NBKAssertAdditionByDigit(T(words:[~0, 0, 0, 0] as W), Int(3), Int(1), T(words:[~0, 3, 0, 0] as W)) - NBKAssertAdditionByDigit(T(words:[~0, ~0, 0, 0] as W), Int(3), Int(1), T(words:[~0, 2, 1, 0] as W)) - NBKAssertAdditionByDigit(T(words:[~0, ~0, ~0, 0] as W), Int(3), Int(1), T(words:[~0, 2, 0, 1] as W)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Miscellaneous - //=------------------------------------------------------------------------= - - func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { - func becauseThisCompilesSuccessfully(_ x: inout T) { - XCTAssertNotNil(x += 0) - XCTAssertNotNil(x.add(0, at: 0)) - - XCTAssertNotNil(x + 0) - XCTAssertNotNil(x.adding(0, at: 0)) - } - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Addition x UIntXL -//*============================================================================* - -final class NBKFlexibleWidthTestsOnAdditionAsUIntXL: XCTestCase { - - typealias T = UIntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testAdding() { - NBKAssertAddition(T(0), T(0), Int(0), T(0)) - NBKAssertAddition(T(0), T(1), Int(0), T(1)) - NBKAssertAddition(T(0), T(2), Int(0), T(2)) - - NBKAssertAddition(T(1), T(0), Int(0), T(1)) - NBKAssertAddition(T(1), T(1), Int(0), T(2)) - NBKAssertAddition(T(1), T(2), Int(0), T(3)) - } - - func testAddingAtIndex() { - NBKAssertAddition(T(words:[ 0, 0, 0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[ 1, 2, 3, 0] as W)) - NBKAssertAddition(T(words:[~0, 0, 0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[ 0, 3, 3, 0] as W)) - NBKAssertAddition(T(words:[~0, ~0, 0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[ 0, 2, 4, 0] as W)) - NBKAssertAddition(T(words:[~0, ~0, ~0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[ 0, 2, 3, 1] as W)) - - NBKAssertAddition(T(words:[ 0, 0, 0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[ 0, 1, 2, 3] as W)) - NBKAssertAddition(T(words:[~0, 0, 0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[~0, 1, 2, 3] as W)) - NBKAssertAddition(T(words:[~0, ~0, 0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[~0, 0, 3, 3] as W)) - NBKAssertAddition(T(words:[~0, ~0, ~0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[~0, 0, 2, 4] as W)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Digit - //=------------------------------------------------------------------------= - - func testAddingDigit() { - NBKAssertAdditionByDigit(T(0), UInt(0), Int(0), T(0)) - NBKAssertAdditionByDigit(T(0), UInt(1), Int(0), T(1)) - NBKAssertAdditionByDigit(T(0), UInt(2), Int(0), T(2)) - - NBKAssertAdditionByDigit(T(1), UInt(0), Int(0), T(1)) - NBKAssertAdditionByDigit(T(1), UInt(1), Int(0), T(2)) - NBKAssertAdditionByDigit(T(1), UInt(2), Int(0), T(3)) - } - - func testAddingDigitAtIndex() { - NBKAssertAdditionByDigit(T(words:[ 0, 0, 0, 0] as W), UInt(3), Int(0), T(words:[ 3, 0, 0, 0] as W)) - NBKAssertAdditionByDigit(T(words:[~0, 0, 0, 0] as W), UInt(3), Int(0), T(words:[ 2, 1, 0, 0] as W)) - NBKAssertAdditionByDigit(T(words:[~0, ~0, 0, 0] as W), UInt(3), Int(0), T(words:[ 2, 0, 1, 0] as W)) - NBKAssertAdditionByDigit(T(words:[~0, ~0, ~0, 0] as W), UInt(3), Int(0), T(words:[ 2, 0, 0, 1] as W)) - - NBKAssertAdditionByDigit(T(words:[ 0, 0, 0, 0] as W), UInt(3), Int(1), T(words:[ 0, 3, 0, 0] as W)) - NBKAssertAdditionByDigit(T(words:[~0, 0, 0, 0] as W), UInt(3), Int(1), T(words:[~0, 3, 0, 0] as W)) - NBKAssertAdditionByDigit(T(words:[~0, ~0, 0, 0] as W), UInt(3), Int(1), T(words:[~0, 2, 1, 0] as W)) - NBKAssertAdditionByDigit(T(words:[~0, ~0, ~0, 0] as W), UInt(3), Int(1), T(words:[~0, 2, 0, 1] as W)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Miscellaneous - //=------------------------------------------------------------------------= - - func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { - func becauseThisCompilesSuccessfully(_ x: inout T) { - XCTAssertNotNil(x += 0) - XCTAssertNotNil(x.add(0, at: 0)) - - XCTAssertNotNil(x + 0) - XCTAssertNotNil(x.adding(0, at: 0)) - } - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Addition x Assertions -//*============================================================================* - -private func NBKAssertAddition( -_ lhs: T, _ rhs: T, _ index: Int, _ partialValue: T, -file: StaticString = #file, line: UInt = #line) { - //=------------------------------------------= - if index.isZero { - XCTAssertEqual( lhs + rhs, partialValue, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs += rhs; return lhs }(), partialValue, file: file, line: line) - } - //=------------------------------------------= - XCTAssertEqual(lhs.adding(rhs, at: index), partialValue, file: file, line: line) - XCTAssertEqual({ var x = lhs; let _ = x.add(rhs, at: index); return x }(), partialValue, file: file, line: line) -} - -private func NBKAssertAdditionByDigit( -_ lhs: T, _ rhs: T.Digit, _ index: Int, _ partialValue: T, -file: StaticString = #file, line: UInt = #line) { - //=------------------------------------------= - if index.isZero { - XCTAssertEqual( lhs + rhs, partialValue, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs += rhs; return lhs }(), partialValue, file: file, line: line) - } - //=------------------------------------------= - XCTAssertEqual(lhs.adding(rhs, at: index), partialValue, file: file, line: line) - XCTAssertEqual({ var x = lhs; let _ = x.add(rhs, at: index); return x }(), partialValue, file: file, line: line) -} - -#endif diff --git a/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Bits.swift b/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Bits.swift deleted file mode 100644 index 230b38b2..00000000 --- a/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Bits.swift +++ /dev/null @@ -1,212 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if DEBUG - -import NBKCoreKit -import NBKTwosComplementKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Flexible Width x Bits x IntXL -//*============================================================================* - -final class NBKFlexibleWidthTestsOnBitsAsIntXL: XCTestCase { - - typealias T = IntXL - typealias M = UIntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testInitBit() { - XCTAssertEqual(T(bit: false), T( )) - XCTAssertEqual(T(bit: true ), T(1)) - } - - func testBitWidth() { - XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).bitWidth, UInt.bitWidth * 1) - XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).bitWidth, UInt.bitWidth * 1) - - XCTAssertEqual(T(sign: .plus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as W)).bitWidth, UInt.bitWidth * 4) - XCTAssertEqual(T(sign: .plus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as W)).bitWidth, UInt.bitWidth * 5) - XCTAssertEqual(T(sign: .plus, magnitude: M(words:[ 1, 0, 0, ~0/2 + 1] as W)).bitWidth, UInt.bitWidth * 5) - - XCTAssertEqual(T(sign: .minus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as W)).bitWidth, UInt.bitWidth * 4) - XCTAssertEqual(T(sign: .minus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as W)).bitWidth, UInt.bitWidth * 4) - XCTAssertEqual(T(sign: .minus, magnitude: M(words:[ 1, 0, 0, ~0/2 + 1] as W)).bitWidth, UInt.bitWidth * 5) - } - - func testNonzeroBitCount() { - XCTAssertEqual(T(sign: .minus, magnitude: 0).nonzeroBitCount, 0) - XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).nonzeroBitCount, 0) - XCTAssertEqual(T(words:[ 1, 1, 1, 1] as W).nonzeroBitCount, 4) - XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).nonzeroBitCount, UInt.bitWidth * 1) - - XCTAssertEqual(T(sign: .plus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as W)).nonzeroBitCount, UInt.bitWidth * 4 - 1) - XCTAssertEqual(T(sign: .plus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as W)).nonzeroBitCount, UInt.bitWidth * 0 + 1) - XCTAssertEqual(T(sign: .plus, magnitude: M(words:[ 1, 0, 0, ~0/2 + 1] as W)).nonzeroBitCount, UInt.bitWidth * 0 + 2) - - XCTAssertEqual(T(sign: .minus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as W)).nonzeroBitCount, UInt.bitWidth * 0 + 2) - XCTAssertEqual(T(sign: .minus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as W)).nonzeroBitCount, UInt.bitWidth * 0 + 1) - XCTAssertEqual(T(sign: .minus, magnitude: M(words:[ 1, 0, 0, ~0/2 + 1] as W)).nonzeroBitCount, UInt.bitWidth * 5 - 1) - } - - func testLeadingZeroBitCount() { - XCTAssertEqual(T(sign: .minus, magnitude: 0).leadingZeroBitCount, UInt.bitWidth * 1) - XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).leadingZeroBitCount, UInt.bitWidth * 1) - XCTAssertEqual(T(words:[ 1, 1, 1, 1] as W).leadingZeroBitCount, UInt.bitWidth * 1 - 1) - XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).leadingZeroBitCount, UInt.bitWidth * 0) - - XCTAssertEqual(T(words:[ 2, 0, 0, 0] as W).leadingZeroBitCount, UInt.bitWidth * 1 - 2) - XCTAssertEqual(T(words:[ 0, 2, 0, 0] as W).leadingZeroBitCount, UInt.bitWidth * 1 - 2) - XCTAssertEqual(T(words:[ 0, 0, 2, 0] as W).leadingZeroBitCount, UInt.bitWidth * 1 - 2) - XCTAssertEqual(T(words:[ 0, 0, 0, 2] as W).leadingZeroBitCount, UInt.bitWidth * 1 - 2) - - XCTAssertEqual(T(sign: .plus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as W)).leadingZeroBitCount, UInt.bitWidth * 0 + 1) - XCTAssertEqual(T(sign: .plus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as W)).leadingZeroBitCount, UInt.bitWidth * 1 + 0) - XCTAssertEqual(T(sign: .plus, magnitude: M(words:[ 1, 0, 0, ~0/2 + 1] as W)).leadingZeroBitCount, UInt.bitWidth * 1 + 0) - - XCTAssertEqual(T(sign: .minus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as W)).leadingZeroBitCount, UInt.bitWidth * 0 + 0) - XCTAssertEqual(T(sign: .minus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as W)).leadingZeroBitCount, UInt.bitWidth * 0 + 0) - XCTAssertEqual(T(sign: .minus, magnitude: M(words:[ 1, 0, 0, ~0/2 + 1] as W)).leadingZeroBitCount, UInt.bitWidth * 0 + 0) - } - - func testTrailingZeroBitCount() { - XCTAssertEqual(T(sign: .minus, magnitude: 0).trailingZeroBitCount, UInt.bitWidth * 1) - XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).trailingZeroBitCount, UInt.bitWidth * 1) - XCTAssertEqual(T(words:[ 1, 1, 1, 1] as W).trailingZeroBitCount, UInt.bitWidth * 0) - XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).trailingZeroBitCount, UInt.bitWidth * 0) - - XCTAssertEqual(T(words:[ 2, 0, 0, 0] as W).trailingZeroBitCount, UInt.bitWidth * 0 + 1) - XCTAssertEqual(T(words:[ 0, 2, 0, 0] as W).trailingZeroBitCount, UInt.bitWidth * 1 + 1) - XCTAssertEqual(T(words:[ 0, 0, 2, 0] as W).trailingZeroBitCount, UInt.bitWidth * 2 + 1) - XCTAssertEqual(T(words:[ 0, 0, 0, 2] as W).trailingZeroBitCount, UInt.bitWidth * 3 + 1) - } - - func testMostSignificantBit() { - XCTAssertEqual(T(sign: .minus, magnitude: 0).mostSignificantBit, false) - XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).mostSignificantBit, false) - XCTAssertEqual(T(words:[ 1, 1, 1, 1] as W).mostSignificantBit, false) - XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).mostSignificantBit, true ) - - XCTAssertEqual(T(words:[~0, 0, 0, 0] as W).mostSignificantBit, false) - XCTAssertEqual(T(words:[ 0, ~0, 0, 0] as W).mostSignificantBit, false) - XCTAssertEqual(T(words:[ 0, 0, ~0, 0] as W).mostSignificantBit, false) - XCTAssertEqual(T(words:[ 0, 0, 0, ~0] as W).mostSignificantBit, true ) - - XCTAssertEqual(T(words:[~0, 1, 0, 0] as W).mostSignificantBit, false) - XCTAssertEqual(T(words:[ 0, ~0, 1, 0] as W).mostSignificantBit, false) - XCTAssertEqual(T(words:[ 0, 0, ~0, 1] as W).mostSignificantBit, false) - XCTAssertEqual(T(words:[ 1, 0, 0, ~0] as W).mostSignificantBit, true ) - } - - func testLeastSignificantBit() { - XCTAssertEqual(T(sign: .minus, magnitude: 0).leastSignificantBit, false) - XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).leastSignificantBit, false) - XCTAssertEqual(T(words:[ 1, 1, 1, 1] as W).leastSignificantBit, true ) - XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).leastSignificantBit, true ) - - XCTAssertEqual(T(words:[~0, 0, 0, 0] as W).leastSignificantBit, true ) - XCTAssertEqual(T(words:[ 0, ~0, 0, 0] as W).leastSignificantBit, false) - XCTAssertEqual(T(words:[ 0, 0, ~0, 0] as W).leastSignificantBit, false) - XCTAssertEqual(T(words:[ 0, 0, 0, ~0] as W).leastSignificantBit, false) - - XCTAssertEqual(T(words:[~0, 1, 0, 0] as W).leastSignificantBit, true ) - XCTAssertEqual(T(words:[ 0, ~0, 1, 0] as W).leastSignificantBit, false) - XCTAssertEqual(T(words:[ 0, 0, ~0, 1] as W).leastSignificantBit, false) - XCTAssertEqual(T(words:[ 1, 0, 0, ~0] as W).leastSignificantBit, true ) - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Bits x UIntXL -//*============================================================================* - -final class NBKFlexibleWidthTestsOnBitsAsUIntXL: XCTestCase { - - typealias T = UIntXL - typealias M = UIntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testInitBit() { - XCTAssertEqual(T(bit: false), T( )) - XCTAssertEqual(T(bit: true ), T(1)) - } - - func testBitWidth() { - XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).bitWidth, UInt.bitWidth * 1) - XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).bitWidth, UInt.bitWidth * 4) - } - - func testNonzeroBitCount() { - XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).nonzeroBitCount, 0) - XCTAssertEqual(T(words:[ 1, 1, 1, 1] as W).nonzeroBitCount, 4) - } - - func testLeadingZeroBitCount() { - XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).leadingZeroBitCount, UInt.bitWidth * 1) - XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).leadingZeroBitCount, UInt.bitWidth * 0) - - XCTAssertEqual(T(words:[ 2, 0, 0, 0] as W).leadingZeroBitCount, UInt.bitWidth * 1 - 2) - XCTAssertEqual(T(words:[ 0, 2, 0, 0] as W).leadingZeroBitCount, UInt.bitWidth * 1 - 2) - XCTAssertEqual(T(words:[ 0, 0, 2, 0] as W).leadingZeroBitCount, UInt.bitWidth * 1 - 2) - XCTAssertEqual(T(words:[ 0, 0, 0, 2] as W).leadingZeroBitCount, UInt.bitWidth * 1 - 2) - } - - func testTrailingZeroBitCount() { - XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).trailingZeroBitCount, UInt.bitWidth * 1) - XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).trailingZeroBitCount, UInt.bitWidth * 0) - - XCTAssertEqual(T(words:[ 2, 0, 0, 0] as W).trailingZeroBitCount, UInt.bitWidth * 0 + 1) - XCTAssertEqual(T(words:[ 0, 2, 0, 0] as W).trailingZeroBitCount, UInt.bitWidth * 1 + 1) - XCTAssertEqual(T(words:[ 0, 0, 2, 0] as W).trailingZeroBitCount, UInt.bitWidth * 2 + 1) - XCTAssertEqual(T(words:[ 0, 0, 0, 2] as W).trailingZeroBitCount, UInt.bitWidth * 3 + 1) - } - - func testMostSignificantBit() { - XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).mostSignificantBit, false) - XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).mostSignificantBit, true ) - - XCTAssertEqual(T(words:[~0, 0, 0, 0] as W).mostSignificantBit, true ) - XCTAssertEqual(T(words:[ 0, ~0, 0, 0] as W).mostSignificantBit, true ) - XCTAssertEqual(T(words:[ 0, 0, ~0, 0] as W).mostSignificantBit, true ) - XCTAssertEqual(T(words:[ 0, 0, 0, ~0] as W).mostSignificantBit, true ) - - XCTAssertEqual(T(words:[~0, 1, 0, 0] as W).mostSignificantBit, false) - XCTAssertEqual(T(words:[ 0, ~0, 1, 0] as W).mostSignificantBit, false) - XCTAssertEqual(T(words:[ 0, 0, ~0, 1] as W).mostSignificantBit, false) - XCTAssertEqual(T(words:[ 1, 0, 0, ~0] as W).mostSignificantBit, true ) - } - - func testLeastSignificantBit() { - XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).leastSignificantBit, false) - XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).leastSignificantBit, true ) - - XCTAssertEqual(T(words:[~0, 0, 0, 0] as W).leastSignificantBit, true ) - XCTAssertEqual(T(words:[ 0, ~0, 0, 0] as W).leastSignificantBit, false) - XCTAssertEqual(T(words:[ 0, 0, ~0, 0] as W).leastSignificantBit, false) - XCTAssertEqual(T(words:[ 0, 0, 0, ~0] as W).leastSignificantBit, false) - - XCTAssertEqual(T(words:[~0, 1, 0, 0] as W).leastSignificantBit, true ) - XCTAssertEqual(T(words:[ 0, ~0, 1, 0] as W).leastSignificantBit, false) - XCTAssertEqual(T(words:[ 0, 0, ~0, 1] as W).leastSignificantBit, false) - XCTAssertEqual(T(words:[ 1, 0, 0, ~0] as W).leastSignificantBit, true ) - } -} - -#endif diff --git a/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Comparisons.swift b/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Comparisons.swift deleted file mode 100644 index aa023308..00000000 --- a/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Comparisons.swift +++ /dev/null @@ -1,593 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if DEBUG - -import NBKCoreKit -import NBKTwosComplementKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Flexible Width x Comparisons x IntXL -//*============================================================================* - -final class NBKFlexibleWidthTestsOnComparisonsAsIntXL: XCTestCase { - - typealias T = IntXL - typealias M = UIntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testIsZero() { - XCTAssertTrue (T(sign: .plus, magnitude: 0).isZero) - XCTAssertTrue (T(sign: .minus, magnitude: 0).isZero) - - XCTAssertTrue (T(words:[ 0] as W).isZero) - XCTAssertFalse(T(words:[ 1] as W).isZero) - XCTAssertFalse(T(words:[ 2] as W).isZero) - - XCTAssertFalse(T(words:[~0] as W).isZero) - XCTAssertFalse(T(words:[~1] as W).isZero) - XCTAssertFalse(T(words:[~2] as W).isZero) - } - - func testIsLessThanZero() { - XCTAssertFalse(T(sign: .plus, magnitude: 0).isLessThanZero) - XCTAssertFalse(T(sign: .minus, magnitude: 0).isLessThanZero) - - XCTAssertFalse(T(words:[ 0] as W).isLessThanZero) - XCTAssertFalse(T(words:[ 1] as W).isLessThanZero) - XCTAssertFalse(T(words:[ 2] as W).isLessThanZero) - - XCTAssertTrue (T(words:[~0] as W).isLessThanZero) - XCTAssertTrue (T(words:[~1] as W).isLessThanZero) - XCTAssertTrue (T(words:[~2] as W).isLessThanZero) - } - - func testIsMoreThanZero() { - XCTAssertFalse(T(sign: .plus, magnitude: 0).isMoreThanZero) - XCTAssertFalse(T(sign: .minus, magnitude: 0).isMoreThanZero) - - XCTAssertFalse(T(words:[ 0] as W).isMoreThanZero) - XCTAssertTrue (T(words:[ 1] as W).isMoreThanZero) - XCTAssertTrue (T(words:[ 2] as W).isMoreThanZero) - - XCTAssertFalse(T(words:[~0] as W).isMoreThanZero) - XCTAssertFalse(T(words:[~1] as W).isMoreThanZero) - XCTAssertFalse(T(words:[~2] as W).isMoreThanZero) - } - - func testIsOdd() { - XCTAssertFalse(T(sign: .plus, magnitude: 0).isOdd) - XCTAssertFalse(T(sign: .minus, magnitude: 0).isOdd) - - XCTAssertFalse(T(words:[ 0] as W).isOdd) - XCTAssertTrue (T(words:[ 1] as W).isOdd) - XCTAssertFalse(T(words:[ 2] as W).isOdd) - - XCTAssertTrue (T(words:[~0] as W).isOdd) - XCTAssertFalse(T(words:[~1] as W).isOdd) - XCTAssertTrue (T(words:[~2] as W).isOdd) - } - - func testIsEven() { - XCTAssertTrue (T(sign: .plus, magnitude: 0).isEven) - XCTAssertTrue (T(sign: .minus, magnitude: 0).isEven) - - XCTAssertTrue (T(words:[ 0] as W).isEven) - XCTAssertFalse(T(words:[ 1] as W).isEven) - XCTAssertTrue (T(words:[ 2] as W).isEven) - - XCTAssertFalse(T(words:[~0] as W).isEven) - XCTAssertTrue (T(words:[~1] as W).isEven) - XCTAssertFalse(T(words:[~2] as W).isEven) - } - - func testIsPowerOf2() { - XCTAssertFalse(T(sign: .plus, magnitude: 0).isPowerOf2) - XCTAssertFalse(T(sign: .minus, magnitude: 0).isPowerOf2) - - XCTAssertFalse(T(words:[~3] as W).isPowerOf2) - XCTAssertFalse(T(words:[~2] as W).isPowerOf2) - XCTAssertFalse(T(words:[~1] as W).isPowerOf2) - XCTAssertFalse(T(words:[~0] as W).isPowerOf2) - XCTAssertFalse(T(words:[ 0] as W).isPowerOf2) - XCTAssertTrue (T(words:[ 1] as W).isPowerOf2) - XCTAssertTrue (T(words:[ 2] as W).isPowerOf2) - XCTAssertFalse(T(words:[ 3] as W).isPowerOf2) - - XCTAssertFalse(T(words:[ 0, 0, 0, 0] as W).isPowerOf2) - XCTAssertTrue (T(words:[ 1, 0, 0, 0] as W).isPowerOf2) - XCTAssertFalse(T(words:[ 1, 1, 0, 0] as W).isPowerOf2) - XCTAssertTrue (T(words:[ 0, 1, 0, 0] as W).isPowerOf2) - XCTAssertFalse(T(words:[ 0, 1, 1, 0] as W).isPowerOf2) - XCTAssertTrue (T(words:[ 0, 0, 1, 0] as W).isPowerOf2) - XCTAssertFalse(T(words:[ 0, 0, 1, 1] as W).isPowerOf2) - XCTAssertTrue (T(words:[ 0, 0, 0, 1] as W).isPowerOf2) - } - - func testSignum() { - NBKAssertSignum(T(sign: .plus, magnitude: 0), Int( 0)) - NBKAssertSignum(T(sign: .minus, magnitude: 0), Int( 0)) - - NBKAssertSignum(T(words:[ 0] as W), Int( 0)) - NBKAssertSignum(T(words:[ 1] as W), Int( 1)) - NBKAssertSignum(T(words:[ 2] as W), Int( 1)) - - NBKAssertSignum(T(words:[~0] as W), Int(-1)) - NBKAssertSignum(T(words:[~1] as W), Int(-1)) - NBKAssertSignum(T(words:[~2] as W), Int(-1)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testHashing() { - var union = Set() - union.insert(T(sign: .minus, magnitude: M())) - union.insert(T(sign: .minus, magnitude: M())) - union.insert(T(words:[0, 0, 0, 0] as W)) - union.insert(T(words:[0, 0, 0, 0] as W)) - union.insert(T(words:[1, 0, 0, 0] as W)) - union.insert(T(words:[1, 0, 0, 0] as W)) - union.insert(T(words:[0, 1, 0, 0] as W)) - union.insert(T(words:[0, 1, 0, 0] as W)) - union.insert(T(words:[0, 0, 1, 0] as W)) - union.insert(T(words:[0, 0, 1, 0] as W)) - union.insert(T(words:[0, 0, 0, 1] as W)) - union.insert(T(words:[0, 0, 0, 1] as W)) - XCTAssertEqual(union.count, 5 as Int) - } - - func testComparing() { - NBKAssertComparisons( T(0), T(0), Int(0)) - NBKAssertComparisons( T(0), -T(0), Int(0)) - NBKAssertComparisons(-T(0), T(0), Int(0)) - NBKAssertComparisons(-T(0), -T(0), Int(0)) - - NBKAssertComparisons( T(1), T(1), Int(0)) - NBKAssertComparisons( T(1), -T(1), Int(1)) - NBKAssertComparisons(-T(1), T(1), -Int(1)) - NBKAssertComparisons(-T(1), -T(1), Int(0)) - - NBKAssertComparisons( T(2), T(3), -Int(1)) - NBKAssertComparisons( T(2), -T(3), Int(1)) - NBKAssertComparisons(-T(2), T(3), -Int(1)) - NBKAssertComparisons(-T(2), -T(3), Int(1)) - - NBKAssertComparisons( T(3), T(2), Int(1)) - NBKAssertComparisons( T(3), -T(2), Int(1)) - NBKAssertComparisons(-T(3), T(2), -Int(1)) - NBKAssertComparisons(-T(3), -T(2), -Int(1)) - - NBKAssertComparisons(T(words:[0, 2, 3, 4] as W), T(words:[1, 2, 3, 4] as W), -Int(1)) - NBKAssertComparisons(T(words:[1, 0, 3, 4] as W), T(words:[1, 2, 3, 4] as W), -Int(1)) - NBKAssertComparisons(T(words:[1, 2, 0, 4] as W), T(words:[1, 2, 3, 4] as W), -Int(1)) - NBKAssertComparisons(T(words:[1, 2, 3, 0] as W), T(words:[1, 2, 3, 4] as W), -Int(1)) - NBKAssertComparisons(T(words:[0, 2, 3, 4] as W), T(words:[0, 2, 3, 4] as W), Int(0)) - NBKAssertComparisons(T(words:[1, 0, 3, 4] as W), T(words:[1, 0, 3, 4] as W), Int(0)) - NBKAssertComparisons(T(words:[1, 2, 0, 4] as W), T(words:[1, 2, 0, 4] as W), Int(0)) - NBKAssertComparisons(T(words:[1, 2, 3, 0] as W), T(words:[1, 2, 3, 0] as W), Int(0)) - NBKAssertComparisons(T(words:[1, 2, 3, 4] as W), T(words:[0, 2, 3, 4] as W), Int(1)) - NBKAssertComparisons(T(words:[1, 2, 3, 4] as W), T(words:[1, 0, 3, 4] as W), Int(1)) - NBKAssertComparisons(T(words:[1, 2, 3, 4] as W), T(words:[1, 2, 0, 4] as W), Int(1)) - NBKAssertComparisons(T(words:[1, 2, 3, 4] as W), T(words:[1, 2, 3, 0] as W), Int(1)) - } - - func testComparingAtIndex() { - NBKAssertComparisonsAtIndex( T(0), T(0), Int(4), Int(0)) - NBKAssertComparisonsAtIndex( T(0), -T(0), Int(4), Int(0)) - NBKAssertComparisonsAtIndex(-T(0), T(0), Int(4), Int(0)) - NBKAssertComparisonsAtIndex(-T(0), -T(0), Int(4), Int(0)) - - NBKAssertComparisonsAtIndex( T(1), T(1), Int(4), -Int(1)) - NBKAssertComparisonsAtIndex( T(1), -T(1), Int(4), Int(1)) - NBKAssertComparisonsAtIndex(-T(1), T(1), Int(4), -Int(1)) - NBKAssertComparisonsAtIndex(-T(1), -T(1), Int(4), Int(1)) - - NBKAssertComparisonsAtIndex( T(2), T(3), Int(4), -Int(1)) - NBKAssertComparisonsAtIndex( T(2), -T(3), Int(4), Int(1)) - NBKAssertComparisonsAtIndex(-T(2), T(3), Int(4), -Int(1)) - NBKAssertComparisonsAtIndex(-T(2), -T(3), Int(4), Int(1)) - - NBKAssertComparisonsAtIndex( T(3), T(2), Int(4), -Int(1)) - NBKAssertComparisonsAtIndex( T(3), -T(2), Int(4), Int(1)) - NBKAssertComparisonsAtIndex(-T(3), T(2), Int(4), -Int(1)) - NBKAssertComparisonsAtIndex(-T(3), -T(2), Int(4), Int(1)) - - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(0), Int(0)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(1), Int(0)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(2), Int(0)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(3), Int(0)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(4), Int(0)) - - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(0), -Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(1), -Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(2), -Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(3), -Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(4), -Int(1)) - - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(0), Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(1), Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(2), Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(3), Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(4), Int(1)) - - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(0), Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(1), Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(2), Int(0)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(3), -Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(4), -Int(1)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Digit - //=------------------------------------------------------------------------= - - func testComparingByDigit() { - NBKAssertComparisonsByDigit( T(0), Int(0), Int(0)) - NBKAssertComparisonsByDigit( T(0), -Int(0), Int(0)) - NBKAssertComparisonsByDigit(-T(0), Int(0), Int(0)) - NBKAssertComparisonsByDigit(-T(0), -Int(0), Int(0)) - - NBKAssertComparisonsByDigit( T(1), Int(1), Int(0)) - NBKAssertComparisonsByDigit( T(1), -Int(1), Int(1)) - NBKAssertComparisonsByDigit(-T(1), Int(1), -Int(1)) - NBKAssertComparisonsByDigit(-T(1), -Int(1), Int(0)) - - NBKAssertComparisonsByDigit( T(2), Int(3), -Int(1)) - NBKAssertComparisonsByDigit( T(2), -Int(3), Int(1)) - NBKAssertComparisonsByDigit(-T(2), Int(3), -Int(1)) - NBKAssertComparisonsByDigit(-T(2), -Int(3), Int(1)) - - NBKAssertComparisonsByDigit( T(3), Int(2), Int(1)) - NBKAssertComparisonsByDigit( T(3), -Int(2), Int(1)) - NBKAssertComparisonsByDigit(-T(3), Int(2), -Int(1)) - NBKAssertComparisonsByDigit(-T(3), -Int(2), -Int(1)) - - NBKAssertComparisonsByDigit( T(words:[0, 0, 0, 0]), Int(1), -Int(1)) - NBKAssertComparisonsByDigit( T(words:[1, 0, 0, 0]), Int(1), Int(0)) - NBKAssertComparisonsByDigit( T(words:[2, 0, 0, 0]), Int(1), Int(1)) - - NBKAssertComparisonsByDigit( T(words:[0, 1, 0, 0]), Int(1), Int(1)) - NBKAssertComparisonsByDigit( T(words:[1, 1, 0, 0]), Int(1), Int(1)) - NBKAssertComparisonsByDigit( T(words:[2, 1, 0, 0]), Int(1), Int(1)) - - NBKAssertComparisonsByDigit(~T(words:[0, 0, 0, 0]), ~Int(1), Int(1)) - NBKAssertComparisonsByDigit(~T(words:[1, 0, 0, 0]), ~Int(1), Int(0)) - NBKAssertComparisonsByDigit(~T(words:[2, 0, 0, 0]), ~Int(1), -Int(1)) - - NBKAssertComparisonsByDigit(~T(words:[0, 1, 0, 0]), ~Int(1), -Int(1)) - NBKAssertComparisonsByDigit(~T(words:[1, 1, 0, 0]), ~Int(1), -Int(1)) - NBKAssertComparisonsByDigit(~T(words:[2, 1, 0, 0]), ~Int(1), -Int(1)) - } - - func testComparingByDigitAtIndex() { - NBKAssertComparisonsByDigitAtIndex( T(0), Int(0), Int(4), Int(0)) - NBKAssertComparisonsByDigitAtIndex( T(0), -Int(0), Int(4), Int(0)) - NBKAssertComparisonsByDigitAtIndex(-T(0), Int(0), Int(4), Int(0)) - NBKAssertComparisonsByDigitAtIndex(-T(0), -Int(0), Int(4), Int(0)) - - NBKAssertComparisonsByDigitAtIndex( T(1), Int(1), Int(4), -Int(1)) - NBKAssertComparisonsByDigitAtIndex( T(1), -Int(1), Int(4), Int(1)) - NBKAssertComparisonsByDigitAtIndex(-T(1), Int(1), Int(4), -Int(1)) - NBKAssertComparisonsByDigitAtIndex(-T(1), -Int(1), Int(4), Int(1)) - - NBKAssertComparisonsByDigitAtIndex( T(2), Int(3), Int(4), -Int(1)) - NBKAssertComparisonsByDigitAtIndex( T(2), -Int(3), Int(4), Int(1)) - NBKAssertComparisonsByDigitAtIndex(-T(2), Int(3), Int(4), -Int(1)) - NBKAssertComparisonsByDigitAtIndex(-T(2), -Int(3), Int(4), Int(1)) - - NBKAssertComparisonsByDigitAtIndex( T(3), Int(2), Int(4), -Int(1)) - NBKAssertComparisonsByDigitAtIndex( T(3), -Int(2), Int(4), Int(1)) - NBKAssertComparisonsByDigitAtIndex(-T(3), Int(2), Int(4), -Int(1)) - NBKAssertComparisonsByDigitAtIndex(-T(3), -Int(2), Int(4), Int(1)) - - NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), Int(4), Int(0), Int(1)) - NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), Int(4), Int(1), Int(1)) - NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), Int(4), Int(2), Int(1)) - NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), Int(4), Int(3), Int(1)) - NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), Int(4), Int(4), -Int(1)) - - NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), Int(5), Int(0), Int(1)) - NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), Int(5), Int(1), Int(1)) - NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), Int(5), Int(2), Int(1)) - NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), Int(5), Int(3), -Int(1)) - NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), Int(5), Int(4), -Int(1)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Miscellaneous - //=------------------------------------------------------------------------= - - func testOverloadsAreUnambiguous() { - func becauseThisCompilesSuccessfully(_ x: inout T) { - XCTAssertNotNil(x.signum()) - } - } - - func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { - func becauseThisCompilesSuccessfully(_ x: inout T) { - XCTAssertNotNil(x.compared(to: 0)) - XCTAssertNotNil(x.compared(to: 0, at: 0)) - } - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Comparisons x UIntXL -//*============================================================================* - -final class NBKFlexibleWidthTestsOnComparisonsAsUIntXL: XCTestCase { - - typealias T = UIntXL - typealias M = UIntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testIsZero() { - XCTAssertTrue (T(words:[ 0] as W).isZero) - XCTAssertFalse(T(words:[ 1] as W).isZero) - XCTAssertFalse(T(words:[ 2] as W).isZero) - - XCTAssertFalse(T(words:[~0] as W).isZero) - XCTAssertFalse(T(words:[~1] as W).isZero) - XCTAssertFalse(T(words:[~2] as W).isZero) - } - - func testIsLessThanZero() { - XCTAssertFalse(T(words:[ 0] as W).isLessThanZero) - XCTAssertFalse(T(words:[ 1] as W).isLessThanZero) - XCTAssertFalse(T(words:[ 2] as W).isLessThanZero) - - XCTAssertFalse(T(words:[~0] as W).isLessThanZero) - XCTAssertFalse(T(words:[~1] as W).isLessThanZero) - XCTAssertFalse(T(words:[~2] as W).isLessThanZero) - } - - func testIsMoreThanZero() { - XCTAssertFalse(T(words:[ 0] as W).isMoreThanZero) - XCTAssertTrue (T(words:[ 1] as W).isMoreThanZero) - XCTAssertTrue (T(words:[ 2] as W).isMoreThanZero) - - XCTAssertTrue (T(words:[~0] as W).isMoreThanZero) - XCTAssertTrue (T(words:[~1] as W).isMoreThanZero) - XCTAssertTrue (T(words:[~2] as W).isMoreThanZero) - } - - func testIsOdd() { - XCTAssertFalse(T(words:[ 0] as W).isOdd) - XCTAssertTrue (T(words:[ 1] as W).isOdd) - XCTAssertFalse(T(words:[ 2] as W).isOdd) - - XCTAssertTrue (T(words:[~0] as W).isOdd) - XCTAssertFalse(T(words:[~1] as W).isOdd) - XCTAssertTrue (T(words:[~2] as W).isOdd) - } - - func testIsEven() { - XCTAssertTrue (T(words:[ 0] as W).isEven) - XCTAssertFalse(T(words:[ 1] as W).isEven) - XCTAssertTrue (T(words:[ 2] as W).isEven) - - XCTAssertFalse(T(words:[~0] as W).isEven) - XCTAssertTrue (T(words:[~1] as W).isEven) - XCTAssertFalse(T(words:[~2] as W).isEven) - } - - func testIsPowerOf2() { - XCTAssertFalse(T(words:[ 0] as W).isPowerOf2) - XCTAssertTrue (T(words:[ 1] as W).isPowerOf2) - XCTAssertTrue (T(words:[ 2] as W).isPowerOf2) - XCTAssertFalse(T(words:[ 3] as W).isPowerOf2) - XCTAssertTrue (T(words:[ 4] as W).isPowerOf2) - XCTAssertFalse(T(words:[ 5] as W).isPowerOf2) - XCTAssertFalse(T(words:[ 6] as W).isPowerOf2) - XCTAssertFalse(T(words:[ 7] as W).isPowerOf2) - - XCTAssertFalse(T(words:[ 0, 0, 0, 0] as W).isPowerOf2) - XCTAssertTrue (T(words:[ 1, 0, 0, 0] as W).isPowerOf2) - XCTAssertFalse(T(words:[ 1, 1, 0, 0] as W).isPowerOf2) - XCTAssertTrue (T(words:[ 0, 1, 0, 0] as W).isPowerOf2) - XCTAssertFalse(T(words:[ 0, 1, 1, 0] as W).isPowerOf2) - XCTAssertTrue (T(words:[ 0, 0, 1, 0] as W).isPowerOf2) - XCTAssertFalse(T(words:[ 0, 0, 1, 1] as W).isPowerOf2) - XCTAssertTrue (T(words:[ 0, 0, 0, 1] as W).isPowerOf2) - } - - func testSignum() { - NBKAssertSignum(T(words:[ 0] as W), Int(0)) - NBKAssertSignum(T(words:[ 1] as W), Int(1)) - NBKAssertSignum(T(words:[ 2] as W), Int(1)) - - NBKAssertSignum(T(words:[~0] as W), Int(1)) - NBKAssertSignum(T(words:[~1] as W), Int(1)) - NBKAssertSignum(T(words:[~2] as W), Int(1)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testHashing() { - var union = Set() - union.insert(T(words:[0, 0, 0, 0] as W)) - union.insert(T(words:[0, 0, 0, 0] as W)) - union.insert(T(words:[1, 0, 0, 0] as W)) - union.insert(T(words:[1, 0, 0, 0] as W)) - union.insert(T(words:[0, 1, 0, 0] as W)) - union.insert(T(words:[0, 1, 0, 0] as W)) - union.insert(T(words:[0, 0, 1, 0] as W)) - union.insert(T(words:[0, 0, 1, 0] as W)) - union.insert(T(words:[0, 0, 0, 1] as W)) - union.insert(T(words:[0, 0, 0, 1] as W)) - XCTAssertEqual(union.count, 5 as Int) - } - - func testComparing() { - NBKAssertComparisons(T(words:[0, 2, 3, 4] as W), T(words:[1, 2, 3, 4] as W), -Int(1)) - NBKAssertComparisons(T(words:[1, 0, 3, 4] as W), T(words:[1, 2, 3, 4] as W), -Int(1)) - NBKAssertComparisons(T(words:[1, 2, 0, 4] as W), T(words:[1, 2, 3, 4] as W), -Int(1)) - NBKAssertComparisons(T(words:[1, 2, 3, 0] as W), T(words:[1, 2, 3, 4] as W), -Int(1)) - NBKAssertComparisons(T(words:[0, 2, 3, 4] as W), T(words:[0, 2, 3, 4] as W), Int(0)) - NBKAssertComparisons(T(words:[1, 0, 3, 4] as W), T(words:[1, 0, 3, 4] as W), Int(0)) - NBKAssertComparisons(T(words:[1, 2, 0, 4] as W), T(words:[1, 2, 0, 4] as W), Int(0)) - NBKAssertComparisons(T(words:[1, 2, 3, 0] as W), T(words:[1, 2, 3, 0] as W), Int(0)) - NBKAssertComparisons(T(words:[1, 2, 3, 4] as W), T(words:[0, 2, 3, 4] as W), Int(1)) - NBKAssertComparisons(T(words:[1, 2, 3, 4] as W), T(words:[1, 0, 3, 4] as W), Int(1)) - NBKAssertComparisons(T(words:[1, 2, 3, 4] as W), T(words:[1, 2, 0, 4] as W), Int(1)) - NBKAssertComparisons(T(words:[1, 2, 3, 4] as W), T(words:[1, 2, 3, 0] as W), Int(1)) - } - - func testComparingAtIndex() { - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(0), Int(0)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(1), Int(0)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(2), Int(0)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(3), Int(0)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(4), Int(0)) - - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(0), -Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(1), -Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(2), -Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(3), -Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(4), -Int(1)) - - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(0), Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(1), Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(2), Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(3), Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(4), Int(1)) - - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(0), Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(1), Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(2), Int(0)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(3), -Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(4), -Int(1)) - } - - func testComparingByDigit() { - NBKAssertComparisonsByDigit(T(0), UInt(0), Int(0)) - NBKAssertComparisonsByDigit(T(1), UInt(1), Int(0)) - NBKAssertComparisonsByDigit(T(2), UInt(3), -Int(1)) - NBKAssertComparisonsByDigit(T(3), UInt(2), Int(1)) - - NBKAssertComparisonsByDigit(T(words:[0, 0, 0, 0]), UInt(1), -Int(1)) - NBKAssertComparisonsByDigit(T(words:[1, 0, 0, 0]), UInt(1), Int(0)) - NBKAssertComparisonsByDigit(T(words:[2, 0, 0, 0]), UInt(1), Int(1)) - - NBKAssertComparisonsByDigit(T(words:[0, 1, 0, 0]), UInt(1), Int(1)) - NBKAssertComparisonsByDigit(T(words:[1, 1, 0, 0]), UInt(1), Int(1)) - NBKAssertComparisonsByDigit(T(words:[2, 1, 0, 0]), UInt(1), Int(1)) - } - - func testComparingByDigitAtIndex() { - NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), UInt(4), Int(0), Int(1)) - NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), UInt(4), Int(1), Int(1)) - NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), UInt(4), Int(2), Int(1)) - NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), UInt(4), Int(3), Int(1)) - NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), UInt(4), Int(4), -Int(1)) - - NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), UInt(5), Int(0), Int(1)) - NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), UInt(5), Int(1), Int(1)) - NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), UInt(5), Int(2), Int(1)) - NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), UInt(5), Int(3), -Int(1)) - NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), UInt(5), Int(4), -Int(1)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Miscellaneous - //=------------------------------------------------------------------------= - - func testOverloadsAreUnambiguous() { - func becauseThisCompilesSuccessfully(_ x: inout T) { - XCTAssertNotNil(x.signum()) - } - } - - func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { - func becauseThisCompilesSuccessfully(_ x: inout T) { - XCTAssertNotNil(x.compared(to: 0)) - XCTAssertNotNil(x.compared(to: 0, at: 0)) - } - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Comparisons x Assertions -//*============================================================================* - -private func NBKAssertSignum( -_ operand: T, _ signum: Int, -file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual(Int(operand.signum() as Int), signum, file: file, line: line) - XCTAssertEqual(Int(operand.signum() as T ), signum, file: file, line: line) // stdlib -} - -private func NBKAssertComparisons( -_ lhs: T, _ rhs: T, _ signum: Int, -file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual(lhs == rhs, signum == 0, file: file, line: line) - XCTAssertEqual(lhs != rhs, signum != 0, file: file, line: line) - - XCTAssertEqual(lhs < rhs, signum == -1, file: file, line: line) - XCTAssertEqual(lhs <= rhs, signum != 1, file: file, line: line) - - XCTAssertEqual(lhs > rhs, signum == 1, file: file, line: line) - XCTAssertEqual(lhs >= rhs, signum != -1, file: file, line: line) - - XCTAssertEqual(lhs.compared(to: rhs), signum, file: file, line: line) -} - -private func NBKAssertComparisonsAtIndex( -_ lhs: T, _ rhs: T, _ index: Int, _ signum: Int, -file: StaticString = #file, line: UInt = #line) { - //=------------------------------------------= - if index.isZero { - NBKAssertComparisons(lhs, rhs, signum, file: file, line: line) - } - //=------------------------------------------= - XCTAssertEqual(lhs.compared(to: rhs, at: index), signum, file: file, line: line) -} - -private func NBKAssertComparisonsByDigit( -_ lhs: T, _ rhs: T.Digit, _ signum: Int, -file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual(lhs == rhs, signum == 0, file: file, line: line) - XCTAssertEqual(lhs != rhs, signum != 0, file: file, line: line) - - XCTAssertEqual(lhs < rhs, signum == -1, file: file, line: line) - XCTAssertEqual(lhs <= rhs, signum != 1, file: file, line: line) - - XCTAssertEqual(lhs > rhs, signum == 1, file: file, line: line) - XCTAssertEqual(lhs >= rhs, signum != -1, file: file, line: line) - - XCTAssertEqual(lhs.compared(to: rhs), signum, file: file, line: line) -} - -private func NBKAssertComparisonsByDigitAtIndex( -_ lhs: T, _ rhs: T.Digit, _ index: Int, _ signum: Int, -file: StaticString = #file, line: UInt = #line) { - //=------------------------------------------= - if index.isZero { - NBKAssertComparisonsByDigit(lhs, rhs, signum, file: file, line: line) - } - //=------------------------------------------= - XCTAssertEqual(lhs.compared(to: rhs, at: index), signum, file: file, line: line) -} - -#endif diff --git a/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Complements.swift b/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Complements.swift deleted file mode 100644 index bc84b34b..00000000 --- a/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Complements.swift +++ /dev/null @@ -1,210 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if DEBUG - -import NBKCoreKit -import NBKTwosComplementKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Flexible Width x Complements x IntXL -//*============================================================================* - -final class NBKFlexibleWidthTestsOnComplementsAsIntXL: XCTestCase { - - typealias T = IntXL - typealias M = UIntXL - - //=------------------------------------------------------------------------= - // MARK: Tests x Magnitude - //=------------------------------------------------------------------------= - - func testMagnitude() { - XCTAssertEqual(T(words:[ 1, 0, 0, 0] as W).magnitude, M(words:[ 1, 0, 0, 0] as W)) - XCTAssertEqual(T(words:[~0, 0, 0, 0] as W).magnitude, M(words:[~0, 0, 0, 0] as W)) - XCTAssertEqual(T(words:[ 1, 1, 1, 1] as W).magnitude, M(words:[ 1, 1, 1, 1] as W)) - XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).magnitude, M(words:[ 1, 0, 0, 0] as W)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x One's Complement - //=------------------------------------------------------------------------= - - func testOnesComplement() { - NBKAssertOnesComplement(-T(1), T(0)) - NBKAssertOnesComplement(-T(0), -T(1)) - NBKAssertOnesComplement( T(0), -T(1)) - NBKAssertOnesComplement( T(1), -T(2)) - - NBKAssertOnesComplement(T(words:[ 0, 0, 0, 0] as W), T(words:[~0, ~0, ~0, ~0] as W)) - NBKAssertOnesComplement(T(words:[ 1, 0, 0, 0] as W), T(words:[~1, ~0, ~0, ~0] as W)) - NBKAssertOnesComplement(T(words:[~0, 0, 0, 0] as W), T(words:[ 0, ~0, ~0, ~0] as W)) - NBKAssertOnesComplement(T(words:[ 1, 1, 1, 1] as W), T(words:[~1, ~1, ~1, ~1] as W)) - NBKAssertOnesComplement(T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 0, 0, 0, 0] as W)) - - NBKAssertOnesComplement(T(words:[~0, ~0, ~0, ~0/2 + 0, 0] as W), T(words:[ 0, 0, 0, ~0/2 + 1, ~0] as W)) - NBKAssertOnesComplement(T(words:[ 0, 0, 0, ~0/2 + 1, 0] as W), T(words:[~0, ~0, ~0, ~0/2 + 0, ~0] as W)) - NBKAssertOnesComplement(T(words:[ 1, 0, 0, ~0/2 + 1, 0] as W), T(words:[~1, ~0, ~0, ~0/2 + 0, ~0] as W)) - - NBKAssertOnesComplement(T(words:[ 1, 0, 0, ~0/2 + 1, ~0] as W), T(words:[~1, ~0, ~0, ~0/2 + 0, 0] as W)) - NBKAssertOnesComplement(T(words:[ 0, 0, 0, ~0/2 + 1, ~0] as W), T(words:[~0, ~0, ~0, ~0/2 + 0, 0] as W)) - NBKAssertOnesComplement(T(words:[~0, ~0, ~0, ~0/2 + 0, ~0] as W), T(words:[ 0, 0, 0, ~0/2 + 1, 0] as W)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Two's Complement - //=------------------------------------------------------------------------= - - func testTwosComplement() { - NBKAssertTwosComplement(-T(1), T(1)) - NBKAssertTwosComplement(-T(0), T(0)) - NBKAssertTwosComplement( T(0), -T(0)) - NBKAssertTwosComplement( T(1), -T(1)) - - NBKAssertTwosComplement(T(words:[ 0, 0, 0, 0] as W), T(words:[ 0, 0, 0, 0] as W)) - NBKAssertTwosComplement(T(words:[ 1, 0, 0, 0] as W), T(words:[~0, ~0, ~0, ~0] as W)) - NBKAssertTwosComplement(T(words:[~0, 0, 0, 0] as W), T(words:[ 1, ~0, ~0, ~0] as W)) - NBKAssertTwosComplement(T(words:[ 1, 1, 1, 1] as W), T(words:[~0, ~1, ~1, ~1] as W)) - NBKAssertTwosComplement(T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 1, 0, 0, 0] as W)) - - NBKAssertTwosComplement(T(words:[~0, ~0, ~0, ~0/2 + 0, 0] as W), T(words:[ 1, 0, 0, ~0/2 + 1, ~0] as W)) - NBKAssertTwosComplement(T(words:[ 0, 0, 0, ~0/2 + 1, 0] as W), T(words:[ 0, 0, 0, ~0/2 + 1, ~0] as W)) - NBKAssertTwosComplement(T(words:[ 1, 0, 0, ~0/2 + 1, 0] as W), T(words:[~0, ~0, ~0, ~0/2 + 0, ~0] as W)) - - NBKAssertTwosComplement(T(words:[ 1, 0, 0, ~0/2 + 1, ~0] as W), T(words:[~0, ~0, ~0, ~0/2 + 0, 0] as W)) - NBKAssertTwosComplement(T(words:[ 0, 0, 0, ~0/2 + 1, ~0] as W), T(words:[ 0, 0, 0, ~0/2 + 1, ~0] as W), true) - NBKAssertTwosComplement(T(words:[~0, ~0, ~0, ~0/2 + 0, ~0] as W), T(words:[ 1, 0, 0, ~0/2 + 1, 0] as W)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Additive Inverse - //=------------------------------------------------------------------------= - - func testAdditiveInverse() { - NBKAssertAdditiveInverse(T(sign: .plus, magnitude: M( )), T(sign: .minus, magnitude: M( ))) - NBKAssertAdditiveInverse(T(sign: .minus, magnitude: M( )), T(sign: .plus, magnitude: M( ))) - NBKAssertAdditiveInverse(T(sign: .plus, magnitude: M(1)), T(sign: .minus, magnitude: M(1))) - NBKAssertAdditiveInverse(T(sign: .minus, magnitude: M(1)), T(sign: .plus, magnitude: M(1))) - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Complements x UIntXL -//*============================================================================* - -final class NBKFlexibleWidthTestsOnComplementsAsUIntXL: XCTestCase { - - typealias T = UIntXL - typealias M = UIntXL - - //=------------------------------------------------------------------------= - // MARK: Tests x Magnitude - //=------------------------------------------------------------------------= - - func testMagnitude() { - XCTAssertEqual(T(words:[ 1, 0, 0, 0] as W).magnitude, M(words:[ 1, 0, 0, 0] as W)) - XCTAssertEqual(T(words:[~0, 0, 0, 0] as W).magnitude, M(words:[~0, 0, 0, 0] as W)) - XCTAssertEqual(T(words:[ 1, 1, 1, 1] as W).magnitude, M(words:[ 1, 1, 1, 1] as W)) - XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).magnitude, M(words:[~0, ~0, ~0, ~0] as W)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x One's Complement - //=------------------------------------------------------------------------= - - func testOnesComplement() { - NBKAssertOnesComplement(T(words:[ 0, 0, 0, 0] as W), T(words:[~0, 0, 0, 0] as W)) - NBKAssertOnesComplement(T(words:[ 1, 0, 0, 0] as W), T(words:[~1, 0, 0, 0] as W)) - NBKAssertOnesComplement(T(words:[~0, 0, 0, 0] as W), T(words:[ 0, 0, 0, 0] as W)) - NBKAssertOnesComplement(T(words:[ 1, 1, 1, 1] as W), T(words:[~1, ~1, ~1, ~1] as W)) - NBKAssertOnesComplement(T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 0, 0, 0, 0] as W)) - - NBKAssertOnesComplement(T(words:[~0, ~0, ~0, ~0/2 + 0] as W), T(words:[ 0, 0, 0, ~0/2 + 1] as W)) - NBKAssertOnesComplement(T(words:[ 0, 0, 0, ~0/2 + 1] as W), T(words:[~0, ~0, ~0, ~0/2 + 0] as W)) - NBKAssertOnesComplement(T(words:[ 1, 0, 0, ~0/2 + 1] as W), T(words:[~1, ~0, ~0, ~0/2 + 0] as W)) - - NBKAssertOnesComplement(T(words:[ 1, 0, 0, ~0/2 + 1] as W), T(words:[~1, ~0, ~0, ~0/2 + 0] as W)) - NBKAssertOnesComplement(T(words:[ 0, 0, 0, ~0/2 + 1] as W), T(words:[~0, ~0, ~0, ~0/2 + 0] as W)) - NBKAssertOnesComplement(T(words:[~0, ~0, ~0, ~0/2 + 0] as W), T(words:[ 0, 0, 0, ~0/2 + 1] as W)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Two's Complement - //=------------------------------------------------------------------------= - - func testTwosComplement() { - NBKAssertTwosComplement(T(words:[ 0, 0, 0, 0] as W), T(words:[ 0, 0, 0, 0] as W), true) - NBKAssertTwosComplement(T(words:[ 1, 0, 0, 0] as W), T(words:[~0, 0, 0, 0] as W)) - NBKAssertTwosComplement(T(words:[~0, 0, 0, 0] as W), T(words:[ 1, 0, 0, 0] as W)) - NBKAssertTwosComplement(T(words:[ 1, 1, 1, 1] as W), T(words:[~0, ~1, ~1, ~1] as W)) - NBKAssertTwosComplement(T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 1, 0, 0, 0] as W)) - - NBKAssertTwosComplement(T(words:[~0, ~0, ~0, ~0/2 + 0] as W), T(words:[ 1, 0, 0, ~0/2 + 1] as W)) - NBKAssertTwosComplement(T(words:[ 0, 0, 0, ~0/2 + 1] as W), T(words:[ 0, 0, 0, ~0/2 + 1] as W)) - NBKAssertTwosComplement(T(words:[ 1, 0, 0, ~0/2 + 1] as W), T(words:[~0, ~0, ~0, ~0/2 + 0] as W)) - - NBKAssertTwosComplement(T(words:[ 1, 0, 0, ~0/2 + 1] as W), T(words:[~0, ~0, ~0, ~0/2 + 0] as W)) - NBKAssertTwosComplement(T(words:[ 0, 0, 0, ~0/2 + 1] as W), T(words:[ 0, 0, 0, ~0/2 + 1] as W)) - NBKAssertTwosComplement(T(words:[~0, ~0, ~0, ~0/2 + 0] as W), T(words:[ 1, 0, 0, ~0/2 + 1] as W)) - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Complements x Assertions -//*============================================================================* - -private func NBKAssertOnesComplement( -_ integer: T, _ result: T, -file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual(integer.onesComplement(), result, file: file, line: line) - XCTAssertEqual(integer.twosComplementSubsequence(false).partialValue, result, file: file, line: line) - - XCTAssertEqual({ var x = integer; let _ = x.formOnesComplement(); return x }(), result, file: file, line: line) - XCTAssertEqual({ var x = integer; let _ = x.formTwosComplementSubsequence(false); return x }(), result, file: file, line: line) -} - -private func NBKAssertTwosComplement( -_ integer: T, _ partialValue: T, _ overflow: Bool = false, -file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual(integer.twosComplement(), partialValue, file: file, line: line) - XCTAssertEqual(integer.twosComplementReportingOverflow().partialValue, partialValue, file: file, line: line) - XCTAssertEqual(integer.twosComplementReportingOverflow().overflow, overflow, file: file, line: line) - XCTAssertEqual(integer.twosComplementSubsequence(true ).partialValue, partialValue, file: file, line: line) - XCTAssertEqual(integer.twosComplementSubsequence(true ).overflow, overflow, file: file, line: line) - - XCTAssertEqual({ var x = integer; x.formTwosComplement(); return x }(), partialValue, file: file, line: line) - XCTAssertEqual({ var x = integer; let _ = x.formTwosComplementReportingOverflow(); return x }(), partialValue, file: file, line: line) - XCTAssertEqual({ var x = integer; let o = x.formTwosComplementReportingOverflow(); return o }(), overflow, file: file, line: line) - XCTAssertEqual({ var x = integer; let _ = x.formTwosComplementSubsequence(true ); return x }(), partialValue, file: file, line: line) - XCTAssertEqual({ var x = integer; let o = x.formTwosComplementSubsequence(true ); return o }(), overflow, file: file, line: line) -} - -private func NBKAssertAdditiveInverse( -_ operand: IntXL, _ partialValue: IntXL, _ overflow: Bool = false, -file: StaticString = #file, line: UInt = #line) { - //=------------------------------------------= - if !overflow { - XCTAssertEqual(-operand, partialValue, file: file, line: line) - XCTAssertEqual((operand).negated(), partialValue, file: file, line: line) - XCTAssertEqual({ var x = operand; x.negate(); return x }(), partialValue, file: file, line: line) - } - //=------------------------------------------= - XCTAssertEqual(operand.negatedReportingOverflow().partialValue, partialValue, file: file, line: line) - XCTAssertEqual(operand.negatedReportingOverflow().overflow, overflow, file: file, line: line) - - XCTAssertEqual({ var x = operand; let _ = x.negateReportingOverflow(); return x }(), partialValue, file: file, line: line) - XCTAssertEqual({ var x = operand; let o = x.negateReportingOverflow(); return o }(), overflow, file: file, line: line) -} - -#endif diff --git a/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Division.swift b/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Division.swift deleted file mode 100644 index 22ec78f8..00000000 --- a/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Division.swift +++ /dev/null @@ -1,371 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if DEBUG - -import NBKCoreKit -@testable import NBKTwosComplementKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Flexible Width x Division x IntXL -//*============================================================================* - -final class NBKFlexibleWidthTestsOnDivisionAsIntXL: XCTestCase { - - typealias T = IntXL - typealias M = UIntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testDividing() { - NBKAssertDivision( T( ), T(1), T( ), T( )) - NBKAssertDivision( T( ), T(2), T( ), T( )) - NBKAssertDivision( T(7), T(1), T(7), T( )) - NBKAssertDivision( T(7), T(2), T(3), T(1)) - - NBKAssertDivision( T(7), T(3), T(2), T(1)) - NBKAssertDivision( T(7), -T(3), -T(2), T(1)) - NBKAssertDivision(-T(7), T(3), -T(2), -T(1)) - NBKAssertDivision(-T(7), -T(3), T(2), -T(1)) - } - - func testDividingReportingOverflow() { - NBKAssertDivision( T(0), T( ), T(0), T( ), true) - NBKAssertDivision( T(1), T( ), T(1), T(1), true) - NBKAssertDivision( T(2), T( ), T(2), T(2), true) - - NBKAssertDivision(T(words:[~0, ~0, ~0, ~0/2 + 0] as W), -T(1), T(words:[1, 0, 0, ~0/2 + 1, ~0] as W), T( )) // Int256.max - NBKAssertDivision(T(words:[ 0, 0, 0, ~0/2 + 1] as W), -T(1), T(words:[0, 0, 0, ~0/2 + 1, 0] as W), T( )) // Int256.min - } - - func testDividingWithLargeDividend() { - NBKAssertDivision( T(words:[1, 2, 3, 4] as W), T(2), T(words:[0, ~0/2 + 2, 1, 2] as W), T(1)) - NBKAssertDivision( T(words:[1, 2, 3, 4] as W), -T(2), -T(words:[0, ~0/2 + 2, 1, 2] as W), T(1)) - NBKAssertDivision(-T(words:[1, 2, 3, 4] as W), T(2), -T(words:[0, ~0/2 + 2, 1, 2] as W), -T(1)) - NBKAssertDivision(-T(words:[1, 2, 3, 4] as W), -T(2), T(words:[0, ~0/2 + 2, 1, 2] as W), -T(1)) - - NBKAssertDivision( T(words:[1, 2, 3, 4] as W), T(words:[0, ~0/2 + 2, 1, 2] as W), T(2), T(1)) - NBKAssertDivision( T(words:[1, 2, 3, 4] as W), -T(words:[0, ~0/2 + 2, 1, 2] as W), -T(2), T(1)) - NBKAssertDivision(-T(words:[1, 2, 3, 4] as W), -T(words:[0, ~0/2 + 2, 1, 2] as W), T(2), -T(1)) - NBKAssertDivision(-T(words:[1, 2, 3, 4] as W), T(words:[0, ~0/2 + 2, 1, 2] as W), -T(2), -T(1)) - } - - func testDividingWithLargeDivisor() { - NBKAssertDivision(T(words:[1, 2, 3, 4 + 1 << 63] as W), T(words:[ 1, 2, 3, 4 &+ 1 << 63] as W), T(1), -T(words:[0, 0, 0, 0] as W)) - NBKAssertDivision(T(words:[1, 2, 3, 4 + 1 << 63] as W), T(words:[ 2, 3, 4, 5 &+ 1 << 63] as W), T(1), -T(words:[1, 1, 1, 1] as W)) - NBKAssertDivision(T(words:[1, 2, 3, 4 + 1 << 63] as W), T(words:[ 3, 4, 5, 6 &+ 1 << 63] as W), T(1), -T(words:[2, 2, 2, 2] as W)) - NBKAssertDivision(T(words:[1, 2, 3, 4 + 1 << 63] as W), T(words:[ 4, 5, 6, 7 &+ 1 << 63] as W), T(1), -T(words:[3, 3, 3, 3] as W)) - - NBKAssertDivision(T(words:[1, 2, 3, 4 + 1 << 63] as W), T(words:[~0, ~2, ~3, ~4 &+ 1 << 63] as W), -T(1), -T(words:[0, 0, 0, 0] as W)) - NBKAssertDivision(T(words:[1, 2, 3, 4 + 1 << 63] as W), T(words:[~1, ~3, ~4, ~5 &+ 1 << 63] as W), -T(1), -T(words:[1, 1, 1, 1] as W)) - NBKAssertDivision(T(words:[1, 2, 3, 4 + 1 << 63] as W), T(words:[~2, ~4, ~5, ~6 &+ 1 << 63] as W), -T(1), -T(words:[2, 2, 2, 2] as W)) - NBKAssertDivision(T(words:[1, 2, 3, 4 + 1 << 63] as W), T(words:[~3, ~5, ~6, ~7 &+ 1 << 63] as W), -T(1), -T(words:[3, 3, 3, 3] as W)) - } - - func testDividingLikeFullWidth() { - var dividend: T - //=--------------------------------------= - dividend = T(words:[ 06, 17, 35, 61, 61, 52, 32, 00] as W) - NBKAssertDivision(dividend, T(words:[ 1, 2, 3, 4] as W), T(words:[ 5, 6, 7, 8] as W), T(words:[ 1, 1, 1, 1] as W)) - NBKAssertDivision(dividend, T(words:[ 5, 6, 7, 8] as W), T(words:[ 1, 2, 3, 4] as W), T(words:[ 1, 1, 1, 1] as W)) - //=--------------------------------------= - dividend = T(words:[ 34, 54, 63, 62, 34, 16, 05, 00] as W) - NBKAssertDivision(dividend, T(words:[ 4, 3, 2, 1] as W), T(words:[ 9, 7, 6, 5] as W), T(words:[~1, ~1, ~0, 0] as W)) - NBKAssertDivision(dividend, T(words:[ 8, 7, 6, 5] as W), T(words:[ 4, 3, 2, 1] as W), T(words:[ 2, 2, 2, 2] as W)) - //=--------------------------------------= - dividend = T(words:[ ~1, ~0, ~0, ~0, ~0, ~0, ~0, ~0] as W) - NBKAssertDivision(dividend, T(words:[ 1, 0, 0, 0] as W), T(words:[~1, ~0, ~0, ~0] as W), T(words:[ 0, 0, 0, 0] as W)) - NBKAssertDivision(dividend, T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 2, 0, 0, 0] as W), T(words:[ 0, 0, 0, 0] as W)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Digit - //=------------------------------------------------------------------------= - - func testDividingByDigit() { - NBKAssertDivisionByDigit( T( ), Int(1), T( ), Int( )) - NBKAssertDivisionByDigit( T( ), Int(2), T( ), Int( )) - NBKAssertDivisionByDigit( T(7), Int(1), T(7), Int( )) - NBKAssertDivisionByDigit( T(7), Int(2), T(3), Int(1)) - - NBKAssertDivisionByDigit( T(7), Int(3), T(2), Int(1)) - NBKAssertDivisionByDigit( T(7), -Int(3), -T(2), Int(1)) - NBKAssertDivisionByDigit(-T(7), Int(3), -T(2), -Int(1)) - NBKAssertDivisionByDigit(-T(7), -Int(3), T(2), -Int(1)) - } - - func testDividingByDigitReportingOverflow() { - NBKAssertDivisionByDigit( T(0), Int( ), T( 0), Int( ), true) - NBKAssertDivisionByDigit( T(1), Int( ), T( 1), Int(1), true) - NBKAssertDivisionByDigit( T(2), Int( ), T( 2), Int(2), true) - - NBKAssertDivisionByDigit(T(words:[~0, ~0, ~0, ~0/2 + 0] as W), -Int(1), T(words:[1, 0, 0, ~0/2 + 1, ~0] as W), Int( )) // Int256.max - NBKAssertDivisionByDigit(T(words:[ 0, 0, 0, ~0/2 + 1] as W), -Int(1), T(words:[0, 0, 0, ~0/2 + 1, 0] as W), Int( )) // Int256.min - } - - func testDividingByDigitWithLargeDividend() { - NBKAssertDivisionByDigit( T(words:[1, 2, 3, 4] as W), Int(2), T(words:[0, ~0/2 + 2, 1, 2] as W), Int(1)) - NBKAssertDivisionByDigit( T(words:[1, 2, 3, 4] as W), -Int(2), -T(words:[0, ~0/2 + 2, 1, 2] as W), Int(1)) - NBKAssertDivisionByDigit(-T(words:[1, 2, 3, 4] as W), Int(2), -T(words:[0, ~0/2 + 2, 1, 2] as W), -Int(1)) - NBKAssertDivisionByDigit(-T(words:[1, 2, 3, 4] as W), -Int(2), T(words:[0, ~0/2 + 2, 1, 2] as W), -Int(1)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Miscellaneous - //=------------------------------------------------------------------------= - - func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { - func becauseThisCompilesSuccessfully(_ x: inout T) { - XCTAssertNotNil(x /= 0) - XCTAssertNotNil(x %= 0) - XCTAssertNotNil(x.divideReportingOverflow(by: 0)) - XCTAssertNotNil(x.formRemainderReportingOverflow(dividingBy: 0)) - - XCTAssertNotNil(x / 0) - XCTAssertNotNil(x % 0) - XCTAssertNotNil(x.dividedReportingOverflow(by: 0)) - XCTAssertNotNil(x.remainderReportingOverflow(dividingBy: 0)) - XCTAssertNotNil(x.quotientAndRemainder(dividingBy: 0)) - XCTAssertNotNil(x.quotientAndRemainderReportingOverflow(dividingBy: 0)) - } - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Division x UIntXL -//*============================================================================* - -final class NBKFlexibleWidthTestsOnDivisionAsUIntXL: XCTestCase { - - typealias T = UIntXL - typealias M = UIntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testDividing() { - NBKAssertDivision(T( ), T(1), T( ), T( )) - NBKAssertDivision(T( ), T(2), T( ), T( )) - NBKAssertDivision(T(7), T(1), T(7), T( )) - NBKAssertDivision(T(7), T(2), T(3), T(1)) - } - - func testDividingReportingOverflow() { - NBKAssertDivision(T( ), T( ), T( ), T( ), true) - NBKAssertDivision(T(1), T( ), T(1), T(1), true) - NBKAssertDivision(T(2), T( ), T(2), T(2), true) - } - - func testDividingWithLargeDividend() { - NBKAssertDivision(T(x64:[~2, ~4, ~6, 9] as X), T(2), T(x64:[~1, ~2, ~3, 4] as X), T(1)) - NBKAssertDivision(T(x64:[~3, ~6, ~9, 14] as X), T(3), T(x64:[~1, ~2, ~3, 4] as X), T(2)) - NBKAssertDivision(T(x64:[~4, ~8, ~12, 19] as X), T(4), T(x64:[~1, ~2, ~3, 4] as X), T(3)) - NBKAssertDivision(T(x64:[~5, ~10, ~15, 24] as X), T(5), T(x64:[~1, ~2, ~3, 4] as X), T(4)) - - NBKAssertDivision(T(x64:[~2, ~4, ~6, 9] as X), T(x64:[~1, ~2, ~3, 4] as X), T(2), T(1)) - NBKAssertDivision(T(x64:[~3, ~6, ~9, 14] as X), T(x64:[~1, ~2, ~3, 4] as X), T(3), T(2)) - NBKAssertDivision(T(x64:[~4, ~8, ~12, 19] as X), T(x64:[~1, ~2, ~3, 4] as X), T(4), T(3)) - NBKAssertDivision(T(x64:[~5, ~10, ~15, 24] as X), T(x64:[~1, ~2, ~3, 4] as X), T(5), T(4)) - } - - func testDividingWithLargeDivisor() { - NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X), T(x64:[ 3, 4, 5, 6 &+ 1 << 63] as X), T(0), T(x64:[1, 2, 3, 4 + 1 << 63] as X)) - NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X), T(x64:[ 2, 3, 4, 5 &+ 1 << 63] as X), T(0), T(x64:[1, 2, 3, 4 + 1 << 63] as X)) - - NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X), T(x64:[ 1, 2, 3, 4 &+ 1 << 63] as X), T(1), T(x64:[0, 0, 0, 0] as X)) - NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X), T(x64:[ 0, 1, 2, 3 &+ 1 << 63] as X), T(1), T(x64:[1, 1, 1, 1] as X)) - NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X), T(x64:[~0, ~0, 0, 2 &+ 1 << 63] as X), T(1), T(x64:[2, 2, 2, 2] as X)) - NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X), T(x64:[~1, ~1, ~0, 0 &+ 1 << 63] as X), T(1), T(x64:[3, 3, 3, 3] as X)) - - NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X), T(x64:[~2, ~2, ~1, ~0 &+ 1 << 63] as X), T(1), T(x64:[4, 4, 4, 4] as X)) - NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X), T(x64:[~3, ~3, ~2, ~1 &+ 1 << 63] as X), T(1), T(x64:[5, 5, 5, 5] as X)) - NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X), T(x64:[~4, ~4, ~3, ~2 &+ 1 << 63] as X), T(1), T(x64:[6, 6, 6, 6] as X)) - NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X), T(x64:[~5, ~5, ~4, ~3 &+ 1 << 63] as X), T(1), T(x64:[7, 7, 7, 7] as X)) - } - - func testDividingLikeFullWidth() { - var dividend: T - //=--------------------------------------= - dividend = T(words:[ 06, 17, 35, 61, 61, 52, 32, 00] as W) - NBKAssertDivision(dividend, T(words:[ 1, 2, 3, 4] as W), T(words:[ 5, 6, 7, 8] as W), T(words:[ 1, 1, 1, 1] as W)) - NBKAssertDivision(dividend, T(words:[ 5, 6, 7, 8] as W), T(words:[ 1, 2, 3, 4] as W), T(words:[ 1, 1, 1, 1] as W)) - //=--------------------------------------= - dividend = T(words:[ 34, 54, 63, 62, 34, 16, 05, 00] as W) - NBKAssertDivision(dividend, T(words:[ 4, 3, 2, 1] as W), T(words:[ 9, 7, 6, 5] as W), T(words:[~1, ~1, ~0, 0] as W)) - NBKAssertDivision(dividend, T(words:[ 8, 7, 6, 5] as W), T(words:[ 4, 3, 2, 1] as W), T(words:[ 2, 2, 2, 2] as W)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Digit - //=------------------------------------------------------------------------= - - func testDividingByDigit() { - NBKAssertDivisionByDigit(T( ), UInt(1), T( ), UInt( )) - NBKAssertDivisionByDigit(T( ), UInt(2), T( ), UInt( )) - NBKAssertDivisionByDigit(T(7), UInt(1), T(7), UInt( )) - NBKAssertDivisionByDigit(T(7), UInt(2), T(3), UInt(1)) - } - - func testDividingByDigitReportingOverflow() { - NBKAssertDivisionByDigit(T( ), UInt( ), T( ), UInt( ), true) - NBKAssertDivisionByDigit(T(1), UInt( ), T(1), UInt(1), true) - NBKAssertDivisionByDigit(T(2), UInt( ), T(2), UInt(2), true) - } - - func testDividingByDigitWithLargeDividend() { - NBKAssertDivisionByDigit(T(words:[~2, ~4, ~6, 9] as W), UInt(2), T(words:[~1, ~2, ~3, 4] as W), UInt(1)) - NBKAssertDivisionByDigit(T(words:[~3, ~6, ~9, 14] as W), UInt(3), T(words:[~1, ~2, ~3, 4] as W), UInt(2)) - NBKAssertDivisionByDigit(T(words:[~4, ~8, ~12, 19] as W), UInt(4), T(words:[~1, ~2, ~3, 4] as W), UInt(3)) - NBKAssertDivisionByDigit(T(words:[~5, ~10, ~15, 24] as W), UInt(5), T(words:[~1, ~2, ~3, 4] as W), UInt(4)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Miscellaneous - //=------------------------------------------------------------------------= - - func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { - func becauseThisCompilesSuccessfully(_ x: inout T) { - XCTAssertNotNil(x /= 0) - XCTAssertNotNil(x %= 0) - XCTAssertNotNil(x.divideReportingOverflow(by: 0)) - XCTAssertNotNil(x.formRemainderReportingOverflow(dividingBy: 0)) - - XCTAssertNotNil(x / 0) - XCTAssertNotNil(x % 0) - XCTAssertNotNil(x.dividedReportingOverflow(by: 0)) - XCTAssertNotNil(x.remainderReportingOverflow(dividingBy: 0)) - XCTAssertNotNil(x.quotientAndRemainder(dividingBy: 0)) - XCTAssertNotNil(x.quotientAndRemainderReportingOverflow(dividingBy: 0)) - } - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Division x UIntXL x Code Coverage -//*============================================================================* - -final class NBKFlexibleWidthTestsOnDivisionCodeCoverageAsUIntXL: XCTestCase { - - typealias T = UIntXL - typealias M = UIntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testDividingFullWidth3212MSBAsUInt256() { - var dividend: T, divisor: T, quotient: T, remainder: T - //=--------------------------------------= - dividend = T(x64:[ 0, 0, 0, 0, 0, ~0, ~0, ~0] as X) - divisor = T(x64:[~0, ~0, ~0, ~0, 0, 0, 0, 0] as X) - quotient = T(x64:[ 0, ~0, ~0, ~0, 0, 0, 0, 0] as X) - remainder = T(x64:[ 0, ~0, ~0, ~0, 0, 0, 0, 0] as X) - NBKAssertDivision(dividend, divisor, quotient, remainder) - //=--------------------------------------= - dividend = T(x64:[~0, ~0, ~0, ~0, 0, ~0, ~0, ~0] as X) - divisor = T(x64:[~0, ~0, ~0, ~0, 0, 0, 0, 0] as X) - quotient = T(x64:[ 1, ~0, ~0, ~0, 0, 0, 0, 0] as X) - remainder = T(x64:[ 0, ~0, ~0, ~0, 0, 0, 0, 0] as X) - NBKAssertDivision(dividend, divisor, quotient, remainder) - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Division x Assertions -//*============================================================================* - -private func NBKAssertDivision( -_ lhs: T, _ rhs: T, _ quotient: T, _ remainder: T, _ overflow: Bool = false, -file: StaticString = #file, line: UInt = #line) { - //=------------------------------------------= - XCTAssertEqual(lhs, quotient * rhs + remainder, "dividend != divisor * quotient + remainder", file: file, line: line) - //=------------------------------------------= - if !overflow { - XCTAssertEqual(lhs / rhs, quotient, file: file, line: line) - XCTAssertEqual(lhs % rhs, remainder, file: file, line: line) - - XCTAssertEqual({ var x = lhs; x /= rhs; return x }(), quotient, file: file, line: line) - XCTAssertEqual({ var x = lhs; x %= rhs; return x }(), remainder, file: file, line: line) - - XCTAssertEqual(lhs.quotientAndRemainder(dividingBy: rhs).quotient, quotient, file: file, line: line) - XCTAssertEqual(lhs.quotientAndRemainder(dividingBy: rhs).remainder, remainder, file: file, line: line) - } - //=------------------------------------------= - XCTAssertEqual(lhs.dividedReportingOverflow(by: rhs).partialValue, quotient, file: file, line: line) - XCTAssertEqual(lhs.dividedReportingOverflow(by: rhs).overflow, overflow, file: file, line: line) - - XCTAssertEqual({ var x = lhs; let _ = x.divideReportingOverflow(by: rhs); return x }(), quotient, file: file, line: line) - XCTAssertEqual({ var x = lhs; let o = x.divideReportingOverflow(by: rhs); return o }(), overflow, file: file, line: line) - - XCTAssertEqual(lhs.remainderReportingOverflow(dividingBy: rhs).partialValue, remainder, file: file, line: line) - XCTAssertEqual(lhs.remainderReportingOverflow(dividingBy: rhs).overflow, overflow, file: file, line: line) - - XCTAssertEqual({ var x = lhs; let _ = x.formRemainderReportingOverflow(dividingBy: rhs); return x }(), remainder, file: file, line: line) - XCTAssertEqual({ var x = lhs; let o = x.formRemainderReportingOverflow(dividingBy: rhs); return o }(), overflow, file: file, line: line) - - XCTAssertEqual(lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs).partialValue.quotient, quotient, file: file, line: line) - XCTAssertEqual(lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs).partialValue.remainder, remainder, file: file, line: line) - XCTAssertEqual(lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs).overflow, overflow, file: file, line: line) - //=------------------------------------------= - guard - let lhs = lhs as? UIntXL, - let rhs = rhs as? UIntXL, - let quotient = quotient as? UIntXL, - let remainder = remainder as? UIntXL - else { return } - //=------------------------------------------= - XCTAssertEqual(lhs.quotientAndRemainderReportingOverflowAsNormal(dividingBy: rhs).partialValue.quotient, quotient, file: file, line: line) - XCTAssertEqual(lhs.quotientAndRemainderReportingOverflowAsNormal(dividingBy: rhs).partialValue.remainder, remainder, file: file, line: line) - XCTAssertEqual(lhs.quotientAndRemainderReportingOverflowAsNormal(dividingBy: rhs).overflow, overflow, file: file, line: line) -} - -private func NBKAssertDivisionByDigit( -_ lhs: T, _ rhs: T.Digit, _ quotient: T, _ remainder: T.Digit, _ overflow: Bool = false, -file: StaticString = #file, line: UInt = #line) { - let extended = T(digit: remainder) - //=------------------------------------------= - XCTAssertEqual(lhs, quotient * rhs + remainder, "dividend != divisor * quotient + remainder", file: file, line: line) - //=------------------------------------------= - if !overflow { - XCTAssertEqual(lhs / rhs, quotient, file: file, line: line) - XCTAssertEqual(lhs % rhs, remainder, file: file, line: line) - - XCTAssertEqual({ var x = lhs; x /= rhs; return x }(), quotient, file: file, line: line) - XCTAssertEqual({ var x = lhs; x %= rhs; return x }(), extended, file: file, line: line) - - XCTAssertEqual(lhs.quotientAndRemainder(dividingBy: rhs).quotient, quotient, file: file, line: line) - XCTAssertEqual(lhs.quotientAndRemainder(dividingBy: rhs).remainder, remainder, file: file, line: line) - } - //=------------------------------------------= - XCTAssertEqual(lhs.dividedReportingOverflow(by: rhs).partialValue, quotient, file: file, line: line) - XCTAssertEqual(lhs.dividedReportingOverflow(by: rhs).overflow, overflow, file: file, line: line) - - XCTAssertEqual({ var x = lhs; let _ = x.divideReportingOverflow(by: rhs); return x }(), quotient, file: file, line: line) - XCTAssertEqual({ var x = lhs; let o = x.divideReportingOverflow(by: rhs); return o }(), overflow, file: file, line: line) - - XCTAssertEqual(lhs.remainderReportingOverflow(dividingBy: rhs).partialValue, remainder, file: file, line: line) - XCTAssertEqual(lhs.remainderReportingOverflow(dividingBy: rhs).overflow, overflow, file: file, line: line) - - XCTAssertEqual({ var x = lhs; let _ = x.formRemainderReportingOverflow(dividingBy: rhs); return x }(), extended, file: file, line: line) - XCTAssertEqual({ var x = lhs; let o = x.formRemainderReportingOverflow(dividingBy: rhs); return o }(), overflow, file: file, line: line) - - XCTAssertEqual(lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs).partialValue.quotient, quotient, file: file, line: line) - XCTAssertEqual(lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs).partialValue.remainder, remainder, file: file, line: line) - XCTAssertEqual(lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs).overflow, overflow, file: file, line: line) -} - -#endif diff --git a/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Literals.swift b/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Literals.swift deleted file mode 100644 index b07b6a97..00000000 --- a/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Literals.swift +++ /dev/null @@ -1,168 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if DEBUG - -import NBKCoreKit -@testable import NBKTwosComplementKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Flexible Width x Literals x IntXL -//*============================================================================* - -final class NBKFlexibleWidthTestsOnLiteralsAsIntXL: XCTestCase { - - typealias T = IntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testFromIntegerLiteral() { - XCTAssertEqual(T(x64:[ 10, 0, 0, 0] as X), (10)) - XCTAssertEqual(T(x64:[ 02, 0, 0, 0] as X), (0b10)) - XCTAssertEqual(T(x64:[ 08, 0, 0, 0] as X), (0o10)) - XCTAssertEqual(T(x64:[ 16, 0, 0, 0] as X), (0x10)) - XCTAssertEqual(T(x64:[ 16, 0, 0, 0] as X), (0x10)) - XCTAssertEqual(T(x64:[ ~9, ~0, ~0, ~0] as X), (-10)) - XCTAssertEqual(T(x64:[ ~1, ~0, ~0, ~0] as X), (-0b10)) - XCTAssertEqual(T(x64:[ ~7, ~0, ~0, ~0] as X), (-0o10)) - XCTAssertEqual(T(x64:[~15, ~0, ~0, ~0] as X), (-0x10)) - #if SBI && swift(>=5.8) - XCTAssertEqual(T(x64:[ 0, 0, 0, 0] as X), (0x000000000000000000000000000000000000000000000000000000000000000000000000000000)) - XCTAssertEqual(T(x64:[ ~0, 0, 0, 0] as X), (0x00000000000000000000000000000000000000000000000000000000000000ffffffffffffffff)) - XCTAssertEqual(T(x64:[ ~0, ~0, 0, 0] as X), (0x0000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffff)) - XCTAssertEqual(T(x64:[ ~0, ~0, ~0, 0] as X), (0x000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff)) - XCTAssertEqual(T(x64:[ ~0, ~0, ~0, ~0] as X), (-0x000000000000000000000000000000000000000000000000000000000000000000000000000001)) - XCTAssertEqual(T(x64:[ 0, ~0, ~0, ~0] as X), (-0x000000000000000000000000000000000000000000000000000000000000010000000000000000)) - XCTAssertEqual(T(x64:[ 0, 0, ~0, ~0] as X), (-0x000000000000000000000000000000000000000000000100000000000000000000000000000000)) - XCTAssertEqual(T(x64:[ 0, 0, 0, ~0] as X), (-0x000000000000000000000000000001000000000000000000000000000000000000000000000000)) - - XCTAssertEqual(T(x64:[ 0, 0, 0, 0] as X), (00000000000000000000000000000000000000000000000000000000000000000000000000000000)) - XCTAssertEqual(T(x64:[ ~0, 0, 0, 0] as X), (00000000000000000000000000000000000000000000000000000000000018446744073709551615)) - XCTAssertEqual(T(x64:[ ~0, ~0, 0, 0] as X), (00000000000000000000000000000000000000000340282366920938463463374607431768211455)) - XCTAssertEqual(T(x64:[ ~0, ~0, ~0, 0] as X), (00000000000000000000006277101735386680763835789423207666416102355444464034512895)) - XCTAssertEqual(T(x64:[ ~0, ~0, ~0, ~0] as X), (-00000000000000000000000000000000000000000000000000000000000000000000000000000001)) - XCTAssertEqual(T(x64:[ 0, ~0, ~0, ~0] as X), (-00000000000000000000000000000000000000000000000000000000000018446744073709551616)) - XCTAssertEqual(T(x64:[ 0, 0, ~0, ~0] as X), (-00000000000000000000000000000000000000000340282366920938463463374607431768211456)) - XCTAssertEqual(T(x64:[ 0, 0, 0, ~0] as X), (-00000000000000000000006277101735386680763835789423207666416102355444464034512896)) - #else - XCTAssertEqual(T(integerLiteral: Int.max), T(x64:[UInt64(Int.max), 0, 0, 0] as X)) - XCTAssertEqual(T(integerLiteral: Int.min), ~T(x64:[UInt64(Int.max), 0, 0, 0] as X)) - #endif - } - - func testFromStringLiteral() { - XCTAssertEqual(T(x64:[ 10, 0, 0, 0] as X), "10") - XCTAssertEqual(T(x64:[ 02, 0, 0, 0] as X), "0b10") - XCTAssertEqual(T(x64:[ 08, 0, 0, 0] as X), "0o10") - XCTAssertEqual(T(x64:[ 16, 0, 0, 0] as X), "0x10") - XCTAssertEqual(T(x64:[ 16, 0, 0, 0] as X), "0x10") - XCTAssertEqual(T(x64:[ ~9, ~0, ~0, ~0] as X), "-10") - XCTAssertEqual(T(x64:[ ~1, ~0, ~0, ~0] as X), "-0b10") - XCTAssertEqual(T(x64:[ ~7, ~0, ~0, ~0] as X), "-0o10") - XCTAssertEqual(T(x64:[~15, ~0, ~0, ~0] as X), "-0x10") - - XCTAssertEqual(T(x64:[ 0, 0, 0, 0] as X), "0x000000000000000000000000000000000000000000000000000000000000000000000000000000") - XCTAssertEqual(T(x64:[ ~0, 0, 0, 0] as X), "0x00000000000000000000000000000000000000000000000000000000000000ffffffffffffffff") - XCTAssertEqual(T(x64:[ ~0, ~0, 0, 0] as X), "0x0000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffff") - XCTAssertEqual(T(x64:[ ~0, ~0, ~0, 0] as X), "0x000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff") - XCTAssertEqual(T(x64:[ ~0, ~0, ~0, ~0] as X), "-0x000000000000000000000000000000000000000000000000000000000000000000000000000001") - XCTAssertEqual(T(x64:[ 0, ~0, ~0, ~0] as X), "-0x000000000000000000000000000000000000000000000000000000000000010000000000000000") - XCTAssertEqual(T(x64:[ 0, 0, ~0, ~0] as X), "-0x000000000000000000000000000000000000000000000100000000000000000000000000000000") - XCTAssertEqual(T(x64:[ 0, 0, 0, ~0] as X), "-0x000000000000000000000000000001000000000000000000000000000000000000000000000000") - - XCTAssertEqual(T(x64:[ 0, 0, 0, 0] as X), "00000000000000000000000000000000000000000000000000000000000000000000000000000000") - XCTAssertEqual(T(x64:[ ~0, 0, 0, 0] as X), "00000000000000000000000000000000000000000000000000000000000018446744073709551615") - XCTAssertEqual(T(x64:[ ~0, ~0, 0, 0] as X), "00000000000000000000000000000000000000000340282366920938463463374607431768211455") - XCTAssertEqual(T(x64:[ ~0, ~0, ~0, 0] as X), "00000000000000000000006277101735386680763835789423207666416102355444464034512895") - XCTAssertEqual(T(x64:[ ~0, ~0, ~0, ~0] as X), "-00000000000000000000000000000000000000000000000000000000000000000000000000000001") - XCTAssertEqual(T(x64:[ 0, ~0, ~0, ~0] as X), "-00000000000000000000000000000000000000000000000000000000000018446744073709551616") - XCTAssertEqual(T(x64:[ 0, 0, ~0, ~0] as X), "-00000000000000000000000000000000000000000340282366920938463463374607431768211456") - XCTAssertEqual(T(x64:[ 0, 0, 0, ~0] as X), "-00000000000000000000006277101735386680763835789423207666416102355444464034512896") - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Literals x UIntXL -//*============================================================================* - -final class NBKFlexibleWidthTestsOnLiteralsAsUIntXL: XCTestCase { - - typealias T = UIntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testFromIntegerLiteral() { - XCTAssertEqual(T(x64:[ 10, 0, 0, 0] as X), (10)) - XCTAssertEqual(T(x64:[ 02, 0, 0, 0] as X), (0b10)) - XCTAssertEqual(T(x64:[ 08, 0, 0, 0] as X), (0o10)) - XCTAssertEqual(T(x64:[ 16, 0, 0, 0] as X), (0x10)) - #if SBI && swift(>=5.8) - XCTAssertEqual(T(x64:[ 0, 0, 0, 0] as X), (0x000000000000000000000000000000000000000000000000000000000000000000000000000000)) - XCTAssertEqual(T(x64:[ ~0, 0, 0, 0] as X), (0x00000000000000000000000000000000000000000000000000000000000000ffffffffffffffff)) - XCTAssertEqual(T(x64:[ ~0, ~0, 0, 0] as X), (0x0000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffff)) - XCTAssertEqual(T(x64:[ ~0, ~0, ~0, 0] as X), (0x000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff)) - XCTAssertEqual(T(x64:[ ~0, ~0, ~0, ~0] as X), (0x00000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)) - XCTAssertEqual(T(x64:[ 0, ~0, ~0, ~0] as X), (0x00000000000000ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000)) - XCTAssertEqual(T(x64:[ 0, 0, ~0, ~0] as X), (0x00000000000000ffffffffffffffffffffffffffffffff00000000000000000000000000000000)) - XCTAssertEqual(T(x64:[ 0, 0, 0, ~0] as X), (0x00000000000000ffffffffffffffff000000000000000000000000000000000000000000000000)) - XCTAssertEqual(T(exactlyIntegerLiteral: (-0x000000000000000000000000000000000000000000000000000000000000000000000000000001)), nil) - - XCTAssertEqual(T(x64:[ 0, 0, 0, 0] as X), (00000000000000000000000000000000000000000000000000000000000000000000000000000000)) - XCTAssertEqual(T(x64:[ ~0, 0, 0, 0] as X), (00000000000000000000000000000000000000000000000000000000000018446744073709551615)) - XCTAssertEqual(T(x64:[ ~0, ~0, 0, 0] as X), (00000000000000000000000000000000000000000340282366920938463463374607431768211455)) - XCTAssertEqual(T(x64:[ ~0, ~0, ~0, 0] as X), (00000000000000000000006277101735386680763835789423207666416102355444464034512895)) - XCTAssertEqual(T(x64:[ ~0, ~0, ~0, ~0] as X), (00115792089237316195423570985008687907853269984665640564039457584007913129639935)) - XCTAssertEqual(T(x64:[ 0, ~0, ~0, ~0] as X), (00115792089237316195423570985008687907853269984665640564039439137263839420088320)) - XCTAssertEqual(T(x64:[ 0, 0, ~0, ~0] as X), (00115792089237316195423570985008687907852929702298719625575994209400481361428480)) - XCTAssertEqual(T(x64:[ 0, 0, 0, ~0] as X), (00115792089237316195417293883273301227089434195242432897623355228563449095127040)) - XCTAssertEqual(T(exactlyIntegerLiteral: (-00000000000000000000000000000000000000000000000000000000000000000000000000000001)), nil) - #else - XCTAssertEqual(T(integerLiteral: UInt.max), T(x64:[UInt64(UInt.max), 0, 0, 0] as X)) - XCTAssertEqual(T(integerLiteral: UInt.min), T(x64:[UInt64(UInt.min), 0, 0, 0] as X)) - #endif - } - - func testFromStringLiteral() { - XCTAssertEqual(T(x64:[ 10, 0, 0, 0] as X), "10") - XCTAssertEqual(T(x64:[ 02, 0, 0, 0] as X), "0b10") - XCTAssertEqual(T(x64:[ 08, 0, 0, 0] as X), "0o10") - XCTAssertEqual(T(x64:[ 16, 0, 0, 0] as X), "0x10") - - XCTAssertEqual(T(x64:[ 0, 0, 0, 0] as X), "0x000000000000000000000000000000000000000000000000000000000000000000000000000000") - XCTAssertEqual(T(x64:[ ~0, 0, 0, 0] as X), "0x00000000000000000000000000000000000000000000000000000000000000ffffffffffffffff") - XCTAssertEqual(T(x64:[ ~0, ~0, 0, 0] as X), "0x0000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffff") - XCTAssertEqual(T(x64:[ ~0, ~0, ~0, 0] as X), "0x000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff") - XCTAssertEqual(T(x64:[ ~0, ~0, ~0, ~0] as X), "0x00000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") - XCTAssertEqual(T(x64:[ 0, ~0, ~0, ~0] as X), "0x00000000000000ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000") - XCTAssertEqual(T(x64:[ 0, 0, ~0, ~0] as X), "0x00000000000000ffffffffffffffffffffffffffffffff00000000000000000000000000000000") - XCTAssertEqual(T(x64:[ 0, 0, 0, ~0] as X), "0x00000000000000ffffffffffffffff000000000000000000000000000000000000000000000000") - XCTAssertEqual(T(exactlyStringLiteral: "-0x000000000000000000000000000000000000000000000000000000000000000000000000000001"), nil) - - XCTAssertEqual(T(x64:[ 0, 0, 0, 0] as X), "00000000000000000000000000000000000000000000000000000000000000000000000000000000") - XCTAssertEqual(T(x64:[ ~0, 0, 0, 0] as X), "00000000000000000000000000000000000000000000000000000000000018446744073709551615") - XCTAssertEqual(T(x64:[ ~0, ~0, 0, 0] as X), "00000000000000000000000000000000000000000340282366920938463463374607431768211455") - XCTAssertEqual(T(x64:[ ~0, ~0, ~0, 0] as X), "00000000000000000000006277101735386680763835789423207666416102355444464034512895") - XCTAssertEqual(T(x64:[ ~0, ~0, ~0, ~0] as X), "00115792089237316195423570985008687907853269984665640564039457584007913129639935") - XCTAssertEqual(T(x64:[ 0, ~0, ~0, ~0] as X), "00115792089237316195423570985008687907853269984665640564039439137263839420088320") - XCTAssertEqual(T(x64:[ 0, 0, ~0, ~0] as X), "00115792089237316195423570985008687907852929702298719625575994209400481361428480") - XCTAssertEqual(T(x64:[ 0, 0, 0, ~0] as X), "00115792089237316195417293883273301227089434195242432897623355228563449095127040") - XCTAssertEqual(T(exactlyStringLiteral: "-00000000000000000000000000000000000000000000000000000000000000000000000000000001"), nil) - } -} - -#endif diff --git a/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Logic.swift b/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Logic.swift deleted file mode 100644 index 5a70aa71..00000000 --- a/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Logic.swift +++ /dev/null @@ -1,170 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if DEBUG - -import NBKCoreKit -import NBKTwosComplementKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Flexible Width x Logic x IntXL -//*============================================================================* - -final class NBKFlexibleWidthTestsOnLogicAsIntXL: XCTestCase { - - typealias T = IntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testNot() { - NBKAssertNot(T(words:[ 0, 0, 0, 0] as W), T(words:[~0, ~0, ~0, ~0] as W)) - NBKAssertNot(T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 0, 0, 0, 0] as W)) - - NBKAssertNot(T(words:[ 0, 1, 2, 3] as W), T(words:[~0, ~1, ~2, ~3] as W)) - NBKAssertNot(T(words:[~0, ~1, ~2, ~3] as W), T(words:[ 0, 1, 2, 3] as W)) - } - - func testAnd() { - NBKAssertAnd(T(words:[ 0, 1, 2, 3] as W), T(words:[ 0, 0, 0, 0] as W), T(words:[ 0, 0, 0, 0] as W)) - NBKAssertAnd(T(words:[ 3, 2, 1, 0] as W), T(words:[ 0, 0, 0, 0] as W), T(words:[ 0, 0, 0, 0] as W)) - - NBKAssertAnd(T(words:[ 0, 1, 2, 3] as W), T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 0, 1, 2, 3] as W)) - NBKAssertAnd(T(words:[ 3, 2, 1, 0] as W), T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 3, 2, 1, 0] as W)) - - NBKAssertAnd(T(words:[ 0, 1, 2, 3] as W), T(words:[ 1, 1, 1, 1] as W), T(words:[ 0, 1, 0, 1] as W)) - NBKAssertAnd(T(words:[ 3, 2, 1, 0] as W), T(words:[ 1, 1, 1, 1] as W), T(words:[ 1, 0, 1, 0] as W)) - } - - func testOr() { - NBKAssertOr (T(words:[ 0, 1, 2, 3] as W), T(words:[ 0, 0, 0, 0] as W), T(words:[ 0, 1, 2, 3] as W)) - NBKAssertOr (T(words:[ 3, 2, 1, 0] as W), T(words:[ 0, 0, 0, 0] as W), T(words:[ 3, 2, 1, 0] as W)) - - NBKAssertOr (T(words:[ 0, 1, 2, 3] as W), T(words:[~0, ~0, ~0, ~0] as W), T(words:[~0, ~0, ~0, ~0] as W)) - NBKAssertOr (T(words:[ 3, 2, 1, 0] as W), T(words:[~0, ~0, ~0, ~0] as W), T(words:[~0, ~0, ~0, ~0] as W)) - - NBKAssertOr (T(words:[ 0, 1, 2, 3] as W), T(words:[ 1, 1, 1, 1] as W), T(words:[ 1, 1, 3, 3] as W)) - NBKAssertOr (T(words:[ 3, 2, 1, 0] as W), T(words:[ 1, 1, 1, 1] as W), T(words:[ 3, 3, 1, 1] as W)) - } - - func testXor() { - NBKAssertXor(T(words:[ 0, 1, 2, 3] as W), T(words:[ 0, 0, 0, 0] as W), T(words:[ 0, 1, 2, 3] as W)) - NBKAssertXor(T(words:[ 3, 2, 1, 0] as W), T(words:[ 0, 0, 0, 0] as W), T(words:[ 3, 2, 1, 0] as W)) - - NBKAssertXor(T(words:[ 0, 1, 2, 3] as W), T(words:[~0, ~0, ~0, ~0] as W), T(words:[~0, ~1, ~2, ~3] as W)) - NBKAssertXor(T(words:[ 3, 2, 1, 0] as W), T(words:[~0, ~0, ~0, ~0] as W), T(words:[~3, ~2, ~1, ~0] as W)) - - NBKAssertXor(T(words:[ 0, 1, 2, 3] as W), T(words:[ 1, 1, 1, 1] as W), T(words:[ 1, 0, 3, 2] as W)) - NBKAssertXor(T(words:[ 3, 2, 1, 0] as W), T(words:[ 1, 1, 1, 1] as W), T(words:[ 2, 3, 0, 1] as W)) - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Logic x UIntXL -//*============================================================================* - -final class NBKFlexibleWidthTestsOnLogicAsUIntXL: XCTestCase { - - typealias T = UIntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testNot() { - NBKAssertNot(T(words:[ 0, 0, 0, 0] as W), T(words:[~0, 0, 0, 0] as W)) - NBKAssertNot(T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 0, 0, 0, 0] as W)) - - NBKAssertNot(T(words:[ 0, 1, 2, 3] as W), T(words:[~0, ~1, ~2, ~3] as W)) - NBKAssertNot(T(words:[~0, ~1, ~2, ~3] as W), T(words:[ 0, 1, 2, 3] as W)) - } - - func testAnd() { - NBKAssertAnd(T(words:[ 0, 1, 2, 3] as W), T(words:[ 0, 0, 0, 0] as W), T(words:[ 0, 0, 0, 0] as W)) - NBKAssertAnd(T(words:[ 3, 2, 1, 0] as W), T(words:[ 0, 0, 0, 0] as W), T(words:[ 0, 0, 0, 0] as W)) - - NBKAssertAnd(T(words:[ 0, 1, 2, 3] as W), T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 0, 1, 2, 3] as W)) - NBKAssertAnd(T(words:[ 3, 2, 1, 0] as W), T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 3, 2, 1, 0] as W)) - - NBKAssertAnd(T(words:[ 0, 1, 2, 3] as W), T(words:[ 1, 1, 1, 1] as W), T(words:[ 0, 1, 0, 1] as W)) - NBKAssertAnd(T(words:[ 3, 2, 1, 0] as W), T(words:[ 1, 1, 1, 1] as W), T(words:[ 1, 0, 1, 0] as W)) - } - - func testOr() { - NBKAssertOr (T(words:[ 0, 1, 2, 3] as W), T(words:[ 0, 0, 0, 0] as W), T(words:[ 0, 1, 2, 3] as W)) - NBKAssertOr (T(words:[ 3, 2, 1, 0] as W), T(words:[ 0, 0, 0, 0] as W), T(words:[ 3, 2, 1, 0] as W)) - - NBKAssertOr (T(words:[ 0, 1, 2, 3] as W), T(words:[~0, ~0, ~0, ~0] as W), T(words:[~0, ~0, ~0, ~0] as W)) - NBKAssertOr (T(words:[ 3, 2, 1, 0] as W), T(words:[~0, ~0, ~0, ~0] as W), T(words:[~0, ~0, ~0, ~0] as W)) - - NBKAssertOr (T(words:[ 0, 1, 2, 3] as W), T(words:[ 1, 1, 1, 1] as W), T(words:[ 1, 1, 3, 3] as W)) - NBKAssertOr (T(words:[ 3, 2, 1, 0] as W), T(words:[ 1, 1, 1, 1] as W), T(words:[ 3, 3, 1, 1] as W)) - } - - func testXor() { - NBKAssertXor(T(words:[ 0, 1, 2, 3] as W), T(words:[ 0, 0, 0, 0] as W), T(words:[ 0, 1, 2, 3] as W)) - NBKAssertXor(T(words:[ 3, 2, 1, 0] as W), T(words:[ 0, 0, 0, 0] as W), T(words:[ 3, 2, 1, 0] as W)) - - NBKAssertXor(T(words:[ 0, 1, 2, 3] as W), T(words:[~0, ~0, ~0, ~0] as W), T(words:[~0, ~1, ~2, ~3] as W)) - NBKAssertXor(T(words:[ 3, 2, 1, 0] as W), T(words:[~0, ~0, ~0, ~0] as W), T(words:[~3, ~2, ~1, ~0] as W)) - - NBKAssertXor(T(words:[ 0, 1, 2, 3] as W), T(words:[ 1, 1, 1, 1] as W), T(words:[ 1, 0, 3, 2] as W)) - NBKAssertXor(T(words:[ 3, 2, 1, 0] as W), T(words:[ 1, 1, 1, 1] as W), T(words:[ 2, 3, 0, 1] as W)) - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Logic x Assertions -//*============================================================================* - -private func NBKAssertNot( -_ operand: T, _ result: T, -file: StaticString = #file, line: UInt = #line) { - if operand.words.last != UInt.max { - XCTAssertEqual(~operand, result, file: file, line: line) - XCTAssertEqual(~result, operand, file: file, line: line) - } else { - XCTAssertEqual(~operand, result, file: file, line: line) - } -} - -private func NBKAssertAnd( -_ lhs: T, _ rhs: T, _ result: T, -file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual( lhs & rhs, result, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs &= rhs; return lhs }(), result, file: file, line: line) - XCTAssertEqual( rhs & lhs, result, file: file, line: line) - XCTAssertEqual({ var rhs = rhs; rhs &= lhs; return rhs }(), result, file: file, line: line) -} - -private func NBKAssertOr( -_ lhs: T, _ rhs: T, _ result: T, -file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual( lhs | rhs, result, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs |= rhs; return lhs }(), result, file: file, line: line) - XCTAssertEqual( rhs | lhs, result, file: file, line: line) - XCTAssertEqual({ var rhs = rhs; rhs |= lhs; return rhs }(), result, file: file, line: line) -} - -private func NBKAssertXor( -_ lhs: T, _ rhs: T, _ result: T, -file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual( lhs ^ rhs, result, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs ^= rhs; return lhs }(), result, file: file, line: line) - XCTAssertEqual( rhs ^ lhs, result, file: file, line: line) - XCTAssertEqual({ var rhs = rhs; rhs ^= lhs; return rhs }(), result, file: file, line: line) -} - -#endif diff --git a/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Multiplication.swift b/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Multiplication.swift deleted file mode 100644 index 5b0ef5e8..00000000 --- a/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Multiplication.swift +++ /dev/null @@ -1,172 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if DEBUG - -import NBKCoreKit -import NBKTwosComplementKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Flexible Width x Multiplication x IntXL -//*============================================================================* - -final class NBKFlexibleWidthTestsOnMultiplicationAsIntXL: XCTestCase { - - typealias T = IntXL - typealias M = UIntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testMultiplying() { - NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as W), T(words:[2, 0, 0, 0] as W), T(words:[ 2, 4, 6, 8, 0, 0, 0, 0] as W)) - NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as W), T(words:[0, 2, 0, 0] as W), T(words:[ 0, 2, 4, 6, 8, 0, 0, 0] as W)) - NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as W), T(words:[0, 0, 2, 0] as W), T(words:[ 0, 0, 2, 4, 6, 8, 0, 0] as W)) - NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as W), T(words:[0, 0, 0, 2] as W), T(words:[ 0, 0, 0, 2, 4, 6, 8, 0] as W)) - - NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as W), -T(words:[2, 0, 0, 0] as W), T(words:[~1, ~4, ~6, ~8, ~0, ~0, ~0, ~0] as W)) - NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as W), -T(words:[0, 2, 0, 0] as W), T(words:[ 0, ~1, ~4, ~6, ~8, ~0, ~0, ~0] as W)) - NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as W), -T(words:[0, 0, 2, 0] as W), T(words:[ 0, 0, ~1, ~4, ~6, ~8, ~0, ~0] as W)) - NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as W), -T(words:[0, 0, 0, 2] as W), T(words:[ 0, 0, 0, ~1, ~4, ~6, ~8, ~0] as W)) - - NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as W), T(words:[2, 0, 0, 0] as W), T(words:[~3, ~4, ~6, ~8, ~0, ~0, ~0, ~0] as W)) - NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as W), T(words:[0, 2, 0, 0] as W), T(words:[ 0, ~3, ~4, ~6, ~8, ~0, ~0, ~0] as W)) - NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as W), T(words:[0, 0, 2, 0] as W), T(words:[ 0, 0, ~3, ~4, ~6, ~8, ~0, ~0] as W)) - NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as W), T(words:[0, 0, 0, 2] as W), T(words:[ 0, 0, 0, ~3, ~4, ~6, ~8, ~0] as W)) - - NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as W), -T(words:[2, 0, 0, 0] as W), T(words:[ 4, 4, 6, 8, 0, 0, 0, 0] as W)) - NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as W), -T(words:[0, 2, 0, 0] as W), T(words:[ 0, 4, 4, 6, 8, 0, 0, 0] as W)) - NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as W), -T(words:[0, 0, 2, 0] as W), T(words:[ 0, 0, 4, 4, 6, 8, 0, 0] as W)) - NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as W), -T(words:[0, 0, 0, 2] as W), T(words:[ 0, 0, 0, 4, 4, 6, 8, 0] as W)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Digit - //=------------------------------------------------------------------------= - - func testMultiplyingByDigit() { - NBKAssertMultiplicationByDigit(T(words:[ 1, 2, 3, 4] as W), Int(2), T(words:[ 2, 4, 6, 8, 0] as W)) - NBKAssertMultiplicationByDigit(T(words:[ 1, 2, 3, 4] as W), -Int(2), T(words:[~1, ~4, ~6, ~8, ~0] as W)) - NBKAssertMultiplicationByDigit(T(words:[~1, ~2, ~3, ~4] as W), Int(2), T(words:[~3, ~4, ~6, ~8, ~0] as W)) - NBKAssertMultiplicationByDigit(T(words:[~1, ~2, ~3, ~4] as W), -Int(2), T(words:[ 4, 4, 6, 8, 0] as W)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Miscellaneous - //=------------------------------------------------------------------------= - - func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { - func becauseThisCompilesSuccessfully(_ x: inout T) { - XCTAssertNotNil(x *= 0) - XCTAssertNotNil(x * 0) - } - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Multiplication x UIntXL -//*============================================================================* - -final class NBKFlexibleWidthTestsOnMultiplicationAsUIntXL: XCTestCase { - - typealias T = UIntXL - typealias M = UIntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testMultiplying() { - NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as W), T(words:[2, 0, 0, 0] as W), T(words:[ 2, 4, 6, 8, 0, 0, 0, 0] as W)) - NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as W), T(words:[0, 2, 0, 0] as W), T(words:[ 0, 2, 4, 6, 8, 0, 0, 0] as W)) - NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as W), T(words:[0, 0, 2, 0] as W), T(words:[ 0, 0, 2, 4, 6, 8, 0, 0] as W)) - NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as W), T(words:[0, 0, 0, 2] as W), T(words:[ 0, 0, 0, 2, 4, 6, 8, 0] as W)) - - NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as W), T(words:[2, 0, 0, 0] as W), T(words:[~3, ~4, ~6, ~8, 1, 0, 0, 0] as W)) - NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as W), T(words:[0, 2, 0, 0] as W), T(words:[ 0, ~3, ~4, ~6, ~8, 1, 0, 0] as W)) - NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as W), T(words:[0, 0, 2, 0] as W), T(words:[ 0, 0, ~3, ~4, ~6, ~8, 1, 0] as W)) - NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as W), T(words:[0, 0, 0, 2] as W), T(words:[ 0, 0, 0, ~3, ~4, ~6, ~8, 1] as W)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Digit - //=------------------------------------------------------------------------= - - func testMultipliedByDigit() { - NBKAssertMultiplicationByDigit(T(words:[1, 2, 3, 4] as W), UInt(0), T(words:[ 0, 0, 0, 0, 0] as W)) - NBKAssertMultiplicationByDigit(T(words:[1, 2, 3, 4] as W), UInt(1), T(words:[ 1, 2, 3, 4, 0] as W)) - NBKAssertMultiplicationByDigit(T(words:[1, 2, 3, 4] as W), UInt(2), T(words:[ 2, 4, 6, 8, 0] as W)) - - NBKAssertMultiplicationByDigit(T(words:[1, 2, 3, 4] as W), ~UInt(0), ~T(words:[ 0, 1, 1, 1, ~3] as W)) - NBKAssertMultiplicationByDigit(T(words:[1, 2, 3, 4] as W), ~UInt(1), ~T(words:[ 1, 3, 4, 5, ~3] as W)) - NBKAssertMultiplicationByDigit(T(words:[1, 2, 3, 4] as W), ~UInt(2), ~T(words:[ 2, 5, 7, 9, ~3] as W)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Digit x Addition - //=------------------------------------------------------------------------= - - func testMultiplicationByDigitWithAddition() { - NBKAssertMultiplicationByDigitWithAddition(T(words:[~0, ~0, ~0, ~0] as W), 0, 0, T(words:[ 0, 0, 0, 0, 0] as W)) - NBKAssertMultiplicationByDigitWithAddition(T(words:[~0, ~0, ~0, ~0] as W), 0, ~0, T(words:[~0, 0, 0, 0, 0] as W)) - NBKAssertMultiplicationByDigitWithAddition(T(words:[~0, ~0, ~0, ~0] as W), ~0, 0, T(words:[ 1, ~0, ~0, ~0, ~1] as W)) - NBKAssertMultiplicationByDigitWithAddition(T(words:[~0, ~0, ~0, ~0] as W), ~0, ~0, T(words:[ 0, 0, 0, 0, ~0] as W)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Miscellaneous - //=------------------------------------------------------------------------= - - func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { - func becauseThisCompilesSuccessfully(_ x: inout T) { - XCTAssertNotNil(x *= 0) - XCTAssertNotNil(x.multiply(by: 0, add: 0)) - - XCTAssertNotNil(x * 0) - XCTAssertNotNil(x.multiplied(by: 0, adding: 0)) - } - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Multiplication x Assertions -//*============================================================================* - -private func NBKAssertMultiplication( -_ lhs: T, _ rhs: T, _ result: T, -file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual( lhs * rhs, result, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs *= rhs; return lhs }(), result, file: file, line: line) -} - -private func NBKAssertMultiplicationByDigit( -_ lhs: T, _ rhs: T.Digit, _ result: T, -file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual( lhs * rhs, result, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs *= rhs; return lhs }(), result, file: file, line: line) -} - -//=----------------------------------------------------------------------------= -// MARK: + Unsigned -//=----------------------------------------------------------------------------= - -private func NBKAssertMultiplicationByDigitWithAddition( -_ lhs: UIntXL, _ rhs: UInt, _ carry: UInt, _ product: UIntXL, -file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual(lhs.multiplied(by: rhs, adding: carry), product, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs.multiply(by: rhs, add: carry); return lhs }(), product, file: file, line: line) -} - -#endif diff --git a/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Numbers.swift b/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Numbers.swift deleted file mode 100644 index 0ed7ac35..00000000 --- a/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Numbers.swift +++ /dev/null @@ -1,573 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if DEBUG - -import NBKCoreKit -import NBKTwosComplementKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Flexible Width x Numbers x IntXL -//*============================================================================* - -final class NBKFlexibleWidthTestsOnNumbersAsIntXL: XCTestCase { - - typealias S = IntXL - typealias T = IntXL - typealias M = UIntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testZero() { - XCTAssertEqual(T( 0), T(words:[0])) - XCTAssertEqual(T.zero, T(words:[0])) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Int - //=------------------------------------------------------------------------= - - func testToInt() { - NBKAssertNumbers(from: T(words:[ 1, 0, 0, 0] as W), default: Int( 1)) - NBKAssertNumbers(from: T(words:[~0, 0, 0, 0] as W), exactly: nil, clamping: Int.max, truncating: -1) - NBKAssertNumbers(from: T(words:[ 1, 1, 1, 1] as W), exactly: nil, clamping: Int.max, truncating: 1) - NBKAssertNumbers(from: T(words:[~0, ~0, ~0, ~0] as W), default: Int(-1)) - } - - func testFromInt() { - NBKAssertNumbers(from: Int.min, default: ~T(words:[UInt(Int.max), 0, 0, 0] as W)) - NBKAssertNumbers(from: Int.max, default: T(words:[UInt(Int.max), 0, 0, 0] as W)) - } - - func testFromIntAsDigit() { - NBKAssertNumbers(from: T(digit: Int.min), default: ~T(words:[UInt(Int.max), 0, 0, 0] as W)) - NBKAssertNumbers(from: T(digit: Int.max), default: T(words:[UInt(Int.max), 0, 0, 0] as W)) - } - - func testFromIntAsDigitAtIndex() { - NBKAssertNumbers(from: T(digit: Int( 4), at: Int(0)), default: T(words:[ 4, 0, 0, 0] as W)) - NBKAssertNumbers(from: T(digit: Int( 4), at: Int(1)), default: T(words:[ 0, 4, 0, 0] as W)) - NBKAssertNumbers(from: T(digit: Int( 4), at: Int(2)), default: T(words:[ 0, 0, 4, 0] as W)) - NBKAssertNumbers(from: T(digit: Int( 4), at: Int(3)), default: T(words:[ 0, 0, 0, 4] as W)) - - NBKAssertNumbers(from: T(digit: Int(-4), at: Int(0)), default: T(words:[~3, ~0, ~0, ~0] as W)) - NBKAssertNumbers(from: T(digit: Int(-4), at: Int(1)), default: T(words:[ 0, ~3, ~0, ~0] as W)) - NBKAssertNumbers(from: T(digit: Int(-4), at: Int(2)), default: T(words:[ 0, 0, ~3, ~0] as W)) - NBKAssertNumbers(from: T(digit: Int(-4), at: Int(3)), default: T(words:[ 0, 0, 0, ~3] as W)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Int32 - //=------------------------------------------------------------------------= - - func testToInt32() { - NBKAssertNumbers(from: T(x32:[ 1, 0, 0, 0] as Y), default: Int32( 1)) - NBKAssertNumbers(from: T(x32:[~0, 0, 0, 0] as Y), exactly: nil, clamping: Int32.max, truncating: -1) - NBKAssertNumbers(from: T(x32:[ 1, 1, 1, 1] as Y), exactly: nil, clamping: Int32.max, truncating: 1) - NBKAssertNumbers(from: T(x32:[~0, ~0, ~0, ~0] as Y), default: Int32(-1)) - } - - func testFromInt32() { - NBKAssertNumbers(from: Int32.min, default: T(words: Int32.min.words)) - NBKAssertNumbers(from: Int32.max, default: T(words: Int32.max.words)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Int64 - //=------------------------------------------------------------------------= - - func testToInt64() { - NBKAssertNumbers(from: T(x64:[ 1, 0, 0, 0] as X), default: Int64( 1)) - NBKAssertNumbers(from: T(x64:[~0, 0, 0, 0] as X), exactly: nil, clamping: Int64.max, truncating: -1) - NBKAssertNumbers(from: T(x64:[ 1, 1, 1, 1] as X), exactly: nil, clamping: Int64.max, truncating: 1) - NBKAssertNumbers(from: T(x64:[~0, ~0, ~0, ~0] as X), default: Int64(-1)) - } - - func testFromInt64() { - NBKAssertNumbers(from: Int64.min, default: T(words: Int64.min.words)) - NBKAssertNumbers(from: Int64.max, default: T(words: Int64.max.words)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x UInt - //=------------------------------------------------------------------------= - - func testToUInt() { - NBKAssertNumbers(from: T(words:[ 1, 0, 0, 0] as W), default: UInt( 1)) - NBKAssertNumbers(from: T(words:[~0, 0, 0, 0] as W), default: UInt.max) - NBKAssertNumbers(from: T(words:[ 1, 1, 1, 1] as W), exactly: nil, clamping: ~0, truncating: UInt( 1)) - NBKAssertNumbers(from: T(words:[~0, ~0, ~0, ~0] as W), exactly: nil, clamping: 0, truncating: UInt.max) - } - - func testFromUInt() { - NBKAssertNumbers(from: UInt.min, default: T(sign: .plus, magnitude: M(words: UInt.min.words))) - NBKAssertNumbers(from: UInt.max, default: T(sign: .plus, magnitude: M(words: UInt.max.words))) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x UInt32 - //=------------------------------------------------------------------------= - - func testToUInt32() { - NBKAssertNumbers(from: T(x32:[ 1, 0, 0, 0] as Y), default: UInt32( 1)) - NBKAssertNumbers(from: T(x32:[~0, 0, 0, 0] as Y), default: UInt32.max) - NBKAssertNumbers(from: T(x32:[ 1, 1, 1, 1] as Y), exactly: nil, clamping: ~0, truncating: UInt32( 1)) - NBKAssertNumbers(from: T(x32:[~0, ~0, ~0, ~0] as Y), exactly: nil, clamping: 0, truncating: UInt32.max) - } - - func testFromUInt32() { - NBKAssertNumbers(from: UInt32.min, default: T(sign: .plus, magnitude: M(words: UInt32.min.words))) - NBKAssertNumbers(from: UInt32.max, default: T(sign: .plus, magnitude: M(words: UInt32.max.words))) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x UInt64 - //=------------------------------------------------------------------------= - - func testToUInt64() { - NBKAssertNumbers(from: T(x64:[ 1, 0, 0, 0] as X), default: UInt64( 1)) - NBKAssertNumbers(from: T(x64:[~0, 0, 0, 0] as X), default: UInt64.max) - NBKAssertNumbers(from: T(x64:[ 1, 1, 1, 1] as X), exactly: nil, clamping: ~0, truncating: UInt64( 1)) - NBKAssertNumbers(from: T(x64:[~0, ~0, ~0, ~0] as X), exactly: nil, clamping: 0, truncating: UInt64.max) - } - - func testFromUInt64() { - NBKAssertNumbers(from: UInt64.min, default: T(sign: .plus, magnitude: M(words: UInt64.min.words))) - NBKAssertNumbers(from: UInt64.max, default: T(sign: .plus, magnitude: M(words: UInt64.max.words))) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Signitude - //=------------------------------------------------------------------------= - - func testToSignitude() { - NBKAssertNumbers(from: T(words:[ 1, 0, 0, 0] as W), default: S(words:[ 1, 0, 0, 0] as W)) - NBKAssertNumbers(from: T(words:[~0, 0, 0, 0] as W), default: S(words:[~0, 0, 0, 0] as W)) - NBKAssertNumbers(from: T(words:[ 1, 1, 1, 1] as W), default: S(words:[ 1, 1, 1, 1] as W)) - NBKAssertNumbers(from: T(words:[~0, ~0, ~0, ~0] as W), default: S(words:[~0, ~0, ~0, ~0] as W)) - } - - func testFromSignitude() { - NBKAssertNumbers(from: S(words:[ 1, 0, 0, 0] as W), default: T(words:[ 1, 0, 0, 0] as W)) - NBKAssertNumbers(from: S(words:[~0, 0, 0, 0] as W), default: T(words:[~0, 0, 0, 0] as W)) - NBKAssertNumbers(from: S(words:[ 1, 1, 1, 1] as W), default: T(words:[ 1, 1, 1, 1] as W)) - NBKAssertNumbers(from: S(words:[~0, ~0, ~0, ~0] as W), default: T(words:[~0, ~0, ~0, ~0] as W)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Magnitude - //=------------------------------------------------------------------------= - - func testToMagnitude() { - NBKAssertNumbers(from: T(words:[ 1, 0, 0, 0] as W), default: M(words:[ 1, 0, 0, 0] as W)) - NBKAssertNumbers(from: T(words:[~0, 0, 0, 0] as W), default: M(words:[~0, 0, 0, 0] as W)) - NBKAssertNumbers(from: T(words:[ 1, 1, 1, 1] as W), default: M(words:[ 1, 1, 1, 1] as W)) - NBKAssertNumbers(from: T(words:[~0, ~0, ~0, ~0] as W), exactly: nil, clamping: M.zero, truncating: M(UInt.max)) - } - - func testFromMagnitude() { - NBKAssertNumbers(from: M(words:[ 1, 0, 0, 0] as W), default: T(words:[ 1, 0, 0, 0, 0] as W)) - NBKAssertNumbers(from: M(words:[~0, 0, 0, 0] as W), default: T(words:[~0, 0, 0, 0, 0] as W)) - NBKAssertNumbers(from: M(words:[ 1, 1, 1, 1] as W), default: T(words:[ 1, 1, 1, 1, 0] as W)) - NBKAssertNumbers(from: M(words:[~0, ~0, ~0, ~0] as W), default: T(words:[~0, ~0, ~0, ~0, 0] as W)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Float32 - //=------------------------------------------------------------------------= - - func testToFloat32() { - XCTAssertEqual(Float32(T(-1)), Float32(-1)) - XCTAssertEqual(Float32(T( 0)), Float32( 0)) - XCTAssertEqual(Float32(T( 1)), Float32( 1)) - - XCTAssertEqual(Float32(T( Int32.min)), Float32( Int32.min)) - XCTAssertEqual(Float32(T( Int32.max)), Float32( Int32.max)) - - XCTAssertEqual(Float32(T(UInt32.min)), Float32(UInt32.min)) - XCTAssertEqual(Float32(T(UInt32.max)), Float32(UInt32.max)) - } - - func testFromFloat32() { - XCTAssertEqual(T(Float32( 22.0)), 22) - XCTAssertEqual(T(Float32( -22.0)), -22) - XCTAssertEqual(T(Float32( 22.5)), 22) - XCTAssertEqual(T(Float32( -22.5)), -22) - - XCTAssertEqual(T(exactly: 22.5), nil) - XCTAssertEqual(T(exactly: -22.5), nil) - - XCTAssertEqual(T(exactly: pow(2, Float32(64 * 0 - 1))), nil) - XCTAssertEqual(T(exactly: pow(2, Float32(64 * 0 - 0))), T(x64:[1, 0, 0, 0] as X)) - XCTAssertEqual(T(exactly: pow(2, Float32(64 * 1 - 1))), T(x64:[1 << 63, 0, 0, 0] as X)) - XCTAssertEqual(T(exactly: pow(2, Float32(64 * 2 - 1))), T(x64:[0, 1 << 63, 0, 0] as X)) - XCTAssertEqual(T(exactly: pow(2, Float32(64 * 2 - 0))), nil) - } - - func testFromFloat32ValuesThatAreSpecial() { - XCTAssertNil(T(exactly: Float32.nan)) - XCTAssertNil(T(exactly: Float32.infinity)) - XCTAssertNil(T(exactly: Float32.signalingNaN)) - XCTAssertNil(T(exactly: Float32.leastNormalMagnitude)) - XCTAssertNil(T(exactly: Float32.leastNonzeroMagnitude)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Float64 - //=------------------------------------------------------------------------= - - func testToFloat64() { - XCTAssertEqual(Float64(T(-1)), Float64(-1)) - XCTAssertEqual(Float64(T( 0)), Float64( 0)) - XCTAssertEqual(Float64(T( 1)), Float64( 1)) - - XCTAssertEqual(Float64(T( Int64.min)), Float64( Int64.min)) - XCTAssertEqual(Float64(T( Int64.max)), Float64( Int64.max)) - - XCTAssertEqual(Float64(T(UInt64.min)), Float64(UInt64.min)) - XCTAssertEqual(Float64(T(UInt64.max)), Float64(UInt64.max)) - } - - func testFromFloat64() { - XCTAssertEqual(T(Float64( 22.0)), 22) - XCTAssertEqual(T(Float64( -22.0)), -22) - XCTAssertEqual(T(Float64( 22.5)), 22) - XCTAssertEqual(T(Float64( -22.5)), -22) - - XCTAssertEqual(T(exactly: 22.5), nil) - XCTAssertEqual(T(exactly: -22.5), nil) - - XCTAssertEqual(T(exactly: pow(2, Float64(64 * 0 - 1))), nil) - XCTAssertEqual(T(exactly: pow(2, Float64(64 * 0 - 0))), T(x64:[1, 0, 0, 0] as X)) - XCTAssertEqual(T(exactly: pow(2, Float64(64 * 1 - 1))), T(x64:[1 << 63, 0, 0, 0] as X)) - XCTAssertEqual(T(exactly: pow(2, Float64(64 * 2 - 1))), T(x64:[0, 1 << 63, 0, 0] as X)) - XCTAssertEqual(T(exactly: pow(2, Float64(64 * 3 - 1))), T(x64:[0, 0, 1 << 63, 0] as X)) - XCTAssertEqual(T(exactly: pow(2, Float64(64 * 4 - 2))), T(x64:[0, 0, 0, 1 << 62] as X)) - XCTAssertEqual(T(exactly: pow(2, Float64(64 * 4 - 1))), -T(x64:[0, 0, 0, 1 << 63] as X)) - } - - func testFromFloat64ValuesThatAreSpecial() { - XCTAssertNil(T(exactly: Float64.nan)) - XCTAssertNil(T(exactly: Float64.infinity)) - XCTAssertNil(T(exactly: Float64.signalingNaN)) - XCTAssertNil(T(exactly: Float64.leastNormalMagnitude)) - XCTAssertNil(T(exactly: Float64.leastNonzeroMagnitude)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Sign & Magnitude - //=------------------------------------------------------------------------= - - func testsFromSignAndMagnitude() { - XCTAssertEqual(T(sign: .plus, magnitude: M(1)), T(1)) - XCTAssertEqual(T(sign: .minus, magnitude: M(1)), -T(1)) - } - - func testsFromSignAndMagnitudeAsPlusMinusZero() { - XCTAssertEqual(T(sign: .plus, magnitude: M( )), T( )) - XCTAssertEqual(T(sign: .minus, magnitude: M( )), -T( )) - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Numbers x UIntXL -//*============================================================================* - -final class NBKFlexibleWidthTestsOnNumbersAsUIntXL: XCTestCase { - - typealias S = IntXL - typealias T = UIntXL - typealias M = UIntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testZero() { - XCTAssertEqual(T( 0), T(words:[0])) - XCTAssertEqual(T.zero, T(words:[0])) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Int - //=------------------------------------------------------------------------= - - func testToInt() { - NBKAssertNumbers(from: T(words:[ 1, 0, 0, 0] as W), default: Int( 1)) - NBKAssertNumbers(from: T(words:[~0, 0, 0, 0] as W), exactly: nil, clamping: Int.max, truncating: -1) - NBKAssertNumbers(from: T(words:[ 1, 1, 1, 1] as W), exactly: nil, clamping: Int.max, truncating: 1) - NBKAssertNumbers(from: T(words:[~0, ~0, ~0, ~0] as W), exactly: nil, clamping: Int.max, truncating: -1) - } - - func testFromInt() { - NBKAssertNumbers(from: Int.min, exactly: nil, clamping: 0, truncating: T(words: Int.min.words)) - NBKAssertNumbers(from: Int.max, default: /*-------------------------*/ T(words: Int.max.words)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Int32 - //=------------------------------------------------------------------------= - - func testToInt32() { - NBKAssertNumbers(from: T(x32:[ 1, 0, 0, 0] as Y), default: Int32( 1)) - NBKAssertNumbers(from: T(x32:[~0, 0, 0, 0] as Y), exactly: nil, clamping: Int32.max, truncating: -1) - NBKAssertNumbers(from: T(x32:[ 1, 1, 1, 1] as Y), exactly: nil, clamping: Int32.max, truncating: 1) - NBKAssertNumbers(from: T(x32:[~0, ~0, ~0, ~0] as Y), exactly: nil, clamping: Int32.max, truncating: -1) - } - - func testFromInt32() { - NBKAssertNumbers(from: Int32.min, exactly: nil, clamping: 0, truncating: T(words: Int32.min.words)) - NBKAssertNumbers(from: Int32.max, default: /*-------------------------*/ T(words: Int32.max.words)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Int64 - //=------------------------------------------------------------------------= - - func testToInt64() { - NBKAssertNumbers(from: T(x64:[ 1, 0, 0, 0] as X), default: Int64( 1)) - NBKAssertNumbers(from: T(x64:[~0, 0, 0, 0] as X), exactly: nil, clamping: Int64.max, truncating: -1) - NBKAssertNumbers(from: T(x64:[ 1, 1, 1, 1] as X), exactly: nil, clamping: Int64.max, truncating: 1) - NBKAssertNumbers(from: T(x64:[~0, ~0, ~0, ~0] as X), exactly: nil, clamping: Int64.max, truncating: -1) - } - - func testFromInt64() { - NBKAssertNumbers(from: Int64.min, exactly: nil, clamping: 0, truncating: T(words: Int64.min.words)) - NBKAssertNumbers(from: Int64.max, default: /*-------------------------*/ T(words: Int64.max.words)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x UInt - //=------------------------------------------------------------------------= - - func testToUInt() { - NBKAssertNumbers(from: T(words:[ 1, 0, 0, 0] as W), default: UInt( 1)) - NBKAssertNumbers(from: T(words:[~0, 0, 0, 0] as W), default: ~UInt( 0)) - NBKAssertNumbers(from: T(words:[ 1, 1, 1, 1] as W), exactly: nil, clamping: UInt.max, truncating: 1) - NBKAssertNumbers(from: T(words:[~0, ~0, ~0, ~0] as W), exactly: nil, clamping: UInt.max, truncating: ~0) - } - - func testFromUInt() { - NBKAssertNumbers(from: UInt.min, default: T(words: UInt.min.words)) - NBKAssertNumbers(from: UInt.max, default: T(words: UInt.max.words)) - } - - func testFromUIntAsDigit() { - NBKAssertNumbers(from: T(digit: UInt.min), default: T(words:[ 0, 0, 0, 0] as W)) - NBKAssertNumbers(from: T(digit: UInt.max), default: T(words:[~0, 0, 0, 0] as W)) - } - - func testFromUIntAsDigitAtIndex() { - NBKAssertNumbers(from: T(digit: UInt.max, at: Int(0)), default: T(words:[~0, 0, 0, 0] as W)) - NBKAssertNumbers(from: T(digit: UInt.max, at: Int(1)), default: T(words:[ 0, ~0, 0, 0] as W)) - NBKAssertNumbers(from: T(digit: UInt.max, at: Int(2)), default: T(words:[ 0, 0, ~0, 0] as W)) - NBKAssertNumbers(from: T(digit: UInt.max, at: Int(3)), default: T(words:[ 0, 0, 0, ~0] as W)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x UInt32 - //=------------------------------------------------------------------------= - - func testToUInt32() { - NBKAssertNumbers(from: T(x32:[ 1, 0, 0, 0] as Y), default: UInt32( 1)) - NBKAssertNumbers(from: T(x32:[~0, 0, 0, 0] as Y), default: ~UInt32( 0)) - NBKAssertNumbers(from: T(x32:[ 1, 1, 1, 1] as Y), exactly: nil, clamping: UInt32.max, truncating: 1) - NBKAssertNumbers(from: T(x32:[~0, ~0, ~0, ~0] as Y), exactly: nil, clamping: UInt32.max, truncating: ~0) - } - - func testFromUInt32() { - NBKAssertNumbers(from: UInt32.min, default: T(words: UInt32.min.words)) - NBKAssertNumbers(from: UInt32.max, default: T(words: UInt32.max.words)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x UInt64 - //=------------------------------------------------------------------------= - - func testToUInt64() { - NBKAssertNumbers(from: T(x64:[ 1, 0, 0, 0] as X), default: UInt64( 1)) - NBKAssertNumbers(from: T(x64:[~0, 0, 0, 0] as X), default: ~UInt64( 0)) - NBKAssertNumbers(from: T(x64:[ 1, 1, 1, 1] as X), exactly: nil, clamping: UInt64.max, truncating: 1) - NBKAssertNumbers(from: T(x64:[~0, ~0, ~0, ~0] as X), exactly: nil, clamping: UInt64.max, truncating: ~0) - } - - func testFromUInt64() { - NBKAssertNumbers(from: UInt64.min, default: T(words: UInt64.min.words)) - NBKAssertNumbers(from: UInt64.max, default: T(words: UInt64.max.words)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Signitude - //=------------------------------------------------------------------------= - - func testToSignitude() { - NBKAssertNumbers(from: T(words:[ 1, 0, 0, 0] as W), default: S(words:[ 1, 0, 0, 0, 0] as W)) - NBKAssertNumbers(from: T(words:[~0, 0, 0, 0] as W), default: S(words:[~0, 0, 0, 0, 0] as W)) - NBKAssertNumbers(from: T(words:[ 1, 1, 1, 1] as W), default: S(words:[ 1, 1, 1, 1, 0] as W)) - NBKAssertNumbers(from: T(words:[~0, ~0, ~0, ~0] as W), default: S(words:[~0, ~0, ~0, ~0, 0] as W)) - } - - func testFromSignitude() { - NBKAssertNumbers(from: S(words:[ 1, 0, 0, 0] as W), default: T(words:[ 1, 0, 0, 0, 0] as W)) - NBKAssertNumbers(from: S(words:[~0, 0, 0, 0] as W), default: T(words:[~0, 0, 0, 0, 0] as W)) - NBKAssertNumbers(from: S(words:[ 1, 1, 1, 1] as W), default: T(words:[ 1, 1, 1, 1, 0] as W)) - NBKAssertNumbers(from: S(words:[~0, ~0, ~0, ~0] as W), exactly: nil, clamping: T.zero, truncating: T(UInt.max)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Magnitude - //=------------------------------------------------------------------------= - - func testToMagnitude() { - NBKAssertNumbers(from: T(words:[ 1, 0, 0, 0] as W), default: M(words:[ 1, 0, 0, 0] as W)) - NBKAssertNumbers(from: T(words:[~0, 0, 0, 0] as W), default: M(words:[~0, 0, 0, 0] as W)) - NBKAssertNumbers(from: T(words:[ 1, 1, 1, 1] as W), default: M(words:[ 1, 1, 1, 1] as W)) - NBKAssertNumbers(from: T(words:[~0, ~0, ~0, ~0] as W), default: M(words:[~0, ~0, ~0, ~0] as W)) - } - - func testFromMagnitude() { - NBKAssertNumbers(from: M(words:[ 1, 0, 0, 0] as W), default: T(words:[ 1, 0, 0, 0] as W)) - NBKAssertNumbers(from: M(words:[~0, 0, 0, 0] as W), default: T(words:[~0, 0, 0, 0] as W)) - NBKAssertNumbers(from: M(words:[ 1, 1, 1, 1] as W), default: T(words:[ 1, 1, 1, 1] as W)) - NBKAssertNumbers(from: M(words:[~0, ~0, ~0, ~0] as W), default: T(words:[~0, ~0, ~0, ~0] as W)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Float32 - //=------------------------------------------------------------------------= - - func testToFloat32() { - XCTAssertEqual(Float32(T(0)), Float32(0)) - XCTAssertEqual(Float32(T(1)), Float32(1)) - - XCTAssertEqual(Float32(T(UInt32.min)), Float32(UInt32.min)) - XCTAssertEqual(Float32(T(UInt32.max)), Float32(UInt32.max)) - } - - func testFromFloat32() { - XCTAssertEqual(T(Float32( 22.0)), 22) - XCTAssertEqual(T(Float32( 22.5)), 22) - - XCTAssertEqual(T(exactly: 22.5), nil) - XCTAssertEqual(T(exactly: -22.5), nil) - - XCTAssertEqual(T(exactly: pow(2, Float32(64 * 0 - 1))), nil) - XCTAssertEqual(T(exactly: pow(2, Float32(64 * 0 - 0))), T(x64:[1, 0, 0, 0] as X)) - XCTAssertEqual(T(exactly: pow(2, Float32(64 * 1 - 1))), T(x64:[1 << 63, 0, 0, 0] as X)) - XCTAssertEqual(T(exactly: pow(2, Float32(64 * 2 - 1))), T(x64:[0, 1 << 63, 0, 0] as X)) - XCTAssertEqual(T(exactly: pow(2, Float32(64 * 2 - 0))), nil) - } - - func testFromFloat32ValuesThatAreSpecial() { - XCTAssertNil(T(exactly: Float32.nan)) - XCTAssertNil(T(exactly: Float32.infinity)) - XCTAssertNil(T(exactly: Float32.signalingNaN)) - XCTAssertNil(T(exactly: Float32.leastNormalMagnitude)) - XCTAssertNil(T(exactly: Float32.leastNonzeroMagnitude)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Float64 - //=------------------------------------------------------------------------= - - func testToFloat64() { - XCTAssertEqual(Float64(T(0)), Float64(0)) - XCTAssertEqual(Float64(T(1)), Float64(1)) - - XCTAssertEqual(Float64(T(UInt64.min)), Float64(UInt64.min)) - XCTAssertEqual(Float64(T(UInt64.max)), Float64(UInt64.max)) - } - - func testFromFloat64() { - XCTAssertEqual(T(Float64( 22.0)), 22) - XCTAssertEqual(T(Float64( 22.5)), 22) - - XCTAssertEqual(T(exactly: 22.5), nil) - XCTAssertEqual(T(exactly: -22.5), nil) - - XCTAssertEqual(T(exactly: pow(2, Float64(64 * 0 - 1))), nil) - XCTAssertEqual(T(exactly: pow(2, Float64(64 * 0 - 0))), T(x64:[1, 0, 0, 0] as X)) - XCTAssertEqual(T(exactly: pow(2, Float64(64 * 1 - 1))), T(x64:[1 << 63, 0, 0, 0] as X)) - XCTAssertEqual(T(exactly: pow(2, Float64(64 * 2 - 1))), T(x64:[0, 1 << 63, 0, 0] as X)) - XCTAssertEqual(T(exactly: pow(2, Float64(64 * 3 - 1))), T(x64:[0, 0, 1 << 63, 0] as X)) - XCTAssertEqual(T(exactly: pow(2, Float64(64 * 4 - 1))), T(x64:[0, 0, 0, 1 << 63] as X)) - } - - func testFromFloat64ValuesThatAreSpecial() { - XCTAssertNil(T(exactly: Float64.nan)) - XCTAssertNil(T(exactly: Float64.infinity)) - XCTAssertNil(T(exactly: Float64.signalingNaN)) - XCTAssertNil(T(exactly: Float64.leastNormalMagnitude)) - XCTAssertNil(T(exactly: Float64.leastNonzeroMagnitude)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Sign & Magnitude - //=------------------------------------------------------------------------= - - func testsFromSignAndMagnitude() { - XCTAssertEqual(T(sign: .plus, magnitude: M( 1)), T( 1)) - XCTAssertEqual(T(sign: .minus, magnitude: M( 1)), nil) - } - - func testsFromSignAndMagnitudeAsPlusMinusZero() { - XCTAssertEqual(T(sign: .plus, magnitude: M( )), T( )) - XCTAssertEqual(T(sign: .minus, magnitude: M( )), T( )) - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Numbers x Assertions -//*============================================================================* - -private func NBKAssertNumbers( -from value: I, default: O, -file: StaticString = #file, line: UInt = #line) { - NBKAssertNumbers(from: value, exactly: `default`, clamping: `default`, truncating: `default`, file: file, line: line) -} - -private func NBKAssertNumbers( -from value: I, default: O, exactly: O?, -file: StaticString = #file, line: UInt = #line) { - NBKAssertNumbers(from: value, exactly: exactly, clamping: `default`, truncating: `default`, file: file, line: line) -} - -private func NBKAssertNumbers( -from value: I, default: O, clamping: O, -file: StaticString = #file, line: UInt = #line) { - NBKAssertNumbers(from: value, exactly: `default`, clamping: clamping, truncating: `default`, file: file, line: line) -} - -private func NBKAssertNumbers( -from value: I, default: O, truncating: O, -file: StaticString = #file, line: UInt = #line) { - NBKAssertNumbers(from: value, exactly: `default`, clamping: `default`, truncating: truncating, file: file, line: line) -} - -private func NBKAssertNumbers( -from value: I, exactly: O?, clamping: O, truncating: O, -file: StaticString = #file, line: UInt = #line) { - //=--------------------------------------= - if let exactly = exactly { - XCTAssertEqual(O(value), exactly, file: file, line: line) - } - //=--------------------------------------= - XCTAssertEqual(O(exactly: value), exactly, file: file, line: line) - XCTAssertEqual(O(clamping: value), clamping, file: file, line: line) - XCTAssertEqual(O(truncatingIfNeeded: value), truncating, file: file, line: line) -} - -#endif diff --git a/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Shifts.swift b/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Shifts.swift deleted file mode 100644 index f8c731e6..00000000 --- a/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Shifts.swift +++ /dev/null @@ -1,324 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if DEBUG - -import NBKCoreKit -import NBKTwosComplementKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Flexible Width x Shifts x IntXL -//*============================================================================* - -final class NBKFlexibleWidthTestsOnShiftsAsIntXL: XCTestCase { - - typealias T = IntXL - - //=------------------------------------------------------------------------= - // MARK: Tests x Left - //=------------------------------------------------------------------------= - - func testBitshiftingLeftByBits() { - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 0, T(x64:[ 1, 2, 3, 4] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 1, T(x64:[ 2, 4, 6, 8] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 2, T(x64:[ 4, 8, 12, 16] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 3, T(x64:[ 8, 16, 24, 32] as X)) - } - - func testBitshiftingLeftByWords() { - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 0, T(x64:[ 1, 2, 3, 4, 0, 0, 0, 0] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 64, T(x64:[ 0, 1, 2, 3, 4, 0, 0, 0] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 128, T(x64:[ 0, 0, 1, 2, 3, 4, 0, 0] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 192, T(x64:[ 0, 0, 0, 1, 2, 3, 4, 0] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 256, T(x64:[ 0, 0, 0, 0, 1, 2, 3, 4] as X)) - } - - func testBitshiftingLeftByWordsAndBits() { - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 3, T(x64:[ 8, 16, 24, 32, 0, 0, 0, 0] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 67, T(x64:[ 0, 8, 16, 24, 32, 0, 0, 0] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 131, T(x64:[ 0, 0, 8, 16, 24, 32, 0, 0] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 195, T(x64:[ 0, 0, 0, 8, 16, 24, 32, 0] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 259, T(x64:[ 0, 0, 0, 0, 8, 16, 24, 32] as X)) - } - - func testBitshiftingLeftSuchThatWordsSplit() { - NBKAssertShiftLeft(T(x64:[~0, 0, 0, 0] as X), 1, T(x64:[~1, 1, 0, 0, 0] as X)) - NBKAssertShiftLeft(T(x64:[ 0, ~0, 0, 0] as X), 1, T(x64:[ 0, ~1, 1, 0, 0] as X)) - NBKAssertShiftLeft(T(x64:[ 0, 0, ~0, 0] as X), 1, T(x64:[ 0, 0, ~1, 1, 0] as X)) - NBKAssertShiftLeft(T(x64:[ 0, 0, 0, ~0] as X), 1, T(x64:[ 0, 0, 0, ~1, ~0] as X)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Right - //=------------------------------------------------------------------------= - - func testBitshiftingRightByBits() { - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 0, T(x64:[ 8, 16, 24, 32] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 1, T(x64:[ 4, 8, 12, 16] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 2, T(x64:[ 2, 4, 6, 8] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 3, T(x64:[ 1, 2, 3, 4] as X)) - } - - func testBitshiftingRightByWords() { - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 0, T(x64:[ 8, 16, 24, 32] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 64, T(x64:[16, 24, 32, 0] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 128, T(x64:[24, 32, 0, 0] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 192, T(x64:[32, 0, 0, 0] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 256, T(x64:[ 0, 0, 0, 0] as X)) - } - - func testBitshiftingRightByWordsAndBits() { - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 3, T(x64:[ 1, 2, 3, 4] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 67, T(x64:[ 2, 3, 4, 0] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 131, T(x64:[ 3, 4, 0, 0] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 195, T(x64:[ 4, 0, 0, 0] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 259, T(x64:[ 0, 0, 0, 0] as X)) - } - - func testBitshiftingRightSuchThatWordsSplit() { - NBKAssertShiftRight(T(x64:[0, 0, 0, 7] as X), 1, T(x64:[ 0, 0, 1 << 63, 3] as X)) - NBKAssertShiftRight(T(x64:[0, 0, 7, 0] as X), 1, T(x64:[ 0, 1 << 63, 3, 0] as X)) - NBKAssertShiftRight(T(x64:[0, 7, 0, 0] as X), 1, T(x64:[ 1 << 63, 3, 0, 0] as X)) - NBKAssertShiftRight(T(x64:[7, 0, 0, 0] as X), 1, T(x64:[ 3, 0, 0, 0] as X)) - } - - func testBitshiftingRightIsSigned() { - NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X), 0, T(x64:[ 0, 0, 0, 1 << 63] as X)) - NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X), 64, T(x64:[ 0, 0, 1 << 63, ~0] as X)) - NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X), 128, T(x64:[ 0, 1 << 63, ~0, ~0] as X)) - NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X), 192, T(x64:[ 1 << 63, ~0, ~0, ~0] as X)) - NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X), 256, T(x64:[~0, ~0, ~0, ~0] as X)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Miscellaneous - //=------------------------------------------------------------------------= - - func testBitshiftingIsSmart() { - XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) << 1, T(x64:[2, 4, 6, 8, 0] as X)) - XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) >> -1, T(x64:[2, 4, 6, 8, 0] as X)) - - XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) << 64, T(x64:[0, 1, 2, 3, 4] as X)) - XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) >> -64, T(x64:[0, 1, 2, 3, 4] as X)) - } - - func testBitshiftingRightDoesNotTrap() { - XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) >> Int.max, T.zero) - XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) << Int.min, T.zero) - } - - func testBitshiftingZeroDoesNotTrap() { - XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) << Int.min, T.zero) - XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) << Int.max, T.zero) - - XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) >> Int.min, T.zero) - XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) >> Int.max, T.zero) - } - - func testBitshiftingZeroDoesNotDoAnything() { - XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) << (UInt.bitWidth + 0), T.zero) - XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) << (UInt.bitWidth + 1), T.zero) - - XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) >> (UInt.bitWidth + 0), T.zero) - XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) >> (UInt.bitWidth + 1), T.zero) - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Shifts x UIntXL -//*============================================================================* - -final class NBKFlexibleWidthTestsOnShiftsAsUIntXL: XCTestCase { - - typealias T = UIntXL - - //=------------------------------------------------------------------------= - // MARK: Tests x Left - //=------------------------------------------------------------------------= - - func testBitshiftingLeftByBits() { - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 0, T(x64:[ 1, 2, 3, 4] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 1, T(x64:[ 2, 4, 6, 8] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 2, T(x64:[ 4, 8, 12, 16] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 3, T(x64:[ 8, 16, 24, 32] as X)) - } - - func testBitshiftingLeftByWords() { - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 0, T(x64:[ 1, 2, 3, 4, 0, 0, 0, 0] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 64, T(x64:[ 0, 1, 2, 3, 4, 0, 0, 0] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 128, T(x64:[ 0, 0, 1, 2, 3, 4, 0, 0] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 192, T(x64:[ 0, 0, 0, 1, 2, 3, 4, 0] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 256, T(x64:[ 0, 0, 0, 0, 1, 2, 3, 4] as X)) - } - - func testBitshiftingLeftByWordsAndBits() { - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 3, T(x64:[ 8, 16, 24, 32, 0, 0, 0, 0] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 67, T(x64:[ 0, 8, 16, 24, 32, 0, 0, 0] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 131, T(x64:[ 0, 0, 8, 16, 24, 32, 0, 0] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 195, T(x64:[ 0, 0, 0, 8, 16, 24, 32, 0] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 259, T(x64:[ 0, 0, 0, 0, 8, 16, 24, 32] as X)) - } - - func testBitshiftingLeftSuchThatWordsSplit() { - NBKAssertShiftLeft(T(x64:[~0, 0, 0, 0] as X), 1, T(x64:[~1, 1, 0, 0, 0] as X)) - NBKAssertShiftLeft(T(x64:[ 0, ~0, 0, 0] as X), 1, T(x64:[ 0, ~1, 1, 0, 0] as X)) - NBKAssertShiftLeft(T(x64:[ 0, 0, ~0, 0] as X), 1, T(x64:[ 0, 0, ~1, 1, 0] as X)) - NBKAssertShiftLeft(T(x64:[ 0, 0, 0, ~0] as X), 1, T(x64:[ 0, 0, 0, ~1, 1] as X)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Right - //=------------------------------------------------------------------------= - - func testBitshiftingRightByBits() { - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 0, T(x64:[ 8, 16, 24, 32] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 1, T(x64:[ 4, 8, 12, 16] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 2, T(x64:[ 2, 4, 6, 8] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 3, T(x64:[ 1, 2, 3, 4] as X)) - } - - func testBitshiftingRightByWords() { - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 0, T(x64:[ 8, 16, 24, 32] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 64, T(x64:[16, 24, 32, 0] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 128, T(x64:[24, 32, 0, 0] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 192, T(x64:[32, 0, 0, 0] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 256, T(x64:[ 0, 0, 0, 0] as X)) - } - - func testBitshiftingRightByWordsAndBits() { - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 3, T(x64:[ 1, 2, 3, 4] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 67, T(x64:[ 2, 3, 4, 0] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 131, T(x64:[ 3, 4, 0, 0] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 195, T(x64:[ 4, 0, 0, 0] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 259, T(x64:[ 0, 0, 0, 0] as X)) - } - - func testBitshiftingRightSuchThatWordsSplit() { - NBKAssertShiftRight(T(x64:[0, 0, 0, 7] as X), 1, T(x64:[ 0, 0, 1 << 63, 3] as X)) - NBKAssertShiftRight(T(x64:[0, 0, 7, 0] as X), 1, T(x64:[ 0, 1 << 63, 3, 0] as X)) - NBKAssertShiftRight(T(x64:[0, 7, 0, 0] as X), 1, T(x64:[ 1 << 63, 3, 0, 0] as X)) - NBKAssertShiftRight(T(x64:[7, 0, 0, 0] as X), 1, T(x64:[ 3, 0, 0, 0] as X)) - } - - func testBitshiftingRightIsUnsigned() { - NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X), 0, T(x64:[0, 0, 0, 1 << 63] as X)) - NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X), 64, T(x64:[0, 0, 1 << 63, 0] as X)) - NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X), 128, T(x64:[0, 1 << 63, 0, 0] as X)) - NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X), 192, T(x64:[1 << 63, 0, 0, 0] as X)) - NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X), 256, T(x64:[0, 0, 0, 0] as X)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Miscellaneous - //=------------------------------------------------------------------------= - - func testBitshiftingIsSmart() { - XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) << 1, T(x64:[2, 4, 6, 8, 0] as X)) - XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) >> -1, T(x64:[2, 4, 6, 8, 0] as X)) - - XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) << 64, T(x64:[0, 1, 2, 3, 4] as X)) - XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) >> -64, T(x64:[0, 1, 2, 3, 4] as X)) - } - - func testBitshiftingRightDoesNotTrap() { - XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) >> Int.max, T.zero) - XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) << Int.min, T.zero) - } - - func testBitshiftingZeroDoesNotTrap() { - XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) << Int.min, T.zero) - XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) << Int.max, T.zero) - - XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) >> Int.min, T.zero) - XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) >> Int.max, T.zero) - } - - func testBitshiftingZeroDoesNotDoAnything() { - XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) << (UInt.bitWidth + 0), T.zero) - XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) << (UInt.bitWidth + 1), T.zero) - - XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) >> (UInt.bitWidth + 0), T.zero) - XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) >> (UInt.bitWidth + 1), T.zero) - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Shifts x Assertions -//*============================================================================* - -private func NBKAssertShiftLeft( -_ lhs: T, _ rhs: Int, _ result: T, -file: StaticString = #file, line: UInt = #line) { - //=------------------------------------------= - let (words, bits) = rhs.quotientAndRemainder(dividingBy: UInt.bitWidth) - //=------------------------------------------= - XCTAssertEqual( lhs << rhs, result, file: file, line: line) - XCTAssertEqual( lhs >> -rhs, result, file: file, line: line) - - XCTAssertEqual({ var lhs = lhs; lhs <<= rhs; return lhs }(), result, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs >>= -rhs; return lhs }(), result, file: file, line: line) - - XCTAssertEqual(lhs.bitshiftedLeftSmart(by: rhs), result, file: file, line: line) - XCTAssertEqual(lhs.bitshiftedRightSmart(by: -rhs), result, file: file, line: line) - - XCTAssertEqual({ var lhs = lhs; lhs.bitshiftLeftSmart(by: rhs); return lhs }(), result, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs.bitshiftRightSmart(by: -rhs); return lhs }(), result, file: file, line: line) - //=------------------------------------------= - if 0 ..< lhs.bitWidth ~= rhs { - XCTAssertEqual(lhs.bitshiftedLeft(by: rhs), result, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs.bitshiftLeft(by: rhs); return lhs }(), result, file: file, line: line) - - XCTAssertEqual(lhs.bitshiftedLeft(words: words, bits: bits), result, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs.bitshiftLeft(words: words, bits: bits); return lhs }(), result, file: file, line: line) - } - //=------------------------------------------= - if 0 ..< lhs.bitWidth ~= rhs, bits.isZero { - XCTAssertEqual(lhs.bitshiftedLeft(words: words), result, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs.bitshiftLeft(words: words); return lhs }(), result, file: file, line: line) - } -} - -private func NBKAssertShiftRight( -_ lhs: T, _ rhs: Int, _ result: T, -file: StaticString = #file, line: UInt = #line) { - //=------------------------------------------= - let (words, bits) = rhs.quotientAndRemainder(dividingBy: UInt.bitWidth) - //=------------------------------------------= - XCTAssertEqual( lhs >> rhs, result, file: file, line: line) - XCTAssertEqual( lhs << -rhs, result, file: file, line: line) - - XCTAssertEqual({ var lhs = lhs; lhs >>= rhs; return lhs }(), result, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs <<= -rhs; return lhs }(), result, file: file, line: line) - - XCTAssertEqual(lhs.bitshiftedRightSmart(by: rhs), result, file: file, line: line) - XCTAssertEqual(lhs.bitshiftedLeftSmart(by: -rhs), result, file: file, line: line) - - XCTAssertEqual({ var lhs = lhs; lhs.bitshiftRightSmart(by: rhs); return lhs }(), result, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs.bitshiftLeftSmart(by: -rhs); return lhs }(), result, file: file, line: line) - //=------------------------------------------= - if 0 ..< lhs.bitWidth ~= rhs { - XCTAssertEqual(lhs.bitshiftedRight(by: rhs), result, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs.bitshiftRight(by: rhs); return lhs }(), result, file: file, line: line) - - XCTAssertEqual(lhs.bitshiftedRight(words: words, bits: bits), result, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs.bitshiftRight(words: words, bits: bits); return lhs }(), result, file: file, line: line) - } - //=------------------------------------------= - if 0 ..< lhs.bitWidth ~= rhs, bits.isZero { - XCTAssertEqual(lhs.bitshiftedRight(words: words), result, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs.bitshiftRight(words: words); return lhs }(), result, file: file, line: line) - } -} - -#endif diff --git a/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Subtraction.swift b/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Subtraction.swift deleted file mode 100644 index c8e4ac13..00000000 --- a/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Subtraction.swift +++ /dev/null @@ -1,275 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if DEBUG - -import NBKCoreKit -import NBKTwosComplementKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Flexible Width x Subtraction x IntXL -//*============================================================================* - -final class NBKFlexibleWidthTestsOnSubtractionAsIntXL: XCTestCase { - - typealias T = IntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testSubtracting() { - NBKAssertSubtraction(T( 1), T( 2), Int(0), T(-1)) - NBKAssertSubtraction(T( 1), T( 1), Int(0), T( 0)) - NBKAssertSubtraction(T( 1), T( 0), Int(0), T( 1)) - NBKAssertSubtraction(T( 1), T(-1), Int(0), T( 2)) - NBKAssertSubtraction(T( 1), T(-2), Int(0), T( 3)) - - NBKAssertSubtraction(T( 0), T( 2), Int(0), T(-2)) - NBKAssertSubtraction(T( 0), T( 1), Int(0), T(-1)) - NBKAssertSubtraction(T( 0), T( 0), Int(0), T( 0)) - NBKAssertSubtraction(T( 0), T(-1), Int(0), T( 1)) - NBKAssertSubtraction(T( 0), T(-2), Int(0), T( 2)) - - NBKAssertSubtraction(T(-1), T( 2), Int(0), T(-3)) - NBKAssertSubtraction(T(-1), T( 1), Int(0), T(-2)) - NBKAssertSubtraction(T(-1), T( 0), Int(0), T(-1)) - NBKAssertSubtraction(T(-1), T(-1), Int(0), T( 0)) - NBKAssertSubtraction(T(-1), T(-2), Int(0), T( 1)) - } - - func testSubtractingAtIndex() { - NBKAssertSubtraction(T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[~1, ~2, ~3, ~0] as W)) - NBKAssertSubtraction(T(words:[ 0, ~0, ~0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[~0, ~3, ~3, ~0] as W)) - NBKAssertSubtraction(T(words:[ 0, 0, ~0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[~0, ~2, ~4, ~0] as W)) - NBKAssertSubtraction(T(words:[ 0, 0, 0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[~0, ~2, ~3, ~1] as W)) - - NBKAssertSubtraction(T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[~0, ~1, ~2, ~3] as W)) - NBKAssertSubtraction(T(words:[ 0, ~0, ~0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[ 0, ~1, ~2, ~3] as W)) - NBKAssertSubtraction(T(words:[ 0, 0, ~0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[ 0, ~0, ~3, ~3] as W)) - NBKAssertSubtraction(T(words:[ 0, 0, 0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[ 0, ~0, ~2, ~4] as W)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Digit - //=------------------------------------------------------------------------= - - func testSubtractingDigit() { - NBKAssertSubtractionByDigit(T( 1), Int( 2), Int(0), T(-1)) - NBKAssertSubtractionByDigit(T( 1), Int( 1), Int(0), T( 0)) - NBKAssertSubtractionByDigit(T( 1), Int( 0), Int(0), T( 1)) - NBKAssertSubtractionByDigit(T( 1), Int(-1), Int(0), T( 2)) - NBKAssertSubtractionByDigit(T( 1), Int(-2), Int(0), T( 3)) - - NBKAssertSubtractionByDigit(T( 0), Int( 2), Int(0), T(-2)) - NBKAssertSubtractionByDigit(T( 0), Int( 1), Int(0), T(-1)) - NBKAssertSubtractionByDigit(T( 0), Int( 0), Int(0), T( 0)) - NBKAssertSubtractionByDigit(T( 0), Int(-1), Int(0), T( 1)) - NBKAssertSubtractionByDigit(T( 0), Int(-2), Int(0), T( 2)) - - NBKAssertSubtractionByDigit(T(-1), Int( 2), Int(0), T(-3)) - NBKAssertSubtractionByDigit(T(-1), Int( 1), Int(0), T(-2)) - NBKAssertSubtractionByDigit(T(-1), Int( 0), Int(0), T(-1)) - NBKAssertSubtractionByDigit(T(-1), Int(-1), Int(0), T( 0)) - NBKAssertSubtractionByDigit(T(-1), Int(-2), Int(0), T( 1)) - } - - func testSubtractingDigitAtIndex() { - NBKAssertSubtractionByDigit(T(words:[~0, ~0, ~0, ~0] as W), Int(3), Int(0), T(words:[~3, ~0, ~0, ~0] as W)) - NBKAssertSubtractionByDigit(T(words:[ 0, ~0, ~0, ~0] as W), Int(3), Int(0), T(words:[~2, ~1, ~0, ~0] as W)) - NBKAssertSubtractionByDigit(T(words:[ 0, 0, ~0, ~0] as W), Int(3), Int(0), T(words:[~2, ~0, ~1, ~0] as W)) - NBKAssertSubtractionByDigit(T(words:[ 0, 0, 0, ~0] as W), Int(3), Int(0), T(words:[~2, ~0, ~0, ~1] as W)) - - NBKAssertSubtractionByDigit(T(words:[~0, ~0, ~0, ~0] as W), Int(3), Int(1), T(words:[~0, ~3, ~0, ~0] as W)) - NBKAssertSubtractionByDigit(T(words:[ 0, ~0, ~0, ~0] as W), Int(3), Int(1), T(words:[ 0, ~3, ~0, ~0] as W)) - NBKAssertSubtractionByDigit(T(words:[ 0, 0, ~0, ~0] as W), Int(3), Int(1), T(words:[ 0, ~2, ~1, ~0] as W)) - NBKAssertSubtractionByDigit(T(words:[ 0, 0, 0, ~0] as W), Int(3), Int(1), T(words:[ 0, ~2, ~0, ~1] as W)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Miscellaneous - //=------------------------------------------------------------------------= - - func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { - func becauseThisCompilesSuccessfully(_ x: inout T) { - XCTAssertNotNil(x -= 0) - XCTAssertNotNil(x.subtract(0, at: 0)) - - XCTAssertNotNil(x - 0) - XCTAssertNotNil(x.subtracting(0, at: 0)) - } - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Subtraction x UIntXL -//*============================================================================* - -final class NBKFlexibleWidthTestsOnSubtractionAsUIntXL: XCTestCase { - - typealias T = UIntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testSubtracting() { - NBKAssertSubtraction(T(3), T(0), Int(0), T(3)) - NBKAssertSubtraction(T(3), T(1), Int(0), T(2)) - NBKAssertSubtraction(T(3), T(2), Int(0), T(1)) - NBKAssertSubtraction(T(3), T(3), Int(0), T(0)) - } - - func testSubtractingReportingOverflow() { - NBKAssertSubtraction(T(1), T(0), Int(0), T(words:[ 1] as W)) - NBKAssertSubtraction(T(1), T(1), Int(0), T(words:[ 0] as W)) - NBKAssertSubtraction(T(1), T(2), Int(0), T(words:[~0] as W), true) - NBKAssertSubtraction(T(1), T(3), Int(0), T(words:[~1] as W), true) - } - - func testSubtractingAtIndex() { - NBKAssertSubtraction(T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[~1, ~2, ~3, ~0] as W)) - NBKAssertSubtraction(T(words:[ 0, ~0, ~0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[~0, ~3, ~3, ~0] as W)) - NBKAssertSubtraction(T(words:[ 0, 0, ~0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[~0, ~2, ~4, ~0] as W)) - NBKAssertSubtraction(T(words:[ 0, 0, 0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[~0, ~2, ~3, ~1] as W)) - - NBKAssertSubtraction(T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[~0, ~1, ~2, ~3] as W)) - NBKAssertSubtraction(T(words:[ 0, ~0, ~0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[ 0, ~1, ~2, ~3] as W)) - NBKAssertSubtraction(T(words:[ 0, 0, ~0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[ 0, ~0, ~3, ~3] as W)) - NBKAssertSubtraction(T(words:[ 0, 0, 0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[ 0, ~0, ~2, ~4] as W)) - } - - func testSubtractingAtIndexReportingOverflow() { - NBKAssertSubtraction(T(words:[ 1, 2, 3, 0] as W), T(words:[ 4, 5, 0, 0] as W), Int(0), T(words:[~2, ~3, 2, 0] as W)) - NBKAssertSubtraction(T(words:[ 1, 2, 3, 0] as W), T(words:[ 4, 5, 0, 0] as W), Int(1), T(words:[ 1, ~1, ~2, 0] as W), true) - NBKAssertSubtraction(T(words:[ 1, 2, 3, 0] as W), T(words:[ 4, 5, 0, 0] as W), Int(2), T(words:[ 1, 2, ~0, ~5] as W), true) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Digit - //=------------------------------------------------------------------------= - - func testSubtractingDigit() { - NBKAssertSubtractionByDigit(T(3), UInt(0), Int(0), T(3)) - NBKAssertSubtractionByDigit(T(3), UInt(1), Int(0), T(2)) - NBKAssertSubtractionByDigit(T(3), UInt(2), Int(0), T(1)) - NBKAssertSubtractionByDigit(T(3), UInt(3), Int(0), T(0)) - } - - func testSubtractingDigitReportingOverflow() { - NBKAssertSubtractionByDigit(T(1), UInt(0), Int(0), T(words:[ 1] as W)) - NBKAssertSubtractionByDigit(T(1), UInt(1), Int(0), T(words:[ 0] as W)) - NBKAssertSubtractionByDigit(T(1), UInt(2), Int(0), T(words:[~0] as W), true) - NBKAssertSubtractionByDigit(T(1), UInt(3), Int(0), T(words:[~1] as W), true) - } - - func testSubtractingDigitAtIndex() { - NBKAssertSubtractionByDigit(T(words:[~0, ~0, ~0, ~0] as W), UInt(3), Int(0), T(words:[~3, ~0, ~0, ~0] as W)) - NBKAssertSubtractionByDigit(T(words:[ 0, ~0, ~0, ~0] as W), UInt(3), Int(0), T(words:[~2, ~1, ~0, ~0] as W)) - NBKAssertSubtractionByDigit(T(words:[ 0, 0, ~0, ~0] as W), UInt(3), Int(0), T(words:[~2, ~0, ~1, ~0] as W)) - NBKAssertSubtractionByDigit(T(words:[ 0, 0, 0, ~0] as W), UInt(3), Int(0), T(words:[~2, ~0, ~0, ~1] as W)) - - NBKAssertSubtractionByDigit(T(words:[~0, ~0, ~0, ~0] as W), UInt(3), Int(1), T(words:[~0, ~3, ~0, ~0] as W)) - NBKAssertSubtractionByDigit(T(words:[ 0, ~0, ~0, ~0] as W), UInt(3), Int(1), T(words:[ 0, ~3, ~0, ~0] as W)) - NBKAssertSubtractionByDigit(T(words:[ 0, 0, ~0, ~0] as W), UInt(3), Int(1), T(words:[ 0, ~2, ~1, ~0] as W)) - NBKAssertSubtractionByDigit(T(words:[ 0, 0, 0, ~0] as W), UInt(3), Int(1), T(words:[ 0, ~2, ~0, ~1] as W)) - } - - func testSubtractingDigitAtIndexReportingOverflow() { - NBKAssertSubtractionByDigit(T(words:[ 1, 2, 3, 0] as W), UInt(5), Int(0), T(words:[~3, 1, 3, 0] as W)) - NBKAssertSubtractionByDigit(T(words:[ 1, 2, 3, 0] as W), UInt(5), Int(1), T(words:[ 1, ~2, 2, 0] as W)) - NBKAssertSubtractionByDigit(T(words:[ 1, 2, 3, 0] as W), UInt(5), Int(2), T(words:[ 1, 2, ~1, 0] as W), true) - NBKAssertSubtractionByDigit(T(words:[ 1, 2, 3, 0] as W), UInt(5), Int(3), T(words:[ 1, 2, 3, ~4] as W), true) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Miscellaneous - //=------------------------------------------------------------------------= - - func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { - func becauseThisCompilesSuccessfully(_ x: inout T) { - XCTAssertNotNil(x -= 0) - XCTAssertNotNil(x.subtract(0, at: 0)) - XCTAssertNotNil(x.subtractReportingOverflow(0, at: 0)) - - XCTAssertNotNil(x - 0) - XCTAssertNotNil(x.subtracting(0, at: 0)) - XCTAssertNotNil(x.subtractingReportingOverflow(0, at: 0)) - } - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Subtraction x Assertions -//*============================================================================* - -private func NBKAssertSubtraction( -_ lhs: T, _ rhs: T, _ index: Int, _ partialValue: T, _ overflow: Bool = false, -file: StaticString = #file, line: UInt = #line) { - //=------------------------------------------= - if !overflow, index.isZero { - XCTAssertEqual( lhs - rhs, partialValue, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs -= rhs; return lhs }(), partialValue, file: file, line: line) - - XCTAssertEqual(lhs.subtracting(rhs, at: Int.zero), partialValue, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs.subtract(rhs, at: Int.zero); return lhs }(), partialValue, file: file, line: line) - } - //=------------------------------------------= - guard let lhs = lhs as? UIntXL, let rhs = rhs as? UIntXL, let partialValue = partialValue as? UIntXL else { return } - //=------------------------------------------= - if index.isZero { - XCTAssertEqual(lhs.subtractingReportingOverflow(rhs).partialValue, partialValue, file: file, line: line) - XCTAssertEqual(lhs.subtractingReportingOverflow(rhs).overflow, overflow, file: file, line: line) - - XCTAssertEqual({ var x = lhs; let _ = x.subtractReportingOverflow(rhs); return x }(), partialValue, file: file, line: line) - XCTAssertEqual({ var x = lhs; let o = x.subtractReportingOverflow(rhs); return o }(), overflow, file: file, line: line) - } - //=------------------------------------------= - XCTAssertEqual(lhs.subtractingReportingOverflow(rhs, at: index).partialValue, partialValue, file: file, line: line) - XCTAssertEqual(lhs.subtractingReportingOverflow(rhs, at: index).overflow, overflow, file: file, line: line) - - XCTAssertEqual({ var x = lhs; let _ = x.subtractReportingOverflow(rhs, at: index); return x }(), partialValue, file: file, line: line) - XCTAssertEqual({ var x = lhs; let o = x.subtractReportingOverflow(rhs, at: index); return o }(), overflow, file: file, line: line) -} - -private func NBKAssertSubtractionByDigit( -_ lhs: T, _ rhs: T.Digit, _ index: Int, _ partialValue: T, _ overflow: Bool = false, -file: StaticString = #file, line: UInt = #line) { - //=------------------------------------------= - if !overflow, index.isZero { - XCTAssertEqual( lhs - rhs, partialValue, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs -= rhs; return lhs }(), partialValue, file: file, line: line) - - XCTAssertEqual(lhs.subtracting(rhs, at: Int.zero), partialValue, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs.subtract(rhs, at: Int.zero); return lhs }(), partialValue, file: file, line: line) - } - //=------------------------------------------= - guard let lhs = lhs as? UIntXL, let rhs = rhs as? UIntXL.Digit, let partialValue = partialValue as? UIntXL else { return } - //=------------------------------------------= - if index.isZero { - XCTAssertEqual(lhs.subtractingReportingOverflow(rhs).partialValue, partialValue, file: file, line: line) - XCTAssertEqual(lhs.subtractingReportingOverflow(rhs).overflow, overflow, file: file, line: line) - - XCTAssertEqual({ var x = lhs; let _ = x.subtractReportingOverflow(rhs); return x }(), partialValue, file: file, line: line) - XCTAssertEqual({ var x = lhs; let o = x.subtractReportingOverflow(rhs); return o }(), overflow, file: file, line: line) - } - //=------------------------------------------= - XCTAssertEqual(lhs.subtractingReportingOverflow(rhs, at: index).partialValue, partialValue, file: file, line: line) - XCTAssertEqual(lhs.subtractingReportingOverflow(rhs, at: index).overflow, overflow, file: file, line: line) - - XCTAssertEqual({ var x = lhs; let _ = x.subtractReportingOverflow(rhs, at: index); return x }(), partialValue, file: file, line: line) - XCTAssertEqual({ var x = lhs; let o = x.subtractReportingOverflow(rhs, at: index); return o }(), overflow, file: file, line: line) -} - -#endif diff --git a/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Text.swift b/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Text.swift deleted file mode 100644 index 416a9122..00000000 --- a/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Text.swift +++ /dev/null @@ -1,1432 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if DEBUG - -import NBKCoreKit -import NBKTwosComplementKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Flexible Width x Text x IntXL -//*============================================================================* - -final class NBKFlexibleWidthTestsOnTextAsIntXL: XCTestCase { - - typealias T = IntXL - - //=------------------------------------------------------------------------= - // MARK: State - //=------------------------------------------------------------------------= - - let bit256 = 256 - let min256 = T.min256 - let max256 = T.max256 - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testFromDescription() { - NBKAssertFromDescription(T?( 10), "10") - NBKAssertFromDescription(T?( 10), "+10") - NBKAssertFromDescription(T?(-10), "-10") - NBKAssertFromDescription(T?(nil), " 10") - NBKAssertFromDescription(T?(nil), "0x10") - NBKAssertFromDescription(T?(nil), "+0x10") - NBKAssertFromDescription(T?(nil), "-0x10") - NBKAssertFromDescription(T?(nil), " 0x10") - } - - func testInstanceDescriptionUsesRadix10() { - XCTAssertEqual("10", T(10).description) - XCTAssertEqual("10", String(describing: T(10))) - } - - func testMetaTypeDescriptionIsSimple() { - XCTAssertEqual("IntXL", T.description) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Decode - //=------------------------------------------------------------------------= - - func testDecodingRadix02() { - NBKAssertDecodeText(min256, 02, "-1" + String(repeating: "0", count: bit256 / 1 - 1)) - NBKAssertDecodeText(max256, 02, String(repeating: "1", count: bit256 / 1 - 1)) - } - - func testDecodingRadix03() { - NBKAssertDecodeText(min256, 03, "-21221122120" + - "12222212211110210202220000022211002111211122012220" + - "12122202101121021220012201000100012101202122101020" + - "20010111121211022111102111220220201211121011101022" ) - NBKAssertDecodeText(max256, 03, "21221122120" + - "12222212211110210202220000022211002111211122012220" + - "12122202101121021220012201000100012101202122101020" + - "20010111121211022111102111220220201211121011101021" ) - } - - func testDecodingRadix04() { - NBKAssertDecodeText(min256, 04, "-2" + String(repeating: "0", count: bit256 / 2 - 1)) - NBKAssertDecodeText(max256, 04, "1" + String(repeating: "3", count: bit256 / 2 - 1)) - } - - func testDecodingRadix08() { - NBKAssertDecodeText(min256, 08, "-1" + String(repeating: "0", count: 85)) - NBKAssertDecodeText(max256, 08, String(repeating: "7", count: 85)) - } - - func testDecodingRadix10() { - NBKAssertDecodeText(min256, 10, "-57896044618658097711785492504343953926634992332820282019728792003956564819968") - NBKAssertDecodeText(max256, 10, "57896044618658097711785492504343953926634992332820282019728792003956564819967") - } - - func testDecodingRadix16() { - NBKAssertDecodeText(min256, 16, "-8" + String(repeating: "0", count: bit256 / 4 - 1)) - NBKAssertDecodeText(max256, 16, "7" + String(repeating: "f", count: bit256 / 4 - 1)) - } - - func testDecodingRadix32() { - NBKAssertDecodeText(min256, 32, "-1" + String(repeating: "0", count: 51)) - NBKAssertDecodeText(max256, 32, String(repeating: "v", count: 51)) - } - - func testDecodingRadix36() { - NBKAssertDecodeText(min256, 36, "-36ukv65j19b11mbvjyfui963v4my01krth19g3r3bk1ojlrwu8") - NBKAssertDecodeText(max256, 36, "36ukv65j19b11mbvjyfui963v4my01krth19g3r3bk1ojlrwu7") - } - - func testDecodingRadixLiteralAsNumber() { - NBKAssertDecodeText(T( 33), 36, "0x") - NBKAssertDecodeText(T( 24), 36, "0o") - NBKAssertDecodeText(T( 11), 36, "0b") - - NBKAssertDecodeText(T( 33), 36, "+0x") - NBKAssertDecodeText(T( 24), 36, "+0o") - NBKAssertDecodeText(T( 11), 36, "+0b") - - NBKAssertDecodeText(T(-33), 36, "-0x") - NBKAssertDecodeText(T(-24), 36, "-0o") - NBKAssertDecodeText(T(-11), 36, "-0b") - } - - func testDecodingRadixLiteralAsRadixReturnsNil() { - NBKAssertDecodeText(T?.none, 10, "0x10") - NBKAssertDecodeText(T?.none, 10, "0o10") - NBKAssertDecodeText(T?.none, 10, "0b10") - - NBKAssertDecodeText(T?.none, 10, "+0x10") - NBKAssertDecodeText(T?.none, 10, "+0o10") - NBKAssertDecodeText(T?.none, 10, "+0b10") - - NBKAssertDecodeText(T?.none, 10, "-0x10") - NBKAssertDecodeText(T?.none, 10, "-0o10") - NBKAssertDecodeText(T?.none, 10, "-0b10") - } - - func testDecodingStringsWithAndWithoutSign() { - NBKAssertDecodeText(T( 1234567890), 10, "1234567890") - NBKAssertDecodeText(T( 1234567890), 10, "+1234567890") - NBKAssertDecodeText(T(-1234567890), 10, "-1234567890") - } - - func testDecodingStrategyIsCaseInsensitive() { - NBKAssertDecodeText(T(0xabcdef), 16, "abcdef") - NBKAssertDecodeText(T(0xABCDEF), 16, "ABCDEF") - NBKAssertDecodeText(T(0xaBcDeF), 16, "aBcDeF") - NBKAssertDecodeText(T(0xAbCdEf), 16, "AbCdEf") - } - - func testDecodingUnalignedStringsIsOK() { - NBKAssertDecodeText(T(1), 10, "1") - NBKAssertDecodeText(T(1), 16, "1") - } - - func testDecodingPrefixingZerosHasNoEffect() { - let zero = String(repeating: "0", count: bit256) + "0" - let one = String(repeating: "0", count: bit256) + "1" - - for radix in 02 ... 36 { - NBKAssertDecodeText(T(0), radix, zero) - NBKAssertDecodeText(T(1), radix, one ) - } - } - - func testDecodingInvalidCharactersReturnsNil() { - NBKAssertDecodeText(T?.none, 16, "/") - NBKAssertDecodeText(T?.none, 16, "G") - - NBKAssertDecodeText(T?.none, 10, "/") - NBKAssertDecodeText(T?.none, 10, ":") - - NBKAssertDecodeText(T?.none, 10, String(repeating: "1", count: 19) + "/") - NBKAssertDecodeText(T?.none, 10, String(repeating: "1", count: 19) + ":") - } - - func testDecodingStringsWithoutDigitsReturnsNil() { - NBKAssertDecodeText(T?.none, 10, "") - NBKAssertDecodeText(T?.none, 10, "+") - NBKAssertDecodeText(T?.none, 10, "-") - NBKAssertDecodeText(T?.none, 10, "~") - - NBKAssertDecodeText(T?.none, 16, "") - NBKAssertDecodeText(T?.none, 16, "+") - NBKAssertDecodeText(T?.none, 16, "-") - NBKAssertDecodeText(T?.none, 16, "~") - } - - func testDecodingValuesOutsideOfRepresentableRangeReturnsNil() { - let positive = "+" + String(repeating: "1", count: bit256) - let negative = "-" + String(repeating: "1", count: bit256) - - for radix in 02 ... 36 { - XCTAssertNotNil(T(positive, radix: radix)) - XCTAssertNotNil(T(negative, radix: radix)) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Encode - //=------------------------------------------------------------------------= - - func testEncodingRadix02() { - NBKAssertEncodeText(min256, 02, false, "-1" + String(repeating: "0", count: bit256 / 1 - 1)) - NBKAssertEncodeText(max256, 02, false, String(repeating: "1", count: bit256 / 1 - 1)) - } - - func testEncodingRadix03() { - NBKAssertEncodeText(min256, 03, false,"-21221122120" + - "12222212211110210202220000022211002111211122012220" + - "12122202101121021220012201000100012101202122101020" + - "20010111121211022111102111220220201211121011101022" ) - NBKAssertEncodeText(max256, 03, false, "21221122120" + - "12222212211110210202220000022211002111211122012220" + - "12122202101121021220012201000100012101202122101020" + - "20010111121211022111102111220220201211121011101021" ) - } - - func testEncodingRadix04() { - NBKAssertEncodeText(min256, 04, false, "-2" + String(repeating: "0", count: bit256 / 2 - 1)) - NBKAssertEncodeText(max256, 04, false, "1" + String(repeating: "3", count: bit256 / 2 - 1)) - } - - func testEncodingRadix08() { - NBKAssertEncodeText(min256, 08, false, "-1" + String(repeating: "0", count: 85)) - NBKAssertEncodeText(max256, 08, false, String(repeating: "7", count: 85)) - } - - func testEncodingRadix10() { - NBKAssertEncodeText(min256, 10, false, "-57896044618658097711785492504343953926634992332820282019728792003956564819968") - NBKAssertEncodeText(max256, 10, false, "57896044618658097711785492504343953926634992332820282019728792003956564819967") - } - - func testEncodingRadix16() { - NBKAssertEncodeText(min256, 16, false, "-8" + String(repeating: "0", count: bit256 / 4 - 1)) - NBKAssertEncodeText(min256, 16, true , "-8" + String(repeating: "0", count: bit256 / 4 - 1)) - NBKAssertEncodeText(max256, 16, false, "7" + String(repeating: "f", count: bit256 / 4 - 1)) - NBKAssertEncodeText(max256, 16, true , "7" + String(repeating: "F", count: bit256 / 4 - 1)) - } - - func testEncodingRadix32() { - NBKAssertEncodeText(min256, 32, false, "-1" + String(repeating: "0", count: 51)) - NBKAssertEncodeText(min256, 32, true , "-1" + String(repeating: "0", count: 51)) - NBKAssertEncodeText(max256, 32, false, String(repeating: "v", count: 51)) - NBKAssertEncodeText(max256, 32, true , String(repeating: "V", count: 51)) - } - - func testEncodingRadix36() { - NBKAssertEncodeText(min256, 36, false, "-36ukv65j19b11mbvjyfui963v4my01krth19g3r3bk1ojlrwu8") - NBKAssertEncodeText(min256, 36, true , "-36UKV65J19B11MBVJYFUI963V4MY01KRTH19G3R3BK1OJLRWU8") - NBKAssertEncodeText(max256, 36, false, "36ukv65j19b11mbvjyfui963v4my01krth19g3r3bk1ojlrwu7") - NBKAssertEncodeText(max256, 36, true , "36UKV65J19B11MBVJYFUI963V4MY01KRTH19G3R3BK1OJLRWU7") - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Text x UIntXL -//*============================================================================* - -final class NBKFlexibleWidthTestsOnTextAsUIntXL: XCTestCase { - - typealias T = UIntXL - - //=------------------------------------------------------------------------= - // MARK: State - //=------------------------------------------------------------------------= - - let bit256 = 256 - let min256 = T.min256 - let max256 = T.max256 - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testFromDescription() { - NBKAssertFromDescription(T?( 10), "10") - NBKAssertFromDescription(T?( 10), "+10") - NBKAssertFromDescription(T?(nil), "-10") - NBKAssertFromDescription(T?(nil), " 10") - NBKAssertFromDescription(T?(nil), "0x10") - NBKAssertFromDescription(T?(nil), "+0x10") - NBKAssertFromDescription(T?(nil), "-0x10") - NBKAssertFromDescription(T?(nil), " 0x10") - } - - func testInstanceDescriptionUsesRadix10() { - XCTAssertEqual("10", T(10).description) - XCTAssertEqual("10", String(describing: T(10))) - } - - func testMetaTypeDescriptionIsSimple() { - XCTAssertEqual("UIntXL", T.description) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Decode - //=------------------------------------------------------------------------= - - func testDecodingRadix02() { - NBKAssertDecodeText(min256, 02, "0") - NBKAssertDecodeText(max256, 02, String(repeating: "1", count: bit256 / 1)) - } - - func testDecodingRadix03() { - NBKAssertDecodeText(min256, 03, "0" ) - NBKAssertDecodeText(max256, 03, "120220022011" + - "02222202122221121112210000122122012000200021102211" + - "02022111210012120210102102000200101210112021202111" + - "10021000020122121222212000211211110200012022202120" ) - } - - func testDecodingRadix04() { - NBKAssertDecodeText(min256, 04, "0") - NBKAssertDecodeText(max256, 04, String(repeating: "3", count: bit256 / 2)) - } - - func testDecodingRadix08() { - NBKAssertDecodeText(min256, 08, "0") - NBKAssertDecodeText(max256, 08, "1" + String(repeating: "7", count: 85)) - } - - func testDecodingRadix10() { - NBKAssertDecodeText(min256, 10, "0") - NBKAssertDecodeText(max256, 10, "115792089237316195423570985008687907853269984665640564039457584007913129639935") - } - - func testDecodingRadix16() { - NBKAssertDecodeText(min256, 16, "0") - NBKAssertDecodeText(max256, 16, String(repeating: "f", count: bit256 / 4)) - } - - func testDecodingRadix32() { - NBKAssertDecodeText(min256, 32, "0") - NBKAssertDecodeText(max256, 32, "1" + String(repeating: "v", count: 51)) - } - - func testDecodingRadix36() { - NBKAssertDecodeText(min256, 36, "0") - NBKAssertDecodeText(max256, 36, "6dp5qcb22im238nr3wvp0ic7q99w035jmy2iw7i6n43d37jtof") - } - - func testDecodingRadixLiteralAsNumber() { - NBKAssertDecodeText(T(33), 36, "0x") - NBKAssertDecodeText(T(24), 36, "0o") - NBKAssertDecodeText(T(11), 36, "0b") - - NBKAssertDecodeText(T(33), 36, "+0x") - NBKAssertDecodeText(T(24), 36, "+0o") - NBKAssertDecodeText(T(11), 36, "+0b") - } - - func testDecodingRadixLiteralAsRadixReturnsNil() { - NBKAssertDecodeText(T?.none, 10, "0x10") - NBKAssertDecodeText(T?.none, 10, "0o10") - NBKAssertDecodeText(T?.none, 10, "0b10") - - NBKAssertDecodeText(T?.none, 10, "+0x10") - NBKAssertDecodeText(T?.none, 10, "+0o10") - NBKAssertDecodeText(T?.none, 10, "+0b10") - } - - func testDecodingStringsWithAndWithoutSign() { - NBKAssertDecodeText(T(1234567890), 10, "1234567890") - NBKAssertDecodeText(T(1234567890), 10, "+1234567890") - } - - func testDecodingStrategyIsCaseInsensitive() { - NBKAssertDecodeText(T(0xabcdef), 16, "abcdef") - NBKAssertDecodeText(T(0xABCDEF), 16, "ABCDEF") - NBKAssertDecodeText(T(0xaBcDeF), 16, "aBcDeF") - NBKAssertDecodeText(T(0xAbCdEf), 16, "AbCdEf") - } - - func testDecodingUnalignedStringsIsOK() { - NBKAssertDecodeText(T(1), 10, "1") - NBKAssertDecodeText(T(1), 16, "1") - } - - func testDecodingPrefixingZerosHasNoEffect() { - let zero = String(repeating: "0", count: bit256) + "0" - let one = String(repeating: "0", count: bit256) + "1" - - for radix in 02 ... 36 { - NBKAssertDecodeText(T(0), radix, zero) - NBKAssertDecodeText(T(1), radix, one ) - } - } - - func testDecodingInvalidCharactersReturnsNil() { - NBKAssertDecodeText(T?.none, 16, "/") - NBKAssertDecodeText(T?.none, 16, "G") - - NBKAssertDecodeText(T?.none, 10, "/") - NBKAssertDecodeText(T?.none, 10, ":") - - NBKAssertDecodeText(T?.none, 10, String(repeating: "1", count: 19) + "/") - NBKAssertDecodeText(T?.none, 10, String(repeating: "1", count: 19) + ":") - } - - func testDecodingStringsWithoutDigitsReturnsNil() { - NBKAssertDecodeText(T?.none, 10, "") - NBKAssertDecodeText(T?.none, 10, "+") - NBKAssertDecodeText(T?.none, 10, "-") - NBKAssertDecodeText(T?.none, 10, "~") - - NBKAssertDecodeText(T?.none, 16, "") - NBKAssertDecodeText(T?.none, 16, "+") - NBKAssertDecodeText(T?.none, 16, "-") - NBKAssertDecodeText(T?.none, 16, "~") - } - - func testDecodingValuesOutsideOfRepresentableRangeReturnsNil() { - let positive = "+" + String(repeating: "1", count: bit256 + 1) - let negative = "-" + String(repeating: "1", count: 1) - - for radix in 02 ... 36 { - XCTAssertNotNil(T(positive, radix: radix)) - NBKAssertDecodeText(T?.none, radix, negative) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Encode - //=------------------------------------------------------------------------= - - func testEncodingRadix02() { - NBKAssertEncodeText(min256, 02, false, "0") - NBKAssertEncodeText(max256, 02, false, String(repeating: "1", count: bit256 / 1)) - } - - func testEncodingRadix03() { - NBKAssertEncodeText(min256, 03, false, "0" ) - NBKAssertEncodeText(max256, 03, false,"120220022011" + - "02222202122221121112210000122122012000200021102211" + - "02022111210012120210102102000200101210112021202111" + - "10021000020122121222212000211211110200012022202120" ) - } - - func testEncodingRadix04() { - NBKAssertEncodeText(min256, 04, false, "0") - NBKAssertEncodeText(max256, 04, false, String(repeating: "3", count: bit256 / 2)) - } - - func testEncodingRadix08() { - NBKAssertEncodeText(min256, 08, false, "0") - NBKAssertEncodeText(max256, 08, false, "1" + String(repeating: "7", count: 85)) - } - - func testEncodingRadix10() { - NBKAssertEncodeText(min256, 10, false, "0") - NBKAssertEncodeText(max256, 10, false, "115792089237316195423570985008687907853269984665640564039457584007913129639935") - } - - func testEncodingRadix16() { - NBKAssertEncodeText(min256, 16, false, "0") - NBKAssertEncodeText(min256, 16, true , "0") - NBKAssertEncodeText(max256, 16, false, String(repeating: "f", count: bit256 / 4)) - NBKAssertEncodeText(max256, 16, true , String(repeating: "F", count: bit256 / 4)) - } - - func testEncodingRadix32() { - NBKAssertEncodeText(min256, 32, false, "0") - NBKAssertEncodeText(min256, 32, true , "0") - NBKAssertEncodeText(max256, 32, false, "1" + String(repeating: "v", count: 51)) - NBKAssertEncodeText(max256, 32, true , "1" + String(repeating: "V", count: 51)) - } - - func testEncodingRadix36() { - NBKAssertEncodeText(min256, 36, false, "0") - NBKAssertEncodeText(min256, 36, true , "0") - NBKAssertEncodeText(max256, 36, false, "6dp5qcb22im238nr3wvp0ic7q99w035jmy2iw7i6n43d37jtof") - NBKAssertEncodeText(max256, 36, true , "6DP5QCB22IM238NR3WVP0IC7Q99W035JMY2IW7I6N43D37JTOF") - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Text x For Each Radix x UIntXL -//*============================================================================* - -final class NBKFlexibleWidthTestsOnTextForEachRadixAsUIntXL: XCTestCase { - - typealias T = UIntXL - - //=------------------------------------------------------------------------= - // MARK: State - //=------------------------------------------------------------------------= - - var radix: Int = 10 - var x64 = (UInt64(), UInt64(), UInt64(), UInt64()) - var txt = (String()) - - //=------------------------------------------------------------------------= - // MARK: Set Up, Tear Down - //=------------------------------------------------------------------------= - - override func setUp() { - self.radix = 10 - self.x64.0 = UInt64() - self.x64.1 = UInt64() - self.x64.2 = UInt64() - self.x64.3 = UInt64() - self.txt = String() - } - - override func tearDown() { - let decoded = T(x64: [x64.0, x64.1, x64.2, x64.3]) - var encoded = String(self.txt.drop{ $0 == "0" }) - if encoded.isEmpty { - encoded.append(contentsOf: self.txt.suffix(1)) - } - - NBKAssertDecodeText(decoded, self.radix, txt) - NBKAssertDecodeText(decoded, self.radix, encoded) - NBKAssertEncodeText(decoded, self.radix, true, encoded.uppercased()) - NBKAssertEncodeText(decoded, self.radix, false, encoded.lowercased()) - } - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testRadix02Top() { - self.radix = 02 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 1111111111111110111111011111110011111011111110101111100111111000\ - 1111011111110110111101011111010011110011111100101111000111110000\ - 1110111111101110111011011110110011101011111010101110100111101000\ - 1110011111100110111001011110010011100011111000101110000111100000 - """ - } - - func testRadix02Bottom() { - self.radix = 02 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 0001111100011110000111010001110000011011000110100001100100011000\ - 0001011100010110000101010001010000010011000100100001000100010000\ - 0000111100001110000011010000110000001011000010100000100100001000\ - 0000011100000110000001010000010000000011000000100000000100000000 - """ - } - - //=----( 03 )--------------------------------------------------------------= - - func testRadix03Top() { - self.radix = 03 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 0000000000000000000000000000001202200212221120001222202211110211\ - 2122212010220102122202121101120111112200201101101222110200202110\ - 0220201022101000210101202220120002101202101120201012012212012002 - """ - } - - func testRadix03Bottom() { - self.radix = 03 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 0000000000000000000000000000000012210112211101210122010202201212\ - 2200112221212101221211222010022020100210220200100011100100222021\ - 2000121220012212111000111110212212201000011111112211120210102101 - """ - } - - //=----( 04 )--------------------------------------------------------------= - - func testRadix04Top() { - self.radix = 04 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 3333333233313330332333223321332033133312331133103303330233013300\ - 3233323232313230322332223221322032133212321132103203320232013200 - """ - } - - func testRadix04Bottom() { - self.radix = 04 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 0133013201310130012301220121012001130112011101100103010201010100\ - 0033003200310030002300220021002000130012001100100003000200010000 - """ - } - - //=----( 05 )--------------------------------------------------------------= - - func testRadix05Top() { - self.radix = 05 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 0000000000000000012224200130200441041444042343242340402322434230\ - 2203100014323101131021202442142123441124102101232423332422334024 - """ - } - - func testRadix05Bottom() { - self.radix = 05 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 0000000000000000000424043311031102404011202312202132022104340041\ - 4431003121344314114341012313341313423214420311244321214230031301 - """ - } - - //=----( 06 )--------------------------------------------------------------= - - func testRadix06Top() { - self.radix = 06 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 0000000000000000000000000000102141010531040333210533123011525130\ - 3433311132532415235332533224344010103324220312020213104050423132 - """ - } - - func testRadix06Bottom() { - self.radix = 06 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 0000000000000000000000000000004353050531332542114015530141512113\ - 1210015440102001011522210020211244125255022541512055450000200144 - """ - } - - //=----( 07 )--------------------------------------------------------------= - - func testRadix07Top() { - self.radix = 07 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 0000000000000000000000000000000000001305333621612661215031353503\ - 1603616341660421351201115002605631306624232666655230226263060363 - """ - } - - func testRadix07Bottom() { - self.radix = 07 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 0000000000000000000000000000000000000114142063044505436351120634\ - 3333263503132100565010106005630324255134635601621240633030645403 - """ - } - - //=----( 08 )--------------------------------------------------------------= - - func testRadix08Top() { - self.radix = 08 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 0000000000000000000000000000000000000000001777767737637376574770\ - 7577336575171762743703577356675472765351721637467136234370560740 - """ - } - - func testRadix08Bottom() { - self.radix = 08 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 0000000000000000000000000000000000000000000174360721603306414430\ - 0561302505011422042100170340641402605011020034060120200300400400 - """ - } - - //=----( 09 )--------------------------------------------------------------= - - func testRadix09Top() { - self.radix = 09 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 0000000000000000000000000000000000000000000000052625846058684424\ - 7876381258254151448064135842067326638330711686502352346635185162 - """ - } - - func testRadix09Bottom() { - self.radix = 09 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 0000000000000000000000000000000000000000000000005715741718122655\ - 8048777185486326632382030431086760556185430443785630144484523371 - """ - } - - //=----( 10 )--------------------------------------------------------------= - - func testRadix10Top() { - self.radix = 10 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 0000000000000000000000000000000000000000000000000011579030850545\ - 5567723526024286119531261069242336003260839703036409543150199264 - """ - } - - func testRadix10Bottom() { - self.radix = 10 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 0000000000000000000000000000000000000000000000000001407490462640\ - 1341155369551180448584754667373453244490859944217516317499064576 - """ - } - - //=----( 11 )--------------------------------------------------------------= - - func testRadix11Top() { - self.radix = 11 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 0000000000000000000000000000000000000000000000000000010019774172\ - 675069499548a05a7794803603a4157366204225264092700a8157a30a948720 - """ - } - - func testRadix11Bottom() { - self.radix = 11 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 0000000000000000000000000000000000000000000000000000001380227a9a\ - 3a453071005401517000a3500756239a46834284766655651370a28295109a06 - """ - } - - //=----( 12 )--------------------------------------------------------------= - - func testRadix12Top() { - self.radix = 12 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 0000000000000000000000000000000000000000000000000000000029231468\ - 41b6624b4657b76b759711256462675490811529026b8b03507956b900591aa8 - """ - } - - func testRadix12Bottom() { - self.radix = 12 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 000000000000000000000000000000000000000000000000000000000404b13b\ - 22595a847521b8ab337490660a0b7439b1495399a8b2918a9521301732309054 - """ - } - - //=----( 13 )--------------------------------------------------------------= - - func testRadix13Top() { - self.radix = 13 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 0000000000000000000000000000000000000000000000000000000000178a92\ - 980701228a277594134c94bb7165a938c70c03a705750115a339820831351c78 - """ - } - - func testRadix13Bottom() { - self.radix = 13 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 00000000000000000000000000000000000000000000000000000000000268a5\ - 1c5770b549c51487a17526804a0a14c0c44bbc981573456a275580297a4a7834 - """ - } - - //=----( 14 )--------------------------------------------------------------= - - func testRadix14Top() { - self.radix = 14 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 0000000000000000000000000000000000000000000000000000000000001c38\ - 14cbd353812dca285cc376972998797340345da539017abd8236000c88ca00da - """ - } - - func testRadix14Bottom() { - self.radix = 14 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 0000000000000000000000000000000000000000000000000000000000000329\ - 76a45325cd6dda6ac91cb8c9bccbbc61488833c2225a774c2da97ab4d4565d3a - """ - } - - //=----( 15 )--------------------------------------------------------------= - - func testRadix15Top() { - self.radix = 15 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 0000000000000000000000000000000000000000000000000000000000000042\ - 314e1223518107b1362e160a5ad29226b4e3e2d35ea57996aaa3242db02966ae - """ - } - - func testRadix15Bottom() { - self.radix = 15 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 0000000000000000000000000000000000000000000000000000000000000007\ - 864d3605e05bd91d94b651ccc4e3078d6edc902745e03953a310b0de5c602701 - """ - } - - //=----( 16 )--------------------------------------------------------------= - - func testRadix16Top() { - self.radix = 16 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e0 - """ - } - - func testRadix16Bottom() { - self.radix = 16 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100 - """ - } - - //=----( 17 )--------------------------------------------------------------= - - func testRadix17Top() { - self.radix = 17 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 05g7d81gc01cdbf42565444eaa12342c35gd9f66bbg36c8d8841baa7a8faab0e - """ - } - - func testRadix17Bottom() { - self.radix = 17 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 00c5b2gcge3c140g4d527274dgd5cg7g58babg3e21bg76739a559151527ce653 - """ - } - - //=----( 18 )--------------------------------------------------------------= - - func testRadix18Top() { - self.radix = 18 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 0031fhf5dce9fgc12bg164e9h35028896f83ddhh8be5286c3e9h17360bg1bg32 - """ - } - - func testRadix18Bottom() { - self.radix = 18 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 0006e51f0da7284a3bb14747c33cgb1hfa3120c549aec7hh58g39hg075a02c3a - """ - } - - //=----( 19 )--------------------------------------------------------------= - - func testRadix19Top() { - self.radix = 19 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 000237ibab6cg652id30fgh76hdai93dhfh7dhagfdc5eb7f782c55d551ed74g6 - """ - } - - func testRadix19Bottom() { - self.radix = 19 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 000050cae6cb5210060eg1g2iicc8e689a04g25829g2f5bc8c84ea4a8a1348f4 - """ - } - - //=----( 20 )--------------------------------------------------------------= - - func testRadix20Top() { - self.radix = 20 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 000020392d6ac9d1jd12d3a88c61i7ba748483ai05hf66c6a7g42977fbe8ei34 - """ - } - - func testRadix20Bottom() { - self.radix = 20 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 000004hd5e33e5189jajhc248c2a513ae74fba267d1b3d1743i8ebgb30i9318g - """ - } - - //=----( 21 )--------------------------------------------------------------= - - func testRadix21Top() { - self.radix = 21 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 0000027gdj7593kjg0f1c5cga4aca1e1d5f08h72cebhcbc1c6cek06cf13eaddh - """ - } - - func testRadix21Bottom() { - self.radix = 21 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 0000006124cec92463a07f87dgg069g06715hcg4j03fha2f1gafce80g895g09a - """ - } - - //=----( 22 )--------------------------------------------------------------= - - func testRadix22Top() { - self.radix = 22 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 0000003b5jk54f19beiidebchgec3ffc28aggdd74h75ijdc00i4ea0ji14954c0 - """ - } - - func testRadix22Bottom() { - self.radix = 22 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 000000098djlg8ll6ge66j798kd129gf43e7c6586a31h5a25adg2l78kj3a82b6 - """ - } - - //=----( 23 )--------------------------------------------------------------= - - func testRadix23Top() { - self.radix = 23 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 000000069a79baglcjbdblbk5111bb46b66g2b7a2f596763kmm7c3hbl336kl14 - """ - } - - func testRadix23Bottom() { - self.radix = 23 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 00000000hl580j6lii99g9c5137ji22ab5i41mba3lh6091cakd4h6llil689h12 - """ - } - - //=----( 24 )--------------------------------------------------------------= - - func testRadix24Top() { - self.radix = 24 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 00000000e4eikjgk76jj7i2fbn6ihk3ngef39fb00gjl3086em4k7g3ag5647hh8 - """ - } - - func testRadix24Bottom() { - self.radix = 24 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 000000001h9gbi9kc8ig99kj5lil4in9d6e81la5d0h872fff899ebj57j88732g - """ - } - - //=----( 25 )--------------------------------------------------------------= - - func testRadix25Top() { - self.radix = 25 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 000000001cea1fa4l49o4dnedkkdcnmfc3509hg185baem9bdo6e5b1dediecike - """ - } - - func testRadix25Bottom() { - self.radix = 25 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 0000000004e4i6362kk6ad7abh2b4j0log0gbjn96nl1d8j88mh9m36enbbmf381 - """ - } - - //=----( 26 )--------------------------------------------------------------= - - func testRadix26Top() { - self.radix = 26 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 0000000004dd8f12of8578gn3cho4kjg1nm4ck49ihk7nahjpeie4d78426fjja8 - """ - } - - func testRadix26Bottom() { - self.radix = 26 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 0000000000e7a4822n1867n87cpm330nai4o7gj05b5j013bb0in29cncoodh584 - """ - } - - //=----( 27 )--------------------------------------------------------------= - - func testRadix27Top() { - self.radix = 27 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 0000000000fo7qe0hopd7gqfbj7q7m4jdh2445pb279oj8a0lakof2akafj55n52 - """ - } - - func testRadix27Bottom() { - self.radix = 27 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 00000000001p4pcg5j6ogq1hng5neo9oj2bk10d12on0go5nd0dcnnj04demflba - """ - } - - //=----( 28 )--------------------------------------------------------------= - - func testRadix28Top() { - self.radix = 28 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 000000000028lp360pqr9fgjmgalj15e5kknmk8pd61irgj23bbe6nbafahp3e6o - """ - } - - func testRadix28Bottom() { - self.radix = 28 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 000000000007odiqi7ipkbell34qeml609e642lhrao5n03422ik497coam17kmo - """ - } - - //=----( 29 )--------------------------------------------------------------= - - func testRadix29Top() { - self.radix = 29 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 00000000000acrhqlapaaob766is1eng6erp522m0f5opigage3d3j4k7f9n8ff2 - """ - } - - func testRadix29Bottom() { - self.radix = 29 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 0000000000017nr4pcg1heg13dh8cgggmn4q34frqm65gn8ec0j45591bmqfhffb - """ - } - - //=----( 30 )--------------------------------------------------------------= - - func testRadix30Top() { - self.radix = 30 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 000000000001nmr6nq4fe87dse4p4i0ama7co4moqch8081liop9spg2kl9rn95e - """ - } - - func testRadix30Bottom() { - self.radix = 30 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 0000000000006g1ldfsednredtimcop3b5l3q70e4kitjnhrn4eql74ecaf5j1mg - """ - } - - //=----( 31 )--------------------------------------------------------------= - - func testRadix31Top() { - self.radix = 31 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 000000000000a30ts5ohp5e917o3nehp8urue2rb4e97icid1me5tcmpil25fi6m - """ - } - - func testRadix31Bottom() { - self.radix = 31 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 000000000000171hhf8063e3r4a99sra00a157pihstia75dmk5kfae5nnn9ab6l - """ - } - - //=----( 32 )--------------------------------------------------------------= - - func testRadix32Top() { - self.radix = 32 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 0000000000001vvuvnufnunpv3rvdtfkufpf3s7ftrmupqvat7kefpn5sjhu5of0 - """ - } - - func testRadix32Bottom() { - self.radix = 32 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 00000000000007ou3ke1m6gp30bhc58k2c91240f1o6go2oa1440e1g50g1g4080 - """ - } - - //=----( 33 )--------------------------------------------------------------= - - func testRadix33Top() { - self.radix = 33 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 0000000000000dodf9g17rn5pvw3et1k184sgnb11u6u7uhk2n9b3bhtfwrh14fb - """ - } - - func testRadix33Bottom() { - self.radix = 33 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 00000000000001m3p6weqc5jk0wsb37sv08ileepww3jad5cr0cfhd0g1aq8in3s - """ - } - - //=----( 34 )--------------------------------------------------------------= - - func testRadix34Top() { - self.radix = 34 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 00000000000003304fs1ae3ixjsrahw1k6lt33dlup2jc54b1p3xxaghpss3swhe - """ - } - - func testRadix34Bottom() { - self.radix = 34 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 00000000000000cpwunuqgcm028uqxuqmjst7gk65egpsowcgixwuci6x899aa2k - """ - } - - //=----( 35 )--------------------------------------------------------------= - - func testRadix35Top() { - self.radix = 35 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 00000000000000pcyhqj7yk3vq8j4l4vfa7wes91wah4p1y3op2k48s4pv0y189o - """ - } - - func testRadix35Bottom() { - self.radix = 35 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 0000000000000032wujn2mg481jyhidxmv5271ucr21qfj9jdvqm429mwneu6b2v - """ - } - - //=----( 36 )--------------------------------------------------------------= - - func testRadix36Top() { - self.radix = 36 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 000000000000006dp15j43ld5l8i7wvimlj7kxgbfxkxkgmo66lge382296ouqjk - """ - } - - func testRadix36Bottom() { - self.radix = 36 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 000000000000000rx55jlhq7obx1pvd9861yo6c11bed0cd8s8wz2hpvczt00c1s - """ - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Text x Assertions -//*============================================================================* - -private func NBKAssertFromDescription( -_ integer: T?, _ description: String, -file: StaticString = #file, line: UInt = #line) { - //=------------------------------------------= - XCTAssertEqual(T(description), integer, file: file, line: line) - XCTAssertEqual(T(description, radix: 10), integer, file: file, line: line) -} - -private func NBKAssertDecodeText ( -_ integer: T?, _ radix: Int, _ text: String, -file: StaticString = #file, line: UInt = #line) { - //=------------------------------------------= - if radix == 10 { - XCTAssertEqual(T.init(text), integer, file: file, line: line) - } - //=------------------------------------------= - XCTAssertEqual(T.init(text, radix: radix), integer, file: file, line: line) -} - -private func NBKAssertEncodeText( -_ integer: T, _ radix: Int, _ uppercase: Bool, _ text: String, -file: StaticString = #file, line: UInt = #line) { - //=------------------------------------------= - if radix == 10, uppercase == false { - XCTAssertEqual(String.init(integer), text, file: file, line: line) - XCTAssertEqual(integer.description, text, file: file, line: line) - } - //=------------------------------------------= - XCTAssertEqual(String.init(integer,radix: radix, uppercase: uppercase), text, file: file, line: line) - XCTAssertEqual(integer.description(radix: radix, uppercase: uppercase), text, file: file, line: line) -} - -#endif diff --git a/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Words.swift b/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Words.swift deleted file mode 100644 index 0ca40164..00000000 --- a/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth+Words.swift +++ /dev/null @@ -1,175 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if DEBUG - -import NBKCoreKit -import NBKTwosComplementKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Flexible Width x Words x IntXL -//*============================================================================* - -final class NBKFlexibleWidthTestsOnWordsAsIntXL: XCTestCase { - - typealias T = IntXL - typealias M = UIntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testWords() { - NBKAssertWords(T(words:[0 ]), [0 ]) - NBKAssertWords(T(words:[1 ]), [1 ]) - NBKAssertWords(T(words:[1, 2 ]), [1, 2 ]) - NBKAssertWords(T(words:[1, 2, 3 ]), [1, 2, 3 ]) - NBKAssertWords(T(words:[1, 2, 3, 4]), [1, 2, 3, 4]) - - NBKAssertWords(T(words:[0, 0, 0, 0]), [0 ]) - NBKAssertWords(T(words:[1, 0, 0, 0]), [1 ]) - NBKAssertWords(T(words:[1, 2, 0, 0]), [1, 2 ]) - NBKAssertWords(T(words:[1, 2, 3, 0]), [1, 2, 3 ]) - NBKAssertWords(T(words:[1, 2, 3, 4]), [1, 2, 3, 4]) - - NBKAssertWords(T(sign: .plus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as W)), [~0, ~0, ~0, ~0/2 + 0 ] as W) // 4 - NBKAssertWords(T(sign: .plus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as W)), [ 0, 0, 0, ~0/2 + 1, 0] as W) // 5 - NBKAssertWords(T(sign: .plus, magnitude: M(words:[ 1, 0, 0, ~0/2 + 1] as W)), [ 1, 0, 0, ~0/2 + 1, 0] as W) // 5 - - NBKAssertWords(T(sign: .minus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as W)), [ 1, 0, 0, ~0/2 + 1 ] as W) // 4 - NBKAssertWords(T(sign: .minus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as W)), [ 0, 0, 0, ~0/2 + 1 ] as W) // 4 - NBKAssertWords(T(sign: .minus, magnitude: M(words:[ 1, 0, 0, ~0/2 + 1] as W)), [~0, ~0, ~0, ~0/2 + 0, ~0] as W) // 5 - } - - func testWordsX64() throws { - guard MemoryLayout.size == MemoryLayout.size else { throw XCTSkip() } - - NBKAssertWords(T(x64:[0 ] as X), [0 ]) - NBKAssertWords(T(x64:[1 ] as X), [1 ]) - NBKAssertWords(T(x64:[1, 2 ] as X), [1, 2 ]) - NBKAssertWords(T(x64:[1, 2, 3 ] as X), [1, 2, 3 ]) - NBKAssertWords(T(x64:[1, 2, 3, 4] as X), [1, 2, 3, 4]) - - NBKAssertWords(T(x64:[0, 0, 0, 0] as X), [0 ]) - NBKAssertWords(T(x64:[1, 0, 0, 0] as X), [1 ]) - NBKAssertWords(T(x64:[1, 2, 0, 0] as X), [1, 2 ]) - NBKAssertWords(T(x64:[1, 2, 3, 0] as X), [1, 2, 3 ]) - NBKAssertWords(T(x64:[1, 2, 3, 4] as X), [1, 2, 3, 4]) - } - - func testWordsX32() throws { - guard MemoryLayout.size == MemoryLayout.size else { throw XCTSkip() } - - NBKAssertWords(T(x32:[0 ] as Y), [0 ]) - NBKAssertWords(T(x32:[1 ] as Y), [1 ]) - NBKAssertWords(T(x32:[1, 2 ] as Y), [1, 2 ]) - NBKAssertWords(T(x32:[1, 2, 3 ] as Y), [1, 2, 3 ]) - NBKAssertWords(T(x32:[1, 2, 3, 4 ] as Y), [1, 2, 3, 4 ]) - NBKAssertWords(T(x32:[1, 2, 3, 4, 5 ] as Y), [1, 2, 3, 4, 5 ]) - NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6 ] as Y), [1, 2, 3, 4, 5, 6 ]) - NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6, 7 ] as Y), [1, 2, 3, 4, 5, 6, 7 ]) - NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6, 7, 8] as Y), [1, 2, 3, 4, 5, 6, 7, 8]) - - NBKAssertWords(T(x32:[0, 0, 0, 0, 0, 0, 0, 0] as Y), [0 ]) - NBKAssertWords(T(x32:[1, 0, 0, 0, 0, 0, 0, 0] as Y), [1 ]) - NBKAssertWords(T(x32:[1, 2, 0, 0, 0, 0, 0, 0] as Y), [1, 2 ]) - NBKAssertWords(T(x32:[1, 2, 3, 0, 0, 0, 0, 0] as Y), [1, 2, 3 ]) - NBKAssertWords(T(x32:[1, 2, 3, 4, 0, 0, 0, 0] as Y), [1, 2, 3, 4 ]) - NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 0, 0, 0] as Y), [1, 2, 3, 4, 5 ]) - NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6, 0, 0] as Y), [1, 2, 3, 4, 5, 6 ]) - NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6, 7, 0] as Y), [1, 2, 3, 4, 5, 6, 7 ]) - NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6, 7, 8] as Y), [1, 2, 3, 4, 5, 6, 7, 8]) - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Words x UIntXL -//*============================================================================* - -final class NBKFlexibleWidthTestsOnWordsAsUIntXL: XCTestCase { - - typealias T = UIntXL - typealias M = UIntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testWords() { - NBKAssertWords(T(words:[0 ]), [0 ]) - NBKAssertWords(T(words:[1 ]), [1 ]) - NBKAssertWords(T(words:[1, 2 ]), [1, 2 ]) - NBKAssertWords(T(words:[1, 2, 3 ]), [1, 2, 3 ]) - NBKAssertWords(T(words:[1, 2, 3, 4]), [1, 2, 3, 4]) - - NBKAssertWords(T(words:[0, 0, 0, 0]), [0 ]) - NBKAssertWords(T(words:[1, 0, 0, 0]), [1 ]) - NBKAssertWords(T(words:[1, 2, 0, 0]), [1, 2 ]) - NBKAssertWords(T(words:[1, 2, 3, 0]), [1, 2, 3 ]) - NBKAssertWords(T(words:[1, 2, 3, 4]), [1, 2, 3, 4]) - } - - func testWordsX64() throws { - guard MemoryLayout.size == MemoryLayout.size else { throw XCTSkip() } - - NBKAssertWords(T(x64:[0 ] as X), [0 ]) - NBKAssertWords(T(x64:[1 ] as X), [1 ]) - NBKAssertWords(T(x64:[1, 2 ] as X), [1, 2 ]) - NBKAssertWords(T(x64:[1, 2, 3 ] as X), [1, 2, 3 ]) - NBKAssertWords(T(x64:[1, 2, 3, 4] as X), [1, 2, 3, 4]) - - NBKAssertWords(T(x64:[0, 0, 0, 0] as X), [0 ]) - NBKAssertWords(T(x64:[1, 0, 0, 0] as X), [1 ]) - NBKAssertWords(T(x64:[1, 2, 0, 0] as X), [1, 2 ]) - NBKAssertWords(T(x64:[1, 2, 3, 0] as X), [1, 2, 3 ]) - NBKAssertWords(T(x64:[1, 2, 3, 4] as X), [1, 2, 3, 4]) - } - - func testWordsX32() throws { - guard MemoryLayout.size == MemoryLayout.size else { throw XCTSkip() } - - NBKAssertWords(T(x32:[0 ] as Y), [0 ]) - NBKAssertWords(T(x32:[1 ] as Y), [1 ]) - NBKAssertWords(T(x32:[1, 2 ] as Y), [1, 2 ]) - NBKAssertWords(T(x32:[1, 2, 3 ] as Y), [1, 2, 3 ]) - NBKAssertWords(T(x32:[1, 2, 3, 4 ] as Y), [1, 2, 3, 4 ]) - NBKAssertWords(T(x32:[1, 2, 3, 4, 5 ] as Y), [1, 2, 3, 4, 5 ]) - NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6 ] as Y), [1, 2, 3, 4, 5, 6 ]) - NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6, 7 ] as Y), [1, 2, 3, 4, 5, 6, 7 ]) - NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6, 7, 8] as Y), [1, 2, 3, 4, 5, 6, 7, 8]) - - NBKAssertWords(T(x32:[0, 0, 0, 0, 0, 0, 0, 0] as Y), [0 ]) - NBKAssertWords(T(x32:[1, 0, 0, 0, 0, 0, 0, 0] as Y), [1 ]) - NBKAssertWords(T(x32:[1, 2, 0, 0, 0, 0, 0, 0] as Y), [1, 2 ]) - NBKAssertWords(T(x32:[1, 2, 3, 0, 0, 0, 0, 0] as Y), [1, 2, 3 ]) - NBKAssertWords(T(x32:[1, 2, 3, 4, 0, 0, 0, 0] as Y), [1, 2, 3, 4 ]) - NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 0, 0, 0] as Y), [1, 2, 3, 4, 5 ]) - NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6, 0, 0] as Y), [1, 2, 3, 4, 5, 6 ]) - NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6, 7, 0] as Y), [1, 2, 3, 4, 5, 6, 7 ]) - NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6, 7, 8] as Y), [1, 2, 3, 4, 5, 6, 7, 8]) - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Words x Assertions -//*============================================================================* - -private func NBKAssertWords( -_ integer: T, _ words: [UInt], -file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual(Array(integer.words), Array(words), file: file, line: line) - XCTAssertEqual(Array(integer.words.reversed()), Array(words.reversed()), file: file, line: line) -} - -#endif diff --git a/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth.swift b/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth.swift deleted file mode 100644 index c1cb189f..00000000 --- a/Tests/NBKTwosComplementKitTests/NBKFlexibleWidth.swift +++ /dev/null @@ -1,68 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit -import NBKTwosComplementKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Flexible Width x IntXL -//*============================================================================* - -extension IntXL { - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - static let min256 = Self(x64:[ 0, 0, 0, ~0/2 + 1] as X) - static let max256 = Self(x64:[~0, ~0, ~0, ~0/2 + 0] as X) - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - init(x32: [UInt32]) { - self.init(words: NBKChunkedInt(x32)) - } - - init(x64: [UInt64]) { - self.init(words: NBKChunkedInt(x64)) - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x UIntXL -//*============================================================================* - -extension UIntXL { - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - static let min256 = Self(x64:[ 0, 0, 0, 0] as X) - static let max256 = Self(x64:[~0, ~0, ~0, ~0] as X) - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - init(x32: [UInt32]) { - self.init(words: NBKChunkedInt(x32)) - } - - init(x64: [UInt64]) { - self.init(words: NBKChunkedInt(x64)) - } -} From 0063ebbf7a9576cb73d4a0203b5f2628adae5e45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Fri, 15 Sep 2023 07:51:12 +0200 Subject: [PATCH 068/133] [NBKFlexibleWidthKit] Cleanup. --- .../NBKFlexibleWidth+Protocols.swift | 6 ---- .../NBKFlexibleWidth+Size.swift | 34 +------------------ .../NBKFlexibleWidth+Update.swift | 23 ------------- .../NBKFlexibleWidth.swift | 12 ++----- 4 files changed, 3 insertions(+), 72 deletions(-) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Protocols.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Protocols.swift index aed23f72..fe73e4b9 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Protocols.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Protocols.swift @@ -15,12 +15,6 @@ import NBKCoreKit public protocol IntXLOrUIntXL: NBKBinaryInteger, ExpressibleByStringLiteral where Magnitude == UIntXL { - //=------------------------------------------------------------------------= - // MARK: Details x Size - //=------------------------------------------------------------------------= - - @inlinable mutating func reserveCapacity(_ minCapacity: Int) - //=------------------------------------------------------------------------= // MARK: Details x Comparisons //=------------------------------------------------------------------------= diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Size.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Size.swift index 431e2016..c9be2063 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Size.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Size.swift @@ -9,36 +9,6 @@ import NBKCoreKit -//*============================================================================* -// MARK: * NBK x Flexible Width x Size x Signed -//*============================================================================* - -extension NBKFlexibleWidth { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable public mutating func reserveCapacity(_ minCapacity: Int) { - self.magnitude.reserveCapacity(minCapacity + 1) - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Size x Unsigned -//*============================================================================* - -extension NBKFlexibleWidth.Magnitude { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable public mutating func reserveCapacity(_ minCapacity: Int) { - self.storage.reserveCapacity(minCapacity) - } -} - //*============================================================================* // MARK: * NBK x Flexible Width x Size x Unsigned x Storage //*============================================================================* @@ -61,12 +31,10 @@ extension NBKFlexibleWidth.Magnitude.Storage { } @inlinable mutating func resize(maxCount: Int) { - //=--------------------------------------= + precondition(maxCount.isMoreThanZero) if self.elements.count > maxCount { self.elements.removeSubrange(maxCount...) } - //=--------------------------------------= - precondition(self.isOK, Self.invariantsInfo()) } @inlinable mutating func reserveCapacity(_ minCapacity: Int) { diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Update.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Update.swift index 3f2ba4ef..0dd89856 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Update.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Update.swift @@ -48,26 +48,3 @@ extension NBKFlexibleWidth.Magnitude { self.storage.normalize(update: value) } } - -//*============================================================================* -// MARK: * NBK x Flexible Width x Update x Unsigned x Storage -//*============================================================================* - -extension NBKFlexibleWidth.Magnitude.Storage { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable mutating func updateZeroValue() { - self.update(repeating: false) - } - - @inlinable mutating func update(repeating bit: Bool) { - self.update(repeating: UInt(repeating: bit)) - } - - @inlinable mutating func update(repeating word: UInt) { - self.withUnsafeMutableBufferPointer({ $0.update(repeating: word) }) - } -} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift index f21bf562..d76441e5 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift @@ -137,29 +137,21 @@ import NBKCoreKit @inlinable init(elements: Elements) { self.elements = elements - precondition(self.isOK, Self.invariantsInfo()) + precondition(!self.elements.isEmpty) } @inlinable init(unchecked elements: Elements) { self.elements = elements - Swift.assert(self.isOK, Self.invariantsInfo()) + Swift.assert(!self.elements.isEmpty) } //=----------------------------------------------------------------= // MARK: Utilities //=----------------------------------------------------------------= - @inlinable var isOK: Bool { - !self.elements.isEmpty - } - @inlinable var isNormal: Bool { self.elements.count == 1 || !self.elements.last!.isZero } - - @inlinable static func invariantsInfo() -> String { - "UIntXL must contain at least one element" - } } } } From c54255d095fe8e708bb9e5f1387f2f2e9e06eb7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Fri, 15 Sep 2023 07:55:18 +0200 Subject: [PATCH 069/133] Start of sign and magnitude (#81). --- .swiftpm/NBKSignedKit-Benchmarks.xctestplan | 24 +++++++ .swiftpm/NBKSignedKit.xctestplan | 32 +++++++++ .swiftpm/Numberick-Benchmarks.xctestplan | 7 ++ .swiftpm/Numberick.xctestplan | 12 ++++ .../NBKSignedKit-Benchmarks.xcscheme | 71 +++++++++++++++++++ .../xcschemes/NBKSignedKit.xcscheme | 71 +++++++++++++++++++ .../xcschemes/Numberick-Benchmarks.xcscheme | 3 + .../xcshareddata/xcschemes/Numberick.xcscheme | 17 +++++ Package.swift | 20 ++++++ Sources/NBKSignedKit/Blank.swift | 1 + Tests/NBKSignedKitBenchmarks/Blank.swift | 1 + Tests/NBKSignedKitTests/Blank.swift | 1 + 12 files changed, 260 insertions(+) create mode 100644 .swiftpm/NBKSignedKit-Benchmarks.xctestplan create mode 100644 .swiftpm/NBKSignedKit.xctestplan create mode 100644 .swiftpm/xcode/xcshareddata/xcschemes/NBKSignedKit-Benchmarks.xcscheme create mode 100644 .swiftpm/xcode/xcshareddata/xcschemes/NBKSignedKit.xcscheme create mode 100644 Sources/NBKSignedKit/Blank.swift create mode 100644 Tests/NBKSignedKitBenchmarks/Blank.swift create mode 100644 Tests/NBKSignedKitTests/Blank.swift diff --git a/.swiftpm/NBKSignedKit-Benchmarks.xctestplan b/.swiftpm/NBKSignedKit-Benchmarks.xctestplan new file mode 100644 index 00000000..af19a60e --- /dev/null +++ b/.swiftpm/NBKSignedKit-Benchmarks.xctestplan @@ -0,0 +1,24 @@ +{ + "configurations" : [ + { + "id" : "2BBD9A51-D890-4B97-AED4-B9962867DF57", + "name" : "Main", + "options" : { + + } + } + ], + "defaultOptions" : { + "codeCoverage" : false + }, + "testTargets" : [ + { + "target" : { + "containerPath" : "container:", + "identifier" : "NBKSignedKitBenchmarks", + "name" : "NBKSignedKitBenchmarks" + } + } + ], + "version" : 1 +} diff --git a/.swiftpm/NBKSignedKit.xctestplan b/.swiftpm/NBKSignedKit.xctestplan new file mode 100644 index 00000000..25e71b3a --- /dev/null +++ b/.swiftpm/NBKSignedKit.xctestplan @@ -0,0 +1,32 @@ +{ + "configurations" : [ + { + "id" : "6FC9897F-2BF3-4836-8372-787CE5195F87", + "name" : "Main", + "options" : { + + } + } + ], + "defaultOptions" : { + "codeCoverage" : { + "targets" : [ + { + "containerPath" : "container:", + "identifier" : "NBKSignedKit", + "name" : "NBKSignedKit" + } + ] + } + }, + "testTargets" : [ + { + "target" : { + "containerPath" : "container:", + "identifier" : "NBKSignedKitTests", + "name" : "NBKSignedKitTests" + } + } + ], + "version" : 1 +} diff --git a/.swiftpm/Numberick-Benchmarks.xctestplan b/.swiftpm/Numberick-Benchmarks.xctestplan index b7a219a1..ffa5330a 100644 --- a/.swiftpm/Numberick-Benchmarks.xctestplan +++ b/.swiftpm/Numberick-Benchmarks.xctestplan @@ -42,6 +42,13 @@ "identifier" : "NBKFlexibleWidthKitBenchmarks", "name" : "NBKFlexibleWidthKitBenchmarks" } + }, + { + "target" : { + "containerPath" : "container:", + "identifier" : "NBKSignedKitBenchmarks", + "name" : "NBKSignedKitBenchmarks" + } } ], "version" : 1 diff --git a/.swiftpm/Numberick.xctestplan b/.swiftpm/Numberick.xctestplan index 74306fdc..aecc3cda 100644 --- a/.swiftpm/Numberick.xctestplan +++ b/.swiftpm/Numberick.xctestplan @@ -25,6 +25,11 @@ "containerPath" : "container:", "identifier" : "NBKFlexibleWidthKit", "name" : "NBKFlexibleWidthKit" + }, + { + "containerPath" : "container:", + "identifier" : "NBKSignedKit", + "name" : "NBKSignedKit" } ] } @@ -50,6 +55,13 @@ "identifier" : "NBKFlexibleWidthKitTests", "name" : "NBKFlexibleWidthKitTests" } + }, + { + "target" : { + "containerPath" : "container:", + "identifier" : "NBKSignedKitTests", + "name" : "NBKSignedKitTests" + } } ], "version" : 1 diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/NBKSignedKit-Benchmarks.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/NBKSignedKit-Benchmarks.xcscheme new file mode 100644 index 00000000..edd967a0 --- /dev/null +++ b/.swiftpm/xcode/xcshareddata/xcschemes/NBKSignedKit-Benchmarks.xcscheme @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/NBKSignedKit.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/NBKSignedKit.xcscheme new file mode 100644 index 00000000..53b88591 --- /dev/null +++ b/.swiftpm/xcode/xcshareddata/xcschemes/NBKSignedKit.xcscheme @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/Numberick-Benchmarks.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/Numberick-Benchmarks.xcscheme index 8cf9cef5..c8f30afc 100644 --- a/.swiftpm/xcode/xcshareddata/xcschemes/Numberick-Benchmarks.xcscheme +++ b/.swiftpm/xcode/xcshareddata/xcschemes/Numberick-Benchmarks.xcscheme @@ -41,6 +41,9 @@ + + + + + + + + Date: Fri, 15 Sep 2023 08:04:44 +0200 Subject: [PATCH 070/133] [NBKSignedKit] NBKSigned (#81). --- .../NBKTwosComplementKit-Benchmarks.xcscheme | 71 ---------- .../xcschemes/NBKTwosComplementKit.xcscheme | 71 ---------- Package.swift | 4 +- Sources/NBKSignedKit/Blank.swift | 1 - .../NBKSigned+Addition+Digit.swift | 34 +++++ Sources/NBKSignedKit/NBKSigned+Addition.swift | 34 +++++ .../NBKSignedKit/NBKSigned+Comparisons.swift | 88 ++++++++++++ .../NBKSigned+Division+Digit.swift | 42 ++++++ Sources/NBKSignedKit/NBKSigned+Division.swift | 42 ++++++ Sources/NBKSignedKit/NBKSigned+Literals.swift | 25 ++++ .../NBKSigned+Multiplication+Digit.swift | 30 +++++ .../NBKSigned+Multiplication.swift | 30 +++++ Sources/NBKSignedKit/NBKSigned+Negation.swift | 37 +++++ Sources/NBKSignedKit/NBKSigned+Numbers.swift | 65 +++++++++ .../NBKSigned+Subtraction+Digit.swift | 34 +++++ .../NBKSignedKit/NBKSigned+Subtraction.swift | 34 +++++ Sources/NBKSignedKit/NBKSigned+Text.swift | 72 ++++++++++ Sources/NBKSignedKit/NBKSigned.swift | 91 +++++++++++++ .../NBKFlexibleWidth+Addition.swift | 2 +- Tests/NBKSignedKitTests/Blank.swift | 1 - .../NBKSignedKitTests/NBKFlexibleWidth.swift | 49 +++++++ .../NBKSigned+Addition.swift | 126 ++++++++++++++++++ .../NBKSigned+Subtract.swift | 126 ++++++++++++++++++ Tests/NBKSignedKitTests/NBKSigned.swift | 61 +++++++++ 24 files changed, 1023 insertions(+), 147 deletions(-) delete mode 100644 .swiftpm/xcode/xcshareddata/xcschemes/NBKTwosComplementKit-Benchmarks.xcscheme delete mode 100644 .swiftpm/xcode/xcshareddata/xcschemes/NBKTwosComplementKit.xcscheme delete mode 100644 Sources/NBKSignedKit/Blank.swift create mode 100644 Sources/NBKSignedKit/NBKSigned+Addition+Digit.swift create mode 100644 Sources/NBKSignedKit/NBKSigned+Addition.swift create mode 100644 Sources/NBKSignedKit/NBKSigned+Comparisons.swift create mode 100644 Sources/NBKSignedKit/NBKSigned+Division+Digit.swift create mode 100644 Sources/NBKSignedKit/NBKSigned+Division.swift create mode 100644 Sources/NBKSignedKit/NBKSigned+Literals.swift create mode 100644 Sources/NBKSignedKit/NBKSigned+Multiplication+Digit.swift create mode 100644 Sources/NBKSignedKit/NBKSigned+Multiplication.swift create mode 100644 Sources/NBKSignedKit/NBKSigned+Negation.swift create mode 100644 Sources/NBKSignedKit/NBKSigned+Numbers.swift create mode 100644 Sources/NBKSignedKit/NBKSigned+Subtraction+Digit.swift create mode 100644 Sources/NBKSignedKit/NBKSigned+Subtraction.swift create mode 100644 Sources/NBKSignedKit/NBKSigned+Text.swift create mode 100644 Sources/NBKSignedKit/NBKSigned.swift delete mode 100644 Tests/NBKSignedKitTests/Blank.swift create mode 100644 Tests/NBKSignedKitTests/NBKFlexibleWidth.swift create mode 100644 Tests/NBKSignedKitTests/NBKSigned+Addition.swift create mode 100644 Tests/NBKSignedKitTests/NBKSigned+Subtract.swift create mode 100644 Tests/NBKSignedKitTests/NBKSigned.swift diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/NBKTwosComplementKit-Benchmarks.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/NBKTwosComplementKit-Benchmarks.xcscheme deleted file mode 100644 index dd6ad91a..00000000 --- a/.swiftpm/xcode/xcshareddata/xcschemes/NBKTwosComplementKit-Benchmarks.xcscheme +++ /dev/null @@ -1,71 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/NBKTwosComplementKit.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/NBKTwosComplementKit.xcscheme deleted file mode 100644 index 6e7e3288..00000000 --- a/.swiftpm/xcode/xcshareddata/xcschemes/NBKTwosComplementKit.xcscheme +++ /dev/null @@ -1,71 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Package.swift b/Package.swift index 04856a65..e1512b68 100644 --- a/Package.swift +++ b/Package.swift @@ -119,11 +119,11 @@ var package = Package( .testTarget( name: "NBKSignedKitBenchmarks", - dependencies: ["NBKSignedKit"]), + dependencies: ["NBKFlexibleWidthKit", "NBKSignedKit"]), .testTarget( name: "NBKSignedKitTests", - dependencies: ["NBKSignedKit"]), + dependencies: ["NBKFlexibleWidthKit", "NBKSignedKit"]), ] ) diff --git a/Sources/NBKSignedKit/Blank.swift b/Sources/NBKSignedKit/Blank.swift deleted file mode 100644 index 8b137891..00000000 --- a/Sources/NBKSignedKit/Blank.swift +++ /dev/null @@ -1 +0,0 @@ - diff --git a/Sources/NBKSignedKit/NBKSigned+Addition+Digit.swift b/Sources/NBKSignedKit/NBKSigned+Addition+Digit.swift new file mode 100644 index 00000000..3fe5f5a2 --- /dev/null +++ b/Sources/NBKSignedKit/NBKSigned+Addition+Digit.swift @@ -0,0 +1,34 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Signed x Addition x Digit +//*============================================================================* + +extension NBKSigned { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @_disfavoredOverload @inlinable public static func +=(lhs: inout Self, rhs: Digit) { + if lhs.sign == rhs.sign { + lhs.magnitude += rhs.magnitude + } else if lhs.magnitude.subtractReportingOverflow(rhs.magnitude) { + lhs.sign = rhs.sign + lhs.magnitude.formTwosComplement() + } + } + + @_disfavoredOverload @inlinable public static func +(lhs: Self, rhs: Digit) -> Self { + var lhs = lhs; lhs += rhs; return lhs + } +} diff --git a/Sources/NBKSignedKit/NBKSigned+Addition.swift b/Sources/NBKSignedKit/NBKSigned+Addition.swift new file mode 100644 index 00000000..3a07a3cf --- /dev/null +++ b/Sources/NBKSignedKit/NBKSigned+Addition.swift @@ -0,0 +1,34 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Signed x Addition +//*============================================================================* + +extension NBKSigned { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public static func +=(lhs: inout Self, rhs: Self) { + if lhs.sign == rhs.sign { + lhs.magnitude += rhs.magnitude + } else if lhs.magnitude.subtractReportingOverflow(rhs.magnitude) { + lhs.sign = rhs.sign + lhs.magnitude.formTwosComplement() + } + } + + @inlinable public static func +(lhs: Self, rhs: Self) -> Self { + var lhs = lhs; lhs += rhs; return lhs + } +} diff --git a/Sources/NBKSignedKit/NBKSigned+Comparisons.swift b/Sources/NBKSignedKit/NBKSigned+Comparisons.swift new file mode 100644 index 00000000..25162311 --- /dev/null +++ b/Sources/NBKSignedKit/NBKSigned+Comparisons.swift @@ -0,0 +1,88 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Signed x Comparisons +//*============================================================================* + +extension NBKSigned { + + //=------------------------------------------------------------------------= + // MARK: Accessors + //=------------------------------------------------------------------------= + + /// Returns `1` if this value is positive, `-1` if it is negative, and `0` otherwise. + @inlinable public func signum() -> Int { + self.isZero ? 0 : self.sign == Sign.plus ? 1 : -1 + } + + /// Returns whether this value is equal to zero. + @inlinable public var isZero: Bool { + self.magnitude.isZero + } + + /// Returns whether this value is less than zero. + @inlinable public var isLessThanZero: Bool { + self.sign != Sign.plus && !self.isZero + } + + /// Returns whether this value is more than zero. + @inlinable public var isMoreThanZero: Bool { + self.sign == Sign.plus && !self.isZero + } + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + @inlinable public func hash(into hasher: inout Hasher) { + hasher.combine(self.magnitude) + hasher.combine(self.normalizedSign) + } + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + @inlinable public static func ==(lhs: Self, rhs: Self) -> Bool { + if lhs.sign != rhs.sign { + return lhs.isZero && rhs.isZero + } else { + return lhs.magnitude == rhs.magnitude + } + } + + @inlinable public static func <(lhs: Self, rhs: Self) -> Bool { + if lhs.sign != rhs.sign { + return (lhs.sign != Sign.plus) && !(lhs.isZero && rhs.isZero) + } else { + return (lhs.sign == Sign.plus) ? lhs.magnitude < rhs.magnitude : rhs.magnitude < lhs.magnitude + } + } + + @inlinable public func compared(to other: Self) -> Int { + if self.sign != other.sign { + return self.isZero && other.isZero ? 0 : self.sign == Sign.plus ? 1 : -1 + } else { + let m = self.magnitude.compared(to: other.magnitude) + return self.sign == Sign.plus ? m : -m + } + } + + @inlinable public func compared(to other: Digit) -> Int { + if self.sign != other.sign { + return self.isZero && other.isZero ? 0 : self.sign == Sign.plus ? 1 : -1 + } else { + let m = self.magnitude.compared(to: other.magnitude) + return self.sign == Sign.plus ? m : -m + } + } +} diff --git a/Sources/NBKSignedKit/NBKSigned+Division+Digit.swift b/Sources/NBKSignedKit/NBKSigned+Division+Digit.swift new file mode 100644 index 00000000..9ee5660a --- /dev/null +++ b/Sources/NBKSignedKit/NBKSigned+Division+Digit.swift @@ -0,0 +1,42 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Signed x Division x Digit +//*============================================================================* + +extension NBKSigned { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @_disfavoredOverload @inlinable public static func /=(lhs: inout Self, rhs: Digit) { + lhs.sign ^= rhs.sign; lhs.magnitude /= rhs.magnitude + } + + @_disfavoredOverload @inlinable public static func /(lhs: Self, rhs: Digit) -> Self { + Self(sign: lhs.sign ^ rhs.sign, magnitude: lhs.magnitude / rhs.magnitude) + } + + @_disfavoredOverload @inlinable public static func %=(lhs: inout Self, rhs: Digit) { + lhs.magnitude %= rhs.magnitude + } + + @_disfavoredOverload @inlinable public static func %(lhs: Self, rhs: Digit) -> Digit { + Digit(sign: lhs.sign, magnitude: lhs.magnitude % rhs.magnitude) + } + + @_disfavoredOverload @inlinable public func quotientAndRemainder(dividingBy other: Digit) -> QR { + let x: QR = self.magnitude.quotientAndRemainder(dividingBy: other.magnitude) + return QR(Self(sign: self.sign ^ other.sign, magnitude: x.quotient), Digit(sign: self.sign, magnitude: x.remainder)) + } +} diff --git a/Sources/NBKSignedKit/NBKSigned+Division.swift b/Sources/NBKSignedKit/NBKSigned+Division.swift new file mode 100644 index 00000000..f60f2a01 --- /dev/null +++ b/Sources/NBKSignedKit/NBKSigned+Division.swift @@ -0,0 +1,42 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Signed x Division +//*============================================================================* + +extension NBKSigned { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public static func /=(lhs: inout Self, rhs: Self) { + lhs.sign ^= rhs.sign; lhs.magnitude /= rhs.magnitude + } + + @inlinable public static func /(lhs: Self, rhs: Self) -> Self { + Self(sign: lhs.sign ^ rhs.sign, magnitude: lhs.magnitude / rhs.magnitude) + } + + @inlinable public static func %=(lhs: inout Self, rhs: Self) { + lhs.magnitude %= rhs.magnitude + } + + @inlinable public static func %(lhs: Self, rhs: Self) -> Self { + Self(sign: lhs.sign, magnitude: lhs.magnitude % rhs.magnitude) + } + + @inlinable public func quotientAndRemainder(dividingBy other: Self) -> QR { + let x: QR = self.magnitude.quotientAndRemainder(dividingBy: other.magnitude) + return QR(Self(sign: self.sign ^ other.sign, magnitude: x.quotient), Self(sign: self.sign, magnitude: x.remainder)) + } +} diff --git a/Sources/NBKSignedKit/NBKSigned+Literals.swift b/Sources/NBKSignedKit/NBKSigned+Literals.swift new file mode 100644 index 00000000..78a17f69 --- /dev/null +++ b/Sources/NBKSignedKit/NBKSigned+Literals.swift @@ -0,0 +1,25 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Signed x Literals +//*============================================================================* + +extension NBKSigned { + + //=------------------------------------------------------------------------= + // MARK: Initializers x Integer Literal Type + //=------------------------------------------------------------------------= + + @inlinable public init(integerLiteral source: Int) { + self.init(source) + } +} diff --git a/Sources/NBKSignedKit/NBKSigned+Multiplication+Digit.swift b/Sources/NBKSignedKit/NBKSigned+Multiplication+Digit.swift new file mode 100644 index 00000000..3251fcbf --- /dev/null +++ b/Sources/NBKSignedKit/NBKSigned+Multiplication+Digit.swift @@ -0,0 +1,30 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Signed x Multiplication x Digit +//*============================================================================* + +extension NBKSigned { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @_disfavoredOverload @inlinable public static func *=(lhs: inout Self, rhs: Digit) { + lhs.sign = lhs.sign ^ rhs.sign + lhs.magnitude *= rhs.magnitude + } + + @_disfavoredOverload @inlinable public static func *(lhs: Self, rhs: Digit) -> Self { + Self(sign: lhs.sign ^ rhs.sign, magnitude: lhs.magnitude * rhs.magnitude) + } +} diff --git a/Sources/NBKSignedKit/NBKSigned+Multiplication.swift b/Sources/NBKSignedKit/NBKSigned+Multiplication.swift new file mode 100644 index 00000000..9d90c767 --- /dev/null +++ b/Sources/NBKSignedKit/NBKSigned+Multiplication.swift @@ -0,0 +1,30 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Signed x Multiplication +//*============================================================================* + +extension NBKSigned { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public static func *=(lhs: inout Self, rhs: Self) { + lhs.sign = lhs.sign ^ rhs.sign + lhs.magnitude *= rhs.magnitude + } + + @inlinable public static func *(lhs: Self, rhs: Self) -> Self { + Self(sign: lhs.sign ^ rhs.sign, magnitude: lhs.magnitude * rhs.magnitude) + } +} diff --git a/Sources/NBKSignedKit/NBKSigned+Negation.swift b/Sources/NBKSignedKit/NBKSigned+Negation.swift new file mode 100644 index 00000000..fac942ac --- /dev/null +++ b/Sources/NBKSignedKit/NBKSigned+Negation.swift @@ -0,0 +1,37 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Signed x Negation +//*============================================================================* + +extension NBKSigned { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public static prefix func -(x: Self) -> Self { + x.negated() + } + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public mutating func negate() { + self.sign.toggle() + } + + @inlinable public func negated() -> Self { + Self(sign: self.sign.toggled(), magnitude: self.magnitude) + } +} diff --git a/Sources/NBKSignedKit/NBKSigned+Numbers.swift b/Sources/NBKSignedKit/NBKSigned+Numbers.swift new file mode 100644 index 00000000..b05f7ec3 --- /dev/null +++ b/Sources/NBKSignedKit/NBKSigned+Numbers.swift @@ -0,0 +1,65 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Signed x Numbers +//*============================================================================* + +extension NBKSigned { + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + @inlinable public init(digit: Digit) { + let sign = digit.sign + let magnitude = Magnitude(digit: digit.magnitude) + self.init(sign: sign, magnitude: magnitude) + } + + //=------------------------------------------------------------------------= + // MARK: Initializers x Magnitude + //=------------------------------------------------------------------------= + + @inlinable public init(_ source: Magnitude) { + self.init(sign: Sign.plus, magnitude: source) + } + + @inlinable public init?(exactly source: Magnitude) { + self.init(sign: Sign.plus, magnitude: source) + } + + @inlinable public init(clamping source: Magnitude) { + self.init(sign: Sign.plus, magnitude: source) + } + + //=------------------------------------------------------------------------= + // MARK: Initializers x Binary Integer + //=------------------------------------------------------------------------= + + @inlinable public init(_ source: some BinaryInteger) { + if let value = Self(exactly: source) { self = value } else { + preconditionFailure("\(Self.self) cannot represent \(source)") + } + } + + @inlinable public init?(exactly source: T) { + let sign = Sign(source < T.zero) + guard let magnitude = Magnitude(exactly: source.magnitude) else { return nil } + self.init(sign: sign, magnitude: magnitude) + } + + @inlinable public init(clamping source: T) { + let sign = Sign(source < T.zero) + let magnitude = Magnitude(clamping: source.magnitude) + self.init(sign: sign, magnitude: magnitude) + } +} diff --git a/Sources/NBKSignedKit/NBKSigned+Subtraction+Digit.swift b/Sources/NBKSignedKit/NBKSigned+Subtraction+Digit.swift new file mode 100644 index 00000000..3e9eb837 --- /dev/null +++ b/Sources/NBKSignedKit/NBKSigned+Subtraction+Digit.swift @@ -0,0 +1,34 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Signed x Subtraction x Digit +//*============================================================================* + +extension NBKSigned { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @_disfavoredOverload @inlinable public static func -=(lhs: inout Self, rhs: Digit) { + if lhs.sign != rhs.sign { + lhs.magnitude += rhs.magnitude + } else if lhs.magnitude.subtractReportingOverflow(rhs.magnitude) { + lhs.sign.toggle() + lhs.magnitude.formTwosComplement() + } + } + + @_disfavoredOverload @inlinable public static func -(lhs: Self, rhs: Digit) -> Self { + var lhs = lhs; lhs -= rhs; return lhs + } +} diff --git a/Sources/NBKSignedKit/NBKSigned+Subtraction.swift b/Sources/NBKSignedKit/NBKSigned+Subtraction.swift new file mode 100644 index 00000000..8a8e3d26 --- /dev/null +++ b/Sources/NBKSignedKit/NBKSigned+Subtraction.swift @@ -0,0 +1,34 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Signed x Subtraction +//*============================================================================* + +extension NBKSigned { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public static func -=(lhs: inout Self, rhs: Self) { + if lhs.sign != rhs.sign { + lhs.magnitude += rhs.magnitude + } else if lhs.magnitude.subtractReportingOverflow(rhs.magnitude) { + lhs.sign.toggle() + lhs.magnitude.formTwosComplement() + } + } + + @inlinable public static func -(lhs: Self, rhs: Self) -> Self { + var lhs = lhs; lhs -= rhs; return lhs + } +} diff --git a/Sources/NBKSignedKit/NBKSigned+Text.swift b/Sources/NBKSignedKit/NBKSigned+Text.swift new file mode 100644 index 00000000..880ff525 --- /dev/null +++ b/Sources/NBKSignedKit/NBKSigned+Text.swift @@ -0,0 +1,72 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Signed x Text +//*============================================================================* + +extension NBKSigned { + + //=------------------------------------------------------------------------= + // MARK: Details x Decode + //=------------------------------------------------------------------------= + + @inlinable public init?(_ description: String) { + self.init(description, radix: 10) + } + + @inlinable public init?(_ description: some StringProtocol, radix: Int) { + let components = NBK.makeIntegerComponents(utf8: description.utf8) + let body = description[components.body.startIndex ..< components.body.endIndex] + guard let magnitude = Magnitude(body, radix: radix) else { return nil } + self.init(sign: components.sign, magnitude: magnitude) + } + + //=------------------------------------------------------------------------= + // MARK: Details x Encode + //=------------------------------------------------------------------------= + + @inlinable public var description: String { + self.description(radix: 10, uppercase: false) + } + + @inlinable public func description(radix: Int = 10, uppercase: Bool = false) -> String { + let minus = self.sign == Sign.minus + let digits = self.magnitude.description(radix: radix, uppercase: uppercase) + return minus ? "-" + digits : digits + } +} + +//=----------------------------------------------------------------------------= +// MARK: + String +//=----------------------------------------------------------------------------= + +extension String { + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + /// Creates a string representing the given value, in the given format. + /// + /// ``` + /// ┌──────────────┬───────┬─────────── → ────────────┐ + /// │ integer │ radix │ uppercase │ self │ + /// ├──────────────┼───────┼─────────── → ────────────┤ + /// │ Int256( 123) │ 12 │ true │ "A3" │ + /// │ Int256(-123) │ 16 │ false │ "-7b" │ + /// └──────────────┴───────┴─────────── → ────────────┘ + /// ``` + /// + @inlinable public init(_ value: NBKSigned, radix: Int = 10, uppercase: Bool = false) { + self = value.description(radix: radix, uppercase: uppercase) + } +} diff --git a/Sources/NBKSignedKit/NBKSigned.swift b/Sources/NBKSignedKit/NBKSigned.swift new file mode 100644 index 00000000..f2db1396 --- /dev/null +++ b/Sources/NBKSignedKit/NBKSigned.swift @@ -0,0 +1,91 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Signed +//*============================================================================* + +@frozen public struct NBKSigned: Comparable, +CustomStringConvertible, ExpressibleByIntegerLiteral, Hashable, Sendable, SignedNumeric { + + public typealias Sign = FloatingPointSign + + public typealias Digit = NBKSigned + + //=------------------------------------------------------------------------= + // MARK: Accessors + //=------------------------------------------------------------------------= + + /// The positive zero value. + /// + /// Positive and negative zero are equal and have the same `hashValue`. + /// + @inlinable public static var zero: Self { + Self() + } + + //=------------------------------------------------------------------------= + // MARK: State + //=------------------------------------------------------------------------= + + /// The sign of this value. + public var sign: Sign + + /// The magnitude of this value. + public var magnitude: Magnitude + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + /// Creates a new instance with a positive zero value. + @inlinable public init() { + self.init(sign: Sign.plus, magnitude: Magnitude.zero) + } + + /// Creates a new instance with the given sign and magnitude. + @inlinable public init(sign: Sign, magnitude: Magnitude) { + self.sign = sign; self.magnitude = magnitude + } + + //=------------------------------------------------------------------------= + // MARK: Details x Normalization + //=------------------------------------------------------------------------= + + /// Returns `true` for all values, except negative zero where it returns `false`. + @inlinable public var isNormal: Bool { + self.sign == Sign.plus || !self.isZero + } + + /// Returns the sign when for all values, except negative zero where it returns `plus`. + @inlinable public var normalizedSign: Sign { + self.isNormal ? self.sign : Sign.plus + } +} + +//*============================================================================* +// MARK: * NBK x Signed x Aliases +//*============================================================================* + +/// A signed integer with a pointer-bit magnitude. +public typealias SInt = NBKSigned + +/// A signed integer with an 8-bit magnitude. +public typealias SInt8 = NBKSigned + +/// A signed integer with a 16-bit magnitude. +public typealias SInt16 = NBKSigned + +/// A signed integer with a 32-bit magnitude. +public typealias SInt32 = NBKSigned + +/// A signed integer with a 64-bit magnitude. +public typealias SInt64 = NBKSigned diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Addition.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Addition.swift index 2f1c5c58..ad4850c7 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Addition.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Addition.swift @@ -10,7 +10,7 @@ #if DEBUG import NBKCoreKit -@testable import NBKFlexibleWidthKit +import NBKFlexibleWidthKit import XCTest private typealias W = [UInt] diff --git a/Tests/NBKSignedKitTests/Blank.swift b/Tests/NBKSignedKitTests/Blank.swift deleted file mode 100644 index 8b137891..00000000 --- a/Tests/NBKSignedKitTests/Blank.swift +++ /dev/null @@ -1 +0,0 @@ - diff --git a/Tests/NBKSignedKitTests/NBKFlexibleWidth.swift b/Tests/NBKSignedKitTests/NBKFlexibleWidth.swift new file mode 100644 index 00000000..1d90cdf2 --- /dev/null +++ b/Tests/NBKSignedKitTests/NBKFlexibleWidth.swift @@ -0,0 +1,49 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit +import NBKFlexibleWidthKit +import NBKSignedKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Flexible Width x Signed +//*============================================================================* + +public typealias SIntXL = NBKSigned + +//*============================================================================* +// MARK: * NBK x Flexible Width x UIntXL +//*============================================================================* + +extension UIntXL { + + //=------------------------------------------------------------------------= + // MARK: Details x Numbers + //=------------------------------------------------------------------------= + + static let min256 = Self(x64:[ 0, 0, 0, 0] as X) + static let max256 = Self(x64:[~0, ~0, ~0, ~0] as X) + + //=------------------------------------------------------------------------= + // MARK: Details x Limbs + //=------------------------------------------------------------------------= + + init(x32: [UInt32]) { + self.init(words: NBKChunkedInt(x32)) + } + + init(x64: [UInt64]) { + self.init(words: NBKChunkedInt(x64)) + } +} diff --git a/Tests/NBKSignedKitTests/NBKSigned+Addition.swift b/Tests/NBKSignedKitTests/NBKSigned+Addition.swift new file mode 100644 index 00000000..665d82c8 --- /dev/null +++ b/Tests/NBKSignedKitTests/NBKSigned+Addition.swift @@ -0,0 +1,126 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +import NBKFlexibleWidthKit +import NBKSignedKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Signed x Addition x SIntXL +//*============================================================================* + +final class NBKSignedTestsOnAdditionAsSIntXL: XCTestCase { + + typealias T = NBKSigned + typealias M = NBKSigned.Magnitude + typealias D = NBKSigned.Digit + typealias U = NBKSigned.Digit.Magnitude + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testAdding() { + NBKAssertAddition( T(M(x64:[~0, ~0, ~0, 0] as X)), T(M(x64:[3, 0, 0, 0] as X)), T(M(x64:[ 2, 0, 0, 1] as X))) + NBKAssertAddition( T(M(x64:[~0, ~0, ~0, 0] as X)), T(M(x64:[0, 3, 0, 0] as X)), T(M(x64:[~0, 2, 0, 1] as X))) + NBKAssertAddition( T(M(x64:[~0, ~0, ~0, 0] as X)), T(M(x64:[0, 0, 3, 0] as X)), T(M(x64:[~0, ~0, 2, 1] as X))) + NBKAssertAddition( T(M(x64:[~0, ~0, ~0, 0] as X)), T(M(x64:[0, 0, 0, 3] as X)), T(M(x64:[~0, ~0, ~0, 3] as X))) + + NBKAssertAddition( T(M(x64:[~0, ~0, ~0, 0] as X)), -T(M(x64:[3, 0, 0, 0] as X)), T(M(x64:[~3, ~0, ~0, 0] as X))) + NBKAssertAddition( T(M(x64:[~0, ~0, ~0, 0] as X)), -T(M(x64:[0, 3, 0, 0] as X)), T(M(x64:[~0, ~3, ~0, 0] as X))) + NBKAssertAddition( T(M(x64:[~0, ~0, ~0, 0] as X)), -T(M(x64:[0, 0, 3, 0] as X)), T(M(x64:[~0, ~0, ~3, 0] as X))) + NBKAssertAddition( T(M(x64:[~0, ~0, ~0, 0] as X)), -T(M(x64:[0, 0, 0, 3] as X)), -T(M(x64:[ 1, 0, 0, 2] as X))) + + NBKAssertAddition(-T(M(x64:[~0, ~0, ~0, 0] as X)), T(M(x64:[3, 0, 0, 0] as X)), -T(M(x64:[~3, ~0, ~0, 0] as X))) + NBKAssertAddition(-T(M(x64:[~0, ~0, ~0, 0] as X)), T(M(x64:[0, 3, 0, 0] as X)), -T(M(x64:[~0, ~3, ~0, 0] as X))) + NBKAssertAddition(-T(M(x64:[~0, ~0, ~0, 0] as X)), T(M(x64:[0, 0, 3, 0] as X)), -T(M(x64:[~0, ~0, ~3, 0] as X))) + NBKAssertAddition(-T(M(x64:[~0, ~0, ~0, 0] as X)), T(M(x64:[0, 0, 0, 3] as X)), T(M(x64:[ 1, 0, 0, 2] as X))) + + NBKAssertAddition(-T(M(x64:[~0, ~0, ~0, 0] as X)), -T(M(x64:[3, 0, 0, 0] as X)), -T(M(x64:[ 2, 0, 0, 1] as X))) + NBKAssertAddition(-T(M(x64:[~0, ~0, ~0, 0] as X)), -T(M(x64:[0, 3, 0, 0] as X)), -T(M(x64:[~0, 2, 0, 1] as X))) + NBKAssertAddition(-T(M(x64:[~0, ~0, ~0, 0] as X)), -T(M(x64:[0, 0, 3, 0] as X)), -T(M(x64:[~0, ~0, 2, 1] as X))) + NBKAssertAddition(-T(M(x64:[~0, ~0, ~0, 0] as X)), -T(M(x64:[0, 0, 0, 3] as X)), -T(M(x64:[~0, ~0, ~0, 3] as X))) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Digit + //=------------------------------------------------------------------------= + + func testAddingDigit() { + NBKAssertAdditionByDigit( T(M(1)), D(U(2)), T(M(3))) + NBKAssertAdditionByDigit( T(M(1)), D(U(1)), T(M(2))) + NBKAssertAdditionByDigit( T(M(1)), D(U(0)), T(M(1))) + NBKAssertAdditionByDigit( T(M(1)), -D(U(0)), T(M(1))) + NBKAssertAdditionByDigit( T(M(1)), -D(U(1)), T(M(0))) + NBKAssertAdditionByDigit( T(M(1)), -D(U(2)), -T(M(1))) + + NBKAssertAdditionByDigit( T(M(0)), D(U(2)), T(M(2))) + NBKAssertAdditionByDigit( T(M(0)), D(U(1)), T(M(1))) + NBKAssertAdditionByDigit( T(M(0)), D(U(0)), T(M(0))) + NBKAssertAdditionByDigit( T(M(0)), -D(U(0)), T(M(0))) + NBKAssertAdditionByDigit( T(M(0)), -D(U(1)), -T(M(1))) + NBKAssertAdditionByDigit( T(M(0)), -D(U(2)), -T(M(2))) + + NBKAssertAdditionByDigit(-T(M(0)), D(U(2)), T(M(2))) + NBKAssertAdditionByDigit(-T(M(0)), D(U(1)), T(M(1))) + NBKAssertAdditionByDigit(-T(M(0)), D(U(0)), -T(M(0))) + NBKAssertAdditionByDigit(-T(M(0)), -D(U(0)), -T(M(0))) + NBKAssertAdditionByDigit(-T(M(0)), -D(U(1)), -T(M(1))) + NBKAssertAdditionByDigit(-T(M(0)), -D(U(2)), -T(M(2))) + + NBKAssertAdditionByDigit(-T(M(1)), D(U(2)), T(M(1))) + NBKAssertAdditionByDigit(-T(M(1)), D(U(1)), -T(M(0))) + NBKAssertAdditionByDigit(-T(M(1)), D(U(0)), -T(M(1))) + NBKAssertAdditionByDigit(-T(M(1)), -D(U(0)), -T(M(1))) + NBKAssertAdditionByDigit(-T(M(1)), -D(U(1)), -T(M(2))) + NBKAssertAdditionByDigit(-T(M(1)), -D(U(2)), -T(M(3))) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Miscellaneous + //=------------------------------------------------------------------------= + + func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { + func becauseThisCompilesSuccessfully(_ x: inout T) { + XCTAssertNotNil(x += 0) + XCTAssertNotNil(x + 0) + } + } +} + +//*============================================================================* +// MARK: * NBK x Signed x Addition x Assertions +//*============================================================================* + +private func NBKAssertAddition( +_ lhs: NBKSigned, _ rhs: NBKSigned, _ partialValue: NBKSigned, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + NBKAssertIdentical( lhs + rhs, partialValue, file: file, line: line) + NBKAssertIdentical({ var lhs = lhs; lhs += rhs; return lhs }(), partialValue, file: file, line: line) +} + +private func NBKAssertAdditionByDigit( +_ lhs: NBKSigned, _ rhs: NBKSigned.Digit, _ partialValue: NBKSigned, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + NBKAssertIdentical( lhs + rhs, partialValue, file: file, line: line) + NBKAssertIdentical({ var lhs = lhs; lhs += rhs; return lhs }(), partialValue, file: file, line: line) + //=------------------------------------------= + NBKAssertAddition(lhs, NBKSigned(digit: rhs), partialValue) +} + +#endif diff --git a/Tests/NBKSignedKitTests/NBKSigned+Subtract.swift b/Tests/NBKSignedKitTests/NBKSigned+Subtract.swift new file mode 100644 index 00000000..ad24326d --- /dev/null +++ b/Tests/NBKSignedKitTests/NBKSigned+Subtract.swift @@ -0,0 +1,126 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +import NBKFlexibleWidthKit +import NBKSignedKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Signed x Subtraction x SIntXL +//*============================================================================* + +final class NBKSignedTestsOnSubtractionAsSIntXL: XCTestCase { + + typealias T = NBKSigned + typealias M = NBKSigned.Magnitude + typealias D = NBKSigned.Digit + typealias U = NBKSigned.Digit.Magnitude + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testSubtracting() { + NBKAssertSubtraction( T(M(x64:[~0, ~0, ~0, 0] as X)), T(M(x64:[3, 0, 0, 0] as X)), T(M(x64:[~3, ~0, ~0, 0] as X))) + NBKAssertSubtraction( T(M(x64:[~0, ~0, ~0, 0] as X)), T(M(x64:[0, 3, 0, 0] as X)), T(M(x64:[~0, ~3, ~0, 0] as X))) + NBKAssertSubtraction( T(M(x64:[~0, ~0, ~0, 0] as X)), T(M(x64:[0, 0, 3, 0] as X)), T(M(x64:[~0, ~0, ~3, 0] as X))) + NBKAssertSubtraction( T(M(x64:[~0, ~0, ~0, 0] as X)), T(M(x64:[0, 0, 0, 3] as X)), -T(M(x64:[ 1, 0, 0, 2] as X))) + + NBKAssertSubtraction( T(M(x64:[~0, ~0, ~0, 0] as X)), -T(M(x64:[3, 0, 0, 0] as X)), T(M(x64:[ 2, 0, 0, 1] as X))) + NBKAssertSubtraction( T(M(x64:[~0, ~0, ~0, 0] as X)), -T(M(x64:[0, 3, 0, 0] as X)), T(M(x64:[~0, 2, 0, 1] as X))) + NBKAssertSubtraction( T(M(x64:[~0, ~0, ~0, 0] as X)), -T(M(x64:[0, 0, 3, 0] as X)), T(M(x64:[~0, ~0, 2, 1] as X))) + NBKAssertSubtraction( T(M(x64:[~0, ~0, ~0, 0] as X)), -T(M(x64:[0, 0, 0, 3] as X)), T(M(x64:[~0, ~0, ~0, 3] as X))) + + NBKAssertSubtraction(-T(M(x64:[~0, ~0, ~0, 0] as X)), T(M(x64:[3, 0, 0, 0] as X)), -T(M(x64:[ 2, 0, 0, 1] as X))) + NBKAssertSubtraction(-T(M(x64:[~0, ~0, ~0, 0] as X)), T(M(x64:[0, 3, 0, 0] as X)), -T(M(x64:[~0, 2, 0, 1] as X))) + NBKAssertSubtraction(-T(M(x64:[~0, ~0, ~0, 0] as X)), T(M(x64:[0, 0, 3, 0] as X)), -T(M(x64:[~0, ~0, 2, 1] as X))) + NBKAssertSubtraction(-T(M(x64:[~0, ~0, ~0, 0] as X)), T(M(x64:[0, 0, 0, 3] as X)), -T(M(x64:[~0, ~0, ~0, 3] as X))) + + NBKAssertSubtraction(-T(M(x64:[~0, ~0, ~0, 0] as X)), -T(M(x64:[3, 0, 0, 0] as X)), -T(M(x64:[~3, ~0, ~0, 0] as X))) + NBKAssertSubtraction(-T(M(x64:[~0, ~0, ~0, 0] as X)), -T(M(x64:[0, 3, 0, 0] as X)), -T(M(x64:[~0, ~3, ~0, 0] as X))) + NBKAssertSubtraction(-T(M(x64:[~0, ~0, ~0, 0] as X)), -T(M(x64:[0, 0, 3, 0] as X)), -T(M(x64:[~0, ~0, ~3, 0] as X))) + NBKAssertSubtraction(-T(M(x64:[~0, ~0, ~0, 0] as X)), -T(M(x64:[0, 0, 0, 3] as X)), T(M(x64:[ 1, 0, 0, 2] as X))) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Digit + //=------------------------------------------------------------------------= + + func testSubtractingDigit() { + NBKAssertSubtractionByDigit( T(M(1)), D(U(2)), -T(M(1))) + NBKAssertSubtractionByDigit( T(M(1)), D(U(1)), T(M(0))) + NBKAssertSubtractionByDigit( T(M(1)), D(U(0)), T(M(1))) + NBKAssertSubtractionByDigit( T(M(1)), -D(U(0)), T(M(1))) + NBKAssertSubtractionByDigit( T(M(1)), -D(U(1)), T(M(2))) + NBKAssertSubtractionByDigit( T(M(1)), -D(U(2)), T(M(3))) + + NBKAssertSubtractionByDigit( T(M(0)), D(U(2)), -T(M(2))) + NBKAssertSubtractionByDigit( T(M(0)), D(U(1)), -T(M(1))) + NBKAssertSubtractionByDigit( T(M(0)), D(U(0)), T(M(0))) + NBKAssertSubtractionByDigit( T(M(0)), -D(U(0)), T(M(0))) + NBKAssertSubtractionByDigit( T(M(0)), -D(U(1)), T(M(1))) + NBKAssertSubtractionByDigit( T(M(0)), -D(U(2)), T(M(2))) + + NBKAssertSubtractionByDigit(-T(M(0)), D(U(2)), -T(M(2))) + NBKAssertSubtractionByDigit(-T(M(0)), D(U(1)), -T(M(1))) + NBKAssertSubtractionByDigit(-T(M(0)), D(U(0)), -T(M(0))) + NBKAssertSubtractionByDigit(-T(M(0)), -D(U(0)), -T(M(0))) + NBKAssertSubtractionByDigit(-T(M(0)), -D(U(1)), T(M(1))) + NBKAssertSubtractionByDigit(-T(M(0)), -D(U(2)), T(M(2))) + + NBKAssertSubtractionByDigit(-T(M(1)), D(U(2)), -T(M(3))) + NBKAssertSubtractionByDigit(-T(M(1)), D(U(1)), -T(M(2))) + NBKAssertSubtractionByDigit(-T(M(1)), D(U(0)), -T(M(1))) + NBKAssertSubtractionByDigit(-T(M(1)), -D(U(0)), -T(M(1))) + NBKAssertSubtractionByDigit(-T(M(1)), -D(U(1)), -T(M(0))) + NBKAssertSubtractionByDigit(-T(M(1)), -D(U(2)), T(M(1))) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Miscellaneous + //=------------------------------------------------------------------------= + + func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { + func becauseThisCompilesSuccessfully(_ x: inout T) { + XCTAssertNotNil(x -= 0) + XCTAssertNotNil(x - 0) + } + } +} + +//*============================================================================* +// MARK: * NBK x Signed x Subtraction x Assertions +//*============================================================================* + +private func NBKAssertSubtraction( +_ lhs: NBKSigned, _ rhs: NBKSigned, _ partialValue: NBKSigned, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + NBKAssertIdentical( lhs - rhs, partialValue, file: file, line: line) + NBKAssertIdentical({ var lhs = lhs; lhs -= rhs; return lhs }(), partialValue, file: file, line: line) +} + +private func NBKAssertSubtractionByDigit( +_ lhs: NBKSigned, _ rhs: NBKSigned.Digit, _ partialValue: NBKSigned, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + NBKAssertIdentical( lhs - rhs, partialValue, file: file, line: line) + NBKAssertIdentical({ var lhs = lhs; lhs -= rhs; return lhs }(), partialValue, file: file, line: line) + //=------------------------------------------= + NBKAssertSubtraction(lhs, NBKSigned(digit: rhs), partialValue) +} + +#endif diff --git a/Tests/NBKSignedKitTests/NBKSigned.swift b/Tests/NBKSignedKitTests/NBKSigned.swift new file mode 100644 index 00000000..43a01323 --- /dev/null +++ b/Tests/NBKSignedKitTests/NBKSigned.swift @@ -0,0 +1,61 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +import NBKSignedKit +import XCTest + +//*============================================================================* +// MARK: * NBK x Signed +//*============================================================================* + +final class NBKSignedTests: XCTestCase { + + typealias T = NBKSigned + typealias M = NBKSigned.Magnitude + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testSign() { + XCTAssertEqual(T(sign: .plus , magnitude: 0).sign, .plus ) + XCTAssertEqual(T(sign: .plus , magnitude: 1).sign, .plus ) + XCTAssertEqual(T(sign: .minus, magnitude: 0).sign, .minus) + XCTAssertEqual(T(sign: .minus, magnitude: 1).sign, .minus) + } + + func testIsNormal() { + XCTAssertEqual(T(sign: .plus , magnitude: 0).isNormal, true ) + XCTAssertEqual(T(sign: .plus , magnitude: 1).isNormal, true ) + XCTAssertEqual(T(sign: .minus, magnitude: 0).isNormal, false) + XCTAssertEqual(T(sign: .minus, magnitude: 1).isNormal, true ) + } + + func testNormalizedSign() { + XCTAssertEqual(T(sign: .plus , magnitude: 0).normalizedSign, .plus ) + XCTAssertEqual(T(sign: .plus , magnitude: 1).normalizedSign, .plus ) + XCTAssertEqual(T(sign: .minus, magnitude: 0).normalizedSign, .plus ) + XCTAssertEqual(T(sign: .minus, magnitude: 1).normalizedSign, .minus) + } +} + +//*============================================================================* +// MARK: * NBK x Signed x Assertions +//*============================================================================* + +func NBKAssertIdentical(_ lhs: NBKSigned?, _ rhs: NBKSigned?, file: StaticString = #file, line: UInt = #line) { + let success: Bool = lhs?.sign == rhs?.sign && lhs?.magnitude == rhs?.magnitude + func description(of x: NBKSigned?) -> String { x.map({ "\($0.sign)\($0.magnitude)" }) ?? "nil" } + XCTAssert(success, "(\(description(of: lhs)) is not identical to \(description(of: rhs))", file: file, line: line) +} + +#endif From 759f2e532f1b651842d0010ea9f3e2fcd8c7a4a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Fri, 15 Sep 2023 14:02:52 +0200 Subject: [PATCH 071/133] [NBKSignedKit] Tests (#81). --- .../NBKSignedKit/NBKSigned+Comparisons.swift | 17 +- .../NBKFlexibleWidth+Division.swift | 2 - .../NBKSigned+Addition.swift | 12 +- .../NBKSigned+Comparisons.swift | 173 ++++++++++++++++++ .../NBKSigned+Division.swift | 140 ++++++++++++++ .../NBKSigned+Multiplication.swift | 98 ++++++++++ .../NBKSigned+Subtract.swift | 10 +- 7 files changed, 433 insertions(+), 19 deletions(-) create mode 100644 Tests/NBKSignedKitTests/NBKSigned+Comparisons.swift create mode 100644 Tests/NBKSignedKitTests/NBKSigned+Division.swift create mode 100644 Tests/NBKSignedKitTests/NBKSigned+Multiplication.swift diff --git a/Sources/NBKSignedKit/NBKSigned+Comparisons.swift b/Sources/NBKSignedKit/NBKSigned+Comparisons.swift index 25162311..7d1b5bd4 100644 --- a/Sources/NBKSignedKit/NBKSigned+Comparisons.swift +++ b/Sources/NBKSignedKit/NBKSigned+Comparisons.swift @@ -19,11 +19,6 @@ extension NBKSigned { // MARK: Accessors //=------------------------------------------------------------------------= - /// Returns `1` if this value is positive, `-1` if it is negative, and `0` otherwise. - @inlinable public func signum() -> Int { - self.isZero ? 0 : self.sign == Sign.plus ? 1 : -1 - } - /// Returns whether this value is equal to zero. @inlinable public var isZero: Bool { self.magnitude.isZero @@ -39,6 +34,16 @@ extension NBKSigned { self.sign == Sign.plus && !self.isZero } + /// Returns whether this value is a power of two. + @inlinable public var isPowerOf2: Bool { + self.sign == Sign.plus && self.magnitude.isPowerOf2 + } + + /// Returns `1` if this value is positive, `-1` if it is negative, and `0` otherwise. + @inlinable public func signum() -> Int { + self.isZero ? 0 : self.sign == Sign.plus ? 1 : -1 + } + //=------------------------------------------------------------------------= // MARK: Utilities //=------------------------------------------------------------------------= @@ -77,7 +82,7 @@ extension NBKSigned { } } - @inlinable public func compared(to other: Digit) -> Int { + @_disfavoredOverload @inlinable public func compared(to other: Digit) -> Int { if self.sign != other.sign { return self.isZero && other.isZero ? 0 : self.sign == Sign.plus ? 1 : -1 } else { diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Division.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Division.swift index 84645c5f..e378a2f4 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Division.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Division.swift @@ -68,7 +68,6 @@ final class NBKFlexibleWidthTestsOnDivisionAsIntXL: XCTestCase { NBKAssertDivision(T(words:[1, 2, 3, 4 + 1 << 63] as W), T(words:[ 2, 3, 4, 5 &+ 1 << 63] as W), T(1), -T(words:[1, 1, 1, 1] as W)) NBKAssertDivision(T(words:[1, 2, 3, 4 + 1 << 63] as W), T(words:[ 3, 4, 5, 6 &+ 1 << 63] as W), T(1), -T(words:[2, 2, 2, 2] as W)) NBKAssertDivision(T(words:[1, 2, 3, 4 + 1 << 63] as W), T(words:[ 4, 5, 6, 7 &+ 1 << 63] as W), T(1), -T(words:[3, 3, 3, 3] as W)) - NBKAssertDivision(T(words:[1, 2, 3, 4 + 1 << 63] as W), T(words:[~0, ~2, ~3, ~4 &+ 1 << 63] as W), -T(1), -T(words:[0, 0, 0, 0] as W)) NBKAssertDivision(T(words:[1, 2, 3, 4 + 1 << 63] as W), T(words:[~1, ~3, ~4, ~5 &+ 1 << 63] as W), -T(1), -T(words:[1, 1, 1, 1] as W)) NBKAssertDivision(T(words:[1, 2, 3, 4 + 1 << 63] as W), T(words:[~2, ~4, ~5, ~6 &+ 1 << 63] as W), -T(1), -T(words:[2, 2, 2, 2] as W)) @@ -190,7 +189,6 @@ final class NBKFlexibleWidthTestsOnDivisionAsUIntXL: XCTestCase { NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X), T(x64:[ 0, 1, 2, 3 &+ 1 << 63] as X), T(1), T(x64:[1, 1, 1, 1] as X)) NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X), T(x64:[~0, ~0, 0, 2 &+ 1 << 63] as X), T(1), T(x64:[2, 2, 2, 2] as X)) NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X), T(x64:[~1, ~1, ~0, 0 &+ 1 << 63] as X), T(1), T(x64:[3, 3, 3, 3] as X)) - NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X), T(x64:[~2, ~2, ~1, ~0 &+ 1 << 63] as X), T(1), T(x64:[4, 4, 4, 4] as X)) NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X), T(x64:[~3, ~3, ~2, ~1 &+ 1 << 63] as X), T(1), T(x64:[5, 5, 5, 5] as X)) NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X), T(x64:[~4, ~4, ~3, ~2 &+ 1 << 63] as X), T(1), T(x64:[6, 6, 6, 6] as X)) diff --git a/Tests/NBKSignedKitTests/NBKSigned+Addition.swift b/Tests/NBKSignedKitTests/NBKSigned+Addition.swift index 665d82c8..dcff0959 100644 --- a/Tests/NBKSignedKitTests/NBKSigned+Addition.swift +++ b/Tests/NBKSignedKitTests/NBKSigned+Addition.swift @@ -33,12 +33,12 @@ final class NBKSignedTestsOnAdditionAsSIntXL: XCTestCase { // MARK: Tests //=------------------------------------------------------------------------= - func testAdding() { + func testAddingLargeToLarge() { NBKAssertAddition( T(M(x64:[~0, ~0, ~0, 0] as X)), T(M(x64:[3, 0, 0, 0] as X)), T(M(x64:[ 2, 0, 0, 1] as X))) NBKAssertAddition( T(M(x64:[~0, ~0, ~0, 0] as X)), T(M(x64:[0, 3, 0, 0] as X)), T(M(x64:[~0, 2, 0, 1] as X))) NBKAssertAddition( T(M(x64:[~0, ~0, ~0, 0] as X)), T(M(x64:[0, 0, 3, 0] as X)), T(M(x64:[~0, ~0, 2, 1] as X))) NBKAssertAddition( T(M(x64:[~0, ~0, ~0, 0] as X)), T(M(x64:[0, 0, 0, 3] as X)), T(M(x64:[~0, ~0, ~0, 3] as X))) - + NBKAssertAddition( T(M(x64:[~0, ~0, ~0, 0] as X)), -T(M(x64:[3, 0, 0, 0] as X)), T(M(x64:[~3, ~0, ~0, 0] as X))) NBKAssertAddition( T(M(x64:[~0, ~0, ~0, 0] as X)), -T(M(x64:[0, 3, 0, 0] as X)), T(M(x64:[~0, ~3, ~0, 0] as X))) NBKAssertAddition( T(M(x64:[~0, ~0, ~0, 0] as X)), -T(M(x64:[0, 0, 3, 0] as X)), T(M(x64:[~0, ~0, ~3, 0] as X))) @@ -56,10 +56,10 @@ final class NBKSignedTestsOnAdditionAsSIntXL: XCTestCase { } //=------------------------------------------------------------------------= - // MARK: Tests x Digit + // MARK: Tests x Digit (and Self) //=------------------------------------------------------------------------= - func testAddingDigit() { + func testAddingSmallToSmall() { NBKAssertAdditionByDigit( T(M(1)), D(U(2)), T(M(3))) NBKAssertAdditionByDigit( T(M(1)), D(U(1)), T(M(2))) NBKAssertAdditionByDigit( T(M(1)), D(U(0)), T(M(1))) @@ -116,11 +116,11 @@ file: StaticString = #file, line: UInt = #line) { private func NBKAssertAdditionByDigit( _ lhs: NBKSigned, _ rhs: NBKSigned.Digit, _ partialValue: NBKSigned, file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + NBKAssertAddition(lhs, NBKSigned(digit: rhs), partialValue) //=------------------------------------------= NBKAssertIdentical( lhs + rhs, partialValue, file: file, line: line) NBKAssertIdentical({ var lhs = lhs; lhs += rhs; return lhs }(), partialValue, file: file, line: line) - //=------------------------------------------= - NBKAssertAddition(lhs, NBKSigned(digit: rhs), partialValue) } #endif diff --git a/Tests/NBKSignedKitTests/NBKSigned+Comparisons.swift b/Tests/NBKSignedKitTests/NBKSigned+Comparisons.swift new file mode 100644 index 00000000..0590c2d5 --- /dev/null +++ b/Tests/NBKSignedKitTests/NBKSigned+Comparisons.swift @@ -0,0 +1,173 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +import NBKFlexibleWidthKit +import NBKSignedKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Signed x Comparisons +//*============================================================================* + +final class NBKSignedTestsOnComparisonsAsSIntXL: XCTestCase { + + typealias T = NBKSigned + typealias M = NBKSigned.Magnitude + typealias D = NBKSigned.Digit + typealias U = NBKSigned.Digit.Magnitude + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testIsZero() { + XCTAssertTrue (( T(0)).isZero) + XCTAssertTrue ((-T(0)).isZero) + XCTAssertFalse(( T(1)).isZero) + XCTAssertFalse((-T(1)).isZero) + } + + func testIsLessThanZero() { + XCTAssertFalse(( T(0)).isLessThanZero) + XCTAssertFalse((-T(0)).isLessThanZero) + XCTAssertFalse(( T(1)).isLessThanZero) + XCTAssertTrue ((-T(1)).isLessThanZero) + } + + func testIsMoreThanZero() { + XCTAssertFalse(( T(0)).isMoreThanZero) + XCTAssertFalse((-T(0)).isMoreThanZero) + XCTAssertTrue (( T(1)).isMoreThanZero) + XCTAssertFalse((-T(1)).isMoreThanZero) + } + + func testSignum() { + NBKAssertSignum(( T(0)), Int( 0)) + NBKAssertSignum((-T(0)), Int( 0)) + NBKAssertSignum(( T(1)), Int( 1)) + NBKAssertSignum((-T(1)), Int(-1)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testHashing() { + var union = Set() + union.insert( T(0)) + union.insert( T(0)) + union.insert(-T(0)) + union.insert(-T(0)) + union.insert( T(1)) + union.insert( T(1)) + union.insert(-T(1)) + union.insert(-T(1)) + XCTAssertEqual(union.count, 3) + } + + func testComparingLargeWithLarge() { + NBKAssertComparisons(T(M(words:[0, 2, 3, 4] as W)), T(M(words:[1, 2, 3, 4] as W)), -Int(1)) + NBKAssertComparisons(T(M(words:[1, 0, 3, 4] as W)), T(M(words:[1, 2, 3, 4] as W)), -Int(1)) + NBKAssertComparisons(T(M(words:[1, 2, 0, 4] as W)), T(M(words:[1, 2, 3, 4] as W)), -Int(1)) + NBKAssertComparisons(T(M(words:[1, 2, 3, 0] as W)), T(M(words:[1, 2, 3, 4] as W)), -Int(1)) + NBKAssertComparisons(T(M(words:[0, 2, 3, 4] as W)), T(M(words:[0, 2, 3, 4] as W)), Int(0)) + NBKAssertComparisons(T(M(words:[1, 0, 3, 4] as W)), T(M(words:[1, 0, 3, 4] as W)), Int(0)) + NBKAssertComparisons(T(M(words:[1, 2, 0, 4] as W)), T(M(words:[1, 2, 0, 4] as W)), Int(0)) + NBKAssertComparisons(T(M(words:[1, 2, 3, 0] as W)), T(M(words:[1, 2, 3, 0] as W)), Int(0)) + NBKAssertComparisons(T(M(words:[1, 2, 3, 4] as W)), T(M(words:[0, 2, 3, 4] as W)), Int(1)) + NBKAssertComparisons(T(M(words:[1, 2, 3, 4] as W)), T(M(words:[1, 0, 3, 4] as W)), Int(1)) + NBKAssertComparisons(T(M(words:[1, 2, 3, 4] as W)), T(M(words:[1, 2, 0, 4] as W)), Int(1)) + NBKAssertComparisons(T(M(words:[1, 2, 3, 4] as W)), T(M(words:[1, 2, 3, 0] as W)), Int(1)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Digit (and Self) + //=------------------------------------------------------------------------= + + func testComparingSmallWithSmall() { + NBKAssertComparisonsByDigit( T(0), D(0), Int(0)) + NBKAssertComparisonsByDigit( T(0), -D(0), Int(0)) + NBKAssertComparisonsByDigit(-T(0), D(0), Int(0)) + NBKAssertComparisonsByDigit(-T(0), -D(0), Int(0)) + + NBKAssertComparisonsByDigit( T(1), D(1), Int(0)) + NBKAssertComparisonsByDigit( T(1), -D(1), Int(1)) + NBKAssertComparisonsByDigit(-T(1), D(1), -Int(1)) + NBKAssertComparisonsByDigit(-T(1), -D(1), Int(0)) + + NBKAssertComparisonsByDigit( T(2), D(3), -Int(1)) + NBKAssertComparisonsByDigit( T(2), -D(3), Int(1)) + NBKAssertComparisonsByDigit(-T(2), D(3), -Int(1)) + NBKAssertComparisonsByDigit(-T(2), -D(3), Int(1)) + + NBKAssertComparisonsByDigit( T(3), D(2), Int(1)) + NBKAssertComparisonsByDigit( T(3), -D(2), Int(1)) + NBKAssertComparisonsByDigit(-T(3), D(2), -Int(1)) + NBKAssertComparisonsByDigit(-T(3), -D(2), -Int(1)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Miscellaneous + //=------------------------------------------------------------------------= + + func testOverloadsAreUnambiguous() { + func becauseThisCompilesSuccessfully(_ x: inout T) { + XCTAssertNotNil(x.signum()) + } + } + + func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { + func becauseThisCompilesSuccessfully(_ x: inout T) { + XCTAssertNotNil(x.compared(to: 0)) + } + } +} + +//*============================================================================* +// MARK: * NBK x Signed x Comparisons x Assertions +//*============================================================================* + +private func NBKAssertSignum( +_ operand: NBKSigned, _ signum: Int, +file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual(Int(operand.signum() as Int), signum, file: file, line: line) +} + +private func NBKAssertComparisons( +_ lhs: NBKSigned, _ rhs: NBKSigned, _ signum: Int, +file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual(lhs == rhs, signum == 0, file: file, line: line) + XCTAssertEqual(lhs != rhs, signum != 0, file: file, line: line) + + XCTAssertEqual(lhs < rhs, signum == -1, file: file, line: line) + XCTAssertEqual(lhs <= rhs, signum != 1, file: file, line: line) + + XCTAssertEqual(lhs > rhs, signum == 1, file: file, line: line) + XCTAssertEqual(lhs >= rhs, signum != -1, file: file, line: line) + + XCTAssertEqual(lhs.compared(to: rhs), signum, file: file, line: line) +} + +private func NBKAssertComparisonsByDigit( +_ lhs: NBKSigned, _ rhs: NBKSigned.Digit, _ signum: Int, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + NBKAssertComparisons(lhs, NBKSigned(digit: rhs), signum) + //=------------------------------------------= + XCTAssertEqual(lhs.compared(to: rhs), signum, file: file, line: line) +} + +#endif diff --git a/Tests/NBKSignedKitTests/NBKSigned+Division.swift b/Tests/NBKSignedKitTests/NBKSigned+Division.swift new file mode 100644 index 00000000..59369925 --- /dev/null +++ b/Tests/NBKSignedKitTests/NBKSigned+Division.swift @@ -0,0 +1,140 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +import NBKFlexibleWidthKit +import NBKSignedKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Signed x Division x SIntXL +//*============================================================================* + +final class NBKSignedTestsOnDivisionAsSIntXL: XCTestCase { + + typealias T = NBKSigned + typealias M = NBKSigned.Magnitude + typealias D = NBKSigned.Digit + typealias U = NBKSigned.Digit.Magnitude + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testDividingLargeByLarge() { + NBKAssertDivision( T(M(x64:[~2, ~4, ~6, 9] as X)), T(M(x64:[~1, ~2, ~3, 4] as X)), T(2), T(1)) + NBKAssertDivision( T(M(x64:[~3, ~6, ~9, 14] as X)), -T(M(x64:[~1, ~2, ~3, 4] as X)), -T(3), T(2)) + NBKAssertDivision(-T(M(x64:[~4, ~8, ~12, 19] as X)), T(M(x64:[~1, ~2, ~3, 4] as X)), -T(4), -T(3)) + NBKAssertDivision(-T(M(x64:[~5, ~10, ~15, 24] as X)), -T(M(x64:[~1, ~2, ~3, 4] as X)), T(5), -T(4)) + } + + func testDividingLargeByLargeWithLargeRemainder() { + NBKAssertDivision( T(M(x64:[1, 2, 3, 4 + 1 << 63] as X)), T(M(x64:[ 1, 2, 3, 4 &+ 1 << 63] as X)), T(1), T(M(x64:[0, 0, 0, 0] as X))) + NBKAssertDivision( T(M(x64:[1, 2, 3, 4 + 1 << 63] as X)), T(M(x64:[ 0, 1, 2, 3 &+ 1 << 63] as X)), T(1), T(M(x64:[1, 1, 1, 1] as X))) + NBKAssertDivision( T(M(x64:[1, 2, 3, 4 + 1 << 63] as X)), -T(M(x64:[~0, ~0, 0, 2 &+ 1 << 63] as X)), -T(1), T(M(x64:[2, 2, 2, 2] as X))) + NBKAssertDivision( T(M(x64:[1, 2, 3, 4 + 1 << 63] as X)), -T(M(x64:[~1, ~1, ~0, 0 &+ 1 << 63] as X)), -T(1), T(M(x64:[3, 3, 3, 3] as X))) + NBKAssertDivision(-T(M(x64:[1, 2, 3, 4 + 1 << 63] as X)), T(M(x64:[~2, ~2, ~1, ~0 &+ 1 << 63] as X)), -T(1), -T(M(x64:[4, 4, 4, 4] as X))) + NBKAssertDivision(-T(M(x64:[1, 2, 3, 4 + 1 << 63] as X)), T(M(x64:[~3, ~3, ~2, ~1 &+ 1 << 63] as X)), -T(1), -T(M(x64:[5, 5, 5, 5] as X))) + NBKAssertDivision(-T(M(x64:[1, 2, 3, 4 + 1 << 63] as X)), -T(M(x64:[~4, ~4, ~3, ~2 &+ 1 << 63] as X)), T(1), -T(M(x64:[6, 6, 6, 6] as X))) + NBKAssertDivision(-T(M(x64:[1, 2, 3, 4 + 1 << 63] as X)), -T(M(x64:[~5, ~5, ~4, ~3 &+ 1 << 63] as X)), T(1), -T(M(x64:[7, 7, 7, 7] as X))) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Digit + //=------------------------------------------------------------------------= + + func testDividingSmallBySmall() { + NBKAssertDivisionByDigit( T( ), D(1), T( ), D( )) + NBKAssertDivisionByDigit( T( ), -D(2), -T( ), D( )) + NBKAssertDivisionByDigit(-T(7), D(1), -T(7), -D( )) + NBKAssertDivisionByDigit(-T(7), -D(2), T(3), -D(1)) + + NBKAssertDivisionByDigit( T(7), D(3), T(2), D(1)) + NBKAssertDivisionByDigit( T(7), -D(3), -T(2), D(1)) + NBKAssertDivisionByDigit(-T(7), D(3), -T(2), -D(1)) + NBKAssertDivisionByDigit(-T(7), -D(3), T(2), -D(1)) + } + + func testDividingLargeBySmall() { + NBKAssertDivisionByDigit( T(M(words:[1, 2, 3, 4] as W)), D(2), T(M(words:[0, ~0/2 + 2, 1, 2] as W)), D(1)) + NBKAssertDivisionByDigit( T(M(words:[1, 2, 3, 4] as W)), -D(2), -T(M(words:[0, ~0/2 + 2, 1, 2] as W)), D(1)) + NBKAssertDivisionByDigit(-T(M(words:[1, 2, 3, 4] as W)), D(2), -T(M(words:[0, ~0/2 + 2, 1, 2] as W)), -D(1)) + NBKAssertDivisionByDigit(-T(M(words:[1, 2, 3, 4] as W)), -D(2), T(M(words:[0, ~0/2 + 2, 1, 2] as W)), -D(1)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Miscellaneous + //=------------------------------------------------------------------------= + + func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { + func becauseThisCompilesSuccessfully(_ x: inout T) { + XCTAssertNotNil(x /= 0) + XCTAssertNotNil(x %= 0) + XCTAssertNotNil(x / 0) + XCTAssertNotNil(x % 0) + XCTAssertNotNil(x.quotientAndRemainder(dividingBy: 0)) + } + } +} + +//*============================================================================* +// MARK: * NBK x Signed x Division x Assertions +//*============================================================================* + +private func NBKAssertDivision( +_ lhs: NBKSigned, _ rhs: NBKSigned, _ quotient: NBKSigned, _ remainder: NBKSigned, _ overflow: Bool = false, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + XCTAssertEqual(lhs, quotient * rhs + remainder, "dividend != divisor * quotient + remainder", file: file, line: line) + //=------------------------------------------= + if !overflow { + NBKAssertIdentical(lhs / rhs, quotient, file: file, line: line) + NBKAssertIdentical(lhs % rhs, remainder, file: file, line: line) + + NBKAssertIdentical({ var x = lhs; x /= rhs; return x }(), quotient, file: file, line: line) + NBKAssertIdentical({ var x = lhs; x %= rhs; return x }(), remainder, file: file, line: line) + + NBKAssertIdentical(lhs.quotientAndRemainder(dividingBy: rhs).quotient, quotient, file: file, line: line) + NBKAssertIdentical(lhs.quotientAndRemainder(dividingBy: rhs).remainder, remainder, file: file, line: line) + } else { + XCTFail("\(NBKSigned.self) is not a binary integer.") + } +} + +private func NBKAssertDivisionByDigit( +_ lhs: NBKSigned, _ rhs: NBKSigned.Digit, _ quotient: NBKSigned, _ remainder: NBKSigned.Digit, _ overflow: Bool = false, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + let extended = NBKSigned(digit: remainder) + //=------------------------------------------= + NBKAssertDivision(lhs, NBKSigned(digit: rhs), quotient, extended) + //=------------------------------------------= + XCTAssertEqual(lhs, quotient * rhs + remainder, "dividend != divisor * quotient + remainder", file: file, line: line) + //=------------------------------------------= + if !overflow { + NBKAssertIdentical(lhs / rhs, quotient, file: file, line: line) + NBKAssertIdentical(lhs % rhs, remainder, file: file, line: line) + + NBKAssertIdentical({ var x = lhs; x /= rhs; return x }(), quotient, file: file, line: line) + NBKAssertIdentical({ var x = lhs; x %= rhs; return x }(), extended, file: file, line: line) + + NBKAssertIdentical(lhs.quotientAndRemainder(dividingBy: rhs).quotient, quotient, file: file, line: line) + NBKAssertIdentical(lhs.quotientAndRemainder(dividingBy: rhs).remainder, remainder, file: file, line: line) + } else { + XCTFail("\(NBKSigned.self) is not a binary integer.") + } +} + +#endif diff --git a/Tests/NBKSignedKitTests/NBKSigned+Multiplication.swift b/Tests/NBKSignedKitTests/NBKSigned+Multiplication.swift new file mode 100644 index 00000000..5f25647d --- /dev/null +++ b/Tests/NBKSignedKitTests/NBKSigned+Multiplication.swift @@ -0,0 +1,98 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +import NBKFlexibleWidthKit +import NBKSignedKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Signed x Multiplication x SIntXL +//*============================================================================* + +final class NBKSignedTestsOnMultiplicationAsSIntXL: XCTestCase { + + typealias T = NBKSigned + typealias M = NBKSigned.Magnitude + typealias D = NBKSigned.Digit + typealias U = NBKSigned.Digit.Magnitude + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testMultiplyingLargeByLarge() { + NBKAssertMultiplication( T( M(x64:[1, 2, 3, 4] as X)), T(M(x64:[2, 0, 0, 0] as X)), T(M(x64:[ 2, 4, 6, 8, 0, 0, 0, 0] as X))) + NBKAssertMultiplication( T( M(x64:[1, 2, 3, 4] as X)), -T(M(x64:[0, 2, 0, 0] as X)), -T(M(x64:[ 0, 2, 4, 6, 8, 0, 0, 0] as X))) + NBKAssertMultiplication(-T( M(x64:[1, 2, 3, 4] as X)), T(M(x64:[0, 0, 2, 0] as X)), -T(M(x64:[ 0, 0, 2, 4, 6, 8, 0, 0] as X))) + NBKAssertMultiplication(-T( M(x64:[1, 2, 3, 4] as X)), -T(M(x64:[0, 0, 0, 2] as X)), T(M(x64:[ 0, 0, 0, 2, 4, 6, 8, 0] as X))) + + NBKAssertMultiplication( T(~M(x64:[1, 2, 3, 4] as X)), T(M(x64:[2, 0, 0, 0] as X)), T(M(x64:[~3, ~4, ~6, ~8, 1, 0, 0, 0] as X))) + NBKAssertMultiplication( T(~M(x64:[1, 2, 3, 4] as X)), -T(M(x64:[0, 2, 0, 0] as X)), -T(M(x64:[ 0, ~3, ~4, ~6, ~8, 1, 0, 0] as X))) + NBKAssertMultiplication(-T(~M(x64:[1, 2, 3, 4] as X)), T(M(x64:[0, 0, 2, 0] as X)), -T(M(x64:[ 0, 0, ~3, ~4, ~6, ~8, 1, 0] as X))) + NBKAssertMultiplication(-T(~M(x64:[1, 2, 3, 4] as X)), -T(M(x64:[0, 0, 0, 2] as X)), T(M(x64:[ 0, 0, 0, ~3, ~4, ~6, ~8, 1] as X))) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Digit (and Self) + //=------------------------------------------------------------------------= + + func testMultiplyingLargeBySmall() { + NBKAssertMultiplicationByDigit( T( M(words:[1, 2, 3, 4] as W)), D(0), T( M(words:[ 0, 0, 0, 0, 0] as W))) + NBKAssertMultiplicationByDigit( T( M(words:[1, 2, 3, 4] as W)), -D(1), -T( M(words:[ 1, 2, 3, 4, 0] as W))) + NBKAssertMultiplicationByDigit(-T( M(words:[1, 2, 3, 4] as W)), D(2), -T( M(words:[ 2, 4, 6, 8, 0] as W))) + NBKAssertMultiplicationByDigit(-T( M(words:[1, 2, 3, 4] as W)), -D(3), T( M(words:[ 3, 6, 9, 12, 0] as W))) + + NBKAssertMultiplicationByDigit( T(~M(words:[1, 2, 3, 4] as W)), D(0), T(~M(words:[~0, ~0, ~0, ~0, ~0] as W))) + NBKAssertMultiplicationByDigit( T(~M(words:[1, 2, 3, 4] as W)), -D(1), -T(~M(words:[ 1, 2, 3, 4, ~0] as W))) + NBKAssertMultiplicationByDigit(-T(~M(words:[1, 2, 3, 4] as W)), D(2), -T(~M(words:[ 3, 4, 6, 8, ~1] as W))) + NBKAssertMultiplicationByDigit(-T(~M(words:[1, 2, 3, 4] as W)), -D(3), T(~M(words:[ 5, 6, 9, 12, ~2] as W))) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Miscellaneous + //=------------------------------------------------------------------------= + + func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { + func becauseThisCompilesSuccessfully(_ x: inout T) { + XCTAssertNotNil(x *= 0) + XCTAssertNotNil(x * 0) + } + } +} + +//*============================================================================* +// MARK: * NBK x Signed x Addition x Assertions +//*============================================================================* + +private func NBKAssertMultiplication( +_ lhs: NBKSigned, _ rhs: NBKSigned, _ result: NBKSigned, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + XCTAssertEqual( lhs * rhs, result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs *= rhs; return lhs }(), result, file: file, line: line) +} + +private func NBKAssertMultiplicationByDigit( +_ lhs: NBKSigned, _ rhs: NBKSigned.Digit, _ result: NBKSigned, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + NBKAssertMultiplication(lhs, NBKSigned(digit: rhs), result) + //=------------------------------------------= + XCTAssertEqual( lhs * rhs, result, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs *= rhs; return lhs }(), result, file: file, line: line) +} + +#endif diff --git a/Tests/NBKSignedKitTests/NBKSigned+Subtract.swift b/Tests/NBKSignedKitTests/NBKSigned+Subtract.swift index ad24326d..38117a4d 100644 --- a/Tests/NBKSignedKitTests/NBKSigned+Subtract.swift +++ b/Tests/NBKSignedKitTests/NBKSigned+Subtract.swift @@ -33,7 +33,7 @@ final class NBKSignedTestsOnSubtractionAsSIntXL: XCTestCase { // MARK: Tests //=------------------------------------------------------------------------= - func testSubtracting() { + func testSubtractingLargeFromLarge() { NBKAssertSubtraction( T(M(x64:[~0, ~0, ~0, 0] as X)), T(M(x64:[3, 0, 0, 0] as X)), T(M(x64:[~3, ~0, ~0, 0] as X))) NBKAssertSubtraction( T(M(x64:[~0, ~0, ~0, 0] as X)), T(M(x64:[0, 3, 0, 0] as X)), T(M(x64:[~0, ~3, ~0, 0] as X))) NBKAssertSubtraction( T(M(x64:[~0, ~0, ~0, 0] as X)), T(M(x64:[0, 0, 3, 0] as X)), T(M(x64:[~0, ~0, ~3, 0] as X))) @@ -56,10 +56,10 @@ final class NBKSignedTestsOnSubtractionAsSIntXL: XCTestCase { } //=------------------------------------------------------------------------= - // MARK: Tests x Digit + // MARK: Tests x Digit (and Self) //=------------------------------------------------------------------------= - func testSubtractingDigit() { + func testSubtractingSmallFromSmall() { NBKAssertSubtractionByDigit( T(M(1)), D(U(2)), -T(M(1))) NBKAssertSubtractionByDigit( T(M(1)), D(U(1)), T(M(0))) NBKAssertSubtractionByDigit( T(M(1)), D(U(0)), T(M(1))) @@ -116,11 +116,11 @@ file: StaticString = #file, line: UInt = #line) { private func NBKAssertSubtractionByDigit( _ lhs: NBKSigned, _ rhs: NBKSigned.Digit, _ partialValue: NBKSigned, file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + NBKAssertSubtraction(lhs, NBKSigned(digit: rhs), partialValue) //=------------------------------------------= NBKAssertIdentical( lhs - rhs, partialValue, file: file, line: line) NBKAssertIdentical({ var lhs = lhs; lhs -= rhs; return lhs }(), partialValue, file: file, line: line) - //=------------------------------------------= - NBKAssertSubtraction(lhs, NBKSigned(digit: rhs), partialValue) } #endif From f23fb2d841bb45c72f0035ac9e84fa5ee3040872 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Fri, 15 Sep 2023 15:07:16 +0200 Subject: [PATCH 072/133] [NBKSignedKit] Tests n' stuff. --- Sources/NBKSignedKit/NBKSigned+Numbers.swift | 58 +++- Sources/NBKSignedKit/NBKSigned.swift | 14 +- .../NBKSigned+Comparisons.swift | 26 +- .../NBKSigned+Division.swift | 44 ++- .../NBKSigned+Multiplication.swift | 8 +- .../NBKSigned+Negation.swift | 63 ++++ .../NBKSignedKitTests/NBKSigned+Numbers.swift | 165 +++++++++++ Tests/NBKSignedKitTests/NBKSigned+Text.swift | 272 ++++++++++++++++++ 8 files changed, 602 insertions(+), 48 deletions(-) create mode 100644 Tests/NBKSignedKitTests/NBKSigned+Negation.swift create mode 100644 Tests/NBKSignedKitTests/NBKSigned+Numbers.swift create mode 100644 Tests/NBKSignedKitTests/NBKSigned+Text.swift diff --git a/Sources/NBKSignedKit/NBKSigned+Numbers.swift b/Sources/NBKSignedKit/NBKSigned+Numbers.swift index b05f7ec3..efcec0d7 100644 --- a/Sources/NBKSignedKit/NBKSigned+Numbers.swift +++ b/Sources/NBKSignedKit/NBKSigned+Numbers.swift @@ -10,7 +10,7 @@ import NBKCoreKit //*============================================================================* -// MARK: * NBK x Signed x Numbers +// MARK: * NBK x Signed x Numbers x Decode //*============================================================================* extension NBKSigned { @@ -19,6 +19,18 @@ extension NBKSigned { // MARK: Initializers //=------------------------------------------------------------------------= + /// The positive zero value. + /// + /// Positive and negative zero are equal and have the same `hashValue`. + /// + @inlinable public static var zero: Self { + Self(sign: Sign.plus, magnitude: Magnitude.zero) + } + + //=------------------------------------------------------------------------= + // MARK: Initializers x Digit + //=------------------------------------------------------------------------= + @inlinable public init(digit: Digit) { let sign = digit.sign let magnitude = Magnitude(digit: digit.magnitude) @@ -63,3 +75,47 @@ extension NBKSigned { self.init(sign: sign, magnitude: magnitude) } } + +//=----------------------------------------------------------------------------= +// MARK: + Fixed Width +//=----------------------------------------------------------------------------= + +extension NBKSigned where Magnitude: FixedWidthInteger { + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + @inlinable public static var max: Self { + Self(sign: Sign.plus, magnitude: Magnitude.max) + } + + @inlinable public static var min: Self { + Self(sign: Sign.minus, magnitude: Magnitude.max) + } +} + +//*============================================================================* +// MARK: * NBK x Signed x Numbers x Encode +//*============================================================================* + +extension NBKBinaryInteger { + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + @inlinable public init(_ source: NBKSigned) { + if let value = Self(exactly: source) { self = value } else { + preconditionFailure("\(Self.self) cannot represent \(source)") + } + } + + @inlinable public init?(exactly source: NBKSigned) { + self.init(sign: source.sign, magnitude: source.magnitude) + } + + @inlinable public init(clamping source: NBKSigned) where Self: NBKFixedWidthInteger { + self = Self(sign: source.sign, magnitude: source.magnitude) ?? (source.sign == .minus ? Self.min : Self.max) + } +} diff --git a/Sources/NBKSignedKit/NBKSigned.swift b/Sources/NBKSignedKit/NBKSigned.swift index f2db1396..86ebf24f 100644 --- a/Sources/NBKSignedKit/NBKSigned.swift +++ b/Sources/NBKSignedKit/NBKSigned.swift @@ -20,18 +20,6 @@ CustomStringConvertible, ExpressibleByIntegerLiteral, Hashable, Sendable, Signed public typealias Digit = NBKSigned - //=------------------------------------------------------------------------= - // MARK: Accessors - //=------------------------------------------------------------------------= - - /// The positive zero value. - /// - /// Positive and negative zero are equal and have the same `hashValue`. - /// - @inlinable public static var zero: Self { - Self() - } - //=------------------------------------------------------------------------= // MARK: State //=------------------------------------------------------------------------= @@ -48,7 +36,7 @@ CustomStringConvertible, ExpressibleByIntegerLiteral, Hashable, Sendable, Signed /// Creates a new instance with a positive zero value. @inlinable public init() { - self.init(sign: Sign.plus, magnitude: Magnitude.zero) + self.init(sign: Sign.plus, magnitude: Magnitude()) } /// Creates a new instance with the given sign and magnitude. diff --git a/Tests/NBKSignedKitTests/NBKSigned+Comparisons.swift b/Tests/NBKSignedKitTests/NBKSigned+Comparisons.swift index 0590c2d5..ff203438 100644 --- a/Tests/NBKSignedKitTests/NBKSigned+Comparisons.swift +++ b/Tests/NBKSignedKitTests/NBKSigned+Comparisons.swift @@ -53,7 +53,27 @@ final class NBKSignedTestsOnComparisonsAsSIntXL: XCTestCase { XCTAssertTrue (( T(1)).isMoreThanZero) XCTAssertFalse((-T(1)).isMoreThanZero) } - + + func testIsPowerOf2() { + XCTAssertFalse((-T(3)).isPowerOf2) + XCTAssertFalse((-T(2)).isPowerOf2) + XCTAssertFalse((-T(1)).isPowerOf2) + XCTAssertFalse((-T(0)).isPowerOf2) + XCTAssertFalse(( T(0)).isPowerOf2) + XCTAssertTrue (( T(1)).isPowerOf2) + XCTAssertTrue (( T(2)).isPowerOf2) + XCTAssertFalse(( T(3)).isPowerOf2) + + XCTAssertFalse(T(M(words:[ 0, 0, 0, 0] as W)).isPowerOf2) + XCTAssertTrue (T(M(words:[ 1, 0, 0, 0] as W)).isPowerOf2) + XCTAssertFalse(T(M(words:[ 1, 1, 0, 0] as W)).isPowerOf2) + XCTAssertTrue (T(M(words:[ 0, 1, 0, 0] as W)).isPowerOf2) + XCTAssertFalse(T(M(words:[ 0, 1, 1, 0] as W)).isPowerOf2) + XCTAssertTrue (T(M(words:[ 0, 0, 1, 0] as W)).isPowerOf2) + XCTAssertFalse(T(M(words:[ 0, 0, 1, 1] as W)).isPowerOf2) + XCTAssertTrue (T(M(words:[ 0, 0, 0, 1] as W)).isPowerOf2) + } + func testSignum() { NBKAssertSignum(( T(0)), Int( 0)) NBKAssertSignum((-T(0)), Int( 0)) @@ -140,9 +160,7 @@ final class NBKSignedTestsOnComparisonsAsSIntXL: XCTestCase { // MARK: * NBK x Signed x Comparisons x Assertions //*============================================================================* -private func NBKAssertSignum( -_ operand: NBKSigned, _ signum: Int, -file: StaticString = #file, line: UInt = #line) { +private func NBKAssertSignum(_ operand: NBKSigned, _ signum: Int, file: StaticString = #file, line: UInt = #line) { XCTAssertEqual(Int(operand.signum() as Int), signum, file: file, line: line) } diff --git a/Tests/NBKSignedKitTests/NBKSigned+Division.swift b/Tests/NBKSignedKitTests/NBKSigned+Division.swift index 59369925..886b80a6 100644 --- a/Tests/NBKSignedKitTests/NBKSigned+Division.swift +++ b/Tests/NBKSignedKitTests/NBKSigned+Division.swift @@ -94,27 +94,23 @@ final class NBKSignedTestsOnDivisionAsSIntXL: XCTestCase { //*============================================================================* private func NBKAssertDivision( -_ lhs: NBKSigned, _ rhs: NBKSigned, _ quotient: NBKSigned, _ remainder: NBKSigned, _ overflow: Bool = false, +_ lhs: NBKSigned, _ rhs: NBKSigned, _ quotient: NBKSigned, _ remainder: NBKSigned, file: StaticString = #file, line: UInt = #line) { //=------------------------------------------= XCTAssertEqual(lhs, quotient * rhs + remainder, "dividend != divisor * quotient + remainder", file: file, line: line) //=------------------------------------------= - if !overflow { - NBKAssertIdentical(lhs / rhs, quotient, file: file, line: line) - NBKAssertIdentical(lhs % rhs, remainder, file: file, line: line) - - NBKAssertIdentical({ var x = lhs; x /= rhs; return x }(), quotient, file: file, line: line) - NBKAssertIdentical({ var x = lhs; x %= rhs; return x }(), remainder, file: file, line: line) - - NBKAssertIdentical(lhs.quotientAndRemainder(dividingBy: rhs).quotient, quotient, file: file, line: line) - NBKAssertIdentical(lhs.quotientAndRemainder(dividingBy: rhs).remainder, remainder, file: file, line: line) - } else { - XCTFail("\(NBKSigned.self) is not a binary integer.") - } + NBKAssertIdentical(lhs / rhs, quotient, file: file, line: line) + NBKAssertIdentical(lhs % rhs, remainder, file: file, line: line) + + NBKAssertIdentical({ var x = lhs; x /= rhs; return x }(), quotient, file: file, line: line) + NBKAssertIdentical({ var x = lhs; x %= rhs; return x }(), remainder, file: file, line: line) + + NBKAssertIdentical(lhs.quotientAndRemainder(dividingBy: rhs).quotient, quotient, file: file, line: line) + NBKAssertIdentical(lhs.quotientAndRemainder(dividingBy: rhs).remainder, remainder, file: file, line: line) } private func NBKAssertDivisionByDigit( -_ lhs: NBKSigned, _ rhs: NBKSigned.Digit, _ quotient: NBKSigned, _ remainder: NBKSigned.Digit, _ overflow: Bool = false, +_ lhs: NBKSigned, _ rhs: NBKSigned.Digit, _ quotient: NBKSigned, _ remainder: NBKSigned.Digit, file: StaticString = #file, line: UInt = #line) { //=------------------------------------------= let extended = NBKSigned(digit: remainder) @@ -123,18 +119,14 @@ file: StaticString = #file, line: UInt = #line) { //=------------------------------------------= XCTAssertEqual(lhs, quotient * rhs + remainder, "dividend != divisor * quotient + remainder", file: file, line: line) //=------------------------------------------= - if !overflow { - NBKAssertIdentical(lhs / rhs, quotient, file: file, line: line) - NBKAssertIdentical(lhs % rhs, remainder, file: file, line: line) - - NBKAssertIdentical({ var x = lhs; x /= rhs; return x }(), quotient, file: file, line: line) - NBKAssertIdentical({ var x = lhs; x %= rhs; return x }(), extended, file: file, line: line) - - NBKAssertIdentical(lhs.quotientAndRemainder(dividingBy: rhs).quotient, quotient, file: file, line: line) - NBKAssertIdentical(lhs.quotientAndRemainder(dividingBy: rhs).remainder, remainder, file: file, line: line) - } else { - XCTFail("\(NBKSigned.self) is not a binary integer.") - } + NBKAssertIdentical(lhs / rhs, quotient, file: file, line: line) + NBKAssertIdentical(lhs % rhs, remainder, file: file, line: line) + + NBKAssertIdentical({ var x = lhs; x /= rhs; return x }(), quotient, file: file, line: line) + NBKAssertIdentical({ var x = lhs; x %= rhs; return x }(), extended, file: file, line: line) + + NBKAssertIdentical(lhs.quotientAndRemainder(dividingBy: rhs).quotient, quotient, file: file, line: line) + NBKAssertIdentical(lhs.quotientAndRemainder(dividingBy: rhs).remainder, remainder, file: file, line: line) } #endif diff --git a/Tests/NBKSignedKitTests/NBKSigned+Multiplication.swift b/Tests/NBKSignedKitTests/NBKSigned+Multiplication.swift index 5f25647d..0f9df536 100644 --- a/Tests/NBKSignedKitTests/NBKSigned+Multiplication.swift +++ b/Tests/NBKSignedKitTests/NBKSigned+Multiplication.swift @@ -81,8 +81,8 @@ private func NBKAssertMultiplication( _ lhs: NBKSigned, _ rhs: NBKSigned, _ result: NBKSigned, file: StaticString = #file, line: UInt = #line) { //=------------------------------------------= - XCTAssertEqual( lhs * rhs, result, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs *= rhs; return lhs }(), result, file: file, line: line) + NBKAssertIdentical( lhs * rhs, result, file: file, line: line) + NBKAssertIdentical({ var lhs = lhs; lhs *= rhs; return lhs }(), result, file: file, line: line) } private func NBKAssertMultiplicationByDigit( @@ -91,8 +91,8 @@ file: StaticString = #file, line: UInt = #line) { //=------------------------------------------= NBKAssertMultiplication(lhs, NBKSigned(digit: rhs), result) //=------------------------------------------= - XCTAssertEqual( lhs * rhs, result, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs *= rhs; return lhs }(), result, file: file, line: line) + NBKAssertIdentical( lhs * rhs, result, file: file, line: line) + NBKAssertIdentical({ var lhs = lhs; lhs *= rhs; return lhs }(), result, file: file, line: line) } #endif diff --git a/Tests/NBKSignedKitTests/NBKSigned+Negation.swift b/Tests/NBKSignedKitTests/NBKSigned+Negation.swift new file mode 100644 index 00000000..c5325c29 --- /dev/null +++ b/Tests/NBKSignedKitTests/NBKSigned+Negation.swift @@ -0,0 +1,63 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKSignedKit +import XCTest + +//*============================================================================* +// MARK: * NBK x Signed x Negation +//*============================================================================* + +final class NBKSignedTestsOnNegation: XCTestCase { + + typealias T = NBKSigned + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testNegating() { + NBKAssertNegation( T(1), -T(1)) + NBKAssertNegation( T(0), -T(0)) + NBKAssertNegation(-T(0), T(0)) + NBKAssertNegation(-T(1), T(1)) + + NBKAssertNegation(T.max, T.min) + NBKAssertNegation(T.min, T.max) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Miscellaneous + //=------------------------------------------------------------------------= + + func testOverloadsAreUnambiguous() { + func becauseThisCompilesSuccessfully(_ x: inout T) { + XCTAssertNotNil(-x) + XCTAssertNotNil(x.negate()) + XCTAssertNotNil(x.negated()) + } + } +} + +//*============================================================================* +// MARK: * NBK x Signed x Negation x Assertions +//*============================================================================* + +private func NBKAssertNegation( +_ operand: NBKSigned, _ result: NBKSigned, +file: StaticString = #file, line: UInt = #line) { + NBKAssertIdentical(-operand, result, file: file, line: line) + NBKAssertIdentical((operand).negated(), result, file: file, line: line) + NBKAssertIdentical({ var x = operand; x.negate(); return x }(), result, file: file, line: line) +} + + +#endif diff --git a/Tests/NBKSignedKitTests/NBKSigned+Numbers.swift b/Tests/NBKSignedKitTests/NBKSigned+Numbers.swift new file mode 100644 index 00000000..324606b2 --- /dev/null +++ b/Tests/NBKSignedKitTests/NBKSigned+Numbers.swift @@ -0,0 +1,165 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +import NBKSignedKit +import XCTest + +//*============================================================================* +// MARK: * NBK x Signed x Numbers +//*============================================================================* + +final class NBKSignedTestsOnNumbers: XCTestCase { + + typealias T = NBKSigned + typealias M = NBKSigned.Magnitude + typealias D = NBKSigned.Digit + typealias S = Int + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testZero() { + NBKAssertIdentical(T( ), T(sign: .plus, magnitude: M( ))) + NBKAssertIdentical(T.zero, T(sign: .plus, magnitude: M( ))) + } + + func testEdges() { + NBKAssertIdentical(T.max, T(sign: .plus, magnitude: M.max)) + NBKAssertIdentical(T.min, T(sign: .minus, magnitude: M.max)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Digit + //=------------------------------------------------------------------------= + + func testFromDigit() { + NBKAssertIdentical(T(digit: D(4)), T(4)) + NBKAssertIdentical(T(digit: -D(4)), -T(4)) + NBKAssertIdentical(D(digit: D(4)), D(4)) + NBKAssertIdentical(D(digit: -D(4)), -D(4)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Signitude + //=------------------------------------------------------------------------= + + func testsToSignitude() { + XCTAssertEqual(S( T(sign: .plus , magnitude: M( 1))), S( 1)) + XCTAssertEqual(S(exactly: T(sign: .plus , magnitude: M( 1))), S( 1)) + XCTAssertEqual(S(clamping: T(sign: .plus , magnitude: M( 1))), S( 1)) + + XCTAssertEqual(S( T(sign: .minus, magnitude: M( 1))), S(-1)) + XCTAssertEqual(S(exactly: T(sign: .minus, magnitude: M( 1))), S(-1)) + XCTAssertEqual(S(clamping: T(sign: .minus, magnitude: M( 1))), S(-1)) + + XCTAssertEqual(S(exactly: T(sign: .plus , magnitude: M.max)), nil) + XCTAssertEqual(S(clamping: T(sign: .plus , magnitude: M.max)), S.max) + + XCTAssertEqual(S(exactly: T(sign: .minus, magnitude: M.max)), nil) + XCTAssertEqual(S(clamping: T(sign: .minus, magnitude: M.max)), S.min) + + XCTAssertEqual(S( T(sign: .plus , magnitude: S.max.magnitude)), S.max) + XCTAssertEqual(S(exactly: T(sign: .plus , magnitude: S.max.magnitude)), S.max) + XCTAssertEqual(S(clamping: T(sign: .plus , magnitude: S.max.magnitude)), S.max) + + XCTAssertEqual(S( T(sign: .minus, magnitude: S.min.magnitude)), S.min) + XCTAssertEqual(S(exactly: T(sign: .minus, magnitude: S.min.magnitude)), S.min) + XCTAssertEqual(S(clamping: T(sign: .minus, magnitude: S.min.magnitude)), S.min) + } + + func testToSignitudeAsPlusMinusZero() { + XCTAssertEqual(S( T(sign: .plus , magnitude: M( ))), S( )) + XCTAssertEqual(S(exactly: T(sign: .plus , magnitude: M( ))), S( )) + XCTAssertEqual(S(clamping: T(sign: .plus , magnitude: M( ))), S( )) + + XCTAssertEqual(S( T(sign: .minus, magnitude: M( ))), S( )) + XCTAssertEqual(S(exactly: T(sign: .minus, magnitude: M( ))), S( )) + XCTAssertEqual(S(clamping: T(sign: .minus, magnitude: M( ))), S( )) + } + + func testFromSignitude() { + NBKAssertIdentical(T( S( 1)), T(1)) + NBKAssertIdentical(T(exactly: S( 1)), T(1)) + NBKAssertIdentical(T(clamping: S( 1)), T(1)) + + NBKAssertIdentical(T( S( )), T( )) + NBKAssertIdentical(T(exactly: S( )), T( )) + NBKAssertIdentical(T(clamping: S( )), T( )) + + NBKAssertIdentical(T( S(-1)), -T(1)) + NBKAssertIdentical(T(exactly: S(-1)), -T(1)) + NBKAssertIdentical(T(clamping: S(-1)), -T(1)) + + NBKAssertIdentical(T( S.max), T(sign: .plus, magnitude: M(S.max) + 0)) + NBKAssertIdentical(T(exactly: S.max), T(sign: .plus, magnitude: M(S.max) + 0)) + NBKAssertIdentical(T(clamping: S.max), T(sign: .plus, magnitude: M(S.max) + 0)) + + NBKAssertIdentical(T( S.min), T(sign: .minus, magnitude: M(S.max) + 1)) + NBKAssertIdentical(T(exactly: S.min), T(sign: .minus, magnitude: M(S.max) + 1)) + NBKAssertIdentical(T(clamping: S.min), T(sign: .minus, magnitude: M(S.max) + 1)) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Magnitude + //=------------------------------------------------------------------------= + + func testsToMagnitude() { + XCTAssertEqual(M( T(sign: .plus , magnitude: M( 1))), M( 1)) + XCTAssertEqual(M(exactly: T(sign: .plus , magnitude: M( 1))), M( 1)) + XCTAssertEqual(M(clamping: T(sign: .plus , magnitude: M( 1))), M( 1)) + + XCTAssertEqual(M(exactly: T(sign: .minus, magnitude: M( 1))), nil) + XCTAssertEqual(M(clamping: T(sign: .minus, magnitude: M( 1))), M.min) + + XCTAssertEqual(M( T(sign: .plus , magnitude: M.max)), M.max) + XCTAssertEqual(M(exactly: T(sign: .plus , magnitude: M.max)), M.max) + XCTAssertEqual(M(clamping: T(sign: .plus , magnitude: M.max)), M.max) + + XCTAssertEqual(M(exactly: T(sign: .minus, magnitude: M.max)), nil) + XCTAssertEqual(M(clamping: T(sign: .minus, magnitude: M.max)), M.min) + + XCTAssertEqual(M( T(sign: .plus , magnitude: M.max.magnitude)), M.max) + XCTAssertEqual(M(exactly: T(sign: .plus , magnitude: M.max.magnitude)), M.max) + XCTAssertEqual(M(clamping: T(sign: .plus , magnitude: M.max.magnitude)), M.max) + + XCTAssertEqual(M( T(sign: .minus, magnitude: M.min.magnitude)), M.min) + XCTAssertEqual(M(exactly: T(sign: .minus, magnitude: M.min.magnitude)), M.min) + XCTAssertEqual(M(clamping: T(sign: .minus, magnitude: M.min.magnitude)), M.min) + } + + func testToMagnitudeAsPlusMinusZero() { + XCTAssertEqual(M( T(sign: .plus , magnitude: M( ))), M( )) + XCTAssertEqual(M(exactly: T(sign: .plus , magnitude: M( ))), M( )) + XCTAssertEqual(M(clamping: T(sign: .plus , magnitude: M( ))), M( )) + + XCTAssertEqual(M( T(sign: .minus, magnitude: M( ))), M( )) + XCTAssertEqual(M(exactly: T(sign: .minus, magnitude: M( ))), M( )) + XCTAssertEqual(M(clamping: T(sign: .minus, magnitude: M( ))), M( )) + } + + func testFromMagnitude() { + NBKAssertIdentical(T( M( )), T( )) + NBKAssertIdentical(T(exactly: M( )), T( )) + NBKAssertIdentical(T(clamping: M( )), T( )) + + NBKAssertIdentical(T( M( 1)), T( 1)) + NBKAssertIdentical(T(exactly: M( 1)), T( 1)) + NBKAssertIdentical(T(clamping: M( 1)), T( 1)) + + NBKAssertIdentical(T( M.max), T.max) + NBKAssertIdentical(T(exactly: M.max), T.max) + NBKAssertIdentical(T(clamping: M.max), T.max) + } +} + +#endif diff --git a/Tests/NBKSignedKitTests/NBKSigned+Text.swift b/Tests/NBKSignedKitTests/NBKSigned+Text.swift new file mode 100644 index 00000000..ef7b0a01 --- /dev/null +++ b/Tests/NBKSignedKitTests/NBKSigned+Text.swift @@ -0,0 +1,272 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKSignedKit +import XCTest + +//*============================================================================* +// MARK: * NBK x Signed x Text +//*============================================================================* + +final class NBKSignedTestsOnText: XCTestCase { + + typealias T = NBKSigned + typealias M = UInt64 + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testFromDescription() { + NBKAssertFromDescription(T?( 10), "10") + NBKAssertFromDescription(T?( 10), "+10") + NBKAssertFromDescription(T?(-10), "-10") + NBKAssertFromDescription(T?(nil), " 10") + NBKAssertFromDescription(T?(nil), "0x10") + NBKAssertFromDescription(T?(nil), "+0x10") + NBKAssertFromDescription(T?(nil), "-0x10") + NBKAssertFromDescription(T?(nil), " 0x10") + } + + func testInstanceDescriptionUsesRadix10() { + XCTAssertEqual("10", T(10).description) + XCTAssertEqual("10", String(describing: T(10))) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Decode + //=------------------------------------------------------------------------= + + func testDecodingRadix02() { + NBKAssertDecodeText(T.min, 02, "-" + String(repeating: "1", count: M.bitWidth / 1)) + NBKAssertDecodeText(T.max, 02, String(repeating: "1", count: M.bitWidth / 1)) + } + + func testDecodingRadix03() { + NBKAssertDecodeText(T.min, 03, "-11112220022122120101211020120210210211220") + NBKAssertDecodeText(T.max, 03, "11112220022122120101211020120210210211220") + } + + func testDecodingRadix04() { + NBKAssertDecodeText(T.min, 04, "-" + String(repeating: "3", count: M.bitWidth / 2)) + NBKAssertDecodeText(T.max, 04, String(repeating: "3", count: M.bitWidth / 2)) + } + + func testDecodingRadix08() { + NBKAssertDecodeText(T.min, 08, "-1" + String(repeating: "7", count: 21)) + NBKAssertDecodeText(T.max, 08, "1" + String(repeating: "7", count: 21)) + } + + func testDecodingRadix10() { + NBKAssertDecodeText(T.min, 10, "-18446744073709551615") + NBKAssertDecodeText(T.max, 10, "18446744073709551615") + } + + func testDecodingRadix16() { + NBKAssertDecodeText(T.min, 16, "-" + String(repeating: "f", count: M.bitWidth / 4)) + NBKAssertDecodeText(T.max, 16, String(repeating: "f", count: M.bitWidth / 4)) + } + + func testDecodingRadix32() { + NBKAssertDecodeText(T.min, 32, "-f" + String(repeating: "v", count: 12)) + NBKAssertDecodeText(T.max, 32, "f" + String(repeating: "v", count: 12)) + } + + func testDecodingRadix36() { + NBKAssertDecodeText(T.min, 36, "-3w5e11264sgsf") + NBKAssertDecodeText(T.max, 36, "3w5e11264sgsf") + } + + func testDecodingRadixLiteralAsNumber() { + NBKAssertDecodeText(T( 33), 36, "0x") + NBKAssertDecodeText(T( 24), 36, "0o") + NBKAssertDecodeText(T( 11), 36, "0b") + + NBKAssertDecodeText(T( 33), 36, "+0x") + NBKAssertDecodeText(T( 24), 36, "+0o") + NBKAssertDecodeText(T( 11), 36, "+0b") + + NBKAssertDecodeText(T(-33), 36, "-0x") + NBKAssertDecodeText(T(-24), 36, "-0o") + NBKAssertDecodeText(T(-11), 36, "-0b") + } + + func testDecodingRadixLiteralAsRadixReturnsNil() { + NBKAssertDecodeText(T?.none, 10, "0x10") + NBKAssertDecodeText(T?.none, 10, "0o10") + NBKAssertDecodeText(T?.none, 10, "0b10") + + NBKAssertDecodeText(T?.none, 10, "+0x10") + NBKAssertDecodeText(T?.none, 10, "+0o10") + NBKAssertDecodeText(T?.none, 10, "+0b10") + + NBKAssertDecodeText(T?.none, 10, "-0x10") + NBKAssertDecodeText(T?.none, 10, "-0o10") + NBKAssertDecodeText(T?.none, 10, "-0b10") + } + + func testDecodingStringsWithAndWithoutSign() { + NBKAssertDecodeText(T( 1234567890), 10, "1234567890") + NBKAssertDecodeText(T( 1234567890), 10, "+1234567890") + NBKAssertDecodeText(T(-1234567890), 10, "-1234567890") + } + + func testDecodingStrategyIsCaseInsensitive() { + NBKAssertDecodeText(T(0xabcdef), 16, "abcdef") + NBKAssertDecodeText(T(0xABCDEF), 16, "ABCDEF") + NBKAssertDecodeText(T(0xaBcDeF), 16, "aBcDeF") + NBKAssertDecodeText(T(0xAbCdEf), 16, "AbCdEf") + } + + func testDecodingUnalignedStringsIsOK() { + NBKAssertDecodeText(T(1), 10, "1") + NBKAssertDecodeText(T(1), 16, "1") + } + + func testDecodingPrefixingZerosHasNoEffect() { + let zero = String(repeating: "0", count: M.bitWidth) + "0" + let one = String(repeating: "0", count: M.bitWidth) + "1" + + for radix in 02 ... 36 { + NBKAssertDecodeText(T(0), radix, zero) + NBKAssertDecodeText(T(1), radix, one ) + } + } + + func testDecodingInvalidCharactersReturnsNil() { + NBKAssertDecodeText(T?.none, 16, "/") + NBKAssertDecodeText(T?.none, 16, "G") + + NBKAssertDecodeText(T?.none, 10, "/") + NBKAssertDecodeText(T?.none, 10, ":") + + NBKAssertDecodeText(T?.none, 10, String(repeating: "1", count: 19) + "/") + NBKAssertDecodeText(T?.none, 10, String(repeating: "1", count: 19) + ":") + } + + func testDecodingStringsWithoutDigitsReturnsNil() { + NBKAssertDecodeText(T?.none, 10, "") + NBKAssertDecodeText(T?.none, 10, "+") + NBKAssertDecodeText(T?.none, 10, "-") + NBKAssertDecodeText(T?.none, 10, "~") + + NBKAssertDecodeText(T?.none, 16, "") + NBKAssertDecodeText(T?.none, 16, "+") + NBKAssertDecodeText(T?.none, 16, "-") + NBKAssertDecodeText(T?.none, 16, "~") + } + + func testDecodingValuesOutsideOfRepresentableRangeReturnsNil() { + let positive = "+" + String(repeating: "1", count: M.bitWidth + 1) + let negative = "-" + String(repeating: "1", count: M.bitWidth + 1) + + for radix in 02 ... 36 { + NBKAssertDecodeText(T?.none, radix, positive) + NBKAssertDecodeText(T?.none, radix, negative) + } + + NBKAssertDecodeText(T?.none, 36, "-3w5e11264sgsg" ) // - 01 + NBKAssertDecodeText(T?.none, 36, "-3w5e11264sgsf0") // * 36 + NBKAssertDecodeText(T?.none, 36, "3w5e11264sgsg" ) // + 01 + NBKAssertDecodeText(T?.none, 36, "3w5e11264sgsf0") // * 36 + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Encode + //=------------------------------------------------------------------------= + + func testEncodingRadix02() { + NBKAssertEncodeText(T.min, 02, false, "-" + String(repeating: "1", count: M.bitWidth / 1)) + NBKAssertEncodeText(T.max, 02, false, String(repeating: "1", count: M.bitWidth / 1)) + } + + func testEncodingRadix03() { + NBKAssertEncodeText(T.min, 03, false, "-11112220022122120101211020120210210211220") + NBKAssertEncodeText(T.max, 03, false, "11112220022122120101211020120210210211220") + } + + func testEncodingRadix04() { + NBKAssertEncodeText(T.min, 04, false, "-" + String(repeating: "3", count: M.bitWidth / 2)) + NBKAssertEncodeText(T.max, 04, false, String(repeating: "3", count: M.bitWidth / 2)) + } + + func testEncodingRadix08() { + NBKAssertEncodeText(T.min, 08, false, "-1" + String(repeating: "7", count: 21)) + NBKAssertEncodeText(T.max, 08, false, "1" + String(repeating: "7", count: 21)) + } + + func testEncodingRadix10() { + NBKAssertEncodeText(T.min, 10, false, "-18446744073709551615") + NBKAssertEncodeText(T.max, 10, false, "18446744073709551615") + } + + func testEncodingRadix16() { + NBKAssertEncodeText(T.min, 16, false, "-" + String(repeating: "f", count: M.bitWidth / 4)) + NBKAssertEncodeText(T.min, 16, true , "-" + String(repeating: "F", count: M.bitWidth / 4)) + NBKAssertEncodeText(T.max, 16, false, String(repeating: "f", count: M.bitWidth / 4)) + NBKAssertEncodeText(T.max, 16, true , String(repeating: "F", count: M.bitWidth / 4)) + } + + func testEncodingRadix32() { + NBKAssertEncodeText(T.min, 32, false, "-f" + String(repeating: "v", count: 12)) + NBKAssertEncodeText(T.min, 32, true , "-F" + String(repeating: "V", count: 12)) + NBKAssertEncodeText(T.max, 32, false, "f" + String(repeating: "v", count: 12)) + NBKAssertEncodeText(T.max, 32, true , "F" + String(repeating: "V", count: 12)) + } + + func testEncodingRadix36() { + NBKAssertEncodeText(T.min, 36, false, "-3w5e11264sgsf") + NBKAssertEncodeText(T.min, 36, true , "-3W5E11264SGSF") + NBKAssertEncodeText(T.max, 36, false, "3w5e11264sgsf") + NBKAssertEncodeText(T.max, 36, true , "3W5E11264SGSF") + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Text x Assertions +//*============================================================================* + +private func NBKAssertFromDescription( +_ integer: NBKSigned?, _ description: String, +file: StaticString = #file, line: UInt = #line) { + typealias T = NBKSigned + //=------------------------------------------= + NBKAssertIdentical(T.init(description), integer, file: file, line: line) + NBKAssertIdentical(T.init(description, radix: 10), integer, file: file, line: line) +} + +private func NBKAssertDecodeText( +_ integer: NBKSigned?, _ radix: Int, _ text: String, +file: StaticString = #file, line: UInt = #line) { + typealias T = NBKSigned + //=------------------------------------------= + if radix == 10 { + NBKAssertIdentical(T.init(text), integer, file: file, line: line) + } + //=------------------------------------------= + NBKAssertIdentical(T.init(text, radix: radix), integer, file: file, line: line) +} + +private func NBKAssertEncodeText( +_ integer: NBKSigned, _ radix: Int, _ uppercase: Bool, _ text: String, +file: StaticString = #file, line: UInt = #line) { + typealias T = NBKSigned + //=------------------------------------------= + if radix == 10, uppercase == false { + XCTAssertEqual(String.init(integer), text, file: file, line: line) + XCTAssertEqual(integer.description, text, file: file, line: line) + } + //=------------------------------------------= + XCTAssertEqual(String.init(integer,radix: radix, uppercase: uppercase), text, file: file, line: line) + XCTAssertEqual(integer.description(radix: radix, uppercase: uppercase), text, file: file, line: line) +} + +#endif From 39a96aa5e7cb2b34da8fd981786a867999fc519b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Fri, 15 Sep 2023 18:41:18 +0200 Subject: [PATCH 073/133] [NBKSignedKit] Benchmarks. --- Tests/NBKSignedKitBenchmarks/Blank.swift | 1 - .../NBKFlexibleWidth.swift | 49 +++++++ .../NBKSigned+Addition.swift | 84 ++++++++++++ .../NBKSigned+Comparisons.swift | 129 ++++++++++++++++++ .../NBKSigned+Complements.swift | 48 +++++++ .../NBKSigned+Division.swift | 77 +++++++++++ .../NBKSigned+Multiplication.swift | 62 +++++++++ .../NBKSigned+Subtraction.swift | 84 ++++++++++++ .../NBKSigned+Text.swift | 86 ++++++++++++ 9 files changed, 619 insertions(+), 1 deletion(-) delete mode 100644 Tests/NBKSignedKitBenchmarks/Blank.swift create mode 100644 Tests/NBKSignedKitBenchmarks/NBKFlexibleWidth.swift create mode 100644 Tests/NBKSignedKitBenchmarks/NBKSigned+Addition.swift create mode 100644 Tests/NBKSignedKitBenchmarks/NBKSigned+Comparisons.swift create mode 100644 Tests/NBKSignedKitBenchmarks/NBKSigned+Complements.swift create mode 100644 Tests/NBKSignedKitBenchmarks/NBKSigned+Division.swift create mode 100644 Tests/NBKSignedKitBenchmarks/NBKSigned+Multiplication.swift create mode 100644 Tests/NBKSignedKitBenchmarks/NBKSigned+Subtraction.swift create mode 100644 Tests/NBKSignedKitBenchmarks/NBKSigned+Text.swift diff --git a/Tests/NBKSignedKitBenchmarks/Blank.swift b/Tests/NBKSignedKitBenchmarks/Blank.swift deleted file mode 100644 index 8b137891..00000000 --- a/Tests/NBKSignedKitBenchmarks/Blank.swift +++ /dev/null @@ -1 +0,0 @@ - diff --git a/Tests/NBKSignedKitBenchmarks/NBKFlexibleWidth.swift b/Tests/NBKSignedKitBenchmarks/NBKFlexibleWidth.swift new file mode 100644 index 00000000..1d90cdf2 --- /dev/null +++ b/Tests/NBKSignedKitBenchmarks/NBKFlexibleWidth.swift @@ -0,0 +1,49 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit +import NBKFlexibleWidthKit +import NBKSignedKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Flexible Width x Signed +//*============================================================================* + +public typealias SIntXL = NBKSigned + +//*============================================================================* +// MARK: * NBK x Flexible Width x UIntXL +//*============================================================================* + +extension UIntXL { + + //=------------------------------------------------------------------------= + // MARK: Details x Numbers + //=------------------------------------------------------------------------= + + static let min256 = Self(x64:[ 0, 0, 0, 0] as X) + static let max256 = Self(x64:[~0, ~0, ~0, ~0] as X) + + //=------------------------------------------------------------------------= + // MARK: Details x Limbs + //=------------------------------------------------------------------------= + + init(x32: [UInt32]) { + self.init(words: NBKChunkedInt(x32)) + } + + init(x64: [UInt64]) { + self.init(words: NBKChunkedInt(x64)) + } +} diff --git a/Tests/NBKSignedKitBenchmarks/NBKSigned+Addition.swift b/Tests/NBKSignedKitBenchmarks/NBKSigned+Addition.swift new file mode 100644 index 00000000..5b9cbc45 --- /dev/null +++ b/Tests/NBKSignedKitBenchmarks/NBKSigned+Addition.swift @@ -0,0 +1,84 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if !DEBUG + +import NBKCoreKit +import NBKFlexibleWidthKit +import NBKSignedKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Signed x Addition x UIntXL +//*============================================================================* + +final class NBKSignedBenchmarksOnAdditionAsSIntXL: XCTestCase { + + typealias T = NBKSigned + typealias M = NBKSigned.Magnitude + typealias D = NBKSigned.Digit + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testAdd() { + var lhs = NBK.blackHoleIdentity(T(M(x64:[~0, ~1, ~2, ~3] as X))) + var rhs = NBK.blackHoleIdentity(T(M(x64:[ 0, 1, 2, 3] as X))) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs += rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testAdding() { + var lhs = NBK.blackHoleIdentity(T(M(x64:[~0, ~1, ~2, ~3] as X))) + var rhs = NBK.blackHoleIdentity(T(M(x64:[ 0, 1, 2, 3] as X))) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs + rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Digit + //=------------------------------------------------------------------------= + + func testAddDigit() { + var lhs = NBK.blackHoleIdentity(T(M(x64:[~0, ~1, ~2, ~3] as X))) + var rhs = NBK.blackHoleIdentity(D.max) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs += rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testAddingDigit() { + var lhs = NBK.blackHoleIdentity(T(M(x64:[~0, ~1, ~2, ~3] as X))) + var rhs = NBK.blackHoleIdentity(D.max) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs + rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } +} + +#endif diff --git a/Tests/NBKSignedKitBenchmarks/NBKSigned+Comparisons.swift b/Tests/NBKSignedKitBenchmarks/NBKSigned+Comparisons.swift new file mode 100644 index 00000000..72f13b1f --- /dev/null +++ b/Tests/NBKSignedKitBenchmarks/NBKSigned+Comparisons.swift @@ -0,0 +1,129 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if !DEBUG + +import NBKCoreKit +import NBKFlexibleWidthKit +import NBKSignedKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Signed x Comparisons x UIntXL +//*============================================================================* + +final class NBKSignedBenchmarksOnComparisonsAsSIntXL: XCTestCase { + + typealias T = NBKSigned + typealias M = NBKSigned.Magnitude + typealias D = NBKSigned.Digit + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testIsZero() { + var abc = NBK.blackHoleIdentity(T(M(x64:[0, 1, 2, 3] as X))) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.isZero) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testIsLessThanZero() { + var abc = NBK.blackHoleIdentity(T(M(x64:[0, 1, 2, 3] as X))) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.isLessThanZero) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testIsMoreThanZero() { + var abc = NBK.blackHoleIdentity(T(M(x64:[0, 1, 2, 3] as X))) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.isMoreThanZero) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testIsPowerOf2() { + var abc = NBK.blackHoleIdentity(T(M(x64:[0, 1, 2, 3] as X))) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.isPowerOf2) + NBK.blackHoleInoutIdentity(&abc) + } + } + + func testSignum() { + var abc = NBK.blackHoleIdentity(T(M(x64:[0, 1, 2, 3] as X))) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.signum()) + NBK.blackHoleInoutIdentity(&abc) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testIsEqualTo() { + var lhs = NBK.blackHoleIdentity(T(M(x64:[0, 1, 2, 3] as X))) + var rhs = NBK.blackHoleIdentity(T(M(x64:[0, 1, 2, 3] as X))) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs == rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testIsLessThan() { + var lhs = NBK.blackHoleIdentity(T(M(x64:[0, 1, 2, 3] as X))) + var rhs = NBK.blackHoleIdentity(T(M(x64:[0, 1, 2, 3] as X))) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs < rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testComparedTo() { + var lhs = NBK.blackHoleIdentity(T(M(x64:[0, 1, 2, 3] as X))) + var rhs = NBK.blackHoleIdentity(T(M(x64:[0, 1, 2, 3] as X))) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs.compared(to: rhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testComparedToDigit() { + var lhs = NBK.blackHoleIdentity(T(M(x64:[0, 1, 2, 3] as X))) + var rhs = NBK.blackHoleIdentity(D.max) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs.compared(to: rhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } +} + +#endif diff --git a/Tests/NBKSignedKitBenchmarks/NBKSigned+Complements.swift b/Tests/NBKSignedKitBenchmarks/NBKSigned+Complements.swift new file mode 100644 index 00000000..dbd7ff46 --- /dev/null +++ b/Tests/NBKSignedKitBenchmarks/NBKSigned+Complements.swift @@ -0,0 +1,48 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if !DEBUG + +import NBKCoreKit +import NBKFlexibleWidthKit +import NBKSignedKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Signed x Complements x UIntXL +//*============================================================================* + +final class NBKSignedBenchmarksOnComplementsAsSIntXL: XCTestCase { + + typealias T = NBKSigned + typealias M = NBKSigned.Magnitude + + //=------------------------------------------------------------------------= + // MARK: Tests x Magnitude + //=------------------------------------------------------------------------= + + func testMagnitude() { + var abc = NBK.blackHoleIdentity(T(M(x64:[ 1, 2, 3, 4] as X))) + var xyz = NBK.blackHoleIdentity(T(M(x64:[~1, ~2, ~3, ~4] as X))) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc.magnitude) + NBK.blackHole(xyz.magnitude) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } +} + +#endif diff --git a/Tests/NBKSignedKitBenchmarks/NBKSigned+Division.swift b/Tests/NBKSignedKitBenchmarks/NBKSigned+Division.swift new file mode 100644 index 00000000..24040593 --- /dev/null +++ b/Tests/NBKSignedKitBenchmarks/NBKSigned+Division.swift @@ -0,0 +1,77 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if !DEBUG + +import NBKCoreKit +import NBKFlexibleWidthKit +import NBKSignedKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Signed x Division x UIntXL +//*============================================================================* + +final class NBKSignedBenchmarksOnDivisionAsSIntXL: XCTestCase { + + typealias T = NBKSigned + typealias M = NBKSigned.Magnitude + typealias D = NBKSigned.Digit + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testQuotientAndRemainder() { + var lhs = NBK.blackHoleIdentity(T(M(x64:[~0, ~1, ~2, ~3] as X))) + var rhs = NBK.blackHoleIdentity(T(M(x64:[ 0, 1, 2, 3] as X))) + + for _ in 0 ..< 250_000 { + NBK.blackHole(lhs.quotientAndRemainder(dividingBy: rhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Digit + //=------------------------------------------------------------------------= + + func testQuotientAndRemainderDividingByDigit() { + var lhs = NBK.blackHoleIdentity(T(M(x64:[~0, ~1, ~2, ~3] as X))) + var rhs = NBK.blackHoleIdentity(D.max) + + for _ in 0 ..< 250_000 { + NBK.blackHole(lhs.quotientAndRemainder(dividingBy: rhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Full Width + //=------------------------------------------------------------------------= + + func testDividingFullWidthAs256() { + var lhs = NBK.blackHoleIdentity(T(M(x64:[~0, ~0, ~0, ~0, ~1, ~0, ~0, ~0] as X))) + var rhs = NBK.blackHoleIdentity(T(M(x64:[~0, ~0, ~0, ~0] as X))) + + for _ in 0 ..< 250_000 { + NBK.blackHole(lhs.quotientAndRemainder(dividingBy: rhs)) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } +} + +#endif diff --git a/Tests/NBKSignedKitBenchmarks/NBKSigned+Multiplication.swift b/Tests/NBKSignedKitBenchmarks/NBKSigned+Multiplication.swift new file mode 100644 index 00000000..c29e1442 --- /dev/null +++ b/Tests/NBKSignedKitBenchmarks/NBKSigned+Multiplication.swift @@ -0,0 +1,62 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if !DEBUG + +import NBKCoreKit +import NBKFlexibleWidthKit +import NBKSignedKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Signed x Multiplication x UIntXL +//*============================================================================* + +final class NBKSignedBenchmarksOnMultiplicationAsSIntXL: XCTestCase { + + typealias T = NBKSigned + typealias M = NBKSigned.Magnitude + typealias D = NBKSigned.Digit + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testMultiplied() { + var lhs = NBK.blackHoleIdentity(T(M(x64:[~1, ~2, ~3, ~4] as X))) + var rhs = NBK.blackHoleIdentity(T(M(x64:[ 1, 2, 3, 4] as X))) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs * rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Digit + //=------------------------------------------------------------------------= + + func testMultipliedByDigit() { + var lhs = NBK.blackHoleIdentity(T(M(x64:[~1, ~2, ~3, ~4] as X))) + var rhs = NBK.blackHoleIdentity(D.max) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs * rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } +} + +#endif diff --git a/Tests/NBKSignedKitBenchmarks/NBKSigned+Subtraction.swift b/Tests/NBKSignedKitBenchmarks/NBKSigned+Subtraction.swift new file mode 100644 index 00000000..5c93eaf3 --- /dev/null +++ b/Tests/NBKSignedKitBenchmarks/NBKSigned+Subtraction.swift @@ -0,0 +1,84 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if !DEBUG + +import NBKCoreKit +import NBKFlexibleWidthKit +import NBKSignedKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Signed x Subtraction x UIntXL +//*============================================================================* + +final class NBKSignedBenchmarksOnSubtractionAsSIntXL: XCTestCase { + + typealias T = NBKSigned + typealias M = NBKSigned.Magnitude + typealias D = NBKSigned.Digit + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testSubtract() { + var lhs = NBK.blackHoleIdentity(T(M(x64:[~0, ~1, ~2, ~3] as X))) + var rhs = NBK.blackHoleIdentity(T(M(x64:[ 0, 1, 2, 3] as X))) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs -= rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testSubtracting() { + var lhs = NBK.blackHoleIdentity(T(M(x64:[~0, ~1, ~2, ~3] as X))) + var rhs = NBK.blackHoleIdentity(T(M(x64:[ 0, 1, 2, 3] as X))) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs - rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Digit + //=------------------------------------------------------------------------= + + func testSubtractDigit() { + var lhs = NBK.blackHoleIdentity(T(M(x64:[~0, ~1, ~2, ~3] as X))) + var rhs = NBK.blackHoleIdentity(D.max) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(lhs -= rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } + + func testSubtractingDigit() { + var lhs = NBK.blackHoleIdentity(T(M(x64:[~0, ~1, ~2, ~3] as X))) + var rhs = NBK.blackHoleIdentity(D.max) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(lhs - rhs) + NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHoleInoutIdentity(&rhs) + } + } +} + +#endif diff --git a/Tests/NBKSignedKitBenchmarks/NBKSigned+Text.swift b/Tests/NBKSignedKitBenchmarks/NBKSigned+Text.swift new file mode 100644 index 00000000..586b9793 --- /dev/null +++ b/Tests/NBKSignedKitBenchmarks/NBKSigned+Text.swift @@ -0,0 +1,86 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if !DEBUG + +import NBKCoreKit +import NBKFlexibleWidthKit +import NBKSignedKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Signed x Text x UIntXL +//*============================================================================* + +final class NBKSignedBenchmarksOnTextAsSIntXL: XCTestCase { + + typealias T = NBKSigned + typealias M = NBKSigned.Magnitude + + //=------------------------------------------------------------------------= + // MARK: State + //=------------------------------------------------------------------------= + + static let decoded = NBK.blackHoleIdentity(T(encoded, radix: 16)!) + static let encoded = NBK.blackHoleIdentity(String(repeating: "1", count: 64)) + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testDecodingRadix10() { + var radix = NBK.blackHoleIdentity(10) + var encoded = NBK.blackHoleIdentity(Self.encoded) + + for _ in 0 ..< 250_000 { + NBK.blackHole(T(encoded, radix: radix)!) + NBK.blackHoleInoutIdentity(&radix) + NBK.blackHoleInoutIdentity(&encoded) + } + } + + func testDecodingRadix16() { + var radix = NBK.blackHoleIdentity(16) + var encoded = NBK.blackHoleIdentity(Self.encoded) + + for _ in 0 ..< 250_000 { + NBK.blackHole(T(encoded, radix: radix)!) + NBK.blackHoleInoutIdentity(&radix) + NBK.blackHoleInoutIdentity(&encoded) + } + } + + func testEncodingRadix10() { + var radix = NBK.blackHoleIdentity(10) + var decoded = NBK.blackHoleIdentity(Self.decoded) + + for _ in 0 ..< 250_000 { + NBK.blackHole(String(decoded, radix: radix)) + NBK.blackHoleInoutIdentity(&radix) + NBK.blackHoleInoutIdentity(&decoded) + } + } + + func testEncodingRadix16() { + var radix = NBK.blackHoleIdentity(16) + var decoded = NBK.blackHoleIdentity(Self.decoded) + + for _ in 0 ..< 250_000 { + NBK.blackHole(String(decoded, radix: radix)) + NBK.blackHoleInoutIdentity(&radix) + NBK.blackHoleInoutIdentity(&decoded) + } + } +} + +#endif From fbe135fe9a9486c52d17c8e78bc49717dc5fffe0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sat, 16 Sep 2023 08:08:27 +0200 Subject: [PATCH 074/133] [NBKFlexibleWidthKit] Dropped IntXL (#33) (#81). --- ...th+Protocols.swift => IntXLOrUIntXL.swift} | 0 .../NBKFlexibleWidth+Addition+Digit.swift | 36 -- .../NBKFlexibleWidth+Addition.swift | 36 -- .../NBKFlexibleWidth+Bits.swift | 57 --- .../NBKFlexibleWidth+Comparisons.swift | 97 ---- .../NBKFlexibleWidth+Complements.swift | 61 --- .../NBKFlexibleWidth+Division+Digit.swift | 41 -- .../NBKFlexibleWidth+Division.swift | 40 -- .../NBKFlexibleWidth+Literals.swift | 74 +-- .../NBKFlexibleWidth+Logic.swift | 51 -- ...BKFlexibleWidth+Multiplication+Digit.swift | 20 - .../NBKFlexibleWidth+Multiplication.swift | 22 +- .../NBKFlexibleWidth+Numbers.swift | 92 +--- .../NBKFlexibleWidth+Shifts.swift | 139 ------ .../NBKFlexibleWidth+Subtraction+Digit.swift | 36 -- .../NBKFlexibleWidth+Subtraction.swift | 36 -- .../NBKFlexibleWidth+Text.swift | 41 +- .../NBKFlexibleWidth+Update.swift | 21 - .../NBKFlexibleWidth+Words.swift | 130 ----- .../NBKFlexibleWidth.swift | 56 +-- .../NBKFlexibleWidth+Addition.swift | 61 --- .../NBKFlexibleWidth+Bits.swift | 104 ---- .../NBKFlexibleWidth+Comparisons.swift | 130 ----- .../NBKFlexibleWidth+Complements.swift | 139 ------ .../NBKFlexibleWidth+Division.swift | 126 +---- .../NBKFlexibleWidth+Multiplication.swift | 39 -- .../NBKFlexibleWidth+Numbers.swift | 398 --------------- .../NBKFlexibleWidth+Shifts.swift | 132 ----- .../NBKFlexibleWidth+Subtraction.swift | 61 --- .../NBKFlexibleWidth+Text.swift | 90 ---- .../NBKFlexibleWidth+Words.swift | 26 - .../NBKFlexibleWidth.swift | 32 +- .../NBKFlexibleWidth+Addition.swift | 95 ---- .../NBKFlexibleWidth+Bits.swift | 113 ----- .../NBKFlexibleWidth+Comparisons.swift | 310 ------------ .../NBKFlexibleWidth+Complements.swift | 99 ---- .../NBKFlexibleWidth+Division.swift | 130 +---- .../NBKFlexibleWidth+Literals.swift | 77 --- .../NBKFlexibleWidth+Logic.swift | 41 +- .../NBKFlexibleWidth+Multiplication.swift | 60 +-- .../NBKFlexibleWidth+Numbers.swift | 283 ----------- .../NBKFlexibleWidth+Shifts.swift | 118 ----- .../NBKFlexibleWidth+Subtraction.swift | 95 ---- .../NBKFlexibleWidth+Text.swift | 457 ------------------ .../NBKFlexibleWidth+Words.swift | 76 --- .../NBKFlexibleWidth.swift | 71 +-- 46 files changed, 41 insertions(+), 4408 deletions(-) rename Sources/NBKFlexibleWidthKit/{NBKFlexibleWidth+Protocols.swift => IntXLOrUIntXL.swift} (100%) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Protocols.swift b/Sources/NBKFlexibleWidthKit/IntXLOrUIntXL.swift similarity index 100% rename from Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Protocols.swift rename to Sources/NBKFlexibleWidthKit/IntXLOrUIntXL.swift diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift index 822a848e..202b8d91 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift @@ -9,42 +9,6 @@ import NBKCoreKit -//*============================================================================* -// MARK: * NBK x Flexible Width x Addition x Digit x Signed -//*============================================================================* - -extension NBKFlexibleWidth { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @_disfavoredOverload @inlinable public static func +=(lhs: inout Self, rhs: Int) { - lhs.add(rhs, at: Int.zero) - } - - @_disfavoredOverload @inlinable public static func +(lhs: Self, rhs: Int) -> Self { - lhs.adding(rhs, at: Int.zero) - } - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @_disfavoredOverload @inlinable public mutating func add(_ other: Int, at index: Int) { - if self.sign == Sign(other.isLessThanZero) { - self.magnitude.add(other.magnitude, at: index) - } else if self.magnitude.subtractReportingOverflow(other.magnitude, at: index) { - self.sign.toggle() - self.magnitude.formTwosComplement() - } - } - - @_disfavoredOverload @inlinable public func adding(_ other: Int, at index: Int) -> Self { - var result = self; result.add(other, at: index); return result - } -} - //*============================================================================* // MARK: * NBK x Flexible Width x Addition x Digit x Unsigned //*============================================================================* diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift index 6fbce02b..f2f7703e 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift @@ -9,42 +9,6 @@ import NBKCoreKit -//*============================================================================* -// MARK: * NBK x Flexible Width x Addition x Signed -//*============================================================================* - -extension NBKFlexibleWidth { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable public static func +=(lhs: inout Self, rhs: Self) { - lhs.add(rhs, at: Int.zero) - } - - @inlinable public static func +(lhs: Self, rhs: Self) -> Self { - lhs.adding(rhs, at: Int.zero) - } - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable public mutating func add(_ other: Self, at index: Int) { - if self.sign == other.sign { - self.magnitude.add(other.magnitude, at: index) - } else if self.magnitude.subtractReportingOverflow(other.magnitude, at: index) { - self.sign.toggle() - self.magnitude.formTwosComplement() - } - } - - @inlinable public func adding(_ other: Self, at index: Int) -> Self { - var result = self; result.add(other, at: index); return result - } -} - //*============================================================================* // MARK: * NBK x Flexible Width x Addition x Unsigned //*============================================================================* diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift index 514adb80..f2e99e0e 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift @@ -9,63 +9,6 @@ import NBKCoreKit -//*============================================================================* -// MARK: * NBK x Flexible Width x Bits x Signed -//*============================================================================* - -extension NBKFlexibleWidth { - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - @inlinable public init(bit: Bool) { - self.init(digit: Digit(bit: bit)) - } - - //=------------------------------------------------------------------------= - // MARK: Accessors - //=------------------------------------------------------------------------= - - @inlinable public var bitWidth: Int { - self.magnitude.bitWidth + self.storageBitWidthNeeded - } - - @inlinable public var nonzeroBitCount: Int { - if self.isLessThanZero { - let s = self.magnitude.storage.elements.withUnsafeBufferPointer(NBK.nonzeroBitCount(twosComplementOf:)) - return s + self.storageBitWidthNeeded - } else { - return self.magnitude.nonzeroBitCount - } - } - - @inlinable public var leadingZeroBitCount: Int { - self.isLessThanZero ? Int.zero : (self.magnitude.leadingZeroBitCount + self.storageBitWidthNeeded) - } - - @inlinable public var trailingZeroBitCount: Int { - self.magnitude.trailingZeroBitCount - } - - @inlinable public var mostSignificantBit: Bool { - self.isLessThanZero - } - - @inlinable public var leastSignificantBit: Bool { - self.magnitude.leastSignificantBit - } - - //=------------------------------------------------------------------------= - // MARK: Utilities x Private - //=------------------------------------------------------------------------= - - /// The number of extra bits in `bitWidth` compared to `magnitude/bitWidth`. - @inlinable var storageBitWidthNeeded: Int { - self.storageNeedsOneMoreWord ? UInt.bitWidth : Int.zero - } -} - //*============================================================================* // MARK: * NBK x Flexible Width x Bits x Unsigned //*============================================================================* diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift index f4bb0390..38455e25 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift @@ -9,103 +9,6 @@ import NBKCoreKit -//*============================================================================* -// MARK: * NBK x Flexible Width x Comparisons x Signed -//*============================================================================* - -extension NBKFlexibleWidth { - - //=------------------------------------------------------------------------= - // MARK: Accessors - //=------------------------------------------------------------------------= - - @inlinable public var isZero: Bool { - self.magnitude.isZero - } - - @inlinable public var isLessThanZero: Bool { - self.sign != Sign.plus && !self.isZero - } - - @inlinable public var isMoreThanZero: Bool { - self.sign == Sign.plus && !self.isZero - } - - @inlinable public var isPowerOf2: Bool { - self.sign == Sign.plus && self.magnitude.isPowerOf2 - } - - @inlinable public func signum() -> Int { - self.isZero ? 0 : self.sign == Sign.plus ? 1 : -1 - } - - //=------------------------------------------------------------------------= - // MARK: Utilities - //=------------------------------------------------------------------------= - - @inlinable public func hash(into hasher: inout Hasher) { - hasher.combine(self.sign == Sign.minus && self.isZero ? Sign.plus : self.sign) - hasher.combine(self.magnitude) - } - - //=------------------------------------------------------------------------= - // MARK: Utilities - //=------------------------------------------------------------------------= - - @inlinable public static func ==(lhs: Self, rhs: Self) -> Bool { - lhs.compared(to: rhs).isZero - } - - @inlinable public static func <(lhs: Self, rhs: Self) -> Bool { - lhs.compared(to: rhs) == -1 - } - - @inlinable public func compared(to other: Self) -> Int { - Self.compare(self, to: other, magnitude:{ $0.compared(to: $1) }) - } - - @inlinable public func compared(to other: Self, at index: Int) -> Int { - Self.compare(self, to: other, magnitude:{ $0.compared(to: $1, at: index) }) - } - - @_disfavoredOverload @inlinable public func compared(to other: Digit) -> Int { - Self.compare(self, to: other, magnitude:{ $0.compared(to: $1) }) - } - - @_disfavoredOverload @inlinable public func compared(to other: Digit, at index: Int) -> Int { - Self.compare(self, to: other, magnitude:{ $0.compared(to: $1, at: index) }) - } - - //=------------------------------------------------------------------------= - // MARK: Accessors x Private - //=------------------------------------------------------------------------= - - @inlinable var isTwosComplementMinValue: Bool { - self.compared(to: Int.min, at: self.magnitude.storage.elements.count - 1).isZero - } -} - -//=----------------------------------------------------------------------------= -// MARK: + Algorithms -//=----------------------------------------------------------------------------= - -extension NBKFlexibleWidth { - - //=------------------------------------------------------------------------= - // MARK: Utilities x Private - //=------------------------------------------------------------------------= - - @inlinable static func compare(_ lhs: Self, to rhs: T, magnitude: (Magnitude, T.Magnitude) -> Int) -> Int where T: NBKBinaryInteger { - //=--------------------------------------= - if lhs.sign.bit != rhs.isLessThanZero { - return lhs.isZero && rhs.isZero ? 0 : lhs.sign.bit ? -1 : 1 - } - //=--------------------------------------= - let magnitude = magnitude(lhs.magnitude, rhs.magnitude) - return lhs.sign.bit ? magnitude.negated() : magnitude - } -} - //*============================================================================* // MARK: * NBK x Flexible Width x Comparisons x Unsigned //*============================================================================* diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements.swift index 3ac70215..d999a146 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements.swift @@ -9,67 +9,6 @@ import NBKCoreKit -//*============================================================================* -// MARK: * NBK x Flexible Width x Complements x Signed -//*============================================================================* - -extension NBKFlexibleWidth { - - //=------------------------------------------------------------------------= - // MARK: Details x Two's Complement - //=------------------------------------------------------------------------= - - @inlinable public mutating func formOnesComplement() { - self.add(1 as Int, at: Int.zero) - self.negate() - } - - @inlinable public func onesComplement() -> Self { - var result = self; result.formOnesComplement(); return result - } - - //=------------------------------------------------------------------------= - // MARK: Details x Two's Complement - //=------------------------------------------------------------------------= - - @inlinable public mutating func formTwosComplementReportingOverflow() -> Bool { - self.isTwosComplementMinValue || self.negateReportingOverflow() - } - - @inlinable public func twosComplementReportingOverflow() -> PVO { - var partialValue = self - let overflow = partialValue.formTwosComplementReportingOverflow() - return PVO(partialValue, overflow) - } - - @inlinable public mutating func formTwosComplementSubsequence(_ carry: Bool) -> Bool { - switch carry { - case true : return self.formTwosComplementReportingOverflow() - case false: self.formOnesComplement(); return false as Bool } - } - - @inlinable public func twosComplementSubsequence(_ carry: Bool) -> PVO { - var partialValue = self - let overflow = partialValue.formTwosComplementSubsequence(carry) - return PVO(partialValue, overflow) - } - - //=------------------------------------------------------------------------= - // MARK: Details x Additive Inverse - //=------------------------------------------------------------------------= - - @inlinable public mutating func negateReportingOverflow() -> Bool { - self.sign.toggle() - return false as Bool - } - - @inlinable public func negatedReportingOverflow() -> PVO { - var partialValue = self - let overflow = partialValue.negateReportingOverflow() - return PVO(partialValue, overflow) - } -} - //*============================================================================* // MARK: * NBK x Flexible Width x Complements x Unsigned //*============================================================================* diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.swift index c2848961..fc0cac04 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.swift @@ -9,47 +9,6 @@ import NBKCoreKit -//*============================================================================* -// MARK: * NBK x Flexible Width x Division x Digit x Signed -//*============================================================================* - -extension NBKFlexibleWidth { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @_disfavoredOverload @inlinable public mutating func divideReportingOverflow(by other: Digit) -> Bool { - let pvo: PVO = self.dividedReportingOverflow(by: other) - self = pvo.partialValue - return pvo.overflow as Bool - } - - @_disfavoredOverload @inlinable public func dividedReportingOverflow(by other: Digit) -> PVO { - let qro: PVO> = self.quotientAndRemainderReportingOverflow(dividingBy: other) - return PVO(qro.partialValue.quotient, qro.overflow) - } - - @_disfavoredOverload @inlinable public mutating func formRemainderReportingOverflow(dividingBy other: Digit) -> Bool { - let pvo: PVO = self.remainderReportingOverflow(dividingBy: other) - self = Self(digit: pvo.partialValue) - return pvo.overflow as Bool - } - - @_disfavoredOverload @inlinable public func remainderReportingOverflow(dividingBy other: Digit) -> PVO { - let qro: PVO> = self.quotientAndRemainderReportingOverflow(dividingBy: other) - return PVO(qro.partialValue.remainder, qro.overflow) - } - - @_disfavoredOverload @inlinable public func quotientAndRemainderReportingOverflow(dividingBy other: Digit) -> PVO> { - let otherSign = Sign(other.isLessThanZero) - let qro: PVO> = self.magnitude.quotientAndRemainderReportingOverflow(dividingBy: other.magnitude) - let quotient = Self(sign: self.sign ^ otherSign, magnitude: qro.partialValue.quotient ) - let remainder = Self.Digit.init(sign: self.sign, magnitude: qro.partialValue.remainder)! - return PVO(QR(quotient, remainder), qro.overflow) - } -} - //*============================================================================* // MARK: * NBK x Flexible Width x Division x Digit x Unsigned //*============================================================================* diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift index a42ddacc..84d92f77 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift @@ -9,46 +9,6 @@ import NBKCoreKit -//*============================================================================* -// MARK: * NBK x Flexible Width x Division x Signed -//*============================================================================* - -extension NBKFlexibleWidth { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable public mutating func divideReportingOverflow(by other: Self) -> Bool { - let pvo: PVO = self.dividedReportingOverflow(by: other) - self = pvo.partialValue - return pvo.overflow as Bool - } - - @inlinable public func dividedReportingOverflow(by other: Self) -> PVO { - let qro: PVO> = self.quotientAndRemainderReportingOverflow(dividingBy: other) - return PVO(qro.partialValue.quotient, qro.overflow) - } - - @inlinable public mutating func formRemainderReportingOverflow(dividingBy other: Self) -> Bool { - let pvo: PVO = self.remainderReportingOverflow(dividingBy: other) - self = pvo.partialValue - return pvo.overflow as Bool - } - - @inlinable public func remainderReportingOverflow(dividingBy other: Self) -> PVO { - let qro: PVO> = self.quotientAndRemainderReportingOverflow(dividingBy: other) - return PVO(qro.partialValue.remainder, qro.overflow) - } - - @inlinable public func quotientAndRemainderReportingOverflow(dividingBy other: Self) -> PVO> { - let qro: PVO> = self.magnitude.quotientAndRemainderReportingOverflow(dividingBy: other.magnitude) - let quotient = Self(sign: self.sign ^ other.sign, magnitude: qro.partialValue.quotient ) - let remainder = Self(sign: self.sign, /*------*/ magnitude: qro.partialValue.remainder) - return PVO(QR(quotient, remainder), qro.overflow) - } -} - //*============================================================================* // MARK: * NBK x Flexible Width x Division x Unsigned //*============================================================================* diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Literals.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Literals.swift index 3698c39a..a1e07fb6 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Literals.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Literals.swift @@ -9,76 +9,6 @@ import NBKCoreKit -//*============================================================================* -// MARK: * NBK x Flexible Width x Literals x Signed -//*============================================================================* - -extension NBKFlexibleWidth { - - //=-------------------------------------------------------------------------= - // MARK: Details x Integer Literal Type - //=-------------------------------------------------------------------------= - #if SBI && swift(>=5.8) - - @inlinable public init(integerLiteral source: StaticBigInt) { - let sourceIsLessThanZero = source.signum() == -1 - //=--------------------------------------= - self.init(sign: Sign.plus, magnitude: Magnitude(truncatingIntegerLiteral: source)) - //=--------------------------------------= - if sourceIsLessThanZero { - self.sign.toggle() - self.magnitude.formTwosComplement() - } - } - - #else - - @inlinable public init(integerLiteral source: Digit.IntegerLiteralType) { - self.init(digit: Digit(integerLiteral: source)) - } - - #endif - //=------------------------------------------------------------------------= - // MARK: Details x String Literal Type - //=------------------------------------------------------------------------= - - /// Creates a new instance from the given string literal. - /// - /// The string literal may contain a plus or minus sign (+ or -), followed by - /// an optional radix indicator (0b, 0o or 0x), then one or more numeric digits - /// (0-9) or letters (a-z or A-Z). If the string literal uses an invalid format, - /// or its value cannot be represented, a runtime error may occur. - /// - /// ``` - /// ┌───────── → ─────────────┐ - /// │ literal │ self │ - /// ├───────── → ─────────────┤ - /// │ "123" │ Int256( 123) │ - /// │ "+0x123" │ Int256( 291) │ - /// │ "-0x123" │ Int256(-291) │ - /// │ "~OX123" │ error │ - /// └───────── → ─────────────┘ - /// ``` - /// - /// - Note: The decoding strategy is case insensitive. - /// - @inlinable public init(stringLiteral source: StaticString) { - if let value = Self(exactlyStringLiteral: source) { self = value } else { - preconditionFailure("\(Self.description) cannot represent \(source)") - } - } - - @inlinable init?(exactlyStringLiteral source: StaticString) { - if let value: Self = source.withUTF8Buffer({ utf8 in - let components = NBK.makeIntegerComponentsByDecodingRadix(utf8: utf8) - let radix = NBK.AnyRadixSolution(components.radix) - let digits = NBK.UnsafeUTF8(rebasing: components.body ) - guard let magnitude = Magnitude(digits: digits, radix: radix) else { return nil } - return Self(sign: components.sign, magnitude: magnitude) - }){ self = value } else { return nil } - } -} - //*============================================================================* // MARK: * NBK x Flexible Width x Literals x Unsigned //*============================================================================* @@ -91,11 +21,9 @@ extension NBKFlexibleWidth.Magnitude { #if SBI && swift(>=5.8) @inlinable public init(integerLiteral source: StaticBigInt) { - guard let value = Self(exactlyIntegerLiteral: source) else { + if let value = Self(exactlyIntegerLiteral: source) { self = value } else { preconditionFailure("\(Self.description) cannot represent \(source)") } - - self = value } @inlinable init?(exactlyIntegerLiteral source: StaticBigInt) { diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift index bb73e7db..ec993ea7 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift @@ -9,57 +9,6 @@ import NBKCoreKit -//*============================================================================* -// MARK: * NBK x Flexible Width x Logic x Signed -//*============================================================================* - -extension NBKFlexibleWidth { - - //=------------------------------------------------------------------------= - // MARK: Transformations x NOT - //=------------------------------------------------------------------------= - - @inlinable public static prefix func ~(x: Self) -> Self { - x.onesComplement() - } - - //=------------------------------------------------------------------------= - // MARK: Transformations x AND - //=------------------------------------------------------------------------= - - @inlinable public static func &=(lhs: inout Self, rhs: Self) { - fatalError("TODO") - } - - @inlinable public static func &(lhs: Self, rhs: Self) -> Self { - var lhs = lhs; lhs &= rhs; return lhs - } - - //=------------------------------------------------------------------------= - // MARK: Transformations x OR - //=------------------------------------------------------------------------= - - @inlinable public static func |=(lhs: inout Self, rhs: Self) { - fatalError("TODO") - } - - @inlinable public static func |(lhs: Self, rhs: Self) -> Self { - var lhs = lhs; lhs |= rhs; return lhs - } - - //=------------------------------------------------------------------------= - // MARK: Transformations x XOR - //=------------------------------------------------------------------------= - - @inlinable public static func ^=(lhs: inout Self, rhs: Self) { - fatalError("TODO") - } - - @inlinable public static func ^(lhs: Self, rhs: Self) -> Self { - var lhs = lhs; lhs ^= rhs; return lhs - } -} - //*============================================================================* // MARK: * NBK x Flexible Width x Logic x Unsigned //*============================================================================* diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift index 4a8c5a15..2f14ec72 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift @@ -9,26 +9,6 @@ import NBKCoreKit -//*============================================================================* -// MARK: * NBK x Flexible Width x Multiplication x Digit x Signed -//*============================================================================* - -extension NBKFlexibleWidth { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @_disfavoredOverload @inlinable public static func *=(lhs: inout Self, rhs: Int) { - lhs.sign ^= Sign(rhs.isLessThanZero) - lhs.magnitude *= rhs.magnitude as UInt - } - - @_disfavoredOverload @inlinable public static func *(lhs: Self, rhs: Int) -> Self { - Self(sign: lhs.sign ^ Sign(rhs.isLessThanZero), magnitude: lhs.magnitude * rhs.magnitude) - } -} - //*============================================================================* // MARK: * NBK x Flexible Width x Multiplication x Digit x Unsigned //*============================================================================* diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift index 9105df3d..78c4d425 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift @@ -9,26 +9,6 @@ import NBKCoreKit -//*============================================================================* -// MARK: * NBK x Flexible Width x Multiplication x Signed -//*============================================================================* - -extension NBKFlexibleWidth { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable public static func *=(lhs: inout Self, rhs: Self) { - lhs.sign ^= rhs.sign - lhs.magnitude *= rhs.magnitude as Magnitude - } - - @inlinable public static func *(lhs: Self, rhs: Self) -> Self { - Self(sign: lhs.sign ^ Sign(rhs.isLessThanZero), magnitude: lhs.magnitude * rhs.magnitude) - } -} - //*============================================================================* // MARK: * NBK x Flexible Width x Multiplication x Unsigned //*============================================================================* @@ -49,7 +29,7 @@ extension NBKFlexibleWidth.Magnitude { } //*============================================================================* -// MARK: * NBK x Resizable Width x Multiplication x Unsigned +// MARK: * NBK x Flexible Width x Multiplication x Unsigned x Storage //*============================================================================* extension NBKFlexibleWidth.Magnitude.Storage { diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift index 31347a0e..14557ea1 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift @@ -9,84 +9,6 @@ import NBKCoreKit -//*============================================================================* -// MARK: * NBK x Flexible Width x Numbers x Signed -//*============================================================================* - -extension NBKFlexibleWidth { - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - public static let zero = Self(0) - - //=------------------------------------------------------------------------= - // MARK: Initializers x Digit - //=------------------------------------------------------------------------= - - @inlinable public init(digit: Int) { - let sign = digit.isLessThanZero - let magnitude = Magnitude(digit: digit.magnitude) - self.init(sign: Sign(sign), magnitude: magnitude) - } - - @inlinable public init(digit: Int, at index: Int) { - let sign = digit.isLessThanZero - let magnitude = Magnitude(digit: digit.magnitude, at: index) - self.init(sign: Sign(sign), magnitude: magnitude) - } - - //=------------------------------------------------------------------------= - // MARK: Initializers x Binary Integer - //=------------------------------------------------------------------------= - - @inlinable public init(_ source: some BinaryInteger) { - //=--------------------------------------= - // Magnitude - //=--------------------------------------= - if let source = source as? Magnitude { - self.init(sign: Sign.plus, magnitude: source) - //=--------------------------------------= - // some BinaryInteger - //=--------------------------------------= - } else { - let sign = Sign(source < 0) - let magnitude = Magnitude(source.magnitude) - self.init(sign: sign, magnitude: magnitude) - } - } - - @inlinable public init?(exactly source: some BinaryInteger) { - self.init(source) - } - - @inlinable public init(clamping source: some BinaryInteger) { - self.init(source) - } - - @inlinable public init(truncatingIfNeeded source: some BinaryInteger) { - self.init(source) - } - - //=------------------------------------------------------------------------= - // MARK: Initializers x Binary Floating Point - //=------------------------------------------------------------------------= - - @inlinable public init(_ source: some BinaryFloatingPoint) { - guard let result = Self(exactly: source.rounded(.towardZero)) else { - preconditionFailure("\(Self.description) cannot represent \(source)") - } - - self = result - } - - @inlinable public init?(exactly source: some BinaryFloatingPoint) { - guard let magnitude = Magnitude(exactly: source.magnitude) else { return nil } - self.init(sign: source.sign, magnitude: magnitude) - } -} - //*============================================================================* // MARK: * NBK x Flexible Width x Numbers x Unsigned //*============================================================================* @@ -97,17 +19,17 @@ extension NBKFlexibleWidth.Magnitude { // MARK: Constants //=------------------------------------------------------------------------= - public static let zero = Self(0) + public static let zero = Self(digit: 0) //=------------------------------------------------------------------------= // MARK: Initializers x Digit //=------------------------------------------------------------------------= @inlinable public init(digit: UInt) { - let storage = Storage(unchecked: [digit]) - self.init(unchecked: storage) + self.init(unchecked: Storage(unchecked: [digit])) } + // #warning("unchecked should be unchecked...") @inlinable public init(digit: UInt, at index: Int) { var storage = Storage(repeating: 0 as UInt, count: index + 1) storage.elements[index] = digit @@ -120,11 +42,9 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @inlinable public init(_ source: some BinaryInteger) { - guard let result = Self(exactly: source) else { + if let value = Self(exactly: source) { self = value } else { preconditionFailure("\(Self.description) cannot represent \(source)") } - - self = result } @inlinable public init?(exactly source: some BinaryInteger) { @@ -145,11 +65,9 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @inlinable public init(_ source: some BinaryFloatingPoint) { - guard let value = Self(exactly: source.rounded(.towardZero)) else { + if let value = Self(exactly: source.rounded(.towardZero)) { self = value } else { preconditionFailure("\(Self.description) cannot represent \(source)") } - - self = value } @inlinable public init?(exactly source: some BinaryFloatingPoint) { diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift index 1dc94523..af0454c8 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift @@ -9,145 +9,6 @@ import NBKCoreKit -//*============================================================================* -// MARK: * NBK x Flexible Width x Shifts x Signed -//*============================================================================* -//=----------------------------------------------------------------------------= -// MARK: + Left -//=----------------------------------------------------------------------------= - -extension NBKFlexibleWidth { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable public static func <<=(lhs: inout Self, rhs: some BinaryInteger) { - lhs.bitshiftLeftSmart(by: NBK.initOrBitCast(clamping: rhs, as: Int.self)) - } - - @inlinable public static func <<(lhs: Self, rhs: some BinaryInteger) -> Self { - var lhs = lhs; lhs <<= rhs; return lhs - } - - //=------------------------------------------------------------------------= - // MARK: Transformations x Int - //=------------------------------------------------------------------------= - - @inlinable public mutating func bitshiftLeftSmart(by distance: Int) { - if distance >= 0 { - self.bitshiftLeft (by: distance) - } else { - self.bitshiftRight(by: NBK.initOrBitCast(clamping: distance.magnitude, as: Int.self)) - } - } - - @inlinable public func bitshiftedLeftSmart(by distance: Int) -> Self { - var result = self; result.bitshiftLeftSmart(by: distance); return result - } - - @inlinable public mutating func bitshiftLeft(by distance: Int) { - precondition(distance >= 0, NBK.callsiteOutOfBoundsInfo()) - let major = NBK .quotientDividingByBitWidthAssumingIsAtLeastZero(distance) - let minor = NBK.remainderDividingByBitWidthAssumingIsAtLeastZero(distance) - return self.bitshiftLeft(words: major, bits: minor) - } - - @inlinable public func bitshiftedLeft(by distance: Int) -> Self { - var result = self; result.bitshiftLeft(by: distance); return result - } - - @inlinable public mutating func bitshiftLeft(words: Int, bits: Int) { - self.magnitude.bitshiftLeft(words: words, bits: bits) - } - - @inlinable public func bitshiftedLeft(words: Int, bits: Int) -> Self { - var result = self; result.bitshiftLeft(words: words, bits: bits); return result - } - - @inlinable public mutating func bitshiftLeft(words: Int) { - self.magnitude.bitshiftLeft(words: words) - } - - @inlinable public func bitshiftedLeft(words: Int) -> Self { - var result = self; result.bitshiftLeft(words: words); return result - } -} - -//=----------------------------------------------------------------------------= -// MARK: + Right -//=----------------------------------------------------------------------------= - -extension NBKFlexibleWidth { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable public static func >>=(lhs: inout Self, rhs: some BinaryInteger) { - lhs.bitshiftRightSmart(by: NBK.initOrBitCast(clamping: rhs, as: Int.self)) - } - - @inlinable public static func >>(lhs: Self, rhs: some BinaryInteger) -> Self { - var lhs = lhs; lhs >>= rhs; return lhs - } - - //=------------------------------------------------------------------------= - // MARK: Transformations x Int - //=------------------------------------------------------------------------= - - @inlinable public mutating func bitshiftRightSmart(by distance: Int) { - if distance >= 0 { - self.bitshiftRight(by: distance) - } else { - self.bitshiftLeft (by: NBK.initOrBitCast(clamping: distance.magnitude, as: Int.self)) - } - } - - @inlinable public func bitshiftedRightSmart(by distance: Int) -> Self { - var result = self; result.bitshiftRightSmart(by: distance); return result - } - - @inlinable public mutating func bitshiftRight(by distance: Int) { - precondition(distance >= 0, NBK.callsiteOutOfBoundsInfo()) - let major = NBK .quotientDividingByBitWidthAssumingIsAtLeastZero(distance) - let minor = NBK.remainderDividingByBitWidthAssumingIsAtLeastZero(distance) - return self.bitshiftRight(words: major, bits: minor) - } - - @inlinable public func bitshiftedRight(by distance: Int) -> Self { - var result = self; result.bitshiftRight(by: distance); return result - } - - @inlinable public mutating func bitshiftRight(words: Int, bits: Int) { - let minus = self.isLessThanZero - //=--------------------------------------= - self.magnitude.bitshiftRight(words: words, bits: bits) - //=--------------------------------------= - if minus, self.isZero { - self.magnitude.update(1 as UInt) - } - } - - @inlinable public func bitshiftedRight(words: Int, bits: Int) -> Self { - var result = self; result.bitshiftRight(words: words, bits: bits); return result - } - - @inlinable public mutating func bitshiftRight(words: Int) { - let minus = self.isLessThanZero - //=--------------------------------------= - self.magnitude.bitshiftRight(words: words) - //=--------------------------------------= - if minus, self.isZero { - self.magnitude.update(1 as UInt) - } - } - - @inlinable public func bitshiftedRight(words: Int) -> Self { - var result = self; result.bitshiftRight(words: words); return result - } -} - //*============================================================================* // MARK: * NBK x Flexible Width x Shifts x Unsigned //*============================================================================* diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift index af500992..9a739721 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift @@ -9,42 +9,6 @@ import NBKCoreKit -//*============================================================================* -// MARK: * NBK x Flexible Width x Subtraction x Digit x Signed -//*============================================================================* - -extension NBKFlexibleWidth { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @_disfavoredOverload @inlinable public static func -=(lhs: inout Self, rhs: Int) { - lhs.subtract(rhs, at: Int.zero) - } - - @_disfavoredOverload @inlinable public static func -(lhs: Self, rhs: Int) -> Self { - lhs.subtracting(rhs, at: Int.zero) - } - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @_disfavoredOverload @inlinable public mutating func subtract(_ other: Int, at index: Int) { - if self.sign != Sign(other.isLessThanZero) { - self.magnitude.add(other.magnitude, at: index) - } else if self.magnitude.subtractReportingOverflow(other.magnitude, at: index) { - self.sign.toggle() - self.magnitude.formTwosComplement() - } - } - - @_disfavoredOverload @inlinable public func subtracting(_ other: Int, at index: Int) -> Self { - var result = self; result.subtract(other, at: index); return result - } -} - //*============================================================================* // MARK: * NBK x Flexible Width x Subtraction x Digit x Unsigned //*============================================================================* diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift index e642e2f6..43bc14f0 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift @@ -9,42 +9,6 @@ import NBKCoreKit -//*============================================================================* -// MARK: * NBK x Flexible Width x Subtraction -//*============================================================================* - -extension NBKFlexibleWidth { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable public static func -=(lhs: inout Self, rhs: Self) { - lhs.subtract(rhs, at: Int.zero) - } - - @inlinable public static func -(lhs: Self, rhs: Self) -> Self { - lhs.subtracting(rhs, at: Int.zero) - } - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable public mutating func subtract(_ other: Self, at index: Int) { - if self.sign != other.sign { - self.magnitude.add(other.magnitude, at: index) - } else if self.magnitude.subtractReportingOverflow(other.magnitude, at: index) { - self.sign.toggle() - self.magnitude.formTwosComplement() - } - } - - @inlinable public func subtracting(_ other: Self, at index: Int) -> Self { - var result = self; result.subtract(other, at: index); return result - } -} - //*============================================================================* // MARK: * NBK x Flexible Width x Subtraction x Unsigned //*============================================================================* diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text.swift index c9768c0f..dbae4003 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text.swift @@ -9,45 +9,6 @@ import NBKCoreKit -//*============================================================================* -// MARK: * NBK x Flexible Width x Text x Signed -//*============================================================================* - -extension NBKFlexibleWidth { - - //=------------------------------------------------------------------------= - // MARK: Details x Decode - //=------------------------------------------------------------------------= - - @inlinable public init?(_ description: some StringProtocol, radix: Int = 10) { - var description = String(description) - - let value: Optional = description.withUTF8 { utf8 in - let radix = NBK.AnyRadixSolution(radix) - let components = NBK.makeIntegerComponents(utf8: utf8) - let digits = NBK.UnsafeUTF8(rebasing: components.body) - guard let magnitude = Magnitude(digits: digits, radix: radix) else { return nil } - return Self(sign: components.sign, magnitude: magnitude) - } - - if let value { self = value } else { return nil } - } - - //=------------------------------------------------------------------------= - // MARK: Details x Encode - //=------------------------------------------------------------------------= - - @inlinable public func description(radix: Int = 10, uppercase: Bool = false) -> String { - Swift.withUnsafePointer(to: UInt8(ascii: "-")) { minus in - let radix = NBK.AnyRadixSolution(radix) - let alphabet = NBK.MaxRadixAlphabetEncoder(uppercase: uppercase) - let prefix = NBK.UnsafeUTF8(start: minus, count: Int(bit: self.isLessThanZero)) - let suffix = NBK.UnsafeUTF8(start: nil, count: Int.zero) - return self.magnitude.description(radix: radix, alphabet: alphabet, prefix: prefix, suffix: suffix) - } - } -} - //*============================================================================* // MARK: * NBK x Flexible Width x Text x Unsigned //*============================================================================* @@ -97,7 +58,7 @@ extension NBKFlexibleWidth.Magnitude { // MARK: Details x Decode x Private //=------------------------------------------------------------------------= - @inlinable init?(digits: NBK.UnsafeUTF8, radix: NBK.AnyRadixSolution) { + @inlinable init?(digits: NBK.UnsafeUTF8, radix: NBK.AnyRadixSolution) { switch radix.power.isZero { case true: self.init(digits: digits, radix: NBK .PerfectRadixSolution(radix)!) case false: self.init(digits: digits, radix: NBK.ImperfectRadixSolution(radix)!) } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Update.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Update.swift index 0dd89856..f32878b9 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Update.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Update.swift @@ -9,27 +9,6 @@ import NBKCoreKit -//*============================================================================* -// MARK: * NBK x Flexible Width x Update x Signed -//*============================================================================* - -extension NBKFlexibleWidth { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable public mutating func updateZeroValue() { - self.sign = Sign.plus - self.magnitude.updateZeroValue() - } - - @inlinable public mutating func update(_ value: Digit) { - self.sign = Sign(value.isLessThanZero) - self.magnitude.update(value.magnitude) - } -} - //*============================================================================* // MARK: * NBK x Flexible Width x Update x Unsigned //*============================================================================* diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift index f4efc167..0698191a 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift @@ -9,136 +9,6 @@ import NBKCoreKit -//*============================================================================* -// MARK: * NBK x Flexible Width x Words x Signed -//*============================================================================* - -extension NBKFlexibleWidth { - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - /// Creates an instance from the given two's complement machine words. - /// - /// - Note: An empty collection defaults to positive zero. - /// - @inlinable public init(words: some Collection) { - var magnitude = Magnitude.Storage(words: words) - let sign = Sign(magnitude.elements.last!.mostSignificantBit) - //=--------------------------------------= - if sign.bit { - magnitude.formTwosComplement() - } - //=--------------------------------------= - magnitude.normalize() // TODO: consuming - //=--------------------------------------= - self.init(sign: sign, magnitude: Magnitude(unchecked: magnitude)) - } - - //=------------------------------------------------------------------------= - // MARK: Accessors - //=------------------------------------------------------------------------= - - @inlinable public var words: Words { - Words(source: self) - } - - //=------------------------------------------------------------------------= - // MARK: Utilities x Private - //=------------------------------------------------------------------------= - - @inlinable var storageNeedsOneMoreWord: Bool { - if self.isLessThanZero { - return !self.magnitude.storage.withUnsafeBufferPointer({ NBK.mostSignificantBit(twosComplementOf: $0)! }) - } else { - return self.magnitude.storage.elements.last!.mostSignificantBit - } - } - - // #warning("IntXL and UIntXL can share Words") - //*========================================================================* - // MARK: * Words - //*========================================================================* - - @frozen public struct Words: RandomAccessCollection { - - //=--------------------------------------------------------------------= - // MARK: State - //=--------------------------------------------------------------------= - - public var count: Int - @usableFromInline let sign: UInt - @usableFromInline var storage: Magnitude.Storage - - //=--------------------------------------------------------------------= - // MARK: Initializers - //=--------------------------------------------------------------------= - - @inlinable init(source: NBKFlexibleWidth) { - self.count = Int(bit: source.storageNeedsOneMoreWord) - self.sign = UInt(repeating: source.isLessThanZero) - self.storage = source.magnitude.storage - //=----------------------------------= - if !self.sign.isZero { - self.storage.formTwosComplement() - } - //=----------------------------------= - self.count += self.storage.elements.count - } - - //=--------------------------------------------------------------------= - // MARK: Accessors - //=--------------------------------------------------------------------= - - @inlinable public var startIndex: Int { - (0 as Int) - } - - @inlinable public var endIndex: Int { - self.count - } - - @inlinable public subscript(index: Int) -> UInt { - switch index < self.storage.elements.endIndex { - case true: return self.storage.elements[index] - case false: return self.sign } - } - - //=--------------------------------------------------------------------= - // MARK: Utilities - //=--------------------------------------------------------------------= - - @inlinable public func distance(from start: Int, to end: Int) -> Int { - self.storage.elements.distance(from: start, to: end) - } - - @inlinable public func index(after index: Int) -> Int { - self.storage.elements.index(after: index) - } - - @inlinable public func formIndex(after index: inout Int) { - self.storage.elements.formIndex(after: &index) - } - - @inlinable public func index(before index: Int) -> Int { - self.storage.elements.index(before: index) - } - - @inlinable public func formIndex(before index: inout Int) { - self.storage.elements.formIndex(before: &index) - } - - @inlinable public func index(_ index: Int, offsetBy distance: Int) -> Int { - self.storage.elements.index(index, offsetBy: distance) - } - - @inlinable public func index(_ index: Int, offsetBy distance: Int, limitedBy limit: Int) -> Int? { - self.storage.elements.index(index, offsetBy: distance, limitedBy: limit) - } - } -} - //*============================================================================* // MARK: * NBK x Flexible Width x Words x Unsigned //*============================================================================* diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift index d76441e5..7762a41c 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift @@ -14,50 +14,13 @@ import NBKCoreKit //*============================================================================* /// A signed, flexible-width, binary integer. -@frozen public struct NBKFlexibleWidth: NBKSignedInteger, IntXLOrUIntXL { - - public typealias Digit = Int - - public typealias Sign = NBK.Sign - - //=------------------------------------------------------------------------= - // MARK: State - //=------------------------------------------------------------------------= - - /// The sign of this value. - public var sign: Sign - - /// The magnitude of this value. - public var magnitude: Magnitude - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - @inlinable public init(sign: Sign, magnitude: Magnitude) { - self.sign = sign - self.magnitude = magnitude - } - - //=------------------------------------------------------------------------= - // MARK: Utilities - //=------------------------------------------------------------------------= - - /// A `description` of this type. - /// - /// ``` - /// ┌─────────────────────────── → ────────────┐ - /// │ type │ description │ - /// ├─────────────────────────── → ────────────┤ - /// │ NBKFlexibleWidth │ "IntXL" │ - /// │ NBKFlexibleWidth.Magnitude │ "UIntXL" │ - /// └─────────────────────────── → ────────────┘ - /// ``` - /// - @inlinable public static var description: String { - "IntXL" - } - +/// +/// This name reserves a spot for a signed 2's-complement-in-memory integer. +/// +/// - Note: You can use `NBKSigned` until `IntXL` becomes available. +/// +@frozen public struct NBKFlexibleWidth { + //*========================================================================* // MARK: * Magnitude //*========================================================================* @@ -161,6 +124,11 @@ import NBKCoreKit //*============================================================================* /// A signed, flexible-width, integer. +/// +/// This name reserves a spot for a signed 2's-complement-in-memory integer. +/// +/// - Note: You can use `NBKSigned` until `IntXL` becomes available. +/// public typealias IntXL = NBKFlexibleWidth /// An unsigned, flexible-width, integer. diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Addition.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Addition.swift index 59ae2e1a..c404130d 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Addition.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Addition.swift @@ -17,67 +17,6 @@ private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] -//*============================================================================* -// MARK: * NBK x Flexible Width x Addition x IntXL -//*============================================================================* - -final class NBKFlexibleWidthBenchmarksOnAdditionAsIntXL: XCTestCase { - - typealias T = IntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testAdd() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(lhs += rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testAdding() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs + rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Digit - //=------------------------------------------------------------------------= - - func testAddDigit() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(Int.max) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(lhs += rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testAddingDigit() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(Int.max) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs + rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } -} - //*============================================================================* // MARK: * NBK x Flexible Width x Addition x UIntXL //*============================================================================* diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Bits.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Bits.swift index 3eb6844b..58efaa73 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Bits.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Bits.swift @@ -17,110 +17,6 @@ private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] -//*============================================================================* -// MARK: * NBK x Flexible Width x Bits x IntXL -//*============================================================================* - -final class NBKFlexibleWidthBenchmarksOnBitsAsIntXL: XCTestCase { - - typealias T = IntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testInitBit() { - var abc = NBK.blackHoleIdentity(true ) - var xyz = NBK.blackHoleIdentity(false) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(T(bit: abc)) - NBK.blackHole(T(bit: xyz)) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - func testBitWidth() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.bitWidth) - NBK.blackHole(xyz.bitWidth) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - func testNonzeroBitCount() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.nonzeroBitCount) - NBK.blackHole(xyz.nonzeroBitCount) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - func testLeadingZeroBitCount() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.leadingZeroBitCount) - NBK.blackHole(xyz.leadingZeroBitCount) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - func testTrailingZeroBitCount() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.trailingZeroBitCount) - NBK.blackHole(xyz.trailingZeroBitCount) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - func testMostSignificantBit() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.mostSignificantBit) - NBK.blackHole(xyz.mostSignificantBit) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - func testLeastSignificantBit() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.leastSignificantBit) - NBK.blackHole(xyz.leastSignificantBit) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } -} - //*============================================================================* // MARK: * NBK x Flexible Width x Bits x UIntXL //*============================================================================* diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Comparisons.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Comparisons.swift index 930489c2..fe9a5424 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Comparisons.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Comparisons.swift @@ -17,136 +17,6 @@ private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] -//*============================================================================* -// MARK: * NBK x Flexible Width x Comparisons x IntXL -//*============================================================================* - -final class NBKFlexibleWidthBenchmarksOnComparisonsAsIntXL: XCTestCase { - - typealias T = IntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testIsZero() { - var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.isZero) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testIsLessThanZero() { - var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.isLessThanZero) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testIsMoreThanZero() { - var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.isMoreThanZero) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testIsPowerOf2() { - var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.isPowerOf2) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testSignum() { - var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.signum()) - NBK.blackHoleInoutIdentity(&abc) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testIsEqualTo() { - var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(lhs == rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testIsLessThan() { - var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(lhs < rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testComparedTo() { - var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(lhs.compared(to: rhs)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testComparedToAtIndex() { - var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[1, 2, 3, 0] as X)) - let xyz = NBK.blackHoleIdentity(1 as Int) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(lhs.compared(to: rhs, at: xyz)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testComparedToDigit() { - var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - var rhs = NBK.blackHoleIdentity(Int.max) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(lhs.compared(to: rhs)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testComparedToDigitAtIndex() { - var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - var rhs = NBK.blackHoleIdentity(3 as Int) - let xyz = NBK.blackHoleIdentity(3 as Int) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(lhs.compared(to: rhs, at: xyz)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } -} - //*============================================================================* // MARK: * NBK x Flexible Width x Comparisons x UIntXL //*============================================================================* diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Complements.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Complements.swift index f865026f..36c088e7 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Complements.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Complements.swift @@ -17,145 +17,6 @@ private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] -//*============================================================================* -// MARK: * NBK x Flexible Width x Complements x IntXL -//*============================================================================* - -final class NBKFlexibleWidthBenchmarksOnComplementsAsIntXL: XCTestCase { - - typealias T = IntXL - typealias M = UIntXL - - //=------------------------------------------------------------------------= - // MARK: Tests x Magnitude - //=------------------------------------------------------------------------= - - func testMagnitude() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.magnitude) - NBK.blackHole(xyz.magnitude) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x One's Complement - //=------------------------------------------------------------------------= - - func testOnesComplement() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) - - for _ in 0 ..< 250_000 { - NBK.blackHole(abc.onesComplement()) - NBK.blackHole(xyz.onesComplement()) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - func testOnesComplementInout() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.formOnesComplement()) - NBK.blackHole(xyz.formOnesComplement()) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Two's Complement - //=------------------------------------------------------------------------= - - func testTwosComplement() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.twosComplement()) - NBK.blackHole(xyz.twosComplement()) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - func testTwosComplementInout() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.formTwosComplement()) - NBK.blackHole(xyz.formTwosComplement()) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - func testTwosComplementReportingOverflow() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.twosComplementReportingOverflow()) - NBK.blackHole(xyz.twosComplementReportingOverflow()) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - func testTwosComplementReportingOverflowInout() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.formTwosComplementReportingOverflow()) - NBK.blackHole(xyz.formTwosComplementReportingOverflow()) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - func testTwosComplementSubsequence() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.twosComplementSubsequence(true)) - NBK.blackHole(xyz.twosComplementSubsequence(true)) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - func testTwosComplementSubsequenceInout() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.formTwosComplementSubsequence(true)) - NBK.blackHole(xyz.formTwosComplementSubsequence(true)) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } -} - //*============================================================================* // MARK: * NBK x Flexible Width x Complements x UIntXL //*============================================================================* diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Division.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Division.swift index dd04728c..4134089a 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Division.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Division.swift @@ -17,116 +17,6 @@ private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] -//*============================================================================* -// MARK: * NBK x Flexible Width x Division x IntXL -//*============================================================================* - -final class NBKFlexibleWidthBenchmarksOnDivisionAsIntXL: XCTestCase { - - typealias T = IntXL - typealias M = IntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testQuotientAndRemainder() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) - - for _ in 0 ..< 250_000 { - NBK.blackHole(lhs.quotientAndRemainder(dividingBy: rhs)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testQuotientReportingOverflow() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) - - for _ in 0 ..< 250_000 { - NBK.blackHole(lhs.dividedReportingOverflow(by: rhs)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testRemainderReportingOverflow() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) - - for _ in 0 ..< 250_000 { - NBK.blackHole(lhs.remainderReportingOverflow(dividingBy: rhs)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Digit - //=------------------------------------------------------------------------= - - func testQuotientAndRemainderDividingByDigit() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(Int.max) - - for _ in 0 ..< 250_000 { - NBK.blackHole(lhs.quotientAndRemainder(dividingBy: rhs)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testQuotientDividingByDigitReportingOverflow() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(Int.max) - - for _ in 0 ..< 250_000 { - NBK.blackHole(lhs.dividedReportingOverflow(by: rhs)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testRemainderDividingByDigitReportingOverflow() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(Int.max) - - for _ in 0 ..< 250_000 { - NBK.blackHole(lhs.remainderReportingOverflow(dividingBy: rhs)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Full Width - //=------------------------------------------------------------------------= - - func testDividingFullWidthAs256() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0/2] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0/2, ~0, ~0, ~0, ~0/4] as X)) - - for _ in 0 ..< 250_000 { - NBK.blackHole(rhs.quotientAndRemainder(dividingBy: lhs)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testDividingFullWidthReportingOverflowAs256() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0/2] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0/2, ~0, ~0, ~0, ~0/4] as X)) - - for _ in 0 ..< 250_000 { - NBK.blackHole(rhs.quotientAndRemainderReportingOverflow(dividingBy: lhs)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } -} - //*============================================================================* // MARK: * NBK x Flexible Width x Division x UIntXL //*============================================================================* @@ -215,24 +105,24 @@ final class NBKFlexibleWidthBenchmarksOnDivisionAsUIntXL: XCTestCase { //=------------------------------------------------------------------------= func testDividingFullWidthAs256() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0, ~1, ~0, ~0, ~0] as X)) + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0, ~1, ~0, ~0, ~0] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0] as X)) for _ in 0 ..< 250_000 { - NBK.blackHole(rhs.quotientAndRemainder(dividingBy: lhs)) - NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHole(lhs.quotientAndRemainder(dividingBy: rhs)) NBK.blackHoleInoutIdentity(&rhs) + NBK.blackHoleInoutIdentity(&lhs) } } func testDividingFullWidthReportingOverflowAs256() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0, ~1, ~0, ~0, ~0] as X)) + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0, ~1, ~0, ~0, ~0] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0] as X)) for _ in 0 ..< 250_000 { - NBK.blackHole(rhs.quotientAndRemainderReportingOverflow(dividingBy: lhs)) - NBK.blackHoleInoutIdentity(&lhs) + NBK.blackHole(lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs)) NBK.blackHoleInoutIdentity(&rhs) + NBK.blackHoleInoutIdentity(&lhs) } } } diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Multiplication.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Multiplication.swift index f8740232..e671d137 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Multiplication.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Multiplication.swift @@ -17,45 +17,6 @@ private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] -//*============================================================================* -// MARK: * NBK x Flexible Width x Multiplication x IntXL -//*============================================================================* - -final class NBKFlexibleWidthBenchmarksOnMultiplicationAsIntXL: XCTestCase { - - typealias T = IntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testMultiplied() { - var lhs = NBK.blackHoleIdentity(T(x64:[~1, ~2, ~3, ~4] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[ 1, 2, 3, 4] as X)) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs * rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Digit - //=------------------------------------------------------------------------= - - func testMultipliedByDigit() { - var lhs = NBK.blackHoleIdentity(T(x64:[~1, ~2, ~3, ~4] as X)) - var rhs = NBK.blackHoleIdentity(Int.max) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs * rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } -} - //*============================================================================* // MARK: * NBK x Flexible Width x Multiplication x UIntXL //*============================================================================* diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Numbers.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Numbers.swift index 5cb1bee9..095d0acb 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Numbers.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Numbers.swift @@ -17,404 +17,6 @@ private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] -//*============================================================================* -// MARK: * NBK x Flexible Width x Numbers x IntXL -//*============================================================================* - -final class NBKFlexibleWidthBenchmarksOnNumbersAsIntXL: XCTestCase { - - typealias T = IntXL - typealias M = UIntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testZero() { - for _ in 0 ..< 100_000 { - NBK.blackHole(T()) - NBK.blackHole(T.zero) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Integers - //=------------------------------------------------------------------------= - - func testToInt() { - var abc = NBK.blackHoleIdentity(T(Int.max)) - - for _ in 0 ..< 50_000 { - NBK.blackHole(Int(abc)) - NBK.blackHole(Int(exactly: abc)) - NBK.blackHole(Int(clamping: abc)) - NBK.blackHole(Int(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testFromInt() { - var abc = NBK.blackHoleIdentity(Int.max) - - for _ in 0 ..< 100_000 { - NBK.blackHole(T(abc)) - NBK.blackHole(T(exactly: abc)) - NBK.blackHole(T(clamping: abc)) - NBK.blackHole(T(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testToUInt() { - var abc = NBK.blackHoleIdentity(T(UInt.max)) - - for _ in 0 ..< 50_000 { - NBK.blackHole(UInt(abc)) - NBK.blackHole(UInt(exactly: abc)) - NBK.blackHole(UInt(clamping: abc)) - NBK.blackHole(UInt(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testFromUInt() { - var abc = NBK.blackHoleIdentity(UInt.max) - - for _ in 0 ..< 100_000 { - NBK.blackHole(T(abc)) - NBK.blackHole(T(exactly: abc)) - NBK.blackHole(T(clamping: abc)) - NBK.blackHole(T(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testToInt8() { - var abc = NBK.blackHoleIdentity(T(Int8.max)) - - for _ in 0 ..< 50_000 { - NBK.blackHole(Int8(abc)) - NBK.blackHole(Int8(exactly: abc)) - NBK.blackHole(Int8(clamping: abc)) - NBK.blackHole(Int8(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testFromInt8() { - var abc = NBK.blackHoleIdentity(Int8.max) - - for _ in 0 ..< 100_000 { - NBK.blackHole(T(abc)) - NBK.blackHole(T(exactly: abc)) - NBK.blackHole(T(clamping: abc)) - NBK.blackHole(T(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testToUInt8() { - var abc = NBK.blackHoleIdentity(T(UInt8.max)) - - for _ in 0 ..< 50_000 { - NBK.blackHole(UInt8(abc)) - NBK.blackHole(UInt8(exactly: abc)) - NBK.blackHole(UInt8(clamping: abc)) - NBK.blackHole(UInt8(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testFromUInt8() { - var abc = NBK.blackHoleIdentity(UInt8.max) - - for _ in 0 ..< 100_000 { - NBK.blackHole(T(abc)) - NBK.blackHole(T(exactly: abc)) - NBK.blackHole(T(clamping: abc)) - NBK.blackHole(T(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testToInt16() { - var abc = NBK.blackHoleIdentity(T(Int16.max)) - - for _ in 0 ..< 50_000 { - NBK.blackHole(Int16(abc)) - NBK.blackHole(Int16(exactly: abc)) - NBK.blackHole(Int16(clamping: abc)) - NBK.blackHole(Int16(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testFromInt16() { - var abc = NBK.blackHoleIdentity(Int16.max) - - for _ in 0 ..< 100_000 { - NBK.blackHole(T(abc)) - NBK.blackHole(T(exactly: abc)) - NBK.blackHole(T(clamping: abc)) - NBK.blackHole(T(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testToUInt16() { - var abc = NBK.blackHoleIdentity(T(UInt16.max)) - - for _ in 0 ..< 50_000 { - NBK.blackHole(UInt16(abc)) - NBK.blackHole(UInt16(exactly: abc)) - NBK.blackHole(UInt16(clamping: abc)) - NBK.blackHole(UInt16(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testFromUInt16() { - var abc = NBK.blackHoleIdentity(UInt16.max) - - for _ in 0 ..< 100_000 { - NBK.blackHole(T(abc)) - NBK.blackHole(T(exactly: abc)) - NBK.blackHole(T(clamping: abc)) - NBK.blackHole(T(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testToInt32() { - var abc = NBK.blackHoleIdentity(T(Int32.max)) - - for _ in 0 ..< 50_000 { - NBK.blackHole(Int32(abc)) - NBK.blackHole(Int32(exactly: abc)) - NBK.blackHole(Int32(clamping: abc)) - NBK.blackHole(Int32(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testFromInt32() { - var abc = NBK.blackHoleIdentity(Int32.max) - - for _ in 0 ..< 100_000 { - NBK.blackHole(T(abc)) - NBK.blackHole(T(exactly: abc)) - NBK.blackHole(T(clamping: abc)) - NBK.blackHole(T(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testToUInt32() { - var abc = NBK.blackHoleIdentity(T(UInt32.max)) - - for _ in 0 ..< 50_000 { - NBK.blackHole(UInt32(abc)) - NBK.blackHole(UInt32(exactly: abc)) - NBK.blackHole(UInt32(clamping: abc)) - NBK.blackHole(UInt32(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testFromUInt32() { - var abc = NBK.blackHoleIdentity(UInt32.max) - - for _ in 0 ..< 100_000 { - NBK.blackHole(T(abc)) - NBK.blackHole(T(exactly: abc)) - NBK.blackHole(T(clamping: abc)) - NBK.blackHole(T(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testToInt64() { - var abc = NBK.blackHoleIdentity(T(Int64.max)) - - for _ in 0 ..< 50_000 { - NBK.blackHole(Int64(abc)) - NBK.blackHole(Int64(exactly: abc)) - NBK.blackHole(Int64(clamping: abc)) - NBK.blackHole(Int64(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testFromInt64() { - var abc = NBK.blackHoleIdentity(Int64.max) - - for _ in 0 ..< 100_000 { - NBK.blackHole(T(abc)) - NBK.blackHole(T(exactly: abc)) - NBK.blackHole(T(clamping: abc)) - NBK.blackHole(T(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testToUInt64() { - var abc = NBK.blackHoleIdentity(T(UInt64.max)) - - for _ in 0 ..< 50_000 { - NBK.blackHole(UInt64(abc)) - NBK.blackHole(UInt64(exactly: abc)) - NBK.blackHole(UInt64(clamping: abc)) - NBK.blackHole(UInt64(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testFromUInt64() { - var abc = NBK.blackHoleIdentity(UInt64.max) - - for _ in 0 ..< 100_000 { - NBK.blackHole(T(abc)) - NBK.blackHole(T(exactly: abc)) - NBK.blackHole(T(clamping: abc)) - NBK.blackHole(T(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Complements - //=------------------------------------------------------------------------= - - func testToDigit() { - var abc = NBK.blackHoleIdentity(T(T.Digit.max)) - - for _ in 0 ..< 50_000 { - NBK.blackHole(T.Digit(abc)) - NBK.blackHole(T.Digit(exactly: abc)) - NBK.blackHole(T.Digit(clamping: abc)) - NBK.blackHole(T.Digit(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testFromDigit() { - var abc = NBK.blackHoleIdentity(T.Digit.max) - - for _ in 0 ..< 100_000 { - NBK.blackHole(T(digit: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testToMagnitude() { - var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - - for _ in 0 ..< 50_000 { - NBK.blackHole(M(abc)) - NBK.blackHole(M(exactly: abc)) - NBK.blackHole(M(clamping: abc)) - NBK.blackHole(M(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testFromMagnitude() { - var abc = NBK.blackHoleIdentity(M(x64:[0, 1, 2, 3] as X)) - - for _ in 0 ..< 100_000 { - NBK.blackHole(T(abc)) - NBK.blackHole(T(exactly: abc)) - NBK.blackHole(T(clamping: abc)) - NBK.blackHole(T(truncatingIfNeeded: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Float - //=------------------------------------------------------------------------= - - // TODO: brrr - func testToFloat16() { - var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - - for _ in 0 ..< 1_000 { - NBK.blackHole(Float16(abc)) - NBK.blackHole(Float16(exactly: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testFromFloat16() { - var abc = NBK.blackHoleIdentity(Float16(123)) - - for _ in 0 ..< 100_000 { - NBK.blackHole(T(abc)) - NBK.blackHole(T(exactly: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - // TODO: brrr - func testToFloat32() { - var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - - for _ in 0 ..< 1_000 { - NBK.blackHole(Float32(abc)) - NBK.blackHole(Float32(exactly: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testFromFloat32() { - var abc = NBK.blackHoleIdentity(Float32(123)) - - for _ in 0 ..< 100_000 { - NBK.blackHole(T(abc)) - NBK.blackHole(T(exactly: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - // TODO: brrr - func testToFloat64() { - var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - - for _ in 0 ..< 1_000 { - NBK.blackHole(Float64(abc)) - NBK.blackHole(Float64(exactly: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testFromFloat64() { - var abc = NBK.blackHoleIdentity(Float64(123)) - - for _ in 0 ..< 100_000 { - NBK.blackHole(T(abc)) - NBK.blackHole(T(exactly: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Sign & Magnitude - //=------------------------------------------------------------------------= - - func testSignAndMagnitude() { - var abc = NBK.blackHoleIdentity((sign: FloatingPointSign.plus, magnitude: M(x64:[0, 1, 2, 3] as X))) - var xyz = NBK.blackHoleIdentity((sign: FloatingPointSign.minus, magnitude: M(x64:[0, 1, 2, 3] as X))) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(T(sign: abc.sign, magnitude: abc.magnitude)) - NBK.blackHoleInoutIdentity(&abc) - - NBK.blackHole(T(sign: xyz.sign, magnitude: xyz.magnitude)) - NBK.blackHoleInoutIdentity(&xyz) - } - } -} - //*============================================================================* // MARK: * NBK x Flexible Width x Numbers x UIntXL //*============================================================================* diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Shifts.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Shifts.swift index 9e69edc1..1564deff 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Shifts.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Shifts.swift @@ -17,138 +17,6 @@ private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] -//*============================================================================* -// MARK: * NBK x Flexible Width x Shifts x IntXL -//*============================================================================* - -final class NBKFlexibleWidthBenchmarksOnShiftsAsIntXL: XCTestCase { - - typealias T = IntXL - - //=------------------------------------------------------------------------= - // MARK: Tests x Left - //=------------------------------------------------------------------------= - - func testBitshiftingLeft() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(UInt.bitWidth * 3/2) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs << rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testBitshiftingLeftByWords() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs.bitshiftedLeft(words: rhs.words)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testBitshiftingLeftByWordsAndBits() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs.bitshiftedLeft(words: rhs.words, bits: rhs.bits)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Right - //=------------------------------------------------------------------------= - - func testBitshiftingRight() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(UInt.bitWidth * 3/2) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs >> rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testBitshiftingRightByWords() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs.bitshiftedRight(words: rhs.words)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testBitshiftingRightByWordsAndBits() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs.bitshiftedRight(words: rhs.words, bits: rhs.bits)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x In Both Directions - //=------------------------------------------------------------------------= - - func testBitshiftingInBothDirectionsInout() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(UInt.bitWidth * 3/2) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs.bitshiftLeft (by: rhs)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - - NBK.blackHole(lhs.bitshiftRight(by: rhs)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testBitshiftingInBothDirectionsByWordsInout() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs.bitshiftLeft (words: rhs.words)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - - NBK.blackHole(lhs.bitshiftRight(words: rhs.words)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testBitshiftingInBothDirectionsByWordsAndBitsInout() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity((words: 1, bits: UInt.bitWidth/2)) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs.bitshiftLeft (words: rhs.words, bits: rhs.bits)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - - NBK.blackHole(lhs.bitshiftRight(words: rhs.words, bits: rhs.bits)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } -} - //*============================================================================* // MARK: * NBK x Flexible Width x Shifts x UIntXL //*============================================================================* diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Subtraction.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Subtraction.swift index 1c7a0733..4b816707 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Subtraction.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Subtraction.swift @@ -17,67 +17,6 @@ private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] -//*============================================================================* -// MARK: * NBK x Flexible Width x Subtraction x IntXL -//*============================================================================* - -final class NBKFlexibleWidthBenchmarksOnSubtractionAsIntXL: XCTestCase { - - typealias T = IntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testSubtract() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(lhs -= rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testSubtracting() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs - rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Digit - //=------------------------------------------------------------------------= - - func testSubtractDigit() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(Int.max) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(lhs -= rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testSubtractingDigit() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(Int.max) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs - rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } -} - //*============================================================================* // MARK: * NBK x Flexible Width x Subtraction x UIntXL //*============================================================================* diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Text.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Text.swift index a4e4e8cc..ac26712e 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Text.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Text.swift @@ -17,96 +17,6 @@ private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] -//*============================================================================* -// MARK: * NBK x Flexible Width x Text x IntXL -//*============================================================================* - -final class NBKFlexibleWidthBenchmarksOnTextAsIntXL: XCTestCase { - - typealias T = IntXL - - //=------------------------------------------------------------------------= - // MARK: State - //=------------------------------------------------------------------------= - - static let decoded = NBK.blackHoleIdentity(T(encoded, radix: 16)!) - static let encoded = NBK.blackHoleIdentity(String(repeating: "1", count: 64)) - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testDecodingRadix10() { - var radix = NBK.blackHoleIdentity(10) - var encoded = NBK.blackHoleIdentity(Self.encoded) - - for _ in 0 ..< 250_000 { - NBK.blackHole(T(encoded, radix: radix)!) - NBK.blackHoleInoutIdentity(&radix) - NBK.blackHoleInoutIdentity(&encoded) - } - } - - func testDecodingRadix16() { - var radix = NBK.blackHoleIdentity(16) - var encoded = NBK.blackHoleIdentity(Self.encoded) - - for _ in 0 ..< 250_000 { - NBK.blackHole(T(encoded, radix: radix)!) - NBK.blackHoleInoutIdentity(&radix) - NBK.blackHoleInoutIdentity(&encoded) - } - } - - func testEncodingRadix10() { - var radix = NBK.blackHoleIdentity(10) - var decoded = NBK.blackHoleIdentity(Self.decoded) - - for _ in 0 ..< 250_000 { - NBK.blackHole(String(decoded, radix: radix)) - NBK.blackHoleInoutIdentity(&radix) - NBK.blackHoleInoutIdentity(&decoded) - } - } - - func testEncodingRadix16() { - var radix = NBK.blackHoleIdentity(16) - var decoded = NBK.blackHoleIdentity(Self.decoded) - - for _ in 0 ..< 250_000 { - NBK.blackHole(String(decoded, radix: radix)) - NBK.blackHoleInoutIdentity(&radix) - NBK.blackHoleInoutIdentity(&decoded) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Swift Standard Library Methods - //=------------------------------------------------------------------------= - - func testEncodingUsingSwiftStdlibRadix10() { - var radix = NBK.blackHoleIdentity(10) - var decoded = NBK.blackHoleIdentity(Self.decoded) - - for _ in 0 ..< 1_000 { - NBK.blackHole(NBK.descriptionAsStdlib(decoded, radix: radix)) - NBK.blackHoleInoutIdentity(&radix) - NBK.blackHoleInoutIdentity(&decoded) - } - } - - func testEncodingUsingSwiftStdlibRadix16() { - var radix = NBK.blackHoleIdentity(16) - var decoded = NBK.blackHoleIdentity(Self.decoded) - - for _ in 0 ..< 1_000 { - NBK.blackHole(NBK.descriptionAsStdlib(decoded, radix: radix)) - NBK.blackHoleInoutIdentity(&radix) - NBK.blackHoleInoutIdentity(&decoded) - } - } -} - //*============================================================================* // MARK: * NBK x Flexible Width x Text x UIntXL //*============================================================================* diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Words.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Words.swift index d9234536..02000ca8 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Words.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Words.swift @@ -17,32 +17,6 @@ private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] -//*============================================================================* -// MARK: * NBK x Flexible Width x Words x IntXL -//*============================================================================* - -final class NBKFlexibleWidthBenchmarksOnWordsAsIntXL: XCTestCase { - - typealias T = IntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testFromWords() { - var abc = NBK.blackHoleIdentity([ 0, 0, 0, 0] as W) - var xyz = NBK.blackHoleIdentity([~0, ~0, ~0, ~0] as W) - - for _ in 0 ..< 250_000 { - NBK.blackHole(T(words: abc)) - NBK.blackHole(T(words: xyz)) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } -} - //*============================================================================* // MARK: * NBK x Flexible Width x Words x UIntXL //*============================================================================* diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth.swift index e2a353aa..bcb1c5a3 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth.swift @@ -16,46 +16,20 @@ private typealias X = [UInt64] private typealias Y = [UInt32] //*============================================================================* -// MARK: * NBK x Flexible Width x Initializers x IntXL -//*============================================================================* - -extension NBKFlexibleWidth { - - //=------------------------------------------------------------------------= - // MARK: Details x Numbers - //=------------------------------------------------------------------------= - - static let min256 = Self(x64:[ 0, 0, 0, ~0/2 + 1] as X) - static let max256 = Self(x64:[~0, ~0, ~0, ~0/2 + 0] as X) - - //=------------------------------------------------------------------------= - // MARK: Details x Limbs - //=------------------------------------------------------------------------= - - init(x32: [UInt32]) { - self.init(words: NBKChunkedInt(x32)) - } - - init(x64: [UInt64]) { - self.init(words: NBKChunkedInt(x64)) - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Initializers x UIntXL +// MARK: * NBK x Flexible Width x UIntXL //*============================================================================* extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= - // MARK: Details x Numbers + // MARK: Initializers //=------------------------------------------------------------------------= static let min256 = Self(x64:[ 0, 0, 0, 0] as X) static let max256 = Self(x64:[~0, ~0, ~0, ~0] as X) //=------------------------------------------------------------------------= - // MARK: Details x Limbs + // MARK: Initializers //=------------------------------------------------------------------------= init(x32: [UInt32]) { diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Addition.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Addition.swift index ad4850c7..9f1c6315 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Addition.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Addition.swift @@ -17,101 +17,6 @@ private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] -//*============================================================================* -// MARK: * NBK x Flexible Width x Addition x IntXL -//*============================================================================* - -final class NBKFlexibleWidthTestsOnAdditionAsIntXL: XCTestCase { - - typealias T = IntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testAdding() { - NBKAssertAddition(T( 1), T( 2), Int(0), T( 3)) - NBKAssertAddition(T( 1), T( 1), Int(0), T( 2)) - NBKAssertAddition(T( 1), T( 0), Int(0), T( 1)) - NBKAssertAddition(T( 1), T(-1), Int(0), T( 0)) - NBKAssertAddition(T( 1), T(-2), Int(0), T(-1)) - - NBKAssertAddition(T( 0), T( 2), Int(0), T( 2)) - NBKAssertAddition(T( 0), T( 1), Int(0), T( 1)) - NBKAssertAddition(T( 0), T( 0), Int(0), T( 0)) - NBKAssertAddition(T( 0), T(-1), Int(0), T(-1)) - NBKAssertAddition(T( 0), T(-2), Int(0), T(-2)) - - NBKAssertAddition(T(-1), T( 2), Int(0), T( 1)) - NBKAssertAddition(T(-1), T( 1), Int(0), T( 0)) - NBKAssertAddition(T(-1), T( 0), Int(0), T(-1)) - NBKAssertAddition(T(-1), T(-1), Int(0), T(-2)) - NBKAssertAddition(T(-1), T(-2), Int(0), T(-3)) - } - - func testAddingAtIndex() { - NBKAssertAddition(T(words:[ 0, 0, 0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[ 1, 2, 3, 0] as W)) - NBKAssertAddition(T(words:[~0, 0, 0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[ 0, 3, 3, 0] as W)) - NBKAssertAddition(T(words:[~0, ~0, 0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[ 0, 2, 4, 0] as W)) - NBKAssertAddition(T(words:[~0, ~0, ~0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[ 0, 2, 3, 1] as W)) - - NBKAssertAddition(T(words:[ 0, 0, 0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[ 0, 1, 2, 3] as W)) - NBKAssertAddition(T(words:[~0, 0, 0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[~0, 1, 2, 3] as W)) - NBKAssertAddition(T(words:[~0, ~0, 0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[~0, 0, 3, 3] as W)) - NBKAssertAddition(T(words:[~0, ~0, ~0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[~0, 0, 2, 4] as W)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Digit - //=------------------------------------------------------------------------= - - func testAddingDigit() { - NBKAssertAdditionByDigit(T( 1), Int( 2), Int(0), T( 3)) - NBKAssertAdditionByDigit(T( 1), Int( 1), Int(0), T( 2)) - NBKAssertAdditionByDigit(T( 1), Int( 0), Int(0), T( 1)) - NBKAssertAdditionByDigit(T( 1), Int(-1), Int(0), T( 0)) - NBKAssertAdditionByDigit(T( 1), Int(-2), Int(0), T(-1)) - - NBKAssertAdditionByDigit(T( 0), Int( 2), Int(0), T( 2)) - NBKAssertAdditionByDigit(T( 0), Int( 1), Int(0), T( 1)) - NBKAssertAdditionByDigit(T( 0), Int( 0), Int(0), T( 0)) - NBKAssertAdditionByDigit(T( 0), Int(-1), Int(0), T(-1)) - NBKAssertAdditionByDigit(T( 0), Int(-2), Int(0), T(-2)) - - NBKAssertAdditionByDigit(T(-1), Int( 2), Int(0), T( 1)) - NBKAssertAdditionByDigit(T(-1), Int( 1), Int(0), T( 0)) - NBKAssertAdditionByDigit(T(-1), Int( 0), Int(0), T(-1)) - NBKAssertAdditionByDigit(T(-1), Int(-1), Int(0), T(-2)) - NBKAssertAdditionByDigit(T(-1), Int(-2), Int(0), T(-3)) - } - - func testAddingDigitAtIndex() { - NBKAssertAdditionByDigit(T(words:[ 0, 0, 0, 0] as W), Int(3), Int(0), T(words:[ 3, 0, 0, 0] as W)) - NBKAssertAdditionByDigit(T(words:[~0, 0, 0, 0] as W), Int(3), Int(0), T(words:[ 2, 1, 0, 0] as W)) - NBKAssertAdditionByDigit(T(words:[~0, ~0, 0, 0] as W), Int(3), Int(0), T(words:[ 2, 0, 1, 0] as W)) - NBKAssertAdditionByDigit(T(words:[~0, ~0, ~0, 0] as W), Int(3), Int(0), T(words:[ 2, 0, 0, 1] as W)) - - NBKAssertAdditionByDigit(T(words:[ 0, 0, 0, 0] as W), Int(3), Int(1), T(words:[ 0, 3, 0, 0] as W)) - NBKAssertAdditionByDigit(T(words:[~0, 0, 0, 0] as W), Int(3), Int(1), T(words:[~0, 3, 0, 0] as W)) - NBKAssertAdditionByDigit(T(words:[~0, ~0, 0, 0] as W), Int(3), Int(1), T(words:[~0, 2, 1, 0] as W)) - NBKAssertAdditionByDigit(T(words:[~0, ~0, ~0, 0] as W), Int(3), Int(1), T(words:[~0, 2, 0, 1] as W)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Miscellaneous - //=------------------------------------------------------------------------= - - func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { - func becauseThisCompilesSuccessfully(_ x: inout T) { - XCTAssertNotNil(x += 0) - XCTAssertNotNil(x.add(0, at: 0)) - - XCTAssertNotNil(x + 0) - XCTAssertNotNil(x.adding(0, at: 0)) - } - } -} - //*============================================================================* // MARK: * NBK x Flexible Width x Addition x UIntXL //*============================================================================* diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Bits.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Bits.swift index f15ef7d9..6f56c9a8 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Bits.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Bits.swift @@ -17,119 +17,6 @@ private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] -//*============================================================================* -// MARK: * NBK x Flexible Width x Bits x IntXL -//*============================================================================* - -final class NBKFlexibleWidthTestsOnBitsAsIntXL: XCTestCase { - - typealias T = IntXL - typealias M = UIntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testInitBit() { - XCTAssertEqual(T(bit: false), T( )) - XCTAssertEqual(T(bit: true ), T(1)) - } - - func testBitWidth() { - XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).bitWidth, UInt.bitWidth * 1) - XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).bitWidth, UInt.bitWidth * 1) - - XCTAssertEqual(T(sign: .plus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as W)).bitWidth, UInt.bitWidth * 4) - XCTAssertEqual(T(sign: .plus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as W)).bitWidth, UInt.bitWidth * 5) - XCTAssertEqual(T(sign: .plus, magnitude: M(words:[ 1, 0, 0, ~0/2 + 1] as W)).bitWidth, UInt.bitWidth * 5) - - XCTAssertEqual(T(sign: .minus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as W)).bitWidth, UInt.bitWidth * 4) - XCTAssertEqual(T(sign: .minus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as W)).bitWidth, UInt.bitWidth * 4) - XCTAssertEqual(T(sign: .minus, magnitude: M(words:[ 1, 0, 0, ~0/2 + 1] as W)).bitWidth, UInt.bitWidth * 5) - } - - func testNonzeroBitCount() { - XCTAssertEqual(T(sign: .minus, magnitude: 0).nonzeroBitCount, 0) - XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).nonzeroBitCount, 0) - XCTAssertEqual(T(words:[ 1, 1, 1, 1] as W).nonzeroBitCount, 4) - XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).nonzeroBitCount, UInt.bitWidth * 1) - - XCTAssertEqual(T(sign: .plus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as W)).nonzeroBitCount, UInt.bitWidth * 4 - 1) - XCTAssertEqual(T(sign: .plus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as W)).nonzeroBitCount, UInt.bitWidth * 0 + 1) - XCTAssertEqual(T(sign: .plus, magnitude: M(words:[ 1, 0, 0, ~0/2 + 1] as W)).nonzeroBitCount, UInt.bitWidth * 0 + 2) - - XCTAssertEqual(T(sign: .minus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as W)).nonzeroBitCount, UInt.bitWidth * 0 + 2) - XCTAssertEqual(T(sign: .minus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as W)).nonzeroBitCount, UInt.bitWidth * 0 + 1) - XCTAssertEqual(T(sign: .minus, magnitude: M(words:[ 1, 0, 0, ~0/2 + 1] as W)).nonzeroBitCount, UInt.bitWidth * 5 - 1) - } - - func testLeadingZeroBitCount() { - XCTAssertEqual(T(sign: .minus, magnitude: 0).leadingZeroBitCount, UInt.bitWidth * 1) - XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).leadingZeroBitCount, UInt.bitWidth * 1) - XCTAssertEqual(T(words:[ 1, 1, 1, 1] as W).leadingZeroBitCount, UInt.bitWidth * 1 - 1) - XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).leadingZeroBitCount, UInt.bitWidth * 0) - - XCTAssertEqual(T(words:[ 2, 0, 0, 0] as W).leadingZeroBitCount, UInt.bitWidth * 1 - 2) - XCTAssertEqual(T(words:[ 0, 2, 0, 0] as W).leadingZeroBitCount, UInt.bitWidth * 1 - 2) - XCTAssertEqual(T(words:[ 0, 0, 2, 0] as W).leadingZeroBitCount, UInt.bitWidth * 1 - 2) - XCTAssertEqual(T(words:[ 0, 0, 0, 2] as W).leadingZeroBitCount, UInt.bitWidth * 1 - 2) - - XCTAssertEqual(T(sign: .plus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as W)).leadingZeroBitCount, UInt.bitWidth * 0 + 1) - XCTAssertEqual(T(sign: .plus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as W)).leadingZeroBitCount, UInt.bitWidth * 1 + 0) - XCTAssertEqual(T(sign: .plus, magnitude: M(words:[ 1, 0, 0, ~0/2 + 1] as W)).leadingZeroBitCount, UInt.bitWidth * 1 + 0) - - XCTAssertEqual(T(sign: .minus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as W)).leadingZeroBitCount, UInt.bitWidth * 0 + 0) - XCTAssertEqual(T(sign: .minus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as W)).leadingZeroBitCount, UInt.bitWidth * 0 + 0) - XCTAssertEqual(T(sign: .minus, magnitude: M(words:[ 1, 0, 0, ~0/2 + 1] as W)).leadingZeroBitCount, UInt.bitWidth * 0 + 0) - } - - func testTrailingZeroBitCount() { - XCTAssertEqual(T(sign: .minus, magnitude: 0).trailingZeroBitCount, UInt.bitWidth * 1) - XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).trailingZeroBitCount, UInt.bitWidth * 1) - XCTAssertEqual(T(words:[ 1, 1, 1, 1] as W).trailingZeroBitCount, UInt.bitWidth * 0) - XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).trailingZeroBitCount, UInt.bitWidth * 0) - - XCTAssertEqual(T(words:[ 2, 0, 0, 0] as W).trailingZeroBitCount, UInt.bitWidth * 0 + 1) - XCTAssertEqual(T(words:[ 0, 2, 0, 0] as W).trailingZeroBitCount, UInt.bitWidth * 1 + 1) - XCTAssertEqual(T(words:[ 0, 0, 2, 0] as W).trailingZeroBitCount, UInt.bitWidth * 2 + 1) - XCTAssertEqual(T(words:[ 0, 0, 0, 2] as W).trailingZeroBitCount, UInt.bitWidth * 3 + 1) - } - - func testMostSignificantBit() { - XCTAssertEqual(T(sign: .minus, magnitude: 0).mostSignificantBit, false) - XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).mostSignificantBit, false) - XCTAssertEqual(T(words:[ 1, 1, 1, 1] as W).mostSignificantBit, false) - XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).mostSignificantBit, true ) - - XCTAssertEqual(T(words:[~0, 0, 0, 0] as W).mostSignificantBit, false) - XCTAssertEqual(T(words:[ 0, ~0, 0, 0] as W).mostSignificantBit, false) - XCTAssertEqual(T(words:[ 0, 0, ~0, 0] as W).mostSignificantBit, false) - XCTAssertEqual(T(words:[ 0, 0, 0, ~0] as W).mostSignificantBit, true ) - - XCTAssertEqual(T(words:[~0, 1, 0, 0] as W).mostSignificantBit, false) - XCTAssertEqual(T(words:[ 0, ~0, 1, 0] as W).mostSignificantBit, false) - XCTAssertEqual(T(words:[ 0, 0, ~0, 1] as W).mostSignificantBit, false) - XCTAssertEqual(T(words:[ 1, 0, 0, ~0] as W).mostSignificantBit, true ) - } - - func testLeastSignificantBit() { - XCTAssertEqual(T(sign: .minus, magnitude: 0).leastSignificantBit, false) - XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).leastSignificantBit, false) - XCTAssertEqual(T(words:[ 1, 1, 1, 1] as W).leastSignificantBit, true ) - XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).leastSignificantBit, true ) - - XCTAssertEqual(T(words:[~0, 0, 0, 0] as W).leastSignificantBit, true ) - XCTAssertEqual(T(words:[ 0, ~0, 0, 0] as W).leastSignificantBit, false) - XCTAssertEqual(T(words:[ 0, 0, ~0, 0] as W).leastSignificantBit, false) - XCTAssertEqual(T(words:[ 0, 0, 0, ~0] as W).leastSignificantBit, false) - - XCTAssertEqual(T(words:[~0, 1, 0, 0] as W).leastSignificantBit, true ) - XCTAssertEqual(T(words:[ 0, ~0, 1, 0] as W).leastSignificantBit, false) - XCTAssertEqual(T(words:[ 0, 0, ~0, 1] as W).leastSignificantBit, false) - XCTAssertEqual(T(words:[ 1, 0, 0, ~0] as W).leastSignificantBit, true ) - } -} - //*============================================================================* // MARK: * NBK x Flexible Width x Bits x UIntXL //*============================================================================* diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Comparisons.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Comparisons.swift index a6a9845b..995a0f1c 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Comparisons.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Comparisons.swift @@ -17,316 +17,6 @@ private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] -//*============================================================================* -// MARK: * NBK x Flexible Width x Comparisons x IntXL -//*============================================================================* - -final class NBKFlexibleWidthTestsOnComparisonsAsIntXL: XCTestCase { - - typealias T = IntXL - typealias M = UIntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testIsZero() { - XCTAssertTrue (T(sign: .plus, magnitude: 0).isZero) - XCTAssertTrue (T(sign: .minus, magnitude: 0).isZero) - - XCTAssertTrue (T(words:[ 0] as W).isZero) - XCTAssertFalse(T(words:[ 1] as W).isZero) - XCTAssertFalse(T(words:[ 2] as W).isZero) - - XCTAssertFalse(T(words:[~0] as W).isZero) - XCTAssertFalse(T(words:[~1] as W).isZero) - XCTAssertFalse(T(words:[~2] as W).isZero) - } - - func testIsLessThanZero() { - XCTAssertFalse(T(sign: .plus, magnitude: 0).isLessThanZero) - XCTAssertFalse(T(sign: .minus, magnitude: 0).isLessThanZero) - - XCTAssertFalse(T(words:[ 0] as W).isLessThanZero) - XCTAssertFalse(T(words:[ 1] as W).isLessThanZero) - XCTAssertFalse(T(words:[ 2] as W).isLessThanZero) - - XCTAssertTrue (T(words:[~0] as W).isLessThanZero) - XCTAssertTrue (T(words:[~1] as W).isLessThanZero) - XCTAssertTrue (T(words:[~2] as W).isLessThanZero) - } - - func testIsMoreThanZero() { - XCTAssertFalse(T(sign: .plus, magnitude: 0).isMoreThanZero) - XCTAssertFalse(T(sign: .minus, magnitude: 0).isMoreThanZero) - - XCTAssertFalse(T(words:[ 0] as W).isMoreThanZero) - XCTAssertTrue (T(words:[ 1] as W).isMoreThanZero) - XCTAssertTrue (T(words:[ 2] as W).isMoreThanZero) - - XCTAssertFalse(T(words:[~0] as W).isMoreThanZero) - XCTAssertFalse(T(words:[~1] as W).isMoreThanZero) - XCTAssertFalse(T(words:[~2] as W).isMoreThanZero) - } - - func testIsOdd() { - XCTAssertFalse(T(sign: .plus, magnitude: 0).isOdd) - XCTAssertFalse(T(sign: .minus, magnitude: 0).isOdd) - - XCTAssertFalse(T(words:[ 0] as W).isOdd) - XCTAssertTrue (T(words:[ 1] as W).isOdd) - XCTAssertFalse(T(words:[ 2] as W).isOdd) - - XCTAssertTrue (T(words:[~0] as W).isOdd) - XCTAssertFalse(T(words:[~1] as W).isOdd) - XCTAssertTrue (T(words:[~2] as W).isOdd) - } - - func testIsEven() { - XCTAssertTrue (T(sign: .plus, magnitude: 0).isEven) - XCTAssertTrue (T(sign: .minus, magnitude: 0).isEven) - - XCTAssertTrue (T(words:[ 0] as W).isEven) - XCTAssertFalse(T(words:[ 1] as W).isEven) - XCTAssertTrue (T(words:[ 2] as W).isEven) - - XCTAssertFalse(T(words:[~0] as W).isEven) - XCTAssertTrue (T(words:[~1] as W).isEven) - XCTAssertFalse(T(words:[~2] as W).isEven) - } - - func testIsPowerOf2() { - XCTAssertFalse(T(sign: .plus, magnitude: 0).isPowerOf2) - XCTAssertFalse(T(sign: .minus, magnitude: 0).isPowerOf2) - - XCTAssertFalse(T(words:[~3] as W).isPowerOf2) - XCTAssertFalse(T(words:[~2] as W).isPowerOf2) - XCTAssertFalse(T(words:[~1] as W).isPowerOf2) - XCTAssertFalse(T(words:[~0] as W).isPowerOf2) - XCTAssertFalse(T(words:[ 0] as W).isPowerOf2) - XCTAssertTrue (T(words:[ 1] as W).isPowerOf2) - XCTAssertTrue (T(words:[ 2] as W).isPowerOf2) - XCTAssertFalse(T(words:[ 3] as W).isPowerOf2) - - XCTAssertFalse(T(words:[ 0, 0, 0, 0] as W).isPowerOf2) - XCTAssertTrue (T(words:[ 1, 0, 0, 0] as W).isPowerOf2) - XCTAssertFalse(T(words:[ 1, 1, 0, 0] as W).isPowerOf2) - XCTAssertTrue (T(words:[ 0, 1, 0, 0] as W).isPowerOf2) - XCTAssertFalse(T(words:[ 0, 1, 1, 0] as W).isPowerOf2) - XCTAssertTrue (T(words:[ 0, 0, 1, 0] as W).isPowerOf2) - XCTAssertFalse(T(words:[ 0, 0, 1, 1] as W).isPowerOf2) - XCTAssertTrue (T(words:[ 0, 0, 0, 1] as W).isPowerOf2) - } - - func testSignum() { - NBKAssertSignum(T(sign: .plus, magnitude: 0), Int( 0)) - NBKAssertSignum(T(sign: .minus, magnitude: 0), Int( 0)) - - NBKAssertSignum(T(words:[ 0] as W), Int( 0)) - NBKAssertSignum(T(words:[ 1] as W), Int( 1)) - NBKAssertSignum(T(words:[ 2] as W), Int( 1)) - - NBKAssertSignum(T(words:[~0] as W), Int(-1)) - NBKAssertSignum(T(words:[~1] as W), Int(-1)) - NBKAssertSignum(T(words:[~2] as W), Int(-1)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testHashing() { - var union = Set() - union.insert(T(sign: .minus, magnitude: M())) - union.insert(T(sign: .minus, magnitude: M())) - union.insert(T(words:[0, 0, 0, 0] as W)) - union.insert(T(words:[0, 0, 0, 0] as W)) - union.insert(T(words:[1, 0, 0, 0] as W)) - union.insert(T(words:[1, 0, 0, 0] as W)) - union.insert(T(words:[0, 1, 0, 0] as W)) - union.insert(T(words:[0, 1, 0, 0] as W)) - union.insert(T(words:[0, 0, 1, 0] as W)) - union.insert(T(words:[0, 0, 1, 0] as W)) - union.insert(T(words:[0, 0, 0, 1] as W)) - union.insert(T(words:[0, 0, 0, 1] as W)) - XCTAssertEqual(union.count, 5 as Int) - } - - func testComparing() { - NBKAssertComparisons( T(0), T(0), Int(0)) - NBKAssertComparisons( T(0), -T(0), Int(0)) - NBKAssertComparisons(-T(0), T(0), Int(0)) - NBKAssertComparisons(-T(0), -T(0), Int(0)) - - NBKAssertComparisons( T(1), T(1), Int(0)) - NBKAssertComparisons( T(1), -T(1), Int(1)) - NBKAssertComparisons(-T(1), T(1), -Int(1)) - NBKAssertComparisons(-T(1), -T(1), Int(0)) - - NBKAssertComparisons( T(2), T(3), -Int(1)) - NBKAssertComparisons( T(2), -T(3), Int(1)) - NBKAssertComparisons(-T(2), T(3), -Int(1)) - NBKAssertComparisons(-T(2), -T(3), Int(1)) - - NBKAssertComparisons( T(3), T(2), Int(1)) - NBKAssertComparisons( T(3), -T(2), Int(1)) - NBKAssertComparisons(-T(3), T(2), -Int(1)) - NBKAssertComparisons(-T(3), -T(2), -Int(1)) - - NBKAssertComparisons(T(words:[0, 2, 3, 4] as W), T(words:[1, 2, 3, 4] as W), -Int(1)) - NBKAssertComparisons(T(words:[1, 0, 3, 4] as W), T(words:[1, 2, 3, 4] as W), -Int(1)) - NBKAssertComparisons(T(words:[1, 2, 0, 4] as W), T(words:[1, 2, 3, 4] as W), -Int(1)) - NBKAssertComparisons(T(words:[1, 2, 3, 0] as W), T(words:[1, 2, 3, 4] as W), -Int(1)) - NBKAssertComparisons(T(words:[0, 2, 3, 4] as W), T(words:[0, 2, 3, 4] as W), Int(0)) - NBKAssertComparisons(T(words:[1, 0, 3, 4] as W), T(words:[1, 0, 3, 4] as W), Int(0)) - NBKAssertComparisons(T(words:[1, 2, 0, 4] as W), T(words:[1, 2, 0, 4] as W), Int(0)) - NBKAssertComparisons(T(words:[1, 2, 3, 0] as W), T(words:[1, 2, 3, 0] as W), Int(0)) - NBKAssertComparisons(T(words:[1, 2, 3, 4] as W), T(words:[0, 2, 3, 4] as W), Int(1)) - NBKAssertComparisons(T(words:[1, 2, 3, 4] as W), T(words:[1, 0, 3, 4] as W), Int(1)) - NBKAssertComparisons(T(words:[1, 2, 3, 4] as W), T(words:[1, 2, 0, 4] as W), Int(1)) - NBKAssertComparisons(T(words:[1, 2, 3, 4] as W), T(words:[1, 2, 3, 0] as W), Int(1)) - } - - func testComparingAtIndex() { - NBKAssertComparisonsAtIndex( T(0), T(0), Int(4), Int(0)) - NBKAssertComparisonsAtIndex( T(0), -T(0), Int(4), Int(0)) - NBKAssertComparisonsAtIndex(-T(0), T(0), Int(4), Int(0)) - NBKAssertComparisonsAtIndex(-T(0), -T(0), Int(4), Int(0)) - - NBKAssertComparisonsAtIndex( T(1), T(1), Int(4), -Int(1)) - NBKAssertComparisonsAtIndex( T(1), -T(1), Int(4), Int(1)) - NBKAssertComparisonsAtIndex(-T(1), T(1), Int(4), -Int(1)) - NBKAssertComparisonsAtIndex(-T(1), -T(1), Int(4), Int(1)) - - NBKAssertComparisonsAtIndex( T(2), T(3), Int(4), -Int(1)) - NBKAssertComparisonsAtIndex( T(2), -T(3), Int(4), Int(1)) - NBKAssertComparisonsAtIndex(-T(2), T(3), Int(4), -Int(1)) - NBKAssertComparisonsAtIndex(-T(2), -T(3), Int(4), Int(1)) - - NBKAssertComparisonsAtIndex( T(3), T(2), Int(4), -Int(1)) - NBKAssertComparisonsAtIndex( T(3), -T(2), Int(4), Int(1)) - NBKAssertComparisonsAtIndex(-T(3), T(2), Int(4), -Int(1)) - NBKAssertComparisonsAtIndex(-T(3), -T(2), Int(4), Int(1)) - - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(0), Int(0)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(1), Int(0)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(2), Int(0)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(3), Int(0)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(4), Int(0)) - - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(0), -Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(1), -Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(2), -Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(3), -Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(4), -Int(1)) - - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(0), Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(1), Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(2), Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(3), Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(4), Int(1)) - - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(0), Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(1), Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(2), Int(0)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(3), -Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(4), -Int(1)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Digit - //=------------------------------------------------------------------------= - - func testComparingByDigit() { - NBKAssertComparisonsByDigit( T(0), Int(0), Int(0)) - NBKAssertComparisonsByDigit( T(0), -Int(0), Int(0)) - NBKAssertComparisonsByDigit(-T(0), Int(0), Int(0)) - NBKAssertComparisonsByDigit(-T(0), -Int(0), Int(0)) - - NBKAssertComparisonsByDigit( T(1), Int(1), Int(0)) - NBKAssertComparisonsByDigit( T(1), -Int(1), Int(1)) - NBKAssertComparisonsByDigit(-T(1), Int(1), -Int(1)) - NBKAssertComparisonsByDigit(-T(1), -Int(1), Int(0)) - - NBKAssertComparisonsByDigit( T(2), Int(3), -Int(1)) - NBKAssertComparisonsByDigit( T(2), -Int(3), Int(1)) - NBKAssertComparisonsByDigit(-T(2), Int(3), -Int(1)) - NBKAssertComparisonsByDigit(-T(2), -Int(3), Int(1)) - - NBKAssertComparisonsByDigit( T(3), Int(2), Int(1)) - NBKAssertComparisonsByDigit( T(3), -Int(2), Int(1)) - NBKAssertComparisonsByDigit(-T(3), Int(2), -Int(1)) - NBKAssertComparisonsByDigit(-T(3), -Int(2), -Int(1)) - - NBKAssertComparisonsByDigit( T(words:[0, 0, 0, 0]), Int(1), -Int(1)) - NBKAssertComparisonsByDigit( T(words:[1, 0, 0, 0]), Int(1), Int(0)) - NBKAssertComparisonsByDigit( T(words:[2, 0, 0, 0]), Int(1), Int(1)) - - NBKAssertComparisonsByDigit( T(words:[0, 1, 0, 0]), Int(1), Int(1)) - NBKAssertComparisonsByDigit( T(words:[1, 1, 0, 0]), Int(1), Int(1)) - NBKAssertComparisonsByDigit( T(words:[2, 1, 0, 0]), Int(1), Int(1)) - - NBKAssertComparisonsByDigit(~T(words:[0, 0, 0, 0]), ~Int(1), Int(1)) - NBKAssertComparisonsByDigit(~T(words:[1, 0, 0, 0]), ~Int(1), Int(0)) - NBKAssertComparisonsByDigit(~T(words:[2, 0, 0, 0]), ~Int(1), -Int(1)) - - NBKAssertComparisonsByDigit(~T(words:[0, 1, 0, 0]), ~Int(1), -Int(1)) - NBKAssertComparisonsByDigit(~T(words:[1, 1, 0, 0]), ~Int(1), -Int(1)) - NBKAssertComparisonsByDigit(~T(words:[2, 1, 0, 0]), ~Int(1), -Int(1)) - } - - func testComparingByDigitAtIndex() { - NBKAssertComparisonsByDigitAtIndex( T(0), Int(0), Int(4), Int(0)) - NBKAssertComparisonsByDigitAtIndex( T(0), -Int(0), Int(4), Int(0)) - NBKAssertComparisonsByDigitAtIndex(-T(0), Int(0), Int(4), Int(0)) - NBKAssertComparisonsByDigitAtIndex(-T(0), -Int(0), Int(4), Int(0)) - - NBKAssertComparisonsByDigitAtIndex( T(1), Int(1), Int(4), -Int(1)) - NBKAssertComparisonsByDigitAtIndex( T(1), -Int(1), Int(4), Int(1)) - NBKAssertComparisonsByDigitAtIndex(-T(1), Int(1), Int(4), -Int(1)) - NBKAssertComparisonsByDigitAtIndex(-T(1), -Int(1), Int(4), Int(1)) - - NBKAssertComparisonsByDigitAtIndex( T(2), Int(3), Int(4), -Int(1)) - NBKAssertComparisonsByDigitAtIndex( T(2), -Int(3), Int(4), Int(1)) - NBKAssertComparisonsByDigitAtIndex(-T(2), Int(3), Int(4), -Int(1)) - NBKAssertComparisonsByDigitAtIndex(-T(2), -Int(3), Int(4), Int(1)) - - NBKAssertComparisonsByDigitAtIndex( T(3), Int(2), Int(4), -Int(1)) - NBKAssertComparisonsByDigitAtIndex( T(3), -Int(2), Int(4), Int(1)) - NBKAssertComparisonsByDigitAtIndex(-T(3), Int(2), Int(4), -Int(1)) - NBKAssertComparisonsByDigitAtIndex(-T(3), -Int(2), Int(4), Int(1)) - - NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), Int(4), Int(0), Int(1)) - NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), Int(4), Int(1), Int(1)) - NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), Int(4), Int(2), Int(1)) - NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), Int(4), Int(3), Int(1)) - NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), Int(4), Int(4), -Int(1)) - - NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), Int(5), Int(0), Int(1)) - NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), Int(5), Int(1), Int(1)) - NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), Int(5), Int(2), Int(1)) - NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), Int(5), Int(3), -Int(1)) - NBKAssertComparisonsByDigitAtIndex(T(words:[1, 2, 3, 4]), Int(5), Int(4), -Int(1)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Miscellaneous - //=------------------------------------------------------------------------= - - func testOverloadsAreUnambiguous() { - func becauseThisCompilesSuccessfully(_ x: inout T) { - XCTAssertNotNil(x.signum()) - } - } - - func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { - func becauseThisCompilesSuccessfully(_ x: inout T) { - XCTAssertNotNil(x.compared(to: 0)) - XCTAssertNotNil(x.compared(to: 0, at: 0)) - } - } -} - //*============================================================================* // MARK: * NBK x Flexible Width x Comparisons x UIntXL //*============================================================================* diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Complements.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Complements.swift index e2fb39f2..9b9e6bba 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Complements.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Complements.swift @@ -17,88 +17,6 @@ private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] -//*============================================================================* -// MARK: * NBK x Flexible Width x Complements x IntXL -//*============================================================================* - -final class NBKFlexibleWidthTestsOnComplementsAsIntXL: XCTestCase { - - typealias T = IntXL - typealias M = UIntXL - - //=------------------------------------------------------------------------= - // MARK: Tests x Magnitude - //=------------------------------------------------------------------------= - - func testMagnitude() { - XCTAssertEqual(T(words:[ 1, 0, 0, 0] as W).magnitude, M(words:[ 1, 0, 0, 0] as W)) - XCTAssertEqual(T(words:[~0, 0, 0, 0] as W).magnitude, M(words:[~0, 0, 0, 0] as W)) - XCTAssertEqual(T(words:[ 1, 1, 1, 1] as W).magnitude, M(words:[ 1, 1, 1, 1] as W)) - XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).magnitude, M(words:[ 1, 0, 0, 0] as W)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x One's Complement - //=------------------------------------------------------------------------= - - func testOnesComplement() { - NBKAssertOnesComplement(-T(1), T(0)) - NBKAssertOnesComplement(-T(0), -T(1)) - NBKAssertOnesComplement( T(0), -T(1)) - NBKAssertOnesComplement( T(1), -T(2)) - - NBKAssertOnesComplement(T(words:[ 0, 0, 0, 0] as W), T(words:[~0, ~0, ~0, ~0] as W)) - NBKAssertOnesComplement(T(words:[ 1, 0, 0, 0] as W), T(words:[~1, ~0, ~0, ~0] as W)) - NBKAssertOnesComplement(T(words:[~0, 0, 0, 0] as W), T(words:[ 0, ~0, ~0, ~0] as W)) - NBKAssertOnesComplement(T(words:[ 1, 1, 1, 1] as W), T(words:[~1, ~1, ~1, ~1] as W)) - NBKAssertOnesComplement(T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 0, 0, 0, 0] as W)) - - NBKAssertOnesComplement(T(words:[~0, ~0, ~0, ~0/2 + 0, 0] as W), T(words:[ 0, 0, 0, ~0/2 + 1, ~0] as W)) - NBKAssertOnesComplement(T(words:[ 0, 0, 0, ~0/2 + 1, 0] as W), T(words:[~0, ~0, ~0, ~0/2 + 0, ~0] as W)) - NBKAssertOnesComplement(T(words:[ 1, 0, 0, ~0/2 + 1, 0] as W), T(words:[~1, ~0, ~0, ~0/2 + 0, ~0] as W)) - - NBKAssertOnesComplement(T(words:[ 1, 0, 0, ~0/2 + 1, ~0] as W), T(words:[~1, ~0, ~0, ~0/2 + 0, 0] as W)) - NBKAssertOnesComplement(T(words:[ 0, 0, 0, ~0/2 + 1, ~0] as W), T(words:[~0, ~0, ~0, ~0/2 + 0, 0] as W)) - NBKAssertOnesComplement(T(words:[~0, ~0, ~0, ~0/2 + 0, ~0] as W), T(words:[ 0, 0, 0, ~0/2 + 1, 0] as W)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Two's Complement - //=------------------------------------------------------------------------= - - func testTwosComplement() { - NBKAssertTwosComplement(-T(1), T(1)) - NBKAssertTwosComplement(-T(0), T(0)) - NBKAssertTwosComplement( T(0), -T(0)) - NBKAssertTwosComplement( T(1), -T(1)) - - NBKAssertTwosComplement(T(words:[ 0, 0, 0, 0] as W), T(words:[ 0, 0, 0, 0] as W)) - NBKAssertTwosComplement(T(words:[ 1, 0, 0, 0] as W), T(words:[~0, ~0, ~0, ~0] as W)) - NBKAssertTwosComplement(T(words:[~0, 0, 0, 0] as W), T(words:[ 1, ~0, ~0, ~0] as W)) - NBKAssertTwosComplement(T(words:[ 1, 1, 1, 1] as W), T(words:[~0, ~1, ~1, ~1] as W)) - NBKAssertTwosComplement(T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 1, 0, 0, 0] as W)) - - NBKAssertTwosComplement(T(words:[~0, ~0, ~0, ~0/2 + 0, 0] as W), T(words:[ 1, 0, 0, ~0/2 + 1, ~0] as W)) - NBKAssertTwosComplement(T(words:[ 0, 0, 0, ~0/2 + 1, 0] as W), T(words:[ 0, 0, 0, ~0/2 + 1, ~0] as W)) - NBKAssertTwosComplement(T(words:[ 1, 0, 0, ~0/2 + 1, 0] as W), T(words:[~0, ~0, ~0, ~0/2 + 0, ~0] as W)) - - NBKAssertTwosComplement(T(words:[ 1, 0, 0, ~0/2 + 1, ~0] as W), T(words:[~0, ~0, ~0, ~0/2 + 0, 0] as W)) - NBKAssertTwosComplement(T(words:[ 0, 0, 0, ~0/2 + 1, ~0] as W), T(words:[ 0, 0, 0, ~0/2 + 1, ~0] as W), true) - NBKAssertTwosComplement(T(words:[~0, ~0, ~0, ~0/2 + 0, ~0] as W), T(words:[ 1, 0, 0, ~0/2 + 1, 0] as W)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Additive Inverse - //=------------------------------------------------------------------------= - - func testAdditiveInverse() { - NBKAssertAdditiveInverse(T(sign: .plus, magnitude: M( )), T(sign: .minus, magnitude: M( ))) - NBKAssertAdditiveInverse(T(sign: .minus, magnitude: M( )), T(sign: .plus, magnitude: M( ))) - NBKAssertAdditiveInverse(T(sign: .plus, magnitude: M(1)), T(sign: .minus, magnitude: M(1))) - NBKAssertAdditiveInverse(T(sign: .minus, magnitude: M(1)), T(sign: .plus, magnitude: M(1))) - } -} - //*============================================================================* // MARK: * NBK x Flexible Width x Complements x UIntXL //*============================================================================* @@ -190,21 +108,4 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual({ var x = integer; let o = x.formTwosComplementSubsequence(true ); return o }(), overflow, file: file, line: line) } -private func NBKAssertAdditiveInverse( -_ operand: IntXL, _ partialValue: IntXL, _ overflow: Bool = false, -file: StaticString = #file, line: UInt = #line) { - //=------------------------------------------= - if !overflow { - NBKAssertIdentical(-operand, partialValue, file: file, line: line) - NBKAssertIdentical((operand).negated(), partialValue, file: file, line: line) - NBKAssertIdentical({ var x = operand; x.negate(); return x }(), partialValue, file: file, line: line) - } - //=------------------------------------------= - NBKAssertIdentical(operand.negatedReportingOverflow().partialValue, partialValue, file: file, line: line) - XCTAssertEqual/**/(operand.negatedReportingOverflow().overflow, overflow, file: file, line: line) - - NBKAssertIdentical({ var x = operand; let _ = x.negateReportingOverflow(); return x }(), partialValue, file: file, line: line) - XCTAssertEqual/**/({ var x = operand; let o = x.negateReportingOverflow(); return o }(), overflow, file: file, line: line) -} - #endif diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Division.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Division.swift index e378a2f4..aae22f35 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Division.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Division.swift @@ -17,132 +17,6 @@ private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] -//*============================================================================* -// MARK: * NBK x Flexible Width x Division x IntXL -//*============================================================================* - -final class NBKFlexibleWidthTestsOnDivisionAsIntXL: XCTestCase { - - typealias T = IntXL - typealias M = UIntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testDividing() { - NBKAssertDivision( T( ), T(1), T( ), T( )) - NBKAssertDivision( T( ), T(2), T( ), T( )) - NBKAssertDivision( T(7), T(1), T(7), T( )) - NBKAssertDivision( T(7), T(2), T(3), T(1)) - - NBKAssertDivision( T(7), T(3), T(2), T(1)) - NBKAssertDivision( T(7), -T(3), -T(2), T(1)) - NBKAssertDivision(-T(7), T(3), -T(2), -T(1)) - NBKAssertDivision(-T(7), -T(3), T(2), -T(1)) - } - - func testDividingReportingOverflow() { - NBKAssertDivision( T(0), T( ), T(0), T( ), true) - NBKAssertDivision( T(1), T( ), T(1), T(1), true) - NBKAssertDivision( T(2), T( ), T(2), T(2), true) - - NBKAssertDivision(T(words:[~0, ~0, ~0, ~0/2 + 0] as W), -T(1), T(words:[1, 0, 0, ~0/2 + 1, ~0] as W), T( )) // Int256.max - NBKAssertDivision(T(words:[ 0, 0, 0, ~0/2 + 1] as W), -T(1), T(words:[0, 0, 0, ~0/2 + 1, 0] as W), T( )) // Int256.min - } - - func testDividingWithLargeDividend() { - NBKAssertDivision( T(words:[1, 2, 3, 4] as W), T(2), T(words:[0, ~0/2 + 2, 1, 2] as W), T(1)) - NBKAssertDivision( T(words:[1, 2, 3, 4] as W), -T(2), -T(words:[0, ~0/2 + 2, 1, 2] as W), T(1)) - NBKAssertDivision(-T(words:[1, 2, 3, 4] as W), T(2), -T(words:[0, ~0/2 + 2, 1, 2] as W), -T(1)) - NBKAssertDivision(-T(words:[1, 2, 3, 4] as W), -T(2), T(words:[0, ~0/2 + 2, 1, 2] as W), -T(1)) - - NBKAssertDivision( T(words:[1, 2, 3, 4] as W), T(words:[0, ~0/2 + 2, 1, 2] as W), T(2), T(1)) - NBKAssertDivision( T(words:[1, 2, 3, 4] as W), -T(words:[0, ~0/2 + 2, 1, 2] as W), -T(2), T(1)) - NBKAssertDivision(-T(words:[1, 2, 3, 4] as W), -T(words:[0, ~0/2 + 2, 1, 2] as W), T(2), -T(1)) - NBKAssertDivision(-T(words:[1, 2, 3, 4] as W), T(words:[0, ~0/2 + 2, 1, 2] as W), -T(2), -T(1)) - } - - func testDividingWithLargeDivisor() { - NBKAssertDivision(T(words:[1, 2, 3, 4 + 1 << 63] as W), T(words:[ 1, 2, 3, 4 &+ 1 << 63] as W), T(1), -T(words:[0, 0, 0, 0] as W)) - NBKAssertDivision(T(words:[1, 2, 3, 4 + 1 << 63] as W), T(words:[ 2, 3, 4, 5 &+ 1 << 63] as W), T(1), -T(words:[1, 1, 1, 1] as W)) - NBKAssertDivision(T(words:[1, 2, 3, 4 + 1 << 63] as W), T(words:[ 3, 4, 5, 6 &+ 1 << 63] as W), T(1), -T(words:[2, 2, 2, 2] as W)) - NBKAssertDivision(T(words:[1, 2, 3, 4 + 1 << 63] as W), T(words:[ 4, 5, 6, 7 &+ 1 << 63] as W), T(1), -T(words:[3, 3, 3, 3] as W)) - NBKAssertDivision(T(words:[1, 2, 3, 4 + 1 << 63] as W), T(words:[~0, ~2, ~3, ~4 &+ 1 << 63] as W), -T(1), -T(words:[0, 0, 0, 0] as W)) - NBKAssertDivision(T(words:[1, 2, 3, 4 + 1 << 63] as W), T(words:[~1, ~3, ~4, ~5 &+ 1 << 63] as W), -T(1), -T(words:[1, 1, 1, 1] as W)) - NBKAssertDivision(T(words:[1, 2, 3, 4 + 1 << 63] as W), T(words:[~2, ~4, ~5, ~6 &+ 1 << 63] as W), -T(1), -T(words:[2, 2, 2, 2] as W)) - NBKAssertDivision(T(words:[1, 2, 3, 4 + 1 << 63] as W), T(words:[~3, ~5, ~6, ~7 &+ 1 << 63] as W), -T(1), -T(words:[3, 3, 3, 3] as W)) - } - - func testDividingLikeFullWidth() { - var dividend: T - //=--------------------------------------= - dividend = T(words:[ 06, 17, 35, 61, 61, 52, 32, 00] as W) - NBKAssertDivision(dividend, T(words:[ 1, 2, 3, 4] as W), T(words:[ 5, 6, 7, 8] as W), T(words:[ 1, 1, 1, 1] as W)) - NBKAssertDivision(dividend, T(words:[ 5, 6, 7, 8] as W), T(words:[ 1, 2, 3, 4] as W), T(words:[ 1, 1, 1, 1] as W)) - //=--------------------------------------= - dividend = T(words:[ 34, 54, 63, 62, 34, 16, 05, 00] as W) - NBKAssertDivision(dividend, T(words:[ 4, 3, 2, 1] as W), T(words:[ 9, 7, 6, 5] as W), T(words:[~1, ~1, ~0, 0] as W)) - NBKAssertDivision(dividend, T(words:[ 8, 7, 6, 5] as W), T(words:[ 4, 3, 2, 1] as W), T(words:[ 2, 2, 2, 2] as W)) - //=--------------------------------------= - dividend = T(words:[ ~1, ~0, ~0, ~0, ~0, ~0, ~0, ~0] as W) - NBKAssertDivision(dividend, T(words:[ 1, 0, 0, 0] as W), T(words:[~1, ~0, ~0, ~0] as W), T(words:[ 0, 0, 0, 0] as W)) - NBKAssertDivision(dividend, T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 2, 0, 0, 0] as W), T(words:[ 0, 0, 0, 0] as W)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Digit - //=------------------------------------------------------------------------= - - func testDividingByDigit() { - NBKAssertDivisionByDigit( T( ), Int(1), T( ), Int( )) - NBKAssertDivisionByDigit( T( ), Int(2), T( ), Int( )) - NBKAssertDivisionByDigit( T(7), Int(1), T(7), Int( )) - NBKAssertDivisionByDigit( T(7), Int(2), T(3), Int(1)) - - NBKAssertDivisionByDigit( T(7), Int(3), T(2), Int(1)) - NBKAssertDivisionByDigit( T(7), -Int(3), -T(2), Int(1)) - NBKAssertDivisionByDigit(-T(7), Int(3), -T(2), -Int(1)) - NBKAssertDivisionByDigit(-T(7), -Int(3), T(2), -Int(1)) - } - - func testDividingByDigitReportingOverflow() { - NBKAssertDivisionByDigit( T(0), Int( ), T( 0), Int( ), true) - NBKAssertDivisionByDigit( T(1), Int( ), T( 1), Int(1), true) - NBKAssertDivisionByDigit( T(2), Int( ), T( 2), Int(2), true) - - NBKAssertDivisionByDigit(T(words:[~0, ~0, ~0, ~0/2 + 0] as W), -Int(1), T(words:[1, 0, 0, ~0/2 + 1, ~0] as W), Int( )) // Int256.max - NBKAssertDivisionByDigit(T(words:[ 0, 0, 0, ~0/2 + 1] as W), -Int(1), T(words:[0, 0, 0, ~0/2 + 1, 0] as W), Int( )) // Int256.min - } - - func testDividingByDigitWithLargeDividend() { - NBKAssertDivisionByDigit( T(words:[1, 2, 3, 4] as W), Int(2), T(words:[0, ~0/2 + 2, 1, 2] as W), Int(1)) - NBKAssertDivisionByDigit( T(words:[1, 2, 3, 4] as W), -Int(2), -T(words:[0, ~0/2 + 2, 1, 2] as W), Int(1)) - NBKAssertDivisionByDigit(-T(words:[1, 2, 3, 4] as W), Int(2), -T(words:[0, ~0/2 + 2, 1, 2] as W), -Int(1)) - NBKAssertDivisionByDigit(-T(words:[1, 2, 3, 4] as W), -Int(2), T(words:[0, ~0/2 + 2, 1, 2] as W), -Int(1)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Miscellaneous - //=------------------------------------------------------------------------= - - func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { - func becauseThisCompilesSuccessfully(_ x: inout T) { - XCTAssertNotNil(x /= 0) - XCTAssertNotNil(x %= 0) - XCTAssertNotNil(x.divideReportingOverflow(by: 0)) - XCTAssertNotNil(x.formRemainderReportingOverflow(dividingBy: 0)) - - XCTAssertNotNil(x / 0) - XCTAssertNotNil(x % 0) - XCTAssertNotNil(x.dividedReportingOverflow(by: 0)) - XCTAssertNotNil(x.remainderReportingOverflow(dividingBy: 0)) - XCTAssertNotNil(x.quotientAndRemainder(dividingBy: 0)) - XCTAssertNotNil(x.quotientAndRemainderReportingOverflow(dividingBy: 0)) - } - } -} - //*============================================================================* // MARK: * NBK x Flexible Width x Division x UIntXL //*============================================================================* @@ -286,7 +160,7 @@ final class NBKFlexibleWidthTestsOnDivisionCodeCoverageAsUIntXL: XCTestCase { // MARK: * NBK x Flexible Width x Division x Assertions //*============================================================================* -private func NBKAssertDivision( +private func NBKAssertDivision( _ lhs: T, _ rhs: T, _ quotient: T, _ remainder: T, _ overflow: Bool = false, file: StaticString = #file, line: UInt = #line) { //=------------------------------------------= @@ -331,7 +205,7 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual(lhs.quotientAndRemainderReportingOverflowAsNormal(dividingBy: rhs).overflow, overflow, file: file, line: line) } -private func NBKAssertDivisionByDigit( +private func NBKAssertDivisionByDigit( _ lhs: T, _ rhs: T.Digit, _ quotient: T, _ remainder: T.Digit, _ overflow: Bool = false, file: StaticString = #file, line: UInt = #line) { let extended = T(digit: remainder) diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Literals.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Literals.swift index b850125c..3a8403ed 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Literals.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Literals.swift @@ -17,83 +17,6 @@ private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] -//*============================================================================* -// MARK: * NBK x Flexible Width x Literals x IntXL -//*============================================================================* - -final class NBKFlexibleWidthTestsOnLiteralsAsIntXL: XCTestCase { - - typealias T = IntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testFromIntegerLiteral() { - XCTAssertEqual(T(x64:[ 10, 0, 0, 0] as X), (10)) - XCTAssertEqual(T(x64:[ 02, 0, 0, 0] as X), (0b10)) - XCTAssertEqual(T(x64:[ 08, 0, 0, 0] as X), (0o10)) - XCTAssertEqual(T(x64:[ 16, 0, 0, 0] as X), (0x10)) - XCTAssertEqual(T(x64:[ 16, 0, 0, 0] as X), (0x10)) - XCTAssertEqual(T(x64:[ ~9, ~0, ~0, ~0] as X), (-10)) - XCTAssertEqual(T(x64:[ ~1, ~0, ~0, ~0] as X), (-0b10)) - XCTAssertEqual(T(x64:[ ~7, ~0, ~0, ~0] as X), (-0o10)) - XCTAssertEqual(T(x64:[~15, ~0, ~0, ~0] as X), (-0x10)) - #if SBI && swift(>=5.8) - XCTAssertEqual(T(x64:[ 0, 0, 0, 0] as X), (0x000000000000000000000000000000000000000000000000000000000000000000000000000000)) - XCTAssertEqual(T(x64:[ ~0, 0, 0, 0] as X), (0x00000000000000000000000000000000000000000000000000000000000000ffffffffffffffff)) - XCTAssertEqual(T(x64:[ ~0, ~0, 0, 0] as X), (0x0000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffff)) - XCTAssertEqual(T(x64:[ ~0, ~0, ~0, 0] as X), (0x000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff)) - XCTAssertEqual(T(x64:[ ~0, ~0, ~0, ~0] as X), (-0x000000000000000000000000000000000000000000000000000000000000000000000000000001)) - XCTAssertEqual(T(x64:[ 0, ~0, ~0, ~0] as X), (-0x000000000000000000000000000000000000000000000000000000000000010000000000000000)) - XCTAssertEqual(T(x64:[ 0, 0, ~0, ~0] as X), (-0x000000000000000000000000000000000000000000000100000000000000000000000000000000)) - XCTAssertEqual(T(x64:[ 0, 0, 0, ~0] as X), (-0x000000000000000000000000000001000000000000000000000000000000000000000000000000)) - - XCTAssertEqual(T(x64:[ 0, 0, 0, 0] as X), (00000000000000000000000000000000000000000000000000000000000000000000000000000000)) - XCTAssertEqual(T(x64:[ ~0, 0, 0, 0] as X), (00000000000000000000000000000000000000000000000000000000000018446744073709551615)) - XCTAssertEqual(T(x64:[ ~0, ~0, 0, 0] as X), (00000000000000000000000000000000000000000340282366920938463463374607431768211455)) - XCTAssertEqual(T(x64:[ ~0, ~0, ~0, 0] as X), (00000000000000000000006277101735386680763835789423207666416102355444464034512895)) - XCTAssertEqual(T(x64:[ ~0, ~0, ~0, ~0] as X), (-00000000000000000000000000000000000000000000000000000000000000000000000000000001)) - XCTAssertEqual(T(x64:[ 0, ~0, ~0, ~0] as X), (-00000000000000000000000000000000000000000000000000000000000018446744073709551616)) - XCTAssertEqual(T(x64:[ 0, 0, ~0, ~0] as X), (-00000000000000000000000000000000000000000340282366920938463463374607431768211456)) - XCTAssertEqual(T(x64:[ 0, 0, 0, ~0] as X), (-00000000000000000000006277101735386680763835789423207666416102355444464034512896)) - #else - XCTAssertEqual(T(integerLiteral: Int.max), T(x64:[UInt64(Int.max), 0, 0, 0] as X)) - XCTAssertEqual(T(integerLiteral: Int.min), ~T(x64:[UInt64(Int.max), 0, 0, 0] as X)) - #endif - } - - func testFromStringLiteral() { - XCTAssertEqual(T(x64:[ 10, 0, 0, 0] as X), "10") - XCTAssertEqual(T(x64:[ 02, 0, 0, 0] as X), "0b10") - XCTAssertEqual(T(x64:[ 08, 0, 0, 0] as X), "0o10") - XCTAssertEqual(T(x64:[ 16, 0, 0, 0] as X), "0x10") - XCTAssertEqual(T(x64:[ 16, 0, 0, 0] as X), "0x10") - XCTAssertEqual(T(x64:[ ~9, ~0, ~0, ~0] as X), "-10") - XCTAssertEqual(T(x64:[ ~1, ~0, ~0, ~0] as X), "-0b10") - XCTAssertEqual(T(x64:[ ~7, ~0, ~0, ~0] as X), "-0o10") - XCTAssertEqual(T(x64:[~15, ~0, ~0, ~0] as X), "-0x10") - - XCTAssertEqual(T(x64:[ 0, 0, 0, 0] as X), "0x000000000000000000000000000000000000000000000000000000000000000000000000000000") - XCTAssertEqual(T(x64:[ ~0, 0, 0, 0] as X), "0x00000000000000000000000000000000000000000000000000000000000000ffffffffffffffff") - XCTAssertEqual(T(x64:[ ~0, ~0, 0, 0] as X), "0x0000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffff") - XCTAssertEqual(T(x64:[ ~0, ~0, ~0, 0] as X), "0x000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff") - XCTAssertEqual(T(x64:[ ~0, ~0, ~0, ~0] as X), "-0x000000000000000000000000000000000000000000000000000000000000000000000000000001") - XCTAssertEqual(T(x64:[ 0, ~0, ~0, ~0] as X), "-0x000000000000000000000000000000000000000000000000000000000000010000000000000000") - XCTAssertEqual(T(x64:[ 0, 0, ~0, ~0] as X), "-0x000000000000000000000000000000000000000000000100000000000000000000000000000000") - XCTAssertEqual(T(x64:[ 0, 0, 0, ~0] as X), "-0x000000000000000000000000000001000000000000000000000000000000000000000000000000") - - XCTAssertEqual(T(x64:[ 0, 0, 0, 0] as X), "00000000000000000000000000000000000000000000000000000000000000000000000000000000") - XCTAssertEqual(T(x64:[ ~0, 0, 0, 0] as X), "00000000000000000000000000000000000000000000000000000000000018446744073709551615") - XCTAssertEqual(T(x64:[ ~0, ~0, 0, 0] as X), "00000000000000000000000000000000000000000340282366920938463463374607431768211455") - XCTAssertEqual(T(x64:[ ~0, ~0, ~0, 0] as X), "00000000000000000000006277101735386680763835789423207666416102355444464034512895") - XCTAssertEqual(T(x64:[ ~0, ~0, ~0, ~0] as X), "-00000000000000000000000000000000000000000000000000000000000000000000000000000001") - XCTAssertEqual(T(x64:[ 0, ~0, ~0, ~0] as X), "-00000000000000000000000000000000000000000000000000000000000018446744073709551616") - XCTAssertEqual(T(x64:[ 0, 0, ~0, ~0] as X), "-00000000000000000000000000000000000000000340282366920938463463374607431768211456") - XCTAssertEqual(T(x64:[ 0, 0, 0, ~0] as X), "-00000000000000000000006277101735386680763835789423207666416102355444464034512896") - } -} - //*============================================================================* // MARK: * NBK x Flexible Width x Literals x UIntXL //*============================================================================* diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Logic.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Logic.swift index d354ff87..7bf2e85c 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Logic.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Logic.swift @@ -17,39 +17,6 @@ private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] -//*============================================================================* -// MARK: * NBK x Flexible Width x Logic x IntXL -//*============================================================================* - -final class NBKFlexibleWidthTestsOnLogicAsIntXL: XCTestCase { - - typealias T = IntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testNot() { - NBKAssertNot(T(words:[ 0, 0, 0, 0] as W), T(words:[~0, ~0, ~0, ~0] as W)) - NBKAssertNot(T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 0, 0, 0, 0] as W)) - - NBKAssertNot(T(words:[ 0, 1, 2, 3] as W), T(words:[~0, ~1, ~2, ~3] as W)) - NBKAssertNot(T(words:[~0, ~1, ~2, ~3] as W), T(words:[ 0, 1, 2, 3] as W)) - } - - func testAnd() { - // TODO: (!) - } - - func testOr() { - // TODO: (!) - } - - func testXor() { - // TODO: (!) - } -} - //*============================================================================* // MARK: * NBK x Flexible Width x Logic x UIntXL //*============================================================================* @@ -108,7 +75,7 @@ final class NBKFlexibleWidthTestsOnLogicAsUIntXL: XCTestCase { // MARK: * NBK x Flexible Width x Logic x Assertions //*============================================================================* -private func NBKAssertNot( +private func NBKAssertNot( _ operand: T, _ result: T, file: StaticString = #file, line: UInt = #line) { if operand.words.last != UInt.max { @@ -119,7 +86,7 @@ file: StaticString = #file, line: UInt = #line) { } } -private func NBKAssertAnd( +private func NBKAssertAnd( _ lhs: T, _ rhs: T, _ result: T, file: StaticString = #file, line: UInt = #line) { XCTAssertEqual( lhs & rhs, result, file: file, line: line) @@ -128,7 +95,7 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual({ var rhs = rhs; rhs &= lhs; return rhs }(), result, file: file, line: line) } -private func NBKAssertOr( +private func NBKAssertOr( _ lhs: T, _ rhs: T, _ result: T, file: StaticString = #file, line: UInt = #line) { XCTAssertEqual( lhs | rhs, result, file: file, line: line) @@ -137,7 +104,7 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual({ var rhs = rhs; rhs |= lhs; return rhs }(), result, file: file, line: line) } -private func NBKAssertXor( +private func NBKAssertXor( _ lhs: T, _ rhs: T, _ result: T, file: StaticString = #file, line: UInt = #line) { XCTAssertEqual( lhs ^ rhs, result, file: file, line: line) diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Multiplication.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Multiplication.swift index f0668a10..e236c25a 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Multiplication.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Multiplication.swift @@ -17,64 +17,6 @@ private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] -//*============================================================================* -// MARK: * NBK x Flexible Width x Multiplication x IntXL -//*============================================================================* - -final class NBKFlexibleWidthTestsOnMultiplicationAsIntXL: XCTestCase { - - typealias T = IntXL - typealias M = UIntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testMultiplying() { - NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as W), T(words:[2, 0, 0, 0] as W), T(words:[ 2, 4, 6, 8, 0, 0, 0, 0] as W)) - NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as W), T(words:[0, 2, 0, 0] as W), T(words:[ 0, 2, 4, 6, 8, 0, 0, 0] as W)) - NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as W), T(words:[0, 0, 2, 0] as W), T(words:[ 0, 0, 2, 4, 6, 8, 0, 0] as W)) - NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as W), T(words:[0, 0, 0, 2] as W), T(words:[ 0, 0, 0, 2, 4, 6, 8, 0] as W)) - - NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as W), -T(words:[2, 0, 0, 0] as W), T(words:[~1, ~4, ~6, ~8, ~0, ~0, ~0, ~0] as W)) - NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as W), -T(words:[0, 2, 0, 0] as W), T(words:[ 0, ~1, ~4, ~6, ~8, ~0, ~0, ~0] as W)) - NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as W), -T(words:[0, 0, 2, 0] as W), T(words:[ 0, 0, ~1, ~4, ~6, ~8, ~0, ~0] as W)) - NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as W), -T(words:[0, 0, 0, 2] as W), T(words:[ 0, 0, 0, ~1, ~4, ~6, ~8, ~0] as W)) - - NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as W), T(words:[2, 0, 0, 0] as W), T(words:[~3, ~4, ~6, ~8, ~0, ~0, ~0, ~0] as W)) - NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as W), T(words:[0, 2, 0, 0] as W), T(words:[ 0, ~3, ~4, ~6, ~8, ~0, ~0, ~0] as W)) - NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as W), T(words:[0, 0, 2, 0] as W), T(words:[ 0, 0, ~3, ~4, ~6, ~8, ~0, ~0] as W)) - NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as W), T(words:[0, 0, 0, 2] as W), T(words:[ 0, 0, 0, ~3, ~4, ~6, ~8, ~0] as W)) - - NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as W), -T(words:[2, 0, 0, 0] as W), T(words:[ 4, 4, 6, 8, 0, 0, 0, 0] as W)) - NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as W), -T(words:[0, 2, 0, 0] as W), T(words:[ 0, 4, 4, 6, 8, 0, 0, 0] as W)) - NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as W), -T(words:[0, 0, 2, 0] as W), T(words:[ 0, 0, 4, 4, 6, 8, 0, 0] as W)) - NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as W), -T(words:[0, 0, 0, 2] as W), T(words:[ 0, 0, 0, 4, 4, 6, 8, 0] as W)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Digit - //=------------------------------------------------------------------------= - - func testMultiplyingByDigit() { - NBKAssertMultiplicationByDigit(T(words:[ 1, 2, 3, 4] as W), Int(2), T(words:[ 2, 4, 6, 8, 0] as W)) - NBKAssertMultiplicationByDigit(T(words:[ 1, 2, 3, 4] as W), -Int(2), T(words:[~1, ~4, ~6, ~8, ~0] as W)) - NBKAssertMultiplicationByDigit(T(words:[~1, ~2, ~3, ~4] as W), Int(2), T(words:[~3, ~4, ~6, ~8, ~0] as W)) - NBKAssertMultiplicationByDigit(T(words:[~1, ~2, ~3, ~4] as W), -Int(2), T(words:[ 4, 4, 6, 8, 0] as W)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Miscellaneous - //=------------------------------------------------------------------------= - - func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { - func becauseThisCompilesSuccessfully(_ x: inout T) { - XCTAssertNotNil(x *= 0) - XCTAssertNotNil(x * 0) - } - } -} - //*============================================================================* // MARK: * NBK x Flexible Width x Multiplication x UIntXL //*============================================================================* @@ -159,7 +101,7 @@ file: StaticString = #file, line: UInt = #line) { } //=----------------------------------------------------------------------------= -// MARK: + Unsigned +// MARK: + UIntXL //=----------------------------------------------------------------------------= private func NBKAssertMultiplicationByDigitWithAddition( diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Numbers.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Numbers.swift index c94ba3ad..ad86ae36 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Numbers.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Numbers.swift @@ -17,271 +17,6 @@ private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] -//*============================================================================* -// MARK: * NBK x Flexible Width x Numbers x IntXL -//*============================================================================* - -final class NBKFlexibleWidthTestsOnNumbersAsIntXL: XCTestCase { - - typealias S = IntXL - typealias T = IntXL - typealias M = UIntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testZero() { - XCTAssertEqual(T( 0), T(words:[0])) - XCTAssertEqual(T.zero, T(words:[0])) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Int - //=------------------------------------------------------------------------= - - func testToInt() { - NBKAssertNumbers(from: T(words:[ 1, 0, 0, 0] as W), default: Int( 1)) - NBKAssertNumbers(from: T(words:[~0, 0, 0, 0] as W), exactly: nil, clamping: Int.max, truncating: -1) - NBKAssertNumbers(from: T(words:[ 1, 1, 1, 1] as W), exactly: nil, clamping: Int.max, truncating: 1) - NBKAssertNumbers(from: T(words:[~0, ~0, ~0, ~0] as W), default: Int(-1)) - } - - func testFromInt() { - NBKAssertNumbers(from: Int.min, default: ~T(words:[UInt(Int.max), 0, 0, 0] as W)) - NBKAssertNumbers(from: Int.max, default: T(words:[UInt(Int.max), 0, 0, 0] as W)) - } - - func testFromIntAsDigit() { - NBKAssertNumbers(from: T(digit: Int.min), default: ~T(words:[UInt(Int.max), 0, 0, 0] as W)) - NBKAssertNumbers(from: T(digit: Int.max), default: T(words:[UInt(Int.max), 0, 0, 0] as W)) - } - - func testFromIntAsDigitAtIndex() { - NBKAssertNumbers(from: T(digit: Int( 4), at: Int(0)), default: T(words:[ 4, 0, 0, 0] as W)) - NBKAssertNumbers(from: T(digit: Int( 4), at: Int(1)), default: T(words:[ 0, 4, 0, 0] as W)) - NBKAssertNumbers(from: T(digit: Int( 4), at: Int(2)), default: T(words:[ 0, 0, 4, 0] as W)) - NBKAssertNumbers(from: T(digit: Int( 4), at: Int(3)), default: T(words:[ 0, 0, 0, 4] as W)) - - NBKAssertNumbers(from: T(digit: Int(-4), at: Int(0)), default: T(words:[~3, ~0, ~0, ~0] as W)) - NBKAssertNumbers(from: T(digit: Int(-4), at: Int(1)), default: T(words:[ 0, ~3, ~0, ~0] as W)) - NBKAssertNumbers(from: T(digit: Int(-4), at: Int(2)), default: T(words:[ 0, 0, ~3, ~0] as W)) - NBKAssertNumbers(from: T(digit: Int(-4), at: Int(3)), default: T(words:[ 0, 0, 0, ~3] as W)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Int32 - //=------------------------------------------------------------------------= - - func testToInt32() { - NBKAssertNumbers(from: T(x32:[ 1, 0, 0, 0] as Y), default: Int32( 1)) - NBKAssertNumbers(from: T(x32:[~0, 0, 0, 0] as Y), exactly: nil, clamping: Int32.max, truncating: -1) - NBKAssertNumbers(from: T(x32:[ 1, 1, 1, 1] as Y), exactly: nil, clamping: Int32.max, truncating: 1) - NBKAssertNumbers(from: T(x32:[~0, ~0, ~0, ~0] as Y), default: Int32(-1)) - } - - func testFromInt32() { - NBKAssertNumbers(from: Int32.min, default: T(words: Int32.min.words)) - NBKAssertNumbers(from: Int32.max, default: T(words: Int32.max.words)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Int64 - //=------------------------------------------------------------------------= - - func testToInt64() { - NBKAssertNumbers(from: T(x64:[ 1, 0, 0, 0] as X), default: Int64( 1)) - NBKAssertNumbers(from: T(x64:[~0, 0, 0, 0] as X), exactly: nil, clamping: Int64.max, truncating: -1) - NBKAssertNumbers(from: T(x64:[ 1, 1, 1, 1] as X), exactly: nil, clamping: Int64.max, truncating: 1) - NBKAssertNumbers(from: T(x64:[~0, ~0, ~0, ~0] as X), default: Int64(-1)) - } - - func testFromInt64() { - NBKAssertNumbers(from: Int64.min, default: T(words: Int64.min.words)) - NBKAssertNumbers(from: Int64.max, default: T(words: Int64.max.words)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x UInt - //=------------------------------------------------------------------------= - - func testToUInt() { - NBKAssertNumbers(from: T(words:[ 1, 0, 0, 0] as W), default: UInt( 1)) - NBKAssertNumbers(from: T(words:[~0, 0, 0, 0] as W), default: UInt.max) - NBKAssertNumbers(from: T(words:[ 1, 1, 1, 1] as W), exactly: nil, clamping: ~0, truncating: UInt( 1)) - NBKAssertNumbers(from: T(words:[~0, ~0, ~0, ~0] as W), exactly: nil, clamping: 0, truncating: UInt.max) - } - - func testFromUInt() { - NBKAssertNumbers(from: UInt.min, default: T(sign: .plus, magnitude: M(words: UInt.min.words))) - NBKAssertNumbers(from: UInt.max, default: T(sign: .plus, magnitude: M(words: UInt.max.words))) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x UInt32 - //=------------------------------------------------------------------------= - - func testToUInt32() { - NBKAssertNumbers(from: T(x32:[ 1, 0, 0, 0] as Y), default: UInt32( 1)) - NBKAssertNumbers(from: T(x32:[~0, 0, 0, 0] as Y), default: UInt32.max) - NBKAssertNumbers(from: T(x32:[ 1, 1, 1, 1] as Y), exactly: nil, clamping: ~0, truncating: UInt32( 1)) - NBKAssertNumbers(from: T(x32:[~0, ~0, ~0, ~0] as Y), exactly: nil, clamping: 0, truncating: UInt32.max) - } - - func testFromUInt32() { - NBKAssertNumbers(from: UInt32.min, default: T(sign: .plus, magnitude: M(words: UInt32.min.words))) - NBKAssertNumbers(from: UInt32.max, default: T(sign: .plus, magnitude: M(words: UInt32.max.words))) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x UInt64 - //=------------------------------------------------------------------------= - - func testToUInt64() { - NBKAssertNumbers(from: T(x64:[ 1, 0, 0, 0] as X), default: UInt64( 1)) - NBKAssertNumbers(from: T(x64:[~0, 0, 0, 0] as X), default: UInt64.max) - NBKAssertNumbers(from: T(x64:[ 1, 1, 1, 1] as X), exactly: nil, clamping: ~0, truncating: UInt64( 1)) - NBKAssertNumbers(from: T(x64:[~0, ~0, ~0, ~0] as X), exactly: nil, clamping: 0, truncating: UInt64.max) - } - - func testFromUInt64() { - NBKAssertNumbers(from: UInt64.min, default: T(sign: .plus, magnitude: M(words: UInt64.min.words))) - NBKAssertNumbers(from: UInt64.max, default: T(sign: .plus, magnitude: M(words: UInt64.max.words))) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Signitude - //=------------------------------------------------------------------------= - - func testToSignitude() { - NBKAssertNumbers(from: T(words:[ 1, 0, 0, 0] as W), default: S(words:[ 1, 0, 0, 0] as W)) - NBKAssertNumbers(from: T(words:[~0, 0, 0, 0] as W), default: S(words:[~0, 0, 0, 0] as W)) - NBKAssertNumbers(from: T(words:[ 1, 1, 1, 1] as W), default: S(words:[ 1, 1, 1, 1] as W)) - NBKAssertNumbers(from: T(words:[~0, ~0, ~0, ~0] as W), default: S(words:[~0, ~0, ~0, ~0] as W)) - } - - func testFromSignitude() { - NBKAssertNumbers(from: S(words:[ 1, 0, 0, 0] as W), default: T(words:[ 1, 0, 0, 0] as W)) - NBKAssertNumbers(from: S(words:[~0, 0, 0, 0] as W), default: T(words:[~0, 0, 0, 0] as W)) - NBKAssertNumbers(from: S(words:[ 1, 1, 1, 1] as W), default: T(words:[ 1, 1, 1, 1] as W)) - NBKAssertNumbers(from: S(words:[~0, ~0, ~0, ~0] as W), default: T(words:[~0, ~0, ~0, ~0] as W)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Magnitude - //=------------------------------------------------------------------------= - - func testToMagnitude() { - NBKAssertNumbers(from: T(words:[ 1, 0, 0, 0] as W), default: M(words:[ 1, 0, 0, 0] as W)) - NBKAssertNumbers(from: T(words:[~0, 0, 0, 0] as W), default: M(words:[~0, 0, 0, 0] as W)) - NBKAssertNumbers(from: T(words:[ 1, 1, 1, 1] as W), default: M(words:[ 1, 1, 1, 1] as W)) - NBKAssertNumbers(from: T(words:[~0, ~0, ~0, ~0] as W), exactly: nil, clamping: M.zero, truncating: M(UInt.max)) - } - - func testFromMagnitude() { - NBKAssertNumbers(from: M(words:[ 1, 0, 0, 0] as W), default: T(words:[ 1, 0, 0, 0, 0] as W)) - NBKAssertNumbers(from: M(words:[~0, 0, 0, 0] as W), default: T(words:[~0, 0, 0, 0, 0] as W)) - NBKAssertNumbers(from: M(words:[ 1, 1, 1, 1] as W), default: T(words:[ 1, 1, 1, 1, 0] as W)) - NBKAssertNumbers(from: M(words:[~0, ~0, ~0, ~0] as W), default: T(words:[~0, ~0, ~0, ~0, 0] as W)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Float32 - //=------------------------------------------------------------------------= - - func testToFloat32() { - XCTAssertEqual(Float32(T(-1)), Float32(-1)) - XCTAssertEqual(Float32(T( 0)), Float32( 0)) - XCTAssertEqual(Float32(T( 1)), Float32( 1)) - - XCTAssertEqual(Float32(T( Int32.min)), Float32( Int32.min)) - XCTAssertEqual(Float32(T( Int32.max)), Float32( Int32.max)) - - XCTAssertEqual(Float32(T(UInt32.min)), Float32(UInt32.min)) - XCTAssertEqual(Float32(T(UInt32.max)), Float32(UInt32.max)) - } - - func testFromFloat32() { - XCTAssertEqual(T(Float32( 22.0)), 22) - XCTAssertEqual(T(Float32( -22.0)), -22) - XCTAssertEqual(T(Float32( 22.5)), 22) - XCTAssertEqual(T(Float32( -22.5)), -22) - - XCTAssertEqual(T(exactly: 22.5), nil) - XCTAssertEqual(T(exactly: -22.5), nil) - - XCTAssertEqual(T(exactly: pow(2, Float32(64 * 0 - 1))), nil) - XCTAssertEqual(T(exactly: pow(2, Float32(64 * 0 - 0))), T(x64:[1, 0, 0, 0] as X)) - XCTAssertEqual(T(exactly: pow(2, Float32(64 * 1 - 1))), T(x64:[1 << 63, 0, 0, 0] as X)) - XCTAssertEqual(T(exactly: pow(2, Float32(64 * 2 - 1))), T(x64:[0, 1 << 63, 0, 0] as X)) - XCTAssertEqual(T(exactly: pow(2, Float32(64 * 2 - 0))), nil) - } - - func testFromFloat32ValuesThatAreSpecial() { - XCTAssertNil(T(exactly: Float32.nan)) - XCTAssertNil(T(exactly: Float32.infinity)) - XCTAssertNil(T(exactly: Float32.signalingNaN)) - XCTAssertNil(T(exactly: Float32.leastNormalMagnitude)) - XCTAssertNil(T(exactly: Float32.leastNonzeroMagnitude)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Float64 - //=------------------------------------------------------------------------= - - func testToFloat64() { - XCTAssertEqual(Float64(T(-1)), Float64(-1)) - XCTAssertEqual(Float64(T( 0)), Float64( 0)) - XCTAssertEqual(Float64(T( 1)), Float64( 1)) - - XCTAssertEqual(Float64(T( Int64.min)), Float64( Int64.min)) - XCTAssertEqual(Float64(T( Int64.max)), Float64( Int64.max)) - - XCTAssertEqual(Float64(T(UInt64.min)), Float64(UInt64.min)) - XCTAssertEqual(Float64(T(UInt64.max)), Float64(UInt64.max)) - } - - func testFromFloat64() { - XCTAssertEqual(T(Float64( 22.0)), 22) - XCTAssertEqual(T(Float64( -22.0)), -22) - XCTAssertEqual(T(Float64( 22.5)), 22) - XCTAssertEqual(T(Float64( -22.5)), -22) - - XCTAssertEqual(T(exactly: 22.5), nil) - XCTAssertEqual(T(exactly: -22.5), nil) - - XCTAssertEqual(T(exactly: pow(2, Float64(64 * 0 - 1))), nil) - XCTAssertEqual(T(exactly: pow(2, Float64(64 * 0 - 0))), T(x64:[1, 0, 0, 0] as X)) - XCTAssertEqual(T(exactly: pow(2, Float64(64 * 1 - 1))), T(x64:[1 << 63, 0, 0, 0] as X)) - XCTAssertEqual(T(exactly: pow(2, Float64(64 * 2 - 1))), T(x64:[0, 1 << 63, 0, 0] as X)) - XCTAssertEqual(T(exactly: pow(2, Float64(64 * 3 - 1))), T(x64:[0, 0, 1 << 63, 0] as X)) - XCTAssertEqual(T(exactly: pow(2, Float64(64 * 4 - 2))), T(x64:[0, 0, 0, 1 << 62] as X)) - XCTAssertEqual(T(exactly: pow(2, Float64(64 * 4 - 1))), -T(x64:[0, 0, 0, 1 << 63] as X)) - } - - func testFromFloat64ValuesThatAreSpecial() { - XCTAssertNil(T(exactly: Float64.nan)) - XCTAssertNil(T(exactly: Float64.infinity)) - XCTAssertNil(T(exactly: Float64.signalingNaN)) - XCTAssertNil(T(exactly: Float64.leastNormalMagnitude)) - XCTAssertNil(T(exactly: Float64.leastNonzeroMagnitude)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Sign & Magnitude - //=------------------------------------------------------------------------= - - func testsFromSignAndMagnitude() { - NBKAssertIdentical(T(sign: .plus, magnitude: M(1)), T(1)) - NBKAssertIdentical(T(sign: .minus, magnitude: M(1)), -T(1)) - } - - func testsFromSignAndMagnitudeAsPlusMinusZero() { - NBKAssertIdentical(T(sign: .plus, magnitude: M( )), T( )) - NBKAssertIdentical(T(sign: .minus, magnitude: M( )), -T( )) - } -} - //*============================================================================* // MARK: * NBK x Flexible Width x Numbers x UIntXL //*============================================================================* @@ -409,24 +144,6 @@ final class NBKFlexibleWidthTestsOnNumbersAsUIntXL: XCTestCase { NBKAssertNumbers(from: UInt64.max, default: T(words: UInt64.max.words)) } - //=------------------------------------------------------------------------= - // MARK: Tests x Signitude - //=------------------------------------------------------------------------= - - func testToSignitude() { - NBKAssertNumbers(from: T(words:[ 1, 0, 0, 0] as W), default: S(words:[ 1, 0, 0, 0, 0] as W)) - NBKAssertNumbers(from: T(words:[~0, 0, 0, 0] as W), default: S(words:[~0, 0, 0, 0, 0] as W)) - NBKAssertNumbers(from: T(words:[ 1, 1, 1, 1] as W), default: S(words:[ 1, 1, 1, 1, 0] as W)) - NBKAssertNumbers(from: T(words:[~0, ~0, ~0, ~0] as W), default: S(words:[~0, ~0, ~0, ~0, 0] as W)) - } - - func testFromSignitude() { - NBKAssertNumbers(from: S(words:[ 1, 0, 0, 0] as W), default: T(words:[ 1, 0, 0, 0, 0] as W)) - NBKAssertNumbers(from: S(words:[~0, 0, 0, 0] as W), default: T(words:[~0, 0, 0, 0, 0] as W)) - NBKAssertNumbers(from: S(words:[ 1, 1, 1, 1] as W), default: T(words:[ 1, 1, 1, 1, 0] as W)) - NBKAssertNumbers(from: S(words:[~0, ~0, ~0, ~0] as W), exactly: nil, clamping: T.zero, truncating: T(UInt.max)) - } - //=------------------------------------------------------------------------= // MARK: Tests x Magnitude //=------------------------------------------------------------------------= diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Shifts.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Shifts.swift index fd77a3c9..d3e05d24 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Shifts.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Shifts.swift @@ -17,124 +17,6 @@ private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] -//*============================================================================* -// MARK: * NBK x Flexible Width x Shifts x IntXL -//*============================================================================* - -final class NBKFlexibleWidthTestsOnShiftsAsIntXL: XCTestCase { - - typealias T = IntXL - - //=------------------------------------------------------------------------= - // MARK: Tests x Left - //=------------------------------------------------------------------------= - - func testBitshiftingLeftByBits() { - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 0, T(x64:[ 1, 2, 3, 4] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 1, T(x64:[ 2, 4, 6, 8] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 2, T(x64:[ 4, 8, 12, 16] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 3, T(x64:[ 8, 16, 24, 32] as X)) - } - - func testBitshiftingLeftByWords() { - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 0, T(x64:[ 1, 2, 3, 4, 0, 0, 0, 0] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 64, T(x64:[ 0, 1, 2, 3, 4, 0, 0, 0] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 128, T(x64:[ 0, 0, 1, 2, 3, 4, 0, 0] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 192, T(x64:[ 0, 0, 0, 1, 2, 3, 4, 0] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 256, T(x64:[ 0, 0, 0, 0, 1, 2, 3, 4] as X)) - } - - func testBitshiftingLeftByWordsAndBits() { - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 3, T(x64:[ 8, 16, 24, 32, 0, 0, 0, 0] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 67, T(x64:[ 0, 8, 16, 24, 32, 0, 0, 0] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 131, T(x64:[ 0, 0, 8, 16, 24, 32, 0, 0] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 195, T(x64:[ 0, 0, 0, 8, 16, 24, 32, 0] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 259, T(x64:[ 0, 0, 0, 0, 8, 16, 24, 32] as X)) - } - - func testBitshiftingLeftSuchThatWordsSplit() { - NBKAssertShiftLeft(T(x64:[~0, 0, 0, 0] as X), 1, T(x64:[~1, 1, 0, 0, 0] as X)) - NBKAssertShiftLeft(T(x64:[ 0, ~0, 0, 0] as X), 1, T(x64:[ 0, ~1, 1, 0, 0] as X)) - NBKAssertShiftLeft(T(x64:[ 0, 0, ~0, 0] as X), 1, T(x64:[ 0, 0, ~1, 1, 0] as X)) - NBKAssertShiftLeft(T(x64:[ 0, 0, 0, ~0] as X), 1, T(x64:[ 0, 0, 0, ~1, ~0] as X)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Right - //=------------------------------------------------------------------------= - - func testBitshiftingRightByBits() { - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 0, T(x64:[ 8, 16, 24, 32] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 1, T(x64:[ 4, 8, 12, 16] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 2, T(x64:[ 2, 4, 6, 8] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 3, T(x64:[ 1, 2, 3, 4] as X)) - } - - func testBitshiftingRightByWords() { - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 0, T(x64:[ 8, 16, 24, 32] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 64, T(x64:[16, 24, 32, 0] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 128, T(x64:[24, 32, 0, 0] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 192, T(x64:[32, 0, 0, 0] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 256, T(x64:[ 0, 0, 0, 0] as X)) - } - - func testBitshiftingRightByWordsAndBits() { - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 3, T(x64:[ 1, 2, 3, 4] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 67, T(x64:[ 2, 3, 4, 0] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 131, T(x64:[ 3, 4, 0, 0] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 195, T(x64:[ 4, 0, 0, 0] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 259, T(x64:[ 0, 0, 0, 0] as X)) - } - - func testBitshiftingRightSuchThatWordsSplit() { - NBKAssertShiftRight(T(x64:[0, 0, 0, 7] as X), 1, T(x64:[ 0, 0, 1 << 63, 3] as X)) - NBKAssertShiftRight(T(x64:[0, 0, 7, 0] as X), 1, T(x64:[ 0, 1 << 63, 3, 0] as X)) - NBKAssertShiftRight(T(x64:[0, 7, 0, 0] as X), 1, T(x64:[ 1 << 63, 3, 0, 0] as X)) - NBKAssertShiftRight(T(x64:[7, 0, 0, 0] as X), 1, T(x64:[ 3, 0, 0, 0] as X)) - } - - func testBitshiftingRightIsSigned() { - NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X), 0, T(x64:[ 0, 0, 0, 1 << 63] as X)) - NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X), 64, T(x64:[ 0, 0, 1 << 63, ~0] as X)) - NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X), 128, T(x64:[ 0, 1 << 63, ~0, ~0] as X)) - NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X), 192, T(x64:[ 1 << 63, ~0, ~0, ~0] as X)) - NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X), 256, T(x64:[~0, ~0, ~0, ~0] as X)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Miscellaneous - //=------------------------------------------------------------------------= - - func testBitshiftingIsSmart() { - XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) << 1, T(x64:[2, 4, 6, 8, 0] as X)) - XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) >> -1, T(x64:[2, 4, 6, 8, 0] as X)) - - XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) << 64, T(x64:[0, 1, 2, 3, 4] as X)) - XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) >> -64, T(x64:[0, 1, 2, 3, 4] as X)) - } - - func testBitshiftingRightDoesNotTrap() { - XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) >> Int.max, T.zero) - XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) << Int.min, T.zero) - } - - func testBitshiftingZeroDoesNotTrap() { - XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) << Int.min, T.zero) - XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) << Int.max, T.zero) - - XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) >> Int.min, T.zero) - XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) >> Int.max, T.zero) - } - - func testBitshiftingZeroDoesNotDoAnything() { - XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) << (UInt.bitWidth + 0), T.zero) - XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) << (UInt.bitWidth + 1), T.zero) - - XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) >> (UInt.bitWidth + 0), T.zero) - XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) >> (UInt.bitWidth + 1), T.zero) - } -} - //*============================================================================* // MARK: * NBK x Flexible Width x Shifts x UIntXL //*============================================================================* diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Subtraction.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Subtraction.swift index a3403d72..271513d6 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Subtraction.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Subtraction.swift @@ -17,101 +17,6 @@ private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] -//*============================================================================* -// MARK: * NBK x Flexible Width x Subtraction x IntXL -//*============================================================================* - -final class NBKFlexibleWidthTestsOnSubtractionAsIntXL: XCTestCase { - - typealias T = IntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testSubtracting() { - NBKAssertSubtraction(T( 1), T( 2), Int(0), T(-1)) - NBKAssertSubtraction(T( 1), T( 1), Int(0), T( 0)) - NBKAssertSubtraction(T( 1), T( 0), Int(0), T( 1)) - NBKAssertSubtraction(T( 1), T(-1), Int(0), T( 2)) - NBKAssertSubtraction(T( 1), T(-2), Int(0), T( 3)) - - NBKAssertSubtraction(T( 0), T( 2), Int(0), T(-2)) - NBKAssertSubtraction(T( 0), T( 1), Int(0), T(-1)) - NBKAssertSubtraction(T( 0), T( 0), Int(0), T( 0)) - NBKAssertSubtraction(T( 0), T(-1), Int(0), T( 1)) - NBKAssertSubtraction(T( 0), T(-2), Int(0), T( 2)) - - NBKAssertSubtraction(T(-1), T( 2), Int(0), T(-3)) - NBKAssertSubtraction(T(-1), T( 1), Int(0), T(-2)) - NBKAssertSubtraction(T(-1), T( 0), Int(0), T(-1)) - NBKAssertSubtraction(T(-1), T(-1), Int(0), T( 0)) - NBKAssertSubtraction(T(-1), T(-2), Int(0), T( 1)) - } - - func testSubtractingAtIndex() { - NBKAssertSubtraction(T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[~1, ~2, ~3, ~0] as W)) - NBKAssertSubtraction(T(words:[ 0, ~0, ~0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[~0, ~3, ~3, ~0] as W)) - NBKAssertSubtraction(T(words:[ 0, 0, ~0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[~0, ~2, ~4, ~0] as W)) - NBKAssertSubtraction(T(words:[ 0, 0, 0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[~0, ~2, ~3, ~1] as W)) - - NBKAssertSubtraction(T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[~0, ~1, ~2, ~3] as W)) - NBKAssertSubtraction(T(words:[ 0, ~0, ~0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[ 0, ~1, ~2, ~3] as W)) - NBKAssertSubtraction(T(words:[ 0, 0, ~0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[ 0, ~0, ~3, ~3] as W)) - NBKAssertSubtraction(T(words:[ 0, 0, 0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[ 0, ~0, ~2, ~4] as W)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Digit - //=------------------------------------------------------------------------= - - func testSubtractingDigit() { - NBKAssertSubtractionByDigit(T( 1), Int( 2), Int(0), T(-1)) - NBKAssertSubtractionByDigit(T( 1), Int( 1), Int(0), T( 0)) - NBKAssertSubtractionByDigit(T( 1), Int( 0), Int(0), T( 1)) - NBKAssertSubtractionByDigit(T( 1), Int(-1), Int(0), T( 2)) - NBKAssertSubtractionByDigit(T( 1), Int(-2), Int(0), T( 3)) - - NBKAssertSubtractionByDigit(T( 0), Int( 2), Int(0), T(-2)) - NBKAssertSubtractionByDigit(T( 0), Int( 1), Int(0), T(-1)) - NBKAssertSubtractionByDigit(T( 0), Int( 0), Int(0), T( 0)) - NBKAssertSubtractionByDigit(T( 0), Int(-1), Int(0), T( 1)) - NBKAssertSubtractionByDigit(T( 0), Int(-2), Int(0), T( 2)) - - NBKAssertSubtractionByDigit(T(-1), Int( 2), Int(0), T(-3)) - NBKAssertSubtractionByDigit(T(-1), Int( 1), Int(0), T(-2)) - NBKAssertSubtractionByDigit(T(-1), Int( 0), Int(0), T(-1)) - NBKAssertSubtractionByDigit(T(-1), Int(-1), Int(0), T( 0)) - NBKAssertSubtractionByDigit(T(-1), Int(-2), Int(0), T( 1)) - } - - func testSubtractingDigitAtIndex() { - NBKAssertSubtractionByDigit(T(words:[~0, ~0, ~0, ~0] as W), Int(3), Int(0), T(words:[~3, ~0, ~0, ~0] as W)) - NBKAssertSubtractionByDigit(T(words:[ 0, ~0, ~0, ~0] as W), Int(3), Int(0), T(words:[~2, ~1, ~0, ~0] as W)) - NBKAssertSubtractionByDigit(T(words:[ 0, 0, ~0, ~0] as W), Int(3), Int(0), T(words:[~2, ~0, ~1, ~0] as W)) - NBKAssertSubtractionByDigit(T(words:[ 0, 0, 0, ~0] as W), Int(3), Int(0), T(words:[~2, ~0, ~0, ~1] as W)) - - NBKAssertSubtractionByDigit(T(words:[~0, ~0, ~0, ~0] as W), Int(3), Int(1), T(words:[~0, ~3, ~0, ~0] as W)) - NBKAssertSubtractionByDigit(T(words:[ 0, ~0, ~0, ~0] as W), Int(3), Int(1), T(words:[ 0, ~3, ~0, ~0] as W)) - NBKAssertSubtractionByDigit(T(words:[ 0, 0, ~0, ~0] as W), Int(3), Int(1), T(words:[ 0, ~2, ~1, ~0] as W)) - NBKAssertSubtractionByDigit(T(words:[ 0, 0, 0, ~0] as W), Int(3), Int(1), T(words:[ 0, ~2, ~0, ~1] as W)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Miscellaneous - //=------------------------------------------------------------------------= - - func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { - func becauseThisCompilesSuccessfully(_ x: inout T) { - XCTAssertNotNil(x -= 0) - XCTAssertNotNil(x.subtract(0, at: 0)) - - XCTAssertNotNil(x - 0) - XCTAssertNotNil(x.subtracting(0, at: 0)) - } - } -} - //*============================================================================* // MARK: * NBK x Flexible Width x Subtraction x UIntXL //*============================================================================* diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Text.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Text.swift index 08bb37b1..6cdd9e9a 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Text.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Text.swift @@ -17,463 +17,6 @@ private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] -//*============================================================================* -// MARK: * NBK x Flexible Width x Text x IntXL -//*============================================================================* - -final class NBKFlexibleWidthTestsOnTextAsIntXL: XCTestCase { - - typealias T = IntXL - - //=------------------------------------------------------------------------= - // MARK: State - //=------------------------------------------------------------------------= - - let bit256 = 256 - let min256 = T.min256 - let max256 = T.max256 - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testFromDescription() { - NBKAssertFromDescription(T?( 10), "10") - NBKAssertFromDescription(T?( 10), "+10") - NBKAssertFromDescription(T?(-10), "-10") - NBKAssertFromDescription(T?(nil), " 10") - NBKAssertFromDescription(T?(nil), "0x10") - NBKAssertFromDescription(T?(nil), "+0x10") - NBKAssertFromDescription(T?(nil), "-0x10") - NBKAssertFromDescription(T?(nil), " 0x10") - } - - func testInstanceDescriptionUsesRadix10() { - XCTAssertEqual("10", T(10).description) - XCTAssertEqual("10", String(describing: T(10))) - } - - func testMetaTypeDescriptionIsSimple() { - XCTAssertEqual("IntXL", T.description) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Decode - //=------------------------------------------------------------------------= - - func testDecodingRadix02() { - NBKAssertDecodeText(min256, 02, "-1" + String(repeating: "0", count: bit256 / 1 - 1)) - NBKAssertDecodeText(max256, 02, String(repeating: "1", count: bit256 / 1 - 1)) - } - - func testDecodingRadix03() { - NBKAssertDecodeText(min256, 03, "-21221122120" + - "12222212211110210202220000022211002111211122012220" + - "12122202101121021220012201000100012101202122101020" + - "20010111121211022111102111220220201211121011101022" ) - NBKAssertDecodeText(max256, 03, "21221122120" + - "12222212211110210202220000022211002111211122012220" + - "12122202101121021220012201000100012101202122101020" + - "20010111121211022111102111220220201211121011101021" ) - } - - func testDecodingRadix04() { - NBKAssertDecodeText(min256, 04, "-2" + String(repeating: "0", count: bit256 / 2 - 1)) - NBKAssertDecodeText(max256, 04, "1" + String(repeating: "3", count: bit256 / 2 - 1)) - } - - func testDecodingRadix08() { - NBKAssertDecodeText(min256, 08, "-1" + String(repeating: "0", count: 85)) - NBKAssertDecodeText(max256, 08, String(repeating: "7", count: 85)) - } - - func testDecodingRadix10() { - NBKAssertDecodeText(min256, 10, "-57896044618658097711785492504343953926634992332820282019728792003956564819968") - NBKAssertDecodeText(max256, 10, "57896044618658097711785492504343953926634992332820282019728792003956564819967") - } - - func testDecodingRadix16() { - NBKAssertDecodeText(min256, 16, "-8" + String(repeating: "0", count: bit256 / 4 - 1)) - NBKAssertDecodeText(max256, 16, "7" + String(repeating: "f", count: bit256 / 4 - 1)) - } - - func testDecodingRadix32() { - NBKAssertDecodeText(min256, 32, "-1" + String(repeating: "0", count: 51)) - NBKAssertDecodeText(max256, 32, String(repeating: "v", count: 51)) - } - - func testDecodingRadix36() { - NBKAssertDecodeText(min256, 36, "-36ukv65j19b11mbvjyfui963v4my01krth19g3r3bk1ojlrwu8") - NBKAssertDecodeText(max256, 36, "36ukv65j19b11mbvjyfui963v4my01krth19g3r3bk1ojlrwu7") - } - - func testDecodingRadixLiteralAsNumber() { - NBKAssertDecodeText(T( 33), 36, "0x") - NBKAssertDecodeText(T( 24), 36, "0o") - NBKAssertDecodeText(T( 11), 36, "0b") - - NBKAssertDecodeText(T( 33), 36, "+0x") - NBKAssertDecodeText(T( 24), 36, "+0o") - NBKAssertDecodeText(T( 11), 36, "+0b") - - NBKAssertDecodeText(T(-33), 36, "-0x") - NBKAssertDecodeText(T(-24), 36, "-0o") - NBKAssertDecodeText(T(-11), 36, "-0b") - } - - func testDecodingRadixLiteralAsRadixReturnsNil() { - NBKAssertDecodeText(T?.none, 10, "0x10") - NBKAssertDecodeText(T?.none, 10, "0o10") - NBKAssertDecodeText(T?.none, 10, "0b10") - - NBKAssertDecodeText(T?.none, 10, "+0x10") - NBKAssertDecodeText(T?.none, 10, "+0o10") - NBKAssertDecodeText(T?.none, 10, "+0b10") - - NBKAssertDecodeText(T?.none, 10, "-0x10") - NBKAssertDecodeText(T?.none, 10, "-0o10") - NBKAssertDecodeText(T?.none, 10, "-0b10") - } - - func testDecodingStringsWithAndWithoutSign() { - NBKAssertDecodeText(T( 1234567890), 10, "1234567890") - NBKAssertDecodeText(T( 1234567890), 10, "+1234567890") - NBKAssertDecodeText(T(-1234567890), 10, "-1234567890") - } - - func testDecodingStrategyIsCaseInsensitive() { - NBKAssertDecodeText(T(0xabcdef), 16, "abcdef") - NBKAssertDecodeText(T(0xABCDEF), 16, "ABCDEF") - NBKAssertDecodeText(T(0xaBcDeF), 16, "aBcDeF") - NBKAssertDecodeText(T(0xAbCdEf), 16, "AbCdEf") - } - - func testDecodingUnalignedStringsIsOK() { - NBKAssertDecodeText(T(1), 10, "1") - NBKAssertDecodeText(T(1), 16, "1") - } - - func testDecodingPrefixingZerosHasNoEffect() { - let zero = String(repeating: "0", count: bit256) + "0" - let one = String(repeating: "0", count: bit256) + "1" - - for radix in 02 ... 36 { - NBKAssertDecodeText(T(0), radix, zero) - NBKAssertDecodeText(T(1), radix, one ) - } - } - - func testDecodingInvalidCharactersReturnsNil() { - NBKAssertDecodeText(T?.none, 16, "/") - NBKAssertDecodeText(T?.none, 16, "G") - - NBKAssertDecodeText(T?.none, 10, "/") - NBKAssertDecodeText(T?.none, 10, ":") - - NBKAssertDecodeText(T?.none, 10, String(repeating: "1", count: 19) + "/") - NBKAssertDecodeText(T?.none, 10, String(repeating: "1", count: 19) + ":") - } - - func testDecodingStringsWithoutDigitsReturnsNil() { - NBKAssertDecodeText(T?.none, 10, "") - NBKAssertDecodeText(T?.none, 10, "+") - NBKAssertDecodeText(T?.none, 10, "-") - NBKAssertDecodeText(T?.none, 10, "~") - - NBKAssertDecodeText(T?.none, 16, "") - NBKAssertDecodeText(T?.none, 16, "+") - NBKAssertDecodeText(T?.none, 16, "-") - NBKAssertDecodeText(T?.none, 16, "~") - } - - func testDecodingValuesOutsideOfRepresentableRangeReturnsNil() { - let positive = "+" + String(repeating: "1", count: bit256) - let negative = "-" + String(repeating: "1", count: bit256) - - for radix in 02 ... 36 { - XCTAssertNotNil(T(positive, radix: radix)) - XCTAssertNotNil(T(negative, radix: radix)) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Encode - //=------------------------------------------------------------------------= - - func testEncodingRadix02() { - NBKAssertEncodeText(min256, 02, false, "-1" + String(repeating: "0", count: bit256 / 1 - 1)) - NBKAssertEncodeText(max256, 02, false, String(repeating: "1", count: bit256 / 1 - 1)) - } - - func testEncodingRadix03() { - NBKAssertEncodeText(min256, 03, false,"-21221122120" + - "12222212211110210202220000022211002111211122012220" + - "12122202101121021220012201000100012101202122101020" + - "20010111121211022111102111220220201211121011101022" ) - NBKAssertEncodeText(max256, 03, false, "21221122120" + - "12222212211110210202220000022211002111211122012220" + - "12122202101121021220012201000100012101202122101020" + - "20010111121211022111102111220220201211121011101021" ) - } - - func testEncodingRadix04() { - NBKAssertEncodeText(min256, 04, false, "-2" + String(repeating: "0", count: bit256 / 2 - 1)) - NBKAssertEncodeText(max256, 04, false, "1" + String(repeating: "3", count: bit256 / 2 - 1)) - } - - func testEncodingRadix08() { - NBKAssertEncodeText(min256, 08, false, "-1" + String(repeating: "0", count: 85)) - NBKAssertEncodeText(max256, 08, false, String(repeating: "7", count: 85)) - } - - func testEncodingRadix10() { - NBKAssertEncodeText(min256, 10, false, "-57896044618658097711785492504343953926634992332820282019728792003956564819968") - NBKAssertEncodeText(max256, 10, false, "57896044618658097711785492504343953926634992332820282019728792003956564819967") - } - - func testEncodingRadix16() { - NBKAssertEncodeText(min256, 16, false, "-8" + String(repeating: "0", count: bit256 / 4 - 1)) - NBKAssertEncodeText(min256, 16, true , "-8" + String(repeating: "0", count: bit256 / 4 - 1)) - NBKAssertEncodeText(max256, 16, false, "7" + String(repeating: "f", count: bit256 / 4 - 1)) - NBKAssertEncodeText(max256, 16, true , "7" + String(repeating: "F", count: bit256 / 4 - 1)) - } - - func testEncodingRadix32() { - NBKAssertEncodeText(min256, 32, false, "-1" + String(repeating: "0", count: 51)) - NBKAssertEncodeText(min256, 32, true , "-1" + String(repeating: "0", count: 51)) - NBKAssertEncodeText(max256, 32, false, String(repeating: "v", count: 51)) - NBKAssertEncodeText(max256, 32, true , String(repeating: "V", count: 51)) - } - - func testEncodingRadix36() { - NBKAssertEncodeText(min256, 36, false, "-36ukv65j19b11mbvjyfui963v4my01krth19g3r3bk1ojlrwu8") - NBKAssertEncodeText(min256, 36, true , "-36UKV65J19B11MBVJYFUI963V4MY01KRTH19G3R3BK1OJLRWU8") - NBKAssertEncodeText(max256, 36, false, "36ukv65j19b11mbvjyfui963v4my01krth19g3r3bk1ojlrwu7") - NBKAssertEncodeText(max256, 36, true , "36UKV65J19B11MBVJYFUI963V4MY01KRTH19G3R3BK1OJLRWU7") - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Text x UIntXL -//*============================================================================* - -final class NBKFlexibleWidthTestsOnTextAsUIntXL: XCTestCase { - - typealias T = UIntXL - - //=------------------------------------------------------------------------= - // MARK: State - //=------------------------------------------------------------------------= - - let bit256 = 256 - let min256 = T.min256 - let max256 = T.max256 - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testFromDescription() { - NBKAssertFromDescription(T?( 10), "10") - NBKAssertFromDescription(T?( 10), "+10") - NBKAssertFromDescription(T?(nil), "-10") - NBKAssertFromDescription(T?(nil), " 10") - NBKAssertFromDescription(T?(nil), "0x10") - NBKAssertFromDescription(T?(nil), "+0x10") - NBKAssertFromDescription(T?(nil), "-0x10") - NBKAssertFromDescription(T?(nil), " 0x10") - } - - func testInstanceDescriptionUsesRadix10() { - XCTAssertEqual("10", T(10).description) - XCTAssertEqual("10", String(describing: T(10))) - } - - func testMetaTypeDescriptionIsSimple() { - XCTAssertEqual("UIntXL", T.description) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Decode - //=------------------------------------------------------------------------= - - func testDecodingRadix02() { - NBKAssertDecodeText(min256, 02, "0") - NBKAssertDecodeText(max256, 02, String(repeating: "1", count: bit256 / 1)) - } - - func testDecodingRadix03() { - NBKAssertDecodeText(min256, 03, "0" ) - NBKAssertDecodeText(max256, 03, "120220022011" + - "02222202122221121112210000122122012000200021102211" + - "02022111210012120210102102000200101210112021202111" + - "10021000020122121222212000211211110200012022202120" ) - } - - func testDecodingRadix04() { - NBKAssertDecodeText(min256, 04, "0") - NBKAssertDecodeText(max256, 04, String(repeating: "3", count: bit256 / 2)) - } - - func testDecodingRadix08() { - NBKAssertDecodeText(min256, 08, "0") - NBKAssertDecodeText(max256, 08, "1" + String(repeating: "7", count: 85)) - } - - func testDecodingRadix10() { - NBKAssertDecodeText(min256, 10, "0") - NBKAssertDecodeText(max256, 10, "115792089237316195423570985008687907853269984665640564039457584007913129639935") - } - - func testDecodingRadix16() { - NBKAssertDecodeText(min256, 16, "0") - NBKAssertDecodeText(max256, 16, String(repeating: "f", count: bit256 / 4)) - } - - func testDecodingRadix32() { - NBKAssertDecodeText(min256, 32, "0") - NBKAssertDecodeText(max256, 32, "1" + String(repeating: "v", count: 51)) - } - - func testDecodingRadix36() { - NBKAssertDecodeText(min256, 36, "0") - NBKAssertDecodeText(max256, 36, "6dp5qcb22im238nr3wvp0ic7q99w035jmy2iw7i6n43d37jtof") - } - - func testDecodingRadixLiteralAsNumber() { - NBKAssertDecodeText(T(33), 36, "0x") - NBKAssertDecodeText(T(24), 36, "0o") - NBKAssertDecodeText(T(11), 36, "0b") - - NBKAssertDecodeText(T(33), 36, "+0x") - NBKAssertDecodeText(T(24), 36, "+0o") - NBKAssertDecodeText(T(11), 36, "+0b") - } - - func testDecodingRadixLiteralAsRadixReturnsNil() { - NBKAssertDecodeText(T?.none, 10, "0x10") - NBKAssertDecodeText(T?.none, 10, "0o10") - NBKAssertDecodeText(T?.none, 10, "0b10") - - NBKAssertDecodeText(T?.none, 10, "+0x10") - NBKAssertDecodeText(T?.none, 10, "+0o10") - NBKAssertDecodeText(T?.none, 10, "+0b10") - } - - func testDecodingStringsWithAndWithoutSign() { - NBKAssertDecodeText(T(1234567890), 10, "1234567890") - NBKAssertDecodeText(T(1234567890), 10, "+1234567890") - } - - func testDecodingStrategyIsCaseInsensitive() { - NBKAssertDecodeText(T(0xabcdef), 16, "abcdef") - NBKAssertDecodeText(T(0xABCDEF), 16, "ABCDEF") - NBKAssertDecodeText(T(0xaBcDeF), 16, "aBcDeF") - NBKAssertDecodeText(T(0xAbCdEf), 16, "AbCdEf") - } - - func testDecodingUnalignedStringsIsOK() { - NBKAssertDecodeText(T(1), 10, "1") - NBKAssertDecodeText(T(1), 16, "1") - } - - func testDecodingPrefixingZerosHasNoEffect() { - let zero = String(repeating: "0", count: bit256) + "0" - let one = String(repeating: "0", count: bit256) + "1" - - for radix in 02 ... 36 { - NBKAssertDecodeText(T(0), radix, zero) - NBKAssertDecodeText(T(1), radix, one ) - } - } - - func testDecodingInvalidCharactersReturnsNil() { - NBKAssertDecodeText(T?.none, 16, "/") - NBKAssertDecodeText(T?.none, 16, "G") - - NBKAssertDecodeText(T?.none, 10, "/") - NBKAssertDecodeText(T?.none, 10, ":") - - NBKAssertDecodeText(T?.none, 10, String(repeating: "1", count: 19) + "/") - NBKAssertDecodeText(T?.none, 10, String(repeating: "1", count: 19) + ":") - } - - func testDecodingStringsWithoutDigitsReturnsNil() { - NBKAssertDecodeText(T?.none, 10, "") - NBKAssertDecodeText(T?.none, 10, "+") - NBKAssertDecodeText(T?.none, 10, "-") - NBKAssertDecodeText(T?.none, 10, "~") - - NBKAssertDecodeText(T?.none, 16, "") - NBKAssertDecodeText(T?.none, 16, "+") - NBKAssertDecodeText(T?.none, 16, "-") - NBKAssertDecodeText(T?.none, 16, "~") - } - - func testDecodingValuesOutsideOfRepresentableRangeReturnsNil() { - let positive = "+" + String(repeating: "1", count: bit256 + 1) - let negative = "-" + String(repeating: "1", count: 1) - - for radix in 02 ... 36 { - XCTAssertNotNil(T(positive, radix: radix)) - NBKAssertDecodeText(T?.none, radix, negative) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Encode - //=------------------------------------------------------------------------= - - func testEncodingRadix02() { - NBKAssertEncodeText(min256, 02, false, "0") - NBKAssertEncodeText(max256, 02, false, String(repeating: "1", count: bit256 / 1)) - } - - func testEncodingRadix03() { - NBKAssertEncodeText(min256, 03, false, "0" ) - NBKAssertEncodeText(max256, 03, false,"120220022011" + - "02222202122221121112210000122122012000200021102211" + - "02022111210012120210102102000200101210112021202111" + - "10021000020122121222212000211211110200012022202120" ) - } - - func testEncodingRadix04() { - NBKAssertEncodeText(min256, 04, false, "0") - NBKAssertEncodeText(max256, 04, false, String(repeating: "3", count: bit256 / 2)) - } - - func testEncodingRadix08() { - NBKAssertEncodeText(min256, 08, false, "0") - NBKAssertEncodeText(max256, 08, false, "1" + String(repeating: "7", count: 85)) - } - - func testEncodingRadix10() { - NBKAssertEncodeText(min256, 10, false, "0") - NBKAssertEncodeText(max256, 10, false, "115792089237316195423570985008687907853269984665640564039457584007913129639935") - } - - func testEncodingRadix16() { - NBKAssertEncodeText(min256, 16, false, "0") - NBKAssertEncodeText(min256, 16, true , "0") - NBKAssertEncodeText(max256, 16, false, String(repeating: "f", count: bit256 / 4)) - NBKAssertEncodeText(max256, 16, true , String(repeating: "F", count: bit256 / 4)) - } - - func testEncodingRadix32() { - NBKAssertEncodeText(min256, 32, false, "0") - NBKAssertEncodeText(min256, 32, true , "0") - NBKAssertEncodeText(max256, 32, false, "1" + String(repeating: "v", count: 51)) - NBKAssertEncodeText(max256, 32, true , "1" + String(repeating: "V", count: 51)) - } - - func testEncodingRadix36() { - NBKAssertEncodeText(min256, 36, false, "0") - NBKAssertEncodeText(min256, 36, true , "0") - NBKAssertEncodeText(max256, 36, false, "6dp5qcb22im238nr3wvp0ic7q99w035jmy2iw7i6n43d37jtof") - NBKAssertEncodeText(max256, 36, true , "6DP5QCB22IM238NR3WVP0IC7Q99W035JMY2IW7I6N43D37JTOF") - } -} - //*============================================================================* // MARK: * NBK x Flexible Width x Text x For Each Radix x UIntXL //*============================================================================* diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Words.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Words.swift index c633268d..08413905 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Words.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Words.swift @@ -17,82 +17,6 @@ private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] -//*============================================================================* -// MARK: * NBK x Flexible Width x Words x IntXL -//*============================================================================* - -final class NBKFlexibleWidthTestsOnWordsAsIntXL: XCTestCase { - - typealias T = IntXL - typealias M = UIntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testWords() { - NBKAssertWords(T(words:[0 ]), [0 ]) - NBKAssertWords(T(words:[1 ]), [1 ]) - NBKAssertWords(T(words:[1, 2 ]), [1, 2 ]) - NBKAssertWords(T(words:[1, 2, 3 ]), [1, 2, 3 ]) - NBKAssertWords(T(words:[1, 2, 3, 4]), [1, 2, 3, 4]) - - NBKAssertWords(T(words:[0, 0, 0, 0]), [0 ]) - NBKAssertWords(T(words:[1, 0, 0, 0]), [1 ]) - NBKAssertWords(T(words:[1, 2, 0, 0]), [1, 2 ]) - NBKAssertWords(T(words:[1, 2, 3, 0]), [1, 2, 3 ]) - NBKAssertWords(T(words:[1, 2, 3, 4]), [1, 2, 3, 4]) - - NBKAssertWords(T(sign: .plus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as W)), [~0, ~0, ~0, ~0/2 + 0 ] as W) // 4 - NBKAssertWords(T(sign: .plus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as W)), [ 0, 0, 0, ~0/2 + 1, 0] as W) // 5 - NBKAssertWords(T(sign: .plus, magnitude: M(words:[ 1, 0, 0, ~0/2 + 1] as W)), [ 1, 0, 0, ~0/2 + 1, 0] as W) // 5 - - NBKAssertWords(T(sign: .minus, magnitude: M(words:[~0, ~0, ~0, ~0/2 + 0] as W)), [ 1, 0, 0, ~0/2 + 1 ] as W) // 4 - NBKAssertWords(T(sign: .minus, magnitude: M(words:[ 0, 0, 0, ~0/2 + 1] as W)), [ 0, 0, 0, ~0/2 + 1 ] as W) // 4 - NBKAssertWords(T(sign: .minus, magnitude: M(words:[ 1, 0, 0, ~0/2 + 1] as W)), [~0, ~0, ~0, ~0/2 + 0, ~0] as W) // 5 - } - - func testWordsX64() throws { - guard MemoryLayout.size == MemoryLayout.size else { throw XCTSkip() } - - NBKAssertWords(T(x64:[0 ] as X), [0 ]) - NBKAssertWords(T(x64:[1 ] as X), [1 ]) - NBKAssertWords(T(x64:[1, 2 ] as X), [1, 2 ]) - NBKAssertWords(T(x64:[1, 2, 3 ] as X), [1, 2, 3 ]) - NBKAssertWords(T(x64:[1, 2, 3, 4] as X), [1, 2, 3, 4]) - - NBKAssertWords(T(x64:[0, 0, 0, 0] as X), [0 ]) - NBKAssertWords(T(x64:[1, 0, 0, 0] as X), [1 ]) - NBKAssertWords(T(x64:[1, 2, 0, 0] as X), [1, 2 ]) - NBKAssertWords(T(x64:[1, 2, 3, 0] as X), [1, 2, 3 ]) - NBKAssertWords(T(x64:[1, 2, 3, 4] as X), [1, 2, 3, 4]) - } - - func testWordsX32() throws { - guard MemoryLayout.size == MemoryLayout.size else { throw XCTSkip() } - - NBKAssertWords(T(x32:[0 ] as Y), [0 ]) - NBKAssertWords(T(x32:[1 ] as Y), [1 ]) - NBKAssertWords(T(x32:[1, 2 ] as Y), [1, 2 ]) - NBKAssertWords(T(x32:[1, 2, 3 ] as Y), [1, 2, 3 ]) - NBKAssertWords(T(x32:[1, 2, 3, 4 ] as Y), [1, 2, 3, 4 ]) - NBKAssertWords(T(x32:[1, 2, 3, 4, 5 ] as Y), [1, 2, 3, 4, 5 ]) - NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6 ] as Y), [1, 2, 3, 4, 5, 6 ]) - NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6, 7 ] as Y), [1, 2, 3, 4, 5, 6, 7 ]) - NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6, 7, 8] as Y), [1, 2, 3, 4, 5, 6, 7, 8]) - - NBKAssertWords(T(x32:[0, 0, 0, 0, 0, 0, 0, 0] as Y), [0 ]) - NBKAssertWords(T(x32:[1, 0, 0, 0, 0, 0, 0, 0] as Y), [1 ]) - NBKAssertWords(T(x32:[1, 2, 0, 0, 0, 0, 0, 0] as Y), [1, 2 ]) - NBKAssertWords(T(x32:[1, 2, 3, 0, 0, 0, 0, 0] as Y), [1, 2, 3 ]) - NBKAssertWords(T(x32:[1, 2, 3, 4, 0, 0, 0, 0] as Y), [1, 2, 3, 4 ]) - NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 0, 0, 0] as Y), [1, 2, 3, 4, 5 ]) - NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6, 0, 0] as Y), [1, 2, 3, 4, 5, 6 ]) - NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6, 7, 0] as Y), [1, 2, 3, 4, 5, 6, 7 ]) - NBKAssertWords(T(x32:[1, 2, 3, 4, 5, 6, 7, 8] as Y), [1, 2, 3, 4, 5, 6, 7, 8]) - } -} - //*============================================================================* // MARK: * NBK x Flexible Width x Words x UIntXL //*============================================================================* diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth.swift index 40448815..bcb1c5a3 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth.swift @@ -16,85 +16,20 @@ private typealias X = [UInt64] private typealias Y = [UInt32] //*============================================================================* -// MARK: * NBK x Flexible Width x IntXL -//*============================================================================* - -final class NBKFlexibleWidthTestsAsIntXL: XCTestCase { - - typealias T = IntXL - typealias M = UIntXL - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testSign() { - XCTAssertEqual(T(sign: .plus, magnitude: 0).sign, .plus ) - XCTAssertEqual(T(sign: .minus, magnitude: 0).sign, .minus) - XCTAssertEqual(T(sign: .plus, magnitude: 1).sign, .plus ) - XCTAssertEqual(T(sign: .minus, magnitude: 1).sign, .minus) - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Assertions -//*============================================================================* - -func NBKAssertIdentical(_ lhs: IntXL?, _ rhs: IntXL?, file: StaticString = #file, line: UInt = #line) { - func description(of value: IntXL?) -> String { - value.map({ "\(UnicodeScalar($0.sign.ascii))\($0.magnitude)" }) ?? "nil" - } - //=--------------------------------------= - let success: Bool = lhs?.sign == rhs?.sign && lhs?.magnitude == rhs?.magnitude - //=--------------------------------------= - if success { - XCTAssertEqual(lhs, rhs, file: file, line: line) - } - //=--------------------------------------= - XCTAssert(success, "\(description(of: lhs)) is not identical to \(description(of: rhs))", file: file, line: line) -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Initializers x IntXL -//*============================================================================* - -extension NBKFlexibleWidth { - - //=------------------------------------------------------------------------= - // MARK: Details x Numbers - //=------------------------------------------------------------------------= - - static let min256 = Self(x64:[ 0, 0, 0, ~0/2 + 1] as X) - static let max256 = Self(x64:[~0, ~0, ~0, ~0/2 + 0] as X) - - //=------------------------------------------------------------------------= - // MARK: Details x Limbs - //=------------------------------------------------------------------------= - - init(x32: [UInt32]) { - self.init(words: NBKChunkedInt(x32)) - } - - init(x64: [UInt64]) { - self.init(words: NBKChunkedInt(x64)) - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Initializers x UIntXL +// MARK: * NBK x Flexible Width x UIntXL //*============================================================================* extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= - // MARK: Details x Numbers + // MARK: Initializers //=------------------------------------------------------------------------= static let min256 = Self(x64:[ 0, 0, 0, 0] as X) static let max256 = Self(x64:[~0, ~0, ~0, ~0] as X) //=------------------------------------------------------------------------= - // MARK: Details x Limbs + // MARK: Initializers //=------------------------------------------------------------------------= init(x32: [UInt32]) { From a79b3f2cfc84ab901fb28bf4cebd45640003e79d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sat, 16 Sep 2023 09:02:24 +0200 Subject: [PATCH 075/133] Miscellaneous. --- Package.swift | 2 +- README.md | 8 ++++ .../NBKFlexibleWidth+Literals.swift | 4 +- .../NBKSigned+Addition+Digit.swift | 2 +- Sources/NBKSignedKit/NBKSigned+Addition.swift | 2 +- Sources/NBKSignedKit/NBKSigned.swift | 44 +++++++++++++++++++ .../Documentation.docc/Documentation.md | 12 ++++- Sources/Numberick/Exports.swift | 1 + .../NBKFlexibleWidth.swift | 10 +---- .../NBKSignedKitTests/NBKFlexibleWidth.swift | 10 +---- 10 files changed, 71 insertions(+), 24 deletions(-) diff --git a/Package.swift b/Package.swift index e1512b68..989617f4 100644 --- a/Package.swift +++ b/Package.swift @@ -67,7 +67,7 @@ var package = Package( //=--------------------------------------= .target( name: "Numberick", - dependencies: ["NBKCoreKit", "NBKDoubleWidthKit", "NBKFlexibleWidthKit"]), + dependencies: ["NBKCoreKit", "NBKDoubleWidthKit", "NBKFlexibleWidthKit", "NBKSignedKit"]), //=--------------------------------------= // NBK x Core Kit //=--------------------------------------= diff --git a/README.md b/README.md index 859af472..70890aa7 100644 --- a/README.md +++ b/README.md @@ -105,6 +105,10 @@ Int256(5) % Int(5), UInt256(5) % UInt(5) 👨‍💻🛠️🚧🧱🧱🏗️🧱🧱🚧⏳ +## [NBKSignedKit][FLX/D] ([Sources][SIG/S], [Tests][SIG/T], [Benchmarks][SIG/B]) + +👨‍💻🛠️🚧🧱🧱🏗️🧱🧱🚧⏳ + ## Acknowledgements This project is inspired by [**Int128**][Apple/Int128] and [**DoubleWidth**][Apple/DoubleWidth] by Apple. @@ -114,18 +118,22 @@ This project is inspired by [**Int128**][Apple/Int128] and [**DoubleWidth**][App [NBK/D]: https://oscbyspro.github.io/Numberick/documentation/numberick [DBL/D]: https://oscbyspro.github.io/Numberick/documentation/numberick/nbkdoublewidth [FLX/D]: https://oscbyspro.github.io/Numberick/documentation/numberick/nbkflexiblewidth +[SIG/D]: https://oscbyspro.github.io/Numberick/documentation/numberick/nbksigned [COR/S]: Sources/NBKCoreKit [DBL/S]: Sources/NBKDoubleWidthKit [FLX/S]: Sources/NBKFlexibleWidthKit +[SIG/S]: Sources/NBKSignedKit [COR/T]: Tests/NBKCoreKitTests [DBL/T]: Tests/NBKDoubleWidthKitTests [FLX/T]: Tests/NBKFlexibleWidthKitTests +[SIG/T]: Tests/NBKSignedKitTests [COR/B]: Tests/NBKCoreKitBenchmarks [DBL/B]: Tests/NBKDoubleWidthKitBenchmarks [FLX/B]: Tests/NBKFlexibleWidthKitBenchmarks +[SIG/B]: Tests/NBKSignedKitBenchmarks diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Literals.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Literals.swift index a1e07fb6..c94f0486 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Literals.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Literals.swift @@ -27,9 +27,7 @@ extension NBKFlexibleWidth.Magnitude { } @inlinable init?(exactlyIntegerLiteral source: StaticBigInt) { - //=--------------------------------------= - if source.signum() == -1 { return nil } - //=--------------------------------------= + if source.signum() == -1 { return nil } self.init(truncatingIntegerLiteral: source) } diff --git a/Sources/NBKSignedKit/NBKSigned+Addition+Digit.swift b/Sources/NBKSignedKit/NBKSigned+Addition+Digit.swift index 3fe5f5a2..63e80b67 100644 --- a/Sources/NBKSignedKit/NBKSigned+Addition+Digit.swift +++ b/Sources/NBKSignedKit/NBKSigned+Addition+Digit.swift @@ -23,7 +23,7 @@ extension NBKSigned { if lhs.sign == rhs.sign { lhs.magnitude += rhs.magnitude } else if lhs.magnitude.subtractReportingOverflow(rhs.magnitude) { - lhs.sign = rhs.sign + lhs.sign.toggle() lhs.magnitude.formTwosComplement() } } diff --git a/Sources/NBKSignedKit/NBKSigned+Addition.swift b/Sources/NBKSignedKit/NBKSigned+Addition.swift index 3a07a3cf..9b653ecf 100644 --- a/Sources/NBKSignedKit/NBKSigned+Addition.swift +++ b/Sources/NBKSignedKit/NBKSigned+Addition.swift @@ -23,7 +23,7 @@ extension NBKSigned { if lhs.sign == rhs.sign { lhs.magnitude += rhs.magnitude } else if lhs.magnitude.subtractReportingOverflow(rhs.magnitude) { - lhs.sign = rhs.sign + lhs.sign.toggle() lhs.magnitude.formTwosComplement() } } diff --git a/Sources/NBKSignedKit/NBKSigned.swift b/Sources/NBKSignedKit/NBKSigned.swift index 86ebf24f..0e469934 100644 --- a/Sources/NBKSignedKit/NBKSigned.swift +++ b/Sources/NBKSignedKit/NBKSigned.swift @@ -13,6 +13,38 @@ import NBKCoreKit // MARK: * NBK x Signed //*============================================================================* +/// A decorative, width agnostic, sign-and-magnitude integer. +/// +/// ```swift +/// typealias SInt = NBKSigned +/// let max = SInt(sign: .plus, magnitude: .max) +/// let min = SInt(sign: .minus, magnitude: .max) +/// ``` +/// +/// ### 🧭 Plus Zero & Minus Zero +/// +/// Zero is signed, meaning that it can be either positive or negative. These values +/// are comparatively equal and have the same hash value. +/// +/// - use `isLessThanZero` to check if a value is `negative` and non-zero +/// - use `isMoreThanZero` to check if a value is `positive` and non-zero +/// +/// ### 🚀 Single Digit Arithmagick +/// +/// Alongside its ordinary arithmagick operations, ``NBKSigned`` provides +/// single-digit operations, where a digit is a sign and an unsigned machine word. +/// These operations are more efficient for small calculations. Here are some examples: +/// +/// ```swift +/// SIntXL(1) + SInt(1) +/// SIntXL(2) - SInt(2) +/// SIntXL(3) * SInt(3) +/// SIntXL(4) / SInt(4) +/// SIntXL(5) % SInt(5) +/// ``` +/// +/// - Note: The `Digit` type is `NBKSigned`. +/// @frozen public struct NBKSigned: Comparable, CustomStringConvertible, ExpressibleByIntegerLiteral, Hashable, Sendable, SignedNumeric { @@ -77,3 +109,15 @@ public typealias SInt32 = NBKSigned /// A signed integer with a 64-bit magnitude. public typealias SInt64 = NBKSigned + +//=----------------------------------------------------------------------------= +// MARK: + Flexible Width +//=----------------------------------------------------------------------------= +#if canImport(NBKFlexibleWidthKit) + +import NBKFlexibleWidthKit + +/// A signed integer with a flexible-width magnitude. +public typealias SIntXL = NBKSigned + +#endif diff --git a/Sources/Numberick/Documentation.docc/Documentation.md b/Sources/Numberick/Documentation.docc/Documentation.md index 7bded1fe..90c68dd5 100644 --- a/Sources/Numberick/Documentation.docc/Documentation.md +++ b/Sources/Numberick/Documentation.docc/Documentation.md @@ -114,25 +114,33 @@ Int256(5) % Int(5), UInt256(5) % UInt(5) - ``NBKDoubleWidth`` - ``NBKEndianness`` - ``NBKFlexibleWidth`` +- ``NBKSigned`` - ``NBKTwinHeaded`` ### Integers -- ``IntXL`` - ``Int128`` - ``Int256`` - ``Int512`` - ``Int1024`` - ``Int2048`` - ``Int4096`` +- ``IntXL`` -- ``UIntXL`` - ``UInt128`` - ``UInt256`` - ``UInt512`` - ``UInt1024`` - ``UInt2048`` - ``UInt4096`` +- ``UIntXL`` + +- ``SInt`` +- ``SInt8`` +- ``SInt16`` +- ``SInt32`` +- ``SInt64`` +- ``SIntXL`` ### Abbreviations diff --git a/Sources/Numberick/Exports.swift b/Sources/Numberick/Exports.swift index 73e171b2..adbbc52d 100644 --- a/Sources/Numberick/Exports.swift +++ b/Sources/Numberick/Exports.swift @@ -14,3 +14,4 @@ @_exported import NBKCoreKit @_exported import NBKDoubleWidthKit @_exported import NBKFlexibleWidthKit +@_exported import NBKSignedKit diff --git a/Tests/NBKSignedKitBenchmarks/NBKFlexibleWidth.swift b/Tests/NBKSignedKitBenchmarks/NBKFlexibleWidth.swift index 1d90cdf2..05a11117 100644 --- a/Tests/NBKSignedKitBenchmarks/NBKFlexibleWidth.swift +++ b/Tests/NBKSignedKitBenchmarks/NBKFlexibleWidth.swift @@ -16,12 +16,6 @@ private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] -//*============================================================================* -// MARK: * NBK x Flexible Width x Signed -//*============================================================================* - -public typealias SIntXL = NBKSigned - //*============================================================================* // MARK: * NBK x Flexible Width x UIntXL //*============================================================================* @@ -29,14 +23,14 @@ public typealias SIntXL = NBKSigned extension UIntXL { //=------------------------------------------------------------------------= - // MARK: Details x Numbers + // MARK: Initializers //=------------------------------------------------------------------------= static let min256 = Self(x64:[ 0, 0, 0, 0] as X) static let max256 = Self(x64:[~0, ~0, ~0, ~0] as X) //=------------------------------------------------------------------------= - // MARK: Details x Limbs + // MARK: Initializers //=------------------------------------------------------------------------= init(x32: [UInt32]) { diff --git a/Tests/NBKSignedKitTests/NBKFlexibleWidth.swift b/Tests/NBKSignedKitTests/NBKFlexibleWidth.swift index 1d90cdf2..05a11117 100644 --- a/Tests/NBKSignedKitTests/NBKFlexibleWidth.swift +++ b/Tests/NBKSignedKitTests/NBKFlexibleWidth.swift @@ -16,12 +16,6 @@ private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] -//*============================================================================* -// MARK: * NBK x Flexible Width x Signed -//*============================================================================* - -public typealias SIntXL = NBKSigned - //*============================================================================* // MARK: * NBK x Flexible Width x UIntXL //*============================================================================* @@ -29,14 +23,14 @@ public typealias SIntXL = NBKSigned extension UIntXL { //=------------------------------------------------------------------------= - // MARK: Details x Numbers + // MARK: Initializers //=------------------------------------------------------------------------= static let min256 = Self(x64:[ 0, 0, 0, 0] as X) static let max256 = Self(x64:[~0, ~0, ~0, ~0] as X) //=------------------------------------------------------------------------= - // MARK: Details x Limbs + // MARK: Initializers //=------------------------------------------------------------------------= init(x32: [UInt32]) { From eb484363bb8ebc24a4feec3798a920e3fa126ea2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sat, 16 Sep 2023 10:42:33 +0200 Subject: [PATCH 076/133] [NBKFlexibleWidthKit] Cleanup. --- .../NBKFlexibleWidthKit/IntXLOrUIntXL.swift | 6 --- .../NBKFlexibleWidth+Addition+Digit.swift | 4 +- .../NBKFlexibleWidth+Addition.swift | 4 +- .../NBKFlexibleWidth+Bits.swift | 10 ++-- .../NBKFlexibleWidth+Comparisons.swift | 4 +- .../NBKFlexibleWidth+Complements.swift | 2 +- .../NBKFlexibleWidth+Data.swift | 18 ++++++- .../NBKFlexibleWidth+Division.swift | 30 +++++------ .../NBKFlexibleWidth+Literals.swift | 20 ++++--- ...BKFlexibleWidth+Multiplication+Digit.swift | 4 +- .../NBKFlexibleWidth+Multiplication.swift | 12 ++--- .../NBKFlexibleWidth+Numbers.swift | 8 --- ...e.swift => NBKFlexibleWidth+Storage.swift} | 21 ++++++-- .../NBKFlexibleWidth+Subtraction+Digit.swift | 8 +-- .../NBKFlexibleWidth+Subtraction.swift | 8 +-- .../NBKFlexibleWidth+Text.swift | 51 ++++++++---------- .../NBKFlexibleWidth+Update.swift | 2 +- .../NBKFlexibleWidth+Words+Pointers.swift | 28 +++++++++- .../NBKFlexibleWidth+Words.swift | 23 ++++---- .../NBKFlexibleWidth.swift | 52 +++++++++++-------- .../NBKSigned+Multiplication+Digit.swift | 3 +- .../NBKSigned+Multiplication.swift | 5 +- Sources/NBKSignedKit/NBKSigned.swift | 14 +---- .../{Exports.swift => Numberick.swift} | 7 +++ .../NBKFlexibleWidth+Numbers.swift | 7 --- 25 files changed, 196 insertions(+), 155 deletions(-) rename Sources/NBKFlexibleWidthKit/{NBKFlexibleWidth+Size.swift => NBKFlexibleWidth+Storage.swift} (75%) rename Sources/Numberick/{Exports.swift => Numberick.swift} (71%) diff --git a/Sources/NBKFlexibleWidthKit/IntXLOrUIntXL.swift b/Sources/NBKFlexibleWidthKit/IntXLOrUIntXL.swift index fe73e4b9..d595d76d 100644 --- a/Sources/NBKFlexibleWidthKit/IntXLOrUIntXL.swift +++ b/Sources/NBKFlexibleWidthKit/IntXLOrUIntXL.swift @@ -23,12 +23,6 @@ public protocol IntXLOrUIntXL: NBKBinaryInteger, ExpressibleByStringLiteral wher func compared(to other: Digit, at index: Int) -> Int - //=------------------------------------------------------------------------= - // MARK: Details x Numbers - //=------------------------------------------------------------------------= - - init(digit: Digit, at index: Int) - //=------------------------------------------------------------------------= // MARK: Details x Addition //=------------------------------------------------------------------------= diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift index 202b8d91..f98c37d3 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift @@ -20,11 +20,11 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @_disfavoredOverload @inlinable public static func +=(lhs: inout Self, rhs: UInt) { - lhs.add(rhs, at: Int.zero) + lhs.add(rhs, at: 0 as Int) } @_disfavoredOverload @inlinable public static func +(lhs: Self, rhs: UInt) -> Self { - lhs.adding(rhs, at: Int.zero) + lhs.adding(rhs, at: 0 as Int) } //=------------------------------------------------------------------------= diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift index f2f7703e..3315d2d1 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift @@ -20,11 +20,11 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @inlinable public static func +=(lhs: inout Self, rhs: Self) { - lhs.add(rhs, at: Int.zero) + lhs.add(rhs, at: 0 as Int) } @inlinable public static func +(lhs: Self, rhs: Self) -> Self { - lhs.adding(rhs, at: Int.zero) + lhs.adding(rhs, at: 0 as Int) } //=------------------------------------------------------------------------= diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift index f2e99e0e..a50172be 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift @@ -32,22 +32,22 @@ extension NBKFlexibleWidth.Magnitude { } @inlinable public var nonzeroBitCount: Int { - self.storage.elements.withUnsafeBufferPointer(NBK.nonzeroBitCount(of:)) + self.withUnsafeBufferPointer(NBK.nonzeroBitCount(of:)) } @inlinable public var leadingZeroBitCount: Int { - self.storage.elements.withUnsafeBufferPointer(NBK.leadingZeroBitCount(of:)) + self.withUnsafeBufferPointer(NBK.leadingZeroBitCount(of:)) } @inlinable public var trailingZeroBitCount: Int { - self.storage.elements.withUnsafeBufferPointer(NBK.trailingZeroBitCount(of:)) + self.withUnsafeBufferPointer(NBK.trailingZeroBitCount(of:)) } @inlinable public var mostSignificantBit: Bool { - self.storage.elements.last!.mostSignificantBit + self.storage.last.mostSignificantBit } @inlinable public var leastSignificantBit: Bool { - self.storage.elements.first!.leastSignificantBit + self.storage.first.leastSignificantBit } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift index 38455e25..1864de10 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift @@ -20,7 +20,7 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @inlinable public var isZero: Bool { - self.storage.elements.count == 1 && self.storage.elements.first!.isZero + self.storage.elements.count == 1 && self.storage.first.isZero } @inlinable public var isLessThanZero: Bool { @@ -32,7 +32,7 @@ extension NBKFlexibleWidth.Magnitude { } @inlinable public var isPowerOf2: Bool { - self.storage.elements.withUnsafeBufferPointer({ NBK.nonzeroBitCount(of: $0, equals: 1) }) + self.withUnsafeBufferPointer({ NBK.nonzeroBitCount(of: $0, equals: 1) }) } @inlinable public func signum() -> Int { diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements.swift index d999a146..524ac4e3 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements.swift @@ -25,7 +25,7 @@ extension NBKFlexibleWidth.Magnitude { } @inlinable public func onesComplement() -> Self { - Self(storage: self.storage.onesComplement()) + Self(normalizing: self.storage.onesComplement()) } //=------------------------------------------------------------------------= diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Data.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Data.swift index d27f905e..b42b5569 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Data.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Data.swift @@ -9,6 +9,22 @@ import NBKCoreKit +//*============================================================================* +// MARK: * NBK x Double Width x Data x Unsigned +//*============================================================================* + +extension NBKFlexibleWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Initializers x Private + //=------------------------------------------------------------------------= + + /// Creates a new instance with unsafe access to its uninitialized memory. + @inlinable static func uninitialized(count: Int, body: (inout NBK.UnsafeMutableWords) -> Void) -> Self { + Self(normalizing: Storage.uninitialized(count: count, body: body)) + } +} + //*============================================================================* // MARK: * NBK x Double Width x Data x Unsigned x Storage //*============================================================================* @@ -21,6 +37,6 @@ extension NBKFlexibleWidth.Magnitude.Storage { /// Creates a new instance with unsafe access to its uninitialized memory. @inlinable static func uninitialized(count: Int, body: (inout NBK.UnsafeMutableWords) -> Void) -> Self { - Self(elements: Elements(unsafeUninitializedCapacity: count) { body(&$0); $1 = count }) + Self(Elements(unsafeUninitializedCapacity: count) { body(&$0); $1 = $0.count }) } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift index 84d92f77..456e23ee 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift @@ -73,34 +73,34 @@ extension NBKFlexibleWidth.Magnitude { // divisor is one word //=--------------------------------------= if other.storage.elements.count == 1 { - let qr = self.quotientAndRemainder(dividingBy: other.storage.elements.first!) + let qr: QR = self.quotientAndRemainder(dividingBy: other.storage.first) self.update(qr.remainder) return PVO(qr.quotient, false) } //=--------------------------------------= // divisor is greater than or equal //=--------------------------------------= - let comparison = other.compared(to: self) - if comparison >= 0 { - if comparison.isZero { - self.updateZeroValue() - return PVO(001, false) - } else { - return PVO(000, false) - } + let comparison = other.compared(to: self) + if comparison.isLessThanZero { + // such empty. much wow. + } else if comparison.isZero { + self.updateZeroValue() + return PVO(001, false) + } else { + return PVO(000, false) } //=--------------------------------------= // shift to clamp approximation //=--------------------------------------= - var divisor = other.storage - let shift = divisor.elements.last!.leadingZeroBitCount as Int - divisor.bitshiftLeft(words: Int.zero, bits: shift) + var divisor = other.storage as Storage + let shift = divisor.last.leadingZeroBitCount as Int + divisor.bitshiftLeft(words: 0 as Int, bits: shift) let divisorLast0 = divisor.elements[divisor.elements.endIndex - 1] as UInt assert(divisorLast0.mostSignificantBit) var remainderIndex = self.storage.elements.endIndex self.storage.append(0) - self.storage.bitshiftLeft(words: Int.zero, bits: shift) + self.storage.bitshiftLeft(words: 0 as Int, bits: shift) //=--------------------------------------= // division: approximate quotient digits //=--------------------------------------= @@ -119,7 +119,7 @@ extension NBKFlexibleWidth.Magnitude { } //=------------------------------= if !digit.isZero { - var overflow = self.storage.subtract(divisor, times: digit, plus: UInt.zero, plus: false, at: quotientIndex) + var overflow = self.storage.subtract(divisor, times: digit, plus: 0 as UInt, plus: false, at: quotientIndex) decrement: while overflow { _ = digit.subtractReportingOverflow(1 as UInt) overflow = !self.storage.add(divisor, plus: false, at: quotientIndex) @@ -134,7 +134,7 @@ extension NBKFlexibleWidth.Magnitude { // undo shift before division //=--------------------------------------= quotient.normalize() - self.storage.bitshiftRight(words: Int.zero, bits: shift) + self.storage.bitshiftRight(words: 0 as Int, bits: shift) self.storage.normalize() return PVO(Self(unchecked: quotient), false) } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Literals.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Literals.swift index c94f0486..5cd21eda 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Literals.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Literals.swift @@ -21,18 +21,24 @@ extension NBKFlexibleWidth.Magnitude { #if SBI && swift(>=5.8) @inlinable public init(integerLiteral source: StaticBigInt) { - if let value = Self(exactlyIntegerLiteral: source) { self = value } else { + if let value = Self(exactlyIntegerLiteral: source) { self = value } else { preconditionFailure("\(Self.description) cannot represent \(source)") } } @inlinable init?(exactlyIntegerLiteral source: StaticBigInt) { - if source.signum() == -1 { return nil } - self.init(truncatingIntegerLiteral: source) - } - - @inlinable init(truncatingIntegerLiteral source: StaticBigInt) { - self.init(storage: Storage(truncatingIntegerLiteral: source)) + guard Self.isSigned || source.signum() >= 0 as Int else { return nil } + //=--------------------------------------= + let bitWidth = Swift.max(1, source.bitWidth - Int(bit: !Self.isSigned)) + let major = NBK .quotientDividingByBitWidthAssumingIsAtLeastZero(bitWidth) + let minor = NBK.remainderDividingByBitWidthAssumingIsAtLeastZero(bitWidth) + let count = major &+ Int(bit: minor.isMoreThanZero) + //=--------------------------------------= + self = Self.uninitialized(count: count) { words in + for index in words.indices { + words.baseAddress!.advanced(by: index).initialize(to: source[index]) + } + } } #else diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift index 2f14ec72..19fdffc1 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift @@ -20,11 +20,11 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @_disfavoredOverload @inlinable public static func *=(lhs: inout Self, rhs: UInt) { - lhs.multiply(by: rhs, add: UInt.zero) + lhs.multiply(by: rhs, add: 0 as UInt) } @_disfavoredOverload @inlinable public static func *(lhs: Self, rhs: UInt) -> Self { - lhs.multiplied(by: rhs, adding: UInt.zero) + lhs.multiplied(by: rhs, adding: 0 as UInt) } //=------------------------------------------------------------------------= diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift index 78c4d425..e98152eb 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift @@ -24,7 +24,7 @@ extension NBKFlexibleWidth.Magnitude { } @inlinable public static func *(lhs: Self, rhs: Self) -> Self { - Self(storage: lhs.storage.multipliedFullWidth(by: rhs.storage)) + Self(normalizing: lhs.storage.multipliedFullWidth(by: rhs.storage)) } } @@ -39,15 +39,15 @@ extension NBKFlexibleWidth.Magnitude.Storage { //=------------------------------------------------------------------------= @inlinable func multipliedFullWidth(by multiplicand: Self) -> Self { - self.multipliedFullWidthByNaiveMethod(by: multiplicand, adding: UInt.zero) + self.multipliedFullWidthByNaiveMethod(by: multiplicand, adding: 0 as UInt) } @inlinable func multipliedFullWidthByNaiveMethod(by multiplicand: Self, adding addend: UInt) -> Self { Self.uninitialized(count: self.elements.count + multiplicand.elements.count) { product in //=----------------------------------= - // de/init: pointee is trivial + // pointee: initialization //=----------------------------------= - product.update(repeating: UInt.zero) + product.initialize(repeating: 0 as UInt) //=----------------------------------= var overflow = addend as UInt for lhsIndex in self.elements.indices { @@ -62,8 +62,8 @@ extension NBKFlexibleWidth.Magnitude.Storage { overflow &+= subproduct.high } - product[lhsIndex + multiplicand.elements.count] = overflow - overflow = UInt.zero + product[lhsIndex + multiplicand.elements.count] = overflow // update + overflow = 0 as UInt } } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift index 14557ea1..a554e5a3 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift @@ -29,14 +29,6 @@ extension NBKFlexibleWidth.Magnitude { self.init(unchecked: Storage(unchecked: [digit])) } - // #warning("unchecked should be unchecked...") - @inlinable public init(digit: UInt, at index: Int) { - var storage = Storage(repeating: 0 as UInt, count: index + 1) - storage.elements[index] = digit - storage.normalize() - self.init(unchecked: storage) - } - //=------------------------------------------------------------------------= // MARK: Initializers x Binary Integer //=------------------------------------------------------------------------= diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Size.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Storage.swift similarity index 75% rename from Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Size.swift rename to Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Storage.swift index c9be2063..b90b22b7 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Size.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Storage.swift @@ -16,7 +16,7 @@ import NBKCoreKit extension NBKFlexibleWidth.Magnitude.Storage { //=------------------------------------------------------------------------= - // MARK: Details x Resize + // MARK: Transformations //=------------------------------------------------------------------------= @inlinable mutating func append(_ word: UInt) { @@ -26,7 +26,7 @@ extension NBKFlexibleWidth.Magnitude.Storage { @inlinable mutating func resize(minCount: Int) { self.reserveCapacity(minCount) appending: while self.elements.count < minCount { - self.elements.append(UInt.zero) + self.elements.append(0 as UInt) } } @@ -40,9 +40,24 @@ extension NBKFlexibleWidth.Magnitude.Storage { @inlinable mutating func reserveCapacity(_ minCapacity: Int) { self.elements.reserveCapacity(minCapacity) } +} + +//=----------------------------------------------------------------------------= +// MARK: + Normalization +//=----------------------------------------------------------------------------= + +extension NBKFlexibleWidth.Magnitude.Storage { + + //=------------------------------------------------------------------------= + // MARK: Accessors + //=------------------------------------------------------------------------= + + @inlinable var isNormal: Bool { + self.elements.count == 1 || !self.last.isZero + } //=------------------------------------------------------------------------= - // MARK: Details x Normalization + // MARK: Transformations //=------------------------------------------------------------------------= @inlinable mutating func normalize() { diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift index 9a739721..ce5ff352 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift @@ -20,19 +20,19 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @_disfavoredOverload @inlinable public static func -=(lhs: inout Self, rhs: UInt) { - lhs.subtract(rhs, at: Int.zero) + lhs.subtract(rhs, at: 0 as Int) } @_disfavoredOverload @inlinable public static func -(lhs: Self, rhs: UInt) -> Self { - lhs.subtracting(rhs, at: Int.zero) + lhs.subtracting(rhs, at: 0 as Int) } @_disfavoredOverload @inlinable public mutating func subtractReportingOverflow(_ other: UInt) -> Bool { - self.subtractReportingOverflow(other, at: Int.zero) + self.subtractReportingOverflow(other, at: 0 as Int) } @_disfavoredOverload @inlinable public func subtractingReportingOverflow(_ other: UInt) -> PVO { - self.subtractingReportingOverflow(other, at: Int.zero) + self.subtractingReportingOverflow(other, at: 0 as Int) } //=------------------------------------------------------------------------= diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift index 43bc14f0..a975fcc5 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift @@ -20,19 +20,19 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @inlinable public static func -=(lhs: inout Self, rhs: Self) { - lhs.subtract(rhs, at: Int.zero) + lhs.subtract(rhs, at: 0 as Int) } @inlinable public static func -(lhs: Self, rhs: Self) -> Self { - lhs.subtracting(rhs, at: Int.zero) + lhs.subtracting(rhs, at: 0 as Int) } @inlinable public mutating func subtractReportingOverflow(_ other: Self) -> Bool { - self.subtractReportingOverflow(other, at: Int.zero) + self.subtractReportingOverflow(other, at: 0 as Int) } @inlinable public func subtractingReportingOverflow(_ other: Self) -> PVO { - self.subtractingReportingOverflow(other, at: Int.zero) + self.subtractingReportingOverflow(other, at: 0 as Int) } //=------------------------------------------------------------------------= diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text.swift index dbae4003..81fc688b 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text.swift @@ -19,7 +19,7 @@ extension NBKFlexibleWidth.Magnitude { // MARK: Details x Decode //=------------------------------------------------------------------------= - @inlinable public init?(_ description: some StringProtocol, radix: Int = 10) { + @inlinable public init?(_ description: some StringProtocol, radix: Int) { var description = String(description) let value: Optional = description.withUTF8 { utf8 in @@ -37,12 +37,12 @@ extension NBKFlexibleWidth.Magnitude { // MARK: Details x Encode //=------------------------------------------------------------------------= - @inlinable public func description(radix: Int = 10, uppercase: Bool = false) -> String { + @inlinable public func description(radix: Int, uppercase: Bool) -> String { Swift.withUnsafePointer(to: UInt8(ascii: "-")) { minus in let radix = NBK.AnyRadixSolution(radix) let alphabet = NBK.MaxRadixAlphabetEncoder(uppercase: uppercase) let prefix = NBK.UnsafeUTF8(start: minus, count: Int(bit: self.isLessThanZero)) - let suffix = NBK.UnsafeUTF8(start: nil, count: Int.zero) + let suffix = NBK.UnsafeUTF8(start: nil, count: 0 as Int) return self.magnitude.description(radix: radix, alphabet: alphabet, prefix: prefix, suffix: suffix) } } @@ -71,20 +71,16 @@ extension NBKFlexibleWidth.Magnitude { let division = digits.count.quotientAndRemainder(dividingBy: radix.exponent) let count = division.quotient + Int(bit: !division.remainder.isZero) //=--------------------------------------= - guard count.isMoreThanZero else { self = Self.zero; return } - //=--------------------------------------= - var error = false - let value = Storage.uninitialized(count: count) { storage in - for index in storage.indices { - let chunk = NBK.UnsafeUTF8(rebasing: NBK.removeSuffix(from: &digits, maxLength: radix.exponent)) - guard let word = NBK.truncating(digits: chunk, radix: radix.base, as: UInt.self) else { return error = true } - storage[index] = word - } - - Swift.assert(digits.isEmpty) + var elements = Elements(repeating: 0, count: count) + + backwards: for index in elements.indices { + let chunk = NBK.UnsafeUTF8(rebasing: NBK.removeSuffix(from: &digits, maxLength: radix.exponent)) + guard let word = NBK.truncating(digits: chunk, radix: radix.base, as: UInt.self) else { return nil } + elements[index] = word } - if !error { self.init(unchecked: value) } else { return nil } + self.init(unchecked: Storage(nonemptying: elements)) + Swift.assert(self.storage.isNormal) } @inlinable init?(digits: NBK.UnsafeUTF8, radix: NBK.ImperfectRadixSolution) { @@ -94,21 +90,18 @@ extension NBKFlexibleWidth.Magnitude { let alignment = digits.count % radix.exponent //=--------------------------------------= self.init() - guard let _ = { // this closure makes it 10% faster for some reason - - forwards: if !alignment.isZero { - let chunk = NBK.UnsafeUTF8(rebasing: NBK.removePrefix(from: &digits, count: alignment)) - guard let word = NBK.truncating(digits: chunk, radix: radix.base, as: UInt.self) else { return nil } - self.storage.elements[self.storage.elements.startIndex] = word - } - forwards: while !digits.isEmpty { - let chunk = NBK.UnsafeUTF8(rebasing: NBK.removePrefix(from: &digits, count: radix.exponent)) - guard let word = NBK.truncating(digits: chunk, radix: radix.base, as: UInt.self) else { return nil } - self.multiply(by: radix.power, add: word) - } - - }() as Void? else { return nil } + forwards: if !alignment.isZero { + let chunk = NBK.UnsafeUTF8(rebasing: NBK.removePrefix(from: &digits, count: alignment)) + guard let word = NBK.truncating(digits: chunk, radix: radix.base, as: UInt.self) else { return nil } + self.storage.elements[self.storage.elements.startIndex] = word + } + + forwards: while !digits.isEmpty { + let chunk = NBK.UnsafeUTF8(rebasing: NBK.removePrefix(from: &digits, count: radix.exponent)) + guard let word = NBK.truncating(digits: chunk, radix: radix.base, as: UInt.self) else { return nil } + self.multiply(by: radix.power, add: word) + } } //=------------------------------------------------------------------------= diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Update.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Update.swift index f32878b9..37a16ae4 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Update.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Update.swift @@ -20,7 +20,7 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @inlinable public mutating func updateZeroValue() { - self.update(UInt.zero) + self.update(0 as UInt) } @inlinable public mutating func update(_ value: Digit) { diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words+Pointers.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words+Pointers.swift index 9aab0d6c..d15b6c5f 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words+Pointers.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words+Pointers.swift @@ -9,6 +9,30 @@ import NBKCoreKit +//*============================================================================* +// MARK: * NBK x Flexible Width x Words x Pointers x Unsigned +//*============================================================================* + +extension NBKFlexibleWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Details x Contiguous UInt Collection + //=------------------------------------------------------------------------= + + /// Grants unsafe access to the collection's contiguous storage. + @inlinable public func withUnsafeBufferPointer( + _ body:(NBK.UnsafeWords) throws -> T) rethrows -> T { + try self.storage.withUnsafeBufferPointer(body) + } + + /// Grants unsafe access to the collection's contiguous mutable storage. + @inlinable public mutating func withUnsafeMutableBufferPointer( + _ body:(inout NBK.UnsafeMutableWords) throws -> T) rethrows -> T { + defer{ self.storage.normalize() } + return try self.storage.withUnsafeMutableBufferPointer(body) + } +} + //*============================================================================* // MARK: * NBK x Flexible Width x Words x Pointers x Unsigned x Storage //*============================================================================* @@ -21,13 +45,13 @@ extension NBKFlexibleWidth.Magnitude.Storage { /// Grants unsafe access to the collection's contiguous storage. @inlinable func withUnsafeBufferPointer( - _ body: (NBK.UnsafeWords) throws -> T) rethrows -> T { + _ body:(NBK.UnsafeWords) throws -> T) rethrows -> T { try self.elements.withUnsafeBufferPointer(body) } /// Grants unsafe access to the collection's contiguous mutable storage. @inlinable mutating func withUnsafeMutableBufferPointer( - _ body: (inout NBK.UnsafeMutableWords) throws -> T) rethrows -> T { + _ body:(inout NBK.UnsafeMutableWords) throws -> T) rethrows -> T { try self.elements.withUnsafeMutableBufferPointer(body) } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift index 0698191a..e700069a 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift @@ -19,15 +19,14 @@ extension NBKFlexibleWidth.Magnitude { // MARK: Initializers //=------------------------------------------------------------------------= - @inlinable public init(words: some Collection) { - self.init(storage: Storage(words: words)) + @inlinable public init(words: some Sequence) { + self.init(normalizing: Storage(nonemptying: Elements(words))) } //=------------------------------------------------------------------------= // MARK: Accessors //=------------------------------------------------------------------------= - // TODO: do not expose the actual type @inlinable public var words: ContiguousArray { _read { yield self.storage.elements } } @@ -38,16 +37,22 @@ extension NBKFlexibleWidth.Magnitude { //*============================================================================* extension NBKFlexibleWidth.Magnitude.Storage { - + //=------------------------------------------------------------------------= - // MARK: Initializers + // MARK: Accessors //=------------------------------------------------------------------------= - @inlinable init(words: some Collection) { - self.init(elements: Elements(words)) + @inlinable var first: UInt { + get { self.elements[self.elements.startIndex] } + set { self.elements[self.elements.startIndex] = newValue } + } + + @inlinable var last: UInt { + get { self.elements[self.lastIndex] } + set { self.elements[self.lastIndex] = newValue } } - @inlinable init(repeating word: UInt, count: Int) { - self.init(elements: Elements(repeating: word, count: count)) + @inlinable var lastIndex: Int { + self.elements.index(before: self.elements.endIndex) } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift index 7762a41c..cc2582ef 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift @@ -20,40 +20,49 @@ import NBKCoreKit /// - Note: You can use `NBKSigned` until `IntXL` becomes available. /// @frozen public struct NBKFlexibleWidth { + + @usableFromInline typealias Elements = ContiguousArray //*========================================================================* // MARK: * Magnitude //*========================================================================* /// An unsigned, flexible-width, binary integer. - /// - /// ### Logic - /// - /// - TODO: Comment on bitwise NOT, AND, OR, XOR semantics. - /// @frozen public struct Magnitude: NBKUnsignedInteger, IntXLOrUIntXL { public typealias Digit = UInt + + public typealias Words = ContiguousArray // TODO: make opaque + + @usableFromInline typealias Elements = NBKFlexibleWidth.Elements //=--------------------------------------------------------------------= // MARK: State //=--------------------------------------------------------------------= + /// The integer's underlying storage. + /// + /// It must be `normal` and `nonempty` at the start and end of each access. + /// @usableFromInline var storage: Storage //=--------------------------------------------------------------------= // MARK: Initializers //=--------------------------------------------------------------------= - @inlinable init(storage: Storage) { + @inlinable init(_ storage: Storage) { + self.storage = storage + precondition(self.storage.isNormal) + } + + @inlinable init(normalizing storage: Storage) { self.storage = storage self.storage.normalize() Swift.assert(self.storage.isNormal) } - @inlinable init(unchecked: Storage) { - self.storage = unchecked - Swift.assert(self.storage.isNormal) + @inlinable init(unchecked storage: Storage) { + self.storage = storage } //=--------------------------------------------------------------------= @@ -75,7 +84,6 @@ import NBKCoreKit "UIntXL" } - // #warning("check uses of elements, first!, last!, count, lastIndex") //*====================================================================* // MARK: * Storage //*====================================================================* @@ -86,34 +94,36 @@ import NBKCoreKit /// @frozen @usableFromInline struct Storage { - @usableFromInline typealias Elements = ContiguousArray + @usableFromInline typealias Elements = NBKFlexibleWidth.Elements //=----------------------------------------------------------------= // MARK: State //=----------------------------------------------------------------= - @usableFromInline var elements: ContiguousArray + /// A collection of unsigned integers. + /// + /// It must be `nonempty` at the start and end of each access. + /// + @usableFromInline var elements: Elements //=----------------------------------------------------------------= // MARK: Initializers //=----------------------------------------------------------------= - @inlinable init(elements: Elements) { + @inlinable init(_ elements: Elements) { self.elements = elements precondition(!self.elements.isEmpty) } - @inlinable init(unchecked elements: Elements) { + @inlinable init(nonemptying elements: Elements) { self.elements = elements - Swift.assert(!self.elements.isEmpty) + if self.elements.isEmpty { + self.elements.append(0) + } } - //=----------------------------------------------------------------= - // MARK: Utilities - //=----------------------------------------------------------------= - - @inlinable var isNormal: Bool { - self.elements.count == 1 || !self.elements.last!.isZero + @inlinable init(unchecked elements: Elements) { + self.elements = elements } } } diff --git a/Sources/NBKSignedKit/NBKSigned+Multiplication+Digit.swift b/Sources/NBKSignedKit/NBKSigned+Multiplication+Digit.swift index 3251fcbf..0bd14a07 100644 --- a/Sources/NBKSignedKit/NBKSigned+Multiplication+Digit.swift +++ b/Sources/NBKSignedKit/NBKSigned+Multiplication+Digit.swift @@ -20,8 +20,7 @@ extension NBKSigned { //=------------------------------------------------------------------------= @_disfavoredOverload @inlinable public static func *=(lhs: inout Self, rhs: Digit) { - lhs.sign = lhs.sign ^ rhs.sign - lhs.magnitude *= rhs.magnitude + lhs.sign ^= rhs.sign; lhs.magnitude *= rhs.magnitude } @_disfavoredOverload @inlinable public static func *(lhs: Self, rhs: Digit) -> Self { diff --git a/Sources/NBKSignedKit/NBKSigned+Multiplication.swift b/Sources/NBKSignedKit/NBKSigned+Multiplication.swift index 9d90c767..112f698b 100644 --- a/Sources/NBKSignedKit/NBKSigned+Multiplication.swift +++ b/Sources/NBKSignedKit/NBKSigned+Multiplication.swift @@ -18,10 +18,9 @@ extension NBKSigned { //=------------------------------------------------------------------------= // MARK: Transformations //=------------------------------------------------------------------------= - + @inlinable public static func *=(lhs: inout Self, rhs: Self) { - lhs.sign = lhs.sign ^ rhs.sign - lhs.magnitude *= rhs.magnitude + lhs.sign ^= rhs.sign; lhs.magnitude *= rhs.magnitude } @inlinable public static func *(lhs: Self, rhs: Self) -> Self { diff --git a/Sources/NBKSignedKit/NBKSigned.swift b/Sources/NBKSignedKit/NBKSigned.swift index 0e469934..c625ac22 100644 --- a/Sources/NBKSignedKit/NBKSigned.swift +++ b/Sources/NBKSignedKit/NBKSigned.swift @@ -13,7 +13,7 @@ import NBKCoreKit // MARK: * NBK x Signed //*============================================================================* -/// A decorative, width agnostic, sign-and-magnitude integer. +/// A decorative sign-and-magnitude integer. /// /// ```swift /// typealias SInt = NBKSigned @@ -109,15 +109,3 @@ public typealias SInt32 = NBKSigned /// A signed integer with a 64-bit magnitude. public typealias SInt64 = NBKSigned - -//=----------------------------------------------------------------------------= -// MARK: + Flexible Width -//=----------------------------------------------------------------------------= -#if canImport(NBKFlexibleWidthKit) - -import NBKFlexibleWidthKit - -/// A signed integer with a flexible-width magnitude. -public typealias SIntXL = NBKSigned - -#endif diff --git a/Sources/Numberick/Exports.swift b/Sources/Numberick/Numberick.swift similarity index 71% rename from Sources/Numberick/Exports.swift rename to Sources/Numberick/Numberick.swift index adbbc52d..a36bbccd 100644 --- a/Sources/Numberick/Exports.swift +++ b/Sources/Numberick/Numberick.swift @@ -15,3 +15,10 @@ @_exported import NBKDoubleWidthKit @_exported import NBKFlexibleWidthKit @_exported import NBKSignedKit + +//*============================================================================* +// MARK: * NBK x Aliases +//*============================================================================* + +/// A signed integer with a flexible-width magnitude. +public typealias SIntXL = NBKSigned diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Numbers.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Numbers.swift index ad86ae36..0741dc3a 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Numbers.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Numbers.swift @@ -105,13 +105,6 @@ final class NBKFlexibleWidthTestsOnNumbersAsUIntXL: XCTestCase { NBKAssertNumbers(from: T(digit: UInt.max), default: T(words:[~0, 0, 0, 0] as W)) } - func testFromUIntAsDigitAtIndex() { - NBKAssertNumbers(from: T(digit: UInt.max, at: Int(0)), default: T(words:[~0, 0, 0, 0] as W)) - NBKAssertNumbers(from: T(digit: UInt.max, at: Int(1)), default: T(words:[ 0, ~0, 0, 0] as W)) - NBKAssertNumbers(from: T(digit: UInt.max, at: Int(2)), default: T(words:[ 0, 0, ~0, 0] as W)) - NBKAssertNumbers(from: T(digit: UInt.max, at: Int(3)), default: T(words:[ 0, 0, 0, ~0] as W)) - } - //=------------------------------------------------------------------------= // MARK: Tests x UInt32 //=------------------------------------------------------------------------= From a4e01a05471d85c9049cea700ce8ffb4701a4ba9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sun, 17 Sep 2023 09:25:34 +0200 Subject: [PATCH 077/133] [NBKFlexibleWidthKit] Strict unsigned integer (#83). --- .../NBKFlexibleWidthKit-Benchmarks.xctestplan | 4 + .../NBKFlexibleWidth+Addition+Digit.swift | 25 +- .../NBKFlexibleWidth+Addition.swift | 23 +- .../NBKFlexibleWidth+Bits.swift | 4 +- .../NBKFlexibleWidth+Comparisons.swift | 2 +- .../NBKFlexibleWidth+Complements.swift | 78 +---- .../NBKFlexibleWidth+Division.swift | 16 +- ...BKFlexibleWidth+Multiplication+Digit.swift | 25 +- .../NBKFlexibleWidth+Storage.swift | 2 +- .../NBKFlexibleWidth+Subtraction+Digit.swift | 19 +- .../NBKFlexibleWidth+Subtraction.swift | 25 +- .../NBKFlexibleWidth+Words+Pointers.swift | 39 +++ .../NBKFlexibleWidth+Words.swift | 35 +- .../NBKStrictUnsignedInteger+Addition.swift | 261 +++++++++++++++ ...NBKStrictUnsignedInteger+Complements.swift | 49 +++ ...StrictUnsignedInteger+Multiplication.swift | 49 +++ ...NBKStrictUnsignedInteger+Subtraction.swift | 310 ++++++++++++++++++ .../Private/NBKStrictUnsignedInteger.swift | 92 ++++++ 18 files changed, 874 insertions(+), 184 deletions(-) create mode 100644 Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Addition.swift create mode 100644 Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Complements.swift create mode 100644 Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Multiplication.swift create mode 100644 Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Subtraction.swift create mode 100644 Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger.swift diff --git a/.swiftpm/NBKFlexibleWidthKit-Benchmarks.xctestplan b/.swiftpm/NBKFlexibleWidthKit-Benchmarks.xctestplan index 44560b00..1501455e 100644 --- a/.swiftpm/NBKFlexibleWidthKit-Benchmarks.xctestplan +++ b/.swiftpm/NBKFlexibleWidthKit-Benchmarks.xctestplan @@ -13,6 +13,10 @@ }, "testTargets" : [ { + "skippedTests" : [ + "NBKFlexibleWidthBenchmarksOnTextAsUIntXL\/testEncodingUsingSwiftStdlibRadix10()", + "NBKFlexibleWidthBenchmarksOnTextAsUIntXL\/testEncodingUsingSwiftStdlibRadix16()" + ], "target" : { "containerPath" : "container:", "identifier" : "NBKFlexibleWidthKitBenchmarks", diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift index f98c37d3..f2311de9 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift @@ -39,26 +39,17 @@ extension NBKFlexibleWidth.Magnitude { if other.isZero { return } //=--------------------------------------= self.storage.resize(minCount: index + 1) - let overflow = self.storage.add(other, plus: false, at: index) - if overflow { self.storage.append(1 as UInt) } + + let overflow = self.storage.withUnsafeMutableStrictUnsignedInteger { + $0.increment(by: other, at: index).overflow + } + + if overflow { + self.storage.append(1 as UInt) + } } @_disfavoredOverload @inlinable public func adding(_ other: UInt, at index: Int) -> Self { var result = self; result.add(other, at: index); return result } } - -//*============================================================================* -// MARK: * NBK x Flexible Width x Addition x Unsigned x Storage -//*============================================================================* - -extension NBKFlexibleWidth.Magnitude.Storage { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @_disfavoredOverload @inlinable mutating func add(_ other: UInt, plus carry: Bool, at index: Int) -> Bool { - NBK.incrementSufficientUnsignedInteger(&self.elements, by: other, plus: carry, at: index).overflow - } -} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift index 3315d2d1..78c264c4 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift @@ -38,8 +38,12 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= if other.isZero { return } //=--------------------------------------= - self.storage.resize(minCount: other.storage.elements.count + index) - let overflow = self.storage.add(other.storage, plus: false, at: index) + self.storage.resize(minCount: other.storage.elements.count + index) + + let overflow = self.storage.withUnsafeMutableStrictUnsignedInteger { + $0.increment(by: other.storage.elements, plus: false, at: index).overflow + } + if overflow { self.storage.append(1 as UInt) } } @@ -47,18 +51,3 @@ extension NBKFlexibleWidth.Magnitude { var result = self; result.add(other, at: index); return result } } - -//*============================================================================* -// MARK: * NBK x Flexible Width x Addition x Unsigned x Storage -//*============================================================================* - -extension NBKFlexibleWidth.Magnitude.Storage { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable mutating func add(_ other: Self, plus carry: Bool, at index: Int) -> Bool { - NBK.incrementSufficientUnsignedInteger(&self.elements, by: other.elements, plus: carry, at: index).overflow - } -} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift index a50172be..69c917d4 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift @@ -44,10 +44,10 @@ extension NBKFlexibleWidth.Magnitude { } @inlinable public var mostSignificantBit: Bool { - self.storage.last.mostSignificantBit + self.last.mostSignificantBit } @inlinable public var leastSignificantBit: Bool { - self.storage.first.leastSignificantBit + self.first.leastSignificantBit } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift index 1864de10..28e8425c 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift @@ -20,7 +20,7 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @inlinable public var isZero: Bool { - self.storage.elements.count == 1 && self.storage.first.isZero + self.withUnsafeStrictUnsignedInteger({ $0.base.count == 1 && $0.first.isZero }) } @inlinable public var isLessThanZero: Bool { diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements.swift index 524ac4e3..f4eecb14 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements.swift @@ -20,12 +20,13 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @inlinable public mutating func formOnesComplement() { - self.storage.formOnesComplement() - self.storage.normalize() + self.withUnsafeMutableStrictUnsignedInteger { + $0.formOnesComplement() + } } @inlinable public func onesComplement() -> Self { - Self(normalizing: self.storage.onesComplement()) + Self(normalizing: Storage(unchecked: Elements(self.storage.elements.lazy.map(~)))) } //=------------------------------------------------------------------------= @@ -33,8 +34,9 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @inlinable public mutating func formTwosComplementReportingOverflow() -> Bool { - defer{ self.storage.normalize() } - return self.storage.formTwosComplementReportingOverflow() + self.withUnsafeMutableStrictUnsignedInteger { + $0.formTwosComplementReportingOverflow() + } } @inlinable public func twosComplementReportingOverflow() -> PVO { @@ -44,72 +46,12 @@ extension NBKFlexibleWidth.Magnitude { } @inlinable public mutating func formTwosComplementSubsequence(_ carry: Bool) -> Bool { - defer{ self.storage.normalize() } - return self.storage.formTwosComplementSubsequence(carry) - } - - @inlinable public func twosComplementSubsequence(_ carry: Bool) -> PVO { - var partialValue = self - let overflow = partialValue.formTwosComplementSubsequence(carry) - return PVO(partialValue, overflow) - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Complements x Unsigned x Storage -//*============================================================================* - -extension NBKFlexibleWidth.Magnitude.Storage { - - //=------------------------------------------------------------------------= - // MARK: Details x One's Complement - //=------------------------------------------------------------------------= - - @inlinable mutating func formOnesComplement() { - for index in self.elements.indices { - self.elements[index].formOnesComplement() + self.withUnsafeMutableStrictUnsignedInteger { + $0.formTwosComplementSubsequence(carry) } } - @inlinable func onesComplement() -> Self { - Self(unchecked: Elements(self.elements.lazy.map(~))) - } - - //=------------------------------------------------------------------------= - // MARK: Details x Two's Complement - //=------------------------------------------------------------------------= - - @inlinable mutating func formTwosComplement() { - _ = self.formTwosComplementSubsequence(true) - } - - @inlinable func twosComplementw() -> Self { - var partialValue = self - partialValue.formTwosComplement() - return partialValue as Self - } - - @inlinable mutating func formTwosComplementReportingOverflow() -> Bool { - self.formTwosComplementSubsequence(true) - } - - @inlinable func twosComplementReportingOverflow() -> PVO { - var partialValue = self - let overflow = partialValue.formTwosComplementReportingOverflow() - return PVO(partialValue, overflow) - } - - @inlinable mutating func formTwosComplementSubsequence(_ carry: Bool) -> Bool { - var carry = carry - - for index in self.elements.indices { - carry = self.elements[index].formTwosComplementSubsequence(carry) - } - - return carry as Bool - } - - @inlinable func twosComplementSubsequence(_ carry: Bool) -> PVO { + @inlinable public func twosComplementSubsequence(_ carry: Bool) -> PVO { var partialValue = self let overflow = partialValue.formTwosComplementSubsequence(carry) return PVO(partialValue, overflow) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift index 456e23ee..887551ef 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift @@ -72,8 +72,8 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= // divisor is one word //=--------------------------------------= - if other.storage.elements.count == 1 { - let qr: QR = self.quotientAndRemainder(dividingBy: other.storage.first) + if other.count == 1 { + let qr: QR = self.quotientAndRemainder(dividingBy: other.first) self.update(qr.remainder) return PVO(qr.quotient, false) } @@ -92,8 +92,8 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= // shift to clamp approximation //=--------------------------------------= + let shift = other.last.leadingZeroBitCount as Int var divisor = other.storage as Storage - let shift = divisor.last.leadingZeroBitCount as Int divisor.bitshiftLeft(words: 0 as Int, bits: shift) let divisorLast0 = divisor.elements[divisor.elements.endIndex - 1] as UInt assert(divisorLast0.mostSignificantBit) @@ -119,10 +119,12 @@ extension NBKFlexibleWidth.Magnitude { } //=------------------------------= if !digit.isZero { - var overflow = self.storage.subtract(divisor, times: digit, plus: 0 as UInt, plus: false, at: quotientIndex) - decrement: while overflow { - _ = digit.subtractReportingOverflow(1 as UInt) - overflow = !self.storage.add(divisor, plus: false, at: quotientIndex) + self.storage.withUnsafeMutableStrictUnsignedInteger { + var overflow = $0.decrement(by: divisor.elements, times: digit, plus: 0 as UInt, plus: false, at: quotientIndex).overflow + decrement: while overflow { + digit &-= 1 as Digit + overflow = !$0.increment(by: divisor.elements, plus: false, at: quotientIndex).overflow + } } } //=------------------------------= diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift index 19fdffc1..56f879d8 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift @@ -41,9 +41,13 @@ extension NBKFlexibleWidth.Magnitude { } //=--------------------------------------= self.storage.reserveCapacity(self.storage.elements.count + 1) - let overflow = self.storage.multiply(by: multiplicand, add: addend) - if !overflow.isZero { - self.storage.append(overflow) + + let carry = self.storage.withUnsafeMutableStrictUnsignedInteger { + $0.multiplyFullWidth(by: multiplicand, add: addend) + } + + if !carry.isZero { + self.storage.append(carry) } } @@ -51,18 +55,3 @@ extension NBKFlexibleWidth.Magnitude { var result = self; result.multiply(by: multiplicand, add: addend); return result } } - -//*============================================================================* -// MARK: * NBK x Resizable Width x Multiplication x Digit x Unsigned -//*============================================================================* - -extension NBKFlexibleWidth.Magnitude.Storage { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @_disfavoredOverload @inlinable mutating func multiply(by other: UInt, add addend: UInt) -> UInt { - NBK.multiplyFullWidthLenientUnsignedInteger(&self.elements, by: other, add: addend) - } -} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Storage.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Storage.swift index b90b22b7..194e5093 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Storage.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Storage.swift @@ -53,7 +53,7 @@ extension NBKFlexibleWidth.Magnitude.Storage { //=------------------------------------------------------------------------= @inlinable var isNormal: Bool { - self.elements.count == 1 || !self.last.isZero + self.elements.count == 1 || !self.elements.last!.isZero } //=------------------------------------------------------------------------= diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift index ce5ff352..e2ce8f70 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift @@ -59,7 +59,9 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= self.storage.resize(minCount: index + 1) defer{ self.storage.normalize() } - return self.storage.subtract(other, plus: false, at: index) + return self.storage.withUnsafeMutableStrictUnsignedInteger { + $0.decrement(by: other, at: index).overflow + } } @_disfavoredOverload @inlinable public func subtractingReportingOverflow(_ other: UInt, at index: Int) -> PVO { @@ -68,18 +70,3 @@ extension NBKFlexibleWidth.Magnitude { return PVO(partialValue, overflow) } } - -//*============================================================================* -// MARK: * NBK x Flexible Width x Subtraction x Digit x Unsigned x Storage -//*============================================================================* - -extension NBKFlexibleWidth.Magnitude.Storage { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @_disfavoredOverload @inlinable mutating func subtract(_ other: UInt, plus borrow: Bool, at index: Int) -> Bool { - NBK.decrementSufficientUnsignedInteger(&self.elements, by: other, plus: borrow, at: index).overflow - } -} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift index a975fcc5..08b76851 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift @@ -59,7 +59,9 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= self.storage.resize(minCount: other.storage.elements.count + index) defer{ self.storage.normalize() } - return self.storage.subtract(other.storage, plus: false, at: index) + return self.storage.withUnsafeMutableStrictUnsignedInteger { + $0.decrement(by: other.storage.elements, plus: false, at: index).overflow + } } @inlinable public func subtractingReportingOverflow(_ other: Self, at index: Int) -> PVO { @@ -68,24 +70,3 @@ extension NBKFlexibleWidth.Magnitude { return PVO(partialValue, overflow) } } - -//*============================================================================* -// MARK: * NBK x Flexible Width x Subtraction x Unsigned x Storage -//*============================================================================* - -extension NBKFlexibleWidth.Magnitude.Storage { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable mutating func subtract(_ other: Self, plus borrow: Bool, at index: Int) -> Bool { - NBK.decrementSufficientUnsignedInteger(&self.elements, by: other.elements, plus: borrow, at: index).overflow - } - - @inlinable mutating func subtract(_ other: Self, times multiplicand: UInt, - plus subtrahend: UInt, plus borrow: Bool, at index: Int) -> Bool { - NBK.decrementSufficientUnsignedInteger(&self.elements, by: other .elements, - times: multiplicand, plus: subtrahend, plus: borrow, at: index).overflow - } -} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words+Pointers.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words+Pointers.swift index d15b6c5f..e80ae420 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words+Pointers.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words+Pointers.swift @@ -31,6 +31,23 @@ extension NBKFlexibleWidth.Magnitude { defer{ self.storage.normalize() } return try self.storage.withUnsafeMutableBufferPointer(body) } + + //=------------------------------------------------------------------------= + // MARK: Details x Strict Unsigned Integer + //=------------------------------------------------------------------------= + + /// Grants unsafe access to the collection's contiguous storage. + @inlinable func withUnsafeStrictUnsignedInteger( + _ body:(NBKStrictUnsignedInteger) throws -> T) rethrows -> T { + try self.storage.withUnsafeStrictUnsignedInteger(body) + } + + /// Grants unsafe access to the collection's contiguous mutable storage. + @inlinable mutating func withUnsafeMutableStrictUnsignedInteger( + _ body:(inout NBKStrictUnsignedInteger) throws -> T) rethrows -> T { + defer{ self.storage.normalize() } + return try self.storage.withUnsafeMutableStrictUnsignedInteger(body) + } } //*============================================================================* @@ -54,4 +71,26 @@ extension NBKFlexibleWidth.Magnitude.Storage { _ body:(inout NBK.UnsafeMutableWords) throws -> T) rethrows -> T { try self.elements.withUnsafeMutableBufferPointer(body) } + + //=------------------------------------------------------------------------= + // MARK: Details x Strict Unsigned Integer + //=------------------------------------------------------------------------= + + /// Grants unsafe access to the collection's contiguous storage. + @inlinable func withUnsafeStrictUnsignedInteger( + _ body:(NBKStrictUnsignedInteger) throws -> T) rethrows -> T { + try self.withUnsafeBufferPointer { + let view = NBKStrictUnsignedInteger($0) + return try body(view) + } + } + + /// Grants unsafe access to the collection's contiguous mutable storage. + @inlinable mutating func withUnsafeMutableStrictUnsignedInteger( + _ body:(inout NBKStrictUnsignedInteger) throws -> T) rethrows -> T { + try self.withUnsafeMutableBufferPointer { + var view = NBKStrictUnsignedInteger($0) + return try body(&view) + } + } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift index e700069a..7b56a204 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift @@ -27,32 +27,37 @@ extension NBKFlexibleWidth.Magnitude { // MARK: Accessors //=------------------------------------------------------------------------= + @inlinable public var count: Int { + self.storage.elements.count + } + @inlinable public var words: ContiguousArray { _read { yield self.storage.elements } } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Words x Unsigned x Storage -//*============================================================================* - -extension NBKFlexibleWidth.Magnitude.Storage { //=------------------------------------------------------------------------= // MARK: Accessors //=------------------------------------------------------------------------= + + /// The least significant word. + /// + /// - Note: This member is required by `Swift.BinaryInteger`. + /// + @inlinable public var _lowWord: UInt { + self.first as UInt + } - @inlinable var first: UInt { - get { self.elements[self.elements.startIndex] } - set { self.elements[self.elements.startIndex] = newValue } + /// The least significant word. + @inlinable public var first: UInt { + self.withUnsafeStrictUnsignedInteger({ $0.first }) } - @inlinable var last: UInt { - get { self.elements[self.lastIndex] } - set { self.elements[self.lastIndex] = newValue } + /// The most significant word. + @inlinable public var last: UInt { + self.withUnsafeStrictUnsignedInteger({ $0.last }) } - @inlinable var lastIndex: Int { - self.elements.index(before: self.elements.endIndex) + @inlinable subscript(index: Int) -> UInt { + index < self.storage.elements.endIndex ? self.storage.elements[index] : 0 as UInt } } diff --git a/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Addition.swift b/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Addition.swift new file mode 100644 index 00000000..10e97d4c --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Addition.swift @@ -0,0 +1,261 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= +// TODO: See whether consuming arguments removes the need for inout in Swift 5.9 +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Strict Unsigned Integer x Addition +//*============================================================================* +// MARK: + Bit +//=----------------------------------------------------------------------------= + +extension NBKStrictUnsignedInteger where Base: MutableCollection { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + /// Increments `base` by `bit` at `index`. + /// + /// - Returns: An overflow indicator and its index in `base`. + /// + @discardableResult @inlinable public mutating func increment( + by bit: Bool, at index: Base.Index) -> NBK.IO { + var index: Base.Index = index, bit: Bool = bit + //=--------------------------------------= + self.increment(by: &bit, at: &index) + //=--------------------------------------= + return NBK.IO(index: index as Base.Index, overflow: bit as Bool) + } + + //=------------------------------------------------------------------------= + // MARK: Transformationsx x Inout + //=------------------------------------------------------------------------= + + /// Increments `base` by `bit` at `index`. + /// + /// - Returns: An overflow indicator and its index in `base`. + /// + @inlinable public mutating func increment( + by bit: inout Bool, at index: inout Base.Index) { + while bit && index < self.base.endIndex { + bit = self.base[index].addReportingOverflow(1 as Base.Element.Digit) + self.base.formIndex(after: &index) + } + } +} + +//=----------------------------------------------------------------------------= +// MARK: + Digit +//=----------------------------------------------------------------------------= + +extension NBKStrictUnsignedInteger where Base: MutableCollection { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + /// Increments `base` by `digit` at `index`. + /// + /// - Returns: An overflow indicator and its index in `base`. + /// + @discardableResult @inlinable public mutating func increment( + by digit: Base.Element, at index: Base.Index) -> NBK.IO { + var index: Base.Index = index, bit: Bool + //=--------------------------------------= + bit = self.increment(by: digit, at: &index) + //=--------------------------------------= + return NBK.IO(index as Base.Index, overflow: bit as Bool) + } + + /// Partially increments `base` by `digit` at `index`. + /// + /// - This operation does not continue beyond the operand intersection. + /// + /// - Returns: An overflow indicator and its index in `base`. + /// + @discardableResult @inlinable public mutating func incrementInIntersection( + by digit: Base.Element, at index: Base.Index) -> NBK.IO { + var index: Base.Index = index, bit: Bool + //=--------------------------------------= + bit = self.incrementInIntersection(by: digit, at: &index) + //=--------------------------------------= + return NBK.IO(index as Base.Index, overflow: bit as Bool) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Inout + //=------------------------------------------------------------------------= + + /// Increments `base` by `digit` at `index`. + /// + /// - Returns: An overflow indicator and its index in `base`. + /// + @inlinable public mutating func increment( + by digit: Base.Element, at index: inout Base.Index) -> Bool { + var bit = self.incrementInIntersection(by: digit, at: &index) + self.increment(by: &bit, at: &index); return bit as Bool + } + + /// Partially increments `base` by `digit` at `index`. + /// + /// - This operation does not continue beyond the operand intersection. + /// + /// - Returns: An overflow indicator and its index in `base`. + /// + @inlinable public mutating func incrementInIntersection( + by digit: Base.Element, at index: inout Base.Index) -> Bool { + defer{ self.base.formIndex(after: &index) } + return self.base[index].addReportingOverflow(digit) + } +} + +//=----------------------------------------------------------------------------= +// MARK: + Digit + Bit +//=----------------------------------------------------------------------------= + +extension NBKStrictUnsignedInteger where Base: MutableCollection { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + /// Increments `base` by the sum of `digit` and `bit` at `index`. + /// + /// - Returns: An overflow indicator and its index in `base`. + /// + @discardableResult @inlinable public mutating func increment( + by digit: Base.Element, plus bit: Bool, at index: Base.Index) -> NBK.IO { + var index: Base.Index = index, bit: Bool = bit + //=--------------------------------------= + self.increment(by: digit, plus: &bit, at: &index) + //=--------------------------------------= + return NBK.IO(index: index as Base.Index, overflow: bit as Bool) + } + + /// Partially increments `base` by the sum of `digit` and `bit` at `index`. + /// + /// - This operation does not continue beyond the operand intersection. + /// + /// - Returns: An overflow indicator and its index in `base`. + /// + @discardableResult @inlinable public mutating func incrementInIntersection( + by digit: Base.Element, plus bit: Bool, at index: Base.Index) -> NBK.IO { + var index: Base.Index = index, bit: Bool = bit, digit: Base.Element = digit + //=--------------------------------------= + self.incrementInIntersection(by: digit, plus: &bit, at: &index) + //=--------------------------------------= + return NBK.IO(index: index as Base.Index, overflow: bit as Bool) + } + + //=------------------------------------------------------------------------= + // MARK: Transformationsx x Inout + //=------------------------------------------------------------------------= + + /// Partially increments `base` by the sum of `digit` and `bit` at `index`. + /// + /// - This operation does not continue beyond the operand intersection. + /// + /// - Returns: An overflow indicator and its index in `base`. + /// + @inlinable public mutating func increment( + by digit: Base.Element, plus bit: inout Bool, at index: inout Base.Index) { + self.incrementInIntersection(by: digit, plus: &bit, at: &index) + self.increment(by: &bit, at: &index) + } + + /// Partially increments `base` by the sum of `digit` and `bit` at `index`. + /// + /// - This operation does not continue beyond the operand intersection. + /// + /// - Returns: An overflow indicator and its index in `base`. + /// + @inlinable public mutating func incrementInIntersection( + by digit: Base.Element, plus bit: inout Bool, at index: inout Base.Index) { + var digit: Base.Element = digit + //=--------------------------------------= + if bit { + bit = digit.addReportingOverflow(1 as Base.Element.Digit) + } + + if !bit { + bit = self.base[index].addReportingOverflow(digit) + } + //=--------------------------------------= + self.base.formIndex(after: &index) + } +} + +//=----------------------------------------------------------------------------= +// MARK: + Elements + Bit +//=----------------------------------------------------------------------------= + +extension NBKStrictUnsignedInteger where Base: MutableCollection { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + /// Increments `base` by the sum of `elements` and `bit` at `index`. + /// + /// - Returns: An overflow indicator and its index in `base`. + /// + @discardableResult @inlinable public mutating func increment( + by elements: some Collection, plus bit: Bool, at index: Base.Index) -> NBK.IO { + var index: Base.Index = index, bit: Bool = bit + //=--------------------------------------= + self.increment(by: elements, plus: &bit, at: &index) + //=--------------------------------------= + return NBK.IO(index: index as Base.Index, overflow: bit as Bool) + } + + /// Partially increments `base` by the sum of `elements` and `bit` at `index`. + /// + /// - This operation does not continue beyond the operand intersection. + /// + /// - Returns: An overflow indicator and its index in `base`. + /// + @discardableResult @inlinable public mutating func incrementInIntersection( + by elements: some Collection, plus bit: Bool, at index: Base.Index) -> NBK.IO { + var index: Base.Index = index, bit: Bool = bit + //=--------------------------------------= + self.incrementInIntersection(by: elements, plus: &bit, at: &index) + //=--------------------------------------= + return NBK.IO(index: index as Base.Index, overflow: bit as Bool) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Inout + //=------------------------------------------------------------------------= + + /// Increments `base` by the sum of `elements` and `bit` at `index`. + /// + /// - Returns: An overflow indicator and its index in `base`. + /// + @inlinable public mutating func increment( + by elements: some Collection, plus bit: inout Bool, at index: inout Base.Index) { + self.incrementInIntersection(by: elements, plus: &bit, at: &index) + self.increment(by: &bit, at: &index) + } + + /// Partially increments `base` by the sum of `elements` and `bit` at `index`. + /// + /// - This operation does not continue beyond the operand intersection. + /// + /// - Returns: An overflow indicator and its index in `base`. + /// + @inlinable public mutating func incrementInIntersection( + by elements: some Collection, plus bit: inout Bool, at index: inout Base.Index) { + for elementIndex in elements.indices { + self.incrementInIntersection(by: elements[elementIndex], plus: &bit, at: &index) + } + } +} diff --git a/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Complements.swift b/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Complements.swift new file mode 100644 index 00000000..b0c65d23 --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Complements.swift @@ -0,0 +1,49 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Strict Unsigned Integer x Complements +//*============================================================================* + +extension NBKStrictUnsignedInteger where Base: MutableCollection { + + //=------------------------------------------------------------------------= + // MARK: Transformations x One's Complement + //=------------------------------------------------------------------------= + + @inlinable mutating func formOnesComplement() { + for index in self.base.indices { + self.base[index].formOnesComplement() + } + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Two's Complement + //=------------------------------------------------------------------------= + + @inlinable mutating func formTwosComplement() { + _ = self.formTwosComplementSubsequence(true) + } + + @inlinable mutating func formTwosComplementReportingOverflow() -> Bool { + self.formTwosComplementSubsequence(true) + } + + @inlinable mutating func formTwosComplementSubsequence(_ carry: Bool) -> Bool { + var carry = carry + + for index in self.base.indices { + carry = self.base[index].formTwosComplementSubsequence(carry) + } + + return carry as Bool + } +} diff --git a/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Multiplication.swift b/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Multiplication.swift new file mode 100644 index 00000000..a58241a6 --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Multiplication.swift @@ -0,0 +1,49 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Strict Unsigned Integer x Multiplication +//*============================================================================* +// MARK: + Digit +//=----------------------------------------------------------------------------= + +extension NBKStrictUnsignedInteger where Base: MutableCollection { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + /// Forms the low product of multiplying `base` and `multiplicand` then adding `addend`. + /// + /// - Returns: An overflow indicator. + /// + @inlinable public mutating func multiply( + by multiplicand: Base.Element, add addend: Base.Element) -> Bool { + !self.multiplyFullWidth(by: multiplicand, add: addend).isZero + } + + /// Forms the low product of multiplying `base` and `multiplicand` then adding `addend`. + /// + /// - Returns: The high product. + /// + @inlinable public mutating func multiplyFullWidth( + by multiplicand: Base.Element, add addend: Base.Element) -> Base.Element { + var carry: Base.Element = addend + + for index in self.base.indices { + var subproduct = self.base[index].multipliedFullWidth(by: multiplicand) + subproduct.high &+= Base.Element(bit: subproduct.low.addReportingOverflow(carry)) + (carry, self.base[index]) = subproduct as HL + } + + return carry as Base.Element + } +} diff --git a/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Subtraction.swift b/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Subtraction.swift new file mode 100644 index 00000000..18099c31 --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Subtraction.swift @@ -0,0 +1,310 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= +// TODO: See whether consuming arguments removes the need for inout in Swift 5.9 +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Strict Unsigned Integer x Subtraction +//*============================================================================* +// MARK: + Bit +//=----------------------------------------------------------------------------= + +extension NBKStrictUnsignedInteger where Base: MutableCollection { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + /// Decrements `base` by `bit` at `index`. + /// + /// - Returns: An overflow indicator and its index in `base`. + /// + @discardableResult @inlinable public mutating func decrement( + by bit: Bool, at index: Base.Index) -> NBK.IO { + var index: Base.Index = index, bit: Bool = bit + //=--------------------------------------= + self.decrement(by: &bit, at: &index) + //=--------------------------------------= + return NBK.IO(index: index as Base.Index, overflow: bit as Bool) + } + + //=------------------------------------------------------------------------= + // MARK: Transformationsx x Inout + //=------------------------------------------------------------------------= + + /// Decrements `base` by `bit` at `index`. + /// + /// - Returns: An overflow indicator and its index in `base`. + /// + @inlinable public mutating func decrement( + by bit: inout Bool, at index: inout Base.Index) { + while bit && index < self.base.endIndex { + bit = self.base[index].subtractReportingOverflow(1 as Base.Element.Digit) + self.base.formIndex(after: &index) + } + } +} + +//=----------------------------------------------------------------------------= +// MARK: + Digit +//=----------------------------------------------------------------------------= + +extension NBKStrictUnsignedInteger where Base: MutableCollection { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + /// Decrements `base` by `digit` at `index`. + /// + /// - Returns: An overflow indicator and its index in `base`. + /// + @discardableResult @inlinable public mutating func decrement( + by digit: Base.Element, at index: Base.Index) -> NBK.IO { + var index: Base.Index = index, bit: Bool + //=--------------------------------------= + bit = self.decrement(by: digit, at: &index) + //=--------------------------------------= + return NBK.IO(index as Base.Index, overflow: bit as Bool) + } + + /// Partially decrements `base` by `digit` at `index`. + /// + /// - This operation does not continue beyond the operand intersection. + /// + /// - Returns: An overflow indicator and its index in `base`. + /// + @discardableResult @inlinable public mutating func decrementInIntersection( + by digit: Base.Element, at index: Base.Index) -> NBK.IO { + var index: Base.Index = index, bit: Bool + //=--------------------------------------= + bit = self.decrementInIntersection(by: digit, at: &index) + //=--------------------------------------= + return NBK.IO(index as Base.Index, overflow: bit as Bool) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Inout + //=------------------------------------------------------------------------= + + /// Decrements `base` by `digit` at `index`. + /// + /// - Returns: An overflow indicator and its index in `base`. + /// + @inlinable public mutating func decrement( + by digit: Base.Element, at index: inout Base.Index) -> Bool { + var bit = self.decrementInIntersection(by: digit, at: &index) + self.decrement(by: &bit, at: &index); return bit as Bool + } + + /// Partially decrements `base` by `digit` at `index`. + /// + /// - This operation does not continue beyond the operand intersection. + /// + /// - Returns: An overflow indicator and its index in `base`. + /// + @inlinable public mutating func decrementInIntersection( + by digit: Base.Element, at index: inout Base.Index) -> Bool { + defer{ self.base.formIndex(after: &index) } + return self.base[index].subtractReportingOverflow(digit) + } +} + +//=----------------------------------------------------------------------------= +// MARK: + Digit + Bit +//=----------------------------------------------------------------------------= + +extension NBKStrictUnsignedInteger where Base: MutableCollection { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + /// Decrements `base` by the sum of `digit` and `bit` at `index`. + /// + /// - Returns: An overflow indicator and its index in `base`. + /// + @discardableResult @inlinable public mutating func decrement( + by digit: Base.Element, plus bit: Bool, at index: Base.Index) -> NBK.IO { + var index: Base.Index = index, bit: Bool = bit + //=--------------------------------------= + self.decrement(by: digit, plus: &bit, at: &index) + //=--------------------------------------= + return NBK.IO(index: index as Base.Index, overflow: bit as Bool) + } + + /// Partially decrements `base` by the sum of `digit` and `bit` at `index`. + /// + /// - This operation does not continue beyond the operand intersection. + /// + /// - Returns: An overflow indicator and its index in `base`. + /// + @discardableResult @inlinable public mutating func decrementInIntersection( + by digit: Base.Element, plus bit: Bool, at index: Base.Index) -> NBK.IO { + var index: Base.Index = index, bit: Bool = bit, digit: Base.Element = digit + //=--------------------------------------= + self.decrementInIntersection(by: digit, plus: &bit, at: &index) + //=--------------------------------------= + return NBK.IO(index: index as Base.Index, overflow: bit as Bool) + } + + //=------------------------------------------------------------------------= + // MARK: Transformationsx x Inout + //=------------------------------------------------------------------------= + + /// Partially decrements `base` by the sum of `digit` and `bit` at `index`. + /// + /// - This operation does not continue beyond the operand intersection. + /// + /// - Returns: An overflow indicator and its index in `base`. + /// + @inlinable public mutating func decrement( + by digit: Base.Element, plus bit: inout Bool, at index: inout Base.Index) { + self.decrementInIntersection(by: digit, plus: &bit, at: &index) + self.decrement(by: &bit, at: &index) + } + + /// Partially decrements `base` by the sum of `digit` and `bit` at `index`. + /// + /// - This operation does not continue beyond the operand intersection. + /// + /// - Returns: An overflow indicator and its index in `base`. + /// + @inlinable public mutating func decrementInIntersection( + by digit: Base.Element, plus bit: inout Bool, at index: inout Base.Index) { + var digit: Base.Element = digit + //=--------------------------------------= + if bit { + bit = digit.addReportingOverflow(1 as Base.Element.Digit) + } + + if !bit { + bit = self.base[index].subtractReportingOverflow(digit) + } + //=--------------------------------------= + self.base.formIndex(after: &index) + } +} + +//=----------------------------------------------------------------------------= +// MARK: + Elements + Bit +//=----------------------------------------------------------------------------= + +extension NBKStrictUnsignedInteger where Base: MutableCollection { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + /// Decrements `base` by the sum of `elements` and `bit` at `index`. + /// + /// - Returns: An overflow indicator and its index in `base`. + /// + @discardableResult @inlinable public mutating func decrement( + by elements: some Collection, plus bit: Bool, at index: Base.Index) -> NBK.IO { + var index: Base.Index = index, bit: Bool = bit + //=--------------------------------------= + self.decrement(by: elements, plus: &bit, at: &index) + //=--------------------------------------= + return NBK.IO(index: index as Base.Index, overflow: bit as Bool) + } + + /// Partially decrements `base` by the sum of `elements` and `bit` at `index`. + /// + /// - This operation does not continue beyond the operand intersection. + /// + /// - Returns: An overflow indicator and its index in `base`. + /// + @discardableResult @inlinable public mutating func decrementInIntersection( + by elements: some Collection, plus bit: Bool, at index: Base.Index) -> NBK.IO { + var index: Base.Index = index, bit: Bool = bit + //=--------------------------------------= + self.decrementInIntersection(by: elements, plus: &bit, at: &index) + //=--------------------------------------= + return NBK.IO(index: index as Base.Index, overflow: bit as Bool) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Inout + //=------------------------------------------------------------------------= + + /// Decrements `base` by the sum of `elements` and `bit` at `index`. + /// + /// - Returns: An overflow indicator and its index in `base`. + /// + @inlinable public mutating func decrement( + by elements: some Collection, plus bit: inout Bool, at index: inout Base.Index) { + self.decrementInIntersection(by: elements, plus: &bit, at: &index) + self.decrement(by: &bit, at: &index) + } + + /// Partially decrements `base` by the sum of `elements` and `bit` at `index`. + /// + /// - This operation does not continue beyond the operand intersection. + /// + /// - Returns: An overflow indicator and its index in `base`. + /// + @inlinable public mutating func decrementInIntersection( + by elements: some Collection, plus bit: inout Bool, at index: inout Base.Index) { + for elementIndex in elements.indices { + self.decrementInIntersection(by: elements[elementIndex], plus: &bit, at: &index) + } + } +} + +//=----------------------------------------------------------------------------= +// MARK: + Elements × Digit + Digit + Bit +//=----------------------------------------------------------------------------= + +extension NBKStrictUnsignedInteger where Base: MutableCollection { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + /// Decrements `base` by the product of `elements` and `multiplicand` at `index`, + /// and the sum of `subtrahend` and `bit` at `index`. + /// + /// - Returns: An overflow indicator and its index in `base`. + /// + @discardableResult @inlinable public mutating func decrement( + by elements: some Collection, times multiplicand: Base.Element, plus subtrahend: Base.Element, + plus bit: Bool, at index: Base.Index) -> NBK.IO { + var index: Base.Index = index, bit: Bool = bit + //=--------------------------------------= + self.decrement(by: elements, times: multiplicand, plus: subtrahend, plus: &bit, at: &index) + //=--------------------------------------= + return NBK.IO(index: index as Base.Index, overflow: bit as Bool) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Inout + //=------------------------------------------------------------------------= + + /// Decrements `base` by the product of `elements` and `multiplicand` at `index`, + /// and the sum of `subtrahend` and `bit` at `index`. + /// + /// - Returns: An overflow indicator and its index in `base`. + /// + @inlinable public mutating func decrement( + by elements: some Collection, times multiplicand: Base.Element, plus subtrahend: Base.Element, + plus bit: inout Bool, at index: inout Base.Index) { + var last: Base.Element = subtrahend + + for limbsIndex in elements.indices { + var subproduct = elements[limbsIndex].multipliedFullWidth(by: multiplicand) + last = Base.Element(bit: subproduct.low.addReportingOverflow(last)) &+ subproduct.high + self.decrementInIntersection(by: subproduct.low, plus: &bit, at: &index) + } + + self.decrement(by: last, plus: &bit, at: &index) + } +} diff --git a/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger.swift b/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger.swift new file mode 100644 index 00000000..da6c4b05 --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger.swift @@ -0,0 +1,92 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Strict Unsigned Integer +//*============================================================================* + +@frozen public struct NBKStrictUnsignedInteger where +Base.Element: NBKCoreInteger & NBKUnsignedInteger { + + //=------------------------------------------------------------------------= + // MARK: State + //=------------------------------------------------------------------------= + + @usableFromInline var base: Base + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + @inlinable public init(_ base: Base) { + self.base = base + precondition(Self.validate(self.base)) + } + + @inlinable public init(unchecked base: Base) { + self.base = base + Swift.assert(Self.validate(self.base)) + } + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + @inlinable public static func validate(_ base: Base) -> Bool { + !base.isEmpty + } +} + +//=----------------------------------------------------------------------------= +// MARK: + Collection +//=----------------------------------------------------------------------------= + +extension NBKStrictUnsignedInteger { + + //=------------------------------------------------------------------------= + // MARK: Accessors + //=------------------------------------------------------------------------= + + @inlinable var first: Base.Element { + self.base[self.base.startIndex] + } + + @inlinable var last: Base.Element { + self.base[self.lastIndex] + } + + @inlinable var lastIndex: Base.Index { + self.base.index(before: self.base.endIndex) + } +} + +//=----------------------------------------------------------------------------= +// MARK: + Collection x Mutable +//=----------------------------------------------------------------------------= + +extension NBKStrictUnsignedInteger where Base: MutableCollection { + + //=------------------------------------------------------------------------= + // MARK: Accessors + //=------------------------------------------------------------------------= + + @inlinable var first: Base.Element { + @available(*, unavailable) + get { self.base[self.base.startIndex] } + set { self.base[self.base.startIndex] = newValue } + } + + @inlinable var last: Base.Element { + @available(*, unavailable) + get { self.base[self.lastIndex] } + set { self.base[self.lastIndex] = newValue } + } +} From f1e05625f21e731492c96b191a3d69e043aabd87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sun, 17 Sep 2023 12:27:29 +0200 Subject: [PATCH 078/133] [NBKFlexibleWidthKit] Cleanup. --- .../NBKFlexibleWidth+Division+Digit.swift | 10 ++- .../NBKStrictUnsignedInteger+Division.swift | 65 +++++++++++++++++++ ...StrictUnsignedInteger+Multiplication.swift | 2 +- .../Private/NBKStrictUnsignedInteger.swift | 12 ++-- 4 files changed, 75 insertions(+), 14 deletions(-) create mode 100644 Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Division.swift diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.swift index fc0cac04..fc431c28 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.swift @@ -47,12 +47,10 @@ extension NBKFlexibleWidth.Magnitude { return PVO(QR(quotient, remainder.partialValue), remainder.overflow) } - //=------------------------------------------------------------------------= - // MARK: Transformations x Private - //=------------------------------------------------------------------------= - + // TODO: perhaps NBKUnsignedInteger should be require this method @_disfavoredOverload @inlinable public mutating func formQuotientWithRemainderReportingOverflow(dividingBy other: Digit) -> PVO { - defer{ self.storage.normalize() } - return NBK.formQuotientWithRemainderReportingOverflowAsLenientUnsignedInteger(of: &self.storage.elements, dividingBy: other) + self.withUnsafeMutableStrictUnsignedInteger { + $0.formQuotientWithRemainderReportingOverflow(dividingBy: other) + } } } diff --git a/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Division.swift b/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Division.swift new file mode 100644 index 00000000..71bef3b6 --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Division.swift @@ -0,0 +1,65 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Strict Unsigned Integer x Division +//*============================================================================* +// MARK: + Digit +//=----------------------------------------------------------------------------= + +extension NBKStrictUnsignedInteger where Base: BidirectionalCollection & MutableCollection { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + /// Returns the `remainder` of dividing the `base` by the `divisor`, + /// along with an `overflow` indicator. + /// + /// - Note: In the case of `overflow`, the result is `base.first`. + /// + @inlinable public mutating func remainderReportingOverflow( + dividingBy divisor: Base.Element) -> PVO { + //=--------------------------------------= + if divisor.isZero { + return PVO(partialValue: self.first, overflow: true) + } + //=--------------------------------------= + var remainder = 0 as Base.Element + + for index in self.base.indices.reversed() { + remainder = divisor.dividingFullWidth(HL(high: remainder, low: self.base[index])).remainder + } + + return PVO(partialValue: remainder, overflow: false) + } + + /// Forms the `quotient` of dividing the `base` by the `divisor`, + /// and returns the `remainder` along with an `overflow` indicator. + /// + /// - Note: In the case of `overflow`, the result is `base` and `base.first`. + /// + @inlinable public mutating func formQuotientWithRemainderReportingOverflow( + dividingBy divisor: Base.Element) -> PVO { + //=--------------------------------------= + if divisor.isZero { + return PVO(partialValue: self.first, overflow: true) + } + //=--------------------------------------= + var remainder = 0 as Base.Element + + for index in self.base.indices.reversed() { + (self.base[index], remainder) = divisor.dividingFullWidth(HL(high: remainder, low: self.base[index])) + } + + return PVO(partialValue: remainder, overflow: false) + } +} diff --git a/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Multiplication.swift b/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Multiplication.swift index a58241a6..b1fc73fc 100644 --- a/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Multiplication.swift +++ b/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Multiplication.swift @@ -25,7 +25,7 @@ extension NBKStrictUnsignedInteger where Base: MutableCollection { /// /// - Returns: An overflow indicator. /// - @inlinable public mutating func multiply( + @inlinable public mutating func multiplyReportingOverflow( by multiplicand: Base.Element, add addend: Base.Element) -> Bool { !self.multiplyFullWidth(by: multiplicand, add: addend).isZero } diff --git a/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger.swift b/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger.swift index da6c4b05..b264e664 100644 --- a/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger.swift +++ b/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger.swift @@ -55,15 +55,15 @@ extension NBKStrictUnsignedInteger { // MARK: Accessors //=------------------------------------------------------------------------= - @inlinable var first: Base.Element { + @inlinable public var first: Base.Element { self.base[self.base.startIndex] } - @inlinable var last: Base.Element { + @inlinable public var last: Base.Element { self.base[self.lastIndex] } - @inlinable var lastIndex: Base.Index { + @inlinable public var lastIndex: Base.Index { self.base.index(before: self.base.endIndex) } } @@ -78,14 +78,12 @@ extension NBKStrictUnsignedInteger where Base: MutableCollection { // MARK: Accessors //=------------------------------------------------------------------------= - @inlinable var first: Base.Element { - @available(*, unavailable) + @inlinable public var first: Base.Element { get { self.base[self.base.startIndex] } set { self.base[self.base.startIndex] = newValue } } - @inlinable var last: Base.Element { - @available(*, unavailable) + @inlinable public var last: Base.Element { get { self.base[self.lastIndex] } set { self.base[self.lastIndex] = newValue } } From 96eee06e799095c29670f06a9493cb6ef73005f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sun, 17 Sep 2023 17:09:27 +0200 Subject: [PATCH 079/133] [NBKFlexibleWidthKit] Shifts. Stuff. --- .../NBKFlexibleWidth+Division.swift | 74 ++++---- .../NBKFlexibleWidth+Shifts.swift | 175 ++---------------- .../NBKFlexibleWidth+Words+Pointers.swift | 4 +- .../NBKStrictUnsignedInteger+Addition.swift | 4 +- .../NBKStrictUnsignedInteger+Shifts.swift | 158 ++++++++++++++++ ...NBKStrictUnsignedInteger+Subtraction.swift | 12 +- 6 files changed, 222 insertions(+), 205 deletions(-) create mode 100644 Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Shifts.swift diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift index 887551ef..bd4ac1e9 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift @@ -92,52 +92,56 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= // shift to clamp approximation //=--------------------------------------= - let shift = other.last.leadingZeroBitCount as Int - var divisor = other.storage as Storage - divisor.bitshiftLeft(words: 0 as Int, bits: shift) - let divisorLast0 = divisor.elements[divisor.elements.endIndex - 1] as UInt - assert(divisorLast0.mostSignificantBit) + var divisor: Storage = other.storage + let divisorLastIndex = divisor.elements.endIndex - 1 as Int + let shift = divisor.elements[divisorLastIndex].leadingZeroBitCount as Int + + var remainderIndex = self.storage.elements.endIndex as Int + self.storage.append(0 as UInt) + + if !shift.isZero { + divisor/*-*/.withUnsafeMutableStrictUnsignedInteger({ $0.bitshiftLeft(major: 0 as Int, minor: shift) }) + self.storage.withUnsafeMutableStrictUnsignedInteger({ $0.bitshiftLeft(major: 0 as Int, minor: shift) }) + } - var remainderIndex = self.storage.elements.endIndex - self.storage.append(0) - self.storage.bitshiftLeft(words: 0 as Int, bits: shift) + let divisorLast0 = divisor.elements[divisorLastIndex] as UInt + assert(divisorLast0.mostSignificantBit) //=--------------------------------------= // division: approximate quotient digits //=--------------------------------------= var quotientIndex = remainderIndex - divisor.elements.endIndex as Int - var quotient = Storage.uninitialized(count: quotientIndex + 1) { quotient in - loop: repeat { - let remainderLast0 = self.storage.elements[remainderIndex] - self.storage.elements.formIndex(before: &remainderIndex) - let remainderLast1 = self.storage.elements[remainderIndex] - //=------------------------------= - var digit: UInt - if divisorLast0 == remainderLast0 { - digit = UInt.max - } else { - digit = divisorLast0.dividingFullWidth(HL(remainderLast0, remainderLast1)).quotient - } - //=------------------------------= - if !digit.isZero { - self.storage.withUnsafeMutableStrictUnsignedInteger { - var overflow = $0.decrement(by: divisor.elements, times: digit, plus: 0 as UInt, plus: false, at: quotientIndex).overflow - decrement: while overflow { - digit &-= 1 as Digit - overflow = !$0.increment(by: divisor.elements, plus: false, at: quotientIndex).overflow + let quotient = Self.uninitialized(count: quotientIndex &+ 1) { quotient in + self.storage.withUnsafeMutableStrictUnsignedInteger { storage in + loop: repeat { + let remainderLast0 = storage.base[remainderIndex] + storage.base.formIndex(before: &remainderIndex) + let remainderLast1 = storage.base[remainderIndex] + //=------------------------------= + var digit: UInt + if divisorLast0 == remainderLast0 { + digit = UInt.max + } else { + digit = divisorLast0.dividingFullWidth(HL(remainderLast0, remainderLast1)).quotient + } + //=------------------------------= + if !digit.isZero { + var overflow = (storage).decrement(by: divisor.elements, times: digit, at: quotientIndex).overflow + while overflow { + overflow = !storage .increment(by: divisor.elements, at: quotientIndex).overflow; digit &-= 01 } } - } - //=------------------------------= - quotient[quotientIndex] = digit - quotient.formIndex(before: "ientIndex) - } while quotientIndex >= quotient.startIndex + //=------------------------------= + quotient[quotientIndex] = digit + quotient.formIndex(before: "ientIndex) + } while quotientIndex >= quotient.startIndex + } } //=--------------------------------------= // undo shift before division //=--------------------------------------= - quotient.normalize() - self.storage.bitshiftRight(words: 0 as Int, bits: shift) + self.storage.withUnsafeMutableStrictUnsignedInteger({ $0.bitshiftRight(major: 0 as Int, minor: shift) }) self.storage.normalize() - return PVO(Self(unchecked: quotient), false) + //=--------------------------------------= + return PVO(partialValue: quotient, overflow: false) } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift index af0454c8..27087d9c 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift @@ -100,7 +100,10 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= let rollover = Int(bit: self.leadingZeroBitCount < bits) self.storage.resize(minCount: self.storage.elements.count + words + rollover) - self.storage.bitshiftLeft(words: words, atLeastOneBit: bits) + + self.storage.withUnsafeMutableStrictUnsignedInteger { + $0.bitshiftLeft(major: words, minorAtLeastOne: bits) + } } /// Performs a left shift. @@ -116,7 +119,10 @@ extension NBKFlexibleWidth.Magnitude { if self.isZero { return } //=--------------------------------------= self.storage.resize(minCount: self.storage.elements.count + words) - self.storage.bitshiftLeft(atLeastOneWord: words) + + self.storage.withUnsafeMutableStrictUnsignedInteger { + $0.bitshiftLeft(majorAtLeastOne: words) + } } } @@ -211,7 +217,10 @@ extension NBKFlexibleWidth.Magnitude { return self.updateZeroValue() } //=--------------------------------------= - self.storage.bitshiftRight(words: words, atLeastOneBit: bits) + self.storage.withUnsafeMutableStrictUnsignedInteger { + $0.bitshiftRight(major: words, minorAtLeastOne: bits) + } + self.storage.resize(maxCount: maxCount) } @@ -229,164 +238,10 @@ extension NBKFlexibleWidth.Magnitude { return self.updateZeroValue() } //=--------------------------------------= - self.storage.bitshiftRight(atLeastOneWord: words) - self.storage.resize(maxCount: self.storage.elements.count - words) - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Shifts x Unsigned x Storage -//*============================================================================* -//=----------------------------------------------------------------------------= -// MARK: + Left -//=----------------------------------------------------------------------------= - -extension NBKFlexibleWidth.Magnitude.Storage { - - //=------------------------------------------------------------------------= - // MARK: Transformations x Int - //=------------------------------------------------------------------------= - - /// Performs a left shift. - /// - /// - Parameters: - /// - distance: `0 <= distance < self.bitWidth` - /// - @inlinable mutating func bitshiftLeft(by distance: Int) { - precondition(distance >= 0, NBK.callsiteOutOfBoundsInfo()) - let major = NBK .quotientDividingByBitWidthAssumingIsAtLeastZero(distance) - let minor = NBK.remainderDividingByBitWidthAssumingIsAtLeastZero(distance) - return self.bitshiftLeft(words: major, bits: minor) - } - - /// Performs a left shift. - /// - /// - Parameters: - /// - words: `0 <= words < self.endIndex` - /// - bits: `0 <= bits  < UInt.bitWidth` - /// - @inlinable mutating func bitshiftLeft(words: Int, bits: Int) { - //=--------------------------------------= - if bits.isZero { - return self.bitshiftLeft(words: words) - } - //=--------------------------------------= - self.bitshiftLeft(words: words, atLeastOneBit: bits) - } - - /// Performs a left shift. - /// - /// - Parameters: - /// - words: `0 <= words < self.endIndex` - /// - @inlinable mutating func bitshiftLeft(words: Int) { - //=--------------------------------------= - if words.isZero { return } - //=--------------------------------------= - self.bitshiftLeft(atLeastOneWord: words) - } - - //=------------------------------------------------------------------------= - // MARK: Transformations x Int x Private - //=------------------------------------------------------------------------= - - /// Performs a left shift. - /// - /// - Parameters: - /// - words: `0 <= words < self.endIndex` - /// - bits: `1 <= bits  < UInt.bitWidth` - /// - @inlinable mutating func bitshiftLeft(words: Int, atLeastOneBit bits: Int) { - self.withUnsafeMutableBufferPointer { - NBK.bitshiftLeftAsFixedLimbsCodeBlock(&$0, environment: false, limbs: words, atLeastOneBit: bits) - } - } - - /// Performs a left shift. - /// - /// - Parameters: - /// - words: `1 <= words < self.endIndex` - /// - @inlinable mutating func bitshiftLeft(atLeastOneWord words: Int) { - self.withUnsafeMutableBufferPointer { - NBK.bitshiftLeftAsFixedLimbsCodeBlock(&$0, environment: false, atLeastOneLimb: words) - } - } -} - -//=----------------------------------------------------------------------------= -// MARK: + Right -//=----------------------------------------------------------------------------= - -extension NBKFlexibleWidth.Magnitude.Storage { - - //=------------------------------------------------------------------------= - // MARK: Transformations x Int - //=------------------------------------------------------------------------= - - /// Performs an un/signed right shift. - /// - /// - Parameters: - /// - distance: `0 <= distance < self.bitWidth` - /// - @inlinable mutating func bitshiftRight(by distance: Int) { - precondition(distance >= 0, NBK.callsiteOutOfBoundsInfo()) - let major = NBK .quotientDividingByBitWidthAssumingIsAtLeastZero(distance) - let minor = NBK.remainderDividingByBitWidthAssumingIsAtLeastZero(distance) - return self.bitshiftRight(words: major, bits: minor) - } - - /// Performs an un/signed right shift. - /// - /// - Parameters: - /// - words: `0 <= words < self.endIndex` - /// - bits: `0 <= bits  < UInt.bitWidth` - /// - @inlinable mutating func bitshiftRight(words: Int, bits: Int) { - //=--------------------------------------= - if bits.isZero { - return self.bitshiftRight(words: words) + self.storage.withUnsafeMutableStrictUnsignedInteger { + $0.bitshiftRight(majorAtLeastOne: words) } - //=--------------------------------------= - self.bitshiftRight(words: words, atLeastOneBit: bits) - } - /// Performs an un/signed right shift. - /// - /// - Parameters: - /// - words: `0 <= words < self.endIndex` - /// - @inlinable mutating func bitshiftRight(words: Int) { - //=--------------------------------------= - if words.isZero { return } - //=--------------------------------------= - self.bitshiftRight(atLeastOneWord: words) - } - - //=------------------------------------------------------------------------= - // MARK: Transformations x Int x Private - //=------------------------------------------------------------------------= - - /// Performs an un/signed right shift. - /// - /// - Parameters: - /// - words: `1 <= words < self.endIndex` - /// - bits: `0 <= bits  < UInt.bitWidth` - /// - @inlinable mutating func bitshiftRight(words: Int, atLeastOneBit bits: Int) { - self.withUnsafeMutableBufferPointer { - NBK.bitshiftRightAsFixedLimbsCodeBlock(&$0, environment: false, limbs: words, atLeastOneBit: bits) - } - } - - /// Performs an un/signed right shift. - /// - /// - Parameters: - /// - words: `1 <= words < self.endIndex` - /// - @inlinable mutating func bitshiftRight(atLeastOneWord words: Int) { - self.withUnsafeMutableBufferPointer { - NBK.bitshiftRightAsFixedLimbsCodeBlock(&$0, environment: false, atLeastOneLimb: words) - } + self.storage.resize(maxCount: self.storage.elements.count - words) } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words+Pointers.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words+Pointers.swift index e80ae420..a5ea5911 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words+Pointers.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words+Pointers.swift @@ -80,7 +80,7 @@ extension NBKFlexibleWidth.Magnitude.Storage { @inlinable func withUnsafeStrictUnsignedInteger( _ body:(NBKStrictUnsignedInteger) throws -> T) rethrows -> T { try self.withUnsafeBufferPointer { - let view = NBKStrictUnsignedInteger($0) + let view = NBKStrictUnsignedInteger(unchecked: $0) return try body(view) } } @@ -89,7 +89,7 @@ extension NBKFlexibleWidth.Magnitude.Storage { @inlinable mutating func withUnsafeMutableStrictUnsignedInteger( _ body:(inout NBKStrictUnsignedInteger) throws -> T) rethrows -> T { try self.withUnsafeMutableBufferPointer { - var view = NBKStrictUnsignedInteger($0) + var view = NBKStrictUnsignedInteger(unchecked: $0) return try body(&view) } } diff --git a/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Addition.swift b/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Addition.swift index 10e97d4c..96d645b9 100644 --- a/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Addition.swift +++ b/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Addition.swift @@ -209,7 +209,7 @@ extension NBKStrictUnsignedInteger where Base: MutableCollection { /// - Returns: An overflow indicator and its index in `base`. /// @discardableResult @inlinable public mutating func increment( - by elements: some Collection, plus bit: Bool, at index: Base.Index) -> NBK.IO { + by elements: some Collection, plus bit: Bool = false, at index: Base.Index) -> NBK.IO { var index: Base.Index = index, bit: Bool = bit //=--------------------------------------= self.increment(by: elements, plus: &bit, at: &index) @@ -224,7 +224,7 @@ extension NBKStrictUnsignedInteger where Base: MutableCollection { /// - Returns: An overflow indicator and its index in `base`. /// @discardableResult @inlinable public mutating func incrementInIntersection( - by elements: some Collection, plus bit: Bool, at index: Base.Index) -> NBK.IO { + by elements: some Collection, plus bit: Bool = false, at index: Base.Index) -> NBK.IO { var index: Base.Index = index, bit: Bool = bit //=--------------------------------------= self.incrementInIntersection(by: elements, plus: &bit, at: &index) diff --git a/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Shifts.swift b/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Shifts.swift new file mode 100644 index 00000000..9b8c25a4 --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Shifts.swift @@ -0,0 +1,158 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Strict Unsigned Integer x Shifts +//*============================================================================* +// MARK: + Left +//=----------------------------------------------------------------------------= + +extension NBKStrictUnsignedInteger where Base: MutableCollection, Base.Indices == Range { // TODO: remove range req. + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + /// Performs a left shift. + /// + /// - Parameters: + /// - distance: `0 <= distance < base.bitWidth` + /// + @inlinable public mutating func bitshiftLeft(by distance: Int) { + precondition(distance >= 0, NBK.callsiteOutOfBoundsInfo()) + let major = NBK .quotientDividingByBitWidthAssumingIsAtLeastZero(distance) + let minor = NBK.remainderDividingByBitWidthAssumingIsAtLeastZero(distance) + return self.bitshiftLeft(major: major, minor: minor) + } + + /// Performs a left shift. + /// + /// - Parameters: + /// - major: `0 <= major < base.endIndex` + /// - minor: `0 <= minor < Base.Element.bitWidth` + /// + @inlinable public mutating func bitshiftLeft(major: Int, minor: Int) { + //=--------------------------------------= + if minor.isZero { + return self.bitshiftLeft(major: major) + } + //=--------------------------------------= + self.bitshiftLeft(major: major, minorAtLeastOne: minor) + } + + /// Performs a left shift. + /// + /// - Parameters: + /// - major: `0 <= major < base.endIndex` + /// + @inlinable public mutating func bitshiftLeft(major: Int) { + //=--------------------------------------= + if major.isZero { return } + //=--------------------------------------= + self.bitshiftLeft(majorAtLeastOne: major) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Algorithms + //=------------------------------------------------------------------------= + + /// Performs a left shift. + /// + /// - Parameters: + /// - major: `0 <= major < base.endIndex` + /// - minor: `1 <= minor < Base.Element.bitWidth` + /// + @inlinable public mutating func bitshiftLeft(major: Int, minorAtLeastOne bits: Int) { + NBK.bitshiftLeftAsFixedLimbsCodeBlock(&self.base, environment: false, limbs: major, atLeastOneBit: bits) + } + + /// Performs a left shift. + /// + /// - Parameters: + /// - major: `1 <= major < base.endIndex` + /// + @inlinable public mutating func bitshiftLeft(majorAtLeastOne major: Int) { + NBK.bitshiftLeftAsFixedLimbsCodeBlock(&self.base, environment: false, atLeastOneLimb: major) + } +} + +//=----------------------------------------------------------------------------= +// MARK: + Right +//=----------------------------------------------------------------------------= + +extension NBKStrictUnsignedInteger where Base: MutableCollection, Base.Indices == Range { // TODO: remove range req. + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + /// Performs an unsigned right shift. + /// + /// - Parameters: + /// - distance: `0 <= distance < base.bitWidth` + /// + @inlinable public mutating func bitshiftRight(by distance: Int) { + precondition(distance >= 0, NBK.callsiteOutOfBoundsInfo()) + let major = NBK .quotientDividingByBitWidthAssumingIsAtLeastZero(distance) + let minor = NBK.remainderDividingByBitWidthAssumingIsAtLeastZero(distance) + return self.bitshiftRight(major: major, minor: minor) + } + + /// Performs an unsigned right shift. + /// + /// - Parameters: + /// - major: `0 <= major < base.endIndex` + /// - bits: `0 <= minor < Base.Element.bitWidth` + /// + @inlinable public mutating func bitshiftRight(major: Int, minor: Int) { + //=--------------------------------------= + if minor.isZero { + return self.bitshiftRight(major: major) + } + //=--------------------------------------= + self.bitshiftRight(major: major, minorAtLeastOne: minor) + } + + /// Performs an unsigned right shift. + /// + /// - Parameters: + /// - major: `0 <= major < base.endIndex` + /// + @inlinable public mutating func bitshiftRight(major: Int) { + //=--------------------------------------= + if major.isZero { return } + //=--------------------------------------= + self.bitshiftRight(majorAtLeastOne: major) + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Algorithms + //=------------------------------------------------------------------------= + + /// Performs an unsigned right shift. + /// + /// - Parameters: + /// - major: `1 <= major < base.endIndex` + /// - minor: `0 <= minor < Base.Element.bitWidth` + /// + @inlinable public mutating func bitshiftRight(major: Int, minorAtLeastOne bits: Int) { + NBK.bitshiftRightAsFixedLimbsCodeBlock(&self.base, environment: false, limbs: major, atLeastOneBit: bits) + } + + /// Performs an unsigned right shift. + /// + /// - Parameters: + /// - major: `1 <= major < base.endIndex` + /// + @inlinable public mutating func bitshiftRight(majorAtLeastOne major: Int) { + NBK.bitshiftRightAsFixedLimbsCodeBlock(&self.base, environment: false, atLeastOneLimb: major) + } +} diff --git a/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Subtraction.swift b/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Subtraction.swift index 18099c31..bafe69c2 100644 --- a/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Subtraction.swift +++ b/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Subtraction.swift @@ -209,7 +209,7 @@ extension NBKStrictUnsignedInteger where Base: MutableCollection { /// - Returns: An overflow indicator and its index in `base`. /// @discardableResult @inlinable public mutating func decrement( - by elements: some Collection, plus bit: Bool, at index: Base.Index) -> NBK.IO { + by elements: some Collection, plus bit: Bool = false, at index: Base.Index) -> NBK.IO { var index: Base.Index = index, bit: Bool = bit //=--------------------------------------= self.decrement(by: elements, plus: &bit, at: &index) @@ -224,7 +224,7 @@ extension NBKStrictUnsignedInteger where Base: MutableCollection { /// - Returns: An overflow indicator and its index in `base`. /// @discardableResult @inlinable public mutating func decrementInIntersection( - by elements: some Collection, plus bit: Bool, at index: Base.Index) -> NBK.IO { + by elements: some Collection, plus bit: Bool = false, at index: Base.Index) -> NBK.IO { var index: Base.Index = index, bit: Bool = bit //=--------------------------------------= self.decrementInIntersection(by: elements, plus: &bit, at: &index) @@ -276,8 +276,8 @@ extension NBKStrictUnsignedInteger where Base: MutableCollection { /// - Returns: An overflow indicator and its index in `base`. /// @discardableResult @inlinable public mutating func decrement( - by elements: some Collection, times multiplicand: Base.Element, plus subtrahend: Base.Element, - plus bit: Bool, at index: Base.Index) -> NBK.IO { + by elements: some Collection, times multiplicand: Base.Element, + plus subtrahend: Base.Element = 0, plus bit: Bool = false, at index: Base.Index) -> NBK.IO { var index: Base.Index = index, bit: Bool = bit //=--------------------------------------= self.decrement(by: elements, times: multiplicand, plus: subtrahend, plus: &bit, at: &index) @@ -295,8 +295,8 @@ extension NBKStrictUnsignedInteger where Base: MutableCollection { /// - Returns: An overflow indicator and its index in `base`. /// @inlinable public mutating func decrement( - by elements: some Collection, times multiplicand: Base.Element, plus subtrahend: Base.Element, - plus bit: inout Bool, at index: inout Base.Index) { + by elements: some Collection, times multiplicand: Base.Element, + plus subtrahend: Base.Element, plus bit: inout Bool, at index: inout Base.Index) { var last: Base.Element = subtrahend for limbsIndex in elements.indices { From 54546b7d944771a44af4caab1acb6477111f8eb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Mon, 18 Sep 2023 12:03:30 +0200 Subject: [PATCH 080/133] [NBKFlexibleWidthKit] Cleanup. --- .../NBKFlexibleWidthKit/IntXLOrUIntXL.swift | 26 +++++++++++++++++++ .../NBKFlexibleWidth+Addition.swift | 6 +++-- .../NBKFlexibleWidth+Division.swift | 19 +++++++------- .../NBKFlexibleWidth+Logic.swift | 2 -- .../NBKFlexibleWidth+Subtraction.swift | 2 +- .../NBKFlexibleWidth.swift | 22 ++-------------- .../NBKStrictUnsignedInteger+Shifts.swift | 4 +-- 7 files changed, 45 insertions(+), 36 deletions(-) diff --git a/Sources/NBKFlexibleWidthKit/IntXLOrUIntXL.swift b/Sources/NBKFlexibleWidthKit/IntXLOrUIntXL.swift index d595d76d..2d5606a2 100644 --- a/Sources/NBKFlexibleWidthKit/IntXLOrUIntXL.swift +++ b/Sources/NBKFlexibleWidthKit/IntXLOrUIntXL.swift @@ -91,3 +91,29 @@ public protocol IntXLOrUIntXL: NBKBinaryInteger, ExpressibleByStringLiteral wher @inlinable mutating func update(_ value: Digit) } + +//=----------------------------------------------------------------------------= +// MARK: + Details +//=----------------------------------------------------------------------------= + +extension IntXLOrUIntXL { + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + /// A `description` of this type. + /// + /// ``` + /// ┌─────────────────────────── → ────────────┐ + /// │ type │ description │ + /// ├─────────────────────────── → ────────────┤ + /// │ NBKFlexibleWidth │ "IntXL" │ + /// │ NBKFlexibleWidth.Magnitude │ "UIntXL" │ + /// └─────────────────────────── → ────────────┘ + /// ``` + /// + @inlinable public static var description: String { + Self.isSigned ? "IntXL" : "UIntXL" + } +} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift index 78c264c4..a24ba73d 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift @@ -41,10 +41,12 @@ extension NBKFlexibleWidth.Magnitude { self.storage.resize(minCount: other.storage.elements.count + index) let overflow = self.storage.withUnsafeMutableStrictUnsignedInteger { - $0.increment(by: other.storage.elements, plus: false, at: index).overflow + $0.increment(by: other.storage.elements, at: index).overflow } - if overflow { self.storage.append(1 as UInt) } + if overflow { + self.storage.append(1 as UInt) + } } @inlinable public func adding(_ other: Self, at index: Int) -> Self { diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift index bd4ac1e9..122e406e 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift @@ -82,7 +82,6 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= let comparison = other.compared(to: self) if comparison.isLessThanZero { - // such empty. much wow. } else if comparison.isZero { self.updateZeroValue() return PVO(001, false) @@ -100,8 +99,8 @@ extension NBKFlexibleWidth.Magnitude { self.storage.append(0 as UInt) if !shift.isZero { - divisor/*-*/.withUnsafeMutableStrictUnsignedInteger({ $0.bitshiftLeft(major: 0 as Int, minor: shift) }) - self.storage.withUnsafeMutableStrictUnsignedInteger({ $0.bitshiftLeft(major: 0 as Int, minor: shift) }) + divisor/*-*/.withUnsafeMutableStrictUnsignedInteger({ $0.bitshiftLeft(major: 0 as Int, minorAtLeastOne: shift) }) + self.storage.withUnsafeMutableStrictUnsignedInteger({ $0.bitshiftLeft(major: 0 as Int, minorAtLeastOne: shift) }) } let divisorLast0 = divisor.elements[divisorLastIndex] as UInt @@ -110,27 +109,27 @@ extension NBKFlexibleWidth.Magnitude { // division: approximate quotient digits //=--------------------------------------= var quotientIndex = remainderIndex - divisor.elements.endIndex as Int - let quotient = Self.uninitialized(count: quotientIndex &+ 1) { quotient in + let quotient = Self.uninitialized(count: quotientIndex + 1) { quotient in self.storage.withUnsafeMutableStrictUnsignedInteger { storage in loop: repeat { let remainderLast0 = storage.base[remainderIndex] storage.base.formIndex(before: &remainderIndex) let remainderLast1 = storage.base[remainderIndex] - //=------------------------------= + //=--------------------------= var digit: UInt if divisorLast0 == remainderLast0 { digit = UInt.max } else { digit = divisorLast0.dividingFullWidth(HL(remainderLast0, remainderLast1)).quotient } - //=------------------------------= + //=--------------------------= if !digit.isZero { var overflow = (storage).decrement(by: divisor.elements, times: digit, at: quotientIndex).overflow while overflow { overflow = !storage .increment(by: divisor.elements, at: quotientIndex).overflow; digit &-= 01 } } - //=------------------------------= + //=--------------------------= quotient[quotientIndex] = digit quotient.formIndex(before: "ientIndex) } while quotientIndex >= quotient.startIndex @@ -139,9 +138,11 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= // undo shift before division //=--------------------------------------= - self.storage.withUnsafeMutableStrictUnsignedInteger({ $0.bitshiftRight(major: 0 as Int, minor: shift) }) + if !shift.isZero { + self.storage.withUnsafeMutableStrictUnsignedInteger({ $0.bitshiftRight(major: 0 as Int, minorAtLeastOne: shift) }) + } + self.storage.normalize() - //=--------------------------------------= return PVO(partialValue: quotient, overflow: false) } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift index ec993ea7..c32ef9eb 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift @@ -30,7 +30,6 @@ extension NBKFlexibleWidth.Magnitude { @inlinable public static func &=(lhs: inout Self, rhs: Self) { lhs.storage.downsizeThenFormInIntersection(with: rhs.storage, each: &) lhs.storage.normalize() - Swift.assert(lhs.storage.isNormal) } @inlinable public static func &(lhs: Self, rhs: Self) -> Self { @@ -57,7 +56,6 @@ extension NBKFlexibleWidth.Magnitude { @inlinable public static func ^=(lhs: inout Self, rhs: Self) { lhs.storage.upsizeThenFormInIntersection(with: rhs.storage, each: ^) lhs.storage.normalize() - Swift.assert(lhs.storage.isNormal) } @inlinable public static func ^(lhs: Self, rhs: Self) -> Self { diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift index 08b76851..d42f2156 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift @@ -60,7 +60,7 @@ extension NBKFlexibleWidth.Magnitude { self.storage.resize(minCount: other.storage.elements.count + index) defer{ self.storage.normalize() } return self.storage.withUnsafeMutableStrictUnsignedInteger { - $0.decrement(by: other.storage.elements, plus: false, at: index).overflow + $0.decrement(by: other.storage.elements, at: index).overflow } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift index cc2582ef..acd36a52 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift @@ -58,30 +58,11 @@ import NBKCoreKit @inlinable init(normalizing storage: Storage) { self.storage = storage self.storage.normalize() - Swift.assert(self.storage.isNormal) } @inlinable init(unchecked storage: Storage) { self.storage = storage - } - - //=--------------------------------------------------------------------= - // MARK: Utilities - //=--------------------------------------------------------------------= - - /// A `description` of this type. - /// - /// ``` - /// ┌─────────────────────────── → ────────────┐ - /// │ type │ description │ - /// ├─────────────────────────── → ────────────┤ - /// │ NBKFlexibleWidth │ "IntXL" │ - /// │ NBKFlexibleWidth.Magnitude │ "UIntXL" │ - /// └─────────────────────────── → ────────────┘ - /// ``` - /// - @inlinable public static var description: String { - "UIntXL" + Swift.assert(self.storage.isNormal) } //*====================================================================* @@ -124,6 +105,7 @@ import NBKCoreKit @inlinable init(unchecked elements: Elements) { self.elements = elements + Swift.assert(!self.elements.isEmpty) } } } diff --git a/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Shifts.swift b/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Shifts.swift index 9b8c25a4..513c4e20 100644 --- a/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Shifts.swift +++ b/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Shifts.swift @@ -140,8 +140,8 @@ extension NBKStrictUnsignedInteger where Base: MutableCollection, Base.Indices = /// Performs an unsigned right shift. /// /// - Parameters: - /// - major: `1 <= major < base.endIndex` - /// - minor: `0 <= minor < Base.Element.bitWidth` + /// - major: `0 <= major < base.endIndex` + /// - minor: `1 <= minor < Base.Element.bitWidth` /// @inlinable public mutating func bitshiftRight(major: Int, minorAtLeastOne bits: Int) { NBK.bitshiftRightAsFixedLimbsCodeBlock(&self.base, environment: false, limbs: major, atLeastOneBit: bits) From 7bbf72c68a1126d3dc46be2fb4c2f352d9e248de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Mon, 18 Sep 2023 12:08:28 +0200 Subject: [PATCH 081/133] [NBKFlexibleWidthKit] Strict bit pattern (#83). --- .../Private/NBKStrictBitPattern+Shifts.swift | 127 ++++++++++++++++++ .../Private/NBKStrictBitPattern.swift | 93 +++++++++++++ .../NBKStrictUnsignedInteger+Addition.swift | 1 + .../NBKStrictUnsignedInteger+Division.swift | 1 + ...StrictUnsignedInteger+Multiplication.swift | 1 + .../NBKStrictUnsignedInteger+Shifts.swift | 13 +- .../Private/NBKStrictUnsignedInteger.swift | 21 +++ 7 files changed, 251 insertions(+), 6 deletions(-) create mode 100644 Sources/NBKFlexibleWidthKit/Private/NBKStrictBitPattern+Shifts.swift create mode 100644 Sources/NBKFlexibleWidthKit/Private/NBKStrictBitPattern.swift diff --git a/Sources/NBKFlexibleWidthKit/Private/NBKStrictBitPattern+Shifts.swift b/Sources/NBKFlexibleWidthKit/Private/NBKStrictBitPattern+Shifts.swift new file mode 100644 index 00000000..3c21cf2c --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/Private/NBKStrictBitPattern+Shifts.swift @@ -0,0 +1,127 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Strict Bit Pattern x Shifts +//*============================================================================* +//=----------------------------------------------------------------------------= +// MARK: + Left +//=----------------------------------------------------------------------------= + +extension NBKStrictBitPattern where Base: MutableCollection, Base.Indices == Range { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + /// Performs a left shift, assuming the `base` is ordered from least to most significant. + /// + /// - Parameters: + /// - pointee: The mutable collection. + /// - environment: The bit used to fill the void. + /// - major: `0 <= major < base.count` + /// - minor: `1 <= minor < Base.Element.bitWidth` + /// + @inlinable public mutating func bitshiftLeft(environment: Bool, major: Int, minorAtLeastOne minor: Int) { + precondition(0 <= major && major < self.base.count/*--*/, NBK.callsiteOutOfBoundsInfo()) + precondition(0 < minor && minor < Base.Element.bitWidth, NBK.callsiteOutOfBoundsInfo()) + //=--------------------------------------= + let push = NBK.initOrBitCast(truncating: minor, as: Base.Element.self) + let pull = NBK.initOrBitCast(truncating: Base.Element.bitWidth - minor, as: Base.Element.self) + let fill = Base.Element(repeating: environment) + //=--------------------------------------= + var destination = self.base.endIndex as Int + let offset: Int = ~(major) + var element = self.base[destination &+ offset] + //=--------------------------------------= + while destination > self.base.startIndex { + self.base.formIndex(before: &destination) + let pushed = element &<< push + element = destination > major ? self.base[destination &+ offset] : fill + let pulled = element &>> pull + self.base[destination] = pushed | pulled + } + } + + /// Performs a left shift, assuming the `base` is ordered from least to most significant. + /// + /// - Parameters: + /// - environment: The bit used to fill the void. + /// - major: `1 <= major < base.count` + /// + @inlinable public mutating func bitshiftLeft(environment: Bool, majorAtLeastOne major: Int) { + precondition(0 < major && major < self.base.count, NBK.callsiteOutOfBoundsInfo()) + //=--------------------------------------= + let fill = Base.Element(repeating: environment) + //=--------------------------------------= + for destination in self.base.indices.reversed() { + self.base[destination] = destination >= major ? self.base[destination - major] : fill + } + } +} + +//=----------------------------------------------------------------------------= +// MARK: + Right +//=----------------------------------------------------------------------------= + +extension NBKStrictBitPattern where Base: MutableCollection { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + /// Performs a right shift, assuming the `base` is ordered from least to most significant. + /// + /// - Parameters: + /// - environment: The bit used to fill the void. + /// - major: `0 <= major < base.count` + /// - minor: `1 <= minor < Base.Element.bitWidth` + /// + @inlinable public mutating func bitshiftRight(environment: Bool, major: Int, minorAtLeastOne minor: Int) { + precondition(0 <= major && major < self.base.count/*--*/, NBK.callsiteOutOfBoundsInfo()) + precondition(0 < minor && minor < Base.Element.bitWidth, NBK.callsiteOutOfBoundsInfo()) + //=--------------------------------------= + let push = NBK.initOrBitCast(truncating: minor, as: Base.Element.self) + let pull = NBK.initOrBitCast(truncating: Base.Element.bitWidth - minor, as: Base.Element.self) + let fill = Base.Element(repeating: environment) + //=--------------------------------------= + var destination = self.base.startIndex + let edge = self.base.distance(from: major, to: self.base.endIndex) + var element = self.base[major] as Base.Element + //=--------------------------------------= + while destination < self.base.endIndex { + let after = self.base.index(after: destination) + let pushed = element &>> push + element = after < edge ? self.base[after &+ major] : fill + let pulled = element &<< pull + self.base[destination] = pushed | pulled + destination = after + } + } + + /// Performs a right shift, assuming the `base` is ordered from least to most significant. + /// + /// - Parameters: + /// - environment: The bit used to fill the void. + /// - major: `1 <= major < base.count` + /// + @inlinable public mutating func bitshiftRight(environment: Bool, majorAtLeastOne major: Int) { + precondition(0 < major && major < self.base.count, NBK.callsiteOutOfBoundsInfo()) + //=--------------------------------------=--= + let fill = Base.Element(repeating: environment) + //=--------------------------------------= + let edge = self.base.distance(from: major, to: self.base.endIndex) + //=--------------------------------------= + for destination in self.base.indices { + self.base[destination] = destination < edge ? self.base[destination + major] : fill + } + } +} diff --git a/Sources/NBKFlexibleWidthKit/Private/NBKStrictBitPattern.swift b/Sources/NBKFlexibleWidthKit/Private/NBKStrictBitPattern.swift new file mode 100644 index 00000000..567de448 --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/Private/NBKStrictBitPattern.swift @@ -0,0 +1,93 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Strict Bit Pattern +//*============================================================================* +//=----------------------------------------------------------------------------= +// TODO: * NBKOffsetIndexed protocol with static index requirements (perf.) +//=----------------------------------------------------------------------------= + +@frozen public struct NBKStrictBitPattern where +Base.Element: NBKCoreInteger & NBKUnsignedInteger, Base.Indices == Range { + + //=------------------------------------------------------------------------= + // MARK: State + //=------------------------------------------------------------------------= + + @usableFromInline var base: Base + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + @inlinable public init(_ base: Base) { + self.base = base + precondition(Self.validate(self.base)) + } + + @inlinable public init(unchecked base: Base) { + self.base = base + Swift.assert(Self.validate(self.base)) + } + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + @inlinable public static func validate(_ base: Base) -> Bool { + !base.isEmpty && base.startIndex.isZero // TODO: req. NBKOffsetIndexed + } +} + +//=----------------------------------------------------------------------------= +// MARK: + Collection +//=----------------------------------------------------------------------------= + +extension NBKStrictBitPattern { + + //=------------------------------------------------------------------------= + // MARK: Accessors + //=------------------------------------------------------------------------= + + @inlinable public var first: Base.Element { + self.base[self.base.startIndex] + } + + @inlinable public var last: Base.Element { + self.base[self.lastIndex] + } + + @inlinable public var lastIndex: Base.Index { + self.base.index(before: self.base.endIndex) + } +} + +//=----------------------------------------------------------------------------= +// MARK: + Collection x Mutable +//=----------------------------------------------------------------------------= + +extension NBKStrictBitPattern where Base: MutableCollection { + + //=------------------------------------------------------------------------= + // MARK: Accessors + //=------------------------------------------------------------------------= + + @inlinable public var first: Base.Element { + get { self.base[self.base.startIndex] } + set { self.base[self.base.startIndex] = newValue } + } + + @inlinable public var last: Base.Element { + get { self.base[self.lastIndex] } + set { self.base[self.lastIndex] = newValue } + } +} diff --git a/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Addition.swift b/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Addition.swift index 96d645b9..bdbfd835 100644 --- a/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Addition.swift +++ b/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Addition.swift @@ -14,6 +14,7 @@ import NBKCoreKit //*============================================================================* // MARK: * NBK x Strict Unsigned Integer x Addition //*============================================================================* +//=----------------------------------------------------------------------------= // MARK: + Bit //=----------------------------------------------------------------------------= diff --git a/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Division.swift b/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Division.swift index 71bef3b6..a216c2cc 100644 --- a/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Division.swift +++ b/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Division.swift @@ -12,6 +12,7 @@ import NBKCoreKit //*============================================================================* // MARK: * NBK x Strict Unsigned Integer x Division //*============================================================================* +//=----------------------------------------------------------------------------= // MARK: + Digit //=----------------------------------------------------------------------------= diff --git a/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Multiplication.swift b/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Multiplication.swift index b1fc73fc..d2644519 100644 --- a/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Multiplication.swift +++ b/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Multiplication.swift @@ -12,6 +12,7 @@ import NBKCoreKit //*============================================================================* // MARK: * NBK x Strict Unsigned Integer x Multiplication //*============================================================================* +//=----------------------------------------------------------------------------= // MARK: + Digit //=----------------------------------------------------------------------------= diff --git a/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Shifts.swift b/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Shifts.swift index 513c4e20..ce4ebc24 100644 --- a/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Shifts.swift +++ b/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Shifts.swift @@ -12,6 +12,7 @@ import NBKCoreKit //*============================================================================* // MARK: * NBK x Strict Unsigned Integer x Shifts //*============================================================================* +//=----------------------------------------------------------------------------= // MARK: + Left //=----------------------------------------------------------------------------= @@ -70,8 +71,8 @@ extension NBKStrictUnsignedInteger where Base: MutableCollection, Base.Indices = /// - major: `0 <= major < base.endIndex` /// - minor: `1 <= minor < Base.Element.bitWidth` /// - @inlinable public mutating func bitshiftLeft(major: Int, minorAtLeastOne bits: Int) { - NBK.bitshiftLeftAsFixedLimbsCodeBlock(&self.base, environment: false, limbs: major, atLeastOneBit: bits) + @inlinable public mutating func bitshiftLeft(major: Int, minorAtLeastOne minor: Int) { + self.bitPattern.bitshiftLeft(environment: false, major: major, minorAtLeastOne: minor) } /// Performs a left shift. @@ -80,7 +81,7 @@ extension NBKStrictUnsignedInteger where Base: MutableCollection, Base.Indices = /// - major: `1 <= major < base.endIndex` /// @inlinable public mutating func bitshiftLeft(majorAtLeastOne major: Int) { - NBK.bitshiftLeftAsFixedLimbsCodeBlock(&self.base, environment: false, atLeastOneLimb: major) + self.bitPattern.bitshiftLeft(environment: false, majorAtLeastOne: major) } } @@ -143,8 +144,8 @@ extension NBKStrictUnsignedInteger where Base: MutableCollection, Base.Indices = /// - major: `0 <= major < base.endIndex` /// - minor: `1 <= minor < Base.Element.bitWidth` /// - @inlinable public mutating func bitshiftRight(major: Int, minorAtLeastOne bits: Int) { - NBK.bitshiftRightAsFixedLimbsCodeBlock(&self.base, environment: false, limbs: major, atLeastOneBit: bits) + @inlinable public mutating func bitshiftRight(major: Int, minorAtLeastOne minor: Int) { + self.bitPattern.bitshiftRight(environment: false, major: major, minorAtLeastOne: minor) } /// Performs an unsigned right shift. @@ -153,6 +154,6 @@ extension NBKStrictUnsignedInteger where Base: MutableCollection, Base.Indices = /// - major: `1 <= major < base.endIndex` /// @inlinable public mutating func bitshiftRight(majorAtLeastOne major: Int) { - NBK.bitshiftRightAsFixedLimbsCodeBlock(&self.base, environment: false, atLeastOneLimb: major) + self.bitPattern.bitshiftRight(environment: false, majorAtLeastOne: major) } } diff --git a/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger.swift b/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger.swift index b264e664..3a20f338 100644 --- a/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger.swift +++ b/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger.swift @@ -88,3 +88,24 @@ extension NBKStrictUnsignedInteger where Base: MutableCollection { set { self.base[self.lastIndex] = newValue } } } + +//=----------------------------------------------------------------------------= +// MARK: + Views x Bit Pattern +//=----------------------------------------------------------------------------= + +extension NBKStrictUnsignedInteger where Base.Indices == Range { + + //=------------------------------------------------------------------------= + // MARK: Utilities x Views + //=------------------------------------------------------------------------= + + @inlinable public var bitPattern: NBKStrictBitPattern { + _read { + yield NBKStrictBitPattern(unchecked: self.base) + } + + _modify { + var view = self.bitPattern; yield &view; self = Self(unchecked: view.base) + } + } +} From c5df811a588165d386ce0e11059deba0a3c27245 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Thu, 28 Sep 2023 08:45:19 +0200 Subject: [PATCH 082/133] [NBKSignedKit] Documentation. --- .../NBKFlexibleWidth+Text.swift | 34 +++++++++ Sources/NBKSignedKit/NBKSigned+Text.swift | 74 ++++++++++++++++++- 2 files changed, 107 insertions(+), 1 deletion(-) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text.swift index 4b7cdfa6..6911cc9d 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text.swift @@ -19,6 +19,25 @@ extension NBKFlexibleWidth.Magnitude { // MARK: Details x Decoding //=------------------------------------------------------------------------= + /// Creates a new instance from the given `description` and `radix`. + /// + /// The `description` may contain a plus or minus sign (+ or -), followed by one + /// or more numeric digits (0-9) or letters (a-z or A-Z). If the description uses + /// an invalid format, or its value cannot be represented, the result is nil. + /// + /// ``` + /// ┌─────────────┬────── → ─────────────┐ + /// │ description │ radix │ self │ + /// ├─────────────┼────── → ─────────────┤ + /// │ "123" │ 16 │ Int256( 291) │ + /// │ "+123" │ 16 │ Int256( 291) │ + /// │ "-123" │ 16 │ Int256(-291) │ + /// │ "~123" │ 16 │ nil │ + /// └─────────────┴────── → ─────────────┘ + /// ``` + /// + /// - Note: The decoding strategy is case insensitive. + /// @inlinable public init?(_ description: some StringProtocol, radix: Int) { let decoder = NBK.IntegerDescription.Decoder(radix: radix) if let value: Self = decoder.decode(description) { self = value } else { return nil } @@ -28,6 +47,21 @@ extension NBKFlexibleWidth.Magnitude { // MARK: Details x Encoding //=------------------------------------------------------------------------= + /// A `description` of this value in the given ASCII format. + /// + /// The description may contain a minus sign (-), followed by one + /// or more numeric digits (0-9) or letters (a-z or A-Z). These represent + /// the integer's sign and magnitude. Zero is always non-negative. + /// + /// ``` + /// ┌──────────────┬───────┬─────────── → ────────────┐ + /// │ self │ radix │ uppercase │ description │ + /// ├──────────────┼───────┼─────────── → ────────────┤ + /// │ Int256( 123) │ 12 │ true │ "A3" │ + /// │ Int256(-123) │ 16 │ false │ "-7b" │ + /// └──────────────┴───────┴─────────── → ────────────┘ + /// ``` + /// @inlinable public func description(radix: Int, uppercase: Bool) -> String { let encoder = NBK.IntegerDescription.Encoder(radix: radix, uppercase: uppercase) return encoder.encode(self) as String diff --git a/Sources/NBKSignedKit/NBKSigned+Text.swift b/Sources/NBKSignedKit/NBKSigned+Text.swift index a735ca5d..9296378a 100644 --- a/Sources/NBKSignedKit/NBKSigned+Text.swift +++ b/Sources/NBKSignedKit/NBKSigned+Text.swift @@ -19,12 +19,52 @@ extension NBKSigned { // MARK: Details x Decoding //=------------------------------------------------------------------------= + /// Creates a new instance from the given `description`. + /// + /// The `description` may contain a plus or minus sign (+ or -), followed + /// by one or more numeric digits (0-9). If the description uses an invalid + /// format, or its value cannot be represented, the result is nil. + /// + /// ``` + /// ┌──────────── → ─────────────┐ + /// │ description │ self │ + /// ├──────────── → ─────────────┤ + /// │ "123" │ Int256( 123) │ + /// │ "+123" │ Int256( 123) │ + /// │ "-123" │ Int256(-123) │ + /// │ "~123" │ nil │ + /// └──────────── → ─────────────┘ + /// ``` + /// + /// - Note: The decoding strategy is case insensitive. + /// + /// - Note: This member is required by `Swift.LosslessStringConvertible`. + /// @inlinable public init?(_ description: String) { self.init(description, radix: 10) } - // TODO: decoder needs a sign and magnitude option + /// Creates a new instance from the given `description` and `radix`. + /// + /// The `description` may contain a plus or minus sign (+ or -), followed by one + /// or more numeric digits (0-9) or letters (a-z or A-Z). If the description uses + /// an invalid format, or its value cannot be represented, the result is nil. + /// + /// ``` + /// ┌─────────────┬────── → ─────────────┐ + /// │ description │ radix │ self │ + /// ├─────────────┼────── → ─────────────┤ + /// │ "123" │ 16 │ Int256( 291) │ + /// │ "+123" │ 16 │ Int256( 291) │ + /// │ "-123" │ 16 │ Int256(-291) │ + /// │ "~123" │ 16 │ nil │ + /// └─────────────┴────── → ─────────────┘ + /// ``` + /// + /// - Note: The decoding strategy is case insensitive. + /// @inlinable public init?(_ description: some StringProtocol, radix: Int) { + // TODO: decoder needs a sign and magnitude option let components = NBK.IntegerDescription.makeSignBody(from: description.utf8) let body = description[components.body.startIndex ..< components.body.endIndex] guard let magnitude = Magnitude(body, radix: radix) else { return nil } @@ -35,10 +75,42 @@ extension NBKSigned { // MARK: Details x Encoding //=------------------------------------------------------------------------= + /// A `description` of this value in base 10 ASCII. + /// + /// The description may contain a minus sign (-), followed by one + /// or more numeric digits (0-9) or letters (a-z or A-Z). These represent + /// the integer's sign and magnitude. Zero is always non-negative. + /// + /// ``` + /// ┌───────────── → ────────────┐ + /// │ self │ description │ + /// ├───────────── → ────────────┤ + /// │ Int256( 123) │ "123" │ + /// │ Int256(-123) │ "-123" │ + /// └───────────── → ────────────┘ + /// ``` + /// + /// - Note: This member is required by `Swift.CustomStringConvertible`. + /// @inlinable public var description: String { self.description(radix: 10, uppercase: false) } + /// A `description` of this value in the given ASCII format. + /// + /// The description may contain a minus sign (-), followed by one + /// or more numeric digits (0-9) or letters (a-z or A-Z). These represent + /// the integer's sign and magnitude. Zero is always non-negative. + /// + /// ``` + /// ┌──────────────┬───────┬─────────── → ────────────┐ + /// │ self │ radix │ uppercase │ description │ + /// ├──────────────┼───────┼─────────── → ────────────┤ + /// │ Int256( 123) │ 12 │ true │ "A3" │ + /// │ Int256(-123) │ 16 │ false │ "-7b" │ + /// └──────────────┴───────┴─────────── → ────────────┘ + /// ``` + /// @inlinable public func description(radix: Int, uppercase: Bool) -> String { let encoder = NBK.IntegerDescription.Encoder(radix: radix, uppercase: uppercase) return encoder.encode(sign: self.sign, magnitude: self.magnitude.words) as String From 05f601a294f48c0b49165a06fb3d3a4a96ee900f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Thu, 28 Sep 2023 11:31:45 +0200 Subject: [PATCH 083/133] [NBKSignedKit] ExpressibleByStringLiteral (#86). --- Sources/NBKSignedKit/NBKSigned+Literals.swift | 36 +++++++++ Sources/NBKSignedKit/NBKSigned.swift | 3 +- .../NBKSignedKitTests/NBKFlexibleWidth.swift | 14 ++++ .../NBKSigned+Literals.swift | 77 +++++++++++++++++++ .../NBKSigned+Negation.swift | 1 - 5 files changed, 129 insertions(+), 2 deletions(-) create mode 100644 Tests/NBKSignedKitTests/NBKSigned+Literals.swift diff --git a/Sources/NBKSignedKit/NBKSigned+Literals.swift b/Sources/NBKSignedKit/NBKSigned+Literals.swift index 78a17f69..8099b5c2 100644 --- a/Sources/NBKSignedKit/NBKSigned+Literals.swift +++ b/Sources/NBKSignedKit/NBKSigned+Literals.swift @@ -22,4 +22,40 @@ extension NBKSigned { @inlinable public init(integerLiteral source: Int) { self.init(source) } + + //=------------------------------------------------------------------------= + // MARK: Details x String Literal Type + //=------------------------------------------------------------------------= + + /// Creates a new instance from the given string literal. + /// + /// The string literal may contain a plus or minus sign (+ or -), followed by + /// an optional radix indicator (0b, 0o or 0x), then one or more numeric digits + /// (0-9) or letters (a-z or A-Z). If the string literal uses an invalid format, + /// or its value cannot be represented, a runtime error may occur. + /// + /// ``` + /// ┌───────── → ─────────────┐ + /// │ literal │ self │ + /// ├───────── → ─────────────┤ + /// │ "123" │ Int256( 123) │ + /// │ "+0x123" │ Int256( 291) │ + /// │ "-0x123" │ Int256(-291) │ + /// │ "~OX123" │ error │ + /// └───────── → ─────────────┘ + /// ``` + /// + /// - Note: The decoding strategy is case insensitive. + /// + @inlinable public init(stringLiteral source: StaticString) { + if let value = Self(exactlyStringLiteral: source) { self = value } else { + preconditionFailure("\(Self.self) cannot represent \(source)") + } + } + + @inlinable init?(exactlyStringLiteral source: StaticString) { + let decoder = NBK.IntegerDescription.DecoderDecodingRadix() + guard let components: SM = decoder.decode(source) else { return nil } + self.init(sign: components.sign, magnitude: components.magnitude) + } } diff --git a/Sources/NBKSignedKit/NBKSigned.swift b/Sources/NBKSignedKit/NBKSigned.swift index c625ac22..78bf3a50 100644 --- a/Sources/NBKSignedKit/NBKSigned.swift +++ b/Sources/NBKSignedKit/NBKSigned.swift @@ -46,7 +46,8 @@ import NBKCoreKit /// - Note: The `Digit` type is `NBKSigned`. /// @frozen public struct NBKSigned: Comparable, -CustomStringConvertible, ExpressibleByIntegerLiteral, Hashable, Sendable, SignedNumeric { +CustomStringConvertible, ExpressibleByIntegerLiteral, ExpressibleByStringLiteral, +Hashable, Sendable, SignedNumeric { public typealias Sign = FloatingPointSign diff --git a/Tests/NBKSignedKitTests/NBKFlexibleWidth.swift b/Tests/NBKSignedKitTests/NBKFlexibleWidth.swift index 05a11117..fc87285b 100644 --- a/Tests/NBKSignedKitTests/NBKFlexibleWidth.swift +++ b/Tests/NBKSignedKitTests/NBKFlexibleWidth.swift @@ -41,3 +41,17 @@ extension UIntXL { self.init(words: NBKChunkedInt(x64)) } } + +//=----------------------------------------------------------------------------= +// MARK: + SIntXL +//=----------------------------------------------------------------------------= + +extension NBKSigned { + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + static let min256 = Self(sign: .minus, magnitude: Magnitude.max256) + static let max256 = Self(sign: .plus, magnitude: Magnitude.max256) +} diff --git a/Tests/NBKSignedKitTests/NBKSigned+Literals.swift b/Tests/NBKSignedKitTests/NBKSigned+Literals.swift new file mode 100644 index 00000000..4c0a4a37 --- /dev/null +++ b/Tests/NBKSignedKitTests/NBKSigned+Literals.swift @@ -0,0 +1,77 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +import NBKFlexibleWidthKit +@testable import NBKSignedKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Signed x Literals x SIntXL +//*============================================================================* + +final class NBKSignedTestsOnLiteralsAsSIntXL: XCTestCase { + + typealias T = NBKSigned + typealias M = NBKSigned.Magnitude + + //=------------------------------------------------------------------------= + // MARK: State + //=------------------------------------------------------------------------= + + let top256 = T(M(x64:[0xe7e6e5e4e3e2e1e0, 0xefeeedecebeae9e8, 0xf7f6f5f4f3f2f1f0, 0xfffefdfcfbfaf9f8] as X)) + let bottom256 = T(M(x64:[0x0706050403020100, 0x0f0e0d0c0b0a0908, 0x1716151413121110, 0x1f1e1d1c1b1a1918] as X)) + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testFromIntegerLiteral() { + XCTAssertEqual( T(M(x64:[ 10, 0, 0, 0] as X)), (10)) + XCTAssertEqual( T(M(x64:[ 02, 0, 0, 0] as X)), (0b10)) + XCTAssertEqual( T(M(x64:[ 08, 0, 0, 0] as X)), (0o10)) + XCTAssertEqual( T(M(x64:[ 16, 0, 0, 0] as X)), (0x10)) + + XCTAssertEqual( T(integerLiteral: Int.max), T(M(x64:[UInt64(UInt.max / 2 + 0), 0, 0, 0] as X))) + XCTAssertEqual( T(integerLiteral: Int.min), -T(M(x64:[UInt64(UInt.max / 2 + 1), 0, 0, 0] as X))) + } + + func testFromStringLiteral() { + XCTAssertEqual( T(M(x64:[ 10, 0, 0, 0] as X)), "10") + XCTAssertEqual( T(M(x64:[ 02, 0, 0, 0] as X)), "0b10") + XCTAssertEqual( T(M(x64:[ 08, 0, 0, 0] as X)), "0o10") + XCTAssertEqual( T(M(x64:[ 16, 0, 0, 0] as X)), "0x10") + XCTAssertEqual(-T(M(x64:[ 10, 0, 0, 0] as X)), "-10") + XCTAssertEqual(-T(M(x64:[ 02, 0, 0, 0] as X)), "-0b10") + XCTAssertEqual(-T(M(x64:[ 08, 0, 0, 0] as X)), "-0o10") + XCTAssertEqual(-T(M(x64:[ 16, 0, 0, 0] as X)), "-0x10") + + XCTAssertEqual(self.top256/*-------*/, "0x00000000000000fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e0") + XCTAssertEqual(self.bottom256/*----*/, "0x000000000000001f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100") + XCTAssertEqual(T(exactlyStringLiteral: "0x000000000000010000000000000000000000000000000000000000000000000000000000000000"), T.max256 + 1) + XCTAssertEqual(T(exactlyStringLiteral: "0x00000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), T.max256) + XCTAssertEqual(T(exactlyStringLiteral: "-0x00000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), T.min256) + XCTAssertEqual(T(exactlyStringLiteral: "-0x000000000000010000000000000000000000000000000000000000000000000000000000000000"), T.min256 - 1) + + XCTAssertEqual(self.top256/*-------*/, "00115790308505455567723526024286119531261069242336003260839703036409543150199264") + XCTAssertEqual(self.bottom256/*----*/, "00014074904626401341155369551180448584754667373453244490859944217516317499064576") + XCTAssertEqual(T(exactlyStringLiteral: "00115792089237316195423570985008687907853269984665640564039457584007913129639936"), T.max256 + 1) + XCTAssertEqual(T(exactlyStringLiteral: "00115792089237316195423570985008687907853269984665640564039457584007913129639935"), T.max256) + XCTAssertEqual(T(exactlyStringLiteral: "-00115792089237316195423570985008687907853269984665640564039457584007913129639935"), T.min256) + XCTAssertEqual(T(exactlyStringLiteral: "-00115792089237316195423570985008687907853269984665640564039457584007913129639936"), T.min256 - 1) + } +} + +#endif diff --git a/Tests/NBKSignedKitTests/NBKSigned+Negation.swift b/Tests/NBKSignedKitTests/NBKSigned+Negation.swift index c5325c29..d28d0c76 100644 --- a/Tests/NBKSignedKitTests/NBKSigned+Negation.swift +++ b/Tests/NBKSignedKitTests/NBKSigned+Negation.swift @@ -59,5 +59,4 @@ file: StaticString = #file, line: UInt = #line) { NBKAssertIdentical({ var x = operand; x.negate(); return x }(), result, file: file, line: line) } - #endif From cd41fcf6f83fa9738d250b769ada3eb39283917e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Fri, 29 Sep 2023 17:10:49 +0200 Subject: [PATCH 084/133] [NBKSignedKit] StaticBigInt. --- Sources/NBKSignedKit/NBKSigned+Literals.swift | 21 ++++++++++++++++ .../NBKSigned+Literals.swift | 25 ++++++++++++++++++- 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/Sources/NBKSignedKit/NBKSigned+Literals.swift b/Sources/NBKSignedKit/NBKSigned+Literals.swift index 8099b5c2..15e7beff 100644 --- a/Sources/NBKSignedKit/NBKSigned+Literals.swift +++ b/Sources/NBKSignedKit/NBKSigned+Literals.swift @@ -18,11 +18,32 @@ extension NBKSigned { //=------------------------------------------------------------------------= // MARK: Initializers x Integer Literal Type //=------------------------------------------------------------------------= + #if SBI && swift(>=5.8) + + @inlinable public init(integerLiteral source: StaticBigInt) { + if let value = Self(exactlyIntegerLiteral: source) { self = value } else { + preconditionFailure("\(Self.self) cannot represent \(source)") + } + } + + @inlinable init?(exactlyIntegerLiteral source: StaticBigInt) { + let isLessThanZero = source.signum() == -1 as Int + guard var magnitude = Magnitude(words: NBKStaticBigInt(source)) else { return nil } + //=--------------------------------------= + if isLessThanZero { + magnitude.formTwosComplement() + } + //=--------------------------------------= + self.init(sign: NBK.Sign(isLessThanZero), magnitude: magnitude) + } + + #else @inlinable public init(integerLiteral source: Int) { self.init(source) } + #endif //=------------------------------------------------------------------------= // MARK: Details x String Literal Type //=------------------------------------------------------------------------= diff --git a/Tests/NBKSignedKitTests/NBKSigned+Literals.swift b/Tests/NBKSignedKitTests/NBKSigned+Literals.swift index b136c361..1728c450 100644 --- a/Tests/NBKSignedKitTests/NBKSigned+Literals.swift +++ b/Tests/NBKSignedKitTests/NBKSigned+Literals.swift @@ -54,9 +54,32 @@ final class NBKSignedTestsOnLiteralsAsSIntXL: XCTestCase { XCTAssertEqual(-T(M(x64:[ 2, 0, 0, 0] as X)), (-0b10)) XCTAssertEqual(-T(M(x64:[ 8, 0, 0, 0] as X)), (-0o10)) XCTAssertEqual(-T(M(x64:[16, 0, 0, 0] as X)), (-0x10)) - + #if SBI && swift(>=5.8) + XCTAssertEqual(self.top256/*--------*/, (0x00000000000000fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e0)) + XCTAssertEqual(self.bottom256/*-----*/, (0x000000000000001f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100)) + XCTAssertEqual(T(exactlyIntegerLiteral: (0x000000000000010000000000000000000000000000000000000000000000000000000000000000)), T.max256 / 1 + 1) + XCTAssertEqual(T(exactlyIntegerLiteral: (0x00000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)), T.max256 / 1 + 0) + XCTAssertEqual(T(exactlyIntegerLiteral: (-0x00000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)), T.min256 / 1 - 0) + XCTAssertEqual(T(exactlyIntegerLiteral: (-0x000000000000010000000000000000000000000000000000000000000000000000000000000000)), T.min256 / 1 - 1) + XCTAssertEqual(T(exactlyIntegerLiteral: (0x000000000000008000000000000000000000000000000000000000000000000000000000000000)), T.max256 / 2 + 1) + XCTAssertEqual(T(exactlyIntegerLiteral: (0x000000000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)), T.max256 / 2 + 0) + XCTAssertEqual(T(exactlyIntegerLiteral: (-0x000000000000008000000000000000000000000000000000000000000000000000000000000000)), T.min256 / 2 - 1) + XCTAssertEqual(T(exactlyIntegerLiteral: (-0x000000000000008000000000000000000000000000000000000000000000000000000000000001)), T.min256 / 2 - 2) + + XCTAssertEqual(self.top256/*--------*/, (00115790308505455567723526024286119531261069242336003260839703036409543150199264)) + XCTAssertEqual(self.bottom256/*-----*/, (00014074904626401341155369551180448584754667373453244490859944217516317499064576)) + XCTAssertEqual(T(exactlyIntegerLiteral: (00115792089237316195423570985008687907853269984665640564039457584007913129639936)), T.max256 / 1 + 1) + XCTAssertEqual(T(exactlyIntegerLiteral: (00115792089237316195423570985008687907853269984665640564039457584007913129639935)), T.max256 / 1 + 0) + XCTAssertEqual(T(exactlyIntegerLiteral: (-00115792089237316195423570985008687907853269984665640564039457584007913129639935)), T.min256 / 1 - 0) + XCTAssertEqual(T(exactlyIntegerLiteral: (-00115792089237316195423570985008687907853269984665640564039457584007913129639936)), T.min256 / 1 - 1) + XCTAssertEqual(T(exactlyIntegerLiteral: (00057896044618658097711785492504343953926634992332820282019728792003956564819968)), T.max256 / 2 + 1) + XCTAssertEqual(T(exactlyIntegerLiteral: (00057896044618658097711785492504343953926634992332820282019728792003956564819967)), T.max256 / 2 + 0) + XCTAssertEqual(T(exactlyIntegerLiteral: (-00057896044618658097711785492504343953926634992332820282019728792003956564819968)), T.min256 / 2 - 1) + XCTAssertEqual(T(exactlyIntegerLiteral: (-00057896044618658097711785492504343953926634992332820282019728792003956564819969)), T.min256 / 2 - 2) + #else XCTAssertEqual( T(integerLiteral: Int.max), T(M(x64:[UInt64(UInt.max / 2 + 0), 0, 0, 0] as X))) XCTAssertEqual( T(integerLiteral: Int.min), -T(M(x64:[UInt64(UInt.max / 2 + 1), 0, 0, 0] as X))) + #endif } func testFromStringLiteral() { From edf1425c37d86a1fd7533c69eecb78c9f9319133 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Mon, 2 Oct 2023 14:46:30 +0200 Subject: [PATCH 085/133] [NBKFlexibleWidthKit] Cleanup. --- .../NBKFlexibleWidth+Addition+Digit.swift | 2 +- .../NBKFlexibleWidth+Addition.swift | 2 +- .../NBKFlexibleWidth+Bits.swift | 6 +- .../NBKFlexibleWidth+Comparisons.swift | 31 +++++----- .../NBKFlexibleWidth+Complements.swift | 6 +- .../NBKFlexibleWidth+Division+Digit.swift | 2 +- .../NBKFlexibleWidth+Division.swift | 13 +++-- ...BKFlexibleWidth+Multiplication+Digit.swift | 2 +- .../NBKFlexibleWidth+Shifts.swift | 32 ++++++++--- .../NBKFlexibleWidth+Subtraction+Digit.swift | 2 +- .../NBKFlexibleWidth+Subtraction.swift | 2 +- .../NBKFlexibleWidth+Words+Collection.swift | 57 +++++++++++++++++++ .../NBKFlexibleWidth+Words.swift | 26 --------- .../NBKFlexibleWidthKit/Private/Aliases.swift | 26 --------- .../NBKFlexibleWidth+Shifts.swift | 25 +++++--- .../NBKFlexibleWidth+Words.swift | 13 +++++ 16 files changed, 146 insertions(+), 101 deletions(-) create mode 100644 Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words+Collection.swift delete mode 100644 Sources/NBKFlexibleWidthKit/Private/Aliases.swift diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift index ad5055d3..ea791bd5 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift @@ -41,7 +41,7 @@ extension NBKFlexibleWidth.Magnitude { self.storage.resize(minCount: index + 1) let overflow = self.storage.withUnsafeMutableBufferPointer { - SUISS.increment(&$0, by: other, at: index).overflow + NBK.SUISS.increment(&$0, by: other, at: index).overflow } if overflow { diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift index 3316a7a0..39d43bae 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift @@ -41,7 +41,7 @@ extension NBKFlexibleWidth.Magnitude { self.storage.resize(minCount: other.storage.elements.count + index) let overflow = self.storage.withUnsafeMutableBufferPointer { - SUISS.increment(&$0, by: other.storage.elements, at: index).overflow + NBK.SUISS.increment(&$0, by: other.storage.elements, at: index).overflow } if overflow { diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift index 469e5f40..3586afdc 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift @@ -32,15 +32,15 @@ extension NBKFlexibleWidth.Magnitude { } @inlinable public var nonzeroBitCount: Int { - self.withUnsafeBufferPointer(SBISS.nonzeroBitCount(of:)) + self.withUnsafeBufferPointer(NBK.SBISS.nonzeroBitCount(of:)) } @inlinable public var leadingZeroBitCount: Int { - self.withUnsafeBufferPointer(SBISS.leadingZeroBitCount(of:)) + self.withUnsafeBufferPointer(NBK.SBISS.leadingZeroBitCount(of:)) } @inlinable public var trailingZeroBitCount: Int { - self.withUnsafeBufferPointer(SBISS.trailingZeroBitCount(of:)) + self.withUnsafeBufferPointer(NBK.SBISS.trailingZeroBitCount(of:)) } @inlinable public var mostSignificantBit: Bool { diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift index 9edbfe38..e7192a0f 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift @@ -32,7 +32,7 @@ extension NBKFlexibleWidth.Magnitude { } @inlinable public var isPowerOf2: Bool { - self.withUnsafeBufferPointer({ SBISS.nonzeroBitCount(of: $0, equals: 1) }) + self.withUnsafeBufferPointer({ NBK.SBISS.nonzeroBitCount(of: $0, equals: 1) }) } @inlinable public func signum() -> Int { @@ -60,30 +60,33 @@ extension NBKFlexibleWidth.Magnitude { } @inlinable public func compared(to other: Self) -> Int { - self .storage.elements.withUnsafeBufferPointer { lhs in - other.storage.elements.withUnsafeBufferPointer { rhs in - SUISS.compare(lhs, to: rhs) - }} + self.storage.elements.withUnsafeBufferPointer { lhs in + other.storage.elements.withUnsafeBufferPointer { rhs in + NBK.SUISS.compare(lhs, to: rhs) + } + } } @inlinable public func compared(to other: Self, at index: Int) -> Int { - self .storage.elements.withUnsafeBufferPointer { lhs in - other.storage.elements.withUnsafeBufferPointer { rhs in - SUISS.compare(lhs, to: rhs, at: index) - }} + self.storage.elements.withUnsafeBufferPointer { lhs in + other.storage.elements.withUnsafeBufferPointer { rhs in + NBK.SUISS.compare(lhs, to: rhs, at: index) + } + } } @_disfavoredOverload @inlinable public func compared(to other: Digit) -> Int { self.storage.elements.withUnsafeBufferPointer { lhs in - SBI.withUnsafeBufferPointer(to: other) { rhs in - SUISS.compare(lhs, to: rhs) - }} + NBK.SBI.withUnsafeBufferPointer(to:other) { rhs in + NBK.SUISS.compare(lhs, to: rhs) + } + } } @_disfavoredOverload @inlinable public func compared(to other: Digit, at index: Int) -> Int { self.storage.elements.withUnsafeBufferPointer { lhs in - SBI.withUnsafeBufferPointer(to: other) { rhs in - SUISS.compare(lhs, to: rhs, at: index) + NBK.SBI.withUnsafeBufferPointer(to:other) { rhs in + NBK.SUISS.compare(lhs, to: rhs, at: index) } } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements.swift index 596469a4..05e4cb78 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements.swift @@ -21,7 +21,7 @@ extension NBKFlexibleWidth.Magnitude { @inlinable public mutating func formOnesComplement() { self.withUnsafeMutableBufferPointer { - SBISS.formOnesComplement(&$0) + NBK.SBISS.formOnesComplement(&$0) } } @@ -35,7 +35,7 @@ extension NBKFlexibleWidth.Magnitude { @inlinable public mutating func formTwosComplementReportingOverflow() -> Bool { self.withUnsafeMutableBufferPointer { - SUISS.formTwosComplementReportingOverflow(&$0) + NBK.SUISS.formTwosComplementReportingOverflow(&$0) } } @@ -47,7 +47,7 @@ extension NBKFlexibleWidth.Magnitude { @inlinable public mutating func formTwosComplementSubsequence(_ carry: Bool) -> Bool { self.withUnsafeMutableBufferPointer { - SUISS.formTwosComplementSubsequence(&$0, carry: carry) + NBK.SUISS.formTwosComplementSubsequence(&$0, carry: carry) } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.swift index c4f28a2b..88de6653 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.swift @@ -60,7 +60,7 @@ extension NBKFlexibleWidth.Magnitude { @_disfavoredOverload @inlinable public mutating func formQuotientWithRemainderReportingOverflow(dividingBy other: Digit) -> PVO { self.withUnsafeMutableBufferPointer { - SUISS.formQuotientWithRemainderReportingOverflow(&$0, dividingBy: other) + NBK.SUISS.formQuotientWithRemainderReportingOverflow(&$0, dividingBy: other) } } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift index 0f267acf..e9cfb628 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift @@ -99,8 +99,8 @@ extension NBKFlexibleWidth.Magnitude { self.storage.append(0 as UInt) if !shift.isZero { - divisor/*-*/.withUnsafeMutableBufferPointer({ SUI.bitshiftLeft(&$0, major: 0 as Int, minorAtLeastOne: shift) }) - self.storage.withUnsafeMutableBufferPointer({ SUI.bitshiftLeft(&$0, major: 0 as Int, minorAtLeastOne: shift) }) + divisor/*-*/.withUnsafeMutableBufferPointer({ NBK.SUI.bitshiftLeft(&$0, major: 0 as Int, minorAtLeastOne: shift) }) + self.storage.withUnsafeMutableBufferPointer({ NBK.SUI.bitshiftLeft(&$0, major: 0 as Int, minorAtLeastOne: shift) }) } let divisorLast0 = divisor.elements[divisorLastIndex] as UInt @@ -124,9 +124,10 @@ extension NBKFlexibleWidth.Magnitude { } //=--------------------------= if !digit.isZero { - var overflow = SUISS.decrement(&storage, by: divisor.elements, times: digit, at: quotientIndex).overflow - while overflow { - overflow = !SUISS.increment(&storage, by: divisor.elements, at: quotientIndex).overflow; digit &-= 01 + var overflow = NBK.SUISS.decrement(&storage, by: divisor.elements, times: digit, at: quotientIndex).overflow + while overflow { + digit &-= 1 as Digit + overflow = !NBK.SUISS.increment(&storage, by: divisor.elements, at: quotientIndex).overflow } } //=--------------------------= @@ -139,7 +140,7 @@ extension NBKFlexibleWidth.Magnitude { // undo shift before division //=--------------------------------------= if !shift.isZero { - self.storage.withUnsafeMutableBufferPointer({ SUI.bitshiftRight(&$0, major: 0 as Int, minorAtLeastOne: shift) }) + self.storage.withUnsafeMutableBufferPointer({ NBK.SUI.bitshiftRight(&$0, major: 0 as Int, minorAtLeastOne: shift) }) } self.storage.normalize() diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift index e5eb2a1c..6528b9e2 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift @@ -43,7 +43,7 @@ extension NBKFlexibleWidth.Magnitude { self.storage.reserveCapacity(self.storage.elements.count + 1) let carry = self.storage.withUnsafeMutableBufferPointer { - SUISS.multiplyFullWidth(&$0, by: multiplicand, add: addend) + NBK.SUISS.multiplyFullWidth(&$0, by: multiplicand, add: addend) } if !carry.isZero { diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift index 6984acb2..cc7584cd 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift @@ -80,6 +80,13 @@ extension NBKFlexibleWidth.Magnitude { @inlinable public func bitshiftedLeft(major: Int) -> Self { var result = self; result.bitshiftLeft(major: major); return result } +} + +//=----------------------------------------------------------------------------= +// MARK: + Left x Algorithms +//=----------------------------------------------------------------------------= + +extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= // MARK: Transformations x Int x Private @@ -88,7 +95,7 @@ extension NBKFlexibleWidth.Magnitude { /// Performs a left shift. /// /// - Parameters: - /// - major: `0 <= major < self.endIndex` + /// - major: `0 <= major` /// - minor: `1 <= minor < UInt.bitWidth` /// @inlinable mutating func bitshiftLeft(major: Int, minorAtLeastOne minor: Int) { @@ -102,14 +109,14 @@ extension NBKFlexibleWidth.Magnitude { self.storage.resize(minCount: self.storage.elements.count + major + rollover) self.storage.withUnsafeMutableBufferPointer { - SUI.bitshiftLeft(&$0, major: major, minorAtLeastOne: minor) + NBK.SUI.bitshiftLeft(&$0, major: major, minorAtLeastOne: minor) } } /// Performs a left shift. /// /// - Parameters: - /// - major: `1 <= major < self.endIndex` + /// - major: `1 <= major` /// @inlinable mutating func bitshiftLeft(majorAtLeastOne major: Int) { defer { @@ -121,7 +128,7 @@ extension NBKFlexibleWidth.Magnitude { self.storage.resize(minCount: self.storage.elements.count + major) self.storage.withUnsafeMutableBufferPointer { - SUI.bitshiftLeft(&$0, majorAtLeastOne: major) + NBK.SUI.bitshiftLeft(&$0, majorAtLeastOne: major) } } } @@ -139,7 +146,7 @@ extension NBKFlexibleWidth.Magnitude { @inlinable public static func >>=(lhs: inout Self, rhs: some BinaryInteger) { lhs.bitshiftRightSmart(by: NBK.initOrBitCast(clamping: rhs, as: Int.self)) } - + @inlinable public static func >>(lhs: Self, rhs: some BinaryInteger) -> Self { var lhs = lhs; lhs >>= rhs; return lhs } @@ -194,6 +201,13 @@ extension NBKFlexibleWidth.Magnitude { @inlinable public func bitshiftedRight(major: Int) -> Self { var result = self; result.bitshiftRight(major: major); return result } +} + +//=----------------------------------------------------------------------------= +// MARK: + Right x Algorithms +//=----------------------------------------------------------------------------= + +extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= // MARK: Transformations x Int x Private @@ -202,7 +216,7 @@ extension NBKFlexibleWidth.Magnitude { /// Performs an unsigned right shift. /// /// - Parameters: - /// - major: `1 <= major < self.endIndex` + /// - major: `1 <= major` /// - minor: `0 <= minor < UInt.bitWidth` /// @inlinable mutating func bitshiftRight(major: Int, minorAtLeastOne minor: Int) { @@ -218,7 +232,7 @@ extension NBKFlexibleWidth.Magnitude { } //=--------------------------------------= self.storage.withUnsafeMutableBufferPointer { - SUI.bitshiftRight(&$0, major: major, minorAtLeastOne: minor) + NBK.SUI.bitshiftRight(&$0, major: major, minorAtLeastOne: minor) } self.storage.resize(maxCount: maxCount) @@ -227,7 +241,7 @@ extension NBKFlexibleWidth.Magnitude { /// Performs an unsigned right shift. /// /// - Parameters: - /// - major: `1 <= major < self.endIndex` + /// - major: `1 <= major` /// @inlinable mutating func bitshiftRight(majorAtLeastOne major: Int) { defer { @@ -239,7 +253,7 @@ extension NBKFlexibleWidth.Magnitude { } //=--------------------------------------= self.storage.withUnsafeMutableBufferPointer { - SUI.bitshiftRight(&$0, majorAtLeastOne: major) + NBK.SUI.bitshiftRight(&$0, majorAtLeastOne: major) } self.storage.resize(maxCount: self.storage.elements.count - major) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift index 20124861..612cee03 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift @@ -60,7 +60,7 @@ extension NBKFlexibleWidth.Magnitude { self.storage.resize(minCount: index + 1) defer{ self.storage.normalize() } return self.storage.withUnsafeMutableBufferPointer { - SUISS.decrement(&$0, by: other, at: index).overflow + NBK.SUISS.decrement(&$0, by: other, at: index).overflow } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift index 3488dcdb..2ee67bd0 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift @@ -60,7 +60,7 @@ extension NBKFlexibleWidth.Magnitude { self.storage.resize(minCount: other.storage.elements.count + index) defer{ self.storage.normalize() } return self.storage.withUnsafeMutableBufferPointer { - SUISS.decrement(&$0, by: other.storage.elements, at: index).overflow + NBK.SUISS.decrement(&$0, by: other.storage.elements, at: index).overflow } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words+Collection.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words+Collection.swift new file mode 100644 index 00000000..1e0959d1 --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words+Collection.swift @@ -0,0 +1,57 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Double Width x Words x Collection +//*============================================================================* +//=----------------------------------------------------------------------------= +// MARK: + Elements +//=----------------------------------------------------------------------------= + +extension NBKFlexibleWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Accessors + //=------------------------------------------------------------------------= + + /// The least significant word. + /// + /// - Note: This member is required by `Swift.BinaryInteger`. + /// + @inlinable public var _lowWord: UInt { + self.first as UInt + } + + /// The least significant word. + @inlinable public var first: UInt { + self.withUnsafeBufferPointer({ $0[0] }) + } + + /// The most significant word. + @inlinable public var last: UInt { + self.withUnsafeBufferPointer({ $0[$0.count - 1] }) + } +} + +//=----------------------------------------------------------------------------= +// MARK: + Elements x Subscripts +//=----------------------------------------------------------------------------= + +extension NBKFlexibleWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Accessors + //=------------------------------------------------------------------------= + + @inlinable public subscript(index: Int) -> UInt { + index < self.storage.elements.endIndex ? self.storage.elements[index] : 0 as UInt + } +} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift index efc46d3a..89f18aee 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift @@ -42,30 +42,4 @@ extension NBKFlexibleWidth.Magnitude { @inlinable public var words: ContiguousArray { _read { yield self.storage.elements } } - - //=------------------------------------------------------------------------= - // MARK: Accessors - //=------------------------------------------------------------------------= - - /// The least significant word. - /// - /// - Note: This member is required by `Swift.BinaryInteger`. - /// - @inlinable public var _lowWord: UInt { - self.first as UInt - } - - /// The least significant word. - @inlinable public var first: UInt { - self.withUnsafeBufferPointer({ $0[0] }) - } - - /// The most significant word. - @inlinable public var last: UInt { - self.withUnsafeBufferPointer({ $0[$0.count - 1] }) - } - - @inlinable subscript(index: Int) -> UInt { - index < self.storage.elements.endIndex ? self.storage.elements[index] : 0 as UInt - } } diff --git a/Sources/NBKFlexibleWidthKit/Private/Aliases.swift b/Sources/NBKFlexibleWidthKit/Private/Aliases.swift deleted file mode 100644 index 37244731..00000000 --- a/Sources/NBKFlexibleWidthKit/Private/Aliases.swift +++ /dev/null @@ -1,26 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Aliases -//*============================================================================* - -@usableFromInline typealias SBI = NBK.StrictBinaryInteger where -Base: RandomAccessCollection, Base.Element: NBKCoreInteger & NBKUnsignedInteger - -@usableFromInline typealias SBISS = NBK.StrictBinaryInteger.SubSequence where -Base: RandomAccessCollection, Base.Element: NBKCoreInteger & NBKUnsignedInteger - -@usableFromInline typealias SUI = NBK.StrictUnsignedInteger where -Base: RandomAccessCollection, Base.Element: NBKCoreInteger & NBKUnsignedInteger - -@usableFromInline typealias SUISS = NBK.StrictUnsignedInteger.SubSequence where -Base: RandomAccessCollection, Base.Element: NBKCoreInteger & NBKUnsignedInteger diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Shifts.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Shifts.swift index e0b521ca..68e40639 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Shifts.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Shifts.swift @@ -113,6 +113,11 @@ final class NBKFlexibleWidthTestsOnShiftsAsUIntXL: XCTestCase { XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) >> -64, T(x64:[0, 1, 2, 3, 4] as X)) } + func testBitshiftingLeftByMoreThanBitWidthDoesNotTrap() { + NBKAssertShiftLeft (T(x64:[1] as X), (UInt.bitWidth + 1), T(x64:[0, 2] as X)) + NBKAssertShiftRight(T(x64:[1] as X), -(UInt.bitWidth + 1), T(x64:[0, 2] as X)) + } + func testBitshiftingRightDoesNotTrap() { XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) >> Int.max, T.zero) XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) << Int.min, T.zero) @@ -157,15 +162,17 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual({ var lhs = lhs; lhs.bitshiftLeftSmart(by: rhs); return lhs }(), result, file: file, line: line) XCTAssertEqual({ var lhs = lhs; lhs.bitshiftRightSmart(by: -rhs); return lhs }(), result, file: file, line: line) //=------------------------------------------= - if 0 ..< lhs.bitWidth ~= rhs { + if major >= 0, minor >= 0 { XCTAssertEqual(lhs.bitshiftedLeft(by: rhs), result, file: file, line: line) XCTAssertEqual({ var lhs = lhs; lhs.bitshiftLeft(by: rhs); return lhs }(), result, file: file, line: line) - + } + + if major >= 0, minor >= 0 { XCTAssertEqual(lhs.bitshiftedLeft(major: major, minor: minor), result, file: file, line: line) XCTAssertEqual({ var lhs = lhs; lhs.bitshiftLeft(major: major, minor: minor); return lhs }(), result, file: file, line: line) } - //=------------------------------------------= - if 0 ..< lhs.bitWidth ~= rhs, minor.isZero { + + if major >= 0, minor == 0 { XCTAssertEqual(lhs.bitshiftedLeft(major: major), result, file: file, line: line) XCTAssertEqual({ var lhs = lhs; lhs.bitshiftLeft(major: major); return lhs }(), result, file: file, line: line) } @@ -189,15 +196,17 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual({ var lhs = lhs; lhs.bitshiftRightSmart(by: rhs); return lhs }(), result, file: file, line: line) XCTAssertEqual({ var lhs = lhs; lhs.bitshiftLeftSmart(by: -rhs); return lhs }(), result, file: file, line: line) //=------------------------------------------= - if 0 ..< lhs.bitWidth ~= rhs { + if major >= 0, minor >= 0 { XCTAssertEqual(lhs.bitshiftedRight(by: rhs), result, file: file, line: line) XCTAssertEqual({ var lhs = lhs; lhs.bitshiftRight(by: rhs); return lhs }(), result, file: file, line: line) - + } + + if major >= 0, minor >= 0 { XCTAssertEqual(lhs.bitshiftedRight(major: major, minor: minor), result, file: file, line: line) XCTAssertEqual({ var lhs = lhs; lhs.bitshiftRight(major: major, minor: minor); return lhs }(), result, file: file, line: line) } - //=------------------------------------------= - if 0 ..< lhs.bitWidth ~= rhs, minor.isZero { + + if major >= 0, minor == 0 { XCTAssertEqual(lhs.bitshiftedRight(major: major), result, file: file, line: line) XCTAssertEqual({ var lhs = lhs; lhs.bitshiftRight(major: major); return lhs }(), result, file: file, line: line) } diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Words.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Words.swift index b0673b7b..aadb21d1 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Words.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Words.swift @@ -101,6 +101,19 @@ final class NBKFlexibleWidthTestsOnWordsAsUIntXL: XCTestCase { NBKAssertToWords(T(x32:[1, 2, 3, 4, 5, 6, 7, 0] as Y), [1, 2, 3, 4, 5, 6, 7 ]) NBKAssertToWords(T(x32:[1, 2, 3, 4, 5, 6, 7, 8] as Y), [1, 2, 3, 4, 5, 6, 7, 8]) } + + //=------------------------------------------------------------------------= + // MARK: Tests x Miscellaneous + //=------------------------------------------------------------------------= + + func testSubscriptSignExtension() { + XCTAssertEqual(T(words:[1, 2, 3, 4] as W)[Int( 0)], 1 as UInt) + XCTAssertEqual(T(words:[1, 2, 3, 4] as W)[Int( 1)], 2 as UInt) + XCTAssertEqual(T(words:[1, 2, 3, 4] as W)[Int( 2)], 3 as UInt) + XCTAssertEqual(T(words:[1, 2, 3, 4] as W)[Int( 3)], 4 as UInt) + XCTAssertEqual(T(words:[1, 2, 3, 4] as W)[Int( 4)], 0 as UInt) + XCTAssertEqual(T(words:[1, 2, 3, 4] as W)[Int.max], 0 as UInt) + } } //*============================================================================* From c9b76e4f1110d386bcd2c1c6ca319491fca02803 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Mon, 2 Oct 2023 15:31:50 +0200 Subject: [PATCH 086/133] =?UTF-8?q?[NBKSignedKit]=20Cleanup=20and=20Static?= =?UTF-8?q?BigInt=20fix=E2=84=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Sources/NBKSignedKit/NBKSigned+Literals.swift | 23 +++++++++----- .../NBKSigned+Literals.swift | 31 +++++++++++++++++-- 2 files changed, 45 insertions(+), 9 deletions(-) diff --git a/Sources/NBKSignedKit/NBKSigned+Literals.swift b/Sources/NBKSignedKit/NBKSigned+Literals.swift index 15e7beff..1eb0a191 100644 --- a/Sources/NBKSignedKit/NBKSigned+Literals.swift +++ b/Sources/NBKSignedKit/NBKSigned+Literals.swift @@ -27,13 +27,18 @@ extension NBKSigned { } @inlinable init?(exactlyIntegerLiteral source: StaticBigInt) { - let isLessThanZero = source.signum() == -1 as Int - guard var magnitude = Magnitude(words: NBKStaticBigInt(source)) else { return nil } - //=--------------------------------------= - if isLessThanZero { - magnitude.formTwosComplement() + let isLessThanZero = source.signum() == -1 + + // TODO: a better solution than this mess + let magnitude = NBK.withUnsafeTemporaryAllocation(copying: NBKStaticBigInt(source)) { words in + if isLessThanZero { + NBK.SBISS.formTwosComplement(&words) + } + + return Magnitude(words: words) } - //=--------------------------------------= + + guard let magnitude else { return nil } self.init(sign: NBK.Sign(isLessThanZero), magnitude: magnitude) } @@ -43,9 +48,13 @@ extension NBKSigned { self.init(source) } + @inlinable init?(exactlyIntegerLiteral source: Int) { + self.init(exactly: source) + } + #endif //=------------------------------------------------------------------------= - // MARK: Details x String Literal Type + // MARK: Initializers x String Literal Type //=------------------------------------------------------------------------= /// Creates a new instance from the given string literal. diff --git a/Tests/NBKSignedKitTests/NBKSigned+Literals.swift b/Tests/NBKSignedKitTests/NBKSigned+Literals.swift index 1728c450..a9cf811c 100644 --- a/Tests/NBKSignedKitTests/NBKSigned+Literals.swift +++ b/Tests/NBKSignedKitTests/NBKSigned+Literals.swift @@ -18,6 +18,33 @@ private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] +//*============================================================================* +// MARK: * NBK x Signed x Literals +//*============================================================================* + +final class NBKSignedTestsOnLiterals: XCTestCase { + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testFromIntegerLiteralAsSInt32() { + XCTAssertEqual(NBKSigned(exactlyIntegerLiteral: 4294967296), nil) + XCTAssertEqual(NBKSigned(exactlyIntegerLiteral: 4294967295), NBKSigned.max) + XCTAssertEqual(NBKSigned(exactlyIntegerLiteral: -4294967295), NBKSigned.min) + XCTAssertEqual(NBKSigned(exactlyIntegerLiteral: -4294967296), nil) + } + + func testFromIntegerLiteralAsSInt64() { + #if SBI && swift(>=5.8) + XCTAssertEqual(NBKSigned(exactlyIntegerLiteral: 18446744073709551616), nil) + XCTAssertEqual(NBKSigned(exactlyIntegerLiteral: 18446744073709551615), NBKSigned.max) + XCTAssertEqual(NBKSigned(exactlyIntegerLiteral: -18446744073709551615), NBKSigned.min) + XCTAssertEqual(NBKSigned(exactlyIntegerLiteral: -18446744073709551616), nil) + #endif + } +} + //*============================================================================* // MARK: * NBK x Signed x Literals x SIntXL //*============================================================================* @@ -77,8 +104,8 @@ final class NBKSignedTestsOnLiteralsAsSIntXL: XCTestCase { XCTAssertEqual(T(exactlyIntegerLiteral: (-00057896044618658097711785492504343953926634992332820282019728792003956564819968)), T.min256 / 2 - 1) XCTAssertEqual(T(exactlyIntegerLiteral: (-00057896044618658097711785492504343953926634992332820282019728792003956564819969)), T.min256 / 2 - 2) #else - XCTAssertEqual( T(integerLiteral: Int.max), T(M(x64:[UInt64(UInt.max / 2 + 0), 0, 0, 0] as X))) - XCTAssertEqual( T(integerLiteral: Int.min), -T(M(x64:[UInt64(UInt.max / 2 + 1), 0, 0, 0] as X))) + XCTAssertEqual(T(integerLiteral: Int.max), T(M(x64:[UInt64(UInt.max / 2 + 0), 0, 0, 0] as X))) + XCTAssertEqual(T(integerLiteral: Int.min), -T(M(x64:[UInt64(UInt.max / 2 + 1), 0, 0, 0] as X))) #endif } From df86d3036dbb67526bdb04d095ba8cf0d5365f70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Tue, 3 Oct 2023 19:21:52 +0200 Subject: [PATCH 087/133] [NBKSigned] StaticBigInt (#97). --- Sources/NBKSignedKit/NBKSigned+Literals.swift | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/Sources/NBKSignedKit/NBKSigned+Literals.swift b/Sources/NBKSignedKit/NBKSigned+Literals.swift index 1eb0a191..6cf22bcf 100644 --- a/Sources/NBKSignedKit/NBKSigned+Literals.swift +++ b/Sources/NBKSignedKit/NBKSigned+Literals.swift @@ -27,18 +27,8 @@ extension NBKSigned { } @inlinable init?(exactlyIntegerLiteral source: StaticBigInt) { - let isLessThanZero = source.signum() == -1 - - // TODO: a better solution than this mess - let magnitude = NBK.withUnsafeTemporaryAllocation(copying: NBKStaticBigInt(source)) { words in - if isLessThanZero { - NBK.SBISS.formTwosComplement(&words) - } - - return Magnitude(words: words) - } - - guard let magnitude else { return nil } + let isLessThanZero = source.signum() == -1 as Int + guard let magnitude = Magnitude(words: NBK.MaybeTwosComplement(NBKStaticBigInt(source), formTwosComplement: isLessThanZero)) else { return nil } self.init(sign: NBK.Sign(isLessThanZero), magnitude: magnitude) } From 91df2332f123e9f567077712a5747ec1844aaf75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Tue, 3 Oct 2023 19:39:46 +0200 Subject: [PATCH 088/133] [NBKSigned] Cleanup. --- Sources/NBKSignedKit/NBKSigned+Literals.swift | 6 +++--- Sources/NBKSignedKit/NBKSigned.swift | 19 +++++++++++++++++++ Tests/NBKSignedKitTests/NBKSigned+Text.swift | 5 +++++ 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/Sources/NBKSignedKit/NBKSigned+Literals.swift b/Sources/NBKSignedKit/NBKSigned+Literals.swift index 6cf22bcf..60635a9f 100644 --- a/Sources/NBKSignedKit/NBKSigned+Literals.swift +++ b/Sources/NBKSignedKit/NBKSigned+Literals.swift @@ -22,12 +22,12 @@ extension NBKSigned { @inlinable public init(integerLiteral source: StaticBigInt) { if let value = Self(exactlyIntegerLiteral: source) { self = value } else { - preconditionFailure("\(Self.self) cannot represent \(source)") + preconditionFailure("\(Self.description) cannot represent \(source)") } } @inlinable init?(exactlyIntegerLiteral source: StaticBigInt) { - let isLessThanZero = source.signum() == -1 as Int + let isLessThanZero: Bool = source.signum() == -1 as Int guard let magnitude = Magnitude(words: NBK.MaybeTwosComplement(NBKStaticBigInt(source), formTwosComplement: isLessThanZero)) else { return nil } self.init(sign: NBK.Sign(isLessThanZero), magnitude: magnitude) } @@ -69,7 +69,7 @@ extension NBKSigned { /// @inlinable public init(stringLiteral source: StaticString) { if let value = Self(exactlyStringLiteral: source) { self = value } else { - preconditionFailure("\(Self.self) cannot represent \(source)") + preconditionFailure("\(Self.description) cannot represent \(source)") } } diff --git a/Sources/NBKSignedKit/NBKSigned.swift b/Sources/NBKSignedKit/NBKSigned.swift index 78bf3a50..16a226e1 100644 --- a/Sources/NBKSignedKit/NBKSigned.swift +++ b/Sources/NBKSignedKit/NBKSigned.swift @@ -53,6 +53,25 @@ Hashable, Sendable, SignedNumeric { public typealias Digit = NBKSigned + //=------------------------------------------------------------------------= + // MARK: Meta Data + //=------------------------------------------------------------------------= + + /// A `description` of this type. + /// + /// ``` + /// ┌────────────────── → ─────────────────── = ───────┐ + /// │ type │ description │ a.k.a │ + /// ├────────────────── → ─────────────────── = ───────┤ + /// │ NBKSigned │ "NBKSigned" │ SInt │ + /// │ NBKSigned │ "NBKSigned" │ SIntXL │ + /// └────────────────── → ─────────────────── = ───────┘ + /// ``` + /// + @inlinable public static var description: String { + String(describing: Self.self) + } + //=------------------------------------------------------------------------= // MARK: State //=------------------------------------------------------------------------= diff --git a/Tests/NBKSignedKitTests/NBKSigned+Text.swift b/Tests/NBKSignedKitTests/NBKSigned+Text.swift index ef7b0a01..ec4cfe6b 100644 --- a/Tests/NBKSignedKitTests/NBKSigned+Text.swift +++ b/Tests/NBKSignedKitTests/NBKSigned+Text.swift @@ -41,6 +41,11 @@ final class NBKSignedTestsOnText: XCTestCase { XCTAssertEqual("10", String(describing: T(10))) } + func testMetaTypeDescriptionCouldUseSomeLove() { + XCTAssertEqual("NBKSigned", NBKSigned .description) + XCTAssertEqual("NBKSigned", NBKSigned.description) + } + //=------------------------------------------------------------------------= // MARK: Tests x Decode //=------------------------------------------------------------------------= From 8264de2295db8b3ff0c564ac9da75793c1d722f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Wed, 4 Oct 2023 07:44:26 +0200 Subject: [PATCH 089/133] [NBKSignedKit] Req. `init?(words:isSigned:)` (#89). --- Sources/NBKSignedKit/NBKSigned+Literals.swift | 4 +- Sources/NBKSignedKit/NBKSigned+Numbers.swift | 2 + Sources/NBKSignedKit/NBKSigned+Words.swift | 31 +++++++ Sources/NBKSignedKit/NBKSigned.swift | 4 + .../NBKSigned+Negation.swift | 4 + .../NBKSignedKitTests/NBKSigned+Numbers.swift | 4 + Tests/NBKSignedKitTests/NBKSigned+Text.swift | 4 + Tests/NBKSignedKitTests/NBKSigned+Words.swift | 84 +++++++++++++++++++ Tests/NBKSignedKitTests/NBKSigned.swift | 4 + 9 files changed, 138 insertions(+), 3 deletions(-) create mode 100644 Sources/NBKSignedKit/NBKSigned+Words.swift create mode 100644 Tests/NBKSignedKitTests/NBKSigned+Words.swift diff --git a/Sources/NBKSignedKit/NBKSigned+Literals.swift b/Sources/NBKSignedKit/NBKSigned+Literals.swift index 60635a9f..10ed8dbc 100644 --- a/Sources/NBKSignedKit/NBKSigned+Literals.swift +++ b/Sources/NBKSignedKit/NBKSigned+Literals.swift @@ -27,9 +27,7 @@ extension NBKSigned { } @inlinable init?(exactlyIntegerLiteral source: StaticBigInt) { - let isLessThanZero: Bool = source.signum() == -1 as Int - guard let magnitude = Magnitude(words: NBK.MaybeTwosComplement(NBKStaticBigInt(source), formTwosComplement: isLessThanZero)) else { return nil } - self.init(sign: NBK.Sign(isLessThanZero), magnitude: magnitude) + self.init(words: NBKStaticBigInt(source)) } #else diff --git a/Sources/NBKSignedKit/NBKSigned+Numbers.swift b/Sources/NBKSignedKit/NBKSigned+Numbers.swift index efcec0d7..137f2c9d 100644 --- a/Sources/NBKSignedKit/NBKSigned+Numbers.swift +++ b/Sources/NBKSignedKit/NBKSigned+Numbers.swift @@ -56,6 +56,8 @@ extension NBKSigned { //=------------------------------------------------------------------------= // MARK: Initializers x Binary Integer //=------------------------------------------------------------------------= + // NOTE: Using init(sign:magnitude:) is more efficient than init(words:). + //=------------------------------------------------------------------------= @inlinable public init(_ source: some BinaryInteger) { if let value = Self(exactly: source) { self = value } else { diff --git a/Sources/NBKSignedKit/NBKSigned+Words.swift b/Sources/NBKSignedKit/NBKSigned+Words.swift new file mode 100644 index 00000000..063b412c --- /dev/null +++ b/Sources/NBKSignedKit/NBKSigned+Words.swift @@ -0,0 +1,31 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Signed x Words +//*============================================================================* + +extension NBKSigned { + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + @inlinable public init?(words: some RandomAccessCollection) { + self.init(words: words, isSigned: true) + } + + @inlinable public init?(words: some RandomAccessCollection, isSigned: Bool) { + let isLessThanZero: Bool = isSigned && words.last?.mostSignificantBit == true + guard let magnitude = Magnitude(words: NBK.MaybeTwosComplement(words, formTwosComplement: isLessThanZero)) else { return nil } + self.init(sign: Sign(isLessThanZero), magnitude: magnitude) + } +} diff --git a/Sources/NBKSignedKit/NBKSigned.swift b/Sources/NBKSignedKit/NBKSigned.swift index 16a226e1..f48b6089 100644 --- a/Sources/NBKSignedKit/NBKSigned.swift +++ b/Sources/NBKSignedKit/NBKSigned.swift @@ -57,6 +57,10 @@ Hashable, Sendable, SignedNumeric { // MARK: Meta Data //=------------------------------------------------------------------------= + @inlinable public static var isSigned: Bool { + true + } + /// A `description` of this type. /// /// ``` diff --git a/Tests/NBKSignedKitTests/NBKSigned+Negation.swift b/Tests/NBKSignedKitTests/NBKSigned+Negation.swift index d28d0c76..e277bd28 100644 --- a/Tests/NBKSignedKitTests/NBKSigned+Negation.swift +++ b/Tests/NBKSignedKitTests/NBKSigned+Negation.swift @@ -12,6 +12,10 @@ import NBKSignedKit import XCTest +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + //*============================================================================* // MARK: * NBK x Signed x Negation //*============================================================================* diff --git a/Tests/NBKSignedKitTests/NBKSigned+Numbers.swift b/Tests/NBKSignedKitTests/NBKSigned+Numbers.swift index 324606b2..af5d94ba 100644 --- a/Tests/NBKSignedKitTests/NBKSigned+Numbers.swift +++ b/Tests/NBKSignedKitTests/NBKSigned+Numbers.swift @@ -13,6 +13,10 @@ import NBKCoreKit import NBKSignedKit import XCTest +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + //*============================================================================* // MARK: * NBK x Signed x Numbers //*============================================================================* diff --git a/Tests/NBKSignedKitTests/NBKSigned+Text.swift b/Tests/NBKSignedKitTests/NBKSigned+Text.swift index ec4cfe6b..e3ebbf11 100644 --- a/Tests/NBKSignedKitTests/NBKSigned+Text.swift +++ b/Tests/NBKSignedKitTests/NBKSigned+Text.swift @@ -12,6 +12,10 @@ import NBKSignedKit import XCTest +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + //*============================================================================* // MARK: * NBK x Signed x Text //*============================================================================* diff --git a/Tests/NBKSignedKitTests/NBKSigned+Words.swift b/Tests/NBKSignedKitTests/NBKSigned+Words.swift new file mode 100644 index 00000000..2b144918 --- /dev/null +++ b/Tests/NBKSignedKitTests/NBKSigned+Words.swift @@ -0,0 +1,84 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +import NBKSignedKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Signed x Words +//*============================================================================* + +final class NBKSignedTestsOnWords: XCTestCase { + + typealias T = NBKSigned + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testFromWords() { + NBKAssertFromWordsIsSigned([ ] as W, true, T(sign: .plus, magnitude: 0)) + NBKAssertFromWordsIsSigned([ ] as W, false, T(sign: .plus, magnitude: 0)) + NBKAssertFromWordsIsSigned([ 0 ] as W, true, T(sign: .plus, magnitude: 0)) + NBKAssertFromWordsIsSigned([ 0 ] as W, false, T(sign: .plus, magnitude: 0)) + NBKAssertFromWordsIsSigned([~0 ] as W, true, T(sign: .minus, magnitude: 1)) + NBKAssertFromWordsIsSigned([~0 ] as W, false, T(sign: .plus, magnitude: ~0)) + NBKAssertFromWordsIsSigned([~0, 0] as W, true, T(sign: .plus, magnitude: ~0)) + NBKAssertFromWordsIsSigned([~0, 0] as W, false, T(sign: .plus, magnitude: ~0)) + NBKAssertFromWordsIsSigned([ 1, ~0] as W, true, T(sign: .minus, magnitude: ~0)) + NBKAssertFromWordsIsSigned([ 1, ~0] as W, false, nil as T?) + + NBKAssertFromWordsIsSigned(W(repeating: 0, count: 2), true, 000 as T?) + NBKAssertFromWordsIsSigned(W(repeating: 1, count: 2), true, nil as T?) + NBKAssertFromWordsIsSigned(W(repeating: ~0, count: 2), true, -01 as T?) + NBKAssertFromWordsIsSigned(W(repeating: ~1, count: 2), true, nil as T?) + + NBKAssertFromWordsIsSigned(W(repeating: 0, count: 2), false, 000 as T?) + NBKAssertFromWordsIsSigned(W(repeating: 1, count: 2), false, nil as T?) + NBKAssertFromWordsIsSigned(W(repeating: ~0, count: 2), false, nil as T?) + NBKAssertFromWordsIsSigned(W(repeating: ~1, count: 2), false, nil as T?) + } +} + +//*============================================================================* +// MARK: * NBK x Signed x Words x Assertions +//*============================================================================* + +private func NBKAssertFromWords( +_ words: [UInt], _ integer: NBKSigned?, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + typealias T = NBKSigned + //=------------------------------------------= + NBKAssertIdentical( T(words: words), integer, file: file, line: line) + //NBKAssertIdentical(integer.flatMap({ T(words: $0.words) }), integer, file: file, line: line) +} + +private func NBKAssertFromWordsIsSigned( +_ words: [UInt], _ isSigned: Bool, _ integer: NBKSigned?, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + typealias T = NBKSigned + //=------------------------------------------= + if isSigned == T.isSigned { + NBKAssertFromWords(words, integer, file: file, line: line) + } + + NBKAssertIdentical( T(words: words, isSigned: isSigned), integer, file: file, line: line) + //NBKAssertIdentical(integer.flatMap({ T(words: $0.words, isSigned: isSigned) }), integer, file: file, line: line) +} + +#endif diff --git a/Tests/NBKSignedKitTests/NBKSigned.swift b/Tests/NBKSignedKitTests/NBKSigned.swift index 43a01323..ed449ea7 100644 --- a/Tests/NBKSignedKitTests/NBKSigned.swift +++ b/Tests/NBKSignedKitTests/NBKSigned.swift @@ -13,6 +13,10 @@ import NBKCoreKit import NBKSignedKit import XCTest +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + //*============================================================================* // MARK: * NBK x Signed //*============================================================================* From 954f580cc4d2add91cf38645c706eb9a28228573 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Wed, 4 Oct 2023 08:20:34 +0200 Subject: [PATCH 090/133] [NBKSignedKit] Words (#81). --- Sources/NBKSignedKit/NBKSigned+Words.swift | 78 +++++++++++++++++++ .../NBKFlexibleWidth+Words.swift | 6 +- Tests/NBKSignedKitTests/NBKSigned+Words.swift | 61 ++++++++++++++- 3 files changed, 140 insertions(+), 5 deletions(-) diff --git a/Sources/NBKSignedKit/NBKSigned+Words.swift b/Sources/NBKSignedKit/NBKSigned+Words.swift index 063b412c..a2b44808 100644 --- a/Sources/NBKSignedKit/NBKSigned+Words.swift +++ b/Sources/NBKSignedKit/NBKSigned+Words.swift @@ -28,4 +28,82 @@ extension NBKSigned { guard let magnitude = Magnitude(words: NBK.MaybeTwosComplement(words, formTwosComplement: isLessThanZero)) else { return nil } self.init(sign: Sign(isLessThanZero), magnitude: magnitude) } + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + @inlinable public var words: Words { + Words(self) + } + + //*========================================================================* + // MARK: * Words + //*========================================================================* + + @frozen public struct Words: RandomAccessCollection { + + //=--------------------------------------------------------------------= + // MARK: State + //=--------------------------------------------------------------------= + + public let count: Int + @usableFromInline let sign: UInt + @usableFromInline let base: NBK.MaybeTwosComplement + + //=--------------------------------------------------------------------= + // MARK: Initializers + //=--------------------------------------------------------------------= + + @inlinable init(_ source: NBKSigned) { + let isLessThanZero = (source.isLessThanZero) + self.sign = UInt(repeating: isLessThanZero) + self.base = NBK.MaybeTwosComplement(source.magnitude.words, formTwosComplement: isLessThanZero) + self.count = self.base.count + Int(bit:/**/self.base.last?.mostSignificantBit != isLessThanZero) + } + + //=--------------------------------------------------------------------= + // MARK: Accessors + //=--------------------------------------------------------------------= + + @inlinable public var startIndex: Int { + (0 as Int) + } + + @inlinable public var endIndex: Int { + self.count + } + + @inlinable public var indices: Range { + 0 as Int ..< self.count + } + + @inlinable public subscript(index: Int) -> UInt { + index < self.base.endIndex ? self.base[self.base.index(self.base.startIndex, offsetBy: index)] : self.sign + } + + //=--------------------------------------------------------------------= + // MARK: Utilities + //=--------------------------------------------------------------------= + + @inlinable public func distance(from start: Int, to end: Int) -> Int { + end - start + } + + @inlinable public func index(after index: Int) -> Int { + index + 1 as Int + } + + @inlinable public func index(before index: Int) -> Int { + index - 1 as Int + } + + @inlinable public func index(_ index: Int, offsetBy distance: Int) -> Int { + index + distance + } + + @inlinable public func index(_ index: Int, offsetBy distance: Int, limitedBy limit: Int) -> Int? { + NBK.arrayIndex(index, offsetBy: distance, limitedBy: limit) + } + } } diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Words.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Words.swift index aadb21d1..d4b7cacf 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Words.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Words.swift @@ -48,7 +48,7 @@ final class NBKFlexibleWidthTestsOnWordsAsUIntXL: XCTestCase { NBKAssertFromWordsIsSigned(Array([~0/2 + 0]), false, T(words:[~0/2 + 0])) } - func testWords() { + func testToWords() { NBKAssertToWords(T(words:[0 ]), [0 ]) NBKAssertToWords(T(words:[1 ]), [1 ]) NBKAssertToWords(T(words:[1, 2 ]), [1, 2 ]) @@ -62,7 +62,7 @@ final class NBKFlexibleWidthTestsOnWordsAsUIntXL: XCTestCase { NBKAssertToWords(T(words:[1, 2, 3, 4]), [1, 2, 3, 4]) } - func testWordsX64() throws { + func testToWordsX64() throws { guard MemoryLayout.size == MemoryLayout.size else { throw XCTSkip() } NBKAssertToWords(T(x64:[0 ] as X), [0 ]) @@ -78,7 +78,7 @@ final class NBKFlexibleWidthTestsOnWordsAsUIntXL: XCTestCase { NBKAssertToWords(T(x64:[1, 2, 3, 4] as X), [1, 2, 3, 4]) } - func testWordsX32() throws { + func testToWordsX32() throws { guard MemoryLayout.size == MemoryLayout.size else { throw XCTSkip() } NBKAssertToWords(T(x32:[0 ] as Y), [0 ]) diff --git a/Tests/NBKSignedKitTests/NBKSigned+Words.swift b/Tests/NBKSignedKitTests/NBKSigned+Words.swift index 2b144918..3f2746ea 100644 --- a/Tests/NBKSignedKitTests/NBKSigned+Words.swift +++ b/Tests/NBKSignedKitTests/NBKSigned+Words.swift @@ -51,6 +51,26 @@ final class NBKSignedTestsOnWords: XCTestCase { NBKAssertFromWordsIsSigned(W(repeating: ~0, count: 2), false, nil as T?) NBKAssertFromWordsIsSigned(W(repeating: ~1, count: 2), false, nil as T?) } + + func testToWords() { + NBKAssertElementsEqual(T(sign: .plus, magnitude: ~0/1 - 0).words, [~0/1 - 0, 0] as W) + NBKAssertElementsEqual(T(sign: .plus, magnitude: ~0/1 - 1).words, [~0/1 - 1, 0] as W) + NBKAssertElementsEqual(T(sign: .minus, magnitude: ~0/1 - 0).words, [ 0/1 + 1, ~0] as W) + NBKAssertElementsEqual(T(sign: .minus, magnitude: ~0/1 - 1).words, [ 0/1 + 2, ~0] as W) + + NBKAssertElementsEqual(T(sign: .plus, magnitude: ~0/2 + 2).words, [~0/2 + 2, 0] as W) + NBKAssertElementsEqual(T(sign: .plus, magnitude: ~0/2 + 1).words, [~0/2 + 1, 0] as W) + NBKAssertElementsEqual(T(sign: .plus, magnitude: ~0/2 + 0).words, [~0/2 + 0, ] as W) + + NBKAssertElementsEqual(T(sign: .minus, magnitude: ~0/2 + 2).words, [~0/2 + 0, ~0] as W) + NBKAssertElementsEqual(T(sign: .minus, magnitude: ~0/2 + 1).words, [~0/2 + 1, ] as W) + NBKAssertElementsEqual(T(sign: .minus, magnitude: ~0/2 + 0).words, [~0/2 + 2, ] as W) + + NBKAssertElementsEqual(T(sign: .plus, magnitude: 0/1 + 0).words, [ 0/1 + 0, ] as W) + NBKAssertElementsEqual(T(sign: .plus, magnitude: 0/1 + 1).words, [ 0/1 + 1, ] as W) + NBKAssertElementsEqual(T(sign: .minus, magnitude: 0/1 + 0).words, [ 0/1 + 0, ] as W) + NBKAssertElementsEqual(T(sign: .minus, magnitude: 0/1 + 1).words, [~0/1 + 0, ] as W) + } } //*============================================================================* @@ -64,7 +84,7 @@ file: StaticString = #file, line: UInt = #line) { typealias T = NBKSigned //=------------------------------------------= NBKAssertIdentical( T(words: words), integer, file: file, line: line) - //NBKAssertIdentical(integer.flatMap({ T(words: $0.words) }), integer, file: file, line: line) + NBKAssertIdentical(integer.flatMap({ T(words: $0.words) }), integer, file: file, line: line) } private func NBKAssertFromWordsIsSigned( @@ -78,7 +98,44 @@ file: StaticString = #file, line: UInt = #line) { } NBKAssertIdentical( T(words: words, isSigned: isSigned), integer, file: file, line: line) - //NBKAssertIdentical(integer.flatMap({ T(words: $0.words, isSigned: isSigned) }), integer, file: file, line: line) + NBKAssertIdentical(integer.flatMap({ T(words: $0.words, isSigned: isSigned) }), integer, file: file, line: line) +} + +//=----------------------------------------------------------------------------= +// MARK: + Collection +//=----------------------------------------------------------------------------= + +private func NBKAssertElementsEqual( +_ base: Base, _ expectation: [Base.Element], +file: StaticString = #file, line: UInt = #line) where Base.Element: Equatable { + //=------------------------------------------= + XCTAssertEqual(Array(base), expectation, file: file, line: line) + XCTAssertEqual(Array(base.indices.map({ base[$0] })), expectation, file: file, line: line) + //=------------------------------------------= + for distance in 0 ..< base.count { + //=--------------------------------------= + let index0 = base.index(base.startIndex, offsetBy: distance + 0) + let index1 = base.index(base.startIndex, offsetBy: distance + 1) + //=--------------------------------------= + XCTAssertEqual(base[index0],expectation[distance], file: file, line: line) + //=--------------------------------------= + XCTAssertEqual(base.index(before: index1), index0, file: file, line: line) + XCTAssertEqual(base.index(after: index0), index1, file: file, line: line) + + XCTAssertEqual(base.index(base.endIndex, offsetBy: distance + 0 - base.count), index0, file: file, line: line) + XCTAssertEqual(base.index(base.endIndex, offsetBy: distance + 1 - base.count), index1, file: file, line: line) + //=--------------------------------------= + XCTAssertEqual(base.distance(from: base.startIndex, to: index0), distance + 0, file: file, line: line) + XCTAssertEqual(base.distance(from: base.startIndex, to: index1), distance + 1, file: file, line: line) + + XCTAssertEqual(base.distance(from: index0, to: base.endIndex), base.count - distance - 0, file: file, line: line) + XCTAssertEqual(base.distance(from: index1, to: base.endIndex), base.count - distance - 1, file: file, line: line) + } + //=------------------------------------------= + for distance in 0 ... base.count + 1 { + XCTAssert(base.prefix(distance).elementsEqual(expectation.prefix(distance)), file: file, line: line) + XCTAssert(base.suffix(distance).elementsEqual(expectation.suffix(distance)), file: file, line: line) + } } #endif From 734f9570766c32301c7ccd4ccc89b6dde1d4a702 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Wed, 4 Oct 2023 09:13:31 +0200 Subject: [PATCH 091/133] [NBKSignedKit] Cleanup. Normalization. --- Sources/NBKSignedKit/NBKSigned+Numbers.swift | 4 +- Sources/NBKSignedKit/NBKSigned.swift | 12 +++- .../NBKFlexibleWidth+Words.swift | 43 ++++++++++++++- Tests/NBKSignedKitTests/NBKSigned+Words.swift | 36 +++++++----- Tests/NBKSignedKitTests/NBKSigned.swift | 55 +++++++++++++++---- 5 files changed, 118 insertions(+), 32 deletions(-) diff --git a/Sources/NBKSignedKit/NBKSigned+Numbers.swift b/Sources/NBKSignedKit/NBKSigned+Numbers.swift index 137f2c9d..284629ff 100644 --- a/Sources/NBKSignedKit/NBKSigned+Numbers.swift +++ b/Sources/NBKSignedKit/NBKSigned+Numbers.swift @@ -36,7 +36,7 @@ extension NBKSigned { let magnitude = Magnitude(digit: digit.magnitude) self.init(sign: sign, magnitude: magnitude) } - + //=------------------------------------------------------------------------= // MARK: Initializers x Magnitude //=------------------------------------------------------------------------= @@ -61,7 +61,7 @@ extension NBKSigned { @inlinable public init(_ source: some BinaryInteger) { if let value = Self(exactly: source) { self = value } else { - preconditionFailure("\(Self.self) cannot represent \(source)") + preconditionFailure("\(Self.description) cannot represent \(source)") } } diff --git a/Sources/NBKSignedKit/NBKSigned.swift b/Sources/NBKSignedKit/NBKSigned.swift index f48b6089..1101cb1a 100644 --- a/Sources/NBKSignedKit/NBKSigned.swift +++ b/Sources/NBKSignedKit/NBKSigned.swift @@ -65,7 +65,7 @@ Hashable, Sendable, SignedNumeric { /// /// ``` /// ┌────────────────── → ─────────────────── = ───────┐ - /// │ type │ description │ a.k.a │ + /// │ type │ description │ a.k.a. │ /// ├────────────────── → ─────────────────── = ───────┤ /// │ NBKSigned │ "NBKSigned" │ SInt │ /// │ NBKSigned │ "NBKSigned" │ SIntXL │ @@ -113,6 +113,16 @@ Hashable, Sendable, SignedNumeric { @inlinable public var normalizedSign: Sign { self.isNormal ? self.sign : Sign.plus } + + /// Turns negative zero into positive zero. + @inlinable public mutating func normalize() { + self.sign = self.normalizedSign + } + + /// Turns negative zero into positive zero. + @inlinable public func normalized() -> Self { + Self(sign: self.normalizedSign, magnitude: self.magnitude) + } } //*============================================================================* diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Words.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Words.swift index d4b7cacf..b0950f07 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Words.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Words.swift @@ -140,12 +140,49 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual(integer.flatMap({ T(words: $0.words, isSigned: isSigned) }), integer, file: file, line: line) } -private func NBKAssertToWords( +private func NBKAssertToWords( _ integer: T, _ words: [UInt], file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual(Array(integer.words), Array(words), file: file, line: line) - XCTAssertEqual(Array(integer.words.reversed()), Array(words.reversed()), file: file, line: line) + NBKAssertElementsEqual(integer.words, words, file: file, line: line) + NBKAssertFromWords(/*--------*/words, integer, file: file, line: line) +} + +//=----------------------------------------------------------------------------= +// MARK: + Collection +//=----------------------------------------------------------------------------= + +private func NBKAssertElementsEqual( +_ base: Base, _ expectation: [Base.Element], +file: StaticString = #file, line: UInt = #line) where Base.Element: Equatable { + //=------------------------------------------= + XCTAssertEqual(Array(base), expectation, file: file, line: line) + XCTAssertEqual(Array(base.indices.map({ base[$0] })), expectation, file: file, line: line) + //=------------------------------------------= + for distance in 0 ..< base.count { + //=--------------------------------------= + let index0 = base.index(base.startIndex, offsetBy: distance + 0) + let index1 = base.index(base.startIndex, offsetBy: distance + 1) + //=--------------------------------------= + XCTAssertEqual(base[index0],expectation[distance], file: file, line: line) + //=--------------------------------------= + XCTAssertEqual(base.index(before: index1), index0, file: file, line: line) + XCTAssertEqual(base.index(after: index0), index1, file: file, line: line) + + XCTAssertEqual(base.index(base.endIndex, offsetBy: distance + 0 - base.count), index0, file: file, line: line) + XCTAssertEqual(base.index(base.endIndex, offsetBy: distance + 1 - base.count), index1, file: file, line: line) + //=--------------------------------------= + XCTAssertEqual(base.distance(from: base.startIndex, to: index0), distance + 0, file: file, line: line) + XCTAssertEqual(base.distance(from: base.startIndex, to: index1), distance + 1, file: file, line: line) + + XCTAssertEqual(base.distance(from: index0, to: base.endIndex), base.count - distance - 0, file: file, line: line) + XCTAssertEqual(base.distance(from: index1, to: base.endIndex), base.count - distance - 1, file: file, line: line) + } + //=------------------------------------------= + for distance in 0 ... base.count + 1 { + XCTAssert(base.prefix(distance).elementsEqual(expectation.prefix(distance)), file: file, line: line) + XCTAssert(base.suffix(distance).elementsEqual(expectation.suffix(distance)), file: file, line: line) + } } #endif diff --git a/Tests/NBKSignedKitTests/NBKSigned+Words.swift b/Tests/NBKSignedKitTests/NBKSigned+Words.swift index 3f2746ea..6439b626 100644 --- a/Tests/NBKSignedKitTests/NBKSigned+Words.swift +++ b/Tests/NBKSignedKitTests/NBKSigned+Words.swift @@ -53,23 +53,23 @@ final class NBKSignedTestsOnWords: XCTestCase { } func testToWords() { - NBKAssertElementsEqual(T(sign: .plus, magnitude: ~0/1 - 0).words, [~0/1 - 0, 0] as W) - NBKAssertElementsEqual(T(sign: .plus, magnitude: ~0/1 - 1).words, [~0/1 - 1, 0] as W) - NBKAssertElementsEqual(T(sign: .minus, magnitude: ~0/1 - 0).words, [ 0/1 + 1, ~0] as W) - NBKAssertElementsEqual(T(sign: .minus, magnitude: ~0/1 - 1).words, [ 0/1 + 2, ~0] as W) + NBKAssertToWords(T(sign: .plus, magnitude: ~0/1 - 0), [~0/1 - 0, 0] as W) + NBKAssertToWords(T(sign: .plus, magnitude: ~0/1 - 1), [~0/1 - 1, 0] as W) + NBKAssertToWords(T(sign: .minus, magnitude: ~0/1 - 0), [ 0/1 + 1, ~0] as W) + NBKAssertToWords(T(sign: .minus, magnitude: ~0/1 - 1), [ 0/1 + 2, ~0] as W) - NBKAssertElementsEqual(T(sign: .plus, magnitude: ~0/2 + 2).words, [~0/2 + 2, 0] as W) - NBKAssertElementsEqual(T(sign: .plus, magnitude: ~0/2 + 1).words, [~0/2 + 1, 0] as W) - NBKAssertElementsEqual(T(sign: .plus, magnitude: ~0/2 + 0).words, [~0/2 + 0, ] as W) + NBKAssertToWords(T(sign: .plus, magnitude: ~0/2 + 2), [~0/2 + 2, 0] as W) + NBKAssertToWords(T(sign: .plus, magnitude: ~0/2 + 1), [~0/2 + 1, 0] as W) + NBKAssertToWords(T(sign: .plus, magnitude: ~0/2 + 0), [~0/2 + 0, ] as W) - NBKAssertElementsEqual(T(sign: .minus, magnitude: ~0/2 + 2).words, [~0/2 + 0, ~0] as W) - NBKAssertElementsEqual(T(sign: .minus, magnitude: ~0/2 + 1).words, [~0/2 + 1, ] as W) - NBKAssertElementsEqual(T(sign: .minus, magnitude: ~0/2 + 0).words, [~0/2 + 2, ] as W) + NBKAssertToWords(T(sign: .minus, magnitude: ~0/2 + 2), [~0/2 + 0, ~0] as W) + NBKAssertToWords(T(sign: .minus, magnitude: ~0/2 + 1), [~0/2 + 1, ] as W) + NBKAssertToWords(T(sign: .minus, magnitude: ~0/2 + 0), [~0/2 + 2, ] as W) - NBKAssertElementsEqual(T(sign: .plus, magnitude: 0/1 + 0).words, [ 0/1 + 0, ] as W) - NBKAssertElementsEqual(T(sign: .plus, magnitude: 0/1 + 1).words, [ 0/1 + 1, ] as W) - NBKAssertElementsEqual(T(sign: .minus, magnitude: 0/1 + 0).words, [ 0/1 + 0, ] as W) - NBKAssertElementsEqual(T(sign: .minus, magnitude: 0/1 + 1).words, [~0/1 + 0, ] as W) + NBKAssertToWords(T(sign: .plus, magnitude: 0/1 + 0), [ 0/1 + 0, ] as W) + NBKAssertToWords(T(sign: .plus, magnitude: 0/1 + 1), [ 0/1 + 1, ] as W) + NBKAssertToWords(T(sign: .minus, magnitude: 0/1 + 0), [ 0/1 + 0, ] as W) + NBKAssertToWords(T(sign: .minus, magnitude: 0/1 + 1), [~0/1 + 0, ] as W) } } @@ -101,6 +101,14 @@ file: StaticString = #file, line: UInt = #line) { NBKAssertIdentical(integer.flatMap({ T(words: $0.words, isSigned: isSigned) }), integer, file: file, line: line) } +private func NBKAssertToWords( +_ integer: NBKSigned, _ words: [UInt], +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + NBKAssertElementsEqual(integer.words, words, file: file, line: line) + NBKAssertFromWords(words, integer.normalized(), file: file, line: line) +} + //=----------------------------------------------------------------------------= // MARK: + Collection //=----------------------------------------------------------------------------= diff --git a/Tests/NBKSignedKitTests/NBKSigned.swift b/Tests/NBKSignedKitTests/NBKSigned.swift index ed449ea7..4a46e06a 100644 --- a/Tests/NBKSignedKitTests/NBKSigned.swift +++ b/Tests/NBKSignedKitTests/NBKSigned.swift @@ -37,18 +37,18 @@ final class NBKSignedTests: XCTestCase { XCTAssertEqual(T(sign: .minus, magnitude: 1).sign, .minus) } - func testIsNormal() { - XCTAssertEqual(T(sign: .plus , magnitude: 0).isNormal, true ) - XCTAssertEqual(T(sign: .plus , magnitude: 1).isNormal, true ) - XCTAssertEqual(T(sign: .minus, magnitude: 0).isNormal, false) - XCTAssertEqual(T(sign: .minus, magnitude: 1).isNormal, true ) + func testMagnitude() { + XCTAssertEqual(T(sign: .plus , magnitude: 0).magnitude, 0 as M) + XCTAssertEqual(T(sign: .plus , magnitude: 1).magnitude, 1 as M) + XCTAssertEqual(T(sign: .minus, magnitude: 0).magnitude, 0 as M) + XCTAssertEqual(T(sign: .minus, magnitude: 1).magnitude, 1 as M) } - func testNormalizedSign() { - XCTAssertEqual(T(sign: .plus , magnitude: 0).normalizedSign, .plus ) - XCTAssertEqual(T(sign: .plus , magnitude: 1).normalizedSign, .plus ) - XCTAssertEqual(T(sign: .minus, magnitude: 0).normalizedSign, .plus ) - XCTAssertEqual(T(sign: .minus, magnitude: 1).normalizedSign, .minus) + func testNormalized() { + NBKAssertNormalization(T(sign: .plus , magnitude: 0), true, .plus, 0 as M) + NBKAssertNormalization(T(sign: .plus , magnitude: 1), true, .plus, 1 as M) + NBKAssertNormalization(T(sign: .minus, magnitude: 0), false, .plus, 0 as M) + NBKAssertNormalization(T(sign: .minus, magnitude: 1), true, .minus, 1 as M) } } @@ -56,9 +56,40 @@ final class NBKSignedTests: XCTestCase { // MARK: * NBK x Signed x Assertions //*============================================================================* +private func NBKAssertNormalization( +_ integer: NBKSigned, _ isNormal: Bool, _ sign: NBKSigned.Sign, _ magnitude: M, +file: StaticString = #file, line: UInt = #line) { + + brr: do { + XCTAssertEqual(integer.isNormal, isNormal, file: file, line: line) + XCTAssertEqual(integer.normalizedSign, sign, file: file, line: line) + XCTAssertEqual(integer.magnitude, magnitude, file: file, line: line) + } + + brr: do { + XCTAssertEqual(integer.normalized().isNormal, true, file: file, line: line) + XCTAssertEqual(integer.normalized().sign, sign, file: file, line: line) + XCTAssertEqual(integer.normalized().magnitude, magnitude, file: file, line: line) + } + + brr: do { + var integer = integer; integer.normalize() + XCTAssertEqual(integer.isNormal, true, file: file, line: line) + XCTAssertEqual(integer.sign, sign, file: file, line: line) + XCTAssertEqual(integer.magnitude, magnitude, file: file, line: line) + } +} + +//=----------------------------------------------------------------------------= +// MARK: + Shared +//=----------------------------------------------------------------------------= + func NBKAssertIdentical(_ lhs: NBKSigned?, _ rhs: NBKSigned?, file: StaticString = #file, line: UInt = #line) { - let success: Bool = lhs?.sign == rhs?.sign && lhs?.magnitude == rhs?.magnitude - func description(of x: NBKSigned?) -> String { x.map({ "\($0.sign)\($0.magnitude)" }) ?? "nil" } + func description(of integer: NBKSigned?) -> String { + integer.map({ "\($0.sign)\($0.magnitude)" }) ?? "nil" + } + + let success: Bool = lhs?.sign == rhs?.sign && lhs?.magnitude == rhs?.magnitude XCTAssert(success, "(\(description(of: lhs)) is not identical to \(description(of: rhs))", file: file, line: line) } From 25ef511ff7e962a8d00a07da1bad7a6175ff8b7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Wed, 4 Oct 2023 10:49:35 +0200 Subject: [PATCH 092/133] [NBKSignedKit] Safer sign stuff. --- ...ign.swift => SwiftFloatingPointSign.swift} | 51 +++++++------------ Sources/NBKSignedKit/NBKSigned+Numbers.swift | 4 +- Sources/NBKSignedKit/NBKSigned+Words.swift | 2 +- .../Swift+FloatingPointSign.swift | 6 +-- 4 files changed, 24 insertions(+), 39 deletions(-) rename Sources/NBKCoreKit/{Swift+FloatingPointSign.swift => SwiftFloatingPointSign.swift} (83%) diff --git a/Sources/NBKCoreKit/Swift+FloatingPointSign.swift b/Sources/NBKCoreKit/SwiftFloatingPointSign.swift similarity index 83% rename from Sources/NBKCoreKit/Swift+FloatingPointSign.swift rename to Sources/NBKCoreKit/SwiftFloatingPointSign.swift index 66da6fd5..182148d4 100644 --- a/Sources/NBKCoreKit/Swift+FloatingPointSign.swift +++ b/Sources/NBKCoreKit/SwiftFloatingPointSign.swift @@ -28,8 +28,8 @@ extension Swift.FloatingPointSign { /// └────── → ───── = ──┘ /// ``` /// - @_transparent public init(_ bit: Bool) { - self = Swift.unsafeBitCast(bit, to: Self.self) + @inlinable public init(bit: Bool) { + self = bit ? Self.minus : Self.plus } //=------------------------------------------------------------------------= @@ -47,8 +47,8 @@ extension Swift.FloatingPointSign { /// └────── = ─ → ────── = ────┘ /// ``` /// - @_transparent public var ascii: UInt8 { - UInt8(ascii: self.bit ? "-" : "+") + @inlinable public var ascii: UInt8 { + UInt8(ascii: self == Self.plus ? "+" : "-") } /// The `bit` representation of this value. @@ -62,23 +62,8 @@ extension Swift.FloatingPointSign { /// └────── = ─ → ──────┘ /// ``` /// - @_transparent public var bit: Bool { - Swift.unsafeBitCast(self, to: Bool.self) - } - - /// The `data` representation of this value. - /// - /// ``` - /// ┌────────── → ─────────┐ - /// │ sign │ data │ - /// ├────── = ─ → ─────────┤ - /// │ plus │ 0 │ UInt8(0) │ - /// │ minus │ 1 │ UInt8(1) │ - /// └────── = ─ → ─────────┘ - /// ``` - /// - @_transparent @usableFromInline var data: UInt8 { - Swift.unsafeBitCast(self, to: UInt8.self) + @inlinable public var bit: Bool { + self == Self.plus ? false : true } //=------------------------------------------------------------------------= @@ -96,7 +81,7 @@ extension Swift.FloatingPointSign { /// └────── = ─ → ───── = ──┘ /// ``` /// - @_transparent public mutating func toggle() { + @inlinable public mutating func toggle() { self = ~self } @@ -111,7 +96,7 @@ extension Swift.FloatingPointSign { /// └────── = ─ → ───── = ──┘ /// ``` /// - @_transparent public func toggled() -> Self { + @inlinable public func toggled() -> Self { ~self } @@ -126,7 +111,7 @@ extension Swift.FloatingPointSign { /// └────── = ─ → ───── = ──┘ /// ``` /// - @_transparent public static prefix func ~(sign: Self) -> Self { + @inlinable public static prefix func ~(sign: Self) -> Self { sign ^ minus } @@ -143,7 +128,7 @@ extension Swift.FloatingPointSign { /// └────── = ─ → ────── = ─ → ──── = ────┘ /// ``` /// - @_transparent public static func &=(lhs: inout Self, rhs: Self) { + @inlinable public static func &=(lhs: inout Self, rhs: Self) { lhs = lhs & rhs } @@ -160,8 +145,8 @@ extension Swift.FloatingPointSign { /// └────── = ─ → ────── = ─ → ──── = ────┘ /// ``` /// - @_transparent public static func &(lhs: Self, rhs: Self) -> Self { - Swift.unsafeBitCast(lhs.data & rhs.data, to: Self.self) + @inlinable public static func &(lhs: Self, rhs: Self) -> Self { + lhs == rhs ? lhs : Self.plus } /// Forms the logical `OR` of `lhs` and `rhs`. @@ -177,7 +162,7 @@ extension Swift.FloatingPointSign { /// └────── = ─ → ────── = ─ → ──── = ────┘ /// ``` /// - @_transparent public static func |=(lhs: inout Self, rhs: Self) { + @inlinable public static func |=(lhs: inout Self, rhs: Self) { lhs = lhs | rhs } @@ -194,8 +179,8 @@ extension Swift.FloatingPointSign { /// └────── = ─ → ────── = ─ → ──── = ────┘ /// ``` /// - @_transparent public static func |(lhs: Self, rhs: Self) -> Self { - Swift.unsafeBitCast(lhs.data | rhs.data, to: Self.self) + @inlinable public static func |(lhs: Self, rhs: Self) -> Self { + lhs == Self.plus ? rhs : lhs } /// Forms the logical `XOR` of `lhs` and `rhs`. @@ -211,7 +196,7 @@ extension Swift.FloatingPointSign { /// └────── = ─ → ────── = ─ → ──── = ────┘ /// ``` /// - @_transparent public static func ^=(lhs: inout Self, rhs: Self) { + @inlinable public static func ^=(lhs: inout Self, rhs: Self) { lhs = lhs ^ rhs } @@ -228,7 +213,7 @@ extension Swift.FloatingPointSign { /// └────── = ─ → ────── = ─ → ──── = ────┘ /// ``` /// - @_transparent public static func ^(lhs: Self, rhs: Self) -> Self { - Swift.unsafeBitCast(lhs.data ^ rhs.data, to: Self.self) + @inlinable public static func ^(lhs: Self, rhs: Self) -> Self { + lhs == rhs ? Self.plus : Self.minus } } diff --git a/Sources/NBKSignedKit/NBKSigned+Numbers.swift b/Sources/NBKSignedKit/NBKSigned+Numbers.swift index 284629ff..a7827309 100644 --- a/Sources/NBKSignedKit/NBKSigned+Numbers.swift +++ b/Sources/NBKSignedKit/NBKSigned+Numbers.swift @@ -66,13 +66,13 @@ extension NBKSigned { } @inlinable public init?(exactly source: T) { - let sign = Sign(source < T.zero) + let sign = Sign(bit: source < T.zero) guard let magnitude = Magnitude(exactly: source.magnitude) else { return nil } self.init(sign: sign, magnitude: magnitude) } @inlinable public init(clamping source: T) { - let sign = Sign(source < T.zero) + let sign = Sign(bit: source < T.zero) let magnitude = Magnitude(clamping: source.magnitude) self.init(sign: sign, magnitude: magnitude) } diff --git a/Sources/NBKSignedKit/NBKSigned+Words.swift b/Sources/NBKSignedKit/NBKSigned+Words.swift index a2b44808..61b0c973 100644 --- a/Sources/NBKSignedKit/NBKSigned+Words.swift +++ b/Sources/NBKSignedKit/NBKSigned+Words.swift @@ -26,7 +26,7 @@ extension NBKSigned { @inlinable public init?(words: some RandomAccessCollection, isSigned: Bool) { let isLessThanZero: Bool = isSigned && words.last?.mostSignificantBit == true guard let magnitude = Magnitude(words: NBK.MaybeTwosComplement(words, formTwosComplement: isLessThanZero)) else { return nil } - self.init(sign: Sign(isLessThanZero), magnitude: magnitude) + self.init(sign: Sign(bit: isLessThanZero), magnitude: magnitude) } //=------------------------------------------------------------------------= diff --git a/Tests/NBKCoreKitTests/Swift+FloatingPointSign.swift b/Tests/NBKCoreKitTests/Swift+FloatingPointSign.swift index ad2ed9ef..08c8fe96 100644 --- a/Tests/NBKCoreKitTests/Swift+FloatingPointSign.swift +++ b/Tests/NBKCoreKitTests/Swift+FloatingPointSign.swift @@ -30,11 +30,11 @@ final class SwiftTestsOnFloatingPointSign: XCTestCase { } func testBit() { - XCTAssertEqual(T(false), T.plus ) - XCTAssertEqual(T(true ), T.minus) - XCTAssertEqual(T.plus .bit, false) XCTAssertEqual(T.minus.bit, true ) + + XCTAssertEqual(T(bit: false), T.plus ) + XCTAssertEqual(T(bit: true ), T.minus) } //=------------------------------------------------------------------------= From a0691378cb7c678902c5103a38c3e641bc297a09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Wed, 4 Oct 2023 13:44:35 +0200 Subject: [PATCH 093/133] [NBKSignedKit] Cleanup. Comparisons. Components. --- .../NBKSignedKit/NBKSigned+Comparisons.swift | 26 ++--------- Sources/NBKSignedKit/NBKSigned+Numbers.swift | 6 +-- Sources/NBKSignedKit/NBKSigned+Words.swift | 2 +- Sources/NBKSignedKit/NBKSigned.swift | 15 ++++++ .../Private/NBK+Comparisons.swift | 42 +++++++++++++++++ .../NBKFlexibleWidth.swift | 14 ++++++ Tests/NBKSignedKitBenchmarks/NBKSigned.swift | 46 +++++++++++++++++++ Tests/NBKSignedKitTests/NBKSigned.swift | 28 ++++++++++- 8 files changed, 152 insertions(+), 27 deletions(-) create mode 100644 Sources/NBKSignedKit/Private/NBK+Comparisons.swift create mode 100644 Tests/NBKSignedKitBenchmarks/NBKSigned.swift diff --git a/Sources/NBKSignedKit/NBKSigned+Comparisons.swift b/Sources/NBKSignedKit/NBKSigned+Comparisons.swift index 7d1b5bd4..7362bbc7 100644 --- a/Sources/NBKSignedKit/NBKSigned+Comparisons.swift +++ b/Sources/NBKSignedKit/NBKSigned+Comparisons.swift @@ -58,36 +58,18 @@ extension NBKSigned { //=------------------------------------------------------------------------= @inlinable public static func ==(lhs: Self, rhs: Self) -> Bool { - if lhs.sign != rhs.sign { - return lhs.isZero && rhs.isZero - } else { - return lhs.magnitude == rhs.magnitude - } + lhs.compared(to: rhs).isZero } @inlinable public static func <(lhs: Self, rhs: Self) -> Bool { - if lhs.sign != rhs.sign { - return (lhs.sign != Sign.plus) && !(lhs.isZero && rhs.isZero) - } else { - return (lhs.sign == Sign.plus) ? lhs.magnitude < rhs.magnitude : rhs.magnitude < lhs.magnitude - } + lhs.compared(to: rhs) == -1 } @inlinable public func compared(to other: Self) -> Int { - if self.sign != other.sign { - return self.isZero && other.isZero ? 0 : self.sign == Sign.plus ? 1 : -1 - } else { - let m = self.magnitude.compared(to: other.magnitude) - return self.sign == Sign.plus ? m : -m - } + NBK.compare(self.components, to: other.components, using:{ $0.compared(to: $1) }) } @_disfavoredOverload @inlinable public func compared(to other: Digit) -> Int { - if self.sign != other.sign { - return self.isZero && other.isZero ? 0 : self.sign == Sign.plus ? 1 : -1 - } else { - let m = self.magnitude.compared(to: other.magnitude) - return self.sign == Sign.plus ? m : -m - } + NBK.compare(self.components, to: other.components, using:{ $0.compared(to: $1) }) } } diff --git a/Sources/NBKSignedKit/NBKSigned+Numbers.swift b/Sources/NBKSignedKit/NBKSigned+Numbers.swift index a7827309..65abee06 100644 --- a/Sources/NBKSignedKit/NBKSigned+Numbers.swift +++ b/Sources/NBKSignedKit/NBKSigned+Numbers.swift @@ -10,7 +10,7 @@ import NBKCoreKit //*============================================================================* -// MARK: * NBK x Signed x Numbers x Decode +// MARK: * NBK x Signed x Numbers x Decoding //*============================================================================* extension NBKSigned { @@ -98,7 +98,7 @@ extension NBKSigned where Magnitude: FixedWidthInteger { } //*============================================================================* -// MARK: * NBK x Signed x Numbers x Encode +// MARK: * NBK x Signed x Numbers x Encoding //*============================================================================* extension NBKBinaryInteger { @@ -118,6 +118,6 @@ extension NBKBinaryInteger { } @inlinable public init(clamping source: NBKSigned) where Self: NBKFixedWidthInteger { - self = Self(sign: source.sign, magnitude: source.magnitude) ?? (source.sign == .minus ? Self.min : Self.max) + self = Self(sign: source.sign, magnitude: source.magnitude) ?? (source.sign == FloatingPointSign.plus ? Self.max : Self.min) } } diff --git a/Sources/NBKSignedKit/NBKSigned+Words.swift b/Sources/NBKSignedKit/NBKSigned+Words.swift index 61b0c973..ae063aa4 100644 --- a/Sources/NBKSignedKit/NBKSigned+Words.swift +++ b/Sources/NBKSignedKit/NBKSigned+Words.swift @@ -79,7 +79,7 @@ extension NBKSigned { } @inlinable public subscript(index: Int) -> UInt { - index < self.base.endIndex ? self.base[self.base.index(self.base.startIndex, offsetBy: index)] : self.sign + index < self.base.count ? self.base[self.base.index(self.base.startIndex, offsetBy: index)] : self.sign } //=--------------------------------------------------------------------= diff --git a/Sources/NBKSignedKit/NBKSigned.swift b/Sources/NBKSignedKit/NBKSigned.swift index 1101cb1a..67ca4552 100644 --- a/Sources/NBKSignedKit/NBKSigned.swift +++ b/Sources/NBKSignedKit/NBKSigned.swift @@ -100,6 +100,21 @@ Hashable, Sendable, SignedNumeric { self.sign = sign; self.magnitude = magnitude } + //=------------------------------------------------------------------------= + // MARK: Details x Components + //=------------------------------------------------------------------------= + + /// Creates a new instance from the given `sign` and `magnitude`. + @inlinable public init(components: SM) { + (sign: self.sign, magnitude: self.magnitude) = components + } + + /// The `sign` and `magnitude` of this value. + @inlinable public var components: SM { + get { (sign: self.sign, magnitude: self.magnitude) } + set { (self.sign, self.magnitude) = newValue as SM } + } + //=------------------------------------------------------------------------= // MARK: Details x Normalization //=------------------------------------------------------------------------= diff --git a/Sources/NBKSignedKit/Private/NBK+Comparisons.swift b/Sources/NBKSignedKit/Private/NBK+Comparisons.swift new file mode 100644 index 00000000..1b567b11 --- /dev/null +++ b/Sources/NBKSignedKit/Private/NBK+Comparisons.swift @@ -0,0 +1,42 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Comparisons +//*============================================================================* + +extension NBK { + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + /// A three-way sign and magnitude comparison using the given magnitude operation. + /// + /// - Parameters: + /// - compare: A three-way magnitude comparison. + /// + /// - Returns: One of the following values: -1 (less), 0 (same), or 1 (more). + /// + @inlinable public static func compare( + _ lhs: SM, to rhs: SM, using compare: (A, B) -> Int) -> Int { + let absoluteValue: Int + + if lhs.sign == rhs.sign { + absoluteValue = compare(lhs.magnitude, rhs.magnitude) + } else { + absoluteValue = lhs.magnitude.isZero && rhs.magnitude.isZero ? 0 : 1 as Int + } + + Swift.assert(-1 <= absoluteValue && absoluteValue <= 1) + return lhs.sign == Sign.plus ? absoluteValue : absoluteValue.twosComplement() + } +} diff --git a/Tests/NBKSignedKitBenchmarks/NBKFlexibleWidth.swift b/Tests/NBKSignedKitBenchmarks/NBKFlexibleWidth.swift index 05a11117..fc87285b 100644 --- a/Tests/NBKSignedKitBenchmarks/NBKFlexibleWidth.swift +++ b/Tests/NBKSignedKitBenchmarks/NBKFlexibleWidth.swift @@ -41,3 +41,17 @@ extension UIntXL { self.init(words: NBKChunkedInt(x64)) } } + +//=----------------------------------------------------------------------------= +// MARK: + SIntXL +//=----------------------------------------------------------------------------= + +extension NBKSigned { + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + static let min256 = Self(sign: .minus, magnitude: Magnitude.max256) + static let max256 = Self(sign: .plus, magnitude: Magnitude.max256) +} diff --git a/Tests/NBKSignedKitBenchmarks/NBKSigned.swift b/Tests/NBKSignedKitBenchmarks/NBKSigned.swift new file mode 100644 index 00000000..8f9341de --- /dev/null +++ b/Tests/NBKSignedKitBenchmarks/NBKSigned.swift @@ -0,0 +1,46 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if !DEBUG + +import NBKCoreKit +import NBKFlexibleWidthKit +import NBKSignedKit +import XCTest + +private typealias X = NBK.U256X64 +private typealias Y = NBK.U256X32 + +//*============================================================================* +// MARK: * NBK x Signed x SIntXL +//*============================================================================* + +final class NBKSignedBenchmarksAsSIntXL: XCTestCase { + + typealias T = NBKSigned + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testInit() { + var abc = NBK.blackHoleIdentity(SM(sign: .plus, magnitude: UIntXL(1))) + var xyz = NBK.blackHoleIdentity(SM(sign: .minus, magnitude: UIntXL(1))) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(T(sign: abc.sign, magnitude: abc.magnitude)) + NBK.blackHole(T(sign: xyz.sign, magnitude: xyz.magnitude)) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } +} + +#endif diff --git a/Tests/NBKSignedKitTests/NBKSigned.swift b/Tests/NBKSignedKitTests/NBKSigned.swift index 4a46e06a..db887b23 100644 --- a/Tests/NBKSignedKitTests/NBKSigned.swift +++ b/Tests/NBKSignedKitTests/NBKSigned.swift @@ -44,7 +44,14 @@ final class NBKSignedTests: XCTestCase { XCTAssertEqual(T(sign: .minus, magnitude: 1).magnitude, 1 as M) } - func testNormalized() { + func testComponents() { + NBKAssertComponentsGetSetInit(T(sign: .plus , magnitude: 0), .plus, 0 as M) + NBKAssertComponentsGetSetInit(T(sign: .plus , magnitude: 1), .plus, 1 as M) + NBKAssertComponentsGetSetInit(T(sign: .minus, magnitude: 0), .minus, 0 as M) + NBKAssertComponentsGetSetInit(T(sign: .minus, magnitude: 1), .minus, 1 as M) + } + + func testNormalization() { NBKAssertNormalization(T(sign: .plus , magnitude: 0), true, .plus, 0 as M) NBKAssertNormalization(T(sign: .plus , magnitude: 1), true, .plus, 1 as M) NBKAssertNormalization(T(sign: .minus, magnitude: 0), false, .plus, 0 as M) @@ -56,6 +63,25 @@ final class NBKSignedTests: XCTestCase { // MARK: * NBK x Signed x Assertions //*============================================================================* +private func NBKAssertComponentsGetSetInit( +_ value: NBKSigned, _ sign: NBKSigned.Sign, _ magnitude: M, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + typealias T = NBKSigned + //=------------------------------------------= + XCTAssertEqual(value.sign, sign, file: file, line: line) + XCTAssertEqual(value.magnitude, magnitude, file: file, line: line) + + XCTAssertEqual(value.components.sign, sign, file: file, line: line) + XCTAssertEqual(value.components.magnitude, magnitude, file: file, line: line) + + NBKAssertIdentical(value, T(sign: sign, magnitude: magnitude), file: file, line: line) + NBKAssertIdentical(value, T(components: SM(sign: sign, magnitude: magnitude)), file: file, line: line) + + NBKAssertIdentical(value, { var x = T(); x.sign = sign; x.magnitude = magnitude; return x }(), file: file, line: line) + NBKAssertIdentical(value, { var x = T(); x.components = SM(sign: sign, magnitude: magnitude); return x }(), file: file, line: line) +} + private func NBKAssertNormalization( _ integer: NBKSigned, _ isNormal: Bool, _ sign: NBKSigned.Sign, _ magnitude: M, file: StaticString = #file, line: UInt = #line) { From c316e9dd8bd5c4009ff72197b12a0deaec834687 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Wed, 4 Oct 2023 15:50:41 +0200 Subject: [PATCH 094/133] [NBKSignedKit] Zzz. --- Tests/NBKCoreKitBenchmarks/Swift+FloatingPointSign.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/NBKCoreKitBenchmarks/Swift+FloatingPointSign.swift b/Tests/NBKCoreKitBenchmarks/Swift+FloatingPointSign.swift index b9d5a435..bb99677d 100644 --- a/Tests/NBKCoreKitBenchmarks/Swift+FloatingPointSign.swift +++ b/Tests/NBKCoreKitBenchmarks/Swift+FloatingPointSign.swift @@ -42,8 +42,8 @@ final class SwiftBenchmarksOnFloatingPointSign: XCTestCase { var xyz = NBK.blackHoleIdentity(false) for _ in 0 ..< 5_000_000 { - NBK.blackHole(T(abc)) - NBK.blackHole(T(xyz)) + NBK.blackHole(T(bit: abc)) + NBK.blackHole(T(bit: xyz)) NBK.blackHoleInoutIdentity(&abc) NBK.blackHoleInoutIdentity(&xyz) From 5de768033cdb783cc5772ec21c8164ce3db00c50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Mon, 16 Oct 2023 15:33:17 +0200 Subject: [PATCH 095/133] [NBKSignedKit] Numbers. Some tests from open source issues. --- Sources/NBKSignedKit/NBKSigned+Numbers.swift | 11 ++--- .../NBKFlexibleWidth+Numbers.swift | 40 +++++++++++++++++ .../NBKFlexibleWidth+Text.swift | 2 +- .../NBKSigned+Complements.swift | 43 +++++++++++++++++++ .../NBKSigned+Division.swift | 37 ++++++++++++++++ .../NBKSigned+Negation.swift | 23 ++++++++++ .../NBKSignedKitTests/NBKSigned+Numbers.swift | 29 +++++++++++++ ...ract.swift => NBKSigned+Subtraction.swift} | 29 +++++++++++++ Tests/NBKSignedKitTests/NBKSigned+Text.swift | 2 +- 9 files changed, 209 insertions(+), 7 deletions(-) create mode 100644 Tests/NBKSignedKitTests/NBKSigned+Complements.swift rename Tests/NBKSignedKitTests/{NBKSigned+Subtract.swift => NBKSigned+Subtraction.swift} (86%) diff --git a/Sources/NBKSignedKit/NBKSigned+Numbers.swift b/Sources/NBKSignedKit/NBKSigned+Numbers.swift index 65abee06..096a16c7 100644 --- a/Sources/NBKSignedKit/NBKSigned+Numbers.swift +++ b/Sources/NBKSignedKit/NBKSigned+Numbers.swift @@ -107,17 +107,18 @@ extension NBKBinaryInteger { // MARK: Initializers //=------------------------------------------------------------------------= - @inlinable public init(_ source: NBKSigned) { + @inlinable public init(_ source: NBKSigned) { if let value = Self(exactly: source) { self = value } else { preconditionFailure("\(Self.self) cannot represent \(source)") } } - @inlinable public init?(exactly source: NBKSigned) { - self.init(sign: source.sign, magnitude: source.magnitude) + @inlinable public init?(exactly source: NBKSigned) { + guard let magnitude: Magnitude = NBK.initOrBitCast(exactly: source.magnitude) else { return nil } + self.init(sign: source.sign, magnitude: magnitude) } - @inlinable public init(clamping source: NBKSigned) where Self: NBKFixedWidthInteger { - self = Self(sign: source.sign, magnitude: source.magnitude) ?? (source.sign == FloatingPointSign.plus ? Self.max : Self.min) + @inlinable public init(clamping source: NBKSigned) where Self: NBKFixedWidthInteger { + self = Self(exactly: source) ?? (source.sign == FloatingPointSign.plus ? Self.max : Self.min) } } diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Numbers.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Numbers.swift index 0741dc3a..06e384ff 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Numbers.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Numbers.swift @@ -239,6 +239,46 @@ final class NBKFlexibleWidthTestsOnNumbersAsUIntXL: XCTestCase { } } +//*============================================================================* +// MARK: * NBK x Flexible Width x Numbers x Open Source Issues +//*============================================================================* + +final class NBKFlexibleWidthTestsOnNumbersOpenSourceIssues: XCTestCase { + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + /// https://github.com/apple/swift-numerics/pull/254 + /// + /// - Note: Said to crash and return incorrect values. + /// + func testSwiftNumericsPull254() { + XCTAssertEqual(UInt64( UIntXL(UInt64.max)), UInt64(UInt64.max)) + XCTAssertEqual(UIntXL( UInt64(UInt64.max)), UIntXL(UInt64.max)) + + XCTAssertEqual(UInt64(exactly: UIntXL(UInt64.max)), UInt64(UInt64.max)) + XCTAssertEqual(UIntXL(exactly: UInt64(UInt64.max)), UIntXL(UInt64.max)) + + XCTAssertEqual(UInt64(clamping: UIntXL(UInt64.max)), UInt64(UInt64.max)) + XCTAssertEqual(UIntXL(clamping: UInt64(UInt64.max)), UIntXL(UInt64.max)) + } + + /// https://github.com/apple/swift-numerics/pull/258 + /// + /// - Note: Said to crash when using Float80 (can't test it). + /// + func testSwiftNumericsPull258() { + XCTAssertEqual( + Float32(exactly: UInt64(UInt64(1) << Float32.significandBitCount)), + Float32(exactly: UIntXL(UInt64(1) << Float32.significandBitCount))) + + XCTAssertEqual( + Float64(exactly: UInt64(UInt64(1) << Float64.significandBitCount)), + Float64(exactly: UIntXL(UInt64(1) << Float64.significandBitCount))) + } +} + //*============================================================================* // MARK: * NBK x Flexible Width x Numbers x Assertions //*============================================================================* diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Text.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Text.swift index 6cdd9e9a..26789b9a 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Text.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Text.swift @@ -963,7 +963,7 @@ private func NBKAssertEncodeText( _ integer: T, _ radix: Int, _ uppercase: Bool, _ text: String, file: StaticString = #file, line: UInt = #line) { //=------------------------------------------= - if radix == 10, uppercase == false { + if radix == 10 { XCTAssertEqual(String.init(integer), text, file: file, line: line) XCTAssertEqual(integer.description, text, file: file, line: line) } diff --git a/Tests/NBKSignedKitTests/NBKSigned+Complements.swift b/Tests/NBKSignedKitTests/NBKSigned+Complements.swift new file mode 100644 index 00000000..ec91d9bd --- /dev/null +++ b/Tests/NBKSignedKitTests/NBKSigned+Complements.swift @@ -0,0 +1,43 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +import NBKFlexibleWidthKit +import NBKSignedKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Signed x Complements x Open Source Issues +//*============================================================================* + +final class NBKSignedTestsOnComplementsOpenSourceIssues: XCTestCase { + + typealias SIntXL = NBKSigned + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + /// https://github.com/apple/swift-numerics/pull/252 + /// + /// - Note: Said to return incorrect values. + /// + func testSwiftNumericsPull252() { + XCTAssertEqual(SIntXL(Int.min ).magnitude, UIntXL(Int.min.magnitude)) + XCTAssertEqual(SIntXL(Int.min.magnitude).magnitude, UIntXL(Int.min.magnitude)) + } +} + +#endif diff --git a/Tests/NBKSignedKitTests/NBKSigned+Division.swift b/Tests/NBKSignedKitTests/NBKSigned+Division.swift index 886b80a6..754c0f54 100644 --- a/Tests/NBKSignedKitTests/NBKSigned+Division.swift +++ b/Tests/NBKSignedKitTests/NBKSigned+Division.swift @@ -89,6 +89,43 @@ final class NBKSignedTestsOnDivisionAsSIntXL: XCTestCase { } } +//*============================================================================* +// MARK: * NBK x Signed x Division x Open Source Issues +//*============================================================================* + +final class NBKSignedTestsOnDivisionOpenSourceIssues: XCTestCase { + + typealias SIntXL = NBKSigned + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + /// https://github.com/apple/swift-numerics/pull/250 + /// + /// - Note: Said to crash and return incorrect values. + /// + func testSwiftNumericsPull250() { + NBKAssertDivision( + SIntXL("-9223372036854775808"), + SIntXL("-0000000000000000001"), + SIntXL("+9223372036854775808"), + SIntXL("-0000000000000000000")) + + NBKAssertDivision( + SIntXL("+18446744073709551615"), + SIntXL("-00000000000000000001"), + SIntXL("-18446744073709551615"), + SIntXL("+00000000000000000000")) + + NBKAssertDivision( + SIntXL("-340282366920938463481821351505477763074"), + SIntXL("+000000000000000000018446744073709551629"), + SIntXL("-000000000000000000018446744073709551604"), + SIntXL("-000000000000000000000000000000000000158")) + } +} + //*============================================================================* // MARK: * NBK x Signed x Division x Assertions //*============================================================================* diff --git a/Tests/NBKSignedKitTests/NBKSigned+Negation.swift b/Tests/NBKSignedKitTests/NBKSigned+Negation.swift index e277bd28..fdfa356c 100644 --- a/Tests/NBKSignedKitTests/NBKSigned+Negation.swift +++ b/Tests/NBKSignedKitTests/NBKSigned+Negation.swift @@ -10,6 +10,7 @@ #if DEBUG import NBKSignedKit +import NBKFlexibleWidthKit import XCTest private typealias W = [UInt] @@ -51,6 +52,28 @@ final class NBKSignedTestsOnNegation: XCTestCase { } } +//*============================================================================* +// MARK: * NBK x Signed x Negation x Open Source Issues +//*============================================================================* + +final class NBKSignedTestsOnNegationOpenSourceIssues: XCTestCase { + + typealias SIntXL = NBKSigned + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + /// https://github.com/apple/swift-numerics/pull/253 + /// + /// - Note: Said to return incorrect values. + /// + func testSwiftNumericsPull253() { + NBKAssertNegation(SIntXL(Int.min), SIntXL(Int.min.magnitude)) + NBKAssertNegation(SIntXL(Int.min.magnitude), SIntXL(Int.min)) + } +} + //*============================================================================* // MARK: * NBK x Signed x Negation x Assertions //*============================================================================* diff --git a/Tests/NBKSignedKitTests/NBKSigned+Numbers.swift b/Tests/NBKSignedKitTests/NBKSigned+Numbers.swift index af5d94ba..bc9a292b 100644 --- a/Tests/NBKSignedKitTests/NBKSigned+Numbers.swift +++ b/Tests/NBKSignedKitTests/NBKSigned+Numbers.swift @@ -11,6 +11,7 @@ import NBKCoreKit import NBKSignedKit +import NBKFlexibleWidthKit import XCTest private typealias W = [UInt] @@ -166,4 +167,32 @@ final class NBKSignedTestsOnNumbers: XCTestCase { } } +//*============================================================================* +// MARK: * NBK x Signed x Numbers x Open Source Issues +//*============================================================================* + +final class NBKSignedTestsOnNumbersOpenSourceIssues: XCTestCase { + + typealias SIntXL = NBKSigned + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + /// https://github.com/apple/swift-numerics/pull/254 + /// + /// - Note: Said to crash and return incorrect values. + /// + func testSwiftNumericsPull254() { + XCTAssertEqual(UInt64( SIntXL(UInt64.max)), UInt64(UInt64.max)) + XCTAssertEqual(SIntXL( UInt64(UInt64.max)), SIntXL(UInt64.max)) + + XCTAssertEqual(UInt64(exactly: SIntXL(UInt64.max)), UInt64(UInt64.max)) + XCTAssertEqual(SIntXL(exactly: UInt64(UInt64.max)), SIntXL(UInt64.max)) + + XCTAssertEqual(UInt64(clamping: SIntXL(UInt64.max)), UInt64(UInt64.max)) + XCTAssertEqual(SIntXL(clamping: UInt64(UInt64.max)), SIntXL(UInt64.max)) + } +} + #endif diff --git a/Tests/NBKSignedKitTests/NBKSigned+Subtract.swift b/Tests/NBKSignedKitTests/NBKSigned+Subtraction.swift similarity index 86% rename from Tests/NBKSignedKitTests/NBKSigned+Subtract.swift rename to Tests/NBKSignedKitTests/NBKSigned+Subtraction.swift index 38117a4d..8ce6c81a 100644 --- a/Tests/NBKSignedKitTests/NBKSigned+Subtract.swift +++ b/Tests/NBKSignedKitTests/NBKSigned+Subtraction.swift @@ -101,6 +101,35 @@ final class NBKSignedTestsOnSubtractionAsSIntXL: XCTestCase { } } +//*============================================================================* +// MARK: * NBK x Signed x Subtraction x Open Source Issues +//*============================================================================* + +final class NBKSignedTestsOnSubtractionOpenSourceIssues: XCTestCase { + + typealias SIntXL = NBKSigned + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + /// https://github.com/apple/swift-numerics/pull/246 + /// + /// - Note: Said to return incorrect values. + /// + func testSwiftNumericsPull246() { + NBKAssertSubtraction( + SIntXL("-0922337203685477587"), + SIntXL("-9223372036854775808"), + SIntXL("08301034833169298221")) + + NBKAssertSubtraction( + SIntXL(Int.max), + SIntXL(sign: .minus, magnitude: UIntXL(UInt.max - UInt(Int.max.magnitude))), + SIntXL(sign: .plus, magnitude: UIntXL(UInt.max))) + } +} + //*============================================================================* // MARK: * NBK x Signed x Subtraction x Assertions //*============================================================================* diff --git a/Tests/NBKSignedKitTests/NBKSigned+Text.swift b/Tests/NBKSignedKitTests/NBKSigned+Text.swift index e3ebbf11..d07f7d2d 100644 --- a/Tests/NBKSignedKitTests/NBKSigned+Text.swift +++ b/Tests/NBKSignedKitTests/NBKSigned+Text.swift @@ -269,7 +269,7 @@ _ integer: NBKSigned, _ radix: Int, _ uppercase: Bool, _ text: String, file: StaticString = #file, line: UInt = #line) { typealias T = NBKSigned //=------------------------------------------= - if radix == 10, uppercase == false { + if radix == 10 { XCTAssertEqual(String.init(integer), text, file: file, line: line) XCTAssertEqual(integer.description, text, file: file, line: line) } From c212607d0b68cccb13fafa88a73dcbdc3ff4ff4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Tue, 17 Oct 2023 14:40:48 +0200 Subject: [PATCH 096/133] [FlexibleWidthKit] Division. --- .../NBKFlexibleWidthKit/IntXLOrUIntXL.swift | 14 +- .../NBKFlexibleWidth+Division.swift | 94 +++++------ .../NBKFlexibleWidth+Numbers.swift | 2 + .../NBKFlexibleWidth+Division.swift | 30 +++- .../NBKFlexibleWidth+Division.swift | 152 +++++++++++++----- 5 files changed, 198 insertions(+), 94 deletions(-) diff --git a/Sources/NBKFlexibleWidthKit/IntXLOrUIntXL.swift b/Sources/NBKFlexibleWidthKit/IntXLOrUIntXL.swift index ffbc427e..1db898df 100644 --- a/Sources/NBKFlexibleWidthKit/IntXLOrUIntXL.swift +++ b/Sources/NBKFlexibleWidthKit/IntXLOrUIntXL.swift @@ -15,13 +15,23 @@ import NBKCoreKit public protocol IntXLOrUIntXL: NBKBinaryInteger, ExpressibleByStringLiteral where Magnitude == UIntXL { + //=------------------------------------------------------------------------= + // MARK: Details x Numbers + //=------------------------------------------------------------------------= + + /// An instance that is equal to `0`. + @inlinable static var zero: Self { get } + + /// An instance that is equal to `1`. + @inlinable static var one: Self { get } + //=------------------------------------------------------------------------= // MARK: Details x Comparisons //=------------------------------------------------------------------------= - func compared(to other: Self, at index: Int) -> Int + @inlinable func compared(to other: Self, at index: Int) -> Int - func compared(to other: Digit, at index: Int) -> Int + @_disfavoredOverload @inlinable func compared(to other: Digit, at index: Int) -> Int //=------------------------------------------------------------------------= // MARK: Details x Addition diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift index e9cfb628..41cd1e75 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift @@ -41,8 +41,8 @@ extension NBKFlexibleWidth.Magnitude { return PVO(qro.partialValue.remainder, qro.overflow) } - @inlinable public func quotientAndRemainderReportingOverflow(dividingBy other: Self) -> PVO> { - self.quotientAndRemainderReportingOverflowAsNormal(dividingBy: other) + @inlinable public func quotientAndRemainderReportingOverflow(dividingBy other: Self) -> PVO> { + self.quotientAndRemainderReportingOverflowByLongDivision(dividingBy: other) } } @@ -56,13 +56,15 @@ extension NBKFlexibleWidth.Magnitude { // MARK: Transformations x Private //=------------------------------------------------------------------------= - @inlinable func quotientAndRemainderReportingOverflowAsNormal(dividingBy other: Self) -> PVO> { + /// Performs long division after some fast-path checks. + @inlinable func quotientAndRemainderReportingOverflowByLongDivision(dividingBy other: Self) -> PVO> { var (remainder) = self - let (quotient, overflow) = remainder.formRemainderWithQuotientReportingOverflowAsNormal(dividingBy: other) + let (quotient, overflow) = remainder.formRemainderWithQuotientReportingOverflowByLongDivision(dividingBy: other) return PVO(QR(quotient, remainder), overflow) } - @inlinable mutating func formRemainderWithQuotientReportingOverflowAsNormal(dividingBy other: Self) -> PVO { + /// Performs long division after some fast-path checks. + @inlinable mutating func formRemainderWithQuotientReportingOverflowByLongDivision(dividingBy other: Self) -> PVO { //=--------------------------------------= // divisor is zero //=--------------------------------------= @@ -73,9 +75,9 @@ extension NBKFlexibleWidth.Magnitude { // divisor is one word //=--------------------------------------= if other.count == 1 { - let qr: QR = self.quotientAndRemainder(dividingBy: other.first) - self.update(qr.remainder) - return PVO(qr.quotient, false) + let (q, r) = self.quotientAndRemainder(dividingBy: other.first) + self.update(r) + return PVO((q), false) } //=--------------------------------------= // divisor is greater than or equal @@ -84,66 +86,66 @@ extension NBKFlexibleWidth.Magnitude { if comparison.isLessThanZero { } else if comparison.isZero { self.updateZeroValue() - return PVO(001, false) + return PVO(Self.one, false) } else { - return PVO(000, false) + return PVO(Self.zero, false) } //=--------------------------------------= - // shift to clamp approximation + // normalization //=--------------------------------------= - var divisor: Storage = other.storage - let divisorLastIndex = divisor.elements.endIndex - 1 as Int - let shift = divisor.elements[divisorLastIndex].leadingZeroBitCount as Int - - var remainderIndex = self.storage.elements.endIndex as Int self.storage.append(0 as UInt) + var other: Self = other + let shift: Int = other.last.leadingZeroBitCount + if !shift.isZero { - divisor/*-*/.withUnsafeMutableBufferPointer({ NBK.SUI.bitshiftLeft(&$0, major: 0 as Int, minorAtLeastOne: shift) }) - self.storage.withUnsafeMutableBufferPointer({ NBK.SUI.bitshiftLeft(&$0, major: 0 as Int, minorAtLeastOne: shift) }) + self .storage.withUnsafeMutableBufferPointer({ NBK.SUI.bitshiftLeft(&$0, major: 0 as Int, minorAtLeastOne: shift) }) + other.storage.withUnsafeMutableBufferPointer({ NBK.SUI.bitshiftLeft(&$0, major: 0 as Int, minorAtLeastOne: shift) }) } - - let divisorLast0 = divisor.elements[divisorLastIndex] as UInt - assert(divisorLast0.mostSignificantBit) //=--------------------------------------= - // division: approximate quotient digits + // division //=--------------------------------------= - var quotientIndex = remainderIndex - divisor.elements.endIndex as Int - let quotient = Self.uninitialized(count: quotientIndex + 1) { quotient in - self.storage.withUnsafeMutableBufferPointer { storage in - loop: repeat { - let remainderLast0 = storage[remainderIndex] - storage.formIndex(before: &remainderIndex) - let remainderLast1 = storage[remainderIndex] - //=--------------------------= - var digit: UInt - if divisorLast0 == remainderLast0 { - digit = UInt.max - } else { - digit = divisorLast0.dividingFullWidth(HL(remainderLast0, remainderLast1)).quotient - } + let quotient = Self.uninitialized(count: self.count - other.count) { quotient in + self.storage.withUnsafeMutableBufferPointer { remainder in + other.storage.withUnsafeBufferPointer { divisor in //=--------------------------= - if !digit.isZero { - var overflow = NBK.SUISS.decrement(&storage, by: divisor.elements, times: digit, at: quotientIndex).overflow - while overflow { - digit &-= 1 as Digit - overflow = !NBK.SUISS.increment(&storage, by: divisor.elements, at: quotientIndex).overflow + let divisorLast: UInt = divisor.last! + var remainderIndex = remainder.index(before: remainder.endIndex) + for quotientIndex in quotient.indices.reversed() { + //=----------------------= + let remainderLast0 = remainder[remainderIndex] + remainder.formIndex(before: &remainderIndex) + let remainderLast1 = remainder[remainderIndex] + //=----------------------= + var digit: UInt + if divisorLast == remainderLast0 { + digit = UInt.max + } else { + digit = divisorLast.dividingFullWidth(HL(high: remainderLast0, low: remainderLast1)).quotient + } + //=----------------------= + if !digit.isZero { + var overflow = (NBK).SUISS.decrement(&remainder, by: divisor, times: digit, at: quotientIndex).overflow + correctQuotientAtMostTwice: while overflow { + digit &-= 1 as Digit // the quotient digit is decremented until product ≤ remainder + overflow = !NBK .SUISS.increment(&remainder, by: divisor, at: quotientIndex).overflow + } } + //=----------------------= + quotient.baseAddress!.advanced(by: quotientIndex).initialize(to: digit) } - //=--------------------------= - quotient[quotientIndex] = digit - quotient.formIndex(before: "ientIndex) - } while quotientIndex >= quotient.startIndex + } } } //=--------------------------------------= - // undo shift before division + // normalization //=--------------------------------------= if !shift.isZero { self.storage.withUnsafeMutableBufferPointer({ NBK.SUI.bitshiftRight(&$0, major: 0 as Int, minorAtLeastOne: shift) }) } self.storage.normalize() + //=--------------------------------------= return PVO(partialValue: quotient, overflow: false) } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift index a554e5a3..7524b1aa 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift @@ -20,6 +20,8 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= public static let zero = Self(digit: 0) + + public static let one = Self(digit: 1) //=------------------------------------------------------------------------= // MARK: Initializers x Digit diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Division.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Division.swift index 4134089a..374bd401 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Division.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Division.swift @@ -104,9 +104,9 @@ final class NBKFlexibleWidthBenchmarksOnDivisionAsUIntXL: XCTestCase { // MARK: Tests x Full Width //=------------------------------------------------------------------------= - func testDividingFullWidthAs256() { + func testDividingFullWidthAs256WhenDivisorIsNormalized() { var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0, ~1, ~0, ~0, ~0] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0] as X)) // msb == true for _ in 0 ..< 250_000 { NBK.blackHole(lhs.quotientAndRemainder(dividingBy: rhs)) @@ -115,9 +115,31 @@ final class NBKFlexibleWidthBenchmarksOnDivisionAsUIntXL: XCTestCase { } } - func testDividingFullWidthReportingOverflowAs256() { + func testDividingFullWidthReportingOverflowAs256WhenDivisorIsNormalized() { var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0, ~1, ~0, ~0, ~0] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0] as X)) // msb == true + + for _ in 0 ..< 250_000 { + NBK.blackHole(lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs)) + NBK.blackHoleInoutIdentity(&rhs) + NBK.blackHoleInoutIdentity(&lhs) + } + } + + func testDividingFullWidthAs256WhenDivisorIsNotNormalized() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0, ~1, ~0, ~0, ~0] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0/2] as X)) // msb == false + + for _ in 0 ..< 250_000 { + NBK.blackHole(lhs.quotientAndRemainder(dividingBy: rhs)) + NBK.blackHoleInoutIdentity(&rhs) + NBK.blackHoleInoutIdentity(&lhs) + } + } + + func testDividingFullWidthReportingOverflowAs256WhenDivisorIsNotNormalized() { + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0, ~1, ~0, ~0, ~0] as X)) + var rhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0/2] as X)) // msb == false for _ in 0 ..< 250_000 { NBK.blackHole(lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs)) diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Division.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Division.swift index aae22f35..b4cef8b4 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Division.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Division.swift @@ -82,7 +82,7 @@ final class NBKFlexibleWidthTestsOnDivisionAsUIntXL: XCTestCase { } //=------------------------------------------------------------------------= - // MARK: Tests x Digit + // MARK: Tests x Digit (and Self) //=------------------------------------------------------------------------= func testDividingByDigit() { @@ -164,34 +164,58 @@ private func NBKAssertDivision( _ lhs: T, _ rhs: T, _ quotient: T, _ remainder: T, _ overflow: Bool = false, file: StaticString = #file, line: UInt = #line) { //=------------------------------------------= - XCTAssertEqual(lhs, quotient * rhs + remainder, "dividend != divisor * quotient + remainder", file: file, line: line) - //=------------------------------------------= + if !overflow { + XCTAssertEqual(lhs, quotient * rhs + remainder, "lhs != rhs * quotient + remainder", file: file, line: line) + } + if !overflow { XCTAssertEqual(lhs / rhs, quotient, file: file, line: line) XCTAssertEqual(lhs % rhs, remainder, file: file, line: line) - - XCTAssertEqual({ var x = lhs; x /= rhs; return x }(), quotient, file: file, line: line) - XCTAssertEqual({ var x = lhs; x %= rhs; return x }(), remainder, file: file, line: line) - - XCTAssertEqual(lhs.quotientAndRemainder(dividingBy: rhs).quotient, quotient, file: file, line: line) - XCTAssertEqual(lhs.quotientAndRemainder(dividingBy: rhs).remainder, remainder, file: file, line: line) + } + + if !overflow { + XCTAssertEqual({ var lhs = lhs; lhs /= rhs; return lhs }(), quotient, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs %= rhs; return lhs }(), remainder, file: file, line: line) + } + + if !overflow { + let out = lhs.quotientAndRemainder(dividingBy: rhs) + XCTAssertEqual(out.quotient, quotient, file: file, line: line) + XCTAssertEqual(out.remainder, remainder, file: file, line: line) } //=------------------------------------------= - XCTAssertEqual(lhs.dividedReportingOverflow(by: rhs).partialValue, quotient, file: file, line: line) - XCTAssertEqual(lhs.dividedReportingOverflow(by: rhs).overflow, overflow, file: file, line: line) + brr: do { + let out = lhs.dividedReportingOverflow(by: rhs) + XCTAssertEqual(out.partialValue, quotient, file: file, line: line) + XCTAssertEqual(out.overflow, overflow, file: file, line: line) + } - XCTAssertEqual({ var x = lhs; let _ = x.divideReportingOverflow(by: rhs); return x }(), quotient, file: file, line: line) - XCTAssertEqual({ var x = lhs; let o = x.divideReportingOverflow(by: rhs); return o }(), overflow, file: file, line: line) + brr: do { + var lhs = lhs + let out = lhs.divideReportingOverflow(by: rhs) + XCTAssertEqual(lhs, quotient, file: file, line: line) + XCTAssertEqual(out, overflow, file: file, line: line) + } - XCTAssertEqual(lhs.remainderReportingOverflow(dividingBy: rhs).partialValue, remainder, file: file, line: line) - XCTAssertEqual(lhs.remainderReportingOverflow(dividingBy: rhs).overflow, overflow, file: file, line: line) + brr: do { + let out = lhs.remainderReportingOverflow(dividingBy: rhs) + XCTAssertEqual(out.partialValue, remainder, file: file, line: line) + XCTAssertEqual(out.overflow, overflow, file: file, line: line) + } - XCTAssertEqual({ var x = lhs; let _ = x.formRemainderReportingOverflow(dividingBy: rhs); return x }(), remainder, file: file, line: line) - XCTAssertEqual({ var x = lhs; let o = x.formRemainderReportingOverflow(dividingBy: rhs); return o }(), overflow, file: file, line: line) - - XCTAssertEqual(lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs).partialValue.quotient, quotient, file: file, line: line) - XCTAssertEqual(lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs).partialValue.remainder, remainder, file: file, line: line) - XCTAssertEqual(lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs).overflow, overflow, file: file, line: line) + brr: do { + var lhs = lhs + let out = lhs.formRemainderReportingOverflow(dividingBy: rhs) + XCTAssertEqual(lhs, remainder, file: file, line: line) + XCTAssertEqual(out, overflow, file: file, line: line) + } + + brr: do { + let pvo = lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs) + XCTAssertEqual(pvo.partialValue.quotient, quotient, file: file, line: line) + XCTAssertEqual(pvo.partialValue.remainder, remainder, file: file, line: line) + XCTAssertEqual(pvo.overflow, overflow, file: file, line: line) + } //=------------------------------------------= guard let lhs = lhs as? UIntXL, @@ -200,9 +224,12 @@ file: StaticString = #file, line: UInt = #line) { let remainder = remainder as? UIntXL else { return } //=------------------------------------------= - XCTAssertEqual(lhs.quotientAndRemainderReportingOverflowAsNormal(dividingBy: rhs).partialValue.quotient, quotient, file: file, line: line) - XCTAssertEqual(lhs.quotientAndRemainderReportingOverflowAsNormal(dividingBy: rhs).partialValue.remainder, remainder, file: file, line: line) - XCTAssertEqual(lhs.quotientAndRemainderReportingOverflowAsNormal(dividingBy: rhs).overflow, overflow, file: file, line: line) + brr: do { + let pvo = lhs.quotientAndRemainderReportingOverflowByLongDivision(dividingBy: rhs) + XCTAssertEqual(pvo.partialValue.quotient, quotient, file: file, line: line) + XCTAssertEqual(pvo.partialValue.remainder, remainder, file: file, line: line) + XCTAssertEqual(pvo.overflow, overflow, file: file, line: line) + } } private func NBKAssertDivisionByDigit( @@ -210,34 +237,75 @@ _ lhs: T, _ rhs: T.Digit, _ quotient: T, _ remainder: T.Digit, _ overflow: Bool file: StaticString = #file, line: UInt = #line) { let extended = T(digit: remainder) //=------------------------------------------= - XCTAssertEqual(lhs, quotient * rhs + remainder, "dividend != divisor * quotient + remainder", file: file, line: line) + NBKAssertDivision(lhs, T(digit: rhs), quotient, T(digit: remainder), overflow, file: file, line: line) //=------------------------------------------= + if !overflow { + XCTAssertEqual(lhs, quotient * rhs + remainder, "lhs != rhs * quotient + remainder", file: file, line: line) + } + if !overflow { XCTAssertEqual(lhs / rhs, quotient, file: file, line: line) XCTAssertEqual(lhs % rhs, remainder, file: file, line: line) - - XCTAssertEqual({ var x = lhs; x /= rhs; return x }(), quotient, file: file, line: line) - XCTAssertEqual({ var x = lhs; x %= rhs; return x }(), extended, file: file, line: line) - - XCTAssertEqual(lhs.quotientAndRemainder(dividingBy: rhs).quotient, quotient, file: file, line: line) - XCTAssertEqual(lhs.quotientAndRemainder(dividingBy: rhs).remainder, remainder, file: file, line: line) + } + + if !overflow { + XCTAssertEqual({ var lhs = lhs; lhs /= rhs; return lhs }(), quotient, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs %= rhs; return lhs }(), extended, file: file, line: line) + } + + if !overflow { + let out = lhs.quotientAndRemainder(dividingBy: rhs) + XCTAssertEqual(out.quotient, quotient, file: file, line: line) + XCTAssertEqual(out.remainder, remainder, file: file, line: line) } //=------------------------------------------= - XCTAssertEqual(lhs.dividedReportingOverflow(by: rhs).partialValue, quotient, file: file, line: line) - XCTAssertEqual(lhs.dividedReportingOverflow(by: rhs).overflow, overflow, file: file, line: line) + brr: do { + let out = lhs.dividedReportingOverflow(by: rhs) + XCTAssertEqual(out.partialValue, quotient, file: file, line: line) + XCTAssertEqual(out.overflow, overflow, file: file, line: line) + } - XCTAssertEqual({ var x = lhs; let _ = x.divideReportingOverflow(by: rhs); return x }(), quotient, file: file, line: line) - XCTAssertEqual({ var x = lhs; let o = x.divideReportingOverflow(by: rhs); return o }(), overflow, file: file, line: line) + brr: do { + var lhs = lhs + let out = lhs.divideReportingOverflow(by: rhs) + XCTAssertEqual(lhs, quotient, file: file, line: line) + XCTAssertEqual(out, overflow, file: file, line: line) + } - XCTAssertEqual(lhs.remainderReportingOverflow(dividingBy: rhs).partialValue, remainder, file: file, line: line) - XCTAssertEqual(lhs.remainderReportingOverflow(dividingBy: rhs).overflow, overflow, file: file, line: line) + brr: do { + let out = lhs.remainderReportingOverflow(dividingBy: rhs) + XCTAssertEqual(out.partialValue, remainder, file: file, line: line) + XCTAssertEqual(out.overflow, overflow, file: file, line: line) + } - XCTAssertEqual({ var x = lhs; let _ = x.formRemainderReportingOverflow(dividingBy: rhs); return x }(), extended, file: file, line: line) - XCTAssertEqual({ var x = lhs; let o = x.formRemainderReportingOverflow(dividingBy: rhs); return o }(), overflow, file: file, line: line) + brr: do { + var lhs = lhs + let out = lhs.formRemainderReportingOverflow(dividingBy: rhs) + XCTAssertEqual(lhs, extended, file: file, line: line) + XCTAssertEqual(out, overflow, file: file, line: line) + } - XCTAssertEqual(lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs).partialValue.quotient, quotient, file: file, line: line) - XCTAssertEqual(lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs).partialValue.remainder, remainder, file: file, line: line) - XCTAssertEqual(lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs).overflow, overflow, file: file, line: line) + brr: do { + let pvo = lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs) + XCTAssertEqual(pvo.partialValue.quotient, quotient, file: file, line: line) + XCTAssertEqual(pvo.partialValue.remainder, remainder, file: file, line: line) + XCTAssertEqual(pvo.overflow, overflow, file: file, line: line) + } + //=------------------------------------------= + guard + let lhs = lhs as? UIntXL, + let rhs = rhs as? UInt, + let quotient = quotient as? UIntXL, + let remainder = remainder as? UInt + else { return } + //=------------------------------------------= + brr: do { + var lhs = lhs + let pvo = lhs.formQuotientWithRemainderReportingOverflow(dividingBy: rhs) + XCTAssertEqual(lhs, quotient, file: file, line: line) + XCTAssertEqual(pvo.partialValue, remainder, file: file, line: line) + XCTAssertEqual(pvo.overflow, overflow, file: file, line: line) + } } #endif From a671bdec6836351c1e51f6908c36dc69f6079c74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Wed, 18 Oct 2023 11:34:05 +0200 Subject: [PATCH 097/133] [NBKFlexibleWidthKit] Division. --- .../NBKFlexibleWidth+Division.swift | 32 +++------- .../NBKStrictUnsignedInteger+Division.swift | 62 +++++++++++++++++++ 2 files changed, 69 insertions(+), 25 deletions(-) create mode 100644 Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Division.swift diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift index 41cd1e75..6a1b7ac7 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift @@ -107,31 +107,12 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= let quotient = Self.uninitialized(count: self.count - other.count) { quotient in self.storage.withUnsafeMutableBufferPointer { remainder in - other.storage.withUnsafeBufferPointer { divisor in - //=--------------------------= - let divisorLast: UInt = divisor.last! - var remainderIndex = remainder.index(before: remainder.endIndex) - for quotientIndex in quotient.indices.reversed() { - //=----------------------= - let remainderLast0 = remainder[remainderIndex] - remainder.formIndex(before: &remainderIndex) - let remainderLast1 = remainder[remainderIndex] - //=----------------------= - var digit: UInt - if divisorLast == remainderLast0 { - digit = UInt.max - } else { - digit = divisorLast.dividingFullWidth(HL(high: remainderLast0, low: remainderLast1)).quotient - } - //=----------------------= - if !digit.isZero { - var overflow = (NBK).SUISS.decrement(&remainder, by: divisor, times: digit, at: quotientIndex).overflow - correctQuotientAtMostTwice: while overflow { - digit &-= 1 as Digit // the quotient digit is decremented until product ≤ remainder - overflow = !NBK .SUISS.increment(&remainder, by: divisor, at: quotientIndex).overflow - } - } - //=----------------------= + other.storage.withUnsafeBufferPointer { (divisor) in + var remainderIndex = remainder.endIndex as Int + for (quotientIndex) in quotient.indices.reversed() { + remainder.formIndex(before: &remainderIndex) + let digit = NBK.SUI.quotientFromLongDivisionIteration211MSBUnchecked( + dividing: &remainder[...remainderIndex], by: divisor) quotient.baseAddress!.advanced(by: quotientIndex).initialize(to: digit) } } @@ -145,6 +126,7 @@ extension NBKFlexibleWidth.Magnitude { } self.storage.normalize() + Swift.assert(quotient.storage.isNormal) //=--------------------------------------= return PVO(partialValue: quotient, overflow: false) } diff --git a/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Division.swift b/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Division.swift new file mode 100644 index 00000000..fe88fd59 --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/Private/NBKStrictUnsignedInteger+Division.swift @@ -0,0 +1,62 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Strict Unsigned Integer x Division +//*============================================================================* +//=----------------------------------------------------------------------------= +// MARK: + Elements where Base is Mutable Collection +//=----------------------------------------------------------------------------= + +extension NBK.StrictUnsignedInteger where Base: MutableCollection { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + /// Returns the quotient element of one long division iteration, then decrements the remainder accordingly. + /// + /// - TODO: Remainder and divisor comparisons in DEBUG mode. + /// - TODO: It would not need pointers slices if it took the last remainder index. + /// + @inlinable static func quotientFromLongDivisionIteration211MSBUnchecked( + dividing remainder: inout Base, by divisor: some RandomAccessCollection) -> Base.Element { + //=--------------------------------------= + Swift.assert(divisor.last!.mostSignificantBit, "the divisor must be normalized") + Swift.assert(remainder.count > divisor.count, "the remainder must be wider than the divisor") + //=--------------------------------------= + var index: Base.Index = remainder.endIndex + + let numerator: NBK.Wide2 + remainder.formIndex(before: &index); numerator.high = remainder[index] + remainder.formIndex(before: &index); numerator.low = remainder[index] + + let denominator = divisor[divisor.index(before: divisor.endIndex)] as Base.Element + //=--------------------------------------= + var quotient : Base.Element; if denominator == numerator.high { // await Swift 5.9 + quotient = Base.Element.max + } else { + quotient = denominator.dividingFullWidth(numerator).quotient + } + //=--------------------------------------= + if quotient.isZero { return quotient } + //=--------------------------------------= + let position = remainder.index(remainder.endIndex, offsetBy: divisor.count.onesComplement()) + var overflow = (NBK).SUISS.decrement(&remainder, by: divisor, times: quotient, at: position).overflow + + correctQuotientApproximationAtMostTwice: while overflow { + quotient = quotient &- 1 as Base.Element + overflow = !NBK .SUISS.increment(&remainder, by: divisor, at: position).overflow + } + + return quotient as Base.Element + } +} From b1eb6ba5babee985b47b2c43319c53e168d22d01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sat, 21 Oct 2023 17:15:41 +0200 Subject: [PATCH 098/133] [NBKFlexibleWidthKit] Long multiplication algorithm. --- .../NBKFlexibleWidth+Division.swift | 10 +-- .../NBKFlexibleWidth+Multiplication.swift | 65 ++++++++++--------- .../NBKFlexibleWidth+Division.swift | 2 +- .../NBKFlexibleWidth+Multiplication.swift | 37 +++++++---- 4 files changed, 68 insertions(+), 46 deletions(-) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift index f1136324..607c37f9 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift @@ -42,12 +42,12 @@ extension NBKFlexibleWidth.Magnitude { } @inlinable public func quotientAndRemainderReportingOverflow(dividingBy other: Self) -> PVO> { - self.quotientAndRemainderReportingOverflowByLongDivision(dividingBy: other) + self.quotientAndRemainderReportingOverflowUsingLongAlgorithm(dividingBy: other) } } //=----------------------------------------------------------------------------= -// MARK: + Normal +// MARK: + Long Division //=----------------------------------------------------------------------------= extension NBKFlexibleWidth.Magnitude { @@ -57,14 +57,14 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= /// Performs long division after some fast-path checks. - @inlinable func quotientAndRemainderReportingOverflowByLongDivision(dividingBy other: Self) -> PVO> { + @inlinable func quotientAndRemainderReportingOverflowUsingLongAlgorithm(dividingBy other: Self) -> PVO> { var (remainder) = self - let (quotient, overflow) = remainder.formRemainderWithQuotientReportingOverflowByLongDivision(dividingBy: other) + let (quotient, overflow) = remainder.formRemainderWithQuotientReportingOverflowUsingLongAlgorithm(dividingBy: other) return PVO(QR(quotient, remainder), overflow) } /// Performs long division after some fast-path checks. - @inlinable mutating func formRemainderWithQuotientReportingOverflowByLongDivision(dividingBy other: Self) -> PVO { + @inlinable mutating func formRemainderWithQuotientReportingOverflowUsingLongAlgorithm(dividingBy other: Self) -> PVO { //=--------------------------------------= // divisor is zero //=--------------------------------------= diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift index e98152eb..46a6045c 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift @@ -24,46 +24,53 @@ extension NBKFlexibleWidth.Magnitude { } @inlinable public static func *(lhs: Self, rhs: Self) -> Self { - Self(normalizing: lhs.storage.multipliedFullWidth(by: rhs.storage)) + lhs.multipliedFullWidthUsingLongAlgorithm(by: rhs, adding: 0 as UInt) } } -//*============================================================================* -// MARK: * NBK x Flexible Width x Multiplication x Unsigned x Storage -//*============================================================================* +//=----------------------------------------------------------------------------= +// MARK: + Long Multiplication +//=----------------------------------------------------------------------------= -extension NBKFlexibleWidth.Magnitude.Storage { +extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= // MARK: Transformations //=------------------------------------------------------------------------= - @inlinable func multipliedFullWidth(by multiplicand: Self) -> Self { - self.multipliedFullWidthByNaiveMethod(by: multiplicand, adding: 0 as UInt) - } - - @inlinable func multipliedFullWidthByNaiveMethod(by multiplicand: Self, adding addend: UInt) -> Self { - Self.uninitialized(count: self.elements.count + multiplicand.elements.count) { product in - //=----------------------------------= - // pointee: initialization - //=----------------------------------= - product.initialize(repeating: 0 as UInt) - //=----------------------------------= - var overflow = addend as UInt - for lhsIndex in self.elements.indices { - let outer = self.elements[lhsIndex] - - for rhsIndex in multiplicand.elements.indices { - let inner = multiplicand.elements[rhsIndex] - var subproduct = outer.multipliedFullWidth(by: inner) + /// Performs long multiplication. + @inlinable func multipliedFullWidthUsingLongAlgorithm(by multiplier: Self, adding addend: UInt) -> Self { + Self.uninitialized(count: self.count + multiplier.count) { pro in + self.storage.withUnsafeBufferPointer { lhs in + multiplier.storage.withUnsafeBufferPointer { rhs in + var pointer = pro.baseAddress! + //=--------------------------= + // pointee: initialization 1 + //=--------------------------= + var carry = addend as UInt + let multiplier = rhs.first! + + for element in lhs { + var wide = element.multipliedFullWidth(by: multiplier) + carry = UInt(bit: wide.low.addReportingOverflow(carry)) &+ wide.high + pointer.initialize(to: wide.low) // done, pointee has no prior value + pointer = pointer.successor() + } + + pointer.initialize(to: carry) + pointer = pointer.successor() + Swift.assert(pro.baseAddress!.distance(to: pointer) == lhs.count + 1) + //=--------------------------= + // pointee: initialization 2 + //=--------------------------= + for var index in rhs.indices.dropFirst() { + pointer.initialize(to: 00000) + pointer = pointer.successor() + NBK.SUISS.incrementInIntersection(&pro, by: lhs, times: rhs[index], plus: 00000, at: &index) + } - overflow = UInt(bit: subproduct.low.addReportingOverflow(overflow)) - overflow &+= UInt(bit: product[lhsIndex + rhsIndex].addReportingOverflow(subproduct.low)) - overflow &+= subproduct.high + Swift.assert(pro.baseAddress!.distance(to: pointer) == pro.count) } - - product[lhsIndex + multiplicand.elements.count] = overflow // update - overflow = 0 as UInt } } } diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Division.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Division.swift index b4cef8b4..2ddf0c66 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Division.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Division.swift @@ -225,7 +225,7 @@ file: StaticString = #file, line: UInt = #line) { else { return } //=------------------------------------------= brr: do { - let pvo = lhs.quotientAndRemainderReportingOverflowByLongDivision(dividingBy: rhs) + let pvo = lhs.quotientAndRemainderReportingOverflowUsingLongAlgorithm(dividingBy: rhs) XCTAssertEqual(pvo.partialValue.quotient, quotient, file: file, line: line) XCTAssertEqual(pvo.partialValue.remainder, remainder, file: file, line: line) XCTAssertEqual(pvo.overflow, overflow, file: file, line: line) diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Multiplication.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Multiplication.swift index e236c25a..36dcf6d6 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Multiplication.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Multiplication.swift @@ -10,7 +10,7 @@ #if DEBUG import NBKCoreKit -import NBKFlexibleWidthKit +@testable import NBKFlexibleWidthKit import XCTest private typealias W = [UInt] @@ -43,7 +43,7 @@ final class NBKFlexibleWidthTestsOnMultiplicationAsUIntXL: XCTestCase { } //=------------------------------------------------------------------------= - // MARK: Tests x Digit + // MARK: Tests x Digit (and Self) //=------------------------------------------------------------------------= func testMultipliedByDigit() { @@ -87,17 +87,29 @@ final class NBKFlexibleWidthTestsOnMultiplicationAsUIntXL: XCTestCase { //*============================================================================* private func NBKAssertMultiplication( -_ lhs: T, _ rhs: T, _ result: T, +_ lhs: T, _ rhs: T, _ pro: T, file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual( lhs * rhs, result, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs *= rhs; return lhs }(), result, file: file, line: line) + //=------------------------------------------= + XCTAssertEqual( lhs * rhs, pro, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs *= rhs; return lhs }(), pro, file: file, line: line) + //=------------------------------------------= + guard + let lhs = lhs as? UIntXL, + let rhs = rhs as? UIntXL, + let pro = pro as? UIntXL + else { return } + //=------------------------------------------= + XCTAssertEqual(lhs.multipliedFullWidthUsingLongAlgorithm(by: rhs, adding: 0), pro, file: file, line: line) } private func NBKAssertMultiplicationByDigit( -_ lhs: T, _ rhs: T.Digit, _ result: T, +_ lhs: T, _ rhs: T.Digit, _ pro: T, file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual( lhs * rhs, result, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs *= rhs; return lhs }(), result, file: file, line: line) + //=------------------------------------------= + XCTAssertEqual( lhs * rhs, pro, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs *= rhs; return lhs }(), pro, file: file, line: line) + //=------------------------------------------= + NBKAssertMultiplication(lhs, T(digit: rhs), pro, file: file, line: line) } //=----------------------------------------------------------------------------= @@ -105,10 +117,13 @@ file: StaticString = #file, line: UInt = #line) { //=----------------------------------------------------------------------------= private func NBKAssertMultiplicationByDigitWithAddition( -_ lhs: UIntXL, _ rhs: UInt, _ carry: UInt, _ product: UIntXL, +_ lhs: UIntXL, _ rhs: UInt, _ add: UInt, _ pro: UIntXL, file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual(lhs.multiplied(by: rhs, adding: carry), product, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs.multiply(by: rhs, add: carry); return lhs }(), product, file: file, line: line) + //=------------------------------------------= + XCTAssertEqual(lhs.multiplied(by: rhs, adding: add), pro, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs.multiply(by: rhs, add: add); return lhs }(), pro, file: file, line: line) + //=------------------------------------------= + XCTAssertEqual(lhs.multipliedFullWidthUsingLongAlgorithm(by: UIntXL(digit: rhs), adding: add), pro, file: file, line: line) } #endif From e062037089d8b747b1944835f91ca1b0a0fc5ae2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sun, 22 Oct 2023 09:31:43 +0200 Subject: [PATCH 099/133] [NBKFlexibleWidthKit] Cleanup. --- .../NBKFlexibleWidth+Multiplication.swift | 8 ++++---- .../NBKFlexibleWidth+Words+Uninitialized.swift | 18 +++++++++++++----- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift index 46a6045c..ccbef8f2 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift @@ -47,11 +47,11 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------= // pointee: initialization 1 //=--------------------------= - var carry = addend as UInt - let multiplier = rhs.first! + var carry: UInt = addend + let first: UInt = rhs.first! for element in lhs { - var wide = element.multipliedFullWidth(by: multiplier) + var wide = element.multipliedFullWidth(by: first) as NBK.Wide2 carry = UInt(bit: wide.low.addReportingOverflow(carry)) &+ wide.high pointer.initialize(to: wide.low) // done, pointee has no prior value pointer = pointer.successor() @@ -63,7 +63,7 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------= // pointee: initialization 2 //=--------------------------= - for var index in rhs.indices.dropFirst() { + for var index in 1 ..< rhs.count { pointer.initialize(to: 00000) pointer = pointer.successor() NBK.SUISS.incrementInIntersection(&pro, by: lhs, times: rhs[index], plus: 00000, at: &index) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words+Uninitialized.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words+Uninitialized.swift index 3acbbd1d..2162ed4f 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words+Uninitialized.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words+Uninitialized.swift @@ -16,12 +16,16 @@ import NBKCoreKit extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= - // MARK: Initializers x Private + // MARK: Initializers //=------------------------------------------------------------------------= /// Creates a new instance with unsafe access to its uninitialized memory. - @inlinable static func uninitialized(count: Int, body: (inout NBK.UnsafeMutableWords) -> Void) -> Self { - Self(normalizing: Storage.uninitialized(count: count, body: body)) + /// + /// The `init` is responsible for initializing the words given to it. + /// + @inlinable public static func uninitialized( + count: Int, init: (inout UnsafeMutableBufferPointer) -> Void) -> Self { + Self(normalizing: Storage.uninitialized(count: count, init: `init`)) } } @@ -36,7 +40,11 @@ extension NBKFlexibleWidth.Magnitude.Storage { //=------------------------------------------------------------------------= /// Creates a new instance with unsafe access to its uninitialized memory. - @inlinable static func uninitialized(count: Int, body: (inout NBK.UnsafeMutableWords) -> Void) -> Self { - Self(Elements(unsafeUninitializedCapacity: count) { body(&$0); $1 = $0.count }) + /// + /// The `init` is responsible for initializing the words given to it. + /// + @inlinable static func uninitialized( + count: Int, init: (inout UnsafeMutableBufferPointer) -> Void) -> Self { + Self(Elements(unsafeUninitializedCapacity: count) { `init`(&$0); $1 = $0.count }) } } From 2b02ab11d54696589d76d9a9d79fa5360ff0482a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sun, 22 Oct 2023 09:33:25 +0200 Subject: [PATCH 100/133] [NBKFlexibleWidthKit] Words. Uninitialized. --- .../NBKFlexibleWidthKit/IntXLOrUIntXL.swift | 105 ++++++++++++++++++ .../NBKFlexibleWidth+Words+Pointers.swift | 51 ++------- ...NBKFlexibleWidth+Words+Uninitialized.swift | 54 +++++++-- .../NBKFlexibleWidth+Words.swift | 72 +++++++++++- 4 files changed, 225 insertions(+), 57 deletions(-) diff --git a/Sources/NBKFlexibleWidthKit/IntXLOrUIntXL.swift b/Sources/NBKFlexibleWidthKit/IntXLOrUIntXL.swift index 1db898df..a77780b7 100644 --- a/Sources/NBKFlexibleWidthKit/IntXLOrUIntXL.swift +++ b/Sources/NBKFlexibleWidthKit/IntXLOrUIntXL.swift @@ -100,6 +100,111 @@ public protocol IntXLOrUIntXL: NBKBinaryInteger, ExpressibleByStringLiteral wher @inlinable mutating func updateZeroValue() @inlinable mutating func update(_ value: Digit) + + //=------------------------------------------------------------------------= + // MARK: Details x Words + //=------------------------------------------------------------------------= + + /// Grants unsafe access to the words of this instance. + /// + /// ``` + /// ┌──────────────────────── = ───────────────────────────┐ + /// │ self │ words on a 64-bit machine │ + /// ├──────────────────────── = ───────────────────────────┤ + /// │ IntXL( ) │ [ 0 ] │ + /// │ IntXL( Int256.max) │ [~0, ~0, ~0, ~0/2 + 0 ] │ + /// │ IntXL( Int256.max) + 1 │ [ 0, 0, 0, ~0/2 + 1, 0] │ + /// │ IntXL( Int256.min) │ [ 0, 0, 0, ~0/2 + 1 ] │ + /// │ IntXL( Int256.min) + 1 │ [~0, ~0, ~0, ~0/2 + 0, ~0] │ + /// │ IntXL(UInt256.max) │ [~0, ~0, ~0, ~0/1 + 0, 0] │ + /// │ IntXL(UInt256.max) + 1 │ [ 0, 0, 0, 0/1 + 0, 1] │ + /// ├──────────────────────── = ───────────────────────────┤ + /// │ UIntXL( ) │ [ 0 ] │ + /// │ UIntXL( Int256.max) │ [~0, ~0, ~0, ~0/2 + 0 ] │ + /// │ UIntXL( Int256.max) + 1 │ [ 0, 0, 0, ~0/2 + 1 ] │ + /// │ UIntXL(UInt256.max) │ [~0, ~0, ~0, ~0/1 + 0 ] │ + /// │ UIntXL(UInt256.max) + 1 │ [ 0, 0, 0, 0/1 + 0, 1] │ + /// └──────────────────────── = ───────────────────────────┘ + /// ``` + /// + @inlinable func withUnsafeBufferPointer( + _ body: (UnsafeBufferPointer) throws -> T) rethrows -> T + + /// Grants unsafe access to the mutable words of this instance. + /// + /// ``` + /// ┌──────────────────────── = ───────────────────────────┐ + /// │ self │ words on a 64-bit machine │ + /// ├──────────────────────── = ───────────────────────────┤ + /// │ IntXL( ) │ [ 0 ] │ + /// │ IntXL( Int256.max) │ [~0, ~0, ~0, ~0/2 + 0 ] │ + /// │ IntXL( Int256.max) + 1 │ [ 0, 0, 0, ~0/2 + 1, 0] │ + /// │ IntXL( Int256.min) │ [ 0, 0, 0, ~0/2 + 1 ] │ + /// │ IntXL( Int256.min) + 1 │ [~0, ~0, ~0, ~0/2 + 0, ~0] │ + /// │ IntXL(UInt256.max) │ [~0, ~0, ~0, ~0/1 + 0, 0] │ + /// │ IntXL(UInt256.max) + 1 │ [ 0, 0, 0, 0/1 + 0, 1] │ + /// ├──────────────────────── = ───────────────────────────┤ + /// │ UIntXL( ) │ [ 0 ] │ + /// │ UIntXL( Int256.max) │ [~0, ~0, ~0, ~0/2 + 0 ] │ + /// │ UIntXL( Int256.max) + 1 │ [ 0, 0, 0, ~0/2 + 1 ] │ + /// │ UIntXL(UInt256.max) │ [~0, ~0, ~0, ~0/1 + 0 ] │ + /// │ UIntXL(UInt256.max) + 1 │ [ 0, 0, 0, 0/1 + 0, 1] │ + /// └──────────────────────── = ───────────────────────────┘ + /// ``` + /// + /// - Note: The words of this instance will be normalized after this operation. + /// + @inlinable mutating func withUnsafeMutableBufferPointer( + _ body: (inout UnsafeMutableBufferPointer) throws -> T) rethrows -> T + + /// Creates a new instance with unsafe access to its uninitialized words. + /// + /// The `init` is responsible for initializing all `count` words given to it. + /// + /// - Note: While the resulting instance may have a capacity larger than the + /// requested amount, the buffer passed to `init` will cover exactly the requested + /// number of words. + /// + /// - Note: This is a non-throwing convenience for `uninitialized(capacity:init:)`. + /// + /// ### No initialized prefix semantics + /// + /// It returns zero when the initialized prefix count is zero because the following + /// expressions must return the same values: + /// + /// ```swift + /// 1. Self.init(words: words) // this is zero when words == [] + /// 2. Self.uninitialized(count: words.count) { _ = $0.initialize(from: words).index } + /// 3. Self.uninitialized(capacity: words.count) { $1 = $0.initialize(from: words).index } + /// ``` + /// + @inlinable static func uninitialized( + count: Int, init: (inout UnsafeMutableBufferPointer) -> Void) -> Self + + /// Creates a new instance with unsafe access to its uninitialized words. + /// + /// The `init` is responsible for initializing up to `capacity` prefixing words. + /// The `init` is given a buffer and an initialized prefix count. All words in + /// the prefix must be initialized and all words after it must be uninitialized. + /// This postcondition must hold even when the `init` throws an error. + /// + /// - Note: While the resulting instance may have a capacity larger than the + /// requested amount, the buffer passed to `init` will cover exactly the requested + /// number of words. + /// + /// ### No initialized prefix semantics + /// + /// It returns zero when the initialized prefix count is zero because the following + /// expressions must return the same values: + /// + /// ```swift + /// 1. Self.init(words: words) // this is zero when words == [] + /// 2. Self.uninitialized(count: words.count) { _ = $0.initialize(from: words).index } + /// 3. Self.uninitialized(capacity: words.count) { $1 = $0.initialize(from: words).index } + /// ``` + /// + @inlinable static func uninitialized( + capacity: Int, init: (inout UnsafeMutableBufferPointer, inout Int) throws -> Void) rethrows -> Self } //=----------------------------------------------------------------------------= diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words+Pointers.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words+Pointers.swift index 8e62f542..e668bfca 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words+Pointers.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words+Pointers.swift @@ -21,43 +21,16 @@ extension NBKFlexibleWidth.Magnitude { /// Grants unsafe access to the collection's contiguous storage. @inlinable public func withUnsafeBufferPointer( - _ body:(NBK.UnsafeWords) throws -> T) rethrows -> T { + _ body: (UnsafeBufferPointer) throws -> T) rethrows -> T { try self.storage.withUnsafeBufferPointer(body) } /// Grants unsafe access to the collection's contiguous mutable storage. @inlinable public mutating func withUnsafeMutableBufferPointer( - _ body:(inout NBK.UnsafeMutableWords) throws -> T) rethrows -> T { + _ body: (inout UnsafeMutableBufferPointer) throws -> T) rethrows -> T { defer{ self.storage.normalize() } return try self.storage.withUnsafeMutableBufferPointer(body) } - - //=------------------------------------------------------------------------= - // MARK: Details x Contiguous UInt Collection x Sub Sequence - //=------------------------------------------------------------------------= - - /// Grants unsafe access to the collection's contiguous storage in the given `range`. - /// - /// ### Development - /// - /// This method is required for performance reasons. - /// - @inlinable public func withUnsafeBufferPointer( - in range: some RangeExpression, perform body:(inout NBK.UnsafeWords) throws -> T) rethrows -> T { - try self.storage.withUnsafeBufferPointer(in: range, perform: body) - } - - /// Grants unsafe access to the collection's contiguous mutable storage in the given `range`. - /// - /// ### Development - /// - /// This method is required for performance reasons. - /// - @inlinable public mutating func withUnsafeMutableBufferPointer( - in range: some RangeExpression, perform body:(inout NBK.UnsafeMutableWords) throws -> T) rethrows -> T { - defer{ self.storage.normalize() } - return try self.storage.withUnsafeMutableBufferPointer(in: range, perform: body) - } } //*============================================================================* @@ -72,43 +45,43 @@ extension NBKFlexibleWidth.Magnitude.Storage { /// Grants unsafe access to the collection's contiguous storage. @inlinable func withUnsafeBufferPointer( - _ body:(NBK.UnsafeWords) throws -> T) rethrows -> T { + _ body: (UnsafeBufferPointer) throws -> T) rethrows -> T { try self.elements.withUnsafeBufferPointer(body) } /// Grants unsafe access to the collection's contiguous mutable storage. @inlinable mutating func withUnsafeMutableBufferPointer( - _ body:(inout NBK.UnsafeMutableWords) throws -> T) rethrows -> T { + _ body: (inout UnsafeMutableBufferPointer) throws -> T) rethrows -> T { try self.elements.withUnsafeMutableBufferPointer(body) } //=------------------------------------------------------------------------= // MARK: Details x Contiguous UInt Collection x Sub Sequence //=------------------------------------------------------------------------= - + /// Grants unsafe access to the collection's contiguous storage in the given `range`. /// /// ### Development /// - /// This method is required for performance reasons. + /// This method is required for performance reasons (see slice arithmetic). /// - @inlinable func withUnsafeBufferPointer( - in range: some RangeExpression, perform body:(inout NBK.UnsafeWords) throws -> T) rethrows -> T { + @inlinable func withUnsafeBufferPointer(in range: some RangeExpression, + perform body: (inout UnsafeBufferPointer) throws -> T) rethrows -> T { try self.withUnsafeBufferPointer { let range = range.relative(to: $0) var slice = NBK.UnsafeWords(start: $0.baseAddress! + range.lowerBound, count: range.count) return try body(&slice) as T } } - + /// Grants unsafe access to the collection's contiguous mutable storage in the given `range`. /// /// ### Development /// - /// This method is required for performance reasons. + /// This method is required for performance reasons (see slice arithmetic). /// - @inlinable mutating func withUnsafeMutableBufferPointer( - in range: some RangeExpression, perform body:(inout NBK.UnsafeMutableWords) throws -> T) rethrows -> T { + @inlinable mutating func withUnsafeMutableBufferPointer(in range: some RangeExpression, + perform body: (inout UnsafeMutableBufferPointer) throws -> T) rethrows -> T { try self.withUnsafeMutableBufferPointer { let range = range.relative(to: $0) var slice = NBK.UnsafeMutableWords(start: $0.baseAddress! + range.lowerBound, count: range.count) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words+Uninitialized.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words+Uninitialized.swift index 2162ed4f..af25eae1 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words+Uninitialized.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words+Uninitialized.swift @@ -9,6 +9,22 @@ import NBKCoreKit +//*============================================================================* +// MARK: * NBK x Double Width x Words x Uninitialized +//*============================================================================* + +extension IntXLOrUIntXL { + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + @inlinable public static func uninitialized( + count: Int, init: (inout UnsafeMutableBufferPointer) -> Void) -> Self { + Self.uninitialized(capacity: count, init:{ $1 = $0.count; `init`(&$0) }) + } +} + //*============================================================================* // MARK: * NBK x Double Width x Words x Uninitialized x Unsigned //*============================================================================* @@ -19,13 +35,9 @@ extension NBKFlexibleWidth.Magnitude { // MARK: Initializers //=------------------------------------------------------------------------= - /// Creates a new instance with unsafe access to its uninitialized memory. - /// - /// The `init` is responsible for initializing the words given to it. - /// @inlinable public static func uninitialized( - count: Int, init: (inout UnsafeMutableBufferPointer) -> Void) -> Self { - Self(normalizing: Storage.uninitialized(count: count, init: `init`)) + capacity: Int, init: (inout UnsafeMutableBufferPointer, inout Int) throws -> Void) rethrows -> Self { + Self(normalizing: try Storage.uninitialized(capacity: capacity, init: `init`)) } } @@ -36,15 +48,33 @@ extension NBKFlexibleWidth.Magnitude { extension NBKFlexibleWidth.Magnitude.Storage { //=------------------------------------------------------------------------= - // MARK: Initializers x Private + // MARK: Initializers //=------------------------------------------------------------------------= - /// Creates a new instance with unsafe access to its uninitialized memory. + /// Creates a new instance with unsafe access to its uninitialized words. /// - /// The `init` is responsible for initializing the words given to it. + /// The `init` is responsible for initializing up to `capacity` prefixing words. + /// The `init` is given a buffer and an initialized prefix count. All words in + /// the prefix must be initialized and all words after it must be uninitialized. + /// This postcondition must hold even when the `init` throws an error. /// - @inlinable static func uninitialized( - count: Int, init: (inout UnsafeMutableBufferPointer) -> Void) -> Self { - Self(Elements(unsafeUninitializedCapacity: count) { `init`(&$0); $1 = $0.count }) + /// - Note: While the resulting instance may have a capacity larger than the + /// requested amount, the buffer passed to `init` will cover exactly the requested + /// number of words. + /// + /// ### No initialized prefix semantics + /// + /// It returns zero when the initialized prefix count is zero because the following + /// expressions must return the same values: + /// + /// ```swift + /// 1. Self.init(words: words) // this is zero when words == [] + /// 2. Self.uninitialized(count: words.count) { _ = $0.initialize(from: words).index } + /// 3. Self.uninitialized(capacity: words.count) { $1 = $0.initialize(from: words).index } + /// ``` + /// + @inlinable public static func uninitialized( + capacity: Int, init: (inout UnsafeMutableBufferPointer, inout Int) throws -> Void) rethrows -> Self { + Self(nonemptying: try Elements(unsafeUninitializedCapacity: capacity, initializingWith: `init`)) } } diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Words.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Words.swift index b0950f07..6cf0516a 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Words.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Words.swift @@ -62,6 +62,26 @@ final class NBKFlexibleWidthTestsOnWordsAsUIntXL: XCTestCase { NBKAssertToWords(T(words:[1, 2, 3, 4]), [1, 2, 3, 4]) } + + /// ``` + /// ┌──────────────────────── = ───────────────────────────┐ + /// │ self │ words on a 64-bit machine │ + /// ├──────────────────────── = ───────────────────────────┤ + /// │ IntXL( ) │ [ 0 ] │ + /// │ IntXL( Int256.max) │ [~0, ~0, ~0, ~0/2 + 0 ] │ + /// │ IntXL( Int256.max) + 1 │ [ 0, 0, 0, ~0/2 + 1, 0] │ + /// │ IntXL( Int256.min) │ [ 0, 0, 0, ~0/2 + 1 ] │ + /// │ IntXL( Int256.min) + 1 │ [~0, ~0, ~0, ~0/2 + 0, ~0] │ + /// │ IntXL(UInt256.max) │ [~0, ~0, ~0, ~0/1 + 0, 0] │ + /// │ IntXL(UInt256.max) + 1 │ [ 0, 0, 0, 0/1 + 0, 1] │ + /// ├──────────────────────── = ───────────────────────────┤ + /// │ UIntXL( ) │ [ 0 ] │ + /// │ UIntXL( Int256.max) │ [~0, ~0, ~0, ~0/2 + 0 ] │ + /// │ UIntXL( Int256.max) + 1 │ [ 0, 0, 0, ~0/2 + 1 ] │ + /// │ UIntXL(UInt256.max) │ [~0, ~0, ~0, ~0/1 + 0 ] │ + /// │ UIntXL(UInt256.max) + 1 │ [ 0, 0, 0, 0/1 + 0, 1] │ + /// └──────────────────────── = ───────────────────────────┘ + /// ``` func testToWordsX64() throws { guard MemoryLayout.size == MemoryLayout.size else { throw XCTSkip() } @@ -76,6 +96,11 @@ final class NBKFlexibleWidthTestsOnWordsAsUIntXL: XCTestCase { NBKAssertToWords(T(x64:[1, 2, 0, 0] as X), [1, 2 ]) NBKAssertToWords(T(x64:[1, 2, 3, 0] as X), [1, 2, 3 ]) NBKAssertToWords(T(x64:[1, 2, 3, 4] as X), [1, 2, 3, 4]) + + NBKAssertToWords(T(x64:[~0, ~0, ~0, ~0/2] as X), [~0, ~0, ~0, ~0/2 + 0 ] as W) // Int256.max + NBKAssertToWords(T(x64:[~0, ~0, ~0, ~0/2] as X) + 1, [ 0, 0, 0, ~0/2 + 1 ] as W) // Int256.max + 1 + NBKAssertToWords(T(x64:[~0, ~0, ~0, ~0/1] as X), [~0, ~0, ~0, ~0/1 + 0 ] as W) // UInt256.max + NBKAssertToWords(T(x64:[~0, ~0, ~0, ~0/1] as X) + 1, [ 0, 0, 0, 0/1 + 0, 1] as W) // UInt256.max + 1 } func testToWordsX32() throws { @@ -123,29 +148,64 @@ final class NBKFlexibleWidthTestsOnWordsAsUIntXL: XCTestCase { private func NBKAssertFromWords( _ words: [UInt], _ integer: T?, file: StaticString = #file, line: UInt = #line) { - + //=------------------------------------------= XCTAssertEqual( T(words: words), integer, file: file, line: line) XCTAssertEqual(integer.flatMap({ T(words: $0.words) }), integer, file: file, line: line) + //=------------------------------------------= + if let integer { + NBKAssertFromWordsByTruncating(words, words.count, integer) + } } private func NBKAssertFromWordsIsSigned( _ words: [UInt], _ isSigned: Bool, _ integer: T?, file: StaticString = #file, line: UInt = #line) { - + //=------------------------------------------= if isSigned == T.isSigned { NBKAssertFromWords(words, integer, file: file, line: line) } - + //=------------------------------------------= XCTAssertEqual( T(words: words, isSigned: isSigned), integer, file: file, line: line) XCTAssertEqual(integer.flatMap({ T(words: $0.words, isSigned: isSigned) }), integer, file: file, line: line) + //=------------------------------------------= + if let integer { + NBKAssertFromWordsByTruncating(words, words.count, integer) + } +} + +private func NBKAssertFromWordsByTruncating( +_ words: [UInt], _ count: Int, _ integer: T, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + if count == words.count { + let initialized = T.uninitialized(count: count, init:{ let _ = $0.initialize(from: words) }) + XCTAssertEqual(initialized, integer, file: file, line: line) + } + + brr: do { + let capacity: Int = count + let initialized = T.uninitialized(capacity: capacity, init:{ $1 = $0.initialize(from: words.prefix(count)).index }) + XCTAssertEqual(initialized, integer, file: file, line: line) + } + + brr: do { + let capacity: Int = count + 1 + let initialized = T.uninitialized(capacity: capacity, init:{ $1 = $0.initialize(from: words.prefix(count)).index }) + XCTAssertEqual(initialized, integer, file: file, line: line) + } } private func NBKAssertToWords( _ integer: T, _ words: [UInt], file: StaticString = #file, line: UInt = #line) { - - NBKAssertElementsEqual(integer.words, words, file: file, line: line) - NBKAssertFromWords(/*--------*/words, integer, file: file, line: line) + //=------------------------------------------= + var integer = integer + //=------------------------------------------= + NBKAssertFromWords(words, integer, file: file, line: line) + //=------------------------------------------= + NBKAssertElementsEqual(integer.words, words, file: file, line: line) + integer.withUnsafeBufferPointer({ NBKAssertElementsEqual($0, words, file: file, line: line) }) + integer.withUnsafeMutableBufferPointer({ NBKAssertElementsEqual($0, words, file: file, line: line) }) } //=----------------------------------------------------------------------------= From 58873b03fc628d8f94428e4152744c0183acd95b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sun, 22 Oct 2023 17:49:21 +0200 Subject: [PATCH 101/133] [NBKFlexibleWidthKit] Cleanup. Comments. --- .../NBKFlexibleWidthKit/IntXLOrUIntXL.swift | 54 ++++++++----------- .../NBKFlexibleWidth+Addition+Digit.swift | 12 ++--- .../NBKFlexibleWidth+Addition.swift | 12 ++--- .../NBKFlexibleWidth+Division.swift | 2 +- ...BKFlexibleWidth+Multiplication+Digit.swift | 9 ++-- .../NBKFlexibleWidth+Shifts.swift | 22 +++----- .../NBKFlexibleWidth+Update.swift | 4 -- .../NBKFlexibleWidth+Words+Pointers.swift | 12 ++--- ...NBKFlexibleWidth+Words+Uninitialized.swift | 4 +- .../NBKFlexibleWidth+Words.swift | 2 +- .../NBKFlexibleWidth.swift | 26 +++++++++ 11 files changed, 82 insertions(+), 77 deletions(-) diff --git a/Sources/NBKFlexibleWidthKit/IntXLOrUIntXL.swift b/Sources/NBKFlexibleWidthKit/IntXLOrUIntXL.swift index a77780b7..cbb156fa 100644 --- a/Sources/NBKFlexibleWidthKit/IntXLOrUIntXL.swift +++ b/Sources/NBKFlexibleWidthKit/IntXLOrUIntXL.swift @@ -29,8 +29,20 @@ public protocol IntXLOrUIntXL: NBKBinaryInteger, ExpressibleByStringLiteral wher // MARK: Details x Comparisons //=------------------------------------------------------------------------= + /// A three-way comparison between `self` and `other` at `index`. + /// + /// - Parameters: + /// - other: Another integer instance. + /// - index: The non-negative offset of `other` measured in `Digit` positions. + /// @inlinable func compared(to other: Self, at index: Int) -> Int - + + /// A three-way comparison between `self` and `other` at `index`. + /// + /// - Parameters: + /// - other: Another integer instance. + /// - index: The non-negative offset of `other` measured in `Digit` positions. + /// @_disfavoredOverload @inlinable func compared(to other: Digit, at index: Int) -> Int //=------------------------------------------------------------------------= @@ -97,8 +109,10 @@ public protocol IntXLOrUIntXL: NBKBinaryInteger, ExpressibleByStringLiteral wher // MARK: Details x Update //=------------------------------------------------------------------------= - @inlinable mutating func updateZeroValue() - + /// Updates this instance in-place so it equals `value`. + /// + /// - Note: This operation is much more efficent than allocating new storage. + /// @inlinable mutating func update(_ value: Digit) //=------------------------------------------------------------------------= @@ -167,9 +181,9 @@ public protocol IntXLOrUIntXL: NBKBinaryInteger, ExpressibleByStringLiteral wher /// /// - Note: This is a non-throwing convenience for `uninitialized(capacity:init:)`. /// - /// ### No initialized prefix semantics + /// ### Semantics when there is no initialized prefix /// - /// It returns zero when the initialized prefix count is zero because the following + /// It returns zero when there is no initialized prefix because the following /// expressions must return the same values: /// /// ```swift @@ -192,9 +206,9 @@ public protocol IntXLOrUIntXL: NBKBinaryInteger, ExpressibleByStringLiteral wher /// requested amount, the buffer passed to `init` will cover exactly the requested /// number of words. /// - /// ### No initialized prefix semantics + /// ### Semantics when there is no initialized prefix /// - /// It returns zero when the initialized prefix count is zero because the following + /// It returns zero when there is no initialized prefix because the following /// expressions must return the same values: /// /// ```swift @@ -206,29 +220,3 @@ public protocol IntXLOrUIntXL: NBKBinaryInteger, ExpressibleByStringLiteral wher @inlinable static func uninitialized( capacity: Int, init: (inout UnsafeMutableBufferPointer, inout Int) throws -> Void) rethrows -> Self } - -//=----------------------------------------------------------------------------= -// MARK: + Details -//=----------------------------------------------------------------------------= - -extension IntXLOrUIntXL { - - //=------------------------------------------------------------------------= - // MARK: Utilities - //=------------------------------------------------------------------------= - - /// A `description` of this type. - /// - /// ``` - /// ┌─────────────────────────── → ────────────┐ - /// │ type │ description │ - /// ├─────────────────────────── → ────────────┤ - /// │ NBKFlexibleWidth │ "IntXL" │ - /// │ NBKFlexibleWidth.Magnitude │ "UIntXL" │ - /// └─────────────────────────── → ────────────┘ - /// ``` - /// - @inlinable public static var description: String { - Self.isSigned ? "IntXL" : "UIntXL" - } -} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift index 52f52863..dbfde5be 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift @@ -37,20 +37,20 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= self.storage.resize(minCount: index + 1) - defer { - Swift.assert(self.storage.isNormal) - } - - let overflow: Bool = self.storage.withUnsafeMutableBufferPointer(in: index...) { + let overflow = self.storage.withUnsafeMutableBufferPointer(in: index...) { NBK.SUISS.increment(&$0, by: other).overflow } if overflow { self.storage.append(1 as UInt) } + + Swift.assert(self.storage.isNormal) } @_disfavoredOverload @inlinable public func adding(_ other: UInt, at index: Int) -> Self { - var result = self; result.add(other, at: index); return result + var result = self + result.add(other, at: index) + return result as Self } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift index 092536f6..bee8784e 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift @@ -37,11 +37,7 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= self.storage.resize(minCount: index + other.storage.elements.count) - defer { - Swift.assert(self.storage.isNormal) - } - - let overflow: Bool = self.storage.withUnsafeMutableBufferPointer(in: index...) { slice in + let overflow = self.storage.withUnsafeMutableBufferPointer(in: index...) { slice in other.storage.withUnsafeBufferPointer { other in NBK.SUISS.increment(&slice, by: other).overflow } @@ -50,9 +46,13 @@ extension NBKFlexibleWidth.Magnitude { if overflow { self.storage.append(1 as UInt) } + + Swift.assert(self.storage.isNormal) } @inlinable public func adding(_ other: Self, at index: Int) -> Self { - var result = self; result.add(other, at: index); return result + var result = self + result.add(other, at: index) + return result as Self } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift index 185d26f2..c37c9f41 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift @@ -85,7 +85,7 @@ extension NBKFlexibleWidth.Magnitude { let comparison = other.compared(to: self) if comparison.isLessThanZero { } else if comparison.isZero { - self.updateZeroValue() + self.update(0 as UInt) return PVO(Self.one, false) } else { return PVO(Self.zero, false) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift index c50ee853..6a3fde8f 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift @@ -32,9 +32,6 @@ extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= @_disfavoredOverload @inlinable public mutating func multiply(by multiplicand: UInt, add addend: UInt) { - defer { - Swift.assert(self.storage.isNormal) - } //=--------------------------------------= if multiplicand.isZero { return self.update(addend) @@ -49,9 +46,13 @@ extension NBKFlexibleWidth.Magnitude { if !carry.isZero { self.storage.append(carry) } + + Swift.assert(self.storage.isNormal) } @_disfavoredOverload @inlinable public func multiplied(by multiplicand: UInt, adding addend: UInt) -> Self { - var result = self; result.multiply(by: multiplicand, add: addend); return result + var result = self + result.multiply(by: multiplicand, add: addend) + return result as Self } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift index b5896abe..dce60ffe 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift @@ -98,9 +98,6 @@ extension NBKFlexibleWidth.Magnitude { /// - minor: `1 <= minor < UInt.bitWidth` /// @inlinable mutating func bitshiftLeft(major: Int, minorAtLeastOne minor: Int) { - defer { - Swift.assert(self.storage.isNormal) - } //=--------------------------------------= if self.isZero { return } //=--------------------------------------= @@ -110,6 +107,8 @@ extension NBKFlexibleWidth.Magnitude { self.storage.withUnsafeMutableBufferPointer { NBK.SUI.bitshiftLeft(&$0, major: major, minorAtLeastOne: minor) } + + Swift.assert(self.storage.isNormal) } /// Performs a left shift. @@ -118,9 +117,6 @@ extension NBKFlexibleWidth.Magnitude { /// - major: `1 <= major` /// @inlinable mutating func bitshiftLeft(majorAtLeastOne major: Int) { - defer { - Swift.assert(self.storage.isNormal) - } //=--------------------------------------= if self.isZero { return } //=--------------------------------------= @@ -129,6 +125,8 @@ extension NBKFlexibleWidth.Magnitude { self.storage.withUnsafeMutableBufferPointer { NBK.SUI.bitshiftLeft(&$0, majorAtLeastOne: major) } + + Swift.assert(self.storage.isNormal) } } @@ -218,15 +216,12 @@ extension NBKFlexibleWidth.Magnitude { /// - minor: `0 <= minor < UInt.bitWidth` /// @inlinable mutating func bitshiftRight(major: Int, minorAtLeastOne minor: Int) { - defer { - Swift.assert(self.storage.isNormal) - } //=--------------------------------------= let rollover = Int(bit: 0 <= minor + self.leadingZeroBitCount - UInt.bitWidth) let maxCount = self.storage.elements.count - major - rollover //=--------------------------------------= if maxCount <= 0 { - return self.updateZeroValue() + return self.update(0 as UInt) } //=--------------------------------------= self.storage.withUnsafeMutableBufferPointer { @@ -234,6 +229,7 @@ extension NBKFlexibleWidth.Magnitude { } self.storage.resize(maxCount: maxCount) + Swift.assert(self.storage.isNormal) } /// Performs an unsigned right shift. @@ -242,12 +238,9 @@ extension NBKFlexibleWidth.Magnitude { /// - major: `1 <= major` /// @inlinable mutating func bitshiftRight(majorAtLeastOne major: Int) { - defer { - Swift.assert(self.storage.isNormal) - } //=--------------------------------------= if self.storage.elements.count <= major { - return self.updateZeroValue() + return self.update(0 as UInt) } //=--------------------------------------= self.storage.withUnsafeMutableBufferPointer { @@ -255,5 +248,6 @@ extension NBKFlexibleWidth.Magnitude { } self.storage.resize(maxCount: self.storage.elements.count - major) + Swift.assert(self.storage.isNormal) } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Update.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Update.swift index 37a16ae4..94cff348 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Update.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Update.swift @@ -19,10 +19,6 @@ extension NBKFlexibleWidth.Magnitude { // MARK: Transformations //=------------------------------------------------------------------------= - @inlinable public mutating func updateZeroValue() { - self.update(0 as UInt) - } - @inlinable public mutating func update(_ value: Digit) { self.storage.normalize(update: value) } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words+Pointers.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words+Pointers.swift index fb44cf06..d91d2ea2 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words+Pointers.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words+Pointers.swift @@ -44,13 +44,13 @@ extension NBKFlexibleWidth.Magnitude.Storage { //=------------------------------------------------------------------------= /// Grants unsafe access to the collection's contiguous storage. - @inlinable func withUnsafeBufferPointer( + @inlinable public func withUnsafeBufferPointer( _ body: (UnsafeBufferPointer) throws -> T) rethrows -> T { try self.elements.withUnsafeBufferPointer(body) } /// Grants unsafe access to the collection's contiguous mutable storage. - @inlinable mutating func withUnsafeMutableBufferPointer( + @inlinable public mutating func withUnsafeMutableBufferPointer( _ body: (inout UnsafeMutableBufferPointer) throws -> T) rethrows -> T { try self.elements.withUnsafeMutableBufferPointer(body) } @@ -65,8 +65,8 @@ extension NBKFlexibleWidth.Magnitude.Storage { /// /// This method is required for performance reasons (see slice arithmetic). /// - @inlinable func withUnsafeBufferPointer(in range: some RangeExpression, - perform body: (inout UnsafeBufferPointer) throws -> T) rethrows -> T { + @inlinable public func withUnsafeBufferPointer( + in range: some RangeExpression, perform body: (inout UnsafeBufferPointer) throws -> T) rethrows -> T { try self.withUnsafeBufferPointer { let range = range.relative(to: $0) var slice = UnsafeBufferPointer(start: $0.baseAddress! + range.lowerBound, count: range.count) @@ -80,8 +80,8 @@ extension NBKFlexibleWidth.Magnitude.Storage { /// /// This method is required for performance reasons (see slice arithmetic). /// - @inlinable mutating func withUnsafeMutableBufferPointer(in range: some RangeExpression, - perform body: (inout UnsafeMutableBufferPointer) throws -> T) rethrows -> T { + @inlinable public mutating func withUnsafeMutableBufferPointer( + in range: some RangeExpression, perform body: (inout UnsafeMutableBufferPointer) throws -> T) rethrows -> T { try self.withUnsafeMutableBufferPointer { let range = range.relative(to: $0) var slice = UnsafeMutableBufferPointer(start: $0.baseAddress! + range.lowerBound, count: range.count) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words+Uninitialized.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words+Uninitialized.swift index af25eae1..75af6ca6 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words+Uninitialized.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words+Uninitialized.swift @@ -62,9 +62,9 @@ extension NBKFlexibleWidth.Magnitude.Storage { /// requested amount, the buffer passed to `init` will cover exactly the requested /// number of words. /// - /// ### No initialized prefix semantics + /// ### Semantics when there is no initialized prefix /// - /// It returns zero when the initialized prefix count is zero because the following + /// It returns zero when there is no initialized prefix because the following /// expressions must return the same values: /// /// ```swift diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift index 89f18aee..e894012b 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift @@ -40,6 +40,6 @@ extension NBKFlexibleWidth.Magnitude { } @inlinable public var words: ContiguousArray { - _read { yield self.storage.elements } + self.storage.elements } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift index 96246867..7712b970 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift @@ -111,6 +111,32 @@ import NBKCoreKit } } +//=----------------------------------------------------------------------------= +// MARK: + Details +//=----------------------------------------------------------------------------= + +extension IntXLOrUIntXL { + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + /// A `description` of this type. + /// + /// ``` + /// ┌─────────────────────────── → ────────────┐ + /// │ type │ description │ + /// ├─────────────────────────── → ────────────┤ + /// │ NBKFlexibleWidth │ "IntXL" │ + /// │ NBKFlexibleWidth.Magnitude │ "UIntXL" │ + /// └─────────────────────────── → ────────────┘ + /// ``` + /// + @inlinable public static var description: String { + Self.isSigned ? "IntXL" : "UIntXL" + } +} + //*============================================================================* // MARK: * NBK x Flexible Width x Aliases //*============================================================================* From 417832a96267938c758c621853f1d95022acee1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Mon, 23 Oct 2023 15:02:19 +0200 Subject: [PATCH 102/133] [NBKFlexibleWidthKit] Cleanup. --- .../NBKFlexibleWidth+Addition+Digit.swift | 2 +- .../NBKFlexibleWidth+Addition.swift | 2 +- .../NBKFlexibleWidth+Division.swift | 6 ++-- ...BKFlexibleWidth+Multiplication+Digit.swift | 12 +++---- .../NBKFlexibleWidth+Multiplication.swift | 8 ++--- .../NBKFlexibleWidth+Subtraction+Digit.swift | 10 +++++- .../NBKFlexibleWidth+Subtraction.swift | 10 +++++- .../NBKFlexibleWidth+Text.swift | 34 ------------------- .../NBKFlexibleWidth+Words+Pointers.swift | 12 +++---- .../NBKFlexibleWidth+Multiplication.swift | 4 +-- .../NBKFlexibleWidth+Words.swift | 2 +- 11 files changed, 42 insertions(+), 60 deletions(-) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift index dbfde5be..e9f4ee16 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift @@ -28,7 +28,7 @@ extension NBKFlexibleWidth.Magnitude { } //=------------------------------------------------------------------------= - // MARK: Transformations + // MARK: Transformations x Index //=------------------------------------------------------------------------= @_disfavoredOverload @inlinable public mutating func add(_ other: UInt, at index: Int) { diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift index bee8784e..896f6620 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift @@ -28,7 +28,7 @@ extension NBKFlexibleWidth.Magnitude { } //=------------------------------------------------------------------------= - // MARK: Transformations + // MARK: Transformations x Index //=------------------------------------------------------------------------= @inlinable public mutating func add(_ other: Self, at index: Int) { diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift index c37c9f41..8827e199 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift @@ -16,7 +16,7 @@ import NBKCoreKit extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= - // MARK: Transformations + // MARK: Transformations x Overflow //=------------------------------------------------------------------------= @inlinable public mutating func divideReportingOverflow(by other: Self) -> Bool { @@ -47,13 +47,13 @@ extension NBKFlexibleWidth.Magnitude { } //=----------------------------------------------------------------------------= -// MARK: + Long Division +// MARK: + Long Division Algorithms //=----------------------------------------------------------------------------= extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= - // MARK: Transformations x Private + // MARK: Transformations x Overflow x Private //=------------------------------------------------------------------------= /// Performs long division after some fast-path checks. diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift index 6a3fde8f..8c937f0d 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.swift @@ -28,19 +28,19 @@ extension NBKFlexibleWidth.Magnitude { } //=------------------------------------------------------------------------= - // MARK: Transformations + // MARK: Transformations x Addition //=------------------------------------------------------------------------= - @_disfavoredOverload @inlinable public mutating func multiply(by multiplicand: UInt, add addend: UInt) { + @_disfavoredOverload @inlinable public mutating func multiply(by multiplier: UInt, add addend: UInt) { //=--------------------------------------= - if multiplicand.isZero { + if multiplier.isZero { return self.update(addend) } //=--------------------------------------= self.storage.reserveCapacity(self.storage.elements.count + 1) let carry = self.storage.withUnsafeMutableBufferPointer { - NBK.SUISS.multiply(&$0, by: multiplicand, add: addend) + NBK.SUISS.multiply(&$0, by: multiplier, add: addend) } if !carry.isZero { @@ -50,9 +50,9 @@ extension NBKFlexibleWidth.Magnitude { Swift.assert(self.storage.isNormal) } - @_disfavoredOverload @inlinable public func multiplied(by multiplicand: UInt, adding addend: UInt) -> Self { + @_disfavoredOverload @inlinable public func multiplied(by multiplier: UInt, adding addend: UInt) -> Self { var result = self - result.multiply(by: multiplicand, add: addend) + result.multiply(by: multiplier, add: addend) return result as Self } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift index ccbef8f2..a5181204 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift @@ -24,22 +24,22 @@ extension NBKFlexibleWidth.Magnitude { } @inlinable public static func *(lhs: Self, rhs: Self) -> Self { - lhs.multipliedFullWidthUsingLongAlgorithm(by: rhs, adding: 0 as UInt) + lhs.multipliedUsingLongAlgorithm(by: rhs, adding: 0 as UInt) } } //=----------------------------------------------------------------------------= -// MARK: + Long Multiplication +// MARK: + Long Multiplication Algorithms //=----------------------------------------------------------------------------= extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= - // MARK: Transformations + // MARK: Transformations x Private //=------------------------------------------------------------------------= /// Performs long multiplication. - @inlinable func multipliedFullWidthUsingLongAlgorithm(by multiplier: Self, adding addend: UInt) -> Self { + @inlinable func multipliedUsingLongAlgorithm(by multiplier: Self, adding addend: UInt) -> Self { Self.uninitialized(count: self.count + multiplier.count) { pro in self.storage.withUnsafeBufferPointer { lhs in multiplier.storage.withUnsafeBufferPointer { rhs in diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift index 65980b44..01b11d11 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift @@ -27,6 +27,10 @@ extension NBKFlexibleWidth.Magnitude { lhs.subtracting(rhs, at: 0 as Int) } + //=------------------------------------------------------------------------= + // MARK: Transformations x Overflow + //=------------------------------------------------------------------------= + @_disfavoredOverload @inlinable public mutating func subtractReportingOverflow(_ other: UInt) -> Bool { self.subtractReportingOverflow(other, at: 0 as Int) } @@ -36,7 +40,7 @@ extension NBKFlexibleWidth.Magnitude { } //=------------------------------------------------------------------------= - // MARK: Transformations + // MARK: Transformations x Index //=------------------------------------------------------------------------= @_disfavoredOverload @inlinable public mutating func subtract(_ other: UInt, at index: Int) { @@ -50,6 +54,10 @@ extension NBKFlexibleWidth.Magnitude { return pvo.partialValue as Self } + //=------------------------------------------------------------------------= + // MARK: Transformations x Index x Overflow + //=------------------------------------------------------------------------= + @_disfavoredOverload @inlinable public mutating func subtractReportingOverflow(_ other: UInt, at index: Int) -> Bool { //=--------------------------------------= if other.isZero { return false } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift index 9eae1cdc..c5e3bae1 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift @@ -27,6 +27,10 @@ extension NBKFlexibleWidth.Magnitude { lhs.subtracting(rhs, at: 0 as Int) } + //=------------------------------------------------------------------------= + // MARK: Transformations x Overflow + //=------------------------------------------------------------------------= + @inlinable public mutating func subtractReportingOverflow(_ other: Self) -> Bool { self.subtractReportingOverflow(other, at: 0 as Int) } @@ -36,7 +40,7 @@ extension NBKFlexibleWidth.Magnitude { } //=------------------------------------------------------------------------= - // MARK: Transformations + // MARK: Transformations x Index //=------------------------------------------------------------------------= @inlinable public mutating func subtract(_ other: Self, at index: Int) { @@ -50,6 +54,10 @@ extension NBKFlexibleWidth.Magnitude { return pvo.partialValue as Self } + //=------------------------------------------------------------------------= + // MARK: Transformations x Index x Overflow + //=------------------------------------------------------------------------= + @inlinable public mutating func subtractReportingOverflow(_ other: Self, at index: Int) -> Bool { //=--------------------------------------= if other.isZero { return false } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text.swift index ac5f37db..538b376a 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text.swift @@ -19,25 +19,6 @@ extension NBKFlexibleWidth.Magnitude { // MARK: Details x Decoding //=------------------------------------------------------------------------= - /// Creates a new instance from the given `description` and `radix`. - /// - /// The `description` may contain a plus or minus sign (+ or -), followed by one - /// or more numeric digits (0-9) or letters (a-z or A-Z). If the description uses - /// an invalid format, or its value cannot be represented, the result is nil. - /// - /// ``` - /// ┌─────────────┬────── → ─────────────┐ - /// │ description │ radix │ self │ - /// ├─────────────┼────── → ─────────────┤ - /// │ "123" │ 16 │ Int256( 291) │ - /// │ "+123" │ 16 │ Int256( 291) │ - /// │ "-123" │ 16 │ Int256(-291) │ - /// │ "~123" │ 16 │ nil │ - /// └─────────────┴────── → ─────────────┘ - /// ``` - /// - /// - Note: The decoding strategy is case insensitive. - /// @inlinable public init?(_ description: some StringProtocol, radix: Int) { let decoder = NBK.IntegerDescription.Decoder(radix: radix) guard let components: SM = decoder.decode(description) else { return nil } @@ -48,21 +29,6 @@ extension NBKFlexibleWidth.Magnitude { // MARK: Details x Encoding //=------------------------------------------------------------------------= - /// A `description` of this value in the given ASCII format. - /// - /// The description may contain a minus sign (-), followed by one - /// or more numeric digits (0-9) or letters (a-z or A-Z). These represent - /// the integer's sign and magnitude. Zero is always non-negative. - /// - /// ``` - /// ┌──────────────┬───────┬─────────── → ────────────┐ - /// │ self │ radix │ uppercase │ description │ - /// ├──────────────┼───────┼─────────── → ────────────┤ - /// │ Int256( 123) │ 12 │ true │ "A3" │ - /// │ Int256(-123) │ 16 │ false │ "-7b" │ - /// └──────────────┴───────┴─────────── → ────────────┘ - /// ``` - /// @inlinable public func description(radix: Int, uppercase: Bool) -> String { NBK.IntegerDescription.Encoder(radix: radix, uppercase: uppercase).encode(self) } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words+Pointers.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words+Pointers.swift index d91d2ea2..b0d5833d 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words+Pointers.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words+Pointers.swift @@ -19,13 +19,13 @@ extension NBKFlexibleWidth.Magnitude { // MARK: Details x Contiguous UInt Collection //=------------------------------------------------------------------------= - /// Grants unsafe access to the collection's contiguous storage. + /// Grants unsafe access to the words of this instance. @inlinable public func withUnsafeBufferPointer( _ body: (UnsafeBufferPointer) throws -> T) rethrows -> T { try self.storage.withUnsafeBufferPointer(body) } - /// Grants unsafe access to the collection's contiguous mutable storage. + /// Grants unsafe access to the mutable words of this instance. @inlinable public mutating func withUnsafeMutableBufferPointer( _ body: (inout UnsafeMutableBufferPointer) throws -> T) rethrows -> T { defer{ self.storage.normalize() } @@ -43,13 +43,13 @@ extension NBKFlexibleWidth.Magnitude.Storage { // MARK: Details x Contiguous UInt Collection //=------------------------------------------------------------------------= - /// Grants unsafe access to the collection's contiguous storage. + /// Grants unsafe access to the words of this instance. @inlinable public func withUnsafeBufferPointer( _ body: (UnsafeBufferPointer) throws -> T) rethrows -> T { try self.elements.withUnsafeBufferPointer(body) } - /// Grants unsafe access to the collection's contiguous mutable storage. + /// Grants unsafe access to the mutable words of this instance. @inlinable public mutating func withUnsafeMutableBufferPointer( _ body: (inout UnsafeMutableBufferPointer) throws -> T) rethrows -> T { try self.elements.withUnsafeMutableBufferPointer(body) @@ -59,7 +59,7 @@ extension NBKFlexibleWidth.Magnitude.Storage { // MARK: Details x Contiguous UInt Collection x Sub Sequence //=------------------------------------------------------------------------= - /// Grants unsafe access to the collection's contiguous storage in the given `range`. + /// Grants unsafe access to the words of this instance in the given `range`. /// /// ### Development /// @@ -74,7 +74,7 @@ extension NBKFlexibleWidth.Magnitude.Storage { } } - /// Grants unsafe access to the collection's contiguous mutable storage in the given `range`. + /// Grants unsafe access to the mutable words of this instance in the given `range`. /// /// ### Development /// diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Multiplication.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Multiplication.swift index 36dcf6d6..f944ce24 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Multiplication.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Multiplication.swift @@ -99,7 +99,7 @@ file: StaticString = #file, line: UInt = #line) { let pro = pro as? UIntXL else { return } //=------------------------------------------= - XCTAssertEqual(lhs.multipliedFullWidthUsingLongAlgorithm(by: rhs, adding: 0), pro, file: file, line: line) + XCTAssertEqual(lhs.multipliedUsingLongAlgorithm(by: rhs, adding: 0), pro, file: file, line: line) } private func NBKAssertMultiplicationByDigit( @@ -123,7 +123,7 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual(lhs.multiplied(by: rhs, adding: add), pro, file: file, line: line) XCTAssertEqual({ var lhs = lhs; lhs.multiply(by: rhs, add: add); return lhs }(), pro, file: file, line: line) //=------------------------------------------= - XCTAssertEqual(lhs.multipliedFullWidthUsingLongAlgorithm(by: UIntXL(digit: rhs), adding: add), pro, file: file, line: line) + XCTAssertEqual(lhs.multipliedUsingLongAlgorithm(by: UIntXL(digit: rhs), adding: add), pro, file: file, line: line) } #endif diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Words.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Words.swift index 6cf0516a..fae305bf 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Words.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Words.swift @@ -205,7 +205,7 @@ file: StaticString = #file, line: UInt = #line) { //=------------------------------------------= NBKAssertElementsEqual(integer.words, words, file: file, line: line) integer.withUnsafeBufferPointer({ NBKAssertElementsEqual($0, words, file: file, line: line) }) - integer.withUnsafeMutableBufferPointer({ NBKAssertElementsEqual($0, words, file: file, line: line) }) + integer.withUnsafeMutableBufferPointer({ NBKAssertElementsEqual($0, words, file: file, line: line) }) } //=----------------------------------------------------------------------------= From c878c3577e0ff9e4c9ffa15f4978f2969fadff19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Mon, 23 Oct 2023 17:25:58 +0200 Subject: [PATCH 103/133] [NBKFlexibleWidthKit] No NBKSignedKit (#33). --- .swiftpm/NBKSignedKit-Benchmarks.xctestplan | 24 -- .swiftpm/NBKSignedKit.xctestplan | 32 -- .swiftpm/Numberick-Benchmarks.xctestplan | 7 - .swiftpm/Numberick.xctestplan | 12 - .../NBKSignedKit-Benchmarks.xcscheme | 71 ----- .../xcschemes/NBKSignedKit.xcscheme | 71 ----- .../xcschemes/Numberick-Benchmarks.xcscheme | 3 - .../xcshareddata/xcschemes/Numberick.xcscheme | 17 -- Package.swift | 22 +- README.md | 10 - .../NBKFlexibleWidthKit/IntXLOrUIntXL.swift | 4 +- .../NBKSigned+Addition+Digit.swift | 34 --- Sources/NBKSignedKit/NBKSigned+Addition.swift | 34 --- .../NBKSignedKit/NBKSigned+Comparisons.swift | 75 ----- .../NBKSigned+Division+Digit.swift | 42 --- Sources/NBKSignedKit/NBKSigned+Division.swift | 42 --- Sources/NBKSignedKit/NBKSigned+Literals.swift | 79 ----- .../NBKSigned+Multiplication+Digit.swift | 29 -- .../NBKSigned+Multiplication.swift | 29 -- Sources/NBKSignedKit/NBKSigned+Negation.swift | 37 --- Sources/NBKSignedKit/NBKSigned+Numbers.swift | 124 -------- .../NBKSigned+Subtraction+Digit.swift | 34 --- .../NBKSignedKit/NBKSigned+Subtraction.swift | 34 --- Sources/NBKSignedKit/NBKSigned+Text.swift | 145 --------- Sources/NBKSignedKit/NBKSigned+Words.swift | 109 ------- Sources/NBKSignedKit/NBKSigned.swift | 160 ---------- Sources/Numberick/Numberick.swift | 8 - .../NBKFlexibleWidth.swift | 57 ---- .../NBKSigned+Addition.swift | 84 ------ .../NBKSigned+Comparisons.swift | 129 -------- .../NBKSigned+Complements.swift | 48 --- .../NBKSigned+Division.swift | 77 ----- .../NBKSigned+Multiplication.swift | 62 ---- .../NBKSigned+Subtraction.swift | 84 ------ .../NBKSigned+Text.swift | 86 ------ Tests/NBKSignedKitBenchmarks/NBKSigned.swift | 46 --- .../NBKSignedKitTests/NBKFlexibleWidth.swift | 57 ---- .../NBKSigned+Addition.swift | 126 -------- .../NBKSigned+Comparisons.swift | 191 ------------ .../NBKSigned+Complements.swift | 43 --- .../NBKSigned+Division.swift | 169 ----------- .../NBKSigned+Literals.swift | 145 --------- .../NBKSigned+Multiplication.swift | 98 ------ .../NBKSigned+Negation.swift | 89 ------ .../NBKSignedKitTests/NBKSigned+Numbers.swift | 198 ------------ .../NBKSigned+Subtraction.swift | 155 ---------- Tests/NBKSignedKitTests/NBKSigned+Text.swift | 281 ------------------ Tests/NBKSignedKitTests/NBKSigned+Words.swift | 149 ---------- Tests/NBKSignedKitTests/NBKSigned.swift | 122 -------- 49 files changed, 3 insertions(+), 3781 deletions(-) delete mode 100644 .swiftpm/NBKSignedKit-Benchmarks.xctestplan delete mode 100644 .swiftpm/NBKSignedKit.xctestplan delete mode 100644 .swiftpm/xcode/xcshareddata/xcschemes/NBKSignedKit-Benchmarks.xcscheme delete mode 100644 .swiftpm/xcode/xcshareddata/xcschemes/NBKSignedKit.xcscheme delete mode 100644 Sources/NBKSignedKit/NBKSigned+Addition+Digit.swift delete mode 100644 Sources/NBKSignedKit/NBKSigned+Addition.swift delete mode 100644 Sources/NBKSignedKit/NBKSigned+Comparisons.swift delete mode 100644 Sources/NBKSignedKit/NBKSigned+Division+Digit.swift delete mode 100644 Sources/NBKSignedKit/NBKSigned+Division.swift delete mode 100644 Sources/NBKSignedKit/NBKSigned+Literals.swift delete mode 100644 Sources/NBKSignedKit/NBKSigned+Multiplication+Digit.swift delete mode 100644 Sources/NBKSignedKit/NBKSigned+Multiplication.swift delete mode 100644 Sources/NBKSignedKit/NBKSigned+Negation.swift delete mode 100644 Sources/NBKSignedKit/NBKSigned+Numbers.swift delete mode 100644 Sources/NBKSignedKit/NBKSigned+Subtraction+Digit.swift delete mode 100644 Sources/NBKSignedKit/NBKSigned+Subtraction.swift delete mode 100644 Sources/NBKSignedKit/NBKSigned+Text.swift delete mode 100644 Sources/NBKSignedKit/NBKSigned+Words.swift delete mode 100644 Sources/NBKSignedKit/NBKSigned.swift delete mode 100644 Tests/NBKSignedKitBenchmarks/NBKFlexibleWidth.swift delete mode 100644 Tests/NBKSignedKitBenchmarks/NBKSigned+Addition.swift delete mode 100644 Tests/NBKSignedKitBenchmarks/NBKSigned+Comparisons.swift delete mode 100644 Tests/NBKSignedKitBenchmarks/NBKSigned+Complements.swift delete mode 100644 Tests/NBKSignedKitBenchmarks/NBKSigned+Division.swift delete mode 100644 Tests/NBKSignedKitBenchmarks/NBKSigned+Multiplication.swift delete mode 100644 Tests/NBKSignedKitBenchmarks/NBKSigned+Subtraction.swift delete mode 100644 Tests/NBKSignedKitBenchmarks/NBKSigned+Text.swift delete mode 100644 Tests/NBKSignedKitBenchmarks/NBKSigned.swift delete mode 100644 Tests/NBKSignedKitTests/NBKFlexibleWidth.swift delete mode 100644 Tests/NBKSignedKitTests/NBKSigned+Addition.swift delete mode 100644 Tests/NBKSignedKitTests/NBKSigned+Comparisons.swift delete mode 100644 Tests/NBKSignedKitTests/NBKSigned+Complements.swift delete mode 100644 Tests/NBKSignedKitTests/NBKSigned+Division.swift delete mode 100644 Tests/NBKSignedKitTests/NBKSigned+Literals.swift delete mode 100644 Tests/NBKSignedKitTests/NBKSigned+Multiplication.swift delete mode 100644 Tests/NBKSignedKitTests/NBKSigned+Negation.swift delete mode 100644 Tests/NBKSignedKitTests/NBKSigned+Numbers.swift delete mode 100644 Tests/NBKSignedKitTests/NBKSigned+Subtraction.swift delete mode 100644 Tests/NBKSignedKitTests/NBKSigned+Text.swift delete mode 100644 Tests/NBKSignedKitTests/NBKSigned+Words.swift delete mode 100644 Tests/NBKSignedKitTests/NBKSigned.swift diff --git a/.swiftpm/NBKSignedKit-Benchmarks.xctestplan b/.swiftpm/NBKSignedKit-Benchmarks.xctestplan deleted file mode 100644 index af19a60e..00000000 --- a/.swiftpm/NBKSignedKit-Benchmarks.xctestplan +++ /dev/null @@ -1,24 +0,0 @@ -{ - "configurations" : [ - { - "id" : "2BBD9A51-D890-4B97-AED4-B9962867DF57", - "name" : "Main", - "options" : { - - } - } - ], - "defaultOptions" : { - "codeCoverage" : false - }, - "testTargets" : [ - { - "target" : { - "containerPath" : "container:", - "identifier" : "NBKSignedKitBenchmarks", - "name" : "NBKSignedKitBenchmarks" - } - } - ], - "version" : 1 -} diff --git a/.swiftpm/NBKSignedKit.xctestplan b/.swiftpm/NBKSignedKit.xctestplan deleted file mode 100644 index 25e71b3a..00000000 --- a/.swiftpm/NBKSignedKit.xctestplan +++ /dev/null @@ -1,32 +0,0 @@ -{ - "configurations" : [ - { - "id" : "6FC9897F-2BF3-4836-8372-787CE5195F87", - "name" : "Main", - "options" : { - - } - } - ], - "defaultOptions" : { - "codeCoverage" : { - "targets" : [ - { - "containerPath" : "container:", - "identifier" : "NBKSignedKit", - "name" : "NBKSignedKit" - } - ] - } - }, - "testTargets" : [ - { - "target" : { - "containerPath" : "container:", - "identifier" : "NBKSignedKitTests", - "name" : "NBKSignedKitTests" - } - } - ], - "version" : 1 -} diff --git a/.swiftpm/Numberick-Benchmarks.xctestplan b/.swiftpm/Numberick-Benchmarks.xctestplan index ffa5330a..b7a219a1 100644 --- a/.swiftpm/Numberick-Benchmarks.xctestplan +++ b/.swiftpm/Numberick-Benchmarks.xctestplan @@ -42,13 +42,6 @@ "identifier" : "NBKFlexibleWidthKitBenchmarks", "name" : "NBKFlexibleWidthKitBenchmarks" } - }, - { - "target" : { - "containerPath" : "container:", - "identifier" : "NBKSignedKitBenchmarks", - "name" : "NBKSignedKitBenchmarks" - } } ], "version" : 1 diff --git a/.swiftpm/Numberick.xctestplan b/.swiftpm/Numberick.xctestplan index aecc3cda..74306fdc 100644 --- a/.swiftpm/Numberick.xctestplan +++ b/.swiftpm/Numberick.xctestplan @@ -25,11 +25,6 @@ "containerPath" : "container:", "identifier" : "NBKFlexibleWidthKit", "name" : "NBKFlexibleWidthKit" - }, - { - "containerPath" : "container:", - "identifier" : "NBKSignedKit", - "name" : "NBKSignedKit" } ] } @@ -55,13 +50,6 @@ "identifier" : "NBKFlexibleWidthKitTests", "name" : "NBKFlexibleWidthKitTests" } - }, - { - "target" : { - "containerPath" : "container:", - "identifier" : "NBKSignedKitTests", - "name" : "NBKSignedKitTests" - } } ], "version" : 1 diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/NBKSignedKit-Benchmarks.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/NBKSignedKit-Benchmarks.xcscheme deleted file mode 100644 index edd967a0..00000000 --- a/.swiftpm/xcode/xcshareddata/xcschemes/NBKSignedKit-Benchmarks.xcscheme +++ /dev/null @@ -1,71 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/NBKSignedKit.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/NBKSignedKit.xcscheme deleted file mode 100644 index 53b88591..00000000 --- a/.swiftpm/xcode/xcshareddata/xcschemes/NBKSignedKit.xcscheme +++ /dev/null @@ -1,71 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/Numberick-Benchmarks.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/Numberick-Benchmarks.xcscheme index c8f30afc..8cf9cef5 100644 --- a/.swiftpm/xcode/xcshareddata/xcschemes/Numberick-Benchmarks.xcscheme +++ b/.swiftpm/xcode/xcshareddata/xcschemes/Numberick-Benchmarks.xcscheme @@ -41,9 +41,6 @@ - - - - - - - - - -## [NBKSignedKit][FLX/D] ([Sources][SIG/S], [Tests][SIG/T], [Benchmarks][SIG/B]) - -👨‍💻🛠️🚧🧱🧱🏗️🧱🧱🚧⏳ - ## Installation @@ -182,17 +175,14 @@ This project is inspired by [**Int128**][Apple/Int128] and [**DoubleWidth**][App [COR/S]: Sources/NBKCoreKit [DBL/S]: Sources/NBKDoubleWidthKit [FLX/S]: Sources/NBKFlexibleWidthKit -[SIG/S]: Sources/NBKSignedKit [COR/T]: Tests/NBKCoreKitTests [DBL/T]: Tests/NBKDoubleWidthKitTests [FLX/T]: Tests/NBKFlexibleWidthKitTests -[SIG/T]: Tests/NBKSignedKitTests [COR/B]: Tests/NBKCoreKitBenchmarks [DBL/B]: Tests/NBKDoubleWidthKitBenchmarks [FLX/B]: Tests/NBKFlexibleWidthKitBenchmarks -[SIG/B]: Tests/NBKSignedKitBenchmarks diff --git a/Sources/NBKFlexibleWidthKit/IntXLOrUIntXL.swift b/Sources/NBKFlexibleWidthKit/IntXLOrUIntXL.swift index 63ac7ff6..4d94cecd 100644 --- a/Sources/NBKFlexibleWidthKit/IntXLOrUIntXL.swift +++ b/Sources/NBKFlexibleWidthKit/IntXLOrUIntXL.swift @@ -142,7 +142,7 @@ public protocol IntXLOrUIntXL: NBKBinaryInteger, ExpressibleByStringLiteral wher /// ``` /// @inlinable func withUnsafeBufferPointer( - _ body: (UnsafeBufferPointer) throws -> T) rethrows -> T + _ body: (UnsafeBufferPointer) throws -> T) rethrows -> T /// Grants unsafe access to the mutable words of this instance. /// @@ -169,7 +169,7 @@ public protocol IntXLOrUIntXL: NBKBinaryInteger, ExpressibleByStringLiteral wher /// - Note: The words of this instance will be normalized after this operation. /// @inlinable mutating func withUnsafeMutableBufferPointer( - _ body: (inout UnsafeMutableBufferPointer) throws -> T) rethrows -> T + _ body: (inout UnsafeMutableBufferPointer) throws -> T) rethrows -> T /// Creates a new instance with unsafe access to its uninitialized words. /// diff --git a/Sources/NBKSignedKit/NBKSigned+Addition+Digit.swift b/Sources/NBKSignedKit/NBKSigned+Addition+Digit.swift deleted file mode 100644 index 63e80b67..00000000 --- a/Sources/NBKSignedKit/NBKSigned+Addition+Digit.swift +++ /dev/null @@ -1,34 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Signed x Addition x Digit -//*============================================================================* - -extension NBKSigned { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @_disfavoredOverload @inlinable public static func +=(lhs: inout Self, rhs: Digit) { - if lhs.sign == rhs.sign { - lhs.magnitude += rhs.magnitude - } else if lhs.magnitude.subtractReportingOverflow(rhs.magnitude) { - lhs.sign.toggle() - lhs.magnitude.formTwosComplement() - } - } - - @_disfavoredOverload @inlinable public static func +(lhs: Self, rhs: Digit) -> Self { - var lhs = lhs; lhs += rhs; return lhs - } -} diff --git a/Sources/NBKSignedKit/NBKSigned+Addition.swift b/Sources/NBKSignedKit/NBKSigned+Addition.swift deleted file mode 100644 index 9b653ecf..00000000 --- a/Sources/NBKSignedKit/NBKSigned+Addition.swift +++ /dev/null @@ -1,34 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Signed x Addition -//*============================================================================* - -extension NBKSigned { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable public static func +=(lhs: inout Self, rhs: Self) { - if lhs.sign == rhs.sign { - lhs.magnitude += rhs.magnitude - } else if lhs.magnitude.subtractReportingOverflow(rhs.magnitude) { - lhs.sign.toggle() - lhs.magnitude.formTwosComplement() - } - } - - @inlinable public static func +(lhs: Self, rhs: Self) -> Self { - var lhs = lhs; lhs += rhs; return lhs - } -} diff --git a/Sources/NBKSignedKit/NBKSigned+Comparisons.swift b/Sources/NBKSignedKit/NBKSigned+Comparisons.swift deleted file mode 100644 index 3726cef0..00000000 --- a/Sources/NBKSignedKit/NBKSigned+Comparisons.swift +++ /dev/null @@ -1,75 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Signed x Comparisons -//*============================================================================* - -extension NBKSigned { - - //=------------------------------------------------------------------------= - // MARK: Accessors - //=------------------------------------------------------------------------= - - /// Returns whether this value is equal to zero. - @inlinable public var isZero: Bool { - self.magnitude.isZero - } - - /// Returns whether this value is less than zero. - @inlinable public var isLessThanZero: Bool { - self.sign != Sign.plus && !self.isZero - } - - /// Returns whether this value is more than zero. - @inlinable public var isMoreThanZero: Bool { - self.sign == Sign.plus && !self.isZero - } - - /// Returns whether this value is a power of two. - @inlinable public var isPowerOf2: Bool { - self.sign == Sign.plus && self.magnitude.isPowerOf2 - } - - /// Returns `1` if this value is positive, `-1` if it is negative, and `0` otherwise. - @inlinable public func signum() -> Int { - self.isZero ? 0 : self.sign == Sign.plus ? 1 : -1 - } - - //=------------------------------------------------------------------------= - // MARK: Utilities - //=------------------------------------------------------------------------= - - @inlinable public func hash(into hasher: inout Hasher) { - hasher.combine(self.magnitude) - hasher.combine(self.normalizedSign) - } - - //=------------------------------------------------------------------------= - // MARK: Utilities - //=------------------------------------------------------------------------= - - @inlinable public static func ==(lhs: Self, rhs: Self) -> Bool { - lhs.compared(to: rhs).isZero - } - - @inlinable public static func <(lhs: Self, rhs: Self) -> Bool { - lhs.compared(to: rhs) == -1 - } - - @inlinable public func compared(to other: Self) -> Int { - NBK.ISM.compare(self.components, to: other.components, using:{ $0.compared(to: $1) }) - } - - @_disfavoredOverload @inlinable public func compared(to other: Digit) -> Int { - NBK.ISM.compare(self.components, to: other.components, using:{ $0.compared(to: $1) }) - } -} diff --git a/Sources/NBKSignedKit/NBKSigned+Division+Digit.swift b/Sources/NBKSignedKit/NBKSigned+Division+Digit.swift deleted file mode 100644 index 9ee5660a..00000000 --- a/Sources/NBKSignedKit/NBKSigned+Division+Digit.swift +++ /dev/null @@ -1,42 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Signed x Division x Digit -//*============================================================================* - -extension NBKSigned { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @_disfavoredOverload @inlinable public static func /=(lhs: inout Self, rhs: Digit) { - lhs.sign ^= rhs.sign; lhs.magnitude /= rhs.magnitude - } - - @_disfavoredOverload @inlinable public static func /(lhs: Self, rhs: Digit) -> Self { - Self(sign: lhs.sign ^ rhs.sign, magnitude: lhs.magnitude / rhs.magnitude) - } - - @_disfavoredOverload @inlinable public static func %=(lhs: inout Self, rhs: Digit) { - lhs.magnitude %= rhs.magnitude - } - - @_disfavoredOverload @inlinable public static func %(lhs: Self, rhs: Digit) -> Digit { - Digit(sign: lhs.sign, magnitude: lhs.magnitude % rhs.magnitude) - } - - @_disfavoredOverload @inlinable public func quotientAndRemainder(dividingBy other: Digit) -> QR { - let x: QR = self.magnitude.quotientAndRemainder(dividingBy: other.magnitude) - return QR(Self(sign: self.sign ^ other.sign, magnitude: x.quotient), Digit(sign: self.sign, magnitude: x.remainder)) - } -} diff --git a/Sources/NBKSignedKit/NBKSigned+Division.swift b/Sources/NBKSignedKit/NBKSigned+Division.swift deleted file mode 100644 index f60f2a01..00000000 --- a/Sources/NBKSignedKit/NBKSigned+Division.swift +++ /dev/null @@ -1,42 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Signed x Division -//*============================================================================* - -extension NBKSigned { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable public static func /=(lhs: inout Self, rhs: Self) { - lhs.sign ^= rhs.sign; lhs.magnitude /= rhs.magnitude - } - - @inlinable public static func /(lhs: Self, rhs: Self) -> Self { - Self(sign: lhs.sign ^ rhs.sign, magnitude: lhs.magnitude / rhs.magnitude) - } - - @inlinable public static func %=(lhs: inout Self, rhs: Self) { - lhs.magnitude %= rhs.magnitude - } - - @inlinable public static func %(lhs: Self, rhs: Self) -> Self { - Self(sign: lhs.sign, magnitude: lhs.magnitude % rhs.magnitude) - } - - @inlinable public func quotientAndRemainder(dividingBy other: Self) -> QR { - let x: QR = self.magnitude.quotientAndRemainder(dividingBy: other.magnitude) - return QR(Self(sign: self.sign ^ other.sign, magnitude: x.quotient), Self(sign: self.sign, magnitude: x.remainder)) - } -} diff --git a/Sources/NBKSignedKit/NBKSigned+Literals.swift b/Sources/NBKSignedKit/NBKSigned+Literals.swift deleted file mode 100644 index 67027dae..00000000 --- a/Sources/NBKSignedKit/NBKSigned+Literals.swift +++ /dev/null @@ -1,79 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Signed x Literals -//*============================================================================* - -extension NBKSigned { - - //=------------------------------------------------------------------------= - // MARK: Initializers x Integer Literal Type - //=------------------------------------------------------------------------= - #if SBI && swift(>=5.8) - - @inlinable public init(integerLiteral source: StaticBigInt) { - if let value = Self(exactlyIntegerLiteral: source) { self = value } else { - preconditionFailure("\(Self.description) cannot represent \(source)") - } - } - - @inlinable init?(exactlyIntegerLiteral source: StaticBigInt) { - self.init(words: NBKStaticBigInt(source)) - } - - #else - - @inlinable public init(integerLiteral source: Int) { - self.init(source) - } - - @inlinable init?(exactlyIntegerLiteral source: Int) { - self.init(exactly: source) - } - - #endif - //=------------------------------------------------------------------------= - // MARK: Initializers x String Literal Type - //=------------------------------------------------------------------------= - - /// Creates a new instance from the given string literal. - /// - /// The string literal may contain a plus or minus sign (+ or -), followed by - /// an optional radix indicator (0b, 0o or 0x), then one or more numeric digits - /// (0-9) or letters (a-z or A-Z). If the string literal uses an invalid format, - /// or its value cannot be represented, a runtime error may occur. - /// - /// ``` - /// ┌───────── → ─────────────┐ - /// │ literal │ self │ - /// ├───────── → ─────────────┤ - /// │ "123" │ Int256( 123) │ - /// │ "+0x123" │ Int256( 291) │ - /// │ "-0x123" │ Int256(-291) │ - /// │ "~OX123" │ error │ - /// └───────── → ─────────────┘ - /// ``` - /// - /// - Note: The decoding strategy is case insensitive. - /// - @inlinable public init(stringLiteral source: StaticString) { - if let value = Self(exactlyStringLiteral: source) { self = value } else { - preconditionFailure("\(Self.description) cannot represent \(source)") - } - } - - @inlinable init?(exactlyStringLiteral source: StaticString) { - let decoder = NBK.IntegerDescription.DecoderDecodingRadix() - guard let components: SM = decoder.decode(source) else { return nil } - self.init(sign: components.sign, magnitude: components.magnitude) - } -} diff --git a/Sources/NBKSignedKit/NBKSigned+Multiplication+Digit.swift b/Sources/NBKSignedKit/NBKSigned+Multiplication+Digit.swift deleted file mode 100644 index 0bd14a07..00000000 --- a/Sources/NBKSignedKit/NBKSigned+Multiplication+Digit.swift +++ /dev/null @@ -1,29 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Signed x Multiplication x Digit -//*============================================================================* - -extension NBKSigned { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @_disfavoredOverload @inlinable public static func *=(lhs: inout Self, rhs: Digit) { - lhs.sign ^= rhs.sign; lhs.magnitude *= rhs.magnitude - } - - @_disfavoredOverload @inlinable public static func *(lhs: Self, rhs: Digit) -> Self { - Self(sign: lhs.sign ^ rhs.sign, magnitude: lhs.magnitude * rhs.magnitude) - } -} diff --git a/Sources/NBKSignedKit/NBKSigned+Multiplication.swift b/Sources/NBKSignedKit/NBKSigned+Multiplication.swift deleted file mode 100644 index 112f698b..00000000 --- a/Sources/NBKSignedKit/NBKSigned+Multiplication.swift +++ /dev/null @@ -1,29 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Signed x Multiplication -//*============================================================================* - -extension NBKSigned { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable public static func *=(lhs: inout Self, rhs: Self) { - lhs.sign ^= rhs.sign; lhs.magnitude *= rhs.magnitude - } - - @inlinable public static func *(lhs: Self, rhs: Self) -> Self { - Self(sign: lhs.sign ^ rhs.sign, magnitude: lhs.magnitude * rhs.magnitude) - } -} diff --git a/Sources/NBKSignedKit/NBKSigned+Negation.swift b/Sources/NBKSignedKit/NBKSigned+Negation.swift deleted file mode 100644 index fac942ac..00000000 --- a/Sources/NBKSignedKit/NBKSigned+Negation.swift +++ /dev/null @@ -1,37 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Signed x Negation -//*============================================================================* - -extension NBKSigned { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable public static prefix func -(x: Self) -> Self { - x.negated() - } - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable public mutating func negate() { - self.sign.toggle() - } - - @inlinable public func negated() -> Self { - Self(sign: self.sign.toggled(), magnitude: self.magnitude) - } -} diff --git a/Sources/NBKSignedKit/NBKSigned+Numbers.swift b/Sources/NBKSignedKit/NBKSigned+Numbers.swift deleted file mode 100644 index 096a16c7..00000000 --- a/Sources/NBKSignedKit/NBKSigned+Numbers.swift +++ /dev/null @@ -1,124 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Signed x Numbers x Decoding -//*============================================================================* - -extension NBKSigned { - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - /// The positive zero value. - /// - /// Positive and negative zero are equal and have the same `hashValue`. - /// - @inlinable public static var zero: Self { - Self(sign: Sign.plus, magnitude: Magnitude.zero) - } - - //=------------------------------------------------------------------------= - // MARK: Initializers x Digit - //=------------------------------------------------------------------------= - - @inlinable public init(digit: Digit) { - let sign = digit.sign - let magnitude = Magnitude(digit: digit.magnitude) - self.init(sign: sign, magnitude: magnitude) - } - - //=------------------------------------------------------------------------= - // MARK: Initializers x Magnitude - //=------------------------------------------------------------------------= - - @inlinable public init(_ source: Magnitude) { - self.init(sign: Sign.plus, magnitude: source) - } - - @inlinable public init?(exactly source: Magnitude) { - self.init(sign: Sign.plus, magnitude: source) - } - - @inlinable public init(clamping source: Magnitude) { - self.init(sign: Sign.plus, magnitude: source) - } - - //=------------------------------------------------------------------------= - // MARK: Initializers x Binary Integer - //=------------------------------------------------------------------------= - // NOTE: Using init(sign:magnitude:) is more efficient than init(words:). - //=------------------------------------------------------------------------= - - @inlinable public init(_ source: some BinaryInteger) { - if let value = Self(exactly: source) { self = value } else { - preconditionFailure("\(Self.description) cannot represent \(source)") - } - } - - @inlinable public init?(exactly source: T) { - let sign = Sign(bit: source < T.zero) - guard let magnitude = Magnitude(exactly: source.magnitude) else { return nil } - self.init(sign: sign, magnitude: magnitude) - } - - @inlinable public init(clamping source: T) { - let sign = Sign(bit: source < T.zero) - let magnitude = Magnitude(clamping: source.magnitude) - self.init(sign: sign, magnitude: magnitude) - } -} - -//=----------------------------------------------------------------------------= -// MARK: + Fixed Width -//=----------------------------------------------------------------------------= - -extension NBKSigned where Magnitude: FixedWidthInteger { - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - @inlinable public static var max: Self { - Self(sign: Sign.plus, magnitude: Magnitude.max) - } - - @inlinable public static var min: Self { - Self(sign: Sign.minus, magnitude: Magnitude.max) - } -} - -//*============================================================================* -// MARK: * NBK x Signed x Numbers x Encoding -//*============================================================================* - -extension NBKBinaryInteger { - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - @inlinable public init(_ source: NBKSigned) { - if let value = Self(exactly: source) { self = value } else { - preconditionFailure("\(Self.self) cannot represent \(source)") - } - } - - @inlinable public init?(exactly source: NBKSigned) { - guard let magnitude: Magnitude = NBK.initOrBitCast(exactly: source.magnitude) else { return nil } - self.init(sign: source.sign, magnitude: magnitude) - } - - @inlinable public init(clamping source: NBKSigned) where Self: NBKFixedWidthInteger { - self = Self(exactly: source) ?? (source.sign == FloatingPointSign.plus ? Self.max : Self.min) - } -} diff --git a/Sources/NBKSignedKit/NBKSigned+Subtraction+Digit.swift b/Sources/NBKSignedKit/NBKSigned+Subtraction+Digit.swift deleted file mode 100644 index 3e9eb837..00000000 --- a/Sources/NBKSignedKit/NBKSigned+Subtraction+Digit.swift +++ /dev/null @@ -1,34 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Signed x Subtraction x Digit -//*============================================================================* - -extension NBKSigned { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @_disfavoredOverload @inlinable public static func -=(lhs: inout Self, rhs: Digit) { - if lhs.sign != rhs.sign { - lhs.magnitude += rhs.magnitude - } else if lhs.magnitude.subtractReportingOverflow(rhs.magnitude) { - lhs.sign.toggle() - lhs.magnitude.formTwosComplement() - } - } - - @_disfavoredOverload @inlinable public static func -(lhs: Self, rhs: Digit) -> Self { - var lhs = lhs; lhs -= rhs; return lhs - } -} diff --git a/Sources/NBKSignedKit/NBKSigned+Subtraction.swift b/Sources/NBKSignedKit/NBKSigned+Subtraction.swift deleted file mode 100644 index 8a8e3d26..00000000 --- a/Sources/NBKSignedKit/NBKSigned+Subtraction.swift +++ /dev/null @@ -1,34 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Signed x Subtraction -//*============================================================================* - -extension NBKSigned { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable public static func -=(lhs: inout Self, rhs: Self) { - if lhs.sign != rhs.sign { - lhs.magnitude += rhs.magnitude - } else if lhs.magnitude.subtractReportingOverflow(rhs.magnitude) { - lhs.sign.toggle() - lhs.magnitude.formTwosComplement() - } - } - - @inlinable public static func -(lhs: Self, rhs: Self) -> Self { - var lhs = lhs; lhs -= rhs; return lhs - } -} diff --git a/Sources/NBKSignedKit/NBKSigned+Text.swift b/Sources/NBKSignedKit/NBKSigned+Text.swift deleted file mode 100644 index e761eb2b..00000000 --- a/Sources/NBKSignedKit/NBKSigned+Text.swift +++ /dev/null @@ -1,145 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Signed x Text -//*============================================================================* - -extension NBKSigned { - - //=------------------------------------------------------------------------= - // MARK: Details x Decoding - //=------------------------------------------------------------------------= - - /// Creates a new instance from the given `description`. - /// - /// The `description` may contain a plus or minus sign (+ or -), followed - /// by one or more numeric digits (0-9). If the description uses an invalid - /// format, or its value cannot be represented, the result is nil. - /// - /// ``` - /// ┌──────────── → ─────────────┐ - /// │ description │ self │ - /// ├──────────── → ─────────────┤ - /// │ "123" │ Int256( 123) │ - /// │ "+123" │ Int256( 123) │ - /// │ "-123" │ Int256(-123) │ - /// │ "~123" │ nil │ - /// └──────────── → ─────────────┘ - /// ``` - /// - /// - Note: The decoding strategy is case insensitive. - /// - /// - Note: This member is required by `Swift.LosslessStringConvertible`. - /// - @inlinable public init?(_ description: String) { - self.init(description, radix: 10) - } - - /// Creates a new instance from the given `description` and `radix`. - /// - /// The `description` may contain a plus or minus sign (+ or -), followed by one - /// or more numeric digits (0-9) or letters (a-z or A-Z). If the description uses - /// an invalid format, or its value cannot be represented, the result is nil. - /// - /// ``` - /// ┌─────────────┬────── → ─────────────┐ - /// │ description │ radix │ self │ - /// ├─────────────┼────── → ─────────────┤ - /// │ "123" │ 16 │ Int256( 291) │ - /// │ "+123" │ 16 │ Int256( 291) │ - /// │ "-123" │ 16 │ Int256(-291) │ - /// │ "~123" │ 16 │ nil │ - /// └─────────────┴────── → ─────────────┘ - /// ``` - /// - /// - Note: The decoding strategy is case insensitive. - /// - @inlinable public init?(_ description: some StringProtocol, radix: Int) { - let decoder = NBK.IntegerDescription.Decoder(radix: radix) - guard let components: SM = decoder.decode(description) else { return nil } - self.init(sign: components.sign, magnitude: components.magnitude) - } - - //=------------------------------------------------------------------------= - // MARK: Details x Encoding - //=------------------------------------------------------------------------= - - /// A `description` of this value in base 10 ASCII. - /// - /// The description may contain a minus sign (-), followed by one - /// or more numeric digits (0-9) or letters (a-z or A-Z). These represent - /// the integer's sign and magnitude. Zero is always non-negative. - /// - /// ``` - /// ┌───────────── → ────────────┐ - /// │ self │ description │ - /// ├───────────── → ────────────┤ - /// │ Int256( 123) │ "123" │ - /// │ Int256(-123) │ "-123" │ - /// └───────────── → ────────────┘ - /// ``` - /// - /// - Note: This member is required by `Swift.CustomStringConvertible`. - /// - @inlinable public var description: String { - self.description(radix: 10, uppercase: false) - } - - /// A `description` of this value in the given ASCII format. - /// - /// The description may contain a minus sign (-), followed by one - /// or more numeric digits (0-9) or letters (a-z or A-Z). These represent - /// the integer's sign and magnitude. Zero is always non-negative. - /// - /// ``` - /// ┌──────────────┬───────┬─────────── → ────────────┐ - /// │ self │ radix │ uppercase │ description │ - /// ├──────────────┼───────┼─────────── → ────────────┤ - /// │ Int256( 123) │ 12 │ true │ "A3" │ - /// │ Int256(-123) │ 16 │ false │ "-7b" │ - /// └──────────────┴───────┴─────────── → ────────────┘ - /// ``` - /// - @inlinable public func description(radix: Int, uppercase: Bool) -> String { - NBK.IntegerDescription.Encoder(radix: radix, uppercase: uppercase).encode(self.components) - } -} - -//=----------------------------------------------------------------------------= -// MARK: + String -//=----------------------------------------------------------------------------= - -extension String { - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - /// Creates a string representing the given value, in the given format. - /// - /// The description may contain a minus sign (-), followed by one - /// or more numeric digits (0-9) or letters (a-z or A-Z). These represent - /// the integer's sign and magnitude. Zero is always non-negative. - /// - /// ``` - /// ┌──────────────┬───────┬─────────── → ────────────┐ - /// │ integer │ radix │ uppercase │ self │ - /// ├──────────────┼───────┼─────────── → ────────────┤ - /// │ Int256( 123) │ 12 │ true │ "A3" │ - /// │ Int256(-123) │ 16 │ false │ "-7b" │ - /// └──────────────┴───────┴─────────── → ────────────┘ - /// ``` - /// - @inlinable public init(_ value: NBKSigned, radix: Int = 10, uppercase: Bool = false) { - self = value.description(radix: radix, uppercase: uppercase) - } -} diff --git a/Sources/NBKSignedKit/NBKSigned+Words.swift b/Sources/NBKSignedKit/NBKSigned+Words.swift deleted file mode 100644 index ae063aa4..00000000 --- a/Sources/NBKSignedKit/NBKSigned+Words.swift +++ /dev/null @@ -1,109 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Signed x Words -//*============================================================================* - -extension NBKSigned { - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - @inlinable public init?(words: some RandomAccessCollection) { - self.init(words: words, isSigned: true) - } - - @inlinable public init?(words: some RandomAccessCollection, isSigned: Bool) { - let isLessThanZero: Bool = isSigned && words.last?.mostSignificantBit == true - guard let magnitude = Magnitude(words: NBK.MaybeTwosComplement(words, formTwosComplement: isLessThanZero)) else { return nil } - self.init(sign: Sign(bit: isLessThanZero), magnitude: magnitude) - } - - //=------------------------------------------------------------------------= - // MARK: Utilities - //=------------------------------------------------------------------------= - - @inlinable public var words: Words { - Words(self) - } - - //*========================================================================* - // MARK: * Words - //*========================================================================* - - @frozen public struct Words: RandomAccessCollection { - - //=--------------------------------------------------------------------= - // MARK: State - //=--------------------------------------------------------------------= - - public let count: Int - @usableFromInline let sign: UInt - @usableFromInline let base: NBK.MaybeTwosComplement - - //=--------------------------------------------------------------------= - // MARK: Initializers - //=--------------------------------------------------------------------= - - @inlinable init(_ source: NBKSigned) { - let isLessThanZero = (source.isLessThanZero) - self.sign = UInt(repeating: isLessThanZero) - self.base = NBK.MaybeTwosComplement(source.magnitude.words, formTwosComplement: isLessThanZero) - self.count = self.base.count + Int(bit:/**/self.base.last?.mostSignificantBit != isLessThanZero) - } - - //=--------------------------------------------------------------------= - // MARK: Accessors - //=--------------------------------------------------------------------= - - @inlinable public var startIndex: Int { - (0 as Int) - } - - @inlinable public var endIndex: Int { - self.count - } - - @inlinable public var indices: Range { - 0 as Int ..< self.count - } - - @inlinable public subscript(index: Int) -> UInt { - index < self.base.count ? self.base[self.base.index(self.base.startIndex, offsetBy: index)] : self.sign - } - - //=--------------------------------------------------------------------= - // MARK: Utilities - //=--------------------------------------------------------------------= - - @inlinable public func distance(from start: Int, to end: Int) -> Int { - end - start - } - - @inlinable public func index(after index: Int) -> Int { - index + 1 as Int - } - - @inlinable public func index(before index: Int) -> Int { - index - 1 as Int - } - - @inlinable public func index(_ index: Int, offsetBy distance: Int) -> Int { - index + distance - } - - @inlinable public func index(_ index: Int, offsetBy distance: Int, limitedBy limit: Int) -> Int? { - NBK.arrayIndex(index, offsetBy: distance, limitedBy: limit) - } - } -} diff --git a/Sources/NBKSignedKit/NBKSigned.swift b/Sources/NBKSignedKit/NBKSigned.swift deleted file mode 100644 index 67ca4552..00000000 --- a/Sources/NBKSignedKit/NBKSigned.swift +++ /dev/null @@ -1,160 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Signed -//*============================================================================* - -/// A decorative sign-and-magnitude integer. -/// -/// ```swift -/// typealias SInt = NBKSigned -/// let max = SInt(sign: .plus, magnitude: .max) -/// let min = SInt(sign: .minus, magnitude: .max) -/// ``` -/// -/// ### 🧭 Plus Zero & Minus Zero -/// -/// Zero is signed, meaning that it can be either positive or negative. These values -/// are comparatively equal and have the same hash value. -/// -/// - use `isLessThanZero` to check if a value is `negative` and non-zero -/// - use `isMoreThanZero` to check if a value is `positive` and non-zero -/// -/// ### 🚀 Single Digit Arithmagick -/// -/// Alongside its ordinary arithmagick operations, ``NBKSigned`` provides -/// single-digit operations, where a digit is a sign and an unsigned machine word. -/// These operations are more efficient for small calculations. Here are some examples: -/// -/// ```swift -/// SIntXL(1) + SInt(1) -/// SIntXL(2) - SInt(2) -/// SIntXL(3) * SInt(3) -/// SIntXL(4) / SInt(4) -/// SIntXL(5) % SInt(5) -/// ``` -/// -/// - Note: The `Digit` type is `NBKSigned`. -/// -@frozen public struct NBKSigned: Comparable, -CustomStringConvertible, ExpressibleByIntegerLiteral, ExpressibleByStringLiteral, -Hashable, Sendable, SignedNumeric { - - public typealias Sign = FloatingPointSign - - public typealias Digit = NBKSigned - - //=------------------------------------------------------------------------= - // MARK: Meta Data - //=------------------------------------------------------------------------= - - @inlinable public static var isSigned: Bool { - true - } - - /// A `description` of this type. - /// - /// ``` - /// ┌────────────────── → ─────────────────── = ───────┐ - /// │ type │ description │ a.k.a. │ - /// ├────────────────── → ─────────────────── = ───────┤ - /// │ NBKSigned │ "NBKSigned" │ SInt │ - /// │ NBKSigned │ "NBKSigned" │ SIntXL │ - /// └────────────────── → ─────────────────── = ───────┘ - /// ``` - /// - @inlinable public static var description: String { - String(describing: Self.self) - } - - //=------------------------------------------------------------------------= - // MARK: State - //=------------------------------------------------------------------------= - - /// The sign of this value. - public var sign: Sign - - /// The magnitude of this value. - public var magnitude: Magnitude - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - /// Creates a new instance with a positive zero value. - @inlinable public init() { - self.init(sign: Sign.plus, magnitude: Magnitude()) - } - - /// Creates a new instance with the given sign and magnitude. - @inlinable public init(sign: Sign, magnitude: Magnitude) { - self.sign = sign; self.magnitude = magnitude - } - - //=------------------------------------------------------------------------= - // MARK: Details x Components - //=------------------------------------------------------------------------= - - /// Creates a new instance from the given `sign` and `magnitude`. - @inlinable public init(components: SM) { - (sign: self.sign, magnitude: self.magnitude) = components - } - - /// The `sign` and `magnitude` of this value. - @inlinable public var components: SM { - get { (sign: self.sign, magnitude: self.magnitude) } - set { (self.sign, self.magnitude) = newValue as SM } - } - - //=------------------------------------------------------------------------= - // MARK: Details x Normalization - //=------------------------------------------------------------------------= - - /// Returns `true` for all values, except negative zero where it returns `false`. - @inlinable public var isNormal: Bool { - self.sign == Sign.plus || !self.isZero - } - - /// Returns the sign when for all values, except negative zero where it returns `plus`. - @inlinable public var normalizedSign: Sign { - self.isNormal ? self.sign : Sign.plus - } - - /// Turns negative zero into positive zero. - @inlinable public mutating func normalize() { - self.sign = self.normalizedSign - } - - /// Turns negative zero into positive zero. - @inlinable public func normalized() -> Self { - Self(sign: self.normalizedSign, magnitude: self.magnitude) - } -} - -//*============================================================================* -// MARK: * NBK x Signed x Aliases -//*============================================================================* - -/// A signed integer with a pointer-bit magnitude. -public typealias SInt = NBKSigned - -/// A signed integer with an 8-bit magnitude. -public typealias SInt8 = NBKSigned - -/// A signed integer with a 16-bit magnitude. -public typealias SInt16 = NBKSigned - -/// A signed integer with a 32-bit magnitude. -public typealias SInt32 = NBKSigned - -/// A signed integer with a 64-bit magnitude. -public typealias SInt64 = NBKSigned diff --git a/Sources/Numberick/Numberick.swift b/Sources/Numberick/Numberick.swift index a36bbccd..73e171b2 100644 --- a/Sources/Numberick/Numberick.swift +++ b/Sources/Numberick/Numberick.swift @@ -14,11 +14,3 @@ @_exported import NBKCoreKit @_exported import NBKDoubleWidthKit @_exported import NBKFlexibleWidthKit -@_exported import NBKSignedKit - -//*============================================================================* -// MARK: * NBK x Aliases -//*============================================================================* - -/// A signed integer with a flexible-width magnitude. -public typealias SIntXL = NBKSigned diff --git a/Tests/NBKSignedKitBenchmarks/NBKFlexibleWidth.swift b/Tests/NBKSignedKitBenchmarks/NBKFlexibleWidth.swift deleted file mode 100644 index fc87285b..00000000 --- a/Tests/NBKSignedKitBenchmarks/NBKFlexibleWidth.swift +++ /dev/null @@ -1,57 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit -import NBKFlexibleWidthKit -import NBKSignedKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Flexible Width x UIntXL -//*============================================================================* - -extension UIntXL { - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - static let min256 = Self(x64:[ 0, 0, 0, 0] as X) - static let max256 = Self(x64:[~0, ~0, ~0, ~0] as X) - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - init(x32: [UInt32]) { - self.init(words: NBKChunkedInt(x32)) - } - - init(x64: [UInt64]) { - self.init(words: NBKChunkedInt(x64)) - } -} - -//=----------------------------------------------------------------------------= -// MARK: + SIntXL -//=----------------------------------------------------------------------------= - -extension NBKSigned { - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - static let min256 = Self(sign: .minus, magnitude: Magnitude.max256) - static let max256 = Self(sign: .plus, magnitude: Magnitude.max256) -} diff --git a/Tests/NBKSignedKitBenchmarks/NBKSigned+Addition.swift b/Tests/NBKSignedKitBenchmarks/NBKSigned+Addition.swift deleted file mode 100644 index 2666fab9..00000000 --- a/Tests/NBKSignedKitBenchmarks/NBKSigned+Addition.swift +++ /dev/null @@ -1,84 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if !DEBUG - -import NBKCoreKit -import NBKFlexibleWidthKit -import NBKSignedKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Signed x Addition x SIntXL -//*============================================================================* - -final class NBKSignedBenchmarksOnAdditionAsSIntXL: XCTestCase { - - typealias T = NBKSigned - typealias M = NBKSigned.Magnitude - typealias D = NBKSigned.Digit - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testAdd() { - var lhs = NBK.blackHoleIdentity(T(M(x64:[~0, ~1, ~2, ~3] as X))) - var rhs = NBK.blackHoleIdentity(T(M(x64:[ 0, 1, 2, 3] as X))) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(lhs += rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testAdding() { - var lhs = NBK.blackHoleIdentity(T(M(x64:[~0, ~1, ~2, ~3] as X))) - var rhs = NBK.blackHoleIdentity(T(M(x64:[ 0, 1, 2, 3] as X))) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs + rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Digit - //=------------------------------------------------------------------------= - - func testAddDigit() { - var lhs = NBK.blackHoleIdentity(T(M(x64:[~0, ~1, ~2, ~3] as X))) - var rhs = NBK.blackHoleIdentity(D.max) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(lhs += rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testAddingDigit() { - var lhs = NBK.blackHoleIdentity(T(M(x64:[~0, ~1, ~2, ~3] as X))) - var rhs = NBK.blackHoleIdentity(D.max) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs + rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } -} - -#endif diff --git a/Tests/NBKSignedKitBenchmarks/NBKSigned+Comparisons.swift b/Tests/NBKSignedKitBenchmarks/NBKSigned+Comparisons.swift deleted file mode 100644 index ffa702f9..00000000 --- a/Tests/NBKSignedKitBenchmarks/NBKSigned+Comparisons.swift +++ /dev/null @@ -1,129 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if !DEBUG - -import NBKCoreKit -import NBKFlexibleWidthKit -import NBKSignedKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Signed x Comparisons x SIntXL -//*============================================================================* - -final class NBKSignedBenchmarksOnComparisonsAsSIntXL: XCTestCase { - - typealias T = NBKSigned - typealias M = NBKSigned.Magnitude - typealias D = NBKSigned.Digit - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testIsZero() { - var abc = NBK.blackHoleIdentity(T(M(x64:[0, 1, 2, 3] as X))) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.isZero) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testIsLessThanZero() { - var abc = NBK.blackHoleIdentity(T(M(x64:[0, 1, 2, 3] as X))) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.isLessThanZero) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testIsMoreThanZero() { - var abc = NBK.blackHoleIdentity(T(M(x64:[0, 1, 2, 3] as X))) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.isMoreThanZero) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testIsPowerOf2() { - var abc = NBK.blackHoleIdentity(T(M(x64:[0, 1, 2, 3] as X))) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.isPowerOf2) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testSignum() { - var abc = NBK.blackHoleIdentity(T(M(x64:[0, 1, 2, 3] as X))) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.signum()) - NBK.blackHoleInoutIdentity(&abc) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testIsEqualTo() { - var lhs = NBK.blackHoleIdentity(T(M(x64:[0, 1, 2, 3] as X))) - var rhs = NBK.blackHoleIdentity(T(M(x64:[0, 1, 2, 3] as X))) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(lhs == rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testIsLessThan() { - var lhs = NBK.blackHoleIdentity(T(M(x64:[0, 1, 2, 3] as X))) - var rhs = NBK.blackHoleIdentity(T(M(x64:[0, 1, 2, 3] as X))) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(lhs < rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testComparedTo() { - var lhs = NBK.blackHoleIdentity(T(M(x64:[0, 1, 2, 3] as X))) - var rhs = NBK.blackHoleIdentity(T(M(x64:[0, 1, 2, 3] as X))) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(lhs.compared(to: rhs)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testComparedToDigit() { - var lhs = NBK.blackHoleIdentity(T(M(x64:[0, 1, 2, 3] as X))) - var rhs = NBK.blackHoleIdentity(D.max) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(lhs.compared(to: rhs)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } -} - -#endif diff --git a/Tests/NBKSignedKitBenchmarks/NBKSigned+Complements.swift b/Tests/NBKSignedKitBenchmarks/NBKSigned+Complements.swift deleted file mode 100644 index b498e0f8..00000000 --- a/Tests/NBKSignedKitBenchmarks/NBKSigned+Complements.swift +++ /dev/null @@ -1,48 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if !DEBUG - -import NBKCoreKit -import NBKFlexibleWidthKit -import NBKSignedKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Signed x Complements x SIntXL -//*============================================================================* - -final class NBKSignedBenchmarksOnComplementsAsSIntXL: XCTestCase { - - typealias T = NBKSigned - typealias M = NBKSigned.Magnitude - - //=------------------------------------------------------------------------= - // MARK: Tests x Magnitude - //=------------------------------------------------------------------------= - - func testMagnitude() { - var abc = NBK.blackHoleIdentity(T(M(x64:[ 1, 2, 3, 4] as X))) - var xyz = NBK.blackHoleIdentity(T(M(x64:[~1, ~2, ~3, ~4] as X))) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc.magnitude) - NBK.blackHole(xyz.magnitude) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } -} - -#endif diff --git a/Tests/NBKSignedKitBenchmarks/NBKSigned+Division.swift b/Tests/NBKSignedKitBenchmarks/NBKSigned+Division.swift deleted file mode 100644 index 6158ff02..00000000 --- a/Tests/NBKSignedKitBenchmarks/NBKSigned+Division.swift +++ /dev/null @@ -1,77 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if !DEBUG - -import NBKCoreKit -import NBKFlexibleWidthKit -import NBKSignedKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Signed x Division x SIntXL -//*============================================================================* - -final class NBKSignedBenchmarksOnDivisionAsSIntXL: XCTestCase { - - typealias T = NBKSigned - typealias M = NBKSigned.Magnitude - typealias D = NBKSigned.Digit - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testQuotientAndRemainder() { - var lhs = NBK.blackHoleIdentity(T(M(x64:[~0, ~1, ~2, ~3] as X))) - var rhs = NBK.blackHoleIdentity(T(M(x64:[ 0, 1, 2, 3] as X))) - - for _ in 0 ..< 250_000 { - NBK.blackHole(lhs.quotientAndRemainder(dividingBy: rhs)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Digit - //=------------------------------------------------------------------------= - - func testQuotientAndRemainderDividingByDigit() { - var lhs = NBK.blackHoleIdentity(T(M(x64:[~0, ~1, ~2, ~3] as X))) - var rhs = NBK.blackHoleIdentity(D.max) - - for _ in 0 ..< 250_000 { - NBK.blackHole(lhs.quotientAndRemainder(dividingBy: rhs)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Full Width - //=------------------------------------------------------------------------= - - func testDividingFullWidthAs256() { - var lhs = NBK.blackHoleIdentity(T(M(x64:[~0, ~0, ~0, ~0, ~1, ~0, ~0, ~0] as X))) - var rhs = NBK.blackHoleIdentity(T(M(x64:[~0, ~0, ~0, ~0] as X))) - - for _ in 0 ..< 250_000 { - NBK.blackHole(lhs.quotientAndRemainder(dividingBy: rhs)) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } -} - -#endif diff --git a/Tests/NBKSignedKitBenchmarks/NBKSigned+Multiplication.swift b/Tests/NBKSignedKitBenchmarks/NBKSigned+Multiplication.swift deleted file mode 100644 index f53ff6b6..00000000 --- a/Tests/NBKSignedKitBenchmarks/NBKSigned+Multiplication.swift +++ /dev/null @@ -1,62 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if !DEBUG - -import NBKCoreKit -import NBKFlexibleWidthKit -import NBKSignedKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Signed x Multiplication x SIntXL -//*============================================================================* - -final class NBKSignedBenchmarksOnMultiplicationAsSIntXL: XCTestCase { - - typealias T = NBKSigned - typealias M = NBKSigned.Magnitude - typealias D = NBKSigned.Digit - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testMultiplied() { - var lhs = NBK.blackHoleIdentity(T(M(x64:[~1, ~2, ~3, ~4] as X))) - var rhs = NBK.blackHoleIdentity(T(M(x64:[ 1, 2, 3, 4] as X))) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs * rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Digit - //=------------------------------------------------------------------------= - - func testMultipliedByDigit() { - var lhs = NBK.blackHoleIdentity(T(M(x64:[~1, ~2, ~3, ~4] as X))) - var rhs = NBK.blackHoleIdentity(D.max) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs * rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } -} - -#endif diff --git a/Tests/NBKSignedKitBenchmarks/NBKSigned+Subtraction.swift b/Tests/NBKSignedKitBenchmarks/NBKSigned+Subtraction.swift deleted file mode 100644 index 6fcc2db9..00000000 --- a/Tests/NBKSignedKitBenchmarks/NBKSigned+Subtraction.swift +++ /dev/null @@ -1,84 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if !DEBUG - -import NBKCoreKit -import NBKFlexibleWidthKit -import NBKSignedKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Signed x Subtraction x SIntXL -//*============================================================================* - -final class NBKSignedBenchmarksOnSubtractionAsSIntXL: XCTestCase { - - typealias T = NBKSigned - typealias M = NBKSigned.Magnitude - typealias D = NBKSigned.Digit - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testSubtract() { - var lhs = NBK.blackHoleIdentity(T(M(x64:[~0, ~1, ~2, ~3] as X))) - var rhs = NBK.blackHoleIdentity(T(M(x64:[ 0, 1, 2, 3] as X))) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(lhs -= rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testSubtracting() { - var lhs = NBK.blackHoleIdentity(T(M(x64:[~0, ~1, ~2, ~3] as X))) - var rhs = NBK.blackHoleIdentity(T(M(x64:[ 0, 1, 2, 3] as X))) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs - rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Digit - //=------------------------------------------------------------------------= - - func testSubtractDigit() { - var lhs = NBK.blackHoleIdentity(T(M(x64:[~0, ~1, ~2, ~3] as X))) - var rhs = NBK.blackHoleIdentity(D.max) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(lhs -= rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } - - func testSubtractingDigit() { - var lhs = NBK.blackHoleIdentity(T(M(x64:[~0, ~1, ~2, ~3] as X))) - var rhs = NBK.blackHoleIdentity(D.max) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(lhs - rhs) - NBK.blackHoleInoutIdentity(&lhs) - NBK.blackHoleInoutIdentity(&rhs) - } - } -} - -#endif diff --git a/Tests/NBKSignedKitBenchmarks/NBKSigned+Text.swift b/Tests/NBKSignedKitBenchmarks/NBKSigned+Text.swift deleted file mode 100644 index 9ef16afb..00000000 --- a/Tests/NBKSignedKitBenchmarks/NBKSigned+Text.swift +++ /dev/null @@ -1,86 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if !DEBUG - -import NBKCoreKit -import NBKFlexibleWidthKit -import NBKSignedKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Signed x Text x SIntXL -//*============================================================================* - -final class NBKSignedBenchmarksOnTextAsSIntXL: XCTestCase { - - typealias T = NBKSigned - typealias M = NBKSigned.Magnitude - - //=------------------------------------------------------------------------= - // MARK: State - //=------------------------------------------------------------------------= - - static let decoded = NBK.blackHoleIdentity(T(encoded, radix: 16)!) - static let encoded = NBK.blackHoleIdentity(String(repeating: "1", count: 64)) - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testDecodingRadix10() { - var radix = NBK.blackHoleIdentity(10) - var encoded = NBK.blackHoleIdentity(Self.encoded) - - for _ in 0 ..< 250_000 { - NBK.blackHole(T(encoded, radix: radix)!) - NBK.blackHoleInoutIdentity(&radix) - NBK.blackHoleInoutIdentity(&encoded) - } - } - - func testDecodingRadix16() { - var radix = NBK.blackHoleIdentity(16) - var encoded = NBK.blackHoleIdentity(Self.encoded) - - for _ in 0 ..< 250_000 { - NBK.blackHole(T(encoded, radix: radix)!) - NBK.blackHoleInoutIdentity(&radix) - NBK.blackHoleInoutIdentity(&encoded) - } - } - - func testEncodingRadix10() { - var radix = NBK.blackHoleIdentity(10) - var decoded = NBK.blackHoleIdentity(Self.decoded) - - for _ in 0 ..< 250_000 { - NBK.blackHole(String(decoded, radix: radix)) - NBK.blackHoleInoutIdentity(&radix) - NBK.blackHoleInoutIdentity(&decoded) - } - } - - func testEncodingRadix16() { - var radix = NBK.blackHoleIdentity(16) - var decoded = NBK.blackHoleIdentity(Self.decoded) - - for _ in 0 ..< 250_000 { - NBK.blackHole(String(decoded, radix: radix)) - NBK.blackHoleInoutIdentity(&radix) - NBK.blackHoleInoutIdentity(&decoded) - } - } -} - -#endif diff --git a/Tests/NBKSignedKitBenchmarks/NBKSigned.swift b/Tests/NBKSignedKitBenchmarks/NBKSigned.swift deleted file mode 100644 index 8f9341de..00000000 --- a/Tests/NBKSignedKitBenchmarks/NBKSigned.swift +++ /dev/null @@ -1,46 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if !DEBUG - -import NBKCoreKit -import NBKFlexibleWidthKit -import NBKSignedKit -import XCTest - -private typealias X = NBK.U256X64 -private typealias Y = NBK.U256X32 - -//*============================================================================* -// MARK: * NBK x Signed x SIntXL -//*============================================================================* - -final class NBKSignedBenchmarksAsSIntXL: XCTestCase { - - typealias T = NBKSigned - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testInit() { - var abc = NBK.blackHoleIdentity(SM(sign: .plus, magnitude: UIntXL(1))) - var xyz = NBK.blackHoleIdentity(SM(sign: .minus, magnitude: UIntXL(1))) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(T(sign: abc.sign, magnitude: abc.magnitude)) - NBK.blackHole(T(sign: xyz.sign, magnitude: xyz.magnitude)) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } -} - -#endif diff --git a/Tests/NBKSignedKitTests/NBKFlexibleWidth.swift b/Tests/NBKSignedKitTests/NBKFlexibleWidth.swift deleted file mode 100644 index fc87285b..00000000 --- a/Tests/NBKSignedKitTests/NBKFlexibleWidth.swift +++ /dev/null @@ -1,57 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit -import NBKFlexibleWidthKit -import NBKSignedKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Flexible Width x UIntXL -//*============================================================================* - -extension UIntXL { - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - static let min256 = Self(x64:[ 0, 0, 0, 0] as X) - static let max256 = Self(x64:[~0, ~0, ~0, ~0] as X) - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - init(x32: [UInt32]) { - self.init(words: NBKChunkedInt(x32)) - } - - init(x64: [UInt64]) { - self.init(words: NBKChunkedInt(x64)) - } -} - -//=----------------------------------------------------------------------------= -// MARK: + SIntXL -//=----------------------------------------------------------------------------= - -extension NBKSigned { - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - static let min256 = Self(sign: .minus, magnitude: Magnitude.max256) - static let max256 = Self(sign: .plus, magnitude: Magnitude.max256) -} diff --git a/Tests/NBKSignedKitTests/NBKSigned+Addition.swift b/Tests/NBKSignedKitTests/NBKSigned+Addition.swift deleted file mode 100644 index dcff0959..00000000 --- a/Tests/NBKSignedKitTests/NBKSigned+Addition.swift +++ /dev/null @@ -1,126 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if DEBUG - -import NBKCoreKit -import NBKFlexibleWidthKit -import NBKSignedKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Signed x Addition x SIntXL -//*============================================================================* - -final class NBKSignedTestsOnAdditionAsSIntXL: XCTestCase { - - typealias T = NBKSigned - typealias M = NBKSigned.Magnitude - typealias D = NBKSigned.Digit - typealias U = NBKSigned.Digit.Magnitude - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testAddingLargeToLarge() { - NBKAssertAddition( T(M(x64:[~0, ~0, ~0, 0] as X)), T(M(x64:[3, 0, 0, 0] as X)), T(M(x64:[ 2, 0, 0, 1] as X))) - NBKAssertAddition( T(M(x64:[~0, ~0, ~0, 0] as X)), T(M(x64:[0, 3, 0, 0] as X)), T(M(x64:[~0, 2, 0, 1] as X))) - NBKAssertAddition( T(M(x64:[~0, ~0, ~0, 0] as X)), T(M(x64:[0, 0, 3, 0] as X)), T(M(x64:[~0, ~0, 2, 1] as X))) - NBKAssertAddition( T(M(x64:[~0, ~0, ~0, 0] as X)), T(M(x64:[0, 0, 0, 3] as X)), T(M(x64:[~0, ~0, ~0, 3] as X))) - - NBKAssertAddition( T(M(x64:[~0, ~0, ~0, 0] as X)), -T(M(x64:[3, 0, 0, 0] as X)), T(M(x64:[~3, ~0, ~0, 0] as X))) - NBKAssertAddition( T(M(x64:[~0, ~0, ~0, 0] as X)), -T(M(x64:[0, 3, 0, 0] as X)), T(M(x64:[~0, ~3, ~0, 0] as X))) - NBKAssertAddition( T(M(x64:[~0, ~0, ~0, 0] as X)), -T(M(x64:[0, 0, 3, 0] as X)), T(M(x64:[~0, ~0, ~3, 0] as X))) - NBKAssertAddition( T(M(x64:[~0, ~0, ~0, 0] as X)), -T(M(x64:[0, 0, 0, 3] as X)), -T(M(x64:[ 1, 0, 0, 2] as X))) - - NBKAssertAddition(-T(M(x64:[~0, ~0, ~0, 0] as X)), T(M(x64:[3, 0, 0, 0] as X)), -T(M(x64:[~3, ~0, ~0, 0] as X))) - NBKAssertAddition(-T(M(x64:[~0, ~0, ~0, 0] as X)), T(M(x64:[0, 3, 0, 0] as X)), -T(M(x64:[~0, ~3, ~0, 0] as X))) - NBKAssertAddition(-T(M(x64:[~0, ~0, ~0, 0] as X)), T(M(x64:[0, 0, 3, 0] as X)), -T(M(x64:[~0, ~0, ~3, 0] as X))) - NBKAssertAddition(-T(M(x64:[~0, ~0, ~0, 0] as X)), T(M(x64:[0, 0, 0, 3] as X)), T(M(x64:[ 1, 0, 0, 2] as X))) - - NBKAssertAddition(-T(M(x64:[~0, ~0, ~0, 0] as X)), -T(M(x64:[3, 0, 0, 0] as X)), -T(M(x64:[ 2, 0, 0, 1] as X))) - NBKAssertAddition(-T(M(x64:[~0, ~0, ~0, 0] as X)), -T(M(x64:[0, 3, 0, 0] as X)), -T(M(x64:[~0, 2, 0, 1] as X))) - NBKAssertAddition(-T(M(x64:[~0, ~0, ~0, 0] as X)), -T(M(x64:[0, 0, 3, 0] as X)), -T(M(x64:[~0, ~0, 2, 1] as X))) - NBKAssertAddition(-T(M(x64:[~0, ~0, ~0, 0] as X)), -T(M(x64:[0, 0, 0, 3] as X)), -T(M(x64:[~0, ~0, ~0, 3] as X))) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Digit (and Self) - //=------------------------------------------------------------------------= - - func testAddingSmallToSmall() { - NBKAssertAdditionByDigit( T(M(1)), D(U(2)), T(M(3))) - NBKAssertAdditionByDigit( T(M(1)), D(U(1)), T(M(2))) - NBKAssertAdditionByDigit( T(M(1)), D(U(0)), T(M(1))) - NBKAssertAdditionByDigit( T(M(1)), -D(U(0)), T(M(1))) - NBKAssertAdditionByDigit( T(M(1)), -D(U(1)), T(M(0))) - NBKAssertAdditionByDigit( T(M(1)), -D(U(2)), -T(M(1))) - - NBKAssertAdditionByDigit( T(M(0)), D(U(2)), T(M(2))) - NBKAssertAdditionByDigit( T(M(0)), D(U(1)), T(M(1))) - NBKAssertAdditionByDigit( T(M(0)), D(U(0)), T(M(0))) - NBKAssertAdditionByDigit( T(M(0)), -D(U(0)), T(M(0))) - NBKAssertAdditionByDigit( T(M(0)), -D(U(1)), -T(M(1))) - NBKAssertAdditionByDigit( T(M(0)), -D(U(2)), -T(M(2))) - - NBKAssertAdditionByDigit(-T(M(0)), D(U(2)), T(M(2))) - NBKAssertAdditionByDigit(-T(M(0)), D(U(1)), T(M(1))) - NBKAssertAdditionByDigit(-T(M(0)), D(U(0)), -T(M(0))) - NBKAssertAdditionByDigit(-T(M(0)), -D(U(0)), -T(M(0))) - NBKAssertAdditionByDigit(-T(M(0)), -D(U(1)), -T(M(1))) - NBKAssertAdditionByDigit(-T(M(0)), -D(U(2)), -T(M(2))) - - NBKAssertAdditionByDigit(-T(M(1)), D(U(2)), T(M(1))) - NBKAssertAdditionByDigit(-T(M(1)), D(U(1)), -T(M(0))) - NBKAssertAdditionByDigit(-T(M(1)), D(U(0)), -T(M(1))) - NBKAssertAdditionByDigit(-T(M(1)), -D(U(0)), -T(M(1))) - NBKAssertAdditionByDigit(-T(M(1)), -D(U(1)), -T(M(2))) - NBKAssertAdditionByDigit(-T(M(1)), -D(U(2)), -T(M(3))) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Miscellaneous - //=------------------------------------------------------------------------= - - func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { - func becauseThisCompilesSuccessfully(_ x: inout T) { - XCTAssertNotNil(x += 0) - XCTAssertNotNil(x + 0) - } - } -} - -//*============================================================================* -// MARK: * NBK x Signed x Addition x Assertions -//*============================================================================* - -private func NBKAssertAddition( -_ lhs: NBKSigned, _ rhs: NBKSigned, _ partialValue: NBKSigned, -file: StaticString = #file, line: UInt = #line) { - //=------------------------------------------= - NBKAssertIdentical( lhs + rhs, partialValue, file: file, line: line) - NBKAssertIdentical({ var lhs = lhs; lhs += rhs; return lhs }(), partialValue, file: file, line: line) -} - -private func NBKAssertAdditionByDigit( -_ lhs: NBKSigned, _ rhs: NBKSigned.Digit, _ partialValue: NBKSigned, -file: StaticString = #file, line: UInt = #line) { - //=------------------------------------------= - NBKAssertAddition(lhs, NBKSigned(digit: rhs), partialValue) - //=------------------------------------------= - NBKAssertIdentical( lhs + rhs, partialValue, file: file, line: line) - NBKAssertIdentical({ var lhs = lhs; lhs += rhs; return lhs }(), partialValue, file: file, line: line) -} - -#endif diff --git a/Tests/NBKSignedKitTests/NBKSigned+Comparisons.swift b/Tests/NBKSignedKitTests/NBKSigned+Comparisons.swift deleted file mode 100644 index ff203438..00000000 --- a/Tests/NBKSignedKitTests/NBKSigned+Comparisons.swift +++ /dev/null @@ -1,191 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if DEBUG - -import NBKCoreKit -import NBKFlexibleWidthKit -import NBKSignedKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Signed x Comparisons -//*============================================================================* - -final class NBKSignedTestsOnComparisonsAsSIntXL: XCTestCase { - - typealias T = NBKSigned - typealias M = NBKSigned.Magnitude - typealias D = NBKSigned.Digit - typealias U = NBKSigned.Digit.Magnitude - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testIsZero() { - XCTAssertTrue (( T(0)).isZero) - XCTAssertTrue ((-T(0)).isZero) - XCTAssertFalse(( T(1)).isZero) - XCTAssertFalse((-T(1)).isZero) - } - - func testIsLessThanZero() { - XCTAssertFalse(( T(0)).isLessThanZero) - XCTAssertFalse((-T(0)).isLessThanZero) - XCTAssertFalse(( T(1)).isLessThanZero) - XCTAssertTrue ((-T(1)).isLessThanZero) - } - - func testIsMoreThanZero() { - XCTAssertFalse(( T(0)).isMoreThanZero) - XCTAssertFalse((-T(0)).isMoreThanZero) - XCTAssertTrue (( T(1)).isMoreThanZero) - XCTAssertFalse((-T(1)).isMoreThanZero) - } - - func testIsPowerOf2() { - XCTAssertFalse((-T(3)).isPowerOf2) - XCTAssertFalse((-T(2)).isPowerOf2) - XCTAssertFalse((-T(1)).isPowerOf2) - XCTAssertFalse((-T(0)).isPowerOf2) - XCTAssertFalse(( T(0)).isPowerOf2) - XCTAssertTrue (( T(1)).isPowerOf2) - XCTAssertTrue (( T(2)).isPowerOf2) - XCTAssertFalse(( T(3)).isPowerOf2) - - XCTAssertFalse(T(M(words:[ 0, 0, 0, 0] as W)).isPowerOf2) - XCTAssertTrue (T(M(words:[ 1, 0, 0, 0] as W)).isPowerOf2) - XCTAssertFalse(T(M(words:[ 1, 1, 0, 0] as W)).isPowerOf2) - XCTAssertTrue (T(M(words:[ 0, 1, 0, 0] as W)).isPowerOf2) - XCTAssertFalse(T(M(words:[ 0, 1, 1, 0] as W)).isPowerOf2) - XCTAssertTrue (T(M(words:[ 0, 0, 1, 0] as W)).isPowerOf2) - XCTAssertFalse(T(M(words:[ 0, 0, 1, 1] as W)).isPowerOf2) - XCTAssertTrue (T(M(words:[ 0, 0, 0, 1] as W)).isPowerOf2) - } - - func testSignum() { - NBKAssertSignum(( T(0)), Int( 0)) - NBKAssertSignum((-T(0)), Int( 0)) - NBKAssertSignum(( T(1)), Int( 1)) - NBKAssertSignum((-T(1)), Int(-1)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testHashing() { - var union = Set() - union.insert( T(0)) - union.insert( T(0)) - union.insert(-T(0)) - union.insert(-T(0)) - union.insert( T(1)) - union.insert( T(1)) - union.insert(-T(1)) - union.insert(-T(1)) - XCTAssertEqual(union.count, 3) - } - - func testComparingLargeWithLarge() { - NBKAssertComparisons(T(M(words:[0, 2, 3, 4] as W)), T(M(words:[1, 2, 3, 4] as W)), -Int(1)) - NBKAssertComparisons(T(M(words:[1, 0, 3, 4] as W)), T(M(words:[1, 2, 3, 4] as W)), -Int(1)) - NBKAssertComparisons(T(M(words:[1, 2, 0, 4] as W)), T(M(words:[1, 2, 3, 4] as W)), -Int(1)) - NBKAssertComparisons(T(M(words:[1, 2, 3, 0] as W)), T(M(words:[1, 2, 3, 4] as W)), -Int(1)) - NBKAssertComparisons(T(M(words:[0, 2, 3, 4] as W)), T(M(words:[0, 2, 3, 4] as W)), Int(0)) - NBKAssertComparisons(T(M(words:[1, 0, 3, 4] as W)), T(M(words:[1, 0, 3, 4] as W)), Int(0)) - NBKAssertComparisons(T(M(words:[1, 2, 0, 4] as W)), T(M(words:[1, 2, 0, 4] as W)), Int(0)) - NBKAssertComparisons(T(M(words:[1, 2, 3, 0] as W)), T(M(words:[1, 2, 3, 0] as W)), Int(0)) - NBKAssertComparisons(T(M(words:[1, 2, 3, 4] as W)), T(M(words:[0, 2, 3, 4] as W)), Int(1)) - NBKAssertComparisons(T(M(words:[1, 2, 3, 4] as W)), T(M(words:[1, 0, 3, 4] as W)), Int(1)) - NBKAssertComparisons(T(M(words:[1, 2, 3, 4] as W)), T(M(words:[1, 2, 0, 4] as W)), Int(1)) - NBKAssertComparisons(T(M(words:[1, 2, 3, 4] as W)), T(M(words:[1, 2, 3, 0] as W)), Int(1)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Digit (and Self) - //=------------------------------------------------------------------------= - - func testComparingSmallWithSmall() { - NBKAssertComparisonsByDigit( T(0), D(0), Int(0)) - NBKAssertComparisonsByDigit( T(0), -D(0), Int(0)) - NBKAssertComparisonsByDigit(-T(0), D(0), Int(0)) - NBKAssertComparisonsByDigit(-T(0), -D(0), Int(0)) - - NBKAssertComparisonsByDigit( T(1), D(1), Int(0)) - NBKAssertComparisonsByDigit( T(1), -D(1), Int(1)) - NBKAssertComparisonsByDigit(-T(1), D(1), -Int(1)) - NBKAssertComparisonsByDigit(-T(1), -D(1), Int(0)) - - NBKAssertComparisonsByDigit( T(2), D(3), -Int(1)) - NBKAssertComparisonsByDigit( T(2), -D(3), Int(1)) - NBKAssertComparisonsByDigit(-T(2), D(3), -Int(1)) - NBKAssertComparisonsByDigit(-T(2), -D(3), Int(1)) - - NBKAssertComparisonsByDigit( T(3), D(2), Int(1)) - NBKAssertComparisonsByDigit( T(3), -D(2), Int(1)) - NBKAssertComparisonsByDigit(-T(3), D(2), -Int(1)) - NBKAssertComparisonsByDigit(-T(3), -D(2), -Int(1)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Miscellaneous - //=------------------------------------------------------------------------= - - func testOverloadsAreUnambiguous() { - func becauseThisCompilesSuccessfully(_ x: inout T) { - XCTAssertNotNil(x.signum()) - } - } - - func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { - func becauseThisCompilesSuccessfully(_ x: inout T) { - XCTAssertNotNil(x.compared(to: 0)) - } - } -} - -//*============================================================================* -// MARK: * NBK x Signed x Comparisons x Assertions -//*============================================================================* - -private func NBKAssertSignum(_ operand: NBKSigned, _ signum: Int, file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual(Int(operand.signum() as Int), signum, file: file, line: line) -} - -private func NBKAssertComparisons( -_ lhs: NBKSigned, _ rhs: NBKSigned, _ signum: Int, -file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual(lhs == rhs, signum == 0, file: file, line: line) - XCTAssertEqual(lhs != rhs, signum != 0, file: file, line: line) - - XCTAssertEqual(lhs < rhs, signum == -1, file: file, line: line) - XCTAssertEqual(lhs <= rhs, signum != 1, file: file, line: line) - - XCTAssertEqual(lhs > rhs, signum == 1, file: file, line: line) - XCTAssertEqual(lhs >= rhs, signum != -1, file: file, line: line) - - XCTAssertEqual(lhs.compared(to: rhs), signum, file: file, line: line) -} - -private func NBKAssertComparisonsByDigit( -_ lhs: NBKSigned, _ rhs: NBKSigned.Digit, _ signum: Int, -file: StaticString = #file, line: UInt = #line) { - //=------------------------------------------= - NBKAssertComparisons(lhs, NBKSigned(digit: rhs), signum) - //=------------------------------------------= - XCTAssertEqual(lhs.compared(to: rhs), signum, file: file, line: line) -} - -#endif diff --git a/Tests/NBKSignedKitTests/NBKSigned+Complements.swift b/Tests/NBKSignedKitTests/NBKSigned+Complements.swift deleted file mode 100644 index ec91d9bd..00000000 --- a/Tests/NBKSignedKitTests/NBKSigned+Complements.swift +++ /dev/null @@ -1,43 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if DEBUG - -import NBKCoreKit -import NBKFlexibleWidthKit -import NBKSignedKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Signed x Complements x Open Source Issues -//*============================================================================* - -final class NBKSignedTestsOnComplementsOpenSourceIssues: XCTestCase { - - typealias SIntXL = NBKSigned - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - /// https://github.com/apple/swift-numerics/pull/252 - /// - /// - Note: Said to return incorrect values. - /// - func testSwiftNumericsPull252() { - XCTAssertEqual(SIntXL(Int.min ).magnitude, UIntXL(Int.min.magnitude)) - XCTAssertEqual(SIntXL(Int.min.magnitude).magnitude, UIntXL(Int.min.magnitude)) - } -} - -#endif diff --git a/Tests/NBKSignedKitTests/NBKSigned+Division.swift b/Tests/NBKSignedKitTests/NBKSigned+Division.swift deleted file mode 100644 index 754c0f54..00000000 --- a/Tests/NBKSignedKitTests/NBKSigned+Division.swift +++ /dev/null @@ -1,169 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if DEBUG - -import NBKCoreKit -import NBKFlexibleWidthKit -import NBKSignedKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Signed x Division x SIntXL -//*============================================================================* - -final class NBKSignedTestsOnDivisionAsSIntXL: XCTestCase { - - typealias T = NBKSigned - typealias M = NBKSigned.Magnitude - typealias D = NBKSigned.Digit - typealias U = NBKSigned.Digit.Magnitude - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testDividingLargeByLarge() { - NBKAssertDivision( T(M(x64:[~2, ~4, ~6, 9] as X)), T(M(x64:[~1, ~2, ~3, 4] as X)), T(2), T(1)) - NBKAssertDivision( T(M(x64:[~3, ~6, ~9, 14] as X)), -T(M(x64:[~1, ~2, ~3, 4] as X)), -T(3), T(2)) - NBKAssertDivision(-T(M(x64:[~4, ~8, ~12, 19] as X)), T(M(x64:[~1, ~2, ~3, 4] as X)), -T(4), -T(3)) - NBKAssertDivision(-T(M(x64:[~5, ~10, ~15, 24] as X)), -T(M(x64:[~1, ~2, ~3, 4] as X)), T(5), -T(4)) - } - - func testDividingLargeByLargeWithLargeRemainder() { - NBKAssertDivision( T(M(x64:[1, 2, 3, 4 + 1 << 63] as X)), T(M(x64:[ 1, 2, 3, 4 &+ 1 << 63] as X)), T(1), T(M(x64:[0, 0, 0, 0] as X))) - NBKAssertDivision( T(M(x64:[1, 2, 3, 4 + 1 << 63] as X)), T(M(x64:[ 0, 1, 2, 3 &+ 1 << 63] as X)), T(1), T(M(x64:[1, 1, 1, 1] as X))) - NBKAssertDivision( T(M(x64:[1, 2, 3, 4 + 1 << 63] as X)), -T(M(x64:[~0, ~0, 0, 2 &+ 1 << 63] as X)), -T(1), T(M(x64:[2, 2, 2, 2] as X))) - NBKAssertDivision( T(M(x64:[1, 2, 3, 4 + 1 << 63] as X)), -T(M(x64:[~1, ~1, ~0, 0 &+ 1 << 63] as X)), -T(1), T(M(x64:[3, 3, 3, 3] as X))) - NBKAssertDivision(-T(M(x64:[1, 2, 3, 4 + 1 << 63] as X)), T(M(x64:[~2, ~2, ~1, ~0 &+ 1 << 63] as X)), -T(1), -T(M(x64:[4, 4, 4, 4] as X))) - NBKAssertDivision(-T(M(x64:[1, 2, 3, 4 + 1 << 63] as X)), T(M(x64:[~3, ~3, ~2, ~1 &+ 1 << 63] as X)), -T(1), -T(M(x64:[5, 5, 5, 5] as X))) - NBKAssertDivision(-T(M(x64:[1, 2, 3, 4 + 1 << 63] as X)), -T(M(x64:[~4, ~4, ~3, ~2 &+ 1 << 63] as X)), T(1), -T(M(x64:[6, 6, 6, 6] as X))) - NBKAssertDivision(-T(M(x64:[1, 2, 3, 4 + 1 << 63] as X)), -T(M(x64:[~5, ~5, ~4, ~3 &+ 1 << 63] as X)), T(1), -T(M(x64:[7, 7, 7, 7] as X))) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Digit - //=------------------------------------------------------------------------= - - func testDividingSmallBySmall() { - NBKAssertDivisionByDigit( T( ), D(1), T( ), D( )) - NBKAssertDivisionByDigit( T( ), -D(2), -T( ), D( )) - NBKAssertDivisionByDigit(-T(7), D(1), -T(7), -D( )) - NBKAssertDivisionByDigit(-T(7), -D(2), T(3), -D(1)) - - NBKAssertDivisionByDigit( T(7), D(3), T(2), D(1)) - NBKAssertDivisionByDigit( T(7), -D(3), -T(2), D(1)) - NBKAssertDivisionByDigit(-T(7), D(3), -T(2), -D(1)) - NBKAssertDivisionByDigit(-T(7), -D(3), T(2), -D(1)) - } - - func testDividingLargeBySmall() { - NBKAssertDivisionByDigit( T(M(words:[1, 2, 3, 4] as W)), D(2), T(M(words:[0, ~0/2 + 2, 1, 2] as W)), D(1)) - NBKAssertDivisionByDigit( T(M(words:[1, 2, 3, 4] as W)), -D(2), -T(M(words:[0, ~0/2 + 2, 1, 2] as W)), D(1)) - NBKAssertDivisionByDigit(-T(M(words:[1, 2, 3, 4] as W)), D(2), -T(M(words:[0, ~0/2 + 2, 1, 2] as W)), -D(1)) - NBKAssertDivisionByDigit(-T(M(words:[1, 2, 3, 4] as W)), -D(2), T(M(words:[0, ~0/2 + 2, 1, 2] as W)), -D(1)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Miscellaneous - //=------------------------------------------------------------------------= - - func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { - func becauseThisCompilesSuccessfully(_ x: inout T) { - XCTAssertNotNil(x /= 0) - XCTAssertNotNil(x %= 0) - XCTAssertNotNil(x / 0) - XCTAssertNotNil(x % 0) - XCTAssertNotNil(x.quotientAndRemainder(dividingBy: 0)) - } - } -} - -//*============================================================================* -// MARK: * NBK x Signed x Division x Open Source Issues -//*============================================================================* - -final class NBKSignedTestsOnDivisionOpenSourceIssues: XCTestCase { - - typealias SIntXL = NBKSigned - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - /// https://github.com/apple/swift-numerics/pull/250 - /// - /// - Note: Said to crash and return incorrect values. - /// - func testSwiftNumericsPull250() { - NBKAssertDivision( - SIntXL("-9223372036854775808"), - SIntXL("-0000000000000000001"), - SIntXL("+9223372036854775808"), - SIntXL("-0000000000000000000")) - - NBKAssertDivision( - SIntXL("+18446744073709551615"), - SIntXL("-00000000000000000001"), - SIntXL("-18446744073709551615"), - SIntXL("+00000000000000000000")) - - NBKAssertDivision( - SIntXL("-340282366920938463481821351505477763074"), - SIntXL("+000000000000000000018446744073709551629"), - SIntXL("-000000000000000000018446744073709551604"), - SIntXL("-000000000000000000000000000000000000158")) - } -} - -//*============================================================================* -// MARK: * NBK x Signed x Division x Assertions -//*============================================================================* - -private func NBKAssertDivision( -_ lhs: NBKSigned, _ rhs: NBKSigned, _ quotient: NBKSigned, _ remainder: NBKSigned, -file: StaticString = #file, line: UInt = #line) { - //=------------------------------------------= - XCTAssertEqual(lhs, quotient * rhs + remainder, "dividend != divisor * quotient + remainder", file: file, line: line) - //=------------------------------------------= - NBKAssertIdentical(lhs / rhs, quotient, file: file, line: line) - NBKAssertIdentical(lhs % rhs, remainder, file: file, line: line) - - NBKAssertIdentical({ var x = lhs; x /= rhs; return x }(), quotient, file: file, line: line) - NBKAssertIdentical({ var x = lhs; x %= rhs; return x }(), remainder, file: file, line: line) - - NBKAssertIdentical(lhs.quotientAndRemainder(dividingBy: rhs).quotient, quotient, file: file, line: line) - NBKAssertIdentical(lhs.quotientAndRemainder(dividingBy: rhs).remainder, remainder, file: file, line: line) -} - -private func NBKAssertDivisionByDigit( -_ lhs: NBKSigned, _ rhs: NBKSigned.Digit, _ quotient: NBKSigned, _ remainder: NBKSigned.Digit, -file: StaticString = #file, line: UInt = #line) { - //=------------------------------------------= - let extended = NBKSigned(digit: remainder) - //=------------------------------------------= - NBKAssertDivision(lhs, NBKSigned(digit: rhs), quotient, extended) - //=------------------------------------------= - XCTAssertEqual(lhs, quotient * rhs + remainder, "dividend != divisor * quotient + remainder", file: file, line: line) - //=------------------------------------------= - NBKAssertIdentical(lhs / rhs, quotient, file: file, line: line) - NBKAssertIdentical(lhs % rhs, remainder, file: file, line: line) - - NBKAssertIdentical({ var x = lhs; x /= rhs; return x }(), quotient, file: file, line: line) - NBKAssertIdentical({ var x = lhs; x %= rhs; return x }(), extended, file: file, line: line) - - NBKAssertIdentical(lhs.quotientAndRemainder(dividingBy: rhs).quotient, quotient, file: file, line: line) - NBKAssertIdentical(lhs.quotientAndRemainder(dividingBy: rhs).remainder, remainder, file: file, line: line) -} - -#endif diff --git a/Tests/NBKSignedKitTests/NBKSigned+Literals.swift b/Tests/NBKSignedKitTests/NBKSigned+Literals.swift deleted file mode 100644 index a9cf811c..00000000 --- a/Tests/NBKSignedKitTests/NBKSigned+Literals.swift +++ /dev/null @@ -1,145 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if DEBUG - -import NBKCoreKit -import NBKFlexibleWidthKit -@testable import NBKSignedKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Signed x Literals -//*============================================================================* - -final class NBKSignedTestsOnLiterals: XCTestCase { - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testFromIntegerLiteralAsSInt32() { - XCTAssertEqual(NBKSigned(exactlyIntegerLiteral: 4294967296), nil) - XCTAssertEqual(NBKSigned(exactlyIntegerLiteral: 4294967295), NBKSigned.max) - XCTAssertEqual(NBKSigned(exactlyIntegerLiteral: -4294967295), NBKSigned.min) - XCTAssertEqual(NBKSigned(exactlyIntegerLiteral: -4294967296), nil) - } - - func testFromIntegerLiteralAsSInt64() { - #if SBI && swift(>=5.8) - XCTAssertEqual(NBKSigned(exactlyIntegerLiteral: 18446744073709551616), nil) - XCTAssertEqual(NBKSigned(exactlyIntegerLiteral: 18446744073709551615), NBKSigned.max) - XCTAssertEqual(NBKSigned(exactlyIntegerLiteral: -18446744073709551615), NBKSigned.min) - XCTAssertEqual(NBKSigned(exactlyIntegerLiteral: -18446744073709551616), nil) - #endif - } -} - -//*============================================================================* -// MARK: * NBK x Signed x Literals x SIntXL -//*============================================================================* - -final class NBKSignedTestsOnLiteralsAsSIntXL: XCTestCase { - - typealias T = NBKSigned - typealias M = NBKSigned.Magnitude - - //=------------------------------------------------------------------------= - // MARK: State - //=------------------------------------------------------------------------= - - let top256 = T(M(x64:[0xe7e6e5e4e3e2e1e0, 0xefeeedecebeae9e8, 0xf7f6f5f4f3f2f1f0, 0xfffefdfcfbfaf9f8] as X)) - let bottom256 = T(M(x64:[0x0706050403020100, 0x0f0e0d0c0b0a0908, 0x1716151413121110, 0x1f1e1d1c1b1a1918] as X)) - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testFromIntegerLiteral() { - XCTAssertEqual( T(M(x64:[ 0, 0, 0, 0] as X)), (0)) - XCTAssertEqual( T(M(x64:[10, 0, 0, 0] as X)), (10)) - XCTAssertEqual( T(M(x64:[ 2, 0, 0, 0] as X)), (0b10)) - XCTAssertEqual( T(M(x64:[ 8, 0, 0, 0] as X)), (0o10)) - XCTAssertEqual( T(M(x64:[16, 0, 0, 0] as X)), (0x10)) - XCTAssertEqual( T(M(x64:[ 0, 0, 0, 0] as X)), (+0)) - XCTAssertEqual( T(M(x64:[10, 0, 0, 0] as X)), (+10)) - XCTAssertEqual( T(M(x64:[ 2, 0, 0, 0] as X)), (+0b10)) - XCTAssertEqual( T(M(x64:[ 8, 0, 0, 0] as X)), (+0o10)) - XCTAssertEqual( T(M(x64:[16, 0, 0, 0] as X)), (+0x10)) - XCTAssertEqual(-T(M(x64:[ 0, 0, 0, 0] as X)), (-0)) - XCTAssertEqual(-T(M(x64:[10, 0, 0, 0] as X)), (-10)) - XCTAssertEqual(-T(M(x64:[ 2, 0, 0, 0] as X)), (-0b10)) - XCTAssertEqual(-T(M(x64:[ 8, 0, 0, 0] as X)), (-0o10)) - XCTAssertEqual(-T(M(x64:[16, 0, 0, 0] as X)), (-0x10)) - #if SBI && swift(>=5.8) - XCTAssertEqual(self.top256/*--------*/, (0x00000000000000fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e0)) - XCTAssertEqual(self.bottom256/*-----*/, (0x000000000000001f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100)) - XCTAssertEqual(T(exactlyIntegerLiteral: (0x000000000000010000000000000000000000000000000000000000000000000000000000000000)), T.max256 / 1 + 1) - XCTAssertEqual(T(exactlyIntegerLiteral: (0x00000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)), T.max256 / 1 + 0) - XCTAssertEqual(T(exactlyIntegerLiteral: (-0x00000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)), T.min256 / 1 - 0) - XCTAssertEqual(T(exactlyIntegerLiteral: (-0x000000000000010000000000000000000000000000000000000000000000000000000000000000)), T.min256 / 1 - 1) - XCTAssertEqual(T(exactlyIntegerLiteral: (0x000000000000008000000000000000000000000000000000000000000000000000000000000000)), T.max256 / 2 + 1) - XCTAssertEqual(T(exactlyIntegerLiteral: (0x000000000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)), T.max256 / 2 + 0) - XCTAssertEqual(T(exactlyIntegerLiteral: (-0x000000000000008000000000000000000000000000000000000000000000000000000000000000)), T.min256 / 2 - 1) - XCTAssertEqual(T(exactlyIntegerLiteral: (-0x000000000000008000000000000000000000000000000000000000000000000000000000000001)), T.min256 / 2 - 2) - - XCTAssertEqual(self.top256/*--------*/, (00115790308505455567723526024286119531261069242336003260839703036409543150199264)) - XCTAssertEqual(self.bottom256/*-----*/, (00014074904626401341155369551180448584754667373453244490859944217516317499064576)) - XCTAssertEqual(T(exactlyIntegerLiteral: (00115792089237316195423570985008687907853269984665640564039457584007913129639936)), T.max256 / 1 + 1) - XCTAssertEqual(T(exactlyIntegerLiteral: (00115792089237316195423570985008687907853269984665640564039457584007913129639935)), T.max256 / 1 + 0) - XCTAssertEqual(T(exactlyIntegerLiteral: (-00115792089237316195423570985008687907853269984665640564039457584007913129639935)), T.min256 / 1 - 0) - XCTAssertEqual(T(exactlyIntegerLiteral: (-00115792089237316195423570985008687907853269984665640564039457584007913129639936)), T.min256 / 1 - 1) - XCTAssertEqual(T(exactlyIntegerLiteral: (00057896044618658097711785492504343953926634992332820282019728792003956564819968)), T.max256 / 2 + 1) - XCTAssertEqual(T(exactlyIntegerLiteral: (00057896044618658097711785492504343953926634992332820282019728792003956564819967)), T.max256 / 2 + 0) - XCTAssertEqual(T(exactlyIntegerLiteral: (-00057896044618658097711785492504343953926634992332820282019728792003956564819968)), T.min256 / 2 - 1) - XCTAssertEqual(T(exactlyIntegerLiteral: (-00057896044618658097711785492504343953926634992332820282019728792003956564819969)), T.min256 / 2 - 2) - #else - XCTAssertEqual(T(integerLiteral: Int.max), T(M(x64:[UInt64(UInt.max / 2 + 0), 0, 0, 0] as X))) - XCTAssertEqual(T(integerLiteral: Int.min), -T(M(x64:[UInt64(UInt.max / 2 + 1), 0, 0, 0] as X))) - #endif - } - - func testFromStringLiteral() { - XCTAssertEqual( T(M(x64:[ 0, 0, 0, 0] as X)), "0") - XCTAssertEqual( T(M(x64:[10, 0, 0, 0] as X)), "10") - XCTAssertEqual( T(M(x64:[ 2, 0, 0, 0] as X)), "0b10") - XCTAssertEqual( T(M(x64:[ 8, 0, 0, 0] as X)), "0o10") - XCTAssertEqual( T(M(x64:[16, 0, 0, 0] as X)), "0x10") - XCTAssertEqual( T(M(x64:[ 0, 0, 0, 0] as X)), "+0") - XCTAssertEqual( T(M(x64:[10, 0, 0, 0] as X)), "+10") - XCTAssertEqual( T(M(x64:[ 2, 0, 0, 0] as X)), "+0b10") - XCTAssertEqual( T(M(x64:[ 8, 0, 0, 0] as X)), "+0o10") - XCTAssertEqual( T(M(x64:[16, 0, 0, 0] as X)), "+0x10") - XCTAssertEqual(-T(M(x64:[ 0, 0, 0, 0] as X)), "-0") - XCTAssertEqual(-T(M(x64:[10, 0, 0, 0] as X)), "-10") - XCTAssertEqual(-T(M(x64:[ 2, 0, 0, 0] as X)), "-0b10") - XCTAssertEqual(-T(M(x64:[ 8, 0, 0, 0] as X)), "-0o10") - XCTAssertEqual(-T(M(x64:[16, 0, 0, 0] as X)), "-0x10") - - XCTAssertEqual(self.top256/*-------*/, "0x00000000000000fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e0") - XCTAssertEqual(self.bottom256/*----*/, "0x000000000000001f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100") - XCTAssertEqual(T(exactlyStringLiteral: "0x000000000000010000000000000000000000000000000000000000000000000000000000000000"), T.max256 + 1) - XCTAssertEqual(T(exactlyStringLiteral: "0x00000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), T.max256) - XCTAssertEqual(T(exactlyStringLiteral: "-0x00000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), T.min256) - XCTAssertEqual(T(exactlyStringLiteral: "-0x000000000000010000000000000000000000000000000000000000000000000000000000000000"), T.min256 - 1) - - XCTAssertEqual(self.top256/*-------*/, "00115790308505455567723526024286119531261069242336003260839703036409543150199264") - XCTAssertEqual(self.bottom256/*----*/, "00014074904626401341155369551180448584754667373453244490859944217516317499064576") - XCTAssertEqual(T(exactlyStringLiteral: "00115792089237316195423570985008687907853269984665640564039457584007913129639936"), T.max256 + 1) - XCTAssertEqual(T(exactlyStringLiteral: "00115792089237316195423570985008687907853269984665640564039457584007913129639935"), T.max256) - XCTAssertEqual(T(exactlyStringLiteral: "-00115792089237316195423570985008687907853269984665640564039457584007913129639935"), T.min256) - XCTAssertEqual(T(exactlyStringLiteral: "-00115792089237316195423570985008687907853269984665640564039457584007913129639936"), T.min256 - 1) - } -} - -#endif diff --git a/Tests/NBKSignedKitTests/NBKSigned+Multiplication.swift b/Tests/NBKSignedKitTests/NBKSigned+Multiplication.swift deleted file mode 100644 index 0f9df536..00000000 --- a/Tests/NBKSignedKitTests/NBKSigned+Multiplication.swift +++ /dev/null @@ -1,98 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if DEBUG - -import NBKCoreKit -import NBKFlexibleWidthKit -import NBKSignedKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Signed x Multiplication x SIntXL -//*============================================================================* - -final class NBKSignedTestsOnMultiplicationAsSIntXL: XCTestCase { - - typealias T = NBKSigned - typealias M = NBKSigned.Magnitude - typealias D = NBKSigned.Digit - typealias U = NBKSigned.Digit.Magnitude - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testMultiplyingLargeByLarge() { - NBKAssertMultiplication( T( M(x64:[1, 2, 3, 4] as X)), T(M(x64:[2, 0, 0, 0] as X)), T(M(x64:[ 2, 4, 6, 8, 0, 0, 0, 0] as X))) - NBKAssertMultiplication( T( M(x64:[1, 2, 3, 4] as X)), -T(M(x64:[0, 2, 0, 0] as X)), -T(M(x64:[ 0, 2, 4, 6, 8, 0, 0, 0] as X))) - NBKAssertMultiplication(-T( M(x64:[1, 2, 3, 4] as X)), T(M(x64:[0, 0, 2, 0] as X)), -T(M(x64:[ 0, 0, 2, 4, 6, 8, 0, 0] as X))) - NBKAssertMultiplication(-T( M(x64:[1, 2, 3, 4] as X)), -T(M(x64:[0, 0, 0, 2] as X)), T(M(x64:[ 0, 0, 0, 2, 4, 6, 8, 0] as X))) - - NBKAssertMultiplication( T(~M(x64:[1, 2, 3, 4] as X)), T(M(x64:[2, 0, 0, 0] as X)), T(M(x64:[~3, ~4, ~6, ~8, 1, 0, 0, 0] as X))) - NBKAssertMultiplication( T(~M(x64:[1, 2, 3, 4] as X)), -T(M(x64:[0, 2, 0, 0] as X)), -T(M(x64:[ 0, ~3, ~4, ~6, ~8, 1, 0, 0] as X))) - NBKAssertMultiplication(-T(~M(x64:[1, 2, 3, 4] as X)), T(M(x64:[0, 0, 2, 0] as X)), -T(M(x64:[ 0, 0, ~3, ~4, ~6, ~8, 1, 0] as X))) - NBKAssertMultiplication(-T(~M(x64:[1, 2, 3, 4] as X)), -T(M(x64:[0, 0, 0, 2] as X)), T(M(x64:[ 0, 0, 0, ~3, ~4, ~6, ~8, 1] as X))) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Digit (and Self) - //=------------------------------------------------------------------------= - - func testMultiplyingLargeBySmall() { - NBKAssertMultiplicationByDigit( T( M(words:[1, 2, 3, 4] as W)), D(0), T( M(words:[ 0, 0, 0, 0, 0] as W))) - NBKAssertMultiplicationByDigit( T( M(words:[1, 2, 3, 4] as W)), -D(1), -T( M(words:[ 1, 2, 3, 4, 0] as W))) - NBKAssertMultiplicationByDigit(-T( M(words:[1, 2, 3, 4] as W)), D(2), -T( M(words:[ 2, 4, 6, 8, 0] as W))) - NBKAssertMultiplicationByDigit(-T( M(words:[1, 2, 3, 4] as W)), -D(3), T( M(words:[ 3, 6, 9, 12, 0] as W))) - - NBKAssertMultiplicationByDigit( T(~M(words:[1, 2, 3, 4] as W)), D(0), T(~M(words:[~0, ~0, ~0, ~0, ~0] as W))) - NBKAssertMultiplicationByDigit( T(~M(words:[1, 2, 3, 4] as W)), -D(1), -T(~M(words:[ 1, 2, 3, 4, ~0] as W))) - NBKAssertMultiplicationByDigit(-T(~M(words:[1, 2, 3, 4] as W)), D(2), -T(~M(words:[ 3, 4, 6, 8, ~1] as W))) - NBKAssertMultiplicationByDigit(-T(~M(words:[1, 2, 3, 4] as W)), -D(3), T(~M(words:[ 5, 6, 9, 12, ~2] as W))) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Miscellaneous - //=------------------------------------------------------------------------= - - func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { - func becauseThisCompilesSuccessfully(_ x: inout T) { - XCTAssertNotNil(x *= 0) - XCTAssertNotNil(x * 0) - } - } -} - -//*============================================================================* -// MARK: * NBK x Signed x Addition x Assertions -//*============================================================================* - -private func NBKAssertMultiplication( -_ lhs: NBKSigned, _ rhs: NBKSigned, _ result: NBKSigned, -file: StaticString = #file, line: UInt = #line) { - //=------------------------------------------= - NBKAssertIdentical( lhs * rhs, result, file: file, line: line) - NBKAssertIdentical({ var lhs = lhs; lhs *= rhs; return lhs }(), result, file: file, line: line) -} - -private func NBKAssertMultiplicationByDigit( -_ lhs: NBKSigned, _ rhs: NBKSigned.Digit, _ result: NBKSigned, -file: StaticString = #file, line: UInt = #line) { - //=------------------------------------------= - NBKAssertMultiplication(lhs, NBKSigned(digit: rhs), result) - //=------------------------------------------= - NBKAssertIdentical( lhs * rhs, result, file: file, line: line) - NBKAssertIdentical({ var lhs = lhs; lhs *= rhs; return lhs }(), result, file: file, line: line) -} - -#endif diff --git a/Tests/NBKSignedKitTests/NBKSigned+Negation.swift b/Tests/NBKSignedKitTests/NBKSigned+Negation.swift deleted file mode 100644 index fdfa356c..00000000 --- a/Tests/NBKSignedKitTests/NBKSigned+Negation.swift +++ /dev/null @@ -1,89 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if DEBUG - -import NBKSignedKit -import NBKFlexibleWidthKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Signed x Negation -//*============================================================================* - -final class NBKSignedTestsOnNegation: XCTestCase { - - typealias T = NBKSigned - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testNegating() { - NBKAssertNegation( T(1), -T(1)) - NBKAssertNegation( T(0), -T(0)) - NBKAssertNegation(-T(0), T(0)) - NBKAssertNegation(-T(1), T(1)) - - NBKAssertNegation(T.max, T.min) - NBKAssertNegation(T.min, T.max) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Miscellaneous - //=------------------------------------------------------------------------= - - func testOverloadsAreUnambiguous() { - func becauseThisCompilesSuccessfully(_ x: inout T) { - XCTAssertNotNil(-x) - XCTAssertNotNil(x.negate()) - XCTAssertNotNil(x.negated()) - } - } -} - -//*============================================================================* -// MARK: * NBK x Signed x Negation x Open Source Issues -//*============================================================================* - -final class NBKSignedTestsOnNegationOpenSourceIssues: XCTestCase { - - typealias SIntXL = NBKSigned - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - /// https://github.com/apple/swift-numerics/pull/253 - /// - /// - Note: Said to return incorrect values. - /// - func testSwiftNumericsPull253() { - NBKAssertNegation(SIntXL(Int.min), SIntXL(Int.min.magnitude)) - NBKAssertNegation(SIntXL(Int.min.magnitude), SIntXL(Int.min)) - } -} - -//*============================================================================* -// MARK: * NBK x Signed x Negation x Assertions -//*============================================================================* - -private func NBKAssertNegation( -_ operand: NBKSigned, _ result: NBKSigned, -file: StaticString = #file, line: UInt = #line) { - NBKAssertIdentical(-operand, result, file: file, line: line) - NBKAssertIdentical((operand).negated(), result, file: file, line: line) - NBKAssertIdentical({ var x = operand; x.negate(); return x }(), result, file: file, line: line) -} - -#endif diff --git a/Tests/NBKSignedKitTests/NBKSigned+Numbers.swift b/Tests/NBKSignedKitTests/NBKSigned+Numbers.swift deleted file mode 100644 index bc9a292b..00000000 --- a/Tests/NBKSignedKitTests/NBKSigned+Numbers.swift +++ /dev/null @@ -1,198 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if DEBUG - -import NBKCoreKit -import NBKSignedKit -import NBKFlexibleWidthKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Signed x Numbers -//*============================================================================* - -final class NBKSignedTestsOnNumbers: XCTestCase { - - typealias T = NBKSigned - typealias M = NBKSigned.Magnitude - typealias D = NBKSigned.Digit - typealias S = Int - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testZero() { - NBKAssertIdentical(T( ), T(sign: .plus, magnitude: M( ))) - NBKAssertIdentical(T.zero, T(sign: .plus, magnitude: M( ))) - } - - func testEdges() { - NBKAssertIdentical(T.max, T(sign: .plus, magnitude: M.max)) - NBKAssertIdentical(T.min, T(sign: .minus, magnitude: M.max)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Digit - //=------------------------------------------------------------------------= - - func testFromDigit() { - NBKAssertIdentical(T(digit: D(4)), T(4)) - NBKAssertIdentical(T(digit: -D(4)), -T(4)) - NBKAssertIdentical(D(digit: D(4)), D(4)) - NBKAssertIdentical(D(digit: -D(4)), -D(4)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Signitude - //=------------------------------------------------------------------------= - - func testsToSignitude() { - XCTAssertEqual(S( T(sign: .plus , magnitude: M( 1))), S( 1)) - XCTAssertEqual(S(exactly: T(sign: .plus , magnitude: M( 1))), S( 1)) - XCTAssertEqual(S(clamping: T(sign: .plus , magnitude: M( 1))), S( 1)) - - XCTAssertEqual(S( T(sign: .minus, magnitude: M( 1))), S(-1)) - XCTAssertEqual(S(exactly: T(sign: .minus, magnitude: M( 1))), S(-1)) - XCTAssertEqual(S(clamping: T(sign: .minus, magnitude: M( 1))), S(-1)) - - XCTAssertEqual(S(exactly: T(sign: .plus , magnitude: M.max)), nil) - XCTAssertEqual(S(clamping: T(sign: .plus , magnitude: M.max)), S.max) - - XCTAssertEqual(S(exactly: T(sign: .minus, magnitude: M.max)), nil) - XCTAssertEqual(S(clamping: T(sign: .minus, magnitude: M.max)), S.min) - - XCTAssertEqual(S( T(sign: .plus , magnitude: S.max.magnitude)), S.max) - XCTAssertEqual(S(exactly: T(sign: .plus , magnitude: S.max.magnitude)), S.max) - XCTAssertEqual(S(clamping: T(sign: .plus , magnitude: S.max.magnitude)), S.max) - - XCTAssertEqual(S( T(sign: .minus, magnitude: S.min.magnitude)), S.min) - XCTAssertEqual(S(exactly: T(sign: .minus, magnitude: S.min.magnitude)), S.min) - XCTAssertEqual(S(clamping: T(sign: .minus, magnitude: S.min.magnitude)), S.min) - } - - func testToSignitudeAsPlusMinusZero() { - XCTAssertEqual(S( T(sign: .plus , magnitude: M( ))), S( )) - XCTAssertEqual(S(exactly: T(sign: .plus , magnitude: M( ))), S( )) - XCTAssertEqual(S(clamping: T(sign: .plus , magnitude: M( ))), S( )) - - XCTAssertEqual(S( T(sign: .minus, magnitude: M( ))), S( )) - XCTAssertEqual(S(exactly: T(sign: .minus, magnitude: M( ))), S( )) - XCTAssertEqual(S(clamping: T(sign: .minus, magnitude: M( ))), S( )) - } - - func testFromSignitude() { - NBKAssertIdentical(T( S( 1)), T(1)) - NBKAssertIdentical(T(exactly: S( 1)), T(1)) - NBKAssertIdentical(T(clamping: S( 1)), T(1)) - - NBKAssertIdentical(T( S( )), T( )) - NBKAssertIdentical(T(exactly: S( )), T( )) - NBKAssertIdentical(T(clamping: S( )), T( )) - - NBKAssertIdentical(T( S(-1)), -T(1)) - NBKAssertIdentical(T(exactly: S(-1)), -T(1)) - NBKAssertIdentical(T(clamping: S(-1)), -T(1)) - - NBKAssertIdentical(T( S.max), T(sign: .plus, magnitude: M(S.max) + 0)) - NBKAssertIdentical(T(exactly: S.max), T(sign: .plus, magnitude: M(S.max) + 0)) - NBKAssertIdentical(T(clamping: S.max), T(sign: .plus, magnitude: M(S.max) + 0)) - - NBKAssertIdentical(T( S.min), T(sign: .minus, magnitude: M(S.max) + 1)) - NBKAssertIdentical(T(exactly: S.min), T(sign: .minus, magnitude: M(S.max) + 1)) - NBKAssertIdentical(T(clamping: S.min), T(sign: .minus, magnitude: M(S.max) + 1)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Magnitude - //=------------------------------------------------------------------------= - - func testsToMagnitude() { - XCTAssertEqual(M( T(sign: .plus , magnitude: M( 1))), M( 1)) - XCTAssertEqual(M(exactly: T(sign: .plus , magnitude: M( 1))), M( 1)) - XCTAssertEqual(M(clamping: T(sign: .plus , magnitude: M( 1))), M( 1)) - - XCTAssertEqual(M(exactly: T(sign: .minus, magnitude: M( 1))), nil) - XCTAssertEqual(M(clamping: T(sign: .minus, magnitude: M( 1))), M.min) - - XCTAssertEqual(M( T(sign: .plus , magnitude: M.max)), M.max) - XCTAssertEqual(M(exactly: T(sign: .plus , magnitude: M.max)), M.max) - XCTAssertEqual(M(clamping: T(sign: .plus , magnitude: M.max)), M.max) - - XCTAssertEqual(M(exactly: T(sign: .minus, magnitude: M.max)), nil) - XCTAssertEqual(M(clamping: T(sign: .minus, magnitude: M.max)), M.min) - - XCTAssertEqual(M( T(sign: .plus , magnitude: M.max.magnitude)), M.max) - XCTAssertEqual(M(exactly: T(sign: .plus , magnitude: M.max.magnitude)), M.max) - XCTAssertEqual(M(clamping: T(sign: .plus , magnitude: M.max.magnitude)), M.max) - - XCTAssertEqual(M( T(sign: .minus, magnitude: M.min.magnitude)), M.min) - XCTAssertEqual(M(exactly: T(sign: .minus, magnitude: M.min.magnitude)), M.min) - XCTAssertEqual(M(clamping: T(sign: .minus, magnitude: M.min.magnitude)), M.min) - } - - func testToMagnitudeAsPlusMinusZero() { - XCTAssertEqual(M( T(sign: .plus , magnitude: M( ))), M( )) - XCTAssertEqual(M(exactly: T(sign: .plus , magnitude: M( ))), M( )) - XCTAssertEqual(M(clamping: T(sign: .plus , magnitude: M( ))), M( )) - - XCTAssertEqual(M( T(sign: .minus, magnitude: M( ))), M( )) - XCTAssertEqual(M(exactly: T(sign: .minus, magnitude: M( ))), M( )) - XCTAssertEqual(M(clamping: T(sign: .minus, magnitude: M( ))), M( )) - } - - func testFromMagnitude() { - NBKAssertIdentical(T( M( )), T( )) - NBKAssertIdentical(T(exactly: M( )), T( )) - NBKAssertIdentical(T(clamping: M( )), T( )) - - NBKAssertIdentical(T( M( 1)), T( 1)) - NBKAssertIdentical(T(exactly: M( 1)), T( 1)) - NBKAssertIdentical(T(clamping: M( 1)), T( 1)) - - NBKAssertIdentical(T( M.max), T.max) - NBKAssertIdentical(T(exactly: M.max), T.max) - NBKAssertIdentical(T(clamping: M.max), T.max) - } -} - -//*============================================================================* -// MARK: * NBK x Signed x Numbers x Open Source Issues -//*============================================================================* - -final class NBKSignedTestsOnNumbersOpenSourceIssues: XCTestCase { - - typealias SIntXL = NBKSigned - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - /// https://github.com/apple/swift-numerics/pull/254 - /// - /// - Note: Said to crash and return incorrect values. - /// - func testSwiftNumericsPull254() { - XCTAssertEqual(UInt64( SIntXL(UInt64.max)), UInt64(UInt64.max)) - XCTAssertEqual(SIntXL( UInt64(UInt64.max)), SIntXL(UInt64.max)) - - XCTAssertEqual(UInt64(exactly: SIntXL(UInt64.max)), UInt64(UInt64.max)) - XCTAssertEqual(SIntXL(exactly: UInt64(UInt64.max)), SIntXL(UInt64.max)) - - XCTAssertEqual(UInt64(clamping: SIntXL(UInt64.max)), UInt64(UInt64.max)) - XCTAssertEqual(SIntXL(clamping: UInt64(UInt64.max)), SIntXL(UInt64.max)) - } -} - -#endif diff --git a/Tests/NBKSignedKitTests/NBKSigned+Subtraction.swift b/Tests/NBKSignedKitTests/NBKSigned+Subtraction.swift deleted file mode 100644 index 8ce6c81a..00000000 --- a/Tests/NBKSignedKitTests/NBKSigned+Subtraction.swift +++ /dev/null @@ -1,155 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if DEBUG - -import NBKCoreKit -import NBKFlexibleWidthKit -import NBKSignedKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Signed x Subtraction x SIntXL -//*============================================================================* - -final class NBKSignedTestsOnSubtractionAsSIntXL: XCTestCase { - - typealias T = NBKSigned - typealias M = NBKSigned.Magnitude - typealias D = NBKSigned.Digit - typealias U = NBKSigned.Digit.Magnitude - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testSubtractingLargeFromLarge() { - NBKAssertSubtraction( T(M(x64:[~0, ~0, ~0, 0] as X)), T(M(x64:[3, 0, 0, 0] as X)), T(M(x64:[~3, ~0, ~0, 0] as X))) - NBKAssertSubtraction( T(M(x64:[~0, ~0, ~0, 0] as X)), T(M(x64:[0, 3, 0, 0] as X)), T(M(x64:[~0, ~3, ~0, 0] as X))) - NBKAssertSubtraction( T(M(x64:[~0, ~0, ~0, 0] as X)), T(M(x64:[0, 0, 3, 0] as X)), T(M(x64:[~0, ~0, ~3, 0] as X))) - NBKAssertSubtraction( T(M(x64:[~0, ~0, ~0, 0] as X)), T(M(x64:[0, 0, 0, 3] as X)), -T(M(x64:[ 1, 0, 0, 2] as X))) - - NBKAssertSubtraction( T(M(x64:[~0, ~0, ~0, 0] as X)), -T(M(x64:[3, 0, 0, 0] as X)), T(M(x64:[ 2, 0, 0, 1] as X))) - NBKAssertSubtraction( T(M(x64:[~0, ~0, ~0, 0] as X)), -T(M(x64:[0, 3, 0, 0] as X)), T(M(x64:[~0, 2, 0, 1] as X))) - NBKAssertSubtraction( T(M(x64:[~0, ~0, ~0, 0] as X)), -T(M(x64:[0, 0, 3, 0] as X)), T(M(x64:[~0, ~0, 2, 1] as X))) - NBKAssertSubtraction( T(M(x64:[~0, ~0, ~0, 0] as X)), -T(M(x64:[0, 0, 0, 3] as X)), T(M(x64:[~0, ~0, ~0, 3] as X))) - - NBKAssertSubtraction(-T(M(x64:[~0, ~0, ~0, 0] as X)), T(M(x64:[3, 0, 0, 0] as X)), -T(M(x64:[ 2, 0, 0, 1] as X))) - NBKAssertSubtraction(-T(M(x64:[~0, ~0, ~0, 0] as X)), T(M(x64:[0, 3, 0, 0] as X)), -T(M(x64:[~0, 2, 0, 1] as X))) - NBKAssertSubtraction(-T(M(x64:[~0, ~0, ~0, 0] as X)), T(M(x64:[0, 0, 3, 0] as X)), -T(M(x64:[~0, ~0, 2, 1] as X))) - NBKAssertSubtraction(-T(M(x64:[~0, ~0, ~0, 0] as X)), T(M(x64:[0, 0, 0, 3] as X)), -T(M(x64:[~0, ~0, ~0, 3] as X))) - - NBKAssertSubtraction(-T(M(x64:[~0, ~0, ~0, 0] as X)), -T(M(x64:[3, 0, 0, 0] as X)), -T(M(x64:[~3, ~0, ~0, 0] as X))) - NBKAssertSubtraction(-T(M(x64:[~0, ~0, ~0, 0] as X)), -T(M(x64:[0, 3, 0, 0] as X)), -T(M(x64:[~0, ~3, ~0, 0] as X))) - NBKAssertSubtraction(-T(M(x64:[~0, ~0, ~0, 0] as X)), -T(M(x64:[0, 0, 3, 0] as X)), -T(M(x64:[~0, ~0, ~3, 0] as X))) - NBKAssertSubtraction(-T(M(x64:[~0, ~0, ~0, 0] as X)), -T(M(x64:[0, 0, 0, 3] as X)), T(M(x64:[ 1, 0, 0, 2] as X))) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Digit (and Self) - //=------------------------------------------------------------------------= - - func testSubtractingSmallFromSmall() { - NBKAssertSubtractionByDigit( T(M(1)), D(U(2)), -T(M(1))) - NBKAssertSubtractionByDigit( T(M(1)), D(U(1)), T(M(0))) - NBKAssertSubtractionByDigit( T(M(1)), D(U(0)), T(M(1))) - NBKAssertSubtractionByDigit( T(M(1)), -D(U(0)), T(M(1))) - NBKAssertSubtractionByDigit( T(M(1)), -D(U(1)), T(M(2))) - NBKAssertSubtractionByDigit( T(M(1)), -D(U(2)), T(M(3))) - - NBKAssertSubtractionByDigit( T(M(0)), D(U(2)), -T(M(2))) - NBKAssertSubtractionByDigit( T(M(0)), D(U(1)), -T(M(1))) - NBKAssertSubtractionByDigit( T(M(0)), D(U(0)), T(M(0))) - NBKAssertSubtractionByDigit( T(M(0)), -D(U(0)), T(M(0))) - NBKAssertSubtractionByDigit( T(M(0)), -D(U(1)), T(M(1))) - NBKAssertSubtractionByDigit( T(M(0)), -D(U(2)), T(M(2))) - - NBKAssertSubtractionByDigit(-T(M(0)), D(U(2)), -T(M(2))) - NBKAssertSubtractionByDigit(-T(M(0)), D(U(1)), -T(M(1))) - NBKAssertSubtractionByDigit(-T(M(0)), D(U(0)), -T(M(0))) - NBKAssertSubtractionByDigit(-T(M(0)), -D(U(0)), -T(M(0))) - NBKAssertSubtractionByDigit(-T(M(0)), -D(U(1)), T(M(1))) - NBKAssertSubtractionByDigit(-T(M(0)), -D(U(2)), T(M(2))) - - NBKAssertSubtractionByDigit(-T(M(1)), D(U(2)), -T(M(3))) - NBKAssertSubtractionByDigit(-T(M(1)), D(U(1)), -T(M(2))) - NBKAssertSubtractionByDigit(-T(M(1)), D(U(0)), -T(M(1))) - NBKAssertSubtractionByDigit(-T(M(1)), -D(U(0)), -T(M(1))) - NBKAssertSubtractionByDigit(-T(M(1)), -D(U(1)), -T(M(0))) - NBKAssertSubtractionByDigit(-T(M(1)), -D(U(2)), T(M(1))) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Miscellaneous - //=------------------------------------------------------------------------= - - func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { - func becauseThisCompilesSuccessfully(_ x: inout T) { - XCTAssertNotNil(x -= 0) - XCTAssertNotNil(x - 0) - } - } -} - -//*============================================================================* -// MARK: * NBK x Signed x Subtraction x Open Source Issues -//*============================================================================* - -final class NBKSignedTestsOnSubtractionOpenSourceIssues: XCTestCase { - - typealias SIntXL = NBKSigned - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - /// https://github.com/apple/swift-numerics/pull/246 - /// - /// - Note: Said to return incorrect values. - /// - func testSwiftNumericsPull246() { - NBKAssertSubtraction( - SIntXL("-0922337203685477587"), - SIntXL("-9223372036854775808"), - SIntXL("08301034833169298221")) - - NBKAssertSubtraction( - SIntXL(Int.max), - SIntXL(sign: .minus, magnitude: UIntXL(UInt.max - UInt(Int.max.magnitude))), - SIntXL(sign: .plus, magnitude: UIntXL(UInt.max))) - } -} - -//*============================================================================* -// MARK: * NBK x Signed x Subtraction x Assertions -//*============================================================================* - -private func NBKAssertSubtraction( -_ lhs: NBKSigned, _ rhs: NBKSigned, _ partialValue: NBKSigned, -file: StaticString = #file, line: UInt = #line) { - //=------------------------------------------= - NBKAssertIdentical( lhs - rhs, partialValue, file: file, line: line) - NBKAssertIdentical({ var lhs = lhs; lhs -= rhs; return lhs }(), partialValue, file: file, line: line) -} - -private func NBKAssertSubtractionByDigit( -_ lhs: NBKSigned, _ rhs: NBKSigned.Digit, _ partialValue: NBKSigned, -file: StaticString = #file, line: UInt = #line) { - //=------------------------------------------= - NBKAssertSubtraction(lhs, NBKSigned(digit: rhs), partialValue) - //=------------------------------------------= - NBKAssertIdentical( lhs - rhs, partialValue, file: file, line: line) - NBKAssertIdentical({ var lhs = lhs; lhs -= rhs; return lhs }(), partialValue, file: file, line: line) -} - -#endif diff --git a/Tests/NBKSignedKitTests/NBKSigned+Text.swift b/Tests/NBKSignedKitTests/NBKSigned+Text.swift deleted file mode 100644 index d07f7d2d..00000000 --- a/Tests/NBKSignedKitTests/NBKSigned+Text.swift +++ /dev/null @@ -1,281 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if DEBUG - -import NBKSignedKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Signed x Text -//*============================================================================* - -final class NBKSignedTestsOnText: XCTestCase { - - typealias T = NBKSigned - typealias M = UInt64 - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testFromDescription() { - NBKAssertFromDescription(T?( 10), "10") - NBKAssertFromDescription(T?( 10), "+10") - NBKAssertFromDescription(T?(-10), "-10") - NBKAssertFromDescription(T?(nil), " 10") - NBKAssertFromDescription(T?(nil), "0x10") - NBKAssertFromDescription(T?(nil), "+0x10") - NBKAssertFromDescription(T?(nil), "-0x10") - NBKAssertFromDescription(T?(nil), " 0x10") - } - - func testInstanceDescriptionUsesRadix10() { - XCTAssertEqual("10", T(10).description) - XCTAssertEqual("10", String(describing: T(10))) - } - - func testMetaTypeDescriptionCouldUseSomeLove() { - XCTAssertEqual("NBKSigned", NBKSigned .description) - XCTAssertEqual("NBKSigned", NBKSigned.description) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Decode - //=------------------------------------------------------------------------= - - func testDecodingRadix02() { - NBKAssertDecodeText(T.min, 02, "-" + String(repeating: "1", count: M.bitWidth / 1)) - NBKAssertDecodeText(T.max, 02, String(repeating: "1", count: M.bitWidth / 1)) - } - - func testDecodingRadix03() { - NBKAssertDecodeText(T.min, 03, "-11112220022122120101211020120210210211220") - NBKAssertDecodeText(T.max, 03, "11112220022122120101211020120210210211220") - } - - func testDecodingRadix04() { - NBKAssertDecodeText(T.min, 04, "-" + String(repeating: "3", count: M.bitWidth / 2)) - NBKAssertDecodeText(T.max, 04, String(repeating: "3", count: M.bitWidth / 2)) - } - - func testDecodingRadix08() { - NBKAssertDecodeText(T.min, 08, "-1" + String(repeating: "7", count: 21)) - NBKAssertDecodeText(T.max, 08, "1" + String(repeating: "7", count: 21)) - } - - func testDecodingRadix10() { - NBKAssertDecodeText(T.min, 10, "-18446744073709551615") - NBKAssertDecodeText(T.max, 10, "18446744073709551615") - } - - func testDecodingRadix16() { - NBKAssertDecodeText(T.min, 16, "-" + String(repeating: "f", count: M.bitWidth / 4)) - NBKAssertDecodeText(T.max, 16, String(repeating: "f", count: M.bitWidth / 4)) - } - - func testDecodingRadix32() { - NBKAssertDecodeText(T.min, 32, "-f" + String(repeating: "v", count: 12)) - NBKAssertDecodeText(T.max, 32, "f" + String(repeating: "v", count: 12)) - } - - func testDecodingRadix36() { - NBKAssertDecodeText(T.min, 36, "-3w5e11264sgsf") - NBKAssertDecodeText(T.max, 36, "3w5e11264sgsf") - } - - func testDecodingRadixLiteralAsNumber() { - NBKAssertDecodeText(T( 33), 36, "0x") - NBKAssertDecodeText(T( 24), 36, "0o") - NBKAssertDecodeText(T( 11), 36, "0b") - - NBKAssertDecodeText(T( 33), 36, "+0x") - NBKAssertDecodeText(T( 24), 36, "+0o") - NBKAssertDecodeText(T( 11), 36, "+0b") - - NBKAssertDecodeText(T(-33), 36, "-0x") - NBKAssertDecodeText(T(-24), 36, "-0o") - NBKAssertDecodeText(T(-11), 36, "-0b") - } - - func testDecodingRadixLiteralAsRadixReturnsNil() { - NBKAssertDecodeText(T?.none, 10, "0x10") - NBKAssertDecodeText(T?.none, 10, "0o10") - NBKAssertDecodeText(T?.none, 10, "0b10") - - NBKAssertDecodeText(T?.none, 10, "+0x10") - NBKAssertDecodeText(T?.none, 10, "+0o10") - NBKAssertDecodeText(T?.none, 10, "+0b10") - - NBKAssertDecodeText(T?.none, 10, "-0x10") - NBKAssertDecodeText(T?.none, 10, "-0o10") - NBKAssertDecodeText(T?.none, 10, "-0b10") - } - - func testDecodingStringsWithAndWithoutSign() { - NBKAssertDecodeText(T( 1234567890), 10, "1234567890") - NBKAssertDecodeText(T( 1234567890), 10, "+1234567890") - NBKAssertDecodeText(T(-1234567890), 10, "-1234567890") - } - - func testDecodingStrategyIsCaseInsensitive() { - NBKAssertDecodeText(T(0xabcdef), 16, "abcdef") - NBKAssertDecodeText(T(0xABCDEF), 16, "ABCDEF") - NBKAssertDecodeText(T(0xaBcDeF), 16, "aBcDeF") - NBKAssertDecodeText(T(0xAbCdEf), 16, "AbCdEf") - } - - func testDecodingUnalignedStringsIsOK() { - NBKAssertDecodeText(T(1), 10, "1") - NBKAssertDecodeText(T(1), 16, "1") - } - - func testDecodingPrefixingZerosHasNoEffect() { - let zero = String(repeating: "0", count: M.bitWidth) + "0" - let one = String(repeating: "0", count: M.bitWidth) + "1" - - for radix in 02 ... 36 { - NBKAssertDecodeText(T(0), radix, zero) - NBKAssertDecodeText(T(1), radix, one ) - } - } - - func testDecodingInvalidCharactersReturnsNil() { - NBKAssertDecodeText(T?.none, 16, "/") - NBKAssertDecodeText(T?.none, 16, "G") - - NBKAssertDecodeText(T?.none, 10, "/") - NBKAssertDecodeText(T?.none, 10, ":") - - NBKAssertDecodeText(T?.none, 10, String(repeating: "1", count: 19) + "/") - NBKAssertDecodeText(T?.none, 10, String(repeating: "1", count: 19) + ":") - } - - func testDecodingStringsWithoutDigitsReturnsNil() { - NBKAssertDecodeText(T?.none, 10, "") - NBKAssertDecodeText(T?.none, 10, "+") - NBKAssertDecodeText(T?.none, 10, "-") - NBKAssertDecodeText(T?.none, 10, "~") - - NBKAssertDecodeText(T?.none, 16, "") - NBKAssertDecodeText(T?.none, 16, "+") - NBKAssertDecodeText(T?.none, 16, "-") - NBKAssertDecodeText(T?.none, 16, "~") - } - - func testDecodingValuesOutsideOfRepresentableRangeReturnsNil() { - let positive = "+" + String(repeating: "1", count: M.bitWidth + 1) - let negative = "-" + String(repeating: "1", count: M.bitWidth + 1) - - for radix in 02 ... 36 { - NBKAssertDecodeText(T?.none, radix, positive) - NBKAssertDecodeText(T?.none, radix, negative) - } - - NBKAssertDecodeText(T?.none, 36, "-3w5e11264sgsg" ) // - 01 - NBKAssertDecodeText(T?.none, 36, "-3w5e11264sgsf0") // * 36 - NBKAssertDecodeText(T?.none, 36, "3w5e11264sgsg" ) // + 01 - NBKAssertDecodeText(T?.none, 36, "3w5e11264sgsf0") // * 36 - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Encode - //=------------------------------------------------------------------------= - - func testEncodingRadix02() { - NBKAssertEncodeText(T.min, 02, false, "-" + String(repeating: "1", count: M.bitWidth / 1)) - NBKAssertEncodeText(T.max, 02, false, String(repeating: "1", count: M.bitWidth / 1)) - } - - func testEncodingRadix03() { - NBKAssertEncodeText(T.min, 03, false, "-11112220022122120101211020120210210211220") - NBKAssertEncodeText(T.max, 03, false, "11112220022122120101211020120210210211220") - } - - func testEncodingRadix04() { - NBKAssertEncodeText(T.min, 04, false, "-" + String(repeating: "3", count: M.bitWidth / 2)) - NBKAssertEncodeText(T.max, 04, false, String(repeating: "3", count: M.bitWidth / 2)) - } - - func testEncodingRadix08() { - NBKAssertEncodeText(T.min, 08, false, "-1" + String(repeating: "7", count: 21)) - NBKAssertEncodeText(T.max, 08, false, "1" + String(repeating: "7", count: 21)) - } - - func testEncodingRadix10() { - NBKAssertEncodeText(T.min, 10, false, "-18446744073709551615") - NBKAssertEncodeText(T.max, 10, false, "18446744073709551615") - } - - func testEncodingRadix16() { - NBKAssertEncodeText(T.min, 16, false, "-" + String(repeating: "f", count: M.bitWidth / 4)) - NBKAssertEncodeText(T.min, 16, true , "-" + String(repeating: "F", count: M.bitWidth / 4)) - NBKAssertEncodeText(T.max, 16, false, String(repeating: "f", count: M.bitWidth / 4)) - NBKAssertEncodeText(T.max, 16, true , String(repeating: "F", count: M.bitWidth / 4)) - } - - func testEncodingRadix32() { - NBKAssertEncodeText(T.min, 32, false, "-f" + String(repeating: "v", count: 12)) - NBKAssertEncodeText(T.min, 32, true , "-F" + String(repeating: "V", count: 12)) - NBKAssertEncodeText(T.max, 32, false, "f" + String(repeating: "v", count: 12)) - NBKAssertEncodeText(T.max, 32, true , "F" + String(repeating: "V", count: 12)) - } - - func testEncodingRadix36() { - NBKAssertEncodeText(T.min, 36, false, "-3w5e11264sgsf") - NBKAssertEncodeText(T.min, 36, true , "-3W5E11264SGSF") - NBKAssertEncodeText(T.max, 36, false, "3w5e11264sgsf") - NBKAssertEncodeText(T.max, 36, true , "3W5E11264SGSF") - } -} - -//*============================================================================* -// MARK: * NBK x Flexible Width x Text x Assertions -//*============================================================================* - -private func NBKAssertFromDescription( -_ integer: NBKSigned?, _ description: String, -file: StaticString = #file, line: UInt = #line) { - typealias T = NBKSigned - //=------------------------------------------= - NBKAssertIdentical(T.init(description), integer, file: file, line: line) - NBKAssertIdentical(T.init(description, radix: 10), integer, file: file, line: line) -} - -private func NBKAssertDecodeText( -_ integer: NBKSigned?, _ radix: Int, _ text: String, -file: StaticString = #file, line: UInt = #line) { - typealias T = NBKSigned - //=------------------------------------------= - if radix == 10 { - NBKAssertIdentical(T.init(text), integer, file: file, line: line) - } - //=------------------------------------------= - NBKAssertIdentical(T.init(text, radix: radix), integer, file: file, line: line) -} - -private func NBKAssertEncodeText( -_ integer: NBKSigned, _ radix: Int, _ uppercase: Bool, _ text: String, -file: StaticString = #file, line: UInt = #line) { - typealias T = NBKSigned - //=------------------------------------------= - if radix == 10 { - XCTAssertEqual(String.init(integer), text, file: file, line: line) - XCTAssertEqual(integer.description, text, file: file, line: line) - } - //=------------------------------------------= - XCTAssertEqual(String.init(integer,radix: radix, uppercase: uppercase), text, file: file, line: line) - XCTAssertEqual(integer.description(radix: radix, uppercase: uppercase), text, file: file, line: line) -} - -#endif diff --git a/Tests/NBKSignedKitTests/NBKSigned+Words.swift b/Tests/NBKSignedKitTests/NBKSigned+Words.swift deleted file mode 100644 index 6439b626..00000000 --- a/Tests/NBKSignedKitTests/NBKSigned+Words.swift +++ /dev/null @@ -1,149 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if DEBUG - -import NBKCoreKit -import NBKSignedKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Signed x Words -//*============================================================================* - -final class NBKSignedTestsOnWords: XCTestCase { - - typealias T = NBKSigned - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testFromWords() { - NBKAssertFromWordsIsSigned([ ] as W, true, T(sign: .plus, magnitude: 0)) - NBKAssertFromWordsIsSigned([ ] as W, false, T(sign: .plus, magnitude: 0)) - NBKAssertFromWordsIsSigned([ 0 ] as W, true, T(sign: .plus, magnitude: 0)) - NBKAssertFromWordsIsSigned([ 0 ] as W, false, T(sign: .plus, magnitude: 0)) - NBKAssertFromWordsIsSigned([~0 ] as W, true, T(sign: .minus, magnitude: 1)) - NBKAssertFromWordsIsSigned([~0 ] as W, false, T(sign: .plus, magnitude: ~0)) - NBKAssertFromWordsIsSigned([~0, 0] as W, true, T(sign: .plus, magnitude: ~0)) - NBKAssertFromWordsIsSigned([~0, 0] as W, false, T(sign: .plus, magnitude: ~0)) - NBKAssertFromWordsIsSigned([ 1, ~0] as W, true, T(sign: .minus, magnitude: ~0)) - NBKAssertFromWordsIsSigned([ 1, ~0] as W, false, nil as T?) - - NBKAssertFromWordsIsSigned(W(repeating: 0, count: 2), true, 000 as T?) - NBKAssertFromWordsIsSigned(W(repeating: 1, count: 2), true, nil as T?) - NBKAssertFromWordsIsSigned(W(repeating: ~0, count: 2), true, -01 as T?) - NBKAssertFromWordsIsSigned(W(repeating: ~1, count: 2), true, nil as T?) - - NBKAssertFromWordsIsSigned(W(repeating: 0, count: 2), false, 000 as T?) - NBKAssertFromWordsIsSigned(W(repeating: 1, count: 2), false, nil as T?) - NBKAssertFromWordsIsSigned(W(repeating: ~0, count: 2), false, nil as T?) - NBKAssertFromWordsIsSigned(W(repeating: ~1, count: 2), false, nil as T?) - } - - func testToWords() { - NBKAssertToWords(T(sign: .plus, magnitude: ~0/1 - 0), [~0/1 - 0, 0] as W) - NBKAssertToWords(T(sign: .plus, magnitude: ~0/1 - 1), [~0/1 - 1, 0] as W) - NBKAssertToWords(T(sign: .minus, magnitude: ~0/1 - 0), [ 0/1 + 1, ~0] as W) - NBKAssertToWords(T(sign: .minus, magnitude: ~0/1 - 1), [ 0/1 + 2, ~0] as W) - - NBKAssertToWords(T(sign: .plus, magnitude: ~0/2 + 2), [~0/2 + 2, 0] as W) - NBKAssertToWords(T(sign: .plus, magnitude: ~0/2 + 1), [~0/2 + 1, 0] as W) - NBKAssertToWords(T(sign: .plus, magnitude: ~0/2 + 0), [~0/2 + 0, ] as W) - - NBKAssertToWords(T(sign: .minus, magnitude: ~0/2 + 2), [~0/2 + 0, ~0] as W) - NBKAssertToWords(T(sign: .minus, magnitude: ~0/2 + 1), [~0/2 + 1, ] as W) - NBKAssertToWords(T(sign: .minus, magnitude: ~0/2 + 0), [~0/2 + 2, ] as W) - - NBKAssertToWords(T(sign: .plus, magnitude: 0/1 + 0), [ 0/1 + 0, ] as W) - NBKAssertToWords(T(sign: .plus, magnitude: 0/1 + 1), [ 0/1 + 1, ] as W) - NBKAssertToWords(T(sign: .minus, magnitude: 0/1 + 0), [ 0/1 + 0, ] as W) - NBKAssertToWords(T(sign: .minus, magnitude: 0/1 + 1), [~0/1 + 0, ] as W) - } -} - -//*============================================================================* -// MARK: * NBK x Signed x Words x Assertions -//*============================================================================* - -private func NBKAssertFromWords( -_ words: [UInt], _ integer: NBKSigned?, -file: StaticString = #file, line: UInt = #line) { - //=------------------------------------------= - typealias T = NBKSigned - //=------------------------------------------= - NBKAssertIdentical( T(words: words), integer, file: file, line: line) - NBKAssertIdentical(integer.flatMap({ T(words: $0.words) }), integer, file: file, line: line) -} - -private func NBKAssertFromWordsIsSigned( -_ words: [UInt], _ isSigned: Bool, _ integer: NBKSigned?, -file: StaticString = #file, line: UInt = #line) { - //=------------------------------------------= - typealias T = NBKSigned - //=------------------------------------------= - if isSigned == T.isSigned { - NBKAssertFromWords(words, integer, file: file, line: line) - } - - NBKAssertIdentical( T(words: words, isSigned: isSigned), integer, file: file, line: line) - NBKAssertIdentical(integer.flatMap({ T(words: $0.words, isSigned: isSigned) }), integer, file: file, line: line) -} - -private func NBKAssertToWords( -_ integer: NBKSigned, _ words: [UInt], -file: StaticString = #file, line: UInt = #line) { - //=------------------------------------------= - NBKAssertElementsEqual(integer.words, words, file: file, line: line) - NBKAssertFromWords(words, integer.normalized(), file: file, line: line) -} - -//=----------------------------------------------------------------------------= -// MARK: + Collection -//=----------------------------------------------------------------------------= - -private func NBKAssertElementsEqual( -_ base: Base, _ expectation: [Base.Element], -file: StaticString = #file, line: UInt = #line) where Base.Element: Equatable { - //=------------------------------------------= - XCTAssertEqual(Array(base), expectation, file: file, line: line) - XCTAssertEqual(Array(base.indices.map({ base[$0] })), expectation, file: file, line: line) - //=------------------------------------------= - for distance in 0 ..< base.count { - //=--------------------------------------= - let index0 = base.index(base.startIndex, offsetBy: distance + 0) - let index1 = base.index(base.startIndex, offsetBy: distance + 1) - //=--------------------------------------= - XCTAssertEqual(base[index0],expectation[distance], file: file, line: line) - //=--------------------------------------= - XCTAssertEqual(base.index(before: index1), index0, file: file, line: line) - XCTAssertEqual(base.index(after: index0), index1, file: file, line: line) - - XCTAssertEqual(base.index(base.endIndex, offsetBy: distance + 0 - base.count), index0, file: file, line: line) - XCTAssertEqual(base.index(base.endIndex, offsetBy: distance + 1 - base.count), index1, file: file, line: line) - //=--------------------------------------= - XCTAssertEqual(base.distance(from: base.startIndex, to: index0), distance + 0, file: file, line: line) - XCTAssertEqual(base.distance(from: base.startIndex, to: index1), distance + 1, file: file, line: line) - - XCTAssertEqual(base.distance(from: index0, to: base.endIndex), base.count - distance - 0, file: file, line: line) - XCTAssertEqual(base.distance(from: index1, to: base.endIndex), base.count - distance - 1, file: file, line: line) - } - //=------------------------------------------= - for distance in 0 ... base.count + 1 { - XCTAssert(base.prefix(distance).elementsEqual(expectation.prefix(distance)), file: file, line: line) - XCTAssert(base.suffix(distance).elementsEqual(expectation.suffix(distance)), file: file, line: line) - } -} - -#endif diff --git a/Tests/NBKSignedKitTests/NBKSigned.swift b/Tests/NBKSignedKitTests/NBKSigned.swift deleted file mode 100644 index db887b23..00000000 --- a/Tests/NBKSignedKitTests/NBKSigned.swift +++ /dev/null @@ -1,122 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if DEBUG - -import NBKCoreKit -import NBKSignedKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Signed -//*============================================================================* - -final class NBKSignedTests: XCTestCase { - - typealias T = NBKSigned - typealias M = NBKSigned.Magnitude - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testSign() { - XCTAssertEqual(T(sign: .plus , magnitude: 0).sign, .plus ) - XCTAssertEqual(T(sign: .plus , magnitude: 1).sign, .plus ) - XCTAssertEqual(T(sign: .minus, magnitude: 0).sign, .minus) - XCTAssertEqual(T(sign: .minus, magnitude: 1).sign, .minus) - } - - func testMagnitude() { - XCTAssertEqual(T(sign: .plus , magnitude: 0).magnitude, 0 as M) - XCTAssertEqual(T(sign: .plus , magnitude: 1).magnitude, 1 as M) - XCTAssertEqual(T(sign: .minus, magnitude: 0).magnitude, 0 as M) - XCTAssertEqual(T(sign: .minus, magnitude: 1).magnitude, 1 as M) - } - - func testComponents() { - NBKAssertComponentsGetSetInit(T(sign: .plus , magnitude: 0), .plus, 0 as M) - NBKAssertComponentsGetSetInit(T(sign: .plus , magnitude: 1), .plus, 1 as M) - NBKAssertComponentsGetSetInit(T(sign: .minus, magnitude: 0), .minus, 0 as M) - NBKAssertComponentsGetSetInit(T(sign: .minus, magnitude: 1), .minus, 1 as M) - } - - func testNormalization() { - NBKAssertNormalization(T(sign: .plus , magnitude: 0), true, .plus, 0 as M) - NBKAssertNormalization(T(sign: .plus , magnitude: 1), true, .plus, 1 as M) - NBKAssertNormalization(T(sign: .minus, magnitude: 0), false, .plus, 0 as M) - NBKAssertNormalization(T(sign: .minus, magnitude: 1), true, .minus, 1 as M) - } -} - -//*============================================================================* -// MARK: * NBK x Signed x Assertions -//*============================================================================* - -private func NBKAssertComponentsGetSetInit( -_ value: NBKSigned, _ sign: NBKSigned.Sign, _ magnitude: M, -file: StaticString = #file, line: UInt = #line) { - //=------------------------------------------= - typealias T = NBKSigned - //=------------------------------------------= - XCTAssertEqual(value.sign, sign, file: file, line: line) - XCTAssertEqual(value.magnitude, magnitude, file: file, line: line) - - XCTAssertEqual(value.components.sign, sign, file: file, line: line) - XCTAssertEqual(value.components.magnitude, magnitude, file: file, line: line) - - NBKAssertIdentical(value, T(sign: sign, magnitude: magnitude), file: file, line: line) - NBKAssertIdentical(value, T(components: SM(sign: sign, magnitude: magnitude)), file: file, line: line) - - NBKAssertIdentical(value, { var x = T(); x.sign = sign; x.magnitude = magnitude; return x }(), file: file, line: line) - NBKAssertIdentical(value, { var x = T(); x.components = SM(sign: sign, magnitude: magnitude); return x }(), file: file, line: line) -} - -private func NBKAssertNormalization( -_ integer: NBKSigned, _ isNormal: Bool, _ sign: NBKSigned.Sign, _ magnitude: M, -file: StaticString = #file, line: UInt = #line) { - - brr: do { - XCTAssertEqual(integer.isNormal, isNormal, file: file, line: line) - XCTAssertEqual(integer.normalizedSign, sign, file: file, line: line) - XCTAssertEqual(integer.magnitude, magnitude, file: file, line: line) - } - - brr: do { - XCTAssertEqual(integer.normalized().isNormal, true, file: file, line: line) - XCTAssertEqual(integer.normalized().sign, sign, file: file, line: line) - XCTAssertEqual(integer.normalized().magnitude, magnitude, file: file, line: line) - } - - brr: do { - var integer = integer; integer.normalize() - XCTAssertEqual(integer.isNormal, true, file: file, line: line) - XCTAssertEqual(integer.sign, sign, file: file, line: line) - XCTAssertEqual(integer.magnitude, magnitude, file: file, line: line) - } -} - -//=----------------------------------------------------------------------------= -// MARK: + Shared -//=----------------------------------------------------------------------------= - -func NBKAssertIdentical(_ lhs: NBKSigned?, _ rhs: NBKSigned?, file: StaticString = #file, line: UInt = #line) { - func description(of integer: NBKSigned?) -> String { - integer.map({ "\($0.sign)\($0.magnitude)" }) ?? "nil" - } - - let success: Bool = lhs?.sign == rhs?.sign && lhs?.magnitude == rhs?.magnitude - XCTAssert(success, "(\(description(of: lhs)) is not identical to \(description(of: rhs))", file: file, line: line) -} - -#endif From ed2e165aca9377fbf64c77a404ada1eb0a9456c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Mon, 23 Oct 2023 18:14:42 +0200 Subject: [PATCH 104/133] [NBKFlexibleWidthKit] In-place update methods. --- .../NBKFlexibleWidthKit/IntXLOrUIntXL.swift | 20 +++++- .../NBKFlexibleWidth+Storage.swift | 4 -- .../NBKFlexibleWidth+Update.swift | 6 +- .../NBKFlexibleWidth+Update.swift | 62 +++++++++++++++++++ 4 files changed, 86 insertions(+), 6 deletions(-) create mode 100644 Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Update.swift diff --git a/Sources/NBKFlexibleWidthKit/IntXLOrUIntXL.swift b/Sources/NBKFlexibleWidthKit/IntXLOrUIntXL.swift index 4d94cecd..f983c1e8 100644 --- a/Sources/NBKFlexibleWidthKit/IntXLOrUIntXL.swift +++ b/Sources/NBKFlexibleWidthKit/IntXLOrUIntXL.swift @@ -25,6 +25,18 @@ public protocol IntXLOrUIntXL: NBKBinaryInteger, ExpressibleByStringLiteral wher /// An instance that is equal to `1`. @inlinable static var one: Self { get } + //=------------------------------------------------------------------------= + // MARK: Details x Words + //=------------------------------------------------------------------------= + + /// Creates a new instance from the given collection of `words`. + /// + /// The `words` are interpreted as a binary integer with the same signedness. + /// + /// - Note: This method returns zero when `words` is empty. + /// + @inlinable init(words: some RandomAccessCollection) + //=------------------------------------------------------------------------= // MARK: Details x Comparisons //=------------------------------------------------------------------------= @@ -111,7 +123,13 @@ public protocol IntXLOrUIntXL: NBKBinaryInteger, ExpressibleByStringLiteral wher /// Updates this instance in-place so it equals `value`. /// - /// - Note: This operation is much more efficent than allocating new storage. + /// - Note: This operation may be more efficient than allocating new storage. + /// + @inlinable mutating func update(_ value: Self) + + /// Updates this instance in-place so it equals `value`. + /// + /// - Note: This operation may be more efficient than allocating new storage. /// @inlinable mutating func update(_ value: Digit) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Storage.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Storage.swift index 194e5093..98b435f6 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Storage.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Storage.swift @@ -65,8 +65,4 @@ extension NBKFlexibleWidth.Magnitude.Storage { self.elements.removeLast() } } - - @inlinable mutating func normalize(update value: UInt) { - self.elements.replaceSubrange(self.elements.indices, with: CollectionOfOne(value)) - } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Update.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Update.swift index 94cff348..a08baded 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Update.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Update.swift @@ -19,7 +19,11 @@ extension NBKFlexibleWidth.Magnitude { // MARK: Transformations //=------------------------------------------------------------------------= + @inlinable public mutating func update(_ value: Self) { + self.storage.elements.replaceSubrange(self.storage.elements.indices, with: value.storage.elements) + } + @inlinable public mutating func update(_ value: Digit) { - self.storage.normalize(update: value) + self.storage.elements.replaceSubrange(self.storage.elements.indices, with: CollectionOfOne(value)) } } diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Update.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Update.swift new file mode 100644 index 00000000..9df45c2c --- /dev/null +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Update.swift @@ -0,0 +1,62 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +import NBKFlexibleWidthKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Flexible Width x Update x UIntXL +//*============================================================================* + +final class NBKFlexibleWidthTestsOnUpdateAsUIntXL: XCTestCase { + + typealias T = UIntXL + typealias M = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testUpdate() { + NBKAssertUpdate(T(words:[ 0, 0, 0, 0 ] as W)) + NBKAssertUpdate(T(words:[~0, ~0, ~0, ~0/2 + 0] as W)) + NBKAssertUpdate(T(words:[ 0, 0, 0, ~0/2 + 1] as W)) + NBKAssertUpdate(T(words:[~0, ~0, ~0, ~0 ] as W)) + } + + func testUpdateAsDigit() { + NBKAssertUpdateAsDigit(T.self, UInt.min) + NBKAssertUpdateAsDigit(T.self, UInt.max/2 + 0) + NBKAssertUpdateAsDigit(T.self, UInt.max/2 + 1) + NBKAssertUpdateAsDigit(T.self, UInt.max) + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Update x Assertions +//*============================================================================* + +private func NBKAssertUpdate(_ value: T, file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual({ var x = T(words:[0, 0, 0, 0] as W); x.update(value); return x }(), value, file: file, line: line) + XCTAssertEqual({ var x = T(words:[1, 2, 3, 4] as W); x.update(value); return x }(), value, file: file, line: line) +} + +private func NBKAssertUpdateAsDigit(_ type: T.Type, _ value: T.Digit, file: StaticString = #file, line: UInt = #line) { + NBKAssertUpdate(T(digit: value), file: file, line: line) + XCTAssertEqual({ var x = T(words:[0, 0, 0, 0] as W); x.update(value); return x }(), T(digit: value), file: file, line: line) + XCTAssertEqual({ var x = T(words:[1, 2, 3, 4] as W); x.update(value); return x }(), T(digit: value), file: file, line: line)} + +#endif From 0629aca17731a81a41406c978a1867663bc03bd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Tue, 24 Oct 2023 14:45:08 +0200 Subject: [PATCH 105/133] [NBKFlexibleWidthKit] Exponentiation. --- .../NBKFlexibleWidthKit-Benchmarks.xctestplan | 1 + .swiftpm/Numberick-Benchmarks.xctestplan | 3 + .../NBKFlexibleWidthKit/IntXLOrUIntXL.swift | 12 +- .../NBKFlexibleWidth+Exponentiation.swift | 51 +++ .../NBKFlexibleWidth+Exponentiation.swift | 77 +++++ .../NBKFlexibleWidth+Exponentiation.swift | 307 ++++++++++++++++++ 6 files changed, 450 insertions(+), 1 deletion(-) create mode 100644 Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Exponentiation.swift create mode 100644 Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Exponentiation.swift create mode 100644 Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Exponentiation.swift diff --git a/.swiftpm/NBKFlexibleWidthKit-Benchmarks.xctestplan b/.swiftpm/NBKFlexibleWidthKit-Benchmarks.xctestplan index 1501455e..e2741ab4 100644 --- a/.swiftpm/NBKFlexibleWidthKit-Benchmarks.xctestplan +++ b/.swiftpm/NBKFlexibleWidthKit-Benchmarks.xctestplan @@ -14,6 +14,7 @@ "testTargets" : [ { "skippedTests" : [ + "NBKFlexibleWidthBenchmarksOnExponentiationAsUIntXL\/test7RaisedToPrime777()", "NBKFlexibleWidthBenchmarksOnTextAsUIntXL\/testEncodingUsingSwiftStdlibRadix10()", "NBKFlexibleWidthBenchmarksOnTextAsUIntXL\/testEncodingUsingSwiftStdlibRadix16()" ], diff --git a/.swiftpm/Numberick-Benchmarks.xctestplan b/.swiftpm/Numberick-Benchmarks.xctestplan index b7a219a1..d26698ab 100644 --- a/.swiftpm/Numberick-Benchmarks.xctestplan +++ b/.swiftpm/Numberick-Benchmarks.xctestplan @@ -37,6 +37,9 @@ } }, { + "skippedTests" : [ + "NBKFlexibleWidthBenchmarksOnExponentiationAsUIntXL\/test7RaisedToPrime777()" + ], "target" : { "containerPath" : "container:", "identifier" : "NBKFlexibleWidthKitBenchmarks", diff --git a/Sources/NBKFlexibleWidthKit/IntXLOrUIntXL.swift b/Sources/NBKFlexibleWidthKit/IntXLOrUIntXL.swift index f983c1e8..f63998c7 100644 --- a/Sources/NBKFlexibleWidthKit/IntXLOrUIntXL.swift +++ b/Sources/NBKFlexibleWidthKit/IntXLOrUIntXL.swift @@ -33,7 +33,7 @@ public protocol IntXLOrUIntXL: NBKBinaryInteger, ExpressibleByStringLiteral wher /// /// The `words` are interpreted as a binary integer with the same signedness. /// - /// - Note: This method returns zero when `words` is empty. + /// - Note: This method returns zero when the given collection of `words` is empty. /// @inlinable init(words: some RandomAccessCollection) @@ -81,6 +81,16 @@ public protocol IntXLOrUIntXL: NBKBinaryInteger, ExpressibleByStringLiteral wher @_disfavoredOverload @inlinable func subtracting(_ other: Digit, at index: Int) -> Self + //=------------------------------------------------------------------------= + // MARK: Details x Exponentiation + //=------------------------------------------------------------------------= + + /// Returns the `power` of `self` raised to `exponent`. + /// + /// - Parameter exponent: A value greater than or equal to zero. + /// + @inlinable func power(_ exponent: Int) -> Self + //=------------------------------------------------------------------------= // MARK: Details x Shifts //=------------------------------------------------------------------------= diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Exponentiation.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Exponentiation.swift new file mode 100644 index 00000000..fdf2fc31 --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Exponentiation.swift @@ -0,0 +1,51 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x Exponentiation x Unsigned +//*============================================================================* + +extension NBKFlexibleWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + /// Returns the `power` of `self` raised to `exponent`. + /// + /// - Parameter exponent: A value greater than or equal to zero. + /// + /// [algorithm]: https://en.wikipedia.org/wiki/Exponentiation_by_squaring + /// + @inlinable public func power(_ exponent: Int) -> Self { + //=--------------------------------------= + if exponent == 0 { return Self.one } + else if exponent == 1 { return self } + //=--------------------------------------= + precondition(exponent > 1) + var power = Self(digit: 1) + var multiplier: Self = self + var pattern = UInt(bitPattern: exponent) + //=--------------------------------------= + repeat { + + if pattern.isOdd { + power *= multiplier + } + + pattern &>>= 0000000001 + multiplier *= multiplier + + } while !pattern.isZero + //=--------------------------------------= + return power as Self as Self as Self + } +} diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Exponentiation.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Exponentiation.swift new file mode 100644 index 00000000..5557f1e5 --- /dev/null +++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Exponentiation.swift @@ -0,0 +1,77 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if !DEBUG + +import NBKCoreKit +import NBKFlexibleWidthKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Flexible Width x Exponentiation x UIntXL +//*============================================================================* + +final class NBKFlexibleWidthBenchmarksOnExponentiationAsUIntXL: XCTestCase { + + typealias T = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func test2RaisedToPrime222() { + var base: T = NBK.blackHoleIdentity(T(000002)) + var exponent = NBK.blackHoleIdentity(Int(1399)) + + for _ in 0 ..< 10_000 { + NBK.blackHole(base.power(exponent)) + NBK.blackHoleInoutIdentity(&base) + NBK.blackHoleInoutIdentity(&exponent) + } + } + + func test3RaisedToPrime333() { + var base: T = NBK.blackHoleIdentity(T(000003)) + var exponent = NBK.blackHoleIdentity(Int(2239)) + + for _ in 0 ..< 10_000 { + NBK.blackHole(base.power(exponent)) + NBK.blackHoleInoutIdentity(&base) + NBK.blackHoleInoutIdentity(&exponent) + } + } + + func test5RaisedToPrime555() { + var base: T = NBK.blackHoleIdentity(T(000005)) + var exponent = NBK.blackHoleIdentity(Int(4019)) + + for _ in 0 ..< 10_000 { + NBK.blackHole(base.power(exponent)) + NBK.blackHoleInoutIdentity(&base) + NBK.blackHoleInoutIdentity(&exponent) + } + } + + func test7RaisedToPrime777() { + var base: T = NBK.blackHoleIdentity(T(000007)) + var exponent = NBK.blackHoleIdentity(Int(5903)) + + for _ in 0 ..< 10_000 { + NBK.blackHole(base.power(exponent)) + NBK.blackHoleInoutIdentity(&base) + NBK.blackHoleInoutIdentity(&exponent) + } + } +} + +#endif diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Exponentiation.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Exponentiation.swift new file mode 100644 index 00000000..930669e9 --- /dev/null +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Exponentiation.swift @@ -0,0 +1,307 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +import NBKFlexibleWidthKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Flexible Width x Exponentiation x UIntXL +//*============================================================================* + +final class NBKFlexibleWidthTestsOnExponentiationAsUIntXL: XCTestCase { + + typealias T = UIntXL + typealias M = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests x Small Base + //=------------------------------------------------------------------------= + + func testPowersOf0() { + for exponent in 0 as Int ..< 10 { + NBKAssertExponentiation(T.zero, exponent, exponent.isZero ? T.one : T.zero) + } + } + + func testPowersOf1() { + for exponent in 0 as Int ..< 10 { + NBKAssertExponentiation(T.one, exponent, T.one) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Small Exponent + //=------------------------------------------------------------------------= + + func testBaseRaisedTo0ReturnsOne() { + func with(_ base: T) { + NBKAssertExponentiation(base, Int(0), T.one) + } + + for word in (-5 ... 5).lazy.map(UInt.init(bitPattern:)){ + with(T(words:[word ] as W)) + with(T(words:[word, word &- 1 ] as W)) + with(T(words:[word, word &- 1, word &+ 2 ] as W)) + with(T(words:[word, word &- 1, word &+ 2, word &* 3] as W)) + } + } + + func testBaseRaisedTo1IsBase() { + func with(_ base: T) { + NBKAssertExponentiation(base, Int(1), base) + } + + for word in (-5 ... 5).lazy.map(UInt.init(bitPattern:)){ + with(T(words:[word ] as W)) + with(T(words:[word, word &- 1 ] as W)) + with(T(words:[word, word &- 1, word &+ 2 ] as W)) + with(T(words:[word, word &- 1, word &+ 2, word &* 3] as W)) + } + } + + func testBaseRaisedTo2IsBaseSquared() { + func with(_ base: T) { + NBKAssertExponentiation(base, Int(2), base * base) + } + + for word in (-5 ... 5).lazy.map(UInt.init(bitPattern:)){ + with(T(words:[word ] as W)) + with(T(words:[word, word &- 1 ] as W)) + with(T(words:[word, word &- 1, word &+ 2 ] as W)) + with(T(words:[word, word &- 1, word &+ 2, word &* 3] as W)) + } + } + + func testBaseRaisedTo3IsBaseCubed() { + func with(_ base: T) { + NBKAssertExponentiation(base, Int(3), base * base * base) + } + + for word in (-5 ... 5).lazy.map(UInt.init(bitPattern:)){ + with(T(words:[word ] as W)) + with(T(words:[word, word &- 1 ] as W)) + with(T(words:[word, word &- 1, word &+ 2 ] as W)) + with(T(words:[word, word &- 1, word &+ 2, word &* 3] as W)) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Miscellaneous + //=------------------------------------------------------------------------= + + func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { + func becauseThisCompilesSuccessfully(_ x: inout T) { + XCTAssertNotNil(x.power(0)) + } + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Exponentiation x UIntXL x Primes +//*============================================================================* + +final class NBKFlexibleWidthTestsOnExponentiationByPrimesAsUIntXL: XCTestCase { + + typealias T = UIntXL + typealias M = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + /// https://www.wolframalpha.com/input?i2d=true&i=Power%5B2%2C1339%5D + func test2RaisedToPrime222() { + NBKAssertExponentiation(T(2), Int(1399), T(""" + 0000000000000000000000000013834514851379060073245971093437442064\ + 9160977983437969614705766643223075185306094487364790624541806526\ + 1469876608299964693394277268648930360258831509072633846696053692\ + 0615225071992089480779025598319909176616250787667116220112182629\ + 2066306122745343237483669467464293469194680096834470280624398144\ + 7140309400278171194198038370675489371535762220733644100930478390\ + 9871197489979144724073675307870340798761005614290980492634226688 + """)) + } + + /// https://www.wolframalpha.com/input?i2d=true&i=Power%5B3%2C2239%5D + func test3RaisedToPrime333() { + NBKAssertExponentiation(T(3), Int(2239), T(""" + 0000000000000000000188143542653317364740047262022158266784428791\ + 9275755434856235633416147929751345775198585370887106410700145660\ + 6941136649945052148587729379215298759841906211465894489332805610\ + 3754563980603820020778896725273833377637201111950279005112886290\ + 8217517791462710719585984177457155945873475389047023763181890095\ + 9473781620831209436384360444149350498181207507201081140457731667\ + 8330429216786541702964381293439187677376199748692174845775469107\ + 1970497833817135114559784314771606933781164789651479259636951051\ + 1939631603190331045111418380453489110302905083967247056298476321\ + 3031701771676257422898074561340984020468039563665625492587401150\ + 2217805773793168451721091497379753074682133867791141932470210853\ + 5500447924439317916852983725285062418604919143133304424502097997\ + 8608095945569404820035699584592750436592636252055799816797294408\ + 0379347764424614210540528598264992483071934555760511919452459358\ + 8835641810301075822245153655314705395817134933252061409024669198\ + 8059476349693766699090206318226803178343171280950787682695695659\ + 6036250169540192297202679456092601217013126286587177412655204267 + """)) + } + + /// https://www.wolframalpha.com/input?i2d=true&i=Power%5B5%2C4019%5D + func test5RaisedToPrime555() { + NBKAssertExponentiation(T(5), Int(4019), T(""" + 0000001446929684346652712293854771363608770525967600083755404601\ + 4957345870087500503487603669487412790514866287646265322998165123\ + 7858490002304274433672147699570659505153044896486895393750640165\ + 6928775867908279515437398191176238951828408573790734470345477155\ + 5523461654011508905437448709888495365320237507108067589052329024\ + 9150152007784011211339914449754828962361147846093684594339840255\ + 4082090351870280593564461792533581515740009197746416184126376462\ + 7513171712952497141572865808593203385483317716323751288867193425\ + 4148468649640058864230675104524048186517447302082906408424956362\ + 9758837840131897008299169989849297847761856730804217735049415782\ + 9576164079541459773697263304564453838344036135321806166247311605\ + 1583922759481958404593247769652134498168235251891967609838551519\ + 6895367299027108368711330107798776358904935596791346512797789271\ + 4896792453973244271314471709632569444905582089098918351559580722\ + 6321106414034452179867244499118249751063342223759587453914686539\ + 6908111618174630570000311233662035613887919737154518565754904733\ + 3083185530695058035521254105752988609692725798470777630752530204\ + 2599940027007370568347125202050752868479632687293640809602767930\ + 3858816432201682904268147124008525621379120457219167772120301585\ + 5924566379439864166360938720555906940258344296315856834431713110\ + 9031510071399560194606949946938965200495181099854874459742836621\ + 9452749381231066739863712410355985286770760288114233351958522528\ + 9254720092509662470547270010401979793646249028556880781998508960\ + 1361859999448519399006853526587504480164807765094325996443657804\ + 1840647438579682202685556945086347285534115616913220314483186795\ + 9505824453508868809675232062282535499100880724452941629449074254\ + 8612182352672327327268400829255931466201932710759855981331047638\ + 0373952548092040726975994716532293619257385003476756537912583205\ + 3118439654075379854319335205290809944413949455014265873545253078\ + 8330205282519080028427767192749459753122069080264973087241014307\ + 2832496925258959405329022843928903214208568103866527037140713169\ + 3604782550976252551168862593185575739685113169373933605227835303\ + 0847072871335150103185467131343559638580148070154916235638591521\ + 7551475263551504418572891033712157135476213809318196160948711372\ + 5354715015499902615236138501149706494374571817673933121619689549\ + 1190330835852177242160254166743595083040762847408006715353013832\ + 8458452645210177792497777945236485562922497538842118636928202205\ + 3232781215026991677078777075079415868972420095294308064034517889\ + 5294513805950305684358059918968985264729204194891997038141044289\ + 4523351216180823177725756322850045350978670133665384205423770116\ + 2034072860275538780053702353667090377996048746658421230595438359\ + 4351041626743397066325398137462696656196425405090145037319940783\ + 4075423829513127773206584989704512568918200936953799420923277344\ + 2116738501755407694565787324325611962194670923054218292236328125 + """)) + } + + /// https://www.wolframalpha.com/input?i2d=true&i=Power%5B7%2C5903%5D + func test7RaisedToPrime777() { + NBKAssertExponentiation(T(7), Int(5903), T(""" + 0004108943827532289998252241834161383961424609336721429562672973\ + 5215518660156770969551613947438106226819575618431824632656548784\ + 2443630744318409823032653940945721503598477652901203967391204332\ + 3158222996451925544379097239021867537542941225033407598605764422\ + 5626993205372457839766802826979647293572000260187726319652445485\ + 9482777216365497907324653716024518534469506020670363036282940141\ + 7345349149930883359235820343903927339761930696186308207677700409\ + 7391771164922837159313352006942436230958342761245333909697097098\ + 1962850117306746317942719737152987263783869529445450162201013093\ + 7640979740872661278132106700453973743232978892847809183649542178\ + 6386091024874014251100007758237318828196343521562370522840436333\ + 9860937826427665567828847794223264241229145944928596285455954773\ + 2336371045463929134249803534108451709651747011690640152682259071\ + 7588531222847352542685069886646970884179932109354875736278011717\ + 7049137345311907474904031124084012054229020837573682684449616986\ + 1141963222206845750828398145035163722273565209503954216564277782\ + 9345151605641026739460433186606694775097789988243538915830478736\ + 2321105525900626126720677155472003434944779964774589232951904517\ + 9476680111837682980783634668338283785251186754580916022872774476\ + 8248487173769642087282206643072554696940829885901306725576309209\ + 1743074872375459772452624462584335614850487024186238154804049698\ + 4811375470004856107048221190933505123463191157187870352180325359\ + 3741701718672664302615728918968015750489563267192890269446915173\ + 1701093323994084381646062513005671630985001682866606254371387996\ + 8024992986421373100014171354432561066598242954612339431648999137\ + 9051435679527308334014939171040310771958013669805318524543112813\ + 9957017193329249909184553798390058883185333407503584493257244158\ + 3266967356357550201757284978687473572038818544870024112088525474\ + 8571207645144242434181117672975231370371178492357391865766085377\ + 3823840040081314628441473981477003917858676159209438834345026935\ + 4779790020210041341578847715514924396711295298299953107848651502\ + 3769622943601147847225941911366166628697715831218025798784981651\ + 6594489454864735330027409414601808651740177800327884257547084972\ + 2974937680043549927608417044479914400414576182906969146216064813\ + 9797351302752302750367394658157006251127397997773654189941600295\ + 7012943921820728784912336613928263599040635592438852410591446463\ + 2206241342371241353735828614033633079948725931648022365152412010\ + 6536877818941494267763684966615953104317136956765112250407063913\ + 3623022142786314689201462019186500031543501414431154405127756671\ + 2598842710382317599518208183440935184711587670120132882808742348\ + 8411078298769546381717505913293931478168035555632794459447381827\ + 1468641906416458172696166794340888092638284873221835454582235513\ + 3898834466941889918244651488283379527147807349915745308667074963\ + 7891453340202992598013755301769390340910183288640813995555377044\ + 7223588515487024291479342125463949093313578539672841465173598174\ + 6497929985814101267907129298071776716937287674794676561056646943\ + 0732206345508882216332886917818007802132509658343825952463482298\ + 4489495136960700641892386060280455771911594308242281539457704395\ + 9524507677196150124432182309556548761806281803523338664967704979\ + 3460861648738117020310880747550817881593881271702214461077779340\ + 4287970525724476964313573471187561031001209171965777853627292097\ + 8752509881640464168980655122431992653071443051558073785207534985\ + 4321311390667792122896825769874659348335793677512574761787460891\ + 0940419324785857595375679045664913268485224001615591380491428459\ + 9770610934799452407468859548167516086051739430826568377985552353\ + 5827900814770399339897945479367857446392755360019877423764266384\ + 9102974526553855472041319878092661554915548899695716722333975665\ + 7217654413703071682361274283821111835404123486866747021789194573\ + 4534154982476166843306613439440924368550646996797997564717871253\ + 9160649498393301802347586561673042384642389863462685684046394436\ + 5346633812583044014990173666027640872684548673874459368061904085\ + 1833388235372538302693052181739532042295454028340795279479946777\ + 0998436672566006010388682401863627158348794580771807628351724156\ + 9645262878014094496495419172431359232834857581736063818066222047\ + 8022377634336210803408343245633680822509378298099363690965609414\ + 4196836682956302330613169375496300657119374497326438865815833130\ + 6641482714265346330788386216670657593653569569417576198111004914\ + 1723667248154259119306662997353637860619174485149827167090042710\ + 6471414747419591688508026916865700879769503331013550956729099212\ + 7820605036546582266249968312554384036359924591010229549799331443\ + 1457638460474955690746307230167670856667830295141891662843469167\ + 0424763717677877513125882858810853633770618510938341766796723021\ + 6826062464545717657085175787821109704957381106356345712265138323\ + 0768347083961948674167484046428595865648150013889410250736872615\ + 6529299656645514273099767510443083082596626167467582361833369755\ + 6481100284602082844869451125548691905562882873118646312028536971\ + 1732106406529921113787189197150818833289607479384389566344975672\ + 7365338338792781072340541456248573682006539809213546535950220343 + """)) + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Exponentiation x Assertions +//*============================================================================* + +private func NBKAssertExponentiation( +_ base: T, _ exponent: Int, _ power: T, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + XCTAssertEqual(base.power(exponent), power, file: file, line: line) +} + +#endif From ba79947ce40fdd30e7df752f2228ca87cfea27ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Tue, 24 Oct 2023 14:55:36 +0200 Subject: [PATCH 106/133] [NBKFlexibleWidthKit] Cleanup. --- .../NBKFlexibleWidth+Exponentiation.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Exponentiation.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Exponentiation.swift index 930669e9..3f7f2933 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Exponentiation.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Exponentiation.swift @@ -122,7 +122,7 @@ final class NBKFlexibleWidthTestsOnExponentiationByPrimesAsUIntXL: XCTestCase { // MARK: Tests //=------------------------------------------------------------------------= - /// https://www.wolframalpha.com/input?i2d=true&i=Power%5B2%2C1339%5D + /// https://www.wolframalpha.com/input?i2d=true&i=Power%5B2%2C1399%5D func test2RaisedToPrime222() { NBKAssertExponentiation(T(2), Int(1399), T(""" 0000000000000000000000000013834514851379060073245971093437442064\ From 50dcd02bcca6c355b3325510321470dcf93ffe7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Wed, 25 Oct 2023 08:03:21 +0200 Subject: [PATCH 107/133] [NBKFlexibleWidthKit] Cleanup. --- .../NBKFlexibleWidth+Exponentiation.swift | 8 +++----- .../NBKFlexibleWidth+Subtraction+Digit.swift | 2 +- .../NBKFlexibleWidth+Subtraction.swift | 2 +- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Exponentiation.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Exponentiation.swift index fdf2fc31..b809986f 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Exponentiation.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Exponentiation.swift @@ -23,17 +23,15 @@ extension NBKFlexibleWidth.Magnitude { /// /// - Parameter exponent: A value greater than or equal to zero. /// - /// [algorithm]: https://en.wikipedia.org/wiki/Exponentiation_by_squaring - /// @inlinable public func power(_ exponent: Int) -> Self { //=--------------------------------------= if exponent == 0 { return Self.one } else if exponent == 1 { return self } //=--------------------------------------= - precondition(exponent > 1) - var power = Self(digit: 1) + Swift.assert(exponent > 001) + var power = Self(digit: 001) var multiplier: Self = self - var pattern = UInt(bitPattern: exponent) + var pattern = UInt(exponent) //=--------------------------------------= repeat { diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift index 01b11d11..6fbdef92 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift @@ -64,7 +64,7 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= self.storage.resize(minCount: index + 1) - let overflow: Bool = self.storage.withUnsafeMutableBufferPointer(in: index...) { + let overflow = self.storage.withUnsafeMutableBufferPointer(in: index...) { NBK.SUISS.decrement(&$0, by: other).overflow } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift index c5e3bae1..88635b13 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift @@ -64,7 +64,7 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------------------= self.storage.resize(minCount: index + other.storage.elements.count) - let overflow: Bool = self.storage.withUnsafeMutableBufferPointer(in: index...) { slice in + let overflow = self.storage.withUnsafeMutableBufferPointer(in: index...) { slice in other.storage.withUnsafeBufferPointer { other in NBK.SUISS.decrement(&slice, by: other).overflow } From 7426b65b989c28f892f2c728b3b964372cdb06ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Wed, 25 Oct 2023 10:10:30 +0200 Subject: [PATCH 108/133] [NBKFlexibleWidthKit] Long square product. --- .../NBKFlexibleWidthKit/IntXLOrUIntXL.swift | 10 +++ .../NBKFlexibleWidth+Exponentiation.swift | 8 +- ...KFlexibleWidth+Multiplication+Square.swift | 75 +++++++++++++++++++ .../NBKFlexibleWidth+Multiplication.swift | 14 ++-- .../NBKFlexibleWidth+Multiplication.swift | 18 ++++- .../NBKFlexibleWidth+Multiplication.swift | 53 +++++++++---- 6 files changed, 149 insertions(+), 29 deletions(-) create mode 100644 Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Square.swift diff --git a/Sources/NBKFlexibleWidthKit/IntXLOrUIntXL.swift b/Sources/NBKFlexibleWidthKit/IntXLOrUIntXL.swift index f63998c7..55fb0f22 100644 --- a/Sources/NBKFlexibleWidthKit/IntXLOrUIntXL.swift +++ b/Sources/NBKFlexibleWidthKit/IntXLOrUIntXL.swift @@ -81,6 +81,16 @@ public protocol IntXLOrUIntXL: NBKBinaryInteger, ExpressibleByStringLiteral wher @_disfavoredOverload @inlinable func subtracting(_ other: Digit, at index: Int) -> Self + //=------------------------------------------------------------------------= + // MARK: Details x Multiplication + //=------------------------------------------------------------------------= + + /// Forms the square product of this value. + @inlinable mutating func square() + + /// Returns the square product of this value. + @inlinable func squared() -> Self + //=------------------------------------------------------------------------= // MARK: Details x Exponentiation //=------------------------------------------------------------------------= diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Exponentiation.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Exponentiation.swift index b809986f..8646e5e2 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Exponentiation.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Exponentiation.swift @@ -36,14 +36,14 @@ extension NBKFlexibleWidth.Magnitude { repeat { if pattern.isOdd { - power *= multiplier + power *= multiplier } - pattern &>>= 0000000001 - multiplier *= multiplier + pattern &>>= 000001 + multiplier.square() } while !pattern.isZero //=--------------------------------------= - return power as Self as Self as Self + return power as Self as Self as Self as Self } } diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Square.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Square.swift new file mode 100644 index 00000000..9f4d65f2 --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Square.swift @@ -0,0 +1,75 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x Multiplication x Square x Unsigned +//*============================================================================* + +extension NBKFlexibleWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public mutating func square() { + self = self.squared() + } + + @inlinable public func squared() -> Self { + Self.productBySquareLongAlgorithm(multiplying: self) + } +} + +//=----------------------------------------------------------------------------= +// MARK: + Algorithms +//=----------------------------------------------------------------------------= + +extension NBKFlexibleWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Transformations x Long Multiplication + //=------------------------------------------------------------------------= + + /// Returns the square product of `base` by performing long multiplication. + /// + /// - Note: It is up to `2x` faster than long multiplication with arbitrary inputs. + /// + @inlinable static func productBySquareLongAlgorithm(multiplying base: Self) -> Self { + Self.uninitialized(count: 2 * base.count) { product in + base.storage.withUnsafeBufferPointer { base in + //=--------------------------= + // pointee: initialization + //=--------------------------= + product.initialize(repeating: 0 as UInt) + //=--------------------------= + var carry0: Bool = false // for multiplication by 02 + var carry1: Bool = false // for addition of diagonal + + for baseIndex in base.indices { + let multiplier = base[baseIndex] + let productIndex = 2 * baseIndex + + NBK.SUISS.incrementInIntersection( + &product[(productIndex + 1)...], // add non-diagonal elements + by: UnsafeBufferPointer(rebasing: base[(baseIndex + 1)...]), times: multiplier) + + carry0 = NBK.SUISS.incrementInIntersection( + &product[(productIndex)...], // partially double non-diagonal elements + by: UnsafeBufferPointer(rebasing: product[(productIndex) ..< (productIndex + 2)]), plus: carry0).overflow + + carry1 = NBK.SUISS.incrementInIntersection( + &product[(productIndex)...], // add the diagonal element + by: CollectionOfOne(multiplier), times: multiplier, plus: UInt(bit: carry1)).overflow + } + } + } + } +} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift index a5181204..910e6da8 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift @@ -24,24 +24,24 @@ extension NBKFlexibleWidth.Magnitude { } @inlinable public static func *(lhs: Self, rhs: Self) -> Self { - lhs.multipliedUsingLongAlgorithm(by: rhs, adding: 0 as UInt) + Self.productByLongAlgorithm(multiplying: lhs, by: rhs, adding: 0 as UInt) } } //=----------------------------------------------------------------------------= -// MARK: + Long Multiplication Algorithms +// MARK: + Algorithms //=----------------------------------------------------------------------------= extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= - // MARK: Transformations x Private + // MARK: Transformations x Long Multiplication //=------------------------------------------------------------------------= - /// Performs long multiplication. - @inlinable func multipliedUsingLongAlgorithm(by multiplier: Self, adding addend: UInt) -> Self { - Self.uninitialized(count: self.count + multiplier.count) { pro in - self.storage.withUnsafeBufferPointer { lhs in + /// Returns the product of `multiplicand` and `multiplier` plus `addend` by performing long multiplication. + @inlinable static func productByLongAlgorithm(multiplying multiplicand: Self, by multiplier: Self, adding addend: UInt) -> Self { + Self.uninitialized(count: multiplicand.count + multiplier.count) { pro in + multiplicand.storage.withUnsafeBufferPointer { lhs in multiplier.storage.withUnsafeBufferPointer { rhs in var pointer = pro.baseAddress! //=--------------------------= diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Multiplication.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Multiplication.swift index e671d137..64525766 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Multiplication.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Multiplication.swift @@ -29,7 +29,7 @@ final class NBKFlexibleWidthBenchmarksOnMultiplicationAsUIntXL: XCTestCase { // MARK: Tests //=------------------------------------------------------------------------= - func testMultiplied() { + func testMultiplying() { var lhs = NBK.blackHoleIdentity(T(x64:[~1, ~2, ~3, ~4] as X)) var rhs = NBK.blackHoleIdentity(T(x64:[ 1, 2, 3, 4] as X)) @@ -44,7 +44,7 @@ final class NBKFlexibleWidthBenchmarksOnMultiplicationAsUIntXL: XCTestCase { // MARK: Tests x Digit //=------------------------------------------------------------------------= - func testMultipliedByDigit() { + func testMultiplyingByDigit() { var lhs = NBK.blackHoleIdentity(T(x64:[~1, ~2, ~3, ~4] as X)) var rhs = NBK.blackHoleIdentity(UInt.max) @@ -54,6 +54,20 @@ final class NBKFlexibleWidthBenchmarksOnMultiplicationAsUIntXL: XCTestCase { NBK.blackHoleInoutIdentity(&rhs) } } + + //=------------------------------------------------------------------------= + // MARK: Tests x Square + //=------------------------------------------------------------------------= + + func testMultiplyingBySquaring() { + var base = NBK.blackHoleIdentity(T(x64:[~1, ~2, ~3, ~4] as X)) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(base.squared()) + NBK.blackHoleInoutIdentity(&base) + NBK.blackHoleInoutIdentity(&base) + } + } } #endif diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Multiplication.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Multiplication.swift index f944ce24..5e81ff1e 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Multiplication.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Multiplication.swift @@ -46,7 +46,7 @@ final class NBKFlexibleWidthTestsOnMultiplicationAsUIntXL: XCTestCase { // MARK: Tests x Digit (and Self) //=------------------------------------------------------------------------= - func testMultipliedByDigit() { + func testMultiplyingByDigit() { NBKAssertMultiplicationByDigit(T(words:[1, 2, 3, 4] as W), UInt(0), T(words:[ 0, 0, 0, 0, 0] as W)) NBKAssertMultiplicationByDigit(T(words:[1, 2, 3, 4] as W), UInt(1), T(words:[ 1, 2, 3, 4, 0] as W)) NBKAssertMultiplicationByDigit(T(words:[1, 2, 3, 4] as W), UInt(2), T(words:[ 2, 4, 6, 8, 0] as W)) @@ -60,13 +60,24 @@ final class NBKFlexibleWidthTestsOnMultiplicationAsUIntXL: XCTestCase { // MARK: Tests x Digit x Addition //=------------------------------------------------------------------------= - func testMultiplicationByDigitWithAddition() { + func testMultiplyingByDigitWithAddition() { NBKAssertMultiplicationByDigitWithAddition(T(words:[~0, ~0, ~0, ~0] as W), 0, 0, T(words:[ 0, 0, 0, 0, 0] as W)) NBKAssertMultiplicationByDigitWithAddition(T(words:[~0, ~0, ~0, ~0] as W), 0, ~0, T(words:[~0, 0, 0, 0, 0] as W)) NBKAssertMultiplicationByDigitWithAddition(T(words:[~0, ~0, ~0, ~0] as W), ~0, 0, T(words:[ 1, ~0, ~0, ~0, ~1] as W)) NBKAssertMultiplicationByDigitWithAddition(T(words:[~0, ~0, ~0, ~0] as W), ~0, ~0, T(words:[ 0, 0, 0, 0, ~0] as W)) } + //=------------------------------------------------------------------------= + // MARK: Tests x Square + //=------------------------------------------------------------------------= + + func testMultiplyingBySquaring() { + NBKAssertMultiplicationBySquaring(T(words:[ 0, 0, 0, 0] as W), T(words:[ 0, 0, 0, 0, 0, 0, 0, 0] as W)) + NBKAssertMultiplicationBySquaring(T(words:[ 1, 2, 3, 4] as W), T(words:[ 1, 4, 10, 20, 25, 24, 16, 0] as W)) + NBKAssertMultiplicationBySquaring(T(words:[~1, ~2, ~3, ~4] as W), T(words:[ 4, 8, 16, 28, 21, 20, 10, ~7] as W)) + NBKAssertMultiplicationBySquaring(T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 1, 0, 0, 0, ~1, ~0, ~0, ~0] as W)) + } + //=------------------------------------------------------------------------= // MARK: Tests x Miscellaneous //=------------------------------------------------------------------------= @@ -87,29 +98,39 @@ final class NBKFlexibleWidthTestsOnMultiplicationAsUIntXL: XCTestCase { //*============================================================================* private func NBKAssertMultiplication( -_ lhs: T, _ rhs: T, _ pro: T, +_ lhs: T, _ rhs: T, _ product: T, file: StaticString = #file, line: UInt = #line) { //=------------------------------------------= - XCTAssertEqual( lhs * rhs, pro, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs *= rhs; return lhs }(), pro, file: file, line: line) + XCTAssertEqual( lhs * rhs, product, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs *= rhs; return lhs }(), product, file: file, line: line) //=------------------------------------------= - guard - let lhs = lhs as? UIntXL, - let rhs = rhs as? UIntXL, - let pro = pro as? UIntXL - else { return } + guard let lhs = lhs as? UIntXL, let rhs = rhs as? UIntXL, let product = product as? UIntXL else { return } //=------------------------------------------= - XCTAssertEqual(lhs.multipliedUsingLongAlgorithm(by: rhs, adding: 0), pro, file: file, line: line) + XCTAssertEqual(UIntXL.productByLongAlgorithm(multiplying: lhs, by: rhs, adding: 0), product, file: file, line: line) } private func NBKAssertMultiplicationByDigit( -_ lhs: T, _ rhs: T.Digit, _ pro: T, +_ lhs: T, _ rhs: T.Digit, _ product: T, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + XCTAssertEqual( lhs * rhs, product, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs *= rhs; return lhs }(), product, file: file, line: line) + //=------------------------------------------= + NBKAssertMultiplication(lhs, T(digit: rhs), product, file: file, line: line) +} + +private func NBKAssertMultiplicationBySquaring( +_ base: T, _ product: T, file: StaticString = #file, line: UInt = #line) { //=------------------------------------------= - XCTAssertEqual( lhs * rhs, pro, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs *= rhs; return lhs }(), pro, file: file, line: line) + NBKAssertMultiplication(base, base, product, file: file, line: line) + //=------------------------------------------= + XCTAssertEqual( base.squared(), product, file: file, line: line) + XCTAssertEqual({ var base = base; base.square (); return base }(), product, file: file, line: line) + //=------------------------------------------= + guard let base = base as? UIntXL, let product = product as? UIntXL else { return } //=------------------------------------------= - NBKAssertMultiplication(lhs, T(digit: rhs), pro, file: file, line: line) + XCTAssertEqual(UIntXL.productBySquareLongAlgorithm(multiplying: base), product, file: file, line: line) } //=----------------------------------------------------------------------------= @@ -123,7 +144,7 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual(lhs.multiplied(by: rhs, adding: add), pro, file: file, line: line) XCTAssertEqual({ var lhs = lhs; lhs.multiply(by: rhs, add: add); return lhs }(), pro, file: file, line: line) //=------------------------------------------= - XCTAssertEqual(lhs.multipliedUsingLongAlgorithm(by: UIntXL(digit: rhs), adding: add), pro, file: file, line: line) + XCTAssertEqual(UIntXL.productByLongAlgorithm(multiplying: lhs, by: UIntXL(digit: rhs), adding: add), pro, file: file, line: line) } #endif From 728798907b5d4084e12dd36a606ddef7211d64ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Thu, 26 Oct 2023 08:25:54 +0200 Subject: [PATCH 109/133] [NBKFlexibleWidthKit] Improved long square product. --- ...KFlexibleWidth+Multiplication+Square.swift | 37 +++++++++------- ...StrictUnsignedInteger+Multiplication.swift | 43 +++++++++++++++++++ .../NBKFlexibleWidth+Multiplication.swift | 15 ++++--- 3 files changed, 74 insertions(+), 21 deletions(-) create mode 100644 Sources/NBKFlexibleWidthKit/Private/StrictUnsignedInteger+Multiplication.swift diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Square.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Square.swift index 9f4d65f2..abfff6e5 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Square.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Square.swift @@ -24,7 +24,7 @@ extension NBKFlexibleWidth.Magnitude { } @inlinable public func squared() -> Self { - Self.productBySquareLongAlgorithm(multiplying: self) + Self.productBySquareLongAlgorithm(multiplying: self, adding: 0 as UInt) } } @@ -42,7 +42,7 @@ extension NBKFlexibleWidth.Magnitude { /// /// - Note: It is up to `2x` faster than long multiplication with arbitrary inputs. /// - @inlinable static func productBySquareLongAlgorithm(multiplying base: Self) -> Self { + @inlinable static func productBySquareLongAlgorithm(multiplying base: Self, adding addend: UInt) -> Self { Self.uninitialized(count: 2 * base.count) { product in base.storage.withUnsafeBufferPointer { base in //=--------------------------= @@ -50,24 +50,31 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------= product.initialize(repeating: 0 as UInt) //=--------------------------= - var carry0: Bool = false // for multiplication by 02 - var carry1: Bool = false // for addition of diagonal - - for baseIndex in base.indices { + var index: Int = 000000 + var carry: UInt = addend + //=--------------------------= + var baseIndex = base.startIndex; while baseIndex < base.endIndex { let multiplier = base[baseIndex] let productIndex = 2 * baseIndex + base.formIndex(after: &baseIndex) + + index = productIndex + 1 // add non-diagonal products + + NBK.SUISS.incrementInIntersection(&product, + by: UnsafeBufferPointer(rebasing: base[baseIndex...]), + times: multiplier, plus: 00000, at: &index) + + index = productIndex // partially double non-diagonal products - NBK.SUISS.incrementInIntersection( - &product[(productIndex + 1)...], // add non-diagonal elements - by: UnsafeBufferPointer(rebasing: base[(baseIndex + 1)...]), times: multiplier) + NBK.SUISS.multiply(&product, + by: 000002, + add: &carry, at: &index, upTo: productIndex + 2) - carry0 = NBK.SUISS.incrementInIntersection( - &product[(productIndex)...], // partially double non-diagonal elements - by: UnsafeBufferPointer(rebasing: product[(productIndex) ..< (productIndex + 2)]), plus: carry0).overflow + index = productIndex // add this iteration's diagonal product - carry1 = NBK.SUISS.incrementInIntersection( - &product[(productIndex)...], // add the diagonal element - by: CollectionOfOne(multiplier), times: multiplier, plus: UInt(bit: carry1)).overflow + carry &+= UInt(bit: NBK.SUISS.incrementInIntersection( + &product, by: CollectionOfOne((multiplier)), + times: multiplier, plus: 00000, at: &index)) } } } diff --git a/Sources/NBKFlexibleWidthKit/Private/StrictUnsignedInteger+Multiplication.swift b/Sources/NBKFlexibleWidthKit/Private/StrictUnsignedInteger+Multiplication.swift new file mode 100644 index 00000000..97c22906 --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/Private/StrictUnsignedInteger+Multiplication.swift @@ -0,0 +1,43 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Strict Unsigned Integer x Multiplication x Sub Sequence +//*============================================================================* +//=----------------------------------------------------------------------------= +// MARK: + Digit + Digit +//=----------------------------------------------------------------------------= + +extension NBK.StrictUnsignedInteger.SubSequence where Base: MutableCollection { + + //=------------------------------------------------------------------------= + // MARK: Transformations x Inout + //=------------------------------------------------------------------------= + + /// Multiplies `base` by `multiplier` then adds `digit` from `index` up to `limit`. + /// + /// - Returns: The `low` and `high` product: (high: `digit`, low: `base`). + /// + @inlinable public static func multiply( + _ base: inout Base, by multiplier: Base.Element, add digit: inout Base.Element, at index: inout Base.Index, upTo limit: Base.Index) { + //=--------------------------------------= + Swift.assert(index >= base.startIndex) + Swift.assert(index <= limit) + Swift.assert(limit <= base.endIndex ) + //=--------------------------------------= + forwards: while index < limit { + var wide = base[index].multipliedFullWidth(by: multiplier) + wide.high &+= Base.Element(bit: wide.low.addReportingOverflow(digit)) + (digit, base[index]) = (wide) + base.formIndex(after: &index) + } + } +} diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Multiplication.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Multiplication.swift index 5e81ff1e..1bb6a67d 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Multiplication.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Multiplication.swift @@ -106,7 +106,8 @@ file: StaticString = #file, line: UInt = #line) { //=------------------------------------------= guard let lhs = lhs as? UIntXL, let rhs = rhs as? UIntXL, let product = product as? UIntXL else { return } //=------------------------------------------= - XCTAssertEqual(UIntXL.productByLongAlgorithm(multiplying: lhs, by: rhs, adding: 0), product, file: file, line: line) + XCTAssertEqual(UIntXL.productByLongAlgorithm(multiplying: lhs, by: rhs, adding: 00000000), product, file: file, line: line) + XCTAssertEqual(UIntXL.productByLongAlgorithm(multiplying: lhs, by: rhs, adding: UInt.max), product + UInt.max, file: file, line: line) } private func NBKAssertMultiplicationByDigit( @@ -130,7 +131,8 @@ file: StaticString = #file, line: UInt = #line) { //=------------------------------------------= guard let base = base as? UIntXL, let product = product as? UIntXL else { return } //=------------------------------------------= - XCTAssertEqual(UIntXL.productBySquareLongAlgorithm(multiplying: base), product, file: file, line: line) + XCTAssertEqual(UIntXL.productBySquareLongAlgorithm(multiplying: base, adding: 00000000), product, file: file, line: line) + XCTAssertEqual(UIntXL.productBySquareLongAlgorithm(multiplying: base, adding: UInt.max), product + UInt.max, file: file, line: line) } //=----------------------------------------------------------------------------= @@ -138,13 +140,14 @@ file: StaticString = #file, line: UInt = #line) { //=----------------------------------------------------------------------------= private func NBKAssertMultiplicationByDigitWithAddition( -_ lhs: UIntXL, _ rhs: UInt, _ add: UInt, _ pro: UIntXL, +_ lhs: UIntXL, _ rhs: UInt, _ addend: UInt, _ product: UIntXL, file: StaticString = #file, line: UInt = #line) { //=------------------------------------------= - XCTAssertEqual(lhs.multiplied(by: rhs, adding: add), pro, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs.multiply(by: rhs, add: add); return lhs }(), pro, file: file, line: line) + XCTAssertEqual(lhs.multiplied(by: rhs, adding: addend), product, file: file, line: line) + XCTAssertEqual({ var lhs = lhs; lhs.multiply(by: rhs, add: addend); return lhs }(), product, file: file, line: line) //=------------------------------------------= - XCTAssertEqual(UIntXL.productByLongAlgorithm(multiplying: lhs, by: UIntXL(digit: rhs), adding: add), pro, file: file, line: line) + XCTAssertEqual(UIntXL.productByLongAlgorithm(multiplying: lhs, by: UIntXL(digit: rhs), adding: addend), product, file: file, line: line) + XCTAssertEqual(UIntXL.productByLongAlgorithm(multiplying: lhs, by: UIntXL(digit: rhs), adding: 000000), product - addend, file: file, line: line) } #endif From c5e815532a7065acf666536f76ed97887004af32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Fri, 3 Nov 2023 13:35:21 +0100 Subject: [PATCH 110/133] [NBKFlexibleWidthKit] Fibonacci sequence pair at index. --- .../NBKFlexibleWidth+Fibonacci.swift | 66 +++++++ .../NBKFlexibleWidth+Fibonacci.swift | 69 ++++++++ .../NBKFlexibleWidth+Fibonacci.swift | 165 ++++++++++++++++++ 3 files changed, 300 insertions(+) create mode 100644 Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Fibonacci.swift create mode 100644 Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Fibonacci.swift create mode 100644 Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Fibonacci.swift diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Fibonacci.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Fibonacci.swift new file mode 100644 index 00000000..6cf2580b --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Fibonacci.swift @@ -0,0 +1,66 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +//*============================================================================* +// MARK: * NBK x Flexible Width x Fibonacci x Unsigned +//*============================================================================* + +extension NBKFlexibleWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + /// Returns the Fibonacci sequence pair at `index`. + /// + /// ```swift + /// UIntXL.fibonacci(0) // (element: 0, next: 1) + /// UIntXL.fibonacci(1) // (element: 1, next: 1) + /// UIntXL.fibonacci(2) // (element: 1, next: 2) + /// UIntXL.fibonacci(3) // (element: 2, next: 3) + /// UIntXL.fibonacci(4) // (element: 3, next: 5) + /// UIntXL.fibonacci(5) // (element: 5, next: 8) + /// ``` + /// + /// - Parameter index: A value greater than zero. + /// + public static func fibonacci(_ index: Int) -> (element: Self, next: Self) { + //=--------------------------------------= + // f(2x + 0) = f(x) * [2 * f(x + 1) - f(x)] + // f(2x + 1) = f(x) ^ 2 + f(x + 1) ^ 2 + //=--------------------------------------= + precondition(index >= Int.zero) + //=--------------------------------------= + var a: Self = Self(digit: 0) + var b: Self = Self(digit: 1) + //=--------------------------------------= + for bitIndex in (0 ..< Int.bitWidth - index.leadingZeroBitCount).reversed() { + + var (x): Self // f(2x + 0) + x = b.bitShiftedLeft(major: Int.zero, minor: Int.one) + x -= a + x *= a + + var (y): Self // f(2x + 1) + y = a.squared() + y += b.squared() + + if (index &>> bitIndex).isOdd { + x += y + a = y + b = x + } else { + a = x + b = y + } + } + + return (element: a as Self, next: b as Self) + } +} diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Fibonacci.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Fibonacci.swift new file mode 100644 index 00000000..524f84d6 --- /dev/null +++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Fibonacci.swift @@ -0,0 +1,69 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if !DEBUG + +import NBKCoreKit +import NBKFlexibleWidthKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Flexible Width x Fibonacci x UIntXL +//*============================================================================* + +final class NBKFlexibleWidthBenchmarksOnFibonacciAsUIntXL: XCTestCase { + + typealias T = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testPrime222() { + var index = NBK.blackHoleIdentity(Int(1399)) + + for _ in 0 ..< 10_000 { + NBK.blackHole(T.fibonacci(index)) + NBK.blackHoleInoutIdentity(&index) + } + } + + func testPrime333() { + var index = NBK.blackHoleIdentity(Int(2239)) + + for _ in 0 ..< 10_000 { + NBK.blackHole(T.fibonacci(index)) + NBK.blackHoleInoutIdentity(&index) + } + } + + func testPrime555() { + var index = NBK.blackHoleIdentity(Int(4019)) + + for _ in 0 ..< 10_000 { + NBK.blackHole(T.fibonacci(index)) + NBK.blackHoleInoutIdentity(&index) + } + } + + func testPrime777() { + var index = NBK.blackHoleIdentity(Int(5903)) + + for _ in 0 ..< 10_000 { + NBK.blackHole(T.fibonacci(index)) + NBK.blackHoleInoutIdentity(&index) + } + } +} + +#endif diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Fibonacci.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Fibonacci.swift new file mode 100644 index 00000000..5d930841 --- /dev/null +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Fibonacci.swift @@ -0,0 +1,165 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +import NBKFlexibleWidthKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Flexible Width x Fibonacci x UIntXL +//*============================================================================* + +final class NBKFlexibleWidthTestsOnFibonacciAsUIntXL: XCTestCase { + + typealias T = UIntXL + typealias M = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testStartSequence() { + NBKAssertFibonacciSequenceElement(0 as Int, 0 as T) + NBKAssertFibonacciSequenceElement(1 as Int, 1 as T) + NBKAssertFibonacciSequenceElement(2 as Int, 1 as T) + NBKAssertFibonacciSequenceElement(3 as Int, 2 as T) + NBKAssertFibonacciSequenceElement(4 as Int, 3 as T) + NBKAssertFibonacciSequenceElement(5 as Int, 5 as T) + } + + func testEachElementInUInt256() { + self.continueAfterFailure = false + var fibonacci = (index: 0 as Int, element: 0 as T, next: 1 as T) + while fibonacci.element.bitWidth <= 256 { + NBKAssertFibonacciSequenceElement(fibonacci.index, fibonacci.element) + fibonacci.index += 1 + fibonacci.element += fibonacci.next + Swift.swap(&fibonacci.element, &fibonacci.next) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Miscellaneous + //=------------------------------------------------------------------------= + + func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { + func becauseThisCompilesSuccessfully(_ x: inout T) { + XCTAssertNotNil(T.fibonacci(0)) + } + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Fibonacci x UIntXL x Primes +//*============================================================================* + +final class NBKFlexibleWidthTestsOnFibonacciByPrimesAsUIntXL: XCTestCase { + + typealias T = UIntXL + typealias M = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + /// https://www.wolframalpha.com/input?i2d=true&i=fibonnaci+1399 + func testPrime222() { + NBKAssertFibonacciSequenceElement(Int(1399), T(""" + 0000000000000000000000000001057362022138877586442790693627392471\ + 4349424343122542609372806319825783387389898145491654340696207977\ + 9703100859330541842708747836587076026853149515123668038994257349\ + 6825711057526259113835863240488302877201171798455616630015796594\ + 0742927387906176446848324713233936084752836275187153808643885101 + """)) + } + + /// https://www.wolframalpha.com/input?i2d=true&i=fibonnaci+2239 + func testPrime333() { + NBKAssertFibonacciSequenceElement(Int(2239), T(""" + 0000000000000000000000000000000000000000000037483619230023616383\ + 1556956012890801755635223834456440078068598512042225565858378705\ + 2775478508439311765008270803174379457823903626436917896144175108\ + 1812500769712739265577812142790633886426904029644292656072176594\ + 5442661544462371162680745392064002681693236118751836449122772276\ + 7869284859173664595855541705821814253059049650198752630703006217\ + 8339242653834274827433371972683579086589883072059016299647032544\ + 7184786711538554743189201957494849217103385151192357985565557661 + """)) + } + + /// https://www.wolframalpha.com/input?i2d=true&i=fibonnaci+4019 + func testPrime555() { + NBKAssertFibonacciSequenceElement(Int(4019), T(""" + 0000000000000000000000000000000000000000000000000000000037311367\ + 1412705742029424968910639277549742521996080310155045098365714482\ + 4104908347036042361244599159615512769990330987960639730865498130\ + 8072433775788325161992682362256795449665494209753670942172171272\ + 2203967369999425701889153758837814681835559585933723133751806881\ + 8496872580801685513615393162520513116429805804142523379378342551\ + 4441029659216936210529080660370851401177631514342389875828339972\ + 6614842546459415022870946655707302191026328812740600578177639873\ + 3039042717454551010941945840815871118048005931668653125862093108\ + 8958611234123487217337182078176768683790720523395222453566084951\ + 4492498420355556195880899437692737868135183556431736743842980245\ + 8400475635400414549626879469797956177065259238066131421408862659\ + 3874545400735945578330890239131064772372045179036218495472538674\ + 0316671667949438060397052349819774423263628326505983968411352681 + """)) + } + + /// https://www.wolframalpha.com/input?i2d=true&i=fibonnaci+5903 + func testPrime777() { + NBKAssertFibonacciSequenceElement(Int(5903), T(""" + 0000000000000000000000000000000000000000000000201630112973699547\ + 8467033798246231765802235127399927076436839763410065672009048903\ + 1282893541236712535277172854664465524821928062556461511462472243\ + 6645751603027750072868408113686717270843656386576571239706531613\ + 8832607318277041589340170938439083061589073645207050078640037387\ + 3930944738614316892092679585355923400727053939446917720844859420\ + 8475286500719315637423740931654098191825715510224786132537906089\ + 2798464444270756081302801050898869097388615552432632699803372579\ + 5006266664207612795271656344222004200834104891232199115031529879\ + 2703171846839972134549632698690061406266150782100519904238693642\ + 7990494803652598109479923921411786233223630306244612906702729633\ + 0936722357821751129503986058477775784943438980499220967251871125\ + 8907675708863225870261545152179027647035709552484493259087293234\ + 3560027918334679621500613235053762398727366706896356186229959919\ + 9113456220990739086184934440183082123185220867952003388928951448\ + 6862918684679538218518939139423048219131427786458175412165472787\ + 2317940678177228138520687104044551650142781207251510823550422463\ + 0550656054019863500046679727553797345950068888003234780117695468\ + 5001758459948949898864934140668770688345102830949505991111324318\ + 0359205788328847352554207256070124136434254282285393279119106977 + """)) + } +} + +//*============================================================================* +// MARK: * NBK x Flexible Width x Fibonacci x Assertions +//*============================================================================* + +private func NBKAssertFibonacciSequenceElement( +_ index: Int, _ element: UIntXL, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + let result0 = UIntXL.fibonacci(index + 0) + let result1 = UIntXL.fibonacci(index + 1) + //=------------------------------------------= + XCTAssertEqual(result0.element, element, file: file, line: line) + XCTAssertEqual(result0.next, result1.element, file: file, line: line) + XCTAssertEqual(result1.next, result0.element + result0.next, file: file, line: line) +} + +#endif From e1b2058cacb1b29e245f9e1c9a20f5a21f11694c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sat, 4 Nov 2023 10:25:24 +0100 Subject: [PATCH 111/133] [NBKFlexibleWidthKit] FibonacciXL. --- README.md | 4 + .../Models/NBKFibonacciXL.swift | 136 ++++++++++++++++++ .../NBKFlexibleWidth+Fibonacci.swift | 66 --------- ...KFlexibleWidth+Multiplication+Square.swift | 10 +- .../NBKFibonacciXL.swift} | 22 +-- .../NBKFibonacciXL.swift} | 90 ++++++------ 6 files changed, 206 insertions(+), 122 deletions(-) create mode 100644 Sources/NBKFlexibleWidthKit/Models/NBKFibonacciXL.swift delete mode 100644 Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Fibonacci.swift rename Tests/NBKFlexibleWidthKitBenchmarks/{NBKFlexibleWidth+Fibonacci.swift => Models/NBKFibonacciXL.swift} (72%) rename Tests/NBKFlexibleWidthKitTests/{NBKFlexibleWidth+Fibonacci.swift => Models/NBKFibonacciXL.swift} (70%) diff --git a/README.md b/README.md index 73438c93..7ad19622 100644 --- a/README.md +++ b/README.md @@ -119,6 +119,10 @@ Int256(5) % Int(5), UInt256(5) % UInt(5) 👨‍💻🛠️🚧🧱🧱🏗️🧱🧱🚧⏳ +### Models + +- [NBKFibonacciXL](Sources/NBKFlexibleWidthKit/Models/NBKFibonacciXL.swift) + ## Installation diff --git a/Sources/NBKFlexibleWidthKit/Models/NBKFibonacciXL.swift b/Sources/NBKFlexibleWidthKit/Models/NBKFibonacciXL.swift new file mode 100644 index 00000000..5914aca7 --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/Models/NBKFibonacciXL.swift @@ -0,0 +1,136 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x FibonacciXL +//*============================================================================* + +/// The [Fibonacci sequence](https://en.wikipedia.org/wiki/fibonacci_sequence). +/// +/// It is represented by an index and two consecutive elements. +/// +/// ```swift +/// NBKFibonacciXL(0) // (index: 0, element: 0, next: 1) +/// NBKFibonacciXL(1) // (index: 1, element: 1, next: 1) +/// NBKFibonacciXL(2) // (index: 2, element: 1, next: 2) +/// NBKFibonacciXL(3) // (index: 3, element: 2, next: 3) +/// NBKFibonacciXL(4) // (index: 4, element: 3, next: 5) +/// NBKFibonacciXL(5) // (index: 5, element: 5, next: 8) +/// ``` +/// +/// ### Development +/// +/// Sequences like these are useful for testing large integer values. +/// +@frozen public struct NBKFibonacciXL { + + //=------------------------------------------------------------------------= + // MARK: State + //=------------------------------------------------------------------------= + + @usableFromInline var i: UInt + @usableFromInline var a: UIntXL + @usableFromInline var b: UIntXL + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + /// Returns the start sequence. + /// + /// ``` + /// (index: 0, element: 0, next: 1) + /// ``` + /// + @inlinable public init() { + self.i = UInt() + self.a = UIntXL(digit: 0) + self.b = UIntXL(digit: 1) + } + + /// Returns the sequence at the given `index`. + /// + /// ```swift + /// UIntXL.Fibonacci(0) // (index: 0, element: 0, next: 1) + /// UIntXL.Fibonacci(1) // (index: 1, element: 1, next: 1) + /// UIntXL.Fibonacci(2) // (index: 2, element: 1, next: 2) + /// UIntXL.Fibonacci(3) // (index: 3, element: 2, next: 3) + /// UIntXL.Fibonacci(4) // (index: 4, element: 3, next: 5) + /// UIntXL.Fibonacci(5) // (index: 5, element: 5, next: 8) + /// ``` + /// + @inlinable public init(_ index: UInt) { + self.i = index as UInt + self.a = UIntXL(digit: 0) + self.b = UIntXL(digit: 1) + + var mask = UInt.one &<< (index.bitWidth &+ index.leadingZeroBitCount.onesComplement()) + doubleAndAdd: while !mask.isZero { + + var (x): UIntXL // f(2x + 0) + x = b.bitShiftedLeft(major: Int.zero, minor: Int.one) + x -= a + x *= a + + var (y): UIntXL // f(2x + 1) + y = a.squared() + y += b.squared() + + if (index & mask).isZero { + a = x + b = y + } else { + x += y + a = y + b = x + } + + mask &>>= UInt.one + } + } + + //=------------------------------------------------------------------------= + // MARK: Accessors + //=------------------------------------------------------------------------= + + /// The sequence `index`. + @inlinable public var index: UInt { + self.i + } + + /// The sequence `element` at `index`. + @inlinable public var element: UIntXL { + self.a + } + + /// The sequence `element` at `index + 1`. + @inlinable public var next: UIntXL { + self.b + } + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + /// Forms the sequence pair before this instance. + public mutating func decrement() { + self.i -= 1 + self.b -= a + Swift.swap(&a, &b) + } + + /// Forms the sequence pair after this instance. + public mutating func increment() { + self.i += 1 + self.a += b + Swift.swap(&a, &b) + } +} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Fibonacci.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Fibonacci.swift deleted file mode 100644 index 6cf2580b..00000000 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Fibonacci.swift +++ /dev/null @@ -1,66 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -//*============================================================================* -// MARK: * NBK x Flexible Width x Fibonacci x Unsigned -//*============================================================================* - -extension NBKFlexibleWidth.Magnitude { - - //=------------------------------------------------------------------------= - // MARK: Utilities - //=------------------------------------------------------------------------= - - /// Returns the Fibonacci sequence pair at `index`. - /// - /// ```swift - /// UIntXL.fibonacci(0) // (element: 0, next: 1) - /// UIntXL.fibonacci(1) // (element: 1, next: 1) - /// UIntXL.fibonacci(2) // (element: 1, next: 2) - /// UIntXL.fibonacci(3) // (element: 2, next: 3) - /// UIntXL.fibonacci(4) // (element: 3, next: 5) - /// UIntXL.fibonacci(5) // (element: 5, next: 8) - /// ``` - /// - /// - Parameter index: A value greater than zero. - /// - public static func fibonacci(_ index: Int) -> (element: Self, next: Self) { - //=--------------------------------------= - // f(2x + 0) = f(x) * [2 * f(x + 1) - f(x)] - // f(2x + 1) = f(x) ^ 2 + f(x + 1) ^ 2 - //=--------------------------------------= - precondition(index >= Int.zero) - //=--------------------------------------= - var a: Self = Self(digit: 0) - var b: Self = Self(digit: 1) - //=--------------------------------------= - for bitIndex in (0 ..< Int.bitWidth - index.leadingZeroBitCount).reversed() { - - var (x): Self // f(2x + 0) - x = b.bitShiftedLeft(major: Int.zero, minor: Int.one) - x -= a - x *= a - - var (y): Self // f(2x + 1) - y = a.squared() - y += b.squared() - - if (index &>> bitIndex).isOdd { - x += y - a = y - b = x - } else { - a = x - b = y - } - } - - return (element: a as Self, next: b as Self) - } -} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Square.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Square.swift index 07d8c64d..42bf042e 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Square.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Square.swift @@ -50,7 +50,7 @@ extension NBKFlexibleWidth.Magnitude { //=--------------------------= product.initialize(repeating: 0 as UInt) //=--------------------------= - var index: Int = 000000 + var index: Int var carry: UInt = addend //=--------------------------= var baseIndex = base.startIndex; while baseIndex < base.endIndex { @@ -60,15 +60,15 @@ extension NBKFlexibleWidth.Magnitude { index = productIndex + 1 // add non-diagonal products - NBK.SUISS.incrementInIntersection(&product, - by: UnsafeBufferPointer(rebasing: base[baseIndex...]), + NBK.SUISS.incrementInIntersection( + &product, by: UnsafeBufferPointer(rebasing: base[baseIndex...]), times: multiplier, plus: 00000, at: &index) index = productIndex // partially double non-diagonal products NBK.SUISS.multiply( - &product, by: 00002, - add: &carry, from: &index, to: productIndex + 2) + &product, by: 0002, + add: &carry, from: &index, to: productIndex + 2) index = productIndex // add this iteration's diagonal product diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Fibonacci.swift b/Tests/NBKFlexibleWidthKitBenchmarks/Models/NBKFibonacciXL.swift similarity index 72% rename from Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Fibonacci.swift rename to Tests/NBKFlexibleWidthKitBenchmarks/Models/NBKFibonacciXL.swift index 524f84d6..4220111a 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Fibonacci.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/Models/NBKFibonacciXL.swift @@ -18,49 +18,49 @@ private typealias X = [UInt64] private typealias Y = [UInt32] //*============================================================================* -// MARK: * NBK x Flexible Width x Fibonacci x UIntXL +// MARK: * NBK x FibonacciXL //*============================================================================* -final class NBKFlexibleWidthBenchmarksOnFibonacciAsUIntXL: XCTestCase { +final class NBKFibonacciXLBenchmarks: XCTestCase { - typealias T = UIntXL + typealias T = NBKFibonacciXL //=------------------------------------------------------------------------= // MARK: Tests //=------------------------------------------------------------------------= func testPrime222() { - var index = NBK.blackHoleIdentity(Int(1399)) + var index = NBK.blackHoleIdentity(UInt(1399)) for _ in 0 ..< 10_000 { - NBK.blackHole(T.fibonacci(index)) + NBK.blackHole(T(index)) NBK.blackHoleInoutIdentity(&index) } } func testPrime333() { - var index = NBK.blackHoleIdentity(Int(2239)) + var index = NBK.blackHoleIdentity(UInt(2239)) for _ in 0 ..< 10_000 { - NBK.blackHole(T.fibonacci(index)) + NBK.blackHole(T(index)) NBK.blackHoleInoutIdentity(&index) } } func testPrime555() { - var index = NBK.blackHoleIdentity(Int(4019)) + var index = NBK.blackHoleIdentity(UInt(4019)) for _ in 0 ..< 10_000 { - NBK.blackHole(T.fibonacci(index)) + NBK.blackHole(T(index)) NBK.blackHoleInoutIdentity(&index) } } func testPrime777() { - var index = NBK.blackHoleIdentity(Int(5903)) + var index = NBK.blackHoleIdentity(UInt(5903)) for _ in 0 ..< 10_000 { - NBK.blackHole(T.fibonacci(index)) + NBK.blackHole(T(index)) NBK.blackHoleInoutIdentity(&index) } } diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Fibonacci.swift b/Tests/NBKFlexibleWidthKitTests/Models/NBKFibonacciXL.swift similarity index 70% rename from Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Fibonacci.swift rename to Tests/NBKFlexibleWidthKitTests/Models/NBKFibonacciXL.swift index 5d930841..6fa4fe62 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Fibonacci.swift +++ b/Tests/NBKFlexibleWidthKitTests/Models/NBKFibonacciXL.swift @@ -18,57 +18,53 @@ private typealias X = [UInt64] private typealias Y = [UInt32] //*============================================================================* -// MARK: * NBK x Flexible Width x Fibonacci x UIntXL +// MARK: * NBK x FibonacciXL //*============================================================================* -final class NBKFlexibleWidthTestsOnFibonacciAsUIntXL: XCTestCase { +final class NBKFibonacciXLTests: XCTestCase { - typealias T = UIntXL - typealias M = UIntXL + typealias T = NBKFibonacciXL //=------------------------------------------------------------------------= // MARK: Tests //=------------------------------------------------------------------------= + func testInit() { + XCTAssertEqual(T().index, 0 as UInt) + XCTAssertEqual(T().element, 0 as UIntXL) + XCTAssertEqual(T().next, 1 as UIntXL) + } + func testStartSequence() { - NBKAssertFibonacciSequenceElement(0 as Int, 0 as T) - NBKAssertFibonacciSequenceElement(1 as Int, 1 as T) - NBKAssertFibonacciSequenceElement(2 as Int, 1 as T) - NBKAssertFibonacciSequenceElement(3 as Int, 2 as T) - NBKAssertFibonacciSequenceElement(4 as Int, 3 as T) - NBKAssertFibonacciSequenceElement(5 as Int, 5 as T) + NBKAssertFibonacciSequenceElement(0 as UInt, 0 as UIntXL) + NBKAssertFibonacciSequenceElement(1 as UInt, 1 as UIntXL) + NBKAssertFibonacciSequenceElement(2 as UInt, 1 as UIntXL) + NBKAssertFibonacciSequenceElement(3 as UInt, 2 as UIntXL) + NBKAssertFibonacciSequenceElement(4 as UInt, 3 as UIntXL) + NBKAssertFibonacciSequenceElement(5 as UInt, 5 as UIntXL) } func testEachElementInUInt256() { self.continueAfterFailure = false - var fibonacci = (index: 0 as Int, element: 0 as T, next: 1 as T) - while fibonacci.element.bitWidth <= 256 { + + var fibonacci = T(); while fibonacci.next.bitWidth <= 256 { NBKAssertFibonacciSequenceElement(fibonacci.index, fibonacci.element) - fibonacci.index += 1 - fibonacci.element += fibonacci.next - Swift.swap(&fibonacci.element, &fibonacci.next) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Miscellaneous - //=------------------------------------------------------------------------= - - func testOverloadsAreUnambiguousWhenUsingIntegerLiterals() { - func becauseThisCompilesSuccessfully(_ x: inout T) { - XCTAssertNotNil(T.fibonacci(0)) + fibonacci.increment() } + + XCTAssertEqual(fibonacci.index, 370 as UInt) + XCTAssertEqual(fibonacci.element, UIntXL("094611056096305838013295371573764256526437182762229865607320618320601813254535")) + XCTAssertEqual(fibonacci.next, UIntXL("153083904475345790698149223310665389766178449653686710164582374234640876900329")) } } //*============================================================================* -// MARK: * NBK x Flexible Width x Fibonacci x UIntXL x Primes +// MARK: * NBK x FibonacciXL x Primes //*============================================================================* -final class NBKFlexibleWidthTestsOnFibonacciByPrimesAsUIntXL: XCTestCase { +final class NBKFibonacciXLTestsOnPrimes: XCTestCase { - typealias T = UIntXL - typealias M = UIntXL + typealias T = NBKFibonacciXL //=------------------------------------------------------------------------= // MARK: Tests @@ -76,7 +72,7 @@ final class NBKFlexibleWidthTestsOnFibonacciByPrimesAsUIntXL: XCTestCase { /// https://www.wolframalpha.com/input?i2d=true&i=fibonnaci+1399 func testPrime222() { - NBKAssertFibonacciSequenceElement(Int(1399), T(""" + NBKAssertFibonacciSequenceElement(UInt(1399), UIntXL(""" 0000000000000000000000000001057362022138877586442790693627392471\ 4349424343122542609372806319825783387389898145491654340696207977\ 9703100859330541842708747836587076026853149515123668038994257349\ @@ -87,7 +83,7 @@ final class NBKFlexibleWidthTestsOnFibonacciByPrimesAsUIntXL: XCTestCase { /// https://www.wolframalpha.com/input?i2d=true&i=fibonnaci+2239 func testPrime333() { - NBKAssertFibonacciSequenceElement(Int(2239), T(""" + NBKAssertFibonacciSequenceElement(UInt(2239), UIntXL(""" 0000000000000000000000000000000000000000000037483619230023616383\ 1556956012890801755635223834456440078068598512042225565858378705\ 2775478508439311765008270803174379457823903626436917896144175108\ @@ -101,7 +97,7 @@ final class NBKFlexibleWidthTestsOnFibonacciByPrimesAsUIntXL: XCTestCase { /// https://www.wolframalpha.com/input?i2d=true&i=fibonnaci+4019 func testPrime555() { - NBKAssertFibonacciSequenceElement(Int(4019), T(""" + NBKAssertFibonacciSequenceElement(UInt(4019), UIntXL(""" 0000000000000000000000000000000000000000000000000000000037311367\ 1412705742029424968910639277549742521996080310155045098365714482\ 4104908347036042361244599159615512769990330987960639730865498130\ @@ -121,7 +117,7 @@ final class NBKFlexibleWidthTestsOnFibonacciByPrimesAsUIntXL: XCTestCase { /// https://www.wolframalpha.com/input?i2d=true&i=fibonnaci+5903 func testPrime777() { - NBKAssertFibonacciSequenceElement(Int(5903), T(""" + NBKAssertFibonacciSequenceElement(UInt(5903), UIntXL(""" 0000000000000000000000000000000000000000000000201630112973699547\ 8467033798246231765802235127399927076436839763410065672009048903\ 1282893541236712535277172854664465524821928062556461511462472243\ @@ -147,19 +143,33 @@ final class NBKFlexibleWidthTestsOnFibonacciByPrimesAsUIntXL: XCTestCase { } //*============================================================================* -// MARK: * NBK x Flexible Width x Fibonacci x Assertions +// MARK: * NBK x FibonacciXL x Assertions //*============================================================================* private func NBKAssertFibonacciSequenceElement( -_ index: Int, _ element: UIntXL, +_ index: UInt, _ element: UIntXL, file: StaticString = #file, line: UInt = #line) { //=------------------------------------------= - let result0 = UIntXL.fibonacci(index + 0) - let result1 = UIntXL.fibonacci(index + 1) + let x0 = NBKFibonacciXL(index + 0) + let x1 = NBKFibonacciXL(index + 1) + //=------------------------------------------= + XCTAssertEqual(x0.element, element, file: file, line: line) + XCTAssertEqual(x0.next, x1.element, file: file, line: line) + XCTAssertEqual(x1.next, x0.element + x1.element, file: file, line: line) //=------------------------------------------= - XCTAssertEqual(result0.element, element, file: file, line: line) - XCTAssertEqual(result0.next, result1.element, file: file, line: line) - XCTAssertEqual(result1.next, result0.element + result0.next, file: file, line: line) + increment1: do { + var x = x0; x.increment() + XCTAssertEqual(x.index, x1.index, file: file, line: line) + XCTAssertEqual(x.element, x1.element, file: file, line: line) + XCTAssertEqual(x.next, x1.next, file: file, line: line) + } + + decrement1: do { + var x = x1; x.decrement() + XCTAssertEqual(x.index, x0.index, file: file, line: line) + XCTAssertEqual(x.element, x0.element, file: file, line: line) + XCTAssertEqual(x.next, x0.next, file: file, line: line) + } } #endif From 447c5131f70880634e5ebec7901f7dcb3f5c87ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sat, 4 Nov 2023 11:29:07 +0100 Subject: [PATCH 112/133] [NBKFlexibleWidthKit] Cleanup. --- .../Models/NBKFibonacciXL.swift | 29 ++++--------------- 1 file changed, 5 insertions(+), 24 deletions(-) diff --git a/Sources/NBKFlexibleWidthKit/Models/NBKFibonacciXL.swift b/Sources/NBKFlexibleWidthKit/Models/NBKFibonacciXL.swift index 5914aca7..cf30df08 100644 --- a/Sources/NBKFlexibleWidthKit/Models/NBKFibonacciXL.swift +++ b/Sources/NBKFlexibleWidthKit/Models/NBKFibonacciXL.swift @@ -26,10 +26,6 @@ import NBKCoreKit /// NBKFibonacciXL(5) // (index: 5, element: 5, next: 8) /// ``` /// -/// ### Development -/// -/// Sequences like these are useful for testing large integer values. -/// @frozen public struct NBKFibonacciXL { //=------------------------------------------------------------------------= @@ -44,29 +40,14 @@ import NBKCoreKit // MARK: Initializers //=------------------------------------------------------------------------= - /// Returns the start sequence. - /// - /// ``` - /// (index: 0, element: 0, next: 1) - /// ``` - /// + /// Creates the first sequence pair. @inlinable public init() { self.i = UInt() self.a = UIntXL(digit: 0) self.b = UIntXL(digit: 1) } - /// Returns the sequence at the given `index`. - /// - /// ```swift - /// UIntXL.Fibonacci(0) // (index: 0, element: 0, next: 1) - /// UIntXL.Fibonacci(1) // (index: 1, element: 1, next: 1) - /// UIntXL.Fibonacci(2) // (index: 2, element: 1, next: 2) - /// UIntXL.Fibonacci(3) // (index: 3, element: 2, next: 3) - /// UIntXL.Fibonacci(4) // (index: 4, element: 3, next: 5) - /// UIntXL.Fibonacci(5) // (index: 5, element: 5, next: 8) - /// ``` - /// + /// Creates the sequence pair at the given `index`. @inlinable public init(_ index: UInt) { self.i = index as UInt self.a = UIntXL(digit: 0) @@ -84,7 +65,7 @@ import NBKCoreKit y = a.squared() y += b.squared() - if (index & mask).isZero { + if (mask & index).isZero { a = x b = y } else { @@ -121,14 +102,14 @@ import NBKCoreKit //=------------------------------------------------------------------------= /// Forms the sequence pair before this instance. - public mutating func decrement() { + @inlinable public mutating func decrement() { self.i -= 1 self.b -= a Swift.swap(&a, &b) } /// Forms the sequence pair after this instance. - public mutating func increment() { + @inlinable public mutating func increment() { self.i += 1 self.a += b Swift.swap(&a, &b) From 974815218bd2d2e234f2a1fb912b9317372379b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sat, 4 Nov 2023 19:49:13 +0100 Subject: [PATCH 113/133] [NBKFlexibleWidthKit] Cleanup. --- .swiftpm/NBKFlexibleWidthKit-Benchmarks.xctestplan | 1 + .swiftpm/Numberick-Benchmarks.xctestplan | 1 + Sources/NBKFlexibleWidthKit/Models/NBKFibonacciXL.swift | 8 ++++---- .../Models/NBKFibonacciXL.swift | 9 +++++++++ .../NBKFlexibleWidthKitTests/Models/NBKFibonacciXL.swift | 2 +- 5 files changed, 16 insertions(+), 5 deletions(-) diff --git a/.swiftpm/NBKFlexibleWidthKit-Benchmarks.xctestplan b/.swiftpm/NBKFlexibleWidthKit-Benchmarks.xctestplan index e2741ab4..87bb9b37 100644 --- a/.swiftpm/NBKFlexibleWidthKit-Benchmarks.xctestplan +++ b/.swiftpm/NBKFlexibleWidthKit-Benchmarks.xctestplan @@ -14,6 +14,7 @@ "testTargets" : [ { "skippedTests" : [ + "NBKFibonacciXLBenchmarks\/testNoLoop100000()", "NBKFlexibleWidthBenchmarksOnExponentiationAsUIntXL\/test7RaisedToPrime777()", "NBKFlexibleWidthBenchmarksOnTextAsUIntXL\/testEncodingUsingSwiftStdlibRadix10()", "NBKFlexibleWidthBenchmarksOnTextAsUIntXL\/testEncodingUsingSwiftStdlibRadix16()" diff --git a/.swiftpm/Numberick-Benchmarks.xctestplan b/.swiftpm/Numberick-Benchmarks.xctestplan index d26698ab..f563ee43 100644 --- a/.swiftpm/Numberick-Benchmarks.xctestplan +++ b/.swiftpm/Numberick-Benchmarks.xctestplan @@ -38,6 +38,7 @@ }, { "skippedTests" : [ + "NBKFibonacciXLBenchmarks\/testNoLoop1000000()", "NBKFlexibleWidthBenchmarksOnExponentiationAsUIntXL\/test7RaisedToPrime777()" ], "target" : { diff --git a/Sources/NBKFlexibleWidthKit/Models/NBKFibonacciXL.swift b/Sources/NBKFlexibleWidthKit/Models/NBKFibonacciXL.swift index cf30df08..7603a17a 100644 --- a/Sources/NBKFlexibleWidthKit/Models/NBKFibonacciXL.swift +++ b/Sources/NBKFlexibleWidthKit/Models/NBKFibonacciXL.swift @@ -13,7 +13,7 @@ import NBKCoreKit // MARK: * NBK x FibonacciXL //*============================================================================* -/// The [Fibonacci sequence](https://en.wikipedia.org/wiki/fibonacci_sequence). +/// The [Fibonacci sequence](https://en.wikipedia.org/wiki/fibonacci_sequence)\. /// /// It is represented by an index and two consecutive elements. /// @@ -53,7 +53,7 @@ import NBKCoreKit self.a = UIntXL(digit: 0) self.b = UIntXL(digit: 1) - var mask = UInt.one &<< (index.bitWidth &+ index.leadingZeroBitCount.onesComplement()) + var mask = UInt.one &<< UInt(bitPattern: index.bitWidth &+ index.leadingZeroBitCount.onesComplement()) doubleAndAdd: while !mask.isZero { var (x): UIntXL // f(2x + 0) @@ -101,14 +101,14 @@ import NBKCoreKit // MARK: Transformations //=------------------------------------------------------------------------= - /// Forms the sequence pair before this instance. + /// Forms the sequence pair at `index - 1`. @inlinable public mutating func decrement() { self.i -= 1 self.b -= a Swift.swap(&a, &b) } - /// Forms the sequence pair after this instance. + /// Forms the sequence pair at `index + 1`. @inlinable public mutating func increment() { self.i += 1 self.a += b diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/Models/NBKFibonacciXL.swift b/Tests/NBKFlexibleWidthKitBenchmarks/Models/NBKFibonacciXL.swift index 4220111a..9e52889b 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/Models/NBKFibonacciXL.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/Models/NBKFibonacciXL.swift @@ -64,6 +64,15 @@ final class NBKFibonacciXLBenchmarks: XCTestCase { NBK.blackHoleInoutIdentity(&index) } } + + //=------------------------------------------------------------------------= + // MARK: Tests x No Loop + //=------------------------------------------------------------------------= + + /// The 1,000,000th element has 208,988 decimal digits. + func testNoLoop1000000() { + NBK.blackHole(T(NBK.blackHoleIdentity(UInt(1_000_000)))) + } } #endif diff --git a/Tests/NBKFlexibleWidthKitTests/Models/NBKFibonacciXL.swift b/Tests/NBKFlexibleWidthKitTests/Models/NBKFibonacciXL.swift index 6fa4fe62..cbaa492f 100644 --- a/Tests/NBKFlexibleWidthKitTests/Models/NBKFibonacciXL.swift +++ b/Tests/NBKFlexibleWidthKitTests/Models/NBKFibonacciXL.swift @@ -47,7 +47,7 @@ final class NBKFibonacciXLTests: XCTestCase { func testEachElementInUInt256() { self.continueAfterFailure = false - var fibonacci = T(); while fibonacci.next.bitWidth <= 256 { + var fibonacci = T(); while fibonacci.next.bitWidth <= 256 { NBKAssertFibonacciSequenceElement(fibonacci.index, fibonacci.element) fibonacci.increment() } From 1c3770dc6da9a99b98ceaa6428406e5fb6c0111e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sun, 5 Nov 2023 14:48:45 +0100 Subject: [PATCH 114/133] Big integer Karatsuba algorithm (#108). --- .../NBKFlexibleWidthKit-Benchmarks.xctestplan | 6 +- .swiftpm/Numberick-Benchmarks.xctestplan | 8 +- ...exibleWidth+Multiplication+Karatsuba.swift | 155 ++++++++++++++++++ ...BKFlexibleWidth+Multiplication+Long.swift} | 52 ++++-- .../NBKFlexibleWidth+Multiplication.swift | 65 +++----- .../Models/NBKFibonacciXL.swift | 9 +- .../NBKFlexibleWidth+Exponentiation.swift | 28 ++++ .../NBKFlexibleWidth+Multiplication.swift | 44 ++++- 8 files changed, 294 insertions(+), 73 deletions(-) create mode 100644 Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Karatsuba.swift rename Sources/NBKFlexibleWidthKit/{NBKFlexibleWidth+Multiplication+Square.swift => NBKFlexibleWidth+Multiplication+Long.swift} (58%) diff --git a/.swiftpm/NBKFlexibleWidthKit-Benchmarks.xctestplan b/.swiftpm/NBKFlexibleWidthKit-Benchmarks.xctestplan index 87bb9b37..6e96461d 100644 --- a/.swiftpm/NBKFlexibleWidthKit-Benchmarks.xctestplan +++ b/.swiftpm/NBKFlexibleWidthKit-Benchmarks.xctestplan @@ -14,8 +14,12 @@ "testTargets" : [ { "skippedTests" : [ - "NBKFibonacciXLBenchmarks\/testNoLoop100000()", + "NBKFibonacciXLBenchmarks\/testNoLoop10000000()", "NBKFlexibleWidthBenchmarksOnExponentiationAsUIntXL\/test7RaisedToPrime777()", + "NBKFlexibleWidthBenchmarksOnExponentiationAsUIntXL\/testNoLoop5RaisedToPrime22222()", + "NBKFlexibleWidthBenchmarksOnExponentiationAsUIntXL\/testNoLoop5RaisedToPrime33333()", + "NBKFlexibleWidthBenchmarksOnExponentiationAsUIntXL\/testNoLoop5RaisedToPrime55555()", + "NBKFlexibleWidthBenchmarksOnExponentiationAsUIntXL\/testNoLoop7RaisedToPrime77777()", "NBKFlexibleWidthBenchmarksOnTextAsUIntXL\/testEncodingUsingSwiftStdlibRadix10()", "NBKFlexibleWidthBenchmarksOnTextAsUIntXL\/testEncodingUsingSwiftStdlibRadix16()" ], diff --git a/.swiftpm/Numberick-Benchmarks.xctestplan b/.swiftpm/Numberick-Benchmarks.xctestplan index f563ee43..1d5524af 100644 --- a/.swiftpm/Numberick-Benchmarks.xctestplan +++ b/.swiftpm/Numberick-Benchmarks.xctestplan @@ -38,8 +38,12 @@ }, { "skippedTests" : [ - "NBKFibonacciXLBenchmarks\/testNoLoop1000000()", - "NBKFlexibleWidthBenchmarksOnExponentiationAsUIntXL\/test7RaisedToPrime777()" + "NBKFibonacciXLBenchmarks\/testNoLoop10000000()", + "NBKFlexibleWidthBenchmarksOnExponentiationAsUIntXL\/test7RaisedToPrime777()", + "NBKFlexibleWidthBenchmarksOnExponentiationAsUIntXL\/testNoLoop5RaisedToPrime22222()", + "NBKFlexibleWidthBenchmarksOnExponentiationAsUIntXL\/testNoLoop5RaisedToPrime33333()", + "NBKFlexibleWidthBenchmarksOnExponentiationAsUIntXL\/testNoLoop5RaisedToPrime55555()", + "NBKFlexibleWidthBenchmarksOnExponentiationAsUIntXL\/testNoLoop7RaisedToPrime77777()" ], "target" : { "containerPath" : "container:", diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Karatsuba.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Karatsuba.swift new file mode 100644 index 00000000..2bbb7c0f --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Karatsuba.swift @@ -0,0 +1,155 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Flexible Width x Multiplication x Karatsuba x Unsigned +//*============================================================================* + +extension NBKFlexibleWidth.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + /// Returns the product of `lhs` and `rhs` using [the Karatsuba algorithm]( + /// https://en.wikipedia.org/wiki/karatsuba_algorithm). + /// + /// high low + /// ┌───────────┴───────────┬───────────┴───────────┐ + /// │ x1 * y1 │ x0 * y0 │ + /// └───────────┬───────────┴───────────┬───────────┘ + /// add │ (x1 + x0) * (y1 + y0) │ + /// ├───────────────────────┤ + /// sub │ x0 * y0 │ + /// ├───────────────────────┤ + /// sub │ x1 * y1 │ + /// └───────────────────────┘ + /// + @inlinable static func productByKaratsubaAlgorithm(multiplying lhs: UIntXL, by rhs: UIntXL) -> UIntXL { + let k0 = Swift.max(lhs.count, rhs.count) + let k1 = k0 &>> 1 &+ k0 & 1 + + let x0 = k1 < lhs.count ? UIntXL(words: lhs.words.prefix(upTo: k1)) : lhs + var x1 = k1 < lhs.count ? UIntXL(words: lhs.words.suffix(from: k1)) : UIntXL() + let y0 = k1 < rhs.count ? UIntXL(words: rhs.words.prefix(upTo: k1)) : rhs + var y1 = k1 < rhs.count ? UIntXL(words: rhs.words.suffix(from: k1)) : UIntXL() + + let z0 = x0 * y0 + let z2 = x1 * y1 + + x1 += x0 + y1 += y0 + var z1 = x1 * y1 + z1 -= z0 + z1 -= z2 + + return Self.uninitialized(count: k1 * 4) { product in + z0.withUnsafeBufferPointer { z0 in + z1.withUnsafeBufferPointer { z1 in + z2.withUnsafeBufferPointer { z2 in + //=----------------------------------= + // pointee: initialization + //=----------------------------------= + product.initialize(repeating: 0 as UInt) + //=----------------------------------= + var index: Int, carry: Bool + + index = 0 + carry = false + + NBK.SUISS.increment(&product, by: z0, plus: &carry, at: &index) + + index = k1 &<< 1 + carry = false + + NBK.SUISS.increment(&product, by: z2, plus: &carry, at: &index) + + index = k1 + carry = false + + NBK.SUISS.increment(&product, by: z1, plus: &carry, at: &index) + }}}} + } + + //=------------------------------------------------------------------------= + // MARK: Transformations x Square + //=------------------------------------------------------------------------= + + /// Returns the square product of `base` by using [the Karatsuba algorithm]( + /// https://en.wikipedia.org/wiki/karatsuba_algorithm). + /// + /// high low + /// ┌───────────┴───────────┬───────────┴───────────┐ + /// │ x1 * x1 │ x0 * x0 │ + /// └───────────┬───────────┴───────────┬───────────┘ + /// add │ x0 * x0 │ + /// ├───────────────────────┤ + /// add │ x1 * x1 │ + /// ├───────────────────────┤ + /// sub │ |x1 - x0| * |x1 - x0| │ + /// └───────────────────────┘ + /// + @inlinable static func productBySquareKaratsubaAlgorithm(multiplying base: UIntXL) -> UIntXL { + let k1 = base.count &>> 1 &+ base.count & 1 + + var x0 = UIntXL(words: base.words.prefix(upTo: k1)) + var x1 = UIntXL(words: base.words.suffix(from: k1)) + + let z0 = x0.squared() + let z2 = x1.squared() + + var z1: Self + if x1 >= x0 { + x1 -= x0 + z1 = x1 + } else { + x0 -= x1 + z1 = x0 + }; z1.square() + + return Self.uninitialized(count: k1 * 4) { product in + z0.withUnsafeBufferPointer { z0 in + z1.withUnsafeBufferPointer { z1 in + z2.withUnsafeBufferPointer { z2 in + //=----------------------------------= + // pointee: initialization + //=----------------------------------= + product.initialize(repeating: 0 as UInt) + //=----------------------------------= + var index: Int, carry: Bool + + index = 0 + carry = false + + NBK.SUISS.incrementInIntersection(&product, by: z0, plus: &carry, at: &index) + + index = k1 &<< 1 + carry = false + + NBK.SUISS.incrementInIntersection(&product, by: z2, plus: &carry, at: &index) + + index = k1 + carry = false + + NBK.SUISS.increment(&product, by: z0, plus: &carry, at: &index) + + index = k1 + carry = false + + NBK.SUISS.increment(&product, by: z2, plus: &carry, at: &index) + + index = k1 + carry = false + + NBK.SUISS.decrement(&product, by: z1, plus: &carry, at: &index) + }}}} + } +} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Square.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Long.swift similarity index 58% rename from Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Square.swift rename to Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Long.swift index 42bf042e..db5589d2 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Square.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Long.swift @@ -10,7 +10,7 @@ import NBKCoreKit //*============================================================================* -// MARK: * NBK x Flexible Width x Multiplication x Square x Unsigned +// MARK: * NBK x Flexible Width x Multiplication x Long x Unsigned //*============================================================================* extension NBKFlexibleWidth.Magnitude { @@ -19,23 +19,45 @@ extension NBKFlexibleWidth.Magnitude { // MARK: Transformations //=------------------------------------------------------------------------= - @inlinable public mutating func square() { - self = self.squared() - } - - @inlinable public func squared() -> Self { - Self.productBySquareLongAlgorithm(multiplying: self, adding: 0 as UInt) + /// Returns the product of `multiplicand` and `multiplier` plus `addend` by performing long multiplication. + @inlinable static func productByLongAlgorithm(multiplying multiplicand: Self, by multiplier: Self, adding addend: UInt) -> Self { + Self.uninitialized(count: multiplicand.count + multiplier.count) { pro in + multiplicand.storage.withUnsafeBufferPointer { lhs in + multiplier.storage.withUnsafeBufferPointer { rhs in + var pointer = pro.baseAddress! + //=--------------------------= + // pointee: initialization 1 + //=--------------------------= + var carry: UInt = addend + let first: UInt = rhs.first! + + for element in lhs { + var wide = element.multipliedFullWidth(by: first) as NBK.Wide2 + carry = UInt(bit: wide.low.addReportingOverflow(carry)) &+ wide.high + pointer.initialize(to: wide.low) // done, pointee has no prior value + pointer = pointer.successor() + } + + pointer.initialize(to: carry) + pointer = pointer.successor() + Swift.assert(pro.baseAddress!.distance(to: pointer) == lhs.count + 1) + //=--------------------------= + // pointee: initialization 2 + //=--------------------------= + for var index in 1 ..< rhs.count { + pointer.initialize(to: 00000) + pointer = pointer.successor() + NBK.SUISS.incrementInIntersection(&pro, by: lhs, times: rhs[index], plus: 00000, at: &index) + } + + Swift.assert(pro.baseAddress!.distance(to: pointer) == pro.count) + } + } + } } -} - -//=----------------------------------------------------------------------------= -// MARK: + Algorithms -//=----------------------------------------------------------------------------= - -extension NBKFlexibleWidth.Magnitude { //=------------------------------------------------------------------------= - // MARK: Transformations x Long Multiplication + // MARK: Transformations x Square //=------------------------------------------------------------------------= /// Returns the square product of `base` by performing long multiplication. diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift index 910e6da8..8108c881 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift @@ -15,6 +15,10 @@ import NBKCoreKit extension NBKFlexibleWidth.Magnitude { + @usableFromInline static let productByKaratsubaAlgorithmThreshold: Int = 40 + + @usableFromInline static let productBySquareKaratsubaAlgorithmThreshold: Int = 40 + //=------------------------------------------------------------------------= // MARK: Transformations //=------------------------------------------------------------------------= @@ -24,54 +28,27 @@ extension NBKFlexibleWidth.Magnitude { } @inlinable public static func *(lhs: Self, rhs: Self) -> Self { - Self.productByLongAlgorithm(multiplying: lhs, by: rhs, adding: 0 as UInt) + if lhs.count < Self.productByKaratsubaAlgorithmThreshold || + rhs.count < Self.productByKaratsubaAlgorithmThreshold { + return self.productByLongAlgorithm(multiplying: lhs, by: rhs, adding: UInt.zero) + } else { + return self.productByKaratsubaAlgorithm(multiplying: lhs, by: rhs) + } } -} - -//=----------------------------------------------------------------------------= -// MARK: + Algorithms -//=----------------------------------------------------------------------------= - -extension NBKFlexibleWidth.Magnitude { - + //=------------------------------------------------------------------------= - // MARK: Transformations x Long Multiplication + // MARK: Transformations x Square //=------------------------------------------------------------------------= - /// Returns the product of `multiplicand` and `multiplier` plus `addend` by performing long multiplication. - @inlinable static func productByLongAlgorithm(multiplying multiplicand: Self, by multiplier: Self, adding addend: UInt) -> Self { - Self.uninitialized(count: multiplicand.count + multiplier.count) { pro in - multiplicand.storage.withUnsafeBufferPointer { lhs in - multiplier.storage.withUnsafeBufferPointer { rhs in - var pointer = pro.baseAddress! - //=--------------------------= - // pointee: initialization 1 - //=--------------------------= - var carry: UInt = addend - let first: UInt = rhs.first! - - for element in lhs { - var wide = element.multipliedFullWidth(by: first) as NBK.Wide2 - carry = UInt(bit: wide.low.addReportingOverflow(carry)) &+ wide.high - pointer.initialize(to: wide.low) // done, pointee has no prior value - pointer = pointer.successor() - } - - pointer.initialize(to: carry) - pointer = pointer.successor() - Swift.assert(pro.baseAddress!.distance(to: pointer) == lhs.count + 1) - //=--------------------------= - // pointee: initialization 2 - //=--------------------------= - for var index in 1 ..< rhs.count { - pointer.initialize(to: 00000) - pointer = pointer.successor() - NBK.SUISS.incrementInIntersection(&pro, by: lhs, times: rhs[index], plus: 00000, at: &index) - } - - Swift.assert(pro.baseAddress!.distance(to: pointer) == pro.count) - } - } + @inlinable public mutating func square() { + self = self.squared() + } + + @inlinable public func squared() -> Self { + if self.count < Self.productBySquareKaratsubaAlgorithmThreshold { + return Self.productBySquareLongAlgorithm(multiplying: self, adding: UInt.zero) + } else { + return Self.productBySquareKaratsubaAlgorithm(multiplying: self) } } } diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/Models/NBKFibonacciXL.swift b/Tests/NBKFlexibleWidthKitBenchmarks/Models/NBKFibonacciXL.swift index 9e52889b..9d61ebae 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/Models/NBKFibonacciXL.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/Models/NBKFibonacciXL.swift @@ -69,9 +69,12 @@ final class NBKFibonacciXLBenchmarks: XCTestCase { // MARK: Tests x No Loop //=------------------------------------------------------------------------= - /// The 1,000,000th element has 208,988 decimal digits. - func testNoLoop1000000() { - NBK.blackHole(T(NBK.blackHoleIdentity(UInt(1_000_000)))) + /// https://www.wolframalpha.com/input?i2d=true&i=fibonacci+10000000 + /// + /// - Note: The 10,000,000th element contains 2,089,877 decimal digits. + /// + func testNoLoop10000000() { + NBK.blackHole(T(NBK.blackHoleIdentity(UInt(10_000_000)))) } } diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Exponentiation.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Exponentiation.swift index 5557f1e5..543ac1c7 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Exponentiation.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Exponentiation.swift @@ -72,6 +72,34 @@ final class NBKFlexibleWidthBenchmarksOnExponentiationAsUIntXL: XCTestCase { NBK.blackHoleInoutIdentity(&exponent) } } + + //=------------------------------------------------------------------------= + // MARK: Tests x No Loop + //=------------------------------------------------------------------------= + + func testNoLoop5RaisedToPrime22222() { + let base: T = NBK.blackHoleIdentity(T(000002)) + let exponent = NBK.blackHoleIdentity(Int(252233)) + NBK.blackHole(base.power(exponent)) + } + + func testNoLoop5RaisedToPrime33333() { + let base: T = NBK.blackHoleIdentity(T(000003)) + let exponent = NBK.blackHoleIdentity(Int(393191)) + NBK.blackHole(base.power(exponent)) + } + + func testNoLoop5RaisedToPrime55555() { + let base: T = NBK.blackHoleIdentity(T(000005)) + let exponent = NBK.blackHoleIdentity(Int(686671)) + NBK.blackHole(base.power(exponent)) + } + + func testNoLoop7RaisedToPrime77777() { + let base: T = NBK.blackHoleIdentity(T(000007)) + let exponent = NBK.blackHoleIdentity(Int(989999)) + NBK.blackHole(base.power(exponent)) + } } #endif diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Multiplication.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Multiplication.swift index 1bb6a67d..c22f25a6 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Multiplication.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Multiplication.swift @@ -104,10 +104,20 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual( lhs * rhs, product, file: file, line: line) XCTAssertEqual({ var lhs = lhs; lhs *= rhs; return lhs }(), product, file: file, line: line) //=------------------------------------------= - guard let lhs = lhs as? UIntXL, let rhs = rhs as? UIntXL, let product = product as? UIntXL else { return } + guard let lhs = lhs as? UIntXL, let rhs = rhs as? UIntXL, let product = product as? UIntXL else { + return precondition(T.isSigned) + } //=------------------------------------------= - XCTAssertEqual(UIntXL.productByLongAlgorithm(multiplying: lhs, by: rhs, adding: 00000000), product, file: file, line: line) - XCTAssertEqual(UIntXL.productByLongAlgorithm(multiplying: lhs, by: rhs, adding: UInt.max), product + UInt.max, file: file, line: line) + long: do { + let algorithm = UIntXL.productByLongAlgorithm(multiplying:by:adding:) + XCTAssertEqual(algorithm(lhs, rhs, 00000000), product, file: file, line: line) + XCTAssertEqual(algorithm(lhs, rhs, UInt.max), product + UInt.max, file: file, line: line) + } + + karatsuab: do { + let algorithm = UIntXL.productByKaratsubaAlgorithm(multiplying:by:) + XCTAssertEqual(algorithm(lhs, rhs), product, file: file, line: line) + } } private func NBKAssertMultiplicationByDigit( @@ -129,10 +139,20 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual( base.squared(), product, file: file, line: line) XCTAssertEqual({ var base = base; base.square (); return base }(), product, file: file, line: line) //=------------------------------------------= - guard let base = base as? UIntXL, let product = product as? UIntXL else { return } + guard let base = base as? UIntXL, let product = product as? UIntXL else { + return precondition(T.isSigned) + } //=------------------------------------------= - XCTAssertEqual(UIntXL.productBySquareLongAlgorithm(multiplying: base, adding: 00000000), product, file: file, line: line) - XCTAssertEqual(UIntXL.productBySquareLongAlgorithm(multiplying: base, adding: UInt.max), product + UInt.max, file: file, line: line) + long: do { + let algorithm = UIntXL.productBySquareLongAlgorithm(multiplying:adding:) + XCTAssertEqual(algorithm(base, 00000000), product, file: file, line: line) + XCTAssertEqual(algorithm(base, UInt.max), product + UInt.max, file: file, line: line) + } + + karatsuba: do { + let algorithm = UIntXL.productBySquareKaratsubaAlgorithm(multiplying:) + XCTAssertEqual(algorithm(base), product, file: file, line: line) + } } //=----------------------------------------------------------------------------= @@ -146,8 +166,16 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual(lhs.multiplied(by: rhs, adding: addend), product, file: file, line: line) XCTAssertEqual({ var lhs = lhs; lhs.multiply(by: rhs, add: addend); return lhs }(), product, file: file, line: line) //=------------------------------------------= - XCTAssertEqual(UIntXL.productByLongAlgorithm(multiplying: lhs, by: UIntXL(digit: rhs), adding: addend), product, file: file, line: line) - XCTAssertEqual(UIntXL.productByLongAlgorithm(multiplying: lhs, by: UIntXL(digit: rhs), adding: 000000), product - addend, file: file, line: line) + long: do { + let algorithm = UIntXL.productByLongAlgorithm(multiplying:by:adding:) + XCTAssertEqual(algorithm(lhs, UIntXL(digit: rhs), addend), product, file: file, line: line) + XCTAssertEqual(algorithm(lhs, UIntXL(digit: rhs), 000000), product - addend, file: file, line: line) + } + + karatsuba: do { + let algorithm = UIntXL.productByKaratsubaAlgorithm(multiplying:by:) + XCTAssertEqual(algorithm(lhs, UIntXL(digit: rhs)), product - addend, file: file, line: line) + } } #endif From 7c45651d89f5d020f4671c8f31e93a964cfb5b1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Mon, 6 Nov 2023 16:42:19 +0100 Subject: [PATCH 115/133] Galaxy brain stuff and Karatsuba squares (20+ words) (#108). --- ...exibleWidth+Multiplication+Karatsuba.swift | 155 ----------- ...NBKFlexibleWidth+Multiplication+Long.swift | 104 ------- .../NBKFlexibleWidth+Multiplication.swift | 24 +- .../Private/NBK+Data.swift | 46 ++++ ...gnedInteger+Multiplication+Karatsuba.swift | 259 ++++++++++++++++++ ...tUnsignedInteger+Multiplication+Long.swift | 117 ++++++++ ...StrictUnsignedInteger+Multiplication.swift | 61 +++++ .../NBK+StrictUnsignedInteger+Split.swift | 30 ++ .../Models/NBKFibonacciXL.swift | 2 +- .../NBKFlexibleWidth+Exponentiation.swift | 177 ++++++++++++ .../NBKFlexibleWidth+Multiplication.swift | 45 +-- 11 files changed, 704 insertions(+), 316 deletions(-) delete mode 100644 Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Karatsuba.swift delete mode 100644 Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Long.swift create mode 100644 Sources/NBKFlexibleWidthKit/Private/NBK+Data.swift create mode 100644 Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Multiplication+Karatsuba.swift create mode 100644 Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Multiplication+Long.swift create mode 100644 Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Multiplication.swift create mode 100644 Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Split.swift diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Karatsuba.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Karatsuba.swift deleted file mode 100644 index 2bbb7c0f..00000000 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Karatsuba.swift +++ /dev/null @@ -1,155 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Flexible Width x Multiplication x Karatsuba x Unsigned -//*============================================================================* - -extension NBKFlexibleWidth.Magnitude { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - /// Returns the product of `lhs` and `rhs` using [the Karatsuba algorithm]( - /// https://en.wikipedia.org/wiki/karatsuba_algorithm). - /// - /// high low - /// ┌───────────┴───────────┬───────────┴───────────┐ - /// │ x1 * y1 │ x0 * y0 │ - /// └───────────┬───────────┴───────────┬───────────┘ - /// add │ (x1 + x0) * (y1 + y0) │ - /// ├───────────────────────┤ - /// sub │ x0 * y0 │ - /// ├───────────────────────┤ - /// sub │ x1 * y1 │ - /// └───────────────────────┘ - /// - @inlinable static func productByKaratsubaAlgorithm(multiplying lhs: UIntXL, by rhs: UIntXL) -> UIntXL { - let k0 = Swift.max(lhs.count, rhs.count) - let k1 = k0 &>> 1 &+ k0 & 1 - - let x0 = k1 < lhs.count ? UIntXL(words: lhs.words.prefix(upTo: k1)) : lhs - var x1 = k1 < lhs.count ? UIntXL(words: lhs.words.suffix(from: k1)) : UIntXL() - let y0 = k1 < rhs.count ? UIntXL(words: rhs.words.prefix(upTo: k1)) : rhs - var y1 = k1 < rhs.count ? UIntXL(words: rhs.words.suffix(from: k1)) : UIntXL() - - let z0 = x0 * y0 - let z2 = x1 * y1 - - x1 += x0 - y1 += y0 - var z1 = x1 * y1 - z1 -= z0 - z1 -= z2 - - return Self.uninitialized(count: k1 * 4) { product in - z0.withUnsafeBufferPointer { z0 in - z1.withUnsafeBufferPointer { z1 in - z2.withUnsafeBufferPointer { z2 in - //=----------------------------------= - // pointee: initialization - //=----------------------------------= - product.initialize(repeating: 0 as UInt) - //=----------------------------------= - var index: Int, carry: Bool - - index = 0 - carry = false - - NBK.SUISS.increment(&product, by: z0, plus: &carry, at: &index) - - index = k1 &<< 1 - carry = false - - NBK.SUISS.increment(&product, by: z2, plus: &carry, at: &index) - - index = k1 - carry = false - - NBK.SUISS.increment(&product, by: z1, plus: &carry, at: &index) - }}}} - } - - //=------------------------------------------------------------------------= - // MARK: Transformations x Square - //=------------------------------------------------------------------------= - - /// Returns the square product of `base` by using [the Karatsuba algorithm]( - /// https://en.wikipedia.org/wiki/karatsuba_algorithm). - /// - /// high low - /// ┌───────────┴───────────┬───────────┴───────────┐ - /// │ x1 * x1 │ x0 * x0 │ - /// └───────────┬───────────┴───────────┬───────────┘ - /// add │ x0 * x0 │ - /// ├───────────────────────┤ - /// add │ x1 * x1 │ - /// ├───────────────────────┤ - /// sub │ |x1 - x0| * |x1 - x0| │ - /// └───────────────────────┘ - /// - @inlinable static func productBySquareKaratsubaAlgorithm(multiplying base: UIntXL) -> UIntXL { - let k1 = base.count &>> 1 &+ base.count & 1 - - var x0 = UIntXL(words: base.words.prefix(upTo: k1)) - var x1 = UIntXL(words: base.words.suffix(from: k1)) - - let z0 = x0.squared() - let z2 = x1.squared() - - var z1: Self - if x1 >= x0 { - x1 -= x0 - z1 = x1 - } else { - x0 -= x1 - z1 = x0 - }; z1.square() - - return Self.uninitialized(count: k1 * 4) { product in - z0.withUnsafeBufferPointer { z0 in - z1.withUnsafeBufferPointer { z1 in - z2.withUnsafeBufferPointer { z2 in - //=----------------------------------= - // pointee: initialization - //=----------------------------------= - product.initialize(repeating: 0 as UInt) - //=----------------------------------= - var index: Int, carry: Bool - - index = 0 - carry = false - - NBK.SUISS.incrementInIntersection(&product, by: z0, plus: &carry, at: &index) - - index = k1 &<< 1 - carry = false - - NBK.SUISS.incrementInIntersection(&product, by: z2, plus: &carry, at: &index) - - index = k1 - carry = false - - NBK.SUISS.increment(&product, by: z0, plus: &carry, at: &index) - - index = k1 - carry = false - - NBK.SUISS.increment(&product, by: z2, plus: &carry, at: &index) - - index = k1 - carry = false - - NBK.SUISS.decrement(&product, by: z1, plus: &carry, at: &index) - }}}} - } -} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Long.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Long.swift deleted file mode 100644 index db5589d2..00000000 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Long.swift +++ /dev/null @@ -1,104 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Flexible Width x Multiplication x Long x Unsigned -//*============================================================================* - -extension NBKFlexibleWidth.Magnitude { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - /// Returns the product of `multiplicand` and `multiplier` plus `addend` by performing long multiplication. - @inlinable static func productByLongAlgorithm(multiplying multiplicand: Self, by multiplier: Self, adding addend: UInt) -> Self { - Self.uninitialized(count: multiplicand.count + multiplier.count) { pro in - multiplicand.storage.withUnsafeBufferPointer { lhs in - multiplier.storage.withUnsafeBufferPointer { rhs in - var pointer = pro.baseAddress! - //=--------------------------= - // pointee: initialization 1 - //=--------------------------= - var carry: UInt = addend - let first: UInt = rhs.first! - - for element in lhs { - var wide = element.multipliedFullWidth(by: first) as NBK.Wide2 - carry = UInt(bit: wide.low.addReportingOverflow(carry)) &+ wide.high - pointer.initialize(to: wide.low) // done, pointee has no prior value - pointer = pointer.successor() - } - - pointer.initialize(to: carry) - pointer = pointer.successor() - Swift.assert(pro.baseAddress!.distance(to: pointer) == lhs.count + 1) - //=--------------------------= - // pointee: initialization 2 - //=--------------------------= - for var index in 1 ..< rhs.count { - pointer.initialize(to: 00000) - pointer = pointer.successor() - NBK.SUISS.incrementInIntersection(&pro, by: lhs, times: rhs[index], plus: 00000, at: &index) - } - - Swift.assert(pro.baseAddress!.distance(to: pointer) == pro.count) - } - } - } - } - - //=------------------------------------------------------------------------= - // MARK: Transformations x Square - //=------------------------------------------------------------------------= - - /// Returns the square product of `base` by performing long multiplication. - /// - /// - Note: It is up to `2x` faster than long multiplication with arbitrary inputs. - /// - @inlinable static func productBySquareLongAlgorithm(multiplying base: Self, adding addend: UInt) -> Self { - Self.uninitialized(count: 2 * base.count) { product in - base.storage.withUnsafeBufferPointer { base in - //=--------------------------= - // pointee: initialization - //=--------------------------= - product.initialize(repeating: 0 as UInt) - //=--------------------------= - var index: Int - var carry: UInt = addend - //=--------------------------= - var baseIndex = base.startIndex; while baseIndex < base.endIndex { - let multiplier = base[ baseIndex] - let productIndex = 2 * baseIndex - base.formIndex(after: &baseIndex) - - index = productIndex + 1 // add non-diagonal products - - NBK.SUISS.incrementInIntersection( - &product, by: UnsafeBufferPointer(rebasing: base[baseIndex...]), - times: multiplier, plus: 00000, at: &index) - - index = productIndex // partially double non-diagonal products - - NBK.SUISS.multiply( - &product, by: 0002, - add: &carry, from: &index, to: productIndex + 2) - - index = productIndex // add this iteration's diagonal product - - carry &+= UInt(bit: NBK.SUISS.incrementInIntersection( - &product, by: CollectionOfOne((multiplier)), - times: multiplier, plus: 00000, at: &index)) - } - } - } - } -} diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift index 8108c881..a93daac2 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift @@ -15,10 +15,6 @@ import NBKCoreKit extension NBKFlexibleWidth.Magnitude { - @usableFromInline static let productByKaratsubaAlgorithmThreshold: Int = 40 - - @usableFromInline static let productBySquareKaratsubaAlgorithmThreshold: Int = 40 - //=------------------------------------------------------------------------= // MARK: Transformations //=------------------------------------------------------------------------= @@ -28,11 +24,12 @@ extension NBKFlexibleWidth.Magnitude { } @inlinable public static func *(lhs: Self, rhs: Self) -> Self { - if lhs.count < Self.productByKaratsubaAlgorithmThreshold || - rhs.count < Self.productByKaratsubaAlgorithmThreshold { - return self.productByLongAlgorithm(multiplying: lhs, by: rhs, adding: UInt.zero) - } else { - return self.productByKaratsubaAlgorithm(multiplying: lhs, by: rhs) + lhs.withUnsafeBufferPointer { lhs in + rhs.withUnsafeBufferPointer { rhs in + Self.uninitialized(count: lhs.count + rhs.count) { + NBK.SUISS.initialize(&$0, to: lhs, times: rhs) + } + } } } @@ -45,10 +42,11 @@ extension NBKFlexibleWidth.Magnitude { } @inlinable public func squared() -> Self { - if self.count < Self.productBySquareKaratsubaAlgorithmThreshold { - return Self.productBySquareLongAlgorithm(multiplying: self, adding: UInt.zero) - } else { - return Self.productBySquareKaratsubaAlgorithm(multiplying: self) + self.withUnsafeBufferPointer{ words in + Self.uninitialized(count: words.count * 2) { + NBK.SUISS.initialize(&$0, toSquareProductOf: words) + } } } } + diff --git a/Sources/NBKFlexibleWidthKit/Private/NBK+Data.swift b/Sources/NBKFlexibleWidthKit/Private/NBK+Data.swift new file mode 100644 index 00000000..7530a090 --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/Private/NBK+Data.swift @@ -0,0 +1,46 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Data +//*============================================================================* + +extension NBK { + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + /// Initializes `base` by pushing `source` then returns the `data`. + @inlinable public static func initialize( + _ base: inout UnsafeMutablePointer, to source: UnsafeBufferPointer) -> UnsafeMutableBufferPointer { + base.initialize(from: source.baseAddress!, count: source.count) + + defer { + base = base.advanced(by: source.count) + } + + return UnsafeMutableBufferPointer(start: base, count: source.count) + } + + + /// Initializes `base` by pushing `source` then returns the `data`. + @inlinable public static func initialize( + _ base: inout UnsafeMutablePointer, repeating element: T, count: Int) -> UnsafeMutableBufferPointer { + base.initialize(repeating: element, count: count) + + defer { + base = base.advanced(by: count) + } + + return UnsafeMutableBufferPointer(start: base, count: count) + } +} diff --git a/Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Multiplication+Karatsuba.swift b/Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Multiplication+Karatsuba.swift new file mode 100644 index 00000000..972f53da --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Multiplication+Karatsuba.swift @@ -0,0 +1,259 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Strict Unsigned Integer x Mul. x Karatsuba x Sub Sequence +//*============================================================================* + +extension NBK.StrictUnsignedInteger.SubSequence where Base: MutableCollection { + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + /// Initializes `base` to the [Karatsuba algorithm][algorithm] product of `lhs` and `rhs`. + /// + /// + /// high : z1 low : z0 + /// ┌───────────┴───────────┬───────────┴───────────┐ + /// │ x1 * y1 │ x0 * y0 │ + /// └───────────┬───────────┴───────────┬───────────┘ + /// add │ x0 * y0 │ + /// ├───────────────────────┤ + /// add │ x1 * y1 │ + /// ├───────────────────────┤ + /// sub │ (x1 - x0) * (y1 - y0) │ : z2 + /// └───────────────────────┘ + /// + /// + /// - Parameters: + /// - base: A buffer of size `lhs.count` + `rhs.count`. + /// + /// - Note: The `base` must be uninitialized or `pointee` must be trivial. + /// + /// [algorithm]: https://en.wikipedia.org/wiki/karatsuba_algorithm + /// + @inline(never) @inlinable public static func initializeByKaratsubaAlgorithm( + _ base: inout Base, to lhs: UnsafeBufferPointer, times rhs: UnsafeBufferPointer) + where Base == UnsafeMutableBufferPointer { + //=--------------------------------------= + Swift.assert(base.count == lhs.count + rhs.count, NBK.callsiteOutOfBoundsInfo()) + //=--------------------------------------= + let k0c = Swift.max(lhs.count, rhs.count) + let k1c = k0c &>> 1 &+ k0c & 1 + let k2c = k1c &<< 1 + + let (x1s, x0s) = NBK.SUISS.partitionTrimmingRedundantZeros(lhs, at: k1c) + let (y1s, y0s) = NBK.SUISS.partitionTrimmingRedundantZeros(rhs, at: k1c) + let (z1c, z0c) = (x1s.count + y1s.count, x0s.count + y0s.count) + + Swift.withUnsafeTemporaryAllocation(of: Base.Element.self, capacity: 2 * (z0c + z1c)) { buffer in + var index: Int, carry: Bool, pointer: UnsafeMutablePointer = buffer.baseAddress! + //=----------------------------------= + // pointee: deferred deinitialization + //=----------------------------------= + defer { + buffer.deinitialize() + } + //=----------------------------------= + // pointee: initialization 1 + //=----------------------------------= + var x0 = NBK.initialize(&pointer, to: x0s) + var x1 = NBK.initialize(&pointer, to: x1s) + var y0 = NBK.initialize(&pointer, to: y0s) + var y1 = NBK.initialize(&pointer, to: y1s) + var z0 = UnsafeMutableBufferPointer(start: pointer, count: z0c); pointer += z0.count + var z1 = UnsafeMutableBufferPointer(start: pointer, count: z1c); pointer += z1.count + Swift.assert(pointer - buffer.baseAddress! == buffer.count) + //=----------------------------------= + // pointee: initialization 2 + //=----------------------------------= + NBK.SUISS.initialize(&z0, to: UnsafeBufferPointer(x0), times: UnsafeBufferPointer(y0)) + NBK.SUISS.initialize(&z1, to: UnsafeBufferPointer(x1), times: UnsafeBufferPointer(y1)) + + let xs = NBK.SUISS.compare(x1, to: x0).isLessThanZero + if xs { + Swift.swap(&x0, &x1) + } + + let ys = NBK.SUISS.compare(y1, to: y0).isLessThanZero + if ys { + Swift.swap(&y0, &y1) + } + + index = 000; carry = false + + NBK.SUISS.decrement(&x1, by: UnsafeBufferPointer(x0), plus: &carry, at: &index) + + index = 000; carry = false + + NBK.SUISS.decrement(&y1, by: UnsafeBufferPointer(y0), plus: &carry, at: &index) + //=----------------------------------= + // product must fit in combined width + //=----------------------------------= + Swift.assert(z1.dropFirst(base[k2c...].count).allSatisfy({ $0.isZero })) + z1 = UnsafeMutableBufferPointer(start: z1.baseAddress!, count: base.count - k2c) + //=----------------------------------= + // pointee: initialization 3 + //=----------------------------------= + pointer = base.baseAddress! + + for element in z0 { + pointer.initialize(to: element) + pointer = pointer.successor() + } + + for _ in z0.count ..< k2c { + pointer.initialize(to: 000000) + pointer = pointer.successor() + } + + for element in z1 { + pointer.initialize(to: element) + pointer = pointer.successor() + } + + Swift.assert(base.baseAddress!.distance(to: pointer) == base.count) + //=----------------------------------= + index = k1c; carry = false + + NBK.SUISS.increment(&base, by: UnsafeBufferPointer(z0), plus: &carry, at: &index) + + index = k1c; carry = false + + NBK.SUISS.increment(&base, by: UnsafeBufferPointer(z1), plus: &carry, at: &index) + + index = k1c; carry = false + + z2: do { // reuse z0 and z1 memory to form z2 + z0 = UnsafeMutableBufferPointer(start: z0.baseAddress!, count: x1.count + y1.count) + NBK.SUISS.initialize(&z0, to: UnsafeBufferPointer(x1), times: UnsafeBufferPointer(y1)) + switch xs == ys { + case true: NBK.SUISS.decrement(&base, by: UnsafeBufferPointer(z0), plus: &carry, at: &index) + case false: NBK.SUISS.increment(&base, by: UnsafeBufferPointer(z0), plus: &carry, at: &index) } + } + } + } + + //=------------------------------------------------------------------------= + // MARK: Initializers x Square + //=------------------------------------------------------------------------= + + /// Initializes `base` to the [square Karatsuba algorithm][algorithm] product of `lhs` and `rhs`. + /// + /// + /// high : z1 low : z0 + /// ┌───────────┴───────────┬───────────┴───────────┐ + /// │ x1 * x1 │ x0 * x0 │ + /// └───────────┬───────────┴───────────┬───────────┘ + /// add │ x0 * x0 │ + /// ├───────────────────────┤ + /// add │ x1 * x1 │ + /// ├───────────────────────┤ + /// sub │ |x1 - x0| * |x1 - x0| │ : z2 + /// └───────────────────────┘ + /// + /// + /// - Parameters: + /// - base: A buffer of size `lhs.count` + `rhs.count`. + /// + /// - Note: The `base` must be uninitialized or `pointee` must be trivial. + /// + /// [algorithm]: https://en.wikipedia.org/wiki/karatsuba_algorithm + /// + /// ### Development + /// + @inline(never) @inlinable public static func initializeByKaratsubaAlgorithm( + _ base: inout Base, toSquareProductOf elements: UnsafeBufferPointer) where Base == UnsafeMutableBufferPointer { + //=--------------------------------------= + Swift.assert(base.count == 2 * elements.count) + //=--------------------------------------= + let k0c = elements.count + let k1c = k0c &>> 1 &+ k0c & 1 + let k2c = k1c &<< 1 + + let (x1s, x0s) = NBK.SUISS.partitionTrimmingRedundantZeros(elements, at: k1c) + let (z1c, z0c) = (2 * x1s.count, 2 * x0s.count) + + Swift.withUnsafeTemporaryAllocation(of: Base.Element.self, capacity: 3 * (x0s.count + x1s.count)) { buffer in + var index: Int, carry: Bool, pointer: UnsafeMutablePointer = buffer.baseAddress! + //=----------------------------------= + // pointee: deferred deinitialization + //=----------------------------------= + defer { + buffer.deinitialize() + } + //=----------------------------------= + // pointee: initialization 1 + //=----------------------------------= + var x0 = NBK.initialize(&pointer, to: x0s) + var x1 = NBK.initialize(&pointer, to: x1s) + var z0 = UnsafeMutableBufferPointer(start: pointer, count: z0c); pointer += z0.count + var z1 = UnsafeMutableBufferPointer(start: pointer, count: z1c); pointer += z1.count + Swift.assert(pointer - buffer.baseAddress! == buffer.count) + //=----------------------------------= + // pointee: initialization 2 + //=----------------------------------= + NBK.SUISS.initialize(&z0, toSquareProductOf: UnsafeBufferPointer(x0)) + NBK.SUISS.initialize(&z1, toSquareProductOf: UnsafeBufferPointer(x1)) + + if NBK.SUISS.compare(UnsafeBufferPointer(x1), to: UnsafeBufferPointer(x0)).isLessThanZero { + Swift.swap(&x0, &x1) + } + + index = 000; carry = false + + NBK.SUISS.decrement(&(x1), by: UnsafeBufferPointer(x0), plus: &carry, at: &index) + //=----------------------------------= + // product must fit in combined width + //=----------------------------------= + Swift.assert(z1.dropFirst(base[k2c...].count).allSatisfy({ $0.isZero })) + z1 = UnsafeMutableBufferPointer(start: z1.baseAddress!, count: base.count - k2c) + //=----------------------------------= + // pointee: initialization 3 + //=----------------------------------= + pointer = base.baseAddress! + + for element in z0 { + pointer.initialize(to: element) + pointer = pointer.successor() + } + + for _ in z0.count ..< k2c { + pointer.initialize(to: 000000) + pointer = pointer.successor() + } + + for element in z1 { + pointer.initialize(to: element) + pointer = pointer.successor() + } + + Swift.assert(base.baseAddress!.distance(to: pointer) == base.count) + //=----------------------------------= + index = k1c; carry = false + + NBK.SUISS.increment(&base, by: UnsafeBufferPointer(z0), plus: &carry, at: &index) + + index = k1c; carry = false + + NBK.SUISS.increment(&base, by: UnsafeBufferPointer(z1), plus: &carry, at: &index) + + index = k1c; carry = false + + z2: do { // reuse z0 and z1 memory to form z2 + z0 = UnsafeMutableBufferPointer(start: z0.baseAddress!, count: x1.count &<< 1) + NBK.SUISS.initialize(&z0, toSquareProductOf: UnsafeBufferPointer(x1)) + NBK.SUISS.decrement(&base, by: UnsafeBufferPointer(z0), plus: &carry, at: &index) + } + } + } +} diff --git a/Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Multiplication+Long.swift b/Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Multiplication+Long.swift new file mode 100644 index 00000000..090c9310 --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Multiplication+Long.swift @@ -0,0 +1,117 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Strict Unsigned Integer x Mul. x Long x Sub Sequence +//*============================================================================* + +extension NBK.StrictUnsignedInteger.SubSequence where Base: MutableCollection { + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + /// Initializes `base` to the [long multiplication][algorithm] product of `lhs` and `rhs`. + /// + /// - Parameters: + /// - base: A buffer of size `lhs.count` + `rhs.count`. + /// + /// - Note: The `base` must be uninitialized or `pointee` must be trivial. + /// + /// [algorithm]: https://en.wikipedia.org/wiki/multiplication_algorithm + /// + @inline(never) @inlinable public static func initializeByLongAlgorithm( + _ base: inout Base, to lhs: UnsafeBufferPointer, times rhs: UnsafeBufferPointer, + plus addend: Base.Element = .zero) where Base == UnsafeMutableBufferPointer { + //=--------------------------------------= + Swift.assert(base.count == lhs.count + rhs.count, NBK.callsiteOutOfBoundsInfo()) + //=--------------------------------------= + var pointer = base.baseAddress! + //=--------------------------------------= + // pointee: initialization 1 + //=--------------------------------------= + var carry: Base.Element = addend + let first: Base.Element = rhs.first ?? Base.Element.zero + + for element in lhs { + var wide = element.multipliedFullWidth(by: first) + carry = Base.Element(bit: wide.low.addReportingOverflow(carry)) &+ wide.high + pointer.initialize(to: wide.low) // done, uninitialized or discarded pointee + pointer = pointer.successor() + } + + if !rhs.isEmpty { + pointer.initialize(to: carry) + pointer = pointer.successor() + } + + Swift.assert(base.baseAddress!.distance(to: pointer) == lhs.count + Int(bit: !rhs.isEmpty)) + //=--------------------------------------= + // pointee: initialization 2 + //=--------------------------------------= + for var index in rhs.indices.dropFirst() { + pointer.initialize(to: 00000) + pointer = pointer.successor() + NBK.SUISS.incrementInIntersection(&base, by: lhs, times: rhs[index], plus: Base.Element.zero, at: &index) + } + + Swift.assert(base.baseAddress!.distance(to: pointer) == base.count) + } + + //=------------------------------------------------------------------------= + // MARK: Initializers x Square + //=------------------------------------------------------------------------= + + /// Initializes `base` to the [square long multiplication][algorithm] product of `elements` plus `addend`. + /// + /// - Parameters: + /// - base: A buffer of size `lhs.count` + `rhs.count`. + /// + /// - Note: The `base` must be uninitialized or `pointee` must be trivial. + /// + /// [algorithm]: https://en.wikipedia.org/wiki/multiplication_algorithm + /// + @inline(never) @inlinable public static func initializeByLongAlgorithm( + _ base: inout Base, toSquareProductOf elements: UnsafeBufferPointer, plus addend: Base.Element = .zero) + where Base == UnsafeMutableBufferPointer { + //=--------------------------------------= + Swift.assert(base.count == 2 * elements.count) + //=--------------------------------------= + // pointee: initialization + //=--------------------------------------= + base.initialize(repeating: 0 as Base.Element) + //=--------------------------------------= + var index: Int + var carry: Base.Element = addend + //=--------------------------------------= + var baseIndex = elements.startIndex; while baseIndex < elements.endIndex { + let multiplier = elements[ baseIndex] + let productIndex = 2 * baseIndex + elements.formIndex(after: &baseIndex) + + index = productIndex + 1 // add non-diagonal products + + NBK.SUISS.incrementInIntersection( + &base, by: UnsafeBufferPointer(rebasing: elements[baseIndex...]), + times: multiplier, plus: 00000, at: &index) + + index = productIndex // partially double non-diagonal products + + NBK.SUISS.multiply(&base, by: 0002, add: &carry, from: &index, to: productIndex + 2) + + index = productIndex // add this iteration's diagonal product + + carry &+= Base.Element(bit: NBK.SUISS.incrementInIntersection( + &base, by: CollectionOfOne((multiplier)), + times: multiplier, plus: 00000, at: &index)) + } + } +} diff --git a/Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Multiplication.swift b/Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Multiplication.swift new file mode 100644 index 00000000..04483abf --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Multiplication.swift @@ -0,0 +1,61 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Strict Unsigned Integer x Multiplication x Sub Sequence +//*============================================================================* + +extension NBK.StrictUnsignedInteger.SubSequence where Base: MutableCollection { + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + /// Initializes `base` to the product of `lhs` and `rhs`. + /// + /// - Parameters: + /// - base: A buffer of size `lhs.count` + `rhs.count`. + /// + /// - Note: The `base` memory must be uninitialized or the pointee must be a trivial type. + /// + @inlinable static func initialize( + _ base: inout Base, to lhs: UnsafeBufferPointer, times rhs: UnsafeBufferPointer) + where Base == UnsafeMutableBufferPointer { + //=--------------------------------------= + if lhs.count < 20 || rhs.count < 20 { + return self.initializeByLongAlgorithm(&base, to: lhs, times: rhs, plus: Base.Element.zero) + } else { + return self.initializeByKaratsubaAlgorithm(&base, to: lhs, times: rhs) + } + } + + //=------------------------------------------------------------------------= + // MARK: Initializers x Square + //=------------------------------------------------------------------------= + + /// Initializes `base` to the square product of `elements`. + /// + /// - Parameters: + /// - base: A buffer of size `2 * elements.count`. + /// + /// - Note: The `base` memory must be uninitialized or the pointee must be a trivial type. + /// + @inlinable static func initialize( + _ base: inout Base, toSquareProductOf elements: UnsafeBufferPointer) + where Base == UnsafeMutableBufferPointer { + //=--------------------------------------= + if elements.count < 20 { + return self.initializeByLongAlgorithm(&base, toSquareProductOf: elements, plus: Base.Element.zero) + } else { + return self.initializeByKaratsubaAlgorithm(&base, toSquareProductOf: elements) + } + } +} diff --git a/Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Split.swift b/Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Split.swift new file mode 100644 index 00000000..e9892d85 --- /dev/null +++ b/Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Split.swift @@ -0,0 +1,30 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +import NBKCoreKit + +//*============================================================================* +// MARK: * NBK x Strict Unsigned Integer x Sub Sequence x Split +//*============================================================================* + +extension NBK.StrictUnsignedInteger.SubSequence { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + /// Splits `base` at `index` then trims all trailing zeros from each sequence. + @inlinable public static func partitionTrimmingRedundantZeros( + _ base: Base, at index: Base.Index) -> HL where Base == UnsafeBufferPointer { + let partition = Swift.min(base.count, index) + let low = Base(start: base.baseAddress!, /*------*/ count: NBK.dropLast(from: base[..( _ lhs: T, _ rhs: T.Digit, _ product: T, file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + NBKAssertMultiplication(lhs, T(digit: rhs), product, file: file, line: line) //=------------------------------------------= XCTAssertEqual( lhs * rhs, product, file: file, line: line) XCTAssertEqual({ var lhs = lhs; lhs *= rhs; return lhs }(), product, file: file, line: line) - //=------------------------------------------= - NBKAssertMultiplication(lhs, T(digit: rhs), product, file: file, line: line) } private func NBKAssertMultiplicationBySquaring( @@ -138,21 +123,6 @@ file: StaticString = #file, line: UInt = #line) { //=------------------------------------------= XCTAssertEqual( base.squared(), product, file: file, line: line) XCTAssertEqual({ var base = base; base.square (); return base }(), product, file: file, line: line) - //=------------------------------------------= - guard let base = base as? UIntXL, let product = product as? UIntXL else { - return precondition(T.isSigned) - } - //=------------------------------------------= - long: do { - let algorithm = UIntXL.productBySquareLongAlgorithm(multiplying:adding:) - XCTAssertEqual(algorithm(base, 00000000), product, file: file, line: line) - XCTAssertEqual(algorithm(base, UInt.max), product + UInt.max, file: file, line: line) - } - - karatsuba: do { - let algorithm = UIntXL.productBySquareKaratsubaAlgorithm(multiplying:) - XCTAssertEqual(algorithm(base), product, file: file, line: line) - } } //=----------------------------------------------------------------------------= @@ -165,17 +135,6 @@ file: StaticString = #file, line: UInt = #line) { //=------------------------------------------= XCTAssertEqual(lhs.multiplied(by: rhs, adding: addend), product, file: file, line: line) XCTAssertEqual({ var lhs = lhs; lhs.multiply(by: rhs, add: addend); return lhs }(), product, file: file, line: line) - //=------------------------------------------= - long: do { - let algorithm = UIntXL.productByLongAlgorithm(multiplying:by:adding:) - XCTAssertEqual(algorithm(lhs, UIntXL(digit: rhs), addend), product, file: file, line: line) - XCTAssertEqual(algorithm(lhs, UIntXL(digit: rhs), 000000), product - addend, file: file, line: line) - } - - karatsuba: do { - let algorithm = UIntXL.productByKaratsubaAlgorithm(multiplying:by:) - XCTAssertEqual(algorithm(lhs, UIntXL(digit: rhs)), product - addend, file: file, line: line) - } } #endif From 8e5fba80298684cffac2c360db00ed50d4b53d84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Mon, 6 Nov 2023 18:42:08 +0100 Subject: [PATCH 116/133] `floor(_:)` good, `ceil(_:)` bad, on floor can sleep (#108). --- ...gnedInteger+Multiplication+Karatsuba.swift | 36 ++-- .../NBKFlexibleWidth+Exponentiation.swift | 194 +++--------------- 2 files changed, 54 insertions(+), 176 deletions(-) diff --git a/Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Multiplication+Karatsuba.swift b/Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Multiplication+Karatsuba.swift index 972f53da..8c9a868e 100644 --- a/Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Multiplication+Karatsuba.swift +++ b/Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Multiplication+Karatsuba.swift @@ -48,7 +48,7 @@ extension NBK.StrictUnsignedInteger.SubSequence where Base: MutableCollection { Swift.assert(base.count == lhs.count + rhs.count, NBK.callsiteOutOfBoundsInfo()) //=--------------------------------------= let k0c = Swift.max(lhs.count, rhs.count) - let k1c = k0c &>> 1 &+ k0c & 1 + let k1c = k0c &>> 1 let k2c = k1c &<< 1 let (x1s, x0s) = NBK.SUISS.partitionTrimmingRedundantZeros(lhs, at: k1c) @@ -100,7 +100,7 @@ extension NBK.StrictUnsignedInteger.SubSequence where Base: MutableCollection { // product must fit in combined width //=----------------------------------= Swift.assert(z1.dropFirst(base[k2c...].count).allSatisfy({ $0.isZero })) - z1 = UnsafeMutableBufferPointer(start: z1.baseAddress!, count: base.count - k2c) + z1 = UnsafeMutableBufferPointer(rebasing: z1.prefix(base[k2c...].count)) //=----------------------------------= // pointee: initialization 3 //=----------------------------------= @@ -108,17 +108,22 @@ extension NBK.StrictUnsignedInteger.SubSequence where Base: MutableCollection { for element in z0 { pointer.initialize(to: element) - pointer = pointer.successor() + pointer = pointer.successor() } for _ in z0.count ..< k2c { - pointer.initialize(to: 000000) - pointer = pointer.successor() + pointer.initialize(to: .zero) + pointer = pointer.successor() } for element in z1 { pointer.initialize(to: element) - pointer = pointer.successor() + pointer = pointer.successor() + } + + for _ in k2c + z1.count ..< base.count { + pointer.initialize(to: .zero) + pointer = pointer.successor() } Swift.assert(base.baseAddress!.distance(to: pointer) == base.count) @@ -158,7 +163,7 @@ extension NBK.StrictUnsignedInteger.SubSequence where Base: MutableCollection { /// ├───────────────────────┤ /// add │ x1 * x1 │ /// ├───────────────────────┤ - /// sub │ |x1 - x0| * |x1 - x0| │ : z2 + /// sub │ (x1 - x0) * (x1 - x0) │ : z2 /// └───────────────────────┘ /// /// @@ -177,7 +182,7 @@ extension NBK.StrictUnsignedInteger.SubSequence where Base: MutableCollection { Swift.assert(base.count == 2 * elements.count) //=--------------------------------------= let k0c = elements.count - let k1c = k0c &>> 1 &+ k0c & 1 + let k1c = k0c &>> 1 let k2c = k1c &<< 1 let (x1s, x0s) = NBK.SUISS.partitionTrimmingRedundantZeros(elements, at: k1c) @@ -216,7 +221,7 @@ extension NBK.StrictUnsignedInteger.SubSequence where Base: MutableCollection { // product must fit in combined width //=----------------------------------= Swift.assert(z1.dropFirst(base[k2c...].count).allSatisfy({ $0.isZero })) - z1 = UnsafeMutableBufferPointer(start: z1.baseAddress!, count: base.count - k2c) + z1 = UnsafeMutableBufferPointer(rebasing: z1.prefix(base[k2c...].count)) //=----------------------------------= // pointee: initialization 3 //=----------------------------------= @@ -224,17 +229,22 @@ extension NBK.StrictUnsignedInteger.SubSequence where Base: MutableCollection { for element in z0 { pointer.initialize(to: element) - pointer = pointer.successor() + pointer = pointer.successor() } for _ in z0.count ..< k2c { - pointer.initialize(to: 000000) - pointer = pointer.successor() + pointer.initialize(to: .zero) + pointer = pointer.successor() } for element in z1 { pointer.initialize(to: element) - pointer = pointer.successor() + pointer = pointer.successor() + } + + for _ in k2c + z1.count ..< base.count { + pointer.initialize(to: .zero) + pointer = pointer.successor() } Swift.assert(base.baseAddress!.distance(to: pointer) == base.count) diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Exponentiation.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Exponentiation.swift index e1944cae..0dde6bb7 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Exponentiation.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Exponentiation.swift @@ -294,179 +294,47 @@ final class NBKFlexibleWidthTestsOnExponentiationByPrimesAsUIntXL: XCTestCase { } //*============================================================================* -// MARK: * NBK x Flexible Width x Exponentiation x UIntXL x Other +// MARK: * NBK x Flexible Width x Exponentiation x UIntXL x Powers Of 10 //*============================================================================* -final class NBKFlexibleWidthTestsOnExponentiationByOtherAsUIntXL: XCTestCase { +final class NBKFlexibleWidthTestsOnExponentiationByPowersOf10AsUIntXL: XCTestCase { typealias T = UIntXL typealias M = UIntXL + //=------------------------------------------------------------------------= + // MARK: State + //=------------------------------------------------------------------------= + + static let x10000 = T("1\(String(repeating: "0", count: 10000))")! + //=------------------------------------------------------------------------= // MARK: Tests //=------------------------------------------------------------------------= - /// https://www.wolframalpha.com/input?i2d=true&i=Power%5B1000000%2C1000%5D - func test10000000000RaisedTo1000() { - NBKAssertExponentiation(T(10_000_000_000), Int(1_000), T(""" - 0000000000000000000000000000000000000000000000010000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000000 - """)) + /// https://www.wolframalpha.com/input?i2d=true&i=Power%5BPower%5B10%2C1%5D%2C10000%5D + func testPower1RaisedTo10000() { + NBKAssertExponentiation(T("1\(String(repeating: "0", count: 1))")!, Int(10000), Self.x10000) + } + + /// https://www.wolframalpha.com/input?i2d=true&i=Power%5BPower%5B10%2C10%5D%2C1000%5D + func testPower10RaisedTo1000() { + NBKAssertExponentiation(T("1\(String(repeating: "0", count: 10))")!, Int(1000), Self.x10000) + } + + /// https://www.wolframalpha.com/input?i2d=true&i=Power%5BPower%5B10%2C100%5D%2C100%5D + func testPower100RaisedTo100() { + NBKAssertExponentiation(T("1\(String(repeating: "0", count: 100))")!, Int(100), Self.x10000) + } + + /// https://www.wolframalpha.com/input?i2d=true&i=Power%5BPower%5B10%2C1000%5D%2C10%5D + func testPower1000RaisedTo10() { + NBKAssertExponentiation(T("1\(String(repeating: "0", count: 1000))")!, Int(10), Self.x10000) + } + + /// https://www.wolframalpha.com/input?i2d=true&i=Power%5BPower%5B10%2C10000%5D%2C1%5D + func testPower10000RaisedTo1() { + NBKAssertExponentiation(Self.x10000, Int(1), Self.x10000) } } From c49f1afa354a971d9f431c86e97b0549d32008f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Tue, 7 Nov 2023 08:15:38 +0100 Subject: [PATCH 117/133] Cleanup of Karatsuba algorithms (#108). --- .../Private/NBK+Data.swift | 29 +-- ...gnedInteger+Multiplication+Karatsuba.swift | 175 +++++++----------- ...tUnsignedInteger+Multiplication+Long.swift | 8 +- 3 files changed, 79 insertions(+), 133 deletions(-) diff --git a/Sources/NBKFlexibleWidthKit/Private/NBK+Data.swift b/Sources/NBKFlexibleWidthKit/Private/NBK+Data.swift index 7530a090..64fdcc1c 100644 --- a/Sources/NBKFlexibleWidthKit/Private/NBK+Data.swift +++ b/Sources/NBKFlexibleWidthKit/Private/NBK+Data.swift @@ -16,31 +16,20 @@ import NBKCoreKit extension NBK { //=------------------------------------------------------------------------= - // MARK: Utilities + // MARK: Initializers //=------------------------------------------------------------------------= - /// Initializes `base` by pushing `source` then returns the `data`. - @inlinable public static func initialize( - _ base: inout UnsafeMutablePointer, to source: UnsafeBufferPointer) -> UnsafeMutableBufferPointer { + /// Initializes `base` to `source` then returns the initialized `count`. + @inlinable public static func initializeGetCount( + _ base: UnsafeMutablePointer, to source: UnsafeBufferPointer) -> Int { base.initialize(from: source.baseAddress!, count: source.count) - - defer { - base = base.advanced(by: source.count) - } - - return UnsafeMutableBufferPointer(start: base, count: source.count) + return source.count as Int } - - /// Initializes `base` by pushing `source` then returns the `data`. - @inlinable public static func initialize( - _ base: inout UnsafeMutablePointer, repeating element: T, count: Int) -> UnsafeMutableBufferPointer { + /// Initializes `base` to `source` then returns the initialized `count`. + @inlinable public static func initializeGetCount( + _ base: UnsafeMutablePointer, repeating element: T, count: Int) -> Int { base.initialize(repeating: element, count: count) - - defer { - base = base.advanced(by: count) - } - - return UnsafeMutableBufferPointer(start: base, count: count) + return count as Int } } diff --git a/Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Multiplication+Karatsuba.swift b/Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Multiplication+Karatsuba.swift index 8c9a868e..af6392f2 100644 --- a/Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Multiplication+Karatsuba.swift +++ b/Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Multiplication+Karatsuba.swift @@ -34,8 +34,7 @@ extension NBK.StrictUnsignedInteger.SubSequence where Base: MutableCollection { /// └───────────────────────┘ /// /// - /// - Parameters: - /// - base: A buffer of size `lhs.count` + `rhs.count`. + /// - Parameter base: A buffer of size `lhs.count` + `rhs.count`. /// /// - Note: The `base` must be uninitialized or `pointee` must be trivial. /// @@ -55,27 +54,34 @@ extension NBK.StrictUnsignedInteger.SubSequence where Base: MutableCollection { let (y1s, y0s) = NBK.SUISS.partitionTrimmingRedundantZeros(rhs, at: k1c) let (z1c, z0c) = (x1s.count + y1s.count, x0s.count + y0s.count) - Swift.withUnsafeTemporaryAllocation(of: Base.Element.self, capacity: 2 * (z0c + z1c)) { buffer in - var index: Int, carry: Bool, pointer: UnsafeMutablePointer = buffer.baseAddress! + let count = 2 * (z0c + z1c) as Int + Swift.withUnsafeTemporaryAllocation(of: Base.Element.self, capacity: count) { buffer in + var pointer: UnsafeMutablePointer //=----------------------------------= // pointee: deferred deinitialization //=----------------------------------= defer { - buffer.deinitialize() + buffer.baseAddress!.deinitialize(count: count) } //=----------------------------------= - // pointee: initialization 1 + // temporary memory regions //=----------------------------------= - var x0 = NBK.initialize(&pointer, to: x0s) - var x1 = NBK.initialize(&pointer, to: x1s) - var y0 = NBK.initialize(&pointer, to: y0s) - var y1 = NBK.initialize(&pointer, to: y1s) - var z0 = UnsafeMutableBufferPointer(start: pointer, count: z0c); pointer += z0.count - var z1 = UnsafeMutableBufferPointer(start: pointer, count: z1c); pointer += z1.count - Swift.assert(pointer - buffer.baseAddress! == buffer.count) + pointer = buffer.baseAddress! as UnsafeMutablePointer + var x0 = UnsafeMutableBufferPointer(start: pointer, count: x0s.count); pointer += x0.count + var x1 = UnsafeMutableBufferPointer(start: pointer, count: x1s.count); pointer += x1.count + var y0 = UnsafeMutableBufferPointer(start: pointer, count: y0s.count); pointer += y0.count + var y1 = UnsafeMutableBufferPointer(start: pointer, count: y1s.count); pointer += y1.count + var z0 = UnsafeMutableBufferPointer(start: pointer, count: z0c); pointer += z0.count + var z1 = UnsafeMutableBufferPointer(start: pointer, count: z1c); pointer += z1.count + Swift.assert(buffer.baseAddress!.distance(to: pointer) == count) //=----------------------------------= - // pointee: initialization 2 + // pointee: initialization 1 //=----------------------------------= + x0.baseAddress!.initialize(from: x0s.baseAddress!, count: x0s.count) + x1.baseAddress!.initialize(from: x1s.baseAddress!, count: x1s.count) + y0.baseAddress!.initialize(from: y0s.baseAddress!, count: y0s.count) + y1.baseAddress!.initialize(from: y1s.baseAddress!, count: y1s.count) + NBK.SUISS.initialize(&z0, to: UnsafeBufferPointer(x0), times: UnsafeBufferPointer(y0)) NBK.SUISS.initialize(&z1, to: UnsafeBufferPointer(x1), times: UnsafeBufferPointer(y1)) @@ -89,61 +95,35 @@ extension NBK.StrictUnsignedInteger.SubSequence where Base: MutableCollection { Swift.swap(&y0, &y1) } - index = 000; carry = false - - NBK.SUISS.decrement(&x1, by: UnsafeBufferPointer(x0), plus: &carry, at: &index) - - index = 000; carry = false - - NBK.SUISS.decrement(&y1, by: UnsafeBufferPointer(y0), plus: &carry, at: &index) + NBK.SUISS.decrement( &x1, by: UnsafeBufferPointer(x0)) + NBK.SUISS.decrement( &y1, by: UnsafeBufferPointer(y0)) //=----------------------------------= // product must fit in combined width //=----------------------------------= Swift.assert(z1.dropFirst(base[k2c...].count).allSatisfy({ $0.isZero })) z1 = UnsafeMutableBufferPointer(rebasing: z1.prefix(base[k2c...].count)) //=----------------------------------= - // pointee: initialization 3 + // pointee: initialization 2 //=----------------------------------= - pointer = base.baseAddress! - - for element in z0 { - pointer.initialize(to: element) - pointer = pointer.successor() - } - - for _ in z0.count ..< k2c { - pointer.initialize(to: .zero) - pointer = pointer.successor() - } - - for element in z1 { - pointer.initialize(to: element) - pointer = pointer.successor() - } - - for _ in k2c + z1.count ..< base.count { - pointer.initialize(to: .zero) - pointer = pointer.successor() - } - + pointer = base.baseAddress! as UnsafeMutablePointer + pointer += NBK.initializeGetCount(pointer, to: UnsafeBufferPointer(z0)) + pointer += NBK.initializeGetCount(pointer, repeating: Base.Element.zero, count: k2c - z0.count) + pointer += NBK.initializeGetCount(pointer, to: UnsafeBufferPointer(z1)) + pointer += NBK.initializeGetCount(pointer, repeating: Base.Element.zero, count: base.count - (k2c + z1.count)) Swift.assert(base.baseAddress!.distance(to: pointer) == base.count) //=----------------------------------= - index = k1c; carry = false - - NBK.SUISS.increment(&base, by: UnsafeBufferPointer(z0), plus: &carry, at: &index) - - index = k1c; carry = false + var slice = UnsafeMutableBufferPointer(rebasing: base.suffix(from: k1c)) - NBK.SUISS.increment(&base, by: UnsafeBufferPointer(z1), plus: &carry, at: &index) - - index = k1c; carry = false + NBK.SUISS.increment(&slice, by: UnsafeBufferPointer(z0)) + NBK.SUISS.increment(&slice, by: UnsafeBufferPointer(z1)) z2: do { // reuse z0 and z1 memory to form z2 - z0 = UnsafeMutableBufferPointer(start: z0.baseAddress!, count: x1.count + y1.count) - NBK.SUISS.initialize(&z0, to: UnsafeBufferPointer(x1), times: UnsafeBufferPointer(y1)) - switch xs == ys { - case true: NBK.SUISS.decrement(&base, by: UnsafeBufferPointer(z0), plus: &carry, at: &index) - case false: NBK.SUISS.increment(&base, by: UnsafeBufferPointer(z0), plus: &carry, at: &index) } + z0 = UnsafeMutableBufferPointer(start: z0.baseAddress!, count: x1.count + y1.count) + NBK.SUISS.initialize(&(z0), to: UnsafeBufferPointer(x1), times: UnsafeBufferPointer(y1)) + }; if xs == ys { + NBK.SUISS.decrement(&slice, by: UnsafeBufferPointer(z0)) + } else { + NBK.SUISS.increment(&slice, by: UnsafeBufferPointer(z0)) } } } @@ -167,8 +147,7 @@ extension NBK.StrictUnsignedInteger.SubSequence where Base: MutableCollection { /// └───────────────────────┘ /// /// - /// - Parameters: - /// - base: A buffer of size `lhs.count` + `rhs.count`. + /// - Parameter base: A buffer of size `lhs.count` + `rhs.count`. /// /// - Note: The `base` must be uninitialized or `pointee` must be trivial. /// @@ -179,7 +158,7 @@ extension NBK.StrictUnsignedInteger.SubSequence where Base: MutableCollection { @inline(never) @inlinable public static func initializeByKaratsubaAlgorithm( _ base: inout Base, toSquareProductOf elements: UnsafeBufferPointer) where Base == UnsafeMutableBufferPointer { //=--------------------------------------= - Swift.assert(base.count == 2 * elements.count) + Swift.assert(base.count == 2 * elements.count, NBK.callsiteOutOfBoundsInfo()) //=--------------------------------------= let k0c = elements.count let k1c = k0c &>> 1 @@ -188,81 +167,61 @@ extension NBK.StrictUnsignedInteger.SubSequence where Base: MutableCollection { let (x1s, x0s) = NBK.SUISS.partitionTrimmingRedundantZeros(elements, at: k1c) let (z1c, z0c) = (2 * x1s.count, 2 * x0s.count) - Swift.withUnsafeTemporaryAllocation(of: Base.Element.self, capacity: 3 * (x0s.count + x1s.count)) { buffer in - var index: Int, carry: Bool, pointer: UnsafeMutablePointer = buffer.baseAddress! + let count = 3 * (x1s.count + x0s.count) as Int + Swift.withUnsafeTemporaryAllocation(of: Base.Element.self, capacity: count) { buffer in + var pointer: UnsafeMutablePointer //=----------------------------------= // pointee: deferred deinitialization //=----------------------------------= defer { - buffer.deinitialize() + buffer.baseAddress!.deinitialize(count: count) } //=----------------------------------= - // pointee: initialization 1 + // temporary memory regions //=----------------------------------= - var x0 = NBK.initialize(&pointer, to: x0s) - var x1 = NBK.initialize(&pointer, to: x1s) - var z0 = UnsafeMutableBufferPointer(start: pointer, count: z0c); pointer += z0.count - var z1 = UnsafeMutableBufferPointer(start: pointer, count: z1c); pointer += z1.count - Swift.assert(pointer - buffer.baseAddress! == buffer.count) + pointer = buffer.baseAddress! as UnsafeMutablePointer + var x0 = UnsafeMutableBufferPointer(start: pointer, count: x0s.count); pointer += x0.count + var x1 = UnsafeMutableBufferPointer(start: pointer, count: x1s.count); pointer += x1.count + var z0 = UnsafeMutableBufferPointer(start: pointer, count: z0c); pointer += z0.count + var z1 = UnsafeMutableBufferPointer(start: pointer, count: z1c); pointer += z1.count + Swift.assert(buffer.baseAddress!.distance(to: pointer) == count) //=----------------------------------= - // pointee: initialization 2 + // pointee: initialization 1 //=----------------------------------= + x0.baseAddress!.initialize(from: x0s.baseAddress!, count: x0s.count) + x1.baseAddress!.initialize(from: x1s.baseAddress!, count: x1s.count) + NBK.SUISS.initialize(&z0, toSquareProductOf: UnsafeBufferPointer(x0)) NBK.SUISS.initialize(&z1, toSquareProductOf: UnsafeBufferPointer(x1)) - if NBK.SUISS.compare(UnsafeBufferPointer(x1), to: UnsafeBufferPointer(x0)).isLessThanZero { + if NBK.SUISS.compare(x1, to: x0).isLessThanZero { Swift.swap(&x0, &x1) } - index = 000; carry = false - - NBK.SUISS.decrement(&(x1), by: UnsafeBufferPointer(x0), plus: &carry, at: &index) + NBK.SUISS.decrement( &x1, by: UnsafeBufferPointer(x0)) //=----------------------------------= // product must fit in combined width //=----------------------------------= Swift.assert(z1.dropFirst(base[k2c...].count).allSatisfy({ $0.isZero })) z1 = UnsafeMutableBufferPointer(rebasing: z1.prefix(base[k2c...].count)) //=----------------------------------= - // pointee: initialization 3 + // pointee: initialization 2 //=----------------------------------= - pointer = base.baseAddress! - - for element in z0 { - pointer.initialize(to: element) - pointer = pointer.successor() - } - - for _ in z0.count ..< k2c { - pointer.initialize(to: .zero) - pointer = pointer.successor() - } - - for element in z1 { - pointer.initialize(to: element) - pointer = pointer.successor() - } - - for _ in k2c + z1.count ..< base.count { - pointer.initialize(to: .zero) - pointer = pointer.successor() - } - + pointer = base.baseAddress! as UnsafeMutablePointer + pointer += NBK.initializeGetCount(pointer, to: UnsafeBufferPointer(z0)) + pointer += NBK.initializeGetCount(pointer, repeating: Base.Element.zero, count: k2c - z0.count) + pointer += NBK.initializeGetCount(pointer, to: UnsafeBufferPointer(z1)) + pointer += NBK.initializeGetCount(pointer, repeating: Base.Element.zero, count: base.count - (k2c + z1.count)) Swift.assert(base.baseAddress!.distance(to: pointer) == base.count) //=----------------------------------= - index = k1c; carry = false - - NBK.SUISS.increment(&base, by: UnsafeBufferPointer(z0), plus: &carry, at: &index) - - index = k1c; carry = false - - NBK.SUISS.increment(&base, by: UnsafeBufferPointer(z1), plus: &carry, at: &index) - - index = k1c; carry = false + var slice = UnsafeMutableBufferPointer(rebasing: base.suffix(from: k1c)) + NBK.SUISS.increment(&slice, by: UnsafeBufferPointer(z0)) + NBK.SUISS.increment(&slice, by: UnsafeBufferPointer(z1)) z2: do { // reuse z0 and z1 memory to form z2 z0 = UnsafeMutableBufferPointer(start: z0.baseAddress!, count: x1.count &<< 1) - NBK.SUISS.initialize(&z0, toSquareProductOf: UnsafeBufferPointer(x1)) - NBK.SUISS.decrement(&base, by: UnsafeBufferPointer(z0), plus: &carry, at: &index) + NBK.SUISS.initialize(&(z0), toSquareProductOf: UnsafeBufferPointer(x1)) + NBK.SUISS.decrement(&slice, by:/*-----------*/ UnsafeBufferPointer(z0)) } } } diff --git a/Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Multiplication+Long.swift b/Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Multiplication+Long.swift index 090c9310..9c9dc21d 100644 --- a/Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Multiplication+Long.swift +++ b/Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Multiplication+Long.swift @@ -21,8 +21,7 @@ extension NBK.StrictUnsignedInteger.SubSequence where Base: MutableCollection { /// Initializes `base` to the [long multiplication][algorithm] product of `lhs` and `rhs`. /// - /// - Parameters: - /// - base: A buffer of size `lhs.count` + `rhs.count`. + /// - Parameter base: A buffer of size `lhs.count` + `rhs.count`. /// /// - Note: The `base` must be uninitialized or `pointee` must be trivial. /// @@ -72,8 +71,7 @@ extension NBK.StrictUnsignedInteger.SubSequence where Base: MutableCollection { /// Initializes `base` to the [square long multiplication][algorithm] product of `elements` plus `addend`. /// - /// - Parameters: - /// - base: A buffer of size `lhs.count` + `rhs.count`. + /// - Parameter base: A buffer of size `lhs.count` + `rhs.count`. /// /// - Note: The `base` must be uninitialized or `pointee` must be trivial. /// @@ -83,7 +81,7 @@ extension NBK.StrictUnsignedInteger.SubSequence where Base: MutableCollection { _ base: inout Base, toSquareProductOf elements: UnsafeBufferPointer, plus addend: Base.Element = .zero) where Base == UnsafeMutableBufferPointer { //=--------------------------------------= - Swift.assert(base.count == 2 * elements.count) + Swift.assert(base.count == 2 * elements.count, NBK.callsiteOutOfBoundsInfo()) //=--------------------------------------= // pointee: initialization //=--------------------------------------= From 316f3ca0288128f750d02426e8ca5b4afa32245b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Tue, 7 Nov 2023 08:20:11 +0100 Subject: [PATCH 118/133] Karatsuba cleanup and larger Fibonacci tests (#108). --- ...gnedInteger+Multiplication+Karatsuba.swift | 27 +- ...tUnsignedInteger+Multiplication+Long.swift | 6 +- ...NBK+StrictUnsignedInteger+Partition.swift} | 7 +- .../Models/NBKFibonacciXL.swift | 473 +++++++++++++++++- 4 files changed, 491 insertions(+), 22 deletions(-) rename Sources/NBKFlexibleWidthKit/Private/{NBK+StrictUnsignedInteger+Split.swift => NBK+StrictUnsignedInteger+Partition.swift} (79%) diff --git a/Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Multiplication+Karatsuba.swift b/Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Multiplication+Karatsuba.swift index af6392f2..e696a2dc 100644 --- a/Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Multiplication+Karatsuba.swift +++ b/Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Multiplication+Karatsuba.swift @@ -19,7 +19,7 @@ extension NBK.StrictUnsignedInteger.SubSequence where Base: MutableCollection { // MARK: Initializers //=------------------------------------------------------------------------= - /// Initializes `base` to the [Karatsuba algorithm][algorithm] product of `lhs` and `rhs`. + /// Initializes `base` to the [Karatsuba][algorithm] product of `lhs` and `rhs`. /// /// /// high : z1 low : z0 @@ -46,9 +46,9 @@ extension NBK.StrictUnsignedInteger.SubSequence where Base: MutableCollection { //=--------------------------------------= Swift.assert(base.count == lhs.count + rhs.count, NBK.callsiteOutOfBoundsInfo()) //=--------------------------------------= - let k0c = Swift.max(lhs.count, rhs.count) - let k1c = k0c &>> 1 - let k2c = k1c &<< 1 + let (k0c): Int = Swift.max(lhs.count, rhs.count) + let (k1c): Int = k0c &>> 1 + let (k2c): Int = k1c &<< 1 let (x1s, x0s) = NBK.SUISS.partitionTrimmingRedundantZeros(lhs, at: k1c) let (y1s, y0s) = NBK.SUISS.partitionTrimmingRedundantZeros(rhs, at: k1c) @@ -91,7 +91,7 @@ extension NBK.StrictUnsignedInteger.SubSequence where Base: MutableCollection { } let ys = NBK.SUISS.compare(y1, to: y0).isLessThanZero - if ys { + if ys { Swift.swap(&y0, &y1) } @@ -113,11 +113,10 @@ extension NBK.StrictUnsignedInteger.SubSequence where Base: MutableCollection { Swift.assert(base.baseAddress!.distance(to: pointer) == base.count) //=----------------------------------= var slice = UnsafeMutableBufferPointer(rebasing: base.suffix(from: k1c)) - NBK.SUISS.increment(&slice, by: UnsafeBufferPointer(z0)) NBK.SUISS.increment(&slice, by: UnsafeBufferPointer(z1)) - z2: do { // reuse z0 and z1 memory to form z2 + z2: do { // reuse z0 and z1 to form z2. pointee is trivial z0 = UnsafeMutableBufferPointer(start: z0.baseAddress!, count: x1.count + y1.count) NBK.SUISS.initialize(&(z0), to: UnsafeBufferPointer(x1), times: UnsafeBufferPointer(y1)) }; if xs == ys { @@ -132,7 +131,7 @@ extension NBK.StrictUnsignedInteger.SubSequence where Base: MutableCollection { // MARK: Initializers x Square //=------------------------------------------------------------------------= - /// Initializes `base` to the [square Karatsuba algorithm][algorithm] product of `lhs` and `rhs`. + /// Initializes `base` to the square [Karatsuba][algorithm] product of `elements`. /// /// /// high : z1 low : z0 @@ -147,7 +146,7 @@ extension NBK.StrictUnsignedInteger.SubSequence where Base: MutableCollection { /// └───────────────────────┘ /// /// - /// - Parameter base: A buffer of size `lhs.count` + `rhs.count`. + /// - Parameter base: A buffer of size `2 * elements.count`. /// /// - Note: The `base` must be uninitialized or `pointee` must be trivial. /// @@ -155,14 +154,16 @@ extension NBK.StrictUnsignedInteger.SubSequence where Base: MutableCollection { /// /// ### Development /// + /// - TODO: Add a test case where `elements` has redundant zeros. + /// @inline(never) @inlinable public static func initializeByKaratsubaAlgorithm( _ base: inout Base, toSquareProductOf elements: UnsafeBufferPointer) where Base == UnsafeMutableBufferPointer { //=--------------------------------------= Swift.assert(base.count == 2 * elements.count, NBK.callsiteOutOfBoundsInfo()) //=--------------------------------------= - let k0c = elements.count - let k1c = k0c &>> 1 - let k2c = k1c &<< 1 + let (k0c): Int = elements.count + let (k1c): Int = k0c &>> 1 + let (k2c): Int = k1c &<< 1 let (x1s, x0s) = NBK.SUISS.partitionTrimmingRedundantZeros(elements, at: k1c) let (z1c, z0c) = (2 * x1s.count, 2 * x0s.count) @@ -218,7 +219,7 @@ extension NBK.StrictUnsignedInteger.SubSequence where Base: MutableCollection { NBK.SUISS.increment(&slice, by: UnsafeBufferPointer(z0)) NBK.SUISS.increment(&slice, by: UnsafeBufferPointer(z1)) - z2: do { // reuse z0 and z1 memory to form z2 + z2: do { // reuse z0 and z1 to form z2. pointee is trivial z0 = UnsafeMutableBufferPointer(start: z0.baseAddress!, count: x1.count &<< 1) NBK.SUISS.initialize(&(z0), toSquareProductOf: UnsafeBufferPointer(x1)) NBK.SUISS.decrement(&slice, by:/*-----------*/ UnsafeBufferPointer(z0)) diff --git a/Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Multiplication+Long.swift b/Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Multiplication+Long.swift index 9c9dc21d..8880fa5e 100644 --- a/Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Multiplication+Long.swift +++ b/Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Multiplication+Long.swift @@ -19,7 +19,7 @@ extension NBK.StrictUnsignedInteger.SubSequence where Base: MutableCollection { // MARK: Initializers //=------------------------------------------------------------------------= - /// Initializes `base` to the [long multiplication][algorithm] product of `lhs` and `rhs`. + /// Initializes `base` to the [long][algorithm] product of `lhs` and `rhs` plus `addend`. /// /// - Parameter base: A buffer of size `lhs.count` + `rhs.count`. /// @@ -69,9 +69,9 @@ extension NBK.StrictUnsignedInteger.SubSequence where Base: MutableCollection { // MARK: Initializers x Square //=------------------------------------------------------------------------= - /// Initializes `base` to the [square long multiplication][algorithm] product of `elements` plus `addend`. + /// Initializes `base` to the square [long][algorithm] product of `elements` plus `addend`. /// - /// - Parameter base: A buffer of size `lhs.count` + `rhs.count`. + /// - Parameter base: A buffer of size `2 * elements`. /// /// - Note: The `base` must be uninitialized or `pointee` must be trivial. /// diff --git a/Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Split.swift b/Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Partition.swift similarity index 79% rename from Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Split.swift rename to Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Partition.swift index e9892d85..cdb832e2 100644 --- a/Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Split.swift +++ b/Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Partition.swift @@ -10,8 +10,11 @@ import NBKCoreKit //*============================================================================* -// MARK: * NBK x Strict Unsigned Integer x Sub Sequence x Split +// MARK: * NBK x Strict Unsigned Integer x Partition x Sub Sequence //*============================================================================* +//=----------------------------------------------------------------------------= +// MARK: + where Base is Unsafe Buffer Pointer +//=----------------------------------------------------------------------------= extension NBK.StrictUnsignedInteger.SubSequence { @@ -19,7 +22,7 @@ extension NBK.StrictUnsignedInteger.SubSequence { // MARK: Transformations //=------------------------------------------------------------------------= - /// Splits `base` at `index` then trims all trailing zeros from each sequence. + /// Splits `base` at `index` then trims redundant zeros from each sequence. @inlinable public static func partitionTrimmingRedundantZeros( _ base: Base, at index: Base.Index) -> HL where Base == UnsafeBufferPointer { let partition = Swift.min(base.count, index) diff --git a/Tests/NBKFlexibleWidthKitTests/Models/NBKFibonacciXL.swift b/Tests/NBKFlexibleWidthKitTests/Models/NBKFibonacciXL.swift index 72be52c2..275fdf57 100644 --- a/Tests/NBKFlexibleWidthKitTests/Models/NBKFibonacciXL.swift +++ b/Tests/NBKFlexibleWidthKitTests/Models/NBKFibonacciXL.swift @@ -71,7 +71,7 @@ final class NBKFibonacciXLTestsOnPrimes: XCTestCase { //=------------------------------------------------------------------------= /// https://www.wolframalpha.com/input?i2d=true&i=fibonnaci+1399 - func testPrime222() { + func testPrime0222() { NBKAssertFibonacciSequenceElement(UInt(1399), UIntXL(""" 0000000000000000000000000001057362022138877586442790693627392471\ 4349424343122542609372806319825783387389898145491654340696207977\ @@ -82,7 +82,7 @@ final class NBKFibonacciXLTestsOnPrimes: XCTestCase { } /// https://www.wolframalpha.com/input?i2d=true&i=fibonnaci+2239 - func testPrime333() { + func testPrime0333() { NBKAssertFibonacciSequenceElement(UInt(2239), UIntXL(""" 0000000000000000000000000000000000000000000037483619230023616383\ 1556956012890801755635223834456440078068598512042225565858378705\ @@ -96,7 +96,7 @@ final class NBKFibonacciXLTestsOnPrimes: XCTestCase { } /// https://www.wolframalpha.com/input?i2d=true&i=fibonnaci+4019 - func testPrime555() { + func testPrime0555() { NBKAssertFibonacciSequenceElement(UInt(4019), UIntXL(""" 0000000000000000000000000000000000000000000000000000000037311367\ 1412705742029424968910639277549742521996080310155045098365714482\ @@ -116,7 +116,7 @@ final class NBKFibonacciXLTestsOnPrimes: XCTestCase { } /// https://www.wolframalpha.com/input?i2d=true&i=fibonnaci+5903 - func testPrime777() { + func testPrime0777() { NBKAssertFibonacciSequenceElement(UInt(5903), UIntXL(""" 0000000000000000000000000000000000000000000000201630112973699547\ 8467033798246231765802235127399927076436839763410065672009048903\ @@ -140,6 +140,471 @@ final class NBKFibonacciXLTestsOnPrimes: XCTestCase { 0359205788328847352554207256070124136434254282285393279119106977 """)) } + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + /// https://www.wolframalpha.com/input?i2d=true&i=fibonnaci+8933 + func testPrime1111() { + NBKAssertFibonacciSequenceElement(UInt(8933), UIntXL(""" + 0000000000000000000000000000000000000000000000000000034443347309\ + 3108100398874159428561534329862460467290782292059374507023810687\ + 7269550645425648759105040052746760332244524364798820376920762224\ + 6877914631058402796663109018927768541957271790876482142932617519\ + 8232710764202658059416769653472274254504964579687081297720007624\ + 6179906590303417326957815996792319972853675080055992845348080638\ + 2943941858852559981242264436155281348871852261317229982765011629\ + 7829399867445887010318141926897940016990199464221680611301721448\ + 4111880877333055360925677292547757377288269228562446803652009867\ + 7763837424235481301902728930839496921587048869618933660929975972\ + 1517514025501625973594302218805499993099572559531211120925573758\ + 1127211049766617087652687605434077686156615302804722142642742969\ + 7236516259493575568417191119601844734416138650251441687029645552\ + 9378027338036524313972052854242021568214636821793074375945751372\ + 2350735288210709662405496337371540441013444112061964378877977540\ + 7320833770153605816578141282892535002595557200364506492670167145\ + 0726828768210402995804992032894376632638787592193974240697731462\ + 4173426093112813331117064297373474850946738192421094692055974066\ + 8615304600181591587016350586791290544589827230483506166379140081\ + 1359202761416259334768284612565771296621865315396703987992963690\ + 0711808907302535316355004671178400195617638079207154035431579923\ + 6275073657060236813235586961734223575624017690360671164251634053\ + 7904112899667901706234971327433315032760833359348656741794825127\ + 0980333914295583912406671914635480194147780346368616686315693921\ + 1960544365157853401078146277796468432978786175071982645306456832\ + 5121277937989335078738684451639804479205134375476415837785960261\ + 3072720886334722185655615819938336831138028603969967045606920077\ + 3923425088074927054057487079424507914976894990682897213726723706\ + 5641602992393369968566546050746410960720492622663285722794807997\ + 8311465295401210944930675482964391010652349529256594693184486853 + """)) + } + + /// https://www.wolframalpha.com/input?i2d=true&i=fibonnaci+10781 + func testPrime1313() { + NBKAssertFibonacciSequenceElement(UInt(10781), UIntXL(""" + 0000000000000000000000000000000000000000000000000005575252393938\ + 9726472552878851686358361695118909953805835298368747083115480810\ + 4134206858282412439295319058881607250949303773993738147379991278\ + 9066389219619830310354918122704287612505372628737469127809777201\ + 1813475701346979469009944172420144596984822494955177372023557647\ + 4043326938010670966508892540357298492565956868756293339723701132\ + 8404250750366560095531400297763195438809085759814739595820309501\ + 9617565922583583797982866665243330079239109282604215784965687742\ + 3199127537109325220857944750281898171470259778544608936346797087\ + 6915506943706869360771458402127275793501020646387627407249104762\ + 2204554630802927208583175306259630935067305208225373494361458800\ + 7096186599980318811061789356312606910681403036416628463971243044\ + 9676454542542605700855087919781107617713561430014113975722279770\ + 1943126909722546119017203186665120360983636830415022614609397450\ + 9604753707365780210044755881283263888107066377496681747347015615\ + 8514085822105828425523508374621670793710046241937432728541155733\ + 0914849674581293014372528590738903198794885095978076379182211356\ + 8850732564285080127893430205879638079510183584289648061314690419\ + 5135955596853796607943727322148752306247174590234861143822254810\ + 6951078192204608500403919930122086472602505237928300102314072907\ + 7179369160802122078897866161437057394653943417426366481490741361\ + 4289364844639936935015401554938898120880039903185920895379153050\ + 8680984989744643618836532812439328568169858429217482962734527536\ + 2112218628051472668046326964948590305480267978383608888402781258\ + 4039624434468498804953615649454730516079195626785256716449895062\ + 0683281068232871339690528745784450361412639047835817184698747525\ + 1330839429557363015356657024930499413609803572635586116589269321\ + 5854296106351102291227895539398459227240334326466881685777618726\ + 1211503678186890387085065010835399785997747697962920002395011222\ + 7618727367561167800274149949254487497443976531205358384475040120\ + 0086277177318594857580065894215493599194537309040684176552912227\ + 4788426089916667312131905399172381261820691014127614124391607030\ + 8838007479628295381664256933648759302881044342226521123067649434\ + 5341174643126781104974171560230306840526654475870921746361461904\ + 5207826330444519833981042764782664689188565204047957279550140376\ + 2211505037201946054045566600359608592562206893317574720788556981 + """)) + } + + /// https://www.wolframalpha.com/input?i2d=true&i=fibonnaci+14657 + func testPrime1717() { + NBKAssertFibonacciSequenceElement(UInt(14657), UIntXL(""" + 0000000006058402761451576720258256337477128057826862985648553231\ + 7792747364397931841629915181414279266064883024426628396291466122\ + 9177123797344399944935353883040192213562607370370942801296415674\ + 4831940815115011704522807000416123941229043159865494449768268284\ + 5213015343812477344582968345381553774862654915281304146488339229\ + 0905751577864480452631488961486944090768718671777277058341949909\ + 0598213463184153769971728000572922970601922048947523233477633862\ + 4605940117480893067776137041766096080844967004804117122804759466\ + 9006105930886794316120039824717802748443209168568841074845662889\ + 6935726413247146161916158962195833997261590008433017661414179268\ + 1831524200571257483454283270201487522745985204231016858721168376\ + 4204838424490224992687215838073324412818476492336363527595903974\ + 2632201125470648063465602204008209868358340208238831880244894853\ + 8380938703087695071958351874730216254209174189928645314880310832\ + 4775157435083240983288867292037332127832230384192457617428710419\ + 0419438440074229054876357310667903268539675182119923471421252525\ + 6537262552593093479745468473830739848278865552686343702365989517\ + 3773211134129308445785053068898808762947645265952573217355793055\ + 4850102686805811390241068600401491893717026095251537359730169457\ + 3990081744311735200080667940019786365915959821622418269801682716\ + 6596659992783767880986211139881334245693235383082252465376547092\ + 4771719305421775423979399445370163126666135411541089674859434142\ + 1835346304339925212842839556354290754209070463222830249340248293\ + 1739993696040883790380813459754972316938279665637020715849857092\ + 5061700639938106659144053614097794348042880102707047616330867299\ + 6973292470394688344839778152623436816659227595915321227938328341\ + 8695229413388365284802370295539401105001856037640545023329968983\ + 9720520624847273775288825663411466903136750790075145785096609543\ + 1363277499484940003702951321364758335635842013672725717191372841\ + 0065626488944560040624474939147969708428874923902611421399953582\ + 2200268101256765961743964970550205355001268110188839226049677505\ + 1623087002378031163767895174628090371966482440348951525466700490\ + 0306839887785292558258342701095931995686366367559877732669332257\ + 1358756356346230890933338073842405693054665848682078025407632677\ + 2620470192165802011259487595954200797717773358315419964815372299\ + 6195409587630063775068328208088024558415834252378093842892718929\ + 2299135473848125337595320340087904453745452079513158053622971165\ + 4085240406291974087797856713448420777479401406754652943183985557\ + 8868203699337170872194994288252608754978892688426536497188510815\ + 7364026610714838180779459845051488817988582107375830890363050042\ + 7853429696042257522758180430172108630956409978805438863836933092\ + 4739581146926696299593021918958476990679847201833345597311390365\ + 9880670405236266277006690355879105629282009156334550051866396408\ + 4563190559147446283063349456439801769070355604620364159336926897\ + 0285743171597680332987690386608022606450622931003173519957475251\ + 4421556793365867802583688605873620149902834626905930182703487959\ + 5789919592472269185943875384292090665220487632998608535326665307\ + 8322112917847080756064230443788370332329358816888052386921588637 + """)) + } + + /// https://www.wolframalpha.com/input?i2d=true&i=fibonnaci+16573 + func testPrime1919() { + NBKAssertFibonacciSequenceElement(UInt(16573), UIntXL(""" + 0000000000000000000000000000000000000000000000000000000015946921\ + 6595804360171148324186170504700247087490619017724032457673189638\ + 8406563053857414743464065246822667413694564519388262483902542550\ + 7304199719296116967907455494069941402609496025287503400080249071\ + 6799346748096884891511650411342902626468451568408085175737224043\ + 2011547064434093596081413407194809084531412469158235626097079599\ + 4544081817757745947896950418000988242770836363338053376657871411\ + 5598616012149116937365648815811675868069045756257264786759082574\ + 0379202988560687772450367294176341690396840950168827943190173803\ + 0245262792901909836914578777130937158419130954373312839400747264\ + 5070533130795934700564479352231707645378096502364456874575890898\ + 8514145855600850496027210479118770752496191274591554959033026411\ + 2683428749134631988657824553937667845055339118615142651449416358\ + 0905997624691969213616678439237042066477305009346447100369253689\ + 3688334565987554374777457109676502759096458814654042501912335167\ + 0706187390719630926967216257738013794523611050256116565490256231\ + 9891136290574443453074828513767742039568535613753300798420089272\ + 2225177115779689566506544422273288588262272759468906150468441359\ + 6397175089896071209509123875268939776743236620957310216529259099\ + 9141943426397131027691801550272209821018760599985945262861927406\ + 9308251190780234336125927386217187911053158496005341601648249672\ + 2401040493122812774460164272671061221091914763033925549937560394\ + 6559665230830369854910585292832139715324065034507736029138309482\ + 2312757918773899364634930497625081850227169787604737714651454450\ + 9516285672211250722561838052711443661737163391222573206800382956\ + 7402008355901388090106402658212300814840071046196772360719117469\ + 2048080216235350346456247064285220256191464017708412972063996814\ + 6429745908023111295091507078703296786049688925676540830776485849\ + 8883041472117433223264782663990220348815837747673458579856454849\ + 5335251858902496697861181020644338469215448158003546846387887720\ + 6220867940421580823312471707704810612356068290594335958731433012\ + 1118061742151671523996812265891356206632166854679526249246979861\ + 3021142197850694945274033708740840977830764209705180218500547661\ + 2848376395847006023633770283282925867961504875080994109763831607\ + 4976100239412235386231903470189894313193983807604929600270781698\ + 5940587113759076695652087202708375382498853097885759661720413638\ + 0416871332567363274357246862035836632999686071143579586707431914\ + 6323497245317108860950389361705272840388955884407740618983477580\ + 7383474742557888511327713349572157192934163695609946438231170881\ + 3006554862841085537945117214241498813126695273657866724995138310\ + 9635215524263847364177520635773276504929770202486144145429157848\ + 9992473449881488436645763988524107358640364006420973373647634965\ + 5593633484530004623163597754642695072841607023346144269903190617\ + 1135374869603116982074369621793523120568517217641298340701484950\ + 2187393346175963513942839492977354054626260629553898018255345302\ + 7810256629740526977349569945652764150426072332211130248793742077\ + 3544538993768616165897011514905274092992594416861406822603855795\ + 2394743069496689729862466445975464211441556129329994146357761647\ + 2115354949796735070148198059437109189897347204481506628002678173\ + 2388253133986778655734158089790160722730615407740177774172234257\ + 8539470039391426726890791083194639399663729497784731973506650313\ + 4775115288605677946764763407188650802066313549519177891446635219\ + 1824446395826617363149926246728983123254560252324359143500529411\ + 6050484096633397161792453290607298549620456797861688826608122173\ + 6904113918598297451117909653465245260904946566563300071924368393 + """)) + } + + /// https://www.wolframalpha.com/input?i2d=true&i=fibonnaci+20599 + func testPrime2323() { + NBKAssertFibonacciSequenceElement(UInt(20599), UIntXL(""" + 0000000000000000000000000000000000000000000000038629270537189582\ + 8529979283940967439802360646972098590319440271529768033095199302\ + 3758130241095668320321605582674812524751729038532342939005581191\ + 5852313415601963873313807646257614513607430604038480591636658114\ + 1034809220533683560162480040259978110450115585485701095831574534\ + 8471561702179686609282117307301726671811028923862563128730001136\ + 9304239549137433567835279117039665545538916392135319260847410090\ + 2940386106871226849989797761088211368775690846792535305626650069\ + 1533415222384985832067470926096962224231289193175887556360836199\ + 0109285065131116526146324009027018570107524189602680579137453274\ + 2933205017049164995462600901232880476529618822140951413684387115\ + 9688949251140022709919715928109411512245300615031816044721410980\ + 7971559673879717157410392220128393490438452527391110631654576188\ + 4870411289114651798946476748047091869685727271206997822805981066\ + 2547021123129285466142482836785305504602152938906455060953275327\ + 8769531288687749159393334553365369720237462193504816916687829598\ + 9027661606674579151684873036377173184232047504292671539128465465\ + 0186522318025302040007409175122452608233688868633543023529723749\ + 0971888303705851314806767584806479111949175713378702583909301852\ + 8660220367677156497008527761885684578246279285663550964684069232\ + 0485907013011203440597823338513181901298053888840395646765393453\ + 5020582849212564471509801252237360276763122153424515880682664287\ + 3560150188489961590551438617878910619974208909978145724909090884\ + 5925953690466207611034227801542453276207033245380240928462289197\ + 8829475552659578415438826807529621137018964571651029050940227311\ + 7815585849897001393958188039104380140895107981267235308324065396\ + 2643078917311865172638219233796967781193452109134743057757607085\ + 4471765406351026425518448983952031840112479488745855641116628217\ + 6083149225670926255802062023512988291943699194002057093162176484\ + 3836640836041252761384935127685044307659055293506159324674205902\ + 2883065376023512902493665587451139635468244701079910415450533837\ + 0167305370532653490899205762281435373738236077601729993676436172\ + 6674866708693149640601914370112017488386183001955416258646268328\ + 2906901681035907393036794860959587350357821360740107973168059353\ + 3170872158813005154474290054865866002216141712360701363139172433\ + 0529747633439789734038560043084297291611744800701049503511748434\ + 9444156654199694548372109881650026477209594077220020260569756967\ + 5043445683563434667094030181089841677385424941855473590669154876\ + 6825236552847508423728100327786148503950184495715149123915222188\ + 6778787577891909382358801159742037582097594000091774327237372615\ + 5591498100224308950722080362544301086324851065279058150374983047\ + 2827589535880653283965670177710328900386004750984407571799666441\ + 3219453034084247931456268333741886306507259754575478680923014795\ + 8614363552006832227029283595770467886199382519399364489861056266\ + 7986340478288414292633005943027983639213182610305303113333808723\ + 8400779440943492534930920184600153736932178875413016916496455813\ + 5498135579354763656230107008910688041759827922058978859885847163\ + 0750719599110541886157144516676995927968842277211309355808274430\ + 0668910903471153895173322232355242398046349540749419513122447306\ + 6658126222411522666207534858164122644659029739492990081078684082\ + 6121266744156663272350313936440364720678062596818917231816899522\ + 9649077315298342777221433996905557076887765706883067250140289922\ + 5192861534495673788499741227523108269807892943116237351431048158\ + 0755253280887792830212019334930546287352187134551874072371496350\ + 8720370474391049174085392413004606230451803404142078245301869866\ + 4892198696913485731552705987761774062672086299266503956939315781\ + 4134704072796931626606350420407380476632203711249610433157983535\ + 1384037365043805017015082776423061625433070372211030610324502079\ + 9110067470790193838488239591139270050806272739561744343105080195\ + 2348749294062218463990587961262685832167406776602602069764912935\ + 4921350970937422748797177694783527787331244764255839670653311966\ + 7721173723947531865654195534587908167254630232634099620460933000\ + 9901467220096254677208328109791993173057095978938176526646955118\ + 8228881106631370547849087601431485580667108502650198015351349219\ + 4270994653050751095565020351346867793055017939430766649343635841\ + 1662647627156027266594751041143972594742023010783979073324611281\ + 8261495424248772493643391973322988200766709718376917562721443421\ + 9519587071569548532206502355071998611351304749711271360148537901 + """)) + } + + /// https://www.wolframalpha.com/input?i2d=true&i=fibonnaci+26701 + func testPrime2929() { + NBKAssertFibonacciSequenceElement(UInt(26701), UIntXL(""" + 0000000000000000000000000000000000000000000000000000675300875109\ + 0234929438935188767280246631646027578654026982038645465528096242\ + 6426996474228975105541687765656964644464830940747498280830235424\ + 2031931141315983895449752055136380893919950303539820327531101620\ + 2323189593857678229639471061837212968488832795060305066128998515\ + 2445222589631354303116100098854863447094244437516950303123502395\ + 7811396615552173086277729189481229809408599467176687856100006194\ + 7969077127677930835716725707618775449761944021527033983686650799\ + 9988087731537573011024600707801055375512747543846864759999924065\ + 2958073029512845206378900624995562864258599737308623622477253238\ + 8186098584753007173913613451418080366009539886828873030677793787\ + 7982127228538580063338262699017443471208292767123511696267977938\ + 2091911574911494559385017518987699777817738874124851335636343463\ + 0719718245175997014994650123235984840183738347325700287132440309\ + 9867793431848098411705271166520994119942825801684960993541327992\ + 5251617410899876800482194741477515315650005475068525751639218059\ + 2630927130982685361384388276077280415689988666423268720052925636\ + 8777451171993973468923935147019594244224567951532774834102103519\ + 0837813583038097773455105112435571915969507201823136759111647941\ + 4954739831339596799167107440954624894201928261844208892749739653\ + 6746563504906609912279484045721419585025746486562349031240589243\ + 9261329198015939592169562410200276565268453079450074540339805658\ + 0532671887528127138285602401002971508847229188004506116260113508\ + 6166941338624254832932090374110821271794318583083483957847495995\ + 9354370411266292990181075684281401846274131626936961931105802226\ + 7505927635502703620791200053191678670633318042194353285203267290\ + 3205605630954018852233111935939120632188848966702550914162445261\ + 3485367611377869467629761543171041065701947376143667672283621617\ + 1379896374342955109313828494473119703073536842954005919813718892\ + 9293448923804331513336315874960926375113726783218069971748978232\ + 8689172475158860462745842000801015715056111594971470366663513744\ + 9583379903964710607051122069597971659442255934402348272587217554\ + 8394606450928602526521721312354359827416772710839999198330627467\ + 5117190151873093526939557238129448125114838888372864471677900013\ + 7373465358389391070601474167847485357834842600025100061435000035\ + 6118692236540156850474258346560386044659291602724753363346027221\ + 6214776214735813888062836325054654731854820935551338353077967903\ + 1273137861831440355701385090237787410627837724347994297762941733\ + 0236512351320363240096525178652160905088032203529209418992899536\ + 9374132753839217901439580336383504454125598360345021349336681071\ + 0390647650373291213880191743067349193829649286747160993444344717\ + 5264107731694812332160327259326136668727385053253031879788204680\ + 7461416228497264133998678536204389046795624613828110266563220278\ + 5149356215859435473510727920261426099081592017011119881490982949\ + 7023002067918672955927247288112423248921694513909595985051779324\ + 2510994156667269945273260236165986445851612532840180037833644309\ + 6287077541685200981777064803899487501036559502525282228254456119\ + 1070901160881141716266743149826394630340530402812049953743614839\ + 1453051301477541050346069082267332209965825572194733939498323190\ + 6805275573138154604982233504548468589880423304091815383284186840\ + 4622453269660083577638544632983245866819326330825182471007540937\ + 6266379610250376797387686495628119067659573866025580059673234197\ + 3092096076361471214691352767311049682547119749441710063154411605\ + 2464352092562762618574849072183894921899200447333098289721754567\ + 6613537085944038622683256986075357990440020263586795913304178407\ + 2281241551493302396086632997070161892094522543349019684133169470\ + 1411396169175064042200135820562002633332956274662379683672737009\ + 0659838936593902163128256612055936132983075868995168279325418925\ + 3106250930810534147888030189042307533889462307566537998210781609\ + 4735153197852048437762899958854363099078007203923210820372467968\ + 0205152820984539492603757631679212082727454614930808036105060801\ + 0230559755035990248712761413957280222008813459677547690391469083\ + 7794820341867232071597403431754582488152407830261464122639385070\ + 0777590426863435094318682572063491344895252375919108079091965422\ + 0101836570561609174623912761337832806562009926210373911779575565\ + 3846743420381552582952183232516702798153821543049757862429733447\ + 8167977685956334813323632814926669247886262219116010252040716135\ + 2897476554437321847731075037020035950383432636877380402664896032\ + 3859995452660921611533114597164502351187600869360932289993346982\ + 9857582098882760846540869838953098184391294780120384390714682114\ + 7499075897874225530699995806316633267716891194856751810563006088\ + 0199330569871792460993720245786881303112584182110447094461058185\ + 1999662418366149061526459414555506619138784703963966348504827390\ + 6863305437623123933978422736834080969892805686986939655368293371\ + 3377706557487026685257764985326698628421445516074006706169110624\ + 5298802290663799157499089134769921914923358262532475599823761560\ + 4483958565750749610881185330992185908390338629113902548769952108\ + 6830869570653210304619977381319537655491467950816307059491892261\ + 6992211184254688699789622049795884156642882638561963607005739786\ + 1988378413519337958563166745062705487428149013040630091182073186\ + 0076828872368594441240747249984053770523742798762458130752166754\ + 7365349925062180430434115813625374893611576994970704106913918722\ + 4760334451852575331317506774408478687735110293441510713556834046\ + 2511699197541436392614083156255450622336998915690629623679934131\ + 8928863961997506076922372592718381989821863599401654547051603339\ + 7697379714496516685268486237901064126719277909321728995891868709\ + 1925542849216077868099431758658201762160604000606437802340205351\ + 9143234259377166658451685076865157931596415423153810612650692201 + """)) + } + + /// https://www.wolframalpha.com/input?i2d=true&i=fibonnaci+28751 + func testPrime3131() { + NBKAssertFibonacciSequenceElement(UInt(28751), UIntXL(""" + 0000000179539422936879670273043077421513074187637090531654188941\ + 5741714251061429371751580439620520390780557350979774794868208366\ + 4166176620878272615316694300157066431179767088884468131326626406\ + 6006793087609312815351213411657546695669274095062698689154398219\ + 4273493634687995463092807527082580641615117429769927175041405435\ + 0295797490359697968749112307931392970248348413038891015623785621\ + 6088847611043512273516649762447035351619033256347137730401912564\ + 3331923459443385236632710033100206681972486278892253338953989812\ + 3946916355990491141327157042882267874194134287364062276578746447\ + 9906202330820336469762881009578044941150880449686894920299840694\ + 1491825760720059082900953382857229547427350359177762089685919844\ + 7618397959101638970146048426296929999043034632587960523515344559\ + 3760366379638998785266019668146381119294252066632685499014459540\ + 3228626661986220007077177536233318464572108992736543438403328805\ + 5574464598751322289974611560904876079017322893499933000150292780\ + 9314181521891997450492395408326917003309389028222204533522299269\ + 9642000490804899546448343060640047086553849375374919580904272499\ + 2861624797203649272053099350900207574531796666472086817602155859\ + 1726945528270185394184089768658379449840625960802021947544967032\ + 4466186751708025198780714921940794569731981222458468445510099036\ + 0443553766379370268117503080771639388168258715530538192587730633\ + 8011648767649780378020253215618980934849061793639902195268270484\ + 2839829671374952066915706595211206930317379946812934908158184018\ + 6632013950586228393873546910724730610623601482513609286385660089\ + 5583205661787583142839574359287019169878432307244569229200612045\ + 5315250627992995880563363584077006573129537285154494784466671567\ + 6932915680429008994407050765199142140297716924995768736291428740\ + 5659885583080498298853597502387982203742256599364832940936912262\ + 7306295914308130060217932216792472674883590412715203292872224381\ + 9052280939272105914017040234667970649280968676984639911487164048\ + 6950512688416085851306225825060523983737858111232273015386133906\ + 3067106584779968201933848186941851209943130293249538453239817040\ + 3166446141432467835847673289873984793187889019124685049346194236\ + 9012603600383131016803724007081968761885862426032848180961930077\ + 9950227963208023000595795424035960037191281549377793907086267841\ + 5354352203190660234784252410121708238590550542287009655613245108\ + 4416679066018355796949509138190703862193823826940976741589457419\ + 9842183809073744133600807601681164860417876735323999739439826648\ + 6396093302983871451192612904135076545912778407507119999762905951\ + 0904335217479313753450789666808129764725813866718422907715543747\ + 5344763133751758328696596023139757344616559598352109613358123372\ + 5336145288103713015016170797186814486644452292159678982593774509\ + 0858972188466104850594765553599721902079446786014336284406080746\ + 6047070155943090400227067832916854600535823815502930111708409043\ + 2646551842931647415209855009938485127601076223545576051292990210\ + 2073345189649748973785384281664653132841926472290823737428037653\ + 6301390966801847207486995822378225832339748068221848846740932398\ + 3959466133500499766954176307273566790793220329043374920481301689\ + 7354443162803012925024323638559444813297758478704463046749525448\ + 3994253427313816352373748756985250548695717403420035283611811551\ + 8903829328845718140654077721662950782418573463754497643481431064\ + 3444759787070706038677485548256120377130269594213530852587880736\ + 3063990392833728301764457275979490777842591550350013392734278293\ + 0393930894524284143461403246004295880475120230584716506627288175\ + 5954208405305936426750512693561765614064070467267484067260606449\ + 3160788244304650910047777206727593713757409794734146439721983067\ + 7409870968970884026847313052795953418080569240543747685844136978\ + 5225197858237765766397728263719405697355726278399445515930357298\ + 8820946469896191657334557780499195433494664378529806387436512888\ + 9384612665032347753991477348768850268462782942582242628537367484\ + 9666383666195546877373280285951667514644359014593205613661066790\ + 2637643008076793963393319103431361492547474087057096618104945092\ + 9068797079145859217618763638460930039892230437159663346142492177\ + 3487965404583123116632813844515253796490318415246151607418608028\ + 3165345513066792765071386479447739995779779804703780812619628392\ + 0818316702529642078660025202341533889455931013711373344622660581\ + 7998569624624648319474551095608887152210196761483059300431511310\ + 8382114269844714319724855109740243228740858105309781623648408010\ + 7923960983889953454879306942395750194186332543209679586920699011\ + 6488027814044240538940310045469339495606646708566622415099015800\ + 4029612595363304441617897449047010514432607944518064803360908350\ + 3221111187440030745261296906933672534423314714794484547420193048\ + 0822412634857367963841998731477632114802046883490061951648320782\ + 1113969713026065616413746693504606279025231159734952205068924264\ + 5445300445311422184567380131890416551079481518026600240603387378\ + 1342039627717709671407636367938362954081810163995396023446847021\ + 4631560420750186123322823291039949303888078407967268763717208095\ + 2543903864295730492482781564450746654358853202741987848049019427\ + 6997291932933637411541980129747240034390408819886320767106029202\ + 2157076256100758673195322200389179370252504774367560355559349336\ + 1421680232486838517875664644500753346409203626845922264415603503\ + 6600023866782527437887467155147365535405191710659008737894371890\ + 2544238762746656220809565535557780409118203706433673604351735361\ + 1800390642391766176484428020897344653285440131973888356373655223\ + 9957549790982938642228964935099790778423157577696154898603995912\ + 2480143799026707122818026432168253584012508348126651287673108845\ + 5775153316563617041325708734461855814522735925258064105229767393\ + 9788941361715571270608197036912192258301294845630182802656964927\ + 4745384928401986455586018549294785940736001683767865500630792096\ + 5443200185649550920854638482906746241812642506927742506108188194\ + 9878469667918098704628894843753687311207089697195422433354870257\ + 2096820521441917774150069112449092359767362686064167992531585299\ + 6612569833761373691337107507656423822097124691089029473989643597\ + 4231470719178170567974934919172609491675022209246170315053321249 + """)) + } } //*============================================================================* From 88bb4ae95d5708b3e1db03501b748e3ea07bfa4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Tue, 7 Nov 2023 12:10:22 +0100 Subject: [PATCH 119/133] [NBKFlexibleWidthKit] Cleanup. --- .../{NBK+Data.swift => NBK+Pointers.swift} | 2 +- ...gnedInteger+Multiplication+Karatsuba.swift | 3 + ...tUnsignedInteger+Multiplication+Long.swift | 3 + ...StrictUnsignedInteger+Multiplication.swift | 3 + .../NBK+StrictUnsignedInteger+Partition.swift | 85 +++++++++++++++++++ 5 files changed, 95 insertions(+), 1 deletion(-) rename Sources/NBKFlexibleWidthKit/Private/{NBK+Data.swift => NBK+Pointers.swift} (98%) create mode 100644 Tests/NBKFlexibleWidthKitTests/Private/NBK+StrictUnsignedInteger+Partition.swift diff --git a/Sources/NBKFlexibleWidthKit/Private/NBK+Data.swift b/Sources/NBKFlexibleWidthKit/Private/NBK+Pointers.swift similarity index 98% rename from Sources/NBKFlexibleWidthKit/Private/NBK+Data.swift rename to Sources/NBKFlexibleWidthKit/Private/NBK+Pointers.swift index 64fdcc1c..13e0b0d9 100644 --- a/Sources/NBKFlexibleWidthKit/Private/NBK+Data.swift +++ b/Sources/NBKFlexibleWidthKit/Private/NBK+Pointers.swift @@ -10,7 +10,7 @@ import NBKCoreKit //*============================================================================* -// MARK: * NBK x Data +// MARK: * NBK x Pointers //*============================================================================* extension NBK { diff --git a/Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Multiplication+Karatsuba.swift b/Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Multiplication+Karatsuba.swift index e696a2dc..cfa736a2 100644 --- a/Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Multiplication+Karatsuba.swift +++ b/Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Multiplication+Karatsuba.swift @@ -12,6 +12,9 @@ import NBKCoreKit //*============================================================================* // MARK: * NBK x Strict Unsigned Integer x Mul. x Karatsuba x Sub Sequence //*============================================================================* +//=----------------------------------------------------------------------------= +// MARK: + where Base is Unsafe Buffer Pointer +//=----------------------------------------------------------------------------= extension NBK.StrictUnsignedInteger.SubSequence where Base: MutableCollection { diff --git a/Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Multiplication+Long.swift b/Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Multiplication+Long.swift index 8880fa5e..d00f196d 100644 --- a/Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Multiplication+Long.swift +++ b/Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Multiplication+Long.swift @@ -12,6 +12,9 @@ import NBKCoreKit //*============================================================================* // MARK: * NBK x Strict Unsigned Integer x Mul. x Long x Sub Sequence //*============================================================================* +//=----------------------------------------------------------------------------= +// MARK: + where Base is Unsafe Buffer Pointer +//=----------------------------------------------------------------------------= extension NBK.StrictUnsignedInteger.SubSequence where Base: MutableCollection { diff --git a/Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Multiplication.swift b/Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Multiplication.swift index 04483abf..4f9e1d3b 100644 --- a/Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Multiplication.swift +++ b/Sources/NBKFlexibleWidthKit/Private/NBK+StrictUnsignedInteger+Multiplication.swift @@ -12,6 +12,9 @@ import NBKCoreKit //*============================================================================* // MARK: * NBK x Strict Unsigned Integer x Multiplication x Sub Sequence //*============================================================================* +//=----------------------------------------------------------------------------= +// MARK: + where Base is Unsafe Buffer Pointer +//=----------------------------------------------------------------------------= extension NBK.StrictUnsignedInteger.SubSequence where Base: MutableCollection { diff --git a/Tests/NBKFlexibleWidthKitTests/Private/NBK+StrictUnsignedInteger+Partition.swift b/Tests/NBKFlexibleWidthKitTests/Private/NBK+StrictUnsignedInteger+Partition.swift new file mode 100644 index 00000000..6bc3dca1 --- /dev/null +++ b/Tests/NBKFlexibleWidthKitTests/Private/NBK+StrictUnsignedInteger+Partition.swift @@ -0,0 +1,85 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +import NBKFlexibleWidthKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Strict Unsigned Integer x Partition x Sub Sequence +//*============================================================================* + +final class NBKStrictUnsignedIntegerTestsOnPartitionAsSubSequence: XCTestCase { + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testSubSequencePartitionTrimmingRedundantZeros() { + NBKAssertSubSequencePartitionTrimmingRedundantZeros([ ] as W, 0 as Int, [ ] as W, [ ] as W) + NBKAssertSubSequencePartitionTrimmingRedundantZeros([ ] as W, 1 as Int, [ ] as W, [ ] as W) + NBKAssertSubSequencePartitionTrimmingRedundantZeros([ ] as W, 2 as Int, [ ] as W, [ ] as W) + NBKAssertSubSequencePartitionTrimmingRedundantZeros([ ] as W, 3 as Int, [ ] as W, [ ] as W) + NBKAssertSubSequencePartitionTrimmingRedundantZeros([1 ] as W, 0 as Int, [ ] as W, [1 ] as W) + NBKAssertSubSequencePartitionTrimmingRedundantZeros([1 ] as W, 1 as Int, [1 ] as W, [ ] as W) + NBKAssertSubSequencePartitionTrimmingRedundantZeros([1 ] as W, 2 as Int, [1 ] as W, [ ] as W) + NBKAssertSubSequencePartitionTrimmingRedundantZeros([1 ] as W, 3 as Int, [1 ] as W, [ ] as W) + NBKAssertSubSequencePartitionTrimmingRedundantZeros([1, 2 ] as W, 0 as Int, [ ] as W, [1, 2 ] as W) + NBKAssertSubSequencePartitionTrimmingRedundantZeros([1, 2 ] as W, 1 as Int, [1 ] as W, [ 2 ] as W) + NBKAssertSubSequencePartitionTrimmingRedundantZeros([1, 2 ] as W, 2 as Int, [1, 2 ] as W, [ ] as W) + NBKAssertSubSequencePartitionTrimmingRedundantZeros([1, 2 ] as W, 3 as Int, [1, 2 ] as W, [ ] as W) + NBKAssertSubSequencePartitionTrimmingRedundantZeros([1, 2, 3 ] as W, 0 as Int, [ ] as W, [1, 2, 3 ] as W) + NBKAssertSubSequencePartitionTrimmingRedundantZeros([1, 2, 3 ] as W, 1 as Int, [1 ] as W, [ 2, 3 ] as W) + NBKAssertSubSequencePartitionTrimmingRedundantZeros([1, 2, 3 ] as W, 2 as Int, [1, 2 ] as W, [ 3 ] as W) + NBKAssertSubSequencePartitionTrimmingRedundantZeros([1, 2, 3 ] as W, 3 as Int, [1, 2, 3 ] as W, [ ] as W) + NBKAssertSubSequencePartitionTrimmingRedundantZeros([1, 2, 3, 4] as W, 0 as Int, [ ] as W, [1, 2, 3, 4] as W) + NBKAssertSubSequencePartitionTrimmingRedundantZeros([1, 2, 3, 4] as W, 1 as Int, [1 ] as W, [ 2, 3, 4] as W) + NBKAssertSubSequencePartitionTrimmingRedundantZeros([1, 2, 3, 4] as W, 2 as Int, [1, 2 ] as W, [ 3, 4] as W) + NBKAssertSubSequencePartitionTrimmingRedundantZeros([1, 2, 3, 4] as W, 3 as Int, [1, 2, 3 ] as W, [ 4] as W) + NBKAssertSubSequencePartitionTrimmingRedundantZeros([0, 0, 0, 0] as W, 0 as Int, [ ] as W, [ ] as W) + NBKAssertSubSequencePartitionTrimmingRedundantZeros([0, 0, 0, 0] as W, 1 as Int, [ ] as W, [ ] as W) + NBKAssertSubSequencePartitionTrimmingRedundantZeros([0, 0, 0, 0] as W, 2 as Int, [ ] as W, [ ] as W) + NBKAssertSubSequencePartitionTrimmingRedundantZeros([0, 0, 0, 0] as W, 3 as Int, [ ] as W, [ ] as W) + NBKAssertSubSequencePartitionTrimmingRedundantZeros([1, 0, 3, 0] as W, 0 as Int, [ ] as W, [1, 0, 3 ] as W) + NBKAssertSubSequencePartitionTrimmingRedundantZeros([1, 0, 3, 0] as W, 1 as Int, [1 ] as W, [ 0, 3 ] as W) + NBKAssertSubSequencePartitionTrimmingRedundantZeros([1, 0, 3, 0] as W, 2 as Int, [1 ] as W, [ 3 ] as W) + NBKAssertSubSequencePartitionTrimmingRedundantZeros([1, 0, 3, 0] as W, 3 as Int, [1, 0, 3 ] as W, [ ] as W) + NBKAssertSubSequencePartitionTrimmingRedundantZeros([0, 2, 0, 4] as W, 0 as Int, [ ] as W, [0, 2, 0, 4] as W) + NBKAssertSubSequencePartitionTrimmingRedundantZeros([0, 2, 0, 4] as W, 1 as Int, [ ] as W, [ 2, 0, 4] as W) + NBKAssertSubSequencePartitionTrimmingRedundantZeros([0, 2, 0, 4] as W, 2 as Int, [0, 2 ] as W, [ 0, 4] as W) + NBKAssertSubSequencePartitionTrimmingRedundantZeros([0, 2, 0, 4] as W, 3 as Int, [0, 2 ] as W, [ 4] as W) + } +} + +//*============================================================================* +// MARK: * NBK x Strict Unsigned Integer x Partition x Assertions +//*============================================================================* + +private func NBKAssertSubSequencePartitionTrimmingRedundantZeros( +_ base: [UInt], _ index: Int, _ low: [UInt], _ high: [UInt], +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + typealias T = NBK.SUISS + //=------------------------------------------= + base.withUnsafeBufferPointer { base in + let partition = T.partitionTrimmingRedundantZeros(base, at: index) + XCTAssertEqual([UInt](partition.low ), low, file: file, line: line) + XCTAssertEqual([UInt](partition.high), high,file: file, line: line) + XCTAssertNotEqual(partition.low .last, UInt.zero, file: file, line: line) + XCTAssertNotEqual(partition.high.last, UInt.zero, file: file, line: line) + } +} + +#endif From a1a33e107380f11989fc89fc274ad933429fa736 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Wed, 8 Nov 2023 14:17:54 +0100 Subject: [PATCH 120/133] Fibonacci sequence element at index by double and add composition (#109). --- .../Models/NBKFibonacciXL.swift | 54 +++++++++---------- .../Models/NBKFibonacciXL.swift | 11 +++- 2 files changed, 36 insertions(+), 29 deletions(-) diff --git a/Sources/NBKFlexibleWidthKit/Models/NBKFibonacciXL.swift b/Sources/NBKFlexibleWidthKit/Models/NBKFibonacciXL.swift index 7603a17a..7f48666d 100644 --- a/Sources/NBKFlexibleWidthKit/Models/NBKFibonacciXL.swift +++ b/Sources/NBKFlexibleWidthKit/Models/NBKFibonacciXL.swift @@ -49,29 +49,13 @@ import NBKCoreKit /// Creates the sequence pair at the given `index`. @inlinable public init(_ index: UInt) { - self.i = index as UInt - self.a = UIntXL(digit: 0) - self.b = UIntXL(digit: 1) - + self.init() var mask = UInt.one &<< UInt(bitPattern: index.bitWidth &+ index.leadingZeroBitCount.onesComplement()) doubleAndAdd: while !mask.isZero { + self.double() - var (x): UIntXL // f(2x + 0) - x = b.bitShiftedLeft(major: Int.zero, minor: Int.one) - x -= a - x *= a - - var (y): UIntXL // f(2x + 1) - y = a.squared() - y += b.squared() - - if (mask & index).isZero { - a = x - b = y - } else { - x += y - a = y - b = x + if !(index & mask).isZero { + self.increment() } mask &>>= UInt.one @@ -101,17 +85,33 @@ import NBKCoreKit // MARK: Transformations //=------------------------------------------------------------------------= + /// Forms the sequence pair at `index + 1`. + @inlinable public mutating func increment() { + i += 1 + a += b + Swift.swap(&a, &b) + } + /// Forms the sequence pair at `index - 1`. @inlinable public mutating func decrement() { - self.i -= 1 - self.b -= a + i -= 1 + b -= a Swift.swap(&a, &b) } - /// Forms the sequence pair at `index + 1`. - @inlinable public mutating func increment() { - self.i += 1 - self.a += b - Swift.swap(&a, &b) + /// Forms the sequence pair at `index * 2`. + @inlinable public mutating func double() { + var (x): UIntXL // f(2x + 0) + x = b.bitShiftedLeft(major: Int.zero, minor: Int.one) + x -= a + x *= a + + var (y): UIntXL // f(2x + 1) + y = a.squared() + y += b.squared() + + i *= 2 + a = x + b = y } } diff --git a/Tests/NBKFlexibleWidthKitTests/Models/NBKFibonacciXL.swift b/Tests/NBKFlexibleWidthKitTests/Models/NBKFibonacciXL.swift index 275fdf57..d4d8e6a9 100644 --- a/Tests/NBKFlexibleWidthKitTests/Models/NBKFibonacciXL.swift +++ b/Tests/NBKFlexibleWidthKitTests/Models/NBKFibonacciXL.swift @@ -622,19 +622,26 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual(x0.next, x1.element, file: file, line: line) XCTAssertEqual(x1.next, x0.element + x1.element, file: file, line: line) //=------------------------------------------= - increment1: do { + increment: do { var x = x0; x.increment() XCTAssertEqual(x.index, x1.index, file: file, line: line) XCTAssertEqual(x.element, x1.element, file: file, line: line) XCTAssertEqual(x.next, x1.next, file: file, line: line) } - decrement1: do { + decrement: do { var x = x1; x.decrement() XCTAssertEqual(x.index, x0.index, file: file, line: line) XCTAssertEqual(x.element, x0.element, file: file, line: line) XCTAssertEqual(x.next, x0.next, file: file, line: line) } + + double: do { + var x = NBKFibonacciXL(index / 2); x.double(); if index.isOdd { x.increment() } + XCTAssertEqual(x.index, x0.index, file: file, line: line) + XCTAssertEqual(x.element, x0.element, file: file, line: line) + XCTAssertEqual(x.next, x0.next, file: file, line: line) + } } #endif From 4854ae09acb03e81b727a286a9c902804e91f12d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Wed, 8 Nov 2023 15:16:49 +0100 Subject: [PATCH 121/133] [NBKFlexibleWidthKit] Fibonacci. --- README.md | 6 ++++ .../Models/NBKFibonacciXL.swift | 29 +++++-------------- 2 files changed, 14 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 7ad19622..b7ba9574 100644 --- a/README.md +++ b/README.md @@ -123,6 +123,12 @@ Int256(5) % Int(5), UInt256(5) % UInt(5) - [NBKFibonacciXL](Sources/NBKFlexibleWidthKit/Models/NBKFibonacciXL.swift) +### Fibonacci + +```swift +NBK.blackHole(NBKFibonacciXL(10_000_000)) // 2.3s on M1 MacBook Pro +``` + ## Installation diff --git a/Sources/NBKFlexibleWidthKit/Models/NBKFibonacciXL.swift b/Sources/NBKFlexibleWidthKit/Models/NBKFibonacciXL.swift index 7f48666d..8b0a3feb 100644 --- a/Sources/NBKFlexibleWidthKit/Models/NBKFibonacciXL.swift +++ b/Sources/NBKFlexibleWidthKit/Models/NBKFibonacciXL.swift @@ -32,34 +32,21 @@ import NBKCoreKit // MARK: State //=------------------------------------------------------------------------= - @usableFromInline var i: UInt - @usableFromInline var a: UIntXL - @usableFromInline var b: UIntXL + @usableFromInline var i = UInt() + @usableFromInline var a = UIntXL(digit: 0) + @usableFromInline var b = UIntXL(digit: 1) //=------------------------------------------------------------------------= // MARK: Initializers //=------------------------------------------------------------------------= /// Creates the first sequence pair. - @inlinable public init() { - self.i = UInt() - self.a = UIntXL(digit: 0) - self.b = UIntXL(digit: 1) - } + @inlinable public init() { } /// Creates the sequence pair at the given `index`. @inlinable public init(_ index: UInt) { - self.init() - var mask = UInt.one &<< UInt(bitPattern: index.bitWidth &+ index.leadingZeroBitCount.onesComplement()) - doubleAndAdd: while !mask.isZero { - self.double() - - if !(index & mask).isZero { - self.increment() - } - - mask &>>= UInt.one - } + var mask = 1 as UInt &<< UInt(bitPattern: index.bitWidth &+ index.leadingZeroBitCount.onesComplement()) + while !mask.isZero { self.double(); if !(index & mask).isZero { self.increment() }; mask &>>= 1 as UInt } } //=------------------------------------------------------------------------= @@ -101,12 +88,12 @@ import NBKCoreKit /// Forms the sequence pair at `index * 2`. @inlinable public mutating func double() { - var (x): UIntXL // f(2x + 0) + var (x): UIntXL // f(2 * index + 0) x = b.bitShiftedLeft(major: Int.zero, minor: Int.one) x -= a x *= a - var (y): UIntXL // f(2x + 1) + var (y): UIntXL // f(2 * index + 1) y = a.squared() y += b.squared() From fe4f8a18773f73a6deac0813b1b82c61db7331d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Thu, 9 Nov 2023 12:01:14 +0100 Subject: [PATCH 122/133] [NBKFlexibleWidthKit] Cleanup. --- .../Models/NBKFibonacciXL.swift | 21 +++++++++++++++++-- .../Models/NBKFibonacciXL.swift | 2 +- .../NBKFlexibleWidth+Division.swift | 18 ++++++---------- .../NBKFlexibleWidth+Subtraction.swift | 8 +++++-- 4 files changed, 32 insertions(+), 17 deletions(-) diff --git a/Sources/NBKFlexibleWidthKit/Models/NBKFibonacciXL.swift b/Sources/NBKFlexibleWidthKit/Models/NBKFibonacciXL.swift index 8b0a3feb..39022055 100644 --- a/Sources/NBKFlexibleWidthKit/Models/NBKFibonacciXL.swift +++ b/Sources/NBKFlexibleWidthKit/Models/NBKFibonacciXL.swift @@ -26,6 +26,23 @@ import NBKCoreKit /// NBKFibonacciXL(5) // (index: 5, element: 5, next: 8) /// ``` /// +/// ### Fast index double-and-add algorithm +/// +/// Large indices are computed using the double-and-add algorithm: +/// +/// ```swift +/// f(x + 1 + 0) == f(x) * 0000 + f(x + 1) * 00000001 +/// f(x + 1 + 1) == f(x) * 0001 + f(x + 1) * 00000001 +/// f(x + 1 + 2) == f(x) * 0001 + f(x + 1) * 00000002 +/// f(x + 1 + 3) == f(x) * 0002 + f(x + 1) * 00000003 +/// f(x + 1 + 4) == f(x) * 0003 + f(x + 1) * 00000005 +/// f(x + 1 + 5) == f(x) * 0005 + f(x + 1) * 00000008 +/// f(x + 1 + 6) == f(x) * 0008 + f(x + 1) * 00000013 +/// ───────────────────────────────────────────────── +/// f(x + 1 + y) == f(x) * f(y) + f(x + 1) * f(y + 1) +/// f(x + 1 + x) == f(x) ^ 0002 + f(x + 1) ^ 00000002 +/// ``` +/// @frozen public struct NBKFibonacciXL { //=------------------------------------------------------------------------= @@ -94,8 +111,8 @@ import NBKCoreKit x *= a var (y): UIntXL // f(2 * index + 1) - y = a.squared() - y += b.squared() + y = b.squared() + y += a.squared() i *= 2 a = x diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/Models/NBKFibonacciXL.swift b/Tests/NBKFlexibleWidthKitBenchmarks/Models/NBKFibonacciXL.swift index 9d61ebae..cbac3e5b 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/Models/NBKFibonacciXL.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/Models/NBKFibonacciXL.swift @@ -74,7 +74,7 @@ final class NBKFibonacciXLBenchmarks: XCTestCase { /// - Note: The 10,000,000th element contains 2,089,877 decimal digits. /// func testNoLoop10000000() { - NBK.blackHole(T(NBK.blackHoleIdentity(UInt(10_000_000)))) + NBK.blackHole(T(NBK.blackHoleIdentity(10_000_000))) } } diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Division.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Division.swift index 2ddf0c66..8219911e 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Division.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Division.swift @@ -217,12 +217,9 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual(pvo.overflow, overflow, file: file, line: line) } //=------------------------------------------= - guard - let lhs = lhs as? UIntXL, - let rhs = rhs as? UIntXL, - let quotient = quotient as? UIntXL, - let remainder = remainder as? UIntXL - else { return } + guard let lhs = lhs as? UIntXL, let rhs = rhs as? UIntXL, let quotient = quotient as? UIntXL, let remainder = remainder as? UIntXL else { + return precondition(T.isSigned) + } //=------------------------------------------= brr: do { let pvo = lhs.quotientAndRemainderReportingOverflowUsingLongAlgorithm(dividingBy: rhs) @@ -292,12 +289,9 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual(pvo.overflow, overflow, file: file, line: line) } //=------------------------------------------= - guard - let lhs = lhs as? UIntXL, - let rhs = rhs as? UInt, - let quotient = quotient as? UIntXL, - let remainder = remainder as? UInt - else { return } + guard let lhs = lhs as? UIntXL, let rhs = rhs as? UInt, let quotient = quotient as? UIntXL, let remainder = remainder as? UInt else { + return precondition(T.isSigned) + } //=------------------------------------------= brr: do { var lhs = lhs diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Subtraction.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Subtraction.swift index 271513d6..f12d895c 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Subtraction.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Subtraction.swift @@ -131,7 +131,9 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual({ var lhs = lhs; lhs.subtract(rhs, at: Int.zero); return lhs }(), partialValue, file: file, line: line) } //=------------------------------------------= - guard let lhs = lhs as? UIntXL, let rhs = rhs as? UIntXL, let partialValue = partialValue as? UIntXL else { return } + guard let lhs = lhs as? UIntXL, let rhs = rhs as? UIntXL, let partialValue = partialValue as? UIntXL else { + return precondition(T.isSigned) + } //=------------------------------------------= if index.isZero { XCTAssertEqual(lhs.subtractingReportingOverflow(rhs).partialValue, partialValue, file: file, line: line) @@ -160,7 +162,9 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual({ var lhs = lhs; lhs.subtract(rhs, at: Int.zero); return lhs }(), partialValue, file: file, line: line) } //=------------------------------------------= - guard let lhs = lhs as? UIntXL, let rhs = rhs as? UIntXL.Digit, let partialValue = partialValue as? UIntXL else { return } + guard let lhs = lhs as? UIntXL, let rhs = rhs as? UIntXL.Digit, let partialValue = partialValue as? UIntXL else { + return precondition(T.isSigned) + } //=------------------------------------------= if index.isZero { XCTAssertEqual(lhs.subtractingReportingOverflow(rhs).partialValue, partialValue, file: file, line: line) From a4cabbb5f94ac1aa9bc417f092c0c86b20bb3c3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sun, 12 Nov 2023 02:38:59 +0100 Subject: [PATCH 123/133] [NBKFlexibleWidthKit] No `#if DEBUG` unit testing (#112). --- .../NBKFlexibleWidth+Literals.swift | 6 +- .../Models/NBKFibonacciXL.swift | 4 - .../NBKFlexibleWidth+Addition.swift | 4 - .../NBKFlexibleWidth+Bits.swift | 4 - .../NBKFlexibleWidth+Comparisons.swift | 4 - .../NBKFlexibleWidth+Complements.swift | 4 - .../NBKFlexibleWidth+Division.swift | 97 ++++++++----------- .../NBKFlexibleWidth+Exponentiation.swift | 4 - .../NBKFlexibleWidth+Literals.swift | 6 +- .../NBKFlexibleWidth+Logic.swift | 4 - .../NBKFlexibleWidth+Multiplication.swift | 6 +- .../NBKFlexibleWidth+Numbers.swift | 4 - .../NBKFlexibleWidth+Shifts.swift | 4 - .../NBKFlexibleWidth+Subtraction.swift | 4 - .../NBKFlexibleWidth+Text.swift | 4 - .../NBKFlexibleWidth+Update.swift | 7 +- .../NBKFlexibleWidth+Words.swift | 4 - 17 files changed, 51 insertions(+), 119 deletions(-) diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Literals.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Literals.swift index bdb2329e..361a9d72 100644 --- a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Literals.swift +++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Literals.swift @@ -26,7 +26,8 @@ extension NBKFlexibleWidth.Magnitude { } } - @inlinable init?(exactlyIntegerLiteral source: StaticBigInt) { + /// - Warning: This method is only public for RELEASE mode testing. + @inlinable public init?(exactlyIntegerLiteral source: StaticBigInt) { guard Self.isSigned || source.signum() >= 0 as Int else { return nil } //=--------------------------------------= let width = Swift.max(1, source.bitWidth - Int(bit: !Self.isSigned)) @@ -78,7 +79,8 @@ extension NBKFlexibleWidth.Magnitude { } } - @inlinable init?(exactlyStringLiteral description: StaticString) { + /// - Warning: This method is only public for RELEASE mode testing. + @inlinable public init?(exactlyStringLiteral description: StaticString) { let decoder = NBK.IntegerDescription.DecoderDecodingRadix() guard let components: SM = decoder.decode(description) else { return nil } self.init(sign: components.sign, magnitude: components.magnitude) diff --git a/Tests/NBKFlexibleWidthKitTests/Models/NBKFibonacciXL.swift b/Tests/NBKFlexibleWidthKitTests/Models/NBKFibonacciXL.swift index d4d8e6a9..e51b5f93 100644 --- a/Tests/NBKFlexibleWidthKitTests/Models/NBKFibonacciXL.swift +++ b/Tests/NBKFlexibleWidthKitTests/Models/NBKFibonacciXL.swift @@ -7,8 +7,6 @@ // See http://www.apache.org/licenses/LICENSE-2.0 for license information. //=----------------------------------------------------------------------------= -#if DEBUG - import NBKCoreKit import NBKFlexibleWidthKit import XCTest @@ -643,5 +641,3 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual(x.next, x0.next, file: file, line: line) } } - -#endif diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Addition.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Addition.swift index 9f1c6315..6336478a 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Addition.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Addition.swift @@ -7,8 +7,6 @@ // See http://www.apache.org/licenses/LICENSE-2.0 for license information. //=----------------------------------------------------------------------------= -#if DEBUG - import NBKCoreKit import NBKFlexibleWidthKit import XCTest @@ -121,5 +119,3 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual(lhs.adding(rhs, at: index), partialValue, file: file, line: line) XCTAssertEqual({ var x = lhs; let _ = x.add(rhs, at: index); return x }(), partialValue, file: file, line: line) } - -#endif diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Bits.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Bits.swift index 6f56c9a8..59db0f98 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Bits.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Bits.swift @@ -7,8 +7,6 @@ // See http://www.apache.org/licenses/LICENSE-2.0 for license information. //=----------------------------------------------------------------------------= -#if DEBUG - import NBKCoreKit import NBKFlexibleWidthKit import XCTest @@ -95,5 +93,3 @@ final class NBKFlexibleWidthTestsOnBitsAsUIntXL: XCTestCase { XCTAssertEqual(T(words:[ 1, 0, 0, ~0] as W).leastSignificantBit, true ) } } - -#endif diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Comparisons.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Comparisons.swift index 995a0f1c..620b914a 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Comparisons.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Comparisons.swift @@ -7,8 +7,6 @@ // See http://www.apache.org/licenses/LICENSE-2.0 for license information. //=----------------------------------------------------------------------------= -#if DEBUG - import NBKCoreKit import NBKFlexibleWidthKit import XCTest @@ -279,5 +277,3 @@ file: StaticString = #file, line: UInt = #line) { //=------------------------------------------= XCTAssertEqual(lhs.compared(to: rhs, at: index), signum, file: file, line: line) } - -#endif diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Complements.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Complements.swift index 651d727d..306b407e 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Complements.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Complements.swift @@ -7,8 +7,6 @@ // See http://www.apache.org/licenses/LICENSE-2.0 for license information. //=----------------------------------------------------------------------------= -#if DEBUG - import NBKCoreKit import NBKFlexibleWidthKit import XCTest @@ -112,5 +110,3 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual({ var x = integer; let _ = x.formTwosComplementSubsequence(true ); return x }(), partialValue, file: file, line: line) XCTAssertEqual({ var x = integer; let o = x.formTwosComplementSubsequence(true ); return o }(), overflow, file: file, line: line) } - -#endif diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Division.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Division.swift index 8219911e..f68c8a4e 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Division.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Division.swift @@ -7,10 +7,8 @@ // See http://www.apache.org/licenses/LICENSE-2.0 for license information. //=----------------------------------------------------------------------------= -#if DEBUG - import NBKCoreKit -@testable import NBKFlexibleWidthKit +import NBKFlexibleWidthKit import XCTest private typealias W = [UInt] @@ -161,68 +159,57 @@ final class NBKFlexibleWidthTestsOnDivisionCodeCoverageAsUIntXL: XCTestCase { //*============================================================================* private func NBKAssertDivision( -_ lhs: T, _ rhs: T, _ quotient: T, _ remainder: T, _ overflow: Bool = false, +_ dividend: T, _ divisor: T, _ quotient: T, _ remainder: T, _ overflow: Bool = false, file: StaticString = #file, line: UInt = #line) { //=------------------------------------------= if !overflow { - XCTAssertEqual(lhs, quotient * rhs + remainder, "lhs != rhs * quotient + remainder", file: file, line: line) + XCTAssertEqual(dividend, quotient * divisor + remainder, "dividend != divisor * quotient + remainder", file: file, line: line) } if !overflow { - XCTAssertEqual(lhs / rhs, quotient, file: file, line: line) - XCTAssertEqual(lhs % rhs, remainder, file: file, line: line) + XCTAssertEqual(dividend / divisor, quotient, file: file, line: line) + XCTAssertEqual(dividend % divisor, remainder, file: file, line: line) } if !overflow { - XCTAssertEqual({ var lhs = lhs; lhs /= rhs; return lhs }(), quotient, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs %= rhs; return lhs }(), remainder, file: file, line: line) + XCTAssertEqual({ var lhs = dividend; lhs /= divisor; return lhs }(), quotient, file: file, line: line) + XCTAssertEqual({ var lhs = dividend; lhs %= divisor; return lhs }(), remainder, file: file, line: line) } if !overflow { - let out = lhs.quotientAndRemainder(dividingBy: rhs) + let out = dividend.quotientAndRemainder(dividingBy: divisor) XCTAssertEqual(out.quotient, quotient, file: file, line: line) XCTAssertEqual(out.remainder, remainder, file: file, line: line) } - //=------------------------------------------= + brr: do { - let out = lhs.dividedReportingOverflow(by: rhs) + let out = dividend.dividedReportingOverflow(by: divisor) XCTAssertEqual(out.partialValue, quotient, file: file, line: line) XCTAssertEqual(out.overflow, overflow, file: file, line: line) } brr: do { - var lhs = lhs - let out = lhs.divideReportingOverflow(by: rhs) + var lhs = dividend + let out = lhs.divideReportingOverflow(by: divisor) XCTAssertEqual(lhs, quotient, file: file, line: line) XCTAssertEqual(out, overflow, file: file, line: line) } brr: do { - let out = lhs.remainderReportingOverflow(dividingBy: rhs) + let out = dividend.remainderReportingOverflow(dividingBy: divisor) XCTAssertEqual(out.partialValue, remainder, file: file, line: line) XCTAssertEqual(out.overflow, overflow, file: file, line: line) } brr: do { - var lhs = lhs - let out = lhs.formRemainderReportingOverflow(dividingBy: rhs) + var lhs = dividend + let out = lhs.formRemainderReportingOverflow(dividingBy: divisor) XCTAssertEqual(lhs, remainder, file: file, line: line) XCTAssertEqual(out, overflow, file: file, line: line) } brr: do { - let pvo = lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs) - XCTAssertEqual(pvo.partialValue.quotient, quotient, file: file, line: line) - XCTAssertEqual(pvo.partialValue.remainder, remainder, file: file, line: line) - XCTAssertEqual(pvo.overflow, overflow, file: file, line: line) - } - //=------------------------------------------= - guard let lhs = lhs as? UIntXL, let rhs = rhs as? UIntXL, let quotient = quotient as? UIntXL, let remainder = remainder as? UIntXL else { - return precondition(T.isSigned) - } - //=------------------------------------------= - brr: do { - let pvo = lhs.quotientAndRemainderReportingOverflowUsingLongAlgorithm(dividingBy: rhs) + let pvo = dividend.quotientAndRemainderReportingOverflow(dividingBy: divisor) XCTAssertEqual(pvo.partialValue.quotient, quotient, file: file, line: line) XCTAssertEqual(pvo.partialValue.remainder, remainder, file: file, line: line) XCTAssertEqual(pvo.overflow, overflow, file: file, line: line) @@ -230,76 +217,78 @@ file: StaticString = #file, line: UInt = #line) { } private func NBKAssertDivisionByDigit( -_ lhs: T, _ rhs: T.Digit, _ quotient: T, _ remainder: T.Digit, _ overflow: Bool = false, +_ dividend: T, _ divisor: T.Digit, _ quotient: T, _ remainder: T.Digit, _ overflow: Bool = false, file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= let extended = T(digit: remainder) //=------------------------------------------= - NBKAssertDivision(lhs, T(digit: rhs), quotient, T(digit: remainder), overflow, file: file, line: line) + NBKAssertDivision(dividend, T(digit: divisor), quotient, T(digit: remainder), overflow, file: file, line: line) //=------------------------------------------= if !overflow { - XCTAssertEqual(lhs, quotient * rhs + remainder, "lhs != rhs * quotient + remainder", file: file, line: line) + XCTAssertEqual(dividend, quotient * divisor + remainder, "dividend != divisor * quotient + remainder", file: file, line: line) } if !overflow { - XCTAssertEqual(lhs / rhs, quotient, file: file, line: line) - XCTAssertEqual(lhs % rhs, remainder, file: file, line: line) + XCTAssertEqual(dividend / divisor, quotient, file: file, line: line) + XCTAssertEqual(dividend % divisor, remainder, file: file, line: line) } if !overflow { - XCTAssertEqual({ var lhs = lhs; lhs /= rhs; return lhs }(), quotient, file: file, line: line) - XCTAssertEqual({ var lhs = lhs; lhs %= rhs; return lhs }(), extended, file: file, line: line) + XCTAssertEqual({ var lhs = dividend; lhs /= divisor; return lhs }(), quotient, file: file, line: line) + XCTAssertEqual({ var lhs = dividend; lhs %= divisor; return lhs }(), extended, file: file, line: line) } if !overflow { - let out = lhs.quotientAndRemainder(dividingBy: rhs) + let out = dividend.quotientAndRemainder(dividingBy: divisor) XCTAssertEqual(out.quotient, quotient, file: file, line: line) XCTAssertEqual(out.remainder, remainder, file: file, line: line) } - //=------------------------------------------= + brr: do { - let out = lhs.dividedReportingOverflow(by: rhs) + let out = dividend.dividedReportingOverflow(by: divisor) XCTAssertEqual(out.partialValue, quotient, file: file, line: line) XCTAssertEqual(out.overflow, overflow, file: file, line: line) } brr: do { - var lhs = lhs - let out = lhs.divideReportingOverflow(by: rhs) + var lhs = dividend + let out = lhs.divideReportingOverflow(by: divisor) XCTAssertEqual(lhs, quotient, file: file, line: line) XCTAssertEqual(out, overflow, file: file, line: line) } brr: do { - let out = lhs.remainderReportingOverflow(dividingBy: rhs) + let out = dividend.remainderReportingOverflow(dividingBy: divisor) XCTAssertEqual(out.partialValue, remainder, file: file, line: line) XCTAssertEqual(out.overflow, overflow, file: file, line: line) } brr: do { - var lhs = lhs - let out = lhs.formRemainderReportingOverflow(dividingBy: rhs) + var lhs = dividend + let out = lhs.formRemainderReportingOverflow(dividingBy: divisor) XCTAssertEqual(lhs, extended, file: file, line: line) XCTAssertEqual(out, overflow, file: file, line: line) } brr: do { - let pvo = lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs) + let pvo = dividend.quotientAndRemainderReportingOverflow(dividingBy: divisor) XCTAssertEqual(pvo.partialValue.quotient, quotient, file: file, line: line) XCTAssertEqual(pvo.partialValue.remainder, remainder, file: file, line: line) XCTAssertEqual(pvo.overflow, overflow, file: file, line: line) } - //=------------------------------------------= - guard let lhs = lhs as? UIntXL, let rhs = rhs as? UInt, let quotient = quotient as? UIntXL, let remainder = remainder as? UInt else { - return precondition(T.isSigned) - } - //=------------------------------------------= + + guard + let dividend = dividend as? UIntXL, + let divisor = divisor as? UInt, + let quotient = quotient as? UIntXL, + let remainder = remainder as? UInt + else { return precondition(T.isSigned) } + brr: do { - var lhs = lhs - let pvo = lhs.formQuotientWithRemainderReportingOverflow(dividingBy: rhs) + var lhs = dividend + let pvo = lhs.formQuotientWithRemainderReportingOverflow(dividingBy: divisor) XCTAssertEqual(lhs, quotient, file: file, line: line) XCTAssertEqual(pvo.partialValue, remainder, file: file, line: line) XCTAssertEqual(pvo.overflow, overflow, file: file, line: line) } } - -#endif diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Exponentiation.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Exponentiation.swift index 0dde6bb7..57fa95cf 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Exponentiation.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Exponentiation.swift @@ -7,8 +7,6 @@ // See http://www.apache.org/licenses/LICENSE-2.0 for license information. //=----------------------------------------------------------------------------= -#if DEBUG - import NBKCoreKit import NBKFlexibleWidthKit import XCTest @@ -348,5 +346,3 @@ file: StaticString = #file, line: UInt = #line) { //=------------------------------------------= XCTAssertEqual(base.power(exponent), power, file: file, line: line) } - -#endif diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Literals.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Literals.swift index 10526877..e7a599a9 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Literals.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Literals.swift @@ -7,10 +7,8 @@ // See http://www.apache.org/licenses/LICENSE-2.0 for license information. //=----------------------------------------------------------------------------= -#if DEBUG - import NBKCoreKit -@testable import NBKFlexibleWidthKit +import NBKFlexibleWidthKit import XCTest private typealias W = [UInt] @@ -103,5 +101,3 @@ final class NBKFlexibleWidthTestsOnLiteralsAsUIntXL: XCTestCase { XCTAssertEqual(T(exactlyStringLiteral: "-00000000000000000000000000000000000000000000000000000000000000000000000000000001"), nil) } } - -#endif diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Logic.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Logic.swift index 7bf2e85c..72422af7 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Logic.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Logic.swift @@ -7,8 +7,6 @@ // See http://www.apache.org/licenses/LICENSE-2.0 for license information. //=----------------------------------------------------------------------------= -#if DEBUG - import NBKCoreKit import NBKFlexibleWidthKit import XCTest @@ -112,5 +110,3 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual( rhs ^ lhs, result, file: file, line: line) XCTAssertEqual({ var rhs = rhs; rhs ^= lhs; return rhs }(), result, file: file, line: line) } - -#endif diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Multiplication.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Multiplication.swift index aea4d385..ae93678d 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Multiplication.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Multiplication.swift @@ -7,10 +7,8 @@ // See http://www.apache.org/licenses/LICENSE-2.0 for license information. //=----------------------------------------------------------------------------= -#if DEBUG - import NBKCoreKit -@testable import NBKFlexibleWidthKit +import NBKFlexibleWidthKit import XCTest private typealias W = [UInt] @@ -136,5 +134,3 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual(lhs.multiplied(by: rhs, adding: addend), product, file: file, line: line) XCTAssertEqual({ var lhs = lhs; lhs.multiply(by: rhs, add: addend); return lhs }(), product, file: file, line: line) } - -#endif diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Numbers.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Numbers.swift index cf9298ad..13555a95 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Numbers.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Numbers.swift @@ -7,8 +7,6 @@ // See http://www.apache.org/licenses/LICENSE-2.0 for license information. //=----------------------------------------------------------------------------= -#if DEBUG - import NBKCoreKit import NBKFlexibleWidthKit import XCTest @@ -345,5 +343,3 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual(O(clamping: value), clamping, file: file, line: line) XCTAssertEqual(O(truncatingIfNeeded: value), truncating, file: file, line: line) } - -#endif diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Shifts.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Shifts.swift index 7b49eeb4..e0488342 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Shifts.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Shifts.swift @@ -7,8 +7,6 @@ // See http://www.apache.org/licenses/LICENSE-2.0 for license information. //=----------------------------------------------------------------------------= -#if DEBUG - import NBKCoreKit import NBKFlexibleWidthKit import XCTest @@ -211,5 +209,3 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual({ var lhs = lhs; lhs.bitShiftRight(major: major); return lhs }(), result, file: file, line: line) } } - -#endif diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Subtraction.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Subtraction.swift index f12d895c..2cfe9d98 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Subtraction.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Subtraction.swift @@ -7,8 +7,6 @@ // See http://www.apache.org/licenses/LICENSE-2.0 for license information. //=----------------------------------------------------------------------------= -#if DEBUG - import NBKCoreKit import NBKFlexibleWidthKit import XCTest @@ -180,5 +178,3 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual({ var x = lhs; let _ = x.subtractReportingOverflow(rhs, at: index); return x }(), partialValue, file: file, line: line) XCTAssertEqual({ var x = lhs; let o = x.subtractReportingOverflow(rhs, at: index); return o }(), overflow, file: file, line: line) } - -#endif diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Text.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Text.swift index 26789b9a..ab0d529b 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Text.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Text.swift @@ -7,8 +7,6 @@ // See http://www.apache.org/licenses/LICENSE-2.0 for license information. //=----------------------------------------------------------------------------= -#if DEBUG - import NBKCoreKit import NBKFlexibleWidthKit import XCTest @@ -971,5 +969,3 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual(String.init(integer,radix: radix, uppercase: uppercase), text, file: file, line: line) XCTAssertEqual(integer.description(radix: radix, uppercase: uppercase), text, file: file, line: line) } - -#endif diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Update.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Update.swift index 9df45c2c..fb929040 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Update.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Update.swift @@ -7,8 +7,6 @@ // See http://www.apache.org/licenses/LICENSE-2.0 for license information. //=----------------------------------------------------------------------------= -#if DEBUG - import NBKCoreKit import NBKFlexibleWidthKit import XCTest @@ -57,6 +55,5 @@ private func NBKAssertUpdate(_ value: T, file: StaticString = private func NBKAssertUpdateAsDigit(_ type: T.Type, _ value: T.Digit, file: StaticString = #file, line: UInt = #line) { NBKAssertUpdate(T(digit: value), file: file, line: line) XCTAssertEqual({ var x = T(words:[0, 0, 0, 0] as W); x.update(value); return x }(), T(digit: value), file: file, line: line) - XCTAssertEqual({ var x = T(words:[1, 2, 3, 4] as W); x.update(value); return x }(), T(digit: value), file: file, line: line)} - -#endif + XCTAssertEqual({ var x = T(words:[1, 2, 3, 4] as W); x.update(value); return x }(), T(digit: value), file: file, line: line) +} diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Words.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Words.swift index fae305bf..f65add2a 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Words.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Words.swift @@ -7,8 +7,6 @@ // See http://www.apache.org/licenses/LICENSE-2.0 for license information. //=----------------------------------------------------------------------------= -#if DEBUG - import NBKCoreKit import NBKFlexibleWidthKit import XCTest @@ -244,5 +242,3 @@ file: StaticString = #file, line: UInt = #line) where Base.Element: Equatable { XCTAssert(base.suffix(distance).elementsEqual(expectation.suffix(distance)), file: file, line: line) } } - -#endif From 6072ac7887e66891cb859a7de1e31cb950e9be85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sun, 12 Nov 2023 10:45:35 +0100 Subject: [PATCH 124/133] [NBKFlexibleWidthKit] README. Large integer division tests using Fibonacci numbers (#109). --- README.md | 22 +++++++++++- .../Models/NBKFibonacciXL.swift | 16 ++++----- .../Models/NBKFibonacciXL.swift | 35 ++++++++++++++++++- 3 files changed, 63 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index b7ba9574..7eff965c 100644 --- a/README.md +++ b/README.md @@ -125,8 +125,28 @@ Int256(5) % Int(5), UInt256(5) % UInt(5) ### Fibonacci +This sequence is instrumental for testing big integers, and it's fun. + +```swift +/// NBKFibonacciXL(0) // (index: 0, element: 0, next: 1) +/// NBKFibonacciXL(1) // (index: 1, element: 1, next: 1) +/// NBKFibonacciXL(2) // (index: 2, element: 1, next: 2) +/// NBKFibonacciXL(3) // (index: 3, element: 2, next: 3) +/// NBKFibonacciXL(4) // (index: 4, element: 3, next: 5) +/// NBKFibonacciXL(5) // (index: 5, element: 5, next: 8) +``` + +It uses a fast double-and-add algorithm to calculate silly numbers quickly. + +```swift +NBKFibonacciXL(10_000_000) // 2.3s on M1 MacBook Pro +``` +Or you can step through it manually if that's your preferred cup of tea. + ```swift -NBK.blackHole(NBKFibonacciXL(10_000_000)) // 2.3s on M1 MacBook Pro +public mutating func increment() { ... } // index + 1 +public mutating func decrement() { ... } // index - 1 +public mutating func double() { ... } // index * 2 ``` diff --git a/Sources/NBKFlexibleWidthKit/Models/NBKFibonacciXL.swift b/Sources/NBKFlexibleWidthKit/Models/NBKFibonacciXL.swift index 39022055..f46d9b9f 100644 --- a/Sources/NBKFlexibleWidthKit/Models/NBKFibonacciXL.swift +++ b/Sources/NBKFlexibleWidthKit/Models/NBKFibonacciXL.swift @@ -31,16 +31,16 @@ import NBKCoreKit /// Large indices are computed using the double-and-add algorithm: /// /// ```swift -/// f(x + 1 + 0) == f(x) * 0000 + f(x + 1) * 00000001 +/// f(x + 0 + 1) == f(x) * 0000 + f(x + 1) * 00000001 /// f(x + 1 + 1) == f(x) * 0001 + f(x + 1) * 00000001 -/// f(x + 1 + 2) == f(x) * 0001 + f(x + 1) * 00000002 -/// f(x + 1 + 3) == f(x) * 0002 + f(x + 1) * 00000003 -/// f(x + 1 + 4) == f(x) * 0003 + f(x + 1) * 00000005 -/// f(x + 1 + 5) == f(x) * 0005 + f(x + 1) * 00000008 -/// f(x + 1 + 6) == f(x) * 0008 + f(x + 1) * 00000013 +/// f(x + 2 + 1) == f(x) * 0001 + f(x + 1) * 00000002 +/// f(x + 3 + 1) == f(x) * 0002 + f(x + 1) * 00000003 +/// f(x + 4 + 1) == f(x) * 0003 + f(x + 1) * 00000005 +/// f(x + 5 + 1) == f(x) * 0005 + f(x + 1) * 00000008 +/// f(x + 6 + 1) == f(x) * 0008 + f(x + 1) * 00000013 /// ───────────────────────────────────────────────── -/// f(x + 1 + y) == f(x) * f(y) + f(x + 1) * f(y + 1) -/// f(x + 1 + x) == f(x) ^ 0002 + f(x + 1) ^ 00000002 +/// f(x + y + 1) == f(x) * f(y) + f(x + 1) * f(y + 1) +/// f(x + x + 1) == f(x) ^ 0002 + f(x + 1) ^ 00000002 /// ``` /// @frozen public struct NBKFibonacciXL { diff --git a/Tests/NBKFlexibleWidthKitTests/Models/NBKFibonacciXL.swift b/Tests/NBKFlexibleWidthKitTests/Models/NBKFibonacciXL.swift index e51b5f93..4d539d88 100644 --- a/Tests/NBKFlexibleWidthKitTests/Models/NBKFibonacciXL.swift +++ b/Tests/NBKFlexibleWidthKitTests/Models/NBKFibonacciXL.swift @@ -610,7 +610,7 @@ final class NBKFibonacciXLTestsOnPrimes: XCTestCase { //*============================================================================* private func NBKAssertFibonacciSequenceElement( -_ index: UInt, _ element: UIntXL, +_ index: UInt, _ element: UIntXL, division: Bool = true, file: StaticString = #file, line: UInt = #line) { //=------------------------------------------= let x0 = NBKFibonacciXL(index + 0) @@ -640,4 +640,37 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual(x.element, x0.element, file: file, line: line) XCTAssertEqual(x.next, x0.next, file: file, line: line) } + + if division { + NBKAssertFibonacciSequenceDivisionInvariants(x0, NBKFibonacciXL(index / 2), file: file, line: line) + NBKAssertFibonacciSequenceDivisionInvariants(x0, NBKFibonacciXL(index / 3), file: file, line: line) + NBKAssertFibonacciSequenceDivisionInvariants(x0, NBKFibonacciXL(index / 5), file: file, line: line) + NBKAssertFibonacciSequenceDivisionInvariants(x0, NBKFibonacciXL(index / 7), file: file, line: line) + } +} + +private func NBKAssertFibonacciSequenceDivisionInvariants( +_ dividend: NBKFibonacciXL, _ divisor: NBKFibonacciXL, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + precondition(dividend.index >= divisor.index) + //=------------------------------------------= + let difference = NBKFibonacciXL(dividend.index - divisor.index) + let division = dividend.next.quotientAndRemainder(dividingBy: divisor.next) + //=------------------------------------------= + brr: do { + var x: UIntXL + + x = division.quotient // f(x + y + 1) / f(x + 1) + x -= difference.next // f(y + 1) + x *= divisor.next // f(x + 1) + x += division.remainder // f(x + y + 1) % f(x + 1) + + var y: UIntXL + + y = divisor.element // f(x) + y *= difference.element // f(y) + + XCTAssertEqual(x, y, file: file, line: line) + } } From a2ece6b9964707a72ca00fb645d1dfd0c298a1c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sun, 12 Nov 2023 12:31:27 +0100 Subject: [PATCH 125/133] [NBKFlexibleWidthKit] NBKFibonacciXL as CustomStringConvertible. --- .../Models/NBKFibonacciXL.swift | 6 ++++- .../Models/NBKFibonacciXL.swift | 27 ++++++++----------- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/Sources/NBKFlexibleWidthKit/Models/NBKFibonacciXL.swift b/Sources/NBKFlexibleWidthKit/Models/NBKFibonacciXL.swift index f46d9b9f..5afe2698 100644 --- a/Sources/NBKFlexibleWidthKit/Models/NBKFibonacciXL.swift +++ b/Sources/NBKFlexibleWidthKit/Models/NBKFibonacciXL.swift @@ -43,7 +43,7 @@ import NBKCoreKit /// f(x + x + 1) == f(x) ^ 0002 + f(x + 1) ^ 00000002 /// ``` /// -@frozen public struct NBKFibonacciXL { +@frozen public struct NBKFibonacciXL: CustomStringConvertible { //=------------------------------------------------------------------------= // MARK: State @@ -85,6 +85,10 @@ import NBKCoreKit self.b } + @inlinable public var description: String { + self.element.description + } + //=------------------------------------------------------------------------= // MARK: Transformations //=------------------------------------------------------------------------= diff --git a/Tests/NBKFlexibleWidthKitTests/Models/NBKFibonacciXL.swift b/Tests/NBKFlexibleWidthKitTests/Models/NBKFibonacciXL.swift index 4d539d88..922fff1e 100644 --- a/Tests/NBKFlexibleWidthKitTests/Models/NBKFibonacciXL.swift +++ b/Tests/NBKFlexibleWidthKitTests/Models/NBKFibonacciXL.swift @@ -650,27 +650,22 @@ file: StaticString = #file, line: UInt = #line) { } private func NBKAssertFibonacciSequenceDivisionInvariants( -_ dividend: NBKFibonacciXL, _ divisor: NBKFibonacciXL, +_ a: NBKFibonacciXL, _ b: NBKFibonacciXL, file: StaticString = #file, line: UInt = #line) { //=------------------------------------------= - precondition(dividend.index >= divisor.index) + let c = NBKFibonacciXL(a.index - b.index) + let d = a.next.quotientAndRemainder(dividingBy: b.next) //=------------------------------------------= - let difference = NBKFibonacciXL(dividend.index - divisor.index) - let division = dividend.next.quotientAndRemainder(dividingBy: divisor.next) - //=------------------------------------------= - brr: do { - var x: UIntXL - - x = division.quotient // f(x + y + 1) / f(x + 1) - x -= difference.next // f(y + 1) - x *= divisor.next // f(x + 1) - x += division.remainder // f(x + y + 1) % f(x + 1) + brr: do { var lhs: UIntXL, rhs: UIntXL - var y: UIntXL + lhs = b.element // f(b) + lhs *= c.element // f(c) - y = divisor.element // f(x) - y *= difference.element // f(y) + rhs = d.quotient // f(a + 1) / f(b + 1) + rhs -= c.next // f(c + 1) + rhs *= b.next // f(b + 1) + rhs += d.remainder // f(a + 1) % f(b + 1) - XCTAssertEqual(x, y, file: file, line: line) + XCTAssertEqual(lhs, rhs, file: file, line: line) } } From 88e0ecbc98e526935a8096da9b34ce73fbd87bfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Fri, 17 Nov 2023 09:43:32 +0100 Subject: [PATCH 126/133] [NBKFlexibleWidthKit] Cleanup. --- README.md | 14 +++++++------- .../Models/NBKFibonacciXL.swift | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 7eff965c..9f345051 100644 --- a/README.md +++ b/README.md @@ -128,12 +128,12 @@ Int256(5) % Int(5), UInt256(5) % UInt(5) This sequence is instrumental for testing big integers, and it's fun. ```swift -/// NBKFibonacciXL(0) // (index: 0, element: 0, next: 1) -/// NBKFibonacciXL(1) // (index: 1, element: 1, next: 1) -/// NBKFibonacciXL(2) // (index: 2, element: 1, next: 2) -/// NBKFibonacciXL(3) // (index: 3, element: 2, next: 3) -/// NBKFibonacciXL(4) // (index: 4, element: 3, next: 5) -/// NBKFibonacciXL(5) // (index: 5, element: 5, next: 8) +NBKFibonacciXL(0) // (index: 0, element: 0, next: 1) +NBKFibonacciXL(1) // (index: 1, element: 1, next: 1) +NBKFibonacciXL(2) // (index: 2, element: 1, next: 2) +NBKFibonacciXL(3) // (index: 3, element: 2, next: 3) +NBKFibonacciXL(4) // (index: 4, element: 3, next: 5) +NBKFibonacciXL(5) // (index: 5, element: 5, next: 8) ``` It uses a fast double-and-add algorithm to calculate silly numbers quickly. @@ -146,7 +146,7 @@ Or you can step through it manually if that's your preferred cup of tea. ```swift public mutating func increment() { ... } // index + 1 public mutating func decrement() { ... } // index - 1 -public mutating func double() { ... } // index * 2 +public mutating func double() { ... } // index * 2 ``` diff --git a/Sources/NBKFlexibleWidthKit/Models/NBKFibonacciXL.swift b/Sources/NBKFlexibleWidthKit/Models/NBKFibonacciXL.swift index 5afe2698..09d31bd3 100644 --- a/Sources/NBKFlexibleWidthKit/Models/NBKFibonacciXL.swift +++ b/Sources/NBKFlexibleWidthKit/Models/NBKFibonacciXL.swift @@ -26,9 +26,9 @@ import NBKCoreKit /// NBKFibonacciXL(5) // (index: 5, element: 5, next: 8) /// ``` /// -/// ### Fast index double-and-add algorithm +/// ### Fast double-and-add algorithm /// -/// Large indices are computed using the double-and-add algorithm: +/// The fast double-and-add algorithm is powered by this observation: /// /// ```swift /// f(x + 0 + 1) == f(x) * 0000 + f(x + 1) * 00000001 From cb04136c2674f6b7cf470ce9fe8606cb60f22593 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Fri, 17 Nov 2023 14:51:37 +0100 Subject: [PATCH 127/133] [NBKFlexibleWidthKit] More encoding tests. MOAR! --- .../NBKFlexibleWidth+Text.swift | 1341 ++++++----------- 1 file changed, 491 insertions(+), 850 deletions(-) diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Text.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Text.swift index ab0d529b..f89dd53c 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Text.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Text.swift @@ -27,910 +27,551 @@ final class NBKFlexibleWidthTestsOnTextForEachRadixAsUIntXL: XCTestCase { // MARK: State //=------------------------------------------------------------------------= - var radix: Int = 10 - var x64 = (UInt64(), UInt64(), UInt64(), UInt64()) - var txt = (String()) + /// The bit pattern: `0xfffefdfcfbfaf9f8...0706050403020100`. + static let bytes = T(x64:[ + 0x0706050403020100, 0x0f0e0d0c0b0a0908, 0x1716151413121110, 0x1f1e1d1c1b1a1918, + 0x2726252423222120, 0x2f2e2d2c2b2a2928, 0x3736353433323130, 0x3f3e3d3c3b3a3938, + 0x4746454443424140, 0x4f4e4d4c4b4a4948, 0x5756555453525150, 0x5f5e5d5c5b5a5958, + 0x6766656463626160, 0x6f6e6d6c6b6a6968, 0x7776757473727170, 0x7f7e7d7c7b7a7978, + 0x8786858483828180, 0x8f8e8d8c8b8a8988, 0x9796959493929190, 0x9f9e9d9c9b9a9998, + 0xa7a6a5a4a3a2a1a0, 0xafaeadacabaaa9a8, 0xb7b6b5b4b3b2b1b0, 0xbfbebdbcbbbab9b8, + 0xc7c6c5c4c3c2c1c0, 0xcfcecdcccbcac9c8, 0xd7d6d5d4d3d2d1d0, 0xdfdedddcdbdad9d8, + 0xe7e6e5e4e3e2e1e0, 0xefeeedecebeae9e8, 0xf7f6f5f4f3f2f1f0, 0xfffefdfcfbfaf9f8]) //=------------------------------------------------------------------------= - // MARK: Set Up, Tear Down + // MARK: Assertions //=------------------------------------------------------------------------= - override func setUp() { - self.radix = 10 - self.x64.0 = UInt64() - self.x64.1 = UInt64() - self.x64.2 = UInt64() - self.x64.3 = UInt64() - self.txt = String() - } - - override func tearDown() { - let decoded = T(x64: [x64.0, x64.1, x64.2, x64.3]) - var encoded = String(self.txt.drop{ $0 == "0" }) + func check(_ integer: T, radix: Int, ascii: String, file: StaticString = #file, line: UInt = #line) { + var encoded = String(ascii.drop(while:{ $0 == "0" })) if encoded.isEmpty { - encoded.append(contentsOf: self.txt.suffix(1)) + encoded.append(contentsOf: ascii.suffix(1)) } - NBKAssertDecodeText(decoded, self.radix, txt) - NBKAssertDecodeText(decoded, self.radix, encoded) - NBKAssertEncodeText(decoded, self.radix, true, encoded.uppercased()) - NBKAssertEncodeText(decoded, self.radix, false, encoded.lowercased()) + NBKAssertDecodingText(integer, radix, ascii, file: file, line: line) + NBKAssertDecodingText(integer, radix, encoded, file: file, line: line) + NBKAssertEncodingText(integer, radix, true, encoded.uppercased(), file: file, line: line) + NBKAssertEncodingText(integer, radix, false, encoded.lowercased(), file: file, line: line) } //=------------------------------------------------------------------------= - // MARK: Tests + // MARK: Tests x Bytes //=------------------------------------------------------------------------= - func testRadix02Top() { - self.radix = 02 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ + func test02() { + self.check(Self.bytes, radix: 02, ascii: """ 1111111111111110111111011111110011111011111110101111100111111000\ 1111011111110110111101011111010011110011111100101111000111110000\ 1110111111101110111011011110110011101011111010101110100111101000\ - 1110011111100110111001011110010011100011111000101110000111100000 - """ - } - - func testRadix02Bottom() { - self.radix = 02 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ + 1110011111100110111001011110010011100011111000101110000111100000\ + 1101111111011110110111011101110011011011110110101101100111011000\ + 1101011111010110110101011101010011010011110100101101000111010000\ + 1100111111001110110011011100110011001011110010101100100111001000\ + 1100011111000110110001011100010011000011110000101100000111000000\ + 1011111110111110101111011011110010111011101110101011100110111000\ + 1011011110110110101101011011010010110011101100101011000110110000\ + 1010111110101110101011011010110010101011101010101010100110101000\ + 1010011110100110101001011010010010100011101000101010000110100000\ + 1001111110011110100111011001110010011011100110101001100110011000\ + 1001011110010110100101011001010010010011100100101001000110010000\ + 1000111110001110100011011000110010001011100010101000100110001000\ + 1000011110000110100001011000010010000011100000101000000110000000\ + 0111111101111110011111010111110001111011011110100111100101111000\ + 0111011101110110011101010111010001110011011100100111000101110000\ + 0110111101101110011011010110110001101011011010100110100101101000\ + 0110011101100110011001010110010001100011011000100110000101100000\ + 0101111101011110010111010101110001011011010110100101100101011000\ + 0101011101010110010101010101010001010011010100100101000101010000\ + 0100111101001110010011010100110001001011010010100100100101001000\ + 0100011101000110010001010100010001000011010000100100000101000000\ + 0011111100111110001111010011110000111011001110100011100100111000\ + 0011011100110110001101010011010000110011001100100011000100110000\ + 0010111100101110001011010010110000101011001010100010100100101000\ + 0010011100100110001001010010010000100011001000100010000100100000\ 0001111100011110000111010001110000011011000110100001100100011000\ 0001011100010110000101010001010000010011000100100001000100010000\ 0000111100001110000011010000110000001011000010100000100100001000\ 0000011100000110000001010000010000000011000000100000000100000000 - """ + """) + } + + func test03() { + self.check(Self.bytes, radix: 03, ascii: """ + 0000000000000000000000000000000000000000000000000001011122001202\ + 0221000010120021121012122122121210201121000021000121212010111102\ + 0021022202211121121121221212000020201221122210202201001002201010\ + 0210001212020121021021121001210100100102120102122200201001202102\ + 2220222111112021200221211122210111211012110122021212001101101012\ + 0200211111121022021211100122022012211112112221002121112202200001\ + 1001122202020122210212021001020200222212112100211020020010002221\ + 0111000010011011101010021210201220102122102122212202102012220100\ + 0111020201112002211002010001100110020220111111012101100222010221\ + 0010122122022201020000102121202021200201200211001212202010110021\ + 2001010202202101112000210220201111022010220200012021000020111021\ + 2201012002120201120221122221012002222200122120210000120121000201\ + 2012211022021200001122102120002110221102210110111021200002120202\ + 2010012002002102202002201200210100102202220110101222010000222022\ + 0200112200201010002020101100200110010000000002001202111210200020\ + 0002120001222001110002220220221011110011011012201210101122122001\ + 2111021020102211121020000002111101220000201210122212002012102220\ + 1110200122122112012100001022010221010222101020220010000121012012\ + 0010010122111111120110221020002211102201221020121121212111201100\ + 0200121221120002212120101220100120101121122112221220012112011121\ + 0121001121010221102001120121101000020200001000211102020110221110 + """) } - - //=----( 03 )--------------------------------------------------------------= - - func testRadix03Top() { - self.radix = 03 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 0000000000000000000000000000001202200212221120001222202211110211\ - 2122212010220102122202121101120111112200201101101222110200202110\ - 0220201022101000210101202220120002101202101120201012012212012002 - """ - } - - func testRadix03Bottom() { - self.radix = 03 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 0000000000000000000000000000000012210112211101210122010202201212\ - 2200112221212101221211222010022020100210220200100011100100222021\ - 2000121220012212111000111110212212201000011111112211120210102101 - """ - } - - //=----( 04 )--------------------------------------------------------------= - - func testRadix04Top() { - self.radix = 04 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ + + func test04() { + self.check(Self.bytes, radix: 04, ascii: """ 3333333233313330332333223321332033133312331133103303330233013300\ - 3233323232313230322332223221322032133212321132103203320232013200 - """ - } - - func testRadix04Bottom() { - self.radix = 04 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ + 3233323232313230322332223221322032133212321132103203320232013200\ + 3133313231313130312331223121312031133112311131103103310231013100\ + 3033303230313030302330223021302030133012301130103003300230013000\ + 2333233223312330232323222321232023132312231123102303230223012300\ + 2233223222312230222322222221222022132212221122102203220222012200\ + 2133213221312130212321222121212021132112211121102103210221012100\ + 2033203220312030202320222021202020132012201120102003200220012000\ + 1333133213311330132313221321132013131312131113101303130213011300\ + 1233123212311230122312221221122012131212121112101203120212011200\ + 1133113211311130112311221121112011131112111111101103110211011100\ + 1033103210311030102310221021102010131012101110101003100210011000\ + 0333033203310330032303220321032003130312031103100303030203010300\ + 0233023202310230022302220221022002130212021102100203020202010200\ 0133013201310130012301220121012001130112011101100103010201010100\ 0033003200310030002300220021002000130012001100100003000200010000 - """ - } - - //=----( 05 )--------------------------------------------------------------= - - func testRadix05Top() { - self.radix = 05 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 0000000000000000012224200130200441041444042343242340402322434230\ - 2203100014323101131021202442142123441124102101232423332422334024 - """ - } - - func testRadix05Bottom() { - self.radix = 05 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 0000000000000000000424043311031102404011202312202132022104340041\ - 4431003121344314114341012313341313423214420311244321214230031301 - """ - } - - //=----( 06 )--------------------------------------------------------------= - - func testRadix06Top() { - self.radix = 06 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 0000000000000000000000000000102141010531040333210533123011525130\ - 3433311132532415235332533224344010103324220312020213104050423132 - """ + """) } - - func testRadix06Bottom() { - self.radix = 06 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 0000000000000000000000000000004353050531332542114015530141512113\ - 1210015440102001011522210020211244125255022541512055450000200144 - """ - } - - //=----( 07 )--------------------------------------------------------------= - - func testRadix07Top() { - self.radix = 07 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 0000000000000000000000000000000000001305333621612661215031353503\ - 1603616341660421351201115002605631306624232666655230226263060363 - """ + + func test05() { + self.check(Self.bytes, radix: 05, ascii: """ + 0000000000000101011133132112303401331203113040334201212224114333\ + 1331210120311431302322401423134214144114302234223323124032013102\ + 2031310012312133044114114101403342401111141021424131121343010430\ + 1421121331201040013433442113440322214443111221044313323014144300\ + 0442200211013021440424413104144331034304433134022344442034220120\ + 0203022440403030041413132134201411232022143440134130244204021202\ + 4204221131331321003014044044023244032003434441023101312044413410\ + 1432032422222011101300422133144024022310244143301333333131313132\ + 1133101212222113330424040311111134211430243400332404421303012024\ + 3301033334140414340340314003013204313402213301322411212023034201\ + 2004134224142103031424130211110200431412144004241140022344304021\ + 2024422012034413242431014044023232132211032301042413413421403001\ + 0304124320331131120040124432124112202220433320304324003340021343\ + 1324223134224004424011000321223301220134021034313232023030324130 + """) } - - func testRadix07Bottom() { - self.radix = 07 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 0000000000000000000000000000000000000114142063044505436351120634\ - 3333263503132100565010106005630324255134635601621240633030645403 - """ + + func test06() { + self.check(Self.bytes, radix: 06, ascii: """ + 0000000000000000000000000000000000000001345131000552333115344121\ + 1214023443243324324333122442522233415252532225231130540122100214\ + 0215244235522514322330122325410454305413105211242412413243515420\ + 4031415411205525200543134520405500520504130422250301225525122255\ + 5304444554221253253024400132115002405214044033240245530335422552\ + 3230145401344324044315001345525133204253014235441544150342233311\ + 3102525333433242251435152053450224205545410400155320525214003341\ + 0114031334552553523440515235201104055151034451040431352324424022\ + 3220325011454332550413335135033252231132320134203510232401355331\ + 2020345410240441033104340125314154522445134135421334244051303551\ + 0152420450032004440445510515505305150554300514513545121304233402\ + 1512140511314534242423200345252352143342420322435054213022035002\ + 4325250215312305241230104233141315022325103343150130404400523320 + """) } - - //=----( 08 )--------------------------------------------------------------= - - func testRadix08Top() { - self.radix = 08 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 0000000000000000000000000000000000000000001777767737637376574770\ - 7577336575171762743703577356675472765351721637467136234370560740 - """ + + func test07() { + self.check(Self.bytes, radix: 07, ascii: """ + 0000000000000000000000000000000000000024653320130023336353601340\ + 0355512020400135330313404163116323361665214341655231546035543041\ + 3335061463602013225153316300026621432263543366545536433610205024\ + 3003025201644424044635410411626456311635136110623401315661102442\ + 0612331166566162241453601510216450625624416556453020643500526255\ + 4225530231005403046503563131246643640004650324634650424453045323\ + 3644226261554166110441022133064452150660600363500515360604100635\ + 1324126506201641562342434011560236352122640326266120664210323233\ + 2635011020024026201015103132011050236605005335425545336151120104\ + 5113112534231011226633116051366211215560241650222456652010032225\ + 3614546631516640255632303266244531025632554125633416523166131412\ + 3533422165650541466015660324101553116436025240606246521266532034 + """) } - - func testRadix08Bottom() { - self.radix = 08 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 0000000000000000000000000000000000000000000174360721603306414430\ + + func test08() { + self.check(Self.bytes, radix: 08, ascii: """ + 0000000000000000000003777757677476775371761737667537236374570760\ + 7376735573165752723643477156274470761341701577366735633366554730\ + 6575332565151722643503176354671462745311621437066134230360540700\ + 5773727557135672563342675553266454731261541276565332625352524650\ + 5172324551121642503202374751663446715231461136264531222344510620\ + 4370721543105612423042074150260440701201400775763727617336474570\ + 3567316535071562342701573346655432665151320635463126214330460540\ + 2765713527055532262541272545252424651121240475162324611322444510\ + 2164310521041502202400771743647416635071160334661523206314430460\ + 1362705513025452122240471142244410621041100174360721603306414430\ 0561302505011422042100170340641402605011020034060120200300400400 - """ - } - - //=----( 09 )--------------------------------------------------------------= - - func testRadix09Top() { - self.radix = 09 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 0000000000000000000000000000000000000000000000052625846058684424\ - 7876381258254151448064135842067326638330711686502352346635185162 - """ - } - - func testRadix09Bottom() { - self.radix = 09 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 0000000000000000000000000000000000000000000000005715741718122655\ - 8048777185486326632382030431086760556185430443785630144484523371 - """ - } - - //=----( 10 )--------------------------------------------------------------= - - func testRadix10Top() { - self.radix = 10 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 0000000000000000000000000000000000000000000000000011579030850545\ - 5567723526024286119531261069242336003260839703036409543150199264 - """ - } - - func testRadix10Bottom() { - self.radix = 10 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 0000000000000000000000000000000000000000000000000001407490462640\ - 1341155369551180448584754667373453244490859944217516317499064576 - """ - } - - //=----( 11 )--------------------------------------------------------------= - - func testRadix11Top() { - self.radix = 11 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 0000000000000000000000000000000000000000000000000000010019774172\ - 675069499548a05a7794803603a4157366204225264092700a8157a30a948720 - """ - } - - func testRadix11Bottom() { - self.radix = 11 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 0000000000000000000000000000000000000000000000000000001380227a9a\ - 3a453071005401517000a3500756239a46834284766655651370a28295109a06 - """ - } - - //=----( 12 )--------------------------------------------------------------= - - func testRadix12Top() { - self.radix = 12 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 0000000000000000000000000000000000000000000000000000000029231468\ - 41b6624b4657b76b759711256462675490811529026b8b03507956b900591aa8 - """ - } - - func testRadix12Bottom() { - self.radix = 12 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 000000000000000000000000000000000000000000000000000000000404b13b\ - 22595a847521b8ab337490660a0b7439b1495399a8b2918a9521301732309054 - """ + """) } - - //=----( 13 )--------------------------------------------------------------= - - func testRadix13Top() { - self.radix = 13 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 0000000000000000000000000000000000000000000000000000000000178a92\ - 980701228a277594134c94bb7165a938c70c03a705750115a339820831351c78 - """ - } - - func testRadix13Bottom() { - self.radix = 13 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 00000000000000000000000000000000000000000000000000000000000268a5\ - 1c5770b549c51487a17526804a0a14c0c44bbc981573456a275580297a4a7834 - """ + + func test09() { + self.check(Self.bytes, radix: 09, ascii: """ + 0000000000000000000000000000000000000000000000000000000001148052\ + 2700350753557855364700701776344207282747547855006657583681032633\ + 2305521723753171031251258063167286874467627748714735418255041335\ + 2074453825431826574548707748260131582218725231220885470736203087\ + 1400313433325365637837878236581014221462732101313226444171328127\ + 0357828120037766762162405566340761122671460726644263820167006437\ + 8116252152758716288057670051702165738250048376073842713437602522\ + 6316207266265071038281335810086820480633066340613100002052453606\ + 0250186140282683440413565334856174236384536002441800653585065386\ + 4361857517003812712833680301716503118444513836084381836547774640\ + 2055750277635631634757585617514717047127361517330220030742213843 + """) } - - //=----( 14 )--------------------------------------------------------------= - - func testRadix14Top() { - self.radix = 14 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 0000000000000000000000000000000000000000000000000000000000001c38\ - 14cbd353812dca285cc376972998797340345da539017abd8236000c88ca00da - """ + + func test10() { + self.check(Self.bytes, radix: 10, ascii: """ + 0000000000000000000000032316509077753586139510713445660514514047\ + 1715800934968659014776021432245405574123404729692361840203777454\ + 0863807743939745614194869975427379141886998502749960224378577364\ + 6750786158629119897527698459159582903277348091197804306308450975\ + 2765897157258671077139706248797954495766510537726453385451362891\ + 2932640350906509210810910107747204614412263847494852734365334510\ + 5797020149055603954704727773430317796884279167058635246262041734\ + 9145786264563977273862044757186140910253489061210709169291375411\ + 8235589361595220880511748744523688475088623430039909767486996242\ + 6348425792929710270231641017897005896324246640151098893336183040 + """) + } + + func test11() { + self.check(Self.bytes, radix: 11, ascii: """ + 0000000000000000000000000000000000000000000000010142aa3554859615\ + 1a9204496a56113782737a0530594194878213854265484228a2873210376102\ + 298531554729267773485a52aaa2030350391963a7a0a94819183a184061767a\ + a1664196a92a29124a90906677a6159283540713930a23461662230751976003\ + 75aa406a38a465902249a525645153a635a40a420899916a90a1749213325274\ + 6766792593268189a459a23695332111336a2574023146139a17034537465a24\ + 8967a2a50a37a69914126a360951448575372782095382a02084543002870940\ + 85532153a572629110a97679073778890291691419a246a95a6016478938298a\ + 358425533763a551898a379424822a252aa411a696485496052a6871743a226a\ + 8989647385195622111666334615228957638330392039898693611430034583 + """) } - - func testRadix14Bottom() { - self.radix = 14 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 0000000000000000000000000000000000000000000000000000000000000329\ - 76a45325cd6dda6ac91cb8c9bccbbc61488833c2225a774c2da97ab4d4565d3a - """ + + func test12() { + self.check(Self.bytes, radix: 12, ascii: """ + 00001b9367266a6039066116339183036aaa985742938485bbb3a46470645276\ + 569234baa5161788742348681a4a5b25ba61622633b09273b03b9aaa7514aa58\ + 900baa9a74852ab0219481b21a86a3153bab534868478662a6191b1659b54964\ + ab9654b6430343071b655848847330017058b16480bb191b0985b8521152b521\ + 563996041b3a74992b7126029326661485b6632a381a4ab4a820460396996731\ + 1955a0b949642455a94aa27512b620a30373879b06207879078319104b12b4b9\ + b2ba94a962459429a746627b83089334822b767922152b60a66b497450a07244\ + b845b1558994981851b953005363a121880435bb95b546ab1558447212026a12\ + 954b5492aa0367a34a0a961a50ba9a07b6279269932a4957a644a2a3a3920540 + """) } - - //=----( 15 )--------------------------------------------------------------= - - func testRadix15Top() { - self.radix = 15 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 0000000000000000000000000000000000000000000000000000000000000042\ - 314e1223518107b1362e160a5ad29226b4e3e2d35ea57996aaa3242db02966ae - """ + + func test13() { + self.check(Self.bytes, radix: 13, ascii: """ + 000000000000000000000031cb7486735908c0144bc1018ac182c82a930a12ca\ + 74aa7825455c0218a1479ca12843cb94baa0938378c1c8384b19b34340a64b01\ + 4c927b86217b9a059379c40089c4314b035b5c702c8371c7c80104445bc99b56\ + 057a91abc9acb1bc37950647b72045a5a647587b15c865bb75c2380191829a66\ + 04a1184400818b29b9513b8c59490494649a18069b449c472c2366c76a2ca852\ + 5096cc27207409700b2a636668139b428455c9a6ac67131b4589833577743c3a\ + 7a091a293275c628b8a06625cb2a15734b58b3a57163a48014a7a5c277499614\ + 79955285c36bc06b629543773288158648aa581166a042608899014254840857\ + 15273b93212a908443abc9abc7929ba5810113319924a7468970130052605289 + """) } - - func testRadix15Bottom() { - self.radix = 15 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 0000000000000000000000000000000000000000000000000000000000000007\ - 864d3605e05bd91d94b651ccc4e3078d6edc902745e03953a310b0de5c602701 - """ + + func test14() { + self.check(Self.bytes, radix: 14, ascii: """ + 00000000000000000000000000000000000000ad0745312ac38003406c77772a\ + c5d337dc56d71b0120a8035c347cd412ba206c7a19b3638983ad6c7dac8866db\ + ad3165c94d93a13248c199cda6773520749b9430c797c2bb0d8ca867ba5a063b\ + 83d226939c0cbd8ab945b687021c84a90d7ba0d68cd37869a55260d1d780666b\ + 0b6a3a99600cd5b1d80b84cc30bd74702723a1126cbdb5a42c285669194da766\ + c63c8d6d1aad3cc15dda115b2445580577049b2b7b818a839a3d0713a25586d3\ + 109b2a74bb9cb5947074d06003a7d8559a8ab638c511c84c158d5c7033b7385d\ + 777b7d6c35b83b7c4a497aa9b859dc77b943581b1799d547b62548548666b945\ + 8d240951c39596c82589a5602b65a7c3b356a46269456953341674c2567b81c4 + """) } - - //=----( 16 )--------------------------------------------------------------= - - func testRadix16Top() { - self.radix = 16 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e0 - """ + + func test15() { + self.check(Self.bytes, radix: 15, ascii: """ + 0000000000000000000000000000000000000000000000000001adcc42d77564\ + 2e8d25576598e679706b39b634284eb4323514682a6a176bc422a0b453010958\ + 11db137066d571a2b91ec47eb29e5870c08bb8759a29eae1e60de477c04c2c97\ + a272774aaa2573b20764ea2a18c62d7c3660ec0387a7b658d71e5d9dc14245d0\ + 163d05e294dac37d9a00339a9b41ee29b3c604d4350739ee6c2617a77c226325\ + 8d6ca4cd40eb15b65a6341963a35035c8441616e6c21e1ec9d1bd1e3ed0a7c5b\ + 349c68802a1365081776371784a3c99b4ab7774eaa850176c7e9d1c8cda75827\ + 5e4ab4757030038b383714cd32c87c560ab2ecb8d102219ec16d0616544bcb2b\ + 651732d918a54ee364a155a488725ac7ce563e994b90e86e485ad50d52e0aab0 + """) } - - func testRadix16Bottom() { - self.radix = 16 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ + + func test16() { + self.check(Self.bytes, radix: 16, ascii: """ + fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e0\ + dfdedddcdbdad9d8d7d6d5d4d3d2d1d0cfcecdcccbcac9c8c7c6c5c4c3c2c1c0\ + bfbebdbcbbbab9b8b7b6b5b4b3b2b1b0afaeadacabaaa9a8a7a6a5a4a3a2a1a0\ + 9f9e9d9c9b9a999897969594939291908f8e8d8c8b8a89888786858483828180\ + 7f7e7d7c7b7a797877767574737271706f6e6d6c6b6a69686766656463626160\ + 5f5e5d5c5b5a595857565554535251504f4e4d4c4b4a49484746454443424140\ + 3f3e3d3c3b3a393837363534333231302f2e2d2c2b2a29282726252423222120\ 1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100 - """ - } - - //=----( 17 )--------------------------------------------------------------= - - func testRadix17Top() { - self.radix = 17 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 05g7d81gc01cdbf42565444eaa12342c35gd9f66bbg36c8d8841baa7a8faab0e - """ - } - - func testRadix17Bottom() { - self.radix = 17 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 00c5b2gcge3c140g4d527274dgd5cg7g58babg3e21bg76739a559151527ce653 - """ - } - - //=----( 18 )--------------------------------------------------------------= - - func testRadix18Top() { - self.radix = 18 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 0031fhf5dce9fgc12bg164e9h35028896f83ddhh8be5286c3e9h17360bg1bg32 - """ - } - - func testRadix18Bottom() { - self.radix = 18 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 0006e51f0da7284a3bb14747c33cgb1hfa3120c549aec7hh58g39hg075a02c3a - """ - } - - //=----( 19 )--------------------------------------------------------------= - - func testRadix19Top() { - self.radix = 19 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 000237ibab6cg652id30fgh76hdai93dhfh7dhagfdc5eb7f782c55d551ed74g6 - """ - } - - func testRadix19Bottom() { - self.radix = 19 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 000050cae6cb5210060eg1g2iicc8e689a04g25829g2f5bc8c84ea4a8a1348f4 - """ - } - - //=----( 20 )--------------------------------------------------------------= - - func testRadix20Top() { - self.radix = 20 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 000020392d6ac9d1jd12d3a88c61i7ba748483ai05hf66c6a7g42977fbe8ei34 - """ - } - - func testRadix20Bottom() { - self.radix = 20 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 000004hd5e33e5189jajhc248c2a513ae74fba267d1b3d1743i8ebgb30i9318g - """ - } - - //=----( 21 )--------------------------------------------------------------= - - func testRadix21Top() { - self.radix = 21 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 0000027gdj7593kjg0f1c5cga4aca1e1d5f08h72cebhcbc1c6cek06cf13eaddh - """ + """) } - func testRadix21Bottom() { - self.radix = 21 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 0000006124cec92463a07f87dgg069g06715hcg4j03fha2f1gafce80g895g09a - """ + func test17() { + self.check(Self.bytes, radix: 17, ascii: """ + 0000000000124b16c3g69bbbag36b77367c8366826a1260aafe896c41e5bebd6\ + eff1edf76b5c850269d547g2993fg898a7eg88g8db235g6c407d4898b5a17d05\ + 9g1d0fc9bgf991cagd36gae0bag2bg730e02b8265dg2e55825g7cdfe2fgedcg1\ + ba3dcc62916e6d11ggf6c160e48154efaf86ce618584dba7d1049ge226f62945\ + cgde056dffgb718cb2211bg5g72g77d5agd7e6b055e6b4ge71gg2e56be45c585\ + e31a98e65adc1c4560b001595gee6a7ec3cdgfb6248a0e351c5fa7gd40bc4afd\ + 2cddf99e175db6fgf31545e48gfb055b4g39cca53b5a97f743922d73b7afb7d7\ + 4928154d92b20gg7992e38cb96c1dd4bea7c7728fgb1127e0e47469feag585g0 + """) } - - //=----( 22 )--------------------------------------------------------------= - - func testRadix22Top() { - self.radix = 22 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 0000003b5jk54f19beiidebchgec3ffc28aggdd74h75ijdc00i4ea0ji14954c0 - """ - } - - func testRadix22Bottom() { - self.radix = 22 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 000000098djlg8ll6ge66j798kd129gf43e7c6586a31h5a25adg2l78kj3a82b6 - """ - } - - //=----( 23 )--------------------------------------------------------------= - - func testRadix23Top() { - self.radix = 23 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 000000069a79baglcjbdblbk5111bb46b66g2b7a2f596763kmm7c3hbl336kl14 - """ - } - - func testRadix23Bottom() { - self.radix = 23 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 00000000hl580j6lii99g9c5137ji22ab5i41mba3lh6091cakd4h6llil689h12 - """ - } - - //=----( 24 )--------------------------------------------------------------= - - func testRadix24Top() { - self.radix = 24 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 00000000e4eikjgk76jj7i2fbn6ihk3ngef39fb00gjl3086em4k7g3ag5647hh8 - """ - } - - func testRadix24Bottom() { - self.radix = 24 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 000000001h9gbi9kc8ig99kj5lil4in9d6e81la5d0h872fff899ebj57j88732g - """ - } - - //=----( 25 )--------------------------------------------------------------= - - func testRadix25Top() { - self.radix = 25 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 000000001cea1fa4l49o4dnedkkdcnmfc3509hg185baem9bdo6e5b1dediecike - """ - } - - func testRadix25Bottom() { - self.radix = 25 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 0000000004e4i6362kk6ad7abh2b4j0log0gbjn96nl1d8j88mh9m36enbbmf381 - """ - } - - //=----( 26 )--------------------------------------------------------------= - - func testRadix26Top() { - self.radix = 26 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 0000000004dd8f12of8578gn3cho4kjg1nm4ck49ihk7nahjpeie4d78426fjja8 - """ - } - - func testRadix26Bottom() { - self.radix = 26 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 0000000000e7a4822n1867n87cpm330nai4o7gj05b5j013bb0in29cncoodh584 - """ - } - - //=----( 27 )--------------------------------------------------------------= - - func testRadix27Top() { - self.radix = 27 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 0000000000fo7qe0hopd7gqfbj7q7m4jdh2445pb279oj8a0lakof2akafj55n52 - """ - } - - func testRadix27Bottom() { - self.radix = 27 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 00000000001p4pcg5j6ogq1hng5neo9oj2bk10d12on0go5nd0dcnnj04demflba - """ - } - - //=----( 28 )--------------------------------------------------------------= - - func testRadix28Top() { - self.radix = 28 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 000000000028lp360pqr9fgjmgalj15e5kknmk8pd61irgj23bbe6nbafahp3e6o - """ + + func test18() { + self.check(Self.bytes, radix: 18, ascii: """ + 0000000000000000000018bga551hha58097eef06aa64bdbh0172b1dcf80417e\ + g30bdd9b1ac2bf53e416fgc92ef713dh5gfc36gcfa8961d4c4eef393d8c95hc4\ + 0bf67b02ag05e7g833b3g6372d4b45169d4693ee6h64h53h6f9c34105cchd1b7\ + 85h609326e8b38343d11a48cebcd7gd402h9d1gb4d9g74f33h1b6d5d47bd9bcf\ + h477eb91g0dd00f428942a478b32bb0eeddb0ch9822e66dbfd615bg4598h7eca\ + 87f81ade8268f1c0fed0b0bh607g9dff3800a9ed58c0036d0258393463e561f1\ + 96ag9g9d2af8495ge2bg3d961a7c04gf931h399da9f8g0d7540b9458fag6d4g1\ + 85055ae5915ch6e98ab88g522b1cb92872cah62f92aa4c75ddg37ed0e80g746c + """) } - - func testRadix28Bottom() { - self.radix = 28 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 000000000007odiqi7ipkbell34qeml609e642lhrao5n03422ik497coam17kmo - """ + + func test19() { + self.check(Self.bytes, radix: 19, ascii: """ + 0000000000000000000000000000017g2f692gg45a5gdf57gcg2g07g4h04bhfa\ + f8c01abeh9d0da94477aa600ddg25953cbh2363a71ghfdehi84ce7782ba4h3i0\ + 3a3822ff9dg3hfh8h61cf785057g74ea5c4821g6ii4h020eif1992fihdh9hedf\ + 020e2dfi21cii026d675dh1819abb0h2bd231egc2h34ei7egf3f4fg2dh0c7422\ + a26c52hgfe1cih2a6ahadie59ae8082c8e0ib75a3h9gdc10bh4d8969b7h57i38\ + 2fb4806i8829h9591ch498hhc7b7d4c9f4d0gb28g72419a2298b3fa9731a32dc\ + d312cai90h6fi0g8401c1561f97gg2fia9822h6575ab83id41bab5cgbgihdaee\ + 7aib31f1gah964c8076a4a1c91ghb0bg7hb407f2h52e28c213d98b3156g85i51 + """) } - - //=----( 29 )--------------------------------------------------------------= - - func testRadix29Top() { - self.radix = 29 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 00000000000acrhqlapaaob766is1eng6erp522m0f5opigage3d3j4k7f9n8ff2 - """ + + func test20() { + self.check(Self.bytes, radix: 20, ascii: """ + 00000000000000000000000000000000000000d5050cagd94ghbfad415d73775\ + 385hih85hd9d80ec925gehjg1j04f2hhiahd169328ai8099750j9jf64g3eg281\ + 863fi1cihc58jdec239iea6i88ci5640be2eddf81i0fj3005gib3ja486927438\ + 6b499cdjj20f29d033023fa1f790bd472c7654g8b4eia3caf829di82457dgd8e\ + f03ch599i30j2bi0f383j43c59035c93d36g7h833ce0hd7555c378hh728j723b\ + 71j23d885j99j36eb72703a83a5418h5ha0bcai1f6724dabd294104ieff49f37\ + ed043626hj5g7eccjjd76chd29g1a2520a88j370bcgac00a5j4h24dc168jgc16\ + 431i8ced8d553fa0jg40cd577ich5ce5a93e8i8jdfa192c27390cff0a87b2hc0 + """) } - - func testRadix29Bottom() { - self.radix = 29 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 0000000000017nr4pcg1heg13dh8cgggmn4q34frqm65gn8ec0j45591bmqfhffb - """ + + func test21() { + self.check(Self.bytes, radix: 21, ascii: """ + 00000000000000000000000000000000000000000000025c52fbheeggjg8507d\ + fje9hf92hjbbficeaf8fi1634i6dbc8ccc4bci9a754b580283fibjbkkbdg8080\ + 26g8e9h734gjj5547ek5hdafj86jab9kf90k9gg6ijiad7415f2eecba9k15891i\ + i929h5478643id40cfhfj51737ga9ggh2281a726a517daefbjafa83kegkgc6gg\ + e2a12973961j9d6ee925i231ja10046cka7j1ckg1391g5h35bj286a0ia14k0d3\ + 3b6c7bi2278fffj4674h6bcjhhi4bg0f65h5h36878023282j9jc9c131di2ake8\ + ka3geadbckebhk979843g6ki6hbkh3a5h4k262h0g6f89k4896gk6aj93g8gje63\ + 409g09916bb8e39hi5ci6djciki7hbd192de689hfjcab3ca39ie0fhg21ea33ji + """) + } + + func test22() { + self.check(Self.bytes, radix: 22, ascii: """ + 000000000000000000000000000000000000000000000000000023icle03ja5d\ + 3hla1053987fc3i93924f5g21bledal5817e1ld8kd7hkl5ic03k8ji34bh740hf\ + jgj2cald12k4b36b2ffd5j09eej95024514ig2db9h3j4i19efbk269k785alk7g\ + hkd6fkf5e6804di2ek2gajf4j3db0l7cgi80jc1j68cib7211ada3616de8628ae\ + k8g9bka30fbe1ahde1c036ch92bckdg6kgg858b214i8518e404b29682a897hf4\ + 3ibdi74gi642k7k14d5aj407j3agk5k1h04dfllc976ahdljcf64j18f14460hhd\ + 4g6ikd7kh496eij9llkeif94kf6g0eg73k6i5226fd2i22ee11hjddj7ah0cij5j\ + kjklak3374ei0e8e0h32e55hef6d1e14b7gd05cgg9fii44kkckgd9fedh07h19e + """) } - - //=----( 30 )--------------------------------------------------------------= - - func testRadix30Top() { - self.radix = 30 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 000000000001nmr6nq4fe87dse4p4i0ama7co4moqch8081liop9spg2kl9rn95e - """ + + func test23() { + self.check(Self.bytes, radix: 23, ascii: """ + 00000000000000000000000000000000000000000000000000000000000a4bj8\ + bale0d596ej9c12m593176b2m0lj5jdelhj11f35ffkh37ja5c4ff45hcffi725e\ + 8cll095fbda26h4ab2mif00639jgmk0429bfl60a8j6fih25al8c04m9e9kgk9gf\ + j6lhf2h8bk6hel39dh1ebb5ik04f4egcfghihj2idmg2ch783i026fmmgj2e2kf6\ + 85g0lkakj0ch8j0c2fel0ffg1k5eg0k0deimgfk4llii0i67g3ghd3ghmehkbbm8\ + 32hael03fh143mk2ebeek17mjk7513c1ff98dmhfg12khmfff1077jl6cgg83085\ + 7ce5lmh42bjmd10madl9m2m58kme472e3a8j79lj43d65m84be21l06h1h8hhd2f\ + 7c13423b97i3b63d627ig0hg3mh0406dem3i77jfifj76ade42d66f48i5cmkg4l + """) } - - func testRadix30Bottom() { - self.radix = 30 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 0000000000006g1ldfsednredtimcop3b5l3q70e4kitjnhrn4eql74ecaf5j1mg - """ + + func test24() { + self.check(Self.bytes, radix: 24, ascii: """ + 08ehhcaace58bei72i8ja72f5hjbgi07b6j65idm59bb5ni8eji1f6lc5g4d6h4g\ + j19gm0ke7lb5d34abbg45fdahn43hmb9gdmh2bn8g529al6jn540id9cjhle26hl\ + i7fm2bmcc1kj35583j173maele2kn5334k1gbm8kcajb2di0ff1hi1ad44adld34\ + a0a32n07mgij7k607949577b62d1c0abfina2jck0l8n1m2mh7ih6mh67dmc2ca4\ + 58ihh733h1mbna818ifeh4b7im6j3gfchhfkj2jkcfd61e1i8inkliigg5f49967\ + 7c1dd7b2nidi934nc3n0k1gj3dj2gg4g22lhg6nm1720kd1imbmf7ia45039bhn5\ + 3lhc76memd39mlh4gbcim3a4n6a3fg86hgk1i29091ccj2md7h5gf2m92eg9l180 + """) } - - //=----( 31 )--------------------------------------------------------------= - - func testRadix31Top() { - self.radix = 31 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 000000000000a30ts5ohp5e917o3nehp8urue2rb4e97icid1me5tcmpil25fi6m - """ + + func test25() { + self.check(Self.bytes, radix: 25, ascii: """ + 0000001116i8b7fj1i736fkim1bce6ni8gb1ag9gfdck9d8m99l9fcjcid7kh1g2\ + agg07gbi4l96l1kimk6695bmlg78n14f9b78ga5k1jiob8o3cbon67b4n8hf99n0\ + 4ma261fbo4elg49ng3n4ngj2dooajc1a232ekkff4988bja96dac9jk8lfem4272\ + m4c6gi8b0f94ko2ho3a3nol2g1gaolj59h3ecca6580mbi9ke2d5elnf8iiggggh\ + 6i577cb8i4e43666jb9fej0ie4m831aei13ij949j3kgk31h4gj2bi1he6bad3m1\ + a48me9b339e826620n979k4e6k2dofkbaema73o8eeg1ko2hh8c63d14e8ljbkf1\ + 347nai6g70k7oh7l7acaniafne0ik28n8ecgjck4mk603bci1c1j25jghh2ffhlf + """) } - - func testRadix31Bottom() { - self.radix = 31 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 000000000000171hhf8063e3r4a99sra00a157pihstia75dmk5kfae5nnn9ab6l - """ + + func test26() { + self.check(Self.bytes, radix: 26, ascii: """ + 0000000000009ng7mg5k5b246fh6fejejo9g6je8amap102c3k88e96fdk7bbl0d\ + l937l2ii3hf448chk6imkjd827pek6j6f3k1gjcb2nbgmeg2639a3ldlgmd14ek2\ + ng6eh4194l1hp8dli4gl0k2m2lpna181bo90dfm7fh45jg1d5ijc591a754k6p28\ + bkkojapjhi24fj9p3paf7fkle9j67mefn6h47hoec2lpmcdg96po0eenja8b1p8h\ + 34c36nckbl597ah5g424apke4h56kd2fho6nmph6cc66d32fhkg6944gk0e0i3og\ + lhjoo6ncaha3a7b9pdg14b12hl18ap0aga2b9eil7ebbalj1j8hb69g1g1nkb1ln\ + h5hgimc7k353o0im2kikcfcpi6m7mi6po47d3o6h868aoef5nb652fm0979373nm + """) } - - //=----( 32 )--------------------------------------------------------------= - - func testRadix32Top() { - self.radix = 32 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 0000000000001vvuvnufnunpv3rvdtfkufpf3s7ftrmupqvat7kefpn5sjhu5of0 - """ + + func test27() { + self.check(Self.bytes, radix: 27, ascii: """ + 00000000000000000aeifkl0aimlgppnb4l0l1nfad678kmgggpn06jphlkj12j3\ + 70gk5bbe9g333n3no69flqkpdfn2ndqaecgaonf443fimdg87m9h85meep2geki1\ + 9eok5p7k9b68pml7b210qac09cd39nb5j7p7qh76hj0d6je2m2319c6odd5a9q3p\ + 15nkob03nfkf6f79goj42f3b874f2bk4cobk0fl0jcnj52fjfphp52qihfl0fg0j\ + jpbkf0eln0m8cp44bf0n6o9f6786852a188ja5o92ooieij326a9ic30021kdli6\ + 0n0hid0q88ad1aaog3enigclj8dli07d5i25aqf6g8jcihhe59183p3qa6o30g55\ + 115mde48b0pcohb5egmfc21nmi8gj5j1j4mphnigfdlg1g3pb1fga06i10mb6cpc + """) } - - func testRadix32Bottom() { - self.radix = 32 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 00000000000007ou3ke1m6gp30bhc58k2c91240f1o6go2oa1440e1g50g1g4080 - """ + + func test28() { + self.check(Self.bytes, radix: 28, ascii: """ + 00000000000000000000011940hqcnpe5i8ehn6cf9c2f0qdd011eaflded1422e\ + 75634p2b6b92chjhi5hhj17dg9o0bbn24c2anpjq2fdikdqfgnqp0em6ornlbkm4\ + 4kajr457ir7f5mnrn5kaoo5o6m34f61gp10ra4g47pk8457hn4m0cpmqe8i6bm5g\ + 1pprale858hm4bp4j20a1pof3dco6f09dpmo2f56ld770b761k5k3e9min8i2la8\ + 9h90bi08n24m3pi37oiojg5pphr13mq8kdd4hfcnd8lmccraap804jjrim5m2qb9\ + 2mnq4r96h4br824079ppojp20nrkmn6jra3gnrrip79ipp2b5d2dd239reenhfib\ + il1on3k9nncfhqfm0obdc9o3a1f6ilq96k8d1ikpmb0e3epn148mhjcoe78rnld4 + """) } - - //=----( 33 )--------------------------------------------------------------= - - func testRadix33Top() { - self.radix = 33 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 0000000000000dodf9g17rn5pvw3et1k184sgnb11u6u7uhk2n9b3bhtfwrh14fb - """ + + func test29() { + self.check(Self.bytes, radix: 29, ascii: """ + 000000000000000000000000006qgf3bdirlm095h66i56k8k9p11hol00og9a39\ + 3mqh7jjofh6bk49k4pbo044bb7k05ppq1jjo8j2kqe8iagllm50r6cdsafdlh915\ + k3iip9mns1o1o0rkaagpab2p8c50gd2cfc2gki5n448pjdsa5i6hsee9s2rp1n01\ + fa1grb4914df5l5l6e9ag8g511og0203m9hncndck52s220rb2f2bpng9leg4mbo\ + qpm0m9k203lrc9mg6fmg8bnmql4fnq3loe2q5nebe4aen0p5nmfadh9nfm8gf612\ + jle8mfq7c1712cgmfiiq0li30gbn883sch73j4ga098h64fqe3s7322rgjh335kp\ + 5csoq4lqelgl4bjom4p15apc6aakaqi1h1lijpmcdogappk3l0caksrcscf2b6cd + """) } - - func testRadix33Bottom() { - self.radix = 33 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 00000000000001m3p6weqc5jk0wsb37sv08ileepww3jad5cr0cfhd0g1aq8in3s - """ + + func test30() { + self.check(Self.bytes, radix: 30, ascii: """ + 0000000000000000000000000000003gc906ob8d00p50qelnf8ma3n5p9phlaqa\ + csshfcol0gn470qt5shaa9prondsstf5jldjq1mjbj8droha6pganj1pnnkqhskb\ + qjd5k8b2lq7dhb3a0n6kmh0k4880q63tr6dpe3a1d7rr5p85pjirlar50b1tk9ht\ + ca9d5fpimnb4po0qombqsms8rb4re1rf41a629hbt9akhtn9ndoo2lgelmq0johi\ + ca565dm8o566k05eq1mg4d0f69rjcl9jlqi5jojeltt6a23b2pp9gkalr40o97o7\ + pgktp83180hdp6q0pfbhme70qi2apg738m324dao0ro0ak55q9e88aan0qre4r81\ + r76f8rfcca39dp5o34teq57r5jpl56aql1imhq4l9dmcom2ebtk25ddgth4jlss0 + """) } - - //=----( 34 )--------------------------------------------------------------= - - func testRadix34Top() { - self.radix = 34 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 00000000000003304fs1ae3ixjsrahw1k6lt33dlup2jc54b1p3xxaghpss3swhe - """ + + func test31() { + self.check(Self.bytes, radix: 31, ascii: """ + 00000000000000000000000000000000003o1q4rle1mom6e5aqbf2gi8q7r00tp\ + ktgt1mu2mfrkrhpo94lg60q0i8el6jk98q2k76nnh40nodjtolp3ps6m01lf72g5\ + qnhpnukeb6e74b1602gfgnoa71i0k8nit8onlcjlqeq2k7t7i3l6n279dalhl0t9\ + b9ibbpc1fa3anjjh7sb55fks9k08p3cl8fgabmrputg7smh3bh2d8on1q72c9qc2\ + oq4ka5pem6u93lkqjk0jk5ssqgd98er49nq1c4upp6726kalnqcpij5gg1rru7df\ + m8g0oscmlu68ffof2b9auiiga5bg8ob3qi8fbrg9fjr3aktct14c9cpjnres9rci\ + dso2trmmkneiq23h298ljg31mb43p1dq7qdl6lmb7de57euffnt5gas6r38j6018 + """) } - - func testRadix34Bottom() { - self.radix = 34 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 00000000000000cpwunuqgcm028uqxuqmjst7gk65egpsowcgixwuci6x899aa2k - """ + + func test32() { + self.check(Self.bytes, radix: 32, ascii: """ + 000000000000000000000000000000000000007vvruvpuvqv7sfftnlujpv5sfg\ + tvnerr7btbkuhpv6snie7on1s3fttnesrfddjm6nqrat9kuiq78cvjmdpj5slie8\ + ov3cbh63ob0s1ftunmubnelpn2rrdddkmepb3c5flqmqpatal6kaf9l5kihq58d0\ + juf9r74rjacph5smima974khi27ot3cche58j247gq2o90s2g607uvjtfhtnkubo\ + etr7at3je9on0rredlm6mqj9d1jmcpb4cdh62o2vbpelomqqb5c5elilah9l4kag\ + 9t74qj2b994kghq68l246gi180vjsf9s7ct3ie1n6oqj8cpi64o2ubhd5glika98\ + 4sj2a91348gi07ou3ke1m6gp30bhc58k2c91240f1o6go2oa1440e1g50g1g4080 + """) } - - //=----( 35 )--------------------------------------------------------------= - - func testRadix35Top() { - self.radix = 35 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 00000000000000pcyhqj7yk3vq8j4l4vfa7wes91wah4p1y3op2k48s4pv0y189o - """ + + func test33() { + self.check(Self.bytes, radix: 33, ascii: """ + 000000000000000000000000000000000000000000wf08osbkbu36iuk1a0c3mg\ + swowotq5g5rfb59tjo423qm0opnic8ukf83hnvggfa3ikaeqh7msfvwtd1m18tct\ + nrwfg3md55vf923rqh2grih41picatv6nf68ofkgn6gg312aomp3jo3ng217vrbs\ + lif6g8g5p29uhn54tck1q2dk22bfkoguw2fgc9gnnn492r3a0pgme41d6202qr53\ + 0cnpf5tpu6pir1uk45l463l6lf91n1w99hicve8ts1ggum0jtup4rti3514019hd\ + f92b9vdnhu2ip86jhue3wol6d37l4njo26s9dmpow9dcwivflpts8lwrjci34ui3\ + seih7hhjjsn6equebc7ca2cr22guqmdsekwewboqq0mgptsi7nkqdrudnahilbl3 + """) } - - func testRadix35Bottom() { - self.radix = 35 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 0000000000000032wujn2mg481jyhidxmv5271ucr21qfj9jdvqm429mwneu6b2v - """ + + func test34() { + self.check(Self.bytes, radix: 34, ascii: """ + 00000000000000000000000000000000000000000000075eo27x9nu9tn7fi1ce\ + 359cvtxx1332aewm3x4qd5llkfj17hxkrsc33uo3sdpp32kj0j3d6vtkmskluagv\ + m4x8d4vojgwvomju3b26lpor71l0a0do4xmdqh8jdiaj2bkokjuwh0v37ladu2he\ + pv65khfagbfqb0xnepxhi81rds2mup1k3i1db3ixlr1bb91x7rkolfoxd500wu41\ + wj3vbgxatgq5fw2p7tnfjn05u4gec6mt0x25d5k0adkodmjf248pl99ij159xxfd\ + 64fw3ikxscupn4eks94cfnjxxcp954x6xb9mg3sbdqc0oai87dv16k2bqf06x42u\ + 2vms3unwqoukwt8v36cmaavlecb5henbvw55gsp1ditrbk6amh0xdapxfqow7e80 + """) } - - //=----( 36 )--------------------------------------------------------------= - - func testRadix36Top() { - self.radix = 36 - self.x64.3 = 0xfffefdfcfbfaf9f8 - self.x64.2 = 0xf7f6f5f4f3f2f1f0 - self.x64.1 = 0xefeeedecebeae9e8 - self.x64.0 = 0xe7e6e5e4e3e2e1e0 - self.txt = """ - 000000000000006dp15j43ld5l8i7wvimlj7kxgbfxkxkgmo66lge382296ouqjk - """ + + func test35() { + self.check(Self.bytes, radix: 35, ascii: """ + 0000000000000000000000000000000000000000000000002ndxwb3ok6s4k5p5\ + ymr8u7p67b6xfhwiwyojwteq5qvdgrigdp50hwnq9e5dogmrg7x392dbx2vxkkr6\ + siwb3rnmah6xi2cee4qldu99xky5ggganqyaxgo7j22st8d5yj6l0wj78r31tkup\ + 9e65y798485dsmnlnsbw9j8hdcbxntls6j4w30j3va6alba73h1c3rn98gsr7aey\ + x4ba5r79ufl1jelh6yeui0t5e5a9o021bsqphjxjy68g1ubmmcfec789r3v3cux0\ + 5yyfhsi04iyjkiwbg2xjff5fw6y70eqsdhrajifhm2q9ybk11yy5tvh0bsxk0ttq\ + fpweb9h70r4fpx177pqg23dm8ck1xnvovqgvs2qp9g7nrlr4kpbnbhuowibrctep + """) } - - func testRadix36Bottom() { - self.radix = 36 - self.x64.3 = 0x1f1e1d1c1b1a1918 - self.x64.2 = 0x1716151413121110 - self.x64.1 = 0x0f0e0d0c0b0a0908 - self.x64.0 = 0x0706050403020100 - self.txt = """ - 000000000000000rx55jlhq7obx1pvd9861yo6c11bed0cd8s8wz2hpvczt00c1s - """ + + func test36() { + self.check(Self.bytes, radix: 36, ascii: """ + 0000000000000000000000000000000000000000000000000001mvj05wljbmpd\ + 8a2mrglgkrl8gqwelpwwxehf7iy1e62a2bgqnwhakfi8fhp4yiy96w7gg8pkrvyc\ + ojpy7czhc5r9tcoz0w5494eh31ezh8ezx4stye8xhigo1k7u2owa4olg2tx3nqhw\ + kiay1mrg4rb09twvlcqx1qnsbsb3qfl7j2wxlrkqhanbcxt2gcztp40bxcwwa0lp\ + 1a39mzhxwmovwnc745vv3sv44jnfgqoekcku7trkz49lvn3kwf7kk1mcn6fg1nxj\ + ccmy6g4p3j4m1hjpywgt9pnq9mgovinv1wq4u3c4s4tv5bux5b5yi5avnt894fm2\ + b8a57jtmggfc3thfwalqq3eruydie3u2rhh2bjf5g8i6qla9b2fh6lrb1ios0wlc + """) } } @@ -946,7 +587,7 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual(T.init(description, radix: 10), integer, file: file, line: line) } -private func NBKAssertDecodeText ( +private func NBKAssertDecodingText ( _ integer: T?, _ radix: Int, _ text: String, file: StaticString = #file, line: UInt = #line) { //=------------------------------------------= @@ -957,7 +598,7 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual(T.init(text, radix: radix), integer, file: file, line: line) } -private func NBKAssertEncodeText( +private func NBKAssertEncodingText( _ integer: T, _ radix: Int, _ uppercase: Bool, _ text: String, file: StaticString = #file, line: UInt = #line) { //=------------------------------------------= From d4639790c08905e38d233803bc7c02583fa4cc49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Fri, 17 Nov 2023 15:21:44 +0100 Subject: [PATCH 128/133] [NBKFlexibleWidthKit] More encoding tests. MOAR! --- .../NBKFlexibleWidth+Text.swift | 533 ++++++++++++++++-- 1 file changed, 495 insertions(+), 38 deletions(-) diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Text.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Text.swift index f89dd53c..e5e79d2f 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Text.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Text.swift @@ -28,7 +28,7 @@ final class NBKFlexibleWidthTestsOnTextForEachRadixAsUIntXL: XCTestCase { //=------------------------------------------------------------------------= /// The bit pattern: `0xfffefdfcfbfaf9f8...0706050403020100`. - static let bytes = T(x64:[ + static let ascending = T(x64:[ 0x0706050403020100, 0x0f0e0d0c0b0a0908, 0x1716151413121110, 0x1f1e1d1c1b1a1918, 0x2726252423222120, 0x2f2e2d2c2b2a2928, 0x3736353433323130, 0x3f3e3d3c3b3a3938, 0x4746454443424140, 0x4f4e4d4c4b4a4948, 0x5756555453525150, 0x5f5e5d5c5b5a5958, @@ -36,7 +36,18 @@ final class NBKFlexibleWidthTestsOnTextForEachRadixAsUIntXL: XCTestCase { 0x8786858483828180, 0x8f8e8d8c8b8a8988, 0x9796959493929190, 0x9f9e9d9c9b9a9998, 0xa7a6a5a4a3a2a1a0, 0xafaeadacabaaa9a8, 0xb7b6b5b4b3b2b1b0, 0xbfbebdbcbbbab9b8, 0xc7c6c5c4c3c2c1c0, 0xcfcecdcccbcac9c8, 0xd7d6d5d4d3d2d1d0, 0xdfdedddcdbdad9d8, - 0xe7e6e5e4e3e2e1e0, 0xefeeedecebeae9e8, 0xf7f6f5f4f3f2f1f0, 0xfffefdfcfbfaf9f8]) + 0xe7e6e5e4e3e2e1e0, 0xefeeedecebeae9e8, 0xf7f6f5f4f3f2f1f0, 0xfffefdfcfbfaf9f8]) + + /// The bit pattern: `0x0001020304050607...f8f9fafbfcfdfeff`. + static let descending = T(x64:[ + 0xf8f9fafbfcfdfeff, 0xf0f1f2f3f4f5f6f7, 0xe8e9eaebecedeeef, 0xe0e1e2e3e4e5e6e7, + 0xd8d9dadbdcdddedf, 0xd0d1d2d3d4d5d6d7, 0xc8c9cacbcccdcecf, 0xc0c1c2c3c4c5c6c7, + 0xb8b9babbbcbdbebf, 0xb0b1b2b3b4b5b6b7, 0xa8a9aaabacadaeaf, 0xa0a1a2a3a4a5a6a7, + 0x98999a9b9c9d9e9f, 0x9091929394959697, 0x88898a8b8c8d8e8f, 0x8081828384858687, + 0x78797a7b7c7d7e7f, 0x7071727374757677, 0x68696a6b6c6d6e6f, 0x6061626364656667, + 0x58595a5b5c5d5e5f, 0x5051525354555657, 0x48494a4b4c4d4e4f, 0x4041424344454647, + 0x38393a3b3c3d3e3f, 0x3031323334353637, 0x28292a2b2c2d2e2f, 0x2021222324252627, + 0x18191a1b1c1d1e1f, 0x1011121314151617, 0x08090a0b0c0d0e0f, 0x0001020304050607]) //=------------------------------------------------------------------------= // MARK: Assertions @@ -55,11 +66,11 @@ final class NBKFlexibleWidthTestsOnTextForEachRadixAsUIntXL: XCTestCase { } //=------------------------------------------------------------------------= - // MARK: Tests x Bytes + // MARK: Tests x Ascending, Descending //=------------------------------------------------------------------------= func test02() { - self.check(Self.bytes, radix: 02, ascii: """ + self.check(Self.ascending, radix: 02, ascii: """ 1111111111111110111111011111110011111011111110101111100111111000\ 1111011111110110111101011111010011110011111100101111000111110000\ 1110111111101110111011011110110011101011111010101110100111101000\ @@ -93,10 +104,45 @@ final class NBKFlexibleWidthTestsOnTextForEachRadixAsUIntXL: XCTestCase { 0000111100001110000011010000110000001011000010100000100100001000\ 0000011100000110000001010000010000000011000000100000000100000000 """) + + self.check(Self.descending, radix: 02, ascii: """ + 0000000000000001000000100000001100000100000001010000011000000111\ + 0000100000001001000010100000101100001100000011010000111000001111\ + 0001000000010001000100100001001100010100000101010001011000010111\ + 0001100000011001000110100001101100011100000111010001111000011111\ + 0010000000100001001000100010001100100100001001010010011000100111\ + 0010100000101001001010100010101100101100001011010010111000101111\ + 0011000000110001001100100011001100110100001101010011011000110111\ + 0011100000111001001110100011101100111100001111010011111000111111\ + 0100000001000001010000100100001101000100010001010100011001000111\ + 0100100001001001010010100100101101001100010011010100111001001111\ + 0101000001010001010100100101001101010100010101010101011001010111\ + 0101100001011001010110100101101101011100010111010101111001011111\ + 0110000001100001011000100110001101100100011001010110011001100111\ + 0110100001101001011010100110101101101100011011010110111001101111\ + 0111000001110001011100100111001101110100011101010111011001110111\ + 0111100001111001011110100111101101111100011111010111111001111111\ + 1000000010000001100000101000001110000100100001011000011010000111\ + 1000100010001001100010101000101110001100100011011000111010001111\ + 1001000010010001100100101001001110010100100101011001011010010111\ + 1001100010011001100110101001101110011100100111011001111010011111\ + 1010000010100001101000101010001110100100101001011010011010100111\ + 1010100010101001101010101010101110101100101011011010111010101111\ + 1011000010110001101100101011001110110100101101011011011010110111\ + 1011100010111001101110101011101110111100101111011011111010111111\ + 1100000011000001110000101100001111000100110001011100011011000111\ + 1100100011001001110010101100101111001100110011011100111011001111\ + 1101000011010001110100101101001111010100110101011101011011010111\ + 1101100011011001110110101101101111011100110111011101111011011111\ + 1110000011100001111000101110001111100100111001011110011011100111\ + 1110100011101001111010101110101111101100111011011110111011101111\ + 1111000011110001111100101111001111110100111101011111011011110111\ + 1111100011111001111110101111101111111100111111011111111011111111 + """) } func test03() { - self.check(Self.bytes, radix: 03, ascii: """ + self.check(Self.ascending, radix: 03, ascii: """ 0000000000000000000000000000000000000000000000000001011122001202\ 0221000010120021121012122122121210201121000021000121212010111102\ 0021022202211121121121221212000020201221122210202201001002201010\ @@ -119,10 +165,34 @@ final class NBKFlexibleWidthTestsOnTextForEachRadixAsUIntXL: XCTestCase { 0200121221120002212120101220100120101121122112221220012112011121\ 0121001121010221102001120121101000020200001000211102020110221110 """) + + self.check(Self.descending, radix: 03, ascii: """ + 0000000000000000000000000000000000000000000000000000000000000100\ + 1201120210220100110000101022020200210120211212120010111000100200\ + 1201120210200222221112211112120122111002022121212221220020020021\ + 1211112200121202200221110201112022200111011002001111211001001210\ + 2220102000012100211210021120211221200212210011220221221210221212\ + 2222022220122111000220122201210100221211021220102010112022011111\ + 0121021201001110200122102112201202022222200221000101120200212101\ + 1010021021022221120101211200201110000211111122201202020202110221\ + 0022120111200020110102012011210110000211200010220002101111120101\ + 1221102201020120002022010122120111111211222012011211212110222012\ + 1202220212201211110122201021001011010112010211112010202102100001\ + 1201212220101111022210120202211012001102022221101101221222200111\ + 0101010020020220000112200212022001021010021100102210101022210211\ + 1202021010021102110001202120201000202122002011122102011220111101\ + 1012211121220210021002212210112100210201120111010221022120001212\ + 1222110100200211122221210100020221110011222001202222000211010100\ + 1122110212221111011200112012012002220201002201222110102200111201\ + 0111111101220210011222012010020001021121201122201012021221210210\ + 2110011012222121222020020212110121100210220002222011101221021021\ + 0112202220101220011210212011210102200110100021221220200201110011\ + 0022000111200121201021102000112221002012210222221221112222201100 + """) } func test04() { - self.check(Self.bytes, radix: 04, ascii: """ + self.check(Self.ascending, radix: 04, ascii: """ 3333333233313330332333223321332033133312331133103303330233013300\ 3233323232313230322332223221322032133212321132103203320232013200\ 3133313231313130312331223121312031133112311131103103310231013100\ @@ -140,10 +210,29 @@ final class NBKFlexibleWidthTestsOnTextForEachRadixAsUIntXL: XCTestCase { 0133013201310130012301220121012001130112011101100103010201010100\ 0033003200310030002300220021002000130012001100100003000200010000 """) + + self.check(Self.descending, radix: 04, ascii: """ + 0000000100020003001000110012001300200021002200230030003100320033\ + 0100010101020103011001110112011301200121012201230130013101320133\ + 0200020102020203021002110212021302200221022202230230023102320233\ + 0300030103020303031003110312031303200321032203230330033103320333\ + 1000100110021003101010111012101310201021102210231030103110321033\ + 1100110111021103111011111112111311201121112211231130113111321133\ + 1200120112021203121012111212121312201221122212231230123112321233\ + 1300130113021303131013111312131313201321132213231330133113321333\ + 2000200120022003201020112012201320202021202220232030203120322033\ + 2100210121022103211021112112211321202121212221232130213121322133\ + 2200220122022203221022112212221322202221222222232230223122322233\ + 2300230123022303231023112312231323202321232223232330233123322333\ + 3000300130023003301030113012301330203021302230233030303130323033\ + 3100310131023103311031113112311331203121312231233130313131323133\ + 3200320132023203321032113212321332203221322232233230323132323233\ + 3300330133023303331033113312331333203321332233233330333133323333 + """) } func test05() { - self.check(Self.bytes, radix: 05, ascii: """ + self.check(Self.ascending, radix: 05, ascii: """ 0000000000000101011133132112303401331203113040334201212224114333\ 1331210120311431302322401423134214144114302234223323124032013102\ 2031310012312133044114114101403342401111141021424131121343010430\ @@ -159,10 +248,27 @@ final class NBKFlexibleWidthTestsOnTextForEachRadixAsUIntXL: XCTestCase { 0304124320331131120040124432124112202220433320304324003340021343\ 1324223134224004424011000321223301220134021034313232023030324130 """) + + self.check(Self.descending, radix: 05, ascii: """ + 0000000000000000000011112220410043202330011120133410031040004330\ + 4341221403222404433322102144041223114211314323343204434113224023\ + 4202133231041330002312141443032100300431040042214130113344324022\ + 0003033132111304421001413014203324242214223404240341232242231142\ + 3340214011113104001131004242024004221443142132444122344311101242\ + 1004023141340203330402132300004344144322442200321404111130230232\ + 3133343130231214411012031114143432214413020420233100440220432423\ + 2243141404410214044100142011212104313004030243322344322310333323\ + 3024401130130344314420430011223234330142032224324334134040231223\ + 3411402203220101304223402340422200404331110030013243131121203033\ + 4421222201121212122344111102000123003033403313011113442344310321\ + 0212040323210123133413431243330144102203032410432301243134312231\ + 0222420103420141120210200140403304423210100101323244203323144103\ + 2244421302202340120224210321141312243002114134133313000033010430 + """) } func test06() { - self.check(Self.bytes, radix: 06, ascii: """ + self.check(Self.ascending, radix: 06, ascii: """ 0000000000000000000000000000000000000001345131000552333115344121\ 1214023443243324324333122442522233415252532225231130540122100214\ 0215244235522514322330122325410454305413105211242412413243515420\ @@ -177,10 +283,26 @@ final class NBKFlexibleWidthTestsOnTextForEachRadixAsUIntXL: XCTestCase { 1512140511314534242423200345252352143342420322435054213022035002\ 4325250215312305241230104233141315022325103343150130404400523320 """) + + self.check(Self.descending, radix: 06, ascii: """ + 0000000000000000000000000000000000000000000001101244524030103050\ + 5531042315523235333525101305553312125110054220232435524352224142\ + 2053151321544434335040524214255145034313244420015104114444532130\ + 5131211403354545331043000404415555115552254524500234324052054544\ + 0212530234155222352503522355044401441443444123253343143251424324\ + 4134551510104424455502335515404533114302125220421213020520110411\ + 1504043310005143320344204330350455513552351141214450322440103324\ + 3125500135505231115445012513503141220340440111403544321144410454\ + 4434544550051012214002454222455235433415531502214521123242404320\ + 4014321430553334134451431214532201142053235043445501013550154325\ + 3024252321100454253441131350205155431304043512204000014004531004\ + 2034152112152200254215340255540550522204504133200444140500531431\ + 2233041532325315013225020141304435140311224252411541420101544143 + """) } func test07() { - self.check(Self.bytes, radix: 07, ascii: """ + self.check(Self.ascending, radix: 07, ascii: """ 0000000000000000000000000000000000000024653320130023336353601340\ 0355512020400135330313404163116323361665214341655231546035543041\ 3335061463602013225153316300026621432263543366545536433610205024\ @@ -194,10 +316,25 @@ final class NBKFlexibleWidthTestsOnTextForEachRadixAsUIntXL: XCTestCase { 3614546631516640255632303266244531025632554125633416523166131412\ 3533422165650541466015660324101553116436025240606246521266532034 """) + + self.check(Self.descending, radix: 07, ascii: """ + 0000000000000000000000000000000000000000000046215156341104144413\ + 6064621423661545444654615066360306060465143246516123400132545065\ + 2014515155412342351261361320435321015260445542345153424665323461\ + 0114416030513346553314263163630631425445505265616243343122362104\ + 2000460423064644315166540105254001105315016506520645232434362254\ + 4331411646406403010516610221633665334030662154232055411300246353\ + 0310563254056060056622336540260033560331003320163152232604433135\ + 4164235460542041401510521102142062156431435343046560332465042201\ + 6511235106510212216314244536164605241220642565660111156412634233\ + 6556106632453464235621424215600534606530001631160211606003002230\ + 1611605222100443162203206534603240202153655435353545022116362124\ + 6026410120242432506346633405306601261561020623142104244113610216 + """) } func test08() { - self.check(Self.bytes, radix: 08, ascii: """ + self.check(Self.ascending, radix: 08, ascii: """ 0000000000000000000003777757677476775371761737667537236374570760\ 7376735573165752723643477156274470761341701577366735633366554730\ 6575332565151722643503176354671462745311621437066134230360540700\ @@ -210,10 +347,24 @@ final class NBKFlexibleWidthTestsOnTextForEachRadixAsUIntXL: XCTestCase { 1362705513025452122240471142244410621041100174360721603306414430\ 0561302505011422042100170340641402605011020034060120200300400400 """) + + self.check(Self.descending, radix: 08, ascii: """ + 0000000000000000000000000020100301002406016040110240541403207017\ + 0401042204612025054134300621503307016436076200411042144411223047\ + 1202445212626055134274601423106315032466156340711643547417237077\ + 2004050220642105214435102224511323046516236501212445152425253127\ + 2605453226656135274575403026114331062546316641513246555433267157\ + 3407056234672165354735703627517337076576377002014050160441303207\ + 4210461242706215435076204431122345112626457142314651563447317237\ + 5012064250722245515236505232525353126656537302615453166455333267\ + 5613467256736275575377006034130361142706617443116254571463347317\ + 6415072264752325655537306635533367156736677603417056174471363347\ + 7216475272766355735677607437136375172766757743717657577477377377 + """) } func test09() { - self.check(Self.bytes, radix: 09, ascii: """ + self.check(Self.ascending, radix: 09, ascii: """ 0000000000000000000000000000000000000000000000000000000001148052\ 2700350753557855364700701776344207282747547855006657583681032633\ 2305521723753171031251258063167286874467627748714735418255041335\ @@ -226,10 +377,24 @@ final class NBKFlexibleWidthTestsOnTextForEachRadixAsUIntXL: XCTestCase { 4361857517003812712833680301716503118444513836084381836547774640\ 2055750277635631634757585617514717047127361517330220030742213843 """) + + self.check(Self.descending, radix: 09, ascii: """ + 0000000000000000000000000000000000000000000000000000000000000010\ + 5152381040033822071675550343032051523628845745518432277787806207\ + 5448055262742146861413204473105386360170753246757625704827853855\ + 8828657402658171085425636346814417251043618375652288627011520771\ + 3323728751175064302444865222242708514606412164713024603802344511\ + 5738121606811851445486515477386552825654418637034115124463672301\ + 5178634428352273504228734185861411106226015625261233240383338724\ + 5223324240167663067806457215644135747823232783470721514127276055\ + 5841062458771022740486168802411048425844150465162821081873380451\ + 1444182315816320124764863525772373135877866225417323802864357237\ + 1568635615376471261330785662140408014617637360487065728857488640 + """) } func test10() { - self.check(Self.bytes, radix: 10, ascii: """ + self.check(Self.ascending, radix: 10, ascii: """ 0000000000000000000000032316509077753586139510713445660514514047\ 1715800934968659014776021432245405574123404729692361840203777454\ 0863807743939745614194869975427379141886998502749960224378577364\ @@ -241,10 +406,23 @@ final class NBKFlexibleWidthTestsOnTextForEachRadixAsUIntXL: XCTestCase { 8235589361595220880511748744523688475088623430039909767486996242\ 6348425792929710270231641017897005896324246640151098893336183040 """) + + self.check(Self.descending, radix: 10, ascii: """ + 0000000000000000000000000000496993557421161204163243009437446396\ + 9310896219871662288678253814305983104785527242321753388930859433\ + 0932284445862203797761045073664730366928240142078351838709159365\ + 4245305591568630492124408336898055480790220185594414336311305186\ + 5615046227503033628676752271565095933109248377684204700624161099\ + 9460398201284924128155924134321292864244193101990764869167297695\ + 2280785510275422238003732540719940795979897949667308357456420122\ + 4430197246959039185181992218946191962058782195636399032805876159\ + 1937103770751746973746316925269816124638211869823911785029642701\ + 0987117809205722959373004300581599055823946915702512166260047615 + """) } func test11() { - self.check(Self.bytes, radix: 11, ascii: """ + self.check(Self.ascending, radix: 11, ascii: """ 0000000000000000000000000000000000000000000000010142aa3554859615\ 1a9204496a56113782737a0530594194878213854265484228a2873210376102\ 298531554729267773485a52aaa2030350391963a7a0a94819183a184061767a\ @@ -256,10 +434,23 @@ final class NBKFlexibleWidthTestsOnTextForEachRadixAsUIntXL: XCTestCase { 358425533763a551898a379424822a252aa411a696485496052a6871743a226a\ 8989647385195622111666334615228957638330392039898693611430034583 """) + + self.check(Self.descending, radix: 11, ascii: """ + 0000000000000000000000000000000000000000000000000000256148a85586\ + 5197664763a413508459939466315799165a6237763aa375593223a736658a62\ + 6175a059a7751a78641a7a475619616477939520a087332893696097491542a0\ + 32141834910a431662128201852a11559a110337a57054a296643718815a7a80\ + 48479962aa316851a2904aa35279872922828167a735214a27215a821861a384\ + 99815a0961a3737601288254235997668057936329799a941615802815674803\ + 25786a7644882756447532455a8a3a35981a95a6909a13497286502490619a17\ + 1a77888724a210a717362256366a598950960902066765804a99481685943069\ + 59110458713a51298801a11123297018992a5501098a28a26006692109193391\ + a16a79092aa045204411a34032199992178aa6827439a86a4a1162545251105a + """) } func test12() { - self.check(Self.bytes, radix: 12, ascii: """ + self.check(Self.ascending, radix: 12, ascii: """ 00001b9367266a6039066116339183036aaa985742938485bbb3a46470645276\ 569234baa5161788742348681a4a5b25ba61622633b09273b03b9aaa7514aa58\ 900baa9a74852ab0219481b21a86a3153bab534868478662a6191b1659b54964\ @@ -270,10 +461,22 @@ final class NBKFlexibleWidthTestsOnTextForEachRadixAsUIntXL: XCTestCase { b845b1558994981851b953005363a121880435bb95b546ab1558447212026a12\ 954b5492aa0367a34a0a961a50ba9a07b6279269932a4957a644a2a3a3920540 """) + + self.check(Self.descending, radix: 12, ascii: """ + 00000000076b918968899b991b3a0b667713391937b3bb902301ab6145a77307\ + 44a2b60b437594576b487310178a094b5808bb63727175a001311367a6b15b60\ + a32b64505a7714b4726537456122412432166973a068b703039439a92559b5b6\ + 5b0a431247a475b7b73780620429b5646b5980809950201652a5a17013a53004\ + 9278712658818566b19311073b683072337992902a246221355872288749aa1a\ + 8b591341aaba72b3b98a0799b919741387205aa722a5a05582862a92506ba89b\ + a307a1a27768ba2575796b18278b74a250523680499a1a60492b1910ba644782\ + 6784970931559000310546aba16a418a4827544331254b700900bb405448b2a4\ + 4b093020088bb2535b47963b7b44608a93421b127bb07b00246477a7b8115053 + """) } func test13() { - self.check(Self.bytes, radix: 13, ascii: """ + self.check(Self.ascending, radix: 13, ascii: """ 000000000000000000000031cb7486735908c0144bc1018ac182c82a930a12ca\ 74aa7825455c0218a1479ca12843cb94baa0938378c1c8384b19b34340a64b01\ 4c927b86217b9a059379c40089c4314b035b5c702c8371c7c80104445bc99b56\ @@ -284,10 +487,22 @@ final class NBKFlexibleWidthTestsOnTextForEachRadixAsUIntXL: XCTestCase { 79955285c36bc06b629543773288158648aa581166a042608899014254840857\ 15273b93212a908443abc9abc7929ba5810113319924a7468970130052605289 """) + + self.check(Self.descending, radix: 13, ascii: """ + 000000000000000000000000001500b062c1244a5ca682353200a96937353c93\ + 73069a0b203a0697c45513ab9487a7205bb57cc5c425a5c032a2474a01bc3aa7\ + 7990173264abb8b83613121b5528156c4048b81422ac426709bccc65a508b4cb\ + 132b977345a9202198a9c32785c770890b69240b96ca5b132b8b9b817411a933\ + 4b72342699707c6b5c874c92ab31903c758988696cca9690145b772b03085bc3\ + 169a4bc0c135baab68558c0798367ba3406b38007b90c8885160454934686c89\ + 4cb56950cba1887a6a20b95b1c99c6b275100512542006c230c4193161a27012\ + 95b489091b11513a7b6aa93691a756cb65c77ca95668543158b357ca8ab95a44\ + a00348774316caaac9b21502a3302702c852a8bb56b24b5400628a24276750bc + """) } func test14() { - self.check(Self.bytes, radix: 14, ascii: """ + self.check(Self.ascending, radix: 14, ascii: """ 00000000000000000000000000000000000000ad0745312ac38003406c77772a\ c5d337dc56d71b0120a8035c347cd412ba206c7a19b3638983ad6c7dac8866db\ ad3165c94d93a13248c199cda6773520749b9430c797c2bb0d8ca867ba5a063b\ @@ -298,10 +513,22 @@ final class NBKFlexibleWidthTestsOnTextForEachRadixAsUIntXL: XCTestCase { 777b7d6c35b83b7c4a497aa9b859dc77b943581b1799d547b62548548666b945\ 8d240951c39596c82589a5602b65a7c3b356a46269456953341674c2567b81c4 """) + + self.check(Self.descending, radix: 14, ascii: """ + 000000000000000000000000000000000000000000665b20da8c012072742a9c\ + a5cd039c351d1954c650a78d38b82408a4277196aba9762211d09d8cd8b0d860\ + 6a3a66d5813834054475593121b4b9b0413200c31c0a2b0dba384d9032706145\ + d308b314144dacdd01dd8587897b13064dbc82a519ca81a734516c2298c2880a\ + 78c76978d6386d10859b60bb745899c01badadda1999d5b791193187c567c0a8\ + 32a2abc1cd43d1c3560bba8d56b67cab62bcd597b554a3d9b2ac51adc018d6cc\ + 80c0126414d43729179abd98859db7a875258b438c6b3a2a285d3786ddb0ad49\ + 5ba3add41a36735295c13053243d4a14dd747ac3353a4dd77b9314a9c9a79560\ + 6101643ad12c8242bac710666c8139696c146dd4da84974da56d48c94dbb007d + """) } func test15() { - self.check(Self.bytes, radix: 15, ascii: """ + self.check(Self.ascending, radix: 15, ascii: """ 0000000000000000000000000000000000000000000000000001adcc42d77564\ 2e8d25576598e679706b39b634284eb4323514682a6a176bc422a0b453010958\ 11db137066d571a2b91ec47eb29e5870c08bb8759a29eae1e60de477c04c2c97\ @@ -312,10 +539,22 @@ final class NBKFlexibleWidthTestsOnTextForEachRadixAsUIntXL: XCTestCase { 5e4ab4757030038b383714cd32c87c560ab2ecb8d102219ec16d0616544bcb2b\ 651732d918a54ee364a155a488725ac7ce563e994b90e86e485ad50d52e0aab0 """) + + self.check(Self.descending, radix: 15, ascii: """ + 0000000000000000000000000000000000000000000000000000000152b2d1a6\ + b8a8c0121657243d73087ce18b51dc75b4205004346095046c5560a817deba1c\ + d4a5a3105bc83eb096390746c90c20224a8317a34198e7cb73c7e970c60b5c74\ + 6a7d68177d9dd4e2c75c15d13b1646d63a900d38b4dc5286319dbb87c4a62e54\ + bd6d6d4d86509dd7036a27ab6d0bb6807483e90ebc70d57282906edbb53123b3\ + 9129135e549279d96ae4b2a1c7147cc03e4b73a279854b5d2a009b6de5301ad4\ + 059d1ae0989433c36c9bbee5a3645c426e40848de409cd82d902da7de45c0bb2\ + ab154e42536bca71849298d982c69e34e86a6a8b20990845809947073d753ba4\ + 370db27a2d22de47e12ab6e298b283e65b3d8b42e273650b315020dc1aa22960 + """) } func test16() { - self.check(Self.bytes, radix: 16, ascii: """ + self.check(Self.ascending, radix: 16, ascii: """ fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e0\ dfdedddcdbdad9d8d7d6d5d4d3d2d1d0cfcecdcccbcac9c8c7c6c5c4c3c2c1c0\ bfbebdbcbbbab9b8b7b6b5b4b3b2b1b0afaeadacabaaa9a8a7a6a5a4a3a2a1a0\ @@ -325,10 +564,21 @@ final class NBKFlexibleWidthTestsOnTextForEachRadixAsUIntXL: XCTestCase { 3f3e3d3c3b3a393837363534333231302f2e2d2c2b2a29282726252423222120\ 1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100 """) + + self.check(Self.descending, radix: 16, ascii: """ + 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f\ + 202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f\ + 404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f\ + 606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f\ + 808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f\ + a0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebf\ + c0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedf\ + e0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff + """) } func test17() { - self.check(Self.bytes, radix: 17, ascii: """ + self.check(Self.ascending, radix: 17, ascii: """ 0000000000124b16c3g69bbbag36b77367c8366826a1260aafe896c41e5bebd6\ eff1edf76b5c850269d547g2993fg898a7eg88g8db235g6c407d4898b5a17d05\ 9g1d0fc9bgf991cagd36gae0bag2bg730e02b8265dg2e55825g7cdfe2fgedcg1\ @@ -338,10 +588,21 @@ final class NBKFlexibleWidthTestsOnTextForEachRadixAsUIntXL: XCTestCase { 2cddf99e175db6fgf31545e48gfb055b4g39cca53b5a97f743922d73b7afb7d7\ 4928154d92b20gg7992e38cb96c1dd4bea7c7728fgb1127e0e47469feag585g0 """) + + self.check(Self.descending, radix: 17, ascii: """ + 0000000000000017ce9c05e067e38a806859ca9f32f4efb5bbc0b1443434a7fe\ + 11f6g3f2g2a7bd55278c6b700309c5bge3dead4e678ab3f9a664703f66f716cg\ + 5b0f53e1655cc321011f1bb33625b5d44580930a9687c4b2926aa7c1gcbc4g63\ + 7c70abfcb0f4bdcfcf7174c446a2417b77512bg9321849db9e8d78e616gd76c8\ + bad838eb8085deb36c92839aee7569412499e53b92427c236dce21aga885bd0d\ + 67ecca7c6dgcdb3bdeb3569gg55a7age3ddb6gf122b89bafce283776af88gd6b\ + 63c8a6b7ab753cfd54cacgbd6cggf6fc12a29dc712bf067e0c0962d1f0e95abc\ + 1aa0038be0af74bb752866508e5b7463abfe155ac0e5a17f758733fa2f7c0fg0 + """) } func test18() { - self.check(Self.bytes, radix: 18, ascii: """ + self.check(Self.ascending, radix: 18, ascii: """ 0000000000000000000018bga551hha58097eef06aa64bdbh0172b1dcf80417e\ g30bdd9b1ac2bf53e416fgc92ef713dh5gfc36gcfa8961d4c4eef393d8c95hc4\ 0bf67b02ag05e7g833b3g6372d4b45169d4693ee6h64h53h6f9c34105cchd1b7\ @@ -351,10 +612,21 @@ final class NBKFlexibleWidthTestsOnTextForEachRadixAsUIntXL: XCTestCase { 96ag9g9d2af8495ge2bg3d961a7c04gf931h399da9f8g0d7540b9458fag6d4g1\ 85055ae5915ch6e98ab88g522b1cb92872cah62f92aa4c75ddg37ed0e80g746c """) + + self.check(Self.descending, radix: 18, ascii: """ + 000000000000000000000000270e4hdf6dde52265g40e1282b6aa8168f0963da\ + a204h4758c9e66b1gf0d7829ad10gch037cbfh4ba69ce6ac12hbe8hf78gh56ac\ + 0hbfa1dgca543f87g84hbf49degbe3h24c31bab01fe5b1be1f62c93866gecd28\ + 4782bgdb95a257g94d5c7a8d8afhgb272aeg5g0gf9153d45b4e26dfa841fe13b\ + a8991ead426ffdc8h73089bfc86fc703hf408ah1bg4haed5595fb6b2b80fh5e3\ + dc0d9ghf5b82592g56773bef87fc7bhgafdf4208dbf79h84gh3e0bdfa5cdh664\ + 7a4e6a1cb51c653ae1ad97fg64c170a59120f1a703bb1a0c2g6gf83304c3d0g4\ + 2af3g30d227eegf3gfb234cdfh59bcgb73ehh1g6hbfeca767501ge43584gfcf9 + """) } func test19() { - self.check(Self.bytes, radix: 19, ascii: """ + self.check(Self.ascending, radix: 19, ascii: """ 0000000000000000000000000000017g2f692gg45a5gdf57gcg2g07g4h04bhfa\ f8c01abeh9d0da94477aa600ddg25953cbh2363a71ghfdehi84ce7782ba4h3i0\ 3a3822ff9dg3hfh8h61cf785057g74ea5c4821g6ii4h020eif1992fihdh9hedf\ @@ -364,10 +636,21 @@ final class NBKFlexibleWidthTestsOnTextForEachRadixAsUIntXL: XCTestCase { d312cai90h6fi0g8401c1561f97gg2fia9822h6575ab83id41bab5cgbgihdaee\ 7aib31f1gah964c8076a4a1c91ghb0bg7hb407f2h52e28c213d98b3156g85i51 """) + + self.check(Self.descending, radix: 19, ascii: """ + 0000000000000000000000000000000002ff85ged5dcd5040bbea5e4dca9f325\ + 2d50797cg4a534i759233di0e13d9c05ic161ced73c61bf5i1b7eg831g16f2b3\ + 5b86g899a83fh5g0ac2id610ieidih0f571cf29dc56f8h812aggi0ga4f65hea6\ + 29ed2c3546e0f0269eh5ihae73d8a56hh3aa38bbf5dh33230cg394hdaa40ga3f\ + 6ii1baa7ag5acb1af0f2fb9cd681c8dc123ahh93cicii5f48c01558eg8gbf6c4\ + 771h4cb4fi896h5b28fgb5gh9b06i28dgfea807g01hh3c98dai86bg2aghi4f46\ + 61d2gc1b6eh2ahhd2dhdd3f0f0eae020hg28ae15bi58c6993f4b1310g9744aef\ + 101f49g24d393ah000ag8ifecbf05ba1de4977e694c9c90497cf4c70dh8caa34 + """) } func test20() { - self.check(Self.bytes, radix: 20, ascii: """ + self.check(Self.ascending, radix: 20, ascii: """ 00000000000000000000000000000000000000d5050cagd94ghbfad415d73775\ 385hih85hd9d80ec925gehjg1j04f2hhiahd169328ai8099750j9jf64g3eg281\ 863fi1cihc58jdec239iea6i88ci5640be2eddf81i0fj3005gib3ja486927438\ @@ -377,10 +660,21 @@ final class NBKFlexibleWidthTestsOnTextForEachRadixAsUIntXL: XCTestCase { ed043626hj5g7eccjjd76chd29g1a2520a88j370bcgac00a5j4h24dc168jgc16\ 431i8ced8d553fa0jg40cd577ich5ce5a93e8i8jdfa192c27390cff0a87b2hc0 """) + + self.check(Self.descending, radix: 20, ascii: """ + 000000000000000000000000000000000000000001cc1j30fcdbj1dgc663fbjb\ + 546f35de96ii52h53cd61cg1i4efi3e42idj30cebgf2b4j64971agf1a9d3fc58\ + 9beg7iaf27741i965c2ccbi4bcahf7hf3c6i8j5974a570gi9b4gfci570abd1b1\ + ijij319a541dej23a5ce69gea7ge595c15gca2h75j6hc142b0ee47658d4gfe0e\ + ej41j5hca7b66iji50ifhchb9aji636ifcig69h9fehce48206a1ae3hbfd52j39\ + d9ad795jifief05d1ebf1387cfi2cef9cab12je6hb4g989971j0cjjg3f06eg55\ + 2f0h1370j335023gie3hd23a81c88ea6h1f7ega4e8373c24jc3fed84ig1d4d8b\ + cbee83a9aah41b143dj910b9i1fd1chcf4278j5ic6j8c1dgg4i68d919hg55j0f + """) } func test21() { - self.check(Self.bytes, radix: 21, ascii: """ + self.check(Self.ascending, radix: 21, ascii: """ 00000000000000000000000000000000000000000000025c52fbheeggjg8507d\ fje9hf92hjbbficeaf8fi1634i6dbc8ccc4bci9a754b580283fibjbkkbdg8080\ 26g8e9h734gjj5547ek5hdafj86jab9kf90k9gg6ijiad7415f2eecba9k15891i\ @@ -390,10 +684,21 @@ final class NBKFlexibleWidthTestsOnTextForEachRadixAsUIntXL: XCTestCase { ka3geadbckebhk979843g6ki6hbkh3a5h4k262h0g6f89k4896gk6aj93g8gje63\ 409g09916bb8e39hi5ci6djciki7hbd192de689hfjcab3ca39ie0fhg21ea33ji """) + + self.check(Self.descending, radix: 21, ascii: """ + 00000000000000000000000000000000000000000000000006g6de0ai8b68b3i\ + c5fjhf6jbg4j4j67h89ffkhead04h99kb290k718afgj8j6jf2f77e57cch210gd\ + jf3f5h95kb3gd0f1jb06d307d06ha0ej2dge91ag1h756eahcabkjdfijd2d2a6c\ + 2144fa9173b69684gkkf8d0c31j3a5k5kab56h975172k04kfhf2h1d0ibb21kc9\ + 09ca372586ad9fghj3dk931f3bk76ca395ikf6g702631k63ke56hbhji67ib077\ + h4883ghb1j6371j6e51e21de93db7ka84ae00d8k9c7a486kehbe572d246d3b1g\ + 601jjhe1e4e9c056agif5gbd928b9g469956g61d975f65kdbacjb4b360ggchej\ + 7cjb53cgag999edk1gd63eegh35bj1jk3g266052f70eei1c7h15d5ka51k0k4j6 + """) } func test22() { - self.check(Self.bytes, radix: 22, ascii: """ + self.check(Self.ascending, radix: 22, ascii: """ 000000000000000000000000000000000000000000000000000023icle03ja5d\ 3hla1053987fc3i93924f5g21bledal5817e1ld8kd7hkl5ic03k8ji34bh740hf\ jgj2cald12k4b36b2ffd5j09eej95024514ig2db9h3j4i19efbk269k785alk7g\ @@ -403,10 +708,21 @@ final class NBKFlexibleWidthTestsOnTextForEachRadixAsUIntXL: XCTestCase { 4g6ikd7kh496eij9llkeif94kf6g0eg73k6i5226fd2i22ee11hjddj7ah0cij5j\ kjklak3374ei0e8e0h32e55hef6d1e14b7gd05cgg9fii44kkckgd9fedh07h19e """) + + self.check(Self.descending, radix: 22, ascii: """ + 000000000000000000000000000000000000000000000000000000007i81bj9f\ + d3800a8d8khk24l27ebd4eli42akghk19ac6hdg78eka61il30flg9alg1eieib3\ + 1d3jc7b4h690f22i4c186gh06950f3l50ldche6c6e86je71j81625hbi34jalgk\ + 6gbf893f216j93cb8cee3778elak46h23g5dcfi09k99cje2icijk1bl5f5gk90f\ + 792ejgbd93c7342chjlhl3gakh60bcg3i97k56bh6ladld8g4fcb7e96db32bclh\ + i59769iaf9f5dg655dh2bcia0i7a7kl10bbh4l4563hkfhh1kkb9if5k9bk8c51g\ + 95kge1kch27jjfea8d37acg24ei5i0fafia4ga5lh2klibakg5kld8eljd3ciebc\ + 32i1bhkca7j1i4g5764lj4da091flf43j8ha4ec13j04abghh88cc8egki99f5dl + """) } func test23() { - self.check(Self.bytes, radix: 23, ascii: """ + self.check(Self.ascending, radix: 23, ascii: """ 00000000000000000000000000000000000000000000000000000000000a4bj8\ bale0d596ej9c12m593176b2m0lj5jdelhj11f35ffkh37ja5c4ff45hcffi725e\ 8cll095fbda26h4ab2mif00639jgmk0429bfl60a8j6fih25al8c04m9e9kgk9gf\ @@ -416,10 +732,21 @@ final class NBKFlexibleWidthTestsOnTextForEachRadixAsUIntXL: XCTestCase { 7ce5lmh42bjmd10madl9m2m58kme472e3a8j79lj43d65m84be21l06h1h8hhd2f\ 7c13423b97i3b63d627ig0hg3mh0406dem3i77jfifj76ade42d66f48i5cmkg4l """) + + self.check(Self.descending, radix: 23, ascii: """ + 000000000000000000000000000000000000000000000000000000000000001k\ + k65fglbgdjki6jld3a8l24hf44hgikie82g6g326eam4g7m05593jg194ell5gl7\ + 9l9c1imblh904ggjegb50l86kjf86222lk342kac5h1kc2ii351hj8ll726g95fh\ + 0dckbdjg1mc045iif4gj44llj2l5g1chb7c2lm2m28a28kfci4kme5jmld5ie917\ + 603f5g8c5fjgd844339c82mjfi1113f71m2f7ebm524d6e35j7c2jbmefkiad36l\ + a65ji1lm3le51ia8k5h2am2fi0ahc59g79ek3515be0a7f4788baejfcaf1da535\ + 3ifdl69b4lkim95fm03b064074aa3669cce3463128920f7lih06e7d0hk9ed3h1\ + ma8251l5l6j6lf8557gk2dgh38h2b83ih6b0d594047g0mb9ik48lj602k7350h5 + """) } func test24() { - self.check(Self.bytes, radix: 24, ascii: """ + self.check(Self.ascending, radix: 24, ascii: """ 08ehhcaace58bei72i8ja72f5hjbgi07b6j65idm59bb5ni8eji1f6lc5g4d6h4g\ j19gm0ke7lb5d34abbg45fdahn43hmb9gdmh2bn8g529al6jn540id9cjhle26hl\ i7fm2bmcc1kj35583j173maele2kn5334k1gbm8kcajb2di0ff1hi1ad44adld34\ @@ -428,10 +755,20 @@ final class NBKFlexibleWidthTestsOnTextForEachRadixAsUIntXL: XCTestCase { 7c1dd7b2nidi934nc3n0k1gj3dj2gg4g22lhg6nm1720kd1imbmf7ia45039bhn5\ 3lhc76memd39mlh4gbcim3a4n6a3fg86hgk1i29091ccj2md7h5gf2m92eg9l180 """) + + self.check(Self.descending, radix: 24, ascii: """ + 00001jmkd0lc7da2k8135ecji7m7k0m7liie7778n9mkj5207l6ma5m1m620jl4c\ + dkffmna0cfh56al9e6j5fh123bm7e905c825ndccabdmcj5582iedi5k04kg70a8\ + j4i11addmi4m57ag8ke9bnh0b0475fcn1k7g3c684mg1l95i7b07ke3n2i781gj4\ + n074501j3dg5ibmad4bii9ab3afjad8f54gb2ccm39ci7mgen0jdgichm0fc94ij\ + jb122182hdldk1dgghn3i37fmbkd6je22e67434a2g7dk303hhdhd73gckndk6jf\ + 9lhnlb2c23gc5fe2ghl1akdn8bghdlaifln67a2aamb76a1gff2l9ljgib5ekf20\ + a186gcecc5mf90ha3kfm52847lji8hfgmdbai334ndaflkj89l5g01ifgbmck32f + """) } func test25() { - self.check(Self.bytes, radix: 25, ascii: """ + self.check(Self.ascending, radix: 25, ascii: """ 0000001116i8b7fj1i736fkim1bce6ni8gb1ag9gfdck9d8m99l9fcjcid7kh1g2\ agg07gbi4l96l1kimk6695bmlg78n14f9b78ga5k1jiob8o3cbon67b4n8hf99n0\ 4ma261fbo4elg49ng3n4ngj2dooajc1a232ekkff4988bja96dac9jk8lfem4272\ @@ -440,10 +777,20 @@ final class NBKFlexibleWidthTestsOnTextForEachRadixAsUIntXL: XCTestCase { a48me9b339e826620n979k4e6k2dofkbaema73o8eeg1ko2hh8c63d14e8ljbkf1\ 347nai6g70k7oh7l7acaniafne0ik28n8ecgjck4mk603bci1c1j25jghh2ffhlf """) + + self.check(Self.descending, radix: 25, ascii: """ + 000000000066cal0nadf16a8j535k0nfnlc93ce4nic5bo47d6m6gndjh4nl8ckd\ + m28hg48f0d799n3b0f4g40mblf6iohkc033gh684m51lf9aieec9cj4e3ldcmd6m\ + ikbk66g406g0mm2k4c9n9bholcjn657m542glj23i428d00no9ncoc0h9466fd2h\ + gijgfd79l573699jhbo824adg0o2anedcn994l294l09a6bb4gf432nhdohd5iid\ + fek6f83ogoan06chji1m3cehnj8kkd7dj6kc3c11fmdkdkmc0kng60f1hn86bafi\ + obcc17777do66201d0fiki8168odog3b2743db1d8j8n7ni1o5c33e5nd1egjgcg\ + 2cm13m1l725a1kki4mh5511hhoaid9l3com82adk72eb3b987ef26lj8i800i14f + """) } func test26() { - self.check(Self.bytes, radix: 26, ascii: """ + self.check(Self.ascending, radix: 26, ascii: """ 0000000000009ng7mg5k5b246fh6fejejo9g6je8amap102c3k88e96fdk7bbl0d\ l937l2ii3hf448chk6imkjd827pek6j6f3k1gjcb2nbgmeg2639a3ldlgmd14ek2\ ng6eh4194l1hp8dli4gl0k2m2lpna181bo90dfm7fh45jg1d5ijc591a754k6p28\ @@ -452,10 +799,20 @@ final class NBKFlexibleWidthTestsOnTextForEachRadixAsUIntXL: XCTestCase { lhjoo6ncaha3a7b9pdg14b12hl18ap0aga2b9eil7ebbalj1j8hb69g1g1nkb1ln\ h5hgimc7k353o0im2kikcfcpi6m7mi6po47d3o6h868aoef5nb652fm0979373nm """) + + self.check(Self.descending, radix: 26, ascii: """ + 0000000000000002hge9dae3h4nj1m0oh96867me28a0b3cdd369i3aghejk8ngh\ + ih3k7ikdi8bn7m8dgo61mp9363242dnnjk312npkjg86h066mhodcgddhf7mg4kb\ + gl8i0o83gkapdl368765eggd64kckmpfoi7e1akc1a05dene3lg901o8g19040e5\ + cjm2iokb5di020cgg0f66fh03l401gd1kgj0k7oc20lkf16pdf4514g81i56bd4p\ + j488gghi26p6nd9g3fgjl04fj6kagbg55k79k0jlppiefaacb68jh56oiaeh8jhj\ + lkm1nf88n6alama7187pg8gbn7iom3da54a1lkonoa08j4bh14gk496bfhf7bea4\ + a60n43hp2ifl6m8ib8honnmafchinij6g2l7h4l72f28h0ck226obh7cmc2gid5p + """) } func test27() { - self.check(Self.bytes, radix: 27, ascii: """ + self.check(Self.ascending, radix: 27, ascii: """ 00000000000000000aeifkl0aimlgppnb4l0l1nfad678kmgggpn06jphlkj12j3\ 70gk5bbe9g333n3no69flqkpdfn2ndqaecgaonf443fimdg87m9h85meep2geki1\ 9eok5p7k9b68pml7b210qac09cd39nb5j7p7qh76hj0d6je2m2319c6odd5a9q3p\ @@ -464,10 +821,20 @@ final class NBKFlexibleWidthTestsOnTextForEachRadixAsUIntXL: XCTestCase { 0n0hid0q88ad1aaog3enigclj8dli07d5i25aqf6g8jcihhe59183p3qa6o30g55\ 115mde48b0pcohb5egmfc21nmi8gj5j1j4mphnigfdlg1g3pb1fga06i10mb6cpc """) + + self.check(Self.descending, radix: 27, ascii: """ + 00000000000000000000354kbj1913ok2akegiac121jfliqpemefhd28gnpo667\ + gdo5fo8d6dko4a9idg99g8j60g2e9mken2h9eknnbnhq8ohd0ohjl9pm7ob3e84d\ + 5bf9d65lmofkqo893e67lc9llqmj5e2492ddq56k7bl8fdi6cb54lc0mi3o2adfa\ + hcob50kj5n4dghjjggm8jn8kh5daq3l3cafbdfb7704jnoad8lfkm51b8paapqid\ + 3a22804o7kiba2c3p3bp7e6l9m7957k327o6dp6ejd45mgol72nle9ljfd3p8f1n\ + hm367eqg328d1hifqi7a34pbhmce1fff8k385pa81e3ddaol4q53617gjhj57pll\ + m1aqnhk27m5c780qjchbbah8j5iebfea81a0nnk249c80digj7b0ep25lqppeqj9 + """) } func test28() { - self.check(Self.bytes, radix: 28, ascii: """ + self.check(Self.ascending, radix: 28, ascii: """ 00000000000000000000011940hqcnpe5i8ehn6cf9c2f0qdd011eaflded1422e\ 75634p2b6b92chjhi5hhj17dg9o0bbn24c2anpjq2fdikdqfgnqp0em6ornlbkm4\ 4kajr457ir7f5mnrn5kaoo5o6m34f61gp10ra4g47pk8457hn4m0cpmqe8i6bm5g\ @@ -476,10 +843,20 @@ final class NBKFlexibleWidthTestsOnTextForEachRadixAsUIntXL: XCTestCase { 2mnq4r96h4br824079ppojp20nrkmn6jra3gnrrip79ipp2b5d2dd239reenhfib\ il1on3k9nncfhqfm0obdc9o3a1f6ilq96k8d1ikpmb0e3epn148mhjcoe78rnld4 """) + + self.check(Self.descending, radix: 28, ascii: """ + 00000000000000000000000009p61rcc333fehpommgkqa37omq8oirgng1rj56b\ + mr6qqjiodrcom1ok5boqe8comk6prpdpj3bcg2j15519ec3oarm25994fj709b6p\ + rfbgpkdegi8nkk90fhejri2m6bcp332rnj04ghn6i9r6l1hqrj5do0gkp3r5c6gi\ + gchhkhimhcni94m682j26rkgj84356eg2jf66155q0d7nqorn8kpoi6offn1inch\ + 5b1facgrbe7h1bmm90d1pih2o3i8kjg1mlb1b7h57b2bg4gpl6ppfl5cn8c0bkkr\ + nbdg0k144dh8gp5n11een6585k8169b0i7a61p8d7q3f5f2e2dj190ge5f255487\ + 1hah1c54arhc5nlmngnlnio897p1f9kpd2a076k1kqqp4ld75h78j4qn0448fl3r + """) } func test29() { - self.check(Self.bytes, radix: 29, ascii: """ + self.check(Self.ascending, radix: 29, ascii: """ 000000000000000000000000006qgf3bdirlm095h66i56k8k9p11hol00og9a39\ 3mqh7jjofh6bk49k4pbo044bb7k05ppq1jjo8j2kqe8iagllm50r6cdsafdlh915\ k3iip9mns1o1o0rkaagpab2p8c50gd2cfc2gki5n448pjdsa5i6hsee9s2rp1n01\ @@ -488,10 +865,20 @@ final class NBKFlexibleWidthTestsOnTextForEachRadixAsUIntXL: XCTestCase { jle8mfq7c1712cgmfiiq0li30gbn883sch73j4ga098h64fqe3s7322rgjh335kp\ 5csoq4lqelgl4bjom4p15apc6aakaqi1h1lijpmcdogappk3l0caksrcscf2b6cd """) + + self.check(Self.descending, radix: 29, ascii: """ + 000000000000000000000000000002h6iifm5gl740qqhok7oeklc0kdhdlepf80\ + ifsan6o6jndhpqshgr16le6d7c58k8i5noh3p632c95df1gdsi1s56gsfoqeali9\ + djgp50kgedfaa9jocfa4qa1caq9lcso27jn7rc63deilrksmjgmreja47r3a9nhh\ + 3boffpbh48npgmsdhl742oknsqo00kdan8qcffh2leb68h9b4049jnk98g5dnls0\ + rhlab9qp643g7f4gp2aj37b18kikrmnl0ifcardkj8kicge9on49j21dd3lkndqp\ + 6im0m33dp5e3h0ls17aqieg24lqd39ng4sj0j74k17o6dj65ambc12c2rap1lms1\ + bonlcs0gii9mgbj7fglh9c7979pdkj0273fd05hj8khnamjcp37l1smagrp4obp2 + """) } func test30() { - self.check(Self.bytes, radix: 30, ascii: """ + self.check(Self.ascending, radix: 30, ascii: """ 0000000000000000000000000000003gc906ob8d00p50qelnf8ma3n5p9phlaqa\ csshfcol0gn470qt5shaa9prondsstf5jldjq1mjbj8droha6pganj1pnnkqhskb\ qjd5k8b2lq7dhb3a0n6kmh0k4880q63tr6dpe3a1d7rr5p85pjirlar50b1tk9ht\ @@ -500,10 +887,20 @@ final class NBKFlexibleWidthTestsOnTextForEachRadixAsUIntXL: XCTestCase { pgktp83180hdp6q0pfbhme70qi2apg738m324dao0ro0ak55q9e88aan0qre4r81\ r76f8rfcca39dp5o34teq57r5jpl56aql1imhq4l9dmcom2ebtk25ddgth4jlss0 """) + + self.check(Self.descending, radix: 30, ascii: """ + 0000000000000000000000000000000001e5g8keo886n2mmihcs1soq5pk1fqm3\ + 6hipgmbprhtgnan7m5eogj51a2ebna097ttt1g49ns3i5tc5s3mhpadssjpm8ser\ + 4ma5n1ldsb70or5k4eg1n1di6cnc0j8as5sqsihc76s33b3aask0k1j4j3gn7ck3\ + 6d9l5n01h8872ddh6scqpqbggshj3sap3mdo97nllpefcr8cil8b26ldh7455lap\ + 40o98i88mcr6heib67chn6hojt95iqf59trsesre3t4idsqktedm1b3qem1ifoas\ + 1ltgcg03765i7no0isqanh36t6700mh5cedb5s37m2rrs0ht7ef00ibg8c53a9b9\ + g4fgdo0363shp7g6e6d9i4286ng1j4nbe25k8pf6clt8251rqfsdl9q6gg33qhaf + """) } func test31() { - self.check(Self.bytes, radix: 31, ascii: """ + self.check(Self.ascending, radix: 31, ascii: """ 00000000000000000000000000000000003o1q4rle1mom6e5aqbf2gi8q7r00tp\ ktgt1mu2mfrkrhpo94lg60q0i8el6jk98q2k76nnh40nodjtolp3ps6m01lf72g5\ qnhpnukeb6e74b1602gfgnoa71i0k8nit8onlcjlqeq2k7t7i3l6n279dalhl0t9\ @@ -512,10 +909,20 @@ final class NBKFlexibleWidthTestsOnTextForEachRadixAsUIntXL: XCTestCase { m8g0oscmlu68ffof2b9auiiga5bg8ob3qi8fbrg9fjr3aktct14c9cpjnres9rci\ dso2trmmkneiq23h298ljg31mb43p1dq7qdl6lmb7de57euffnt5gas6r38j6018 """) + + self.check(Self.descending, radix: 31, ascii: """ + 00000000000000000000000000000000000001mjhjojnfirn3c5brjtjk678qds\ + eobfaoo3u4pt6c8gp3qq7d3gs6mhic3bt5u8albbjs084e2df2lk0emlpnk5i1n7\ + 03pihpu5l0pi4tk105oig7aiebgiu5j5sr5b25l6972cu4cj91npannpnc2728dc\ + q1igcra12qk77hapu1b1qr6d4sskf9ab7j7m60452eh7aadkdpdid946fq12ri1j\ + q727jria8qda7db990diombqtjds5bn0h275frk8n7d2jifftqlb9dkjp0ls0blq\ + 7jubdjr23abk7n6in56etkbbis6bbp90fns3qgo1smgnasor6pf4nf32q1fttojs\ + sijo13oepa99njdhrb4hldth0rbbho66pmrsp76p4g13khulkdj6dgj4hojgk8fu + """) } func test32() { - self.check(Self.bytes, radix: 32, ascii: """ + self.check(Self.ascending, radix: 32, ascii: """ 000000000000000000000000000000000000007vvruvpuvqv7sfftnlujpv5sfg\ tvnerr7btbkuhpv6snie7on1s3fttnesrfddjm6nqrat9kuiq78cvjmdpj5slie8\ ov3cbh63ob0s1ftunmubnelpn2rrdddkmepb3c5flqmqpatal6kaf9l5kihq58d0\ @@ -524,10 +931,20 @@ final class NBKFlexibleWidthTestsOnTextForEachRadixAsUIntXL: XCTestCase { 9t74qj2b994kghq68l246gi180vjsf9s7ct3ie1n6oqj8cpi64o2ubhd5glika98\ 4sj2a91348gi07ou3ke1m6gp30bhc58k2c91240f1o6go2oa1440e1g50g1g4080 """) + + self.check(Self.descending, radix: 32, ascii: """ + 0000000000000000000000000000000000000000041061050o3gg28a1c60q3gf\ + 208h44ok2kb1e60p38dho78u3sg228h34giic9p854l2mb1d5onj0c9i6cq3adhn\ + 70sjkeps7kv3ug21891k8ha68t44iiib9h6ksjqga5956l2lapblgmaqbde5qniv\ + c1gm4or4clj6eq39d9lmorbedto72sjjehqnctrof5t7mv3tfpvo10c2ge28b1k7\ + h24ol2schm78v44hia9p95cmiuc9j6krjiept7t0k6ha7955kqjqhadalemarblf\ + m2or5ctkmmrbfe5pnatrpfdunv0c3gm3oj2sdhu8p75cnj6dpr7t1keiqfadblmn\ + r3ctlmusrnfdvo71sbhu9pf6svkejqnbtjmutrvgu7pf7t7lurrvhufqvfufrvnv + """) } func test33() { - self.check(Self.bytes, radix: 33, ascii: """ + self.check(Self.ascending, radix: 33, ascii: """ 000000000000000000000000000000000000000000wf08osbkbu36iuk1a0c3mg\ swowotq5g5rfb59tjo423qm0opnic8ukf83hnvggfa3ikaeqh7msfvwtd1m18tct\ nrwfg3md55vf923rqh2grih41picatv6nf68ofkgn6gg312aomp3jo3ng217vrbs\ @@ -536,10 +953,20 @@ final class NBKFlexibleWidthTestsOnTextForEachRadixAsUIntXL: XCTestCase { f92b9vdnhu2ip86jhue3wol6d37l4njo26s9dmpow9dcwivflpts8lwrjci34ui3\ seih7hhjjsn6equebc7ca2cr22guqmdsekwewboqq0mgptsi7nkqdrudnahilbl3 """) + + self.check(Self.descending, radix: 33, ascii: """ + 000000000000000000000000000000000000000000000huu8mu1391be05tiior\ + sugdp9856i3vo2c0eg05gbcenilm7rpi94op52duat3m17fjo352wmr7wugsnpau\ + ggfq6nshd3ru8d9ovlc0jta1okqtorlhwjgco8c32e8q9otw6lr82id874k8ut1f\ + cag9cadwg5lpwvrk3jl2eh993e5wumehcwns9a2f8s086arsvukpb6pn3umep923\ + l38rajfap3ovwupv90jgvkku2mmp52n9t6il3surpkrlpggihcllh3dhtr83qsb4\ + 6l89pj79tsu1gurf3uetwi9onlcik36ugenvfhd8e4llunsn5v1d7anaiad60wbr\ + uq5tpbad4f1qdno3arm2cdr2e3b1lkpqpkgcjnmwjo5u04s5573v9jg3002jrogl + """) } func test34() { - self.check(Self.bytes, radix: 34, ascii: """ + self.check(Self.ascending, radix: 34, ascii: """ 00000000000000000000000000000000000000000000075eo27x9nu9tn7fi1ce\ 359cvtxx1332aewm3x4qd5llkfj17hxkrsc33uo3sdpp32kj0j3d6vtkmskluagv\ m4x8d4vojgwvomju3b26lpor71l0a0do4xmdqh8jdiaj2bkokjuwh0v37ladu2he\ @@ -548,10 +975,20 @@ final class NBKFlexibleWidthTestsOnTextForEachRadixAsUIntXL: XCTestCase { 64fw3ikxscupn4eks94cfnjxxcp954x6xb9mg3sbdqc0oai87dv16k2bqf06x42u\ 2vms3unwqoukwt8v36cmaavlecb5henbvw55gsp1ditrbk6amh0xdapxfqow7e80 """) + + self.check(Self.descending, radix: 34, ascii: """ + 0000000000000000000000000000000000000000000000004b4u5cfn5h1xh89d\ + arnchrh1qf49301ph2rjhwdimd3lhg973lh1199v2tlj1uis340cgxnsrssdoa02\ + 61h9bb1gpmw7wp6ahnic3d61a2atxmf9l7dks4sqd1tlml9c7ghomvid96gl1ia7\ + vfwupqgiaibmexrhdb568iiuxv3og4fw3llepqw2wlre0hcpissu0jo3wfg2gabf\ + crrirps1mnr2d16o5kmuroimut7jqtl379gl0676dqj5ns6dui1gj7intmml9e05\ + n370k1qtcqrldu01rv2mg4sx4wawi5ttwnvikn37jpjggjm14r265oputhi2dauf\ + 2ivs8hvh14miwn2ht27s3ne00710gshi4wjdd9irtw3gq9im9rljn7f05tfm03xh + """) } func test35() { - self.check(Self.bytes, radix: 35, ascii: """ + self.check(Self.ascending, radix: 35, ascii: """ 0000000000000000000000000000000000000000000000002ndxwb3ok6s4k5p5\ ymr8u7p67b6xfhwiwyojwteq5qvdgrigdp50hwnq9e5dogmrg7x392dbx2vxkkr6\ siwb3rnmah6xi2cee4qldu99xky5ggganqyaxgo7j22st8d5yj6l0wj78r31tkup\ @@ -560,10 +997,20 @@ final class NBKFlexibleWidthTestsOnTextForEachRadixAsUIntXL: XCTestCase { 5yyfhsi04iyjkiwbg2xjff5fw6y70eqsdhrajifhm2q9ybk11yy5tvh0bsxk0ttq\ fpweb9h70r4fpx177pqg23dm8ck1xnvovqgvs2qp9g7nrlr4kpbnbhuowibrctep """) + + self.check(Self.descending, radix: 35, ascii: """ + 0000000000000000000000000000000000000000000000000001qkgbhr64tc6b\ + 17vdeio9gje48qcyx4eo3e4sxidf1957u7eh03vsy3sw2us3ikyvkllqcfow48mt\ + 4q9hb9g00wpif6guu41gaxyka76n9yimb23jocx1834e0emuvgcinkyi772jn0ae\ + ct3x1yrafusiiroujcnp25ao4lx7ffrp7e6qnrd310cjyq8rrcadniwokk9wf0o8\ + s9xmemd1mmu8f81m7w3t5ncubi2ihwajjwscjhxuug0j2fikf17yw8bypxnyv1kt\ + ajv7q6xa08dhoxb8427vjjby5ge5sbpn9cj3b2klwetn5tjfngy3a955xkk12tdu\ + 6cs10ev42acvbmytmqmc4yehncbc7k4y560tije2r18fsl37vgcwma4sa33jmlwk + """) } func test36() { - self.check(Self.bytes, radix: 36, ascii: """ + self.check(Self.ascending, radix: 36, ascii: """ 0000000000000000000000000000000000000000000000000001mvj05wljbmpd\ 8a2mrglgkrl8gqwelpwwxehf7iy1e62a2bgqnwhakfi8fhp4yiy96w7gg8pkrvyc\ ojpy7czhc5r9tcoz0w5494eh31ezh8ezx4stye8xhigo1k7u2owa4olg2tx3nqhw\ @@ -572,6 +1019,16 @@ final class NBKFlexibleWidthTestsOnTextForEachRadixAsUIntXL: XCTestCase { ccmy6g4p3j4m1hjpywgt9pnq9mgovinv1wq4u3c4s4tv5bux5b5yi5avnt894fm2\ b8a57jtmggfc3thfwalqq3eruydie3u2rhh2bjf5g8i6qla9b2fh6lrb1ios0wlc """) + + self.check(Self.descending, radix: 36, ascii: """ + 000000000000000000000000000000000000000000000000000000168swoi6iu\ + zj4fbwknlnh695zl88v65qcfgnwrwepqcxb9dysmluowqahvt3r9gsc1v47ssxdi\ + vjda3nttl6r044pzz7zwhtgu2mkow5ts28x2mbwenh3wfz4s1sarspfhlrakvqrg\ + pmzb66sgtz2lzbotl7r28wcq8925c747b44l60vrk3scrin4zvnwn7pdsukgo6lg\ + jhu1nuwj7yt1h9ujpe3os17onsk7sp4ysmytu568do2tqetwnrmbxb2dtd8kqorc\ + oakaizlm9svr8axe1acxfursz11nubrhighfd64yhmp99ucvzr944n8co01o4x64\ + cmbd8be0hqbm2zy5uwe4uplc4sa50xajel4bkkxb1kh21pisna37eqwpbpq11ypr + """) } } From 0eafe04a59f744a77a02ed4a401b15342632e70c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sat, 18 Nov 2023 11:13:16 +0100 Subject: [PATCH 129/133] [NBKFlexibleWidthKit] More text tests. MOAR! --- .../NBKFlexibleWidth+Text.swift | 137 ++++++++++++++++++ 1 file changed, 137 insertions(+) diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Text.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Text.swift index e5e79d2f..7050d74c 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Text.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Text.swift @@ -15,6 +15,123 @@ private typealias W = [UInt] private typealias X = [UInt64] private typealias Y = [UInt32] +//*============================================================================* +// MARK: * NBK x Flexible Width x Text x UIntXL +//*============================================================================* +//=----------------------------------------------------------------------------= +// NOTE: See the for-each-radix section for more encoding tests. +//=----------------------------------------------------------------------------= + +final class NBKFlexibleWidthTestsOnTextAsUIntXL: XCTestCase { + + typealias T = UIntXL + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + /// - Note: Its description is not as lenient as its string literal. + func testFromDescription() { + NBKAssertFromDescription(T?( 10), "10") + NBKAssertFromDescription(T?( 10), "+10") + NBKAssertFromDescription(T?(nil), "-10") + NBKAssertFromDescription(T?(nil), " 10") + NBKAssertFromDescription(T?(nil), "0x10") + NBKAssertFromDescription(T?(nil), "+0x10") + NBKAssertFromDescription(T?(nil), "-0x10") + NBKAssertFromDescription(T?(nil), " 0x10") + } + + func testInstanceDescriptionUsesRadix10() { + XCTAssertEqual("10", T(10).description) + XCTAssertEqual("10", String(describing: T(10))) + } + + func testMetaTypeDescriptionIsSimple() { + XCTAssertEqual("UIntXL", T.description) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Decoding + //=------------------------------------------------------------------------= + + func testDecodingUnalignedStringsIsOK() { + NBKAssertDecodingText(T(1), 10, "1") + NBKAssertDecodingText(T(1), 16, "1") + } + + func testDecodingRadixLiteralAsNumber() { + NBKAssertDecodingText(T(33), 36, "0x") + NBKAssertDecodingText(T(24), 36, "0o") + NBKAssertDecodingText(T(11), 36, "0b") + + NBKAssertDecodingText(T(33), 36, "+0x") + NBKAssertDecodingText(T(24), 36, "+0o") + NBKAssertDecodingText(T(11), 36, "+0b") + } + + func testDecodingRadixLiteralAsRadixReturnsNil() { + NBKAssertDecodingText(T?.none, 10, "0x10") + NBKAssertDecodingText(T?.none, 10, "0o10") + NBKAssertDecodingText(T?.none, 10, "0b10") + + NBKAssertDecodingText(T?.none, 10, "+0x10") + NBKAssertDecodingText(T?.none, 10, "+0o10") + NBKAssertDecodingText(T?.none, 10, "+0b10") + } + + func testDecodingStringsWithAndWithoutSign() { + NBKAssertDecodingText(T(1234567890), 10, "1234567890") + NBKAssertDecodingText(T(1234567890), 10, "+1234567890") + } + + func testDecodingStrategyIsCaseInsensitive() { + NBKAssertDecodingText(T(0xabcdef), 16, "abcdef") + NBKAssertDecodingText(T(0xABCDEF), 16, "ABCDEF") + NBKAssertDecodingText(T(0xaBcDeF), 16, "aBcDeF") + NBKAssertDecodingText(T(0xAbCdEf), 16, "AbCdEf") + } + + func testDecodingPrefixingZerosHasNoEffect() { + let zero = String(repeating: "0", count: 256) + "0" + let one = String(repeating: "0", count: 256) + "1" + + for radix in 02 ... 36 { + NBKAssertDecodingText(T(0), radix, zero) + NBKAssertDecodingText(T(1), radix, one ) + } + } + + func testDecodingInvalidCharactersReturnsNil() { + NBKAssertDecodingText(T?.none, 16, "/") + NBKAssertDecodingText(T?.none, 16, "G") + + NBKAssertDecodingText(T?.none, 10, "/") + NBKAssertDecodingText(T?.none, 10, ":") + + NBKAssertDecodingText(T?.none, 10, String(repeating: "1", count: 19) + "/") + NBKAssertDecodingText(T?.none, 10, String(repeating: "1", count: 19) + ":") + } + + func testDecodingStringsWithoutDigitsReturnsNil() { + NBKAssertDecodingText(T?.none, 10, "") + NBKAssertDecodingText(T?.none, 10, "+") + NBKAssertDecodingText(T?.none, 10, "-") + NBKAssertDecodingText(T?.none, 10, "~") + + NBKAssertDecodingText(T?.none, 16, "") + NBKAssertDecodingText(T?.none, 16, "+") + NBKAssertDecodingText(T?.none, 16, "-") + NBKAssertDecodingText(T?.none, 16, "~") + } + + func testDecodingValuesOutsideOfRepresentableRangeReturnsNil() { + for radix in 02 ... 36 { + NBKAssertDecodingText(T?.none, radix, "-1") + } + } +} + //*============================================================================* // MARK: * NBK x Flexible Width x Text x For Each Radix x UIntXL //*============================================================================* @@ -65,6 +182,26 @@ final class NBKFlexibleWidthTestsOnTextForEachRadixAsUIntXL: XCTestCase { NBKAssertEncodingText(integer, radix, false, encoded.lowercased(), file: file, line: line) } + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testImportantValues() { + for radix in 2 ... 36 { + self.check(T(0), radix: radix, ascii: "0") + self.check(T(1), radix: radix, ascii: "1") + } + + for radix in 02 ... 36 { + NBKAssertDecodingText(T?( 0), radix, "0") + NBKAssertDecodingText(T?( 0), radix, "+0") + NBKAssertDecodingText(T?( 0), radix, "-0") + NBKAssertDecodingText(T?( 1), radix, "1") + NBKAssertDecodingText(T?( 1), radix, "+1") + NBKAssertDecodingText(T?(nil), radix, "-1") + } + } + //=------------------------------------------------------------------------= // MARK: Tests x Ascending, Descending //=------------------------------------------------------------------------= From b5e23fc8adf6f6da9555cd542bfa972e235f6600 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sun, 19 Nov 2023 11:50:06 +0100 Subject: [PATCH 130/133] [Tests] Cleanup of aliases. --- .../Models/NBKFibonacciXL.swift | 6 +- .../NBKFlexibleWidth+Addition.swift | 18 +- .../NBKFlexibleWidth+Bits.swift | 30 +-- .../NBKFlexibleWidth+Comparisons.swift | 36 ++-- .../NBKFlexibleWidth+Complements.swift | 42 ++-- .../NBKFlexibleWidth+Division.swift | 40 ++-- .../NBKFlexibleWidth+Exponentiation.swift | 6 +- .../NBKFlexibleWidth+Logic.swift | 34 +-- .../NBKFlexibleWidth+Multiplication.swift | 14 +- .../NBKFlexibleWidth+Numbers.swift | 20 +- .../NBKFlexibleWidth+Shifts.swift | 24 +-- .../NBKFlexibleWidth+Subtraction.swift | 18 +- .../NBKFlexibleWidth+Text.swift | 6 +- .../NBKFlexibleWidth+Words.swift | 10 +- .../NBKFlexibleWidth.swift | 10 +- .../Models/NBKFibonacciXL.swift | 6 +- .../NBKFlexibleWidth+Addition.swift | 38 ++-- .../NBKFlexibleWidth+Bits.swift | 78 +++---- .../NBKFlexibleWidth+Comparisons.swift | 194 +++++++++--------- .../NBKFlexibleWidth+Complements.swift | 66 +++--- .../NBKFlexibleWidth+Division.swift | 78 +++---- .../NBKFlexibleWidth+Exponentiation.swift | 38 ++-- .../NBKFlexibleWidth+Literals.swift | 122 +++++------ .../NBKFlexibleWidth+Logic.swift | 50 ++--- .../NBKFlexibleWidth+Multiplication.swift | 50 ++--- .../NBKFlexibleWidth+Numbers.swift | 90 ++++---- .../NBKFlexibleWidth+Shifts.swift | 120 +++++------ .../NBKFlexibleWidth+Subtraction.swift | 68 +++--- .../NBKFlexibleWidth+Text.swift | 6 +- .../NBKFlexibleWidth+Update.swift | 22 +- .../NBKFlexibleWidth+Words.swift | 82 ++++---- .../NBKFlexibleWidth.swift | 18 +- 32 files changed, 720 insertions(+), 720 deletions(-) diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/Models/NBKFibonacciXL.swift b/Tests/NBKFlexibleWidthKitBenchmarks/Models/NBKFibonacciXL.swift index cbac3e5b..fa75116f 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/Models/NBKFibonacciXL.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/Models/NBKFibonacciXL.swift @@ -13,9 +13,9 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] +private typealias X = [UInt] +private typealias X64 = [UInt64] +private typealias X32 = [UInt32] //*============================================================================* // MARK: * NBK x FibonacciXL diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Addition.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Addition.swift index c404130d..8310c55b 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Addition.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Addition.swift @@ -13,9 +13,9 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] +private typealias X = [UInt] +private typealias X64 = [UInt64] +private typealias X32 = [UInt32] //*============================================================================* // MARK: * NBK x Flexible Width x Addition x UIntXL @@ -30,8 +30,8 @@ final class NBKFlexibleWidthBenchmarksOnAdditionAsUIntXL: XCTestCase { //=------------------------------------------------------------------------= func testAdd() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X64)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X64)) for _ in 0 ..< 5_000_000 { NBK.blackHole(lhs += rhs) @@ -41,8 +41,8 @@ final class NBKFlexibleWidthBenchmarksOnAdditionAsUIntXL: XCTestCase { } func testAdding() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X64)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X64)) for _ in 0 ..< 1_000_000 { NBK.blackHole(lhs + rhs) @@ -56,7 +56,7 @@ final class NBKFlexibleWidthBenchmarksOnAdditionAsUIntXL: XCTestCase { //=------------------------------------------------------------------------= func testAddDigit() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X64)) var rhs = NBK.blackHoleIdentity(UInt.max) for _ in 0 ..< 5_000_000 { @@ -67,7 +67,7 @@ final class NBKFlexibleWidthBenchmarksOnAdditionAsUIntXL: XCTestCase { } func testAddingDigit() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X64)) var rhs = NBK.blackHoleIdentity(UInt.max) for _ in 0 ..< 1_000_000 { diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Bits.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Bits.swift index 58efaa73..cf7702f4 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Bits.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Bits.swift @@ -13,9 +13,9 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] +private typealias X = [UInt] +private typealias X64 = [UInt64] +private typealias X32 = [UInt32] //*============================================================================* // MARK: * NBK x Flexible Width x Bits x UIntXL @@ -43,8 +43,8 @@ final class NBKFlexibleWidthBenchmarksOnBitsAsUIntXL: XCTestCase { } func testBitWidth() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X64)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X64)) for _ in 0 ..< 5_000_000 { NBK.blackHole(abc.bitWidth) @@ -56,8 +56,8 @@ final class NBKFlexibleWidthBenchmarksOnBitsAsUIntXL: XCTestCase { } func testNonzeroBitCount() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X64)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X64)) for _ in 0 ..< 5_000_000 { NBK.blackHole(abc.nonzeroBitCount) @@ -69,8 +69,8 @@ final class NBKFlexibleWidthBenchmarksOnBitsAsUIntXL: XCTestCase { } func testLeadingZeroBitCount() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X64)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X64)) for _ in 0 ..< 5_000_000 { NBK.blackHole(abc.leadingZeroBitCount) @@ -82,8 +82,8 @@ final class NBKFlexibleWidthBenchmarksOnBitsAsUIntXL: XCTestCase { } func testTrailingZeroBitCount() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X64)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X64)) for _ in 0 ..< 5_000_000 { NBK.blackHole(abc.trailingZeroBitCount) @@ -95,8 +95,8 @@ final class NBKFlexibleWidthBenchmarksOnBitsAsUIntXL: XCTestCase { } func testMostSignificantBit() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X64)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X64)) for _ in 0 ..< 5_000_000 { NBK.blackHole(abc.mostSignificantBit) @@ -108,8 +108,8 @@ final class NBKFlexibleWidthBenchmarksOnBitsAsUIntXL: XCTestCase { } func testLeastSignificantBit() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X64)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X64)) for _ in 0 ..< 5_000_000 { NBK.blackHole(abc.leastSignificantBit) diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Comparisons.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Comparisons.swift index fe9a5424..e3bad654 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Comparisons.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Comparisons.swift @@ -13,9 +13,9 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] +private typealias X = [UInt] +private typealias X64 = [UInt64] +private typealias X32 = [UInt32] //*============================================================================* // MARK: * NBK x Flexible Width x Comparisons x UIntXL @@ -30,7 +30,7 @@ final class NBKFlexibleWidthBenchmarksOnComparisonsAsUIntXL: XCTestCase { //=------------------------------------------------------------------------= func testIsZero() { - var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X64)) for _ in 0 ..< 5_000_000 { NBK.blackHole(abc.isZero) @@ -39,7 +39,7 @@ final class NBKFlexibleWidthBenchmarksOnComparisonsAsUIntXL: XCTestCase { } func testIsLessThanZero() { - var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X64)) for _ in 0 ..< 5_000_000 { NBK.blackHole(abc.isLessThanZero) @@ -48,7 +48,7 @@ final class NBKFlexibleWidthBenchmarksOnComparisonsAsUIntXL: XCTestCase { } func testIsMoreThanZero() { - var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X64)) for _ in 0 ..< 5_000_000 { NBK.blackHole(abc.isMoreThanZero) @@ -57,7 +57,7 @@ final class NBKFlexibleWidthBenchmarksOnComparisonsAsUIntXL: XCTestCase { } func testIsPowerOf2() { - var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X64)) for _ in 0 ..< 5_000_000 { NBK.blackHole(abc.isPowerOf2) @@ -66,7 +66,7 @@ final class NBKFlexibleWidthBenchmarksOnComparisonsAsUIntXL: XCTestCase { } func testSignum() { - var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X64)) for _ in 0 ..< 5_000_000 { NBK.blackHole(abc.signum()) @@ -79,8 +79,8 @@ final class NBKFlexibleWidthBenchmarksOnComparisonsAsUIntXL: XCTestCase { //=------------------------------------------------------------------------= func testIsEqualTo() { - var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X64)) + var rhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X64)) for _ in 0 ..< 5_000_000 { NBK.blackHole(lhs == rhs) @@ -90,8 +90,8 @@ final class NBKFlexibleWidthBenchmarksOnComparisonsAsUIntXL: XCTestCase { } func testIsLessThan() { - var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X64)) + var rhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X64)) for _ in 0 ..< 5_000_000 { NBK.blackHole(lhs < rhs) @@ -101,8 +101,8 @@ final class NBKFlexibleWidthBenchmarksOnComparisonsAsUIntXL: XCTestCase { } func testComparedTo() { - var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X64)) + var rhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X64)) for _ in 0 ..< 5_000_000 { NBK.blackHole(lhs.compared(to: rhs)) @@ -112,8 +112,8 @@ final class NBKFlexibleWidthBenchmarksOnComparisonsAsUIntXL: XCTestCase { } func testComparedToAtIndex() { - var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[1, 2, 3, 0] as X)) + var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X64)) + var rhs = NBK.blackHoleIdentity(T(x64:[1, 2, 3, 0] as X64)) let xyz = NBK.blackHoleIdentity(1 as Int) for _ in 0 ..< 5_000_000 { @@ -124,7 +124,7 @@ final class NBKFlexibleWidthBenchmarksOnComparisonsAsUIntXL: XCTestCase { } func testComparedToDigit() { - var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X64)) var rhs = NBK.blackHoleIdentity(UInt.max) for _ in 0 ..< 5_000_000 { @@ -135,7 +135,7 @@ final class NBKFlexibleWidthBenchmarksOnComparisonsAsUIntXL: XCTestCase { } func testComparedToDigitAtIndex() { - var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + var lhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X64)) var rhs = NBK.blackHoleIdentity(UInt( 3)) let xyz = NBK.blackHoleIdentity(3 as Int) diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Complements.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Complements.swift index 36c088e7..248dfc37 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Complements.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Complements.swift @@ -13,9 +13,9 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] +private typealias X = [UInt] +private typealias X64 = [UInt64] +private typealias X32 = [UInt32] //*============================================================================* // MARK: * NBK x Flexible Width x Complements x UIntXL @@ -31,8 +31,8 @@ final class NBKFlexibleWidthBenchmarksOnComplementsAsUIntXL: XCTestCase { //=------------------------------------------------------------------------= func testMagnitude() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X64)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X64)) for _ in 0 ..< 5_000_000 { NBK.blackHole(abc.magnitude) @@ -48,8 +48,8 @@ final class NBKFlexibleWidthBenchmarksOnComplementsAsUIntXL: XCTestCase { //=------------------------------------------------------------------------= func testOnesComplement() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X64)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X64)) for _ in 0 ..< 250_000 { NBK.blackHole(abc.onesComplement()) @@ -61,8 +61,8 @@ final class NBKFlexibleWidthBenchmarksOnComplementsAsUIntXL: XCTestCase { } func testOnesComplementInout() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X64)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X64)) for _ in 0 ..< 5_000_000 { NBK.blackHole(abc.formOnesComplement()) @@ -78,8 +78,8 @@ final class NBKFlexibleWidthBenchmarksOnComplementsAsUIntXL: XCTestCase { //=------------------------------------------------------------------------= func testTwosComplement() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X64)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X64)) for _ in 0 ..< 250_000 { NBK.blackHole(abc.twosComplement()) @@ -91,8 +91,8 @@ final class NBKFlexibleWidthBenchmarksOnComplementsAsUIntXL: XCTestCase { } func testTwosComplementInout() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X64)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X64)) for _ in 0 ..< 5_000_000 { NBK.blackHole(abc.formTwosComplement()) @@ -104,8 +104,8 @@ final class NBKFlexibleWidthBenchmarksOnComplementsAsUIntXL: XCTestCase { } func testTwosComplementReportingOverflow() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X64)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X64)) for _ in 0 ..< 250_000 { NBK.blackHole(abc.twosComplementReportingOverflow()) @@ -118,8 +118,8 @@ final class NBKFlexibleWidthBenchmarksOnComplementsAsUIntXL: XCTestCase { func testTwosComplementReportingOverflowInout() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X64)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X64)) for _ in 0 ..< 5_000_000 { NBK.blackHole(abc.formTwosComplementReportingOverflow()) @@ -131,8 +131,8 @@ final class NBKFlexibleWidthBenchmarksOnComplementsAsUIntXL: XCTestCase { } func testTwosComplementSubsequence() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X64)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X64)) for _ in 0 ..< 250_000 { NBK.blackHole(abc.twosComplementSubsequence(true)) @@ -144,8 +144,8 @@ final class NBKFlexibleWidthBenchmarksOnComplementsAsUIntXL: XCTestCase { } func testTwosComplementSubsequenceInout() { - var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X)) - var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X)) + var abc = NBK.blackHoleIdentity( T(x64:[0, 0, 0, 0] as X64)) + var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X64)) for _ in 0 ..< 5_000_000 { NBK.blackHole(abc.formTwosComplementSubsequence(true)) diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Division.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Division.swift index 374bd401..528172bc 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Division.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Division.swift @@ -13,9 +13,9 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] +private typealias X = [UInt] +private typealias X64 = [UInt64] +private typealias X32 = [UInt32] //*============================================================================* // MARK: * NBK x Flexible Width x Division x UIntXL @@ -31,8 +31,8 @@ final class NBKFlexibleWidthBenchmarksOnDivisionAsUIntXL: XCTestCase { //=------------------------------------------------------------------------= func testQuotientAndRemainder() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X64)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X64)) for _ in 0 ..< 250_000 { NBK.blackHole(lhs.quotientAndRemainder(dividingBy: rhs)) @@ -42,8 +42,8 @@ final class NBKFlexibleWidthBenchmarksOnDivisionAsUIntXL: XCTestCase { } func testQuotientReportingOverflow() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X64)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X64)) for _ in 0 ..< 250_000 { NBK.blackHole(lhs.dividedReportingOverflow(by: rhs)) @@ -53,8 +53,8 @@ final class NBKFlexibleWidthBenchmarksOnDivisionAsUIntXL: XCTestCase { } func testRemainderReportingOverflow() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X64)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X64)) for _ in 0 ..< 250_000 { NBK.blackHole(lhs.remainderReportingOverflow(dividingBy: rhs)) @@ -68,7 +68,7 @@ final class NBKFlexibleWidthBenchmarksOnDivisionAsUIntXL: XCTestCase { //=------------------------------------------------------------------------= func testQuotientAndRemainderDividingByDigit() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X64)) var rhs = NBK.blackHoleIdentity(UInt.max) for _ in 0 ..< 250_000 { @@ -79,7 +79,7 @@ final class NBKFlexibleWidthBenchmarksOnDivisionAsUIntXL: XCTestCase { } func testQuotientDividingByDigitReportingOverflow() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X64)) var rhs = NBK.blackHoleIdentity(UInt.max) for _ in 0 ..< 250_000 { @@ -90,7 +90,7 @@ final class NBKFlexibleWidthBenchmarksOnDivisionAsUIntXL: XCTestCase { } func testRemainderDividingByDigitReportingOverflow() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X64)) var rhs = NBK.blackHoleIdentity(UInt.max) for _ in 0 ..< 250_000 { @@ -105,8 +105,8 @@ final class NBKFlexibleWidthBenchmarksOnDivisionAsUIntXL: XCTestCase { //=------------------------------------------------------------------------= func testDividingFullWidthAs256WhenDivisorIsNormalized() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0, ~1, ~0, ~0, ~0] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0] as X)) // msb == true + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0, ~1, ~0, ~0, ~0] as X64)) + var rhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0] as X64)) // msb == true for _ in 0 ..< 250_000 { NBK.blackHole(lhs.quotientAndRemainder(dividingBy: rhs)) @@ -116,8 +116,8 @@ final class NBKFlexibleWidthBenchmarksOnDivisionAsUIntXL: XCTestCase { } func testDividingFullWidthReportingOverflowAs256WhenDivisorIsNormalized() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0, ~1, ~0, ~0, ~0] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0] as X)) // msb == true + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0, ~1, ~0, ~0, ~0] as X64)) + var rhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0] as X64)) // msb == true for _ in 0 ..< 250_000 { NBK.blackHole(lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs)) @@ -127,8 +127,8 @@ final class NBKFlexibleWidthBenchmarksOnDivisionAsUIntXL: XCTestCase { } func testDividingFullWidthAs256WhenDivisorIsNotNormalized() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0, ~1, ~0, ~0, ~0] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0/2] as X)) // msb == false + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0, ~1, ~0, ~0, ~0] as X64)) + var rhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0/2] as X64)) // msb == false for _ in 0 ..< 250_000 { NBK.blackHole(lhs.quotientAndRemainder(dividingBy: rhs)) @@ -138,8 +138,8 @@ final class NBKFlexibleWidthBenchmarksOnDivisionAsUIntXL: XCTestCase { } func testDividingFullWidthReportingOverflowAs256WhenDivisorIsNotNormalized() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0, ~1, ~0, ~0, ~0] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0/2] as X)) // msb == false + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0, ~1, ~0, ~0, ~0] as X64)) + var rhs = NBK.blackHoleIdentity(T(x64:[~0, ~0, ~0, ~0/2] as X64)) // msb == false for _ in 0 ..< 250_000 { NBK.blackHole(lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs)) diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Exponentiation.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Exponentiation.swift index 543ac1c7..ef434ff1 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Exponentiation.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Exponentiation.swift @@ -13,9 +13,9 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] +private typealias X = [UInt] +private typealias X64 = [UInt64] +private typealias X32 = [UInt32] //*============================================================================* // MARK: * NBK x Flexible Width x Exponentiation x UIntXL diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Logic.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Logic.swift index bb90656a..fc4337fb 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Logic.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Logic.swift @@ -13,9 +13,9 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] +private typealias X = [UInt] +private typealias X64 = [UInt64] +private typealias X32 = [UInt32] //*============================================================================* // MARK: * NBK x Flexible Width x Logic x UIntXL @@ -30,7 +30,7 @@ final class NBKFlexibleWidthBenchmarksOnLogicAsUIntXL: XCTestCase { //=------------------------------------------------------------------------= func testNotInout() { - var abc = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var abc = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X64)) for _ in 0 ..< 5_000_000 { NBK.blackHole(abc.formOnesComplement()) @@ -39,7 +39,7 @@ final class NBKFlexibleWidthBenchmarksOnLogicAsUIntXL: XCTestCase { } func testNot() { - var abc = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var abc = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X64)) for _ in 0 ..< 1_000_000 { NBK.blackHole(~abc) @@ -48,8 +48,8 @@ final class NBKFlexibleWidthBenchmarksOnLogicAsUIntXL: XCTestCase { } func testAndInout() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X64)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X64)) for _ in 0 ..< 5_000_000 { NBK.blackHole(lhs &= rhs) @@ -59,8 +59,8 @@ final class NBKFlexibleWidthBenchmarksOnLogicAsUIntXL: XCTestCase { } func testAnd() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X64)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X64)) for _ in 0 ..< 1_000_000 { NBK.blackHole(lhs & rhs) @@ -70,8 +70,8 @@ final class NBKFlexibleWidthBenchmarksOnLogicAsUIntXL: XCTestCase { } func testOrInout() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X64)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X64)) for _ in 0 ..< 5_000_000 { NBK.blackHole(lhs |= rhs) @@ -81,8 +81,8 @@ final class NBKFlexibleWidthBenchmarksOnLogicAsUIntXL: XCTestCase { } func testOr() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X64)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X64)) for _ in 0 ..< 1_000_000 { NBK.blackHole(lhs | rhs) @@ -92,8 +92,8 @@ final class NBKFlexibleWidthBenchmarksOnLogicAsUIntXL: XCTestCase { } func testXorInout() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X64)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X64)) for _ in 0 ..< 5_000_000 { NBK.blackHole(lhs ^= rhs) @@ -103,8 +103,8 @@ final class NBKFlexibleWidthBenchmarksOnLogicAsUIntXL: XCTestCase { } func testXor() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X64)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X64)) for _ in 0 ..< 1_000_000 { NBK.blackHole(lhs ^ rhs) diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Multiplication.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Multiplication.swift index 64525766..ba562634 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Multiplication.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Multiplication.swift @@ -13,9 +13,9 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] +private typealias X = [UInt] +private typealias X64 = [UInt64] +private typealias X32 = [UInt32] //*============================================================================* // MARK: * NBK x Flexible Width x Multiplication x UIntXL @@ -30,8 +30,8 @@ final class NBKFlexibleWidthBenchmarksOnMultiplicationAsUIntXL: XCTestCase { //=------------------------------------------------------------------------= func testMultiplying() { - var lhs = NBK.blackHoleIdentity(T(x64:[~1, ~2, ~3, ~4] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[ 1, 2, 3, 4] as X)) + var lhs = NBK.blackHoleIdentity(T(x64:[~1, ~2, ~3, ~4] as X64)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 1, 2, 3, 4] as X64)) for _ in 0 ..< 1_000_000 { NBK.blackHole(lhs * rhs) @@ -45,7 +45,7 @@ final class NBKFlexibleWidthBenchmarksOnMultiplicationAsUIntXL: XCTestCase { //=------------------------------------------------------------------------= func testMultiplyingByDigit() { - var lhs = NBK.blackHoleIdentity(T(x64:[~1, ~2, ~3, ~4] as X)) + var lhs = NBK.blackHoleIdentity(T(x64:[~1, ~2, ~3, ~4] as X64)) var rhs = NBK.blackHoleIdentity(UInt.max) for _ in 0 ..< 1_000_000 { @@ -60,7 +60,7 @@ final class NBKFlexibleWidthBenchmarksOnMultiplicationAsUIntXL: XCTestCase { //=------------------------------------------------------------------------= func testMultiplyingBySquaring() { - var base = NBK.blackHoleIdentity(T(x64:[~1, ~2, ~3, ~4] as X)) + var base = NBK.blackHoleIdentity(T(x64:[~1, ~2, ~3, ~4] as X64)) for _ in 0 ..< 1_000_000 { NBK.blackHole(base.squared()) diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Numbers.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Numbers.swift index 8fc13b1e..5a2d3cb2 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Numbers.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Numbers.swift @@ -13,9 +13,9 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] +private typealias X = [UInt] +private typealias X64 = [UInt64] +private typealias X32 = [UInt32] //*============================================================================* // MARK: * NBK x Flexible Width x Numbers x UIntXL @@ -324,7 +324,7 @@ final class NBKFlexibleWidthBenchmarksOnNumbersAsUIntXL: XCTestCase { } func testToMagnitude() { - var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X64)) for _ in 0 ..< 50_000 { NBK.blackHole(M(abc)) @@ -336,7 +336,7 @@ final class NBKFlexibleWidthBenchmarksOnNumbersAsUIntXL: XCTestCase { } func testFromMagnitude() { - var abc = NBK.blackHoleIdentity(M(x64:[0, 1, 2, 3] as X)) + var abc = NBK.blackHoleIdentity(M(x64:[0, 1, 2, 3] as X64)) for _ in 0 ..< 100_000 { NBK.blackHole(T(abc)) @@ -353,7 +353,7 @@ final class NBKFlexibleWidthBenchmarksOnNumbersAsUIntXL: XCTestCase { // TODO: brrr func testToFloat16() { - var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X64)) for _ in 0 ..< 1_000 { NBK.blackHole(Float16(abc)) @@ -374,7 +374,7 @@ final class NBKFlexibleWidthBenchmarksOnNumbersAsUIntXL: XCTestCase { // TODO: brrr func testToFloat32() { - var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X64)) for _ in 0 ..< 1_000 { NBK.blackHole(Float32(abc)) @@ -395,7 +395,7 @@ final class NBKFlexibleWidthBenchmarksOnNumbersAsUIntXL: XCTestCase { // TODO: brrr func testToFloat64() { - var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X)) + var abc = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X64)) for _ in 0 ..< 1_000 { NBK.blackHole(Float64(abc)) @@ -419,8 +419,8 @@ final class NBKFlexibleWidthBenchmarksOnNumbersAsUIntXL: XCTestCase { //=------------------------------------------------------------------------= func testSignAndMagnitude() { - var abc = NBK.blackHoleIdentity((sign: FloatingPointSign.plus, magnitude: M(x64:[0, 1, 2, 3] as X))) - var xyz = NBK.blackHoleIdentity((sign: FloatingPointSign.minus, magnitude: M(x64:[0, 1, 2, 3] as X))) + var abc = NBK.blackHoleIdentity((sign: FloatingPointSign.plus, magnitude: M(x64:[0, 1, 2, 3] as X64))) + var xyz = NBK.blackHoleIdentity((sign: FloatingPointSign.minus, magnitude: M(x64:[0, 1, 2, 3] as X64))) for _ in 0 ..< 1_000_000 { NBK.blackHole(T(sign: abc.sign, magnitude: abc.magnitude)) diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Shifts.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Shifts.swift index 82881a3d..916c786c 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Shifts.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Shifts.swift @@ -13,9 +13,9 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] +private typealias X = [UInt] +private typealias X64 = [UInt64] +private typealias X32 = [UInt32] //*============================================================================* // MARK: * NBK x Flexible Width x Shifts x UIntXL @@ -30,7 +30,7 @@ final class NBKFlexibleWidthBenchmarksOnShiftsAsUIntXL: XCTestCase { //=------------------------------------------------------------------------= func testBitShiftingLeft() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X64)) var rhs = NBK.blackHoleIdentity(UInt.bitWidth * 3/2) for _ in 0 ..< 1_000_000 { @@ -41,7 +41,7 @@ final class NBKFlexibleWidthBenchmarksOnShiftsAsUIntXL: XCTestCase { } func testBitShiftingLeftByWords() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X64)) var rhs = NBK.blackHoleIdentity((major: 1, minor: UInt.bitWidth/2)) for _ in 0 ..< 1_000_000 { @@ -52,7 +52,7 @@ final class NBKFlexibleWidthBenchmarksOnShiftsAsUIntXL: XCTestCase { } func testBitShiftingLeftByWordsAndBits() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X64)) var rhs = NBK.blackHoleIdentity((major: 1, minor: UInt.bitWidth/2)) for _ in 0 ..< 1_000_000 { @@ -67,7 +67,7 @@ final class NBKFlexibleWidthBenchmarksOnShiftsAsUIntXL: XCTestCase { //=------------------------------------------------------------------------= func testBitShiftingRight() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X64)) var rhs = NBK.blackHoleIdentity(UInt.bitWidth * 3/2) for _ in 0 ..< 1_000_000 { @@ -78,7 +78,7 @@ final class NBKFlexibleWidthBenchmarksOnShiftsAsUIntXL: XCTestCase { } func testBitShiftingRightByWords() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X64)) var rhs = NBK.blackHoleIdentity((major: 1, minor: UInt.bitWidth/2)) for _ in 0 ..< 1_000_000 { @@ -89,7 +89,7 @@ final class NBKFlexibleWidthBenchmarksOnShiftsAsUIntXL: XCTestCase { } func testBitShiftingRightByWordsAndBits() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X64)) var rhs = NBK.blackHoleIdentity((major: 1, minor: UInt.bitWidth/2)) for _ in 0 ..< 1_000_000 { @@ -104,7 +104,7 @@ final class NBKFlexibleWidthBenchmarksOnShiftsAsUIntXL: XCTestCase { //=------------------------------------------------------------------------= func testBitShiftingInBothDirectionsInout() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X64)) var rhs = NBK.blackHoleIdentity(UInt.bitWidth * 3/2) for _ in 0 ..< 1_000_000 { @@ -119,7 +119,7 @@ final class NBKFlexibleWidthBenchmarksOnShiftsAsUIntXL: XCTestCase { } func testBitShiftingInBothDirectionsByWordsInout() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X64)) var rhs = NBK.blackHoleIdentity((major: 1, minor: UInt.bitWidth/2)) for _ in 0 ..< 1_000_000 { @@ -134,7 +134,7 @@ final class NBKFlexibleWidthBenchmarksOnShiftsAsUIntXL: XCTestCase { } func testBitShiftingInBothDirectionsByWordsAndBitsInout() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X64)) var rhs = NBK.blackHoleIdentity((major: 1, minor: UInt.bitWidth/2)) for _ in 0 ..< 1_000_000 { diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Subtraction.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Subtraction.swift index 4b816707..8fbfa337 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Subtraction.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Subtraction.swift @@ -13,9 +13,9 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] +private typealias X = [UInt] +private typealias X64 = [UInt64] +private typealias X32 = [UInt32] //*============================================================================* // MARK: * NBK x Flexible Width x Subtraction x UIntXL @@ -30,8 +30,8 @@ final class NBKFlexibleWidthBenchmarksOnSubtractionAsUIntXL: XCTestCase { //=------------------------------------------------------------------------= func testSubtract() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X64)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X64)) for _ in 0 ..< 5_000_000 { NBK.blackHole(lhs -= rhs) @@ -41,8 +41,8 @@ final class NBKFlexibleWidthBenchmarksOnSubtractionAsUIntXL: XCTestCase { } func testSubtracting() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) - var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X)) + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X64)) + var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X64)) for _ in 0 ..< 1_000_000 { NBK.blackHole(lhs - rhs) @@ -56,7 +56,7 @@ final class NBKFlexibleWidthBenchmarksOnSubtractionAsUIntXL: XCTestCase { //=------------------------------------------------------------------------= func testSubtractDigit() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X64)) var rhs = NBK.blackHoleIdentity(UInt.max) for _ in 0 ..< 5_000_000 { @@ -67,7 +67,7 @@ final class NBKFlexibleWidthBenchmarksOnSubtractionAsUIntXL: XCTestCase { } func testSubtractingDigit() { - var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X)) + var lhs = NBK.blackHoleIdentity(T(x64:[~0, ~1, ~2, ~3] as X64)) var rhs = NBK.blackHoleIdentity(UInt.max) for _ in 0 ..< 1_000_000 { diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Text.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Text.swift index bf339821..38290548 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Text.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Text.swift @@ -13,9 +13,9 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] +private typealias X = [UInt] +private typealias X64 = [UInt64] +private typealias X32 = [UInt32] //*============================================================================* // MARK: * NBK x Flexible Width x Text x UIntXL diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Words.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Words.swift index 02000ca8..0cbb4e6a 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Words.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Words.swift @@ -13,9 +13,9 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] +private typealias X = [UInt] +private typealias X64 = [UInt64] +private typealias X32 = [UInt32] //*============================================================================* // MARK: * NBK x Flexible Width x Words x UIntXL @@ -30,8 +30,8 @@ final class NBKFlexibleWidthBenchmarksOnWordsAsUIntXL: XCTestCase { //=------------------------------------------------------------------------= func testFromWords() { - var abc = NBK.blackHoleIdentity([ 0, 0, 0, 0] as W) - var xyz = NBK.blackHoleIdentity([~0, ~0, ~0, ~0] as W) + var abc = NBK.blackHoleIdentity([ 0, 0, 0, 0] as X) + var xyz = NBK.blackHoleIdentity([~0, ~0, ~0, ~0] as X) for _ in 0 ..< 250_000 { NBK.blackHole(T(words: abc)) diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth.swift index bcb1c5a3..cabd8fa2 100644 --- a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth.swift +++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth.swift @@ -11,9 +11,9 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] +private typealias X = [UInt] +private typealias X64 = [UInt64] +private typealias X32 = [UInt32] //*============================================================================* // MARK: * NBK x Flexible Width x UIntXL @@ -25,8 +25,8 @@ extension NBKFlexibleWidth.Magnitude { // MARK: Initializers //=------------------------------------------------------------------------= - static let min256 = Self(x64:[ 0, 0, 0, 0] as X) - static let max256 = Self(x64:[~0, ~0, ~0, ~0] as X) + static let min256 = Self(x64:[ 0, 0, 0, 0] as X64) + static let max256 = Self(x64:[~0, ~0, ~0, ~0] as X64) //=------------------------------------------------------------------------= // MARK: Initializers diff --git a/Tests/NBKFlexibleWidthKitTests/Models/NBKFibonacciXL.swift b/Tests/NBKFlexibleWidthKitTests/Models/NBKFibonacciXL.swift index 922fff1e..f2973551 100644 --- a/Tests/NBKFlexibleWidthKitTests/Models/NBKFibonacciXL.swift +++ b/Tests/NBKFlexibleWidthKitTests/Models/NBKFibonacciXL.swift @@ -11,9 +11,9 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] +private typealias X = [UInt] +private typealias X64 = [UInt64] +private typealias X32 = [UInt32] //*============================================================================* // MARK: * NBK x FibonacciXL diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Addition.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Addition.swift index 6336478a..a9abc45d 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Addition.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Addition.swift @@ -11,9 +11,9 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] +private typealias X = [UInt] +private typealias X64 = [UInt64] +private typealias X32 = [UInt32] //*============================================================================* // MARK: * NBK x Flexible Width x Addition x UIntXL @@ -38,15 +38,15 @@ final class NBKFlexibleWidthTestsOnAdditionAsUIntXL: XCTestCase { } func testAddingAtIndex() { - NBKAssertAddition(T(words:[ 0, 0, 0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[ 1, 2, 3, 0] as W)) - NBKAssertAddition(T(words:[~0, 0, 0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[ 0, 3, 3, 0] as W)) - NBKAssertAddition(T(words:[~0, ~0, 0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[ 0, 2, 4, 0] as W)) - NBKAssertAddition(T(words:[~0, ~0, ~0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[ 0, 2, 3, 1] as W)) + NBKAssertAddition(T(words:[ 0, 0, 0, 0] as X), T(words:[ 1, 2, 3, 0] as X), Int(0), T(words:[ 1, 2, 3, 0] as X)) + NBKAssertAddition(T(words:[~0, 0, 0, 0] as X), T(words:[ 1, 2, 3, 0] as X), Int(0), T(words:[ 0, 3, 3, 0] as X)) + NBKAssertAddition(T(words:[~0, ~0, 0, 0] as X), T(words:[ 1, 2, 3, 0] as X), Int(0), T(words:[ 0, 2, 4, 0] as X)) + NBKAssertAddition(T(words:[~0, ~0, ~0, 0] as X), T(words:[ 1, 2, 3, 0] as X), Int(0), T(words:[ 0, 2, 3, 1] as X)) - NBKAssertAddition(T(words:[ 0, 0, 0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[ 0, 1, 2, 3] as W)) - NBKAssertAddition(T(words:[~0, 0, 0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[~0, 1, 2, 3] as W)) - NBKAssertAddition(T(words:[~0, ~0, 0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[~0, 0, 3, 3] as W)) - NBKAssertAddition(T(words:[~0, ~0, ~0, 0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[~0, 0, 2, 4] as W)) + NBKAssertAddition(T(words:[ 0, 0, 0, 0] as X), T(words:[ 1, 2, 3, 0] as X), Int(1), T(words:[ 0, 1, 2, 3] as X)) + NBKAssertAddition(T(words:[~0, 0, 0, 0] as X), T(words:[ 1, 2, 3, 0] as X), Int(1), T(words:[~0, 1, 2, 3] as X)) + NBKAssertAddition(T(words:[~0, ~0, 0, 0] as X), T(words:[ 1, 2, 3, 0] as X), Int(1), T(words:[~0, 0, 3, 3] as X)) + NBKAssertAddition(T(words:[~0, ~0, ~0, 0] as X), T(words:[ 1, 2, 3, 0] as X), Int(1), T(words:[~0, 0, 2, 4] as X)) } //=------------------------------------------------------------------------= @@ -64,15 +64,15 @@ final class NBKFlexibleWidthTestsOnAdditionAsUIntXL: XCTestCase { } func testAddingDigitAtIndex() { - NBKAssertAdditionByDigit(T(words:[ 0, 0, 0, 0] as W), UInt(3), Int(0), T(words:[ 3, 0, 0, 0] as W)) - NBKAssertAdditionByDigit(T(words:[~0, 0, 0, 0] as W), UInt(3), Int(0), T(words:[ 2, 1, 0, 0] as W)) - NBKAssertAdditionByDigit(T(words:[~0, ~0, 0, 0] as W), UInt(3), Int(0), T(words:[ 2, 0, 1, 0] as W)) - NBKAssertAdditionByDigit(T(words:[~0, ~0, ~0, 0] as W), UInt(3), Int(0), T(words:[ 2, 0, 0, 1] as W)) + NBKAssertAdditionByDigit(T(words:[ 0, 0, 0, 0] as X), UInt(3), Int(0), T(words:[ 3, 0, 0, 0] as X)) + NBKAssertAdditionByDigit(T(words:[~0, 0, 0, 0] as X), UInt(3), Int(0), T(words:[ 2, 1, 0, 0] as X)) + NBKAssertAdditionByDigit(T(words:[~0, ~0, 0, 0] as X), UInt(3), Int(0), T(words:[ 2, 0, 1, 0] as X)) + NBKAssertAdditionByDigit(T(words:[~0, ~0, ~0, 0] as X), UInt(3), Int(0), T(words:[ 2, 0, 0, 1] as X)) - NBKAssertAdditionByDigit(T(words:[ 0, 0, 0, 0] as W), UInt(3), Int(1), T(words:[ 0, 3, 0, 0] as W)) - NBKAssertAdditionByDigit(T(words:[~0, 0, 0, 0] as W), UInt(3), Int(1), T(words:[~0, 3, 0, 0] as W)) - NBKAssertAdditionByDigit(T(words:[~0, ~0, 0, 0] as W), UInt(3), Int(1), T(words:[~0, 2, 1, 0] as W)) - NBKAssertAdditionByDigit(T(words:[~0, ~0, ~0, 0] as W), UInt(3), Int(1), T(words:[~0, 2, 0, 1] as W)) + NBKAssertAdditionByDigit(T(words:[ 0, 0, 0, 0] as X), UInt(3), Int(1), T(words:[ 0, 3, 0, 0] as X)) + NBKAssertAdditionByDigit(T(words:[~0, 0, 0, 0] as X), UInt(3), Int(1), T(words:[~0, 3, 0, 0] as X)) + NBKAssertAdditionByDigit(T(words:[~0, ~0, 0, 0] as X), UInt(3), Int(1), T(words:[~0, 2, 1, 0] as X)) + NBKAssertAdditionByDigit(T(words:[~0, ~0, ~0, 0] as X), UInt(3), Int(1), T(words:[~0, 2, 0, 1] as X)) } //=------------------------------------------------------------------------= diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Bits.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Bits.swift index 59db0f98..041744d5 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Bits.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Bits.swift @@ -11,9 +11,9 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] +private typealias X = [UInt] +private typealias X64 = [UInt64] +private typealias X32 = [UInt32] //*============================================================================* // MARK: * NBK x Flexible Width x Bits x UIntXL @@ -34,62 +34,62 @@ final class NBKFlexibleWidthTestsOnBitsAsUIntXL: XCTestCase { } func testBitWidth() { - XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).bitWidth, UInt.bitWidth * 1) - XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).bitWidth, UInt.bitWidth * 4) + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as X).bitWidth, UInt.bitWidth * 1) + XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as X).bitWidth, UInt.bitWidth * 4) } func testNonzeroBitCount() { - XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).nonzeroBitCount, 0) - XCTAssertEqual(T(words:[ 1, 1, 1, 1] as W).nonzeroBitCount, 4) + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as X).nonzeroBitCount, 0) + XCTAssertEqual(T(words:[ 1, 1, 1, 1] as X).nonzeroBitCount, 4) } func testLeadingZeroBitCount() { - XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).leadingZeroBitCount, UInt.bitWidth * 1) - XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).leadingZeroBitCount, UInt.bitWidth * 0) + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as X).leadingZeroBitCount, UInt.bitWidth * 1) + XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as X).leadingZeroBitCount, UInt.bitWidth * 0) - XCTAssertEqual(T(words:[ 2, 0, 0, 0] as W).leadingZeroBitCount, UInt.bitWidth * 1 - 2) - XCTAssertEqual(T(words:[ 0, 2, 0, 0] as W).leadingZeroBitCount, UInt.bitWidth * 1 - 2) - XCTAssertEqual(T(words:[ 0, 0, 2, 0] as W).leadingZeroBitCount, UInt.bitWidth * 1 - 2) - XCTAssertEqual(T(words:[ 0, 0, 0, 2] as W).leadingZeroBitCount, UInt.bitWidth * 1 - 2) + XCTAssertEqual(T(words:[ 2, 0, 0, 0] as X).leadingZeroBitCount, UInt.bitWidth * 1 - 2) + XCTAssertEqual(T(words:[ 0, 2, 0, 0] as X).leadingZeroBitCount, UInt.bitWidth * 1 - 2) + XCTAssertEqual(T(words:[ 0, 0, 2, 0] as X).leadingZeroBitCount, UInt.bitWidth * 1 - 2) + XCTAssertEqual(T(words:[ 0, 0, 0, 2] as X).leadingZeroBitCount, UInt.bitWidth * 1 - 2) } func testTrailingZeroBitCount() { - XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).trailingZeroBitCount, UInt.bitWidth * 1) - XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).trailingZeroBitCount, UInt.bitWidth * 0) + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as X).trailingZeroBitCount, UInt.bitWidth * 1) + XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as X).trailingZeroBitCount, UInt.bitWidth * 0) - XCTAssertEqual(T(words:[ 2, 0, 0, 0] as W).trailingZeroBitCount, UInt.bitWidth * 0 + 1) - XCTAssertEqual(T(words:[ 0, 2, 0, 0] as W).trailingZeroBitCount, UInt.bitWidth * 1 + 1) - XCTAssertEqual(T(words:[ 0, 0, 2, 0] as W).trailingZeroBitCount, UInt.bitWidth * 2 + 1) - XCTAssertEqual(T(words:[ 0, 0, 0, 2] as W).trailingZeroBitCount, UInt.bitWidth * 3 + 1) + XCTAssertEqual(T(words:[ 2, 0, 0, 0] as X).trailingZeroBitCount, UInt.bitWidth * 0 + 1) + XCTAssertEqual(T(words:[ 0, 2, 0, 0] as X).trailingZeroBitCount, UInt.bitWidth * 1 + 1) + XCTAssertEqual(T(words:[ 0, 0, 2, 0] as X).trailingZeroBitCount, UInt.bitWidth * 2 + 1) + XCTAssertEqual(T(words:[ 0, 0, 0, 2] as X).trailingZeroBitCount, UInt.bitWidth * 3 + 1) } func testMostSignificantBit() { - XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).mostSignificantBit, false) - XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).mostSignificantBit, true ) + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as X).mostSignificantBit, false) + XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as X).mostSignificantBit, true ) - XCTAssertEqual(T(words:[~0, 0, 0, 0] as W).mostSignificantBit, true ) - XCTAssertEqual(T(words:[ 0, ~0, 0, 0] as W).mostSignificantBit, true ) - XCTAssertEqual(T(words:[ 0, 0, ~0, 0] as W).mostSignificantBit, true ) - XCTAssertEqual(T(words:[ 0, 0, 0, ~0] as W).mostSignificantBit, true ) + XCTAssertEqual(T(words:[~0, 0, 0, 0] as X).mostSignificantBit, true ) + XCTAssertEqual(T(words:[ 0, ~0, 0, 0] as X).mostSignificantBit, true ) + XCTAssertEqual(T(words:[ 0, 0, ~0, 0] as X).mostSignificantBit, true ) + XCTAssertEqual(T(words:[ 0, 0, 0, ~0] as X).mostSignificantBit, true ) - XCTAssertEqual(T(words:[~0, 1, 0, 0] as W).mostSignificantBit, false) - XCTAssertEqual(T(words:[ 0, ~0, 1, 0] as W).mostSignificantBit, false) - XCTAssertEqual(T(words:[ 0, 0, ~0, 1] as W).mostSignificantBit, false) - XCTAssertEqual(T(words:[ 1, 0, 0, ~0] as W).mostSignificantBit, true ) + XCTAssertEqual(T(words:[~0, 1, 0, 0] as X).mostSignificantBit, false) + XCTAssertEqual(T(words:[ 0, ~0, 1, 0] as X).mostSignificantBit, false) + XCTAssertEqual(T(words:[ 0, 0, ~0, 1] as X).mostSignificantBit, false) + XCTAssertEqual(T(words:[ 1, 0, 0, ~0] as X).mostSignificantBit, true ) } func testLeastSignificantBit() { - XCTAssertEqual(T(words:[ 0, 0, 0, 0] as W).leastSignificantBit, false) - XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).leastSignificantBit, true ) + XCTAssertEqual(T(words:[ 0, 0, 0, 0] as X).leastSignificantBit, false) + XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as X).leastSignificantBit, true ) - XCTAssertEqual(T(words:[~0, 0, 0, 0] as W).leastSignificantBit, true ) - XCTAssertEqual(T(words:[ 0, ~0, 0, 0] as W).leastSignificantBit, false) - XCTAssertEqual(T(words:[ 0, 0, ~0, 0] as W).leastSignificantBit, false) - XCTAssertEqual(T(words:[ 0, 0, 0, ~0] as W).leastSignificantBit, false) + XCTAssertEqual(T(words:[~0, 0, 0, 0] as X).leastSignificantBit, true ) + XCTAssertEqual(T(words:[ 0, ~0, 0, 0] as X).leastSignificantBit, false) + XCTAssertEqual(T(words:[ 0, 0, ~0, 0] as X).leastSignificantBit, false) + XCTAssertEqual(T(words:[ 0, 0, 0, ~0] as X).leastSignificantBit, false) - XCTAssertEqual(T(words:[~0, 1, 0, 0] as W).leastSignificantBit, true ) - XCTAssertEqual(T(words:[ 0, ~0, 1, 0] as W).leastSignificantBit, false) - XCTAssertEqual(T(words:[ 0, 0, ~0, 1] as W).leastSignificantBit, false) - XCTAssertEqual(T(words:[ 1, 0, 0, ~0] as W).leastSignificantBit, true ) + XCTAssertEqual(T(words:[~0, 1, 0, 0] as X).leastSignificantBit, true ) + XCTAssertEqual(T(words:[ 0, ~0, 1, 0] as X).leastSignificantBit, false) + XCTAssertEqual(T(words:[ 0, 0, ~0, 1] as X).leastSignificantBit, false) + XCTAssertEqual(T(words:[ 1, 0, 0, ~0] as X).leastSignificantBit, true ) } } diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Comparisons.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Comparisons.swift index 620b914a..4586a51f 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Comparisons.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Comparisons.swift @@ -11,9 +11,9 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] +private typealias X = [UInt] +private typealias X64 = [UInt64] +private typealias X32 = [UInt32] //*============================================================================* // MARK: * NBK x Flexible Width x Comparisons x UIntXL @@ -29,83 +29,83 @@ final class NBKFlexibleWidthTestsOnComparisonsAsUIntXL: XCTestCase { //=------------------------------------------------------------------------= func testIsZero() { - XCTAssertTrue (T(words:[ 0] as W).isZero) - XCTAssertFalse(T(words:[ 1] as W).isZero) - XCTAssertFalse(T(words:[ 2] as W).isZero) + XCTAssertTrue (T(words:[ 0] as X).isZero) + XCTAssertFalse(T(words:[ 1] as X).isZero) + XCTAssertFalse(T(words:[ 2] as X).isZero) - XCTAssertFalse(T(words:[~0] as W).isZero) - XCTAssertFalse(T(words:[~1] as W).isZero) - XCTAssertFalse(T(words:[~2] as W).isZero) + XCTAssertFalse(T(words:[~0] as X).isZero) + XCTAssertFalse(T(words:[~1] as X).isZero) + XCTAssertFalse(T(words:[~2] as X).isZero) } func testIsLessThanZero() { - XCTAssertFalse(T(words:[ 0] as W).isLessThanZero) - XCTAssertFalse(T(words:[ 1] as W).isLessThanZero) - XCTAssertFalse(T(words:[ 2] as W).isLessThanZero) + XCTAssertFalse(T(words:[ 0] as X).isLessThanZero) + XCTAssertFalse(T(words:[ 1] as X).isLessThanZero) + XCTAssertFalse(T(words:[ 2] as X).isLessThanZero) - XCTAssertFalse(T(words:[~0] as W).isLessThanZero) - XCTAssertFalse(T(words:[~1] as W).isLessThanZero) - XCTAssertFalse(T(words:[~2] as W).isLessThanZero) + XCTAssertFalse(T(words:[~0] as X).isLessThanZero) + XCTAssertFalse(T(words:[~1] as X).isLessThanZero) + XCTAssertFalse(T(words:[~2] as X).isLessThanZero) } func testIsMoreThanZero() { - XCTAssertFalse(T(words:[ 0] as W).isMoreThanZero) - XCTAssertTrue (T(words:[ 1] as W).isMoreThanZero) - XCTAssertTrue (T(words:[ 2] as W).isMoreThanZero) + XCTAssertFalse(T(words:[ 0] as X).isMoreThanZero) + XCTAssertTrue (T(words:[ 1] as X).isMoreThanZero) + XCTAssertTrue (T(words:[ 2] as X).isMoreThanZero) - XCTAssertTrue (T(words:[~0] as W).isMoreThanZero) - XCTAssertTrue (T(words:[~1] as W).isMoreThanZero) - XCTAssertTrue (T(words:[~2] as W).isMoreThanZero) + XCTAssertTrue (T(words:[~0] as X).isMoreThanZero) + XCTAssertTrue (T(words:[~1] as X).isMoreThanZero) + XCTAssertTrue (T(words:[~2] as X).isMoreThanZero) } func testIsOdd() { - XCTAssertFalse(T(words:[ 0] as W).isOdd) - XCTAssertTrue (T(words:[ 1] as W).isOdd) - XCTAssertFalse(T(words:[ 2] as W).isOdd) + XCTAssertFalse(T(words:[ 0] as X).isOdd) + XCTAssertTrue (T(words:[ 1] as X).isOdd) + XCTAssertFalse(T(words:[ 2] as X).isOdd) - XCTAssertTrue (T(words:[~0] as W).isOdd) - XCTAssertFalse(T(words:[~1] as W).isOdd) - XCTAssertTrue (T(words:[~2] as W).isOdd) + XCTAssertTrue (T(words:[~0] as X).isOdd) + XCTAssertFalse(T(words:[~1] as X).isOdd) + XCTAssertTrue (T(words:[~2] as X).isOdd) } func testIsEven() { - XCTAssertTrue (T(words:[ 0] as W).isEven) - XCTAssertFalse(T(words:[ 1] as W).isEven) - XCTAssertTrue (T(words:[ 2] as W).isEven) + XCTAssertTrue (T(words:[ 0] as X).isEven) + XCTAssertFalse(T(words:[ 1] as X).isEven) + XCTAssertTrue (T(words:[ 2] as X).isEven) - XCTAssertFalse(T(words:[~0] as W).isEven) - XCTAssertTrue (T(words:[~1] as W).isEven) - XCTAssertFalse(T(words:[~2] as W).isEven) + XCTAssertFalse(T(words:[~0] as X).isEven) + XCTAssertTrue (T(words:[~1] as X).isEven) + XCTAssertFalse(T(words:[~2] as X).isEven) } func testIsPowerOf2() { - XCTAssertFalse(T(words:[ 0] as W).isPowerOf2) - XCTAssertTrue (T(words:[ 1] as W).isPowerOf2) - XCTAssertTrue (T(words:[ 2] as W).isPowerOf2) - XCTAssertFalse(T(words:[ 3] as W).isPowerOf2) - XCTAssertTrue (T(words:[ 4] as W).isPowerOf2) - XCTAssertFalse(T(words:[ 5] as W).isPowerOf2) - XCTAssertFalse(T(words:[ 6] as W).isPowerOf2) - XCTAssertFalse(T(words:[ 7] as W).isPowerOf2) + XCTAssertFalse(T(words:[ 0] as X).isPowerOf2) + XCTAssertTrue (T(words:[ 1] as X).isPowerOf2) + XCTAssertTrue (T(words:[ 2] as X).isPowerOf2) + XCTAssertFalse(T(words:[ 3] as X).isPowerOf2) + XCTAssertTrue (T(words:[ 4] as X).isPowerOf2) + XCTAssertFalse(T(words:[ 5] as X).isPowerOf2) + XCTAssertFalse(T(words:[ 6] as X).isPowerOf2) + XCTAssertFalse(T(words:[ 7] as X).isPowerOf2) - XCTAssertFalse(T(words:[ 0, 0, 0, 0] as W).isPowerOf2) - XCTAssertTrue (T(words:[ 1, 0, 0, 0] as W).isPowerOf2) - XCTAssertFalse(T(words:[ 1, 1, 0, 0] as W).isPowerOf2) - XCTAssertTrue (T(words:[ 0, 1, 0, 0] as W).isPowerOf2) - XCTAssertFalse(T(words:[ 0, 1, 1, 0] as W).isPowerOf2) - XCTAssertTrue (T(words:[ 0, 0, 1, 0] as W).isPowerOf2) - XCTAssertFalse(T(words:[ 0, 0, 1, 1] as W).isPowerOf2) - XCTAssertTrue (T(words:[ 0, 0, 0, 1] as W).isPowerOf2) + XCTAssertFalse(T(words:[ 0, 0, 0, 0] as X).isPowerOf2) + XCTAssertTrue (T(words:[ 1, 0, 0, 0] as X).isPowerOf2) + XCTAssertFalse(T(words:[ 1, 1, 0, 0] as X).isPowerOf2) + XCTAssertTrue (T(words:[ 0, 1, 0, 0] as X).isPowerOf2) + XCTAssertFalse(T(words:[ 0, 1, 1, 0] as X).isPowerOf2) + XCTAssertTrue (T(words:[ 0, 0, 1, 0] as X).isPowerOf2) + XCTAssertFalse(T(words:[ 0, 0, 1, 1] as X).isPowerOf2) + XCTAssertTrue (T(words:[ 0, 0, 0, 1] as X).isPowerOf2) } func testSignum() { - NBKAssertSignum(T(words:[ 0] as W), Int(0)) - NBKAssertSignum(T(words:[ 1] as W), Int(1)) - NBKAssertSignum(T(words:[ 2] as W), Int(1)) + NBKAssertSignum(T(words:[ 0] as X), Int(0)) + NBKAssertSignum(T(words:[ 1] as X), Int(1)) + NBKAssertSignum(T(words:[ 2] as X), Int(1)) - NBKAssertSignum(T(words:[~0] as W), Int(1)) - NBKAssertSignum(T(words:[~1] as W), Int(1)) - NBKAssertSignum(T(words:[~2] as W), Int(1)) + NBKAssertSignum(T(words:[~0] as X), Int(1)) + NBKAssertSignum(T(words:[~1] as X), Int(1)) + NBKAssertSignum(T(words:[~2] as X), Int(1)) } //=------------------------------------------------------------------------= @@ -114,58 +114,58 @@ final class NBKFlexibleWidthTestsOnComparisonsAsUIntXL: XCTestCase { func testHashing() { var union = Set() - union.insert(T(words:[0, 0, 0, 0] as W)) - union.insert(T(words:[0, 0, 0, 0] as W)) - union.insert(T(words:[1, 0, 0, 0] as W)) - union.insert(T(words:[1, 0, 0, 0] as W)) - union.insert(T(words:[0, 1, 0, 0] as W)) - union.insert(T(words:[0, 1, 0, 0] as W)) - union.insert(T(words:[0, 0, 1, 0] as W)) - union.insert(T(words:[0, 0, 1, 0] as W)) - union.insert(T(words:[0, 0, 0, 1] as W)) - union.insert(T(words:[0, 0, 0, 1] as W)) + union.insert(T(words:[0, 0, 0, 0] as X)) + union.insert(T(words:[0, 0, 0, 0] as X)) + union.insert(T(words:[1, 0, 0, 0] as X)) + union.insert(T(words:[1, 0, 0, 0] as X)) + union.insert(T(words:[0, 1, 0, 0] as X)) + union.insert(T(words:[0, 1, 0, 0] as X)) + union.insert(T(words:[0, 0, 1, 0] as X)) + union.insert(T(words:[0, 0, 1, 0] as X)) + union.insert(T(words:[0, 0, 0, 1] as X)) + union.insert(T(words:[0, 0, 0, 1] as X)) XCTAssertEqual(union.count, 5 as Int) } func testComparing() { - NBKAssertComparisons(T(words:[0, 2, 3, 4] as W), T(words:[1, 2, 3, 4] as W), -Int(1)) - NBKAssertComparisons(T(words:[1, 0, 3, 4] as W), T(words:[1, 2, 3, 4] as W), -Int(1)) - NBKAssertComparisons(T(words:[1, 2, 0, 4] as W), T(words:[1, 2, 3, 4] as W), -Int(1)) - NBKAssertComparisons(T(words:[1, 2, 3, 0] as W), T(words:[1, 2, 3, 4] as W), -Int(1)) - NBKAssertComparisons(T(words:[0, 2, 3, 4] as W), T(words:[0, 2, 3, 4] as W), Int(0)) - NBKAssertComparisons(T(words:[1, 0, 3, 4] as W), T(words:[1, 0, 3, 4] as W), Int(0)) - NBKAssertComparisons(T(words:[1, 2, 0, 4] as W), T(words:[1, 2, 0, 4] as W), Int(0)) - NBKAssertComparisons(T(words:[1, 2, 3, 0] as W), T(words:[1, 2, 3, 0] as W), Int(0)) - NBKAssertComparisons(T(words:[1, 2, 3, 4] as W), T(words:[0, 2, 3, 4] as W), Int(1)) - NBKAssertComparisons(T(words:[1, 2, 3, 4] as W), T(words:[1, 0, 3, 4] as W), Int(1)) - NBKAssertComparisons(T(words:[1, 2, 3, 4] as W), T(words:[1, 2, 0, 4] as W), Int(1)) - NBKAssertComparisons(T(words:[1, 2, 3, 4] as W), T(words:[1, 2, 3, 0] as W), Int(1)) + NBKAssertComparisons(T(words:[0, 2, 3, 4] as X), T(words:[1, 2, 3, 4] as X), -Int(1)) + NBKAssertComparisons(T(words:[1, 0, 3, 4] as X), T(words:[1, 2, 3, 4] as X), -Int(1)) + NBKAssertComparisons(T(words:[1, 2, 0, 4] as X), T(words:[1, 2, 3, 4] as X), -Int(1)) + NBKAssertComparisons(T(words:[1, 2, 3, 0] as X), T(words:[1, 2, 3, 4] as X), -Int(1)) + NBKAssertComparisons(T(words:[0, 2, 3, 4] as X), T(words:[0, 2, 3, 4] as X), Int(0)) + NBKAssertComparisons(T(words:[1, 0, 3, 4] as X), T(words:[1, 0, 3, 4] as X), Int(0)) + NBKAssertComparisons(T(words:[1, 2, 0, 4] as X), T(words:[1, 2, 0, 4] as X), Int(0)) + NBKAssertComparisons(T(words:[1, 2, 3, 0] as X), T(words:[1, 2, 3, 0] as X), Int(0)) + NBKAssertComparisons(T(words:[1, 2, 3, 4] as X), T(words:[0, 2, 3, 4] as X), Int(1)) + NBKAssertComparisons(T(words:[1, 2, 3, 4] as X), T(words:[1, 0, 3, 4] as X), Int(1)) + NBKAssertComparisons(T(words:[1, 2, 3, 4] as X), T(words:[1, 2, 0, 4] as X), Int(1)) + NBKAssertComparisons(T(words:[1, 2, 3, 4] as X), T(words:[1, 2, 3, 0] as X), Int(1)) } func testComparingAtIndex() { - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(0), Int(0)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(1), Int(0)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(2), Int(0)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(3), Int(0)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(4), Int(0)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as X), T(words:[0, 0, 0, 0] as X), Int(0), Int(0)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as X), T(words:[0, 0, 0, 0] as X), Int(1), Int(0)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as X), T(words:[0, 0, 0, 0] as X), Int(2), Int(0)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as X), T(words:[0, 0, 0, 0] as X), Int(3), Int(0)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as X), T(words:[0, 0, 0, 0] as X), Int(4), Int(0)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(0), -Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(1), -Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(2), -Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(3), -Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(4), -Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as X), T(words:[1, 2, 3, 4] as X), Int(0), -Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as X), T(words:[1, 2, 3, 4] as X), Int(1), -Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as X), T(words:[1, 2, 3, 4] as X), Int(2), -Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as X), T(words:[1, 2, 3, 4] as X), Int(3), -Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 0, 0, 0, 0, 0, 0] as X), T(words:[1, 2, 3, 4] as X), Int(4), -Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(0), Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(1), Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(2), Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(3), Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[0, 0, 0, 0] as W), Int(4), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as X), T(words:[0, 0, 0, 0] as X), Int(0), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as X), T(words:[0, 0, 0, 0] as X), Int(1), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as X), T(words:[0, 0, 0, 0] as X), Int(2), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as X), T(words:[0, 0, 0, 0] as X), Int(3), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as X), T(words:[0, 0, 0, 0] as X), Int(4), Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(0), Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(1), Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(2), Int(0)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(3), -Int(1)) - NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as W), T(words:[1, 2, 3, 4] as W), Int(4), -Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as X), T(words:[1, 2, 3, 4] as X), Int(0), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as X), T(words:[1, 2, 3, 4] as X), Int(1), Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as X), T(words:[1, 2, 3, 4] as X), Int(2), Int(0)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as X), T(words:[1, 2, 3, 4] as X), Int(3), -Int(1)) + NBKAssertComparisonsAtIndex(T(words:[0, 0, 1, 2, 3, 4, 0, 0] as X), T(words:[1, 2, 3, 4] as X), Int(4), -Int(1)) } func testComparingByDigit() { diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Complements.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Complements.swift index 306b407e..76815bf5 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Complements.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Complements.swift @@ -11,9 +11,9 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] +private typealias X = [UInt] +private typealias X64 = [UInt64] +private typealias X32 = [UInt32] //*============================================================================* // MARK: * NBK x Flexible Width x Complements x UIntXL @@ -29,15 +29,15 @@ final class NBKFlexibleWidthTestsOnComplementsAsUIntXL: XCTestCase { //=------------------------------------------------------------------------= func testMagnitude() { - XCTAssertEqual(T(words:[ 1, 0, 0, 0] as W).magnitude, M(words:[ 1, 0, 0, 0] as W)) - XCTAssertEqual(T(words:[~0, 0, 0, 0] as W).magnitude, M(words:[~0, 0, 0, 0] as W)) - XCTAssertEqual(T(words:[ 1, 1, 1, 1] as W).magnitude, M(words:[ 1, 1, 1, 1] as W)) - XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as W).magnitude, M(words:[~0, ~0, ~0, ~0] as W)) + XCTAssertEqual(T(words:[ 1, 0, 0, 0] as X).magnitude, M(words:[ 1, 0, 0, 0] as X)) + XCTAssertEqual(T(words:[~0, 0, 0, 0] as X).magnitude, M(words:[~0, 0, 0, 0] as X)) + XCTAssertEqual(T(words:[ 1, 1, 1, 1] as X).magnitude, M(words:[ 1, 1, 1, 1] as X)) + XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as X).magnitude, M(words:[~0, ~0, ~0, ~0] as X)) - XCTAssertEqual(T(magnitude: M(words:[ 1, 0, 0, 0] as W)), M(words:[ 1, 0, 0, 0] as W)) - XCTAssertEqual(T(magnitude: M(words:[~0, 0, 0, 0] as W)), M(words:[~0, 0, 0, 0] as W)) - XCTAssertEqual(T(magnitude: M(words:[ 1, 1, 1, 1] as W)), M(words:[ 1, 1, 1, 1] as W)) - XCTAssertEqual(T(magnitude: M(words:[~0, ~0, ~0, ~0] as W)), M(words:[~0, ~0, ~0, ~0] as W)) + XCTAssertEqual(T(magnitude: M(words:[ 1, 0, 0, 0] as X)), M(words:[ 1, 0, 0, 0] as X)) + XCTAssertEqual(T(magnitude: M(words:[~0, 0, 0, 0] as X)), M(words:[~0, 0, 0, 0] as X)) + XCTAssertEqual(T(magnitude: M(words:[ 1, 1, 1, 1] as X)), M(words:[ 1, 1, 1, 1] as X)) + XCTAssertEqual(T(magnitude: M(words:[~0, ~0, ~0, ~0] as X)), M(words:[~0, ~0, ~0, ~0] as X)) } //=------------------------------------------------------------------------= @@ -45,19 +45,19 @@ final class NBKFlexibleWidthTestsOnComplementsAsUIntXL: XCTestCase { //=------------------------------------------------------------------------= func testOnesComplement() { - NBKAssertOnesComplement(T(words:[ 0, 0, 0, 0] as W), T(words:[~0, 0, 0, 0] as W)) - NBKAssertOnesComplement(T(words:[ 1, 0, 0, 0] as W), T(words:[~1, 0, 0, 0] as W)) - NBKAssertOnesComplement(T(words:[~0, 0, 0, 0] as W), T(words:[ 0, 0, 0, 0] as W)) - NBKAssertOnesComplement(T(words:[ 1, 1, 1, 1] as W), T(words:[~1, ~1, ~1, ~1] as W)) - NBKAssertOnesComplement(T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 0, 0, 0, 0] as W)) + NBKAssertOnesComplement(T(words:[ 0, 0, 0, 0] as X), T(words:[~0, 0, 0, 0] as X)) + NBKAssertOnesComplement(T(words:[ 1, 0, 0, 0] as X), T(words:[~1, 0, 0, 0] as X)) + NBKAssertOnesComplement(T(words:[~0, 0, 0, 0] as X), T(words:[ 0, 0, 0, 0] as X)) + NBKAssertOnesComplement(T(words:[ 1, 1, 1, 1] as X), T(words:[~1, ~1, ~1, ~1] as X)) + NBKAssertOnesComplement(T(words:[~0, ~0, ~0, ~0] as X), T(words:[ 0, 0, 0, 0] as X)) - NBKAssertOnesComplement(T(words:[~0, ~0, ~0, ~0/2 + 0] as W), T(words:[ 0, 0, 0, ~0/2 + 1] as W)) - NBKAssertOnesComplement(T(words:[ 0, 0, 0, ~0/2 + 1] as W), T(words:[~0, ~0, ~0, ~0/2 + 0] as W)) - NBKAssertOnesComplement(T(words:[ 1, 0, 0, ~0/2 + 1] as W), T(words:[~1, ~0, ~0, ~0/2 + 0] as W)) + NBKAssertOnesComplement(T(words:[~0, ~0, ~0, ~0/2 + 0] as X), T(words:[ 0, 0, 0, ~0/2 + 1] as X)) + NBKAssertOnesComplement(T(words:[ 0, 0, 0, ~0/2 + 1] as X), T(words:[~0, ~0, ~0, ~0/2 + 0] as X)) + NBKAssertOnesComplement(T(words:[ 1, 0, 0, ~0/2 + 1] as X), T(words:[~1, ~0, ~0, ~0/2 + 0] as X)) - NBKAssertOnesComplement(T(words:[ 1, 0, 0, ~0/2 + 1] as W), T(words:[~1, ~0, ~0, ~0/2 + 0] as W)) - NBKAssertOnesComplement(T(words:[ 0, 0, 0, ~0/2 + 1] as W), T(words:[~0, ~0, ~0, ~0/2 + 0] as W)) - NBKAssertOnesComplement(T(words:[~0, ~0, ~0, ~0/2 + 0] as W), T(words:[ 0, 0, 0, ~0/2 + 1] as W)) + NBKAssertOnesComplement(T(words:[ 1, 0, 0, ~0/2 + 1] as X), T(words:[~1, ~0, ~0, ~0/2 + 0] as X)) + NBKAssertOnesComplement(T(words:[ 0, 0, 0, ~0/2 + 1] as X), T(words:[~0, ~0, ~0, ~0/2 + 0] as X)) + NBKAssertOnesComplement(T(words:[~0, ~0, ~0, ~0/2 + 0] as X), T(words:[ 0, 0, 0, ~0/2 + 1] as X)) } //=------------------------------------------------------------------------= @@ -65,19 +65,19 @@ final class NBKFlexibleWidthTestsOnComplementsAsUIntXL: XCTestCase { //=------------------------------------------------------------------------= func testTwosComplement() { - NBKAssertTwosComplement(T(words:[ 0, 0, 0, 0] as W), T(words:[ 0, 0, 0, 0] as W), true) - NBKAssertTwosComplement(T(words:[ 1, 0, 0, 0] as W), T(words:[~0, 0, 0, 0] as W)) - NBKAssertTwosComplement(T(words:[~0, 0, 0, 0] as W), T(words:[ 1, 0, 0, 0] as W)) - NBKAssertTwosComplement(T(words:[ 1, 1, 1, 1] as W), T(words:[~0, ~1, ~1, ~1] as W)) - NBKAssertTwosComplement(T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 1, 0, 0, 0] as W)) + NBKAssertTwosComplement(T(words:[ 0, 0, 0, 0] as X), T(words:[ 0, 0, 0, 0] as X), true) + NBKAssertTwosComplement(T(words:[ 1, 0, 0, 0] as X), T(words:[~0, 0, 0, 0] as X)) + NBKAssertTwosComplement(T(words:[~0, 0, 0, 0] as X), T(words:[ 1, 0, 0, 0] as X)) + NBKAssertTwosComplement(T(words:[ 1, 1, 1, 1] as X), T(words:[~0, ~1, ~1, ~1] as X)) + NBKAssertTwosComplement(T(words:[~0, ~0, ~0, ~0] as X), T(words:[ 1, 0, 0, 0] as X)) - NBKAssertTwosComplement(T(words:[~0, ~0, ~0, ~0/2 + 0] as W), T(words:[ 1, 0, 0, ~0/2 + 1] as W)) - NBKAssertTwosComplement(T(words:[ 0, 0, 0, ~0/2 + 1] as W), T(words:[ 0, 0, 0, ~0/2 + 1] as W)) - NBKAssertTwosComplement(T(words:[ 1, 0, 0, ~0/2 + 1] as W), T(words:[~0, ~0, ~0, ~0/2 + 0] as W)) + NBKAssertTwosComplement(T(words:[~0, ~0, ~0, ~0/2 + 0] as X), T(words:[ 1, 0, 0, ~0/2 + 1] as X)) + NBKAssertTwosComplement(T(words:[ 0, 0, 0, ~0/2 + 1] as X), T(words:[ 0, 0, 0, ~0/2 + 1] as X)) + NBKAssertTwosComplement(T(words:[ 1, 0, 0, ~0/2 + 1] as X), T(words:[~0, ~0, ~0, ~0/2 + 0] as X)) - NBKAssertTwosComplement(T(words:[ 1, 0, 0, ~0/2 + 1] as W), T(words:[~0, ~0, ~0, ~0/2 + 0] as W)) - NBKAssertTwosComplement(T(words:[ 0, 0, 0, ~0/2 + 1] as W), T(words:[ 0, 0, 0, ~0/2 + 1] as W)) - NBKAssertTwosComplement(T(words:[~0, ~0, ~0, ~0/2 + 0] as W), T(words:[ 1, 0, 0, ~0/2 + 1] as W)) + NBKAssertTwosComplement(T(words:[ 1, 0, 0, ~0/2 + 1] as X), T(words:[~0, ~0, ~0, ~0/2 + 0] as X)) + NBKAssertTwosComplement(T(words:[ 0, 0, 0, ~0/2 + 1] as X), T(words:[ 0, 0, 0, ~0/2 + 1] as X)) + NBKAssertTwosComplement(T(words:[~0, ~0, ~0, ~0/2 + 0] as X), T(words:[ 1, 0, 0, ~0/2 + 1] as X)) } } diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Division.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Division.swift index f68c8a4e..2350f371 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Division.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Division.swift @@ -11,9 +11,9 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] +private typealias X = [UInt] +private typealias X64 = [UInt64] +private typealias X32 = [UInt32] //*============================================================================* // MARK: * NBK x Flexible Width x Division x UIntXL @@ -42,41 +42,41 @@ final class NBKFlexibleWidthTestsOnDivisionAsUIntXL: XCTestCase { } func testDividingWithLargeDividend() { - NBKAssertDivision(T(x64:[~2, ~4, ~6, 9] as X), T(2), T(x64:[~1, ~2, ~3, 4] as X), T(1)) - NBKAssertDivision(T(x64:[~3, ~6, ~9, 14] as X), T(3), T(x64:[~1, ~2, ~3, 4] as X), T(2)) - NBKAssertDivision(T(x64:[~4, ~8, ~12, 19] as X), T(4), T(x64:[~1, ~2, ~3, 4] as X), T(3)) - NBKAssertDivision(T(x64:[~5, ~10, ~15, 24] as X), T(5), T(x64:[~1, ~2, ~3, 4] as X), T(4)) + NBKAssertDivision(T(x64:[~2, ~4, ~6, 9] as X64), T(2), T(x64:[~1, ~2, ~3, 4] as X64), T(1)) + NBKAssertDivision(T(x64:[~3, ~6, ~9, 14] as X64), T(3), T(x64:[~1, ~2, ~3, 4] as X64), T(2)) + NBKAssertDivision(T(x64:[~4, ~8, ~12, 19] as X64), T(4), T(x64:[~1, ~2, ~3, 4] as X64), T(3)) + NBKAssertDivision(T(x64:[~5, ~10, ~15, 24] as X64), T(5), T(x64:[~1, ~2, ~3, 4] as X64), T(4)) - NBKAssertDivision(T(x64:[~2, ~4, ~6, 9] as X), T(x64:[~1, ~2, ~3, 4] as X), T(2), T(1)) - NBKAssertDivision(T(x64:[~3, ~6, ~9, 14] as X), T(x64:[~1, ~2, ~3, 4] as X), T(3), T(2)) - NBKAssertDivision(T(x64:[~4, ~8, ~12, 19] as X), T(x64:[~1, ~2, ~3, 4] as X), T(4), T(3)) - NBKAssertDivision(T(x64:[~5, ~10, ~15, 24] as X), T(x64:[~1, ~2, ~3, 4] as X), T(5), T(4)) + NBKAssertDivision(T(x64:[~2, ~4, ~6, 9] as X64), T(x64:[~1, ~2, ~3, 4] as X64), T(2), T(1)) + NBKAssertDivision(T(x64:[~3, ~6, ~9, 14] as X64), T(x64:[~1, ~2, ~3, 4] as X64), T(3), T(2)) + NBKAssertDivision(T(x64:[~4, ~8, ~12, 19] as X64), T(x64:[~1, ~2, ~3, 4] as X64), T(4), T(3)) + NBKAssertDivision(T(x64:[~5, ~10, ~15, 24] as X64), T(x64:[~1, ~2, ~3, 4] as X64), T(5), T(4)) } func testDividingWithLargeDivisor() { - NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X), T(x64:[ 3, 4, 5, 6 &+ 1 << 63] as X), T(0), T(x64:[1, 2, 3, 4 + 1 << 63] as X)) - NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X), T(x64:[ 2, 3, 4, 5 &+ 1 << 63] as X), T(0), T(x64:[1, 2, 3, 4 + 1 << 63] as X)) + NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X64), T(x64:[ 3, 4, 5, 6 &+ 1 << 63] as X64), T(0), T(x64:[1, 2, 3, 4 + 1 << 63] as X64)) + NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X64), T(x64:[ 2, 3, 4, 5 &+ 1 << 63] as X64), T(0), T(x64:[1, 2, 3, 4 + 1 << 63] as X64)) - NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X), T(x64:[ 1, 2, 3, 4 &+ 1 << 63] as X), T(1), T(x64:[0, 0, 0, 0] as X)) - NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X), T(x64:[ 0, 1, 2, 3 &+ 1 << 63] as X), T(1), T(x64:[1, 1, 1, 1] as X)) - NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X), T(x64:[~0, ~0, 0, 2 &+ 1 << 63] as X), T(1), T(x64:[2, 2, 2, 2] as X)) - NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X), T(x64:[~1, ~1, ~0, 0 &+ 1 << 63] as X), T(1), T(x64:[3, 3, 3, 3] as X)) - NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X), T(x64:[~2, ~2, ~1, ~0 &+ 1 << 63] as X), T(1), T(x64:[4, 4, 4, 4] as X)) - NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X), T(x64:[~3, ~3, ~2, ~1 &+ 1 << 63] as X), T(1), T(x64:[5, 5, 5, 5] as X)) - NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X), T(x64:[~4, ~4, ~3, ~2 &+ 1 << 63] as X), T(1), T(x64:[6, 6, 6, 6] as X)) - NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X), T(x64:[~5, ~5, ~4, ~3 &+ 1 << 63] as X), T(1), T(x64:[7, 7, 7, 7] as X)) + NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X64), T(x64:[ 1, 2, 3, 4 &+ 1 << 63] as X64), T(1), T(x64:[0, 0, 0, 0] as X64)) + NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X64), T(x64:[ 0, 1, 2, 3 &+ 1 << 63] as X64), T(1), T(x64:[1, 1, 1, 1] as X64)) + NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X64), T(x64:[~0, ~0, 0, 2 &+ 1 << 63] as X64), T(1), T(x64:[2, 2, 2, 2] as X64)) + NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X64), T(x64:[~1, ~1, ~0, 0 &+ 1 << 63] as X64), T(1), T(x64:[3, 3, 3, 3] as X64)) + NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X64), T(x64:[~2, ~2, ~1, ~0 &+ 1 << 63] as X64), T(1), T(x64:[4, 4, 4, 4] as X64)) + NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X64), T(x64:[~3, ~3, ~2, ~1 &+ 1 << 63] as X64), T(1), T(x64:[5, 5, 5, 5] as X64)) + NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X64), T(x64:[~4, ~4, ~3, ~2 &+ 1 << 63] as X64), T(1), T(x64:[6, 6, 6, 6] as X64)) + NBKAssertDivision(T(x64:[1, 2, 3, 4 + 1 << 63] as X64), T(x64:[~5, ~5, ~4, ~3 &+ 1 << 63] as X64), T(1), T(x64:[7, 7, 7, 7] as X64)) } func testDividingLikeFullWidth() { var dividend: T //=--------------------------------------= - dividend = T(words:[ 06, 17, 35, 61, 61, 52, 32, 00] as W) - NBKAssertDivision(dividend, T(words:[ 1, 2, 3, 4] as W), T(words:[ 5, 6, 7, 8] as W), T(words:[ 1, 1, 1, 1] as W)) - NBKAssertDivision(dividend, T(words:[ 5, 6, 7, 8] as W), T(words:[ 1, 2, 3, 4] as W), T(words:[ 1, 1, 1, 1] as W)) + dividend = T(words:[ 06, 17, 35, 61, 61, 52, 32, 00] as X) + NBKAssertDivision(dividend, T(words:[ 1, 2, 3, 4] as X), T(words:[ 5, 6, 7, 8] as X), T(words:[ 1, 1, 1, 1] as X)) + NBKAssertDivision(dividend, T(words:[ 5, 6, 7, 8] as X), T(words:[ 1, 2, 3, 4] as X), T(words:[ 1, 1, 1, 1] as X)) //=--------------------------------------= - dividend = T(words:[ 34, 54, 63, 62, 34, 16, 05, 00] as W) - NBKAssertDivision(dividend, T(words:[ 4, 3, 2, 1] as W), T(words:[ 9, 7, 6, 5] as W), T(words:[~1, ~1, ~0, 0] as W)) - NBKAssertDivision(dividend, T(words:[ 8, 7, 6, 5] as W), T(words:[ 4, 3, 2, 1] as W), T(words:[ 2, 2, 2, 2] as W)) + dividend = T(words:[ 34, 54, 63, 62, 34, 16, 05, 00] as X) + NBKAssertDivision(dividend, T(words:[ 4, 3, 2, 1] as X), T(words:[ 9, 7, 6, 5] as X), T(words:[~1, ~1, ~0, 0] as X)) + NBKAssertDivision(dividend, T(words:[ 8, 7, 6, 5] as X), T(words:[ 4, 3, 2, 1] as X), T(words:[ 2, 2, 2, 2] as X)) } //=------------------------------------------------------------------------= @@ -97,10 +97,10 @@ final class NBKFlexibleWidthTestsOnDivisionAsUIntXL: XCTestCase { } func testDividingByDigitWithLargeDividend() { - NBKAssertDivisionByDigit(T(words:[~2, ~4, ~6, 9] as W), UInt(2), T(words:[~1, ~2, ~3, 4] as W), UInt(1)) - NBKAssertDivisionByDigit(T(words:[~3, ~6, ~9, 14] as W), UInt(3), T(words:[~1, ~2, ~3, 4] as W), UInt(2)) - NBKAssertDivisionByDigit(T(words:[~4, ~8, ~12, 19] as W), UInt(4), T(words:[~1, ~2, ~3, 4] as W), UInt(3)) - NBKAssertDivisionByDigit(T(words:[~5, ~10, ~15, 24] as W), UInt(5), T(words:[~1, ~2, ~3, 4] as W), UInt(4)) + NBKAssertDivisionByDigit(T(words:[~2, ~4, ~6, 9] as X), UInt(2), T(words:[~1, ~2, ~3, 4] as X), UInt(1)) + NBKAssertDivisionByDigit(T(words:[~3, ~6, ~9, 14] as X), UInt(3), T(words:[~1, ~2, ~3, 4] as X), UInt(2)) + NBKAssertDivisionByDigit(T(words:[~4, ~8, ~12, 19] as X), UInt(4), T(words:[~1, ~2, ~3, 4] as X), UInt(3)) + NBKAssertDivisionByDigit(T(words:[~5, ~10, ~15, 24] as X), UInt(5), T(words:[~1, ~2, ~3, 4] as X), UInt(4)) } //=------------------------------------------------------------------------= @@ -140,16 +140,16 @@ final class NBKFlexibleWidthTestsOnDivisionCodeCoverageAsUIntXL: XCTestCase { func testDividingFullWidth3212MSBAsUInt256() { var dividend: T, divisor: T, quotient: T, remainder: T //=--------------------------------------= - dividend = T(x64:[ 0, 0, 0, 0, 0, ~0, ~0, ~0] as X) - divisor = T(x64:[~0, ~0, ~0, ~0, 0, 0, 0, 0] as X) - quotient = T(x64:[ 0, ~0, ~0, ~0, 0, 0, 0, 0] as X) - remainder = T(x64:[ 0, ~0, ~0, ~0, 0, 0, 0, 0] as X) + dividend = T(x64:[ 0, 0, 0, 0, 0, ~0, ~0, ~0] as X64) + divisor = T(x64:[~0, ~0, ~0, ~0, 0, 0, 0, 0] as X64) + quotient = T(x64:[ 0, ~0, ~0, ~0, 0, 0, 0, 0] as X64) + remainder = T(x64:[ 0, ~0, ~0, ~0, 0, 0, 0, 0] as X64) NBKAssertDivision(dividend, divisor, quotient, remainder) //=--------------------------------------= - dividend = T(x64:[~0, ~0, ~0, ~0, 0, ~0, ~0, ~0] as X) - divisor = T(x64:[~0, ~0, ~0, ~0, 0, 0, 0, 0] as X) - quotient = T(x64:[ 1, ~0, ~0, ~0, 0, 0, 0, 0] as X) - remainder = T(x64:[ 0, ~0, ~0, ~0, 0, 0, 0, 0] as X) + dividend = T(x64:[~0, ~0, ~0, ~0, 0, ~0, ~0, ~0] as X64) + divisor = T(x64:[~0, ~0, ~0, ~0, 0, 0, 0, 0] as X64) + quotient = T(x64:[ 1, ~0, ~0, ~0, 0, 0, 0, 0] as X64) + remainder = T(x64:[ 0, ~0, ~0, ~0, 0, 0, 0, 0] as X64) NBKAssertDivision(dividend, divisor, quotient, remainder) } } diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Exponentiation.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Exponentiation.swift index 57fa95cf..95ed38d6 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Exponentiation.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Exponentiation.swift @@ -11,9 +11,9 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] +private typealias X = [UInt] +private typealias X64 = [UInt64] +private typealias X32 = [UInt32] //*============================================================================* // MARK: * NBK x Flexible Width x Exponentiation x UIntXL @@ -50,10 +50,10 @@ final class NBKFlexibleWidthTestsOnExponentiationAsUIntXL: XCTestCase { } for word in (-5 ... 5).lazy.map(UInt.init(bitPattern:)){ - with(T(words:[word ] as W)) - with(T(words:[word, word &- 1 ] as W)) - with(T(words:[word, word &- 1, word &+ 2 ] as W)) - with(T(words:[word, word &- 1, word &+ 2, word &* 3] as W)) + with(T(words:[word ] as X)) + with(T(words:[word, word &- 1 ] as X)) + with(T(words:[word, word &- 1, word &+ 2 ] as X)) + with(T(words:[word, word &- 1, word &+ 2, word &* 3] as X)) } } @@ -63,10 +63,10 @@ final class NBKFlexibleWidthTestsOnExponentiationAsUIntXL: XCTestCase { } for word in (-5 ... 5).lazy.map(UInt.init(bitPattern:)){ - with(T(words:[word ] as W)) - with(T(words:[word, word &- 1 ] as W)) - with(T(words:[word, word &- 1, word &+ 2 ] as W)) - with(T(words:[word, word &- 1, word &+ 2, word &* 3] as W)) + with(T(words:[word ] as X)) + with(T(words:[word, word &- 1 ] as X)) + with(T(words:[word, word &- 1, word &+ 2 ] as X)) + with(T(words:[word, word &- 1, word &+ 2, word &* 3] as X)) } } @@ -76,10 +76,10 @@ final class NBKFlexibleWidthTestsOnExponentiationAsUIntXL: XCTestCase { } for word in (-5 ... 5).lazy.map(UInt.init(bitPattern:)){ - with(T(words:[word ] as W)) - with(T(words:[word, word &- 1 ] as W)) - with(T(words:[word, word &- 1, word &+ 2 ] as W)) - with(T(words:[word, word &- 1, word &+ 2, word &* 3] as W)) + with(T(words:[word ] as X)) + with(T(words:[word, word &- 1 ] as X)) + with(T(words:[word, word &- 1, word &+ 2 ] as X)) + with(T(words:[word, word &- 1, word &+ 2, word &* 3] as X)) } } @@ -89,10 +89,10 @@ final class NBKFlexibleWidthTestsOnExponentiationAsUIntXL: XCTestCase { } for word in (-5 ... 5).lazy.map(UInt.init(bitPattern:)){ - with(T(words:[word ] as W)) - with(T(words:[word, word &- 1 ] as W)) - with(T(words:[word, word &- 1, word &+ 2 ] as W)) - with(T(words:[word, word &- 1, word &+ 2, word &* 3] as W)) + with(T(words:[word ] as X)) + with(T(words:[word, word &- 1 ] as X)) + with(T(words:[word, word &- 1, word &+ 2 ] as X)) + with(T(words:[word, word &- 1, word &+ 2, word &* 3] as X)) } } diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Literals.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Literals.swift index e7a599a9..ed6065c4 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Literals.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Literals.swift @@ -11,9 +11,9 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] +private typealias X = [UInt] +private typealias X64 = [UInt64] +private typealias X32 = [UInt32] //*============================================================================* // MARK: * NBK x Flexible Width x Literals x UIntXL @@ -28,76 +28,76 @@ final class NBKFlexibleWidthTestsOnLiteralsAsUIntXL: XCTestCase { //=------------------------------------------------------------------------= func testFromIntegerLiteral() { - XCTAssertEqual(T(x64:[ 0, 0, 0, 0] as X), (0)) - XCTAssertEqual(T(x64:[ 10, 0, 0, 0] as X), (10)) - XCTAssertEqual(T(x64:[ 2, 0, 0, 0] as X), (0b10)) - XCTAssertEqual(T(x64:[ 8, 0, 0, 0] as X), (0o10)) - XCTAssertEqual(T(x64:[ 16, 0, 0, 0] as X), (0x10)) - XCTAssertEqual(T(x64:[ 16, 0, 0, 0] as X), (0x10)) - XCTAssertEqual(T(x64:[ 0, 0, 0, 0] as X), (+0)) - XCTAssertEqual(T(x64:[ 10, 0, 0, 0] as X), (+10)) - XCTAssertEqual(T(x64:[ 2, 0, 0, 0] as X), (+0b10)) - XCTAssertEqual(T(x64:[ 8, 0, 0, 0] as X), (+0o10)) - XCTAssertEqual(T(x64:[ 16, 0, 0, 0] as X), (+0x10)) - XCTAssertEqual(T(x64:[ 16, 0, 0, 0] as X), (+0x10)) + XCTAssertEqual(T(x64:[ 0, 0, 0, 0] as X64), (0)) + XCTAssertEqual(T(x64:[ 10, 0, 0, 0] as X64), (10)) + XCTAssertEqual(T(x64:[ 2, 0, 0, 0] as X64), (0b10)) + XCTAssertEqual(T(x64:[ 8, 0, 0, 0] as X64), (0o10)) + XCTAssertEqual(T(x64:[ 16, 0, 0, 0] as X64), (0x10)) + XCTAssertEqual(T(x64:[ 16, 0, 0, 0] as X64), (0x10)) + XCTAssertEqual(T(x64:[ 0, 0, 0, 0] as X64), (+0)) + XCTAssertEqual(T(x64:[ 10, 0, 0, 0] as X64), (+10)) + XCTAssertEqual(T(x64:[ 2, 0, 0, 0] as X64), (+0b10)) + XCTAssertEqual(T(x64:[ 8, 0, 0, 0] as X64), (+0o10)) + XCTAssertEqual(T(x64:[ 16, 0, 0, 0] as X64), (+0x10)) + XCTAssertEqual(T(x64:[ 16, 0, 0, 0] as X64), (+0x10)) #if SBI && swift(>=5.8) - XCTAssertEqual(T(x64:[ 0, 0, 0, 0] as X), (0x000000000000000000000000000000000000000000000000000000000000000000000000000000)) - XCTAssertEqual(T(x64:[ ~0, 0, 0, 0] as X), (0x00000000000000000000000000000000000000000000000000000000000000ffffffffffffffff)) - XCTAssertEqual(T(x64:[ ~0, ~0, 0, 0] as X), (0x0000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffff)) - XCTAssertEqual(T(x64:[ ~0, ~0, ~0, 0] as X), (0x000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff)) - XCTAssertEqual(T(x64:[ ~0, ~0, ~0, ~0] as X), (0x00000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)) - XCTAssertEqual(T(x64:[ 0, ~0, ~0, ~0] as X), (0x00000000000000ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000)) - XCTAssertEqual(T(x64:[ 0, 0, ~0, ~0] as X), (0x00000000000000ffffffffffffffffffffffffffffffff00000000000000000000000000000000)) - XCTAssertEqual(T(x64:[ 0, 0, 0, ~0] as X), (0x00000000000000ffffffffffffffff000000000000000000000000000000000000000000000000)) + XCTAssertEqual(T(x64:[ 0, 0, 0, 0] as X64), (0x000000000000000000000000000000000000000000000000000000000000000000000000000000)) + XCTAssertEqual(T(x64:[ ~0, 0, 0, 0] as X64), (0x00000000000000000000000000000000000000000000000000000000000000ffffffffffffffff)) + XCTAssertEqual(T(x64:[ ~0, ~0, 0, 0] as X64), (0x0000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffff)) + XCTAssertEqual(T(x64:[ ~0, ~0, ~0, 0] as X64), (0x000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff)) + XCTAssertEqual(T(x64:[ ~0, ~0, ~0, ~0] as X64), (0x00000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)) + XCTAssertEqual(T(x64:[ 0, ~0, ~0, ~0] as X64), (0x00000000000000ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000)) + XCTAssertEqual(T(x64:[ 0, 0, ~0, ~0] as X64), (0x00000000000000ffffffffffffffffffffffffffffffff00000000000000000000000000000000)) + XCTAssertEqual(T(x64:[ 0, 0, 0, ~0] as X64), (0x00000000000000ffffffffffffffff000000000000000000000000000000000000000000000000)) XCTAssertEqual(T(exactlyIntegerLiteral: (-0x000000000000000000000000000000000000000000000000000000000000000000000000000001)), nil) - XCTAssertEqual(T(x64:[ 0, 0, 0, 0] as X), (00000000000000000000000000000000000000000000000000000000000000000000000000000000)) - XCTAssertEqual(T(x64:[ ~0, 0, 0, 0] as X), (00000000000000000000000000000000000000000000000000000000000018446744073709551615)) - XCTAssertEqual(T(x64:[ ~0, ~0, 0, 0] as X), (00000000000000000000000000000000000000000340282366920938463463374607431768211455)) - XCTAssertEqual(T(x64:[ ~0, ~0, ~0, 0] as X), (00000000000000000000006277101735386680763835789423207666416102355444464034512895)) - XCTAssertEqual(T(x64:[ ~0, ~0, ~0, ~0] as X), (00115792089237316195423570985008687907853269984665640564039457584007913129639935)) - XCTAssertEqual(T(x64:[ 0, ~0, ~0, ~0] as X), (00115792089237316195423570985008687907853269984665640564039439137263839420088320)) - XCTAssertEqual(T(x64:[ 0, 0, ~0, ~0] as X), (00115792089237316195423570985008687907852929702298719625575994209400481361428480)) - XCTAssertEqual(T(x64:[ 0, 0, 0, ~0] as X), (00115792089237316195417293883273301227089434195242432897623355228563449095127040)) + XCTAssertEqual(T(x64:[ 0, 0, 0, 0] as X64), (00000000000000000000000000000000000000000000000000000000000000000000000000000000)) + XCTAssertEqual(T(x64:[ ~0, 0, 0, 0] as X64), (00000000000000000000000000000000000000000000000000000000000018446744073709551615)) + XCTAssertEqual(T(x64:[ ~0, ~0, 0, 0] as X64), (00000000000000000000000000000000000000000340282366920938463463374607431768211455)) + XCTAssertEqual(T(x64:[ ~0, ~0, ~0, 0] as X64), (00000000000000000000006277101735386680763835789423207666416102355444464034512895)) + XCTAssertEqual(T(x64:[ ~0, ~0, ~0, ~0] as X64), (00115792089237316195423570985008687907853269984665640564039457584007913129639935)) + XCTAssertEqual(T(x64:[ 0, ~0, ~0, ~0] as X64), (00115792089237316195423570985008687907853269984665640564039439137263839420088320)) + XCTAssertEqual(T(x64:[ 0, 0, ~0, ~0] as X64), (00115792089237316195423570985008687907852929702298719625575994209400481361428480)) + XCTAssertEqual(T(x64:[ 0, 0, 0, ~0] as X64), (00115792089237316195417293883273301227089434195242432897623355228563449095127040)) XCTAssertEqual(T(exactlyIntegerLiteral: (-00000000000000000000000000000000000000000000000000000000000000000000000000000001)), nil) #else - XCTAssertEqual(T(integerLiteral: UInt.max), T(x64:[UInt64(UInt.max), 0, 0, 0] as X)) - XCTAssertEqual(T(integerLiteral: UInt.min), T(x64:[UInt64(UInt.min), 0, 0, 0] as X)) + XCTAssertEqual(T(integerLiteral: UInt.max), T(x64:[UInt64(UInt.max), 0, 0, 0] as X64)) + XCTAssertEqual(T(integerLiteral: UInt.min), T(x64:[UInt64(UInt.min), 0, 0, 0] as X64)) #endif } func testFromStringLiteral() { - XCTAssertEqual(T(x64:[ 0, 0, 0, 0] as X), "0") - XCTAssertEqual(T(x64:[ 10, 0, 0, 0] as X), "10") - XCTAssertEqual(T(x64:[ 2, 0, 0, 0] as X), "0b10") - XCTAssertEqual(T(x64:[ 8, 0, 0, 0] as X), "0o10") - XCTAssertEqual(T(x64:[ 16, 0, 0, 0] as X), "0x10") - XCTAssertEqual(T(x64:[ 16, 0, 0, 0] as X), "0x10") - XCTAssertEqual(T(x64:[ 0, 0, 0, 0] as X), "+0") - XCTAssertEqual(T(x64:[ 10, 0, 0, 0] as X), "+10") - XCTAssertEqual(T(x64:[ 2, 0, 0, 0] as X), "+0b10") - XCTAssertEqual(T(x64:[ 8, 0, 0, 0] as X), "+0o10") - XCTAssertEqual(T(x64:[ 16, 0, 0, 0] as X), "+0x10") - XCTAssertEqual(T(x64:[ 16, 0, 0, 0] as X), "+0x10") + XCTAssertEqual(T(x64:[ 0, 0, 0, 0] as X64), "0") + XCTAssertEqual(T(x64:[ 10, 0, 0, 0] as X64), "10") + XCTAssertEqual(T(x64:[ 2, 0, 0, 0] as X64), "0b10") + XCTAssertEqual(T(x64:[ 8, 0, 0, 0] as X64), "0o10") + XCTAssertEqual(T(x64:[ 16, 0, 0, 0] as X64), "0x10") + XCTAssertEqual(T(x64:[ 16, 0, 0, 0] as X64), "0x10") + XCTAssertEqual(T(x64:[ 0, 0, 0, 0] as X64), "+0") + XCTAssertEqual(T(x64:[ 10, 0, 0, 0] as X64), "+10") + XCTAssertEqual(T(x64:[ 2, 0, 0, 0] as X64), "+0b10") + XCTAssertEqual(T(x64:[ 8, 0, 0, 0] as X64), "+0o10") + XCTAssertEqual(T(x64:[ 16, 0, 0, 0] as X64), "+0x10") + XCTAssertEqual(T(x64:[ 16, 0, 0, 0] as X64), "+0x10") - XCTAssertEqual(T(x64:[ 0, 0, 0, 0] as X), "0x000000000000000000000000000000000000000000000000000000000000000000000000000000") - XCTAssertEqual(T(x64:[ ~0, 0, 0, 0] as X), "0x00000000000000000000000000000000000000000000000000000000000000ffffffffffffffff") - XCTAssertEqual(T(x64:[ ~0, ~0, 0, 0] as X), "0x0000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffff") - XCTAssertEqual(T(x64:[ ~0, ~0, ~0, 0] as X), "0x000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff") - XCTAssertEqual(T(x64:[ ~0, ~0, ~0, ~0] as X), "0x00000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") - XCTAssertEqual(T(x64:[ 0, ~0, ~0, ~0] as X), "0x00000000000000ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000") - XCTAssertEqual(T(x64:[ 0, 0, ~0, ~0] as X), "0x00000000000000ffffffffffffffffffffffffffffffff00000000000000000000000000000000") - XCTAssertEqual(T(x64:[ 0, 0, 0, ~0] as X), "0x00000000000000ffffffffffffffff000000000000000000000000000000000000000000000000") + XCTAssertEqual(T(x64:[ 0, 0, 0, 0] as X64), "0x000000000000000000000000000000000000000000000000000000000000000000000000000000") + XCTAssertEqual(T(x64:[ ~0, 0, 0, 0] as X64), "0x00000000000000000000000000000000000000000000000000000000000000ffffffffffffffff") + XCTAssertEqual(T(x64:[ ~0, ~0, 0, 0] as X64), "0x0000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffff") + XCTAssertEqual(T(x64:[ ~0, ~0, ~0, 0] as X64), "0x000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff") + XCTAssertEqual(T(x64:[ ~0, ~0, ~0, ~0] as X64), "0x00000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") + XCTAssertEqual(T(x64:[ 0, ~0, ~0, ~0] as X64), "0x00000000000000ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000") + XCTAssertEqual(T(x64:[ 0, 0, ~0, ~0] as X64), "0x00000000000000ffffffffffffffffffffffffffffffff00000000000000000000000000000000") + XCTAssertEqual(T(x64:[ 0, 0, 0, ~0] as X64), "0x00000000000000ffffffffffffffff000000000000000000000000000000000000000000000000") XCTAssertEqual(T(exactlyStringLiteral: "-0x000000000000000000000000000000000000000000000000000000000000000000000000000001"), nil) - XCTAssertEqual(T(x64:[ 0, 0, 0, 0] as X), "00000000000000000000000000000000000000000000000000000000000000000000000000000000") - XCTAssertEqual(T(x64:[ ~0, 0, 0, 0] as X), "00000000000000000000000000000000000000000000000000000000000018446744073709551615") - XCTAssertEqual(T(x64:[ ~0, ~0, 0, 0] as X), "00000000000000000000000000000000000000000340282366920938463463374607431768211455") - XCTAssertEqual(T(x64:[ ~0, ~0, ~0, 0] as X), "00000000000000000000006277101735386680763835789423207666416102355444464034512895") - XCTAssertEqual(T(x64:[ ~0, ~0, ~0, ~0] as X), "00115792089237316195423570985008687907853269984665640564039457584007913129639935") - XCTAssertEqual(T(x64:[ 0, ~0, ~0, ~0] as X), "00115792089237316195423570985008687907853269984665640564039439137263839420088320") - XCTAssertEqual(T(x64:[ 0, 0, ~0, ~0] as X), "00115792089237316195423570985008687907852929702298719625575994209400481361428480") - XCTAssertEqual(T(x64:[ 0, 0, 0, ~0] as X), "00115792089237316195417293883273301227089434195242432897623355228563449095127040") + XCTAssertEqual(T(x64:[ 0, 0, 0, 0] as X64), "00000000000000000000000000000000000000000000000000000000000000000000000000000000") + XCTAssertEqual(T(x64:[ ~0, 0, 0, 0] as X64), "00000000000000000000000000000000000000000000000000000000000018446744073709551615") + XCTAssertEqual(T(x64:[ ~0, ~0, 0, 0] as X64), "00000000000000000000000000000000000000000340282366920938463463374607431768211455") + XCTAssertEqual(T(x64:[ ~0, ~0, ~0, 0] as X64), "00000000000000000000006277101735386680763835789423207666416102355444464034512895") + XCTAssertEqual(T(x64:[ ~0, ~0, ~0, ~0] as X64), "00115792089237316195423570985008687907853269984665640564039457584007913129639935") + XCTAssertEqual(T(x64:[ 0, ~0, ~0, ~0] as X64), "00115792089237316195423570985008687907853269984665640564039439137263839420088320") + XCTAssertEqual(T(x64:[ 0, 0, ~0, ~0] as X64), "00115792089237316195423570985008687907852929702298719625575994209400481361428480") + XCTAssertEqual(T(x64:[ 0, 0, 0, ~0] as X64), "00115792089237316195417293883273301227089434195242432897623355228563449095127040") XCTAssertEqual(T(exactlyStringLiteral: "-00000000000000000000000000000000000000000000000000000000000000000000000000000001"), nil) } } diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Logic.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Logic.swift index 72422af7..7d1915bb 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Logic.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Logic.swift @@ -11,9 +11,9 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] +private typealias X = [UInt] +private typealias X64 = [UInt64] +private typealias X32 = [UInt32] //*============================================================================* // MARK: * NBK x Flexible Width x Logic x UIntXL @@ -28,44 +28,44 @@ final class NBKFlexibleWidthTestsOnLogicAsUIntXL: XCTestCase { //=------------------------------------------------------------------------= func testNot() { - NBKAssertNot(T(words:[ 0, 0, 0, 0] as W), T(words:[~0, 0, 0, 0] as W)) - NBKAssertNot(T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 0, 0, 0, 0] as W)) + NBKAssertNot(T(words:[ 0, 0, 0, 0] as X), T(words:[~0, 0, 0, 0] as X)) + NBKAssertNot(T(words:[~0, ~0, ~0, ~0] as X), T(words:[ 0, 0, 0, 0] as X)) - NBKAssertNot(T(words:[ 0, 1, 2, 3] as W), T(words:[~0, ~1, ~2, ~3] as W)) - NBKAssertNot(T(words:[~0, ~1, ~2, ~3] as W), T(words:[ 0, 1, 2, 3] as W)) + NBKAssertNot(T(words:[ 0, 1, 2, 3] as X), T(words:[~0, ~1, ~2, ~3] as X)) + NBKAssertNot(T(words:[~0, ~1, ~2, ~3] as X), T(words:[ 0, 1, 2, 3] as X)) } func testAnd() { - NBKAssertAnd(T(words:[ 0, 1, 2, 3] as W), T(words:[ 0, 0, 0, 0] as W), T(words:[ 0, 0, 0, 0] as W)) - NBKAssertAnd(T(words:[ 3, 2, 1, 0] as W), T(words:[ 0, 0, 0, 0] as W), T(words:[ 0, 0, 0, 0] as W)) + NBKAssertAnd(T(words:[ 0, 1, 2, 3] as X), T(words:[ 0, 0, 0, 0] as X), T(words:[ 0, 0, 0, 0] as X)) + NBKAssertAnd(T(words:[ 3, 2, 1, 0] as X), T(words:[ 0, 0, 0, 0] as X), T(words:[ 0, 0, 0, 0] as X)) - NBKAssertAnd(T(words:[ 0, 1, 2, 3] as W), T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 0, 1, 2, 3] as W)) - NBKAssertAnd(T(words:[ 3, 2, 1, 0] as W), T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 3, 2, 1, 0] as W)) + NBKAssertAnd(T(words:[ 0, 1, 2, 3] as X), T(words:[~0, ~0, ~0, ~0] as X), T(words:[ 0, 1, 2, 3] as X)) + NBKAssertAnd(T(words:[ 3, 2, 1, 0] as X), T(words:[~0, ~0, ~0, ~0] as X), T(words:[ 3, 2, 1, 0] as X)) - NBKAssertAnd(T(words:[ 0, 1, 2, 3] as W), T(words:[ 1, 1, 1, 1] as W), T(words:[ 0, 1, 0, 1] as W)) - NBKAssertAnd(T(words:[ 3, 2, 1, 0] as W), T(words:[ 1, 1, 1, 1] as W), T(words:[ 1, 0, 1, 0] as W)) + NBKAssertAnd(T(words:[ 0, 1, 2, 3] as X), T(words:[ 1, 1, 1, 1] as X), T(words:[ 0, 1, 0, 1] as X)) + NBKAssertAnd(T(words:[ 3, 2, 1, 0] as X), T(words:[ 1, 1, 1, 1] as X), T(words:[ 1, 0, 1, 0] as X)) } func testOr() { - NBKAssertOr (T(words:[ 0, 1, 2, 3] as W), T(words:[ 0, 0, 0, 0] as W), T(words:[ 0, 1, 2, 3] as W)) - NBKAssertOr (T(words:[ 3, 2, 1, 0] as W), T(words:[ 0, 0, 0, 0] as W), T(words:[ 3, 2, 1, 0] as W)) + NBKAssertOr (T(words:[ 0, 1, 2, 3] as X), T(words:[ 0, 0, 0, 0] as X), T(words:[ 0, 1, 2, 3] as X)) + NBKAssertOr (T(words:[ 3, 2, 1, 0] as X), T(words:[ 0, 0, 0, 0] as X), T(words:[ 3, 2, 1, 0] as X)) - NBKAssertOr (T(words:[ 0, 1, 2, 3] as W), T(words:[~0, ~0, ~0, ~0] as W), T(words:[~0, ~0, ~0, ~0] as W)) - NBKAssertOr (T(words:[ 3, 2, 1, 0] as W), T(words:[~0, ~0, ~0, ~0] as W), T(words:[~0, ~0, ~0, ~0] as W)) + NBKAssertOr (T(words:[ 0, 1, 2, 3] as X), T(words:[~0, ~0, ~0, ~0] as X), T(words:[~0, ~0, ~0, ~0] as X)) + NBKAssertOr (T(words:[ 3, 2, 1, 0] as X), T(words:[~0, ~0, ~0, ~0] as X), T(words:[~0, ~0, ~0, ~0] as X)) - NBKAssertOr (T(words:[ 0, 1, 2, 3] as W), T(words:[ 1, 1, 1, 1] as W), T(words:[ 1, 1, 3, 3] as W)) - NBKAssertOr (T(words:[ 3, 2, 1, 0] as W), T(words:[ 1, 1, 1, 1] as W), T(words:[ 3, 3, 1, 1] as W)) + NBKAssertOr (T(words:[ 0, 1, 2, 3] as X), T(words:[ 1, 1, 1, 1] as X), T(words:[ 1, 1, 3, 3] as X)) + NBKAssertOr (T(words:[ 3, 2, 1, 0] as X), T(words:[ 1, 1, 1, 1] as X), T(words:[ 3, 3, 1, 1] as X)) } func testXor() { - NBKAssertXor(T(words:[ 0, 1, 2, 3] as W), T(words:[ 0, 0, 0, 0] as W), T(words:[ 0, 1, 2, 3] as W)) - NBKAssertXor(T(words:[ 3, 2, 1, 0] as W), T(words:[ 0, 0, 0, 0] as W), T(words:[ 3, 2, 1, 0] as W)) + NBKAssertXor(T(words:[ 0, 1, 2, 3] as X), T(words:[ 0, 0, 0, 0] as X), T(words:[ 0, 1, 2, 3] as X)) + NBKAssertXor(T(words:[ 3, 2, 1, 0] as X), T(words:[ 0, 0, 0, 0] as X), T(words:[ 3, 2, 1, 0] as X)) - NBKAssertXor(T(words:[ 0, 1, 2, 3] as W), T(words:[~0, ~0, ~0, ~0] as W), T(words:[~0, ~1, ~2, ~3] as W)) - NBKAssertXor(T(words:[ 3, 2, 1, 0] as W), T(words:[~0, ~0, ~0, ~0] as W), T(words:[~3, ~2, ~1, ~0] as W)) + NBKAssertXor(T(words:[ 0, 1, 2, 3] as X), T(words:[~0, ~0, ~0, ~0] as X), T(words:[~0, ~1, ~2, ~3] as X)) + NBKAssertXor(T(words:[ 3, 2, 1, 0] as X), T(words:[~0, ~0, ~0, ~0] as X), T(words:[~3, ~2, ~1, ~0] as X)) - NBKAssertXor(T(words:[ 0, 1, 2, 3] as W), T(words:[ 1, 1, 1, 1] as W), T(words:[ 1, 0, 3, 2] as W)) - NBKAssertXor(T(words:[ 3, 2, 1, 0] as W), T(words:[ 1, 1, 1, 1] as W), T(words:[ 2, 3, 0, 1] as W)) + NBKAssertXor(T(words:[ 0, 1, 2, 3] as X), T(words:[ 1, 1, 1, 1] as X), T(words:[ 1, 0, 3, 2] as X)) + NBKAssertXor(T(words:[ 3, 2, 1, 0] as X), T(words:[ 1, 1, 1, 1] as X), T(words:[ 2, 3, 0, 1] as X)) } } diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Multiplication.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Multiplication.swift index ae93678d..c03ef702 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Multiplication.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Multiplication.swift @@ -11,9 +11,9 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] +private typealias X = [UInt] +private typealias X64 = [UInt64] +private typealias X32 = [UInt32] //*============================================================================* // MARK: * NBK x Flexible Width x Multiplication x UIntXL @@ -29,15 +29,15 @@ final class NBKFlexibleWidthTestsOnMultiplicationAsUIntXL: XCTestCase { //=------------------------------------------------------------------------= func testMultiplying() { - NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as W), T(words:[2, 0, 0, 0] as W), T(words:[ 2, 4, 6, 8, 0, 0, 0, 0] as W)) - NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as W), T(words:[0, 2, 0, 0] as W), T(words:[ 0, 2, 4, 6, 8, 0, 0, 0] as W)) - NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as W), T(words:[0, 0, 2, 0] as W), T(words:[ 0, 0, 2, 4, 6, 8, 0, 0] as W)) - NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as W), T(words:[0, 0, 0, 2] as W), T(words:[ 0, 0, 0, 2, 4, 6, 8, 0] as W)) + NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as X), T(words:[2, 0, 0, 0] as X), T(words:[ 2, 4, 6, 8, 0, 0, 0, 0] as X)) + NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as X), T(words:[0, 2, 0, 0] as X), T(words:[ 0, 2, 4, 6, 8, 0, 0, 0] as X)) + NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as X), T(words:[0, 0, 2, 0] as X), T(words:[ 0, 0, 2, 4, 6, 8, 0, 0] as X)) + NBKAssertMultiplication(T(words:[ 1, 2, 3, 4] as X), T(words:[0, 0, 0, 2] as X), T(words:[ 0, 0, 0, 2, 4, 6, 8, 0] as X)) - NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as W), T(words:[2, 0, 0, 0] as W), T(words:[~3, ~4, ~6, ~8, 1, 0, 0, 0] as W)) - NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as W), T(words:[0, 2, 0, 0] as W), T(words:[ 0, ~3, ~4, ~6, ~8, 1, 0, 0] as W)) - NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as W), T(words:[0, 0, 2, 0] as W), T(words:[ 0, 0, ~3, ~4, ~6, ~8, 1, 0] as W)) - NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as W), T(words:[0, 0, 0, 2] as W), T(words:[ 0, 0, 0, ~3, ~4, ~6, ~8, 1] as W)) + NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as X), T(words:[2, 0, 0, 0] as X), T(words:[~3, ~4, ~6, ~8, 1, 0, 0, 0] as X)) + NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as X), T(words:[0, 2, 0, 0] as X), T(words:[ 0, ~3, ~4, ~6, ~8, 1, 0, 0] as X)) + NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as X), T(words:[0, 0, 2, 0] as X), T(words:[ 0, 0, ~3, ~4, ~6, ~8, 1, 0] as X)) + NBKAssertMultiplication(T(words:[~1, ~2, ~3, ~4] as X), T(words:[0, 0, 0, 2] as X), T(words:[ 0, 0, 0, ~3, ~4, ~6, ~8, 1] as X)) } //=------------------------------------------------------------------------= @@ -45,13 +45,13 @@ final class NBKFlexibleWidthTestsOnMultiplicationAsUIntXL: XCTestCase { //=------------------------------------------------------------------------= func testMultiplyingByDigit() { - NBKAssertMultiplicationByDigit(T(words:[1, 2, 3, 4] as W), UInt(0), T(words:[ 0, 0, 0, 0, 0] as W)) - NBKAssertMultiplicationByDigit(T(words:[1, 2, 3, 4] as W), UInt(1), T(words:[ 1, 2, 3, 4, 0] as W)) - NBKAssertMultiplicationByDigit(T(words:[1, 2, 3, 4] as W), UInt(2), T(words:[ 2, 4, 6, 8, 0] as W)) + NBKAssertMultiplicationByDigit(T(words:[1, 2, 3, 4] as X), UInt(0), T(words:[ 0, 0, 0, 0, 0] as X)) + NBKAssertMultiplicationByDigit(T(words:[1, 2, 3, 4] as X), UInt(1), T(words:[ 1, 2, 3, 4, 0] as X)) + NBKAssertMultiplicationByDigit(T(words:[1, 2, 3, 4] as X), UInt(2), T(words:[ 2, 4, 6, 8, 0] as X)) - NBKAssertMultiplicationByDigit(T(words:[1, 2, 3, 4] as W), ~UInt(0), ~T(words:[ 0, 1, 1, 1, ~3] as W)) - NBKAssertMultiplicationByDigit(T(words:[1, 2, 3, 4] as W), ~UInt(1), ~T(words:[ 1, 3, 4, 5, ~3] as W)) - NBKAssertMultiplicationByDigit(T(words:[1, 2, 3, 4] as W), ~UInt(2), ~T(words:[ 2, 5, 7, 9, ~3] as W)) + NBKAssertMultiplicationByDigit(T(words:[1, 2, 3, 4] as X), ~UInt(0), ~T(words:[ 0, 1, 1, 1, ~3] as X)) + NBKAssertMultiplicationByDigit(T(words:[1, 2, 3, 4] as X), ~UInt(1), ~T(words:[ 1, 3, 4, 5, ~3] as X)) + NBKAssertMultiplicationByDigit(T(words:[1, 2, 3, 4] as X), ~UInt(2), ~T(words:[ 2, 5, 7, 9, ~3] as X)) } //=------------------------------------------------------------------------= @@ -59,10 +59,10 @@ final class NBKFlexibleWidthTestsOnMultiplicationAsUIntXL: XCTestCase { //=------------------------------------------------------------------------= func testMultiplyingByDigitWithAddition() { - NBKAssertMultiplicationByDigitWithAddition(T(words:[~0, ~0, ~0, ~0] as W), 0, 0, T(words:[ 0, 0, 0, 0, 0] as W)) - NBKAssertMultiplicationByDigitWithAddition(T(words:[~0, ~0, ~0, ~0] as W), 0, ~0, T(words:[~0, 0, 0, 0, 0] as W)) - NBKAssertMultiplicationByDigitWithAddition(T(words:[~0, ~0, ~0, ~0] as W), ~0, 0, T(words:[ 1, ~0, ~0, ~0, ~1] as W)) - NBKAssertMultiplicationByDigitWithAddition(T(words:[~0, ~0, ~0, ~0] as W), ~0, ~0, T(words:[ 0, 0, 0, 0, ~0] as W)) + NBKAssertMultiplicationByDigitWithAddition(T(words:[~0, ~0, ~0, ~0] as X), 0, 0, T(words:[ 0, 0, 0, 0, 0] as X)) + NBKAssertMultiplicationByDigitWithAddition(T(words:[~0, ~0, ~0, ~0] as X), 0, ~0, T(words:[~0, 0, 0, 0, 0] as X)) + NBKAssertMultiplicationByDigitWithAddition(T(words:[~0, ~0, ~0, ~0] as X), ~0, 0, T(words:[ 1, ~0, ~0, ~0, ~1] as X)) + NBKAssertMultiplicationByDigitWithAddition(T(words:[~0, ~0, ~0, ~0] as X), ~0, ~0, T(words:[ 0, 0, 0, 0, ~0] as X)) } //=------------------------------------------------------------------------= @@ -70,10 +70,10 @@ final class NBKFlexibleWidthTestsOnMultiplicationAsUIntXL: XCTestCase { //=------------------------------------------------------------------------= func testMultiplyingBySquaring() { - NBKAssertMultiplicationBySquaring(T(words:[ 0, 0, 0, 0] as W), T(words:[ 0, 0, 0, 0, 0, 0, 0, 0] as W)) - NBKAssertMultiplicationBySquaring(T(words:[ 1, 2, 3, 4] as W), T(words:[ 1, 4, 10, 20, 25, 24, 16, 0] as W)) - NBKAssertMultiplicationBySquaring(T(words:[~1, ~2, ~3, ~4] as W), T(words:[ 4, 8, 16, 28, 21, 20, 10, ~7] as W)) - NBKAssertMultiplicationBySquaring(T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 1, 0, 0, 0, ~1, ~0, ~0, ~0] as W)) + NBKAssertMultiplicationBySquaring(T(words:[ 0, 0, 0, 0] as X), T(words:[ 0, 0, 0, 0, 0, 0, 0, 0] as X)) + NBKAssertMultiplicationBySquaring(T(words:[ 1, 2, 3, 4] as X), T(words:[ 1, 4, 10, 20, 25, 24, 16, 0] as X)) + NBKAssertMultiplicationBySquaring(T(words:[~1, ~2, ~3, ~4] as X), T(words:[ 4, 8, 16, 28, 21, 20, 10, ~7] as X)) + NBKAssertMultiplicationBySquaring(T(words:[~0, ~0, ~0, ~0] as X), T(words:[ 1, 0, 0, 0, ~1, ~0, ~0, ~0] as X)) } //=------------------------------------------------------------------------= diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Numbers.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Numbers.swift index 13555a95..e7c20195 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Numbers.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Numbers.swift @@ -11,9 +11,9 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] +private typealias X = [UInt] +private typealias X64 = [UInt64] +private typealias X32 = [UInt32] //*============================================================================* // MARK: * NBK x Flexible Width x Numbers x UIntXL @@ -65,10 +65,10 @@ final class NBKFlexibleWidthTestsOnNumbersAsUIntXL: XCTestCase { //=------------------------------------------------------------------------= func testToInt() { - NBKAssertNumbers(from: T(words:[ 1, 0, 0, 0] as W), default: Int( 1)) - NBKAssertNumbers(from: T(words:[~0, 0, 0, 0] as W), exactly: nil, clamping: Int.max, truncating: -1) - NBKAssertNumbers(from: T(words:[ 1, 1, 1, 1] as W), exactly: nil, clamping: Int.max, truncating: 1) - NBKAssertNumbers(from: T(words:[~0, ~0, ~0, ~0] as W), exactly: nil, clamping: Int.max, truncating: -1) + NBKAssertNumbers(from: T(words:[ 1, 0, 0, 0] as X), default: Int( 1)) + NBKAssertNumbers(from: T(words:[~0, 0, 0, 0] as X), exactly: nil, clamping: Int.max, truncating: -1) + NBKAssertNumbers(from: T(words:[ 1, 1, 1, 1] as X), exactly: nil, clamping: Int.max, truncating: 1) + NBKAssertNumbers(from: T(words:[~0, ~0, ~0, ~0] as X), exactly: nil, clamping: Int.max, truncating: -1) } func testFromInt() { @@ -81,10 +81,10 @@ final class NBKFlexibleWidthTestsOnNumbersAsUIntXL: XCTestCase { //=------------------------------------------------------------------------= func testToInt32() { - NBKAssertNumbers(from: T(x32:[ 1, 0, 0, 0] as Y), default: Int32( 1)) - NBKAssertNumbers(from: T(x32:[~0, 0, 0, 0] as Y), exactly: nil, clamping: Int32.max, truncating: -1) - NBKAssertNumbers(from: T(x32:[ 1, 1, 1, 1] as Y), exactly: nil, clamping: Int32.max, truncating: 1) - NBKAssertNumbers(from: T(x32:[~0, ~0, ~0, ~0] as Y), exactly: nil, clamping: Int32.max, truncating: -1) + NBKAssertNumbers(from: T(x32:[ 1, 0, 0, 0] as X32), default: Int32( 1)) + NBKAssertNumbers(from: T(x32:[~0, 0, 0, 0] as X32), exactly: nil, clamping: Int32.max, truncating: -1) + NBKAssertNumbers(from: T(x32:[ 1, 1, 1, 1] as X32), exactly: nil, clamping: Int32.max, truncating: 1) + NBKAssertNumbers(from: T(x32:[~0, ~0, ~0, ~0] as X32), exactly: nil, clamping: Int32.max, truncating: -1) } func testFromInt32() { @@ -97,10 +97,10 @@ final class NBKFlexibleWidthTestsOnNumbersAsUIntXL: XCTestCase { //=------------------------------------------------------------------------= func testToInt64() { - NBKAssertNumbers(from: T(x64:[ 1, 0, 0, 0] as X), default: Int64( 1)) - NBKAssertNumbers(from: T(x64:[~0, 0, 0, 0] as X), exactly: nil, clamping: Int64.max, truncating: -1) - NBKAssertNumbers(from: T(x64:[ 1, 1, 1, 1] as X), exactly: nil, clamping: Int64.max, truncating: 1) - NBKAssertNumbers(from: T(x64:[~0, ~0, ~0, ~0] as X), exactly: nil, clamping: Int64.max, truncating: -1) + NBKAssertNumbers(from: T(x64:[ 1, 0, 0, 0] as X64), default: Int64( 1)) + NBKAssertNumbers(from: T(x64:[~0, 0, 0, 0] as X64), exactly: nil, clamping: Int64.max, truncating: -1) + NBKAssertNumbers(from: T(x64:[ 1, 1, 1, 1] as X64), exactly: nil, clamping: Int64.max, truncating: 1) + NBKAssertNumbers(from: T(x64:[~0, ~0, ~0, ~0] as X64), exactly: nil, clamping: Int64.max, truncating: -1) } func testFromInt64() { @@ -113,10 +113,10 @@ final class NBKFlexibleWidthTestsOnNumbersAsUIntXL: XCTestCase { //=------------------------------------------------------------------------= func testToUInt() { - NBKAssertNumbers(from: T(words:[ 1, 0, 0, 0] as W), default: UInt( 1)) - NBKAssertNumbers(from: T(words:[~0, 0, 0, 0] as W), default: ~UInt( 0)) - NBKAssertNumbers(from: T(words:[ 1, 1, 1, 1] as W), exactly: nil, clamping: UInt.max, truncating: 1) - NBKAssertNumbers(from: T(words:[~0, ~0, ~0, ~0] as W), exactly: nil, clamping: UInt.max, truncating: ~0) + NBKAssertNumbers(from: T(words:[ 1, 0, 0, 0] as X), default: UInt( 1)) + NBKAssertNumbers(from: T(words:[~0, 0, 0, 0] as X), default: ~UInt( 0)) + NBKAssertNumbers(from: T(words:[ 1, 1, 1, 1] as X), exactly: nil, clamping: UInt.max, truncating: 1) + NBKAssertNumbers(from: T(words:[~0, ~0, ~0, ~0] as X), exactly: nil, clamping: UInt.max, truncating: ~0) } func testFromUInt() { @@ -125,8 +125,8 @@ final class NBKFlexibleWidthTestsOnNumbersAsUIntXL: XCTestCase { } func testFromUIntAsDigit() { - NBKAssertNumbers(from: T(digit: UInt.min), default: T(words:[ 0, 0, 0, 0] as W)) - NBKAssertNumbers(from: T(digit: UInt.max), default: T(words:[~0, 0, 0, 0] as W)) + NBKAssertNumbers(from: T(digit: UInt.min), default: T(words:[ 0, 0, 0, 0] as X)) + NBKAssertNumbers(from: T(digit: UInt.max), default: T(words:[~0, 0, 0, 0] as X)) } //=------------------------------------------------------------------------= @@ -134,10 +134,10 @@ final class NBKFlexibleWidthTestsOnNumbersAsUIntXL: XCTestCase { //=------------------------------------------------------------------------= func testToUInt32() { - NBKAssertNumbers(from: T(x32:[ 1, 0, 0, 0] as Y), default: UInt32( 1)) - NBKAssertNumbers(from: T(x32:[~0, 0, 0, 0] as Y), default: ~UInt32( 0)) - NBKAssertNumbers(from: T(x32:[ 1, 1, 1, 1] as Y), exactly: nil, clamping: UInt32.max, truncating: 1) - NBKAssertNumbers(from: T(x32:[~0, ~0, ~0, ~0] as Y), exactly: nil, clamping: UInt32.max, truncating: ~0) + NBKAssertNumbers(from: T(x32:[ 1, 0, 0, 0] as X32), default: UInt32( 1)) + NBKAssertNumbers(from: T(x32:[~0, 0, 0, 0] as X32), default: ~UInt32( 0)) + NBKAssertNumbers(from: T(x32:[ 1, 1, 1, 1] as X32), exactly: nil, clamping: UInt32.max, truncating: 1) + NBKAssertNumbers(from: T(x32:[~0, ~0, ~0, ~0] as X32), exactly: nil, clamping: UInt32.max, truncating: ~0) } func testFromUInt32() { @@ -150,10 +150,10 @@ final class NBKFlexibleWidthTestsOnNumbersAsUIntXL: XCTestCase { //=------------------------------------------------------------------------= func testToUInt64() { - NBKAssertNumbers(from: T(x64:[ 1, 0, 0, 0] as X), default: UInt64( 1)) - NBKAssertNumbers(from: T(x64:[~0, 0, 0, 0] as X), default: ~UInt64( 0)) - NBKAssertNumbers(from: T(x64:[ 1, 1, 1, 1] as X), exactly: nil, clamping: UInt64.max, truncating: 1) - NBKAssertNumbers(from: T(x64:[~0, ~0, ~0, ~0] as X), exactly: nil, clamping: UInt64.max, truncating: ~0) + NBKAssertNumbers(from: T(x64:[ 1, 0, 0, 0] as X64), default: UInt64( 1)) + NBKAssertNumbers(from: T(x64:[~0, 0, 0, 0] as X64), default: ~UInt64( 0)) + NBKAssertNumbers(from: T(x64:[ 1, 1, 1, 1] as X64), exactly: nil, clamping: UInt64.max, truncating: 1) + NBKAssertNumbers(from: T(x64:[~0, ~0, ~0, ~0] as X64), exactly: nil, clamping: UInt64.max, truncating: ~0) } func testFromUInt64() { @@ -166,17 +166,17 @@ final class NBKFlexibleWidthTestsOnNumbersAsUIntXL: XCTestCase { //=------------------------------------------------------------------------= func testToMagnitude() { - NBKAssertNumbers(from: T(words:[ 1, 0, 0, 0] as W), default: M(words:[ 1, 0, 0, 0] as W)) - NBKAssertNumbers(from: T(words:[~0, 0, 0, 0] as W), default: M(words:[~0, 0, 0, 0] as W)) - NBKAssertNumbers(from: T(words:[ 1, 1, 1, 1] as W), default: M(words:[ 1, 1, 1, 1] as W)) - NBKAssertNumbers(from: T(words:[~0, ~0, ~0, ~0] as W), default: M(words:[~0, ~0, ~0, ~0] as W)) + NBKAssertNumbers(from: T(words:[ 1, 0, 0, 0] as X), default: M(words:[ 1, 0, 0, 0] as X)) + NBKAssertNumbers(from: T(words:[~0, 0, 0, 0] as X), default: M(words:[~0, 0, 0, 0] as X)) + NBKAssertNumbers(from: T(words:[ 1, 1, 1, 1] as X), default: M(words:[ 1, 1, 1, 1] as X)) + NBKAssertNumbers(from: T(words:[~0, ~0, ~0, ~0] as X), default: M(words:[~0, ~0, ~0, ~0] as X)) } func testFromMagnitude() { - NBKAssertNumbers(from: M(words:[ 1, 0, 0, 0] as W), default: T(words:[ 1, 0, 0, 0] as W)) - NBKAssertNumbers(from: M(words:[~0, 0, 0, 0] as W), default: T(words:[~0, 0, 0, 0] as W)) - NBKAssertNumbers(from: M(words:[ 1, 1, 1, 1] as W), default: T(words:[ 1, 1, 1, 1] as W)) - NBKAssertNumbers(from: M(words:[~0, ~0, ~0, ~0] as W), default: T(words:[~0, ~0, ~0, ~0] as W)) + NBKAssertNumbers(from: M(words:[ 1, 0, 0, 0] as X), default: T(words:[ 1, 0, 0, 0] as X)) + NBKAssertNumbers(from: M(words:[~0, 0, 0, 0] as X), default: T(words:[~0, 0, 0, 0] as X)) + NBKAssertNumbers(from: M(words:[ 1, 1, 1, 1] as X), default: T(words:[ 1, 1, 1, 1] as X)) + NBKAssertNumbers(from: M(words:[~0, ~0, ~0, ~0] as X), default: T(words:[~0, ~0, ~0, ~0] as X)) } //=------------------------------------------------------------------------= @@ -199,9 +199,9 @@ final class NBKFlexibleWidthTestsOnNumbersAsUIntXL: XCTestCase { XCTAssertEqual(T(exactly: -22.5), nil) XCTAssertEqual(T(exactly: pow(2, Float32(64 * 0 - 1))), nil) - XCTAssertEqual(T(exactly: pow(2, Float32(64 * 0 - 0))), T(x64:[1, 0, 0, 0] as X)) - XCTAssertEqual(T(exactly: pow(2, Float32(64 * 1 - 1))), T(x64:[1 << 63, 0, 0, 0] as X)) - XCTAssertEqual(T(exactly: pow(2, Float32(64 * 2 - 1))), T(x64:[0, 1 << 63, 0, 0] as X)) + XCTAssertEqual(T(exactly: pow(2, Float32(64 * 0 - 0))), T(x64:[1, 0, 0, 0] as X64)) + XCTAssertEqual(T(exactly: pow(2, Float32(64 * 1 - 1))), T(x64:[1 << 63, 0, 0, 0] as X64)) + XCTAssertEqual(T(exactly: pow(2, Float32(64 * 2 - 1))), T(x64:[0, 1 << 63, 0, 0] as X64)) XCTAssertEqual(T(exactly: pow(2, Float32(64 * 2 - 0))), nil) } @@ -233,11 +233,11 @@ final class NBKFlexibleWidthTestsOnNumbersAsUIntXL: XCTestCase { XCTAssertEqual(T(exactly: -22.5), nil) XCTAssertEqual(T(exactly: pow(2, Float64(64 * 0 - 1))), nil) - XCTAssertEqual(T(exactly: pow(2, Float64(64 * 0 - 0))), T(x64:[1, 0, 0, 0] as X)) - XCTAssertEqual(T(exactly: pow(2, Float64(64 * 1 - 1))), T(x64:[1 << 63, 0, 0, 0] as X)) - XCTAssertEqual(T(exactly: pow(2, Float64(64 * 2 - 1))), T(x64:[0, 1 << 63, 0, 0] as X)) - XCTAssertEqual(T(exactly: pow(2, Float64(64 * 3 - 1))), T(x64:[0, 0, 1 << 63, 0] as X)) - XCTAssertEqual(T(exactly: pow(2, Float64(64 * 4 - 1))), T(x64:[0, 0, 0, 1 << 63] as X)) + XCTAssertEqual(T(exactly: pow(2, Float64(64 * 0 - 0))), T(x64:[1, 0, 0, 0] as X64)) + XCTAssertEqual(T(exactly: pow(2, Float64(64 * 1 - 1))), T(x64:[1 << 63, 0, 0, 0] as X64)) + XCTAssertEqual(T(exactly: pow(2, Float64(64 * 2 - 1))), T(x64:[0, 1 << 63, 0, 0] as X64)) + XCTAssertEqual(T(exactly: pow(2, Float64(64 * 3 - 1))), T(x64:[0, 0, 1 << 63, 0] as X64)) + XCTAssertEqual(T(exactly: pow(2, Float64(64 * 4 - 1))), T(x64:[0, 0, 0, 1 << 63] as X64)) } func testFromFloat64ValuesThatAreSpecial() { diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Shifts.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Shifts.swift index e0488342..253495b6 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Shifts.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Shifts.swift @@ -11,9 +11,9 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] +private typealias X = [UInt] +private typealias X64 = [UInt64] +private typealias X32 = [UInt32] //*============================================================================* // MARK: * NBK x Flexible Width x Shifts x UIntXL @@ -28,33 +28,33 @@ final class NBKFlexibleWidthTestsOnShiftsAsUIntXL: XCTestCase { //=------------------------------------------------------------------------= func testBitShiftingLeftByBits() { - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 0, T(x64:[ 1, 2, 3, 4] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 1, T(x64:[ 2, 4, 6, 8] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 2, T(x64:[ 4, 8, 12, 16] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 3, T(x64:[ 8, 16, 24, 32] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X64), 0, T(x64:[ 1, 2, 3, 4] as X64)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X64), 1, T(x64:[ 2, 4, 6, 8] as X64)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X64), 2, T(x64:[ 4, 8, 12, 16] as X64)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X64), 3, T(x64:[ 8, 16, 24, 32] as X64)) } func testBitShiftingLeftByWords() { - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 0, T(x64:[ 1, 2, 3, 4, 0, 0, 0, 0] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 64, T(x64:[ 0, 1, 2, 3, 4, 0, 0, 0] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 128, T(x64:[ 0, 0, 1, 2, 3, 4, 0, 0] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 192, T(x64:[ 0, 0, 0, 1, 2, 3, 4, 0] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 256, T(x64:[ 0, 0, 0, 0, 1, 2, 3, 4] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X64), 0, T(x64:[ 1, 2, 3, 4, 0, 0, 0, 0] as X64)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X64), 64, T(x64:[ 0, 1, 2, 3, 4, 0, 0, 0] as X64)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X64), 128, T(x64:[ 0, 0, 1, 2, 3, 4, 0, 0] as X64)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X64), 192, T(x64:[ 0, 0, 0, 1, 2, 3, 4, 0] as X64)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X64), 256, T(x64:[ 0, 0, 0, 0, 1, 2, 3, 4] as X64)) } func testBitShiftingLeftByWordsAndBits() { - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 3, T(x64:[ 8, 16, 24, 32, 0, 0, 0, 0] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 67, T(x64:[ 0, 8, 16, 24, 32, 0, 0, 0] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 131, T(x64:[ 0, 0, 8, 16, 24, 32, 0, 0] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 195, T(x64:[ 0, 0, 0, 8, 16, 24, 32, 0] as X)) - NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X), 259, T(x64:[ 0, 0, 0, 0, 8, 16, 24, 32] as X)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X64), 3, T(x64:[ 8, 16, 24, 32, 0, 0, 0, 0] as X64)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X64), 67, T(x64:[ 0, 8, 16, 24, 32, 0, 0, 0] as X64)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X64), 131, T(x64:[ 0, 0, 8, 16, 24, 32, 0, 0] as X64)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X64), 195, T(x64:[ 0, 0, 0, 8, 16, 24, 32, 0] as X64)) + NBKAssertShiftLeft(T(x64:[ 1, 2, 3, 4] as X64), 259, T(x64:[ 0, 0, 0, 0, 8, 16, 24, 32] as X64)) } func testBitShiftingLeftSuchThatWordsSplit() { - NBKAssertShiftLeft(T(x64:[~0, 0, 0, 0] as X), 1, T(x64:[~1, 1, 0, 0, 0] as X)) - NBKAssertShiftLeft(T(x64:[ 0, ~0, 0, 0] as X), 1, T(x64:[ 0, ~1, 1, 0, 0] as X)) - NBKAssertShiftLeft(T(x64:[ 0, 0, ~0, 0] as X), 1, T(x64:[ 0, 0, ~1, 1, 0] as X)) - NBKAssertShiftLeft(T(x64:[ 0, 0, 0, ~0] as X), 1, T(x64:[ 0, 0, 0, ~1, 1] as X)) + NBKAssertShiftLeft(T(x64:[~0, 0, 0, 0] as X64), 1, T(x64:[~1, 1, 0, 0, 0] as X64)) + NBKAssertShiftLeft(T(x64:[ 0, ~0, 0, 0] as X64), 1, T(x64:[ 0, ~1, 1, 0, 0] as X64)) + NBKAssertShiftLeft(T(x64:[ 0, 0, ~0, 0] as X64), 1, T(x64:[ 0, 0, ~1, 1, 0] as X64)) + NBKAssertShiftLeft(T(x64:[ 0, 0, 0, ~0] as X64), 1, T(x64:[ 0, 0, 0, ~1, 1] as X64)) } //=------------------------------------------------------------------------= @@ -62,41 +62,41 @@ final class NBKFlexibleWidthTestsOnShiftsAsUIntXL: XCTestCase { //=------------------------------------------------------------------------= func testBitShiftingRightByBits() { - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 0, T(x64:[ 8, 16, 24, 32] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 1, T(x64:[ 4, 8, 12, 16] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 2, T(x64:[ 2, 4, 6, 8] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 3, T(x64:[ 1, 2, 3, 4] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X64), 0, T(x64:[ 8, 16, 24, 32] as X64)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X64), 1, T(x64:[ 4, 8, 12, 16] as X64)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X64), 2, T(x64:[ 2, 4, 6, 8] as X64)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X64), 3, T(x64:[ 1, 2, 3, 4] as X64)) } func testBitShiftingRightByWords() { - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 0, T(x64:[ 8, 16, 24, 32] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 64, T(x64:[16, 24, 32, 0] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 128, T(x64:[24, 32, 0, 0] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 192, T(x64:[32, 0, 0, 0] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 256, T(x64:[ 0, 0, 0, 0] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X64), 0, T(x64:[ 8, 16, 24, 32] as X64)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X64), 64, T(x64:[16, 24, 32, 0] as X64)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X64), 128, T(x64:[24, 32, 0, 0] as X64)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X64), 192, T(x64:[32, 0, 0, 0] as X64)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X64), 256, T(x64:[ 0, 0, 0, 0] as X64)) } func testBitShiftingRightByWordsAndBits() { - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 3, T(x64:[ 1, 2, 3, 4] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 67, T(x64:[ 2, 3, 4, 0] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 131, T(x64:[ 3, 4, 0, 0] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 195, T(x64:[ 4, 0, 0, 0] as X)) - NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X), 259, T(x64:[ 0, 0, 0, 0] as X)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X64), 3, T(x64:[ 1, 2, 3, 4] as X64)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X64), 67, T(x64:[ 2, 3, 4, 0] as X64)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X64), 131, T(x64:[ 3, 4, 0, 0] as X64)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X64), 195, T(x64:[ 4, 0, 0, 0] as X64)) + NBKAssertShiftRight(T(x64:[8, 16, 24, 32] as X64), 259, T(x64:[ 0, 0, 0, 0] as X64)) } func testBitShiftingRightSuchThatWordsSplit() { - NBKAssertShiftRight(T(x64:[0, 0, 0, 7] as X), 1, T(x64:[ 0, 0, 1 << 63, 3] as X)) - NBKAssertShiftRight(T(x64:[0, 0, 7, 0] as X), 1, T(x64:[ 0, 1 << 63, 3, 0] as X)) - NBKAssertShiftRight(T(x64:[0, 7, 0, 0] as X), 1, T(x64:[ 1 << 63, 3, 0, 0] as X)) - NBKAssertShiftRight(T(x64:[7, 0, 0, 0] as X), 1, T(x64:[ 3, 0, 0, 0] as X)) + NBKAssertShiftRight(T(x64:[0, 0, 0, 7] as X64), 1, T(x64:[ 0, 0, 1 << 63, 3] as X64)) + NBKAssertShiftRight(T(x64:[0, 0, 7, 0] as X64), 1, T(x64:[ 0, 1 << 63, 3, 0] as X64)) + NBKAssertShiftRight(T(x64:[0, 7, 0, 0] as X64), 1, T(x64:[ 1 << 63, 3, 0, 0] as X64)) + NBKAssertShiftRight(T(x64:[7, 0, 0, 0] as X64), 1, T(x64:[ 3, 0, 0, 0] as X64)) } func testBitShiftingRightIsUnsigned() { - NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X), 0, T(x64:[0, 0, 0, 1 << 63] as X)) - NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X), 64, T(x64:[0, 0, 1 << 63, 0] as X)) - NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X), 128, T(x64:[0, 1 << 63, 0, 0] as X)) - NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X), 192, T(x64:[1 << 63, 0, 0, 0] as X)) - NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X), 256, T(x64:[0, 0, 0, 0] as X)) + NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X64), 0, T(x64:[0, 0, 0, 1 << 63] as X64)) + NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X64), 64, T(x64:[0, 0, 1 << 63, 0] as X64)) + NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X64), 128, T(x64:[0, 1 << 63, 0, 0] as X64)) + NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X64), 192, T(x64:[1 << 63, 0, 0, 0] as X64)) + NBKAssertShiftRight(T(x64:[0, 0, 0, 1 << 63] as X64), 256, T(x64:[0, 0, 0, 0] as X64)) } //=------------------------------------------------------------------------= @@ -104,37 +104,37 @@ final class NBKFlexibleWidthTestsOnShiftsAsUIntXL: XCTestCase { //=------------------------------------------------------------------------= func testBitShiftingIsSmart() { - XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) << 1, T(x64:[2, 4, 6, 8, 0] as X)) - XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) >> -1, T(x64:[2, 4, 6, 8, 0] as X)) + XCTAssertEqual(T(x64:[1, 2, 3, 4] as X64) << 1, T(x64:[2, 4, 6, 8, 0] as X64)) + XCTAssertEqual(T(x64:[1, 2, 3, 4] as X64) >> -1, T(x64:[2, 4, 6, 8, 0] as X64)) - XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) << 64, T(x64:[0, 1, 2, 3, 4] as X)) - XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) >> -64, T(x64:[0, 1, 2, 3, 4] as X)) + XCTAssertEqual(T(x64:[1, 2, 3, 4] as X64) << 64, T(x64:[0, 1, 2, 3, 4] as X64)) + XCTAssertEqual(T(x64:[1, 2, 3, 4] as X64) >> -64, T(x64:[0, 1, 2, 3, 4] as X64)) } func testBitShiftingLeftByMoreThanBitWidthDoesNotTrap() { - NBKAssertShiftLeft (T(x64:[1] as X), (UInt.bitWidth + 1), T(x64:[0, 2] as X)) - NBKAssertShiftRight(T(x64:[1] as X), -(UInt.bitWidth + 1), T(x64:[0, 2] as X)) + NBKAssertShiftLeft (T(x64:[1] as X64), (UInt.bitWidth + 1), T(x64:[0, 2] as X64)) + NBKAssertShiftRight(T(x64:[1] as X64), -(UInt.bitWidth + 1), T(x64:[0, 2] as X64)) } func testBitShiftingRightDoesNotTrap() { - XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) >> Int.max, T.zero) - XCTAssertEqual(T(x64:[1, 2, 3, 4] as X) << Int.min, T.zero) + XCTAssertEqual(T(x64:[1, 2, 3, 4] as X64) >> Int.max, T.zero) + XCTAssertEqual(T(x64:[1, 2, 3, 4] as X64) << Int.min, T.zero) } func testBitShiftingZeroDoesNotTrap() { - XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) << Int.min, T.zero) - XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) << Int.max, T.zero) + XCTAssertEqual(T(x64:[0, 0, 0, 0] as X64) << Int.min, T.zero) + XCTAssertEqual(T(x64:[0, 0, 0, 0] as X64) << Int.max, T.zero) - XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) >> Int.min, T.zero) - XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) >> Int.max, T.zero) + XCTAssertEqual(T(x64:[0, 0, 0, 0] as X64) >> Int.min, T.zero) + XCTAssertEqual(T(x64:[0, 0, 0, 0] as X64) >> Int.max, T.zero) } func testBitShiftingZeroDoesNotDoAnything() { - XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) << (UInt.bitWidth + 0), T.zero) - XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) << (UInt.bitWidth + 1), T.zero) + XCTAssertEqual(T(x64:[0, 0, 0, 0] as X64) << (UInt.bitWidth + 0), T.zero) + XCTAssertEqual(T(x64:[0, 0, 0, 0] as X64) << (UInt.bitWidth + 1), T.zero) - XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) >> (UInt.bitWidth + 0), T.zero) - XCTAssertEqual(T(x64:[0, 0, 0, 0] as X) >> (UInt.bitWidth + 1), T.zero) + XCTAssertEqual(T(x64:[0, 0, 0, 0] as X64) >> (UInt.bitWidth + 0), T.zero) + XCTAssertEqual(T(x64:[0, 0, 0, 0] as X64) >> (UInt.bitWidth + 1), T.zero) } } diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Subtraction.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Subtraction.swift index 2cfe9d98..8fecfcf3 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Subtraction.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Subtraction.swift @@ -11,9 +11,9 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] +private typealias X = [UInt] +private typealias X64 = [UInt64] +private typealias X32 = [UInt32] //*============================================================================* // MARK: * NBK x Flexible Width x Subtraction x UIntXL @@ -35,28 +35,28 @@ final class NBKFlexibleWidthTestsOnSubtractionAsUIntXL: XCTestCase { } func testSubtractingReportingOverflow() { - NBKAssertSubtraction(T(1), T(0), Int(0), T(words:[ 1] as W)) - NBKAssertSubtraction(T(1), T(1), Int(0), T(words:[ 0] as W)) - NBKAssertSubtraction(T(1), T(2), Int(0), T(words:[~0] as W), true) - NBKAssertSubtraction(T(1), T(3), Int(0), T(words:[~1] as W), true) + NBKAssertSubtraction(T(1), T(0), Int(0), T(words:[ 1] as X)) + NBKAssertSubtraction(T(1), T(1), Int(0), T(words:[ 0] as X)) + NBKAssertSubtraction(T(1), T(2), Int(0), T(words:[~0] as X), true) + NBKAssertSubtraction(T(1), T(3), Int(0), T(words:[~1] as X), true) } func testSubtractingAtIndex() { - NBKAssertSubtraction(T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[~1, ~2, ~3, ~0] as W)) - NBKAssertSubtraction(T(words:[ 0, ~0, ~0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[~0, ~3, ~3, ~0] as W)) - NBKAssertSubtraction(T(words:[ 0, 0, ~0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[~0, ~2, ~4, ~0] as W)) - NBKAssertSubtraction(T(words:[ 0, 0, 0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(0), T(words:[~0, ~2, ~3, ~1] as W)) + NBKAssertSubtraction(T(words:[~0, ~0, ~0, ~0] as X), T(words:[ 1, 2, 3, 0] as X), Int(0), T(words:[~1, ~2, ~3, ~0] as X)) + NBKAssertSubtraction(T(words:[ 0, ~0, ~0, ~0] as X), T(words:[ 1, 2, 3, 0] as X), Int(0), T(words:[~0, ~3, ~3, ~0] as X)) + NBKAssertSubtraction(T(words:[ 0, 0, ~0, ~0] as X), T(words:[ 1, 2, 3, 0] as X), Int(0), T(words:[~0, ~2, ~4, ~0] as X)) + NBKAssertSubtraction(T(words:[ 0, 0, 0, ~0] as X), T(words:[ 1, 2, 3, 0] as X), Int(0), T(words:[~0, ~2, ~3, ~1] as X)) - NBKAssertSubtraction(T(words:[~0, ~0, ~0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[~0, ~1, ~2, ~3] as W)) - NBKAssertSubtraction(T(words:[ 0, ~0, ~0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[ 0, ~1, ~2, ~3] as W)) - NBKAssertSubtraction(T(words:[ 0, 0, ~0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[ 0, ~0, ~3, ~3] as W)) - NBKAssertSubtraction(T(words:[ 0, 0, 0, ~0] as W), T(words:[ 1, 2, 3, 0] as W), Int(1), T(words:[ 0, ~0, ~2, ~4] as W)) + NBKAssertSubtraction(T(words:[~0, ~0, ~0, ~0] as X), T(words:[ 1, 2, 3, 0] as X), Int(1), T(words:[~0, ~1, ~2, ~3] as X)) + NBKAssertSubtraction(T(words:[ 0, ~0, ~0, ~0] as X), T(words:[ 1, 2, 3, 0] as X), Int(1), T(words:[ 0, ~1, ~2, ~3] as X)) + NBKAssertSubtraction(T(words:[ 0, 0, ~0, ~0] as X), T(words:[ 1, 2, 3, 0] as X), Int(1), T(words:[ 0, ~0, ~3, ~3] as X)) + NBKAssertSubtraction(T(words:[ 0, 0, 0, ~0] as X), T(words:[ 1, 2, 3, 0] as X), Int(1), T(words:[ 0, ~0, ~2, ~4] as X)) } func testSubtractingAtIndexReportingOverflow() { - NBKAssertSubtraction(T(words:[ 1, 2, 3, 0] as W), T(words:[ 4, 5, 0, 0] as W), Int(0), T(words:[~2, ~3, 2, 0] as W)) - NBKAssertSubtraction(T(words:[ 1, 2, 3, 0] as W), T(words:[ 4, 5, 0, 0] as W), Int(1), T(words:[ 1, ~1, ~2, 0] as W), true) - NBKAssertSubtraction(T(words:[ 1, 2, 3, 0] as W), T(words:[ 4, 5, 0, 0] as W), Int(2), T(words:[ 1, 2, ~0, ~5] as W), true) + NBKAssertSubtraction(T(words:[ 1, 2, 3, 0] as X), T(words:[ 4, 5, 0, 0] as X), Int(0), T(words:[~2, ~3, 2, 0] as X)) + NBKAssertSubtraction(T(words:[ 1, 2, 3, 0] as X), T(words:[ 4, 5, 0, 0] as X), Int(1), T(words:[ 1, ~1, ~2, 0] as X), true) + NBKAssertSubtraction(T(words:[ 1, 2, 3, 0] as X), T(words:[ 4, 5, 0, 0] as X), Int(2), T(words:[ 1, 2, ~0, ~5] as X), true) } //=------------------------------------------------------------------------= @@ -71,29 +71,29 @@ final class NBKFlexibleWidthTestsOnSubtractionAsUIntXL: XCTestCase { } func testSubtractingDigitReportingOverflow() { - NBKAssertSubtractionByDigit(T(1), UInt(0), Int(0), T(words:[ 1] as W)) - NBKAssertSubtractionByDigit(T(1), UInt(1), Int(0), T(words:[ 0] as W)) - NBKAssertSubtractionByDigit(T(1), UInt(2), Int(0), T(words:[~0] as W), true) - NBKAssertSubtractionByDigit(T(1), UInt(3), Int(0), T(words:[~1] as W), true) + NBKAssertSubtractionByDigit(T(1), UInt(0), Int(0), T(words:[ 1] as X)) + NBKAssertSubtractionByDigit(T(1), UInt(1), Int(0), T(words:[ 0] as X)) + NBKAssertSubtractionByDigit(T(1), UInt(2), Int(0), T(words:[~0] as X), true) + NBKAssertSubtractionByDigit(T(1), UInt(3), Int(0), T(words:[~1] as X), true) } func testSubtractingDigitAtIndex() { - NBKAssertSubtractionByDigit(T(words:[~0, ~0, ~0, ~0] as W), UInt(3), Int(0), T(words:[~3, ~0, ~0, ~0] as W)) - NBKAssertSubtractionByDigit(T(words:[ 0, ~0, ~0, ~0] as W), UInt(3), Int(0), T(words:[~2, ~1, ~0, ~0] as W)) - NBKAssertSubtractionByDigit(T(words:[ 0, 0, ~0, ~0] as W), UInt(3), Int(0), T(words:[~2, ~0, ~1, ~0] as W)) - NBKAssertSubtractionByDigit(T(words:[ 0, 0, 0, ~0] as W), UInt(3), Int(0), T(words:[~2, ~0, ~0, ~1] as W)) + NBKAssertSubtractionByDigit(T(words:[~0, ~0, ~0, ~0] as X), UInt(3), Int(0), T(words:[~3, ~0, ~0, ~0] as X)) + NBKAssertSubtractionByDigit(T(words:[ 0, ~0, ~0, ~0] as X), UInt(3), Int(0), T(words:[~2, ~1, ~0, ~0] as X)) + NBKAssertSubtractionByDigit(T(words:[ 0, 0, ~0, ~0] as X), UInt(3), Int(0), T(words:[~2, ~0, ~1, ~0] as X)) + NBKAssertSubtractionByDigit(T(words:[ 0, 0, 0, ~0] as X), UInt(3), Int(0), T(words:[~2, ~0, ~0, ~1] as X)) - NBKAssertSubtractionByDigit(T(words:[~0, ~0, ~0, ~0] as W), UInt(3), Int(1), T(words:[~0, ~3, ~0, ~0] as W)) - NBKAssertSubtractionByDigit(T(words:[ 0, ~0, ~0, ~0] as W), UInt(3), Int(1), T(words:[ 0, ~3, ~0, ~0] as W)) - NBKAssertSubtractionByDigit(T(words:[ 0, 0, ~0, ~0] as W), UInt(3), Int(1), T(words:[ 0, ~2, ~1, ~0] as W)) - NBKAssertSubtractionByDigit(T(words:[ 0, 0, 0, ~0] as W), UInt(3), Int(1), T(words:[ 0, ~2, ~0, ~1] as W)) + NBKAssertSubtractionByDigit(T(words:[~0, ~0, ~0, ~0] as X), UInt(3), Int(1), T(words:[~0, ~3, ~0, ~0] as X)) + NBKAssertSubtractionByDigit(T(words:[ 0, ~0, ~0, ~0] as X), UInt(3), Int(1), T(words:[ 0, ~3, ~0, ~0] as X)) + NBKAssertSubtractionByDigit(T(words:[ 0, 0, ~0, ~0] as X), UInt(3), Int(1), T(words:[ 0, ~2, ~1, ~0] as X)) + NBKAssertSubtractionByDigit(T(words:[ 0, 0, 0, ~0] as X), UInt(3), Int(1), T(words:[ 0, ~2, ~0, ~1] as X)) } func testSubtractingDigitAtIndexReportingOverflow() { - NBKAssertSubtractionByDigit(T(words:[ 1, 2, 3, 0] as W), UInt(5), Int(0), T(words:[~3, 1, 3, 0] as W)) - NBKAssertSubtractionByDigit(T(words:[ 1, 2, 3, 0] as W), UInt(5), Int(1), T(words:[ 1, ~2, 2, 0] as W)) - NBKAssertSubtractionByDigit(T(words:[ 1, 2, 3, 0] as W), UInt(5), Int(2), T(words:[ 1, 2, ~1, 0] as W), true) - NBKAssertSubtractionByDigit(T(words:[ 1, 2, 3, 0] as W), UInt(5), Int(3), T(words:[ 1, 2, 3, ~4] as W), true) + NBKAssertSubtractionByDigit(T(words:[ 1, 2, 3, 0] as X), UInt(5), Int(0), T(words:[~3, 1, 3, 0] as X)) + NBKAssertSubtractionByDigit(T(words:[ 1, 2, 3, 0] as X), UInt(5), Int(1), T(words:[ 1, ~2, 2, 0] as X)) + NBKAssertSubtractionByDigit(T(words:[ 1, 2, 3, 0] as X), UInt(5), Int(2), T(words:[ 1, 2, ~1, 0] as X), true) + NBKAssertSubtractionByDigit(T(words:[ 1, 2, 3, 0] as X), UInt(5), Int(3), T(words:[ 1, 2, 3, ~4] as X), true) } //=------------------------------------------------------------------------= diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Text.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Text.swift index 7050d74c..5e208c91 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Text.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Text.swift @@ -11,9 +11,9 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] +private typealias X = [UInt] +private typealias X64 = [UInt64] +private typealias X32 = [UInt32] //*============================================================================* // MARK: * NBK x Flexible Width x Text x UIntXL diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Update.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Update.swift index fb929040..16f30c4c 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Update.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Update.swift @@ -11,9 +11,9 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] +private typealias X = [UInt] +private typealias X64 = [UInt64] +private typealias X32 = [UInt32] //*============================================================================* // MARK: * NBK x Flexible Width x Update x UIntXL @@ -29,10 +29,10 @@ final class NBKFlexibleWidthTestsOnUpdateAsUIntXL: XCTestCase { //=------------------------------------------------------------------------= func testUpdate() { - NBKAssertUpdate(T(words:[ 0, 0, 0, 0 ] as W)) - NBKAssertUpdate(T(words:[~0, ~0, ~0, ~0/2 + 0] as W)) - NBKAssertUpdate(T(words:[ 0, 0, 0, ~0/2 + 1] as W)) - NBKAssertUpdate(T(words:[~0, ~0, ~0, ~0 ] as W)) + NBKAssertUpdate(T(words:[ 0, 0, 0, 0 ] as X)) + NBKAssertUpdate(T(words:[~0, ~0, ~0, ~0/2 + 0] as X)) + NBKAssertUpdate(T(words:[ 0, 0, 0, ~0/2 + 1] as X)) + NBKAssertUpdate(T(words:[~0, ~0, ~0, ~0 ] as X)) } func testUpdateAsDigit() { @@ -48,12 +48,12 @@ final class NBKFlexibleWidthTestsOnUpdateAsUIntXL: XCTestCase { //*============================================================================* private func NBKAssertUpdate(_ value: T, file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual({ var x = T(words:[0, 0, 0, 0] as W); x.update(value); return x }(), value, file: file, line: line) - XCTAssertEqual({ var x = T(words:[1, 2, 3, 4] as W); x.update(value); return x }(), value, file: file, line: line) + XCTAssertEqual({ var x = T(words:[0, 0, 0, 0] as X); x.update(value); return x }(), value, file: file, line: line) + XCTAssertEqual({ var x = T(words:[1, 2, 3, 4] as X); x.update(value); return x }(), value, file: file, line: line) } private func NBKAssertUpdateAsDigit(_ type: T.Type, _ value: T.Digit, file: StaticString = #file, line: UInt = #line) { NBKAssertUpdate(T(digit: value), file: file, line: line) - XCTAssertEqual({ var x = T(words:[0, 0, 0, 0] as W); x.update(value); return x }(), T(digit: value), file: file, line: line) - XCTAssertEqual({ var x = T(words:[1, 2, 3, 4] as W); x.update(value); return x }(), T(digit: value), file: file, line: line) + XCTAssertEqual({ var x = T(words:[0, 0, 0, 0] as X); x.update(value); return x }(), T(digit: value), file: file, line: line) + XCTAssertEqual({ var x = T(words:[1, 2, 3, 4] as X); x.update(value); return x }(), T(digit: value), file: file, line: line) } diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Words.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Words.swift index f65add2a..f01315bd 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Words.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Words.swift @@ -11,9 +11,9 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] +private typealias X = [UInt] +private typealias X64 = [UInt64] +private typealias X32 = [UInt32] //*============================================================================* // MARK: * NBK x Flexible Width x Words x UIntXL @@ -83,46 +83,46 @@ final class NBKFlexibleWidthTestsOnWordsAsUIntXL: XCTestCase { func testToWordsX64() throws { guard MemoryLayout.size == MemoryLayout.size else { throw XCTSkip() } - NBKAssertToWords(T(x64:[0 ] as X), [0 ]) - NBKAssertToWords(T(x64:[1 ] as X), [1 ]) - NBKAssertToWords(T(x64:[1, 2 ] as X), [1, 2 ]) - NBKAssertToWords(T(x64:[1, 2, 3 ] as X), [1, 2, 3 ]) - NBKAssertToWords(T(x64:[1, 2, 3, 4] as X), [1, 2, 3, 4]) + NBKAssertToWords(T(x64:[0 ] as X64), [0 ]) + NBKAssertToWords(T(x64:[1 ] as X64), [1 ]) + NBKAssertToWords(T(x64:[1, 2 ] as X64), [1, 2 ]) + NBKAssertToWords(T(x64:[1, 2, 3 ] as X64), [1, 2, 3 ]) + NBKAssertToWords(T(x64:[1, 2, 3, 4] as X64), [1, 2, 3, 4]) - NBKAssertToWords(T(x64:[0, 0, 0, 0] as X), [0 ]) - NBKAssertToWords(T(x64:[1, 0, 0, 0] as X), [1 ]) - NBKAssertToWords(T(x64:[1, 2, 0, 0] as X), [1, 2 ]) - NBKAssertToWords(T(x64:[1, 2, 3, 0] as X), [1, 2, 3 ]) - NBKAssertToWords(T(x64:[1, 2, 3, 4] as X), [1, 2, 3, 4]) + NBKAssertToWords(T(x64:[0, 0, 0, 0] as X64), [0 ]) + NBKAssertToWords(T(x64:[1, 0, 0, 0] as X64), [1 ]) + NBKAssertToWords(T(x64:[1, 2, 0, 0] as X64), [1, 2 ]) + NBKAssertToWords(T(x64:[1, 2, 3, 0] as X64), [1, 2, 3 ]) + NBKAssertToWords(T(x64:[1, 2, 3, 4] as X64), [1, 2, 3, 4]) - NBKAssertToWords(T(x64:[~0, ~0, ~0, ~0/2] as X), [~0, ~0, ~0, ~0/2 + 0 ] as W) // Int256.max - NBKAssertToWords(T(x64:[~0, ~0, ~0, ~0/2] as X) + 1, [ 0, 0, 0, ~0/2 + 1 ] as W) // Int256.max + 1 - NBKAssertToWords(T(x64:[~0, ~0, ~0, ~0/1] as X), [~0, ~0, ~0, ~0/1 + 0 ] as W) // UInt256.max - NBKAssertToWords(T(x64:[~0, ~0, ~0, ~0/1] as X) + 1, [ 0, 0, 0, 0/1 + 0, 1] as W) // UInt256.max + 1 + NBKAssertToWords(T(x64:[~0, ~0, ~0, ~0/2] as X64), [~0, ~0, ~0, ~0/2 + 0 ] as X) // Int256.max + NBKAssertToWords(T(x64:[~0, ~0, ~0, ~0/2] as X64) + 1, [ 0, 0, 0, ~0/2 + 1 ] as X) // Int256.max + 1 + NBKAssertToWords(T(x64:[~0, ~0, ~0, ~0/1] as X64), [~0, ~0, ~0, ~0/1 + 0 ] as X) // UInt256.max + NBKAssertToWords(T(x64:[~0, ~0, ~0, ~0/1] as X64) + 1, [ 0, 0, 0, 0/1 + 0, 1] as X) // UInt256.max + 1 } func testToWordsX32() throws { guard MemoryLayout.size == MemoryLayout.size else { throw XCTSkip() } - NBKAssertToWords(T(x32:[0 ] as Y), [0 ]) - NBKAssertToWords(T(x32:[1 ] as Y), [1 ]) - NBKAssertToWords(T(x32:[1, 2 ] as Y), [1, 2 ]) - NBKAssertToWords(T(x32:[1, 2, 3 ] as Y), [1, 2, 3 ]) - NBKAssertToWords(T(x32:[1, 2, 3, 4 ] as Y), [1, 2, 3, 4 ]) - NBKAssertToWords(T(x32:[1, 2, 3, 4, 5 ] as Y), [1, 2, 3, 4, 5 ]) - NBKAssertToWords(T(x32:[1, 2, 3, 4, 5, 6 ] as Y), [1, 2, 3, 4, 5, 6 ]) - NBKAssertToWords(T(x32:[1, 2, 3, 4, 5, 6, 7 ] as Y), [1, 2, 3, 4, 5, 6, 7 ]) - NBKAssertToWords(T(x32:[1, 2, 3, 4, 5, 6, 7, 8] as Y), [1, 2, 3, 4, 5, 6, 7, 8]) + NBKAssertToWords(T(x32:[0 ] as X32), [0 ]) + NBKAssertToWords(T(x32:[1 ] as X32), [1 ]) + NBKAssertToWords(T(x32:[1, 2 ] as X32), [1, 2 ]) + NBKAssertToWords(T(x32:[1, 2, 3 ] as X32), [1, 2, 3 ]) + NBKAssertToWords(T(x32:[1, 2, 3, 4 ] as X32), [1, 2, 3, 4 ]) + NBKAssertToWords(T(x32:[1, 2, 3, 4, 5 ] as X32), [1, 2, 3, 4, 5 ]) + NBKAssertToWords(T(x32:[1, 2, 3, 4, 5, 6 ] as X32), [1, 2, 3, 4, 5, 6 ]) + NBKAssertToWords(T(x32:[1, 2, 3, 4, 5, 6, 7 ] as X32), [1, 2, 3, 4, 5, 6, 7 ]) + NBKAssertToWords(T(x32:[1, 2, 3, 4, 5, 6, 7, 8] as X32), [1, 2, 3, 4, 5, 6, 7, 8]) - NBKAssertToWords(T(x32:[0, 0, 0, 0, 0, 0, 0, 0] as Y), [0 ]) - NBKAssertToWords(T(x32:[1, 0, 0, 0, 0, 0, 0, 0] as Y), [1 ]) - NBKAssertToWords(T(x32:[1, 2, 0, 0, 0, 0, 0, 0] as Y), [1, 2 ]) - NBKAssertToWords(T(x32:[1, 2, 3, 0, 0, 0, 0, 0] as Y), [1, 2, 3 ]) - NBKAssertToWords(T(x32:[1, 2, 3, 4, 0, 0, 0, 0] as Y), [1, 2, 3, 4 ]) - NBKAssertToWords(T(x32:[1, 2, 3, 4, 5, 0, 0, 0] as Y), [1, 2, 3, 4, 5 ]) - NBKAssertToWords(T(x32:[1, 2, 3, 4, 5, 6, 0, 0] as Y), [1, 2, 3, 4, 5, 6 ]) - NBKAssertToWords(T(x32:[1, 2, 3, 4, 5, 6, 7, 0] as Y), [1, 2, 3, 4, 5, 6, 7 ]) - NBKAssertToWords(T(x32:[1, 2, 3, 4, 5, 6, 7, 8] as Y), [1, 2, 3, 4, 5, 6, 7, 8]) + NBKAssertToWords(T(x32:[0, 0, 0, 0, 0, 0, 0, 0] as X32), [0 ]) + NBKAssertToWords(T(x32:[1, 0, 0, 0, 0, 0, 0, 0] as X32), [1 ]) + NBKAssertToWords(T(x32:[1, 2, 0, 0, 0, 0, 0, 0] as X32), [1, 2 ]) + NBKAssertToWords(T(x32:[1, 2, 3, 0, 0, 0, 0, 0] as X32), [1, 2, 3 ]) + NBKAssertToWords(T(x32:[1, 2, 3, 4, 0, 0, 0, 0] as X32), [1, 2, 3, 4 ]) + NBKAssertToWords(T(x32:[1, 2, 3, 4, 5, 0, 0, 0] as X32), [1, 2, 3, 4, 5 ]) + NBKAssertToWords(T(x32:[1, 2, 3, 4, 5, 6, 0, 0] as X32), [1, 2, 3, 4, 5, 6 ]) + NBKAssertToWords(T(x32:[1, 2, 3, 4, 5, 6, 7, 0] as X32), [1, 2, 3, 4, 5, 6, 7 ]) + NBKAssertToWords(T(x32:[1, 2, 3, 4, 5, 6, 7, 8] as X32), [1, 2, 3, 4, 5, 6, 7, 8]) } //=------------------------------------------------------------------------= @@ -130,12 +130,12 @@ final class NBKFlexibleWidthTestsOnWordsAsUIntXL: XCTestCase { //=------------------------------------------------------------------------= func testSubscriptSignExtension() { - XCTAssertEqual(T(words:[1, 2, 3, 4] as W)[Int( 0)], 1 as UInt) - XCTAssertEqual(T(words:[1, 2, 3, 4] as W)[Int( 1)], 2 as UInt) - XCTAssertEqual(T(words:[1, 2, 3, 4] as W)[Int( 2)], 3 as UInt) - XCTAssertEqual(T(words:[1, 2, 3, 4] as W)[Int( 3)], 4 as UInt) - XCTAssertEqual(T(words:[1, 2, 3, 4] as W)[Int( 4)], 0 as UInt) - XCTAssertEqual(T(words:[1, 2, 3, 4] as W)[Int.max], 0 as UInt) + XCTAssertEqual(T(words:[1, 2, 3, 4] as X)[Int( 0)], 1 as UInt) + XCTAssertEqual(T(words:[1, 2, 3, 4] as X)[Int( 1)], 2 as UInt) + XCTAssertEqual(T(words:[1, 2, 3, 4] as X)[Int( 2)], 3 as UInt) + XCTAssertEqual(T(words:[1, 2, 3, 4] as X)[Int( 3)], 4 as UInt) + XCTAssertEqual(T(words:[1, 2, 3, 4] as X)[Int( 4)], 0 as UInt) + XCTAssertEqual(T(words:[1, 2, 3, 4] as X)[Int.max], 0 as UInt) } } diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth.swift index dde99dfc..67f47d67 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth.swift @@ -11,9 +11,9 @@ import NBKCoreKit import NBKFlexibleWidthKit import XCTest -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] +private typealias X = [UInt] +private typealias X64 = [UInt64] +private typealias X32 = [UInt32] //*============================================================================* // MARK: * NBK x Flexible Width x UIntXL @@ -25,15 +25,15 @@ extension NBKFlexibleWidth.Magnitude { // MARK: Constants //=------------------------------------------------------------------------= - static let min256 = Self(x64:[ 0, 0, 0, 0] as X) + static let min256 = Self(x64:[ 0, 0, 0, 0] as X64) - static let max256 = Self(x64:[~0, ~0, ~0, ~0] as X) + static let max256 = Self(x64:[~0, ~0, ~0, ~0] as X64) static let basket: [Self] = (-5 ... 5).lazy.map(UInt.init(bitPattern:)).flatMap({[ - Self(words:[$0 ] as W), - Self(words:[$0, $0 &+ 1 ] as W), - Self(words:[$0, $0 &+ 1, $0 &+ 2 ] as W), - Self(words:[$0, $0 &+ 1, $0 &+ 2, $0 &+ 3] as W), + Self(words:[$0 ] as X), + Self(words:[$0, $0 &+ 1 ] as X), + Self(words:[$0, $0 &+ 1, $0 &+ 2 ] as X), + Self(words:[$0, $0 &+ 1, $0 &+ 2, $0 &+ 3] as X), ]}) //=------------------------------------------------------------------------= From ec3da385405447d04f205cb5730f64eff0f84363 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sun, 10 Dec 2023 11:00:51 +0100 Subject: [PATCH 131/133] Cleanup. --- Sources/NBKCoreKit/Models/NBKPrimeSieve.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/NBKCoreKit/Models/NBKPrimeSieve.swift b/Sources/NBKCoreKit/Models/NBKPrimeSieve.swift index eb0d750d..28f16ac7 100644 --- a/Sources/NBKCoreKit/Models/NBKPrimeSieve.swift +++ b/Sources/NBKCoreKit/Models/NBKPrimeSieve.swift @@ -717,7 +717,7 @@ extension NBKPrimeSieve { /// 5) [6A, 6B, 2A, 6D, 6E, 2B] // 6B, 6E /// 6) [6A, 6B, 6C, 6D, 6E, 6F] // 6C, 6F /// - /// The idea is to reuse words and subsequences whenever possible. + /// The idea is to reuse elements and subsequences whenever possible. /// /// - Important: The sieve culls even numbers by omission, so start with `[3,5]`. /// @@ -736,7 +736,7 @@ extension NBKPrimeSieve { patternIndex.remainder &+= current.prime }; chunk.formOnesComplement() //=--------------------------= - // pattern: reuse words + // pattern: reuse elements //=--------------------------= var ((destination)) = patternIndex.quotient while destination < current.product { From da5b5f631383b7b6aaf5f4b5853d81a87676919c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sun, 10 Dec 2023 11:24:32 +0100 Subject: [PATCH 132/133] [NBKFlexibleWidthKit] Prepare for merge into main branch. --- .swiftpm/Numberick-Benchmarks.xctestplan | 15 -------- .swiftpm/Numberick.xctestplan | 12 ------- .../xcschemes/Numberick-Benchmarks.xcscheme | 6 ---- .../xcshareddata/xcschemes/Numberick.xcscheme | 17 --------- Package.swift | 2 +- README.md | 14 ++++---- .../Documentation.docc/Documentation.md | 35 +++++++++++++++++++ Sources/Numberick/Numberick.swift | 1 - 8 files changed, 44 insertions(+), 58 deletions(-) diff --git a/.swiftpm/Numberick-Benchmarks.xctestplan b/.swiftpm/Numberick-Benchmarks.xctestplan index 050e93e4..4c5f5d54 100644 --- a/.swiftpm/Numberick-Benchmarks.xctestplan +++ b/.swiftpm/Numberick-Benchmarks.xctestplan @@ -41,21 +41,6 @@ "identifier" : "NBKDoubleWidthKitBenchmarks", "name" : "NBKDoubleWidthKitBenchmarks" } - }, - { - "skippedTests" : [ - "NBKFibonacciXLBenchmarks\/testNoLoop10000000()", - "NBKFlexibleWidthBenchmarksOnExponentiationAsUIntXL\/test7RaisedToPrime777()", - "NBKFlexibleWidthBenchmarksOnExponentiationAsUIntXL\/testNoLoop5RaisedToPrime22222()", - "NBKFlexibleWidthBenchmarksOnExponentiationAsUIntXL\/testNoLoop5RaisedToPrime33333()", - "NBKFlexibleWidthBenchmarksOnExponentiationAsUIntXL\/testNoLoop5RaisedToPrime55555()", - "NBKFlexibleWidthBenchmarksOnExponentiationAsUIntXL\/testNoLoop7RaisedToPrime77777()" - ], - "target" : { - "containerPath" : "container:", - "identifier" : "NBKFlexibleWidthKitBenchmarks", - "name" : "NBKFlexibleWidthKitBenchmarks" - } } ], "version" : 1 diff --git a/.swiftpm/Numberick.xctestplan b/.swiftpm/Numberick.xctestplan index 74306fdc..ac666b5b 100644 --- a/.swiftpm/Numberick.xctestplan +++ b/.swiftpm/Numberick.xctestplan @@ -20,11 +20,6 @@ "containerPath" : "container:", "identifier" : "NBKDoubleWidthKit", "name" : "NBKDoubleWidthKit" - }, - { - "containerPath" : "container:", - "identifier" : "NBKFlexibleWidthKit", - "name" : "NBKFlexibleWidthKit" } ] } @@ -43,13 +38,6 @@ "identifier" : "NBKDoubleWidthKitTests", "name" : "NBKDoubleWidthKitTests" } - }, - { - "target" : { - "containerPath" : "container:", - "identifier" : "NBKFlexibleWidthKitTests", - "name" : "NBKFlexibleWidthKitTests" - } } ], "version" : 1 diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/Numberick-Benchmarks.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/Numberick-Benchmarks.xcscheme index 531d838b..d7d2f95c 100644 --- a/.swiftpm/xcode/xcshareddata/xcschemes/Numberick-Benchmarks.xcscheme +++ b/.swiftpm/xcode/xcshareddata/xcschemes/Numberick-Benchmarks.xcscheme @@ -75,12 +75,6 @@ - - - - - - - - - - [!IMPORTANT] +> It's a work in progress. I may rework it at any time. ### Models - [NBKFibonacciXL](Sources/NBKFlexibleWidthKit/Models/NBKFibonacciXL.swift) +- [UIntXL](Sources/NBKFlexibleWidthKit/Models/NBKFlexibleWidth.swift) ### Fibonacci -This sequence is instrumental for testing big integers, and it's fun. - ```swift NBKFibonacciXL(0) // (index: 0, element: 0, next: 1) NBKFibonacciXL(1) // (index: 1, element: 1, next: 1) @@ -141,6 +141,7 @@ It uses a fast double-and-add algorithm: ```swift NBKFibonacciXL(10_000_000) // 2.3s on M1 MacBook Pro +``` But you can also step through it manually: @@ -175,9 +176,10 @@ Add this package to your list of package dependencies. Choose target dependencies from the products in [Package.swift](Package.swift). ```swift -.product(name: "Numberick", package: "Numberick"), -.product(name: "NBKCoreKit", package: "Numberick"), -.product(name: "NBKDoubleWidthKit", package: "Numberick"), +.product(name: "Numberick", package: "Numberick"), +.product(name: "NBKCoreKit", package: "Numberick"), +.product(name: "NBKDoubleWidthKit", package: "Numberick"), +.product(name: "NBKFlexibleWidthKit", package: "Numberick"), ``` ### Using [CocoaPods](http://cocoapods.org) diff --git a/Sources/Numberick/Documentation.docc/Documentation.md b/Sources/Numberick/Documentation.docc/Documentation.md index 6d9b2618..46c64b13 100644 --- a/Sources/Numberick/Documentation.docc/Documentation.md +++ b/Sources/Numberick/Documentation.docc/Documentation.md @@ -96,6 +96,41 @@ Int256(5) % Int(5), UInt256(5) % UInt(5) - Note: You can use `StaticString` until `StaticBigInt` becomes available. +> [!IMPORTANT] +> It's a work in progress. I may rework it at any time. + +## NBKFlexibleWidthKit + +### Models + +- ``NBKFibonacciXL`` +- ``UIntXL`` + +### Fibonacci + +```swift +NBKFibonacciXL(0) // (index: 0, element: 0, next: 1) +NBKFibonacciXL(1) // (index: 1, element: 1, next: 1) +NBKFibonacciXL(2) // (index: 2, element: 1, next: 2) +NBKFibonacciXL(3) // (index: 3, element: 2, next: 3) +NBKFibonacciXL(4) // (index: 4, element: 3, next: 5) +NBKFibonacciXL(5) // (index: 5, element: 5, next: 8) +``` + +It uses a fast double-and-add algorithm: + +```swift +NBKFibonacciXL(10_000_000) // 2.3s on M1 MacBook Pro +``` + +But you can also step through it manually: + +```swift +public mutating func increment() { ... } // index + 1 +public mutating func decrement() { ... } // index - 1 +public mutating func double() { ... } // index * 2 +``` + ## Topics ### Protocols diff --git a/Sources/Numberick/Numberick.swift b/Sources/Numberick/Numberick.swift index 73e171b2..77d13b91 100644 --- a/Sources/Numberick/Numberick.swift +++ b/Sources/Numberick/Numberick.swift @@ -13,4 +13,3 @@ @_exported import NBKCoreKit @_exported import NBKDoubleWidthKit -@_exported import NBKFlexibleWidthKit From b4884ed0adf267e1f310672d0285c7a6d02fd2c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sun, 10 Dec 2023 12:38:27 +0100 Subject: [PATCH 133/133] Cleanup (#119). GitHub action failed because I used a tuple label introduced in Swift 5.8. --- Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Words.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Words.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Words.swift index f01315bd..f91e67a9 100644 --- a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Words.swift +++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Words.swift @@ -176,19 +176,19 @@ _ words: [UInt], _ count: Int, _ integer: T, file: StaticString = #file, line: UInt = #line) { //=------------------------------------------= if count == words.count { - let initialized = T.uninitialized(count: count, init:{ let _ = $0.initialize(from: words) }) + let initialized = T.uninitialized(count: count, init:{ _ = $0.initialize(from: words) }) XCTAssertEqual(initialized, integer, file: file, line: line) } brr: do { let capacity: Int = count - let initialized = T.uninitialized(capacity: capacity, init:{ $1 = $0.initialize(from: words.prefix(count)).index }) + let initialized = T.uninitialized(capacity: capacity, init:{ $1 = $0.initialize(from: words.prefix(count)).1 }) XCTAssertEqual(initialized, integer, file: file, line: line) } brr: do { let capacity: Int = count + 1 - let initialized = T.uninitialized(capacity: capacity, init:{ $1 = $0.initialize(from: words.prefix(count)).index }) + let initialized = T.uninitialized(capacity: capacity, init:{ $1 = $0.initialize(from: words.prefix(count)).1 }) XCTAssertEqual(initialized, integer, file: file, line: line) } }