net.i2p.util
Class NativeBigInteger

java.lang.Object
  extended by java.lang.Number
      extended by java.math.BigInteger
          extended by net.i2p.util.NativeBigInteger
All Implemented Interfaces:
java.io.Serializable, java.lang.Comparable<java.math.BigInteger>

public class NativeBigInteger
extends java.math.BigInteger

BigInteger that takes advantage of the jbigi library for the modPow operation, which accounts for a massive segment of the processing cost of asymmetric crypto. It also takes advantage of the jbigi library for converting a BigInteger value to a double. Sun's implementation of the 'doubleValue()' method is _very_ lousy. The jbigi library itself is basically just a JNI wrapper around the GMP library - a collection of insanely efficient routines for dealing with big numbers.

There are three environmental properties for configuring this component:

If jbigi.enable is set to false, this class won't even attempt to use the native library, but if it is set to true (or is not specified), it will first check the platform specific library path for the "jbigi" library, as defined by Runtime.loadLibrary(java.lang.String) - e.g. C:\windows\jbigi.dll or /lib/libjbigi.so, as well as the CLASSPATH for a resource named 'jbigi'. If that fails, it reviews the jbigi.impl environment property - if that is set, it checks all of the components in the CLASSPATH for the file specified and attempts to load it as the native library. If jbigi.impl is not set, it uses the jcpuid library described below. If there is still no matching resource, or if that resource is not a valid OS/architecture specific library, the NativeBigInteger will revert to using the pure java implementation.

When attempting to load the native implementation as a resource from the CLASSPATH, the NativeBigInteger will make use of the jcpuid component which runs some assembly code to determine the current CPU implementation, such as "pentium4" or "k623". We then use that, combined with the OS, to build an optimized resource name - e.g. "net/i2p/util/libjbigi-freebsd-pentium4.so" or "net/i2p/util/jbigi-windows-k623.dll". If that resource exists, we use it. If it doesn't (or the jcpuid component fails), we try a generic native implementation using "none" for the CPU (ala "net/i2p/util/jbigi-windows-none.dll").

Running this class by itself does a basic unit test and benchmarks the NativeBigInteger.modPow/doubleValue vs. the BigInteger.modPow/doubleValue by running a 2Kbit op 100 times. At the end of each test, if the native implementation is loaded this will output something like:

  native run time:        6090ms (60ms each)
  java run time:          68067ms (673ms each)
  native = 8.947066860593239% of pure java time
 

If the native implementation is not loaded, it will start by saying:

  WARN: Native BigInteger library jbigi not loaded - using pure java
 

Then go on to run the test, finally outputting:

  java run time:  64653ms (640ms each)
  However, we couldn't load the native library, so this doesn't test much
 

See Also:
Serialized Form

Field Summary
 
Fields inherited from class java.math.BigInteger
ONE, TEN, ZERO
 
Constructor Summary
NativeBigInteger(java.math.BigInteger integer)
          Creates a new NativeBigInteger with the same value as the supplied BigInteger.
NativeBigInteger(byte[] val)
           
NativeBigInteger(int signum, byte[] magnitude)
           
NativeBigInteger(int bitlen, int certainty, java.util.Random rnd)
           
NativeBigInteger(int numbits, java.util.Random rnd)
           
NativeBigInteger(java.lang.String val)
           
NativeBigInteger(java.lang.String val, int radix)
           
 
Method Summary
static java.lang.String cpuModel()
           
static java.lang.String cpuType()
           
 double doubleValue()
          Deprecated. unused
static boolean isNative()
           
static java.lang.String loadStatus()
           
static void main(java.lang.String[] args)
          Compare the BigInteger.modPow/doubleValue vs the NativeBigInteger.modPow/doubleValue of some really big (2Kbit) numbers 100 different times and benchmark the performance (or shit a brick if they don't match).
 java.math.BigInteger modPow(java.math.BigInteger exponent, java.math.BigInteger m)
           
static double nativeDoubleValue(byte[] ba)
          Deprecated. unused
static byte[] nativeModPow(byte[] base, byte[] exponent, byte[] modulus)
          calculate (base ^ exponent) % modulus.
 byte[] toByteArray()
           
 
Methods inherited from class java.math.BigInteger
abs, add, and, andNot, bitCount, bitLength, clearBit, compareTo, divide, divideAndRemainder, equals, flipBit, floatValue, gcd, getLowestSetBit, hashCode, intValue, isProbablePrime, longValue, max, min, mod, modInverse, multiply, negate, nextProbablePrime, not, or, pow, probablePrime, remainder, setBit, shiftLeft, shiftRight, signum, subtract, testBit, toString, toString, valueOf, xor
 
Methods inherited from class java.lang.Number
byteValue, shortValue
 
Methods inherited from class java.lang.Object
clone, finalize, getClass, notify, notifyAll, wait, wait, wait
 

Constructor Detail

NativeBigInteger

public NativeBigInteger(byte[] val)

NativeBigInteger

public NativeBigInteger(int signum,
                        byte[] magnitude)

NativeBigInteger

public NativeBigInteger(int bitlen,
                        int certainty,
                        java.util.Random rnd)

NativeBigInteger

public NativeBigInteger(int numbits,
                        java.util.Random rnd)

NativeBigInteger

public NativeBigInteger(java.lang.String val)

NativeBigInteger

public NativeBigInteger(java.lang.String val,
                        int radix)

NativeBigInteger

public NativeBigInteger(java.math.BigInteger integer)
Creates a new NativeBigInteger with the same value as the supplied BigInteger. Warning!, not very efficent

Method Detail

nativeModPow

public static byte[] nativeModPow(byte[] base,
                                  byte[] exponent,
                                  byte[] modulus)
calculate (base ^ exponent) % modulus.

Parameters:
base - big endian twos complement representation of the base (but it must be positive)
exponent - big endian twos complement representation of the exponent
modulus - big endian twos complement representation of the modulus
Returns:
big endian twos complement representation of (base ^ exponent) % modulus

nativeDoubleValue

public static double nativeDoubleValue(byte[] ba)
Deprecated. unused

Converts a BigInteger byte-array to a 'double'

Parameters:
ba - Big endian twos complement representation of the BigInteger to convert to a double
Returns:
The plain double-value represented by 'ba'

modPow

public java.math.BigInteger modPow(java.math.BigInteger exponent,
                                   java.math.BigInteger m)
Overrides:
modPow in class java.math.BigInteger

toByteArray

public byte[] toByteArray()
Overrides:
toByteArray in class java.math.BigInteger

doubleValue

public double doubleValue()
Deprecated. unused

Overrides:
doubleValue in class java.math.BigInteger

isNative

public static boolean isNative()
Returns:
True iff native methods will be used by this class

loadStatus

public static java.lang.String loadStatus()

cpuType

public static java.lang.String cpuType()

cpuModel

public static java.lang.String cpuModel()

main

public static void main(java.lang.String[] args)

Compare the BigInteger.modPow/doubleValue vs the NativeBigInteger.modPow/doubleValue of some really big (2Kbit) numbers 100 different times and benchmark the performance (or shit a brick if they don't match).