{"record":{"id":"67c4c76946e17d59","repo":"TheAlgorithms/Java","slug":"n-must-be-positive-and-odd","errorCode":null,"errorMessage":"n must be positive and odd.","messagePattern":"n must be positive and odd\\.","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"src/main/java/com/thealgorithms/maths/EulerPseudoprime.java","lineNumber":69,"sourceCode":"\n            BigInteger exp = n.subtract(BigInteger.ONE).divide(BigInteger.TWO);\n            BigInteger modExp = a.modPow(exp, n);\n\n            // Euler's criterion: a^((n-1)/2) ≡ (a/n) (mod n)\n            if (!modExp.equals(jacobi.mod(n))) {\n                return false; // definitely composite\n            }\n        }\n        return true; // probably prime\n    }\n\n    /**\n     * Computes the Jacobi symbol (a/n).\n     * Assumes n is positive and odd.\n     */\n    public static int jacobiSymbol(BigInteger a, BigInteger n) {\n        if (n.signum() <= 0 || n.mod(BigInteger.TWO).equals(BigInteger.ZERO)) {\n            throw new IllegalArgumentException(\"n must be positive and odd.\");\n        }\n\n        int result = 1;\n        a = a.mod(n);\n\n        while (a.compareTo(BigInteger.ZERO) != 0) {\n            while (a.mod(BigInteger.TWO).equals(BigInteger.ZERO)) {\n                a = a.divide(BigInteger.TWO);\n                BigInteger nMod8 = n.mod(BigInteger.valueOf(8));\n                if (nMod8.equals(BigInteger.valueOf(3)) || nMod8.equals(BigInteger.valueOf(5))) {\n                    result = -result;\n                }\n            }\n\n            BigInteger temp = a;\n            a = n;\n            n = temp;\n","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/TheAlgorithms/Java/blob/fdfb9a395b310167a66bd29e311e36e0e3e9b964/src/main/java/com/thealgorithms/maths/EulerPseudoprime.java#L51-L87","documentation":"Thrown by EulerPseudoprime.jacobiSymbol when n is not positive or not odd. The Jacobi symbol (a/n) is defined for odd positive n; even or non-positive n have no Jacobi symbol under the standard definition. The implementation's reduction loop (halving a, checking n mod 8) assumes n is odd, so the guard prevents mathematically meaningless and incorrect computation.","triggerScenarios":"Calling jacobiSymbol(a, n) with n <= 0 (e.g. BigInteger.ZERO or a negative), or n even (e.g. BigInteger.valueOf(2), 4, 10). Common when n is an arbitrary modulus not constrained to odd primes, or when n comes from user input.","commonSituations":"Using a general modulus instead of an odd one; feeding an even composite; n parsed from input without parity validation; confusing Jacobi with a general modular operation.","solutions":["Pass an odd positive BigInteger for n, e.g. jacobiSymbol(a, BigInteger.valueOf(9)).","Validate n at the caller: ensure n.signum() > 0 and n is odd before calling.","If you need Legendre symbols, ensure n is an odd prime."],"exampleFix":"// before\nint j = EulerPseudoprime.jacobiSymbol(a, BigInteger.valueOf(8)); // even => throws\n\n// after\nint j = EulerPseudoprime.jacobiSymbol(a, BigInteger.valueOf(9));","handlingStrategy":"validation","validationCode":"if (n.signum() <= 0 || n.mod(BigInteger.TWO).equals(BigInteger.ZERO)) {\n    throw new IllegalArgumentException(\"Jacobi n must be positive and odd\");\n}\nEulerPseudoprime.jacobiSymbol(a, n);","typeGuard":"static boolean isOddPositive(BigInteger n) {\n    return n.signum() > 0 && n.testBit(0);\n}","tryCatchPattern":null,"preventionTips":["Constrain n to odd positive values at the source (prime generation, validated input).","Use n.testBit(0) for an efficient oddness check.","Do not feed arbitrary moduli; the Jacobi symbol is defined only for odd positive n."],"tags":["validation","number-theory","cryptographic","precondition"],"backgroundTag":null,"analyzedSha":"fdfb9a395b310167a66bd29e311e36e0e3e9b964","analyzedAt":"2026-08-13T23:36:13.315Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}