Date: Thu, 28 Aug 2003 09:38:57 -0500 From: Eric Rudd Subject: Re: Arithmetic Exceptions in C99 In-reply-to: <200308272025.h7RKPrFT003625@speedy.ludd.luth.se> To: djgpp-workers AT delorie DOT com Message-id: <3F4E1401.1020602@cyberoptics.com> Organization: CyberOptics MIME-version: 1.0 Content-type: text/plain; charset=windows-1252; format=flowed X-Accept-Language: en,pdf User-Agent: Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.3) Gecko/20030312 References: <200308272025 DOT h7RKPrFT003625 AT speedy DOT ludd DOT luth DOT se> X-MailScanner-Information: Please contact the ISP for more information X-MailScanner: Found to be clean Content-Transfer-Encoding: 8bit X-MIME-Autoconverted: from quoted-printable to 8bit by delorie.com id h7SEu5t01029 Reply-To: djgpp-workers AT delorie DOT com Errors-To: nobody AT delorie DOT com X-Mailing-List: djgpp-workers AT delorie DOT com X-Unsubscribes-To: listserv AT delorie DOT com Precedence: bulk ams AT ludd DOT luth DOT se wrote: >>||||||which suggests to me that SIGFPE should not be set by the math >> >> >(What do the pipes ("|") do there?) > The pipes were put there by my GUI E-mail client without my knowledge or approval. They were evidently related to cutting and pasting from the PDF document. >I think that paragraph only applies to the valid input >arguments. I. e. if you give values which are not valid input, this >paragraph have no bearing, i. e. exception is ok. > I saw no qualification on the statement in 7.12.1, so I read it as applying to all representable arguments. There really wouldn't be much point in stating that no exception should occur for sensible arguments -- you wouldn't expect an exception to occur, anyway. The interesting question is what happens for (to take your example) asin(2.0). There is good reason not to "generate externally visible exceptional conditions", since they might make error recovery impossible. The notion -- which I tried to follow in my libc math functions -- was that no matter what argument you fed to them, they would come back with some result, possibly setting errno. For instance, if you call atan2(0., 0.), it tests for that special case, returns with NaN, and sets errno to EDOM. If this were not done, an actual attempted division by zero might well crash the program (depending on the FPU exception mask in the control word), preventing recovery. >However I don't quite see how my reasoning would legitimise raising an >exception on overflow, underflow etc. Are values that cause overflow >not "representable values of its [the function's] input arguments"? > On a Control Data computer I used a long time ago, there were certain bit patterns that were illegal for floating point numbers. If you tried loading such numbers into the FPU, an exception was generated and the program crashed. I think that's an example of what C99 means by "non-representable value". On the DJGPP platform, I don't think that there are any non-representable values -- they all print out as a number, inf, or NaN without causing a crash. >>straighten me out, but I thought that "exception" in the context of C99 >>had to do with setting errno, rather than a low-level processor state, >>as it seems to imply in Annex F. Perhaps this would be a good question >>for comp.std.c. >> >What text in C99 says "raising an exception" == "errno = number>;" to you? > Part of the problem is that C99 never satisfactorily defines "exception". Reading between the lines in footnote 178 in clause 7.6.2.2 (bear in mind that the footnotes are informative, not normative), it appears that "exception" is intended to be an FPU processor exception, as described by Intel, but I've searched in vain for a normative definition. Of course, C99 can't talk about processor specifics; it would instead talk of the consequences of the exception visible to the program. Furthermore, there seem to be two parallel mechanisms for handling errors in C99. In my earlier reply, I suppose that I was still thinking of C90, where only the errno mechanism existed. See 7.12.1, paragraph 2: 2 For all functions, a domain error occurs if an input argument is outside the domain over which the mathematical function is defined. The description of each function lists any required domain errors; an implementation may define additional domain errors, provided that such errors are consistent with the mathematical definition of the function.194) On a domain error, the function returns an implementation-defined value; if the integer expression math_errhandling & MATH_ERRNO is nonzero, the integer expression errno acquires the value EDOM; if the integer expression math_errhandling & MATH_ERREXCEPT is nonzero, the ‘‘invalid’’ floating-point exception is raised. >Perhaps somebody (you?) should ask for clarification on comp.std.c. > I'll do that, though I've learned from experience that one needs to get one's ducks very well in a row before posting to that group. It's not clear to me whether the errno mechanism is a legacy feature that's only retained for compatibility, or if it is intended for apps to be able to use both mechanisms. (Errno is not required to be set at all -- see 7.3.2.) Also see C99 7.5, paragraph 3. I'll try to quote it here; I hope I don't get pipes again: The value of errno is zero at program startup, but is never set to zero by any library function.170) The value of errno may be set to nonzero by a library function call whether or not there is an error, provided the use of errno is not documented in the description of the function in this International Standard. >>To cause the math functions to set SIGFPE, where they previously did >>not, could break existing code. >> >Again, how do you _set_ SIGFPE? I thought you raised it, i. e. calling >the signal hander somehow. > I was sloppy in my terminology. I should have said "raised" SIGFPE. >The math functions shouldn't raise SIGFPE unless something goes wrong. > By "something goes wrong", do you mean "an unreasonable argument was passed", or do you mean "a bug in the math functions caused a problem"? >The answer is: as Annex F is normative and we want to comply to C99, >yes. (When we reach that status is a different story.) > The material in Annex F needs to be implemented only if __STDC_IEC_559__ is defined. Some older processors make compliance with Annex F very difficult, so compilers for such machines would probably not define __STDC_IEC_559__. The x87 FPU mostly complies with IEC 60559, so a compiler written from scratch for the x87 FPU could easily comply. Whether it is worthwhile (or even desirable) to re-write the existing math routines to comply with IEC 60559/Annex F is another matter entirely. As I have pointed out before, several features of Annex F are contrary to long-accepted rules of mathematics. For instance, 0./0. is normally expected to produce a NaN, but according to F.9.1.4, computing atan2(0., 0.) returns 0. without a floating-point exception, and atan2(+inf, +inf) returns pi/4, even though inf/inf = NaN in normal arithmetic. -Eric Rudd rudd AT cyberoptics DOT com