From 7c450f29a628cdbe8f07c5c7dcc24ceeb388f29e Mon Sep 17 00:00:00 2001 From: Yehor Popovych Date: Fri, 11 Aug 2023 20:00:54 +0100 Subject: [PATCH 001/111] added podspecs and GitHub Actions --- .github/workflows/deploy.yml | 34 ++++++++++++ .github/workflows/test.yml | 77 +++++++++++++++++++++++++++ Package.swift | 12 ++--- pods/Numberick-CoreKit.podspec | 35 ++++++++++++ pods/Numberick-DoubleWidthKit.podspec | 38 +++++++++++++ pods/Numberick.podspec | 25 +++++++++ 6 files changed, 215 insertions(+), 6 deletions(-) create mode 100644 .github/workflows/deploy.yml create mode 100644 .github/workflows/test.yml create mode 100644 pods/Numberick-CoreKit.podspec create mode 100644 pods/Numberick-DoubleWidthKit.podspec create mode 100644 pods/Numberick.podspec diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 00000000..8610ed1b --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,34 @@ +name: Publish CocoaPods package +on: + release: + types: [created] +jobs: + publish: + runs-on: macos-13 + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Select Xcode + run: sudo xcode-select -s /Applications/Xcode_14.3.1.app + - name: Save version to podspecs + env: + VERSION_TAG: ${{ github.event.release.tag_name }} + run: | + VERSION=$(echo "${VERSION_TAG}" | sed "s|^v\(.*\)$|\1|g") + sed -i '' "s|[[:blank:]]*s\.version.*|s.version = '${VERSION}'|g" pods/Numberick-CoreKit.podspec + sed -i '' "s|[[:blank:]]*s\.version.*|s.version = '${VERSION}'|g" pods/Numberick-DoubleWidthKit.podspec + sed -i '' "s|[[:blank:]]*s\.version.*|s.version = '${VERSION}'|g" pods/Numberick.podspec + - name: Publish 'Numberick-CoreKit' Pod + run: pod trunk push --allow-warnings --synchronous pods/Numberick-CoreKit.podspec + env: + COCOAPODS_TRUNK_TOKEN: ${{ secrets.COCOAPODS_TRUNK_TOKEN }} + - name: Publish 'Numberick-DoubleWidthKit' Pod + run: pod trunk push --allow-warnings --synchronous pods/Numberick-DoubleWidthKit.podspec + env: + COCOAPODS_TRUNK_TOKEN: ${{ secrets.COCOAPODS_TRUNK_TOKEN }} + - name: Publish 'Numberick' Pod + run: pod trunk push --allow-warnings --synchronous pods/Numberick.podspec + env: + COCOAPODS_TRUNK_TOKEN: ${{ secrets.COCOAPODS_TRUNK_TOKEN }} + + \ No newline at end of file diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 00000000..dc27c93f --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,77 @@ +name: Build & Tests +on: [push, pull_request] +jobs: + macos: + strategy: + matrix: + xcode: ['14.2', '14.3.1'] + runs-on: macos-13 + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Create sources zip + run: | + tempfile=$(mktemp -u).zip + zip -r "${tempfile}" . + echo "SOURCES_ZIP=${tempfile}" >> "$GITHUB_ENV" + - name: Select Xcode + run: sudo xcode-select -s /Applications/Xcode_${{ matrix.xcode }}.app + - name: Build and Test macOS + run: xcodebuild test -scheme 'Numberick' -destination "platform=macOS" + - name: Benchmarks macOS + run: xcodebuild test -scheme 'Numberick-Benchmarks' -destination "platform=macOS" + - name: Build and Test iOS Simulator + run: xcodebuild test -scheme 'Numberick' -destination "platform=iOS Simulator,name=iPhone 14" + - name: Benchmarks iOS Simulator + run: xcodebuild test -scheme 'Numberick-Benchmarks' -destination "platform=iOS Simulator,name=iPhone 14" + - name: Build and Test tvOS Simulator + run: xcodebuild test -scheme 'Numberick' -destination "platform=tvOS Simulator,name=Apple TV" + - name: Benchmarks tvOS Simulator + run: xcodebuild test -scheme 'Numberick-Benchmarks' -destination "platform=tvOS Simulator,name=Apple TV" + - name: Build and Test watchOS Simulator + run: xcodebuild test -scheme 'Numberick' -destination "platform=watchOS Simulator,name=Apple Watch Series 6 (40mm)" + - name: Benchmarks watchOS Simulator + run: xcodebuild test -scheme 'Numberick-Benchmarks' -destination "platform=watchOS Simulator,name=Apple Watch Series 6 (40mm)" + - name: Setup Local CocoaPods Repo + run: | + COCOAPODS_LOCAL_REPO=$(mktemp -d) + git init --bare -b main "$COCOAPODS_LOCAL_REPO" + git clone "$COCOAPODS_LOCAL_REPO" git_temp_dir + cd git_temp_dir + touch .gitignore && git add .gitignore && git commit -a -m "repo init" && git push + cd ../ && rm -r git_temp_dir + pod repo add local "${COCOAPODS_LOCAL_REPO}" + pod repo update + echo "COCOAPODS_LOCAL_REPO=${COCOAPODS_LOCAL_REPO}" >> "$GITHUB_ENV" + - name: CocoaPods 'Numberick-CoreKit' Lint & Local Push + run: | + sed -i '' "s|[[:blank:]]*s\.source.*|s.source = { :http => 'file://${SOURCES_ZIP}' \}|g" pods/Numberick-CoreKit.podspec + pod repo push --allow-warnings --fail-fast --synchronous local pods/Numberick-CoreKit.podspec + pod repo update + - name: CocoaPods 'Numberick-DoubleWidthKit' Lint & Local Push + run: | + sed -i '' "s|[[:blank:]]*s\.source.*|s.source = { :http => 'file://${SOURCES_ZIP}' \}|g" pods/Numberick-DoubleWidthKit.podspec + pod repo push --allow-warnings --fail-fast --synchronous local pods/Numberick-DoubleWidthKit.podspec + pod repo update + - name: CocoaPods 'Numberick' Lint + run: pod lib lint --allow-warnings --fail-fast --sources="local,https://cdn.cocoapods.org" pods/Numberick.podspec + - name: Cleanup + if: always() + run: | + [ -f "${SOURCES_ZIP}" ] && rm -f "${SOURCES_ZIP}" + [ -d "${COCOAPODS_LOCAL_REPO}" ] && rm -rf "${COCOAPODS_LOCAL_REPO}" + linux: + strategy: + matrix: + swift: ['5.7', '5.8'] + runs-on: ubuntu-latest + container: + image: swift:${{ matrix.swift }} + options: --cap-add=SYS_PTRACE --security-opt seccomp=unconfined --security-opt apparmor=unconfined + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Build and Test + run: swift test + - name: Run Benchmarks + run: swift test -c release \ No newline at end of file diff --git a/Package.swift b/Package.swift index 2d00f6e7..94c7cf01 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version: 5.8 +// swift-tools-version: 5.7 //=----------------------------------------------------------------------------= // This source file is part of the Numberick open source project. // @@ -17,11 +17,11 @@ import PackageDescription let package = Package( name: "Numberick", platforms: [ - .iOS("16.4"), - .macCatalyst("16.4"), - .macOS("13.3"), - .tvOS("16.4"), - .watchOS("9.4"), + .iOS(.v14), + .macCatalyst(.v14), + .macOS(.v11), + .tvOS(.v14), + .watchOS(.v7), ], products: [ //=--------------------------------------= diff --git a/pods/Numberick-CoreKit.podspec b/pods/Numberick-CoreKit.podspec new file mode 100644 index 00000000..bbd524e3 --- /dev/null +++ b/pods/Numberick-CoreKit.podspec @@ -0,0 +1,35 @@ +Pod::Spec.new do |s| + s.name = 'Numberick-CoreKit' + s.version = '999.99.9' + s.summary = "A new protocol hierarchy that refines Swift's standard integer library." + + s.description = <<-DESC + A new protocol hierarchy that refines Swift's standard library. Core part of Numberick. + DESC + + s.homepage = 'https://github.com/oscbyspro/Numberick' + + s.license = { :type => 'Apache-2.0', :file => 'LICENSE' } + s.author = { 'Oscar Byström Ericsson' => 'oscbyspro@protonmail.com' } + s.source = { :git => 'https://github.com/oscbyspro/Numberick.git', :tag => "v#{s.version}" } + + base_platforms = { :ios => '14.0', :osx => '11.0', :tvos => '14.0' } + + s.platforms = base_platforms.merge({ :watchos => '7.0' }) + + s.module_name = 'NBKCoreKit' + + s.swift_version = '5.7' + + s.source_files = 'Sources/NBKCoreKit/**/*.swift' + + s.test_spec 'Tests' do |ts| + ts.platforms = base_platforms + ts.source_files = 'Tests/NBKCoreKitTests/**/*.swift' + end + + s.test_spec 'Benchmarks' do |ts| + ts.platforms = base_platforms + ts.source_files = 'Tests/NBKCoreKitBenchmarks/**/*.swift' + end +end \ No newline at end of file diff --git a/pods/Numberick-DoubleWidthKit.podspec b/pods/Numberick-DoubleWidthKit.podspec new file mode 100644 index 00000000..fd845360 --- /dev/null +++ b/pods/Numberick-DoubleWidthKit.podspec @@ -0,0 +1,38 @@ +Pod::Spec.new do |s| + s.name = 'Numberick-DoubleWidthKit' + s.version = '999.99.9' + s.summary = "Generic software model for working with fixed-width integers larger than one machine word" + + s.description = <<-DESC + NBKDoubleWidth is a generic software model for working with fixed-width integers larger than one machine word. + Its bit width is double the bit width of its High component. Main part of Numberick. + DESC + + s.homepage = 'https://github.com/oscbyspro/Numberick' + + s.license = { :type => 'Apache-2.0', :file => 'LICENSE' } + s.author = { 'Oscar Byström Ericsson' => 'oscbyspro@protonmail.com' } + s.source = { :git => 'https://github.com/oscbyspro/Numberick.git', :tag => "v#{s.version}" } + + base_platforms = { :ios => '14.0', :osx => '11.0', :tvos => '14.0' } + + s.platforms = base_platforms.merge({ :watchos => '7.0' }) + + s.module_name = 'NBKDoubleWidthKit' + + s.swift_version = '5.7' + + s.source_files = 'Sources/NBKDoubleWidthKit/**/*.swift' + + s.dependency 'Numberick-CoreKit', "#{s.version}" + + s.test_spec 'Tests' do |ts| + ts.platforms = base_platforms + ts.source_files = 'Tests/NBKDoubleWidthKitTests/**/*.swift' + end + + s.test_spec 'Benchmarks' do |ts| + ts.platforms = base_platforms + ts.source_files = 'Tests/NBKDoubleWidthKitBenchmarks/**/*.swift' + end +end \ No newline at end of file diff --git a/pods/Numberick.podspec b/pods/Numberick.podspec new file mode 100644 index 00000000..851e7698 --- /dev/null +++ b/pods/Numberick.podspec @@ -0,0 +1,25 @@ +Pod::Spec.new do |s| + s.name = 'Numberick' + s.version = '999.99.9' + s.summary = "A composable, large, fixed-width, two's complement, binary integer." + + s.description = <<-DESC + A generic software model for working with fixed-width integers larger than one machine word. + Main package. + DESC + + s.homepage = 'https://github.com/oscbyspro/Numberick' + + s.license = { :type => 'Apache-2.0', :file => 'LICENSE' } + s.author = { 'Oscar Byström Ericsson' => 'oscbyspro@protonmail.com' } + s.source = { :git => 'https://github.com/oscbyspro/Numberick.git', :tag => "v#{s.version}" } + + s.platforms = { :ios => '14.0', :osx => '11.0', :tvos => '14.0', :watchos => '7.0' } + + s.swift_version = '5.7' + + s.source_files = 'Sources/Numberick/**/*.swift' + + s.dependency 'Numberick-CoreKit', "#{s.version}" + s.dependency 'Numberick-DoubleWidthKit', "#{s.version}" +end \ No newline at end of file From 15b6ffbd78a21eba8248ea702757f0ff584da037 Mon Sep 17 00:00:00 2001 From: Yehor Popovych Date: Fri, 11 Aug 2023 20:17:21 +0100 Subject: [PATCH 002/111] disabled non-working tests --- README.md | 2 +- .../NBKDoubleWidth+IntegerLiteral.swift | 50 +++++++++++ .../NBKDoubleWidth+Numbers.swift | 25 ------ .../NBKDoubleWidth+Numbers.swift | 82 ++++++++++--------- .../NBKDoubleWidth+Numbers.swift | 73 ++++++++++------- 5 files changed, 137 insertions(+), 95 deletions(-) create mode 100644 Sources/NBKDoubleWidthKit/NBKDoubleWidth+IntegerLiteral.swift diff --git a/README.md b/README.md index cb52a1bf..7317ca98 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ | Package | Swift | iOS | iPadOS | Mac Catalyst | macOS | tvOS | watchOS | |:-------:|:-----:|:----:|:------:|:------------:|:-----:|:----:|:-------:| -| 0.8.0 | 5.8 | 16.4 | 16.4 | 16.4 | 13.3 | 16.4 | 9.4 | +| 0.8.0 | 5.7 | 14 | 14 | 14 | 11 | 14 | 7 | ## NBKCoreKit ([Sources][COR/S], [Tests][COR/T], [Benchmarks][COR/B]) diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+IntegerLiteral.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+IntegerLiteral.swift new file mode 100644 index 00000000..b206fff6 --- /dev/null +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+IntegerLiteral.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. +//=----------------------------------------------------------------------------= + +//*============================================================================* +// MARK: * NBK x Double Width x IntegerLiteral +//*============================================================================* + +extension NBKDoubleWidth { + public typealias IntegerLiteralType = Int64 + + @inlinable public init(integerLiteral source: Int64) { + self.init(source) + } +} + +// StaticBigInt available only from macOS 13.3. +// Enable when drop old OS support +//extension NBKDoubleWidth { +// +// //=------------------------------------------------------------------------= +// // MARK: Initializers +// //=------------------------------------------------------------------------= +// +// @inlinable public init(integerLiteral source: StaticBigInt) { +// guard let value = Self(exactlyIntegerLiteral: source) else { +// preconditionFailure("\(Self.description) cannot represent \(source)") +// } +// +// self = value +// } +// +// @inlinable init?(exactlyIntegerLiteral source: StaticBigInt) { +// guard Self.isSigned +// ? source.bitWidth <= Self.bitWidth +// : source.bitWidth <= Self.bitWidth + 1 && source.signum() >= 0 +// else { return nil } +// +// self = Self.uninitialized { value in +// for index in value.indices { +// value[unchecked: index] = source[index] +// } +// } +// } +//} diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Numbers.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Numbers.swift index 08402973..3e9080cc 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Numbers.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Numbers.swift @@ -46,31 +46,6 @@ extension NBKDoubleWidth { // MARK: Initializers //=------------------------------------------------------------------------= - @inlinable public init(integerLiteral source: StaticBigInt) { - guard let value = Self(exactlyIntegerLiteral: source) else { - preconditionFailure("\(Self.description) cannot represent \(source)") - } - - self = value - } - - @inlinable init?(exactlyIntegerLiteral source: StaticBigInt) { - guard Self.isSigned - ? source.bitWidth <= Self.bitWidth - : source.bitWidth <= Self.bitWidth + 1 && source.signum() >= 0 - else { return nil } - - self = Self.uninitialized { value in - for index in value.indices { - value[unchecked: index] = source[index] - } - } - } - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - @inlinable public init(_ source: some BinaryInteger) { guard let result = Self(exactly: source) else { preconditionFailure("\(Self.description) cannot represent \(source)") diff --git a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Numbers.swift b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Numbers.swift index 7e4feb20..40348e3c 100644 --- a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Numbers.swift +++ b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Numbers.swift @@ -366,25 +366,28 @@ final class NBKDoubleWidthBenchmarksOnNumbersAsInt256: XCTestCase { //=------------------------------------------------------------------------= // TODO: brrr - func testToFloat16() { - var abc = NBK.blackHoleIdentity(T.max) - - for _ in 0 ..< 1_000 { - NBK.blackHole(Float16(abc)) - NBK.blackHole(Float16(exactly: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testFromFloat16() { - var abc = NBK.blackHoleIdentity(Float16(123)) - - for _ in 0 ..< 250_000 { - NBK.blackHole(T(abc)) - NBK.blackHole(T(exactly: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } + // Float16 doesn't have BinaryInteger initializers +//#if swift(>=5.8) +// func testToFloat16() { +// var abc = NBK.blackHoleIdentity(T.max) +// +// for _ in 0 ..< 1_000 { +// NBK.blackHole(Float16(abc)) +// NBK.blackHole(Float16(exactly: abc)) +// NBK.blackHoleInoutIdentity(&abc) +// } +// } +// +// func testFromFloat16() { +// var abc = NBK.blackHoleIdentity(Float16(123)) +// +// for _ in 0 ..< 250_000 { +// NBK.blackHole(T(abc)) +// NBK.blackHole(T(exactly: abc)) +// NBK.blackHoleInoutIdentity(&abc) +// } +// } +//#endif // TODO: brrr func testToFloat32() { @@ -796,25 +799,28 @@ final class NBKDoubleWidthBenchmarksOnNumbersAsUInt256: XCTestCase { //=------------------------------------------------------------------------= // TODO: brrr - func testToFloat16() { - var abc = NBK.blackHoleIdentity(T.max) - - for _ in 0 ..< 1_000 { - NBK.blackHole(Float16(abc)) - NBK.blackHole(Float16(exactly: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testFromFloat16() { - var abc = NBK.blackHoleIdentity(Float16(123)) - - for _ in 0 ..< 250_000 { - NBK.blackHole(T(abc)) - NBK.blackHole(T(exactly: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } + // Float16 doesn't have BinaryInteger initializers +//#if swift(>=5.8) +// func testToFloat16() { +// var abc = NBK.blackHoleIdentity(T.max) +// +// for _ in 0 ..< 1_000 { +// NBK.blackHole(Float16(abc)) +// NBK.blackHole(Float16(exactly: abc)) +// NBK.blackHoleInoutIdentity(&abc) +// } +// } +// +// func testFromFloat16() { +// var abc = NBK.blackHoleIdentity(Float16(123)) +// +// for _ in 0 ..< 250_000 { +// NBK.blackHole(T(abc)) +// NBK.blackHole(T(exactly: abc)) +// NBK.blackHoleInoutIdentity(&abc) +// } +// } +//#endif // TODO: brrr func testToFloat32() { diff --git a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Numbers.swift b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Numbers.swift index 68db9a80..3e818458 100644 --- a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Numbers.swift +++ b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Numbers.swift @@ -155,9 +155,16 @@ final class NBKDoubleWidthTestsOnNumbersAsInt256: XCTestCase { func testFromUInt64() { NBKAssertNumbers(from: UInt64.min, default: T()) - NBKAssertNumbers(from: UInt64.max, default: T(18446744073709551615)) + NBKAssertNumbers(from: UInt64.max, default: T(UInt64.max)) } + // StaticBigInt available only from macOS 13.3. + // Enable when drop old OS support +// func testFromUInt64Literal() { +// NBKAssertNumbers(from: UInt64.min, default: T()) +// NBKAssertNumbers(from: UInt64.max, default: T(18446744073709551615)) +// } + //=------------------------------------------------------------------------= // MARK: Tests x Signitude //=------------------------------------------------------------------------= @@ -329,21 +336,23 @@ final class NBKDoubleWidthTestsOnNumbersAsInt256: XCTestCase { // MARK: Tests x Literal //=------------------------------------------------------------------------= - func testFromLiteral() { - XCTAssertEqual(T(x64: X( 0, 0, 0, 0)), 0x0000000000000000000000000000000000000000000000000000000000000000) - XCTAssertEqual(T(x64: X(~0, 0, 0, 0)), 0x000000000000000000000000000000000000000000000000ffffffffffffffff) - XCTAssertEqual(T(x64: X(~0, ~0, 0, 0)), 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) - XCTAssertEqual(T(x64: X(~0, ~0, ~0, 0)), 0x0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff) - XCTAssertEqual(T(x64: X(~0, ~0, ~0, ~0)), -0x0000000000000000000000000000000000000000000000000000000000000001) - XCTAssertEqual(T(x64: X( 0, ~0, ~0, ~0)), -0x0000000000000000000000000000000000000000000000010000000000000000) - XCTAssertEqual(T(x64: X( 0, 0, ~0, ~0)), -0x0000000000000000000000000000000100000000000000000000000000000000) - XCTAssertEqual(T(x64: X( 0, 0, 0, ~0)), -0x0000000000000001000000000000000000000000000000000000000000000000) - - XCTAssertEqual(T(exactlyIntegerLiteral: 0x8000000000000000000000000000000000000000000000000000000000000000), nil) - XCTAssertEqual(T(exactlyIntegerLiteral: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff), T.max) - XCTAssertEqual(T(exactlyIntegerLiteral: -0x8000000000000000000000000000000000000000000000000000000000000000), T.min) - XCTAssertEqual(T(exactlyIntegerLiteral: -0x8000000000000000000000000000000000000000000000000000000000000001), nil) - } + // StaticBigInt available only from macOS 13.3. + // Enable when drop old OS support +// func testFromLiteral() { +// XCTAssertEqual(T(x64: X( 0, 0, 0, 0)), 0x0000000000000000000000000000000000000000000000000000000000000000) +// XCTAssertEqual(T(x64: X(~0, 0, 0, 0)), 0x000000000000000000000000000000000000000000000000ffffffffffffffff) +// XCTAssertEqual(T(x64: X(~0, ~0, 0, 0)), 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) +// XCTAssertEqual(T(x64: X(~0, ~0, ~0, 0)), 0x0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff) +// XCTAssertEqual(T(x64: X(~0, ~0, ~0, ~0)), -0x0000000000000000000000000000000000000000000000000000000000000001) +// XCTAssertEqual(T(x64: X( 0, ~0, ~0, ~0)), -0x0000000000000000000000000000000000000000000000010000000000000000) +// XCTAssertEqual(T(x64: X( 0, 0, ~0, ~0)), -0x0000000000000000000000000000000100000000000000000000000000000000) +// XCTAssertEqual(T(x64: X( 0, 0, 0, ~0)), -0x0000000000000001000000000000000000000000000000000000000000000000) +// +// XCTAssertEqual(T(exactlyIntegerLiteral: 0x8000000000000000000000000000000000000000000000000000000000000000), nil) +// XCTAssertEqual(T(exactlyIntegerLiteral: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff), T.max) +// XCTAssertEqual(T(exactlyIntegerLiteral: -0x8000000000000000000000000000000000000000000000000000000000000000), T.min) +// XCTAssertEqual(T(exactlyIntegerLiteral: -0x8000000000000000000000000000000000000000000000000000000000000001), nil) +// } } //*============================================================================* @@ -644,21 +653,23 @@ final class NBKDoubleWidthTestsOnNumbersAsUInt256: XCTestCase { // MARK: Tests x Literal //=------------------------------------------------------------------------= - func testFromLiteral() { - XCTAssertEqual(T(x64: X( 0, 0, 0, 0)), 0x0000000000000000000000000000000000000000000000000000000000000000) - XCTAssertEqual(T(x64: X(~0, 0, 0, 0)), 0x000000000000000000000000000000000000000000000000ffffffffffffffff) - XCTAssertEqual(T(x64: X(~0, ~0, 0, 0)), 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) - XCTAssertEqual(T(x64: X(~0, ~0, ~0, 0)), 0x0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff) - XCTAssertEqual(T(x64: X(~0, ~0, ~0, ~0)), 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) - XCTAssertEqual(T(x64: X( 0, ~0, ~0, ~0)), 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) - XCTAssertEqual(T(x64: X( 0, 0, ~0, ~0)), 0xffffffffffffffffffffffffffffffff00000000000000000000000000000000) - XCTAssertEqual(T(x64: X( 0, 0, 0, ~0)), 0xffffffffffffffff000000000000000000000000000000000000000000000000) - - XCTAssertEqual(T(exactlyIntegerLiteral: 0x010000000000000000000000000000000000000000000000000000000000000000), nil) - XCTAssertEqual(T(exactlyIntegerLiteral: 0x00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff), T.max) - XCTAssertEqual(T(exactlyIntegerLiteral: 0x000000000000000000000000000000000000000000000000000000000000000000), T.min) - XCTAssertEqual(T(exactlyIntegerLiteral: -0x000000000000000000000000000000000000000000000000000000000000000001), nil) - } + // StaticBigInt available only from macOS 13.3. + // Enable when drop old OS support +// func testFromLiteral() { +// XCTAssertEqual(T(x64: X( 0, 0, 0, 0)), 0x0000000000000000000000000000000000000000000000000000000000000000) +// XCTAssertEqual(T(x64: X(~0, 0, 0, 0)), 0x000000000000000000000000000000000000000000000000ffffffffffffffff) +// XCTAssertEqual(T(x64: X(~0, ~0, 0, 0)), 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) +// XCTAssertEqual(T(x64: X(~0, ~0, ~0, 0)), 0x0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff) +// XCTAssertEqual(T(x64: X(~0, ~0, ~0, ~0)), 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) +// XCTAssertEqual(T(x64: X( 0, ~0, ~0, ~0)), 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) +// XCTAssertEqual(T(x64: X( 0, 0, ~0, ~0)), 0xffffffffffffffffffffffffffffffff00000000000000000000000000000000) +// XCTAssertEqual(T(x64: X( 0, 0, 0, ~0)), 0xffffffffffffffff000000000000000000000000000000000000000000000000) +// +// XCTAssertEqual(T(exactlyIntegerLiteral: 0x010000000000000000000000000000000000000000000000000000000000000000), nil) +// XCTAssertEqual(T(exactlyIntegerLiteral: 0x00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff), T.max) +// XCTAssertEqual(T(exactlyIntegerLiteral: 0x000000000000000000000000000000000000000000000000000000000000000000), T.min) +// XCTAssertEqual(T(exactlyIntegerLiteral: -0x000000000000000000000000000000000000000000000000000000000000000001), nil) +// } } //*============================================================================* From 3f78c129d072bab835b5d323eef52a4988d4c6cc Mon Sep 17 00:00:00 2001 From: Yehor Popovych Date: Fri, 11 Aug 2023 20:49:44 +0100 Subject: [PATCH 003/111] fixes for test workflow --- .github/workflows/test.yml | 39 +++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index dc27c93f..5a9fad04 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -12,26 +12,26 @@ jobs: - name: Create sources zip run: | tempfile=$(mktemp -u).zip - zip -r "${tempfile}" . + zip -r "${tempfile}" ./* echo "SOURCES_ZIP=${tempfile}" >> "$GITHUB_ENV" - name: Select Xcode run: sudo xcode-select -s /Applications/Xcode_${{ matrix.xcode }}.app - - name: Build and Test macOS - run: xcodebuild test -scheme 'Numberick' -destination "platform=macOS" - - name: Benchmarks macOS - run: xcodebuild test -scheme 'Numberick-Benchmarks' -destination "platform=macOS" - - name: Build and Test iOS Simulator - run: xcodebuild test -scheme 'Numberick' -destination "platform=iOS Simulator,name=iPhone 14" - - name: Benchmarks iOS Simulator - run: xcodebuild test -scheme 'Numberick-Benchmarks' -destination "platform=iOS Simulator,name=iPhone 14" - - name: Build and Test tvOS Simulator - run: xcodebuild test -scheme 'Numberick' -destination "platform=tvOS Simulator,name=Apple TV" - - name: Benchmarks tvOS Simulator - run: xcodebuild test -scheme 'Numberick-Benchmarks' -destination "platform=tvOS Simulator,name=Apple TV" - - name: Build and Test watchOS Simulator - run: xcodebuild test -scheme 'Numberick' -destination "platform=watchOS Simulator,name=Apple Watch Series 6 (40mm)" - - name: Benchmarks watchOS Simulator - run: xcodebuild test -scheme 'Numberick-Benchmarks' -destination "platform=watchOS Simulator,name=Apple Watch Series 6 (40mm)" + # - name: Build and Test macOS + # run: xcodebuild test -scheme 'Numberick' -destination "platform=macOS" + # - name: Benchmarks macOS + # run: xcodebuild test -scheme 'Numberick-Benchmarks' -destination "platform=macOS" + # - name: Build and Test iOS Simulator + # run: xcodebuild test -scheme 'Numberick' -destination "platform=iOS Simulator,name=iPhone 14" + # - name: Benchmarks iOS Simulator + # run: xcodebuild test -scheme 'Numberick-Benchmarks' -destination "platform=iOS Simulator,name=iPhone 14" + # - name: Build and Test tvOS Simulator + # run: xcodebuild test -scheme 'Numberick' -destination "platform=tvOS Simulator,name=Apple TV" + # - name: Benchmarks tvOS Simulator + # run: xcodebuild test -scheme 'Numberick-Benchmarks' -destination "platform=tvOS Simulator,name=Apple TV" + # - name: Build and Test watchOS Simulator + # run: xcodebuild test -scheme 'Numberick' -destination "platform=watchOS Simulator,name=Apple Watch Series 6 (40mm)" + # - name: Benchmarks watchOS Simulator + # run: xcodebuild test -scheme 'Numberick-Benchmarks' -destination "platform=watchOS Simulator,name=Apple Watch Series 6 (40mm)" - name: Setup Local CocoaPods Repo run: | COCOAPODS_LOCAL_REPO=$(mktemp -d) @@ -46,12 +46,12 @@ jobs: - name: CocoaPods 'Numberick-CoreKit' Lint & Local Push run: | sed -i '' "s|[[:blank:]]*s\.source.*|s.source = { :http => 'file://${SOURCES_ZIP}' \}|g" pods/Numberick-CoreKit.podspec - pod repo push --allow-warnings --fail-fast --synchronous local pods/Numberick-CoreKit.podspec + pod repo push --allow-warnings --synchronous local pods/Numberick-CoreKit.podspec pod repo update - name: CocoaPods 'Numberick-DoubleWidthKit' Lint & Local Push run: | sed -i '' "s|[[:blank:]]*s\.source.*|s.source = { :http => 'file://${SOURCES_ZIP}' \}|g" pods/Numberick-DoubleWidthKit.podspec - pod repo push --allow-warnings --fail-fast --synchronous local pods/Numberick-DoubleWidthKit.podspec + pod repo push --allow-warnings --synchronous local pods/Numberick-DoubleWidthKit.podspec pod repo update - name: CocoaPods 'Numberick' Lint run: pod lib lint --allow-warnings --fail-fast --sources="local,https://cdn.cocoapods.org" pods/Numberick.podspec @@ -60,6 +60,7 @@ jobs: run: | [ -f "${SOURCES_ZIP}" ] && rm -f "${SOURCES_ZIP}" [ -d "${COCOAPODS_LOCAL_REPO}" ] && rm -rf "${COCOAPODS_LOCAL_REPO}" + pod repo remove local linux: strategy: matrix: From 068c53ab9f6e530380398e5c235822bced8586df Mon Sep 17 00:00:00 2001 From: Yehor Popovych Date: Fri, 11 Aug 2023 20:52:33 +0100 Subject: [PATCH 004/111] test workflow fix --- .github/workflows/test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5a9fad04..182abd36 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -46,12 +46,12 @@ jobs: - name: CocoaPods 'Numberick-CoreKit' Lint & Local Push run: | sed -i '' "s|[[:blank:]]*s\.source.*|s.source = { :http => 'file://${SOURCES_ZIP}' \}|g" pods/Numberick-CoreKit.podspec - pod repo push --allow-warnings --synchronous local pods/Numberick-CoreKit.podspec + pod repo push --allow-warnings local pods/Numberick-CoreKit.podspec pod repo update - name: CocoaPods 'Numberick-DoubleWidthKit' Lint & Local Push run: | sed -i '' "s|[[:blank:]]*s\.source.*|s.source = { :http => 'file://${SOURCES_ZIP}' \}|g" pods/Numberick-DoubleWidthKit.podspec - pod repo push --allow-warnings --synchronous local pods/Numberick-DoubleWidthKit.podspec + pod repo push --allow-warnings local pods/Numberick-DoubleWidthKit.podspec pod repo update - name: CocoaPods 'Numberick' Lint run: pod lib lint --allow-warnings --fail-fast --sources="local,https://cdn.cocoapods.org" pods/Numberick.podspec From 8d99f9128ed58ef5733f2bbf64fea66c2387b58f Mon Sep 17 00:00:00 2001 From: Yehor Popovych Date: Fri, 11 Aug 2023 21:18:29 +0100 Subject: [PATCH 005/111] fixed workflows --- .github/workflows/deploy.yml | 6 +++--- .github/workflows/test.yml | 11 +++++++---- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 8610ed1b..3a393902 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -15,9 +15,9 @@ jobs: VERSION_TAG: ${{ github.event.release.tag_name }} run: | VERSION=$(echo "${VERSION_TAG}" | sed "s|^v\(.*\)$|\1|g") - sed -i '' "s|[[:blank:]]*s\.version.*|s.version = '${VERSION}'|g" pods/Numberick-CoreKit.podspec - sed -i '' "s|[[:blank:]]*s\.version.*|s.version = '${VERSION}'|g" pods/Numberick-DoubleWidthKit.podspec - sed -i '' "s|[[:blank:]]*s\.version.*|s.version = '${VERSION}'|g" pods/Numberick.podspec + sed -i '' "s|[[:blank:]]*s\.version[[:blank:]].*|s.version = '${VERSION}'|g" pods/Numberick-CoreKit.podspec + sed -i '' "s|[[:blank:]]*s\.version[[:blank:]].*|s.version = '${VERSION}'|g" pods/Numberick-DoubleWidthKit.podspec + sed -i '' "s|[[:blank:]]*s\.version[[:blank:]].*|s.version = '${VERSION}'|g" pods/Numberick.podspec - name: Publish 'Numberick-CoreKit' Pod run: pod trunk push --allow-warnings --synchronous pods/Numberick-CoreKit.podspec env: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 182abd36..12b80294 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -39,27 +39,30 @@ jobs: git clone "$COCOAPODS_LOCAL_REPO" git_temp_dir cd git_temp_dir touch .gitignore && git add .gitignore && git commit -a -m "repo init" && git push - cd ../ && rm -r git_temp_dir + cd ../ && rm -rf git_temp_dir pod repo add local "${COCOAPODS_LOCAL_REPO}" pod repo update echo "COCOAPODS_LOCAL_REPO=${COCOAPODS_LOCAL_REPO}" >> "$GITHUB_ENV" - name: CocoaPods 'Numberick-CoreKit' Lint & Local Push run: | - sed -i '' "s|[[:blank:]]*s\.source.*|s.source = { :http => 'file://${SOURCES_ZIP}' \}|g" pods/Numberick-CoreKit.podspec + sed -i '' "s|[[:blank:]]*s\.source[[:blank:]].*|s.source = { :http => 'file://${SOURCES_ZIP}' \}|g" pods/Numberick-CoreKit.podspec pod repo push --allow-warnings local pods/Numberick-CoreKit.podspec pod repo update - name: CocoaPods 'Numberick-DoubleWidthKit' Lint & Local Push run: | - sed -i '' "s|[[:blank:]]*s\.source.*|s.source = { :http => 'file://${SOURCES_ZIP}' \}|g" pods/Numberick-DoubleWidthKit.podspec + sed -i '' "s|[[:blank:]]*s\.source[[:blank:]].*|s.source = { :http => 'file://${SOURCES_ZIP}' \}|g" pods/Numberick-DoubleWidthKit.podspec pod repo push --allow-warnings local pods/Numberick-DoubleWidthKit.podspec pod repo update - name: CocoaPods 'Numberick' Lint - run: pod lib lint --allow-warnings --fail-fast --sources="local,https://cdn.cocoapods.org" pods/Numberick.podspec + run: | + cp pods/Numberick.podspec ./ + pod lib lint --allow-warnings --fail-fast --sources="local,https://cdn.cocoapods.org" Numberick.podspec - name: Cleanup if: always() run: | [ -f "${SOURCES_ZIP}" ] && rm -f "${SOURCES_ZIP}" [ -d "${COCOAPODS_LOCAL_REPO}" ] && rm -rf "${COCOAPODS_LOCAL_REPO}" + rm -f Numberick.podspec pod repo remove local linux: strategy: From 83578118332f63f9311215036d7d02e291f44452 Mon Sep 17 00:00:00 2001 From: Yehor Popovych Date: Fri, 11 Aug 2023 21:42:12 +0100 Subject: [PATCH 006/111] enabled all tests --- .github/workflows/test.yml | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 12b80294..57009dab 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -16,22 +16,22 @@ jobs: echo "SOURCES_ZIP=${tempfile}" >> "$GITHUB_ENV" - name: Select Xcode run: sudo xcode-select -s /Applications/Xcode_${{ matrix.xcode }}.app - # - name: Build and Test macOS - # run: xcodebuild test -scheme 'Numberick' -destination "platform=macOS" - # - name: Benchmarks macOS - # run: xcodebuild test -scheme 'Numberick-Benchmarks' -destination "platform=macOS" - # - name: Build and Test iOS Simulator - # run: xcodebuild test -scheme 'Numberick' -destination "platform=iOS Simulator,name=iPhone 14" - # - name: Benchmarks iOS Simulator - # run: xcodebuild test -scheme 'Numberick-Benchmarks' -destination "platform=iOS Simulator,name=iPhone 14" - # - name: Build and Test tvOS Simulator - # run: xcodebuild test -scheme 'Numberick' -destination "platform=tvOS Simulator,name=Apple TV" - # - name: Benchmarks tvOS Simulator - # run: xcodebuild test -scheme 'Numberick-Benchmarks' -destination "platform=tvOS Simulator,name=Apple TV" - # - name: Build and Test watchOS Simulator - # run: xcodebuild test -scheme 'Numberick' -destination "platform=watchOS Simulator,name=Apple Watch Series 6 (40mm)" - # - name: Benchmarks watchOS Simulator - # run: xcodebuild test -scheme 'Numberick-Benchmarks' -destination "platform=watchOS Simulator,name=Apple Watch Series 6 (40mm)" + - name: Build and Test macOS + run: xcodebuild test -scheme 'Numberick' -destination "platform=macOS" + - name: Benchmarks macOS + run: xcodebuild test -scheme 'Numberick-Benchmarks' -destination "platform=macOS" + - name: Build and Test iOS Simulator + run: xcodebuild test -scheme 'Numberick' -destination "platform=iOS Simulator,name=iPhone 14" + - name: Benchmarks iOS Simulator + run: xcodebuild test -scheme 'Numberick-Benchmarks' -destination "platform=iOS Simulator,name=iPhone 14" + - name: Build and Test tvOS Simulator + run: xcodebuild test -scheme 'Numberick' -destination "platform=tvOS Simulator,name=Apple TV" + - name: Benchmarks tvOS Simulator + run: xcodebuild test -scheme 'Numberick-Benchmarks' -destination "platform=tvOS Simulator,name=Apple TV" + - name: Build and Test watchOS Simulator + run: xcodebuild test -scheme 'Numberick' -destination "platform=watchOS Simulator,name=Apple Watch Series 6 (40mm)" + - name: Benchmarks watchOS Simulator + run: xcodebuild test -scheme 'Numberick-Benchmarks' -destination "platform=watchOS Simulator,name=Apple Watch Series 6 (40mm)" - name: Setup Local CocoaPods Repo run: | COCOAPODS_LOCAL_REPO=$(mktemp -d) From 41dd9dcce3ec55fb6683694576e2e9add8ce05dc Mon Sep 17 00:00:00 2001 From: Yehor Popovych Date: Fri, 11 Aug 2023 21:49:01 +0100 Subject: [PATCH 007/111] cleanup --- .github/workflows/deploy.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 3a393902..1de5338f 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -29,6 +29,4 @@ jobs: - name: Publish 'Numberick' Pod run: pod trunk push --allow-warnings --synchronous pods/Numberick.podspec env: - COCOAPODS_TRUNK_TOKEN: ${{ secrets.COCOAPODS_TRUNK_TOKEN }} - - \ No newline at end of file + COCOAPODS_TRUNK_TOKEN: ${{ secrets.COCOAPODS_TRUNK_TOKEN }} \ No newline at end of file From 518feeaedc3e8ed86aa92d131c685e1c26a60111 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sat, 12 Aug 2023 11:20:12 +0200 Subject: [PATCH 008/111] NBKCoreKit: Cleanup. --- Sources/NBKCoreKit/NBKBinaryInteger.swift | 30 +++++++++---------- .../NBKCoreKit/Private/NBK+Collection.swift | 2 +- .../NBKCoreKitTests/Private/NBK+BitCast.swift | 20 ++++++------- 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/Sources/NBKCoreKit/NBKBinaryInteger.swift b/Sources/NBKCoreKit/NBKBinaryInteger.swift index ddc27f00..c9469727 100644 --- a/Sources/NBKCoreKit/NBKBinaryInteger.swift +++ b/Sources/NBKCoreKit/NBKBinaryInteger.swift @@ -104,10 +104,10 @@ where Magnitude: NBKUnsignedInteger, Words: Sendable { /// ┌───────────────────────── → ────────┐ /// │ self │ n.z.b.c │ /// ├─────────── = ─────────── → ────────┤ - /// │ Int256( 3) │ 0........11 │ 2 │ - /// │ Int256( 2) │ 0........10 │ 1 │ - /// │ Int256( 1) │ 0.........1 │ 1 │ - /// │ Int256( 0) │ 0.......... │ 0 │ + /// │ Int256( 3) │ 0........11 │ 002 │ + /// │ Int256( 2) │ 0........10 │ 001 │ + /// │ Int256( 1) │ 0.........1 │ 001 │ + /// │ Int256( 0) │ 0.......... │ 000 │ /// │ Int256(-1) │ 1.......... │ 256 │ /// │ Int256(-2) │ 1.........0 │ 255 │ /// │ Int256(-3) │ 1........01 │ 255 │ @@ -133,10 +133,10 @@ where Magnitude: NBKUnsignedInteger, Words: Sendable { /// │ Int256( 2) │ 0........10 │ 254 │ /// │ Int256( 1) │ 0.........1 │ 255 │ /// │ Int256( 0) │ 0.......... │ 256 │ - /// │ Int256(-1) │ 1.......... │ 0 │ - /// │ Int256(-2) │ 1.........0 │ 0 │ - /// │ Int256(-3) │ 1........01 │ 0 │ - /// │ Int256(-4) │ 1........00 │ 0 │ + /// │ Int256(-1) │ 1.......... │ 000 │ + /// │ Int256(-2) │ 1.........0 │ 000 │ + /// │ Int256(-3) │ 1........01 │ 000 │ + /// │ Int256(-4) │ 1........00 │ 000 │ /// └─────────── = ─────────── → ────────┘ /// ``` /// @@ -154,14 +154,14 @@ where Magnitude: NBKUnsignedInteger, Words: Sendable { /// ┌───────────────────────── → ────────┐ /// │ self │ t.z.b.c │ /// ├─────────── = ─────────── → ────────┤ - /// │ Int256( 3) │ 0........11 │ 0 │ - /// │ Int256( 2) │ 0........10 │ 1 │ - /// │ Int256( 1) │ 0.........1 │ 0 │ + /// │ Int256( 3) │ 0........11 │ 000 │ + /// │ Int256( 2) │ 0........10 │ 001 │ + /// │ Int256( 1) │ 0.........1 │ 000 │ /// │ Int256( 0) │ 0.......... │ 256 │ - /// │ Int256(-1) │ 1.......... │ 0 │ - /// │ Int256(-2) │ 1.........0 │ 1 │ - /// │ Int256(-3) │ 1........01 │ 0 │ - /// │ Int256(-4) │ 1........00 │ 2 │ + /// │ Int256(-1) │ 1.......... │ 000 │ + /// │ Int256(-2) │ 1.........0 │ 001 │ + /// │ Int256(-3) │ 1........01 │ 000 │ + /// │ Int256(-4) │ 1........00 │ 002 │ /// └─────────── = ─────────── → ────────┘ /// ``` /// diff --git a/Sources/NBKCoreKit/Private/NBK+Collection.swift b/Sources/NBKCoreKit/Private/NBK+Collection.swift index 40570650..0875e484 100644 --- a/Sources/NBKCoreKit/Private/NBK+Collection.swift +++ b/Sources/NBKCoreKit/Private/NBK+Collection.swift @@ -17,7 +17,7 @@ extension NBK { // MARK: Transformations x Drop //=------------------------------------------------------------------------= - /// Drops elements that the satisfy the predicate from the end of the given `collection`. + /// Drops elements that satisfy the predicate from the end of the given `collection`. @_transparent public static func dropLast(from collection: T, while predicate: (T.Element) -> Bool) -> T.SubSequence where T: BidirectionalCollection { var newEndIndex = collection.endIndex diff --git a/Tests/NBKCoreKitTests/Private/NBK+BitCast.swift b/Tests/NBKCoreKitTests/Private/NBK+BitCast.swift index 2ae6c93c..a18ceeb8 100644 --- a/Tests/NBKCoreKitTests/Private/NBK+BitCast.swift +++ b/Tests/NBKCoreKitTests/Private/NBK+BitCast.swift @@ -22,8 +22,8 @@ final class NBKTestsOnBitCast: XCTestCase { // MARK: State //=------------------------------------------------------------------------= - let uint32_top = UInt32.max >> 01 - let uint64_top = UInt64.max >> 01 + let uint32_mid = UInt32.max >> 01 + let uint64_mid = UInt64.max >> 01 let uint32_msb = UInt32( 1) << 31 let uint64_msb = UInt64( 1) << 63 @@ -66,28 +66,28 @@ final class NBKTestsOnBitCast: XCTestCase { func testInitOrBitCastUInt32AsUInt32() { NBKAssertInitOrBitCast(UInt32.min, exactly: UInt32( ) >> 00, clamping: UInt32( ) >> 00, truncating: UInt32( ) >> 00) - NBKAssertInitOrBitCast(uint32_top, exactly: UInt32.max >> 01, clamping: UInt32.max >> 01, truncating: UInt32.max >> 01) + NBKAssertInitOrBitCast(uint32_mid, exactly: UInt32.max >> 01, clamping: UInt32.max >> 01, truncating: UInt32.max >> 01) NBKAssertInitOrBitCast(uint32_msb, exactly: UInt32( 1) << 31, clamping: UInt32( 1) << 31, truncating: UInt32( 1) << 31) NBKAssertInitOrBitCast(UInt32.max, exactly: UInt32.max >> 00, clamping: UInt32.max >> 00, truncating: UInt32.max >> 00) } func testInitOrBitCastUInt32AsUInt64() { NBKAssertInitOrBitCast(UInt32.min, exactly: UInt64( ) >> 32, clamping: UInt64( ) >> 32, truncating: UInt64( ) >> 32) - NBKAssertInitOrBitCast(uint32_top, exactly: UInt64.max >> 33, clamping: UInt64.max >> 33, truncating: UInt64.max >> 33) + NBKAssertInitOrBitCast(uint32_mid, exactly: UInt64.max >> 33, clamping: UInt64.max >> 33, truncating: UInt64.max >> 33) NBKAssertInitOrBitCast(uint32_msb, exactly: UInt64( 1) << 31, clamping: UInt64( 1) << 31, truncating: UInt64( 1) << 31) NBKAssertInitOrBitCast(UInt32.max, exactly: UInt64.max >> 32, clamping: UInt64.max >> 32, truncating: UInt64.max >> 32) } func testInitOrBitCastUInt64AsUInt32() { NBKAssertInitOrBitCast(UInt64.min, exactly: UInt32( ) >> 00, clamping: UInt32( ) >> 00, truncating: UInt32( ) >> 00) - NBKAssertInitOrBitCast(uint64_top, exactly: nil, clamping: UInt32.max >> 00, truncating: UInt32.max >> 00) + NBKAssertInitOrBitCast(uint64_mid, exactly: nil, clamping: UInt32.max >> 00, truncating: UInt32.max >> 00) NBKAssertInitOrBitCast(uint64_msb, exactly: nil, clamping: UInt32.max >> 00, truncating: UInt32( ) << 00) NBKAssertInitOrBitCast(UInt64.max, exactly: nil, clamping: UInt32.max >> 00, truncating: UInt32.max >> 00) } func testInitOrBitCastUInt64AsUInt64() { NBKAssertInitOrBitCast(UInt64.min, exactly: UInt64( ) >> 00, clamping: UInt64( ) >> 00, truncating: UInt64( ) >> 00) - NBKAssertInitOrBitCast(uint64_top, exactly: UInt64.max >> 01, clamping: UInt64.max >> 01, truncating: UInt64.max >> 01) + NBKAssertInitOrBitCast(uint64_mid, exactly: UInt64.max >> 01, clamping: UInt64.max >> 01, truncating: UInt64.max >> 01) NBKAssertInitOrBitCast(uint64_msb, exactly: UInt64( 1) << 63, clamping: UInt64( 1) << 63, truncating: UInt64( 1) << 63) NBKAssertInitOrBitCast(UInt64.max, exactly: UInt64.max >> 00, clamping: UInt64.max >> 00, truncating: UInt64.max >> 00) } @@ -130,28 +130,28 @@ final class NBKTestsOnBitCast: XCTestCase { func testInitOrBitCastUInt32AsInt32() { NBKAssertInitOrBitCast(UInt32.min, exactly: Int32( ) >> 00, clamping: Int32( ) >> 00, truncating: Int32( ) >> 00) - NBKAssertInitOrBitCast(uint32_top, exactly: Int32.max >> 00, clamping: Int32.max >> 00, truncating: Int32.max >> 00) + NBKAssertInitOrBitCast(uint32_mid, exactly: Int32.max >> 00, clamping: Int32.max >> 00, truncating: Int32.max >> 00) NBKAssertInitOrBitCast(uint32_msb, exactly: nil, clamping: Int32.max >> 00, truncating: Int32.min >> 00) NBKAssertInitOrBitCast(UInt32.max, exactly: nil, clamping: Int32.max >> 00, truncating: Int32(-1) >> 00) } func testInitOrBitCastUInt32AsInt64() { NBKAssertInitOrBitCast(UInt32.min, exactly: Int64( ) >> 00, clamping: Int64( ) >> 00, truncating: Int64( ) >> 00) - NBKAssertInitOrBitCast(uint32_top, exactly: Int64.max >> 32, clamping: Int64.max >> 32, truncating: Int64.max >> 32) + NBKAssertInitOrBitCast(uint32_mid, exactly: Int64.max >> 32, clamping: Int64.max >> 32, truncating: Int64.max >> 32) NBKAssertInitOrBitCast(uint32_msb, exactly: Int64( 1) << 31, clamping: Int64( 1) << 31, truncating: Int64( 1) << 31) NBKAssertInitOrBitCast(UInt32.max, exactly: Int64.max >> 31, clamping: Int64.max >> 31, truncating: Int64.max >> 31) } func testInitOrBitCastUInt64AsInt32() { NBKAssertInitOrBitCast(UInt64.min, exactly: Int32( ) >> 00, clamping: Int32( ) >> 00, truncating: Int32( ) >> 00) - NBKAssertInitOrBitCast(uint64_top, exactly: nil, clamping: Int32.max >> 00, truncating: Int32(-1) >> 00) + NBKAssertInitOrBitCast(uint64_mid, exactly: nil, clamping: Int32.max >> 00, truncating: Int32(-1) >> 00) NBKAssertInitOrBitCast(uint64_msb, exactly: nil, clamping: Int32.max >> 00, truncating: Int32( ) >> 00) NBKAssertInitOrBitCast(UInt64.max, exactly: nil, clamping: Int32.max >> 00, truncating: Int32(-1) >> 00) } func testInitOrBitCastUInt64AsInt64() { NBKAssertInitOrBitCast(UInt64.min, exactly: Int64( ) >> 00, clamping: Int64( ) >> 00, truncating: Int64( ) >> 00) - NBKAssertInitOrBitCast(uint64_top, exactly: Int64.max >> 00, clamping: Int64.max >> 00, truncating: Int64.max >> 00) + NBKAssertInitOrBitCast(uint64_mid, exactly: Int64.max >> 00, clamping: Int64.max >> 00, truncating: Int64.max >> 00) NBKAssertInitOrBitCast(uint64_msb, exactly: nil, clamping: Int64.max >> 00, truncating: Int64.min >> 00) NBKAssertInitOrBitCast(UInt64.max, exactly: nil, clamping: Int64.max >> 00, truncating: Int64(-1) >> 00) } From 6ad7a11c7b60dfedbfaeea504b490f5bfe1efedc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sat, 12 Aug 2023 17:59:02 +0200 Subject: [PATCH 009/111] The poor man's feature flag (#55) (#57). --- Package.swift | 25 +- .../NBKDoubleWidth+Literals.swift | 56 +++ .../NBKDoubleWidth+Numbers.swift | 29 +- .../NBKDoubleWidth+Numbers.swift | 46 +- .../NBKDoubleWidth+Literals.swift | 125 ++++++ .../NBKDoubleWidth+Numbers.swift | 420 ++++++------------ 6 files changed, 342 insertions(+), 359 deletions(-) create mode 100644 Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift create mode 100644 Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Literals.swift diff --git a/Package.swift b/Package.swift index 2d00f6e7..79c531bb 100644 --- a/Package.swift +++ b/Package.swift @@ -13,15 +13,30 @@ import PackageDescription //*============================================================================* // MARK: * Numberick //*============================================================================* +// The poor man's feature flag: +// FIND...: /([*/])([*/])(flag)\*/ +// REPLACE: /$2$1$3*/ +//=----------------------------------------------------------------------------= let package = Package( name: "Numberick", platforms: [ - .iOS("16.4"), - .macCatalyst("16.4"), - .macOS("13.3"), - .tvOS("16.4"), - .watchOS("9.4"), + //=--------------------------------------= + // Static Big Int x Yay + //=--------------------------------------= + /*/SBI*/.iOS("16.4"), + /*/SBI*/.macCatalyst("16.4"), + /*/SBI*/.macOS("13.3"), + /*/SBI*/.tvOS("16.4"), + /*/SBI*/.watchOS("9.4"), + //=--------------------------------------= + // Static Big Int x Nay + //=--------------------------------------= + //*SBI*/.iOS(.v14), + //*SBI*/.macCatalyst(.v14), + //*SBI*/.macOS(.v11), + //*SBI*/.tvOS(.v14), + //*SBI*/.watchOS(.v7), ], products: [ //=--------------------------------------= diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift new file mode 100644 index 00000000..7d9f30cf --- /dev/null +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.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. +//=----------------------------------------------------------------------------= + +//*============================================================================* +// MARK: * NBK x Double Width x Literals +//*============================================================================* +//=----------------------------------------------------------------------------= +// MARK: + Version ≥ iOS 16.4, macOS 13.3 +//=----------------------------------------------------------------------------= + +/*/SBI*/extension NBKDoubleWidth { +/*/SBI*/ +/*/SBI*/ //=-----------------------------------------------------------------= +/*/SBI*/ // MARK: Initializers +/*/SBI*/ //=-----------------------------------------------------------------= +/*/SBI*/ +/*/SBI*/ @inlinable public init(integerLiteral source: StaticBigInt) { +/*/SBI*/ if let value = Self(exactlyIntegerLiteral: source) { self = value } else { +/*/SBI*/ preconditionFailure("\(Self.description) cannot represent \(source)") +/*/SBI*/ } +/*/SBI*/ } +/*/SBI*/ +/*/SBI*/ @inlinable init?(exactlyIntegerLiteral source: StaticBigInt) { +/*/SBI*/ guard Self.isSigned +/*/SBI*/ ? source.bitWidth <= Self.bitWidth +/*/SBI*/ : source.bitWidth <= Self.bitWidth + 1 && source.signum() >= 0 +/*/SBI*/ else { return nil } +/*/SBI*/ +/*/SBI*/ self = Self.uninitialized { value in +/*/SBI*/ for index in value.indices { +/*/SBI*/ value[unchecked: index] = source[index] +/*/SBI*/ } +/*/SBI*/ } +/*/SBI*/ } +/*/SBI*/} + +//=----------------------------------------------------------------------------= +// MARK: + Version < iOS 16.4, macOS 13.3 +//=----------------------------------------------------------------------------= + +//*SBI*/extension NBKDoubleWidth { +//*SBI*/ +//*SBI*/ //=----------------------------------------------------------------= +//*SBI*/ // MARK: Initializers +//*SBI*/ //=----------------------------------------------------------------= +//*SBI*/ +//*SBI*/ @inlinable public init(integerLiteral source: Int64) { +//*SBI*/ self.init(source) +//*SBI*/ } +//*SBI*/} diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Numbers.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Numbers.swift index 08402973..992f86cc 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Numbers.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Numbers.swift @@ -46,37 +46,10 @@ extension NBKDoubleWidth { // MARK: Initializers //=------------------------------------------------------------------------= - @inlinable public init(integerLiteral source: StaticBigInt) { - guard let value = Self(exactlyIntegerLiteral: source) else { - preconditionFailure("\(Self.description) cannot represent \(source)") - } - - self = value - } - - @inlinable init?(exactlyIntegerLiteral source: StaticBigInt) { - guard Self.isSigned - ? source.bitWidth <= Self.bitWidth - : source.bitWidth <= Self.bitWidth + 1 && source.signum() >= 0 - else { return nil } - - self = Self.uninitialized { value in - for index in value.indices { - value[unchecked: index] = source[index] - } - } - } - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - @inlinable public init(_ source: some BinaryInteger) { - guard let result = Self(exactly: source) else { + if let value = Self(exactly: source) { self = value } else { preconditionFailure("\(Self.description) cannot represent \(source)") } - - self = result } @inlinable public init?(exactly source: some BinaryInteger) { diff --git a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Numbers.swift b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Numbers.swift index 7e4feb20..0833e3e8 100644 --- a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Numbers.swift +++ b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Numbers.swift @@ -362,30 +362,9 @@ final class NBKDoubleWidthBenchmarksOnNumbersAsInt256: XCTestCase { } //=------------------------------------------------------------------------= - // MARK: Tests x Float + // MARK: Tests x Float (> 16 Bits) //=------------------------------------------------------------------------= - // TODO: brrr - func testToFloat16() { - var abc = NBK.blackHoleIdentity(T.max) - - for _ in 0 ..< 1_000 { - NBK.blackHole(Float16(abc)) - NBK.blackHole(Float16(exactly: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testFromFloat16() { - var abc = NBK.blackHoleIdentity(Float16(123)) - - for _ in 0 ..< 250_000 { - NBK.blackHole(T(abc)) - NBK.blackHole(T(exactly: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - // TODO: brrr func testToFloat32() { var abc = NBK.blackHoleIdentity(T.max) @@ -792,30 +771,9 @@ final class NBKDoubleWidthBenchmarksOnNumbersAsUInt256: XCTestCase { } //=------------------------------------------------------------------------= - // MARK: Tests x Float + // MARK: Tests x Float (> 16 Bits) //=------------------------------------------------------------------------= - // TODO: brrr - func testToFloat16() { - var abc = NBK.blackHoleIdentity(T.max) - - for _ in 0 ..< 1_000 { - NBK.blackHole(Float16(abc)) - NBK.blackHole(Float16(exactly: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - - func testFromFloat16() { - var abc = NBK.blackHoleIdentity(Float16(123)) - - for _ in 0 ..< 250_000 { - NBK.blackHole(T(abc)) - NBK.blackHole(T(exactly: abc)) - NBK.blackHoleInoutIdentity(&abc) - } - } - // TODO: brrr func testToFloat32() { var abc = NBK.blackHoleIdentity(T.max) diff --git a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Literals.swift b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Literals.swift new file mode 100644 index 00000000..1d43d818 --- /dev/null +++ b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Literals.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. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +@testable import NBKDoubleWidthKit +import XCTest + +private typealias X = NBK.U256X64 +private typealias Y = NBK.U256X32 + +//*============================================================================* +// MARK: * NBK x Double Width x Literals x Int256 +//*============================================================================* +//=----------------------------------------------------------------------------= +// MARK: + Version ≥ iOS 16.4, macOS 13.3 +//=----------------------------------------------------------------------------= + +/*/SBI*/final class NBKDoubleWidthTestsOnLiteralsAsInt256: XCTestCase { +/*/SBI*/ +/*/SBI*/ typealias T = Int256 +/*/SBI*/ +/*/SBI*/ //=----------------------------------------------------------------= +/*/SBI*/ // MARK: Tests +/*/SBI*/ //=----------------------------------------------------------------= +/*/SBI*/ +/*/SBI*/ func testFromIntegerLiteral() { +/*/SBI*/ XCTAssertEqual(T(x64: X( 0, 0, 0, 0)), 0x0000000000000000000000000000000000000000000000000000000000000000) +/*/SBI*/ XCTAssertEqual(T(x64: X(~0, 0, 0, 0)), 0x000000000000000000000000000000000000000000000000ffffffffffffffff) +/*/SBI*/ XCTAssertEqual(T(x64: X(~0, ~0, 0, 0)), 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) +/*/SBI*/ XCTAssertEqual(T(x64: X(~0, ~0, ~0, 0)), 0x0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff) +/*/SBI*/ XCTAssertEqual(T(x64: X(~0, ~0, ~0, ~0)), -0x0000000000000000000000000000000000000000000000000000000000000001) +/*/SBI*/ XCTAssertEqual(T(x64: X( 0, ~0, ~0, ~0)), -0x0000000000000000000000000000000000000000000000010000000000000000) +/*/SBI*/ XCTAssertEqual(T(x64: X( 0, 0, ~0, ~0)), -0x0000000000000000000000000000000100000000000000000000000000000000) +/*/SBI*/ XCTAssertEqual(T(x64: X( 0, 0, 0, ~0)), -0x0000000000000001000000000000000000000000000000000000000000000000) +/*/SBI*/ +/*/SBI*/ XCTAssertEqual(T(exactlyIntegerLiteral: 0x8000000000000000000000000000000000000000000000000000000000000000), nil) +/*/SBI*/ XCTAssertEqual(T(exactlyIntegerLiteral: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff), T.max) +/*/SBI*/ XCTAssertEqual(T(exactlyIntegerLiteral: -0x8000000000000000000000000000000000000000000000000000000000000000), T.min) +/*/SBI*/ XCTAssertEqual(T(exactlyIntegerLiteral: -0x8000000000000000000000000000000000000000000000000000000000000001), nil) +/*/SBI*/ } +/*/SBI*/} + +//=----------------------------------------------------------------------------= +// MARK: + Version < iOS 16.4, macOS 13.3 +//=----------------------------------------------------------------------------= + +//*SBI*/final class NBKDoubleWidthTestsOnLiteralsAsInt256: XCTestCase { +//*SBI*/ +//*SBI*/ typealias T = Int256 +//*SBI*/ typealias L = Int256.IntegerLiteralType +//*SBI*/ +//*SBI*/ //=----------------------------------------------------------------= +//*SBI*/ // MARK: Tests +//*SBI*/ //=----------------------------------------------------------------= +//*SBI*/ +//*SBI*/ func testFromIntegerLiteral() { +//*SBI*/ XCTAssertEqual(T(integerLiteral: 0x7fffffffffffffff as L), T(x64: X(UInt64(L.max), 0, 0, 0))) +//*SBI*/ XCTAssertEqual(T(integerLiteral: 0x0000000000000000 as L), T(x64: X(UInt64(L( )), 0, 0, 0))) +//*SBI*/ XCTAssertEqual(T(integerLiteral: -0x0000000000000001 as L), ~T(x64: X(UInt64(L( )), 0, 0, 0))) +//*SBI*/ XCTAssertEqual(T(integerLiteral: -0x8000000000000000 as L), ~T(x64: X(UInt64(L.max), 0, 0, 0))) +//*SBI*/ } +//*SBI*/} + +//*============================================================================* +// MARK: * NBK x Double Width x Literals x UInt256 +//*============================================================================* +//=----------------------------------------------------------------------------= +// MARK: + Version ≥ iOS 16.4, macOS 13.3 +//=----------------------------------------------------------------------------= + +/*/SBI*/final class NBKDoubleWidthTestsOnLiteralsAsUInt256: XCTestCase { +/*/SBI*/ +/*/SBI*/ typealias T = UInt256 +/*/SBI*/ +/*/SBI*/ //=----------------------------------------------------------------= +/*/SBI*/ // MARK: Tests +/*/SBI*/ //=----------------------------------------------------------------= +/*/SBI*/ +/*/SBI*/ func testFromIntegerLiteral() { +/*/SBI*/ XCTAssertEqual(T(x64: X( 0, 0, 0, 0)), 0x0000000000000000000000000000000000000000000000000000000000000000) +/*/SBI*/ XCTAssertEqual(T(x64: X(~0, 0, 0, 0)), 0x000000000000000000000000000000000000000000000000ffffffffffffffff) +/*/SBI*/ XCTAssertEqual(T(x64: X(~0, ~0, 0, 0)), 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) +/*/SBI*/ XCTAssertEqual(T(x64: X(~0, ~0, ~0, 0)), 0x0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff) +/*/SBI*/ XCTAssertEqual(T(x64: X(~0, ~0, ~0, ~0)), 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) +/*/SBI*/ XCTAssertEqual(T(x64: X( 0, ~0, ~0, ~0)), 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) +/*/SBI*/ XCTAssertEqual(T(x64: X( 0, 0, ~0, ~0)), 0xffffffffffffffffffffffffffffffff00000000000000000000000000000000) +/*/SBI*/ XCTAssertEqual(T(x64: X( 0, 0, 0, ~0)), 0xffffffffffffffff000000000000000000000000000000000000000000000000) +/*/SBI*/ +/*/SBI*/ XCTAssertEqual(T(exactlyIntegerLiteral: 0x010000000000000000000000000000000000000000000000000000000000000000), nil) +/*/SBI*/ XCTAssertEqual(T(exactlyIntegerLiteral: 0x00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff), T.max) +/*/SBI*/ XCTAssertEqual(T(exactlyIntegerLiteral: 0x000000000000000000000000000000000000000000000000000000000000000000), T.min) +/*/SBI*/ XCTAssertEqual(T(exactlyIntegerLiteral: -0x000000000000000000000000000000000000000000000000000000000000000001), nil) +/*/SBI*/ } +/*/SBI*/} + +//=----------------------------------------------------------------------------= +// MARK: + Version < iOS 16.4, macOS 13.3 +//=----------------------------------------------------------------------------= + +//*SBI*/final class NBKDoubleWidthTestsOnLiteralsAsUInt256: XCTestCase { +//*SBI*/ +//*SBI*/ typealias T = UInt256 +//*SBI*/ typealias L = UInt256.IntegerLiteralType +//*SBI*/ +//*SBI*/ //=----------------------------------------------------------------= +//*SBI*/ // MARK: Tests +//*SBI*/ //=----------------------------------------------------------------= +//*SBI*/ +//*SBI*/ func testFromIntegerLiteral() { +//*SBI*/ XCTAssertEqual(T(integerLiteral: 0x7fffffffffffffff as L), T(x64: X(UInt64(L.max), 0, 0, 0))) +//*SBI*/ XCTAssertEqual(T(integerLiteral: 0x0000000000000000 as L), T(x64: X(UInt64(L( )), 0, 0, 0))) +//*SBI*/ XCTAssertEqual(T(exactly: -0x0000000000000001 as L), nil) +//*SBI*/ XCTAssertEqual(T(exactly: -0x8000000000000000 as L), nil) +//*SBI*/ } +//*SBI*/} + +#endif diff --git a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Numbers.swift b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Numbers.swift index 68db9a80..8c7246c5 100644 --- a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Numbers.swift +++ b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Numbers.swift @@ -10,7 +10,7 @@ #if DEBUG import NBKCoreKit -@testable import NBKDoubleWidthKit +import NBKDoubleWidthKit import XCTest private typealias X = NBK.U256X64 @@ -45,117 +45,69 @@ final class NBKDoubleWidthTestsOnNumbersAsInt256: XCTestCase { } //=------------------------------------------------------------------------= - // MARK: Tests x Int, Digit + // MARK: Tests x 64 Bits Or Less //=------------------------------------------------------------------------= - func testFromInt() { - NBKAssertNumbers(from: Int.min, default: ~T(x64: X(UInt64(Int.max), 0, 0, 0))) - NBKAssertNumbers(from: Int.max, default: T(x64: X(UInt64(Int.max), 0, 0, 0))) - } - - func testFromIntAsDigit() { - NBKAssertNumbers(from: T(digit: Int.min), default: ~T(x64: X(UInt64(Int.max), 0, 0, 0))) - NBKAssertNumbers(from: T(digit: Int.max), default: T(x64: X(UInt64(Int.max), 0, 0, 0))) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x UInt - //=------------------------------------------------------------------------= - - func testFromUInt() { - NBKAssertNumbers(from: UInt.min, default: T(x64: X(UInt64(UInt.min), 0, 0, 0))) - NBKAssertNumbers(from: UInt.max, default: T(x64: X(UInt64(UInt.max), 0, 0, 0))) - } - - func testFromUIntAsBits() { - NBKAssertNumbers(from: T(_truncatingBits: UInt.min), default: T(x64: X(UInt64(UInt.min), 0, 0, 0))) - NBKAssertNumbers(from: T(_truncatingBits: UInt.max), default: T(x64: X(UInt64(UInt.max), 0, 0, 0))) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Int8 - //=------------------------------------------------------------------------= - - func testFromInt8() { - NBKAssertNumbers(from: Int8.min, default: T(-128)) - NBKAssertNumbers(from: Int8.max, default: T( 127)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x UInt8 - //=------------------------------------------------------------------------= - - func testFromUInt8() { - NBKAssertNumbers(from: UInt8.min, default: T()) - NBKAssertNumbers(from: UInt8.max, default: T(255)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Int16 - //=------------------------------------------------------------------------= - - func testFromInt16() { - NBKAssertNumbers(from: Int16.min, default: T(-32768)) - NBKAssertNumbers(from: Int16.max, default: T( 32767)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x UInt16 - //=------------------------------------------------------------------------= - - func testFromUInt16() { - NBKAssertNumbers(from: UInt16.min, default: T()) - NBKAssertNumbers(from: UInt16.max, default: T( 65535)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Int32 - //=------------------------------------------------------------------------= - - func testFromInt32() { - NBKAssertNumbers(from: Int32.min, default: T(-2147483648)) - NBKAssertNumbers(from: Int32.max, default: T( 2147483647)) + func testToAtMost64BitSignedInteger() { + func whereIs(_ type: I.Type) { + NBKAssertNumbers(from: T(x64: X( 1, 0, 0, 0)), default: I( 1)) + NBKAssertNumbers(from: T(x64: X(~0, 0, 0, 0)), exactly: nil, clamping: I.max, truncating: ~0) + NBKAssertNumbers(from: T(x64: X( 1, 1, 1, 1)), exactly: nil, clamping: I.max, truncating: 1) + NBKAssertNumbers(from: T(x64: X(~0, ~0, ~0, ~0)), default: I(-1)) + } + + for type: any NBKFixedWidthInteger.Type in [Int.self, Int8.self, Int16.self, Int32.self, Int64.self] { + whereIs(type) + } } - - //=------------------------------------------------------------------------= - // MARK: Tests x UInt32 - //=------------------------------------------------------------------------= - - func testFromUInt32() { - NBKAssertNumbers(from: UInt32.min, default: T()) - NBKAssertNumbers(from: UInt32.max, default: T(4294967295)) + + func testToAtMost64BitUnsignedInteger() { + func whereIs(_ type: I.Type) { + NBKAssertNumbers(from: T(x64: X( 1, 0, 0, 0)), default: I( 1)) + NBKAssertNumbers(from: T(x64: X(~0, 0, 0, 0)), default: I.max, exactly: I(exactly: UInt64.max)) + NBKAssertNumbers(from: T(x64: X( 1, 1, 1, 1)), exactly: nil, clamping: I.max, truncating: I( 1)) + NBKAssertNumbers(from: T(x64: X(~0, ~0, ~0, ~0)), exactly: nil, clamping: I.min, truncating: I.max) + } + + for type: any NBKFixedWidthInteger.Type in [UInt.self, UInt8.self, UInt16.self, UInt32.self, UInt64.self] { + whereIs(type) + } } - //=------------------------------------------------------------------------= - // MARK: Tests x Int64 - //=------------------------------------------------------------------------= - - func testToInt64() { - NBKAssertNumbers(from: T(x64: X( 1, 0, 0, 0)), default: Int64( 1)) - NBKAssertNumbers(from: T(x64: X(~0, 0, 0, 0)), exactly: nil, clamping: Int64.max, truncating: -1) - NBKAssertNumbers(from: T(x64: X( 1, 1, 1, 1)), exactly: nil, clamping: Int64.max, truncating: 1) - NBKAssertNumbers(from: T(x64: X(~0, ~0, ~0, ~0)), default: Int64(-1)) + func testFromAtMost64BitSignedInteger() { + func whereIs(_ type: I.Type) { + NBKAssertNumbers(from: I.min, default: ~T(x64: X(UInt64(I.max), 0, 0, 0))) + NBKAssertNumbers(from: I.max, default: T(x64: X(UInt64(I.max), 0, 0, 0))) + } + + for type: any NBKFixedWidthInteger.Type in [Int.self, Int8.self, Int16.self, Int32.self, Int64.self] { + whereIs(type) + } } - func testFromInt64() { - NBKAssertNumbers(from: Int64.min, default: T(-9223372036854775808)) - NBKAssertNumbers(from: Int64.max, default: T( 9223372036854775807)) + func testFromAtMost64BitUnsignedInteger() { + func whereIs(_ type: I.Type) { + NBKAssertNumbers(from: I.min, default: T(x64: X(UInt64(I.min), 0, 0, 0))) + NBKAssertNumbers(from: I.max, default: T(x64: X(UInt64(I.max), 0, 0, 0))) + } + + for type: any NBKFixedWidthInteger.Type in [UInt.self, UInt8.self, UInt16.self, UInt32.self, UInt64.self] { + whereIs(type) + } } //=------------------------------------------------------------------------= - // MARK: Tests x UInt64 + // MARK: Tests x Bits & Digit //=------------------------------------------------------------------------= - func testToUInt64() { - NBKAssertNumbers(from: T(x64: X( 1, 0, 0, 0)), default: UInt64( 1)) - NBKAssertNumbers(from: T(x64: X(~0, 0, 0, 0)), default: UInt64.max) - NBKAssertNumbers(from: T(x64: X( 1, 1, 1, 1)), exactly: nil, clamping: ~0, truncating: UInt64( 1)) - NBKAssertNumbers(from: T(x64: X(~0, ~0, ~0, ~0)), exactly: nil, clamping: 0, truncating: UInt64.max) + func testFromUIntAsBits() { + XCTAssertEqual(T(_truncatingBits: UInt.min), T(x64: X(UInt64(UInt.min), 0, 0, 0))) + XCTAssertEqual(T(_truncatingBits: UInt.max), T(x64: X(UInt64(UInt.max), 0, 0, 0))) } - func testFromUInt64() { - NBKAssertNumbers(from: UInt64.min, default: T()) - NBKAssertNumbers(from: UInt64.max, default: T(18446744073709551615)) + func testFromIntAsDigit() { + XCTAssertEqual(T(digit: Int.min), ~T(x64: X(UInt64(Int.max), 0, 0, 0))) + XCTAssertEqual(T(digit: Int.max), T(x64: X(UInt64(Int.max), 0, 0, 0))) } //=------------------------------------------------------------------------= @@ -222,7 +174,7 @@ final class NBKDoubleWidthTestsOnNumbersAsInt256: XCTestCase { } //=------------------------------------------------------------------------= - // MARK: Tests x Float32 + // MARK: Tests x Float (> 16 Bits) //=------------------------------------------------------------------------= func testToFloat32() { @@ -236,6 +188,18 @@ final class NBKDoubleWidthTestsOnNumbersAsInt256: XCTestCase { XCTAssertEqual(Float32(T(UInt32.min)), Float32(UInt32.min)) XCTAssertEqual(Float32(T(UInt32.max)), Float32(UInt32.max)) } + + func testToFloat64() { + XCTAssertEqual(Float64(T(-1)), Float64(-1)) + XCTAssertEqual(Float64(T( 0)), Float64( 0)) + XCTAssertEqual(Float64(T( 1)), Float64( 1)) + + XCTAssertEqual(Float64(T( Int64.min)), Float64( Int64.min)) + XCTAssertEqual(Float64(T( Int64.max)), Float64( Int64.max)) + + XCTAssertEqual(Float64(T(UInt64.min)), Float64(UInt64.min)) + XCTAssertEqual(Float64(T(UInt64.max)), Float64(UInt64.max)) + } func testFromFloat32() { XCTAssertEqual(T(Float32( 22.0)), 22) @@ -255,30 +219,6 @@ final class NBKDoubleWidthTestsOnNumbersAsInt256: XCTestCase { XCTAssertEqual(T(exactly: pow(2, Float32(64 * 2 - 0))), nil) } - func testFromFloat32ValuesThatAreSpecial() { - XCTAssertNil(T(exactly: Float32.nan)) - XCTAssertNil(T(exactly: Float32.infinity)) - XCTAssertNil(T(exactly: Float32.signalingNaN)) - XCTAssertNil(T(exactly: Float32.leastNormalMagnitude)) - XCTAssertNil(T(exactly: Float32.leastNonzeroMagnitude)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Float64 - //=------------------------------------------------------------------------= - - func testToFloat64() { - XCTAssertEqual(Float64(T(-1)), Float64(-1)) - XCTAssertEqual(Float64(T( 0)), Float64( 0)) - XCTAssertEqual(Float64(T( 1)), Float64( 1)) - - XCTAssertEqual(Float64(T( Int64.min)), Float64( Int64.min)) - XCTAssertEqual(Float64(T( Int64.max)), Float64( Int64.max)) - - XCTAssertEqual(Float64(T(UInt64.min)), Float64(UInt64.min)) - XCTAssertEqual(Float64(T(UInt64.max)), Float64(UInt64.max)) - } - func testFromFloat64() { XCTAssertEqual(T(Float64( 22.0)), 22) XCTAssertEqual(T(Float64( -22.0)), -22) @@ -299,6 +239,14 @@ final class NBKDoubleWidthTestsOnNumbersAsInt256: XCTestCase { XCTAssertEqual(T(exactly: pow(2, Float64(64 * 4 - 1))), 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)) + } + func testFromFloat64ValuesThatAreSpecial() { XCTAssertNil(T(exactly: Float64.nan)) XCTAssertNil(T(exactly: Float64.infinity)) @@ -324,26 +272,6 @@ final class NBKDoubleWidthTestsOnNumbersAsInt256: XCTestCase { XCTAssertEqual(T(sign: .plus, magnitude: M( )), T( )) XCTAssertEqual(T(sign: .minus, magnitude: M( )), T( )) } - - //=------------------------------------------------------------------------= - // MARK: Tests x Literal - //=------------------------------------------------------------------------= - - func testFromLiteral() { - XCTAssertEqual(T(x64: X( 0, 0, 0, 0)), 0x0000000000000000000000000000000000000000000000000000000000000000) - XCTAssertEqual(T(x64: X(~0, 0, 0, 0)), 0x000000000000000000000000000000000000000000000000ffffffffffffffff) - XCTAssertEqual(T(x64: X(~0, ~0, 0, 0)), 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) - XCTAssertEqual(T(x64: X(~0, ~0, ~0, 0)), 0x0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff) - XCTAssertEqual(T(x64: X(~0, ~0, ~0, ~0)), -0x0000000000000000000000000000000000000000000000000000000000000001) - XCTAssertEqual(T(x64: X( 0, ~0, ~0, ~0)), -0x0000000000000000000000000000000000000000000000010000000000000000) - XCTAssertEqual(T(x64: X( 0, 0, ~0, ~0)), -0x0000000000000000000000000000000100000000000000000000000000000000) - XCTAssertEqual(T(x64: X( 0, 0, 0, ~0)), -0x0000000000000001000000000000000000000000000000000000000000000000) - - XCTAssertEqual(T(exactlyIntegerLiteral: 0x8000000000000000000000000000000000000000000000000000000000000000), nil) - XCTAssertEqual(T(exactlyIntegerLiteral: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff), T.max) - XCTAssertEqual(T(exactlyIntegerLiteral: -0x8000000000000000000000000000000000000000000000000000000000000000), T.min) - XCTAssertEqual(T(exactlyIntegerLiteral: -0x8000000000000000000000000000000000000000000000000000000000000001), nil) - } } //*============================================================================* @@ -375,117 +303,69 @@ final class NBKDoubleWidthTestsOnNumbersAsUInt256: XCTestCase { } //=------------------------------------------------------------------------= - // MARK: Tests x Int - //=------------------------------------------------------------------------= - - func testFromInt() { - NBKAssertNumbers(from: Int.min, exactly: nil, clamping: 0, truncating: ~T(x64: X(UInt64(Int.max), 0, 0, 0))) - NBKAssertNumbers(from: Int.max, default: /*-------------------------*/ T(x64: X(UInt64(Int.max), 0, 0, 0))) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x UInt, Digit - //=------------------------------------------------------------------------= - - func testFromUInt() { - NBKAssertNumbers(from: UInt.min, default: T(x64: X(UInt64(UInt.min), 0, 0, 0))) - NBKAssertNumbers(from: UInt.max, default: T(x64: X(UInt64(UInt.max), 0, 0, 0))) - } - - func testFromUIntAsDigit() { - NBKAssertNumbers(from: T(digit: UInt.min), default: T(x64: X(UInt64(UInt.min), 0, 0, 0))) - NBKAssertNumbers(from: T(digit: UInt.max), default: T(x64: X(UInt64(UInt.max), 0, 0, 0))) - } - - func testFromUIntAsBits() { - NBKAssertNumbers(from: T(_truncatingBits: UInt.min), default: T(x64: X(UInt64(UInt.min), 0, 0, 0))) - NBKAssertNumbers(from: T(_truncatingBits: UInt.max), default: T(x64: X(UInt64(UInt.max), 0, 0, 0))) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Int8 - //=------------------------------------------------------------------------= - - func testFromInt8() { - NBKAssertNumbers(from: Int8.min, exactly: nil, clamping: 0, truncating: ~T(127)) - NBKAssertNumbers(from: Int8.max, default: /*-------------------------*/ T(127)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x UInt8 - //=------------------------------------------------------------------------= - - func testFromUInt8() { - NBKAssertNumbers(from: UInt8.min, default: T()) - NBKAssertNumbers(from: UInt8.max, default: T(255)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Int16 - //=------------------------------------------------------------------------= - - func testFromInt16() { - NBKAssertNumbers(from: Int16.min, exactly: nil, clamping: 0, truncating: ~T(32767)) - NBKAssertNumbers(from: Int16.max, default: /*-------------------------*/ T(32767)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x UInt16 - //=------------------------------------------------------------------------= - - func testFromUInt16() { - NBKAssertNumbers(from: UInt16.min, default: T()) - NBKAssertNumbers(from: UInt16.max, default: T(65535)) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Int32 + // MARK: Tests x 64 Bits Or Less //=------------------------------------------------------------------------= - func testFromInt32() { - NBKAssertNumbers(from: Int32.min, exactly: nil, clamping: 0, truncating: ~T(2147483647)) - NBKAssertNumbers(from: Int32.max, default: /*-------------------------*/ T(2147483647)) + func testToAtMost64BitSignedInteger() { + func whereIs(_ type: I.Type) { + NBKAssertNumbers(from: T(x64: X( 1, 0, 0, 0)), default: 1 as I) + NBKAssertNumbers(from: T(x64: X(~0, 0, 0, 0)), exactly: nil, clamping: I.max, truncating: ~0) + NBKAssertNumbers(from: T(x64: X( 1, 1, 1, 1)), exactly: nil, clamping: I.max, truncating: 1) + NBKAssertNumbers(from: T(x64: X(~0, ~0, ~0, ~0)), exactly: nil, clamping: I.max, truncating: ~0) + } + + for type: any NBKFixedWidthInteger.Type in [Int.self, Int8.self, Int16.self, Int32.self, Int64.self] { + whereIs(type) + } } - - //=------------------------------------------------------------------------= - // MARK: Tests x UInt32 - //=------------------------------------------------------------------------= - - func testFromUInt32() { - NBKAssertNumbers(from: UInt32.min, default: T()) - NBKAssertNumbers(from: UInt32.max, default: T(4294967295)) + + func testToAtMost64BitUnsignedInteger() { + func whereIs(_ type: I.Type) { + NBKAssertNumbers(from: T(x64: X( 1, 0, 0, 0)), default: I( 1)) + NBKAssertNumbers(from: T(x64: X(~0, 0, 0, 0)), default: I.max, exactly: I(exactly: UInt64.max)) + NBKAssertNumbers(from: T(x64: X( 1, 1, 1, 1)), exactly: nil, clamping: I.max, truncating: I( 1)) + NBKAssertNumbers(from: T(x64: X(~0, ~0, ~0, ~0)), exactly: nil, clamping: I.max, truncating: I.max) + } + + for type: any NBKFixedWidthInteger.Type in [UInt.self, UInt8.self, UInt16.self, UInt32.self, UInt64.self] { + whereIs(type) + } } - //=------------------------------------------------------------------------= - // MARK: Tests x Int64 - //=------------------------------------------------------------------------= - - func testToInt64() { - NBKAssertNumbers(from: T(x64: X( 1, 0, 0, 0)), default: Int64( 1)) - NBKAssertNumbers(from: T(x64: X(~0, 0, 0, 0)), exactly: nil, clamping: Int64.max, truncating: ~0) - NBKAssertNumbers(from: T(x64: X( 1, 1, 1, 1)), exactly: nil, clamping: Int64.max, truncating: 1) - NBKAssertNumbers(from: T(x64: X(~0, ~0, ~0, ~0)), exactly: nil, clamping: Int64.max, truncating: ~0) + func testFromAtMost64BitSignedInteger() { + func whereIs(_ type: I.Type) { + NBKAssertNumbers(from: I.min, exactly: nil, clamping: 0, truncating: ~T(x64: X(UInt64(I.max), 0, 0, 0))) + NBKAssertNumbers(from: I.max, default: /*-------------------------*/ T(x64: X(UInt64(I.max), 0, 0, 0))) + } + + for type: any NBKFixedWidthInteger.Type in [Int.self, Int8.self, Int16.self, Int32.self, Int64.self] { + whereIs(type) + } } - func testFromInt64() { - NBKAssertNumbers(from: Int64.min, exactly: nil, clamping: 0, truncating: ~T(x64: X(UInt64(Int64.max), 0, 0, 0))) - NBKAssertNumbers(from: Int64.max, default: /*-------------------------*/ T(x64: X(UInt64(Int64.max), 0, 0, 0))) + func testFromAtMost64BitUnsignedInteger() { + func whereIs(_ type: I.Type) { + NBKAssertNumbers(from: I.min, default: T(x64: X(UInt64(I.min), 0, 0, 0))) + NBKAssertNumbers(from: I.max, default: T(x64: X(UInt64(I.max), 0, 0, 0))) + } + + for type: any NBKFixedWidthInteger.Type in [UInt.self, UInt8.self, UInt16.self, UInt32.self, UInt64.self] { + whereIs(type) + } } //=------------------------------------------------------------------------= - // MARK: Tests x UInt64 + // MARK: Tests x Bits & Digit //=------------------------------------------------------------------------= - func testToUInt64() { - NBKAssertNumbers(from: T(x64: X( 1, 0, 0, 0)), default: UInt64( 1)) - NBKAssertNumbers(from: T(x64: X(~0, 0, 0, 0)), default: UInt64.max) - NBKAssertNumbers(from: T(x64: X( 1, 1, 1, 1)), exactly: nil, clamping: UInt64.max, truncating: 1) - NBKAssertNumbers(from: T(x64: X(~0, ~0, ~0, ~0)), exactly: nil, clamping: UInt64.max, truncating: ~0) + func testFromUIntAsBits() { + XCTAssertEqual(T(_truncatingBits: UInt.min), T(x64: X(UInt64(UInt.min), 0, 0, 0))) + XCTAssertEqual(T(_truncatingBits: UInt.max), T(x64: X(UInt64(UInt.max), 0, 0, 0))) } - func testFromUInt64() { - NBKAssertNumbers(from: UInt64.min, default: T(x64: X(UInt64.min, 0, 0, 0))) - NBKAssertNumbers(from: UInt64.max, default: T(x64: X(UInt64.max, 0, 0, 0))) + func testFromUIntAsDigit() { + XCTAssertEqual(T(digit: UInt.min), T(x64: X(UInt64(UInt.min), 0, 0, 0))) + XCTAssertEqual(T(digit: UInt.max), T(x64: X(UInt64(UInt.max), 0, 0, 0))) } //=------------------------------------------------------------------------= @@ -508,7 +388,7 @@ final class NBKDoubleWidthTestsOnNumbersAsUInt256: XCTestCase { NBKAssertNumbers(from: S(x64: X( 1, 1, 1, 1)), default: T(x64: X( 1, 1, 1, 1))) NBKAssertNumbers(from: S(x64: X(~0, ~0, ~0, ~0)), exactly: nil, clamping: T.min, truncating: T(bitPattern: S(-1))) } - + //=------------------------------------------------------------------------= // MARK: Tests x Magnitude //=------------------------------------------------------------------------= @@ -549,7 +429,7 @@ final class NBKDoubleWidthTestsOnNumbersAsUInt256: XCTestCase { } //=------------------------------------------------------------------------= - // MARK: Tests x Float32 + // MARK: Tests x Float (> 16 Bits) //=------------------------------------------------------------------------= func testToFloat32() { @@ -559,7 +439,15 @@ final class NBKDoubleWidthTestsOnNumbersAsUInt256: XCTestCase { XCTAssertEqual(Float32(T(UInt32.min)), Float32(UInt32.min)) XCTAssertEqual(Float32(T(UInt32.max)), Float32(UInt32.max)) } + + 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 testFromFloat32() { XCTAssertEqual(T(Float32( 22.0)), 22) XCTAssertEqual(T(Float32( 22.5)), 22) @@ -576,26 +464,6 @@ final class NBKDoubleWidthTestsOnNumbersAsUInt256: XCTestCase { 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) @@ -614,6 +482,14 @@ final class NBKDoubleWidthTestsOnNumbersAsUInt256: XCTestCase { XCTAssertEqual(T(exactly: pow(2, Float64(64 * 4 - 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)) + } + func testFromFloat64ValuesThatAreSpecial() { XCTAssertNil(T(exactly: Float64.nan)) XCTAssertNil(T(exactly: Float64.infinity)) @@ -639,26 +515,6 @@ final class NBKDoubleWidthTestsOnNumbersAsUInt256: XCTestCase { XCTAssertEqual(T(sign: .plus, magnitude: M( )), T( )) XCTAssertEqual(T(sign: .minus, magnitude: M( )), T( )) } - - //=------------------------------------------------------------------------= - // MARK: Tests x Literal - //=------------------------------------------------------------------------= - - func testFromLiteral() { - XCTAssertEqual(T(x64: X( 0, 0, 0, 0)), 0x0000000000000000000000000000000000000000000000000000000000000000) - XCTAssertEqual(T(x64: X(~0, 0, 0, 0)), 0x000000000000000000000000000000000000000000000000ffffffffffffffff) - XCTAssertEqual(T(x64: X(~0, ~0, 0, 0)), 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) - XCTAssertEqual(T(x64: X(~0, ~0, ~0, 0)), 0x0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff) - XCTAssertEqual(T(x64: X(~0, ~0, ~0, ~0)), 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) - XCTAssertEqual(T(x64: X( 0, ~0, ~0, ~0)), 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) - XCTAssertEqual(T(x64: X( 0, 0, ~0, ~0)), 0xffffffffffffffffffffffffffffffff00000000000000000000000000000000) - XCTAssertEqual(T(x64: X( 0, 0, 0, ~0)), 0xffffffffffffffff000000000000000000000000000000000000000000000000) - - XCTAssertEqual(T(exactlyIntegerLiteral: 0x010000000000000000000000000000000000000000000000000000000000000000), nil) - XCTAssertEqual(T(exactlyIntegerLiteral: 0x00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff), T.max) - XCTAssertEqual(T(exactlyIntegerLiteral: 0x000000000000000000000000000000000000000000000000000000000000000000), T.min) - XCTAssertEqual(T(exactlyIntegerLiteral: -0x000000000000000000000000000000000000000000000000000000000000000001), nil) - } } //*============================================================================* From 016ed024d3bca8db045e7dea70a40a05a706d872 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sun, 13 Aug 2023 13:37:50 +0200 Subject: [PATCH 010/111] Cleanup (#57). --- Package.swift | 9 +- .../NBKDoubleWidth+Literals.swift | 75 ++++---- .../NBKDoubleWidth+Literals.swift | 168 +++++++++--------- 3 files changed, 135 insertions(+), 117 deletions(-) diff --git a/Package.swift b/Package.swift index 79c531bb..0b6f85de 100644 --- a/Package.swift +++ b/Package.swift @@ -14,8 +14,13 @@ import PackageDescription // MARK: * Numberick //*============================================================================* // The poor man's feature flag: -// FIND...: /([*/])([*/])(flag)\*/ -// REPLACE: /$2$1$3*/ +// +// FIND...: \/([*/-])([*/-])(FLAG)([*/-])\/ +// REPLACE: \/$2$1$3$4\/ +// +// LINE...: //*FLAG*/ or /*/FLAG*/ +// HEAD...: //*FLAG-/ or /*/FLAG-/ +// TAIL...: //-FLAG*/ or /-/FLAG*/ //=----------------------------------------------------------------------------= let package = Package( diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift index 7d9f30cf..5a5bbcb0 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift @@ -13,44 +13,49 @@ //=----------------------------------------------------------------------------= // MARK: + Version ≥ iOS 16.4, macOS 13.3 //=----------------------------------------------------------------------------= +//*SBI-/ -/*/SBI*/extension NBKDoubleWidth { -/*/SBI*/ -/*/SBI*/ //=-----------------------------------------------------------------= -/*/SBI*/ // MARK: Initializers -/*/SBI*/ //=-----------------------------------------------------------------= -/*/SBI*/ -/*/SBI*/ @inlinable public init(integerLiteral source: StaticBigInt) { -/*/SBI*/ if let value = Self(exactlyIntegerLiteral: source) { self = value } else { -/*/SBI*/ preconditionFailure("\(Self.description) cannot represent \(source)") -/*/SBI*/ } -/*/SBI*/ } -/*/SBI*/ -/*/SBI*/ @inlinable init?(exactlyIntegerLiteral source: StaticBigInt) { -/*/SBI*/ guard Self.isSigned -/*/SBI*/ ? source.bitWidth <= Self.bitWidth -/*/SBI*/ : source.bitWidth <= Self.bitWidth + 1 && source.signum() >= 0 -/*/SBI*/ else { return nil } -/*/SBI*/ -/*/SBI*/ self = Self.uninitialized { value in -/*/SBI*/ for index in value.indices { -/*/SBI*/ value[unchecked: index] = source[index] -/*/SBI*/ } -/*/SBI*/ } -/*/SBI*/ } -/*/SBI*/} +extension NBKDoubleWidth { + //=-------------------------------------------------------------------------= + // MARK: Initializers + //=-------------------------------------------------------------------------= + + @inlinable public init(integerLiteral source: StaticBigInt) { + if let value = Self(exactlyIntegerLiteral: source) { self = value } else { + preconditionFailure("\(Self.description) cannot represent \(source)") + } + } + + @inlinable init?(exactlyIntegerLiteral source: StaticBigInt) { + guard Self.isSigned + ? source.bitWidth <= Self.bitWidth + : source.bitWidth <= Self.bitWidth + 1 && source.signum() >= 0 + else { return nil } + + self = Self.uninitialized { value in + for index in value.indices { + value[unchecked: index] = source[index] + } + } + } +} + +//-SBI*/ //=----------------------------------------------------------------------------= // MARK: + Version < iOS 16.4, macOS 13.3 //=----------------------------------------------------------------------------= +/*/SBI-/ + +extension NBKDoubleWidth { + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + @inlinable public init(integerLiteral source: Int64) { + self.init(source) + } +} -//*SBI*/extension NBKDoubleWidth { -//*SBI*/ -//*SBI*/ //=----------------------------------------------------------------= -//*SBI*/ // MARK: Initializers -//*SBI*/ //=----------------------------------------------------------------= -//*SBI*/ -//*SBI*/ @inlinable public init(integerLiteral source: Int64) { -//*SBI*/ self.init(source) -//*SBI*/ } -//*SBI*/} +/-/SBI*/ diff --git a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Literals.swift b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Literals.swift index 1d43d818..57bf1e92 100644 --- a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Literals.swift +++ b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Literals.swift @@ -22,104 +22,112 @@ private typealias Y = NBK.U256X32 //=----------------------------------------------------------------------------= // MARK: + Version ≥ iOS 16.4, macOS 13.3 //=----------------------------------------------------------------------------= +//*SBI-/ + +final class NBKDoubleWidthTestsOnLiteralsAsInt256: XCTestCase { -/*/SBI*/final class NBKDoubleWidthTestsOnLiteralsAsInt256: XCTestCase { -/*/SBI*/ -/*/SBI*/ typealias T = Int256 -/*/SBI*/ -/*/SBI*/ //=----------------------------------------------------------------= -/*/SBI*/ // MARK: Tests -/*/SBI*/ //=----------------------------------------------------------------= -/*/SBI*/ -/*/SBI*/ func testFromIntegerLiteral() { -/*/SBI*/ XCTAssertEqual(T(x64: X( 0, 0, 0, 0)), 0x0000000000000000000000000000000000000000000000000000000000000000) -/*/SBI*/ XCTAssertEqual(T(x64: X(~0, 0, 0, 0)), 0x000000000000000000000000000000000000000000000000ffffffffffffffff) -/*/SBI*/ XCTAssertEqual(T(x64: X(~0, ~0, 0, 0)), 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) -/*/SBI*/ XCTAssertEqual(T(x64: X(~0, ~0, ~0, 0)), 0x0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff) -/*/SBI*/ XCTAssertEqual(T(x64: X(~0, ~0, ~0, ~0)), -0x0000000000000000000000000000000000000000000000000000000000000001) -/*/SBI*/ XCTAssertEqual(T(x64: X( 0, ~0, ~0, ~0)), -0x0000000000000000000000000000000000000000000000010000000000000000) -/*/SBI*/ XCTAssertEqual(T(x64: X( 0, 0, ~0, ~0)), -0x0000000000000000000000000000000100000000000000000000000000000000) -/*/SBI*/ XCTAssertEqual(T(x64: X( 0, 0, 0, ~0)), -0x0000000000000001000000000000000000000000000000000000000000000000) -/*/SBI*/ -/*/SBI*/ XCTAssertEqual(T(exactlyIntegerLiteral: 0x8000000000000000000000000000000000000000000000000000000000000000), nil) -/*/SBI*/ XCTAssertEqual(T(exactlyIntegerLiteral: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff), T.max) -/*/SBI*/ XCTAssertEqual(T(exactlyIntegerLiteral: -0x8000000000000000000000000000000000000000000000000000000000000000), T.min) -/*/SBI*/ XCTAssertEqual(T(exactlyIntegerLiteral: -0x8000000000000000000000000000000000000000000000000000000000000001), nil) -/*/SBI*/ } -/*/SBI*/} + typealias T = Int256 + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + func testFromIntegerLiteral() { + XCTAssertEqual(T(x64: X( 0, 0, 0, 0)), 0x0000000000000000000000000000000000000000000000000000000000000000) + XCTAssertEqual(T(x64: X(~0, 0, 0, 0)), 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + XCTAssertEqual(T(x64: X(~0, ~0, 0, 0)), 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + XCTAssertEqual(T(x64: X(~0, ~0, ~0, 0)), 0x0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff) + XCTAssertEqual(T(x64: X(~0, ~0, ~0, ~0)), -0x0000000000000000000000000000000000000000000000000000000000000001) + XCTAssertEqual(T(x64: X( 0, ~0, ~0, ~0)), -0x0000000000000000000000000000000000000000000000010000000000000000) + XCTAssertEqual(T(x64: X( 0, 0, ~0, ~0)), -0x0000000000000000000000000000000100000000000000000000000000000000) + XCTAssertEqual(T(x64: X( 0, 0, 0, ~0)), -0x0000000000000001000000000000000000000000000000000000000000000000) + + XCTAssertEqual(T(exactlyIntegerLiteral: 0x8000000000000000000000000000000000000000000000000000000000000000), nil) + XCTAssertEqual(T(exactlyIntegerLiteral: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff), T.max) + XCTAssertEqual(T(exactlyIntegerLiteral: -0x8000000000000000000000000000000000000000000000000000000000000000), T.min) + XCTAssertEqual(T(exactlyIntegerLiteral: -0x8000000000000000000000000000000000000000000000000000000000000001), nil) + } +} + +//-SBI*/ //=----------------------------------------------------------------------------= // MARK: + Version < iOS 16.4, macOS 13.3 //=----------------------------------------------------------------------------= +/*/SBI-/ + +final class NBKDoubleWidthTestsOnLiteralsAsInt256: XCTestCase { -//*SBI*/final class NBKDoubleWidthTestsOnLiteralsAsInt256: XCTestCase { -//*SBI*/ -//*SBI*/ typealias T = Int256 -//*SBI*/ typealias L = Int256.IntegerLiteralType -//*SBI*/ -//*SBI*/ //=----------------------------------------------------------------= -//*SBI*/ // MARK: Tests -//*SBI*/ //=----------------------------------------------------------------= -//*SBI*/ -//*SBI*/ func testFromIntegerLiteral() { -//*SBI*/ XCTAssertEqual(T(integerLiteral: 0x7fffffffffffffff as L), T(x64: X(UInt64(L.max), 0, 0, 0))) -//*SBI*/ XCTAssertEqual(T(integerLiteral: 0x0000000000000000 as L), T(x64: X(UInt64(L( )), 0, 0, 0))) -//*SBI*/ XCTAssertEqual(T(integerLiteral: -0x0000000000000001 as L), ~T(x64: X(UInt64(L( )), 0, 0, 0))) -//*SBI*/ XCTAssertEqual(T(integerLiteral: -0x8000000000000000 as L), ~T(x64: X(UInt64(L.max), 0, 0, 0))) -//*SBI*/ } -//*SBI*/} + typealias T = Int256 + typealias L = Int256.IntegerLiteralType + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testFromIntegerLiteral() { + XCTAssertEqual(T(integerLiteral: 0x7fffffffffffffff as L), T(x64: X(UInt64(L.max), 0, 0, 0))) + XCTAssertEqual(T(integerLiteral: 0x0000000000000000 as L), T(x64: X(UInt64(L( )), 0, 0, 0))) + XCTAssertEqual(T(integerLiteral: -0x0000000000000001 as L), ~T(x64: X(UInt64(L( )), 0, 0, 0))) + XCTAssertEqual(T(integerLiteral: -0x8000000000000000 as L), ~T(x64: X(UInt64(L.max), 0, 0, 0))) + } +} + +/-/SBI*/ //*============================================================================* // MARK: * NBK x Double Width x Literals x UInt256 //*============================================================================* //=----------------------------------------------------------------------------= // MARK: + Version ≥ iOS 16.4, macOS 13.3 //=----------------------------------------------------------------------------= +//*SBI-/ + +final class NBKDoubleWidthTestsOnLiteralsAsUInt256: XCTestCase { -/*/SBI*/final class NBKDoubleWidthTestsOnLiteralsAsUInt256: XCTestCase { -/*/SBI*/ -/*/SBI*/ typealias T = UInt256 -/*/SBI*/ -/*/SBI*/ //=----------------------------------------------------------------= -/*/SBI*/ // MARK: Tests -/*/SBI*/ //=----------------------------------------------------------------= -/*/SBI*/ -/*/SBI*/ func testFromIntegerLiteral() { -/*/SBI*/ XCTAssertEqual(T(x64: X( 0, 0, 0, 0)), 0x0000000000000000000000000000000000000000000000000000000000000000) -/*/SBI*/ XCTAssertEqual(T(x64: X(~0, 0, 0, 0)), 0x000000000000000000000000000000000000000000000000ffffffffffffffff) -/*/SBI*/ XCTAssertEqual(T(x64: X(~0, ~0, 0, 0)), 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) -/*/SBI*/ XCTAssertEqual(T(x64: X(~0, ~0, ~0, 0)), 0x0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff) -/*/SBI*/ XCTAssertEqual(T(x64: X(~0, ~0, ~0, ~0)), 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) -/*/SBI*/ XCTAssertEqual(T(x64: X( 0, ~0, ~0, ~0)), 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) -/*/SBI*/ XCTAssertEqual(T(x64: X( 0, 0, ~0, ~0)), 0xffffffffffffffffffffffffffffffff00000000000000000000000000000000) -/*/SBI*/ XCTAssertEqual(T(x64: X( 0, 0, 0, ~0)), 0xffffffffffffffff000000000000000000000000000000000000000000000000) -/*/SBI*/ -/*/SBI*/ XCTAssertEqual(T(exactlyIntegerLiteral: 0x010000000000000000000000000000000000000000000000000000000000000000), nil) -/*/SBI*/ XCTAssertEqual(T(exactlyIntegerLiteral: 0x00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff), T.max) -/*/SBI*/ XCTAssertEqual(T(exactlyIntegerLiteral: 0x000000000000000000000000000000000000000000000000000000000000000000), T.min) -/*/SBI*/ XCTAssertEqual(T(exactlyIntegerLiteral: -0x000000000000000000000000000000000000000000000000000000000000000001), nil) -/*/SBI*/ } -/*/SBI*/} + typealias T = UInt256 + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testFromIntegerLiteral() { + XCTAssertEqual(T(x64: X( 0, 0, 0, 0)), 0x0000000000000000000000000000000000000000000000000000000000000000) + XCTAssertEqual(T(x64: X(~0, 0, 0, 0)), 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + XCTAssertEqual(T(x64: X(~0, ~0, 0, 0)), 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + XCTAssertEqual(T(x64: X(~0, ~0, ~0, 0)), 0x0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff) + XCTAssertEqual(T(x64: X(~0, ~0, ~0, ~0)), 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + XCTAssertEqual(T(x64: X( 0, ~0, ~0, ~0)), 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + XCTAssertEqual(T(x64: X( 0, 0, ~0, ~0)), 0xffffffffffffffffffffffffffffffff00000000000000000000000000000000) + XCTAssertEqual(T(x64: X( 0, 0, 0, ~0)), 0xffffffffffffffff000000000000000000000000000000000000000000000000) + + XCTAssertEqual(T(exactlyIntegerLiteral: 0x010000000000000000000000000000000000000000000000000000000000000000), nil) + XCTAssertEqual(T(exactlyIntegerLiteral: 0x00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff), T.max) + XCTAssertEqual(T(exactlyIntegerLiteral: 0x000000000000000000000000000000000000000000000000000000000000000000), T.min) + XCTAssertEqual(T(exactlyIntegerLiteral: -0x000000000000000000000000000000000000000000000000000000000000000001), nil) + } +} + +//-SBI*/ //=----------------------------------------------------------------------------= // MARK: + Version < iOS 16.4, macOS 13.3 //=----------------------------------------------------------------------------= +/*/SBI-/ + +final class NBKDoubleWidthTestsOnLiteralsAsUInt256: XCTestCase { + + typealias T = UInt256 + typealias L = UInt256.IntegerLiteralType + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= -//*SBI*/final class NBKDoubleWidthTestsOnLiteralsAsUInt256: XCTestCase { -//*SBI*/ -//*SBI*/ typealias T = UInt256 -//*SBI*/ typealias L = UInt256.IntegerLiteralType -//*SBI*/ -//*SBI*/ //=----------------------------------------------------------------= -//*SBI*/ // MARK: Tests -//*SBI*/ //=----------------------------------------------------------------= -//*SBI*/ -//*SBI*/ func testFromIntegerLiteral() { -//*SBI*/ XCTAssertEqual(T(integerLiteral: 0x7fffffffffffffff as L), T(x64: X(UInt64(L.max), 0, 0, 0))) -//*SBI*/ XCTAssertEqual(T(integerLiteral: 0x0000000000000000 as L), T(x64: X(UInt64(L( )), 0, 0, 0))) -//*SBI*/ XCTAssertEqual(T(exactly: -0x0000000000000001 as L), nil) -//*SBI*/ XCTAssertEqual(T(exactly: -0x8000000000000000 as L), nil) -//*SBI*/ } -//*SBI*/} + func testFromIntegerLiteral() { + XCTAssertEqual(T(integerLiteral: 0x7fffffffffffffff as L), T(x64: X(UInt64(L.max), 0, 0, 0))) + XCTAssertEqual(T(integerLiteral: 0x0000000000000000 as L), T(x64: X(UInt64(L( )), 0, 0, 0))) + XCTAssertEqual(T(exactly: -0x0000000000000001 as L), nil) + XCTAssertEqual(T(exactly: -0x8000000000000000 as L), nil) + } +} +/-/SBI*/ #endif From ad22dfec08c2b20cbc85d0c34cd14d0ce59f0555 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sun, 13 Aug 2023 19:01:40 +0200 Subject: [PATCH 011/111] The rich man's feature flag (#57). --- Package.swift | 55 ++++++++++--------- .../NBKDoubleWidth+Literals.swift | 7 +-- .../NBKDoubleWidth+Literals.swift | 30 +++++----- 3 files changed, 47 insertions(+), 45 deletions(-) diff --git a/Package.swift b/Package.swift index 0b6f85de..c0ac13d6 100644 --- a/Package.swift +++ b/Package.swift @@ -13,35 +13,21 @@ import PackageDescription //*============================================================================* // MARK: * Numberick //*============================================================================* -// The poor man's feature flag: -// -// FIND...: \/([*/-])([*/-])(FLAG)([*/-])\/ -// REPLACE: \/$2$1$3$4\/ -// -// LINE...: //*FLAG*/ or /*/FLAG*/ -// HEAD...: //*FLAG-/ or /*/FLAG-/ -// TAIL...: //-FLAG*/ or /-/FLAG*/ + +let withStaticBigInt = true + +//=----------------------------------------------------------------------------= +// MARK: + Version < iOS 16.4, macOS 13.3 //=----------------------------------------------------------------------------= -let package = Package( +var package = Package( name: "Numberick", platforms: [ - //=--------------------------------------= - // Static Big Int x Yay - //=--------------------------------------= - /*/SBI*/.iOS("16.4"), - /*/SBI*/.macCatalyst("16.4"), - /*/SBI*/.macOS("13.3"), - /*/SBI*/.tvOS("16.4"), - /*/SBI*/.watchOS("9.4"), - //=--------------------------------------= - // Static Big Int x Nay - //=--------------------------------------= - //*SBI*/.iOS(.v14), - //*SBI*/.macCatalyst(.v14), - //*SBI*/.macOS(.v11), - //*SBI*/.tvOS(.v14), - //*SBI*/.watchOS(.v7), + .iOS(.v14), + .macCatalyst(.v14), + .macOS(.v11), + .tvOS(.v14), + .watchOS(.v7), ], products: [ //=--------------------------------------= @@ -100,3 +86,22 @@ let package = Package( dependencies: ["NBKDoubleWidthKit"]), ] ) + +//=----------------------------------------------------------------------------= +// MARK: + Version ≥ iOS 16.4, macOS 13.3 +//=----------------------------------------------------------------------------= + +if withStaticBigInt { + package.platforms = [ + .iOS("16.4"), + .macCatalyst("16.4"), + .macOS("13.3"), + .tvOS("16.4"), + .watchOS("9.4") + ] + + let flag = SwiftSetting.define("SBI") + for target in package.targets where target.name.hasPrefix("NBKDoubleWidthKit") { + target.swiftSettings?.append(flag) ?? (target.swiftSettings = [flag]) + } +} diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift index 5a5bbcb0..cb3e6aee 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift @@ -13,7 +13,7 @@ //=----------------------------------------------------------------------------= // MARK: + Version ≥ iOS 16.4, macOS 13.3 //=----------------------------------------------------------------------------= -//*SBI-/ +#if swift(>=5.8) && SBI extension NBKDoubleWidth { @@ -41,11 +41,10 @@ extension NBKDoubleWidth { } } -//-SBI*/ +#else //=----------------------------------------------------------------------------= // MARK: + Version < iOS 16.4, macOS 13.3 //=----------------------------------------------------------------------------= -/*/SBI-/ extension NBKDoubleWidth { @@ -58,4 +57,4 @@ extension NBKDoubleWidth { } } -/-/SBI*/ +#endif diff --git a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Literals.swift b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Literals.swift index 57bf1e92..3066bd8a 100644 --- a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Literals.swift +++ b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Literals.swift @@ -22,8 +22,8 @@ private typealias Y = NBK.U256X32 //=----------------------------------------------------------------------------= // MARK: + Version ≥ iOS 16.4, macOS 13.3 //=----------------------------------------------------------------------------= -//*SBI-/ - +#if swift(>=5.8) && SBI + final class NBKDoubleWidthTestsOnLiteralsAsInt256: XCTestCase { typealias T = Int256 @@ -49,11 +49,10 @@ final class NBKDoubleWidthTestsOnLiteralsAsInt256: XCTestCase { } } -//-SBI*/ +#else //=----------------------------------------------------------------------------= // MARK: + Version < iOS 16.4, macOS 13.3 //=----------------------------------------------------------------------------= -/*/SBI-/ final class NBKDoubleWidthTestsOnLiteralsAsInt256: XCTestCase { @@ -72,23 +71,23 @@ final class NBKDoubleWidthTestsOnLiteralsAsInt256: XCTestCase { } } -/-/SBI*/ +#endif //*============================================================================* // MARK: * NBK x Double Width x Literals x UInt256 //*============================================================================* //=----------------------------------------------------------------------------= // MARK: + Version ≥ iOS 16.4, macOS 13.3 //=----------------------------------------------------------------------------= -//*SBI-/ +#if swift(>=5.8) && SBI final class NBKDoubleWidthTestsOnLiteralsAsUInt256: XCTestCase { - + typealias T = UInt256 - + //=------------------------------------------------------------------------= // MARK: Tests //=------------------------------------------------------------------------= - + func testFromIntegerLiteral() { XCTAssertEqual(T(x64: X( 0, 0, 0, 0)), 0x0000000000000000000000000000000000000000000000000000000000000000) XCTAssertEqual(T(x64: X(~0, 0, 0, 0)), 0x000000000000000000000000000000000000000000000000ffffffffffffffff) @@ -98,7 +97,7 @@ final class NBKDoubleWidthTestsOnLiteralsAsUInt256: XCTestCase { XCTAssertEqual(T(x64: X( 0, ~0, ~0, ~0)), 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) XCTAssertEqual(T(x64: X( 0, 0, ~0, ~0)), 0xffffffffffffffffffffffffffffffff00000000000000000000000000000000) XCTAssertEqual(T(x64: X( 0, 0, 0, ~0)), 0xffffffffffffffff000000000000000000000000000000000000000000000000) - + XCTAssertEqual(T(exactlyIntegerLiteral: 0x010000000000000000000000000000000000000000000000000000000000000000), nil) XCTAssertEqual(T(exactlyIntegerLiteral: 0x00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff), T.max) XCTAssertEqual(T(exactlyIntegerLiteral: 0x000000000000000000000000000000000000000000000000000000000000000000), T.min) @@ -106,21 +105,20 @@ final class NBKDoubleWidthTestsOnLiteralsAsUInt256: XCTestCase { } } -//-SBI*/ +#else //=----------------------------------------------------------------------------= // MARK: + Version < iOS 16.4, macOS 13.3 //=----------------------------------------------------------------------------= -/*/SBI-/ final class NBKDoubleWidthTestsOnLiteralsAsUInt256: XCTestCase { - + typealias T = UInt256 typealias L = UInt256.IntegerLiteralType - + //=------------------------------------------------------------------------= // MARK: Tests //=------------------------------------------------------------------------= - + func testFromIntegerLiteral() { XCTAssertEqual(T(integerLiteral: 0x7fffffffffffffff as L), T(x64: X(UInt64(L.max), 0, 0, 0))) XCTAssertEqual(T(integerLiteral: 0x0000000000000000 as L), T(x64: X(UInt64(L( )), 0, 0, 0))) @@ -129,5 +127,5 @@ final class NBKDoubleWidthTestsOnLiteralsAsUInt256: XCTestCase { } } -/-/SBI*/ +#endif #endif From db9300b185c0b4382c0414973d90dd0e701494ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Mon, 14 Aug 2023 15:12:42 +0200 Subject: [PATCH 012/111] Cleanup. --- Package.swift | 4 +- .../NBKDoubleWidth+Literals.swift | 46 +++++++++---------- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/Package.swift b/Package.swift index c0ac13d6..24522fe4 100644 --- a/Package.swift +++ b/Package.swift @@ -97,11 +97,11 @@ if withStaticBigInt { .macCatalyst("16.4"), .macOS("13.3"), .tvOS("16.4"), - .watchOS("9.4") + .watchOS("9.4"), ] let flag = SwiftSetting.define("SBI") - for target in package.targets where target.name.hasPrefix("NBKDoubleWidthKit") { + for target in package.targets { target.swiftSettings?.append(flag) ?? (target.swiftSettings = [flag]) } } diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift index cb3e6aee..56a71748 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift @@ -16,29 +16,29 @@ #if swift(>=5.8) && SBI extension NBKDoubleWidth { - - //=-------------------------------------------------------------------------= - // MARK: Initializers - //=-------------------------------------------------------------------------= - - @inlinable public init(integerLiteral source: StaticBigInt) { - if let value = Self(exactlyIntegerLiteral: source) { self = value } else { - preconditionFailure("\(Self.description) cannot represent \(source)") - } - } - - @inlinable init?(exactlyIntegerLiteral source: StaticBigInt) { - guard Self.isSigned - ? source.bitWidth <= Self.bitWidth - : source.bitWidth <= Self.bitWidth + 1 && source.signum() >= 0 - else { return nil } - - self = Self.uninitialized { value in - for index in value.indices { - value[unchecked: index] = source[index] - } - } - } + + //=-------------------------------------------------------------------------= + // MARK: Initializers + //=-------------------------------------------------------------------------= + + @inlinable public init(integerLiteral source: StaticBigInt) { + if let value = Self(exactlyIntegerLiteral: source) { self = value } else { + preconditionFailure("\(Self.description) cannot represent \(source)") + } + } + + @inlinable init?(exactlyIntegerLiteral source: StaticBigInt) { + guard Self.isSigned + ? source.bitWidth <= Self.bitWidth + : source.bitWidth <= Self.bitWidth + 1 && source.signum() >= 0 + else { return nil } + + self = Self.uninitialized { value in + for index in value.indices { + value[unchecked: index] = source[index] + } + } + } } #else From 51df05379d183153657799c333929549281adfa3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Mon, 14 Aug 2023 15:14:19 +0200 Subject: [PATCH 013/111] Lower the minimum Swift version to 5.7 (#58). --- Package.swift | 2 +- README.md | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Package.swift b/Package.swift index 24522fe4..203b227f 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version: 5.8 +// swift-tools-version: 5.7 //=----------------------------------------------------------------------------= // This source file is part of the Numberick open source project. // diff --git a/README.md b/README.md index cb52a1bf..0ae84079 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ | Package | Swift | iOS | iPadOS | Mac Catalyst | macOS | tvOS | watchOS | |:-------:|:-----:|:----:|:------:|:------------:|:-----:|:----:|:-------:| | 0.8.0 | 5.8 | 16.4 | 16.4 | 16.4 | 13.3 | 16.4 | 9.4 | +| 0.9.0 | 5.7 | 16.4 | 16.4 | 16.4 | 13.3 | 16.4 | 9.4 | ## NBKCoreKit ([Sources][COR/S], [Tests][COR/T], [Benchmarks][COR/B]) From f7e9c17e40ed87d339b3aea6b758208f0174775d Mon Sep 17 00:00:00 2001 From: Yehor Popovych Date: Mon, 14 Aug 2023 17:54:49 +0100 Subject: [PATCH 014/111] removed duplicate --- .../NBKDoubleWidth+IntegerLiteral.swift | 50 ------------------- 1 file changed, 50 deletions(-) delete mode 100644 Sources/NBKDoubleWidthKit/NBKDoubleWidth+IntegerLiteral.swift diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+IntegerLiteral.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+IntegerLiteral.swift deleted file mode 100644 index b206fff6..00000000 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+IntegerLiteral.swift +++ /dev/null @@ -1,50 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -//*============================================================================* -// MARK: * NBK x Double Width x IntegerLiteral -//*============================================================================* - -extension NBKDoubleWidth { - public typealias IntegerLiteralType = Int64 - - @inlinable public init(integerLiteral source: Int64) { - self.init(source) - } -} - -// StaticBigInt available only from macOS 13.3. -// Enable when drop old OS support -//extension NBKDoubleWidth { -// -// //=------------------------------------------------------------------------= -// // MARK: Initializers -// //=------------------------------------------------------------------------= -// -// @inlinable public init(integerLiteral source: StaticBigInt) { -// guard let value = Self(exactlyIntegerLiteral: source) else { -// preconditionFailure("\(Self.description) cannot represent \(source)") -// } -// -// self = value -// } -// -// @inlinable init?(exactlyIntegerLiteral source: StaticBigInt) { -// guard Self.isSigned -// ? source.bitWidth <= Self.bitWidth -// : source.bitWidth <= Self.bitWidth + 1 && source.signum() >= 0 -// else { return nil } -// -// self = Self.uninitialized { value in -// for index in value.indices { -// value[unchecked: index] = source[index] -// } -// } -// } -//} From 16d0f4a034622334cafc89419ef4540674db8e31 Mon Sep 17 00:00:00 2001 From: Yehor Popovych Date: Mon, 14 Aug 2023 18:43:20 +0100 Subject: [PATCH 015/111] custom features in Package.swift and CocoaPods --- .github/workflows/deploy.yml | 11 +++++- .github/workflows/test.yml | 48 ++++++++++++++++++++++++--- pods/Numberick-CoreKit.podspec | 19 ++++++++--- pods/Numberick-DoubleWidthKit.podspec | 19 ++++++++--- pods/Numberick.podspec | 14 ++++++-- 5 files changed, 93 insertions(+), 18 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 1de5338f..4559f8aa 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -1,7 +1,9 @@ name: Publish CocoaPods package on: release: - types: [created] + types: [created] +env: + SWIFT_CUSTOM_FEATURES: 'StaticBigInt' jobs: publish: runs-on: macos-13 @@ -18,6 +20,13 @@ jobs: sed -i '' "s|[[:blank:]]*s\.version[[:blank:]].*|s.version = '${VERSION}'|g" pods/Numberick-CoreKit.podspec sed -i '' "s|[[:blank:]]*s\.version[[:blank:]].*|s.version = '${VERSION}'|g" pods/Numberick-DoubleWidthKit.podspec sed -i '' "s|[[:blank:]]*s\.version[[:blank:]].*|s.version = '${VERSION}'|g" pods/Numberick.podspec + - name: Set enabled features in this branch + run: | + for feature in "${{ env.SWIFT_CUSTOM_FEATURES }}" + do + status=$(cat Package.swift | sed -n "s|^.*with${feature}[[:blank:]]*=[[:blank:]]\(.*\)$|\1|p") + echo "SWIFT_FEATURE_${feature}=${status}" >> "$GITHUB_ENV" + done - name: Publish 'Numberick-CoreKit' Pod run: pod trunk push --allow-warnings --synchronous pods/Numberick-CoreKit.podspec env: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 57009dab..7c3ddf01 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -4,7 +4,16 @@ jobs: macos: strategy: matrix: - xcode: ['14.2', '14.3.1'] + env: + - xcode: '14.2' + enabled_features: '' + disabled_features: 'StaticBigInt' + - xcode: '14.3.1' + enabled_features: '' + disabled_features: 'StaticBigInt' + - xcode: '14.3.1' + enabled_features: 'StaticBigInt' + disabled_features: '' runs-on: macos-13 steps: - name: Checkout @@ -14,8 +23,20 @@ jobs: tempfile=$(mktemp -u).zip zip -r "${tempfile}" ./* echo "SOURCES_ZIP=${tempfile}" >> "$GITHUB_ENV" + - name: Select Swift custom features + run: | + for feature in "${{ matrix.env.enabled_features }}" + do + sed -i '' "s|^\(.*\)with${feature}[[:blank:]]*=[[:blank:]].*$|\1 with${feature} = true|g" Package.swift + echo "SWIFT_FEATURE_${feature}=true" >> "$GITHUB_ENV" + done + for feature in "${{ matrix.env.disabled_features }}" + do + sed -i '' "s|^\(.*\)with${feature}[[:blank:]]*=[[:blank:]].*$|\1 with${feature} = false|g" Package.swift + echo "SWIFT_FEATURE_${feature}=false" >> "$GITHUB_ENV" + done - name: Select Xcode - run: sudo xcode-select -s /Applications/Xcode_${{ matrix.xcode }}.app + run: sudo xcode-select -s /Applications/Xcode_${{ matrix.env.xcode }}.app - name: Build and Test macOS run: xcodebuild test -scheme 'Numberick' -destination "platform=macOS" - name: Benchmarks macOS @@ -67,14 +88,33 @@ jobs: linux: strategy: matrix: - swift: ['5.7', '5.8'] + env: + - swift: '5.7' + enabled_features: '' + disabled_features: 'StaticBigInt' + - swift: '5.8' + enabled_features: '' + disabled_features: 'StaticBigInt' + - swift: '5.8' + enabled_features: 'StaticBigInt' + disabled_features: '' runs-on: ubuntu-latest container: - image: swift:${{ matrix.swift }} + image: swift:${{ matrix.env.swift }} options: --cap-add=SYS_PTRACE --security-opt seccomp=unconfined --security-opt apparmor=unconfined steps: - name: Checkout uses: actions/checkout@v3 + - name: Select Swift custom features + run: | + for feature in "${{ matrix.env.enabled_features }}" + do + sed -i '' "s|^\(.*\)with${feature}[[:blank:]]*=[[:blank:]].*$|\1 with${feature} = true|g" Package.swift + done + for feature in "${{ matrix.env.disabled_features }}" + do + sed -i '' "s|^\(.*\)with${feature}[[:blank:]]*=[[:blank:]].*$|\1 with${feature} = false|g" Package.swift + done - name: Build and Test run: swift test - name: Run Benchmarks diff --git a/pods/Numberick-CoreKit.podspec b/pods/Numberick-CoreKit.podspec index bbd524e3..d90f045f 100644 --- a/pods/Numberick-CoreKit.podspec +++ b/pods/Numberick-CoreKit.podspec @@ -13,15 +13,24 @@ Pod::Spec.new do |s| s.author = { 'Oscar Byström Ericsson' => 'oscbyspro@protonmail.com' } s.source = { :git => 'https://github.com/oscbyspro/Numberick.git', :tag => "v#{s.version}" } - base_platforms = { :ios => '14.0', :osx => '11.0', :tvos => '14.0' } + base_platforms = { :ios => '14.0', :osx => '11.0', :tvos => '14.0' } - s.platforms = base_platforms.merge({ :watchos => '7.0' }) + s.platforms = base_platforms.merge({ :watchos => '7.0' }) - s.module_name = 'NBKCoreKit' + s.module_name = 'NBKCoreKit' - s.swift_version = '5.7' + s.swift_version = '5.7' - s.source_files = 'Sources/NBKCoreKit/**/*.swift' + s.source_files = 'Sources/NBKCoreKit/**/*.swift' + + s.pod_target_xcconfig = { 'OTHER_SWIFT_FLAGS' => '' } + + if ENV['SWIFT_FEATURE_StaticBigInt'] == 'true' + base_platforms = { :ios => '16.4', :osx => '13.3', :tvos => '16.4' } + s.platforms = base_platforms.merge({ :watchos => '9.4' }) + s.swift_version = '5.8' + s.pod_target_xcconfig['OTHER_SWIFT_FLAGS'] += '-DSBI ' + end s.test_spec 'Tests' do |ts| ts.platforms = base_platforms diff --git a/pods/Numberick-DoubleWidthKit.podspec b/pods/Numberick-DoubleWidthKit.podspec index fd845360..2f266c62 100644 --- a/pods/Numberick-DoubleWidthKit.podspec +++ b/pods/Numberick-DoubleWidthKit.podspec @@ -14,15 +14,24 @@ Pod::Spec.new do |s| s.author = { 'Oscar Byström Ericsson' => 'oscbyspro@protonmail.com' } s.source = { :git => 'https://github.com/oscbyspro/Numberick.git', :tag => "v#{s.version}" } - base_platforms = { :ios => '14.0', :osx => '11.0', :tvos => '14.0' } + base_platforms = { :ios => '14.0', :osx => '11.0', :tvos => '14.0' } - s.platforms = base_platforms.merge({ :watchos => '7.0' }) + s.platforms = base_platforms.merge({ :watchos => '7.0' }) - s.module_name = 'NBKDoubleWidthKit' + s.module_name = 'NBKDoubleWidthKit' - s.swift_version = '5.7' + s.swift_version = '5.7' - s.source_files = 'Sources/NBKDoubleWidthKit/**/*.swift' + s.source_files = 'Sources/NBKDoubleWidthKit/**/*.swift' + + s.pod_target_xcconfig = { 'OTHER_SWIFT_FLAGS' => '' } + + if ENV['SWIFT_FEATURE_StaticBigInt'] == 'true' + base_platforms = { :ios => '16.4', :osx => '13.3', :tvos => '16.4' } + s.platforms = base_platforms.merge({ :watchos => '9.4' }) + s.swift_version = '5.8' + s.pod_target_xcconfig['OTHER_SWIFT_FLAGS'] += '-DSBI ' + end s.dependency 'Numberick-CoreKit', "#{s.version}" diff --git a/pods/Numberick.podspec b/pods/Numberick.podspec index 851e7698..6b6709b0 100644 --- a/pods/Numberick.podspec +++ b/pods/Numberick.podspec @@ -14,11 +14,19 @@ Pod::Spec.new do |s| s.author = { 'Oscar Byström Ericsson' => 'oscbyspro@protonmail.com' } s.source = { :git => 'https://github.com/oscbyspro/Numberick.git', :tag => "v#{s.version}" } - s.platforms = { :ios => '14.0', :osx => '11.0', :tvos => '14.0', :watchos => '7.0' } + s.platforms = { :ios => '14.0', :osx => '11.0', :tvos => '14.0', :watchos => '7.0' } - s.swift_version = '5.7' + s.swift_version = '5.7' - s.source_files = 'Sources/Numberick/**/*.swift' + s.source_files = 'Sources/Numberick/**/*.swift' + + s.pod_target_xcconfig = { 'OTHER_SWIFT_FLAGS' => '' } + + if ENV['SWIFT_FEATURE_StaticBigInt'] == 'true' + s.platforms = { :ios => '16.4', :osx => '13.3', :tvos => '16.4', :watchos => '9.4' } + s.swift_version = '5.8' + s.pod_target_xcconfig['OTHER_SWIFT_FLAGS'] += '-DSBI ' + end s.dependency 'Numberick-CoreKit', "#{s.version}" s.dependency 'Numberick-DoubleWidthKit', "#{s.version}" From 12dc59309eb963964956bca63df489edb5d61d85 Mon Sep 17 00:00:00 2001 From: Yehor Popovych Date: Mon, 14 Aug 2023 18:55:31 +0100 Subject: [PATCH 016/111] fixed sed for linux. Removed empty features --- .github/workflows/deploy.yml | 3 ++- .github/workflows/test.yml | 8 ++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 4559f8aa..0f5caead 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -20,10 +20,11 @@ jobs: sed -i '' "s|[[:blank:]]*s\.version[[:blank:]].*|s.version = '${VERSION}'|g" pods/Numberick-CoreKit.podspec sed -i '' "s|[[:blank:]]*s\.version[[:blank:]].*|s.version = '${VERSION}'|g" pods/Numberick-DoubleWidthKit.podspec sed -i '' "s|[[:blank:]]*s\.version[[:blank:]].*|s.version = '${VERSION}'|g" pods/Numberick.podspec - - name: Set enabled features in this branch + - name: Set enabled features in this branch for CocoaPods run: | for feature in "${{ env.SWIFT_CUSTOM_FEATURES }}" do + [ ! -z "${feature}" ] || continue status=$(cat Package.swift | sed -n "s|^.*with${feature}[[:blank:]]*=[[:blank:]]\(.*\)$|\1|p") echo "SWIFT_FEATURE_${feature}=${status}" >> "$GITHUB_ENV" done diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7c3ddf01..f9881bda 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -27,11 +27,13 @@ jobs: run: | for feature in "${{ matrix.env.enabled_features }}" do + [ ! -z "${feature}" ] || continue sed -i '' "s|^\(.*\)with${feature}[[:blank:]]*=[[:blank:]].*$|\1 with${feature} = true|g" Package.swift echo "SWIFT_FEATURE_${feature}=true" >> "$GITHUB_ENV" done for feature in "${{ matrix.env.disabled_features }}" do + [ ! -z "${feature}" ] || continue sed -i '' "s|^\(.*\)with${feature}[[:blank:]]*=[[:blank:]].*$|\1 with${feature} = false|g" Package.swift echo "SWIFT_FEATURE_${feature}=false" >> "$GITHUB_ENV" done @@ -109,11 +111,13 @@ jobs: run: | for feature in "${{ matrix.env.enabled_features }}" do - sed -i '' "s|^\(.*\)with${feature}[[:blank:]]*=[[:blank:]].*$|\1 with${feature} = true|g" Package.swift + [ ! -z "${feature}" ] || continue + sed -i "s|^\(.*\)with${feature}[[:blank:]]*=[[:blank:]].*$|\1 with${feature} = true|g" Package.swift done for feature in "${{ matrix.env.disabled_features }}" do - sed -i '' "s|^\(.*\)with${feature}[[:blank:]]*=[[:blank:]].*$|\1 with${feature} = false|g" Package.swift + [ ! -z "${feature}" ] || continue + sed -i "s|^\(.*\)with${feature}[[:blank:]]*=[[:blank:]].*$|\1 with${feature} = false|g" Package.swift done - name: Build and Test run: swift test From fe99eb4f3c21fbba73d6179b463c1559536235e2 Mon Sep 17 00:00:00 2001 From: Yehor Popovych Date: Mon, 14 Aug 2023 19:03:28 +0100 Subject: [PATCH 017/111] added package.swift print for debug --- .github/workflows/test.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f9881bda..acb64f1a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -37,6 +37,7 @@ jobs: sed -i '' "s|^\(.*\)with${feature}[[:blank:]]*=[[:blank:]].*$|\1 with${feature} = false|g" Package.swift echo "SWIFT_FEATURE_${feature}=false" >> "$GITHUB_ENV" done + cat Package.swift - name: Select Xcode run: sudo xcode-select -s /Applications/Xcode_${{ matrix.env.xcode }}.app - name: Build and Test macOS @@ -119,6 +120,7 @@ jobs: [ ! -z "${feature}" ] || continue sed -i "s|^\(.*\)with${feature}[[:blank:]]*=[[:blank:]].*$|\1 with${feature} = false|g" Package.swift done + cat Package.swift - name: Build and Test run: swift test - name: Run Benchmarks From 6d86e6b9919715982f49d7a0fb284ed561c2ee97 Mon Sep 17 00:00:00 2001 From: Yehor Popovych Date: Mon, 14 Aug 2023 19:55:33 +0100 Subject: [PATCH 018/111] better cocoapods features --- .github/workflows/deploy.yml | 1 + .github/workflows/test.yml | 13 ++++++++----- pods/Numberick-CoreKit.podspec | 14 ++++++++------ pods/Numberick-DoubleWidthKit.podspec | 12 +++++++----- pods/Numberick.podspec | 6 ++++-- 5 files changed, 28 insertions(+), 18 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 0f5caead..d5ddb8e4 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -27,6 +27,7 @@ jobs: [ ! -z "${feature}" ] || continue status=$(cat Package.swift | sed -n "s|^.*with${feature}[[:blank:]]*=[[:blank:]]\(.*\)$|\1|p") echo "SWIFT_FEATURE_${feature}=${status}" >> "$GITHUB_ENV" + echo "${feature} = ${status}" done - name: Publish 'Numberick-CoreKit' Pod run: pod trunk push --allow-warnings --synchronous pods/Numberick-CoreKit.podspec diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index acb64f1a..19dd940c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -28,16 +28,17 @@ jobs: for feature in "${{ matrix.env.enabled_features }}" do [ ! -z "${feature}" ] || continue - sed -i '' "s|^\(.*\)with${feature}[[:blank:]]*=[[:blank:]].*$|\1 with${feature} = true|g" Package.swift + sed -i '' "s|^\(.*\)with${feature}[[:blank:]]*=[[:blank:]].*$|\1with${feature} = true|g" Package.swift echo "SWIFT_FEATURE_${feature}=true" >> "$GITHUB_ENV" + echo "${feature} = true" done for feature in "${{ matrix.env.disabled_features }}" do [ ! -z "${feature}" ] || continue - sed -i '' "s|^\(.*\)with${feature}[[:blank:]]*=[[:blank:]].*$|\1 with${feature} = false|g" Package.swift + sed -i '' "s|^\(.*\)with${feature}[[:blank:]]*=[[:blank:]].*$|\1with${feature} = false|g" Package.swift echo "SWIFT_FEATURE_${feature}=false" >> "$GITHUB_ENV" + echo "${feature} = false" done - cat Package.swift - name: Select Xcode run: sudo xcode-select -s /Applications/Xcode_${{ matrix.env.xcode }}.app - name: Build and Test macOS @@ -113,12 +114,14 @@ jobs: for feature in "${{ matrix.env.enabled_features }}" do [ ! -z "${feature}" ] || continue - sed -i "s|^\(.*\)with${feature}[[:blank:]]*=[[:blank:]].*$|\1 with${feature} = true|g" Package.swift + sed -i "s|^\(.*\)with${feature}[[:blank:]]*=[[:blank:]].*$|\1with${feature} = true|g" Package.swift + echo "${feature} = true" done for feature in "${{ matrix.env.disabled_features }}" do [ ! -z "${feature}" ] || continue - sed -i "s|^\(.*\)with${feature}[[:blank:]]*=[[:blank:]].*$|\1 with${feature} = false|g" Package.swift + sed -i "s|^\(.*\)with${feature}[[:blank:]]*=[[:blank:]].*$|\1with${feature} = false|g" Package.swift + echo "${feature} = false" done cat Package.swift - name: Build and Test diff --git a/pods/Numberick-CoreKit.podspec b/pods/Numberick-CoreKit.podspec index d90f045f..f896334b 100644 --- a/pods/Numberick-CoreKit.podspec +++ b/pods/Numberick-CoreKit.podspec @@ -23,14 +23,16 @@ Pod::Spec.new do |s| s.source_files = 'Sources/NBKCoreKit/**/*.swift' - s.pod_target_xcconfig = { 'OTHER_SWIFT_FLAGS' => '' } - + swift_custom_flags = '' + if ENV['SWIFT_FEATURE_StaticBigInt'] == 'true' - base_platforms = { :ios => '16.4', :osx => '13.3', :tvos => '16.4' } - s.platforms = base_platforms.merge({ :watchos => '9.4' }) - s.swift_version = '5.8' - s.pod_target_xcconfig['OTHER_SWIFT_FLAGS'] += '-DSBI ' + base_platforms = { :ios => '16.4', :osx => '13.3', :tvos => '16.4' } + s.platforms = base_platforms.merge({ :watchos => '9.4' }) + s.swift_version = '5.8' + swift_custom_flags += 'SBI ' end + + s.pod_target_xcconfig = { 'SWIFT_ACTIVE_COMPILATION_CONDITIONS' => swift_custom_flags } s.test_spec 'Tests' do |ts| ts.platforms = base_platforms diff --git a/pods/Numberick-DoubleWidthKit.podspec b/pods/Numberick-DoubleWidthKit.podspec index 2f266c62..6d236ddf 100644 --- a/pods/Numberick-DoubleWidthKit.podspec +++ b/pods/Numberick-DoubleWidthKit.podspec @@ -24,15 +24,17 @@ Pod::Spec.new do |s| s.source_files = 'Sources/NBKDoubleWidthKit/**/*.swift' - s.pod_target_xcconfig = { 'OTHER_SWIFT_FLAGS' => '' } + swift_custom_flags = '' if ENV['SWIFT_FEATURE_StaticBigInt'] == 'true' - base_platforms = { :ios => '16.4', :osx => '13.3', :tvos => '16.4' } - s.platforms = base_platforms.merge({ :watchos => '9.4' }) - s.swift_version = '5.8' - s.pod_target_xcconfig['OTHER_SWIFT_FLAGS'] += '-DSBI ' + base_platforms = { :ios => '16.4', :osx => '13.3', :tvos => '16.4' } + s.platforms = base_platforms.merge({ :watchos => '9.4' }) + s.swift_version = '5.8' + swift_custom_flags += 'SBI ' end + s.pod_target_xcconfig = { 'SWIFT_ACTIVE_COMPILATION_CONDITIONS' => swift_custom_flags } + s.dependency 'Numberick-CoreKit', "#{s.version}" s.test_spec 'Tests' do |ts| diff --git a/pods/Numberick.podspec b/pods/Numberick.podspec index 6b6709b0..420e4afe 100644 --- a/pods/Numberick.podspec +++ b/pods/Numberick.podspec @@ -20,13 +20,15 @@ Pod::Spec.new do |s| s.source_files = 'Sources/Numberick/**/*.swift' - s.pod_target_xcconfig = { 'OTHER_SWIFT_FLAGS' => '' } + swift_custom_flags = '' if ENV['SWIFT_FEATURE_StaticBigInt'] == 'true' s.platforms = { :ios => '16.4', :osx => '13.3', :tvos => '16.4', :watchos => '9.4' } s.swift_version = '5.8' - s.pod_target_xcconfig['OTHER_SWIFT_FLAGS'] += '-DSBI ' + swift_custom_flags += 'SBI ' end + + s.pod_target_xcconfig = { 'SWIFT_ACTIVE_COMPILATION_CONDITIONS' => swift_custom_flags } s.dependency 'Numberick-CoreKit', "#{s.version}" s.dependency 'Numberick-DoubleWidthKit', "#{s.version}" From 7a92f198b343a205eab8d9dfbbc8e4c490b8ac57 Mon Sep 17 00:00:00 2001 From: Yehor Popovych Date: Mon, 14 Aug 2023 20:41:52 +0100 Subject: [PATCH 019/111] better CI scripts --- .github/workflows/deploy.yml | 13 +++----- .github/workflows/test.yml | 58 +++++++++++++----------------------- 2 files changed, 25 insertions(+), 46 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index d5ddb8e4..5743a515 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -2,8 +2,6 @@ name: Publish CocoaPods package on: release: types: [created] -env: - SWIFT_CUSTOM_FEATURES: 'StaticBigInt' jobs: publish: runs-on: macos-13 @@ -20,15 +18,12 @@ jobs: sed -i '' "s|[[:blank:]]*s\.version[[:blank:]].*|s.version = '${VERSION}'|g" pods/Numberick-CoreKit.podspec sed -i '' "s|[[:blank:]]*s\.version[[:blank:]].*|s.version = '${VERSION}'|g" pods/Numberick-DoubleWidthKit.podspec sed -i '' "s|[[:blank:]]*s\.version[[:blank:]].*|s.version = '${VERSION}'|g" pods/Numberick.podspec + echo "Updated version to: ${VERSION}" - name: Set enabled features in this branch for CocoaPods run: | - for feature in "${{ env.SWIFT_CUSTOM_FEATURES }}" - do - [ ! -z "${feature}" ] || continue - status=$(cat Package.swift | sed -n "s|^.*with${feature}[[:blank:]]*=[[:blank:]]\(.*\)$|\1|p") - echo "SWIFT_FEATURE_${feature}=${status}" >> "$GITHUB_ENV" - echo "${feature} = ${status}" - done + features=$(cat Package.swift | sed -n "s|^let[[:blank:]]*with\([a-zA-Z0-9\_]*\)[[:blank:]]*=[[:blank:]]*\(.*\)$|SWIFT_FEATURE_\1=\2|p") + echo "${features}" >> "$GITHUB_ENV" + echo "${features}" - name: Publish 'Numberick-CoreKit' Pod run: pod trunk push --allow-warnings --synchronous pods/Numberick-CoreKit.podspec env: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 19dd940c..cb63dc36 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -4,16 +4,13 @@ jobs: macos: strategy: matrix: - env: + tests: - xcode: '14.2' - enabled_features: '' - disabled_features: 'StaticBigInt' + features: '-StaticBigInt' - xcode: '14.3.1' - enabled_features: '' - disabled_features: 'StaticBigInt' + features: '-StaticBigInt' - xcode: '14.3.1' - enabled_features: 'StaticBigInt' - disabled_features: '' + features: '+StaticBigInt' runs-on: macos-13 steps: - name: Checkout @@ -25,22 +22,17 @@ jobs: echo "SOURCES_ZIP=${tempfile}" >> "$GITHUB_ENV" - name: Select Swift custom features run: | - for feature in "${{ matrix.env.enabled_features }}" + for feature in "${{ matrix.tests.features }}" do [ ! -z "${feature}" ] || continue - sed -i '' "s|^\(.*\)with${feature}[[:blank:]]*=[[:blank:]].*$|\1with${feature} = true|g" Package.swift - echo "SWIFT_FEATURE_${feature}=true" >> "$GITHUB_ENV" - echo "${feature} = true" - done - for feature in "${{ matrix.env.disabled_features }}" - do - [ ! -z "${feature}" ] || continue - sed -i '' "s|^\(.*\)with${feature}[[:blank:]]*=[[:blank:]].*$|\1with${feature} = false|g" Package.swift - echo "SWIFT_FEATURE_${feature}=false" >> "$GITHUB_ENV" - echo "${feature} = false" + status=$([[ "${feature}" = -* ]] && echo "false" || echo "true") + feature="${feature:1}" + sed -i '' "s|^let[[:blank:]]*with${feature}[[:blank:]]*=.*$|let with${feature} = ${status}|g" Package.swift + echo "SWIFT_FEATURE_${feature}=${status}" >> "$GITHUB_ENV" + echo "${feature} = ${status}" done - name: Select Xcode - run: sudo xcode-select -s /Applications/Xcode_${{ matrix.env.xcode }}.app + run: sudo xcode-select -s /Applications/Xcode_${{ matrix.tests.xcode }}.app - name: Build and Test macOS run: xcodebuild test -scheme 'Numberick' -destination "platform=macOS" - name: Benchmarks macOS @@ -92,38 +84,30 @@ jobs: linux: strategy: matrix: - env: + tests: - swift: '5.7' - enabled_features: '' - disabled_features: 'StaticBigInt' + features: '-StaticBigInt' - swift: '5.8' - enabled_features: '' - disabled_features: 'StaticBigInt' + features: '-StaticBigInt' - swift: '5.8' - enabled_features: 'StaticBigInt' - disabled_features: '' + features: '+StaticBigInt' runs-on: ubuntu-latest container: - image: swift:${{ matrix.env.swift }} + image: swift:${{ matrix.tests.swift }} options: --cap-add=SYS_PTRACE --security-opt seccomp=unconfined --security-opt apparmor=unconfined steps: - name: Checkout uses: actions/checkout@v3 - name: Select Swift custom features run: | - for feature in "${{ matrix.env.enabled_features }}" - do - [ ! -z "${feature}" ] || continue - sed -i "s|^\(.*\)with${feature}[[:blank:]]*=[[:blank:]].*$|\1with${feature} = true|g" Package.swift - echo "${feature} = true" - done - for feature in "${{ matrix.env.disabled_features }}" + for feature in "${{ matrix.tests.features }}" do [ ! -z "${feature}" ] || continue - sed -i "s|^\(.*\)with${feature}[[:blank:]]*=[[:blank:]].*$|\1with${feature} = false|g" Package.swift - echo "${feature} = false" + status=$([[ "${feature}" = -* ]] && echo "false" || echo "true") + feature="${feature:1}" + sed -i "s|^let[[:blank:]]*with${feature}[[:blank:]]*=.*$|let with${feature} = ${status}|g" Package.swift + echo "${feature} = ${status}" done - cat Package.swift - name: Build and Test run: swift test - name: Run Benchmarks From 5082fc1755200200284a228a234e6a7f76a74027 Mon Sep 17 00:00:00 2001 From: Yehor Popovych Date: Mon, 14 Aug 2023 21:13:37 +0100 Subject: [PATCH 020/111] renamed env variable. set shell to bash for CI --- .github/workflows/deploy.yml | 5 ++++- .github/workflows/test.yml | 12 +++++++++--- pods/Numberick-CoreKit.podspec | 2 +- pods/Numberick-DoubleWidthKit.podspec | 2 +- pods/Numberick.podspec | 2 +- 5 files changed, 16 insertions(+), 7 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 5743a515..7eb8595b 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -5,6 +5,9 @@ on: jobs: publish: runs-on: macos-13 + defaults: + run: + shell: bash steps: - name: Checkout uses: actions/checkout@v3 @@ -21,7 +24,7 @@ jobs: echo "Updated version to: ${VERSION}" - name: Set enabled features in this branch for CocoaPods run: | - features=$(cat Package.swift | sed -n "s|^let[[:blank:]]*with\([a-zA-Z0-9\_]*\)[[:blank:]]*=[[:blank:]]*\(.*\)$|SWIFT_FEATURE_\1=\2|p") + features=$(cat Package.swift | sed -n "s|^let[[:blank:]]*with\([a-zA-Z0-9\_]*\)[[:blank:]]*=[[:blank:]]*\(.*\)$|NBK_FEATURE_\1=\2|p") echo "${features}" >> "$GITHUB_ENV" echo "${features}" - name: Publish 'Numberick-CoreKit' Pod diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index cb63dc36..e2c24916 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -12,6 +12,9 @@ jobs: - xcode: '14.3.1' features: '+StaticBigInt' runs-on: macos-13 + defaults: + run: + shell: bash steps: - name: Checkout uses: actions/checkout@v3 @@ -24,11 +27,11 @@ jobs: run: | for feature in "${{ matrix.tests.features }}" do - [ ! -z "${feature}" ] || continue + [ "${feature}" ] || continue status=$([[ "${feature}" = -* ]] && echo "false" || echo "true") feature="${feature:1}" sed -i '' "s|^let[[:blank:]]*with${feature}[[:blank:]]*=.*$|let with${feature} = ${status}|g" Package.swift - echo "SWIFT_FEATURE_${feature}=${status}" >> "$GITHUB_ENV" + echo "NBK_FEATURE_${feature}=${status}" >> "$GITHUB_ENV" echo "${feature} = ${status}" done - name: Select Xcode @@ -92,6 +95,9 @@ jobs: - swift: '5.8' features: '+StaticBigInt' runs-on: ubuntu-latest + defaults: + run: + shell: bash container: image: swift:${{ matrix.tests.swift }} options: --cap-add=SYS_PTRACE --security-opt seccomp=unconfined --security-opt apparmor=unconfined @@ -102,7 +108,7 @@ jobs: run: | for feature in "${{ matrix.tests.features }}" do - [ ! -z "${feature}" ] || continue + [ "${feature}" ] || continue status=$([[ "${feature}" = -* ]] && echo "false" || echo "true") feature="${feature:1}" sed -i "s|^let[[:blank:]]*with${feature}[[:blank:]]*=.*$|let with${feature} = ${status}|g" Package.swift diff --git a/pods/Numberick-CoreKit.podspec b/pods/Numberick-CoreKit.podspec index f896334b..aedf7cce 100644 --- a/pods/Numberick-CoreKit.podspec +++ b/pods/Numberick-CoreKit.podspec @@ -25,7 +25,7 @@ Pod::Spec.new do |s| swift_custom_flags = '' - if ENV['SWIFT_FEATURE_StaticBigInt'] == 'true' + if ENV['NBK_FEATURE_StaticBigInt'] == 'true' base_platforms = { :ios => '16.4', :osx => '13.3', :tvos => '16.4' } s.platforms = base_platforms.merge({ :watchos => '9.4' }) s.swift_version = '5.8' diff --git a/pods/Numberick-DoubleWidthKit.podspec b/pods/Numberick-DoubleWidthKit.podspec index 6d236ddf..c5db10d6 100644 --- a/pods/Numberick-DoubleWidthKit.podspec +++ b/pods/Numberick-DoubleWidthKit.podspec @@ -26,7 +26,7 @@ Pod::Spec.new do |s| swift_custom_flags = '' - if ENV['SWIFT_FEATURE_StaticBigInt'] == 'true' + if ENV['NBK_FEATURE_StaticBigInt'] == 'true' base_platforms = { :ios => '16.4', :osx => '13.3', :tvos => '16.4' } s.platforms = base_platforms.merge({ :watchos => '9.4' }) s.swift_version = '5.8' diff --git a/pods/Numberick.podspec b/pods/Numberick.podspec index 420e4afe..25ef9c85 100644 --- a/pods/Numberick.podspec +++ b/pods/Numberick.podspec @@ -22,7 +22,7 @@ Pod::Spec.new do |s| swift_custom_flags = '' - if ENV['SWIFT_FEATURE_StaticBigInt'] == 'true' + if ENV['NBK_FEATURE_StaticBigInt'] == 'true' s.platforms = { :ios => '16.4', :osx => '13.3', :tvos => '16.4', :watchos => '9.4' } s.swift_version = '5.8' swift_custom_flags += 'SBI ' From 191693b2b5beb9d093962a355ace7efd43ad35b3 Mon Sep 17 00:00:00 2001 From: Yehor Popovych Date: Mon, 14 Aug 2023 21:43:30 +0100 Subject: [PATCH 021/111] added xcconfig for test targets --- pods/Numberick-CoreKit.podspec | 2 ++ pods/Numberick-DoubleWidthKit.podspec | 2 ++ 2 files changed, 4 insertions(+) diff --git a/pods/Numberick-CoreKit.podspec b/pods/Numberick-CoreKit.podspec index aedf7cce..79ceac1a 100644 --- a/pods/Numberick-CoreKit.podspec +++ b/pods/Numberick-CoreKit.podspec @@ -37,10 +37,12 @@ Pod::Spec.new do |s| s.test_spec 'Tests' do |ts| ts.platforms = base_platforms ts.source_files = 'Tests/NBKCoreKitTests/**/*.swift' + ts.pod_target_xcconfig = { 'SWIFT_ACTIVE_COMPILATION_CONDITIONS' => swift_custom_flags } end s.test_spec 'Benchmarks' do |ts| ts.platforms = base_platforms ts.source_files = 'Tests/NBKCoreKitBenchmarks/**/*.swift' + ts.pod_target_xcconfig = { 'SWIFT_ACTIVE_COMPILATION_CONDITIONS' => swift_custom_flags } end end \ No newline at end of file diff --git a/pods/Numberick-DoubleWidthKit.podspec b/pods/Numberick-DoubleWidthKit.podspec index c5db10d6..32f6f020 100644 --- a/pods/Numberick-DoubleWidthKit.podspec +++ b/pods/Numberick-DoubleWidthKit.podspec @@ -40,10 +40,12 @@ Pod::Spec.new do |s| s.test_spec 'Tests' do |ts| ts.platforms = base_platforms ts.source_files = 'Tests/NBKDoubleWidthKitTests/**/*.swift' + ts.pod_target_xcconfig = { 'SWIFT_ACTIVE_COMPILATION_CONDITIONS' => swift_custom_flags } end s.test_spec 'Benchmarks' do |ts| ts.platforms = base_platforms ts.source_files = 'Tests/NBKDoubleWidthKitBenchmarks/**/*.swift' + ts.pod_target_xcconfig = { 'SWIFT_ACTIVE_COMPILATION_CONDITIONS' => swift_custom_flags } end end \ No newline at end of file From f7d7d484b68dfd1e65f88a3847985f838e2e8cc0 Mon Sep 17 00:00:00 2001 From: Yehor Popovych Date: Tue, 15 Aug 2023 01:52:10 +0100 Subject: [PATCH 022/111] run 5.7 tests on macos-12 --- .github/workflows/test.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e2c24916..b705716d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -6,12 +6,15 @@ jobs: matrix: tests: - xcode: '14.2' + machine: macos-12 features: '-StaticBigInt' - - xcode: '14.3.1' + - xcode: '14.3' + machine: macos-13 features: '-StaticBigInt' - xcode: '14.3.1' + machine: macos-13 features: '+StaticBigInt' - runs-on: macos-13 + runs-on: ${{ matrix.tests.machine }} defaults: run: shell: bash From 721b0f64ea120f498fc892f2b859b108864820a0 Mon Sep 17 00:00:00 2001 From: Yehor Popovych Date: Tue, 15 Aug 2023 09:07:13 +0100 Subject: [PATCH 023/111] removed benchmarks from CocoaPods --- pods/Numberick-CoreKit.podspec | 6 ------ pods/Numberick-DoubleWidthKit.podspec | 6 ------ 2 files changed, 12 deletions(-) diff --git a/pods/Numberick-CoreKit.podspec b/pods/Numberick-CoreKit.podspec index 79ceac1a..c1e54d62 100644 --- a/pods/Numberick-CoreKit.podspec +++ b/pods/Numberick-CoreKit.podspec @@ -39,10 +39,4 @@ Pod::Spec.new do |s| ts.source_files = 'Tests/NBKCoreKitTests/**/*.swift' ts.pod_target_xcconfig = { 'SWIFT_ACTIVE_COMPILATION_CONDITIONS' => swift_custom_flags } end - - s.test_spec 'Benchmarks' do |ts| - ts.platforms = base_platforms - ts.source_files = 'Tests/NBKCoreKitBenchmarks/**/*.swift' - ts.pod_target_xcconfig = { 'SWIFT_ACTIVE_COMPILATION_CONDITIONS' => swift_custom_flags } - end end \ No newline at end of file diff --git a/pods/Numberick-DoubleWidthKit.podspec b/pods/Numberick-DoubleWidthKit.podspec index 32f6f020..7c10ced2 100644 --- a/pods/Numberick-DoubleWidthKit.podspec +++ b/pods/Numberick-DoubleWidthKit.podspec @@ -42,10 +42,4 @@ Pod::Spec.new do |s| ts.source_files = 'Tests/NBKDoubleWidthKitTests/**/*.swift' ts.pod_target_xcconfig = { 'SWIFT_ACTIVE_COMPILATION_CONDITIONS' => swift_custom_flags } end - - s.test_spec 'Benchmarks' do |ts| - ts.platforms = base_platforms - ts.source_files = 'Tests/NBKDoubleWidthKitBenchmarks/**/*.swift' - ts.pod_target_xcconfig = { 'SWIFT_ACTIVE_COMPILATION_CONDITIONS' => swift_custom_flags } - end end \ No newline at end of file From 106202447f9d6bd5663c7c900b5051b73d17dfaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Tue, 15 Aug 2023 14:30:33 +0200 Subject: [PATCH 024/111] Package: Utilities. --- .utilities/update-gh-pages-docs-no-push.sh | 59 ++++++++++++++++++++++ README.md | 2 +- 2 files changed, 60 insertions(+), 1 deletion(-) create mode 100755 .utilities/update-gh-pages-docs-no-push.sh diff --git a/.utilities/update-gh-pages-docs-no-push.sh b/.utilities/update-gh-pages-docs-no-push.sh new file mode 100755 index 00000000..35b81d6d --- /dev/null +++ b/.utilities/update-gh-pages-docs-no-push.sh @@ -0,0 +1,59 @@ +#!/bin/bash +#=-----------------------------------------------------------------------------= +# This source file is part of the Numberick open source project. +# +# Copyright (c) 2023 Oscar Byström Ericsson +# Licensed under Apache License, Version 2.0 +# +# See http://www.apache.org/licenses/LICENSE-2.0 for license information. +#=-----------------------------------------------------------------------------= +# This script requires an orphaned gh-pages branch and the following structure: +# +# PROJECT/ +# │ +# ├─── .../ +# │ │ +# │ └─── SCRIPT.sh +# │ +# └─── .../ +# │ +# └─── PROJECT.xcodescheme +#=-----------------------------------------------------------------------------= + +set -eu + +# Variables + +PROJECT_NAME="Numberick" +XCODE_SCHEME_NAME=$PROJECT_NAME + +PROJECT_PATH=$(dirname $(dirname $(realpath $0))) +CURRENT_COMMIT_HASH=$(git rev-parse --short HEAD) + +# Variables x Environment + +export DOCC_JSON_PRETTYPRINT="YES" # nondeterministic :( + +# Actions + +cd $PROJECT_PATH + +xcodebuild docbuild \ +-scheme $XCODE_SCHEME_NAME \ +-derivedDataPath "docc" \ +-destination 'generic/platform=iOS' + +DOCC_ARCHIVE_PATH=$(find "docc" -name "$XCODE_SCHEME_NAME.doccarchive" | head -n 1) + +git worktree add --checkout "gh-pages" + +$(xcrun --find docc) process-archive transform-for-static-hosting $DOCC_ARCHIVE_PATH \ +--output-path "gh-pages/docs" \ +--hosting-base-path $PROJECT_NAME + +rm -rf docc +cd gh-pages +git add docs +git commit -m "GitHub Pages. DocC. $CURRENT_COMMIT_HASH." +cd .. +git worktree remove gh-pages diff --git a/README.md b/README.md index 0ae84079..7d38eb5e 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,8 @@ | Package | Swift | iOS | iPadOS | Mac Catalyst | macOS | tvOS | watchOS | |:-------:|:-----:|:----:|:------:|:------------:|:-----:|:----:|:-------:| -| 0.8.0 | 5.8 | 16.4 | 16.4 | 16.4 | 13.3 | 16.4 | 9.4 | | 0.9.0 | 5.7 | 16.4 | 16.4 | 16.4 | 13.3 | 16.4 | 9.4 | +| 0.8.0 | 5.8 | 16.4 | 16.4 | 16.4 | 13.3 | 16.4 | 9.4 | ## NBKCoreKit ([Sources][COR/S], [Tests][COR/T], [Benchmarks][COR/B]) From 235144e04037c098d5ae44d4e1dc20416021f939 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Wed, 16 Aug 2023 09:39:57 +0200 Subject: [PATCH 025/111] Cleanup. --- .utilities/update-gh-pages-docs-no-push.sh | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/.utilities/update-gh-pages-docs-no-push.sh b/.utilities/update-gh-pages-docs-no-push.sh index 35b81d6d..3890d4a9 100755 --- a/.utilities/update-gh-pages-docs-no-push.sh +++ b/.utilities/update-gh-pages-docs-no-push.sh @@ -11,13 +11,12 @@ # # PROJECT/ # │ -# ├─── .../ +# ├─── DIRECTORY/ # │ │ # │ └─── SCRIPT.sh # │ -# └─── .../ -# │ -# └─── PROJECT.xcodescheme +# └─── .swiftpm/xcode/xcshareddata/PROJECT.xcscheme +# #=-----------------------------------------------------------------------------= set -eu @@ -30,8 +29,6 @@ XCODE_SCHEME_NAME=$PROJECT_NAME PROJECT_PATH=$(dirname $(dirname $(realpath $0))) CURRENT_COMMIT_HASH=$(git rev-parse --short HEAD) -# Variables x Environment - export DOCC_JSON_PRETTYPRINT="YES" # nondeterministic :( # Actions From 1037a2625e1dcc635372a07453de458aa02faad6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Thu, 17 Aug 2023 09:19:38 +0200 Subject: [PATCH 026/111] Version 0.9.0. --- README.md | 1 - Sources/NBKCoreKit/Private/NBK+Text+RadixUIntRoot.swift | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 7d38eb5e..a61efa45 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,6 @@ | Package | Swift | iOS | iPadOS | Mac Catalyst | macOS | tvOS | watchOS | |:-------:|:-----:|:----:|:------:|:------------:|:-----:|:----:|:-------:| | 0.9.0 | 5.7 | 16.4 | 16.4 | 16.4 | 13.3 | 16.4 | 9.4 | -| 0.8.0 | 5.8 | 16.4 | 16.4 | 16.4 | 13.3 | 16.4 | 9.4 | ## NBKCoreKit ([Sources][COR/S], [Tests][COR/T], [Benchmarks][COR/B]) diff --git a/Sources/NBKCoreKit/Private/NBK+Text+RadixUIntRoot.swift b/Sources/NBKCoreKit/Private/NBK+Text+RadixUIntRoot.swift index cf122f10..226be75b 100644 --- a/Sources/NBKCoreKit/Private/NBK+Text+RadixUIntRoot.swift +++ b/Sources/NBKCoreKit/Private/NBK+Text+RadixUIntRoot.swift @@ -76,7 +76,7 @@ extension NBK { // MARK: * Perfect //*========================================================================* - /// A ``RadixUIntRoot`` with a power that is zero. + /// A `RadixUIntRoot` with a power that is zero. @frozen public struct PerfectRadixUIntRoot: _NBKRadixUIntRoot { //=--------------------------------------------------------------------= @@ -127,7 +127,7 @@ extension NBK { // MARK: * NBK x Imperfect //*========================================================================* - /// A ``RadixUIntRoot`` with a power that is non-zero. + /// A `RadixUIntRoot` with a power that is non-zero. @frozen public struct ImperfectRadixUIntRoot: _NBKRadixUIntRoot { //=--------------------------------------------------------------------= @@ -176,7 +176,7 @@ extension NBK { // MARK: * Any //*========================================================================* - /// A ``RadixUIntRoot`` with a power that may be zero. + /// A `RadixUIntRoot` with a power that may be zero. @frozen public struct AnyRadixUIntRoot: _NBKRadixUIntRoot { @usableFromInline typealias Solution = (exponent: UInt, power: UInt) From 537a266c30a1ebf3bbdfc8ec6d4cb9327dce1451 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Thu, 17 Aug 2023 11:53:12 +0200 Subject: [PATCH 027/111] [NBKCoreKit] `removeRadixPrefix(utf8:)` (#62) --- .../Private/NBK+Text+Components.swift | 37 ++++++++++++++++++- .../Private/NBK+Text+Components.swift | 31 ++++++++++++++-- 2 files changed, 62 insertions(+), 6 deletions(-) diff --git a/Sources/NBKCoreKit/Private/NBK+Text+Components.swift b/Sources/NBKCoreKit/Private/NBK+Text+Components.swift index f81c4c3e..6b5e0d8e 100644 --- a/Sources/NBKCoreKit/Private/NBK+Text+Components.swift +++ b/Sources/NBKCoreKit/Private/NBK+Text+Components.swift @@ -21,7 +21,7 @@ extension NBK { /// /// ``` /// ┌─────── → ──────┬────────┐ - /// │ self │ sign │  self │ + /// │ body │ sign │ body │ /// ├─────── → ──────┼────────┤ /// │ "+123" │ plus │ "123" │ /// │ "-123" │ minus │ "123" │ @@ -36,11 +36,44 @@ extension NBK { default: return nil } } + #warning("tests") + /// Removes and returns an `UTF-8` encoded `radix` prefix, if it exists. + /// + /// ``` + /// ┌──────── → ──────┬─────────┐ + /// │ body │ radix │  body │ + /// ├──────── → ──────┼─────────┤ + /// │ "0b123" │ 002 │ "123" │ + /// │ "0o123" │ 008 │ "123" │ + /// │ "0x123" │ 016 │ "123" │ + /// ├──────── → ──────┼─────────┤ + /// │ "1x123" │ nil │ "1x123" │ + /// │ "0X123" │ nil │ "0X123" │ + /// └──────── → ──────┴─────────┘ + /// ``` + /// + @inlinable public static func removeRadixPrefix(utf8: inout T) -> Int? where T: Collection, T == T.SubSequence { + var radix: Int? + + var index = utf8.startIndex + if index < utf8.endIndex, utf8[index] == UInt8(ascii: "0") { + utf8.formIndex(after: &index) + + switch utf8[index] { + case UInt8(ascii: "x"): radix = 0x10; utf8 = utf8[utf8.index(after: index)...] + case UInt8(ascii: "o"): radix = 0o10; utf8 = utf8[utf8.index(after: index)...] + case UInt8(ascii: "b"): radix = 0b10; utf8 = utf8[utf8.index(after: index)...] + default: break } + } + + return radix as Int? + } + /// Returns an `UTF-8` encoded integer's `sign` and `body`. /// /// ``` /// ┌─────── → ──────┬────────┐ - /// │ utf8 │ sign │  body │ + /// │ body │ sign │ body │ /// ├─────── → ──────┼────────┤ /// │ "+123" │ plus │ "123" │ /// │ "-123" │ minus │ "123" │ diff --git a/Tests/NBKCoreKitTests/Private/NBK+Text+Components.swift b/Tests/NBKCoreKitTests/Private/NBK+Text+Components.swift index 6682fe93..428f649c 100644 --- a/Tests/NBKCoreKitTests/Private/NBK+Text+Components.swift +++ b/Tests/NBKCoreKitTests/Private/NBK+Text+Components.swift @@ -32,6 +32,20 @@ final class NBKTestsOnTextByComponents: XCTestCase { NBKAssertRemoveSignPrefix("~123", nil, "~123") } + func testRemoveRadixPrefix() { + NBKAssertRemoveRadixPrefix( "", nil, "") + NBKAssertRemoveRadixPrefix( "0b", 002, "") + NBKAssertRemoveRadixPrefix( "0o", 008, "") + NBKAssertRemoveRadixPrefix( "0x", 016, "") + NBKAssertRemoveRadixPrefix( "1x", nil, "1x") + NBKAssertRemoveRadixPrefix( "0X", nil, "0X") + NBKAssertRemoveRadixPrefix("0b123", 002, "123") + NBKAssertRemoveRadixPrefix("0o123", 008, "123") + NBKAssertRemoveRadixPrefix("0x123", 016, "123") + NBKAssertRemoveRadixPrefix("1x123", nil, "1x123") + NBKAssertRemoveRadixPrefix("0X123", nil, "0X123") + } + func testMakeIntegerComponents() { NBKAssertMakeIntegerComponents( "", .plus, "") NBKAssertMakeIntegerComponents( "+", .plus, "") @@ -52,16 +66,25 @@ _ text: String, _ sign: FloatingPointSign?, _ body: String, file: StaticString = #file, line: UInt = #line) { var componentsBody = text.utf8[...] let componentsSign = NBK.removeSignPrefix(utf8: &componentsBody) - XCTAssertEqual(componentsSign, sign) - XCTAssertEqual(Array(componentsBody), Array(body.utf8)) + XCTAssertEqual(componentsSign, sign, file: file, line: line) + XCTAssertEqual(Array(componentsBody), Array(body.utf8), file: file, line: line) +} + +private func NBKAssertRemoveRadixPrefix( +_ text: String, _ radix: Int?, _ body: String, +file: StaticString = #file, line: UInt = #line) { + var componentsBody = text.utf8[...] + let componentsSign = NBK.removeRadixPrefix(utf8: &componentsBody) + XCTAssertEqual(componentsSign, radix, file: file, line: line) + XCTAssertEqual(Array(componentsBody), Array(body.utf8), file: file, line: line) } private func NBKAssertMakeIntegerComponents( _ text: String, _ sign: FloatingPointSign?, _ body: String, file: StaticString = #file, line: UInt = #line) { let components = NBK.makeIntegerComponents(utf8: text.utf8) - XCTAssertEqual(components.sign, sign) - XCTAssertEqual(Array(components.body), Array(body.utf8)) + XCTAssertEqual(components.sign, sign, file: file, line: line) + XCTAssertEqual(Array(components.body), Array(body.utf8), file: file, line: line) } #endif From e2116d5808c0791c838218450ec66c9a8790a7a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Thu, 17 Aug 2023 12:18:03 +0200 Subject: [PATCH 028/111] [NBKCoreKit] `makeIntegerComponentsWithRadix(utf8:)` (#62) --- .../Private/NBK+Text+Components.swift | 28 ++++++++++++++++- .../Private/NBK+Text+Components.swift | 30 +++++++++++++++++++ 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/Sources/NBKCoreKit/Private/NBK+Text+Components.swift b/Sources/NBKCoreKit/Private/NBK+Text+Components.swift index 6b5e0d8e..836ba10c 100644 --- a/Sources/NBKCoreKit/Private/NBK+Text+Components.swift +++ b/Sources/NBKCoreKit/Private/NBK+Text+Components.swift @@ -36,7 +36,6 @@ extension NBK { default: return nil } } - #warning("tests") /// Removes and returns an `UTF-8` encoded `radix` prefix, if it exists. /// /// ``` @@ -77,6 +76,7 @@ extension NBK { /// ├─────── → ──────┼────────┤ /// │ "+123" │ plus │ "123" │ /// │ "-123" │ minus │ "123" │ + /// ├─────── → ──────┼────────┤ /// │ "~123" │ plus │ "~123" │ /// └─────── → ──────┴────────┘ /// ``` @@ -88,4 +88,30 @@ extension NBK { let sign = NBK.removeSignPrefix(utf8: &body) ?? Sign.plus return (sign: sign, body: body) } + + /// Returns an `UTF-8` encoded integer's `sign`, `radix`, and `body`. + /// + /// ``` + /// ┌───────── → ──────┬───────┬──────────┐ + /// │ body │ sign │ radix │ body │ + /// ├───────── → ──────┼───────┼──────────┤ + /// │ "+0b123" │ plus │ 002 │ "123" │ + /// │ "-0x123" │ minus │ 016 │ "123" │ + /// ├───────── → ──────┼───────┼──────────┤ + /// │ "123" │ plus │ 010 │ "123" │ + /// │ "~1x123" │ plus │ 010 │ "~1x123" │ + /// │ "~0X123" │ plus │ 010 │ "~0X123" │ + /// └───────── → ──────┴───────┴──────────┘ + /// ``` + /// + /// - Note: Integers without sign are interpreted as positive. + /// + /// - Note: Integers without radix are interpreted as base 10. + /// + @inlinable public static func makeIntegerComponentsWithRadix(utf8: T) -> (sign: Sign, radix: Int, body: T.SubSequence) where T: Collection { + var body = utf8[...] as T.SubSequence + let sign = NBK.removeSignPrefix(utf8: &body) ?? Sign.plus + let radix = NBK.removeRadixPrefix(utf8: &body) ?? 10 as Int + return (sign: sign, radix: radix, body: body) + } } diff --git a/Tests/NBKCoreKitTests/Private/NBK+Text+Components.swift b/Tests/NBKCoreKitTests/Private/NBK+Text+Components.swift index 428f649c..574d2a93 100644 --- a/Tests/NBKCoreKitTests/Private/NBK+Text+Components.swift +++ b/Tests/NBKCoreKitTests/Private/NBK+Text+Components.swift @@ -55,6 +55,27 @@ final class NBKTestsOnTextByComponents: XCTestCase { NBKAssertMakeIntegerComponents("-123", .minus, "123") NBKAssertMakeIntegerComponents("~123", .plus, "~123") } + + func testMakeIntegerComponentsWithRadix() { + NBKAssertMakeIntegerComponentsWithRadix( "", .plus, 10, "") + NBKAssertMakeIntegerComponentsWithRadix( "+", .plus, 10, "") + NBKAssertMakeIntegerComponentsWithRadix( "-", .minus, 10, "") + NBKAssertMakeIntegerComponentsWithRadix( "~", .plus, 10, "~") + NBKAssertMakeIntegerComponentsWithRadix( "0b", .plus, 02, "") + NBKAssertMakeIntegerComponentsWithRadix( "0o", .plus, 08, "") + NBKAssertMakeIntegerComponentsWithRadix( "0x", .plus, 16, "") + NBKAssertMakeIntegerComponentsWithRadix( "1x", .plus, 10, "1x") + NBKAssertMakeIntegerComponentsWithRadix( "0X", .plus, 10, "0X") + NBKAssertMakeIntegerComponentsWithRadix( "123", .plus, 10, "123") + NBKAssertMakeIntegerComponentsWithRadix("+0b123", .plus, 02, "123") + NBKAssertMakeIntegerComponentsWithRadix("+0o123", .plus, 08, "123") + NBKAssertMakeIntegerComponentsWithRadix("+0x123", .plus, 16, "123") + NBKAssertMakeIntegerComponentsWithRadix("-0b123", .minus, 02, "123") + NBKAssertMakeIntegerComponentsWithRadix("-0o123", .minus, 08, "123") + NBKAssertMakeIntegerComponentsWithRadix("-0x123", .minus, 16, "123") + NBKAssertMakeIntegerComponentsWithRadix("~1x123", .plus, 10, "~1x123") + NBKAssertMakeIntegerComponentsWithRadix("~0X123", .plus, 10, "~0X123") + } } //*============================================================================* @@ -87,4 +108,13 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual(Array(components.body), Array(body.utf8), file: file, line: line) } +private func NBKAssertMakeIntegerComponentsWithRadix( +_ text: String, _ sign: FloatingPointSign?, _ radix: Int?, _ body: String, +file: StaticString = #file, line: UInt = #line) { + let components = NBK.makeIntegerComponentsWithRadix(utf8: text.utf8) + XCTAssertEqual(components.sign, sign, file: file, line: line) + XCTAssertEqual(components.radix, radix, file: file, line: line) + XCTAssertEqual(Array(components.body), Array(body.utf8), file: file, line: line) +} + #endif From ebe4f5580f522b234ad87048b394033fdbb24cf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Thu, 17 Aug 2023 12:23:33 +0200 Subject: [PATCH 029/111] [NBKDoubleWidthKit] ExpressibleByStringLiteral (#62) --- .../NBKDoubleWidth+Literals.swift | 24 ++++++++- .../NBKDoubleWidth+Literals.swift | 32 +++++++++++ .../NBKDoubleWidth+Text.swift | 53 +++++++++++-------- 3 files changed, 85 insertions(+), 24 deletions(-) diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift index 56a71748..ab465820 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift @@ -7,6 +7,8 @@ // See http://www.apache.org/licenses/LICENSE-2.0 for license information. //=----------------------------------------------------------------------------= +import NBKCoreKit + //*============================================================================* // MARK: * NBK x Double Width x Literals //*============================================================================* @@ -46,7 +48,7 @@ extension NBKDoubleWidth { // MARK: + Version < iOS 16.4, macOS 13.3 //=----------------------------------------------------------------------------= -extension NBKDoubleWidth { +extension NBKDoubleWidth: ExpressibleByStringLiteral { //=------------------------------------------------------------------------= // MARK: Initializers @@ -55,6 +57,26 @@ extension NBKDoubleWidth { @inlinable public init(integerLiteral source: Int64) { self.init(source) } + + @inlinable public init(stringLiteral source: StringLiteralType) { + if let value = Self(exactlyStringLiteral: source) { self = value } else { + preconditionFailure("\(Self.description) cannot represent \(source)") + } + } + + @inlinable init?(exactlyStringLiteral source: StringLiteralType) { + var source = source + + let value: Optional = source.withUTF8 { utf8 in + let components = NBK.makeIntegerComponentsWithRadix(utf8: utf8) + let radix = NBK.AnyRadixUIntRoot(components.radix) + let digits = NBK.UnsafeUTF8(rebasing: components.body) + guard let magnitude = Magnitude(digits: digits, radix: radix) else { return nil } + return Self(sign: components.sign, magnitude: magnitude) + } + + if let value { self = value } else { return nil } + } } #endif diff --git a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Literals.swift b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Literals.swift index 3066bd8a..112b3ef0 100644 --- a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Literals.swift +++ b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Literals.swift @@ -69,6 +69,22 @@ final class NBKDoubleWidthTestsOnLiteralsAsInt256: XCTestCase { XCTAssertEqual(T(integerLiteral: -0x0000000000000001 as L), ~T(x64: X(UInt64(L( )), 0, 0, 0))) XCTAssertEqual(T(integerLiteral: -0x8000000000000000 as L), ~T(x64: X(UInt64(L.max), 0, 0, 0))) } + + func testFromStringLiteral() { + XCTAssertEqual(T(x64: X( 0, 0, 0, 0)), "0x0000000000000000000000000000000000000000000000000000000000000000") + XCTAssertEqual(T(x64: X(~0, 0, 0, 0)), "0x000000000000000000000000000000000000000000000000ffffffffffffffff") + XCTAssertEqual(T(x64: X(~0, ~0, 0, 0)), "0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff") + XCTAssertEqual(T(x64: X(~0, ~0, ~0, 0)), "0x0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff") + XCTAssertEqual(T(x64: X(~0, ~0, ~0, ~0)), "-0x0000000000000000000000000000000000000000000000000000000000000001") + XCTAssertEqual(T(x64: X( 0, ~0, ~0, ~0)), "-0x0000000000000000000000000000000000000000000000010000000000000000") + XCTAssertEqual(T(x64: X( 0, 0, ~0, ~0)), "-0x0000000000000000000000000000000100000000000000000000000000000000") + XCTAssertEqual(T(x64: X( 0, 0, 0, ~0)), "-0x0000000000000001000000000000000000000000000000000000000000000000") + + XCTAssertEqual(T(exactlyStringLiteral: "0x8000000000000000000000000000000000000000000000000000000000000000"), nil) + XCTAssertEqual(T(exactlyStringLiteral: "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), T.max) + XCTAssertEqual(T(exactlyStringLiteral: "-0x8000000000000000000000000000000000000000000000000000000000000000"), T.min) + XCTAssertEqual(T(exactlyStringLiteral: "-0x8000000000000000000000000000000000000000000000000000000000000001"), nil) + } } #endif @@ -125,6 +141,22 @@ final class NBKDoubleWidthTestsOnLiteralsAsUInt256: XCTestCase { XCTAssertEqual(T(exactly: -0x0000000000000001 as L), nil) XCTAssertEqual(T(exactly: -0x8000000000000000 as L), nil) } + + func testFromStringLiteral() { + XCTAssertEqual(T(x64: X( 0, 0, 0, 0)), "0x0000000000000000000000000000000000000000000000000000000000000000") + XCTAssertEqual(T(x64: X(~0, 0, 0, 0)), "0x000000000000000000000000000000000000000000000000ffffffffffffffff") + XCTAssertEqual(T(x64: X(~0, ~0, 0, 0)), "0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff") + XCTAssertEqual(T(x64: X(~0, ~0, ~0, 0)), "0x0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff") + XCTAssertEqual(T(x64: X(~0, ~0, ~0, ~0)), "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") + XCTAssertEqual(T(x64: X( 0, ~0, ~0, ~0)), "0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000") + XCTAssertEqual(T(x64: X( 0, 0, ~0, ~0)), "0xffffffffffffffffffffffffffffffff00000000000000000000000000000000") + XCTAssertEqual(T(x64: X( 0, 0, 0, ~0)), "0xffffffffffffffff000000000000000000000000000000000000000000000000") + + XCTAssertEqual(T(exactlyStringLiteral: "0x010000000000000000000000000000000000000000000000000000000000000000"), nil) + XCTAssertEqual(T(exactlyStringLiteral: "0x00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), T.max) + XCTAssertEqual(T(exactlyStringLiteral: "0x000000000000000000000000000000000000000000000000000000000000000000"), T.min) + XCTAssertEqual(T(exactlyStringLiteral: "-0x000000000000000000000000000000000000000000000000000000000000000001"), nil) + } } #endif diff --git a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Text.swift b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Text.swift index 164409fa..1569918e 100644 --- a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Text.swift +++ b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Text.swift @@ -29,19 +29,18 @@ final class NBKDoubleWidthTestsOnTextAsInt256: XCTestCase { // MARK: Tests //=------------------------------------------------------------------------= - func testInitDescription() { - XCTAssertEqual(T( "10"), 10) - XCTAssertEqual(T( "+10"), 10) - XCTAssertEqual(T( "-10"), -10) - XCTAssertEqual(T( " 10"), nil) - - XCTAssertEqual(T( "0x10"), nil) - XCTAssertEqual(T("+0x10"), nil) - XCTAssertEqual(T("-0x10"), nil) - XCTAssertEqual(T(" 0x10"), nil) - } - - func testInstanceDescriptionUsesRadix10() { + func testDescriptionInit() { + NBKAssertDescriptionInit(T?( 10), "10") + NBKAssertDescriptionInit(T?( 10), "+10") + NBKAssertDescriptionInit(T?(-10), "-10") + NBKAssertDescriptionInit(T?(nil), " 10") + NBKAssertDescriptionInit(T?(nil), "0x10") + NBKAssertDescriptionInit(T?(nil), "+0x10") + NBKAssertDescriptionInit(T?(nil), "-0x10") + NBKAssertDescriptionInit(T?(nil), " 0x10") + } + + func testDescriptionUsesRadix10() { XCTAssertEqual( "10", T( 10).description) XCTAssertEqual("-10", T(-10).description) @@ -268,16 +267,15 @@ final class NBKDoubleWidthTestsOnTextAsUInt256: XCTestCase { // MARK: Tests //=------------------------------------------------------------------------= - func testInitDescription() { - XCTAssertEqual(T( "10"), 10) - XCTAssertEqual(T( "+10"), 10) - XCTAssertEqual(T( "-10"), nil) - XCTAssertEqual(T( " 10"), nil) - - XCTAssertEqual(T( "0x10"), nil) - XCTAssertEqual(T("+0x10"), nil) - XCTAssertEqual(T("-0x10"), nil) - XCTAssertEqual(T(" 0x10"), nil) + func testDescriptionInit() { + NBKAssertDescriptionInit(T?( 10), "10") + NBKAssertDescriptionInit(T?( 10), "+10") + NBKAssertDescriptionInit(T?(nil), "-10") + NBKAssertDescriptionInit(T?(nil), " 10") + NBKAssertDescriptionInit(T?(nil), "0x10") + NBKAssertDescriptionInit(T?(nil), "+0x10") + NBKAssertDescriptionInit(T?(nil), "-0x10") + NBKAssertDescriptionInit(T?(nil), " 0x10") } func testInstanceDescriptionUsesRadix10() { @@ -478,6 +476,15 @@ final class NBKDoubleWidthTestsOnTextAsUInt256: XCTestCase { // MARK: * NBK x Double Width x Text x Assertions //*============================================================================* +private func NBKAssertDescriptionInit( +_ integer: NBKDoubleWidth?, _ description: String, +file: StaticString = #file, line: UInt = #line) { + typealias T = NBKDoubleWidth + //=------------------------------------------= + XCTAssertEqual(T(description), integer, file: file, line: line) + XCTAssertEqual(T(description, radix: 10), integer, file: file, line: line) +} + private func NBKAssertDecodeText( _ integer: NBKDoubleWidth?, _ radix: Int, _ text: String, file: StaticString = #file, line: UInt = #line) { From 4a157b33c0b4c7910898b64d0b1bd7b3a26e1d00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Thu, 17 Aug 2023 15:17:20 +0200 Subject: [PATCH 030/111] [NBKDoubleWidthKit] ExpressibleByStringLiteral (#62) --- .../NBKDoubleWidth+Literals.swift | 61 +++++++++------ .../NBKDoubleWidthKit/NBKDoubleWidth.swift | 2 +- .../NBKDoubleWidth+Literals.swift | 74 +++++-------------- .../NBKDoubleWidth+Text.swift | 38 +++++----- 4 files changed, 78 insertions(+), 97 deletions(-) diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift index ab465820..c12df004 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift @@ -12,6 +12,41 @@ import NBKCoreKit //*============================================================================* // MARK: * NBK x Double Width x Literals //*============================================================================* + +extension NBKDoubleWidth { + + + //=------------------------------------------------------------------------= + // MARK: Details x String Literal Type + //=------------------------------------------------------------------------= + + #if swift(>=5.8) && SBI + @available(swift, deprecated: 5.8, message: "Use an integer literal instead.") + #endif + @inlinable public init(stringLiteral source: StringLiteralType) { + if let value = Self(exactlyStringLiteral: source) { self = value } else { + preconditionFailure("\(Self.description) cannot represent \(source)") + } + } + + #if swift(>=5.8) && SBI + @available(swift, deprecated: 5.8, message: "Use an integer literal instead.") + #endif + @inlinable init?(exactlyStringLiteral source: StringLiteralType) { + var source = source + + let value: Optional = source.withUTF8 { utf8 in + let components = NBK.makeIntegerComponentsWithRadix(utf8: utf8) + let radix = NBK.AnyRadixUIntRoot(components.radix) + let digits = NBK.UnsafeUTF8(rebasing: components.body) + guard let magnitude = Magnitude(digits: digits, radix: radix) else { return nil } + return Self(sign: components.sign, magnitude: magnitude) + } + + if let value { self = value } else { return nil } + } +} + //=----------------------------------------------------------------------------= // MARK: + Version ≥ iOS 16.4, macOS 13.3 //=----------------------------------------------------------------------------= @@ -20,7 +55,7 @@ import NBKCoreKit extension NBKDoubleWidth { //=-------------------------------------------------------------------------= - // MARK: Initializers + // MARK: Details x Integer Literal Type //=-------------------------------------------------------------------------= @inlinable public init(integerLiteral source: StaticBigInt) { @@ -48,35 +83,15 @@ extension NBKDoubleWidth { // MARK: + Version < iOS 16.4, macOS 13.3 //=----------------------------------------------------------------------------= -extension NBKDoubleWidth: ExpressibleByStringLiteral { +extension NBKDoubleWidth { //=------------------------------------------------------------------------= - // MARK: Initializers + // MARK: Initializers x Integer Literal Type //=------------------------------------------------------------------------= @inlinable public init(integerLiteral source: Int64) { self.init(source) } - - @inlinable public init(stringLiteral source: StringLiteralType) { - if let value = Self(exactlyStringLiteral: source) { self = value } else { - preconditionFailure("\(Self.description) cannot represent \(source)") - } - } - - @inlinable init?(exactlyStringLiteral source: StringLiteralType) { - var source = source - - let value: Optional = source.withUTF8 { utf8 in - let components = NBK.makeIntegerComponentsWithRadix(utf8: utf8) - let radix = NBK.AnyRadixUIntRoot(components.radix) - let digits = NBK.UnsafeUTF8(rebasing: components.body) - guard let magnitude = Magnitude(digits: digits, radix: radix) else { return nil } - return Self(sign: components.sign, magnitude: magnitude) - } - - if let value { self = value } else { return nil } - } } #endif diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift index adc9228c..9d546069 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift @@ -81,7 +81,7 @@ import NBKCoreKit /// /// - Note: The `Digit` type is `Int` when `Self` is signed, and `UInt` otherwise. /// -@frozen public struct NBKDoubleWidth: +@frozen public struct NBKDoubleWidth: ExpressibleByStringLiteral, NBKFixedWidthInteger, MutableCollection, RandomAccessCollection where High: NBKFixedWidthInteger, High.Digit: NBKCoreInteger { diff --git a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Literals.swift b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Literals.swift index 112b3ef0..689f8326 100644 --- a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Literals.swift +++ b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Literals.swift @@ -19,10 +19,6 @@ private typealias Y = NBK.U256X32 //*============================================================================* // MARK: * NBK x Double Width x Literals x Int256 //*============================================================================* -//=----------------------------------------------------------------------------= -// MARK: + Version ≥ iOS 16.4, macOS 13.3 -//=----------------------------------------------------------------------------= -#if swift(>=5.8) && SBI final class NBKDoubleWidthTestsOnLiteralsAsInt256: XCTestCase { @@ -33,6 +29,7 @@ final class NBKDoubleWidthTestsOnLiteralsAsInt256: XCTestCase { //=------------------------------------------------------------------------= func testFromIntegerLiteral() { + #if swift(>=5.8) && SBI XCTAssertEqual(T(x64: X( 0, 0, 0, 0)), 0x0000000000000000000000000000000000000000000000000000000000000000) XCTAssertEqual(T(x64: X(~0, 0, 0, 0)), 0x000000000000000000000000000000000000000000000000ffffffffffffffff) XCTAssertEqual(T(x64: X(~0, ~0, 0, 0)), 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) @@ -46,30 +43,17 @@ final class NBKDoubleWidthTestsOnLiteralsAsInt256: XCTestCase { XCTAssertEqual(T(exactlyIntegerLiteral: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff), T.max) XCTAssertEqual(T(exactlyIntegerLiteral: -0x8000000000000000000000000000000000000000000000000000000000000000), T.min) XCTAssertEqual(T(exactlyIntegerLiteral: -0x8000000000000000000000000000000000000000000000000000000000000001), nil) - } -} - -#else -//=----------------------------------------------------------------------------= -// MARK: + Version < iOS 16.4, macOS 13.3 -//=----------------------------------------------------------------------------= - -final class NBKDoubleWidthTestsOnLiteralsAsInt256: XCTestCase { - - typealias T = Int256 - typealias L = Int256.IntegerLiteralType - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testFromIntegerLiteral() { - XCTAssertEqual(T(integerLiteral: 0x7fffffffffffffff as L), T(x64: X(UInt64(L.max), 0, 0, 0))) - XCTAssertEqual(T(integerLiteral: 0x0000000000000000 as L), T(x64: X(UInt64(L( )), 0, 0, 0))) - XCTAssertEqual(T(integerLiteral: -0x0000000000000001 as L), ~T(x64: X(UInt64(L( )), 0, 0, 0))) - XCTAssertEqual(T(integerLiteral: -0x8000000000000000 as L), ~T(x64: X(UInt64(L.max), 0, 0, 0))) + #else + XCTAssertEqual(T(integerLiteral: 0x7fffffffffffffff as Int64), T(x64: X(UInt64(Int64.max), 0, 0, 0))) + XCTAssertEqual(T(integerLiteral: 0x0000000000000000 as Int64), T(x64: X(UInt64(Int64( )), 0, 0, 0))) + XCTAssertEqual(T(integerLiteral: -0x0000000000000001 as Int64), ~T(x64: X(UInt64(Int64( )), 0, 0, 0))) + XCTAssertEqual(T(integerLiteral: -0x8000000000000000 as Int64), ~T(x64: X(UInt64(Int64.max), 0, 0, 0))) + #endif } + #if swift(>=5.8) && SBI + @available(swift, deprecated: 5.8, message: "Use an integer literal instead.") + #endif func testFromStringLiteral() { XCTAssertEqual(T(x64: X( 0, 0, 0, 0)), "0x0000000000000000000000000000000000000000000000000000000000000000") XCTAssertEqual(T(x64: X(~0, 0, 0, 0)), "0x000000000000000000000000000000000000000000000000ffffffffffffffff") @@ -87,14 +71,9 @@ final class NBKDoubleWidthTestsOnLiteralsAsInt256: XCTestCase { } } -#endif //*============================================================================* // MARK: * NBK x Double Width x Literals x UInt256 //*============================================================================* -//=----------------------------------------------------------------------------= -// MARK: + Version ≥ iOS 16.4, macOS 13.3 -//=----------------------------------------------------------------------------= -#if swift(>=5.8) && SBI final class NBKDoubleWidthTestsOnLiteralsAsUInt256: XCTestCase { @@ -105,6 +84,7 @@ final class NBKDoubleWidthTestsOnLiteralsAsUInt256: XCTestCase { //=------------------------------------------------------------------------= func testFromIntegerLiteral() { + #if swift(>=5.8) && SBI XCTAssertEqual(T(x64: X( 0, 0, 0, 0)), 0x0000000000000000000000000000000000000000000000000000000000000000) XCTAssertEqual(T(x64: X(~0, 0, 0, 0)), 0x000000000000000000000000000000000000000000000000ffffffffffffffff) XCTAssertEqual(T(x64: X(~0, ~0, 0, 0)), 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) @@ -118,30 +98,17 @@ final class NBKDoubleWidthTestsOnLiteralsAsUInt256: XCTestCase { XCTAssertEqual(T(exactlyIntegerLiteral: 0x00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff), T.max) XCTAssertEqual(T(exactlyIntegerLiteral: 0x000000000000000000000000000000000000000000000000000000000000000000), T.min) XCTAssertEqual(T(exactlyIntegerLiteral: -0x000000000000000000000000000000000000000000000000000000000000000001), nil) - } -} - -#else -//=----------------------------------------------------------------------------= -// MARK: + Version < iOS 16.4, macOS 13.3 -//=----------------------------------------------------------------------------= - -final class NBKDoubleWidthTestsOnLiteralsAsUInt256: XCTestCase { - - typealias T = UInt256 - typealias L = UInt256.IntegerLiteralType - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testFromIntegerLiteral() { - XCTAssertEqual(T(integerLiteral: 0x7fffffffffffffff as L), T(x64: X(UInt64(L.max), 0, 0, 0))) - XCTAssertEqual(T(integerLiteral: 0x0000000000000000 as L), T(x64: X(UInt64(L( )), 0, 0, 0))) - XCTAssertEqual(T(exactly: -0x0000000000000001 as L), nil) - XCTAssertEqual(T(exactly: -0x8000000000000000 as L), nil) + #else + XCTAssertEqual(T(integerLiteral: 0x7fffffffffffffff as Int64), T(x64: X(UInt64(Int64.max), 0, 0, 0))) + XCTAssertEqual(T(integerLiteral: 0x0000000000000000 as Int64), T(x64: X(UInt64(Int64( )), 0, 0, 0))) + XCTAssertEqual(T(exactly: -0x0000000000000001 as Int64), nil) + XCTAssertEqual(T(exactly: -0x8000000000000000 as Int64), nil) + #endif } + #if swift(>=5.8) && SBI + @available(swift, deprecated: 5.8, message: "Use an integer literal instead.") + #endif func testFromStringLiteral() { XCTAssertEqual(T(x64: X( 0, 0, 0, 0)), "0x0000000000000000000000000000000000000000000000000000000000000000") XCTAssertEqual(T(x64: X(~0, 0, 0, 0)), "0x000000000000000000000000000000000000000000000000ffffffffffffffff") @@ -160,4 +127,3 @@ final class NBKDoubleWidthTestsOnLiteralsAsUInt256: XCTestCase { } #endif -#endif diff --git a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Text.swift b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Text.swift index 1569918e..4806f3f8 100644 --- a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Text.swift +++ b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Text.swift @@ -29,15 +29,15 @@ final class NBKDoubleWidthTestsOnTextAsInt256: XCTestCase { // MARK: Tests //=------------------------------------------------------------------------= - func testDescriptionInit() { - NBKAssertDescriptionInit(T?( 10), "10") - NBKAssertDescriptionInit(T?( 10), "+10") - NBKAssertDescriptionInit(T?(-10), "-10") - NBKAssertDescriptionInit(T?(nil), " 10") - NBKAssertDescriptionInit(T?(nil), "0x10") - NBKAssertDescriptionInit(T?(nil), "+0x10") - NBKAssertDescriptionInit(T?(nil), "-0x10") - NBKAssertDescriptionInit(T?(nil), " 0x10") + func testFromDescription() { + NBKAssertFromDescription(T?( 10), "10") + NBKAssertFromDescription(T?( 10), "+10") + NBKAssertFromDescription(T?(-10), "-10") + NBKAssertFromDescription(T?(nil), " 10") + NBKAssertFromDescription(T?(nil), "0x10") + NBKAssertFromDescription(T?(nil), "+0x10") + NBKAssertFromDescription(T?(nil), "-0x10") + NBKAssertFromDescription(T?(nil), " 0x10") } func testDescriptionUsesRadix10() { @@ -267,15 +267,15 @@ final class NBKDoubleWidthTestsOnTextAsUInt256: XCTestCase { // MARK: Tests //=------------------------------------------------------------------------= - func testDescriptionInit() { - NBKAssertDescriptionInit(T?( 10), "10") - NBKAssertDescriptionInit(T?( 10), "+10") - NBKAssertDescriptionInit(T?(nil), "-10") - NBKAssertDescriptionInit(T?(nil), " 10") - NBKAssertDescriptionInit(T?(nil), "0x10") - NBKAssertDescriptionInit(T?(nil), "+0x10") - NBKAssertDescriptionInit(T?(nil), "-0x10") - NBKAssertDescriptionInit(T?(nil), " 0x10") + 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() { @@ -476,7 +476,7 @@ final class NBKDoubleWidthTestsOnTextAsUInt256: XCTestCase { // MARK: * NBK x Double Width x Text x Assertions //*============================================================================* -private func NBKAssertDescriptionInit( +private func NBKAssertFromDescription( _ integer: NBKDoubleWidth?, _ description: String, file: StaticString = #file, line: UInt = #line) { typealias T = NBKDoubleWidth From 9ff2ece7a31eb928d25dbd107fc148b4c2c11390 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Thu, 17 Aug 2023 18:02:46 +0200 Subject: [PATCH 031/111] [NBKCoreKit] Cleanup. --- .../Private/NBK+Text+Components.swift | 26 +++--- .../NBKDoubleWidth+Literals.swift | 2 +- .../Private/NBK+Text+Components.swift | 90 +++++++++---------- 3 files changed, 60 insertions(+), 58 deletions(-) diff --git a/Sources/NBKCoreKit/Private/NBK+Text+Components.swift b/Sources/NBKCoreKit/Private/NBK+Text+Components.swift index 836ba10c..ebc78461 100644 --- a/Sources/NBKCoreKit/Private/NBK+Text+Components.swift +++ b/Sources/NBKCoreKit/Private/NBK+Text+Components.swift @@ -29,7 +29,7 @@ extension NBK { /// └─────── → ──────┴────────┘ /// ``` /// - @inlinable public static func removeSignPrefix(utf8: inout T) -> Sign? where T: Collection, T == T.SubSequence { + @inlinable public static func removeLeadingSign(utf8: inout T) -> Sign? where T: Collection, T == T.SubSequence { switch utf8.first { case UInt8(ascii: "+"): utf8.removeFirst(); return Sign.plus case UInt8(ascii: "-"): utf8.removeFirst(); return Sign.minus @@ -46,12 +46,12 @@ extension NBK { /// │ "0o123" │ 008 │ "123" │ /// │ "0x123" │ 016 │ "123" │ /// ├──────── → ──────┼─────────┤ - /// │ "1x123" │ nil │ "1x123" │ + /// │ "Ox123" │ nil │ "Ox123" │ /// │ "0X123" │ nil │ "0X123" │ /// └──────── → ──────┴─────────┘ /// ``` /// - @inlinable public static func removeRadixPrefix(utf8: inout T) -> Int? where T: Collection, T == T.SubSequence { + @inlinable public static func removeLeadingRadix(utf8: inout T) -> Int? where T: Collection, T == T.SubSequence { var radix: Int? var index = utf8.startIndex @@ -83,9 +83,10 @@ extension NBK { /// /// - Note: Integers without sign are interpreted as positive. /// - @inlinable public static func makeIntegerComponents(utf8: T) -> (sign: Sign, body: T.SubSequence) where T: Collection { + @inlinable public static func makeIntegerComponents(utf8: T) + -> (sign: Sign, body: T.SubSequence) where T: Collection { var body = utf8[...] as T.SubSequence - let sign = NBK.removeSignPrefix(utf8: &body) ?? Sign.plus + let sign = NBK.removeLeadingSign(utf8: &body) ?? Sign.plus return (sign: sign, body: body) } @@ -95,11 +96,11 @@ extension NBK { /// ┌───────── → ──────┬───────┬──────────┐ /// │ body │ sign │ radix │ body │ /// ├───────── → ──────┼───────┼──────────┤ + /// │ "123" │ plus │ 010 │ "123" │ /// │ "+0b123" │ plus │ 002 │ "123" │ /// │ "-0x123" │ minus │ 016 │ "123" │ /// ├───────── → ──────┼───────┼──────────┤ - /// │ "123" │ plus │ 010 │ "123" │ - /// │ "~1x123" │ plus │ 010 │ "~1x123" │ + /// │ "~Ox123" │ plus │ 010 │ "~Ox123" │ /// │ "~0X123" │ plus │ 010 │ "~0X123" │ /// └───────── → ──────┴───────┴──────────┘ /// ``` @@ -108,10 +109,11 @@ extension NBK { /// /// - Note: Integers without radix are interpreted as base 10. /// - @inlinable public static func makeIntegerComponentsWithRadix(utf8: T) -> (sign: Sign, radix: Int, body: T.SubSequence) where T: Collection { - var body = utf8[...] as T.SubSequence - let sign = NBK.removeSignPrefix(utf8: &body) ?? Sign.plus - let radix = NBK.removeRadixPrefix(utf8: &body) ?? 10 as Int - return (sign: sign, radix: radix, body: body) + @inlinable public static func makeIntegerComponentsByDecodingRadix(utf8: T) + -> (sign: Sign, radix: Int, body: T.SubSequence) where T: Collection { + var body = utf8[...] as T.SubSequence + let sign = NBK.removeLeadingSign (utf8: &body) ?? Sign.plus + let radix = NBK.removeLeadingRadix(utf8: &body) ?? 10 as Int + return (sign: sign, radix: radix, body: body) } } diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift index c12df004..686c1ae9 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift @@ -36,7 +36,7 @@ extension NBKDoubleWidth { var source = source let value: Optional = source.withUTF8 { utf8 in - let components = NBK.makeIntegerComponentsWithRadix(utf8: utf8) + let components = NBK.makeIntegerComponentsByDecodingRadix(utf8: utf8) let radix = NBK.AnyRadixUIntRoot(components.radix) let digits = NBK.UnsafeUTF8(rebasing: components.body) guard let magnitude = Magnitude(digits: digits, radix: radix) else { return nil } diff --git a/Tests/NBKCoreKitTests/Private/NBK+Text+Components.swift b/Tests/NBKCoreKitTests/Private/NBK+Text+Components.swift index 574d2a93..ad5e6e16 100644 --- a/Tests/NBKCoreKitTests/Private/NBK+Text+Components.swift +++ b/Tests/NBKCoreKitTests/Private/NBK+Text+Components.swift @@ -22,28 +22,28 @@ final class NBKTestsOnTextByComponents: XCTestCase { // MARK: Tests //=------------------------------------------------------------------------= - func testRemoveSignPrefix() { - NBKAssertRemoveSignPrefix( "", nil, "") - NBKAssertRemoveSignPrefix( "+", .plus, "") - NBKAssertRemoveSignPrefix( "-", .minus, "") - NBKAssertRemoveSignPrefix( "~", nil, "~") - NBKAssertRemoveSignPrefix("+123", .plus, "123") - NBKAssertRemoveSignPrefix("-123", .minus, "123") - NBKAssertRemoveSignPrefix("~123", nil, "~123") + func testRemoveLeadingSign() { + NBKAssertRemoveLeadingSign( "", nil, "") + NBKAssertRemoveLeadingSign( "+", .plus, "") + NBKAssertRemoveLeadingSign( "-", .minus, "") + NBKAssertRemoveLeadingSign( "~", nil, "~") + NBKAssertRemoveLeadingSign("+123", .plus, "123") + NBKAssertRemoveLeadingSign("-123", .minus, "123") + NBKAssertRemoveLeadingSign("~123", nil, "~123") } - func testRemoveRadixPrefix() { - NBKAssertRemoveRadixPrefix( "", nil, "") - NBKAssertRemoveRadixPrefix( "0b", 002, "") - NBKAssertRemoveRadixPrefix( "0o", 008, "") - NBKAssertRemoveRadixPrefix( "0x", 016, "") - NBKAssertRemoveRadixPrefix( "1x", nil, "1x") - NBKAssertRemoveRadixPrefix( "0X", nil, "0X") - NBKAssertRemoveRadixPrefix("0b123", 002, "123") - NBKAssertRemoveRadixPrefix("0o123", 008, "123") - NBKAssertRemoveRadixPrefix("0x123", 016, "123") - NBKAssertRemoveRadixPrefix("1x123", nil, "1x123") - NBKAssertRemoveRadixPrefix("0X123", nil, "0X123") + func testRemoveLeadingRadix() { + NBKAssertRemoveLeadingRadix( "", nil, "") + NBKAssertRemoveLeadingRadix( "0b", 002, "") + NBKAssertRemoveLeadingRadix( "0o", 008, "") + NBKAssertRemoveLeadingRadix( "0x", 016, "") + NBKAssertRemoveLeadingRadix( "Ox", nil, "Ox") + NBKAssertRemoveLeadingRadix( "0X", nil, "0X") + NBKAssertRemoveLeadingRadix("0b123", 002, "123") + NBKAssertRemoveLeadingRadix("0o123", 008, "123") + NBKAssertRemoveLeadingRadix("0x123", 016, "123") + NBKAssertRemoveLeadingRadix("Ox123", nil, "Ox123") + NBKAssertRemoveLeadingRadix("0X123", nil, "0X123") } func testMakeIntegerComponents() { @@ -56,25 +56,25 @@ final class NBKTestsOnTextByComponents: XCTestCase { NBKAssertMakeIntegerComponents("~123", .plus, "~123") } - func testMakeIntegerComponentsWithRadix() { - NBKAssertMakeIntegerComponentsWithRadix( "", .plus, 10, "") - NBKAssertMakeIntegerComponentsWithRadix( "+", .plus, 10, "") - NBKAssertMakeIntegerComponentsWithRadix( "-", .minus, 10, "") - NBKAssertMakeIntegerComponentsWithRadix( "~", .plus, 10, "~") - NBKAssertMakeIntegerComponentsWithRadix( "0b", .plus, 02, "") - NBKAssertMakeIntegerComponentsWithRadix( "0o", .plus, 08, "") - NBKAssertMakeIntegerComponentsWithRadix( "0x", .plus, 16, "") - NBKAssertMakeIntegerComponentsWithRadix( "1x", .plus, 10, "1x") - NBKAssertMakeIntegerComponentsWithRadix( "0X", .plus, 10, "0X") - NBKAssertMakeIntegerComponentsWithRadix( "123", .plus, 10, "123") - NBKAssertMakeIntegerComponentsWithRadix("+0b123", .plus, 02, "123") - NBKAssertMakeIntegerComponentsWithRadix("+0o123", .plus, 08, "123") - NBKAssertMakeIntegerComponentsWithRadix("+0x123", .plus, 16, "123") - NBKAssertMakeIntegerComponentsWithRadix("-0b123", .minus, 02, "123") - NBKAssertMakeIntegerComponentsWithRadix("-0o123", .minus, 08, "123") - NBKAssertMakeIntegerComponentsWithRadix("-0x123", .minus, 16, "123") - NBKAssertMakeIntegerComponentsWithRadix("~1x123", .plus, 10, "~1x123") - NBKAssertMakeIntegerComponentsWithRadix("~0X123", .plus, 10, "~0X123") + func testMakeIntegerComponentsByDecodingRadix() { + NBKAssertMakeIntegerComponentsByDecodingRadix( "", .plus, 10, "") + NBKAssertMakeIntegerComponentsByDecodingRadix( "+", .plus, 10, "") + NBKAssertMakeIntegerComponentsByDecodingRadix( "-", .minus, 10, "") + NBKAssertMakeIntegerComponentsByDecodingRadix( "~", .plus, 10, "~") + NBKAssertMakeIntegerComponentsByDecodingRadix( "0b", .plus, 02, "") + NBKAssertMakeIntegerComponentsByDecodingRadix( "0o", .plus, 08, "") + NBKAssertMakeIntegerComponentsByDecodingRadix( "0x", .plus, 16, "") + NBKAssertMakeIntegerComponentsByDecodingRadix( "Ox", .plus, 10, "Ox") + NBKAssertMakeIntegerComponentsByDecodingRadix( "0X", .plus, 10, "0X") + NBKAssertMakeIntegerComponentsByDecodingRadix( "123", .plus, 10, "123") + NBKAssertMakeIntegerComponentsByDecodingRadix("+0b123", .plus, 02, "123") + NBKAssertMakeIntegerComponentsByDecodingRadix("+0o123", .plus, 08, "123") + NBKAssertMakeIntegerComponentsByDecodingRadix("+0x123", .plus, 16, "123") + NBKAssertMakeIntegerComponentsByDecodingRadix("-0b123", .minus, 02, "123") + NBKAssertMakeIntegerComponentsByDecodingRadix("-0o123", .minus, 08, "123") + NBKAssertMakeIntegerComponentsByDecodingRadix("-0x123", .minus, 16, "123") + NBKAssertMakeIntegerComponentsByDecodingRadix("~Ox123", .plus, 10, "~Ox123") + NBKAssertMakeIntegerComponentsByDecodingRadix("~0X123", .plus, 10, "~0X123") } } @@ -82,20 +82,20 @@ final class NBKTestsOnTextByComponents: XCTestCase { // MARK: * NBK x Text x Components x Assertions //*============================================================================* -private func NBKAssertRemoveSignPrefix( +private func NBKAssertRemoveLeadingSign( _ text: String, _ sign: FloatingPointSign?, _ body: String, file: StaticString = #file, line: UInt = #line) { var componentsBody = text.utf8[...] - let componentsSign = NBK.removeSignPrefix(utf8: &componentsBody) + let componentsSign = NBK.removeLeadingSign(utf8: &componentsBody) XCTAssertEqual(componentsSign, sign, file: file, line: line) XCTAssertEqual(Array(componentsBody), Array(body.utf8), file: file, line: line) } -private func NBKAssertRemoveRadixPrefix( +private func NBKAssertRemoveLeadingRadix( _ text: String, _ radix: Int?, _ body: String, file: StaticString = #file, line: UInt = #line) { var componentsBody = text.utf8[...] - let componentsSign = NBK.removeRadixPrefix(utf8: &componentsBody) + let componentsSign = NBK.removeLeadingRadix(utf8: &componentsBody) XCTAssertEqual(componentsSign, radix, file: file, line: line) XCTAssertEqual(Array(componentsBody), Array(body.utf8), file: file, line: line) } @@ -108,10 +108,10 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual(Array(components.body), Array(body.utf8), file: file, line: line) } -private func NBKAssertMakeIntegerComponentsWithRadix( +private func NBKAssertMakeIntegerComponentsByDecodingRadix( _ text: String, _ sign: FloatingPointSign?, _ radix: Int?, _ body: String, file: StaticString = #file, line: UInt = #line) { - let components = NBK.makeIntegerComponentsWithRadix(utf8: text.utf8) + let components = NBK.makeIntegerComponentsByDecodingRadix(utf8: text.utf8) XCTAssertEqual(components.sign, sign, file: file, line: line) XCTAssertEqual(components.radix, radix, file: file, line: line) XCTAssertEqual(Array(components.body), Array(body.utf8), file: file, line: line) From 750833a4967402cd9a5debc827be9df9846a8a3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Fri, 18 Aug 2023 10:49:39 +0200 Subject: [PATCH 032/111] [Package] Lower platform requirements (#61) (#62). --- .utilities/update-gh-pages-docs-no-push.sh | 1 - Package.swift | 2 +- README.md | 25 +++++- .../NBKDoubleWidth+Addition+Digit.swift | 3 + .../NBKDoubleWidth+Addition.swift | 3 + .../NBKDoubleWidth+Bits.swift | 3 + .../NBKDoubleWidth+Comparisons.swift | 3 + .../NBKDoubleWidth+Complements.swift | 3 + .../NBKDoubleWidth+Division+Digit.swift | 6 ++ .../NBKDoubleWidth+Division.swift | 6 ++ .../NBKDoubleWidth+Endianness.swift | 3 + .../NBKDoubleWidth+Literals.swift | 86 ++++++++----------- .../NBKDoubleWidth+Logic.swift | 3 + .../NBKDoubleWidth+Multiplication+Digit.swift | 6 ++ .../NBKDoubleWidth+Multiplication.swift | 6 ++ .../NBKDoubleWidth+Numbers.swift | 3 + .../NBKDoubleWidth+Rotations.swift | 6 ++ .../NBKDoubleWidth+Shifts.swift | 6 ++ .../NBKDoubleWidth+Strides.swift | 3 + .../NBKDoubleWidth+Subtraction+Digit.swift | 3 + .../NBKDoubleWidth+Subtraction.swift | 3 + .../NBKDoubleWidth+Text.swift | 6 ++ .../NBKDoubleWidth+Uninitialized.swift | 3 + .../NBKDoubleWidth+Words+Pointers.swift | 3 + .../NBKDoubleWidth+Words.swift | 12 +++ .../NBKDoubleWidthKit/NBKDoubleWidth.swift | 64 ++++++++++++++ .../Documentation.docc/Documentation.md | 12 +++ .../NBKDoubleWidth+Addition.swift | 6 ++ .../NBKDoubleWidth+Bits.swift | 6 ++ .../NBKDoubleWidth+Comparisons.swift | 6 ++ .../NBKDoubleWidth+Complements.swift | 6 ++ .../NBKDoubleWidth+Division.swift | 6 ++ .../NBKDoubleWidth+Endianness.swift | 6 ++ .../NBKDoubleWidth+Logic.swift | 6 ++ .../NBKDoubleWidth+Multiplication.swift | 6 ++ .../NBKDoubleWidth+Numbers.swift | 6 ++ .../NBKDoubleWidth+Random.swift | 6 ++ .../NBKDoubleWidth+Rotations.swift | 6 ++ .../NBKDoubleWidth+Shifts.swift | 6 ++ .../NBKDoubleWidth+Strides.swift | 6 ++ .../NBKDoubleWidth+Subtraction.swift | 6 ++ .../NBKDoubleWidth+Text.swift | 6 ++ .../NBKDoubleWidth.swift | 9 ++ .../NBKDoubleWidth+Addition.swift | 12 +++ .../NBKDoubleWidth+Bits.swift | 6 ++ .../NBKDoubleWidth+Comparisons.swift | 15 ++++ .../NBKDoubleWidth+Complements.swift | 21 +++++ .../NBKDoubleWidth+Division.swift | 18 ++++ .../NBKDoubleWidth+Endianness.swift | 6 ++ .../NBKDoubleWidth+Literals.swift | 14 ++- .../NBKDoubleWidth+Logic.swift | 18 ++++ .../NBKDoubleWidth+Multiplication.swift | 15 ++++ .../NBKDoubleWidth+Numbers.swift | 21 +++++ .../NBKDoubleWidth+Rotations.swift | 12 +++ .../NBKDoubleWidth+Shifts.swift | 18 ++++ .../NBKDoubleWidth+Strides.swift | 6 ++ .../NBKDoubleWidth+Subtraction.swift | 12 +++ .../NBKDoubleWidth+Text.swift | 15 ++++ .../NBKDoubleWidth+Words.swift | 15 ++++ .../NBKDoubleWidth.swift | 15 ++++ 60 files changed, 561 insertions(+), 60 deletions(-) diff --git a/.utilities/update-gh-pages-docs-no-push.sh b/.utilities/update-gh-pages-docs-no-push.sh index 3890d4a9..7ab1081b 100755 --- a/.utilities/update-gh-pages-docs-no-push.sh +++ b/.utilities/update-gh-pages-docs-no-push.sh @@ -16,7 +16,6 @@ # │ └─── SCRIPT.sh # │ # └─── .swiftpm/xcode/xcshareddata/PROJECT.xcscheme -# #=-----------------------------------------------------------------------------= set -eu diff --git a/Package.swift b/Package.swift index 203b227f..3bf2d141 100644 --- a/Package.swift +++ b/Package.swift @@ -14,7 +14,7 @@ import PackageDescription // MARK: * Numberick //*============================================================================* -let withStaticBigInt = true +let withStaticBigInt = false //=----------------------------------------------------------------------------= // MARK: + Version < iOS 16.4, macOS 13.3 diff --git a/README.md b/README.md index a61efa45..1983eadb 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,10 @@ ✨ An arithmagick overhaul in Swift. -| Package | Swift | iOS | iPadOS | Mac Catalyst | macOS | tvOS | watchOS | -|:-------:|:-----:|:----:|:------:|:------------:|:-----:|:----:|:-------:| -| 0.9.0 | 5.7 | 16.4 | 16.4 | 16.4 | 13.3 | 16.4 | 9.4 | +| Package | Swift | iOS | Mac Catalyst | macOS | tvOS | watchOS | +|:-------:|:-----:|:-----:|:------------:|:-----:|:-----:|:-------:| +| 0.10.0 | 5.7+ | 14.0+ | 14.0+ | 11.0+ | 14.0+ | 7.0+ | +| 0.9.0 | 5.7+ | 16.4+ | 16.4+ | 13.3+ | 16.4+ | 9.4+ | ## NBKCoreKit ([Sources][COR/S], [Tests][COR/T], [Benchmarks][COR/B]) @@ -89,6 +90,19 @@ Int256(5) % Int(5), UInt256(5) % UInt(5) > **Note**: The `Digit` type is `Int` when `Self` is signed, and `UInt` otherwise. +### Feature: StaticBigInt (v0.10.0+) + +Because `StaticBigInt` [does not back-deploy][Apple/StaticBigInt/SE], it is gated +by [availability][Apple/StaticBigInt] and the compiler flag `SBI`. Setting the +constant `withStaticBigInt` to `true` in `Package.swift` enables it. Alternatively, +you can use the command line: + +``` +swift build -Xswiftc -DSBI +``` + +> **Note**: You can use `init(stringLiteral:)` until `StaticBigInt` becomes available. + ## Acknowledgements This project is inspired by [**Int128**][Apple/Int128] and [**DoubleWidth**][Apple/DoubleWidth] by Apple. @@ -107,6 +121,11 @@ This project is inspired by [**Int128**][Apple/Int128] and [**DoubleWidth**][App [COR/B]: Tests/NBKCoreKitBenchmarks [DBL/B]: Tests/NBKDoubleWidthKitBenchmarks + + +[Apple/StaticBigInt]: https://developer.apple.com/documentation/swift/staticbigint +[Apple/StaticBigInt/SE]: https://github.com/apple/swift-evolution/blob/main/proposals/0368-staticbigint.md + [Apple/Int128]: https://github.com/apple/swift/blob/main/stdlib/public/core/Int128.swift.gyb diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Addition+Digit.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Addition+Digit.swift index 6b9eb3f9..a68260fa 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Addition+Digit.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Addition+Digit.swift @@ -13,6 +13,9 @@ import NBKCoreKit // MARK: * NBK x Double Width x Addition x Digit //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Addition.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Addition.swift index 2edbe327..e9cba24c 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Addition.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Addition.swift @@ -13,6 +13,9 @@ import NBKCoreKit // MARK: * NBK x Double Width x Addition //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Bits.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Bits.swift index 167da9f8..502551fd 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Bits.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Bits.swift @@ -13,6 +13,9 @@ import NBKCoreKit // MARK: * NBK x Double Width x Bits //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Comparisons.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Comparisons.swift index b3ef7983..c05fc564 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Comparisons.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Comparisons.swift @@ -13,6 +13,9 @@ import NBKCoreKit // MARK: * NBK x Double Width x Comparisons //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Complements.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Complements.swift index 4fd3bd0a..56eac937 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Complements.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Complements.swift @@ -13,6 +13,9 @@ import NBKCoreKit // MARK: * NBK x Double Width x Complements //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Division+Digit.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Division+Digit.swift index 13c6212a..db686eed 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Division+Digit.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Division+Digit.swift @@ -13,6 +13,9 @@ import NBKCoreKit // MARK: * NBK x Double Width x Division x Digit //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= @@ -68,6 +71,9 @@ extension NBKDoubleWidth { // MARK: + Unsigned //=----------------------------------------------------------------------------= +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif extension NBKDoubleWidth where High == High.Magnitude { //=------------------------------------------------------------------------= diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Division.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Division.swift index 6cb22dde..8dbfeb24 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Division.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Division.swift @@ -13,6 +13,9 @@ import NBKCoreKit // MARK: * NBK x Double Width x Division //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= @@ -114,6 +117,9 @@ extension NBKDoubleWidth { // MARK: + Unsigned //=----------------------------------------------------------------------------= +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif extension NBKDoubleWidth where High == High.Magnitude { //=------------------------------------------------------------------------= diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Endianness.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Endianness.swift index 511fd439..50a5cc19 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Endianness.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Endianness.swift @@ -13,6 +13,9 @@ import NBKCoreKit // MARK: * NBK x Double Width x Endianness //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift index 686c1ae9..fcd6f266 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift @@ -13,14 +13,47 @@ import NBKCoreKit // MARK: * NBK x Double Width x Literals //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif extension NBKDoubleWidth { + //=-------------------------------------------------------------------------= + // MARK: Details x Integer Literal Type + //=-------------------------------------------------------------------------= + #if SBI && swift(>=5.8) + + @inlinable public init(integerLiteral source: StaticBigInt) { + if let value = Self(exactlyIntegerLiteral: source) { self = value } else { + preconditionFailure("\(Self.description) cannot represent \(source)") + } + } + + @inlinable init?(exactlyIntegerLiteral source: StaticBigInt) { + guard Self.isSigned + ? source.bitWidth <= Self.bitWidth + : source.bitWidth <= Self.bitWidth + 1 && source.signum() >= 0 + else { return nil } + + self = Self.uninitialized { value in + for index in value.indices { + value[unchecked: index] = source[index] + } + } + } + + #else + + @inlinable public init(integerLiteral source: Swift.Int64) { + self.init(source) + } + #endif //=------------------------------------------------------------------------= // MARK: Details x String Literal Type //=------------------------------------------------------------------------= - #if swift(>=5.8) && SBI + #if SBI && swift(>=5.8) @available(swift, deprecated: 5.8, message: "Use an integer literal instead.") #endif @inlinable public init(stringLiteral source: StringLiteralType) { @@ -29,7 +62,7 @@ extension NBKDoubleWidth { } } - #if swift(>=5.8) && SBI + #if SBI && swift(>=5.8) @available(swift, deprecated: 5.8, message: "Use an integer literal instead.") #endif @inlinable init?(exactlyStringLiteral source: StringLiteralType) { @@ -46,52 +79,3 @@ extension NBKDoubleWidth { if let value { self = value } else { return nil } } } - -//=----------------------------------------------------------------------------= -// MARK: + Version ≥ iOS 16.4, macOS 13.3 -//=----------------------------------------------------------------------------= -#if swift(>=5.8) && SBI - -extension NBKDoubleWidth { - - //=-------------------------------------------------------------------------= - // MARK: Details x Integer Literal Type - //=-------------------------------------------------------------------------= - - @inlinable public init(integerLiteral source: StaticBigInt) { - if let value = Self(exactlyIntegerLiteral: source) { self = value } else { - preconditionFailure("\(Self.description) cannot represent \(source)") - } - } - - @inlinable init?(exactlyIntegerLiteral source: StaticBigInt) { - guard Self.isSigned - ? source.bitWidth <= Self.bitWidth - : source.bitWidth <= Self.bitWidth + 1 && source.signum() >= 0 - else { return nil } - - self = Self.uninitialized { value in - for index in value.indices { - value[unchecked: index] = source[index] - } - } - } -} - -#else -//=----------------------------------------------------------------------------= -// MARK: + Version < iOS 16.4, macOS 13.3 -//=----------------------------------------------------------------------------= - -extension NBKDoubleWidth { - - //=------------------------------------------------------------------------= - // MARK: Initializers x Integer Literal Type - //=------------------------------------------------------------------------= - - @inlinable public init(integerLiteral source: Int64) { - self.init(source) - } -} - -#endif diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Logic.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Logic.swift index 01c0a13b..aee1cae0 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Logic.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Logic.swift @@ -13,6 +13,9 @@ import NBKCoreKit // MARK: * NBK x Double Width x Logic //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Multiplication+Digit.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Multiplication+Digit.swift index 9375d72c..4cd3f664 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Multiplication+Digit.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Multiplication+Digit.swift @@ -13,6 +13,9 @@ import NBKCoreKit // MARK: * NBK x Double Width x Multiplication x Digit //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= @@ -72,6 +75,9 @@ extension NBKDoubleWidth { // MARK: * NBK x Double Width x Multiplication x Digit x Unsigned //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif extension NBKDoubleWidth where High == High.Magnitude { //=------------------------------------------------------------------------= diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Multiplication.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Multiplication.swift index dc2f4e64..8b1d1fc8 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Multiplication.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Multiplication.swift @@ -13,6 +13,9 @@ import NBKCoreKit // MARK: * NBK x Double Width x Multiplication //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= @@ -72,6 +75,9 @@ extension NBKDoubleWidth { // MARK: + Unsigned //=----------------------------------------------------------------------------= +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif extension NBKDoubleWidth where High == High.Magnitude { //=------------------------------------------------------------------------= diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Numbers.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Numbers.swift index 992f86cc..ee1d5334 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Numbers.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Numbers.swift @@ -13,6 +13,9 @@ import NBKCoreKit // MARK: * NBK x Double Width x Numbers //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Rotations.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Rotations.swift index 34102b30..9c3c5aff 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Rotations.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Rotations.swift @@ -13,6 +13,9 @@ import NBKCoreKit // MARK: * NBK x Double Width x Rotations x Left //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= @@ -123,6 +126,9 @@ extension NBKDoubleWidth { // MARK: * NBK x Double Width x Rotations x Right //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Shifts.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Shifts.swift index d758807e..156c4f94 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Shifts.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Shifts.swift @@ -13,6 +13,9 @@ import NBKCoreKit // MARK: * NBK x Double Width x Shifts x Left //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= @@ -134,6 +137,9 @@ extension NBKDoubleWidth { // MARK: * NBK x Double Width x Shifts x Right //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Strides.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Strides.swift index e5c28df3..5879e08d 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Strides.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Strides.swift @@ -13,6 +13,9 @@ import NBKCoreKit // MARK: * NBK x Double Width x Strides //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Subtraction+Digit.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Subtraction+Digit.swift index bacfe5c1..879e6490 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Subtraction+Digit.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Subtraction+Digit.swift @@ -13,6 +13,9 @@ import NBKCoreKit // MARK: * NBK x Double Width x Subtraction x Digit //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Subtraction.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Subtraction.swift index 73871089..ddb7ad92 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Subtraction.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Subtraction.swift @@ -13,6 +13,9 @@ import NBKCoreKit // MARK: * NBK x Double Width x Subtraction //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text.swift index dce1e7d5..e2130664 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text.swift @@ -13,6 +13,9 @@ import NBKCoreKit // MARK: * NBK x Double Width x Text //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= @@ -52,6 +55,9 @@ extension NBKDoubleWidth { // MARK: * NBK x Double Width x Text x Unsigned //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif extension NBKDoubleWidth where High == High.Magnitude { //=------------------------------------------------------------------------= diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Uninitialized.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Uninitialized.swift index 10c1aa09..c6c043fa 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Uninitialized.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Uninitialized.swift @@ -11,6 +11,9 @@ // MARK: * NBK x Double Width x Uninitialized //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words+Pointers.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words+Pointers.swift index da1a8c97..ca559921 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words+Pointers.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words+Pointers.swift @@ -13,6 +13,9 @@ import NBKCoreKit // MARK: * NBK x Double Width x Words x Pointers //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words.swift index 6064f136..d3dad616 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words.swift @@ -13,6 +13,9 @@ import NBKCoreKit // MARK: * NBK x Double Width x Words //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= @@ -43,6 +46,9 @@ extension NBKDoubleWidth { // MARK: + Collection x Indices //=----------------------------------------------------------------------------= +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= @@ -133,6 +139,9 @@ extension NBKDoubleWidth { // MARK: + Collection x Elements //=----------------------------------------------------------------------------= +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= @@ -266,6 +275,9 @@ extension NBKDoubleWidth { // MARK: + Unsigned //=----------------------------------------------------------------------------= +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif extension NBKDoubleWidth where High == High.Magnitude { //=------------------------------------------------------------------------= diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift index 9d546069..c60c1dac 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift @@ -81,6 +81,21 @@ import NBKCoreKit /// /// - Note: The `Digit` type is `Int` when `Self` is signed, and `UInt` otherwise. /// +/// ### Feature: StaticBigInt (v0.10.0+) +/// +/// Because `StaticBigInt` does not back-deploy, it is gated by availability and +/// the compiler flag `SBI`. Setting the constant `withStaticBigInt` to `true` in +/// `Package.swift` enables it. Alternatively, you can use the command line: +/// +/// ``` +/// swift build -Xswiftc -DSBI +/// ``` +/// +/// - Note: You can use `init(stringLiteral:)` until `StaticBigInt` becomes available. +/// +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif @frozen public struct NBKDoubleWidth: ExpressibleByStringLiteral, NBKFixedWidthInteger, MutableCollection, RandomAccessCollection where High: NBKFixedWidthInteger, High.Digit: NBKCoreInteger { @@ -219,7 +234,14 @@ High: NBKFixedWidthInteger, High.Digit: NBKCoreInteger { // MARK: * NBK x Double Width x Conditional Conformances //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif extension NBKDoubleWidth: NBKSignedInteger, SignedInteger, SignedNumeric where High: NBKSignedInteger { } + +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif extension NBKDoubleWidth: NBKUnsignedInteger, UnsignedInteger /*---------*/ where High: NBKUnsignedInteger { } //*============================================================================* @@ -229,17 +251,29 @@ extension NBKDoubleWidth: NBKUnsignedInteger, UnsignedInteger /*---------*/ whe #if arch(i386) || arch(arm) || arch(arm64_32) || arch(wasm32) || arch(powerpc) /// A signed, 128-bit, integer. +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif public typealias Int128 = NBKDoubleWidth> /// An unsigned, 128-bit, integer. +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif public typealias UInt128 = NBKDoubleWidth> #elseif arch(x86_64) || arch(arm64) || arch(powerpc64) || arch(powerpc64le) || arch(s390x) /// A signed, 128-bit, integer. +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif public typealias Int128 = NBKDoubleWidth /// An unsigned, 128-bit, integer. +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif public typealias UInt128 = NBKDoubleWidth #else @@ -253,9 +287,15 @@ public typealias UInt128 = NBKDoubleWidth //*============================================================================* /// A signed, 256-bit, integer. +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif public typealias Int256 = NBKDoubleWidth /// An unsigned, 256-bit, integer. +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif public typealias UInt256 = NBKDoubleWidth //*============================================================================* @@ -263,9 +303,15 @@ public typealias UInt256 = NBKDoubleWidth //*============================================================================* /// A signed, 512-bit, integer. +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif public typealias Int512 = NBKDoubleWidth /// An unsigned, 512-bit, integer. +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif public typealias UInt512 = NBKDoubleWidth //*============================================================================* @@ -273,9 +319,15 @@ public typealias UInt512 = NBKDoubleWidth //*============================================================================* /// A signed, 1024-bit, integer. +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif public typealias Int1024 = NBKDoubleWidth /// An unsigned, 1024-bit, integer. +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif public typealias UInt1024 = NBKDoubleWidth //*============================================================================* @@ -283,9 +335,15 @@ public typealias UInt1024 = NBKDoubleWidth //*============================================================================* /// A signed, 2048-bit, integer. +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif public typealias Int2048 = NBKDoubleWidth /// An unsigned, 2048-bit, integer. +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif public typealias UInt2048 = NBKDoubleWidth //*============================================================================* @@ -293,7 +351,13 @@ public typealias UInt2048 = NBKDoubleWidth //*============================================================================* /// A signed, 4096-bit, integer. +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif public typealias Int4096 = NBKDoubleWidth /// An unsigned, 4096-bit, integer. +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif public typealias UInt4096 = NBKDoubleWidth diff --git a/Sources/Numberick/Documentation.docc/Documentation.md b/Sources/Numberick/Documentation.docc/Documentation.md index d1399473..793ec8b2 100644 --- a/Sources/Numberick/Documentation.docc/Documentation.md +++ b/Sources/Numberick/Documentation.docc/Documentation.md @@ -85,6 +85,18 @@ Int256(5) % Int(5), UInt256(5) % UInt(5) - Note: The `Digit` type is `Int` when `Self` is signed, and `UInt` otherwise. +### Feature: StaticBigInt (v0.10.0+) + +Because `StaticBigInt` does not back-deploy, it is gated by availability and +the compiler flag `SBI`. Setting the constant `withStaticBigInt` to `true` in +`Package.swift` enables it. Alternatively, you can use the command line: + +``` +swift build -Xswiftc -DSBI +``` + +- Note: You can use `init(stringLiteral:)` until `StaticBigInt` becomes available. + ## Topics ### Protocols diff --git a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Addition.swift b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Addition.swift index aef7af16..fe1d6f22 100644 --- a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Addition.swift +++ b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Addition.swift @@ -20,6 +20,9 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Addition x Int256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthBenchmarksOnAdditionAsInt256: XCTestCase { typealias T = Int256 @@ -103,6 +106,9 @@ final class NBKDoubleWidthBenchmarksOnAdditionAsInt256: XCTestCase { // MARK: * NBK x Double Width x Addition x UInt256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthBenchmarksOnAdditionAsUInt256: XCTestCase { typealias T = UInt256 diff --git a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Bits.swift b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Bits.swift index 671b7046..1f0fc4a6 100644 --- a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Bits.swift +++ b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Bits.swift @@ -20,6 +20,9 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Bits x Int256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthBenchmarksOnBitsAsInt256: XCTestCase { typealias T = Int256 @@ -137,6 +140,9 @@ final class NBKDoubleWidthBenchmarksOnBitsAsInt256: XCTestCase { // MARK: * NBK x Double Width x Bits x UInt256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthBenchmarksOnBitsAsUInt256: XCTestCase { typealias T = UInt256 diff --git a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Comparisons.swift b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Comparisons.swift index 65346848..58aa6b62 100644 --- a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Comparisons.swift +++ b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Comparisons.swift @@ -20,6 +20,9 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Comparisons x Int256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthBenchmarksOnComparisonsAsInt256: XCTestCase { typealias T = Int256 @@ -126,6 +129,9 @@ final class NBKDoubleWidthBenchmarksOnComparisonsAsInt256: XCTestCase { // MARK: * NBK x Double Width x Comparisons x UInt256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthBenchmarksOnComparisonsAsUInt256: XCTestCase { typealias T = UInt256 diff --git a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Complements.swift b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Complements.swift index d214d8f9..e8150fcc 100644 --- a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Complements.swift +++ b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Complements.swift @@ -20,6 +20,9 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Complements x Int256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthBenchmarksOnComplementsAsInt256: XCTestCase { typealias T = Int256 @@ -167,6 +170,9 @@ final class NBKDoubleWidthBenchmarksOnComplementsAsInt256: XCTestCase { // MARK: * NBK x Double Width x Complements x UInt256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthBenchmarksOnComplementsAsUInt256: XCTestCase { typealias T = UInt256 diff --git a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Division.swift b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Division.swift index 850faacb..95f0f2a9 100644 --- a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Division.swift +++ b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Division.swift @@ -20,6 +20,9 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Division x Int256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthBenchmarksOnDivisionAsInt256: XCTestCase { typealias T = Int256 @@ -130,6 +133,9 @@ final class NBKDoubleWidthBenchmarksOnDivisionAsInt256: XCTestCase { // MARK: * NBK x Double Width x Division x UInt256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthBenchmarksOnDivisionAsUInt256: XCTestCase { typealias T = UInt256 diff --git a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Endianness.swift b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Endianness.swift index 32af8219..433f5f9b 100644 --- a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Endianness.swift +++ b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Endianness.swift @@ -20,6 +20,9 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Endianness x Int256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthBenchmarksOnEndiannessAsInt256: XCTestCase { typealias T = Int256 @@ -60,6 +63,9 @@ final class NBKDoubleWidthBenchmarksOnEndiannessAsInt256: XCTestCase { // MARK: * NBK x Double Width x Endianness x UInt256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthBenchmarksOnEndiannessAsUInt256: XCTestCase { typealias T = UInt256 diff --git a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Logic.swift b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Logic.swift index c2dd923d..afa30e0a 100644 --- a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Logic.swift +++ b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Logic.swift @@ -20,6 +20,9 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Logic x Int256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthBenchmarksOnLogicAsInt256: XCTestCase { typealias T = Int256 @@ -75,6 +78,9 @@ final class NBKDoubleWidthBenchmarksOnLogicAsInt256: XCTestCase { // MARK: * NBK x Double Width x Logic x UInt256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthBenchmarksOnLogicAsUInt256: XCTestCase { typealias T = UInt256 diff --git a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Multiplication.swift b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Multiplication.swift index 1aaa1229..1c5db3ee 100644 --- a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Multiplication.swift +++ b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Multiplication.swift @@ -20,6 +20,9 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Multiplication x Int256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthBenchmarksOnMultiplicationAsInt256: XCTestCase { typealias T = Int256 @@ -125,6 +128,9 @@ final class NBKDoubleWidthBenchmarksOnMultiplicationAsInt256: XCTestCase { // MARK: * NBK x Double Width x Multiplication x UInt256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthBenchmarksOnMultiplicationAsUInt256: XCTestCase { typealias T = UInt256 diff --git a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Numbers.swift b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Numbers.swift index 0833e3e8..4755f704 100644 --- a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Numbers.swift +++ b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Numbers.swift @@ -20,6 +20,9 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Numbers x Int256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthBenchmarksOnNumbersAsInt256: XCTestCase { typealias S = Int256 @@ -429,6 +432,9 @@ final class NBKDoubleWidthBenchmarksOnNumbersAsInt256: XCTestCase { // MARK: * NBK x Double Width x Numbers x UInt256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthBenchmarksOnNumbersAsUInt256: XCTestCase { typealias S = Int256 diff --git a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Random.swift b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Random.swift index 5cffc07a..4385125d 100644 --- a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Random.swift +++ b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Random.swift @@ -20,6 +20,9 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Random x Int256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthBenchmarksOnRandomAsInt256: XCTestCase { typealias T = Int256 @@ -44,6 +47,9 @@ final class NBKDoubleWidthBenchmarksOnRandomAsInt256: XCTestCase { // MARK: * NBK x Double Width x Random x UInt256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthBenchmarksOnRandomAsUInt256: XCTestCase { typealias T = UInt256 diff --git a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Rotations.swift b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Rotations.swift index 3ac6b74b..9e0d04b7 100644 --- a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Rotations.swift +++ b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Rotations.swift @@ -20,6 +20,9 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Rotations x Int256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthBenchmarksOnRotationsAsInt256: XCTestCase { typealias T = Int256 @@ -103,6 +106,9 @@ final class NBKDoubleWidthBenchmarksOnRotationsAsInt256: XCTestCase { // MARK: * NBK x Double Width x Rotations x UInt256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthBenchmarksOnRotationsAsUInt256: XCTestCase { typealias T = UInt256 diff --git a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Shifts.swift b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Shifts.swift index 78e4b4bb..c5e8a194 100644 --- a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Shifts.swift +++ b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Shifts.swift @@ -20,6 +20,9 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Shifts x Int256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthBenchmarksOnShiftsAsInt256: XCTestCase { typealias T = Int256 @@ -125,6 +128,9 @@ final class NBKDoubleWidthBenchmarksOnShiftsAsInt256: XCTestCase { // MARK: * NBK x Double Width x Shifts x UInt256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthBenchmarksOnShiftsAsUInt256: XCTestCase { typealias T = UInt256 diff --git a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Strides.swift b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Strides.swift index 8312d640..42c0fe32 100644 --- a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Strides.swift +++ b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Strides.swift @@ -20,6 +20,9 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Strides x Int256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthBenchmarksOnStridesAsInt256: XCTestCase { typealias T = Int256 @@ -55,6 +58,9 @@ final class NBKDoubleWidthBenchmarksOnStridesAsInt256: XCTestCase { // MARK: * NBK x Double Width x Strides x UInt256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthBenchmarksOnStridesAsUInt256: XCTestCase { typealias T = UInt256 diff --git a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Subtraction.swift b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Subtraction.swift index 130b19d2..f7503bbc 100644 --- a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Subtraction.swift +++ b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Subtraction.swift @@ -20,6 +20,9 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Subtraction x Int256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthBenchmarksOnSubtractionAsInt256: XCTestCase { typealias T = Int256 @@ -103,6 +106,9 @@ final class NBKDoubleWidthBenchmarksOnSubtractionAsInt256: XCTestCase { // MARK: * NBK x Double Width x Subtraction x UInt256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthBenchmarksOnSubtractionAsUInt256: XCTestCase { typealias T = UInt256 diff --git a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Text.swift b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Text.swift index f770f8d1..ca0c8d5d 100644 --- a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Text.swift +++ b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Text.swift @@ -20,6 +20,9 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Text x Int256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthBenchmarksOnTextAsInt256: XCTestCase { typealias T = Int256 @@ -132,6 +135,9 @@ final class NBKDoubleWidthBenchmarksOnTextAsInt256: XCTestCase { // MARK: * NBK x Double Width x Text x UInt256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthBenchmarksOnTextAsUInt256: XCTestCase { typealias T = UInt256 diff --git a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth.swift b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth.swift index 8951c8e9..77ff9efa 100644 --- a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth.swift +++ b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth.swift @@ -20,6 +20,9 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Int256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthBenchmarksAsInt256: XCTestCase { typealias T = Int256 @@ -47,6 +50,9 @@ final class NBKDoubleWidthBenchmarksAsInt256: XCTestCase { // MARK: * NBK x Double Width x UInt256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthBenchmarksAsUInt256: XCTestCase { typealias T = UInt256 @@ -74,6 +80,9 @@ final class NBKDoubleWidthBenchmarksAsUInt256: XCTestCase { // MARK: * NBK x Double Width x Initializers //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= diff --git a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Addition.swift b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Addition.swift index 3208215d..2f7644ee 100644 --- a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Addition.swift +++ b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Addition.swift @@ -20,6 +20,9 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Addition x Int256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthTestsOnAdditionAsInt256: XCTestCase { typealias T = Int256 @@ -140,6 +143,9 @@ final class NBKDoubleWidthTestsOnAdditionAsInt256: XCTestCase { // MARK: * NBK x Double Width x Addition x UInt256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthTestsOnAdditionAsUInt256: XCTestCase { typealias T = UInt256 @@ -217,6 +223,9 @@ final class NBKDoubleWidthTestsOnAdditionAsUInt256: XCTestCase { // MARK: * NBK x Double Width x Addition x Assertions //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif private func NBKAssertAddition( _ lhs: NBKDoubleWidth, _ rhs: NBKDoubleWidth, _ partialValue: NBKDoubleWidth, _ overflow: Bool = false, @@ -237,6 +246,9 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual({ var x = lhs; let o = x.addReportingOverflow(rhs); return o }(), overflow, file: file, line: line) } +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif private func NBKAssertAdditionByDigit( _ lhs: NBKDoubleWidth, _ rhs: NBKDoubleWidth.Digit, _ partialValue: NBKDoubleWidth, _ overflow: Bool = false, diff --git a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Bits.swift b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Bits.swift index bdb64959..f21a2bee 100644 --- a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Bits.swift +++ b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Bits.swift @@ -20,6 +20,9 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Bits x Int256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthTestsOnBitsAsInt256: XCTestCase { typealias T = Int256 @@ -94,6 +97,9 @@ final class NBKDoubleWidthTestsOnBitsAsInt256: XCTestCase { // MARK: * NBK x Double Width x Bits x UInt256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthTestsOnBitsAsUInt256: XCTestCase { typealias T = UInt256 diff --git a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Comparisons.swift b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Comparisons.swift index 4a616b85..6cfed07b 100644 --- a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Comparisons.swift +++ b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Comparisons.swift @@ -20,6 +20,9 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Comparisons x Int256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthTestsOnComparisonsAsInt256: XCTestCase { typealias T = Int256 @@ -218,6 +221,9 @@ final class NBKDoubleWidthTestsOnComparisonsAsInt256: XCTestCase { // MARK: * NBK x Double Width x Comparisons x UInt256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthTestsOnComparisonsAsUInt256: XCTestCase { typealias T = UInt256 @@ -378,6 +384,9 @@ final class NBKDoubleWidthTestsOnComparisonsAsUInt256: XCTestCase { // MARK: * NBK x Double Width x Comparisons x Assertions //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif private func NBKAssertSignum( _ operand: NBKDoubleWidth, _ signum: Int, file: StaticString = #file, line: UInt = #line) { @@ -387,6 +396,9 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual(Int(operand.signum() as T ), signum, file: file, line: line) // stdlib } +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif private func NBKAssertComparisons( _ lhs: NBKDoubleWidth, _ rhs: NBKDoubleWidth, _ signum: Int, file: StaticString = #file, line: UInt = #line) { @@ -402,6 +414,9 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual(lhs.compared(to: rhs), signum, file: file, line: line) } +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif private func NBKAssertComparisonsByDigit( _ lhs: NBKDoubleWidth, _ rhs: NBKDoubleWidth.Digit, _ signum: Int, file: StaticString = #file, line: UInt = #line) { diff --git a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Complements.swift b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Complements.swift index 7e567a38..a10bc69a 100644 --- a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Complements.swift +++ b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Complements.swift @@ -20,6 +20,9 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Complements x Int256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthTestsOnComplementsAsInt256: XCTestCase { typealias T = Int256 @@ -101,6 +104,9 @@ final class NBKDoubleWidthTestsOnComplementsAsInt256: XCTestCase { // MARK: * NBK x Double Width x Complements x UInt256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthTestsOnComplementsAsUInt256: XCTestCase { typealias T = UInt256 @@ -161,6 +167,9 @@ final class NBKDoubleWidthTestsOnComplementsAsUInt256: XCTestCase { // MARK: * NBK x Double Width x Complements x Assertions //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif private func NBKAssertBitPattern( _ integer: NBKDoubleWidth, _ bitPattern: NBKDoubleWidth.BitPattern, file: StaticString = #file, line: UInt = #line) { @@ -173,6 +182,9 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual(B(bitPattern: integer), bitPattern, file: file, line: line) } +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif private func NBKAssertBitPattern( _ integer: T, _ bitPattern: T.BitPattern, file: StaticString = #file, line: UInt = #line) where T.BitPattern: Equatable { @@ -182,6 +194,9 @@ file: StaticString = #file, line: UInt = #line) where T.BitPattern: Equatable { XCTAssertEqual(T.BitPattern(bitPattern: integer), bitPattern, file: file, line: line) } +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif private func NBKAssertOnesComplement( _ integer: NBKDoubleWidth, _ result: NBKDoubleWidth, file: StaticString = #file, line: UInt = #line) { @@ -192,6 +207,9 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual({ var x = integer; let _ = x.formTwosComplementSubsequence(false); return x }(), result, file: file, line: line) } +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif private func NBKAssertTwosComplement( _ integer: NBKDoubleWidth, _ partialValue: NBKDoubleWidth, _ overflow: Bool = false, file: StaticString = #file, line: UInt = #line) { @@ -208,6 +226,9 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual({ var x = integer; let o = x.formTwosComplementSubsequence(true ); return o }(), overflow, file: file, line: line) } +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif private func NBKAssertAdditiveInverse( _ operand: NBKDoubleWidth, _ partialValue: NBKDoubleWidth, _ overflow: Bool = false, file: StaticString = #file, line: UInt = #line) { diff --git a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Division.swift b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Division.swift index 6ce50303..7a42a055 100644 --- a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Division.swift +++ b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Division.swift @@ -20,6 +20,9 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Division x Int256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthTestsOnDivisionAsInt256: XCTestCase { typealias T = Int256 @@ -223,6 +226,9 @@ final class NBKDoubleWidthTestsOnDivisionAsInt256: XCTestCase { // MARK: * NBK x Double Width x Division x UInt256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthTestsOnDivisionAsUInt256: XCTestCase { typealias T = UInt256 @@ -376,6 +382,9 @@ final class NBKDoubleWidthTestsOnDivisionAsUInt256: XCTestCase { // MARK: * NBK x Double Width x Division x UInt256 x Code Coverage //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthTestsOnDivisionAsUInt256CodeCoverage: XCTestCase { typealias T = UInt256 @@ -404,6 +413,9 @@ final class NBKDoubleWidthTestsOnDivisionAsUInt256CodeCoverage: XCTestCase { // MARK: * NBK x Double Width x Division x Assertions //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif private func NBKAssertDivision( _ lhs: NBKDoubleWidth, _ rhs: NBKDoubleWidth, _ quotient: NBKDoubleWidth, _ remainder: NBKDoubleWidth, _ overflow: Bool = false, @@ -441,6 +453,9 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual(lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs).overflow, overflow, file: file, line: line) } +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif private func NBKAssertDivisionByDigit( _ lhs: NBKDoubleWidth, _ rhs: NBKDoubleWidth.Digit, _ quotient: NBKDoubleWidth, _ remainder: NBKDoubleWidth.Digit, _ overflow: Bool = false, @@ -483,6 +498,9 @@ file: StaticString = #file, line: UInt = #line) { // MARK: + Full Width //=----------------------------------------------------------------------------= +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif private func NBKAssertDivisionFullWidth( _ lhs: HL, NBKDoubleWidth.Magnitude>, _ rhs: NBKDoubleWidth, _ quotient: NBKDoubleWidth, _ remainder: NBKDoubleWidth, _ overflow: Bool = false, diff --git a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Endianness.swift b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Endianness.swift index caa415b3..2b6d5296 100644 --- a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Endianness.swift +++ b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Endianness.swift @@ -20,6 +20,9 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Endianness x Int256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthTestsOnEndiannessAsInt256: XCTestCase { typealias T = Int256 @@ -66,6 +69,9 @@ final class NBKDoubleWidthTestsOnEndiannessAsInt256: XCTestCase { // MARK: * NBK x Double Width x Endianness x UInt256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthTestsOnEndiannessAsUInt256: XCTestCase { typealias T = UInt256 diff --git a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Literals.swift b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Literals.swift index 689f8326..df68f5f1 100644 --- a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Literals.swift +++ b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Literals.swift @@ -20,6 +20,9 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Literals x Int256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthTestsOnLiteralsAsInt256: XCTestCase { typealias T = Int256 @@ -29,7 +32,7 @@ final class NBKDoubleWidthTestsOnLiteralsAsInt256: XCTestCase { //=------------------------------------------------------------------------= func testFromIntegerLiteral() { - #if swift(>=5.8) && SBI + #if SBI && swift(>=5.8) XCTAssertEqual(T(x64: X( 0, 0, 0, 0)), 0x0000000000000000000000000000000000000000000000000000000000000000) XCTAssertEqual(T(x64: X(~0, 0, 0, 0)), 0x000000000000000000000000000000000000000000000000ffffffffffffffff) XCTAssertEqual(T(x64: X(~0, ~0, 0, 0)), 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) @@ -51,7 +54,7 @@ final class NBKDoubleWidthTestsOnLiteralsAsInt256: XCTestCase { #endif } - #if swift(>=5.8) && SBI + #if SBI && swift(>=5.8) @available(swift, deprecated: 5.8, message: "Use an integer literal instead.") #endif func testFromStringLiteral() { @@ -75,6 +78,9 @@ final class NBKDoubleWidthTestsOnLiteralsAsInt256: XCTestCase { // MARK: * NBK x Double Width x Literals x UInt256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthTestsOnLiteralsAsUInt256: XCTestCase { typealias T = UInt256 @@ -84,7 +90,7 @@ final class NBKDoubleWidthTestsOnLiteralsAsUInt256: XCTestCase { //=------------------------------------------------------------------------= func testFromIntegerLiteral() { - #if swift(>=5.8) && SBI + #if SBI && swift(>=5.8) XCTAssertEqual(T(x64: X( 0, 0, 0, 0)), 0x0000000000000000000000000000000000000000000000000000000000000000) XCTAssertEqual(T(x64: X(~0, 0, 0, 0)), 0x000000000000000000000000000000000000000000000000ffffffffffffffff) XCTAssertEqual(T(x64: X(~0, ~0, 0, 0)), 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) @@ -106,7 +112,7 @@ final class NBKDoubleWidthTestsOnLiteralsAsUInt256: XCTestCase { #endif } - #if swift(>=5.8) && SBI + #if SBI && swift(>=5.8) @available(swift, deprecated: 5.8, message: "Use an integer literal instead.") #endif func testFromStringLiteral() { diff --git a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Logic.swift b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Logic.swift index 9d896a82..7de05765 100644 --- a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Logic.swift +++ b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Logic.swift @@ -20,6 +20,9 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Logic x Int256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthTestsOnLogicAsInt256: XCTestCase { typealias T = Int256 @@ -71,6 +74,9 @@ final class NBKDoubleWidthTestsOnLogicAsInt256: XCTestCase { // MARK: * NBK x Double Width x Logic x UInt256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthTestsOnLogicAsUInt256: XCTestCase { typealias T = UInt256 @@ -122,6 +128,9 @@ final class NBKDoubleWidthTestsOnLogicAsUInt256: XCTestCase { // MARK: * NBK x Double Width x Logic x Assertions //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif private func NBKAssertNot( _ operand: NBKDoubleWidth, _ result: NBKDoubleWidth, file: StaticString = #file, line: UInt = #line) { @@ -135,6 +144,9 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual({ var x = result; x.formOnesComplement(); return x }(), operand, file: file, line: line) } +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif private func NBKAssertAnd( _ lhs: NBKDoubleWidth, _ rhs: NBKDoubleWidth, _ result: NBKDoubleWidth, file: StaticString = #file, line: UInt = #line) { @@ -144,6 +156,9 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual({ var rhs = rhs; rhs &= lhs; return rhs }(), result, file: file, line: line) } +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif private func NBKAssertOr( _ lhs: NBKDoubleWidth, _ rhs: NBKDoubleWidth, _ result: NBKDoubleWidth, file: StaticString = #file, line: UInt = #line) { @@ -153,6 +168,9 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual({ var rhs = rhs; rhs |= lhs; return rhs }(), result, file: file, line: line) } +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif private func NBKAssertXor( _ lhs: NBKDoubleWidth, _ rhs: NBKDoubleWidth, _ result: NBKDoubleWidth, file: StaticString = #file, line: UInt = #line) { diff --git a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Multiplication.swift b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Multiplication.swift index 415b9050..f6107870 100644 --- a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Multiplication.swift +++ b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Multiplication.swift @@ -20,6 +20,9 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Multiplication x Int256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthTestsOnMultiplicationAsInt256: XCTestCase { typealias T = Int256 @@ -154,6 +157,9 @@ final class NBKDoubleWidthTestsOnMultiplicationAsInt256: XCTestCase { // MARK: * NBK x Double Width x Multiplication x UInt256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthTestsOnMultiplicationAsUInt256: XCTestCase { typealias T = UInt256 @@ -246,6 +252,9 @@ final class NBKDoubleWidthTestsOnMultiplicationAsUInt256: XCTestCase { // MARK: * NBK x Double Width x Multiplication x Assertions //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif private func NBKAssertMultiplication( _ lhs: NBKDoubleWidth, _ rhs: NBKDoubleWidth, _ low: NBKDoubleWidth, _ high: NBKDoubleWidth? = nil, _ overflow: Bool = false, @@ -275,6 +284,9 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual({ var x = lhs; let o = x.multiplyFullWidth(by: rhs); return o }(), high, file: file, line: line) } +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif private func NBKAssertMultiplicationByDigit( _ lhs: NBKDoubleWidth, _ rhs: NBKDoubleWidth.Digit, _ low: NBKDoubleWidth, _ high: NBKDoubleWidth.Digit? = nil, _ overflow: Bool = false, @@ -304,6 +316,9 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual({ var x = lhs; let o = x.multiplyFullWidth(by: rhs); return o }(), high, file: file, line: line) } +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif private func NBKAssertMultiplicationByDigitWithAddition( _ lhs: NBKDoubleWidth, _ rhs: UInt, _ carry: UInt, _ low: NBKDoubleWidth, _ high: UInt, _ overflow: Bool = false, diff --git a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Numbers.swift b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Numbers.swift index 8c7246c5..639bd071 100644 --- a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Numbers.swift +++ b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Numbers.swift @@ -20,6 +20,9 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Numbers x Int256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthTestsOnNumbersAsInt256: XCTestCase { typealias S = Int256 @@ -278,6 +281,9 @@ final class NBKDoubleWidthTestsOnNumbersAsInt256: XCTestCase { // MARK: * NBK x Double Width x Numbers x UInt256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthTestsOnNumbersAsUInt256: XCTestCase { typealias S = Int256 @@ -521,30 +527,45 @@ final class NBKDoubleWidthTestsOnNumbersAsUInt256: XCTestCase { // MARK: * NBK x Double Width x Numbers x Assertions //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif 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) } +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif 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) } +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif 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) } +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif 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) } +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif private func NBKAssertNumbers( from value: I, exactly: O?, clamping: O, truncating: O, file: StaticString = #file, line: UInt = #line) { diff --git a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Rotations.swift b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Rotations.swift index 2f79641e..bf49c48a 100644 --- a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Rotations.swift +++ b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Rotations.swift @@ -20,6 +20,9 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Rotations x Int256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthTestsOnRotationsAsInt256: XCTestCase { typealias T = Int256 @@ -93,6 +96,9 @@ final class NBKDoubleWidthTestsOnRotationsAsInt256: XCTestCase { // MARK: * NBK x Double Width x Rotations x UInt256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthTestsOnRotationsAsUInt256: XCTestCase { typealias T = UInt256 @@ -166,6 +172,9 @@ final class NBKDoubleWidthTestsOnRotationsAsUInt256: XCTestCase { // MARK: * NBK x Double Width x Rotations x Assertions //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif private func NBKAssertRotateLeft( _ lhs: NBKDoubleWidth, _ rhs: Int, _ result: NBKDoubleWidth, file: StaticString = #file, line: UInt = #line) { @@ -188,6 +197,9 @@ file: StaticString = #file, line: UInt = #line) { } } +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif private func NBKAssertRotateRight( _ lhs: NBKDoubleWidth, _ rhs: Int, _ result: NBKDoubleWidth, file: StaticString = #file, line: UInt = #line) { diff --git a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Shifts.swift b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Shifts.swift index 001d12ca..ca3f815f 100644 --- a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Shifts.swift +++ b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Shifts.swift @@ -20,6 +20,9 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Shifts x Int256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthTestsOnShiftsAsInt256: XCTestCase { typealias S = Int256 @@ -143,6 +146,9 @@ final class NBKDoubleWidthTestsOnShiftsAsInt256: XCTestCase { // MARK: * NBK x Double Width x Shifts x UInt256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthTestsOnShiftsAsUInt256: XCTestCase { typealias S = Int256 @@ -266,6 +272,9 @@ final class NBKDoubleWidthTestsOnShiftsAsUInt256: XCTestCase { // MARK: * NBK x Double Width x Shifts x Assertions //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif private func NBKAssertShiftLeft( _ lhs: NBKDoubleWidth, _ rhs: Int, _ result: NBKDoubleWidth, file: StaticString = #file, line: UInt = #line) { @@ -303,6 +312,9 @@ file: StaticString = #file, line: UInt = #line) { } } +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif private func NBKAssertShiftRight( _ lhs: NBKDoubleWidth, _ rhs: Int, _ result: NBKDoubleWidth, file: StaticString = #file, line: UInt = #line) { @@ -344,6 +356,9 @@ file: StaticString = #file, line: UInt = #line) { // MARK: + Masking //=----------------------------------------------------------------------------= +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif private func NBKAssertShiftLeftByMasking( _ lhs: NBKDoubleWidth, _ rhs: Int, _ result: NBKDoubleWidth, signitude: S.Type, file: StaticString = #file, line: UInt = #line) where S.Digit: NBKCoreInteger { @@ -383,6 +398,9 @@ file: StaticString = #file, line: UInt = #line) where S.Digit: NBKCoreInteger=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif private func NBKAssertShiftRightByMasking( _ lhs: NBKDoubleWidth, _ rhs: Int, _ result: NBKDoubleWidth, signitude: S.Type, file: StaticString = #file, line: UInt = #line) where S.Digit: NBKCoreInteger { diff --git a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Strides.swift b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Strides.swift index 812c386d..2046dd0c 100644 --- a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Strides.swift +++ b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Strides.swift @@ -20,6 +20,9 @@ private typealias Y = [UInt64] // MARK: * NBK x Double Width x Strides x Int256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthTestsOnStridesAsInt256: XCTestCase { typealias T = Int256 @@ -51,6 +54,9 @@ final class NBKDoubleWidthTestsOnStridesAsInt256: XCTestCase { // MARK: * NBK x Double Width x Strides x UInt256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthTestsOnStridesAsUInt256: XCTestCase { typealias T = UInt256 diff --git a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Subtraction.swift b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Subtraction.swift index 6cf226f1..9b730a74 100644 --- a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Subtraction.swift +++ b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Subtraction.swift @@ -20,6 +20,9 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Subtraction x Int256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthTestsOnSubtractionAsInt256: XCTestCase { typealias T = Int256 @@ -140,6 +143,9 @@ final class NBKDoubleWidthTestsOnSubtractionAsInt256: XCTestCase { // MARK: * NBK x Double Width x Subtraction x UInt256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthTestsOnSubtractionAsUInt256: XCTestCase { typealias T = UInt256 @@ -211,6 +217,9 @@ final class NBKDoubleWidthTestsOnSubtractionAsUInt256: XCTestCase { // MARK: * NBK x Double Width x Subtraction x Assertions //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif private func NBKAssertSubtraction( _ lhs: NBKDoubleWidth, _ rhs: NBKDoubleWidth, _ partialValue: NBKDoubleWidth, _ overflow: Bool = false, @@ -231,6 +240,9 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual({ var x = lhs; let o = x.subtractReportingOverflow(rhs); return o }(), overflow, file: file, line: line) } +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif private func NBKAssertSubtractionByDigit( _ lhs: NBKDoubleWidth, _ rhs: NBKDoubleWidth.Digit, _ partialValue: NBKDoubleWidth, _ overflow: Bool = false, diff --git a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Text.swift b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Text.swift index 4806f3f8..d1869e5d 100644 --- a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Text.swift +++ b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Text.swift @@ -20,6 +20,9 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Text x Int256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthTestsOnTextAsInt256: XCTestCase { typealias T = Int256 @@ -258,6 +261,9 @@ final class NBKDoubleWidthTestsOnTextAsInt256: XCTestCase { // MARK: * NBK x Double Width x Text x UInt256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthTestsOnTextAsUInt256: XCTestCase { typealias T = UInt256 @@ -476,6 +482,9 @@ final class NBKDoubleWidthTestsOnTextAsUInt256: XCTestCase { // MARK: * NBK x Double Width x Text x Assertions //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif private func NBKAssertFromDescription( _ integer: NBKDoubleWidth?, _ description: String, file: StaticString = #file, line: UInt = #line) { @@ -485,6 +494,9 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual(T(description, radix: 10), integer, file: file, line: line) } +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif private func NBKAssertDecodeText( _ integer: NBKDoubleWidth?, _ radix: Int, _ text: String, file: StaticString = #file, line: UInt = #line) { @@ -497,6 +509,9 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual(T(text, radix: radix), integer, file: file, line: line) } +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif private func NBKAssertEncodeText( _ integer: NBKDoubleWidth, _ radix: Int, _ uppercase: Bool, _ text: String, file: StaticString = #file, line: UInt = #line) { diff --git a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Words.swift b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Words.swift index b438f783..30b8ca29 100644 --- a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Words.swift +++ b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Words.swift @@ -20,6 +20,9 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Words x Int256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthTestsOnWordsAsInt256: XCTestCase { typealias T = Int256 @@ -99,6 +102,9 @@ final class NBKDoubleWidthTestsOnWordsAsInt256: XCTestCase { // MARK: * NBK x Double Width x Words x UInt256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthTestsOnWordsAsUInt256: XCTestCase { typealias T = UInt256 @@ -178,6 +184,9 @@ final class NBKDoubleWidthTestsOnWordsAsUInt256: XCTestCase { // MARK: * NBK x Double Width x Words x Assertions //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif private func NBKAssertWords( _ integer: NBKDoubleWidth, _ words: [UInt], file: StaticString = #file, line: UInt = #line) { @@ -204,6 +213,9 @@ file: StaticString = #file, line: UInt = #line) { // MARK: + Indices //=----------------------------------------------------------------------------= +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif private func NBKAssertIndexOffsetByLimitedBy( _ integer: NBKDoubleWidth, _ index: Int, _ distance: Int, _ limit: Int, _ expectation: Int?, file: StaticString = #file, line: UInt = #line) { @@ -218,6 +230,9 @@ file: StaticString = #file, line: UInt = #line) { // MARK: + Elements x First, Last, Tail //=----------------------------------------------------------------------------= +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif private func NBKAssertFirstLastTail( _ integer: NBKDoubleWidth, first: UInt, last: UInt, tail: H.Digit, file: StaticString = #file, line: UInt = #line) { diff --git a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth.swift b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth.swift index 4cf97474..d77291d4 100644 --- a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth.swift +++ b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth.swift @@ -18,6 +18,9 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthTests: XCTestCase { typealias T = any NBKFixedWidthInteger.Type @@ -59,6 +62,9 @@ final class NBKDoubleWidthTests: XCTestCase { // MARK: * NBK x Double Width x Int256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthTestsAsInt256: XCTestCase { typealias T = Int256 @@ -102,6 +108,9 @@ final class NBKDoubleWidthTestsAsInt256: XCTestCase { // MARK: * NBK x Double Width x UInt256 //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif final class NBKDoubleWidthTestsAsUInt256: XCTestCase { typealias T = UInt256 @@ -145,6 +154,9 @@ final class NBKDoubleWidthTestsAsUInt256: XCTestCase { // MARK: * NBK x Double Width x Assertions //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif private func NBKAssertHalvesGetSetInit( _ value: NBKDoubleWidth, _ low: H.Magnitude, _ high: H, file: StaticString = #file, line: UInt = #line) { @@ -182,6 +194,9 @@ file: StaticString = #file, line: UInt = #line) { // MARK: * NBK x Double Width x Initializers //*============================================================================* +#if SBI && swift(>=5.8) +@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) +#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= From b761a97130b76c5f0e30da21f29e47e10494e0c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Fri, 18 Aug 2023 13:58:21 +0200 Subject: [PATCH 033/111] [NBKDoubleWidthKit] StaticString (#62). --- README.md | 2 +- Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift | 8 +++----- Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift | 2 +- Sources/Numberick/Documentation.docc/Documentation.md | 2 +- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 1983eadb..bcfefe27 100644 --- a/README.md +++ b/README.md @@ -101,7 +101,7 @@ you can use the command line: swift build -Xswiftc -DSBI ``` -> **Note**: You can use `init(stringLiteral:)` until `StaticBigInt` becomes available. +> **Note**: You can use `StaticString` until `StaticBigInt` becomes available. ## Acknowledgements diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift index fcd6f266..d5563145 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift @@ -56,7 +56,7 @@ extension NBKDoubleWidth { #if SBI && swift(>=5.8) @available(swift, deprecated: 5.8, message: "Use an integer literal instead.") #endif - @inlinable public init(stringLiteral source: StringLiteralType) { + @inlinable public init(stringLiteral source: StaticString) { if let value = Self(exactlyStringLiteral: source) { self = value } else { preconditionFailure("\(Self.description) cannot represent \(source)") } @@ -65,10 +65,8 @@ extension NBKDoubleWidth { #if SBI && swift(>=5.8) @available(swift, deprecated: 5.8, message: "Use an integer literal instead.") #endif - @inlinable init?(exactlyStringLiteral source: StringLiteralType) { - var source = source - - let value: Optional = source.withUTF8 { utf8 in + @inlinable init?(exactlyStringLiteral source: StaticString) { + let value: Optional = source.withUTF8Buffer { utf8 in let components = NBK.makeIntegerComponentsByDecodingRadix(utf8: utf8) let radix = NBK.AnyRadixUIntRoot(components.radix) let digits = NBK.UnsafeUTF8(rebasing: components.body) diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift index c60c1dac..35bdd794 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift @@ -91,7 +91,7 @@ import NBKCoreKit /// swift build -Xswiftc -DSBI /// ``` /// -/// - Note: You can use `init(stringLiteral:)` until `StaticBigInt` becomes available. +/// - Note: You can use `StaticString` until `StaticBigInt` becomes available. /// #if SBI && swift(>=5.8) @available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) diff --git a/Sources/Numberick/Documentation.docc/Documentation.md b/Sources/Numberick/Documentation.docc/Documentation.md index 793ec8b2..a55744d2 100644 --- a/Sources/Numberick/Documentation.docc/Documentation.md +++ b/Sources/Numberick/Documentation.docc/Documentation.md @@ -95,7 +95,7 @@ the compiler flag `SBI`. Setting the constant `withStaticBigInt` to `true` in swift build -Xswiftc -DSBI ``` -- Note: You can use `init(stringLiteral:)` until `StaticBigInt` becomes available. +- Note: You can use `StaticString` until `StaticBigInt` becomes available. ## Topics From 97f9a6bf64d312b6845fbb7368119c08d28cd725 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sat, 19 Aug 2023 07:15:55 +0200 Subject: [PATCH 034/111] Tests on Linux (#60). --- .github/workflows/tests-on-linux.yml | 31 ++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 .github/workflows/tests-on-linux.yml diff --git a/.github/workflows/tests-on-linux.yml b/.github/workflows/tests-on-linux.yml new file mode 100644 index 00000000..2df8c86d --- /dev/null +++ b/.github/workflows/tests-on-linux.yml @@ -0,0 +1,31 @@ +name: Tests on Linux + +on: + workflow_dispatch: + push: + branches: ["main"] + pull_request: + branches: ["main"] + +jobs: + linux: + strategy: + matrix: + element: + - swift: '5.7' + withStaticBigInt: false + - swift: '5.8' + withStaticBigInt: true + + runs-on: ubuntu-latest + container: + image: swift:${{ matrix.element.swift }} + + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Test + run: swift test + - name: Test with StaticBigInt + if: matrix.element.withStaticBigInt + run: swift test -Xswiftc -DSBI From ed51792ac7fcc1d77dd4203904bf8ed3ac4a658b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sat, 19 Aug 2023 08:26:12 +0200 Subject: [PATCH 035/111] A workaround for Swift 5.7 compiler bug (#63). --- Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift index 35bdd794..aae2cef2 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift @@ -253,14 +253,18 @@ extension NBKDoubleWidth: NBKUnsignedInteger, UnsignedInteger /*---------*/ whe /// A signed, 128-bit, integer. #if SBI && swift(>=5.8) @available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif public typealias Int128 = NBKDoubleWidth> +#else // because Swift 5.7 cannot parse it otherwise +public typealias Int128 = NBKDoubleWidth> +#endif /// An unsigned, 128-bit, integer. #if SBI && swift(>=5.8) @available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif public typealias UInt128 = NBKDoubleWidth> +#else // because Swift 5.7 cannot parse it otherwise +public typealias UInt128 = NBKDoubleWidth> +#endif #elseif arch(x86_64) || arch(arm64) || arch(powerpc64) || arch(powerpc64le) || arch(s390x) From 839e48258a3e9f55e1a8fb9c38fdef7fd102d085 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sat, 19 Aug 2023 09:53:25 +0200 Subject: [PATCH 036/111] No conditionally compiled availability (#64). --- .../NBKDoubleWidth+Addition+Digit.swift | 3 - .../NBKDoubleWidth+Addition.swift | 3 - .../NBKDoubleWidth+Bits.swift | 3 - .../NBKDoubleWidth+Comparisons.swift | 3 - .../NBKDoubleWidth+Complements.swift | 3 - .../NBKDoubleWidth+Division+Digit.swift | 6 -- .../NBKDoubleWidth+Division.swift | 6 -- .../NBKDoubleWidth+Endianness.swift | 3 - .../NBKDoubleWidth+Literals.swift | 3 - .../NBKDoubleWidth+Logic.swift | 3 - .../NBKDoubleWidth+Multiplication+Digit.swift | 6 -- .../NBKDoubleWidth+Multiplication.swift | 6 -- .../NBKDoubleWidth+Numbers.swift | 3 - .../NBKDoubleWidth+Rotations.swift | 6 -- .../NBKDoubleWidth+Shifts.swift | 6 -- .../NBKDoubleWidth+Strides.swift | 3 - .../NBKDoubleWidth+Subtraction+Digit.swift | 3 - .../NBKDoubleWidth+Subtraction.swift | 3 - .../NBKDoubleWidth+Text.swift | 6 -- .../NBKDoubleWidth+Uninitialized.swift | 3 - .../NBKDoubleWidth+Words+Pointers.swift | 3 - .../NBKDoubleWidth+Words.swift | 12 ---- .../NBKDoubleWidthKit/NBKDoubleWidth.swift | 55 ------------------- .../NBKDoubleWidth+Addition.swift | 6 -- .../NBKDoubleWidth+Bits.swift | 6 -- .../NBKDoubleWidth+Comparisons.swift | 6 -- .../NBKDoubleWidth+Complements.swift | 6 -- .../NBKDoubleWidth+Division.swift | 6 -- .../NBKDoubleWidth+Endianness.swift | 6 -- .../NBKDoubleWidth+Logic.swift | 6 -- .../NBKDoubleWidth+Multiplication.swift | 6 -- .../NBKDoubleWidth+Numbers.swift | 6 -- .../NBKDoubleWidth+Random.swift | 6 -- .../NBKDoubleWidth+Rotations.swift | 6 -- .../NBKDoubleWidth+Shifts.swift | 6 -- .../NBKDoubleWidth+Strides.swift | 6 -- .../NBKDoubleWidth+Subtraction.swift | 6 -- .../NBKDoubleWidth+Text.swift | 6 -- .../NBKDoubleWidth.swift | 9 --- .../NBKDoubleWidth+Addition.swift | 12 ---- .../NBKDoubleWidth+Bits.swift | 6 -- .../NBKDoubleWidth+Comparisons.swift | 15 ----- .../NBKDoubleWidth+Complements.swift | 21 ------- .../NBKDoubleWidth+Division.swift | 18 ------ .../NBKDoubleWidth+Endianness.swift | 6 -- .../NBKDoubleWidth+Literals.swift | 6 -- .../NBKDoubleWidth+Logic.swift | 18 ------ .../NBKDoubleWidth+Multiplication.swift | 15 ----- .../NBKDoubleWidth+Numbers.swift | 21 ------- .../NBKDoubleWidth+Rotations.swift | 12 ---- .../NBKDoubleWidth+Shifts.swift | 18 ------ .../NBKDoubleWidth+Strides.swift | 6 -- .../NBKDoubleWidth+Subtraction.swift | 12 ---- .../NBKDoubleWidth+Text.swift | 15 ----- .../NBKDoubleWidth+Words.swift | 15 ----- .../NBKDoubleWidth.swift | 15 ----- 56 files changed, 481 deletions(-) diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Addition+Digit.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Addition+Digit.swift index a68260fa..6b9eb3f9 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Addition+Digit.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Addition+Digit.swift @@ -13,9 +13,6 @@ import NBKCoreKit // MARK: * NBK x Double Width x Addition x Digit //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Addition.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Addition.swift index e9cba24c..2edbe327 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Addition.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Addition.swift @@ -13,9 +13,6 @@ import NBKCoreKit // MARK: * NBK x Double Width x Addition //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Bits.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Bits.swift index 502551fd..167da9f8 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Bits.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Bits.swift @@ -13,9 +13,6 @@ import NBKCoreKit // MARK: * NBK x Double Width x Bits //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Comparisons.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Comparisons.swift index c05fc564..b3ef7983 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Comparisons.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Comparisons.swift @@ -13,9 +13,6 @@ import NBKCoreKit // MARK: * NBK x Double Width x Comparisons //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Complements.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Complements.swift index 56eac937..4fd3bd0a 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Complements.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Complements.swift @@ -13,9 +13,6 @@ import NBKCoreKit // MARK: * NBK x Double Width x Complements //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Division+Digit.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Division+Digit.swift index db686eed..13c6212a 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Division+Digit.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Division+Digit.swift @@ -13,9 +13,6 @@ import NBKCoreKit // MARK: * NBK x Double Width x Division x Digit //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= @@ -71,9 +68,6 @@ extension NBKDoubleWidth { // MARK: + Unsigned //=----------------------------------------------------------------------------= -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif extension NBKDoubleWidth where High == High.Magnitude { //=------------------------------------------------------------------------= diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Division.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Division.swift index 8dbfeb24..6cb22dde 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Division.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Division.swift @@ -13,9 +13,6 @@ import NBKCoreKit // MARK: * NBK x Double Width x Division //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= @@ -117,9 +114,6 @@ extension NBKDoubleWidth { // MARK: + Unsigned //=----------------------------------------------------------------------------= -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif extension NBKDoubleWidth where High == High.Magnitude { //=------------------------------------------------------------------------= diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Endianness.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Endianness.swift index 50a5cc19..511fd439 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Endianness.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Endianness.swift @@ -13,9 +13,6 @@ import NBKCoreKit // MARK: * NBK x Double Width x Endianness //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift index d5563145..3797df84 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift @@ -13,9 +13,6 @@ import NBKCoreKit // MARK: * NBK x Double Width x Literals //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif extension NBKDoubleWidth { //=-------------------------------------------------------------------------= diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Logic.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Logic.swift index aee1cae0..01c0a13b 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Logic.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Logic.swift @@ -13,9 +13,6 @@ import NBKCoreKit // MARK: * NBK x Double Width x Logic //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Multiplication+Digit.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Multiplication+Digit.swift index 4cd3f664..9375d72c 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Multiplication+Digit.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Multiplication+Digit.swift @@ -13,9 +13,6 @@ import NBKCoreKit // MARK: * NBK x Double Width x Multiplication x Digit //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= @@ -75,9 +72,6 @@ extension NBKDoubleWidth { // MARK: * NBK x Double Width x Multiplication x Digit x Unsigned //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif extension NBKDoubleWidth where High == High.Magnitude { //=------------------------------------------------------------------------= diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Multiplication.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Multiplication.swift index 8b1d1fc8..dc2f4e64 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Multiplication.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Multiplication.swift @@ -13,9 +13,6 @@ import NBKCoreKit // MARK: * NBK x Double Width x Multiplication //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= @@ -75,9 +72,6 @@ extension NBKDoubleWidth { // MARK: + Unsigned //=----------------------------------------------------------------------------= -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif extension NBKDoubleWidth where High == High.Magnitude { //=------------------------------------------------------------------------= diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Numbers.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Numbers.swift index ee1d5334..992f86cc 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Numbers.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Numbers.swift @@ -13,9 +13,6 @@ import NBKCoreKit // MARK: * NBK x Double Width x Numbers //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Rotations.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Rotations.swift index 9c3c5aff..34102b30 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Rotations.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Rotations.swift @@ -13,9 +13,6 @@ import NBKCoreKit // MARK: * NBK x Double Width x Rotations x Left //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= @@ -126,9 +123,6 @@ extension NBKDoubleWidth { // MARK: * NBK x Double Width x Rotations x Right //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Shifts.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Shifts.swift index 156c4f94..d758807e 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Shifts.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Shifts.swift @@ -13,9 +13,6 @@ import NBKCoreKit // MARK: * NBK x Double Width x Shifts x Left //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= @@ -137,9 +134,6 @@ extension NBKDoubleWidth { // MARK: * NBK x Double Width x Shifts x Right //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Strides.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Strides.swift index 5879e08d..e5c28df3 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Strides.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Strides.swift @@ -13,9 +13,6 @@ import NBKCoreKit // MARK: * NBK x Double Width x Strides //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Subtraction+Digit.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Subtraction+Digit.swift index 879e6490..bacfe5c1 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Subtraction+Digit.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Subtraction+Digit.swift @@ -13,9 +13,6 @@ import NBKCoreKit // MARK: * NBK x Double Width x Subtraction x Digit //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Subtraction.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Subtraction.swift index ddb7ad92..73871089 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Subtraction.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Subtraction.swift @@ -13,9 +13,6 @@ import NBKCoreKit // MARK: * NBK x Double Width x Subtraction //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text.swift index e2130664..dce1e7d5 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text.swift @@ -13,9 +13,6 @@ import NBKCoreKit // MARK: * NBK x Double Width x Text //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= @@ -55,9 +52,6 @@ extension NBKDoubleWidth { // MARK: * NBK x Double Width x Text x Unsigned //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif extension NBKDoubleWidth where High == High.Magnitude { //=------------------------------------------------------------------------= diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Uninitialized.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Uninitialized.swift index c6c043fa..10c1aa09 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Uninitialized.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Uninitialized.swift @@ -11,9 +11,6 @@ // MARK: * NBK x Double Width x Uninitialized //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words+Pointers.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words+Pointers.swift index ca559921..da1a8c97 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words+Pointers.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words+Pointers.swift @@ -13,9 +13,6 @@ import NBKCoreKit // MARK: * NBK x Double Width x Words x Pointers //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words.swift index d3dad616..6064f136 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words.swift @@ -13,9 +13,6 @@ import NBKCoreKit // MARK: * NBK x Double Width x Words //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= @@ -46,9 +43,6 @@ extension NBKDoubleWidth { // MARK: + Collection x Indices //=----------------------------------------------------------------------------= -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= @@ -139,9 +133,6 @@ extension NBKDoubleWidth { // MARK: + Collection x Elements //=----------------------------------------------------------------------------= -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= @@ -275,9 +266,6 @@ extension NBKDoubleWidth { // MARK: + Unsigned //=----------------------------------------------------------------------------= -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif extension NBKDoubleWidth where High == High.Magnitude { //=------------------------------------------------------------------------= diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift index aae2cef2..44a99b91 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift @@ -93,9 +93,6 @@ import NBKCoreKit /// /// - Note: You can use `StaticString` until `StaticBigInt` becomes available. /// -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif @frozen public struct NBKDoubleWidth: ExpressibleByStringLiteral, NBKFixedWidthInteger, MutableCollection, RandomAccessCollection where High: NBKFixedWidthInteger, High.Digit: NBKCoreInteger { @@ -234,14 +231,8 @@ High: NBKFixedWidthInteger, High.Digit: NBKCoreInteger { // MARK: * NBK x Double Width x Conditional Conformances //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif extension NBKDoubleWidth: NBKSignedInteger, SignedInteger, SignedNumeric where High: NBKSignedInteger { } -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif extension NBKDoubleWidth: NBKUnsignedInteger, UnsignedInteger /*---------*/ where High: NBKUnsignedInteger { } //*============================================================================* @@ -251,33 +242,17 @@ extension NBKDoubleWidth: NBKUnsignedInteger, UnsignedInteger /*---------*/ whe #if arch(i386) || arch(arm) || arch(arm64_32) || arch(wasm32) || arch(powerpc) /// A signed, 128-bit, integer. -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) public typealias Int128 = NBKDoubleWidth> -#else // because Swift 5.7 cannot parse it otherwise -public typealias Int128 = NBKDoubleWidth> -#endif /// An unsigned, 128-bit, integer. -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) public typealias UInt128 = NBKDoubleWidth> -#else // because Swift 5.7 cannot parse it otherwise -public typealias UInt128 = NBKDoubleWidth> -#endif #elseif arch(x86_64) || arch(arm64) || arch(powerpc64) || arch(powerpc64le) || arch(s390x) /// A signed, 128-bit, integer. -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif public typealias Int128 = NBKDoubleWidth /// An unsigned, 128-bit, integer. -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif public typealias UInt128 = NBKDoubleWidth #else @@ -291,15 +266,9 @@ public typealias UInt128 = NBKDoubleWidth //*============================================================================* /// A signed, 256-bit, integer. -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif public typealias Int256 = NBKDoubleWidth /// An unsigned, 256-bit, integer. -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif public typealias UInt256 = NBKDoubleWidth //*============================================================================* @@ -307,15 +276,9 @@ public typealias UInt256 = NBKDoubleWidth //*============================================================================* /// A signed, 512-bit, integer. -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif public typealias Int512 = NBKDoubleWidth /// An unsigned, 512-bit, integer. -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif public typealias UInt512 = NBKDoubleWidth //*============================================================================* @@ -323,15 +286,9 @@ public typealias UInt512 = NBKDoubleWidth //*============================================================================* /// A signed, 1024-bit, integer. -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif public typealias Int1024 = NBKDoubleWidth /// An unsigned, 1024-bit, integer. -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif public typealias UInt1024 = NBKDoubleWidth //*============================================================================* @@ -339,15 +296,9 @@ public typealias UInt1024 = NBKDoubleWidth //*============================================================================* /// A signed, 2048-bit, integer. -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif public typealias Int2048 = NBKDoubleWidth /// An unsigned, 2048-bit, integer. -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif public typealias UInt2048 = NBKDoubleWidth //*============================================================================* @@ -355,13 +306,7 @@ public typealias UInt2048 = NBKDoubleWidth //*============================================================================* /// A signed, 4096-bit, integer. -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif public typealias Int4096 = NBKDoubleWidth /// An unsigned, 4096-bit, integer. -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif public typealias UInt4096 = NBKDoubleWidth diff --git a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Addition.swift b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Addition.swift index fe1d6f22..aef7af16 100644 --- a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Addition.swift +++ b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Addition.swift @@ -20,9 +20,6 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Addition x Int256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthBenchmarksOnAdditionAsInt256: XCTestCase { typealias T = Int256 @@ -106,9 +103,6 @@ final class NBKDoubleWidthBenchmarksOnAdditionAsInt256: XCTestCase { // MARK: * NBK x Double Width x Addition x UInt256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthBenchmarksOnAdditionAsUInt256: XCTestCase { typealias T = UInt256 diff --git a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Bits.swift b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Bits.swift index 1f0fc4a6..671b7046 100644 --- a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Bits.swift +++ b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Bits.swift @@ -20,9 +20,6 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Bits x Int256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthBenchmarksOnBitsAsInt256: XCTestCase { typealias T = Int256 @@ -140,9 +137,6 @@ final class NBKDoubleWidthBenchmarksOnBitsAsInt256: XCTestCase { // MARK: * NBK x Double Width x Bits x UInt256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthBenchmarksOnBitsAsUInt256: XCTestCase { typealias T = UInt256 diff --git a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Comparisons.swift b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Comparisons.swift index 58aa6b62..65346848 100644 --- a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Comparisons.swift +++ b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Comparisons.swift @@ -20,9 +20,6 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Comparisons x Int256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthBenchmarksOnComparisonsAsInt256: XCTestCase { typealias T = Int256 @@ -129,9 +126,6 @@ final class NBKDoubleWidthBenchmarksOnComparisonsAsInt256: XCTestCase { // MARK: * NBK x Double Width x Comparisons x UInt256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthBenchmarksOnComparisonsAsUInt256: XCTestCase { typealias T = UInt256 diff --git a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Complements.swift b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Complements.swift index e8150fcc..d214d8f9 100644 --- a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Complements.swift +++ b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Complements.swift @@ -20,9 +20,6 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Complements x Int256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthBenchmarksOnComplementsAsInt256: XCTestCase { typealias T = Int256 @@ -170,9 +167,6 @@ final class NBKDoubleWidthBenchmarksOnComplementsAsInt256: XCTestCase { // MARK: * NBK x Double Width x Complements x UInt256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthBenchmarksOnComplementsAsUInt256: XCTestCase { typealias T = UInt256 diff --git a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Division.swift b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Division.swift index 95f0f2a9..850faacb 100644 --- a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Division.swift +++ b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Division.swift @@ -20,9 +20,6 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Division x Int256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthBenchmarksOnDivisionAsInt256: XCTestCase { typealias T = Int256 @@ -133,9 +130,6 @@ final class NBKDoubleWidthBenchmarksOnDivisionAsInt256: XCTestCase { // MARK: * NBK x Double Width x Division x UInt256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthBenchmarksOnDivisionAsUInt256: XCTestCase { typealias T = UInt256 diff --git a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Endianness.swift b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Endianness.swift index 433f5f9b..32af8219 100644 --- a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Endianness.swift +++ b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Endianness.swift @@ -20,9 +20,6 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Endianness x Int256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthBenchmarksOnEndiannessAsInt256: XCTestCase { typealias T = Int256 @@ -63,9 +60,6 @@ final class NBKDoubleWidthBenchmarksOnEndiannessAsInt256: XCTestCase { // MARK: * NBK x Double Width x Endianness x UInt256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthBenchmarksOnEndiannessAsUInt256: XCTestCase { typealias T = UInt256 diff --git a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Logic.swift b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Logic.swift index afa30e0a..c2dd923d 100644 --- a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Logic.swift +++ b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Logic.swift @@ -20,9 +20,6 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Logic x Int256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthBenchmarksOnLogicAsInt256: XCTestCase { typealias T = Int256 @@ -78,9 +75,6 @@ final class NBKDoubleWidthBenchmarksOnLogicAsInt256: XCTestCase { // MARK: * NBK x Double Width x Logic x UInt256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthBenchmarksOnLogicAsUInt256: XCTestCase { typealias T = UInt256 diff --git a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Multiplication.swift b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Multiplication.swift index 1c5db3ee..1aaa1229 100644 --- a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Multiplication.swift +++ b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Multiplication.swift @@ -20,9 +20,6 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Multiplication x Int256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthBenchmarksOnMultiplicationAsInt256: XCTestCase { typealias T = Int256 @@ -128,9 +125,6 @@ final class NBKDoubleWidthBenchmarksOnMultiplicationAsInt256: XCTestCase { // MARK: * NBK x Double Width x Multiplication x UInt256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthBenchmarksOnMultiplicationAsUInt256: XCTestCase { typealias T = UInt256 diff --git a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Numbers.swift b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Numbers.swift index 4755f704..0833e3e8 100644 --- a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Numbers.swift +++ b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Numbers.swift @@ -20,9 +20,6 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Numbers x Int256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthBenchmarksOnNumbersAsInt256: XCTestCase { typealias S = Int256 @@ -432,9 +429,6 @@ final class NBKDoubleWidthBenchmarksOnNumbersAsInt256: XCTestCase { // MARK: * NBK x Double Width x Numbers x UInt256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthBenchmarksOnNumbersAsUInt256: XCTestCase { typealias S = Int256 diff --git a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Random.swift b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Random.swift index 4385125d..5cffc07a 100644 --- a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Random.swift +++ b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Random.swift @@ -20,9 +20,6 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Random x Int256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthBenchmarksOnRandomAsInt256: XCTestCase { typealias T = Int256 @@ -47,9 +44,6 @@ final class NBKDoubleWidthBenchmarksOnRandomAsInt256: XCTestCase { // MARK: * NBK x Double Width x Random x UInt256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthBenchmarksOnRandomAsUInt256: XCTestCase { typealias T = UInt256 diff --git a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Rotations.swift b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Rotations.swift index 9e0d04b7..3ac6b74b 100644 --- a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Rotations.swift +++ b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Rotations.swift @@ -20,9 +20,6 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Rotations x Int256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthBenchmarksOnRotationsAsInt256: XCTestCase { typealias T = Int256 @@ -106,9 +103,6 @@ final class NBKDoubleWidthBenchmarksOnRotationsAsInt256: XCTestCase { // MARK: * NBK x Double Width x Rotations x UInt256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthBenchmarksOnRotationsAsUInt256: XCTestCase { typealias T = UInt256 diff --git a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Shifts.swift b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Shifts.swift index c5e8a194..78e4b4bb 100644 --- a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Shifts.swift +++ b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Shifts.swift @@ -20,9 +20,6 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Shifts x Int256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthBenchmarksOnShiftsAsInt256: XCTestCase { typealias T = Int256 @@ -128,9 +125,6 @@ final class NBKDoubleWidthBenchmarksOnShiftsAsInt256: XCTestCase { // MARK: * NBK x Double Width x Shifts x UInt256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthBenchmarksOnShiftsAsUInt256: XCTestCase { typealias T = UInt256 diff --git a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Strides.swift b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Strides.swift index 42c0fe32..8312d640 100644 --- a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Strides.swift +++ b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Strides.swift @@ -20,9 +20,6 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Strides x Int256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthBenchmarksOnStridesAsInt256: XCTestCase { typealias T = Int256 @@ -58,9 +55,6 @@ final class NBKDoubleWidthBenchmarksOnStridesAsInt256: XCTestCase { // MARK: * NBK x Double Width x Strides x UInt256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthBenchmarksOnStridesAsUInt256: XCTestCase { typealias T = UInt256 diff --git a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Subtraction.swift b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Subtraction.swift index f7503bbc..130b19d2 100644 --- a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Subtraction.swift +++ b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Subtraction.swift @@ -20,9 +20,6 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Subtraction x Int256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthBenchmarksOnSubtractionAsInt256: XCTestCase { typealias T = Int256 @@ -106,9 +103,6 @@ final class NBKDoubleWidthBenchmarksOnSubtractionAsInt256: XCTestCase { // MARK: * NBK x Double Width x Subtraction x UInt256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthBenchmarksOnSubtractionAsUInt256: XCTestCase { typealias T = UInt256 diff --git a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Text.swift b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Text.swift index ca0c8d5d..f770f8d1 100644 --- a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Text.swift +++ b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth+Text.swift @@ -20,9 +20,6 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Text x Int256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthBenchmarksOnTextAsInt256: XCTestCase { typealias T = Int256 @@ -135,9 +132,6 @@ final class NBKDoubleWidthBenchmarksOnTextAsInt256: XCTestCase { // MARK: * NBK x Double Width x Text x UInt256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthBenchmarksOnTextAsUInt256: XCTestCase { typealias T = UInt256 diff --git a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth.swift b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth.swift index 77ff9efa..8951c8e9 100644 --- a/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth.swift +++ b/Tests/NBKDoubleWidthKitBenchmarks/NBKDoubleWidth.swift @@ -20,9 +20,6 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Int256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthBenchmarksAsInt256: XCTestCase { typealias T = Int256 @@ -50,9 +47,6 @@ final class NBKDoubleWidthBenchmarksAsInt256: XCTestCase { // MARK: * NBK x Double Width x UInt256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthBenchmarksAsUInt256: XCTestCase { typealias T = UInt256 @@ -80,9 +74,6 @@ final class NBKDoubleWidthBenchmarksAsUInt256: XCTestCase { // MARK: * NBK x Double Width x Initializers //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= diff --git a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Addition.swift b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Addition.swift index 2f7644ee..3208215d 100644 --- a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Addition.swift +++ b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Addition.swift @@ -20,9 +20,6 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Addition x Int256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthTestsOnAdditionAsInt256: XCTestCase { typealias T = Int256 @@ -143,9 +140,6 @@ final class NBKDoubleWidthTestsOnAdditionAsInt256: XCTestCase { // MARK: * NBK x Double Width x Addition x UInt256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthTestsOnAdditionAsUInt256: XCTestCase { typealias T = UInt256 @@ -223,9 +217,6 @@ final class NBKDoubleWidthTestsOnAdditionAsUInt256: XCTestCase { // MARK: * NBK x Double Width x Addition x Assertions //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif private func NBKAssertAddition( _ lhs: NBKDoubleWidth, _ rhs: NBKDoubleWidth, _ partialValue: NBKDoubleWidth, _ overflow: Bool = false, @@ -246,9 +237,6 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual({ var x = lhs; let o = x.addReportingOverflow(rhs); return o }(), overflow, file: file, line: line) } -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif private func NBKAssertAdditionByDigit( _ lhs: NBKDoubleWidth, _ rhs: NBKDoubleWidth.Digit, _ partialValue: NBKDoubleWidth, _ overflow: Bool = false, diff --git a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Bits.swift b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Bits.swift index f21a2bee..bdb64959 100644 --- a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Bits.swift +++ b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Bits.swift @@ -20,9 +20,6 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Bits x Int256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthTestsOnBitsAsInt256: XCTestCase { typealias T = Int256 @@ -97,9 +94,6 @@ final class NBKDoubleWidthTestsOnBitsAsInt256: XCTestCase { // MARK: * NBK x Double Width x Bits x UInt256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthTestsOnBitsAsUInt256: XCTestCase { typealias T = UInt256 diff --git a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Comparisons.swift b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Comparisons.swift index 6cfed07b..4a616b85 100644 --- a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Comparisons.swift +++ b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Comparisons.swift @@ -20,9 +20,6 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Comparisons x Int256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthTestsOnComparisonsAsInt256: XCTestCase { typealias T = Int256 @@ -221,9 +218,6 @@ final class NBKDoubleWidthTestsOnComparisonsAsInt256: XCTestCase { // MARK: * NBK x Double Width x Comparisons x UInt256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthTestsOnComparisonsAsUInt256: XCTestCase { typealias T = UInt256 @@ -384,9 +378,6 @@ final class NBKDoubleWidthTestsOnComparisonsAsUInt256: XCTestCase { // MARK: * NBK x Double Width x Comparisons x Assertions //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif private func NBKAssertSignum( _ operand: NBKDoubleWidth, _ signum: Int, file: StaticString = #file, line: UInt = #line) { @@ -396,9 +387,6 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual(Int(operand.signum() as T ), signum, file: file, line: line) // stdlib } -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif private func NBKAssertComparisons( _ lhs: NBKDoubleWidth, _ rhs: NBKDoubleWidth, _ signum: Int, file: StaticString = #file, line: UInt = #line) { @@ -414,9 +402,6 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual(lhs.compared(to: rhs), signum, file: file, line: line) } -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif private func NBKAssertComparisonsByDigit( _ lhs: NBKDoubleWidth, _ rhs: NBKDoubleWidth.Digit, _ signum: Int, file: StaticString = #file, line: UInt = #line) { diff --git a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Complements.swift b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Complements.swift index a10bc69a..7e567a38 100644 --- a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Complements.swift +++ b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Complements.swift @@ -20,9 +20,6 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Complements x Int256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthTestsOnComplementsAsInt256: XCTestCase { typealias T = Int256 @@ -104,9 +101,6 @@ final class NBKDoubleWidthTestsOnComplementsAsInt256: XCTestCase { // MARK: * NBK x Double Width x Complements x UInt256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthTestsOnComplementsAsUInt256: XCTestCase { typealias T = UInt256 @@ -167,9 +161,6 @@ final class NBKDoubleWidthTestsOnComplementsAsUInt256: XCTestCase { // MARK: * NBK x Double Width x Complements x Assertions //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif private func NBKAssertBitPattern( _ integer: NBKDoubleWidth, _ bitPattern: NBKDoubleWidth.BitPattern, file: StaticString = #file, line: UInt = #line) { @@ -182,9 +173,6 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual(B(bitPattern: integer), bitPattern, file: file, line: line) } -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif private func NBKAssertBitPattern( _ integer: T, _ bitPattern: T.BitPattern, file: StaticString = #file, line: UInt = #line) where T.BitPattern: Equatable { @@ -194,9 +182,6 @@ file: StaticString = #file, line: UInt = #line) where T.BitPattern: Equatable { XCTAssertEqual(T.BitPattern(bitPattern: integer), bitPattern, file: file, line: line) } -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif private func NBKAssertOnesComplement( _ integer: NBKDoubleWidth, _ result: NBKDoubleWidth, file: StaticString = #file, line: UInt = #line) { @@ -207,9 +192,6 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual({ var x = integer; let _ = x.formTwosComplementSubsequence(false); return x }(), result, file: file, line: line) } -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif private func NBKAssertTwosComplement( _ integer: NBKDoubleWidth, _ partialValue: NBKDoubleWidth, _ overflow: Bool = false, file: StaticString = #file, line: UInt = #line) { @@ -226,9 +208,6 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual({ var x = integer; let o = x.formTwosComplementSubsequence(true ); return o }(), overflow, file: file, line: line) } -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif private func NBKAssertAdditiveInverse( _ operand: NBKDoubleWidth, _ partialValue: NBKDoubleWidth, _ overflow: Bool = false, file: StaticString = #file, line: UInt = #line) { diff --git a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Division.swift b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Division.swift index 7a42a055..6ce50303 100644 --- a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Division.swift +++ b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Division.swift @@ -20,9 +20,6 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Division x Int256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthTestsOnDivisionAsInt256: XCTestCase { typealias T = Int256 @@ -226,9 +223,6 @@ final class NBKDoubleWidthTestsOnDivisionAsInt256: XCTestCase { // MARK: * NBK x Double Width x Division x UInt256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthTestsOnDivisionAsUInt256: XCTestCase { typealias T = UInt256 @@ -382,9 +376,6 @@ final class NBKDoubleWidthTestsOnDivisionAsUInt256: XCTestCase { // MARK: * NBK x Double Width x Division x UInt256 x Code Coverage //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthTestsOnDivisionAsUInt256CodeCoverage: XCTestCase { typealias T = UInt256 @@ -413,9 +404,6 @@ final class NBKDoubleWidthTestsOnDivisionAsUInt256CodeCoverage: XCTestCase { // MARK: * NBK x Double Width x Division x Assertions //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif private func NBKAssertDivision( _ lhs: NBKDoubleWidth, _ rhs: NBKDoubleWidth, _ quotient: NBKDoubleWidth, _ remainder: NBKDoubleWidth, _ overflow: Bool = false, @@ -453,9 +441,6 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual(lhs.quotientAndRemainderReportingOverflow(dividingBy: rhs).overflow, overflow, file: file, line: line) } -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif private func NBKAssertDivisionByDigit( _ lhs: NBKDoubleWidth, _ rhs: NBKDoubleWidth.Digit, _ quotient: NBKDoubleWidth, _ remainder: NBKDoubleWidth.Digit, _ overflow: Bool = false, @@ -498,9 +483,6 @@ file: StaticString = #file, line: UInt = #line) { // MARK: + Full Width //=----------------------------------------------------------------------------= -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif private func NBKAssertDivisionFullWidth( _ lhs: HL, NBKDoubleWidth.Magnitude>, _ rhs: NBKDoubleWidth, _ quotient: NBKDoubleWidth, _ remainder: NBKDoubleWidth, _ overflow: Bool = false, diff --git a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Endianness.swift b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Endianness.swift index 2b6d5296..caa415b3 100644 --- a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Endianness.swift +++ b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Endianness.swift @@ -20,9 +20,6 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Endianness x Int256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthTestsOnEndiannessAsInt256: XCTestCase { typealias T = Int256 @@ -69,9 +66,6 @@ final class NBKDoubleWidthTestsOnEndiannessAsInt256: XCTestCase { // MARK: * NBK x Double Width x Endianness x UInt256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthTestsOnEndiannessAsUInt256: XCTestCase { typealias T = UInt256 diff --git a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Literals.swift b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Literals.swift index df68f5f1..c6692e24 100644 --- a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Literals.swift +++ b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Literals.swift @@ -20,9 +20,6 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Literals x Int256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthTestsOnLiteralsAsInt256: XCTestCase { typealias T = Int256 @@ -78,9 +75,6 @@ final class NBKDoubleWidthTestsOnLiteralsAsInt256: XCTestCase { // MARK: * NBK x Double Width x Literals x UInt256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthTestsOnLiteralsAsUInt256: XCTestCase { typealias T = UInt256 diff --git a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Logic.swift b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Logic.swift index 7de05765..9d896a82 100644 --- a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Logic.swift +++ b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Logic.swift @@ -20,9 +20,6 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Logic x Int256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthTestsOnLogicAsInt256: XCTestCase { typealias T = Int256 @@ -74,9 +71,6 @@ final class NBKDoubleWidthTestsOnLogicAsInt256: XCTestCase { // MARK: * NBK x Double Width x Logic x UInt256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthTestsOnLogicAsUInt256: XCTestCase { typealias T = UInt256 @@ -128,9 +122,6 @@ final class NBKDoubleWidthTestsOnLogicAsUInt256: XCTestCase { // MARK: * NBK x Double Width x Logic x Assertions //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif private func NBKAssertNot( _ operand: NBKDoubleWidth, _ result: NBKDoubleWidth, file: StaticString = #file, line: UInt = #line) { @@ -144,9 +135,6 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual({ var x = result; x.formOnesComplement(); return x }(), operand, file: file, line: line) } -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif private func NBKAssertAnd( _ lhs: NBKDoubleWidth, _ rhs: NBKDoubleWidth, _ result: NBKDoubleWidth, file: StaticString = #file, line: UInt = #line) { @@ -156,9 +144,6 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual({ var rhs = rhs; rhs &= lhs; return rhs }(), result, file: file, line: line) } -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif private func NBKAssertOr( _ lhs: NBKDoubleWidth, _ rhs: NBKDoubleWidth, _ result: NBKDoubleWidth, file: StaticString = #file, line: UInt = #line) { @@ -168,9 +153,6 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual({ var rhs = rhs; rhs |= lhs; return rhs }(), result, file: file, line: line) } -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif private func NBKAssertXor( _ lhs: NBKDoubleWidth, _ rhs: NBKDoubleWidth, _ result: NBKDoubleWidth, file: StaticString = #file, line: UInt = #line) { diff --git a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Multiplication.swift b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Multiplication.swift index f6107870..415b9050 100644 --- a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Multiplication.swift +++ b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Multiplication.swift @@ -20,9 +20,6 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Multiplication x Int256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthTestsOnMultiplicationAsInt256: XCTestCase { typealias T = Int256 @@ -157,9 +154,6 @@ final class NBKDoubleWidthTestsOnMultiplicationAsInt256: XCTestCase { // MARK: * NBK x Double Width x Multiplication x UInt256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthTestsOnMultiplicationAsUInt256: XCTestCase { typealias T = UInt256 @@ -252,9 +246,6 @@ final class NBKDoubleWidthTestsOnMultiplicationAsUInt256: XCTestCase { // MARK: * NBK x Double Width x Multiplication x Assertions //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif private func NBKAssertMultiplication( _ lhs: NBKDoubleWidth, _ rhs: NBKDoubleWidth, _ low: NBKDoubleWidth, _ high: NBKDoubleWidth? = nil, _ overflow: Bool = false, @@ -284,9 +275,6 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual({ var x = lhs; let o = x.multiplyFullWidth(by: rhs); return o }(), high, file: file, line: line) } -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif private func NBKAssertMultiplicationByDigit( _ lhs: NBKDoubleWidth, _ rhs: NBKDoubleWidth.Digit, _ low: NBKDoubleWidth, _ high: NBKDoubleWidth.Digit? = nil, _ overflow: Bool = false, @@ -316,9 +304,6 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual({ var x = lhs; let o = x.multiplyFullWidth(by: rhs); return o }(), high, file: file, line: line) } -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif private func NBKAssertMultiplicationByDigitWithAddition( _ lhs: NBKDoubleWidth, _ rhs: UInt, _ carry: UInt, _ low: NBKDoubleWidth, _ high: UInt, _ overflow: Bool = false, diff --git a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Numbers.swift b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Numbers.swift index 639bd071..8c7246c5 100644 --- a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Numbers.swift +++ b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Numbers.swift @@ -20,9 +20,6 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Numbers x Int256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthTestsOnNumbersAsInt256: XCTestCase { typealias S = Int256 @@ -281,9 +278,6 @@ final class NBKDoubleWidthTestsOnNumbersAsInt256: XCTestCase { // MARK: * NBK x Double Width x Numbers x UInt256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthTestsOnNumbersAsUInt256: XCTestCase { typealias S = Int256 @@ -527,45 +521,30 @@ final class NBKDoubleWidthTestsOnNumbersAsUInt256: XCTestCase { // MARK: * NBK x Double Width x Numbers x Assertions //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif 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) } -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif 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) } -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif 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) } -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif 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) } -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif private func NBKAssertNumbers( from value: I, exactly: O?, clamping: O, truncating: O, file: StaticString = #file, line: UInt = #line) { diff --git a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Rotations.swift b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Rotations.swift index bf49c48a..2f79641e 100644 --- a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Rotations.swift +++ b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Rotations.swift @@ -20,9 +20,6 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Rotations x Int256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthTestsOnRotationsAsInt256: XCTestCase { typealias T = Int256 @@ -96,9 +93,6 @@ final class NBKDoubleWidthTestsOnRotationsAsInt256: XCTestCase { // MARK: * NBK x Double Width x Rotations x UInt256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthTestsOnRotationsAsUInt256: XCTestCase { typealias T = UInt256 @@ -172,9 +166,6 @@ final class NBKDoubleWidthTestsOnRotationsAsUInt256: XCTestCase { // MARK: * NBK x Double Width x Rotations x Assertions //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif private func NBKAssertRotateLeft( _ lhs: NBKDoubleWidth, _ rhs: Int, _ result: NBKDoubleWidth, file: StaticString = #file, line: UInt = #line) { @@ -197,9 +188,6 @@ file: StaticString = #file, line: UInt = #line) { } } -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif private func NBKAssertRotateRight( _ lhs: NBKDoubleWidth, _ rhs: Int, _ result: NBKDoubleWidth, file: StaticString = #file, line: UInt = #line) { diff --git a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Shifts.swift b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Shifts.swift index ca3f815f..001d12ca 100644 --- a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Shifts.swift +++ b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Shifts.swift @@ -20,9 +20,6 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Shifts x Int256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthTestsOnShiftsAsInt256: XCTestCase { typealias S = Int256 @@ -146,9 +143,6 @@ final class NBKDoubleWidthTestsOnShiftsAsInt256: XCTestCase { // MARK: * NBK x Double Width x Shifts x UInt256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthTestsOnShiftsAsUInt256: XCTestCase { typealias S = Int256 @@ -272,9 +266,6 @@ final class NBKDoubleWidthTestsOnShiftsAsUInt256: XCTestCase { // MARK: * NBK x Double Width x Shifts x Assertions //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif private func NBKAssertShiftLeft( _ lhs: NBKDoubleWidth, _ rhs: Int, _ result: NBKDoubleWidth, file: StaticString = #file, line: UInt = #line) { @@ -312,9 +303,6 @@ file: StaticString = #file, line: UInt = #line) { } } -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif private func NBKAssertShiftRight( _ lhs: NBKDoubleWidth, _ rhs: Int, _ result: NBKDoubleWidth, file: StaticString = #file, line: UInt = #line) { @@ -356,9 +344,6 @@ file: StaticString = #file, line: UInt = #line) { // MARK: + Masking //=----------------------------------------------------------------------------= -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif private func NBKAssertShiftLeftByMasking( _ lhs: NBKDoubleWidth, _ rhs: Int, _ result: NBKDoubleWidth, signitude: S.Type, file: StaticString = #file, line: UInt = #line) where S.Digit: NBKCoreInteger { @@ -398,9 +383,6 @@ file: StaticString = #file, line: UInt = #line) where S.Digit: NBKCoreInteger=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif private func NBKAssertShiftRightByMasking( _ lhs: NBKDoubleWidth, _ rhs: Int, _ result: NBKDoubleWidth, signitude: S.Type, file: StaticString = #file, line: UInt = #line) where S.Digit: NBKCoreInteger { diff --git a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Strides.swift b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Strides.swift index 2046dd0c..812c386d 100644 --- a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Strides.swift +++ b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Strides.swift @@ -20,9 +20,6 @@ private typealias Y = [UInt64] // MARK: * NBK x Double Width x Strides x Int256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthTestsOnStridesAsInt256: XCTestCase { typealias T = Int256 @@ -54,9 +51,6 @@ final class NBKDoubleWidthTestsOnStridesAsInt256: XCTestCase { // MARK: * NBK x Double Width x Strides x UInt256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthTestsOnStridesAsUInt256: XCTestCase { typealias T = UInt256 diff --git a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Subtraction.swift b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Subtraction.swift index 9b730a74..6cf226f1 100644 --- a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Subtraction.swift +++ b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Subtraction.swift @@ -20,9 +20,6 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Subtraction x Int256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthTestsOnSubtractionAsInt256: XCTestCase { typealias T = Int256 @@ -143,9 +140,6 @@ final class NBKDoubleWidthTestsOnSubtractionAsInt256: XCTestCase { // MARK: * NBK x Double Width x Subtraction x UInt256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthTestsOnSubtractionAsUInt256: XCTestCase { typealias T = UInt256 @@ -217,9 +211,6 @@ final class NBKDoubleWidthTestsOnSubtractionAsUInt256: XCTestCase { // MARK: * NBK x Double Width x Subtraction x Assertions //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif private func NBKAssertSubtraction( _ lhs: NBKDoubleWidth, _ rhs: NBKDoubleWidth, _ partialValue: NBKDoubleWidth, _ overflow: Bool = false, @@ -240,9 +231,6 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual({ var x = lhs; let o = x.subtractReportingOverflow(rhs); return o }(), overflow, file: file, line: line) } -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif private func NBKAssertSubtractionByDigit( _ lhs: NBKDoubleWidth, _ rhs: NBKDoubleWidth.Digit, _ partialValue: NBKDoubleWidth, _ overflow: Bool = false, diff --git a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Text.swift b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Text.swift index d1869e5d..4806f3f8 100644 --- a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Text.swift +++ b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Text.swift @@ -20,9 +20,6 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Text x Int256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthTestsOnTextAsInt256: XCTestCase { typealias T = Int256 @@ -261,9 +258,6 @@ final class NBKDoubleWidthTestsOnTextAsInt256: XCTestCase { // MARK: * NBK x Double Width x Text x UInt256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthTestsOnTextAsUInt256: XCTestCase { typealias T = UInt256 @@ -482,9 +476,6 @@ final class NBKDoubleWidthTestsOnTextAsUInt256: XCTestCase { // MARK: * NBK x Double Width x Text x Assertions //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif private func NBKAssertFromDescription( _ integer: NBKDoubleWidth?, _ description: String, file: StaticString = #file, line: UInt = #line) { @@ -494,9 +485,6 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual(T(description, radix: 10), integer, file: file, line: line) } -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif private func NBKAssertDecodeText( _ integer: NBKDoubleWidth?, _ radix: Int, _ text: String, file: StaticString = #file, line: UInt = #line) { @@ -509,9 +497,6 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual(T(text, radix: radix), integer, file: file, line: line) } -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif private func NBKAssertEncodeText( _ integer: NBKDoubleWidth, _ radix: Int, _ uppercase: Bool, _ text: String, file: StaticString = #file, line: UInt = #line) { diff --git a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Words.swift b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Words.swift index 30b8ca29..b438f783 100644 --- a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Words.swift +++ b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Words.swift @@ -20,9 +20,6 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width x Words x Int256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthTestsOnWordsAsInt256: XCTestCase { typealias T = Int256 @@ -102,9 +99,6 @@ final class NBKDoubleWidthTestsOnWordsAsInt256: XCTestCase { // MARK: * NBK x Double Width x Words x UInt256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthTestsOnWordsAsUInt256: XCTestCase { typealias T = UInt256 @@ -184,9 +178,6 @@ final class NBKDoubleWidthTestsOnWordsAsUInt256: XCTestCase { // MARK: * NBK x Double Width x Words x Assertions //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif private func NBKAssertWords( _ integer: NBKDoubleWidth, _ words: [UInt], file: StaticString = #file, line: UInt = #line) { @@ -213,9 +204,6 @@ file: StaticString = #file, line: UInt = #line) { // MARK: + Indices //=----------------------------------------------------------------------------= -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif private func NBKAssertIndexOffsetByLimitedBy( _ integer: NBKDoubleWidth, _ index: Int, _ distance: Int, _ limit: Int, _ expectation: Int?, file: StaticString = #file, line: UInt = #line) { @@ -230,9 +218,6 @@ file: StaticString = #file, line: UInt = #line) { // MARK: + Elements x First, Last, Tail //=----------------------------------------------------------------------------= -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif private func NBKAssertFirstLastTail( _ integer: NBKDoubleWidth, first: UInt, last: UInt, tail: H.Digit, file: StaticString = #file, line: UInt = #line) { diff --git a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth.swift b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth.swift index d77291d4..4cf97474 100644 --- a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth.swift +++ b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth.swift @@ -18,9 +18,6 @@ private typealias Y = NBK.U256X32 // MARK: * NBK x Double Width //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthTests: XCTestCase { typealias T = any NBKFixedWidthInteger.Type @@ -62,9 +59,6 @@ final class NBKDoubleWidthTests: XCTestCase { // MARK: * NBK x Double Width x Int256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthTestsAsInt256: XCTestCase { typealias T = Int256 @@ -108,9 +102,6 @@ final class NBKDoubleWidthTestsAsInt256: XCTestCase { // MARK: * NBK x Double Width x UInt256 //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif final class NBKDoubleWidthTestsAsUInt256: XCTestCase { typealias T = UInt256 @@ -154,9 +145,6 @@ final class NBKDoubleWidthTestsAsUInt256: XCTestCase { // MARK: * NBK x Double Width x Assertions //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif private func NBKAssertHalvesGetSetInit( _ value: NBKDoubleWidth, _ low: H.Magnitude, _ high: H, file: StaticString = #file, line: UInt = #line) { @@ -194,9 +182,6 @@ file: StaticString = #file, line: UInt = #line) { // MARK: * NBK x Double Width x Initializers //*============================================================================* -#if SBI && swift(>=5.8) -@available(iOS 16.4, macCatalyst 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *) -#endif extension NBKDoubleWidth { //=------------------------------------------------------------------------= From 1d51325da8173bfedd66459a9752400c65e400d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sat, 19 Aug 2023 10:20:28 +0200 Subject: [PATCH 037/111] Tests on macOS (#60). --- ...ts-on-linux.yml => run-tests-on-linux.yml} | 2 +- .github/workflows/run-tests-on-macos.yml | 33 +++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) rename .github/workflows/{tests-on-linux.yml => run-tests-on-linux.yml} (96%) create mode 100644 .github/workflows/run-tests-on-macos.yml diff --git a/.github/workflows/tests-on-linux.yml b/.github/workflows/run-tests-on-linux.yml similarity index 96% rename from .github/workflows/tests-on-linux.yml rename to .github/workflows/run-tests-on-linux.yml index 2df8c86d..c87fb10d 100644 --- a/.github/workflows/tests-on-linux.yml +++ b/.github/workflows/run-tests-on-linux.yml @@ -1,4 +1,4 @@ -name: Tests on Linux +name: Run tests on Linux on: workflow_dispatch: diff --git a/.github/workflows/run-tests-on-macos.yml b/.github/workflows/run-tests-on-macos.yml new file mode 100644 index 00000000..26f3896d --- /dev/null +++ b/.github/workflows/run-tests-on-macos.yml @@ -0,0 +1,33 @@ +name: Run tests on macOS + +on: + workflow_dispatch: + push: + branches: ["main"] + pull_request: + branches: ["main"] + +jobs: + macos: + strategy: + matrix: + element: + - xcode: '14.2' + machine: macos-12 + withStaticBigInt: false + - xcode: '14.3' + machine: macos-13 + withStaticBigInt: true + + runs-on: ${{ matrix.element.machine }} + + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Select Xcode + run: sudo xcode-select -s /Applications/Xcode_${{ matrix.element.xcode }}.app + - name: Test + run: swift test + - name: Test with StaticBigInt + if: matrix.element.withStaticBigInt + run: swift test -Xswiftc -DSBI From 33dcfb8d001c060e67dcb51fd18e96ed377f92bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sat, 19 Aug 2023 12:56:05 +0200 Subject: [PATCH 038/111] No command line option because Swift 5.7 (#61). --- .github/workflows/run-tests-on-linux.yml | 5 ----- .github/workflows/run-tests-on-macos.yml | 9 ++------- README.md | 9 ++------- Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift | 10 +++------- Sources/Numberick/Documentation.docc/Documentation.md | 10 +++------- 5 files changed, 10 insertions(+), 33 deletions(-) diff --git a/.github/workflows/run-tests-on-linux.yml b/.github/workflows/run-tests-on-linux.yml index c87fb10d..16c4b85c 100644 --- a/.github/workflows/run-tests-on-linux.yml +++ b/.github/workflows/run-tests-on-linux.yml @@ -13,9 +13,7 @@ jobs: matrix: element: - swift: '5.7' - withStaticBigInt: false - swift: '5.8' - withStaticBigInt: true runs-on: ubuntu-latest container: @@ -26,6 +24,3 @@ jobs: uses: actions/checkout@v3 - name: Test run: swift test - - name: Test with StaticBigInt - if: matrix.element.withStaticBigInt - run: swift test -Xswiftc -DSBI diff --git a/.github/workflows/run-tests-on-macos.yml b/.github/workflows/run-tests-on-macos.yml index 26f3896d..7b376ddf 100644 --- a/.github/workflows/run-tests-on-macos.yml +++ b/.github/workflows/run-tests-on-macos.yml @@ -14,20 +14,15 @@ jobs: element: - xcode: '14.2' machine: macos-12 - withStaticBigInt: false - xcode: '14.3' machine: macos-13 - withStaticBigInt: true runs-on: ${{ matrix.element.machine }} steps: - name: Checkout uses: actions/checkout@v3 - - name: Select Xcode + - name: Select Xcode Version run: sudo xcode-select -s /Applications/Xcode_${{ matrix.element.xcode }}.app - name: Test - run: swift test - - name: Test with StaticBigInt - if: matrix.element.withStaticBigInt - run: swift test -Xswiftc -DSBI + run: xcrun swift test diff --git a/README.md b/README.md index bcfefe27..0d690a0e 100644 --- a/README.md +++ b/README.md @@ -93,13 +93,8 @@ Int256(5) % Int(5), UInt256(5) % UInt(5) ### Feature: StaticBigInt (v0.10.0+) Because `StaticBigInt` [does not back-deploy][Apple/StaticBigInt/SE], it is gated -by [availability][Apple/StaticBigInt] and the compiler flag `SBI`. Setting the -constant `withStaticBigInt` to `true` in `Package.swift` enables it. Alternatively, -you can use the command line: - -``` -swift build -Xswiftc -DSBI -``` +by [availability][Apple/StaticBigInt] and a build condition. Setting the constant +`withStaticBigInt` to `true` in `Package.swift` enables it. > **Note**: You can use `StaticString` until `StaticBigInt` becomes available. diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift index 44a99b91..9f9d6c7d 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift @@ -83,13 +83,9 @@ import NBKCoreKit /// /// ### Feature: StaticBigInt (v0.10.0+) /// -/// Because `StaticBigInt` does not back-deploy, it is gated by availability and -/// the compiler flag `SBI`. Setting the constant `withStaticBigInt` to `true` in -/// `Package.swift` enables it. Alternatively, you can use the command line: -/// -/// ``` -/// swift build -Xswiftc -DSBI -/// ``` +/// Because `StaticBigInt` does not back-deploy, it is gated by availability +/// and a build condition. Setting the constant `withStaticBigInt` to `true` +/// in `Package.swift` enables it. /// /// - Note: You can use `StaticString` until `StaticBigInt` becomes available. /// diff --git a/Sources/Numberick/Documentation.docc/Documentation.md b/Sources/Numberick/Documentation.docc/Documentation.md index a55744d2..410ddafb 100644 --- a/Sources/Numberick/Documentation.docc/Documentation.md +++ b/Sources/Numberick/Documentation.docc/Documentation.md @@ -87,13 +87,9 @@ Int256(5) % Int(5), UInt256(5) % UInt(5) ### Feature: StaticBigInt (v0.10.0+) -Because `StaticBigInt` does not back-deploy, it is gated by availability and -the compiler flag `SBI`. Setting the constant `withStaticBigInt` to `true` in -`Package.swift` enables it. Alternatively, you can use the command line: - -``` -swift build -Xswiftc -DSBI -``` +Because `StaticBigInt` does not back-deploy, it is gated by availability +and a build condition. Setting the constant `withStaticBigInt` to `true` +in `Package.swift` enables it. - Note: You can use `StaticString` until `StaticBigInt` becomes available. From c031d6eed890edd5521786cd7eae7c1b21a5640d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sat, 19 Aug 2023 17:20:18 +0200 Subject: [PATCH 039/111] Cleanup (#62). `[U]Int` until `StaticBigInt` (#65). --- README.md | 4 ++-- .../NBKDoubleWidth+Literals.swift | 10 ++-------- Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift | 2 +- .../Documentation.docc/Documentation.md | 2 +- .../NBKDoubleWidth+Literals.swift | 18 ++++-------------- 5 files changed, 10 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 0d690a0e..e26d5df9 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,7 @@ Int256(5) % Int(5), UInt256(5) % UInt(5) > **Note**: The `Digit` type is `Int` when `Self` is signed, and `UInt` otherwise. -### Feature: StaticBigInt (v0.10.0+) +### ⭐️ Feature: StaticBigInt (v0.10.0) Because `StaticBigInt` [does not back-deploy][Apple/StaticBigInt/SE], it is gated by [availability][Apple/StaticBigInt] and a build condition. Setting the constant @@ -116,7 +116,7 @@ This project is inspired by [**Int128**][Apple/Int128] and [**DoubleWidth**][App [COR/B]: Tests/NBKCoreKitBenchmarks [DBL/B]: Tests/NBKDoubleWidthKitBenchmarks - + [Apple/StaticBigInt]: https://developer.apple.com/documentation/swift/staticbigint [Apple/StaticBigInt/SE]: https://github.com/apple/swift-evolution/blob/main/proposals/0368-staticbigint.md diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift index 3797df84..92f80d52 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift @@ -41,8 +41,8 @@ extension NBKDoubleWidth { #else - @inlinable public init(integerLiteral source: Swift.Int64) { - self.init(source) + @inlinable public init(integerLiteral source: Digit.IntegerLiteralType) { + self.init(digit: Digit(integerLiteral: source)) } #endif @@ -50,18 +50,12 @@ extension NBKDoubleWidth { // MARK: Details x String Literal Type //=------------------------------------------------------------------------= - #if SBI && swift(>=5.8) - @available(swift, deprecated: 5.8, message: "Use an integer literal instead.") - #endif @inlinable public init(stringLiteral source: StaticString) { if let value = Self(exactlyStringLiteral: source) { self = value } else { preconditionFailure("\(Self.description) cannot represent \(source)") } } - #if SBI && swift(>=5.8) - @available(swift, deprecated: 5.8, message: "Use an integer literal instead.") - #endif @inlinable init?(exactlyStringLiteral source: StaticString) { let value: Optional = source.withUTF8Buffer { utf8 in let components = NBK.makeIntegerComponentsByDecodingRadix(utf8: utf8) diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift index 9f9d6c7d..b3fbea9b 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift @@ -81,7 +81,7 @@ import NBKCoreKit /// /// - Note: The `Digit` type is `Int` when `Self` is signed, and `UInt` otherwise. /// -/// ### Feature: StaticBigInt (v0.10.0+) +/// ### ⭐️ Feature: StaticBigInt (v0.10.0+) /// /// Because `StaticBigInt` does not back-deploy, it is gated by availability /// and a build condition. Setting the constant `withStaticBigInt` to `true` diff --git a/Sources/Numberick/Documentation.docc/Documentation.md b/Sources/Numberick/Documentation.docc/Documentation.md index 410ddafb..99b20bc4 100644 --- a/Sources/Numberick/Documentation.docc/Documentation.md +++ b/Sources/Numberick/Documentation.docc/Documentation.md @@ -85,7 +85,7 @@ Int256(5) % Int(5), UInt256(5) % UInt(5) - Note: The `Digit` type is `Int` when `Self` is signed, and `UInt` otherwise. -### Feature: StaticBigInt (v0.10.0+) +### ⭐️ Feature: StaticBigInt (v0.10.0+) Because `StaticBigInt` does not back-deploy, it is gated by availability and a build condition. Setting the constant `withStaticBigInt` to `true` diff --git a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Literals.swift b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Literals.swift index c6692e24..e8266184 100644 --- a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Literals.swift +++ b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Literals.swift @@ -44,16 +44,11 @@ final class NBKDoubleWidthTestsOnLiteralsAsInt256: XCTestCase { XCTAssertEqual(T(exactlyIntegerLiteral: -0x8000000000000000000000000000000000000000000000000000000000000000), T.min) XCTAssertEqual(T(exactlyIntegerLiteral: -0x8000000000000000000000000000000000000000000000000000000000000001), nil) #else - XCTAssertEqual(T(integerLiteral: 0x7fffffffffffffff as Int64), T(x64: X(UInt64(Int64.max), 0, 0, 0))) - XCTAssertEqual(T(integerLiteral: 0x0000000000000000 as Int64), T(x64: X(UInt64(Int64( )), 0, 0, 0))) - XCTAssertEqual(T(integerLiteral: -0x0000000000000001 as Int64), ~T(x64: X(UInt64(Int64( )), 0, 0, 0))) - XCTAssertEqual(T(integerLiteral: -0x8000000000000000 as Int64), ~T(x64: X(UInt64(Int64.max), 0, 0, 0))) + XCTAssertEqual(T(integerLiteral: Int.max), T(x64: X(UInt64(Int.max), 0, 0, 0))) + XCTAssertEqual(T(integerLiteral: Int.min), ~T(x64: X(UInt64(Int.max), 0, 0, 0))) #endif } - #if SBI && swift(>=5.8) - @available(swift, deprecated: 5.8, message: "Use an integer literal instead.") - #endif func testFromStringLiteral() { XCTAssertEqual(T(x64: X( 0, 0, 0, 0)), "0x0000000000000000000000000000000000000000000000000000000000000000") XCTAssertEqual(T(x64: X(~0, 0, 0, 0)), "0x000000000000000000000000000000000000000000000000ffffffffffffffff") @@ -99,16 +94,11 @@ final class NBKDoubleWidthTestsOnLiteralsAsUInt256: XCTestCase { XCTAssertEqual(T(exactlyIntegerLiteral: 0x000000000000000000000000000000000000000000000000000000000000000000), T.min) XCTAssertEqual(T(exactlyIntegerLiteral: -0x000000000000000000000000000000000000000000000000000000000000000001), nil) #else - XCTAssertEqual(T(integerLiteral: 0x7fffffffffffffff as Int64), T(x64: X(UInt64(Int64.max), 0, 0, 0))) - XCTAssertEqual(T(integerLiteral: 0x0000000000000000 as Int64), T(x64: X(UInt64(Int64( )), 0, 0, 0))) - XCTAssertEqual(T(exactly: -0x0000000000000001 as Int64), nil) - XCTAssertEqual(T(exactly: -0x8000000000000000 as Int64), nil) + XCTAssertEqual(T(integerLiteral: UInt.max), T(x64: X(UInt64(UInt.max), 0, 0, 0))) + XCTAssertEqual(T(integerLiteral: UInt.min), T(x64: X(UInt64(UInt.min), 0, 0, 0))) #endif } - #if SBI && swift(>=5.8) - @available(swift, deprecated: 5.8, message: "Use an integer literal instead.") - #endif func testFromStringLiteral() { XCTAssertEqual(T(x64: X( 0, 0, 0, 0)), "0x0000000000000000000000000000000000000000000000000000000000000000") XCTAssertEqual(T(x64: X(~0, 0, 0, 0)), "0x000000000000000000000000000000000000000000000000ffffffffffffffff") From 0d044d2ce455c0c1d38de1009b248917493f525f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sun, 20 Aug 2023 09:00:42 +0200 Subject: [PATCH 040/111] Cleanup. --- .github/workflows/run-tests-on-linux.yml | 4 ++-- .github/workflows/run-tests-on-macos.yml | 4 ++-- README.md | 17 ++++++----------- Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift | 5 ++--- .../Documentation.docc/Documentation.md | 5 ++--- 5 files changed, 14 insertions(+), 21 deletions(-) diff --git a/.github/workflows/run-tests-on-linux.yml b/.github/workflows/run-tests-on-linux.yml index 16c4b85c..1fee9113 100644 --- a/.github/workflows/run-tests-on-linux.yml +++ b/.github/workflows/run-tests-on-linux.yml @@ -3,9 +3,9 @@ name: Run tests on Linux on: workflow_dispatch: push: - branches: ["main"] + branches: [main] pull_request: - branches: ["main"] + branches: [main] jobs: linux: diff --git a/.github/workflows/run-tests-on-macos.yml b/.github/workflows/run-tests-on-macos.yml index 7b376ddf..9114ee90 100644 --- a/.github/workflows/run-tests-on-macos.yml +++ b/.github/workflows/run-tests-on-macos.yml @@ -3,9 +3,9 @@ name: Run tests on macOS on: workflow_dispatch: push: - branches: ["main"] + branches: [main] pull_request: - branches: ["main"] + branches: [main] jobs: macos: diff --git a/README.md b/README.md index e26d5df9..ae49d71a 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,8 @@ | Package | Swift | iOS | Mac Catalyst | macOS | tvOS | watchOS | |:-------:|:-----:|:-----:|:------------:|:-----:|:-----:|:-------:| -| 0.10.0 | 5.7+ | 14.0+ | 14.0+ | 11.0+ | 14.0+ | 7.0+ | -| 0.9.0 | 5.7+ | 16.4+ | 16.4+ | 13.3+ | 16.4+ | 9.4+ | +| 0.10.0 | 5.7 | 14.0 | 14.0 | 11.0 | 14.0 | 7.0 | +| 0.9.0 | 5.7 | 16.4 | 16.4 | 13.3 | 16.4 | 9.4 | ## NBKCoreKit ([Sources][COR/S], [Tests][COR/T], [Benchmarks][COR/B]) @@ -92,9 +92,8 @@ Int256(5) % Int(5), UInt256(5) % UInt(5) ### ⭐️ Feature: StaticBigInt (v0.10.0) -Because `StaticBigInt` [does not back-deploy][Apple/StaticBigInt/SE], it is gated -by [availability][Apple/StaticBigInt] and a build condition. Setting the constant -`withStaticBigInt` to `true` in `Package.swift` enables it. +`StaticBigInt` [does not back-deploy][Apple/StaticBigInt/SE] and is disabled by default. +Set `withStaticBigInt` in `Package.swift` to enable it. > **Note**: You can use `StaticString` until `StaticBigInt` becomes available. @@ -116,12 +115,8 @@ This project is inspired by [**Int128**][Apple/Int128] and [**DoubleWidth**][App [COR/B]: Tests/NBKCoreKitBenchmarks [DBL/B]: Tests/NBKDoubleWidthKitBenchmarks - - -[Apple/StaticBigInt]: https://developer.apple.com/documentation/swift/staticbigint -[Apple/StaticBigInt/SE]: https://github.com/apple/swift-evolution/blob/main/proposals/0368-staticbigint.md - - + [Apple/Int128]: https://github.com/apple/swift/blob/main/stdlib/public/core/Int128.swift.gyb [Apple/DoubleWidth]: https://github.com/apple/swift/blob/main/test/Prototypes/DoubleWidth.swift.gyb +[Apple/StaticBigInt/SE]: https://github.com/apple/swift-evolution/blob/main/proposals/0368-staticbigint.md diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift index b3fbea9b..90590e83 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift @@ -83,9 +83,8 @@ import NBKCoreKit /// /// ### ⭐️ Feature: StaticBigInt (v0.10.0+) /// -/// Because `StaticBigInt` does not back-deploy, it is gated by availability -/// and a build condition. Setting the constant `withStaticBigInt` to `true` -/// in `Package.swift` enables it. +/// `StaticBigInt` does not back-deploy and is disabled by default. +/// Set `withStaticBigInt` in `Package.swift` to enable it. /// /// - Note: You can use `StaticString` until `StaticBigInt` becomes available. /// diff --git a/Sources/Numberick/Documentation.docc/Documentation.md b/Sources/Numberick/Documentation.docc/Documentation.md index 99b20bc4..47ce763c 100644 --- a/Sources/Numberick/Documentation.docc/Documentation.md +++ b/Sources/Numberick/Documentation.docc/Documentation.md @@ -87,9 +87,8 @@ Int256(5) % Int(5), UInt256(5) % UInt(5) ### ⭐️ Feature: StaticBigInt (v0.10.0+) -Because `StaticBigInt` does not back-deploy, it is gated by availability -and a build condition. Setting the constant `withStaticBigInt` to `true` -in `Package.swift` enables it. +`StaticBigInt` does not back-deploy and is disabled by default. +Set `withStaticBigInt` in `Package.swift` to enable it. - Note: You can use `StaticString` until `StaticBigInt` becomes available. From 4adc494d17a8d14d66f57b6e7c2665b1cd843aa0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sun, 20 Aug 2023 09:06:28 +0200 Subject: [PATCH 041/111] Cleanup. --- README.md | 4 +--- Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift | 3 +-- Sources/Numberick/Documentation.docc/Documentation.md | 3 +-- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index ae49d71a..861354fd 100644 --- a/README.md +++ b/README.md @@ -92,8 +92,7 @@ Int256(5) % Int(5), UInt256(5) % UInt(5) ### ⭐️ Feature: StaticBigInt (v0.10.0) -`StaticBigInt` [does not back-deploy][Apple/StaticBigInt/SE] and is disabled by default. -Set `withStaticBigInt` in `Package.swift` to enable it. +`StaticBigInt` is disabled by default. You enable it in `Package.swift`. > **Note**: You can use `StaticString` until `StaticBigInt` becomes available. @@ -119,4 +118,3 @@ This project is inspired by [**Int128**][Apple/Int128] and [**DoubleWidth**][App [Apple/Int128]: https://github.com/apple/swift/blob/main/stdlib/public/core/Int128.swift.gyb [Apple/DoubleWidth]: https://github.com/apple/swift/blob/main/test/Prototypes/DoubleWidth.swift.gyb -[Apple/StaticBigInt/SE]: https://github.com/apple/swift-evolution/blob/main/proposals/0368-staticbigint.md diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift index 90590e83..60628fcc 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift @@ -83,8 +83,7 @@ import NBKCoreKit /// /// ### ⭐️ Feature: StaticBigInt (v0.10.0+) /// -/// `StaticBigInt` does not back-deploy and is disabled by default. -/// Set `withStaticBigInt` in `Package.swift` to enable it. +/// `StaticBigInt` is disabled by default. You enable it in `Package.swift`. /// /// - Note: You can use `StaticString` until `StaticBigInt` becomes available. /// diff --git a/Sources/Numberick/Documentation.docc/Documentation.md b/Sources/Numberick/Documentation.docc/Documentation.md index 47ce763c..3529932d 100644 --- a/Sources/Numberick/Documentation.docc/Documentation.md +++ b/Sources/Numberick/Documentation.docc/Documentation.md @@ -87,8 +87,7 @@ Int256(5) % Int(5), UInt256(5) % UInt(5) ### ⭐️ Feature: StaticBigInt (v0.10.0+) -`StaticBigInt` does not back-deploy and is disabled by default. -Set `withStaticBigInt` in `Package.swift` to enable it. +`StaticBigInt` is disabled by default. You enable it in `Package.swift`. - Note: You can use `StaticString` until `StaticBigInt` becomes available. From 161ef829169c0cd6de5733d70611b8b4b663e7ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sun, 20 Aug 2023 09:50:10 +0200 Subject: [PATCH 042/111] Cleanup. --- .github/workflows/run-tests-on-macos.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/run-tests-on-macos.yml b/.github/workflows/run-tests-on-macos.yml index 9114ee90..9256aaa1 100644 --- a/.github/workflows/run-tests-on-macos.yml +++ b/.github/workflows/run-tests-on-macos.yml @@ -22,7 +22,7 @@ jobs: steps: - name: Checkout uses: actions/checkout@v3 - - name: Select Xcode Version + - name: Select Xcode ${{ matrix.element.xcode }} run: sudo xcode-select -s /Applications/Xcode_${{ matrix.element.xcode }}.app - name: Test run: xcrun swift test From 085881cca7655d90ba75950876fdbe93c65453a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sun, 20 Aug 2023 14:24:13 +0200 Subject: [PATCH 043/111] Cleanup. CocoaPods. Workflow. --- .github/workflows/deploy.yml | 41 ------ .../publish-specifications-on-cocoapods.yml | 31 +++++ .../run-lint-on-cocoapods-specifications.yml | 25 ++++ .github/workflows/test.yml | 123 ------------------ Numberick-NBKCoreKit.podspec | 45 +++++++ Numberick-NBKDoubleWidthKit.podspec | 51 ++++++++ Numberick.podspec | 43 ++++++ pods/Numberick-CoreKit.podspec | 42 ------ pods/Numberick-DoubleWidthKit.podspec | 45 ------- pods/Numberick.podspec | 35 ----- 10 files changed, 195 insertions(+), 286 deletions(-) delete mode 100644 .github/workflows/deploy.yml create mode 100644 .github/workflows/publish-specifications-on-cocoapods.yml create mode 100644 .github/workflows/run-lint-on-cocoapods-specifications.yml delete mode 100644 .github/workflows/test.yml create mode 100644 Numberick-NBKCoreKit.podspec create mode 100644 Numberick-NBKDoubleWidthKit.podspec create mode 100644 Numberick.podspec delete mode 100644 pods/Numberick-CoreKit.podspec delete mode 100644 pods/Numberick-DoubleWidthKit.podspec delete mode 100644 pods/Numberick.podspec diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml deleted file mode 100644 index 7eb8595b..00000000 --- a/.github/workflows/deploy.yml +++ /dev/null @@ -1,41 +0,0 @@ -name: Publish CocoaPods package -on: - release: - types: [created] -jobs: - publish: - runs-on: macos-13 - defaults: - run: - shell: bash - steps: - - name: Checkout - uses: actions/checkout@v3 - - name: Select Xcode - run: sudo xcode-select -s /Applications/Xcode_14.3.1.app - - name: Save version to podspecs - env: - VERSION_TAG: ${{ github.event.release.tag_name }} - run: | - VERSION=$(echo "${VERSION_TAG}" | sed "s|^v\(.*\)$|\1|g") - sed -i '' "s|[[:blank:]]*s\.version[[:blank:]].*|s.version = '${VERSION}'|g" pods/Numberick-CoreKit.podspec - sed -i '' "s|[[:blank:]]*s\.version[[:blank:]].*|s.version = '${VERSION}'|g" pods/Numberick-DoubleWidthKit.podspec - sed -i '' "s|[[:blank:]]*s\.version[[:blank:]].*|s.version = '${VERSION}'|g" pods/Numberick.podspec - echo "Updated version to: ${VERSION}" - - name: Set enabled features in this branch for CocoaPods - run: | - features=$(cat Package.swift | sed -n "s|^let[[:blank:]]*with\([a-zA-Z0-9\_]*\)[[:blank:]]*=[[:blank:]]*\(.*\)$|NBK_FEATURE_\1=\2|p") - echo "${features}" >> "$GITHUB_ENV" - echo "${features}" - - name: Publish 'Numberick-CoreKit' Pod - run: pod trunk push --allow-warnings --synchronous pods/Numberick-CoreKit.podspec - env: - COCOAPODS_TRUNK_TOKEN: ${{ secrets.COCOAPODS_TRUNK_TOKEN }} - - name: Publish 'Numberick-DoubleWidthKit' Pod - run: pod trunk push --allow-warnings --synchronous pods/Numberick-DoubleWidthKit.podspec - env: - COCOAPODS_TRUNK_TOKEN: ${{ secrets.COCOAPODS_TRUNK_TOKEN }} - - name: Publish 'Numberick' Pod - run: pod trunk push --allow-warnings --synchronous pods/Numberick.podspec - env: - COCOAPODS_TRUNK_TOKEN: ${{ secrets.COCOAPODS_TRUNK_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/publish-specifications-on-cocoapods.yml b/.github/workflows/publish-specifications-on-cocoapods.yml new file mode 100644 index 00000000..4304a8cb --- /dev/null +++ b/.github/workflows/publish-specifications-on-cocoapods.yml @@ -0,0 +1,31 @@ +name: Publish specifications on CocoaPods + +on: + workflow_dispatch: + release: + types: [created] + +jobs: + publish: + runs-on: macos-13 + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Select Xcode 14.3.1 + run: sudo xcode-select --switch /Applications/Xcode_14.3.1.app + + - name: Publish 'Numberick-NBKCoreKit' + run: pod trunk push --allow-warnings --synchronous Numberick-NBKCoreKit.podspec + env: + COCOAPODS_TRUNK_TOKEN: ${{ secrets.COCOAPODS_TRUNK_TOKEN }} + + - name: Publish 'Numberick-NBKDoubleWidthKit' + run: pod trunk push --allow-warnings --synchronous Numberick-NBKDoubleWidthKit.podspec + env: + COCOAPODS_TRUNK_TOKEN: ${{ secrets.COCOAPODS_TRUNK_TOKEN }} + + - name: Publish 'Numberick' + run: pod trunk push --allow-warnings --synchronous Numberick.podspec + env: + COCOAPODS_TRUNK_TOKEN: ${{ secrets.COCOAPODS_TRUNK_TOKEN }} diff --git a/.github/workflows/run-lint-on-cocoapods-specifications.yml b/.github/workflows/run-lint-on-cocoapods-specifications.yml new file mode 100644 index 00000000..615d4690 --- /dev/null +++ b/.github/workflows/run-lint-on-cocoapods-specifications.yml @@ -0,0 +1,25 @@ +name: Run lint on CocoaPods specifications + +on: + workflow_dispatch: + +jobs: + lint: + strategy: + matrix: + element: + - xcode: '14.3.1' + + runs-on: macOS-latest + + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Select Xcode ${{ matrix.element.xcode }} + run: sudo xcode-select --switch /Applications/Xcode_${{ matrix.element.xcode }}.app + - name: Lint Numberick-NBKCoreKit.podspec + run: pod lib lint --allow-warnings --fail-fast Numberick-NBKCoreKit.podspec + - name: Lint Numberick-NBKDoubleWidthKit.podspec + run: pod lib lint --allow-warnings --fail-fast Numberick-NBKDoubleWidthKit.podspec + - name: Lint Numberick.podspec + run: pod lib lint --allow-warnings --fail-fast Numberick.podspec diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml deleted file mode 100644 index b705716d..00000000 --- a/.github/workflows/test.yml +++ /dev/null @@ -1,123 +0,0 @@ -name: Build & Tests -on: [push, pull_request] -jobs: - macos: - strategy: - matrix: - tests: - - xcode: '14.2' - machine: macos-12 - features: '-StaticBigInt' - - xcode: '14.3' - machine: macos-13 - features: '-StaticBigInt' - - xcode: '14.3.1' - machine: macos-13 - features: '+StaticBigInt' - runs-on: ${{ matrix.tests.machine }} - defaults: - run: - shell: bash - steps: - - name: Checkout - uses: actions/checkout@v3 - - name: Create sources zip - run: | - tempfile=$(mktemp -u).zip - zip -r "${tempfile}" ./* - echo "SOURCES_ZIP=${tempfile}" >> "$GITHUB_ENV" - - name: Select Swift custom features - run: | - for feature in "${{ matrix.tests.features }}" - do - [ "${feature}" ] || continue - status=$([[ "${feature}" = -* ]] && echo "false" || echo "true") - feature="${feature:1}" - sed -i '' "s|^let[[:blank:]]*with${feature}[[:blank:]]*=.*$|let with${feature} = ${status}|g" Package.swift - echo "NBK_FEATURE_${feature}=${status}" >> "$GITHUB_ENV" - echo "${feature} = ${status}" - done - - name: Select Xcode - run: sudo xcode-select -s /Applications/Xcode_${{ matrix.tests.xcode }}.app - - name: Build and Test macOS - run: xcodebuild test -scheme 'Numberick' -destination "platform=macOS" - - name: Benchmarks macOS - run: xcodebuild test -scheme 'Numberick-Benchmarks' -destination "platform=macOS" - - name: Build and Test iOS Simulator - run: xcodebuild test -scheme 'Numberick' -destination "platform=iOS Simulator,name=iPhone 14" - - name: Benchmarks iOS Simulator - run: xcodebuild test -scheme 'Numberick-Benchmarks' -destination "platform=iOS Simulator,name=iPhone 14" - - name: Build and Test tvOS Simulator - run: xcodebuild test -scheme 'Numberick' -destination "platform=tvOS Simulator,name=Apple TV" - - name: Benchmarks tvOS Simulator - run: xcodebuild test -scheme 'Numberick-Benchmarks' -destination "platform=tvOS Simulator,name=Apple TV" - - name: Build and Test watchOS Simulator - run: xcodebuild test -scheme 'Numberick' -destination "platform=watchOS Simulator,name=Apple Watch Series 6 (40mm)" - - name: Benchmarks watchOS Simulator - run: xcodebuild test -scheme 'Numberick-Benchmarks' -destination "platform=watchOS Simulator,name=Apple Watch Series 6 (40mm)" - - name: Setup Local CocoaPods Repo - run: | - COCOAPODS_LOCAL_REPO=$(mktemp -d) - git init --bare -b main "$COCOAPODS_LOCAL_REPO" - git clone "$COCOAPODS_LOCAL_REPO" git_temp_dir - cd git_temp_dir - touch .gitignore && git add .gitignore && git commit -a -m "repo init" && git push - cd ../ && rm -rf git_temp_dir - pod repo add local "${COCOAPODS_LOCAL_REPO}" - pod repo update - echo "COCOAPODS_LOCAL_REPO=${COCOAPODS_LOCAL_REPO}" >> "$GITHUB_ENV" - - name: CocoaPods 'Numberick-CoreKit' Lint & Local Push - run: | - sed -i '' "s|[[:blank:]]*s\.source[[:blank:]].*|s.source = { :http => 'file://${SOURCES_ZIP}' \}|g" pods/Numberick-CoreKit.podspec - pod repo push --allow-warnings local pods/Numberick-CoreKit.podspec - pod repo update - - name: CocoaPods 'Numberick-DoubleWidthKit' Lint & Local Push - run: | - sed -i '' "s|[[:blank:]]*s\.source[[:blank:]].*|s.source = { :http => 'file://${SOURCES_ZIP}' \}|g" pods/Numberick-DoubleWidthKit.podspec - pod repo push --allow-warnings local pods/Numberick-DoubleWidthKit.podspec - pod repo update - - name: CocoaPods 'Numberick' Lint - run: | - cp pods/Numberick.podspec ./ - pod lib lint --allow-warnings --fail-fast --sources="local,https://cdn.cocoapods.org" Numberick.podspec - - name: Cleanup - if: always() - run: | - [ -f "${SOURCES_ZIP}" ] && rm -f "${SOURCES_ZIP}" - [ -d "${COCOAPODS_LOCAL_REPO}" ] && rm -rf "${COCOAPODS_LOCAL_REPO}" - rm -f Numberick.podspec - pod repo remove local - linux: - strategy: - matrix: - tests: - - swift: '5.7' - features: '-StaticBigInt' - - swift: '5.8' - features: '-StaticBigInt' - - swift: '5.8' - features: '+StaticBigInt' - runs-on: ubuntu-latest - defaults: - run: - shell: bash - container: - image: swift:${{ matrix.tests.swift }} - options: --cap-add=SYS_PTRACE --security-opt seccomp=unconfined --security-opt apparmor=unconfined - steps: - - name: Checkout - uses: actions/checkout@v3 - - name: Select Swift custom features - run: | - for feature in "${{ matrix.tests.features }}" - do - [ "${feature}" ] || continue - status=$([[ "${feature}" = -* ]] && echo "false" || echo "true") - feature="${feature:1}" - sed -i "s|^let[[:blank:]]*with${feature}[[:blank:]]*=.*$|let with${feature} = ${status}|g" Package.swift - echo "${feature} = ${status}" - done - - name: Build and Test - run: swift test - - name: Run Benchmarks - run: swift test -c release \ No newline at end of file diff --git a/Numberick-NBKCoreKit.podspec b/Numberick-NBKCoreKit.podspec new file mode 100644 index 00000000..d5d01719 --- /dev/null +++ b/Numberick-NBKCoreKit.podspec @@ -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. +#=-----------------------------------------------------------------------------= + +#*=============================================================================* +# MARK: * NBK x Core Kit +#*=============================================================================* + +Pod::Spec.new do |spec| + spec.version = "0.10.0" + spec.module_name = "NBKCoreKit" + spec.name = "Numberick-#{spec.module_name}" + spec.summary = "A new protocol hierarchy that refines Swift's standard library." + + spec.license = { :type => "Apache-2.0", :file => "LICENSE" } + spec.author = { "Oscar Byström Ericsson" => "oscbyspro@protonmail.com" } + + spec.homepage = "https://github.com/oscbyspro/Numberick" + spec.readme = "https://raw.githubusercontent.com/oscbyspro/Numberick/v#{spec.version}/README.md" + spec.documentation_url = "https://oscbyspro.github.io/Numberick/documentation/numberick/" + + spec.source = { :git => "https://github.com/oscbyspro/Numberick.git", :tag => "v#{spec.version}" } + spec.source_files = "Sources/#{spec.module_name}/**/*.swift" + + #=-------------------------------------------------------------------------= + # MARK: Requirements + #=-------------------------------------------------------------------------= + + spec.swift_version = "5.7" + spec.platforms = { :ios => "14.0", :osx => "11.0", :tvos => "14.0", :watchos => "7.0" } + + #=-------------------------------------------------------------------------= + # MARK: Tests + #=-------------------------------------------------------------------------= + + spec.test_spec "Tests" do |test_spec| + test_spec.source_files = "Tests/#{spec.module_name}Tests/**/*.swift" + test_spec.platforms = { :ios => "14.0", :osx => "11.0", :tvos => "14.0" } + end +end diff --git a/Numberick-NBKDoubleWidthKit.podspec b/Numberick-NBKDoubleWidthKit.podspec new file mode 100644 index 00000000..ee337e31 --- /dev/null +++ b/Numberick-NBKDoubleWidthKit.podspec @@ -0,0 +1,51 @@ +#=-----------------------------------------------------------------------------= +# This source file is part of the Numberick open source project. +# +# Copyright (c) 2023 Oscar Byström Ericsson +# Licensed under Apache License, Version 2.0 +# +# See http://www.apache.org/licenses/LICENSE-2.0 for license information. +#=-----------------------------------------------------------------------------= + +#*=============================================================================* +# MARK: * NBK x Double Width Kit +#*=============================================================================* + +Pod::Spec.new do |spec| + spec.version = "0.10.0" + spec.module_name = "NBKDoubleWidthKit" + spec.name = "Numberick-#{spec.module_name}" + spec.summary = "A composable, large, fixed-width, two's complement, binary integer." + + spec.license = { :type => "Apache-2.0", :file => "LICENSE" } + spec.author = { "Oscar Byström Ericsson" => "oscbyspro@protonmail.com" } + + spec.homepage = "https://github.com/oscbyspro/Numberick" + spec.readme = "https://raw.githubusercontent.com/oscbyspro/Numberick/v#{spec.version}/README.md" + spec.documentation_url = "https://oscbyspro.github.io/Numberick/documentation/numberick/" + + spec.source = { :git => "https://github.com/oscbyspro/Numberick.git", :tag => "v#{spec.version}" } + spec.source_files = "Sources/#{spec.module_name}/**/*.swift" + + #=-------------------------------------------------------------------------= + # MARK: Requirements + #=-------------------------------------------------------------------------= + + spec.swift_version = "5.7" + spec.platforms = { :ios => "14.0", :osx => "11.0", :tvos => "14.0", :watchos => "7.0" } + + #=-------------------------------------------------------------------------= + # MARK: Tests + #=-------------------------------------------------------------------------= + + spec.test_spec "Tests" do |test_spec| + test_spec.source_files = "Tests/#{spec.module_name}Tests/**/*.swift" + test_spec.platforms = { :ios => "14.0", :osx => "11.0", :tvos => "14.0" } + end + + #=-------------------------------------------------------------------------= + # MARK: Dependencies + #=-------------------------------------------------------------------------= + + spec.dependency "Numberick-NBKCoreKit", "#{spec.version}" +end diff --git a/Numberick.podspec b/Numberick.podspec new file mode 100644 index 00000000..5367bcab --- /dev/null +++ b/Numberick.podspec @@ -0,0 +1,43 @@ +#=-----------------------------------------------------------------------------= +# This source file is part of the Numberick open source project. +# +# Copyright (c) 2023 Oscar Byström Ericsson +# Licensed under Apache License, Version 2.0 +# +# See http://www.apache.org/licenses/LICENSE-2.0 for license information. +#=-----------------------------------------------------------------------------= + +#*=============================================================================* +# MARK: * NBK +#*=============================================================================* + +Pod::Spec.new do |spec| + spec.version = "0.10.0" + spec.name = "Numberick" + spec.module_name = "Numberick" + spec.summary = "✨ An arithmagick overhaul in Swift." + + spec.license = { :type => "Apache-2.0", :file => "LICENSE" } + spec.author = { "Oscar Byström Ericsson" => "oscbyspro@protonmail.com" } + + spec.homepage = "https://github.com/oscbyspro/Numberick" + spec.readme = "https://raw.githubusercontent.com/oscbyspro/Numberick/v#{spec.version}/README.md" + spec.documentation_url = "https://oscbyspro.github.io/Numberick/documentation/numberick/" + + spec.source = { :git => "https://github.com/oscbyspro/Numberick.git", :tag => "v#{spec.version}" } + spec.source_files = "Sources/#{spec.module_name}/**/*.swift" + + #=-------------------------------------------------------------------------= + # MARK: Requirements + #=-------------------------------------------------------------------------= + + spec.swift_version = "5.7" + spec.platforms = { :ios => "14.0", :osx => "11.0", :tvos => "14.0", :watchos => "7.0" } + + #=-------------------------------------------------------------------------= + # MARK: Dependencies + #=-------------------------------------------------------------------------= + + spec.dependency "Numberick-NBKCoreKit", "#{spec.version}" + spec.dependency "Numberick-NBKDoubleWidthKit", "#{spec.version}" +end diff --git a/pods/Numberick-CoreKit.podspec b/pods/Numberick-CoreKit.podspec deleted file mode 100644 index c1e54d62..00000000 --- a/pods/Numberick-CoreKit.podspec +++ /dev/null @@ -1,42 +0,0 @@ -Pod::Spec.new do |s| - s.name = 'Numberick-CoreKit' - s.version = '999.99.9' - s.summary = "A new protocol hierarchy that refines Swift's standard integer library." - - s.description = <<-DESC - A new protocol hierarchy that refines Swift's standard library. Core part of Numberick. - DESC - - s.homepage = 'https://github.com/oscbyspro/Numberick' - - s.license = { :type => 'Apache-2.0', :file => 'LICENSE' } - s.author = { 'Oscar Byström Ericsson' => 'oscbyspro@protonmail.com' } - s.source = { :git => 'https://github.com/oscbyspro/Numberick.git', :tag => "v#{s.version}" } - - base_platforms = { :ios => '14.0', :osx => '11.0', :tvos => '14.0' } - - s.platforms = base_platforms.merge({ :watchos => '7.0' }) - - s.module_name = 'NBKCoreKit' - - s.swift_version = '5.7' - - s.source_files = 'Sources/NBKCoreKit/**/*.swift' - - swift_custom_flags = '' - - if ENV['NBK_FEATURE_StaticBigInt'] == 'true' - base_platforms = { :ios => '16.4', :osx => '13.3', :tvos => '16.4' } - s.platforms = base_platforms.merge({ :watchos => '9.4' }) - s.swift_version = '5.8' - swift_custom_flags += 'SBI ' - end - - s.pod_target_xcconfig = { 'SWIFT_ACTIVE_COMPILATION_CONDITIONS' => swift_custom_flags } - - s.test_spec 'Tests' do |ts| - ts.platforms = base_platforms - ts.source_files = 'Tests/NBKCoreKitTests/**/*.swift' - ts.pod_target_xcconfig = { 'SWIFT_ACTIVE_COMPILATION_CONDITIONS' => swift_custom_flags } - end -end \ No newline at end of file diff --git a/pods/Numberick-DoubleWidthKit.podspec b/pods/Numberick-DoubleWidthKit.podspec deleted file mode 100644 index 7c10ced2..00000000 --- a/pods/Numberick-DoubleWidthKit.podspec +++ /dev/null @@ -1,45 +0,0 @@ -Pod::Spec.new do |s| - s.name = 'Numberick-DoubleWidthKit' - s.version = '999.99.9' - s.summary = "Generic software model for working with fixed-width integers larger than one machine word" - - s.description = <<-DESC - NBKDoubleWidth is a generic software model for working with fixed-width integers larger than one machine word. - Its bit width is double the bit width of its High component. Main part of Numberick. - DESC - - s.homepage = 'https://github.com/oscbyspro/Numberick' - - s.license = { :type => 'Apache-2.0', :file => 'LICENSE' } - s.author = { 'Oscar Byström Ericsson' => 'oscbyspro@protonmail.com' } - s.source = { :git => 'https://github.com/oscbyspro/Numberick.git', :tag => "v#{s.version}" } - - base_platforms = { :ios => '14.0', :osx => '11.0', :tvos => '14.0' } - - s.platforms = base_platforms.merge({ :watchos => '7.0' }) - - s.module_name = 'NBKDoubleWidthKit' - - s.swift_version = '5.7' - - s.source_files = 'Sources/NBKDoubleWidthKit/**/*.swift' - - swift_custom_flags = '' - - if ENV['NBK_FEATURE_StaticBigInt'] == 'true' - base_platforms = { :ios => '16.4', :osx => '13.3', :tvos => '16.4' } - s.platforms = base_platforms.merge({ :watchos => '9.4' }) - s.swift_version = '5.8' - swift_custom_flags += 'SBI ' - end - - s.pod_target_xcconfig = { 'SWIFT_ACTIVE_COMPILATION_CONDITIONS' => swift_custom_flags } - - s.dependency 'Numberick-CoreKit', "#{s.version}" - - s.test_spec 'Tests' do |ts| - ts.platforms = base_platforms - ts.source_files = 'Tests/NBKDoubleWidthKitTests/**/*.swift' - ts.pod_target_xcconfig = { 'SWIFT_ACTIVE_COMPILATION_CONDITIONS' => swift_custom_flags } - end -end \ No newline at end of file diff --git a/pods/Numberick.podspec b/pods/Numberick.podspec deleted file mode 100644 index 25ef9c85..00000000 --- a/pods/Numberick.podspec +++ /dev/null @@ -1,35 +0,0 @@ -Pod::Spec.new do |s| - s.name = 'Numberick' - s.version = '999.99.9' - s.summary = "A composable, large, fixed-width, two's complement, binary integer." - - s.description = <<-DESC - A generic software model for working with fixed-width integers larger than one machine word. - Main package. - DESC - - s.homepage = 'https://github.com/oscbyspro/Numberick' - - s.license = { :type => 'Apache-2.0', :file => 'LICENSE' } - s.author = { 'Oscar Byström Ericsson' => 'oscbyspro@protonmail.com' } - s.source = { :git => 'https://github.com/oscbyspro/Numberick.git', :tag => "v#{s.version}" } - - s.platforms = { :ios => '14.0', :osx => '11.0', :tvos => '14.0', :watchos => '7.0' } - - s.swift_version = '5.7' - - s.source_files = 'Sources/Numberick/**/*.swift' - - swift_custom_flags = '' - - if ENV['NBK_FEATURE_StaticBigInt'] == 'true' - s.platforms = { :ios => '16.4', :osx => '13.3', :tvos => '16.4', :watchos => '9.4' } - s.swift_version = '5.8' - swift_custom_flags += 'SBI ' - end - - s.pod_target_xcconfig = { 'SWIFT_ACTIVE_COMPILATION_CONDITIONS' => swift_custom_flags } - - s.dependency 'Numberick-CoreKit', "#{s.version}" - s.dependency 'Numberick-DoubleWidthKit', "#{s.version}" -end \ No newline at end of file From 082d109f27adf8d007c90c9c139e9c9d9a261d97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Mon, 21 Aug 2023 11:09:22 +0200 Subject: [PATCH 044/111] [CocoaPods] Yer a wizard (#52). --- .../run-lint-on-cocoapods-specifications.yml | 26 ++++++++++++------- Numberick-NBKCoreKit.podspec | 4 +-- Numberick-NBKDoubleWidthKit.podspec | 4 +-- Numberick.podspec | 13 ++++++++-- 4 files changed, 32 insertions(+), 15 deletions(-) diff --git a/.github/workflows/run-lint-on-cocoapods-specifications.yml b/.github/workflows/run-lint-on-cocoapods-specifications.yml index 615d4690..6c7069a0 100644 --- a/.github/workflows/run-lint-on-cocoapods-specifications.yml +++ b/.github/workflows/run-lint-on-cocoapods-specifications.yml @@ -2,24 +2,32 @@ name: Run lint on CocoaPods specifications on: workflow_dispatch: + push: + tags: + - 'CocoaPods-v[0-9]+.[0-9]+.[0-9]+' + - 'CocoaPods-v[0-9]+.[0-9]+.[0-9]+-*' jobs: - lint: + macos: strategy: matrix: element: - - xcode: '14.3.1' - - runs-on: macOS-latest + - xcode: '14.3' + machine: macos-13 + + runs-on: ${{ matrix.element.machine }} steps: - name: Checkout uses: actions/checkout@v3 - name: Select Xcode ${{ matrix.element.xcode }} run: sudo xcode-select --switch /Applications/Xcode_${{ matrix.element.xcode }}.app - - name: Lint Numberick-NBKCoreKit.podspec - run: pod lib lint --allow-warnings --fail-fast Numberick-NBKCoreKit.podspec - - name: Lint Numberick-NBKDoubleWidthKit.podspec - run: pod lib lint --allow-warnings --fail-fast Numberick-NBKDoubleWidthKit.podspec - name: Lint Numberick.podspec - run: pod lib lint --allow-warnings --fail-fast Numberick.podspec + run: | + DEPENDENCIES='' + DEPENDENCIES+=Numberick-NBKCoreKit.podspec, + DEPENDENCIES+=Numberick-NBKDoubleWidthKit.podspec, + pod lib lint Numberick.podspec \ + --allow-warnings \ + --fail-fast \ + --include-podspecs=\{$DEPENDENCIES\} diff --git a/Numberick-NBKCoreKit.podspec b/Numberick-NBKCoreKit.podspec index d5d01719..15363610 100644 --- a/Numberick-NBKCoreKit.podspec +++ b/Numberick-NBKCoreKit.podspec @@ -12,7 +12,7 @@ #*=============================================================================* Pod::Spec.new do |spec| - spec.version = "0.10.0" + spec.version = "0.10.0-alpha" spec.module_name = "NBKCoreKit" spec.name = "Numberick-#{spec.module_name}" spec.summary = "A new protocol hierarchy that refines Swift's standard library." @@ -24,7 +24,7 @@ Pod::Spec.new do |spec| spec.readme = "https://raw.githubusercontent.com/oscbyspro/Numberick/v#{spec.version}/README.md" spec.documentation_url = "https://oscbyspro.github.io/Numberick/documentation/numberick/" - spec.source = { :git => "https://github.com/oscbyspro/Numberick.git", :tag => "v#{spec.version}" } + spec.source = { :git => "https://github.com/oscbyspro/Numberick.git", :tag => "CocoaPods-v#{spec.version}" } spec.source_files = "Sources/#{spec.module_name}/**/*.swift" #=-------------------------------------------------------------------------= diff --git a/Numberick-NBKDoubleWidthKit.podspec b/Numberick-NBKDoubleWidthKit.podspec index ee337e31..11e113cc 100644 --- a/Numberick-NBKDoubleWidthKit.podspec +++ b/Numberick-NBKDoubleWidthKit.podspec @@ -12,7 +12,7 @@ #*=============================================================================* Pod::Spec.new do |spec| - spec.version = "0.10.0" + spec.version = "0.10.0-alpha" spec.module_name = "NBKDoubleWidthKit" spec.name = "Numberick-#{spec.module_name}" spec.summary = "A composable, large, fixed-width, two's complement, binary integer." @@ -24,7 +24,7 @@ Pod::Spec.new do |spec| spec.readme = "https://raw.githubusercontent.com/oscbyspro/Numberick/v#{spec.version}/README.md" spec.documentation_url = "https://oscbyspro.github.io/Numberick/documentation/numberick/" - spec.source = { :git => "https://github.com/oscbyspro/Numberick.git", :tag => "v#{spec.version}" } + spec.source = { :git => "https://github.com/oscbyspro/Numberick.git", :tag => "CocoaPods-v#{spec.version}" } spec.source_files = "Sources/#{spec.module_name}/**/*.swift" #=-------------------------------------------------------------------------= diff --git a/Numberick.podspec b/Numberick.podspec index 5367bcab..3b9d3cbe 100644 --- a/Numberick.podspec +++ b/Numberick.podspec @@ -12,7 +12,7 @@ #*=============================================================================* Pod::Spec.new do |spec| - spec.version = "0.10.0" + spec.version = "0.10.0-alpha" spec.name = "Numberick" spec.module_name = "Numberick" spec.summary = "✨ An arithmagick overhaul in Swift." @@ -24,7 +24,7 @@ Pod::Spec.new do |spec| spec.readme = "https://raw.githubusercontent.com/oscbyspro/Numberick/v#{spec.version}/README.md" spec.documentation_url = "https://oscbyspro.github.io/Numberick/documentation/numberick/" - spec.source = { :git => "https://github.com/oscbyspro/Numberick.git", :tag => "v#{spec.version}" } + spec.source = { :git => "https://github.com/oscbyspro/Numberick.git", :tag => "CocoaPods-v#{spec.version}" } spec.source_files = "Sources/#{spec.module_name}/**/*.swift" #=-------------------------------------------------------------------------= @@ -34,6 +34,15 @@ Pod::Spec.new do |spec| spec.swift_version = "5.7" spec.platforms = { :ios => "14.0", :osx => "11.0", :tvos => "14.0", :watchos => "7.0" } + #=-------------------------------------------------------------------------= + # MARK: Tests + #=-------------------------------------------------------------------------= + + spec.test_spec "Tests" do |test_spec| + test_spec.source_files = "Tests/*Tests/**/*.swift" + test_spec.platforms = { :ios => "14.0", :osx => "11.0", :tvos => "14.0" } + end + #=-------------------------------------------------------------------------= # MARK: Dependencies #=-------------------------------------------------------------------------= From 0c4354b6dd63a6863eb6ca21212354da9ea255e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Mon, 21 Aug 2023 12:24:04 +0200 Subject: [PATCH 045/111] Some cleanup and documentation. --- .../publish-specifications-on-cocoapods.yml | 6 ++--- .../run-lint-on-cocoapods-specifications.yml | 2 +- Sources/NBKCoreKit/NBKBinaryInteger.swift | 5 ++-- Sources/NBKCoreKit/Private/NBK+Text.swift | 6 ++--- .../NBKDoubleWidth+Literals.swift | 20 ++++++++++++++++ .../NBKDoubleWidth+Multiplication+Digit.swift | 24 +++++++++++++++++++ .../Documentation.docc/Documentation.md | 4 ++-- 7 files changed, 55 insertions(+), 12 deletions(-) diff --git a/.github/workflows/publish-specifications-on-cocoapods.yml b/.github/workflows/publish-specifications-on-cocoapods.yml index 4304a8cb..71f94a14 100644 --- a/.github/workflows/publish-specifications-on-cocoapods.yml +++ b/.github/workflows/publish-specifications-on-cocoapods.yml @@ -15,17 +15,17 @@ jobs: - name: Select Xcode 14.3.1 run: sudo xcode-select --switch /Applications/Xcode_14.3.1.app - - name: Publish 'Numberick-NBKCoreKit' + - name: Publish 'Numberick-NBKCoreKit.podspec' run: pod trunk push --allow-warnings --synchronous Numberick-NBKCoreKit.podspec env: COCOAPODS_TRUNK_TOKEN: ${{ secrets.COCOAPODS_TRUNK_TOKEN }} - - name: Publish 'Numberick-NBKDoubleWidthKit' + - name: Publish 'Numberick-NBKDoubleWidthKit.podspec' run: pod trunk push --allow-warnings --synchronous Numberick-NBKDoubleWidthKit.podspec env: COCOAPODS_TRUNK_TOKEN: ${{ secrets.COCOAPODS_TRUNK_TOKEN }} - - name: Publish 'Numberick' + - name: Publish 'Numberick.podspec' run: pod trunk push --allow-warnings --synchronous Numberick.podspec env: COCOAPODS_TRUNK_TOKEN: ${{ secrets.COCOAPODS_TRUNK_TOKEN }} diff --git a/.github/workflows/run-lint-on-cocoapods-specifications.yml b/.github/workflows/run-lint-on-cocoapods-specifications.yml index 6c7069a0..f52ef716 100644 --- a/.github/workflows/run-lint-on-cocoapods-specifications.yml +++ b/.github/workflows/run-lint-on-cocoapods-specifications.yml @@ -22,7 +22,7 @@ jobs: uses: actions/checkout@v3 - name: Select Xcode ${{ matrix.element.xcode }} run: sudo xcode-select --switch /Applications/Xcode_${{ matrix.element.xcode }}.app - - name: Lint Numberick.podspec + - name: Run lint on 'Numberick.podspec' run: | DEPENDENCIES='' DEPENDENCIES+=Numberick-NBKCoreKit.podspec, diff --git a/Sources/NBKCoreKit/NBKBinaryInteger.swift b/Sources/NBKCoreKit/NBKBinaryInteger.swift index c9469727..32684d2d 100644 --- a/Sources/NBKCoreKit/NBKBinaryInteger.swift +++ b/Sources/NBKCoreKit/NBKBinaryInteger.swift @@ -1210,9 +1210,8 @@ where Magnitude: NBKUnsignedInteger, Words: Sendable { /// Creates a new instance from the given `description` and `radix`. /// /// The `description` may contain a plus or minus sign (+ or -), followed by one - /// or more numeric digits (0-9) or letters (a-z or A-Z), according to the `radix`. - /// If the description uses an invalid format, or its value cannot be represented, - /// the result is nil. + /// or more numeric digits (0-9) or letters (a-z or A-Z). If the description uses + /// an invalid format, or its value cannot be represented, the result is nil. /// /// ``` /// ┌─────────────┬────── → ─────────────┐ diff --git a/Sources/NBKCoreKit/Private/NBK+Text.swift b/Sources/NBKCoreKit/Private/NBK+Text.swift index 1a936aa3..d067282c 100644 --- a/Sources/NBKCoreKit/Private/NBK+Text.swift +++ b/Sources/NBKCoreKit/Private/NBK+Text.swift @@ -20,9 +20,9 @@ extension NBK { /// Creates a new instance by truncating the given `digits` and `radix`. /// /// The sequence passed as `digits` may contain one or more numeric digits - /// (0-9) or letters (a-z or A-Z), according to the `radix`. If the sequence - /// passed as `digits` uses an invalid format, the result is nil. If the - /// sequence passed as `digits` cannot be represented, the result is truncated. + /// (0-9) or letters (a-z or A-Z). If the sequence passed as `digits` uses + /// an invalid format, the result is nil. If the sequence passed as `digits` + /// cannot be represented, the result is truncated. /// /// - Note: The decoding strategy is case insensitive. /// diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift index 92f80d52..2267d300 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift @@ -50,6 +50,26 @@ extension NBKDoubleWidth { // 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, the result is nil. + /// + /// ``` + /// ┌───────── → ─────────────┐ + /// │ literal │ self │ + /// ├───────── → ─────────────┤ + /// │ "123" │ Int256( 123) │ + /// │ "+0x123" │ Int256( 291) │ + /// │ "-0x123" │ Int256(-291) │ + /// │ "~OX123" │ nil │ + /// └───────── → ─────────────┘ + /// ``` + /// + /// - Note: The decoding strategy is case insensitive. + /// @inlinable public init(stringLiteral source: StaticString) { if let value = Self(exactlyStringLiteral: source) { self = value } else { preconditionFailure("\(Self.description) cannot represent \(source)") diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Multiplication+Digit.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Multiplication+Digit.swift index 9375d72c..3d2f4285 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Multiplication+Digit.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Multiplication+Digit.swift @@ -78,11 +78,19 @@ extension NBKDoubleWidth where High == High.Magnitude { // MARK: Transformations //=------------------------------------------------------------------------= + /// Forms the result of multiplication and addition. + /// + /// - Note: In the case of `overflow`, a runtime error may occur. + /// @_disfavoredOverload @inlinable public mutating func multiply(by other: Digit, add carry: Digit) { let overflow: Bool = self.multiplyReportingOverflow(by: other, add: carry) precondition(!overflow, NBK.callsiteOverflowInfo()) } + /// Returns the result of multiplication and addition. + /// + /// - Note: In the case of `overflow`, a runtime error may occur. + /// @_disfavoredOverload @inlinable public func multiplied(by other: Digit, adding carry: Digit) -> Self { let pvo: PVO = self.multipliedReportingOverflow(by: other, adding: carry) precondition(!pvo.overflow, NBK.callsiteOverflowInfo()) @@ -93,10 +101,18 @@ extension NBKDoubleWidth where High == High.Magnitude { // MARK: Transformations x Overflow //=------------------------------------------------------------------------= + /// Forms the result of multiplication and addition, and returns an `overflow` indicator. + /// + /// - Note: In the case of `overflow`, the result is truncated. + /// @_disfavoredOverload @inlinable public mutating func multiplyReportingOverflow(by other: Digit, add carry: Digit) -> Bool { !self.multiplyFullWidth(by: other, add: carry).isZero } + /// Returns the result of multiplication and addition, along with an `overflow` indicator. + /// + /// - Note: In the case of `overflow`, the result is truncated. + /// @_disfavoredOverload @inlinable public func multipliedReportingOverflow(by other: Digit, adding carry: Digit) -> PVO { var pvo = PVO(self, false) pvo.overflow = pvo.partialValue.multiplyReportingOverflow(by: other, add: carry) @@ -107,10 +123,18 @@ extension NBKDoubleWidth where High == High.Magnitude { // MARK: Transformations x Full Width //=------------------------------------------------------------------------= + /// Forms the `low` part of multiplication and addition, and returns the `high`. + /// + /// - Note: The `high` and `low` parts contain the entire `overflow` from `low` to `high`. + /// @_disfavoredOverload @inlinable public mutating func multiplyFullWidth(by other: Digit, add carry: Digit) -> Digit { NBK.multiplyFullWidthLenientUnsignedInteger(&self, by: other, add: carry) } + /// Returns the `low` and `high` parts of multiplication and addition. + /// + /// - Note: The `high` and `low` parts contain the entire `overflow` from `low` to `high`. + /// @_disfavoredOverload @inlinable public func multipliedFullWidth(by other: Digit, adding carry: Digit) -> HL { var product = HL(UInt.zero, self) product.high = product.low.multiplyFullWidth(by: other, add: carry) diff --git a/Sources/Numberick/Documentation.docc/Documentation.md b/Sources/Numberick/Documentation.docc/Documentation.md index 3529932d..47490712 100644 --- a/Sources/Numberick/Documentation.docc/Documentation.md +++ b/Sources/Numberick/Documentation.docc/Documentation.md @@ -1,10 +1,10 @@ # ``Numberick`` -Large number arithmagick in Swift. +✨ An arithmagick overhaul in Swift. ## NBKCoreKit -Models, protocols, and utilities underpinning this package. +A new protocol hierarchy that refines Swift's standard library. ### Protocols From a019baa93eb56dc59f465a334884e3918231ada8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Mon, 21 Aug 2023 18:16:49 +0200 Subject: [PATCH 046/111] `StaticString` documentation fix. --- .../NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift index 2267d300..8be749d4 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift @@ -52,10 +52,10 @@ extension NBKDoubleWidth { /// 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, the result is nil. + /// 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. /// /// ``` /// ┌───────── → ─────────────┐ @@ -64,7 +64,7 @@ extension NBKDoubleWidth { /// │ "123" │ Int256( 123) │ /// │ "+0x123" │ Int256( 291) │ /// │ "-0x123" │ Int256(-291) │ - /// │ "~OX123" │ nil │ + /// │ "~OX123" │ error │ /// └───────── → ─────────────┘ /// ``` /// From 07b3817907906fb7be6f90d1be1d9303b47ecbb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Tue, 22 Aug 2023 17:08:15 +0200 Subject: [PATCH 047/111] [Swift] Some trivial de/init stuff (#67). --- Sources/NBKCoreKit/Private/NBK+Limbs.swift | 2 + .../Private/NBK+Text+RadixUIntRoot.swift | 27 ++++++++------ Sources/NBKCoreKit/Private/NBK+Text.swift | 37 ++++++++++--------- .../NBKDoubleWidth+Text.swift | 18 ++++++--- .../NBKDoubleWidth+Uninitialized.swift | 2 +- 5 files changed, 50 insertions(+), 36 deletions(-) diff --git a/Sources/NBKCoreKit/Private/NBK+Limbs.swift b/Sources/NBKCoreKit/Private/NBK+Limbs.swift index 3d11f043..08222988 100644 --- a/Sources/NBKCoreKit/Private/NBK+Limbs.swift +++ b/Sources/NBKCoreKit/Private/NBK+Limbs.swift @@ -49,6 +49,7 @@ extension NBK { } } + // TODO: trivial type de/init is req. @discardableResult @inlinable static func minorLimbs(_ minorLimbs: inout B, majorLimbs: A, isSigned: Bool) -> B.Index where A: Collection, A.Element: NBKCoreInteger, B: MutableCollection, B.Element: NBKCoreInteger { precondition(A.Element.bitWidth.isPowerOf2) @@ -86,6 +87,7 @@ extension NBK { } } + // TODO: trivial type de/init is req. @discardableResult @inlinable static func majorLimbs(_ majorLimbs: inout B, minorLimbs: A, isSigned: Bool) -> B.Index where A: Collection, A.Element: NBKCoreInteger, B: MutableCollection, B.Element: NBKCoreInteger { precondition(A.Element.bitWidth.isPowerOf2) diff --git a/Sources/NBKCoreKit/Private/NBK+Text+RadixUIntRoot.swift b/Sources/NBKCoreKit/Private/NBK+Text+RadixUIntRoot.swift index 226be75b..d7fed51e 100644 --- a/Sources/NBKCoreKit/Private/NBK+Text+RadixUIntRoot.swift +++ b/Sources/NBKCoreKit/Private/NBK+Text+RadixUIntRoot.swift @@ -246,32 +246,35 @@ extension NBK { //=--------------------------------------= let capacity: Int = UInt.bitWidth.trailingZeroBitCount - 1 return Swift.withUnsafeTemporaryAllocation(of: Solution.self, capacity: capacity) { squares in + var solution = Solution(1, radix) + let start = squares.baseAddress! + var position = start as UnsafeMutablePointer //=----------------------------------= - // de/init: pointee is trivial + // pointee: initialization //=----------------------------------= - var solution = Solution(1, radix) - var index = squares.startIndex as Int - - loop: while index < squares.endIndex { - squares[index] = solution + loop: while true { + position.initialize(to: solution) let product = solution.power.multipliedReportingOverflow(by: solution.power) if product.overflow { break loop } solution.exponent &<<= 1 as UInt solution.power = product.partialValue - squares.formIndex(after: &index) + position = position.successor() } - - loop: while index > squares.startIndex { - squares.formIndex(before: &index) - let square = squares[index] + //=----------------------------------= + // pointee: deinitialization by move + //=----------------------------------= + assert(position <= start.advanced(by: squares.count)) + loop: while position > start { + position = position.predecessor() + let square = position.move() let product = solution.power.multipliedReportingOverflow(by: square.power) if product.overflow { continue loop } solution.exponent &+= square.exponent solution.power = product.partialValue } - + //=----------------------------------= return solution as Solution } } diff --git a/Sources/NBKCoreKit/Private/NBK+Text.swift b/Sources/NBKCoreKit/Private/NBK+Text.swift index d067282c..ad062894 100644 --- a/Sources/NBKCoreKit/Private/NBK+Text.swift +++ b/Sources/NBKCoreKit/Private/NBK+Text.swift @@ -64,20 +64,20 @@ extension NBK { //=--------------------------------------= var remainders = chunks[...] let mostSignificantChunk = remainders.popLast() ?? UInt() - return NBK.withIntegerTextUnchecked(chunk: mostSignificantChunk, radix: radix, alphabet: alphabet) { first in + return NBK.withUnsafeTemporaryIntegerTextUnchecked(chunk: mostSignificantChunk, radix: radix, alphabet: alphabet) { first in var count: Int count = prefix.count count += first .count count += remainders.count * radix.exponent count += suffix.count return String(unsafeUninitializedCapacity: count) { utf8 in + var position = utf8.baseAddress!.advanced(by: count) //=------------------------------= - // de/init: pointee is trivial + // pointee: initialization //=------------------------------= - var index = count as Int func pull(_ unit: UInt8) { - utf8.formIndex(before: &index) - utf8[index] = unit + position = position.predecessor() + position.initialize(to: unit) } //=------------------------------= suffix.reversed().forEach(pull) @@ -93,9 +93,8 @@ extension NBK { first .reversed().forEach(pull) prefix.reversed().forEach(pull) //=------------------------------= - assert(utf8.startIndex == index) - assert(utf8[index..(chunk: UInt, radix: some _NBKRadixUIntRoot, - alphabet: MaxRadixAlphabetEncoder, body: (NBK.UnsafeUTF8) -> T) -> T { + @inlinable public static func withUnsafeTemporaryIntegerTextUnchecked( + chunk: UInt, radix: some _NBKRadixUIntRoot, alphabet: MaxRadixAlphabetEncoder, body: (NBK.UnsafeUTF8) -> T) -> T { assert(radix.power.isZero || chunk < radix.power, "chunks must be less than radix's power") return Swift.withUnsafeTemporaryAllocation(of: UInt8.self, capacity: radix.exponent) { utf8 in - //=----------------------------------= - // de/init: pointee is trivial - //=----------------------------------= var chunk = chunk as UInt - var index = radix.exponent as Int + let end = utf8.baseAddress!.advanced(by: radix.exponent) + var start = end as UnsafeMutablePointer + //=----------------------------------= + // pointee: initialization //=----------------------------------= backwards: repeat { let digit: UInt (chunk, digit) = radix.dividing(chunk) - utf8.formIndex(before: &index) - utf8[index] = alphabet.encode(UInt8(truncatingIfNeeded: digit))! + start = start.predecessor() + start.initialize(to: alphabet.encode(UInt8(truncatingIfNeeded: digit))!) } while !chunk.isZero //=----------------------------------= - return body(NBK.UnsafeUTF8(rebasing: utf8[index...])) + // pointee: deferred deinitialization + //=----------------------------------= + let count: Int = start.distance(to: end) + defer{ start.deinitialize (count: count) } + return body(NBK.UnsafeUTF8(start: start, count: count)) } } } diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text.swift index dce1e7d5..d9457609 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text.swift @@ -135,20 +135,26 @@ extension NBKDoubleWidth where High == High.Magnitude { //=--------------------------------------= let capacity: Int = radix.divisibilityByPowerUpperBound(self) return Swift.withUnsafeTemporaryAllocation(of: UInt.self, capacity: capacity) { buffer in - //=----------------------------------= - // de/init: pointee is trivial //=----------------------------------= var magnitude: Magnitude = self - var index: Int = buffer.startIndex + let start = buffer.baseAddress! + var position = start as UnsafeMutablePointer + //=----------------------------------= + // pointee: initialization //=----------------------------------= rebasing: while !magnitude.isZero { let (remainder, overflow) = magnitude.formQuotientWithRemainderReportingOverflow(dividingBy: radix.power) - buffer[index] = remainder - buffer.formIndex(after: &index) + position.initialize(to: remainder) + position = position.successor() assert(!overflow) } //=----------------------------------= - let chunks = NBK.UnsafeWords(rebasing: buffer[.. Void) -> Self { Swift.withUnsafeTemporaryAllocation(of: Self.self, capacity: 1) { buffer in //=----------------------------------= - // de/init: pointee is trivial + // TODO: trivial type de/init is req. //=----------------------------------= body( &buffer.baseAddress.unsafelyUnwrapped.pointee) return buffer.baseAddress.unsafelyUnwrapped.pointee From 7635b04487ce0b1059c36f058c21c9d82d674c00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Wed, 23 Aug 2023 07:40:33 +0200 Subject: [PATCH 048/111] [Swift] Major limbs sequence (#67). --- Sources/NBKCoreKit/Private/NBK+Limbs.swift | 135 +++++++++++++-------- 1 file changed, 87 insertions(+), 48 deletions(-) diff --git a/Sources/NBKCoreKit/Private/NBK+Limbs.swift b/Sources/NBKCoreKit/Private/NBK+Limbs.swift index 08222988..9e7262db 100644 --- a/Sources/NBKCoreKit/Private/NBK+Limbs.swift +++ b/Sources/NBKCoreKit/Private/NBK+Limbs.swift @@ -21,14 +21,14 @@ extension NBK { -> Array where A: Collection, A.Element: NBKCoreInteger, BE: NBKCoreInteger { switch A.Element.bitWidth >= BE.bitWidth { case true: return NBK.minorLimbs(majorLimbs: source, isSigned: isSigned, as: type) - case false: return NBK.majorLimbs(minorLimbs: source, isSigned: isSigned, as: type) } + case false: return Array(MajorLimbs(minorLimbs: source, isSigned: isSigned, as: BE.self)) } } @inlinable public static func limbs(_ source: A, isSigned: Bool = false, as type: ContiguousArray.Type = ContiguousArray.self) -> ContiguousArray where A: Collection, A.Element: NBKCoreInteger, BE: NBKCoreInteger { switch A.Element.bitWidth >= BE.bitWidth { case true: return NBK.minorLimbs(majorLimbs: source, isSigned: isSigned, as: type) - case false: return NBK.majorLimbs(minorLimbs: source, isSigned: isSigned, as: type) } + case false: return ContiguousArray(MajorLimbs(minorLimbs: source, isSigned: isSigned, as: BE.self)) } } //=------------------------------------------------------------------------= @@ -67,57 +67,96 @@ extension NBK { return (minorLimbsIndex) as B.Index } - //=------------------------------------------------------------------------= - // MARK: Details x Major - //=------------------------------------------------------------------------= - - @inlinable static func majorLimbs(minorLimbs: A, isSigned: Bool, as type: Array.Type) - -> Array where A: Collection, A.Element: NBKCoreInteger, BE: NBKCoreInteger { - let count = minorLimbs.count.quotientAndRemainder(dividingBy: BE.bitWidth / A.Element.bitWidth) - return Array(unsafeUninitializedCapacity: count.quotient + Int(bit: !count.remainder.isZero)) { - $1 = NBK.majorLimbs(&$0, minorLimbs: minorLimbs, isSigned: isSigned) - } - } + //*========================================================================* + // MARK: * Major Limbs + //*========================================================================* - @inlinable static func majorLimbs(minorLimbs: A, isSigned: Bool, as type: ContiguousArray.Type) - -> ContiguousArray where A: Collection, A.Element: NBKCoreInteger, BE: NBKCoreInteger { - let count = minorLimbs.count.quotientAndRemainder(dividingBy: BE.bitWidth / A.Element.bitWidth) - return ContiguousArray(unsafeUninitializedCapacity: count.quotient + Int(bit: !count.remainder.isZero)) { - $1 = NBK.majorLimbs(&$0, minorLimbs: minorLimbs, isSigned: isSigned) + @frozen @usableFromInline struct MajorLimbs: Sequence where + MajorLimb: NBKCoreInteger, MinorLimbs: Sequence, MinorLimbs.Element: NBKCoreInteger { + + @usableFromInline typealias MinorLimb = MinorLimbs.Element + + //=--------------------------------------------------------------------= + // MARK: State + //=--------------------------------------------------------------------= + + @usableFromInline let minorLimbs: MinorLimbs + @usableFromInline let isSigned: Bool + + //=--------------------------------------------------------------------= + // MARK: Initializers + //=--------------------------------------------------------------------= + + @inlinable init(minorLimbs: MinorLimbs, isSigned: Bool, as type: MajorLimb.Type = MajorLimb.self) { + //=--------------------------------------= + precondition(MinorLimb.bitWidth.isPowerOf2) + precondition(MajorLimb.bitWidth.isPowerOf2) + precondition(MinorLimb.bitWidth <= MajorLimb.bitWidth) + //=--------------------------------------= + self.isSigned = isSigned + self.minorLimbs = minorLimbs } - } - - // TODO: trivial type de/init is req. - @discardableResult @inlinable static func majorLimbs(_ majorLimbs: inout B, minorLimbs: A, isSigned: Bool) - -> B.Index where A: Collection, A.Element: NBKCoreInteger, B: MutableCollection, B.Element: NBKCoreInteger { - precondition(A.Element.bitWidth.isPowerOf2) - precondition(B.Element.bitWidth.isPowerOf2) - precondition(A.Element.bitWidth <= B.Element.bitWidth) - //=--------------------------------------= - var majorLimb = B.Element.zero - var minorLimb = A.Element.Magnitude.zero - var minorLimbsShift = Int.zero - var majorLimbsIndex = majorLimbs.startIndex - for minorLimbsIndex in minorLimbs.indices { - minorLimb = A.Element.Magnitude(bitPattern: minorLimbs[minorLimbsIndex]) - majorLimb |= B.Element(truncatingIfNeeded: minorLimb) &<< minorLimbsShift - - do{ minorLimbsShift += A.Element.bitWidth } - if minorLimbsShift == B.Element.bitWidth { - majorLimbs[majorLimbsIndex] = majorLimb - majorLimbs.formIndex(after: &majorLimbsIndex) - majorLimb = B.Element.zero - minorLimbsShift = Int.zero - } + + //=--------------------------------------------------------------------= + // MARK: Utilities + //=--------------------------------------------------------------------= + + /// Returns the exact count when `minorLimbs.underestimatedCount` does. + @inlinable var underestimatedCount: Int { + let ratio = MajorLimb.bitWidth / MinorLimb.bitWidth + let division = minorLimbs.underestimatedCount.quotientAndRemainder(dividingBy: ratio) + return division.quotient + Int(bit: !division.remainder.isZero) } - if !minorLimbsShift.isZero { - let sign = B.Element(repeating: isSigned && minorLimb.mostSignificantBit) - majorLimb |= (sign &<< minorLimbsShift) - majorLimbs[majorLimbsIndex] = majorLimb - majorLimbs.formIndex(after: &majorLimbsIndex) + @inlinable func makeIterator() -> Iterator { + Iterator(minorLimbs: self.minorLimbs, isSigned: self.isSigned) } - return (majorLimbsIndex) as B.Index + //*====================================================================* + // MARK: * Iterator + //*====================================================================* + + @frozen @usableFromInline struct Iterator: IteratorProtocol { + + //=----------------------------------------------------------------= + // MARK: State + //=----------------------------------------------------------------= + + @usableFromInline var minorLimbs: MinorLimbs.Iterator + @usableFromInline let isSigned: Bool + + //=----------------------------------------------------------------= + // MARK: Initializers + //=----------------------------------------------------------------= + + @inlinable init(minorLimbs: MinorLimbs, isSigned: Bool) { + self.isSigned = isSigned + self.minorLimbs = minorLimbs.makeIterator() + } + + //=----------------------------------------------------------------= + // MARK: Utilities + //=----------------------------------------------------------------= + + @inlinable mutating func next() -> MajorLimb? { + var majorLimb = MajorLimb.zero + var minorLimb = MinorLimb.Magnitude.zero + var minorLimbsShift = Int.zero + + while let next = self.minorLimbs.next() { + minorLimb = MinorLimb.Magnitude(bitPattern: next) + majorLimb |= MajorLimb(truncatingIfNeeded: minorLimb) &<< minorLimbsShift + + do{ minorLimbsShift += MinorLimb.bitWidth } + if minorLimbsShift == MajorLimb.bitWidth { + return majorLimb + } + } + + guard !minorLimbsShift.isZero else { return nil } + majorLimb |= (MajorLimb(repeating: self.isSigned && minorLimb.mostSignificantBit) &<< minorLimbsShift) + return majorLimb as MajorLimb + } + } } } From 8e4505fc073f30977f172743862cb94ee9424cbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Wed, 23 Aug 2023 07:42:16 +0200 Subject: [PATCH 049/111] [Swift] Minor limbs sequence (#67). --- Sources/NBKCoreKit/Private/NBK+Limbs.swift | 141 ++++++++++++++++----- 1 file changed, 110 insertions(+), 31 deletions(-) diff --git a/Sources/NBKCoreKit/Private/NBK+Limbs.swift b/Sources/NBKCoreKit/Private/NBK+Limbs.swift index 9e7262db..b6ed363f 100644 --- a/Sources/NBKCoreKit/Private/NBK+Limbs.swift +++ b/Sources/NBKCoreKit/Private/NBK+Limbs.swift @@ -20,51 +20,130 @@ extension NBK { @inlinable public static func limbs(_ source: A, isSigned: Bool = false, as type: Array.Type = Array.self) -> Array where A: Collection, A.Element: NBKCoreInteger, BE: NBKCoreInteger { switch A.Element.bitWidth >= BE.bitWidth { - case true: return NBK.minorLimbs(majorLimbs: source, isSigned: isSigned, as: type) - case false: return Array(MajorLimbs(minorLimbs: source, isSigned: isSigned, as: BE.self)) } + case true: return Array(MinorLimbs(majorLimbs: source)) + case false: return Array(MajorLimbs(minorLimbs: source, isSigned: isSigned)) } } @inlinable public static func limbs(_ source: A, isSigned: Bool = false, as type: ContiguousArray.Type = ContiguousArray.self) -> ContiguousArray where A: Collection, A.Element: NBKCoreInteger, BE: NBKCoreInteger { switch A.Element.bitWidth >= BE.bitWidth { - case true: return NBK.minorLimbs(majorLimbs: source, isSigned: isSigned, as: type) - case false: return ContiguousArray(MajorLimbs(minorLimbs: source, isSigned: isSigned, as: BE.self)) } + case true: return ContiguousArray(MinorLimbs(majorLimbs: source)) + case false: return ContiguousArray(MajorLimbs(minorLimbs: source, isSigned: isSigned)) } } - //=------------------------------------------------------------------------= - // MARK: Details x Minor - //=------------------------------------------------------------------------= + //*========================================================================* + // MARK: * Minor Limbs + //*========================================================================* - @inlinable static func minorLimbs(majorLimbs: A, isSigned: Bool, as type: Array.Type) - -> Array where A: Collection, A.Element: NBKCoreInteger, BE: NBKCoreInteger { - Array(unsafeUninitializedCapacity: A.Element.bitWidth / BE.bitWidth * majorLimbs.count) { - $1 = NBK.minorLimbs(&$0, majorLimbs: majorLimbs, isSigned: isSigned) + @frozen @usableFromInline struct MinorLimbs: Sequence where + MinorLimb: NBKCoreInteger, MajorLimbs: Sequence, MajorLimbs.Element: NBKCoreInteger { + + @usableFromInline typealias MajorLimb = MajorLimbs.Element + + //=--------------------------------------------------------------------= + // MARK: State + //=--------------------------------------------------------------------= + + @usableFromInline let majorLimbs: MajorLimbs + + //=--------------------------------------------------------------------= + // MARK: Initializers + //=--------------------------------------------------------------------= + + @inlinable init(majorLimbs: MajorLimbs, as type: MinorLimb.Type = MinorLimb.self) { + //=--------------------------------------= + precondition(MinorLimb.bitWidth.isPowerOf2) + precondition(MajorLimb.bitWidth.isPowerOf2) + precondition(MinorLimb.bitWidth <= MajorLimb.bitWidth) + //=--------------------------------------= + self.majorLimbs = majorLimbs } - } - - @inlinable static func minorLimbs(majorLimbs: A, isSigned: Bool, as type: ContiguousArray.Type) - -> ContiguousArray where A: Collection, A.Element: NBKCoreInteger, BE: NBKCoreInteger { - ContiguousArray(unsafeUninitializedCapacity: A.Element.bitWidth / BE.bitWidth * majorLimbs.count) { - $1 = NBK.minorLimbs(&$0, majorLimbs: majorLimbs, isSigned: isSigned) + + //=--------------------------------------------------------------------= + // MARK: Utilities + //=--------------------------------------------------------------------= + + /// Returns the exact count when `minorLimbs.underestimatedCount` does. + @inlinable var underestimatedCount: Int { + MajorLimb.bitWidth / MinorLimb.bitWidth * self.majorLimbs.underestimatedCount + } + + @inlinable func makeIterator() -> some IteratorProtocol { + self.majorLimbs.lazy.flatMap({ MinorLimbsSubSequence(majorLimb: $0) }).makeIterator() } } - // TODO: trivial type de/init is req. - @discardableResult @inlinable static func minorLimbs(_ minorLimbs: inout B, majorLimbs: A, isSigned: Bool) - -> B.Index where A: Collection, A.Element: NBKCoreInteger, B: MutableCollection, B.Element: NBKCoreInteger { - precondition(A.Element.bitWidth.isPowerOf2) - precondition(B.Element.bitWidth.isPowerOf2) - precondition(A.Element.bitWidth >= B.Element.bitWidth) - //=--------------------------------------= - var minorLimbsIndex = minorLimbs.startIndex - for majorLimb in majorLimbs { - for majorLimbsShift in stride(from: Int.zero, to: A.Element.bitWidth, by: B.Element.bitWidth) { - minorLimbs[minorLimbsIndex] = B.Element(truncatingIfNeeded: majorLimb &>> majorLimbsShift) - minorLimbs.formIndex(after: &minorLimbsIndex) - } + //*========================================================================* + // MARK: * Minor Limbs Sub Sequence + //*========================================================================* + + @frozen @usableFromInline struct MinorLimbsSubSequence: + Sequence where MinorLimb: NBKCoreInteger, MajorLimb: NBKCoreInteger { + + //=--------------------------------------------------------------------= + // MARK: State + //=--------------------------------------------------------------------= + + @usableFromInline let majorLimb: MajorLimb + + //=--------------------------------------------------------------------= + // MARK: Initializers + //=--------------------------------------------------------------------= + + @inlinable init(majorLimb: MajorLimb, as type: MinorLimb.Type = MinorLimb.self) { + //=--------------------------------------= + precondition(MinorLimb.bitWidth.isPowerOf2) + precondition(MajorLimb.bitWidth.isPowerOf2) + precondition(MinorLimb.bitWidth <= MajorLimb.bitWidth) + //=--------------------------------------= + self.majorLimb = majorLimb } - return (minorLimbsIndex) as B.Index + //=--------------------------------------------------------------------= + // MARK: Utilities + //=--------------------------------------------------------------------= + + /// Returns the exact count. + @inlinable var underestimatedCount: Int { + MajorLimb.bitWidth / MinorLimb.bitWidth + } + + @inlinable func makeIterator() -> Iterator { + Iterator(majorLimb: self.majorLimb) + } + + //*====================================================================* + // MARK: * Iterator + //*====================================================================* + + @frozen @usableFromInline struct Iterator: IteratorProtocol { + + //=----------------------------------------------------------------= + // MARK: State + //=----------------------------------------------------------------= + + @usableFromInline let majorLimb: MajorLimb + @usableFromInline var majorLimbShift: Int + + //=----------------------------------------------------------------= + // MARK: Initializers + //=----------------------------------------------------------------= + + @inlinable init(majorLimb: MajorLimb) { + self.majorLimb = majorLimb + self.majorLimbShift = Int.zero + } + + //=----------------------------------------------------------------= + // MARK: Utilities + //=----------------------------------------------------------------= + + @inlinable mutating func next() -> MinorLimb? { + guard self.majorLimbShift < MajorLimb.bitWidth else { return nil } + defer{ self.majorLimbShift += MinorLimb.bitWidth } + return MinorLimb(truncatingIfNeeded: self.majorLimb &>> self.majorLimbShift) + } + } } //*========================================================================* From 92959304b4c0d908db9e95078dc6dec546bb112a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Wed, 23 Aug 2023 11:29:47 +0200 Subject: [PATCH 050/111] [NBKCoreKit] MajorOrMinorLimbsSequence. --- Sources/NBKCoreKit/Private/NBK+Limbs.swift | 261 ++++++++++++------ .../Private/NBK+Limbs.swift | 8 +- Tests/NBKCoreKitTests/Private/NBK+Limbs.swift | 60 ++-- 3 files changed, 197 insertions(+), 132 deletions(-) diff --git a/Sources/NBKCoreKit/Private/NBK+Limbs.swift b/Sources/NBKCoreKit/Private/NBK+Limbs.swift index b6ed363f..9ff8a3ee 100644 --- a/Sources/NBKCoreKit/Private/NBK+Limbs.swift +++ b/Sources/NBKCoreKit/Private/NBK+Limbs.swift @@ -13,145 +13,102 @@ extension NBK { - //=------------------------------------------------------------------------= - // MARK: Details - //=------------------------------------------------------------------------= - - @inlinable public static func limbs(_ source: A, isSigned: Bool = false, as type: Array.Type = Array.self) - -> Array where A: Collection, A.Element: NBKCoreInteger, BE: NBKCoreInteger { - switch A.Element.bitWidth >= BE.bitWidth { - case true: return Array(MinorLimbs(majorLimbs: source)) - case false: return Array(MajorLimbs(minorLimbs: source, isSigned: isSigned)) } - } - - @inlinable public static func limbs(_ source: A, isSigned: Bool = false, as type: ContiguousArray.Type = ContiguousArray.self) - -> ContiguousArray where A: Collection, A.Element: NBKCoreInteger, BE: NBKCoreInteger { - switch A.Element.bitWidth >= BE.bitWidth { - case true: return ContiguousArray(MinorLimbs(majorLimbs: source)) - case false: return ContiguousArray(MajorLimbs(minorLimbs: source, isSigned: isSigned)) } - } - //*========================================================================* - // MARK: * Minor Limbs + // MARK: * Major Or Minor Limbs Sequence //*========================================================================* - @frozen @usableFromInline struct MinorLimbs: Sequence where - MinorLimb: NBKCoreInteger, MajorLimbs: Sequence, MajorLimbs.Element: NBKCoreInteger { - - @usableFromInline typealias MajorLimb = MajorLimbs.Element - - //=--------------------------------------------------------------------= - // MARK: State - //=--------------------------------------------------------------------= - - @usableFromInline let majorLimbs: MajorLimbs - - //=--------------------------------------------------------------------= - // MARK: Initializers - //=--------------------------------------------------------------------= - - @inlinable init(majorLimbs: MajorLimbs, as type: MinorLimb.Type = MinorLimb.self) { - //=--------------------------------------= - precondition(MinorLimb.bitWidth.isPowerOf2) - precondition(MajorLimb.bitWidth.isPowerOf2) - precondition(MinorLimb.bitWidth <= MajorLimb.bitWidth) - //=--------------------------------------= - self.majorLimbs = majorLimbs - } + @frozen public struct MajorOrMinorLimbsSequence: Sequence where + Limb: NBKCoreInteger, Source: Sequence, Source.Element: NBKCoreInteger { - //=--------------------------------------------------------------------= - // MARK: Utilities - //=--------------------------------------------------------------------= + @usableFromInline typealias MinorLimbs = NBK.MinorLimbsSequence - /// Returns the exact count when `minorLimbs.underestimatedCount` does. - @inlinable var underestimatedCount: Int { - MajorLimb.bitWidth / MinorLimb.bitWidth * self.majorLimbs.underestimatedCount - } + @usableFromInline typealias MajorLimbs = NBK.MajorLimbsSequence - @inlinable func makeIterator() -> some IteratorProtocol { - self.majorLimbs.lazy.flatMap({ MinorLimbsSubSequence(majorLimb: $0) }).makeIterator() - } - } - - //*========================================================================* - // MARK: * Minor Limbs Sub Sequence - //*========================================================================* - - @frozen @usableFromInline struct MinorLimbsSubSequence: - Sequence where MinorLimb: NBKCoreInteger, MajorLimb: NBKCoreInteger { - //=--------------------------------------------------------------------= // MARK: State //=--------------------------------------------------------------------= + // note: parallel optionals appears to be faster than a combined enum + //=--------------------------------------------------------------------= - @usableFromInline let majorLimb: MajorLimb + @usableFromInline let minorLimbs: MinorLimbs? + @usableFromInline let majorLimbs: MajorLimbs? //=--------------------------------------------------------------------= // MARK: Initializers //=--------------------------------------------------------------------= - @inlinable init(majorLimb: MajorLimb, as type: MinorLimb.Type = MinorLimb.self) { - //=--------------------------------------= - precondition(MinorLimb.bitWidth.isPowerOf2) - precondition(MajorLimb.bitWidth.isPowerOf2) - precondition(MinorLimb.bitWidth <= MajorLimb.bitWidth) - //=--------------------------------------= - self.majorLimb = majorLimb + @inlinable public init(_ source: Source, isSigned: Bool = false) { + if Limb.bitWidth < Source.Element.bitWidth { + self.minorLimbs = MinorLimbs(majorLimbs: source) + self.majorLimbs = nil + } else { + self.minorLimbs = nil + self.majorLimbs = MajorLimbs(minorLimbs: source, isSigned: isSigned) + } } //=--------------------------------------------------------------------= // MARK: Utilities //=--------------------------------------------------------------------= - /// Returns the exact count. - @inlinable var underestimatedCount: Int { - MajorLimb.bitWidth / MinorLimb.bitWidth + @inlinable public var underestimatedCount: Int { + if Limb.bitWidth < Source.Element.bitWidth { + return self.minorLimbs!.underestimatedCount + } else { + return self.majorLimbs!.underestimatedCount + } } - @inlinable func makeIterator() -> Iterator { - Iterator(majorLimb: self.majorLimb) + @inlinable public func makeIterator() -> Iterator { + if Limb.bitWidth < Source.Element.bitWidth { + return Iterator(minorLimbs: self.minorLimbs!.makeIterator()) + } else { + return Iterator(majorLimbs: self.majorLimbs!.makeIterator()) + } } //*====================================================================* // MARK: * Iterator //*====================================================================* - @frozen @usableFromInline struct Iterator: IteratorProtocol { + @frozen public struct Iterator: IteratorProtocol { //=----------------------------------------------------------------= // MARK: State //=----------------------------------------------------------------= - @usableFromInline let majorLimb: MajorLimb - @usableFromInline var majorLimbShift: Int + @usableFromInline var minorLimbs: MinorLimbs.Iterator? + @usableFromInline var majorLimbs: MajorLimbs.Iterator? //=----------------------------------------------------------------= // MARK: Initializers //=----------------------------------------------------------------= - @inlinable init(majorLimb: MajorLimb) { - self.majorLimb = majorLimb - self.majorLimbShift = Int.zero + @inlinable init(minorLimbs: MinorLimbs.Iterator? = nil, majorLimbs: MajorLimbs.Iterator? = nil) { + self.minorLimbs = minorLimbs + self.majorLimbs = majorLimbs } //=----------------------------------------------------------------= // MARK: Utilities //=----------------------------------------------------------------= - @inlinable mutating func next() -> MinorLimb? { - guard self.majorLimbShift < MajorLimb.bitWidth else { return nil } - defer{ self.majorLimbShift += MinorLimb.bitWidth } - return MinorLimb(truncatingIfNeeded: self.majorLimb &>> self.majorLimbShift) + @inlinable public mutating func next() -> Limb? { + if Limb.bitWidth < Source.Element.bitWidth { + return self.minorLimbs!.next() + } else { + return self.majorLimbs!.next() + } } } } //*========================================================================* - // MARK: * Major Limbs + // MARK: * Major Limbs Sequence //*========================================================================* - @frozen @usableFromInline struct MajorLimbs: Sequence where - MajorLimb: NBKCoreInteger, MinorLimbs: Sequence, MinorLimbs.Element: NBKCoreInteger { + @frozen public struct MajorLimbsSequence: Sequence + where MajorLimb: NBKCoreInteger, MinorLimbs: Sequence, MinorLimbs.Element: NBKCoreInteger { @usableFromInline typealias MinorLimb = MinorLimbs.Element @@ -166,7 +123,7 @@ extension NBK { // MARK: Initializers //=--------------------------------------------------------------------= - @inlinable init(minorLimbs: MinorLimbs, isSigned: Bool, as type: MajorLimb.Type = MajorLimb.self) { + @inlinable public init(minorLimbs: MinorLimbs, isSigned: Bool = false, as majorLimb: MajorLimb.Type = MajorLimb.self) { //=--------------------------------------= precondition(MinorLimb.bitWidth.isPowerOf2) precondition(MajorLimb.bitWidth.isPowerOf2) @@ -181,13 +138,13 @@ extension NBK { //=--------------------------------------------------------------------= /// Returns the exact count when `minorLimbs.underestimatedCount` does. - @inlinable var underestimatedCount: Int { + @inlinable public var underestimatedCount: Int { let ratio = MajorLimb.bitWidth / MinorLimb.bitWidth let division = minorLimbs.underestimatedCount.quotientAndRemainder(dividingBy: ratio) return division.quotient + Int(bit: !division.remainder.isZero) } - @inlinable func makeIterator() -> Iterator { + @inlinable public func makeIterator() -> Iterator { Iterator(minorLimbs: self.minorLimbs, isSigned: self.isSigned) } @@ -195,7 +152,7 @@ extension NBK { // MARK: * Iterator //*====================================================================* - @frozen @usableFromInline struct Iterator: IteratorProtocol { + @frozen public struct Iterator: IteratorProtocol { //=----------------------------------------------------------------= // MARK: State @@ -217,7 +174,7 @@ extension NBK { // MARK: Utilities //=----------------------------------------------------------------= - @inlinable mutating func next() -> MajorLimb? { + @inlinable public mutating func next() -> MajorLimb? { var majorLimb = MajorLimb.zero var minorLimb = MinorLimb.Magnitude.zero var minorLimbsShift = Int.zero @@ -238,4 +195,124 @@ extension NBK { } } } + + //*========================================================================* + // MARK: * Minor Limbs + //*========================================================================* + + @frozen public struct MinorLimbsSequence: Sequence where + MinorLimb: NBKCoreInteger, MajorLimbs: Sequence, MajorLimbs.Element: NBKCoreInteger { + + public typealias MajorLimb = MajorLimbs.Element + + public typealias MinorLimbsSubSequence = NBK.MinorLimbsSubSequence + + public typealias Iterator = FlattenSequence>.Iterator + + //=--------------------------------------------------------------------= + // MARK: State + //=--------------------------------------------------------------------= + + @usableFromInline let majorLimbs: MajorLimbs + + //=--------------------------------------------------------------------= + // MARK: Initializers + //=--------------------------------------------------------------------= + + @inlinable public init(majorLimbs: MajorLimbs, as minorLimb: MinorLimb.Type = MinorLimb.self) { + //=--------------------------------------= + precondition(MinorLimb.bitWidth.isPowerOf2) + precondition(MajorLimb.bitWidth.isPowerOf2) + precondition(MinorLimb.bitWidth <= MajorLimb.bitWidth) + //=--------------------------------------= + self.majorLimbs = majorLimbs + } + + //=--------------------------------------------------------------------= + // MARK: Utilities + //=--------------------------------------------------------------------= + + /// Returns the exact count when `majorLimbs.underestimatedCount` does. + @inlinable public var underestimatedCount: Int { + MajorLimb.bitWidth / MinorLimb.bitWidth * self.majorLimbs.underestimatedCount + } + + @inlinable public func makeIterator() -> Iterator { + // this type is not opaque because the type inferance seeems to fail otherwise :( + self.majorLimbs.lazy.flatMap({ MinorLimbsSubSequence(majorLimb: $0) }).makeIterator() + } + } + + //*========================================================================* + // MARK: * Minor Limbs Sub Sequence + //*========================================================================* + + @frozen public struct MinorLimbsSubSequence: + Sequence where MinorLimb: NBKCoreInteger, MajorLimb: NBKCoreInteger { + + //=--------------------------------------------------------------------= + // MARK: State + //=--------------------------------------------------------------------= + + @usableFromInline let majorLimb: MajorLimb + + //=--------------------------------------------------------------------= + // MARK: Initializers + //=--------------------------------------------------------------------= + + @inlinable public init(majorLimb: MajorLimb, as minorLimb: MinorLimb.Type = MinorLimb.self) { + //=--------------------------------------= + precondition(MinorLimb.bitWidth.isPowerOf2) + precondition(MajorLimb.bitWidth.isPowerOf2) + precondition(MinorLimb.bitWidth <= MajorLimb.bitWidth) + //=--------------------------------------= + self.majorLimb = majorLimb + } + + //=--------------------------------------------------------------------= + // MARK: Utilities + //=--------------------------------------------------------------------= + + /// Returns the exact count. + @inlinable public var underestimatedCount: Int { + MajorLimb.bitWidth / MinorLimb.bitWidth + } + + @inlinable public func makeIterator() -> Iterator { + Iterator(majorLimb: self.majorLimb) + } + + //*====================================================================* + // MARK: * Iterator + //*====================================================================* + + @frozen public struct Iterator: IteratorProtocol { + + //=----------------------------------------------------------------= + // MARK: State + //=----------------------------------------------------------------= + + @usableFromInline let majorLimb: MajorLimb + @usableFromInline var majorLimbShift: Int + + //=----------------------------------------------------------------= + // MARK: Initializers + //=----------------------------------------------------------------= + + @inlinable init(majorLimb: MajorLimb) { + self.majorLimb = majorLimb + self.majorLimbShift = Int.zero + } + + //=----------------------------------------------------------------= + // MARK: Utilities + //=----------------------------------------------------------------= + + @inlinable public mutating func next() -> MinorLimb? { + guard self.majorLimbShift < MajorLimb.bitWidth else { return nil } + defer{ self.majorLimbShift += MinorLimb.bitWidth } + return MinorLimb(truncatingIfNeeded: self.majorLimb &>> self.majorLimbShift) + } + } + } } diff --git a/Tests/NBKCoreKitBenchmarks/Private/NBK+Limbs.swift b/Tests/NBKCoreKitBenchmarks/Private/NBK+Limbs.swift index 6c6107fa..17b9965f 100644 --- a/Tests/NBKCoreKitBenchmarks/Private/NBK+Limbs.swift +++ b/Tests/NBKCoreKitBenchmarks/Private/NBK+Limbs.swift @@ -31,8 +31,8 @@ final class NBKBenchmarksOnLimbs: XCTestCase { var xyz = NBK.blackHoleIdentity([~1, ~2, ~3, ~4] as X) for _ in 0 ..< 1_000_000 { - NBK.blackHole(NBK.limbs(abc, as: Y.self)) - NBK.blackHole(NBK.limbs(xyz, as: Y.self)) + NBK.blackHole(Y(NBK.MajorOrMinorLimbsSequence(abc))) + NBK.blackHole(Y(NBK.MajorOrMinorLimbsSequence(xyz))) NBK.blackHoleInoutIdentity(&abc) NBK.blackHoleInoutIdentity(&xyz) @@ -44,8 +44,8 @@ final class NBKBenchmarksOnLimbs: XCTestCase { var xyz = NBK.blackHoleIdentity([~1, ~0, ~2, ~0, ~3, ~0, ~4, ~0] as Y) for _ in 0 ..< 1_000_000 { - NBK.blackHole(NBK.limbs(abc, as: X.self)) - NBK.blackHole(NBK.limbs(xyz, as: X.self)) + NBK.blackHole(X(NBK.MajorOrMinorLimbsSequence(abc))) + NBK.blackHole(X(NBK.MajorOrMinorLimbsSequence(xyz))) NBK.blackHoleInoutIdentity(&abc) NBK.blackHoleInoutIdentity(&xyz) diff --git a/Tests/NBKCoreKitTests/Private/NBK+Limbs.swift b/Tests/NBKCoreKitTests/Private/NBK+Limbs.swift index a8fc915a..0609e9c9 100644 --- a/Tests/NBKCoreKitTests/Private/NBK+Limbs.swift +++ b/Tests/NBKCoreKitTests/Private/NBK+Limbs.swift @@ -159,35 +159,27 @@ file: StaticString = #file, line: UInt = #line) { let rhsUnsigned = rhs.map(B.Magnitude.init(bitPattern:)) //=------------------------------------------= if isSigned == nil || isSigned == true { - XCTAssertEqual(NBK.limbs( (lhs), isSigned: true ), (rhs), file: file, line: line) - XCTAssertEqual(NBK.limbs( (lhsUnsigned), isSigned: true ), (rhsUnsigned), file: file, line: line) - XCTAssertEqual(NBK.limbs(X(lhs), isSigned: true ), X(rhs), file: file, line: line) - XCTAssertEqual(NBK.limbs(X(lhsUnsigned), isSigned: true ), X(rhsUnsigned), file: file, line: line) - XCTAssertEqual(NBK.limbs(Y(lhs), isSigned: true ), Y(rhs), file: file, line: line) - XCTAssertEqual(NBK.limbs(Y(lhsUnsigned), isSigned: true ), Y(rhsUnsigned), file: file, line: line) + XCTAssertEqual(X(NBK.MajorOrMinorLimbsSequence(X(lhs), isSigned: true )), X(rhs), file: file, line: line) + XCTAssertEqual(X(NBK.MajorOrMinorLimbsSequence(X(lhsUnsigned), isSigned: true )), X(rhsUnsigned), file: file, line: line) + XCTAssertEqual(Y(NBK.MajorOrMinorLimbsSequence(Y(lhs), isSigned: true )), Y(rhs), file: file, line: line) + XCTAssertEqual(Y(NBK.MajorOrMinorLimbsSequence(Y(lhsUnsigned), isSigned: true )), Y(rhsUnsigned), file: file, line: line) - XCTAssertEqual(NBK.limbs( (rhs), isSigned: true ), (lhs), file: file, line: line) - XCTAssertEqual(NBK.limbs( (rhsUnsigned), isSigned: true ), (lhsUnsigned), file: file, line: line) - XCTAssertEqual(NBK.limbs(X(rhs), isSigned: true ), X(lhs), file: file, line: line) - XCTAssertEqual(NBK.limbs(X(rhsUnsigned), isSigned: true ), X(lhsUnsigned), file: file, line: line) - XCTAssertEqual(NBK.limbs(Y(rhs), isSigned: true ), Y(lhs), file: file, line: line) - XCTAssertEqual(NBK.limbs(Y(rhsUnsigned), isSigned: true ), Y(lhsUnsigned), file: file, line: line) + XCTAssertEqual(X(NBK.MajorOrMinorLimbsSequence(X(rhs), isSigned: true )), X(lhs), file: file, line: line) + XCTAssertEqual(X(NBK.MajorOrMinorLimbsSequence(X(rhsUnsigned), isSigned: true )), X(lhsUnsigned), file: file, line: line) + XCTAssertEqual(Y(NBK.MajorOrMinorLimbsSequence(Y(rhs), isSigned: true )), Y(lhs), file: file, line: line) + XCTAssertEqual(Y(NBK.MajorOrMinorLimbsSequence(Y(rhsUnsigned), isSigned: true )), Y(lhsUnsigned), file: file, line: line) } if isSigned == nil || isSigned == false { - XCTAssertEqual(NBK.limbs( (lhs), isSigned: true ), (rhs), file: file, line: line) - XCTAssertEqual(NBK.limbs( (lhsUnsigned), isSigned: true ), (rhsUnsigned), file: file, line: line) - XCTAssertEqual(NBK.limbs(X(lhs), isSigned: true ), X(rhs), file: file, line: line) - XCTAssertEqual(NBK.limbs(X(lhsUnsigned), isSigned: true ), X(rhsUnsigned), file: file, line: line) - XCTAssertEqual(NBK.limbs(Y(lhs), isSigned: true ), Y(rhs), file: file, line: line) - XCTAssertEqual(NBK.limbs(Y(lhsUnsigned), isSigned: true ), Y(rhsUnsigned), file: file, line: line) + XCTAssertEqual(X(NBK.MajorOrMinorLimbsSequence(X(lhs), isSigned: true )), X(rhs), file: file, line: line) + XCTAssertEqual(X(NBK.MajorOrMinorLimbsSequence(X(lhsUnsigned), isSigned: true )), X(rhsUnsigned), file: file, line: line) + XCTAssertEqual(Y(NBK.MajorOrMinorLimbsSequence(Y(lhs), isSigned: true )), Y(rhs), file: file, line: line) + XCTAssertEqual(Y(NBK.MajorOrMinorLimbsSequence(Y(lhsUnsigned), isSigned: true )), Y(rhsUnsigned), file: file, line: line) - XCTAssertEqual(NBK.limbs( (rhs), isSigned: false), (lhs), file: file, line: line) - XCTAssertEqual(NBK.limbs( (rhsUnsigned), isSigned: false), (lhsUnsigned), file: file, line: line) - XCTAssertEqual(NBK.limbs(X(rhs), isSigned: false), X(lhs), file: file, line: line) - XCTAssertEqual(NBK.limbs(X(rhsUnsigned), isSigned: false), X(lhsUnsigned), file: file, line: line) - XCTAssertEqual(NBK.limbs(Y(rhs), isSigned: false), Y(lhs), file: file, line: line) - XCTAssertEqual(NBK.limbs(Y(rhsUnsigned), isSigned: false), Y(lhsUnsigned), file: file, line: line) + XCTAssertEqual(X(NBK.MajorOrMinorLimbsSequence(X(rhs), isSigned: false)), X(lhs), file: file, line: line) + XCTAssertEqual(X(NBK.MajorOrMinorLimbsSequence(X(rhsUnsigned), isSigned: false)), X(lhsUnsigned), file: file, line: line) + XCTAssertEqual(Y(NBK.MajorOrMinorLimbsSequence(Y(rhs), isSigned: false)), Y(lhs), file: file, line: line) + XCTAssertEqual(Y(NBK.MajorOrMinorLimbsSequence(Y(rhsUnsigned), isSigned: false)), Y(lhsUnsigned), file: file, line: line) } } @@ -202,21 +194,17 @@ file: StaticString = #file, line: UInt = #line) { let rhsUnsigned = rhs.map(B.Magnitude.init(bitPattern:)) //=------------------------------------------= if isSigned == nil || isSigned == true { - XCTAssertEqual(NBK.limbs( (lhs), isSigned: true ), (rhs), file: file, line: line) - XCTAssertEqual(NBK.limbs( (lhsUnsigned), isSigned: true ), (rhsUnsigned), file: file, line: line) - XCTAssertEqual(NBK.limbs(X(lhs), isSigned: true ), X(rhs), file: file, line: line) - XCTAssertEqual(NBK.limbs(X(lhsUnsigned), isSigned: true ), X(rhsUnsigned), file: file, line: line) - XCTAssertEqual(NBK.limbs(Y(lhs), isSigned: true ), Y(rhs), file: file, line: line) - XCTAssertEqual(NBK.limbs(Y(lhsUnsigned), isSigned: true ), Y(rhsUnsigned), file: file, line: line) + XCTAssertEqual(X(NBK.MajorOrMinorLimbsSequence(X(lhs), isSigned: true )), X(rhs), file: file, line: line) + XCTAssertEqual(X(NBK.MajorOrMinorLimbsSequence(X(lhsUnsigned), isSigned: true )), X(rhsUnsigned), file: file, line: line) + XCTAssertEqual(Y(NBK.MajorOrMinorLimbsSequence(Y(lhs), isSigned: true )), Y(rhs), file: file, line: line) + XCTAssertEqual(Y(NBK.MajorOrMinorLimbsSequence(Y(lhsUnsigned), isSigned: true )), Y(rhsUnsigned), file: file, line: line) } if isSigned == nil || isSigned == false { - XCTAssertEqual(NBK.limbs( (lhs), isSigned: false), (rhs), file: file, line: line) - XCTAssertEqual(NBK.limbs( (lhsUnsigned), isSigned: false), (rhsUnsigned), file: file, line: line) - XCTAssertEqual(NBK.limbs(X(lhs), isSigned: false), X(rhs), file: file, line: line) - XCTAssertEqual(NBK.limbs(X(lhsUnsigned), isSigned: false), X(rhsUnsigned), file: file, line: line) - XCTAssertEqual(NBK.limbs(Y(lhs), isSigned: false), Y(rhs), file: file, line: line) - XCTAssertEqual(NBK.limbs(Y(lhsUnsigned), isSigned: false), Y(rhsUnsigned), file: file, line: line) + XCTAssertEqual(X(NBK.MajorOrMinorLimbsSequence(X(lhs), isSigned: false)), X(rhs), file: file, line: line) + XCTAssertEqual(X(NBK.MajorOrMinorLimbsSequence(X(lhsUnsigned), isSigned: false)), X(rhsUnsigned), file: file, line: line) + XCTAssertEqual(Y(NBK.MajorOrMinorLimbsSequence(Y(lhs), isSigned: false)), Y(rhs), file: file, line: line) + XCTAssertEqual(Y(NBK.MajorOrMinorLimbsSequence(Y(lhsUnsigned), isSigned: false)), Y(rhsUnsigned), file: file, line: line) } } From 50761c38bcddbd6945329214054bbdbdb974ab59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Wed, 23 Aug 2023 19:46:52 +0200 Subject: [PATCH 051/111] Cleanup. --- Sources/NBKCoreKit/Private/NBK+Limbs.swift | 26 ++++++++++++------- Sources/NBKCoreKit/Private/NBK+Text.swift | 14 +++++----- .../NBKDoubleWidth+Text.swift | 4 +-- 3 files changed, 25 insertions(+), 19 deletions(-) diff --git a/Sources/NBKCoreKit/Private/NBK+Limbs.swift b/Sources/NBKCoreKit/Private/NBK+Limbs.swift index 9ff8a3ee..cddd2ed1 100644 --- a/Sources/NBKCoreKit/Private/NBK+Limbs.swift +++ b/Sources/NBKCoreKit/Private/NBK+Limbs.swift @@ -27,7 +27,7 @@ extension NBK { //=--------------------------------------------------------------------= // MARK: State //=--------------------------------------------------------------------= - // note: parallel optionals appears to be faster than a combined enum + // note: two parallel options appear to be faster than a combined enum //=--------------------------------------------------------------------= @usableFromInline let minorLimbs: MinorLimbs? @@ -37,7 +37,7 @@ extension NBK { // MARK: Initializers //=--------------------------------------------------------------------= - @inlinable public init(_ source: Source, isSigned: Bool = false) { + @inlinable public init(_ source: Source, isSigned: Bool = false, as limb: Limb.Type = Limb.self) { if Limb.bitWidth < Source.Element.bitWidth { self.minorLimbs = MinorLimbs(majorLimbs: source) self.majorLimbs = nil @@ -107,10 +107,12 @@ extension NBK { // MARK: * Major Limbs Sequence //*========================================================================* - @frozen public struct MajorLimbsSequence: Sequence - where MajorLimb: NBKCoreInteger, MinorLimbs: Sequence, MinorLimbs.Element: NBKCoreInteger { + @frozen public struct MajorLimbsSequence: Sequence where + MajorLimb: NBKCoreInteger, MinorLimbs: Sequence, MinorLimbs.Element: NBKCoreInteger { - @usableFromInline typealias MinorLimb = MinorLimbs.Element + public typealias MajorLimb = MajorLimb + + public typealias MinorLimb = MinorLimbs.Element //=--------------------------------------------------------------------= // MARK: State @@ -202,10 +204,12 @@ extension NBK { @frozen public struct MinorLimbsSequence: Sequence where MinorLimb: NBKCoreInteger, MajorLimbs: Sequence, MajorLimbs.Element: NBKCoreInteger { - + public typealias MajorLimb = MajorLimbs.Element - public typealias MinorLimbsSubSequence = NBK.MinorLimbsSubSequence + public typealias MinorLimb = MinorLimb + + public typealias MinorLimbsSubSequence = NBK.MinorLimbsSubSequence public typealias Iterator = FlattenSequence>.Iterator @@ -237,8 +241,8 @@ extension NBK { MajorLimb.bitWidth / MinorLimb.bitWidth * self.majorLimbs.underestimatedCount } - @inlinable public func makeIterator() -> Iterator { - // this type is not opaque because the type inferance seeems to fail otherwise :( + @inlinable public func makeIterator() -> Iterator { + // this type is not opaque because the type inference seems to fail otherwise :( self.majorLimbs.lazy.flatMap({ MinorLimbsSubSequence(majorLimb: $0) }).makeIterator() } } @@ -249,6 +253,10 @@ extension NBK { @frozen public struct MinorLimbsSubSequence: Sequence where MinorLimb: NBKCoreInteger, MajorLimb: NBKCoreInteger { + + public typealias MajorLimb = MajorLimb + + public typealias MinorLimb = MinorLimb //=--------------------------------------------------------------------= // MARK: State diff --git a/Sources/NBKCoreKit/Private/NBK+Text.swift b/Sources/NBKCoreKit/Private/NBK+Text.swift index ad062894..f96d6791 100644 --- a/Sources/NBKCoreKit/Private/NBK+Text.swift +++ b/Sources/NBKCoreKit/Private/NBK+Text.swift @@ -108,23 +108,23 @@ extension NBK { assert(radix.power.isZero || chunk < radix.power, "chunks must be less than radix's power") return Swift.withUnsafeTemporaryAllocation(of: UInt8.self, capacity: radix.exponent) { utf8 in var chunk = chunk as UInt - let end = utf8.baseAddress!.advanced(by: radix.exponent) - var start = end as UnsafeMutablePointer + let end = utf8.baseAddress!.advanced(by: utf8.count) + var position = end as UnsafeMutablePointer //=----------------------------------= // pointee: initialization //=----------------------------------= backwards: repeat { let digit: UInt (chunk, digit) = radix.dividing(chunk) - start = start.predecessor() - start.initialize(to: alphabet.encode(UInt8(truncatingIfNeeded: digit))!) + position = position.predecessor() + position.initialize(to: alphabet.encode(UInt8(truncatingIfNeeded: digit))!) } while !chunk.isZero //=----------------------------------= // pointee: deferred deinitialization //=----------------------------------= - let count: Int = start.distance(to: end) - defer{ start.deinitialize (count: count) } - return body(NBK.UnsafeUTF8(start: start, count: count)) + let count: Int = position.distance(to: end) + defer{ position.deinitialize(count: count) } + return body(NBK.UnsafeUTF8(start: position, count: count)) } } } diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text.swift index d9457609..41335392 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text.swift @@ -143,10 +143,8 @@ extension NBKDoubleWidth where High == High.Magnitude { // pointee: initialization //=----------------------------------= rebasing: while !magnitude.isZero { - let (remainder, overflow) = magnitude.formQuotientWithRemainderReportingOverflow(dividingBy: radix.power) - position.initialize(to: remainder) + position.initialize(to: magnitude.formQuotientWithRemainderReportingOverflow(dividingBy: radix.power).partialValue) position = position.successor() - assert(!overflow) } //=----------------------------------= // pointee: deferred deinitialization From 9ca4e029a08f96b5f223a5692de31e8993fe1b91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Wed, 23 Aug 2023 19:47:29 +0200 Subject: [PATCH 052/111] [NBKCoreKit] BlackHole. --- Sources/NBKCoreKit/Private/NBK+BlackHole.swift | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/Sources/NBKCoreKit/Private/NBK+BlackHole.swift b/Sources/NBKCoreKit/Private/NBK+BlackHole.swift index cf2b6dd0..0ce50d2d 100644 --- a/Sources/NBKCoreKit/Private/NBK+BlackHole.swift +++ b/Sources/NBKCoreKit/Private/NBK+BlackHole.swift @@ -21,20 +21,17 @@ extension NBK { /// /// Optimizer folklore has it that its secrets are revealed only to the supreme architect. /// - @inline(never) @_semantics("optimize.no.crossmodule") - public static func blackHole(_ x: T) { } + @_optimize(none) public static func blackHole(_ x: T) { } /// Opaquely returns the argument. /// /// Optimizer folklore has it that its secrets are revealed only to the supreme architect. /// - @inline(never) @_semantics("optimize.no.crossmodule") - public static func blackHoleIdentity(_ x: T) -> T { x } + @_optimize(none) public static func blackHoleIdentity(_ x: T) -> T { x } /// Opaquely mutates the argument. /// /// Optimizer folklore has it that its secrets are revealed only to the supreme architect. /// - @inline(never) @_semantics("optimize.no.crossmodule") - public static func blackHoleInoutIdentity(_ x: inout T) { } + @_optimize(none) public static func blackHoleInoutIdentity(_ x: inout T) { } } From 6f7ed44951fa46ab2ec6db6e3ee82b7b4649b90f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Wed, 23 Aug 2023 19:49:52 +0200 Subject: [PATCH 053/111] [NBKDoubleWidthKit] `withContiguousStorage(_:)`. --- .../NBKDoubleWidth+Words+Pointers.swift | 74 +++++-------------- 1 file changed, 19 insertions(+), 55 deletions(-) diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words+Pointers.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words+Pointers.swift index da1a8c97..00eba173 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words+Pointers.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words+Pointers.swift @@ -24,11 +24,15 @@ extension NBKDoubleWidth { /// The elements of the contiguous storage appear in the order of the collection. /// @inlinable public func withContiguousStorage(_ body: (NBK.UnsafeWords) throws -> T) rethrows -> T { - var base = self - #if _endian(big) - base.reverse() - #endif - return try base.withUnsafeUIntBufferPointer(body) + var base = self; return try Swift.withUnsafeMutablePointer(to: &base) { value in + try value.withMemoryRebound(to: UInt.self, capacity: Self.count) { start in + var words = UnsafeMutableBufferPointer(start: start, count: Self.count) + #if _endian(big) + words.reverse() + #endif + return try body(UnsafeBufferPointer(words)) + } + } } /// Grants unsafe access to the collection's contiguous storage. @@ -46,11 +50,16 @@ extension NBKDoubleWidth { /// The elements of the contiguous mutable storage appear in the order of the collection. /// @inlinable public mutating func withContiguousMutableStorage(_ body: (inout NBK.UnsafeMutableWords) throws -> T) rethrows -> T { - #if _endian(big) - do { self.reverse() } - defer { self.reverse() } - #endif - return try self.withUnsafeMutableUIntBufferPointer(body) + try Swift.withUnsafeMutablePointer(to: &self) { value in + try value.withMemoryRebound(to: UInt.self, capacity: Self.count) { start in + var words = UnsafeMutableBufferPointer(start: start, count: Self.count) + #if _endian(big) + do { words.reverse() } + defer { words.reverse() } + #endif + return try body(&words) + } + } } /// Grants unsafe access to the collection's contiguous mutable storage. @@ -62,49 +71,4 @@ extension NBKDoubleWidth { @inlinable public mutating func withContiguousMutableStorageIfAvailable(_ body: (inout NBK.UnsafeMutableWords) throws -> T) rethrows -> T? { try self.withContiguousMutableStorage(body) } - - //=------------------------------------------------------------------------= - // MARK: Details x Trivial UInt Collection x Private - //=------------------------------------------------------------------------= - - /// Grants unsafe access to the integer's in-memory representation. - /// - /// - Note: The order of the integer's words depends on the platform's endianness. - /// - @inlinable func withUnsafeUIntPointer(_ body: (UnsafePointer) throws -> T) rethrows -> T { - try Swift.withUnsafePointer(to: self) { base in - try base.withMemoryRebound(to: UInt.self, capacity: Self.count, body) - } - } - - /// Grants unsafe access to the integer's in-memory representation. - /// - /// - Note: The order of the integer's words depends on the platform's endianness. - /// - @inlinable func withUnsafeUIntBufferPointer(_ body: (NBK.UnsafeWords) throws -> T) rethrows -> T { - try self.withUnsafeUIntPointer { base in - try body(UnsafeBufferPointer(start: base, count: Self.count)) - } - } - - /// Grants unsafe access to the integer's in-memory representation. - /// - /// - Note: The order of the integer's words depends on the platform's endianness. - /// - @inlinable mutating func withUnsafeMutableUIntPointer(_ body: (UnsafeMutablePointer) throws -> T) rethrows -> T { - try Swift.withUnsafeMutablePointer(to: &self) { base in - try base.withMemoryRebound(to: UInt.self, capacity: Self.count, body) - } - } - - /// Grants unsafe access to the integer's in-memory representation. - /// - /// - Note: The order of the integer's words depends on the platform's endianness. - /// - @inlinable mutating func withUnsafeMutableUIntBufferPointer(_ body: (inout NBK.UnsafeMutableWords) throws -> T) rethrows -> T { - try self.withUnsafeMutableUIntPointer { base in - var buffer = UnsafeMutableBufferPointer(start: base, count: Self.count) - return try body(&buffer) - } - } } From bafed64a04ae74393f5efc2c968c4c7e8a72c42d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Thu, 24 Aug 2023 10:03:04 +0200 Subject: [PATCH 054/111] [NBKDoubleWidthKit] Addition & Subtraction. --- Sources/NBKCoreKit/Private/NBK+Limbs.swift | 2 +- .../NBKDoubleWidth+Addition+Digit.swift | 15 ++++----------- .../NBKDoubleWidth+Subtraction+Digit.swift | 15 ++++----------- 3 files changed, 9 insertions(+), 23 deletions(-) diff --git a/Sources/NBKCoreKit/Private/NBK+Limbs.swift b/Sources/NBKCoreKit/Private/NBK+Limbs.swift index cddd2ed1..599f653f 100644 --- a/Sources/NBKCoreKit/Private/NBK+Limbs.swift +++ b/Sources/NBKCoreKit/Private/NBK+Limbs.swift @@ -27,7 +27,7 @@ extension NBK { //=--------------------------------------------------------------------= // MARK: State //=--------------------------------------------------------------------= - // note: two parallel options appear to be faster than a combined enum + // NOTE: Two parallel options appear to be faster than a combined enum. //=--------------------------------------------------------------------= @usableFromInline let minorLimbs: MinorLimbs? diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Addition+Digit.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Addition+Digit.swift index 6b9eb3f9..9f53bd9f 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Addition+Digit.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Addition+Digit.swift @@ -20,17 +20,10 @@ extension NBKDoubleWidth { //=------------------------------------------------------------------------= @_disfavoredOverload @inlinable public mutating func addReportingOverflow(_ other: Digit) -> Bool { - let minus: Bool = other.isLessThanZero - var carry: Bool = self.first.addReportingOverflow(UInt(bitPattern: other)) - //=----------------------------------= - if carry == minus { return false } - let extra = UInt(bitPattern: minus ? -1 : 1) - //=----------------------------------= - for index in 1 ..< self.lastIndex { - carry = self[index].addReportingOverflow(extra) - if carry == minus { return false } - } - //=----------------------------------= + let minus = other.isLessThanZero as Bool + if self.first.addReportingOverflow(UInt(bitPattern: other)) == minus { return false } + let extra = UInt(bitPattern: minus ? -1 : 1) + for index in 1 ..< self.lastIndex where self[index].addReportingOverflow(extra) == minus { return false } return self.tail.addReportingOverflow(Digit(bitPattern: extra)) } diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Subtraction+Digit.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Subtraction+Digit.swift index bacfe5c1..096a406d 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Subtraction+Digit.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Subtraction+Digit.swift @@ -20,17 +20,10 @@ extension NBKDoubleWidth { //=------------------------------------------------------------------------= @_disfavoredOverload @inlinable public mutating func subtractReportingOverflow(_ other: Digit) -> Bool { - let minus: Bool = other.isLessThanZero - var carry: Bool = self.first.subtractReportingOverflow(UInt(bitPattern: other)) - //=----------------------------------= - if carry == minus { return false } - let extra = UInt(bitPattern: minus ? -1 : 1) - //=----------------------------------= - for index in 1 ..< self.lastIndex { - carry = self[index].subtractReportingOverflow(extra) - if carry == minus { return false } - } - //=----------------------------------= + let minus = other.isLessThanZero as Bool + if self.first.subtractReportingOverflow(UInt(bitPattern: other)) == minus { return false } + let extra = UInt(bitPattern: minus ? -1 : 1) + for index in 1 ..< self.lastIndex where self[index].subtractReportingOverflow(extra) == minus { return false } return self.tail.subtractReportingOverflow(Digit(bitPattern: extra)) } From e10cc2fc3a5ba5e40aafc1701e38f564ddb2e8e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Thu, 24 Aug 2023 18:57:14 +0200 Subject: [PATCH 055/111] [NBKDoubleWidthKit] Cleanup. --- .../NBKDoubleWidth+Words+Pointers.swift | 2 +- .../NBKDoubleWidth+Words.swift | 27 +++++++++---------- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words+Pointers.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words+Pointers.swift index 00eba173..5ec9837f 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words+Pointers.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words+Pointers.swift @@ -16,7 +16,7 @@ import NBKCoreKit extension NBKDoubleWidth { //=------------------------------------------------------------------------= - // MARK: Details x Trivial UInt Collection + // MARK: Details x Contiguous UInt Collection //=------------------------------------------------------------------------= /// Grants unsafe access to the collection's contiguous storage. diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words.swift index 6064f136..5a822012 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words.swift @@ -239,7 +239,7 @@ extension NBKDoubleWidth { yield &self[unchecked: index, as: T.self] } } - + /// Accesses the word at the given index, from least significant to most. /// /// - Parameter index: The machine word index. @@ -247,14 +247,14 @@ extension NBKDoubleWidth { /// @inlinable subscript(unchecked index: Int, as type: T.Type) -> T where T: NBKCoreInteger { get { - let offset = BitPattern.endiannessSensitiveByteOffset(unchecked: index) + let offset = BitPattern.endiannessSensitiveByteOffset(at: index) return Swift.withUnsafeBytes(of: self) { data in data.load(fromByteOffset: offset, as: T.self) } } set { - let offset = BitPattern.endiannessSensitiveByteOffset(unchecked: index) + let offset = BitPattern.endiannessSensitiveByteOffset(at: index) Swift.withUnsafeMutableBytes(of: &self) { data in data.storeBytes(of: newValue, toByteOffset: offset, as: T.self) } @@ -262,9 +262,9 @@ extension NBKDoubleWidth { } } -//=----------------------------------------------------------------------------= -// MARK: + Unsigned -//=----------------------------------------------------------------------------= +//*============================================================================* +// MARK: * NBK x Double Width x Words x Unsigned +//*============================================================================* extension NBKDoubleWidth where High == High.Magnitude { @@ -272,16 +272,15 @@ extension NBKDoubleWidth where High == High.Magnitude { // MARK: Utilities x Private //=------------------------------------------------------------------------= - @inlinable static func endiannessSensitiveIndex(unchecked index: Int) -> Int { - assert(self.indices ~= index, NBK.callsiteOutOfBoundsInfo()) + /// Returns the in-memory byte offset of the word at the given index. + /// + /// - Note: This operation is unchecked. + /// + @inlinable static func endiannessSensitiveByteOffset(at index: Int) -> Int { #if _endian(big) - return self.lastIndex - index + return MemoryLayout.stride * ~index + MemoryLayout.size #else - return index + return MemoryLayout.stride * (index) #endif } - - @inlinable static func endiannessSensitiveByteOffset(unchecked index: Int) -> Int { - self.endiannessSensitiveIndex(unchecked: index) * MemoryLayout.stride - } } From b3562a39d37ae1c3ba8f5ed7dde8a60e5ab57786 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Thu, 24 Aug 2023 20:55:00 +0200 Subject: [PATCH 056/111] [NBKDoubleWidthKit] Removed static indices (#70). --- .../NBKDoubleWidth+Words.swift | 30 ++++--------------- 1 file changed, 5 insertions(+), 25 deletions(-) diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words.swift index 5a822012..b0b44da6 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words.swift @@ -19,7 +19,7 @@ extension NBKDoubleWidth { // MARK: Accessors //=------------------------------------------------------------------------= - /// The number of words. + /// The number of words in this type of integer. @inlinable public static var count: Int { assert(MemoryLayout.size / MemoryLayout.stride >= 2) assert(MemoryLayout.size % MemoryLayout.stride == 0) @@ -50,43 +50,23 @@ extension NBKDoubleWidth { //=------------------------------------------------------------------------= /// The index of the least significant word. - @inlinable public static var startIndex: Int { + @inlinable public var startIndex: Int { 0 } /// The index of the most significant word. - @inlinable public static var lastIndex: Int { + @inlinable public var lastIndex: Int { self.count - 1 } /// The index after the last valid subscript argument. - @inlinable public static var endIndex: Int { + @inlinable public var endIndex: Int { self.count } /// A collection of each valid subscript argument, in ascending order. - @inlinable public static var indices: Range { - 0 ..< self.count - } - - //=------------------------------------------------------------------------= - // MARK: Accessors - //=------------------------------------------------------------------------= - - @inlinable public var startIndex: Int { - Self.startIndex - } - - @inlinable public var lastIndex: Int { - Self.lastIndex - } - - @inlinable public var endIndex: Int { - Self.endIndex - } - @inlinable public var indices: Range { - Self.indices + 0 ..< self.count } //=------------------------------------------------------------------------= From 540a08b2bf64d4ce20c1d008416fcf1646ab788d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Fri, 25 Aug 2023 10:03:49 +0200 Subject: [PATCH 057/111] Cleanup. --- README.md | 2 +- Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words.swift | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 861354fd..f3026385 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,7 @@ Int256(5) % Int(5), UInt256(5) % UInt(5) > **Note**: The `Digit` type is `Int` when `Self` is signed, and `UInt` otherwise. -### ⭐️ Feature: StaticBigInt (v0.10.0) +### ⭐️ Swift.StaticBigInt (v0.10.0) `StaticBigInt` is disabled by default. You enable it in `Package.swift`. diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words.swift index b0b44da6..411f2a47 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words.swift @@ -31,7 +31,7 @@ extension NBKDoubleWidth { //=------------------------------------------------------------------------= @inlinable public var count: Int { - Self.count + Self.count as Int } @inlinable public var words: Self { @@ -228,15 +228,17 @@ extension NBKDoubleWidth { @inlinable subscript(unchecked index: Int, as type: T.Type) -> T where T: NBKCoreInteger { get { let offset = BitPattern.endiannessSensitiveByteOffset(at: index) - return Swift.withUnsafeBytes(of: self) { data in - data.load(fromByteOffset: offset, as: T.self) + assert(0 <= offset && offset <= MemoryLayout.size - MemoryLayout.stride, NBK.callsiteOutOfBoundsInfo()) + return Swift.withUnsafePointer(to: self) { pointer in + UnsafeRawPointer(pointer).load(fromByteOffset: offset, as: T.self) } } set { let offset = BitPattern.endiannessSensitiveByteOffset(at: index) - Swift.withUnsafeMutableBytes(of: &self) { data in - data.storeBytes(of: newValue, toByteOffset: offset, as: T.self) + assert(0 <= offset && offset <= MemoryLayout.size - MemoryLayout.stride, NBK.callsiteOutOfBoundsInfo()) + Swift.withUnsafeMutablePointer(to: &self) { pointer in + UnsafeMutableRawPointer(pointer).storeBytes(of: newValue, toByteOffset: offset, as: T.self) } } } From f35f601968c1d4c91f68cc18655695adf0fe0a62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Fri, 25 Aug 2023 17:09:41 +0200 Subject: [PATCH 058/111] [NBKCoreKit] NBKLittleEndianOrdered (#71). --- .../NBKCoreKit/NBKLittleEndianOrdered.swift | 203 ++++++++++++++++++ .../NBKDoubleWidth+Uninitialized.swift | 2 + .../NBKDoubleWidthKit/NBKDoubleWidth.swift | 6 +- .../NBKLittleEndianCollection.swift | 110 ++++++++++ 4 files changed, 318 insertions(+), 3 deletions(-) create mode 100644 Sources/NBKCoreKit/NBKLittleEndianOrdered.swift create mode 100644 Tests/NBKCoreKitTests/NBKLittleEndianCollection.swift diff --git a/Sources/NBKCoreKit/NBKLittleEndianOrdered.swift b/Sources/NBKCoreKit/NBKLittleEndianOrdered.swift new file mode 100644 index 00000000..e3bdc5c1 --- /dev/null +++ b/Sources/NBKCoreKit/NBKLittleEndianOrdered.swift @@ -0,0 +1,203 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +//*============================================================================* +// MARK: * NBK x Little Endian Ordered +//*============================================================================* + +/// A collection that iterates forwards or backwards depending on the platform. +/// +/// It iterates front-to-back on little-endian platforms, and back-to-front otherwise. +/// +@frozen public struct NBKLittleEndianOrdered: BidirectionalCollection where Base: BidirectionalCollection { + + #if _endian(big) + @usableFromInline typealias Storage = ReversedCollection + #else + @usableFromInline typealias Storage = Base + #endif + + //=------------------------------------------------------------------------= + // MARK: State + //=------------------------------------------------------------------------= + + @usableFromInline var storage: Storage + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + @inlinable public init(_ base: Base) { + #if _endian(big) + self.storage = base.reversed() + #else + self.storage = base + #endif + } + + //=------------------------------------------------------------------------= + // MARK: Accessors + //=------------------------------------------------------------------------= + + @inlinable public var base: Base { + #if _endian(big) + return self.storage.reversed() // from >= Swift 4.2 + #else + return self.storage + #endif + } + + @inlinable public var count: Int { + self.storage.count + } + + @inlinable public var startIndex: Index { + Index(self.storage.startIndex) + } + + @inlinable public var endIndex: Index { + Index(self.storage.endIndex) + } + + @inlinable public subscript(index: Index) -> Base.Element { + _read { yield self.storage[index.storageIndex] } + } + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + @inlinable public func makeIterator() -> Iterator { + Iterator(self.storage.makeIterator()) + } + + @inlinable public func distance(from start: Index, to end: Index) -> Int { + self.storage.distance(from: start.storageIndex, to: end.storageIndex) + } + + @inlinable public func index(after index: Index) -> Index { + Index(self.storage.index(after: index.storageIndex)) + } + + @inlinable public func formIndex(after index: inout Index) { + self.storage.formIndex(after: &index.storageIndex) + } + + @inlinable public func index(before index: Index) -> Index { + Index(self.storage.index(before: index.storageIndex)) + } + + @inlinable public func formIndex(before index: inout Index) { + self.storage.formIndex(before: &index.storageIndex) + } + + @inlinable public func index(_ index: Index, offsetBy distance: Int) -> Index { + Index(self.storage.index(index.storageIndex, offsetBy: distance)) + } + + @inlinable public func index(_ index: Index, offsetBy distance: Int, limitedBy limit: Index) -> Index? { + self.storage.index(index.storageIndex, offsetBy: distance, limitedBy: limit.storageIndex).map(Index.init) + } + + @inlinable public func baseSubscriptIndex(at index: Index) -> Base.Index { + #if _endian(big) + return self.storage.index(after: index.storageIndex).base + #else + return index.storageIndex + #endif + } + + //*========================================================================* + // MARK: * Index + //*========================================================================* + + @frozen public struct Index: Comparable { + + //=--------------------------------------------------------------------= + // MARK: State + //=--------------------------------------------------------------------= + + /// An index depending on platform endianness. + /// + /// ``` + /// BE: base.endIndex ..< base.startIndex (back-to-front) + /// LE: base.startIndex ..< base.endIndex (front-to-back) + /// ``` + /// + @usableFromInline var storageIndex: Storage.Index + + //=--------------------------------------------------------------------= + // MARK: Initializers + //=--------------------------------------------------------------------= + + @inlinable init(_ storageIndex: Storage.Index) { + self.storageIndex = storageIndex + } + + //=--------------------------------------------------------------------= + // MARK: Utilities + //=--------------------------------------------------------------------= + + @inlinable public static func ==(lhs: Self, rhs: Self) -> Bool { + lhs.storageIndex == rhs.storageIndex + } + + @inlinable public static func < (lhs: Self, rhs: Self) -> Bool { + lhs.storageIndex < rhs.storageIndex + } + + /// Returns the subscript index of the corresponding collection, assuming it exists. + /// + /// - Note: This operation is unchecked. + /// + @inlinable public func baseSubscriptIndex() -> Base.Index where Base.Indices == Range { + #if _endian(big) + return self.storageIndex.base.advanced(by: -1) + #else + return self.storageIndex + #endif + } + } + + //*========================================================================* + // MARK: * Iterator + //*========================================================================* + + @frozen public struct Iterator: Sequence, IteratorProtocol { + + //=--------------------------------------------------------------------= + // MARK: State + //=--------------------------------------------------------------------= + + @usableFromInline var storageIterator: Storage.Iterator + + //=--------------------------------------------------------------------= + // MARK: Initializers + //=--------------------------------------------------------------------= + + @inlinable init(_ storageIterator: Storage.Iterator) { + self.storageIterator = storageIterator + } + + //=--------------------------------------------------------------------= + // MARK: Utilities + //=--------------------------------------------------------------------= + + @inlinable public mutating func next() -> Base.Element? { + self.storageIterator.next() + } + } +} + +//=----------------------------------------------------------------------------= +// MARK: + Conditional Conformances +//=----------------------------------------------------------------------------= + +extension NBKLittleEndianOrdered.Index: Hashable where Base.Index: Hashable { } +extension NBKLittleEndianOrdered: RandomAccessCollection where Base: RandomAccessCollection { } diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Uninitialized.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Uninitialized.swift index 902d89eb..14868006 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Uninitialized.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Uninitialized.swift @@ -7,6 +7,8 @@ // See http://www.apache.org/licenses/LICENSE-2.0 for license information. //=----------------------------------------------------------------------------= +import NBKCoreKit + //*============================================================================* // MARK: * NBK x Double Width x Uninitialized //*============================================================================* diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift index 60628fcc..255853de 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift @@ -221,9 +221,9 @@ High: NBKFixedWidthInteger, High.Digit: NBKCoreInteger { } } -//*============================================================================* -// MARK: * NBK x Double Width x Conditional Conformances -//*============================================================================* +//=----------------------------------------------------------------------------= +// MARK: + Conditional Conformances +//=----------------------------------------------------------------------------= extension NBKDoubleWidth: NBKSignedInteger, SignedInteger, SignedNumeric where High: NBKSignedInteger { } diff --git a/Tests/NBKCoreKitTests/NBKLittleEndianCollection.swift b/Tests/NBKCoreKitTests/NBKLittleEndianCollection.swift new file mode 100644 index 00000000..0144c286 --- /dev/null +++ b/Tests/NBKCoreKitTests/NBKLittleEndianCollection.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 XCTest + +//*============================================================================* +// MARK: * NBK x Little Endian Ordered +//*============================================================================* + +final class NBKLittleEndianOrderedTests: XCTestCase { + + typealias T = NBKLittleEndianOrdered where + Base: RandomAccessCollection, Base.Indices == Range + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testIteration() { + var integer = UInt64.zero + + integer |= 0 << (0 * 8) + integer |= 1 << (1 * 8) + integer |= 2 << (2 * 8) + integer |= 3 << (3 * 8) + integer |= 4 << (4 * 8) + integer |= 5 << (5 * 8) + integer |= 6 << (6 * 8) + integer |= 7 << (7 * 8) + + Swift.withUnsafeBytes(of: integer) { integer in + NBKAssertLittleEndianOrderedIteration(T(integer), [0, 1, 2, 3, 4, 5, 6, 7]) + } + } +} + +//*============================================================================* +// MARK: * NBK x Little Endian Ordered x Assertions +//*============================================================================* + +private func NBKAssertLittleEndianOrderedIteration( +_ lhs: NBKLittleEndianOrdered, _ rhs: [B.Element], +file: StaticString = #file, line: UInt = #line) where B.Element: Equatable, B.Indices == Range { + XCTAssertEqual(Array(lhs), rhs, file: file, line: line) + XCTAssertEqual(Array(lhs.reversed()), rhs.reversed(), file: file, line: line) + + do { + var lhsIndex = lhs.startIndex + var rhsIndex = rhs.startIndex + while lhsIndex < lhs.endIndex { + XCTAssertEqual(lhs[lhsIndex], rhs[rhsIndex], file: file, line: line) + lhsIndex = lhs.index(after: lhsIndex) + rhsIndex = rhs.index(after: rhsIndex) + } + } + + do { + var lhsIndex = lhs.endIndex + var rhsIndex = rhs.endIndex + while lhsIndex > lhs.startIndex { + lhsIndex = lhs.index(before: lhsIndex) + rhsIndex = rhs.index(before: rhsIndex) + XCTAssertEqual(lhs[lhsIndex], rhs[rhsIndex], file: file, line: line) + } + } + + do { + for lhsIndex in lhs.indices.enumerated() { + XCTAssertEqual(lhs[lhsIndex.element], rhs[lhsIndex.offset], file: file, line: line) + } + } + + do { + for lhsIndex in lhs.indices { + XCTAssertEqual(lhs[lhsIndex], lhs.base[lhsIndex.baseSubscriptIndex()], file: file, line: line) + XCTAssertEqual(lhs[lhsIndex], lhs.base[lhs.baseSubscriptIndex(at: lhsIndex)], file: file, line: line) + } + } + + do { + for dropFirst in 0 ..< (2 * lhs.count) { + XCTAssertEqual(Array(lhs.dropFirst(dropFirst)), Array(rhs.dropFirst(dropFirst)), file: file, line: line) + if let first = lhs.dropFirst(dropFirst).first { + let firstIndex = lhs.index(lhs.startIndex, offsetBy: dropFirst) + XCTAssertEqual(first, lhs[firstIndex], file: file, line: line) + } + } + } + + do { + for dropLast in 0 ..< (2 * lhs.count) { + XCTAssertEqual(Array(lhs.dropLast(dropLast)), Array(rhs.dropLast(dropLast)), file: file, line: line) + if let last = lhs.dropLast(dropLast).last { + let lastIndex = lhs.index(lhs.endIndex, offsetBy: ~dropLast) + XCTAssertEqual(last, lhs[lastIndex], file: file, line: line) + } + } + } +} + +#endif From dd92c8ca84cf194101577f65ca9c42c687f84712 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Fri, 25 Aug 2023 17:23:12 +0200 Subject: [PATCH 059/111] Some cleanup and documentation. --- README.md | 4 ++++ Sources/NBKCoreKit/{ => Models}/NBKLittleEndianOrdered.swift | 4 ++-- Sources/Numberick/Documentation.docc/Documentation.md | 1 + .../NBKLittleEndianOrdered.swift} | 3 +-- 4 files changed, 8 insertions(+), 4 deletions(-) rename Sources/NBKCoreKit/{ => Models}/NBKLittleEndianOrdered.swift (98%) rename Tests/NBKCoreKitTests/{NBKLittleEndianCollection.swift => Models/NBKLittleEndianOrdered.swift} (97%) diff --git a/README.md b/README.md index f3026385..c0c87480 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,10 @@ A new protocol hierarchy that refines Swift's standard library. - [NBKSignedInteger](Sources/NBKCoreKit/NBKBinaryInteger.swift) - [NBKUnsignedInteger](Sources/NBKCoreKit/NBKBinaryInteger.swift) +### Models + +- [NBKLittleEndianOrdered](Sources/NBKCoreKit/NBKLittleEndianOrdered.swift) + ## [NBKDoubleWidthKit][DBL/D] ([Sources][DBL/S], [Tests][DBL/T], [Benchmarks][DBL/B]) A composable, large, fixed-width, two's complement, binary integer. diff --git a/Sources/NBKCoreKit/NBKLittleEndianOrdered.swift b/Sources/NBKCoreKit/Models/NBKLittleEndianOrdered.swift similarity index 98% rename from Sources/NBKCoreKit/NBKLittleEndianOrdered.swift rename to Sources/NBKCoreKit/Models/NBKLittleEndianOrdered.swift index e3bdc5c1..58592b9b 100644 --- a/Sources/NBKCoreKit/NBKLittleEndianOrdered.swift +++ b/Sources/NBKCoreKit/Models/NBKLittleEndianOrdered.swift @@ -123,7 +123,7 @@ // MARK: State //=--------------------------------------------------------------------= - /// An index depending on platform endianness. + /// An index depending on the platform's endianness. /// /// ``` /// BE: base.endIndex ..< base.startIndex (back-to-front) @@ -169,7 +169,7 @@ // MARK: * Iterator //*========================================================================* - @frozen public struct Iterator: Sequence, IteratorProtocol { + @frozen public struct Iterator: IteratorProtocol { //=--------------------------------------------------------------------= // MARK: State diff --git a/Sources/Numberick/Documentation.docc/Documentation.md b/Sources/Numberick/Documentation.docc/Documentation.md index 47490712..e53f59f5 100644 --- a/Sources/Numberick/Documentation.docc/Documentation.md +++ b/Sources/Numberick/Documentation.docc/Documentation.md @@ -105,6 +105,7 @@ Int256(5) % Int(5), UInt256(5) % UInt(5) ### Models - ``NBKDoubleWidth`` +- ``NBKLittleEndianOrdered`` ### Integers diff --git a/Tests/NBKCoreKitTests/NBKLittleEndianCollection.swift b/Tests/NBKCoreKitTests/Models/NBKLittleEndianOrdered.swift similarity index 97% rename from Tests/NBKCoreKitTests/NBKLittleEndianCollection.swift rename to Tests/NBKCoreKitTests/Models/NBKLittleEndianOrdered.swift index 0144c286..9258ddbd 100644 --- a/Tests/NBKCoreKitTests/NBKLittleEndianCollection.swift +++ b/Tests/NBKCoreKitTests/Models/NBKLittleEndianOrdered.swift @@ -18,8 +18,7 @@ import XCTest final class NBKLittleEndianOrderedTests: XCTestCase { - typealias T = NBKLittleEndianOrdered where - Base: RandomAccessCollection, Base.Indices == Range + typealias T = NBKLittleEndianOrdered where Base: BidirectionalCollection //=------------------------------------------------------------------------= // MARK: Tests From 6f46bfe1aaf4048774222d39f24316fc023879ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Fri, 25 Aug 2023 18:00:19 +0200 Subject: [PATCH 060/111] Cleanup. --- README.md | 2 +- .../Models/NBKLittleEndianOrdered.swift | 48 +++++-------------- 2 files changed, 14 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index c0c87480..d622454c 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ A new protocol hierarchy that refines Swift's standard library. ### Models -- [NBKLittleEndianOrdered](Sources/NBKCoreKit/NBKLittleEndianOrdered.swift) +- [NBKLittleEndianOrdered](Sources/NBKCoreKit/Models/NBKLittleEndianOrdered.swift) ## [NBKDoubleWidthKit][DBL/D] ([Sources][DBL/S], [Tests][DBL/T], [Benchmarks][DBL/B]) diff --git a/Sources/NBKCoreKit/Models/NBKLittleEndianOrdered.swift b/Sources/NBKCoreKit/Models/NBKLittleEndianOrdered.swift index 58592b9b..26fdc09a 100644 --- a/Sources/NBKCoreKit/Models/NBKLittleEndianOrdered.swift +++ b/Sources/NBKCoreKit/Models/NBKLittleEndianOrdered.swift @@ -27,7 +27,14 @@ // MARK: State //=------------------------------------------------------------------------= - @usableFromInline var storage: Storage + /// A collection based on the platform's endianness. + /// + /// ``` + /// BE: base.reversed() (back-to-front) + /// LE: base (front-to-back) + /// ``` + /// + @usableFromInline let storage: Storage //=------------------------------------------------------------------------= // MARK: Initializers @@ -73,10 +80,6 @@ // MARK: Utilities //=------------------------------------------------------------------------= - @inlinable public func makeIterator() -> Iterator { - Iterator(self.storage.makeIterator()) - } - @inlinable public func distance(from start: Index, to end: Index) -> Int { self.storage.distance(from: start.storageIndex, to: end.storageIndex) } @@ -113,6 +116,10 @@ #endif } + @inlinable public func makeIterator() -> some IteratorProtocol { + self.storage.makeIterator() + } + //*========================================================================* // MARK: * Index //*========================================================================* @@ -123,7 +130,7 @@ // MARK: State //=--------------------------------------------------------------------= - /// An index depending on the platform's endianness. + /// An index based on the platform's endianness. /// /// ``` /// BE: base.endIndex ..< base.startIndex (back-to-front) @@ -164,35 +171,6 @@ #endif } } - - //*========================================================================* - // MARK: * Iterator - //*========================================================================* - - @frozen public struct Iterator: IteratorProtocol { - - //=--------------------------------------------------------------------= - // MARK: State - //=--------------------------------------------------------------------= - - @usableFromInline var storageIterator: Storage.Iterator - - //=--------------------------------------------------------------------= - // MARK: Initializers - //=--------------------------------------------------------------------= - - @inlinable init(_ storageIterator: Storage.Iterator) { - self.storageIterator = storageIterator - } - - //=--------------------------------------------------------------------= - // MARK: Utilities - //=--------------------------------------------------------------------= - - @inlinable public mutating func next() -> Base.Element? { - self.storageIterator.next() - } - } } //=----------------------------------------------------------------------------= From da257df3305eeda1c270a2de95d5a4c0ff44b434 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sat, 26 Aug 2023 07:19:56 +0200 Subject: [PATCH 061/111] [NBKCoreKit]: NBKLittleEndianOrdered (#71). --- .../Models/NBKLittleEndianOrdered.swift | 168 ++++++------------ .../Models/NBKLittleEndianOrdered.swift | 5 +- 2 files changed, 61 insertions(+), 112 deletions(-) diff --git a/Sources/NBKCoreKit/Models/NBKLittleEndianOrdered.swift b/Sources/NBKCoreKit/Models/NBKLittleEndianOrdered.swift index 26fdc09a..d619c59a 100644 --- a/Sources/NBKCoreKit/Models/NBKLittleEndianOrdered.swift +++ b/Sources/NBKCoreKit/Models/NBKLittleEndianOrdered.swift @@ -15,167 +15,117 @@ /// /// It iterates front-to-back on little-endian platforms, and back-to-front otherwise. /// -@frozen public struct NBKLittleEndianOrdered: BidirectionalCollection where Base: BidirectionalCollection { - - #if _endian(big) - @usableFromInline typealias Storage = ReversedCollection - #else - @usableFromInline typealias Storage = Base - #endif +/// ```swift +/// let value = Int256.uninitialized { words in +/// for index in words.indices { +/// words.base.initializeElement(at: words.baseIndex(index), to: UInt.zero) +/// } +/// } +/// ``` +/// +@frozen public struct NBKLittleEndianOrdered: RandomAccessCollection where Base: RandomAccessCollection { //=------------------------------------------------------------------------= // MARK: State //=------------------------------------------------------------------------= - /// A collection based on the platform's endianness. - /// - /// ``` - /// BE: base.reversed() (back-to-front) - /// LE: base (front-to-back) - /// ``` - /// - @usableFromInline let storage: Storage + /// The collection wrapped by this instance. + public var base: Base //=------------------------------------------------------------------------= // MARK: Initializers //=------------------------------------------------------------------------= + /// Creates a view presenting the collection's elements in an endianness-dependent order. @inlinable public init(_ base: Base) { - #if _endian(big) - self.storage = base.reversed() - #else - self.storage = base - #endif + self.base = base } //=------------------------------------------------------------------------= // MARK: Accessors //=------------------------------------------------------------------------= - @inlinable public var base: Base { - #if _endian(big) - return self.storage.reversed() // from >= Swift 4.2 - #else - return self.storage - #endif + @inlinable public var count: Int { + self.base.count } - @inlinable public var count: Int { - self.storage.count + @inlinable public var startIndex: Int { + Int.zero } - @inlinable public var startIndex: Index { - Index(self.storage.startIndex) + @inlinable public var endIndex: Int { + self.base.count } - @inlinable public var endIndex: Index { - Index(self.storage.endIndex) + @inlinable public var indices: Range { + Range(uncheckedBounds:(self.startIndex, self.endIndex)) } - @inlinable public subscript(index: Index) -> Base.Element { - _read { yield self.storage[index.storageIndex] } + @inlinable public subscript(index: Int) -> Base.Element { + _read { yield self.base[self.baseIndex(index)] } + } + + @inlinable public subscript(index: Int) -> Base.Element where Base: MutableCollection { + _read { yield self.base[self.baseIndex(index)] } + _modify { yield &self.base[self.baseIndex(index)] } } //=------------------------------------------------------------------------= // MARK: Utilities //=------------------------------------------------------------------------= - @inlinable public func distance(from start: Index, to end: Index) -> Int { - self.storage.distance(from: start.storageIndex, to: end.storageIndex) + @inlinable public func distance(from start: Int, to end: Int) -> Int { + end - start } - @inlinable public func index(after index: Index) -> Index { - Index(self.storage.index(after: index.storageIndex)) + @inlinable public func index(after index: Int) -> Int { + index + 1 } - @inlinable public func formIndex(after index: inout Index) { - self.storage.formIndex(after: &index.storageIndex) + @inlinable public func formIndex(after index: inout Int) { + index += 1 } - @inlinable public func index(before index: Index) -> Index { - Index(self.storage.index(before: index.storageIndex)) + @inlinable public func index(before index: Int) -> Int { + index - 1 } - @inlinable public func formIndex(before index: inout Index) { - self.storage.formIndex(before: &index.storageIndex) + @inlinable public func formIndex(before index: inout Int) { + index -= 1 } - @inlinable public func index(_ index: Index, offsetBy distance: Int) -> Index { - Index(self.storage.index(index.storageIndex, offsetBy: distance)) + @inlinable public func index(_ index: Int, offsetBy distance: Int) -> Int { + index + distance } - @inlinable public func index(_ index: Index, offsetBy distance: Int, limitedBy limit: Index) -> Index? { - self.storage.index(index.storageIndex, offsetBy: distance, limitedBy: limit.storageIndex).map(Index.init) + @inlinable public func index(_ index: Int, offsetBy distance: Int, limitedBy limit: Int) -> Int? { + let distanceLimit: Int = self.distance(from: index, to: limit) + + guard distance >= 0 + ? distance <= distanceLimit || distanceLimit < 0 + : distance >= distanceLimit || distanceLimit > 0 + else { return nil } + + return self.index(index, offsetBy: distance) as Int } - @inlinable public func baseSubscriptIndex(at index: Index) -> Base.Index { + /// Returns the corresponding base index, assuming it exists. + /// + /// - Note: This operation is unchecked. + /// + /// - Parameter index: `self.startIndex <= index < self.endIndex` + /// + @inlinable public func baseIndex(_ index: Int) -> Base.Index { #if _endian(big) - return self.storage.index(after: index.storageIndex).base + return self.base.index(self.base.endIndex, offsetBy: ~index) #else - return index.storageIndex + return self.base.index(self.base.startIndex, offsetBy: index) #endif } - - @inlinable public func makeIterator() -> some IteratorProtocol { - self.storage.makeIterator() - } - - //*========================================================================* - // MARK: * Index - //*========================================================================* - - @frozen public struct Index: Comparable { - - //=--------------------------------------------------------------------= - // MARK: State - //=--------------------------------------------------------------------= - - /// An index based on the platform's endianness. - /// - /// ``` - /// BE: base.endIndex ..< base.startIndex (back-to-front) - /// LE: base.startIndex ..< base.endIndex (front-to-back) - /// ``` - /// - @usableFromInline var storageIndex: Storage.Index - - //=--------------------------------------------------------------------= - // MARK: Initializers - //=--------------------------------------------------------------------= - - @inlinable init(_ storageIndex: Storage.Index) { - self.storageIndex = storageIndex - } - - //=--------------------------------------------------------------------= - // MARK: Utilities - //=--------------------------------------------------------------------= - - @inlinable public static func ==(lhs: Self, rhs: Self) -> Bool { - lhs.storageIndex == rhs.storageIndex - } - - @inlinable public static func < (lhs: Self, rhs: Self) -> Bool { - lhs.storageIndex < rhs.storageIndex - } - - /// Returns the subscript index of the corresponding collection, assuming it exists. - /// - /// - Note: This operation is unchecked. - /// - @inlinable public func baseSubscriptIndex() -> Base.Index where Base.Indices == Range { - #if _endian(big) - return self.storageIndex.base.advanced(by: -1) - #else - return self.storageIndex - #endif - } - } } //=----------------------------------------------------------------------------= // MARK: + Conditional Conformances //=----------------------------------------------------------------------------= -extension NBKLittleEndianOrdered.Index: Hashable where Base.Index: Hashable { } -extension NBKLittleEndianOrdered: RandomAccessCollection where Base: RandomAccessCollection { } +extension NBKLittleEndianOrdered: MutableCollection where Base: MutableCollection { } diff --git a/Tests/NBKCoreKitTests/Models/NBKLittleEndianOrdered.swift b/Tests/NBKCoreKitTests/Models/NBKLittleEndianOrdered.swift index 9258ddbd..a5c8167f 100644 --- a/Tests/NBKCoreKitTests/Models/NBKLittleEndianOrdered.swift +++ b/Tests/NBKCoreKitTests/Models/NBKLittleEndianOrdered.swift @@ -18,7 +18,7 @@ import XCTest final class NBKLittleEndianOrderedTests: XCTestCase { - typealias T = NBKLittleEndianOrdered where Base: BidirectionalCollection + typealias T = NBKLittleEndianOrdered where Base: RandomAccessCollection //=------------------------------------------------------------------------= // MARK: Tests @@ -80,8 +80,7 @@ file: StaticString = #file, line: UInt = #line) where B.Element: Equatable, B.I do { for lhsIndex in lhs.indices { - XCTAssertEqual(lhs[lhsIndex], lhs.base[lhsIndex.baseSubscriptIndex()], file: file, line: line) - XCTAssertEqual(lhs[lhsIndex], lhs.base[lhs.baseSubscriptIndex(at: lhsIndex)], file: file, line: line) + XCTAssertEqual(lhs[lhsIndex], lhs.base[lhs.baseIndex(lhsIndex)], file: file, line: line) } } From 8fcc57ade06f47110fdfd0bca875300ec252ff5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sat, 26 Aug 2023 08:51:17 +0200 Subject: [PATCH 062/111] [NBKDoubleWidthKit]: Reworked `uninitialized(_:)` (#67). --- README.md | 2 +- .../Models/NBKLittleEndianOrdered.swift | 51 ++++++++++++------ .../NBKDoubleWidth+Literals.swift | 12 +++-- .../NBKDoubleWidth+Numbers.swift | 8 +-- .../NBKDoubleWidth+Rotations.swift | 22 ++++---- .../NBKDoubleWidth+Text.swift | 4 +- .../NBKDoubleWidth+Uninitialized.swift | 52 +++++++++++++++++-- .../Models/NBKLittleEndianOrdered.swift | 8 +++ 8 files changed, 119 insertions(+), 40 deletions(-) diff --git a/README.md b/README.md index d622454c..934fcb97 100644 --- a/README.md +++ b/README.md @@ -94,7 +94,7 @@ Int256(5) % Int(5), UInt256(5) % UInt(5) > **Note**: The `Digit` type is `Int` when `Self` is signed, and `UInt` otherwise. -### ⭐️ Swift.StaticBigInt (v0.10.0) +### ⭐️ Feature: Swift.StaticBigInt `StaticBigInt` is disabled by default. You enable it in `Package.swift`. diff --git a/Sources/NBKCoreKit/Models/NBKLittleEndianOrdered.swift b/Sources/NBKCoreKit/Models/NBKLittleEndianOrdered.swift index d619c59a..a2364d44 100644 --- a/Sources/NBKCoreKit/Models/NBKLittleEndianOrdered.swift +++ b/Sources/NBKCoreKit/Models/NBKLittleEndianOrdered.swift @@ -36,11 +36,45 @@ // MARK: Initializers //=------------------------------------------------------------------------= - /// Creates a view presenting the collection's elements in an endianness-dependent order. + /// Creates a view presenting the collection's elements in an endianness-sensitive order. @inlinable public init(_ base: Base) { self.base = base } + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + /// Returns the iteration direction as 1 (front-to-back) or -1 (back-to-front). + @inlinable public var direction: Int { + #if _endian(big) + return -1 + #else + return (1) + #endif + } + + /// Returns the corresponding base index, assuming it exists. + /// + /// - Note: This operation is unchecked. + /// + /// - Parameter index: `self.startIndex <= index < self.endIndex` + /// + @inlinable public func baseIndex(_ index: Int) -> Base.Index { + #if _endian(big) + return self.base.index(self.base.endIndex, offsetBy: ~index) + #else + return self.base.index(self.base.startIndex, offsetBy: index) + #endif + } +} + +//=----------------------------------------------------------------------------= +// MARK: + Indices +//=----------------------------------------------------------------------------= + +extension NBKLittleEndianOrdered { + //=------------------------------------------------------------------------= // MARK: Accessors //=------------------------------------------------------------------------= @@ -98,6 +132,7 @@ index + distance } + // TODO: NBK.arrayIndex(_:offsetBy:limitedBy:) @inlinable public func index(_ index: Int, offsetBy distance: Int, limitedBy limit: Int) -> Int? { let distanceLimit: Int = self.distance(from: index, to: limit) @@ -108,20 +143,6 @@ return self.index(index, offsetBy: distance) as Int } - - /// Returns the corresponding base index, assuming it exists. - /// - /// - Note: This operation is unchecked. - /// - /// - Parameter index: `self.startIndex <= index < self.endIndex` - /// - @inlinable public func baseIndex(_ index: Int) -> Base.Index { - #if _endian(big) - return self.base.index(self.base.endIndex, offsetBy: ~index) - #else - return self.base.index(self.base.startIndex, offsetBy: index) - #endif - } } //=----------------------------------------------------------------------------= diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift index 8be749d4..eba8ea5f 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift @@ -31,10 +31,16 @@ extension NBKDoubleWidth { ? source.bitWidth <= Self.bitWidth : source.bitWidth <= Self.bitWidth + 1 && source.signum() >= 0 else { return nil } - + //=--------------------------------------= + // gets outlined without manual iteration + //=--------------------------------------= self = Self.uninitialized { value in - for index in value.indices { - value[unchecked: index] = source[index] + var index = value.startIndex + var pointer = value.base.baseAddress!.advanced(by: value.baseIndex(index)) + while index < value.endIndex { + pointer.initialize(to: source[index]) + pointer = pointer.advanced(by: value.direction) + value.formIndex(after: &index) } } } diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Numbers.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Numbers.swift index 992f86cc..ba44a414 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Numbers.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Numbers.swift @@ -73,9 +73,11 @@ extension NBKDoubleWidth { let isLessThanZero: Bool = T.isSigned && words.last?.mostSignificantBit == true let sign = UInt(repeating: isLessThanZero) //=--------------------------------------= - let value = Self.uninitialized { value in - for index in value.indices { - value[unchecked: index] = index < words.count ? words[words.index(words.startIndex, offsetBy: index)] : sign + let value = Self.uninitialized { value in + let start = value.base.baseAddress! + for index in value.indices { + let word = index < words.count ? words[words.index(words.startIndex, offsetBy: index)] : sign + start.advanced(by: value.baseIndex(index)).initialize(to: word) } } //=--------------------------------------= diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Rotations.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Rotations.swift index 34102b30..afa74cc4 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Rotations.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Rotations.swift @@ -69,13 +69,13 @@ extension NBKDoubleWidth { //=--------------------------------------= return Self.uninitialized { result in var (word) = self.last as UInt - var destination = words + var destination = result.index(result.startIndex, offsetBy: words) for source in self.indices { //=------------------------------= let pulled = word &>> pull (word) = self[source] let pushed = word &<< push - result[destination] = pulled | pushed + result.base.baseAddress!.advanced(by: result.baseIndex(destination)).initialize(to: pulled | pushed) //=------------------------------= result.formIndex(after: &destination) if destination >= result.endIndex { @@ -105,10 +105,10 @@ extension NBKDoubleWidth { if words.isZero { return self } //=--------------------------------------= return Self.uninitialized { result in - var destination = words + var destination = result.index(result.startIndex, offsetBy: words) for source in self.indices { //=------------------------------= - result[destination] = self[source] + result.base.baseAddress!.advanced(by: result.baseIndex(destination)).initialize(to: self[source]) //=------------------------------= result.formIndex(after: &destination) if destination >= result.endIndex { @@ -179,14 +179,14 @@ extension NBKDoubleWidth { //=--------------------------------------= return Self.uninitialized { result in var (word) = self.last as UInt - var destination = result.endIndex &+ ~(words) - precondition(0 ..< result.endIndex ~= destination) + var destination = result.index(result.endIndex, offsetBy: ~words) + precondition(result.startIndex ..< result.endIndex ~= destination) for source in self.indices { //=------------------------------= let pulled = word &>> push (word) = self[source] let pushed = word &<< pull - result[destination] = pulled | pushed + result.base.baseAddress!.advanced(by: result.baseIndex(destination)).initialize(to: pulled | pushed) //=------------------------------= result.formIndex(after: &destination) if destination >= result.endIndex { @@ -216,11 +216,11 @@ extension NBKDoubleWidth { if words.isZero { return self } //=--------------------------------------= return Self.uninitialized { result in - var destination = result.endIndex &- words - precondition(0 ..< result.endIndex ~= destination) - for source in self { + var destination = result.index(result.endIndex, offsetBy: -words) + precondition(result.startIndex ..< result.endIndex ~= destination) + for source in self.indices { //=------------------------------= - result[destination] = source + result.base.baseAddress!.advanced(by: result.baseIndex(destination)).initialize(to: self[source]) //=------------------------------= result.formIndex(after: &destination) if destination >= result.endIndex { diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text.swift index 41335392..8efcd8cf 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text.swift @@ -73,11 +73,11 @@ extension NBKDoubleWidth where High == High.Magnitude { let value = Self.uninitialized { value in for index in value.indices { if digits.isEmpty { - value[index] = UInt.zero + value.base.baseAddress!.advanced(by: value.baseIndex(index)).initialize(to: 0000) } else { let chunk = NBK.UnsafeUTF8(rebasing: NBK.removeSuffix(from: &digits, maxLength: radix.exponent)) guard let word = NBK.truncating(digits: chunk, radix: radix.base, as: UInt.self) else { return error = true } - value[index] = word + value.base.baseAddress!.advanced(by: value.baseIndex(index)).initialize(to: word) } } } diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Uninitialized.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Uninitialized.swift index 14868006..91dcf553 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Uninitialized.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Uninitialized.swift @@ -18,15 +18,57 @@ extension NBKDoubleWidth { //=------------------------------------------------------------------------= // MARK: Initializers //=------------------------------------------------------------------------= + // NOTE: Wrapped function call fixes Swift 5.7 performance problem. + //=------------------------------------------------------------------------= - /// Creates a new instance with access to a temporary allocation. - @inlinable public static func uninitialized(_ body: (inout Self) -> Void) -> Self { + /// Creates a new instance with unsafe access to uninitialized words. + /// + /// ```swift + /// let value = Int256.uninitialized { words in + /// for index in words.indices { + /// words.base.initializeElement(at: words.baseIndex(index), to: UInt.zero) + /// } + /// } + /// ``` + /// + @inlinable public static func uninitialized(_ body: (NBKLittleEndianOrdered) -> Void) -> Self { + Self(bitPattern: BitPattern.uninitialized(body)) + } +} + +//*============================================================================* +// MARK: * NBK x Double Width x Uninitialized x Uninitialized +//*============================================================================* + +extension NBKDoubleWidth where High == High.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Initializers x Private + //=------------------------------------------------------------------------= + + /// Creates a new instance with unsafe access to uninitialized words. + /// + /// ```swift + /// let value = Int256.uninitialized { words in + /// for index in words.indices { + /// words.base.initializeElement(at: words.baseIndex(index), to: UInt.zero) + /// } + /// } + /// ``` + /// + @inlinable static func uninitialized(_ body: (NBKLittleEndianOrdered) -> Void) -> Self { Swift.withUnsafeTemporaryAllocation(of: Self.self, capacity: 1) { buffer in + let pointer = buffer.baseAddress.unsafelyUnwrapped + //=----------------------------------= + // pointee: initialization by callee + //=----------------------------------= + pointer.withMemoryRebound(to: UInt.self, capacity: Self.count) { start in + body(NBKLittleEndianOrdered(NBK.UnsafeMutableWords(start: start, count: Self.count))) + } //=----------------------------------= - // TODO: trivial type de/init is req. + // pointee: deinitialization by move //=----------------------------------= - body( &buffer.baseAddress.unsafelyUnwrapped.pointee) - return buffer.baseAddress.unsafelyUnwrapped.pointee + return pointer.move() } } } diff --git a/Tests/NBKCoreKitTests/Models/NBKLittleEndianOrdered.swift b/Tests/NBKCoreKitTests/Models/NBKLittleEndianOrdered.swift index a5c8167f..efd6e1ff 100644 --- a/Tests/NBKCoreKitTests/Models/NBKLittleEndianOrdered.swift +++ b/Tests/NBKCoreKitTests/Models/NBKLittleEndianOrdered.swift @@ -52,6 +52,14 @@ file: StaticString = #file, line: UInt = #line) where B.Element: Equatable, B.I XCTAssertEqual(Array(lhs), rhs, file: file, line: line) XCTAssertEqual(Array(lhs.reversed()), rhs.reversed(), file: file, line: line) + do { + var rhsIndex = lhs.baseIndex(lhs.startIndex) + for lhsIndex in lhs.indices { + XCTAssertEqual(lhs[lhsIndex], rhs[rhsIndex], file: file, line: line) + rhs.formIndex(&rhsIndex, offsetBy: lhs.direction) + } + } + do { var lhsIndex = lhs.startIndex var rhsIndex = rhs.startIndex From 2c1cdf9de997a089d194eb5e414aa523fa9c3f7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sat, 26 Aug 2023 14:56:25 +0200 Subject: [PATCH 063/111] Version 0.10.0. --- Numberick-NBKCoreKit.podspec | 2 +- Numberick-NBKDoubleWidthKit.podspec | 2 +- Numberick.podspec | 2 +- README.md | 1 - 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Numberick-NBKCoreKit.podspec b/Numberick-NBKCoreKit.podspec index 15363610..b549c4ec 100644 --- a/Numberick-NBKCoreKit.podspec +++ b/Numberick-NBKCoreKit.podspec @@ -12,7 +12,7 @@ #*=============================================================================* Pod::Spec.new do |spec| - spec.version = "0.10.0-alpha" + spec.version = "0.10.0" spec.module_name = "NBKCoreKit" spec.name = "Numberick-#{spec.module_name}" spec.summary = "A new protocol hierarchy that refines Swift's standard library." diff --git a/Numberick-NBKDoubleWidthKit.podspec b/Numberick-NBKDoubleWidthKit.podspec index 11e113cc..2eec78a8 100644 --- a/Numberick-NBKDoubleWidthKit.podspec +++ b/Numberick-NBKDoubleWidthKit.podspec @@ -12,7 +12,7 @@ #*=============================================================================* Pod::Spec.new do |spec| - spec.version = "0.10.0-alpha" + spec.version = "0.10.0" spec.module_name = "NBKDoubleWidthKit" spec.name = "Numberick-#{spec.module_name}" spec.summary = "A composable, large, fixed-width, two's complement, binary integer." diff --git a/Numberick.podspec b/Numberick.podspec index 3b9d3cbe..e7aea835 100644 --- a/Numberick.podspec +++ b/Numberick.podspec @@ -12,7 +12,7 @@ #*=============================================================================* Pod::Spec.new do |spec| - spec.version = "0.10.0-alpha" + spec.version = "0.10.0" spec.name = "Numberick" spec.module_name = "Numberick" spec.summary = "✨ An arithmagick overhaul in Swift." diff --git a/README.md b/README.md index 934fcb97..7584e8ea 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,6 @@ | Package | Swift | iOS | Mac Catalyst | macOS | tvOS | watchOS | |:-------:|:-----:|:-----:|:------------:|:-----:|:-----:|:-------:| | 0.10.0 | 5.7 | 14.0 | 14.0 | 11.0 | 14.0 | 7.0 | -| 0.9.0 | 5.7 | 16.4 | 16.4 | 13.3 | 16.4 | 9.4 | ## NBKCoreKit ([Sources][COR/S], [Tests][COR/T], [Benchmarks][COR/B]) From bd969cb0068c97d0dcec3be12a9ce3c14227c44c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Mon, 28 Aug 2023 08:36:15 +0200 Subject: [PATCH 064/111] Cleanup. --- Sources/NBKCoreKit/Models/NBKLittleEndianOrdered.swift | 2 +- Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text.swift | 9 ++++++--- .../NBKDoubleWidth+Words+Pointers.swift | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Sources/NBKCoreKit/Models/NBKLittleEndianOrdered.swift b/Sources/NBKCoreKit/Models/NBKLittleEndianOrdered.swift index a2364d44..e7ae6455 100644 --- a/Sources/NBKCoreKit/Models/NBKLittleEndianOrdered.swift +++ b/Sources/NBKCoreKit/Models/NBKLittleEndianOrdered.swift @@ -70,7 +70,7 @@ } //=----------------------------------------------------------------------------= -// MARK: + Indices +// MARK: + Collection //=----------------------------------------------------------------------------= extension NBKLittleEndianOrdered { diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text.swift index 8efcd8cf..562b3ba7 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text.swift @@ -113,13 +113,15 @@ extension NBKDoubleWidth where High == High.Magnitude { // MARK: Details x Encode x Private //=------------------------------------------------------------------------= - @inlinable func description(radix: NBK.AnyRadixUIntRoot, alphabet: NBK.MaxRadixAlphabetEncoder, prefix: NBK.UnsafeUTF8, suffix: NBK.UnsafeUTF8) -> String { + @inlinable func description(radix: NBK.AnyRadixUIntRoot, alphabet: NBK.MaxRadixAlphabetEncoder, + prefix: NBK.UnsafeUTF8, suffix: NBK.UnsafeUTF8) -> String { switch radix.power.isZero { case true: return self.description(radix: NBK .PerfectRadixUIntRoot(unchecked: radix), alphabet: alphabet, prefix: prefix, suffix: suffix) case false: return self.description(radix: NBK.ImperfectRadixUIntRoot(unchecked: radix), alphabet: alphabet, prefix: prefix, suffix: suffix) } } - @inlinable func description(radix: NBK.PerfectRadixUIntRoot, alphabet: NBK.MaxRadixAlphabetEncoder, prefix: NBK.UnsafeUTF8, suffix: NBK.UnsafeUTF8) -> String { + @inlinable func description(radix: NBK.PerfectRadixUIntRoot, alphabet: NBK.MaxRadixAlphabetEncoder, + prefix: NBK.UnsafeUTF8, suffix: NBK.UnsafeUTF8) -> String { //=--------------------------------------= // with one buffer pointer specialization //=--------------------------------------= @@ -129,7 +131,8 @@ extension NBKDoubleWidth where High == High.Magnitude { } } - @inlinable func description(radix: NBK.ImperfectRadixUIntRoot, alphabet: NBK.MaxRadixAlphabetEncoder, prefix: NBK.UnsafeUTF8, suffix: NBK.UnsafeUTF8) -> String { + @inlinable func description(radix: NBK.ImperfectRadixUIntRoot, alphabet: NBK.MaxRadixAlphabetEncoder, + prefix: NBK.UnsafeUTF8, suffix: NBK.UnsafeUTF8) -> String { //=--------------------------------------= // with one buffer pointer specialization //=--------------------------------------= diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words+Pointers.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words+Pointers.swift index 5ec9837f..26c6af0d 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words+Pointers.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words+Pointers.swift @@ -34,7 +34,7 @@ extension NBKDoubleWidth { } } } - + /// Grants unsafe access to the collection's contiguous storage. /// /// The elements of the contiguous storage appear in the order of the collection. From 6b3e8f62575d989ee451a166ec175f61c6632daf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Mon, 28 Aug 2023 08:41:39 +0200 Subject: [PATCH 065/111] [NBKCoreKit] Endianness (#74). --- Sources/NBKCoreKit/Models/NBKEndianness.swift | 55 +++++++++++++++++++ .../Models/NBKEndianness.swift | 45 +++++++++++++++ 2 files changed, 100 insertions(+) create mode 100644 Sources/NBKCoreKit/Models/NBKEndianness.swift create mode 100644 Tests/NBKCoreKitTests/Models/NBKEndianness.swift diff --git a/Sources/NBKCoreKit/Models/NBKEndianness.swift b/Sources/NBKCoreKit/Models/NBKEndianness.swift new file mode 100644 index 00000000..388bbec7 --- /dev/null +++ b/Sources/NBKCoreKit/Models/NBKEndianness.swift @@ -0,0 +1,55 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +//*============================================================================* +// MARK: * NBK x Endianness +//*============================================================================* + +/// An enumeration of big and little endianness. +/// +/// ### Static vs Dynamic +/// +/// Some algorithms differ depending on endianness. Generic type parameterization +/// can express the difference, but dynamic solutions are often viable. This type +/// encurages the latter. +/// +@frozen public enum NBKEndianness: Hashable { + + //=------------------------------------------------------------------------= + // MARK: State + //=------------------------------------------------------------------------= + + /// A value representing big endianness. + case big + + /// A value representing little endianness. + case little + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + /// Returns the endianness of the current system. + @inlinable public static var system: Self { + #if _endian(big) + return .big + #else + return .little + #endif + } + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + /// Returns the opposite endianness. + @inlinable public static prefix func !(operand: Self) -> Self { + switch operand { case .big: return .little; case .little: return .big } + } +} diff --git a/Tests/NBKCoreKitTests/Models/NBKEndianness.swift b/Tests/NBKCoreKitTests/Models/NBKEndianness.swift new file mode 100644 index 00000000..9af975ec --- /dev/null +++ b/Tests/NBKCoreKitTests/Models/NBKEndianness.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. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +import XCTest + +//*============================================================================* +// MARK: * NBK x Endianness +//*============================================================================* + +final class NBKEndiannessTests: XCTestCase { + + typealias T = NBKEndianness + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testSystem() { + #if _endian(big) + XCTAssertEqual(T.system, T.big) + #elseif _endian(little) + XCTAssertEqual(T.system, T.little) + #endif + } + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testOpposite() { + XCTAssertEqual(!T.big, T.little) + XCTAssertEqual(!T.little, T.big) + } +} + +#endif From 645f0f2b7a280d88c5b5fbd27bec08f3c823fde8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Mon, 28 Aug 2023 09:00:11 +0200 Subject: [PATCH 066/111] [NBKCoreKit] Endianness (#74). --- README.md | 1 + Sources/NBKCoreKit/Models/NBKEndianness.swift | 20 ++++++++++--------- .../Documentation.docc/Documentation.md | 6 ++++++ 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 7584e8ea..761e556e 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,7 @@ A new protocol hierarchy that refines Swift's standard library. ### Models +- [NBKEndianness](Sources/NBKCoreKit/Models/NBKEndianness.swift) - [NBKLittleEndianOrdered](Sources/NBKCoreKit/Models/NBKLittleEndianOrdered.swift) ## [NBKDoubleWidthKit][DBL/D] ([Sources][DBL/S], [Tests][DBL/T], [Benchmarks][DBL/B]) diff --git a/Sources/NBKCoreKit/Models/NBKEndianness.swift b/Sources/NBKCoreKit/Models/NBKEndianness.swift index 388bbec7..5b6f0d8c 100644 --- a/Sources/NBKCoreKit/Models/NBKEndianness.swift +++ b/Sources/NBKCoreKit/Models/NBKEndianness.swift @@ -11,7 +11,7 @@ // MARK: * NBK x Endianness //*============================================================================* -/// An enumeration of big and little endianness. +/// An enumeration of little and big endianness. /// /// ### Static vs Dynamic /// @@ -24,12 +24,14 @@ //=------------------------------------------------------------------------= // MARK: State //=------------------------------------------------------------------------= + // NOTE: The raw value is equal to the case index. + //=------------------------------------------------------------------------= - /// A value representing big endianness. - case big + /// A value representing a least-to-most-significant byte order. + case little // 0x00 - /// A value representing little endianness. - case little + /// A value representing a most-to-least-significant byte order. + case big // 0x01 //=------------------------------------------------------------------------= // MARK: Initializers @@ -37,10 +39,10 @@ /// Returns the endianness of the current system. @inlinable public static var system: Self { - #if _endian(big) - return .big - #else + #if _endian(little) return .little + #else + return .big #endif } @@ -50,6 +52,6 @@ /// Returns the opposite endianness. @inlinable public static prefix func !(operand: Self) -> Self { - switch operand { case .big: return .little; case .little: return .big } + switch operand { case .little: return .big; case .big: return .little } } } diff --git a/Sources/Numberick/Documentation.docc/Documentation.md b/Sources/Numberick/Documentation.docc/Documentation.md index e53f59f5..605c272b 100644 --- a/Sources/Numberick/Documentation.docc/Documentation.md +++ b/Sources/Numberick/Documentation.docc/Documentation.md @@ -15,6 +15,11 @@ A new protocol hierarchy that refines Swift's standard library. - ``NBKSignedInteger`` - ``NBKUnsignedInteger`` +### Models + +- ``NBKEndianness`` +- ``NBKLittleEndianOrdered`` + ## NBKDoubleWidthKit A composable, large, fixed-width, two's complement, binary integer. @@ -105,6 +110,7 @@ Int256(5) % Int(5), UInt256(5) % UInt(5) ### Models - ``NBKDoubleWidth`` +- ``NBKEndianness`` - ``NBKLittleEndianOrdered`` ### Integers From fd7303561f80541b1979f67fb2f61007d793f3e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Mon, 28 Aug 2023 10:27:54 +0200 Subject: [PATCH 067/111] [NBKCoreKit] TwinHeaded (#72). --- README.md | 1 + Sources/NBKCoreKit/Models/NBKEndianness.swift | 1 - Sources/NBKCoreKit/Models/NBKTwinHeaded.swift | 177 ++++++++++++++++++ .../Documentation.docc/Documentation.md | 2 + .../Models/NBKTwinHeaded.swift | 122 ++++++++++++ 5 files changed, 302 insertions(+), 1 deletion(-) create mode 100644 Sources/NBKCoreKit/Models/NBKTwinHeaded.swift create mode 100644 Tests/NBKCoreKitTests/Models/NBKTwinHeaded.swift diff --git a/README.md b/README.md index 761e556e..740ec193 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,7 @@ A new protocol hierarchy that refines Swift's standard library. - [NBKEndianness](Sources/NBKCoreKit/Models/NBKEndianness.swift) - [NBKLittleEndianOrdered](Sources/NBKCoreKit/Models/NBKLittleEndianOrdered.swift) +- [NBKTwinHeaded](Sources/NBKCoreKit/Models/NBKTwinHeaded.swift) ## [NBKDoubleWidthKit][DBL/D] ([Sources][DBL/S], [Tests][DBL/T], [Benchmarks][DBL/B]) diff --git a/Sources/NBKCoreKit/Models/NBKEndianness.swift b/Sources/NBKCoreKit/Models/NBKEndianness.swift index 5b6f0d8c..d5e4787b 100644 --- a/Sources/NBKCoreKit/Models/NBKEndianness.swift +++ b/Sources/NBKCoreKit/Models/NBKEndianness.swift @@ -20,7 +20,6 @@ /// encurages the latter. /// @frozen public enum NBKEndianness: Hashable { - //=------------------------------------------------------------------------= // MARK: State //=------------------------------------------------------------------------= diff --git a/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift b/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift new file mode 100644 index 00000000..dc03746c --- /dev/null +++ b/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift @@ -0,0 +1,177 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +//*============================================================================* +// MARK: * NBK x Twin Headed +//*============================================================================* + +/// A collection that iterates forwards or backwards in a dynamic but branchless way. +@frozen public struct NBKTwinHeaded: RandomAccessCollection where Base: RandomAccessCollection { + + public typealias Index = Int + + public typealias Indices = Range + + public typealias Element = Base.Element + + //=------------------------------------------------------------------------= + // MARK: State + //=------------------------------------------------------------------------= + + public var base: Base + @usableFromInline var mask: Self.Index + @usableFromInline var edge: Base.Index + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + /// Creates a view presenting the collection's elements in a dynamic order. + /// + /// - Parameters: + /// - base: The collection viewed through this instance. + /// - reversed: A value indicating whether the direction should be reversed. + /// + @inlinable public init(_ other: Self, reversed: Bool = false) { + self.init(other.base, reversed: other.mask.isLessThanZero != reversed) + } + + /// Creates a view presenting the collection's elements in a dynamic order. + /// + /// - Parameters: + /// - base: The collection viewed through this instance. + /// - reversed: A value indicating whether the direction should be reversed. + /// + @_disfavoredOverload @inlinable public init(_ base: Base, reversed: Bool = false) { + self.base = base + self.mask = Int.zero + self.edge = self.base.startIndex + if reversed { self.reverse() } + } + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + /// Forms this collection but reversed. + /// + /// - Complexity: O(1). + /// + @inlinable public mutating func reverse() { + self.edge = self.base.index(self.edge, offsetBy: self.mask ^ self.count - self.mask) + self.mask = ~self.mask + } + + /// Returns this collection but reversed. + /// + /// - Complexity: O(1). + /// + @inlinable public func reversed() -> Self { + var result = self; result.reverse(); return result + } + + //=------------------------------------------------------------------------= + // MARK: Utilities x Private + //=------------------------------------------------------------------------= + + /// Returns the corresponding index in the base collection. + /// + /// - Parameter index: `self.startIndex <= index < self.endIndex` + /// + @inlinable func baseSubscriptIndex(_ index: Int) -> Base.Index { + assert(self.startIndex <= index && index < self.endIndex) + return self.base.index(self.edge, offsetBy: self.mask ^ index) + } +} + +//=----------------------------------------------------------------------------= +// MARK: + Collection +//=----------------------------------------------------------------------------= + +extension NBKTwinHeaded { + + //=------------------------------------------------------------------------= + // MARK: Accessors + //=------------------------------------------------------------------------= + + @inlinable public var count: Int { + self.base.count + } + + @inlinable public var startIndex: Int { + Int.zero + } + + @inlinable public var endIndex: Int { + self.count + } + + @inlinable public var indices: Range { + Range(uncheckedBounds:(self.startIndex, self.endIndex)) + } + + //=------------------------------------------------------------------------= + // MARK: Accessors x Element + //=------------------------------------------------------------------------= + + @inlinable public subscript(index: Int) -> Element { + _read { yield self.base[self.baseSubscriptIndex(index)] } + } + + @inlinable public subscript(index: Int) -> Element where Base: MutableCollection { + _read { yield self.base[self.baseSubscriptIndex(index)] } + _modify { yield &self.base[self.baseSubscriptIndex(index)] } + } + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + @inlinable public func distance(from start: Int, to end: Int) -> Int { + end - start + } + + @inlinable public func index(after index: Int) -> Int { + index + 1 + } + + @inlinable public func formIndex(after index: inout Int) { + index += 1 + } + + @inlinable public func index(before index: Int) -> Int { + index - 1 + } + + @inlinable public func formIndex(before index: inout Int) { + index -= 1 + } + + @inlinable public func index(_ index: Int, offsetBy distance: Int) -> Int { + index + distance + } + + // TODO: NBK.arrayIndex(_:offsetBy:limitedBy:) + @inlinable public func index(_ index: Int, offsetBy distance: Int, limitedBy limit: Int) -> Int? { + let distanceLimit: Int = self.distance(from: index, to: limit) + + guard distance >= 0 + ? distance <= distanceLimit || distanceLimit < 0 + : distance >= distanceLimit || distanceLimit > 0 + else { return nil } + + return self.index(index, offsetBy: distance) as Int + } +} + +//=----------------------------------------------------------------------------= +// MARK: + Conditional Conformances +//=----------------------------------------------------------------------------= + +extension NBKTwinHeaded: MutableCollection where Base: MutableCollection { } diff --git a/Sources/Numberick/Documentation.docc/Documentation.md b/Sources/Numberick/Documentation.docc/Documentation.md index 605c272b..1dd9d99e 100644 --- a/Sources/Numberick/Documentation.docc/Documentation.md +++ b/Sources/Numberick/Documentation.docc/Documentation.md @@ -19,6 +19,7 @@ A new protocol hierarchy that refines Swift's standard library. - ``NBKEndianness`` - ``NBKLittleEndianOrdered`` +- ``NBKTwinHeaded`` ## NBKDoubleWidthKit @@ -112,6 +113,7 @@ Int256(5) % Int(5), UInt256(5) % UInt(5) - ``NBKDoubleWidth`` - ``NBKEndianness`` - ``NBKLittleEndianOrdered`` +- ``NBKTwinHeaded`` ### Integers diff --git a/Tests/NBKCoreKitTests/Models/NBKTwinHeaded.swift b/Tests/NBKCoreKitTests/Models/NBKTwinHeaded.swift new file mode 100644 index 00000000..58ac182f --- /dev/null +++ b/Tests/NBKCoreKitTests/Models/NBKTwinHeaded.swift @@ -0,0 +1,122 @@ +#if DEBUG + +import NBKCoreKit +import XCTest + +//*============================================================================* +// MARK: * NBK x Twin Headed +//*============================================================================* + +final class NBKTwinHeadedTests: XCTestCase { + + typealias T = NBKTwinHeaded where Base: RandomAccessCollection + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testInit() { + let base = [0, 1, 2, 3] + + NBKAssertIteration( T(base, reversed: false), [0, 1, 2, 3]) + NBKAssertIteration( T(base, reversed: true ), [3, 2, 1, 0]) + NBKAssertIteration(T(T(base, reversed: false), reversed: false), [0, 1, 2, 3]) + NBKAssertIteration(T(T(base, reversed: false), reversed: true ), [3, 2, 1, 0]) + NBKAssertIteration(T(T(base, reversed: true ), reversed: false), [3, 2, 1, 0]) + NBKAssertIteration(T(T(base, reversed: true ), reversed: true ), [0, 1, 2, 3]) + } + + func testInitDoesNotReverseByDefault() { + let base = [0, 1, 2, 3] + + NBKAssertIteration( T(base), [0, 1, 2, 3]) + NBKAssertIteration(T(T(base)), [0, 1, 2, 3]) + } + + func testReversed() { + let base = [0, 1, 2, 3] + + NBKAssertIteration(T(base, reversed: false), [0, 1, 2, 3]) + NBKAssertIteration(T(base, reversed: false).reversed(), [3, 2, 1, 0]) + NBKAssertIteration(T(base, reversed: false).reversed().reversed(), [0, 1, 2, 3]) + + NBKAssertIteration(T(base, reversed: true ), [3, 2, 1, 0]) + NBKAssertIteration(T(base, reversed: true ).reversed(), [0, 1, 2, 3]) + NBKAssertIteration(T(base, reversed: true ).reversed().reversed(), [3, 2, 1, 0]) + + XCTAssert(type(of: T(base)) == type(of: T(T(base)))) + XCTAssert(type(of: T(base)) == type(of: T(base).reversed())) + } +} + +//*============================================================================* +// MARK: * NBK x Twin Headed x Assertions +//*============================================================================* + +private func NBKAssertIteration( +_ lhs: B, _ rhs: [B.Element], +file: StaticString = #file, line: UInt = #line) where B.Element: FixedWidthInteger, B.Element: Equatable { + XCTAssertEqual(Array(lhs), rhs, file: file, line: line) + XCTAssertEqual(Array(lhs.reversed()), rhs.reversed(), file: file, line: line) + XCTAssertEqual(Array({ var x = lhs; x.reverse(); return x }()), rhs.reversed(), file: file, line: line) + + do { + var lhsIndex = lhs.startIndex + var rhsIndex = rhs.startIndex + while lhsIndex < lhs.endIndex { + XCTAssertEqual(lhs[lhsIndex], rhs[rhsIndex], file: file, line: line) + lhsIndex = lhs.index(after: lhsIndex) + rhsIndex = rhs.index(after: rhsIndex) + } + } + + do { + var lhsIndex = lhs.endIndex + var rhsIndex = rhs.endIndex + while lhsIndex > lhs.startIndex { + lhsIndex = lhs.index(before: lhsIndex) + rhsIndex = rhs.index(before: rhsIndex) + XCTAssertEqual(lhs[lhsIndex], rhs[rhsIndex], file: file, line: line) + } + } + + do { + for lhsIndex in lhs.indices.enumerated() { + XCTAssertEqual(lhs[lhsIndex.element], rhs[lhsIndex.offset], file: file, line: line) + } + } + + do { + for dropFirst in 0 ..< (2 * lhs.count) { + XCTAssertEqual(Array(lhs.dropFirst(dropFirst)), Array(rhs.dropFirst(dropFirst)), file: file, line: line) + if let first = lhs.dropFirst(dropFirst).first { + let firstIndex = lhs.index(lhs.startIndex, offsetBy: dropFirst) + XCTAssertEqual(first, lhs[firstIndex], file: file, line: line) + } + } + } + + do { + for dropLast in 0 ..< (2 * lhs.count) { + XCTAssertEqual(Array(lhs.dropLast(dropLast)), Array(rhs.dropLast(dropLast)), file: file, line: line) + if let last = lhs.dropLast(dropLast).last { + let lastIndex = lhs.index(lhs.endIndex, offsetBy: ~dropLast) + XCTAssertEqual(last, lhs[lastIndex], file: file, line: line) + } + } + } + + do { + var lhs = lhs, lhsIndex = lhs.startIndex + var rhs = rhs, rhsIndex = rhs.startIndex + while lhsIndex < lhs.endIndex { + lhs[lhsIndex] &+= 1 + rhs[rhsIndex] &+= 1 + XCTAssertEqual(lhs[lhsIndex], rhs[rhsIndex], file: file, line: line) + lhs.formIndex(after: &lhsIndex) + rhs.formIndex(after: &rhsIndex) + } + } +} + +#endif From 7fc54fb94a36ef24c5042bfda22b5e9baabe186c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Mon, 28 Aug 2023 11:01:31 +0200 Subject: [PATCH 068/111] [NBKCoreKit] TwinHeaded (#72). --- Sources/NBKCoreKit/Models/NBKTwinHeaded.swift | 20 ++++++++-- .../Models/NBKTwinHeaded.swift | 40 ++++++++++++++++--- 2 files changed, 50 insertions(+), 10 deletions(-) diff --git a/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift b/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift index dc03746c..f4a9160c 100644 --- a/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift +++ b/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift @@ -14,6 +14,8 @@ /// A collection that iterates forwards or backwards in a dynamic but branchless way. @frozen public struct NBKTwinHeaded: RandomAccessCollection where Base: RandomAccessCollection { + public typealias Base = Base + public typealias Index = Int public typealias Indices = Range @@ -38,8 +40,18 @@ /// - base: The collection viewed through this instance. /// - reversed: A value indicating whether the direction should be reversed. /// - @inlinable public init(_ other: Self, reversed: Bool = false) { - self.init(other.base, reversed: other.mask.isLessThanZero != reversed) + @inlinable public init(_ other: Self, reversed: Bool = false) { + self.init(other.base, reversed: other.mask.isZero == reversed) + } + + /// Creates a view presenting the collection's elements in a dynamic order. + /// + /// - Parameters: + /// - base: The collection viewed through this instance. + /// - reversed: A value indicating whether the direction should be reversed. + /// + @inlinable public init(_ other: ReversedCollection, reversed: Bool = false) { + self.init(other.reversed(), reversed: !reversed) } /// Creates a view presenting the collection's elements in a dynamic order. @@ -54,9 +66,9 @@ self.edge = self.base.startIndex if reversed { self.reverse() } } - + //=------------------------------------------------------------------------= - // MARK: Utilities + // MARK: Transformations //=------------------------------------------------------------------------= /// Forms this collection but reversed. diff --git a/Tests/NBKCoreKitTests/Models/NBKTwinHeaded.swift b/Tests/NBKCoreKitTests/Models/NBKTwinHeaded.swift index 58ac182f..bf87fce9 100644 --- a/Tests/NBKCoreKitTests/Models/NBKTwinHeaded.swift +++ b/Tests/NBKCoreKitTests/Models/NBKTwinHeaded.swift @@ -1,3 +1,12 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 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 @@ -12,27 +21,46 @@ final class NBKTwinHeadedTests: XCTestCase { typealias T = NBKTwinHeaded where Base: RandomAccessCollection //=------------------------------------------------------------------------= - // MARK: Tests + // MARK: Tests x Initializers //=------------------------------------------------------------------------= - func testInit() { + func testFromBase() { let base = [0, 1, 2, 3] + NBKAssertIteration( T(base), [0, 1, 2, 3]) + NBKAssertIteration(T(T(base)), [0, 1, 2, 3]) + NBKAssertIteration( T(base, reversed: false), [0, 1, 2, 3]) NBKAssertIteration( T(base, reversed: true ), [3, 2, 1, 0]) NBKAssertIteration(T(T(base, reversed: false), reversed: false), [0, 1, 2, 3]) NBKAssertIteration(T(T(base, reversed: false), reversed: true ), [3, 2, 1, 0]) NBKAssertIteration(T(T(base, reversed: true ), reversed: false), [3, 2, 1, 0]) NBKAssertIteration(T(T(base, reversed: true ), reversed: true ), [0, 1, 2, 3]) + + XCTAssert(T<[Int]>.self == type(of: T(base) )) + XCTAssert(T<[Int]>.self == type(of: T(T(base)))) } - func testInitDoesNotReverseByDefault() { - let base = [0, 1, 2, 3] + func testFromReversedCollection() { + let base = [3, 2, 1, 0].reversed() as ReversedCollection<[Int]> NBKAssertIteration( T(base), [0, 1, 2, 3]) NBKAssertIteration(T(T(base)), [0, 1, 2, 3]) + + NBKAssertIteration( T(base, reversed: false), [0, 1, 2, 3]) + NBKAssertIteration( T(base, reversed: true ), [3, 2, 1, 0]) + NBKAssertIteration(T(T(base, reversed: false), reversed: false), [0, 1, 2, 3]) + NBKAssertIteration(T(T(base, reversed: false), reversed: true ), [3, 2, 1, 0]) + NBKAssertIteration(T(T(base, reversed: true ), reversed: false), [3, 2, 1, 0]) + NBKAssertIteration(T(T(base, reversed: true ), reversed: true ), [0, 1, 2, 3]) + + XCTAssert(T<[Int]>.self == type(of: T(base))) } + //=------------------------------------------------------------------------= + // MARK: Tests x Transformations + //=------------------------------------------------------------------------= + func testReversed() { let base = [0, 1, 2, 3] @@ -44,8 +72,8 @@ final class NBKTwinHeadedTests: XCTestCase { NBKAssertIteration(T(base, reversed: true ).reversed(), [0, 1, 2, 3]) NBKAssertIteration(T(base, reversed: true ).reversed().reversed(), [3, 2, 1, 0]) - XCTAssert(type(of: T(base)) == type(of: T(T(base)))) - XCTAssert(type(of: T(base)) == type(of: T(base).reversed())) + XCTAssert(T<[Int]>.self == type(of: T(base))) + XCTAssert(T<[Int]>.self == type(of: T(base).reversed())) } } From 09ccc6f0c9747ed38a29d39e019cf31fd04f9b62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Tue, 29 Aug 2023 09:20:52 +0200 Subject: [PATCH 069/111] [NBKCoreKit] TwinHeaded (#72). --- Sources/NBKCoreKit/Models/NBKTwinHeaded.swift | 141 ++++++++++++++--- .../Models/NBKTwinHeaded.swift | 149 ++++++++++++++---- 2 files changed, 241 insertions(+), 49 deletions(-) diff --git a/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift b/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift index f4a9160c..16e8dcc4 100644 --- a/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift +++ b/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift @@ -22,13 +22,29 @@ public typealias Element = Base.Element + public typealias SubSequence = Slice + //=------------------------------------------------------------------------= // MARK: State //=------------------------------------------------------------------------= - public var base: Base + /// The base collection that is viewed through this instance. + /// + /// - Note: The base collection must be private if one of its indices is stored. + /// + @usableFromInline var body: Base + + /// The bit-mask used to change the offset based on the current direction. + /// + /// It is equal to zero when front-to-back, and minus one otherwise. + /// @usableFromInline var mask: Self.Index - @usableFromInline var edge: Base.Index + + /// The base index to be offset. + /// + /// It is the base's start index when front-to-back, and its end index otherwise. + /// + @usableFromInline var head: Base.Index //=------------------------------------------------------------------------= // MARK: Initializers @@ -40,8 +56,8 @@ /// - base: The collection viewed through this instance. /// - reversed: A value indicating whether the direction should be reversed. /// - @inlinable public init(_ other: Self, reversed: Bool = false) { - self.init(other.base, reversed: other.mask.isZero == reversed) + @inlinable public init(_ other: Self, reversed: Bool = false) { + self.init(other.base, reversed: other.isFrontToBack == reversed) } /// Creates a view presenting the collection's elements in a dynamic order. @@ -61,12 +77,41 @@ /// - reversed: A value indicating whether the direction should be reversed. /// @_disfavoredOverload @inlinable public init(_ base: Base, reversed: Bool = false) { - self.base = base - self.mask = Int.zero - self.edge = self.base.startIndex + self.body = base + self.mask = Int .zero + self.head = self.body.startIndex if reversed { self.reverse() } } + //=------------------------------------------------------------------------= + // MARK: Accessors + //=------------------------------------------------------------------------= + + /// The base collection that is viewed through this instance. + @inlinable public var base: Base { + self.body as Base + } + + /// Returns whether the base collection's elements are presented front-to-back. + @inlinable public var isFrontToBack: Bool { + self.mask == ( 0) as Int + } + + /// Returns the base collection, if its elements matches this collection. + @inlinable public var asFrontToBack: Base? { + self.isFrontToBack ? self.base : nil + } + + /// Returns whether the base collection's elements are presented back-to-front. + @inlinable public var isBackToFront: Bool { + self.mask == (-1) as Int + } + + /// Returns the base collection but reversed, if its elements matches this collection. + @inlinable public var asBackToFront: ReversedCollection? { + self.isBackToFront ? self.base.reversed() : nil + } + //=------------------------------------------------------------------------= // MARK: Transformations //=------------------------------------------------------------------------= @@ -76,7 +121,7 @@ /// - Complexity: O(1). /// @inlinable public mutating func reverse() { - self.edge = self.base.index(self.edge, offsetBy: self.mask ^ self.count - self.mask) + self.head = self.baseIndex(self.endIndex) self.mask = ~self.mask } @@ -92,13 +137,39 @@ // MARK: Utilities x Private //=------------------------------------------------------------------------= - /// Returns the corresponding index in the base collection. + /// Returns the base collection's corresponding subscript index. /// /// - Parameter index: `self.startIndex <= index < self.endIndex` /// @inlinable func baseSubscriptIndex(_ index: Int) -> Base.Index { assert(self.startIndex <= index && index < self.endIndex) - return self.base.index(self.edge, offsetBy: self.mask ^ index) + return self.base.index(self.head, offsetBy: self.mask ^ index) + } + + /// Returns the base collection's corresponding index. + /// + /// - Parameter index: `self.startIndex <= index <= self.endIndex` + /// + @inlinable func baseIndex(_ index: Int) -> Base.Index { + assert(self.startIndex <= index && index <= self.endIndex) + return self.base.index(self.head, offsetBy: self.mask ^ index - self.mask) + } + + /// Returns the base collection's corresponding indices. + /// + /// - Parameter index: `self.startIndex <= index <= self.endIndex` + /// + @inlinable func baseIndices(_ indices: Range) -> Range { + assert(self.startIndex <= indices.lowerBound && indices.upperBound <= self.endIndex) + + var lowerBound = self.baseIndex(indices.lowerBound) + var upperBound = self.baseIndex(indices.upperBound) + + if self.isBackToFront { + Swift.swap(&lowerBound, &upperBound) + } + + return Range(uncheckedBounds:(lowerBound, upperBound)) } } @@ -128,17 +199,8 @@ extension NBKTwinHeaded { Range(uncheckedBounds:(self.startIndex, self.endIndex)) } - //=------------------------------------------------------------------------= - // MARK: Accessors x Element - //=------------------------------------------------------------------------= - @inlinable public subscript(index: Int) -> Element { - _read { yield self.base[self.baseSubscriptIndex(index)] } - } - - @inlinable public subscript(index: Int) -> Element where Base: MutableCollection { - _read { yield self.base[self.baseSubscriptIndex(index)] } - _modify { yield &self.base[self.baseSubscriptIndex(index)] } + _read { yield self.base[self.baseSubscriptIndex(index)] } } //=------------------------------------------------------------------------= @@ -183,7 +245,42 @@ extension NBKTwinHeaded { } //=----------------------------------------------------------------------------= -// MARK: + Conditional Conformances +// MARK: + Mutable Collection +//=----------------------------------------------------------------------------= + +extension NBKTwinHeaded: MutableCollection where Base: MutableCollection { + + //=------------------------------------------------------------------------= + // MARK: Accessors + //=------------------------------------------------------------------------= + + @inlinable public subscript(index: Int) -> Element { + _read { yield self.body[self.baseSubscriptIndex(index)] } + _modify { yield &self.body[self.baseSubscriptIndex(index)] } + } +} + +//=----------------------------------------------------------------------------= +// MARK: + where Base is Unsafe Buffer Pointer //=----------------------------------------------------------------------------= -extension NBKTwinHeaded: MutableCollection where Base: MutableCollection { } +extension NBKTwinHeaded { + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + /// Creates a collection with the same data and direction as the given subsequence. + @inlinable public init(rebasing subsequence: SubSequence) where Base == UnsafeBufferPointer { + let subindices = Range(uncheckedBounds:(subsequence.startIndex, subsequence.endIndex)) + let base = Base(rebasing: subsequence.base.base[subsequence.base.baseIndices(subindices)]) + self.init(base, reversed: subsequence.base.isBackToFront) + } + + /// Creates a collection with the same data and direction as the given subsequence. + @inlinable public init(rebasing subsequence: SubSequence) where Base == UnsafeMutableBufferPointer { + let subindices = Range(uncheckedBounds:(subsequence.startIndex, subsequence.endIndex)) + let base = Base(rebasing: subsequence.base.base[subsequence.base.baseIndices(subindices)]) + self.init(base, reversed: subsequence.base.isBackToFront) + } +} diff --git a/Tests/NBKCoreKitTests/Models/NBKTwinHeaded.swift b/Tests/NBKCoreKitTests/Models/NBKTwinHeaded.swift index bf87fce9..b7817f49 100644 --- a/Tests/NBKCoreKitTests/Models/NBKTwinHeaded.swift +++ b/Tests/NBKCoreKitTests/Models/NBKTwinHeaded.swift @@ -57,6 +57,37 @@ final class NBKTwinHeadedTests: XCTestCase { XCTAssert(T<[Int]>.self == type(of: T(base))) } + func testFromEmpty() { + NBKAssertIteration(T(Array(), reversed: false), [ ]) + NBKAssertIteration(T(Array(), reversed: true ), [ ]) + + NBKAssertIteration(T(Array().reversed(), reversed: false), [ ]) + NBKAssertIteration(T(Array().reversed(), reversed: true ), [ ]) + + NBKAssertIteration(T(EmptyCollection(), reversed: false), [ ]) + NBKAssertIteration(T(EmptyCollection(), reversed: true ), [ ]) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Accessors + //=------------------------------------------------------------------------= + + func testIsFrontToBackOrBackToFront() { + let base = [0, 1, 2, 3] + + XCTAssertEqual(T(base, reversed: false).isFrontToBack, true ) + XCTAssertEqual(T(base, reversed: true ).isFrontToBack, false) + + XCTAssertEqual(T(base, reversed: false).asFrontToBack, base ) + XCTAssertEqual(T(base, reversed: true ).asFrontToBack, nil ) + + XCTAssertEqual(T(base, reversed: false).isBackToFront, false) + XCTAssertEqual(T(base, reversed: true ).isBackToFront, true ) + + XCTAssertEqual(T(base, reversed: false).asBackToFront.map(Array.init), nil) + XCTAssertEqual(T(base, reversed: true ).asBackToFront.map(Array.init), base.reversed()) + } + //=------------------------------------------------------------------------= // MARK: Tests x Transformations //=------------------------------------------------------------------------= @@ -75,6 +106,42 @@ final class NBKTwinHeadedTests: XCTestCase { XCTAssert(T<[Int]>.self == type(of: T(base))) XCTAssert(T<[Int]>.self == type(of: T(base).reversed())) } + + //=------------------------------------------------------------------------= + // MARK: Details x Rebasing Unsafe Buffer Pointers + //=------------------------------------------------------------------------= + + func testFromSubSequenceByRebasingUnsafeBufferPointer() { + let frontToBack = [0, 1, 2, 3] + let backToFront = [3, 2, 1, 0] + + frontToBack.withUnsafeBufferPointer { frontToBack in + backToFront.withUnsafeBufferPointer { backToFront in + for i in 0 ... 4 { + for j in i ... 4 { + XCTAssert(T(rebasing: T(frontToBack, reversed: false)[i ..< j]).elementsEqual(frontToBack[i ..< j])) + XCTAssert(T(rebasing: T(frontToBack, reversed: true )[i ..< j]).elementsEqual(backToFront[i ..< j])) + XCTAssert(T(rebasing: T(backToFront, reversed: false)[i ..< j]).elementsEqual(backToFront[i ..< j])) + XCTAssert(T(rebasing: T(backToFront, reversed: true )[i ..< j]).elementsEqual(frontToBack[i ..< j])) + }} + }} + } + + func testFromSubSequenceByRebasingUnsafeMutableBufferPointer() { + var frontToBack = [0, 1, 2, 3] + var backToFront = [3, 2, 1, 0] + + frontToBack.withUnsafeMutableBufferPointer { frontToBack in + backToFront.withUnsafeMutableBufferPointer { backToFront in + for i in 0 ... 4 { + for j in i ... 4 { + XCTAssert(T(rebasing: T(frontToBack, reversed: false)[i ..< j]).elementsEqual(frontToBack[i ..< j])) + XCTAssert(T(rebasing: T(frontToBack, reversed: true )[i ..< j]).elementsEqual(backToFront[i ..< j])) + XCTAssert(T(rebasing: T(backToFront, reversed: false)[i ..< j]).elementsEqual(backToFront[i ..< j])) + XCTAssert(T(rebasing: T(backToFront, reversed: true )[i ..< j]).elementsEqual(frontToBack[i ..< j])) + }} + }} + } } //*============================================================================* @@ -82,41 +149,73 @@ final class NBKTwinHeadedTests: XCTestCase { //*============================================================================* private func NBKAssertIteration( -_ lhs: B, _ rhs: [B.Element], +_ lhs: NBKTwinHeaded, _ rhs: [B.Element], file: StaticString = #file, line: UInt = #line) where B.Element: FixedWidthInteger, B.Element: Equatable { XCTAssertEqual(Array(lhs), rhs, file: file, line: line) XCTAssertEqual(Array(lhs.reversed()), rhs.reversed(), file: file, line: line) XCTAssertEqual(Array({ var x = lhs; x.reverse(); return x }()), rhs.reversed(), file: file, line: line) - do { + testIndices: do { + for lhsIndex in lhs.indices.enumerated() { + XCTAssertEqual(lhs[lhsIndex.element], rhs[lhsIndex.offset], file: file, line: line) + } + } + + testFrontToBack: do { var lhsIndex = lhs.startIndex var rhsIndex = rhs.startIndex while lhsIndex < lhs.endIndex { + let lhsIndexAfter = lhs.index(after: lhsIndex) + let rhsIndexAfter = rhs.index(after: lhsIndex) + XCTAssertEqual(lhs[lhsIndex], rhs[rhsIndex], file: file, line: line) - lhsIndex = lhs.index(after: lhsIndex) - rhsIndex = rhs.index(after: rhsIndex) + XCTAssertEqual(lhsIndexAfter, rhsIndexAfter, file: file, line: line) + + lhs.formIndex(after: &lhsIndex) + rhs.formIndex(after: &rhsIndex) } } - do { + testBackToFront: do { var lhsIndex = lhs.endIndex var rhsIndex = rhs.endIndex while lhsIndex > lhs.startIndex { - lhsIndex = lhs.index(before: lhsIndex) - rhsIndex = rhs.index(before: rhsIndex) - XCTAssertEqual(lhs[lhsIndex], rhs[rhsIndex], file: file, line: line) + let lhsIndexBefore = lhs.index(before: lhsIndex) + let rhsIndexBefore = rhs.index(before: lhsIndex) + + lhs.formIndex(before: &lhsIndex) + rhs.formIndex(before: &rhsIndex) + + XCTAssertEqual(lhs[lhsIndex], rhs[rhsIndex], file: file, line: line) + XCTAssertEqual(lhsIndexBefore, rhsIndexBefore, file: file, line: line) } } - do { - for lhsIndex in lhs.indices.enumerated() { - XCTAssertEqual(lhs[lhsIndex.element], rhs[lhsIndex.offset], file: file, line: line) + testAsMutableCollection: do { + var lhs = lhs, lhsIndex = lhs.startIndex + var rhs = rhs, rhsIndex = rhs.startIndex + while lhsIndex < lhs.endIndex { + lhs[lhsIndex] &+= 1 + rhs[rhsIndex] &+= 1 + + XCTAssertEqual(lhs[lhsIndex], rhs[rhsIndex], file: file, line: line) + + lhs.formIndex(after: &lhsIndex) + rhs.formIndex(after: &rhsIndex) } } - do { + testDropFirst: do { for dropFirst in 0 ..< (2 * lhs.count) { - XCTAssertEqual(Array(lhs.dropFirst(dropFirst)), Array(rhs.dropFirst(dropFirst)), file: file, line: line) + let lhsDropFirst = lhs.dropFirst(dropFirst) + let rhsDropFirst = rhs.dropFirst(dropFirst) + + let lhsDropFirstIndices = lhs.indices[lhsDropFirst.indices] + let rhsDropFirstIndices = rhs.indices[rhsDropFirst.indices] + + XCTAssertEqual(Array(lhsDropFirst), Array(rhsDropFirst), file: file, line: line) + XCTAssertEqual(Array(lhs[lhsDropFirstIndices]), Array(rhs[rhsDropFirstIndices]), file: file, line: line) + if let first = lhs.dropFirst(dropFirst).first { let firstIndex = lhs.index(lhs.startIndex, offsetBy: dropFirst) XCTAssertEqual(first, lhs[firstIndex], file: file, line: line) @@ -124,27 +223,23 @@ file: StaticString = #file, line: UInt = #line) where B.Element: FixedWidthInte } } - do { + testDropLast: do { for dropLast in 0 ..< (2 * lhs.count) { - XCTAssertEqual(Array(lhs.dropLast(dropLast)), Array(rhs.dropLast(dropLast)), file: file, line: line) + let lhsDropLast = lhs.dropFirst(dropLast) + let rhsDropLast = rhs.dropFirst(dropLast) + + let lhsDropLastIndices = lhs.indices[lhsDropLast.indices] + let rhsDropLastIndices = rhs.indices[rhsDropLast.indices] + + XCTAssertEqual(Array(lhsDropLast), Array(rhsDropLast), file: file, line: line) + XCTAssertEqual(Array(lhs[lhsDropLastIndices]), Array(rhs[rhsDropLastIndices]), file: file, line: line) + if let last = lhs.dropLast(dropLast).last { let lastIndex = lhs.index(lhs.endIndex, offsetBy: ~dropLast) XCTAssertEqual(last, lhs[lastIndex], file: file, line: line) } } } - - do { - var lhs = lhs, lhsIndex = lhs.startIndex - var rhs = rhs, rhsIndex = rhs.startIndex - while lhsIndex < lhs.endIndex { - lhs[lhsIndex] &+= 1 - rhs[rhsIndex] &+= 1 - XCTAssertEqual(lhs[lhsIndex], rhs[rhsIndex], file: file, line: line) - lhs.formIndex(after: &lhsIndex) - rhs.formIndex(after: &rhsIndex) - } - } } #endif From df6bff2fa2b7222932a3f5fc648d4f6cc31e139f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Tue, 29 Aug 2023 15:22:47 +0200 Subject: [PATCH 070/111] [NBKCoreKit] TwinHeaded (#72). --- Sources/NBKCoreKit/Models/NBKTwinHeaded.swift | 142 +++++++++++++----- .../Models/NBKTwinHeaded.swift | 41 +++-- 2 files changed, 135 insertions(+), 48 deletions(-) diff --git a/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift b/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift index 16e8dcc4..659a74c9 100644 --- a/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift +++ b/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift @@ -30,19 +30,19 @@ /// The base collection that is viewed through this instance. /// - /// - Note: The base collection must be private if one of its indices is stored. + /// - Note: It is private so the head index stays valid. /// @usableFromInline var body: Base /// The bit-mask used to change the offset based on the current direction. /// - /// It is equal to zero when front-to-back, and minus one otherwise. + /// It equals zero when front-to-back, and minus one otherwise. /// @usableFromInline var mask: Self.Index /// The base index to be offset. /// - /// It is the base's start index when front-to-back, and its end index otherwise. + /// It equals the base's start index when front-to-back, and the end index otherwise. /// @usableFromInline var head: Base.Index @@ -54,10 +54,11 @@ /// /// - Parameters: /// - base: The collection viewed through this instance. - /// - reversed: A value indicating whether the direction should be reversed. /// - @inlinable public init(_ other: Self, reversed: Bool = false) { - self.init(other.base, reversed: other.isFrontToBack == reversed) + @_disfavoredOverload @inlinable public init(_ base: Base) { + self.body = base + self.mask = Int .zero + self.head = self.body.startIndex } /// Creates a view presenting the collection's elements in a dynamic order. @@ -66,21 +67,18 @@ /// - base: The collection viewed through this instance. /// - reversed: A value indicating whether the direction should be reversed. /// - @inlinable public init(_ other: ReversedCollection, reversed: Bool = false) { - self.init(other.reversed(), reversed: !reversed) + @_disfavoredOverload @inlinable public init(_ base: Base, reversed: Bool) { + self.init(base); if reversed { self.reverse() } } /// Creates a view presenting the collection's elements in a dynamic order. /// /// - Parameters: /// - base: The collection viewed through this instance. - /// - reversed: A value indicating whether the direction should be reversed. + /// - head: The direction of the collection in terms of endianness. /// - @_disfavoredOverload @inlinable public init(_ base: Base, reversed: Bool = false) { - self.body = base - self.mask = Int .zero - self.head = self.body.startIndex - if reversed { self.reverse() } + @_disfavoredOverload @inlinable public init(_ base: Base, head: NBKEndianness) { + self.init(base, reversed: head == NBKEndianness.big) } //=------------------------------------------------------------------------= @@ -173,6 +171,97 @@ } } +//=----------------------------------------------------------------------------= +// MARK: + Initializers +//=----------------------------------------------------------------------------= + +extension NBKTwinHeaded { + + //=------------------------------------------------------------------------= + // MARK: Details x Self + //=------------------------------------------------------------------------= + + /// Creates a view presenting the collection's elements in a dynamic order. + /// + /// - Parameters: + /// - base: The collection viewed through this instance. + /// + @inlinable public init(_ other: Self) { + self = other + } + + /// Creates a view presenting the collection's elements in a dynamic order. + /// + /// - Parameters: + /// - base: The collection viewed through this instance. + /// - reversed: A value indicating whether the direction should be reversed. + /// + @inlinable public init(_ other: Self, reversed: Bool) { + self.init(other.base, reversed: other.isFrontToBack == reversed) + } + + /// Creates a view presenting the collection's elements in a dynamic order. + /// + /// - Parameters: + /// - base: The collection viewed through this instance. + /// - head: The direction of the collection in terms of endianness. + /// + @inlinable public init(_ other: Self, head: NBKEndianness) { + self.init(other, reversed: head == NBKEndianness.big) + } + + //=------------------------------------------------------------------------= + // MARK: Details x Reversed Collection + //=------------------------------------------------------------------------= + + /// Creates a view presenting the collection's elements in a dynamic order. + /// + /// - Parameters: + /// - base: The collection viewed through this instance. + /// + @inlinable public init(_ other: ReversedCollection) { + self.init(other.reversed(), reversed: true) + } + + /// Creates a view presenting the collection's elements in a dynamic order. + /// + /// - Parameters: + /// - base: The collection viewed through this instance. + /// - reversed: A value indicating whether the direction should be reversed. + /// + @inlinable public init(_ other: ReversedCollection, reversed: Bool) { + self.init(other.reversed(), reversed: !reversed) + } + + /// Creates a view presenting the collection's elements in a dynamic order. + /// + /// - Parameters: + /// - base: The collection viewed through this instance. + /// - head: The direction of the collection in terms of endianness. + /// + @inlinable public init(_ other: ReversedCollection, head: NBKEndianness) { + self.init(other.reversed(), reversed: head == NBKEndianness.little) + } + + //=------------------------------------------------------------------------= + // MARK: Details x Unsafe Buffer Pointers + //=------------------------------------------------------------------------= + + /// Creates a collection with the same data and direction as the given subsequence. + @inlinable public init(rebasing subsequence: SubSequence) where Base == UnsafeBufferPointer { + let subindices = Range(uncheckedBounds:(subsequence.startIndex, subsequence.endIndex)) + let base = Base(rebasing: subsequence.base.base[subsequence.base.baseIndices(subindices)]) + self.init(base, reversed: subsequence.base.isBackToFront) + } + + /// Creates a collection with the same data and direction as the given subsequence. + @inlinable public init(rebasing subsequence: SubSequence) where Base == UnsafeMutableBufferPointer { + let subindices = Range(uncheckedBounds:(subsequence.startIndex, subsequence.endIndex)) + let base = Base(rebasing: subsequence.base.base[subsequence.base.baseIndices(subindices)]) + self.init(base, reversed: subsequence.base.isBackToFront) + } +} + //=----------------------------------------------------------------------------= // MARK: + Collection //=----------------------------------------------------------------------------= @@ -259,28 +348,3 @@ extension NBKTwinHeaded: MutableCollection where Base: MutableCollection { _modify { yield &self.body[self.baseSubscriptIndex(index)] } } } - -//=----------------------------------------------------------------------------= -// MARK: + where Base is Unsafe Buffer Pointer -//=----------------------------------------------------------------------------= - -extension NBKTwinHeaded { - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - /// Creates a collection with the same data and direction as the given subsequence. - @inlinable public init(rebasing subsequence: SubSequence) where Base == UnsafeBufferPointer { - let subindices = Range(uncheckedBounds:(subsequence.startIndex, subsequence.endIndex)) - let base = Base(rebasing: subsequence.base.base[subsequence.base.baseIndices(subindices)]) - self.init(base, reversed: subsequence.base.isBackToFront) - } - - /// Creates a collection with the same data and direction as the given subsequence. - @inlinable public init(rebasing subsequence: SubSequence) where Base == UnsafeMutableBufferPointer { - let subindices = Range(uncheckedBounds:(subsequence.startIndex, subsequence.endIndex)) - let base = Base(rebasing: subsequence.base.base[subsequence.base.baseIndices(subindices)]) - self.init(base, reversed: subsequence.base.isBackToFront) - } -} diff --git a/Tests/NBKCoreKitTests/Models/NBKTwinHeaded.swift b/Tests/NBKCoreKitTests/Models/NBKTwinHeaded.swift index b7817f49..0a98ceed 100644 --- a/Tests/NBKCoreKitTests/Models/NBKTwinHeaded.swift +++ b/Tests/NBKCoreKitTests/Models/NBKTwinHeaded.swift @@ -30,13 +30,20 @@ final class NBKTwinHeadedTests: XCTestCase { NBKAssertIteration( T(base), [0, 1, 2, 3]) NBKAssertIteration(T(T(base)), [0, 1, 2, 3]) - NBKAssertIteration( T(base, reversed: false), [0, 1, 2, 3]) - NBKAssertIteration( T(base, reversed: true ), [3, 2, 1, 0]) + NBKAssertIteration( T(base, reversed: false), [0, 1, 2, 3]) + NBKAssertIteration( T(base, reversed: true ), [3, 2, 1, 0]) NBKAssertIteration(T(T(base, reversed: false), reversed: false), [0, 1, 2, 3]) NBKAssertIteration(T(T(base, reversed: false), reversed: true ), [3, 2, 1, 0]) NBKAssertIteration(T(T(base, reversed: true ), reversed: false), [3, 2, 1, 0]) NBKAssertIteration(T(T(base, reversed: true ), reversed: true ), [0, 1, 2, 3]) + NBKAssertIteration( T(base, head: .little), [0, 1, 2, 3]) + NBKAssertIteration( T(base, head: .big ), [3, 2, 1, 0]) + NBKAssertIteration(T(T(base, head: .little), head: .little), [0, 1, 2, 3]) + NBKAssertIteration(T(T(base, head: .little), head: .big ), [3, 2, 1, 0]) + NBKAssertIteration(T(T(base, head: .big ), head: .little), [3, 2, 1, 0]) + NBKAssertIteration(T(T(base, head: .big ), head: .big ), [0, 1, 2, 3]) + XCTAssert(T<[Int]>.self == type(of: T(base) )) XCTAssert(T<[Int]>.self == type(of: T(T(base)))) } @@ -47,25 +54,41 @@ final class NBKTwinHeadedTests: XCTestCase { NBKAssertIteration( T(base), [0, 1, 2, 3]) NBKAssertIteration(T(T(base)), [0, 1, 2, 3]) - NBKAssertIteration( T(base, reversed: false), [0, 1, 2, 3]) - NBKAssertIteration( T(base, reversed: true ), [3, 2, 1, 0]) + NBKAssertIteration( T(base, reversed: false), [0, 1, 2, 3]) + NBKAssertIteration( T(base, reversed: true ), [3, 2, 1, 0]) NBKAssertIteration(T(T(base, reversed: false), reversed: false), [0, 1, 2, 3]) NBKAssertIteration(T(T(base, reversed: false), reversed: true ), [3, 2, 1, 0]) NBKAssertIteration(T(T(base, reversed: true ), reversed: false), [3, 2, 1, 0]) NBKAssertIteration(T(T(base, reversed: true ), reversed: true ), [0, 1, 2, 3]) + NBKAssertIteration( T(base, head: .little), [0, 1, 2, 3]) + NBKAssertIteration( T(base, head: .big ), [3, 2, 1, 0]) + NBKAssertIteration(T(T(base, head: .little), head: .little), [0, 1, 2, 3]) + NBKAssertIteration(T(T(base, head: .little), head: .big ), [3, 2, 1, 0]) + NBKAssertIteration(T(T(base, head: .big ), head: .little), [3, 2, 1, 0]) + NBKAssertIteration(T(T(base, head: .big ), head: .big ), [0, 1, 2, 3]) + XCTAssert(T<[Int]>.self == type(of: T(base))) } - func testFromEmpty() { - NBKAssertIteration(T(Array(), reversed: false), [ ]) - NBKAssertIteration(T(Array(), reversed: true ), [ ]) + func testFromNoElements() { + NBKAssertIteration(T(Array()), [ ]) + NBKAssertIteration(T(Array().reversed()), [ ]) + NBKAssertIteration(T(EmptyCollection ()), [ ]) + NBKAssertIteration(T(Array(), reversed: false), [ ]) + NBKAssertIteration(T(Array(), reversed: true ), [ ]) NBKAssertIteration(T(Array().reversed(), reversed: false), [ ]) NBKAssertIteration(T(Array().reversed(), reversed: true ), [ ]) + NBKAssertIteration(T(EmptyCollection (), reversed: false), [ ]) + NBKAssertIteration(T(EmptyCollection (), reversed: true ), [ ]) - NBKAssertIteration(T(EmptyCollection(), reversed: false), [ ]) - NBKAssertIteration(T(EmptyCollection(), reversed: true ), [ ]) + NBKAssertIteration(T(Array(), head: .little), [ ]) + NBKAssertIteration(T(Array(), head: .big ), [ ]) + NBKAssertIteration(T(Array().reversed(), head: .little), [ ]) + NBKAssertIteration(T(Array().reversed(), head: .big ), [ ]) + NBKAssertIteration(T(EmptyCollection (), head: .little), [ ]) + NBKAssertIteration(T(EmptyCollection (), head: .big ), [ ]) } //=------------------------------------------------------------------------= From d373ed618c957e364dfca539bbe7d87c0c47c7f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Tue, 29 Aug 2023 16:04:56 +0200 Subject: [PATCH 071/111] [NBKDoubleWidthKit] Data, Text (#72). --- Sources/NBKCoreKit/Models/NBKEndianness.swift | 1 + .../NBKDoubleWidth+Data.swift | 59 +++++++++++++++++++ .../NBKDoubleWidth+Text.swift | 10 ++-- .../NBKDoubleWidth+Words+Pointers.swift | 28 ++++----- 4 files changed, 77 insertions(+), 21 deletions(-) create mode 100644 Sources/NBKDoubleWidthKit/NBKDoubleWidth+Data.swift diff --git a/Sources/NBKCoreKit/Models/NBKEndianness.swift b/Sources/NBKCoreKit/Models/NBKEndianness.swift index d5e4787b..5b6f0d8c 100644 --- a/Sources/NBKCoreKit/Models/NBKEndianness.swift +++ b/Sources/NBKCoreKit/Models/NBKEndianness.swift @@ -20,6 +20,7 @@ /// encurages the latter. /// @frozen public enum NBKEndianness: Hashable { + //=------------------------------------------------------------------------= // MARK: State //=------------------------------------------------------------------------= diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Data.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Data.swift new file mode 100644 index 00000000..260f4ec8 --- /dev/null +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Data.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 Double Width x Data +//*============================================================================* + +extension NBKDoubleWidth { + + //=------------------------------------------------------------------------= + // MARK: Utilities x Private + //=------------------------------------------------------------------------= + + /// Grants unsafe access to the in-memory representation of this value. + /// + /// - Note: The bytes of this integer are ordered by system endianness. + /// + @inlinable func withUnsafeData( + as type: T.Type, perform body: (UnsafeBufferPointer) throws -> U) rethrows -> U { + //=--------------------------------------= + assert(MemoryLayout.size / MemoryLayout.stride >= 1) + assert(MemoryLayout.size % MemoryLayout.stride == 0) + //=--------------------------------------= + return try Swift.withUnsafePointer(to: self) { base in + let count = MemoryLayout.size / MemoryLayout.stride + return try base.withMemoryRebound(to: T.self, capacity: count) { start in + let data = UnsafeBufferPointer(start: start, count: count) + return try body(data) + } + } + } + + /// Grants unsafe access to the in-memory representation of this value. + /// + /// - Note: The bytes of this integer are ordered by system endianness. + /// + @inlinable mutating func withUnsafeMutableData( + as type: T.Type, perform body: (inout UnsafeMutableBufferPointer) throws -> U) rethrows -> U { + //=--------------------------------------= + assert(MemoryLayout.size / MemoryLayout.stride >= 1) + assert(MemoryLayout.size % MemoryLayout.stride == 0) + //=--------------------------------------= + return try Swift.withUnsafeMutablePointer(to: &self) { base in + let count = MemoryLayout.size / MemoryLayout.stride + return try base.withMemoryRebound(to: T.self, capacity: count) { start in + var data = UnsafeMutableBufferPointer(start: start, count: count) + return try body(&data) + } + } + } +} diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text.swift index 562b3ba7..512c1616 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text.swift @@ -112,6 +112,8 @@ extension NBKDoubleWidth where High == High.Magnitude { //=------------------------------------------------------------------------= // MARK: Details x Encode x Private //=------------------------------------------------------------------------= + // NOTE: Both branches specialize NBKTwinHeaded>. + //=------------------------------------------------------------------------= @inlinable func description(radix: NBK.AnyRadixUIntRoot, alphabet: NBK.MaxRadixAlphabetEncoder, prefix: NBK.UnsafeUTF8, suffix: NBK.UnsafeUTF8) -> String { @@ -125,9 +127,9 @@ extension NBKDoubleWidth where High == High.Magnitude { //=--------------------------------------= // with one buffer pointer specialization //=--------------------------------------= - self.withContiguousStorage { buffer in - let chunks = NBK.UnsafeWords(rebasing: NBK.dropLast(from: buffer, while: { $0.isZero })) - return NBK.integerTextUnchecked(chunks: chunks, radix: radix, alphabet: alphabet, prefix: prefix, suffix: suffix) + return self.withUnsafeData(as: UInt.self) { data in + let chunks = NBKTwinHeaded(rebasing: NBK.dropLast(from: NBKTwinHeaded(data, head: .system), while: { $0.isZero })) + return NBK.integerTextUnchecked(chunks: chunks, radix: radix, alphabet: alphabet, prefix: prefix, suffix: suffix) } } @@ -155,7 +157,7 @@ extension NBKDoubleWidth where High == High.Magnitude { let count = start.distance(to: position) defer { start.deinitialize(count: count) } //=----------------------------------= - let chunks = NBK.UnsafeWords(start: start, count: count) + let chunks = NBKTwinHeaded(NBK.UnsafeWords(start: start, count: count)) return NBK.integerTextUnchecked(chunks: chunks, radix: radix, alphabet: alphabet, prefix: prefix, suffix: suffix) } } diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words+Pointers.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words+Pointers.swift index 26c6af0d..1fd626b1 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words+Pointers.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words+Pointers.swift @@ -24,14 +24,11 @@ extension NBKDoubleWidth { /// The elements of the contiguous storage appear in the order of the collection. /// @inlinable public func withContiguousStorage(_ body: (NBK.UnsafeWords) throws -> T) rethrows -> T { - var base = self; return try Swift.withUnsafeMutablePointer(to: &base) { value in - try value.withMemoryRebound(to: UInt.self, capacity: Self.count) { start in - var words = UnsafeMutableBufferPointer(start: start, count: Self.count) - #if _endian(big) - words.reverse() - #endif - return try body(UnsafeBufferPointer(words)) - } + var base = self; return try base.withUnsafeMutableData(as: UInt.self) { data in + #if _endian(big) + data.reverse() + #endif + return try body(UnsafeBufferPointer(data)) } } @@ -50,15 +47,12 @@ extension NBKDoubleWidth { /// The elements of the contiguous mutable storage appear in the order of the collection. /// @inlinable public mutating func withContiguousMutableStorage(_ body: (inout NBK.UnsafeMutableWords) throws -> T) rethrows -> T { - try Swift.withUnsafeMutablePointer(to: &self) { value in - try value.withMemoryRebound(to: UInt.self, capacity: Self.count) { start in - var words = UnsafeMutableBufferPointer(start: start, count: Self.count) - #if _endian(big) - do { words.reverse() } - defer { words.reverse() } - #endif - return try body(&words) - } + return try self.withUnsafeMutableData(as: UInt.self) { data in + #if _endian(big) + do { data.reverse() } + defer { data.reverse() } + #endif + return try body(&data) } } From 1d9f556bcb5f8321bcf603e1a7fe233ca0a35f23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Wed, 30 Aug 2023 08:55:38 +0200 Subject: [PATCH 072/111] Cleanup. Endianness (#72) (#74). --- Sources/NBKCoreKit/Models/NBKEndianness.swift | 13 +- Sources/NBKCoreKit/Models/NBKTwinHeaded.swift | 134 +++++++----------- .../NBKCoreKit/Private/NBK+Endianness.swift | 35 +++++ .../NBKDoubleWidth+Data.swift | 106 +++++++++++--- .../NBKDoubleWidth+Literals.swift | 5 +- .../NBKDoubleWidth+Numbers.swift | 5 +- .../NBKDoubleWidth+Rotations.swift | 42 +++--- .../NBKDoubleWidth+Text.swift | 16 ++- .../NBKDoubleWidth+Words+Pointers.swift | 14 +- .../NBKDoubleWidth+Words.swift | 31 +--- .../Models/NBKEndianness.swift | 25 ++-- .../Models/NBKTwinHeaded.swift | 58 +++----- .../Private/NBK+Endianness.swift | 36 +++++ 13 files changed, 306 insertions(+), 214 deletions(-) create mode 100644 Sources/NBKCoreKit/Private/NBK+Endianness.swift create mode 100644 Tests/NBKCoreKitTests/Private/NBK+Endianness.swift diff --git a/Sources/NBKCoreKit/Models/NBKEndianness.swift b/Sources/NBKCoreKit/Models/NBKEndianness.swift index 5b6f0d8c..b319735e 100644 --- a/Sources/NBKCoreKit/Models/NBKEndianness.swift +++ b/Sources/NBKCoreKit/Models/NBKEndianness.swift @@ -13,25 +13,28 @@ /// An enumeration of little and big endianness. /// +/// ```swift +/// NBKEndianness.little.rawValue // 0x00 +/// NBKEndianness.big .rawValue // 0x01 +/// ``` +/// /// ### Static vs Dynamic /// /// Some algorithms differ depending on endianness. Generic type parameterization /// can express the difference, but dynamic solutions are often viable. This type /// encurages the latter. /// -@frozen public enum NBKEndianness: Hashable { +@frozen public enum NBKEndianness: UInt8, Hashable { //=------------------------------------------------------------------------= // MARK: State //=------------------------------------------------------------------------= - // NOTE: The raw value is equal to the case index. - //=------------------------------------------------------------------------= /// A value representing a least-to-most-significant byte order. - case little // 0x00 + case little = 0x00 /// A value representing a most-to-least-significant byte order. - case big // 0x01 + case big = 0x01 //=------------------------------------------------------------------------= // MARK: Initializers diff --git a/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift b/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift index 659a74c9..fbbec992 100644 --- a/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift +++ b/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift @@ -55,30 +55,11 @@ /// - Parameters: /// - base: The collection viewed through this instance. /// - @_disfavoredOverload @inlinable public init(_ base: Base) { + @_disfavoredOverload @inlinable public init(_ base: Base, reversed: Bool = false) { self.body = base self.mask = Int .zero self.head = self.body.startIndex - } - - /// Creates a view presenting the collection's elements in a dynamic order. - /// - /// - Parameters: - /// - base: The collection viewed through this instance. - /// - reversed: A value indicating whether the direction should be reversed. - /// - @_disfavoredOverload @inlinable public init(_ base: Base, reversed: Bool) { - self.init(base); if reversed { self.reverse() } - } - - /// Creates a view presenting the collection's elements in a dynamic order. - /// - /// - Parameters: - /// - base: The collection viewed through this instance. - /// - head: The direction of the collection in terms of endianness. - /// - @_disfavoredOverload @inlinable public init(_ base: Base, head: NBKEndianness) { - self.init(base, reversed: head == NBKEndianness.big) + if reversed { self.reverse() } } //=------------------------------------------------------------------------= @@ -111,53 +92,57 @@ } //=------------------------------------------------------------------------= - // MARK: Transformations + // MARK: Accessors //=------------------------------------------------------------------------= - /// Forms this collection but reversed. + /// Returns the direction of iteratorn as 1 (front-to-back) or -1 (back-to-front). /// - /// - Complexity: O(1). + /// ``` + /// isFrontToBack: 1 + /// isBackToFront: -1 + /// ``` /// - @inlinable public mutating func reverse() { - self.head = self.baseIndex(self.endIndex) - self.mask = ~self.mask + @inlinable public var direction: Int { + self.mask &<< (1 as Int) | (1 as Int) } - /// Returns this collection but reversed. - /// - /// - Complexity: O(1). - /// - @inlinable public func reversed() -> Self { - var result = self; result.reverse(); return result - } - - //=------------------------------------------------------------------------= - // MARK: Utilities x Private - //=------------------------------------------------------------------------= - /// Returns the base collection's corresponding subscript index. /// + /// ``` + /// isFrontToBack: base.index(base.startIndex, offsetBy: index + 0) + /// isBackToFront: base.index(base.endIndex, offsetBy: -index + -1) + /// ``` + /// /// - Parameter index: `self.startIndex <= index < self.endIndex` /// - @inlinable func baseSubscriptIndex(_ index: Int) -> Base.Index { + @inlinable public func baseSubscriptIndex(_ index: Int) -> Base.Index { assert(self.startIndex <= index && index < self.endIndex) return self.base.index(self.head, offsetBy: self.mask ^ index) } /// Returns the base collection's corresponding index. /// + /// ``` + /// isFrontToBack: base.index(base.startIndex, offsetBy: index) + /// isBackToFront: base.index(base.endIndex, offsetBy: -index) + /// ``` + /// + /// - Note: Use ``baseSubscriptIndex(_:)`` to subscript the base collection. + /// /// - Parameter index: `self.startIndex <= index <= self.endIndex` /// - @inlinable func baseIndex(_ index: Int) -> Base.Index { + @inlinable public func baseIndex(_ index: Int) -> Base.Index { assert(self.startIndex <= index && index <= self.endIndex) return self.base.index(self.head, offsetBy: self.mask ^ index - self.mask) } /// Returns the base collection's corresponding indices. /// + /// - Note: Use ``baseSubscriptIndex(_:)`` to subscript the base collection. + /// /// - Parameter index: `self.startIndex <= index <= self.endIndex` /// - @inlinable func baseIndices(_ indices: Range) -> Range { + @inlinable public func baseIndices(_ indices: Range) -> Range { assert(self.startIndex <= indices.lowerBound && indices.upperBound <= self.endIndex) var lowerBound = self.baseIndex(indices.lowerBound) @@ -169,58 +154,47 @@ return Range(uncheckedBounds:(lowerBound, upperBound)) } -} - -//=----------------------------------------------------------------------------= -// MARK: + Initializers -//=----------------------------------------------------------------------------= - -extension NBKTwinHeaded { //=------------------------------------------------------------------------= - // MARK: Details x Self + // MARK: Transformations //=------------------------------------------------------------------------= - /// Creates a view presenting the collection's elements in a dynamic order. - /// - /// - Parameters: - /// - base: The collection viewed through this instance. - /// - @inlinable public init(_ other: Self) { - self = other - } - - /// Creates a view presenting the collection's elements in a dynamic order. + /// Forms this collection but reversed. /// - /// - Parameters: - /// - base: The collection viewed through this instance. - /// - reversed: A value indicating whether the direction should be reversed. + /// - Complexity: O(1). /// - @inlinable public init(_ other: Self, reversed: Bool) { - self.init(other.base, reversed: other.isFrontToBack == reversed) + @inlinable public mutating func reverse() { + self.head = self.baseIndex(self.endIndex) + self.mask = ~self.mask } - /// Creates a view presenting the collection's elements in a dynamic order. + /// Returns this collection but reversed. /// - /// - Parameters: - /// - base: The collection viewed through this instance. - /// - head: The direction of the collection in terms of endianness. + /// - Complexity: O(1). /// - @inlinable public init(_ other: Self, head: NBKEndianness) { - self.init(other, reversed: head == NBKEndianness.big) + @inlinable public func reversed() -> Self { + var result = self; result.reverse(); return result } +} + +//=----------------------------------------------------------------------------= +// MARK: + Initializers +//=----------------------------------------------------------------------------= + +extension NBKTwinHeaded { //=------------------------------------------------------------------------= - // MARK: Details x Reversed Collection + // MARK: Details x Flattened Conversions //=------------------------------------------------------------------------= /// Creates a view presenting the collection's elements in a dynamic order. /// /// - Parameters: /// - base: The collection viewed through this instance. + /// - reversed: A value indicating whether the direction should be reversed. /// - @inlinable public init(_ other: ReversedCollection) { - self.init(other.reversed(), reversed: true) + @inlinable public init(_ other: Self, reversed: Bool = false) { + self.init(other.base, reversed: other.isFrontToBack == reversed) } /// Creates a view presenting the collection's elements in a dynamic order. @@ -229,20 +203,10 @@ extension NBKTwinHeaded { /// - base: The collection viewed through this instance. /// - reversed: A value indicating whether the direction should be reversed. /// - @inlinable public init(_ other: ReversedCollection, reversed: Bool) { + @inlinable public init(_ other: ReversedCollection, reversed: Bool = false) { self.init(other.reversed(), reversed: !reversed) } - /// Creates a view presenting the collection's elements in a dynamic order. - /// - /// - Parameters: - /// - base: The collection viewed through this instance. - /// - head: The direction of the collection in terms of endianness. - /// - @inlinable public init(_ other: ReversedCollection, head: NBKEndianness) { - self.init(other.reversed(), reversed: head == NBKEndianness.little) - } - //=------------------------------------------------------------------------= // MARK: Details x Unsafe Buffer Pointers //=------------------------------------------------------------------------= diff --git a/Sources/NBKCoreKit/Private/NBK+Endianness.swift b/Sources/NBKCoreKit/Private/NBK+Endianness.swift new file mode 100644 index 00000000..1723e2ad --- /dev/null +++ b/Sources/NBKCoreKit/Private/NBK+Endianness.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. +//=----------------------------------------------------------------------------= + +//*============================================================================* +// MARK: * NBK x Endianess +//*============================================================================* + +extension NBK { + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + @_transparent public static var isBigEndian: Bool { + #if _endian(big) + return true + #else + return false + #endif + } + + @_transparent public static var isLittleEndian: Bool { + #if _endian(little) + return true + #else + return false + #endif + } +} diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Data.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Data.swift index 260f4ec8..83b3de56 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Data.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Data.swift @@ -15,6 +15,21 @@ import NBKCoreKit extension NBKDoubleWidth { + //=------------------------------------------------------------------------= + // MARK: Initializers x Private + //=------------------------------------------------------------------------= + // NOTE: Wrapped function call fixes Swift 5.7 performance problem. + //=------------------------------------------------------------------------= + + /// Creates a new instance with unsafe access to its uninitialized memory. + /// + /// - Note: The bytes of this integer are ordered by system endianness. + /// + @inlinable static func uninitialized( + as type: T.Type, init body: (UnsafeMutableBufferPointer) -> Void) -> Self { + Self(bitPattern: BitPattern.uninitialized(as: T.self, init: body)) + } + //=------------------------------------------------------------------------= // MARK: Utilities x Private //=------------------------------------------------------------------------= @@ -23,16 +38,11 @@ extension NBKDoubleWidth { /// /// - Note: The bytes of this integer are ordered by system endianness. /// - @inlinable func withUnsafeData( - as type: T.Type, perform body: (UnsafeBufferPointer) throws -> U) rethrows -> U { - //=--------------------------------------= - assert(MemoryLayout.size / MemoryLayout.stride >= 1) - assert(MemoryLayout.size % MemoryLayout.stride == 0) - //=--------------------------------------= - return try Swift.withUnsafePointer(to: self) { base in - let count = MemoryLayout.size / MemoryLayout.stride - return try base.withMemoryRebound(to: T.self, capacity: count) { start in - let data = UnsafeBufferPointer(start: start, count: count) + @inlinable func withUnsafeData( + as type: T.Type, perform body: (UnsafeBufferPointer) throws -> R) rethrows -> R { + try Swift.withUnsafePointer(to: self) { base in + try base.withMemoryRebound(to: T.self, capacity: BitPattern.count(T.self)) { start in + let data = UnsafeBufferPointer(start: start, count: BitPattern.count(T.self)) return try body(data) } } @@ -42,18 +52,74 @@ extension NBKDoubleWidth { /// /// - Note: The bytes of this integer are ordered by system endianness. /// - @inlinable mutating func withUnsafeMutableData( - as type: T.Type, perform body: (inout UnsafeMutableBufferPointer) throws -> U) rethrows -> U { - //=--------------------------------------= - assert(MemoryLayout.size / MemoryLayout.stride >= 1) - assert(MemoryLayout.size % MemoryLayout.stride == 0) - //=--------------------------------------= - return try Swift.withUnsafeMutablePointer(to: &self) { base in - let count = MemoryLayout.size / MemoryLayout.stride - return try base.withMemoryRebound(to: T.self, capacity: count) { start in - var data = UnsafeMutableBufferPointer(start: start, count: count) + @inlinable mutating func withUnsafeMutableData( + as type: T.Type, perform body: (inout UnsafeMutableBufferPointer< T>) throws -> R) rethrows -> R { + try Swift.withUnsafeMutablePointer(to: &self) { base in + try base.withMemoryRebound(to: T.self, capacity: BitPattern.count(T.self)) { start in + var data = UnsafeMutableBufferPointer(start: start, count: BitPattern.count(T.self)) return try body(&data) } } } } + +//*============================================================================* +// MARK: * NBK x Double Width x Data x Unsigned +//*============================================================================* + +extension NBKDoubleWidth where High == High.Magnitude { + + //=------------------------------------------------------------------------= + // MARK: Initializers x Private + //=------------------------------------------------------------------------= + + /// Creates a new instance with unsafe access to its uninitialized memory. + /// + /// - Note: The bytes of this integer are ordered by system endianness. + /// + @inlinable static func uninitialized( + as type: T.Type, init body: (UnsafeMutableBufferPointer) -> Void) -> Self { + Swift.withUnsafeTemporaryAllocation(of: Self.self, capacity: 1) { buffer in + let pointer = buffer.baseAddress.unsafelyUnwrapped + //=----------------------------------= + // pointee: initialization by callee + //=----------------------------------= + pointer.withMemoryRebound(to: T.self, capacity: BitPattern.count(T.self)) { start in + body(UnsafeMutableBufferPointer(start: start, count: BitPattern.count(T.self))) + } + //=----------------------------------= + // pointee: deinitialization by move + //=----------------------------------= + return pointer.move() + } + } + + //=------------------------------------------------------------------------= + // MARK: Utilities x Private + //=------------------------------------------------------------------------= + + /// Counts the number of elements that fit in this type. + /// + /// The size of this type is an integer multiple of every core integer size. + /// The smallest component is Int and it is at least half the size of Int64, + /// so this double-width integer type can fit at least one Int64. + /// + @inlinable static func count(_ type: T.Type) -> Int where T: NBKCoreInteger { + assert(MemoryLayout.size / MemoryLayout.stride >= 1) + assert(MemoryLayout.size % MemoryLayout.stride == 0) + return MemoryLayout.size / MemoryLayout.stride + } + + /// Returns the in-memory byte offset of the element at the given index. + /// + /// - Note: This operation is unchecked. + /// + @inlinable static func endiannessSensitiveByteOffset(of type: T.Type, at index: Int) -> Int where T: NBKCoreInteger { + assert(0 <= index && index < BitPattern.count(T.BitPattern.self)) + #if _endian(big) + return MemoryLayout.stride * ~index + MemoryLayout.size + #else + return MemoryLayout.stride * (index) + #endif + } +} diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift index eba8ea5f..7e8c6bcb 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift @@ -34,9 +34,10 @@ extension NBKDoubleWidth { //=--------------------------------------= // gets outlined without manual iteration //=--------------------------------------= - self = Self.uninitialized { value in + self = Self.uninitialized(as: UInt.self) { + let value = NBKTwinHeaded($0, reversed: NBK.isBigEndian) var index = value.startIndex - var pointer = value.base.baseAddress!.advanced(by: value.baseIndex(index)) + var pointer = value.base.baseAddress!.advanced(by: value.baseSubscriptIndex(index)) while index < value.endIndex { pointer.initialize(to: source[index]) pointer = pointer.advanced(by: value.direction) diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Numbers.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Numbers.swift index ba44a414..85a06a32 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Numbers.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Numbers.swift @@ -73,11 +73,12 @@ extension NBKDoubleWidth { let isLessThanZero: Bool = T.isSigned && words.last?.mostSignificantBit == true let sign = UInt(repeating: isLessThanZero) //=--------------------------------------= - let value = Self.uninitialized { value in + let value = Self.uninitialized(as: UInt.self) { + let value = NBKTwinHeaded($0, reversed: NBK.isBigEndian) let start = value.base.baseAddress! for index in value.indices { let word = index < words.count ? words[words.index(words.startIndex, offsetBy: index)] : sign - start.advanced(by: value.baseIndex(index)).initialize(to: word) + start.advanced(by: value.baseSubscriptIndex(index)).initialize(to: word) } } //=--------------------------------------= diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Rotations.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Rotations.swift index afa74cc4..ac6c3635 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Rotations.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Rotations.swift @@ -67,15 +67,18 @@ extension NBKDoubleWidth { let push = UInt(bitPattern: bits) let pull = UInt(bitPattern: UInt.bitWidth - bits) //=--------------------------------------= - return Self.uninitialized { result in - var (word) = self.last as UInt + return Self.uninitialized(as: UInt.self) { + var word = self.last as UInt + let result = NBKTwinHeaded($0, reversed: NBK.isBigEndian) var destination = result.index(result.startIndex, offsetBy: words) + //=----------------------------------= for source in self.indices { //=------------------------------= let pulled = word &>> pull (word) = self[source] let pushed = word &<< push - result.base.baseAddress!.advanced(by: result.baseIndex(destination)).initialize(to: pulled | pushed) + //=------------------------------= + result.base.baseAddress!.advanced(by: result.baseSubscriptIndex(destination)).initialize(to: pulled | pushed) //=------------------------------= result.formIndex(after: &destination) if destination >= result.endIndex { @@ -104,11 +107,13 @@ extension NBKDoubleWidth { //=--------------------------------------= if words.isZero { return self } //=--------------------------------------= - return Self.uninitialized { result in + return Self.uninitialized(as: UInt.self) { + let result = NBKTwinHeaded($0, reversed: NBK.isBigEndian) var destination = result.index(result.startIndex, offsetBy: words) + //=----------------------------------= for source in self.indices { //=------------------------------= - result.base.baseAddress!.advanced(by: result.baseIndex(destination)).initialize(to: self[source]) + result.base.baseAddress!.advanced(by: result.baseSubscriptIndex(destination)).initialize(to: self[source]) //=------------------------------= result.formIndex(after: &destination) if destination >= result.endIndex { @@ -177,16 +182,19 @@ extension NBKDoubleWidth { let push = UInt(bitPattern: bits) let pull = UInt(bitPattern: UInt.bitWidth - bits) //=--------------------------------------= - return Self.uninitialized { result in - var (word) = self.last as UInt - var destination = result.index(result.endIndex, offsetBy: ~words) - precondition(result.startIndex ..< result.endIndex ~= destination) - for source in self.indices { + return Self.uninitialized(as: UInt.self) { + var word = self.last as UInt + let result = NBKTwinHeaded($0, reversed: NBK.isBigEndian) + var destination = result.index(result.endIndex, offsetBy: ~words) + //=----------------------------------= + precondition(result.indices ~= destination) + for source in self.indices { //=------------------------------= let pulled = word &>> push (word) = self[source] let pushed = word &<< pull - result.base.baseAddress!.advanced(by: result.baseIndex(destination)).initialize(to: pulled | pushed) + //=------------------------------= + result.base.baseAddress!.advanced(by: result.baseSubscriptIndex(destination)).initialize(to: pulled | pushed) //=------------------------------= result.formIndex(after: &destination) if destination >= result.endIndex { @@ -215,12 +223,14 @@ extension NBKDoubleWidth { //=--------------------------------------= if words.isZero { return self } //=--------------------------------------= - return Self.uninitialized { result in - var destination = result.index(result.endIndex, offsetBy: -words) - precondition(result.startIndex ..< result.endIndex ~= destination) - for source in self.indices { + return Self.uninitialized(as: UInt.self) { + let result = NBKTwinHeaded($0, reversed: NBK.isBigEndian) + var destination = result.index(result.endIndex, offsetBy: -words) + //=----------------------------------= + precondition(result.indices ~= destination) + for source in self.indices { //=------------------------------= - result.base.baseAddress!.advanced(by: result.baseIndex(destination)).initialize(to: self[source]) + result.base.baseAddress!.advanced(by: result.baseSubscriptIndex(destination)).initialize(to: self[source]) //=------------------------------= result.formIndex(after: &destination) if destination >= result.endIndex { diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text.swift index 512c1616..41ed12e1 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text.swift @@ -70,14 +70,15 @@ extension NBKDoubleWidth where High == High.Magnitude { var digits = digits.drop(while:{ $0 == 48 }) //=--------------------------------------= var error = false - let value = Self.uninitialized { value in + let value = Self.uninitialized(as: UInt.self) { + let value = NBKTwinHeaded($0, reversed: NBK.isBigEndian) for index in value.indices { if digits.isEmpty { - value.base.baseAddress!.advanced(by: value.baseIndex(index)).initialize(to: 0000) + value.base.baseAddress!.advanced(by: value.baseSubscriptIndex(index)).initialize(to: 0000) } else { let chunk = NBK.UnsafeUTF8(rebasing: NBK.removeSuffix(from: &digits, maxLength: radix.exponent)) guard let word = NBK.truncating(digits: chunk, radix: radix.base, as: UInt.self) else { return error = true } - value.base.baseAddress!.advanced(by: value.baseIndex(index)).initialize(to: word) + value.base.baseAddress!.advanced(by: value.baseSubscriptIndex(index)).initialize(to: word) } } } @@ -127,9 +128,10 @@ extension NBKDoubleWidth where High == High.Magnitude { //=--------------------------------------= // with one buffer pointer specialization //=--------------------------------------= - return self.withUnsafeData(as: UInt.self) { data in - let chunks = NBKTwinHeaded(rebasing: NBK.dropLast(from: NBKTwinHeaded(data, head: .system), while: { $0.isZero })) - return NBK.integerTextUnchecked(chunks: chunks, radix: radix, alphabet: alphabet, prefix: prefix, suffix: suffix) + self.withUnsafeData(as: UInt.self) { data in + let words = NBKTwinHeaded(data, reversed: NBK.isBigEndian) + let chunks = NBKTwinHeaded(rebasing:NBK.dropLast(from: words, while:{ $0.isZero })) + return NBK.integerTextUnchecked(chunks: chunks, radix: radix, alphabet: alphabet, prefix: prefix, suffix: suffix) } } @@ -157,7 +159,7 @@ extension NBKDoubleWidth where High == High.Magnitude { let count = start.distance(to: position) defer { start.deinitialize(count: count) } //=----------------------------------= - let chunks = NBKTwinHeaded(NBK.UnsafeWords(start: start, count: count)) + let chunks = NBKTwinHeaded(UnsafeBufferPointer( start: start, count: count)) return NBK.integerTextUnchecked(chunks: chunks, radix: radix, alphabet: alphabet, prefix: prefix, suffix: suffix) } } diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words+Pointers.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words+Pointers.swift index 1fd626b1..0721f690 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words+Pointers.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words+Pointers.swift @@ -23,7 +23,8 @@ extension NBKDoubleWidth { /// /// The elements of the contiguous storage appear in the order of the collection. /// - @inlinable public func withContiguousStorage(_ body: (NBK.UnsafeWords) throws -> T) rethrows -> T { + @inlinable public func withContiguousStorage( + _ body: (UnsafeBufferPointer) throws -> T) rethrows -> T { var base = self; return try base.withUnsafeMutableData(as: UInt.self) { data in #if _endian(big) data.reverse() @@ -38,7 +39,8 @@ extension NBKDoubleWidth { /// /// - Note: This member is required by `Swift.Sequence`. /// - @inlinable public func withContiguousStorageIfAvailable(_ body: (NBK.UnsafeWords) throws -> T) rethrows -> T? { + @inlinable public func withContiguousStorageIfAvailable( + _ body: (UnsafeBufferPointer) throws -> T) rethrows -> T? { try self.withContiguousStorage(body) } @@ -46,7 +48,8 @@ extension NBKDoubleWidth { /// /// The elements of the contiguous mutable storage appear in the order of the collection. /// - @inlinable public mutating func withContiguousMutableStorage(_ body: (inout NBK.UnsafeMutableWords) throws -> T) rethrows -> T { + @inlinable public mutating func withContiguousMutableStorage( + _ body: (inout UnsafeMutableBufferPointer) throws -> T) rethrows -> T { return try self.withUnsafeMutableData(as: UInt.self) { data in #if _endian(big) do { data.reverse() } @@ -62,7 +65,8 @@ extension NBKDoubleWidth { /// /// - Note: This member is required by `Swift.MutableCollection`. /// - @inlinable public mutating func withContiguousMutableStorageIfAvailable(_ body: (inout NBK.UnsafeMutableWords) throws -> T) rethrows -> T? { - try self.withContiguousMutableStorage(body) + @inlinable public mutating func withContiguousMutableStorageIfAvailable( + _ body: (inout UnsafeMutableBufferPointer) throws -> T) rethrows -> T? { + try self.withContiguousMutableStorage(body) } } diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words.swift index 411f2a47..8cc2c80c 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words.swift @@ -21,9 +21,7 @@ extension NBKDoubleWidth { /// The number of words in this type of integer. @inlinable public static var count: Int { - assert(MemoryLayout.size / MemoryLayout.stride >= 2) - assert(MemoryLayout.size % MemoryLayout.stride == 0) - return MemoryLayout.size / MemoryLayout.stride + BitPattern.count(UInt.self) } //=------------------------------------------------------------------------= @@ -227,7 +225,7 @@ extension NBKDoubleWidth { /// @inlinable subscript(unchecked index: Int, as type: T.Type) -> T where T: NBKCoreInteger { get { - let offset = BitPattern.endiannessSensitiveByteOffset(at: index) + let offset = BitPattern.endiannessSensitiveByteOffset(of: T.BitPattern.self, at: index) assert(0 <= offset && offset <= MemoryLayout.size - MemoryLayout.stride, NBK.callsiteOutOfBoundsInfo()) return Swift.withUnsafePointer(to: self) { pointer in UnsafeRawPointer(pointer).load(fromByteOffset: offset, as: T.self) @@ -235,7 +233,7 @@ extension NBKDoubleWidth { } set { - let offset = BitPattern.endiannessSensitiveByteOffset(at: index) + let offset = BitPattern.endiannessSensitiveByteOffset(of: T.BitPattern.self, at: index) assert(0 <= offset && offset <= MemoryLayout.size - MemoryLayout.stride, NBK.callsiteOutOfBoundsInfo()) Swift.withUnsafeMutablePointer(to: &self) { pointer in UnsafeMutableRawPointer(pointer).storeBytes(of: newValue, toByteOffset: offset, as: T.self) @@ -243,26 +241,3 @@ extension NBKDoubleWidth { } } } - -//*============================================================================* -// MARK: * NBK x Double Width x Words x Unsigned -//*============================================================================* - -extension NBKDoubleWidth where High == High.Magnitude { - - //=------------------------------------------------------------------------= - // MARK: Utilities x Private - //=------------------------------------------------------------------------= - - /// Returns the in-memory byte offset of the word at the given index. - /// - /// - Note: This operation is unchecked. - /// - @inlinable static func endiannessSensitiveByteOffset(at index: Int) -> Int { - #if _endian(big) - return MemoryLayout.stride * ~index + MemoryLayout.size - #else - return MemoryLayout.stride * (index) - #endif - } -} diff --git a/Tests/NBKCoreKitTests/Models/NBKEndianness.swift b/Tests/NBKCoreKitTests/Models/NBKEndianness.swift index 9af975ec..70613a17 100644 --- a/Tests/NBKCoreKitTests/Models/NBKEndianness.swift +++ b/Tests/NBKCoreKitTests/Models/NBKEndianness.swift @@ -24,22 +24,29 @@ final class NBKEndiannessTests: XCTestCase { // MARK: Tests //=------------------------------------------------------------------------= - func testSystem() { - #if _endian(big) - XCTAssertEqual(T.system, T.big) - #elseif _endian(little) + func testSystemValue() { + #if _endian(little) XCTAssertEqual(T.system, T.little) + #elseif _endian(big) + XCTAssertEqual(T.system, T.big) #endif } - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testOpposite() { + func testOppositeValue() { XCTAssertEqual(!T.big, T.little) XCTAssertEqual(!T.little, T.big) } + + func testToRawValue() { + XCTAssertEqual(0x00 as UInt8, T.little.rawValue) + XCTAssertEqual(0x01 as UInt8, T.big.rawValue) + } + + func testFromRawValue() { + XCTAssertEqual(T(rawValue: 0x00 as UInt8), T.little) + XCTAssertEqual(T(rawValue: 0x01 as UInt8), T.big) + XCTAssertEqual(T(rawValue: 0x02 as UInt8), nil) + } } #endif diff --git a/Tests/NBKCoreKitTests/Models/NBKTwinHeaded.swift b/Tests/NBKCoreKitTests/Models/NBKTwinHeaded.swift index 0a98ceed..e48bf3f2 100644 --- a/Tests/NBKCoreKitTests/Models/NBKTwinHeaded.swift +++ b/Tests/NBKCoreKitTests/Models/NBKTwinHeaded.swift @@ -37,13 +37,6 @@ final class NBKTwinHeadedTests: XCTestCase { NBKAssertIteration(T(T(base, reversed: true ), reversed: false), [3, 2, 1, 0]) NBKAssertIteration(T(T(base, reversed: true ), reversed: true ), [0, 1, 2, 3]) - NBKAssertIteration( T(base, head: .little), [0, 1, 2, 3]) - NBKAssertIteration( T(base, head: .big ), [3, 2, 1, 0]) - NBKAssertIteration(T(T(base, head: .little), head: .little), [0, 1, 2, 3]) - NBKAssertIteration(T(T(base, head: .little), head: .big ), [3, 2, 1, 0]) - NBKAssertIteration(T(T(base, head: .big ), head: .little), [3, 2, 1, 0]) - NBKAssertIteration(T(T(base, head: .big ), head: .big ), [0, 1, 2, 3]) - XCTAssert(T<[Int]>.self == type(of: T(base) )) XCTAssert(T<[Int]>.self == type(of: T(T(base)))) } @@ -61,13 +54,6 @@ final class NBKTwinHeadedTests: XCTestCase { NBKAssertIteration(T(T(base, reversed: true ), reversed: false), [3, 2, 1, 0]) NBKAssertIteration(T(T(base, reversed: true ), reversed: true ), [0, 1, 2, 3]) - NBKAssertIteration( T(base, head: .little), [0, 1, 2, 3]) - NBKAssertIteration( T(base, head: .big ), [3, 2, 1, 0]) - NBKAssertIteration(T(T(base, head: .little), head: .little), [0, 1, 2, 3]) - NBKAssertIteration(T(T(base, head: .little), head: .big ), [3, 2, 1, 0]) - NBKAssertIteration(T(T(base, head: .big ), head: .little), [3, 2, 1, 0]) - NBKAssertIteration(T(T(base, head: .big ), head: .big ), [0, 1, 2, 3]) - XCTAssert(T<[Int]>.self == type(of: T(base))) } @@ -82,33 +68,35 @@ final class NBKTwinHeadedTests: XCTestCase { NBKAssertIteration(T(Array().reversed(), reversed: true ), [ ]) NBKAssertIteration(T(EmptyCollection (), reversed: false), [ ]) NBKAssertIteration(T(EmptyCollection (), reversed: true ), [ ]) - - NBKAssertIteration(T(Array(), head: .little), [ ]) - NBKAssertIteration(T(Array(), head: .big ), [ ]) - NBKAssertIteration(T(Array().reversed(), head: .little), [ ]) - NBKAssertIteration(T(Array().reversed(), head: .big ), [ ]) - NBKAssertIteration(T(EmptyCollection (), head: .little), [ ]) - NBKAssertIteration(T(EmptyCollection (), head: .big ), [ ]) } //=------------------------------------------------------------------------= // MARK: Tests x Accessors //=------------------------------------------------------------------------= - func testIsFrontToBackOrBackToFront() { - let base = [0, 1, 2, 3] - - XCTAssertEqual(T(base, reversed: false).isFrontToBack, true ) - XCTAssertEqual(T(base, reversed: true ).isFrontToBack, false) - - XCTAssertEqual(T(base, reversed: false).asFrontToBack, base ) - XCTAssertEqual(T(base, reversed: true ).asFrontToBack, nil ) - - XCTAssertEqual(T(base, reversed: false).isBackToFront, false) - XCTAssertEqual(T(base, reversed: true ).isBackToFront, true ) - - XCTAssertEqual(T(base, reversed: false).asBackToFront.map(Array.init), nil) - XCTAssertEqual(T(base, reversed: true ).asBackToFront.map(Array.init), base.reversed()) + func testDirection() { + XCTAssertEqual(T([0, 1, 2, 3], reversed: false).direction, 1) + XCTAssertEqual(T([0, 1, 2, 3], reversed: true ).direction, -1) + } + + func testIsFrontToBack() { + XCTAssertEqual(T([0, 1, 2, 3], reversed: false).isFrontToBack, true ) + XCTAssertEqual(T([0, 1, 2, 3], reversed: true ).isFrontToBack, false) + } + + func testAsFrontToBack() { + XCTAssertEqual(T([0, 1, 2, 3], reversed: false).asFrontToBack, [0, 1, 2, 3]) + XCTAssertEqual(T([0, 1, 2, 3], reversed: true ).asFrontToBack, nil) + } + + func testIsBackToFront() { + XCTAssertEqual(T([0, 1, 2, 3], reversed: false).isBackToFront, false) + XCTAssertEqual(T([0, 1, 2, 3], reversed: true ).isBackToFront, true ) + } + + func testAsBackToFront() { + XCTAssertEqual(T([0, 1, 2, 3], reversed: false).asBackToFront.map(Array.init), nil) + XCTAssertEqual(T([0, 1, 2, 3], reversed: true ).asBackToFront.map(Array.init), [0, 1, 2, 3].reversed()) } //=------------------------------------------------------------------------= diff --git a/Tests/NBKCoreKitTests/Private/NBK+Endianness.swift b/Tests/NBKCoreKitTests/Private/NBK+Endianness.swift new file mode 100644 index 00000000..579c743e --- /dev/null +++ b/Tests/NBKCoreKitTests/Private/NBK+Endianness.swift @@ -0,0 +1,36 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +import XCTest + +//*============================================================================* +// MARK: * NBK x Endianness +//*============================================================================* + +final class NBKTestsOnEndianness: XCTestCase { + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testIsLittleOrBigEndian() { + #if _endian(big) + XCTAssertTrue (NBK.isBigEndian) + XCTAssertFalse(NBK.isLittleEndian) + #elseif _endian(little) + XCTAssertFalse(NBK.isBigEndian) + XCTAssertTrue (NBK.isLittleEndian) + #endif + } +} + +#endif From 9f8eb572b1cfc33d2e31c106e7362806f0e7017a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Wed, 30 Aug 2023 08:58:08 +0200 Subject: [PATCH 073/111] No `uninitialized(_:)` (#75). --- .../NBKDoubleWidth+Uninitialized.swift | 74 ------------------- 1 file changed, 74 deletions(-) delete mode 100644 Sources/NBKDoubleWidthKit/NBKDoubleWidth+Uninitialized.swift diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Uninitialized.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Uninitialized.swift deleted file mode 100644 index 91dcf553..00000000 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Uninitialized.swift +++ /dev/null @@ -1,74 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -import NBKCoreKit - -//*============================================================================* -// MARK: * NBK x Double Width x Uninitialized -//*============================================================================* - -extension NBKDoubleWidth { - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - // NOTE: Wrapped function call fixes Swift 5.7 performance problem. - //=------------------------------------------------------------------------= - - /// Creates a new instance with unsafe access to uninitialized words. - /// - /// ```swift - /// let value = Int256.uninitialized { words in - /// for index in words.indices { - /// words.base.initializeElement(at: words.baseIndex(index), to: UInt.zero) - /// } - /// } - /// ``` - /// - @inlinable public static func uninitialized(_ body: (NBKLittleEndianOrdered) -> Void) -> Self { - Self(bitPattern: BitPattern.uninitialized(body)) - } -} - -//*============================================================================* -// MARK: * NBK x Double Width x Uninitialized x Uninitialized -//*============================================================================* - -extension NBKDoubleWidth where High == High.Magnitude { - - //=------------------------------------------------------------------------= - // MARK: Initializers x Private - //=------------------------------------------------------------------------= - - /// Creates a new instance with unsafe access to uninitialized words. - /// - /// ```swift - /// let value = Int256.uninitialized { words in - /// for index in words.indices { - /// words.base.initializeElement(at: words.baseIndex(index), to: UInt.zero) - /// } - /// } - /// ``` - /// - @inlinable static func uninitialized(_ body: (NBKLittleEndianOrdered) -> Void) -> Self { - Swift.withUnsafeTemporaryAllocation(of: Self.self, capacity: 1) { buffer in - let pointer = buffer.baseAddress.unsafelyUnwrapped - //=----------------------------------= - // pointee: initialization by callee - //=----------------------------------= - pointer.withMemoryRebound(to: UInt.self, capacity: Self.count) { start in - body(NBKLittleEndianOrdered(NBK.UnsafeMutableWords(start: start, count: Self.count))) - } - //=----------------------------------= - // pointee: deinitialization by move - //=----------------------------------= - return pointer.move() - } - } -} From 334371f3057c258cc4f4113dc8f668c55bf60060 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Wed, 30 Aug 2023 08:59:18 +0200 Subject: [PATCH 074/111] No LittleEndianOrdered (#72). --- README.md | 1 - .../Models/NBKLittleEndianOrdered.swift | 152 ------------------ .../Documentation.docc/Documentation.md | 2 - .../Models/NBKLittleEndianOrdered.swift | 116 ------------- 4 files changed, 271 deletions(-) delete mode 100644 Sources/NBKCoreKit/Models/NBKLittleEndianOrdered.swift delete mode 100644 Tests/NBKCoreKitTests/Models/NBKLittleEndianOrdered.swift diff --git a/README.md b/README.md index 740ec193..b1369c46 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,6 @@ A new protocol hierarchy that refines Swift's standard library. ### Models - [NBKEndianness](Sources/NBKCoreKit/Models/NBKEndianness.swift) -- [NBKLittleEndianOrdered](Sources/NBKCoreKit/Models/NBKLittleEndianOrdered.swift) - [NBKTwinHeaded](Sources/NBKCoreKit/Models/NBKTwinHeaded.swift) ## [NBKDoubleWidthKit][DBL/D] ([Sources][DBL/S], [Tests][DBL/T], [Benchmarks][DBL/B]) diff --git a/Sources/NBKCoreKit/Models/NBKLittleEndianOrdered.swift b/Sources/NBKCoreKit/Models/NBKLittleEndianOrdered.swift deleted file mode 100644 index e7ae6455..00000000 --- a/Sources/NBKCoreKit/Models/NBKLittleEndianOrdered.swift +++ /dev/null @@ -1,152 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -//*============================================================================* -// MARK: * NBK x Little Endian Ordered -//*============================================================================* - -/// A collection that iterates forwards or backwards depending on the platform. -/// -/// It iterates front-to-back on little-endian platforms, and back-to-front otherwise. -/// -/// ```swift -/// let value = Int256.uninitialized { words in -/// for index in words.indices { -/// words.base.initializeElement(at: words.baseIndex(index), to: UInt.zero) -/// } -/// } -/// ``` -/// -@frozen public struct NBKLittleEndianOrdered: RandomAccessCollection where Base: RandomAccessCollection { - - //=------------------------------------------------------------------------= - // MARK: State - //=------------------------------------------------------------------------= - - /// The collection wrapped by this instance. - public var base: Base - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - /// Creates a view presenting the collection's elements in an endianness-sensitive order. - @inlinable public init(_ base: Base) { - self.base = base - } - - //=------------------------------------------------------------------------= - // MARK: Utilities - //=------------------------------------------------------------------------= - - /// Returns the iteration direction as 1 (front-to-back) or -1 (back-to-front). - @inlinable public var direction: Int { - #if _endian(big) - return -1 - #else - return (1) - #endif - } - - /// Returns the corresponding base index, assuming it exists. - /// - /// - Note: This operation is unchecked. - /// - /// - Parameter index: `self.startIndex <= index < self.endIndex` - /// - @inlinable public func baseIndex(_ index: Int) -> Base.Index { - #if _endian(big) - return self.base.index(self.base.endIndex, offsetBy: ~index) - #else - return self.base.index(self.base.startIndex, offsetBy: index) - #endif - } -} - -//=----------------------------------------------------------------------------= -// MARK: + Collection -//=----------------------------------------------------------------------------= - -extension NBKLittleEndianOrdered { - - //=------------------------------------------------------------------------= - // MARK: Accessors - //=------------------------------------------------------------------------= - - @inlinable public var count: Int { - self.base.count - } - - @inlinable public var startIndex: Int { - Int.zero - } - - @inlinable public var endIndex: Int { - self.base.count - } - - @inlinable public var indices: Range { - Range(uncheckedBounds:(self.startIndex, self.endIndex)) - } - - @inlinable public subscript(index: Int) -> Base.Element { - _read { yield self.base[self.baseIndex(index)] } - } - - @inlinable public subscript(index: Int) -> Base.Element where Base: MutableCollection { - _read { yield self.base[self.baseIndex(index)] } - _modify { yield &self.base[self.baseIndex(index)] } - } - - //=------------------------------------------------------------------------= - // MARK: Utilities - //=------------------------------------------------------------------------= - - @inlinable public func distance(from start: Int, to end: Int) -> Int { - end - start - } - - @inlinable public func index(after index: Int) -> Int { - index + 1 - } - - @inlinable public func formIndex(after index: inout Int) { - index += 1 - } - - @inlinable public func index(before index: Int) -> Int { - index - 1 - } - - @inlinable public func formIndex(before index: inout Int) { - index -= 1 - } - - @inlinable public func index(_ index: Int, offsetBy distance: Int) -> Int { - index + distance - } - - // TODO: NBK.arrayIndex(_:offsetBy:limitedBy:) - @inlinable public func index(_ index: Int, offsetBy distance: Int, limitedBy limit: Int) -> Int? { - let distanceLimit: Int = self.distance(from: index, to: limit) - - guard distance >= 0 - ? distance <= distanceLimit || distanceLimit < 0 - : distance >= distanceLimit || distanceLimit > 0 - else { return nil } - - return self.index(index, offsetBy: distance) as Int - } -} - -//=----------------------------------------------------------------------------= -// MARK: + Conditional Conformances -//=----------------------------------------------------------------------------= - -extension NBKLittleEndianOrdered: MutableCollection where Base: MutableCollection { } diff --git a/Sources/Numberick/Documentation.docc/Documentation.md b/Sources/Numberick/Documentation.docc/Documentation.md index 1dd9d99e..326d50bf 100644 --- a/Sources/Numberick/Documentation.docc/Documentation.md +++ b/Sources/Numberick/Documentation.docc/Documentation.md @@ -18,7 +18,6 @@ A new protocol hierarchy that refines Swift's standard library. ### Models - ``NBKEndianness`` -- ``NBKLittleEndianOrdered`` - ``NBKTwinHeaded`` ## NBKDoubleWidthKit @@ -112,7 +111,6 @@ Int256(5) % Int(5), UInt256(5) % UInt(5) - ``NBKDoubleWidth`` - ``NBKEndianness`` -- ``NBKLittleEndianOrdered`` - ``NBKTwinHeaded`` ### Integers diff --git a/Tests/NBKCoreKitTests/Models/NBKLittleEndianOrdered.swift b/Tests/NBKCoreKitTests/Models/NBKLittleEndianOrdered.swift deleted file mode 100644 index efd6e1ff..00000000 --- a/Tests/NBKCoreKitTests/Models/NBKLittleEndianOrdered.swift +++ /dev/null @@ -1,116 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if DEBUG - -import NBKCoreKit -import XCTest - -//*============================================================================* -// MARK: * NBK x Little Endian Ordered -//*============================================================================* - -final class NBKLittleEndianOrderedTests: XCTestCase { - - typealias T = NBKLittleEndianOrdered where Base: RandomAccessCollection - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testIteration() { - var integer = UInt64.zero - - integer |= 0 << (0 * 8) - integer |= 1 << (1 * 8) - integer |= 2 << (2 * 8) - integer |= 3 << (3 * 8) - integer |= 4 << (4 * 8) - integer |= 5 << (5 * 8) - integer |= 6 << (6 * 8) - integer |= 7 << (7 * 8) - - Swift.withUnsafeBytes(of: integer) { integer in - NBKAssertLittleEndianOrderedIteration(T(integer), [0, 1, 2, 3, 4, 5, 6, 7]) - } - } -} - -//*============================================================================* -// MARK: * NBK x Little Endian Ordered x Assertions -//*============================================================================* - -private func NBKAssertLittleEndianOrderedIteration( -_ lhs: NBKLittleEndianOrdered, _ rhs: [B.Element], -file: StaticString = #file, line: UInt = #line) where B.Element: Equatable, B.Indices == Range { - XCTAssertEqual(Array(lhs), rhs, file: file, line: line) - XCTAssertEqual(Array(lhs.reversed()), rhs.reversed(), file: file, line: line) - - do { - var rhsIndex = lhs.baseIndex(lhs.startIndex) - for lhsIndex in lhs.indices { - XCTAssertEqual(lhs[lhsIndex], rhs[rhsIndex], file: file, line: line) - rhs.formIndex(&rhsIndex, offsetBy: lhs.direction) - } - } - - do { - var lhsIndex = lhs.startIndex - var rhsIndex = rhs.startIndex - while lhsIndex < lhs.endIndex { - XCTAssertEqual(lhs[lhsIndex], rhs[rhsIndex], file: file, line: line) - lhsIndex = lhs.index(after: lhsIndex) - rhsIndex = rhs.index(after: rhsIndex) - } - } - - do { - var lhsIndex = lhs.endIndex - var rhsIndex = rhs.endIndex - while lhsIndex > lhs.startIndex { - lhsIndex = lhs.index(before: lhsIndex) - rhsIndex = rhs.index(before: rhsIndex) - XCTAssertEqual(lhs[lhsIndex], rhs[rhsIndex], file: file, line: line) - } - } - - do { - for lhsIndex in lhs.indices.enumerated() { - XCTAssertEqual(lhs[lhsIndex.element], rhs[lhsIndex.offset], file: file, line: line) - } - } - - do { - for lhsIndex in lhs.indices { - XCTAssertEqual(lhs[lhsIndex], lhs.base[lhs.baseIndex(lhsIndex)], file: file, line: line) - } - } - - do { - for dropFirst in 0 ..< (2 * lhs.count) { - XCTAssertEqual(Array(lhs.dropFirst(dropFirst)), Array(rhs.dropFirst(dropFirst)), file: file, line: line) - if let first = lhs.dropFirst(dropFirst).first { - let firstIndex = lhs.index(lhs.startIndex, offsetBy: dropFirst) - XCTAssertEqual(first, lhs[firstIndex], file: file, line: line) - } - } - } - - do { - for dropLast in 0 ..< (2 * lhs.count) { - XCTAssertEqual(Array(lhs.dropLast(dropLast)), Array(rhs.dropLast(dropLast)), file: file, line: line) - if let last = lhs.dropLast(dropLast).last { - let lastIndex = lhs.index(lhs.endIndex, offsetBy: ~dropLast) - XCTAssertEqual(last, lhs[lastIndex], file: file, line: line) - } - } - } -} - -#endif From ce28c3f16b9e131e6a5ab7d121615a153c10bfb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Wed, 30 Aug 2023 13:19:12 +0200 Subject: [PATCH 075/111] [NBKCoreKit] Cleanup, Limbs (#73). --- Sources/NBKCoreKit/Models/NBKTwinHeaded.swift | 52 +++++++------- Sources/NBKCoreKit/Private/NBK+Limbs.swift | 68 ++++++++++++++----- Tests/NBKCoreKitTests/Private/NBK+Limbs.swift | 58 ++++++++-------- 3 files changed, 105 insertions(+), 73 deletions(-) diff --git a/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift b/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift index fbbec992..88858a2d 100644 --- a/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift +++ b/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift @@ -71,6 +71,11 @@ self.body as Base } + /// Returns the direction of iteratorn as 1 (front-to-back) or -1 (back-to-front). + @inlinable public var direction: Int { + self.mask &<< (1 as Int) | (1 as Int) + } + /// Returns whether the base collection's elements are presented front-to-back. @inlinable public var isFrontToBack: Bool { self.mask == ( 0) as Int @@ -92,20 +97,30 @@ } //=------------------------------------------------------------------------= - // MARK: Accessors + // MARK: Transformations //=------------------------------------------------------------------------= - /// Returns the direction of iteratorn as 1 (front-to-back) or -1 (back-to-front). + /// Forms this collection but reversed. /// - /// ``` - /// isFrontToBack: 1 - /// isBackToFront: -1 - /// ``` + /// - Complexity: O(1). /// - @inlinable public var direction: Int { - self.mask &<< (1 as Int) | (1 as Int) + @inlinable public mutating func reverse() { + self.head = self.baseIndex(self.endIndex) + self.mask = ~self.mask + } + + /// Returns this collection but reversed. + /// + /// - Complexity: O(1). + /// + @inlinable public func reversed() -> Self { + var result = self; result.reverse(); return result } + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + /// Returns the base collection's corresponding subscript index. /// /// ``` @@ -154,27 +169,6 @@ return Range(uncheckedBounds:(lowerBound, upperBound)) } - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - /// Forms this collection but reversed. - /// - /// - Complexity: O(1). - /// - @inlinable public mutating func reverse() { - self.head = self.baseIndex(self.endIndex) - self.mask = ~self.mask - } - - /// Returns this collection but reversed. - /// - /// - Complexity: O(1). - /// - @inlinable public func reversed() -> Self { - var result = self; result.reverse(); return result - } } //=----------------------------------------------------------------------------= diff --git a/Sources/NBKCoreKit/Private/NBK+Limbs.swift b/Sources/NBKCoreKit/Private/NBK+Limbs.swift index 599f653f..b16f0297 100644 --- a/Sources/NBKCoreKit/Private/NBK+Limbs.swift +++ b/Sources/NBKCoreKit/Private/NBK+Limbs.swift @@ -161,15 +161,15 @@ extension NBK { //=----------------------------------------------------------------= @usableFromInline var minorLimbs: MinorLimbs.Iterator - @usableFromInline let isSigned: Bool + @usableFromInline let minorLimbsIsSigned: Bool //=----------------------------------------------------------------= // MARK: Initializers //=----------------------------------------------------------------= @inlinable init(minorLimbs: MinorLimbs, isSigned: Bool) { - self.isSigned = isSigned self.minorLimbs = minorLimbs.makeIterator() + self.minorLimbsIsSigned = isSigned } //=----------------------------------------------------------------= @@ -178,22 +178,20 @@ extension NBK { @inlinable public mutating func next() -> MajorLimb? { var majorLimb = MajorLimb.zero + var majorLimbShift = Int.zero var minorLimb = MinorLimb.Magnitude.zero - var minorLimbsShift = Int.zero while let next = self.minorLimbs.next() { minorLimb = MinorLimb.Magnitude(bitPattern: next) - majorLimb |= MajorLimb(truncatingIfNeeded: minorLimb) &<< minorLimbsShift + majorLimb |= MajorLimb(truncatingIfNeeded: minorLimb) &<< majorLimbShift - do{ minorLimbsShift += MinorLimb.bitWidth } - if minorLimbsShift == MajorLimb.bitWidth { - return majorLimb - } + do { majorLimbShift += MinorLimb.bitWidth } + guard majorLimbShift < MajorLimb.bitWidth else { return majorLimb } } - guard !minorLimbsShift.isZero else { return nil } - majorLimb |= (MajorLimb(repeating: self.isSigned && minorLimb.mostSignificantBit) &<< minorLimbsShift) - return majorLimb as MajorLimb + guard !majorLimbShift.isZero else { return nil } + let bit: Bool = self.minorLimbsIsSigned && minorLimb.mostSignificantBit + return majorLimb | MajorLimb(repeating: bit) &<< majorLimbShift } } } @@ -211,8 +209,6 @@ extension NBK { public typealias MinorLimbsSubSequence = NBK.MinorLimbsSubSequence - public typealias Iterator = FlattenSequence>.Iterator - //=--------------------------------------------------------------------= // MARK: State //=--------------------------------------------------------------------= @@ -242,8 +238,48 @@ extension NBK { } @inlinable public func makeIterator() -> Iterator { - // this type is not opaque because the type inference seems to fail otherwise :( - self.majorLimbs.lazy.flatMap({ MinorLimbsSubSequence(majorLimb: $0) }).makeIterator() + Iterator(self.majorLimbs.makeIterator()) + } + + //*====================================================================* + // MARK: * Iterator + //*====================================================================* + + @frozen public struct Iterator: IteratorProtocol { + + //=----------------------------------------------------------------= + // MARK: State + //=----------------------------------------------------------------= + + @usableFromInline var majorLimbs: MajorLimbs.Iterator + @usableFromInline var minorLimbs: MinorLimbsSubSequence.Iterator? + + //=----------------------------------------------------------------= + // MARK: Initializers + //=----------------------------------------------------------------= + + @inlinable init(_ majorLimbs: MajorLimbs.Iterator) { + self.majorLimbs = majorLimbs + self.minorLimbs = nil + } + + //=----------------------------------------------------------------= + // MARK: Utilities + //=----------------------------------------------------------------= + + @inlinable mutating public func next() -> MinorLimb? { + repeat { + + if let minorLimb = self.minorLimbs?.next() { + return minorLimb + } else if let majorLimb = self.majorLimbs.next() { + self.minorLimbs = MinorLimbsSubSequence.Iterator(majorLimb: majorLimb) + } else { + return nil + } + + } while true + } } } @@ -257,7 +293,7 @@ extension NBK { public typealias MajorLimb = MajorLimb public typealias MinorLimb = MinorLimb - + //=--------------------------------------------------------------------= // MARK: State //=--------------------------------------------------------------------= diff --git a/Tests/NBKCoreKitTests/Private/NBK+Limbs.swift b/Tests/NBKCoreKitTests/Private/NBK+Limbs.swift index 0609e9c9..1ac7a53f 100644 --- a/Tests/NBKCoreKitTests/Private/NBK+Limbs.swift +++ b/Tests/NBKCoreKitTests/Private/NBK+Limbs.swift @@ -152,34 +152,35 @@ private func NBKAssertLimbs( _ lhs: [A], _ rhs: [B], isSigned: Bool? = nil, file: StaticString = #file, line: UInt = #line) { //=------------------------------------------= - typealias X = Array - typealias Y = ContiguousArray + typealias X = Array + typealias Y = ContiguousArray + typealias T = NBK.MajorOrMinorLimbsSequence //=------------------------------------------= let lhsUnsigned = lhs.map(A.Magnitude.init(bitPattern:)) let rhsUnsigned = rhs.map(B.Magnitude.init(bitPattern:)) //=------------------------------------------= if isSigned == nil || isSigned == true { - XCTAssertEqual(X(NBK.MajorOrMinorLimbsSequence(X(lhs), isSigned: true )), X(rhs), file: file, line: line) - XCTAssertEqual(X(NBK.MajorOrMinorLimbsSequence(X(lhsUnsigned), isSigned: true )), X(rhsUnsigned), file: file, line: line) - XCTAssertEqual(Y(NBK.MajorOrMinorLimbsSequence(Y(lhs), isSigned: true )), Y(rhs), file: file, line: line) - XCTAssertEqual(Y(NBK.MajorOrMinorLimbsSequence(Y(lhsUnsigned), isSigned: true )), Y(rhsUnsigned), file: file, line: line) + XCTAssertEqual(X(T(X(lhs), isSigned: true )), X(rhs), file: file, line: line) + XCTAssertEqual(X(T(X(lhsUnsigned), isSigned: true )), X(rhsUnsigned), file: file, line: line) + XCTAssertEqual(Y(T(Y(lhs), isSigned: true )), Y(rhs), file: file, line: line) + XCTAssertEqual(Y(T(Y(lhsUnsigned), isSigned: true )), Y(rhsUnsigned), file: file, line: line) - XCTAssertEqual(X(NBK.MajorOrMinorLimbsSequence(X(rhs), isSigned: true )), X(lhs), file: file, line: line) - XCTAssertEqual(X(NBK.MajorOrMinorLimbsSequence(X(rhsUnsigned), isSigned: true )), X(lhsUnsigned), file: file, line: line) - XCTAssertEqual(Y(NBK.MajorOrMinorLimbsSequence(Y(rhs), isSigned: true )), Y(lhs), file: file, line: line) - XCTAssertEqual(Y(NBK.MajorOrMinorLimbsSequence(Y(rhsUnsigned), isSigned: true )), Y(lhsUnsigned), file: file, line: line) + XCTAssertEqual(X(T(X(rhs), isSigned: true )), X(lhs), file: file, line: line) + XCTAssertEqual(X(T(X(rhsUnsigned), isSigned: true )), X(lhsUnsigned), file: file, line: line) + XCTAssertEqual(Y(T(Y(rhs), isSigned: true )), Y(lhs), file: file, line: line) + XCTAssertEqual(Y(T(Y(rhsUnsigned), isSigned: true )), Y(lhsUnsigned), file: file, line: line) } if isSigned == nil || isSigned == false { - XCTAssertEqual(X(NBK.MajorOrMinorLimbsSequence(X(lhs), isSigned: true )), X(rhs), file: file, line: line) - XCTAssertEqual(X(NBK.MajorOrMinorLimbsSequence(X(lhsUnsigned), isSigned: true )), X(rhsUnsigned), file: file, line: line) - XCTAssertEqual(Y(NBK.MajorOrMinorLimbsSequence(Y(lhs), isSigned: true )), Y(rhs), file: file, line: line) - XCTAssertEqual(Y(NBK.MajorOrMinorLimbsSequence(Y(lhsUnsigned), isSigned: true )), Y(rhsUnsigned), file: file, line: line) + XCTAssertEqual(X(T(X(lhs), isSigned: false)), X(rhs), file: file, line: line) + XCTAssertEqual(X(T(X(lhsUnsigned), isSigned: false)), X(rhsUnsigned), file: file, line: line) + XCTAssertEqual(Y(T(Y(lhs), isSigned: false)), Y(rhs), file: file, line: line) + XCTAssertEqual(Y(T(Y(lhsUnsigned), isSigned: false)), Y(rhsUnsigned), file: file, line: line) - XCTAssertEqual(X(NBK.MajorOrMinorLimbsSequence(X(rhs), isSigned: false)), X(lhs), file: file, line: line) - XCTAssertEqual(X(NBK.MajorOrMinorLimbsSequence(X(rhsUnsigned), isSigned: false)), X(lhsUnsigned), file: file, line: line) - XCTAssertEqual(Y(NBK.MajorOrMinorLimbsSequence(Y(rhs), isSigned: false)), Y(lhs), file: file, line: line) - XCTAssertEqual(Y(NBK.MajorOrMinorLimbsSequence(Y(rhsUnsigned), isSigned: false)), Y(lhsUnsigned), file: file, line: line) + XCTAssertEqual(X(T(X(rhs), isSigned: false)), X(lhs), file: file, line: line) + XCTAssertEqual(X(T(X(rhsUnsigned), isSigned: false)), X(lhsUnsigned), file: file, line: line) + XCTAssertEqual(Y(T(Y(rhs), isSigned: false)), Y(lhs), file: file, line: line) + XCTAssertEqual(Y(T(Y(rhsUnsigned), isSigned: false)), Y(lhsUnsigned), file: file, line: line) } } @@ -187,24 +188,25 @@ private func NBKAssertLimbsSubsequence( _ lhs: [A], _ rhs: [B], isSigned: Bool? = nil, file: StaticString = #file, line: UInt = #line) { //=------------------------------------------= - typealias X = Array - typealias Y = ContiguousArray + typealias X = Array + typealias Y = ContiguousArray + typealias T = NBK.MajorOrMinorLimbsSequence //=------------------------------------------= let lhsUnsigned = lhs.map(A.Magnitude.init(bitPattern:)) let rhsUnsigned = rhs.map(B.Magnitude.init(bitPattern:)) //=------------------------------------------= if isSigned == nil || isSigned == true { - XCTAssertEqual(X(NBK.MajorOrMinorLimbsSequence(X(lhs), isSigned: true )), X(rhs), file: file, line: line) - XCTAssertEqual(X(NBK.MajorOrMinorLimbsSequence(X(lhsUnsigned), isSigned: true )), X(rhsUnsigned), file: file, line: line) - XCTAssertEqual(Y(NBK.MajorOrMinorLimbsSequence(Y(lhs), isSigned: true )), Y(rhs), file: file, line: line) - XCTAssertEqual(Y(NBK.MajorOrMinorLimbsSequence(Y(lhsUnsigned), isSigned: true )), Y(rhsUnsigned), file: file, line: line) + XCTAssertEqual(X(T(X(lhs), isSigned: true )), X(rhs), file: file, line: line) + XCTAssertEqual(X(T(X(lhsUnsigned), isSigned: true )), X(rhsUnsigned), file: file, line: line) + XCTAssertEqual(Y(T(Y(lhs), isSigned: true )), Y(rhs), file: file, line: line) + XCTAssertEqual(Y(T(Y(lhsUnsigned), isSigned: true )), Y(rhsUnsigned), file: file, line: line) } if isSigned == nil || isSigned == false { - XCTAssertEqual(X(NBK.MajorOrMinorLimbsSequence(X(lhs), isSigned: false)), X(rhs), file: file, line: line) - XCTAssertEqual(X(NBK.MajorOrMinorLimbsSequence(X(lhsUnsigned), isSigned: false)), X(rhsUnsigned), file: file, line: line) - XCTAssertEqual(Y(NBK.MajorOrMinorLimbsSequence(Y(lhs), isSigned: false)), Y(rhs), file: file, line: line) - XCTAssertEqual(Y(NBK.MajorOrMinorLimbsSequence(Y(lhsUnsigned), isSigned: false)), Y(rhsUnsigned), file: file, line: line) + XCTAssertEqual(X(T(X(lhs), isSigned: false)), X(rhs), file: file, line: line) + XCTAssertEqual(X(T(X(lhsUnsigned), isSigned: false)), X(rhsUnsigned), file: file, line: line) + XCTAssertEqual(Y(T(Y(lhs), isSigned: false)), Y(rhs), file: file, line: line) + XCTAssertEqual(Y(T(Y(lhsUnsigned), isSigned: false)), Y(rhsUnsigned), file: file, line: line) } } From d69235df657945f7051d000b1c425cbc887e0ab0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Thu, 31 Aug 2023 07:35:10 +0200 Subject: [PATCH 076/111] Cleanup. --- Sources/NBKCoreKit/Models/NBKTwinHeaded.swift | 2 +- Sources/NBKCoreKit/Private/NBK+Limbs.swift | 8 ++++---- Sources/NBKDoubleWidthKit/NBKDoubleWidth+Data.swift | 2 +- Sources/NBKDoubleWidthKit/NBKDoubleWidth+Rotations.swift | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift b/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift index 88858a2d..bb9c5784 100644 --- a/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift +++ b/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift @@ -155,7 +155,7 @@ /// /// - Note: Use ``baseSubscriptIndex(_:)`` to subscript the base collection. /// - /// - Parameter index: `self.startIndex <= index <= self.endIndex` + /// - Parameter indices: `self.startIndex <= index <= self.endIndex` /// @inlinable public func baseIndices(_ indices: Range) -> Range { assert(self.startIndex <= indices.lowerBound && indices.upperBound <= self.endIndex) diff --git a/Sources/NBKCoreKit/Private/NBK+Limbs.swift b/Sources/NBKCoreKit/Private/NBK+Limbs.swift index b16f0297..cfdbf6d8 100644 --- a/Sources/NBKCoreKit/Private/NBK+Limbs.swift +++ b/Sources/NBKCoreKit/Private/NBK+Limbs.swift @@ -119,7 +119,7 @@ extension NBK { //=--------------------------------------------------------------------= @usableFromInline let minorLimbs: MinorLimbs - @usableFromInline let isSigned: Bool + @usableFromInline let minorLimbsIsSigned: Bool //=--------------------------------------------------------------------= // MARK: Initializers @@ -131,8 +131,8 @@ extension NBK { precondition(MajorLimb.bitWidth.isPowerOf2) precondition(MinorLimb.bitWidth <= MajorLimb.bitWidth) //=--------------------------------------= - self.isSigned = isSigned self.minorLimbs = minorLimbs + self.minorLimbsIsSigned = isSigned } //=--------------------------------------------------------------------= @@ -146,8 +146,8 @@ extension NBK { return division.quotient + Int(bit: !division.remainder.isZero) } - @inlinable public func makeIterator() -> Iterator { - Iterator(minorLimbs: self.minorLimbs, isSigned: self.isSigned) + @inlinable public func makeIterator() -> Iterator { + Iterator(minorLimbs: self.minorLimbs, isSigned: self.minorLimbsIsSigned) } //*====================================================================* diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Data.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Data.swift index 83b3de56..3a7ba3ff 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Data.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Data.swift @@ -115,7 +115,7 @@ extension NBKDoubleWidth where High == High.Magnitude { /// - Note: This operation is unchecked. /// @inlinable static func endiannessSensitiveByteOffset(of type: T.Type, at index: Int) -> Int where T: NBKCoreInteger { - assert(0 <= index && index < BitPattern.count(T.BitPattern.self)) + assert(0 <= index && index < BitPattern.count(T.self)) #if _endian(big) return MemoryLayout.stride * ~index + MemoryLayout.size #else diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Rotations.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Rotations.swift index ac6c3635..2a3fa176 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Rotations.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Rotations.swift @@ -68,7 +68,7 @@ extension NBKDoubleWidth { let pull = UInt(bitPattern: UInt.bitWidth - bits) //=--------------------------------------= return Self.uninitialized(as: UInt.self) { - var word = self.last as UInt + var (word) = self.last as UInt let result = NBKTwinHeaded($0, reversed: NBK.isBigEndian) var destination = result.index(result.startIndex, offsetBy: words) //=----------------------------------= @@ -183,7 +183,7 @@ extension NBKDoubleWidth { let pull = UInt(bitPattern: UInt.bitWidth - bits) //=--------------------------------------= return Self.uninitialized(as: UInt.self) { - var word = self.last as UInt + var (word) = self.last as UInt let result = NBKTwinHeaded($0, reversed: NBK.isBigEndian) var destination = result.index(result.endIndex, offsetBy: ~words) //=----------------------------------= From f0e1ad1a71560c0e4c101355d99fb9aa896f1e3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Thu, 31 Aug 2023 07:37:15 +0200 Subject: [PATCH 077/111] [NBKCoreKit] MajorOrMinorIntegerLimbs (#73). --- README.md | 1 + .../Models/NBKMajorOrMinorIntegerLimbs.swift | 112 +++++++++++++ .../Documentation.docc/Documentation.md | 2 + .../Models/NBKMajorOrMinorLimbs.swift | 157 ++++++++++++++++++ 4 files changed, 272 insertions(+) create mode 100644 Sources/NBKCoreKit/Models/NBKMajorOrMinorIntegerLimbs.swift create mode 100644 Tests/NBKCoreKitTests/Models/NBKMajorOrMinorLimbs.swift diff --git a/README.md b/README.md index b1369c46..0342f1a4 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,7 @@ A new protocol hierarchy that refines Swift's standard library. - [NBKEndianness](Sources/NBKCoreKit/Models/NBKEndianness.swift) - [NBKTwinHeaded](Sources/NBKCoreKit/Models/NBKTwinHeaded.swift) +- [NBKMajorOrMinorIntegerLimbs](Sources/NBKCoreKit/Models/NBKMajorOrMinorIntegerLimbs.swift) ## [NBKDoubleWidthKit][DBL/D] ([Sources][DBL/S], [Tests][DBL/T], [Benchmarks][DBL/B]) diff --git a/Sources/NBKCoreKit/Models/NBKMajorOrMinorIntegerLimbs.swift b/Sources/NBKCoreKit/Models/NBKMajorOrMinorIntegerLimbs.swift new file mode 100644 index 00000000..6193b66a --- /dev/null +++ b/Sources/NBKCoreKit/Models/NBKMajorOrMinorIntegerLimbs.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. +//=----------------------------------------------------------------------------= + +// TODO: Use input to output parameter order? +//*============================================================================* +// MARK: * NBK x Major Or Minor Integer Limbs +//*============================================================================* + +/// A sequence that merges or splits another sequence of un/signed integer limbs. +/// +/// ### Binary Integer Order +/// +/// This sequence is binary integer ordered, so it merges or splits limbs +/// from least to most significant. You can reorder it by reversing the input, +/// the output, or both. +/// +@frozen public struct NBKMajorOrMinorIntegerLimbs: Sequence where +Limb: NBKCoreInteger, Source: Sequence, Source.Element: NBKCoreInteger { + + public typealias Source = Source + + // TODO: with public models + public typealias MajorLimbs = NBK.MajorLimbsSequence + + // TODO: with public models + public typealias MinorLimbs = NBK.MinorLimbsSequence + + //=--------------------------------------------------------------------= + // MARK: State + //=--------------------------------------------------------------------= + // NOTE: Two parallel options appear to be faster than a combined enum. + //=--------------------------------------------------------------------= + + @usableFromInline let minorLimbs: MinorLimbs? + @usableFromInline let majorLimbs: MajorLimbs? + + //=--------------------------------------------------------------------= + // MARK: Initializers + //=--------------------------------------------------------------------= + + /// Creates a sequence of the given type, from an un/signed source. + @inlinable public init(_ source: Source, isSigned: Bool = false, as limb: Limb.Type = Limb.self) { + if Limb.bitWidth < Source.Element.bitWidth { + self.minorLimbs = MinorLimbs(majorLimbs: source) + self.majorLimbs = nil + } else { + self.minorLimbs = nil + self.majorLimbs = MajorLimbs(minorLimbs: source, isSigned: isSigned) + } + } + + //=--------------------------------------------------------------------= + // MARK: Utilities + //=--------------------------------------------------------------------= + + @inlinable public var underestimatedCount: Int { + if Limb.bitWidth < Source.Element.bitWidth { + return self.minorLimbs!.underestimatedCount + } else { + return self.majorLimbs!.underestimatedCount + } + } + + @inlinable public func makeIterator() -> Iterator { + if Limb.bitWidth < Source.Element.bitWidth { + return Iterator(minorLimbs: self.minorLimbs!.makeIterator()) + } else { + return Iterator(majorLimbs: self.majorLimbs!.makeIterator()) + } + } + + //*====================================================================* + // MARK: * Iterator + //*====================================================================* + + @frozen public struct Iterator: IteratorProtocol { + + //=----------------------------------------------------------------= + // MARK: State + //=----------------------------------------------------------------= + + @usableFromInline var minorLimbs: MinorLimbs.Iterator? + @usableFromInline var majorLimbs: MajorLimbs.Iterator? + + //=----------------------------------------------------------------= + // MARK: Initializers + //=----------------------------------------------------------------= + + @inlinable init(minorLimbs: MinorLimbs.Iterator? = nil, majorLimbs: MajorLimbs.Iterator? = nil) { + self.minorLimbs = minorLimbs + self.majorLimbs = majorLimbs + } + + //=----------------------------------------------------------------= + // MARK: Utilities + //=----------------------------------------------------------------= + + @inlinable public mutating func next() -> Limb? { + if Limb.bitWidth < Source.Element.bitWidth { + return self.minorLimbs!.next() + } else { + return self.majorLimbs!.next() + } + } + } +} diff --git a/Sources/Numberick/Documentation.docc/Documentation.md b/Sources/Numberick/Documentation.docc/Documentation.md index 326d50bf..71efa577 100644 --- a/Sources/Numberick/Documentation.docc/Documentation.md +++ b/Sources/Numberick/Documentation.docc/Documentation.md @@ -19,6 +19,7 @@ A new protocol hierarchy that refines Swift's standard library. - ``NBKEndianness`` - ``NBKTwinHeaded`` +- ``NBKMajorOrMinorIntegerLimbs`` ## NBKDoubleWidthKit @@ -112,6 +113,7 @@ Int256(5) % Int(5), UInt256(5) % UInt(5) - ``NBKDoubleWidth`` - ``NBKEndianness`` - ``NBKTwinHeaded`` +- ``NBKMajorOrMinorIntegerLimbs`` ### Integers diff --git a/Tests/NBKCoreKitTests/Models/NBKMajorOrMinorLimbs.swift b/Tests/NBKCoreKitTests/Models/NBKMajorOrMinorLimbs.swift new file mode 100644 index 00000000..ecea72e9 --- /dev/null +++ b/Tests/NBKCoreKitTests/Models/NBKMajorOrMinorLimbs.swift @@ -0,0 +1,157 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Major Or Minor Integer Limbs +//*============================================================================* + +final class NBKMajorOrMinorIntegerLimbsTests: XCTestCase { + + private typealias S64 = [Int64] + private typealias S32 = [Int32] + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testUInt32AsUInt32() { + NBKAssertMajorOrMinorIntegerLimbs([ ] as S32, [ ] as S32) + NBKAssertMajorOrMinorIntegerLimbs([ 1 ] as S32, [ 1 ] as S32) + NBKAssertMajorOrMinorIntegerLimbs([ 1, 2 ] as S32, [ 1, 2 ] as S32) + NBKAssertMajorOrMinorIntegerLimbs([ 1, 2, 3 ] as S32, [ 1, 2, 3 ] as S32) + NBKAssertMajorOrMinorIntegerLimbs([ 1, 2, 3, 4] as S32, [ 1, 2, 3, 4] as S32) + + NBKAssertMajorOrMinorIntegerLimbs([ ] as S32, [ ] as S32) + NBKAssertMajorOrMinorIntegerLimbs([~1 ] as S32, [~1 ] as S32) + NBKAssertMajorOrMinorIntegerLimbs([~1, ~2 ] as S32, [~1, ~2 ] as S32) + NBKAssertMajorOrMinorIntegerLimbs([~1, ~2, ~3 ] as S32, [~1, ~2, ~3 ] as S32) + NBKAssertMajorOrMinorIntegerLimbs([~1, ~2, ~3, ~4] as S32, [~1, ~2, ~3, ~4] as S32) + } + + func testUInt32AsUInt64() { + NBKAssertMajorOrMinorIntegerLimbs([ ] as S32, [ ] as S64) + NBKAssertMajorOrMinorIntegerLimbs([ 1, 0 ] as S32, [ 1 ] as S64) + NBKAssertMajorOrMinorIntegerLimbs([ 1, 0, 2, 0 ] as S32, [ 1, 2 ] as S64) + NBKAssertMajorOrMinorIntegerLimbs([ 1, 0, 2, 0, 3, 0 ] as S32, [ 1, 2, 3 ] as S64) + NBKAssertMajorOrMinorIntegerLimbs([ 1, 0, 2, 0, 3, 0, 4, 0] as S32, [ 1, 2, 3, 4] as S64) + + NBKAssertMajorOrMinorIntegerLimbs([ ] as S32, [ ] as S64) + NBKAssertMajorOrMinorIntegerLimbs([~1, ~0 ] as S32, [~1 ] as S64) + NBKAssertMajorOrMinorIntegerLimbs([~1, ~0, ~2, ~0 ] as S32, [~1, ~2 ] as S64) + NBKAssertMajorOrMinorIntegerLimbs([~1, ~0, ~2, ~0, ~3, ~0 ] as S32, [~1, ~2, ~3 ] as S64) + NBKAssertMajorOrMinorIntegerLimbs([~1, ~0, ~2, ~0, ~3, ~0, ~4, ~0] as S32, [~1, ~2, ~3, ~4] as S64) + } + + func testUInt64AsUInt64() { + NBKAssertMajorOrMinorIntegerLimbs([ ] as S64, [ ] as S64) + NBKAssertMajorOrMinorIntegerLimbs([ 1 ] as S64, [ 1 ] as S64) + NBKAssertMajorOrMinorIntegerLimbs([ 1, 2 ] as S64, [ 1, 2 ] as S64) + NBKAssertMajorOrMinorIntegerLimbs([ 1, 2, 3 ] as S64, [ 1, 2, 3 ] as S64) + NBKAssertMajorOrMinorIntegerLimbs([ 1, 2, 3, 4] as S64, [ 1, 2, 3, 4] as S64) + + NBKAssertMajorOrMinorIntegerLimbs([ ] as S64, [ ] as S64) + NBKAssertMajorOrMinorIntegerLimbs([~1 ] as S64, [~1 ] as S64) + NBKAssertMajorOrMinorIntegerLimbs([~1, ~2 ] as S64, [~1, ~2 ] as S64) + NBKAssertMajorOrMinorIntegerLimbs([~1, ~2, ~3 ] as S64, [~1, ~2, ~3 ] as S64) + NBKAssertMajorOrMinorIntegerLimbs([~1, ~2, ~3, ~4] as S64, [~1, ~2, ~3, ~4] as S64) + } + + func testUInt64AsUInt32() { + NBKAssertMajorOrMinorIntegerLimbs([ ] as S64, [ ] as S32) + NBKAssertMajorOrMinorIntegerLimbs([ 1 ] as S64, [ 1, 0 ] as S32) + NBKAssertMajorOrMinorIntegerLimbs([ 1, 2 ] as S64, [ 1, 0, 2, 0 ] as S32) + NBKAssertMajorOrMinorIntegerLimbs([ 1, 2, 3 ] as S64, [ 1, 0, 2, 0, 3, 0 ] as S32) + NBKAssertMajorOrMinorIntegerLimbs([ 1, 2, 3, 4] as S64, [ 1, 0, 2, 0, 3, 0, 4, 0] as S32) + + NBKAssertMajorOrMinorIntegerLimbs([ ] as S64, [ ] as S32) + NBKAssertMajorOrMinorIntegerLimbs([~1 ] as S64, [~1, ~0 ] as S32) + NBKAssertMajorOrMinorIntegerLimbs([~1, ~2 ] as S64, [~1, ~0, ~2, ~0 ] as S32) + NBKAssertMajorOrMinorIntegerLimbs([~1, ~2, ~3 ] as S64, [~1, ~0, ~2, ~0, ~3, ~0 ] as S32) + NBKAssertMajorOrMinorIntegerLimbs([~1, ~2, ~3, ~4] as S64, [~1, ~0, ~2, ~0, ~3, ~0, ~4, ~0] as S32) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Signed or Unsigned + //=------------------------------------------------------------------------= + + func testMajorLimbsFromIncompleteMinorLimbs() { + NBKAssertMajorOrMinorIntegerLimbsOneWay([ ] as S32, [ ] as S64, isSigned: true ) + NBKAssertMajorOrMinorIntegerLimbsOneWay([ 1 ] as S32, [ 1 ] as S64, isSigned: true ) + NBKAssertMajorOrMinorIntegerLimbsOneWay([ 1, 0, 2 ] as S32, [ 1, 2 ] as S64, isSigned: true ) + NBKAssertMajorOrMinorIntegerLimbsOneWay([ 1, 0, 2, 0, 3 ] as S32, [ 1, 2, 3 ] as S64, isSigned: true ) + NBKAssertMajorOrMinorIntegerLimbsOneWay([ 1, 0, 2, 0, 3, 0, 4] as S32, [ 1, 2, 3, 4 ] as S64, isSigned: true ) + + NBKAssertMajorOrMinorIntegerLimbsOneWay([ ] as S32, [ ] as S64, isSigned: true ) + NBKAssertMajorOrMinorIntegerLimbsOneWay([~1 ] as S32, [~1 ] as S64, isSigned: true ) + NBKAssertMajorOrMinorIntegerLimbsOneWay([~1, ~0, ~2 ] as S32, [~1, ~2 ] as S64, isSigned: true ) + NBKAssertMajorOrMinorIntegerLimbsOneWay([~1, ~0, ~2, ~0, ~3 ] as S32, [~1, ~2, ~3 ] as S64, isSigned: true ) + NBKAssertMajorOrMinorIntegerLimbsOneWay([~1, ~0, ~2, ~0, ~3, ~0, ~4] as S32, [~1, ~2, ~3, ~4 ] as S64, isSigned: true ) + + NBKAssertMajorOrMinorIntegerLimbsOneWay([ ] as S32, [ ] as S64, isSigned: false) + NBKAssertMajorOrMinorIntegerLimbsOneWay([ 1 ] as S32, [ 1 ] as S64, isSigned: false) + NBKAssertMajorOrMinorIntegerLimbsOneWay([ 1, 0, 2 ] as S32, [ 1, 2 ] as S64, isSigned: false) + NBKAssertMajorOrMinorIntegerLimbsOneWay([ 1, 0, 2, 0, 3 ] as S32, [ 1, 2, 3 ] as S64, isSigned: false) + NBKAssertMajorOrMinorIntegerLimbsOneWay([ 1, 0, 2, 0, 3, 0, 4] as S32, [ 1, 2, 3, 4 ] as S64, isSigned: false) + + NBKAssertMajorOrMinorIntegerLimbsOneWay([ ] as S32, [ ] as S64, isSigned: false) + NBKAssertMajorOrMinorIntegerLimbsOneWay([~1 ] as S32, [ 0xfffffffe] as S64, isSigned: false) + NBKAssertMajorOrMinorIntegerLimbsOneWay([~1, ~0, ~2 ] as S32, [~1, 0xfffffffd] as S64, isSigned: false) + NBKAssertMajorOrMinorIntegerLimbsOneWay([~1, ~0, ~2, ~0, ~3 ] as S32, [~1, ~2, 0xfffffffc] as S64, isSigned: false) + NBKAssertMajorOrMinorIntegerLimbsOneWay([~1, ~0, ~2, ~0, ~3, ~0, ~4] as S32, [~1, ~2, ~3, 0xfffffffb] as S64, isSigned: false) + } +} + +//*============================================================================* +// MARK: * NBK x Major Or Minor Integer Limbs x Assertions +//*============================================================================* + +private func NBKAssertMajorOrMinorIntegerLimbs( +_ lhs: [A], _ rhs: [B], isSigned: Bool? = nil, +file: StaticString = #file, line: UInt = #line) { + + NBKAssertMajorOrMinorIntegerLimbsOneWay(lhs, rhs, isSigned: isSigned) + NBKAssertMajorOrMinorIntegerLimbsOneWay(rhs, lhs, isSigned: isSigned) +} + +private func NBKAssertMajorOrMinorIntegerLimbsOneWay( +_ lhs: [A], _ rhs: [B], isSigned: Bool? = nil, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + typealias X = Array + typealias Y = ContiguousArray + typealias T = NBKMajorOrMinorIntegerLimbs + //=------------------------------------------= + let lhsUnsigned = lhs.map(A.Magnitude.init(bitPattern:)) + let rhsUnsigned = rhs.map(B.Magnitude.init(bitPattern:)) + //=------------------------------------------= + if isSigned == nil || isSigned == true { + XCTAssertEqual(X(T(X(lhs), isSigned: true )), X(rhs), file: file, line: line) + XCTAssertEqual(X(T(X(lhsUnsigned), isSigned: true )), X(rhsUnsigned), file: file, line: line) + XCTAssertEqual(Y(T(Y(lhs), isSigned: true )), Y(rhs), file: file, line: line) + XCTAssertEqual(Y(T(Y(lhsUnsigned), isSigned: true )), Y(rhsUnsigned), file: file, line: line) + } + + if isSigned == nil || isSigned == false { + XCTAssertEqual(X(T(X(lhs), isSigned: false)), X(rhs), file: file, line: line) + XCTAssertEqual(X(T(X(lhsUnsigned), isSigned: false)), X(rhsUnsigned), file: file, line: line) + XCTAssertEqual(Y(T(Y(lhs), isSigned: false)), Y(rhs), file: file, line: line) + XCTAssertEqual(Y(T(Y(lhsUnsigned), isSigned: false)), Y(rhsUnsigned), file: file, line: line) + } +} + +#endif From 80fb2e14e9f00bd73a7ce020f4c08d57c1037e80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Thu, 31 Aug 2023 08:49:36 +0200 Subject: [PATCH 078/111] [NBKCoreKit] MajorIntegerLimbs (#73). --- README.md | 3 +- .../Models/NBKMajorOrMinorIntegerLimbs.swift | 97 ++++++++++++++++++- .../Documentation.docc/Documentation.md | 6 +- ...wift => NBKMajorOrMinorIntegerLimbs.swift} | 0 4 files changed, 101 insertions(+), 5 deletions(-) rename Tests/NBKCoreKitTests/Models/{NBKMajorOrMinorLimbs.swift => NBKMajorOrMinorIntegerLimbs.swift} (100%) diff --git a/README.md b/README.md index 0342f1a4..0864fb11 100644 --- a/README.md +++ b/README.md @@ -22,8 +22,9 @@ A new protocol hierarchy that refines Swift's standard library. ### Models - [NBKEndianness](Sources/NBKCoreKit/Models/NBKEndianness.swift) -- [NBKTwinHeaded](Sources/NBKCoreKit/Models/NBKTwinHeaded.swift) +- [NBKMajorIntegerLimbs](Sources/NBKCoreKit/Models/NBKMajorOrMinorIntegerLimbs.swift) - [NBKMajorOrMinorIntegerLimbs](Sources/NBKCoreKit/Models/NBKMajorOrMinorIntegerLimbs.swift) +- [NBKTwinHeaded](Sources/NBKCoreKit/Models/NBKTwinHeaded.swift) ## [NBKDoubleWidthKit][DBL/D] ([Sources][DBL/S], [Tests][DBL/T], [Benchmarks][DBL/B]) diff --git a/Sources/NBKCoreKit/Models/NBKMajorOrMinorIntegerLimbs.swift b/Sources/NBKCoreKit/Models/NBKMajorOrMinorIntegerLimbs.swift index 6193b66a..7b12848d 100644 --- a/Sources/NBKCoreKit/Models/NBKMajorOrMinorIntegerLimbs.swift +++ b/Sources/NBKCoreKit/Models/NBKMajorOrMinorIntegerLimbs.swift @@ -26,7 +26,7 @@ Limb: NBKCoreInteger, Source: Sequence, Source.Element: NBKCoreInteger { public typealias Source = Source // TODO: with public models - public typealias MajorLimbs = NBK.MajorLimbsSequence + public typealias MajorLimbs = NBKMajorIntegerLimbs // TODO: with public models public typealias MinorLimbs = NBK.MinorLimbsSequence @@ -51,7 +51,7 @@ Limb: NBKCoreInteger, Source: Sequence, Source.Element: NBKCoreInteger { self.majorLimbs = nil } else { self.minorLimbs = nil - self.majorLimbs = MajorLimbs(minorLimbs: source, isSigned: isSigned) + self.majorLimbs = MajorLimbs(source, isSigned: isSigned) } } @@ -110,3 +110,96 @@ Limb: NBKCoreInteger, Source: Sequence, Source.Element: NBKCoreInteger { } } } + +//*============================================================================* +// MARK: * NBK x Major Integer Limbs +//*============================================================================* + +@frozen public struct NBKMajorIntegerLimbs: Sequence where +MajorLimb: NBKCoreInteger, MinorLimbs: Sequence, MinorLimbs.Element: NBKCoreInteger { + + public typealias MajorLimb = MajorLimb + + public typealias MinorLimb = MinorLimbs.Element + + //=--------------------------------------------------------------------= + // MARK: State + //=--------------------------------------------------------------------= + + @usableFromInline let minorLimbs: MinorLimbs + @usableFromInline let minorLimbsIsSigned: Bool + + //=--------------------------------------------------------------------= + // MARK: Initializers + //=--------------------------------------------------------------------= + + @inlinable public init(_ minorLimbs: MinorLimbs, isSigned: Bool = false, as majorLimb: MajorLimb.Type = MajorLimb.self) { + //=--------------------------------------= + precondition(MinorLimb.bitWidth.isPowerOf2) + precondition(MajorLimb.bitWidth.isPowerOf2) + precondition(MinorLimb.bitWidth <= MajorLimb.bitWidth) + //=--------------------------------------= + self.minorLimbs = minorLimbs + self.minorLimbsIsSigned = isSigned + } + + //=--------------------------------------------------------------------= + // MARK: Utilities + //=--------------------------------------------------------------------= + + /// Returns the exact count when `minorLimbs.underestimatedCount` does. + @inlinable public var underestimatedCount: Int { + let ratio = MajorLimb.bitWidth / MinorLimb.bitWidth + let division = minorLimbs.underestimatedCount.quotientAndRemainder(dividingBy: ratio) + return division.quotient + Int(bit: !division.remainder.isZero) + } + + @inlinable public func makeIterator() -> Iterator { + Iterator(minorLimbs: self.minorLimbs, isSigned: self.minorLimbsIsSigned) + } + + //*====================================================================* + // MARK: * Iterator + //*====================================================================* + + @frozen public struct Iterator: IteratorProtocol { + + //=----------------------------------------------------------------= + // MARK: State + //=----------------------------------------------------------------= + + @usableFromInline var minorLimbs: MinorLimbs.Iterator + @usableFromInline let minorLimbsIsSigned: Bool + + //=----------------------------------------------------------------= + // MARK: Initializers + //=----------------------------------------------------------------= + + @inlinable init(minorLimbs: MinorLimbs, isSigned: Bool) { + self.minorLimbs = minorLimbs.makeIterator() + self.minorLimbsIsSigned = isSigned + } + + //=----------------------------------------------------------------= + // MARK: Utilities + //=----------------------------------------------------------------= + + @inlinable public mutating func next() -> MajorLimb? { + var majorLimb = MajorLimb.zero + var majorLimbShift = Int.zero + var minorLimb = MinorLimb.Magnitude.zero + + while let next = self.minorLimbs.next() { + minorLimb = MinorLimb.Magnitude(bitPattern: next) + majorLimb |= MajorLimb(truncatingIfNeeded: minorLimb) &<< majorLimbShift + + do { majorLimbShift += MinorLimb.bitWidth } + guard majorLimbShift < MajorLimb.bitWidth else { return majorLimb } + } + + guard !majorLimbShift.isZero else { return nil } + let bit: Bool = self.minorLimbsIsSigned && minorLimb.mostSignificantBit + return majorLimb | MajorLimb(repeating: bit) &<< majorLimbShift + } + } +} diff --git a/Sources/Numberick/Documentation.docc/Documentation.md b/Sources/Numberick/Documentation.docc/Documentation.md index 71efa577..562c4878 100644 --- a/Sources/Numberick/Documentation.docc/Documentation.md +++ b/Sources/Numberick/Documentation.docc/Documentation.md @@ -18,8 +18,9 @@ A new protocol hierarchy that refines Swift's standard library. ### Models - ``NBKEndianness`` -- ``NBKTwinHeaded`` +- ``NBKMajorIntegerLimbs`` - ``NBKMajorOrMinorIntegerLimbs`` +- ``NBKTwinHeaded`` ## NBKDoubleWidthKit @@ -112,8 +113,9 @@ Int256(5) % Int(5), UInt256(5) % UInt(5) - ``NBKDoubleWidth`` - ``NBKEndianness`` -- ``NBKTwinHeaded`` +- ``NBKMajorIntegerLimbs`` - ``NBKMajorOrMinorIntegerLimbs`` +- ``NBKTwinHeaded`` ### Integers diff --git a/Tests/NBKCoreKitTests/Models/NBKMajorOrMinorLimbs.swift b/Tests/NBKCoreKitTests/Models/NBKMajorOrMinorIntegerLimbs.swift similarity index 100% rename from Tests/NBKCoreKitTests/Models/NBKMajorOrMinorLimbs.swift rename to Tests/NBKCoreKitTests/Models/NBKMajorOrMinorIntegerLimbs.swift From f5fbfe8603b008c2426d7b5d39489522305ab925 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Thu, 31 Aug 2023 08:56:22 +0200 Subject: [PATCH 079/111] [NBKCoreKit] MinorIntegerLimbs (#73). --- README.md | 1 + .../Models/NBKMajorOrMinorIntegerLimbs.swift | 146 ++++++++++++++---- .../Documentation.docc/Documentation.md | 2 + 3 files changed, 120 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index 0864fb11..9aa93e29 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,7 @@ A new protocol hierarchy that refines Swift's standard library. - [NBKEndianness](Sources/NBKCoreKit/Models/NBKEndianness.swift) - [NBKMajorIntegerLimbs](Sources/NBKCoreKit/Models/NBKMajorOrMinorIntegerLimbs.swift) - [NBKMajorOrMinorIntegerLimbs](Sources/NBKCoreKit/Models/NBKMajorOrMinorIntegerLimbs.swift) +- [NBKMinorIntegerLimbs](Sources/NBKCoreKit/Models/NBKMajorOrMinorIntegerLimbs.swift) - [NBKTwinHeaded](Sources/NBKCoreKit/Models/NBKTwinHeaded.swift) ## [NBKDoubleWidthKit][DBL/D] ([Sources][DBL/S], [Tests][DBL/T], [Benchmarks][DBL/B]) diff --git a/Sources/NBKCoreKit/Models/NBKMajorOrMinorIntegerLimbs.swift b/Sources/NBKCoreKit/Models/NBKMajorOrMinorIntegerLimbs.swift index 7b12848d..67deb877 100644 --- a/Sources/NBKCoreKit/Models/NBKMajorOrMinorIntegerLimbs.swift +++ b/Sources/NBKCoreKit/Models/NBKMajorOrMinorIntegerLimbs.swift @@ -29,25 +29,25 @@ Limb: NBKCoreInteger, Source: Sequence, Source.Element: NBKCoreInteger { public typealias MajorLimbs = NBKMajorIntegerLimbs // TODO: with public models - public typealias MinorLimbs = NBK.MinorLimbsSequence + public typealias MinorLimbs = NBKMinorIntegerLimbs - //=--------------------------------------------------------------------= + //=------------------------------------------------------------------------= // MARK: State - //=--------------------------------------------------------------------= + //=------------------------------------------------------------------------= // NOTE: Two parallel options appear to be faster than a combined enum. - //=--------------------------------------------------------------------= + //=------------------------------------------------------------------------= @usableFromInline let minorLimbs: MinorLimbs? @usableFromInline let majorLimbs: MajorLimbs? - //=--------------------------------------------------------------------= + //=------------------------------------------------------------------------= // MARK: Initializers - //=--------------------------------------------------------------------= + //=------------------------------------------------------------------------= /// Creates a sequence of the given type, from an un/signed source. @inlinable public init(_ source: Source, isSigned: Bool = false, as limb: Limb.Type = Limb.self) { if Limb.bitWidth < Source.Element.bitWidth { - self.minorLimbs = MinorLimbs(majorLimbs: source) + self.minorLimbs = MinorLimbs(source, isSigned: isSigned) self.majorLimbs = nil } else { self.minorLimbs = nil @@ -55,9 +55,9 @@ Limb: NBKCoreInteger, Source: Sequence, Source.Element: NBKCoreInteger { } } - //=--------------------------------------------------------------------= + //=------------------------------------------------------------------------= // MARK: Utilities - //=--------------------------------------------------------------------= + //=------------------------------------------------------------------------= @inlinable public var underestimatedCount: Int { if Limb.bitWidth < Source.Element.bitWidth { @@ -81,25 +81,25 @@ Limb: NBKCoreInteger, Source: Sequence, Source.Element: NBKCoreInteger { @frozen public struct Iterator: IteratorProtocol { - //=----------------------------------------------------------------= + //=--------------------------------------------------------------------= // MARK: State - //=----------------------------------------------------------------= + //=--------------------------------------------------------------------= @usableFromInline var minorLimbs: MinorLimbs.Iterator? @usableFromInline var majorLimbs: MajorLimbs.Iterator? - //=----------------------------------------------------------------= + //=--------------------------------------------------------------------= // MARK: Initializers - //=----------------------------------------------------------------= + //=--------------------------------------------------------------------= @inlinable init(minorLimbs: MinorLimbs.Iterator? = nil, majorLimbs: MajorLimbs.Iterator? = nil) { self.minorLimbs = minorLimbs self.majorLimbs = majorLimbs } - //=----------------------------------------------------------------= + //=--------------------------------------------------------------------= // MARK: Utilities - //=----------------------------------------------------------------= + //=--------------------------------------------------------------------= @inlinable public mutating func next() -> Limb? { if Limb.bitWidth < Source.Element.bitWidth { @@ -122,16 +122,16 @@ MajorLimb: NBKCoreInteger, MinorLimbs: Sequence, MinorLimbs.Element: NBKCoreInte public typealias MinorLimb = MinorLimbs.Element - //=--------------------------------------------------------------------= + //=------------------------------------------------------------------------= // MARK: State - //=--------------------------------------------------------------------= + //=------------------------------------------------------------------------= @usableFromInline let minorLimbs: MinorLimbs @usableFromInline let minorLimbsIsSigned: Bool - //=--------------------------------------------------------------------= + //=------------------------------------------------------------------------= // MARK: Initializers - //=--------------------------------------------------------------------= + //=------------------------------------------------------------------------= @inlinable public init(_ minorLimbs: MinorLimbs, isSigned: Bool = false, as majorLimb: MajorLimb.Type = MajorLimb.self) { //=--------------------------------------= @@ -143,9 +143,9 @@ MajorLimb: NBKCoreInteger, MinorLimbs: Sequence, MinorLimbs.Element: NBKCoreInte self.minorLimbsIsSigned = isSigned } - //=--------------------------------------------------------------------= + //=------------------------------------------------------------------------= // MARK: Utilities - //=--------------------------------------------------------------------= + //=------------------------------------------------------------------------= /// Returns the exact count when `minorLimbs.underestimatedCount` does. @inlinable public var underestimatedCount: Int { @@ -158,31 +158,31 @@ MajorLimb: NBKCoreInteger, MinorLimbs: Sequence, MinorLimbs.Element: NBKCoreInte Iterator(minorLimbs: self.minorLimbs, isSigned: self.minorLimbsIsSigned) } - //*====================================================================* + //*========================================================================* // MARK: * Iterator - //*====================================================================* + //*========================================================================* @frozen public struct Iterator: IteratorProtocol { - //=----------------------------------------------------------------= + //=--------------------------------------------------------------------= // MARK: State - //=----------------------------------------------------------------= + //=--------------------------------------------------------------------= @usableFromInline var minorLimbs: MinorLimbs.Iterator @usableFromInline let minorLimbsIsSigned: Bool - //=----------------------------------------------------------------= + //=--------------------------------------------------------------------= // MARK: Initializers - //=----------------------------------------------------------------= + //=--------------------------------------------------------------------= @inlinable init(minorLimbs: MinorLimbs, isSigned: Bool) { self.minorLimbs = minorLimbs.makeIterator() self.minorLimbsIsSigned = isSigned } - //=----------------------------------------------------------------= + //=--------------------------------------------------------------------= // MARK: Utilities - //=----------------------------------------------------------------= + //=--------------------------------------------------------------------= @inlinable public mutating func next() -> MajorLimb? { var majorLimb = MajorLimb.zero @@ -203,3 +203,91 @@ MajorLimb: NBKCoreInteger, MinorLimbs: Sequence, MinorLimbs.Element: NBKCoreInte } } } + +//*============================================================================* +// MARK: * NBK x Minor Integer Limbs +//*============================================================================* + +@frozen public struct NBKMinorIntegerLimbs: Sequence where +MinorLimb: NBKCoreInteger, MajorLimbs: Sequence, MajorLimbs.Element: NBKCoreInteger { + + public typealias MajorLimb = MajorLimbs.Element + + public typealias MinorLimb = MinorLimb + + // TODO: with public models + @usableFromInline typealias MinorLimbsOfOne = NBK.MinorLimbsSubSequence + + //=------------------------------------------------------------------------= + // MARK: State + //=------------------------------------------------------------------------= + + @usableFromInline let majorLimbs: MajorLimbs + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + @inlinable public init(_ majorLimbs: MajorLimbs, isSigned: Bool = false, as minorLimb: MinorLimb.Type = MinorLimb.self) { + //=--------------------------------------= + precondition(MinorLimb.bitWidth.isPowerOf2) + precondition(MajorLimb.bitWidth.isPowerOf2) + precondition(MinorLimb.bitWidth <= MajorLimb.bitWidth) + //=--------------------------------------= + self.majorLimbs = majorLimbs + } + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + /// Returns the exact count when `majorLimbs.underestimatedCount` does. + @inlinable public var underestimatedCount: Int { + MajorLimb.bitWidth / MinorLimb.bitWidth * self.majorLimbs.underestimatedCount + } + + @inlinable public func makeIterator() -> Iterator { + Iterator(self.majorLimbs.makeIterator()) + } + + //*========================================================================* + // MARK: * Iterator + //*========================================================================* + + @frozen public struct Iterator: IteratorProtocol { + + //=--------------------------------------------------------------------= + // MARK: State + //=--------------------------------------------------------------------= + + @usableFromInline var majorLimbs: MajorLimbs.Iterator + @usableFromInline var minorLimbs: MinorLimbsOfOne.Iterator? + + //=--------------------------------------------------------------------= + // MARK: Initializers + //=--------------------------------------------------------------------= + + @inlinable init(_ majorLimbs: MajorLimbs.Iterator) { + self.majorLimbs = majorLimbs + self.minorLimbs = nil + } + + //=--------------------------------------------------------------------= + // MARK: Utilities + //=--------------------------------------------------------------------= + + @inlinable mutating public func next() -> MinorLimb? { + repeat { + + if let minorLimb = self.minorLimbs?.next() { + return minorLimb + } else if let majorLimb = self.majorLimbs.next() { + self.minorLimbs = MinorLimbsOfOne.Iterator(majorLimb: majorLimb) + } else { + return nil + } + + } while true + } + } +} diff --git a/Sources/Numberick/Documentation.docc/Documentation.md b/Sources/Numberick/Documentation.docc/Documentation.md index 562c4878..d7fdeb6a 100644 --- a/Sources/Numberick/Documentation.docc/Documentation.md +++ b/Sources/Numberick/Documentation.docc/Documentation.md @@ -20,6 +20,7 @@ A new protocol hierarchy that refines Swift's standard library. - ``NBKEndianness`` - ``NBKMajorIntegerLimbs`` - ``NBKMajorOrMinorIntegerLimbs`` +- ``NBKMinorIntegerLimbs`` - ``NBKTwinHeaded`` ## NBKDoubleWidthKit @@ -115,6 +116,7 @@ Int256(5) % Int(5), UInt256(5) % UInt(5) - ``NBKEndianness`` - ``NBKMajorIntegerLimbs`` - ``NBKMajorOrMinorIntegerLimbs`` +- ``NBKMinorIntegerLimbs`` - ``NBKTwinHeaded`` ### Integers From 32be22fd0e044140f195345e3e193f5d007dc7ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Thu, 31 Aug 2023 09:06:00 +0200 Subject: [PATCH 080/111] [NBKCoreKit] MinorIntegerLimbsOfOne (#73). --- README.md | 1 + .../Models/NBKMajorOrMinorIntegerLimbs.swift | 141 ++++++++++++++---- .../Documentation.docc/Documentation.md | 2 + 3 files changed, 116 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 9aa93e29..6a9cc1f1 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,7 @@ A new protocol hierarchy that refines Swift's standard library. - [NBKMajorIntegerLimbs](Sources/NBKCoreKit/Models/NBKMajorOrMinorIntegerLimbs.swift) - [NBKMajorOrMinorIntegerLimbs](Sources/NBKCoreKit/Models/NBKMajorOrMinorIntegerLimbs.swift) - [NBKMinorIntegerLimbs](Sources/NBKCoreKit/Models/NBKMajorOrMinorIntegerLimbs.swift) +- [NBKMinorIntegerLimbsOfOne](Sources/NBKCoreKit/Models/NBKMajorOrMinorIntegerLimbs.swift) - [NBKTwinHeaded](Sources/NBKCoreKit/Models/NBKTwinHeaded.swift) ## [NBKDoubleWidthKit][DBL/D] ([Sources][DBL/S], [Tests][DBL/T], [Benchmarks][DBL/B]) diff --git a/Sources/NBKCoreKit/Models/NBKMajorOrMinorIntegerLimbs.swift b/Sources/NBKCoreKit/Models/NBKMajorOrMinorIntegerLimbs.swift index 67deb877..3a4d6bbc 100644 --- a/Sources/NBKCoreKit/Models/NBKMajorOrMinorIntegerLimbs.swift +++ b/Sources/NBKCoreKit/Models/NBKMajorOrMinorIntegerLimbs.swift @@ -25,10 +25,8 @@ Limb: NBKCoreInteger, Source: Sequence, Source.Element: NBKCoreInteger { public typealias Source = Source - // TODO: with public models public typealias MajorLimbs = NBKMajorIntegerLimbs - // TODO: with public models public typealias MinorLimbs = NBKMinorIntegerLimbs //=------------------------------------------------------------------------= @@ -47,7 +45,7 @@ Limb: NBKCoreInteger, Source: Sequence, Source.Element: NBKCoreInteger { /// Creates a sequence of the given type, from an un/signed source. @inlinable public init(_ source: Source, isSigned: Bool = false, as limb: Limb.Type = Limb.self) { if Limb.bitWidth < Source.Element.bitWidth { - self.minorLimbs = MinorLimbs(source, isSigned: isSigned) + self.minorLimbs = MinorLimbs(source) self.majorLimbs = nil } else { self.minorLimbs = nil @@ -59,6 +57,7 @@ Limb: NBKCoreInteger, Source: Sequence, Source.Element: NBKCoreInteger { // MARK: Utilities //=------------------------------------------------------------------------= + // TODO: documentation @inlinable public var underestimatedCount: Int { if Limb.bitWidth < Source.Element.bitWidth { return self.minorLimbs!.underestimatedCount @@ -79,27 +78,28 @@ Limb: NBKCoreInteger, Source: Sequence, Source.Element: NBKCoreInteger { // MARK: * Iterator //*====================================================================* + // TODO: documentation @frozen public struct Iterator: IteratorProtocol { - //=--------------------------------------------------------------------= + //=------------------------------------------------------------------------= // MARK: State - //=--------------------------------------------------------------------= + //=------------------------------------------------------------------------= @usableFromInline var minorLimbs: MinorLimbs.Iterator? @usableFromInline var majorLimbs: MajorLimbs.Iterator? - //=--------------------------------------------------------------------= + //=------------------------------------------------------------------------= // MARK: Initializers - //=--------------------------------------------------------------------= + //=------------------------------------------------------------------------= @inlinable init(minorLimbs: MinorLimbs.Iterator? = nil, majorLimbs: MajorLimbs.Iterator? = nil) { self.minorLimbs = minorLimbs self.majorLimbs = majorLimbs } - //=--------------------------------------------------------------------= + //=------------------------------------------------------------------------= // MARK: Utilities - //=--------------------------------------------------------------------= + //=------------------------------------------------------------------------= @inlinable public mutating func next() -> Limb? { if Limb.bitWidth < Source.Element.bitWidth { @@ -115,6 +115,7 @@ Limb: NBKCoreInteger, Source: Sequence, Source.Element: NBKCoreInteger { // MARK: * NBK x Major Integer Limbs //*============================================================================* +// TODO: documentation @frozen public struct NBKMajorIntegerLimbs: Sequence where MajorLimb: NBKCoreInteger, MinorLimbs: Sequence, MinorLimbs.Element: NBKCoreInteger { @@ -133,6 +134,7 @@ MajorLimb: NBKCoreInteger, MinorLimbs: Sequence, MinorLimbs.Element: NBKCoreInte // MARK: Initializers //=------------------------------------------------------------------------= + // TODO: documentation @inlinable public init(_ minorLimbs: MinorLimbs, isSigned: Bool = false, as majorLimb: MajorLimb.Type = MajorLimb.self) { //=--------------------------------------= precondition(MinorLimb.bitWidth.isPowerOf2) @@ -155,34 +157,35 @@ MajorLimb: NBKCoreInteger, MinorLimbs: Sequence, MinorLimbs.Element: NBKCoreInte } @inlinable public func makeIterator() -> Iterator { - Iterator(minorLimbs: self.minorLimbs, isSigned: self.minorLimbsIsSigned) + Iterator(self.minorLimbs.makeIterator(), isSigned: self.minorLimbsIsSigned) } //*========================================================================* // MARK: * Iterator //*========================================================================* + // TODO: documentation @frozen public struct Iterator: IteratorProtocol { - //=--------------------------------------------------------------------= + //=------------------------------------------------------------------------= // MARK: State - //=--------------------------------------------------------------------= + //=------------------------------------------------------------------------= @usableFromInline var minorLimbs: MinorLimbs.Iterator @usableFromInline let minorLimbsIsSigned: Bool - //=--------------------------------------------------------------------= + //=------------------------------------------------------------------------= // MARK: Initializers - //=--------------------------------------------------------------------= + //=------------------------------------------------------------------------= - @inlinable init(minorLimbs: MinorLimbs, isSigned: Bool) { - self.minorLimbs = minorLimbs.makeIterator() + @inlinable init(_ minorLimbs: MinorLimbs.Iterator, isSigned: Bool) { + self.minorLimbs = minorLimbs self.minorLimbsIsSigned = isSigned } - //=--------------------------------------------------------------------= + //=------------------------------------------------------------------------= // MARK: Utilities - //=--------------------------------------------------------------------= + //=------------------------------------------------------------------------= @inlinable public mutating func next() -> MajorLimb? { var majorLimb = MajorLimb.zero @@ -208,6 +211,7 @@ MajorLimb: NBKCoreInteger, MinorLimbs: Sequence, MinorLimbs.Element: NBKCoreInte // MARK: * NBK x Minor Integer Limbs //*============================================================================* +// TODO: documentation @frozen public struct NBKMinorIntegerLimbs: Sequence where MinorLimb: NBKCoreInteger, MajorLimbs: Sequence, MajorLimbs.Element: NBKCoreInteger { @@ -215,8 +219,7 @@ MinorLimb: NBKCoreInteger, MajorLimbs: Sequence, MajorLimbs.Element: NBKCoreInte public typealias MinorLimb = MinorLimb - // TODO: with public models - @usableFromInline typealias MinorLimbsOfOne = NBK.MinorLimbsSubSequence + @usableFromInline typealias MinorLimbsOfOne = NBKMinorIntegerLimbsOfOne //=------------------------------------------------------------------------= // MARK: State @@ -228,7 +231,8 @@ MinorLimb: NBKCoreInteger, MajorLimbs: Sequence, MajorLimbs.Element: NBKCoreInte // MARK: Initializers //=------------------------------------------------------------------------= - @inlinable public init(_ majorLimbs: MajorLimbs, isSigned: Bool = false, as minorLimb: MinorLimb.Type = MinorLimb.self) { + // TODO: documentation + @inlinable public init(_ majorLimbs: MajorLimbs, as minorLimb: MinorLimb.Type = MinorLimb.self) { //=--------------------------------------= precondition(MinorLimb.bitWidth.isPowerOf2) precondition(MajorLimb.bitWidth.isPowerOf2) @@ -254,27 +258,28 @@ MinorLimb: NBKCoreInteger, MajorLimbs: Sequence, MajorLimbs.Element: NBKCoreInte // MARK: * Iterator //*========================================================================* + // TODO: documentation @frozen public struct Iterator: IteratorProtocol { - //=--------------------------------------------------------------------= + //=------------------------------------------------------------------------= // MARK: State - //=--------------------------------------------------------------------= + //=------------------------------------------------------------------------= @usableFromInline var majorLimbs: MajorLimbs.Iterator @usableFromInline var minorLimbs: MinorLimbsOfOne.Iterator? - //=--------------------------------------------------------------------= + //=------------------------------------------------------------------------= // MARK: Initializers - //=--------------------------------------------------------------------= + //=------------------------------------------------------------------------= @inlinable init(_ majorLimbs: MajorLimbs.Iterator) { self.majorLimbs = majorLimbs self.minorLimbs = nil } - //=--------------------------------------------------------------------= + //=------------------------------------------------------------------------= // MARK: Utilities - //=--------------------------------------------------------------------= + //=------------------------------------------------------------------------= @inlinable mutating public func next() -> MinorLimb? { repeat { @@ -282,7 +287,7 @@ MinorLimb: NBKCoreInteger, MajorLimbs: Sequence, MajorLimbs.Element: NBKCoreInte if let minorLimb = self.minorLimbs?.next() { return minorLimb } else if let majorLimb = self.majorLimbs.next() { - self.minorLimbs = MinorLimbsOfOne.Iterator(majorLimb: majorLimb) + self.minorLimbs = MinorLimbsOfOne.Iterator(majorLimb) } else { return nil } @@ -291,3 +296,83 @@ MinorLimb: NBKCoreInteger, MajorLimbs: Sequence, MajorLimbs.Element: NBKCoreInte } } } + +//*============================================================================* +// MARK: * NBK x Minor Integer Limbs Of One +//*============================================================================* + +// TODO: documentation +@frozen public struct NBKMinorIntegerLimbsOfOne: +Sequence where MinorLimb: NBKCoreInteger, MajorLimb: NBKCoreInteger { + + public typealias MajorLimb = MajorLimb + + public typealias MinorLimb = MinorLimb + + //=------------------------------------------------------------------------= + // MARK: State + //=------------------------------------------------------------------------= + + @usableFromInline let majorLimb: MajorLimb + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + // TODO: documentation + @inlinable public init(_ majorLimb: MajorLimb, as minorLimb: MinorLimb.Type = MinorLimb.self) { + //=--------------------------------------= + precondition(MinorLimb.bitWidth.isPowerOf2) + precondition(MajorLimb.bitWidth.isPowerOf2) + precondition(MinorLimb.bitWidth <= MajorLimb.bitWidth) + //=--------------------------------------= + self.majorLimb = majorLimb + } + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + /// Returns the exact count. + @inlinable public var underestimatedCount: Int { + MajorLimb.bitWidth / MinorLimb.bitWidth + } + + @inlinable public func makeIterator() -> Iterator { + Iterator(self.majorLimb) + } + + //*========================================================================* + // MARK: * Iterator + //*========================================================================* + + // TODO: documentation + @frozen public struct Iterator: IteratorProtocol { + + //=--------------------------------------------------------------------= + // MARK: State + //=--------------------------------------------------------------------= + + @usableFromInline let majorLimb: MajorLimb + @usableFromInline var majorLimbShift: Int + + //=--------------------------------------------------------------------= + // MARK: Initializers + //=--------------------------------------------------------------------= + + @inlinable init(_ majorLimb: MajorLimb) { + self.majorLimb = majorLimb + self.majorLimbShift = Int.zero + } + + //=--------------------------------------------------------------------= + // MARK: Utilities + //=--------------------------------------------------------------------= + + @inlinable public mutating func next() -> MinorLimb? { + guard self.majorLimbShift < MajorLimb.bitWidth else { return nil } + defer{ self.majorLimbShift += MinorLimb.bitWidth } + return MinorLimb(truncatingIfNeeded: self.majorLimb &>> self.majorLimbShift) + } + } +} diff --git a/Sources/Numberick/Documentation.docc/Documentation.md b/Sources/Numberick/Documentation.docc/Documentation.md index d7fdeb6a..330452ad 100644 --- a/Sources/Numberick/Documentation.docc/Documentation.md +++ b/Sources/Numberick/Documentation.docc/Documentation.md @@ -21,6 +21,7 @@ A new protocol hierarchy that refines Swift's standard library. - ``NBKMajorIntegerLimbs`` - ``NBKMajorOrMinorIntegerLimbs`` - ``NBKMinorIntegerLimbs`` +- ``NBKMinorIntegerLimbsOfOne`` - ``NBKTwinHeaded`` ## NBKDoubleWidthKit @@ -117,6 +118,7 @@ Int256(5) % Int(5), UInt256(5) % UInt(5) - ``NBKMajorIntegerLimbs`` - ``NBKMajorOrMinorIntegerLimbs`` - ``NBKMinorIntegerLimbs`` +- ``NBKMinorIntegerLimbsOfOne`` - ``NBKTwinHeaded`` ### Integers From 83c233eabe5c3df0fa716f4bf2c2765091d71e0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Thu, 31 Aug 2023 09:19:39 +0200 Subject: [PATCH 081/111] [NBKCoreKit] MajorOrMinorIntegerLimbs (#73). --- .../Models/NBKMajorOrMinorIntegerLimbs.swift | 3 +- Sources/NBKCoreKit/Private/NBK+Limbs.swift | 362 ------------------ .../Models/NBKMajorOrMinorIntegerLimbs.swift | 58 +++ .../Private/NBK+Limbs.swift | 30 -- Tests/NBKCoreKitTests/Private/NBK+Limbs.swift | 155 -------- 5 files changed, 59 insertions(+), 549 deletions(-) delete mode 100644 Sources/NBKCoreKit/Private/NBK+Limbs.swift create mode 100644 Tests/NBKCoreKitBenchmarks/Models/NBKMajorOrMinorIntegerLimbs.swift diff --git a/Sources/NBKCoreKit/Models/NBKMajorOrMinorIntegerLimbs.swift b/Sources/NBKCoreKit/Models/NBKMajorOrMinorIntegerLimbs.swift index 3a4d6bbc..dd878b0b 100644 --- a/Sources/NBKCoreKit/Models/NBKMajorOrMinorIntegerLimbs.swift +++ b/Sources/NBKCoreKit/Models/NBKMajorOrMinorIntegerLimbs.swift @@ -7,7 +7,6 @@ // See http://www.apache.org/licenses/LICENSE-2.0 for license information. //=----------------------------------------------------------------------------= -// TODO: Use input to output parameter order? //*============================================================================* // MARK: * NBK x Major Or Minor Integer Limbs //*============================================================================* @@ -17,7 +16,7 @@ /// ### Binary Integer Order /// /// This sequence is binary integer ordered, so it merges or splits limbs -/// from least to most significant. You can reorder it by reversing the input, +/// from least significant to most. You can reorder it by reversing the input, /// the output, or both. /// @frozen public struct NBKMajorOrMinorIntegerLimbs: Sequence where diff --git a/Sources/NBKCoreKit/Private/NBK+Limbs.swift b/Sources/NBKCoreKit/Private/NBK+Limbs.swift deleted file mode 100644 index cfdbf6d8..00000000 --- a/Sources/NBKCoreKit/Private/NBK+Limbs.swift +++ /dev/null @@ -1,362 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -//*============================================================================* -// MARK: * NBK x Limbs -//*============================================================================* - -extension NBK { - - //*========================================================================* - // MARK: * Major Or Minor Limbs Sequence - //*========================================================================* - - @frozen public struct MajorOrMinorLimbsSequence: Sequence where - Limb: NBKCoreInteger, Source: Sequence, Source.Element: NBKCoreInteger { - - @usableFromInline typealias MinorLimbs = NBK.MinorLimbsSequence - - @usableFromInline typealias MajorLimbs = NBK.MajorLimbsSequence - - //=--------------------------------------------------------------------= - // MARK: State - //=--------------------------------------------------------------------= - // NOTE: Two parallel options appear to be faster than a combined enum. - //=--------------------------------------------------------------------= - - @usableFromInline let minorLimbs: MinorLimbs? - @usableFromInline let majorLimbs: MajorLimbs? - - //=--------------------------------------------------------------------= - // MARK: Initializers - //=--------------------------------------------------------------------= - - @inlinable public init(_ source: Source, isSigned: Bool = false, as limb: Limb.Type = Limb.self) { - if Limb.bitWidth < Source.Element.bitWidth { - self.minorLimbs = MinorLimbs(majorLimbs: source) - self.majorLimbs = nil - } else { - self.minorLimbs = nil - self.majorLimbs = MajorLimbs(minorLimbs: source, isSigned: isSigned) - } - } - - //=--------------------------------------------------------------------= - // MARK: Utilities - //=--------------------------------------------------------------------= - - @inlinable public var underestimatedCount: Int { - if Limb.bitWidth < Source.Element.bitWidth { - return self.minorLimbs!.underestimatedCount - } else { - return self.majorLimbs!.underestimatedCount - } - } - - @inlinable public func makeIterator() -> Iterator { - if Limb.bitWidth < Source.Element.bitWidth { - return Iterator(minorLimbs: self.minorLimbs!.makeIterator()) - } else { - return Iterator(majorLimbs: self.majorLimbs!.makeIterator()) - } - } - - //*====================================================================* - // MARK: * Iterator - //*====================================================================* - - @frozen public struct Iterator: IteratorProtocol { - - //=----------------------------------------------------------------= - // MARK: State - //=----------------------------------------------------------------= - - @usableFromInline var minorLimbs: MinorLimbs.Iterator? - @usableFromInline var majorLimbs: MajorLimbs.Iterator? - - //=----------------------------------------------------------------= - // MARK: Initializers - //=----------------------------------------------------------------= - - @inlinable init(minorLimbs: MinorLimbs.Iterator? = nil, majorLimbs: MajorLimbs.Iterator? = nil) { - self.minorLimbs = minorLimbs - self.majorLimbs = majorLimbs - } - - //=----------------------------------------------------------------= - // MARK: Utilities - //=----------------------------------------------------------------= - - @inlinable public mutating func next() -> Limb? { - if Limb.bitWidth < Source.Element.bitWidth { - return self.minorLimbs!.next() - } else { - return self.majorLimbs!.next() - } - } - } - } - - //*========================================================================* - // MARK: * Major Limbs Sequence - //*========================================================================* - - @frozen public struct MajorLimbsSequence: Sequence where - MajorLimb: NBKCoreInteger, MinorLimbs: Sequence, MinorLimbs.Element: NBKCoreInteger { - - public typealias MajorLimb = MajorLimb - - public typealias MinorLimb = MinorLimbs.Element - - //=--------------------------------------------------------------------= - // MARK: State - //=--------------------------------------------------------------------= - - @usableFromInline let minorLimbs: MinorLimbs - @usableFromInline let minorLimbsIsSigned: Bool - - //=--------------------------------------------------------------------= - // MARK: Initializers - //=--------------------------------------------------------------------= - - @inlinable public init(minorLimbs: MinorLimbs, isSigned: Bool = false, as majorLimb: MajorLimb.Type = MajorLimb.self) { - //=--------------------------------------= - precondition(MinorLimb.bitWidth.isPowerOf2) - precondition(MajorLimb.bitWidth.isPowerOf2) - precondition(MinorLimb.bitWidth <= MajorLimb.bitWidth) - //=--------------------------------------= - self.minorLimbs = minorLimbs - self.minorLimbsIsSigned = isSigned - } - - //=--------------------------------------------------------------------= - // MARK: Utilities - //=--------------------------------------------------------------------= - - /// Returns the exact count when `minorLimbs.underestimatedCount` does. - @inlinable public var underestimatedCount: Int { - let ratio = MajorLimb.bitWidth / MinorLimb.bitWidth - let division = minorLimbs.underestimatedCount.quotientAndRemainder(dividingBy: ratio) - return division.quotient + Int(bit: !division.remainder.isZero) - } - - @inlinable public func makeIterator() -> Iterator { - Iterator(minorLimbs: self.minorLimbs, isSigned: self.minorLimbsIsSigned) - } - - //*====================================================================* - // MARK: * Iterator - //*====================================================================* - - @frozen public struct Iterator: IteratorProtocol { - - //=----------------------------------------------------------------= - // MARK: State - //=----------------------------------------------------------------= - - @usableFromInline var minorLimbs: MinorLimbs.Iterator - @usableFromInline let minorLimbsIsSigned: Bool - - //=----------------------------------------------------------------= - // MARK: Initializers - //=----------------------------------------------------------------= - - @inlinable init(minorLimbs: MinorLimbs, isSigned: Bool) { - self.minorLimbs = minorLimbs.makeIterator() - self.minorLimbsIsSigned = isSigned - } - - //=----------------------------------------------------------------= - // MARK: Utilities - //=----------------------------------------------------------------= - - @inlinable public mutating func next() -> MajorLimb? { - var majorLimb = MajorLimb.zero - var majorLimbShift = Int.zero - var minorLimb = MinorLimb.Magnitude.zero - - while let next = self.minorLimbs.next() { - minorLimb = MinorLimb.Magnitude(bitPattern: next) - majorLimb |= MajorLimb(truncatingIfNeeded: minorLimb) &<< majorLimbShift - - do { majorLimbShift += MinorLimb.bitWidth } - guard majorLimbShift < MajorLimb.bitWidth else { return majorLimb } - } - - guard !majorLimbShift.isZero else { return nil } - let bit: Bool = self.minorLimbsIsSigned && minorLimb.mostSignificantBit - return majorLimb | MajorLimb(repeating: bit) &<< majorLimbShift - } - } - } - - //*========================================================================* - // MARK: * Minor Limbs - //*========================================================================* - - @frozen public struct MinorLimbsSequence: Sequence where - MinorLimb: NBKCoreInteger, MajorLimbs: Sequence, MajorLimbs.Element: NBKCoreInteger { - - public typealias MajorLimb = MajorLimbs.Element - - public typealias MinorLimb = MinorLimb - - public typealias MinorLimbsSubSequence = NBK.MinorLimbsSubSequence - - //=--------------------------------------------------------------------= - // MARK: State - //=--------------------------------------------------------------------= - - @usableFromInline let majorLimbs: MajorLimbs - - //=--------------------------------------------------------------------= - // MARK: Initializers - //=--------------------------------------------------------------------= - - @inlinable public init(majorLimbs: MajorLimbs, as minorLimb: MinorLimb.Type = MinorLimb.self) { - //=--------------------------------------= - precondition(MinorLimb.bitWidth.isPowerOf2) - precondition(MajorLimb.bitWidth.isPowerOf2) - precondition(MinorLimb.bitWidth <= MajorLimb.bitWidth) - //=--------------------------------------= - self.majorLimbs = majorLimbs - } - - //=--------------------------------------------------------------------= - // MARK: Utilities - //=--------------------------------------------------------------------= - - /// Returns the exact count when `majorLimbs.underestimatedCount` does. - @inlinable public var underestimatedCount: Int { - MajorLimb.bitWidth / MinorLimb.bitWidth * self.majorLimbs.underestimatedCount - } - - @inlinable public func makeIterator() -> Iterator { - Iterator(self.majorLimbs.makeIterator()) - } - - //*====================================================================* - // MARK: * Iterator - //*====================================================================* - - @frozen public struct Iterator: IteratorProtocol { - - //=----------------------------------------------------------------= - // MARK: State - //=----------------------------------------------------------------= - - @usableFromInline var majorLimbs: MajorLimbs.Iterator - @usableFromInline var minorLimbs: MinorLimbsSubSequence.Iterator? - - //=----------------------------------------------------------------= - // MARK: Initializers - //=----------------------------------------------------------------= - - @inlinable init(_ majorLimbs: MajorLimbs.Iterator) { - self.majorLimbs = majorLimbs - self.minorLimbs = nil - } - - //=----------------------------------------------------------------= - // MARK: Utilities - //=----------------------------------------------------------------= - - @inlinable mutating public func next() -> MinorLimb? { - repeat { - - if let minorLimb = self.minorLimbs?.next() { - return minorLimb - } else if let majorLimb = self.majorLimbs.next() { - self.minorLimbs = MinorLimbsSubSequence.Iterator(majorLimb: majorLimb) - } else { - return nil - } - - } while true - } - } - } - - //*========================================================================* - // MARK: * Minor Limbs Sub Sequence - //*========================================================================* - - @frozen public struct MinorLimbsSubSequence: - Sequence where MinorLimb: NBKCoreInteger, MajorLimb: NBKCoreInteger { - - public typealias MajorLimb = MajorLimb - - public typealias MinorLimb = MinorLimb - - //=--------------------------------------------------------------------= - // MARK: State - //=--------------------------------------------------------------------= - - @usableFromInline let majorLimb: MajorLimb - - //=--------------------------------------------------------------------= - // MARK: Initializers - //=--------------------------------------------------------------------= - - @inlinable public init(majorLimb: MajorLimb, as minorLimb: MinorLimb.Type = MinorLimb.self) { - //=--------------------------------------= - precondition(MinorLimb.bitWidth.isPowerOf2) - precondition(MajorLimb.bitWidth.isPowerOf2) - precondition(MinorLimb.bitWidth <= MajorLimb.bitWidth) - //=--------------------------------------= - self.majorLimb = majorLimb - } - - //=--------------------------------------------------------------------= - // MARK: Utilities - //=--------------------------------------------------------------------= - - /// Returns the exact count. - @inlinable public var underestimatedCount: Int { - MajorLimb.bitWidth / MinorLimb.bitWidth - } - - @inlinable public func makeIterator() -> Iterator { - Iterator(majorLimb: self.majorLimb) - } - - //*====================================================================* - // MARK: * Iterator - //*====================================================================* - - @frozen public struct Iterator: IteratorProtocol { - - //=----------------------------------------------------------------= - // MARK: State - //=----------------------------------------------------------------= - - @usableFromInline let majorLimb: MajorLimb - @usableFromInline var majorLimbShift: Int - - //=----------------------------------------------------------------= - // MARK: Initializers - //=----------------------------------------------------------------= - - @inlinable init(majorLimb: MajorLimb) { - self.majorLimb = majorLimb - self.majorLimbShift = Int.zero - } - - //=----------------------------------------------------------------= - // MARK: Utilities - //=----------------------------------------------------------------= - - @inlinable public mutating func next() -> MinorLimb? { - guard self.majorLimbShift < MajorLimb.bitWidth else { return nil } - defer{ self.majorLimbShift += MinorLimb.bitWidth } - return MinorLimb(truncatingIfNeeded: self.majorLimb &>> self.majorLimbShift) - } - } - } -} diff --git a/Tests/NBKCoreKitBenchmarks/Models/NBKMajorOrMinorIntegerLimbs.swift b/Tests/NBKCoreKitBenchmarks/Models/NBKMajorOrMinorIntegerLimbs.swift new file mode 100644 index 00000000..9e01550d --- /dev/null +++ b/Tests/NBKCoreKitBenchmarks/Models/NBKMajorOrMinorIntegerLimbs.swift @@ -0,0 +1,58 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if !DEBUG + +import NBKCoreKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Major Or Minor Integer Limbs +//*============================================================================* + +final class NBKMajorOrMinorIntegerLimbsBenchmarks: XCTestCase { + + typealias T = NBKMajorOrMinorIntegerLimbs + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testUInt64AsUInt32() { + var abc = NBK.blackHoleIdentity([ 1, 2, 3, 4] as X) + var xyz = NBK.blackHoleIdentity([~1, ~2, ~3, ~4] as X) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(Y(T(abc))) + NBK.blackHole(Y(T(xyz))) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testUInt32AsUInt64() { + var abc = NBK.blackHoleIdentity([ 1, 0, 2, 0, 3, 0, 4, 0] as Y) + var xyz = NBK.blackHoleIdentity([~1, ~0, ~2, ~0, ~3, ~0, ~4, ~0] as Y) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(X(T(abc))) + NBK.blackHole(X(T(xyz))) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } +} + +#endif diff --git a/Tests/NBKCoreKitBenchmarks/Private/NBK+Limbs.swift b/Tests/NBKCoreKitBenchmarks/Private/NBK+Limbs.swift index 17b9965f..b047c0c9 100644 --- a/Tests/NBKCoreKitBenchmarks/Private/NBK+Limbs.swift +++ b/Tests/NBKCoreKitBenchmarks/Private/NBK+Limbs.swift @@ -26,36 +26,6 @@ final class NBKBenchmarksOnLimbs: XCTestCase { // MARK: Tests //=------------------------------------------------------------------------= - func testUInt64AsUInt32() { - var abc = NBK.blackHoleIdentity([ 1, 2, 3, 4] as X) - var xyz = NBK.blackHoleIdentity([~1, ~2, ~3, ~4] as X) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(Y(NBK.MajorOrMinorLimbsSequence(abc))) - NBK.blackHole(Y(NBK.MajorOrMinorLimbsSequence(xyz))) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - func testUInt32AsUInt64() { - var abc = NBK.blackHoleIdentity([ 1, 0, 2, 0, 3, 0, 4, 0] as Y) - var xyz = NBK.blackHoleIdentity([~1, ~0, ~2, ~0, ~3, ~0, ~4, ~0] as Y) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(X(NBK.MajorOrMinorLimbsSequence(abc))) - NBK.blackHole(X(NBK.MajorOrMinorLimbsSequence(xyz))) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Succinct - //=------------------------------------------------------------------------= - func testMakeSuccinctSignedInteger() { var abc = NBK.blackHoleIdentity([ 1, 0, 2, 0, 3, 0, 4, 0] as W) var xyz = NBK.blackHoleIdentity([~1, ~0, ~2, ~0, ~3, ~0, ~4, ~0] as W) diff --git a/Tests/NBKCoreKitTests/Private/NBK+Limbs.swift b/Tests/NBKCoreKitTests/Private/NBK+Limbs.swift index 1ac7a53f..8effa911 100644 --- a/Tests/NBKCoreKitTests/Private/NBK+Limbs.swift +++ b/Tests/NBKCoreKitTests/Private/NBK+Limbs.swift @@ -22,99 +22,10 @@ private typealias Y = [UInt32] final class NBKTestsOnLimbs: XCTestCase { - private typealias S64 = [Int64] - private typealias S32 = [Int32] - //=------------------------------------------------------------------------= // MARK: Tests //=------------------------------------------------------------------------= - func testUInt32AsUInt32() { - NBKAssertLimbs([ ] as S32, [ ] as S32) - NBKAssertLimbs([ 1 ] as S32, [ 1 ] as S32) - NBKAssertLimbs([ 1, 2 ] as S32, [ 1, 2 ] as S32) - NBKAssertLimbs([ 1, 2, 3 ] as S32, [ 1, 2, 3 ] as S32) - NBKAssertLimbs([ 1, 2, 3, 4] as S32, [ 1, 2, 3, 4] as S32) - - NBKAssertLimbs([ ] as S32, [ ] as S32) - NBKAssertLimbs([~1 ] as S32, [~1 ] as S32) - NBKAssertLimbs([~1, ~2 ] as S32, [~1, ~2 ] as S32) - NBKAssertLimbs([~1, ~2, ~3 ] as S32, [~1, ~2, ~3 ] as S32) - NBKAssertLimbs([~1, ~2, ~3, ~4] as S32, [~1, ~2, ~3, ~4] as S32) - } - - func testUInt32AsUInt64() { - NBKAssertLimbs([ ] as S32, [ ] as S64) - NBKAssertLimbs([ 1, 0 ] as S32, [ 1 ] as S64) - NBKAssertLimbs([ 1, 0, 2, 0 ] as S32, [ 1, 2 ] as S64) - NBKAssertLimbs([ 1, 0, 2, 0, 3, 0 ] as S32, [ 1, 2, 3 ] as S64) - NBKAssertLimbs([ 1, 0, 2, 0, 3, 0, 4, 0] as S32, [ 1, 2, 3, 4] as S64) - - NBKAssertLimbs([ ] as S32, [ ] as S64) - NBKAssertLimbs([~1, ~0 ] as S32, [~1 ] as S64) - NBKAssertLimbs([~1, ~0, ~2, ~0 ] as S32, [~1, ~2 ] as S64) - NBKAssertLimbs([~1, ~0, ~2, ~0, ~3, ~0 ] as S32, [~1, ~2, ~3 ] as S64) - NBKAssertLimbs([~1, ~0, ~2, ~0, ~3, ~0, ~4, ~0] as S32, [~1, ~2, ~3, ~4] as S64) - } - - func testUInt64AsUInt64() { - NBKAssertLimbs([ ] as S64, [ ] as S64) - NBKAssertLimbs([ 1 ] as S64, [ 1 ] as S64) - NBKAssertLimbs([ 1, 2 ] as S64, [ 1, 2 ] as S64) - NBKAssertLimbs([ 1, 2, 3 ] as S64, [ 1, 2, 3 ] as S64) - NBKAssertLimbs([ 1, 2, 3, 4] as S64, [ 1, 2, 3, 4] as S64) - - NBKAssertLimbs([ ] as S64, [ ] as S64) - NBKAssertLimbs([~1 ] as S64, [~1 ] as S64) - NBKAssertLimbs([~1, ~2 ] as S64, [~1, ~2 ] as S64) - NBKAssertLimbs([~1, ~2, ~3 ] as S64, [~1, ~2, ~3 ] as S64) - NBKAssertLimbs([~1, ~2, ~3, ~4] as S64, [~1, ~2, ~3, ~4] as S64) - } - - func testUInt64AsUInt32() { - NBKAssertLimbs([ ] as S64, [ ] as S32) - NBKAssertLimbs([ 1 ] as S64, [ 1, 0 ] as S32) - NBKAssertLimbs([ 1, 2 ] as S64, [ 1, 0, 2, 0 ] as S32) - NBKAssertLimbs([ 1, 2, 3 ] as S64, [ 1, 0, 2, 0, 3, 0 ] as S32) - NBKAssertLimbs([ 1, 2, 3, 4] as S64, [ 1, 0, 2, 0, 3, 0, 4, 0] as S32) - - NBKAssertLimbs([ ] as S64, [ ] as S32) - NBKAssertLimbs([~1 ] as S64, [~1, ~0 ] as S32) - NBKAssertLimbs([~1, ~2 ] as S64, [~1, ~0, ~2, ~0 ] as S32) - NBKAssertLimbs([~1, ~2, ~3 ] as S64, [~1, ~0, ~2, ~0, ~3, ~0 ] as S32) - NBKAssertLimbs([~1, ~2, ~3, ~4] as S64, [~1, ~0, ~2, ~0, ~3, ~0, ~4, ~0] as S32) - } - - func testMajorLimbsFromMinorLimbsSubsequence() { - NBKAssertLimbsSubsequence([ ] as S32, [ ] as S64, isSigned: true ) - NBKAssertLimbsSubsequence([ 1 ] as S32, [ 1 ] as S64, isSigned: true ) - NBKAssertLimbsSubsequence([ 1, 0, 2 ] as S32, [ 1, 2 ] as S64, isSigned: true ) - NBKAssertLimbsSubsequence([ 1, 0, 2, 0, 3 ] as S32, [ 1, 2, 3 ] as S64, isSigned: true ) - NBKAssertLimbsSubsequence([ 1, 0, 2, 0, 3, 0, 4 ] as S32, [ 1, 2, 3, 4 ] as S64, isSigned: true ) - - NBKAssertLimbsSubsequence([ ] as S32, [ ] as S64, isSigned: true ) - NBKAssertLimbsSubsequence([~1 ] as S32, [~1 ] as S64, isSigned: true ) - NBKAssertLimbsSubsequence([~1, ~0, ~2 ] as S32, [~1, ~2 ] as S64, isSigned: true ) - NBKAssertLimbsSubsequence([~1, ~0, ~2, ~0, ~3 ] as S32, [~1, ~2, ~3 ] as S64, isSigned: true ) - NBKAssertLimbsSubsequence([~1, ~0, ~2, ~0, ~3, ~0, ~4 ] as S32, [~1, ~2, ~3, ~4 ] as S64, isSigned: true ) - - NBKAssertLimbsSubsequence([ ] as S32, [ ] as S64, isSigned: false) - NBKAssertLimbsSubsequence([ 1 ] as S32, [ 1 ] as S64, isSigned: false) - NBKAssertLimbsSubsequence([ 1, 0, 2 ] as S32, [ 1, 2 ] as S64, isSigned: false) - NBKAssertLimbsSubsequence([ 1, 0, 2, 0, 3 ] as S32, [ 1, 2, 3 ] as S64, isSigned: false) - NBKAssertLimbsSubsequence([ 1, 0, 2, 0, 3, 0, 4 ] as S32, [ 1, 2, 3, 4 ] as S64, isSigned: false) - - NBKAssertLimbsSubsequence([ ] as S32, [ ] as S64, isSigned: false) - NBKAssertLimbsSubsequence([~1 ] as S32, [ 0xfffffffe] as S64, isSigned: false) - NBKAssertLimbsSubsequence([~1, ~0, ~2 ] as S32, [~1, 0xfffffffd] as S64, isSigned: false) - NBKAssertLimbsSubsequence([~1, ~0, ~2, ~0, ~3 ] as S32, [~1, ~2, 0xfffffffc] as S64, isSigned: false) - NBKAssertLimbsSubsequence([~1, ~0, ~2, ~0, ~3, ~0, ~4 ] as S32, [~1, ~2, ~3, 0xfffffffb] as S64, isSigned: false) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Succinct - //=------------------------------------------------------------------------= - func testMakeSuccinctSignedInteger() { NBKAssertMakeSuccinctSignedInteger([ 0, 0, 0, 0] as W, [ ] as W, false) NBKAssertMakeSuccinctSignedInteger([ 1, 0, 0, 0] as W, [ 1 ] as W, false) @@ -148,72 +59,6 @@ final class NBKTestsOnLimbs: XCTestCase { // MARK: * NBK x Limbs x Assertions //*============================================================================* -private func NBKAssertLimbs( -_ lhs: [A], _ rhs: [B], isSigned: Bool? = nil, -file: StaticString = #file, line: UInt = #line) { - //=------------------------------------------= - typealias X = Array - typealias Y = ContiguousArray - typealias T = NBK.MajorOrMinorLimbsSequence - //=------------------------------------------= - let lhsUnsigned = lhs.map(A.Magnitude.init(bitPattern:)) - let rhsUnsigned = rhs.map(B.Magnitude.init(bitPattern:)) - //=------------------------------------------= - if isSigned == nil || isSigned == true { - XCTAssertEqual(X(T(X(lhs), isSigned: true )), X(rhs), file: file, line: line) - XCTAssertEqual(X(T(X(lhsUnsigned), isSigned: true )), X(rhsUnsigned), file: file, line: line) - XCTAssertEqual(Y(T(Y(lhs), isSigned: true )), Y(rhs), file: file, line: line) - XCTAssertEqual(Y(T(Y(lhsUnsigned), isSigned: true )), Y(rhsUnsigned), file: file, line: line) - - XCTAssertEqual(X(T(X(rhs), isSigned: true )), X(lhs), file: file, line: line) - XCTAssertEqual(X(T(X(rhsUnsigned), isSigned: true )), X(lhsUnsigned), file: file, line: line) - XCTAssertEqual(Y(T(Y(rhs), isSigned: true )), Y(lhs), file: file, line: line) - XCTAssertEqual(Y(T(Y(rhsUnsigned), isSigned: true )), Y(lhsUnsigned), file: file, line: line) - } - - if isSigned == nil || isSigned == false { - XCTAssertEqual(X(T(X(lhs), isSigned: false)), X(rhs), file: file, line: line) - XCTAssertEqual(X(T(X(lhsUnsigned), isSigned: false)), X(rhsUnsigned), file: file, line: line) - XCTAssertEqual(Y(T(Y(lhs), isSigned: false)), Y(rhs), file: file, line: line) - XCTAssertEqual(Y(T(Y(lhsUnsigned), isSigned: false)), Y(rhsUnsigned), file: file, line: line) - - XCTAssertEqual(X(T(X(rhs), isSigned: false)), X(lhs), file: file, line: line) - XCTAssertEqual(X(T(X(rhsUnsigned), isSigned: false)), X(lhsUnsigned), file: file, line: line) - XCTAssertEqual(Y(T(Y(rhs), isSigned: false)), Y(lhs), file: file, line: line) - XCTAssertEqual(Y(T(Y(rhsUnsigned), isSigned: false)), Y(lhsUnsigned), file: file, line: line) - } -} - -private func NBKAssertLimbsSubsequence( -_ lhs: [A], _ rhs: [B], isSigned: Bool? = nil, -file: StaticString = #file, line: UInt = #line) { - //=------------------------------------------= - typealias X = Array - typealias Y = ContiguousArray - typealias T = NBK.MajorOrMinorLimbsSequence - //=------------------------------------------= - let lhsUnsigned = lhs.map(A.Magnitude.init(bitPattern:)) - let rhsUnsigned = rhs.map(B.Magnitude.init(bitPattern:)) - //=------------------------------------------= - if isSigned == nil || isSigned == true { - XCTAssertEqual(X(T(X(lhs), isSigned: true )), X(rhs), file: file, line: line) - XCTAssertEqual(X(T(X(lhsUnsigned), isSigned: true )), X(rhsUnsigned), file: file, line: line) - XCTAssertEqual(Y(T(Y(lhs), isSigned: true )), Y(rhs), file: file, line: line) - XCTAssertEqual(Y(T(Y(lhsUnsigned), isSigned: true )), Y(rhsUnsigned), file: file, line: line) - } - - if isSigned == nil || isSigned == false { - XCTAssertEqual(X(T(X(lhs), isSigned: false)), X(rhs), file: file, line: line) - XCTAssertEqual(X(T(X(lhsUnsigned), isSigned: false)), X(rhsUnsigned), file: file, line: line) - XCTAssertEqual(Y(T(Y(lhs), isSigned: false)), Y(rhs), file: file, line: line) - XCTAssertEqual(Y(T(Y(lhsUnsigned), isSigned: false)), Y(rhsUnsigned), file: file, line: line) - } -} - -//=----------------------------------------------------------------------------= -// MARK: + Succinct -//=----------------------------------------------------------------------------= - private func NBKAssertMakeSuccinctSignedInteger( _ source: [UInt], _ body: [UInt], _ sign: Bool, file: StaticString = #file, line: UInt = #line) { From 14cdb8ea2aed796e633106c9a6a96c456d34ba2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Thu, 31 Aug 2023 12:02:14 +0200 Subject: [PATCH 082/111] [NBKCoreKit] Cleanup (#73). --- README.md | 8 +- ...mbs.swift => NBKMajorOrMinorInteger.swift} | 59 ++++-- .../Documentation.docc/Documentation.md | 16 +- ...mbs.swift => NBKMajorOrMinorInteger.swift} | 6 +- .../Private/NBK+Limbs+Comparisons.swift | 2 +- ...K+Limbs.swift => NBK+Limbs+Succinct.swift} | 4 +- .../Models/NBKMajorOrMinorInteger.swift | 177 ++++++++++++++++++ .../Models/NBKMajorOrMinorIntegerLimbs.swift | 157 ---------------- .../Private/NBK+Limbs+Comparisons.swift | 2 +- ...K+Limbs.swift => NBK+Limbs+Succinct.swift} | 4 +- 10 files changed, 238 insertions(+), 197 deletions(-) rename Sources/NBKCoreKit/Models/{NBKMajorOrMinorIntegerLimbs.swift => NBKMajorOrMinorInteger.swift} (88%) rename Tests/NBKCoreKitBenchmarks/Models/{NBKMajorOrMinorIntegerLimbs.swift => NBKMajorOrMinorInteger.swift} (91%) rename Tests/NBKCoreKitBenchmarks/Private/{NBK+Limbs.swift => NBK+Limbs+Succinct.swift} (96%) create mode 100644 Tests/NBKCoreKitTests/Models/NBKMajorOrMinorInteger.swift delete mode 100644 Tests/NBKCoreKitTests/Models/NBKMajorOrMinorIntegerLimbs.swift rename Tests/NBKCoreKitTests/Private/{NBK+Limbs.swift => NBK+Limbs+Succinct.swift} (97%) diff --git a/README.md b/README.md index 6a9cc1f1..1de25c2e 100644 --- a/README.md +++ b/README.md @@ -22,10 +22,10 @@ A new protocol hierarchy that refines Swift's standard library. ### Models - [NBKEndianness](Sources/NBKCoreKit/Models/NBKEndianness.swift) -- [NBKMajorIntegerLimbs](Sources/NBKCoreKit/Models/NBKMajorOrMinorIntegerLimbs.swift) -- [NBKMajorOrMinorIntegerLimbs](Sources/NBKCoreKit/Models/NBKMajorOrMinorIntegerLimbs.swift) -- [NBKMinorIntegerLimbs](Sources/NBKCoreKit/Models/NBKMajorOrMinorIntegerLimbs.swift) -- [NBKMinorIntegerLimbsOfOne](Sources/NBKCoreKit/Models/NBKMajorOrMinorIntegerLimbs.swift) +- [NBKMajorInteger](Sources/NBKCoreKit/Models/NBKMajorOrMinorInteger.swift) +- [NBKMajorOrMinorInteger](Sources/NBKCoreKit/Models/NBKMajorOrMinorInteger.swift) +- [NBKMinorInteger](Sources/NBKCoreKit/Models/NBKMajorOrMinorInteger.swift) +- [NBKMinorIntegerOfOne](Sources/NBKCoreKit/Models/NBKMajorOrMinorInteger.swift) - [NBKTwinHeaded](Sources/NBKCoreKit/Models/NBKTwinHeaded.swift) ## [NBKDoubleWidthKit][DBL/D] ([Sources][DBL/S], [Tests][DBL/T], [Benchmarks][DBL/B]) diff --git a/Sources/NBKCoreKit/Models/NBKMajorOrMinorIntegerLimbs.swift b/Sources/NBKCoreKit/Models/NBKMajorOrMinorInteger.swift similarity index 88% rename from Sources/NBKCoreKit/Models/NBKMajorOrMinorIntegerLimbs.swift rename to Sources/NBKCoreKit/Models/NBKMajorOrMinorInteger.swift index dd878b0b..17a37008 100644 --- a/Sources/NBKCoreKit/Models/NBKMajorOrMinorIntegerLimbs.swift +++ b/Sources/NBKCoreKit/Models/NBKMajorOrMinorInteger.swift @@ -8,25 +8,25 @@ //=----------------------------------------------------------------------------= //*============================================================================* -// MARK: * NBK x Major Or Minor Integer Limbs +// MARK: * NBK x Major Or Minor Integer //*============================================================================* -/// A sequence that merges or splits another sequence of un/signed integer limbs. +/// A sequence that merges or splits components of an un/signed integer sequence. /// /// ### Binary Integer Order /// -/// This sequence is binary integer ordered, so it merges or splits limbs -/// from least significant to most. You can reorder it by reversing the input, -/// the output, or both. +/// This sequence is ordered like a binary integer, meaning it merges and splits +/// its components from least significant to most. You can reorder it by reversing +/// the input, the output, or both. /// -@frozen public struct NBKMajorOrMinorIntegerLimbs: Sequence where +@frozen public struct NBKMajorOrMinorInteger: Sequence where Limb: NBKCoreInteger, Source: Sequence, Source.Element: NBKCoreInteger { public typealias Source = Source - public typealias MajorLimbs = NBKMajorIntegerLimbs + public typealias MajorLimbs = NBKMajorInteger - public typealias MinorLimbs = NBKMinorIntegerLimbs + public typealias MinorLimbs = NBKMinorInteger //=------------------------------------------------------------------------= // MARK: State @@ -111,11 +111,18 @@ Limb: NBKCoreInteger, Source: Sequence, Source.Element: NBKCoreInteger { } //*============================================================================* -// MARK: * NBK x Major Integer Limbs +// MARK: * NBK x Major Integer //*============================================================================* -// TODO: documentation -@frozen public struct NBKMajorIntegerLimbs: Sequence where +/// A sequence that merges components of an un/signed integer sequence. +/// +/// ### Binary Integer Order +/// +/// This sequence is ordered like a binary integer, meaning it merges and splits +/// its components from least significant to most. You can reorder it by reversing +/// the input, the output, or both. +/// +@frozen public struct NBKMajorInteger: Sequence where MajorLimb: NBKCoreInteger, MinorLimbs: Sequence, MinorLimbs.Element: NBKCoreInteger { public typealias MajorLimb = MajorLimb @@ -207,18 +214,25 @@ MajorLimb: NBKCoreInteger, MinorLimbs: Sequence, MinorLimbs.Element: NBKCoreInte } //*============================================================================* -// MARK: * NBK x Minor Integer Limbs +// MARK: * NBK x Minor Integer //*============================================================================* -// TODO: documentation -@frozen public struct NBKMinorIntegerLimbs: Sequence where +/// A sequence that splits components of an un/signed integer sequence. +/// +/// ### Binary Integer Order +/// +/// This sequence is ordered like a binary integer, meaning it merges and splits +/// its components from least significant to most. You can reorder it by reversing +/// the input, the output, or both. +/// +@frozen public struct NBKMinorInteger: Sequence where MinorLimb: NBKCoreInteger, MajorLimbs: Sequence, MajorLimbs.Element: NBKCoreInteger { public typealias MajorLimb = MajorLimbs.Element public typealias MinorLimb = MinorLimb - @usableFromInline typealias MinorLimbsOfOne = NBKMinorIntegerLimbsOfOne + @usableFromInline typealias MinorLimbsOfOne = NBKMinorIntegerOfOne //=------------------------------------------------------------------------= // MARK: State @@ -286,7 +300,7 @@ MinorLimb: NBKCoreInteger, MajorLimbs: Sequence, MajorLimbs.Element: NBKCoreInte if let minorLimb = self.minorLimbs?.next() { return minorLimb } else if let majorLimb = self.majorLimbs.next() { - self.minorLimbs = MinorLimbsOfOne.Iterator(majorLimb) + self.minorLimbs = MinorLimbsOfOne(majorLimb).makeIterator() } else { return nil } @@ -297,11 +311,18 @@ MinorLimb: NBKCoreInteger, MajorLimbs: Sequence, MajorLimbs.Element: NBKCoreInte } //*============================================================================* -// MARK: * NBK x Minor Integer Limbs Of One +// MARK: * NBK x Minor Integer Of One //*============================================================================* -// TODO: documentation -@frozen public struct NBKMinorIntegerLimbsOfOne: +/// A sequence that splits components of an un/signed integer sequence. +/// +/// ### Binary Integer Order +/// +/// This sequence is ordered like a binary integer, meaning it merges and splits +/// its components from least significant to most. You can reorder it by reversing +/// the input, the output, or both. +/// +@frozen public struct NBKMinorIntegerOfOne: Sequence where MinorLimb: NBKCoreInteger, MajorLimb: NBKCoreInteger { public typealias MajorLimb = MajorLimb diff --git a/Sources/Numberick/Documentation.docc/Documentation.md b/Sources/Numberick/Documentation.docc/Documentation.md index 330452ad..3b3e5d08 100644 --- a/Sources/Numberick/Documentation.docc/Documentation.md +++ b/Sources/Numberick/Documentation.docc/Documentation.md @@ -18,10 +18,10 @@ A new protocol hierarchy that refines Swift's standard library. ### Models - ``NBKEndianness`` -- ``NBKMajorIntegerLimbs`` -- ``NBKMajorOrMinorIntegerLimbs`` -- ``NBKMinorIntegerLimbs`` -- ``NBKMinorIntegerLimbsOfOne`` +- ``NBKMajorInteger`` +- ``NBKMajorOrMinorInteger`` +- ``NBKMinorInteger`` +- ``NBKMinorIntegerOfOne`` - ``NBKTwinHeaded`` ## NBKDoubleWidthKit @@ -115,10 +115,10 @@ Int256(5) % Int(5), UInt256(5) % UInt(5) - ``NBKDoubleWidth`` - ``NBKEndianness`` -- ``NBKMajorIntegerLimbs`` -- ``NBKMajorOrMinorIntegerLimbs`` -- ``NBKMinorIntegerLimbs`` -- ``NBKMinorIntegerLimbsOfOne`` +- ``NBKMajorInteger`` +- ``NBKMajorOrMinorInteger`` +- ``NBKMinorInteger`` +- ``NBKMinorIntegerOfOne`` - ``NBKTwinHeaded`` ### Integers diff --git a/Tests/NBKCoreKitBenchmarks/Models/NBKMajorOrMinorIntegerLimbs.swift b/Tests/NBKCoreKitBenchmarks/Models/NBKMajorOrMinorInteger.swift similarity index 91% rename from Tests/NBKCoreKitBenchmarks/Models/NBKMajorOrMinorIntegerLimbs.swift rename to Tests/NBKCoreKitBenchmarks/Models/NBKMajorOrMinorInteger.swift index 9e01550d..3b09c4f3 100644 --- a/Tests/NBKCoreKitBenchmarks/Models/NBKMajorOrMinorIntegerLimbs.swift +++ b/Tests/NBKCoreKitBenchmarks/Models/NBKMajorOrMinorInteger.swift @@ -17,12 +17,12 @@ private typealias X = [UInt64] private typealias Y = [UInt32] //*============================================================================* -// MARK: * NBK x Major Or Minor Integer Limbs +// MARK: * NBK x Major Or Minor Integer //*============================================================================* -final class NBKMajorOrMinorIntegerLimbsBenchmarks: XCTestCase { +final class NBKMajorOrMinorIntegerBenchmarks: XCTestCase { - typealias T = NBKMajorOrMinorIntegerLimbs + typealias T = NBKMajorOrMinorInteger //=------------------------------------------------------------------------= // MARK: Tests diff --git a/Tests/NBKCoreKitBenchmarks/Private/NBK+Limbs+Comparisons.swift b/Tests/NBKCoreKitBenchmarks/Private/NBK+Limbs+Comparisons.swift index 0410aaa2..091ad02c 100644 --- a/Tests/NBKCoreKitBenchmarks/Private/NBK+Limbs+Comparisons.swift +++ b/Tests/NBKCoreKitBenchmarks/Private/NBK+Limbs+Comparisons.swift @@ -23,7 +23,7 @@ private typealias Y = [UInt32] final class NBKBenchmarksOnLimbsByComparisons: XCTestCase { //=------------------------------------------------------------------------= - // MARK: Tests x Binary Integer Limbs + // MARK: Tests //=------------------------------------------------------------------------= func testCompareStrictSignedInteger() { diff --git a/Tests/NBKCoreKitBenchmarks/Private/NBK+Limbs.swift b/Tests/NBKCoreKitBenchmarks/Private/NBK+Limbs+Succinct.swift similarity index 96% rename from Tests/NBKCoreKitBenchmarks/Private/NBK+Limbs.swift rename to Tests/NBKCoreKitBenchmarks/Private/NBK+Limbs+Succinct.swift index b047c0c9..97e0712b 100644 --- a/Tests/NBKCoreKitBenchmarks/Private/NBK+Limbs.swift +++ b/Tests/NBKCoreKitBenchmarks/Private/NBK+Limbs+Succinct.swift @@ -17,10 +17,10 @@ private typealias X = [UInt64] private typealias Y = [UInt32] //*============================================================================* -// MARK: * NBK x Limbs +// MARK: * NBK x Limbs x Succinct //*============================================================================* -final class NBKBenchmarksOnLimbs: XCTestCase { +final class NBKBenchmarksOnLimbsBySuccinct: XCTestCase { //=------------------------------------------------------------------------= // MARK: Tests diff --git a/Tests/NBKCoreKitTests/Models/NBKMajorOrMinorInteger.swift b/Tests/NBKCoreKitTests/Models/NBKMajorOrMinorInteger.swift new file mode 100644 index 00000000..05e19fe5 --- /dev/null +++ b/Tests/NBKCoreKitTests/Models/NBKMajorOrMinorInteger.swift @@ -0,0 +1,177 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Major Or Minor Integer +//*============================================================================* + +final class NBKMajorOrMinorIntegerTests: XCTestCase { + + private typealias S64 = [Int64] + private typealias S32 = [Int32] + + private typealias T = NBKMajorOrMinorInteger + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testUInt32AsUInt32() { + NBKAssertMajorOrMinorInteger([ ] as S32, [ ] as S32) + NBKAssertMajorOrMinorInteger([ 1 ] as S32, [ 1 ] as S32) + NBKAssertMajorOrMinorInteger([ 1, 2 ] as S32, [ 1, 2 ] as S32) + NBKAssertMajorOrMinorInteger([ 1, 2, 3 ] as S32, [ 1, 2, 3 ] as S32) + NBKAssertMajorOrMinorInteger([ 1, 2, 3, 4] as S32, [ 1, 2, 3, 4] as S32) + + NBKAssertMajorOrMinorInteger([ ] as S32, [ ] as S32) + NBKAssertMajorOrMinorInteger([~1 ] as S32, [~1 ] as S32) + NBKAssertMajorOrMinorInteger([~1, ~2 ] as S32, [~1, ~2 ] as S32) + NBKAssertMajorOrMinorInteger([~1, ~2, ~3 ] as S32, [~1, ~2, ~3 ] as S32) + NBKAssertMajorOrMinorInteger([~1, ~2, ~3, ~4] as S32, [~1, ~2, ~3, ~4] as S32) + } + + func testUInt32AsUInt64() { + NBKAssertMajorOrMinorInteger([ ] as S32, [ ] as S64) + NBKAssertMajorOrMinorInteger([ 1, 0 ] as S32, [ 1 ] as S64) + NBKAssertMajorOrMinorInteger([ 1, 0, 2, 0 ] as S32, [ 1, 2 ] as S64) + NBKAssertMajorOrMinorInteger([ 1, 0, 2, 0, 3, 0 ] as S32, [ 1, 2, 3 ] as S64) + NBKAssertMajorOrMinorInteger([ 1, 0, 2, 0, 3, 0, 4, 0] as S32, [ 1, 2, 3, 4] as S64) + + NBKAssertMajorOrMinorInteger([ ] as S32, [ ] as S64) + NBKAssertMajorOrMinorInteger([~1, ~0 ] as S32, [~1 ] as S64) + NBKAssertMajorOrMinorInteger([~1, ~0, ~2, ~0 ] as S32, [~1, ~2 ] as S64) + NBKAssertMajorOrMinorInteger([~1, ~0, ~2, ~0, ~3, ~0 ] as S32, [~1, ~2, ~3 ] as S64) + NBKAssertMajorOrMinorInteger([~1, ~0, ~2, ~0, ~3, ~0, ~4, ~0] as S32, [~1, ~2, ~3, ~4] as S64) + } + + func testUInt64AsUInt64() { + NBKAssertMajorOrMinorInteger([ ] as S64, [ ] as S64) + NBKAssertMajorOrMinorInteger([ 1 ] as S64, [ 1 ] as S64) + NBKAssertMajorOrMinorInteger([ 1, 2 ] as S64, [ 1, 2 ] as S64) + NBKAssertMajorOrMinorInteger([ 1, 2, 3 ] as S64, [ 1, 2, 3 ] as S64) + NBKAssertMajorOrMinorInteger([ 1, 2, 3, 4] as S64, [ 1, 2, 3, 4] as S64) + + NBKAssertMajorOrMinorInteger([ ] as S64, [ ] as S64) + NBKAssertMajorOrMinorInteger([~1 ] as S64, [~1 ] as S64) + NBKAssertMajorOrMinorInteger([~1, ~2 ] as S64, [~1, ~2 ] as S64) + NBKAssertMajorOrMinorInteger([~1, ~2, ~3 ] as S64, [~1, ~2, ~3 ] as S64) + NBKAssertMajorOrMinorInteger([~1, ~2, ~3, ~4] as S64, [~1, ~2, ~3, ~4] as S64) + } + + func testUInt64AsUInt32() { + NBKAssertMajorOrMinorInteger([ ] as S64, [ ] as S32) + NBKAssertMajorOrMinorInteger([ 1 ] as S64, [ 1, 0 ] as S32) + NBKAssertMajorOrMinorInteger([ 1, 2 ] as S64, [ 1, 0, 2, 0 ] as S32) + NBKAssertMajorOrMinorInteger([ 1, 2, 3 ] as S64, [ 1, 0, 2, 0, 3, 0 ] as S32) + NBKAssertMajorOrMinorInteger([ 1, 2, 3, 4] as S64, [ 1, 0, 2, 0, 3, 0, 4, 0] as S32) + + NBKAssertMajorOrMinorInteger([ ] as S64, [ ] as S32) + NBKAssertMajorOrMinorInteger([~1 ] as S64, [~1, ~0 ] as S32) + NBKAssertMajorOrMinorInteger([~1, ~2 ] as S64, [~1, ~0, ~2, ~0 ] as S32) + NBKAssertMajorOrMinorInteger([~1, ~2, ~3 ] as S64, [~1, ~0, ~2, ~0, ~3, ~0 ] as S32) + NBKAssertMajorOrMinorInteger([~1, ~2, ~3, ~4] as S64, [~1, ~0, ~2, ~0, ~3, ~0, ~4, ~0] as S32) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Signed or Unsigned + //=------------------------------------------------------------------------= + + func testMajorLimbsFromIncompleteMinorLimbs() { + NBKAssertMajorOrMinorIntegerOneWay([ ] as S32, [ ] as S64, isSigned: true ) + NBKAssertMajorOrMinorIntegerOneWay([ 1 ] as S32, [ 1 ] as S64, isSigned: true ) + NBKAssertMajorOrMinorIntegerOneWay([ 1, 0, 2 ] as S32, [ 1, 2 ] as S64, isSigned: true ) + NBKAssertMajorOrMinorIntegerOneWay([ 1, 0, 2, 0, 3 ] as S32, [ 1, 2, 3 ] as S64, isSigned: true ) + NBKAssertMajorOrMinorIntegerOneWay([ 1, 0, 2, 0, 3, 0, 4] as S32, [ 1, 2, 3, 4 ] as S64, isSigned: true ) + + NBKAssertMajorOrMinorIntegerOneWay([ ] as S32, [ ] as S64, isSigned: true ) + NBKAssertMajorOrMinorIntegerOneWay([~1 ] as S32, [~1 ] as S64, isSigned: true ) + NBKAssertMajorOrMinorIntegerOneWay([~1, ~0, ~2 ] as S32, [~1, ~2 ] as S64, isSigned: true ) + NBKAssertMajorOrMinorIntegerOneWay([~1, ~0, ~2, ~0, ~3 ] as S32, [~1, ~2, ~3 ] as S64, isSigned: true ) + NBKAssertMajorOrMinorIntegerOneWay([~1, ~0, ~2, ~0, ~3, ~0, ~4] as S32, [~1, ~2, ~3, ~4 ] as S64, isSigned: true ) + + NBKAssertMajorOrMinorIntegerOneWay([ ] as S32, [ ] as S64, isSigned: false) + NBKAssertMajorOrMinorIntegerOneWay([ 1 ] as S32, [ 1 ] as S64, isSigned: false) + NBKAssertMajorOrMinorIntegerOneWay([ 1, 0, 2 ] as S32, [ 1, 2 ] as S64, isSigned: false) + NBKAssertMajorOrMinorIntegerOneWay([ 1, 0, 2, 0, 3 ] as S32, [ 1, 2, 3 ] as S64, isSigned: false) + NBKAssertMajorOrMinorIntegerOneWay([ 1, 0, 2, 0, 3, 0, 4] as S32, [ 1, 2, 3, 4 ] as S64, isSigned: false) + + NBKAssertMajorOrMinorIntegerOneWay([ ] as S32, [ ] as S64, isSigned: false) + NBKAssertMajorOrMinorIntegerOneWay([~1 ] as S32, [ 0xfffffffe] as S64, isSigned: false) + NBKAssertMajorOrMinorIntegerOneWay([~1, ~0, ~2 ] as S32, [~1, 0xfffffffd] as S64, isSigned: false) + NBKAssertMajorOrMinorIntegerOneWay([~1, ~0, ~2, ~0, ~3 ] as S32, [~1, ~2, 0xfffffffc] as S64, isSigned: false) + NBKAssertMajorOrMinorIntegerOneWay([~1, ~0, ~2, ~0, ~3, ~0, ~4] as S32, [~1, ~2, ~3, 0xfffffffb] as S64, isSigned: false) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Miscellaneous + //=------------------------------------------------------------------------= + + func testMajorToMinorComposableReordering() { + XCTAssertEqual([1, 2, 3, 4], Array(T(([0x0201, 0x0403] as [Int16]), as: Int8.self))) + XCTAssertEqual([2, 1, 4, 3], Array(T(([0x0201, 0x0403] as [Int16]).reversed(), as: Int8.self)).reversed()) + XCTAssertEqual([3, 4, 1, 2], Array(T(([0x0201, 0x0403] as [Int16]).reversed(), as: Int8.self))) + XCTAssertEqual([4, 3, 2, 1], Array(T(([0x0201, 0x0403] as [Int16]), as: Int8.self)).reversed()) + } + + func testMinorToMajorComposableReordering() { + XCTAssertEqual([0x0201, 0x0403], Array(T(([1, 2, 3, 4] as [Int8]), as: Int16.self))) + XCTAssertEqual([0x0102, 0x0304], Array(T(([1, 2, 3, 4] as [Int8]).reversed(), as: Int16.self)).reversed()) + XCTAssertEqual([0x0403, 0x0201], Array(T(([1, 2, 3, 4] as [Int8]), as: Int16.self)).reversed()) + XCTAssertEqual([0x0304, 0x0102], Array(T(([1, 2, 3, 4] as [Int8]).reversed(), as: Int16.self))) + } +} + +//*============================================================================* +// MARK: * NBK x Major Or Minor Integer x Assertions +//*============================================================================* + +private func NBKAssertMajorOrMinorInteger( +_ lhs: [A], _ rhs: [B], isSigned: Bool? = nil, +file: StaticString = #file, line: UInt = #line) { + + NBKAssertMajorOrMinorIntegerOneWay(lhs, rhs, isSigned: isSigned) + NBKAssertMajorOrMinorIntegerOneWay(rhs, lhs, isSigned: isSigned) +} + +private func NBKAssertMajorOrMinorIntegerOneWay( +_ lhs: [A], _ rhs: [B], isSigned: Bool? = nil, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + typealias X = Array + typealias Y = ContiguousArray + typealias T = NBKMajorOrMinorInteger + //=------------------------------------------= + let lhsUnsigned = lhs.map(A.Magnitude.init(bitPattern:)) + let rhsUnsigned = rhs.map(B.Magnitude.init(bitPattern:)) + //=------------------------------------------= + if isSigned == nil || isSigned == true { + XCTAssertEqual(X(T(X(lhs), isSigned: true )), X(rhs), file: file, line: line) + XCTAssertEqual(X(T(X(lhsUnsigned), isSigned: true )), X(rhsUnsigned), file: file, line: line) + XCTAssertEqual(Y(T(Y(lhs), isSigned: true )), Y(rhs), file: file, line: line) + XCTAssertEqual(Y(T(Y(lhsUnsigned), isSigned: true )), Y(rhsUnsigned), file: file, line: line) + } + + if isSigned == nil || isSigned == false { + XCTAssertEqual(X(T(X(lhs), isSigned: false)), X(rhs), file: file, line: line) + XCTAssertEqual(X(T(X(lhsUnsigned), isSigned: false)), X(rhsUnsigned), file: file, line: line) + XCTAssertEqual(Y(T(Y(lhs), isSigned: false)), Y(rhs), file: file, line: line) + XCTAssertEqual(Y(T(Y(lhsUnsigned), isSigned: false)), Y(rhsUnsigned), file: file, line: line) + } +} + +#endif diff --git a/Tests/NBKCoreKitTests/Models/NBKMajorOrMinorIntegerLimbs.swift b/Tests/NBKCoreKitTests/Models/NBKMajorOrMinorIntegerLimbs.swift deleted file mode 100644 index ecea72e9..00000000 --- a/Tests/NBKCoreKitTests/Models/NBKMajorOrMinorIntegerLimbs.swift +++ /dev/null @@ -1,157 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if DEBUG - -import NBKCoreKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Major Or Minor Integer Limbs -//*============================================================================* - -final class NBKMajorOrMinorIntegerLimbsTests: XCTestCase { - - private typealias S64 = [Int64] - private typealias S32 = [Int32] - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testUInt32AsUInt32() { - NBKAssertMajorOrMinorIntegerLimbs([ ] as S32, [ ] as S32) - NBKAssertMajorOrMinorIntegerLimbs([ 1 ] as S32, [ 1 ] as S32) - NBKAssertMajorOrMinorIntegerLimbs([ 1, 2 ] as S32, [ 1, 2 ] as S32) - NBKAssertMajorOrMinorIntegerLimbs([ 1, 2, 3 ] as S32, [ 1, 2, 3 ] as S32) - NBKAssertMajorOrMinorIntegerLimbs([ 1, 2, 3, 4] as S32, [ 1, 2, 3, 4] as S32) - - NBKAssertMajorOrMinorIntegerLimbs([ ] as S32, [ ] as S32) - NBKAssertMajorOrMinorIntegerLimbs([~1 ] as S32, [~1 ] as S32) - NBKAssertMajorOrMinorIntegerLimbs([~1, ~2 ] as S32, [~1, ~2 ] as S32) - NBKAssertMajorOrMinorIntegerLimbs([~1, ~2, ~3 ] as S32, [~1, ~2, ~3 ] as S32) - NBKAssertMajorOrMinorIntegerLimbs([~1, ~2, ~3, ~4] as S32, [~1, ~2, ~3, ~4] as S32) - } - - func testUInt32AsUInt64() { - NBKAssertMajorOrMinorIntegerLimbs([ ] as S32, [ ] as S64) - NBKAssertMajorOrMinorIntegerLimbs([ 1, 0 ] as S32, [ 1 ] as S64) - NBKAssertMajorOrMinorIntegerLimbs([ 1, 0, 2, 0 ] as S32, [ 1, 2 ] as S64) - NBKAssertMajorOrMinorIntegerLimbs([ 1, 0, 2, 0, 3, 0 ] as S32, [ 1, 2, 3 ] as S64) - NBKAssertMajorOrMinorIntegerLimbs([ 1, 0, 2, 0, 3, 0, 4, 0] as S32, [ 1, 2, 3, 4] as S64) - - NBKAssertMajorOrMinorIntegerLimbs([ ] as S32, [ ] as S64) - NBKAssertMajorOrMinorIntegerLimbs([~1, ~0 ] as S32, [~1 ] as S64) - NBKAssertMajorOrMinorIntegerLimbs([~1, ~0, ~2, ~0 ] as S32, [~1, ~2 ] as S64) - NBKAssertMajorOrMinorIntegerLimbs([~1, ~0, ~2, ~0, ~3, ~0 ] as S32, [~1, ~2, ~3 ] as S64) - NBKAssertMajorOrMinorIntegerLimbs([~1, ~0, ~2, ~0, ~3, ~0, ~4, ~0] as S32, [~1, ~2, ~3, ~4] as S64) - } - - func testUInt64AsUInt64() { - NBKAssertMajorOrMinorIntegerLimbs([ ] as S64, [ ] as S64) - NBKAssertMajorOrMinorIntegerLimbs([ 1 ] as S64, [ 1 ] as S64) - NBKAssertMajorOrMinorIntegerLimbs([ 1, 2 ] as S64, [ 1, 2 ] as S64) - NBKAssertMajorOrMinorIntegerLimbs([ 1, 2, 3 ] as S64, [ 1, 2, 3 ] as S64) - NBKAssertMajorOrMinorIntegerLimbs([ 1, 2, 3, 4] as S64, [ 1, 2, 3, 4] as S64) - - NBKAssertMajorOrMinorIntegerLimbs([ ] as S64, [ ] as S64) - NBKAssertMajorOrMinorIntegerLimbs([~1 ] as S64, [~1 ] as S64) - NBKAssertMajorOrMinorIntegerLimbs([~1, ~2 ] as S64, [~1, ~2 ] as S64) - NBKAssertMajorOrMinorIntegerLimbs([~1, ~2, ~3 ] as S64, [~1, ~2, ~3 ] as S64) - NBKAssertMajorOrMinorIntegerLimbs([~1, ~2, ~3, ~4] as S64, [~1, ~2, ~3, ~4] as S64) - } - - func testUInt64AsUInt32() { - NBKAssertMajorOrMinorIntegerLimbs([ ] as S64, [ ] as S32) - NBKAssertMajorOrMinorIntegerLimbs([ 1 ] as S64, [ 1, 0 ] as S32) - NBKAssertMajorOrMinorIntegerLimbs([ 1, 2 ] as S64, [ 1, 0, 2, 0 ] as S32) - NBKAssertMajorOrMinorIntegerLimbs([ 1, 2, 3 ] as S64, [ 1, 0, 2, 0, 3, 0 ] as S32) - NBKAssertMajorOrMinorIntegerLimbs([ 1, 2, 3, 4] as S64, [ 1, 0, 2, 0, 3, 0, 4, 0] as S32) - - NBKAssertMajorOrMinorIntegerLimbs([ ] as S64, [ ] as S32) - NBKAssertMajorOrMinorIntegerLimbs([~1 ] as S64, [~1, ~0 ] as S32) - NBKAssertMajorOrMinorIntegerLimbs([~1, ~2 ] as S64, [~1, ~0, ~2, ~0 ] as S32) - NBKAssertMajorOrMinorIntegerLimbs([~1, ~2, ~3 ] as S64, [~1, ~0, ~2, ~0, ~3, ~0 ] as S32) - NBKAssertMajorOrMinorIntegerLimbs([~1, ~2, ~3, ~4] as S64, [~1, ~0, ~2, ~0, ~3, ~0, ~4, ~0] as S32) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Signed or Unsigned - //=------------------------------------------------------------------------= - - func testMajorLimbsFromIncompleteMinorLimbs() { - NBKAssertMajorOrMinorIntegerLimbsOneWay([ ] as S32, [ ] as S64, isSigned: true ) - NBKAssertMajorOrMinorIntegerLimbsOneWay([ 1 ] as S32, [ 1 ] as S64, isSigned: true ) - NBKAssertMajorOrMinorIntegerLimbsOneWay([ 1, 0, 2 ] as S32, [ 1, 2 ] as S64, isSigned: true ) - NBKAssertMajorOrMinorIntegerLimbsOneWay([ 1, 0, 2, 0, 3 ] as S32, [ 1, 2, 3 ] as S64, isSigned: true ) - NBKAssertMajorOrMinorIntegerLimbsOneWay([ 1, 0, 2, 0, 3, 0, 4] as S32, [ 1, 2, 3, 4 ] as S64, isSigned: true ) - - NBKAssertMajorOrMinorIntegerLimbsOneWay([ ] as S32, [ ] as S64, isSigned: true ) - NBKAssertMajorOrMinorIntegerLimbsOneWay([~1 ] as S32, [~1 ] as S64, isSigned: true ) - NBKAssertMajorOrMinorIntegerLimbsOneWay([~1, ~0, ~2 ] as S32, [~1, ~2 ] as S64, isSigned: true ) - NBKAssertMajorOrMinorIntegerLimbsOneWay([~1, ~0, ~2, ~0, ~3 ] as S32, [~1, ~2, ~3 ] as S64, isSigned: true ) - NBKAssertMajorOrMinorIntegerLimbsOneWay([~1, ~0, ~2, ~0, ~3, ~0, ~4] as S32, [~1, ~2, ~3, ~4 ] as S64, isSigned: true ) - - NBKAssertMajorOrMinorIntegerLimbsOneWay([ ] as S32, [ ] as S64, isSigned: false) - NBKAssertMajorOrMinorIntegerLimbsOneWay([ 1 ] as S32, [ 1 ] as S64, isSigned: false) - NBKAssertMajorOrMinorIntegerLimbsOneWay([ 1, 0, 2 ] as S32, [ 1, 2 ] as S64, isSigned: false) - NBKAssertMajorOrMinorIntegerLimbsOneWay([ 1, 0, 2, 0, 3 ] as S32, [ 1, 2, 3 ] as S64, isSigned: false) - NBKAssertMajorOrMinorIntegerLimbsOneWay([ 1, 0, 2, 0, 3, 0, 4] as S32, [ 1, 2, 3, 4 ] as S64, isSigned: false) - - NBKAssertMajorOrMinorIntegerLimbsOneWay([ ] as S32, [ ] as S64, isSigned: false) - NBKAssertMajorOrMinorIntegerLimbsOneWay([~1 ] as S32, [ 0xfffffffe] as S64, isSigned: false) - NBKAssertMajorOrMinorIntegerLimbsOneWay([~1, ~0, ~2 ] as S32, [~1, 0xfffffffd] as S64, isSigned: false) - NBKAssertMajorOrMinorIntegerLimbsOneWay([~1, ~0, ~2, ~0, ~3 ] as S32, [~1, ~2, 0xfffffffc] as S64, isSigned: false) - NBKAssertMajorOrMinorIntegerLimbsOneWay([~1, ~0, ~2, ~0, ~3, ~0, ~4] as S32, [~1, ~2, ~3, 0xfffffffb] as S64, isSigned: false) - } -} - -//*============================================================================* -// MARK: * NBK x Major Or Minor Integer Limbs x Assertions -//*============================================================================* - -private func NBKAssertMajorOrMinorIntegerLimbs( -_ lhs: [A], _ rhs: [B], isSigned: Bool? = nil, -file: StaticString = #file, line: UInt = #line) { - - NBKAssertMajorOrMinorIntegerLimbsOneWay(lhs, rhs, isSigned: isSigned) - NBKAssertMajorOrMinorIntegerLimbsOneWay(rhs, lhs, isSigned: isSigned) -} - -private func NBKAssertMajorOrMinorIntegerLimbsOneWay( -_ lhs: [A], _ rhs: [B], isSigned: Bool? = nil, -file: StaticString = #file, line: UInt = #line) { - //=------------------------------------------= - typealias X = Array - typealias Y = ContiguousArray - typealias T = NBKMajorOrMinorIntegerLimbs - //=------------------------------------------= - let lhsUnsigned = lhs.map(A.Magnitude.init(bitPattern:)) - let rhsUnsigned = rhs.map(B.Magnitude.init(bitPattern:)) - //=------------------------------------------= - if isSigned == nil || isSigned == true { - XCTAssertEqual(X(T(X(lhs), isSigned: true )), X(rhs), file: file, line: line) - XCTAssertEqual(X(T(X(lhsUnsigned), isSigned: true )), X(rhsUnsigned), file: file, line: line) - XCTAssertEqual(Y(T(Y(lhs), isSigned: true )), Y(rhs), file: file, line: line) - XCTAssertEqual(Y(T(Y(lhsUnsigned), isSigned: true )), Y(rhsUnsigned), file: file, line: line) - } - - if isSigned == nil || isSigned == false { - XCTAssertEqual(X(T(X(lhs), isSigned: false)), X(rhs), file: file, line: line) - XCTAssertEqual(X(T(X(lhsUnsigned), isSigned: false)), X(rhsUnsigned), file: file, line: line) - XCTAssertEqual(Y(T(Y(lhs), isSigned: false)), Y(rhs), file: file, line: line) - XCTAssertEqual(Y(T(Y(lhsUnsigned), isSigned: false)), Y(rhsUnsigned), file: file, line: line) - } -} - -#endif diff --git a/Tests/NBKCoreKitTests/Private/NBK+Limbs+Comparisons.swift b/Tests/NBKCoreKitTests/Private/NBK+Limbs+Comparisons.swift index 17b61779..0512f3af 100644 --- a/Tests/NBKCoreKitTests/Private/NBK+Limbs+Comparisons.swift +++ b/Tests/NBKCoreKitTests/Private/NBK+Limbs+Comparisons.swift @@ -23,7 +23,7 @@ private typealias Y = [UInt32] final class NBKTestsOnLimbsByComparisons: XCTestCase { //=------------------------------------------------------------------------= - // MARK: Tests x Binary Integer Limbs + // MARK: Tests x Binary Integer //=------------------------------------------------------------------------= func testCompareStrictSignedInteger() { diff --git a/Tests/NBKCoreKitTests/Private/NBK+Limbs.swift b/Tests/NBKCoreKitTests/Private/NBK+Limbs+Succinct.swift similarity index 97% rename from Tests/NBKCoreKitTests/Private/NBK+Limbs.swift rename to Tests/NBKCoreKitTests/Private/NBK+Limbs+Succinct.swift index 8effa911..3971b439 100644 --- a/Tests/NBKCoreKitTests/Private/NBK+Limbs.swift +++ b/Tests/NBKCoreKitTests/Private/NBK+Limbs+Succinct.swift @@ -17,10 +17,10 @@ private typealias X = [UInt64] private typealias Y = [UInt32] //*============================================================================* -// MARK: * NBK x Limbs +// MARK: * NBK x Limbs x Succinct //*============================================================================* -final class NBKTestsOnLimbs: XCTestCase { +final class NBKTestsOnLimbsBySuccinct: XCTestCase { //=------------------------------------------------------------------------= // MARK: Tests From 6365fa1f01a063e7d3a1f44dc7682087e9b57835 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Fri, 1 Sep 2023 07:46:38 +0200 Subject: [PATCH 083/111] [NBKCoreKit] OffsetIndexed (#76). --- README.md | 1 + Sources/NBKCoreKit/Models/NBKTwinHeaded.swift | 153 +++++------------- Sources/NBKCoreKit/NBKOffsetIndexed.swift | 107 ++++++++++++ .../Documentation.docc/Documentation.md | 2 + Tests/NBKCoreKitTests/NBKOffsetIndexed.swift | 57 +++++++ 5 files changed, 210 insertions(+), 110 deletions(-) create mode 100644 Sources/NBKCoreKit/NBKOffsetIndexed.swift create mode 100644 Tests/NBKCoreKitTests/NBKOffsetIndexed.swift diff --git a/README.md b/README.md index 1de25c2e..506a968b 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ A new protocol hierarchy that refines Swift's standard library. - [NBKBitPatternConvertible](Sources/NBKCoreKit/NBKBitPatternConvertible.swift) - [NBKCoreInteger](Sources/NBKCoreKit/NBKCoreInteger.swift) - [NBKFixedWidthInteger](Sources/NBKCoreKit/NBKFixedWidthInteger.swift) +- [NBKOffsetIndexed](Sources/NBKCoreKit/NBKOffsetIndexed.swift) - [NBKSignedInteger](Sources/NBKCoreKit/NBKBinaryInteger.swift) - [NBKUnsignedInteger](Sources/NBKCoreKit/NBKBinaryInteger.swift) diff --git a/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift b/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift index bb9c5784..1ba84af1 100644 --- a/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift +++ b/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift @@ -12,7 +12,7 @@ //*============================================================================* /// A collection that iterates forwards or backwards in a dynamic but branchless way. -@frozen public struct NBKTwinHeaded: RandomAccessCollection where Base: RandomAccessCollection { +@frozen public struct NBKTwinHeaded: NBKOffsetIndexed where Base: RandomAccessCollection { public typealias Base = Base @@ -50,6 +50,26 @@ // MARK: Initializers //=------------------------------------------------------------------------= + /// Creates a view presenting the collection's elements in a dynamic order. + /// + /// - Parameters: + /// - base: The collection viewed through this instance. + /// - reversed: A value indicating whether the direction should be reversed. + /// + @inlinable public init(_ other: Self, reversed: Bool = false) { + self.init(other.base, reversed: other.isFrontToBack == reversed) + } + + /// Creates a view presenting the collection's elements in a dynamic order. + /// + /// - Parameters: + /// - base: The collection viewed through this instance. + /// - reversed: A value indicating whether the direction should be reversed. + /// + @inlinable public init(_ other: ReversedCollection, reversed: Bool = false) { + self.init(other.reversed(), reversed: !reversed) + } + /// Creates a view presenting the collection's elements in a dynamic order. /// /// - Parameters: @@ -96,6 +116,14 @@ self.isBackToFront ? self.base.reversed() : nil } + @inlinable public var count: Int { + self.base.count + } + + @inlinable public subscript(index: Int) -> Element { + _read { yield self.base[self.baseSubscriptIndex(index)] } + } + //=------------------------------------------------------------------------= // MARK: Transformations //=------------------------------------------------------------------------= @@ -172,37 +200,29 @@ } //=----------------------------------------------------------------------------= -// MARK: + Initializers +// MARK: + Mutable Collection //=----------------------------------------------------------------------------= -extension NBKTwinHeaded { +extension NBKTwinHeaded: MutableCollection where Base: MutableCollection { //=------------------------------------------------------------------------= - // MARK: Details x Flattened Conversions + // MARK: Accessors //=------------------------------------------------------------------------= - /// Creates a view presenting the collection's elements in a dynamic order. - /// - /// - Parameters: - /// - base: The collection viewed through this instance. - /// - reversed: A value indicating whether the direction should be reversed. - /// - @inlinable public init(_ other: Self, reversed: Bool = false) { - self.init(other.base, reversed: other.isFrontToBack == reversed) - } - - /// Creates a view presenting the collection's elements in a dynamic order. - /// - /// - Parameters: - /// - base: The collection viewed through this instance. - /// - reversed: A value indicating whether the direction should be reversed. - /// - @inlinable public init(_ other: ReversedCollection, reversed: Bool = false) { - self.init(other.reversed(), reversed: !reversed) + @inlinable public subscript(index: Int) -> Element { + _read { yield self.body[self.baseSubscriptIndex(index)] } + _modify { yield &self.body[self.baseSubscriptIndex(index)] } } +} + +//=----------------------------------------------------------------------------= +// MARK: + Sub Sequence +//=----------------------------------------------------------------------------= + +extension NBKTwinHeaded { //=------------------------------------------------------------------------= - // MARK: Details x Unsafe Buffer Pointers + // MARK: Initializers //=------------------------------------------------------------------------= /// Creates a collection with the same data and direction as the given subsequence. @@ -219,90 +239,3 @@ extension NBKTwinHeaded { self.init(base, reversed: subsequence.base.isBackToFront) } } - -//=----------------------------------------------------------------------------= -// MARK: + Collection -//=----------------------------------------------------------------------------= - -extension NBKTwinHeaded { - - //=------------------------------------------------------------------------= - // MARK: Accessors - //=------------------------------------------------------------------------= - - @inlinable public var count: Int { - self.base.count - } - - @inlinable public var startIndex: Int { - Int.zero - } - - @inlinable public var endIndex: Int { - self.count - } - - @inlinable public var indices: Range { - Range(uncheckedBounds:(self.startIndex, self.endIndex)) - } - - @inlinable public subscript(index: Int) -> Element { - _read { yield self.base[self.baseSubscriptIndex(index)] } - } - - //=------------------------------------------------------------------------= - // MARK: Utilities - //=------------------------------------------------------------------------= - - @inlinable public func distance(from start: Int, to end: Int) -> Int { - end - start - } - - @inlinable public func index(after index: Int) -> Int { - index + 1 - } - - @inlinable public func formIndex(after index: inout Int) { - index += 1 - } - - @inlinable public func index(before index: Int) -> Int { - index - 1 - } - - @inlinable public func formIndex(before index: inout Int) { - index -= 1 - } - - @inlinable public func index(_ index: Int, offsetBy distance: Int) -> Int { - index + distance - } - - // TODO: NBK.arrayIndex(_:offsetBy:limitedBy:) - @inlinable public func index(_ index: Int, offsetBy distance: Int, limitedBy limit: Int) -> Int? { - let distanceLimit: Int = self.distance(from: index, to: limit) - - guard distance >= 0 - ? distance <= distanceLimit || distanceLimit < 0 - : distance >= distanceLimit || distanceLimit > 0 - else { return nil } - - return self.index(index, offsetBy: distance) as Int - } -} - -//=----------------------------------------------------------------------------= -// MARK: + Mutable Collection -//=----------------------------------------------------------------------------= - -extension NBKTwinHeaded: MutableCollection where Base: MutableCollection { - - //=------------------------------------------------------------------------= - // MARK: Accessors - //=------------------------------------------------------------------------= - - @inlinable public subscript(index: Int) -> Element { - _read { yield self.body[self.baseSubscriptIndex(index)] } - _modify { yield &self.body[self.baseSubscriptIndex(index)] } - } -} diff --git a/Sources/NBKCoreKit/NBKOffsetIndexed.swift b/Sources/NBKCoreKit/NBKOffsetIndexed.swift new file mode 100644 index 00000000..d622cb21 --- /dev/null +++ b/Sources/NBKCoreKit/NBKOffsetIndexed.swift @@ -0,0 +1,107 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +//*============================================================================* +// MARK: * NBK x Offset Indexed +//*============================================================================* + +/// A random access collection with indices from `zero` to `count`. +/// +/// ### Defaults +/// +/// The defaults provided depend on an independent `count` accessor. +/// +public protocol NBKOffsetIndexed: RandomAccessCollection where Indices == Range { } + +//=----------------------------------------------------------------------------= +// MARK: + Details +//=----------------------------------------------------------------------------= + +extension NBKOffsetIndexed { + + //=------------------------------------------------------------------------= + // MARK: Accessors + //=------------------------------------------------------------------------= + + @inlinable public var startIndex: Int { + Int.zero + } + + @inlinable public var endIndex: Int { + self.count + } + + @inlinable public var indices: Range { + Range(uncheckedBounds:(Int.zero, self.count)) + } + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + @inlinable public func distance(from start: Int, to end: Int) -> Int { + end - start + } + + @inlinable public func index(after index: Int) -> Int { + index + 1 + } + + @inlinable public func formIndex(after index: inout Int) { + index += 1 + } + + @inlinable public func index(before index: Int) -> Int { + index - 1 + } + + @inlinable public func formIndex(before index: inout Int) { + index -= 1 + } + + @inlinable public func index(_ index: Int, offsetBy distance: Int) -> Int { + index + distance + } + + @inlinable public func index(_ index: Int, offsetBy distance: Int, limitedBy limit: Int) -> Int? { + NBK.offset(index, by: distance, limit: limit) + } +} + +//*============================================================================* +// MARK: * NBK x Offset Indexed x Algorithms +//*============================================================================* + +extension NBK { + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + /// Returns the array-like result of `index(_:offsetBy:limitedBy:)`. + @inlinable public static func offset(_ index: Int, by distance: Int, limit: Int) -> Int? { + let distanceLimit = limit - index + + guard distance >= Int.zero + ? distance <= distanceLimit || distanceLimit < Int.zero + : distance >= distanceLimit || distanceLimit > Int.zero + else { return nil } + + return index + distance as Int + } +} + +//*============================================================================* +// MARK: * NBK x Offset Indexed x Swift +//*============================================================================* + +extension Array: NBKOffsetIndexed { } +extension ContiguousArray: NBKOffsetIndexed { } +extension UnsafeBufferPointer: NBKOffsetIndexed { } +extension UnsafeMutableBufferPointer: NBKOffsetIndexed { } diff --git a/Sources/Numberick/Documentation.docc/Documentation.md b/Sources/Numberick/Documentation.docc/Documentation.md index 3b3e5d08..75fd94b8 100644 --- a/Sources/Numberick/Documentation.docc/Documentation.md +++ b/Sources/Numberick/Documentation.docc/Documentation.md @@ -12,6 +12,7 @@ A new protocol hierarchy that refines Swift's standard library. - ``NBKBitPatternConvertible`` - ``NBKCoreInteger`` - ``NBKFixedWidthInteger`` +- ``NBKOffsetIndexed`` - ``NBKSignedInteger`` - ``NBKUnsignedInteger`` @@ -108,6 +109,7 @@ Int256(5) % Int(5), UInt256(5) % UInt(5) - ``NBKBitPatternConvertible`` - ``NBKCoreInteger`` - ``NBKFixedWidthInteger`` +- ``NBKOffsetIndexed`` - ``NBKSignedInteger`` - ``NBKUnsignedInteger`` diff --git a/Tests/NBKCoreKitTests/NBKOffsetIndexed.swift b/Tests/NBKCoreKitTests/NBKOffsetIndexed.swift new file mode 100644 index 00000000..d746f734 --- /dev/null +++ b/Tests/NBKCoreKitTests/NBKOffsetIndexed.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. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +import XCTest + +//*============================================================================* +// MARK: * NBK x Offset Index +//*============================================================================* + +final class NBKOffsetIndexedTests: XCTestCase { + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testIndexOffsetByLimitedBy() { + NBKAssertIndexOffsetByLimitedBy(1, 2, 2, nil) + NBKAssertIndexOffsetByLimitedBy(1, 1, 2, 2) + NBKAssertIndexOffsetByLimitedBy(1, 0, 2, 1) + NBKAssertIndexOffsetByLimitedBy(1, -1, 2, 0) + NBKAssertIndexOffsetByLimitedBy(1, -2, 2, -1) + + NBKAssertIndexOffsetByLimitedBy(2, 2, 2, nil) + NBKAssertIndexOffsetByLimitedBy(2, 1, 2, nil) + NBKAssertIndexOffsetByLimitedBy(2, 0, 2, 2) + NBKAssertIndexOffsetByLimitedBy(2, -1, 2, nil) + NBKAssertIndexOffsetByLimitedBy(2, -2, 2, nil) + + NBKAssertIndexOffsetByLimitedBy(3, 2, 2, 5) + NBKAssertIndexOffsetByLimitedBy(3, 1, 2, 4) + NBKAssertIndexOffsetByLimitedBy(3, 0, 2, 3) + NBKAssertIndexOffsetByLimitedBy(3, -1, 2, 2) + NBKAssertIndexOffsetByLimitedBy(3, -2, 2, nil) + } +} + +//*============================================================================* +// MARK: * NBK x Offset Indexed x Assertions +//*============================================================================* + +private func NBKAssertIndexOffsetByLimitedBy( +_ index: Int, _ distance: Int, _ limit: Int, _ expectation: Int?, +file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual(NBK .offset(index, by: distance, limit: limit), expectation, file: file, line: line) + XCTAssertEqual([Int]().index(index, offsetBy: distance, limitedBy: limit), expectation, file: file, line: line) +} + +#endif From bdd9aa11b05a44051af5d649e6140dd9b9cdfc9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Fri, 1 Sep 2023 08:27:43 +0200 Subject: [PATCH 084/111] [NBKDoubleWidthKit] OffsetIndexed (#76). --- Sources/NBKCoreKit/NBKOffsetIndexed.swift | 20 ++--- .../NBKDoubleWidth+Words.swift | 84 +++---------------- .../NBKDoubleWidthKit/NBKDoubleWidth.swift | 2 +- .../NBKDoubleWidth+Words.swift | 62 -------------- 4 files changed, 21 insertions(+), 147 deletions(-) diff --git a/Sources/NBKCoreKit/NBKOffsetIndexed.swift b/Sources/NBKCoreKit/NBKOffsetIndexed.swift index d622cb21..35323ffb 100644 --- a/Sources/NBKCoreKit/NBKOffsetIndexed.swift +++ b/Sources/NBKCoreKit/NBKOffsetIndexed.swift @@ -29,15 +29,15 @@ extension NBKOffsetIndexed { // MARK: Accessors //=------------------------------------------------------------------------= - @inlinable public var startIndex: Int { + @_transparent public var startIndex: Int { Int.zero } - @inlinable public var endIndex: Int { + @_transparent public var endIndex: Int { self.count } - @inlinable public var indices: Range { + @_transparent public var indices: Range { Range(uncheckedBounds:(Int.zero, self.count)) } @@ -45,31 +45,31 @@ extension NBKOffsetIndexed { // MARK: Utilities //=------------------------------------------------------------------------= - @inlinable public func distance(from start: Int, to end: Int) -> Int { + @_transparent public func distance(from start: Int, to end: Int) -> Int { end - start } - @inlinable public func index(after index: Int) -> Int { + @_transparent public func index(after index: Int) -> Int { index + 1 } - @inlinable public func formIndex(after index: inout Int) { + @_transparent public func formIndex(after index: inout Int) { index += 1 } - @inlinable public func index(before index: Int) -> Int { + @_transparent public func index(before index: Int) -> Int { index - 1 } - @inlinable public func formIndex(before index: inout Int) { + @_transparent public func formIndex(before index: inout Int) { index -= 1 } - @inlinable public func index(_ index: Int, offsetBy distance: Int) -> Int { + @_transparent public func index(_ index: Int, offsetBy distance: Int) -> Int { index + distance } - @inlinable public func index(_ index: Int, offsetBy distance: Int, limitedBy limit: Int) -> Int? { + @_transparent public func index(_ index: Int, offsetBy distance: Int, limitedBy limit: Int) -> Int? { NBK.offset(index, by: distance, limit: limit) } } diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words.swift index 8cc2c80c..25be53f0 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words.swift @@ -19,7 +19,7 @@ extension NBKDoubleWidth { // MARK: Accessors //=------------------------------------------------------------------------= - /// The number of words in this type of integer. + /// The number of words in this integer type. @inlinable public static var count: Int { BitPattern.count(UInt.self) } @@ -28,17 +28,18 @@ extension NBKDoubleWidth { // MARK: Accessors //=------------------------------------------------------------------------= - @inlinable public var count: Int { - Self.count as Int - } - @inlinable public var words: Self { _read { yield self } } + + /// The number of words in this integer type. + @inlinable public var count: Int { + Self.count as Int + } } //=----------------------------------------------------------------------------= -// MARK: + Collection x Indices +// MARK: + Collection //=----------------------------------------------------------------------------= extension NBKDoubleWidth { @@ -47,75 +48,10 @@ extension NBKDoubleWidth { // MARK: Accessors //=------------------------------------------------------------------------= - /// The index of the least significant word. - @inlinable public var startIndex: Int { - 0 - } - /// The index of the most significant word. @inlinable public var lastIndex: Int { - self.count - 1 - } - - /// The index after the last valid subscript argument. - @inlinable public var endIndex: Int { - self.count - } - - /// A collection of each valid subscript argument, in ascending order. - @inlinable public var indices: Range { - 0 ..< self.count - } - - //=------------------------------------------------------------------------= - // MARK: Utilities - //=------------------------------------------------------------------------= - - @inlinable public func distance(from start: Int, to end: Int) -> Int { - end - start - } - - @inlinable public func index(after index: Int) -> Int { - index + 1 - } - - @inlinable public func formIndex(after index: inout Int) { - index += 1 - } - - @inlinable public func index(before index: Int) -> Int { - index - 1 - } - - @inlinable public func formIndex(before index: inout Int) { - index -= 1 - } - - @inlinable public func index(_ index: Int, offsetBy distance: Int) -> Int { - index + distance - } - - @inlinable public func index(_ index: Int, offsetBy distance: Int, limitedBy limit: Int) -> Int? { - let distanceLimit: Int = self.distance(from: index, to: limit) - - guard distance >= 0 - ? distance <= distanceLimit || distanceLimit < 0 - : distance >= distanceLimit || distanceLimit > 0 - else { return nil } - - return self.index(index, offsetBy: distance) as Int + self.count as Int - 1 } -} - -//=----------------------------------------------------------------------------= -// MARK: + Collection x Elements -//=----------------------------------------------------------------------------= - -extension NBKDoubleWidth { - - //=------------------------------------------------------------------------= - // MARK: Accessors - //=------------------------------------------------------------------------= /// The least significant word. /// @@ -144,7 +80,7 @@ extension NBKDoubleWidth { } //=------------------------------------------------------------------------= - // MARK: Accessors + // MARK: Accessors x Subscripts //=------------------------------------------------------------------------= /// Accesses the word at the given index, from least significant to most. @@ -198,7 +134,7 @@ extension NBKDoubleWidth { } //=------------------------------------------------------------------------= - // MARK: Accessors x Private + // MARK: Accessors x Subscripts x Private //=------------------------------------------------------------------------= /// Accesses the word at the given index, from least significant to most. diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift index 255853de..77d5b974 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift @@ -88,7 +88,7 @@ import NBKCoreKit /// - Note: You can use `StaticString` until `StaticBigInt` becomes available. /// @frozen public struct NBKDoubleWidth: ExpressibleByStringLiteral, -NBKFixedWidthInteger, MutableCollection, RandomAccessCollection where +NBKFixedWidthInteger, MutableCollection, NBKOffsetIndexed where High: NBKFixedWidthInteger, High.Digit: NBKCoreInteger { /// The most significant half of this type. diff --git a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Words.swift b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Words.swift index b438f783..a4aaa34d 100644 --- a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Words.swift +++ b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Words.swift @@ -69,30 +69,6 @@ final class NBKDoubleWidthTestsOnWordsAsInt256: XCTestCase { NBKAssertFirstLastTail( T(x32: Y(1, 2, 3, 4, 5, 6, 7, 8)), first: 1, last: 8, tail: 8) NBKAssertFirstLastTail(~T(x32: Y(1, 2, 3, 4, 5, 6, 7, 8)), first: ~1, last: ~8, tail: ~8) } - - //=----------------------------------------------------------------------------= - // MARK: + Indices - //=----------------------------------------------------------------------------= - - func testIndexOffsetByLimitedBy() { - NBKAssertIndexOffsetByLimitedBy(T.zero, 1, 2, 2, nil) - NBKAssertIndexOffsetByLimitedBy(T.zero, 1, 1, 2, 2) - NBKAssertIndexOffsetByLimitedBy(T.zero, 1, 0, 2, 1) - NBKAssertIndexOffsetByLimitedBy(T.zero, 1, -1, 2, 0) - NBKAssertIndexOffsetByLimitedBy(T.zero, 1, -2, 2, -1) - - NBKAssertIndexOffsetByLimitedBy(T.zero, 2, 2, 2, nil) - NBKAssertIndexOffsetByLimitedBy(T.zero, 2, 1, 2, nil) - NBKAssertIndexOffsetByLimitedBy(T.zero, 2, 0, 2, 2) - NBKAssertIndexOffsetByLimitedBy(T.zero, 2, -1, 2, nil) - NBKAssertIndexOffsetByLimitedBy(T.zero, 2, -2, 2, nil) - - NBKAssertIndexOffsetByLimitedBy(T.zero, 3, 2, 2, 5) - NBKAssertIndexOffsetByLimitedBy(T.zero, 3, 1, 2, 4) - NBKAssertIndexOffsetByLimitedBy(T.zero, 3, 0, 2, 3) - NBKAssertIndexOffsetByLimitedBy(T.zero, 3, -1, 2, 2) - NBKAssertIndexOffsetByLimitedBy(T.zero, 3, -2, 2, nil) - } } //*============================================================================* @@ -148,30 +124,6 @@ final class NBKDoubleWidthTestsOnWordsAsUInt256: XCTestCase { NBKAssertFirstLastTail( T(x32: Y(1, 2, 3, 4, 5, 6, 7, 8)), first: 1, last: 8, tail: 8) NBKAssertFirstLastTail(~T(x32: Y(1, 2, 3, 4, 5, 6, 7, 8)), first: ~1, last: ~8, tail: ~8) } - - //=----------------------------------------------------------------------------= - // MARK: + Indices - //=----------------------------------------------------------------------------= - - func testIndexOffsetByLimitedBy() { - NBKAssertIndexOffsetByLimitedBy(T.zero, 1, 2, 2, nil) - NBKAssertIndexOffsetByLimitedBy(T.zero, 1, 1, 2, 2) - NBKAssertIndexOffsetByLimitedBy(T.zero, 1, 0, 2, 1) - NBKAssertIndexOffsetByLimitedBy(T.zero, 1, -1, 2, 0) - NBKAssertIndexOffsetByLimitedBy(T.zero, 1, -2, 2, -1) - - NBKAssertIndexOffsetByLimitedBy(T.zero, 2, 2, 2, nil) - NBKAssertIndexOffsetByLimitedBy(T.zero, 2, 1, 2, nil) - NBKAssertIndexOffsetByLimitedBy(T.zero, 2, 0, 2, 2) - NBKAssertIndexOffsetByLimitedBy(T.zero, 2, -1, 2, nil) - NBKAssertIndexOffsetByLimitedBy(T.zero, 2, -2, 2, nil) - - NBKAssertIndexOffsetByLimitedBy(T.zero, 3, 2, 2, 5) - NBKAssertIndexOffsetByLimitedBy(T.zero, 3, 1, 2, 4) - NBKAssertIndexOffsetByLimitedBy(T.zero, 3, 0, 2, 3) - NBKAssertIndexOffsetByLimitedBy(T.zero, 3, -1, 2, 2) - NBKAssertIndexOffsetByLimitedBy(T.zero, 3, -2, 2, nil) - } } //*============================================================================* @@ -200,20 +152,6 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual(generic.withContiguousMutableStorageIfAvailable({ Array($0) }), words, file: file, line: line) } -//=----------------------------------------------------------------------------= -// MARK: + Indices -//=----------------------------------------------------------------------------= - -private func NBKAssertIndexOffsetByLimitedBy( -_ integer: NBKDoubleWidth, _ index: Int, _ distance: Int, _ limit: Int, _ expectation: Int?, -file: StaticString = #file, line: UInt = #line) { - let wordsIndex = /*-*/(integer).index(index, offsetBy: distance, limitedBy: limit) - let arrayIndex = Array(integer).index(index, offsetBy: distance, limitedBy: limit) - - XCTAssertEqual(wordsIndex, expectation, file: file, line: line) - XCTAssertEqual(arrayIndex, expectation, file: file, line: line) -} - //=----------------------------------------------------------------------------= // MARK: + Elements x First, Last, Tail //=----------------------------------------------------------------------------= From a08e1b8c05bee96ac8fb3dc81d6205058073a5b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Fri, 1 Sep 2023 09:18:48 +0200 Subject: [PATCH 085/111] [NBKCoreKit] Un/signedInteger.swift. --- README.md | 4 +- Sources/NBKCoreKit/NBKBinaryInteger.swift | 244 -------------------- Sources/NBKCoreKit/NBKOffsetIndexed.swift | 2 +- Sources/NBKCoreKit/NBKSignedInteger.swift | 148 ++++++++++++ Sources/NBKCoreKit/NBKUnsignedInteger.swift | 112 +++++++++ 5 files changed, 263 insertions(+), 247 deletions(-) create mode 100644 Sources/NBKCoreKit/NBKSignedInteger.swift create mode 100644 Sources/NBKCoreKit/NBKUnsignedInteger.swift diff --git a/README.md b/README.md index 506a968b..f305a34f 100644 --- a/README.md +++ b/README.md @@ -17,8 +17,8 @@ A new protocol hierarchy that refines Swift's standard library. - [NBKCoreInteger](Sources/NBKCoreKit/NBKCoreInteger.swift) - [NBKFixedWidthInteger](Sources/NBKCoreKit/NBKFixedWidthInteger.swift) - [NBKOffsetIndexed](Sources/NBKCoreKit/NBKOffsetIndexed.swift) -- [NBKSignedInteger](Sources/NBKCoreKit/NBKBinaryInteger.swift) -- [NBKUnsignedInteger](Sources/NBKCoreKit/NBKBinaryInteger.swift) +- [NBKSignedInteger](Sources/NBKCoreKit/NBKSignedInteger.swift) +- [NBKUnsignedInteger](Sources/NBKCoreKit/NBKUnsignedInteger.swift) ### Models diff --git a/Sources/NBKCoreKit/NBKBinaryInteger.swift b/Sources/NBKCoreKit/NBKBinaryInteger.swift index 32684d2d..31f2f38b 100644 --- a/Sources/NBKCoreKit/NBKBinaryInteger.swift +++ b/Sources/NBKCoreKit/NBKBinaryInteger.swift @@ -1445,247 +1445,3 @@ extension String { self = source.description(radix: radix, uppercase: uppercase) } } - -//*============================================================================* -// MARK: * NBK x Binary Integer x Signed -//*============================================================================* - -/// A signed, binary, integer. -/// -/// ### Two's Complement -/// -/// Like `BinaryInteger`, it has [two's complement][2s] semantics. -/// -/// ``` -/// The two's complement representation of 0 is an infinite sequence of 0s. -/// The two's complement representation of -1 is an infinite sequence of 1s. -/// ``` -/// -/// [2s]: https://en.wikipedia.org/wiki/Two%27s_complement -/// -public protocol NBKSignedInteger: NBKBinaryInteger, SignedInteger where Digit: NBKSignedInteger { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - /// Returns the additive inverse of `number`. - /// - /// ``` - /// ┌─────────── → ───────────┬──────────┐ - /// │ number │ -number │ overflow │ - /// ├─────────── → ───────────┼──────────┤ - /// │ Int256( 1) │ Int256(-1) │ false │ - /// │ Int256( 0) │ Int256( 0) │ false │ - /// │ Int256(-1) │ Int256( 1) │ false │ - /// ├─────────── → ───────────┼──────────┤ - /// | Int256.min | Int256.min | true | - /// └─────────── → ───────────┴──────────┘ - /// ``` - /// - /// - Note: In the case of `overflow`, a runtime error may occur. - /// - @inlinable static prefix func -(number: Self) -> Self - - /// Forms the additive inverse of `self`. - /// - /// ``` - /// ┌─────────── → ───────────┬──────────┐ - /// │ self │ -self │ overflow │ - /// ├─────────── → ───────────┼──────────┤ - /// │ Int256( 1) │ Int256(-1) │ false │ - /// │ Int256( 0) │ Int256( 0) │ false │ - /// │ Int256(-1) │ Int256( 1) │ false │ - /// ├─────────── → ───────────┼──────────┤ - /// | Int256.min | Int256.min | true | - /// └─────────── → ───────────┴──────────┘ - /// ``` - /// - /// - Note: In the case of `overflow`, a runtime error may occur. - /// - @inlinable mutating func negate() - - /// Returns the additive inverse of `self`. - /// - /// ``` - /// ┌─────────── → ───────────┬──────────┐ - /// │ self │ -self │ overflow │ - /// ├─────────── → ───────────┼──────────┤ - /// │ Int256( 1) │ Int256(-1) │ false │ - /// │ Int256( 0) │ Int256( 0) │ false │ - /// │ Int256(-1) │ Int256( 1) │ false │ - /// ├─────────── → ───────────┼──────────┤ - /// | Int256.min | Int256.min | true | - /// └─────────── → ───────────┴──────────┘ - /// ``` - /// - /// - Note: In the case of `overflow`, a runtime error may occur. - /// - @inlinable func negated() -> Self - - /// Forms the additive inverse of `self`, and returns an `overflow` indicator. - /// - /// ``` - /// ┌─────────── → ───────────┬──────────┐ - /// │ self │ -self │ overflow │ - /// ├─────────── → ───────────┼──────────┤ - /// │ Int256( 1) │ Int256(-1) │ false │ - /// │ Int256( 0) │ Int256( 0) │ false │ - /// │ Int256(-1) │ Int256( 1) │ false │ - /// ├─────────── → ───────────┼──────────┤ - /// | Int256.min | Int256.min | true | - /// └─────────── → ───────────┴──────────┘ - /// ``` - /// - /// - Note: In the case of `overflow`, the result is truncated. - /// - @inlinable mutating func negateReportingOverflow() -> Bool - - /// Returns the additive inverse of `self`, along with an `overflow` indicator. - /// - /// ``` - /// ┌─────────── → ───────────┬──────────┐ - /// │ self │ -self │ overflow │ - /// ├─────────── → ───────────┼──────────┤ - /// │ Int256( 1) │ Int256(-1) │ false │ - /// │ Int256( 0) │ Int256( 0) │ false │ - /// │ Int256(-1) │ Int256( 1) │ false │ - /// ├─────────── → ───────────┼──────────┤ - /// | Int256.min | Int256.min | true | - /// └─────────── → ───────────┴──────────┘ - /// ``` - /// - /// - Note: In the case of `overflow`, the result is truncated. - /// - @inlinable func negatedReportingOverflow() -> PVO -} - -//=----------------------------------------------------------------------------= -// MARK: + Details -//=----------------------------------------------------------------------------= - -extension NBKSignedInteger { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - @inlinable public static prefix func -(x: Self) -> Self { - x.negated() - } - - @inlinable public mutating func negate() { - let overflow: Bool = self.negateReportingOverflow() - precondition(!overflow, NBK.callsiteOverflowInfo()) - } - - @inlinable public func negated() -> Self { - let pvo: PVO = self.negatedReportingOverflow() - precondition(!pvo.overflow, NBK.callsiteOverflowInfo()) - return pvo.partialValue as Self - } -} - -//*============================================================================* -// MARK: * NBK x Binary Integer x Unsigned -//*============================================================================* - -/// An unsigned, binary, integer. -/// -/// ### Two's Complement -/// -/// Like `BinaryInteger`, it has [two's complement][2s] semantics. -/// -/// ``` -/// The two's complement representation of 0 is an infinite sequence of 0s. -/// The two's complement representation of -1 is an infinite sequence of 1s. -/// ``` -/// -/// [2s]: https://en.wikipedia.org/wiki/Two%27s_complement -/// -public protocol NBKUnsignedInteger: NBKBinaryInteger, UnsignedInteger where Digit: NBKUnsignedInteger, Magnitude == Self { - - //=------------------------------------------------------------------------= - // MARK: Transformations - //=------------------------------------------------------------------------= - - /// Forms the `difference` of `self` and `other`, and returns an `overflow` indicator. - /// - /// ``` - /// ┌────────────┬─────────── → ───────────┬──────────┐ - /// │ self │ other │ difference │ overflow │ - /// ├────────────┼─────────── → ───────────┤──────────┤ - /// │ Int256( 1) │ Int256( 4) │ Int256(-3) │ false │ - /// │ Int256( 2) │ Int256(-3) │ Int256( 5) │ false │ - /// │ Int256(-3) │ Int256( 2) │ Int256(-5) │ false │ - /// │ Int256(-4) │ Int256(-1) │ Int256(-3) │ false │ - /// │────────────┤─────────── → ───────────┤──────────┤ - /// │ Int256.max │ Int256(-1) │ Int256.min │ true │ - /// │ Int256.min │ Int256( 1) │ Int256.max │ true │ - /// └────────────┴─────────── → ───────────┴──────────┘ - /// ``` - /// - /// - Note: In the case of `overflow`, the result is truncated. - /// - @inlinable mutating func subtractReportingOverflow(_ other: Self) -> Bool - - /// Forms the `difference` of `self` and `other`, and returns an `overflow` indicator. - /// - /// ``` - /// ┌────────────┬─────────── → ───────────┬──────────┐ - /// │ self │ other │ difference │ overflow │ - /// ├────────────┼─────────── → ───────────┤──────────┤ - /// │ Int256( 1) │ Int( 4) │ Int256(-3) │ false │ - /// │ Int256( 2) │ Int( -3) │ Int256( 5) │ false │ - /// │ Int256(-3) │ Int( 2) │ Int256(-5) │ false │ - /// │ Int256(-4) │ Int( -1) │ Int256(-3) │ false │ - /// │────────────┤─────────── → ───────────┤──────────┤ - /// │ Int256.max │ Int( -1) │ Int256.min │ true │ - /// │ Int256.min │ Int( 1) │ Int256.max │ true │ - /// └────────────┴─────────── → ───────────┴──────────┘ - /// ``` - /// - /// - Note: In the case of `overflow`, the result is truncated. - /// - @_disfavoredOverload @inlinable mutating func subtractReportingOverflow(_ other: Digit) -> Bool - - /// Returns the `difference` of `self` and `other`, along with an `overflow` indicator. - /// - /// ``` - /// ┌────────────┬─────────── → ───────────┬──────────┐ - /// │ self │ other │ difference │ overflow │ - /// ├────────────┼─────────── → ───────────┤──────────┤ - /// │ Int256( 1) │ Int256( 4) │ Int256(-3) │ false │ - /// │ Int256( 2) │ Int256(-3) │ Int256( 5) │ false │ - /// │ Int256(-3) │ Int256( 2) │ Int256(-5) │ false │ - /// │ Int256(-4) │ Int256(-1) │ Int256(-3) │ false │ - /// │────────────┤─────────── → ───────────┤──────────┤ - /// │ Int256.max │ Int256(-1) │ Int256.min │ true │ - /// │ Int256.min │ Int256( 1) │ Int256.max │ true │ - /// └────────────┴─────────── → ───────────┴──────────┘ - /// ``` - /// - /// - Note: In the case of `overflow`, the result is truncated. - /// - @inlinable func subtractingReportingOverflow(_ other: Self) -> PVO - - /// Returns the `difference` of `self` and `other`, along with an `overflow` indicator. - /// - /// ``` - /// ┌────────────┬─────────── → ───────────┬──────────┐ - /// │ self │ other │ difference │ overflow │ - /// ├────────────┼─────────── → ───────────┤──────────┤ - /// │ Int256( 1) │ Int( 4) │ Int256(-3) │ false │ - /// │ Int256( 2) │ Int( -3) │ Int256( 5) │ false │ - /// │ Int256(-3) │ Int( 2) │ Int256(-5) │ false │ - /// │ Int256(-4) │ Int( -1) │ Int256(-3) │ false │ - /// │────────────┤─────────── → ───────────┤──────────┤ - /// │ Int256.max │ Int( -1) │ Int256.min │ true │ - /// │ Int256.min │ Int( 1) │ Int256.max │ true │ - /// └────────────┴─────────── → ───────────┴──────────┘ - /// ``` - /// - /// - Note: In the case of `overflow`, the result is truncated. - /// - @_disfavoredOverload @inlinable func subtractingReportingOverflow(_ other: Digit) -> PVO -} diff --git a/Sources/NBKCoreKit/NBKOffsetIndexed.swift b/Sources/NBKCoreKit/NBKOffsetIndexed.swift index 35323ffb..0cc3c3f5 100644 --- a/Sources/NBKCoreKit/NBKOffsetIndexed.swift +++ b/Sources/NBKCoreKit/NBKOffsetIndexed.swift @@ -38,7 +38,7 @@ extension NBKOffsetIndexed { } @_transparent public var indices: Range { - Range(uncheckedBounds:(Int.zero, self.count)) + Range(uncheckedBounds:(self.startIndex, self.endIndex)) } //=------------------------------------------------------------------------= diff --git a/Sources/NBKCoreKit/NBKSignedInteger.swift b/Sources/NBKCoreKit/NBKSignedInteger.swift new file mode 100644 index 00000000..2d2fecd5 --- /dev/null +++ b/Sources/NBKCoreKit/NBKSignedInteger.swift @@ -0,0 +1,148 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +//*============================================================================* +// MARK: * NBK x Signed Integer +//*============================================================================* + +/// A signed, binary, integer. +/// +/// ### Two's Complement +/// +/// Like `BinaryInteger`, it has [two's complement][2s] semantics. +/// +/// ``` +/// The two's complement representation of 0 is an infinite sequence of 0s. +/// The two's complement representation of -1 is an infinite sequence of 1s. +/// ``` +/// +/// [2s]: https://en.wikipedia.org/wiki/Two%27s_complement +/// +public protocol NBKSignedInteger: NBKBinaryInteger, SignedInteger where Digit: NBKSignedInteger { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + /// Returns the additive inverse of `number`. + /// + /// ``` + /// ┌─────────── → ───────────┬──────────┐ + /// │ number │ -number │ overflow │ + /// ├─────────── → ───────────┼──────────┤ + /// │ Int256( 1) │ Int256(-1) │ false │ + /// │ Int256( 0) │ Int256( 0) │ false │ + /// │ Int256(-1) │ Int256( 1) │ false │ + /// ├─────────── → ───────────┼──────────┤ + /// | Int256.min | Int256.min | true | + /// └─────────── → ───────────┴──────────┘ + /// ``` + /// + /// - Note: In the case of `overflow`, a runtime error may occur. + /// + @inlinable static prefix func -(number: Self) -> Self + + /// Forms the additive inverse of `self`. + /// + /// ``` + /// ┌─────────── → ───────────┬──────────┐ + /// │ self │ -self │ overflow │ + /// ├─────────── → ───────────┼──────────┤ + /// │ Int256( 1) │ Int256(-1) │ false │ + /// │ Int256( 0) │ Int256( 0) │ false │ + /// │ Int256(-1) │ Int256( 1) │ false │ + /// ├─────────── → ───────────┼──────────┤ + /// | Int256.min | Int256.min | true | + /// └─────────── → ───────────┴──────────┘ + /// ``` + /// + /// - Note: In the case of `overflow`, a runtime error may occur. + /// + @inlinable mutating func negate() + + /// Returns the additive inverse of `self`. + /// + /// ``` + /// ┌─────────── → ───────────┬──────────┐ + /// │ self │ -self │ overflow │ + /// ├─────────── → ───────────┼──────────┤ + /// │ Int256( 1) │ Int256(-1) │ false │ + /// │ Int256( 0) │ Int256( 0) │ false │ + /// │ Int256(-1) │ Int256( 1) │ false │ + /// ├─────────── → ───────────┼──────────┤ + /// | Int256.min | Int256.min | true | + /// └─────────── → ───────────┴──────────┘ + /// ``` + /// + /// - Note: In the case of `overflow`, a runtime error may occur. + /// + @inlinable func negated() -> Self + + /// Forms the additive inverse of `self`, and returns an `overflow` indicator. + /// + /// ``` + /// ┌─────────── → ───────────┬──────────┐ + /// │ self │ -self │ overflow │ + /// ├─────────── → ───────────┼──────────┤ + /// │ Int256( 1) │ Int256(-1) │ false │ + /// │ Int256( 0) │ Int256( 0) │ false │ + /// │ Int256(-1) │ Int256( 1) │ false │ + /// ├─────────── → ───────────┼──────────┤ + /// | Int256.min | Int256.min | true | + /// └─────────── → ───────────┴──────────┘ + /// ``` + /// + /// - Note: In the case of `overflow`, the result is truncated. + /// + @inlinable mutating func negateReportingOverflow() -> Bool + + /// Returns the additive inverse of `self`, along with an `overflow` indicator. + /// + /// ``` + /// ┌─────────── → ───────────┬──────────┐ + /// │ self │ -self │ overflow │ + /// ├─────────── → ───────────┼──────────┤ + /// │ Int256( 1) │ Int256(-1) │ false │ + /// │ Int256( 0) │ Int256( 0) │ false │ + /// │ Int256(-1) │ Int256( 1) │ false │ + /// ├─────────── → ───────────┼──────────┤ + /// | Int256.min | Int256.min | true | + /// └─────────── → ───────────┴──────────┘ + /// ``` + /// + /// - Note: In the case of `overflow`, the result is truncated. + /// + @inlinable func negatedReportingOverflow() -> PVO +} + +//=----------------------------------------------------------------------------= +// MARK: + Details +//=----------------------------------------------------------------------------= + +extension NBKSignedInteger { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + @inlinable public static prefix func -(x: Self) -> Self { + x.negated() + } + + @inlinable public mutating func negate() { + let overflow: Bool = self.negateReportingOverflow() + precondition(!overflow, NBK.callsiteOverflowInfo()) + } + + @inlinable public func negated() -> Self { + let pvo: PVO = self.negatedReportingOverflow() + precondition(!pvo.overflow, NBK.callsiteOverflowInfo()) + return pvo.partialValue as Self + } +} diff --git a/Sources/NBKCoreKit/NBKUnsignedInteger.swift b/Sources/NBKCoreKit/NBKUnsignedInteger.swift new file mode 100644 index 00000000..d36adecc --- /dev/null +++ b/Sources/NBKCoreKit/NBKUnsignedInteger.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. +//=----------------------------------------------------------------------------= + +//*============================================================================* +// MARK: * NBK x Unsigned Integer +//*============================================================================* + +/// An unsigned, binary, integer. +/// +/// ### Two's Complement +/// +/// Like `BinaryInteger`, it has [two's complement][2s] semantics. +/// +/// ``` +/// The two's complement representation of 0 is an infinite sequence of 0s. +/// The two's complement representation of -1 is an infinite sequence of 1s. +/// ``` +/// +/// [2s]: https://en.wikipedia.org/wiki/Two%27s_complement +/// +public protocol NBKUnsignedInteger: NBKBinaryInteger, UnsignedInteger where Digit: NBKUnsignedInteger, Magnitude == Self { + + //=------------------------------------------------------------------------= + // MARK: Transformations + //=------------------------------------------------------------------------= + + /// Forms the `difference` of `self` and `other`, and returns an `overflow` indicator. + /// + /// ``` + /// ┌────────────┬─────────── → ───────────┬──────────┐ + /// │ self │ other │ difference │ overflow │ + /// ├────────────┼─────────── → ───────────┤──────────┤ + /// │ Int256( 1) │ Int256( 4) │ Int256(-3) │ false │ + /// │ Int256( 2) │ Int256(-3) │ Int256( 5) │ false │ + /// │ Int256(-3) │ Int256( 2) │ Int256(-5) │ false │ + /// │ Int256(-4) │ Int256(-1) │ Int256(-3) │ false │ + /// │────────────┤─────────── → ───────────┤──────────┤ + /// │ Int256.max │ Int256(-1) │ Int256.min │ true │ + /// │ Int256.min │ Int256( 1) │ Int256.max │ true │ + /// └────────────┴─────────── → ───────────┴──────────┘ + /// ``` + /// + /// - Note: In the case of `overflow`, the result is truncated. + /// + @inlinable mutating func subtractReportingOverflow(_ other: Self) -> Bool + + /// Forms the `difference` of `self` and `other`, and returns an `overflow` indicator. + /// + /// ``` + /// ┌────────────┬─────────── → ───────────┬──────────┐ + /// │ self │ other │ difference │ overflow │ + /// ├────────────┼─────────── → ───────────┤──────────┤ + /// │ Int256( 1) │ Int( 4) │ Int256(-3) │ false │ + /// │ Int256( 2) │ Int( -3) │ Int256( 5) │ false │ + /// │ Int256(-3) │ Int( 2) │ Int256(-5) │ false │ + /// │ Int256(-4) │ Int( -1) │ Int256(-3) │ false │ + /// │────────────┤─────────── → ───────────┤──────────┤ + /// │ Int256.max │ Int( -1) │ Int256.min │ true │ + /// │ Int256.min │ Int( 1) │ Int256.max │ true │ + /// └────────────┴─────────── → ───────────┴──────────┘ + /// ``` + /// + /// - Note: In the case of `overflow`, the result is truncated. + /// + @_disfavoredOverload @inlinable mutating func subtractReportingOverflow(_ other: Digit) -> Bool + + /// Returns the `difference` of `self` and `other`, along with an `overflow` indicator. + /// + /// ``` + /// ┌────────────┬─────────── → ───────────┬──────────┐ + /// │ self │ other │ difference │ overflow │ + /// ├────────────┼─────────── → ───────────┤──────────┤ + /// │ Int256( 1) │ Int256( 4) │ Int256(-3) │ false │ + /// │ Int256( 2) │ Int256(-3) │ Int256( 5) │ false │ + /// │ Int256(-3) │ Int256( 2) │ Int256(-5) │ false │ + /// │ Int256(-4) │ Int256(-1) │ Int256(-3) │ false │ + /// │────────────┤─────────── → ───────────┤──────────┤ + /// │ Int256.max │ Int256(-1) │ Int256.min │ true │ + /// │ Int256.min │ Int256( 1) │ Int256.max │ true │ + /// └────────────┴─────────── → ───────────┴──────────┘ + /// ``` + /// + /// - Note: In the case of `overflow`, the result is truncated. + /// + @inlinable func subtractingReportingOverflow(_ other: Self) -> PVO + + /// Returns the `difference` of `self` and `other`, along with an `overflow` indicator. + /// + /// ``` + /// ┌────────────┬─────────── → ───────────┬──────────┐ + /// │ self │ other │ difference │ overflow │ + /// ├────────────┼─────────── → ───────────┤──────────┤ + /// │ Int256( 1) │ Int( 4) │ Int256(-3) │ false │ + /// │ Int256( 2) │ Int( -3) │ Int256( 5) │ false │ + /// │ Int256(-3) │ Int( 2) │ Int256(-5) │ false │ + /// │ Int256(-4) │ Int( -1) │ Int256(-3) │ false │ + /// │────────────┤─────────── → ───────────┤──────────┤ + /// │ Int256.max │ Int( -1) │ Int256.min │ true │ + /// │ Int256.min │ Int( 1) │ Int256.max │ true │ + /// └────────────┴─────────── → ───────────┴──────────┘ + /// ``` + /// + /// - Note: In the case of `overflow`, the result is truncated. + /// + @_disfavoredOverload @inlinable func subtractingReportingOverflow(_ other: Digit) -> PVO +} From ffb1f3d976562a0717334b6d9b41953fec0c8988 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Fri, 1 Sep 2023 09:38:07 +0200 Subject: [PATCH 086/111] No NBKOffsetIndexed defaults (#76). --- Sources/NBKCoreKit/Models/NBKTwinHeaded.swift | 71 +++++++++++++-- Sources/NBKCoreKit/NBKOffsetIndexed.swift | 57 +----------- .../NBKDoubleWidth+Words.swift | 89 +++++++++++++++---- 3 files changed, 137 insertions(+), 80 deletions(-) diff --git a/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift b/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift index 1ba84af1..dbcdbbc9 100644 --- a/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift +++ b/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift @@ -91,6 +91,10 @@ self.body as Base } + @inlinable public var count: Int { + self.base.count + } + /// Returns the direction of iteratorn as 1 (front-to-back) or -1 (back-to-front). @inlinable public var direction: Int { self.mask &<< (1 as Int) | (1 as Int) @@ -116,14 +120,6 @@ self.isBackToFront ? self.base.reversed() : nil } - @inlinable public var count: Int { - self.base.count - } - - @inlinable public subscript(index: Int) -> Element { - _read { yield self.base[self.baseSubscriptIndex(index)] } - } - //=------------------------------------------------------------------------= // MARK: Transformations //=------------------------------------------------------------------------= @@ -199,6 +195,65 @@ } } +//=----------------------------------------------------------------------------= +// MARK: + Collection +//=----------------------------------------------------------------------------= + +extension NBKTwinHeaded { + + //=------------------------------------------------------------------------= + // MARK: Accessors + //=------------------------------------------------------------------------= + + @inlinable public var startIndex: Int { + 0 as Int + } + + @inlinable public var endIndex: Int { + self.count + } + + @inlinable public var indices: Range { + Range(uncheckedBounds:(0 as Int, self.count)) + } + + @inlinable public subscript(index: Int) -> Element { + _read { yield self.base[self.baseSubscriptIndex(index)] } + } + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + @inlinable public func distance(from start: Int, to end: Int) -> Int { + end - start + } + + @inlinable public func index(after index: Int) -> Int { + index + 1 as Int + } + + @inlinable public func formIndex(after index: inout Int) { + index += 1 as Int + } + + @inlinable public func index(before index: Int) -> Int { + index - 1 as Int + } + + @inlinable public func formIndex(before index: inout Int) { + index -= 1 as Int + } + + @inlinable public func index(_ index: Int, offsetBy distance: Int) -> Int { + index + distance + } + + @inlinable public func index(_ index: Int, offsetBy distance: Int, limitedBy limit: Int) -> Int? { + NBK.offset(index, by: distance, limit: limit) + } +} + //=----------------------------------------------------------------------------= // MARK: + Mutable Collection //=----------------------------------------------------------------------------= diff --git a/Sources/NBKCoreKit/NBKOffsetIndexed.swift b/Sources/NBKCoreKit/NBKOffsetIndexed.swift index 0cc3c3f5..f9167df8 100644 --- a/Sources/NBKCoreKit/NBKOffsetIndexed.swift +++ b/Sources/NBKCoreKit/NBKOffsetIndexed.swift @@ -20,64 +20,9 @@ public protocol NBKOffsetIndexed: RandomAccessCollection where Indices == Range { } //=----------------------------------------------------------------------------= -// MARK: + Details +// MARK: + Algorithms //=----------------------------------------------------------------------------= -extension NBKOffsetIndexed { - - //=------------------------------------------------------------------------= - // MARK: Accessors - //=------------------------------------------------------------------------= - - @_transparent public var startIndex: Int { - Int.zero - } - - @_transparent public var endIndex: Int { - self.count - } - - @_transparent public var indices: Range { - Range(uncheckedBounds:(self.startIndex, self.endIndex)) - } - - //=------------------------------------------------------------------------= - // MARK: Utilities - //=------------------------------------------------------------------------= - - @_transparent public func distance(from start: Int, to end: Int) -> Int { - end - start - } - - @_transparent public func index(after index: Int) -> Int { - index + 1 - } - - @_transparent public func formIndex(after index: inout Int) { - index += 1 - } - - @_transparent public func index(before index: Int) -> Int { - index - 1 - } - - @_transparent public func formIndex(before index: inout Int) { - index -= 1 - } - - @_transparent public func index(_ index: Int, offsetBy distance: Int) -> Int { - index + distance - } - - @_transparent public func index(_ index: Int, offsetBy distance: Int, limitedBy limit: Int) -> Int? { - NBK.offset(index, by: distance, limit: limit) - } -} - -//*============================================================================* -// MARK: * NBK x Offset Indexed x Algorithms -//*============================================================================* - extension NBK { //=------------------------------------------------------------------------= diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words.swift index 25be53f0..d9b9caa4 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words.swift @@ -19,7 +19,7 @@ extension NBKDoubleWidth { // MARK: Accessors //=------------------------------------------------------------------------= - /// The number of words in this integer type. + /// The number of words that fit in this integer type. @inlinable public static var count: Int { BitPattern.count(UInt.self) } @@ -28,18 +28,17 @@ extension NBKDoubleWidth { // MARK: Accessors //=------------------------------------------------------------------------= - @inlinable public var words: Self { - _read { yield self } - } - - /// The number of words in this integer type. @inlinable public var count: Int { Self.count as Int } + + @inlinable public var words: Self { + _read { yield self } + } } //=----------------------------------------------------------------------------= -// MARK: + Collection +// MARK: + Collection x Indices //=----------------------------------------------------------------------------= extension NBKDoubleWidth { @@ -48,11 +47,69 @@ extension NBKDoubleWidth { // MARK: Accessors //=------------------------------------------------------------------------= + /// The index of the least significant word. + @inlinable public var startIndex: Int { + 0 as Int + } + /// The index of the most significant word. @inlinable public var lastIndex: Int { - self.count as Int - 1 + self.count - 1 as Int + } + + /// The index after the last valid subscript argument. + @inlinable public var endIndex: Int { + self.count + } + + /// A collection of each valid subscript argument, in ascending order. + @inlinable public var indices: Range { + 0 as Int ..< self.count + } + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + @inlinable public func distance(from start: Int, to end: Int) -> Int { + end - start + } + + @inlinable public func index(after index: Int) -> Int { + index + 1 as Int } + @inlinable public func formIndex(after index: inout Int) { + index += 1 as Int + } + + @inlinable public func index(before index: Int) -> Int { + index - 1 as Int + } + + @inlinable public func formIndex(before index: inout Int) { + index -= 1 as Int + } + + @inlinable public func index(_ index: Int, offsetBy distance: Int) -> Int { + index + distance + } + + @inlinable public func index(_ index: Int, offsetBy distance: Int, limitedBy limit: Int) -> Int? { + NBK.offset(index, by: distance, limit: limit) + } +} + +//=----------------------------------------------------------------------------= +// MARK: + Collection x Elements +//=----------------------------------------------------------------------------= + +extension NBKDoubleWidth { + + //=------------------------------------------------------------------------= + // MARK: Accessors + //=------------------------------------------------------------------------= + /// The least significant word. /// /// - Note: This member is required by `Swift.BinaryInteger`. @@ -80,7 +137,7 @@ extension NBKDoubleWidth { } //=------------------------------------------------------------------------= - // MARK: Accessors x Subscripts + // MARK: Accessors //=------------------------------------------------------------------------= /// Accesses the word at the given index, from least significant to most. @@ -134,7 +191,7 @@ extension NBKDoubleWidth { } //=------------------------------------------------------------------------= - // MARK: Accessors x Subscripts x Private + // MARK: Accessors x Private //=------------------------------------------------------------------------= /// Accesses the word at the given index, from least significant to most. @@ -161,18 +218,18 @@ extension NBKDoubleWidth { /// @inlinable subscript(unchecked index: Int, as type: T.Type) -> T where T: NBKCoreInteger { get { - let offset = BitPattern.endiannessSensitiveByteOffset(of: T.BitPattern.self, at: index) - assert(0 <= offset && offset <= MemoryLayout.size - MemoryLayout.stride, NBK.callsiteOutOfBoundsInfo()) + let byteOffset = BitPattern.endiannessSensitiveByteOffset(of: T.BitPattern.self, at: index) + assert(0 <= byteOffset && byteOffset <= MemoryLayout.size - MemoryLayout.stride, NBK.callsiteOutOfBoundsInfo()) return Swift.withUnsafePointer(to: self) { pointer in - UnsafeRawPointer(pointer).load(fromByteOffset: offset, as: T.self) + UnsafeRawPointer(pointer).load(fromByteOffset: byteOffset, as: T.self) } } set { - let offset = BitPattern.endiannessSensitiveByteOffset(of: T.BitPattern.self, at: index) - assert(0 <= offset && offset <= MemoryLayout.size - MemoryLayout.stride, NBK.callsiteOutOfBoundsInfo()) + let byteOffset = BitPattern.endiannessSensitiveByteOffset(of: T.BitPattern.self, at: index) + assert(0 <= byteOffset && byteOffset <= MemoryLayout.size - MemoryLayout.stride, NBK.callsiteOutOfBoundsInfo()) Swift.withUnsafeMutablePointer(to: &self) { pointer in - UnsafeMutableRawPointer(pointer).storeBytes(of: newValue, toByteOffset: offset, as: T.self) + UnsafeMutableRawPointer(pointer).storeBytes(of: newValue, toByteOffset: byteOffset, as: T.self) } } } From 626a02b812c2ca0ade2fe33390a70aec058abb6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Fri, 1 Sep 2023 10:31:20 +0200 Subject: [PATCH 087/111] Use `0 as Int` rather than `Int.zero` (#77). --- Sources/NBKCoreKit/Models/NBKMajorOrMinorInteger.swift | 4 ++-- Sources/NBKCoreKit/NBKOffsetIndexed.swift | 6 +++--- Sources/NBKCoreKit/Private/NBK+Limbs+Bits.swift | 4 ++-- Sources/NBKCoreKit/Private/NBK+Limbs+Comparisons.swift | 2 +- Sources/NBKDoubleWidthKit/NBKDoubleWidth+Comparisons.swift | 2 +- .../NBKDoubleWidth+Multiplication+Digit.swift | 6 +++--- Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text.swift | 2 +- Tests/NBKCoreKitTests/Private/NBK+Limbs+Addition.swift | 4 ++-- Tests/NBKCoreKitTests/Private/NBK+Limbs+Comparisons.swift | 4 ++-- Tests/NBKCoreKitTests/Private/NBK+Limbs+Subtraction.swift | 4 ++-- 10 files changed, 19 insertions(+), 19 deletions(-) diff --git a/Sources/NBKCoreKit/Models/NBKMajorOrMinorInteger.swift b/Sources/NBKCoreKit/Models/NBKMajorOrMinorInteger.swift index 17a37008..b6c58385 100644 --- a/Sources/NBKCoreKit/Models/NBKMajorOrMinorInteger.swift +++ b/Sources/NBKCoreKit/Models/NBKMajorOrMinorInteger.swift @@ -195,7 +195,7 @@ MajorLimb: NBKCoreInteger, MinorLimbs: Sequence, MinorLimbs.Element: NBKCoreInte @inlinable public mutating func next() -> MajorLimb? { var majorLimb = MajorLimb.zero - var majorLimbShift = Int.zero + var majorLimbShift = 0 as Int var minorLimb = MinorLimb.Magnitude.zero while let next = self.minorLimbs.next() { @@ -382,7 +382,7 @@ Sequence where MinorLimb: NBKCoreInteger, MajorLimb: NBKCoreInteger { @inlinable init(_ majorLimb: MajorLimb) { self.majorLimb = majorLimb - self.majorLimbShift = Int.zero + self.majorLimbShift = 0 as Int } //=--------------------------------------------------------------------= diff --git a/Sources/NBKCoreKit/NBKOffsetIndexed.swift b/Sources/NBKCoreKit/NBKOffsetIndexed.swift index f9167df8..87cc181b 100644 --- a/Sources/NBKCoreKit/NBKOffsetIndexed.swift +++ b/Sources/NBKCoreKit/NBKOffsetIndexed.swift @@ -33,9 +33,9 @@ extension NBK { @inlinable public static func offset(_ index: Int, by distance: Int, limit: Int) -> Int? { let distanceLimit = limit - index - guard distance >= Int.zero - ? distance <= distanceLimit || distanceLimit < Int.zero - : distance >= distanceLimit || distanceLimit > Int.zero + guard distance >= 0 as Int + ? distance <= distanceLimit || distanceLimit < 0 as Int + : distance >= distanceLimit || distanceLimit > 0 as Int else { return nil } return index + distance as Int diff --git a/Sources/NBKCoreKit/Private/NBK+Limbs+Bits.swift b/Sources/NBKCoreKit/Private/NBK+Limbs+Bits.swift index 31facc03..0e4a0485 100644 --- a/Sources/NBKCoreKit/Private/NBK+Limbs+Bits.swift +++ b/Sources/NBKCoreKit/Private/NBK+Limbs+Bits.swift @@ -68,7 +68,7 @@ extension NBK { /// - Note: The nonzero bit count is zero when `limbs` is empty. /// @inlinable public static func nonzeroBitCount(of limbs: some Collection) -> Int { - limbs.reduce(Int.zero) { $0 + $1.nonzeroBitCount } + limbs.reduce(0 as Int) { $0 + $1.nonzeroBitCount } } /// Returns whether the nonzero bit count of `limbs` equals `comparand`. @@ -92,7 +92,7 @@ extension NBK { /// - Note: The nonzero bit count is zero when `limbs` is empty. /// @inlinable public static func nonzeroBitCount(twosComplementOf limbs: some Collection) -> Int { - guard let index = limbs.firstIndex(where:{ !$0.isZero }) else { return Int.zero } + guard let index = limbs.firstIndex(where:{ !$0.isZero }) else { return 0 as Int } return limbs.indices[index...].reduce(1 - limbs[index].trailingZeroBitCount) { $0 + limbs[$1].onesComplement().nonzeroBitCount } } } diff --git a/Sources/NBKCoreKit/Private/NBK+Limbs+Comparisons.swift b/Sources/NBKCoreKit/Private/NBK+Limbs+Comparisons.swift index 4e0287ef..fa40b6c8 100644 --- a/Sources/NBKCoreKit/Private/NBK+Limbs+Comparisons.swift +++ b/Sources/NBKCoreKit/Private/NBK+Limbs+Comparisons.swift @@ -136,6 +136,6 @@ extension NBK { //=--------------------------------------= // Same //=--------------------------------------= - return Int.zero + return 0 as Int } } diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Comparisons.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Comparisons.swift index b3ef7983..2e17871c 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Comparisons.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Comparisons.swift @@ -69,7 +69,7 @@ extension NBKDoubleWidth { if lhsWord != rhsWord { return lhsWord < rhsWord ? -1 : 1 } } - return Int.zero + return 0 as Int } @_disfavoredOverload @inlinable public func compared(to other: Digit) -> Int { diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Multiplication+Digit.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Multiplication+Digit.swift index 3d2f4285..c27a53f9 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Multiplication+Digit.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Multiplication+Digit.swift @@ -30,7 +30,7 @@ extension NBKDoubleWidth { let rhsIsLessThanZero: Bool = other.isLessThanZero let minus = lhsIsLessThanZero != rhsIsLessThanZero //=--------------------------------------= - var pvo = NBK.bitCast(self.magnitude.multipliedReportingOverflow(by: other.magnitude, adding: UInt.zero)) as PVO + var pvo = NBK.bitCast(self.magnitude.multipliedReportingOverflow(by: other.magnitude, adding: 0 as UInt)) as PVO //=--------------------------------------= var suboverflow = (pvo.partialValue.isLessThanZero) if minus { @@ -57,7 +57,7 @@ extension NBKDoubleWidth { let rhsIsLessThanZero: Bool = other.isLessThanZero var minus = lhsIsLessThanZero != rhsIsLessThanZero //=--------------------------------------= - var product = self.magnitude.multipliedFullWidth(by: other.magnitude, adding: UInt.zero) as HL + var product = self.magnitude.multipliedFullWidth(by: other.magnitude, adding: 0 as UInt) as HL //=--------------------------------------= if minus { minus = product.low .formTwosComplementSubsequence(minus) @@ -136,7 +136,7 @@ extension NBKDoubleWidth where High == High.Magnitude { /// - Note: The `high` and `low` parts contain the entire `overflow` from `low` to `high`. /// @_disfavoredOverload @inlinable public func multipliedFullWidth(by other: Digit, adding carry: Digit) -> HL { - var product = HL(UInt.zero, self) + var product = HL(0 as UInt, self) product.high = product.low.multiplyFullWidth(by: other, add: carry) return product as HL } diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text.swift index 41ed12e1..8260d281 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text.swift @@ -42,7 +42,7 @@ extension NBKDoubleWidth { let radix = NBK.AnyRadixUIntRoot(radix) let alphabet = NBK.MaxRadixAlphabetEncoder(uppercase: uppercase) let prefix = NBK.UnsafeUTF8(start: minus, count: Int(bit: self.isLessThanZero)) - let suffix = NBK.UnsafeUTF8(start: nil, count: Int.zero) + let suffix = NBK.UnsafeUTF8(start: nil, count: 0 as Int) return self.magnitude.description(radix: radix, alphabet: alphabet, prefix: prefix, suffix: suffix) } } diff --git a/Tests/NBKCoreKitTests/Private/NBK+Limbs+Addition.swift b/Tests/NBKCoreKitTests/Private/NBK+Limbs+Addition.swift index 4f8372b5..d281d929 100644 --- a/Tests/NBKCoreKitTests/Private/NBK+Limbs+Addition.swift +++ b/Tests/NBKCoreKitTests/Private/NBK+Limbs+Addition.swift @@ -108,7 +108,7 @@ file: StaticString = #file, line: UInt = #line) { brr: do { var lhs = lhs, rhs = rhs let min = NBK.incrementSufficientUnsignedIntegerInIntersection(&lhs, by: rhs, plus: false, at: index) - let sfx = Array(repeating: UInt.zero, count: lhs.suffix(from: min.index).count) + let sfx = Array(repeating: 0 as UInt, count: lhs.suffix(from: min.index).count) let max = NBK.incrementSufficientUnsignedIntegerInIntersection(&lhs, by: sfx, plus: min.overflow, at: min.index) XCTAssertEqual(lhs, result, file: file, line: line) XCTAssertEqual(max.overflow, overflow, file: file, line: line) @@ -156,7 +156,7 @@ file: StaticString = #file, line: UInt = #line) { brr: do { var lhs = lhs, rhs = rhs let min = NBK.incrementSufficientUnsignedIntegerInIntersection(&lhs, by: rhs, plus: false, at: index) - let sfx = Array(repeating: UInt.zero, count: lhs.suffix(from: min.index).count) + let sfx = Array(repeating: 0 as UInt, count: lhs.suffix(from: min.index).count) let max = NBK.incrementSufficientUnsignedIntegerInIntersection(&lhs, by: sfx, plus: min.overflow, at: min.index) XCTAssertEqual(lhs, result, file: file, line: line) XCTAssertEqual(max.overflow, overflow, file: file, line: line) diff --git a/Tests/NBKCoreKitTests/Private/NBK+Limbs+Comparisons.swift b/Tests/NBKCoreKitTests/Private/NBK+Limbs+Comparisons.swift index 0512f3af..cbc9fde4 100644 --- a/Tests/NBKCoreKitTests/Private/NBK+Limbs+Comparisons.swift +++ b/Tests/NBKCoreKitTests/Private/NBK+Limbs+Comparisons.swift @@ -182,7 +182,7 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual(NBK.compareStrictSignedInteger(lhs, to: rhs, at: index), signum, file: file, line: line) }} //=------------------------------------------= - NBKAssertCompareStrictSignedInteger(lhs, Array(repeating: UInt.zero, count: index) + rhs, signum, file: file, line: line) + NBKAssertCompareStrictSignedInteger(lhs, Array(repeating: 0 as UInt, count: index) + rhs, signum, file: file, line: line) } private func NBKAssertCompareLenientUnsignedInteger( @@ -204,7 +204,7 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual(NBK.compareLenientUnsignedInteger(lhs, to: rhs, at: index), signum, file: file, line: line) }} //=------------------------------------------= - NBKAssertCompareLenientUnsignedInteger(lhs, Array(repeating: UInt.zero, count: index) + rhs, signum, file: file, line: line) + NBKAssertCompareLenientUnsignedInteger(lhs, Array(repeating: 0 as UInt, count: index) + rhs, signum, file: file, line: line) } #endif diff --git a/Tests/NBKCoreKitTests/Private/NBK+Limbs+Subtraction.swift b/Tests/NBKCoreKitTests/Private/NBK+Limbs+Subtraction.swift index c2b25395..0aa8e812 100644 --- a/Tests/NBKCoreKitTests/Private/NBK+Limbs+Subtraction.swift +++ b/Tests/NBKCoreKitTests/Private/NBK+Limbs+Subtraction.swift @@ -172,7 +172,7 @@ file: StaticString = #file, line: UInt = #line) { brr: do { var lhs = lhs, rhs = rhs let min = NBK.decrementSufficientUnsignedIntegerInIntersection(&lhs, by: rhs, plus: false, at: index) - let sfx = Array(repeating: UInt.zero, count: lhs.suffix(from: min.index).count) + let sfx = Array(repeating: 0 as UInt, count: lhs.suffix(from: min.index).count) let max = NBK.decrementSufficientUnsignedIntegerInIntersection(&lhs, by: sfx, plus: min.overflow, at: min.index) XCTAssertEqual(lhs, result, file: file, line: line) XCTAssertEqual(max.overflow, overflow, file: file, line: line) @@ -220,7 +220,7 @@ file: StaticString = #file, line: UInt = #line) { brr: do { var lhs = lhs, rhs = rhs let min = NBK.decrementSufficientUnsignedIntegerInIntersection(&lhs, by: rhs, plus: false, at: index) - let sfx = Array(repeating: UInt.zero, count: lhs.suffix(from: min.index).count) + let sfx = Array(repeating: 0 as UInt, count: lhs.suffix(from: min.index).count) let max = NBK.decrementSufficientUnsignedIntegerInIntersection(&lhs, by: sfx, plus: min.overflow, at: min.index) XCTAssertEqual(lhs, result, file: file, line: line) XCTAssertEqual(max.overflow, overflow, file: file, line: line) From a5ab8e6362c1a15d83c59a62559ff996efaa7ced Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Fri, 1 Sep 2023 10:48:41 +0200 Subject: [PATCH 088/111] No OffsetIndexed protocol (#76). --- README.md | 1 - Sources/NBKCoreKit/Models/NBKTwinHeaded.swift | 4 +- Sources/NBKCoreKit/NBKOffsetIndexed.swift | 52 ----------------- .../NBKCoreKit/Private/NBK+Collection.swift | 16 ++++++ .../NBKDoubleWidth+Division.swift | 2 +- .../NBKDoubleWidth+Words.swift | 2 +- .../NBKDoubleWidthKit/NBKDoubleWidth.swift | 2 +- .../Documentation.docc/Documentation.md | 2 - Tests/NBKCoreKitTests/NBKOffsetIndexed.swift | 57 ------------------- .../Private/NBK+Collection.swift | 36 ++++++++++++ 10 files changed, 57 insertions(+), 117 deletions(-) delete mode 100644 Sources/NBKCoreKit/NBKOffsetIndexed.swift delete mode 100644 Tests/NBKCoreKitTests/NBKOffsetIndexed.swift diff --git a/README.md b/README.md index f305a34f..294f8144 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,6 @@ A new protocol hierarchy that refines Swift's standard library. - [NBKBitPatternConvertible](Sources/NBKCoreKit/NBKBitPatternConvertible.swift) - [NBKCoreInteger](Sources/NBKCoreKit/NBKCoreInteger.swift) - [NBKFixedWidthInteger](Sources/NBKCoreKit/NBKFixedWidthInteger.swift) -- [NBKOffsetIndexed](Sources/NBKCoreKit/NBKOffsetIndexed.swift) - [NBKSignedInteger](Sources/NBKCoreKit/NBKSignedInteger.swift) - [NBKUnsignedInteger](Sources/NBKCoreKit/NBKUnsignedInteger.swift) diff --git a/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift b/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift index dbcdbbc9..260e305a 100644 --- a/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift +++ b/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift @@ -12,7 +12,7 @@ //*============================================================================* /// A collection that iterates forwards or backwards in a dynamic but branchless way. -@frozen public struct NBKTwinHeaded: NBKOffsetIndexed where Base: RandomAccessCollection { +@frozen public struct NBKTwinHeaded: RandomAccessCollection where Base: RandomAccessCollection { public typealias Base = Base @@ -250,7 +250,7 @@ extension NBKTwinHeaded { } @inlinable public func index(_ index: Int, offsetBy distance: Int, limitedBy limit: Int) -> Int? { - NBK.offset(index, by: distance, limit: limit) + NBK.arrayIndex(index, offsetBy: distance, limitedBy: limit) } } diff --git a/Sources/NBKCoreKit/NBKOffsetIndexed.swift b/Sources/NBKCoreKit/NBKOffsetIndexed.swift deleted file mode 100644 index 87cc181b..00000000 --- a/Sources/NBKCoreKit/NBKOffsetIndexed.swift +++ /dev/null @@ -1,52 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -//*============================================================================* -// MARK: * NBK x Offset Indexed -//*============================================================================* - -/// A random access collection with indices from `zero` to `count`. -/// -/// ### Defaults -/// -/// The defaults provided depend on an independent `count` accessor. -/// -public protocol NBKOffsetIndexed: RandomAccessCollection where Indices == Range { } - -//=----------------------------------------------------------------------------= -// MARK: + Algorithms -//=----------------------------------------------------------------------------= - -extension NBK { - - //=------------------------------------------------------------------------= - // MARK: Utilities - //=------------------------------------------------------------------------= - - /// Returns the array-like result of `index(_:offsetBy:limitedBy:)`. - @inlinable public static func offset(_ index: Int, by distance: Int, limit: Int) -> Int? { - let distanceLimit = limit - index - - guard distance >= 0 as Int - ? distance <= distanceLimit || distanceLimit < 0 as Int - : distance >= distanceLimit || distanceLimit > 0 as Int - else { return nil } - - return index + distance as Int - } -} - -//*============================================================================* -// MARK: * NBK x Offset Indexed x Swift -//*============================================================================* - -extension Array: NBKOffsetIndexed { } -extension ContiguousArray: NBKOffsetIndexed { } -extension UnsafeBufferPointer: NBKOffsetIndexed { } -extension UnsafeMutableBufferPointer: NBKOffsetIndexed { } diff --git a/Sources/NBKCoreKit/Private/NBK+Collection.swift b/Sources/NBKCoreKit/Private/NBK+Collection.swift index 0875e484..a057dbfe 100644 --- a/Sources/NBKCoreKit/Private/NBK+Collection.swift +++ b/Sources/NBKCoreKit/Private/NBK+Collection.swift @@ -68,4 +68,20 @@ extension NBK { collection = collection.prefix(upTo: suffix.startIndex) return suffix as T } + + //=------------------------------------------------------------------------= + // MARK: Utilities x Array Index + //=------------------------------------------------------------------------= + + /// Returns the array-like result of `index(_:offsetBy:limitedBy:)`. + @inlinable public static func arrayIndex(_ index: Int, offsetBy distance: Int, limitedBy limit: Int) -> Int? { + let distanceLimit = limit - index + + guard distance >= 0 as Int + ? distance <= distanceLimit || distanceLimit < 0 as Int + : distance >= distanceLimit || distanceLimit > 0 as Int + else { return nil } + + return index + distance as Int + } } diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Division.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Division.swift index 6cb22dde..902daec4 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Division.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Division.swift @@ -142,7 +142,7 @@ extension NBKDoubleWidth where High == High.Magnitude { //=--------------------------------------= let comparison: Int = rhs.compared(to: lhs) if comparison >= 0 { - return comparison.isZero ? QR(1, Self.zero) : QR(Self.zero, lhs) + return comparison.isZero ? QR(1, 0) : QR(0, lhs) } //=--------------------------------------= // division: 1111 diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words.swift index d9b9caa4..d5b38585 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Words.swift @@ -96,7 +96,7 @@ extension NBKDoubleWidth { } @inlinable public func index(_ index: Int, offsetBy distance: Int, limitedBy limit: Int) -> Int? { - NBK.offset(index, by: distance, limit: limit) + NBK.arrayIndex(index, offsetBy: distance, limitedBy: limit) } } diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift index 77d5b974..255853de 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift @@ -88,7 +88,7 @@ import NBKCoreKit /// - Note: You can use `StaticString` until `StaticBigInt` becomes available. /// @frozen public struct NBKDoubleWidth: ExpressibleByStringLiteral, -NBKFixedWidthInteger, MutableCollection, NBKOffsetIndexed where +NBKFixedWidthInteger, MutableCollection, RandomAccessCollection where High: NBKFixedWidthInteger, High.Digit: NBKCoreInteger { /// The most significant half of this type. diff --git a/Sources/Numberick/Documentation.docc/Documentation.md b/Sources/Numberick/Documentation.docc/Documentation.md index 75fd94b8..3b3e5d08 100644 --- a/Sources/Numberick/Documentation.docc/Documentation.md +++ b/Sources/Numberick/Documentation.docc/Documentation.md @@ -12,7 +12,6 @@ A new protocol hierarchy that refines Swift's standard library. - ``NBKBitPatternConvertible`` - ``NBKCoreInteger`` - ``NBKFixedWidthInteger`` -- ``NBKOffsetIndexed`` - ``NBKSignedInteger`` - ``NBKUnsignedInteger`` @@ -109,7 +108,6 @@ Int256(5) % Int(5), UInt256(5) % UInt(5) - ``NBKBitPatternConvertible`` - ``NBKCoreInteger`` - ``NBKFixedWidthInteger`` -- ``NBKOffsetIndexed`` - ``NBKSignedInteger`` - ``NBKUnsignedInteger`` diff --git a/Tests/NBKCoreKitTests/NBKOffsetIndexed.swift b/Tests/NBKCoreKitTests/NBKOffsetIndexed.swift deleted file mode 100644 index d746f734..00000000 --- a/Tests/NBKCoreKitTests/NBKOffsetIndexed.swift +++ /dev/null @@ -1,57 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if DEBUG - -import NBKCoreKit -import XCTest - -//*============================================================================* -// MARK: * NBK x Offset Index -//*============================================================================* - -final class NBKOffsetIndexedTests: XCTestCase { - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testIndexOffsetByLimitedBy() { - NBKAssertIndexOffsetByLimitedBy(1, 2, 2, nil) - NBKAssertIndexOffsetByLimitedBy(1, 1, 2, 2) - NBKAssertIndexOffsetByLimitedBy(1, 0, 2, 1) - NBKAssertIndexOffsetByLimitedBy(1, -1, 2, 0) - NBKAssertIndexOffsetByLimitedBy(1, -2, 2, -1) - - NBKAssertIndexOffsetByLimitedBy(2, 2, 2, nil) - NBKAssertIndexOffsetByLimitedBy(2, 1, 2, nil) - NBKAssertIndexOffsetByLimitedBy(2, 0, 2, 2) - NBKAssertIndexOffsetByLimitedBy(2, -1, 2, nil) - NBKAssertIndexOffsetByLimitedBy(2, -2, 2, nil) - - NBKAssertIndexOffsetByLimitedBy(3, 2, 2, 5) - NBKAssertIndexOffsetByLimitedBy(3, 1, 2, 4) - NBKAssertIndexOffsetByLimitedBy(3, 0, 2, 3) - NBKAssertIndexOffsetByLimitedBy(3, -1, 2, 2) - NBKAssertIndexOffsetByLimitedBy(3, -2, 2, nil) - } -} - -//*============================================================================* -// MARK: * NBK x Offset Indexed x Assertions -//*============================================================================* - -private func NBKAssertIndexOffsetByLimitedBy( -_ index: Int, _ distance: Int, _ limit: Int, _ expectation: Int?, -file: StaticString = #file, line: UInt = #line) { - XCTAssertEqual(NBK .offset(index, by: distance, limit: limit), expectation, file: file, line: line) - XCTAssertEqual([Int]().index(index, offsetBy: distance, limitedBy: limit), expectation, file: file, line: line) -} - -#endif diff --git a/Tests/NBKCoreKitTests/Private/NBK+Collection.swift b/Tests/NBKCoreKitTests/Private/NBK+Collection.swift index c8337fc9..ecc88a34 100644 --- a/Tests/NBKCoreKitTests/Private/NBK+Collection.swift +++ b/Tests/NBKCoreKitTests/Private/NBK+Collection.swift @@ -82,6 +82,30 @@ final class NBKTestsOnCollection: XCTestCase { NBKAssertRemoveSuffixMaxLength(8, [ ], [1, 2, 3, 4, 5]) NBKAssertRemoveSuffixMaxLength(9, [ ], [1, 2, 3, 4, 5]) } + + //=------------------------------------------------------------------------= + // MARK: Tests x Array Index + //=------------------------------------------------------------------------= + + func testArrayIndexOffsetByLimitedBy() { + NBKAssertArrayIndexOffsetByLimitedBy(1, 2, 2, nil) + NBKAssertArrayIndexOffsetByLimitedBy(1, 1, 2, 2) + NBKAssertArrayIndexOffsetByLimitedBy(1, 0, 2, 1) + NBKAssertArrayIndexOffsetByLimitedBy(1, -1, 2, 0) + NBKAssertArrayIndexOffsetByLimitedBy(1, -2, 2, -1) + + NBKAssertArrayIndexOffsetByLimitedBy(2, 2, 2, nil) + NBKAssertArrayIndexOffsetByLimitedBy(2, 1, 2, nil) + NBKAssertArrayIndexOffsetByLimitedBy(2, 0, 2, 2) + NBKAssertArrayIndexOffsetByLimitedBy(2, -1, 2, nil) + NBKAssertArrayIndexOffsetByLimitedBy(2, -2, 2, nil) + + NBKAssertArrayIndexOffsetByLimitedBy(3, 2, 2, 5) + NBKAssertArrayIndexOffsetByLimitedBy(3, 1, 2, 4) + NBKAssertArrayIndexOffsetByLimitedBy(3, 0, 2, 3) + NBKAssertArrayIndexOffsetByLimitedBy(3, -1, 2, 2) + NBKAssertArrayIndexOffsetByLimitedBy(3, -2, 2, nil) + } } //*============================================================================* @@ -146,4 +170,16 @@ file: StaticString = #file, line: UInt = #line) { XCTAssertEqual(Array(extraction), suffix, file: file, line: line) } +//=----------------------------------------------------------------------------= +// MARK: + Array Index +//=----------------------------------------------------------------------------= + +private func NBKAssertArrayIndexOffsetByLimitedBy( +_ index: Int, _ distance: Int, _ limit: Int, _ expectation: Int?, +file: StaticString = #file, line: UInt = #line) { + + XCTAssertEqual(NBK.arrayIndex(index, offsetBy: distance, limitedBy: limit), expectation, file: file, line: line) + XCTAssertEqual([Int]( ).index(index, offsetBy: distance, limitedBy: limit), expectation, file: file, line: line) +} + #endif From d1896e3440c65be8d7b69752e75cad1b237af89f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Fri, 1 Sep 2023 16:45:58 +0200 Subject: [PATCH 089/111] [NBKCoreKit] Reworked merge/split sequences (#73). --- README.md | 1 - .../NBKCoreKit/Models/NBKMajorInteger.swift | 129 ++++++ .../Models/NBKMajorOrMinorInteger.swift | 371 +++--------------- .../NBKCoreKit/Models/NBKMinorInteger.swift | 119 ++++++ .../Documentation.docc/Documentation.md | 2 - .../Models/NBKMajorOrMinorInteger.swift | 26 +- 6 files changed, 323 insertions(+), 325 deletions(-) create mode 100644 Sources/NBKCoreKit/Models/NBKMajorInteger.swift create mode 100644 Sources/NBKCoreKit/Models/NBKMinorInteger.swift diff --git a/README.md b/README.md index 294f8144..fa81141d 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,6 @@ A new protocol hierarchy that refines Swift's standard library. - [NBKMajorInteger](Sources/NBKCoreKit/Models/NBKMajorOrMinorInteger.swift) - [NBKMajorOrMinorInteger](Sources/NBKCoreKit/Models/NBKMajorOrMinorInteger.swift) - [NBKMinorInteger](Sources/NBKCoreKit/Models/NBKMajorOrMinorInteger.swift) -- [NBKMinorIntegerOfOne](Sources/NBKCoreKit/Models/NBKMajorOrMinorInteger.swift) - [NBKTwinHeaded](Sources/NBKCoreKit/Models/NBKTwinHeaded.swift) ## [NBKDoubleWidthKit][DBL/D] ([Sources][DBL/S], [Tests][DBL/T], [Benchmarks][DBL/B]) diff --git a/Sources/NBKCoreKit/Models/NBKMajorInteger.swift b/Sources/NBKCoreKit/Models/NBKMajorInteger.swift new file mode 100644 index 00000000..d6832dd0 --- /dev/null +++ b/Sources/NBKCoreKit/Models/NBKMajorInteger.swift @@ -0,0 +1,129 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +//*============================================================================* +// MARK: * NBK x Major Integer +//*============================================================================* + +/// A sequence that merges components of an un/signed integer sequence. +/// +/// ### Binary Integer Order +/// +/// This sequence is ordered like a binary integer, meaning it merges and splits +/// its components from least significant to most. You can reorder it by reversing +/// the input, the output, or both. +/// +@frozen public struct NBKMajorInteger: RandomAccessCollection where +Element: NBKCoreInteger, Base: RandomAccessCollection, Base.Element: NBKCoreInteger { + + @inlinable static var ratio: Int { Self.Element.bitWidth / Base.Element.bitWidth } + + //=------------------------------------------------------------------------= + // MARK: State + //=------------------------------------------------------------------------= + + @usableFromInline let base: Base + @usableFromInline let sign: Element + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + // TODO: documentation + @inlinable public init(_ minorLimbs: Base, isSigned: Bool = false, as majorLimb: Element.Type = Element.self) { + //=--------------------------------------= + Swift.assert(Self.Element.bitWidth.isPowerOf2) // core + Swift.assert(Base.Element.bitWidth.isPowerOf2) // core + precondition(Self.Element.bitWidth >= Base.Element.bitWidth) + //=--------------------------------------= + self.base = minorLimbs + let bit = isSigned && self.base.last?.mostSignificantBit == true + self.sign = Self.Element(repeating: bit) + } + + //=------------------------------------------------------------------------= + // MARK: Accessors + //=------------------------------------------------------------------------= + + @inlinable public var count: Int { + let division = base.count.quotientAndRemainder(dividingBy: Self.ratio) + return division.quotient + Int(bit: !division.remainder.isZero) + } + + @inlinable public subscript(index: Int) -> Element { + var shift = 0 as Int + var major = 0 as Self.Element + //=--------------------------------------= + var baseIndex = self.base.index(self.base.startIndex, offsetBy: index * Self.ratio) + while baseIndex < self.base.endIndex && shift < Self.Element.bitWidth { + major |= Self.Element(truncatingIfNeeded: Base.Element.Magnitude(bitPattern: self.base[baseIndex])) &<< shift + shift += Base.Element.bitWidth as Int + self.base.formIndex(after: &baseIndex) + } + //=--------------------------------------= + if shift < Self.Element.bitWidth { major |= self.sign &<< shift } + //=--------------------------------------= + return major + } +} + +//=----------------------------------------------------------------------------= +// MARK: + Collection +//=----------------------------------------------------------------------------= + +extension NBKMajorInteger { + + //=------------------------------------------------------------------------= + // MARK: Accessors + //=------------------------------------------------------------------------= + + @inlinable public var startIndex: Int { + 0 as Int + } + + @inlinable public var endIndex: Int { + self.count + } + + @inlinable public var indices: Range { + Range(uncheckedBounds:(0 as Int, self.count)) + } + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + @inlinable public func distance(from start: Int, to end: Int) -> Int { + end - start + } + + @inlinable public func index(after index: Int) -> Int { + index + 1 as Int + } + + @inlinable public func formIndex(after index: inout Int) { + index += 1 as Int + } + + @inlinable public func index(before index: Int) -> Int { + index - 1 as Int + } + + @inlinable public func formIndex(before index: inout Int) { + index -= 1 as Int + } + + @inlinable public func index(_ index: Int, offsetBy distance: Int) -> Int { + index + distance + } + + @inlinable public func index(_ index: Int, offsetBy distance: Int, limitedBy limit: Int) -> Int? { + NBK.arrayIndex(index, offsetBy: distance, limitedBy: limit) + } +} diff --git a/Sources/NBKCoreKit/Models/NBKMajorOrMinorInteger.swift b/Sources/NBKCoreKit/Models/NBKMajorOrMinorInteger.swift index b6c58385..68e3c665 100644 --- a/Sources/NBKCoreKit/Models/NBKMajorOrMinorInteger.swift +++ b/Sources/NBKCoreKit/Models/NBKMajorOrMinorInteger.swift @@ -19,380 +19,111 @@ /// its components from least significant to most. You can reorder it by reversing /// the input, the output, or both. /// -@frozen public struct NBKMajorOrMinorInteger: Sequence where -Limb: NBKCoreInteger, Source: Sequence, Source.Element: NBKCoreInteger { +@frozen public struct NBKMajorOrMinorInteger: RandomAccessCollection where +Element: NBKCoreInteger, Base: RandomAccessCollection, Base.Element: NBKCoreInteger { - public typealias Source = Source + public typealias Base = Base - public typealias MajorLimbs = NBKMajorInteger - - public typealias MinorLimbs = NBKMinorInteger + public typealias MajorLimbs = NBKMajorInteger + public typealias MinorLimbs = NBKMinorInteger + //=------------------------------------------------------------------------= // MARK: State //=------------------------------------------------------------------------= - // NOTE: Two parallel options appear to be faster than a combined enum. - //=------------------------------------------------------------------------= - @usableFromInline let minorLimbs: MinorLimbs? - @usableFromInline let majorLimbs: MajorLimbs? + @usableFromInline let storage: Storage //=------------------------------------------------------------------------= // MARK: Initializers //=------------------------------------------------------------------------= /// Creates a sequence of the given type, from an un/signed source. - @inlinable public init(_ source: Source, isSigned: Bool = false, as limb: Limb.Type = Limb.self) { - if Limb.bitWidth < Source.Element.bitWidth { - self.minorLimbs = MinorLimbs(source) - self.majorLimbs = nil - } else { - self.minorLimbs = nil - self.majorLimbs = MajorLimbs(source, isSigned: isSigned) - } - } - - //=------------------------------------------------------------------------= - // MARK: Utilities - //=------------------------------------------------------------------------= - - // TODO: documentation - @inlinable public var underestimatedCount: Int { - if Limb.bitWidth < Source.Element.bitWidth { - return self.minorLimbs!.underestimatedCount - } else { - return self.majorLimbs!.underestimatedCount - } - } - - @inlinable public func makeIterator() -> Iterator { - if Limb.bitWidth < Source.Element.bitWidth { - return Iterator(minorLimbs: self.minorLimbs!.makeIterator()) + @inlinable public init(_ source: Base, isSigned: Bool = false, as limb: Element.Type = Element.self) { + if Element.bitWidth > Base.Element.bitWidth { + self.storage = .majorLimbs(MajorLimbs(source, isSigned: isSigned)) } else { - return Iterator(majorLimbs: self.majorLimbs!.makeIterator()) - } - } - - //*====================================================================* - // MARK: * Iterator - //*====================================================================* - - // TODO: documentation - @frozen public struct Iterator: IteratorProtocol { - - //=------------------------------------------------------------------------= - // MARK: State - //=------------------------------------------------------------------------= - - @usableFromInline var minorLimbs: MinorLimbs.Iterator? - @usableFromInline var majorLimbs: MajorLimbs.Iterator? - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - @inlinable init(minorLimbs: MinorLimbs.Iterator? = nil, majorLimbs: MajorLimbs.Iterator? = nil) { - self.minorLimbs = minorLimbs - self.majorLimbs = majorLimbs - } - - //=------------------------------------------------------------------------= - // MARK: Utilities - //=------------------------------------------------------------------------= - - @inlinable public mutating func next() -> Limb? { - if Limb.bitWidth < Source.Element.bitWidth { - return self.minorLimbs!.next() - } else { - return self.majorLimbs!.next() - } + self.storage = .minorLimbs(MinorLimbs(source, isSigned: isSigned)) } } -} - -//*============================================================================* -// MARK: * NBK x Major Integer -//*============================================================================* - -/// A sequence that merges components of an un/signed integer sequence. -/// -/// ### Binary Integer Order -/// -/// This sequence is ordered like a binary integer, meaning it merges and splits -/// its components from least significant to most. You can reorder it by reversing -/// the input, the output, or both. -/// -@frozen public struct NBKMajorInteger: Sequence where -MajorLimb: NBKCoreInteger, MinorLimbs: Sequence, MinorLimbs.Element: NBKCoreInteger { - - public typealias MajorLimb = MajorLimb - - public typealias MinorLimb = MinorLimbs.Element - - //=------------------------------------------------------------------------= - // MARK: State - //=------------------------------------------------------------------------= - - @usableFromInline let minorLimbs: MinorLimbs - @usableFromInline let minorLimbsIsSigned: Bool - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - // TODO: documentation - @inlinable public init(_ minorLimbs: MinorLimbs, isSigned: Bool = false, as majorLimb: MajorLimb.Type = MajorLimb.self) { - //=--------------------------------------= - precondition(MinorLimb.bitWidth.isPowerOf2) - precondition(MajorLimb.bitWidth.isPowerOf2) - precondition(MinorLimb.bitWidth <= MajorLimb.bitWidth) - //=--------------------------------------= - self.minorLimbs = minorLimbs - self.minorLimbsIsSigned = isSigned - } //=------------------------------------------------------------------------= - // MARK: Utilities + // MARK: Accessors //=------------------------------------------------------------------------= - /// Returns the exact count when `minorLimbs.underestimatedCount` does. - @inlinable public var underestimatedCount: Int { - let ratio = MajorLimb.bitWidth / MinorLimb.bitWidth - let division = minorLimbs.underestimatedCount.quotientAndRemainder(dividingBy: ratio) - return division.quotient + Int(bit: !division.remainder.isZero) + @inlinable public var count: Int { + switch storage { + case let .majorLimbs(limbs): return limbs.count + case let .minorLimbs(limbs): return limbs.count } } - @inlinable public func makeIterator() -> Iterator { - Iterator(self.minorLimbs.makeIterator(), isSigned: self.minorLimbsIsSigned) + @inlinable public subscript(index: Int) -> Element { + switch storage { + case let .majorLimbs(limbs): return limbs[index] + case let .minorLimbs(limbs): return limbs[index] } } //*========================================================================* - // MARK: * Iterator + // MARK: * Storage //*========================================================================* - // TODO: documentation - @frozen public struct Iterator: IteratorProtocol { - - //=------------------------------------------------------------------------= - // MARK: State - //=------------------------------------------------------------------------= - - @usableFromInline var minorLimbs: MinorLimbs.Iterator - @usableFromInline let minorLimbsIsSigned: Bool - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - @inlinable init(_ minorLimbs: MinorLimbs.Iterator, isSigned: Bool) { - self.minorLimbs = minorLimbs - self.minorLimbsIsSigned = isSigned - } - - //=------------------------------------------------------------------------= - // MARK: Utilities - //=------------------------------------------------------------------------= - - @inlinable public mutating func next() -> MajorLimb? { - var majorLimb = MajorLimb.zero - var majorLimbShift = 0 as Int - var minorLimb = MinorLimb.Magnitude.zero - - while let next = self.minorLimbs.next() { - minorLimb = MinorLimb.Magnitude(bitPattern: next) - majorLimb |= MajorLimb(truncatingIfNeeded: minorLimb) &<< majorLimbShift - - do { majorLimbShift += MinorLimb.bitWidth } - guard majorLimbShift < MajorLimb.bitWidth else { return majorLimb } - } - - guard !majorLimbShift.isZero else { return nil } - let bit: Bool = self.minorLimbsIsSigned && minorLimb.mostSignificantBit - return majorLimb | MajorLimb(repeating: bit) &<< majorLimbShift - } + @frozen @usableFromInline enum Storage { + case majorLimbs(MajorLimbs) + case minorLimbs(MinorLimbs) } } -//*============================================================================* -// MARK: * NBK x Minor Integer -//*============================================================================* +//=----------------------------------------------------------------------------= +// MARK: + Collection +//=----------------------------------------------------------------------------= -/// A sequence that splits components of an un/signed integer sequence. -/// -/// ### Binary Integer Order -/// -/// This sequence is ordered like a binary integer, meaning it merges and splits -/// its components from least significant to most. You can reorder it by reversing -/// the input, the output, or both. -/// -@frozen public struct NBKMinorInteger: Sequence where -MinorLimb: NBKCoreInteger, MajorLimbs: Sequence, MajorLimbs.Element: NBKCoreInteger { - - public typealias MajorLimb = MajorLimbs.Element - - public typealias MinorLimb = MinorLimb - - @usableFromInline typealias MinorLimbsOfOne = NBKMinorIntegerOfOne +extension NBKMajorOrMinorInteger { //=------------------------------------------------------------------------= - // MARK: State + // MARK: Accessors //=------------------------------------------------------------------------= - @usableFromInline let majorLimbs: MajorLimbs + @inlinable public var startIndex: Int { + 0 as Int + } - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= + @inlinable public var endIndex: Int { + self.count + } - // TODO: documentation - @inlinable public init(_ majorLimbs: MajorLimbs, as minorLimb: MinorLimb.Type = MinorLimb.self) { - //=--------------------------------------= - precondition(MinorLimb.bitWidth.isPowerOf2) - precondition(MajorLimb.bitWidth.isPowerOf2) - precondition(MinorLimb.bitWidth <= MajorLimb.bitWidth) - //=--------------------------------------= - self.majorLimbs = majorLimbs + @inlinable public var indices: Range { + Range(uncheckedBounds:(0 as Int, self.count)) } //=------------------------------------------------------------------------= // MARK: Utilities //=------------------------------------------------------------------------= - /// Returns the exact count when `majorLimbs.underestimatedCount` does. - @inlinable public var underestimatedCount: Int { - MajorLimb.bitWidth / MinorLimb.bitWidth * self.majorLimbs.underestimatedCount + @inlinable public func distance(from start: Int, to end: Int) -> Int { + end - start } - @inlinable public func makeIterator() -> Iterator { - Iterator(self.majorLimbs.makeIterator()) + @inlinable public func index(after index: Int) -> Int { + index + 1 as Int } - //*========================================================================* - // MARK: * Iterator - //*========================================================================* - - // TODO: documentation - @frozen public struct Iterator: IteratorProtocol { - - //=------------------------------------------------------------------------= - // MARK: State - //=------------------------------------------------------------------------= - - @usableFromInline var majorLimbs: MajorLimbs.Iterator - @usableFromInline var minorLimbs: MinorLimbsOfOne.Iterator? - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - @inlinable init(_ majorLimbs: MajorLimbs.Iterator) { - self.majorLimbs = majorLimbs - self.minorLimbs = nil - } - - //=------------------------------------------------------------------------= - // MARK: Utilities - //=------------------------------------------------------------------------= - - @inlinable mutating public func next() -> MinorLimb? { - repeat { - - if let minorLimb = self.minorLimbs?.next() { - return minorLimb - } else if let majorLimb = self.majorLimbs.next() { - self.minorLimbs = MinorLimbsOfOne(majorLimb).makeIterator() - } else { - return nil - } - - } while true - } + @inlinable public func formIndex(after index: inout Int) { + index += 1 as Int } -} - -//*============================================================================* -// MARK: * NBK x Minor Integer Of One -//*============================================================================* - -/// A sequence that splits components of an un/signed integer sequence. -/// -/// ### Binary Integer Order -/// -/// This sequence is ordered like a binary integer, meaning it merges and splits -/// its components from least significant to most. You can reorder it by reversing -/// the input, the output, or both. -/// -@frozen public struct NBKMinorIntegerOfOne: -Sequence where MinorLimb: NBKCoreInteger, MajorLimb: NBKCoreInteger { - - public typealias MajorLimb = MajorLimb - - public typealias MinorLimb = MinorLimb - - //=------------------------------------------------------------------------= - // MARK: State - //=------------------------------------------------------------------------= - - @usableFromInline let majorLimb: MajorLimb - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - // TODO: documentation - @inlinable public init(_ majorLimb: MajorLimb, as minorLimb: MinorLimb.Type = MinorLimb.self) { - //=--------------------------------------= - precondition(MinorLimb.bitWidth.isPowerOf2) - precondition(MajorLimb.bitWidth.isPowerOf2) - precondition(MinorLimb.bitWidth <= MajorLimb.bitWidth) - //=--------------------------------------= - self.majorLimb = majorLimb + @inlinable public func index(before index: Int) -> Int { + index - 1 as Int } - //=------------------------------------------------------------------------= - // MARK: Utilities - //=------------------------------------------------------------------------= - - /// Returns the exact count. - @inlinable public var underestimatedCount: Int { - MajorLimb.bitWidth / MinorLimb.bitWidth + @inlinable public func formIndex(before index: inout Int) { + index -= 1 as Int } - @inlinable public func makeIterator() -> Iterator { - Iterator(self.majorLimb) + @inlinable public func index(_ index: Int, offsetBy distance: Int) -> Int { + index + distance } - //*========================================================================* - // MARK: * Iterator - //*========================================================================* - - // TODO: documentation - @frozen public struct Iterator: IteratorProtocol { - - //=--------------------------------------------------------------------= - // MARK: State - //=--------------------------------------------------------------------= - - @usableFromInline let majorLimb: MajorLimb - @usableFromInline var majorLimbShift: Int - - //=--------------------------------------------------------------------= - // MARK: Initializers - //=--------------------------------------------------------------------= - - @inlinable init(_ majorLimb: MajorLimb) { - self.majorLimb = majorLimb - self.majorLimbShift = 0 as Int - } - - //=--------------------------------------------------------------------= - // MARK: Utilities - //=--------------------------------------------------------------------= - - @inlinable public mutating func next() -> MinorLimb? { - guard self.majorLimbShift < MajorLimb.bitWidth else { return nil } - defer{ self.majorLimbShift += MinorLimb.bitWidth } - return MinorLimb(truncatingIfNeeded: self.majorLimb &>> self.majorLimbShift) - } + @inlinable public func index(_ index: Int, offsetBy distance: Int, limitedBy limit: Int) -> Int? { + NBK.arrayIndex(index, offsetBy: distance, limitedBy: limit) } } diff --git a/Sources/NBKCoreKit/Models/NBKMinorInteger.swift b/Sources/NBKCoreKit/Models/NBKMinorInteger.swift new file mode 100644 index 00000000..bb68dff5 --- /dev/null +++ b/Sources/NBKCoreKit/Models/NBKMinorInteger.swift @@ -0,0 +1,119 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +//*============================================================================* +// MARK: * NBK x Minor Integer +//*============================================================================* + +/// A sequence that splits components of an un/signed integer sequence. +/// +/// ### Binary Integer Order +/// +/// This sequence is ordered like a binary integer, meaning it merges and splits +/// its components from least significant to most. You can reorder it by reversing +/// the input, the output, or both. +/// +@frozen public struct NBKMinorInteger: RandomAccessCollection where +Element: NBKCoreInteger, Base: RandomAccessCollection, Base.Element: NBKCoreInteger { + + @inlinable static var ratio: Int { Base.Element.bitWidth / Self.Element.bitWidth } + + //=------------------------------------------------------------------------= + // MARK: State + //=------------------------------------------------------------------------= + + @usableFromInline let base: Base + @usableFromInline let sign: Self.Element + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + // TODO: documentation + @inlinable public init(_ majorLimbs: Base, isSigned: Bool, as minorLimb: Element.Type = Element.self) { + //=--------------------------------------= + Swift.assert(Base.Element.bitWidth.isPowerOf2) // core + Swift.assert(Self.Element.bitWidth.isPowerOf2) // core + precondition(Base.Element.bitWidth >= Self.Element.bitWidth) + //=--------------------------------------= + self.base = majorLimbs + let bit = isSigned && self.base.last?.mostSignificantBit == true + self.sign = Self.Element(repeating: bit) + } + + //=------------------------------------------------------------------------= + // MARK: Accessors + //=------------------------------------------------------------------------= + + @inlinable public var count: Int { + Self.ratio * self.base.count + } + + @inlinable public subscript(index: Int) -> Element { + guard index < self.count else { return self.sign } + let indices = index.quotientAndRemainder(dividingBy: Self.ratio) + let major = self.base[self.base.index(self.base.startIndex, offsetBy: indices.quotient)] + return Element(truncatingIfNeeded: major &>> (indices.remainder * Element.bitWidth)) + } +} + +//=----------------------------------------------------------------------------= +// MARK: + Collection +//=----------------------------------------------------------------------------= + +extension NBKMinorInteger { + + //=------------------------------------------------------------------------= + // MARK: Accessors + //=------------------------------------------------------------------------= + + @inlinable public var startIndex: Int { + 0 as Int + } + + @inlinable public var endIndex: Int { + self.count + } + + @inlinable public var indices: Range { + Range(uncheckedBounds:(0 as Int, self.count)) + } + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + @inlinable public func distance(from start: Int, to end: Int) -> Int { + end - start + } + + @inlinable public func index(after index: Int) -> Int { + index + 1 as Int + } + + @inlinable public func formIndex(after index: inout Int) { + index += 1 as Int + } + + @inlinable public func index(before index: Int) -> Int { + index - 1 as Int + } + + @inlinable public func formIndex(before index: inout Int) { + index -= 1 as Int + } + + @inlinable public func index(_ index: Int, offsetBy distance: Int) -> Int { + index + distance + } + + @inlinable public func index(_ index: Int, offsetBy distance: Int, limitedBy limit: Int) -> Int? { + NBK.arrayIndex(index, offsetBy: distance, limitedBy: limit) + } +} diff --git a/Sources/Numberick/Documentation.docc/Documentation.md b/Sources/Numberick/Documentation.docc/Documentation.md index 3b3e5d08..d064e847 100644 --- a/Sources/Numberick/Documentation.docc/Documentation.md +++ b/Sources/Numberick/Documentation.docc/Documentation.md @@ -21,7 +21,6 @@ A new protocol hierarchy that refines Swift's standard library. - ``NBKMajorInteger`` - ``NBKMajorOrMinorInteger`` - ``NBKMinorInteger`` -- ``NBKMinorIntegerOfOne`` - ``NBKTwinHeaded`` ## NBKDoubleWidthKit @@ -118,7 +117,6 @@ Int256(5) % Int(5), UInt256(5) % UInt(5) - ``NBKMajorInteger`` - ``NBKMajorOrMinorInteger`` - ``NBKMinorInteger`` -- ``NBKMinorIntegerOfOne`` - ``NBKTwinHeaded`` ### Integers diff --git a/Tests/NBKCoreKitTests/Models/NBKMajorOrMinorInteger.swift b/Tests/NBKCoreKitTests/Models/NBKMajorOrMinorInteger.swift index 05e19fe5..013e0430 100644 --- a/Tests/NBKCoreKitTests/Models/NBKMajorOrMinorInteger.swift +++ b/Tests/NBKCoreKitTests/Models/NBKMajorOrMinorInteger.swift @@ -91,6 +91,28 @@ final class NBKMajorOrMinorIntegerTests: XCTestCase { // MARK: Tests x Signed or Unsigned //=------------------------------------------------------------------------= + func testSubscriptSignExtension() { + XCTAssertEqual(T([ 0] as S32, isSigned: false, as: Int32.self)[144], 0) + XCTAssertEqual(T([ 0] as S32, isSigned: true, as: Int32.self)[144], 0) + XCTAssertEqual(T([~0] as S32, isSigned: false, as: Int32.self)[144], 0) + XCTAssertEqual(T([~0] as S32, isSigned: true, as: Int32.self)[144], ~0) + + XCTAssertEqual(T([ 0] as S32, isSigned: false, as: Int64.self)[144], 0) + XCTAssertEqual(T([ 0] as S32, isSigned: true, as: Int64.self)[144], 0) + XCTAssertEqual(T([~0] as S32, isSigned: false, as: Int64.self)[144], 0) + XCTAssertEqual(T([~0] as S32, isSigned: true, as: Int64.self)[144], ~0) + + XCTAssertEqual(T([ 0] as S64, isSigned: false, as: Int32.self)[144], 0) + XCTAssertEqual(T([ 0] as S64, isSigned: true, as: Int32.self)[144], 0) + XCTAssertEqual(T([~0] as S64, isSigned: false, as: Int32.self)[144], 0) + XCTAssertEqual(T([~0] as S64, isSigned: true, as: Int32.self)[144], ~0) + + XCTAssertEqual(T([ 0] as S64, isSigned: false, as: Int64.self)[144], 0) + XCTAssertEqual(T([ 0] as S64, isSigned: true, as: Int64.self)[144], 0) + XCTAssertEqual(T([~0] as S64, isSigned: false, as: Int64.self)[144], 0) + XCTAssertEqual(T([~0] as S64, isSigned: true, as: Int64.self)[144], ~0) + } + func testMajorLimbsFromIncompleteMinorLimbs() { NBKAssertMajorOrMinorIntegerOneWay([ ] as S32, [ ] as S64, isSigned: true ) NBKAssertMajorOrMinorIntegerOneWay([ 1 ] as S32, [ 1 ] as S64, isSigned: true ) @@ -144,8 +166,8 @@ private func NBKAssertMajorOrMinorInteger( _ lhs: [A], _ rhs: [B], isSigned: Bool? = nil, file: StaticString = #file, line: UInt = #line) { - NBKAssertMajorOrMinorIntegerOneWay(lhs, rhs, isSigned: isSigned) - NBKAssertMajorOrMinorIntegerOneWay(rhs, lhs, isSigned: isSigned) + NBKAssertMajorOrMinorIntegerOneWay(lhs, rhs, isSigned: isSigned, file: file, line: line) + NBKAssertMajorOrMinorIntegerOneWay(rhs, lhs, isSigned: isSigned, file: file, line: line) } private func NBKAssertMajorOrMinorIntegerOneWay( From 8106e0ec28b0e88f331d241dd2e264d9d838a4d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Fri, 1 Sep 2023 16:55:42 +0200 Subject: [PATCH 090/111] [NBKCoreKit] Cleanup (#73). --- .../NBKCoreKit/Models/NBKMajorInteger.swift | 19 ++++++----- .../Models/NBKMajorOrMinorInteger.swift | 34 +++++++------------ .../NBKCoreKit/Models/NBKMinorInteger.swift | 17 ++++++---- 3 files changed, 34 insertions(+), 36 deletions(-) diff --git a/Sources/NBKCoreKit/Models/NBKMajorInteger.swift b/Sources/NBKCoreKit/Models/NBKMajorInteger.swift index d6832dd0..e5828725 100644 --- a/Sources/NBKCoreKit/Models/NBKMajorInteger.swift +++ b/Sources/NBKCoreKit/Models/NBKMajorInteger.swift @@ -22,6 +22,8 @@ @frozen public struct NBKMajorInteger: RandomAccessCollection where Element: NBKCoreInteger, Base: RandomAccessCollection, Base.Element: NBKCoreInteger { + public typealias Base = Base + @inlinable static var ratio: Int { Self.Element.bitWidth / Base.Element.bitWidth } //=------------------------------------------------------------------------= @@ -35,14 +37,14 @@ Element: NBKCoreInteger, Base: RandomAccessCollection, Base.Element: NBKCoreInte // MARK: Initializers //=------------------------------------------------------------------------= - // TODO: documentation - @inlinable public init(_ minorLimbs: Base, isSigned: Bool = false, as majorLimb: Element.Type = Element.self) { + /// Creates a sequence of the given type, from an un/signed source. + @inlinable public init(_ base: Base, isSigned: Bool = false, as element: Element.Type = Element.self) { //=--------------------------------------= - Swift.assert(Self.Element.bitWidth.isPowerOf2) // core - Swift.assert(Base.Element.bitWidth.isPowerOf2) // core + Swift.assert(Self.Element.bitWidth.isPowerOf2) + Swift.assert(Base.Element.bitWidth.isPowerOf2) precondition(Self.Element.bitWidth >= Base.Element.bitWidth) //=--------------------------------------= - self.base = minorLimbs + self.base = base let bit = isSigned && self.base.last?.mostSignificantBit == true self.sign = Self.Element(repeating: bit) } @@ -56,20 +58,21 @@ Element: NBKCoreInteger, Base: RandomAccessCollection, Base.Element: NBKCoreInte return division.quotient + Int(bit: !division.remainder.isZero) } + /// The elements are ordered from least significant to most, with an infinite sign extension. @inlinable public subscript(index: Int) -> Element { var shift = 0 as Int var major = 0 as Self.Element //=--------------------------------------= - var baseIndex = self.base.index(self.base.startIndex, offsetBy: index * Self.ratio) + var baseIndex = self.base.index(self.base.startIndex, offsetBy: Self.ratio * index) while baseIndex < self.base.endIndex && shift < Self.Element.bitWidth { - major |= Self.Element(truncatingIfNeeded: Base.Element.Magnitude(bitPattern: self.base[baseIndex])) &<< shift + major |= Self.Element(truncatingIfNeeded: Base.Element.Magnitude(bitPattern: self.base[baseIndex])) &<< shift shift += Base.Element.bitWidth as Int self.base.formIndex(after: &baseIndex) } //=--------------------------------------= if shift < Self.Element.bitWidth { major |= self.sign &<< shift } //=--------------------------------------= - return major + return major as Self.Element } } diff --git a/Sources/NBKCoreKit/Models/NBKMajorOrMinorInteger.swift b/Sources/NBKCoreKit/Models/NBKMajorOrMinorInteger.swift index 68e3c665..ec1208fd 100644 --- a/Sources/NBKCoreKit/Models/NBKMajorOrMinorInteger.swift +++ b/Sources/NBKCoreKit/Models/NBKMajorOrMinorInteger.swift @@ -24,9 +24,11 @@ Element: NBKCoreInteger, Base: RandomAccessCollection, Base.Element: NBKCoreInte public typealias Base = Base - public typealias MajorLimbs = NBKMajorInteger + public typealias Major = NBKMajorInteger - public typealias MinorLimbs = NBKMinorInteger + public typealias Minor = NBKMinorInteger + + @frozen @usableFromInline enum Storage { case major(Major), minor(Minor) } //=------------------------------------------------------------------------= // MARK: State @@ -39,12 +41,10 @@ Element: NBKCoreInteger, Base: RandomAccessCollection, Base.Element: NBKCoreInte //=------------------------------------------------------------------------= /// Creates a sequence of the given type, from an un/signed source. - @inlinable public init(_ source: Base, isSigned: Bool = false, as limb: Element.Type = Element.self) { - if Element.bitWidth > Base.Element.bitWidth { - self.storage = .majorLimbs(MajorLimbs(source, isSigned: isSigned)) - } else { - self.storage = .minorLimbs(MinorLimbs(source, isSigned: isSigned)) - } + @inlinable public init(_ base: Base, isSigned: Bool = false, as element: Element.Type = Element.self) { + switch Self.Element.bitWidth > Base.Element.bitWidth { + case true: self.storage = .major(Major(base, isSigned: isSigned)) + case false: self.storage = .minor(Minor(base, isSigned: isSigned)) } } //=------------------------------------------------------------------------= @@ -53,23 +53,15 @@ Element: NBKCoreInteger, Base: RandomAccessCollection, Base.Element: NBKCoreInte @inlinable public var count: Int { switch storage { - case let .majorLimbs(limbs): return limbs.count - case let .minorLimbs(limbs): return limbs.count } + case let .major(base): return base.count + case let .minor(base): return base.count } } + /// The elements are ordered from least significant to most, with an infinite sign extension. @inlinable public subscript(index: Int) -> Element { switch storage { - case let .majorLimbs(limbs): return limbs[index] - case let .minorLimbs(limbs): return limbs[index] } - } - - //*========================================================================* - // MARK: * Storage - //*========================================================================* - - @frozen @usableFromInline enum Storage { - case majorLimbs(MajorLimbs) - case minorLimbs(MinorLimbs) + case let .major(base): return base[index] + case let .minor(base): return base[index] } } } diff --git a/Sources/NBKCoreKit/Models/NBKMinorInteger.swift b/Sources/NBKCoreKit/Models/NBKMinorInteger.swift index bb68dff5..4e2d9b19 100644 --- a/Sources/NBKCoreKit/Models/NBKMinorInteger.swift +++ b/Sources/NBKCoreKit/Models/NBKMinorInteger.swift @@ -22,6 +22,8 @@ @frozen public struct NBKMinorInteger: RandomAccessCollection where Element: NBKCoreInteger, Base: RandomAccessCollection, Base.Element: NBKCoreInteger { + public typealias Base = Base + @inlinable static var ratio: Int { Base.Element.bitWidth / Self.Element.bitWidth } //=------------------------------------------------------------------------= @@ -35,14 +37,14 @@ Element: NBKCoreInteger, Base: RandomAccessCollection, Base.Element: NBKCoreInte // MARK: Initializers //=------------------------------------------------------------------------= - // TODO: documentation - @inlinable public init(_ majorLimbs: Base, isSigned: Bool, as minorLimb: Element.Type = Element.self) { + /// Creates a sequence of the given type, from an un/signed source. + @inlinable public init(_ base: Base, isSigned: Bool = false, as element: Element.Type = Element.self) { //=--------------------------------------= - Swift.assert(Base.Element.bitWidth.isPowerOf2) // core - Swift.assert(Self.Element.bitWidth.isPowerOf2) // core + Swift.assert(Base.Element.bitWidth.isPowerOf2) + Swift.assert(Self.Element.bitWidth.isPowerOf2) precondition(Base.Element.bitWidth >= Self.Element.bitWidth) //=--------------------------------------= - self.base = majorLimbs + self.base = base let bit = isSigned && self.base.last?.mostSignificantBit == true self.sign = Self.Element(repeating: bit) } @@ -55,11 +57,12 @@ Element: NBKCoreInteger, Base: RandomAccessCollection, Base.Element: NBKCoreInte Self.ratio * self.base.count } + /// The elements are ordered from least significant to most, with an infinite sign extension. @inlinable public subscript(index: Int) -> Element { guard index < self.count else { return self.sign } let indices = index.quotientAndRemainder(dividingBy: Self.ratio) - let major = self.base[self.base.index(self.base.startIndex, offsetBy: indices.quotient)] - return Element(truncatingIfNeeded: major &>> (indices.remainder * Element.bitWidth)) + let major = self.base[self.base.index(self.base.startIndex, offsetBy: indices.quotient)] + return Self.Element(truncatingIfNeeded: major &>> (indices.remainder * Element.bitWidth)) } } From d9c0b7a2af43ee5918dcbb33a815b6f23582de3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sat, 2 Sep 2023 08:42:51 +0200 Subject: [PATCH 091/111] [NBKCoreKit] Merge/split with count (#73). --- .../NBKCoreKit/Models/NBKMajorInteger.swift | 67 ++++++++++++------- .../Models/NBKMajorOrMinorInteger.swift | 16 +++-- .../NBKCoreKit/Models/NBKMinorInteger.swift | 45 ++++++++----- .../Models/NBKMajorOrMinorInteger.swift | 26 +++++++ .../Models/NBKMajorOrMinorInteger.swift | 52 +++++++++----- 5 files changed, 149 insertions(+), 57 deletions(-) diff --git a/Sources/NBKCoreKit/Models/NBKMajorInteger.swift b/Sources/NBKCoreKit/Models/NBKMajorInteger.swift index e5828725..518af77b 100644 --- a/Sources/NBKCoreKit/Models/NBKMajorInteger.swift +++ b/Sources/NBKCoreKit/Models/NBKMajorInteger.swift @@ -13,6 +13,10 @@ /// A sequence that merges components of an un/signed integer sequence. /// +/// ```swift +/// for word in NBKMajorInteger(source, isSigned: false, count: nil, as: UInt.self) { ... } +/// ``` +/// /// ### Binary Integer Order /// /// This sequence is ordered like a binary integer, meaning it merges and splits @@ -24,55 +28,72 @@ Element: NBKCoreInteger, Base: RandomAccessCollection, Base.Element: NBKCoreInte public typealias Base = Base - @inlinable static var ratio: Int { Self.Element.bitWidth / Base.Element.bitWidth } - //=------------------------------------------------------------------------= // MARK: State //=------------------------------------------------------------------------= @usableFromInline let base: Base @usableFromInline let sign: Element + public let count: Int //=------------------------------------------------------------------------= // MARK: Initializers //=------------------------------------------------------------------------= /// Creates a sequence of the given type, from an un/signed source. - @inlinable public init(_ base: Base, isSigned: Bool = false, as element: Element.Type = Element.self) { + @inlinable public init(_ base: Base, isSigned: Bool = false, count: Int? = nil, as element: Element.Type = Element.self) { //=--------------------------------------= Swift.assert(Self.Element.bitWidth.isPowerOf2) Swift.assert(Base.Element.bitWidth.isPowerOf2) precondition(Self.Element.bitWidth >= Base.Element.bitWidth) //=--------------------------------------= - self.base = base - let bit = isSigned && self.base.last?.mostSignificantBit == true - self.sign = Self.Element(repeating: bit) + self.base = base + self.sign = Self.Element(repeating: isSigned && self.base.last?.mostSignificantBit == true) + self.count = count ?? Self.count(of: self.base) } //=------------------------------------------------------------------------= // MARK: Accessors //=------------------------------------------------------------------------= - @inlinable public var count: Int { - let division = base.count.quotientAndRemainder(dividingBy: Self.ratio) - return division.quotient + Int(bit: !division.remainder.isZero) - } - - /// The elements are ordered from least significant to most, with an infinite sign extension. + /// Returns the element at the given index. + /// + /// Its elements are ordered from least significant to most, with infinite sign extension. + /// @inlinable public subscript(index: Int) -> Element { - var shift = 0 as Int - var major = 0 as Self.Element + precondition(index >= 0 as Int, NBK.callsiteOutOfBoundsInfo()) //=--------------------------------------= - var baseIndex = self.base.index(self.base.startIndex, offsetBy: Self.ratio * index) - while baseIndex < self.base.endIndex && shift < Self.Element.bitWidth { - major |= Self.Element(truncatingIfNeeded: Base.Element.Magnitude(bitPattern: self.base[baseIndex])) &<< shift - shift += Base.Element.bitWidth as Int - self.base.formIndex(after: &baseIndex) + var major = 0 as Element + var shift = 0 as Int + + if var baseIndex = self.baseIndex(index) { + while baseIndex < self.base.endIndex, shift < Self.Element.bitWidth { + major |= Self.Element(truncatingIfNeeded: Base.Element.Magnitude(bitPattern: self.base[baseIndex])) &<< shift + shift += Base.Element.bitWidth + self.base.formIndex(after: &baseIndex) + } } - //=--------------------------------------= - if shift < Self.Element.bitWidth { major |= self.sign &<< shift } - //=--------------------------------------= - return major as Self.Element + + return shift >= Self.Element.bitWidth ? major : major | self.sign &<< shift + } + + //=------------------------------------------------------------------------= + // MARK: Utilities x Private + //=------------------------------------------------------------------------= + + @inlinable func baseIndex(_ index: Int) -> Base.Index? { + let position = Self.ratio * index + guard position < self.base.count else { return nil } + return self.base.index(self.base.startIndex, offsetBy: position) + } + + @inlinable static var ratio: Int { + Self.Element.bitWidth / Base.Element.bitWidth + } + + @inlinable static func count(of base: Base) -> Int { + let division = base.count.quotientAndRemainder(dividingBy: Self.ratio) + return division.quotient + Int(bit: !division.remainder.isZero) } } diff --git a/Sources/NBKCoreKit/Models/NBKMajorOrMinorInteger.swift b/Sources/NBKCoreKit/Models/NBKMajorOrMinorInteger.swift index ec1208fd..62d7a5e6 100644 --- a/Sources/NBKCoreKit/Models/NBKMajorOrMinorInteger.swift +++ b/Sources/NBKCoreKit/Models/NBKMajorOrMinorInteger.swift @@ -13,6 +13,11 @@ /// A sequence that merges or splits components of an un/signed integer sequence. /// +/// ```swift +/// for word in NBKMajorOrMinorInteger(source, isSigned: false, count: nil, as: UInt.self) { ... } +/// for byte in NBKMajorOrMinorInteger(source, isSigned: false, count: nil, as: Int8.self) { ... } +/// ``` +/// /// ### Binary Integer Order /// /// This sequence is ordered like a binary integer, meaning it merges and splits @@ -41,10 +46,10 @@ Element: NBKCoreInteger, Base: RandomAccessCollection, Base.Element: NBKCoreInte //=------------------------------------------------------------------------= /// Creates a sequence of the given type, from an un/signed source. - @inlinable public init(_ base: Base, isSigned: Bool = false, as element: Element.Type = Element.self) { + @inlinable public init(_ base: Base, isSigned: Bool = false, count: Int? = nil, as element: Element.Type = Element.self) { switch Self.Element.bitWidth > Base.Element.bitWidth { - case true: self.storage = .major(Major(base, isSigned: isSigned)) - case false: self.storage = .minor(Minor(base, isSigned: isSigned)) } + case true: self.storage = .major(Major(base, isSigned: isSigned, count: count)) + case false: self.storage = .minor(Minor(base, isSigned: isSigned, count: count)) } } //=------------------------------------------------------------------------= @@ -57,7 +62,10 @@ Element: NBKCoreInteger, Base: RandomAccessCollection, Base.Element: NBKCoreInte case let .minor(base): return base.count } } - /// The elements are ordered from least significant to most, with an infinite sign extension. + /// Returns the element at the given index. + /// + /// Its elements are ordered from least significant to most, with infinite sign extension. + /// @inlinable public subscript(index: Int) -> Element { switch storage { case let .major(base): return base[index] diff --git a/Sources/NBKCoreKit/Models/NBKMinorInteger.swift b/Sources/NBKCoreKit/Models/NBKMinorInteger.swift index 4e2d9b19..e9beabd0 100644 --- a/Sources/NBKCoreKit/Models/NBKMinorInteger.swift +++ b/Sources/NBKCoreKit/Models/NBKMinorInteger.swift @@ -13,6 +13,10 @@ /// A sequence that splits components of an un/signed integer sequence. /// +/// ```swift +/// for byte in NBKMinorInteger(source, isSigned: false, count: nil, as: Int8.self) { ... } +/// ``` +/// /// ### Binary Integer Order /// /// This sequence is ordered like a binary integer, meaning it merges and splits @@ -23,46 +27,57 @@ Element: NBKCoreInteger, Base: RandomAccessCollection, Base.Element: NBKCoreInteger { public typealias Base = Base - - @inlinable static var ratio: Int { Base.Element.bitWidth / Self.Element.bitWidth } - + //=------------------------------------------------------------------------= // MARK: State //=------------------------------------------------------------------------= @usableFromInline let base: Base @usableFromInline let sign: Self.Element + public let count: Int //=------------------------------------------------------------------------= // MARK: Initializers //=------------------------------------------------------------------------= /// Creates a sequence of the given type, from an un/signed source. - @inlinable public init(_ base: Base, isSigned: Bool = false, as element: Element.Type = Element.self) { + @inlinable public init(_ base: Base, isSigned: Bool = false, count: Int? = nil, as element: Element.Type = Element.self) { //=--------------------------------------= Swift.assert(Base.Element.bitWidth.isPowerOf2) Swift.assert(Self.Element.bitWidth.isPowerOf2) precondition(Base.Element.bitWidth >= Self.Element.bitWidth) //=--------------------------------------= - self.base = base - let bit = isSigned && self.base.last?.mostSignificantBit == true - self.sign = Self.Element(repeating: bit) + self.base = base + self.sign = Self.Element(repeating: isSigned && self.base.last?.mostSignificantBit == true) + self.count = count ?? Self.count(of: self.base) } //=------------------------------------------------------------------------= // MARK: Accessors //=------------------------------------------------------------------------= - @inlinable public var count: Int { - Self.ratio * self.base.count + /// Returns the element at the given index. + /// + /// Its elements are ordered from least significant to most, with infinite sign extension. + /// + @inlinable public subscript(index: Int) -> Element { + precondition(index >= 0 as Int, NBK.callsiteOutOfBoundsInfo()) + let (quotient, remainder) = index.quotientAndRemainder(dividingBy: Self.ratio) + guard quotient < self.base.count else { return self.sign } + let major = self.base[self.base.index(self.base.startIndex, offsetBy: quotient)] + return Self.Element(truncatingIfNeeded: major &>> (remainder * Element.bitWidth)) + } + + //=------------------------------------------------------------------------= + // MARK: Utilities x Private + //=------------------------------------------------------------------------= + + @inlinable static var ratio: Int { + Base.Element.bitWidth / Self.Element.bitWidth } - /// The elements are ordered from least significant to most, with an infinite sign extension. - @inlinable public subscript(index: Int) -> Element { - guard index < self.count else { return self.sign } - let indices = index.quotientAndRemainder(dividingBy: Self.ratio) - let major = self.base[self.base.index(self.base.startIndex, offsetBy: indices.quotient)] - return Self.Element(truncatingIfNeeded: major &>> (indices.remainder * Element.bitWidth)) + @inlinable static func count(of base: Base) -> Int { + Self.ratio * base.count } } diff --git a/Tests/NBKCoreKitBenchmarks/Models/NBKMajorOrMinorInteger.swift b/Tests/NBKCoreKitBenchmarks/Models/NBKMajorOrMinorInteger.swift index 3b09c4f3..1530b3c7 100644 --- a/Tests/NBKCoreKitBenchmarks/Models/NBKMajorOrMinorInteger.swift +++ b/Tests/NBKCoreKitBenchmarks/Models/NBKMajorOrMinorInteger.swift @@ -41,6 +41,19 @@ final class NBKMajorOrMinorIntegerBenchmarks: XCTestCase { } } + func testUInt64AsUInt32AsMinor() { + var abc = NBK.blackHoleIdentity([ 1, 2, 3, 4] as X) + var xyz = NBK.blackHoleIdentity([~1, ~2, ~3, ~4] as X) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(Y(T.Minor(abc))) + NBK.blackHole(Y(T.Minor(xyz))) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + func testUInt32AsUInt64() { var abc = NBK.blackHoleIdentity([ 1, 0, 2, 0, 3, 0, 4, 0] as Y) var xyz = NBK.blackHoleIdentity([~1, ~0, ~2, ~0, ~3, ~0, ~4, ~0] as Y) @@ -53,6 +66,19 @@ final class NBKMajorOrMinorIntegerBenchmarks: XCTestCase { NBK.blackHoleInoutIdentity(&xyz) } } + + func testUInt32AsUInt64AsMajor() { + var abc = NBK.blackHoleIdentity([ 1, 0, 2, 0, 3, 0, 4, 0] as Y) + var xyz = NBK.blackHoleIdentity([~1, ~0, ~2, ~0, ~3, ~0, ~4, ~0] as Y) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(X(T.Major(abc))) + NBK.blackHole(X(T.Major(xyz))) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } } #endif diff --git a/Tests/NBKCoreKitTests/Models/NBKMajorOrMinorInteger.swift b/Tests/NBKCoreKitTests/Models/NBKMajorOrMinorInteger.swift index 013e0430..e9794e83 100644 --- a/Tests/NBKCoreKitTests/Models/NBKMajorOrMinorInteger.swift +++ b/Tests/NBKCoreKitTests/Models/NBKMajorOrMinorInteger.swift @@ -87,6 +87,29 @@ final class NBKMajorOrMinorIntegerTests: XCTestCase { NBKAssertMajorOrMinorInteger([~1, ~2, ~3, ~4] as S64, [~1, ~0, ~2, ~0, ~3, ~0, ~4, ~0] as S32) } + //=------------------------------------------------------------------------= + // MARK: Tests x Count + //=------------------------------------------------------------------------= + + func testUInt32AsUInt64WithCustomCount() { + XCTAssertEqual([1, 2 ], Array(T([1, 0, 2, 0] as S32, count: nil, as: Int64.self))) + XCTAssertEqual([ ], Array(T([1, 0, 2, 0] as S32, count: 000, as: Int64.self))) + XCTAssertEqual([1 ], Array(T([1, 0, 2, 0] as S32, count: 001, as: Int64.self))) + XCTAssertEqual([1, 2 ], Array(T([1, 0, 2, 0] as S32, count: 002, as: Int64.self))) + XCTAssertEqual([1, 2, 0], Array(T([1, 0, 2, 0] as S32, count: 003, as: Int64.self))) + } + + func testUInt64AsUInt32WithCustomCount() { + XCTAssertEqual([1, 0, 2, 0 ], Array(T([1, 2] as S64, count: nil, as: Int32.self))) + XCTAssertEqual([ ], Array(T([1, 2] as S64, count: 000, as: Int32.self))) + XCTAssertEqual([1 ], Array(T([1, 2] as S64, count: 001, as: Int32.self))) + XCTAssertEqual([1, 0 ], Array(T([1, 2] as S64, count: 002, as: Int32.self))) + XCTAssertEqual([1, 0, 2 ], Array(T([1, 2] as S64, count: 003, as: Int32.self))) + XCTAssertEqual([1, 0, 2, 0 ], Array(T([1, 2] as S64, count: 004, as: Int32.self))) + XCTAssertEqual([1, 0, 2, 0, 0 ], Array(T([1, 2] as S64, count: 005, as: Int32.self))) + XCTAssertEqual([1, 0, 2, 0, 0, 0], Array(T([1, 2] as S64, count: 006, as: Int32.self))) + } + //=------------------------------------------------------------------------= // MARK: Tests x Signed or Unsigned //=------------------------------------------------------------------------= @@ -173,27 +196,26 @@ file: StaticString = #file, line: UInt = #line) { private func NBKAssertMajorOrMinorIntegerOneWay( _ lhs: [A], _ rhs: [B], isSigned: Bool? = nil, file: StaticString = #file, line: UInt = #line) { - //=------------------------------------------= - typealias X = Array - typealias Y = ContiguousArray typealias T = NBKMajorOrMinorInteger //=------------------------------------------= let lhsUnsigned = lhs.map(A.Magnitude.init(bitPattern:)) let rhsUnsigned = rhs.map(B.Magnitude.init(bitPattern:)) //=------------------------------------------= - if isSigned == nil || isSigned == true { - XCTAssertEqual(X(T(X(lhs), isSigned: true )), X(rhs), file: file, line: line) - XCTAssertEqual(X(T(X(lhsUnsigned), isSigned: true )), X(rhsUnsigned), file: file, line: line) - XCTAssertEqual(Y(T(Y(lhs), isSigned: true )), Y(rhs), file: file, line: line) - XCTAssertEqual(Y(T(Y(lhsUnsigned), isSigned: true )), Y(rhsUnsigned), file: file, line: line) - } - - if isSigned == nil || isSigned == false { - XCTAssertEqual(X(T(X(lhs), isSigned: false)), X(rhs), file: file, line: line) - XCTAssertEqual(X(T(X(lhsUnsigned), isSigned: false)), X(rhsUnsigned), file: file, line: line) - XCTAssertEqual(Y(T(Y(lhs), isSigned: false)), Y(rhs), file: file, line: line) - XCTAssertEqual(Y(T(Y(lhsUnsigned), isSigned: false)), Y(rhsUnsigned), file: file, line: line) + func with(isSigned: Bool) { + do { + XCTAssertEqual(Array(T.init (lhs, isSigned: isSigned)), rhs, file: file, line: line) + XCTAssertEqual(Array(T.init (lhsUnsigned, isSigned: isSigned)), rhsUnsigned, file: file, line: line) + }; if B.bitWidth >= A.bitWidth { + XCTAssertEqual(Array(T.Major(lhs, isSigned: isSigned)), rhs, file: file, line: line) + XCTAssertEqual(Array(T.Major(lhsUnsigned, isSigned: isSigned)), rhsUnsigned, file: file, line: line) + }; if B.bitWidth <= A.bitWidth { + XCTAssertEqual(Array(T.Minor(lhs, isSigned: isSigned)), rhs, file: file, line: line) + XCTAssertEqual(Array(T.Minor(lhsUnsigned, isSigned: isSigned)), rhsUnsigned, file: file, line: line) + } } + //=------------------------------------------= + if isSigned == nil || isSigned == true { with(isSigned: true ) } + if isSigned == nil || isSigned == false { with(isSigned: false) } } #endif From 807e6fbe9bfdef89d6949f698b3cd37d1a913f31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sat, 2 Sep 2023 11:31:30 +0200 Subject: [PATCH 092/111] [NBKCoreKit] Cleanup. --- Sources/NBKCoreKit/Models/NBKMajorInteger.swift | 10 ++++++---- Sources/NBKCoreKit/Models/NBKMinorInteger.swift | 2 ++ Sources/NBKCoreKit/Models/NBKTwinHeaded.swift | 10 ---------- Tests/NBKCoreKitTests/Models/NBKTwinHeaded.swift | 10 ---------- 4 files changed, 8 insertions(+), 24 deletions(-) diff --git a/Sources/NBKCoreKit/Models/NBKMajorInteger.swift b/Sources/NBKCoreKit/Models/NBKMajorInteger.swift index 518af77b..9994a923 100644 --- a/Sources/NBKCoreKit/Models/NBKMajorInteger.swift +++ b/Sources/NBKCoreKit/Models/NBKMajorInteger.swift @@ -13,6 +13,8 @@ /// A sequence that merges components of an un/signed integer sequence. /// +/// To use this sequence, the base sequence's element type must fit in its element type. +/// /// ```swift /// for word in NBKMajorInteger(source, isSigned: false, count: nil, as: UInt.self) { ... } /// ``` @@ -63,10 +65,10 @@ Element: NBKCoreInteger, Base: RandomAccessCollection, Base.Element: NBKCoreInte @inlinable public subscript(index: Int) -> Element { precondition(index >= 0 as Int, NBK.callsiteOutOfBoundsInfo()) //=--------------------------------------= - var major = 0 as Element var shift = 0 as Int + var major = 0 as Element - if var baseIndex = self.baseIndex(index) { + if var baseIndex = self.baseSubscriptIndex(index) { while baseIndex < self.base.endIndex, shift < Self.Element.bitWidth { major |= Self.Element(truncatingIfNeeded: Base.Element.Magnitude(bitPattern: self.base[baseIndex])) &<< shift shift += Base.Element.bitWidth @@ -81,8 +83,8 @@ Element: NBKCoreInteger, Base: RandomAccessCollection, Base.Element: NBKCoreInte // MARK: Utilities x Private //=------------------------------------------------------------------------= - @inlinable func baseIndex(_ index: Int) -> Base.Index? { - let position = Self.ratio * index + @inlinable func baseSubscriptIndex(_ index: Int) -> Base.Index? { + let position = Self.ratio * index guard position < self.base.count else { return nil } return self.base.index(self.base.startIndex, offsetBy: position) } diff --git a/Sources/NBKCoreKit/Models/NBKMinorInteger.swift b/Sources/NBKCoreKit/Models/NBKMinorInteger.swift index e9beabd0..9d4ac527 100644 --- a/Sources/NBKCoreKit/Models/NBKMinorInteger.swift +++ b/Sources/NBKCoreKit/Models/NBKMinorInteger.swift @@ -13,6 +13,8 @@ /// A sequence that splits components of an un/signed integer sequence. /// +/// To use this sequence, its element type must fit in the base sequence's element type. +/// /// ```swift /// for byte in NBKMinorInteger(source, isSigned: false, count: nil, as: Int8.self) { ... } /// ``` diff --git a/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift b/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift index 260e305a..c7350204 100644 --- a/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift +++ b/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift @@ -105,21 +105,11 @@ self.mask == ( 0) as Int } - /// Returns the base collection, if its elements matches this collection. - @inlinable public var asFrontToBack: Base? { - self.isFrontToBack ? self.base : nil - } - /// Returns whether the base collection's elements are presented back-to-front. @inlinable public var isBackToFront: Bool { self.mask == (-1) as Int } - /// Returns the base collection but reversed, if its elements matches this collection. - @inlinable public var asBackToFront: ReversedCollection? { - self.isBackToFront ? self.base.reversed() : nil - } - //=------------------------------------------------------------------------= // MARK: Transformations //=------------------------------------------------------------------------= diff --git a/Tests/NBKCoreKitTests/Models/NBKTwinHeaded.swift b/Tests/NBKCoreKitTests/Models/NBKTwinHeaded.swift index e48bf3f2..25b8210a 100644 --- a/Tests/NBKCoreKitTests/Models/NBKTwinHeaded.swift +++ b/Tests/NBKCoreKitTests/Models/NBKTwinHeaded.swift @@ -84,21 +84,11 @@ final class NBKTwinHeadedTests: XCTestCase { XCTAssertEqual(T([0, 1, 2, 3], reversed: true ).isFrontToBack, false) } - func testAsFrontToBack() { - XCTAssertEqual(T([0, 1, 2, 3], reversed: false).asFrontToBack, [0, 1, 2, 3]) - XCTAssertEqual(T([0, 1, 2, 3], reversed: true ).asFrontToBack, nil) - } - func testIsBackToFront() { XCTAssertEqual(T([0, 1, 2, 3], reversed: false).isBackToFront, false) XCTAssertEqual(T([0, 1, 2, 3], reversed: true ).isBackToFront, true ) } - func testAsBackToFront() { - XCTAssertEqual(T([0, 1, 2, 3], reversed: false).asBackToFront.map(Array.init), nil) - XCTAssertEqual(T([0, 1, 2, 3], reversed: true ).asBackToFront.map(Array.init), [0, 1, 2, 3].reversed()) - } - //=------------------------------------------------------------------------= // MARK: Tests x Transformations //=------------------------------------------------------------------------= From eeee802fa64c2fac8bc63e53c1c42913cc808029 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sat, 2 Sep 2023 15:16:12 +0200 Subject: [PATCH 093/111] [NBKCoreKit] Cleanup. --- Sources/NBKCoreKit/Models/NBKEndianness.swift | 5 -- .../NBKCoreKit/Models/NBKMajorInteger.swift | 33 +++++++------ .../Models/NBKMajorOrMinorInteger.swift | 13 ++++-- .../NBKCoreKit/Models/NBKMinorInteger.swift | 13 ++++-- .../Models/NBKMajorOrMinorInteger.swift | 46 ++++++++++--------- 5 files changed, 63 insertions(+), 47 deletions(-) diff --git a/Sources/NBKCoreKit/Models/NBKEndianness.swift b/Sources/NBKCoreKit/Models/NBKEndianness.swift index b319735e..345f60c1 100644 --- a/Sources/NBKCoreKit/Models/NBKEndianness.swift +++ b/Sources/NBKCoreKit/Models/NBKEndianness.swift @@ -13,11 +13,6 @@ /// An enumeration of little and big endianness. /// -/// ```swift -/// NBKEndianness.little.rawValue // 0x00 -/// NBKEndianness.big .rawValue // 0x01 -/// ``` -/// /// ### Static vs Dynamic /// /// Some algorithms differ depending on endianness. Generic type parameterization diff --git a/Sources/NBKCoreKit/Models/NBKMajorInteger.swift b/Sources/NBKCoreKit/Models/NBKMajorInteger.swift index 9994a923..e14061db 100644 --- a/Sources/NBKCoreKit/Models/NBKMajorInteger.swift +++ b/Sources/NBKCoreKit/Models/NBKMajorInteger.swift @@ -11,7 +11,7 @@ // MARK: * NBK x Major Integer //*============================================================================* -/// A sequence that merges components of an un/signed integer sequence. +/// A sequence that merges elements of an un/signed integer sequence. /// /// To use this sequence, the base sequence's element type must fit in its element type. /// @@ -22,7 +22,7 @@ /// ### Binary Integer Order /// /// This sequence is ordered like a binary integer, meaning it merges and splits -/// its components from least significant to most. You can reorder it by reversing +/// its elements from least significant to most. You can reorder it by reversing /// the input, the output, or both. /// @frozen public struct NBKMajorInteger: RandomAccessCollection where @@ -37,12 +37,19 @@ Element: NBKCoreInteger, Base: RandomAccessCollection, Base.Element: NBKCoreInte @usableFromInline let base: Base @usableFromInline let sign: Element public let count: Int - + //=------------------------------------------------------------------------= // MARK: Initializers //=------------------------------------------------------------------------= - /// Creates a sequence of the given type, from an un/signed source. + /// Creates a sequence of the given type from an un/signed source. + /// + /// - Parameters: + /// - base: The base sequence viewed through this model. + /// - isSigned: A value indicating whether the base sequence is signed. + /// - count: A value used to extend or truncate the base sequence. + /// - element: The type of element produced by this model. + /// @inlinable public init(_ base: Base, isSigned: Bool = false, count: Int? = nil, as element: Element.Type = Element.self) { //=--------------------------------------= Swift.assert(Self.Element.bitWidth.isPowerOf2) @@ -67,28 +74,24 @@ Element: NBKCoreInteger, Base: RandomAccessCollection, Base.Element: NBKCoreInte //=--------------------------------------= var shift = 0 as Int var major = 0 as Element + let minorindex = index * Self.ratio - if var baseIndex = self.baseSubscriptIndex(index) { - while baseIndex < self.base.endIndex, shift < Self.Element.bitWidth { - major |= Self.Element(truncatingIfNeeded: Base.Element.Magnitude(bitPattern: self.base[baseIndex])) &<< shift + if minorindex < base.count { + var baseIndex = base.index(base.startIndex, offsetBy: minorindex) + while baseIndex < base.endIndex, shift < Element.bitWidth { + major |= Element(truncatingIfNeeded: Base.Element.Magnitude(bitPattern: base[baseIndex])) &<< shift shift += Base.Element.bitWidth - self.base.formIndex(after: &baseIndex) + base.formIndex(after: &baseIndex) } } - return shift >= Self.Element.bitWidth ? major : major | self.sign &<< shift + return shift >= Element.bitWidth ? major : major | sign &<< shift } //=------------------------------------------------------------------------= // MARK: Utilities x Private //=------------------------------------------------------------------------= - @inlinable func baseSubscriptIndex(_ index: Int) -> Base.Index? { - let position = Self.ratio * index - guard position < self.base.count else { return nil } - return self.base.index(self.base.startIndex, offsetBy: position) - } - @inlinable static var ratio: Int { Self.Element.bitWidth / Base.Element.bitWidth } diff --git a/Sources/NBKCoreKit/Models/NBKMajorOrMinorInteger.swift b/Sources/NBKCoreKit/Models/NBKMajorOrMinorInteger.swift index 62d7a5e6..8a139468 100644 --- a/Sources/NBKCoreKit/Models/NBKMajorOrMinorInteger.swift +++ b/Sources/NBKCoreKit/Models/NBKMajorOrMinorInteger.swift @@ -11,7 +11,7 @@ // MARK: * NBK x Major Or Minor Integer //*============================================================================* -/// A sequence that merges or splits components of an un/signed integer sequence. +/// A sequence that merges or splits elements of an un/signed integer sequence. /// /// ```swift /// for word in NBKMajorOrMinorInteger(source, isSigned: false, count: nil, as: UInt.self) { ... } @@ -21,7 +21,7 @@ /// ### Binary Integer Order /// /// This sequence is ordered like a binary integer, meaning it merges and splits -/// its components from least significant to most. You can reorder it by reversing +/// its elements from least significant to most. You can reorder it by reversing /// the input, the output, or both. /// @frozen public struct NBKMajorOrMinorInteger: RandomAccessCollection where @@ -45,7 +45,14 @@ Element: NBKCoreInteger, Base: RandomAccessCollection, Base.Element: NBKCoreInte // MARK: Initializers //=------------------------------------------------------------------------= - /// Creates a sequence of the given type, from an un/signed source. + /// Creates a sequence of the given type from an un/signed source. + /// + /// - Parameters: + /// - base: The base sequence viewed through this model. + /// - isSigned: A value indicating whether the base sequence is signed. + /// - count: A value used to extend or truncate the base sequence. + /// - element: The type of element produced by this model. + /// @inlinable public init(_ base: Base, isSigned: Bool = false, count: Int? = nil, as element: Element.Type = Element.self) { switch Self.Element.bitWidth > Base.Element.bitWidth { case true: self.storage = .major(Major(base, isSigned: isSigned, count: count)) diff --git a/Sources/NBKCoreKit/Models/NBKMinorInteger.swift b/Sources/NBKCoreKit/Models/NBKMinorInteger.swift index 9d4ac527..3f01b8ab 100644 --- a/Sources/NBKCoreKit/Models/NBKMinorInteger.swift +++ b/Sources/NBKCoreKit/Models/NBKMinorInteger.swift @@ -11,7 +11,7 @@ // MARK: * NBK x Minor Integer //*============================================================================* -/// A sequence that splits components of an un/signed integer sequence. +/// A sequence that splits elements of an un/signed integer sequence. /// /// To use this sequence, its element type must fit in the base sequence's element type. /// @@ -22,7 +22,7 @@ /// ### Binary Integer Order /// /// This sequence is ordered like a binary integer, meaning it merges and splits -/// its components from least significant to most. You can reorder it by reversing +/// its elements from least significant to most. You can reorder it by reversing /// the input, the output, or both. /// @frozen public struct NBKMinorInteger: RandomAccessCollection where @@ -42,7 +42,14 @@ Element: NBKCoreInteger, Base: RandomAccessCollection, Base.Element: NBKCoreInte // MARK: Initializers //=------------------------------------------------------------------------= - /// Creates a sequence of the given type, from an un/signed source. + /// Creates a sequence of the given type from an un/signed source. + /// + /// - Parameters: + /// - base: The base sequence viewed through this model. + /// - isSigned: A value indicating whether the base sequence is signed. + /// - count: A value used to extend or truncate the base sequence. + /// - element: The type of element produced by this model. + /// @inlinable public init(_ base: Base, isSigned: Bool = false, count: Int? = nil, as element: Element.Type = Element.self) { //=--------------------------------------= Swift.assert(Base.Element.bitWidth.isPowerOf2) diff --git a/Tests/NBKCoreKitBenchmarks/Models/NBKMajorOrMinorInteger.swift b/Tests/NBKCoreKitBenchmarks/Models/NBKMajorOrMinorInteger.swift index 1530b3c7..f1555f01 100644 --- a/Tests/NBKCoreKitBenchmarks/Models/NBKMajorOrMinorInteger.swift +++ b/Tests/NBKCoreKitBenchmarks/Models/NBKMajorOrMinorInteger.swift @@ -25,55 +25,59 @@ final class NBKMajorOrMinorIntegerBenchmarks: XCTestCase { typealias T = NBKMajorOrMinorInteger //=------------------------------------------------------------------------= - // MARK: Tests + // MARK: Tests x Major //=------------------------------------------------------------------------= - func testUInt64AsUInt32() { - var abc = NBK.blackHoleIdentity([ 1, 2, 3, 4] as X) - var xyz = NBK.blackHoleIdentity([~1, ~2, ~3, ~4] as X) + func testUInt32AsUInt64() { + var abc = NBK.blackHoleIdentity([ 1, 0, 2, 0, 3, 0, 4, 0] as Y) + var xyz = NBK.blackHoleIdentity([~1, ~0, ~2, ~0, ~3, ~0, ~4, ~0] as Y) for _ in 0 ..< 1_000_000 { - NBK.blackHole(Y(T(abc))) - NBK.blackHole(Y(T(xyz))) + NBK.blackHole(X(T(abc))) + NBK.blackHole(X(T(xyz))) NBK.blackHoleInoutIdentity(&abc) NBK.blackHoleInoutIdentity(&xyz) } } - func testUInt64AsUInt32AsMinor() { - var abc = NBK.blackHoleIdentity([ 1, 2, 3, 4] as X) - var xyz = NBK.blackHoleIdentity([~1, ~2, ~3, ~4] as X) + func testUInt32AsUInt64AsMajor() { + var abc = NBK.blackHoleIdentity([ 1, 0, 2, 0, 3, 0, 4, 0] as Y) + var xyz = NBK.blackHoleIdentity([~1, ~0, ~2, ~0, ~3, ~0, ~4, ~0] as Y) for _ in 0 ..< 1_000_000 { - NBK.blackHole(Y(T.Minor(abc))) - NBK.blackHole(Y(T.Minor(xyz))) + NBK.blackHole(X(T.Major(abc))) + NBK.blackHole(X(T.Major(xyz))) NBK.blackHoleInoutIdentity(&abc) NBK.blackHoleInoutIdentity(&xyz) } } - func testUInt32AsUInt64() { - var abc = NBK.blackHoleIdentity([ 1, 0, 2, 0, 3, 0, 4, 0] as Y) - var xyz = NBK.blackHoleIdentity([~1, ~0, ~2, ~0, ~3, ~0, ~4, ~0] as Y) + //=------------------------------------------------------------------------= + // MARK: Tests x Minor + //=------------------------------------------------------------------------= + + func testUInt64AsUInt32() { + var abc = NBK.blackHoleIdentity([ 1, 2, 3, 4] as X) + var xyz = NBK.blackHoleIdentity([~1, ~2, ~3, ~4] as X) for _ in 0 ..< 1_000_000 { - NBK.blackHole(X(T(abc))) - NBK.blackHole(X(T(xyz))) + NBK.blackHole(Y(T(abc))) + NBK.blackHole(Y(T(xyz))) NBK.blackHoleInoutIdentity(&abc) NBK.blackHoleInoutIdentity(&xyz) } } - func testUInt32AsUInt64AsMajor() { - var abc = NBK.blackHoleIdentity([ 1, 0, 2, 0, 3, 0, 4, 0] as Y) - var xyz = NBK.blackHoleIdentity([~1, ~0, ~2, ~0, ~3, ~0, ~4, ~0] as Y) + func testUInt64AsUInt32AsMinor() { + var abc = NBK.blackHoleIdentity([ 1, 2, 3, 4] as X) + var xyz = NBK.blackHoleIdentity([~1, ~2, ~3, ~4] as X) for _ in 0 ..< 1_000_000 { - NBK.blackHole(X(T.Major(abc))) - NBK.blackHole(X(T.Major(xyz))) + NBK.blackHole(Y(T.Minor(abc))) + NBK.blackHole(Y(T.Minor(xyz))) NBK.blackHoleInoutIdentity(&abc) NBK.blackHoleInoutIdentity(&xyz) From 2e144161b15176a7504e902b3bcf7bccc81ad5d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sun, 3 Sep 2023 10:59:48 +0200 Subject: [PATCH 094/111] [NBKCoreKit] One merge/split sequence (#73). --- README.md | 2 - .../NBKCoreKit/Models/NBKMajorInteger.swift | 158 ------------------ .../Models/NBKMajorOrMinorInteger.swift | 139 ++++++++++++--- .../NBKCoreKit/Models/NBKMinorInteger.swift | 146 ---------------- .../NBKDoubleWidth+Text.swift | 2 +- .../Documentation.docc/Documentation.md | 4 - .../Models/NBKMajorOrMinorInteger.swift | 22 +-- .../Models/NBKMajorOrMinorInteger.swift | 12 +- 8 files changed, 131 insertions(+), 354 deletions(-) delete mode 100644 Sources/NBKCoreKit/Models/NBKMajorInteger.swift delete mode 100644 Sources/NBKCoreKit/Models/NBKMinorInteger.swift diff --git a/README.md b/README.md index fa81141d..3da83b13 100644 --- a/README.md +++ b/README.md @@ -22,9 +22,7 @@ A new protocol hierarchy that refines Swift's standard library. ### Models - [NBKEndianness](Sources/NBKCoreKit/Models/NBKEndianness.swift) -- [NBKMajorInteger](Sources/NBKCoreKit/Models/NBKMajorOrMinorInteger.swift) - [NBKMajorOrMinorInteger](Sources/NBKCoreKit/Models/NBKMajorOrMinorInteger.swift) -- [NBKMinorInteger](Sources/NBKCoreKit/Models/NBKMajorOrMinorInteger.swift) - [NBKTwinHeaded](Sources/NBKCoreKit/Models/NBKTwinHeaded.swift) ## [NBKDoubleWidthKit][DBL/D] ([Sources][DBL/S], [Tests][DBL/T], [Benchmarks][DBL/B]) diff --git a/Sources/NBKCoreKit/Models/NBKMajorInteger.swift b/Sources/NBKCoreKit/Models/NBKMajorInteger.swift deleted file mode 100644 index e14061db..00000000 --- a/Sources/NBKCoreKit/Models/NBKMajorInteger.swift +++ /dev/null @@ -1,158 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -//*============================================================================* -// MARK: * NBK x Major Integer -//*============================================================================* - -/// A sequence that merges elements of an un/signed integer sequence. -/// -/// To use this sequence, the base sequence's element type must fit in its element type. -/// -/// ```swift -/// for word in NBKMajorInteger(source, isSigned: false, count: nil, as: UInt.self) { ... } -/// ``` -/// -/// ### Binary Integer Order -/// -/// This sequence is ordered like a binary integer, meaning it merges and splits -/// its elements from least significant to most. You can reorder it by reversing -/// the input, the output, or both. -/// -@frozen public struct NBKMajorInteger: RandomAccessCollection where -Element: NBKCoreInteger, Base: RandomAccessCollection, Base.Element: NBKCoreInteger { - - public typealias Base = Base - - //=------------------------------------------------------------------------= - // MARK: State - //=------------------------------------------------------------------------= - - @usableFromInline let base: Base - @usableFromInline let sign: Element - public let count: Int - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - /// Creates a sequence of the given type from an un/signed source. - /// - /// - Parameters: - /// - base: The base sequence viewed through this model. - /// - isSigned: A value indicating whether the base sequence is signed. - /// - count: A value used to extend or truncate the base sequence. - /// - element: The type of element produced by this model. - /// - @inlinable public init(_ base: Base, isSigned: Bool = false, count: Int? = nil, as element: Element.Type = Element.self) { - //=--------------------------------------= - Swift.assert(Self.Element.bitWidth.isPowerOf2) - Swift.assert(Base.Element.bitWidth.isPowerOf2) - precondition(Self.Element.bitWidth >= Base.Element.bitWidth) - //=--------------------------------------= - self.base = base - self.sign = Self.Element(repeating: isSigned && self.base.last?.mostSignificantBit == true) - self.count = count ?? Self.count(of: self.base) - } - - //=------------------------------------------------------------------------= - // MARK: Accessors - //=------------------------------------------------------------------------= - - /// Returns the element at the given index. - /// - /// Its elements are ordered from least significant to most, with infinite sign extension. - /// - @inlinable public subscript(index: Int) -> Element { - precondition(index >= 0 as Int, NBK.callsiteOutOfBoundsInfo()) - //=--------------------------------------= - var shift = 0 as Int - var major = 0 as Element - let minorindex = index * Self.ratio - - if minorindex < base.count { - var baseIndex = base.index(base.startIndex, offsetBy: minorindex) - while baseIndex < base.endIndex, shift < Element.bitWidth { - major |= Element(truncatingIfNeeded: Base.Element.Magnitude(bitPattern: base[baseIndex])) &<< shift - shift += Base.Element.bitWidth - base.formIndex(after: &baseIndex) - } - } - - return shift >= Element.bitWidth ? major : major | sign &<< shift - } - - //=------------------------------------------------------------------------= - // MARK: Utilities x Private - //=------------------------------------------------------------------------= - - @inlinable static var ratio: Int { - Self.Element.bitWidth / Base.Element.bitWidth - } - - @inlinable static func count(of base: Base) -> Int { - let division = base.count.quotientAndRemainder(dividingBy: Self.ratio) - return division.quotient + Int(bit: !division.remainder.isZero) - } -} - -//=----------------------------------------------------------------------------= -// MARK: + Collection -//=----------------------------------------------------------------------------= - -extension NBKMajorInteger { - - //=------------------------------------------------------------------------= - // MARK: Accessors - //=------------------------------------------------------------------------= - - @inlinable public var startIndex: Int { - 0 as Int - } - - @inlinable public var endIndex: Int { - self.count - } - - @inlinable public var indices: Range { - Range(uncheckedBounds:(0 as Int, self.count)) - } - - //=------------------------------------------------------------------------= - // MARK: Utilities - //=------------------------------------------------------------------------= - - @inlinable public func distance(from start: Int, to end: Int) -> Int { - end - start - } - - @inlinable public func index(after index: Int) -> Int { - index + 1 as Int - } - - @inlinable public func formIndex(after index: inout Int) { - index += 1 as Int - } - - @inlinable public func index(before index: Int) -> Int { - index - 1 as Int - } - - @inlinable public func formIndex(before index: inout Int) { - index -= 1 as Int - } - - @inlinable public func index(_ index: Int, offsetBy distance: Int) -> Int { - index + distance - } - - @inlinable public func index(_ index: Int, offsetBy distance: Int, limitedBy limit: Int) -> Int? { - NBK.arrayIndex(index, offsetBy: distance, limitedBy: limit) - } -} diff --git a/Sources/NBKCoreKit/Models/NBKMajorOrMinorInteger.swift b/Sources/NBKCoreKit/Models/NBKMajorOrMinorInteger.swift index 8a139468..15da8bbf 100644 --- a/Sources/NBKCoreKit/Models/NBKMajorOrMinorInteger.swift +++ b/Sources/NBKCoreKit/Models/NBKMajorOrMinorInteger.swift @@ -29,17 +29,19 @@ Element: NBKCoreInteger, Base: RandomAccessCollection, Base.Element: NBKCoreInte public typealias Base = Base - public typealias Major = NBKMajorInteger + @frozen @usableFromInline enum Major { } - public typealias Minor = NBKMinorInteger + @frozen @usableFromInline enum Minor { } + + @frozen @usableFromInline enum Equal { } - @frozen @usableFromInline enum Storage { case major(Major), minor(Minor) } - //=------------------------------------------------------------------------= // MARK: State //=------------------------------------------------------------------------= - @usableFromInline let storage: Storage + @usableFromInline let base: Base + @usableFromInline let sign: Element + public let count: Int //=------------------------------------------------------------------------= // MARK: Initializers @@ -48,35 +50,132 @@ Element: NBKCoreInteger, Base: RandomAccessCollection, Base.Element: NBKCoreInte /// Creates a sequence of the given type from an un/signed source. /// /// - Parameters: - /// - base: The base sequence viewed through this model. - /// - isSigned: A value indicating whether the base sequence is signed. - /// - count: A value used to extend or truncate the base sequence. - /// - element: The type of element produced by this model. + /// - base: The base sequence viewed through this sequence. + /// - isSigned: The signedness of the base sequence. + /// - count: An optionally chosen number of elements to view. + /// - element: The type of element produced by this sequence. /// @inlinable public init(_ base: Base, isSigned: Bool = false, count: Int? = nil, as element: Element.Type = Element.self) { - switch Self.Element.bitWidth > Base.Element.bitWidth { - case true: self.storage = .major(Major(base, isSigned: isSigned, count: count)) - case false: self.storage = .minor(Minor(base, isSigned: isSigned, count: count)) } + Swift.assert(Self.Element.bitWidth.isPowerOf2) + Swift.assert(Base.Element.bitWidth.isPowerOf2) + + self.base = base + self.sign = Self.Element(repeating: isSigned && self.base.last?.mostSignificantBit == true) + self.count = count ?? Self.count(of: self.base) } //=------------------------------------------------------------------------= // MARK: Accessors //=------------------------------------------------------------------------= - @inlinable public var count: Int { - switch storage { - case let .major(base): return base.count - case let .minor(base): return base.count } + @inlinable static func count(of base: Base) -> Int { + if Self.Element.bitWidth > Base.Element.bitWidth { + return Major.count(of: base) + } else if Self.Element.bitWidth < Base.Element.bitWidth { + return Minor.count(of: base) + } else { + return Equal.count(of: base) + } } /// Returns the element at the given index. /// - /// Its elements are ordered from least significant to most, with infinite sign extension. + /// The elements are ordered from least significant to most, with infinite sign extension. /// @inlinable public subscript(index: Int) -> Element { - switch storage { - case let .major(base): return base[index] - case let .minor(base): return base[index] } + if Self.Element.bitWidth > Base.Element.bitWidth { + return Major.element(index, base: self.base, sign: self.sign) + } else if Self.Element.bitWidth < Base.Element.bitWidth { + return Minor.element(index, base: self.base, sign: self.sign) + } else { + return Equal.element(index, base: self.base, sign: self.sign) + } + } +} + +//=----------------------------------------------------------------------------= +// MARK: + Major +//=----------------------------------------------------------------------------= + +extension NBKMajorOrMinorInteger.Major { + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + @inlinable static var ratio: Int { + Element.bitWidth / Base.Element.bitWidth + } + + @inlinable static func count(of base: Base) -> Int { + let division = base.count.quotientAndRemainder(dividingBy: self.ratio) + return division.quotient + Int(bit: !division.remainder.isZero) + } + + @inlinable static func element(_ index: Int, base: Base, sign: Element) -> Element { + precondition(index >= 0 as Int, NBK.callsiteOutOfBoundsInfo()) + + var shift = 0 as Int + var major = 0 as Element + let minorindex = index * self.ratio + + if minorindex < base.count { + var baseIndex = base.index(base.startIndex, offsetBy: minorindex) + while baseIndex < base.endIndex, shift < Element.bitWidth { + major |= Element(truncatingIfNeeded: Base.Element.Magnitude(bitPattern: base[baseIndex])) &<< shift + shift += Base.Element.bitWidth + base.formIndex(after: &baseIndex) + } + } + + return shift >= Element.bitWidth ? major : major | sign &<< shift + } +} + +//=----------------------------------------------------------------------------= +// MARK: + Minor +//=----------------------------------------------------------------------------= + +extension NBKMajorOrMinorInteger.Minor { + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + @inlinable static var ratio: Int { + Base.Element.bitWidth / Element.bitWidth + } + + @inlinable static func count(of base: Base) -> Int { + base.count * self.ratio + } + + @inlinable static func element(_ index: Int, base: Base, sign: Element) -> Element { + precondition(index >= 0 as Int, NBK.callsiteOutOfBoundsInfo()) + let (quotient, remainder) = index.quotientAndRemainder(dividingBy: self.ratio) + guard quotient < base.count else { return sign } + let major = base[base.index(base.startIndex, offsetBy: quotient)] + return Element(truncatingIfNeeded: major &>> (remainder * Element.bitWidth)) + } +} + +//=----------------------------------------------------------------------------= +// MARK: + Equal +//=----------------------------------------------------------------------------= + +extension NBKMajorOrMinorInteger.Equal { + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + @inlinable static func count(of base: Base) -> Int { + base.count + } + + @inlinable static func element(_ index: Int, base: Base, sign: Element) -> Element { + guard index < base.count else { return sign } + return NBK.initOrBitCast(truncating: base[base.index(base.startIndex, offsetBy: index)]) } } diff --git a/Sources/NBKCoreKit/Models/NBKMinorInteger.swift b/Sources/NBKCoreKit/Models/NBKMinorInteger.swift deleted file mode 100644 index 3f01b8ab..00000000 --- a/Sources/NBKCoreKit/Models/NBKMinorInteger.swift +++ /dev/null @@ -1,146 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -//*============================================================================* -// MARK: * NBK x Minor Integer -//*============================================================================* - -/// A sequence that splits elements of an un/signed integer sequence. -/// -/// To use this sequence, its element type must fit in the base sequence's element type. -/// -/// ```swift -/// for byte in NBKMinorInteger(source, isSigned: false, count: nil, as: Int8.self) { ... } -/// ``` -/// -/// ### Binary Integer Order -/// -/// This sequence is ordered like a binary integer, meaning it merges and splits -/// its elements from least significant to most. You can reorder it by reversing -/// the input, the output, or both. -/// -@frozen public struct NBKMinorInteger: RandomAccessCollection where -Element: NBKCoreInteger, Base: RandomAccessCollection, Base.Element: NBKCoreInteger { - - public typealias Base = Base - - //=------------------------------------------------------------------------= - // MARK: State - //=------------------------------------------------------------------------= - - @usableFromInline let base: Base - @usableFromInline let sign: Self.Element - public let count: Int - - //=------------------------------------------------------------------------= - // MARK: Initializers - //=------------------------------------------------------------------------= - - /// Creates a sequence of the given type from an un/signed source. - /// - /// - Parameters: - /// - base: The base sequence viewed through this model. - /// - isSigned: A value indicating whether the base sequence is signed. - /// - count: A value used to extend or truncate the base sequence. - /// - element: The type of element produced by this model. - /// - @inlinable public init(_ base: Base, isSigned: Bool = false, count: Int? = nil, as element: Element.Type = Element.self) { - //=--------------------------------------= - Swift.assert(Base.Element.bitWidth.isPowerOf2) - Swift.assert(Self.Element.bitWidth.isPowerOf2) - precondition(Base.Element.bitWidth >= Self.Element.bitWidth) - //=--------------------------------------= - self.base = base - self.sign = Self.Element(repeating: isSigned && self.base.last?.mostSignificantBit == true) - self.count = count ?? Self.count(of: self.base) - } - - //=------------------------------------------------------------------------= - // MARK: Accessors - //=------------------------------------------------------------------------= - - /// Returns the element at the given index. - /// - /// Its elements are ordered from least significant to most, with infinite sign extension. - /// - @inlinable public subscript(index: Int) -> Element { - precondition(index >= 0 as Int, NBK.callsiteOutOfBoundsInfo()) - let (quotient, remainder) = index.quotientAndRemainder(dividingBy: Self.ratio) - guard quotient < self.base.count else { return self.sign } - let major = self.base[self.base.index(self.base.startIndex, offsetBy: quotient)] - return Self.Element(truncatingIfNeeded: major &>> (remainder * Element.bitWidth)) - } - - //=------------------------------------------------------------------------= - // MARK: Utilities x Private - //=------------------------------------------------------------------------= - - @inlinable static var ratio: Int { - Base.Element.bitWidth / Self.Element.bitWidth - } - - @inlinable static func count(of base: Base) -> Int { - Self.ratio * base.count - } -} - -//=----------------------------------------------------------------------------= -// MARK: + Collection -//=----------------------------------------------------------------------------= - -extension NBKMinorInteger { - - //=------------------------------------------------------------------------= - // MARK: Accessors - //=------------------------------------------------------------------------= - - @inlinable public var startIndex: Int { - 0 as Int - } - - @inlinable public var endIndex: Int { - self.count - } - - @inlinable public var indices: Range { - Range(uncheckedBounds:(0 as Int, self.count)) - } - - //=------------------------------------------------------------------------= - // MARK: Utilities - //=------------------------------------------------------------------------= - - @inlinable public func distance(from start: Int, to end: Int) -> Int { - end - start - } - - @inlinable public func index(after index: Int) -> Int { - index + 1 as Int - } - - @inlinable public func formIndex(after index: inout Int) { - index += 1 as Int - } - - @inlinable public func index(before index: Int) -> Int { - index - 1 as Int - } - - @inlinable public func formIndex(before index: inout Int) { - index -= 1 as Int - } - - @inlinable public func index(_ index: Int, offsetBy distance: Int) -> Int { - index + distance - } - - @inlinable public func index(_ index: Int, offsetBy distance: Int, limitedBy limit: Int) -> Int? { - NBK.arrayIndex(index, offsetBy: distance, limitedBy: limit) - } -} diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text.swift index 8260d281..7aa48e0b 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text.swift @@ -76,7 +76,7 @@ extension NBKDoubleWidth where High == High.Magnitude { if digits.isEmpty { value.base.baseAddress!.advanced(by: value.baseSubscriptIndex(index)).initialize(to: 0000) } else { - let chunk = NBK.UnsafeUTF8(rebasing: NBK.removeSuffix(from: &digits, maxLength: radix.exponent)) + let chunk = NBK.UnsafeUTF8(rebasing: NBK.removeSuffix(from: &digits, maxLength: radix.exponent)) guard let word = NBK.truncating(digits: chunk, radix: radix.base, as: UInt.self) else { return error = true } value.base.baseAddress!.advanced(by: value.baseSubscriptIndex(index)).initialize(to: word) } diff --git a/Sources/Numberick/Documentation.docc/Documentation.md b/Sources/Numberick/Documentation.docc/Documentation.md index d064e847..ea53203e 100644 --- a/Sources/Numberick/Documentation.docc/Documentation.md +++ b/Sources/Numberick/Documentation.docc/Documentation.md @@ -18,9 +18,7 @@ A new protocol hierarchy that refines Swift's standard library. ### Models - ``NBKEndianness`` -- ``NBKMajorInteger`` - ``NBKMajorOrMinorInteger`` -- ``NBKMinorInteger`` - ``NBKTwinHeaded`` ## NBKDoubleWidthKit @@ -114,9 +112,7 @@ Int256(5) % Int(5), UInt256(5) % UInt(5) - ``NBKDoubleWidth`` - ``NBKEndianness`` -- ``NBKMajorInteger`` - ``NBKMajorOrMinorInteger`` -- ``NBKMinorInteger`` - ``NBKTwinHeaded`` ### Integers diff --git a/Tests/NBKCoreKitBenchmarks/Models/NBKMajorOrMinorInteger.swift b/Tests/NBKCoreKitBenchmarks/Models/NBKMajorOrMinorInteger.swift index f1555f01..f402425d 100644 --- a/Tests/NBKCoreKitBenchmarks/Models/NBKMajorOrMinorInteger.swift +++ b/Tests/NBKCoreKitBenchmarks/Models/NBKMajorOrMinorInteger.swift @@ -28,36 +28,32 @@ final class NBKMajorOrMinorIntegerBenchmarks: XCTestCase { // MARK: Tests x Major //=------------------------------------------------------------------------= - func testUInt32AsUInt64() { + func testUInt32AsUInt32() { var abc = NBK.blackHoleIdentity([ 1, 0, 2, 0, 3, 0, 4, 0] as Y) var xyz = NBK.blackHoleIdentity([~1, ~0, ~2, ~0, ~3, ~0, ~4, ~0] as Y) for _ in 0 ..< 1_000_000 { - NBK.blackHole(X(T(abc))) - NBK.blackHole(X(T(xyz))) + NBK.blackHole(Y(T(abc))) + NBK.blackHole(Y(T(xyz))) NBK.blackHoleInoutIdentity(&abc) NBK.blackHoleInoutIdentity(&xyz) } } - func testUInt32AsUInt64AsMajor() { + func testUInt32AsUInt64() { var abc = NBK.blackHoleIdentity([ 1, 0, 2, 0, 3, 0, 4, 0] as Y) var xyz = NBK.blackHoleIdentity([~1, ~0, ~2, ~0, ~3, ~0, ~4, ~0] as Y) for _ in 0 ..< 1_000_000 { - NBK.blackHole(X(T.Major(abc))) - NBK.blackHole(X(T.Major(xyz))) + NBK.blackHole(X(T(abc))) + NBK.blackHole(X(T(xyz))) NBK.blackHoleInoutIdentity(&abc) NBK.blackHoleInoutIdentity(&xyz) } } - //=------------------------------------------------------------------------= - // MARK: Tests x Minor - //=------------------------------------------------------------------------= - func testUInt64AsUInt32() { var abc = NBK.blackHoleIdentity([ 1, 2, 3, 4] as X) var xyz = NBK.blackHoleIdentity([~1, ~2, ~3, ~4] as X) @@ -71,13 +67,13 @@ final class NBKMajorOrMinorIntegerBenchmarks: XCTestCase { } } - func testUInt64AsUInt32AsMinor() { + func testUInt64AsUInt64() { var abc = NBK.blackHoleIdentity([ 1, 2, 3, 4] as X) var xyz = NBK.blackHoleIdentity([~1, ~2, ~3, ~4] as X) for _ in 0 ..< 1_000_000 { - NBK.blackHole(Y(T.Minor(abc))) - NBK.blackHole(Y(T.Minor(xyz))) + NBK.blackHole(X(T(abc))) + NBK.blackHole(X(T(xyz))) NBK.blackHoleInoutIdentity(&abc) NBK.blackHoleInoutIdentity(&xyz) diff --git a/Tests/NBKCoreKitTests/Models/NBKMajorOrMinorInteger.swift b/Tests/NBKCoreKitTests/Models/NBKMajorOrMinorInteger.swift index e9794e83..c4d463ea 100644 --- a/Tests/NBKCoreKitTests/Models/NBKMajorOrMinorInteger.swift +++ b/Tests/NBKCoreKitTests/Models/NBKMajorOrMinorInteger.swift @@ -202,16 +202,8 @@ file: StaticString = #file, line: UInt = #line) { let rhsUnsigned = rhs.map(B.Magnitude.init(bitPattern:)) //=------------------------------------------= func with(isSigned: Bool) { - do { - XCTAssertEqual(Array(T.init (lhs, isSigned: isSigned)), rhs, file: file, line: line) - XCTAssertEqual(Array(T.init (lhsUnsigned, isSigned: isSigned)), rhsUnsigned, file: file, line: line) - }; if B.bitWidth >= A.bitWidth { - XCTAssertEqual(Array(T.Major(lhs, isSigned: isSigned)), rhs, file: file, line: line) - XCTAssertEqual(Array(T.Major(lhsUnsigned, isSigned: isSigned)), rhsUnsigned, file: file, line: line) - }; if B.bitWidth <= A.bitWidth { - XCTAssertEqual(Array(T.Minor(lhs, isSigned: isSigned)), rhs, file: file, line: line) - XCTAssertEqual(Array(T.Minor(lhsUnsigned, isSigned: isSigned)), rhsUnsigned, file: file, line: line) - } + XCTAssertEqual(Array(T(lhs, isSigned: isSigned)), rhs, file: file, line: line) + XCTAssertEqual(Array(T(lhsUnsigned, isSigned: isSigned)), rhsUnsigned, file: file, line: line) } //=------------------------------------------= if isSigned == nil || isSigned == true { with(isSigned: true ) } From 91c99b7d8bbd18967bb621a57f6420582b0aee17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sun, 3 Sep 2023 17:20:41 +0200 Subject: [PATCH 095/111] [NBKCoreKit] Some minor changes (#73) (#74). --- README.md | 2 +- ...MinorInteger.swift => NBKChunkedInt.swift} | 49 +-- Sources/NBKCoreKit/Models/NBKEndianness.swift | 17 +- .../Documentation.docc/Documentation.md | 4 +- .../Models/NBKChunkedInt.swift | 114 +++++++ .../Models/NBKEndianness.swift | 58 ++++ .../Models/NBKMajorOrMinorInteger.swift | 84 ----- .../Models/NBKChunkedInt.swift | 296 ++++++++++++++++++ .../Models/NBKEndianness.swift | 20 +- .../Models/NBKMajorOrMinorInteger.swift | 213 ------------- .../Models/NBKTwinHeaded.swift | 34 +- 11 files changed, 520 insertions(+), 371 deletions(-) rename Sources/NBKCoreKit/Models/{NBKMajorOrMinorInteger.swift => NBKChunkedInt.swift} (90%) create mode 100644 Tests/NBKCoreKitBenchmarks/Models/NBKChunkedInt.swift create mode 100644 Tests/NBKCoreKitBenchmarks/Models/NBKEndianness.swift delete mode 100644 Tests/NBKCoreKitBenchmarks/Models/NBKMajorOrMinorInteger.swift create mode 100644 Tests/NBKCoreKitTests/Models/NBKChunkedInt.swift delete mode 100644 Tests/NBKCoreKitTests/Models/NBKMajorOrMinorInteger.swift diff --git a/README.md b/README.md index 3da83b13..46f29f2b 100644 --- a/README.md +++ b/README.md @@ -21,8 +21,8 @@ A new protocol hierarchy that refines Swift's standard library. ### Models +- [NBKChunkedInt](Sources/NBKCoreKit/Models/NBKChunkedInt.swift) - [NBKEndianness](Sources/NBKCoreKit/Models/NBKEndianness.swift) -- [NBKMajorOrMinorInteger](Sources/NBKCoreKit/Models/NBKMajorOrMinorInteger.swift) - [NBKTwinHeaded](Sources/NBKCoreKit/Models/NBKTwinHeaded.swift) ## [NBKDoubleWidthKit][DBL/D] ([Sources][DBL/S], [Tests][DBL/T], [Benchmarks][DBL/B]) diff --git a/Sources/NBKCoreKit/Models/NBKMajorOrMinorInteger.swift b/Sources/NBKCoreKit/Models/NBKChunkedInt.swift similarity index 90% rename from Sources/NBKCoreKit/Models/NBKMajorOrMinorInteger.swift rename to Sources/NBKCoreKit/Models/NBKChunkedInt.swift index 15da8bbf..c2506cba 100644 --- a/Sources/NBKCoreKit/Models/NBKMajorOrMinorInteger.swift +++ b/Sources/NBKCoreKit/Models/NBKChunkedInt.swift @@ -8,14 +8,14 @@ //=----------------------------------------------------------------------------= //*============================================================================* -// MARK: * NBK x Major Or Minor Integer +// MARK: * NBK x Chunked Int //*============================================================================* /// A sequence that merges or splits elements of an un/signed integer sequence. /// /// ```swift -/// for word in NBKMajorOrMinorInteger(source, isSigned: false, count: nil, as: UInt.self) { ... } -/// for byte in NBKMajorOrMinorInteger(source, isSigned: false, count: nil, as: Int8.self) { ... } +/// for word in NBKChunkedInt(source, isSigned: false, count: nil, as: UInt.self) { ... } +/// for byte in NBKChunkedInt(source, isSigned: false, count: nil, as: Int8.self) { ... } /// ``` /// /// ### Binary Integer Order @@ -24,9 +24,10 @@ /// its elements from least significant to most. You can reorder it by reversing /// the input, the output, or both. /// -@frozen public struct NBKMajorOrMinorInteger: RandomAccessCollection where +@frozen public struct NBKChunkedInt: RandomAccessCollection where Element: NBKCoreInteger, Base: RandomAccessCollection, Base.Element: NBKCoreInteger { + /// The base sequence type. public typealias Base = Base @frozen @usableFromInline enum Major { } @@ -68,16 +69,6 @@ Element: NBKCoreInteger, Base: RandomAccessCollection, Base.Element: NBKCoreInte // MARK: Accessors //=------------------------------------------------------------------------= - @inlinable static func count(of base: Base) -> Int { - if Self.Element.bitWidth > Base.Element.bitWidth { - return Major.count(of: base) - } else if Self.Element.bitWidth < Base.Element.bitWidth { - return Minor.count(of: base) - } else { - return Equal.count(of: base) - } - } - /// Returns the element at the given index. /// /// The elements are ordered from least significant to most, with infinite sign extension. @@ -91,13 +82,27 @@ Element: NBKCoreInteger, Base: RandomAccessCollection, Base.Element: NBKCoreInte return Equal.element(index, base: self.base, sign: self.sign) } } + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + @inlinable static func count(of base: Base) -> Int { + if Self.Element.bitWidth > Base.Element.bitWidth { + return Major.count(of: base) + } else if Self.Element.bitWidth < Base.Element.bitWidth { + return Minor.count(of: base) + } else { + return Equal.count(of: base) + } + } } //=----------------------------------------------------------------------------= // MARK: + Major //=----------------------------------------------------------------------------= -extension NBKMajorOrMinorInteger.Major { +extension NBKChunkedInt.Major { //=------------------------------------------------------------------------= // MARK: Utilities @@ -113,14 +118,12 @@ extension NBKMajorOrMinorInteger.Major { } @inlinable static func element(_ index: Int, base: Base, sign: Element) -> Element { - precondition(index >= 0 as Int, NBK.callsiteOutOfBoundsInfo()) - var shift = 0 as Int var major = 0 as Element - let minorindex = index * self.ratio + let minor = index as Int * self.ratio - if minorindex < base.count { - var baseIndex = base.index(base.startIndex, offsetBy: minorindex) + if minor < base.count { + var baseIndex = base.index(base.startIndex, offsetBy: minor) while baseIndex < base.endIndex, shift < Element.bitWidth { major |= Element(truncatingIfNeeded: Base.Element.Magnitude(bitPattern: base[baseIndex])) &<< shift shift += Base.Element.bitWidth @@ -136,7 +139,7 @@ extension NBKMajorOrMinorInteger.Major { // MARK: + Minor //=----------------------------------------------------------------------------= -extension NBKMajorOrMinorInteger.Minor { +extension NBKChunkedInt.Minor { //=------------------------------------------------------------------------= // MARK: Utilities @@ -163,7 +166,7 @@ extension NBKMajorOrMinorInteger.Minor { // MARK: + Equal //=----------------------------------------------------------------------------= -extension NBKMajorOrMinorInteger.Equal { +extension NBKChunkedInt.Equal { //=------------------------------------------------------------------------= // MARK: Utilities @@ -183,7 +186,7 @@ extension NBKMajorOrMinorInteger.Equal { // MARK: + Collection //=----------------------------------------------------------------------------= -extension NBKMajorOrMinorInteger { +extension NBKChunkedInt { //=------------------------------------------------------------------------= // MARK: Accessors diff --git a/Sources/NBKCoreKit/Models/NBKEndianness.swift b/Sources/NBKCoreKit/Models/NBKEndianness.swift index 345f60c1..4dfc3412 100644 --- a/Sources/NBKCoreKit/Models/NBKEndianness.swift +++ b/Sources/NBKCoreKit/Models/NBKEndianness.swift @@ -19,17 +19,17 @@ /// can express the difference, but dynamic solutions are often viable. This type /// encurages the latter. /// -@frozen public enum NBKEndianness: UInt8, Hashable { +@frozen public enum NBKEndianness: Hashable { //=------------------------------------------------------------------------= // MARK: State //=------------------------------------------------------------------------= /// A value representing a least-to-most-significant byte order. - case little = 0x00 + case little /// A value representing a most-to-least-significant byte order. - case big = 0x01 + case big //=------------------------------------------------------------------------= // MARK: Initializers @@ -39,17 +39,8 @@ @inlinable public static var system: Self { #if _endian(little) return .little - #else + #elseif _endian(big) return .big #endif } - - //=------------------------------------------------------------------------= - // MARK: Utilities - //=------------------------------------------------------------------------= - - /// Returns the opposite endianness. - @inlinable public static prefix func !(operand: Self) -> Self { - switch operand { case .little: return .big; case .big: return .little } - } } diff --git a/Sources/Numberick/Documentation.docc/Documentation.md b/Sources/Numberick/Documentation.docc/Documentation.md index ea53203e..75f26446 100644 --- a/Sources/Numberick/Documentation.docc/Documentation.md +++ b/Sources/Numberick/Documentation.docc/Documentation.md @@ -17,8 +17,8 @@ A new protocol hierarchy that refines Swift's standard library. ### Models +- ``NBKChunkedInt`` - ``NBKEndianness`` -- ``NBKMajorOrMinorInteger`` - ``NBKTwinHeaded`` ## NBKDoubleWidthKit @@ -110,9 +110,9 @@ Int256(5) % Int(5), UInt256(5) % UInt(5) ### Models +- ``NBKChunkedInt`` - ``NBKDoubleWidth`` - ``NBKEndianness`` -- ``NBKMajorOrMinorInteger`` - ``NBKTwinHeaded`` ### Integers diff --git a/Tests/NBKCoreKitBenchmarks/Models/NBKChunkedInt.swift b/Tests/NBKCoreKitBenchmarks/Models/NBKChunkedInt.swift new file mode 100644 index 00000000..fc2ec6f9 --- /dev/null +++ b/Tests/NBKCoreKitBenchmarks/Models/NBKChunkedInt.swift @@ -0,0 +1,114 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if !DEBUG + +import NBKCoreKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Chunked Int +//*============================================================================* + +final class NBKChunkedIntBenchmarks: XCTestCase { + + typealias T = NBKChunkedInt + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testUInt32AsUInt32() { + var abc = NBK.blackHoleIdentity(Y(repeating: .min, count: 144)) + var xyz = NBK.blackHoleIdentity(Y(repeating: .max, count: 144)) + + for _ in 0 ..< 144_000 { + NBK.blackHole(Y(T(abc))) + NBK.blackHole(Y(T(xyz))) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testUInt32AsUInt64() { + var abc = NBK.blackHoleIdentity(Y(repeating: .min, count: 144)) + var xyz = NBK.blackHoleIdentity(Y(repeating: .max, count: 144)) + + for _ in 0 ..< 144_000 { + NBK.blackHole(X(T(abc))) + NBK.blackHole(X(T(xyz))) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testUInt64AsUInt32() { + var abc = NBK.blackHoleIdentity(X(repeating: .min, count: 144)) + var xyz = NBK.blackHoleIdentity(X(repeating: .max, count: 144)) + + for _ in 0 ..< 144_000 { + NBK.blackHole(Y(T(abc))) + NBK.blackHole(Y(T(xyz))) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testUInt64AsUInt64() { + var abc = NBK.blackHoleIdentity(X(repeating: .min, count: 144)) + var xyz = NBK.blackHoleIdentity(X(repeating: .max, count: 144)) + + for _ in 0 ..< 144_000 { + NBK.blackHole(X(T(abc))) + NBK.blackHole(X(T(xyz))) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Miscellaneous + //=------------------------------------------------------------------------= + + func testUInt32AsUInt32ByUnsafeBufferPointer() { + var abc = NBK.blackHoleIdentity(Y(repeating: .min, count: 144)) + var xyz = NBK.blackHoleIdentity(Y(repeating: .max, count: 144)) + + for _ in 0 ..< 144_000 { + NBK.blackHole(abc.withUnsafeBufferPointer(Y.init)) + NBK.blackHole(xyz.withUnsafeBufferPointer(Y.init)) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testUInt64AsUInt64ByUnsafeBufferPointer() { + var abc = NBK.blackHoleIdentity(X(repeating: .min, count: 144)) + var xyz = NBK.blackHoleIdentity(X(repeating: .max, count: 144)) + + for _ in 0 ..< 144_000 { + NBK.blackHole(abc.withUnsafeBufferPointer(X.init)) + NBK.blackHole(xyz.withUnsafeBufferPointer(X.init)) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } +} + +#endif diff --git a/Tests/NBKCoreKitBenchmarks/Models/NBKEndianness.swift b/Tests/NBKCoreKitBenchmarks/Models/NBKEndianness.swift new file mode 100644 index 00000000..f17ba682 --- /dev/null +++ b/Tests/NBKCoreKitBenchmarks/Models/NBKEndianness.swift @@ -0,0 +1,58 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if !DEBUG + +import NBKCoreKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Endianness +//*============================================================================* + +final class NBKEndiannessBenchmarks: XCTestCase { + + typealias T = NBKEndianness + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testIsEqualTo() { + var abc = NBK.blackHoleIdentity(T.little) + var xyz = NBK.blackHoleIdentity(T.big ) + + for _ in 0 ..< 5_000_000 { + NBK.blackHole(abc == T.system) + NBK.blackHole(xyz == T.system) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testHashValue() { + var abc = NBK.blackHoleIdentity(T.little) + var xyz = NBK.blackHoleIdentity(T.big ) + + for _ in 0 ..< 1_000_000 { + NBK.blackHole(abc.hashValue) + NBK.blackHole(xyz.hashValue) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } +} + +#endif diff --git a/Tests/NBKCoreKitBenchmarks/Models/NBKMajorOrMinorInteger.swift b/Tests/NBKCoreKitBenchmarks/Models/NBKMajorOrMinorInteger.swift deleted file mode 100644 index f402425d..00000000 --- a/Tests/NBKCoreKitBenchmarks/Models/NBKMajorOrMinorInteger.swift +++ /dev/null @@ -1,84 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if !DEBUG - -import NBKCoreKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Major Or Minor Integer -//*============================================================================* - -final class NBKMajorOrMinorIntegerBenchmarks: XCTestCase { - - typealias T = NBKMajorOrMinorInteger - - //=------------------------------------------------------------------------= - // MARK: Tests x Major - //=------------------------------------------------------------------------= - - func testUInt32AsUInt32() { - var abc = NBK.blackHoleIdentity([ 1, 0, 2, 0, 3, 0, 4, 0] as Y) - var xyz = NBK.blackHoleIdentity([~1, ~0, ~2, ~0, ~3, ~0, ~4, ~0] as Y) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(Y(T(abc))) - NBK.blackHole(Y(T(xyz))) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - func testUInt32AsUInt64() { - var abc = NBK.blackHoleIdentity([ 1, 0, 2, 0, 3, 0, 4, 0] as Y) - var xyz = NBK.blackHoleIdentity([~1, ~0, ~2, ~0, ~3, ~0, ~4, ~0] as Y) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(X(T(abc))) - NBK.blackHole(X(T(xyz))) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - func testUInt64AsUInt32() { - var abc = NBK.blackHoleIdentity([ 1, 2, 3, 4] as X) - var xyz = NBK.blackHoleIdentity([~1, ~2, ~3, ~4] as X) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(Y(T(abc))) - NBK.blackHole(Y(T(xyz))) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - func testUInt64AsUInt64() { - var abc = NBK.blackHoleIdentity([ 1, 2, 3, 4] as X) - var xyz = NBK.blackHoleIdentity([~1, ~2, ~3, ~4] as X) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(X(T(abc))) - NBK.blackHole(X(T(xyz))) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } -} - -#endif diff --git a/Tests/NBKCoreKitTests/Models/NBKChunkedInt.swift b/Tests/NBKCoreKitTests/Models/NBKChunkedInt.swift new file mode 100644 index 00000000..716d96f8 --- /dev/null +++ b/Tests/NBKCoreKitTests/Models/NBKChunkedInt.swift @@ -0,0 +1,296 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Chunked Int +//*============================================================================* + +final class NBKChunkedIntTests: XCTestCase { + + private typealias S64 = [Int64] + private typealias S32 = [Int32] + + private typealias T = NBKChunkedInt + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testUInt32AsUInt32() { + NBKAssertChunkedInt([ ] as S32, [ ] as S32) + NBKAssertChunkedInt([ 1 ] as S32, [ 1 ] as S32) + NBKAssertChunkedInt([ 1, 2 ] as S32, [ 1, 2 ] as S32) + NBKAssertChunkedInt([ 1, 2, 3 ] as S32, [ 1, 2, 3 ] as S32) + NBKAssertChunkedInt([ 1, 2, 3, 4] as S32, [ 1, 2, 3, 4] as S32) + + NBKAssertChunkedInt([ ] as S32, [ ] as S32) + NBKAssertChunkedInt([~1 ] as S32, [~1 ] as S32) + NBKAssertChunkedInt([~1, ~2 ] as S32, [~1, ~2 ] as S32) + NBKAssertChunkedInt([~1, ~2, ~3 ] as S32, [~1, ~2, ~3 ] as S32) + NBKAssertChunkedInt([~1, ~2, ~3, ~4] as S32, [~1, ~2, ~3, ~4] as S32) + } + + func testUInt32AsUInt64() { + NBKAssertChunkedInt([ ] as S32, [ ] as S64) + NBKAssertChunkedInt([ 1, 0 ] as S32, [ 1 ] as S64) + NBKAssertChunkedInt([ 1, 0, 2, 0 ] as S32, [ 1, 2 ] as S64) + NBKAssertChunkedInt([ 1, 0, 2, 0, 3, 0 ] as S32, [ 1, 2, 3 ] as S64) + NBKAssertChunkedInt([ 1, 0, 2, 0, 3, 0, 4, 0] as S32, [ 1, 2, 3, 4] as S64) + + NBKAssertChunkedInt([ ] as S32, [ ] as S64) + NBKAssertChunkedInt([~1, ~0 ] as S32, [~1 ] as S64) + NBKAssertChunkedInt([~1, ~0, ~2, ~0 ] as S32, [~1, ~2 ] as S64) + NBKAssertChunkedInt([~1, ~0, ~2, ~0, ~3, ~0 ] as S32, [~1, ~2, ~3 ] as S64) + NBKAssertChunkedInt([~1, ~0, ~2, ~0, ~3, ~0, ~4, ~0] as S32, [~1, ~2, ~3, ~4] as S64) + } + + func testUInt64AsUInt64() { + NBKAssertChunkedInt([ ] as S64, [ ] as S64) + NBKAssertChunkedInt([ 1 ] as S64, [ 1 ] as S64) + NBKAssertChunkedInt([ 1, 2 ] as S64, [ 1, 2 ] as S64) + NBKAssertChunkedInt([ 1, 2, 3 ] as S64, [ 1, 2, 3 ] as S64) + NBKAssertChunkedInt([ 1, 2, 3, 4] as S64, [ 1, 2, 3, 4] as S64) + + NBKAssertChunkedInt([ ] as S64, [ ] as S64) + NBKAssertChunkedInt([~1 ] as S64, [~1 ] as S64) + NBKAssertChunkedInt([~1, ~2 ] as S64, [~1, ~2 ] as S64) + NBKAssertChunkedInt([~1, ~2, ~3 ] as S64, [~1, ~2, ~3 ] as S64) + NBKAssertChunkedInt([~1, ~2, ~3, ~4] as S64, [~1, ~2, ~3, ~4] as S64) + } + + func testUInt64AsUInt32() { + NBKAssertChunkedInt([ ] as S64, [ ] as S32) + NBKAssertChunkedInt([ 1 ] as S64, [ 1, 0 ] as S32) + NBKAssertChunkedInt([ 1, 2 ] as S64, [ 1, 0, 2, 0 ] as S32) + NBKAssertChunkedInt([ 1, 2, 3 ] as S64, [ 1, 0, 2, 0, 3, 0 ] as S32) + NBKAssertChunkedInt([ 1, 2, 3, 4] as S64, [ 1, 0, 2, 0, 3, 0, 4, 0] as S32) + + NBKAssertChunkedInt([ ] as S64, [ ] as S32) + NBKAssertChunkedInt([~1 ] as S64, [~1, ~0 ] as S32) + NBKAssertChunkedInt([~1, ~2 ] as S64, [~1, ~0, ~2, ~0 ] as S32) + NBKAssertChunkedInt([~1, ~2, ~3 ] as S64, [~1, ~0, ~2, ~0, ~3, ~0 ] as S32) + NBKAssertChunkedInt([~1, ~2, ~3, ~4] as S64, [~1, ~0, ~2, ~0, ~3, ~0, ~4, ~0] as S32) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Count + //=------------------------------------------------------------------------= + + func testUInt32AsUInt64WithCustomCount() { + XCTAssertEqual([1, 2 ], Array(T([1, 0, 2, 0] as S32, count: nil, as: Int64.self))) + XCTAssertEqual([ ], Array(T([1, 0, 2, 0] as S32, count: 000, as: Int64.self))) + XCTAssertEqual([1 ], Array(T([1, 0, 2, 0] as S32, count: 001, as: Int64.self))) + XCTAssertEqual([1, 2 ], Array(T([1, 0, 2, 0] as S32, count: 002, as: Int64.self))) + XCTAssertEqual([1, 2, 0], Array(T([1, 0, 2, 0] as S32, count: 003, as: Int64.self))) + } + + func testUInt64AsUInt32WithCustomCount() { + XCTAssertEqual([1, 0, 2, 0 ], Array(T([1, 2] as S64, count: nil, as: Int32.self))) + XCTAssertEqual([ ], Array(T([1, 2] as S64, count: 000, as: Int32.self))) + XCTAssertEqual([1 ], Array(T([1, 2] as S64, count: 001, as: Int32.self))) + XCTAssertEqual([1, 0 ], Array(T([1, 2] as S64, count: 002, as: Int32.self))) + XCTAssertEqual([1, 0, 2 ], Array(T([1, 2] as S64, count: 003, as: Int32.self))) + XCTAssertEqual([1, 0, 2, 0 ], Array(T([1, 2] as S64, count: 004, as: Int32.self))) + XCTAssertEqual([1, 0, 2, 0, 0 ], Array(T([1, 2] as S64, count: 005, as: Int32.self))) + XCTAssertEqual([1, 0, 2, 0, 0, 0], Array(T([1, 2] as S64, count: 006, as: Int32.self))) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Signed or Unsigned + //=------------------------------------------------------------------------= + + func testSubscriptSignExtension() { + XCTAssertEqual(T([ 0] as S32, isSigned: false, as: Int32.self)[144], 0) + XCTAssertEqual(T([ 0] as S32, isSigned: true, as: Int32.self)[144], 0) + XCTAssertEqual(T([~0] as S32, isSigned: false, as: Int32.self)[144], 0) + XCTAssertEqual(T([~0] as S32, isSigned: true, as: Int32.self)[144], ~0) + + XCTAssertEqual(T([ 0] as S32, isSigned: false, as: Int64.self)[144], 0) + XCTAssertEqual(T([ 0] as S32, isSigned: true, as: Int64.self)[144], 0) + XCTAssertEqual(T([~0] as S32, isSigned: false, as: Int64.self)[144], 0) + XCTAssertEqual(T([~0] as S32, isSigned: true, as: Int64.self)[144], ~0) + + XCTAssertEqual(T([ 0] as S64, isSigned: false, as: Int32.self)[144], 0) + XCTAssertEqual(T([ 0] as S64, isSigned: true, as: Int32.self)[144], 0) + XCTAssertEqual(T([~0] as S64, isSigned: false, as: Int32.self)[144], 0) + XCTAssertEqual(T([~0] as S64, isSigned: true, as: Int32.self)[144], ~0) + + XCTAssertEqual(T([ 0] as S64, isSigned: false, as: Int64.self)[144], 0) + XCTAssertEqual(T([ 0] as S64, isSigned: true, as: Int64.self)[144], 0) + XCTAssertEqual(T([~0] as S64, isSigned: false, as: Int64.self)[144], 0) + XCTAssertEqual(T([~0] as S64, isSigned: true, as: Int64.self)[144], ~0) + } + + func testMajorLimbsFromIncompleteMinorLimbs() { + NBKAssertChunkedIntOneWay([ ] as S32, [ ] as S64, isSigned: true ) + NBKAssertChunkedIntOneWay([ 1 ] as S32, [ 1 ] as S64, isSigned: true ) + NBKAssertChunkedIntOneWay([ 1, 0, 2 ] as S32, [ 1, 2 ] as S64, isSigned: true ) + NBKAssertChunkedIntOneWay([ 1, 0, 2, 0, 3 ] as S32, [ 1, 2, 3 ] as S64, isSigned: true ) + NBKAssertChunkedIntOneWay([ 1, 0, 2, 0, 3, 0, 4] as S32, [ 1, 2, 3, 4 ] as S64, isSigned: true ) + + NBKAssertChunkedIntOneWay([ ] as S32, [ ] as S64, isSigned: true ) + NBKAssertChunkedIntOneWay([~1 ] as S32, [~1 ] as S64, isSigned: true ) + NBKAssertChunkedIntOneWay([~1, ~0, ~2 ] as S32, [~1, ~2 ] as S64, isSigned: true ) + NBKAssertChunkedIntOneWay([~1, ~0, ~2, ~0, ~3 ] as S32, [~1, ~2, ~3 ] as S64, isSigned: true ) + NBKAssertChunkedIntOneWay([~1, ~0, ~2, ~0, ~3, ~0, ~4] as S32, [~1, ~2, ~3, ~4 ] as S64, isSigned: true ) + + NBKAssertChunkedIntOneWay([ ] as S32, [ ] as S64, isSigned: false) + NBKAssertChunkedIntOneWay([ 1 ] as S32, [ 1 ] as S64, isSigned: false) + NBKAssertChunkedIntOneWay([ 1, 0, 2 ] as S32, [ 1, 2 ] as S64, isSigned: false) + NBKAssertChunkedIntOneWay([ 1, 0, 2, 0, 3 ] as S32, [ 1, 2, 3 ] as S64, isSigned: false) + NBKAssertChunkedIntOneWay([ 1, 0, 2, 0, 3, 0, 4] as S32, [ 1, 2, 3, 4 ] as S64, isSigned: false) + + NBKAssertChunkedIntOneWay([ ] as S32, [ ] as S64, isSigned: false) + NBKAssertChunkedIntOneWay([~1 ] as S32, [ 0xfffffffe] as S64, isSigned: false) + NBKAssertChunkedIntOneWay([~1, ~0, ~2 ] as S32, [~1, 0xfffffffd] as S64, isSigned: false) + NBKAssertChunkedIntOneWay([~1, ~0, ~2, ~0, ~3 ] as S32, [~1, ~2, 0xfffffffc] as S64, isSigned: false) + NBKAssertChunkedIntOneWay([~1, ~0, ~2, ~0, ~3, ~0, ~4] as S32, [~1, ~2, ~3, 0xfffffffb] as S64, isSigned: false) + } + + //=------------------------------------------------------------------------= + // MARK: Tests x Miscellaneous + //=------------------------------------------------------------------------= + + func testMajorToMinorComposableReordering() { + XCTAssertEqual([1, 2, 3, 4], Array(T(([0x0201, 0x0403] as [Int16]), as: Int8.self))) + XCTAssertEqual([2, 1, 4, 3], Array(T(([0x0201, 0x0403] as [Int16]).reversed(), as: Int8.self)).reversed()) + XCTAssertEqual([3, 4, 1, 2], Array(T(([0x0201, 0x0403] as [Int16]).reversed(), as: Int8.self))) + XCTAssertEqual([4, 3, 2, 1], Array(T(([0x0201, 0x0403] as [Int16]), as: Int8.self)).reversed()) + } + + func testMinorToMajorComposableReordering() { + XCTAssertEqual([0x0201, 0x0403], Array(T(([1, 2, 3, 4] as [Int8]), as: Int16.self))) + XCTAssertEqual([0x0102, 0x0304], Array(T(([1, 2, 3, 4] as [Int8]).reversed(), as: Int16.self)).reversed()) + XCTAssertEqual([0x0403, 0x0201], Array(T(([1, 2, 3, 4] as [Int8]), as: Int16.self)).reversed()) + XCTAssertEqual([0x0304, 0x0102], Array(T(([1, 2, 3, 4] as [Int8]).reversed(), as: Int16.self))) + } +} + +//*============================================================================* +// MARK: * NBK x Chunked Int x Assertions +//*============================================================================* + +private func NBKAssertChunkedInt( +_ lhs: [A], _ rhs: [B], isSigned: Bool? = nil, +file: StaticString = #file, line: UInt = #line) { + + NBKAssertChunkedIntOneWay(lhs, rhs, isSigned: isSigned, file: file, line: line) + NBKAssertChunkedIntOneWay(rhs, lhs, isSigned: isSigned, file: file, line: line) +} + +private func NBKAssertChunkedIntOneWay( +_ lhs: [A], _ rhs: [B], isSigned: Bool? = nil, +file: StaticString = #file, line: UInt = #line) { + typealias T = NBKChunkedInt + //=------------------------------------------= + let lhsUnsigned = lhs.map(A.Magnitude.init(bitPattern:)) + let rhsUnsigned = rhs.map(B.Magnitude.init(bitPattern:)) + //=------------------------------------------= + func with(isSigned: Bool) { + NBKAssertIteration(T(lhs, isSigned: isSigned), rhs, file: file, line: line) + NBKAssertIteration(T(lhsUnsigned, isSigned: isSigned), rhsUnsigned, file: file, line: line) + } + //=------------------------------------------= + if isSigned == nil || isSigned == true { with(isSigned: true ) } + if isSigned == nil || isSigned == false { with(isSigned: false) } +} + +//=----------------------------------------------------------------------------= +// MARK: + Collection +//=----------------------------------------------------------------------------= + +private func NBKAssertIteration( +_ lhs: NBKChunkedInt, _ rhs: [Element], +file: StaticString = #file, line: UInt = #line) { + XCTAssertEqual(Array(lhs), rhs, file: file, line: line) + XCTAssertEqual(Array(lhs.reversed()), rhs.reversed(), file: file, line: line) + + testIndices: do { + for lhsIndex in lhs.indices.enumerated() { + XCTAssertEqual(lhs[lhsIndex.element], rhs[lhsIndex.offset], file: file, line: line) + } + } + + testFrontToBack: do { + var lhsIndex = lhs.startIndex + var rhsIndex = rhs.startIndex + while lhsIndex < lhs.endIndex { + let lhsIndexAfter = lhs.index(after: lhsIndex) + let rhsIndexAfter = rhs.index(after: lhsIndex) + + XCTAssertEqual(lhs[lhsIndex], rhs[rhsIndex], file: file, line: line) + XCTAssertEqual(lhsIndexAfter, rhsIndexAfter, file: file, line: line) + + lhs.formIndex(after: &lhsIndex) + rhs.formIndex(after: &rhsIndex) + } + } + + testBackToFront: do { + var lhsIndex = lhs.endIndex + var rhsIndex = rhs.endIndex + while lhsIndex > lhs.startIndex { + let lhsIndexBefore = lhs.index(before: lhsIndex) + let rhsIndexBefore = rhs.index(before: lhsIndex) + + lhs.formIndex(before: &lhsIndex) + rhs.formIndex(before: &rhsIndex) + + XCTAssertEqual(lhs[lhsIndex], rhs[rhsIndex], file: file, line: line) + XCTAssertEqual(lhsIndexBefore, rhsIndexBefore, file: file, line: line) + } + } + + testDropFirst: do { + for dropFirst in 0 ..< (2 * lhs.count) { + let lhsDropFirst = lhs.dropFirst(dropFirst) + let rhsDropFirst = rhs.dropFirst(dropFirst) + + let lhsDropFirstIndices = lhs.indices[lhsDropFirst.indices] + let rhsDropFirstIndices = rhs.indices[rhsDropFirst.indices] + + XCTAssertEqual(Array(lhsDropFirst), Array(rhsDropFirst), file: file, line: line) + XCTAssertEqual(Array(lhs[lhsDropFirstIndices]), Array(rhs[rhsDropFirstIndices]), file: file, line: line) + + if let first = lhs.dropFirst(dropFirst).first { + let firstIndex = lhs.index(lhs.startIndex, offsetBy: dropFirst) + XCTAssertEqual(first, lhs[firstIndex], file: file, line: line) + } + } + } + + testDropLast: do { + for dropLast in 0 ..< (2 * lhs.count) { + let lhsDropLast = lhs.dropFirst(dropLast) + let rhsDropLast = rhs.dropFirst(dropLast) + + let lhsDropLastIndices = lhs.indices[lhsDropLast.indices] + let rhsDropLastIndices = rhs.indices[rhsDropLast.indices] + + XCTAssertEqual(Array(lhsDropLast), Array(rhsDropLast), file: file, line: line) + XCTAssertEqual(Array(lhs[lhsDropLastIndices]), Array(rhs[rhsDropLastIndices]), file: file, line: line) + + if let last = lhs.dropLast(dropLast).last { + let lastIndex = lhs.index(lhs.endIndex, offsetBy: ~dropLast) + XCTAssertEqual(last, lhs[lastIndex], file: file, line: line) + } + } + } +} + +#endif diff --git a/Tests/NBKCoreKitTests/Models/NBKEndianness.swift b/Tests/NBKCoreKitTests/Models/NBKEndianness.swift index 70613a17..53da0069 100644 --- a/Tests/NBKCoreKitTests/Models/NBKEndianness.swift +++ b/Tests/NBKCoreKitTests/Models/NBKEndianness.swift @@ -24,29 +24,13 @@ final class NBKEndiannessTests: XCTestCase { // MARK: Tests //=------------------------------------------------------------------------= - func testSystemValue() { - #if _endian(little) + func testSystem() { + #if _endian(little) XCTAssertEqual(T.system, T.little) #elseif _endian(big) XCTAssertEqual(T.system, T.big) #endif } - - func testOppositeValue() { - XCTAssertEqual(!T.big, T.little) - XCTAssertEqual(!T.little, T.big) - } - - func testToRawValue() { - XCTAssertEqual(0x00 as UInt8, T.little.rawValue) - XCTAssertEqual(0x01 as UInt8, T.big.rawValue) - } - - func testFromRawValue() { - XCTAssertEqual(T(rawValue: 0x00 as UInt8), T.little) - XCTAssertEqual(T(rawValue: 0x01 as UInt8), T.big) - XCTAssertEqual(T(rawValue: 0x02 as UInt8), nil) - } } #endif diff --git a/Tests/NBKCoreKitTests/Models/NBKMajorOrMinorInteger.swift b/Tests/NBKCoreKitTests/Models/NBKMajorOrMinorInteger.swift deleted file mode 100644 index c4d463ea..00000000 --- a/Tests/NBKCoreKitTests/Models/NBKMajorOrMinorInteger.swift +++ /dev/null @@ -1,213 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if DEBUG - -import NBKCoreKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Major Or Minor Integer -//*============================================================================* - -final class NBKMajorOrMinorIntegerTests: XCTestCase { - - private typealias S64 = [Int64] - private typealias S32 = [Int32] - - private typealias T = NBKMajorOrMinorInteger - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testUInt32AsUInt32() { - NBKAssertMajorOrMinorInteger([ ] as S32, [ ] as S32) - NBKAssertMajorOrMinorInteger([ 1 ] as S32, [ 1 ] as S32) - NBKAssertMajorOrMinorInteger([ 1, 2 ] as S32, [ 1, 2 ] as S32) - NBKAssertMajorOrMinorInteger([ 1, 2, 3 ] as S32, [ 1, 2, 3 ] as S32) - NBKAssertMajorOrMinorInteger([ 1, 2, 3, 4] as S32, [ 1, 2, 3, 4] as S32) - - NBKAssertMajorOrMinorInteger([ ] as S32, [ ] as S32) - NBKAssertMajorOrMinorInteger([~1 ] as S32, [~1 ] as S32) - NBKAssertMajorOrMinorInteger([~1, ~2 ] as S32, [~1, ~2 ] as S32) - NBKAssertMajorOrMinorInteger([~1, ~2, ~3 ] as S32, [~1, ~2, ~3 ] as S32) - NBKAssertMajorOrMinorInteger([~1, ~2, ~3, ~4] as S32, [~1, ~2, ~3, ~4] as S32) - } - - func testUInt32AsUInt64() { - NBKAssertMajorOrMinorInteger([ ] as S32, [ ] as S64) - NBKAssertMajorOrMinorInteger([ 1, 0 ] as S32, [ 1 ] as S64) - NBKAssertMajorOrMinorInteger([ 1, 0, 2, 0 ] as S32, [ 1, 2 ] as S64) - NBKAssertMajorOrMinorInteger([ 1, 0, 2, 0, 3, 0 ] as S32, [ 1, 2, 3 ] as S64) - NBKAssertMajorOrMinorInteger([ 1, 0, 2, 0, 3, 0, 4, 0] as S32, [ 1, 2, 3, 4] as S64) - - NBKAssertMajorOrMinorInteger([ ] as S32, [ ] as S64) - NBKAssertMajorOrMinorInteger([~1, ~0 ] as S32, [~1 ] as S64) - NBKAssertMajorOrMinorInteger([~1, ~0, ~2, ~0 ] as S32, [~1, ~2 ] as S64) - NBKAssertMajorOrMinorInteger([~1, ~0, ~2, ~0, ~3, ~0 ] as S32, [~1, ~2, ~3 ] as S64) - NBKAssertMajorOrMinorInteger([~1, ~0, ~2, ~0, ~3, ~0, ~4, ~0] as S32, [~1, ~2, ~3, ~4] as S64) - } - - func testUInt64AsUInt64() { - NBKAssertMajorOrMinorInteger([ ] as S64, [ ] as S64) - NBKAssertMajorOrMinorInteger([ 1 ] as S64, [ 1 ] as S64) - NBKAssertMajorOrMinorInteger([ 1, 2 ] as S64, [ 1, 2 ] as S64) - NBKAssertMajorOrMinorInteger([ 1, 2, 3 ] as S64, [ 1, 2, 3 ] as S64) - NBKAssertMajorOrMinorInteger([ 1, 2, 3, 4] as S64, [ 1, 2, 3, 4] as S64) - - NBKAssertMajorOrMinorInteger([ ] as S64, [ ] as S64) - NBKAssertMajorOrMinorInteger([~1 ] as S64, [~1 ] as S64) - NBKAssertMajorOrMinorInteger([~1, ~2 ] as S64, [~1, ~2 ] as S64) - NBKAssertMajorOrMinorInteger([~1, ~2, ~3 ] as S64, [~1, ~2, ~3 ] as S64) - NBKAssertMajorOrMinorInteger([~1, ~2, ~3, ~4] as S64, [~1, ~2, ~3, ~4] as S64) - } - - func testUInt64AsUInt32() { - NBKAssertMajorOrMinorInteger([ ] as S64, [ ] as S32) - NBKAssertMajorOrMinorInteger([ 1 ] as S64, [ 1, 0 ] as S32) - NBKAssertMajorOrMinorInteger([ 1, 2 ] as S64, [ 1, 0, 2, 0 ] as S32) - NBKAssertMajorOrMinorInteger([ 1, 2, 3 ] as S64, [ 1, 0, 2, 0, 3, 0 ] as S32) - NBKAssertMajorOrMinorInteger([ 1, 2, 3, 4] as S64, [ 1, 0, 2, 0, 3, 0, 4, 0] as S32) - - NBKAssertMajorOrMinorInteger([ ] as S64, [ ] as S32) - NBKAssertMajorOrMinorInteger([~1 ] as S64, [~1, ~0 ] as S32) - NBKAssertMajorOrMinorInteger([~1, ~2 ] as S64, [~1, ~0, ~2, ~0 ] as S32) - NBKAssertMajorOrMinorInteger([~1, ~2, ~3 ] as S64, [~1, ~0, ~2, ~0, ~3, ~0 ] as S32) - NBKAssertMajorOrMinorInteger([~1, ~2, ~3, ~4] as S64, [~1, ~0, ~2, ~0, ~3, ~0, ~4, ~0] as S32) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Count - //=------------------------------------------------------------------------= - - func testUInt32AsUInt64WithCustomCount() { - XCTAssertEqual([1, 2 ], Array(T([1, 0, 2, 0] as S32, count: nil, as: Int64.self))) - XCTAssertEqual([ ], Array(T([1, 0, 2, 0] as S32, count: 000, as: Int64.self))) - XCTAssertEqual([1 ], Array(T([1, 0, 2, 0] as S32, count: 001, as: Int64.self))) - XCTAssertEqual([1, 2 ], Array(T([1, 0, 2, 0] as S32, count: 002, as: Int64.self))) - XCTAssertEqual([1, 2, 0], Array(T([1, 0, 2, 0] as S32, count: 003, as: Int64.self))) - } - - func testUInt64AsUInt32WithCustomCount() { - XCTAssertEqual([1, 0, 2, 0 ], Array(T([1, 2] as S64, count: nil, as: Int32.self))) - XCTAssertEqual([ ], Array(T([1, 2] as S64, count: 000, as: Int32.self))) - XCTAssertEqual([1 ], Array(T([1, 2] as S64, count: 001, as: Int32.self))) - XCTAssertEqual([1, 0 ], Array(T([1, 2] as S64, count: 002, as: Int32.self))) - XCTAssertEqual([1, 0, 2 ], Array(T([1, 2] as S64, count: 003, as: Int32.self))) - XCTAssertEqual([1, 0, 2, 0 ], Array(T([1, 2] as S64, count: 004, as: Int32.self))) - XCTAssertEqual([1, 0, 2, 0, 0 ], Array(T([1, 2] as S64, count: 005, as: Int32.self))) - XCTAssertEqual([1, 0, 2, 0, 0, 0], Array(T([1, 2] as S64, count: 006, as: Int32.self))) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Signed or Unsigned - //=------------------------------------------------------------------------= - - func testSubscriptSignExtension() { - XCTAssertEqual(T([ 0] as S32, isSigned: false, as: Int32.self)[144], 0) - XCTAssertEqual(T([ 0] as S32, isSigned: true, as: Int32.self)[144], 0) - XCTAssertEqual(T([~0] as S32, isSigned: false, as: Int32.self)[144], 0) - XCTAssertEqual(T([~0] as S32, isSigned: true, as: Int32.self)[144], ~0) - - XCTAssertEqual(T([ 0] as S32, isSigned: false, as: Int64.self)[144], 0) - XCTAssertEqual(T([ 0] as S32, isSigned: true, as: Int64.self)[144], 0) - XCTAssertEqual(T([~0] as S32, isSigned: false, as: Int64.self)[144], 0) - XCTAssertEqual(T([~0] as S32, isSigned: true, as: Int64.self)[144], ~0) - - XCTAssertEqual(T([ 0] as S64, isSigned: false, as: Int32.self)[144], 0) - XCTAssertEqual(T([ 0] as S64, isSigned: true, as: Int32.self)[144], 0) - XCTAssertEqual(T([~0] as S64, isSigned: false, as: Int32.self)[144], 0) - XCTAssertEqual(T([~0] as S64, isSigned: true, as: Int32.self)[144], ~0) - - XCTAssertEqual(T([ 0] as S64, isSigned: false, as: Int64.self)[144], 0) - XCTAssertEqual(T([ 0] as S64, isSigned: true, as: Int64.self)[144], 0) - XCTAssertEqual(T([~0] as S64, isSigned: false, as: Int64.self)[144], 0) - XCTAssertEqual(T([~0] as S64, isSigned: true, as: Int64.self)[144], ~0) - } - - func testMajorLimbsFromIncompleteMinorLimbs() { - NBKAssertMajorOrMinorIntegerOneWay([ ] as S32, [ ] as S64, isSigned: true ) - NBKAssertMajorOrMinorIntegerOneWay([ 1 ] as S32, [ 1 ] as S64, isSigned: true ) - NBKAssertMajorOrMinorIntegerOneWay([ 1, 0, 2 ] as S32, [ 1, 2 ] as S64, isSigned: true ) - NBKAssertMajorOrMinorIntegerOneWay([ 1, 0, 2, 0, 3 ] as S32, [ 1, 2, 3 ] as S64, isSigned: true ) - NBKAssertMajorOrMinorIntegerOneWay([ 1, 0, 2, 0, 3, 0, 4] as S32, [ 1, 2, 3, 4 ] as S64, isSigned: true ) - - NBKAssertMajorOrMinorIntegerOneWay([ ] as S32, [ ] as S64, isSigned: true ) - NBKAssertMajorOrMinorIntegerOneWay([~1 ] as S32, [~1 ] as S64, isSigned: true ) - NBKAssertMajorOrMinorIntegerOneWay([~1, ~0, ~2 ] as S32, [~1, ~2 ] as S64, isSigned: true ) - NBKAssertMajorOrMinorIntegerOneWay([~1, ~0, ~2, ~0, ~3 ] as S32, [~1, ~2, ~3 ] as S64, isSigned: true ) - NBKAssertMajorOrMinorIntegerOneWay([~1, ~0, ~2, ~0, ~3, ~0, ~4] as S32, [~1, ~2, ~3, ~4 ] as S64, isSigned: true ) - - NBKAssertMajorOrMinorIntegerOneWay([ ] as S32, [ ] as S64, isSigned: false) - NBKAssertMajorOrMinorIntegerOneWay([ 1 ] as S32, [ 1 ] as S64, isSigned: false) - NBKAssertMajorOrMinorIntegerOneWay([ 1, 0, 2 ] as S32, [ 1, 2 ] as S64, isSigned: false) - NBKAssertMajorOrMinorIntegerOneWay([ 1, 0, 2, 0, 3 ] as S32, [ 1, 2, 3 ] as S64, isSigned: false) - NBKAssertMajorOrMinorIntegerOneWay([ 1, 0, 2, 0, 3, 0, 4] as S32, [ 1, 2, 3, 4 ] as S64, isSigned: false) - - NBKAssertMajorOrMinorIntegerOneWay([ ] as S32, [ ] as S64, isSigned: false) - NBKAssertMajorOrMinorIntegerOneWay([~1 ] as S32, [ 0xfffffffe] as S64, isSigned: false) - NBKAssertMajorOrMinorIntegerOneWay([~1, ~0, ~2 ] as S32, [~1, 0xfffffffd] as S64, isSigned: false) - NBKAssertMajorOrMinorIntegerOneWay([~1, ~0, ~2, ~0, ~3 ] as S32, [~1, ~2, 0xfffffffc] as S64, isSigned: false) - NBKAssertMajorOrMinorIntegerOneWay([~1, ~0, ~2, ~0, ~3, ~0, ~4] as S32, [~1, ~2, ~3, 0xfffffffb] as S64, isSigned: false) - } - - //=------------------------------------------------------------------------= - // MARK: Tests x Miscellaneous - //=------------------------------------------------------------------------= - - func testMajorToMinorComposableReordering() { - XCTAssertEqual([1, 2, 3, 4], Array(T(([0x0201, 0x0403] as [Int16]), as: Int8.self))) - XCTAssertEqual([2, 1, 4, 3], Array(T(([0x0201, 0x0403] as [Int16]).reversed(), as: Int8.self)).reversed()) - XCTAssertEqual([3, 4, 1, 2], Array(T(([0x0201, 0x0403] as [Int16]).reversed(), as: Int8.self))) - XCTAssertEqual([4, 3, 2, 1], Array(T(([0x0201, 0x0403] as [Int16]), as: Int8.self)).reversed()) - } - - func testMinorToMajorComposableReordering() { - XCTAssertEqual([0x0201, 0x0403], Array(T(([1, 2, 3, 4] as [Int8]), as: Int16.self))) - XCTAssertEqual([0x0102, 0x0304], Array(T(([1, 2, 3, 4] as [Int8]).reversed(), as: Int16.self)).reversed()) - XCTAssertEqual([0x0403, 0x0201], Array(T(([1, 2, 3, 4] as [Int8]), as: Int16.self)).reversed()) - XCTAssertEqual([0x0304, 0x0102], Array(T(([1, 2, 3, 4] as [Int8]).reversed(), as: Int16.self))) - } -} - -//*============================================================================* -// MARK: * NBK x Major Or Minor Integer x Assertions -//*============================================================================* - -private func NBKAssertMajorOrMinorInteger( -_ lhs: [A], _ rhs: [B], isSigned: Bool? = nil, -file: StaticString = #file, line: UInt = #line) { - - NBKAssertMajorOrMinorIntegerOneWay(lhs, rhs, isSigned: isSigned, file: file, line: line) - NBKAssertMajorOrMinorIntegerOneWay(rhs, lhs, isSigned: isSigned, file: file, line: line) -} - -private func NBKAssertMajorOrMinorIntegerOneWay( -_ lhs: [A], _ rhs: [B], isSigned: Bool? = nil, -file: StaticString = #file, line: UInt = #line) { - typealias T = NBKMajorOrMinorInteger - //=------------------------------------------= - let lhsUnsigned = lhs.map(A.Magnitude.init(bitPattern:)) - let rhsUnsigned = rhs.map(B.Magnitude.init(bitPattern:)) - //=------------------------------------------= - func with(isSigned: Bool) { - XCTAssertEqual(Array(T(lhs, isSigned: isSigned)), rhs, file: file, line: line) - XCTAssertEqual(Array(T(lhsUnsigned, isSigned: isSigned)), rhsUnsigned, file: file, line: line) - } - //=------------------------------------------= - if isSigned == nil || isSigned == true { with(isSigned: true ) } - if isSigned == nil || isSigned == false { with(isSigned: false) } -} - -#endif diff --git a/Tests/NBKCoreKitTests/Models/NBKTwinHeaded.swift b/Tests/NBKCoreKitTests/Models/NBKTwinHeaded.swift index 25b8210a..3d52b42e 100644 --- a/Tests/NBKCoreKitTests/Models/NBKTwinHeaded.swift +++ b/Tests/NBKCoreKitTests/Models/NBKTwinHeaded.swift @@ -149,9 +149,9 @@ final class NBKTwinHeadedTests: XCTestCase { // MARK: * NBK x Twin Headed x Assertions //*============================================================================* -private func NBKAssertIteration( -_ lhs: NBKTwinHeaded, _ rhs: [B.Element], -file: StaticString = #file, line: UInt = #line) where B.Element: FixedWidthInteger, B.Element: Equatable { +private func NBKAssertIteration( +_ lhs: NBKTwinHeaded, _ rhs: [T.Element], +file: StaticString = #file, line: UInt = #line) where T.Element: FixedWidthInteger, T.Element: Equatable { XCTAssertEqual(Array(lhs), rhs, file: file, line: line) XCTAssertEqual(Array(lhs.reversed()), rhs.reversed(), file: file, line: line) XCTAssertEqual(Array({ var x = lhs; x.reverse(); return x }()), rhs.reversed(), file: file, line: line) @@ -192,20 +192,6 @@ file: StaticString = #file, line: UInt = #line) where B.Element: FixedWidthInte } } - testAsMutableCollection: do { - var lhs = lhs, lhsIndex = lhs.startIndex - var rhs = rhs, rhsIndex = rhs.startIndex - while lhsIndex < lhs.endIndex { - lhs[lhsIndex] &+= 1 - rhs[rhsIndex] &+= 1 - - XCTAssertEqual(lhs[lhsIndex], rhs[rhsIndex], file: file, line: line) - - lhs.formIndex(after: &lhsIndex) - rhs.formIndex(after: &rhsIndex) - } - } - testDropFirst: do { for dropFirst in 0 ..< (2 * lhs.count) { let lhsDropFirst = lhs.dropFirst(dropFirst) @@ -241,6 +227,20 @@ file: StaticString = #file, line: UInt = #line) where B.Element: FixedWidthInte } } } + + testAsMutableCollection: do { + var lhs = lhs, lhsIndex = lhs.startIndex + var rhs = rhs, rhsIndex = rhs.startIndex + while lhsIndex < lhs.endIndex { + lhs[lhsIndex] &+= 1 + rhs[rhsIndex] &+= 1 + + XCTAssertEqual(lhs[lhsIndex], rhs[rhsIndex], file: file, line: line) + + lhs.formIndex(after: &lhsIndex) + rhs.formIndex(after: &rhsIndex) + } + } } #endif From f57e3521abb5a93262b1471bbfe8d3d550a329f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sun, 3 Sep 2023 19:35:40 +0200 Subject: [PATCH 096/111] [NBKCoreKit] Chunk count checks (#73). --- Sources/NBKCoreKit/Models/NBKChunkedInt.swift | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Sources/NBKCoreKit/Models/NBKChunkedInt.swift b/Sources/NBKCoreKit/Models/NBKChunkedInt.swift index c2506cba..162d4c3d 100644 --- a/Sources/NBKCoreKit/Models/NBKChunkedInt.swift +++ b/Sources/NBKCoreKit/Models/NBKChunkedInt.swift @@ -11,7 +11,7 @@ // MARK: * NBK x Chunked Int //*============================================================================* -/// A sequence that merges or splits elements of an un/signed integer sequence. +/// A sequence that chunks elements of an un/signed source. /// /// ```swift /// for word in NBKChunkedInt(source, isSigned: false, count: nil, as: UInt.self) { ... } @@ -57,12 +57,13 @@ Element: NBKCoreInteger, Base: RandomAccessCollection, Base.Element: NBKCoreInte /// - element: The type of element produced by this sequence. /// @inlinable public init(_ base: Base, isSigned: Bool = false, count: Int? = nil, as element: Element.Type = Element.self) { - Swift.assert(Self.Element.bitWidth.isPowerOf2) - Swift.assert(Base.Element.bitWidth.isPowerOf2) - self.base = base self.sign = Self.Element(repeating: isSigned && self.base.last?.mostSignificantBit == true) self.count = count ?? Self.count(of: self.base) + + precondition(self.count >= 0 as Int) + Swift.assert(Self.Element.bitWidth.isPowerOf2) + Swift.assert(Base.Element.bitWidth.isPowerOf2) } //=------------------------------------------------------------------------= @@ -201,7 +202,7 @@ extension NBKChunkedInt { } @inlinable public var indices: Range { - Range(uncheckedBounds:(0 as Int, self.count)) + 0 as Int ..< self.count } //=------------------------------------------------------------------------= From d7aa932a9434839bd17a3da86707ed0b134946d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Mon, 4 Sep 2023 10:53:14 +0200 Subject: [PATCH 097/111] Cleanup. --- Sources/NBKCoreKit/Models/NBKChunkedInt.swift | 1 - Sources/NBKCoreKit/Models/NBKEndianness.swift | 2 +- Sources/NBKCoreKit/Models/NBKTwinHeaded.swift | 14 +---- Sources/NBKCoreKit/Private/NBK+BitCast.swift | 24 +++++--- .../NBKDoubleWidthKit/NBKDoubleWidth.swift | 2 +- .../Documentation.docc/Documentation.md | 2 +- .../Models/NBKChunkedInt.swift | 28 +++++++++ .../Models/NBKEndianness.swift | 58 ------------------- 8 files changed, 50 insertions(+), 81 deletions(-) delete mode 100644 Tests/NBKCoreKitBenchmarks/Models/NBKEndianness.swift diff --git a/Sources/NBKCoreKit/Models/NBKChunkedInt.swift b/Sources/NBKCoreKit/Models/NBKChunkedInt.swift index 162d4c3d..8ec754d4 100644 --- a/Sources/NBKCoreKit/Models/NBKChunkedInt.swift +++ b/Sources/NBKCoreKit/Models/NBKChunkedInt.swift @@ -27,7 +27,6 @@ @frozen public struct NBKChunkedInt: RandomAccessCollection where Element: NBKCoreInteger, Base: RandomAccessCollection, Base.Element: NBKCoreInteger { - /// The base sequence type. public typealias Base = Base @frozen @usableFromInline enum Major { } diff --git a/Sources/NBKCoreKit/Models/NBKEndianness.swift b/Sources/NBKCoreKit/Models/NBKEndianness.swift index 4dfc3412..b1cd5458 100644 --- a/Sources/NBKCoreKit/Models/NBKEndianness.swift +++ b/Sources/NBKCoreKit/Models/NBKEndianness.swift @@ -35,7 +35,7 @@ // MARK: Initializers //=------------------------------------------------------------------------= - /// Returns the endianness of the current system. + /// Returns the current system's byte order. @inlinable public static var system: Self { #if _endian(little) return .little diff --git a/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift b/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift index c7350204..b2179bef 100644 --- a/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift +++ b/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift @@ -16,14 +16,6 @@ public typealias Base = Base - public typealias Index = Int - - public typealias Indices = Range - - public typealias Element = Base.Element - - public typealias SubSequence = Slice - //=------------------------------------------------------------------------= // MARK: State //=------------------------------------------------------------------------= @@ -38,7 +30,7 @@ /// /// It equals zero when front-to-back, and minus one otherwise. /// - @usableFromInline var mask: Self.Index + @usableFromInline var mask: Int /// The base index to be offset. /// @@ -207,7 +199,7 @@ extension NBKTwinHeaded { Range(uncheckedBounds:(0 as Int, self.count)) } - @inlinable public subscript(index: Int) -> Element { + @inlinable public subscript(index: Int) -> Base.Element { _read { yield self.base[self.baseSubscriptIndex(index)] } } @@ -254,7 +246,7 @@ extension NBKTwinHeaded: MutableCollection where Base: MutableCollection { // MARK: Accessors //=------------------------------------------------------------------------= - @inlinable public subscript(index: Int) -> Element { + @inlinable public subscript(index: Int) -> Base.Element { _read { yield self.body[self.baseSubscriptIndex(index)] } _modify { yield &self.body[self.baseSubscriptIndex(index)] } } diff --git a/Sources/NBKCoreKit/Private/NBK+BitCast.swift b/Sources/NBKCoreKit/Private/NBK+BitCast.swift index 00d2501e..77e5b9fe 100644 --- a/Sources/NBKCoreKit/Private/NBK+BitCast.swift +++ b/Sources/NBKCoreKit/Private/NBK+BitCast.swift @@ -56,7 +56,8 @@ extension NBK { //=------------------------------------------------------------------------= /// Converts the given integer by bit-casting it when possible. - @inlinable public static func initOrBitCast(_ source: T, as type: U.Type = U.self) -> U where T: BinaryInteger, U: BinaryInteger { + @inlinable public static func initOrBitCast( + _ source: T, as type: U.Type = U.self) -> U { if T.self != U.self { return U(source) } else { @@ -65,7 +66,8 @@ extension NBK { } /// Validates the given integer by bit-casting it when possible. - @inlinable public static func initOrBitCast(exactly source: T, as type: U.Type = U.self) -> U? where T: BinaryInteger, U: BinaryInteger { + @inlinable public static func initOrBitCast( + exactly source: T, as type: U.Type = U.self) -> U? { if T.self != U.self { return U(exactly: source) } else { @@ -74,7 +76,8 @@ extension NBK { } /// Clamps the given integer by bit-casting it when possible. - @inlinable public static func initOrBitCast(clamping source: T, as type: U.Type = U.self) -> U where T: BinaryInteger, U: BinaryInteger { + @inlinable public static func initOrBitCast( + clamping source: T, as type: U.Type = U.self) -> U { if T.self != U.self { return U(clamping: source) } else { @@ -83,7 +86,8 @@ extension NBK { } /// Truncates the given integer by bit-casting it when possible. - @inlinable public static func initOrBitCast(truncating source: T, as type: U.Type = U.self) -> U where T: BinaryInteger, U: BinaryInteger { + @inlinable public static func initOrBitCast( + truncating source: T, as type: U.Type = U.self) -> U { if T.self != U.self { return U(truncatingIfNeeded: source) } else { @@ -96,7 +100,8 @@ extension NBK { //=------------------------------------------------------------------------= /// Converts the given integer by bit-casting it when possible. - @inlinable public static func initOrBitCast(_ source: T, as type: U.Type = U.self) -> U where T: NBKFixedWidthInteger, U: NBKFixedWidthInteger { + @inlinable public static func initOrBitCast( + _ source: T, as type: U.Type = U.self) -> U { if T.BitPattern.self != U.BitPattern.self { return U(source) } else if T.isSigned == U.isSigned || !source.mostSignificantBit { @@ -107,7 +112,8 @@ extension NBK { } /// Validates the given integer by bit-casting it when possible. - @inlinable public static func initOrBitCast(exactly source: T, as type: U.Type = U.self) -> U? where T: NBKFixedWidthInteger, U: NBKFixedWidthInteger { + @inlinable public static func initOrBitCast( + exactly source: T, as type: U.Type = U.self) -> U? { if T.BitPattern.self != U.BitPattern.self { return U(exactly: source) } else if T.isSigned == U.isSigned || !source.mostSignificantBit { @@ -118,7 +124,8 @@ extension NBK { } /// Clamps the given integer by bit-casting it when possible. - @inlinable public static func initOrBitCast(clamping source: T, as type: U.Type = U.self) -> U where T: NBKFixedWidthInteger, U: NBKFixedWidthInteger { + @inlinable public static func initOrBitCast( + clamping source: T, as type: U.Type = U.self) -> U { if T.BitPattern.self != U.BitPattern.self { return U(clamping: source) } else if T.isSigned == U.isSigned || !source.mostSignificantBit { @@ -129,7 +136,8 @@ extension NBK { } /// Truncates the given integer by bit-casting it when possible. - @inlinable public static func initOrBitCast(truncating source: T, as type: U.Type = U.self) -> U where T: NBKFixedWidthInteger, U: NBKFixedWidthInteger { + @inlinable public static func initOrBitCast( + truncating source: T, as type: U.Type = U.self) -> U { if T.BitPattern.self != U.BitPattern.self { return U(truncatingIfNeeded: source) } else { diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift index 255853de..b40245bb 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift @@ -81,7 +81,7 @@ import NBKCoreKit /// /// - Note: The `Digit` type is `Int` when `Self` is signed, and `UInt` otherwise. /// -/// ### ⭐️ Feature: StaticBigInt (v0.10.0+) +/// ### ⭐️ Feature: StaticBigInt /// /// `StaticBigInt` is disabled by default. You enable it in `Package.swift`. /// diff --git a/Sources/Numberick/Documentation.docc/Documentation.md b/Sources/Numberick/Documentation.docc/Documentation.md index 75f26446..543cc9e2 100644 --- a/Sources/Numberick/Documentation.docc/Documentation.md +++ b/Sources/Numberick/Documentation.docc/Documentation.md @@ -91,7 +91,7 @@ Int256(5) % Int(5), UInt256(5) % UInt(5) - Note: The `Digit` type is `Int` when `Self` is signed, and `UInt` otherwise. -### ⭐️ Feature: StaticBigInt (v0.10.0+) +### ⭐️ Feature: StaticBigInt `StaticBigInt` is disabled by default. You enable it in `Package.swift`. diff --git a/Tests/NBKCoreKitBenchmarks/Models/NBKChunkedInt.swift b/Tests/NBKCoreKitBenchmarks/Models/NBKChunkedInt.swift index fc2ec6f9..41787064 100644 --- a/Tests/NBKCoreKitBenchmarks/Models/NBKChunkedInt.swift +++ b/Tests/NBKCoreKitBenchmarks/Models/NBKChunkedInt.swift @@ -83,6 +83,21 @@ final class NBKChunkedIntBenchmarks: XCTestCase { //=------------------------------------------------------------------------= // MARK: Tests x Miscellaneous //=------------------------------------------------------------------------= + // Note: The array conversions call Sequence/_copyToContiguousArray(). + //=------------------------------------------------------------------------= + + func testUInt32AsUInt32ByReversedCollection() { + var abc = NBK.blackHoleIdentity(Y(repeating: .min, count: 144)) + var xyz = NBK.blackHoleIdentity(Y(repeating: .max, count: 144)) + + for _ in 0 ..< 144_000 { + NBK.blackHole(Y(abc.reversed())) + NBK.blackHole(Y(xyz.reversed())) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } func testUInt32AsUInt32ByUnsafeBufferPointer() { var abc = NBK.blackHoleIdentity(Y(repeating: .min, count: 144)) @@ -97,6 +112,19 @@ final class NBKChunkedIntBenchmarks: XCTestCase { } } + func testUInt64AsUInt64ByReversedCollection() { + var abc = NBK.blackHoleIdentity(X(repeating: .min, count: 144)) + var xyz = NBK.blackHoleIdentity(X(repeating: .max, count: 144)) + + for _ in 0 ..< 144_000 { + NBK.blackHole(X(abc.reversed())) + NBK.blackHole(X(xyz.reversed())) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + func testUInt64AsUInt64ByUnsafeBufferPointer() { var abc = NBK.blackHoleIdentity(X(repeating: .min, count: 144)) var xyz = NBK.blackHoleIdentity(X(repeating: .max, count: 144)) diff --git a/Tests/NBKCoreKitBenchmarks/Models/NBKEndianness.swift b/Tests/NBKCoreKitBenchmarks/Models/NBKEndianness.swift deleted file mode 100644 index f17ba682..00000000 --- a/Tests/NBKCoreKitBenchmarks/Models/NBKEndianness.swift +++ /dev/null @@ -1,58 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if !DEBUG - -import NBKCoreKit -import XCTest - -private typealias W = [UInt] -private typealias X = [UInt64] -private typealias Y = [UInt32] - -//*============================================================================* -// MARK: * NBK x Endianness -//*============================================================================* - -final class NBKEndiannessBenchmarks: XCTestCase { - - typealias T = NBKEndianness - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testIsEqualTo() { - var abc = NBK.blackHoleIdentity(T.little) - var xyz = NBK.blackHoleIdentity(T.big ) - - for _ in 0 ..< 5_000_000 { - NBK.blackHole(abc == T.system) - NBK.blackHole(xyz == T.system) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } - - func testHashValue() { - var abc = NBK.blackHoleIdentity(T.little) - var xyz = NBK.blackHoleIdentity(T.big ) - - for _ in 0 ..< 1_000_000 { - NBK.blackHole(abc.hashValue) - NBK.blackHole(xyz.hashValue) - - NBK.blackHoleInoutIdentity(&abc) - NBK.blackHoleInoutIdentity(&xyz) - } - } -} - -#endif From 655b47013682201811e6d7fc57b8e888491c7670 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Mon, 4 Sep 2023 11:41:20 +0200 Subject: [PATCH 098/111] Version 0.11.0. --- Numberick-NBKCoreKit.podspec | 2 +- Numberick-NBKDoubleWidthKit.podspec | 2 +- Numberick.podspec | 2 +- README.md | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Numberick-NBKCoreKit.podspec b/Numberick-NBKCoreKit.podspec index b549c4ec..f1fd7608 100644 --- a/Numberick-NBKCoreKit.podspec +++ b/Numberick-NBKCoreKit.podspec @@ -12,7 +12,7 @@ #*=============================================================================* Pod::Spec.new do |spec| - spec.version = "0.10.0" + spec.version = "0.11.0" spec.module_name = "NBKCoreKit" spec.name = "Numberick-#{spec.module_name}" spec.summary = "A new protocol hierarchy that refines Swift's standard library." diff --git a/Numberick-NBKDoubleWidthKit.podspec b/Numberick-NBKDoubleWidthKit.podspec index 2eec78a8..b7e537ad 100644 --- a/Numberick-NBKDoubleWidthKit.podspec +++ b/Numberick-NBKDoubleWidthKit.podspec @@ -12,7 +12,7 @@ #*=============================================================================* Pod::Spec.new do |spec| - spec.version = "0.10.0" + spec.version = "0.11.0" spec.module_name = "NBKDoubleWidthKit" spec.name = "Numberick-#{spec.module_name}" spec.summary = "A composable, large, fixed-width, two's complement, binary integer." diff --git a/Numberick.podspec b/Numberick.podspec index e7aea835..81fb916d 100644 --- a/Numberick.podspec +++ b/Numberick.podspec @@ -12,7 +12,7 @@ #*=============================================================================* Pod::Spec.new do |spec| - spec.version = "0.10.0" + spec.version = "0.11.0" spec.name = "Numberick" spec.module_name = "Numberick" spec.summary = "✨ An arithmagick overhaul in Swift." diff --git a/README.md b/README.md index 46f29f2b..69f10a13 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ | Package | Swift | iOS | Mac Catalyst | macOS | tvOS | watchOS | |:-------:|:-----:|:-----:|:------------:|:-----:|:-----:|:-------:| -| 0.10.0 | 5.7 | 14.0 | 14.0 | 11.0 | 14.0 | 7.0 | +| 0.11.0 | 5.7 | 14.0 | 14.0 | 11.0 | 14.0 | 7.0 | ## NBKCoreKit ([Sources][COR/S], [Tests][COR/T], [Benchmarks][COR/B]) From 3c6a95db803f8d1044d33d879727a69babdbc005 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Tue, 5 Sep 2023 07:08:49 +0200 Subject: [PATCH 099/111] [NBKCoreKit] Cleanup (#73). --- Sources/NBKCoreKit/Models/NBKChunkedInt.swift | 12 +++ .../Models/NBKChunkedInt.swift | 87 ++++++++++++++++--- .../Models/NBKChunkedInt.swift | 2 +- 3 files changed, 90 insertions(+), 11 deletions(-) diff --git a/Sources/NBKCoreKit/Models/NBKChunkedInt.swift b/Sources/NBKCoreKit/Models/NBKChunkedInt.swift index 8ec754d4..01cf63a9 100644 --- a/Sources/NBKCoreKit/Models/NBKChunkedInt.swift +++ b/Sources/NBKCoreKit/Models/NBKChunkedInt.swift @@ -24,6 +24,18 @@ /// its elements from least significant to most. You can reorder it by reversing /// the input, the output, or both. /// +/// ```swift +/// [1, 2, 3, 4] == Array(NBKChunkedInt(([0x0201, 0x0403] as [Int16]), as: UInt8.self)) +/// [2, 1, 4, 3] == Array(NBKChunkedInt(([0x0201, 0x0403] as [Int16]).reversed(), as: UInt8.self).reversed()) +/// [3, 4, 1, 2] == Array(NBKChunkedInt(([0x0201, 0x0403] as [Int16]).reversed(), as: UInt8.self)) +/// [4, 3, 2, 1] == Array(NBKChunkedInt(([0x0201, 0x0403] as [Int16]), as: UInt8.self).reversed()) +/// +/// [0x0201, 0x0403] == Array(NBKChunkedInt(([1, 2, 3, 4] as [UInt8]), as: Int16.self)) +/// [0x0102, 0x0304] == Array(NBKChunkedInt(([1, 2, 3, 4] as [UInt8]).reversed(), as: Int16.self).reversed()) +/// [0x0403, 0x0201] == Array(NBKChunkedInt(([1, 2, 3, 4] as [UInt8]), as: Int16.self).reversed()) +/// [0x0304, 0x0102] == Array(NBKChunkedInt(([1, 2, 3, 4] as [UInt8]).reversed(), as: Int16.self)) +/// ``` +/// @frozen public struct NBKChunkedInt: RandomAccessCollection where Element: NBKCoreInteger, Base: RandomAccessCollection, Base.Element: NBKCoreInteger { diff --git a/Tests/NBKCoreKitBenchmarks/Models/NBKChunkedInt.swift b/Tests/NBKCoreKitBenchmarks/Models/NBKChunkedInt.swift index 41787064..42a43af1 100644 --- a/Tests/NBKCoreKitBenchmarks/Models/NBKChunkedInt.swift +++ b/Tests/NBKCoreKitBenchmarks/Models/NBKChunkedInt.swift @@ -81,12 +81,12 @@ final class NBKChunkedIntBenchmarks: XCTestCase { } //=------------------------------------------------------------------------= - // MARK: Tests x Miscellaneous + // MARK: Tests x Versus Other Collections //=------------------------------------------------------------------------= - // Note: The array conversions call Sequence/_copyToContiguousArray(). + // NOTE: The array conversions call Sequence/_copyToContiguousArray(). //=------------------------------------------------------------------------= - func testUInt32AsUInt32ByReversedCollection() { + func testWithReversedCollectionUInt32AsUInt32() { var abc = NBK.blackHoleIdentity(Y(repeating: .min, count: 144)) var xyz = NBK.blackHoleIdentity(Y(repeating: .max, count: 144)) @@ -99,7 +99,20 @@ final class NBKChunkedIntBenchmarks: XCTestCase { } } - func testUInt32AsUInt32ByUnsafeBufferPointer() { + func testWithReversedCollectionUInt64AsUInt64() { + var abc = NBK.blackHoleIdentity(X(repeating: .min, count: 144)) + var xyz = NBK.blackHoleIdentity(X(repeating: .max, count: 144)) + + for _ in 0 ..< 144_000 { + NBK.blackHole(X(abc.reversed())) + NBK.blackHole(X(xyz.reversed())) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testWithUnsafeBufferPointerUInt32AsUInt32() { var abc = NBK.blackHoleIdentity(Y(repeating: .min, count: 144)) var xyz = NBK.blackHoleIdentity(Y(repeating: .max, count: 144)) @@ -112,26 +125,80 @@ final class NBKChunkedIntBenchmarks: XCTestCase { } } - func testUInt64AsUInt64ByReversedCollection() { + func testWithUnsafeBufferPointerUInt64AsUInt64() { var abc = NBK.blackHoleIdentity(X(repeating: .min, count: 144)) var xyz = NBK.blackHoleIdentity(X(repeating: .max, count: 144)) for _ in 0 ..< 144_000 { - NBK.blackHole(X(abc.reversed())) - NBK.blackHole(X(xyz.reversed())) + NBK.blackHole(abc.withUnsafeBufferPointer(X.init)) + NBK.blackHole(xyz.withUnsafeBufferPointer(X.init)) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } +} + +//*============================================================================* +// MARK: * NBK x Chunked Int x Reordering +//*============================================================================* + +final class NBKChunkedIntBenchmarksByReordering: XCTestCase { + + typealias T = NBKChunkedInt + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + // NOTE: Makes arrays from lazily reversed inputs and outputs. + //=------------------------------------------------------------------------= + + func testUInt32AsUInt32() { + var abc = NBK.blackHoleIdentity(Y(repeating: .min, count: 144)) + var xyz = NBK.blackHoleIdentity(Y(repeating: .max, count: 144)) + + for _ in 0 ..< 144_000 { + NBK.blackHole(Y(T(abc.reversed()).reversed())) + NBK.blackHole(Y(T(xyz.reversed()).reversed())) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testUInt32AsUInt64() { + var abc = NBK.blackHoleIdentity(Y(repeating: .min, count: 144)) + var xyz = NBK.blackHoleIdentity(Y(repeating: .max, count: 144)) + + for _ in 0 ..< 144_000 { + NBK.blackHole(X(T(abc.reversed()).reversed())) + NBK.blackHole(X(T(xyz.reversed()).reversed())) NBK.blackHoleInoutIdentity(&abc) NBK.blackHoleInoutIdentity(&xyz) } } - func testUInt64AsUInt64ByUnsafeBufferPointer() { + func testUInt64AsUInt32() { var abc = NBK.blackHoleIdentity(X(repeating: .min, count: 144)) var xyz = NBK.blackHoleIdentity(X(repeating: .max, count: 144)) for _ in 0 ..< 144_000 { - NBK.blackHole(abc.withUnsafeBufferPointer(X.init)) - NBK.blackHole(xyz.withUnsafeBufferPointer(X.init)) + NBK.blackHole(Y(T(abc.reversed()).reversed())) + NBK.blackHole(Y(T(xyz.reversed()).reversed())) + + NBK.blackHoleInoutIdentity(&abc) + NBK.blackHoleInoutIdentity(&xyz) + } + } + + func testUInt64AsUInt64() { + var abc = NBK.blackHoleIdentity(X(repeating: .min, count: 144)) + var xyz = NBK.blackHoleIdentity(X(repeating: .max, count: 144)) + + for _ in 0 ..< 144_000 { + NBK.blackHole(X(T(abc.reversed()).reversed())) + NBK.blackHole(X(T(xyz.reversed()).reversed())) NBK.blackHoleInoutIdentity(&abc) NBK.blackHoleInoutIdentity(&xyz) diff --git a/Tests/NBKCoreKitTests/Models/NBKChunkedInt.swift b/Tests/NBKCoreKitTests/Models/NBKChunkedInt.swift index 716d96f8..3145edbb 100644 --- a/Tests/NBKCoreKitTests/Models/NBKChunkedInt.swift +++ b/Tests/NBKCoreKitTests/Models/NBKChunkedInt.swift @@ -182,7 +182,7 @@ final class NBKChunkedIntTests: XCTestCase { } //*============================================================================* -// MARK: * NBK x Chunked Int x Assertions +// MARK: * NBK x Chunked Int x Assertions //*============================================================================* private func NBKAssertChunkedInt( From 25cafce8af3eb73aea3d4a9a29be13bebee2ea69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Tue, 5 Sep 2023 08:21:52 +0200 Subject: [PATCH 100/111] [Package] xcodebuild-clean-build-platforms.sh. --- .../xcodebuild-clean-build-platforms.sh | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100755 .utilities/xcodebuild-clean-build-platforms.sh diff --git a/.utilities/xcodebuild-clean-build-platforms.sh b/.utilities/xcodebuild-clean-build-platforms.sh new file mode 100755 index 00000000..1846ae7d --- /dev/null +++ b/.utilities/xcodebuild-clean-build-platforms.sh @@ -0,0 +1,38 @@ +#!/bin/bash +#=-----------------------------------------------------------------------------= +# This source file is part of the Numberick open source project. +# +# Copyright (c) 2023 Oscar Byström Ericsson +# Licensed under Apache License, Version 2.0 +# +# See http://www.apache.org/licenses/LICENSE-2.0 for license information. +#=-----------------------------------------------------------------------------= +# This script requires the following structure: +# +# PROJECT/ +# │ +# ├─── DIRECTORY/ +# │ │ +# │ └─── SCRIPT.sh +# │ +# └─── .swiftpm/xcode/xcshareddata/PROJECT.xcscheme +#=-----------------------------------------------------------------------------= + +set -eu + +# Variables + +PROJECT_NAME="Numberick" +PROJECT_PATH=$(dirname $(dirname $(realpath $0))) +XCODE_SCHEME_NAME=$PROJECT_NAME + +# Actions + +cd $PROJECT_PATH + +xcodebuild clean build \ +-scheme $XCODE_SCHEME_NAME \ +-destination "generic/platform=iOS" \ +-destination "generic/platform=macOS" \ +-destination "generic/platform=tvOS" \ +-destination "generic/platform=watchOS" From 5287ac1d5f2540ad673cbe18512b05fb6f43f872 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Wed, 6 Sep 2023 07:12:05 +0200 Subject: [PATCH 101/111] Cleanup. --- .utilities/update-gh-pages-docs-no-push.sh | 4 +--- .utilities/xcodebuild-clean-build-platforms.sh | 4 +--- Sources/NBKCoreKit/Models/NBKTwinHeaded.swift | 8 ++++---- Sources/NBKCoreKit/Private/NBK+Limbs+Succinct.swift | 2 ++ Sources/NBKDoubleWidthKit/NBKDoubleWidth+Data.swift | 1 + 5 files changed, 9 insertions(+), 10 deletions(-) diff --git a/.utilities/update-gh-pages-docs-no-push.sh b/.utilities/update-gh-pages-docs-no-push.sh index 7ab1081b..7a7272db 100755 --- a/.utilities/update-gh-pages-docs-no-push.sh +++ b/.utilities/update-gh-pages-docs-no-push.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/bash -eu #=-----------------------------------------------------------------------------= # This source file is part of the Numberick open source project. # @@ -18,8 +18,6 @@ # └─── .swiftpm/xcode/xcshareddata/PROJECT.xcscheme #=-----------------------------------------------------------------------------= -set -eu - # Variables PROJECT_NAME="Numberick" diff --git a/.utilities/xcodebuild-clean-build-platforms.sh b/.utilities/xcodebuild-clean-build-platforms.sh index 1846ae7d..bdd66371 100755 --- a/.utilities/xcodebuild-clean-build-platforms.sh +++ b/.utilities/xcodebuild-clean-build-platforms.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/bash -eu #=-----------------------------------------------------------------------------= # This source file is part of the Numberick open source project. # @@ -18,8 +18,6 @@ # └─── .swiftpm/xcode/xcshareddata/PROJECT.xcscheme #=-----------------------------------------------------------------------------= -set -eu - # Variables PROJECT_NAME="Numberick" diff --git a/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift b/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift index b2179bef..959f9013 100644 --- a/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift +++ b/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift @@ -130,8 +130,8 @@ /// Returns the base collection's corresponding subscript index. /// /// ``` - /// isFrontToBack: base.index(base.startIndex, offsetBy: index + 0) - /// isBackToFront: base.index(base.endIndex, offsetBy: -index + -1) + /// front-to-back: base.index(base.startIndex, offsetBy: index + 0) + /// back-to-front: base.index(base.endIndex, offsetBy: -index + -1) /// ``` /// /// - Parameter index: `self.startIndex <= index < self.endIndex` @@ -144,8 +144,8 @@ /// Returns the base collection's corresponding index. /// /// ``` - /// isFrontToBack: base.index(base.startIndex, offsetBy: index) - /// isBackToFront: base.index(base.endIndex, offsetBy: -index) + /// front-to-back: base.index(base.startIndex, offsetBy: index) + /// back-to-front: base.index(base.endIndex, offsetBy: -index) /// ``` /// /// - Note: Use ``baseSubscriptIndex(_:)`` to subscript the base collection. diff --git a/Sources/NBKCoreKit/Private/NBK+Limbs+Succinct.swift b/Sources/NBKCoreKit/Private/NBK+Limbs+Succinct.swift index 91eb51f4..0add5f48 100644 --- a/Sources/NBKCoreKit/Private/NBK+Limbs+Succinct.swift +++ b/Sources/NBKCoreKit/Private/NBK+Limbs+Succinct.swift @@ -27,6 +27,8 @@ extension NBK { /// │ 1, 2, 0, 0 │ 1, 2 │ false │ /// │ ~1, ~2, ~0, ~0 │ ~1, ~2 │ true │ /// │ ~0, ~0, ~0, ~0 │ │ true │ + /// ├─────────────── → ───────────────┼───────┤ + /// │ │ │ error │ /// └─────────────── → ───────────────┴───────┘ /// ``` /// diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Data.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Data.swift index 3a7ba3ff..7fa491db 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Data.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Data.swift @@ -85,6 +85,7 @@ extension NBKDoubleWidth where High == High.Magnitude { // pointee: initialization by callee //=----------------------------------= pointer.withMemoryRebound(to: T.self, capacity: BitPattern.count(T.self)) { start in + // wrapping this in a binary integer words convenience requires inline(always) body(UnsafeMutableBufferPointer(start: start, count: BitPattern.count(T.self))) } //=----------------------------------= From cab48aef5f197cef6a2bd2c28cedee65ef582973 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Wed, 6 Sep 2023 07:22:53 +0200 Subject: [PATCH 102/111] [NBKCoreKit] Text and radix rework (#78). --- .../Private/NBK+Text+RadixSolution.swift | 449 ++++++++++++++++++ .../Private/NBK+Text+RadixUIntRoot.swift | 282 ----------- Sources/NBKCoreKit/Private/NBK+Text.swift | 50 +- .../NBKDoubleWidth+Literals.swift | 4 +- .../NBKDoubleWidth+Text.swift | 33 +- .../Private/NBK+Text+RadixSolution.swift | 50 ++ .../Private/NBK+Text+RadixUIntRoot.swift | 44 -- 7 files changed, 555 insertions(+), 357 deletions(-) create mode 100644 Sources/NBKCoreKit/Private/NBK+Text+RadixSolution.swift delete mode 100644 Sources/NBKCoreKit/Private/NBK+Text+RadixUIntRoot.swift create mode 100644 Tests/NBKCoreKitTests/Private/NBK+Text+RadixSolution.swift delete mode 100644 Tests/NBKCoreKitTests/Private/NBK+Text+RadixUIntRoot.swift diff --git a/Sources/NBKCoreKit/Private/NBK+Text+RadixSolution.swift b/Sources/NBKCoreKit/Private/NBK+Text+RadixSolution.swift new file mode 100644 index 00000000..b6b3b8fc --- /dev/null +++ b/Sources/NBKCoreKit/Private/NBK+Text+RadixSolution.swift @@ -0,0 +1,449 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +//*============================================================================* +// MARK: * NBK x Radix Solution +//*============================================================================* + +extension NBK { + + //=------------------------------------------------------------------------= + // MARK: Protocols + //=------------------------------------------------------------------------= + + public typealias RadixSolution = _NBKRadixSolution + + public typealias RadixSolutionDivisor = _NBKRadixSolutionDivisor + + //=------------------------------------------------------------------------= + // MARK: Models + //=------------------------------------------------------------------------= + + public typealias AnyRadixSolution = _NBKAnyRadixSolution + + public typealias PerfectRadixSolution = _NBKPerfectRadixSolution + + public typealias ImperfectRadixSolution = _NBKImperfectRadixSolution +} + +//*============================================================================* +// MARK: * NBK x Radix Solution +//*============================================================================* + +/// Max power and exponent in `pow(base, exponent) <= Element.max + 1`. +/// +/// - The `base` is `>= 2` and `<= 36` +/// - The `exponent` is `>= 1` and `<= Element.bitWidth` +/// - A power of `Element.max + 1` is represented by `0` +/// +public protocol _NBKRadixSolution { + + typealias Element = Size.Magnitude + + associatedtype Size: NBKCoreInteger & NBKSignedInteger + + associatedtype Divisor: NBK.RadixSolutionDivisor where Divisor.Size == Size + + //=------------------------------------------------------------------------= + // MARK: State + //=------------------------------------------------------------------------= + + @inlinable var base: Element { get } + + @inlinable var exponent: Element { get } + + @inlinable var power: Element { get } + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + @inlinable func divisor() -> Divisor +} + +//=----------------------------------------------------------------------------= +// MARK: + Details +//=----------------------------------------------------------------------------= + +extension NBK.RadixSolution { + + //=------------------------------------------------------------------------= + // MARK: Accessors + //=------------------------------------------------------------------------= + + @inlinable public var base: Size { + assert((self.base as Element) <= 36) + return Size(bitPattern: self.base) + } + + @inlinable public var exponent: Size { + assert((self.exponent as Element) <= Element.bitWidth) + return Size(bitPattern: self.exponent) + } + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + @inlinable public func dividing(_ dividend: Element) -> QR { + self.divisor().dividing(dividend) + } +} + +//*============================================================================* +// MARK: * NBK x Radix Solution x Divisor +//*============================================================================* + +/// An radix solution helper model allowing efficient repeated division. +public protocol _NBKRadixSolutionDivisor where Size: NBKCoreInteger & NBKSignedInteger { + + typealias Element = Size.Magnitude + + associatedtype Size: NBKCoreInteger & NBKSignedInteger + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + /// Returns the `quotient` and `remainder` of dividing `dividend` by `self`. + @inlinable func dividing(_ dividend: Element) -> QR +} + +//*============================================================================* +// MARK: * NBK x Radix Solution x Perfect +//*============================================================================* + +/// A `RadixSolution` with a power that is zero. +@frozen public struct _NBKPerfectRadixSolution: NBK.RadixSolution where Size: NBKCoreInteger & NBKSignedInteger { + + //=------------------------------------------------------------------------= + // MARK: State + //=------------------------------------------------------------------------= + + @usableFromInline let solution: NBK.AnyRadixSolution + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + @inlinable public init?(_ solution: NBK.AnyRadixSolution) { + guard solution.power.isZero else { return nil } + assert(solution.power.isZero) + assert([2, 4, 16].contains(solution.base)) + self.solution = solution + } + + //=------------------------------------------------------------------------= + // MARK: Accessors + //=------------------------------------------------------------------------= + + @inlinable public var base: Element { + self.solution.base + } + + @inlinable public var exponent: Element { + self.solution.exponent + } + + @inlinable public var power: Element { + self.solution.power + } + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + @inlinable public func divisor() -> Divisor { + Divisor(self) + } + + //*========================================================================* + // MARK: * Divisor + //*========================================================================* + + @frozen public struct Divisor: NBK.RadixSolutionDivisor { + + //=--------------------------------------------------------------------= + // MARK: State + //=--------------------------------------------------------------------= + + @usableFromInline let quotientShift: Element + @usableFromInline let remainderMask: Element + + //=--------------------------------------------------------------------= + // MARK: Initializers + //=--------------------------------------------------------------------= + + @inlinable init(_ solution: NBK.PerfectRadixSolution) { + self.quotientShift = NBK.initOrBitCast(truncating: solution.base.trailingZeroBitCount) + self.remainderMask = solution.base &- (1 as Element) + } + + //=--------------------------------------------------------------------= + // MARK: Utilities + //=--------------------------------------------------------------------= + + @inlinable public func dividing(_ dividend: Element) -> QR { + QR(dividend &>> self.quotientShift, dividend & self.remainderMask) + } + } +} + +//*============================================================================* +// MARK: * NBK x Radix Solution x Imperfect +//*============================================================================* + +/// A `RadixSolution` with a power that is non-zero. +@frozen public struct _NBKImperfectRadixSolution: NBK.RadixSolution where Size: NBKCoreInteger & NBKSignedInteger { + + //=------------------------------------------------------------------------= + // MARK: State + //=------------------------------------------------------------------------= + + @usableFromInline let solution: NBK.AnyRadixSolution + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + @inlinable public init?(_ solution: NBK.AnyRadixSolution) { + guard !solution.power.isZero else { return nil } + assert(!solution.power.isZero) + assert(![2, 4, 16].contains(solution.base)) + self.solution = solution + } + + //=------------------------------------------------------------------------= + // MARK: Accessors + //=------------------------------------------------------------------------= + + @inlinable public var base: Element { + self.solution.base + } + + @inlinable public var exponent: Element { + self.solution.exponent + } + + @inlinable public var power: Element { + self.solution.power + } + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + @inlinable public func divisor() -> Divisor { + Divisor(self) + } + + /// Overestimates how many times its power divides the magnitude. + @inlinable public func divisibilityByPowerUpperBound(_ magnitude: some UnsignedInteger) -> Int { + magnitude.bitWidth / 36.leadingZeroBitCount &+ 1 + } + + //*========================================================================* + // MARK: * Divisor + //*========================================================================* + + @frozen public struct Divisor: NBK.RadixSolutionDivisor { + + //=--------------------------------------------------------------------= + // MARK: State + //=--------------------------------------------------------------------= + + @usableFromInline let base: Element + + //=--------------------------------------------------------------------= + // MARK: Initializers + //=--------------------------------------------------------------------= + + @inlinable init(_ solution: NBK.ImperfectRadixSolution) { + self.base = solution.base + } + + //=--------------------------------------------------------------------= + // MARK: Utilities + //=--------------------------------------------------------------------= + + @inlinable public func dividing(_ dividend: Element) -> QR { + QR(dividend.quotientAndRemainder(dividingBy: self.base)) + } + } +} + +//*============================================================================* +// MARK: * NBK x Radix Solution x Any +//*============================================================================* + +@frozen public struct _NBKAnyRadixSolution: NBK.RadixSolution where Size: NBKCoreInteger & NBKSignedInteger { + + @usableFromInline typealias Value = (exponent: Element, power: Element) + + //=------------------------------------------------------------------------= + // MARK: State + //=------------------------------------------------------------------------= + + public let base: Element + public let exponent: Element + public let power: Element + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + /// Creates a new instance from the given radix. + /// + /// The radix must not exceed `36` because that is the size of the alphabet. + /// + /// - Parameter radix: A value from `2` through `36`. + /// + @inlinable public init(_ radix: Int) { + precondition(2 ... 36 ~= radix) + //=--------------------------------------= + self.base = NBK.initOrBitCast(truncating: radix) + // all core integers can represent the range 2 ... 36 + + switch radix.isPowerOf2 { + case true: (self.exponent, self.power) = Self.valueAssumingRadixIsPowerOf2(self.base) + case false: (self.exponent, self.power) = Self.valueAssumingRadixIsNotPowerOf2(self.base) } + } + + @inlinable public init(_ radix: NBK.PerfectRadixSolution) { + self = radix.solution + } + + @inlinable public init(_ radix: NBK.ImperfectRadixSolution) { + self = radix.solution + } + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + @inlinable public func divisor() -> Divisor { + Divisor(self) + } + + //*========================================================================* + // MARK: * Divisor + //*========================================================================* + + @frozen public struct Divisor: NBK.RadixSolutionDivisor { + + //=--------------------------------------------------------------------= + // MARK: State + //=--------------------------------------------------------------------= + + @usableFromInline let baseOrQuotientShift: Element + @usableFromInline let zeroOrRemainderMask: Element + + //=--------------------------------------------------------------------= + // MARK: Initializers + //=--------------------------------------------------------------------= + + @inlinable init(_ solution: _NBKAnyRadixSolution) { + assert(solution.base >= 2) + if solution.power.isZero { + self.baseOrQuotientShift = NBK.initOrBitCast(truncating: solution.base.trailingZeroBitCount) + self.zeroOrRemainderMask = solution.base &+ Element.max // &- 1 + } else { + self.baseOrQuotientShift = solution.base + self.zeroOrRemainderMask = 00000 as Element + } + } + + //=--------------------------------------------------------------------= + // MARK: Utilities + //=--------------------------------------------------------------------= + + @inlinable public func dividing(_ dividend: Element) -> QR { + switch self.zeroOrRemainderMask.isZero { + case true: return QR(dividend.quotientAndRemainder(dividingBy: self.baseOrQuotientShift) ) + case false: return QR(dividend &>> baseOrQuotientShift, dividend & self.zeroOrRemainderMask) } + } + } +} + +//=----------------------------------------------------------------------------= +// MARK: + Algorithms +//=----------------------------------------------------------------------------= + +extension _NBKAnyRadixSolution { + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + /// Returns the largest exponent in `pow(radix, exponent) <= Element.max + 1`. + @inlinable static func valueAssumingRadixIsPowerOf2(_ radix: Element) -> Value { + assert(radix >= 2) + assert(radix.isPowerOf2) + //=--------------------------------------= + let value: Value + let zeros: Element = NBK.initOrBitCast(truncating: radix.trailingZeroBitCount) + //=--------------------------------------= + // radix: 002, 004, 016, 256, ... + //=--------------------------------------= + if zeros.isPowerOf2 { + value.exponent = NBK.initOrBitCast(truncating: Element.bitWidth &>> zeros.trailingZeroBitCount) + value.power = (0 as Element) + //=--------------------------------------= + // radix: 008, 032, 064, 128, ... + //=--------------------------------------= + } else { + value.exponent = NBK.initOrBitCast(truncating: Element.bitWidth) / (zeros) + value.power = (1 as Element) &<< (zeros &* value.exponent) + } + + return value as Value + } + + /// Returns the largest exponent in `pow(radix, exponent) <= Element.max + 1`. + @inlinable static func valueAssumingRadixIsNotPowerOf2(_ radix: Element) -> Value { + assert(radix >= 2) + assert(radix.isPowerOf2 == false) + //=--------------------------------------= + // radix: 003, 005, 006, 007, ... + //=--------------------------------------= + let capacity: Int = Element.bitWidth.trailingZeroBitCount - 1 + return Swift.withUnsafeTemporaryAllocation(of: Value.self, capacity: capacity) { squares in + let start = squares.baseAddress! + var position = start as UnsafeMutablePointer + var value = Value(exponent: 1, power: radix) + //=----------------------------------= + // pointee: initialization + //=----------------------------------= + loop: while true { + position.initialize(to: value) + let product = value.power.multipliedReportingOverflow(by: value.power) + if product.overflow { break loop } + + value.exponent &<<= 1 as Element + value.power = product.partialValue + position = position.successor() + } + //=----------------------------------= + // pointee: deinitialization by move + //=----------------------------------= + assert(position <= start.advanced(by: squares.count)) + loop: while position > start { + position = position.predecessor() + let square = position.move() + let product = value.power.multipliedReportingOverflow(by: square.power) + if product.overflow { continue loop } + + value.exponent &+= square.exponent + value.power = product.partialValue + } + + return value as Value + } + } +} diff --git a/Sources/NBKCoreKit/Private/NBK+Text+RadixUIntRoot.swift b/Sources/NBKCoreKit/Private/NBK+Text+RadixUIntRoot.swift deleted file mode 100644 index d7fed51e..00000000 --- a/Sources/NBKCoreKit/Private/NBK+Text+RadixUIntRoot.swift +++ /dev/null @@ -1,282 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -//*============================================================================* -// MARK: * NBK x Radix UInt Root -//*============================================================================* - -/// Max power and exponent in `pow(base, exponent) <= UInt.max + 1`. -/// -/// - The `base` is `>= 2` and `<= 36` -/// - The `exponent` is `>= 1` and `<= UInt.bitWidth` -/// - A power of `UInt.max + 1` is represented by `0` -/// -public protocol _NBKRadixUIntRoot { - - //=------------------------------------------------------------------------= - // MARK: State - //=------------------------------------------------------------------------= - - @inlinable var base: UInt { get } - - @inlinable var exponent: UInt { get } - - @inlinable var power: UInt { get } - - //=------------------------------------------------------------------------= - // MARK: Utilities - //=------------------------------------------------------------------------= - - /// Divides `dividend` by the `base` of this solution. - @inlinable func dividing(_ dividend: UInt) -> QR -} - -//=----------------------------------------------------------------------------= -// MARK: + Details -//=----------------------------------------------------------------------------= - -extension _NBKRadixUIntRoot { - - //=------------------------------------------------------------------------= - // MARK: Accessors - //=------------------------------------------------------------------------= - - @inlinable public var base: Int { - assert((self.base as UInt) <= 36) - return Int(bitPattern: self.base) - } - - @inlinable public var exponent: Int { - assert((self.exponent as UInt) <= UInt.bitWidth) - return Int(bitPattern: self.exponent) - } - - //=------------------------------------------------------------------------= - // MARK: Utilities - //=------------------------------------------------------------------------= - - @inlinable public func dividing(_ dividend: UInt) -> QR { - dividend.quotientAndRemainder(dividingBy: self.base) - } -} - -//*============================================================================* -// MARK: * NBK x Radix UInt Root x Implementations -//*============================================================================* - -extension NBK { - - //*========================================================================* - // MARK: * Perfect - //*========================================================================* - - /// A `RadixUIntRoot` with a power that is zero. - @frozen public struct PerfectRadixUIntRoot: _NBKRadixUIntRoot { - - //=--------------------------------------------------------------------= - // MARK: State - //=--------------------------------------------------------------------= - - @usableFromInline let root: AnyRadixUIntRoot - @usableFromInline let special: QR - - //=--------------------------------------------------------------------= - // MARK: Initializers - //=--------------------------------------------------------------------= - - @inlinable public init(unchecked: AnyRadixUIntRoot) { - assert(unchecked.power.isZero) - assert([2, 4, 16].contains(unchecked.base)) - self.root = unchecked - self.special.quotient = UInt(bitPattern: self.root.base.trailingZeroBitCount) - self.special.remainder = self.root.base &- 1 - } - - //=--------------------------------------------------------------------= - // MARK: Accessors - //=--------------------------------------------------------------------= - - @inlinable public var base: UInt { - self.root.base - } - - @inlinable public var exponent: UInt { - self.root.exponent - } - - @inlinable public var power: UInt { - self.root.power - } - - //=--------------------------------------------------------------------= - // MARK: Utilities - //=--------------------------------------------------------------------= - - @inlinable public func dividing(_ dividend: UInt) -> QR { - QR(dividend &>> self.special.quotient, dividend & self.special.remainder) - } - } - - //*========================================================================* - // MARK: * NBK x Imperfect - //*========================================================================* - - /// A `RadixUIntRoot` with a power that is non-zero. - @frozen public struct ImperfectRadixUIntRoot: _NBKRadixUIntRoot { - - //=--------------------------------------------------------------------= - // MARK: State - //=--------------------------------------------------------------------= - - @usableFromInline let root: AnyRadixUIntRoot - - //=--------------------------------------------------------------------= - // MARK: Initializers - //=--------------------------------------------------------------------= - - @inlinable public init(unchecked: AnyRadixUIntRoot) { - assert(!unchecked.power.isZero) - assert(![2, 4, 16].contains(unchecked.base)) - self.root = unchecked - } - - //=--------------------------------------------------------------------= - // MARK: Accessors - //=--------------------------------------------------------------------= - - @inlinable public var base: UInt { - self.root.base - } - - @inlinable public var exponent: UInt { - self.root.exponent - } - - @inlinable public var power: UInt { - self.root.power - } - - //=--------------------------------------------------------------------= - // MARK: Utilities - //=--------------------------------------------------------------------= - - /// Overestimates how many times its power divides the magnitude. - @inlinable public func divisibilityByPowerUpperBound(_ magnitude: some UnsignedInteger) -> Int { - magnitude.bitWidth / 36.leadingZeroBitCount &+ 1 - } - } - - //*========================================================================* - // MARK: * Any - //*========================================================================* - - /// A `RadixUIntRoot` with a power that may be zero. - @frozen public struct AnyRadixUIntRoot: _NBKRadixUIntRoot { - - @usableFromInline typealias Solution = (exponent: UInt, power: UInt) - - //=--------------------------------------------------------------------= - // MARK: State - //=--------------------------------------------------------------------= - - public let base: UInt - public let exponent: UInt - public let power: UInt - - //=--------------------------------------------------------------------= - // MARK: Initializers - //=--------------------------------------------------------------------= - - /// Creates a new instance from the given radix. - /// - /// The radix must not exceed `36` because that is the size of the alphabet. - /// - /// - Parameter radix: A value from `2` through `36`. - /// - @inlinable public init(_ radix: Int) { - Swift.precondition(2 ... 36 ~= radix) - (self.base) = UInt(bitPattern: radix) - (self.exponent, self.power) = Self.solution(unchecked: self.base) - } - - //=--------------------------------------------------------------------= - // MARK: Utilities - //=--------------------------------------------------------------------= - - /// Returns the largest exponent in `pow(radix, exponent) <= UInt.max + 1`. - @inlinable static func solution(unchecked radix: UInt) -> Solution { - switch radix.isPowerOf2 { - case true: return Self.solutionAssumingRadixIsPowerOf2 (unchecked: radix) - case false: return Self.solutionAssumingRadixIsNotPowerOf2(unchecked: radix) } - } - - /// Returns the largest exponent in `pow(radix, exponent) <= UInt.max + 1`. - @inlinable static func solutionAssumingRadixIsPowerOf2(unchecked radix: UInt) -> Solution { - assert(radix >= 2) - assert(radix.isPowerOf2) - //=--------------------------------------= - let zeros = UInt(bitPattern: radix.trailingZeroBitCount) - //=--------------------------------------= - // radix: 002, 004, 016, 256, ... - //=--------------------------------------= - if zeros.isPowerOf2 { - let exponent = UInt(bitPattern: UInt.bitWidth &>> zeros.trailingZeroBitCount) - return Solution(exponent: exponent, power: 0) - //=--------------------------------------= - // radix: 008, 032, 064, 128, ... - //=--------------------------------------= - } else { - let exponent = UInt(bitPattern: UInt.bitWidth) / (zeros as UInt) - return Solution(exponent: exponent, power: 1 &<< (zeros &* exponent)) - } - } - - /// Returns the largest exponent in `pow(radix, exponent) <= UInt.max + 1`. - @inlinable static func solutionAssumingRadixIsNotPowerOf2(unchecked radix: UInt) -> Solution { - assert(radix >= 2) - assert(radix.isPowerOf2 == false) - //=--------------------------------------= - // radix: 003, 005, 006, 007, ... - //=--------------------------------------= - let capacity: Int = UInt.bitWidth.trailingZeroBitCount - 1 - return Swift.withUnsafeTemporaryAllocation(of: Solution.self, capacity: capacity) { squares in - var solution = Solution(1, radix) - let start = squares.baseAddress! - var position = start as UnsafeMutablePointer - //=----------------------------------= - // pointee: initialization - //=----------------------------------= - loop: while true { - position.initialize(to: solution) - let product = solution.power.multipliedReportingOverflow(by: solution.power) - if product.overflow { break loop } - - solution.exponent &<<= 1 as UInt - solution.power = product.partialValue - position = position.successor() - } - //=----------------------------------= - // pointee: deinitialization by move - //=----------------------------------= - assert(position <= start.advanced(by: squares.count)) - loop: while position > start { - position = position.predecessor() - let square = position.move() - let product = solution.power.multipliedReportingOverflow(by: square.power) - if product.overflow { continue loop } - - solution.exponent &+= square.exponent - solution.power = product.partialValue - } - //=----------------------------------= - return solution as Solution - } - } - } -} diff --git a/Sources/NBKCoreKit/Private/NBK+Text.swift b/Sources/NBKCoreKit/Private/NBK+Text.swift index f96d6791..886fec4c 100644 --- a/Sources/NBKCoreKit/Private/NBK+Text.swift +++ b/Sources/NBKCoreKit/Private/NBK+Text.swift @@ -30,7 +30,8 @@ extension NBK { /// /// Creating a new decoder is faster than passing one as an argument. /// - @inlinable public static func truncating(digits: NBK.UnsafeUTF8, radix: Int, as type: T.Type = T.self) -> T? where T: NBKCoreInteger { + @inlinable public static func truncating( + digits: UnsafeUTF8, radix: Int, as type: T.Type = T.self) -> T? { guard !digits.isEmpty else { return nil } //=--------------------------------------= let alphabet = NBK.AnyRadixAlphabetDecoder(radix: radix) @@ -57,14 +58,18 @@ extension NBK { /// /// In this context, a chunk is a digit in the base of the given radix's power. /// - @inlinable public static func integerTextUnchecked(chunks: some RandomAccessCollection, radix: some _NBKRadixUIntRoot, - alphabet: MaxRadixAlphabetEncoder, prefix: NBK.UnsafeUTF8, suffix: NBK.UnsafeUTF8) -> String { + /// - Note: `@inlinable` is not needed. + /// + public static func integerTextUnchecked( + chunks: NBKTwinHeaded, radix: AnyRadixSolution, + alphabet: MaxRadixAlphabetEncoder, prefix: UnsafeUTF8, suffix: UnsafeUTF8) -> String { assert(chunks.count <= 1 || chunks.last != 0, "chunks must not contain redundant zeros") assert(radix.power.isZero || chunks.allSatisfy({ $0 < radix.power }), "chunks must be less than radix's power") //=--------------------------------------= var remainders = chunks[...] let mostSignificantChunk = remainders.popLast() ?? UInt() - return NBK.withUnsafeTemporaryIntegerTextUnchecked(chunk: mostSignificantChunk, radix: radix, alphabet: alphabet) { first in + return NBK.withUnsafeTemporaryIntegerTextUnchecked( + chunk: mostSignificantChunk, radix: radix, alphabet: alphabet) { first in var count: Int count = prefix.count count += first .count @@ -81,15 +86,28 @@ extension NBK { } //=------------------------------= suffix.reversed().forEach(pull) - - for var chunk in remainders { - for _ in 0 ..< radix.exponent { - let digit: UInt - (chunk, digit) = radix.dividing(chunk) - pull(alphabet.encode(UInt8(truncatingIfNeeded: digit))!) + //=------------------------------= + // dynamic: loop unswitch perf. + //=------------------------------= + if radix.power.isZero { + let divisor = PerfectRadixSolution(radix)!.divisor() + for var chunk in remainders { + for _ in 0 as UInt ..< radix.exponent { + let digit: UInt; (chunk, digit) = divisor.dividing(chunk) + pull(alphabet.encode(UInt8(truncatingIfNeeded: digit))!) + } + } + + } else { + let divisor = ImperfectRadixSolution(radix)!.divisor() + for var chunk in remainders { + for _ in 0 as UInt ..< radix.exponent { + let digit: UInt; (chunk, digit) = divisor.dividing(chunk) + pull(alphabet.encode(UInt8(truncatingIfNeeded: digit))!) + } } } - + //=------------------------------= first .reversed().forEach(pull) prefix.reversed().forEach(pull) //=------------------------------= @@ -103,8 +121,10 @@ extension NBK { /// /// In this context, a chunk is a digit in the base of the given radix's power. /// - @inlinable public static func withUnsafeTemporaryIntegerTextUnchecked( - chunk: UInt, radix: some _NBKRadixUIntRoot, alphabet: MaxRadixAlphabetEncoder, body: (NBK.UnsafeUTF8) -> T) -> T { + /// - Note: `@inlinable` is not needed. + /// + public static func withUnsafeTemporaryIntegerTextUnchecked( + chunk: UInt, radix: AnyRadixSolution, alphabet: MaxRadixAlphabetEncoder, body:(UnsafeUTF8) -> T) -> T { assert(radix.power.isZero || chunk < radix.power, "chunks must be less than radix's power") return Swift.withUnsafeTemporaryAllocation(of: UInt8.self, capacity: radix.exponent) { utf8 in var chunk = chunk as UInt @@ -113,9 +133,9 @@ extension NBK { //=----------------------------------= // pointee: initialization //=----------------------------------= + let divisor = radix.divisor() backwards: repeat { - let digit: UInt - (chunk, digit) = radix.dividing(chunk) + let digit: UInt; (chunk, digit) = divisor.dividing(chunk) position = position.predecessor() position.initialize(to: alphabet.encode(UInt8(truncatingIfNeeded: digit))!) } while !chunk.isZero diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift index 7e8c6bcb..f46098f7 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Literals.swift @@ -86,8 +86,8 @@ extension NBKDoubleWidth { @inlinable init?(exactlyStringLiteral source: StaticString) { let value: Optional = source.withUTF8Buffer { utf8 in let components = NBK.makeIntegerComponentsByDecodingRadix(utf8: utf8) - let radix = NBK.AnyRadixUIntRoot(components.radix) - let digits = NBK.UnsafeUTF8(rebasing: components.body) + let radix = NBK.AnyRadixSolution(components.radix) + let digits = NBK.UnsafeUTF8(rebasing: components.body ) guard let magnitude = Magnitude(digits: digits, radix: radix) else { return nil } return Self(sign: components.sign, magnitude: magnitude) } diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text.swift index 7aa48e0b..7871e61f 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text.swift @@ -23,7 +23,7 @@ extension NBKDoubleWidth { var description = String(description) let value: Optional = description.withUTF8 { utf8 in - let radix = NBK.AnyRadixUIntRoot(radix) + let radix = NBK.AnyRadixSolution(radix) let components = NBK.makeIntegerComponents(utf8: utf8) let digits = NBK.UnsafeUTF8(rebasing: components.body) guard let magnitude = Magnitude(digits: digits, radix: radix) else { return nil } @@ -39,7 +39,7 @@ extension NBKDoubleWidth { @inlinable public func description(radix: Int = 10, uppercase: Bool = false) -> String { Swift.withUnsafePointer(to: UInt8(ascii: "-")) { minus in - let radix = NBK.AnyRadixUIntRoot(radix) + let radix = NBK.AnyRadixSolution(radix) let alphabet = NBK.MaxRadixAlphabetEncoder(uppercase: uppercase) let prefix = NBK.UnsafeUTF8(start: minus, count: Int(bit: self.isLessThanZero)) let suffix = NBK.UnsafeUTF8(start: nil, count: 0 as Int) @@ -58,13 +58,13 @@ extension NBKDoubleWidth where High == High.Magnitude { // MARK: Details x Decode x Private //=------------------------------------------------------------------------= - @inlinable init?(digits: NBK.UnsafeUTF8, radix: NBK.AnyRadixUIntRoot) { + @inlinable init?(digits: NBK.UnsafeUTF8, radix: NBK.AnyRadixSolution) { switch radix.power.isZero { - case true: self.init(digits: digits, radix: NBK .PerfectRadixUIntRoot(unchecked: radix)) - case false: self.init(digits: digits, radix: NBK.ImperfectRadixUIntRoot(unchecked: radix)) } + case true: self.init(digits: digits, radix: NBK .PerfectRadixSolution(radix)!) + case false: self.init(digits: digits, radix: NBK.ImperfectRadixSolution(radix)!) } } - @inlinable init?(digits: NBK.UnsafeUTF8, radix: NBK.PerfectRadixUIntRoot) { + @inlinable init?(digits: NBK.UnsafeUTF8, radix: NBK.PerfectRadixSolution) { guard !digits.isEmpty else { return nil } //=--------------------------------------= var digits = digits.drop(while:{ $0 == 48 }) @@ -86,7 +86,7 @@ extension NBKDoubleWidth where High == High.Magnitude { if !error, digits.isEmpty { self = value } else { return nil } } - @inlinable init?(digits: NBK.UnsafeUTF8, radix: NBK.ImperfectRadixUIntRoot) { + @inlinable init?(digits: NBK.UnsafeUTF8, radix: NBK.ImperfectRadixSolution) { guard !digits.isEmpty else { return nil } //=--------------------------------------= var digits = digits.drop(while:{ $0 == 48 }) @@ -116,26 +116,30 @@ extension NBKDoubleWidth where High == High.Magnitude { // NOTE: Both branches specialize NBKTwinHeaded>. //=------------------------------------------------------------------------= - @inlinable func description(radix: NBK.AnyRadixUIntRoot, alphabet: NBK.MaxRadixAlphabetEncoder, + @inlinable func description( + radix: NBK.AnyRadixSolution, alphabet: NBK.MaxRadixAlphabetEncoder, prefix: NBK.UnsafeUTF8, suffix: NBK.UnsafeUTF8) -> String { switch radix.power.isZero { - case true: return self.description(radix: NBK .PerfectRadixUIntRoot(unchecked: radix), alphabet: alphabet, prefix: prefix, suffix: suffix) - case false: return self.description(radix: NBK.ImperfectRadixUIntRoot(unchecked: radix), alphabet: alphabet, prefix: prefix, suffix: suffix) } + case true: return self.description(radix: NBK .PerfectRadixSolution(radix)!, alphabet: alphabet, prefix: prefix, suffix: suffix) + case false: return self.description(radix: NBK.ImperfectRadixSolution(radix)!, alphabet: alphabet, prefix: prefix, suffix: suffix) } } - @inlinable func description(radix: NBK.PerfectRadixUIntRoot, alphabet: NBK.MaxRadixAlphabetEncoder, + @inlinable func description( + radix: NBK.PerfectRadixSolution, alphabet: NBK.MaxRadixAlphabetEncoder, prefix: NBK.UnsafeUTF8, suffix: NBK.UnsafeUTF8) -> String { //=--------------------------------------= // with one buffer pointer specialization //=--------------------------------------= self.withUnsafeData(as: UInt.self) { data in + let radix = NBK.AnyRadixSolution(radix) let words = NBKTwinHeaded(data, reversed: NBK.isBigEndian) let chunks = NBKTwinHeaded(rebasing:NBK.dropLast(from: words, while:{ $0.isZero })) return NBK.integerTextUnchecked(chunks: chunks, radix: radix, alphabet: alphabet, prefix: prefix, suffix: suffix) } } - @inlinable func description(radix: NBK.ImperfectRadixUIntRoot, alphabet: NBK.MaxRadixAlphabetEncoder, + @inlinable func description( + radix: NBK.ImperfectRadixSolution, alphabet: NBK.MaxRadixAlphabetEncoder, prefix: NBK.UnsafeUTF8, suffix: NBK.UnsafeUTF8) -> String { //=--------------------------------------= // with one buffer pointer specialization @@ -149,10 +153,10 @@ extension NBKDoubleWidth where High == High.Magnitude { //=----------------------------------= // pointee: initialization //=----------------------------------= - rebasing: while !magnitude.isZero { + rebasing: repeat { position.initialize(to: magnitude.formQuotientWithRemainderReportingOverflow(dividingBy: radix.power).partialValue) position = position.successor() - } + } while !magnitude.isZero //=----------------------------------= // pointee: deferred deinitialization //=----------------------------------= @@ -160,6 +164,7 @@ extension NBKDoubleWidth where High == High.Magnitude { defer { start.deinitialize(count: count) } //=----------------------------------= let chunks = NBKTwinHeaded(UnsafeBufferPointer( start: start, count: count)) + let radix = NBK.AnyRadixSolution(radix) return NBK.integerTextUnchecked(chunks: chunks, radix: radix, alphabet: alphabet, prefix: prefix, suffix: suffix) } } diff --git a/Tests/NBKCoreKitTests/Private/NBK+Text+RadixSolution.swift b/Tests/NBKCoreKitTests/Private/NBK+Text+RadixSolution.swift new file mode 100644 index 00000000..413cdba0 --- /dev/null +++ b/Tests/NBKCoreKitTests/Private/NBK+Text+RadixSolution.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. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +import XCTest + +//*============================================================================* +// MARK: * NBK x Text x Radix Solution +//*============================================================================* + +final class NBKTestsOnTextByRadixSolution: XCTestCase { + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testAnyRadixSolution() { + func whereIsSize(_ size: T.Type) where T: NBKCoreInteger & NBKSignedInteger { + for radix in 2 ... 36 { + let solution = NBK.AnyRadixSolution(radix) + XCTAssertEqual(solution.base, T.Magnitude(radix)) + + var product = HL(T.Magnitude(0), T.Magnitude(1)) + for _ in 0 ..< solution.exponent { + XCTAssert(product.high.isZero) + product = product.low.multipliedFullWidth(by: T.Magnitude(radix)) + } + + XCTAssertEqual(product.low, solution.power) + XCTAssertEqual(product.low.isZero, [2, 4, 16].contains(radix)) + XCTAssertEqual(product.high, /**/ [2, 4, 16].contains(radix) ? 1 : 0) + XCTAssertEqual(product.low.multipliedReportingOverflow(by: T.Magnitude(radix)).overflow, ![2, 4, 16].contains(radix)) + } + } + + for size: any (NBKCoreInteger & NBKSignedInteger).Type in [Int.self, Int8.self, Int16.self, Int32.self, Int64.self] { + whereIsSize(size) + } + } +} + +#endif diff --git a/Tests/NBKCoreKitTests/Private/NBK+Text+RadixUIntRoot.swift b/Tests/NBKCoreKitTests/Private/NBK+Text+RadixUIntRoot.swift deleted file mode 100644 index 6aa6a1f1..00000000 --- a/Tests/NBKCoreKitTests/Private/NBK+Text+RadixUIntRoot.swift +++ /dev/null @@ -1,44 +0,0 @@ -//=----------------------------------------------------------------------------= -// This source file is part of the Numberick open source project. -// -// Copyright (c) 2023 Oscar Byström Ericsson -// Licensed under Apache License, Version 2.0 -// -// See http://www.apache.org/licenses/LICENSE-2.0 for license information. -//=----------------------------------------------------------------------------= - -#if DEBUG - -import NBKCoreKit -import XCTest - -//*============================================================================* -// MARK: * NBK x Text x Radix UInt Root -//*============================================================================* - -final class NBKTestsOnTextByRadixUIntRoot: XCTestCase { - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - - func testAnyRadixUIntRoot() { - for radix in 2 ... 36 { - let solution = NBK.AnyRadixUIntRoot(radix) - XCTAssertEqual(solution.base, UInt(radix)) - - var product = HL(UInt(0), UInt(1)) - for _ in 0 ..< solution.exponent { - XCTAssert(product.high.isZero) - product = product.low.multipliedFullWidth(by: UInt(radix)) - } - - XCTAssertEqual(product.low, solution.power) - XCTAssertEqual(product.low.isZero, [2, 4, 16].contains(radix)) - XCTAssertEqual(product.high, /**/ [2, 4, 16].contains(radix) ? 1 : 0) - XCTAssertEqual(product.low.multipliedReportingOverflow(by: UInt(radix)).overflow, ![2, 4, 16].contains(radix)) - } - } -} - -#endif From de84402461121dbfe2a0285c9382ba2d87cfd7fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Thu, 7 Sep 2023 08:19:24 +0200 Subject: [PATCH 103/111] [NBKCoreKit] Cleanup (#78). --- .../Private/NBK+Text+RadixSolution.swift | 66 +++++++++---------- Sources/NBKCoreKit/Private/NBK+Text.swift | 54 ++++++++++----- .../NBKDoubleWidth+Text.swift | 2 +- .../NBKDoubleWidthKit/NBKDoubleWidth.swift | 1 - .../Private/NBK+Text+RadixSolution.swift | 6 +- 5 files changed, 72 insertions(+), 57 deletions(-) diff --git a/Sources/NBKCoreKit/Private/NBK+Text+RadixSolution.swift b/Sources/NBKCoreKit/Private/NBK+Text+RadixSolution.swift index b6b3b8fc..8961a5e3 100644 --- a/Sources/NBKCoreKit/Private/NBK+Text+RadixSolution.swift +++ b/Sources/NBKCoreKit/Private/NBK+Text+RadixSolution.swift @@ -42,7 +42,7 @@ extension NBK { /// - The `exponent` is `>= 1` and `<= Element.bitWidth` /// - A power of `Element.max + 1` is represented by `0` /// -public protocol _NBKRadixSolution { +public protocol _NBKRadixSolution { typealias Element = Size.Magnitude @@ -53,13 +53,15 @@ public protocol _NBKRadixSolution { //=------------------------------------------------------------------------= // MARK: State //=------------------------------------------------------------------------= - + @inlinable var base: Element { get } @inlinable var exponent: Element { get } @inlinable var power: Element { get } + @inlinable var solution: NBK.AnyRadixSolution { get } + //=------------------------------------------------------------------------= // MARK: Utilities //=------------------------------------------------------------------------= @@ -86,14 +88,6 @@ extension NBK.RadixSolution { assert((self.exponent as Element) <= Element.bitWidth) return Size(bitPattern: self.exponent) } - - //=------------------------------------------------------------------------= - // MARK: Utilities - //=------------------------------------------------------------------------= - - @inlinable public func dividing(_ dividend: Element) -> QR { - self.divisor().dividing(dividend) - } } //*============================================================================* @@ -126,7 +120,7 @@ public protocol _NBKRadixSolutionDivisor where Size: NBKCoreInteger & NBKS // MARK: State //=------------------------------------------------------------------------= - @usableFromInline let solution: NBK.AnyRadixSolution + public let solution: NBK.AnyRadixSolution //=------------------------------------------------------------------------= // MARK: Initializers @@ -134,8 +128,7 @@ public protocol _NBKRadixSolutionDivisor where Size: NBKCoreInteger & NBKS @inlinable public init?(_ solution: NBK.AnyRadixSolution) { guard solution.power.isZero else { return nil } - assert(solution.power.isZero) - assert([2, 4, 16].contains(solution.base)) + Swift.assert([2, 4, 16].contains(solution.base)) self.solution = solution } @@ -206,16 +199,15 @@ public protocol _NBKRadixSolutionDivisor where Size: NBKCoreInteger & NBKS // MARK: State //=------------------------------------------------------------------------= - @usableFromInline let solution: NBK.AnyRadixSolution + public let solution: NBK.AnyRadixSolution //=------------------------------------------------------------------------= // MARK: Initializers //=------------------------------------------------------------------------= @inlinable public init?(_ solution: NBK.AnyRadixSolution) { - guard !solution.power.isZero else { return nil } - assert(!solution.power.isZero) - assert(![2, 4, 16].contains(solution.base)) + guard !solution.power.isZero else { return nil } + Swift.assert(![2, 4, 16].contains(solution.base)) self.solution = solution } @@ -311,17 +303,19 @@ public protocol _NBKRadixSolutionDivisor where Size: NBKCoreInteger & NBKS // all core integers can represent the range 2 ... 36 switch radix.isPowerOf2 { - case true: (self.exponent, self.power) = Self.valueAssumingRadixIsPowerOf2(self.base) - case false: (self.exponent, self.power) = Self.valueAssumingRadixIsNotPowerOf2(self.base) } + case true: (self.exponent, self.power) = Self.valueAssumingRadixIsAnyPowerOf2From2(self.base) + case false: (self.exponent, self.power) = Self.valueAssumingRadixIsNonPowerOf2From2(self.base) } } - @inlinable public init(_ radix: NBK.PerfectRadixSolution) { - self = radix.solution + @inlinable public init(_ other: some NBK.RadixSolution) { + self = other.solution } - @inlinable public init(_ radix: NBK.ImperfectRadixSolution) { - self = radix.solution - } + //=------------------------------------------------------------------------= + // MARK: Accessors + //=------------------------------------------------------------------------= + + @inlinable public var solution: NBK.AnyRadixSolution { self } //=------------------------------------------------------------------------= // MARK: Utilities @@ -348,14 +342,14 @@ public protocol _NBKRadixSolutionDivisor where Size: NBKCoreInteger & NBKS // MARK: Initializers //=--------------------------------------------------------------------= - @inlinable init(_ solution: _NBKAnyRadixSolution) { + @inlinable init(_ solution: NBK.AnyRadixSolution) { assert(solution.base >= 2) if solution.power.isZero { self.baseOrQuotientShift = NBK.initOrBitCast(truncating: solution.base.trailingZeroBitCount) - self.zeroOrRemainderMask = solution.base &+ Element.max // &- 1 + self.zeroOrRemainderMask = solution.base &+ Element.max // &- 1 } else { self.baseOrQuotientShift = solution.base - self.zeroOrRemainderMask = 00000 as Element + self.zeroOrRemainderMask = 00 as Element } } @@ -365,8 +359,8 @@ public protocol _NBKRadixSolutionDivisor where Size: NBKCoreInteger & NBKS @inlinable public func dividing(_ dividend: Element) -> QR { switch self.zeroOrRemainderMask.isZero { - case true: return QR(dividend.quotientAndRemainder(dividingBy: self.baseOrQuotientShift) ) - case false: return QR(dividend &>> baseOrQuotientShift, dividend & self.zeroOrRemainderMask) } + case true: return QR(dividend.quotientAndRemainder(dividingBy: self.baseOrQuotientShift) ) + case false: return QR(dividend &>> self.baseOrQuotientShift, dividend & self.zeroOrRemainderMask) } } } } @@ -382,7 +376,7 @@ extension _NBKAnyRadixSolution { //=------------------------------------------------------------------------= /// Returns the largest exponent in `pow(radix, exponent) <= Element.max + 1`. - @inlinable static func valueAssumingRadixIsPowerOf2(_ radix: Element) -> Value { + @inlinable static func valueAssumingRadixIsAnyPowerOf2From2(_ radix: Element) -> Value { assert(radix >= 2) assert(radix.isPowerOf2) //=--------------------------------------= @@ -406,17 +400,17 @@ extension _NBKAnyRadixSolution { } /// Returns the largest exponent in `pow(radix, exponent) <= Element.max + 1`. - @inlinable static func valueAssumingRadixIsNotPowerOf2(_ radix: Element) -> Value { + @inlinable static func valueAssumingRadixIsNonPowerOf2From2(_ radix: Element) -> Value { assert(radix >= 2) assert(radix.isPowerOf2 == false) //=--------------------------------------= // radix: 003, 005, 006, 007, ... //=--------------------------------------= - let capacity: Int = Element.bitWidth.trailingZeroBitCount - 1 + let capacity = Element.bitWidth.trailingZeroBitCount - 1 return Swift.withUnsafeTemporaryAllocation(of: Value.self, capacity: capacity) { squares in let start = squares.baseAddress! var position = start as UnsafeMutablePointer - var value = Value(exponent: 1, power: radix) + var value = Value(1 as Element, radix) //=----------------------------------= // pointee: initialization //=----------------------------------= @@ -432,9 +426,9 @@ extension _NBKAnyRadixSolution { //=----------------------------------= // pointee: deinitialization by move //=----------------------------------= - assert(position <= start.advanced(by: squares.count)) - loop: while position > start { - position = position.predecessor() + Swift.assert(position <= start.advanced(by: squares.count)) + loop: while position > start { + position = position.predecessor() let square = position.move() let product = value.power.multipliedReportingOverflow(by: square.power) if product.overflow { continue loop } diff --git a/Sources/NBKCoreKit/Private/NBK+Text.swift b/Sources/NBKCoreKit/Private/NBK+Text.swift index 886fec4c..4517d88a 100644 --- a/Sources/NBKCoreKit/Private/NBK+Text.swift +++ b/Sources/NBKCoreKit/Private/NBK+Text.swift @@ -58,16 +58,18 @@ extension NBK { /// /// In this context, a chunk is a digit in the base of the given radix's power. /// - /// - Note: `@inlinable` is not needed. + /// ### Development + /// + /// - `@inlinable` is not needed. /// public static func integerTextUnchecked( - chunks: NBKTwinHeaded, radix: AnyRadixSolution, - alphabet: MaxRadixAlphabetEncoder, prefix: UnsafeUTF8, suffix: UnsafeUTF8) -> String { + chunks: NBKTwinHeaded, radix: AnyRadixSolution, alphabet: MaxRadixAlphabetEncoder, + prefix: UnsafeUTF8, suffix: UnsafeUTF8) -> String { assert(chunks.count <= 1 || chunks.last != 0, "chunks must not contain redundant zeros") assert(radix.power.isZero || chunks.allSatisfy({ $0 < radix.power }), "chunks must be less than radix's power") //=--------------------------------------= var remainders = chunks[...] - let mostSignificantChunk = remainders.popLast() ?? UInt() + let mostSignificantChunk = remainders.popLast() ?? 0 as UInt return NBK.withUnsafeTemporaryIntegerTextUnchecked( chunk: mostSignificantChunk, radix: radix, alphabet: alphabet) { first in var count: Int @@ -85,9 +87,11 @@ extension NBK { position.initialize(to: unit) } //=------------------------------= - suffix.reversed().forEach(pull) + for index in suffix.indices.reversed() { + pull(suffix[index]) // loop: index >= element + } //=------------------------------= - // dynamic: loop unswitch perf. + // dynamic: unswitch perf. //=------------------------------= if radix.power.isZero { let divisor = PerfectRadixSolution(radix)!.divisor() @@ -108,8 +112,13 @@ extension NBK { } } //=------------------------------= - first .reversed().forEach(pull) - prefix.reversed().forEach(pull) + for index in first .indices.reversed() { + pull(first [index]) // loop: index >= element + } + + for index in prefix.indices.reversed() { + pull(prefix[index]) // loop: index >= element + } //=------------------------------= assert(position == utf8.baseAddress!) return count as Int @@ -121,7 +130,9 @@ extension NBK { /// /// In this context, a chunk is a digit in the base of the given radix's power. /// - /// - Note: `@inlinable` is not needed. + /// ### Development + /// + /// - `@inlinable` is not needed. /// public static func withUnsafeTemporaryIntegerTextUnchecked( chunk: UInt, radix: AnyRadixSolution, alphabet: MaxRadixAlphabetEncoder, body:(UnsafeUTF8) -> T) -> T { @@ -132,19 +143,30 @@ extension NBK { var position = end as UnsafeMutablePointer //=----------------------------------= // pointee: initialization + // dynamic: unswitch perf. //=----------------------------------= - let divisor = radix.divisor() - backwards: repeat { - let digit: UInt; (chunk, digit) = divisor.dividing(chunk) - position = position.predecessor() - position.initialize(to: alphabet.encode(UInt8(truncatingIfNeeded: digit))!) - } while !chunk.isZero + if radix.power.isZero { + let divisor = PerfectRadixSolution(radix)!.divisor() + backwards: repeat { + let digit: UInt; (chunk, digit) = divisor.dividing(chunk) + position = position.predecessor() + position.initialize(to: alphabet.encode(UInt8(truncatingIfNeeded: digit))!) + } while !chunk.isZero + + } else { + let divisor = ImperfectRadixSolution(radix)!.divisor() + backwards: repeat { + let digit: UInt; (chunk, digit) = divisor.dividing(chunk) + position = position.predecessor() + position.initialize(to: alphabet.encode(UInt8(truncatingIfNeeded: digit))!) + } while !chunk.isZero + } //=----------------------------------= // pointee: deferred deinitialization //=----------------------------------= let count: Int = position.distance(to: end) defer{ position.deinitialize(count: count) } - return body(NBK.UnsafeUTF8(start: position, count: count)) + return body(UnsafeUTF8(start: position, count: count)) } } } diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text.swift index 7871e61f..6f02d3eb 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth+Text.swift @@ -163,8 +163,8 @@ extension NBKDoubleWidth where High == High.Magnitude { let count = start.distance(to: position) defer { start.deinitialize(count: count) } //=----------------------------------= - let chunks = NBKTwinHeaded(UnsafeBufferPointer( start: start, count: count)) let radix = NBK.AnyRadixSolution(radix) + let chunks = NBKTwinHeaded(UnsafeBufferPointer( start: start, count: count)) return NBK.integerTextUnchecked(chunks: chunks, radix: radix, alphabet: alphabet, prefix: prefix, suffix: suffix) } } diff --git a/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift b/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift index b40245bb..d239182a 100644 --- a/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift +++ b/Sources/NBKDoubleWidthKit/NBKDoubleWidth.swift @@ -226,7 +226,6 @@ High: NBKFixedWidthInteger, High.Digit: NBKCoreInteger { //=----------------------------------------------------------------------------= extension NBKDoubleWidth: NBKSignedInteger, SignedInteger, SignedNumeric where High: NBKSignedInteger { } - extension NBKDoubleWidth: NBKUnsignedInteger, UnsignedInteger /*---------*/ where High: NBKUnsignedInteger { } //*============================================================================* diff --git a/Tests/NBKCoreKitTests/Private/NBK+Text+RadixSolution.swift b/Tests/NBKCoreKitTests/Private/NBK+Text+RadixSolution.swift index 413cdba0..8ef504a9 100644 --- a/Tests/NBKCoreKitTests/Private/NBK+Text+RadixSolution.swift +++ b/Tests/NBKCoreKitTests/Private/NBK+Text+RadixSolution.swift @@ -23,12 +23,12 @@ final class NBKTestsOnTextByRadixSolution: XCTestCase { //=------------------------------------------------------------------------= func testAnyRadixSolution() { - func whereIsSize(_ size: T.Type) where T: NBKCoreInteger & NBKSignedInteger { + func whereSizeIs(_ size: T.Type) where T: NBKCoreInteger & NBKSignedInteger { for radix in 2 ... 36 { let solution = NBK.AnyRadixSolution(radix) XCTAssertEqual(solution.base, T.Magnitude(radix)) - var product = HL(T.Magnitude(0), T.Magnitude(1)) + var product = HL(T.Magnitude(0), T.Magnitude(1)) for _ in 0 ..< solution.exponent { XCTAssert(product.high.isZero) product = product.low.multipliedFullWidth(by: T.Magnitude(radix)) @@ -42,7 +42,7 @@ final class NBKTestsOnTextByRadixSolution: XCTestCase { } for size: any (NBKCoreInteger & NBKSignedInteger).Type in [Int.self, Int8.self, Int16.self, Int32.self, Int64.self] { - whereIsSize(size) + whereSizeIs(size) } } } From 8733940bcf81e8409b11e60abccf63b75b8ff896 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Thu, 7 Sep 2023 09:48:56 +0200 Subject: [PATCH 104/111] [NBKCoreKit] Unswitched loop methods (#78). --- Sources/NBKCoreKit/Private/NBK+Text.swift | 112 +++++++++++++++------- 1 file changed, 77 insertions(+), 35 deletions(-) diff --git a/Sources/NBKCoreKit/Private/NBK+Text.swift b/Sources/NBKCoreKit/Private/NBK+Text.swift index 4517d88a..3002559a 100644 --- a/Sources/NBKCoreKit/Private/NBK+Text.swift +++ b/Sources/NBKCoreKit/Private/NBK+Text.swift @@ -72,52 +72,49 @@ extension NBK { let mostSignificantChunk = remainders.popLast() ?? 0 as UInt return NBK.withUnsafeTemporaryIntegerTextUnchecked( chunk: mostSignificantChunk, radix: radix, alphabet: alphabet) { first in + //=----------------------------------= var count: Int count = prefix.count count += first .count count += remainders.count * radix.exponent count += suffix.count + //=----------------------------------= return String(unsafeUninitializedCapacity: count) { utf8 in var position = utf8.baseAddress!.advanced(by: count) //=------------------------------= // pointee: initialization //=------------------------------= - func pull(_ unit: UInt8) { + func pull(_ element: UInt8) { position = position.predecessor() - position.initialize(to: unit) + position.initialize(to: element) } //=------------------------------= for index in suffix.indices.reversed() { - pull(suffix[index]) // loop: index >= element + pull(suffix[index]) // loop: index > element } //=------------------------------= // dynamic: unswitch perf. //=------------------------------= if radix.power.isZero { - let divisor = PerfectRadixSolution(radix)!.divisor() - for var chunk in remainders { - for _ in 0 as UInt ..< radix.exponent { - let digit: UInt; (chunk, digit) = divisor.dividing(chunk) - pull(alphabet.encode(UInt8(truncatingIfNeeded: digit))!) - } - } - + NBK.integerTextUncheckedForEachCodeBlock( + remainders: remainders, + radix: PerfectRadixSolution(radix)!, + alphabet: alphabet, + perform: pull(_:)) } else { - let divisor = ImperfectRadixSolution(radix)!.divisor() - for var chunk in remainders { - for _ in 0 as UInt ..< radix.exponent { - let digit: UInt; (chunk, digit) = divisor.dividing(chunk) - pull(alphabet.encode(UInt8(truncatingIfNeeded: digit))!) - } - } + NBK.integerTextUncheckedForEachCodeBlock( + remainders: remainders, + radix: ImperfectRadixSolution(radix)!, + alphabet: alphabet, + perform: pull(_:)) } //=------------------------------= for index in first .indices.reversed() { - pull(first [index]) // loop: index >= element + pull(first [index]) // loop: index > element } for index in prefix.indices.reversed() { - pull(prefix[index]) // loop: index >= element + pull(prefix[index]) // loop: index > element } //=------------------------------= assert(position == utf8.baseAddress!) @@ -138,28 +135,30 @@ extension NBK { chunk: UInt, radix: AnyRadixSolution, alphabet: MaxRadixAlphabetEncoder, body:(UnsafeUTF8) -> T) -> T { assert(radix.power.isZero || chunk < radix.power, "chunks must be less than radix's power") return Swift.withUnsafeTemporaryAllocation(of: UInt8.self, capacity: radix.exponent) { utf8 in - var chunk = chunk as UInt - let end = utf8.baseAddress!.advanced(by: utf8.count) + let end = utf8.baseAddress!.advanced(by: utf8.count) var position = end as UnsafeMutablePointer //=----------------------------------= // pointee: initialization + //=----------------------------------= + func pull(_ element: UInt8) { + position = position.predecessor() + position.initialize(to: element) + } + //=----------------------------------= // dynamic: unswitch perf. //=----------------------------------= if radix.power.isZero { - let divisor = PerfectRadixSolution(radix)!.divisor() - backwards: repeat { - let digit: UInt; (chunk, digit) = divisor.dividing(chunk) - position = position.predecessor() - position.initialize(to: alphabet.encode(UInt8(truncatingIfNeeded: digit))!) - } while !chunk.isZero - + NBK.integerTextUncheckedForEachCodeBlock( + first: chunk, + radix: PerfectRadixSolution(radix)!, + alphabet: alphabet, + perform: pull(_:)) } else { - let divisor = ImperfectRadixSolution(radix)!.divisor() - backwards: repeat { - let digit: UInt; (chunk, digit) = divisor.dividing(chunk) - position = position.predecessor() - position.initialize(to: alphabet.encode(UInt8(truncatingIfNeeded: digit))!) - } while !chunk.isZero + NBK.integerTextUncheckedForEachCodeBlock( + first: chunk, + radix: ImperfectRadixSolution(radix)!, + alphabet: alphabet, + perform: pull(_:)) } //=----------------------------------= // pointee: deferred deinitialization @@ -169,4 +168,47 @@ extension NBK { return body(UnsafeUTF8(start: position, count: count)) } } + + //=------------------------------------------------------------------------= + // MARK: Details x Encode x Code Blocks + //=------------------------------------------------------------------------= + + /// Executes the given closure on each integer text digit made from the first chunk. + /// + /// ### Development + /// + /// The nested version performed poorly, so now it's freestanding with `@inline(always)`. + /// + @inline(__always) @inlinable static func integerTextUncheckedForEachCodeBlock( + first: UInt, radix: some RadixSolution, alphabet: MaxRadixAlphabetEncoder, perform: (UInt8) -> Void) { + assert(radix.power.isZero || first < radix.power, "chunks must be less than radix's power") + //=--------------------------------------= + var chunk = first as UInt + let divisor = radix.divisor() + //=--------------------------------------= + backwards: repeat { + let digit: UInt; (chunk,digit) = divisor.dividing(chunk) + perform(alphabet.encode(UInt8(truncatingIfNeeded: digit))!) + } while !chunk.isZero + } + + /// Executes the given closure on each integer text digit made from non-first chunks. + /// + /// ### Development + /// + /// The nested version performed poorly, so now it's freestanding with `@inline(always)`. + /// + @inline(__always) @inlinable static func integerTextUncheckedForEachCodeBlock( + remainders: some Collection, radix: some RadixSolution, alphabet: MaxRadixAlphabetEncoder, perform: (UInt8) -> Void) { + assert(radix.power.isZero || remainders.allSatisfy({ $0 < radix.power }), "chunks must be less than radix's power") + //=--------------------------------------= + let divisor = radix.divisor() + //=--------------------------------------= + for var chunk in remainders { + for _ in 0 as UInt ..< radix.exponent { + let digit: UInt; (chunk,digit) = divisor.dividing(chunk) + perform(alphabet.encode(UInt8(truncatingIfNeeded: digit))!) + } + } + } } From 36e59a094c5269d4ddebde853a41c7da66600a19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Thu, 7 Sep 2023 11:47:41 +0200 Subject: [PATCH 105/111] [NBKCoreKit] Cleanup (#78). --- .../Private/NBK+Text+RadixSolution.swift | 2 +- Sources/NBKCoreKit/Private/NBK+Text.swift | 56 ++++++++----------- .../NBKDoubleWidth+Text.swift | 36 ++++++++++++ 3 files changed, 61 insertions(+), 33 deletions(-) diff --git a/Sources/NBKCoreKit/Private/NBK+Text+RadixSolution.swift b/Sources/NBKCoreKit/Private/NBK+Text+RadixSolution.swift index 8961a5e3..36a6ce1d 100644 --- a/Sources/NBKCoreKit/Private/NBK+Text+RadixSolution.swift +++ b/Sources/NBKCoreKit/Private/NBK+Text+RadixSolution.swift @@ -393,7 +393,7 @@ extension _NBKAnyRadixSolution { //=--------------------------------------= } else { value.exponent = NBK.initOrBitCast(truncating: Element.bitWidth) / (zeros) - value.power = (1 as Element) &<< (zeros &* value.exponent) + value.power = (1 as Element) &<< (zeros &* value.exponent) } return value as Value diff --git a/Sources/NBKCoreKit/Private/NBK+Text.swift b/Sources/NBKCoreKit/Private/NBK+Text.swift index 3002559a..c4092519 100644 --- a/Sources/NBKCoreKit/Private/NBK+Text.swift +++ b/Sources/NBKCoreKit/Private/NBK+Text.swift @@ -93,20 +93,14 @@ extension NBK { pull(suffix[index]) // loop: index > element } //=------------------------------= - // dynamic: unswitch perf. + // dynamic: loop unswitching perf. //=------------------------------= if radix.power.isZero { - NBK.integerTextUncheckedForEachCodeBlock( - remainders: remainders, - radix: PerfectRadixSolution(radix)!, - alphabet: alphabet, - perform: pull(_:)) + NBK.integerTextSubsequenceReversedForEachCodeBlockUnchecked( + body: remainders, radix: PerfectRadixSolution(radix)!, alphabet: alphabet, perform: pull) } else { - NBK.integerTextUncheckedForEachCodeBlock( - remainders: remainders, - radix: ImperfectRadixSolution(radix)!, - alphabet: alphabet, - perform: pull(_:)) + NBK.integerTextSubsequenceReversedForEachCodeBlockUnchecked( + body: remainders, radix: ImperfectRadixSolution(radix)!, alphabet: alphabet, perform: pull) } //=------------------------------= for index in first .indices.reversed() { @@ -145,20 +139,14 @@ extension NBK { position.initialize(to: element) } //=----------------------------------= - // dynamic: unswitch perf. + // dynamic: loop unswitching perf. //=----------------------------------= if radix.power.isZero { - NBK.integerTextUncheckedForEachCodeBlock( - first: chunk, - radix: PerfectRadixSolution(radix)!, - alphabet: alphabet, - perform: pull(_:)) + NBK.integerTextSubsequenceReversedForEachCodeBlockUnchecked( + tail: chunk, radix: PerfectRadixSolution(radix)!, alphabet: alphabet, perform: pull) } else { - NBK.integerTextUncheckedForEachCodeBlock( - first: chunk, - radix: ImperfectRadixSolution(radix)!, - alphabet: alphabet, - perform: pull(_:)) + NBK.integerTextSubsequenceReversedForEachCodeBlockUnchecked( + tail: chunk, radix: ImperfectRadixSolution(radix)!, alphabet: alphabet, perform: pull) } //=----------------------------------= // pointee: deferred deinitialization @@ -173,17 +161,19 @@ extension NBK { // MARK: Details x Encode x Code Blocks //=------------------------------------------------------------------------= - /// Executes the given closure on each integer text digit made from the first chunk. + /// Performs an action for each digit of a most-significant chunk. + /// + /// The digits appear from least significant to most and redundant zeros are excluded. /// /// ### Development /// /// The nested version performed poorly, so now it's freestanding with `@inline(always)`. /// - @inline(__always) @inlinable static func integerTextUncheckedForEachCodeBlock( - first: UInt, radix: some RadixSolution, alphabet: MaxRadixAlphabetEncoder, perform: (UInt8) -> Void) { - assert(radix.power.isZero || first < radix.power, "chunks must be less than radix's power") + @inline(__always) @inlinable static func integerTextSubsequenceReversedForEachCodeBlockUnchecked( + tail: UInt, radix: some RadixSolution, alphabet: MaxRadixAlphabetEncoder, perform: (UInt8) -> Void) { + assert(radix.power.isZero || tail < radix.power, "chunks must be less than radix's power") //=--------------------------------------= - var chunk = first as UInt + var chunk = tail as UInt let divisor = radix.divisor() //=--------------------------------------= backwards: repeat { @@ -192,19 +182,21 @@ extension NBK { } while !chunk.isZero } - /// Executes the given closure on each integer text digit made from non-first chunks. + /// Performs an action for each digit of non-most-significant chunks. + /// + /// The digits appear from least significant to most and redundant zeros are included. /// /// ### Development /// /// The nested version performed poorly, so now it's freestanding with `@inline(always)`. /// - @inline(__always) @inlinable static func integerTextUncheckedForEachCodeBlock( - remainders: some Collection, radix: some RadixSolution, alphabet: MaxRadixAlphabetEncoder, perform: (UInt8) -> Void) { - assert(radix.power.isZero || remainders.allSatisfy({ $0 < radix.power }), "chunks must be less than radix's power") + @inline(__always) @inlinable static func integerTextSubsequenceReversedForEachCodeBlockUnchecked( + body: some Collection, radix: some RadixSolution, alphabet: MaxRadixAlphabetEncoder, perform: (UInt8) -> Void) { + assert(radix.power.isZero || body.allSatisfy({ $0 < radix.power }), "chunks must be less than radix's power") //=--------------------------------------= let divisor = radix.divisor() //=--------------------------------------= - for var chunk in remainders { + for var chunk in body { for _ in 0 as UInt ..< radix.exponent { let digit: UInt; (chunk,digit) = divisor.dividing(chunk) perform(alphabet.encode(UInt8(truncatingIfNeeded: digit))!) diff --git a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Text.swift b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Text.swift index 4806f3f8..801f60ef 100644 --- a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Text.swift +++ b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Text.swift @@ -472,6 +472,42 @@ final class NBKDoubleWidthTestsOnTextAsUInt256: XCTestCase { } } +//*============================================================================* +// MARK: * NBK x Double Width x Text x Simple Cases x UInt256 +//*============================================================================* + +final class NBKDoubleWidthTestsOnTextBySimpleCasesAsUInt256: XCTestCase { + + typealias T = UInt256 + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testDecodingAndEncodingRadix16() { + var x64: (UInt64, UInt64, UInt64, UInt64) + var y64: (String, String, String, String) + //=--------------------------------------= + x64.3 = 0x3130292827262524; y64.3 = "3130292827262524" + x64.2 = 0x2322212019181716; y64.2 = "2322212019181716" + x64.1 = 0x0154131211100908; y64.1 = "0154131211100908" + x64.0 = 0x0706050403020100; y64.0 = "0706050403020100" + + NBKAssertDecodeText(T(x64: x64), 16, "\(y64.3)\(y64.2)\(y64.1)\(y64.0)") + NBKAssertEncodeText(T(x64: x64), 16, true, "\(y64.3)\(y64.2)\(y64.1)\(y64.0)") + NBKAssertEncodeText(T(x64: x64), 16, false, "\(y64.3)\(y64.2)\(y64.1)\(y64.0)") + //=--------------------------------------= + x64.3 = 0x0001020304050607; y64.3 = "1020304050607" + x64.2 = 0x0809101112131415; y64.2 = "0809101112131415" + x64.1 = 0x1617181920212223; y64.1 = "1617181920212223" + x64.0 = 0x2425262728293031; y64.0 = "2425262728293031" + + NBKAssertDecodeText(T(x64: x64), 16, "\(y64.3)\(y64.2)\(y64.1)\(y64.0)") + NBKAssertEncodeText(T(x64: x64), 16, true, "\(y64.3)\(y64.2)\(y64.1)\(y64.0)") + NBKAssertEncodeText(T(x64: x64), 16, false, "\(y64.3)\(y64.2)\(y64.1)\(y64.0)") + } +} + //*============================================================================* // MARK: * NBK x Double Width x Text x Assertions //*============================================================================* From 7df2709c7b233e82f440bc2a859f67e95300c1f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Thu, 7 Sep 2023 18:26:06 +0200 Subject: [PATCH 106/111] [NBKCoreKit] Closure, no divisor (#78). --- .../Private/NBK+Text+RadixSolution.swift | 81 +++++++------------ Sources/NBKCoreKit/Private/NBK+Text.swift | 12 +-- .../NBKDoubleWidth+Text.swift | 3 +- 3 files changed, 37 insertions(+), 59 deletions(-) diff --git a/Sources/NBKCoreKit/Private/NBK+Text+RadixSolution.swift b/Sources/NBKCoreKit/Private/NBK+Text+RadixSolution.swift index 36a6ce1d..449f3e94 100644 --- a/Sources/NBKCoreKit/Private/NBK+Text+RadixSolution.swift +++ b/Sources/NBKCoreKit/Private/NBK+Text+RadixSolution.swift @@ -14,17 +14,11 @@ extension NBK { //=------------------------------------------------------------------------= - // MARK: Protocols + // MARK: Aliases //=------------------------------------------------------------------------= public typealias RadixSolution = _NBKRadixSolution - public typealias RadixSolutionDivisor = _NBKRadixSolutionDivisor - - //=------------------------------------------------------------------------= - // MARK: Models - //=------------------------------------------------------------------------= - public typealias AnyRadixSolution = _NBKAnyRadixSolution public typealias PerfectRadixSolution = _NBKPerfectRadixSolution @@ -44,21 +38,23 @@ extension NBK { /// public protocol _NBKRadixSolution { - typealias Element = Size.Magnitude - + typealias Element = Size.Magnitude + associatedtype Size: NBKCoreInteger & NBKSignedInteger - associatedtype Divisor: NBK.RadixSolutionDivisor where Divisor.Size == Size - //=------------------------------------------------------------------------= // MARK: State //=------------------------------------------------------------------------= - @inlinable var base: Element { get } + @inlinable var base: Element { get } @inlinable var exponent: Element { get } - @inlinable var power: Element { get } + @inlinable var power: Element { get } + + //=------------------------------------------------------------------------= + // MARK: Accessors + //=------------------------------------------------------------------------= @inlinable var solution: NBK.AnyRadixSolution { get } @@ -66,7 +62,7 @@ public protocol _NBKRadixSolution { // MARK: Utilities //=------------------------------------------------------------------------= - @inlinable func divisor() -> Divisor + @inlinable func division() -> (Element) -> QR } //=----------------------------------------------------------------------------= @@ -90,25 +86,6 @@ extension NBK.RadixSolution { } } -//*============================================================================* -// MARK: * NBK x Radix Solution x Divisor -//*============================================================================* - -/// An radix solution helper model allowing efficient repeated division. -public protocol _NBKRadixSolutionDivisor where Size: NBKCoreInteger & NBKSignedInteger { - - typealias Element = Size.Magnitude - - associatedtype Size: NBKCoreInteger & NBKSignedInteger - - //=------------------------------------------------------------------------= - // MARK: Utilities - //=------------------------------------------------------------------------= - - /// Returns the `quotient` and `remainder` of dividing `dividend` by `self`. - @inlinable func dividing(_ dividend: Element) -> QR -} - //*============================================================================* // MARK: * NBK x Radix Solution x Perfect //*============================================================================* @@ -152,15 +129,15 @@ public protocol _NBKRadixSolutionDivisor where Size: NBKCoreInteger & NBKS // MARK: Utilities //=------------------------------------------------------------------------= - @inlinable public func divisor() -> Divisor { - Divisor(self) + @inlinable public func division() -> (Element) -> QR { + Division(self).callAsFunction } //*========================================================================* - // MARK: * Divisor + // MARK: * Division //*========================================================================* - @frozen public struct Divisor: NBK.RadixSolutionDivisor { + @frozen @usableFromInline struct Division { //=--------------------------------------------------------------------= // MARK: State @@ -175,14 +152,14 @@ public protocol _NBKRadixSolutionDivisor where Size: NBKCoreInteger & NBKS @inlinable init(_ solution: NBK.PerfectRadixSolution) { self.quotientShift = NBK.initOrBitCast(truncating: solution.base.trailingZeroBitCount) - self.remainderMask = solution.base &- (1 as Element) + self.remainderMask = solution.base &+ Element.max // &- 1 } //=--------------------------------------------------------------------= // MARK: Utilities //=--------------------------------------------------------------------= - @inlinable public func dividing(_ dividend: Element) -> QR { + @inlinable func callAsFunction(_ dividend: Element) -> QR { QR(dividend &>> self.quotientShift, dividend & self.remainderMask) } } @@ -231,8 +208,8 @@ public protocol _NBKRadixSolutionDivisor where Size: NBKCoreInteger & NBKS // MARK: Utilities //=------------------------------------------------------------------------= - @inlinable public func divisor() -> Divisor { - Divisor(self) + @inlinable public func division() -> (Element) -> QR { + Division(self).callAsFunction } /// Overestimates how many times its power divides the magnitude. @@ -241,10 +218,10 @@ public protocol _NBKRadixSolutionDivisor where Size: NBKCoreInteger & NBKS } //*========================================================================* - // MARK: * Divisor + // MARK: * Division //*========================================================================* - @frozen public struct Divisor: NBK.RadixSolutionDivisor { + @frozen @usableFromInline struct Division { //=--------------------------------------------------------------------= // MARK: State @@ -264,8 +241,8 @@ public protocol _NBKRadixSolutionDivisor where Size: NBKCoreInteger & NBKS // MARK: Utilities //=--------------------------------------------------------------------= - @inlinable public func dividing(_ dividend: Element) -> QR { - QR(dividend.quotientAndRemainder(dividingBy: self.base)) + @inlinable func callAsFunction(_ dividend: Element) -> QR { + dividend.quotientAndRemainder(dividingBy: self.base) } } } @@ -321,15 +298,15 @@ public protocol _NBKRadixSolutionDivisor where Size: NBKCoreInteger & NBKS // MARK: Utilities //=------------------------------------------------------------------------= - @inlinable public func divisor() -> Divisor { - Divisor(self) + @inlinable public func division() -> (Element) -> QR { + Division(self).callAsFunction } //*========================================================================* - // MARK: * Divisor + // MARK: * Division //*========================================================================* - @frozen public struct Divisor: NBK.RadixSolutionDivisor { + @frozen @usableFromInline struct Division { //=--------------------------------------------------------------------= // MARK: State @@ -357,7 +334,7 @@ public protocol _NBKRadixSolutionDivisor where Size: NBKCoreInteger & NBKS // MARK: Utilities //=--------------------------------------------------------------------= - @inlinable public func dividing(_ dividend: Element) -> QR { + @inlinable func callAsFunction(_ dividend: Element) -> QR { switch self.zeroOrRemainderMask.isZero { case true: return QR(dividend.quotientAndRemainder(dividingBy: self.baseOrQuotientShift) ) case false: return QR(dividend &>> self.baseOrQuotientShift, dividend & self.zeroOrRemainderMask) } @@ -396,7 +373,7 @@ extension _NBKAnyRadixSolution { value.power = (1 as Element) &<< (zeros &* value.exponent) } - return value as Value + return value as Value as Value as Value } /// Returns the largest exponent in `pow(radix, exponent) <= Element.max + 1`. @@ -437,7 +414,7 @@ extension _NBKAnyRadixSolution { value.power = product.partialValue } - return value as Value + return value as Value as Value as Value } } } diff --git a/Sources/NBKCoreKit/Private/NBK+Text.swift b/Sources/NBKCoreKit/Private/NBK+Text.swift index c4092519..beb1001f 100644 --- a/Sources/NBKCoreKit/Private/NBK+Text.swift +++ b/Sources/NBKCoreKit/Private/NBK+Text.swift @@ -129,7 +129,7 @@ extension NBK { chunk: UInt, radix: AnyRadixSolution, alphabet: MaxRadixAlphabetEncoder, body:(UnsafeUTF8) -> T) -> T { assert(radix.power.isZero || chunk < radix.power, "chunks must be less than radix's power") return Swift.withUnsafeTemporaryAllocation(of: UInt8.self, capacity: radix.exponent) { utf8 in - let end = utf8.baseAddress!.advanced(by: utf8.count) + let end = utf8.baseAddress!.advanced (by: utf8.count) var position = end as UnsafeMutablePointer //=----------------------------------= // pointee: initialization @@ -173,11 +173,11 @@ extension NBK { tail: UInt, radix: some RadixSolution, alphabet: MaxRadixAlphabetEncoder, perform: (UInt8) -> Void) { assert(radix.power.isZero || tail < radix.power, "chunks must be less than radix's power") //=--------------------------------------= - var chunk = tail as UInt - let divisor = radix.divisor() + var chunk = tail as UInt + let division = radix.division() //=--------------------------------------= backwards: repeat { - let digit: UInt; (chunk,digit) = divisor.dividing(chunk) + let digit: UInt; (chunk,digit) = division(chunk) perform(alphabet.encode(UInt8(truncatingIfNeeded: digit))!) } while !chunk.isZero } @@ -194,11 +194,11 @@ extension NBK { body: some Collection, radix: some RadixSolution, alphabet: MaxRadixAlphabetEncoder, perform: (UInt8) -> Void) { assert(radix.power.isZero || body.allSatisfy({ $0 < radix.power }), "chunks must be less than radix's power") //=--------------------------------------= - let divisor = radix.divisor() + let division = radix.division() //=--------------------------------------= for var chunk in body { for _ in 0 as UInt ..< radix.exponent { - let digit: UInt; (chunk,digit) = divisor.dividing(chunk) + let digit: UInt; (chunk,digit) = division(chunk) perform(alphabet.encode(UInt8(truncatingIfNeeded: digit))!) } } diff --git a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Text.swift b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Text.swift index 801f60ef..1f0bb823 100644 --- a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Text.swift +++ b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Text.swift @@ -485,12 +485,13 @@ final class NBKDoubleWidthTestsOnTextBySimpleCasesAsUInt256: XCTestCase { //=------------------------------------------------------------------------= func testDecodingAndEncodingRadix16() { + //=--------------------------------------= var x64: (UInt64, UInt64, UInt64, UInt64) var y64: (String, String, String, String) //=--------------------------------------= x64.3 = 0x3130292827262524; y64.3 = "3130292827262524" x64.2 = 0x2322212019181716; y64.2 = "2322212019181716" - x64.1 = 0x0154131211100908; y64.1 = "0154131211100908" + x64.1 = 0x1514131211100908; y64.1 = "1514131211100908" x64.0 = 0x0706050403020100; y64.0 = "0706050403020100" NBKAssertDecodeText(T(x64: x64), 16, "\(y64.3)\(y64.2)\(y64.1)\(y64.0)") From 8dfb4c77c003ba9389c233959a1231d011ff97aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Fri, 8 Sep 2023 09:21:06 +0200 Subject: [PATCH 107/111] Some text conversion tests. --- .../NBKDoubleWidth+Text.swift | 139 ++++++++++++++++-- 1 file changed, 124 insertions(+), 15 deletions(-) diff --git a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Text.swift b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Text.swift index 1f0bb823..832be4ad 100644 --- a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Text.swift +++ b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Text.swift @@ -473,10 +473,10 @@ final class NBKDoubleWidthTestsOnTextAsUInt256: XCTestCase { } //*============================================================================* -// MARK: * NBK x Double Width x Text x Simple Cases x UInt256 +// MARK: * NBK x Double Width x Text x Other Cases x UInt256 //*============================================================================* -final class NBKDoubleWidthTestsOnTextBySimpleCasesAsUInt256: XCTestCase { +final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { typealias T = UInt256 @@ -484,28 +484,137 @@ final class NBKDoubleWidthTestsOnTextBySimpleCasesAsUInt256: XCTestCase { // MARK: Tests //=------------------------------------------------------------------------= - func testDecodingAndEncodingRadix16() { + func testDecodingAndEncodingRadix02() { + var txt: (String) + var x64: (UInt64, UInt64, UInt64, UInt64) + //=--------------------------------------= + x64.3 = 0xfffefdfcfbfaf9f8 + x64.2 = 0xf7f6f5f4f3f2f1f0 + x64.1 = 0xefeeedecebeae9e8 + x64.0 = 0xe7e6e5e4e3e2e1e0 + txt = """ + 1111111111111110111111011111110011111011111110101111100111111000\ + 1111011111110110111101011111010011110011111100101111000111110000\ + 1110111111101110111011011110110011101011111010101110100111101000\ + 1110011111100110111001011110010011100011111000101110000111100000 + """ + + NBKAssertDecodeText(T(x64: x64), 02, txt) + NBKAssertEncodeText(T(x64: x64), 02, true, String(txt.drop(while:{ $0 == "0" })).uppercased()) + NBKAssertEncodeText(T(x64: x64), 02, false, String(txt.drop(while:{ $0 == "0" })).lowercased()) + //=--------------------------------------= + x64.3 = 0x1f1e1d1c1b1a1918 + x64.2 = 0x1716151413121110 + x64.1 = 0x0f0e0d0c0b0a0908 + x64.0 = 0x0706050403020100 + txt = """ + 0001111100011110000111010001110000011011000110100001100100011000\ + 0001011100010110000101010001010000010011000100100001000100010000\ + 0000111100001110000011010000110000001011000010100000100100001000\ + 0000011100000110000001010000010000000011000000100000000100000000 + """ + + NBKAssertDecodeText(T(x64: x64), 02, txt) + NBKAssertEncodeText(T(x64: x64), 02, true, String(txt.drop(while:{ $0 == "0" })).uppercased()) + NBKAssertEncodeText(T(x64: x64), 02, false, String(txt.drop(while:{ $0 == "0" })).lowercased()) + } + + func testDecodingAndEncodingRadix08() { + var txt: (String) + var x64: (UInt64, UInt64, UInt64, UInt64) + //=--------------------------------------= + x64.3 = 0xfffefdfcfbfaf9f8 + x64.2 = 0xf7f6f5f4f3f2f1f0 + x64.1 = 0xefeeedecebeae9e8 + x64.0 = 0xe7e6e5e4e3e2e1e0 + txt = "17777677376373765747707577336575171762743703577356675472765351721637467136234370560740" + + NBKAssertDecodeText(T(x64: x64), 08, txt) + NBKAssertEncodeText(T(x64: x64), 08, true, String(txt.drop(while:{ $0 == "0" })).uppercased()) + NBKAssertEncodeText(T(x64: x64), 08, false, String(txt.drop(while:{ $0 == "0" })).lowercased()) + //=-----------------------s---------------= + x64.3 = 0x1f1e1d1c1b1a1918 + x64.2 = 0x1716151413121110 + x64.1 = 0x0f0e0d0c0b0a0908 + x64.0 = 0x0706050403020100 + txt = "01743607216033064144300561302505011422042100170340641402605011020034060120200300400400" + + NBKAssertDecodeText(T(x64: x64), 08, txt) + NBKAssertEncodeText(T(x64: x64), 08, true, String(txt.drop(while:{ $0 == "0" })).uppercased()) + NBKAssertEncodeText(T(x64: x64), 08, false, String(txt.drop(while:{ $0 == "0" })).lowercased()) + } + + func testDecodingAndEncodingRadix10() { + var txt: (String) + var x64: (UInt64, UInt64, UInt64, UInt64) + //=--------------------------------------= + x64.3 = 0xfffefdfcfbfaf9f8 + x64.2 = 0xf7f6f5f4f3f2f1f0 + x64.1 = 0xefeeedecebeae9e8 + x64.0 = 0xe7e6e5e4e3e2e1e0 + txt = "115790308505455567723526024286119531261069242336003260839703036409543150199264" + + NBKAssertDecodeText(T(x64: x64), 10, txt) + NBKAssertEncodeText(T(x64: x64), 10, true, String(txt.drop(while:{ $0 == "0" })).uppercased()) + NBKAssertEncodeText(T(x64: x64), 10, false, String(txt.drop(while:{ $0 == "0" })).lowercased()) //=--------------------------------------= + x64.3 = 0x1f1e1d1c1b1a1918 + x64.2 = 0x1716151413121110 + x64.1 = 0x0f0e0d0c0b0a0908 + x64.0 = 0x0706050403020100 + txt = "014074904626401341155369551180448584754667373453244490859944217516317499064576" + + NBKAssertDecodeText(T(x64: x64), 10, txt) + NBKAssertEncodeText(T(x64: x64), 10, true, String(txt.drop(while:{ $0 == "0" })).uppercased()) + NBKAssertEncodeText(T(x64: x64), 10, false, String(txt.drop(while:{ $0 == "0" })).lowercased()) + } + + func testDecodingAndEncodingRadix16() { var x64: (UInt64, UInt64, UInt64, UInt64) var y64: (String, String, String, String) //=--------------------------------------= - x64.3 = 0x3130292827262524; y64.3 = "3130292827262524" - x64.2 = 0x2322212019181716; y64.2 = "2322212019181716" - x64.1 = 0x1514131211100908; y64.1 = "1514131211100908" - x64.0 = 0x0706050403020100; y64.0 = "0706050403020100" + x64.3 = 0xfffefdfcfbfaf9f8; y64.3 = "fffefdfcfbfaf9f8" + x64.2 = 0xf7f6f5f4f3f2f1f0; y64.2 = "f7f6f5f4f3f2f1f0" + x64.1 = 0xefeeedecebeae9e8; y64.1 = "efeeedecebeae9e8" + x64.0 = 0xe7e6e5e4e3e2e1e0; y64.0 = "e7e6e5e4e3e2e1e0" NBKAssertDecodeText(T(x64: x64), 16, "\(y64.3)\(y64.2)\(y64.1)\(y64.0)") - NBKAssertEncodeText(T(x64: x64), 16, true, "\(y64.3)\(y64.2)\(y64.1)\(y64.0)") - NBKAssertEncodeText(T(x64: x64), 16, false, "\(y64.3)\(y64.2)\(y64.1)\(y64.0)") + NBKAssertEncodeText(T(x64: x64), 16, true, "\(y64.3)\(y64.2)\(y64.1)\(y64.0)".uppercased()) + NBKAssertEncodeText(T(x64: x64), 16, false, "\(y64.3)\(y64.2)\(y64.1)\(y64.0)".lowercased()) //=--------------------------------------= - x64.3 = 0x0001020304050607; y64.3 = "1020304050607" - x64.2 = 0x0809101112131415; y64.2 = "0809101112131415" - x64.1 = 0x1617181920212223; y64.1 = "1617181920212223" - x64.0 = 0x2425262728293031; y64.0 = "2425262728293031" + x64.3 = 0x1f1e1d1c1b1a1918; y64.3 = "1f1e1d1c1b1a1918" + x64.2 = 0x1716151413121110; y64.2 = "1716151413121110" + x64.1 = 0x0f0e0d0c0b0a0908; y64.1 = "0f0e0d0c0b0a0908" + x64.0 = 0x0706050403020100; y64.0 = "0706050403020100" NBKAssertDecodeText(T(x64: x64), 16, "\(y64.3)\(y64.2)\(y64.1)\(y64.0)") - NBKAssertEncodeText(T(x64: x64), 16, true, "\(y64.3)\(y64.2)\(y64.1)\(y64.0)") - NBKAssertEncodeText(T(x64: x64), 16, false, "\(y64.3)\(y64.2)\(y64.1)\(y64.0)") + NBKAssertEncodeText(T(x64: x64), 16, true, "\(y64.3)\(y64.2)\(y64.1)\(y64.0)".uppercased()) + NBKAssertEncodeText(T(x64: x64), 16, false, "\(y64.3)\(y64.2)\(y64.1)\(y64.0)".lowercased()) + } + + func testDecodingAndEncodingRadix36() { + var txt: (String) + var x64: (UInt64, UInt64, UInt64, UInt64) + //=--------------------------------------= + x64.3 = 0xfffefdfcfbfaf9f8 + x64.2 = 0xf7f6f5f4f3f2f1f0 + x64.1 = 0xefeeedecebeae9e8 + x64.0 = 0xe7e6e5e4e3e2e1e0 + txt = "6dp15j43ld5l8i7wvimlj7kxgbfxkxkgmo66lge382296ouqjk" + + NBKAssertDecodeText(T(x64: x64), 36, txt) + NBKAssertEncodeText(T(x64: x64), 36, true, String(txt.drop(while:{ $0 == "0" })).uppercased()) + NBKAssertEncodeText(T(x64: x64), 36, false, String(txt.drop(while:{ $0 == "0" })).lowercased()) + //=--------------------------------------= + x64.3 = 0x1f1e1d1c1b1a1918 + x64.2 = 0x1716151413121110 + x64.1 = 0x0f0e0d0c0b0a0908 + x64.0 = 0x0706050403020100 + txt = "0rx55jlhq7obx1pvd9861yo6c11bed0cd8s8wz2hpvczt00c1s" + + NBKAssertDecodeText(T(x64: x64), 36, txt) + NBKAssertEncodeText(T(x64: x64), 36, true, String(txt.drop(while:{ $0 == "0" })).uppercased()) + NBKAssertEncodeText(T(x64: x64), 36, false, String(txt.drop(while:{ $0 == "0" })).lowercased()) } } From f424169f979cfe401973608b11afef1ed5d49915 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Fri, 8 Sep 2023 10:34:11 +0200 Subject: [PATCH 108/111] Moar text conversion tests! --- .../NBKDoubleWidth+Text.swift | 1012 +++++++++++++++-- 1 file changed, 891 insertions(+), 121 deletions(-) diff --git a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Text.swift b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Text.swift index 832be4ad..f5d41ba1 100644 --- a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Text.swift +++ b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Text.swift @@ -480,141 +480,911 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { typealias T = UInt256 + //=------------------------------------------------------------------------= + // MARK: State + //=------------------------------------------------------------------------= + + var radix: Int = 10 + var x64 = (UInt64(), UInt64(), UInt64(), UInt64()) + var txt = (String()) + + //=------------------------------------------------------------------------= + // MARK: Set Up, Tear Down + //=------------------------------------------------------------------------= + + override func setUp() { + self.radix = 10 + self.x64.0 = UInt64() + self.x64.1 = UInt64() + self.x64.2 = UInt64() + self.x64.3 = UInt64() + self.txt = String() + } + + override func tearDown() { + let decoded = T(x64: self.x64) + var encoded = String(self.txt.drop(while:{ $0 == "0" })) + if encoded.isEmpty { encoded += "0" } + + NBKAssertDecodeText(decoded, self.radix, encoded) + NBKAssertEncodeText(decoded, self.radix, true, encoded.uppercased()) + NBKAssertEncodeText(decoded, self.radix, false, encoded.lowercased()) + } + //=------------------------------------------------------------------------= // MARK: Tests //=------------------------------------------------------------------------= - func testDecodingAndEncodingRadix02() { - var txt: (String) - var x64: (UInt64, UInt64, UInt64, UInt64) - //=--------------------------------------= - x64.3 = 0xfffefdfcfbfaf9f8 - x64.2 = 0xf7f6f5f4f3f2f1f0 - x64.1 = 0xefeeedecebeae9e8 - x64.0 = 0xe7e6e5e4e3e2e1e0 - txt = """ + func testRadix02TopToBottom() { + self.radix = 02 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ 1111111111111110111111011111110011111011111110101111100111111000\ 1111011111110110111101011111010011110011111100101111000111110000\ 1110111111101110111011011110110011101011111010101110100111101000\ 1110011111100110111001011110010011100011111000101110000111100000 """ - - NBKAssertDecodeText(T(x64: x64), 02, txt) - NBKAssertEncodeText(T(x64: x64), 02, true, String(txt.drop(while:{ $0 == "0" })).uppercased()) - NBKAssertEncodeText(T(x64: x64), 02, false, String(txt.drop(while:{ $0 == "0" })).lowercased()) - //=--------------------------------------= - x64.3 = 0x1f1e1d1c1b1a1918 - x64.2 = 0x1716151413121110 - x64.1 = 0x0f0e0d0c0b0a0908 - x64.0 = 0x0706050403020100 - txt = """ + } + + func testRadix02BottomToTop() { + self.radix = 02 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ 0001111100011110000111010001110000011011000110100001100100011000\ 0001011100010110000101010001010000010011000100100001000100010000\ 0000111100001110000011010000110000001011000010100000100100001000\ 0000011100000110000001010000010000000011000000100000000100000000 """ - - NBKAssertDecodeText(T(x64: x64), 02, txt) - NBKAssertEncodeText(T(x64: x64), 02, true, String(txt.drop(while:{ $0 == "0" })).uppercased()) - NBKAssertEncodeText(T(x64: x64), 02, false, String(txt.drop(while:{ $0 == "0" })).lowercased()) - } - - func testDecodingAndEncodingRadix08() { - var txt: (String) - var x64: (UInt64, UInt64, UInt64, UInt64) - //=--------------------------------------= - x64.3 = 0xfffefdfcfbfaf9f8 - x64.2 = 0xf7f6f5f4f3f2f1f0 - x64.1 = 0xefeeedecebeae9e8 - x64.0 = 0xe7e6e5e4e3e2e1e0 - txt = "17777677376373765747707577336575171762743703577356675472765351721637467136234370560740" - - NBKAssertDecodeText(T(x64: x64), 08, txt) - NBKAssertEncodeText(T(x64: x64), 08, true, String(txt.drop(while:{ $0 == "0" })).uppercased()) - NBKAssertEncodeText(T(x64: x64), 08, false, String(txt.drop(while:{ $0 == "0" })).lowercased()) - //=-----------------------s---------------= - x64.3 = 0x1f1e1d1c1b1a1918 - x64.2 = 0x1716151413121110 - x64.1 = 0x0f0e0d0c0b0a0908 - x64.0 = 0x0706050403020100 - txt = "01743607216033064144300561302505011422042100170340641402605011020034060120200300400400" - - NBKAssertDecodeText(T(x64: x64), 08, txt) - NBKAssertEncodeText(T(x64: x64), 08, true, String(txt.drop(while:{ $0 == "0" })).uppercased()) - NBKAssertEncodeText(T(x64: x64), 08, false, String(txt.drop(while:{ $0 == "0" })).lowercased()) - } - - func testDecodingAndEncodingRadix10() { - var txt: (String) - var x64: (UInt64, UInt64, UInt64, UInt64) - //=--------------------------------------= - x64.3 = 0xfffefdfcfbfaf9f8 - x64.2 = 0xf7f6f5f4f3f2f1f0 - x64.1 = 0xefeeedecebeae9e8 - x64.0 = 0xe7e6e5e4e3e2e1e0 - txt = "115790308505455567723526024286119531261069242336003260839703036409543150199264" - - NBKAssertDecodeText(T(x64: x64), 10, txt) - NBKAssertEncodeText(T(x64: x64), 10, true, String(txt.drop(while:{ $0 == "0" })).uppercased()) - NBKAssertEncodeText(T(x64: x64), 10, false, String(txt.drop(while:{ $0 == "0" })).lowercased()) - //=--------------------------------------= - x64.3 = 0x1f1e1d1c1b1a1918 - x64.2 = 0x1716151413121110 - x64.1 = 0x0f0e0d0c0b0a0908 - x64.0 = 0x0706050403020100 - txt = "014074904626401341155369551180448584754667373453244490859944217516317499064576" - - NBKAssertDecodeText(T(x64: x64), 10, txt) - NBKAssertEncodeText(T(x64: x64), 10, true, String(txt.drop(while:{ $0 == "0" })).uppercased()) - NBKAssertEncodeText(T(x64: x64), 10, false, String(txt.drop(while:{ $0 == "0" })).lowercased()) - } - - func testDecodingAndEncodingRadix16() { - var x64: (UInt64, UInt64, UInt64, UInt64) - var y64: (String, String, String, String) - //=--------------------------------------= - x64.3 = 0xfffefdfcfbfaf9f8; y64.3 = "fffefdfcfbfaf9f8" - x64.2 = 0xf7f6f5f4f3f2f1f0; y64.2 = "f7f6f5f4f3f2f1f0" - x64.1 = 0xefeeedecebeae9e8; y64.1 = "efeeedecebeae9e8" - x64.0 = 0xe7e6e5e4e3e2e1e0; y64.0 = "e7e6e5e4e3e2e1e0" - - NBKAssertDecodeText(T(x64: x64), 16, "\(y64.3)\(y64.2)\(y64.1)\(y64.0)") - NBKAssertEncodeText(T(x64: x64), 16, true, "\(y64.3)\(y64.2)\(y64.1)\(y64.0)".uppercased()) - NBKAssertEncodeText(T(x64: x64), 16, false, "\(y64.3)\(y64.2)\(y64.1)\(y64.0)".lowercased()) - //=--------------------------------------= - x64.3 = 0x1f1e1d1c1b1a1918; y64.3 = "1f1e1d1c1b1a1918" - x64.2 = 0x1716151413121110; y64.2 = "1716151413121110" - x64.1 = 0x0f0e0d0c0b0a0908; y64.1 = "0f0e0d0c0b0a0908" - x64.0 = 0x0706050403020100; y64.0 = "0706050403020100" - - NBKAssertDecodeText(T(x64: x64), 16, "\(y64.3)\(y64.2)\(y64.1)\(y64.0)") - NBKAssertEncodeText(T(x64: x64), 16, true, "\(y64.3)\(y64.2)\(y64.1)\(y64.0)".uppercased()) - NBKAssertEncodeText(T(x64: x64), 16, false, "\(y64.3)\(y64.2)\(y64.1)\(y64.0)".lowercased()) - } - - func testDecodingAndEncodingRadix36() { - var txt: (String) - var x64: (UInt64, UInt64, UInt64, UInt64) - //=--------------------------------------= - x64.3 = 0xfffefdfcfbfaf9f8 - x64.2 = 0xf7f6f5f4f3f2f1f0 - x64.1 = 0xefeeedecebeae9e8 - x64.0 = 0xe7e6e5e4e3e2e1e0 - txt = "6dp15j43ld5l8i7wvimlj7kxgbfxkxkgmo66lge382296ouqjk" - - NBKAssertDecodeText(T(x64: x64), 36, txt) - NBKAssertEncodeText(T(x64: x64), 36, true, String(txt.drop(while:{ $0 == "0" })).uppercased()) - NBKAssertEncodeText(T(x64: x64), 36, false, String(txt.drop(while:{ $0 == "0" })).lowercased()) - //=--------------------------------------= - x64.3 = 0x1f1e1d1c1b1a1918 - x64.2 = 0x1716151413121110 - x64.1 = 0x0f0e0d0c0b0a0908 - x64.0 = 0x0706050403020100 - txt = "0rx55jlhq7obx1pvd9861yo6c11bed0cd8s8wz2hpvczt00c1s" - - NBKAssertDecodeText(T(x64: x64), 36, txt) - NBKAssertEncodeText(T(x64: x64), 36, true, String(txt.drop(while:{ $0 == "0" })).uppercased()) - NBKAssertEncodeText(T(x64: x64), 36, false, String(txt.drop(while:{ $0 == "0" })).lowercased()) + } + + //=----= 03 =--------------------------------------------------------------= + + func testRadix03TopToBottom() { + self.radix = 03 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000000000000000000000000000001202200212221120001222202211110211\ + 2122212010220102122202121101120111112200201101101222110200202110\ + 0220201022101000210101202220120002101202101120201012012212012002 + """ + } + + func testRadix03BottomToTop() { + self.radix = 03 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0000000000000000000000000000000012210112211101210122010202201212\ + 2200112221212101221211222010022020100210220200100011100100222021\ + 2000121220012212111000111110212212201000011111112211120210102101 + """ + } + + //=----= 04 =--------------------------------------------------------------= + + func testRadix04TopToBottom() { + self.radix = 04 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 3333333233313330332333223321332033133312331133103303330233013300\ + 3233323232313230322332223221322032133212321132103203320232013200 + """ + } + + func testRadix04BottomToTop() { + self.radix = 04 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0133013201310130012301220121012001130112011101100103010201010100\ + 0033003200310030002300220021002000130012001100100003000200010000 + """ + } + + //=----= 05 =--------------------------------------------------------------= + + func testRadix05TopToBottom() { + self.radix = 05 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000000000000000012224200130200441041444042343242340402322434230\ + 2203100014323101131021202442142123441124102101232423332422334024 + """ + } + + func testRadix05BottomToTop() { + self.radix = 05 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0000000000000000000424043311031102404011202312202132022104340041\ + 4431003121344314114341012313341313423214420311244321214230031301 + """ + } + + //=----= 06 =--------------------------------------------------------------= + + func testRadix06TopToBottom() { + self.radix = 06 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000000000000000000000000000102141010531040333210533123011525130\ + 3433311132532415235332533224344010103324220312020213104050423132 + """ + } + + func testRadix06BottomToTop() { + self.radix = 06 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0000000000000000000000000000004353050531332542114015530141512113\ + 1210015440102001011522210020211244125255022541512055450000200144 + """ + } + + //=----= 07 =--------------------------------------------------------------= + + func testRadix07TopToBottom() { + self.radix = 07 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000000000000000000000000000000000001305333621612661215031353503\ + 1603616341660421351201115002605631306624232666655230226263060363 + """ + } + + func testRadix07BottomToTop() { + self.radix = 07 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0000000000000000000000000000000000000114142063044505436351120634\ + 3333263503132100565010106005630324255134635601621240633030645403 + """ + } + + //=----= 08 =--------------------------------------------------------------= + + func testRadix08TopToBottom() { + self.radix = 08 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000000000000000000000000000000000000000001777767737637376574770\ + 7577336575171762743703577356675472765351721637467136234370560740 + """ + } + + func testRadix08BottomToTop() { + self.radix = 08 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0000000000000000000000000000000000000000000174360721603306414430\ + 0561302505011422042100170340641402605011020034060120200300400400 + """ + } + + //=----= 09 =--------------------------------------------------------------= + + func testRadix09TopToBottom() { + self.radix = 09 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000000000000000000000000000000000000000000000052625846058684424\ + 7876381258254151448064135842067326638330711686502352346635185162 + """ + } + + func testRadix09BottomToTop() { + self.radix = 09 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0000000000000000000000000000000000000000000000005715741718122655\ + 8048777185486326632382030431086760556185430443785630144484523371 + """ + } + + //=----= 10 =--------------------------------------------------------------= + + func testRadix10TopToBottom() { + self.radix = 10 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000000000000000000000000000000000000000000000000011579030850545\ + 5567723526024286119531261069242336003260839703036409543150199264 + """ + } + + func testRadix10BottomToTop() { + self.radix = 10 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0000000000000000000000000000000000000000000000000001407490462640\ + 1341155369551180448584754667373453244490859944217516317499064576 + """ + } + + //=----= 11 =--------------------------------------------------------------= + + func testRadix11TopToBottom() { + self.radix = 11 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000000000000000000000000000000000000000000000000000010019774172\ + 675069499548a05a7794803603a4157366204225264092700a8157a30a948720 + """ + } + + func testRadix11BottomToTop() { + self.radix = 11 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0000000000000000000000000000000000000000000000000000001380227a9a\ + 3a453071005401517000a3500756239a46834284766655651370a28295109a06 + """ + } + + //=----= 12 =--------------------------------------------------------------= + + func testRadix12TopToBottom() { + self.radix = 12 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000000000000000000000000000000000000000000000000000000029231468\ + 41b6624b4657b76b759711256462675490811529026b8b03507956b900591aa8 + """ + } + + func testRadix12BottomToTop() { + self.radix = 12 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 000000000000000000000000000000000000000000000000000000000404b13b\ + 22595a847521b8ab337490660a0b7439b1495399a8b2918a9521301732309054 + """ + } + + //=----= 13 =--------------------------------------------------------------= + + func testRadix13TopToBottom() { + self.radix = 13 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000000000000000000000000000000000000000000000000000000000178a92\ + 980701228a277594134c94bb7165a938c70c03a705750115a339820831351c78 + """ + } + + func testRadix13BottomToTop() { + self.radix = 13 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 00000000000000000000000000000000000000000000000000000000000268a5\ + 1c5770b549c51487a17526804a0a14c0c44bbc981573456a275580297a4a7834 + """ + } + + //=----= 14 =--------------------------------------------------------------= + + func testRadix14TopToBottom() { + self.radix = 14 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000000000000000000000000000000000000000000000000000000000001c38\ + 14cbd353812dca285cc376972998797340345da539017abd8236000c88ca00da + """ + } + + func testRadix14BottomToTop() { + self.radix = 14 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0000000000000000000000000000000000000000000000000000000000000329\ + 76a45325cd6dda6ac91cb8c9bccbbc61488833c2225a774c2da97ab4d4565d3a + """ + } + + //=----= 15 =--------------------------------------------------------------= + + func testRadix15TopToBottom() { + self.radix = 15 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000000000000000000000000000000000000000000000000000000000000042\ + 314e1223518107b1362e160a5ad29226b4e3e2d35ea57996aaa3242db02966ae + """ + } + + func testRadix15BottomToTop() { + self.radix = 15 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0000000000000000000000000000000000000000000000000000000000000007\ + 864d3605e05bd91d94b651ccc4e3078d6edc902745e03953a310b0de5c602701 + """ + } + + //=----= 16 =--------------------------------------------------------------= + + func testRadix16TopToBottom() { + self.radix = 16 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e0 + """ + } + + func testRadix16BottomToTop() { + self.radix = 16 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100 + """ + } + + //=----= 17 =--------------------------------------------------------------= + + func testRadix17TopToBottom() { + self.radix = 17 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 05g7d81gc01cdbf42565444eaa12342c35gd9f66bbg36c8d8841baa7a8faab0e + """ + } + + func testRadix17BottomToTop() { + self.radix = 17 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 00c5b2gcge3c140g4d527274dgd5cg7g58babg3e21bg76739a559151527ce653 + """ + } + + //=----= 18 =--------------------------------------------------------------= + + func testRadix18TopToBottom() { + self.radix = 18 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0031fhf5dce9fgc12bg164e9h35028896f83ddhh8be5286c3e9h17360bg1bg32 + """ + } + + func testRadix18BottomToTop() { + self.radix = 18 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0006e51f0da7284a3bb14747c33cgb1hfa3120c549aec7hh58g39hg075a02c3a + """ + } + + //=----= 19 =--------------------------------------------------------------= + + func testRadix19TopToBottom() { + self.radix = 19 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 000237ibab6cg652id30fgh76hdai93dhfh7dhagfdc5eb7f782c55d551ed74g6 + """ + } + + func testRadix19BottomToTop() { + self.radix = 19 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 000050cae6cb5210060eg1g2iicc8e689a04g25829g2f5bc8c84ea4a8a1348f4 + """ + } + + //=----= 20 =--------------------------------------------------------------= + + func testRadix20TopToBottom() { + self.radix = 20 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 000020392d6ac9d1jd12d3a88c61i7ba748483ai05hf66c6a7g42977fbe8ei34 + """ + } + + func testRadix20BottomToTop() { + self.radix = 20 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 000004hd5e33e5189jajhc248c2a513ae74fba267d1b3d1743i8ebgb30i9318g + """ + } + + //=----= 21 =--------------------------------------------------------------= + + func testRadix21TopToBottom() { + self.radix = 21 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000027gdj7593kjg0f1c5cga4aca1e1d5f08h72cebhcbc1c6cek06cf13eaddh + """ + } + + func testRadix21BottomToTop() { + self.radix = 21 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0000006124cec92463a07f87dgg069g06715hcg4j03fha2f1gafce80g895g09a + """ + } + + //=----= 22 =--------------------------------------------------------------= + + func testRadix22TopToBottom() { + self.radix = 22 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000003b5jk54f19beiidebchgec3ffc28aggdd74h75ijdc00i4ea0ji14954c0 + """ + } + + func testRadix22BottomToTop() { + self.radix = 22 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 000000098djlg8ll6ge66j798kd129gf43e7c6586a31h5a25adg2l78kj3a82b6 + """ + } + + //=----= 23 =--------------------------------------------------------------= + + func testRadix23TopToBottom() { + self.radix = 23 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 000000069a79baglcjbdblbk5111bb46b66g2b7a2f596763kmm7c3hbl336kl14 + """ + } + + func testRadix23BottomToTop() { + self.radix = 23 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 00000000hl580j6lii99g9c5137ji22ab5i41mba3lh6091cakd4h6llil689h12 + """ + } + + //=----= 24 =--------------------------------------------------------------= + + func testRadix24TopToBottom() { + self.radix = 24 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 00000000e4eikjgk76jj7i2fbn6ihk3ngef39fb00gjl3086em4k7g3ag5647hh8 + """ + } + + func testRadix24BottomToTop() { + self.radix = 24 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 000000001h9gbi9kc8ig99kj5lil4in9d6e81la5d0h872fff899ebj57j88732g + """ + } + + //=----= 25 =--------------------------------------------------------------= + + func testRadix25TopToBottom() { + self.radix = 25 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 000000001cea1fa4l49o4dnedkkdcnmfc3509hg185baem9bdo6e5b1dediecike + """ + } + + func testRadix25BottomToTop() { + self.radix = 25 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0000000004e4i6362kk6ad7abh2b4j0log0gbjn96nl1d8j88mh9m36enbbmf381 + """ + } + + //=----= 26 =--------------------------------------------------------------= + + func testRadix26TopToBottom() { + self.radix = 26 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000000004dd8f12of8578gn3cho4kjg1nm4ck49ihk7nahjpeie4d78426fjja8 + """ + } + + func testRadix26BottomToTop() { + self.radix = 26 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0000000000e7a4822n1867n87cpm330nai4o7gj05b5j013bb0in29cncoodh584 + """ + } + + //=----= 27 =--------------------------------------------------------------= + + func testRadix27TopToBottom() { + self.radix = 27 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000000000fo7qe0hopd7gqfbj7q7m4jdh2445pb279oj8a0lakof2akafj55n52 + """ + } + + func testRadix27BottomToTop() { + self.radix = 27 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 00000000001p4pcg5j6ogq1hng5neo9oj2bk10d12on0go5nd0dcnnj04demflba + """ + } + + //=----= 28 =--------------------------------------------------------------= + + func testRadix28TopToBottom() { + self.radix = 28 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 000000000028lp360pqr9fgjmgalj15e5kknmk8pd61irgj23bbe6nbafahp3e6o + """ + } + + func testRadix28BottomToTop() { + self.radix = 28 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 000000000007odiqi7ipkbell34qeml609e642lhrao5n03422ik497coam17kmo + """ + } + + //=----= 29 =--------------------------------------------------------------= + + func testRadix29TopToBottom() { + self.radix = 29 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 00000000000acrhqlapaaob766is1eng6erp522m0f5opigage3d3j4k7f9n8ff2 + """ + } + + func testRadix29BottomToTop() { + self.radix = 29 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0000000000017nr4pcg1heg13dh8cgggmn4q34frqm65gn8ec0j45591bmqfhffb + """ + } + + //=----= 30 =--------------------------------------------------------------= + + func testRadix30TopToBottom() { + self.radix = 30 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 000000000001nmr6nq4fe87dse4p4i0ama7co4moqch8081liop9spg2kl9rn95e + """ + } + + func testRadix30BottomToTop() { + self.radix = 30 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0000000000006g1ldfsednredtimcop3b5l3q70e4kitjnhrn4eql74ecaf5j1mg + """ + } + + //=----= 31 =--------------------------------------------------------------= + + func testRadix31TopToBottom() { + self.radix = 31 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 000000000000a30ts5ohp5e917o3nehp8urue2rb4e97icid1me5tcmpil25fi6m + """ + } + + func testRadix31BottomToTop() { + self.radix = 31 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 000000000000171hhf8063e3r4a99sra00a157pihstia75dmk5kfae5nnn9ab6l + """ + } + + //=----= 32 =--------------------------------------------------------------= + + func testRadix32TopToBottom() { + self.radix = 32 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000000000001vvuvnufnunpv3rvdtfkufpf3s7ftrmupqvat7kefpn5sjhu5of0 + """ + } + + func testRadix32BottomToTop() { + self.radix = 32 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 00000000000007ou3ke1m6gp30bhc58k2c91240f1o6go2oa1440e1g50g1g4080 + """ + } + + //=----= 33 =--------------------------------------------------------------= + + func testRadix33TopToBottom() { + self.radix = 33 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 0000000000000dodf9g17rn5pvw3et1k184sgnb11u6u7uhk2n9b3bhtfwrh14fb + """ + } + + func testRadix33BottomToTop() { + self.radix = 33 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 00000000000001m3p6weqc5jk0wsb37sv08ileepww3jad5cr0cfhd0g1aq8in3s + """ + } + + //=----= 34 =--------------------------------------------------------------= + + func testRadix34TopToBottom() { + self.radix = 34 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 00000000000003304fs1ae3ixjsrahw1k6lt33dlup2jc54b1p3xxaghpss3swhe + """ + } + + func testRadix34BottomToTop() { + self.radix = 34 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 00000000000000cpwunuqgcm028uqxuqmjst7gk65egpsowcgixwuci6x899aa2k + """ + } + + //=----= 35 =--------------------------------------------------------------= + + func testRadix35TopToBottom() { + self.radix = 35 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 00000000000000pcyhqj7yk3vq8j4l4vfa7wes91wah4p1y3op2k48s4pv0y189o + """ + } + + func testRadix35BottomToTop() { + self.radix = 35 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 0000000000000032wujn2mg481jyhidxmv5271ucr21qfj9jdvqm429mwneu6b2v + """ + } + + //=----= 36 =--------------------------------------------------------------= + + func testRadix36TopToBottom() { + self.radix = 36 + self.x64.3 = 0xfffefdfcfbfaf9f8 + self.x64.2 = 0xf7f6f5f4f3f2f1f0 + self.x64.1 = 0xefeeedecebeae9e8 + self.x64.0 = 0xe7e6e5e4e3e2e1e0 + self.txt = """ + 000000000000006dp15j43ld5l8i7wvimlj7kxgbfxkxkgmo66lge382296ouqjk + """ + } + + func testRadix36BottomToTop() { + self.radix = 36 + self.x64.3 = 0x1f1e1d1c1b1a1918 + self.x64.2 = 0x1716151413121110 + self.x64.1 = 0x0f0e0d0c0b0a0908 + self.x64.0 = 0x0706050403020100 + self.txt = """ + 000000000000000rx55jlhq7obx1pvd9861yo6c11bed0cd8s8wz2hpvczt00c1s + """ } } From ef9e8eb5c41b457769603048fd38bc01bcd4f30f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Fri, 8 Sep 2023 16:44:33 +0200 Subject: [PATCH 109/111] Cleanup. --- .../NBKDoubleWidth+Text.swift | 219 +++++++++--------- 1 file changed, 111 insertions(+), 108 deletions(-) diff --git a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Text.swift b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Text.swift index f5d41ba1..4dbf53f6 100644 --- a/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Text.swift +++ b/Tests/NBKDoubleWidthKitTests/NBKDoubleWidth+Text.swift @@ -473,10 +473,10 @@ final class NBKDoubleWidthTestsOnTextAsUInt256: XCTestCase { } //*============================================================================* -// MARK: * NBK x Double Width x Text x Other Cases x UInt256 +// MARK: * NBK x Double Width x Text x For Each Radix x UInt256 //*============================================================================* -final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { +final class NBKDoubleWidthTestsOnTextForEachRadixAsUInt256: XCTestCase { typealias T = UInt256 @@ -503,9 +503,12 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { override func tearDown() { let decoded = T(x64: self.x64) - var encoded = String(self.txt.drop(while:{ $0 == "0" })) - if encoded.isEmpty { encoded += "0" } + var encoded = String(self.txt.drop{ $0 == "0" }) + if encoded.isEmpty { + encoded.append(contentsOf: self.txt.suffix(1)) + } + NBKAssertDecodeText(decoded, self.radix, txt) NBKAssertDecodeText(decoded, self.radix, encoded) NBKAssertEncodeText(decoded, self.radix, true, encoded.uppercased()) NBKAssertEncodeText(decoded, self.radix, false, encoded.lowercased()) @@ -515,7 +518,7 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { // MARK: Tests //=------------------------------------------------------------------------= - func testRadix02TopToBottom() { + func testRadix02Top() { self.radix = 02 self.x64.3 = 0xfffefdfcfbfaf9f8 self.x64.2 = 0xf7f6f5f4f3f2f1f0 @@ -529,7 +532,7 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - func testRadix02BottomToTop() { + func testRadix02Bottom() { self.radix = 02 self.x64.3 = 0x1f1e1d1c1b1a1918 self.x64.2 = 0x1716151413121110 @@ -543,9 +546,9 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - //=----= 03 =--------------------------------------------------------------= + //=----( 03 )--------------------------------------------------------------= - func testRadix03TopToBottom() { + func testRadix03Top() { self.radix = 03 self.x64.3 = 0xfffefdfcfbfaf9f8 self.x64.2 = 0xf7f6f5f4f3f2f1f0 @@ -558,7 +561,7 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - func testRadix03BottomToTop() { + func testRadix03Bottom() { self.radix = 03 self.x64.3 = 0x1f1e1d1c1b1a1918 self.x64.2 = 0x1716151413121110 @@ -571,9 +574,9 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - //=----= 04 =--------------------------------------------------------------= + //=----( 04 )--------------------------------------------------------------= - func testRadix04TopToBottom() { + func testRadix04Top() { self.radix = 04 self.x64.3 = 0xfffefdfcfbfaf9f8 self.x64.2 = 0xf7f6f5f4f3f2f1f0 @@ -585,7 +588,7 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - func testRadix04BottomToTop() { + func testRadix04Bottom() { self.radix = 04 self.x64.3 = 0x1f1e1d1c1b1a1918 self.x64.2 = 0x1716151413121110 @@ -597,9 +600,9 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - //=----= 05 =--------------------------------------------------------------= + //=----( 05 )--------------------------------------------------------------= - func testRadix05TopToBottom() { + func testRadix05Top() { self.radix = 05 self.x64.3 = 0xfffefdfcfbfaf9f8 self.x64.2 = 0xf7f6f5f4f3f2f1f0 @@ -611,7 +614,7 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - func testRadix05BottomToTop() { + func testRadix05Bottom() { self.radix = 05 self.x64.3 = 0x1f1e1d1c1b1a1918 self.x64.2 = 0x1716151413121110 @@ -623,9 +626,9 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - //=----= 06 =--------------------------------------------------------------= + //=----( 06 )--------------------------------------------------------------= - func testRadix06TopToBottom() { + func testRadix06Top() { self.radix = 06 self.x64.3 = 0xfffefdfcfbfaf9f8 self.x64.2 = 0xf7f6f5f4f3f2f1f0 @@ -637,7 +640,7 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - func testRadix06BottomToTop() { + func testRadix06Bottom() { self.radix = 06 self.x64.3 = 0x1f1e1d1c1b1a1918 self.x64.2 = 0x1716151413121110 @@ -649,9 +652,9 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - //=----= 07 =--------------------------------------------------------------= + //=----( 07 )--------------------------------------------------------------= - func testRadix07TopToBottom() { + func testRadix07Top() { self.radix = 07 self.x64.3 = 0xfffefdfcfbfaf9f8 self.x64.2 = 0xf7f6f5f4f3f2f1f0 @@ -663,7 +666,7 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - func testRadix07BottomToTop() { + func testRadix07Bottom() { self.radix = 07 self.x64.3 = 0x1f1e1d1c1b1a1918 self.x64.2 = 0x1716151413121110 @@ -675,9 +678,9 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - //=----= 08 =--------------------------------------------------------------= + //=----( 08 )--------------------------------------------------------------= - func testRadix08TopToBottom() { + func testRadix08Top() { self.radix = 08 self.x64.3 = 0xfffefdfcfbfaf9f8 self.x64.2 = 0xf7f6f5f4f3f2f1f0 @@ -689,7 +692,7 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - func testRadix08BottomToTop() { + func testRadix08Bottom() { self.radix = 08 self.x64.3 = 0x1f1e1d1c1b1a1918 self.x64.2 = 0x1716151413121110 @@ -701,9 +704,9 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - //=----= 09 =--------------------------------------------------------------= + //=----( 09 )--------------------------------------------------------------= - func testRadix09TopToBottom() { + func testRadix09Top() { self.radix = 09 self.x64.3 = 0xfffefdfcfbfaf9f8 self.x64.2 = 0xf7f6f5f4f3f2f1f0 @@ -715,7 +718,7 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - func testRadix09BottomToTop() { + func testRadix09Bottom() { self.radix = 09 self.x64.3 = 0x1f1e1d1c1b1a1918 self.x64.2 = 0x1716151413121110 @@ -727,9 +730,9 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - //=----= 10 =--------------------------------------------------------------= + //=----( 10 )--------------------------------------------------------------= - func testRadix10TopToBottom() { + func testRadix10Top() { self.radix = 10 self.x64.3 = 0xfffefdfcfbfaf9f8 self.x64.2 = 0xf7f6f5f4f3f2f1f0 @@ -741,7 +744,7 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - func testRadix10BottomToTop() { + func testRadix10Bottom() { self.radix = 10 self.x64.3 = 0x1f1e1d1c1b1a1918 self.x64.2 = 0x1716151413121110 @@ -753,9 +756,9 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - //=----= 11 =--------------------------------------------------------------= + //=----( 11 )--------------------------------------------------------------= - func testRadix11TopToBottom() { + func testRadix11Top() { self.radix = 11 self.x64.3 = 0xfffefdfcfbfaf9f8 self.x64.2 = 0xf7f6f5f4f3f2f1f0 @@ -767,7 +770,7 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - func testRadix11BottomToTop() { + func testRadix11Bottom() { self.radix = 11 self.x64.3 = 0x1f1e1d1c1b1a1918 self.x64.2 = 0x1716151413121110 @@ -779,9 +782,9 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - //=----= 12 =--------------------------------------------------------------= + //=----( 12 )--------------------------------------------------------------= - func testRadix12TopToBottom() { + func testRadix12Top() { self.radix = 12 self.x64.3 = 0xfffefdfcfbfaf9f8 self.x64.2 = 0xf7f6f5f4f3f2f1f0 @@ -793,7 +796,7 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - func testRadix12BottomToTop() { + func testRadix12Bottom() { self.radix = 12 self.x64.3 = 0x1f1e1d1c1b1a1918 self.x64.2 = 0x1716151413121110 @@ -805,9 +808,9 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - //=----= 13 =--------------------------------------------------------------= + //=----( 13 )--------------------------------------------------------------= - func testRadix13TopToBottom() { + func testRadix13Top() { self.radix = 13 self.x64.3 = 0xfffefdfcfbfaf9f8 self.x64.2 = 0xf7f6f5f4f3f2f1f0 @@ -819,7 +822,7 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - func testRadix13BottomToTop() { + func testRadix13Bottom() { self.radix = 13 self.x64.3 = 0x1f1e1d1c1b1a1918 self.x64.2 = 0x1716151413121110 @@ -831,9 +834,9 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - //=----= 14 =--------------------------------------------------------------= + //=----( 14 )--------------------------------------------------------------= - func testRadix14TopToBottom() { + func testRadix14Top() { self.radix = 14 self.x64.3 = 0xfffefdfcfbfaf9f8 self.x64.2 = 0xf7f6f5f4f3f2f1f0 @@ -845,7 +848,7 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - func testRadix14BottomToTop() { + func testRadix14Bottom() { self.radix = 14 self.x64.3 = 0x1f1e1d1c1b1a1918 self.x64.2 = 0x1716151413121110 @@ -857,9 +860,9 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - //=----= 15 =--------------------------------------------------------------= + //=----( 15 )--------------------------------------------------------------= - func testRadix15TopToBottom() { + func testRadix15Top() { self.radix = 15 self.x64.3 = 0xfffefdfcfbfaf9f8 self.x64.2 = 0xf7f6f5f4f3f2f1f0 @@ -871,7 +874,7 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - func testRadix15BottomToTop() { + func testRadix15Bottom() { self.radix = 15 self.x64.3 = 0x1f1e1d1c1b1a1918 self.x64.2 = 0x1716151413121110 @@ -883,9 +886,9 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - //=----= 16 =--------------------------------------------------------------= + //=----( 16 )--------------------------------------------------------------= - func testRadix16TopToBottom() { + func testRadix16Top() { self.radix = 16 self.x64.3 = 0xfffefdfcfbfaf9f8 self.x64.2 = 0xf7f6f5f4f3f2f1f0 @@ -896,7 +899,7 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - func testRadix16BottomToTop() { + func testRadix16Bottom() { self.radix = 16 self.x64.3 = 0x1f1e1d1c1b1a1918 self.x64.2 = 0x1716151413121110 @@ -907,9 +910,9 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - //=----= 17 =--------------------------------------------------------------= + //=----( 17 )--------------------------------------------------------------= - func testRadix17TopToBottom() { + func testRadix17Top() { self.radix = 17 self.x64.3 = 0xfffefdfcfbfaf9f8 self.x64.2 = 0xf7f6f5f4f3f2f1f0 @@ -920,7 +923,7 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - func testRadix17BottomToTop() { + func testRadix17Bottom() { self.radix = 17 self.x64.3 = 0x1f1e1d1c1b1a1918 self.x64.2 = 0x1716151413121110 @@ -931,9 +934,9 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - //=----= 18 =--------------------------------------------------------------= + //=----( 18 )--------------------------------------------------------------= - func testRadix18TopToBottom() { + func testRadix18Top() { self.radix = 18 self.x64.3 = 0xfffefdfcfbfaf9f8 self.x64.2 = 0xf7f6f5f4f3f2f1f0 @@ -944,7 +947,7 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - func testRadix18BottomToTop() { + func testRadix18Bottom() { self.radix = 18 self.x64.3 = 0x1f1e1d1c1b1a1918 self.x64.2 = 0x1716151413121110 @@ -955,9 +958,9 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - //=----= 19 =--------------------------------------------------------------= + //=----( 19 )--------------------------------------------------------------= - func testRadix19TopToBottom() { + func testRadix19Top() { self.radix = 19 self.x64.3 = 0xfffefdfcfbfaf9f8 self.x64.2 = 0xf7f6f5f4f3f2f1f0 @@ -968,7 +971,7 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - func testRadix19BottomToTop() { + func testRadix19Bottom() { self.radix = 19 self.x64.3 = 0x1f1e1d1c1b1a1918 self.x64.2 = 0x1716151413121110 @@ -979,9 +982,9 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - //=----= 20 =--------------------------------------------------------------= + //=----( 20 )--------------------------------------------------------------= - func testRadix20TopToBottom() { + func testRadix20Top() { self.radix = 20 self.x64.3 = 0xfffefdfcfbfaf9f8 self.x64.2 = 0xf7f6f5f4f3f2f1f0 @@ -992,7 +995,7 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - func testRadix20BottomToTop() { + func testRadix20Bottom() { self.radix = 20 self.x64.3 = 0x1f1e1d1c1b1a1918 self.x64.2 = 0x1716151413121110 @@ -1003,9 +1006,9 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - //=----= 21 =--------------------------------------------------------------= + //=----( 21 )--------------------------------------------------------------= - func testRadix21TopToBottom() { + func testRadix21Top() { self.radix = 21 self.x64.3 = 0xfffefdfcfbfaf9f8 self.x64.2 = 0xf7f6f5f4f3f2f1f0 @@ -1016,7 +1019,7 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - func testRadix21BottomToTop() { + func testRadix21Bottom() { self.radix = 21 self.x64.3 = 0x1f1e1d1c1b1a1918 self.x64.2 = 0x1716151413121110 @@ -1027,9 +1030,9 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - //=----= 22 =--------------------------------------------------------------= + //=----( 22 )--------------------------------------------------------------= - func testRadix22TopToBottom() { + func testRadix22Top() { self.radix = 22 self.x64.3 = 0xfffefdfcfbfaf9f8 self.x64.2 = 0xf7f6f5f4f3f2f1f0 @@ -1040,7 +1043,7 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - func testRadix22BottomToTop() { + func testRadix22Bottom() { self.radix = 22 self.x64.3 = 0x1f1e1d1c1b1a1918 self.x64.2 = 0x1716151413121110 @@ -1051,9 +1054,9 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - //=----= 23 =--------------------------------------------------------------= + //=----( 23 )--------------------------------------------------------------= - func testRadix23TopToBottom() { + func testRadix23Top() { self.radix = 23 self.x64.3 = 0xfffefdfcfbfaf9f8 self.x64.2 = 0xf7f6f5f4f3f2f1f0 @@ -1064,7 +1067,7 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - func testRadix23BottomToTop() { + func testRadix23Bottom() { self.radix = 23 self.x64.3 = 0x1f1e1d1c1b1a1918 self.x64.2 = 0x1716151413121110 @@ -1075,9 +1078,9 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - //=----= 24 =--------------------------------------------------------------= + //=----( 24 )--------------------------------------------------------------= - func testRadix24TopToBottom() { + func testRadix24Top() { self.radix = 24 self.x64.3 = 0xfffefdfcfbfaf9f8 self.x64.2 = 0xf7f6f5f4f3f2f1f0 @@ -1088,7 +1091,7 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - func testRadix24BottomToTop() { + func testRadix24Bottom() { self.radix = 24 self.x64.3 = 0x1f1e1d1c1b1a1918 self.x64.2 = 0x1716151413121110 @@ -1099,9 +1102,9 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - //=----= 25 =--------------------------------------------------------------= + //=----( 25 )--------------------------------------------------------------= - func testRadix25TopToBottom() { + func testRadix25Top() { self.radix = 25 self.x64.3 = 0xfffefdfcfbfaf9f8 self.x64.2 = 0xf7f6f5f4f3f2f1f0 @@ -1112,7 +1115,7 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - func testRadix25BottomToTop() { + func testRadix25Bottom() { self.radix = 25 self.x64.3 = 0x1f1e1d1c1b1a1918 self.x64.2 = 0x1716151413121110 @@ -1123,9 +1126,9 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - //=----= 26 =--------------------------------------------------------------= + //=----( 26 )--------------------------------------------------------------= - func testRadix26TopToBottom() { + func testRadix26Top() { self.radix = 26 self.x64.3 = 0xfffefdfcfbfaf9f8 self.x64.2 = 0xf7f6f5f4f3f2f1f0 @@ -1136,7 +1139,7 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - func testRadix26BottomToTop() { + func testRadix26Bottom() { self.radix = 26 self.x64.3 = 0x1f1e1d1c1b1a1918 self.x64.2 = 0x1716151413121110 @@ -1147,9 +1150,9 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - //=----= 27 =--------------------------------------------------------------= + //=----( 27 )--------------------------------------------------------------= - func testRadix27TopToBottom() { + func testRadix27Top() { self.radix = 27 self.x64.3 = 0xfffefdfcfbfaf9f8 self.x64.2 = 0xf7f6f5f4f3f2f1f0 @@ -1160,7 +1163,7 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - func testRadix27BottomToTop() { + func testRadix27Bottom() { self.radix = 27 self.x64.3 = 0x1f1e1d1c1b1a1918 self.x64.2 = 0x1716151413121110 @@ -1171,9 +1174,9 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - //=----= 28 =--------------------------------------------------------------= + //=----( 28 )--------------------------------------------------------------= - func testRadix28TopToBottom() { + func testRadix28Top() { self.radix = 28 self.x64.3 = 0xfffefdfcfbfaf9f8 self.x64.2 = 0xf7f6f5f4f3f2f1f0 @@ -1184,7 +1187,7 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - func testRadix28BottomToTop() { + func testRadix28Bottom() { self.radix = 28 self.x64.3 = 0x1f1e1d1c1b1a1918 self.x64.2 = 0x1716151413121110 @@ -1195,9 +1198,9 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - //=----= 29 =--------------------------------------------------------------= + //=----( 29 )--------------------------------------------------------------= - func testRadix29TopToBottom() { + func testRadix29Top() { self.radix = 29 self.x64.3 = 0xfffefdfcfbfaf9f8 self.x64.2 = 0xf7f6f5f4f3f2f1f0 @@ -1208,7 +1211,7 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - func testRadix29BottomToTop() { + func testRadix29Bottom() { self.radix = 29 self.x64.3 = 0x1f1e1d1c1b1a1918 self.x64.2 = 0x1716151413121110 @@ -1219,9 +1222,9 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - //=----= 30 =--------------------------------------------------------------= + //=----( 30 )--------------------------------------------------------------= - func testRadix30TopToBottom() { + func testRadix30Top() { self.radix = 30 self.x64.3 = 0xfffefdfcfbfaf9f8 self.x64.2 = 0xf7f6f5f4f3f2f1f0 @@ -1232,7 +1235,7 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - func testRadix30BottomToTop() { + func testRadix30Bottom() { self.radix = 30 self.x64.3 = 0x1f1e1d1c1b1a1918 self.x64.2 = 0x1716151413121110 @@ -1243,9 +1246,9 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - //=----= 31 =--------------------------------------------------------------= + //=----( 31 )--------------------------------------------------------------= - func testRadix31TopToBottom() { + func testRadix31Top() { self.radix = 31 self.x64.3 = 0xfffefdfcfbfaf9f8 self.x64.2 = 0xf7f6f5f4f3f2f1f0 @@ -1256,7 +1259,7 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - func testRadix31BottomToTop() { + func testRadix31Bottom() { self.radix = 31 self.x64.3 = 0x1f1e1d1c1b1a1918 self.x64.2 = 0x1716151413121110 @@ -1267,9 +1270,9 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - //=----= 32 =--------------------------------------------------------------= + //=----( 32 )--------------------------------------------------------------= - func testRadix32TopToBottom() { + func testRadix32Top() { self.radix = 32 self.x64.3 = 0xfffefdfcfbfaf9f8 self.x64.2 = 0xf7f6f5f4f3f2f1f0 @@ -1280,7 +1283,7 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - func testRadix32BottomToTop() { + func testRadix32Bottom() { self.radix = 32 self.x64.3 = 0x1f1e1d1c1b1a1918 self.x64.2 = 0x1716151413121110 @@ -1291,9 +1294,9 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - //=----= 33 =--------------------------------------------------------------= + //=----( 33 )--------------------------------------------------------------= - func testRadix33TopToBottom() { + func testRadix33Top() { self.radix = 33 self.x64.3 = 0xfffefdfcfbfaf9f8 self.x64.2 = 0xf7f6f5f4f3f2f1f0 @@ -1304,7 +1307,7 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - func testRadix33BottomToTop() { + func testRadix33Bottom() { self.radix = 33 self.x64.3 = 0x1f1e1d1c1b1a1918 self.x64.2 = 0x1716151413121110 @@ -1315,9 +1318,9 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - //=----= 34 =--------------------------------------------------------------= + //=----( 34 )--------------------------------------------------------------= - func testRadix34TopToBottom() { + func testRadix34Top() { self.radix = 34 self.x64.3 = 0xfffefdfcfbfaf9f8 self.x64.2 = 0xf7f6f5f4f3f2f1f0 @@ -1328,7 +1331,7 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - func testRadix34BottomToTop() { + func testRadix34Bottom() { self.radix = 34 self.x64.3 = 0x1f1e1d1c1b1a1918 self.x64.2 = 0x1716151413121110 @@ -1339,9 +1342,9 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - //=----= 35 =--------------------------------------------------------------= + //=----( 35 )--------------------------------------------------------------= - func testRadix35TopToBottom() { + func testRadix35Top() { self.radix = 35 self.x64.3 = 0xfffefdfcfbfaf9f8 self.x64.2 = 0xf7f6f5f4f3f2f1f0 @@ -1352,7 +1355,7 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - func testRadix35BottomToTop() { + func testRadix35Bottom() { self.radix = 35 self.x64.3 = 0x1f1e1d1c1b1a1918 self.x64.2 = 0x1716151413121110 @@ -1363,9 +1366,9 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - //=----= 36 =--------------------------------------------------------------= + //=----( 36 )--------------------------------------------------------------= - func testRadix36TopToBottom() { + func testRadix36Top() { self.radix = 36 self.x64.3 = 0xfffefdfcfbfaf9f8 self.x64.2 = 0xf7f6f5f4f3f2f1f0 @@ -1376,7 +1379,7 @@ final class NBKDoubleWidthTestsOnTextByOtherCasesAsUInt256: XCTestCase { """ } - func testRadix36BottomToTop() { + func testRadix36Bottom() { self.radix = 36 self.x64.3 = 0x1f1e1d1c1b1a1918 self.x64.2 = 0x1716151413121110 From f9f604275e70048f04b77d3a6ef9b96d65cb8537 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sat, 9 Sep 2023 08:19:08 +0200 Subject: [PATCH 110/111] [NBKCoreKit] Sendable (#72) (#73) (#74). --- Sources/NBKCoreKit/Models/NBKChunkedInt.swift | 6 ++++++ Sources/NBKCoreKit/Models/NBKEndianness.swift | 2 +- Sources/NBKCoreKit/Models/NBKTwinHeaded.swift | 6 ++++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/Sources/NBKCoreKit/Models/NBKChunkedInt.swift b/Sources/NBKCoreKit/Models/NBKChunkedInt.swift index 01cf63a9..3190b95a 100644 --- a/Sources/NBKCoreKit/Models/NBKChunkedInt.swift +++ b/Sources/NBKCoreKit/Models/NBKChunkedInt.swift @@ -110,6 +110,12 @@ Element: NBKCoreInteger, Base: RandomAccessCollection, Base.Element: NBKCoreInte } } +//=----------------------------------------------------------------------------= +// MARK: + Sendable +//=----------------------------------------------------------------------------= + +extension NBKChunkedInt: Sendable where Base: Sendable { } + //=----------------------------------------------------------------------------= // MARK: + Major //=----------------------------------------------------------------------------= diff --git a/Sources/NBKCoreKit/Models/NBKEndianness.swift b/Sources/NBKCoreKit/Models/NBKEndianness.swift index b1cd5458..1af379a3 100644 --- a/Sources/NBKCoreKit/Models/NBKEndianness.swift +++ b/Sources/NBKCoreKit/Models/NBKEndianness.swift @@ -19,7 +19,7 @@ /// can express the difference, but dynamic solutions are often viable. This type /// encurages the latter. /// -@frozen public enum NBKEndianness: Hashable { +@frozen public enum NBKEndianness: Hashable, Sendable { //=------------------------------------------------------------------------= // MARK: State diff --git a/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift b/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift index 959f9013..0357f8bf 100644 --- a/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift +++ b/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift @@ -177,6 +177,12 @@ } } +//=----------------------------------------------------------------------------= +// MARK: + Sendable +//=----------------------------------------------------------------------------= + +extension NBKTwinHeaded: Sendable where Base: Sendable, Base.Index: Sendable { } + //=----------------------------------------------------------------------------= // MARK: + Collection //=----------------------------------------------------------------------------= From 98a69b0effb31cf48b57718e5bae21daf9e15691 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Sat, 9 Sep 2023 08:19:38 +0200 Subject: [PATCH 111/111] [NBKCoreKit] Cleanup. --- Sources/NBKCoreKit/Models/NBKTwinHeaded.swift | 17 ++++++++++++++--- .../Private/NBK+Limbs+Subtraction.swift | 6 ++++-- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift b/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift index 0357f8bf..c08d0db9 100644 --- a/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift +++ b/Sources/NBKCoreKit/Models/NBKTwinHeaded.swift @@ -130,8 +130,8 @@ /// Returns the base collection's corresponding subscript index. /// /// ``` - /// front-to-back: base.index(base.startIndex, offsetBy: index + 0) - /// back-to-front: base.index(base.endIndex, offsetBy: -index + -1) + /// front-to-back: base.index(base.startIndex, offsetBy: index) + /// back-to-front: base.index(base.endIndex, offsetBy: ~index) /// ``` /// /// - Parameter index: `self.startIndex <= index < self.endIndex` @@ -259,7 +259,7 @@ extension NBKTwinHeaded: MutableCollection where Base: MutableCollection { } //=----------------------------------------------------------------------------= -// MARK: + Sub Sequence +// MARK: + where Base is Unsafe Buffer Pointer //=----------------------------------------------------------------------------= extension NBKTwinHeaded { @@ -274,6 +274,17 @@ extension NBKTwinHeaded { let base = Base(rebasing: subsequence.base.base[subsequence.base.baseIndices(subindices)]) self.init(base, reversed: subsequence.base.isBackToFront) } +} + +//=----------------------------------------------------------------------------= +// MARK: + where Base is Unsafe Mutable Buffer Pointer +//=----------------------------------------------------------------------------= + +extension NBKTwinHeaded { + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= /// Creates a collection with the same data and direction as the given subsequence. @inlinable public init(rebasing subsequence: SubSequence) where Base == UnsafeMutableBufferPointer { diff --git a/Sources/NBKCoreKit/Private/NBK+Limbs+Subtraction.swift b/Sources/NBKCoreKit/Private/NBK+Limbs+Subtraction.swift index e5c72905..c3bb39d1 100644 --- a/Sources/NBKCoreKit/Private/NBK+Limbs+Subtraction.swift +++ b/Sources/NBKCoreKit/Private/NBK+Limbs+Subtraction.swift @@ -271,7 +271,8 @@ extension NBK { /// - Returns: An overflow indicator and its index in `pointee`. /// @_transparent @discardableResult public static func decrementSufficientUnsignedInteger( - _ pointee: inout T, by limbs: T, times multiplicand: T.Element, plus subtrahend: T.Element, plus bit: Bool, at index: T.Index) -> IO + _ pointee: inout T, by limbs: T, times multiplicand: T.Element, + plus subtrahend: T.Element, plus bit: Bool, at index: T.Index) -> IO where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { var index: T.Index = index, bit: Bool = bit NBK.decrementSufficientUnsignedInteger(&pointee, by: limbs, times: multiplicand, plus: subtrahend, plus: &bit, at: &index) @@ -288,7 +289,8 @@ extension NBK { /// - Returns: An overflow indicator and its index in `pointee`. /// @inlinable public static func decrementSufficientUnsignedInteger( - _ pointee: inout T, by limbs: T, times multiplicand: T.Element, plus subtrahend: T.Element, plus bit: inout Bool, at index: inout T.Index) + _ pointee: inout T, by limbs: T, times multiplicand: T.Element, + plus subtrahend: T.Element, plus bit: inout Bool, at index: inout T.Index) where T: MutableCollection, T.Element: NBKFixedWidthInteger & NBKUnsignedInteger { var last: T.Element = subtrahend