Skip to content

Commit

Permalink
[NBKCoreKit] Cleanup. StrictSignMagnitude (#85).
Browse files Browse the repository at this point in the history
  • Loading branch information
oscbyspro committed Oct 5, 2023
1 parent afe71ff commit 1081daa
Show file tree
Hide file tree
Showing 12 changed files with 357 additions and 130 deletions.
32 changes: 25 additions & 7 deletions Sources/NBKCoreKit/Private/NBK.swift
Original file line number Diff line number Diff line change
Expand Up @@ -65,15 +65,9 @@
public typealias Wide3<T> = (high: T, mid: T.Magnitude, low: T.Magnitude) where T: NBKFixedWidthInteger

//=------------------------------------------------------------------------=
// MARK: Namespaces
// MARK: Namespaces x Binary Integer
//=------------------------------------------------------------------------=

/// A namespace for `Numberick` development.
///
/// - Warning: Do not use this namespace outside of `Numberick` development.
///
public typealias SAM<Magnitude> = NBK.SignAndMagnitude<Magnitude> where Magnitude: NBKUnsignedInteger

/// A namespace for `Numberick` development.
///
/// - Warning: Do not use this namespace outside of `Numberick` development.
Expand Down Expand Up @@ -115,4 +109,28 @@
///
public typealias SUISS<Base> = NBK.StrictUnsignedInteger<Base>.SubSequence where
Base: RandomAccessCollection, Base.Element: NBKCoreInteger & NBKUnsignedInteger

//=------------------------------------------------------------------------=
// MARK: Namespaces x Sign & Magnitude
//=------------------------------------------------------------------------=

/// A namespace for `Numberick` development.
///
/// - Warning: Do not use this namespace outside of `Numberick` development.
///
public typealias ISM<Magnitude> = NBK.IntegerSignMagnitude<Magnitude> where Magnitude: NBKUnsignedInteger

/// A namespace for `Numberick` development.
///
/// - Warning: Do not use this namespace outside of `Numberick` development.
///
public typealias SSM<Base> = NBK.StrictSignMagnitude<Base> where
Base: RandomAccessCollection, Base.Element: NBKCoreInteger & NBKUnsignedInteger

/// A namespace for `Numberick` development.
///
/// - Warning: Do not use this namespace outside of `Numberick` development.
///
public typealias SSMSS<Base> = NBK.StrictSignMagnitude<Base>.SubSequence where
Base: RandomAccessCollection, Base.Element: NBKCoreInteger & NBKUnsignedInteger
}
44 changes: 20 additions & 24 deletions Sources/NBKCoreKit/Private/NBKIntegerDescription+Decoding.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@ extension NBK.IntegerDescription {
///
@frozen public struct Decoder<Magnitude: NBKUnsignedInteger> {

public typealias Components = (sign: NBK.Sign, magnitude: Magnitude)

//=--------------------------------------------------------------------=
// MARK: State
//=--------------------------------------------------------------------=
Expand All @@ -58,19 +56,19 @@ extension NBK.IntegerDescription {
// MARK: Utilities
//=--------------------------------------------------------------------=

@inlinable public func decode(_ description: some StringProtocol) -> Components? {
var description = String(description); return description.withUTF8(self.decode)
}

@inlinable public func decode(_ description: StaticString) -> Components? {
@inlinable public func decode(_ description: StaticString) -> SM<Magnitude>? {
description.withUTF8Buffer(self.decode)
}

@inlinable public func decode(_ description: NBK.UnsafeUTF8) -> Components? {
let components = NBK.IntegerDescription.makeSignBody(from: description)
let digits = NBK.UnsafeUTF8(rebasing: components.body)
guard let magnitude: Magnitude = NBK.IntegerDescription.decode(digits: digits, solution: self.solution) else { return nil }
return SM(sign: components.sign, magnitude: magnitude)
@inlinable public func decode(_ description: some StringProtocol) -> SM<Magnitude>? {
var description = String(description); return description.withUTF8(self.decode)
}

@inlinable public func decode(_ description: NBK.UnsafeUTF8) -> SM<Magnitude>? {
let inputs = NBK.IntegerDescription.makeSignBody(from: description)
let digits = NBK.UnsafeUTF8(rebasing: inputs.body)
guard let magnitude: Magnitude = NBK.IntegerDescription.decode(digits: digits, solution: self.solution) else { return nil }
return SM(sign: inputs.sign, magnitude: magnitude)
}
}

Expand Down Expand Up @@ -100,8 +98,6 @@ extension NBK.IntegerDescription {
///
@frozen public struct DecoderDecodingRadix<Magnitude> where Magnitude: NBKUnsignedInteger {

public typealias Components = (sign: NBK.Sign, radix: Int, magnitude: Magnitude)

//=--------------------------------------------------------------------=
// MARK: Initializers
//=--------------------------------------------------------------------=
Expand All @@ -112,20 +108,20 @@ extension NBK.IntegerDescription {
// MARK: Utilities
//=--------------------------------------------------------------------=

@inlinable public func decode(_ description: some StringProtocol) -> Components? {
var description = String(description); return description.withUTF8(self.decode)
@inlinable public func decode(_ description: StaticString) -> SM<Magnitude>? {
description.withUTF8Buffer(self.decode)
}

@inlinable public func decode(_ description: StaticString) -> Components? {
description.withUTF8Buffer(self.decode)
@inlinable public func decode(_ description: some StringProtocol) -> SM<Magnitude>? {
var description = String(description); return description.withUTF8(self.decode)
}

@inlinable public func decode(_ description: NBK.UnsafeUTF8) -> Components? {
let components = NBK.IntegerDescription.makeSignRadixBody(from: description)
let solution = AnyRadixSolution<UInt>(components.radix)
let digits = NBK.UnsafeUTF8(rebasing: components.body )
guard let magnitude: Magnitude = NBK.IntegerDescription.decode(digits: digits, solution: solution) else { return nil }
return (sign: components.sign, radix: components.radix, magnitude: magnitude)
@inlinable public func decode(_ description: NBK.UnsafeUTF8) -> SM<Magnitude>? {
let inputs = NBK.IntegerDescription.makeSignRadixBody(from: description)
let solution = NBK.IntegerDescription.AnyRadixSolution<UInt>(inputs.radix)
let digits = NBK.UnsafeUTF8(rebasing: inputs.body)
guard let magnitude: Magnitude = NBK.IntegerDescription.decode(digits: digits, solution: solution) else { return nil }
return SM(sign: inputs.sign, magnitude: magnitude)
}
}
}
Expand Down
61 changes: 42 additions & 19 deletions Sources/NBKCoreKit/Private/NBKIntegerDescription+Encoding.swift
Original file line number Diff line number Diff line change
Expand Up @@ -55,35 +55,35 @@ extension NBK.IntegerDescription {
//=--------------------------------------------------------------------=

@inlinable public func encode(_ integer: some NBKBinaryInteger) -> String {
let isLessThanZero: Bool = integer.isLessThanZero
let isLessThanZero = integer.isLessThanZero
return NBK.withUnsafeTemporaryAllocation(copying: integer.magnitude.words) {
self.encode(minus: isLessThanZero, magnitude: &$0)
NBK.IntegerDescription.encode(
magnitude: &$0,
solution: solution as AnyRadixSolution<UInt>,
alphabet: alphabet as MaxRadixAlphabetEncoder,
minus: isLessThanZero as Bool)
}
}

@inlinable public func encode(sign: FloatingPointSign, magnitude: some RandomAccessCollection<UInt>) -> String {
let isLessThanZero: Bool = (sign == FloatingPointSign.minus) && !magnitude.allSatisfy({ $0.isZero })
return NBK.withUnsafeTemporaryAllocation(copying: magnitude) {
self.encode(minus: isLessThanZero, magnitude: &$0)
@inlinable public func encode(_ components: SM<some NBKUnsignedInteger>) -> String {
let isLessThanZero = NBK.ISM.isLessThanZero(components)
return NBK.withUnsafeTemporaryAllocation(copying: components.magnitude.words) {
NBK.IntegerDescription.encode(
magnitude: &$0,
solution: solution as AnyRadixSolution<UInt>,
alphabet: alphabet as MaxRadixAlphabetEncoder,
minus: isLessThanZero as Bool)
}
}

//=--------------------------------------------------------------------=
// MARK: Utilities x Private
//=--------------------------------------------------------------------=

/// ### Development
///
/// - `@inlinable` is not required (nongeneric algorithm).
///
@usableFromInline func encode(minus: Bool, magnitude: inout NBK.UnsafeMutableWords) -> String {
NBK.IntegerDescription.withUnsafeTemporarySignPrefix(minus: minus) { prefix in
@_disfavoredOverload @inlinable public func encode(_ components: SM<some RandomAccessCollection<UInt>>) -> String {
let isLessThanZero = NBK.SSMSS.isLessThanZero(components)
return NBK.withUnsafeTemporaryAllocation(copying: components.magnitude) {
NBK.IntegerDescription.encode(
magnitude: &magnitude,
magnitude: &$0,
solution: solution as AnyRadixSolution<UInt>,
alphabet: alphabet as MaxRadixAlphabetEncoder,
prefix: prefix as NBK.UnsafeUTF8,
suffix: NBK.UnsafeUTF8(start: nil, count: 0 as Int))
minus: isLessThanZero as Bool)
}
}
}
Expand All @@ -99,6 +99,29 @@ extension NBK.IntegerDescription {
// MARK: Utilities
//=------------------------------------------------------------------------=

/// Encodes the magnitude, with or without a minus sign, using the given UTF-8 format.
///
/// ### Development
///
/// - `@inlinable` is not required (nongeneric algorithm).
///
@usableFromInline static func encode(
magnitude: inout NBK.UnsafeMutableWords, solution: AnyRadixSolution<UInt>, alphabet: MaxRadixAlphabetEncoder,
minus: Bool) -> String {
NBK.IntegerDescription.withUnsafeTemporarySignPrefix(minus: minus) { prefix in
NBK.IntegerDescription.encode(
magnitude: &magnitude,
solution: solution as AnyRadixSolution<UInt>,
alphabet: alphabet as MaxRadixAlphabetEncoder,
prefix: prefix as NBK.UnsafeUTF8,
suffix: NBK.UnsafeUTF8(start: nil, count: 0 as Int))
}
}

//=------------------------------------------------------------------------=
// MARK: Utilities
//=------------------------------------------------------------------------=

@inlinable static func encode(
magnitude: inout NBK.UnsafeMutableWords, solution: AnyRadixSolution<UInt>, alphabet: MaxRadixAlphabetEncoder,
prefix: NBK.UnsafeUTF8, suffix: NBK.UnsafeUTF8) -> String {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,36 @@
//=----------------------------------------------------------------------------=

//*============================================================================*
// MARK: * NBK x Sign & Magnitude x Comparisons
// MARK: * NBK x Integer Sign Magnitude x Comparisons
//*============================================================================*

extension NBK.SignAndMagnitude {
extension NBK.IntegerSignMagnitude {

//=------------------------------------------------------------------------=
// MARK: Utilities
//=------------------------------------------------------------------------=

/// Returns whether `components` is less than `zero`.
@inlinable public static func isLessThanZero(_ components: Components) -> Bool {
components.sign == Sign.minus && !components.magnitude.isZero
}

/// Returns whether `components` is more than `zero`.
@inlinable public static func isMoreThanZero(_ components: Components) -> Bool {
components.sign == Sign.plus && !components.magnitude.isZero
}

/// A three-way comparison of `components` against `zero`.
@inlinable public static func signum(_ components: Components) -> Int {
components.magnitude.isZero ? 0 : components.sign == Sign.plus ? 1 : -1
}
}

//=----------------------------------------------------------------------------=
// MARK: + Composition
//=----------------------------------------------------------------------------=

extension NBK.IntegerSignMagnitude {

//=------------------------------------------------------------------------=
// MARK: Utilities
Expand All @@ -26,7 +52,7 @@ extension NBK.SignAndMagnitude {
/// - Returns: One of the following values: -1 (less), 0 (same), or 1 (more).
///
@inlinable public static func compare<Other: NBKUnsignedInteger>(
_ lhs: Components, to rhs: NBK.SignAndMagnitude<Other>.Components, using compare: (Magnitude, Other) -> Int) -> Int {
_ lhs: Components, to rhs: NBK.IntegerSignMagnitude<Other>.Components, using compare: (Magnitude, Other) -> Int) -> Int {
let absoluteValue: Int

if lhs.sign == rhs.sign {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@
//=----------------------------------------------------------------------------=

//*============================================================================*
// MARK: * NBK x Sign & Magnitude
// MARK: * NBK x Integer Sign Magnitude
//*============================================================================*

extension NBK {

/// A namespace for sign and magnitude algorithms.
@frozen public enum SignAndMagnitude<Magnitude> where Magnitude: NBKUnsignedInteger {
/// A namespace for integer sign-magnitude algorithms.
@frozen public enum IntegerSignMagnitude<Magnitude> where Magnitude: NBKUnsignedInteger {

/// The sign and of this type.
public typealias Sign = NBK.Sign
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//=----------------------------------------------------------------------------=
// 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 Strict Sign Magnitude x Comparisons x Sub Sequence
//*============================================================================*

extension NBK.StrictSignMagnitude.SubSequence {

//=------------------------------------------------------------------------=
// MARK: Utilities
//=------------------------------------------------------------------------=

/// Returns whether `components` is less than `zero`.
@inlinable public static func isLessThanZero(_ components: Components) -> Bool {
components.sign == Sign.minus && !components.magnitude.allSatisfy({ $0.isZero })
}

/// Returns whether `components` is more than `zero`.
@inlinable public static func isMoreThanZero(_ components: Components) -> Bool {
components.sign == Sign.plus && !components.magnitude.allSatisfy({ $0.isZero })
}

/// A three-way comparison of `components` against `zero`.
@inlinable public static func signum(_ components: Components) -> Int {
components.magnitude.allSatisfy({ $0.isZero }) ? 0 : components.sign == Sign.plus ? 1 : -1
}
}
53 changes: 53 additions & 0 deletions Sources/NBKCoreKit/Private/NBKStrictSignMagnitude.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
//=----------------------------------------------------------------------------=
// This source file is part of the Numberick open source project.
//
// Copyright (c) 2023 Oscar Byström Ericsson
// Licensed under Apache License, Version 2.0
//
// See http://www.apache.org/licenses/LICENSE-2.0 for license information.
//=----------------------------------------------------------------------------=

//*============================================================================*
// MARK: * NBK x Strict Sign Magnitude
//*============================================================================*

extension NBK {

/// A namespace for strict sign-magnitude algorithms.
///
/// The `base` must be `nonempty` at the start and end of each access.
///
/// ```swift
/// static func algorithm(_ base: inout Base, input: Input) -> Output
/// ```
///
/// ### Development
///
/// Remaking this as a view when Swift gets view types might be neat.
///
@frozen public enum StrictSignMagnitude<Base> where Base: RandomAccessCollection, Base.Element: NBKCoreInteger & NBKUnsignedInteger {

/// The sign and of this type.
public typealias Sign = NBK.Sign

/// The sign and a magnitude of this type.
public typealias Components = SM<Base>

//*====================================================================*
// MARK: * Sub Sequence
//*====================================================================*

/// The sub sequence namespace of this type.
///
/// The `base` may be `empty` at the start and end of each access.
///
@frozen public enum SubSequence {

/// The sign and of this type.
public typealias Sign = NBK.Sign

/// The sign and a magnitude of this type.
public typealias Components = SM<Base>
}
}
}
Loading

0 comments on commit 1081daa

Please sign in to comment.