Discussion:
How to byte swap an IEEE Float?
(too old to reply)
Björn
2005-06-28 13:53:42 UTC
Permalink
I need to read some float values from file that have been written in
big-endian byte order from a c-program. The simple swapping procedure
that I have just interchanges the byte order of type IEEE_Float_32 to
get little-endian. The problem is that for some values (eg. 33.229000)
it is a "NaN" when doing IEEE_Float_32'Read and I get a constraint
error (invalid data) from stream_io when the value is read. How do I
get around this?

Thanks
Björn
Marius Amado Alves
2005-06-28 15:06:46 UTC
Permalink
Post by Björn
I need to read some float values from file that have been written in
big-endian byte order from a c-program. The simple swapping procedure
that I have just interchanges the byte order of type IEEE_Float_32 to
get little-endian. The problem is that for some values (eg. 33.229000)
it is a "NaN" when doing IEEE_Float_32'Read and I get a constraint
error (invalid data) from stream_io when the value is read. How do I
get around this?
Simple. Setup an array of bytes with the same representation of the
float type (use representation clauses and pragma Pack). Read the array
of bytes. Swap the bytes. Convert to the float type (use unchecked
conversion).
Simon Wright
2005-06-28 15:55:07 UTC
Permalink
Post by Marius Amado Alves
Post by Björn
I need to read some float values from file that have been written in
big-endian byte order from a c-program. The simple swapping procedure
that I have just interchanges the byte order of type IEEE_Float_32 to
get little-endian. The problem is that for some values (eg. 33.229000)
it is a "NaN" when doing IEEE_Float_32'Read and I get a constraint
error (invalid data) from stream_io when the value is read. How do I
get around this?
Simple. Setup an array of bytes with the same representation of the
float type (use representation clauses and pragma Pack). Read the
array of bytes. Swap the bytes. Convert to the float type (use
unchecked conversion).
Marius,

I think you mean 'of the same length as the float type'?

OP doesn't say what processor he gets the BE value from, but assuming
PowerPC you either get Float (4 bytes) for digits <= 6 or Long_Float
(8 bytes) for digits 7 .. 15.

On Intel hardware there's an 80-bit Long_Long_Float (digits 18).

-S
Marius Amado Alves
2005-06-28 16:59:27 UTC
Permalink
Post by Simon Wright
Post by Marius Amado Alves
Post by Björn
I need to read some float values from file that have been written in
big-endian byte order from a c-program. The simple swapping procedure
that I have just interchanges the byte order of type IEEE_Float_32 to
get little-endian. The problem is that for some values (eg.
33.229000)
it is a "NaN" when doing IEEE_Float_32'Read and I get a constraint
error (invalid data) from stream_io when the value is read. How do I
get around this?
Simple. Setup an array of bytes with the same representation of the
float type (use representation clauses and pragma Pack). Read the
array of bytes. Swap the bytes. Convert to the float type (use
unchecked conversion).
Marius,
I think you mean 'of the same length as the float type'?
OP doesn't say what processor he gets the BE value from, but assuming
PowerPC you either get Float (4 bytes) for digits <= 6 or Long_Float
(8 bytes) for digits 7 .. 15.
On Intel hardware there's an 80-bit Long_Long_Float (digits 18).
Sure. You know, I meant representation = bits and bytes, implying same
length. It seems the OP already has the float type (IEEE_Float_32),
32-bit = 4-byte long, and the data are floats of this length, only
different in byte order.

OP, if the data are of a different length, then you have to unchecked
convert first to a float type of that length, and then normal convert
to the final type (risking Constraint_Error).
Björn
2005-06-28 20:43:24 UTC
Permalink
Post by Marius Amado Alves
Sure. You know, I meant representation = bits and bytes, implying same
length. It seems the OP already has the float type (IEEE_Float_32),
32-bit = 4-byte long, and the data are floats of this length, only
different in byte order.
OP, if the data are of a different length, then you have to unchecked
convert first to a float type of that length, and then normal convert
to the final type (risking Constraint_Error).
All the data in the file are of 32 bits float so that should be ok.
The target for the values is at the moment x86 (although I do expect it
to work on PowerPC as well so I check System.Default_Bit_Order before
doing any byte swapping). My dirty workaround for the moment was to
read the data as a string. I was merly wondering which is the
normal/"best" way to deal with this, since I expect it to be a
fairly common task. A packed byte array does however seem like a much
better idea than handling it as a string.

Regards
Björn
Marius Amado Alves
2005-06-29 00:13:17 UTC
Permalink
Post by Björn
Post by Marius Amado Alves
Sure. You know, I meant representation = bits and bytes, implying same
length. It seems the OP already has the float type (IEEE_Float_32),
32-bit = 4-byte long, and the data are floats of this length, only
different in byte order.
OP, if the data are of a different length, then you have to unchecked
convert first to a float type of that length, and then normal convert
to the final type (risking Constraint_Error).
All the data in the file are of 32 bits float so that should be ok.
The target for the values is at the moment x86 (although I do expect it
to work on PowerPC as well so I check System.Default_Bit_Order before
doing any byte swapping). My dirty workaround for the moment was to
read the data as a string. I was merly wondering which is the
normal/"best" way to deal with this, since I expect it to be a
fairly common task. A packed byte array does however seem like a much
better idea than handling it as a string.
It is better. Because it's portable. Probably you got away with a
String because on your system a String happens to be a packed array of
bytes, but this is not guaranteed for all systems by the standard.
Randy Brukardt
2005-06-30 19:14:35 UTC
Permalink
"Bj�rn" <***@hotmail.com> wrote in message news:***@g14g2000cwa.googlegroups.com...
...
Post by Björn
All the data in the file are of 32 bits float so that should be ok.
The target for the values is at the moment x86 (although I do expect it
to work on PowerPC as well so I check System.Default_Bit_Order before
doing any byte swapping). My dirty workaround for the moment was to
read the data as a string. I was merly wondering which is the
normal/"best" way to deal with this, since I expect it to be a
fairly common task. A packed byte array does however seem like a much
better idea than handling it as a string.
I'd suggest using an array of stream elements for that (presuming that
they're the right size, they would be on almost all machines). That's
especially useful if you're reading the type as a stream in the first place,
because it would let you skip a copy.

If you absolutely have to have portability to any possible machine, then
you'd need to use your own type. But such a machine (such as the 36 bit
Unisys U2200) would probably have problems with 32-bit float values anyway.

Randy.
Martin Dowie
2005-06-28 16:05:16 UTC
Permalink
Post by Björn
I need to read some float values from file that have been written in
big-endian byte order from a c-program. The simple swapping procedure
that I have just interchanges the byte order of type IEEE_Float_32 to
get little-endian. The problem is that for some values (eg. 33.229000)
it is a "NaN" when doing IEEE_Float_32'Read and I get a constraint
error (invalid data) from stream_io when the value is read. How do I
get around this?
What's the source/target for the values? PowerPC/ARM/Intelx86/Alpha/etc??
Stephen Leake
2005-06-28 23:35:56 UTC
Permalink
Post by Björn
I need to read some float values from file that have been written in
big-endian byte order from a c-program.
See SAL.Network_Order.Gen_Scalar_64 at
http://www.toadmail.com/~ada_wizard/ada/sal.html for a convenient way
to do this.
Post by Björn
The simple swapping procedure that I have just interchanges the byte
order of type IEEE_Float_32 to get little-endian.
Ok.
Post by Björn
The problem is that for some values (eg. 33.229000) it is a "NaN"
when doing IEEE_Float_32'Read and I get a constraint error (invalid
data) from stream_io when the value is read. How do I get around
this?
Hmm. Are you saying the original value is _not_ a NaN? If so, then
your swap implementation is faulty; try mine.
--
-- Stephe
Björn
2005-06-29 10:00:26 UTC
Permalink
Post by Stephen Leake
See SAL.Network_Order.Gen_Scalar_64 at
http://www.toadmail.com/~ada_wizard/ada/sal.html for a convenient way
to do this.
Thanks! I will check it out.
Post by Stephen Leake
Hmm. Are you saying the original value is _not_ a NaN? If so, then
your swap implementation is faulty; try mine.
No the original value _is_ a NaN when read as a float on x86 (the
subject on this thread was perhaps a bit misleading)

BR
Björn
Stephen Leake
2005-06-30 00:52:34 UTC
Permalink
Post by Björn
Post by Stephen Leake
See SAL.Network_Order.Gen_Scalar_64 at
http://www.toadmail.com/~ada_wizard/ada/sal.html for a convenient way
to do this.
Thanks! I will check it out.
Post by Stephen Leake
Hmm. Are you saying the original value is _not_ a NaN? If so, then
your swap implementation is faulty; try mine.
No the original value _is_ a NaN when read as a float on x86 (the
subject on this thread was perhaps a bit misleading)
Ok. So you have some code that generates a NaN, sends it over a
network or something, and then some Ada code wants to store it in a
Float value, still as a NaN.

Unchecked_Conversion should support that. I'm not quite clear what
will happen when you try to use the value or even assign the value;
you'll probably get Constraint_Error. You might try 'Valid.

The Ada model of floating point numbers does _not_ include NaN's, nor
infinities.
--
-- Stephe
Simon Wright
2005-07-01 04:51:22 UTC
Permalink
Post by Stephen Leake
Ok. So you have some code that generates a NaN, sends it over a
network or something, and then some Ada code wants to store it in a
Float value, still as a NaN.
I understood that the problem was

read a big-endian value from a file into a little-endian float
byte-swap the float

Clearly you're at risk until the swap. Personally I'd read into an
array 1 .. 4 of Unsigned_8, swap, unchecked convert to Float ...
Post by Stephen Leake
Unchecked_Conversion should support that. I'm not quite clear what
will happen when you try to use the value or even assign the value;
you'll probably get Constraint_Error. You might try 'Valid.
The Ada model of floating point numbers does _not_ include NaN's, nor
infinities.
You can generate them, but they are not 'Valid. With GNAT, you don't
get a Constraint_Error if you use type Float, but you do if you use

subtype Checking_Float is Float range Float'First .. Float'Last;

-S
Damien
2005-06-29 20:10:57 UTC
Permalink
Post by Björn
I need to read some float values from file that have been written in
big-endian byte order from a c-program. The simple swapping procedure
that I have just interchanges the byte order of type IEEE_Float_32 to
get little-endian. The problem is that for some values (eg. 33.229000)
it is a "NaN" when doing IEEE_Float_32'Read and I get a constraint
error (invalid data) from stream_io when the value is read. How do I
get around this?
I had to deal with byte swapping for floats and doubles between Intel
and PPC. This was C++ and I discovered that swapping had to be done in a
neutral form (byte array) before interpretation to float or double.
Initialy I directly swapped floats and doubles, and for certain values
some bits were changed.
So a function with such a signature should never be defined:
function Swap (X : Float) return Float;
It seems that all bit patterns can not be legal floats. I interpreted
this as a normalisation of the float, but this is not sure at all.

So, to swap a float or a double X, do this :
1) convert X to a byte array Y (right size)
2) swap Y from host 1 format to network or archive format
3) send Y
4) read Y
5) swap Y from network or archive format to host 2 format
6) convert Y to X

I don't know if this is related to your problem, but it seems similar,
and it may help.
It was C++, but those issues are language independent.

Damien Carbonne
Peter Hermann
2005-06-30 11:35:00 UTC
Permalink
http://www.csv.ica.uni-stuttgart.de/homes/ph/adakurs/invert4bytes.adb

(this code intentionally prevents compiler optimization)

(see also
http://www.csv.ica.uni-stuttgart.de/homes/ph/adakurs/stream2ph.adb
)

Peter Hermann
Damien
2005-06-30 22:26:09 UTC
Permalink
Post by Peter Hermann
http://www.csv.ica.uni-stuttgart.de/homes/ph/adakurs/invert4bytes.adb
(this code intentionally prevents compiler optimization)
(see also
http://www.csv.ica.uni-stuttgart.de/homes/ph/adakurs/stream2ph.adb
)
Those examples only have integer values, for which a function like :
function Swap (X : Integer) return Integer;
does not raise any problem.
Any Integer or Modular type should not be a problem. It is only with
floats that problems arise.

Damien
Peter Hermann
2005-07-01 07:37:26 UTC
Permalink
It is only with floats that problems arise.
of course. I just pointed to copyable code.

Conceivable are (e.g. GNAT-specific) mapped machine independent floating
point types for transfer purposes with a couple of predefined mantissa
and exponent sizes.
They may be more efficient than human readable text strings
(in any number base).
--
--Peter Hermann(49)0711-68587244 fax209 ***@csv.ica.uni-stuttgart.de
--Nobelstr.19 Raum 0.030, D-70550 Stuttgart Uni Hoechstleistungsrechnen
--http://www.csv.ica.uni-stuttgart.de/homes/ph/
Loading...