Skip to content

Commit

Permalink
[NBKCoreKit] Long division algorithm.
Browse files Browse the repository at this point in the history
  • Loading branch information
oscbyspro committed Oct 19, 2023
1 parent f7a9071 commit 76e5fbc
Showing 1 changed file with 76 additions and 0 deletions.
76 changes: 76 additions & 0 deletions Sources/NBKCoreKit/Private/NBKStrictUnsignedInteger+Division.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,82 @@
// See http://www.apache.org/licenses/LICENSE-2.0 for license information.
//=----------------------------------------------------------------------------=

//*============================================================================*
// MARK: * NBK x Strict Unsigned Integer x Division
//*============================================================================*
//=----------------------------------------------------------------------------=
// MARK: + Long Division Algorithms
//=----------------------------------------------------------------------------=

extension NBK.StrictUnsignedInteger where Base: MutableCollection {

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

/// Returns the `quotient` element of one long division iteration, then subtracts
/// the product of `divisor` and `quotient` from the `remainder` at the `quotient`
/// element's index (which must match the `remainder`'s start index).
///
/// - Parameters:
/// - remainder: The `remainder` suffix from the `quotient` element's index.
/// It must be exactly one element wider than the `divisor`.
/// - divisor: The normalized `divisor`. Its last element's most significant
/// bit must be set to ensure that the initial `quotient` approximation will
/// exceed the real `quotient` by at most 2.
///
/// - Returns: The `quotient` element at the `remainder`'s start index.
///
/// ## Example Usage in Long Division Algorithm
///
/// ```swift
/// // use fast path
/// // normalization
///
/// var quotient = uninitialized(remainder.count - divisor.count) { quotient in
/// for index in quotient.indices.reversed() {
/// let digit = quotientFromLongDivisionIteration2111MSBUnchecked(
/// dividing: &remainder[index ..< index + divisor.count + 1], by: divisor)
/// quotient.baseAddress!.advanced(by: index).initialize(to: digit)
/// }
/// }
///
/// // normalization
/// // return values
/// ```
///
@inlinable public static func quotientFromLongDivisionIteration2111MSBUnchecked(
dividing remainder: inout Base, by divisor: some RandomAccessCollection<Base.Element>) -> Base.Element {
//=--------------------------------------=
Swift.assert(divisor.last!.mostSignificantBit,
"the divisor must be normalized")

Swift.assert(remainder.count == divisor.count + 1,
"the remainder must be exactly one element wider than the divisor")
//=--------------------------------------=
let numerator = NBK.TBI<Base.Element>.suffix2(remainder)
let denominator = NBK.TBI<Base.Element>.suffix1((divisor))
//=--------------------------------------=
var quotient : Base.Element; if denominator == numerator.high { // await Swift 5.9
quotient = Base.Element.max
} else {
quotient = denominator.dividingFullWidth(numerator).quotient
}
//=--------------------------------------=
if quotient.isZero { return quotient }
//=--------------------------------------=
var overflow = (NBK).SUISS.decrement(&remainder, by: divisor, times: quotient).overflow

decrementQuotientAtMostTwice: while overflow {
quotient = quotient &- 1 as Base.Element
overflow = !NBK .SUISS.increment(&remainder, by: divisor).overflow
}

Swift.assert(NBK.SUISS.compare(remainder, to: divisor).isLessThanZero)
return quotient as Base.Element
}
}

//*============================================================================*
// MARK: * NBK x Strict Unsigned Integer x Division x Sub Sequence
//*============================================================================*
Expand Down

0 comments on commit 76e5fbc

Please sign in to comment.