Skip to content

Commit

Permalink
NBKCoreKit: Cleanup.
Browse files Browse the repository at this point in the history
  • Loading branch information
oscbyspro committed Aug 5, 2023
1 parent 40f2958 commit 391f496
Show file tree
Hide file tree
Showing 31 changed files with 217 additions and 193 deletions.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,6 @@ extension NBK {
// MARK: Details
//=------------------------------------------------------------------------=

/// Returns the most significant bit for the two's complement of `limbs`.
///
/// - Note: The most significant bit does not exist when `limbs` is empty.
///
@inlinable public static func mostSignificantBit(twosComplementOf limbs: some BidirectionalCollection<some NBKFixedWidthInteger>) -> Bool? {
guard let index = limbs.firstIndex(where:{ !$0.isZero }) else { return limbs.isEmpty ? nil : false }
let lastIndex = limbs.index(before: limbs.endIndex)
return limbs[lastIndex].twosComplementSubsequence(index == lastIndex).partialValue.mostSignificantBit
}

//=------------------------------------------------------------------------=
// MARK: Details x Trailing Zero Bit Count
//=------------------------------------------------------------------------=

/// Returns the trailing zero bit count of `limbs`.
///
/// - Note: The trailing zero bit count is zero when `limbs` is empty.
Expand All @@ -47,6 +33,16 @@ extension NBK {
return limbs.distance(from: limbs.startIndex, to: index) * T.bitWidth - T.bitWidth + element.trailingZeroBitCount
}

/// Returns the most significant bit for the two's complement of `limbs`.
///
/// - Note: The most significant bit does not exist when `limbs` is empty.
///
@inlinable public static func mostSignificantBit(twosComplementOf limbs: some BidirectionalCollection<some NBKFixedWidthInteger>) -> Bool? {
guard let index = limbs.firstIndex(where:{ !$0.isZero }) else { return limbs.isEmpty ? nil : false }
let lastIndex = limbs.index(before: limbs.endIndex)
return limbs[lastIndex].twosComplementSubsequence(index == lastIndex).partialValue.mostSignificantBit
}

//=------------------------------------------------------------------------=
// MARK: Details x Nonzero Bit Count
//=------------------------------------------------------------------------=
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -8,52 +8,11 @@
//=----------------------------------------------------------------------------=

//*============================================================================*
// MARK: * NBK x Radix Integers
// MARK: * NBK x Text x Radix
//*============================================================================*

extension NBK {

//=------------------------------------------------------------------------=
// MARK: Details x Components
//=------------------------------------------------------------------------=

/// Returns an `UTF-8` encoded integer's `sign` and `body`.
///
/// ```
/// ┌─────── → ──────┬────────┐
/// │ utf8 │ sign │  body │
/// ├─────── → ──────┼────────┤
/// │ "+123" │ plus │ "123" │
/// │ "-123" │ minus │ "123" │
/// │ "~123" │ plus │ "~123" │
/// └─────── → ──────┴────────┘
/// ```
///
@inlinable public static func integerComponents<T>(utf8: T) -> (sign: Sign, body: T.SubSequence) where T: Collection<UInt8> {
var body = utf8[...] as T.SubSequence
let sign = NBK.removeSignPrefix(utf8: &body) ?? Sign.plus
return (sign: sign, body: body)
}

/// Removes and returns an `UTF-8` encoded `sign` prefix, if it exists.
///
/// ```
/// ┌─────── → ──────┬────────┐
/// │ self │ sign │  self │
/// ├─────── → ──────┼────────┤
/// │ "+123" │ plus │ "123" │
/// │ "-123" │ minus │ "123" │
/// │ "~123" │ nil │ "~123" │
/// └─────── → ──────┴────────┘
/// ```
///
@inlinable public static func removeSignPrefix<T>(utf8: inout T) -> Sign? where T: Collection<UInt8>, T == T.SubSequence {
switch utf8.first {
case UInt8(ascii: "+"): utf8.removeFirst(); return Sign.plus
case UInt8(ascii: "-"): utf8.removeFirst(); return Sign.minus
default: return nil }
}

//=------------------------------------------------------------------------=
// MARK: Details x Decode
//=------------------------------------------------------------------------=
Expand Down
56 changes: 56 additions & 0 deletions Sources/NBKCoreKit/Private/NBK+Text.swift
Original file line number Diff line number Diff line change
@@ -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 Text
//*============================================================================*

extension NBK {

//=------------------------------------------------------------------------=
// MARK: Transformations
//=------------------------------------------------------------------------=

/// Returns an `UTF-8` encoded integer's `sign` and `body`.
///
/// ```
/// ┌─────── → ──────┬────────┐
/// │ utf8 │ sign │  body │
/// ├─────── → ──────┼────────┤
/// │ "+123" │ plus │ "123" │
/// │ "-123" │ minus │ "123" │
/// │ "~123" │ plus │ "~123" │
/// └─────── → ──────┴────────┘
/// ```
///
@inlinable public static func integerComponents<T>(utf8: T) -> (sign: Sign, body: T.SubSequence) where T: Collection<UInt8> {
var body = utf8[...] as T.SubSequence
let sign = NBK.removeSignPrefix(utf8: &body) ?? Sign.plus
return (sign: sign, body: body)
}

/// Removes and returns an `UTF-8` encoded `sign` prefix, if it exists.
///
/// ```
/// ┌─────── → ──────┬────────┐
/// │ self │ sign │  self │
/// ├─────── → ──────┼────────┤
/// │ "+123" │ plus │ "123" │
/// │ "-123" │ minus │ "123" │
/// │ "~123" │ nil │ "~123" │
/// └─────── → ──────┴────────┘
/// ```
///
@inlinable public static func removeSignPrefix<T>(utf8: inout T) -> Sign? where T: Collection<UInt8>, T == T.SubSequence {
switch utf8.first {
case UInt8(ascii: "+"): utf8.removeFirst(); return Sign.plus
case UInt8(ascii: "-"): utf8.removeFirst(); return Sign.minus
default: return nil }
}
}
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
//=----------------------------------------------------------------------------=

//*============================================================================*
// MARK: * NBK x Namespace
// MARK: * NBK
//*============================================================================*

/// A namespace for `Numberick` development.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import XCTest
// MARK: * NBK x Bits
//*============================================================================*

final class BitsBenchmarks: XCTestCase {
final class NBKBenchmarksOnBits: XCTestCase {

private typealias U64 = [UInt64]
private typealias U32 = [UInt32]
Expand All @@ -25,30 +25,26 @@ final class BitsBenchmarks: XCTestCase {
// MARK: Tests
//=------------------------------------------------------------------------=

func testMostSignificantBitTwosComplementOf() {
func testTrailingZeroBitCount() {
var abc = NBK.blackHoleIdentity([ 0, 0, 0, 0, 0, 0, 0, 0] as U64)
var xyz = NBK.blackHoleIdentity([~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0] as U64)

for _ in 0 ..< 5_000_000 {
NBK.blackHole(NBK.mostSignificantBit(twosComplementOf: abc)!)
NBK.blackHole(NBK.mostSignificantBit(twosComplementOf: xyz)!)
NBK.blackHole(NBK.trailingZeroBitCount(of: abc))
NBK.blackHole(NBK.trailingZeroBitCount(of: xyz))

NBK.blackHoleInoutIdentity(&abc)
NBK.blackHoleInoutIdentity(&xyz)
}
}

//=------------------------------------------------------------------------=
// MARK: Tests x Trailing Bit Count
//=------------------------------------------------------------------------=

func testTrailingZeroBitCount() {
func testMostSignificantBitTwosComplementOf() {
var abc = NBK.blackHoleIdentity([ 0, 0, 0, 0, 0, 0, 0, 0] as U64)
var xyz = NBK.blackHoleIdentity([~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0] as U64)

for _ in 0 ..< 5_000_000 {
NBK.blackHole(NBK.trailingZeroBitCount(of: abc))
NBK.blackHole(NBK.trailingZeroBitCount(of: xyz))
NBK.blackHole(NBK.mostSignificantBit(twosComplementOf: abc)!)
NBK.blackHole(NBK.mostSignificantBit(twosComplementOf: xyz)!)

NBK.blackHoleInoutIdentity(&abc)
NBK.blackHoleInoutIdentity(&xyz)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import XCTest
// MARK: * NBK x Limbs
//*============================================================================*

final class LimbsBenchmarks: XCTestCase {
final class NBKBenchmarksOnLimbs: XCTestCase {

//=------------------------------------------------------------------------=
// MARK: Tests
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ import NBKCoreKit
import XCTest

//*============================================================================*
// MARK: * NBK x Bit Cast x Integers
// MARK: * NBK x Bit Cast
//*============================================================================*

final class BitCastTestsOnIntegers: XCTestCase {
final class NBKTestsOnBitCast: XCTestCase {

//=------------------------------------------------------------------------=
// MARK: State
Expand Down Expand Up @@ -157,9 +157,9 @@ final class BitCastTestsOnIntegers: XCTestCase {
}
}

//=----------------------------------------------------------------------------=
// MARK: Utilities
//=----------------------------------------------------------------------------=
//*============================================================================*
// MARK: * NBK x Bit Cast x Assertions
//*============================================================================*

private func NBKAssertInitOrBitCast<I: NBKFixedWidthInteger, O: NBKFixedWidthInteger>(
_ source: I, exactly: O?, clamping: O, truncating: O,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import XCTest
// MARK: * NBK x Bits
//*============================================================================*

final class BitsTests: XCTestCase {
final class NBKTestsOnBits: XCTestCase {

private typealias U64 = [UInt64]
private typealias U32 = [UInt32]
Expand All @@ -25,27 +25,6 @@ final class BitsTests: XCTestCase {
// MARK: Tests
//=------------------------------------------------------------------------=

func testMostSignificantBitTwosComplementOf() {
NBKAssertMostSignificantBit(twosComplementOf:[00, 00, 00, 00] as U64, false)
NBKAssertMostSignificantBit(twosComplementOf:[~0, ~0, ~0, ~0] as U64, false)

NBKAssertMostSignificantBit(twosComplementOf:[01, 00, 00, 00] as U64, true )
NBKAssertMostSignificantBit(twosComplementOf:[~1, ~0, ~0, ~0] as U64, false)

NBKAssertMostSignificantBit(twosComplementOf:[ 0, 0, 0, ~0/2 + 1] as U64, true) // Int256.min
NBKAssertMostSignificantBit(twosComplementOf:[~0, ~0, ~0, ~0/2 + 0] as U64, true) // Int256.max
}

func testMostSignificantBitTwosComplementOfReturnsNilWhenLimbsIsEmpty() {
NBKAssertMostSignificantBit(twosComplementOf:[ ] as U64, nil )
NBKAssertMostSignificantBit(twosComplementOf:[ 0] as U64, false)
NBKAssertMostSignificantBit(twosComplementOf:[ 1] as U64, true )
}

//=------------------------------------------------------------------------=
// MARK: Tests x Trailing Zero Bit Count
//=------------------------------------------------------------------------=

func testTrailingZeroBitCount() {
NBKAssertTrailingZeroBitCount([ ] as U64, 000)
NBKAssertTrailingZeroBitCount([00 ] as U64, 064)
Expand All @@ -64,6 +43,23 @@ final class BitsTests: XCTestCase {
NBKAssertTrailingZeroBitCount([00, 00, 00, 02] as U64, 193)
}

func testMostSignificantBitTwosComplementOf() {
NBKAssertMostSignificantBit(twosComplementOf:[00, 00, 00, 00] as U64, false)
NBKAssertMostSignificantBit(twosComplementOf:[~0, ~0, ~0, ~0] as U64, false)

NBKAssertMostSignificantBit(twosComplementOf:[01, 00, 00, 00] as U64, true )
NBKAssertMostSignificantBit(twosComplementOf:[~1, ~0, ~0, ~0] as U64, false)

NBKAssertMostSignificantBit(twosComplementOf:[ 0, 0, 0, ~0/2 + 1] as U64, true) // Int256.min
NBKAssertMostSignificantBit(twosComplementOf:[~0, ~0, ~0, ~0/2 + 0] as U64, true) // Int256.max
}

func testMostSignificantBitTwosComplementOfReturnsNilWhenLimbsIsEmpty() {
NBKAssertMostSignificantBit(twosComplementOf:[ ] as U64, nil )
NBKAssertMostSignificantBit(twosComplementOf:[ 0] as U64, false)
NBKAssertMostSignificantBit(twosComplementOf:[ 1] as U64, true )
}

//=------------------------------------------------------------------------=
// MARK: Tests x Nonzero Bit Count
//=------------------------------------------------------------------------=
Expand Down Expand Up @@ -123,9 +119,9 @@ final class BitsTests: XCTestCase {
}
}

//=----------------------------------------------------------------------------=
// MARK: + Utilities
//=----------------------------------------------------------------------------=
//*============================================================================*
// MARK: * NBK x Bits x Assertions
//*============================================================================*

private func NBKAssertMostSignificantBit(
twosComplementOf limbs: [UInt64], _ bit: Bool?,
Expand All @@ -142,7 +138,7 @@ file: StaticString = #file, line: UInt = #line) {
}

//=----------------------------------------------------------------------------=
// MARK: + Utilities x Nonzero Bit Count
// MARK: + Nonzero Bit Count
//=----------------------------------------------------------------------------=

private func NBKAssertNonzeroBitCount(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import XCTest
// MARK: * NBK x Collection
//*============================================================================*

final class CollectionTests: XCTestCase {
final class NBKTestsOnCollection: XCTestCase {

//=------------------------------------------------------------------------=
// MARK: Tests x Drop
Expand Down Expand Up @@ -84,8 +84,11 @@ final class CollectionTests: XCTestCase {
}
}

//*============================================================================*
// MARK: * NBK x Collection x Assertions
//*============================================================================*
//=----------------------------------------------------------------------------=
// MARK: + Utilities x Drop
// MARK: + Drop
//=----------------------------------------------------------------------------=

private func NBKAssertDropLastWhile(
Expand All @@ -96,7 +99,7 @@ file: StaticString = #file, line: UInt = #line) {
}

//=----------------------------------------------------------------------------=
// MARK: + Utilities x Remove Count
// MARK: + Remove Count
//=----------------------------------------------------------------------------=

private func NBKAssertRemovePrefixCount(
Expand All @@ -120,7 +123,7 @@ file: StaticString = #file, line: UInt = #line) {
}

//=----------------------------------------------------------------------------=
// MARK: + Utilities x Remove Max Length
// MARK: + Remove Max Length
//=----------------------------------------------------------------------------=

private func NBKAssertRemovePrefixMaxLength(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import XCTest
// MARK: * NBK x Division x Int or UInt
//*============================================================================*

final class DivisionTestsOnIntOrUInt: XCTestCase {
final class NBKTestsOnDivisionAsIntOrUInt: XCTestCase {

typealias T = UInt

Expand Down Expand Up @@ -51,9 +51,9 @@ final class DivisionTestsOnIntOrUInt: XCTestCase {
}
}

//=----------------------------------------------------------------------------=
// MARK: + Utilities
//=----------------------------------------------------------------------------=
//*============================================================================*
// MARK: * NBK x Division x Assertions
//*============================================================================*

private func NBKAssertDividingByBitWidthAsIntOrUInt(
_ value: UInt, _ quotient: UInt, _ remainder: UInt,
Expand Down
Loading

0 comments on commit 391f496

Please sign in to comment.