Skip to content

Commit f9a3e53

Browse files
committed
use new small composites test for TDiv variants, fix error in TDiv63
1 parent 3b982fb commit f9a3e53

File tree

7 files changed

+608
-8
lines changed

7 files changed

+608
-8
lines changed

src/main/java/de/tilman_neumann/jml/factor/tdiv/TDiv63.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public TDiv63 setTestLimit(int pLimit) {
4949
public void factor(BigInteger Nbig, SortedMultiset<BigInteger> primeFactors) {
5050
long N = Nbig.longValue();
5151

52-
int i=1, p;
52+
int i=0, p;
5353
while ((p = SMALL_PRIMES.getPrime(i++)) <= pLimit) { // upper bound avoids positive int overflow
5454
if (N%p == 0) {
5555
int exp = 0;
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/*
2+
* java-math-library is a Java library focused on number theory, but not necessarily limited to it. It is based on the PSIQS 4.0 factoring project.
3+
* Copyright (C) 2018-2025 Tilman Neumann - tilman.neumann@web.de
4+
*
5+
* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License
6+
* as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
7+
*
8+
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
9+
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
10+
*
11+
* You should have received a copy of the GNU General Public License along with this program;
12+
* if not, see <http://www.gnu.org/licenses/>.
13+
*/
14+
package de.tilman_neumann.jml.factor.tdiv;
15+
16+
import static org.junit.Assert.assertEquals;
17+
import static org.junit.Assert.assertNotEquals;
18+
import static org.junit.Assert.fail;
19+
20+
import java.math.BigInteger;
21+
import java.util.List;
22+
23+
import org.apache.logging.log4j.LogManager;
24+
import org.apache.logging.log4j.Logger;
25+
import org.junit.BeforeClass;
26+
import org.junit.Test;
27+
28+
import de.tilman_neumann.jml.factor.FactorAlgorithm;
29+
import de.tilman_neumann.jml.factor.FactorTestInfrastructure;
30+
import de.tilman_neumann.jml.factor.TestNumberNature;
31+
import de.tilman_neumann.jml.factor.TestsetGenerator;
32+
import de.tilman_neumann.jml.factor.squfof.SquFoF63;
33+
import de.tilman_neumann.util.ConfigUtil;
34+
import de.tilman_neumann.util.SortedMultiset;
35+
36+
public class TDiv31BarrettTest {
37+
38+
private static final Logger LOG = LogManager.getLogger(TDiv31BarrettTest.class);
39+
40+
private static final TDiv31Barrett tdiv = new TDiv31Barrett();
41+
// don't use CombinedFactorAlgorithm as verificationFactorizer because Tdiv is part of it
42+
private static final FactorAlgorithm verificationFactorizer = new SquFoF63();
43+
44+
@BeforeClass
45+
public static void setup() {
46+
ConfigUtil.initProject();
47+
}
48+
49+
@Test
50+
public void testSmallestComposites() {
51+
List<Integer> fails = FactorTestInfrastructure.testSmallComposites(100000, tdiv);
52+
assertEquals("Failed to factor n = " + fails, 0, fails.size());
53+
}
54+
55+
@Test
56+
public void testSomeParticularNumbers() {
57+
assertFactorizationSuccess(621887327L, "853 * 729059"); // 30 bit
58+
assertFactorizationSuccess(676762483L, "877 * 771679"); // 30 bit
59+
}
60+
61+
/**
62+
* Tests random composite numbers in the range where TDiv63Test should work correctly, i.e. with factorLimit=2^21 up to 42 bit.
63+
*/
64+
@Test
65+
public void testRandomComposites() {
66+
int count = 10000;
67+
for (int bits=20; bits<32; bits++) {
68+
BigInteger[] testNumbers = TestsetGenerator.generate(count, bits, TestNumberNature.RANDOM_ODD_COMPOSITES);
69+
LOG.info("Testing " + count + " random numbers with " + bits + " bit...");
70+
int failCount = 0;
71+
for (int i=0; i<count; i++) {
72+
BigInteger NBig = testNumbers[i];
73+
int N = NBig.intValue();
74+
int tdivFactor = tdiv.findSingleFactor(N);
75+
if (tdivFactor < 2) {
76+
int correctFactor = verificationFactorizer.findSingleFactor(NBig).intValue();
77+
if (correctFactor > 1 && correctFactor<N) {
78+
LOG.debug("N=" + N + ": TDiv63Inverse failed to find factor " + correctFactor);
79+
failCount++;
80+
} else {
81+
LOG.error("The reference factorizer failed to factor N=" + N + " !");
82+
fail();
83+
}
84+
} else {
85+
if (N % tdivFactor != 0) {
86+
failCount++;
87+
}
88+
}
89+
}
90+
LOG.info(" #fails = " + failCount);
91+
assertEquals(failCount, 0);
92+
}
93+
}
94+
95+
private void assertFactorizationSuccess(long N, String expectedPrimeFactorizationStr) {
96+
BigInteger NBig = BigInteger.valueOf(N);
97+
LOG.info("Test " + N + " (" + NBig.bitLength() + " bit)");
98+
SortedMultiset<BigInteger> factors = tdiv.factor(NBig);
99+
LOG.info(N + " = " + factors.toString("*", "^"));
100+
assertEquals(expectedPrimeFactorizationStr, factors.toString("*", "^"));
101+
}
102+
103+
@SuppressWarnings("unused")
104+
private void assertFactorizationError(long N, String expectedPrimeFactorizationStr) {
105+
BigInteger NBig = BigInteger.valueOf(N);
106+
LOG.info("Test " + N + " (" + NBig.bitLength() + " bit)");
107+
SortedMultiset<BigInteger> factors = tdiv.factor(NBig);
108+
LOG.info(N + " = " + factors.toString("*", "^"));
109+
assertNotEquals(expectedPrimeFactorizationStr, factors.toString("*", "^"));
110+
}
111+
}
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/*
2+
* java-math-library is a Java library focused on number theory, but not necessarily limited to it. It is based on the PSIQS 4.0 factoring project.
3+
* Copyright (C) 2018-2025 Tilman Neumann - tilman.neumann@web.de
4+
*
5+
* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License
6+
* as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
7+
*
8+
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
9+
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
10+
*
11+
* You should have received a copy of the GNU General Public License along with this program;
12+
* if not, see <http://www.gnu.org/licenses/>.
13+
*/
14+
package de.tilman_neumann.jml.factor.tdiv;
15+
16+
import static org.junit.Assert.assertEquals;
17+
import static org.junit.Assert.assertNotEquals;
18+
import static org.junit.Assert.fail;
19+
20+
import java.math.BigInteger;
21+
import java.util.List;
22+
23+
import org.apache.logging.log4j.LogManager;
24+
import org.apache.logging.log4j.Logger;
25+
import org.junit.BeforeClass;
26+
import org.junit.Test;
27+
28+
import de.tilman_neumann.jml.factor.FactorAlgorithm;
29+
import de.tilman_neumann.jml.factor.FactorTestInfrastructure;
30+
import de.tilman_neumann.jml.factor.TestNumberNature;
31+
import de.tilman_neumann.jml.factor.TestsetGenerator;
32+
import de.tilman_neumann.jml.factor.squfof.SquFoF63;
33+
import de.tilman_neumann.util.ConfigUtil;
34+
import de.tilman_neumann.util.SortedMultiset;
35+
36+
public class TDiv31InverseTest {
37+
38+
private static final Logger LOG = LogManager.getLogger(TDiv31InverseTest.class);
39+
40+
private static final TDiv31Inverse tdiv = new TDiv31Inverse();
41+
// don't use CombinedFactorAlgorithm as verificationFactorizer because Tdiv is part of it
42+
private static final FactorAlgorithm verificationFactorizer = new SquFoF63();
43+
44+
@BeforeClass
45+
public static void setup() {
46+
ConfigUtil.initProject();
47+
}
48+
49+
@Test
50+
public void testSmallestComposites() {
51+
List<Integer> fails = FactorTestInfrastructure.testSmallComposites(100000, tdiv);
52+
assertEquals("Failed to factor n = " + fails, 0, fails.size());
53+
}
54+
55+
@Test
56+
public void testSomeParticularNumbers() {
57+
assertFactorizationSuccess(621887327L, "853 * 729059"); // 30 bit
58+
assertFactorizationSuccess(676762483L, "877 * 771679"); // 30 bit
59+
}
60+
61+
/**
62+
* Tests random composite numbers in the range where TDiv63Test should work correctly, i.e. with factorLimit=2^21 up to 42 bit.
63+
*/
64+
@Test
65+
public void testRandomComposites() {
66+
int count = 10000;
67+
for (int bits=20; bits<32; bits++) {
68+
BigInteger[] testNumbers = TestsetGenerator.generate(count, bits, TestNumberNature.RANDOM_ODD_COMPOSITES);
69+
LOG.info("Testing " + count + " random numbers with " + bits + " bit...");
70+
int failCount = 0;
71+
for (int i=0; i<count; i++) {
72+
BigInteger NBig = testNumbers[i];
73+
int N = NBig.intValue();
74+
int tdivFactor = tdiv.findSingleFactor(N);
75+
if (tdivFactor < 2) {
76+
int correctFactor = verificationFactorizer.findSingleFactor(NBig).intValue();
77+
if (correctFactor > 1 && correctFactor<N) {
78+
LOG.debug("N=" + N + ": TDiv63Inverse failed to find factor " + correctFactor);
79+
failCount++;
80+
} else {
81+
LOG.error("The reference factorizer failed to factor N=" + N + " !");
82+
fail();
83+
}
84+
} else {
85+
if (N % tdivFactor != 0) {
86+
failCount++;
87+
}
88+
}
89+
}
90+
LOG.info(" #fails = " + failCount);
91+
assertEquals(failCount, 0);
92+
}
93+
}
94+
95+
private void assertFactorizationSuccess(long N, String expectedPrimeFactorizationStr) {
96+
BigInteger NBig = BigInteger.valueOf(N);
97+
LOG.info("Test " + N + " (" + NBig.bitLength() + " bit)");
98+
SortedMultiset<BigInteger> factors = tdiv.factor(NBig);
99+
LOG.info(N + " = " + factors.toString("*", "^"));
100+
assertEquals(expectedPrimeFactorizationStr, factors.toString("*", "^"));
101+
}
102+
103+
@SuppressWarnings("unused")
104+
private void assertFactorizationError(long N, String expectedPrimeFactorizationStr) {
105+
BigInteger NBig = BigInteger.valueOf(N);
106+
LOG.info("Test " + N + " (" + NBig.bitLength() + " bit)");
107+
SortedMultiset<BigInteger> factors = tdiv.factor(NBig);
108+
LOG.info(N + " = " + factors.toString("*", "^"));
109+
assertNotEquals(expectedPrimeFactorizationStr, factors.toString("*", "^"));
110+
}
111+
}
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/*
2+
* java-math-library is a Java library focused on number theory, but not necessarily limited to it. It is based on the PSIQS 4.0 factoring project.
3+
* Copyright (C) 2018-2025 Tilman Neumann - tilman.neumann@web.de
4+
*
5+
* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License
6+
* as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
7+
*
8+
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
9+
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
10+
*
11+
* You should have received a copy of the GNU General Public License along with this program;
12+
* if not, see <http://www.gnu.org/licenses/>.
13+
*/
14+
package de.tilman_neumann.jml.factor.tdiv;
15+
16+
import static org.junit.Assert.assertEquals;
17+
import static org.junit.Assert.assertNotEquals;
18+
import static org.junit.Assert.fail;
19+
20+
import java.math.BigInteger;
21+
import java.util.List;
22+
23+
import org.apache.logging.log4j.LogManager;
24+
import org.apache.logging.log4j.Logger;
25+
import org.junit.BeforeClass;
26+
import org.junit.Test;
27+
28+
import de.tilman_neumann.jml.factor.FactorAlgorithm;
29+
import de.tilman_neumann.jml.factor.FactorTestInfrastructure;
30+
import de.tilman_neumann.jml.factor.TestNumberNature;
31+
import de.tilman_neumann.jml.factor.TestsetGenerator;
32+
import de.tilman_neumann.jml.factor.squfof.SquFoF63;
33+
import de.tilman_neumann.util.ConfigUtil;
34+
import de.tilman_neumann.util.SortedMultiset;
35+
36+
public class TDiv31Test {
37+
38+
private static final Logger LOG = LogManager.getLogger(TDiv31Test.class);
39+
40+
private static final TDiv31 tdiv = new TDiv31();
41+
// don't use CombinedFactorAlgorithm as verificationFactorizer because Tdiv is part of it
42+
private static final FactorAlgorithm verificationFactorizer = new SquFoF63();
43+
44+
@BeforeClass
45+
public static void setup() {
46+
ConfigUtil.initProject();
47+
}
48+
49+
@Test
50+
public void testSmallestComposites() {
51+
List<Integer> fails = FactorTestInfrastructure.testSmallComposites(100000, tdiv);
52+
assertEquals("Failed to factor n = " + fails, 0, fails.size());
53+
}
54+
55+
@Test
56+
public void testSomeParticularNumbers() {
57+
assertFactorizationSuccess(621887327L, "853 * 729059"); // 30 bit
58+
assertFactorizationSuccess(676762483L, "877 * 771679"); // 30 bit
59+
}
60+
61+
/**
62+
* Tests random composite numbers in the range where TDiv63Test should work correctly, i.e. with factorLimit=2^21 up to 42 bit.
63+
*/
64+
@Test
65+
public void testRandomComposites() {
66+
int count = 10000;
67+
for (int bits=20; bits<32; bits++) {
68+
BigInteger[] testNumbers = TestsetGenerator.generate(count, bits, TestNumberNature.RANDOM_ODD_COMPOSITES);
69+
LOG.info("Testing " + count + " random numbers with " + bits + " bit...");
70+
int failCount = 0;
71+
for (int i=0; i<count; i++) {
72+
BigInteger NBig = testNumbers[i];
73+
int N = NBig.intValue();
74+
int tdivFactor = tdiv.findSingleFactor(N);
75+
if (tdivFactor < 2) {
76+
int correctFactor = verificationFactorizer.findSingleFactor(NBig).intValue();
77+
if (correctFactor > 1 && correctFactor<N) {
78+
LOG.debug("N=" + N + ": TDiv63Inverse failed to find factor " + correctFactor);
79+
failCount++;
80+
} else {
81+
LOG.error("The reference factorizer failed to factor N=" + N + " !");
82+
fail();
83+
}
84+
} else {
85+
if (N % tdivFactor != 0) {
86+
failCount++;
87+
}
88+
}
89+
}
90+
LOG.info(" #fails = " + failCount);
91+
assertEquals(failCount, 0);
92+
}
93+
}
94+
95+
private void assertFactorizationSuccess(long N, String expectedPrimeFactorizationStr) {
96+
BigInteger NBig = BigInteger.valueOf(N);
97+
LOG.info("Test " + N + " (" + NBig.bitLength() + " bit)");
98+
SortedMultiset<BigInteger> factors = tdiv.factor(NBig);
99+
LOG.info(N + " = " + factors.toString("*", "^"));
100+
assertEquals(expectedPrimeFactorizationStr, factors.toString("*", "^"));
101+
}
102+
103+
@SuppressWarnings("unused")
104+
private void assertFactorizationError(long N, String expectedPrimeFactorizationStr) {
105+
BigInteger NBig = BigInteger.valueOf(N);
106+
LOG.info("Test " + N + " (" + NBig.bitLength() + " bit)");
107+
SortedMultiset<BigInteger> factors = tdiv.factor(NBig);
108+
LOG.info(N + " = " + factors.toString("*", "^"));
109+
assertNotEquals(expectedPrimeFactorizationStr, factors.toString("*", "^"));
110+
}
111+
}

0 commit comments

Comments
 (0)