delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2000/05/14/06:24:51

Message-Id: <200005141011.GAA13109@delorie.com>
From: "Dieter Buerssner" <buers AT gmx DOT de>
To: Eli Zaretskii <eliz AT is DOT elta DOT co DOT il>
Date: Sun, 14 May 2000 13:19:50 +0200
MIME-Version: 1.0
Subject: Re: Math functions
CC: djgpp-workers AT delorie DOT com
In-reply-to: <200005132121.RAA16247@indy.delorie.com>
References: <200005131249 DOT PAA15925 AT is DOT elta DOT co DOT il> (buers AT gmx DOT de)
X-mailer: Pegasus Mail for Win32 (v3.12b)
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

On 13 May 00, at 17:21, Eli Zaretskii wrote:

> > > Anyway, the only saving would be a single integer instruction that
> > > stores a value in errno.
> > 
> > Unfortunately, it can be much more. You have to test the arguments 
> > for range errors, poles, and special values.
> 
> For the return value, not for errno, at least not typically.  There
> are only two possible values to set errno to: EDOM and ERANGE, so the
> tests to decide which one is relevant are not that time-consuming,
> especially compared to the many cycles gobbled by a typical FPU
> instruction.

I already accepted, that setting of errno is better. But it may be 
time consuming, tedious and error prone, especially in the case of 
long doubles. For my log example, you have to test for zero, smaller 
zero, +Infinity, NaNs and unnormals. My small code snippet is sort of 
"self-healing" in that case, it will set the correct exception bits 
int the FPU-SW and return in all the cases the correct value.

> We avoid exceptions to have control on what values are returned in
> abnormal cases: the value we return is not always the FPU's masked
> response to the appropriate exception.  If you let the FPU to do its
> thing, you cannot have that kind of control on the return value.

I don't understand what you mean here by "FPU's masked response to 
the appropriate exception". When you give a NaN to the FPU, it will 
give you a NaN back. When you call fsqrt with a negative number, you 
get a NaN back. When you use log with zero, you get -Infinity. Where 
do you see wrong cases. (I know of the fpatan2 for 0, 0, which I 
check for.)
 
> > Could you please explain, why you dislike the exceptions.
> 
> They are more trouble than they help, especially in the DJGPP
> environment.  See the thread about FP exceptions being delivered to
> the parent program on Windows 9X, for example.

I still cannot see the disadvantage. The exceptions are all masked by 
default. If you unmask them, you probably know what you do. You can 
unmask the inexact exception, and almost all math code will throw 
masses of exceptions to you. (This was useful, when I developed the 
argument reduction codes.) Why should there be a difference with math 
functions. If I call sqrt(-1), I think the same should happen, as 
when I do 0/0 or Inf-Inf. When I call log(0), the same should happen, 
as when I do -1/0. Why not? I probably made an error, if not, I 
need to know how to deal with it in both cases.

> > Besides the point, I made for debugging, they 
> > can also be useful in interactive numerical programs. Set a flag in
> > a signal handler for SIGFPE, that can be checked at strategical
> > places, 
> 
> You can test for NaN's and Inf's at the same places.  

Unfortunately, you can't. NaNs may dissapear by various means. If, 
for efficiency, I only want to test at strategical places, the NaNs 
may already be gone.

> If you really
> want fine control on what happens in abnormal cases, link with -lm and
> write a custom `matherr' function; this is more portable than
> exceptions, and also easier.

Matherr is not not portable in my experience. 
Another point is, the functions of <fenv.h> in C99 (I started work 
for an implementation of those for DJGPP). There will be portable 
ways to ask for the FPU-SW. If, say in expl, I test for overflow, and 
return some internal Infinity, the overflow flag will not be set. If 
I return one/zero, it will be set.

BTW. When I coded the math functions in 1993, I did the non-exception-
throwing return method. I came to the conclusion, that this is wrong. 
Now, you are telling me, that this was correct ;) 

Perhaps, I can find a way, to have both ways, by some macros. 
Something like

#ifdef SILENT_RETURNS
#define GENERATE_POSITIVE_INFINITYL (__one/__zero)
#define GENERATE_POSITIVE_UNDERFLOWL (__tinyl*__tinyl)
...
#else
#define GENERATE_POSITIVE_INFINITYL (__MATH_PLUS_INFINITYL)
#define GENERATE_POSITIVE_UNDERFLOWL (0.0L)
...
#endif

I have not a good idea for assembler sources yet.


> Also, most people don't even know how to write a SIGFPE handler that
> will avoid triggering another SIGFPE when it returns.  And on NT you
> cannot catch SIGFPE at all (I'm not sure what happens on Windows2000).

Who cannot write the signal handler, propbably cannot unmask the 
exceptions. Is there a misunderstanding? I never have seen floating 
point exceptions with DJGPP 2x when not especially asking for them. 
(In 1x some were enabled, and IIRC, they couldn't be caught by a 
signal handler). Is the default masking of the exceptions unreliable? 
I have seen the threat about make, and I wondered, how this can 
happen.

> If you could add at least some of the test programs to djtst, it would
> be even better.

There are already some of them in the tests directory. They certainly 
need some polishing. I fear, they were not of much help, because some 
bugs they found in 1994, were still left about a year ago. Now, Eric 
has fixed them. 
 
> Perhaps it would be a good idea to include fast inline versions in
> some system header, possibly included by math.h under some special
> compiler switch, such as -ffast-math.

I fear, that this is very difficult. When you look at the log 
function, in my first message to this threat, this might be a good 
candidate, that should even always produce the correct results. But 
there are various problems inlining this. The code, I posted uses the 
"m" constraint, which might not be the most efficient in some cases. 
But, more important, it uses 2 entries in the FPU stack, and even 
after carefully reading much documentation, I have not found a way to 
tell this to gcc.



- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019