Permalink
Browse files

Support mpz_kronecker.

  • Loading branch information...
ruescasd authored and dragonsinth committed Apr 22, 2016
1 parent d59ba75 commit 98d6f1784017ca75a2604269eaf8b500856fb77c
View
@@ -28,6 +28,7 @@ Available on Maven central as `com.squareup.jnagmp:bouncycastle-rsa`.
- Christian Meier <meier.kristian@gmail.com> - classloader fix
- Elijah Zupancic <elijah.zupancic@joyent.com> - Solaris binary build
- Wilko Henecka <wilko.henecka@nicta.com.au> - modInverse
- David Ruescas <fastness@gmail.com> - kronecker
## Licensing
View
@@ -18,6 +18,10 @@ performance improvement would be on the order of 5x faster than Java.
A faster version of BigInteger.modInverse()
### kronecker (jacobi, legendre)
The GMP kronecker implementation generalizes jacobi and legendre symbols.
##Notes
- The maven artifact/jar embeds a precompiled libgmp for some platforms. LibGmp will
@@ -28,6 +28,7 @@
import static com.squareup.jnagmp.LibGmp.__gmpz_import;
import static com.squareup.jnagmp.LibGmp.__gmpz_init;
import static com.squareup.jnagmp.LibGmp.__gmpz_invert;
import static com.squareup.jnagmp.LibGmp.__gmpz_jacobi;
import static com.squareup.jnagmp.LibGmp.__gmpz_neg;
import static com.squareup.jnagmp.LibGmp.__gmpz_powm;
import static com.squareup.jnagmp.LibGmp.__gmpz_powm_sec;
@@ -61,6 +62,7 @@ public static void checkLoaded() {
// 2 ^ 3 = 8, 8 mod 5 = 3
BigInteger two = BigInteger.valueOf(2);
BigInteger three = BigInteger.valueOf(3);
BigInteger four = BigInteger.valueOf(4);
BigInteger five = BigInteger.valueOf(5);
BigInteger answer;
@@ -73,6 +75,22 @@ public static void checkLoaded() {
if (!three.equals(answer)) {
throw new AssertionError("libgmp is loaded but modPowSecure returned the wrong answer");
}
int answr = kronecker(four, five);
if (answr != 1) {
throw new AssertionError("libgmp is loaded but kronecker returned the wrong answer");
}
}
/**
* Calculate kronecker symbol a|p. Generalization of legendre and jacobi.
*
* @param a an integer
* @param p the modulus
* @return a|p
*/
public static int kronecker(BigInteger a, BigInteger p) {
return INSTANCE.get().kroneckerImpl(a, p);
}
/**
@@ -199,6 +217,13 @@ private Gmp() {
assert offset == SHARED_MEM_SIZE;
}
private int kroneckerImpl(BigInteger a, BigInteger p) {
mpz_t aPeer = getPeer(a, sharedOperands[0]);
mpz_t pPeer = getPeer(p, sharedOperands[1]);
return __gmpz_jacobi(aPeer, pPeer);
}
private BigInteger modPowInsecureImpl(BigInteger base, BigInteger exp, BigInteger mod) {
mpz_t basePeer = getPeer(base, sharedOperands[0]);
mpz_t expPeer = getPeer(exp, sharedOperands[1]);
@@ -334,6 +334,13 @@ public static void __gmpz_export(Pointer rop, Pointer countp, int order, int siz
*/
public static native int __gmpz_invert(mpz_t rop, mpz_t op1, mpz_t op2);
/**
* Calculate the Jacobi symbol (a/p). This code does triple duty as mpz_jacobi, mpz_legendre and
* mpz_kronecker. For ABI compatibility, the link symbol is __gmpz_jacobi, not __gmpz_kronecker,
* even though the latter would be more logical.
*/
public static native int __gmpz_jacobi(mpz_t a, mpz_t p);
private LibGmp() {
}
}
@@ -23,6 +23,7 @@
import org.junit.BeforeClass;
import org.junit.Test;
import static com.squareup.jnagmp.Gmp.kronecker;
import static com.squareup.jnagmp.Gmp.modInverse;
import static com.squareup.jnagmp.Gmp.modPowInsecure;
import static com.squareup.jnagmp.Gmp.modPowSecure;
@@ -173,6 +174,52 @@ public void testModInverseArithmeticException() {
}
}
@Test
public void testKronecker() {
// Prime (legendre)
assertEquals(0, kronecker(BigInteger.valueOf(0), BigInteger.valueOf(7)));
assertEquals(1, kronecker(BigInteger.valueOf(1), BigInteger.valueOf(7)));
assertEquals(1, kronecker(BigInteger.valueOf(2), BigInteger.valueOf(7)));
assertEquals(-1, kronecker(BigInteger.valueOf(3), BigInteger.valueOf(7)));
assertEquals(1, kronecker(BigInteger.valueOf(4), BigInteger.valueOf(7)));
assertEquals(-1, kronecker(BigInteger.valueOf(5), BigInteger.valueOf(7)));
assertEquals(-1, kronecker(BigInteger.valueOf(6), BigInteger.valueOf(7)));
assertEquals(0, kronecker(BigInteger.valueOf(7), BigInteger.valueOf(7)));
// Non-prime odd (jacobi)
assertEquals(0, kronecker(BigInteger.valueOf(0), BigInteger.valueOf(9)));
assertEquals(1, kronecker(BigInteger.valueOf(1), BigInteger.valueOf(9)));
assertEquals(1, kronecker(BigInteger.valueOf(2), BigInteger.valueOf(9)));
assertEquals(0, kronecker(BigInteger.valueOf(3), BigInteger.valueOf(9)));
assertEquals(1, kronecker(BigInteger.valueOf(4), BigInteger.valueOf(9)));
assertEquals(1, kronecker(BigInteger.valueOf(5), BigInteger.valueOf(9)));
assertEquals(0, kronecker(BigInteger.valueOf(6), BigInteger.valueOf(9)));
assertEquals(1, kronecker(BigInteger.valueOf(7), BigInteger.valueOf(9)));
assertEquals(1, kronecker(BigInteger.valueOf(8), BigInteger.valueOf(9)));
assertEquals(0, kronecker(BigInteger.valueOf(9), BigInteger.valueOf(9)));
// Anything (kronecker)
assertEquals(0, kronecker(BigInteger.valueOf(0), BigInteger.valueOf(8)));
assertEquals(1, kronecker(BigInteger.valueOf(1), BigInteger.valueOf(8)));
assertEquals(0, kronecker(BigInteger.valueOf(2), BigInteger.valueOf(8)));
assertEquals(-1, kronecker(BigInteger.valueOf(3), BigInteger.valueOf(8)));
assertEquals(0, kronecker(BigInteger.valueOf(4), BigInteger.valueOf(8)));
assertEquals(-1, kronecker(BigInteger.valueOf(5), BigInteger.valueOf(8)));
assertEquals(0, kronecker(BigInteger.valueOf(6), BigInteger.valueOf(8)));
assertEquals(1, kronecker(BigInteger.valueOf(7), BigInteger.valueOf(8)));
assertEquals(0, kronecker(BigInteger.valueOf(8), BigInteger.valueOf(8)));
assertEquals(0, kronecker(BigInteger.valueOf(0), BigInteger.valueOf(-8)));
assertEquals(1, kronecker(BigInteger.valueOf(1), BigInteger.valueOf(-8)));
assertEquals(0, kronecker(BigInteger.valueOf(2), BigInteger.valueOf(-8)));
assertEquals(-1, kronecker(BigInteger.valueOf(3), BigInteger.valueOf(-8)));
assertEquals(0, kronecker(BigInteger.valueOf(4), BigInteger.valueOf(-8)));
assertEquals(-1, kronecker(BigInteger.valueOf(5), BigInteger.valueOf(-8)));
assertEquals(0, kronecker(BigInteger.valueOf(6), BigInteger.valueOf(-8)));
assertEquals(1, kronecker(BigInteger.valueOf(7), BigInteger.valueOf(-8)));
assertEquals(0, kronecker(BigInteger.valueOf(8), BigInteger.valueOf(-8)));
}
private void testOddExamples() {
// 2 ^ 3 = 8
assertEquals(2, modPow(2, 3, 3));

0 comments on commit 98d6f17

Please sign in to comment.