From willemw@komp Thu Sep 4 16:29:19 1997
Received: from komp.ace.nl (komp.ace.nl [193.78.104.90]) by dkuug.dk (8.6.12/8.6.12) with SMTP id QAA09535 for ; Thu, 4 Sep 1997 16:29:19 +0200
Received: by komp.ace.nl with SMTP id AA27823 (1.14/2.17);
Thu, 4 Sep 97 16:27:16 +0200 (MET)
To: sc22wg11@dkuug.dk
Subject: WG11 N440 (5 of 7): LIA-1 binding for C: LIA-1 annex
Date: Thu, 04 Sep 97 16:27:15 N
Message-Id: <27821.873383235@komp>
From: Willem Wakker
* Document Number: WG14 N750/J11 97-113
C9X Revision Proposal
=====================
* Title: LIA-1 Binding: LIA-1 annex.
Author: Fred J. Tydeman
Author Affiliation: Tydeman Consulting
Postal Address: 3711 Del Robles Dr., Austin, Texas, USA, 78727
E-mail Address: tydeman@tybor.com
Telephone Number: +1 (512) 255-8696
Fax Number: +1 (512) 255-8696
Sponsor: WG14
Date: 1997-08-27
Proposal Category:
__ Editorial change/non-normative contribution
__ Correction
Y_ New feature
__ Addition to obsolescent feature list
__ Addition to Future Directions
__ Other (please specify) ______________________________
Area of Standard Affected:
__ Environment
Y_ Language
__ Preprocessor
__ Library
__ Macro/typedef/tag name
__ Function
__ Header
Y_ Other (please specify) Annex_________________________
Prior Art: Very little. Sun, and maybe others, print messages
at program termination if any IEC 559 flags are raised. That
is one small part of this proposal.
Target Audience: Programmers writing programs that perform a
significant amount of numeric processing.___________________
Related Documents (if any):
WG14/N753 (LIA-1 Binding: Rationale),
WG14/N752 (LIA-1 Binding: Optional parts annex),
WG14/N751 (LIA-1 Binding: LIA-1 + IEC-559 annex),
WG14/N749 (LIA-1 Binding: ),
WG14/N748 (LIA-1 Binding: Adding 'pole' from LIA-2),
WG14/N747 (IEC 559 Binding: Signaling NaNs),
WG14/N528 (C Binding of LIA-1),
WG14/N487 (LIA-1),
WG14/N486 (LIA Overview),
WG14/N463 (Impact of adding LIA-1)
Proposal Attached: _Y Yes __ No, but what's your interest?
Abstract: This part of the C9X+LIA binding discusses the
binding of LIA-1 to C, that is, what it takes to have a LIA-1
conformant implementation.
Proposal:
Note: The '*' characters in the lefthand column are not part
of the proposal (they are useful for emacs M-x outline mode)
In the following, **bold text**, *italic text*,
`code sample` are the conventions used to indicate
text different from normal.
* -- Add to 6.8.6 Pragma directive:
#pragma STDC LIA_NOTIFY { UNDEF | FLAGS | TRAP }
and add to the list of forward references:
the LIA_NOTIFY pragma (7.x.1.1)
* -- Add to 6.8.8 Predefined macro names:
The following macro name is defined if and only if the
implementation conforms to Annex H.
__STDC_LIA_1__ The decimal constant 1.
* -- Add to Annex A Bibliography:
ISO/IEC 10967-1:1994(E) *Information technology --
Language independent arithmetic -- Part 1: Integer and
floating point arithmetic*.
* -- Add a new annex, here called H, after annex G IEC
559-compatible complex arithmetic:
Annex H
(normative)
LIA-1 arithmetic
** H.1 Introduction
This annex specifies C language support for the ISO/IEC
10967-1 language independent arithmetic (LIA-1) standard.
An implementation that defines __STDC_LIA_1__ conforms to
the specification in this annex. Where a binding between
the C language and LIA-1 is indicated, the LIA-1-specified
behavior is adopted by reference, unless stated otherwise.
An implementation shall conform to all the requirements of
LIA-1 (ISO 10967-1:1994) unless otherwise specified in this
clause.
LIA-1 specifies a parameterized model of arithmetic
computation. The purpose of LIA-1 is to provide a known
environment in conforming implementations across platforms
and languages for applications requiring numeric
computation. Overall, the C binding of LIA-1 doesn't affect
existing programs but new programs will achieve a higher
degree of portability on LIA-1 systems. The impact of the
changes are: adding some macros, adding a handful of library
functions, and requiring the implementation to document
certain features of its arithmetic.
** H.2 Types
*** H.2.1 Boolean Type
The LIA-1 data type Boolean is implemented in the C data
type **int** (1 == true and 0 == false).
*** H.2.2 Integral Types
The integral types **int**, **long**, **long
long**, **unsigned int**, **unsigned long**,
**unsigned long long** conform to LIA-1[footnote].
[footnote]: The conformity of **short** and **char**
(plain, signed or unsigned) is not relevant since values of
these types are promoted to **int** (plain, signed or
unsigned) before computations are done.
**** H.2.2.1 Integer Parameters
The parameters for the LIA-1 integer data types can be
accessed by the following:
maxint INT_MAX, LONG_MAX, LLONG_MAX,
UINT_MAX, ULONG_MAX, ULLONG_MAX.
minint INT_MIN, LONG_MIN, LLONG_MIN.
modulo INT_OUT_OF_BOUNDS, LONG_OUT_OF_BOUNDS,
LLONG_OUT_OF_BOUNDS.
The parameter bounded is always true, and is not provided.
The parameter minint is always 0 for the unsigned types, and
is not provided for those types. The parameter modulo is
always true for the unsigned types, and is not provided for
those types. The parameter modulo is either 1 (wrap) or 2
(notify) for the signed types.
**** H.2.2.2 Integer Operations
The integer operations are the following:
addI x + y.
subI x - y.
mulI x * y.
divI, divtI x / y.
remI, remtI x % y.
modaI modulo(x, y), lmodulo(x, y), llmodulo(x, y).
modpI No binding.
negI - x.
absI abs(x), labs(x), llabs(x).
signI sgn(x), lsgn(x), llsgn(x).
eqI x == y.
neqI x != y.
lssI x < y.
leqI x <= y.
gtrI x > y.
geqI x >= y.
where x and y are expressions of the same integral type.
*** H.2.3 Floating-Point Types
The floating types **float**, **double**, and **long
double** conform to LIA-1.
**** H.2.3.1 Floating-Point Parameters
The parameters for a floating point data type can be
accessed by the following:
r FLT_RADIX.
p FLT_MANT_DIG, DBL_MANT_DIG, LDBL_MANT_DIG.
emax FLT_MAX_EXP, DBL_MAX_EXP, LDBL_MAX_EXP.
emin FLT_MIN_EXP, DBL_MIN_EXP, LDBL_MIN_EXP.
denorm FLT_SUBNORMAL, DBL_SUBNORMAL, LDBL_SUBNORMAL.
iec_559 FLT_IEC_559, DBL_IEC_559, LDBL_IEC_559.
The *_IEC_559 macros represent booleans and have values 1 or
0.
The derived constants for the floating types are accessed by
the following:
fmax FLT_MAX, DBL_MAX, LDBL_MAX.
fminN FLT_MIN, DBL_MIN, LDBL_MIN.
fmin FLT_TRUE_MIN, DBL_TRUE_MIN, LDBL_TRUE_MIN.
epsilon FLT_EPSILON, DBL_EPSILON, LDBL_EPSILON.
rnd_error FLT_RND_ERR, DBL_RND_ERR, LDBL_RND_ERR.
rnd_style FLT_ROUNDS.
The LIA_STRICT macro must be 1.
The SILENT_UNDERFLOW macro must be 0.
The COMPARISON_VIA_SUBTRACT macro must be 0.
The NEGATE_MAY_FAIL macro must be 0.
The *_RND_ERR macros must be less than or equal to 1.0
Rounding error ***_RND_ERR** depends upon rounding mode
**FLT_ROUNDS**. Rounding error will be constant
expression suitable for use in **#if** only if
**FLT_ROUNDS** is constant.
If *_SUBNORMAL is not 1, then *_TRUE_MIN is the same as
*_MIN.
**** H.2.3.2 Floating-Point Operations
LIA-1 operations shall be provided for all floating types.
The floating point operations are:
addF x + y.
subF x - y.
mulF x * y.
divF x / y.
negF - x.
absF fabsf(x), fabs(x), fabsl(x).
signF fsgnf(x), fsgn(x), fsgnl(x).
exponentF 1.f+logbf(x), 1.0+logb(x), 1.L+logbl(x).
fractionF fracrepf(x), fracrep(x), fracrepl(x).
scaleF scalbnf(x, n), scalbn(x, n), scalbnl(x, n).
succF fsuccf(x), fsucc(x), fsuccl(x).
predF fpredf(x), fpred(x), fprecl(x).
ulpF ulpf(x), ulp(x), ulpl(x).
truncF trunctof(x, n), truncto(x, n), trunctol(x, n).
roundF roundtof(x, n), roundto(x, n), roundtol(x, n).
intpartF modff(x, &y), modf(x, &y), modfl(x, &y).
fractpartF modff(x, &y), modf(x, &y), modfl(x, &y).
eqF x == y.
neqF x != y.
lssF x < y.
leqF x <= y.
gtrF x > y.
geqF x >= y.
where x and y are expressions of the same floating point
type, and n is of type **int**.
**** H.2.3.3 Rounding Styles
The C Standard requires all floating types use the same
radix and rounding style, so that only one identifier for
each is provided in the LIA-1 binding.
The FLT_ROUNDS [footnote] parameter corresponds to the LIA-1
rounding styles:
truncate FLT_ROUNDS == 0.
nearest FLT_ROUNDS == 1.
other FLT_ROUNDS != 0 && FLT_ROUNDS != 1.
[footnote] The definition of FLT_ROUNDS has been extended to
cover the rounding style used in all LIA-1 operations, not
just addition.
*** H.2.4 Type Conversions
The LIA-1 type conversions are the following macro calls or
type casts:
cvtF->I icvt(x), lcvt(x), llcvt(x),
uicvt(x), ulcvt(x), ulcvt(x).
cvtI'->I (int)x, (long)x, (long long)x,
(unsigned int)x, (unsigned long)x,
(unsigned long long)x.
cvtI->F (float) x, (double) x, (long double) x.
cvtF'->F (float) x, (double) x, (long double) x.
** H.3 Notification
Notificaiton is the process by which a user or program is
informed that an arithmetic operation cannot be performed.
Specifically, a notification shall occur when any arithmetic
operation returns an exceptional value as defined in LIA-1
clause 5.
*** H.3.1 Notification alternatives
The implementation shall provide at least the following two
alternatives for handling of notifications: setting
indicators or trap and terminate. The notification
alternative selected may influence code generation. Because
of this, an implementation need only support a given
alternative for the entire translation unit. An
implementation may support the ability to switch between
notification alternatives during execution, but is not
required to do so. An implementation can provide separate
selection for each kind of notification, but this is not
required.
**** H.3.1.1 Indicators
The following indicators shall be provided. They shall be
clear at the start of the program. They are set when any
arithmetic operation returns an exceptional value as defined
in LIA-1 clause 5. Once set, an indicatior shall be cleared
only by explicit action of the program (that is, they are
sticky).
undefined FE_INVALID, INT_INVALID.
pole FE_DIVBYZERO, INT_DIVBYZERO.
integer_overflow INT_OVERFLOW.
floating_overflow FE_OVERFLOW.
underflow FE_UNDERFLOW.
Undefined covers zero/zero, while pole covers finite
non-zero/zero. For implementations that cannot distinguish
the two cases, undefined is used.
The values representing individual indicators shall be
distinct non-negative powers of two. The empty set is
denoted by 0. Other indicator subsets are named by
combining individual indicators using bit-or. For example,
the LIA-1 indicator subset
{floating_overflow, underflow, integer_overflow}
would be denoted by the expression
FE_OVERFLOW | FE_UNDERFLOW | INT_OVERFLOW
The indicator interrogation and manipulation operations are:
set_indicators feraiseexcept(i), ieraiseexcept(i).
clear_indicators feclearexcept(i), ieclearexcept(i).
test_indicators fetestexcept(i), ietestexcept(i).
current_indicators fetestexcept(~0), ietestexcept(~0).
where i is an expression of type **int** representing a
LIA-1 indicator subset.
The implementation shall not allow a program to complete
successfully with an indicator that is set. Unsuccessful
completion of a program shall be reported to the user of the
program in an unambiguous and "hard to ignore" manner (see
LIA-1 subclause 6.1.2)
A suggested method is to register a function during program
startup (as if by the use of atexit()), so that upon program
termination, it prints out to **stderr** the indicators
still set.
`
void __lia_indicators(void){ /* during program termination */
int fp_flags = fetestexcept(~0);
int int_flags = ietestexcept(~0);
int fail = 0;
if( (fp_flags & FE_INVALID) || (int_flags & INT_INVALID) ){
(void)fprintf(stderr, "LIA: Undefined set");
fail = 1;
}
if( (fp_flags & FE_DIVBYZERO) || (int_flags & INT_DIVBYZERO) ){
(void)fprintf(stderr, "LIA: Pole set");
fail = 1;
}
if( int_flags & INT_OVERFLOW ){
(void)fprintf(stderr, "LIA: Integer overflow set");
fail = 1;
}
if( fp_flags & FE_OVERFLOW ){
(void)fprintf(stderr, "LIA: Float overflow set");
fail = 1;
}
if( fp_flags & FE_UNDERFLOW ){
(void)fprintf(stderr, "LIA: Float underflow set");
fail = 1;
}
if( fail ){
exit(EXIT_FAILURE); /* unsuccessful completion */
}
};
atexit( __lia_indicators ); /* during program startup */
`
**** H.3.1.2 Traps
When notification via traps is chosen, at program startup,
the equivalent of
**signal(SIGFPE, SIG_DFL);**
shall be executed.
When notification results in traps, then whenever a LIA-1
exceptional value would result, **SIGFPE** shall be sent
to the executing program.
***** H.3.1.2.1 Trap and terminate
The implementation shall provide an alternative of
notification through termination with a ``hard-to-ignore''
message (see LIA-1 subclause 6.1.3).
When SIGFPE is sent to the executing program, the default
signal handler for SIGFPE is invoked.
The default signal handler for **SIGFPE** shall send a
message to **stderr**. It shall then end execution of
the program with a termination status of **EXIT_FAILURE**
to the host environment, as if, **exit(EXIT_FAILURE);**
were done.
The message sent to **stderr** should identify the cause
of the notification and the operation responsible.
***** H.3.1.2.2 Trap and resume
A user specifies code (a trap handler) to compensate for
exceptions by:
**signal(SIGFPE, user_trap_handler);**
where user_trap_handler is the user's function.
When SIGFPE is sent to the executing program, the user's
signal handler for SIGFPE is invoked.
Program execution is continued from the user's trap handler
shall be supported by the use of the **longjmp**
function.
An implementation may support **return** from a user's
**SIGFPE** trap handler, but is not required to do so.
*** H.3.2 User selection
The implementation shall provide a means for a user or
program to select among the alternative notification
mechanisms provided (see LIA-1 subclause 6.3). The
LIA_NOTIFY pragma is the method used. LIA_NOTIFY FLAGS and
LIA_NOTIFY TRAP are the LIA-1 required conformant mechanisms.
** H.4
This subclause contains specification of facilities
that is required for LIA-1 implementations.
*** H.4.1 Nearest integer macros
The macros used to convert from floating-point types to
signed integral types are defined for out-of-bounds results
in both wrapping and trapping modes.
**** **H.4.1.1 The icvt macro**
If the rounded value is outside the range of **int** and
**INT_OUT_OF_BOUNDS** is 1 (wrap), the rounded value is
wrapped modulo (**INT_MAX-INT_MIN+1**).
If the rounded value is outside the range of **int** and
**INT_OUT_OF_BOUNDS** is 2 (notify), the numeric result
is unspecified and **INT_OVERFLOW** is raised.
**** **H.4.1.2 The lcvt macro**
If the rounded value is outside the range of **long** and
**LONG_OUT_OF_BOUNDS** is 1 (wrap), the rounded value is
wrapped modulo (**LONG_MAX-LONG_MIN+1**).
If the rounded value is outside the range of **long** and
**LONG_OUT_OF_BOUNDS** is 2 (notify), the numeric result
is unspecified and **INT_OVERFLOW** is raised.
**** **H.4.1.3 The llcvt macro**
If the rounded value is outside the range of **long
long** and **LLONG_OUT_OF_BOUNDS** is 1 (wrap), the
rounded value is wrapped modulo
(**LLONG_MAX-LLONG_MIN+1**).
If the rounded value is outside the range of **long
long** and **LLONG_OUT_OF_BOUNDS** is 2 (notify), the
numeric result is unspecified and **INT_OVERFLOW** is
raised.
*** H.4.2 Modulo functions
The functions used to compute the modulus are defined for a
zero denominator.
**** **H.4.2.1 The modulo function**
If the denominator is zero, **INT_INVALID** is raised.
**** **H.4.2.2 The lmodulo function**
If the denominator is zero, **INT_INVALID** is raised.
**** **H.4.2.3 The llmodulo function**
If the denominator is zero, **INT_INVALID** is raised.
- ---
Fred J. Tydeman +1 (512) 255-8696 Tydeman Consulting
3711 Del Robles tydeman@tybor.com Programming, testing, numerics
Austin, Texas 78727 Voting member of X3J11 (ANSI "C")
USA Sample C9X+FPCE tests: ftp://jump.net/pub/tybor/