> On 2012-02-09 12:36:01 -0500, Geert Bosch wrote:
>> I think it would make sense to have a check list of properties, and
>> use configure-based tests to categorize implementations. These tests
>> would be added as we go along.
>> 
>> Criteria:
>> 
>> [ ] Conforms to C99 for exceptional values 
>>     (accepting/producing NaNs, infinities)
> 
> C is not the only language. Other languages (e.g. Java) may have
> different rules. And IEEE 754-2008 also specifies different rules.
> And you may want to consider LIA-2 too, which is again different...

True, but I tried to keep the number of criteria small. Actually, 
my main interest here is allowing conformance with the Ada standard,
see chapter G.2 
(http://www.adaic.org/resources/add_content/standards/05rm/html/RM-G-2.html),
so I'm not looking at this with a "C-only" mindset. :-)

However, even though the Ada requirements are different, it would
still be tremendously helpful to be able to rely on the C99 standard,
and then just deal with other cases separately. But yes, we might
want to include even more configurability.

>> [ ] Handles non-standard rounding modes,
>>     trapping math, errno, etc.
> 
> By "non-standard rounding modes", I assume you mean "non-default
> rounding modes".
Yes, indeed.
> 
>> [ ] Meets certain relative error bounds,
>>     copy from Ada Annex G numerical requirements
>>     (typically between 2 eps and 4 eps for much of range)
> 
> FYI, OpenCL also has numerical requirements.
They seem similar, though only apply to single precision,
while the rules defined by Ada are parametrized by type.
Where OpenCL specifies an error as 4 ulps, Ada specifies a
relative error of 2 epsilon. For values just below a
power of 2, 2 epsilon equals 4 ulps, while for values 
just above they are ulps and eps are equivalent.
So, the Ada requirements are a bit tighter in general.
Probably we can define something that is the union
of both sets of requirements. 

>> [ ] Guaranteed error less than 1 ulp over all arguments,
>>     typical max. error close to 0.5 ulp.
> 
> Instead, I would say faithful rounding (this is slightly stricter
> for results close to powers of 2).
Yes, that is better.
> 
>> [ ] Correctly rounded for all arguments
> 
> I would add:
> 
>   [ ] Symmetry (e.g. cos(-x) = cos(x), sin(-x) = - sin(x)) in the
>       symmetric rounding modes.
> 
>   [ ] Monotonicity (for monotonous functions).
> 
> (note that they are implied by correct rounding).
Right, my goal was to have just a few different buckets that fit
well with GCC compilation options and allow categorization of 
existing functions. 

I guess, it should be a few check boxes and a numerical level.
This would be a categorization for source code, not compiled
code where me might have additional copies based on optimization
(size/latency/throughput/vectorization).

Properties:

  [ ]  Conforms to C99 for exceptional values 
       (accepting/producing NaNs, infinities)

  [ ]  Handles non-default rounding modes,
       trapping math, errno, etc.

  [ ]  Requires IEEE compliant binary64 arithmetic
       (no implicit extended range or precision)

  [ ]  Requires IEEE compliant binary80 arithmetic
       (I know, not official format, but YKWIM)
 
Accuracy level:

  0 - Correctly rounded

  1 - Faithfully rounded, preserving symmetry and monotonicity

  2 - Tightly approximated, meeting prescribed relative error
      bounds. Conforming to OpenCL and Ada Annex G "strict mode"
      numerical bounds.

  3 - Unspecified error bounds

Note that currently of all different operating systems we (AdaCore)
support for the GNAT compiler, I don't know of any where we can rely
on the system math library to meet level 2 requirements for all
functions and over all of the range! Much of this is due to us 
supporting OS versions as long as there is vendor support, so while 
SPARC Solaris 9 and later are fine, Solaris 8 had some issues. 
GNU Linux is quite good, but has issues with the "pow" function for
large exponents, even in current versions, and even though Ada
allows a relative error of (4.0 + |Right · log(Left)| / 32.0) 
for this function, or up to 310 ulps at the end of the range.
Similarly, for trigonometric functions, the relative error for 
arguments larger than some implementation-defined angle threshold
is not specified, though the angle threshold needs to be at
least radix**(mantissa bits / 2), so 2.0**12 for binary32 or 2.0**32
for binary80. OpenCL doesn't specify an angle threshold, but I
doubt they intend to require sufficient accurate reduction over
the entire range to have a final error of 4 ulps: that doesn't fit
with the rest of the requirements.

The Ada test suite (ACATS) already has quite extensive tests for (2),
which are automatically parameterized for any type (including those
with non-binary radix). That, and the fact that this level apparently
is still a challenge for most system math libraries seems like a good
reason for aiming for this level as a base level.

We should consider any libm function not meeting these minimal 
criteria to be buggy (or: only usable with -ffast-math, if actually fast),
and use a replacement. We could have -fstrict-math select the most
accurate functions we have, with the actual level being more for 
documentation purposes than anything else.

  -Geert

Reply via email to