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/