From 63dea6b2858f99d3b812b0f7409a55411d647b50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Bystr=C3=B6m=20Ericsson?= Date: Fri, 22 Sep 2023 08:29:57 +0200 Subject: [PATCH] [NBKCoreKit] Simpler shifts (#76). --- .../NBKStrictBinaryInteger+Shifts.swift | 101 ++++++++++++------ .../Private/NBKStrictBinaryInteger.swift | 2 +- .../Private/NBKStrictSignedInteger.swift | 2 +- .../NBKStrictUnsignedInteger+Addition.swift | 16 ++- ...NBKStrictUnsignedInteger+Subtraction.swift | 19 ++-- .../Private/NBKStrictUnsignedInteger.swift | 2 +- .../Private/NBKSuccinctInt+Comparisons.swift | 6 +- 7 files changed, 88 insertions(+), 60 deletions(-) diff --git a/Sources/NBKCoreKit/Private/NBKStrictBinaryInteger+Shifts.swift b/Sources/NBKCoreKit/Private/NBKStrictBinaryInteger+Shifts.swift index 57a02441..673fd5d7 100644 --- a/Sources/NBKCoreKit/Private/NBKStrictBinaryInteger+Shifts.swift +++ b/Sources/NBKCoreKit/Private/NBKStrictBinaryInteger+Shifts.swift @@ -32,15 +32,24 @@ extension NBK.StrictBinaryInteger where Base: MutableCollection { //=--------------------------------------= // major: zero works but it is pointless //=--------------------------------------= - Swift.assert(000000000001 <= major, NBK.callsiteOutOfBoundsInfo()) - precondition(base.indices ~= major, NBK.callsiteOutOfBoundsInfo()) - //=--------------------------------------= - let offset: Int = major.twosComplement() var destination = base.endIndex as Base.Index + var source = base.index(destination, offsetBy: major.twosComplement()) + //=--------------------------------------= + Swift.assert(base.startIndex < source) + precondition(base.startIndex <= source && source < base.endIndex, NBK.callsiteOutOfBoundsInfo()) //=--------------------------------------= while destination > base.startIndex { + let element: Base.Element + + if source > base.startIndex { + base.formIndex(before: &source) + element = base[source] + } else { + element = environment + } + base.formIndex(before: &destination) - base[destination] = destination >= major ? base[destination &+ offset] : environment + base[destination] = element } } } @@ -83,21 +92,30 @@ extension NBK.StrictBinaryInteger where Base: MutableCollection { @inline(__always) @inlinable public static func bitshiftLeftCodeBlock( _ base: inout Base, environment: Base.Element, major: Int, minorAtLeastOne minor: Int) { //=--------------------------------------= - precondition(0 <= major && major < base.count, NBK.callsiteOutOfBoundsInfo()) - precondition(0 < minor && minor < Base.Element.bitWidth, NBK.callsiteOutOfBoundsInfo()) + precondition((1 as Int) <= minor && minor < Base.Element.bitWidth, NBK.callsiteOutOfBoundsInfo()) //=--------------------------------------= - let push = NBK.initOrBitCast(truncating: minor, as: Base.Element.self) + let push = Base.Element(truncatingIfNeeded: minor) let pull = push.twosComplement() //=--------------------------------------= - let offset: Int = major.onesComplement() var destination = base.endIndex as Base.Index - var element = base[destination &+ offset] + var source = base.index(destination, offsetBy: major.onesComplement()) + //=--------------------------------------= + precondition(base.startIndex <= source && source < base.endIndex, NBK.callsiteOutOfBoundsInfo()) //=--------------------------------------= + var element = base[source] as Base.Element + while destination > base.startIndex { + let pushed: Base.Element = element &<< push + + if source > base.startIndex { + base.formIndex(before: &source) + element = base[source] + } else { + element = environment + } + + let pulled: Base.Element = element &>> pull base.formIndex(before: &destination) - let pushed = element &<< push - element = destination > major ? base[destination &+ offset] : environment - let pulled = element &>> pull base[destination] = pushed | pulled } } @@ -128,15 +146,27 @@ extension NBK.StrictBinaryInteger where Base: MutableCollection { //=--------------------------------------= // major: zero works but it is pointless //=--------------------------------------= - Swift.assert(000000000001 <= major, NBK.callsiteOutOfBoundsInfo()) - precondition(base.indices ~= major, NBK.callsiteOutOfBoundsInfo()) - //=--------------------------------------= - let edge = base.endIndex &+ major.onesComplement() var destination = base.startIndex as Base.Index - //=--------------------------------------= - while destination < base.endIndex { - base[destination] = destination <= edge ? base[destination &+ major] : environment + var source = base.index(destination, offsetBy: major) + //=--------------------------------------= + Swift.assert(base.startIndex < source) + precondition(base.startIndex <= source && source < base.endIndex, NBK.callsiteOutOfBoundsInfo()) + //=--------------------------------------= + while destination < base.endIndex { + let element: Base.Element + let offset: Int + + if source < base.endIndex { + element = base[source] + offset = 1 as Int + } else { + element = environment + offset = 0 as Int + } + + base[destination] = element base.formIndex(after: &destination) + base.formIndex(&source, offsetBy: offset) } } } @@ -179,23 +209,32 @@ extension NBK.StrictBinaryInteger where Base: MutableCollection { @inline(__always) @inlinable public static func bitshiftRightCodeBlock( _ base: inout Base, environment: Base.Element, major: Int, minorAtLeastOne minor: Int) { //=--------------------------------------= - precondition(0 <= major && major < base.count, NBK.callsiteOutOfBoundsInfo()) - precondition(0 < minor && minor < Base.Element.bitWidth, NBK.callsiteOutOfBoundsInfo()) + precondition((1 as Int) <= minor && minor < Base.Element.bitWidth, NBK.callsiteOutOfBoundsInfo()) //=--------------------------------------= - let push = NBK.initOrBitCast(truncating: minor, as: Base.Element.self) + let push = Base.Element(truncatingIfNeeded: minor) let pull = push.twosComplement() //=--------------------------------------= - var destination = base.startIndex - var element = base[major] as Base.Element + var destination = base.startIndex as Base.Index + var source = base.index(destination, offsetBy: major) + //=--------------------------------------= + precondition(base.startIndex <= source && source < base.endIndex, NBK.callsiteOutOfBoundsInfo()) //=--------------------------------------= + var element = base[source] as Base.Element + base.formIndex(after: &source) + while destination < base.endIndex { - let after = destination &+ 1 - let source = after &+ major - let pushed = element &>> push - element = source < base.endIndex ? base[source] : environment - let pulled = element &<< pull + let pushed: Base.Element = element &>> push + + if source < base.endIndex { + element = base[source] + base.formIndex(after: &source) + } else { + element = environment + } + + let pulled: Base.Element = element &<< pull base[destination] = pushed | pulled - destination = after as Base.Index + base.formIndex(after: &destination) } } } diff --git a/Sources/NBKCoreKit/Private/NBKStrictBinaryInteger.swift b/Sources/NBKCoreKit/Private/NBKStrictBinaryInteger.swift index 2c315235..b60ea29d 100644 --- a/Sources/NBKCoreKit/Private/NBKStrictBinaryInteger.swift +++ b/Sources/NBKCoreKit/Private/NBKStrictBinaryInteger.swift @@ -29,7 +29,7 @@ extension NBK { /// /// Remaking this as a view when Swift gets view types might be neat. /// - @frozen public struct StrictBinaryInteger where Base: NBKOffsetAccessCollection, + @frozen public struct StrictBinaryInteger where Base: RandomAccessCollection, Base.Element: NBKCoreInteger & NBKUnsignedInteger { //*====================================================================* diff --git a/Sources/NBKCoreKit/Private/NBKStrictSignedInteger.swift b/Sources/NBKCoreKit/Private/NBKStrictSignedInteger.swift index 09b343e7..17076f8f 100644 --- a/Sources/NBKCoreKit/Private/NBKStrictSignedInteger.swift +++ b/Sources/NBKCoreKit/Private/NBKStrictSignedInteger.swift @@ -29,7 +29,7 @@ extension NBK { /// /// Remaking this as a view when Swift gets view types might be neat. /// - @frozen public enum StrictSignedInteger where Base: NBKOffsetAccessCollection, + @frozen public enum StrictSignedInteger where Base: RandomAccessCollection, Base.Element: NBKCoreInteger & NBKUnsignedInteger { /// The binary integer namespace of this type. diff --git a/Sources/NBKCoreKit/Private/NBKStrictUnsignedInteger+Addition.swift b/Sources/NBKCoreKit/Private/NBKStrictUnsignedInteger+Addition.swift index 5fa53d73..c0c2aeaa 100644 --- a/Sources/NBKCoreKit/Private/NBKStrictUnsignedInteger+Addition.swift +++ b/Sources/NBKCoreKit/Private/NBKStrictUnsignedInteger+Addition.swift @@ -47,8 +47,8 @@ extension NBK.StrictUnsignedInteger.SubSequence where Base: MutableCollection { @inlinable public static func increment( _ base: inout Base, by bit: inout Bool, at index: inout Base.Index) { //=--------------------------------------= - Swift.assert(index >= 0 as Int) - Swift.assert(base.count >= index) // void + Swift.assert(index >= base.startIndex) + Swift.assert(index <= base.endIndex ) // void //=--------------------------------------= while bit && index < base.endIndex { bit = base[index].addReportingOverflow(1 as Base.Element.Digit) @@ -123,8 +123,8 @@ extension NBK.StrictUnsignedInteger.SubSequence where Base: MutableCollection { @inlinable public static func incrementInIntersection( _ base: inout Base, by digit: Base.Element, at index: inout Base.Index) -> Bool { //=--------------------------------------= - Swift.assert(index >= 0 as Int) - Swift.assert(base.count > index) + Swift.assert(index >= base.startIndex) + Swift.assert(index < base.endIndex ) //=--------------------------------------= defer{ base.formIndex(after: &index) } return base[index].addReportingOverflow(digit) @@ -196,8 +196,8 @@ extension NBK.StrictUnsignedInteger.SubSequence where Base: MutableCollection { @inlinable public static func incrementInIntersection( _ base: inout Base, by digit: Base.Element, plus bit: inout Bool, at index: inout Base.Index) { //=--------------------------------------= - Swift.assert(index >= 0 as Int) - Swift.assert(base.count > index) + Swift.assert(index >= base.startIndex) + Swift.assert(index < base.endIndex ) //=--------------------------------------= var digit: Base.Element = digit //=--------------------------------------= @@ -275,10 +275,6 @@ extension NBK.StrictUnsignedInteger.SubSequence where Base: MutableCollection { /// @inlinable public static func incrementInIntersection( _ base: inout Base, by elements: some Collection, plus bit: inout Bool, at index: inout Base.Index) { - //=--------------------------------------= - Swift.assert(index >= 0 as Int) - Swift.assert(base.count >= elements.count + index) - //=--------------------------------------= for elementIndex in elements.indices { self.incrementInIntersection(&base, by: elements[elementIndex], plus: &bit, at: &index) } diff --git a/Sources/NBKCoreKit/Private/NBKStrictUnsignedInteger+Subtraction.swift b/Sources/NBKCoreKit/Private/NBKStrictUnsignedInteger+Subtraction.swift index 8e4f454f..fd8dc6fa 100644 --- a/Sources/NBKCoreKit/Private/NBKStrictUnsignedInteger+Subtraction.swift +++ b/Sources/NBKCoreKit/Private/NBKStrictUnsignedInteger+Subtraction.swift @@ -46,8 +46,8 @@ extension NBK.StrictUnsignedInteger.SubSequence where Base: MutableCollection { @inlinable public static func decrement( _ base: inout Base, by bit: inout Bool, at index: inout Base.Index) { //=--------------------------------------= - Swift.assert(index >= 0 as Int) - Swift.assert(base.count >= index) // void + Swift.assert(index >= base.startIndex) + Swift.assert(index <= base.endIndex ) // void //=--------------------------------------= while bit && index < base.endIndex { bit = base[index].subtractReportingOverflow(1 as Base.Element.Digit) @@ -122,8 +122,8 @@ extension NBK.StrictUnsignedInteger.SubSequence where Base: MutableCollection { @inlinable public static func decrementInIntersection( _ base: inout Base, by digit: Base.Element, at index: inout Base.Index) -> Bool { //=--------------------------------------= - Swift.assert(index >= 0 as Int) - Swift.assert(base.count > index) + Swift.assert(index >= base.startIndex) + Swift.assert(index < base.endIndex ) //=--------------------------------------= defer{ base.formIndex(after: &index) } return base[index].subtractReportingOverflow(digit) @@ -195,8 +195,8 @@ extension NBK.StrictUnsignedInteger.SubSequence where Base: MutableCollection { @inlinable public static func decrementInIntersection( _ base: inout Base, by digit: Base.Element, plus bit: inout Bool, at index: inout Base.Index) { //=--------------------------------------= - Swift.assert(index >= 0 as Int) - Swift.assert(base.count > index) + Swift.assert(index >= base.startIndex) + Swift.assert(index < base.endIndex ) //=--------------------------------------= var digit: Base.Element = digit //=--------------------------------------= @@ -274,9 +274,6 @@ extension NBK.StrictUnsignedInteger.SubSequence where Base: MutableCollection { /// @inlinable public static func decrementInIntersection( _ base: inout Base, by elements: some Collection, plus bit: inout Bool, at index: inout Base.Index) { - //=--------------------------------------= - Swift.assert(base.count >= elements.count + index) - //=--------------------------------------= for elementsIndex in elements.indices { self.decrementInIntersection(&base, by: elements[elementsIndex], plus: &bit, at: &index) } @@ -321,10 +318,6 @@ extension NBK.StrictUnsignedInteger.SubSequence where Base: MutableCollection { @inlinable public static func decrement( _ base: inout Base, by elements: some Collection, times multiplicand: Base.Element, plus subtrahend: Base.Element, plus bit: inout Bool, at index: inout Base.Index) { - //=--------------------------------------= - Swift.assert(index >= 0 as Int) - Swift.assert(base.count > elements.count + index) - //=--------------------------------------= var last: Base.Element = subtrahend for elementsIndex in elements.indices { diff --git a/Sources/NBKCoreKit/Private/NBKStrictUnsignedInteger.swift b/Sources/NBKCoreKit/Private/NBKStrictUnsignedInteger.swift index a1a2aaa5..57116fc0 100644 --- a/Sources/NBKCoreKit/Private/NBKStrictUnsignedInteger.swift +++ b/Sources/NBKCoreKit/Private/NBKStrictUnsignedInteger.swift @@ -29,7 +29,7 @@ extension NBK { /// /// Remaking this as a view when Swift gets view types might be neat. /// - @frozen public enum StrictUnsignedInteger where Base: NBKOffsetAccessCollection, + @frozen public enum StrictUnsignedInteger where Base: RandomAccessCollection, Base.Element: NBKCoreInteger & NBKUnsignedInteger { /// The binary integer namespace of this type. diff --git a/Sources/NBKCoreKit/Private/NBKSuccinctInt+Comparisons.swift b/Sources/NBKCoreKit/Private/NBKSuccinctInt+Comparisons.swift index 7dc56e40..c7548cfe 100644 --- a/Sources/NBKCoreKit/Private/NBKSuccinctInt+Comparisons.swift +++ b/Sources/NBKCoreKit/Private/NBKSuccinctInt+Comparisons.swift @@ -36,15 +36,15 @@ extension NBK.SuccinctInt { //=--------------------------------------= // Long & Short //=--------------------------------------= - if self.body.count != other.body.count { + if self.body.count != other.body.count { return self.sign == (self.body.count > other.body.count) ? -1 : 1 } //=--------------------------------------= - return self.compared(toSameSizeSameSign: other) + return self.compared(toSameSignSameSize: other) } /// A three-way comparison of `self` against `other`. - @inlinable public func compared(toSameSizeSameSign other: Self) -> Int { + @inlinable public func compared(toSameSignSameSize other: Self) -> Int { //=--------------------------------------= Swift.assert(self.sign/*--*/ == other.sign/*--*/) Swift.assert(self.body.count == other.body.count)