Skip to content

Commit 3d203d6

Browse files
committed
add warmup round to get more accurate performance results, inline enum
1 parent 238281f commit 3d203d6

File tree

2 files changed

+71
-83
lines changed

2 files changed

+71
-83
lines changed

src/main/java/de/tilman_neumann/jml/factor/TestMode.java

-30
This file was deleted.

src/test/java/de/tilman_neumann/jml/factor/FactorizerTest.java

+71-53
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,19 @@
4848

4949
/**
5050
* Main class to compare the performance of factor algorithms.
51+
*
52+
* Does one warmup-round and a System.gc() before each algorithm is tested.
53+
*
5154
* @author Tilman Neumann
5255
*/
53-
// TODO Is there a better name for this class? It is no unit test, but no simple performance test either, it also checks correctness...
54-
// Suggenstions: FactorizerPerformanceTest, FactorizerComparator, FactorizerTestRunner, ...
5556
@SuppressWarnings("unused") // suppress warnings on unused imports
5657
public class FactorizerTest {
58+
59+
private enum TestMode {
60+
FIRST_FACTOR,
61+
PRIME_FACTORIZATION
62+
}
63+
5764
private static final Logger LOG = LogManager.getLogger(FactorizerTest.class);
5865

5966
private static final boolean DEBUG = false;
@@ -119,10 +126,13 @@ public FactorizerTest() {
119126
//new PollardRhoBrentMontgomery64(),
120127
//new PollardRhoBrentMontgomery64MH(),
121128
//new PollardRhoBrentMontgomery64MHInlined(),
122-
129+
123130
//new PollardRho(),
124131
//new PollardRhoProductGcd(),
132+
//new PollardRhoTwoLoops(),
133+
//new PollardRhoTwoLoopsModBlock(),
125134
//new PollardRhoBrent(),
135+
//new PollardRhoBrentModBlock(),
126136

127137
// SquFoF variants
128138
// * pretty good, but never the best algorithm
@@ -212,7 +222,7 @@ private void testRange(int bits) {
212222

213223
// take REPEATS timings for each algorithm to be quite sure that one timing is not falsified by garbage collection
214224
TreeMap<Long, List<FactorAlgorithm>> ms_2_algorithms = new TreeMap<Long, List<FactorAlgorithm>>();
215-
for (int i=0; i<REPEATS; i++) {
225+
for (int i=0; i < REPEATS + 1; i++) { // round 0 is a warmup-round
216226
for (FactorAlgorithm algorithm : algorithms) {
217227
// exclude special size implementations
218228
String algName = algorithm.getName();
@@ -225,8 +235,8 @@ private void testRange(int bits) {
225235
if (bits>42 && algName.startsWith("TDiv63Inverse")) continue; // not enough primes stored
226236
if (bits>52 && algName.startsWith("SquFoF31")) continue; // int implementation
227237
if (bits>57 && algName.equals("PollardRhoBrentMontgomeryR64Mul63")) continue; // very slow above
228-
if (bits>59 && algName.startsWith("Lehman")) continue; // TODO make it work again for 60 bit?
229-
if (bits>63 && algName.startsWith("PollardRhoBrentMontgomery64")) continue; // long implementation
238+
if (bits>59 && algName.startsWith("Lehman")) continue;
239+
if (bits>62 && algName.startsWith("PollardRhoBrentMontgomery64")) continue; // long implementation
230240
if (bits>98 && algName.startsWith("CFrac63")) continue; // unstable for N>98 bits
231241
if (bits<54 && algName.startsWith("SIQS")) continue; // unstable for smaller N
232242
if (bits<57 && algName.startsWith("PSIQS")) continue; // unstable for smaller N
@@ -251,16 +261,18 @@ private void testRange(int bits) {
251261
duration = endTimeMillis - startTimeMillis; // duration in ms
252262
//LOG.debug("algorithm " + algName + " finished test set with " + bits + " bits");
253263

254-
// test correctness
255-
for (int j=0; j<N_COUNT; j++) {
256-
BigInteger N = testNumbers[j];
257-
BigInteger factor = factors[j];
258-
if (factor==null || factor.equals(I_0) || factor.abs().equals(I_1) || factor.abs().equals(N.abs())) {
259-
if (loggedFailCount++<10) LOG.error("FactorAlgorithm " + algorithm.getName() + " did not find a factor of N=" + N + ", it returned " + factor);
260-
failCount++;
261-
} else if (!N.mod(factor).equals(I_0)) {
262-
if (loggedFailCount++<10) LOG.error("FactorAlgorithm " + algorithm.getName() + " returned " + factor + ", but this is not a factor of N=" + N);
263-
failCount++;
264+
if (i==0) {
265+
// test correctness
266+
for (int j=0; j<N_COUNT; j++) {
267+
BigInteger N = testNumbers[j];
268+
BigInteger factor = factors[j];
269+
if (factor==null || factor.equals(I_0) || factor.abs().equals(I_1) || factor.abs().equals(N.abs())) {
270+
if (loggedFailCount++<10) LOG.error("FactorAlgorithm " + algorithm.getName() + " did not find a factor of N=" + N + ", it returned " + factor);
271+
failCount++;
272+
} else if (!N.mod(factor).equals(I_0)) {
273+
if (loggedFailCount++<10) LOG.error("FactorAlgorithm " + algorithm.getName() + " returned " + factor + ", but this is not a factor of N=" + N);
274+
failCount++;
275+
}
264276
}
265277
}
266278
break;
@@ -280,37 +292,39 @@ private void testRange(int bits) {
280292
duration = endTimeMillis - startTimeMillis; // duration in ms
281293
//LOG.debug("algorithm " + algName + " finished test set with " + bits + " bits");
282294

283-
// test correctness
284-
for (int j=0; j<N_COUNT; j++) {
285-
BigInteger N = testNumbers[j];
286-
SortedMultiset<BigInteger> factorSet = factorSetArray[j];
287-
if (factorSet==null || factorSet.size()==0) {
288-
if (loggedFailCount++<10) LOG.error("FactorAlgorithm " + algorithm.getName() + " did not find any factor of N=" + N + ", it returned " + factorSet);
289-
failCount++;
290-
} else {
291-
BigInteger product = I_1;
292-
ArrayList<BigInteger> nonFactors = new ArrayList<>();
293-
ArrayList<BigInteger> nonPrimeFactors = new ArrayList<>();
294-
for (BigInteger factor : factorSet.keySet()) {
295-
if (factor==null || factor.equals(I_0) || factor.abs().equals(I_1) || factor.abs().equals(N.abs()) || !N.mod(factor).equals(I_0)) {
296-
nonFactors.add(factor);
297-
} else if (!bpsw.isProbablePrime(factor)) {
298-
// not finding the prime factorization is an error
299-
nonPrimeFactors.add(factor);
295+
if (i==0) {
296+
// test correctness
297+
for (int j=0; j<N_COUNT; j++) {
298+
BigInteger N = testNumbers[j];
299+
SortedMultiset<BigInteger> factorSet = factorSetArray[j];
300+
if (factorSet==null || factorSet.size()==0) {
301+
if (loggedFailCount++<10) LOG.error("FactorAlgorithm " + algorithm.getName() + " did not find any factor of N=" + N + ", it returned " + factorSet);
302+
failCount++;
303+
} else {
304+
BigInteger product = I_1;
305+
ArrayList<BigInteger> nonFactors = new ArrayList<>();
306+
ArrayList<BigInteger> nonPrimeFactors = new ArrayList<>();
307+
for (BigInteger factor : factorSet.keySet()) {
308+
if (factor==null || factor.equals(I_0) || factor.abs().equals(I_1) || factor.abs().equals(N.abs()) || !N.mod(factor).equals(I_0)) {
309+
nonFactors.add(factor);
310+
} else if (!bpsw.isProbablePrime(factor)) {
311+
// not finding the prime factorization is an error
312+
nonPrimeFactors.add(factor);
313+
}
314+
int exp = factorSet.get(factor);
315+
BigInteger pow = factor.pow(exp);
316+
product = product.multiply(pow);
300317
}
301-
int exp = factorSet.get(factor);
302-
BigInteger pow = factor.pow(exp);
303-
product = product.multiply(pow);
304-
}
305-
if (nonFactors.size()>0 || nonPrimeFactors.size()>0 || !N.equals(product)) {
306-
if (loggedFailCount++<10) {
307-
String msg = "FactorAlgorithm " + algorithm.getName() + " falsely returned N=" + N + " = " + factorSet + ":";
308-
if (nonFactors.size()>0) msg += " " + nonFactors + " are not factors of N.";
309-
if (nonPrimeFactors.size()>0) msg += " The found factors " + nonPrimeFactors + " are not prime.";
310-
if (!N.equals(product)) msg += " The product of the returned factors is not N but " + product + ".";
311-
LOG.error(msg);
318+
if (nonFactors.size()>0 || nonPrimeFactors.size()>0 || !N.equals(product)) {
319+
if (loggedFailCount++<10) {
320+
String msg = "FactorAlgorithm " + algorithm.getName() + " falsely returned N=" + N + " = " + factorSet + ":";
321+
if (nonFactors.size()>0) msg += " " + nonFactors + " are not factors of N.";
322+
if (nonPrimeFactors.size()>0) msg += " The found factors " + nonPrimeFactors + " are not prime.";
323+
if (!N.equals(product)) msg += " The product of the returned factors is not N but " + product + ".";
324+
LOG.error(msg);
325+
}
326+
failCount++;
312327
}
313-
failCount++;
314328
}
315329
}
316330
}
@@ -319,15 +333,19 @@ private void testRange(int bits) {
319333
default: throw new IllegalArgumentException("TestMode = " + TEST_MODE);
320334
}
321335

322-
// performance results
323-
List<FactorAlgorithm> algList = ms_2_algorithms.get(duration);
324-
if (algList==null) algList = new ArrayList<FactorAlgorithm>();
325-
algList.add(algorithm);
326-
ms_2_algorithms.put(duration, algList);
336+
if (i > 0) {
337+
// add performance results
338+
List<FactorAlgorithm> algList = ms_2_algorithms.get(duration);
339+
if (algList==null) algList = new ArrayList<FactorAlgorithm>();
340+
algList.add(algorithm);
341+
ms_2_algorithms.put(duration, algList);
342+
}
327343

328-
// failure summary
329-
if (failCount>0) {
330-
LOG.error("FactorAlgorithm " + algorithm.getName() + " failed at " + failCount + "/" + N_COUNT + " test numbers");
344+
if (i==0) {
345+
// failure summary
346+
if (failCount>0) {
347+
LOG.error("FactorAlgorithm " + algorithm.getName() + " failed at " + failCount + "/" + N_COUNT + " test numbers");
348+
}
331349
}
332350
}
333351
}

0 commit comments

Comments
 (0)