Skip to content

An arbitrary precision library written in C which supports fractional datum. Arbitraire is fully portable to all linux, mac and netbsd/freebsd/openbsd architectures

License

Notifications You must be signed in to change notification settings

hlibc/arbitraire

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Arbitraire

	An arbitrary precision mathematics library. 
	
	Arbitraire supports a pure mathematics number system of continuous and
	arbitrarily sized fractional data. The following algorithms are used:
	
	Division:
		1. Knuth's TAOCP vol 2 Algorithm D

	Subtraction and addition:
		1. 5-loop (limited conditionals)
		2. compact (intensive conditionals)

	Multiplication:
		1. Karatsuba method (>1000 limb)
		2. long-multiplication method (<1000 limb)

	Square root:
		1. Newton's method
		2. Fibonacci's method

	Arbitraire strictly follows POSIX and the C99/C11 standards, and so, is
	portable to any POSIX compliant system and works with all of the
	architectures offered by linux, mac, BSD and many other systems.

	Arbitraire's "fxdpnt" number system allows for efficient POSIX 
	compliant implementations of POSIX bc. It is a "pen and paper" style of
	number system yet with POSIX bc scale and printing semantics. For these 
	semantics the 'base' field has to be set to 10. However, the ability to 
	operate natively in other bases is left as a decision to the caller.

	Arbitraire is an original work authored by CM Graff.


BUILDING:
---------

	git clone https://github.com/hlibc/arbitraire
	cd arbitraire
	./configure --prefix=$(pwd)/usr 
	CFLAGS="-O3" make
	make install

	Arbitraire should be built at optimization level -O3, but nonetheless
	performs fine with no optimization.

	The contents of tests/ is not installed. This method is for installing
	arbitraire on a target system, for testing and developing arbitraire
	see TESTING: below.


TESTING:
--------

	Test the core operations (add, mul, sub, div and sqrt) with a series 
	of pseudo-random 10-10000 digit numbers.

		make test

	Test the core operations with valgrind:

		make release

		This should output the number "1100" showing that 1100 tests
		were performed that showed no memory errors or leaks.


	Run the test wrappers and binaries:
	
		./tests/random-wrapper.sh add|mul|sub|div|sqrt 10000 null
	
		(argument agnostic, (functions of the form f(a, a, a));
		./tests/random-wrapper.sh add|mul|sub|div|sqrt 10000 agnostic


	Automatic testing with valgrind|strace|time:

		./tests/random-wrapper.sh sqrt 10000 null valgrind|strace|time

	"random-wrapper.sh" wraps "random-tests" by invoking it 100 times,
	logging its output and allowing it to be ran with other tools. However,
	random-tests can also be used on its own:

		./tests/random-tests div 10000 null

		or for argument agnostic:

		./tests/random-tests div 10000 agnostic

	Each function also has its own test, for instance, to add two numbers:

		./tests/add 123 123 10


USING THE API:
--------------

	An example for writing a program to add two numbers is provided 
	below:

	#include <arbitraire/arbitraire.h>

	int main(int argc, char *argv[])
	{
		if (argc < 4 )
			arb_error("Needs 3 args, such as: 123.456 123.456 base");

		int base = strtol(argv[3], NULL, 10);
		fxdpnt *a, *b, *c = NULL;
		a = arb_str2fxdpnt(argv[1]);
		b = arb_str2fxdpnt(argv[2]);
		c = arb_add(a, b, c, base);
		arb_print(c);
		arb_free(a);
		arb_free(b);
		arb_free(c);
		return 0;
	}

	Compile the example program as follows:

		cc example.c libarbitraire.a -I./include

	You can also compile your programs against arbitraire by either
	installing it or by putting them inside of tests/ and running
	./configure ; make

	Bear in mind that 1 atexit slot of the C standard library is consumed
	by arbitraire in order to free its "global" (file scope variables with 
	external linkage) constants.

	If you want to use the global constants for some reason, make sure not
	to modify or free them. They are; zero, one, p5 (.5), two and ten.

	It does not make much sense to try and pre-define arbitrarily sized
	transcendental constants such as pi or e. If you need these types of
	numbers you should generate them to the needed precision or include
	them.


	Hardware types can be converted to fxdpnt bignums using hrdware2arb.

		fxdpnt *a = hrdware2arb(16123123);

	This is not a very powerful or fast function as this is not a typical
	internal operation for arbitraire. It only supports size_t. If you
	really need to use hardware types you should probably write a new set
	of functions for this. Functions such as hrdware2arb, which allocate 
	their own memory require that the caller free the memory using 
	arb_free().
	
	Arbitraire's numbers are opaque objects, but can be accessed for
	debugging using arb_size(), arb_allocated(), arb_sign() and arb_left(). 
	Because of this, the numbers must be accessed as pure mathematical 
	objects. Object opacity helps to provide a safe and portable interface 
	which can withstand internal security changes and other updates without 
	affecting the code which uses arbitraire as a bignum library.


DEBUGGING:
----------

	A special set of internal functions has been created.
	They are:

		add, sub, divv and mul.

	These functions are not exposed by the API so as to preserve the
	namespace.

	These special debugging functions have a final field, which when
	filled with a character string, will print that string and the
	function name using __func__ and finally the result of the function.

	If you don't compile with `CFLAGS=-D_ARB_DEBUG make' then it will
	not be possible to activate the final field of these functions.
	In this way, the final field can be populated but still not print
	any information if it is never replaced with a NULL or 0 prior to
	release.

	These functions are used as follows:

		mul(a, b, &c, base, scale, "message");
		divv(a, b, &c, base, scale, "message");
		add(a, b, &c, base, "message");
		sub(a, b, &c, base, "message");

	Generally, "message" would be populated with the name of the
	variable you are using for the final "answer" which goes into
	"c". The debugging functions then print the function name,
	your message, and the final "answer" which goes into "c".

	I use them as follows:

		mul(a, b, c, base, scale, "c = ");

	C has no way of knowing the variable names verbatim as they are
	used, so in this way one can debug their work without interfering
	in the programming process with extra lines of code to print their
	results out to screen.

	
INSPIRATIONS:
-------------

	Fabrice Bellard's libBF library 
	https://bellard.org/libbf/

	GNU's GMP library

	Donald Knuth's TAOCP

	Professor Wayne Clark -- thank you again for all of your guidance


SPONSORS:
---------

	Packet, Works on ARM

	The gcc farm


CONTACTS:
---------

	CM Graff  cm0graff@gmail.com


RELEASES:
---------

	Github doesn't have an ideal method for naming releases so we opted to 
	use these simple naming schemes. More conventionally named releases 
	will be available after we get our main website back up.

	When possible, make sure to use the last release available. Arbitraire
	has been going through a lot of massive internal changes lately, but
	these releases will allow you to get a stable and bug-free interface.

	https://github.com/hlibc/arbitraire/archive/v0.3.tar.gz

	https://github.com/hlibc/arbitraire/archive/v0.4.tar.gz

	https://github.com/hlibc/arbitraire/archive/v0.5.tar.gz

	https://github.com/hlibc/arbitraire/archive/v0.6.tar.gz

	https://github.com/hlibc/arbitraire/archive/v0.7.tar.gz


About

An arbitrary precision library written in C which supports fractional datum. Arbitraire is fully portable to all linux, mac and netbsd/freebsd/openbsd architectures

Resources

License

Stars

Watchers

Forks

Packages

No packages published