-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[NBKFlexibleWidthKit] Strict bit pattern (#83).
- Loading branch information
Showing
7 changed files
with
251 additions
and
6 deletions.
There are no files selected for viewing
127 changes: 127 additions & 0 deletions
127
Sources/NBKFlexibleWidthKit/Private/NBKStrictBitPattern+Shifts.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
//=----------------------------------------------------------------------------= | ||
// This source file is part of the Numberick open source project. | ||
// | ||
// Copyright (c) 2023 Oscar Byström Ericsson | ||
// Licensed under Apache License, Version 2.0 | ||
// | ||
// See http://www.apache.org/licenses/LICENSE-2.0 for license information. | ||
//=----------------------------------------------------------------------------= | ||
|
||
import NBKCoreKit | ||
|
||
//*============================================================================* | ||
// MARK: * NBK x Strict Bit Pattern x Shifts | ||
//*============================================================================* | ||
//=----------------------------------------------------------------------------= | ||
// MARK: + Left | ||
//=----------------------------------------------------------------------------= | ||
|
||
extension NBKStrictBitPattern where Base: MutableCollection, Base.Indices == Range<Int> { | ||
|
||
//=------------------------------------------------------------------------= | ||
// MARK: Transformations | ||
//=------------------------------------------------------------------------= | ||
|
||
/// Performs a left shift, assuming the `base` is ordered from least to most significant. | ||
/// | ||
/// - Parameters: | ||
/// - pointee: The mutable collection. | ||
/// - environment: The bit used to fill the void. | ||
/// - major: `0 <= major < base.count` | ||
/// - minor: `1 <= minor < Base.Element.bitWidth` | ||
/// | ||
@inlinable public mutating func bitshiftLeft(environment: Bool, major: Int, minorAtLeastOne minor: Int) { | ||
precondition(0 <= major && major < self.base.count/*--*/, NBK.callsiteOutOfBoundsInfo()) | ||
precondition(0 < minor && minor < Base.Element.bitWidth, NBK.callsiteOutOfBoundsInfo()) | ||
//=--------------------------------------= | ||
let push = NBK.initOrBitCast(truncating: minor, as: Base.Element.self) | ||
let pull = NBK.initOrBitCast(truncating: Base.Element.bitWidth - minor, as: Base.Element.self) | ||
let fill = Base.Element(repeating: environment) | ||
//=--------------------------------------= | ||
var destination = self.base.endIndex as Int | ||
let offset: Int = ~(major) | ||
var element = self.base[destination &+ offset] | ||
//=--------------------------------------= | ||
while destination > self.base.startIndex { | ||
self.base.formIndex(before: &destination) | ||
let pushed = element &<< push | ||
element = destination > major ? self.base[destination &+ offset] : fill | ||
let pulled = element &>> pull | ||
self.base[destination] = pushed | pulled | ||
} | ||
} | ||
|
||
/// Performs a left shift, assuming the `base` is ordered from least to most significant. | ||
/// | ||
/// - Parameters: | ||
/// - environment: The bit used to fill the void. | ||
/// - major: `1 <= major < base.count` | ||
/// | ||
@inlinable public mutating func bitshiftLeft(environment: Bool, majorAtLeastOne major: Int) { | ||
precondition(0 < major && major < self.base.count, NBK.callsiteOutOfBoundsInfo()) | ||
//=--------------------------------------= | ||
let fill = Base.Element(repeating: environment) | ||
//=--------------------------------------= | ||
for destination in self.base.indices.reversed() { | ||
self.base[destination] = destination >= major ? self.base[destination - major] : fill | ||
} | ||
} | ||
} | ||
|
||
//=----------------------------------------------------------------------------= | ||
// MARK: + Right | ||
//=----------------------------------------------------------------------------= | ||
|
||
extension NBKStrictBitPattern where Base: MutableCollection { | ||
|
||
//=------------------------------------------------------------------------= | ||
// MARK: Transformations | ||
//=------------------------------------------------------------------------= | ||
|
||
/// Performs a right shift, assuming the `base` is ordered from least to most significant. | ||
/// | ||
/// - Parameters: | ||
/// - environment: The bit used to fill the void. | ||
/// - major: `0 <= major < base.count` | ||
/// - minor: `1 <= minor < Base.Element.bitWidth` | ||
/// | ||
@inlinable public mutating func bitshiftRight(environment: Bool, major: Int, minorAtLeastOne minor: Int) { | ||
precondition(0 <= major && major < self.base.count/*--*/, NBK.callsiteOutOfBoundsInfo()) | ||
precondition(0 < minor && minor < Base.Element.bitWidth, NBK.callsiteOutOfBoundsInfo()) | ||
//=--------------------------------------= | ||
let push = NBK.initOrBitCast(truncating: minor, as: Base.Element.self) | ||
let pull = NBK.initOrBitCast(truncating: Base.Element.bitWidth - minor, as: Base.Element.self) | ||
let fill = Base.Element(repeating: environment) | ||
//=--------------------------------------= | ||
var destination = self.base.startIndex | ||
let edge = self.base.distance(from: major, to: self.base.endIndex) | ||
var element = self.base[major] as Base.Element | ||
//=--------------------------------------= | ||
while destination < self.base.endIndex { | ||
let after = self.base.index(after: destination) | ||
let pushed = element &>> push | ||
element = after < edge ? self.base[after &+ major] : fill | ||
let pulled = element &<< pull | ||
self.base[destination] = pushed | pulled | ||
destination = after | ||
} | ||
} | ||
|
||
/// Performs a right shift, assuming the `base` is ordered from least to most significant. | ||
/// | ||
/// - Parameters: | ||
/// - environment: The bit used to fill the void. | ||
/// - major: `1 <= major < base.count` | ||
/// | ||
@inlinable public mutating func bitshiftRight(environment: Bool, majorAtLeastOne major: Int) { | ||
precondition(0 < major && major < self.base.count, NBK.callsiteOutOfBoundsInfo()) | ||
//=--------------------------------------=--= | ||
let fill = Base.Element(repeating: environment) | ||
//=--------------------------------------= | ||
let edge = self.base.distance(from: major, to: self.base.endIndex) | ||
//=--------------------------------------= | ||
for destination in self.base.indices { | ||
self.base[destination] = destination < edge ? self.base[destination + major] : fill | ||
} | ||
} | ||
} |
93 changes: 93 additions & 0 deletions
93
Sources/NBKFlexibleWidthKit/Private/NBKStrictBitPattern.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
//=----------------------------------------------------------------------------= | ||
// This source file is part of the Numberick open source project. | ||
// | ||
// Copyright (c) 2023 Oscar Byström Ericsson | ||
// Licensed under Apache License, Version 2.0 | ||
// | ||
// See http://www.apache.org/licenses/LICENSE-2.0 for license information. | ||
//=----------------------------------------------------------------------------= | ||
|
||
import NBKCoreKit | ||
|
||
//*============================================================================* | ||
// MARK: * NBK x Strict Bit Pattern | ||
//*============================================================================* | ||
//=----------------------------------------------------------------------------= | ||
// TODO: * NBKOffsetIndexed protocol with static index requirements (perf.) | ||
//=----------------------------------------------------------------------------= | ||
|
||
@frozen public struct NBKStrictBitPattern<Base: RandomAccessCollection> where | ||
Base.Element: NBKCoreInteger & NBKUnsignedInteger, Base.Indices == Range<Int> { | ||
|
||
//=------------------------------------------------------------------------= | ||
// MARK: State | ||
//=------------------------------------------------------------------------= | ||
|
||
@usableFromInline var base: Base | ||
|
||
//=------------------------------------------------------------------------= | ||
// MARK: Initializers | ||
//=------------------------------------------------------------------------= | ||
|
||
@inlinable public init(_ base: Base) { | ||
self.base = base | ||
precondition(Self.validate(self.base)) | ||
} | ||
|
||
@inlinable public init(unchecked base: Base) { | ||
self.base = base | ||
Swift.assert(Self.validate(self.base)) | ||
} | ||
|
||
//=------------------------------------------------------------------------= | ||
// MARK: Utilities | ||
//=------------------------------------------------------------------------= | ||
|
||
@inlinable public static func validate(_ base: Base) -> Bool { | ||
!base.isEmpty && base.startIndex.isZero // TODO: req. NBKOffsetIndexed | ||
} | ||
} | ||
|
||
//=----------------------------------------------------------------------------= | ||
// MARK: + Collection | ||
//=----------------------------------------------------------------------------= | ||
|
||
extension NBKStrictBitPattern { | ||
|
||
//=------------------------------------------------------------------------= | ||
// MARK: Accessors | ||
//=------------------------------------------------------------------------= | ||
|
||
@inlinable public var first: Base.Element { | ||
self.base[self.base.startIndex] | ||
} | ||
|
||
@inlinable public var last: Base.Element { | ||
self.base[self.lastIndex] | ||
} | ||
|
||
@inlinable public var lastIndex: Base.Index { | ||
self.base.index(before: self.base.endIndex) | ||
} | ||
} | ||
|
||
//=----------------------------------------------------------------------------= | ||
// MARK: + Collection x Mutable | ||
//=----------------------------------------------------------------------------= | ||
|
||
extension NBKStrictBitPattern where Base: MutableCollection { | ||
|
||
//=------------------------------------------------------------------------= | ||
// MARK: Accessors | ||
//=------------------------------------------------------------------------= | ||
|
||
@inlinable public var first: Base.Element { | ||
get { self.base[self.base.startIndex] } | ||
set { self.base[self.base.startIndex] = newValue } | ||
} | ||
|
||
@inlinable public var last: Base.Element { | ||
get { self.base[self.lastIndex] } | ||
set { self.base[self.lastIndex] = newValue } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters