From: Jerry on
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
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
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
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
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?