Date: Tue, 18 Mar 2003 09:09:58 -0600 From: Eric Rudd 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 Content-type: text/plain; charset=ISO-8859-1; format=flowed Content-transfer-encoding: 7bit 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 Precedence: bulk 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