Re: Garbage in dead zone



"Charles Coldwell" <coldwell@xxxxxxxxx> wrote in message
news:rzpod6mmzei.fsf@xxxxxxxxxxxx

Let me see if I understand this expression

transfer([real(cc),0.0_10],0_16)

correctly. In order to keep things 32-bit aligned, a REAL(KIND=10)
variable actually occupies twelve bytes in memory instead of ten.

It's more complicated than that. Actually a REAL(KIND=10) variable
takes up 16 bytes on the compiler in question (gfortran for 64-bit
Windows). I gather that some if not all compilers which implement
REAL(KIND=10) variables on 32-bit Windows pad them out to only 12
bytes. I guess the 32-bit Windows people never read

http://www.intel.com/design/processor/manuals/248966.pdf

where it is recommended in section 3.6.3:

"Align 80-bit data so that its base address is a multiple of
sixteen."

So
the actual arguments supplied to

TRANSFER(SOURCE, MOLD [,SIZE])

are

SOURCE : a two-element rank-1 array occupying 24 bytes
MOLD : a scalar occupying 16 bytes

Actually as explained above for the system in question SOURCE
occupies 32 bytes.

The result should be "of type and type parameters those of MOLD", so
the result is going to be a 16-byte scalar integer. Furthermore, "If
the physical representation of the result is as long as or longer than
that of SOURCE, the result contains SOURCE as its leding part and the
rest is undefined; otherwise the result is the leading part of
SOURCE." So, IIUC the goal of

transfer([real(cc),0.0_10],0_16)

is to express REAL(cc) as a 16-byte integer.

That is correct.

Since REAL(cc) is a ten
byte floating point number plus two bytes of padding, TRANSFER-ing it
into a 16-byte integer scalar would leave at least four bytes
undefined, or six bytes undefined if we include the two padding bytes.
Therefore, you create a two element rank-1 REAL(KIND=10) array, for 24
bytes total, then transfer the first 16 bytes of this array into an
integer. So the first ten bytes of the 16-byte integer are the bits
from your original REAL(KIND=10), the next two (undefined) bytes are
alignment padding, and the last four are zeros taken from the 0.0_10
second array element.

As explained it's more complicated than that.

Then you

write(*,'(z0.20)') transfer([real(cc),0.0_10],0_16)
write(*,'(z0.20)') transfer([aimag(cc),0.0_10],0_16)

which should show us the bits in the COMPLEX(KIND=10) variable cc:

Invoking ACOSH...
00000000000000000000
7FF000000000000000000000000

so the real part is zero, and the imaginary part has some other stuff
in it. What puzzles me is the placement of that other stuff. I would
not have been surprised to find that the alignment padding bytes
contain random garbage, but if I'm counting zeros correctly, the
7FF garbage is above that:

00000000 (LSB)
00000000
00000000
000007FF (MSB)

In other words, the garbage is in the most significant 4 bytes of the
16-byte integer value returned by the TRANSFER. I think those should
have been zeroed by the second element in your two-element temporary
array. You're on a little-endian (W64) machine, right?

What you haven't seen is that if the above-quoted WRITE statements
are reversed, it's the REAL part that picks up the garbage.
gfortran seems to be inconsistent about the entire upper 6 bytes of
a REAL(KIND=10) variable, sometimes meticulously copying the lower
12 bytes, obviously an FSTP instruction that writes such a variable
writes 10 bytes, and sometimes all 16 bytes after they get corrupted
as shown are preserved.

An extra call to IBITS would work around this problem but some
people might claim that the original WRITE statements are already
quite complicated because they contain an invocation of TRANSFER in
in them. What's so hard to read about TRANSFER?

--
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end


.



Relevant Pages

  • Re: Idea for ECMA/C# Standard - compile time hash for performance
    ... I agree with you the chance of a compiler change is slim, ... and then delegating to the standard hash for fields accessed less frequently. ... or the array lookup which would require the ... > 64-bit architecture) for each enum value that doesn't map to anything. ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: Q: Checking the size of a non-allocated array?
    ... an actual argument is already invalid ... First note that you don't have an unallocated array in the subroutine. ... it is comparable to disassociated or undefined pointers. ... Obviously the compiler has ...
    (comp.lang.fortran)
  • Re: Windows array allocation problem
    ... array reference has to have a 64-bit index or array subscript triplet? ... to fit in one. ... That assumes, of course, that your compiler ... limits on just about anything. ...
    (comp.lang.fortran)
  • Bounds checked arrays
    ... As everybody knows, the C language lacks ... When the state of this toggle is ON, the compiler ... Important is to know that the array updates ... We have just to allow him/her to specify what to do ...
    (comp.lang.c)
  • Re: Error handling library
    ... which lets the compiler catch out-of-range usage. ... and assuming that a higher int means "more dangerous error" ... with a comment warning that one is used as an index into the array ... languages while running (an array of languages, ...
    (comp.lang.c)