This project checks various implementations of various floating
point functions. If you are writing a floating point math library,
and you want to compare it against other implementations in an
automated, way, you might find this useful.
There are
- A bunch of impl-XYZ programs. They get started with option flags
telling them what function f to run. They then listen on stdin
for byte sequences x0, x1, ..., xN, responding on stdout with
byte sequences f(x0), f(x1), ..., f(xN).
- A checker program. It is responsible for starting all the
impl-XYZs, feeding them all the xi values, and then making sure
they return equivalent f(xi) values. If two impls disagree, the
checker prints out a diagnostic to stdout.
To compile everything, go into each directory and run `make' or
`mbld' or whatever. If you like, you can run `make' in the main
directory.
To test a bunch of random values with single precision, on the sine
function, do something like:
checker/obj/checker -s -f sin
To use a specific seed for the random values (by default the seed
is the current time):
checker/obj/checker -s -f sin -r 12345
To exhaustively test every possible single-precision floating point
input:
checker/obj/checker -s -f sin -e
To use double-precision instead (it's not recommended to attempt
to exhaust double-precision):
checker/obj/checker -d -f exp1m
To figure out what functions are supported (legal values for -f):
checker/obj/checker -l
To see all options:
checker/obj/checker -h
----
On the internal side, an impl program is invoked via:
impl-XYZ [-s|-d] -n <num_inputs> -f <function-name>
where -s and -d specify single/double precision, and num_inputs
describes how much data will be sent in and out for each iteration.
Different functions may take different numbers of arguments (e.g.
sin vs. atan2).
num_inputs is entirely for speed concerns: it is desirable to
exhaustively test single-precision inputs. However, if values are
sent and received one at a time, programs spend most of their time
reading, writing, and waiting for new input.
The checker has to have some way of finding the impl programs. It
does this in the dumbest way possible: walking through all files
in "." and checking if they are 1) executable and 2) the name starts
with "impl-". Therefore, you should probably run the checker from
the root directory of the project.
Since multi-byte data is written and read over channels, endian-ness
is a concern. This was written and run on little-endian machines.
----
There's a lot of duplication in the code. This is partially intentional
(to avoid building an over-complicated in a multi-language project)
and partially because I'm lazy.