From ae7e3b219717232cfd700da03c7257f8e8cc322b Mon Sep 17 00:00:00 2001 From: saahilmahato Date: Mon, 6 Oct 2025 21:02:29 +0545 Subject: [PATCH 1/9] feat: add euler primality test --- .../maths/Prime/EulerPseudoprime.java | 105 ++++++++++++++++++ .../maths/prime/EulerPseudoprimeTest.java | 30 +++++ 2 files changed, 135 insertions(+) create mode 100644 src/main/java/com/thealgorithms/maths/Prime/EulerPseudoprime.java create mode 100644 src/test/java/com/thealgorithms/maths/prime/EulerPseudoprimeTest.java diff --git a/src/main/java/com/thealgorithms/maths/Prime/EulerPseudoprime.java b/src/main/java/com/thealgorithms/maths/Prime/EulerPseudoprime.java new file mode 100644 index 000000000000..b8d5cdb73905 --- /dev/null +++ b/src/main/java/com/thealgorithms/maths/Prime/EulerPseudoprime.java @@ -0,0 +1,105 @@ +package com.thealgorithms.maths.Prime; + +import java.math.BigInteger; +import java.security.SecureRandom; + +/** + * The {@code EulerPseudoprime} class implements the Euler primality test. + * + * It is based on Euler’s criterion: + * For an odd prime number {@code n} and any integer {@code a} coprime to {@code n}: + * a^((n-1)/2) ≡ (a/n) (mod n) + * where (a/n) is the Jacobi symbol. + * + * This algorithm is a stronger probabilistic test than Fermat’s test. + * It may still incorrectly identify a composite as “probably prime” (Euler pseudoprime), + * but such cases are rare. + */ +public class EulerPseudoprime { + + private EulerPseudoprime() { + } + + private static final SecureRandom random = new SecureRandom(); + + /** + * Performs the Euler primality test for a given number. + * + * @param n number to test (must be > 2 and odd) + * @param trials number of random bases to test + * @return {@code true} if {@code n} passes all Euler tests (probably prime), + * {@code false} if composite. + */ + public static boolean isProbablePrime(BigInteger n, int trials) { + if (n.compareTo(BigInteger.TWO) < 0) { + return false; + } + if (n.equals(BigInteger.TWO) || n.equals(BigInteger.valueOf(3))) { + return true; + } + if (n.mod(BigInteger.TWO).equals(BigInteger.ZERO)) { + return false; + } + + for (int i = 0; i < trials; i++) { + BigInteger a = uniformRandom(BigInteger.TWO, n.subtract(BigInteger.TWO)); + BigInteger jacobi = BigInteger.valueOf(jacobiSymbol(a, n)); + if (jacobi.equals(BigInteger.ZERO)) return false; + + BigInteger exp = n.subtract(BigInteger.ONE).divide(BigInteger.TWO); + BigInteger modExp = a.modPow(exp, n); + + // Euler's criterion: a^((n-1)/2) ≡ (a/n) (mod n) + if (!modExp.equals(jacobi.mod(n))) { + return false; // definitely composite + } + } + return true; // probably prime + } + + /** + * Generates a random BigInteger between {@code min} and {@code max}, inclusive. + */ + private static BigInteger uniformRandom(BigInteger min, BigInteger max) { + BigInteger result; + do { + result = new BigInteger(max.bitLength(), random); + } while (result.compareTo(min) < 0 || result.compareTo(max) > 0); + return result; + } + + /** + * Computes the Jacobi symbol (a/n). + * Assumes n is positive and odd. + */ + private static int jacobiSymbol(BigInteger a, BigInteger n) { + if (n.signum() <= 0 || n.mod(BigInteger.TWO).equals(BigInteger.ZERO)) { + throw new IllegalArgumentException("n must be positive and odd."); + } + + int result = 1; + a = a.mod(n); + + while (a.compareTo(BigInteger.ZERO) != 0) { + while (a.mod(BigInteger.TWO).equals(BigInteger.ZERO)) { + a = a.divide(BigInteger.TWO); + BigInteger nMod8 = n.mod(BigInteger.valueOf(8)); + if (nMod8.equals(BigInteger.valueOf(3)) || nMod8.equals(BigInteger.valueOf(5))) { + result = -result; + } + } + + BigInteger temp = a; + a = n; + n = temp; + + if (a.mod(BigInteger.valueOf(4)).equals(BigInteger.valueOf(3)) && n.mod(BigInteger.valueOf(4)).equals(BigInteger.valueOf(3))) { + result = -result; + } + + a = a.mod(n); + } + + return n.equals(BigInteger.ONE) ? result : 0; + } +} diff --git a/src/test/java/com/thealgorithms/maths/prime/EulerPseudoprimeTest.java b/src/test/java/com/thealgorithms/maths/prime/EulerPseudoprimeTest.java new file mode 100644 index 000000000000..522edf9866b3 --- /dev/null +++ b/src/test/java/com/thealgorithms/maths/prime/EulerPseudoprimeTest.java @@ -0,0 +1,30 @@ +package com.thealgorithms.maths.prime; + +import static org.junit.jupiter.api.Assertions.*; + +import com.thealgorithms.maths.Prime.EulerPseudoprime; +import java.math.BigInteger; +import org.junit.jupiter.api.Test; + +class EulerPseudoprimeTest { + + @Test + void testPrimeNumbers() { + assertTrue(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(7), 10)); + assertTrue(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(13), 10)); + assertTrue(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(101), 10)); + } + + @Test + void testCompositeNumbers() { + assertFalse(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(9), 10)); + assertFalse(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(21), 10)); + assertFalse(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(221), 10)); + } + + @Test + void testEvenNumbers() { + assertFalse(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(4), 10)); + assertFalse(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(100), 10)); + } +} From 2c1a9576c65216187e912ad250b0392140734cc6 Mon Sep 17 00:00:00 2001 From: saahilmahato Date: Mon, 6 Oct 2025 21:06:35 +0545 Subject: [PATCH 2/9] refactor: use fixed seed --- .../java/com/thealgorithms/maths/Prime/EulerPseudoprime.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/thealgorithms/maths/Prime/EulerPseudoprime.java b/src/main/java/com/thealgorithms/maths/Prime/EulerPseudoprime.java index b8d5cdb73905..d08814f50488 100644 --- a/src/main/java/com/thealgorithms/maths/Prime/EulerPseudoprime.java +++ b/src/main/java/com/thealgorithms/maths/Prime/EulerPseudoprime.java @@ -1,7 +1,7 @@ package com.thealgorithms.maths.Prime; import java.math.BigInteger; -import java.security.SecureRandom; +import java.util.Random; /** * The {@code EulerPseudoprime} class implements the Euler primality test. @@ -18,9 +18,10 @@ public class EulerPseudoprime { private EulerPseudoprime() { + // Private constructor to prevent instantiation. } - private static final SecureRandom random = new SecureRandom(); + private static final Random random = new Random(1); /** * Performs the Euler primality test for a given number. From 58fc8743191d9e9f2e930c91b6b50300215a38e8 Mon Sep 17 00:00:00 2001 From: saahilmahato Date: Mon, 6 Oct 2025 21:21:22 +0545 Subject: [PATCH 3/9] fix: more unit test coverage --- .../maths/prime/EulerPseudoprimeTest.java | 68 ++++++++++++++++--- 1 file changed, 60 insertions(+), 8 deletions(-) diff --git a/src/test/java/com/thealgorithms/maths/prime/EulerPseudoprimeTest.java b/src/test/java/com/thealgorithms/maths/prime/EulerPseudoprimeTest.java index 522edf9866b3..0be362071776 100644 --- a/src/test/java/com/thealgorithms/maths/prime/EulerPseudoprimeTest.java +++ b/src/test/java/com/thealgorithms/maths/prime/EulerPseudoprimeTest.java @@ -10,21 +10,73 @@ class EulerPseudoprimeTest { @Test void testPrimeNumbers() { - assertTrue(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(7), 10)); - assertTrue(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(13), 10)); - assertTrue(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(101), 10)); + assertTrue(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(7), 5)); + assertTrue(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(13), 5)); + assertTrue(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(101), 5)); } @Test void testCompositeNumbers() { - assertFalse(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(9), 10)); - assertFalse(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(21), 10)); - assertFalse(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(221), 10)); + assertFalse(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(9), 5)); + assertFalse(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(21), 5)); + assertFalse(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(221), 5)); } @Test void testEvenNumbers() { - assertFalse(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(4), 10)); - assertFalse(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(100), 10)); + assertFalse(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(4), 5)); + assertFalse(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(100), 5)); + } + + @Test + void testEdgeCases() { + assertFalse(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(0), 5)); + assertFalse(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(1), 5)); + assertTrue(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(2), 5)); + assertTrue(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(3), 5)); + } + + @Test + void testSingleTrialConsistency() { + BigInteger n = BigInteger.valueOf(97); + boolean result1 = EulerPseudoprime.isProbablePrime(n, 1); + boolean result2 = EulerPseudoprime.isProbablePrime(n, 1); + assertEquals(result1, result2, "Results should be deterministic with constant seed"); + } + + @Test + void testJacobiSymbolBasicCases() throws Exception { + var method = EulerPseudoprime.class.getDeclaredMethod("jacobiSymbol", BigInteger.class, BigInteger.class); + method.setAccessible(true); + + // (a/n) = (2/3) = -1 + assertEquals(-1, (int) method.invoke(null, BigInteger.valueOf(2), BigInteger.valueOf(3))); + + // (a/n) = (1/5) = 1 + assertEquals(1, (int) method.invoke(null, BigInteger.ONE, BigInteger.valueOf(5))); + + // (a/n) = (2/9) = 1 + assertEquals(1, (int) method.invoke(null, BigInteger.valueOf(2), BigInteger.valueOf(9))); + + // (a/n) = (3/9) = 0 since gcd(3,9)>1 + assertEquals(0, (int) method.invoke(null, BigInteger.valueOf(3), BigInteger.valueOf(9))); + } + + @Test + void testUniformRandomRange() throws Exception { + var method = EulerPseudoprime.class.getDeclaredMethod("uniformRandom", BigInteger.class, BigInteger.class); + method.setAccessible(true); + + BigInteger min = BigInteger.TWO; + BigInteger max = BigInteger.valueOf(20); + BigInteger value = (BigInteger) method.invoke(null, min, max); + + assertTrue(value.compareTo(min) >= 0 && value.compareTo(max) <= 0, "Random value should be within [min, max]"); + } + + @Test + void testCompositeWithZeroJacobiSymbol() { + // Choose n = 9, a = 3 → jacobi(3,9) = 0 should make it return false early + assertFalse(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(9), 1)); } } From 3b665edff6adc41f30a356e6dff37a058d601c0e Mon Sep 17 00:00:00 2001 From: saahilmahato Date: Mon, 6 Oct 2025 22:50:27 +0545 Subject: [PATCH 4/9] fix: add mock tests for edge cases --- .../maths/Prime/EulerPseudoprime.java | 28 +++++----- .../maths/prime/EulerPseudoprimeTest.java | 55 ++++++++++++++++++- 2 files changed, 67 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/thealgorithms/maths/Prime/EulerPseudoprime.java b/src/main/java/com/thealgorithms/maths/Prime/EulerPseudoprime.java index d08814f50488..23908bb83827 100644 --- a/src/main/java/com/thealgorithms/maths/Prime/EulerPseudoprime.java +++ b/src/main/java/com/thealgorithms/maths/Prime/EulerPseudoprime.java @@ -45,7 +45,9 @@ public static boolean isProbablePrime(BigInteger n, int trials) { for (int i = 0; i < trials; i++) { BigInteger a = uniformRandom(BigInteger.TWO, n.subtract(BigInteger.TWO)); BigInteger jacobi = BigInteger.valueOf(jacobiSymbol(a, n)); - if (jacobi.equals(BigInteger.ZERO)) return false; + if (jacobi.equals(BigInteger.ZERO)) { + return false; + } BigInteger exp = n.subtract(BigInteger.ONE).divide(BigInteger.TWO); BigInteger modExp = a.modPow(exp, n); @@ -58,22 +60,11 @@ public static boolean isProbablePrime(BigInteger n, int trials) { return true; // probably prime } - /** - * Generates a random BigInteger between {@code min} and {@code max}, inclusive. - */ - private static BigInteger uniformRandom(BigInteger min, BigInteger max) { - BigInteger result; - do { - result = new BigInteger(max.bitLength(), random); - } while (result.compareTo(min) < 0 || result.compareTo(max) > 0); - return result; - } - /** * Computes the Jacobi symbol (a/n). * Assumes n is positive and odd. */ - private static int jacobiSymbol(BigInteger a, BigInteger n) { + public static int jacobiSymbol(BigInteger a, BigInteger n) { if (n.signum() <= 0 || n.mod(BigInteger.TWO).equals(BigInteger.ZERO)) { throw new IllegalArgumentException("n must be positive and odd."); } @@ -103,4 +94,15 @@ private static int jacobiSymbol(BigInteger a, BigInteger n) { return n.equals(BigInteger.ONE) ? result : 0; } + + /** + * Generates a random BigInteger between {@code min} and {@code max}, inclusive. + */ + private static BigInteger uniformRandom(BigInteger min, BigInteger max) { + BigInteger result; + do { + result = new BigInteger(max.bitLength(), random); + } while (result.compareTo(min) < 0 || result.compareTo(max) > 0); + return result; + } } diff --git a/src/test/java/com/thealgorithms/maths/prime/EulerPseudoprimeTest.java b/src/test/java/com/thealgorithms/maths/prime/EulerPseudoprimeTest.java index 0be362071776..a7e1c47b04e1 100644 --- a/src/test/java/com/thealgorithms/maths/prime/EulerPseudoprimeTest.java +++ b/src/test/java/com/thealgorithms/maths/prime/EulerPseudoprimeTest.java @@ -1,10 +1,13 @@ package com.thealgorithms.maths.prime; import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; import com.thealgorithms.maths.Prime.EulerPseudoprime; import java.math.BigInteger; import org.junit.jupiter.api.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; class EulerPseudoprimeTest { @@ -75,8 +78,54 @@ void testUniformRandomRange() throws Exception { } @Test - void testCompositeWithZeroJacobiSymbol() { - // Choose n = 9, a = 3 → jacobi(3,9) = 0 should make it return false early - assertFalse(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(9), 1)); + void testIsProbablePrimeWhenJacobiSymbolIsZero() { + try (MockedStatic mockedPrimality = Mockito.mockStatic(EulerPseudoprime.class, Mockito.CALLS_REAL_METHODS)) { + + // Mock jacobiSymbol to return 0 to test the branch + mockedPrimality.when(() -> EulerPseudoprime.jacobiSymbol(any(BigInteger.class), any(BigInteger.class))).thenReturn(0); + + boolean result = EulerPseudoprime.isProbablePrime(BigInteger.valueOf(15), 1); + + assertFalse(result); + } + } + + @Test + void testJacobiSymbolThrowsForEvenOrNonPositiveN() throws Exception { + var method = EulerPseudoprime.class.getDeclaredMethod("jacobiSymbol", BigInteger.class, BigInteger.class); + method.setAccessible(true); + + // Helper lambda to unwrap InvocationTargetException + Runnable invokeJacobi = () -> { + try { + method.invoke(null, BigInteger.valueOf(2), BigInteger.valueOf(8)); + } catch (Exception e) { + // unwrap + Throwable cause = e.getCause(); + if (cause instanceof IllegalArgumentException) { + throw (IllegalArgumentException) cause; + } else { + throw new RuntimeException(e); + } + } + }; + + // Now check that it actually throws + assertThrows(IllegalArgumentException.class, invokeJacobi::run); + + // Another case: non-positive n + Runnable invokeJacobi2 = () -> { + try { + method.invoke(null, BigInteger.valueOf(5), BigInteger.valueOf(-3)); + } catch (Exception e) { + Throwable cause = e.getCause(); + if (cause instanceof IllegalArgumentException) { + throw (IllegalArgumentException) cause; + } else { + throw new RuntimeException(e); + } + } + }; + assertThrows(IllegalArgumentException.class, invokeJacobi2::run); } } From f846450fbec358126f715929fb013c943382ac44 Mon Sep 17 00:00:00 2001 From: saahilmahato Date: Mon, 6 Oct 2025 22:56:23 +0545 Subject: [PATCH 5/9] fix: styling issues --- .../com/thealgorithms/maths/Prime/EulerPseudoprime.java | 6 +++--- .../com/thealgorithms/maths/prime/EulerPseudoprimeTest.java | 5 ++++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/thealgorithms/maths/Prime/EulerPseudoprime.java b/src/main/java/com/thealgorithms/maths/Prime/EulerPseudoprime.java index 23908bb83827..0fbfe9e1e701 100644 --- a/src/main/java/com/thealgorithms/maths/Prime/EulerPseudoprime.java +++ b/src/main/java/com/thealgorithms/maths/Prime/EulerPseudoprime.java @@ -15,13 +15,13 @@ * It may still incorrectly identify a composite as “probably prime” (Euler pseudoprime), * but such cases are rare. */ -public class EulerPseudoprime { +public final class EulerPseudoprime { private EulerPseudoprime() { // Private constructor to prevent instantiation. } - private static final Random random = new Random(1); + private static final Random RANDOM = new Random(1); /** * Performs the Euler primality test for a given number. @@ -101,7 +101,7 @@ public static int jacobiSymbol(BigInteger a, BigInteger n) { private static BigInteger uniformRandom(BigInteger min, BigInteger max) { BigInteger result; do { - result = new BigInteger(max.bitLength(), random); + result = new BigInteger(max.bitLength(), RANDOM); } while (result.compareTo(min) < 0 || result.compareTo(max) > 0); return result; } diff --git a/src/test/java/com/thealgorithms/maths/prime/EulerPseudoprimeTest.java b/src/test/java/com/thealgorithms/maths/prime/EulerPseudoprimeTest.java index a7e1c47b04e1..1b6d7bb73592 100644 --- a/src/test/java/com/thealgorithms/maths/prime/EulerPseudoprimeTest.java +++ b/src/test/java/com/thealgorithms/maths/prime/EulerPseudoprimeTest.java @@ -1,6 +1,9 @@ package com.thealgorithms.maths.prime; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import com.thealgorithms.maths.Prime.EulerPseudoprime; From 4b099b3860dfb2bc66543cca5f921aca84b0159b Mon Sep 17 00:00:00 2001 From: saahilmahato Date: Mon, 6 Oct 2025 23:02:46 +0545 Subject: [PATCH 6/9] refactor: remove duplicate tests --- .../maths/prime/EulerPseudoprimeTest.java | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/test/java/com/thealgorithms/maths/prime/EulerPseudoprimeTest.java b/src/test/java/com/thealgorithms/maths/prime/EulerPseudoprimeTest.java index 1b6d7bb73592..07db9fd9fa57 100644 --- a/src/test/java/com/thealgorithms/maths/prime/EulerPseudoprimeTest.java +++ b/src/test/java/com/thealgorithms/maths/prime/EulerPseudoprimeTest.java @@ -53,7 +53,6 @@ void testSingleTrialConsistency() { @Test void testJacobiSymbolBasicCases() throws Exception { var method = EulerPseudoprime.class.getDeclaredMethod("jacobiSymbol", BigInteger.class, BigInteger.class); - method.setAccessible(true); // (a/n) = (2/3) = -1 assertEquals(-1, (int) method.invoke(null, BigInteger.valueOf(2), BigInteger.valueOf(3))); @@ -68,18 +67,6 @@ void testJacobiSymbolBasicCases() throws Exception { assertEquals(0, (int) method.invoke(null, BigInteger.valueOf(3), BigInteger.valueOf(9))); } - @Test - void testUniformRandomRange() throws Exception { - var method = EulerPseudoprime.class.getDeclaredMethod("uniformRandom", BigInteger.class, BigInteger.class); - method.setAccessible(true); - - BigInteger min = BigInteger.TWO; - BigInteger max = BigInteger.valueOf(20); - BigInteger value = (BigInteger) method.invoke(null, min, max); - - assertTrue(value.compareTo(min) >= 0 && value.compareTo(max) <= 0, "Random value should be within [min, max]"); - } - @Test void testIsProbablePrimeWhenJacobiSymbolIsZero() { try (MockedStatic mockedPrimality = Mockito.mockStatic(EulerPseudoprime.class, Mockito.CALLS_REAL_METHODS)) { @@ -96,7 +83,6 @@ void testIsProbablePrimeWhenJacobiSymbolIsZero() { @Test void testJacobiSymbolThrowsForEvenOrNonPositiveN() throws Exception { var method = EulerPseudoprime.class.getDeclaredMethod("jacobiSymbol", BigInteger.class, BigInteger.class); - method.setAccessible(true); // Helper lambda to unwrap InvocationTargetException Runnable invokeJacobi = () -> { From a787945fba4a5ffeb7b2f8c7773c8020624b1221 Mon Sep 17 00:00:00 2001 From: saahilmahato Date: Mon, 6 Oct 2025 23:15:39 +0545 Subject: [PATCH 7/9] refactor: reduce static imports --- .../maths/prime/EulerPseudoprimeTest.java | 28 +++++++++---------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/src/test/java/com/thealgorithms/maths/prime/EulerPseudoprimeTest.java b/src/test/java/com/thealgorithms/maths/prime/EulerPseudoprimeTest.java index 07db9fd9fa57..208b231b7861 100644 --- a/src/test/java/com/thealgorithms/maths/prime/EulerPseudoprimeTest.java +++ b/src/test/java/com/thealgorithms/maths/prime/EulerPseudoprimeTest.java @@ -1,9 +1,7 @@ package com.thealgorithms.maths.prime; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import com.thealgorithms.maths.Prime.EulerPseudoprime; @@ -16,30 +14,30 @@ class EulerPseudoprimeTest { @Test void testPrimeNumbers() { - assertTrue(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(7), 5)); - assertTrue(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(13), 5)); - assertTrue(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(101), 5)); + assertEquals(true, EulerPseudoprime.isProbablePrime(BigInteger.valueOf(7), 5)); + assertEquals(true, EulerPseudoprime.isProbablePrime(BigInteger.valueOf(13), 5)); + assertEquals(true, EulerPseudoprime.isProbablePrime(BigInteger.valueOf(101), 5)); } @Test void testCompositeNumbers() { - assertFalse(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(9), 5)); - assertFalse(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(21), 5)); - assertFalse(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(221), 5)); + assertEquals(false, EulerPseudoprime.isProbablePrime(BigInteger.valueOf(9), 5)); + assertEquals(false, EulerPseudoprime.isProbablePrime(BigInteger.valueOf(21), 5)); + assertEquals(false, EulerPseudoprime.isProbablePrime(BigInteger.valueOf(221), 5)); } @Test void testEvenNumbers() { - assertFalse(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(4), 5)); - assertFalse(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(100), 5)); + assertEquals(false, EulerPseudoprime.isProbablePrime(BigInteger.valueOf(4), 5)); + assertEquals(false, EulerPseudoprime.isProbablePrime(BigInteger.valueOf(100), 5)); } @Test void testEdgeCases() { - assertFalse(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(0), 5)); - assertFalse(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(1), 5)); - assertTrue(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(2), 5)); - assertTrue(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(3), 5)); + assertEquals(false, EulerPseudoprime.isProbablePrime(BigInteger.valueOf(0), 5)); + assertEquals(false, EulerPseudoprime.isProbablePrime(BigInteger.valueOf(1), 5)); + assertEquals(true, EulerPseudoprime.isProbablePrime(BigInteger.valueOf(2), 5)); + assertEquals(true, EulerPseudoprime.isProbablePrime(BigInteger.valueOf(3), 5)); } @Test @@ -76,7 +74,7 @@ void testIsProbablePrimeWhenJacobiSymbolIsZero() { boolean result = EulerPseudoprime.isProbablePrime(BigInteger.valueOf(15), 1); - assertFalse(result); + assertEquals(false, result); } } From 0a54ce791a110d55c493a3d17ff54515f892950f Mon Sep 17 00:00:00 2001 From: saahilmahato Date: Mon, 6 Oct 2025 23:27:55 +0545 Subject: [PATCH 8/9] refactor: remove unnecessary tests --- .../maths/prime/EulerPseudoprimeTest.java | 54 ++++++------------- 1 file changed, 15 insertions(+), 39 deletions(-) diff --git a/src/test/java/com/thealgorithms/maths/prime/EulerPseudoprimeTest.java b/src/test/java/com/thealgorithms/maths/prime/EulerPseudoprimeTest.java index 208b231b7861..936bc1a0d489 100644 --- a/src/test/java/com/thealgorithms/maths/prime/EulerPseudoprimeTest.java +++ b/src/test/java/com/thealgorithms/maths/prime/EulerPseudoprimeTest.java @@ -1,7 +1,8 @@ package com.thealgorithms.maths.prime; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import com.thealgorithms.maths.Prime.EulerPseudoprime; @@ -14,55 +15,30 @@ class EulerPseudoprimeTest { @Test void testPrimeNumbers() { - assertEquals(true, EulerPseudoprime.isProbablePrime(BigInteger.valueOf(7), 5)); - assertEquals(true, EulerPseudoprime.isProbablePrime(BigInteger.valueOf(13), 5)); - assertEquals(true, EulerPseudoprime.isProbablePrime(BigInteger.valueOf(101), 5)); + assertTrue(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(7), 5)); + assertTrue(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(13), 5)); + assertTrue(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(101), 5)); } @Test void testCompositeNumbers() { - assertEquals(false, EulerPseudoprime.isProbablePrime(BigInteger.valueOf(9), 5)); - assertEquals(false, EulerPseudoprime.isProbablePrime(BigInteger.valueOf(21), 5)); - assertEquals(false, EulerPseudoprime.isProbablePrime(BigInteger.valueOf(221), 5)); + assertFalse(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(9), 5)); + assertFalse(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(21), 5)); + assertFalse(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(221), 5)); } @Test void testEvenNumbers() { - assertEquals(false, EulerPseudoprime.isProbablePrime(BigInteger.valueOf(4), 5)); - assertEquals(false, EulerPseudoprime.isProbablePrime(BigInteger.valueOf(100), 5)); + assertFalse(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(4), 5)); + assertFalse(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(100), 5)); } @Test void testEdgeCases() { - assertEquals(false, EulerPseudoprime.isProbablePrime(BigInteger.valueOf(0), 5)); - assertEquals(false, EulerPseudoprime.isProbablePrime(BigInteger.valueOf(1), 5)); - assertEquals(true, EulerPseudoprime.isProbablePrime(BigInteger.valueOf(2), 5)); - assertEquals(true, EulerPseudoprime.isProbablePrime(BigInteger.valueOf(3), 5)); - } - - @Test - void testSingleTrialConsistency() { - BigInteger n = BigInteger.valueOf(97); - boolean result1 = EulerPseudoprime.isProbablePrime(n, 1); - boolean result2 = EulerPseudoprime.isProbablePrime(n, 1); - assertEquals(result1, result2, "Results should be deterministic with constant seed"); - } - - @Test - void testJacobiSymbolBasicCases() throws Exception { - var method = EulerPseudoprime.class.getDeclaredMethod("jacobiSymbol", BigInteger.class, BigInteger.class); - - // (a/n) = (2/3) = -1 - assertEquals(-1, (int) method.invoke(null, BigInteger.valueOf(2), BigInteger.valueOf(3))); - - // (a/n) = (1/5) = 1 - assertEquals(1, (int) method.invoke(null, BigInteger.ONE, BigInteger.valueOf(5))); - - // (a/n) = (2/9) = 1 - assertEquals(1, (int) method.invoke(null, BigInteger.valueOf(2), BigInteger.valueOf(9))); - - // (a/n) = (3/9) = 0 since gcd(3,9)>1 - assertEquals(0, (int) method.invoke(null, BigInteger.valueOf(3), BigInteger.valueOf(9))); + assertFalse(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(0), 5)); + assertFalse(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(1), 5)); + assertTrue(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(2), 5)); + assertTrue(EulerPseudoprime.isProbablePrime(BigInteger.valueOf(3), 5)); } @Test @@ -74,7 +50,7 @@ void testIsProbablePrimeWhenJacobiSymbolIsZero() { boolean result = EulerPseudoprime.isProbablePrime(BigInteger.valueOf(15), 1); - assertEquals(false, result); + assertFalse(result); } } From e746ccaade12abf458efc129ddf0768b83afed66 Mon Sep 17 00:00:00 2001 From: saahilmahato Date: Mon, 6 Oct 2025 23:58:58 +0545 Subject: [PATCH 9/9] refactor: move to maths package --- .../com/thealgorithms/maths/{Prime => }/EulerPseudoprime.java | 2 +- .../thealgorithms/maths/{prime => }/EulerPseudoprimeTest.java | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) rename src/main/java/com/thealgorithms/maths/{Prime => }/EulerPseudoprime.java (98%) rename src/test/java/com/thealgorithms/maths/{prime => }/EulerPseudoprimeTest.java (97%) diff --git a/src/main/java/com/thealgorithms/maths/Prime/EulerPseudoprime.java b/src/main/java/com/thealgorithms/maths/EulerPseudoprime.java similarity index 98% rename from src/main/java/com/thealgorithms/maths/Prime/EulerPseudoprime.java rename to src/main/java/com/thealgorithms/maths/EulerPseudoprime.java index 0fbfe9e1e701..9a03f4e21d17 100644 --- a/src/main/java/com/thealgorithms/maths/Prime/EulerPseudoprime.java +++ b/src/main/java/com/thealgorithms/maths/EulerPseudoprime.java @@ -1,4 +1,4 @@ -package com.thealgorithms.maths.Prime; +package com.thealgorithms.maths; import java.math.BigInteger; import java.util.Random; diff --git a/src/test/java/com/thealgorithms/maths/prime/EulerPseudoprimeTest.java b/src/test/java/com/thealgorithms/maths/EulerPseudoprimeTest.java similarity index 97% rename from src/test/java/com/thealgorithms/maths/prime/EulerPseudoprimeTest.java rename to src/test/java/com/thealgorithms/maths/EulerPseudoprimeTest.java index 936bc1a0d489..b4ee0cf0659c 100644 --- a/src/test/java/com/thealgorithms/maths/prime/EulerPseudoprimeTest.java +++ b/src/test/java/com/thealgorithms/maths/EulerPseudoprimeTest.java @@ -1,11 +1,10 @@ -package com.thealgorithms.maths.prime; +package com.thealgorithms.maths; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; -import com.thealgorithms.maths.Prime.EulerPseudoprime; import java.math.BigInteger; import org.junit.jupiter.api.Test; import org.mockito.MockedStatic;