Skip to content

Commit

Permalink
[NBKCoreKit] Modular multiplicative inverse.
Browse files Browse the repository at this point in the history
  • Loading branch information
oscbyspro committed Oct 31, 2023
1 parent 99262f5 commit 9ea179f
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,16 @@ extension NBK.ProperBinaryInteger {
///
/// - Returns: A value from `0` to `modulus` or `nil`.
///
@inlinable public static func modularMultiplicativeInverse(of integer: Integer, mod modulus: Integer) -> Integer? {
@inlinable public static func modularMultiplicativeInverse(of lhs: Integer, mod rhs: Integer) -> Integer? {
//=--------------------------------------=
let lhsIsLessThanZero = integer.isLessThanZero
let rhsIsLessThanZero = modulus.isLessThanZero
let lhsIsLessThanZero = lhs.isLessThanZero
let rhsIsLessThanZero = rhs.isLessThanZero
//=--------------------------------------=
if rhsIsLessThanZero { return nil }
//=--------------------------------------=
guard let unsigned = Magnitude.modularMultiplicativeInverse(of: integer.magnitude, mod: modulus.magnitude) else { return nil }
//=--------------------------------------=
var inverse = Integer(sign: NBK.sign(lhsIsLessThanZero), magnitude: unsigned)!
if inverse.isLessThanZero { inverse += modulus }
return inverse as Integer as Integer as Integer
guard let magnitude = Magnitude.modularMultiplicativeInverse(
sign: NBK.sign(lhsIsLessThanZero), magnitude: lhs.magnitude, mod: rhs.magnitude) else { return nil }
return Integer(sign: NBK.Sign.plus, magnitude: magnitude)!
}
}

Expand All @@ -46,23 +44,24 @@ extension NBK.ProperBinaryInteger where Integer: NBKUnsignedInteger {
// MARK: Utilities
//=------------------------------------------------------------------------=

/// Returns the modular multiplicative inverse of `integer` modulo `modulus`, if it exists.
/// Returns the modular multiplicative inverse of `sign` and `magnitude` modulo `modulus`, if it exists.
///
/// - Returns: A value from `0` to `modulus` or `nil`.
///
@inlinable public static func modularMultiplicativeInverse(of integer: Integer, mod modulus: Integer) -> Integer? {
@inlinable public static func modularMultiplicativeInverse(sign: NBK.Sign, magnitude: Integer, mod modulus: Integer) -> Integer? {
//=--------------------------------------=
switch modulus.compared(to: 1 as Integer.Digit) {
case 1: break;
case 0: return Integer.zero
default: return nil }
//=--------------------------------------=
let extended = self.greatestCommonDivisorByEuclideanAlgorithm10(of: integer, and: modulus)
let extended = self.greatestCommonDivisorByEuclideanAlgorithm10(of: magnitude, and: modulus)
//=--------------------------------------=
guard extended.result.compared(to: 1 as Integer.Digit).isZero else {
return nil // the arguments must be coprime
}
//=--------------------------------------=
return extended.iteration.isOdd ? modulus - extended.lhsCoefficient : extended.lhsCoefficient
Swift.assert(extended.lhsCoefficient.isMoreThanZero)
return (sign == .minus) == extended.iteration.isEven ? modulus - extended.lhsCoefficient : extended.lhsCoefficient
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//=----------------------------------------------------------------------------=
// 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.
//=----------------------------------------------------------------------------=

#if !DEBUG

import NBKCoreKit
import XCTest

private typealias W = [UInt]
private typealias X = [UInt64]
private typealias Y = [UInt32]

//*============================================================================*
// MARK: * NBK x Proper Binary Integer x Modular Multiplicative Inverse
//*============================================================================*

final class NBKProperBinaryIntegerBenchmarksOnModularMultiplicativeInverse: XCTestCase {

typealias T = NBK.PBI

//=------------------------------------------------------------------------=
// MARK: Tests x Binary Algorithm
//=------------------------------------------------------------------------=

func testInt8s() {
for _ in 0 ..< 50 {
for lhs in Int8.min ... Int8.max {
for rhs in Int8.min ... Int8.max {
NBK.blackHole(T.modularMultiplicativeInverse(of: lhs, mod: rhs))
}
}
}
}

func testUInt8s() {
for _ in 0 ..< 50 {
for lhs in UInt8.min ... UInt8.max {
for rhs in UInt8.min ... UInt8.max {
NBK.blackHole(T.modularMultiplicativeInverse(of: lhs, mod: rhs))
}
}
}
}
}

#endif

0 comments on commit 9ea179f

Please sign in to comment.