package nl.bluering; import java.util.*; import java.math.BigInteger; /** * This library handles the java BigIntegers */ public class BigIntLib extends Interpreter { /** * For each function this Lib supports there is a constant. * By using the constant you can switch/case to the right code, which is * fast than string comparision */ public final static int ZERO=0,ONE=1,CONSTRUCT=2,CONSTRUCT2=3,ADD=4,SUB=5,NEG=6,MOD=7; public final static int MODPOW=8,ABS=9,AND=10,OR=11,XOR=12,RANDOM=13,PRIME=15,ISPRIME=16; public final static int DIV=17,MUL=18,GCD=19,MODINV=20,POW=21,LSHIFT=22,RSHIFT=23,SIGNUM=24; public final static int STRING=25,BITLENGTH=26; BigIntLib() { } static BigInteger biZERO=new BigInteger("0"); static BigInteger biONE=new BigInteger("1"); static Class bigintclass=biZERO.getClass(); public void mountall() { mspecial("bi_zero",0,ZERO,"return bigInteger with value 0"); mspecial("bi_one",0,ONE,"return bigInteger with value 1"); mspecial("newbigint",1,CONSTRUCT,"convert int or string to bigInteger"); mspecial("newbigint",2,CONSTRUCT2,"convert string a0 in radix a1 notation to BigInteger"); mnormal("add",2,ADD,"add two bigintegers",bigintclass); mnormal("sub",2,SUB,"subtract tow integers",bigintclass); mnormal("neg",1,NEG,"return -a0 for a bigint a0",bigintclass); mnormal("mod",2,MOD,"return the remainder of a0 from division by a1",bigintclass); mnormal("modexp",3,MODPOW,"return (a0**a1)%a2",bigintclass); mnormal("abs",1,ABS,"return the distance to zero",bigintclass); mnormal("and",2,AND,"do bitwise and on two numbers",bigintclass); mnormal("or",2,OR,"do bitwise or on two numbers",bigintclass); mnormal("xor",2,XOR,"do bitwise XOR on two numbers",bigintclass); mnormal("random",1,RANDOM,"create random bigint of a0 bits",bigintclass); mspecial("newprime",1,PRIME,"create random prime of a0 bits"); mnormal("isprime",1,ISPRIME,"returns true if bigint a0 is prime",bigintclass); mnormal("div",2,DIV,"divide two bigInts",bigintclass); mnormal("mul",2,MUL,"divide two BigInts",bigintclass); mnormal("gcd",2,GCD,"get greatest common divisor of two bigints",bigintclass); mnormal("modinv",2,MODINV,"get the inverse of a0 in Z_a1",bigintclass); mnormal("exp",2,POW,"raise a0 to the power a1",bigintclass); mnormal("shift",2,LSHIFT,"shift a0 a1 places to the left",bigintclass); mnormal("rshift",2,RSHIFT,"shift a0 a1 places to the right",bigintclass); mnormal("sign",1,SIGNUM,"return -1 if a0<0, 1 if a0>0, or 0",bigintclass); mnormal("length",1,BITLENGTH,"return the number of bits of a0",bigintclass); mnormal("tostring",2,STRING,"convert a0 to string using radius a1",bigintclass); } public Variable run(Variable result,Expression e,int index) throws Exception {Object o1,o2,o3; BigInteger bi0,bi1,bi2; int size,i1; switch(index) {case ZERO: result.set(biZERO); break; case ONE: result.set(biONE); break; case CONSTRUCT: result.set(new BigInteger(root.run(result,e.get(0)).getstring()));break; case CONSTRUCT2: String data=root.run(result,e.get(0)).getstring(); int base=root.run(result,e.get(1)).getint(); result.set(new BigInteger(data,base)); break; case ADD: bi0=getbi(result,e,0); bi1=getbi(result,e,1); result.set(bi0.add(bi1)); break; case SUB: bi0=getbi(result,e,0); bi1=getbi(result,e,1); result.set(bi0.subtract(bi1)); break; case NEG: bi0=getbi(result,e,0); result.set(bi0.negate()); break; case MOD: bi0=getbi(result,e,0); bi1=getbi(result,e,1); result.set(bi0.mod(bi1)); break; case MODPOW: bi0=getbi(result,e,0); bi1=getbi(result,e,1); bi2=getbi(result,e,2); result.set(bi0.modPow(bi1,bi2)); break; case ABS: bi0=getbi(result,e,0); result.set(bi0.abs()); case AND: bi0=getbi(result,e,0); bi1=getbi(result,e,1); result.set(bi0.and(bi1)); break; case OR: bi0=getbi(result,e,0); bi1=getbi(result,e,1); result.set(bi0.or(bi1)); break; case XOR: bi0=getbi(result,e,0); bi1=getbi(result,e,1); result.set(bi0.xor(bi1)); break; case RANDOM: size=root.run(result,e.get(0)).getint(); result.set(new BigInteger(size,new Random())); break; case PRIME: size=root.run(result,e.get(0)).getint(); result.set(new BigInteger(size,20,new Random())); break; case ISPRIME: bi0=getbi(result,e,0); result.set(bi0.isProbablePrime(20)); break; case DIV: bi0=getbi(result,e,0); bi1=getbi(result,e,1); result.set(bi0.divide(bi1)); break; case MUL: bi0=getbi(result,e,0); bi1=getbi(result,e,1); result.set(bi0.multiply(bi1)); break; case GCD: bi0=getbi(result,e,0); bi1=getbi(result,e,1); result.set(bi0.gcd(bi1)); break; case MODINV: bi0=getbi(result,e,0); bi1=getbi(result,e,1); result.set(bi0.modInverse(bi1)); break; case POW: bi0=getbi(result,e,0); i1=root.run(result,e.get(1)).getint(); result.set(bi0.pow(i1)); break; case LSHIFT: bi0=getbi(result,e,0); i1=root.run(result,e.get(1)).getint(); result.set(bi0.shiftLeft(i1)); break; case RSHIFT: bi0=getbi(result,e,0); i1=root.run(result,e.get(1)).getint(); result.set(bi0.shiftRight(i1)); break; case SIGNUM: bi0=getbi(result,e,0); result.set(bi0.signum()); break; case BITLENGTH: bi0=getbi(result,e,0); result.set(bi0.bitLength()); break; case STRING: bi0=getbi(result,e,0); int radix=root.run(result,e.get(1)).getint(); result.set(bi0.toString(radix)); break; } return result; } }