Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask

[OT] Endianness and extended precision (80-bit) long doubles

by syphilis (Bishop)
on Aug 24, 2019 at 08:14 UTC ( #11104934=perlquestion: print w/replies, xml ) Need Help??

syphilis has asked for the wisdom of the Perl Monks concerning the following question:

The extended precision long double uses only 10 bytes, but is assigned either 12 bytes (32-bit architecture) or 16 bytes (64-bit architecture).
On my little endian machine, the unused (meaningless) bytes are at the high end (at indexes 10-11 or 10-15).
So, I have a C for loop that iterates through the meaningful bytes:
for(i = 0; i < 10; i++) { do stuff with the byte at index number i }

I'd like to know whether I can use the exact same code on a big endian machine - or whether doing so will actually access the unused bytes.
NOTE: The order in which I iterate through the meaningful bytes is irrelevant for my exercise - but the loop must avoid those unused bytes.

Unfortunately, I don't have a suitable big endian machine on which I can test ... and I haven't managed to google up the answer yet.
Anyone know the answer ?


Replies are listed 'Best First'.
Re: [OT] Endianness and extended precision (80-bit) long doubles
by johngg (Canon) on Aug 24, 2019 at 11:19 UTC

    Sadly my last SPARC box (ancient Ultra-80) has died but I wonder if you could emulate the architecture. Googling QEMU SPARC resulted in several links. Just a thought.



      Possibly try Amiga Forever running Amiga OS4.1?
Re: [OT] Endianness and extended precision (80-bit) long doubles
by Marshall (Abbot) on Aug 24, 2019 at 17:46 UTC
    No - this same code cannot be used.
    12 or 16 bytes is normal because the total number of bytes for an integer at least needs to be divisible by 4 for efficient hardware implementation. You can access an individual byte, but the hardware can access a "row of bytes" in the same time that it can access a single byte within a row. A "row" is either 32 (4 bytes) or 64 bits (8 bytes).

    I presume this for loop is within Perl code after a read of a binary file? You should consider pack() and unpack() to get the data into a Perl binary value (big endian). The right kind of pack() or unpack() is dependent upon the architecture (endianness).

    It would be helpful to show some code and a short explanation of why you are accessing the individual bytes of what apparently is a multi-byte integer?
    Update: too many bytes for an int.. I guess this is a float? It is quite common for binary values to written with big endian values to disk, etc.

      It would be helpful to show some code

      Yes, it might have been clearer if I'd phrased the question in terms of pack/unpack.
      On my 64-bit little-endian machine (Ubuntu-18.04), running a perl whose NV is the extended precision (80-bit) long double, I get:
      $ perl -le 'print unpack "h*", pack "D", sqrt 2;' 4846ed9f333f405bfff3000000000000
      If I ran the identical one-liner on a 64-bit *big-endian* machine,running a perl whose NV is the extended precision (80-bit) long double, where would that substring of 12 consecutive zeroes appear ? Would it still appear at the end of the string (as was the case on my little-endian machine), or would it appear at the beginning ?

      I have long-standing C code in Math-MPFR (MPFR.xs) that presumes that the substring in question will appear at the end of the string, irrespective of endianess:
      .... n = bits == 64 ? 10 : 16; #ifdef MPFR_HAVE_BENDIAN /* Big Endian architecture */ for (i = 0; i < n; i++) { #else for (i = n - 1; i >= 0; i--) { #endif // code that does something with byte i
      but I don't recall having ever established the correctness of that code for the big-endian case.

      If it were incorrect, then the test suite should expose the error - but then I don't know if Math::MPFR has ever been built on a big-endian machine, using a perl whose NV is the 80-bit long double.

        I am not sure that I can help. current Pack docs. I am on Perl 5.24 and it appears to me that you are using a feature from Perl 5.30? This "D" option to pack() appears in red in my browser.

        If Perl source code of:

        $ perl -le 'print unpack "h*", pack "D", sqrt 2;' 4846ed9f333f405bfff3000000000000
        works? I am also unsure about what will happen on a different architecture. My main machine is Intel (little endian). I have a Raspberry PI which I think is big endian, but I have a lot of hardware cables to screw around with to get it working. Sorry.
        D A float of long-double precision in native format. (Long doubles are available only if your system supports long double values _and_ if Perl has been compiled to support those. Raises an exception otherwise. Note that there are different long double formats.) h A hex string (low nybble first). H A hex string (high nybble first).
Re: [OT] Endianness and extended precision (80-bit) long doubles (SOLVED)
by syphilis (Bishop) on Aug 27, 2019 at 13:13 UTC
    I finally found an answer on Wikipedia:

    Little endian processors order bytes in memory with the least significant byte of a multi-byte value in the lowest-numbered memory location. Big endian architectures instead order them with the most significant byte at the lowest-numbered address.

    IOW, both endians will start at the lowest-numbered memory location with (for this particular type) the unused bytes being at indexes 10 and upwards.
    This is the best outcome (because it makes things simplest) and also is consistent with what I've done in Math::MPFR.


Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://11104934]
Approved by haukex
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others imbibing at the Monastery: (3)
As of 2019-10-20 06:25 GMT
Find Nodes?
    Voting Booth?