This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RFC: TS 18661-1 floating-point interfaces


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]