G.5 Binary operators
G.6.2 Hyperbolic functions
G.6.2.1 The cacosh functions
15
G.6.2.2 The casinh functions
An example of a special case is:
casinh(+INF+iINF) becomes
clog(+INF+iINF+csqrt(1+(+INF+iINF)*(+INF+iINF))) becomes clog(+INF+iINF+csqrt(1+(+0+iINF))) becomes
20
clog(+INF+iINF+csqrt(1+iINF)) becomes clog(+INF+iINF+INF+iINF) becomes
clog(+INF+iINF) becomes +INF+ipi/4.
G.6.2.3 The catanh functions
25
An example of a special case is: catanh(+x+iINF) becomes
(clog(1+x+iINF)-clog(1-x-iINF))/2 becomes (clog(1+x+iINF)-clog(1-x-iINF))/2 becomes
(clog(INF*cis(pi/2))-clog(INF*cis(-pi/2)))/2 becomes (INF+ipi/2 - (INF-ipi/2))/2 becomes
(0+i*pi)/2 becomes 0.0+i*pi/2.
G.6.2.4 The ccosh functions
5
An approach to figure out the special cases is to work backwards from the ccosh(z) formula. In that case, consider, cacosh(0+i0). Since ccosh(x+iy) is cosh(x)*cos(y) + i*sinh(x)*sin(y), cos(y) must be zero and sinh(x) must be zero, therefore, y is pi/2 and x is zero, hence, cacosh(0+i0) = 0+ipi/2.
An example of a special case is: 10
ccosh(+0.0+iNaN) becomes
cosh(0.0)*cos(NaN)+i*sinh(0.0)*sin(NaN) or 1.0*NaN+i*0.0*NaN or
NaN+/-i0.
G.6.2.5 The csinh functions
15
An example of a special case is: csinh(+INF+iy) becomes
sinh(INF)*cos(y)+i*cosh(INF)*sin(y) or INF*cos(y)+i*INF*sin(y) or
INF*cis(y). 20
G.6.2.6 The ctanh functions
An example of a special case is: ctanh(+INF+iy) becomes
(sinh(2*INF)+i*sin(2y))/(cosh(2*INF)+cos(2y)) or (INF+i*sin(2y))/(INF+cos(2y)) or
(INF+i*sin(2y))/INF or 1+i*0*sin(2y).
G.6.3 Exponential and logarithmic functions
G.6.3.1 The cexp functions
An example of one of the special cases is: 5
cexp(NaN+i0) becomes
exp(NaN)*cos(0) + i*exp(NaN)*sin(0), or NaN*1 + i*NaN*0 or
NaN + i0 (since the direction vector cis(0) is along the x-axis, the result needs to be alone the x-axis, e.g., the imaginary part of the result needs to be 0).
10
G.6.3.2 The clog functions
An example of a special case is: clog(x+iINF), finite x. So, in polar, z is
INF*cis(pi/2), therefore, clog(z) is log(INF)+i*pi/2, or INF+i*pi/2.
G.6.4 Power and absolute-value functions
G.6.4.1 The cpow functions
15
G.6.4.2 The csqrt functions
An example of one of the special cases is:
csqrt(INF+iNAN) becomes z is INF*cis(NAN), so csqrt(z) is
sqrt(INF)*cis(NAN/2) or INF*cis(NAN) or INF+i*NAN to retain some information (that there is an infinity).
20
G.7 Type-generic math <tgmath.h>
Exploiting the fact that some functions map the imaginary axis onto the real or imaginary axis gains more efficient calculation involving imaginaries, and better meets user expectations in some cases. However, dropping out of the complex domain may lead to surprises as subsequent operations may be done with real functions, which generally are more restrictive than their 25
complex counterparts. For example, sqrt(-cos(I)) invokes the real sqrt function, which is invalid for the negative real value -cos(I), whereas the complex sqrt is valid everywhere.
Annex H Language independent arithmetic (informative)
A new feature of C99.LIA-1 was not made a normative part of C99 for three reasons: implementation vendors saw no need to add LIA-1 support because customers are not asking for it, LIA-1 may change now that work on LIA-2 is finishing and work on LIA-3 is starting, and the Committee did not wish to 5
rush a possibly incomplete specification into C99 at the last moment. A proposed binding between C and LIA-1 was produced a few months before C99 was frozen. That binding was a compromise between those who believe LIA-1 should be forgotten and those who wanted full LIA-1 and more (for example, C signal handlers that could patch up exceptions on the fly and restart the exceptional floating-point instruction). It took several years for the NCEG floating- 10
point specification to settle down, so it was assumed that it would take a similar timeframe to get the LIA-1 binding stable. The Committee did not wish to delay C99 for this one item. An informative LIA-1 annex was added, however, because all programming languages covered by ISO/IEC JTC1 SC22 standards are expected to review LIA-1 and incorporate and further define the binding between LIA-1 and each programming language.
15
C99’s binding between C and LIA-1 differs from LIA-1’s C binding in three cases in which the Committee believes that LIA-1 is incorrect. First, LIA-2 and LIA-1 have different behaviors for mathematical pole exceptions (similar to finite non-zero divided by zero and log(0)). The Committee believes that LIA-2 is better and that LIA-1 will be changed to match LIA-2. Second, the existing hardware that many computers use for conversion from floating-point type 20
to integer type raises the undefined exception, instead of the required integer overflow, for values that are out of bounds. Third, requiring support for signaling NaNs on IEC 60559
implementations should be optional because existing hardware support for signaling NaNs is inconsistent.
H.3.1.2 Traps 25
The math library is required by both C89 and C99 to be atomic in that no exceptions (raise of a signal and invocation of a user’s signal handler) may be visible in the user’s program. Because of that requirement, C99 cannot meet LIA’s requirement of either trap-and-terminate or trap-and- resume for math library errors. On the other hand, both kinds of traps are allowed for the
arithmetic operations. 30
MSE.
Multibyte Support Extensions Rationale
This text was taken from the rationale furnished with the amendment, ISO/IEC 9899/AMD1:1995, called simply AMD1 in this Annex.MSE.1 MSE Background
Most traditional computer systems and computer languages, including traditional C, have an 5
assumption, sometimes undocumented, that a “character” can be handled as an atomic quantity associated with a single memory storage unit — a “byte” or something similar. This is not true in general. For example, a Japanese, Chinese or Korean character usually requires a
representation of two or three bytes; this is a multibyte character as defined by §3.7.2 and §5.2.1.2. Even in the Latin world, a multibyte coded character set appears. This conflict is 10
called the byte and character problem.
A related concern in this area is how to address having at least two different meanings for string length: number of bytes and number of characters.
To cope with these problems, many technical experts, particularly in Japan, have developed their own sets of additional multibyte character functions, sometimes independently and sometimes 15
cooperatively. Fortunately, the developed extensions are actually quite similar. It can be said that in the process they have found common features for multibyte character support. Moreover, the industry currently has many good implementations of such support.
The above in no way denigrates the important groundwork in multibyte- and wide-character programming provided by C90:
20
• Both the source and execution character sets can contain multibyte characters with possibly different encodings, even in the “C” locale.
• Multibyte characters are permitted in comments, string literals, character constants, and header names.
• The language supports wide-character constants and strings. 25
• The library has five basic functions that convert between multibyte and wide characters. However, the five functions are often too restrictive and too primitive to develop portable international programs that manage characters. Consider a simple program that wants to count the number of characters, not bytes, in its input.
The prototypical program, #include <stdio.h> int main(void){
int c, n = 0;
while ((c = getchar()) != EOF) 5
n++;
printf("Count = %d\n", n);
return 0;
}
does not work as expected if the input contains multibyte characters; it always counts the number 10
of bytes. It is certainly possible to rewrite this program using just some of the five basic conversion functions, but the simplicity and elegance of the above are lost.
C90 deliberately chose not to invent a more complete multibyte- and wide-character library, choosing instead to await their natural development as the C community acquired more experience with wide characters. The task of the Committee was to study the various existing 15
implementations and, with care, develop the first amendment to C90. The set of developed library functions is commonly called the MSE (Multibyte Support Extension).
Similarly, C90 deliberately chose not to address in detail the problem of writing C source code with character sets such as the national variants of ISO/IEC 646. These variants often redefine several of the punctuation characters used to write a number of C tokens. The partial solution 20
adopted was to add trigraphs to the language. Thus, for example, ??< can appear anywhere in a C program that { can appear, even within a character constant or a string literal.
AMD1 responds to an international sentiment that more readable alternatives should also be provided wherever possible. Thus, it adds to the language alternate spellings of several tokens. It also adds a library header, <iso646.h>, that defines a number of macros that expand to still 25
other tokens which are less readable when spelled with trigraphs. Note, however, that trigraphs are still the only alternative to writing certain characters within a character constant or a string literal.
An important goal of any amendment to an international standard is to minimize quiet changes — changes in the definition of a programming language that transform a previously valid 30
program into another valid program, or into an invalid program that need not generate a
diagnostic message, with different behavior. (By contrast, changes that invalidate a previously valid program are generally considered palatable if they generate an obligatory diagnostic message at translation time.) Nevertheless, AMD1 knowingly introduces two classes of quiet changes:
35
• digraphs — The tokens %: and %:%: are just sequences of preprocessing tokens in C90 but become single preprocessing tokens with specific meanings in AMD1. An existing program that uses either of these tokens in a macro argument can behave differently as a result of AMD1.
• new function names — Several names with external linkage, such as btowc, not reserved to the implementation in C90, are now so reserved. An existing program that uses any of these names can behave differently as a result of AMD1.
MSE.2
Programming model based on wide characters
Using the MSE functions, a multibyte-character-handling program can be written as easily and in 5
the same style as a traditional single-byte-based program. A programming model based on MSE function is as follows. First, a multibyte character or a multibyte string is read from an external file into a wchar_t object or a wchar_t array object by the fgetwc function, or other input functions based on the fgetwc function such as getwchar, getwc, or fgetws. During this read operation, a code conversion occurs: the input function converts the multibyte character to 10
the corresponding wide character as if by a call to the mbrtowc function.
After all necessary multibyte characters are read and converted, the wchar_t objects are
processed in memory by the MSE functions such as iswxxx, wcstod, wcscpy, wmemcmp, and so on. Finally, the resulting wchar_t objects are written to an external file as a sequence of multibyte characters by the fputwc function or other output functions based on the fputwc 15
function such as putwchar, putwc, or fputws. During this write operation, a code conversion occurs: the output function converts the wide character to the corresponding multibyte character as if by a call to the wcrtomb function.
In the case of the formatted input/output functions, a similar programming style can be applied, except that the character code conversion may also be done through extended conversion 20
specifiers such as %ls and %lc. For example, the wide-character-based program corresponding to that shown in §MSE.1 can be written as follows:
#include <stdio.h> #include <wchar.h> int main(void) 25 { wint_t wc; int n = 0;
while ((wc = getwchar()) != WEOF) n++;
30
wprintf(L"Count = %d\n", n);
return 0;
}
MSE.3
Parallelism versus improvement
When defining the MSE library functions, the Committee could have chosen a design policy 35
based either on parallelism or on improvement. “Parallelism” means that a function interface defined in AMD1 is similar to the corresponding single-byte function in C90. The number of parameters in corresponding functions are exactly same, and the types of parameters and the types of return values have a simple correspondence: