Skip to content

Commit

Permalink
[NBKCoreKit] Proper binary integer namespace (#85).
Browse files Browse the repository at this point in the history
  • Loading branch information
oscbyspro committed Oct 26, 2023
1 parent 5c76dfc commit a99f1b9
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 19 deletions.
21 changes: 21 additions & 0 deletions Sources/NBKCoreKit/Private/NBK.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,27 @@
// MARK: Namespaces x Binary Integer
//=------------------------------------------------------------------------=

/// A namespace for `Numberick` development.
///
/// - Warning: Do not use this namespace outside of `Numberick` development.
///
public typealias PBI<Integer> = NBK.ProperBinaryInteger<Integer>
where Integer: NBKBinaryInteger

/// A namespace for `Numberick` development.
///
/// - Warning: Do not use this namespace outside of `Numberick` development.
///
public typealias PSI<Integer> = NBK.ProperBinaryInteger<Integer>
where Integer: NBKBinaryInteger & NBKSignedInteger

/// A namespace for `Numberick` development.
///
/// - Warning: Do not use this namespace outside of `Numberick` development.
///
public typealias PUI<Integer> = NBK.ProperBinaryInteger<Integer>
where Integer: NBKBinaryInteger & NBKUnsignedInteger

/// A namespace for `Numberick` development.
///
/// - Warning: Do not use this namespace outside of `Numberick` development.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
//=----------------------------------------------------------------------------=

//*============================================================================*
// MARK: * NBK x Greatest Common Divisor
// MARK: * NBK x Proper Binary Integer x Greatest Common Divisor
//*============================================================================*

extension NBK {
extension NBK.ProperBinaryInteger {

//=------------------------------------------------------------------------=
// MARK: Utilities
Expand All @@ -21,28 +21,39 @@ extension NBK {
///
/// [algorithm]: https://en.wikipedia.org/wiki/binary_GCD_algorithm
///
@inlinable public static func greatestCommonDivisorByBinaryAlgorithm<T>(
of lhs: T, and rhs: T) -> T.Magnitude where T: NBKBinaryInteger {
self.greatestCommonDivisorByBinaryAlgorithm(of: lhs.magnitude, and: rhs.magnitude)
@inlinable public static func greatestCommonDivisorByBinaryAlgorithm(
of lhs: Integer, and rhs: Integer) -> Integer.Magnitude {
NBK.PUI.greatestCommonDivisorByBinaryAlgorithm(of: lhs.magnitude, and: rhs.magnitude)
}
}

//*============================================================================*
// MARK: * NBK x Proper Binary Integer x Greatest Common Divisor x Unsigned
//*============================================================================*

extension NBK.ProperBinaryInteger where Integer: NBKUnsignedInteger {

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

/// Finds the GCD of `lhs` and `rhs` by using [this binary algorithm][algorithm].
///
/// [algorithm]: https://en.wikipedia.org/wiki/binary_GCD_algorithm
///
/// - TODO: Use `bitShift(...)` methods if/when NBKBinaryInteger...
///
@inlinable public static func greatestCommonDivisorByBinaryAlgorithm<T>(
of lhs: T, and rhs: T) -> T where T: NBKUnsignedInteger {
@inlinable public static func greatestCommonDivisorByBinaryAlgorithm(
of lhs: Integer, and rhs: Integer) -> Integer {
//=--------------------------------------=
if rhs.isZero { return lhs }
if lhs.isZero { return rhs }
//=--------------------------------------=
let lhsShift: Int = lhs.trailingZeroBitCount
let rhsShift: Int = rhs.trailingZeroBitCount
let lhsShift = lhs.trailingZeroBitCount as Int
let rhsShift = rhs.trailingZeroBitCount as Int
//=--------------------------------------=
var lhs: T = lhs >> lhsShift
var rhs: T = rhs >> rhsShift
var lhs: Integer = lhs >> lhsShift
var rhs: Integer = rhs >> rhsShift

while lhs != rhs {
if lhs < rhs {
Expand All @@ -55,6 +66,6 @@ extension NBK {
}

lhs <<= Swift.min(lhsShift, rhsShift)
return lhs as T.Magnitude
return lhs as Integer.Magnitude
}
}
28 changes: 28 additions & 0 deletions Sources/NBKCoreKit/Private/NBKProperBinaryInteger.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//=----------------------------------------------------------------------------=
// 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 Proper Binary Integer
//*============================================================================*

extension NBK {

/// A namespace for proper binary integer algorithms.
///
/// - Note: Proper binary integer models conform to ``NBKBinaryInteger``.
///
@frozen public enum ProperBinaryInteger<Integer> where Integer: NBKBinaryInteger {

//*====================================================================*
// MARK: * Magnitude
//*====================================================================*

public typealias Magnitude = ProperBinaryInteger<Integer.Magnitude>
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ import NBKCoreKit
import XCTest

//*============================================================================*
// MARK: * NBK x Greatest Common Divisor
// MARK: * NBK x Proper Binary Integer x Greatest Common Divisor
//*============================================================================*

final class NBKTestsOnGreatestCommonDivisor: XCTestCase {
final class NBKProperBinaryIntegerTestsOnGreatestCommonDivisor: XCTestCase {

//=------------------------------------------------------------------------=
// MARK: Tests
Expand Down Expand Up @@ -84,20 +84,22 @@ final class NBKTestsOnGreatestCommonDivisor: XCTestCase {
}

//*============================================================================*
// MARK: * NBK x Greatest Common Divisor x Assertions
// MARK: * NBK x Proper Binary Integer x Greatest Common Divisor x Assertions
//*============================================================================*

private func NBKAssertGreatestCommonDivisor<T: NBKBinaryInteger>(
_ lhs: T, _ rhs: T, _ gcd: T.Magnitude,
file: StaticString = #file, line: UInt = #line) {
//=------------------------------------------=
let binary = NBK.ProperBinaryInteger<T>.greatestCommonDivisorByBinaryAlgorithm(of:and:)
//=------------------------------------------=
func with(_ lhs: T, _ rhs: T, _ gcd: T.Magnitude) {
brr: do {
XCTAssertEqual(NBK.greatestCommonDivisorByBinaryAlgorithm(of: 0 + lhs, and: 0 + rhs), gcd, file: file, line: line)
XCTAssertEqual(binary(0 + lhs, 0 + rhs), gcd, file: file, line: line)
}; if T.isSigned {
XCTAssertEqual(NBK.greatestCommonDivisorByBinaryAlgorithm(of: 0 + lhs, and: 0 - rhs), gcd, file: file, line: line)
XCTAssertEqual(NBK.greatestCommonDivisorByBinaryAlgorithm(of: 0 - lhs, and: 0 + rhs), gcd, file: file, line: line)
XCTAssertEqual(NBK.greatestCommonDivisorByBinaryAlgorithm(of: 0 - lhs, and: 0 - rhs), gcd, file: file, line: line)
XCTAssertEqual(binary(0 + lhs, 0 - rhs), gcd, file: file, line: line)
XCTAssertEqual(binary(0 - lhs, 0 + rhs), gcd, file: file, line: line)
XCTAssertEqual(binary(0 - lhs, 0 - rhs), gcd, file: file, line: line)
}
}
//=------------------------------------------=
Expand Down

0 comments on commit a99f1b9

Please sign in to comment.