Implement naive multithreaded prime generator
This commit is contained in:
parent
3a5d001e15
commit
05b8cfa9bc
4
.idea/encodings.xml
Normal file
4
.idea/encodings.xml
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding" addBOMForNewFiles="with NO BOM" />
|
||||
</project>
|
6
.idea/misc.xml
Normal file
6
.idea/misc.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
8
.idea/modules.xml
Normal file
8
.idea/modules.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/RSA.iml" filepath="$PROJECT_DIR$/RSA.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
6
.idea/vcs.xml
Normal file
6
.idea/vcs.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
11
RSA.iml
Normal file
11
RSA.iml
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
9
src/Main.java
Normal file
9
src/Main.java
Normal file
@ -0,0 +1,9 @@
|
||||
import java.math.BigInteger;
|
||||
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
BigInteger prime = Prime.generate(32);
|
||||
System.out.println("Finished - number is "+prime);
|
||||
|
||||
}
|
||||
}
|
132
src/Prime.java
Normal file
132
src/Prime.java
Normal file
@ -0,0 +1,132 @@
|
||||
import java.math.BigInteger;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
public class Prime {
|
||||
/**
|
||||
* Calculates the integer square root of a number.
|
||||
* Source: https://stackoverflow.com/questions/4407839/how-can-i-find-the-square-root-of-a-java-biginteger/13023513#13023513
|
||||
*
|
||||
* @param x the number
|
||||
* @return the square root
|
||||
*/
|
||||
private static BigInteger sqrt(BigInteger x) {
|
||||
BigInteger div = BigInteger.ZERO.setBit(x.bitLength()/2);
|
||||
BigInteger div2 = div;
|
||||
// Loop until we hit the same value twice in a row, or wind
|
||||
// up alternating.
|
||||
for(;;) {
|
||||
BigInteger y = div.add(x.divide(div)).shiftRight(1);
|
||||
if (y.equals(div) || y.equals(div2))
|
||||
return y;
|
||||
div2 = div;
|
||||
div = y;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks, whether a number is a prime or not. Uses naive implementation accelerated by multithreading.
|
||||
*
|
||||
* @param candidate the number to check
|
||||
* @return the boolean
|
||||
*/
|
||||
private static boolean isPrime(BigInteger candidate) {
|
||||
// Check special candidate values 0, 1, 2 and even
|
||||
if (candidate.compareTo(BigInteger.ZERO) == 0 // candidate == 0
|
||||
|| candidate.compareTo(BigInteger.ONE) == 0) { // candidate == 1)
|
||||
return false;
|
||||
}
|
||||
if (candidate.compareTo(BigInteger.valueOf(2)) == 0) { // candidate == 2
|
||||
return true;
|
||||
} else if (candidate.mod(BigInteger.valueOf(2)).equals(BigInteger.ZERO)) { // candidate is even
|
||||
return false;
|
||||
}
|
||||
|
||||
// Divide interval into segments, one for each cpu core
|
||||
int cores = Runtime.getRuntime().availableProcessors();
|
||||
|
||||
BigInteger max = sqrt(candidate).add(BigInteger.ONE);
|
||||
BigInteger min = BigInteger.valueOf(3);
|
||||
BigInteger step = max.subtract(min).divide(BigInteger.valueOf(cores));
|
||||
BigInteger remainder = max.subtract(min).mod(BigInteger.valueOf(cores));
|
||||
|
||||
int i = 0;
|
||||
List<Worker> workers = new LinkedList<>();
|
||||
while (i < cores) {
|
||||
BigInteger num = step;
|
||||
if (remainder.compareTo(BigInteger.ZERO) == 1) { // remainder > 0
|
||||
num = num.add(BigInteger.ONE);
|
||||
remainder = remainder.subtract(BigInteger.ONE);
|
||||
}
|
||||
num = num.subtract(BigInteger.ONE);
|
||||
if (num.compareTo(BigInteger.ZERO) >= 0) {
|
||||
workers.add(new Worker(candidate, min, min.add(num), "Thread " + i));
|
||||
workers.get(i).start();
|
||||
min = min.add(num).add(BigInteger.ONE);
|
||||
}
|
||||
|
||||
i++;
|
||||
if (min.compareTo(max) > 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Wait for workers to complete
|
||||
boolean stop = false;
|
||||
boolean isPrime = true;
|
||||
|
||||
while (!stop) {
|
||||
i = 0;
|
||||
while (i < workers.size()) {
|
||||
Worker w = workers.get(i);
|
||||
try {
|
||||
w.join(500);
|
||||
} catch (InterruptedException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
if (w.hasFinished()) {
|
||||
if (!w.isPrime()) {
|
||||
isPrime = false;
|
||||
stop = true;
|
||||
break;
|
||||
} else {
|
||||
// This worker is done, remove it from the list
|
||||
workers.remove(w);
|
||||
if (workers.isEmpty()) {
|
||||
stop = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
// Stop workers
|
||||
for (Worker w: workers) {
|
||||
w.interrupt();
|
||||
}
|
||||
|
||||
return isPrime;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates a guaranteed prime of the given length.
|
||||
*
|
||||
* @param bits binary length of the prime to generate
|
||||
* @return prime number
|
||||
*/
|
||||
public static BigInteger generate(int bits) {
|
||||
Random rng = new Random();
|
||||
BigInteger candidate = new BigInteger(bits, rng);
|
||||
int i = 0;
|
||||
while (!isPrime(candidate)){
|
||||
//System.out.println("Not a prime: " + candidate);
|
||||
candidate = new BigInteger(bits, rng);
|
||||
i++;
|
||||
}
|
||||
//System.out.println("Found prime after " + i + " tries: " + candidate);
|
||||
return candidate;
|
||||
}
|
||||
}
|
28
src/RSA.java
Normal file
28
src/RSA.java
Normal file
@ -0,0 +1,28 @@
|
||||
public class RSA {
|
||||
// p = 5, q = 11
|
||||
// RSA-Modul N = p * q = 55
|
||||
// Phi(N) = Phi(p)*Phi(q) | weil eigenschaft eulersche phi funktion und p,q teilerfremd
|
||||
// = (p-1)*(q-1) | p,q primzahlen, daher nur durch 1 und sich selbst teilbar und alle anderen teilerfremd
|
||||
// = 4*10 = 40
|
||||
// e: 1 < e < Phi(N) und ggT(e, Phi(N)) = 1
|
||||
// e elem aus {3,..} => e = 3
|
||||
// (e,N) = (3, 55) public key
|
||||
// -----
|
||||
// d: e*d kongr 1 mod Phi(N) => e*d mod Phi(N) = 1
|
||||
// 3*d mod 40 = 1
|
||||
// Durch probieren: d=27 => (27, 55) private key
|
||||
//
|
||||
// ----
|
||||
// Verschlüsseln
|
||||
// 13
|
||||
// c = m^e (mod N) => 13^3 (mod 55) = 52 = c
|
||||
// ----
|
||||
// Entschlüsseln
|
||||
// m = c^d (mod N) => 52^27 (mod 55) = 13 = m
|
||||
public RSA() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
58
src/Worker.java
Normal file
58
src/Worker.java
Normal file
@ -0,0 +1,58 @@
|
||||
import java.math.BigInteger;
|
||||
|
||||
/**
|
||||
* Worker class used in multithreading to check, whether a given number is a prime.
|
||||
*/
|
||||
public class Worker extends Thread {
|
||||
private boolean isPrime;
|
||||
private BigInteger minVal;
|
||||
private BigInteger maxVal;
|
||||
private BigInteger candidate;
|
||||
private boolean finished = false;
|
||||
private String threadName ;
|
||||
|
||||
public Worker(BigInteger candidate, BigInteger min, BigInteger max, String threadName) {
|
||||
this.minVal = min;
|
||||
this.maxVal = max;
|
||||
this.candidate = candidate;
|
||||
this.isPrime = true;
|
||||
this.threadName = threadName;
|
||||
//System.out.println("Created "+threadName+" for "+min+"-"+max+"");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a flag, indicating whether the prime candidate has a divisor in the given interval.
|
||||
* Since the thread might be still be running, it is important to check it first by using the
|
||||
* hasFinished() method.
|
||||
*
|
||||
* @return flag indicating whether there is a divisor or not
|
||||
*/
|
||||
public boolean isPrime() {
|
||||
return this.isPrime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if the thread has finished checking the given interval.
|
||||
*
|
||||
* @return the boolean
|
||||
*/
|
||||
public boolean hasFinished() { return this.finished; }
|
||||
|
||||
public void run() {
|
||||
BigInteger divCandidate = minVal;
|
||||
if (divCandidate.mod(BigInteger.valueOf(2)).equals(BigInteger.ZERO)){
|
||||
divCandidate = divCandidate.add(BigInteger.ONE);
|
||||
}
|
||||
while (divCandidate.compareTo(maxVal) < 1){ //divCandidate <= maxVal
|
||||
//System.out.println(this.threadName + " is testing "+divCandidate);
|
||||
if (candidate.mod(divCandidate).equals(BigInteger.ZERO)) {
|
||||
this.isPrime = false;
|
||||
this.finished = true;
|
||||
return;
|
||||
}
|
||||
divCandidate = divCandidate.add(BigInteger.ONE).add(BigInteger.ONE);
|
||||
}
|
||||
this.finished = true;
|
||||
// No divisor found, we are done for this interval
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user