This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
RFC: TS 18661-1 floating-point interfaces
- From: Joseph Myers <joseph at codesourcery dot com>
- To: <libc-alpha at sourceware dot org>
- Date: Sat, 11 Jun 2016 00:58:31 +0000
- Subject: RFC: TS 18661-1 floating-point interfaces
- Authentication-results: sourceware.org; auth=none
ISO/IEC TS 18661-1:2014 provides C interfaces for various required
features of IEEE 754-2008, analogous to the support for IEEE 754-1985
added in C99.
We currently support the issignaling macro, added because it's useful in
glibc testcases, and patches for the nextup/nextdown functions are under
review, and for the strfrom functions are planned, as part of the
preparation for float128 support. I'm looking at possibly implementing
some or all of the other features from this TS (excluding at least for now
the support for constant rounding directions).
Following <https://sourceware.org/ml/libc-alpha/2015-11/msg00162.html> I
think we have at least provisional consensus on the suitability of these
APIs for glibc, but more comments on that would be desirable. The
following gives more details of how I propose those APIs would relate to
ABIs in glibc.
There is also an important question of the extent to which different APIs
are appropriate to add separately when the implementations are ready,
versus all being included together in the same release of glibc. (Of
course, the ones we have so far or in progress, issignaling,
nextup*/nextdown* and strfrom*, have not all gone in together.) The
broadest division into most clearly separate groups of APIs (excluding
those already implemented or in progress) might be:
* <limits.h> macros.
* <stdint.h> macros.
* <fenv.h> interfaces.
* <math.h> interfaces other than functions that round result to narrower
type.
* Functions that round result to narrower type (these pose their own
significant complications in that they require testsuite infrastructure to
be extended to cover functions parametrized on two types rather than just
one).
The fourth of these in turn contains lots of separate sets of macros /
functions, grouped separately in the TS: (signaling) NaN support; Nearest
integer functions; The llogb functions; Max-min magnitude functions;
Comparison macros; Classification macros; Total order functions;
Canonicalize functions; NaN functions. The <fenv.h> functions could also
be split up similarly (fesetexcept; fetestexceptflag; Control modes).
In all cases, the following would apply. Implementations would be
expected to cover all supported floating-point formats. If float128
support had gone in first, implementations would be expected to include
the *f128 API; if it had not, the float128 work would be expected to add
the *f128 versions of relevant new functions that had been added to
glibc[*]. There would be no expectation of optimized versions for
particular systems, although it would be useful to note where they are
likely to be possible. In some cases, it might be appropriate to ask for
architecture maintainer help with some updates, and to split patches by
architecture, especially as regards the <fenv.h> functions, but the
changes should be designed to at least keep all architectures building
after every commit. Commits might be more fine-grained than the division
into pieces that go in together (e.g., it would be reasonable for fminmag*
and fmaxmag* to be separately posted patches committed in two commits, but
not for a release to have one of those sets of functions but not the
other).
[*] Neither of these applies to the functions rounding result to narrower
type; those only need versions for new types when *more than one* _FloatN
/ _FloatNx type is supported, not when any glibc port supports at most one
such type.
I estimate a plausible division into over 70 patches (excluding those
relating to fixing individual existing function semantics for sNaNs or
other new requirements), but various groups of those patches are
sufficiently closely related that they should clearly be committed in
quick succession rather than treated as independent.
The following are the proposals for how APIs would relate to ABIs:
* New libm functions in <fenv.h> are: fesetexcept fetestexceptflag
fegetmode fesetmode. Note that fesetexcept is not fully implementable on
all architectures (on x86, setting an exception flag causes enabled traps
to occur on the next floating-point operation), although formally enabled
traps aren't part of the standard. femode_t would be an integer typedef
if fenv_t is, otherwise a structure or integer sufficient to cover the
relevant subset of fenv_t (control modes such as the rounding mode and
trap enablement flags, without state such as currently raised exceptions).
FE_DFL_MODE would be a magic const femode_t * value like FE_DFL_ENV.
* All the functions listed for <math.h> would be added to libm.so; long
double functions would be aliased to the double ones when the ABIs are the
same (and libnldbl versions added in the long-double-optional case). The
FP_INT_* rounding direction macros would be assigned
architecture-independent consecutive integer values from 0 to 4 in the
order listed in the TS (any future compiler built-in functions for
*fromfp* would need to know the choice of values). FP_LLOGB0 and
FP_LLOGBNAN would be given values corresponding to those of FP_ILOGB0 and
FP_ILOGBNAN (+/- INT_MAX -> +/- LONG_MAX, INT_MIN -> LONG_MIN); llogb
functions would be aliased to ilogb functions when long is 32-bit, but
could not be aliased otherwise.
* iseqsig would have underlying libm functions __iseqsig and __iseqsigf,
plus __iseqsigl only if long double has a different ABI from double.
* iscanonical would have an underlying libm function only for ldbl-96 and
ldbl-128ibm, that being called __iscanonicall; for other formats, the
macro would just evaluate its argument and return 1. Formally it's
intended for DFP cases where there are valid, noncanonical
representations, not for those formats where there are canonical
representations (sometimes multiple valid representations of a value with
no one being more canonical than another) and invalid ones, but it seems
useful as a quality-of-implementation issue to make the function report
invalid representations as noncanonical.
* issubnormal and iszero would not have any underlying functions, since
they can be based on fpclassify (and except with -fsignaling-nans or
excess range / precision, iszero can expand into ((x) == 0)).
(Optimizations of those macros would better be done through sNaN-aware GCC
built-in functions than through adding more-specific underlying functions
to glibc.)
There would be 4 new libm.so functions for <fenv.h>, 60 for <math.h>
functions (not counting nextup* and nextdown*), and 2-4 for <math.h>
macros (__iseqsig, __iseqsigf, possibly __iseqsigl and __iscanonicall
depending on the ABI). float128 support would of course increase those
last two figures.
Does anyone see other cases where there would be ABI choices to make for
the implementation?
--
Joseph S. Myers
joseph@codesourcery.com