From 8fc2a5535f9283c3ec0962b76b2e44ac48605b00 Mon Sep 17 00:00:00 2001 From: saahil-mahato Date: Thu, 10 Oct 2024 10:03:02 +0545 Subject: [PATCH 1/6] feat: add solovay strassen primality test --- .../maths/SolovayStrassenPrimalityTest.java | 126 +++++++++++++++++ .../SolovayStrassenPrimalityTestTest.java | 130 ++++++++++++++++++ 2 files changed, 256 insertions(+) create mode 100644 src/main/java/com/thealgorithms/maths/SolovayStrassenPrimalityTest.java create mode 100644 src/test/java/com/thealgorithms/maths/SolovayStrassenPrimalityTestTest.java diff --git a/src/main/java/com/thealgorithms/maths/SolovayStrassenPrimalityTest.java b/src/main/java/com/thealgorithms/maths/SolovayStrassenPrimalityTest.java new file mode 100644 index 000000000000..4523f1b2611f --- /dev/null +++ b/src/main/java/com/thealgorithms/maths/SolovayStrassenPrimalityTest.java @@ -0,0 +1,126 @@ +package com.thealgorithms.maths; + +import java.util.Random; + +/** + * This class implements the Solovay-Strassen primality test, + * which is a probabilistic algorithm to determine whether a number is prime. + * The algorithm is based on properties of the Jacobi symbol and modular exponentiation. + */ +class SolovayStrassenPrimalityTest { + + private Random random; + + /** + * Constructs a SolovayStrassenPrimalityTest instance with a specified seed for randomness. + * + * @param seed the seed for generating random numbers + */ + private SolovayStrassenPrimalityTest(int seed) { + random = new Random(seed); + } + + /** + * Factory method to create an instance of SolovayStrassenPrimalityTest. + * + * @param seed the seed for generating random numbers + * @return a new instance of SolovayStrassenPrimalityTest + */ + public static SolovayStrassenPrimalityTest getSolovayStrassenPrimalityTest(int seed) { + return new SolovayStrassenPrimalityTest(seed); + } + + /** + * Calculates modular exponentiation using the method of exponentiation by squaring. + * + * @param base the base number + * @param exponent the exponent + * @param mod the modulus + * @return (base^exponent) mod mod + */ + private static long calculateModularExponentiation(long base, long exponent, long mod) { + long x = 1; // This will hold the result of (base^exponent) % mod + long y = base; // This holds the current base value being squared + + while (exponent > 0) { + // If exponent is odd, multiply the current base (y) with x + if (exponent % 2 == 1) + x = (x * y) % mod; // Update result with current base + + // Square the base for the next iteration + y = (y * y) % mod; // Update base to be y^2 + exponent = exponent / 2; // Halve the exponent for next iteration + } + + return x % mod; // Return final result after all iterations + } + + /** + * Computes the Jacobi symbol (a/n), which is a generalization of the Legendre symbol. + * + * @param a the numerator + * @param num the denominator (must be an odd positive integer) + * @return the Jacobi symbol value: 1, -1, or 0 + */ + public int calculateJacobi(long a, long num) { + // Check if num is non-positive or even; Jacobi symbol is not defined in these cases + if (num <= 0 || num % 2 == 0) { + return 0; + } + + a = a % num; // Reduce a modulo num to simplify calculations + int jacobi = 1; // Initialize Jacobi symbol value + + while (a != 0) { + // While a is even, reduce it and adjust jacobi based on properties of num + while (a % 2 == 0) { + a /= 2; // Divide a by 2 until it becomes odd + long nMod8 = num % 8; // Get num modulo 8 to check conditions for jacobi adjustment + if (nMod8 == 3 || nMod8 == 5) { + jacobi = -jacobi; // Flip jacobi sign based on properties of num modulo 8 + } + } + + long temp = a; // Temporarily store value of a + a = num; // Set a to be num for next iteration + num = temp; // Set num to be previous value of a + + // Adjust jacobi based on properties of both numbers when both are odd and congruent to 3 modulo 4 + if (a % 4 == 3 && num % 4 == 3) { + jacobi = -jacobi; // Flip jacobi sign again based on congruences + } + + a = a % num; // Reduce a modulo num for next iteration of Jacobi computation + } + + return (num == 1) ? jacobi : 0; // If num reduces to 1, return jacobi value, otherwise return 0 (not defined) + } + + /** + * Performs the Solovay-Strassen primality test on a given number. + * + * @param num the number to be tested for primality + * @param iterations the number of iterations to run for accuracy + * @return true if num is likely prime, false if it is composite + */ + public boolean solovayStrassen(long num, int iterations) { + if (num <= 1) return false; // Numbers <=1 are not prime by definition. + if (num <= 3) return true; // Numbers <=3 are prime. + + for (int i = 0; i < iterations; i++) { + long r = (random.nextLong() & Long.MAX_VALUE); // Generate a non-negative random number. + long a = r % (num - 1) + 1; // Choose random 'a' in range [1, n-1]. + + long jacobi = (num + calculateJacobi(a, num)) % num; + // Calculate Jacobi symbol and adjust it modulo n. + + long mod = calculateModularExponentiation(a, (num - 1) / 2, num); + // Calculate modular exponentiation: a^((n-1)/2) mod n. + + if (jacobi == 0 || mod != jacobi) return false; + // If Jacobi symbol is zero or doesn't match modular result, n is composite. + } + + return true; // If no contradictions found after all iterations, n is likely prime. + } +} \ No newline at end of file diff --git a/src/test/java/com/thealgorithms/maths/SolovayStrassenPrimalityTestTest.java b/src/test/java/com/thealgorithms/maths/SolovayStrassenPrimalityTestTest.java new file mode 100644 index 000000000000..f500dd70997b --- /dev/null +++ b/src/test/java/com/thealgorithms/maths/SolovayStrassenPrimalityTestTest.java @@ -0,0 +1,130 @@ +package com.thealgorithms.maths; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for the {@link SolovayStrassenPrimalityTest} class. + * This class tests the functionality of the Solovay-Strassen primality test implementation. + */ +class SolovayStrassenPrimalityTestTest { + + private static final int RANDOM_SEED = 123; // Seed for reproducibility + private SolovayStrassenPrimalityTest testInstance; + + /** + * Sets up a new instance of {@link SolovayStrassenPrimalityTest} + * before each test case, using a fixed random seed for consistency. + */ + @BeforeEach + void setUp() { + testInstance = SolovayStrassenPrimalityTest.getSolovayStrassenPrimalityTest(RANDOM_SEED); + } + + /** + * Provides test cases for prime numbers with various values of n and k (iterations). + * + * @return an array of objects containing pairs of n and k values + */ + static Object[][] primeNumbers() { + return new Object[][]{ + {2, 1}, {3, 1}, {5, 5}, {7, 10}, + {11, 20}, {13, 10}, {17, 5}, {19, 1} + }; + } + + /** + * Tests known prime numbers with various values of n and k (iterations). + * + * @param n the number to be tested for primality + * @param k the number of iterations to use in the primality test + */ + @ParameterizedTest + @MethodSource("primeNumbers") + void testPrimeNumbersWithDifferentNAndK(int n, int k) { + assertTrue(testInstance.solovayStrassen(n, k), n + " should be prime"); + } + + /** + * Provides test cases for composite numbers with various values of n and k (iterations). + * + * @return an array of objects containing pairs of n and k values + */ + static Object[][] compositeNumbers() { + return new Object[][]{ + {4, 1}, {6, 5}, {8, 10}, {9, 20}, + {10, 1}, {12, 5}, {15, 10} + }; + } + + /** + * Tests known composite numbers with various values of n and k (iterations). + * + * @param n the number to be tested for primality + * @param k the number of iterations to use in the primality test + */ + @ParameterizedTest + @MethodSource("compositeNumbers") + void testCompositeNumbersWithDifferentNAndK(int n, int k) { + assertFalse(testInstance.solovayStrassen(n, k), n + " should be composite"); + } + + /** + * Tests edge cases for the primality test. + * This includes negative numbers and small integers (0 and 1). + */ + @Test + void testEdgeCases() { + assertFalse(testInstance.solovayStrassen(-1, 10), "-1 should not be prime"); + assertFalse(testInstance.solovayStrassen(0, 10), "0 should not be prime"); + assertFalse(testInstance.solovayStrassen(1, 10), "1 should not be prime"); + + // Test small primes and composites + assertTrue(testInstance.solovayStrassen(2, 1), "2 is a prime number (single iteration)"); + assertFalse(testInstance.solovayStrassen(9, 1), "9 is a composite number (single iteration)"); + + // Test larger primes and composites + long largePrime = 104729; // Known large prime number + long largeComposite = 104730; // Known composite number (even) + + assertTrue(testInstance.solovayStrassen(largePrime, 20), "104729 is a prime number"); + assertFalse(testInstance.solovayStrassen(largeComposite, 20), "104730 is a composite number"); + + // Test very large numbers (may take longer) + long veryLargePrime = 512927357; // Near the upper limit of long + long veryLargeComposite = 512927358; // Composite (even) + + assertTrue(testInstance.solovayStrassen(veryLargePrime, 20), + Long.MAX_VALUE - 1 + " is likely a prime number."); + + assertFalse(testInstance.solovayStrassen(veryLargeComposite, 20), + Long.MAX_VALUE + " is a composite number."); + } + + /** + * Tests the Jacobi symbol calculation directly for known values. + * This verifies that the Jacobi symbol method behaves as expected. + */ + @Test + void testJacobiSymbolCalculation() { + // Jacobi symbol (a/n) where n is odd and positive + int jacobi1 = testInstance.calculateJacobi(6, 11); // Should return -1 + int jacobi2 = testInstance.calculateJacobi(5, 11); // Should return +1 + int jacobi3 = testInstance.calculateJacobi(4, 11); // Should return +1 + + assertEquals(-1, jacobi1); + assertEquals(+1, jacobi2); + assertEquals(+1, jacobi3); + + // Edge case: Jacobi symbol with even n or non-positive n + int jacobi4 = testInstance.calculateJacobi(5, -11); // Should return 0 (invalid) + int jacobi5 = testInstance.calculateJacobi(5, 0); // Should return 0 (invalid) + + assertEquals(0, jacobi4); + assertEquals(0, jacobi5); + } +} \ No newline at end of file From db29206ea3ac4eaa0ccbc56b66d045a933015f97 Mon Sep 17 00:00:00 2001 From: saahil-mahato Date: Thu, 10 Oct 2024 10:06:18 +0545 Subject: [PATCH 2/6] chore: add wikipedia link --- .../com/thealgorithms/maths/SolovayStrassenPrimalityTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/com/thealgorithms/maths/SolovayStrassenPrimalityTest.java b/src/main/java/com/thealgorithms/maths/SolovayStrassenPrimalityTest.java index 4523f1b2611f..65b4626c73ee 100644 --- a/src/main/java/com/thealgorithms/maths/SolovayStrassenPrimalityTest.java +++ b/src/main/java/com/thealgorithms/maths/SolovayStrassenPrimalityTest.java @@ -6,6 +6,8 @@ * This class implements the Solovay-Strassen primality test, * which is a probabilistic algorithm to determine whether a number is prime. * The algorithm is based on properties of the Jacobi symbol and modular exponentiation. + * + * For more information, go to {@link https://en.wikipedia.org/wiki/Solovay%E2%80%93Strassen_primality_test} */ class SolovayStrassenPrimalityTest { From 65bbfb9687b34f470023ade54411ad8a829ca4c7 Mon Sep 17 00:00:00 2001 From: saahil-mahato Date: Thu, 10 Oct 2024 10:54:40 +0545 Subject: [PATCH 3/6] fix: format and coverage --- .../maths/SolovayStrassenPrimalityTest.java | 27 ++++++------ .../SolovayStrassenPrimalityTestTest.java | 44 +++++++------------ 2 files changed, 30 insertions(+), 41 deletions(-) diff --git a/src/main/java/com/thealgorithms/maths/SolovayStrassenPrimalityTest.java b/src/main/java/com/thealgorithms/maths/SolovayStrassenPrimalityTest.java index 65b4626c73ee..c42f7bdc51a8 100644 --- a/src/main/java/com/thealgorithms/maths/SolovayStrassenPrimalityTest.java +++ b/src/main/java/com/thealgorithms/maths/SolovayStrassenPrimalityTest.java @@ -3,10 +3,10 @@ import java.util.Random; /** - * This class implements the Solovay-Strassen primality test, + * This class implements the Solovay-Strassen primality test, * which is a probabilistic algorithm to determine whether a number is prime. * The algorithm is based on properties of the Jacobi symbol and modular exponentiation. - * + * * For more information, go to {@link https://en.wikipedia.org/wiki/Solovay%E2%80%93Strassen_primality_test} */ class SolovayStrassenPrimalityTest { @@ -46,14 +46,13 @@ private static long calculateModularExponentiation(long base, long exponent, lon while (exponent > 0) { // If exponent is odd, multiply the current base (y) with x - if (exponent % 2 == 1) - x = (x * y) % mod; // Update result with current base + if (exponent % 2 == 1) x = (x * y) % mod; // Update result with current base // Square the base for the next iteration y = (y * y) % mod; // Update base to be y^2 exponent = exponent / 2; // Halve the exponent for next iteration } - + return x % mod; // Return final result after all iterations } @@ -107,22 +106,22 @@ public int calculateJacobi(long a, long num) { */ public boolean solovayStrassen(long num, int iterations) { if (num <= 1) return false; // Numbers <=1 are not prime by definition. - if (num <= 3) return true; // Numbers <=3 are prime. + if (num <= 3) return true; // Numbers <=3 are prime. for (int i = 0; i < iterations; i++) { - long r = (random.nextLong() & Long.MAX_VALUE); // Generate a non-negative random number. + long r = Math.abs(random.nextLong() % (num - 1)) + 2; // Generate a non-negative random number. long a = r % (num - 1) + 1; // Choose random 'a' in range [1, n-1]. - - long jacobi = (num + calculateJacobi(a, num)) % num; - // Calculate Jacobi symbol and adjust it modulo n. - - long mod = calculateModularExponentiation(a, (num - 1) / 2, num); + + long jacobi = (num + calculateJacobi(a, num)) % num; + // Calculate Jacobi symbol and adjust it modulo n. + + long mod = calculateModularExponentiation(a, (num - 1) / 2, num); // Calculate modular exponentiation: a^((n-1)/2) mod n. - if (jacobi == 0 || mod != jacobi) return false; + if (jacobi == 0 || mod != jacobi) return false; // If Jacobi symbol is zero or doesn't match modular result, n is composite. } return true; // If no contradictions found after all iterations, n is likely prime. } -} \ No newline at end of file +} diff --git a/src/test/java/com/thealgorithms/maths/SolovayStrassenPrimalityTestTest.java b/src/test/java/com/thealgorithms/maths/SolovayStrassenPrimalityTestTest.java index f500dd70997b..86904d9ff8bf 100644 --- a/src/test/java/com/thealgorithms/maths/SolovayStrassenPrimalityTestTest.java +++ b/src/test/java/com/thealgorithms/maths/SolovayStrassenPrimalityTestTest.java @@ -1,12 +1,12 @@ package com.thealgorithms.maths; +import static org.junit.jupiter.api.Assertions.*; + import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; -import static org.junit.jupiter.api.Assertions.*; - /** * Unit tests for the {@link SolovayStrassenPrimalityTest} class. * This class tests the functionality of the Solovay-Strassen primality test implementation. @@ -17,7 +17,7 @@ class SolovayStrassenPrimalityTestTest { private SolovayStrassenPrimalityTest testInstance; /** - * Sets up a new instance of {@link SolovayStrassenPrimalityTest} + * Sets up a new instance of {@link SolovayStrassenPrimalityTest} * before each test case, using a fixed random seed for consistency. */ @BeforeEach @@ -31,10 +31,7 @@ void setUp() { * @return an array of objects containing pairs of n and k values */ static Object[][] primeNumbers() { - return new Object[][]{ - {2, 1}, {3, 1}, {5, 5}, {7, 10}, - {11, 20}, {13, 10}, {17, 5}, {19, 1} - }; + return new Object[][] {{2, 1}, {3, 1}, {5, 5}, {7, 10}, {11, 20}, {13, 10}, {17, 5}, {19, 1}}; } /** @@ -55,10 +52,7 @@ void testPrimeNumbersWithDifferentNAndK(int n, int k) { * @return an array of objects containing pairs of n and k values */ static Object[][] compositeNumbers() { - return new Object[][]{ - {4, 1}, {6, 5}, {8, 10}, {9, 20}, - {10, 1}, {12, 5}, {15, 10} - }; + return new Object[][] {{4, 1}, {6, 5}, {8, 10}, {9, 20}, {10, 1}, {12, 5}, {15, 10}}; } /** @@ -89,20 +83,18 @@ void testEdgeCases() { // Test larger primes and composites long largePrime = 104729; // Known large prime number - long largeComposite = 104730; // Known composite number (even) - + long largeComposite = 104730; // Composite number (even) + assertTrue(testInstance.solovayStrassen(largePrime, 20), "104729 is a prime number"); assertFalse(testInstance.solovayStrassen(largeComposite, 20), "104730 is a composite number"); // Test very large numbers (may take longer) - long veryLargePrime = 512927357; // Near the upper limit of long - long veryLargeComposite = 512927358; // Composite (even) - - assertTrue(testInstance.solovayStrassen(veryLargePrime, 20), - Long.MAX_VALUE - 1 + " is likely a prime number."); - - assertFalse(testInstance.solovayStrassen(veryLargeComposite, 20), - Long.MAX_VALUE + " is a composite number."); + long veryLargePrime = 512927357; // Known very large prime number + long veryLargeComposite = 512927358; // Composite number (even) + + assertTrue(testInstance.solovayStrassen(veryLargePrime, 20), Long.MAX_VALUE - 1 + " is likely a prime number."); + + assertFalse(testInstance.solovayStrassen(veryLargeComposite, 20), Long.MAX_VALUE + " is a composite number."); } /** @@ -114,17 +106,15 @@ void testJacobiSymbolCalculation() { // Jacobi symbol (a/n) where n is odd and positive int jacobi1 = testInstance.calculateJacobi(6, 11); // Should return -1 int jacobi2 = testInstance.calculateJacobi(5, 11); // Should return +1 - int jacobi3 = testInstance.calculateJacobi(4, 11); // Should return +1 assertEquals(-1, jacobi1); assertEquals(+1, jacobi2); - assertEquals(+1, jacobi3); - + // Edge case: Jacobi symbol with even n or non-positive n int jacobi4 = testInstance.calculateJacobi(5, -11); // Should return 0 (invalid) - int jacobi5 = testInstance.calculateJacobi(5, 0); // Should return 0 (invalid) - + int jacobi5 = testInstance.calculateJacobi(5, 0); // Should return 0 (invalid) + assertEquals(0, jacobi4); assertEquals(0, jacobi5); } -} \ No newline at end of file +} From 90c14f92f6ff12ac2429a40f701f1e808cad7a42 Mon Sep 17 00:00:00 2001 From: saahil-mahato Date: Thu, 10 Oct 2024 11:03:41 +0545 Subject: [PATCH 4/6] fix: mvn stylecheck --- .../maths/SolovayStrassenPrimalityTest.java | 20 ++++++++++++------- .../SolovayStrassenPrimalityTestTest.java | 4 +++- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/thealgorithms/maths/SolovayStrassenPrimalityTest.java b/src/main/java/com/thealgorithms/maths/SolovayStrassenPrimalityTest.java index c42f7bdc51a8..27a099976902 100644 --- a/src/main/java/com/thealgorithms/maths/SolovayStrassenPrimalityTest.java +++ b/src/main/java/com/thealgorithms/maths/SolovayStrassenPrimalityTest.java @@ -9,7 +9,7 @@ * * For more information, go to {@link https://en.wikipedia.org/wiki/Solovay%E2%80%93Strassen_primality_test} */ -class SolovayStrassenPrimalityTest { +final class SolovayStrassenPrimalityTest { private Random random; @@ -46,8 +46,9 @@ private static long calculateModularExponentiation(long base, long exponent, lon while (exponent > 0) { // If exponent is odd, multiply the current base (y) with x - if (exponent % 2 == 1) x = (x * y) % mod; // Update result with current base - + if (exponent % 2 == 1) { + x = (x * y) % mod; // Update result with current base + } // Square the base for the next iteration y = (y * y) % mod; // Update base to be y^2 exponent = exponent / 2; // Halve the exponent for next iteration @@ -105,8 +106,12 @@ public int calculateJacobi(long a, long num) { * @return true if num is likely prime, false if it is composite */ public boolean solovayStrassen(long num, int iterations) { - if (num <= 1) return false; // Numbers <=1 are not prime by definition. - if (num <= 3) return true; // Numbers <=3 are prime. + if (num <= 1) { + return false; // Numbers <=1 are not prime by definition. + } + if (num <= 3) { + return true; // Numbers <=3 are prime. + } for (int i = 0; i < iterations; i++) { long r = Math.abs(random.nextLong() % (num - 1)) + 2; // Generate a non-negative random number. @@ -118,8 +123,9 @@ public boolean solovayStrassen(long num, int iterations) { long mod = calculateModularExponentiation(a, (num - 1) / 2, num); // Calculate modular exponentiation: a^((n-1)/2) mod n. - if (jacobi == 0 || mod != jacobi) return false; - // If Jacobi symbol is zero or doesn't match modular result, n is composite. + if (jacobi == 0 || mod != jacobi) { + return false; // If Jacobi symbol is zero or doesn't match modular result, n is composite. + } } return true; // If no contradictions found after all iterations, n is likely prime. diff --git a/src/test/java/com/thealgorithms/maths/SolovayStrassenPrimalityTestTest.java b/src/test/java/com/thealgorithms/maths/SolovayStrassenPrimalityTestTest.java index 86904d9ff8bf..18cc35266c8c 100644 --- a/src/test/java/com/thealgorithms/maths/SolovayStrassenPrimalityTestTest.java +++ b/src/test/java/com/thealgorithms/maths/SolovayStrassenPrimalityTestTest.java @@ -1,6 +1,8 @@ package com.thealgorithms.maths; -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.assertTrue; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; From cbe6da980b770cafc8d184d8b274b9a09b62f333 Mon Sep 17 00:00:00 2001 From: saahil-mahato Date: Thu, 10 Oct 2024 11:08:08 +0545 Subject: [PATCH 5/6] fix: PMD errors --- .../com/thealgorithms/maths/SolovayStrassenPrimalityTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/thealgorithms/maths/SolovayStrassenPrimalityTest.java b/src/main/java/com/thealgorithms/maths/SolovayStrassenPrimalityTest.java index 27a099976902..04be7bee04df 100644 --- a/src/main/java/com/thealgorithms/maths/SolovayStrassenPrimalityTest.java +++ b/src/main/java/com/thealgorithms/maths/SolovayStrassenPrimalityTest.java @@ -47,10 +47,10 @@ private static long calculateModularExponentiation(long base, long exponent, lon while (exponent > 0) { // If exponent is odd, multiply the current base (y) with x if (exponent % 2 == 1) { - x = (x * y) % mod; // Update result with current base + x = x * y % mod; // Update result with current base } // Square the base for the next iteration - y = (y * y) % mod; // Update base to be y^2 + y = y * y % mod; // Update base to be y^2 exponent = exponent / 2; // Halve the exponent for next iteration } From ee248b8953f6949a94d7c6bea1ec4c04e128825c Mon Sep 17 00:00:00 2001 From: saahil-mahato Date: Thu, 10 Oct 2024 17:12:48 +0545 Subject: [PATCH 6/6] refactor: make random final --- .../com/thealgorithms/maths/SolovayStrassenPrimalityTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/thealgorithms/maths/SolovayStrassenPrimalityTest.java b/src/main/java/com/thealgorithms/maths/SolovayStrassenPrimalityTest.java index 04be7bee04df..caa1abfc3203 100644 --- a/src/main/java/com/thealgorithms/maths/SolovayStrassenPrimalityTest.java +++ b/src/main/java/com/thealgorithms/maths/SolovayStrassenPrimalityTest.java @@ -11,7 +11,7 @@ */ final class SolovayStrassenPrimalityTest { - private Random random; + private final Random random; /** * Constructs a SolovayStrassenPrimalityTest instance with a specified seed for randomness.