I had a closer look at LibBF. It is a very attractive library. It is pure C with a demo that you get a significantly faster version by enabling some CPU specific optimizations. It is a small pure C library using the MIT license, so we no longer need conditional compilation (with/without GMP). What makes it attractive is that it provides a single representation for computing with binary floats, decimal floats and big integers (bigints are represented as infinite precision floats). The next great point is that it is stateless. Functions take arguments to deal with precision and rounding (all modes) and a little context argument passes in the memory management functions. Functions properly return failure due to allocation failure. This means we can have a per-thread allocation context with and we do not need the hacky stuff to protect the process from aborting that we need with GMP (guess size, when in reasonable boundaries try the GMP, but wrap it using setjmp/longjmp as you may not return from an allocation attempt and do some tricky allocation wrapping).
I’ve implemented sin(X) and mul(X,Y) for bigints. sin(X) is about 10 times slower than Linux libm, so I did the same using mpfr, which is about 5 times slower. Mul wasn’t integrated as it eventually needs to be, but the performance seems not too far away from GMP. The package claims it looses on small numbers, but actually wins against GMP on (some) really big numbers. In our case, we can avoid a lot of the overhead due to the cleaner interface, providing hope for “small” big integers.
The main issue is the lack of support for rational numbers. That would need to be resolved. I do not know enough about these issues to judge how hard that would be. Of course, a rational number is just a pair of big integers, but how easy is the required normalization? Are there more clever tricks than high school math to deal with the basic multiplication, addition, etc? Probably some things are missing (e.g., random numbers). Some should be easy to replace.
Some float functions like sinh() are missing. We could wrap the libm versions for that. Possibly we could do that for all libm functions that we use to provide a runtime switch between quick and dirty or precise floats.
Another issue is how one should make rounding, precision and binary vs. decimal floats accessible to the Prolog user?
All in all, I think LibBF should be a serious candidate. Copying big numbers to the stack is comparable to GMP. The uniform representation, the fact that we do not need conditional compilation (#ifdef
) all over the place and proper failure codes on allocation failures should make the implementation a lot cleaner.
Portability seems no issue. The library has been extensively tested against mpfr. I tried sin(X), comparing native, LibBF and mpfr on random floats. About 1 in every few thousand attempts the native one disagrees, while LibBF and mpfr agree with each other. Using wcalc (based on mpfr), computing at higher precision I could validate that LibBF and mpfr were correct (by hand, so not many verifications).
Only, this is a serious amount of work. First access whether it is really a good idea, then implement. To get this done, we need programmers and/or money.
I don’t recall the details, but I think it is more serious than that on some functions.