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/Oracle'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:
- jbigi.enable: whether to use the native library (defaults to "true")
- jbigi.impl: select which resource to use as the native implementation
- jbigi.ref: the file specified in this parameter may contain a resource name to override jbigi.impl (defaults to "jbigi.cfg")
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 {@link Runtime#loadLibrary} - e.g. C:\windows\jbigi.dll or /lib/libjbigi.so.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, if there is 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.
That means NativeBigInteger will not attempt to guess the correct platform/OS/whatever - applications using this class should define that property prior to referencing the NativeBigInteger (or before loading the JVM, of course). Alternately, people with custom built jbigi implementations in their OS's standard search path (LD_LIBRARY_PATH, etc) needn't bother.
One way to deploy the native library is to create a jbigi.jar file containing all of the native implementations with filenames such as "win-athlon", "linux-p2", "freebsd-sparcv4", where those files are the OS specific libraries (the contents of the DLL or .so file built for those OSes / architectures). The user would then simply specify -Djbigi.impl=win-athlon and this component would pick up that library.
Another way is to create a separate jbigi.jar file for each platform containing one file - "native", where that file is the OS / architecture specific library implementation, as above. This way the user would download the correct jbigi.jar (and not all of the libraries for platforms/OSes they don't need) and would specify -Djbigi.impl=native.
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