forked from kodecocodes/swift-algorithm-club
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request kodecocodes#819 from kayoslab/miller-rabin-primali…
…ty-test-code-improvement Extended Miller-Rabin Primality test [code]
- Loading branch information
Showing
6 changed files
with
209 additions
and
225 deletions.
There are no files selected for viewing
46 changes: 24 additions & 22 deletions
46
Miller-Rabin Primality Test/MRPrimality.playground/Contents.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 |
---|---|---|
@@ -1,24 +1,26 @@ | ||
//: Playground - noun: a place where people can play | ||
|
||
// Real primes | ||
mrPrimalityTest(5) | ||
mrPrimalityTest(439) | ||
mrPrimalityTest(1201) | ||
mrPrimalityTest(143477) | ||
mrPrimalityTest(1299869) | ||
mrPrimalityTest(15487361) | ||
mrPrimalityTest(179426363) | ||
mrPrimalityTest(32416187747) | ||
|
||
// Fake primes | ||
mrPrimalityTest(15) | ||
mrPrimalityTest(435) | ||
mrPrimalityTest(1207) | ||
mrPrimalityTest(143473) | ||
mrPrimalityTest(1291869) | ||
mrPrimalityTest(15487161) | ||
mrPrimalityTest(178426363) | ||
mrPrimalityTest(32415187747) | ||
|
||
// With iteration | ||
mrPrimalityTest(32416190071, iteration: 10) | ||
do { | ||
// Real primes | ||
try checkWithMillerRabin(5) | ||
try checkWithMillerRabin(439) | ||
try checkWithMillerRabin(1201) | ||
try checkWithMillerRabin(143477) | ||
try checkWithMillerRabin(1299869) | ||
try checkWithMillerRabin(15487361) | ||
try checkWithMillerRabin(179426363) | ||
|
||
// Fake primes | ||
try checkWithMillerRabin(15) | ||
try checkWithMillerRabin(435) | ||
try checkWithMillerRabin(1207) | ||
try checkWithMillerRabin(143473) | ||
try checkWithMillerRabin(1291869) | ||
try checkWithMillerRabin(15487161) | ||
try checkWithMillerRabin(178426363) | ||
|
||
// Specifying accuracy | ||
try checkWithMillerRabin(179426363, accuracy: 10) | ||
} catch { | ||
dump(error) | ||
} |
111 changes: 0 additions & 111 deletions
111
Miller-Rabin Primality Test/MRPrimality.playground/Sources/MRPrimality.swift
This file was deleted.
Oops, something went wrong.
100 changes: 100 additions & 0 deletions
100
Miller-Rabin Primality Test/MRPrimality.playground/Sources/MillerRabin.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,100 @@ | ||
// | ||
// MRPrimality.swift | ||
// | ||
// | ||
// Created by Sahn Cha on 2016. 10. 18.. | ||
// | ||
// | ||
|
||
import Foundation | ||
|
||
enum MillerRabinError: Error { | ||
case primeLowAccuracy | ||
case primeLowerBorder | ||
case uIntOverflow | ||
} | ||
|
||
/* | ||
The Miller–Rabin test relies on an equality or set of equalities that | ||
hold true for prime values, then checks whether or not they hold for | ||
a number that we want to test for primality. | ||
|
||
- Parameter n: an odd integer to be tested for primality; | ||
- Parameter k: a parameter that determines the accuracy of the test | ||
- throws: Can throw an error of type `MillerRabinError`. | ||
- Returns: composite if n is composite, otherwise probably prime | ||
*/ | ||
public func checkWithMillerRabin(_ n: UInt, accuracy k: UInt = 1) throws -> Bool { | ||
guard k > 0 else { throw MillerRabinError.primeLowAccuracy } | ||
guard n > 0 else { throw MillerRabinError.primeLowerBorder } | ||
guard n > 3 else { return true } | ||
|
||
// return false for all even numbers bigger than 2 | ||
if n % 2 == 0 { | ||
return false | ||
} | ||
|
||
let s: UInt = UInt((n - 1).trailingZeroBitCount) | ||
let d: UInt = (n - 1) >> s | ||
|
||
guard UInt(pow(2.0, Double(s))) * d == n - 1 else { throw MillerRabinError.primeLowerBorder } | ||
|
||
/// Inspect whether a given witness will reveal the true identity of n. | ||
func tryComposite(_ a: UInt, d: UInt, n: UInt) throws -> Bool? { | ||
var x = try calculateModularExponentiation(base: a, exponent: d, modulus: n) | ||
if x == 1 || x == (n - 1) { | ||
return nil | ||
} | ||
for _ in 1..<s { | ||
x = try calculateModularExponentiation(base: x, exponent: 2, modulus: n) | ||
if x == 1 { | ||
return false | ||
} else if x == (n - 1) { | ||
return nil | ||
} | ||
} | ||
return false | ||
} | ||
|
||
for _ in 0..<k { | ||
let a = UInt.random(in: 2..<n-2) | ||
if let composite = try tryComposite(a, d: d, n: n) { | ||
return composite | ||
} | ||
} | ||
|
||
return true | ||
} | ||
|
||
/* | ||
Calculates the modular exponentiation based on `Applied Cryptography by Bruce Schneier.` | ||
in `Schneier, Bruce (1996). Applied Cryptography: Protocols, Algorithms, | ||
and Source Code in C, Second Edition (2nd ed.). Wiley. ISBN 978-0-471-11709-4.` | ||
|
||
- Parameter base: The natural base b. | ||
- Parameter base: The natural exponent e. | ||
- Parameter base: The natural modulus m. | ||
- Throws: Can throw a `uIntOverflow` if the modulus' square exceeds the memory | ||
limitations of UInt on the current system. | ||
- Returns: The modular exponentiation c. | ||
*/ | ||
private func calculateModularExponentiation(base: UInt, exponent: UInt, modulus: UInt) throws -> UInt { | ||
guard modulus > 1 else { return 0 } | ||
guard !(modulus-1).multipliedReportingOverflow(by: (modulus-1)).overflow else { | ||
throw MillerRabinError.uIntOverflow | ||
} | ||
|
||
var result: UInt = 1 | ||
var exponentCopy = exponent | ||
var baseCopy = base % modulus | ||
|
||
while exponentCopy > 0 { | ||
if exponentCopy % 2 == 1 { | ||
result = (result * baseCopy) % modulus | ||
} | ||
exponentCopy = exponentCopy >> 1 | ||
baseCopy = (baseCopy * baseCopy) % modulus | ||
} | ||
|
||
return result | ||
} |
3 changes: 3 additions & 0 deletions
3
...bin Primality Test/MRPrimality.playground/playground.xcworkspace/contents.xcworkspacedata
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Oops, something went wrong.