From: LC's No-Spam Newsreading account on
It is at least 18 years I've been using a set of byteswapping routines
of mine. Since when I first wrote them, there were only REAL*8 but
REAL*4 and INTEGER*4, I wrote two routines but called them in 3 cases:

Namely the routine designed for 32-bit byte swap had a nominal integer
argument

SUBROUTINE SWAPI4(DATA,N)
INTEGER N
INTEGER*4 DATA(N)

but I freely called it interchangeably with integer or float
arguments, as e.g. CALL SWAPI4(I4(1),1) or CALL SWAPI4(R4(1),1)

The routine for 64-bit byte swap had nominally a float argument (full
code attached below). Since at the time the only 64-bit quantities used
were double precision float, I had no problems.

However recently I had the need of byteswapping 64-bit integers,
therefore I called it passing an INTEGER*8 argument (equivalenced to a
REAL*8)

I found that in some rare cases (for me this was 5 out 10,000 values !)
the result was incorrect. I was able to pinpoint it to the case when the
bit pattern of the integer correspond to that of a signalling NAN,
which, in the argument passage, is silently converted to a quiet NAN.

As a result, the byteswapped returned (integer) value is wrong, e.g.

FFF0150068000000 is swapped into 000000680015F8FF

So if somebody has the need of using similar legacy routines, beware !

SUBROUTINE SWAPR8(DATA,N)
INTEGER N
REAL*8 DATA(N)
REAL*8 WORK
CHARACTER C(8),W
EQUIVALENCE (WORK,C)
INTEGER I
C
IF(N.LE.0)RETURN
DO 1 I=1,N
WORK=DATA(I)
W=C(1)
C(1)=C(8)
C(8)=W
W=C(2)
C(2)=C(7)
C(7)=W
W=C(3)
C(3)=C(6)
C(6)=W
W=C(4)
C(4)=C(5)
C(5)=W
DATA(I)=WORK
1 CONTINUE
RETURN
END




--
----------------------------------------------------------------------
nospam(a)mi.iasf.cnr.it is a newsreading account used by more persons to
avoid unwanted spam. Any mail returning to this address will be rejected.
Users can disclose their e-mail address in the article if they wish so.
From: glen herrmannsfeldt on
LC's No-Spam Newsreading account <nospam(a)mi.iasf.cnr.it> wrote:

> It is at least 18 years I've been using a set of byteswapping routines
> of mine. Since when I first wrote them, there were only REAL*8 but
> REAL*4 and INTEGER*4, I wrote two routines but called them in 3 cases:

> Namely the routine designed for 32-bit byte swap had a nominal integer
> argument

> SUBROUTINE SWAPI4(DATA,N)
> INTEGER N
> INTEGER*4 DATA(N)

> but I freely called it interchangeably with integer or float
> arguments, as e.g. CALL SWAPI4(I4(1),1) or CALL SWAPI4(R4(1),1)

That will usually work, but the standard doesn't require
it to work. It is more likely to work if the called routine
uses INTEGER instead of REAL.

> The routine for 64-bit byte swap had nominally a float argument (full
> code attached below). Since at the time the only 64-bit quantities used
> were double precision float, I had no problems.

> However recently I had the need of byteswapping 64-bit integers,
> therefore I called it passing an INTEGER*8 argument (equivalenced to a
> REAL*8)

If you rewrite the routine to use INTEGER*8 then it wouldn't
even try to do floating point operations. It might, for
example, load the value into a floating point register and
then store it.

> I found that in some rare cases (for me this was 5 out 10,000 values !)
> the result was incorrect. I was able to pinpoint it to the case when the
> bit pattern of the integer correspond to that of a signalling NAN,
> which, in the argument passage, is silently converted to a quiet NAN.

> As a result, the byteswapped returned (integer) value is wrong, e.g.
>
> FFF0150068000000 is swapped into 000000680015F8FF

(snip of routine that exchanges through an EQUIVALENCEd
CHARACTER*8 variable.)

Many now have INTEGER*1, but CHARACTER should work on most machines.
(Watch out for ones with 16 bit unicode characters.)

Also, many processors have a hardware byte swap instruction,
at least for 16 bit and 32 bit swaps. That is likely much
faster than doing it in any high-level language.

-- glen
From: Steve Lionel on
On 3/1/2010 5:38 AM, LC's No-Spam Newsreading account wrote:

> I found that in some rare cases (for me this was 5 out 10,000 values !)
> the result was incorrect. I was able to pinpoint it to the case when the
> bit pattern of the integer correspond to that of a signalling NAN,
> which, in the argument passage, is silently converted to a quiet NAN.

This is a feature of the IA-32 architecture. On a floating load of a
signaling NaN, it is converted to a quiet NaN. I've seen customers run
into this before. Depending on compiler options, an integer value
corresponding to an IEEE denormal might be changed to zero.

You are correct to alert others to this issue - never use REALs as a
proxy for arbitrary datatypes.

--
Steve Lionel
Developer Products Division
Intel Corporation
Nashua, NH

For email address, replace "invalid" with "com"

User communities for Intel Software Development Products
http://software.intel.com/en-us/forums/
Intel Software Development Products Support
http://software.intel.com/sites/support/
My Fortran blog
http://www.intel.com/software/drfortran
From: glen herrmannsfeldt on
Steve Lionel <steve.lionel(a)intel.invalid> wrote:
(snip on converting SNaN to QNan)

> This is a feature of the IA-32 architecture. On a floating load of a
> signaling NaN, it is converted to a quiet NaN. I've seen customers run
> into this before. Depending on compiler options, an integer value
> corresponding to an IEEE denormal might be changed to zero.

In the OS/360 days, I sometimes used REAL*8 for Hollerith data.
Fortunately S/360 doesn't change the bit patterns on load
or store to floating point registers. Specifically, it doesn't
normalize values. (It will if you add zero, so don't do that.)

> You are correct to alert others to this issue - never use REALs as a
> proxy for arbitrary datatypes.

This is, in general, a good idea. (Especially with the popularity
of IA32.) Though as not all systems supported INTEGER*8 until
somewhat recently, there wasn't always an alternative.

-- glen

From: robin on
glen herrmannsfeldt wrote in message ...
>LC's No-Spam Newsreading account <nospam(a)mi.iasf.cnr.it> wrote:
>(snip of routine that exchanges through an EQUIVALENCEd
>CHARACTER*8 variable.)

No, he didn't equivalence to CHARACTER*8.
He equivalenced to an array of Character*1.