delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2003/03/18/10:08:47

Date: Tue, 18 Mar 2003 09:09:58 -0600
From: Eric Rudd <rudd AT cyberoptics DOT com>
Subject: Re: isnan and isinf
In-reply-to: <200303181210.NAA03843@lws256.lu.erisoft.se>
To: djgpp-workers AT delorie DOT com
Message-id: <3E7736C6.5040903@cyberoptics.com>
Organization: CyberOptics
MIME-version: 1.0
X-Accept-Language: en,pdf
User-Agent: Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.2.1) Gecko/20021130
References: <200303181210 DOT NAA03843 AT lws256 DOT lu DOT erisoft DOT se>
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

Martin Stromberg wrote:

>But how would you access the bits directly? Doesn't you have to store the float and load it into an unsigned int? Or is there specific CPU instructions for that?
>
Take a look at what I did in the libc math functions.  In order to 
handle errno properly, I had to do argument tests against infinity and 
NaN in virtually all the functions.  An argument comes in on the stack, 
and you do a move into eax to test the bits, as well as the usual fldl 
into the FPU.  (After you've got the number into the FPU stack, you can 
also do NaN tests with fxam, but they're slower.)  In most cases you 
only need to examine the most significant longword, rather than the 
entire 8 bytes.  I would recommend assembler for isnan() and similar 
functions -- for these kinds of tests, it's actually more 
straightforward and readable than those ugly C casts, and not many more 
instructions.  Another thing to keep in mind is that if you write the 
isnan() macro like this

   #define isnan(x) isnand((double) x)

so that it works for floats as well as doubles (where isnand() is a 
function that expects a double argument), and you call it like this

   float x;
   int i;
   i = isnan(x);

gcc will generate an flds and an fstl to explicitly convert the argument 
from a float to a double, which is fairly time-consuming compared to the 
simple integer bit tests.  I don't know how to avoid this problem, since 
C, unlike FORTRAN, doesn't have type-generic built-in functions.  Can 
anyone think of a way around this, perhaps using typeof()?

The question also came up about which flavors of NaN to recognize.  In 
normal FPU computation, the only type of NaN that occurs is the "real 
indefinite" non-signalling NaN, which you get, for instance, by 
computing 0./0.  I think that the penalty for recognizing all the 
flavors is that you have to test both upper and lower longwords, rather 
than just the most-significant longword.  I decided that the extra 
effort wasn't justified for the libc math routines, since the other NaNs 
aren't supposed to occur anyway, but maybe we want to put the extra code 
into an explicit function like isnan().

-Eric

- Raw text -


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