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 <sc22wg11@dkuug.dk>; 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 <willemw@komp.ace.nl>


*                     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: <stdlia.h>),
        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, <B>bold text</B>, <I>italic text</I>,
       <TT>code sample</TT> 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) <I>Information technology --
       Language independent arithmetic -- Part 1: Integer and
       floating point arithmetic</I>.


*      -- 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 <B>int</B> (1 == true and 0 == false).

***    H.2.2 Integral Types

       The integral types <B>int</B>, <B>long</B>, <B>long
       long</B>, <B>unsigned int</B>, <B>unsigned long</B>,
       <B>unsigned long long</B> conform to LIA-1[footnote].

       [footnote]: The conformity of <B>short</B> and <B>char</B>
       (plain, signed or unsigned) is not relevant since values of
       these types are promoted to <B>int</B> (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 <B>float</B>, <B>double</B>, and <B>long
       double</B> 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 <B>*_RND_ERR</B> depends upon rounding mode
       <B>FLT_ROUNDS</B>.  Rounding error will be constant
       expression suitable for use in <B>#if</B> only if
       <B>FLT_ROUNDS</B> 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 <B>int</B>.


****   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 <B>int</B> 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 <B>stderr</B> the indicators
       still set.

       <TT>
       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 */
       </TT>

****   H.3.1.2 Traps

       When notification via traps is chosen, at program startup,
       the equivalent of

         <B>signal(SIGFPE, SIG_DFL);</B>

       shall be executed.

       When notification results in traps, then whenever a LIA-1
       exceptional value would result, <B>SIGFPE</B> 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 <B>SIGFPE</B> shall send a
       message to <B>stderr</B>.  It shall then end execution of
       the program with a termination status of <B>EXIT_FAILURE</B>
       to the host environment, as if, <B>exit(EXIT_FAILURE);</B>
       were done.

       The message sent to <B>stderr</B> 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:

	 <B>signal(SIGFPE, user_trap_handler);</B>

       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 <B>longjmp</B>
       function.

       An implementation may support <B>return</B> from a user's
       <B>SIGFPE</B> 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 <stdlia.h>

       This subclause contains specification of <stdlia.h> 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.

****   <B>H.4.1.1 The icvt macro</B>

       If the rounded value is outside the range of <B>int</B> and
       <B>INT_OUT_OF_BOUNDS</B> is 1 (wrap), the rounded value is
       wrapped modulo (<B>INT_MAX-INT_MIN+1</B>).

       If the rounded value is outside the range of <B>int</B> and
       <B>INT_OUT_OF_BOUNDS</B> is 2 (notify), the numeric result
       is unspecified and <B>INT_OVERFLOW</B> is raised.

****   <B>H.4.1.2 The lcvt macro</B>

       If the rounded value is outside the range of <B>long</B> and
       <B>LONG_OUT_OF_BOUNDS</B> is 1 (wrap), the rounded value is
       wrapped modulo (<B>LONG_MAX-LONG_MIN+1</B>).

       If the rounded value is outside the range of <B>long</B> and
       <B>LONG_OUT_OF_BOUNDS</B> is 2 (notify), the numeric result
       is unspecified and <B>INT_OVERFLOW</B> is raised.

****   <B>H.4.1.3 The llcvt macro</B>

       If the rounded value is outside the range of <B>long
       long</B> and <B>LLONG_OUT_OF_BOUNDS</B> is 1 (wrap), the
       rounded value is wrapped modulo
       (<B>LLONG_MAX-LLONG_MIN+1</B>).

       If the rounded value is outside the range of <B>long
       long</B> and <B>LLONG_OUT_OF_BOUNDS</B> is 2 (notify), the
       numeric result is unspecified and <B>INT_OVERFLOW</B> is
       raised.

***    H.4.2 Modulo functions

       The functions used to compute the modulus are defined for a
       zero denominator.

****   <B>H.4.2.1 The modulo function</B>

       If the denominator is zero, <B>INT_INVALID</B> is raised.

****   <B>H.4.2.2 The lmodulo function</B>

       If the denominator is zero, <B>INT_INVALID</B> is raised.

****   <B>H.4.2.3 The llmodulo function</B>

       If the denominator is zero, <B>INT_INVALID</B> 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/

