Codebase list libmawk / 1df34837-a1d9-4cbd-a796-a1f5ebe673fc/main doc / numeric.html

Tree @1df34837-a1d9-4cbd-a796-a1f5ebe673fc/main (Download .tar.gz)

numeric.html @1df34837-a1d9-4cbd-a796-a1f5ebe673fc/mainraw · history · blame

	<H1> libmawk numerics </H1>
	Mawk implemented all numeric calculations using double precision floating
	point numbers. Libmawk has a compile-time option for using different
	types for numerics, with the following choices available:
		<LI> double (default)
		<LI> int

	<H2> handling exceptions and NaNs </H2>
	Mawk was geared towards catching floating point errors (such as
	division by zero or log(-1)) and report a runtime error as soon as
	possible. Libmawk, targeting embedded script application, should minimize
	runtime errors by providing means for the script to check for them and
	There are multiple approaches for handling suc errors. A design decision
	has been made for exclusively using NaN (<I>Not a Number</I>) - on platforms where it is not
	implemented by the FPU or by libc, it's emulated. NaN support shall work
	the same way for all available numeric types.
	Rules about NaN are few and simple:
		<LI> 1. NaN should be a sepcial value that can not be mistaken for a valid number by the script
		<LI> 2. math library calls (e.g. log()) should return NaN for invalid input; library calls shall accept NaN as input and return NaN as output
		<LI> 3. other library functions should handle NaN properly (i.e. printf %f or print shall write "nan" and a string-to-number conversion shall be able to understand "nan")
		<LI> 4. if any input of a calculation is NaN, the result shall be NaN (e.g. NaN+1 is NaN); such calculations never cause runtime error
		<LI> 5. 1/0, 0/0 and similar corner cases are all NaN - there is no inf
		<LI> 6. the only runtime error that may be caused by NaNs is when a conditional jump depends on a NaN (e.g. if (nan) {})
		<LI> 7. isnan(x) returns 1 if x is NaN.
	In practice this means a block of numeric calculations can be done safely,
	without checking any input or intermediate results. At the end of the
	block the result(s) shall be checked with isnan(). As long as the results
	(even indirectly) depend on an input or intermediate result that is NaN,
	the result is guaranteed to be NaN too, without the risk of a runtime error.

	<H2> Implementation </H2>
	<H3> type: double </H3>
	If the system has FPE, it's disabled. If the system does not have native
	NaN, a special NaN value is defined (using HUGE_VAL) and
	before each operation all inputs are checked for NaN to make sure the
	output is NaN too. On systems with NaN 
	### TODO: inf? ###
	<H3> type: int </h3>
	### TODO: ###
	<H3> division by zero </H3>
	Before divisions input is always checked and division by zero is
	replaced by a NaN. The same mechanism is in place for all numeric types.