|
Prev: Ada / MS WinCE
Next: A4 formatted ARM?
From: Jerry on 6 May 2008 14:09 On May 5, 1:49 pm, Adam Beneschan <a...(a)irvine.com> wrote: > On May 5, 11:23 am, Martin Krischik <krisc...(a)users.sourceforge.net> > wrote: > > > Jerry wrote: > > > How would one check a Float or Long_Float if it has value NaN? The > > > only ways that I can come up with are to import a C function (isnan, I > > > think) or to write Long_Float'image(Some_Float) to a string and > > > examine the first three characters to see if they are "NaN" (and that > > > seems to be a GNAT implementation choice so might not be portable, > > > which is OK for my use). > > > How about an Unchecked Conversion to an Unsigned_64 and comparing > > > >2#0111_1111_1111_0000_0000_0000_0000_0000# > > > Note that it's '>' as 2#0111_1111_1111_0000_0000_0000_0000_0000# is positive > > infinity. > > Any negative float (including negative infinity) would be > than the > binary number you give, since the leftmost bit (sign bit) would be 1. > I think you need to clear the sign bit first, then your comparison > will work: > > Is_NaN := (To_Unsigned_64(X) and not > 2#1000_0000_0000_0000_0000_0000_0000_0000#) > > 2#0111_1111_1111_0000_0000_0000_0000_0000#; > > But I haven't tried it. > > -- Adam I thought about doing something like this once I saw the bit patterns on the Wikipedia page. However, I would guess that the bit pattern for quiet and signaling NaNs is different, so the test would be somewhat more complicated if one wanted to detect both types. Jerry
From: Wiljan Derks on 6 May 2008 14:45 The following code works fine for us: type Ieee_Short_Real is record Mantisse_Sign : Integer range 0 .. 1; Exponent : Integer range 0 .. 2 ** 8 - 1; Mantisse : Integer range 0 .. 2 ** 23 - 1; end record; for Ieee_Short_Real use record Mantisse_Sign at 0 range 31 .. 31; Exponent at 0 range 23 .. 30; Mantisse at 0 range 0 .. 22; end record; function Valid_Real (Number : Float) return Boolean is function To_Ieee_Short_Real is new Ada.Unchecked_Conversion (Float, Ieee_Short_Real); begin return To_Ieee_Short_Real (Number).Exponent /= 255; end Valid_Real; Wiljan
From: Martin Krischik on 5 May 2008 14:23 Jerry wrote: > How would one check a Float or Long_Float if it has value NaN? The > only ways that I can come up with are to import a C function (isnan, I > think) or to write Long_Float'image(Some_Float) to a string and > examine the first three characters to see if they are "NaN" (and that > seems to be a GNAT implementation choice so might not be portable, > which is OK for my use). How about an Unchecked Conversion to an Unsigned_64 and comparing >2#0111_1111_1111_0000_0000_0000_0000_0000# Note that it's '>' as 2#0111_1111_1111_0000_0000_0000_0000_0000# is positive infinity. Martin -- mailto://krischik(a)users.sourceforge.net Ada programming at: http://ada.krischik.com
From: Adam Beneschan on 5 May 2008 16:49 On May 5, 11:23 am, Martin Krischik <krisc...(a)users.sourceforge.net> wrote: > Jerry wrote: > > How would one check a Float or Long_Float if it has value NaN? The > > only ways that I can come up with are to import a C function (isnan, I > > think) or to write Long_Float'image(Some_Float) to a string and > > examine the first three characters to see if they are "NaN" (and that > > seems to be a GNAT implementation choice so might not be portable, > > which is OK for my use). > > How about an Unchecked Conversion to an Unsigned_64 and comparing > > >2#0111_1111_1111_0000_0000_0000_0000_0000# > > Note that it's '>' as 2#0111_1111_1111_0000_0000_0000_0000_0000# is positive > infinity. Any negative float (including negative infinity) would be > than the binary number you give, since the leftmost bit (sign bit) would be 1. I think you need to clear the sign bit first, then your comparison will work: Is_NaN := (To_Unsigned_64(X) and not 2#1000_0000_0000_0000_0000_0000_0000_0000#) > 2#0111_1111_1111_0000_0000_0000_0000_0000#; But I haven't tried it. -- Adam
From: Adam Beneschan on 6 May 2008 18:18 On May 6, 11:45 am, "Wiljan Derks" <Wiljan.De...(a)gmail.com> wrote: > The following code works fine for us: > > type Ieee_Short_Real is > record > Mantisse_Sign : Integer range 0 .. 1; > Exponent : Integer range 0 .. 2 ** 8 - 1; > Mantisse : Integer range 0 .. 2 ** 23 - 1; > end record; > > for Ieee_Short_Real use > record > Mantisse_Sign at 0 range 31 .. 31; > Exponent at 0 range 23 .. 30; > Mantisse at 0 range 0 .. 22; > end record; > > function Valid_Real (Number : Float) return Boolean is > function To_Ieee_Short_Real is > new Ada.Unchecked_Conversion (Float, Ieee_Short_Real); > begin > return To_Ieee_Short_Real (Number).Exponent /= 255; > end Valid_Real; It might make sense to use modular types instead of signed integer types for Mantisse_Sign, Exponent, and Mantisse (or Mantissa, if you want to use English); then you can use "and", "or", and "not" operations to test bits. Actually, I'd probably define a couple constants here: Exponent_Size : constant := 8; Mantissa_Size : constant := 23; type Exponent_Type is mod 2 ** Exponent_Size; type Mantissa_Type is mod 2 ** Mantissa_Size; type Mantissa_Sign_Type is mod 2; Using constants makes it easy to re-implement this for 64- and 80-bit floats. type Ieee_Short_Real is record Mantissa_Sign : Mantissa_Sign_Type; Exponent : Exponent_Type; Mantissa : Mantissa_Type; end record; (I've omitted the rep clause because I think the one above might work only for big-endian and not little-endian machines or vice versa, and I don't feel like figuring it out because I have a cold and my head hurts enough already.) Then, if X is the result of the Unchecked_Conversion: Number is a valid float if X.Exponent /= Exponent_Type'Last Number is an infinity if X.Exponent = Exponent_Type'Last and X.Mantissa = 0 Number is a qNaN if X.Exponent = Exponent_Type'Last and (X.Mantissa and 2**(Mantissa_Size-1) /= 0) Number is a sNaN if X.Exponent = Exponent_Type'Last and X.Mantissa /= 0 and (X.Mantissa and 2**(Mantissa_Size-1) = 0) On the Pentium, Number is a "real indefinite" if X.Exponent = Exponent_Type'Last and X.Mantissa = 2**(Mantissa_Size-1) Number is a denormal if X.Exponent = 0 and X.Mantissa /= 0 Hope this helps someone (and I hope I didn't screw up and get something wrong), -- Adam
|
Pages: 1 Prev: Ada / MS WinCE Next: A4 formatted ARM? |