diff --git a/.swiftpm/NBKFlexibleWidthKit-Benchmarks.xctestplan b/.swiftpm/NBKFlexibleWidthKit-Benchmarks.xctestplan
new file mode 100644
index 00000000..6e96461d
--- /dev/null
+++ b/.swiftpm/NBKFlexibleWidthKit-Benchmarks.xctestplan
@@ -0,0 +1,34 @@
+{
+ "configurations" : [
+ {
+ "id" : "2BBD9A51-D890-4B97-AED4-B9962867DF57",
+ "name" : "Main",
+ "options" : {
+
+ }
+ }
+ ],
+ "defaultOptions" : {
+ "codeCoverage" : false
+ },
+ "testTargets" : [
+ {
+ "skippedTests" : [
+ "NBKFibonacciXLBenchmarks\/testNoLoop10000000()",
+ "NBKFlexibleWidthBenchmarksOnExponentiationAsUIntXL\/test7RaisedToPrime777()",
+ "NBKFlexibleWidthBenchmarksOnExponentiationAsUIntXL\/testNoLoop5RaisedToPrime22222()",
+ "NBKFlexibleWidthBenchmarksOnExponentiationAsUIntXL\/testNoLoop5RaisedToPrime33333()",
+ "NBKFlexibleWidthBenchmarksOnExponentiationAsUIntXL\/testNoLoop5RaisedToPrime55555()",
+ "NBKFlexibleWidthBenchmarksOnExponentiationAsUIntXL\/testNoLoop7RaisedToPrime77777()",
+ "NBKFlexibleWidthBenchmarksOnTextAsUIntXL\/testEncodingUsingSwiftStdlibRadix10()",
+ "NBKFlexibleWidthBenchmarksOnTextAsUIntXL\/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/xcode/xcshareddata/xcschemes/NBKFlexibleWidthKit-Benchmarks.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/NBKFlexibleWidthKit-Benchmarks.xcscheme
new file mode 100644
index 00000000..c12d963f
--- /dev/null
+++ b/.swiftpm/xcode/xcshareddata/xcschemes/NBKFlexibleWidthKit-Benchmarks.xcscheme
@@ -0,0 +1,74 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
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/Package.swift b/Package.swift
index 7fcb06eb..7878ac37 100644
--- a/Package.swift
+++ b/Package.swift
@@ -48,6 +48,12 @@ let package = Package(
.library(
name: "NBKDoubleWidthKit",
targets: ["NBKDoubleWidthKit"]),
+ //=--------------------------------------=
+ // NBK x Flexible Width Kit
+ //=--------------------------------------=
+ .library(
+ name: "NBKFlexibleWidthKit",
+ targets: ["NBKFlexibleWidthKit"]),
],
targets: [
//=--------------------------------------=
@@ -84,6 +90,20 @@ let package = Package(
.testTarget(
name: "NBKDoubleWidthKitTests",
dependencies: ["NBKDoubleWidthKit"]),
+ //=--------------------------------------=
+ // NBK x Flexible Width Kit
+ //=--------------------------------------=
+ .target(
+ name: "NBKFlexibleWidthKit",
+ dependencies: ["NBKCoreKit"]),
+
+ .testTarget(
+ name: "NBKFlexibleWidthKitBenchmarks",
+ dependencies: ["NBKFlexibleWidthKit"]),
+
+ .testTarget(
+ name: "NBKFlexibleWidthKitTests",
+ dependencies: ["NBKFlexibleWidthKit"]),
]
)
diff --git a/README.md b/README.md
index 70d92b47..7a93f3ef 100644
--- a/README.md
+++ b/README.md
@@ -10,6 +10,7 @@
* [NBKCoreKit](#nbkcorekit)
* [NBKDoubleWidthKit](#nbkdoublewidthkit)
+* [NBKFlexibleWidthKit](#nbkflexiblewidthkit)
* [Installation](#installation)
* [Acknowledgements](#acknowledgements)
@@ -113,6 +114,43 @@ Int256(5) % Int(5), UInt256(5) % UInt(5)
> [!NOTE]
> You can use `StaticString` until `StaticBigInt` becomes available.
+
+
+## [NBKFlexibleWidthKit][FLX/D] ([Sources][FLX/S], [Tests][FLX/T], [Benchmarks][FLX/B])
+
+> [!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
+
+```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
+```
+
## Installation
@@ -138,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)
@@ -163,15 +202,20 @@ 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
[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/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 {
diff --git a/Sources/NBKFlexibleWidthKit/IntXLOrUIntXL.swift b/Sources/NBKFlexibleWidthKit/IntXLOrUIntXL.swift
new file mode 100644
index 00000000..ec467729
--- /dev/null
+++ b/Sources/NBKFlexibleWidthKit/IntXLOrUIntXL.swift
@@ -0,0 +1,250 @@
+//=----------------------------------------------------------------------------=
+// This source file is part of the Numberick open source project.
+//
+// Copyright (c) 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 Magnitude == UIntXL {
+
+ //=------------------------------------------------------------------------=
+ // 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 the given collection of `words` is empty.
+ ///
+ @inlinable init(words: some RandomAccessCollection)
+
+ //=------------------------------------------------------------------------=
+ // 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
+
+ //=------------------------------------------------------------------------=
+ // 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
+
+ //=------------------------------------------------------------------------=
+ // 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
+ //=------------------------------------------------------------------------=
+
+ /// 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
+ //=------------------------------------------------------------------------=
+
+ @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(major: Int, minor: Int)
+
+ @inlinable func bitShiftedLeft(major: Int, minor: Int) -> Self
+
+ @inlinable mutating func bitShiftLeft(major: Int)
+
+ @inlinable func bitShiftedLeft(major: 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(major: Int, minor: Int)
+
+ @inlinable func bitShiftedRight(major: Int, minor: Int) -> Self
+
+ @inlinable mutating func bitShiftRight(major: Int)
+
+ @inlinable func bitShiftedRight(major: Int) -> Self
+
+ //=------------------------------------------------------------------------=
+ // MARK: Details x Update
+ //=------------------------------------------------------------------------=
+
+ /// 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: 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)
+
+ //=------------------------------------------------------------------------=
+ // 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:)`.
+ ///
+ /// ### Semantics when there is no initialized prefix
+ ///
+ /// It returns zero when there is no initialized prefix 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.
+ ///
+ /// ### Semantics when there is no initialized prefix
+ ///
+ /// It returns zero when there is no initialized prefix 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/Models/NBKFibonacciXL.swift b/Sources/NBKFlexibleWidthKit/Models/NBKFibonacciXL.swift
new file mode 100644
index 00000000..09d31bd3
--- /dev/null
+++ b/Sources/NBKFlexibleWidthKit/Models/NBKFibonacciXL.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 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)
+/// ```
+///
+/// ### Fast 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
+/// f(x + 1 + 1) == f(x) * 0001 + f(x + 1) * 00000001
+/// 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 + 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: CustomStringConvertible {
+
+ //=------------------------------------------------------------------------=
+ // MARK: State
+ //=------------------------------------------------------------------------=
+
+ @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() { }
+
+ /// Creates the sequence pair at the given `index`.
+ @inlinable public init(_ index: UInt) {
+ 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 }
+ }
+
+ //=------------------------------------------------------------------------=
+ // 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
+ }
+
+ @inlinable public var description: String {
+ self.element.description
+ }
+
+ //=------------------------------------------------------------------------=
+ // 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() {
+ i -= 1
+ b -= a
+ Swift.swap(&a, &b)
+ }
+
+ /// Forms the sequence pair at `index * 2`.
+ @inlinable public mutating func double() {
+ var (x): UIntXL // f(2 * index + 0)
+ x = b.bitShiftedLeft(major: Int.zero, minor: Int.one)
+ x -= a
+ x *= a
+
+ var (y): UIntXL // f(2 * index + 1)
+ y = b.squared()
+ y += a.squared()
+
+ i *= 2
+ a = x
+ b = y
+ }
+}
diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift
new file mode 100644
index 00000000..e9f4ee16
--- /dev/null
+++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition+Digit.swift
@@ -0,0 +1,56 @@
+//=----------------------------------------------------------------------------=
+// This source file is part of the Numberick open source project.
+//
+// Copyright (c) 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: 0 as Int)
+ }
+
+ @_disfavoredOverload @inlinable public static func +(lhs: Self, rhs: UInt) -> Self {
+ lhs.adding(rhs, at: 0 as Int)
+ }
+
+ //=------------------------------------------------------------------------=
+ // MARK: Transformations x Index
+ //=------------------------------------------------------------------------=
+
+ @_disfavoredOverload @inlinable public mutating func add(_ other: UInt, at index: Int) {
+ //=--------------------------------------=
+ if other.isZero { return }
+ //=--------------------------------------=
+ self.storage.resize(minCount: index + 1)
+
+ 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 as Self
+ }
+}
diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Addition.swift
new file mode 100644
index 00000000..896f6620
--- /dev/null
+++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+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.
+//=----------------------------------------------------------------------------=
+
+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: 0 as Int)
+ }
+
+ @inlinable public static func +(lhs: Self, rhs: Self) -> Self {
+ lhs.adding(rhs, at: 0 as Int)
+ }
+
+ //=------------------------------------------------------------------------=
+ // MARK: Transformations x Index
+ //=------------------------------------------------------------------------=
+
+ @inlinable public mutating func add(_ other: Self, at index: Int) {
+ //=--------------------------------------=
+ if other.isZero { return }
+ //=--------------------------------------=
+ self.storage.resize(minCount: index + other.storage.elements.count)
+
+ let overflow = self.storage.withUnsafeMutableBufferPointer(in: index...) { slice in
+ other.storage.withUnsafeBufferPointer { other in
+ NBK.SUISS.increment(&slice, by: other).overflow
+ }
+ }
+
+ 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 as Self
+ }
+}
diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Bits.swift
new file mode 100644
index 00000000..3586afdc
--- /dev/null
+++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+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 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.elements.count * UInt.bitWidth
+ }
+
+ @inlinable public var nonzeroBitCount: Int {
+ self.withUnsafeBufferPointer(NBK.SBISS.nonzeroBitCount(of:))
+ }
+
+ @inlinable public var leadingZeroBitCount: Int {
+ self.withUnsafeBufferPointer(NBK.SBISS.leadingZeroBitCount(of:))
+ }
+
+ @inlinable public var trailingZeroBitCount: Int {
+ self.withUnsafeBufferPointer(NBK.SBISS.trailingZeroBitCount(of:))
+ }
+
+ @inlinable public var mostSignificantBit: Bool {
+ self.last.mostSignificantBit
+ }
+
+ @inlinable public var leastSignificantBit: Bool {
+ self.first.leastSignificantBit
+ }
+}
diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.swift
new file mode 100644
index 00000000..e7192a0f
--- /dev/null
+++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Comparisons.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 Comparisons x Unsigned
+//*============================================================================*
+
+extension NBKFlexibleWidth.Magnitude {
+
+ //=------------------------------------------------------------------------=
+ // MARK: Accessors
+ //=------------------------------------------------------------------------=
+
+ @inlinable public var isZero: Bool {
+ self.withUnsafeBufferPointer({ $0.count == 1 && $0.first!.isZero })
+ }
+
+ @inlinable public var isLessThanZero: Bool {
+ false
+ }
+
+ @inlinable public var isMoreThanZero: Bool {
+ !self.isZero
+ }
+
+ @inlinable public var isPowerOf2: Bool {
+ self.withUnsafeBufferPointer({ NBK.SBISS.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.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
+ NBK.SUISS.compare(lhs, to: rhs, at: index)
+ }
+ }
+ }
+
+ @_disfavoredOverload @inlinable public func compared(to other: Digit) -> Int {
+ self.storage.elements.withUnsafeBufferPointer { lhs in
+ 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
+ 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
new file mode 100644
index 00000000..05e4cb78
--- /dev/null
+++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Complements.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 Complements x Unsigned
+//*============================================================================*
+
+extension NBKFlexibleWidth.Magnitude {
+
+ //=------------------------------------------------------------------------=
+ // MARK: Details x One's Complement
+ //=------------------------------------------------------------------------=
+
+ @inlinable public mutating func formOnesComplement() {
+ self.withUnsafeMutableBufferPointer {
+ NBK.SBISS.formOnesComplement(&$0)
+ }
+ }
+
+ @inlinable public func onesComplement() -> Self {
+ Self(normalizing: Storage(unchecked: Elements(self.storage.elements.lazy.map(~))))
+ }
+
+ //=------------------------------------------------------------------------=
+ // MARK: Details x Two's Complement
+ //=------------------------------------------------------------------------=
+
+ @inlinable public mutating func formTwosComplementReportingOverflow() -> Bool {
+ self.withUnsafeMutableBufferPointer {
+ NBK.SUISS.formTwosComplementReportingOverflow(&$0)
+ }
+ }
+
+ @inlinable public func twosComplementReportingOverflow() -> PVO {
+ var partialValue = self
+ let overflow = partialValue.formTwosComplementReportingOverflow()
+ return PVO(partialValue, overflow)
+ }
+
+ @inlinable public mutating func formTwosComplementSubsequence(_ carry: Bool) -> Bool {
+ self.withUnsafeMutableBufferPointer {
+ NBK.SUISS.formTwosComplementSubsequence(&$0, carry: carry)
+ }
+ }
+
+ @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+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.swift
new file mode 100644
index 00000000..d418c52f
--- /dev/null
+++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division+Digit.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 Division x Digit x Unsigned
+//*============================================================================*
+
+extension NBKFlexibleWidth.Magnitude {
+
+ //=------------------------------------------------------------------------=
+ // MARK: Transformations x Overflow
+ //=------------------------------------------------------------------------=
+
+ @_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: + Algorithms
+//=----------------------------------------------------------------------------=
+
+extension NBKFlexibleWidth.Magnitude {
+
+ //=------------------------------------------------------------------------=
+ // MARK: Transformations x Overflow
+ //=------------------------------------------------------------------------=
+
+ @_disfavoredOverload @inlinable public mutating func formQuotientWithRemainderReportingOverflow(dividingBy other: Digit) -> PVO {
+ self.withUnsafeMutableBufferPointer {
+ NBK.SUISS.formQuotientWithRemainderReportingOverflow(dividing: &$0, by: other)
+ }
+ }
+}
diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.swift
new file mode 100644
index 00000000..3fa300cc
--- /dev/null
+++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Division.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 Division x Unsigned
+//*============================================================================*
+
+extension NBKFlexibleWidth.Magnitude {
+
+ //=------------------------------------------------------------------------=
+ // MARK: Transformations x Overflow
+ //=------------------------------------------------------------------------=
+
+ @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.quotientAndRemainderReportingOverflowUsingLongAlgorithm(dividingBy: other)
+ }
+}
+
+//=----------------------------------------------------------------------------=
+// MARK: + Long Division Algorithms
+//=----------------------------------------------------------------------------=
+
+extension NBKFlexibleWidth.Magnitude {
+
+ //=------------------------------------------------------------------------=
+ // MARK: Transformations x Overflow x Private
+ //=------------------------------------------------------------------------=
+
+ /// Performs long division after some fast-path checks.
+ @inlinable func quotientAndRemainderReportingOverflowUsingLongAlgorithm(dividingBy other: Self) -> PVO> {
+ var (remainder) = self
+ let (quotient, overflow) = remainder.formRemainderWithQuotientReportingOverflowUsingLongAlgorithm(dividingBy: other)
+ return PVO(QR(quotient, remainder), overflow)
+ }
+
+ /// Performs long division after some fast-path checks.
+ @inlinable mutating func formRemainderWithQuotientReportingOverflowUsingLongAlgorithm(dividingBy other: Self) -> PVO {
+ //=--------------------------------------=
+ // divisor is zero
+ //=--------------------------------------=
+ if other.isZero {
+ return PVO(self, true)
+ }
+ //=--------------------------------------=
+ // divisor is one word
+ //=--------------------------------------=
+ if other.count == Int.one {
+ let (q, r) = self.quotientAndRemainder(dividingBy: other.first)
+ self.update(r)
+ return PVO((q), false)
+ }
+ //=--------------------------------------=
+ // divisor is greater than or equal
+ //=--------------------------------------=
+ let comparison = other.compared(to: self)
+ if comparison.isLessThanZero {
+ } else if comparison.isZero {
+ self.update(UInt.zero)
+ return PVO(Self.one, false)
+ } else {
+ return PVO(Self.zero, false)
+ }
+ //=--------------------------------------=
+ // normalization
+ //=--------------------------------------=
+ self.storage.append(UInt.zero)
+
+ var other: Self = other
+ let shift: Int = other.last.leadingZeroBitCount
+
+ if !shift.isZero {
+ 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) })
+ }
+ //=--------------------------------------=
+ // division
+ //=--------------------------------------=
+ let quotient = Self.uninitialized(count: self.count - other.count) { quotient in
+ self .storage.withUnsafeMutableBufferPointer { dividend in
+ other.storage.withUnsafeBufferPointer/*---*/ { divisor in
+ NBK.SUI.initializeToQuotientFormRemainderByLongAlgorithm2111MSB("ient, dividing: ÷nd, by: divisor)
+ }}}
+ //=--------------------------------------=
+ // normalization
+ //=--------------------------------------=
+ if !shift.isZero {
+ self.storage.withUnsafeMutableBufferPointer({ NBK.SUI.bitShiftRight(&$0, major: 0 as Int, minorAtLeastOne: shift) })
+ }
+
+ self.storage.normalize()
+ Swift.assert(quotient.storage.isNormal)
+ //=--------------------------------------=
+ return PVO(partialValue: quotient, overflow: false)
+ }
+}
diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Exponentiation.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Exponentiation.swift
new file mode 100644
index 00000000..8646e5e2
--- /dev/null
+++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Exponentiation.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 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.
+ ///
+ @inlinable public func power(_ exponent: Int) -> Self {
+ //=--------------------------------------=
+ if exponent == 0 { return Self.one }
+ else if exponent == 1 { return self }
+ //=--------------------------------------=
+ Swift.assert(exponent > 001)
+ var power = Self(digit: 001)
+ var multiplier: Self = self
+ var pattern = UInt(exponent)
+ //=--------------------------------------=
+ repeat {
+
+ if pattern.isOdd {
+ power *= multiplier
+ }
+
+ pattern &>>= 000001
+ multiplier.square()
+
+ } while !pattern.isZero
+ //=--------------------------------------=
+ return power as Self as Self as Self as Self
+ }
+}
diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Literals.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Literals.swift
new file mode 100644
index 00000000..361a9d72
--- /dev/null
+++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Literals.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 Flexible Width x Literals x Unsigned
+//*============================================================================*
+
+extension NBKFlexibleWidth.Magnitude {
+
+ //=-------------------------------------------------------------------------=
+ // 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)")
+ }
+ }
+
+ /// - 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))
+ let major = NBK.PBI .quotient(dividing: NBK.ZeroOrMore(unchecked: width), by: NBK.PowerOf2(bitWidth: UInt.self))
+ let minor = NBK.PBI.remainder(dividing: NBK.ZeroOrMore(unchecked: width), by: NBK.PowerOf2(bitWidth: UInt.self))
+ 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.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 description: StaticString) {
+ if let value = Self(exactlyStringLiteral: description) { self = value } else {
+ preconditionFailure("\(Self.description) cannot represent \(description)")
+ }
+ }
+
+ /// - 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/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.swift
new file mode 100644
index 00000000..c32ef9eb
--- /dev/null
+++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Logic.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 Logic x Unsigned
+//*============================================================================*
+
+extension NBKFlexibleWidth.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.storage.downsizeThenFormInIntersection(with: rhs.storage, each: &)
+ lhs.storage.normalize()
+ }
+
+ @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.storage.upsizeThenFormInIntersection(with: rhs.storage, each: |)
+ Swift.assert(lhs.storage.isNormal)
+ }
+
+ @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.storage.upsizeThenFormInIntersection(with: rhs.storage, each: ^)
+ lhs.storage.normalize()
+ }
+
+ @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 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
new file mode 100644
index 00000000..8c937f0d
--- /dev/null
+++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication+Digit.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 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, add: 0 as UInt)
+ }
+
+ @_disfavoredOverload @inlinable public static func *(lhs: Self, rhs: UInt) -> Self {
+ lhs.multiplied(by: rhs, adding: 0 as UInt)
+ }
+
+ //=------------------------------------------------------------------------=
+ // MARK: Transformations x Addition
+ //=------------------------------------------------------------------------=
+
+ @_disfavoredOverload @inlinable public mutating func multiply(by multiplier: UInt, add addend: UInt) {
+ //=--------------------------------------=
+ 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: multiplier, add: addend)
+ }
+
+ if !carry.isZero {
+ self.storage.append(carry)
+ }
+
+ Swift.assert(self.storage.isNormal)
+ }
+
+ @_disfavoredOverload @inlinable public func multiplied(by multiplier: UInt, adding addend: UInt) -> Self {
+ var result = self
+ result.multiply(by: multiplier, add: addend)
+ return result as Self
+ }
+}
diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift
new file mode 100644
index 00000000..a93daac2
--- /dev/null
+++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Multiplication.swift
@@ -0,0 +1,52 @@
+//=----------------------------------------------------------------------------=
+// This source file is part of the Numberick open source project.
+//
+// Copyright (c) 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 = lhs * rhs
+ }
+
+ @inlinable public static func *(lhs: Self, rhs: Self) -> Self {
+ lhs.withUnsafeBufferPointer { lhs in
+ rhs.withUnsafeBufferPointer { rhs in
+ Self.uninitialized(count: lhs.count + rhs.count) {
+ NBK.SUISS.initialize(&$0, to: lhs, times: rhs)
+ }
+ }
+ }
+ }
+
+ //=------------------------------------------------------------------------=
+ // MARK: Transformations x Square
+ //=------------------------------------------------------------------------=
+
+ @inlinable public mutating func square() {
+ self = self.squared()
+ }
+
+ @inlinable public func squared() -> Self {
+ self.withUnsafeBufferPointer{ words in
+ Self.uninitialized(count: words.count * 2) {
+ NBK.SUISS.initialize(&$0, toSquareProductOf: words)
+ }
+ }
+ }
+}
+
diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.swift
new file mode 100644
index 00000000..bb703551
--- /dev/null
+++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Numbers.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 Numbers x Unsigned
+//*============================================================================*
+
+extension NBKFlexibleWidth.Magnitude {
+
+ //=------------------------------------------------------------------------=
+ // MARK: Constants
+ //=------------------------------------------------------------------------=
+
+ public static let zero = Self(digit: 0)
+
+ public static let one = Self(digit: 1)
+
+ //=------------------------------------------------------------------------=
+ // MARK: Initializers x Digit
+ //=------------------------------------------------------------------------=
+
+ @inlinable public init(digit: UInt) {
+ self.init(unchecked: Storage(unchecked: [digit]))
+ }
+
+ //=------------------------------------------------------------------------=
+ // 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) {
+ guard source.sign == FloatingPointSign.plus else { 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?(magnitude: Magnitude) {
+ self = magnitude
+ }
+
+ @inlinable public init?(sign: FloatingPointSign, magnitude: Magnitude) {
+ if sign == FloatingPointSign.plus || magnitude.isZero { self = magnitude } else { return nil }
+ }
+}
diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift
new file mode 100644
index 00000000..eb32772d
--- /dev/null
+++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Shifts.swift
@@ -0,0 +1,253 @@
+//=----------------------------------------------------------------------------=
+// This source file is part of the Numberick open source project.
+//
+// Copyright (c) 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: 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(@NBK.ZeroOrMore by distance: Int) {
+ let major = NBK.PBI .quotient(dividing: $distance, by: NBK.PowerOf2(bitWidth: UInt.self))
+ let minor = NBK.PBI.remainder(dividing: $distance, by: NBK.PowerOf2(bitWidth: UInt.self))
+ return self.bitShiftLeft(major: major, minor: minor)
+ }
+
+ @inlinable public func bitShiftedLeft(by distance: Int) -> Self {
+ var result = self; result.bitShiftLeft(by: distance); return result
+ }
+
+ @inlinable public mutating func bitShiftLeft(major: Int, minor: Int) {
+ //=--------------------------------------=
+ if minor.isZero {
+ return self.bitShiftLeft(major: major)
+ }
+ //=--------------------------------------=
+ self.bitShiftLeft(major: major, minorAtLeastOne: minor)
+ }
+
+ @inlinable public func bitShiftedLeft(major: Int, minor: Int) -> Self {
+ var result = self; result.bitShiftLeft(major: major, minor: minor); return result
+ }
+
+ @inlinable public mutating func bitShiftLeft(major: Int) {
+ //=--------------------------------------=
+ if major.isZero { return }
+ //=--------------------------------------=
+ self.bitShiftLeft(majorAtLeastOne: major)
+ }
+
+ @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
+ //=------------------------------------------------------------------------=
+
+ /// Performs a left shift.
+ ///
+ /// - Parameters:
+ /// - major: `0 <= major`
+ /// - minor: `1 <= minor < UInt.bitWidth`
+ ///
+ @inlinable mutating func bitShiftLeft(major: Int, minorAtLeastOne minor: Int) {
+ //=--------------------------------------=
+ if self.isZero { return }
+ //=--------------------------------------=
+ let rollover = Int(bit: self.leadingZeroBitCount < minor)
+ self.storage.resize(minCount: self.storage.elements.count + major + rollover)
+
+ self.storage.withUnsafeMutableBufferPointer {
+ NBK.SUI.bitShiftLeft(&$0, major: major, minorAtLeastOne: minor)
+ }
+
+ Swift.assert(self.storage.isNormal)
+ }
+
+ /// Performs a left shift.
+ ///
+ /// - Parameters:
+ /// - major: `1 <= major`
+ ///
+ @inlinable mutating func bitShiftLeft(majorAtLeastOne major: Int) {
+ //=--------------------------------------=
+ if self.isZero { return }
+ //=--------------------------------------=
+ self.storage.resize(minCount: self.storage.elements.count + major)
+
+ self.storage.withUnsafeMutableBufferPointer {
+ NBK.SUI.bitShiftLeft(&$0, majorAtLeastOne: major)
+ }
+
+ Swift.assert(self.storage.isNormal)
+ }
+}
+
+//=----------------------------------------------------------------------------=
+// MARK: + Right
+//=----------------------------------------------------------------------------=
+
+extension NBKFlexibleWidth.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
+ //=------------------------------------------------------------------------=
+
+ @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(@NBK.ZeroOrMore by distance: Int) {
+ let major = NBK.PBI .quotient(dividing: $distance, by: NBK.PowerOf2(bitWidth: UInt.self))
+ let minor = NBK.PBI.remainder(dividing: $distance, by: NBK.PowerOf2(bitWidth: UInt.self))
+ return self.bitShiftRight(major: major, minor: minor)
+ }
+
+ @inlinable public func bitShiftedRight(by distance: Int) -> Self {
+ var result = self; result.bitShiftRight(by: distance); return result
+ }
+
+ @inlinable public mutating func bitShiftRight(major: Int, minor: Int) {
+ //=--------------------------------------=
+ if minor.isZero {
+ return self.bitShiftRight(major: major)
+ }
+ //=--------------------------------------=
+ self.bitShiftRight(major: major, minorAtLeastOne: minor)
+ }
+
+ @inlinable public func bitShiftedRight(major: Int, minor: Int) -> Self {
+ var result = self; result.bitShiftRight(major: major, minor: minor); return result
+ }
+
+ @inlinable public mutating func bitShiftRight(major: Int) {
+ //=--------------------------------------=
+ if major.isZero { return }
+ //=--------------------------------------=
+ self.bitShiftRight(majorAtLeastOne: major)
+ }
+
+ @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
+ //=------------------------------------------------------------------------=
+
+ /// Performs an unsigned right shift.
+ ///
+ /// - Parameters:
+ /// - major: `1 <= major`
+ /// - minor: `0 <= minor < UInt.bitWidth`
+ ///
+ @inlinable mutating func bitShiftRight(major: Int, minorAtLeastOne minor: Int) {
+ //=--------------------------------------=
+ let rollover = Int(bit: 0 <= minor + self.leadingZeroBitCount - UInt.bitWidth)
+ let maxCount = self.storage.elements.count - major - rollover
+ //=--------------------------------------=
+ if maxCount <= 0 {
+ return self.update(0 as UInt)
+ }
+ //=--------------------------------------=
+ self.storage.withUnsafeMutableBufferPointer {
+ NBK.SUI.bitShiftRight(&$0, major: major, minorAtLeastOne: minor)
+ }
+
+ self.storage.resize(maxCount: maxCount)
+ Swift.assert(self.storage.isNormal)
+ }
+
+ /// Performs an unsigned right shift.
+ ///
+ /// - Parameters:
+ /// - major: `1 <= major`
+ ///
+ @inlinable mutating func bitShiftRight(majorAtLeastOne major: Int) {
+ //=--------------------------------------=
+ if self.storage.elements.count <= major {
+ return self.update(0 as UInt)
+ }
+ //=--------------------------------------=
+ self.storage.withUnsafeMutableBufferPointer {
+ NBK.SUI.bitShiftRight(&$0, majorAtLeastOne: major)
+ }
+
+ self.storage.resize(maxCount: self.storage.elements.count - major)
+ Swift.assert(self.storage.isNormal)
+ }
+}
diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Storage.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Storage.swift
new file mode 100644
index 00000000..98b435f6
--- /dev/null
+++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Storage.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 Flexible Width x Size x Unsigned x Storage
+//*============================================================================*
+
+extension NBKFlexibleWidth.Magnitude.Storage {
+
+ //=------------------------------------------------------------------------=
+ // MARK: Transformations
+ //=------------------------------------------------------------------------=
+
+ @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(0 as UInt)
+ }
+ }
+
+ @inlinable mutating func resize(maxCount: Int) {
+ precondition(maxCount.isMoreThanZero)
+ if self.elements.count > maxCount {
+ self.elements.removeSubrange(maxCount...)
+ }
+ }
+
+ @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.elements.last!.isZero
+ }
+
+ //=------------------------------------------------------------------------=
+ // MARK: Transformations
+ //=------------------------------------------------------------------------=
+
+ @inlinable mutating func normalize() {
+ trimming: while self.elements.count > 1, self.elements.last!.isZero {
+ self.elements.removeLast()
+ }
+ }
+}
diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.swift
new file mode 100644
index 00000000..6fbdef92
--- /dev/null
+++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction+Digit.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
+
+//*============================================================================*
+// 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) {
+ lhs.subtract(rhs, at: 0 as Int)
+ }
+
+ @_disfavoredOverload @inlinable public static func -(lhs: Self, rhs: UInt) -> Self {
+ 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)
+ }
+
+ @_disfavoredOverload @inlinable public func subtractingReportingOverflow(_ other: UInt) -> PVO {
+ self.subtractingReportingOverflow(other, at: 0 as Int)
+ }
+
+ //=------------------------------------------------------------------------=
+ // MARK: Transformations x Index
+ //=------------------------------------------------------------------------=
+
+ @_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 x Index x Overflow
+ //=------------------------------------------------------------------------=
+
+ @_disfavoredOverload @inlinable public mutating func subtractReportingOverflow(_ other: UInt, at index: Int) -> Bool {
+ //=--------------------------------------=
+ if other.isZero { return false }
+ //=--------------------------------------=
+ self.storage.resize(minCount: index + 1)
+
+ let overflow = self.storage.withUnsafeMutableBufferPointer(in: index...) {
+ NBK.SUISS.decrement(&$0, by: other).overflow
+ }
+
+ self.storage.normalize()
+ return overflow as Bool
+ }
+
+ @_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/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift
new file mode 100644
index 00000000..88635b13
--- /dev/null
+++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Subtraction.swift
@@ -0,0 +1,82 @@
+//=----------------------------------------------------------------------------=
+// This source file is part of the Numberick open source project.
+//
+// Copyright (c) 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) {
+ lhs.subtract(rhs, at: 0 as Int)
+ }
+
+ @inlinable public static func -(lhs: Self, rhs: Self) -> Self {
+ 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)
+ }
+
+ @inlinable public func subtractingReportingOverflow(_ other: Self) -> PVO {
+ self.subtractingReportingOverflow(other, at: 0 as Int)
+ }
+
+ //=------------------------------------------------------------------------=
+ // MARK: Transformations x Index
+ //=------------------------------------------------------------------------=
+
+ @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 x Index x Overflow
+ //=------------------------------------------------------------------------=
+
+ @inlinable public mutating func subtractReportingOverflow(_ other: Self, at index: Int) -> Bool {
+ //=--------------------------------------=
+ if other.isZero { return false }
+ //=--------------------------------------=
+ self.storage.resize(minCount: index + other.storage.elements.count)
+
+ let overflow = self.storage.withUnsafeMutableBufferPointer(in: index...) { slice in
+ other.storage.withUnsafeBufferPointer { other in
+ NBK.SUISS.decrement(&slice, by: other).overflow
+ }
+ }
+
+ self.storage.normalize()
+ return overflow as Bool
+ }
+
+ @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.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text.swift
new file mode 100644
index 00000000..538b376a
--- /dev/null
+++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Text.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 Text x Unsigned
+//*============================================================================*
+
+extension NBKFlexibleWidth.Magnitude {
+
+ //=------------------------------------------------------------------------=
+ // MARK: Details x Decoding
+ //=------------------------------------------------------------------------=
+
+ @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
+ //=------------------------------------------------------------------------=
+
+ @inlinable public func description(radix: Int, uppercase: Bool) -> String {
+ NBK.IntegerDescription.Encoder(radix: radix, uppercase: uppercase).encode(self)
+ }
+}
diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Update.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Update.swift
new file mode 100644
index 00000000..a08baded
--- /dev/null
+++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+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 x Unsigned
+//*============================================================================*
+
+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.elements.replaceSubrange(self.storage.elements.indices, with: CollectionOfOne(value))
+ }
+}
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+Pointers.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words+Pointers.swift
new file mode 100644
index 00000000..b0d5833d
--- /dev/null
+++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words+Pointers.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 Words x Pointers x Unsigned
+//*============================================================================*
+
+extension NBKFlexibleWidth.Magnitude {
+
+ //=------------------------------------------------------------------------=
+ // MARK: Details x Contiguous UInt Collection
+ //=------------------------------------------------------------------------=
+
+ /// 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 mutable words of this instance.
+ @inlinable public mutating func withUnsafeMutableBufferPointer(
+ _ body: (inout UnsafeMutableBufferPointer) 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
+//*============================================================================*
+
+extension NBKFlexibleWidth.Magnitude.Storage {
+
+ //=------------------------------------------------------------------------=
+ // MARK: Details x Contiguous UInt Collection
+ //=------------------------------------------------------------------------=
+
+ /// 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 mutable words of this instance.
+ @inlinable public mutating func withUnsafeMutableBufferPointer(
+ _ 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 words of this instance in the given `range`.
+ ///
+ /// ### Development
+ ///
+ /// This method is required for performance reasons (see slice arithmetic).
+ ///
+ @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)
+ return try body(&slice) as T
+ }
+ }
+
+ /// Grants unsafe access to the mutable words of this instance in the given `range`.
+ ///
+ /// ### Development
+ ///
+ /// This method is required for performance reasons (see slice arithmetic).
+ ///
+ @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)
+ return try body(&slice) as T
+ }
+ }
+}
diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words+Uninitialized.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words+Uninitialized.swift
new file mode 100644
index 00000000..75af6ca6
--- /dev/null
+++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words+Uninitialized.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
+
+//*============================================================================*
+// 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
+//*============================================================================*
+
+extension NBKFlexibleWidth.Magnitude {
+
+ //=------------------------------------------------------------------------=
+ // MARK: Initializers
+ //=------------------------------------------------------------------------=
+
+ @inlinable public static func uninitialized(
+ capacity: Int, init: (inout UnsafeMutableBufferPointer, inout Int) throws -> Void) rethrows -> Self {
+ Self(normalizing: try Storage.uninitialized(capacity: capacity, init: `init`))
+ }
+}
+
+//*============================================================================*
+// MARK: * NBK x Double Width x Words x Uninitialized x Unsigned x Storage
+//*============================================================================*
+
+extension NBKFlexibleWidth.Magnitude.Storage {
+
+ //=------------------------------------------------------------------------=
+ // MARK: Initializers
+ //=------------------------------------------------------------------------=
+
+ /// 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.
+ ///
+ /// ### Semantics when there is no initialized prefix
+ ///
+ /// It returns zero when there is no initialized prefix 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/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift
new file mode 100644
index 00000000..e894012b
--- /dev/null
+++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth+Words.swift
@@ -0,0 +1,45 @@
+//=----------------------------------------------------------------------------=
+// This source file is part of the Numberick open source project.
+//
+// Copyright (c) 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 Sequence) {
+ self.init(words: words, isSigned: Self.isSigned)!
+ }
+
+ @inlinable public init?(words: some Sequence, isSigned: Bool) {
+ var storage = Storage(nonemptying: Elements(words))
+ if isSigned && storage.elements.last!.mostSignificantBit { return nil }
+
+ storage.normalize()
+ self.init(unchecked: storage)
+ }
+
+ //=------------------------------------------------------------------------=
+ // MARK: Accessors
+ //=------------------------------------------------------------------------=
+
+ @inlinable public var count: Int {
+ self.storage.elements.count
+ }
+
+ @inlinable public var words: ContiguousArray {
+ self.storage.elements
+ }
+}
diff --git a/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift
new file mode 100644
index 00000000..7712b970
--- /dev/null
+++ b/Sources/NBKFlexibleWidthKit/NBKFlexibleWidth.swift
@@ -0,0 +1,153 @@
+//=----------------------------------------------------------------------------=
+// This source file is part of the Numberick open source project.
+//
+// Copyright (c) 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.
+///
+/// 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 {
+
+ @usableFromInline typealias Elements = ContiguousArray
+
+ //*========================================================================*
+ // MARK: * Magnitude
+ //*========================================================================*
+
+ /// An unsigned, flexible-width, binary integer.
+ @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) {
+ self.storage = storage
+ precondition(self.storage.isNormal)
+ }
+
+ @inlinable init(normalizing storage: Storage) {
+ self.storage = storage
+ self.storage.normalize()
+ }
+
+ @inlinable init(unchecked storage: Storage) {
+ self.storage = storage
+ Swift.assert(self.storage.isNormal)
+ }
+
+ //*====================================================================*
+ // 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 = 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(nonemptying elements: Elements) {
+ self.elements = elements
+ if self.elements.isEmpty {
+ self.elements.append(0)
+ }
+ }
+
+ @inlinable init(unchecked elements: Elements) {
+ self.elements = elements
+ Swift.assert(!self.elements.isEmpty)
+ }
+ }
+ }
+}
+
+//=----------------------------------------------------------------------------=
+// 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.
+///
+/// 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.
+public typealias UIntXL = NBKFlexibleWidth.Magnitude
diff --git a/Sources/Numberick/Documentation.docc/Documentation.md b/Sources/Numberick/Documentation.docc/Documentation.md
index 3456a435..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
@@ -112,6 +147,7 @@ Int256(5) % Int(5), UInt256(5) % UInt(5)
- ``NBKChunkedInt``
- ``NBKDoubleWidth``
- ``NBKEndianness``
+- ``NBKFlexibleWidth``
- ``NBKPrimeSieve``
- ``NBKStaticBigInt``
@@ -130,6 +166,7 @@ Int256(5) % Int(5), UInt256(5) % UInt(5)
- ``UInt1024``
- ``UInt2048``
- ``UInt4096``
+- ``UIntXL``
### Abbreviations
diff --git a/Sources/Numberick/Exports.swift b/Sources/Numberick/Numberick.swift
similarity index 100%
rename from Sources/Numberick/Exports.swift
rename to Sources/Numberick/Numberick.swift
diff --git a/Tests/NBKCoreKitTests/NBKCoreInteger+Comparisons.swift b/Tests/NBKCoreKitTests/NBKCoreInteger+Comparisons.swift
index b540d80f..303d9f09 100644
--- a/Tests/NBKCoreKitTests/NBKCoreInteger+Comparisons.swift
+++ b/Tests/NBKCoreKitTests/NBKCoreInteger+Comparisons.swift
@@ -211,9 +211,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/NBKFlexibleWidthKitBenchmarks/Models/NBKFibonacciXL.swift b/Tests/NBKFlexibleWidthKitBenchmarks/Models/NBKFibonacciXL.swift
new file mode 100644
index 00000000..fa75116f
--- /dev/null
+++ b/Tests/NBKFlexibleWidthKitBenchmarks/Models/NBKFibonacciXL.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.
+//=----------------------------------------------------------------------------=
+
+#if !DEBUG
+
+import NBKCoreKit
+import NBKFlexibleWidthKit
+import XCTest
+
+private typealias X = [UInt]
+private typealias X64 = [UInt64]
+private typealias X32 = [UInt32]
+
+//*============================================================================*
+// MARK: * NBK x FibonacciXL
+//*============================================================================*
+
+final class NBKFibonacciXLBenchmarks: XCTestCase {
+
+ typealias T = NBKFibonacciXL
+
+ //=------------------------------------------------------------------------=
+ // MARK: Tests
+ //=------------------------------------------------------------------------=
+
+ func testPrime222() {
+ var index = NBK.blackHoleIdentity(UInt(1399))
+
+ for _ in 0 ..< 10_000 {
+ NBK.blackHole(T(index))
+ NBK.blackHoleInoutIdentity(&index)
+ }
+ }
+
+ func testPrime333() {
+ var index = NBK.blackHoleIdentity(UInt(2239))
+
+ for _ in 0 ..< 10_000 {
+ NBK.blackHole(T(index))
+ NBK.blackHoleInoutIdentity(&index)
+ }
+ }
+
+ func testPrime555() {
+ var index = NBK.blackHoleIdentity(UInt(4019))
+
+ for _ in 0 ..< 10_000 {
+ NBK.blackHole(T(index))
+ NBK.blackHoleInoutIdentity(&index)
+ }
+ }
+
+ func testPrime777() {
+ var index = NBK.blackHoleIdentity(UInt(5903))
+
+ for _ in 0 ..< 10_000 {
+ NBK.blackHole(T(index))
+ NBK.blackHoleInoutIdentity(&index)
+ }
+ }
+
+ //=------------------------------------------------------------------------=
+ // MARK: Tests x No Loop
+ //=------------------------------------------------------------------------=
+
+ /// 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(10_000_000)))
+ }
+}
+
+#endif
diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Addition.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Addition.swift
new file mode 100644
index 00000000..8310c55b
--- /dev/null
+++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Addition.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.
+//=----------------------------------------------------------------------------=
+
+#if !DEBUG
+
+import NBKCoreKit
+import NBKFlexibleWidthKit
+import XCTest
+
+private typealias X = [UInt]
+private typealias X64 = [UInt64]
+private typealias X32 = [UInt32]
+
+//*============================================================================*
+// 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 X64))
+ var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X64))
+
+ 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 X64))
+ var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X64))
+
+ 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 X64))
+ 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 X64))
+ 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/NBKFlexibleWidth+Bits.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Bits.swift
new file mode 100644
index 00000000..cf7702f4
--- /dev/null
+++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+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 NBKFlexibleWidthKit
+import XCTest
+
+private typealias X = [UInt]
+private typealias X64 = [UInt64]
+private typealias X32 = [UInt32]
+
+//*============================================================================*
+// 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 X64))
+ var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X64))
+
+ 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 X64))
+ var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X64))
+
+ 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 X64))
+ var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X64))
+
+ 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 X64))
+ var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X64))
+
+ 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 X64))
+ var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X64))
+
+ 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 X64))
+ var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X64))
+
+ 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/NBKFlexibleWidth+Comparisons.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Comparisons.swift
new file mode 100644
index 00000000..e3bad654
--- /dev/null
+++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Comparisons.swift
@@ -0,0 +1,150 @@
+//=----------------------------------------------------------------------------=
+// This source file is part of the Numberick open source project.
+//
+// Copyright (c) 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 = [UInt]
+private typealias X64 = [UInt64]
+private typealias X32 = [UInt32]
+
+//*============================================================================*
+// 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 X64))
+
+ 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 X64))
+
+ 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 X64))
+
+ 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 X64))
+
+ 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 X64))
+
+ 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 X64))
+ var rhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X64))
+
+ 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 X64))
+ var rhs = NBK.blackHoleIdentity(T(x64:[0, 1, 2, 3] as X64))
+
+ 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 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))
+ NBK.blackHoleInoutIdentity(&lhs)
+ NBK.blackHoleInoutIdentity(&rhs)
+ }
+ }
+
+ func testComparedToAtIndex() {
+ 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 {
+ 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 X64))
+ 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 X64))
+ 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/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Complements.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Complements.swift
new file mode 100644
index 00000000..248dfc37
--- /dev/null
+++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Complements.swift
@@ -0,0 +1,160 @@
+//=----------------------------------------------------------------------------=
+// This source file is part of the Numberick open source project.
+//
+// Copyright (c) 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 = [UInt]
+private typealias X64 = [UInt64]
+private typealias X32 = [UInt32]
+
+//*============================================================================*
+// 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 X64))
+ var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X64))
+
+ 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 X64))
+ var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X64))
+
+ 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 X64))
+ var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X64))
+
+ 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 X64))
+ var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X64))
+
+ 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 X64))
+ var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X64))
+
+ 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 X64))
+ var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X64))
+
+ 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 X64))
+ var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X64))
+
+ 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 X64))
+ var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X64))
+
+ 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 X64))
+ var xyz = NBK.blackHoleIdentity(~T(x64:[0, 0, 0, 0] as X64))
+
+ 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/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Division.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Division.swift
new file mode 100644
index 00000000..528172bc
--- /dev/null
+++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Division.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 NBKFlexibleWidthKit
+import XCTest
+
+private typealias X = [UInt]
+private typealias X64 = [UInt64]
+private typealias X32 = [UInt32]
+
+//*============================================================================*
+// 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 X64))
+ var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X64))
+
+ 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 X64))
+ var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X64))
+
+ 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 X64))
+ var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X64))
+
+ 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 X64))
+ 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 X64))
+ 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 X64))
+ 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 testDividingFullWidthAs256WhenDivisorIsNormalized() {
+ 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))
+ NBK.blackHoleInoutIdentity(&rhs)
+ NBK.blackHoleInoutIdentity(&lhs)
+ }
+ }
+
+ func testDividingFullWidthReportingOverflowAs256WhenDivisorIsNormalized() {
+ 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))
+ NBK.blackHoleInoutIdentity(&rhs)
+ NBK.blackHoleInoutIdentity(&lhs)
+ }
+ }
+
+ func testDividingFullWidthAs256WhenDivisorIsNotNormalized() {
+ 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))
+ NBK.blackHoleInoutIdentity(&rhs)
+ NBK.blackHoleInoutIdentity(&lhs)
+ }
+ }
+
+ func testDividingFullWidthReportingOverflowAs256WhenDivisorIsNotNormalized() {
+ 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))
+ NBK.blackHoleInoutIdentity(&rhs)
+ NBK.blackHoleInoutIdentity(&lhs)
+ }
+ }
+}
+
+#endif
diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Exponentiation.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Exponentiation.swift
new file mode 100644
index 00000000..ef434ff1
--- /dev/null
+++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Exponentiation.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 = [UInt]
+private typealias X64 = [UInt64]
+private typealias X32 = [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)
+ }
+ }
+
+ //=------------------------------------------------------------------------=
+ // 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/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Logic.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Logic.swift
new file mode 100644
index 00000000..fc4337fb
--- /dev/null
+++ b/Tests/NBKFlexibleWidthKitBenchmarks/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 NBKFlexibleWidthKit
+import XCTest
+
+private typealias X = [UInt]
+private typealias X64 = [UInt64]
+private typealias X32 = [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 X64))
+
+ 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 X64))
+
+ 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 X64))
+ var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X64))
+
+ 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 X64))
+ var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X64))
+
+ 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 X64))
+ var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X64))
+
+ 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 X64))
+ var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X64))
+
+ 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 X64))
+ var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X64))
+
+ 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 X64))
+ var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X64))
+
+ for _ in 0 ..< 1_000_000 {
+ NBK.blackHole(lhs ^ rhs)
+ NBK.blackHoleInoutIdentity(&lhs)
+ NBK.blackHoleInoutIdentity(&rhs)
+ }
+ }
+}
+
+#endif
diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Multiplication.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Multiplication.swift
new file mode 100644
index 00000000..ba562634
--- /dev/null
+++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Multiplication.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 = [UInt]
+private typealias X64 = [UInt64]
+private typealias X32 = [UInt32]
+
+//*============================================================================*
+// MARK: * NBK x Flexible Width x Multiplication x UIntXL
+//*============================================================================*
+
+final class NBKFlexibleWidthBenchmarksOnMultiplicationAsUIntXL: XCTestCase {
+
+ typealias T = UIntXL
+
+ //=------------------------------------------------------------------------=
+ // MARK: Tests
+ //=------------------------------------------------------------------------=
+
+ func testMultiplying() {
+ 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)
+ NBK.blackHoleInoutIdentity(&lhs)
+ NBK.blackHoleInoutIdentity(&rhs)
+ }
+ }
+
+ //=------------------------------------------------------------------------=
+ // MARK: Tests x Digit
+ //=------------------------------------------------------------------------=
+
+ func testMultiplyingByDigit() {
+ var lhs = NBK.blackHoleIdentity(T(x64:[~1, ~2, ~3, ~4] as X64))
+ var rhs = NBK.blackHoleIdentity(UInt.max)
+
+ for _ in 0 ..< 1_000_000 {
+ NBK.blackHole(lhs * rhs)
+ NBK.blackHoleInoutIdentity(&lhs)
+ NBK.blackHoleInoutIdentity(&rhs)
+ }
+ }
+
+ //=------------------------------------------------------------------------=
+ // MARK: Tests x Square
+ //=------------------------------------------------------------------------=
+
+ func testMultiplyingBySquaring() {
+ var base = NBK.blackHoleIdentity(T(x64:[~1, ~2, ~3, ~4] as X64))
+
+ for _ in 0 ..< 1_000_000 {
+ NBK.blackHole(base.squared())
+ NBK.blackHoleInoutIdentity(&base)
+ NBK.blackHoleInoutIdentity(&base)
+ }
+ }
+}
+
+#endif
diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Numbers.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Numbers.swift
new file mode 100644
index 00000000..5a2d3cb2
--- /dev/null
+++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Numbers.swift
@@ -0,0 +1,435 @@
+//=----------------------------------------------------------------------------=
+// This source file is part of the Numberick open source project.
+//
+// Copyright (c) 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 = [UInt]
+private typealias X64 = [UInt64]
+private typealias X32 = [UInt32]
+
+//*============================================================================*
+// MARK: * NBK x Flexible Width x Numbers x UIntXL
+//*============================================================================*
+
+final class NBKFlexibleWidthBenchmarksOnNumbersAsUIntXL: XCTestCase {
+
+ typealias T = UIntXL
+ typealias M = UIntXL
+
+ //=------------------------------------------------------------------------=
+ // MARK: Tests x Constants
+ //=------------------------------------------------------------------------=
+
+ @_optimize(none)
+ func makeInit() -> T { T( ) }
+ func testInit() {
+ for _ in 0 ..< 1_000_000 {
+ NBK.blackHole(makeInit())
+ }
+ }
+
+ @_optimize(none)
+ func makeZero() -> T { T.zero }
+ func testZero() {
+ for _ in 0 ..< 1_000_000 {
+ NBK.blackHole(makeZero())
+ }
+ }
+
+ @_optimize(none)
+ func makeOne() -> T { T.one }
+ func testOne() {
+ for _ in 0 ..< 1_000_000 {
+ NBK.blackHole(makeOne())
+ }
+ }
+
+ //=------------------------------------------------------------------------=
+ // 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 X64))
+
+ 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 X64))
+
+ 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 X64))
+
+ 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 X64))
+
+ 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 X64))
+
+ 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 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))
+ NBK.blackHoleInoutIdentity(&abc)
+
+ NBK.blackHole(T(sign: xyz.sign, magnitude: xyz.magnitude))
+ NBK.blackHoleInoutIdentity(&xyz)
+ }
+ }
+}
+
+#endif
diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Shifts.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Shifts.swift
new file mode 100644
index 00000000..916c786c
--- /dev/null
+++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+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 NBKFlexibleWidthKit
+import XCTest
+
+private typealias X = [UInt]
+private typealias X64 = [UInt64]
+private typealias X32 = [UInt32]
+
+//*============================================================================*
+// 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 X64))
+ 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 X64))
+ var rhs = NBK.blackHoleIdentity((major: 1, minor: UInt.bitWidth/2))
+
+ for _ in 0 ..< 1_000_000 {
+ NBK.blackHole(lhs.bitShiftedLeft(major: rhs.major))
+ NBK.blackHoleInoutIdentity(&lhs)
+ NBK.blackHoleInoutIdentity(&rhs)
+ }
+ }
+
+ func testBitShiftingLeftByWordsAndBits() {
+ 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 {
+ NBK.blackHole(lhs.bitShiftedLeft(major: rhs.major, minor: rhs.minor))
+ NBK.blackHoleInoutIdentity(&lhs)
+ NBK.blackHoleInoutIdentity(&rhs)
+ }
+ }
+
+ //=------------------------------------------------------------------------=
+ // MARK: Tests x Right
+ //=------------------------------------------------------------------------=
+
+ func testBitShiftingRight() {
+ 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 {
+ NBK.blackHole(lhs >> rhs)
+ NBK.blackHoleInoutIdentity(&lhs)
+ NBK.blackHoleInoutIdentity(&rhs)
+ }
+ }
+
+ func testBitShiftingRightByWords() {
+ 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 {
+ NBK.blackHole(lhs.bitShiftedRight(major: rhs.major))
+ NBK.blackHoleInoutIdentity(&lhs)
+ NBK.blackHoleInoutIdentity(&rhs)
+ }
+ }
+
+ func testBitShiftingRightByWordsAndBits() {
+ 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 {
+ NBK.blackHole(lhs.bitShiftedRight(major: rhs.major, minor: rhs.minor))
+ 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 X64))
+ 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 X64))
+ var rhs = NBK.blackHoleIdentity((major: 1, minor: UInt.bitWidth/2))
+
+ for _ in 0 ..< 1_000_000 {
+ NBK.blackHole(lhs.bitShiftLeft (major: rhs.major))
+ NBK.blackHoleInoutIdentity(&lhs)
+ NBK.blackHoleInoutIdentity(&rhs)
+
+ NBK.blackHole(lhs.bitShiftRight(major: rhs.major))
+ NBK.blackHoleInoutIdentity(&lhs)
+ NBK.blackHoleInoutIdentity(&rhs)
+ }
+ }
+
+ func testBitShiftingInBothDirectionsByWordsAndBitsInout() {
+ 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 {
+ NBK.blackHole(lhs.bitShiftLeft (major: rhs.major, minor: rhs.minor))
+ NBK.blackHoleInoutIdentity(&lhs)
+ NBK.blackHoleInoutIdentity(&rhs)
+
+ NBK.blackHole(lhs.bitShiftRight(major: rhs.major, minor: rhs.minor))
+ NBK.blackHoleInoutIdentity(&lhs)
+ NBK.blackHoleInoutIdentity(&rhs)
+ }
+ }
+}
+
+#endif
diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Subtraction.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Subtraction.swift
new file mode 100644
index 00000000..8fbfa337
--- /dev/null
+++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Subtraction.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.
+//=----------------------------------------------------------------------------=
+
+#if !DEBUG
+
+import NBKCoreKit
+import NBKFlexibleWidthKit
+import XCTest
+
+private typealias X = [UInt]
+private typealias X64 = [UInt64]
+private typealias X32 = [UInt32]
+
+//*============================================================================*
+// 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 X64))
+ var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X64))
+
+ 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 X64))
+ var rhs = NBK.blackHoleIdentity(T(x64:[ 0, 1, 2, 3] as X64))
+
+ 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 X64))
+ 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 X64))
+ 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/NBKFlexibleWidth+Text.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Text.swift
new file mode 100644
index 00000000..38290548
--- /dev/null
+++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Text.swift
@@ -0,0 +1,110 @@
+//=----------------------------------------------------------------------------=
+// This source file is part of the Numberick open source project.
+//
+// Copyright (c) 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 = [UInt]
+private typealias X64 = [UInt64]
+private typealias X32 = [UInt32]
+
+//*============================================================================*
+// 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(String(NBK.someSwiftBinaryInteger(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(NBK.someSwiftBinaryInteger(decoded), radix: radix))
+ NBK.blackHoleInoutIdentity(&radix)
+ NBK.blackHoleInoutIdentity(&decoded)
+ }
+ }
+}
+
+#endif
diff --git a/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Words.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+Words.swift
new file mode 100644
index 00000000..0cbb4e6a
--- /dev/null
+++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth+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 NBKFlexibleWidthKit
+import XCTest
+
+private typealias X = [UInt]
+private typealias X64 = [UInt64]
+private typealias X32 = [UInt32]
+
+//*============================================================================*
+// 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 X)
+ var xyz = NBK.blackHoleIdentity([~0, ~0, ~0, ~0] as X)
+
+ 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/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth.swift b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth.swift
new file mode 100644
index 00000000..cabd8fa2
--- /dev/null
+++ b/Tests/NBKFlexibleWidthKitBenchmarks/NBKFlexibleWidth.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
+
+private typealias X = [UInt]
+private typealias X64 = [UInt64]
+private typealias X32 = [UInt32]
+
+//*============================================================================*
+// MARK: * NBK x Flexible Width x UIntXL
+//*============================================================================*
+
+extension NBKFlexibleWidth.Magnitude {
+
+ //=------------------------------------------------------------------------=
+ // MARK: Initializers
+ //=------------------------------------------------------------------------=
+
+ static let min256 = Self(x64:[ 0, 0, 0, 0] as X64)
+ static let max256 = Self(x64:[~0, ~0, ~0, ~0] as X64)
+
+ //=------------------------------------------------------------------------=
+ // MARK: Initializers
+ //=------------------------------------------------------------------------=
+
+ init(x32: [UInt32]) {
+ self.init(words: NBKChunkedInt(x32))
+ }
+
+ init(x64: [UInt64]) {
+ self.init(words: NBKChunkedInt(x64))
+ }
+}
diff --git a/Tests/NBKFlexibleWidthKitTests/Models/NBKFibonacciXL.swift b/Tests/NBKFlexibleWidthKitTests/Models/NBKFibonacciXL.swift
new file mode 100644
index 00000000..f2973551
--- /dev/null
+++ b/Tests/NBKFlexibleWidthKitTests/Models/NBKFibonacciXL.swift
@@ -0,0 +1,671 @@
+//=----------------------------------------------------------------------------=
+// This source file is part of the Numberick open source project.
+//
+// Copyright (c) 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
+
+private typealias X = [UInt]
+private typealias X64 = [UInt64]
+private typealias X32 = [UInt32]
+
+//*============================================================================*
+// MARK: * NBK x FibonacciXL
+//*============================================================================*
+
+final class NBKFibonacciXLTests: XCTestCase {
+
+ 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 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 = T(); while fibonacci.next <= UIntXL.max256 {
+ NBKAssertFibonacciSequenceElement(fibonacci.index, fibonacci.element)
+ fibonacci.increment()
+ }
+
+ XCTAssertEqual(fibonacci.index, 370 as UInt)
+ XCTAssertEqual(fibonacci.element, UIntXL("094611056096305838013295371573764256526437182762229865607320618320601813254535"))
+ XCTAssertEqual(fibonacci.next, UIntXL("153083904475345790698149223310665389766178449653686710164582374234640876900329"))
+ }
+}
+
+//*============================================================================*
+// MARK: * NBK x FibonacciXL x Primes
+//*============================================================================*
+
+final class NBKFibonacciXLTestsOnPrimes: XCTestCase {
+
+ typealias T = NBKFibonacciXL
+
+ //=------------------------------------------------------------------------=
+ // MARK: Tests
+ //=------------------------------------------------------------------------=
+
+ /// https://www.wolframalpha.com/input?i2d=true&i=fibonnaci+1399
+ func testPrime0222() {
+ NBKAssertFibonacciSequenceElement(UInt(1399), UIntXL("""
+ 0000000000000000000000000001057362022138877586442790693627392471\
+ 4349424343122542609372806319825783387389898145491654340696207977\
+ 9703100859330541842708747836587076026853149515123668038994257349\
+ 6825711057526259113835863240488302877201171798455616630015796594\
+ 0742927387906176446848324713233936084752836275187153808643885101
+ """))
+ }
+
+ /// https://www.wolframalpha.com/input?i2d=true&i=fibonnaci+2239
+ func testPrime0333() {
+ NBKAssertFibonacciSequenceElement(UInt(2239), UIntXL("""
+ 0000000000000000000000000000000000000000000037483619230023616383\
+ 1556956012890801755635223834456440078068598512042225565858378705\
+ 2775478508439311765008270803174379457823903626436917896144175108\
+ 1812500769712739265577812142790633886426904029644292656072176594\
+ 5442661544462371162680745392064002681693236118751836449122772276\
+ 7869284859173664595855541705821814253059049650198752630703006217\
+ 8339242653834274827433371972683579086589883072059016299647032544\
+ 7184786711538554743189201957494849217103385151192357985565557661
+ """))
+ }
+
+ /// https://www.wolframalpha.com/input?i2d=true&i=fibonnaci+4019
+ func testPrime0555() {
+ NBKAssertFibonacciSequenceElement(UInt(4019), UIntXL("""
+ 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 testPrime0777() {
+ NBKAssertFibonacciSequenceElement(UInt(5903), UIntXL("""
+ 0000000000000000000000000000000000000000000000201630112973699547\
+ 8467033798246231765802235127399927076436839763410065672009048903\
+ 1282893541236712535277172854664465524821928062556461511462472243\
+ 6645751603027750072868408113686717270843656386576571239706531613\
+ 8832607318277041589340170938439083061589073645207050078640037387\
+ 3930944738614316892092679585355923400727053939446917720844859420\
+ 8475286500719315637423740931654098191825715510224786132537906089\
+ 2798464444270756081302801050898869097388615552432632699803372579\
+ 5006266664207612795271656344222004200834104891232199115031529879\
+ 2703171846839972134549632698690061406266150782100519904238693642\
+ 7990494803652598109479923921411786233223630306244612906702729633\
+ 0936722357821751129503986058477775784943438980499220967251871125\
+ 8907675708863225870261545152179027647035709552484493259087293234\
+ 3560027918334679621500613235053762398727366706896356186229959919\
+ 9113456220990739086184934440183082123185220867952003388928951448\
+ 6862918684679538218518939139423048219131427786458175412165472787\
+ 2317940678177228138520687104044551650142781207251510823550422463\
+ 0550656054019863500046679727553797345950068888003234780117695468\
+ 5001758459948949898864934140668770688345102830949505991111324318\
+ 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
+ """))
+ }
+}
+
+//*============================================================================*
+// MARK: * NBK x FibonacciXL x Assertions
+//*============================================================================*
+
+private func NBKAssertFibonacciSequenceElement(
+_ index: UInt, _ element: UIntXL, division: Bool = true,
+file: StaticString = #file, line: UInt = #line) {
+ //=------------------------------------------=
+ 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)
+ //=------------------------------------------=
+ 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)
+ }
+
+ 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)
+ }
+
+ 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(
+_ a: NBKFibonacciXL, _ b: NBKFibonacciXL,
+file: StaticString = #file, line: UInt = #line) {
+ //=------------------------------------------=
+ let c = NBKFibonacciXL(a.index - b.index)
+ let d = a.next.quotientAndRemainder(dividingBy: b.next)
+ //=------------------------------------------=
+ brr: do { var lhs: UIntXL, rhs: UIntXL
+
+ lhs = b.element // f(b)
+ lhs *= c.element // f(c)
+
+ 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(lhs, rhs, file: file, line: line)
+ }
+}
diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Addition.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Addition.swift
new file mode 100644
index 00000000..a9abc45d
--- /dev/null
+++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Addition.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
+import NBKFlexibleWidthKit
+import XCTest
+
+private typealias X = [UInt]
+private typealias X64 = [UInt64]
+private typealias X32 = [UInt32]
+
+//*============================================================================*
+// 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 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 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))
+ }
+
+ //=------------------------------------------------------------------------=
+ // 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 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 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))
+ }
+
+ //=------------------------------------------------------------------------=
+ // 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)
+}
diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Bits.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Bits.swift
new file mode 100644
index 00000000..041744d5
--- /dev/null
+++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Bits.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.
+//=----------------------------------------------------------------------------=
+
+import NBKCoreKit
+import NBKFlexibleWidthKit
+import XCTest
+
+private typealias X = [UInt]
+private typealias X64 = [UInt64]
+private typealias X32 = [UInt32]
+
+//*============================================================================*
+// 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 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 X).nonzeroBitCount, 0)
+ XCTAssertEqual(T(words:[ 1, 1, 1, 1] as X).nonzeroBitCount, 4)
+ }
+
+ func testLeadingZeroBitCount() {
+ 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 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 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 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 X).mostSignificantBit, false)
+ 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, 0, 0, ~0] as X).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 X).leastSignificantBit, false)
+ XCTAssertEqual(T(words:[~0, ~0, ~0, ~0] as X).leastSignificantBit, true )
+
+ 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 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
new file mode 100644
index 00000000..4586a51f
--- /dev/null
+++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Comparisons.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.
+//=----------------------------------------------------------------------------=
+
+import NBKCoreKit
+import NBKFlexibleWidthKit
+import XCTest
+
+private typealias X = [UInt]
+private typealias X64 = [UInt64]
+private typealias X32 = [UInt32]
+
+//*============================================================================*
+// 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 X).isZero)
+ XCTAssertFalse(T(words:[ 1] as X).isZero)
+ XCTAssertFalse(T(words:[ 2] as X).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 X).isLessThanZero)
+ XCTAssertFalse(T(words:[ 1] as X).isLessThanZero)
+ XCTAssertFalse(T(words:[ 2] as X).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 X).isMoreThanZero)
+ XCTAssertTrue (T(words:[ 1] as X).isMoreThanZero)
+ XCTAssertTrue (T(words:[ 2] as X).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 X).isOdd)
+ XCTAssertTrue (T(words:[ 1] as X).isOdd)
+ XCTAssertFalse(T(words:[ 2] as X).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 X).isEven)
+ XCTAssertFalse(T(words:[ 1] as X).isEven)
+ XCTAssertTrue (T(words:[ 2] as X).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 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 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 X), Int(0))
+ NBKAssertSignum(T(words:[ 1] as X), Int(1))
+ NBKAssertSignum(T(words:[ 2] as X), 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))
+ }
+
+ //=------------------------------------------------------------------------=
+ // MARK: Tests
+ //=------------------------------------------------------------------------=
+
+ func testHashing() {
+ var union = Set()
+ 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 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 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 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 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 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() {
+ 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)
+}
diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Complements.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Complements.swift
new file mode 100644
index 00000000..76815bf5
--- /dev/null
+++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Complements.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
+import NBKFlexibleWidthKit
+import XCTest
+
+private typealias X = [UInt]
+private typealias X64 = [UInt64]
+private typealias X32 = [UInt32]
+
+//*============================================================================*
+// 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 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 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))
+ }
+
+ //=------------------------------------------------------------------------=
+ // MARK: Tests x One's Complement
+ //=------------------------------------------------------------------------=
+
+ func testOnesComplement() {
+ 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 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 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))
+ }
+
+ //=------------------------------------------------------------------------=
+ // MARK: Tests x Two's Complement
+ //=------------------------------------------------------------------------=
+
+ func testTwosComplement() {
+ 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 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 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))
+ }
+}
+
+//*============================================================================*
+// 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)
+}
diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Division.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Division.swift
new file mode 100644
index 00000000..2350f371
--- /dev/null
+++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Division.swift
@@ -0,0 +1,294 @@
+//=----------------------------------------------------------------------------=
+// This source file is part of the Numberick open source project.
+//
+// Copyright (c) 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
+
+private typealias X = [UInt]
+private typealias X64 = [UInt64]
+private typealias X32 = [UInt32]
+
+//*============================================================================*
+// 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 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 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 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 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 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 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))
+ }
+
+ //=------------------------------------------------------------------------=
+ // MARK: Tests x Digit (and Self)
+ //=------------------------------------------------------------------------=
+
+ 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 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))
+ }
+
+ //=------------------------------------------------------------------------=
+ // 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 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 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)
+ }
+}
+
+//*============================================================================*
+// MARK: * NBK x Flexible Width x Division x Assertions
+//*============================================================================*
+
+private func NBKAssertDivision(
+_ dividend: T, _ divisor: T, _ quotient: T, _ remainder: T, _ overflow: Bool = false,
+file: StaticString = #file, line: UInt = #line) {
+ //=------------------------------------------=
+ if !overflow {
+ XCTAssertEqual(dividend, quotient * divisor + remainder, "dividend != divisor * quotient + remainder", file: file, line: line)
+ }
+
+ if !overflow {
+ XCTAssertEqual(dividend / divisor, quotient, file: file, line: line)
+ XCTAssertEqual(dividend % divisor, remainder, file: file, line: line)
+ }
+
+ if !overflow {
+ 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 = dividend.quotientAndRemainder(dividingBy: divisor)
+ XCTAssertEqual(out.quotient, quotient, file: file, line: line)
+ XCTAssertEqual(out.remainder, remainder, file: file, line: line)
+ }
+
+ brr: do {
+ 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 = 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 = dividend.remainderReportingOverflow(dividingBy: divisor)
+ XCTAssertEqual(out.partialValue, remainder, file: file, line: line)
+ XCTAssertEqual(out.overflow, overflow, file: file, line: line)
+ }
+
+ brr: do {
+ 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 = 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)
+ }
+}
+
+private func NBKAssertDivisionByDigit(
+_ 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(dividend, T(digit: divisor), quotient, T(digit: remainder), overflow, file: file, line: line)
+ //=------------------------------------------=
+ if !overflow {
+ XCTAssertEqual(dividend, quotient * divisor + remainder, "dividend != divisor * quotient + remainder", file: file, line: line)
+ }
+
+ if !overflow {
+ XCTAssertEqual(dividend / divisor, quotient, file: file, line: line)
+ XCTAssertEqual(dividend % divisor, remainder, file: file, line: line)
+ }
+
+ if !overflow {
+ 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 = dividend.quotientAndRemainder(dividingBy: divisor)
+ XCTAssertEqual(out.quotient, quotient, file: file, line: line)
+ XCTAssertEqual(out.remainder, remainder, file: file, line: line)
+ }
+
+ brr: do {
+ 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 = 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 = dividend.remainderReportingOverflow(dividingBy: divisor)
+ XCTAssertEqual(out.partialValue, remainder, file: file, line: line)
+ XCTAssertEqual(out.overflow, overflow, file: file, line: line)
+ }
+
+ brr: do {
+ 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 = 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 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 = 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)
+ }
+}
diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Exponentiation.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Exponentiation.swift
new file mode 100644
index 00000000..95ed38d6
--- /dev/null
+++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Exponentiation.swift
@@ -0,0 +1,348 @@
+//=----------------------------------------------------------------------------=
+// This source file is part of the Numberick open source project.
+//
+// Copyright (c) 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
+
+private typealias X = [UInt]
+private typealias X64 = [UInt64]
+private typealias X32 = [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 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))
+ }
+ }
+
+ 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 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))
+ }
+ }
+
+ 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 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))
+ }
+ }
+
+ 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 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))
+ }
+ }
+
+ //=------------------------------------------------------------------------=
+ // 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%2C1399%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 UIntXL x Powers Of 10
+//*============================================================================*
+
+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%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)
+ }
+}
+
+//*============================================================================*
+// 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)
+}
diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Literals.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Literals.swift
new file mode 100644
index 00000000..ed6065c4
--- /dev/null
+++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Literals.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.
+//=----------------------------------------------------------------------------=
+
+import NBKCoreKit
+import NBKFlexibleWidthKit
+import XCTest
+
+private typealias X = [UInt]
+private typealias X64 = [UInt64]
+private typealias X32 = [UInt32]
+
+//*============================================================================*
+// MARK: * NBK x Flexible Width x Literals x UIntXL
+//*============================================================================*
+
+final class NBKFlexibleWidthTestsOnLiteralsAsUIntXL: XCTestCase {
+
+ typealias T = UIntXL
+
+ //=------------------------------------------------------------------------=
+ // MARK: Tests
+ //=------------------------------------------------------------------------=
+
+ func testFromIntegerLiteral() {
+ 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 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 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 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 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 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 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
new file mode 100644
index 00000000..7d1915bb
--- /dev/null
+++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+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
+import NBKFlexibleWidthKit
+import XCTest
+
+private typealias X = [UInt]
+private typealias X64 = [UInt64]
+private typealias X32 = [UInt32]
+
+//*============================================================================*
+// 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 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 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 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 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 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 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 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 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 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 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 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))
+ }
+}
+
+//*============================================================================*
+// 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)
+}
diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Multiplication.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Multiplication.swift
new file mode 100644
index 00000000..c03ef702
--- /dev/null
+++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Multiplication.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
+import NBKFlexibleWidthKit
+import XCTest
+
+private typealias X = [UInt]
+private typealias X64 = [UInt64]
+private typealias X32 = [UInt32]
+
+//*============================================================================*
+// 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 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 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))
+ }
+
+ //=------------------------------------------------------------------------=
+ // MARK: Tests x Digit (and Self)
+ //=------------------------------------------------------------------------=
+
+ func testMultiplyingByDigit() {
+ 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 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))
+ }
+
+ //=------------------------------------------------------------------------=
+ // MARK: Tests x Digit x Addition
+ //=------------------------------------------------------------------------=
+
+ func testMultiplyingByDigitWithAddition() {
+ 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))
+ }
+
+ //=------------------------------------------------------------------------=
+ // MARK: Tests x Square
+ //=------------------------------------------------------------------------=
+
+ func testMultiplyingBySquaring() {
+ 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))
+ }
+
+ //=------------------------------------------------------------------------=
+ // 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, _ 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)
+}
+
+private func NBKAssertMultiplicationByDigit(
+_ 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)
+}
+
+private func NBKAssertMultiplicationBySquaring(
+_ base: T, _ product: T,
+file: StaticString = #file, line: UInt = #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)
+}
+
+//=----------------------------------------------------------------------------=
+// MARK: + UIntXL
+//=----------------------------------------------------------------------------=
+
+private func NBKAssertMultiplicationByDigitWithAddition(
+_ lhs: UIntXL, _ rhs: UInt, _ addend: UInt, _ product: UIntXL,
+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)
+}
diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Numbers.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Numbers.swift
new file mode 100644
index 00000000..e7c20195
--- /dev/null
+++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Numbers.swift
@@ -0,0 +1,345 @@
+//=----------------------------------------------------------------------------=
+// This source file is part of the Numberick open source project.
+//
+// Copyright (c) 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
+
+private typealias X = [UInt]
+private typealias X64 = [UInt64]
+private typealias X32 = [UInt32]
+
+//*============================================================================*
+// 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]))
+
+ for x in T.basket {
+ XCTAssertEqual(x + T.zero, x)
+ XCTAssertEqual(T.zero + x, x)
+
+ XCTAssertEqual(x - x, T.zero)
+ XCTAssertEqual(x - T.zero, x)
+ }
+ }
+
+ func testOne() {
+ XCTAssertEqual(T( 1), T(words:[1]))
+ XCTAssertEqual(T.one, T(words:[1]))
+
+ for x in T.basket {
+ XCTAssertEqual(x * T.one, x)
+ XCTAssertEqual(T.one * x, x)
+
+ XCTAssertEqual(x / T.one, x)
+ XCTAssertEqual(x % T.one, T.zero)
+
+ if !x.isZero {
+ XCTAssertEqual(x / x, T.one )
+ XCTAssertEqual(x % x, T.zero)
+ }
+ }
+ }
+
+ //=------------------------------------------------------------------------=
+ // MARK: Tests x Int
+ //=------------------------------------------------------------------------=
+
+ func testToInt() {
+ 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() {
+ 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 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() {
+ 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 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() {
+ 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 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() {
+ 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 X))
+ NBKAssertNumbers(from: T(digit: UInt.max), default: T(words:[~0, 0, 0, 0] as X))
+ }
+
+ //=------------------------------------------------------------------------=
+ // MARK: Tests x UInt32
+ //=------------------------------------------------------------------------=
+
+ func testToUInt32() {
+ 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() {
+ 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 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() {
+ NBKAssertNumbers(from: UInt64.min, default: T(words: UInt64.min.words))
+ NBKAssertNumbers(from: UInt64.max, default: T(words: UInt64.max.words))
+ }
+
+ //=------------------------------------------------------------------------=
+ // MARK: Tests x Magnitude
+ //=------------------------------------------------------------------------=
+
+ func testToMagnitude() {
+ 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 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))
+ }
+
+ //=------------------------------------------------------------------------=
+ // 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 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)
+ }
+
+ 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 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() {
+ 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 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
+//*============================================================================*
+
+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)
+}
diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Shifts.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Shifts.swift
new file mode 100644
index 00000000..253495b6
--- /dev/null
+++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Shifts.swift
@@ -0,0 +1,211 @@
+//=----------------------------------------------------------------------------=
+// This source file is part of the Numberick open source project.
+//
+// Copyright (c) 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
+
+private typealias X = [UInt]
+private typealias X64 = [UInt64]
+private typealias X32 = [UInt32]
+
+//*============================================================================*
+// 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 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 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 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 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))
+ }
+
+ //=------------------------------------------------------------------------=
+ // MARK: Tests x Right
+ //=------------------------------------------------------------------------=
+
+ func testBitShiftingRightByBits() {
+ 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 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 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 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 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))
+ }
+
+ //=------------------------------------------------------------------------=
+ // MARK: Tests x Miscellaneous
+ //=------------------------------------------------------------------------=
+
+ func testBitShiftingIsSmart() {
+ 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 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 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 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 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 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 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 X64) >> (UInt.bitWidth + 0), T.zero)
+ XCTAssertEqual(T(x64:[0, 0, 0, 0] as X64) >> (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 (major, minor) = 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 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 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)
+ }
+}
+
+private func NBKAssertShiftRight(
+_ lhs: T, _ rhs: Int, _ result: T,
+file: StaticString = #file, line: UInt = #line) {
+ //=------------------------------------------=
+ let (major, minor) = 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 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 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+Subtraction.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Subtraction.swift
new file mode 100644
index 00000000..8fecfcf3
--- /dev/null
+++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Subtraction.swift
@@ -0,0 +1,180 @@
+//=----------------------------------------------------------------------------=
+// This source file is part of the Numberick open source project.
+//
+// Copyright (c) 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
+
+private typealias X = [UInt]
+private typealias X64 = [UInt64]
+private typealias X32 = [UInt32]
+
+//*============================================================================*
+// 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 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 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 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 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)
+ }
+
+ //=------------------------------------------------------------------------=
+ // 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 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 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 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 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)
+ }
+
+ //=------------------------------------------------------------------------=
+ // 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 precondition(T.isSigned)
+ }
+ //=------------------------------------------=
+ 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 precondition(T.isSigned)
+ }
+ //=------------------------------------------=
+ 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/NBKFlexibleWidth+Text.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Text.swift
new file mode 100644
index 00000000..5e208c91
--- /dev/null
+++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Text.swift
@@ -0,0 +1,1206 @@
+//=----------------------------------------------------------------------------=
+// This source file is part of the Numberick open source project.
+//
+// Copyright (c) 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
+
+private typealias X = [UInt]
+private typealias X64 = [UInt64]
+private typealias X32 = [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
+//*============================================================================*
+
+final class NBKFlexibleWidthTestsOnTextForEachRadixAsUIntXL: XCTestCase {
+
+ typealias T = UIntXL
+
+ //=------------------------------------------------------------------------=
+ // MARK: State
+ //=------------------------------------------------------------------------=
+
+ /// The bit pattern: `0xfffefdfcfbfaf9f8...0706050403020100`.
+ static let ascending = 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])
+
+ /// 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
+ //=------------------------------------------------------------------------=
+
+ 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: ascii.suffix(1))
+ }
+
+ 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
+ //=------------------------------------------------------------------------=
+
+ 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
+ //=------------------------------------------------------------------------=
+
+ func test02() {
+ self.check(Self.ascending, radix: 02, ascii: """
+ 1111111111111110111111011111110011111011111110101111100111111000\
+ 1111011111110110111101011111010011110011111100101111000111110000\
+ 1110111111101110111011011110110011101011111010101110100111101000\
+ 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
+ """)
+
+ 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.ascending, radix: 03, ascii: """
+ 0000000000000000000000000000000000000000000000000001011122001202\
+ 0221000010120021121012122122121210201121000021000121212010111102\
+ 0021022202211121121121221212000020201221122210202201001002201010\
+ 0210001212020121021021121001210100100102120102122200201001202102\
+ 2220222111112021200221211122210111211012110122021212001101101012\
+ 0200211111121022021211100122022012211112112221002121112202200001\
+ 1001122202020122210212021001020200222212112100211020020010002221\
+ 0111000010011011101010021210201220102122102122212202102012220100\
+ 0111020201112002211002010001100110020220111111012101100222010221\
+ 0010122122022201020000102121202021200201200211001212202010110021\
+ 2001010202202101112000210220201111022010220200012021000020111021\
+ 2201012002120201120221122221012002222200122120210000120121000201\
+ 2012211022021200001122102120002110221102210110111021200002120202\
+ 2010012002002102202002201200210100102202220110101222010000222022\
+ 0200112200201010002020101100200110010000000002001202111210200020\
+ 0002120001222001110002220220221011110011011012201210101122122001\
+ 2111021020102211121020000002111101220000201210122212002012102220\
+ 1110200122122112012100001022010221010222101020220010000121012012\
+ 0010010122111111120110221020002211102201221020121121212111201100\
+ 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.ascending, radix: 04, ascii: """
+ 3333333233313330332333223321332033133312331133103303330233013300\
+ 3233323232313230322332223221322032133212321132103203320232013200\
+ 3133313231313130312331223121312031133112311131103103310231013100\
+ 3033303230313030302330223021302030133012301130103003300230013000\
+ 2333233223312330232323222321232023132312231123102303230223012300\
+ 2233223222312230222322222221222022132212221122102203220222012200\
+ 2133213221312130212321222121212021132112211121102103210221012100\
+ 2033203220312030202320222021202020132012201120102003200220012000\
+ 1333133213311330132313221321132013131312131113101303130213011300\
+ 1233123212311230122312221221122012131212121112101203120212011200\
+ 1133113211311130112311221121112011131112111111101103110211011100\
+ 1033103210311030102310221021102010131012101110101003100210011000\
+ 0333033203310330032303220321032003130312031103100303030203010300\
+ 0233023202310230022302220221022002130212021102100203020202010200\
+ 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.ascending, radix: 05, ascii: """
+ 0000000000000101011133132112303401331203113040334201212224114333\
+ 1331210120311431302322401423134214144114302234223323124032013102\
+ 2031310012312133044114114101403342401111141021424131121343010430\
+ 1421121331201040013433442113440322214443111221044313323014144300\
+ 0442200211013021440424413104144331034304433134022344442034220120\
+ 0203022440403030041413132134201411232022143440134130244204021202\
+ 4204221131331321003014044044023244032003434441023101312044413410\
+ 1432032422222011101300422133144024022310244143301333333131313132\
+ 1133101212222113330424040311111134211430243400332404421303012024\
+ 3301033334140414340340314003013204313402213301322411212023034201\
+ 2004134224142103031424130211110200431412144004241140022344304021\
+ 2024422012034413242431014044023232132211032301042413413421403001\
+ 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.ascending, radix: 06, ascii: """
+ 0000000000000000000000000000000000000001345131000552333115344121\
+ 1214023443243324324333122442522233415252532225231130540122100214\
+ 0215244235522514322330122325410454305413105211242412413243515420\
+ 4031415411205525200543134520405500520504130422250301225525122255\
+ 5304444554221253253024400132115002405214044033240245530335422552\
+ 3230145401344324044315001345525133204253014235441544150342233311\
+ 3102525333433242251435152053450224205545410400155320525214003341\
+ 0114031334552553523440515235201104055151034451040431352324424022\
+ 3220325011454332550413335135033252231132320134203510232401355331\
+ 2020345410240441033104340125314154522445134135421334244051303551\
+ 0152420450032004440445510515505305150554300514513545121304233402\
+ 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.ascending, radix: 07, ascii: """
+ 0000000000000000000000000000000000000024653320130023336353601340\
+ 0355512020400135330313404163116323361665214341655231546035543041\
+ 3335061463602013225153316300026621432263543366545536433610205024\
+ 3003025201644424044635410411626456311635136110623401315661102442\
+ 0612331166566162241453601510216450625624416556453020643500526255\
+ 4225530231005403046503563131246643640004650324634650424453045323\
+ 3644226261554166110441022133064452150660600363500515360604100635\
+ 1324126506201641562342434011560236352122640326266120664210323233\
+ 2635011020024026201015103132011050236605005335425545336151120104\
+ 5113112534231011226633116051366211215560241650222456652010032225\
+ 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.ascending, radix: 08, ascii: """
+ 0000000000000000000003777757677476775371761737667537236374570760\
+ 7376735573165752723643477156274470761341701577366735633366554730\
+ 6575332565151722643503176354671462745311621437066134230360540700\
+ 5773727557135672563342675553266454731261541276565332625352524650\
+ 5172324551121642503202374751663446715231461136264531222344510620\
+ 4370721543105612423042074150260440701201400775763727617336474570\
+ 3567316535071562342701573346655432665151320635463126214330460540\
+ 2765713527055532262541272545252424651121240475162324611322444510\
+ 2164310521041502202400771743647416635071160334661523206314430460\
+ 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.ascending, radix: 09, ascii: """
+ 0000000000000000000000000000000000000000000000000000000001148052\
+ 2700350753557855364700701776344207282747547855006657583681032633\
+ 2305521723753171031251258063167286874467627748714735418255041335\
+ 2074453825431826574548707748260131582218725231220885470736203087\
+ 1400313433325365637837878236581014221462732101313226444171328127\
+ 0357828120037766762162405566340761122671460726644263820167006437\
+ 8116252152758716288057670051702165738250048376073842713437602522\
+ 6316207266265071038281335810086820480633066340613100002052453606\
+ 0250186140282683440413565334856174236384536002441800653585065386\
+ 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.ascending, radix: 10, ascii: """
+ 0000000000000000000000032316509077753586139510713445660514514047\
+ 1715800934968659014776021432245405574123404729692361840203777454\
+ 0863807743939745614194869975427379141886998502749960224378577364\
+ 6750786158629119897527698459159582903277348091197804306308450975\
+ 2765897157258671077139706248797954495766510537726453385451362891\
+ 2932640350906509210810910107747204614412263847494852734365334510\
+ 5797020149055603954704727773430317796884279167058635246262041734\
+ 9145786264563977273862044757186140910253489061210709169291375411\
+ 8235589361595220880511748744523688475088623430039909767486996242\
+ 6348425792929710270231641017897005896324246640151098893336183040
+ """)
+
+ self.check(Self.descending, radix: 10, ascii: """
+ 0000000000000000000000000000496993557421161204163243009437446396\
+ 9310896219871662288678253814305983104785527242321753388930859433\
+ 0932284445862203797761045073664730366928240142078351838709159365\
+ 4245305591568630492124408336898055480790220185594414336311305186\
+ 5615046227503033628676752271565095933109248377684204700624161099\
+ 9460398201284924128155924134321292864244193101990764869167297695\
+ 2280785510275422238003732540719940795979897949667308357456420122\
+ 4430197246959039185181992218946191962058782195636399032805876159\
+ 1937103770751746973746316925269816124638211869823911785029642701\
+ 0987117809205722959373004300581599055823946915702512166260047615
+ """)
+ }
+
+ func test11() {
+ self.check(Self.ascending, radix: 11, ascii: """
+ 0000000000000000000000000000000000000000000000010142aa3554859615\
+ 1a9204496a56113782737a0530594194878213854265484228a2873210376102\
+ 298531554729267773485a52aaa2030350391963a7a0a94819183a184061767a\
+ a1664196a92a29124a90906677a6159283540713930a23461662230751976003\
+ 75aa406a38a465902249a525645153a635a40a420899916a90a1749213325274\
+ 6766792593268189a459a23695332111336a2574023146139a17034537465a24\
+ 8967a2a50a37a69914126a360951448575372782095382a02084543002870940\
+ 85532153a572629110a97679073778890291691419a246a95a6016478938298a\
+ 358425533763a551898a379424822a252aa411a696485496052a6871743a226a\
+ 8989647385195622111666334615228957638330392039898693611430034583
+ """)
+
+ self.check(Self.descending, radix: 11, ascii: """
+ 0000000000000000000000000000000000000000000000000000256148a85586\
+ 5197664763a413508459939466315799165a6237763aa375593223a736658a62\
+ 6175a059a7751a78641a7a475619616477939520a087332893696097491542a0\
+ 32141834910a431662128201852a11559a110337a57054a296643718815a7a80\
+ 48479962aa316851a2904aa35279872922828167a735214a27215a821861a384\
+ 99815a0961a3737601288254235997668057936329799a941615802815674803\
+ 25786a7644882756447532455a8a3a35981a95a6909a13497286502490619a17\
+ 1a77888724a210a717362256366a598950960902066765804a99481685943069\
+ 59110458713a51298801a11123297018992a5501098a28a26006692109193391\
+ a16a79092aa045204411a34032199992178aa6827439a86a4a1162545251105a
+ """)
+ }
+
+ func test12() {
+ self.check(Self.ascending, radix: 12, ascii: """
+ 00001b9367266a6039066116339183036aaa985742938485bbb3a46470645276\
+ 569234baa5161788742348681a4a5b25ba61622633b09273b03b9aaa7514aa58\
+ 900baa9a74852ab0219481b21a86a3153bab534868478662a6191b1659b54964\
+ ab9654b6430343071b655848847330017058b16480bb191b0985b8521152b521\
+ 563996041b3a74992b7126029326661485b6632a381a4ab4a820460396996731\
+ 1955a0b949642455a94aa27512b620a30373879b06207879078319104b12b4b9\
+ b2ba94a962459429a746627b83089334822b767922152b60a66b497450a07244\
+ b845b1558994981851b953005363a121880435bb95b546ab1558447212026a12\
+ 954b5492aa0367a34a0a961a50ba9a07b6279269932a4957a644a2a3a3920540
+ """)
+
+ self.check(Self.descending, radix: 12, ascii: """
+ 00000000076b918968899b991b3a0b667713391937b3bb902301ab6145a77307\
+ 44a2b60b437594576b487310178a094b5808bb63727175a001311367a6b15b60\
+ a32b64505a7714b4726537456122412432166973a068b703039439a92559b5b6\
+ 5b0a431247a475b7b73780620429b5646b5980809950201652a5a17013a53004\
+ 9278712658818566b19311073b683072337992902a246221355872288749aa1a\
+ 8b591341aaba72b3b98a0799b919741387205aa722a5a05582862a92506ba89b\
+ a307a1a27768ba2575796b18278b74a250523680499a1a60492b1910ba644782\
+ 6784970931559000310546aba16a418a4827544331254b700900bb405448b2a4\
+ 4b093020088bb2535b47963b7b44608a93421b127bb07b00246477a7b8115053
+ """)
+ }
+
+ func test13() {
+ self.check(Self.ascending, radix: 13, ascii: """
+ 000000000000000000000031cb7486735908c0144bc1018ac182c82a930a12ca\
+ 74aa7825455c0218a1479ca12843cb94baa0938378c1c8384b19b34340a64b01\
+ 4c927b86217b9a059379c40089c4314b035b5c702c8371c7c80104445bc99b56\
+ 057a91abc9acb1bc37950647b72045a5a647587b15c865bb75c2380191829a66\
+ 04a1184400818b29b9513b8c59490494649a18069b449c472c2366c76a2ca852\
+ 5096cc27207409700b2a636668139b428455c9a6ac67131b4589833577743c3a\
+ 7a091a293275c628b8a06625cb2a15734b58b3a57163a48014a7a5c277499614\
+ 79955285c36bc06b629543773288158648aa581166a042608899014254840857\
+ 15273b93212a908443abc9abc7929ba5810113319924a7468970130052605289
+ """)
+
+ self.check(Self.descending, radix: 13, ascii: """
+ 000000000000000000000000001500b062c1244a5ca682353200a96937353c93\
+ 73069a0b203a0697c45513ab9487a7205bb57cc5c425a5c032a2474a01bc3aa7\
+ 7990173264abb8b83613121b5528156c4048b81422ac426709bccc65a508b4cb\
+ 132b977345a9202198a9c32785c770890b69240b96ca5b132b8b9b817411a933\
+ 4b72342699707c6b5c874c92ab31903c758988696cca9690145b772b03085bc3\
+ 169a4bc0c135baab68558c0798367ba3406b38007b90c8885160454934686c89\
+ 4cb56950cba1887a6a20b95b1c99c6b275100512542006c230c4193161a27012\
+ 95b489091b11513a7b6aa93691a756cb65c77ca95668543158b357ca8ab95a44\
+ a00348774316caaac9b21502a3302702c852a8bb56b24b5400628a24276750bc
+ """)
+ }
+
+ func test14() {
+ self.check(Self.ascending, radix: 14, ascii: """
+ 00000000000000000000000000000000000000ad0745312ac38003406c77772a\
+ c5d337dc56d71b0120a8035c347cd412ba206c7a19b3638983ad6c7dac8866db\
+ ad3165c94d93a13248c199cda6773520749b9430c797c2bb0d8ca867ba5a063b\
+ 83d226939c0cbd8ab945b687021c84a90d7ba0d68cd37869a55260d1d780666b\
+ 0b6a3a99600cd5b1d80b84cc30bd74702723a1126cbdb5a42c285669194da766\
+ c63c8d6d1aad3cc15dda115b2445580577049b2b7b818a839a3d0713a25586d3\
+ 109b2a74bb9cb5947074d06003a7d8559a8ab638c511c84c158d5c7033b7385d\
+ 777b7d6c35b83b7c4a497aa9b859dc77b943581b1799d547b62548548666b945\
+ 8d240951c39596c82589a5602b65a7c3b356a46269456953341674c2567b81c4
+ """)
+
+ self.check(Self.descending, radix: 14, ascii: """
+ 000000000000000000000000000000000000000000665b20da8c012072742a9c\
+ a5cd039c351d1954c650a78d38b82408a4277196aba9762211d09d8cd8b0d860\
+ 6a3a66d5813834054475593121b4b9b0413200c31c0a2b0dba384d9032706145\
+ d308b314144dacdd01dd8587897b13064dbc82a519ca81a734516c2298c2880a\
+ 78c76978d6386d10859b60bb745899c01badadda1999d5b791193187c567c0a8\
+ 32a2abc1cd43d1c3560bba8d56b67cab62bcd597b554a3d9b2ac51adc018d6cc\
+ 80c0126414d43729179abd98859db7a875258b438c6b3a2a285d3786ddb0ad49\
+ 5ba3add41a36735295c13053243d4a14dd747ac3353a4dd77b9314a9c9a79560\
+ 6101643ad12c8242bac710666c8139696c146dd4da84974da56d48c94dbb007d
+ """)
+ }
+
+ func test15() {
+ self.check(Self.ascending, radix: 15, ascii: """
+ 0000000000000000000000000000000000000000000000000001adcc42d77564\
+ 2e8d25576598e679706b39b634284eb4323514682a6a176bc422a0b453010958\
+ 11db137066d571a2b91ec47eb29e5870c08bb8759a29eae1e60de477c04c2c97\
+ a272774aaa2573b20764ea2a18c62d7c3660ec0387a7b658d71e5d9dc14245d0\
+ 163d05e294dac37d9a00339a9b41ee29b3c604d4350739ee6c2617a77c226325\
+ 8d6ca4cd40eb15b65a6341963a35035c8441616e6c21e1ec9d1bd1e3ed0a7c5b\
+ 349c68802a1365081776371784a3c99b4ab7774eaa850176c7e9d1c8cda75827\
+ 5e4ab4757030038b383714cd32c87c560ab2ecb8d102219ec16d0616544bcb2b\
+ 651732d918a54ee364a155a488725ac7ce563e994b90e86e485ad50d52e0aab0
+ """)
+
+ self.check(Self.descending, radix: 15, ascii: """
+ 0000000000000000000000000000000000000000000000000000000152b2d1a6\
+ b8a8c0121657243d73087ce18b51dc75b4205004346095046c5560a817deba1c\
+ d4a5a3105bc83eb096390746c90c20224a8317a34198e7cb73c7e970c60b5c74\
+ 6a7d68177d9dd4e2c75c15d13b1646d63a900d38b4dc5286319dbb87c4a62e54\
+ bd6d6d4d86509dd7036a27ab6d0bb6807483e90ebc70d57282906edbb53123b3\
+ 9129135e549279d96ae4b2a1c7147cc03e4b73a279854b5d2a009b6de5301ad4\
+ 059d1ae0989433c36c9bbee5a3645c426e40848de409cd82d902da7de45c0bb2\
+ ab154e42536bca71849298d982c69e34e86a6a8b20990845809947073d753ba4\
+ 370db27a2d22de47e12ab6e298b283e65b3d8b42e273650b315020dc1aa22960
+ """)
+ }
+
+ func test16() {
+ self.check(Self.ascending, radix: 16, ascii: """
+ fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e0\
+ dfdedddcdbdad9d8d7d6d5d4d3d2d1d0cfcecdcccbcac9c8c7c6c5c4c3c2c1c0\
+ bfbebdbcbbbab9b8b7b6b5b4b3b2b1b0afaeadacabaaa9a8a7a6a5a4a3a2a1a0\
+ 9f9e9d9c9b9a999897969594939291908f8e8d8c8b8a89888786858483828180\
+ 7f7e7d7c7b7a797877767574737271706f6e6d6c6b6a69686766656463626160\
+ 5f5e5d5c5b5a595857565554535251504f4e4d4c4b4a49484746454443424140\
+ 3f3e3d3c3b3a393837363534333231302f2e2d2c2b2a29282726252423222120\
+ 1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100
+ """)
+
+ self.check(Self.descending, radix: 16, ascii: """
+ 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f\
+ 202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f\
+ 404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f\
+ 606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f\
+ 808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f\
+ a0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebf\
+ c0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedf\
+ e0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff
+ """)
+ }
+
+ func test17() {
+ self.check(Self.ascending, radix: 17, ascii: """
+ 0000000000124b16c3g69bbbag36b77367c8366826a1260aafe896c41e5bebd6\
+ eff1edf76b5c850269d547g2993fg898a7eg88g8db235g6c407d4898b5a17d05\
+ 9g1d0fc9bgf991cagd36gae0bag2bg730e02b8265dg2e55825g7cdfe2fgedcg1\
+ ba3dcc62916e6d11ggf6c160e48154efaf86ce618584dba7d1049ge226f62945\
+ cgde056dffgb718cb2211bg5g72g77d5agd7e6b055e6b4ge71gg2e56be45c585\
+ e31a98e65adc1c4560b001595gee6a7ec3cdgfb6248a0e351c5fa7gd40bc4afd\
+ 2cddf99e175db6fgf31545e48gfb055b4g39cca53b5a97f743922d73b7afb7d7\
+ 4928154d92b20gg7992e38cb96c1dd4bea7c7728fgb1127e0e47469feag585g0
+ """)
+
+ self.check(Self.descending, radix: 17, ascii: """
+ 0000000000000017ce9c05e067e38a806859ca9f32f4efb5bbc0b1443434a7fe\
+ 11f6g3f2g2a7bd55278c6b700309c5bge3dead4e678ab3f9a664703f66f716cg\
+ 5b0f53e1655cc321011f1bb33625b5d44580930a9687c4b2926aa7c1gcbc4g63\
+ 7c70abfcb0f4bdcfcf7174c446a2417b77512bg9321849db9e8d78e616gd76c8\
+ bad838eb8085deb36c92839aee7569412499e53b92427c236dce21aga885bd0d\
+ 67ecca7c6dgcdb3bdeb3569gg55a7age3ddb6gf122b89bafce283776af88gd6b\
+ 63c8a6b7ab753cfd54cacgbd6cggf6fc12a29dc712bf067e0c0962d1f0e95abc\
+ 1aa0038be0af74bb752866508e5b7463abfe155ac0e5a17f758733fa2f7c0fg0
+ """)
+ }
+
+ func test18() {
+ self.check(Self.ascending, radix: 18, ascii: """
+ 0000000000000000000018bga551hha58097eef06aa64bdbh0172b1dcf80417e\
+ g30bdd9b1ac2bf53e416fgc92ef713dh5gfc36gcfa8961d4c4eef393d8c95hc4\
+ 0bf67b02ag05e7g833b3g6372d4b45169d4693ee6h64h53h6f9c34105cchd1b7\
+ 85h609326e8b38343d11a48cebcd7gd402h9d1gb4d9g74f33h1b6d5d47bd9bcf\
+ h477eb91g0dd00f428942a478b32bb0eeddb0ch9822e66dbfd615bg4598h7eca\
+ 87f81ade8268f1c0fed0b0bh607g9dff3800a9ed58c0036d0258393463e561f1\
+ 96ag9g9d2af8495ge2bg3d961a7c04gf931h399da9f8g0d7540b9458fag6d4g1\
+ 85055ae5915ch6e98ab88g522b1cb92872cah62f92aa4c75ddg37ed0e80g746c
+ """)
+
+ self.check(Self.descending, radix: 18, ascii: """
+ 000000000000000000000000270e4hdf6dde52265g40e1282b6aa8168f0963da\
+ a204h4758c9e66b1gf0d7829ad10gch037cbfh4ba69ce6ac12hbe8hf78gh56ac\
+ 0hbfa1dgca543f87g84hbf49degbe3h24c31bab01fe5b1be1f62c93866gecd28\
+ 4782bgdb95a257g94d5c7a8d8afhgb272aeg5g0gf9153d45b4e26dfa841fe13b\
+ a8991ead426ffdc8h73089bfc86fc703hf408ah1bg4haed5595fb6b2b80fh5e3\
+ dc0d9ghf5b82592g56773bef87fc7bhgafdf4208dbf79h84gh3e0bdfa5cdh664\
+ 7a4e6a1cb51c653ae1ad97fg64c170a59120f1a703bb1a0c2g6gf83304c3d0g4\
+ 2af3g30d227eegf3gfb234cdfh59bcgb73ehh1g6hbfeca767501ge43584gfcf9
+ """)
+ }
+
+ func test19() {
+ self.check(Self.ascending, radix: 19, ascii: """
+ 0000000000000000000000000000017g2f692gg45a5gdf57gcg2g07g4h04bhfa\
+ f8c01abeh9d0da94477aa600ddg25953cbh2363a71ghfdehi84ce7782ba4h3i0\
+ 3a3822ff9dg3hfh8h61cf785057g74ea5c4821g6ii4h020eif1992fihdh9hedf\
+ 020e2dfi21cii026d675dh1819abb0h2bd231egc2h34ei7egf3f4fg2dh0c7422\
+ a26c52hgfe1cih2a6ahadie59ae8082c8e0ib75a3h9gdc10bh4d8969b7h57i38\
+ 2fb4806i8829h9591ch498hhc7b7d4c9f4d0gb28g72419a2298b3fa9731a32dc\
+ d312cai90h6fi0g8401c1561f97gg2fia9822h6575ab83id41bab5cgbgihdaee\
+ 7aib31f1gah964c8076a4a1c91ghb0bg7hb407f2h52e28c213d98b3156g85i51
+ """)
+
+ self.check(Self.descending, radix: 19, ascii: """
+ 0000000000000000000000000000000002ff85ged5dcd5040bbea5e4dca9f325\
+ 2d50797cg4a534i759233di0e13d9c05ic161ced73c61bf5i1b7eg831g16f2b3\
+ 5b86g899a83fh5g0ac2id610ieidih0f571cf29dc56f8h812aggi0ga4f65hea6\
+ 29ed2c3546e0f0269eh5ihae73d8a56hh3aa38bbf5dh33230cg394hdaa40ga3f\
+ 6ii1baa7ag5acb1af0f2fb9cd681c8dc123ahh93cicii5f48c01558eg8gbf6c4\
+ 771h4cb4fi896h5b28fgb5gh9b06i28dgfea807g01hh3c98dai86bg2aghi4f46\
+ 61d2gc1b6eh2ahhd2dhdd3f0f0eae020hg28ae15bi58c6993f4b1310g9744aef\
+ 101f49g24d393ah000ag8ifecbf05ba1de4977e694c9c90497cf4c70dh8caa34
+ """)
+ }
+
+ func test20() {
+ self.check(Self.ascending, radix: 20, ascii: """
+ 00000000000000000000000000000000000000d5050cagd94ghbfad415d73775\
+ 385hih85hd9d80ec925gehjg1j04f2hhiahd169328ai8099750j9jf64g3eg281\
+ 863fi1cihc58jdec239iea6i88ci5640be2eddf81i0fj3005gib3ja486927438\
+ 6b499cdjj20f29d033023fa1f790bd472c7654g8b4eia3caf829di82457dgd8e\
+ f03ch599i30j2bi0f383j43c59035c93d36g7h833ce0hd7555c378hh728j723b\
+ 71j23d885j99j36eb72703a83a5418h5ha0bcai1f6724dabd294104ieff49f37\
+ ed043626hj5g7eccjjd76chd29g1a2520a88j370bcgac00a5j4h24dc168jgc16\
+ 431i8ced8d553fa0jg40cd577ich5ce5a93e8i8jdfa192c27390cff0a87b2hc0
+ """)
+
+ self.check(Self.descending, radix: 20, ascii: """
+ 000000000000000000000000000000000000000001cc1j30fcdbj1dgc663fbjb\
+ 546f35de96ii52h53cd61cg1i4efi3e42idj30cebgf2b4j64971agf1a9d3fc58\
+ 9beg7iaf27741i965c2ccbi4bcahf7hf3c6i8j5974a570gi9b4gfci570abd1b1\
+ ijij319a541dej23a5ce69gea7ge595c15gca2h75j6hc142b0ee47658d4gfe0e\
+ ej41j5hca7b66iji50ifhchb9aji636ifcig69h9fehce48206a1ae3hbfd52j39\
+ d9ad795jifief05d1ebf1387cfi2cef9cab12je6hb4g989971j0cjjg3f06eg55\
+ 2f0h1370j335023gie3hd23a81c88ea6h1f7ega4e8373c24jc3fed84ig1d4d8b\
+ cbee83a9aah41b143dj910b9i1fd1chcf4278j5ic6j8c1dgg4i68d919hg55j0f
+ """)
+ }
+
+ func test21() {
+ self.check(Self.ascending, radix: 21, ascii: """
+ 00000000000000000000000000000000000000000000025c52fbheeggjg8507d\
+ fje9hf92hjbbficeaf8fi1634i6dbc8ccc4bci9a754b580283fibjbkkbdg8080\
+ 26g8e9h734gjj5547ek5hdafj86jab9kf90k9gg6ijiad7415f2eecba9k15891i\
+ i929h5478643id40cfhfj51737ga9ggh2281a726a517daefbjafa83kegkgc6gg\
+ e2a12973961j9d6ee925i231ja10046cka7j1ckg1391g5h35bj286a0ia14k0d3\
+ 3b6c7bi2278fffj4674h6bcjhhi4bg0f65h5h36878023282j9jc9c131di2ake8\
+ ka3geadbckebhk979843g6ki6hbkh3a5h4k262h0g6f89k4896gk6aj93g8gje63\
+ 409g09916bb8e39hi5ci6djciki7hbd192de689hfjcab3ca39ie0fhg21ea33ji
+ """)
+
+ self.check(Self.descending, radix: 21, ascii: """
+ 00000000000000000000000000000000000000000000000006g6de0ai8b68b3i\
+ c5fjhf6jbg4j4j67h89ffkhead04h99kb290k718afgj8j6jf2f77e57cch210gd\
+ jf3f5h95kb3gd0f1jb06d307d06ha0ej2dge91ag1h756eahcabkjdfijd2d2a6c\
+ 2144fa9173b69684gkkf8d0c31j3a5k5kab56h975172k04kfhf2h1d0ibb21kc9\
+ 09ca372586ad9fghj3dk931f3bk76ca395ikf6g702631k63ke56hbhji67ib077\
+ h4883ghb1j6371j6e51e21de93db7ka84ae00d8k9c7a486kehbe572d246d3b1g\
+ 601jjhe1e4e9c056agif5gbd928b9g469956g61d975f65kdbacjb4b360ggchej\
+ 7cjb53cgag999edk1gd63eegh35bj1jk3g266052f70eei1c7h15d5ka51k0k4j6
+ """)
+ }
+
+ func test22() {
+ self.check(Self.ascending, radix: 22, ascii: """
+ 000000000000000000000000000000000000000000000000000023icle03ja5d\
+ 3hla1053987fc3i93924f5g21bledal5817e1ld8kd7hkl5ic03k8ji34bh740hf\
+ jgj2cald12k4b36b2ffd5j09eej95024514ig2db9h3j4i19efbk269k785alk7g\
+ hkd6fkf5e6804di2ek2gajf4j3db0l7cgi80jc1j68cib7211ada3616de8628ae\
+ k8g9bka30fbe1ahde1c036ch92bckdg6kgg858b214i8518e404b29682a897hf4\
+ 3ibdi74gi642k7k14d5aj407j3agk5k1h04dfllc976ahdljcf64j18f14460hhd\
+ 4g6ikd7kh496eij9llkeif94kf6g0eg73k6i5226fd2i22ee11hjddj7ah0cij5j\
+ kjklak3374ei0e8e0h32e55hef6d1e14b7gd05cgg9fii44kkckgd9fedh07h19e
+ """)
+
+ self.check(Self.descending, radix: 22, ascii: """
+ 000000000000000000000000000000000000000000000000000000007i81bj9f\
+ d3800a8d8khk24l27ebd4eli42akghk19ac6hdg78eka61il30flg9alg1eieib3\
+ 1d3jc7b4h690f22i4c186gh06950f3l50ldche6c6e86je71j81625hbi34jalgk\
+ 6gbf893f216j93cb8cee3778elak46h23g5dcfi09k99cje2icijk1bl5f5gk90f\
+ 792ejgbd93c7342chjlhl3gakh60bcg3i97k56bh6ladld8g4fcb7e96db32bclh\
+ i59769iaf9f5dg655dh2bcia0i7a7kl10bbh4l4563hkfhh1kkb9if5k9bk8c51g\
+ 95kge1kch27jjfea8d37acg24ei5i0fafia4ga5lh2klibakg5kld8eljd3ciebc\
+ 32i1bhkca7j1i4g5764lj4da091flf43j8ha4ec13j04abghh88cc8egki99f5dl
+ """)
+ }
+
+ func test23() {
+ self.check(Self.ascending, radix: 23, ascii: """
+ 00000000000000000000000000000000000000000000000000000000000a4bj8\
+ bale0d596ej9c12m593176b2m0lj5jdelhj11f35ffkh37ja5c4ff45hcffi725e\
+ 8cll095fbda26h4ab2mif00639jgmk0429bfl60a8j6fih25al8c04m9e9kgk9gf\
+ j6lhf2h8bk6hel39dh1ebb5ik04f4egcfghihj2idmg2ch783i026fmmgj2e2kf6\
+ 85g0lkakj0ch8j0c2fel0ffg1k5eg0k0deimgfk4llii0i67g3ghd3ghmehkbbm8\
+ 32hael03fh143mk2ebeek17mjk7513c1ff98dmhfg12khmfff1077jl6cgg83085\
+ 7ce5lmh42bjmd10madl9m2m58kme472e3a8j79lj43d65m84be21l06h1h8hhd2f\
+ 7c13423b97i3b63d627ig0hg3mh0406dem3i77jfifj76ade42d66f48i5cmkg4l
+ """)
+
+ self.check(Self.descending, radix: 23, ascii: """
+ 000000000000000000000000000000000000000000000000000000000000001k\
+ k65fglbgdjki6jld3a8l24hf44hgikie82g6g326eam4g7m05593jg194ell5gl7\
+ 9l9c1imblh904ggjegb50l86kjf86222lk342kac5h1kc2ii351hj8ll726g95fh\
+ 0dckbdjg1mc045iif4gj44llj2l5g1chb7c2lm2m28a28kfci4kme5jmld5ie917\
+ 603f5g8c5fjgd844339c82mjfi1113f71m2f7ebm524d6e35j7c2jbmefkiad36l\
+ a65ji1lm3le51ia8k5h2am2fi0ahc59g79ek3515be0a7f4788baejfcaf1da535\
+ 3ifdl69b4lkim95fm03b064074aa3669cce3463128920f7lih06e7d0hk9ed3h1\
+ ma8251l5l6j6lf8557gk2dgh38h2b83ih6b0d594047g0mb9ik48lj602k7350h5
+ """)
+ }
+
+ func test24() {
+ self.check(Self.ascending, radix: 24, ascii: """
+ 08ehhcaace58bei72i8ja72f5hjbgi07b6j65idm59bb5ni8eji1f6lc5g4d6h4g\
+ j19gm0ke7lb5d34abbg45fdahn43hmb9gdmh2bn8g529al6jn540id9cjhle26hl\
+ i7fm2bmcc1kj35583j173maele2kn5334k1gbm8kcajb2di0ff1hi1ad44adld34\
+ a0a32n07mgij7k607949577b62d1c0abfina2jck0l8n1m2mh7ih6mh67dmc2ca4\
+ 58ihh733h1mbna818ifeh4b7im6j3gfchhfkj2jkcfd61e1i8inkliigg5f49967\
+ 7c1dd7b2nidi934nc3n0k1gj3dj2gg4g22lhg6nm1720kd1imbmf7ia45039bhn5\
+ 3lhc76memd39mlh4gbcim3a4n6a3fg86hgk1i29091ccj2md7h5gf2m92eg9l180
+ """)
+
+ self.check(Self.descending, radix: 24, ascii: """
+ 00001jmkd0lc7da2k8135ecji7m7k0m7liie7778n9mkj5207l6ma5m1m620jl4c\
+ dkffmna0cfh56al9e6j5fh123bm7e905c825ndccabdmcj5582iedi5k04kg70a8\
+ j4i11addmi4m57ag8ke9bnh0b0475fcn1k7g3c684mg1l95i7b07ke3n2i781gj4\
+ n074501j3dg5ibmad4bii9ab3afjad8f54gb2ccm39ci7mgen0jdgichm0fc94ij\
+ jb122182hdldk1dgghn3i37fmbkd6je22e67434a2g7dk303hhdhd73gckndk6jf\
+ 9lhnlb2c23gc5fe2ghl1akdn8bghdlaifln67a2aamb76a1gff2l9ljgib5ekf20\
+ a186gcecc5mf90ha3kfm52847lji8hfgmdbai334ndaflkj89l5g01ifgbmck32f
+ """)
+ }
+
+ func test25() {
+ self.check(Self.ascending, radix: 25, ascii: """
+ 0000001116i8b7fj1i736fkim1bce6ni8gb1ag9gfdck9d8m99l9fcjcid7kh1g2\
+ agg07gbi4l96l1kimk6695bmlg78n14f9b78ga5k1jiob8o3cbon67b4n8hf99n0\
+ 4ma261fbo4elg49ng3n4ngj2dooajc1a232ekkff4988bja96dac9jk8lfem4272\
+ m4c6gi8b0f94ko2ho3a3nol2g1gaolj59h3ecca6580mbi9ke2d5elnf8iiggggh\
+ 6i577cb8i4e43666jb9fej0ie4m831aei13ij949j3kgk31h4gj2bi1he6bad3m1\
+ a48me9b339e826620n979k4e6k2dofkbaema73o8eeg1ko2hh8c63d14e8ljbkf1\
+ 347nai6g70k7oh7l7acaniafne0ik28n8ecgjck4mk603bci1c1j25jghh2ffhlf
+ """)
+
+ self.check(Self.descending, radix: 25, ascii: """
+ 000000000066cal0nadf16a8j535k0nfnlc93ce4nic5bo47d6m6gndjh4nl8ckd\
+ m28hg48f0d799n3b0f4g40mblf6iohkc033gh684m51lf9aieec9cj4e3ldcmd6m\
+ ikbk66g406g0mm2k4c9n9bholcjn657m542glj23i428d00no9ncoc0h9466fd2h\
+ gijgfd79l573699jhbo824adg0o2anedcn994l294l09a6bb4gf432nhdohd5iid\
+ fek6f83ogoan06chji1m3cehnj8kkd7dj6kc3c11fmdkdkmc0kng60f1hn86bafi\
+ obcc17777do66201d0fiki8168odog3b2743db1d8j8n7ni1o5c33e5nd1egjgcg\
+ 2cm13m1l725a1kki4mh5511hhoaid9l3com82adk72eb3b987ef26lj8i800i14f
+ """)
+ }
+
+ func test26() {
+ self.check(Self.ascending, radix: 26, ascii: """
+ 0000000000009ng7mg5k5b246fh6fejejo9g6je8amap102c3k88e96fdk7bbl0d\
+ l937l2ii3hf448chk6imkjd827pek6j6f3k1gjcb2nbgmeg2639a3ldlgmd14ek2\
+ ng6eh4194l1hp8dli4gl0k2m2lpna181bo90dfm7fh45jg1d5ijc591a754k6p28\
+ bkkojapjhi24fj9p3paf7fkle9j67mefn6h47hoec2lpmcdg96po0eenja8b1p8h\
+ 34c36nckbl597ah5g424apke4h56kd2fho6nmph6cc66d32fhkg6944gk0e0i3og\
+ lhjoo6ncaha3a7b9pdg14b12hl18ap0aga2b9eil7ebbalj1j8hb69g1g1nkb1ln\
+ h5hgimc7k353o0im2kikcfcpi6m7mi6po47d3o6h868aoef5nb652fm0979373nm
+ """)
+
+ self.check(Self.descending, radix: 26, ascii: """
+ 0000000000000002hge9dae3h4nj1m0oh96867me28a0b3cdd369i3aghejk8ngh\
+ ih3k7ikdi8bn7m8dgo61mp9363242dnnjk312npkjg86h066mhodcgddhf7mg4kb\
+ gl8i0o83gkapdl368765eggd64kckmpfoi7e1akc1a05dene3lg901o8g19040e5\
+ cjm2iokb5di020cgg0f66fh03l401gd1kgj0k7oc20lkf16pdf4514g81i56bd4p\
+ j488gghi26p6nd9g3fgjl04fj6kagbg55k79k0jlppiefaacb68jh56oiaeh8jhj\
+ lkm1nf88n6alama7187pg8gbn7iom3da54a1lkonoa08j4bh14gk496bfhf7bea4\
+ a60n43hp2ifl6m8ib8honnmafchinij6g2l7h4l72f28h0ck226obh7cmc2gid5p
+ """)
+ }
+
+ func test27() {
+ self.check(Self.ascending, radix: 27, ascii: """
+ 00000000000000000aeifkl0aimlgppnb4l0l1nfad678kmgggpn06jphlkj12j3\
+ 70gk5bbe9g333n3no69flqkpdfn2ndqaecgaonf443fimdg87m9h85meep2geki1\
+ 9eok5p7k9b68pml7b210qac09cd39nb5j7p7qh76hj0d6je2m2319c6odd5a9q3p\
+ 15nkob03nfkf6f79goj42f3b874f2bk4cobk0fl0jcnj52fjfphp52qihfl0fg0j\
+ jpbkf0eln0m8cp44bf0n6o9f6786852a188ja5o92ooieij326a9ic30021kdli6\
+ 0n0hid0q88ad1aaog3enigclj8dli07d5i25aqf6g8jcihhe59183p3qa6o30g55\
+ 115mde48b0pcohb5egmfc21nmi8gj5j1j4mphnigfdlg1g3pb1fga06i10mb6cpc
+ """)
+
+ self.check(Self.descending, radix: 27, ascii: """
+ 00000000000000000000354kbj1913ok2akegiac121jfliqpemefhd28gnpo667\
+ gdo5fo8d6dko4a9idg99g8j60g2e9mken2h9eknnbnhq8ohd0ohjl9pm7ob3e84d\
+ 5bf9d65lmofkqo893e67lc9llqmj5e2492ddq56k7bl8fdi6cb54lc0mi3o2adfa\
+ hcob50kj5n4dghjjggm8jn8kh5daq3l3cafbdfb7704jnoad8lfkm51b8paapqid\
+ 3a22804o7kiba2c3p3bp7e6l9m7957k327o6dp6ejd45mgol72nle9ljfd3p8f1n\
+ hm367eqg328d1hifqi7a34pbhmce1fff8k385pa81e3ddaol4q53617gjhj57pll\
+ m1aqnhk27m5c780qjchbbah8j5iebfea81a0nnk249c80digj7b0ep25lqppeqj9
+ """)
+ }
+
+ func test28() {
+ self.check(Self.ascending, radix: 28, ascii: """
+ 00000000000000000000011940hqcnpe5i8ehn6cf9c2f0qdd011eaflded1422e\
+ 75634p2b6b92chjhi5hhj17dg9o0bbn24c2anpjq2fdikdqfgnqp0em6ornlbkm4\
+ 4kajr457ir7f5mnrn5kaoo5o6m34f61gp10ra4g47pk8457hn4m0cpmqe8i6bm5g\
+ 1pprale858hm4bp4j20a1pof3dco6f09dpmo2f56ld770b761k5k3e9min8i2la8\
+ 9h90bi08n24m3pi37oiojg5pphr13mq8kdd4hfcnd8lmccraap804jjrim5m2qb9\
+ 2mnq4r96h4br824079ppojp20nrkmn6jra3gnrrip79ipp2b5d2dd239reenhfib\
+ il1on3k9nncfhqfm0obdc9o3a1f6ilq96k8d1ikpmb0e3epn148mhjcoe78rnld4
+ """)
+
+ self.check(Self.descending, radix: 28, ascii: """
+ 00000000000000000000000009p61rcc333fehpommgkqa37omq8oirgng1rj56b\
+ mr6qqjiodrcom1ok5boqe8comk6prpdpj3bcg2j15519ec3oarm25994fj709b6p\
+ rfbgpkdegi8nkk90fhejri2m6bcp332rnj04ghn6i9r6l1hqrj5do0gkp3r5c6gi\
+ gchhkhimhcni94m682j26rkgj84356eg2jf66155q0d7nqorn8kpoi6offn1inch\
+ 5b1facgrbe7h1bmm90d1pih2o3i8kjg1mlb1b7h57b2bg4gpl6ppfl5cn8c0bkkr\
+ nbdg0k144dh8gp5n11een6585k8169b0i7a61p8d7q3f5f2e2dj190ge5f255487\
+ 1hah1c54arhc5nlmngnlnio897p1f9kpd2a076k1kqqp4ld75h78j4qn0448fl3r
+ """)
+ }
+
+ func test29() {
+ self.check(Self.ascending, radix: 29, ascii: """
+ 000000000000000000000000006qgf3bdirlm095h66i56k8k9p11hol00og9a39\
+ 3mqh7jjofh6bk49k4pbo044bb7k05ppq1jjo8j2kqe8iagllm50r6cdsafdlh915\
+ k3iip9mns1o1o0rkaagpab2p8c50gd2cfc2gki5n448pjdsa5i6hsee9s2rp1n01\
+ fa1grb4914df5l5l6e9ag8g511og0203m9hncndck52s220rb2f2bpng9leg4mbo\
+ qpm0m9k203lrc9mg6fmg8bnmql4fnq3loe2q5nebe4aen0p5nmfadh9nfm8gf612\
+ jle8mfq7c1712cgmfiiq0li30gbn883sch73j4ga098h64fqe3s7322rgjh335kp\
+ 5csoq4lqelgl4bjom4p15apc6aakaqi1h1lijpmcdogappk3l0caksrcscf2b6cd
+ """)
+
+ self.check(Self.descending, radix: 29, ascii: """
+ 000000000000000000000000000002h6iifm5gl740qqhok7oeklc0kdhdlepf80\
+ ifsan6o6jndhpqshgr16le6d7c58k8i5noh3p632c95df1gdsi1s56gsfoqeali9\
+ djgp50kgedfaa9jocfa4qa1caq9lcso27jn7rc63deilrksmjgmreja47r3a9nhh\
+ 3boffpbh48npgmsdhl742oknsqo00kdan8qcffh2leb68h9b4049jnk98g5dnls0\
+ rhlab9qp643g7f4gp2aj37b18kikrmnl0ifcardkj8kicge9on49j21dd3lkndqp\
+ 6im0m33dp5e3h0ls17aqieg24lqd39ng4sj0j74k17o6dj65ambc12c2rap1lms1\
+ bonlcs0gii9mgbj7fglh9c7979pdkj0273fd05hj8khnamjcp37l1smagrp4obp2
+ """)
+ }
+
+ func test30() {
+ self.check(Self.ascending, radix: 30, ascii: """
+ 0000000000000000000000000000003gc906ob8d00p50qelnf8ma3n5p9phlaqa\
+ csshfcol0gn470qt5shaa9prondsstf5jldjq1mjbj8droha6pganj1pnnkqhskb\
+ qjd5k8b2lq7dhb3a0n6kmh0k4880q63tr6dpe3a1d7rr5p85pjirlar50b1tk9ht\
+ ca9d5fpimnb4po0qombqsms8rb4re1rf41a629hbt9akhtn9ndoo2lgelmq0johi\
+ ca565dm8o566k05eq1mg4d0f69rjcl9jlqi5jojeltt6a23b2pp9gkalr40o97o7\
+ pgktp83180hdp6q0pfbhme70qi2apg738m324dao0ro0ak55q9e88aan0qre4r81\
+ r76f8rfcca39dp5o34teq57r5jpl56aql1imhq4l9dmcom2ebtk25ddgth4jlss0
+ """)
+
+ self.check(Self.descending, radix: 30, ascii: """
+ 0000000000000000000000000000000001e5g8keo886n2mmihcs1soq5pk1fqm3\
+ 6hipgmbprhtgnan7m5eogj51a2ebna097ttt1g49ns3i5tc5s3mhpadssjpm8ser\
+ 4ma5n1ldsb70or5k4eg1n1di6cnc0j8as5sqsihc76s33b3aask0k1j4j3gn7ck3\
+ 6d9l5n01h8872ddh6scqpqbggshj3sap3mdo97nllpefcr8cil8b26ldh7455lap\
+ 40o98i88mcr6heib67chn6hojt95iqf59trsesre3t4idsqktedm1b3qem1ifoas\
+ 1ltgcg03765i7no0isqanh36t6700mh5cedb5s37m2rrs0ht7ef00ibg8c53a9b9\
+ g4fgdo0363shp7g6e6d9i4286ng1j4nbe25k8pf6clt8251rqfsdl9q6gg33qhaf
+ """)
+ }
+
+ func test31() {
+ self.check(Self.ascending, radix: 31, ascii: """
+ 00000000000000000000000000000000003o1q4rle1mom6e5aqbf2gi8q7r00tp\
+ ktgt1mu2mfrkrhpo94lg60q0i8el6jk98q2k76nnh40nodjtolp3ps6m01lf72g5\
+ qnhpnukeb6e74b1602gfgnoa71i0k8nit8onlcjlqeq2k7t7i3l6n279dalhl0t9\
+ b9ibbpc1fa3anjjh7sb55fks9k08p3cl8fgabmrputg7smh3bh2d8on1q72c9qc2\
+ oq4ka5pem6u93lkqjk0jk5ssqgd98er49nq1c4upp6726kalnqcpij5gg1rru7df\
+ m8g0oscmlu68ffof2b9auiiga5bg8ob3qi8fbrg9fjr3aktct14c9cpjnres9rci\
+ dso2trmmkneiq23h298ljg31mb43p1dq7qdl6lmb7de57euffnt5gas6r38j6018
+ """)
+
+ self.check(Self.descending, radix: 31, ascii: """
+ 00000000000000000000000000000000000001mjhjojnfirn3c5brjtjk678qds\
+ eobfaoo3u4pt6c8gp3qq7d3gs6mhic3bt5u8albbjs084e2df2lk0emlpnk5i1n7\
+ 03pihpu5l0pi4tk105oig7aiebgiu5j5sr5b25l6972cu4cj91npannpnc2728dc\
+ q1igcra12qk77hapu1b1qr6d4sskf9ab7j7m60452eh7aadkdpdid946fq12ri1j\
+ q727jria8qda7db990diombqtjds5bn0h275frk8n7d2jifftqlb9dkjp0ls0blq\
+ 7jubdjr23abk7n6in56etkbbis6bbp90fns3qgo1smgnasor6pf4nf32q1fttojs\
+ sijo13oepa99njdhrb4hldth0rbbho66pmrsp76p4g13khulkdj6dgj4hojgk8fu
+ """)
+ }
+
+ func test32() {
+ self.check(Self.ascending, radix: 32, ascii: """
+ 000000000000000000000000000000000000007vvruvpuvqv7sfftnlujpv5sfg\
+ tvnerr7btbkuhpv6snie7on1s3fttnesrfddjm6nqrat9kuiq78cvjmdpj5slie8\
+ ov3cbh63ob0s1ftunmubnelpn2rrdddkmepb3c5flqmqpatal6kaf9l5kihq58d0\
+ juf9r74rjacph5smima974khi27ot3cche58j247gq2o90s2g607uvjtfhtnkubo\
+ etr7at3je9on0rredlm6mqj9d1jmcpb4cdh62o2vbpelomqqb5c5elilah9l4kag\
+ 9t74qj2b994kghq68l246gi180vjsf9s7ct3ie1n6oqj8cpi64o2ubhd5glika98\
+ 4sj2a91348gi07ou3ke1m6gp30bhc58k2c91240f1o6go2oa1440e1g50g1g4080
+ """)
+
+ self.check(Self.descending, radix: 32, ascii: """
+ 0000000000000000000000000000000000000000041061050o3gg28a1c60q3gf\
+ 208h44ok2kb1e60p38dho78u3sg228h34giic9p854l2mb1d5onj0c9i6cq3adhn\
+ 70sjkeps7kv3ug21891k8ha68t44iiib9h6ksjqga5956l2lapblgmaqbde5qniv\
+ c1gm4or4clj6eq39d9lmorbedto72sjjehqnctrof5t7mv3tfpvo10c2ge28b1k7\
+ h24ol2schm78v44hia9p95cmiuc9j6krjiept7t0k6ha7955kqjqhadalemarblf\
+ m2or5ctkmmrbfe5pnatrpfdunv0c3gm3oj2sdhu8p75cnj6dpr7t1keiqfadblmn\
+ r3ctlmusrnfdvo71sbhu9pf6svkejqnbtjmutrvgu7pf7t7lurrvhufqvfufrvnv
+ """)
+ }
+
+ func test33() {
+ self.check(Self.ascending, radix: 33, ascii: """
+ 000000000000000000000000000000000000000000wf08osbkbu36iuk1a0c3mg\
+ swowotq5g5rfb59tjo423qm0opnic8ukf83hnvggfa3ikaeqh7msfvwtd1m18tct\
+ nrwfg3md55vf923rqh2grih41picatv6nf68ofkgn6gg312aomp3jo3ng217vrbs\
+ lif6g8g5p29uhn54tck1q2dk22bfkoguw2fgc9gnnn492r3a0pgme41d6202qr53\
+ 0cnpf5tpu6pir1uk45l463l6lf91n1w99hicve8ts1ggum0jtup4rti3514019hd\
+ f92b9vdnhu2ip86jhue3wol6d37l4njo26s9dmpow9dcwivflpts8lwrjci34ui3\
+ seih7hhjjsn6equebc7ca2cr22guqmdsekwewboqq0mgptsi7nkqdrudnahilbl3
+ """)
+
+ self.check(Self.descending, radix: 33, ascii: """
+ 000000000000000000000000000000000000000000000huu8mu1391be05tiior\
+ sugdp9856i3vo2c0eg05gbcenilm7rpi94op52duat3m17fjo352wmr7wugsnpau\
+ ggfq6nshd3ru8d9ovlc0jta1okqtorlhwjgco8c32e8q9otw6lr82id874k8ut1f\
+ cag9cadwg5lpwvrk3jl2eh993e5wumehcwns9a2f8s086arsvukpb6pn3umep923\
+ l38rajfap3ovwupv90jgvkku2mmp52n9t6il3surpkrlpggihcllh3dhtr83qsb4\
+ 6l89pj79tsu1gurf3uetwi9onlcik36ugenvfhd8e4llunsn5v1d7anaiad60wbr\
+ uq5tpbad4f1qdno3arm2cdr2e3b1lkpqpkgcjnmwjo5u04s5573v9jg3002jrogl
+ """)
+ }
+
+ func test34() {
+ self.check(Self.ascending, radix: 34, ascii: """
+ 00000000000000000000000000000000000000000000075eo27x9nu9tn7fi1ce\
+ 359cvtxx1332aewm3x4qd5llkfj17hxkrsc33uo3sdpp32kj0j3d6vtkmskluagv\
+ m4x8d4vojgwvomju3b26lpor71l0a0do4xmdqh8jdiaj2bkokjuwh0v37ladu2he\
+ pv65khfagbfqb0xnepxhi81rds2mup1k3i1db3ixlr1bb91x7rkolfoxd500wu41\
+ wj3vbgxatgq5fw2p7tnfjn05u4gec6mt0x25d5k0adkodmjf248pl99ij159xxfd\
+ 64fw3ikxscupn4eks94cfnjxxcp954x6xb9mg3sbdqc0oai87dv16k2bqf06x42u\
+ 2vms3unwqoukwt8v36cmaavlecb5henbvw55gsp1ditrbk6amh0xdapxfqow7e80
+ """)
+
+ self.check(Self.descending, radix: 34, ascii: """
+ 0000000000000000000000000000000000000000000000004b4u5cfn5h1xh89d\
+ arnchrh1qf49301ph2rjhwdimd3lhg973lh1199v2tlj1uis340cgxnsrssdoa02\
+ 61h9bb1gpmw7wp6ahnic3d61a2atxmf9l7dks4sqd1tlml9c7ghomvid96gl1ia7\
+ vfwupqgiaibmexrhdb568iiuxv3og4fw3llepqw2wlre0hcpissu0jo3wfg2gabf\
+ crrirps1mnr2d16o5kmuroimut7jqtl379gl0676dqj5ns6dui1gj7intmml9e05\
+ n370k1qtcqrldu01rv2mg4sx4wawi5ttwnvikn37jpjggjm14r265oputhi2dauf\
+ 2ivs8hvh14miwn2ht27s3ne00710gshi4wjdd9irtw3gq9im9rljn7f05tfm03xh
+ """)
+ }
+
+ func test35() {
+ self.check(Self.ascending, radix: 35, ascii: """
+ 0000000000000000000000000000000000000000000000002ndxwb3ok6s4k5p5\
+ ymr8u7p67b6xfhwiwyojwteq5qvdgrigdp50hwnq9e5dogmrg7x392dbx2vxkkr6\
+ siwb3rnmah6xi2cee4qldu99xky5ggganqyaxgo7j22st8d5yj6l0wj78r31tkup\
+ 9e65y798485dsmnlnsbw9j8hdcbxntls6j4w30j3va6alba73h1c3rn98gsr7aey\
+ x4ba5r79ufl1jelh6yeui0t5e5a9o021bsqphjxjy68g1ubmmcfec789r3v3cux0\
+ 5yyfhsi04iyjkiwbg2xjff5fw6y70eqsdhrajifhm2q9ybk11yy5tvh0bsxk0ttq\
+ fpweb9h70r4fpx177pqg23dm8ck1xnvovqgvs2qp9g7nrlr4kpbnbhuowibrctep
+ """)
+
+ self.check(Self.descending, radix: 35, ascii: """
+ 0000000000000000000000000000000000000000000000000001qkgbhr64tc6b\
+ 17vdeio9gje48qcyx4eo3e4sxidf1957u7eh03vsy3sw2us3ikyvkllqcfow48mt\
+ 4q9hb9g00wpif6guu41gaxyka76n9yimb23jocx1834e0emuvgcinkyi772jn0ae\
+ ct3x1yrafusiiroujcnp25ao4lx7ffrp7e6qnrd310cjyq8rrcadniwokk9wf0o8\
+ s9xmemd1mmu8f81m7w3t5ncubi2ihwajjwscjhxuug0j2fikf17yw8bypxnyv1kt\
+ ajv7q6xa08dhoxb8427vjjby5ge5sbpn9cj3b2klwetn5tjfngy3a955xkk12tdu\
+ 6cs10ev42acvbmytmqmc4yehncbc7k4y560tije2r18fsl37vgcwma4sa33jmlwk
+ """)
+ }
+
+ func test36() {
+ self.check(Self.ascending, radix: 36, ascii: """
+ 0000000000000000000000000000000000000000000000000001mvj05wljbmpd\
+ 8a2mrglgkrl8gqwelpwwxehf7iy1e62a2bgqnwhakfi8fhp4yiy96w7gg8pkrvyc\
+ ojpy7czhc5r9tcoz0w5494eh31ezh8ezx4stye8xhigo1k7u2owa4olg2tx3nqhw\
+ kiay1mrg4rb09twvlcqx1qnsbsb3qfl7j2wxlrkqhanbcxt2gcztp40bxcwwa0lp\
+ 1a39mzhxwmovwnc745vv3sv44jnfgqoekcku7trkz49lvn3kwf7kk1mcn6fg1nxj\
+ ccmy6g4p3j4m1hjpywgt9pnq9mgovinv1wq4u3c4s4tv5bux5b5yi5avnt894fm2\
+ b8a57jtmggfc3thfwalqq3eruydie3u2rhh2bjf5g8i6qla9b2fh6lrb1ios0wlc
+ """)
+
+ self.check(Self.descending, radix: 36, ascii: """
+ 000000000000000000000000000000000000000000000000000000168swoi6iu\
+ zj4fbwknlnh695zl88v65qcfgnwrwepqcxb9dysmluowqahvt3r9gsc1v47ssxdi\
+ vjda3nttl6r044pzz7zwhtgu2mkow5ts28x2mbwenh3wfz4s1sarspfhlrakvqrg\
+ pmzb66sgtz2lzbotl7r28wcq8925c747b44l60vrk3scrin4zvnwn7pdsukgo6lg\
+ jhu1nuwj7yt1h9ujpe3os17onsk7sp4ysmytu568do2tqetwnrmbxb2dtd8kqorc\
+ oakaizlm9svr8axe1acxfursz11nubrhighfd64yhmp99ucvzr944n8co01o4x64\
+ cmbd8be0hqbm2zy5uwe4uplc4sa50xajel4bkkxb1kh21pisna37eqwpbpq11ypr
+ """)
+ }
+}
+
+//*============================================================================*
+// MARK: * NBK x Flexible Width x Text x Assertions
+//*============================================================================*
+
+private func NBKAssertFromDescription(
+_ integer: T?, _ description: String,
+file: StaticString = #file, line: UInt = #line) {
+ //=------------------------------------------=
+ XCTAssertEqual(T.init(description), integer, file: file, line: line)
+ XCTAssertEqual(T.init(description, radix: 10), integer, file: file, line: line)
+}
+
+private func NBKAssertDecodingText (
+_ 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 NBKAssertEncodingText(
+_ integer: T, _ radix: Int, _ uppercase: Bool, _ text: String,
+file: StaticString = #file, line: UInt = #line) {
+ //=------------------------------------------=
+ 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)
+}
diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Update.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Update.swift
new file mode 100644
index 00000000..16f30c4c
--- /dev/null
+++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Update.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
+import NBKFlexibleWidthKit
+import XCTest
+
+private typealias X = [UInt]
+private typealias X64 = [UInt64]
+private typealias X32 = [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 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() {
+ 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 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 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
new file mode 100644
index 00000000..f91e67a9
--- /dev/null
+++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth+Words.swift
@@ -0,0 +1,244 @@
+//=----------------------------------------------------------------------------=
+// This source file is part of the Numberick open source project.
+//
+// Copyright (c) 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
+
+private typealias X = [UInt]
+private typealias X64 = [UInt64]
+private typealias X32 = [UInt32]
+
+//*============================================================================*
+// MARK: * NBK x Flexible Width x Words x UIntXL
+//*============================================================================*
+
+final class NBKFlexibleWidthTestsOnWordsAsUIntXL: XCTestCase {
+
+ typealias T = UIntXL
+ typealias M = UIntXL
+
+ //=------------------------------------------------------------------------=
+ // MARK: Tests
+ //=------------------------------------------------------------------------=
+
+ func testFromWords() {
+ NBKAssertFromWordsIsSigned(Array( ), true, T( ))
+ NBKAssertFromWordsIsSigned(Array(T( ).words), true, T( ))
+ NBKAssertFromWordsIsSigned(Array(T.min256.words), true, T.min256)
+ NBKAssertFromWordsIsSigned(Array(T.max256.words), true, nil as T?)
+
+ NBKAssertFromWordsIsSigned(Array( ), false, T( ))
+ NBKAssertFromWordsIsSigned(Array(T( ).words), false, T( ))
+ NBKAssertFromWordsIsSigned(Array(T.min256.words), false, T.min256)
+ NBKAssertFromWordsIsSigned(Array(T.max256.words), false, T.max256)
+
+ NBKAssertFromWordsIsSigned(Array([~0/2 + 1]), true, nil as T?)
+ NBKAssertFromWordsIsSigned(Array([~0/2 + 0]), true, T(words:[~0/2 + 0]))
+
+ NBKAssertFromWordsIsSigned(Array([~0/2 + 1]), false, T(words:[~0/2 + 1]))
+ NBKAssertFromWordsIsSigned(Array([~0/2 + 0]), false, T(words:[~0/2 + 0]))
+ }
+
+ func testToWords() {
+ NBKAssertToWords(T(words:[0 ]), [0 ])
+ NBKAssertToWords(T(words:[1 ]), [1 ])
+ NBKAssertToWords(T(words:[1, 2 ]), [1, 2 ])
+ NBKAssertToWords(T(words:[1, 2, 3 ]), [1, 2, 3 ])
+ NBKAssertToWords(T(words:[1, 2, 3, 4]), [1, 2, 3, 4])
+
+ NBKAssertToWords(T(words:[0, 0, 0, 0]), [0 ])
+ NBKAssertToWords(T(words:[1, 0, 0, 0]), [1 ])
+ NBKAssertToWords(T(words:[1, 2, 0, 0]), [1, 2 ])
+ NBKAssertToWords(T(words:[1, 2, 3, 0]), [1, 2, 3 ])
+ 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() }
+
+ 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 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 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 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 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])
+ }
+
+ //=------------------------------------------------------------------------=
+ // MARK: Tests x Miscellaneous
+ //=------------------------------------------------------------------------=
+
+ func testSubscriptSignExtension() {
+ 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)
+ }
+}
+
+//*============================================================================*
+// MARK: * NBK x Flexible Width x Words x Assertions
+//*============================================================================*
+
+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:{ _ = $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)).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)).1 })
+ XCTAssertEqual(initialized, integer, file: file, line: line)
+ }
+}
+
+private func NBKAssertToWords(
+_ integer: T, _ words: [UInt],
+file: StaticString = #file, line: UInt = #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) })
+}
+
+//=----------------------------------------------------------------------------=
+// 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)
+ }
+}
diff --git a/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth.swift b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth.swift
new file mode 100644
index 00000000..67f47d67
--- /dev/null
+++ b/Tests/NBKFlexibleWidthKitTests/NBKFlexibleWidth.swift
@@ -0,0 +1,50 @@
+//=----------------------------------------------------------------------------=
+// This source file is part of the Numberick open source project.
+//
+// Copyright (c) 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
+
+private typealias X = [UInt]
+private typealias X64 = [UInt64]
+private typealias X32 = [UInt32]
+
+//*============================================================================*
+// MARK: * NBK x Flexible Width x UIntXL
+//*============================================================================*
+
+extension NBKFlexibleWidth.Magnitude {
+
+ //=------------------------------------------------------------------------=
+ // MARK: Constants
+ //=------------------------------------------------------------------------=
+
+ static let min256 = Self(x64:[ 0, 0, 0, 0] as X64)
+
+ 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 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),
+ ]})
+
+ //=------------------------------------------------------------------------=
+ // MARK: Initializers
+ //=------------------------------------------------------------------------=
+
+ init(x32: [UInt32]) {
+ self.init(words: NBKChunkedInt(x32))
+ }
+
+ init(x64: [UInt64]) {
+ self.init(words: NBKChunkedInt(x64))
+ }
+}