2

I have a binary file written by a Fortran code which I am required to read in using C++, edit, and then rewrite to the original format.

The majority of the file is straightforward to manipulate but I am encountering a problematic type. The file has been written using:

integer, parameter :: long = selected_real_kind(18,4096)

and subsequently has a number of values to be read/written of type:

real(long)

I have been able to determine that these values are stored as 16 bytes in the original binary file and hence should be read in to a long double, but on my system a long double is only 8 bytes and reads incorrectly.

Firstly, can anyone tell me anymore information about how the selected_real_kind values are stored as binary?

Secondly, can anyone recommend a way to read and write this abnormal 16 byte binary real in and out of C++ which can only store up to 8 byte doubles?

EDIT: This is all using Visual Studio 2017 on Windows 10, so GCC quadmath.h is not applicable.

Ian Bush
  • 6,996
  • 1
  • 21
  • 27
DHorn
  • 21
  • 2
  • Does this answer your question? [Quadruple Precision in C++ (GCC)](https://stackoverflow.com/questions/5451447/quadruple-precision-in-c-gcc) – Dan M. Nov 06 '20 at 10:08
  • 1
    The binary format for writing floating point values (of any kind) - and, in fact, most types - depends on the Fortran compiler. If you got things to work with other types, you are embedding assumptions about a specific pair of Fortran and C++ compilers, that are not necessarily true in general. Practically, you might be better writing Fortran code to do the manipulation - then the code will work as long as the program which writes the file and the program that manipulates it are built using the same Fortran compiler - rather than having code that is specific to *two* compilers. – Peter Nov 06 '20 at 10:31
  • In Fortran you can ask what is the `numeric_storage_size` for an entity, where the function returns the number of bits. I suspect that if you do `print *, numeric_storage_size(1._long)`, you'll get 128. And, if you do `print *, kind(1._long)`, you'll get 10. So, `REAL(long)` is the same as `REAL(10)`, which requires 10 bytes (not the 8 bytes you claim). So, why 128 bits? Because, on i386/x86_64, the 10 bytes are padded to 16 bytes for efficient hardware utilization. – evets Nov 06 '20 at 15:07
  • There is really nothing special with what Fortran is doing, `selected_real_kind(18,4096)` does not do anything magical, it just points to the 128 bit }in memory size) floating point type. If your compiler cannot use 128 bit floating point types (or the 80 bit ones), you either have to change your compiler or find some library that implements them for you. Gfortran might actually even use different types on different platforms when explicitly asked to use 128 bit floats (again / in memory). It might use the 10-byt ones (fit in the registers) or the full 16-byte ones (in software). – Vladimir F Героям слава Nov 06 '20 at 17:52

0 Answers0