Use the generic `scalbn` to provide `f16` and `f128` versions, which
also work for `ldexp`.
This involves a new algorithm for `f16` because the default does not
converge fast enough with a limited number of rounds.
This function is significantly slower than all others so includes an
override in `EXTREMELY_SLOW_TESTS`. Without it, PR CI takes ~1hour and
the extensive tests in CI take ~1day.
This also allows reusing the same generator logic between logspace tests
and extensive tests, so comes with a nice bit of cleanup.
Changes:
* Make the generator part of `CheckCtx` since a `Generator` and
`CheckCtx` are almost always passed together.
* Rename `domain_logspace` to `spaced` since this no longer only
operates within a domain and we may want to handle integer spacing.
* Domain is now calculated at runtime rather than using traits, which is
much easier to work with.
* With the above, domains for multidimensional functions are added.
* The extensive test generator code tests has been combined with the
domain_logspace generator code. With this, the domain tests have just
become a subset of extensive tests. These were renamed to "quickspace"
since, technically, the extensive tests are also "domain" or "domain
logspace" tests.
* Edge case generators now handle functions with multiple inputs.
* The test runners can be significantly cleaned up and deduplicated.
Currently the features that control what we test against are
`build-musl` and `test-multiprecision`. I didn't name them very
consistently and there isn't really any reason for that.
Rename `test-multiprecision` to `build-mpfr` to better reflect what it
actually does and to be more consistent with `build-musl`.
Update test traits to support `f16` and `f128`, as applicable. Add the
new routines (`fabs` and `copysign` for `f16` and `f128`) to the list of
all operations.
Add a generator that will test all inputs for input spaces `u32::MAX` or
smaller (e.g. single-argument `f32` routines). For anything larger,
still run approximately `u32::MAX` tests, but distribute inputs evenly
across the function domain.
Since we often only want to run one of these tests at a time, this
implementation parallelizes within each test using `rayon`. A custom
test runner is used so a progress bar is possible.
Specific tests must be enabled by setting the `LIBM_EXTENSIVE_TESTS`
environment variable, e.g.
LIBM_EXTENSIVE_TESTS=all_f16,cos,cosf cargo run ...
Testing on a recent machine, most tests take about two minutes or less.
The Bessel functions are quite slow and take closer to 10 minutes, and
FMA is increased to run for about the same.
Currently, all inputs are generated and then cached. This works
reasonably well but it isn't very configurable or extensible (adding
`f16` and `f128` is awkward).
Replace this with a trait for generating random sequences of tuples.
This also removes possible storage limitations of caching all inputs.
Once we start addinf `f16` and `f128` routines, we will need to have
this cfg for almost all uses of `for_each_function`. Rather than needing
to specify this each time, always emit `#[cfg(f16_enabled)]` or
`#[cfg(f128_enabled)]` for each function that uses `f16` or `f128`,
respectively.
Now that we are using rustdoc output to locate public functions, the
test is indicating a few that were missed since they don't have their
own function. Update everything to now include the following routines:
* `erfc`
* `erfcf`
* `y0`
* `y0f`
* `y1`
* `y1f`
* `yn`
* `ynf`
We now have tests against our custom-built musl as well as tests against
MPFR. The tests against system musl covers less than those against
custom-built musl, and are less portable; there isn't much benefit to
keeping them around so just remove them.
Currently there is a combination of names starting with
`multiprecision_`, `mp_` and `multiprec_`. Update so `multiprecision_`
is always used when a long form makes sense, `mp_` otherwise
(eliminating `multiprec_`).
Check our functions against `musl-math-sys`. This is similar to the
existing musl tests that go through binary serialization, but works on
more platforms.
Create a new test that checks `for_each_fn` against `ALL_FUNCTIONS`,
i.e. the manually entered function list against the automatically
collected list. If any are missing (e.g. new symbol added), then this
will produce an error.
We will have more test features in the near future, and it would be nice
for them all to have a common `test-` prefix. Reverse the existing
feature so this is the case.
There isn't any reason for this feature to be exposed or part of the
build script. Move it to a separate crate.
We will also want more tests that require some support functions; this
will create a place for them.